@sfxcode/nuxt-ui-formkit 1.0.6 → 1.1.0

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 (43) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/FUDataDebug.d.vue.ts +2 -2
  3. package/dist/runtime/components/FUDataDebug.vue +21 -10
  4. package/dist/runtime/components/FUDataDebug.vue.d.ts +2 -2
  5. package/dist/runtime/components/FUDataEdit.vue +2 -2
  6. package/dist/runtime/components/FUDataView.vue +1 -1
  7. package/dist/runtime/components/inputs/FUCheckbox.d.vue.ts +2 -0
  8. package/dist/runtime/components/inputs/FUCheckbox.vue +2 -0
  9. package/dist/runtime/components/inputs/FUCheckbox.vue.d.ts +2 -0
  10. package/dist/runtime/components/inputs/FUInputMenu.d.vue.ts +4 -0
  11. package/dist/runtime/components/inputs/FUInputMenu.vue +4 -0
  12. package/dist/runtime/components/inputs/FUInputMenu.vue.d.ts +4 -0
  13. package/dist/runtime/components/inputs/FUInputNumber.d.vue.ts +1 -0
  14. package/dist/runtime/components/inputs/FUInputNumber.vue +2 -0
  15. package/dist/runtime/components/inputs/FUInputNumber.vue.d.ts +1 -0
  16. package/dist/runtime/components/inputs/FUInputTags.d.vue.ts +1 -1
  17. package/dist/runtime/components/inputs/FUInputTags.vue +1 -1
  18. package/dist/runtime/components/inputs/FUInputTags.vue.d.ts +1 -1
  19. package/dist/runtime/components/inputs/FUListbox.d.vue.ts +1 -0
  20. package/dist/runtime/components/inputs/FUListbox.vue +3 -2
  21. package/dist/runtime/components/inputs/FUListbox.vue.d.ts +1 -0
  22. package/dist/runtime/components/inputs/FUPinInput.d.vue.ts +2 -0
  23. package/dist/runtime/components/inputs/FUPinInput.vue +2 -0
  24. package/dist/runtime/components/inputs/FUPinInput.vue.d.ts +2 -0
  25. package/dist/runtime/components/inputs/FUSelect.d.vue.ts +1 -0
  26. package/dist/runtime/components/inputs/FUSelect.vue +1 -0
  27. package/dist/runtime/components/inputs/FUSelect.vue.d.ts +1 -0
  28. package/dist/runtime/components/inputs/FUSelectMenu.d.vue.ts +2 -0
  29. package/dist/runtime/components/inputs/FUSelectMenu.vue +2 -0
  30. package/dist/runtime/components/inputs/FUSelectMenu.vue.d.ts +2 -0
  31. package/dist/runtime/components/inputs/FUSwitch.d.vue.ts +2 -0
  32. package/dist/runtime/components/inputs/FUSwitch.vue +2 -0
  33. package/dist/runtime/components/inputs/FUSwitch.vue.d.ts +2 -0
  34. package/dist/runtime/components/output/FUOutputText.d.vue.ts +1 -1
  35. package/dist/runtime/components/output/FUOutputText.vue +15 -0
  36. package/dist/runtime/components/output/FUOutputText.vue.d.ts +1 -1
  37. package/dist/runtime/formkit/definitions/input.js +10 -10
  38. package/dist/runtime/formkit/definitions/input.mjs +10 -10
  39. package/dist/runtime/formkit/definitions/repeater.js +136 -58
  40. package/dist/runtime/formkit/definitions/repeater.mjs +136 -58
  41. package/dist/runtime/plugin.js +3 -0
  42. package/dist/runtime/utils/useFormKitInput.d.ts +1 -1
  43. package/package.json +30 -21
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=4.0.0"
6
6
  },
7
- "version": "1.0.6",
7
+ "version": "1.1.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
@@ -1,6 +1,6 @@
1
- declare var __VLS_7: {};
1
+ declare var __VLS_19: {};
2
2
  type __VLS_Slots = {} & {
3
- default?: (props: typeof __VLS_7) => any;
3
+ default?: (props: typeof __VLS_19) => any;
4
4
  };
5
5
  declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
6
6
  data: {
@@ -6,7 +6,7 @@ defineProps({
6
6
  },
7
7
  header: {
8
8
  type: String,
9
- default: "Debug"
9
+ default: "Debug Data"
10
10
  },
11
11
  textClass: {
12
12
  type: String,
@@ -18,15 +18,26 @@ defineProps({
18
18
  <template>
19
19
  <div class="formkit-debug">
20
20
  <client-only>
21
- <h3 class="text-lg font-semibold mb-2">
22
- {{ header }}
23
- </h3>
24
- <slot />
25
- <pre
26
- v-if="data"
27
- :class="textClass"
28
- >{{ data }}</pre>
29
- <span v-else>No Data available</span>
21
+ <UCollapsible class="flex flex-col gap-2">
22
+ <UButton
23
+ :label="header"
24
+ color="neutral"
25
+ variant="outline"
26
+ leading-icon="i-lucide-bug"
27
+ trailing-icon="i-lucide-chevron-down"
28
+ block
29
+ />
30
+ <template #content>
31
+ <div>
32
+ <slot />
33
+ </div>
34
+ <pre
35
+ v-if="data"
36
+ :class="textClass"
37
+ >{{ data }}</pre>
38
+ <span v-else>No Data available</span>
39
+ </template>
40
+ </UCollapsible>
30
41
  </client-only>
31
42
  </div>
32
43
  </template>
@@ -1,6 +1,6 @@
1
- declare var __VLS_7: {};
1
+ declare var __VLS_19: {};
2
2
  type __VLS_Slots = {} & {
3
- default?: (props: typeof __VLS_7) => any;
3
+ default?: (props: typeof __VLS_19) => any;
4
4
  };
5
5
  declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
6
6
  data: {
@@ -140,12 +140,12 @@ function handleReset() {
140
140
  <FUDataDebug
141
141
  v-if="debugData"
142
142
  :data="formData"
143
- header="Data"
143
+ header="Debug Data"
144
144
  />
145
145
  <FUDataDebug
146
146
  v-if="debugSchema"
147
147
  :data="formSchema"
148
- header="Schema"
148
+ header="Debug Schema"
149
149
  />
150
150
  </div>
151
151
  </template>
@@ -58,7 +58,7 @@ if (props.data) {
58
58
  <FuDataDebug
59
59
  v-if="debugData"
60
60
  :data="formData"
61
- header="Data"
61
+ header="Debug Data"
62
62
  />
63
63
  <FuDataDebug
64
64
  v-if="debugSchema"
@@ -9,6 +9,8 @@ export interface FormKitCheckboxProps {
9
9
  indicator?: 'start' | 'end' | 'hidden';
10
10
  icon?: string;
11
11
  indeterminateIcon?: string;
12
+ trueValue?: unknown;
13
+ falseValue?: unknown;
12
14
  autofocus?: false | true | 'true' | 'false';
13
15
  ui?: Record<string, unknown>;
14
16
  }
@@ -25,6 +25,8 @@ const { handleInput, handleChange, styleClass, modelValue, color, validSlotNames
25
25
  :indicator="context.indicator"
26
26
  :icon="context.icon"
27
27
  :indeterminate-icon="context.indeterminateIcon"
28
+ :true-value="context.trueValue"
29
+ :false-value="context.falseValue"
28
30
  :autofocus="context.autofocus"
29
31
  :ui="context.ui"
30
32
  @change="handleChange"
@@ -9,6 +9,8 @@ export interface FormKitCheckboxProps {
9
9
  indicator?: 'start' | 'end' | 'hidden';
10
10
  icon?: string;
11
11
  indeterminateIcon?: string;
12
+ trueValue?: unknown;
13
+ falseValue?: unknown;
12
14
  autofocus?: false | true | 'true' | 'false';
13
15
  ui?: Record<string, unknown>;
14
16
  }
@@ -28,6 +28,10 @@ export interface FormKitInputMenuProps {
28
28
  arrow?: boolean;
29
29
  portal?: boolean;
30
30
  virtualize?: boolean;
31
+ content?: Record<string, unknown>;
32
+ mode?: 'combobox' | 'autocomplete';
33
+ by?: string | ((a: unknown, b: unknown) => boolean);
34
+ open?: boolean;
31
35
  valueKey?: string;
32
36
  labelKey?: string;
33
37
  descriptionKey?: string;
@@ -35,6 +35,10 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, ite
35
35
  :arrow="context.arrow"
36
36
  :portal="context.portal"
37
37
  :virtualize="context.virtualize"
38
+ :content="context.content"
39
+ :mode="context.mode"
40
+ :by="context.by"
41
+ :open="context.open"
38
42
  :value-key="context.valueKey"
39
43
  :label-key="context.labelKey"
40
44
  :description-key="context.descriptionKey"
@@ -28,6 +28,10 @@ export interface FormKitInputMenuProps {
28
28
  arrow?: boolean;
29
29
  portal?: boolean;
30
30
  virtualize?: boolean;
31
+ content?: Record<string, unknown>;
32
+ mode?: 'combobox' | 'autocomplete';
33
+ by?: string | ((a: unknown, b: unknown) => boolean);
34
+ open?: boolean;
31
35
  valueKey?: string;
32
36
  labelKey?: string;
33
37
  descriptionKey?: string;
@@ -24,6 +24,7 @@ export interface FormKitInputNumberProps {
24
24
  disableWheelChange?: boolean;
25
25
  invertWheelChange?: boolean;
26
26
  focusOnChange?: boolean;
27
+ locale?: string;
27
28
  list: string;
28
29
  autocomplete?: string & {} | 'on' | 'off';
29
30
  ui?: Record<string, unknown>;
@@ -16,6 +16,7 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, val
16
16
  v-bind="{ ...context?.attrs }"
17
17
  :class="styleClass"
18
18
  :disabled="!!context?.disabled"
19
+ :readonly="context?.attrs.readonly ?? false"
19
20
  :style="context?.attrs.style"
20
21
  :color="color"
21
22
  :size="context.size ?? 'md'"
@@ -39,6 +40,7 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, val
39
40
  :disable-wheel-change="context.disableWheelChange"
40
41
  :invert-wheel-change="context.invertWheelChange"
41
42
  :focus-on-change="context.focusOnChange"
43
+ :locale="context.locale"
42
44
  :placeholder="context.placeholder"
43
45
  :list="context.list"
44
46
  :autocomplete="context.autocomplete"
@@ -24,6 +24,7 @@ export interface FormKitInputNumberProps {
24
24
  disableWheelChange?: boolean;
25
25
  invertWheelChange?: boolean;
26
26
  focusOnChange?: boolean;
27
+ locale?: string;
27
28
  list: string;
28
29
  autocomplete?: string & {} | 'on' | 'off';
29
30
  ui?: Record<string, unknown>;
@@ -16,7 +16,7 @@ export interface FormKitInputTagsProps {
16
16
  addOnTab?: boolean;
17
17
  addOnBlur?: boolean;
18
18
  duplicate?: boolean;
19
- delimiters?: string | RegExp;
19
+ delimiter?: string | RegExp;
20
20
  max: number;
21
21
  convertValue?: (value: string) => string;
22
22
  displayValue?: (value: string) => string;
@@ -32,7 +32,7 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, val
32
32
  :add-on-tab="context.addOnTab"
33
33
  :add-on-blur="context.addOnBlur"
34
34
  :duplicate="context.duplicate"
35
- :delimiters="context.delimiters"
35
+ :delimiter="context.delimiter"
36
36
  :max="context.max"
37
37
  :convert-value="context.convertValue"
38
38
  :display-value="context.displayValue"
@@ -16,7 +16,7 @@ export interface FormKitInputTagsProps {
16
16
  addOnTab?: boolean;
17
17
  addOnBlur?: boolean;
18
18
  duplicate?: boolean;
19
- delimiters?: string | RegExp;
19
+ delimiter?: string | RegExp;
20
20
  max: number;
21
21
  convertValue?: (value: string) => string;
22
22
  displayValue?: (value: string) => string;
@@ -16,6 +16,7 @@ export interface ListboxItem {
16
16
  export interface FormKitListboxProps {
17
17
  options?: string[] | ListboxItem[] | ListboxItem[][];
18
18
  as?: string;
19
+ color?: 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'error' | 'neutral';
19
20
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
20
21
  by?: string | ((a: unknown, b: unknown) => boolean);
21
22
  displayMode?: 'single' | 'transfer';
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { computed } from "vue";
2
+ import { computed, ref, watch } from "vue";
3
3
  import { useFormKitInput } from "../../utils/useFormKitInput";
4
4
  const props = defineProps({
5
5
  context: {
@@ -7,7 +7,7 @@ const props = defineProps({
7
7
  required: true
8
8
  }
9
9
  });
10
- const { handleInput, handleChange, isInvalid, styleClass, modelValue, items, validSlotNames } = useFormKitInput(props.context);
10
+ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, items, validSlotNames } = useFormKitInput(props.context);
11
11
  const targetItems = ref(modelValue.value || []);
12
12
  const sourceSelection = ref([]);
13
13
  const targetSelection = ref([]);
@@ -50,6 +50,7 @@ watch(targetItems, (newVal) => {
50
50
  :class="styleClass"
51
51
  :style="context?.attrs.style"
52
52
  :as="context.as"
53
+ :color="color"
53
54
  :size="context.size ?? 'md'"
54
55
  :items="items"
55
56
  :by="context.by"
@@ -16,6 +16,7 @@ export interface ListboxItem {
16
16
  export interface FormKitListboxProps {
17
17
  options?: string[] | ListboxItem[] | ListboxItem[][];
18
18
  as?: string;
19
+ color?: 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'error' | 'neutral';
19
20
  size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
20
21
  by?: string | ((a: unknown, b: unknown) => boolean);
21
22
  displayMode?: 'single' | 'transfer';
@@ -12,6 +12,8 @@ export interface FormKitPinInputProps {
12
12
  defaultValue?: string[] | undefined;
13
13
  mask?: boolean;
14
14
  otp?: boolean;
15
+ separator?: number | number[];
16
+ type?: 'text' | 'number';
15
17
  placeholder?: string;
16
18
  ui?: Record<string, unknown>;
17
19
  }
@@ -29,6 +29,8 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue } =
29
29
  :fixed="context.fixed"
30
30
  :mask="context.mask"
31
31
  :otp="context.otp"
32
+ :separator="context.separator"
33
+ :type="context.type ?? 'text'"
32
34
  :placeholder="context.placeholder"
33
35
  :ui="context.ui"
34
36
  @change="handleChange"
@@ -12,6 +12,8 @@ export interface FormKitPinInputProps {
12
12
  defaultValue?: string[] | undefined;
13
13
  mask?: boolean;
14
14
  otp?: boolean;
15
+ separator?: number | number[];
16
+ type?: 'text' | 'number';
15
17
  placeholder?: string;
16
18
  ui?: Record<string, unknown>;
17
19
  }
@@ -11,6 +11,7 @@ export interface FormKitSelectProps {
11
11
  selectedIcon?: string;
12
12
  arrow?: boolean;
13
13
  portal?: boolean;
14
+ content?: Record<string, unknown>;
14
15
  valueKey?: string;
15
16
  labelKey?: string;
16
17
  descriptionKey?: string;
@@ -34,6 +34,7 @@ const { handleInput, handleChange, isInvalid, color, styleClass, modelValue, ite
34
34
  :loading-icon="context.loadingIcon"
35
35
  :arrow="context.arrow"
36
36
  :portal="context.portal"
37
+ :content="context.content"
37
38
  :value-key="context.valueKey"
38
39
  :label-key="context.labelKey"
39
40
  :description-key="context.descriptionKey"
@@ -11,6 +11,7 @@ export interface FormKitSelectProps {
11
11
  selectedIcon?: string;
12
12
  arrow?: boolean;
13
13
  portal?: boolean;
14
+ content?: Record<string, unknown>;
14
15
  valueKey?: string;
15
16
  labelKey?: string;
16
17
  descriptionKey?: string;
@@ -37,6 +37,8 @@ export interface FormKitSelectMenuProps {
37
37
  arrow?: boolean;
38
38
  portal?: boolean;
39
39
  virtualize?: boolean;
40
+ content?: Record<string, unknown>;
41
+ by?: string | ((a: unknown, b: unknown) => boolean);
40
42
  valueKey?: string;
41
43
  labelKey?: string;
42
44
  descriptionKey?: string;
@@ -38,6 +38,8 @@ const { handleInput, handleChange, isInvalid, styleClass, color, modelValue, ite
38
38
  :arrow="context.arrow"
39
39
  :portal="context.portal"
40
40
  :virtualize="context.virtualize"
41
+ :content="context.content"
42
+ :by="context.by"
41
43
  :value-key="context.valueKey"
42
44
  :label-key="context.labelKey"
43
45
  :description-key="context.descriptionKey"
@@ -37,6 +37,8 @@ export interface FormKitSelectMenuProps {
37
37
  arrow?: boolean;
38
38
  portal?: boolean;
39
39
  virtualize?: boolean;
40
+ content?: Record<string, unknown>;
41
+ by?: string | ((a: unknown, b: unknown) => boolean);
40
42
  valueKey?: string;
41
43
  labelKey?: string;
42
44
  descriptionKey?: string;
@@ -10,6 +10,8 @@ export interface FormKitSwitchProps {
10
10
  label?: string;
11
11
  description?: string;
12
12
  defaultValue?: boolean;
13
+ trueValue?: unknown;
14
+ falseValue?: unknown;
13
15
  autofocus?: false | true | 'true' | 'false';
14
16
  ui?: Record<string, unknown>;
15
17
  }
@@ -26,6 +26,8 @@ const { handleInput, handleChange, styleClass, color, modelValue, validSlotNames
26
26
  :label="context.label"
27
27
  :description="context.description"
28
28
  :default-value="context.defaultValue"
29
+ :true-value="context.trueValue"
30
+ :false-value="context.falseValue"
29
31
  :autofocus="context.autofocus"
30
32
  :ui="context.ui"
31
33
  @change="handleChange"
@@ -10,6 +10,8 @@ export interface FormKitSwitchProps {
10
10
  label?: string;
11
11
  description?: string;
12
12
  defaultValue?: boolean;
13
+ trueValue?: unknown;
14
+ falseValue?: unknown;
13
15
  autofocus?: false | true | 'true' | 'false';
14
16
  ui?: Record<string, unknown>;
15
17
  }
@@ -10,7 +10,7 @@ export interface FormKitOutputTextProps {
10
10
  trailing?: boolean;
11
11
  trailingIcon?: string;
12
12
  variant?: 'outline' | 'soft' | 'subtle' | 'ghost' | 'none';
13
- outputType?: 'text' | 'email' | 'url' | 'tel' | 'color' | 'duration';
13
+ outputType?: 'text' | 'email' | 'url' | 'tel' | 'color' | 'duration' | 'i18n';
14
14
  }
15
15
  declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
16
16
  context: {
@@ -1,5 +1,6 @@
1
1
  <script setup>
2
2
  import { computed } from "vue";
3
+ import { useI18n } from "vue-i18n";
3
4
  import { useFormKitOutput } from "../../utils/useFormKitOutput";
4
5
  import { convertColorToHex } from "../../utils/colorConverter";
5
6
  import { formattedDuration } from "../../utils/durationConverter";
@@ -11,10 +12,24 @@ const props = defineProps({
11
12
  }
12
13
  });
13
14
  const outputType = computed(() => props.context.outputType ?? "text");
15
+ let translate;
16
+ try {
17
+ translate = useI18n().t;
18
+ } catch {
19
+ translate = void 0;
20
+ }
14
21
  const displayValue = computed(() => {
15
22
  let result = props.context._value ?? "";
16
23
  if (outputType.value === "duration") {
17
24
  result = formattedDuration(result);
25
+ } else if (outputType.value === "i18n") {
26
+ const key = String(result ?? "");
27
+ if (key && translate) {
28
+ const translated = translate(key);
29
+ result = typeof translated === "string" && translated.length > 0 ? translated : key;
30
+ } else {
31
+ result = key;
32
+ }
18
33
  }
19
34
  return result;
20
35
  });
@@ -10,7 +10,7 @@ export interface FormKitOutputTextProps {
10
10
  trailing?: boolean;
11
11
  trailingIcon?: string;
12
12
  variant?: 'outline' | 'soft' | 'subtle' | 'ghost' | 'none';
13
- outputType?: 'text' | 'email' | 'url' | 'tel' | 'color' | 'duration';
13
+ outputType?: 'text' | 'email' | 'url' | 'tel' | 'color' | 'duration' | 'i18n';
14
14
  }
15
15
  declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
16
16
  context: {
@@ -17,11 +17,11 @@ import FUSlider from "../../../runtime/components/inputs/FUSlider.vue";
17
17
  import FUSwitch from "../../../runtime/components/inputs/FUSwitch.vue";
18
18
  import FUTextarea from "../../../runtime/components/inputs/FUTextarea.vue";
19
19
  export const nuxtUICheckboxDefinition = createInput(FUCheckbox, {
20
- props: ["label", "description", "color", "variant", "size", "indicator", "icon", "indeterminateIcon", "autofocus", "ui"],
20
+ props: ["label", "description", "color", "variant", "size", "indicator", "icon", "indeterminateIcon", "trueValue", "falseValue", "autofocus", "ui"],
21
21
  family: "NuxtUIInput"
22
22
  });
23
23
  export const nuxtUICheckboxGroupDefinition = createInput(FUCheckboxGroup, {
24
- props: ["options", "legend", "valueKey", "labelKey", "descriptionKey", "size", "variant", "orientation", "loop", "color", "indicator", "icon", "ui", "items"],
24
+ props: ["options", "legend", "valueKey", "labelKey", "descriptionKey", "size", "variant", "orientation", "loop", "name", "color", "indicator", "icon", "ui", "items"],
25
25
  family: "NuxtUIInput"
26
26
  });
27
27
  export const nuxtUIColorPickerDefinition = createInput(FUColorPicker, {
@@ -37,15 +37,15 @@ export const nuxtUIInputDateDefinition = createInput(FUInputDate, {
37
37
  family: "NuxtUIInput"
38
38
  });
39
39
  export const nuxtUIInputMenuDefinition = createInput(FUInputMenu, {
40
- props: ["options", "inputType", "placeholder", "color", "variant", "size", "autofocus", "autofocusDelay", "trailingIcon", "selectedIcon", "deleteIcon", "clear", "clearIcon", "arrow", "portal", "virtualize", "valueKey", "labelKey", "descriptionKey", "multiple", "highlight", "fixed", "createItem", "filterFields", "ignoreFilter", "defaultOpen", "resetSearchTermOnBlur", "resetSearchTermOnSelect", "resetModelValueOnClear", "highlightOnHover", "openOnClick", "openOnFocus", "icon", "leading", "leadingIcon", "trailing", "loading", "loadingIcon", "list", "autocomplete", "searchTerm", "ui"],
40
+ props: ["options", "inputType", "placeholder", "color", "variant", "size", "autofocus", "autofocusDelay", "trailingIcon", "selectedIcon", "deleteIcon", "clear", "clearIcon", "arrow", "portal", "virtualize", "content", "mode", "by", "open", "valueKey", "labelKey", "descriptionKey", "multiple", "highlight", "fixed", "createItem", "filterFields", "ignoreFilter", "defaultOpen", "resetSearchTermOnBlur", "resetSearchTermOnSelect", "resetModelValueOnClear", "highlightOnHover", "openOnClick", "openOnFocus", "icon", "leading", "leadingIcon", "trailing", "loading", "loadingIcon", "list", "autocomplete", "searchTerm", "ui"],
41
41
  family: "NuxtUIInput"
42
42
  });
43
43
  export const nuxtUIInputNumberDefinition = createInput(FUInputNumber, {
44
- props: ["placeholder", "color", "variant", "size", "highlight", "fixed", "orientation", "increment", "incrementIcon", "incrementDisabled", "decrement", "decrementIcon", "decrementDisabled", "autofocus", "autofocusDelay", "min", "max", "step", "stepSnapping", "formatOptions", "disableWheelChange", "invertWheelChange", "focusOnChange", "list", "autocomplete", "ui"],
44
+ props: ["placeholder", "color", "variant", "size", "highlight", "fixed", "orientation", "increment", "incrementIcon", "incrementDisabled", "decrement", "decrementIcon", "decrementDisabled", "autofocus", "autofocusDelay", "min", "max", "step", "stepSnapping", "formatOptions", "disableWheelChange", "invertWheelChange", "focusOnChange", "locale", "list", "autocomplete", "ui"],
45
45
  family: "NuxtUIInput"
46
46
  });
47
47
  export const nuxtUIInputTagsDefinition = createInput(FUInputTags, {
48
- props: ["placeholder", "maxLength", "color", "variant", "size", "autofocus", "autofocusDelay", "deleteIcon", "highlight", "fixed", "addOnPaste", "addOnTab", "addOnBlur", "duplicate", "delimiters", "max", "convertValue", "displayValue", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "list", "autocomplete", "ui"],
48
+ props: ["placeholder", "maxLength", "color", "variant", "size", "autofocus", "autofocusDelay", "deleteIcon", "highlight", "fixed", "addOnPaste", "addOnTab", "addOnBlur", "duplicate", "delimiter", "max", "convertValue", "displayValue", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "list", "autocomplete", "ui"],
49
49
  family: "NuxtUIInput"
50
50
  });
51
51
  export const nuxtUIInputTimeDefinition = createInput(FUInputTime, {
@@ -53,11 +53,11 @@ export const nuxtUIInputTimeDefinition = createInput(FUInputTime, {
53
53
  family: "NuxtUIInput"
54
54
  });
55
55
  export const nuxtUIListboxDefinition = createInput(FUListbox, {
56
- props: ["options", "as", "size", "by", "orientation", "selectionBehavior", "disabled", "defaultValue", "multiple", "valueKey", "labelKey", "descriptionKey", "loading", "loadingIcon", "filter", "filterFields", "ignoreFilter", "selectedIcon", "virtualize", "highlight", "highlightOnHover", "autofocus", "autofocusDelay", "searchTerm", "ui", "displayMode", "transferLeftHeaderText", "transferRightHeaderText", "transferAll", "transferHeaderClass"],
56
+ props: ["options", "as", "color", "size", "by", "orientation", "selectionBehavior", "disabled", "defaultValue", "multiple", "valueKey", "labelKey", "descriptionKey", "loading", "loadingIcon", "filter", "filterFields", "ignoreFilter", "selectedIcon", "virtualize", "highlight", "highlightOnHover", "autofocus", "autofocusDelay", "searchTerm", "ui", "displayMode", "transferLeftHeaderText", "transferRightHeaderText", "transferAll", "transferHeaderClass"],
57
57
  family: "NuxtUIInput"
58
58
  });
59
59
  export const nuxtUIPinInputDefinition = createInput(FUPinInput, {
60
- props: ["color", "variant", "size", "length", "autofocus", "autofocusDelay", "highlight", "fixed", "defaultValue", "mask", "otp", "placeholder", "ui"],
60
+ props: ["color", "variant", "size", "length", "autofocus", "autofocusDelay", "highlight", "fixed", "defaultValue", "mask", "otp", "separator", "type", "placeholder", "ui"],
61
61
  family: "NuxtUIInput"
62
62
  });
63
63
  export const nuxtUIRadioGroupDefinition = createInput(FURadioGroup, {
@@ -65,11 +65,11 @@ export const nuxtUIRadioGroupDefinition = createInput(FURadioGroup, {
65
65
  family: "NuxtUIInput"
66
66
  });
67
67
  export const nuxtUISelectDefinition = createInput(FUSelect, {
68
- props: ["options", "placeholder", "color", "variant", "size", "selectedIcon", "arrow", "portal", "valueKey", "labelKey", "descriptionKey", "defaultValue", "multiple", "highlight", "fixed", "autofocus", "autofocusDelay", "open", "defaultOpen", "autocomplete", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "ui"],
68
+ props: ["options", "placeholder", "color", "variant", "size", "selectedIcon", "arrow", "portal", "content", "valueKey", "labelKey", "descriptionKey", "defaultValue", "multiple", "highlight", "fixed", "autofocus", "autofocusDelay", "open", "defaultOpen", "autocomplete", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "ui"],
69
69
  family: "NuxtUIInput"
70
70
  });
71
71
  export const nuxtUISelectMenuDefinition = createInput(FUSelectMenu, {
72
- props: ["options", "placeholder", "searchInput", "color", "variant", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "selectedIcon", "clear", "clearIcon", "arrow", "portal", "virtualize", "valueKey", "labelKey", "descriptionKey", "defaultValue", "multiple", "highlight", "fixed", "createItem", "filterFields", "ignoreFilter", "autofocus", "autofocusDelay", "open", "defaultOpen", "resetSearchTermOnBlur", "resetSearchTermOnSelect", "resetModelValueOnClear", "highlightOnHover", "searchTerm", "ui"],
72
+ props: ["options", "placeholder", "searchInput", "color", "variant", "size", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "selectedIcon", "clear", "clearIcon", "arrow", "portal", "virtualize", "content", "by", "valueKey", "labelKey", "descriptionKey", "defaultValue", "multiple", "highlight", "fixed", "createItem", "filterFields", "ignoreFilter", "autofocus", "autofocusDelay", "open", "defaultOpen", "resetSearchTermOnBlur", "resetSearchTermOnSelect", "resetModelValueOnClear", "highlightOnHover", "searchTerm", "ui"],
73
73
  family: "NuxtUIInput"
74
74
  });
75
75
  export const nuxtUISliderDefinition = createInput(FUSlider, {
@@ -77,7 +77,7 @@ export const nuxtUISliderDefinition = createInput(FUSlider, {
77
77
  family: "NuxtUIInput"
78
78
  });
79
79
  export const nuxtUISwitchDefinition = createInput(FUSwitch, {
80
- props: ["color", "size", "loading", "loadingIcon", "checkedIcon", "uncheckedIcon", "label", "description", "defaultValue", "autofocus", "ui"],
80
+ props: ["color", "size", "loading", "loadingIcon", "checkedIcon", "uncheckedIcon", "label", "description", "defaultValue", "trueValue", "falseValue", "autofocus", "ui"],
81
81
  family: "NuxtUIInput"
82
82
  });
83
83
  export const nuxtUITextareaDefinition = createInput(FUTextarea, {
@@ -17,11 +17,11 @@ import FUSlider from "../../../runtime/components/inputs/FUSlider.vue";
17
17
  import FUSwitch from "../../../runtime/components/inputs/FUSwitch.vue";
18
18
  import FUTextarea from "../../../runtime/components/inputs/FUTextarea.vue";
19
19
  export const nuxtUICheckboxDefinition = createInput(FUCheckbox, {
20
- props: ["label", "description", "color", "variant", "size", "indicator", "icon", "indeterminateIcon", "autofocus", "ui"],
20
+ props: ["label", "description", "color", "variant", "size", "indicator", "icon", "indeterminateIcon", "trueValue", "falseValue", "autofocus", "ui"],
21
21
  family: "NuxtUIInput"
22
22
  });
23
23
  export const nuxtUICheckboxGroupDefinition = createInput(FUCheckboxGroup, {
24
- props: ["options", "legend", "valueKey", "labelKey", "descriptionKey", "size", "variant", "orientation", "loop", "color", "indicator", "icon", "ui", "items"],
24
+ props: ["options", "legend", "valueKey", "labelKey", "descriptionKey", "size", "variant", "orientation", "loop", "name", "color", "indicator", "icon", "ui", "items"],
25
25
  family: "NuxtUIInput"
26
26
  });
27
27
  export const nuxtUIColorPickerDefinition = createInput(FUColorPicker, {
@@ -37,15 +37,15 @@ export const nuxtUIInputDateDefinition = createInput(FUInputDate, {
37
37
  family: "NuxtUIInput"
38
38
  });
39
39
  export const nuxtUIInputMenuDefinition = createInput(FUInputMenu, {
40
- props: ["options", "inputType", "placeholder", "color", "variant", "size", "autofocus", "autofocusDelay", "trailingIcon", "selectedIcon", "deleteIcon", "clear", "clearIcon", "arrow", "portal", "virtualize", "valueKey", "labelKey", "descriptionKey", "multiple", "highlight", "fixed", "createItem", "filterFields", "ignoreFilter", "defaultOpen", "resetSearchTermOnBlur", "resetSearchTermOnSelect", "resetModelValueOnClear", "highlightOnHover", "openOnClick", "openOnFocus", "icon", "leading", "leadingIcon", "trailing", "loading", "loadingIcon", "list", "autocomplete", "searchTerm", "ui"],
40
+ props: ["options", "inputType", "placeholder", "color", "variant", "size", "autofocus", "autofocusDelay", "trailingIcon", "selectedIcon", "deleteIcon", "clear", "clearIcon", "arrow", "portal", "virtualize", "content", "mode", "by", "open", "valueKey", "labelKey", "descriptionKey", "multiple", "highlight", "fixed", "createItem", "filterFields", "ignoreFilter", "defaultOpen", "resetSearchTermOnBlur", "resetSearchTermOnSelect", "resetModelValueOnClear", "highlightOnHover", "openOnClick", "openOnFocus", "icon", "leading", "leadingIcon", "trailing", "loading", "loadingIcon", "list", "autocomplete", "searchTerm", "ui"],
41
41
  family: "NuxtUIInput"
42
42
  });
43
43
  export const nuxtUIInputNumberDefinition = createInput(FUInputNumber, {
44
- props: ["placeholder", "color", "variant", "size", "highlight", "fixed", "orientation", "increment", "incrementIcon", "incrementDisabled", "decrement", "decrementIcon", "decrementDisabled", "autofocus", "autofocusDelay", "min", "max", "step", "stepSnapping", "formatOptions", "disableWheelChange", "invertWheelChange", "focusOnChange", "list", "autocomplete", "ui"],
44
+ props: ["placeholder", "color", "variant", "size", "highlight", "fixed", "orientation", "increment", "incrementIcon", "incrementDisabled", "decrement", "decrementIcon", "decrementDisabled", "autofocus", "autofocusDelay", "min", "max", "step", "stepSnapping", "formatOptions", "disableWheelChange", "invertWheelChange", "focusOnChange", "locale", "list", "autocomplete", "ui"],
45
45
  family: "NuxtUIInput"
46
46
  });
47
47
  export const nuxtUIInputTagsDefinition = createInput(FUInputTags, {
48
- props: ["placeholder", "maxLength", "color", "variant", "size", "autofocus", "autofocusDelay", "deleteIcon", "highlight", "fixed", "addOnPaste", "addOnTab", "addOnBlur", "duplicate", "delimiters", "max", "convertValue", "displayValue", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "list", "autocomplete", "ui"],
48
+ props: ["placeholder", "maxLength", "color", "variant", "size", "autofocus", "autofocusDelay", "deleteIcon", "highlight", "fixed", "addOnPaste", "addOnTab", "addOnBlur", "duplicate", "delimiter", "max", "convertValue", "displayValue", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "list", "autocomplete", "ui"],
49
49
  family: "NuxtUIInput"
50
50
  });
51
51
  export const nuxtUIInputTimeDefinition = createInput(FUInputTime, {
@@ -53,11 +53,11 @@ export const nuxtUIInputTimeDefinition = createInput(FUInputTime, {
53
53
  family: "NuxtUIInput"
54
54
  });
55
55
  export const nuxtUIListboxDefinition = createInput(FUListbox, {
56
- props: ["options", "as", "size", "by", "orientation", "selectionBehavior", "disabled", "defaultValue", "multiple", "valueKey", "labelKey", "descriptionKey", "loading", "loadingIcon", "filter", "filterFields", "ignoreFilter", "selectedIcon", "virtualize", "highlight", "highlightOnHover", "autofocus", "autofocusDelay", "searchTerm", "ui", "displayMode", "transferLeftHeaderText", "transferRightHeaderText", "transferAll", "transferHeaderClass"],
56
+ props: ["options", "as", "color", "size", "by", "orientation", "selectionBehavior", "disabled", "defaultValue", "multiple", "valueKey", "labelKey", "descriptionKey", "loading", "loadingIcon", "filter", "filterFields", "ignoreFilter", "selectedIcon", "virtualize", "highlight", "highlightOnHover", "autofocus", "autofocusDelay", "searchTerm", "ui", "displayMode", "transferLeftHeaderText", "transferRightHeaderText", "transferAll", "transferHeaderClass"],
57
57
  family: "NuxtUIInput"
58
58
  });
59
59
  export const nuxtUIPinInputDefinition = createInput(FUPinInput, {
60
- props: ["color", "variant", "size", "length", "autofocus", "autofocusDelay", "highlight", "fixed", "defaultValue", "mask", "otp", "placeholder", "ui"],
60
+ props: ["color", "variant", "size", "length", "autofocus", "autofocusDelay", "highlight", "fixed", "defaultValue", "mask", "otp", "separator", "type", "placeholder", "ui"],
61
61
  family: "NuxtUIInput"
62
62
  });
63
63
  export const nuxtUIRadioGroupDefinition = createInput(FURadioGroup, {
@@ -65,11 +65,11 @@ export const nuxtUIRadioGroupDefinition = createInput(FURadioGroup, {
65
65
  family: "NuxtUIInput"
66
66
  });
67
67
  export const nuxtUISelectDefinition = createInput(FUSelect, {
68
- props: ["options", "placeholder", "color", "variant", "size", "selectedIcon", "arrow", "portal", "valueKey", "labelKey", "descriptionKey", "defaultValue", "multiple", "highlight", "fixed", "autofocus", "autofocusDelay", "open", "defaultOpen", "autocomplete", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "ui"],
68
+ props: ["options", "placeholder", "color", "variant", "size", "selectedIcon", "arrow", "portal", "content", "valueKey", "labelKey", "descriptionKey", "defaultValue", "multiple", "highlight", "fixed", "autofocus", "autofocusDelay", "open", "defaultOpen", "autocomplete", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "ui"],
69
69
  family: "NuxtUIInput"
70
70
  });
71
71
  export const nuxtUISelectMenuDefinition = createInput(FUSelectMenu, {
72
- props: ["options", "placeholder", "searchInput", "color", "variant", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "selectedIcon", "clear", "clearIcon", "arrow", "portal", "virtualize", "valueKey", "labelKey", "descriptionKey", "defaultValue", "multiple", "highlight", "fixed", "createItem", "filterFields", "ignoreFilter", "autofocus", "autofocusDelay", "open", "defaultOpen", "resetSearchTermOnBlur", "resetSearchTermOnSelect", "resetModelValueOnClear", "highlightOnHover", "searchTerm", "ui"],
72
+ props: ["options", "placeholder", "searchInput", "color", "variant", "size", "icon", "avatar", "leading", "leadingIcon", "trailing", "trailingIcon", "loading", "loadingIcon", "selectedIcon", "clear", "clearIcon", "arrow", "portal", "virtualize", "content", "by", "valueKey", "labelKey", "descriptionKey", "defaultValue", "multiple", "highlight", "fixed", "createItem", "filterFields", "ignoreFilter", "autofocus", "autofocusDelay", "open", "defaultOpen", "resetSearchTermOnBlur", "resetSearchTermOnSelect", "resetModelValueOnClear", "highlightOnHover", "searchTerm", "ui"],
73
73
  family: "NuxtUIInput"
74
74
  });
75
75
  export const nuxtUISliderDefinition = createInput(FUSlider, {
@@ -77,7 +77,7 @@ export const nuxtUISliderDefinition = createInput(FUSlider, {
77
77
  family: "NuxtUIInput"
78
78
  });
79
79
  export const nuxtUISwitchDefinition = createInput(FUSwitch, {
80
- props: ["color", "size", "loading", "loadingIcon", "checkedIcon", "uncheckedIcon", "label", "description", "defaultValue", "autofocus", "ui"],
80
+ props: ["color", "size", "loading", "loadingIcon", "checkedIcon", "uncheckedIcon", "label", "description", "defaultValue", "trueValue", "falseValue", "autofocus", "ui"],
81
81
  family: "NuxtUIInput"
82
82
  });
83
83
  export const nuxtUITextareaDefinition = createInput(FUTextarea, {
@@ -18,19 +18,36 @@ function addInsertButton(label = "Add Item", icon = "i-lucide-plus", styleClass
18
18
  addComponent("UButton", { onClick: "$insertNode($node)", label, icon, size: buttonSize, disabled: "$node.value.length > $maxItems -1" })
19
19
  ], { class: styleClass }, render);
20
20
  }
21
+ function addDragHandle(handleClass = "", iconName = "", render = "true") {
22
+ return addElement("span", [
23
+ addComponent("UIcon", { name: iconName })
24
+ ], {
25
+ "class": handleClass,
26
+ "aria-label": "Drag to reorder"
27
+ }, render);
28
+ }
21
29
  export const nuxtUIRepeaterDefinition = createInput(
22
- addElement("ul", [
30
+ addElement("div", [
23
31
  addList("$listName", [
24
32
  addInsertButton("$insertButtonLabel", "i-lucide-plus", "$insertButtonClass", "$insertButtonSize", "$node.children.length == 0 || $alwaysDisplayInsertButton"),
25
33
  addListGroup([
26
- addElement(
27
- "li",
28
- [{ children: "$slots.default" }, addButtonGroup("$buttonGroupClass", "$buttonGroupItemClass", "$buttonSize", "$renderButtons")],
29
- { class: "$internalListItemClass" }
30
- )
34
+ addElement("div", [
35
+ addDragHandle("$internalDragHandleClass", "$dragHandleIconName", "$renderDragHandle"),
36
+ { children: "$slots.default" },
37
+ addButtonGroup("$buttonGroupClass", "$buttonGroupItemClass", "$buttonSize", "$renderButtons")
38
+ ], {
39
+ id: "$getListItemId($index)",
40
+ class: "$getListItemClass($index)",
41
+ draggable: "$draggable",
42
+ onDragstart: "$dragNodeStart($node.parent, $index)",
43
+ onDragover: "$dragNodeOver($index)",
44
+ onDragleave: "$dragNodeLeave($index)",
45
+ onDrop: "$dropNode($node.parent, $index)",
46
+ onDragend: "$dragNodeEnd"
47
+ })
31
48
  ], true, {})
32
49
  ], true, "true")
33
- ], { class: "$internalListClass" }, true),
50
+ ], { class: "$internalListClass", id: "$internalListId" }, true),
34
51
  {
35
52
  props: [
36
53
  "insertButtonLabel",
@@ -49,7 +66,11 @@ export const nuxtUIRepeaterDefinition = createInput(
49
66
  "displayAddButton",
50
67
  "displayDeleteButton",
51
68
  "minItems",
52
- "maxItems"
69
+ "maxItems",
70
+ "draggable",
71
+ "displayDragHandle",
72
+ "dragHandleClass",
73
+ "dragHandleIconName"
53
74
  ],
54
75
  features: [addRepeaterHandler]
55
76
  }
@@ -62,56 +83,113 @@ function addRepeaterHandler(node) {
62
83
  }
63
84
  return array;
64
85
  };
86
+ const uuid = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2);
65
87
  node.on("created", () => {
66
- node.context.listName = node.name;
67
- node.context.renderButtons = !node.context.hideButtonGroup;
68
- node.context.insertButtonSize = node.context.insertButtonSize ? node.context.insertButtonSize : "md";
69
- node.context.buttonSize = node.context.buttonSize ? node.context.buttonSize : "md";
70
- node.context.renderMoveButtons = !node.context.hideMoveButtons;
71
- node.context.internalListClass = node.context.listClass ? `formkit-items ${node.context.listClass}` : "formkit-items";
72
- node.context.internalListItemClass = node.context.listItemClass ? `formkit-item ${node.context.listItemClass}` : "formkit-item";
73
- node.context.minItems = node.context.minItems !== void 0 ? node.context.minItems : 0;
74
- node.context.maxItems = node.context.maxItems !== void 0 ? node.context.maxItems : Number.POSITIVE_INFINITY;
75
- node.context.insertNode = (parentNode) => () => {
76
- if (parentNode && Array.isArray(parentNode._value)) {
77
- const item = node.context.newItem ? { ...node.context.newItem } : {};
78
- const array = parentNode.value;
79
- array.push(item);
80
- parentNode.input(array, false);
81
- }
82
- };
83
- node.context.removeNode = (parentNode, index) => () => {
84
- if (parentNode && Array.isArray(parentNode._value)) {
85
- parentNode.input(parentNode._value.filter((_, i) => i !== index), false);
86
- }
87
- };
88
- node.context.addNode = (parentNode, index) => () => {
89
- if (parentNode && Array.isArray(parentNode._value)) {
90
- const array = parentNode.value;
91
- const item = node.context.newItem ? { ...node.context.newItem } : {};
92
- array.splice(index + 1, 0, item);
93
- parentNode.input(array, false);
94
- }
95
- };
96
- node.context.cloneNode = (parentNode, index) => () => {
97
- if (parentNode && Array.isArray(parentNode._value)) {
98
- const item = parentNode.value[index];
99
- const array = parentNode.value;
100
- array.splice(index + 1, 0, item);
101
- parentNode.input(array, false);
102
- }
103
- };
104
- node.context.moveNodeUp = (parentNode, index) => () => {
105
- if (parentNode && Array.isArray(parentNode._value)) {
106
- if (index > 0)
107
- parentNode.input(swapElements(parentNode.value, index - 1, index), false);
108
- }
109
- };
110
- node.context.moveNodeDown = (parentNode, index) => () => {
111
- if (parentNode && Array.isArray(parentNode._value)) {
112
- if (index < parentNode.value.length - 1)
113
- parentNode.input(swapElements(parentNode.value, index, index + 1), false);
114
- }
115
- };
88
+ if (node.context) {
89
+ let dragStartIndex = null;
90
+ let dragOverIndex = null;
91
+ const newItem = node.context.newItem || {};
92
+ node.context.listName = node.name;
93
+ node.context.renderButtons = !node.context.hideButtonGroup;
94
+ node.context.insertButtonSize = node.context.insertButtonSize ? node.context.insertButtonSize : "md";
95
+ node.context.buttonSize = node.context.buttonSize ? node.context.buttonSize : "md";
96
+ node.context.renderMoveButtons = !node.context.hideMoveButtons;
97
+ node.context.draggable = !!node.context.draggable;
98
+ node.context.renderDragHandle = !!node.context.displayDragHandle;
99
+ node.context.dragHandleIconName = node.context.dragHandleIconName || "i-lucide-grip-vertical";
100
+ node.context.internalDragHandleClass = node.context.dragHandleClass ? `formkit-repeater-drag-handle ${node.context.dragHandleClass}` : "formkit-repeater-drag-handle";
101
+ node.context.internalListClass = node.context.listClass ? `formkit-items ${node.context.listClass}` : "formkit-items";
102
+ node.context.internalListItemClass = node.context.listItemClass ? `formkit-item ${node.context.listItemClass}` : "formkit-item";
103
+ node.context.internalListId = `formkit-items-${uuid}`;
104
+ node.context.minItems = node.context.minItems !== void 0 ? node.context.minItems : 0;
105
+ node.context.maxItems = node.context.maxItems !== void 0 ? node.context.maxItems : Number.POSITIVE_INFINITY;
106
+ node.context.getListItemClass = (index) => {
107
+ if (dragOverIndex === index && dragStartIndex !== index)
108
+ return `${node.context?.internalListItemClass} formkit-repeater-drop-target`;
109
+ return node.context?.internalListItemClass?.toString() ?? "";
110
+ };
111
+ node.context.getListItemId = (index) => {
112
+ return `formkit-item-${index}-${uuid}`;
113
+ };
114
+ node.context.insertNode = (parentNode) => () => {
115
+ if (parentNode && Array.isArray(parentNode._value)) {
116
+ const newArray = [{ ...newItem }, ...parentNode.value];
117
+ parentNode.input(newArray, false);
118
+ }
119
+ };
120
+ node.context.removeNode = (parentNode, index) => () => {
121
+ if (parentNode && Array.isArray(parentNode._value)) {
122
+ parentNode.input(parentNode._value.filter((_, i) => i !== index), false);
123
+ }
124
+ };
125
+ node.context.addNode = (parentNode, index) => () => {
126
+ if (parentNode && Array.isArray(parentNode._value)) {
127
+ const array = parentNode.value;
128
+ array.splice(index + 1, 0, { ...newItem });
129
+ parentNode.input(array, false);
130
+ }
131
+ };
132
+ node.context.cloneNode = (parentNode, index) => () => {
133
+ if (parentNode && Array.isArray(parentNode._value)) {
134
+ const item = parentNode.value[index];
135
+ const array = parentNode.value;
136
+ array.splice(index + 1, 0, { ...item });
137
+ parentNode.input(array, false);
138
+ }
139
+ };
140
+ node.context.moveNodeUp = (parentNode, index) => () => {
141
+ if (parentNode && Array.isArray(parentNode._value)) {
142
+ if (index > 0)
143
+ parentNode.input(swapElements(parentNode.value, index - 1, index), false);
144
+ }
145
+ };
146
+ node.context.moveNodeDown = (parentNode, index) => () => {
147
+ if (parentNode && Array.isArray(parentNode._value)) {
148
+ if (index < parentNode.value.length - 1)
149
+ parentNode.input(swapElements(parentNode.value, index, index + 1), false);
150
+ }
151
+ };
152
+ node.context.dragNodeStart = (_parentNode, index) => (event) => {
153
+ dragStartIndex = index;
154
+ if (event?.dataTransfer) {
155
+ event.dataTransfer.effectAllowed = "move";
156
+ event.dataTransfer.setData("text/plain", String(index));
157
+ }
158
+ };
159
+ node.context.dragNodeOver = (targetIndex) => (event) => {
160
+ event?.preventDefault();
161
+ dragOverIndex = targetIndex;
162
+ if (event?.dataTransfer)
163
+ event.dataTransfer.dropEffect = "move";
164
+ };
165
+ node.context.dragNodeLeave = (targetIndex) => () => {
166
+ if (dragOverIndex === targetIndex)
167
+ dragOverIndex = null;
168
+ };
169
+ node.context.dropNode = (parentNode, targetIndex) => (event) => {
170
+ event?.preventDefault();
171
+ if (!parentNode || !Array.isArray(parentNode._value)) {
172
+ dragOverIndex = null;
173
+ return;
174
+ }
175
+ const sourceFromEvent = Number.parseInt(event?.dataTransfer?.getData("text/plain") || "", 10);
176
+ const sourceIndex = Number.isInteger(sourceFromEvent) ? sourceFromEvent : dragStartIndex;
177
+ if (sourceIndex === null || sourceIndex === targetIndex) {
178
+ dragOverIndex = null;
179
+ return;
180
+ }
181
+ if (sourceIndex < 0 || sourceIndex >= parentNode.value.length) {
182
+ dragOverIndex = null;
183
+ return;
184
+ }
185
+ parentNode.input(swapElements(parentNode.value, sourceIndex, targetIndex), false);
186
+ dragStartIndex = null;
187
+ dragOverIndex = null;
188
+ };
189
+ node.context.dragNodeEnd = () => {
190
+ dragStartIndex = null;
191
+ dragOverIndex = null;
192
+ };
193
+ }
116
194
  });
117
195
  }
@@ -18,19 +18,36 @@ function addInsertButton(label = "Add Item", icon = "i-lucide-plus", styleClass
18
18
  addComponent("UButton", { onClick: "$insertNode($node)", label, icon, size: buttonSize, disabled: "$node.value.length > $maxItems -1" })
19
19
  ], { class: styleClass }, render);
20
20
  }
21
+ function addDragHandle(handleClass = "", iconName = "", render = "true") {
22
+ return addElement("span", [
23
+ addComponent("UIcon", { name: iconName })
24
+ ], {
25
+ "class": handleClass,
26
+ "aria-label": "Drag to reorder"
27
+ }, render);
28
+ }
21
29
  export const nuxtUIRepeaterDefinition = createInput(
22
- addElement("ul", [
30
+ addElement("div", [
23
31
  addList("$listName", [
24
32
  addInsertButton("$insertButtonLabel", "i-lucide-plus", "$insertButtonClass", "$insertButtonSize", "$node.children.length == 0 || $alwaysDisplayInsertButton"),
25
33
  addListGroup([
26
- addElement(
27
- "li",
28
- [{ children: "$slots.default" }, addButtonGroup("$buttonGroupClass", "$buttonGroupItemClass", "$buttonSize", "$renderButtons")],
29
- { class: "$internalListItemClass" }
30
- )
34
+ addElement("div", [
35
+ addDragHandle("$internalDragHandleClass", "$dragHandleIconName", "$renderDragHandle"),
36
+ { children: "$slots.default" },
37
+ addButtonGroup("$buttonGroupClass", "$buttonGroupItemClass", "$buttonSize", "$renderButtons")
38
+ ], {
39
+ id: "$getListItemId($index)",
40
+ class: "$getListItemClass($index)",
41
+ draggable: "$draggable",
42
+ onDragstart: "$dragNodeStart($node.parent, $index)",
43
+ onDragover: "$dragNodeOver($index)",
44
+ onDragleave: "$dragNodeLeave($index)",
45
+ onDrop: "$dropNode($node.parent, $index)",
46
+ onDragend: "$dragNodeEnd"
47
+ })
31
48
  ], true, {})
32
49
  ], true, "true")
33
- ], { class: "$internalListClass" }, true),
50
+ ], { class: "$internalListClass", id: "$internalListId" }, true),
34
51
  {
35
52
  props: [
36
53
  "insertButtonLabel",
@@ -49,7 +66,11 @@ export const nuxtUIRepeaterDefinition = createInput(
49
66
  "displayAddButton",
50
67
  "displayDeleteButton",
51
68
  "minItems",
52
- "maxItems"
69
+ "maxItems",
70
+ "draggable",
71
+ "displayDragHandle",
72
+ "dragHandleClass",
73
+ "dragHandleIconName"
53
74
  ],
54
75
  features: [addRepeaterHandler]
55
76
  }
@@ -62,56 +83,113 @@ function addRepeaterHandler(node) {
62
83
  }
63
84
  return array;
64
85
  };
86
+ const uuid = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2);
65
87
  node.on("created", () => {
66
- node.context.listName = node.name;
67
- node.context.renderButtons = !node.context.hideButtonGroup;
68
- node.context.insertButtonSize = node.context.insertButtonSize ? node.context.insertButtonSize : "md";
69
- node.context.buttonSize = node.context.buttonSize ? node.context.buttonSize : "md";
70
- node.context.renderMoveButtons = !node.context.hideMoveButtons;
71
- node.context.internalListClass = node.context.listClass ? `formkit-items ${node.context.listClass}` : "formkit-items";
72
- node.context.internalListItemClass = node.context.listItemClass ? `formkit-item ${node.context.listItemClass}` : "formkit-item";
73
- node.context.minItems = node.context.minItems !== void 0 ? node.context.minItems : 0;
74
- node.context.maxItems = node.context.maxItems !== void 0 ? node.context.maxItems : Number.POSITIVE_INFINITY;
75
- node.context.insertNode = (parentNode) => () => {
76
- if (parentNode && Array.isArray(parentNode._value)) {
77
- const item = node.context.newItem ? { ...node.context.newItem } : {};
78
- const array = parentNode.value;
79
- array.push(item);
80
- parentNode.input(array, false);
81
- }
82
- };
83
- node.context.removeNode = (parentNode, index) => () => {
84
- if (parentNode && Array.isArray(parentNode._value)) {
85
- parentNode.input(parentNode._value.filter((_, i) => i !== index), false);
86
- }
87
- };
88
- node.context.addNode = (parentNode, index) => () => {
89
- if (parentNode && Array.isArray(parentNode._value)) {
90
- const array = parentNode.value;
91
- const item = node.context.newItem ? { ...node.context.newItem } : {};
92
- array.splice(index + 1, 0, item);
93
- parentNode.input(array, false);
94
- }
95
- };
96
- node.context.cloneNode = (parentNode, index) => () => {
97
- if (parentNode && Array.isArray(parentNode._value)) {
98
- const item = parentNode.value[index];
99
- const array = parentNode.value;
100
- array.splice(index + 1, 0, item);
101
- parentNode.input(array, false);
102
- }
103
- };
104
- node.context.moveNodeUp = (parentNode, index) => () => {
105
- if (parentNode && Array.isArray(parentNode._value)) {
106
- if (index > 0)
107
- parentNode.input(swapElements(parentNode.value, index - 1, index), false);
108
- }
109
- };
110
- node.context.moveNodeDown = (parentNode, index) => () => {
111
- if (parentNode && Array.isArray(parentNode._value)) {
112
- if (index < parentNode.value.length - 1)
113
- parentNode.input(swapElements(parentNode.value, index, index + 1), false);
114
- }
115
- };
88
+ if (node.context) {
89
+ let dragStartIndex = null;
90
+ let dragOverIndex = null;
91
+ const newItem = node.context.newItem || {};
92
+ node.context.listName = node.name;
93
+ node.context.renderButtons = !node.context.hideButtonGroup;
94
+ node.context.insertButtonSize = node.context.insertButtonSize ? node.context.insertButtonSize : "md";
95
+ node.context.buttonSize = node.context.buttonSize ? node.context.buttonSize : "md";
96
+ node.context.renderMoveButtons = !node.context.hideMoveButtons;
97
+ node.context.draggable = !!node.context.draggable;
98
+ node.context.renderDragHandle = !!node.context.displayDragHandle;
99
+ node.context.dragHandleIconName = node.context.dragHandleIconName || "i-lucide-grip-vertical";
100
+ node.context.internalDragHandleClass = node.context.dragHandleClass ? `formkit-repeater-drag-handle ${node.context.dragHandleClass}` : "formkit-repeater-drag-handle";
101
+ node.context.internalListClass = node.context.listClass ? `formkit-items ${node.context.listClass}` : "formkit-items";
102
+ node.context.internalListItemClass = node.context.listItemClass ? `formkit-item ${node.context.listItemClass}` : "formkit-item";
103
+ node.context.internalListId = `formkit-items-${uuid}`;
104
+ node.context.minItems = node.context.minItems !== void 0 ? node.context.minItems : 0;
105
+ node.context.maxItems = node.context.maxItems !== void 0 ? node.context.maxItems : Number.POSITIVE_INFINITY;
106
+ node.context.getListItemClass = (index) => {
107
+ if (dragOverIndex === index && dragStartIndex !== index)
108
+ return `${node.context?.internalListItemClass} formkit-repeater-drop-target`;
109
+ return node.context?.internalListItemClass?.toString() ?? "";
110
+ };
111
+ node.context.getListItemId = (index) => {
112
+ return `formkit-item-${index}-${uuid}`;
113
+ };
114
+ node.context.insertNode = (parentNode) => () => {
115
+ if (parentNode && Array.isArray(parentNode._value)) {
116
+ const newArray = [{ ...newItem }, ...parentNode.value];
117
+ parentNode.input(newArray, false);
118
+ }
119
+ };
120
+ node.context.removeNode = (parentNode, index) => () => {
121
+ if (parentNode && Array.isArray(parentNode._value)) {
122
+ parentNode.input(parentNode._value.filter((_, i) => i !== index), false);
123
+ }
124
+ };
125
+ node.context.addNode = (parentNode, index) => () => {
126
+ if (parentNode && Array.isArray(parentNode._value)) {
127
+ const array = parentNode.value;
128
+ array.splice(index + 1, 0, { ...newItem });
129
+ parentNode.input(array, false);
130
+ }
131
+ };
132
+ node.context.cloneNode = (parentNode, index) => () => {
133
+ if (parentNode && Array.isArray(parentNode._value)) {
134
+ const item = parentNode.value[index];
135
+ const array = parentNode.value;
136
+ array.splice(index + 1, 0, { ...item });
137
+ parentNode.input(array, false);
138
+ }
139
+ };
140
+ node.context.moveNodeUp = (parentNode, index) => () => {
141
+ if (parentNode && Array.isArray(parentNode._value)) {
142
+ if (index > 0)
143
+ parentNode.input(swapElements(parentNode.value, index - 1, index), false);
144
+ }
145
+ };
146
+ node.context.moveNodeDown = (parentNode, index) => () => {
147
+ if (parentNode && Array.isArray(parentNode._value)) {
148
+ if (index < parentNode.value.length - 1)
149
+ parentNode.input(swapElements(parentNode.value, index, index + 1), false);
150
+ }
151
+ };
152
+ node.context.dragNodeStart = (_parentNode, index) => (event) => {
153
+ dragStartIndex = index;
154
+ if (event?.dataTransfer) {
155
+ event.dataTransfer.effectAllowed = "move";
156
+ event.dataTransfer.setData("text/plain", String(index));
157
+ }
158
+ };
159
+ node.context.dragNodeOver = (targetIndex) => (event) => {
160
+ event?.preventDefault();
161
+ dragOverIndex = targetIndex;
162
+ if (event?.dataTransfer)
163
+ event.dataTransfer.dropEffect = "move";
164
+ };
165
+ node.context.dragNodeLeave = (targetIndex) => () => {
166
+ if (dragOverIndex === targetIndex)
167
+ dragOverIndex = null;
168
+ };
169
+ node.context.dropNode = (parentNode, targetIndex) => (event) => {
170
+ event?.preventDefault();
171
+ if (!parentNode || !Array.isArray(parentNode._value)) {
172
+ dragOverIndex = null;
173
+ return;
174
+ }
175
+ const sourceFromEvent = Number.parseInt(event?.dataTransfer?.getData("text/plain") || "", 10);
176
+ const sourceIndex = Number.isInteger(sourceFromEvent) ? sourceFromEvent : dragStartIndex;
177
+ if (sourceIndex === null || sourceIndex === targetIndex) {
178
+ dragOverIndex = null;
179
+ return;
180
+ }
181
+ if (sourceIndex < 0 || sourceIndex >= parentNode.value.length) {
182
+ dragOverIndex = null;
183
+ return;
184
+ }
185
+ parentNode.input(swapElements(parentNode.value, sourceIndex, targetIndex), false);
186
+ dragStartIndex = null;
187
+ dragOverIndex = null;
188
+ };
189
+ node.context.dragNodeEnd = () => {
190
+ dragStartIndex = null;
191
+ dragOverIndex = null;
192
+ };
193
+ }
116
194
  });
117
195
  }
@@ -1,3 +1,6 @@
1
1
  import { defineNuxtPlugin } from "#app";
2
+ import { UButton, UIcon } from "#components";
2
3
  export default defineNuxtPlugin((_nuxtApp) => {
4
+ _nuxtApp.vueApp.component("UButton", UButton);
5
+ _nuxtApp.vueApp.component("UIcon", UIcon);
3
6
  });
@@ -3,7 +3,7 @@ export declare function useFormKitInput(context: FormKitFrameworkContext): {
3
3
  isInvalid: import("vue").ComputedRef<any>;
4
4
  validSlotNames: import("vue").ComputedRef<string[]>;
5
5
  styleClass: import("vue").ComputedRef<string>;
6
- color: import("vue").ComputedRef<"primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral">;
6
+ color: import("vue").ComputedRef<"neutral" | "primary" | "secondary" | "success" | "info" | "warning" | "error">;
7
7
  handleBlur: (event: FocusEvent) => void;
8
8
  handleChange: (_: unknown) => void;
9
9
  handleInput: (_: unknown) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sfxcode/nuxt-ui-formkit",
3
- "version": "1.0.6",
3
+ "version": "1.1.0",
4
4
  "description": "FormKit integration for Nuxt UI - Seamlessly connect FormKit form handling with Nuxt UI components",
5
5
  "author": {
6
6
  "name": "Tom",
@@ -78,7 +78,7 @@
78
78
  "dev": "npm run dev:prepare && nuxi dev playground",
79
79
  "dev:build": "nuxi build playground",
80
80
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
81
- "release": "npm run lint && npm run test && npm run prepack && changelogen --patch --release && npm publish --access=public && git push --follow-tags",
81
+ "release": "npm run lint && npm run test && npm run prepack && changelogen --minor --release && npm publish --access=public && git push --follow-tags",
82
82
  "lint": "eslint .",
83
83
  "test": "vitest run",
84
84
  "test:watch": "vitest watch",
@@ -88,40 +88,49 @@
88
88
  "docs:preview": "vitepress preview docs"
89
89
  },
90
90
  "dependencies": {
91
- "@formkit/addons": "^2.0.0",
92
- "@formkit/nuxt": "^2.0.0",
93
- "@nuxt/kit": "4.4.6",
94
- "@nuxt/ui": "^4.8.2",
95
- "@vue/compiler-dom": "^3.5.35"
91
+ "@formkit/addons": "^2.1.0",
92
+ "@formkit/nuxt": "^2.1.0",
93
+ "@nuxt/kit": "4.4.8",
94
+ "@nuxt/ui": "^4.9.0",
95
+ "@vue/compiler-dom": "^3.5.38"
96
+ },
97
+ "peerDependencies": {
98
+ "vue-i18n": "^11.0.0"
99
+ },
100
+ "peerDependenciesMeta": {
101
+ "vue-i18n": {
102
+ "optional": true
103
+ }
96
104
  },
97
105
  "devDependencies": {
106
+ "@codemirror/lang-json": "^6.0.2",
107
+ "@codemirror/state": "^6.6.0",
108
+ "@codemirror/theme-one-dark": "^6.1.3",
109
+ "@codemirror/view": "^6.43.1",
98
110
  "@iconify-json/heroicons": "^1.2.3",
99
- "@iconify-json/lucide": "^1.2.111",
100
- "@iconify-json/simple-icons": "^1.2.85",
111
+ "@iconify-json/lucide": "^1.2.114",
112
+ "@iconify-json/simple-icons": "^1.2.86",
101
113
  "@nuxt/devtools": "4.0.0-alpha.7",
102
- "@nuxt/eslint-config": "^1.15.2",
114
+ "@nuxt/eslint-config": "^1.16.0",
103
115
  "@nuxt/module-builder": "^1.0.2",
104
- "@nuxt/schema": "4.4.6",
116
+ "@nuxt/schema": "4.4.8",
105
117
  "@nuxt/test-utils": "^4.0.3",
106
118
  "@types/node": "latest",
107
119
  "@vitejs/plugin-vue": "^6.0.7",
108
120
  "changelogen": "^0.6.2",
109
- "eslint": "^10.4.1",
121
+ "codemirror": "^6.0.2",
122
+ "eslint": "^10.5.0",
110
123
  "jsdom": "^29.1.1",
111
124
  "mkdist": "^2.4.1",
112
- "nuxt": "4.4.6",
125
+ "nuxt": "4.4.8",
113
126
  "sass-embedded": "^1.100.0",
114
127
  "typescript": "~6.0.3",
115
128
  "unbuild": "^3.6.1",
116
129
  "vitepress": "2.0.0-alpha.17",
117
- "vitest": "^4.1.8",
118
- "vue": "^3.5.35",
119
- "vue-tsc": "^3.3.3",
120
- "@codemirror/lang-json": "^6.0.2",
121
- "@codemirror/state": "^6.6.0",
122
- "@codemirror/theme-one-dark": "^6.1.3",
123
- "@codemirror/view": "^6.43.0",
124
- "codemirror": "^6.0.2"
130
+ "vitest": "^4.1.9",
131
+ "vue": "^3.5.38",
132
+ "vue-i18n": "^11.4.6",
133
+ "vue-tsc": "^3.3.5"
125
134
  },
126
135
  "packageManager": "pnpm@11.1.2+sha512.415a1cc25974731e75455c1468371be74c5aa5fb7621b50d4056d222451609f11412f23fd602e6169f1e060466641f798597e1be961a10688836a67b16569499"
127
136
  }