@ark-ui/vue
Version:
A collection of unstyled, accessible UI components for Vue, utilizing state machines for seamless interaction.
79 lines (76 loc) • 2.44 kB
JavaScript
import { getWindow } from '@zag-js/dom-query';
import { reactive, ref, onMounted, onBeforeUnmount, computed, toValue, useId } from 'vue';
import { parts } from './fieldset.anatomy.js';
const useFieldset = (props) => {
const state = reactive({
hasErrorText: false,
hasHelperText: false
});
const rootRef = ref(null);
let observer = null;
onMounted(() => {
const rootNode = rootRef.value;
if (!rootNode) return;
const win = getWindow(rootNode);
const doc = win.document;
const checkTextElements = () => {
const fieldsetProps = toValue(props);
const id = fieldsetProps.id ?? useId();
const errorTextId = `fieldset::${id}::error-text`;
const helperTextId = `fieldset::${id}::helper-text`;
state.hasErrorText = !!doc.getElementById(errorTextId);
state.hasHelperText = !!doc.getElementById(helperTextId);
};
checkTextElements();
observer = new win.MutationObserver(checkTextElements);
observer.observe(rootNode, { childList: true, subtree: true });
});
onBeforeUnmount(() => {
observer?.disconnect();
});
return computed(() => {
const fieldsetProps = toValue(props);
const { disabled, invalid } = fieldsetProps;
const id = fieldsetProps.id ?? useId();
const errorTextId = `fieldset::${id}::error-text`;
const helperTextId = `fieldset::${id}::helper-text`;
const labelId = `fieldset::${id}::label`;
const labelIds = [];
if (state.hasErrorText && invalid) labelIds.push(errorTextId);
if (state.hasHelperText) labelIds.push(helperTextId);
const getRootProps = () => ({
...parts.root.attrs,
disabled,
"data-disabled": disabled ? "true" : void 0,
"data-invalid": invalid ? "true" : void 0,
"aria-describedby": labelIds.join(" ")
});
const getLegendProps = () => ({
id: labelId,
...parts.legend.attrs,
"data-disabled": disabled ? "true" : void 0,
"data-invalid": invalid ? "true" : void 0
});
const getHelperTextProps = () => ({
id: helperTextId,
...parts.helperText.attrs
});
const getErrorTextProps = () => ({
id: errorTextId,
...parts.errorText.attrs,
"aria-live": "polite"
});
return {
refs: {
rootRef
},
disabled,
invalid,
getRootProps,
getLegendProps,
getHelperTextProps,
getErrorTextProps
};
});
};
export { useFieldset };