UNPKG

@ark-ui/solid

Version:

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

269 lines (262 loc) 8.89 kB
import { useFieldsetContext } from './6HQNY7WM.js'; import { composeRefs } from './ROP6QZQ7.js'; import { createSplitProps } from './ZMHI4GDJ.js'; import { ark } from './EPLBB4QN.js'; import { useEnvironmentContext } from './YO2MCGXO.js'; import { createContext } from './TROPIN4C.js'; import { __export } from './ESLJRKWD.js'; import { createComponent, mergeProps as mergeProps$1 } from 'solid-js/web'; import { mergeProps } from '@zag-js/solid'; import { splitProps, onMount, onCleanup, Show, mergeProps as mergeProps$2, createSignal, createUniqueId, createMemo } from 'solid-js'; import { dataAttr, ariaAttr } from '@zag-js/dom-query'; import { createAnatomy } from '@zag-js/anatomy'; import { autoresizeTextarea } from '@zag-js/auto-resize'; // src/components/field/use-field-context.ts var [FieldProvider, useFieldContext] = createContext({ hookName: "useFieldContext", providerName: "<FieldProvider />", strict: false }); // src/components/field/field-context.tsx var FieldContext = (props) => props.children(useFieldContext()); var FieldErrorText = (props) => { const field = useFieldContext(); const mergedProps = mergeProps(() => field().getErrorTextProps(), props); return createComponent(Show, { get when() { return field?.().invalid; }, get children() { return createComponent(ark.span, mergedProps); } }); }; var FieldHelperText = (props) => { const field = useFieldContext(); const mergedProps = mergeProps(() => field().getHelperTextProps(), props); return createComponent(ark.span, mergedProps); }; var FieldInput = (props) => { const field = useFieldContext(); const mergedProps = mergeProps(() => field?.().getInputProps(), props); return createComponent(ark.input, mergedProps); }; var FieldLabel = (props) => { const field = useFieldContext(); const mergedProps = mergeProps(() => field?.().getLabelProps(), props); return createComponent(ark.label, mergedProps); }; var FieldRequiredIndicator = (props) => { const field = useFieldContext(); const mergedProps = mergeProps(() => field().getRequiredIndicatorProps(), props); return createComponent(Show, { get when() { return field().required; }, get fallback() { return props.fallback; }, get children() { return createComponent(ark.span, mergeProps$1(mergedProps, { get children() { return props.children ?? "*"; } })); } }); }; var fieldAnatomy = createAnatomy("field").parts( "root", "errorText", "helperText", "input", "label", "select", "textarea", "requiredIndicator" ); var parts = fieldAnatomy.build(); // src/components/field/use-field.ts var useField = (props) => { const fieldset = useFieldsetContext(); const env = useEnvironmentContext(); const fieldProps = mergeProps$2( { disabled: Boolean(fieldset?.().disabled), required: false, invalid: false, readOnly: false }, props ); const [hasErrorText, setHasErrorText] = createSignal(false); const [hasHelperText, setHasHelperText] = createSignal(false); const id = fieldProps.id ?? createUniqueId(); const [rootRef, setRootRef] = createSignal(void 0); const rootId = fieldProps.ids?.control ?? `field::${id}`; const errorTextId = fieldProps.ids?.errorText ?? `field::${id}::error-text`; const helperTextId = fieldProps.ids?.helperText ?? `field::${id}::helper-text`; const labelId = fieldProps.ids?.label ?? `field::${id}::label`; onMount(() => { const rootNode = rootRef(); if (!rootNode) return; const checkTextElements = () => { const docOrShadowRoot = env().getRootNode(); setHasErrorText(!!docOrShadowRoot.getElementById(errorTextId)); setHasHelperText(!!docOrShadowRoot.getElementById(helperTextId)); }; checkTextElements(); const win = env().getWindow(); const observer = new win.MutationObserver(checkTextElements); observer.observe(rootNode, { childList: true, subtree: true }); onCleanup(() => observer.disconnect()); }); const getRootProps = () => ({ ...parts.root.attrs, id: rootId, role: "group", "data-disabled": dataAttr(fieldProps.disabled), "data-invalid": dataAttr(fieldProps.invalid), "data-readonly": dataAttr(fieldProps.readOnly) }); const getLabelProps = () => ({ ...parts.label.attrs, id: labelId, "data-disabled": dataAttr(fieldProps.disabled), "data-invalid": dataAttr(fieldProps.invalid), "data-readonly": dataAttr(fieldProps.readOnly), htmlFor: id }); const labelIds = createMemo(() => { const ids = []; if (hasErrorText() && fieldProps.invalid) ids.push(errorTextId); if (hasHelperText()) ids.push(helperTextId); return ids; }); const getControlProps = () => ({ "aria-describedby": labelIds().join(" ") || void 0, "aria-invalid": ariaAttr(fieldProps.invalid), "data-invalid": dataAttr(fieldProps.invalid), "data-required": dataAttr(fieldProps.required), "data-readonly": dataAttr(fieldProps.readOnly), id, required: fieldProps.required, disabled: fieldProps.disabled, readOnly: fieldProps.readOnly || void 0 }); const getInputProps = () => ({ ...getControlProps(), ...parts.input.attrs }); const getTextareaProps = () => ({ ...getControlProps(), ...parts.textarea.attrs }); const getSelectProps = () => ({ ...getControlProps(), ...parts.select.attrs }); const getHelperTextProps = () => ({ id: helperTextId, ...parts.helperText.attrs, "data-disabled": dataAttr(fieldProps.disabled) }); const getErrorTextProps = () => ({ id: errorTextId, ...parts.errorText.attrs, "aria-live": "polite" }); const getRequiredIndicatorProps = () => ({ "aria-hidden": true, ...parts.requiredIndicator.attrs }); return createMemo(() => ({ ariaDescribedby: labelIds().join(" "), ids: { control: id, label: labelId, errorText: errorTextId, helperText: helperTextId }, refs: { rootRef: setRootRef }, disabled: fieldProps.disabled, invalid: fieldProps.invalid, readOnly: fieldProps.readOnly, required: fieldProps.required, getLabelProps, getRootProps, getInputProps, getTextareaProps, getSelectProps, getHelperTextProps, getErrorTextProps, getRequiredIndicatorProps })); }; // src/components/field/field-root.tsx var FieldRoot = (props) => { const [useFieldProps, localProps] = createSplitProps()(props, ["id", "ids", "disabled", "invalid", "readOnly", "required"]); const field = useField(useFieldProps); const mergedProps = mergeProps(() => field().getRootProps(), localProps); return createComponent(FieldProvider, { value: field, get children() { return createComponent(ark.div, mergeProps$1(mergedProps, { ref(r$) { var _ref$ = composeRefs(field().refs.rootRef, props.ref); typeof _ref$ === "function" && _ref$(r$); } })); } }); }; var FieldRootProvider = (props) => { const [{ value: field }, localProps] = createSplitProps()(props, ["value"]); const mergedProps = mergeProps(() => field().getRootProps(), localProps); return createComponent(FieldProvider, { value: field, get children() { return createComponent(ark.div, mergedProps); } }); }; var FieldSelect = (props) => { const field = useFieldContext(); const mergedProps = mergeProps(() => field?.().getSelectProps(), props); return createComponent(ark.select, mergedProps); }; var FieldTextarea = (props) => { const field = useFieldContext(); let textareaRef; const [autoresizeProps, textareaProps] = splitProps(props, ["autoresize"]); const mergedProps = mergeProps(() => field?.().getTextareaProps(), () => ({ style: { resize: autoresizeProps.autoresize ? "none" : void 0 } }), textareaProps); onMount(() => { if (!autoresizeProps.autoresize) return; const cleanup = autoresizeTextarea(textareaRef); onCleanup(() => cleanup?.()); }); return createComponent(ark.textarea, mergeProps$1(mergedProps, { ref(r$) { var _ref$ = composeRefs((el) => textareaRef = el, props.ref); typeof _ref$ === "function" && _ref$(r$); } })); }; // src/components/field/field.ts var field_exports = {}; __export(field_exports, { Context: () => FieldContext, ErrorText: () => FieldErrorText, HelperText: () => FieldHelperText, Input: () => FieldInput, Label: () => FieldLabel, RequiredIndicator: () => FieldRequiredIndicator, Root: () => FieldRoot, RootProvider: () => FieldRootProvider, Select: () => FieldSelect, Textarea: () => FieldTextarea }); export { FieldContext, FieldErrorText, FieldHelperText, FieldInput, FieldLabel, FieldRequiredIndicator, FieldRoot, FieldRootProvider, FieldSelect, FieldTextarea, fieldAnatomy, field_exports, useField, useFieldContext };