UNPKG

@ark-ui/solid

Version:

A collection of unstyled, accessible UI components for Solid, utilizing state machines for seamless interaction.

353 lines (347 loc) 11.1 kB
import { createMachine } from './PKUUD527.js'; import { useFieldContext } from './NC7W2KIE.js'; import { createSplitProps as createSplitProps$1 } from './ZMHI4GDJ.js'; import { ark } from './EPLBB4QN.js'; import { useEnvironmentContext } from './YO2MCGXO.js'; import { useLocaleContext } from './OKZ64GSY.js'; import { createContext } from './TROPIN4C.js'; import { runIfFn } from './DT73WLR4.js'; import { __export } from './ESLJRKWD.js'; import { createComponent, mergeProps as mergeProps$1 } from 'solid-js/web'; import { mergeProps, useMachine, normalizeProps } from '@zag-js/solid'; import { Show, createUniqueId, createMemo } from 'solid-js'; import { createAnatomy } from '@zag-js/anatomy'; import { dataAttr, isLeftClick, ariaAttr } from '@zag-js/dom-query'; import { uuid, createSplitProps } from '@zag-js/utils'; import { createProps } from '@zag-js/types'; // src/components/password-input/use-password-input-context.ts var [PasswordInputProvider, usePasswordInputContext] = createContext({ hookName: "usePasswordInputContext", providerName: "<PasswordInputProvider />" }); // src/components/password-input/password-input-context.tsx var PasswordInputContext = (props2) => props2.children(usePasswordInputContext()); var PasswordInputControl = (props2) => { const passwordInput = usePasswordInputContext(); const mergedProps = mergeProps(() => passwordInput().getControlProps(), props2); return createComponent(ark.div, mergedProps); }; var PasswordInputIndicator = (props2) => { const passwordInput = usePasswordInputContext(); const mergedProps = mergeProps(() => passwordInput().getIndicatorProps(), props2); return createComponent(ark.span, mergeProps$1(mergedProps, { get children() { return createComponent(Show, { get when() { return passwordInput().visible; }, get fallback() { return props2.fallback; }, get children() { return props2.children; } }); } })); }; var PasswordInputInput = (props2) => { const passwordInput = usePasswordInputContext(); const mergedProps = mergeProps(() => passwordInput().getInputProps(), props2); const field = useFieldContext(); return createComponent(ark.input, mergeProps$1({ get ["aria-describedby"]() { return field?.().ariaDescribedby; } }, mergedProps)); }; var PasswordInputLabel = (props2) => { const passwordInput = usePasswordInputContext(); const mergedProps = mergeProps(() => passwordInput().getLabelProps(), props2); return createComponent(ark.label, mergedProps); }; var anatomy = createAnatomy("password-input").parts( "root", "input", "label", "control", "indicator", "visibilityTrigger" ); var parts = anatomy.build(); var getInputId = (ctx) => ctx.ids?.input ?? `p-input-${ctx.id}-input`; var getInputEl = (ctx) => ctx.getById(getInputId(ctx)); function connect(service, normalize) { const { scope, prop, context } = service; const visible = context.get("visible"); const disabled = !!prop("disabled"); const invalid = !!prop("invalid"); const readOnly = !!prop("readOnly"); const interactive = !(readOnly || disabled); const translations = prop("translations"); return { visible, disabled, invalid, focus() { getInputEl(scope)?.focus(); }, setVisible(value) { service.send({ type: "VISIBILITY.SET", value }); }, toggleVisible() { service.send({ type: "VISIBILITY.SET", value: !visible }); }, getRootProps() { return normalize.element({ ...parts.root.attrs, dir: prop("dir"), "data-disabled": dataAttr(disabled), "data-invalid": dataAttr(invalid), "data-readonly": dataAttr(readOnly) }); }, getLabelProps() { return normalize.label({ ...parts.label.attrs, htmlFor: getInputId(scope), "data-disabled": dataAttr(disabled), "data-invalid": dataAttr(invalid), "data-readonly": dataAttr(readOnly) }); }, getInputProps() { return normalize.input({ ...parts.input.attrs, id: getInputId(scope), autoCapitalize: "off", name: prop("name"), required: prop("required"), autoComplete: prop("autoComplete"), spellCheck: false, readOnly, disabled, type: visible ? "text" : "password", "data-state": visible ? "visible" : "hidden", "aria-invalid": ariaAttr(invalid), "data-disabled": dataAttr(disabled), "data-invalid": dataAttr(invalid), "data-readonly": dataAttr(readOnly), ...prop("ignorePasswordManagers") ? passwordManagerProps : {} }); }, getVisibilityTriggerProps() { return normalize.button({ ...parts.visibilityTrigger.attrs, type: "button", tabIndex: -1, "aria-controls": getInputId(scope), "aria-expanded": visible, "data-readonly": dataAttr(readOnly), disabled, "data-disabled": dataAttr(disabled), "data-state": visible ? "visible" : "hidden", "aria-label": translations?.visibilityTrigger?.(visible), onPointerDown(event) { if (!isLeftClick(event)) return; if (!interactive) return; event.preventDefault(); service.send({ type: "TRIGGER.CLICK" }); } }); }, getIndicatorProps() { return normalize.element({ ...parts.indicator.attrs, "aria-hidden": true, "data-state": visible ? "visible" : "hidden", "data-disabled": dataAttr(disabled), "data-invalid": dataAttr(invalid), "data-readonly": dataAttr(readOnly) }); }, getControlProps() { return normalize.element({ ...parts.control.attrs, "data-disabled": dataAttr(disabled), "data-invalid": dataAttr(invalid), "data-readonly": dataAttr(readOnly) }); } }; } var passwordManagerProps = { // 1Password "data-1p-ignore": "", // LastPass "data-lpignore": "true", // Bitwarden "data-bwignore": "true", // Dashlane "data-form-type": "other", // Proton Pass "data-protonpass-ignore": "true" }; var machine = createMachine({ props({ props: props2 }) { return { id: uuid(), defaultVisible: false, autoComplete: "current-password", ignorePasswordManagers: false, ...props2, translations: { visibilityTrigger(visible) { return visible ? "Hide password" : "Show password"; }, ...props2.translations } }; }, context({ prop, bindable }) { return { visible: bindable(() => ({ value: prop("visible"), defaultValue: prop("defaultVisible"), onChange(value) { prop("onVisibilityChange")?.({ visible: value }); } })) }; }, initialState() { return "idle"; }, effects: ["trackFormEvents"], states: { idle: { on: { "VISIBILITY.SET": { actions: ["setVisibility"] }, "TRIGGER.CLICK": { actions: ["toggleVisibility", "focusInputEl"] } } } }, implementations: { actions: { setVisibility({ context, event }) { context.set("visible", event.value); }, toggleVisibility({ context }) { context.set("visible", (c) => !c); }, focusInputEl({ scope }) { const inputEl = getInputEl(scope); inputEl?.focus(); } }, effects: { trackFormEvents({ scope, send }) { const inputEl = getInputEl(scope); const form = inputEl?.form; if (!form) return; const win = scope.getWin(); const controller = new win.AbortController(); form.addEventListener( "reset", (event) => { if (event.defaultPrevented) return; send({ type: "VISIBILITY.SET", value: false }); }, { signal: controller.signal } ); form.addEventListener( "submit", () => { send({ type: "VISIBILITY.SET", value: false }); }, { signal: controller.signal } ); return () => controller.abort(); } } } }); var props = createProps()([ "defaultVisible", "dir", "id", "onVisibilityChange", "visible", "ids", "getRootNode", "disabled", "invalid", "required", "readOnly", "translations", "ignorePasswordManagers", "autoComplete", "name" ]); createSplitProps(props); var usePasswordInput = (props2) => { const id = createUniqueId(); const locale = useLocaleContext(); const environment = useEnvironmentContext(); const field = useFieldContext(); const machineProps = createMemo(() => ({ id, ids: { input: field?.().ids.control }, disabled: field?.().disabled, readOnly: field?.().readOnly, required: field?.().required, invalid: field?.().invalid, dir: locale().dir, getRootNode: environment().getRootNode, ...runIfFn(props2) })); const service = useMachine(machine, machineProps); return createMemo(() => connect(service, normalizeProps)); }; // src/components/password-input/password-input-root.tsx var PasswordInputRoot = (props2) => { const [usePasswordInputProps, localProps] = createSplitProps$1()(props2, ["autoComplete", "defaultVisible", "disabled", "id", "ids", "ignorePasswordManagers", "invalid", "name", "onVisibilityChange", "readOnly", "required", "translations", "visible"]); const passwordInput = usePasswordInput(usePasswordInputProps); const mergedProps = mergeProps(() => passwordInput().getRootProps(), localProps); return createComponent(PasswordInputProvider, { value: passwordInput, get children() { return createComponent(ark.div, mergedProps); } }); }; var PasswordInputRootProvider = (props2) => { const mergedProps = mergeProps(() => props2.value().getRootProps(), props2); return createComponent(PasswordInputProvider, { get value() { return props2.value; }, get children() { return createComponent(ark.div, mergedProps); } }); }; var PasswordInputVisibilityTrigger = (props2) => { const passwordInput = usePasswordInputContext(); const mergedProps = mergeProps(() => passwordInput().getVisibilityTriggerProps(), props2); return createComponent(ark.button, mergedProps); }; // src/components/password-input/password-input.ts var password_input_exports = {}; __export(password_input_exports, { Context: () => PasswordInputContext, Control: () => PasswordInputControl, Indicator: () => PasswordInputIndicator, Input: () => PasswordInputInput, Label: () => PasswordInputLabel, Root: () => PasswordInputRoot, RootProvider: () => PasswordInputRootProvider, VisibilityTrigger: () => PasswordInputVisibilityTrigger }); export { PasswordInputContext, PasswordInputControl, PasswordInputIndicator, PasswordInputInput, PasswordInputLabel, PasswordInputRoot, PasswordInputRootProvider, PasswordInputVisibilityTrigger, anatomy, password_input_exports, usePasswordInput, usePasswordInputContext };