@sfxcode/formkit-openvue 0.8.1 → 0.9.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.
package/README.md CHANGED
@@ -49,7 +49,7 @@ Migrating from `@sfxcode/formkit-primevue` to `@sfxcode/formkit-openvue`:
49
49
 
50
50
  5. Update custom CSS: selectors like `[data-type="primeCheckbox"]` become `[data-type="formCheckbox"]`.
51
51
 
52
- Also rename the `primeAttributes` prop to `formAttributes` (`prime-attributes` to `form-attributes` in templates). Rename the i18n keys `formkit.prime.true` / `formkit.prime.false` to `formkit.form.true` / `formkit.form.false`. Not changed: the `p-formkit` wrapper class. The stylesheet is now `formkit-openvue.scss` (update imports of `dist/sass/formkit-primevue.scss`).
52
+ Also rename the i18n keys `formkit.prime.true` / `formkit.prime.false` to `formkit.form.true` / `formkit.form.false`. If you use `useInputEditor`, its data fields `prime`, `prime_key` and `prime_value` are now `form`, `form_key` and `form_value`. The stylesheet is now `formkit-openvue.scss` (update imports of `dist/sass/formkit-primevue.scss`). Not changed: the `p-formkit` wrapper class.
53
53
 
54
54
  ## Build
55
55
 
@@ -63,6 +63,64 @@ Also rename the `primeAttributes` prop to `formAttributes` (`prime-attributes` t
63
63
 
64
64
  [Demo/Playground](https://formkit-openvue.netlify.app/)
65
65
 
66
+ ## Getting Started
67
+
68
+ Install the latest release of [`@sfxcode/formkit-openvue`](https://www.npmjs.com/package/@sfxcode/formkit-openvue) together with OpenVue:
69
+
70
+ ```bash
71
+ pnpm add @sfxcode/formkit-openvue openvue @openvue/themes @openvue/openicons
72
+ # or: npm install ... / yarn add ...
73
+ ```
74
+
75
+ Set up OpenVue, FormKit and the form inputs in your *main.ts*:
76
+
77
+ ```typescript
78
+ import Aura from '@openvue/themes/aura'
79
+ import { defaultConfig, plugin } from '@formkit/vue'
80
+ import { formInputs, useFormInputs } from '@sfxcode/formkit-openvue'
81
+ import OpenVue from 'openvue/config'
82
+ import { createApp } from 'vue'
83
+ import App from './App.vue'
84
+ import '@openvue/openicons/openicons.css'
85
+ import '@sfxcode/formkit-openvue/dist/style.css'
86
+
87
+ const app = createApp(App)
88
+
89
+ // OpenVue with theme
90
+ app.use(OpenVue, { theme: { preset: Aura } })
91
+
92
+ // register the OpenVue components used by the form inputs
93
+ const { registerInputs } = useFormInputs()
94
+ registerInputs(app)
95
+
96
+ // FormKit with the OpenVue inputs
97
+ app.use(plugin, defaultConfig({ inputs: formInputs }))
98
+
99
+ app.mount('#app')
100
+ ```
101
+
102
+ Use the inputs in a FormKit schema (or as `<FormKit type="formInputText" ... />`):
103
+
104
+ ```vue
105
+ <script setup lang="ts">
106
+ import { ref } from 'vue'
107
+
108
+ const data = ref({ email: '' })
109
+ const schema = [
110
+ { $formkit: 'formInputText', name: 'email', label: 'Email', validation: 'required|email' },
111
+ { $formkit: 'formCheckbox', name: 'newsletter', label: 'Subscribe to the newsletter' },
112
+ ]
113
+ </script>
114
+
115
+ <template>
116
+ <FormKit v-model="data" type="form">
117
+ <FormKitSchema :schema="schema" :data="data" />
118
+ </FormKit>
119
+ </template>
120
+ ```
121
+
122
+ See [Usage](#usage) for outputs, i18n and more configuration.
123
+
66
124
  ## Usage
67
125
 
68
126
  ### Configuration
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.formRepeaterDefinition = void 0;
7
7
  var _vue = require("@formkit/vue");
8
8
  var _composables = require("../composables");
9
+ var _clonePlain = require("../utils/clonePlain");
9
10
  const {
10
11
  addList,
11
12
  addElement,
@@ -13,18 +14,21 @@ const {
13
14
  addComponent
14
15
  } = (0, _composables.useFormKitSchema)();
15
16
  function addButtonGroup(buttonGroupClass = "", buttonGroupItemClass = "", buttonSize, render = "true") {
16
- const addActionButtonComponent = (onClick = "", icon = "", severity = "", render2 = "true", disabled = "false") => {
17
+ const addActionButtonComponent = (onClick = "", icon = "", severity = "", render2 = "true", disabled = "false", label = "") => {
18
+ const name = `${label} + " " + ($index + 1)`;
17
19
  return addElement("div", [addComponent("Button", {
18
- onClick,
20
+ "onClick": onClick,
19
21
  icon,
20
22
  severity,
21
23
  disabled,
22
- size: buttonSize
24
+ "size": buttonSize,
25
+ "aria-label": name,
26
+ "title": name
23
27
  })], {
24
28
  class: buttonGroupItemClass
25
29
  }, render2);
26
30
  };
27
- return addElement("div", [addActionButtonComponent("$moveNodeUp($node.parent, $index)", "oi oi-arrow-up", "secondary", "$renderMoveButtons", "$index === 0"), addActionButtonComponent("$removeNode($node.parent, $index)", "oi oi-trash", "danger", "$displayDeleteButton", "$node.parent.value.length === $minItems"), addActionButtonComponent("$cloneNode($node.parent, $index)", "oi oi-clone", "", "$displayCloneButton", "$node.parent.value.length > $maxItems -1"), addActionButtonComponent("$addNode($node.parent, $index)", "oi oi-plus", "", "$displayAddButton", "$node.parent.value.length > $maxItems -1"), addActionButtonComponent("$moveNodeDown($node.parent, $index)", "oi oi-arrow-down", "secondary", "$renderMoveButtons", "$index === $node.parent.value.length -1")], {
31
+ return addElement("div", [addActionButtonComponent("$moveNodeUp($node.parent, $index)", "oi oi-arrow-up", "secondary", "$renderMoveButtons", "$index === 0", "$moveUpLabel"), addActionButtonComponent("$removeNode($node.parent, $index)", "oi oi-trash", "danger", "$displayDeleteButton", "$node.parent.value.length === $minItems", "$deleteLabel"), addActionButtonComponent("$cloneNode($node.parent, $index)", "oi oi-clone", "", "$displayCloneButton", "$node.parent.value.length > $maxItems -1", "$cloneLabel"), addActionButtonComponent("$addNode($node.parent, $index)", "oi oi-plus", "", "$displayAddButton", "$node.parent.value.length > $maxItems -1", "$addLabel"), addActionButtonComponent("$moveNodeDown($node.parent, $index)", "oi oi-arrow-down", "secondary", "$renderMoveButtons", "$index === $node.parent.value.length -1", "$moveDownLabel")], {
28
32
  class: buttonGroupClass
29
33
  }, render);
30
34
  }
@@ -39,6 +43,19 @@ function addInsertButton(label = "Add Item", icon = "i-lucide-plus", styleClass
39
43
  class: styleClass
40
44
  }, render);
41
45
  }
46
+ function addUndoBar(render = "true") {
47
+ return addElement("div", [addElement("div", [addElement("span", ["$deletedLabel"]), addComponent("Button", {
48
+ onClick: "$undoRemoveNode($node)",
49
+ label: "$undoLabel",
50
+ size: "small",
51
+ variant: "text"
52
+ })], {
53
+ class: "formkit-repeater-undo"
54
+ }, "$removedItem")], {
55
+ "role": "status",
56
+ "aria-live": "polite"
57
+ }, render);
58
+ }
42
59
  function addDragHandle(handleClass = "", iconClass = "", render = "true") {
43
60
  return addElement("span", [addElement("i", [], {
44
61
  class: iconClass
@@ -58,13 +75,14 @@ const formRepeaterDefinition = exports.formRepeaterDefinition = (0, _vue.createI
58
75
  onDragleave: "$dragNodeLeave($index)",
59
76
  onDrop: "$dropNode($node.parent, $index)",
60
77
  onDragend: "$dragNodeEnd"
61
- })], true, {})], true, "true", {
62
- value: "$value"
78
+ })], true, {}), addUndoBar("$undoDelete")], true, "true", {
79
+ value: "$value",
80
+ validation: "$repeaterValidation"
63
81
  })], {
64
82
  class: "$internalListClass",
65
83
  id: "$internalListId"
66
84
  }, true), {
67
- props: ["insertButtonLabel", "insertButtonClass", "insertButtonSize", "alwaysDisplayInsertButton", "newItem", "listClass", "listItemClass", "hideButtonGroup", "hideMoveButtons", "buttonGroupClass", "buttonGroupItemClass", "buttonSize", "displayCloneButton", "displayAddButton", "displayDeleteButton", "minItems", "maxItems", "displayDragHandle", "draggable", "dragHandleClass", "dragHandleIconClass"],
85
+ props: ["insertButtonLabel", "insertButtonClass", "insertButtonSize", "alwaysDisplayInsertButton", "newItem", "listClass", "listItemClass", "hideButtonGroup", "hideMoveButtons", "buttonGroupClass", "buttonGroupItemClass", "buttonSize", "displayCloneButton", "displayAddButton", "displayDeleteButton", "minItems", "maxItems", "moveUpLabel", "moveDownLabel", "deleteLabel", "cloneLabel", "addLabel", "undoDelete", "undoLabel", "deletedLabel", "undoTimeout", "displayDragHandle", "draggable", "dragHandleClass", "dragHandleIconClass"],
68
86
  features: [addRepeaterHandler]
69
87
  });
70
88
  function addRepeaterHandler(node) {
@@ -72,12 +90,20 @@ function addRepeaterHandler(node) {
72
90
  array.splice(index2, 0, array.splice(index1, 1)[0]);
73
91
  return array;
74
92
  };
75
- const uuid = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2);
76
93
  node.on("created", () => {
77
94
  if (node.context) {
78
95
  let dragStartIndex = null;
79
- let dragOverIndex = null;
80
- const newItem = node.context.newItem || {};
96
+ const makeNewItem = () => (0, _clonePlain.clonePlain)(node.context?.newItem || {});
97
+ const instanceId = String(node.props.id ?? node.name);
98
+ const context = node.context;
99
+ context.dragOverIndex = null;
100
+ let undoTimer;
101
+ const forgetRemoved = () => {
102
+ clearTimeout(undoTimer);
103
+ undoTimer = void 0;
104
+ context.removedItem = void 0;
105
+ };
106
+ node.on("destroying", () => clearTimeout(undoTimer));
81
107
  node.context.listName = node.name;
82
108
  node.context.renderButtons = !node.context.hideButtonGroup;
83
109
  node.context.insertButtonSize = node.context.insertButtonSize ? node.context.insertButtonSize : "";
@@ -89,39 +115,68 @@ function addRepeaterHandler(node) {
89
115
  node.context.internalDragHandleClass = node.context.dragHandleClass ? `formkit-repeater-drag-handle ${node.context.dragHandleClass}` : "formkit-repeater-drag-handle";
90
116
  node.context.internalListClass = node.context.listClass ? `formkit-items ${node.context.listClass}` : "formkit-items";
91
117
  node.context.internalListItemClass = node.context.listItemClass ? `formkit-item ${node.context.listItemClass}` : "formkit-item";
92
- node.context.internalListId = `formkit-items-${uuid}`;
118
+ node.context.moveUpLabel = node.context.moveUpLabel || "Move item up";
119
+ node.context.moveDownLabel = node.context.moveDownLabel || "Move item down";
120
+ node.context.deleteLabel = node.context.deleteLabel || "Delete item";
121
+ node.context.cloneLabel = node.context.cloneLabel || "Clone item";
122
+ node.context.addLabel = node.context.addLabel || "Add item below";
123
+ node.context.undoDelete = !!node.context.undoDelete;
124
+ node.context.undoLabel = node.context.undoLabel || "Undo";
125
+ node.context.deletedLabel = node.context.deletedLabel || "Item deleted";
126
+ node.context.undoTimeout = node.context.undoTimeout !== void 0 ? Number(node.context.undoTimeout) : 8e3;
127
+ node.context.removedItem = void 0;
128
+ node.context.minItems = node.context.minItems !== void 0 ? node.context.minItems : 0;
129
+ node.context.maxItems = node.context.maxItems !== void 0 ? node.context.maxItems : Number.POSITIVE_INFINITY;
130
+ node.context.repeaterValidation = [["+length", node.context.minItems, node.context.maxItems]];
131
+ node.context.internalListId = `formkit-items-${instanceId}`;
93
132
  node.context.getListItemClass = index => {
94
- if (dragOverIndex === index && dragStartIndex !== index) return `${node.context?.internalListItemClass} formkit-repeater-drop-target`;
133
+ if (context.dragOverIndex === index && dragStartIndex !== index) return `${node.context?.internalListItemClass} formkit-repeater-drop-target`;
95
134
  return node.context?.internalListItemClass?.toString() ?? "";
96
135
  };
97
136
  node.context.getListItemId = index => {
98
- return `formkit-item-${index}-${uuid}`;
137
+ return `formkit-item-${index}-${instanceId}`;
99
138
  };
100
139
  node.context.insertNode = parentNode => () => {
101
140
  if (parentNode && Array.isArray(parentNode._value)) {
102
- const newArray = [{
103
- ...newItem
104
- }, ...parentNode.value];
141
+ const newArray = [makeNewItem(), ...parentNode.value];
105
142
  parentNode.input(newArray, false);
106
143
  }
107
144
  };
108
145
  node.context.removeNode = (parentNode, index) => () => {
109
146
  if (parentNode && Array.isArray(parentNode._value)) {
147
+ const removed = (0, _clonePlain.clonePlain)(parentNode._value[index]);
110
148
  parentNode.input(parentNode._value.filter((_, i) => i !== index), false);
149
+ if (context.undoDelete) {
150
+ clearTimeout(undoTimer);
151
+ context.removedItem = {
152
+ index,
153
+ item: removed
154
+ };
155
+ const timeout = Number(context.undoTimeout);
156
+ undoTimer = timeout > 0 ? setTimeout(forgetRemoved, timeout) : void 0;
157
+ }
158
+ }
159
+ };
160
+ node.context.undoRemoveNode = parentNode => () => {
161
+ const removed = context.removedItem;
162
+ if (removed && parentNode && Array.isArray(parentNode._value) && parentNode._value.length < Number(context.maxItems)) {
163
+ const array = [...parentNode.value];
164
+ array.splice(Math.min(removed.index, array.length), 0, (0, _clonePlain.clonePlain)(removed.item));
165
+ parentNode.input(array, false);
111
166
  }
167
+ forgetRemoved();
112
168
  };
113
169
  node.context.addNode = (parentNode, index) => () => {
114
170
  if (parentNode && Array.isArray(parentNode._value)) {
115
171
  const array = parentNode.value;
116
- array.splice(index + 1, 0, newItem);
172
+ array.splice(index + 1, 0, makeNewItem());
117
173
  parentNode.input(array, false);
118
174
  }
119
175
  };
120
176
  node.context.cloneNode = (parentNode, index) => () => {
121
177
  if (parentNode && Array.isArray(parentNode._value)) {
122
- const item = parentNode.value[index];
123
178
  const array = parentNode.value;
124
- array.splice(index + 1, 0, item);
179
+ array.splice(index + 1, 0, (0, _clonePlain.clonePlain)(array[index]));
125
180
  parentNode.input(array, false);
126
181
  }
127
182
  };
@@ -144,35 +199,35 @@ function addRepeaterHandler(node) {
144
199
  };
145
200
  node.context.dragNodeOver = targetIndex => event => {
146
201
  event?.preventDefault();
147
- dragOverIndex = targetIndex;
202
+ context.dragOverIndex = targetIndex;
148
203
  if (event?.dataTransfer) event.dataTransfer.dropEffect = "move";
149
204
  };
150
205
  node.context.dragNodeLeave = targetIndex => () => {
151
- if (dragOverIndex === targetIndex) dragOverIndex = null;
206
+ if (context.dragOverIndex === targetIndex) context.dragOverIndex = null;
152
207
  };
153
208
  node.context.dropNode = (parentNode, targetIndex) => event => {
154
209
  event?.preventDefault();
155
210
  if (!parentNode || !Array.isArray(parentNode._value)) {
156
- dragOverIndex = null;
211
+ context.dragOverIndex = null;
157
212
  return;
158
213
  }
159
214
  const sourceFromEvent = Number.parseInt(event?.dataTransfer?.getData("text/plain") || "", 10);
160
215
  const sourceIndex = Number.isInteger(sourceFromEvent) ? sourceFromEvent : dragStartIndex;
161
216
  if (sourceIndex === null || sourceIndex === targetIndex) {
162
- dragOverIndex = null;
217
+ context.dragOverIndex = null;
163
218
  return;
164
219
  }
165
220
  if (sourceIndex < 0 || sourceIndex >= parentNode.value.length) {
166
- dragOverIndex = null;
221
+ context.dragOverIndex = null;
167
222
  return;
168
223
  }
169
224
  parentNode.input(swapElements(parentNode.value, sourceIndex, targetIndex), false);
170
225
  dragStartIndex = null;
171
- dragOverIndex = null;
226
+ context.dragOverIndex = null;
172
227
  };
173
228
  node.context.dragNodeEnd = () => {
174
229
  dragStartIndex = null;
175
- dragOverIndex = null;
230
+ context.dragOverIndex = null;
176
231
  };
177
232
  }
178
233
  });
@@ -1,16 +1,18 @@
1
1
  import { createInput } from "@formkit/vue";
2
2
  import { useFormKitSchema } from "../composables/index.mjs";
3
+ import { clonePlain } from "../utils/clonePlain.mjs";
3
4
  const { addList, addElement, addListGroup, addComponent } = useFormKitSchema();
4
5
  function addButtonGroup(buttonGroupClass = "", buttonGroupItemClass = "", buttonSize, render = "true") {
5
- const addActionButtonComponent = (onClick = "", icon = "", severity = "", render2 = "true", disabled = "false") => {
6
- return addElement("div", [addComponent("Button", { onClick, icon, severity, disabled, size: buttonSize })], { class: buttonGroupItemClass }, render2);
6
+ const addActionButtonComponent = (onClick = "", icon = "", severity = "", render2 = "true", disabled = "false", label = "") => {
7
+ const name = `${label} + " " + ($index + 1)`;
8
+ return addElement("div", [addComponent("Button", { "onClick": onClick, icon, severity, disabled, "size": buttonSize, "aria-label": name, "title": name })], { class: buttonGroupItemClass }, render2);
7
9
  };
8
10
  return addElement("div", [
9
- addActionButtonComponent("$moveNodeUp($node.parent, $index)", "oi oi-arrow-up", "secondary", "$renderMoveButtons", "$index === 0"),
10
- addActionButtonComponent("$removeNode($node.parent, $index)", "oi oi-trash", "danger", "$displayDeleteButton", "$node.parent.value.length === $minItems"),
11
- addActionButtonComponent("$cloneNode($node.parent, $index)", "oi oi-clone", "", "$displayCloneButton", "$node.parent.value.length > $maxItems -1"),
12
- addActionButtonComponent("$addNode($node.parent, $index)", "oi oi-plus", "", "$displayAddButton", "$node.parent.value.length > $maxItems -1"),
13
- addActionButtonComponent("$moveNodeDown($node.parent, $index)", "oi oi-arrow-down", "secondary", "$renderMoveButtons", "$index === $node.parent.value.length -1")
11
+ addActionButtonComponent("$moveNodeUp($node.parent, $index)", "oi oi-arrow-up", "secondary", "$renderMoveButtons", "$index === 0", "$moveUpLabel"),
12
+ addActionButtonComponent("$removeNode($node.parent, $index)", "oi oi-trash", "danger", "$displayDeleteButton", "$node.parent.value.length === $minItems", "$deleteLabel"),
13
+ addActionButtonComponent("$cloneNode($node.parent, $index)", "oi oi-clone", "", "$displayCloneButton", "$node.parent.value.length > $maxItems -1", "$cloneLabel"),
14
+ addActionButtonComponent("$addNode($node.parent, $index)", "oi oi-plus", "", "$displayAddButton", "$node.parent.value.length > $maxItems -1", "$addLabel"),
15
+ addActionButtonComponent("$moveNodeDown($node.parent, $index)", "oi oi-arrow-down", "secondary", "$renderMoveButtons", "$index === $node.parent.value.length -1", "$moveDownLabel")
14
16
  ], { class: buttonGroupClass }, render);
15
17
  }
16
18
  function addInsertButton(label = "Add Item", icon = "i-lucide-plus", styleClass = "", buttonSize, render = "true") {
@@ -18,6 +20,14 @@ function addInsertButton(label = "Add Item", icon = "i-lucide-plus", styleClass
18
20
  addComponent("Button", { onClick: "$insertNode($node)", label, icon, size: buttonSize, disabled: "$node.value.length > $maxItems -1" })
19
21
  ], { class: styleClass }, render);
20
22
  }
23
+ function addUndoBar(render = "true") {
24
+ return addElement("div", [
25
+ addElement("div", [
26
+ addElement("span", ["$deletedLabel"]),
27
+ addComponent("Button", { onClick: "$undoRemoveNode($node)", label: "$undoLabel", size: "small", variant: "text" })
28
+ ], { class: "formkit-repeater-undo" }, "$removedItem")
29
+ ], { "role": "status", "aria-live": "polite" }, render);
30
+ }
21
31
  function addDragHandle(handleClass = "", iconClass = "", render = "true") {
22
32
  return addElement("span", [
23
33
  addElement("i", [], { class: iconClass })
@@ -45,11 +55,12 @@ export const formRepeaterDefinition = createInput(
45
55
  onDrop: "$dropNode($node.parent, $index)",
46
56
  onDragend: "$dragNodeEnd"
47
57
  })
48
- ], true, {})
49
- ], true, "true", { value: "$value" })
58
+ ], true, {}),
59
+ addUndoBar("$undoDelete")
60
+ ], true, "true", { value: "$value", validation: "$repeaterValidation" })
50
61
  ], { class: "$internalListClass", id: "$internalListId" }, true),
51
62
  {
52
- props: ["insertButtonLabel", "insertButtonClass", "insertButtonSize", "alwaysDisplayInsertButton", "newItem", "listClass", "listItemClass", "hideButtonGroup", "hideMoveButtons", "buttonGroupClass", "buttonGroupItemClass", "buttonSize", "displayCloneButton", "displayAddButton", "displayDeleteButton", "minItems", "maxItems", "displayDragHandle", "draggable", "dragHandleClass", "dragHandleIconClass"],
63
+ props: ["insertButtonLabel", "insertButtonClass", "insertButtonSize", "alwaysDisplayInsertButton", "newItem", "listClass", "listItemClass", "hideButtonGroup", "hideMoveButtons", "buttonGroupClass", "buttonGroupItemClass", "buttonSize", "displayCloneButton", "displayAddButton", "displayDeleteButton", "minItems", "maxItems", "moveUpLabel", "moveDownLabel", "deleteLabel", "cloneLabel", "addLabel", "undoDelete", "undoLabel", "deletedLabel", "undoTimeout", "displayDragHandle", "draggable", "dragHandleClass", "dragHandleIconClass"],
53
64
  features: [addRepeaterHandler]
54
65
  }
55
66
  );
@@ -58,12 +69,20 @@ function addRepeaterHandler(node) {
58
69
  array.splice(index2, 0, array.splice(index1, 1)[0]);
59
70
  return array;
60
71
  };
61
- const uuid = typeof crypto !== "undefined" && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2);
62
72
  node.on("created", () => {
63
73
  if (node.context) {
64
74
  let dragStartIndex = null;
65
- let dragOverIndex = null;
66
- const newItem = node.context.newItem || {};
75
+ const makeNewItem = () => clonePlain(node.context?.newItem || {});
76
+ const instanceId = String(node.props.id ?? node.name);
77
+ const context = node.context;
78
+ context.dragOverIndex = null;
79
+ let undoTimer;
80
+ const forgetRemoved = () => {
81
+ clearTimeout(undoTimer);
82
+ undoTimer = void 0;
83
+ context.removedItem = void 0;
84
+ };
85
+ node.on("destroying", () => clearTimeout(undoTimer));
67
86
  node.context.listName = node.name;
68
87
  node.context.renderButtons = !node.context.hideButtonGroup;
69
88
  node.context.insertButtonSize = node.context.insertButtonSize ? node.context.insertButtonSize : "";
@@ -75,38 +94,66 @@ function addRepeaterHandler(node) {
75
94
  node.context.internalDragHandleClass = node.context.dragHandleClass ? `formkit-repeater-drag-handle ${node.context.dragHandleClass}` : "formkit-repeater-drag-handle";
76
95
  node.context.internalListClass = node.context.listClass ? `formkit-items ${node.context.listClass}` : "formkit-items";
77
96
  node.context.internalListItemClass = node.context.listItemClass ? `formkit-item ${node.context.listItemClass}` : "formkit-item";
78
- node.context.internalListId = `formkit-items-${uuid}`;
97
+ node.context.moveUpLabel = node.context.moveUpLabel || "Move item up";
98
+ node.context.moveDownLabel = node.context.moveDownLabel || "Move item down";
99
+ node.context.deleteLabel = node.context.deleteLabel || "Delete item";
100
+ node.context.cloneLabel = node.context.cloneLabel || "Clone item";
101
+ node.context.addLabel = node.context.addLabel || "Add item below";
102
+ node.context.undoDelete = !!node.context.undoDelete;
103
+ node.context.undoLabel = node.context.undoLabel || "Undo";
104
+ node.context.deletedLabel = node.context.deletedLabel || "Item deleted";
105
+ node.context.undoTimeout = node.context.undoTimeout !== void 0 ? Number(node.context.undoTimeout) : 8e3;
106
+ node.context.removedItem = void 0;
107
+ node.context.minItems = node.context.minItems !== void 0 ? node.context.minItems : 0;
108
+ node.context.maxItems = node.context.maxItems !== void 0 ? node.context.maxItems : Number.POSITIVE_INFINITY;
109
+ node.context.repeaterValidation = [["+length", node.context.minItems, node.context.maxItems]];
110
+ node.context.internalListId = `formkit-items-${instanceId}`;
79
111
  node.context.getListItemClass = (index) => {
80
- if (dragOverIndex === index && dragStartIndex !== index)
112
+ if (context.dragOverIndex === index && dragStartIndex !== index)
81
113
  return `${node.context?.internalListItemClass} formkit-repeater-drop-target`;
82
114
  return node.context?.internalListItemClass?.toString() ?? "";
83
115
  };
84
116
  node.context.getListItemId = (index) => {
85
- return `formkit-item-${index}-${uuid}`;
117
+ return `formkit-item-${index}-${instanceId}`;
86
118
  };
87
119
  node.context.insertNode = (parentNode) => () => {
88
120
  if (parentNode && Array.isArray(parentNode._value)) {
89
- const newArray = [{ ...newItem }, ...parentNode.value];
121
+ const newArray = [makeNewItem(), ...parentNode.value];
90
122
  parentNode.input(newArray, false);
91
123
  }
92
124
  };
93
125
  node.context.removeNode = (parentNode, index) => () => {
94
126
  if (parentNode && Array.isArray(parentNode._value)) {
127
+ const removed = clonePlain(parentNode._value[index]);
95
128
  parentNode.input(parentNode._value.filter((_, i) => i !== index), false);
129
+ if (context.undoDelete) {
130
+ clearTimeout(undoTimer);
131
+ context.removedItem = { index, item: removed };
132
+ const timeout = Number(context.undoTimeout);
133
+ undoTimer = timeout > 0 ? setTimeout(forgetRemoved, timeout) : void 0;
134
+ }
135
+ }
136
+ };
137
+ node.context.undoRemoveNode = (parentNode) => () => {
138
+ const removed = context.removedItem;
139
+ if (removed && parentNode && Array.isArray(parentNode._value) && parentNode._value.length < Number(context.maxItems)) {
140
+ const array = [...parentNode.value];
141
+ array.splice(Math.min(removed.index, array.length), 0, clonePlain(removed.item));
142
+ parentNode.input(array, false);
96
143
  }
144
+ forgetRemoved();
97
145
  };
98
146
  node.context.addNode = (parentNode, index) => () => {
99
147
  if (parentNode && Array.isArray(parentNode._value)) {
100
148
  const array = parentNode.value;
101
- array.splice(index + 1, 0, newItem);
149
+ array.splice(index + 1, 0, makeNewItem());
102
150
  parentNode.input(array, false);
103
151
  }
104
152
  };
105
153
  node.context.cloneNode = (parentNode, index) => () => {
106
154
  if (parentNode && Array.isArray(parentNode._value)) {
107
- const item = parentNode.value[index];
108
155
  const array = parentNode.value;
109
- array.splice(index + 1, 0, item);
156
+ array.splice(index + 1, 0, clonePlain(array[index]));
110
157
  parentNode.input(array, false);
111
158
  }
112
159
  };
@@ -131,37 +178,37 @@ function addRepeaterHandler(node) {
131
178
  };
132
179
  node.context.dragNodeOver = (targetIndex) => (event) => {
133
180
  event?.preventDefault();
134
- dragOverIndex = targetIndex;
181
+ context.dragOverIndex = targetIndex;
135
182
  if (event?.dataTransfer)
136
183
  event.dataTransfer.dropEffect = "move";
137
184
  };
138
185
  node.context.dragNodeLeave = (targetIndex) => () => {
139
- if (dragOverIndex === targetIndex)
140
- dragOverIndex = null;
186
+ if (context.dragOverIndex === targetIndex)
187
+ context.dragOverIndex = null;
141
188
  };
142
189
  node.context.dropNode = (parentNode, targetIndex) => (event) => {
143
190
  event?.preventDefault();
144
191
  if (!parentNode || !Array.isArray(parentNode._value)) {
145
- dragOverIndex = null;
192
+ context.dragOverIndex = null;
146
193
  return;
147
194
  }
148
195
  const sourceFromEvent = Number.parseInt(event?.dataTransfer?.getData("text/plain") || "", 10);
149
196
  const sourceIndex = Number.isInteger(sourceFromEvent) ? sourceFromEvent : dragStartIndex;
150
197
  if (sourceIndex === null || sourceIndex === targetIndex) {
151
- dragOverIndex = null;
198
+ context.dragOverIndex = null;
152
199
  return;
153
200
  }
154
201
  if (sourceIndex < 0 || sourceIndex >= parentNode.value.length) {
155
- dragOverIndex = null;
202
+ context.dragOverIndex = null;
156
203
  return;
157
204
  }
158
205
  parentNode.input(swapElements(parentNode.value, sourceIndex, targetIndex), false);
159
206
  dragStartIndex = null;
160
- dragOverIndex = null;
207
+ context.dragOverIndex = null;
161
208
  };
162
209
  node.context.dragNodeEnd = () => {
163
210
  dragStartIndex = null;
164
- dragOverIndex = null;
211
+ context.dragOverIndex = null;
165
212
  };
166
213
  }
167
214
  });
@@ -0,0 +1,9 @@
1
+ import type { AutoAnimateOptions } from '@formkit/auto-animate';
2
+ import type { FormKitNode } from '@formkit/core';
3
+ /** Sections to animate, per input type. `global` applies to every input. */
4
+ export type AutoAnimateTargets = Record<string, string[]>;
5
+ /**
6
+ * Drop-in replacement for `createAutoAnimatePlugin` from `@formkit/addons` with the same
7
+ * arguments, that does not stack animations on an element after inputs are added to it.
8
+ */
9
+ export declare function createAutoAnimatePlugin(options?: Partial<AutoAnimateOptions>, targets?: AutoAnimateTargets): (node: FormKitNode) => void;
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createAutoAnimatePlugin = createAutoAnimatePlugin;
7
+ var _autoAnimate = _interopRequireDefault(require("@formkit/auto-animate"));
8
+ var _core = require("@formkit/core");
9
+ var _inputs = require("@formkit/inputs");
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ const DEFAULT_KEY = "true";
12
+ const optionsByKey = /* @__PURE__ */new Map();
13
+ const attached = /* @__PURE__ */new WeakSet();
14
+ const pendingIds = /* @__PURE__ */new Set();
15
+ let observer = null;
16
+ let attachTimer;
17
+ function attachNewTargets() {
18
+ if (typeof document === "undefined") return;
19
+ document.querySelectorAll("[data-auto-animate]").forEach(target => {
20
+ if (attached.has(target)) return;
21
+ attached.add(target);
22
+ (0, _autoAnimate.default)(target, optionsByKey.get(target.getAttribute("data-auto-animate") ?? "") ?? {});
23
+ });
24
+ }
25
+ function checkPendingIds() {
26
+ if (typeof document === "undefined") return;
27
+ pendingIds.forEach(id => {
28
+ if (!document.getElementById(id)) return;
29
+ pendingIds.delete(id);
30
+ clearTimeout(attachTimer);
31
+ attachTimer = setTimeout(attachNewTargets, 250);
32
+ });
33
+ }
34
+ function observeUntilRendered() {
35
+ if (observer || typeof document === "undefined") return;
36
+ checkPendingIds();
37
+ if (!pendingIds.size) return;
38
+ observer = new MutationObserver(() => {
39
+ checkPendingIds();
40
+ if (!pendingIds.size) {
41
+ observer?.disconnect();
42
+ observer = null;
43
+ }
44
+ });
45
+ observer.observe(document, {
46
+ childList: true,
47
+ subtree: true
48
+ });
49
+ }
50
+ function createAutoAnimatePlugin(options = {}, targets = {}) {
51
+ optionsByKey.set(DEFAULT_KEY, options);
52
+ return node => {
53
+ node.on("created", () => {
54
+ if (typeof node.props.definition?.schema !== "function") return;
55
+ const typeTargets = targets[node.props.type] ?? [];
56
+ const originalSchema = node.props.definition.schema;
57
+ node.props.definition.schema = extensions => {
58
+ const schema = originalSchema(extensions);
59
+ const finalSchema = Array.isArray(schema) ? schema[0] : schema;
60
+ let marked = false;
61
+ (0, _inputs.eachSection)(finalSchema, section => {
62
+ if (!(0, _core.isDOM)(section)) return;
63
+ let key;
64
+ const meta = section.meta;
65
+ if (meta?.autoAnimate) {
66
+ key = DEFAULT_KEY;
67
+ if (typeof meta.autoAnimate === "object") {
68
+ key = `${node.props.id}-${meta.section ?? "section"}`;
69
+ optionsByKey.set(key, {
70
+ ...options,
71
+ ...meta.autoAnimate
72
+ });
73
+ }
74
+ } else {
75
+ const sectionName = meta?.section;
76
+ if (typeof sectionName === "string" && (targets.global?.includes(sectionName) || typeTargets.includes(sectionName))) key = DEFAULT_KEY;
77
+ }
78
+ if (key === void 0) return;
79
+ section.attrs = {
80
+ ...section.attrs,
81
+ "data-auto-animate": key
82
+ };
83
+ marked = true;
84
+ });
85
+ if (marked && node.props.id && typeof window !== "undefined") {
86
+ pendingIds.add(node.props.id);
87
+ observeUntilRendered();
88
+ }
89
+ return finalSchema;
90
+ };
91
+ });
92
+ };
93
+ }
@@ -0,0 +1,87 @@
1
+ import autoAnimate from "@formkit/auto-animate";
2
+ import { isDOM } from "@formkit/core";
3
+ import { eachSection } from "@formkit/inputs";
4
+ const DEFAULT_KEY = "true";
5
+ const optionsByKey = /* @__PURE__ */ new Map();
6
+ const attached = /* @__PURE__ */ new WeakSet();
7
+ const pendingIds = /* @__PURE__ */ new Set();
8
+ let observer = null;
9
+ let attachTimer;
10
+ function attachNewTargets() {
11
+ if (typeof document === "undefined")
12
+ return;
13
+ document.querySelectorAll("[data-auto-animate]").forEach((target) => {
14
+ if (attached.has(target))
15
+ return;
16
+ attached.add(target);
17
+ autoAnimate(target, optionsByKey.get(target.getAttribute("data-auto-animate") ?? "") ?? {});
18
+ });
19
+ }
20
+ function checkPendingIds() {
21
+ if (typeof document === "undefined")
22
+ return;
23
+ pendingIds.forEach((id) => {
24
+ if (!document.getElementById(id))
25
+ return;
26
+ pendingIds.delete(id);
27
+ clearTimeout(attachTimer);
28
+ attachTimer = setTimeout(attachNewTargets, 250);
29
+ });
30
+ }
31
+ function observeUntilRendered() {
32
+ if (observer || typeof document === "undefined")
33
+ return;
34
+ checkPendingIds();
35
+ if (!pendingIds.size)
36
+ return;
37
+ observer = new MutationObserver(() => {
38
+ checkPendingIds();
39
+ if (!pendingIds.size) {
40
+ observer?.disconnect();
41
+ observer = null;
42
+ }
43
+ });
44
+ observer.observe(document, { childList: true, subtree: true });
45
+ }
46
+ export function createAutoAnimatePlugin(options = {}, targets = {}) {
47
+ optionsByKey.set(DEFAULT_KEY, options);
48
+ return (node) => {
49
+ node.on("created", () => {
50
+ if (typeof node.props.definition?.schema !== "function")
51
+ return;
52
+ const typeTargets = targets[node.props.type] ?? [];
53
+ const originalSchema = node.props.definition.schema;
54
+ node.props.definition.schema = (extensions) => {
55
+ const schema = originalSchema(extensions);
56
+ const finalSchema = Array.isArray(schema) ? schema[0] : schema;
57
+ let marked = false;
58
+ eachSection(finalSchema, (section) => {
59
+ if (!isDOM(section))
60
+ return;
61
+ let key;
62
+ const meta = section.meta;
63
+ if (meta?.autoAnimate) {
64
+ key = DEFAULT_KEY;
65
+ if (typeof meta.autoAnimate === "object") {
66
+ key = `${node.props.id}-${meta.section ?? "section"}`;
67
+ optionsByKey.set(key, { ...options, ...meta.autoAnimate });
68
+ }
69
+ } else {
70
+ const sectionName = meta?.section;
71
+ if (typeof sectionName === "string" && (targets.global?.includes(sectionName) || typeTargets.includes(sectionName)))
72
+ key = DEFAULT_KEY;
73
+ }
74
+ if (key === void 0)
75
+ return;
76
+ section.attrs = { ...section.attrs, "data-auto-animate": key };
77
+ marked = true;
78
+ });
79
+ if (marked && node.props.id && typeof window !== "undefined") {
80
+ pendingIds.add(node.props.id);
81
+ observeUntilRendered();
82
+ }
83
+ return finalSchema;
84
+ };
85
+ });
86
+ };
87
+ }
@@ -1,3 +1,5 @@
1
1
  import type { FormKitNode } from '@formkit/core';
2
2
  export declare function addFormAsteriskPlugin(node: FormKitNode): void;
3
3
  export declare function addLabelPlugin(node: FormKitNode): void;
4
+ export { createAutoAnimatePlugin } from './autoAnimate';
5
+ export type { AutoAnimateTargets } from './autoAnimate';
@@ -5,6 +5,13 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.addFormAsteriskPlugin = addFormAsteriskPlugin;
7
7
  exports.addLabelPlugin = addLabelPlugin;
8
+ Object.defineProperty(exports, "createAutoAnimatePlugin", {
9
+ enumerable: true,
10
+ get: function () {
11
+ return _autoAnimate.createAutoAnimatePlugin;
12
+ }
13
+ });
14
+ var _autoAnimate = require("./autoAnimate");
8
15
  function addFormAsteriskPlugin(node) {
9
16
  if (!/^form[A-Z]/.test(node.props.type) || node.props.type.startsWith("formOutput")) return;
10
17
  node.on("created", () => {
@@ -53,3 +53,4 @@ export function addLabelPlugin(node) {
53
53
  }
54
54
  });
55
55
  }
56
+ export { createAutoAnimatePlugin } from "./autoAnimate.mjs";
@@ -314,7 +314,8 @@ $grid-breakpoints: (
314
314
  align-items: stretch;
315
315
  gap: 1rem;
316
316
  width: 100%;
317
- min-width: 600px;
317
+ // never wider than the container it is in
318
+ min-width: min(600px, 100%);
318
319
  }
319
320
 
320
321
  .p-formkit-transfer-list-container {
@@ -333,6 +334,36 @@ $grid-breakpoints: (
333
334
  gap: 0.5rem;
334
335
  }
335
336
 
337
+ // Repeater: the bar that offers to put back a deleted row
338
+ .formkit-repeater-undo {
339
+ display: flex;
340
+ align-items: center;
341
+ gap: 0.5rem;
342
+ padding: 0.25rem 0.5rem;
343
+ margin-top: 0.5rem;
344
+ border: 1px solid var(--p-content-border-color);
345
+ border-radius: var(--p-content-border-radius);
346
+ background: var(--p-content-hover-background);
347
+ font-size: 0.875rem;
348
+ }
349
+
350
+ // Narrow screens: the lists are stacked, the buttons sit between them in a row and their arrows point down and up.
351
+ @media (max-width: 640px) {
352
+ .p-formkit-transfer {
353
+ flex-direction: column;
354
+ min-width: 0;
355
+ }
356
+
357
+ .p-formkit-transfer-buttons {
358
+ flex-direction: row;
359
+ flex-wrap: wrap;
360
+
361
+ .oi {
362
+ transform: rotate(90deg);
363
+ }
364
+ }
365
+ }
366
+
336
367
  .p-formkit-transfer-option {
337
368
  width: 100%;
338
369
  }
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- :root{--formkit-error-color: #ef9a9a}.formkit-form .formkit-messages{margin:.125rem 0;padding-top:.5rem;padding-left:.5rem}.formkit-form .formkit-message{list-style:none;padding:0;margin:0;color:var(--formkit-error-color);font-size:.8rem}.formkit-form .formkit-outer{padding-bottom:.8rem}.formkit-form .formkit-outer .formkit-messages{margin:.125rem 0;padding-top:.25rem;padding-left:0}.formkit-form .formkit-outer .formkit-inner .p-formkit .p-formkit-icon{box-sizing:border-box;width:100%}.formkit-form .formkit-outer .formkit-inner .p-formkit .p-inputtext,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-textarea,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-password,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-multiselect,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-select,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-editor{box-sizing:border-box;width:100%}.formkit-form .formkit-outer .formkit-inner .p-formkit .p-inputtext.p-colorpicker-preview,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-textarea.p-colorpicker-preview,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-password.p-colorpicker-preview,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-multiselect.p-colorpicker-preview,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-select.p-colorpicker-preview,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-editor.p-colorpicker-preview{width:2rem}.formkit-form .formkit-outer .formkit-help{margin:.25rem 0 0 0;font-size:.8rem;color:var(--text-color-secondary)}.formkit-form .formkit-label{display:block;margin:0;padding-bottom:.5rem;font-weight:bold;font-size:.8rem}.formkit-form .p-formkit>*{margin-right:.5rem}.formkit-form .p-formkit>*:last-child,.formkit-form .p-formkit>*:only-child{margin-right:0}.formkit-form .p-formkit-options{display:flex;flex-wrap:wrap;gap:.5rem}.formkit-form .p-formkit-options .p-formkit-option{display:flex;align-items:center}.formkit-form .p-formkit-options .p-formkit-option label{margin-left:.5rem}.formkit-form .formkit-fieldset{margin:0;padding:0;border-radius:0;border:0}.formkit-form .formkit-fieldset:focus-within{border:0}.formkit-form .formkit-fieldset>.formkit-help{margin-top:0;margin-bottom:0}.formkit-form .formkit-legend{display:block;margin:0;padding:0}.formkit-form .formkit-actions{padding-top:.5rem;display:flex}.formkit-form .formkit-actions button{margin-right:.5rem}.formkit-form .p-action-buttons{margin-top:.25rem}.formkit-form .p-action-buttons .p-button{margin-right:.5rem}.formkit-form .p-action-buttons span .p-space{margin-right:3rem}.formkit-form .p-chip-item{align-items:center;background:var(--p-surface-500);color:var(--p-surface-0);border-radius:1rem;padding:.2rem .5rem}.formkit-form .formkit-repeater-drag-handle{display:inline-flex;align-items:center;cursor:grab;user-select:none}.formkit-form .formkit-item[draggable=true]{cursor:grab}.formkit-form .formkit-item[draggable=true]:active{cursor:grabbing}.formkit-form .formkit-item[draggable=true].formkit-repeater-drop-target{outline:1px dashed var(--p-primary-color, #3b82f6);outline-offset:2px;background:color-mix(in srgb, var(--p-primary-color, #3b82f6) 12%, transparent)}.p-formkit-data-view .formkit-outer{padding-bottom:.5rem}.p-formkit-data-view.form-horizontal{padding-bottom:.8rem}.p-formkit-data-view .formkit-help{padding-top:.25rem;margin:0}.p-formkit-data-view ul,.p-formkit-data-view ol{padding-inline-start:1rem;margin-block-start:0;margin-block-end:0}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper{display:flex;flex-wrap:wrap}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper .formkit-inner{width:auto !important}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label{width:auto;order:2;padding:.125rem 0}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:after{content:""}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label+.formkit-inner{margin-left:0 !important;order:1;flex-basis:2rem;flex-grow:0;flex-shrink:0;overflow:hidden}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label+.formkit-inner:has(label){flex-grow:1;flex-basis:100%}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:first-child:nth-last-child(3),.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:first-child:nth-last-child(3)~label{width:auto}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:first-child:nth-last-child(3){order:1}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:first-child:nth-last-child(3)+div.p-checkbox{order:2;width:auto}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:first-child:nth-last-child(3)~label{order:3}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper .formkit-inner:first-child{margin-left:0 !important}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper .formkit-inner:first-child .p-formkit{display:flex}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper .p-checkbox:not(:only-child){width:2rem;overflow:hidden}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-help{width:auto !important}.p-formkit-transfer{display:flex;align-items:stretch;gap:1rem;width:100%;min-width:600px}.p-formkit-transfer-list-container{display:flex;flex-direction:column;flex:1;gap:.5rem;min-width:0}.p-formkit-transfer-buttons{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem}.p-formkit-transfer-option{width:100%}.p-formkit-transfer-option-draggable{cursor:grab}.p-formkit-transfer-option-draggable:active{cursor:grabbing}.p-formkit-data-debug pre,.p-formkit-data-debug span{font-size:.75rem;line-height:1rem}@media(min-width: 1024px){.formkit-form{display:flex;flex-wrap:wrap;margin-left:-0.5rem;margin-right:-0.5rem}.formkit-form>*{flex-shrink:0;width:100%;max-width:100%;padding-left:.5rem;padding-right:.5rem}.col-1{width:8.3333333333%}.col-2{width:16.6666666667%}.col-3{width:25%}.col-4{width:33.3333333333%}.col-5{width:41.6666666667%}.col-6{width:50%}.col-7{width:58.3333333333%}.col-8{width:66.6666666667%}.col-9{width:75%}.col-10{width:83.3333333333%}.col-11{width:91.6666666667%}.col-12{width:100%}}@media(min-width: 768px){.formkit-form.form-horizontal .formkit-wrapper{display:flex}.formkit-form.form-horizontal .formkit-wrapper label{display:inline-block;padding:0 .25rem 0 0;font-size:inherit}.formkit-form.form-horizontal .formkit-wrapper label:after{content:":"}}@media(min-width: 768px)and (min-width: 768px){.formkit-form.form-horizontal.form-horizontal-checkbox-indent .formkit-outer[data-type=formCheckbox]{padding-left:33.3333333333%}}@media(min-width: 768px){.p-formkit-data-view .formkit-form.form-horizontal label{white-space:nowrap}.p-formkit-data-edit .formkit-form.form-horizontal .formkit-outer{width:100%}.p-formkit-data-edit .formkit-form.form-horizontal .formkit-outer label{width:33.3333333333%;padding-top:.25rem;line-height:normal}.p-formkit-data-edit .formkit-form.form-horizontal .formkit-outer .formkit-inner{width:66.6666666667%}.p-formkit-data-edit .formkit-form.form-horizontal div[data-type=formCheckbox] .formkit-inner{margin-left:auto}.p-formkit-data-edit .formkit-form.form-horizontal div[data-type=formCheckbox] .formkit-inner .p-formkit{display:flex}.p-formkit-data-edit .formkit-form.form-horizontal div[data-type=formCheckbox] .formkit-inner label{width:auto;padding:0}.p-formkit-data-edit .formkit-form.form-horizontal .formkit-help,.p-formkit-data-edit .formkit-form.form-horizontal .formkit-messages{width:66.6666666667%;margin-left:auto}}
1
+ :root{--formkit-error-color: #ef9a9a}.formkit-form .formkit-messages{margin:.125rem 0;padding-top:.5rem;padding-left:.5rem}.formkit-form .formkit-message{list-style:none;padding:0;margin:0;color:var(--formkit-error-color);font-size:.8rem}.formkit-form .formkit-outer{padding-bottom:.8rem}.formkit-form .formkit-outer .formkit-messages{margin:.125rem 0;padding-top:.25rem;padding-left:0}.formkit-form .formkit-outer .formkit-inner .p-formkit .p-formkit-icon{box-sizing:border-box;width:100%}.formkit-form .formkit-outer .formkit-inner .p-formkit .p-inputtext,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-textarea,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-password,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-multiselect,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-select,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-editor{box-sizing:border-box;width:100%}.formkit-form .formkit-outer .formkit-inner .p-formkit .p-inputtext.p-colorpicker-preview,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-textarea.p-colorpicker-preview,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-password.p-colorpicker-preview,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-multiselect.p-colorpicker-preview,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-select.p-colorpicker-preview,.formkit-form .formkit-outer .formkit-inner .p-formkit .p-editor.p-colorpicker-preview{width:2rem}.formkit-form .formkit-outer .formkit-help{margin:.25rem 0 0 0;font-size:.8rem;color:var(--text-color-secondary)}.formkit-form .formkit-label{display:block;margin:0;padding-bottom:.5rem;font-weight:bold;font-size:.8rem}.formkit-form .p-formkit>*{margin-right:.5rem}.formkit-form .p-formkit>*:last-child,.formkit-form .p-formkit>*:only-child{margin-right:0}.formkit-form .p-formkit-options{display:flex;flex-wrap:wrap;gap:.5rem}.formkit-form .p-formkit-options .p-formkit-option{display:flex;align-items:center}.formkit-form .p-formkit-options .p-formkit-option label{margin-left:.5rem}.formkit-form .formkit-fieldset{margin:0;padding:0;border-radius:0;border:0}.formkit-form .formkit-fieldset:focus-within{border:0}.formkit-form .formkit-fieldset>.formkit-help{margin-top:0;margin-bottom:0}.formkit-form .formkit-legend{display:block;margin:0;padding:0}.formkit-form .formkit-actions{padding-top:.5rem;display:flex}.formkit-form .formkit-actions button{margin-right:.5rem}.formkit-form .p-action-buttons{margin-top:.25rem}.formkit-form .p-action-buttons .p-button{margin-right:.5rem}.formkit-form .p-action-buttons span .p-space{margin-right:3rem}.formkit-form .p-chip-item{align-items:center;background:var(--p-surface-500);color:var(--p-surface-0);border-radius:1rem;padding:.2rem .5rem}.formkit-form .formkit-repeater-drag-handle{display:inline-flex;align-items:center;cursor:grab;user-select:none}.formkit-form .formkit-item[draggable=true]{cursor:grab}.formkit-form .formkit-item[draggable=true]:active{cursor:grabbing}.formkit-form .formkit-item[draggable=true].formkit-repeater-drop-target{outline:1px dashed var(--p-primary-color, #3b82f6);outline-offset:2px;background:color-mix(in srgb, var(--p-primary-color, #3b82f6) 12%, transparent)}.p-formkit-data-view .formkit-outer{padding-bottom:.5rem}.p-formkit-data-view.form-horizontal{padding-bottom:.8rem}.p-formkit-data-view .formkit-help{padding-top:.25rem;margin:0}.p-formkit-data-view ul,.p-formkit-data-view ol{padding-inline-start:1rem;margin-block-start:0;margin-block-end:0}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper{display:flex;flex-wrap:wrap}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper .formkit-inner{width:auto !important}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label{width:auto;order:2;padding:.125rem 0}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:after{content:""}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label+.formkit-inner{margin-left:0 !important;order:1;flex-basis:2rem;flex-grow:0;flex-shrink:0;overflow:hidden}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label+.formkit-inner:has(label){flex-grow:1;flex-basis:100%}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:first-child:nth-last-child(3),.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:first-child:nth-last-child(3)~label{width:auto}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:first-child:nth-last-child(3){order:1}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:first-child:nth-last-child(3)+div.p-checkbox{order:2;width:auto}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper label:first-child:nth-last-child(3)~label{order:3}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper .formkit-inner:first-child{margin-left:0 !important}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper .formkit-inner:first-child .p-formkit{display:flex}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-wrapper .p-checkbox:not(:only-child){width:2rem;overflow:hidden}.p-formkit-data-edit .formkit-outer[data-type=formCheckbox] .formkit-help{width:auto !important}.p-formkit-transfer{display:flex;align-items:stretch;gap:1rem;width:100%;min-width:min(600px,100%)}.p-formkit-transfer-list-container{display:flex;flex-direction:column;flex:1;gap:.5rem;min-width:0}.p-formkit-transfer-buttons{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem}.formkit-repeater-undo{display:flex;align-items:center;gap:.5rem;padding:.25rem .5rem;margin-top:.5rem;border:1px solid var(--p-content-border-color);border-radius:var(--p-content-border-radius);background:var(--p-content-hover-background);font-size:.875rem}@media(max-width: 640px){.p-formkit-transfer{flex-direction:column;min-width:0}.p-formkit-transfer-buttons{flex-direction:row;flex-wrap:wrap}.p-formkit-transfer-buttons .oi{transform:rotate(90deg)}}.p-formkit-transfer-option{width:100%}.p-formkit-transfer-option-draggable{cursor:grab}.p-formkit-transfer-option-draggable:active{cursor:grabbing}.p-formkit-data-debug pre,.p-formkit-data-debug span{font-size:.75rem;line-height:1rem}@media(min-width: 1024px){.formkit-form{display:flex;flex-wrap:wrap;margin-left:-0.5rem;margin-right:-0.5rem}.formkit-form>*{flex-shrink:0;width:100%;max-width:100%;padding-left:.5rem;padding-right:.5rem}.col-1{width:8.3333333333%}.col-2{width:16.6666666667%}.col-3{width:25%}.col-4{width:33.3333333333%}.col-5{width:41.6666666667%}.col-6{width:50%}.col-7{width:58.3333333333%}.col-8{width:66.6666666667%}.col-9{width:75%}.col-10{width:83.3333333333%}.col-11{width:91.6666666667%}.col-12{width:100%}}@media(min-width: 768px){.formkit-form.form-horizontal .formkit-wrapper{display:flex}.formkit-form.form-horizontal .formkit-wrapper label{display:inline-block;padding:0 .25rem 0 0;font-size:inherit}.formkit-form.form-horizontal .formkit-wrapper label:after{content:":"}}@media(min-width: 768px)and (min-width: 768px){.formkit-form.form-horizontal.form-horizontal-checkbox-indent .formkit-outer[data-type=formCheckbox]{padding-left:33.3333333333%}}@media(min-width: 768px){.p-formkit-data-view .formkit-form.form-horizontal label{white-space:nowrap}.p-formkit-data-edit .formkit-form.form-horizontal .formkit-outer{width:100%}.p-formkit-data-edit .formkit-form.form-horizontal .formkit-outer label{width:33.3333333333%;padding-top:.25rem;line-height:normal}.p-formkit-data-edit .formkit-form.form-horizontal .formkit-outer .formkit-inner{width:66.6666666667%}.p-formkit-data-edit .formkit-form.form-horizontal div[data-type=formCheckbox] .formkit-inner{margin-left:auto}.p-formkit-data-edit .formkit-form.form-horizontal div[data-type=formCheckbox] .formkit-inner .p-formkit{display:flex}.p-formkit-data-edit .formkit-form.form-horizontal div[data-type=formCheckbox] .formkit-inner label{width:auto;padding:0}.p-formkit-data-edit .formkit-form.form-horizontal .formkit-help,.p-formkit-data-edit .formkit-form.form-horizontal .formkit-messages{width:66.6666666667%;margin-left:auto}}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Deep-copies arrays and plain objects and leaves every other value - class
3
+ * instances such as `@internationalized/date`'s `CalendarDate`/`Time`/
4
+ * `ZonedDateTime`, `Date`, `File`, `Map` - as the same reference.
5
+ *
6
+ * Not `@formkit/utils`' `cloneAny`: it shares a `Date`/`File`/`Map` but rebuilds a
7
+ * `CalendarDate` as a plain object without its prototype, so the date inputs lose
8
+ * the value without any error. A cycle is copied as a cycle.
9
+ */
10
+ export declare function clonePlain<T>(value: T, seen?: WeakMap<object, unknown>): T;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.clonePlain = clonePlain;
7
+ function isPlainObject(value) {
8
+ const prototype = Object.getPrototypeOf(value);
9
+ return prototype === Object.prototype || prototype === null;
10
+ }
11
+ function clonePlain(value, seen = /* @__PURE__ */new WeakMap()) {
12
+ if (value === null || typeof value !== "object") return value;
13
+ if (seen.has(value)) return seen.get(value);
14
+ if (Array.isArray(value)) {
15
+ const copy2 = [];
16
+ seen.set(value, copy2);
17
+ for (const item of value) copy2.push(clonePlain(item, seen));
18
+ return copy2;
19
+ }
20
+ if (!isPlainObject(value)) return value;
21
+ const copy = Object.getPrototypeOf(value) === null ? /* @__PURE__ */Object.create(null) : {};
22
+ seen.set(value, copy);
23
+ for (const key of Object.keys(value)) copy[key] = clonePlain(value[key], seen);
24
+ return copy;
25
+ }
@@ -0,0 +1,24 @@
1
+ function isPlainObject(value) {
2
+ const prototype = Object.getPrototypeOf(value);
3
+ return prototype === Object.prototype || prototype === null;
4
+ }
5
+ export function clonePlain(value, seen = /* @__PURE__ */ new WeakMap()) {
6
+ if (value === null || typeof value !== "object")
7
+ return value;
8
+ if (seen.has(value))
9
+ return seen.get(value);
10
+ if (Array.isArray(value)) {
11
+ const copy2 = [];
12
+ seen.set(value, copy2);
13
+ for (const item of value)
14
+ copy2.push(clonePlain(item, seen));
15
+ return copy2;
16
+ }
17
+ if (!isPlainObject(value))
18
+ return value;
19
+ const copy = Object.getPrototypeOf(value) === null ? /* @__PURE__ */ Object.create(null) : {};
20
+ seen.set(value, copy);
21
+ for (const key of Object.keys(value))
22
+ copy[key] = clonePlain(value[key], seen);
23
+ return copy;
24
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sfxcode/formkit-openvue",
3
3
  "type": "module",
4
- "version": "0.8.1",
4
+ "version": "0.9.0",
5
5
  "packageManager": "pnpm@11.0.9+sha512.34ce82e6780233cf9cad8685029a8f81d2e06196c5a9bad98879f7424940c6817c4e4524fb7d38b8553ceed48b9758b8ebaf1abd3600c232c4c8cf7366086f38",
6
6
  "author": {
7
7
  "name": "Tom",
@@ -79,7 +79,7 @@
79
79
  "dev": "vite serve dev",
80
80
  "dev:build": "vite build dev",
81
81
  "dev:preview": "vite preview dev",
82
- "release": "npm run lint && npm run build && changelogen --patch --release && npm publish --access public && git push --follow-tags",
82
+ "release": "npm run lint && npm run build && changelogen --major --release && npm publish --access public && git push --follow-tags",
83
83
  "lint": "eslint .",
84
84
  "lint:fix": "eslint . --fix",
85
85
  "prepublishOnly": "pnpm build",
@@ -100,51 +100,39 @@
100
100
  "@formkit/i18n": "^2.1.2",
101
101
  "@formkit/inputs": "^2.1.2",
102
102
  "@formkit/vue": "^2.1.2",
103
- "@intlify/core": "^11.4.13",
103
+ "@intlify/core": "^11.4.14",
104
104
  "@openvue/openicons": "^1.0.0",
105
105
  "@openvue/openicons-vue": "^1.0.0",
106
106
  "openvue": "1.0.0",
107
- "vue-i18n": "^11.4.13"
107
+ "vue-i18n": "^11.4.14"
108
108
  },
109
109
  "devDependencies": {
110
110
  "@antfu/eslint-config": "^9.5.1",
111
111
  "@openvue/themes": "1.0.0",
112
112
  "@types/node": "latest",
113
- "@unocss/preset-icons": "^66.10.5",
114
- "@unocss/preset-uno": "^66.10.5",
115
- "@vitejs/plugin-vue": "^6.0.9",
116
- "@vitest/coverage-v8": "^5.0.3",
117
- "@vitest/ui": "^5.0.3",
118
- "@vue/compiler-sfc": "^3.5.43",
119
- "@vue/server-renderer": "^3.5.43",
120
- "@vue/test-utils": "^2.5.1",
113
+ "@vitejs/plugin-vue": "^6.0.10",
114
+ "@vitest/coverage-v8": "^5.0.5",
115
+ "@vitest/ui": "^5.0.5",
121
116
  "@vue/tsconfig": "^0.9.1",
122
117
  "@vueuse/core": "^15.0.0",
123
- "@vueuse/head": "^2.0.0",
124
118
  "changelogen": "^0.6.2",
125
- "chart.js": "^4.5.1",
126
- "consola": "^3.4.2",
127
- "esbuild": "^0.28.2",
128
- "eslint": "^10.12.0",
129
- "happy-dom": "^20.14.5",
119
+ "eslint": "^10.13.0",
120
+ "happy-dom": "^21.0.3",
130
121
  "json-editor-vue": "^0.19.2",
131
122
  "mkdist": "^2.4.1",
132
- "sass": "^1.105.1",
133
- "tslib": "^2.8.1",
123
+ "sass": "^1.105.2",
134
124
  "typescript": "^6.0.3",
135
125
  "unbuild": "^3.6.1",
136
- "unocss": "^66.10.5",
126
+ "unocss": "^66.11.0",
137
127
  "unplugin-auto-import": "^21.1.0",
138
128
  "unplugin-vue-components": "^32.1.0",
139
- "vite": "^8.3.2",
129
+ "vite": "^8.3.4",
140
130
  "vite-plugin-pages": "^0.33.3",
141
- "vite-ssg": "^28.3.0",
142
131
  "vitepress": "2.0.0-alpha.20",
143
- "vitest": "^5.0.3",
144
- "vue": "^3.5.43",
145
- "vue-demi": "^0.14.10",
146
- "vue-router": "^5.3.1",
132
+ "vitest": "^5.0.5",
133
+ "vue": "^3.5.44",
134
+ "vue-router": "^5.4.0",
147
135
  "vue-sfc-transformer": "^0.3.0",
148
- "vue-tsc": "^3.3.12"
136
+ "vue-tsc": "^3.3.13"
149
137
  }
150
138
  }