@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
JavaScript
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 };