@iris-ui-kit/vue 0.2.21 → 0.2.23
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.
- package/dist/admin.cjs +14 -5
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.js +2 -2
- package/dist/async.cjs +48 -2
- package/dist/async.cjs.map +1 -1
- package/dist/async.d.cts +27 -3
- package/dist/async.d.ts +27 -3
- package/dist/async.js +1 -1
- package/dist/behaviors.cjs +87 -48
- package/dist/behaviors.cjs.map +1 -1
- package/dist/behaviors.d.cts +2 -2
- package/dist/behaviors.d.ts +2 -2
- package/dist/behaviors.js +1 -1
- package/dist/chunk-25NYWSXP.js +20 -0
- package/dist/chunk-25NYWSXP.js.map +1 -0
- package/dist/{chunk-CWXH44OF.js → chunk-3IH7IJ5S.js} +90 -51
- package/dist/chunk-3IH7IJ5S.js.map +1 -0
- package/dist/{chunk-ENKE2BPC.js → chunk-BEPH6PPL.js} +23 -5
- package/dist/chunk-BEPH6PPL.js.map +1 -0
- package/dist/{chunk-FG5USQSY.js → chunk-I7PR4ILF.js} +8 -3
- package/dist/chunk-I7PR4ILF.js.map +1 -0
- package/dist/{chunk-4FLIW67H.js → chunk-IAG64CHL.js} +21 -28
- package/dist/chunk-IAG64CHL.js.map +1 -0
- package/dist/chunk-NNOF7KUH.js +24 -0
- package/dist/chunk-NNOF7KUH.js.map +1 -0
- package/dist/{chunk-4WQOZ2OV.js → chunk-QQ25RKOO.js} +6 -4
- package/dist/chunk-QQ25RKOO.js.map +1 -0
- package/dist/chunk-SJB5DIIY.js +119 -0
- package/dist/chunk-SJB5DIIY.js.map +1 -0
- package/dist/form.cjs +28 -23
- package/dist/form.cjs.map +1 -1
- package/dist/form.d.cts +3 -2
- package/dist/form.d.ts +3 -2
- package/dist/form.js +2 -1
- package/dist/index.cjs +216 -91
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +29 -18
- package/dist/index.js.map +1 -1
- package/dist/machine.cjs +11 -4
- package/dist/machine.cjs.map +1 -1
- package/dist/machine.d.cts +12 -3
- package/dist/machine.d.ts +12 -3
- package/dist/machine.js +1 -1
- package/dist/resource.cjs +7 -3
- package/dist/resource.cjs.map +1 -1
- package/dist/resource.d.cts +10 -1
- package/dist/resource.d.ts +10 -1
- package/dist/resource.js +1 -1
- package/dist/skeletons.cjs +21 -3
- package/dist/skeletons.cjs.map +1 -1
- package/dist/skeletons.d.cts +21 -0
- package/dist/skeletons.d.ts +21 -0
- package/dist/skeletons.js +1 -1
- package/dist/undo.cjs +6 -1
- package/dist/undo.cjs.map +1 -1
- package/dist/undo.d.cts +5 -0
- package/dist/undo.d.ts +5 -0
- package/dist/undo.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-4FLIW67H.js.map +0 -1
- package/dist/chunk-4WQOZ2OV.js.map +0 -1
- package/dist/chunk-CWXH44OF.js.map +0 -1
- package/dist/chunk-ENKE2BPC.js.map +0 -1
- package/dist/chunk-FG5USQSY.js.map +0 -1
- package/dist/chunk-TQB5LVOH.js +0 -17
- package/dist/chunk-TQB5LVOH.js.map +0 -1
- package/dist/chunk-XSLBANUV.js +0 -16
- package/dist/chunk-XSLBANUV.js.map +0 -1
- package/dist/chunk-ZY4NLITM.js +0 -73
- 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":"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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 { 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
|
|
58
|
-
* on each store change,
|
|
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
|
|
58
|
-
* on each store change,
|
|
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-
|
|
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.
|
|
235
|
-
|
|
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 =
|
|
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
|
|
332
|
-
const
|
|
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
|
|
338
|
-
dirty
|
|
342
|
+
touched,
|
|
343
|
+
dirty,
|
|
339
344
|
setValue: (next) => form.setFieldValue(name, next),
|
|
340
|
-
setTouched: (
|
|
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
|
|
352
|
-
const
|
|
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
|
|
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(
|
|
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
|
|
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.
|
|
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(
|
|
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
|
},
|
|
@@ -3037,12 +3089,17 @@ function useUndoStack(options) {
|
|
|
3037
3089
|
index: raw.index
|
|
3038
3090
|
});
|
|
3039
3091
|
const sync = () => {
|
|
3040
|
-
|
|
3092
|
+
const next = {
|
|
3041
3093
|
canUndo: raw.canUndo(),
|
|
3042
3094
|
canRedo: raw.canRedo(),
|
|
3043
3095
|
depth: raw.depth,
|
|
3044
3096
|
index: raw.index
|
|
3045
3097
|
};
|
|
3098
|
+
const cur = state.value;
|
|
3099
|
+
if (next.canUndo === cur.canUndo && next.canRedo === cur.canRedo && next.depth === cur.depth && next.index === cur.index) {
|
|
3100
|
+
return;
|
|
3101
|
+
}
|
|
3102
|
+
state.value = next;
|
|
3046
3103
|
};
|
|
3047
3104
|
const stack = trackUndoStack(raw, sync);
|
|
3048
3105
|
const push = (snapshot) => stack.push(snapshot);
|
|
@@ -6293,7 +6350,10 @@ var IrisList = vue.defineComponent({
|
|
|
6293
6350
|
const { state, isContent, stateKey, stateProps } = useDataState(() => ({
|
|
6294
6351
|
loading: props.loading,
|
|
6295
6352
|
error: props.error,
|
|
6296
|
-
empty: props.items.length === 0
|
|
6353
|
+
empty: props.items.length === 0,
|
|
6354
|
+
// Already-loaded items stay mounted during a revalidate (SWR): a load
|
|
6355
|
+
// in flight no longer replaces them with the loading/error state.
|
|
6356
|
+
hasContent: props.items.length > 0
|
|
6297
6357
|
}));
|
|
6298
6358
|
const isEnabled = (i) => !props.items[i]?.disabled;
|
|
6299
6359
|
const nav = core.createKeyboardNav({
|
|
@@ -6406,12 +6466,13 @@ var IrisList = vue.defineComponent({
|
|
|
6406
6466
|
"data-iris-list-index": index,
|
|
6407
6467
|
"data-iris-list-item": "",
|
|
6408
6468
|
"data-state": selected ? "selected" : active ? "active" : "idle",
|
|
6469
|
+
"data-hovered": hoveredIndex.value === index ? "true" : "false",
|
|
6409
6470
|
onClick: item.disabled ? void 0 : onClick,
|
|
6410
6471
|
onFocus,
|
|
6411
|
-
|
|
6472
|
+
onMouseenter: () => {
|
|
6412
6473
|
hoveredIndex.value = index;
|
|
6413
6474
|
},
|
|
6414
|
-
|
|
6475
|
+
onMouseleave: () => {
|
|
6415
6476
|
if (hoveredIndex.value === index) hoveredIndex.value = -1;
|
|
6416
6477
|
},
|
|
6417
6478
|
style: baseStyle
|
|
@@ -6429,7 +6490,9 @@ var IrisList = vue.defineComponent({
|
|
|
6429
6490
|
role: "listbox",
|
|
6430
6491
|
"aria-label": props.ariaLabel,
|
|
6431
6492
|
"aria-multiselectable": props.multi ? "true" : void 0,
|
|
6432
|
-
|
|
6493
|
+
// Decoupled from resolved state: signals both the initial load and
|
|
6494
|
+
// an in-flight background revalidate (content stays mounted).
|
|
6495
|
+
"aria-busy": props.loading ? "true" : void 0,
|
|
6433
6496
|
"data-iris-list": "",
|
|
6434
6497
|
onKeydown: onKeyDown,
|
|
6435
6498
|
style: {
|
|
@@ -12006,7 +12069,10 @@ var IrisTree = vue.defineComponent({
|
|
|
12006
12069
|
const { state, isContent, stateKey, stateProps } = useDataState(() => ({
|
|
12007
12070
|
loading: props.loading,
|
|
12008
12071
|
error: props.error,
|
|
12009
|
-
empty: props.nodes.length === 0
|
|
12072
|
+
empty: props.nodes.length === 0,
|
|
12073
|
+
// Already-loaded nodes stay mounted during a revalidate (SWR): a load
|
|
12074
|
+
// in flight no longer replaces them with the loading/error state.
|
|
12075
|
+
hasContent: props.nodes.length > 0
|
|
12010
12076
|
}));
|
|
12011
12077
|
const lazyCache = vue.ref(/* @__PURE__ */ new Map());
|
|
12012
12078
|
const loadingIds = vue.ref(/* @__PURE__ */ new Set());
|
|
@@ -12326,7 +12392,9 @@ var IrisTree = vue.defineComponent({
|
|
|
12326
12392
|
role: "tree",
|
|
12327
12393
|
"aria-label": props.ariaLabel ?? t("tree.label"),
|
|
12328
12394
|
"aria-multiselectable": props.selectionMode === "multi" ? "true" : void 0,
|
|
12329
|
-
|
|
12395
|
+
// Decoupled from resolved state: signals both the initial load and
|
|
12396
|
+
// an in-flight background revalidate (content stays mounted).
|
|
12397
|
+
"aria-busy": props.loading ? "true" : void 0,
|
|
12330
12398
|
"data-iris-tree": "",
|
|
12331
12399
|
style: {
|
|
12332
12400
|
display: "flex",
|
|
@@ -18386,14 +18454,32 @@ var IrisDashboardTemplate = vue.defineComponent({
|
|
|
18386
18454
|
activeId: { type: String, default: "" },
|
|
18387
18455
|
/** Cards to render in the main grid. Skip to use the `default` slot only. */
|
|
18388
18456
|
cards: { type: Array, default: () => [] },
|
|
18389
|
-
defaultCollapsed: { type: Boolean, default: false }
|
|
18457
|
+
defaultCollapsed: { type: Boolean, default: false },
|
|
18458
|
+
/**
|
|
18459
|
+
* Controlled collapsed state. When unset (`undefined`), the component
|
|
18460
|
+
* manages its own state seeded from `defaultCollapsed`; when set, this
|
|
18461
|
+
* value takes precedence and changes are re-emitted via
|
|
18462
|
+
* `update:collapsed` (`v-model:collapsed`).
|
|
18463
|
+
*/
|
|
18464
|
+
collapsed: { type: Boolean, default: void 0 }
|
|
18390
18465
|
},
|
|
18391
18466
|
emits: {
|
|
18392
18467
|
"update:activeId": (_id) => true,
|
|
18393
18468
|
"update:collapsed": (_value) => true
|
|
18394
18469
|
},
|
|
18395
18470
|
setup(props, { attrs, slots, emit }) {
|
|
18396
|
-
const
|
|
18471
|
+
const isControlled = vue.computed(() => props.collapsed !== void 0);
|
|
18472
|
+
const internalCollapsed = vue.ref(props.defaultCollapsed);
|
|
18473
|
+
const collapsed = vue.computed(
|
|
18474
|
+
() => isControlled.value ? Boolean(props.collapsed) : internalCollapsed.value
|
|
18475
|
+
);
|
|
18476
|
+
vue.watch(
|
|
18477
|
+
() => props.collapsed,
|
|
18478
|
+
(value) => {
|
|
18479
|
+
if (value !== void 0) internalCollapsed.value = value;
|
|
18480
|
+
},
|
|
18481
|
+
{ immediate: true }
|
|
18482
|
+
);
|
|
18397
18483
|
const onSelectNav = (id) => {
|
|
18398
18484
|
emit("update:activeId", id);
|
|
18399
18485
|
};
|
|
@@ -18415,7 +18501,7 @@ var IrisDashboardTemplate = vue.defineComponent({
|
|
|
18415
18501
|
{
|
|
18416
18502
|
collapsed: collapsed.value,
|
|
18417
18503
|
"onUpdate:collapsed": (v) => {
|
|
18418
|
-
|
|
18504
|
+
if (!isControlled.value) internalCollapsed.value = v;
|
|
18419
18505
|
emit("update:collapsed", v);
|
|
18420
18506
|
},
|
|
18421
18507
|
width: 240,
|
|
@@ -18602,6 +18688,72 @@ function handlePosition2(handle) {
|
|
|
18602
18688
|
s.cursor = HANDLE_CURSORS2[handle];
|
|
18603
18689
|
return s;
|
|
18604
18690
|
}
|
|
18691
|
+
var ResizableHandle = vue.defineComponent({
|
|
18692
|
+
name: "ResizableHandle",
|
|
18693
|
+
props: {
|
|
18694
|
+
handle: { type: String, required: true },
|
|
18695
|
+
disabled: { type: Boolean, default: false },
|
|
18696
|
+
keepAspect: { type: Boolean, default: false },
|
|
18697
|
+
minWidth: { type: Number, default: 40 },
|
|
18698
|
+
minHeight: { type: Number, default: 40 },
|
|
18699
|
+
maxWidth: { type: Number, default: Infinity },
|
|
18700
|
+
maxHeight: { type: Number, default: Infinity },
|
|
18701
|
+
/** Stable computed ref from the parent; read only (never mutated). */
|
|
18702
|
+
sizeRef: { type: Object, required: true },
|
|
18703
|
+
/** Stable setup-level callbacks from the parent. */
|
|
18704
|
+
onUpdate: { type: Function, required: true },
|
|
18705
|
+
onResizeStart: {
|
|
18706
|
+
type: Function,
|
|
18707
|
+
default: void 0
|
|
18708
|
+
},
|
|
18709
|
+
onResizeEnd: { type: Function, default: void 0 }
|
|
18710
|
+
},
|
|
18711
|
+
setup(props) {
|
|
18712
|
+
const handleRef = vue.ref(null);
|
|
18713
|
+
let startSize = { width: 0, height: 0 };
|
|
18714
|
+
let aspect = 1;
|
|
18715
|
+
useDrag({
|
|
18716
|
+
handle: handleRef,
|
|
18717
|
+
disabled: vue.computed(() => props.disabled),
|
|
18718
|
+
onStart: () => {
|
|
18719
|
+
startSize = { ...props.sizeRef.value };
|
|
18720
|
+
aspect = startSize.width / Math.max(1, startSize.height);
|
|
18721
|
+
props.onResizeStart?.(startSize);
|
|
18722
|
+
},
|
|
18723
|
+
onDrag: ({ dx, dy }) => {
|
|
18724
|
+
const t = props.handle.includes("top");
|
|
18725
|
+
const b = props.handle.includes("bottom");
|
|
18726
|
+
const l = props.handle.includes("left");
|
|
18727
|
+
const r = props.handle.includes("right");
|
|
18728
|
+
let nextW = startSize.width;
|
|
18729
|
+
let nextH = startSize.height;
|
|
18730
|
+
if (r) nextW = startSize.width + dx;
|
|
18731
|
+
if (l) nextW = startSize.width - dx;
|
|
18732
|
+
if (b) nextH = startSize.height + dy;
|
|
18733
|
+
if (t) nextH = startSize.height - dy;
|
|
18734
|
+
if (props.keepAspect && (t || b) && (l || r)) {
|
|
18735
|
+
nextH = nextW / aspect;
|
|
18736
|
+
}
|
|
18737
|
+
nextW = Math.max(props.minWidth, Math.min(props.maxWidth, nextW));
|
|
18738
|
+
nextH = Math.max(props.minHeight, Math.min(props.maxHeight, nextH));
|
|
18739
|
+
props.onUpdate({ width: nextW, height: nextH });
|
|
18740
|
+
},
|
|
18741
|
+
onEnd: () => props.onResizeEnd?.()
|
|
18742
|
+
});
|
|
18743
|
+
return () => vue.h("div", {
|
|
18744
|
+
ref: (el) => {
|
|
18745
|
+
handleRef.value = el ?? null;
|
|
18746
|
+
},
|
|
18747
|
+
"data-iris-resizable-handle": props.handle,
|
|
18748
|
+
style: {
|
|
18749
|
+
...handlePosition2(props.handle),
|
|
18750
|
+
touchAction: "none",
|
|
18751
|
+
background: "transparent",
|
|
18752
|
+
zIndex: "1"
|
|
18753
|
+
}
|
|
18754
|
+
});
|
|
18755
|
+
}
|
|
18756
|
+
});
|
|
18605
18757
|
var IrisResizable = vue.defineComponent({
|
|
18606
18758
|
name: "IrisResizable",
|
|
18607
18759
|
inheritAttrs: false,
|
|
@@ -18634,53 +18786,8 @@ var IrisResizable = vue.defineComponent({
|
|
|
18634
18786
|
if (!isControlled.value) internal.value = next;
|
|
18635
18787
|
emit("update:size", next);
|
|
18636
18788
|
};
|
|
18637
|
-
const
|
|
18638
|
-
|
|
18639
|
-
let startSize = { width: 0, height: 0 };
|
|
18640
|
-
let aspect = 1;
|
|
18641
|
-
useDrag({
|
|
18642
|
-
handle: handleRef,
|
|
18643
|
-
disabled: vue.computed(() => props.disabled),
|
|
18644
|
-
onStart: () => {
|
|
18645
|
-
startSize = { ...size.value };
|
|
18646
|
-
aspect = startSize.width / Math.max(1, startSize.height);
|
|
18647
|
-
emit("resizeStart", startSize);
|
|
18648
|
-
},
|
|
18649
|
-
onDrag: ({ dx, dy }) => {
|
|
18650
|
-
const t = handle.includes("top");
|
|
18651
|
-
const b = handle.includes("bottom");
|
|
18652
|
-
const l = handle.includes("left");
|
|
18653
|
-
const r = handle.includes("right");
|
|
18654
|
-
let nextW = startSize.width;
|
|
18655
|
-
let nextH = startSize.height;
|
|
18656
|
-
if (r) nextW = startSize.width + dx;
|
|
18657
|
-
if (l) nextW = startSize.width - dx;
|
|
18658
|
-
if (b) nextH = startSize.height + dy;
|
|
18659
|
-
if (t) nextH = startSize.height - dy;
|
|
18660
|
-
if (props.keepAspect && (t || b) && (l || r)) {
|
|
18661
|
-
nextH = nextW / aspect;
|
|
18662
|
-
}
|
|
18663
|
-
nextW = Math.max(props.minWidth, Math.min(props.maxWidth, nextW));
|
|
18664
|
-
nextH = Math.max(props.minHeight, Math.min(props.maxHeight, nextH));
|
|
18665
|
-
setSize({ width: nextW, height: nextH });
|
|
18666
|
-
},
|
|
18667
|
-
onEnd: () => {
|
|
18668
|
-
emit("resizeEnd", size.value);
|
|
18669
|
-
}
|
|
18670
|
-
});
|
|
18671
|
-
return vue.h("div", {
|
|
18672
|
-
ref: (el) => {
|
|
18673
|
-
handleRef.value = el ?? null;
|
|
18674
|
-
},
|
|
18675
|
-
"data-iris-resizable-handle": handle,
|
|
18676
|
-
style: {
|
|
18677
|
-
...handlePosition2(handle),
|
|
18678
|
-
touchAction: "none",
|
|
18679
|
-
background: "transparent",
|
|
18680
|
-
zIndex: "1"
|
|
18681
|
-
}
|
|
18682
|
-
});
|
|
18683
|
-
};
|
|
18789
|
+
const emitResizeStart = (s) => emit("resizeStart", s);
|
|
18790
|
+
const emitResizeEnd = () => emit("resizeEnd", size.value);
|
|
18684
18791
|
return () => vue.h(
|
|
18685
18792
|
"div",
|
|
18686
18793
|
{
|
|
@@ -18695,7 +18802,25 @@ var IrisResizable = vue.defineComponent({
|
|
|
18695
18802
|
...attrs.style ?? {}
|
|
18696
18803
|
}
|
|
18697
18804
|
},
|
|
18698
|
-
[
|
|
18805
|
+
[
|
|
18806
|
+
slots.default?.(),
|
|
18807
|
+
...props.handles.map(
|
|
18808
|
+
(handle) => vue.h(ResizableHandle, {
|
|
18809
|
+
key: handle,
|
|
18810
|
+
handle,
|
|
18811
|
+
disabled: props.disabled,
|
|
18812
|
+
keepAspect: props.keepAspect,
|
|
18813
|
+
minWidth: props.minWidth,
|
|
18814
|
+
minHeight: props.minHeight,
|
|
18815
|
+
maxWidth: props.maxWidth,
|
|
18816
|
+
maxHeight: props.maxHeight,
|
|
18817
|
+
sizeRef: size,
|
|
18818
|
+
onUpdate: setSize,
|
|
18819
|
+
onResizeStart: emitResizeStart,
|
|
18820
|
+
onResizeEnd: emitResizeEnd
|
|
18821
|
+
})
|
|
18822
|
+
)
|
|
18823
|
+
]
|
|
18699
18824
|
);
|
|
18700
18825
|
}
|
|
18701
18826
|
});
|