@sfxcode/nuxt-ui-formkit 1.2.2 → 1.2.4

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 (40) hide show
  1. package/README.md +7 -0
  2. package/dist/module.json +1 -1
  3. package/dist/runtime/components/FUAutoFormOverlay.d.vue.ts +82 -0
  4. package/dist/runtime/components/FUAutoFormOverlay.vue +106 -0
  5. package/dist/runtime/components/FUAutoFormOverlay.vue.d.ts +82 -0
  6. package/dist/runtime/components/FUDataEdit.d.vue.ts +10 -0
  7. package/dist/runtime/components/FUDataEdit.vue +15 -3
  8. package/dist/runtime/components/FUDataEdit.vue.d.ts +10 -0
  9. package/dist/runtime/components/FUDataEditOverlay.d.vue.ts +64 -0
  10. package/dist/runtime/components/FUDataEditOverlay.vue +94 -0
  11. package/dist/runtime/components/FUDataEditOverlay.vue.d.ts +64 -0
  12. package/dist/runtime/components/inputs/FUCalendar.vue +3 -0
  13. package/dist/runtime/components/inputs/FUCheckbox.vue +2 -1
  14. package/dist/runtime/components/inputs/FUCheckboxGroup.vue +3 -0
  15. package/dist/runtime/components/inputs/FUEditor.vue +58 -54
  16. package/dist/runtime/components/inputs/FUFileUpload.vue +2 -1
  17. package/dist/runtime/components/inputs/FUInput.vue +2 -1
  18. package/dist/runtime/components/inputs/FUInputDate.vue +5 -1
  19. package/dist/runtime/components/inputs/FUInputMenu.vue +2 -1
  20. package/dist/runtime/components/inputs/FUInputNumber.vue +2 -1
  21. package/dist/runtime/components/inputs/FUInputTags.vue +2 -1
  22. package/dist/runtime/components/inputs/FUInputTime.vue +5 -1
  23. package/dist/runtime/components/inputs/FUListbox.vue +4 -0
  24. package/dist/runtime/components/inputs/FUPinInput.vue +8 -1
  25. package/dist/runtime/components/inputs/FURadioGroup.vue +3 -0
  26. package/dist/runtime/components/inputs/FUSwitch.vue +2 -1
  27. package/dist/runtime/components/inputs/FUTextarea.vue +2 -1
  28. package/dist/runtime/composables/useFormKitForm.d.ts +5 -1
  29. package/dist/runtime/composables/useFormKitForm.js +9 -3
  30. package/dist/runtime/composables/useFormKitOverlay.d.ts +20 -0
  31. package/dist/runtime/composables/useFormKitOverlay.js +42 -0
  32. package/dist/runtime/composables/useFormKitStandardSchema.d.ts +20 -0
  33. package/dist/runtime/composables/useFormKitStandardSchema.js +68 -0
  34. package/dist/runtime/utils/standardSchemaErrors.d.ts +14 -0
  35. package/dist/runtime/utils/standardSchemaErrors.js +15 -0
  36. package/dist/runtime/utils/useFormKitContainerBlur.d.ts +37 -0
  37. package/dist/runtime/utils/useFormKitContainerBlur.js +9 -0
  38. package/dist/runtime/utils/useOverlayCloseResolution.d.ts +20 -0
  39. package/dist/runtime/utils/useOverlayCloseResolution.js +17 -0
  40. package/package.json +2 -1
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import { useFormKitInput } from "../../utils/useFormKitInput";
3
+ import { createContainerBlurHandler } from "../../utils/useFormKitContainerBlur";
3
4
  const props = defineProps({
4
5
  context: {
5
6
  type: Object,
@@ -7,6 +8,7 @@ const props = defineProps({
7
8
  }
8
9
  });
9
10
  const { handleInput, handleChange, styleClass, color, modelValue, items, validSlotNames } = useFormKitInput(props.context);
11
+ const handleContainerBlur = createContainerBlurHandler(props.context);
10
12
  </script>
11
13
 
12
14
  <template>
@@ -31,6 +33,7 @@ const { handleInput, handleChange, styleClass, color, modelValue, items, validSl
31
33
  :name="context.name"
32
34
  @change="handleChange"
33
35
  @update:model-value="handleInput"
36
+ @focusout="handleContainerBlur"
34
37
  >
35
38
  <template
36
39
  v-for="slotName in validSlotNames"
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import { useFormKitInput } from "../../utils/useFormKitInput";
3
+ import { createContainerBlurHandler } from "../../utils/useFormKitContainerBlur";
3
4
  const DEFAULT_EDITOR_TOOLBAR_ITEMS = [
4
5
  [
5
6
  { kind: "undo", icon: "i-lucide-undo", tooltip: { text: "Undo" } },
@@ -61,61 +62,64 @@ const props = defineProps({
61
62
  }
62
63
  });
63
64
  const { handleInput, styleClass, modelValue } = useFormKitInput(props.context);
65
+ const handleContainerBlur = createContainerBlurHandler(props.context);
64
66
  </script>
65
67
 
66
68
  <template>
67
- <UEditor
68
- :id="context.id"
69
- v-model="modelValue"
70
- v-bind="{ ...context?.attrs }"
71
- :class="styleClass"
72
- :editable="!context?.disabled"
73
- :style="context?.attrs.style"
74
- :content-type="context.contentType"
75
- :starter-kit="context.starterKit"
76
- :placeholder="context.placeholder"
77
- :markdown="context.markdown"
78
- :image="context.image"
79
- :mention="context.mention"
80
- :handlers="context.editorHandlers"
81
- :extensions="context.extensions"
82
- :autofocus="context.autofocus"
83
- :ui="context.ui"
84
- @update:model-value="handleInput"
85
- >
86
- <template #default="{ editor, handlers }">
87
- <UEditorToolbar
88
- v-if="context.toolbar !== false"
89
- :editor="editor"
90
- :items="context.toolbarItems ?? DEFAULT_EDITOR_TOOLBAR_ITEMS"
91
- class="border-b border-default px-2 py-1 mb-2 flex-wrap"
92
- />
93
- <UEditorToolbar
94
- v-if="context.bubbleToolbar !== false"
95
- :editor="editor"
96
- :items="context.bubbleToolbarItems ?? DEFAULT_BUBBLE_TOOLBAR_ITEMS"
97
- layout="bubble"
98
- :should-show="bubbleToolbarShouldShow"
99
- />
100
- <UEditorDragHandle
101
- v-if="context.dragHandle"
102
- :editor="editor"
103
- />
104
- <UEditorSuggestionMenu
105
- v-if="context.suggestionMenu"
106
- :editor="editor"
107
- :items="context.suggestionMenuItems ?? DEFAULT_SUGGESTION_MENU_ITEMS"
108
- />
109
- <UEditorMentionMenu
110
- v-if="context.mentionItems?.length"
111
- :editor="editor"
112
- :items="context.mentionItems"
113
- />
114
- <component
115
- :is="context.slots.default"
116
- v-if="context?.slots?.default"
117
- v-bind="{ ...context, editor, handlers }"
118
- />
119
- </template>
120
- </UEditor>
69
+ <div @focusout="handleContainerBlur">
70
+ <UEditor
71
+ :id="context.id"
72
+ v-model="modelValue"
73
+ v-bind="{ ...context?.attrs }"
74
+ :class="styleClass"
75
+ :editable="!context?.disabled"
76
+ :style="context?.attrs.style"
77
+ :content-type="context.contentType"
78
+ :starter-kit="context.starterKit"
79
+ :placeholder="context.placeholder"
80
+ :markdown="context.markdown"
81
+ :image="context.image"
82
+ :mention="context.mention"
83
+ :handlers="context.editorHandlers"
84
+ :extensions="context.extensions"
85
+ :autofocus="context.autofocus"
86
+ :ui="context.ui"
87
+ @update:model-value="handleInput"
88
+ >
89
+ <template #default="{ editor, handlers }">
90
+ <UEditorToolbar
91
+ v-if="context.toolbar !== false"
92
+ :editor="editor"
93
+ :items="context.toolbarItems ?? DEFAULT_EDITOR_TOOLBAR_ITEMS"
94
+ class="border-b border-default px-2 py-1 mb-2 flex-wrap"
95
+ />
96
+ <UEditorToolbar
97
+ v-if="context.bubbleToolbar !== false"
98
+ :editor="editor"
99
+ :items="context.bubbleToolbarItems ?? DEFAULT_BUBBLE_TOOLBAR_ITEMS"
100
+ layout="bubble"
101
+ :should-show="bubbleToolbarShouldShow"
102
+ />
103
+ <UEditorDragHandle
104
+ v-if="context.dragHandle"
105
+ :editor="editor"
106
+ />
107
+ <UEditorSuggestionMenu
108
+ v-if="context.suggestionMenu"
109
+ :editor="editor"
110
+ :items="context.suggestionMenuItems ?? DEFAULT_SUGGESTION_MENU_ITEMS"
111
+ />
112
+ <UEditorMentionMenu
113
+ v-if="context.mentionItems?.length"
114
+ :editor="editor"
115
+ :items="context.mentionItems"
116
+ />
117
+ <component
118
+ :is="context.slots.default"
119
+ v-if="context?.slots?.default"
120
+ v-bind="{ ...context, editor, handlers }"
121
+ />
122
+ </template>
123
+ </UEditor>
124
+ </div>
121
125
  </template>
@@ -6,7 +6,7 @@ const props = defineProps({
6
6
  required: true
7
7
  }
8
8
  });
9
- const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
9
+ const { handleInput, handleChange, handleBlur, isInvalid, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
10
10
  </script>
11
11
 
12
12
  <template>
@@ -41,6 +41,7 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, val
41
41
  :ui="context.ui"
42
42
  @change="handleChange"
43
43
  @update:model-value="handleInput"
44
+ @blur="handleBlur"
44
45
  >
45
46
  <template
46
47
  v-for="slotName in validSlotNames"
@@ -6,7 +6,7 @@ const props = defineProps({
6
6
  required: true
7
7
  }
8
8
  });
9
- const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
9
+ const { handleInput, handleChange, handleBlur, isInvalid, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
10
10
  </script>
11
11
 
12
12
  <template>
@@ -46,6 +46,7 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, val
46
46
  :ui="context.ui"
47
47
  @change="handleChange"
48
48
  @update:model-value="handleInput"
49
+ @blur="handleBlur"
49
50
  >
50
51
  <template
51
52
  v-for="slotName in validSlotNames"
@@ -1,6 +1,7 @@
1
1
  <script setup>
2
2
  import { computed } from "vue";
3
3
  import { useFormKitInput } from "../../utils/useFormKitInput";
4
+ import { createContainerBlurHandler } from "../../utils/useFormKitContainerBlur";
4
5
  import { fromDateValueOrRange, toDateValue, toDateValueOrRange } from "../../utils/dateValueConversion";
5
6
  const props = defineProps({
6
7
  context: {
@@ -8,7 +9,8 @@ const props = defineProps({
8
9
  required: true
9
10
  }
10
11
  });
11
- const { handleInput, handleChange, isInvalid, styleClass, color, validSlotNames } = useFormKitInput(props.context);
12
+ const { handleInput, handleChange, handleBlur, isInvalid, styleClass, color, validSlotNames } = useFormKitInput(props.context);
13
+ const handleContainerBlur = createContainerBlurHandler(props.context);
12
14
  const conversionOptions = computed(() => ({
13
15
  granularity: props.context.granularity,
14
16
  hideTimeZone: props.context.hideTimeZone,
@@ -66,6 +68,8 @@ const minValue = computed(() => toDateValue(props.context.minValue, conversionOp
66
68
  :ui="context.ui"
67
69
  @change="handleChange"
68
70
  @update:model-value="handleInput"
71
+ @blur="handleBlur"
72
+ @focusout="handleContainerBlur"
69
73
  >
70
74
  <template
71
75
  v-for="slotName in validSlotNames"
@@ -6,7 +6,7 @@ const props = defineProps({
6
6
  required: true
7
7
  }
8
8
  });
9
- const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, items, validSlotNames } = useFormKitInput(props.context);
9
+ const { handleInput, handleChange, handleBlur, isInvalid, styleClass, color, modelValue, items, validSlotNames } = useFormKitInput(props.context);
10
10
  </script>
11
11
 
12
12
  <template>
@@ -65,6 +65,7 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, ite
65
65
  :ui="context.ui"
66
66
  @change="handleChange"
67
67
  @update:model-value="handleInput"
68
+ @blur="handleBlur"
68
69
  >
69
70
  <template
70
71
  v-for="slotName in validSlotNames"
@@ -6,7 +6,7 @@ const props = defineProps({
6
6
  required: true
7
7
  }
8
8
  });
9
- const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
9
+ const { handleInput, handleChange, handleBlur, isInvalid, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
10
10
  </script>
11
11
 
12
12
  <template>
@@ -47,6 +47,7 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, val
47
47
  :ui="context.ui"
48
48
  @change="handleChange"
49
49
  @update:model-value="handleInput"
50
+ @blur="handleBlur"
50
51
  >
51
52
  <template
52
53
  v-for="slotName in validSlotNames"
@@ -6,7 +6,7 @@ const props = defineProps({
6
6
  required: true
7
7
  }
8
8
  });
9
- const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
9
+ const { handleInput, handleChange, handleBlur, isInvalid, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
10
10
  </script>
11
11
 
12
12
  <template>
@@ -49,6 +49,7 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, val
49
49
  :ui="context.ui"
50
50
  @change="handleChange"
51
51
  @update:model-value="handleInput"
52
+ @blur="handleBlur"
52
53
  >
53
54
  <template
54
55
  v-for="slotName in validSlotNames"
@@ -1,12 +1,14 @@
1
1
  <script setup>
2
2
  import { useFormKitInput } from "../../utils/useFormKitInput";
3
+ import { createContainerBlurHandler } from "../../utils/useFormKitContainerBlur";
3
4
  const props = defineProps({
4
5
  context: {
5
6
  type: Object,
6
7
  required: true
7
8
  }
8
9
  });
9
- const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
10
+ const { handleInput, handleChange, handleBlur, isInvalid, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
11
+ const handleContainerBlur = createContainerBlurHandler(props.context);
10
12
  </script>
11
13
 
12
14
  <template>
@@ -46,6 +48,8 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, val
46
48
  :ui="context.ui"
47
49
  @change="handleChange"
48
50
  @update:model-value="handleInput"
51
+ @blur="handleBlur"
52
+ @focusout="handleContainerBlur"
49
53
  >
50
54
  <template
51
55
  v-for="slotName in validSlotNames"
@@ -1,6 +1,7 @@
1
1
  <script setup>
2
2
  import { computed, nextTick, ref, watch } from "vue";
3
3
  import { useFormKitInput } from "../../utils/useFormKitInput";
4
+ import { createContainerBlurHandler } from "../../utils/useFormKitContainerBlur";
4
5
  const props = defineProps({
5
6
  context: {
6
7
  type: Object,
@@ -8,6 +9,7 @@ const props = defineProps({
8
9
  }
9
10
  });
10
11
  const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, items, validSlotNames } = useFormKitInput(props.context);
12
+ const handleContainerBlur = createContainerBlurHandler(props.context);
11
13
  const targetItems = ref(modelValue.value || []);
12
14
  const sourceSelection = ref([]);
13
15
  const targetSelection = ref([]);
@@ -240,6 +242,7 @@ watch(targetItems, (newVal) => {
240
242
  :ui="context.ui"
241
243
  @change="handleChange"
242
244
  @update:model-value="handleInput"
245
+ @focusout="handleContainerBlur"
243
246
  >
244
247
  <template
245
248
  v-for="slotName in validSlotNames"
@@ -255,6 +258,7 @@ watch(targetItems, (newVal) => {
255
258
  <div
256
259
  v-if="context.displayMode === 'transfer'"
257
260
  class="flex items-stretch gap-4 w-full"
261
+ @focusout="handleContainerBlur"
258
262
  >
259
263
  <div
260
264
  ref="sourceContainerRef"
@@ -1,12 +1,17 @@
1
1
  <script setup>
2
2
  import { useFormKitInput } from "../../utils/useFormKitInput";
3
+ import { createContainerBlurHandler } from "../../utils/useFormKitContainerBlur";
3
4
  const props = defineProps({
4
5
  context: {
5
6
  type: Object,
6
7
  required: true
7
8
  }
8
9
  });
9
- const { handleInput, handleChange, isInvalid, styleClass, color, modelValue } = useFormKitInput(props.context);
10
+ const { handleInput, handleChange, handleBlur, isInvalid, styleClass, color, modelValue } = useFormKitInput(props.context);
11
+ const handleContainerBlur = createContainerBlurHandler(props.context);
12
+ function handlePinBlur(event) {
13
+ handleBlur(event);
14
+ }
10
15
  </script>
11
16
 
12
17
  <template>
@@ -35,5 +40,7 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue } =
35
40
  :ui="context.ui"
36
41
  @change="handleChange"
37
42
  @update:model-value="handleInput"
43
+ @blur="handlePinBlur"
44
+ @focusout="handleContainerBlur"
38
45
  />
39
46
  </template>
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import { useFormKitInput } from "../../utils/useFormKitInput";
3
+ import { createContainerBlurHandler } from "../../utils/useFormKitContainerBlur";
3
4
  const props = defineProps({
4
5
  context: {
5
6
  type: Object,
@@ -7,6 +8,7 @@ const props = defineProps({
7
8
  }
8
9
  });
9
10
  const { handleInput, handleChange, styleClass, color, modelValue, items, validSlotNames } = useFormKitInput(props.context);
11
+ const handleContainerBlur = createContainerBlurHandler(props.context);
10
12
  </script>
11
13
 
12
14
  <template>
@@ -31,6 +33,7 @@ const { handleInput, handleChange, styleClass, color, modelValue, items, validSl
31
33
  :ui="context.ui"
32
34
  @change="handleChange"
33
35
  @update:model-value="handleInput"
36
+ @focusout="handleContainerBlur"
34
37
  >
35
38
  <template
36
39
  v-for="slotName in validSlotNames"
@@ -6,7 +6,7 @@ const props = defineProps({
6
6
  required: true
7
7
  }
8
8
  });
9
- const { handleInput, handleChange, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
9
+ const { handleInput, handleChange, handleBlur, styleClass, color, modelValue, validSlotNames } = useFormKitInput(props.context);
10
10
  </script>
11
11
 
12
12
  <template>
@@ -32,6 +32,7 @@ const { handleInput, handleChange, styleClass, color, modelValue, validSlotNames
32
32
  :ui="context.ui"
33
33
  @change="handleChange"
34
34
  @update:model-value="handleInput"
35
+ @blur="handleBlur"
35
36
  >
36
37
  <template
37
38
  v-for="slotName in validSlotNames"
@@ -6,7 +6,7 @@ const props = defineProps({
6
6
  required: true
7
7
  }
8
8
  });
9
- const { handleInput, handleChange, styleClass, color, isInvalid, modelValue, validSlotNames } = useFormKitInput(props.context);
9
+ const { handleInput, handleChange, handleBlur, styleClass, color, isInvalid, modelValue, validSlotNames } = useFormKitInput(props.context);
10
10
  </script>
11
11
 
12
12
  <template>
@@ -46,6 +46,7 @@ const { handleInput, handleChange, styleClass, color, isInvalid, modelValue, val
46
46
  :ui="context.ui"
47
47
  @change="handleChange"
48
48
  @update:model-value="handleInput"
49
+ @blur="handleBlur"
49
50
  >
50
51
  <template
51
52
  v-for="slotName in validSlotNames"
@@ -1,5 +1,9 @@
1
1
  import type { ErrorMessages } from '@formkit/core';
2
- export declare function useFormKitForm(id: string): {
2
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
3
+ export interface UseFormKitFormOptions {
4
+ standardSchema?: StandardSchemaV1;
5
+ }
6
+ export declare function useFormKitForm(id: string, options?: UseFormKitFormOptions): {
3
7
  submit: (handler?: () => unknown | Promise<unknown>) => void;
4
8
  reset: (resetTo?: unknown) => void;
5
9
  setErrors: (localErrors: ErrorMessages, childErrors?: ErrorMessages) => void;
@@ -1,8 +1,14 @@
1
1
  import { clearErrors, reset, setErrors, submitForm } from "@formkit/core";
2
2
  import { useFormKitContextById } from "@formkit/vue";
3
- import { computed, ref } from "vue";
4
- export function useFormKitForm(id) {
5
- const context = useFormKitContextById(id);
3
+ import { computed, onScopeDispose, ref } from "vue";
4
+ import { attachStandardSchema } from "./useFormKitStandardSchema.js";
5
+ export function useFormKitForm(id, options) {
6
+ let detachStandardSchema;
7
+ const context = useFormKitContextById(id, (formContext) => {
8
+ if (options?.standardSchema)
9
+ detachStandardSchema = attachStandardSchema(formContext.node, options.standardSchema);
10
+ });
11
+ onScopeDispose(() => detachStandardSchema?.());
6
12
  const isLoading = ref(false);
7
13
  const isValid = computed(() => context.value?.state.valid ?? false);
8
14
  const isSubmitted = computed(() => context.value?.state.submitted ?? false);
@@ -0,0 +1,20 @@
1
+ import type { FormKitSchemaDefinition } from '@formkit/core';
2
+ import type { AutoFormOverrides, ValibotLikeSchema, ZodLikeSchema } from './useFormKitAutoForm.js';
3
+ export interface FormKitOverlayEditOptions {
4
+ data: unknown;
5
+ schema: FormKitSchemaDefinition;
6
+ title?: string;
7
+ as?: 'modal' | 'slideover';
8
+ }
9
+ export interface FormKitOverlayAutoOptions {
10
+ data?: unknown;
11
+ valibotSchema?: ValibotLikeSchema;
12
+ zodSchema?: ZodLikeSchema;
13
+ overrides?: AutoFormOverrides;
14
+ title?: string;
15
+ as?: 'modal' | 'slideover';
16
+ }
17
+ export declare function useFormKitOverlay(): {
18
+ edit: (options: FormKitOverlayEditOptions) => Promise<unknown>;
19
+ auto: (options: FormKitOverlayAutoOptions) => Promise<unknown>;
20
+ };
@@ -0,0 +1,42 @@
1
+ import { useOverlay } from "@nuxt/ui/composables";
2
+ import FUAutoFormOverlay from "../components/FUAutoFormOverlay.vue";
3
+ import FUDataEditOverlay from "../components/FUDataEditOverlay.vue";
4
+ const registeredOverlays = /* @__PURE__ */ new WeakMap();
5
+ const registeredAutoOverlays = /* @__PURE__ */ new WeakMap();
6
+ let formIdCounter = 0;
7
+ export function useFormKitOverlay() {
8
+ const overlay = useOverlay();
9
+ let registeredOverlay = registeredOverlays.get(overlay);
10
+ if (!registeredOverlay) {
11
+ registeredOverlay = overlay.create(FUDataEditOverlay);
12
+ registeredOverlays.set(overlay, registeredOverlay);
13
+ }
14
+ let registeredAutoOverlay = registeredAutoOverlays.get(overlay);
15
+ if (!registeredAutoOverlay) {
16
+ registeredAutoOverlay = overlay.create(FUAutoFormOverlay);
17
+ registeredAutoOverlays.set(overlay, registeredAutoOverlay);
18
+ }
19
+ function edit(options) {
20
+ const id = `formkit-overlay-${++formIdCounter}`;
21
+ return registeredOverlay.open({
22
+ id,
23
+ data: options.data,
24
+ schema: options.schema,
25
+ title: options.title,
26
+ as: options.as ?? "modal"
27
+ });
28
+ }
29
+ function auto(options) {
30
+ const id = `formkit-autoform-overlay-${++formIdCounter}`;
31
+ return registeredAutoOverlay.open({
32
+ id,
33
+ data: options.data,
34
+ valibotSchema: options.valibotSchema,
35
+ zodSchema: options.zodSchema,
36
+ overrides: options.overrides,
37
+ title: options.title,
38
+ as: options.as ?? "modal"
39
+ });
40
+ }
41
+ return { edit, auto };
42
+ }
@@ -0,0 +1,20 @@
1
+ import type { FormKitNode } from '@formkit/core';
2
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
3
+ /**
4
+ * Runs `schema` against `node`'s live value and applies the resulting issues
5
+ * as `type: 'validation'` messages - to `node` itself for root-level issues,
6
+ * and to the addressed descendant (`resolveAddress(node, address)`) for
7
+ * every `childErrors` entry - so they respect each target's own
8
+ * `validationVisibility` timing exactly like FormKit's native rule-derived
9
+ * errors, instead of appearing instantly like `setErrors` does. See phase 1
10
+ * of the standard-schema-validation-bridge plan for why.
11
+ *
12
+ * Re-validates on the node's own `commit` event, which already fires once
13
+ * per settled change regardless of which descendant triggered it (a child's
14
+ * `calm()` cascades synchronously up through every ancestor's own `commit`),
15
+ * so this doesn't need a second debounce layer.
16
+ *
17
+ * Returns a detach function that stops re-validating and clears every
18
+ * schema-derived message this call ever applied.
19
+ */
20
+ export declare function attachStandardSchema(node: FormKitNode, schema: StandardSchemaV1): () => void;
@@ -0,0 +1,68 @@
1
+ import { createMessage, isNode } from "@formkit/core";
2
+ import { issuesToFormKitErrors } from "../utils/standardSchemaErrors.js";
3
+ const STANDARD_SCHEMA_SOURCE = "standard-schema";
4
+ function isStandardSchemaMessage(message) {
5
+ return message.meta.source === STANDARD_SCHEMA_SOURCE;
6
+ }
7
+ function clearStandardSchemaMessages(node) {
8
+ node.store.filter((message) => !isStandardSchemaMessage(message), "validation");
9
+ }
10
+ function setStandardSchemaMessages(node, values) {
11
+ clearStandardSchemaMessages(node);
12
+ values.forEach((value, index) => {
13
+ node.store.set(createMessage({
14
+ key: `standard_schema_${index}`,
15
+ type: "validation",
16
+ blocking: true,
17
+ value,
18
+ meta: { source: STANDARD_SCHEMA_SOURCE }
19
+ }));
20
+ });
21
+ }
22
+ function resolveAddress(root, address) {
23
+ let pointer = root;
24
+ for (const segment of address.split(root.config.delimiter)) {
25
+ if (!pointer)
26
+ return void 0;
27
+ const matches = pointer.children.filter(isNode).filter((child) => String(child.name) === segment);
28
+ pointer = matches.find((child) => child.type !== "input") ?? matches[0];
29
+ }
30
+ return pointer;
31
+ }
32
+ export function attachStandardSchema(node, schema) {
33
+ let previousAddresses = /* @__PURE__ */ new Set();
34
+ let runToken = 0;
35
+ async function validate() {
36
+ const token = ++runToken;
37
+ const result = await schema["~standard"].validate(node.value);
38
+ if (token !== runToken)
39
+ return;
40
+ const { localErrors, childErrors } = issuesToFormKitErrors(result.issues ?? []);
41
+ setStandardSchemaMessages(node, localErrors);
42
+ const currentAddresses = new Set(Object.keys(childErrors));
43
+ for (const address of previousAddresses) {
44
+ if (currentAddresses.has(address))
45
+ continue;
46
+ const target = resolveAddress(node, address);
47
+ if (target)
48
+ clearStandardSchemaMessages(target);
49
+ }
50
+ for (const [address, messages] of Object.entries(childErrors)) {
51
+ const target = resolveAddress(node, address);
52
+ if (target)
53
+ setStandardSchemaMessages(target, messages);
54
+ }
55
+ previousAddresses = currentAddresses;
56
+ }
57
+ const receipt = node.on("commit", () => void validate());
58
+ void validate();
59
+ return function detachStandardSchema() {
60
+ node.off(receipt);
61
+ clearStandardSchemaMessages(node);
62
+ for (const address of previousAddresses) {
63
+ const target = resolveAddress(node, address);
64
+ if (target)
65
+ clearStandardSchemaMessages(target);
66
+ }
67
+ };
68
+ }
@@ -0,0 +1,14 @@
1
+ import type { StandardSchemaV1 } from '@standard-schema/spec';
2
+ export interface FormKitStandardSchemaErrors {
3
+ localErrors: string[];
4
+ childErrors: Record<string, string[]>;
5
+ }
6
+ /**
7
+ * Normalizes a Standard Schema `Issue[]` array into FormKit's
8
+ * `setErrors`/`clearErrors` address shape. Mirrors `@nuxt/ui`'s own
9
+ * `validateStandardSchema()` path-flattening exactly (`item.key` for object
10
+ * path segments, the bare value otherwise, joined with `.`) so a Zod/Valibot
11
+ * issue at `items[2].email` resolves to the same FormKit node address
12
+ * (`"items.2.email"`) Nuxt UI's own forms would use for the same schema.
13
+ */
14
+ export declare function issuesToFormKitErrors(issues: readonly StandardSchemaV1.Issue[]): FormKitStandardSchemaErrors;
@@ -0,0 +1,15 @@
1
+ export function issuesToFormKitErrors(issues) {
2
+ const localErrors = [];
3
+ const childErrors = {};
4
+ for (const issue of issues) {
5
+ const address = issue.path?.map((item) => typeof item === "object" ? item.key : item).join(".");
6
+ if (!address) {
7
+ localErrors.push(issue.message);
8
+ continue;
9
+ }
10
+ if (!childErrors[address])
11
+ childErrors[address] = [];
12
+ childErrors[address].push(issue.message);
13
+ }
14
+ return { localErrors, childErrors };
15
+ }