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