@iris-ui-kit/vue 0.2.21 → 0.2.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/admin.cjs +14 -5
  2. package/dist/admin.cjs.map +1 -1
  3. package/dist/admin.js +2 -2
  4. package/dist/async.cjs +48 -2
  5. package/dist/async.cjs.map +1 -1
  6. package/dist/async.d.cts +27 -3
  7. package/dist/async.d.ts +27 -3
  8. package/dist/async.js +1 -1
  9. package/dist/chunk-25NYWSXP.js +20 -0
  10. package/dist/chunk-25NYWSXP.js.map +1 -0
  11. package/dist/{chunk-4FLIW67H.js → chunk-IAG64CHL.js} +21 -28
  12. package/dist/chunk-IAG64CHL.js.map +1 -0
  13. package/dist/chunk-NNOF7KUH.js +24 -0
  14. package/dist/chunk-NNOF7KUH.js.map +1 -0
  15. package/dist/{chunk-4WQOZ2OV.js → chunk-QQ25RKOO.js} +6 -4
  16. package/dist/chunk-QQ25RKOO.js.map +1 -0
  17. package/dist/chunk-SJB5DIIY.js +119 -0
  18. package/dist/chunk-SJB5DIIY.js.map +1 -0
  19. package/dist/form.cjs +28 -23
  20. package/dist/form.cjs.map +1 -1
  21. package/dist/form.d.cts +3 -2
  22. package/dist/form.d.ts +3 -2
  23. package/dist/form.js +2 -1
  24. package/dist/index.cjs +88 -35
  25. package/dist/index.cjs.map +1 -1
  26. package/dist/index.js +10 -9
  27. package/dist/index.js.map +1 -1
  28. package/dist/machine.cjs +11 -4
  29. package/dist/machine.cjs.map +1 -1
  30. package/dist/machine.d.cts +12 -3
  31. package/dist/machine.d.ts +12 -3
  32. package/dist/machine.js +1 -1
  33. package/dist/resource.cjs +7 -3
  34. package/dist/resource.cjs.map +1 -1
  35. package/dist/resource.d.cts +10 -1
  36. package/dist/resource.d.ts +10 -1
  37. package/dist/resource.js +1 -1
  38. package/package.json +1 -1
  39. package/dist/chunk-4FLIW67H.js.map +0 -1
  40. package/dist/chunk-4WQOZ2OV.js.map +0 -1
  41. package/dist/chunk-TQB5LVOH.js +0 -17
  42. package/dist/chunk-TQB5LVOH.js.map +0 -1
  43. package/dist/chunk-XSLBANUV.js +0 -16
  44. package/dist/chunk-XSLBANUV.js.map +0 -1
  45. package/dist/chunk-ZY4NLITM.js +0 -73
  46. package/dist/chunk-ZY4NLITM.js.map +0 -1
package/dist/form.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/form/context.ts","../src/form/Form.ts","../src/form/useForm.ts","../src/form/useField.ts","../src/form/useFieldArray.ts"],"names":["inject","defineComponent","provide","ref","h","createFormStore","onBeforeUnmount","computed","formatPath","getByPath"],"mappings":";;;;;;AAQO,IAAM,gBAAA,0BAA+D,UAAU;AAE/E,SAAS,cAAA,GAAwC;AACtD,EAAA,MAAM,IAAA,GAAOA,UAAA,CAAO,gBAAA,EAAkB,IAAI,CAAA;AAC1C,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,MAAM,IAAI,MAAM,6DAA6D,CAAA;AAAA,EAC/E;AACA,EAAA,OAAO,IAAA;AACT;;;ACXA,SAAS,eAAA,CACP,QACA,MAAA,EACM;AACN,EAAA,IAAI,CAAC,MAAA,EAAQ;AACb,EAAA,MAAM,IAAA,GAAO,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA;AAC/B,EAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACvB,EAAA,MAAM,WAAW,MAAA,CAAO,gBAAA;AAAA,IACtB;AAAA,GACF;AACA,EAAA,KAAA,MAAW,EAAA,IAAM,KAAA,CAAM,IAAA,CAAK,QAAQ,CAAA,EAAG;AACrC,IAAA,MAAM,OAAO,EAAA,CAAG,YAAA,CAAa,MAAM,CAAA,IAAK,EAAA,CAAG,aAAa,iBAAiB,CAAA;AACzE,IAAA,IAAI,IAAA,IAAQ,IAAA,CAAK,QAAA,CAAS,IAAI,CAAA,EAAG;AAC/B,MAAA,EAAA,CAAG,KAAA,EAAM;AACT,MAAA,IAAI;AACF,QAAA,EAAA,CAAG,cAAA,CAAe,EAAE,KAAA,EAAO,QAAA,EAAU,CAAA;AAAA,MACvC,CAAA,CAAA,MAAQ;AAAA,MAER;AACA,MAAA;AAAA,IACF;AAAA,EACF;AACF;AAaO,IAAM,WAAWC,mBAAA,CAAgB;AAAA,EACtC,IAAA,EAAM,UAAA;AAAA,EACN,KAAA,EAAO;AAAA;AAAA,IAEL,IAAA,EAAM;AAAA,MACJ,IAAA,EAAM,MAAA;AAAA,MACN,QAAA,EAAU;AAAA;AACZ,GACF;AAAA,EACA,KAAA,CAAM,KAAA,EAAO,EAAE,KAAA,EAAM,EAAG;AACtB,IAAAC,WAAA,CAAQ,gBAAA,EAAkB,MAAM,IAAI,CAAA;AACpC,IAAA,MAAM,OAAA,GAAUC,QAAwB,IAAI,CAAA;AAC5C,IAAA,OAAO,MACLC,KAAA;AAAA,MACE,MAAA;AAAA,MACA;AAAA,QACE,GAAA,EAAK,OAAA;AAAA,QACL,gBAAA,EAAkB,EAAA;AAAA,QAClB,QAAA,EAAU,CAAC,KAAA,KAAiB;AAC1B,UAAA,KAAA,CAAM,cAAA,EAAe;AAErB,UAAA,KAAK,KAAA,CAAM,IAAA,CACR,YAAA,EAAa,CACb,KAAK,MAAM,eAAA,CAAgB,OAAA,CAAQ,KAAA,EAAO,KAAA,CAAM,IAAA,CAAK,QAAA,EAAS,CAAE,MAAM,CAAC,CAAA;AAAA,QAC5E;AAAA,OACF;AAAA,MACA,MAAM,OAAA;AAAU,KAClB;AAAA,EACJ;AACF,CAAC;AC3BM,SAAS,QAA8B,MAAA,EAAyC;AACrF,EAAA,MAAM,IAAA,GAAOC,qBAAgB,MAAM,CAAA;AACnC,EAAA,MAAM,KAAA,GAAQF,OAAAA,CAAI,IAAA,CAAK,QAAA,EAAU,CAAA;AACjC,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,SAAA,CAAU,CAAC,IAAA,KAAS;AAC3C,IAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AAAA,EAChB,CAAC,CAAA;AACD,EAAAG,mBAAA,CAAgB,WAAW,CAAA;AAE3B,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAA,EAAQC,YAAA,CAAS,MAAM,KAAA,CAAM,MAAM,MAAM,CAAA;AAAA,IACzC,MAAA,EAAQA,YAAA,CAAS,MAAM,KAAA,CAAM,MAAM,MAAM,CAAA;AAAA,IACzC,OAAA,EAASA,YAAA,CAAS,MAAM,KAAA,CAAM,MAAM,OAAO,CAAA;AAAA,IAC3C,KAAA,EAAOA,YAAA,CAAS,MAAM,KAAA,CAAM,MAAM,KAAK,CAAA;AAAA,IACvC,YAAA,EAAcA,YAAA,CAAS,MAAM,KAAA,CAAM,MAAM,YAAY,CAAA;AAAA,IACrD,YAAA,EAAcA,YAAA,CAAS,MAAM,KAAA,CAAM,MAAM,YAAY,CAAA;AAAA,IACrD,WAAA,EAAaA,YAAA,CAAS,MAAM,KAAA,CAAM,MAAM,WAAW,CAAA;AAAA,IACnD,OAAA,EAASA,YAAA,CAAS,MAAM,MAAA,CAAO,IAAA,CAAK,MAAM,KAAA,CAAM,MAAM,CAAA,CAAE,MAAA,KAAW,CAAC,CAAA;AAAA,IACpE,eAAe,IAAA,CAAK,aAAA;AAAA,IACpB,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,iBAAiB,IAAA,CAAK,eAAA;AAAA,IACtB,eAAe,IAAA,CAAK,aAAA;AAAA,IACpB,WAAW,IAAA,CAAK,SAAA;AAAA,IAChB,eAAe,IAAA,CAAK,aAAA;AAAA,IACpB,cAAc,IAAA,CAAK,YAAA;AAAA,IACnB,cAAc,IAAA,CAAK,YAAA;AAAA,IACnB,OAAO,IAAA,CAAK;AAAA,GACd;AACF;ACpCO,SAAS,SAAsB,IAAA,EAAiC;AACrE,EAAA,MAAM,OAAO,cAAA,EAAe;AAC5B,EAAA,MAAM,KAAA,GAAQJ,OAAAA,CAAI,IAAA,CAAK,QAAA,EAAU,CAAA;AACjC,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,SAAA,CAAU,CAAC,IAAA,KAAS;AAC3C,IAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AAAA,EAChB,CAAC,CAAA;AACD,EAAAG,oBAAgB,WAAW,CAAA;AAG3B,EAAA,MAAM,GAAA,GAAME,gBAAW,IAAI,CAAA;AAC3B,EAAA,MAAM,KAAA,GAAQD,aAAS,MAAME,cAAA,CAAU,MAAM,KAAA,CAAM,MAAA,EAAQ,IAAI,CAAM,CAAA;AACrE,EAAA,MAAM,QAAQF,YAAAA,CAAS,MAAM,MAAM,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAEpD,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,KAAA;AAAA,IACA,KAAA;AAAA,IACA,OAAA,EAASA,aAAS,MAAM,OAAA,CAAQ,MAAM,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAC,CAAC,CAAA;AAAA,IACzD,KAAA,EAAOA,aAAS,MAAM,OAAA,CAAQ,MAAM,KAAA,CAAM,KAAA,CAAM,GAAG,CAAC,CAAC,CAAA;AAAA,IACrD,UAAU,CAAC,IAAA,KAAS,IAAA,CAAK,aAAA,CAAc,MAAM,IAAa,CAAA;AAAA,IAC1D,YAAY,CAAC,OAAA,GAAU,SAAS,IAAA,CAAK,eAAA,CAAgB,MAAM,OAAO,CAAA;AAAA,IAClE,UAAA,EAAYA,aAAS,OAAO;AAAA,MAC1B,YAAY,KAAA,CAAM,KAAA;AAAA,MAClB,uBAAuB,CAAC,IAAA,KAAkB,IAAA,CAAK,aAAA,CAAc,MAAM,IAAa,CAAA;AAAA,MAChF,OAAA,EAAS,OAAA,CAAQ,KAAA,CAAM,KAAK,CAAA;AAAA,MAC5B,MAAA,EAAQ,MAAM,IAAA,CAAK,eAAA,CAAgB,MAAM,IAAI;AAAA,KAC/C,CAAE;AAAA,GACJ;AACF;ACnCO,SAAS,cAA2B,IAAA,EAAsC;AAC/E,EAAA,MAAM,OAAO,cAAA,EAAe;AAC5B,EAAA,MAAM,KAAA,GAAQJ,OAAAA,CAAI,IAAA,CAAK,QAAA,EAAU,CAAA;AACjC,EAAA,MAAM,WAAA,GAAc,IAAA,CAAK,SAAA,CAAU,CAAC,IAAA,KAAS;AAC3C,IAAA,KAAA,CAAM,KAAA,GAAQ,IAAA;AAAA,EAChB,CAAC,CAAA;AACD,EAAAG,oBAAgB,WAAW,CAAA;AAE3B,EAAA,OAAO;AAAA,IACL,IAAA;AAAA,IACA,MAAA,EAAQC,YAAAA;AAAA,MACN,MAAO,KAAA,CAAM,OAAA,CAAQ,KAAA,CAAM,MAAM,MAAA,CAAO,IAAI,CAAC,CAAA,GAAI,KAAA,CAAM,KAAA,CAAM,MAAA,CAAO,IAAI,IAAI;AAAC,KAC/E;AAAA,IACA,MAAM,CAAC,IAAA,KAAS,IAAA,CAAK,SAAA,CAAU,MAAe,IAAa,CAAA;AAAA,IAC3D,QAAQ,CAAC,KAAA,KAAU,IAAA,CAAK,WAAA,CAAY,MAAe,KAAK,CAAA;AAAA,IACxD,MAAA,EAAQ,CAAC,KAAA,EAAO,IAAA,KAAS,KAAK,WAAA,CAAY,IAAA,EAAe,OAAO,IAAa,CAAA;AAAA,IAC7E,IAAA,EAAM,CAAC,IAAA,EAAM,EAAA,KAAO,KAAK,SAAA,CAAU,IAAA,EAAe,MAAM,EAAE,CAAA;AAAA,IAC1D,SAAS,CAAC,KAAA,KAAU,IAAA,CAAK,aAAA,CAAc,MAAM,KAAc;AAAA,GAC7D;AACF","file":"form.cjs","sourcesContent":["import { inject, type InjectionKey } from 'vue'\nimport type { FormStore, FormValues } from '@iris-ui-kit/core'\n\n/**\n * Provides the active form's {@link FormStore} to descendant fields so\n * `useField` can bind without prop drilling. The generic is erased at the\n * injection boundary; `useField<T>` re-applies the value type at the call site.\n */\nexport const FormInjectionKey: InjectionKey<FormStore<FormValues>> = Symbol('IrisForm')\n\nexport function useFormContext(): FormStore<FormValues> {\n const form = inject(FormInjectionKey, null)\n if (!form) {\n throw new Error('useField / useFormContext must be used within an <IrisForm>')\n }\n return form\n}\n","import { defineComponent, h, provide, ref, type PropType } from 'vue'\nimport type { FormStore, FormValues } from '@iris-ui-kit/core'\nimport { FormInjectionKey } from './context'\n\n/** Focus (and best-effort scroll to) the first errored named control in DOM order. */\nfunction focusFirstError(\n formEl: HTMLElement | null,\n errors: Record<string, string | undefined>,\n): void {\n if (!formEl) return\n const keys = Object.keys(errors)\n if (keys.length === 0) return\n const controls = formEl.querySelectorAll<HTMLElement>(\n 'input[name], select[name], textarea[name], [data-iris-field]',\n )\n for (const el of Array.from(controls)) {\n const name = el.getAttribute('name') ?? el.getAttribute('data-iris-field')\n if (name && keys.includes(name)) {\n el.focus()\n try {\n el.scrollIntoView({ block: 'center' })\n } catch {\n /* scrollIntoView is unavailable in jsdom — focus is the contract */\n }\n return\n }\n }\n}\n\n/**\n * Provides the form store to descendant `useField` calls and wires the native\n * `<form>` submit to `handleSubmit` (with `preventDefault`). Composition:\n *\n * ```html\n * <IrisForm :form=\"f.form\">\n * <IrisFormField label=\"Email\"><IrisInput v-bind=\"email.fieldProps.value\" /></IrisFormField>\n * <IrisButton type=\"submit\" :disabled=\"f.isSubmitting.value\">Save</IrisButton>\n * </IrisForm>\n * ```\n */\nexport const IrisForm = defineComponent({\n name: 'IrisForm',\n props: {\n /** The store from `useForm(...).form`. */\n form: {\n type: Object as PropType<FormStore<FormValues>>,\n required: true,\n },\n },\n setup(props, { slots }) {\n provide(FormInjectionKey, props.form)\n const formRef = ref<HTMLElement | null>(null)\n return () =>\n h(\n 'form',\n {\n ref: formRef,\n 'data-iris-form': '',\n onSubmit: (event: Event) => {\n event.preventDefault()\n // On a failed submit, move focus to the first errored field (a11y).\n void props.form\n .handleSubmit()\n .then(() => focusFirstError(formRef.value, props.form.getState().errors))\n },\n },\n slots.default?.(),\n )\n },\n})\n","import { computed, onBeforeUnmount, ref, type ComputedRef, type Ref } from 'vue'\nimport {\n createFormStore,\n type FieldErrors,\n type FieldFlags,\n type FormConfig,\n type FormState,\n type FormStore,\n type FormValues,\n} from '@iris-ui-kit/core'\n\nexport interface UseFormReturn<V extends FormValues> {\n /** The form store — pass to `<IrisForm :form=\"...\">`. */\n form: FormStore<V>\n /** The full reactive state snapshot. */\n state: Ref<FormState<V>>\n values: ComputedRef<V>\n errors: ComputedRef<FieldErrors<V>>\n touched: ComputedRef<FieldFlags<V>>\n dirty: ComputedRef<FieldFlags<V>>\n isSubmitting: ComputedRef<boolean>\n isValidating: ComputedRef<boolean>\n submitCount: ComputedRef<number>\n isValid: ComputedRef<boolean>\n setFieldValue: FormStore<V>['setFieldValue']\n setValues: FormStore<V>['setValues']\n setFieldTouched: FormStore<V>['setFieldTouched']\n setFieldError: FormStore<V>['setFieldError']\n setErrors: FormStore<V>['setErrors']\n validateField: FormStore<V>['validateField']\n validateForm: FormStore<V>['validateForm']\n handleSubmit: FormStore<V>['handleSubmit']\n reset: FormStore<V>['reset']\n}\n\n/**\n * Vue binding for the framework-agnostic form engine. Creates the store in\n * `setup()` (runs once) and bridges it into Vue reactivity via a `ref` updated\n * on each store change, cleaned up on unmount. Because `setup` runs once,\n * `onSubmit` / `validate` closures stay live against reactive state — no\n * stale-callback handling is needed (unlike the React adapter).\n */\nexport function useForm<V extends FormValues>(config: FormConfig<V>): UseFormReturn<V> {\n const form = createFormStore(config)\n const state = ref(form.getState()) as Ref<FormState<V>>\n const unsubscribe = form.subscribe((next) => {\n state.value = next\n })\n onBeforeUnmount(unsubscribe)\n\n return {\n form,\n state,\n values: computed(() => state.value.values),\n errors: computed(() => state.value.errors),\n touched: computed(() => state.value.touched),\n dirty: computed(() => state.value.dirty),\n isSubmitting: computed(() => state.value.isSubmitting),\n isValidating: computed(() => state.value.isValidating),\n submitCount: computed(() => state.value.submitCount),\n isValid: computed(() => Object.keys(state.value.errors).length === 0),\n setFieldValue: form.setFieldValue,\n setValues: form.setValues,\n setFieldTouched: form.setFieldTouched,\n setFieldError: form.setFieldError,\n setErrors: form.setErrors,\n validateField: form.validateField,\n validateForm: form.validateForm,\n handleSubmit: form.handleSubmit,\n reset: form.reset,\n }\n}\n","import { computed, onBeforeUnmount, ref, type ComputedRef, type Ref } from 'vue'\nimport { formatPath, getByPath, type FormState, type FormValues } from '@iris-ui-kit/core'\nimport { useFormContext } from './context'\n\nexport interface FieldBindProps {\n modelValue: unknown\n 'onUpdate:modelValue': (value: unknown) => void\n invalid: boolean\n onBlur: () => void\n}\n\nexport interface UseFieldReturn<T> {\n name: string\n value: ComputedRef<T>\n error: ComputedRef<string | undefined>\n touched: ComputedRef<boolean>\n dirty: ComputedRef<boolean>\n setValue: (value: T) => void\n setTouched: (touched?: boolean) => void\n /**\n * Bundle for `v-bind` onto a v-model'd Iris control (`IrisInput`,\n * `IrisSelect`, …): wires `modelValue` / `update:modelValue` / `invalid` /\n * `blur`. Use `value` + `setValue` directly for bespoke bindings.\n */\n fieldProps: ComputedRef<FieldBindProps>\n}\n\n/**\n * Binds a single field to the surrounding `<IrisForm>`. `T` is the value type\n * at the call site (the injection erases the form's generic).\n *\n * `name` may be a flat top-level key OR a nested PATH (`'address.city'`,\n * `'items[2].sku'`); a flat key is a 1-segment path and stays back-compatible\n * (v3 R19).\n */\nexport function useField<T = unknown>(name: string): UseFieldReturn<T> {\n const form = useFormContext()\n const state = ref(form.getState()) as Ref<FormState<FormValues>>\n const unsubscribe = form.subscribe((next) => {\n state.value = next\n })\n onBeforeUnmount(unsubscribe)\n\n // Canonical key for per-field state lookups (a flat key maps to itself).\n const key = formatPath(name)\n const value = computed(() => getByPath(state.value.values, name) as T)\n const error = computed(() => state.value.errors[key])\n\n return {\n name,\n value,\n error,\n touched: computed(() => Boolean(state.value.touched[key])),\n dirty: computed(() => Boolean(state.value.dirty[key])),\n setValue: (next) => form.setFieldValue(name, next as never),\n setTouched: (touched = true) => form.setFieldTouched(name, touched),\n fieldProps: computed(() => ({\n modelValue: value.value,\n 'onUpdate:modelValue': (next: unknown) => form.setFieldValue(name, next as never),\n invalid: Boolean(error.value),\n onBlur: () => form.setFieldTouched(name, true),\n })),\n }\n}\n","import { computed, onBeforeUnmount, ref, type ComputedRef, type Ref } from 'vue'\nimport type { FormState, FormValues } from '@iris-ui-kit/core'\nimport { useFormContext } from './context'\n\nexport interface UseFieldArrayReturn<T> {\n name: string\n /** Current array value (reactive). */\n fields: ComputedRef<T[]>\n /** Append an item. */\n push: (item: T) => void\n /** Remove the item at `index`. */\n remove: (index: number) => void\n /** Insert `item` at `index` (shifting the rest right). */\n insert: (index: number, item: T) => void\n /** Move the item from `from` to `to`. */\n move: (from: number, to: number) => void\n /** Replace the whole array. */\n replace: (items: T[]) => void\n}\n\n/**\n * Manage a dynamic array field (repeatable rows) inside an `<IrisForm>`. Mutators\n * delegate to the core {@link FormStore} array helpers (`arrayPush`/`arrayInsert`/\n * `arrayRemove`/`arrayMove`), which RE-KEY each element's error/touched/dirty/\n * validating state across the mutation — so a row's per-element validation state\n * FOLLOWS the row when rows are removed or reordered (removing `items[0]` shifts\n * `items[2]`'s error down to `items[1]`). `replace` swaps the whole array.\n */\nexport function useFieldArray<T = unknown>(name: string): UseFieldArrayReturn<T> {\n const form = useFormContext()\n const state = ref(form.getState()) as Ref<FormState<FormValues>>\n const unsubscribe = form.subscribe((next) => {\n state.value = next\n })\n onBeforeUnmount(unsubscribe)\n\n return {\n name,\n fields: computed(\n () => (Array.isArray(state.value.values[name]) ? state.value.values[name] : []) as T[],\n ),\n push: (item) => form.arrayPush(name as never, item as never),\n remove: (index) => form.arrayRemove(name as never, index),\n insert: (index, item) => form.arrayInsert(name as never, index, item as never),\n move: (from, to) => form.arrayMove(name as never, from, to),\n replace: (items) => form.setFieldValue(name, items as never),\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/form/context.ts","../src/form/Form.ts","../src/useStore.ts","../src/form/useForm.ts","../src/form/useField.ts","../src/form/useFieldArray.ts"],"names":["inject","defineComponent","provide","ref","h","shallowRef","onScopeDispose","createFormStore","computed","formatPath","parsePath","getByPath","touched"],"mappings":"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","file":"form.cjs","sourcesContent":["import { inject, type InjectionKey } from 'vue'\nimport type { FormStore, FormValues } from '@iris-ui-kit/core'\n\n/**\n * Provides the active form's {@link FormStore} to descendant fields so\n * `useField` can bind without prop drilling. The generic is erased at the\n * injection boundary; `useField<T>` re-applies the value type at the call site.\n */\nexport const FormInjectionKey: InjectionKey<FormStore<FormValues>> = Symbol('IrisForm')\n\nexport function useFormContext(): FormStore<FormValues> {\n const form = inject(FormInjectionKey, null)\n if (!form) {\n throw new Error('useField / useFormContext must be used within an <IrisForm>')\n }\n return form\n}\n","import { defineComponent, h, provide, ref, type PropType } from 'vue'\nimport type { FormStore, FormValues } from '@iris-ui-kit/core'\nimport { FormInjectionKey } from './context'\n\n/** Focus (and best-effort scroll to) the first errored named control in DOM order. */\nfunction focusFirstError(\n formEl: HTMLElement | null,\n errors: Record<string, string | undefined>,\n): void {\n if (!formEl) return\n const keys = Object.keys(errors)\n if (keys.length === 0) return\n const controls = formEl.querySelectorAll<HTMLElement>(\n 'input[name], select[name], textarea[name], [data-iris-field]',\n )\n for (const el of Array.from(controls)) {\n const name = el.getAttribute('name') ?? el.getAttribute('data-iris-field')\n if (name && keys.includes(name)) {\n el.focus()\n try {\n el.scrollIntoView({ block: 'center' })\n } catch {\n /* scrollIntoView is unavailable in jsdom — focus is the contract */\n }\n return\n }\n }\n}\n\n/**\n * Provides the form store to descendant `useField` calls and wires the native\n * `<form>` submit to `handleSubmit` (with `preventDefault`). Composition:\n *\n * ```html\n * <IrisForm :form=\"f.form\">\n * <IrisFormField label=\"Email\"><IrisInput v-bind=\"email.fieldProps.value\" /></IrisFormField>\n * <IrisButton type=\"submit\" :disabled=\"f.isSubmitting.value\">Save</IrisButton>\n * </IrisForm>\n * ```\n */\nexport const IrisForm = defineComponent({\n name: 'IrisForm',\n props: {\n /** The store from `useForm(...).form`. */\n form: {\n type: Object as PropType<FormStore<FormValues>>,\n required: true,\n },\n },\n setup(props, { slots }) {\n provide(FormInjectionKey, props.form)\n const formRef = ref<HTMLElement | null>(null)\n return () =>\n h(\n 'form',\n {\n ref: formRef,\n 'data-iris-form': '',\n onSubmit: (event: Event) => {\n event.preventDefault()\n // On a failed submit, move focus to the first errored field (a11y).\n void props.form\n .handleSubmit()\n .then(() => focusFirstError(formRef.value, props.form.getState().errors))\n },\n },\n slots.default?.(),\n )\n },\n})\n","import { shallowRef, onScopeDispose, type ShallowRef } from 'vue'\nimport type { ReadonlyStore, Store } from '@iris-ui-kit/core'\n\n/**\n * Bridge a framework-agnostic `@iris-ui-kit/core` store into a Vue ref — updates on\n * every store emission. The mirror of React's `useSyncExternalStore`, Solid's\n * `createSignal`, and Svelte's `readable`. Seeds synchronously from\n * `store.getState()` (SSR-safe); detaches on scope dispose.\n */\nexport function useStore<T>(store: ReadonlyStore<T>): Readonly<ShallowRef<T>> {\n const state = shallowRef(store.getState()) as ShallowRef<T>\n onScopeDispose(store.subscribe((next) => (state.value = next)))\n return state\n}\n\n/**\n * Subscribe to a DERIVED slice of a core store — the ref updates only when\n * `selector(state)` changes per `equals` (default `Object.is`), not on every\n * store emission. Built on {@link Store.subscribeWith}.\n */\nexport function useStoreSelector<T, U>(\n store: Store<T>,\n selector: (state: T) => U,\n equals?: (a: U, b: U) => boolean,\n): Readonly<ShallowRef<U>> {\n const slice = shallowRef(selector(store.getState())) as ShallowRef<U>\n onScopeDispose(store.subscribeWith(selector, (v) => (slice.value = v), equals))\n return slice\n}\n","import { computed, type ComputedRef, type Ref } from 'vue'\nimport {\n createFormStore,\n type FieldErrors,\n type FieldFlags,\n type FormConfig,\n type FormState,\n type FormStore,\n type FormValues,\n} from '@iris-ui-kit/core'\nimport { useStore } from '../useStore'\n\nexport interface UseFormReturn<V extends FormValues> {\n /** The form store — pass to `<IrisForm :form=\"...\">`. */\n form: FormStore<V>\n /** The full reactive state snapshot. */\n state: Ref<FormState<V>>\n values: ComputedRef<V>\n errors: ComputedRef<FieldErrors<V>>\n touched: ComputedRef<FieldFlags<V>>\n dirty: ComputedRef<FieldFlags<V>>\n isSubmitting: ComputedRef<boolean>\n isValidating: ComputedRef<boolean>\n submitCount: ComputedRef<number>\n isValid: ComputedRef<boolean>\n setFieldValue: FormStore<V>['setFieldValue']\n setValues: FormStore<V>['setValues']\n setFieldTouched: FormStore<V>['setFieldTouched']\n setFieldError: FormStore<V>['setFieldError']\n setErrors: FormStore<V>['setErrors']\n validateField: FormStore<V>['validateField']\n validateForm: FormStore<V>['validateForm']\n handleSubmit: FormStore<V>['handleSubmit']\n reset: FormStore<V>['reset']\n}\n\n/**\n * Vue binding for the framework-agnostic form engine. Creates the store in\n * `setup()` (runs once) and bridges it into Vue reactivity via `useStore` (a\n * shallow snapshot ref updated on each store change, detached on scope\n * dispose). Because `setup` runs once,\n * `onSubmit` / `validate` closures stay live against reactive state — no\n * stale-callback handling is needed (unlike the React adapter).\n */\nexport function useForm<V extends FormValues>(config: FormConfig<V>): UseFormReturn<V> {\n const form = createFormStore(config)\n\n // Whole-state bridge via the shared `useStore` (shallow, detached on scope\n // dispose — identical to the old `onBeforeUnmount` for setup-scope consumers,\n // and correct for nested scopes too). The published `state: Ref<FormState<V>>`\n // type is unchanged (R5); the runtime is a shallow snapshot — the store is the\n // only write path (it always was), so this localized cast is type-only. The\n // per-field narrowing payoff comes from `useField` / `useFieldArray`; the\n // form-level computeds below are whole-form aggregates by design.\n const state = useStore(form.store) as unknown as Ref<FormState<V>>\n\n return {\n form,\n state,\n values: computed(() => state.value.values),\n errors: computed(() => state.value.errors),\n touched: computed(() => state.value.touched),\n dirty: computed(() => state.value.dirty),\n isSubmitting: computed(() => state.value.isSubmitting),\n isValidating: computed(() => state.value.isValidating),\n submitCount: computed(() => state.value.submitCount),\n isValid: computed(() => Object.keys(state.value.errors).length === 0),\n setFieldValue: form.setFieldValue,\n setValues: form.setValues,\n setFieldTouched: form.setFieldTouched,\n setFieldError: form.setFieldError,\n setErrors: form.setErrors,\n validateField: form.validateField,\n validateForm: form.validateForm,\n handleSubmit: form.handleSubmit,\n reset: form.reset,\n }\n}\n","import { computed, type ComputedRef } from 'vue'\nimport { formatPath, getByPath, parsePath } from '@iris-ui-kit/core'\nimport { useFormContext } from './context'\nimport { useStoreSelector } from '../useStore'\n\nexport interface FieldBindProps {\n modelValue: unknown\n 'onUpdate:modelValue': (value: unknown) => void\n invalid: boolean\n onBlur: () => void\n}\n\nexport interface UseFieldReturn<T> {\n name: string\n value: ComputedRef<T>\n error: ComputedRef<string | undefined>\n touched: ComputedRef<boolean>\n dirty: ComputedRef<boolean>\n setValue: (value: T) => void\n setTouched: (touched?: boolean) => void\n /**\n * Bundle for `v-bind` onto a v-model'd Iris control (`IrisInput`,\n * `IrisSelect`, …): wires `modelValue` / `update:modelValue` / `invalid` /\n * `blur`. Use `value` + `setValue` directly for bespoke bindings.\n */\n fieldProps: ComputedRef<FieldBindProps>\n}\n\n/**\n * Binds a single field to the surrounding `<IrisForm>`. `T` is the value type\n * at the call site (the injection erases the form's generic).\n *\n * `name` may be a flat top-level key OR a nested PATH (`'address.city'`,\n * `'items[2].sku'`); a flat key is a 1-segment path and stays back-compatible\n * (v3 R19).\n */\nexport function useField<T = unknown>(name: string): UseFieldReturn<T> {\n const form = useFormContext()\n\n // Canonical key for per-field state lookups (a flat key maps to itself).\n const key = formatPath(name)\n // Hoisted once — selectors run on every store emission (core `subscribeWith`).\n const segments = parsePath(name)\n\n // Four narrow per-field slices, each Object.is-gated by core `subscribeWith`.\n // Core writes use structural sharing (`setByPath`, per-key flag spread-copies),\n // so an unrelated keystroke does NOT move these refs and this field's computeds\n // do not invalidate (previously a whole-form deep `ref` re-ran every field's\n // computeds on every emission). Selectors are allocation-free by construction.\n const valueSlice = useStoreSelector(form.store, (s) => getByPath(s.values, segments) as T)\n const errorSlice = useStoreSelector(form.store, (s) => s.errors[key])\n const touchedSlice = useStoreSelector(form.store, (s) => Boolean(s.touched[key]))\n const dirtySlice = useStoreSelector(form.store, (s) => Boolean(s.dirty[key]))\n\n // computed wrappers keep the published ComputedRef<T> member types exactly as\n // declared (a bare shallow ref is not assignable to ComputedRef in Vue 3.4+),\n // and each computed invalidates only when its own slice actually moves.\n const value = computed(() => valueSlice.value)\n const error = computed(() => errorSlice.value)\n const touched = computed(() => touchedSlice.value)\n const dirty = computed(() => dirtySlice.value)\n\n return {\n name,\n value,\n error,\n touched,\n dirty,\n setValue: (next) => form.setFieldValue(name, next as never),\n setTouched: (touched = true) => form.setFieldTouched(name, touched),\n fieldProps: computed(() => ({\n modelValue: value.value,\n 'onUpdate:modelValue': (next: unknown) => form.setFieldValue(name, next as never),\n invalid: Boolean(error.value),\n onBlur: () => form.setFieldTouched(name, true),\n })),\n }\n}\n","import { computed, type ComputedRef } from 'vue'\nimport { useFormContext } from './context'\nimport { useStoreSelector } from '../useStore'\n\nexport interface UseFieldArrayReturn<T> {\n name: string\n /** Current array value (reactive). */\n fields: ComputedRef<T[]>\n /** Append an item. */\n push: (item: T) => void\n /** Remove the item at `index`. */\n remove: (index: number) => void\n /** Insert `item` at `index` (shifting the rest right). */\n insert: (index: number, item: T) => void\n /** Move the item from `from` to `to`. */\n move: (from: number, to: number) => void\n /** Replace the whole array. */\n replace: (items: T[]) => void\n}\n\n/**\n * Manage a dynamic array field (repeatable rows) inside an `<IrisForm>`. Mutators\n * delegate to the core {@link FormStore} array helpers (`arrayPush`/`arrayInsert`/\n * `arrayRemove`/`arrayMove`), which RE-KEY each element's error/touched/dirty/\n * validating state across the mutation — so a row's per-element validation state\n * FOLLOWS the row when rows are removed or reordered (removing `items[0]` shifts\n * `items[2]`'s error down to `items[1]`). `replace` swaps the whole array.\n */\nexport function useFieldArray<T = unknown>(name: string): UseFieldArrayReturn<T> {\n const form = useFormContext()\n\n // One narrow slice for the whole array, Object.is-gated by core `subscribeWith`.\n // CRITICAL: the selector must not allocate — `(s) => s.values[name] ?? []` would\n // mint a fresh [] per emission and defeat the Object.is gate — so the `[]`\n // fallback lives in the computed wrapper (re-evaluated only when the raw slice\n // moves). Array mutations produce a fresh array (correct re-render); untouched\n // rows are unaffected.\n const raw = useStoreSelector(form.store, (s) => s.values[name])\n const fields = computed(() => (Array.isArray(raw.value) ? raw.value : []) as T[])\n\n return {\n name,\n fields,\n push: (item) => form.arrayPush(name as never, item as never),\n remove: (index) => form.arrayRemove(name as never, index),\n insert: (index, item) => form.arrayInsert(name as never, index, item as never),\n move: (from, to) => form.arrayMove(name as never, from, to),\n replace: (items) => form.setFieldValue(name, items as never),\n }\n}\n"]}
package/dist/form.d.cts CHANGED
@@ -54,8 +54,9 @@ interface UseFormReturn<V extends FormValues> {
54
54
  }
55
55
  /**
56
56
  * Vue binding for the framework-agnostic form engine. Creates the store in
57
- * `setup()` (runs once) and bridges it into Vue reactivity via a `ref` updated
58
- * on each store change, cleaned up on unmount. Because `setup` runs once,
57
+ * `setup()` (runs once) and bridges it into Vue reactivity via `useStore` (a
58
+ * shallow snapshot ref updated on each store change, detached on scope
59
+ * dispose). Because `setup` runs once,
59
60
  * `onSubmit` / `validate` closures stay live against reactive state — no
60
61
  * stale-callback handling is needed (unlike the React adapter).
61
62
  */
package/dist/form.d.ts CHANGED
@@ -54,8 +54,9 @@ interface UseFormReturn<V extends FormValues> {
54
54
  }
55
55
  /**
56
56
  * Vue binding for the framework-agnostic form engine. Creates the store in
57
- * `setup()` (runs once) and bridges it into Vue reactivity via a `ref` updated
58
- * on each store change, cleaned up on unmount. Because `setup` runs once,
57
+ * `setup()` (runs once) and bridges it into Vue reactivity via `useStore` (a
58
+ * shallow snapshot ref updated on each store change, detached on scope
59
+ * dispose). Because `setup` runs once,
59
60
  * `onSubmit` / `validate` closures stay live against reactive state — no
60
61
  * stale-callback handling is needed (unlike the React adapter).
61
62
  */
package/dist/form.js CHANGED
@@ -1,3 +1,4 @@
1
- export { FormInjectionKey, IrisForm, useField, useFieldArray, useForm, useFormContext } from './chunk-4FLIW67H.js';
1
+ export { FormInjectionKey, IrisForm, useField, useFieldArray, useForm, useFormContext } from './chunk-IAG64CHL.js';
2
+ import './chunk-75GSYEJS.js';
2
3
  //# sourceMappingURL=form.js.map
3
4
  //# sourceMappingURL=form.js.map
package/dist/index.cjs CHANGED
@@ -226,14 +226,21 @@ function useSkin() {
226
226
  errors: engine.errors
227
227
  };
228
228
  }
229
- function useMachine(machine) {
229
+ function useMachine(machine, options = {}) {
230
230
  const state = vue.ref(machine.store.getState());
231
231
  const unsubscribe = machine.store.subscribe((next) => {
232
232
  state.value = next;
233
233
  });
234
- vue.onBeforeUnmount(() => {
235
- unsubscribe();
236
- });
234
+ vue.onScopeDispose(
235
+ () => {
236
+ unsubscribe();
237
+ if (options.stopOnUnmount !== false) machine.stop();
238
+ },
239
+ // failSilently: outside any effect scope there is nothing to dispose —
240
+ // registering is a no-op and must not emit the "no active effect scope"
241
+ // dev warning. Within a component/effectScope this arg changes nothing.
242
+ true
243
+ );
237
244
  return { state, send: machine.send };
238
245
  }
239
246
  var FormInjectionKey = /* @__PURE__ */ Symbol("IrisForm");
@@ -293,11 +300,7 @@ var IrisForm = vue.defineComponent({
293
300
  });
294
301
  function useForm(config) {
295
302
  const form = core.createFormStore(config);
296
- const state = vue.ref(form.getState());
297
- const unsubscribe = form.subscribe((next) => {
298
- state.value = next;
299
- });
300
- vue.onBeforeUnmount(unsubscribe);
303
+ const state = useStore(form.store);
301
304
  return {
302
305
  form,
303
306
  state,
@@ -322,22 +325,24 @@ function useForm(config) {
322
325
  }
323
326
  function useField(name) {
324
327
  const form = useFormContext();
325
- const state = vue.ref(form.getState());
326
- const unsubscribe = form.subscribe((next) => {
327
- state.value = next;
328
- });
329
- vue.onBeforeUnmount(unsubscribe);
330
328
  const key = core.formatPath(name);
331
- const value = vue.computed(() => core.getByPath(state.value.values, name));
332
- const error = vue.computed(() => state.value.errors[key]);
329
+ const segments = core.parsePath(name);
330
+ const valueSlice = useStoreSelector(form.store, (s) => core.getByPath(s.values, segments));
331
+ const errorSlice = useStoreSelector(form.store, (s) => s.errors[key]);
332
+ const touchedSlice = useStoreSelector(form.store, (s) => Boolean(s.touched[key]));
333
+ const dirtySlice = useStoreSelector(form.store, (s) => Boolean(s.dirty[key]));
334
+ const value = vue.computed(() => valueSlice.value);
335
+ const error = vue.computed(() => errorSlice.value);
336
+ const touched = vue.computed(() => touchedSlice.value);
337
+ const dirty = vue.computed(() => dirtySlice.value);
333
338
  return {
334
339
  name,
335
340
  value,
336
341
  error,
337
- touched: vue.computed(() => Boolean(state.value.touched[key])),
338
- dirty: vue.computed(() => Boolean(state.value.dirty[key])),
342
+ touched,
343
+ dirty,
339
344
  setValue: (next) => form.setFieldValue(name, next),
340
- setTouched: (touched = true) => form.setFieldTouched(name, touched),
345
+ setTouched: (touched2 = true) => form.setFieldTouched(name, touched2),
341
346
  fieldProps: vue.computed(() => ({
342
347
  modelValue: value.value,
343
348
  "onUpdate:modelValue": (next) => form.setFieldValue(name, next),
@@ -348,16 +353,11 @@ function useField(name) {
348
353
  }
349
354
  function useFieldArray(name) {
350
355
  const form = useFormContext();
351
- const state = vue.ref(form.getState());
352
- const unsubscribe = form.subscribe((next) => {
353
- state.value = next;
354
- });
355
- vue.onBeforeUnmount(unsubscribe);
356
+ const raw = useStoreSelector(form.store, (s) => s.values[name]);
357
+ const fields = vue.computed(() => Array.isArray(raw.value) ? raw.value : []);
356
358
  return {
357
359
  name,
358
- fields: vue.computed(
359
- () => Array.isArray(state.value.values[name]) ? state.value.values[name] : []
360
- ),
360
+ fields,
361
361
  push: (item) => form.arrayPush(name, item),
362
362
  remove: (index) => form.arrayRemove(name, index),
363
363
  insert: (index, item) => form.arrayInsert(name, index, item),
@@ -465,8 +465,31 @@ function useI18n() {
465
465
  };
466
466
  }
467
467
  function useAsyncResource(fetcher, options = {}) {
468
+ const holder = {
469
+ // isRef-only resolution. NEVER toValue() here: the element type is itself
470
+ // a function, so toValue(fetcher) would *invoke the fetcher at setup*
471
+ // (spurious request) and toValue(getter) would do the same. isRef narrows
472
+ // to the only unambiguous reactive form: ref(fetcher) / computed(() =>
473
+ // fetcher) / shallowRef(fetcher) — a ComputedRef IS a Ref.
474
+ // F3 elision point — the ONE explicit narrowing cast: after the isRef
475
+ // guard the else arm is `F | (() => F)`, and the bare-getter arm's return
476
+ // `F` (a function) is not assignable to `F` (TS2322). No runtime
477
+ // discriminant distinguishes a plain fetcher from a bare getter (both are
478
+ // functions), so the cast encodes exactly the documented F3 ambiguity and
479
+ // adds no unsafety beyond F3.
480
+ current: vue.isRef(fetcher) ? fetcher.value : fetcher
481
+ };
482
+ if (vue.isRef(fetcher)) {
483
+ vue.watch(
484
+ fetcher,
485
+ (next) => {
486
+ holder.current = next;
487
+ },
488
+ { flush: "sync" }
489
+ );
490
+ }
468
491
  const config = "initialData" in options ? { initialData: options.initialData } : {};
469
- const resource = core.createAsyncResource(fetcher, config);
492
+ const resource = core.createAsyncResource((...params) => holder.current(...params), config);
470
493
  const state = vue.ref(resource.getState());
471
494
  const unsubscribe = resource.subscribe((next) => {
472
495
  state.value = next;
@@ -494,7 +517,30 @@ function useAsyncResource(fetcher, options = {}) {
494
517
  };
495
518
  }
496
519
  function usePaginatedResource(fetcher, options = {}) {
497
- const resource = core.createPaginatedResource(fetcher, {
520
+ const holder = {
521
+ // isRef-only resolution. NEVER toValue() here: the element type is itself
522
+ // a function, so toValue(fetcher) would *invoke the fetcher at setup*
523
+ // (spurious request) and toValue(getter) would do the same. isRef narrows
524
+ // to the only unambiguous reactive form: ref(fetcher) / computed(() =>
525
+ // fetcher) / shallowRef(fetcher) — a ComputedRef IS a Ref.
526
+ // F3 elision point — the ONE explicit narrowing cast: after the isRef
527
+ // guard the else arm is `F | (() => F)`, and the bare-getter arm's return
528
+ // `F` (a function) is not assignable to `F` (TS2322). No runtime
529
+ // discriminant distinguishes a plain fetcher from a bare getter (both are
530
+ // functions), so the cast encodes exactly the documented F3 ambiguity and
531
+ // adds no unsafety beyond F3.
532
+ current: vue.isRef(fetcher) ? fetcher.value : fetcher
533
+ };
534
+ if (vue.isRef(fetcher)) {
535
+ vue.watch(
536
+ fetcher,
537
+ (next) => {
538
+ holder.current = next;
539
+ },
540
+ { flush: "sync" }
541
+ );
542
+ }
543
+ const resource = core.createPaginatedResource((query) => holder.current(query), {
498
544
  pageSize: options.pageSize,
499
545
  mode: options.mode
500
546
  });
@@ -530,10 +576,14 @@ function usePaginatedResource(fetcher, options = {}) {
530
576
  };
531
577
  }
532
578
  function useResourceController(config) {
533
- const controller = core.createResourceController(config);
579
+ const controller = core.createResourceController({ ...config, immediate: false });
580
+ const immediate = config.immediate !== false;
581
+ if (immediate) {
582
+ vue.onMounted(() => void controller.load());
583
+ }
584
+ vue.onScopeDispose(() => controller.destroy());
534
585
  const state = vue.shallowRef(controller.getState());
535
- vue.onBeforeUnmount(controller.subscribe((next) => state.value = next));
536
- vue.onBeforeUnmount(() => controller.destroy());
586
+ vue.onScopeDispose(controller.subscribe((next) => state.value = next));
537
587
  return { ...controller, state };
538
588
  }
539
589
  function useDataSource(config) {
@@ -2484,7 +2534,9 @@ var IrisAdminTabs = vue.defineComponent({
2484
2534
  onClick: (e) => {
2485
2535
  e.stopPropagation();
2486
2536
  close(tab.key);
2487
- const root = e.currentTarget.closest('[role="tablist"]');
2537
+ const root = e.currentTarget.closest(
2538
+ '[role="tablist"]'
2539
+ );
2488
2540
  void vue.nextTick(() => focusTab(root, props.nav.getState().activeKey));
2489
2541
  }
2490
2542
  },
@@ -6406,12 +6458,13 @@ var IrisList = vue.defineComponent({
6406
6458
  "data-iris-list-index": index,
6407
6459
  "data-iris-list-item": "",
6408
6460
  "data-state": selected ? "selected" : active ? "active" : "idle",
6461
+ "data-hovered": hoveredIndex.value === index ? "true" : "false",
6409
6462
  onClick: item.disabled ? void 0 : onClick,
6410
6463
  onFocus,
6411
- onMouseEnter: () => {
6464
+ onMouseenter: () => {
6412
6465
  hoveredIndex.value = index;
6413
6466
  },
6414
- onMouseLeave: () => {
6467
+ onMouseleave: () => {
6415
6468
  if (hoveredIndex.value === index) hoveredIndex.value = -1;
6416
6469
  },
6417
6470
  style: baseStyle