@sfxcode/formkit-openvue 0.0.0-stage → 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.
Files changed (96) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +227 -2
  3. package/components.d.ts +1 -0
  4. package/dist/components/FormAutoComplete.vue +100 -0
  5. package/dist/components/FormCascadeSelect.vue +41 -0
  6. package/dist/components/FormCheckbox.vue +49 -0
  7. package/dist/components/FormColorPicker.vue +31 -0
  8. package/dist/components/FormDatePicker.vue +93 -0
  9. package/dist/components/FormInputMask.vue +67 -0
  10. package/dist/components/FormInputNumber.vue +72 -0
  11. package/dist/components/FormInputOtp.vue +40 -0
  12. package/dist/components/FormInputText.vue +63 -0
  13. package/dist/components/FormKitDataDebug.vue +25 -0
  14. package/dist/components/FormKitDataEdit.vue +123 -0
  15. package/dist/components/FormKitDataView.vue +56 -0
  16. package/dist/components/FormKitIcon.vue +23 -0
  17. package/dist/components/FormKitPrefix.vue +9 -0
  18. package/dist/components/FormKitSuffix.vue +9 -0
  19. package/dist/components/FormKnob.vue +48 -0
  20. package/dist/components/FormListbox.vue +482 -0
  21. package/dist/components/FormMultiSelect.vue +68 -0
  22. package/dist/components/FormOutputBoolean.vue +30 -0
  23. package/dist/components/FormOutputDate.vue +40 -0
  24. package/dist/components/FormOutputDuration.vue +24 -0
  25. package/dist/components/FormOutputLink.vue +39 -0
  26. package/dist/components/FormOutputList.vue +105 -0
  27. package/dist/components/FormOutputNumber.vue +47 -0
  28. package/dist/components/FormOutputReference.vue +52 -0
  29. package/dist/components/FormOutputText.vue +52 -0
  30. package/dist/components/FormPassword.vue +47 -0
  31. package/dist/components/FormRadioButton.vue +39 -0
  32. package/dist/components/FormRating.vue +38 -0
  33. package/dist/components/FormSelect.vue +69 -0
  34. package/dist/components/FormSelectButton.vue +42 -0
  35. package/dist/components/FormSlider.vue +40 -0
  36. package/dist/components/FormTextarea.vue +35 -0
  37. package/dist/components/FormToggleButton.vue +40 -0
  38. package/dist/components/FormToggleSwitch.vue +40 -0
  39. package/dist/components/FormTreeSelect.vue +46 -0
  40. package/dist/components/index.d.ts +24 -0
  41. package/dist/components/index.js +167 -0
  42. package/dist/components/index.mjs +48 -0
  43. package/dist/composables/index.d.ts +9 -0
  44. package/dist/composables/index.js +61 -0
  45. package/dist/composables/index.mjs +18 -0
  46. package/dist/composables/useFormInputs.d.ts +3 -0
  47. package/dist/composables/useFormInputs.js +62 -0
  48. package/dist/composables/useFormInputs.mjs +53 -0
  49. package/dist/composables/useFormKitInput.d.ts +11 -0
  50. package/dist/composables/useFormKitInput.js +58 -0
  51. package/dist/composables/useFormKitInput.mjs +45 -0
  52. package/dist/composables/useFormKitRepeater.d.ts +18 -0
  53. package/dist/composables/useFormKitRepeater.js +74 -0
  54. package/dist/composables/useFormKitRepeater.mjs +54 -0
  55. package/dist/composables/useFormKitSchema.d.ts +36 -0
  56. package/dist/composables/useFormKitSchema.js +83 -0
  57. package/dist/composables/useFormKitSchema.mjs +58 -0
  58. package/dist/composables/useFormKitSection.d.ts +7 -0
  59. package/dist/composables/useFormKitSection.js +31 -0
  60. package/dist/composables/useFormKitSection.mjs +19 -0
  61. package/dist/composables/useInputEditor.d.ts +8 -0
  62. package/dist/composables/useInputEditor.js +148 -0
  63. package/dist/composables/useInputEditor.mjs +143 -0
  64. package/dist/composables/useInputEditorSchema.d.ts +163 -0
  65. package/dist/composables/useInputEditorSchema.js +313 -0
  66. package/dist/composables/useInputEditorSchema.mjs +315 -0
  67. package/dist/composables/useOutputDuration.d.ts +4 -0
  68. package/dist/composables/useOutputDuration.js +40 -0
  69. package/dist/composables/useOutputDuration.mjs +35 -0
  70. package/dist/definitions/index.d.ts +35 -0
  71. package/dist/definitions/index.js +44 -0
  72. package/dist/definitions/index.mjs +70 -0
  73. package/dist/definitions/input.d.ts +23 -0
  74. package/dist/definitions/input.js +118 -0
  75. package/dist/definitions/input.mjs +111 -0
  76. package/dist/definitions/output.d.ts +9 -0
  77. package/dist/definitions/output.js +46 -0
  78. package/dist/definitions/output.mjs +136 -0
  79. package/dist/definitions/repeater.d.ts +2 -0
  80. package/dist/definitions/repeater.js +234 -0
  81. package/dist/definitions/repeater.mjs +215 -0
  82. package/dist/index.d.ts +148 -0
  83. package/dist/index.js +62 -0
  84. package/dist/index.mjs +14 -0
  85. package/dist/plugins/autoAnimate.d.ts +9 -0
  86. package/dist/plugins/autoAnimate.js +93 -0
  87. package/dist/plugins/autoAnimate.mjs +87 -0
  88. package/dist/plugins/index.d.ts +5 -0
  89. package/dist/plugins/index.js +67 -0
  90. package/dist/plugins/index.mjs +56 -0
  91. package/dist/sass/formkit-openvue.scss +491 -0
  92. package/dist/style.css +1 -0
  93. package/dist/utils/clonePlain.d.ts +10 -0
  94. package/dist/utils/clonePlain.js +25 -0
  95. package/dist/utils/clonePlain.mjs +24 -0
  96. package/package.json +136 -4
@@ -0,0 +1,482 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ import { useFormKitInput } from "../composables";
4
+ const props = defineProps({ context: {
5
+ type: Object,
6
+ required: true
7
+ } });
8
+ const { validSlotNames, unstyled, isInvalid, handleInput, handleBlur, handleChange, modelValue } = useFormKitInput(props.context);
9
+ // Computed properties for transfer mode styling
10
+ const transferContainerClass = computed(() => {
11
+ return props.context.transferContainerClass || "p-formkit-transfer";
12
+ });
13
+ const transferListContainerClass = computed(() => {
14
+ return props.context.transferListContainerClass || "p-formkit-transfer-list-container";
15
+ });
16
+ const transferButtonClass = computed(() => {
17
+ return props.context.transferButtonClass || "";
18
+ });
19
+ const transferButtonSeverity = computed(() => {
20
+ return props.context.transferButtonSeverity || "secondary";
21
+ });
22
+ const transferDragDrop = computed(() => {
23
+ return props.context.transferDragDrop ?? true;
24
+ });
25
+ const transferSlotNames = computed(() => {
26
+ return validSlotNames.value.filter((slotName) => slotName !== "option");
27
+ });
28
+ // Transfer List functionality
29
+ const optionValueKey = computed(() => {
30
+ const key = props.context.optionValue;
31
+ return typeof key === "string" ? key : null;
32
+ });
33
+ // Helper function to convert values to full objects
34
+ function valuesToObjects(values) {
35
+ if (!optionValueKey.value) return values;
36
+ const options = props.context?.options || [];
37
+ return values.map((val) => {
38
+ if (typeof val === "object") return val;
39
+ return options.find((opt) => opt[optionValueKey.value] === val) || val;
40
+ });
41
+ }
42
+ // Initialize targetItems by converting any values to full objects
43
+ const initialTargetItems = Array.isArray(modelValue.value) ? valuesToObjects(modelValue.value) : [];
44
+ const targetItems = ref(initialTargetItems);
45
+ const sourceSelection = ref([]);
46
+ const targetSelection = ref([]);
47
+ const transferHeaderClass = computed(() => {
48
+ return props.context.transferHeaderClass || "text-base font-semibold";
49
+ });
50
+ const sourceItems = computed(() => {
51
+ const options = props.context?.options || [];
52
+ if (!Array.isArray(options)) return [];
53
+ return options.filter((item) => {
54
+ const itemValue = optionValueKey.value && typeof item === "object" ? item[optionValueKey.value] : item;
55
+ return !targetItems.value.some((t) => {
56
+ const targetValue = optionValueKey.value && typeof t === "object" ? t[optionValueKey.value] : t;
57
+ return targetValue === itemValue;
58
+ });
59
+ });
60
+ });
61
+ const dragSource = ref(null);
62
+ const draggedItems = ref([]);
63
+ const activeDropzone = ref(null);
64
+ const dragOverIndex = ref(null);
65
+ function getComparableValue(item) {
66
+ const valueKey = optionValueKey.value;
67
+ return valueKey && typeof item === "object" ? item?.[valueKey] : item;
68
+ }
69
+ function isSameOption(left, right) {
70
+ return getComparableValue(left) === getComparableValue(right);
71
+ }
72
+ function getUniqueItems(items) {
73
+ return items.filter((item, index) => items.findIndex((candidate) => isSameOption(candidate, item)) === index);
74
+ }
75
+ function mergeUniqueItems(base, toAdd) {
76
+ return [...base, ...toAdd.filter((item) => !base.some((candidate) => isSameOption(candidate, item)))];
77
+ }
78
+ function getDraggableItems(origin, option) {
79
+ const selection = origin === "source" ? sourceSelection.value : targetSelection.value;
80
+ if (!selection.length) return [option];
81
+ const hasOptionSelected = selection.some((item) => isSameOption(item, option));
82
+ return hasOptionSelected ? getUniqueItems(selection) : [option];
83
+ }
84
+ function clearDragState() {
85
+ dragSource.value = null;
86
+ draggedItems.value = [];
87
+ activeDropzone.value = null;
88
+ dragOverIndex.value = null;
89
+ }
90
+ function canDropInto(target) {
91
+ if (!transferDragDrop.value || props.context.disabled || !dragSource.value || draggedItems.value.length === 0) return false;
92
+ // The target list accepts cross-list moves as well as same-list reordering.
93
+ if (target === "target") return true;
94
+ // The source list only accepts items coming from the target (i.e. removal).
95
+ return dragSource.value !== target;
96
+ }
97
+ function handleOptionDragStart(origin, option, event) {
98
+ if (!transferDragDrop.value || props.context.disabled) return;
99
+ draggedItems.value = getDraggableItems(origin, option);
100
+ dragSource.value = origin;
101
+ if (event.dataTransfer) {
102
+ event.dataTransfer.effectAllowed = "move";
103
+ event.dataTransfer.setData("text/plain", "formkit-openvue-transfer");
104
+ }
105
+ }
106
+ function handleOptionDragEnd() {
107
+ clearDragState();
108
+ }
109
+ function handleDropzoneDragOver(target, event) {
110
+ if (!canDropInto(target)) return;
111
+ event.preventDefault();
112
+ activeDropzone.value = target;
113
+ // Hovering empty space (not over a specific item) clears the per-item highlight.
114
+ dragOverIndex.value = null;
115
+ if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
116
+ }
117
+ function handleDropzoneDragLeave(target) {
118
+ if (activeDropzone.value === target) activeDropzone.value = null;
119
+ }
120
+ function handleDropzoneDrop(target, event) {
121
+ if (!canDropInto(target)) {
122
+ clearDragState();
123
+ return;
124
+ }
125
+ event.preventDefault();
126
+ if (target === "target") {
127
+ targetItems.value = mergeUniqueItems(targetItems.value, draggedItems.value);
128
+ sourceSelection.value = [];
129
+ } else {
130
+ targetItems.value = targetItems.value.filter((item) => !draggedItems.value.some((dragged) => isSameOption(dragged, item)));
131
+ targetSelection.value = [];
132
+ }
133
+ clearDragState();
134
+ }
135
+ function handleTargetItemDragOver(index, event) {
136
+ if (!canDropInto("target")) return;
137
+ // Handle the drop at the item level so it lands at a precise position.
138
+ event.preventDefault();
139
+ event.stopPropagation();
140
+ activeDropzone.value = "target";
141
+ dragOverIndex.value = index;
142
+ if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
143
+ }
144
+ function handleTargetItemDrop(index, event) {
145
+ if (!canDropInto("target")) {
146
+ clearDragState();
147
+ return;
148
+ }
149
+ event.preventDefault();
150
+ event.stopPropagation();
151
+ const referenceItem = targetItems.value[index];
152
+ const itemsToInsert = getUniqueItems(draggedItems.value);
153
+ if (dragSource.value === "target") {
154
+ // Reorder within the target list: move the dragged items to the drop position.
155
+ if (itemsToInsert.some((dragged) => isSameOption(dragged, referenceItem))) {
156
+ clearDragState();
157
+ return;
158
+ }
159
+ const remaining = targetItems.value.filter((item) => !itemsToInsert.some((dragged) => isSameOption(dragged, item)));
160
+ let insertAt = remaining.findIndex((item) => isSameOption(item, referenceItem));
161
+ if (insertAt === -1) insertAt = remaining.length;
162
+ remaining.splice(insertAt, 0, ...itemsToInsert);
163
+ targetItems.value = remaining;
164
+ targetSelection.value = [];
165
+ } else {
166
+ // Cross-list move: insert the dragged source items at the drop position.
167
+ const additions = itemsToInsert.filter((item) => !targetItems.value.some((candidate) => isSameOption(candidate, item)));
168
+ const updated = [...targetItems.value];
169
+ updated.splice(index, 0, ...additions);
170
+ targetItems.value = updated;
171
+ sourceSelection.value = [];
172
+ }
173
+ clearDragState();
174
+ }
175
+ function resolveOptionDisabled(option) {
176
+ const optionDisabled = props.context.optionDisabled;
177
+ if (!optionDisabled) return false;
178
+ if (typeof optionDisabled === "function") return !!optionDisabled(option);
179
+ if (typeof optionDisabled === "string") return !!option?.[optionDisabled];
180
+ return !!optionDisabled;
181
+ }
182
+ function resolveOptionLabel(option) {
183
+ if (!props.context.optionLabel) return String(option);
184
+ if (typeof props.context.optionLabel === "function") return String(props.context.optionLabel(option));
185
+ return String(option?.[props.context.optionLabel] ?? option);
186
+ }
187
+ function transferSelected() {
188
+ if (sourceSelection.value.length === 0) return;
189
+ // Use splice-based approach for better performance
190
+ targetItems.value = [...targetItems.value, ...sourceSelection.value];
191
+ sourceSelection.value = [];
192
+ }
193
+ function transferAll() {
194
+ if (sourceItems.value.length === 0) return;
195
+ targetItems.value = [...targetItems.value, ...sourceItems.value];
196
+ sourceSelection.value = [];
197
+ }
198
+ function removeSelected() {
199
+ if (targetSelection.value.length === 0) return;
200
+ // Filter out selected items using splice-inspired logic
201
+ const valueKey = optionValueKey.value;
202
+ targetItems.value = targetItems.value.filter((item) => {
203
+ const itemValue = valueKey && typeof item === "object" ? item[valueKey] : item;
204
+ return !targetSelection.value.some((sel) => {
205
+ const selValue = valueKey && typeof sel === "object" ? sel[valueKey] : sel;
206
+ return selValue === itemValue;
207
+ });
208
+ });
209
+ targetSelection.value = [];
210
+ }
211
+ function removeAll() {
212
+ if (targetItems.value.length === 0) return;
213
+ targetItems.value = [];
214
+ targetSelection.value = [];
215
+ }
216
+ watch(targetItems, (newVal) => {
217
+ modelValue.value = newVal;
218
+ handleInput(newVal);
219
+ handleChange(newVal);
220
+ }, { deep: true });
221
+ // Watch for external changes to modelValue and update targetItems
222
+ watch(() => modelValue.value, (newVal) => {
223
+ if (props.context.displayMode === "transfer" && Array.isArray(newVal)) {
224
+ const converted = valuesToObjects(newVal);
225
+ // Only update if the values are actually different to avoid infinite loops
226
+ if (JSON.stringify(converted) !== JSON.stringify(targetItems.value)) {
227
+ targetItems.value = converted;
228
+ }
229
+ }
230
+ }, { deep: true });
231
+ </script>
232
+
233
+ <template>
234
+ <!-- Single Mode (default) -->
235
+ <div v-if="!context.displayMode || context.displayMode === 'single'" class="p-formkit">
236
+ <Listbox
237
+ :id="context.id"
238
+ v-model="modelValue"
239
+ v-bind="context?.attrs"
240
+ :disabled="!!context?.disabled"
241
+ :readonly="context?.attrs.readonly ?? false"
242
+ :list-style="context?.attrs.style"
243
+ :class="context?.attrs?.class"
244
+ :invalid="isInvalid"
245
+ :tabindex="context?.attrs.tabindex"
246
+ :aria-label="context?.attrs.ariaLabel"
247
+ :aria-labelledby="context?.attrs.ariaLabelledby"
248
+ :options="context?.options"
249
+ :option-label="context.optionLabel"
250
+ :option-value="context.optionValue"
251
+ :option-disabled="context.optionDisabled"
252
+ :option-group-label="context.optionGroupLabel"
253
+ :option-group-children="context.optionGroupChildren"
254
+ :multiple="context.multiple ?? false"
255
+ :filter="context.filter ?? false"
256
+ :filter-icon="context.filterIcon"
257
+ :filter-placeholder="context.filterPlaceholder"
258
+ :filter-locale="context.filterLocale"
259
+ :filter-match-mode="context.filterMatchMode"
260
+ :auto-option-focus="context.autoOptionFocus ?? true"
261
+ :select-on-focus="context.selectOnFocus ?? false"
262
+ :data-key="context.dataKey"
263
+ :meta-key-selection="context.metaKeySelection ?? false"
264
+ :virtual-scroller-options="context.virtualScrollerOptions"
265
+ :pt="context.pt"
266
+ :pt-options="context.ptOptions"
267
+ :unstyled="unstyled"
268
+ @update:model-value="handleInput"
269
+ @change="handleChange"
270
+ @blur="handleBlur"
271
+ >
272
+ <template v-for="slotName in validSlotNames" :key="slotName" #[slotName]="slotProps">
273
+ <component :is="context?.slots[slotName]" v-bind="{ ...context, ...slotProps }" />
274
+ </template>
275
+ </Listbox>
276
+ </div>
277
+
278
+ <!-- Transfer Mode -->
279
+ <div
280
+ v-if="context.displayMode === 'transfer'"
281
+ :class="transferContainerClass"
282
+ >
283
+ <!-- Source List -->
284
+ <div
285
+ :class="[transferListContainerClass, { 'p-formkit-transfer-dropzone-active': activeDropzone === 'source' }]"
286
+ @dragover="handleDropzoneDragOver('source', $event)"
287
+ @dragleave="handleDropzoneDragLeave('source')"
288
+ @drop="handleDropzoneDrop('source', $event)"
289
+ >
290
+ <span
291
+ v-if="context.transferLeftHeaderText"
292
+ :class="transferHeaderClass"
293
+ >{{ context.transferLeftHeaderText }}</span>
294
+ <Listbox
295
+ :id="`${context.id}-transfer-source`"
296
+ v-model="sourceSelection"
297
+ v-bind="context?.attrs"
298
+ :disabled="!!context?.disabled"
299
+ :readonly="context?.attrs.readonly ?? false"
300
+ :list-style="context?.attrs.style"
301
+ :class="context?.attrs?.class"
302
+ :invalid="isInvalid"
303
+ :tabindex="context?.attrs.tabindex"
304
+ :aria-label="context?.attrs.ariaLabel || 'Source list'"
305
+ :aria-labelledby="context?.attrs.ariaLabelledby"
306
+ :options="sourceItems"
307
+ :option-label="context.optionLabel"
308
+ :option-disabled="context.optionDisabled"
309
+ :option-group-label="context.optionGroupLabel"
310
+ :option-group-children="context.optionGroupChildren"
311
+ :data-key="context.dataKey"
312
+ :multiple="true"
313
+ :filter="context.filter ?? false"
314
+ :filter-icon="context.filterIcon"
315
+ :filter-placeholder="context.filterPlaceholder"
316
+ :filter-locale="context.filterLocale"
317
+ :filter-match-mode="context.filterMatchMode"
318
+ :auto-option-focus="context.autoOptionFocus ?? true"
319
+ :select-on-focus="context.selectOnFocus ?? false"
320
+ :meta-key-selection="context.metaKeySelection ?? false"
321
+ :virtual-scroller-options="context.virtualScrollerOptions"
322
+ :pt="context.pt"
323
+ :pt-options="context.ptOptions"
324
+ :unstyled="unstyled"
325
+ @blur="handleBlur"
326
+ >
327
+ <template #option="slotProps">
328
+ <div
329
+ :draggable="transferDragDrop && !context.disabled && !resolveOptionDisabled(slotProps.option)"
330
+ class="p-formkit-transfer-option"
331
+ :class="{ 'p-formkit-transfer-option-draggable': transferDragDrop && !context.disabled && !resolveOptionDisabled(slotProps.option) }"
332
+ @dragstart="handleOptionDragStart('source', slotProps.option, $event)"
333
+ @dragend="handleOptionDragEnd"
334
+ >
335
+ <component
336
+ :is="context?.slots.option"
337
+ v-if="context?.slots?.option"
338
+ v-bind="{ ...context, ...slotProps }"
339
+ />
340
+ <span v-else>{{ resolveOptionLabel(slotProps.option) }}</span>
341
+ </div>
342
+ </template>
343
+ <template v-for="slotName in transferSlotNames" :key="slotName" #[slotName]="slotProps">
344
+ <component :is="context?.slots[slotName]" v-bind="{ ...context, ...slotProps }" />
345
+ </template>
346
+ </Listbox>
347
+ </div>
348
+
349
+ <!-- Transfer Buttons -->
350
+ <div class="p-formkit-transfer-buttons">
351
+ <Button
352
+ icon="oi oi-angle-right"
353
+ :severity="transferButtonSeverity"
354
+ :class="transferButtonClass"
355
+ outlined
356
+ :disabled="sourceSelection.length === 0"
357
+ :aria-label="context.transferAll ? 'Move selected to target' : 'Move to target'"
358
+ @click="transferSelected"
359
+ />
360
+ <Button
361
+ v-if="context.transferAll"
362
+ icon="oi oi-angle-double-right"
363
+ :severity="transferButtonSeverity"
364
+ :class="transferButtonClass"
365
+ outlined
366
+ :disabled="sourceItems.length === 0"
367
+ aria-label="Move all to target"
368
+ @click="transferAll"
369
+ />
370
+ <Button
371
+ icon="oi oi-angle-left"
372
+ :severity="transferButtonSeverity"
373
+ :class="transferButtonClass"
374
+ outlined
375
+ :disabled="targetSelection.length === 0"
376
+ :aria-label="context.transferAll ? 'Move selected to source' : 'Move to source'"
377
+ @click="removeSelected"
378
+ />
379
+ <Button
380
+ v-if="context.transferAll"
381
+ icon="oi oi-angle-double-left"
382
+ :severity="transferButtonSeverity"
383
+ :class="transferButtonClass"
384
+ outlined
385
+ :disabled="targetItems.length === 0"
386
+ aria-label="Move all to source"
387
+ @click="removeAll"
388
+ />
389
+ </div>
390
+
391
+ <!-- Target List -->
392
+ <div
393
+ :class="[transferListContainerClass, { 'p-formkit-transfer-dropzone-active': activeDropzone === 'target' }]"
394
+ @dragover="handleDropzoneDragOver('target', $event)"
395
+ @dragleave="handleDropzoneDragLeave('target')"
396
+ @drop="handleDropzoneDrop('target', $event)"
397
+ >
398
+ <span
399
+ v-if="context.transferRightHeaderText"
400
+ :class="transferHeaderClass"
401
+ >{{ context.transferRightHeaderText }}</span>
402
+ <Listbox
403
+ :id="`${context.id}-transfer-target`"
404
+ v-model="targetSelection"
405
+ v-bind="context?.attrs"
406
+ :disabled="!!context?.disabled"
407
+ :readonly="context?.attrs.readonly ?? false"
408
+ :list-style="context?.attrs.style"
409
+ :class="context?.attrs?.class"
410
+ :invalid="isInvalid"
411
+ :tabindex="context?.attrs.tabindex"
412
+ :aria-label="context?.attrs.ariaLabel || 'Target list'"
413
+ :aria-labelledby="context?.attrs.ariaLabelledby"
414
+ :options="targetItems"
415
+ :option-label="context.optionLabel"
416
+ :option-disabled="context.optionDisabled"
417
+ :option-group-label="context.optionGroupLabel"
418
+ :option-group-children="context.optionGroupChildren"
419
+ :data-key="context.dataKey"
420
+ :multiple="true"
421
+ :filter="context.filter ?? false"
422
+ :filter-icon="context.filterIcon"
423
+ :filter-placeholder="context.filterPlaceholder"
424
+ :filter-locale="context.filterLocale"
425
+ :filter-match-mode="context.filterMatchMode"
426
+ :auto-option-focus="context.autoOptionFocus ?? true"
427
+ :select-on-focus="context.selectOnFocus ?? false"
428
+ :meta-key-selection="context.metaKeySelection ?? false"
429
+ :virtual-scroller-options="context.virtualScrollerOptions"
430
+ :pt="context.pt"
431
+ :pt-options="context.ptOptions"
432
+ :unstyled="unstyled"
433
+ @blur="handleBlur"
434
+ >
435
+ <template #option="slotProps">
436
+ <div
437
+ :draggable="transferDragDrop && !context.disabled && !resolveOptionDisabled(slotProps.option)"
438
+ class="p-formkit-transfer-option"
439
+ :class="{
440
+ 'p-formkit-transfer-option-draggable': transferDragDrop && !context.disabled && !resolveOptionDisabled(slotProps.option),
441
+ 'p-formkit-transfer-option-dragover': dragOverIndex === slotProps.index,
442
+ }"
443
+ @dragstart="handleOptionDragStart('target', slotProps.option, $event)"
444
+ @dragend="handleOptionDragEnd"
445
+ @dragover="handleTargetItemDragOver(slotProps.index, $event)"
446
+ @drop="handleTargetItemDrop(slotProps.index, $event)"
447
+ >
448
+ <component
449
+ :is="context?.slots.option"
450
+ v-if="context?.slots?.option"
451
+ v-bind="{ ...context, ...slotProps }"
452
+ />
453
+ <span v-else>{{ resolveOptionLabel(slotProps.option) }}</span>
454
+ </div>
455
+ </template>
456
+ <template v-for="slotName in transferSlotNames" :key="slotName" #[slotName]="slotProps">
457
+ <component :is="context?.slots[slotName]" v-bind="{ ...context, ...slotProps }" />
458
+ </template>
459
+ </Listbox>
460
+ </div>
461
+ </div>
462
+ </template>
463
+
464
+ <style scoped>
465
+ .p-formkit-transfer :deep(.p-listbox) {
466
+ width: 100%;
467
+ height: 100%;
468
+ }
469
+
470
+ .p-formkit-transfer :deep(.p-listbox-list-container) {
471
+ max-height: none;
472
+ }
473
+
474
+ .p-formkit-transfer-dropzone-active :deep(.p-listbox) {
475
+ outline: 2px dashed var(--p-primary-color);
476
+ outline-offset: 2px;
477
+ }
478
+
479
+ .p-formkit-transfer-option-dragover {
480
+ box-shadow: inset 0 2px 0 0 var(--p-primary-color);
481
+ }
482
+ </style>
@@ -0,0 +1,68 @@
1
+ <script setup>
2
+ import { useFormKitInput } from "../composables";
3
+ const props = defineProps({ context: {
4
+ type: Object,
5
+ required: true
6
+ } });
7
+ const { validSlotNames, unstyled, isInvalid, handleBlur, handleChange, modelValue } = useFormKitInput(props.context);
8
+ </script>
9
+
10
+ <template>
11
+ <div class="p-formkit">
12
+ <MultiSelect
13
+ v-model="modelValue"
14
+ v-bind="context?.attrs"
15
+ :input-id="context.id"
16
+ :disabled="!!context?.disabled"
17
+ :readonly="context?.attrs.readonly ?? false"
18
+ :list-style="context?.attrs.style"
19
+ :class="context?.attrs?.class"
20
+ :invalid="isInvalid"
21
+ :tabindex="context?.attrs.tabindex"
22
+ :aria-label="context?.attrs.ariaLabel"
23
+ :aria-labelledby="context?.attrs.ariaLabelledby"
24
+ :size="context?.size ?? undefined"
25
+ :placeholder="context.placeholder"
26
+ :options="context.options"
27
+ :option-label="context.optionLabel"
28
+ :option-value="context.optionValue"
29
+ :option-disabled="context.optionDisabled"
30
+ :option-group-label="context.optionGroupLabel"
31
+ :option-group-children="context.optionGroupChildren"
32
+ :scroll-height="context.scrollHeight"
33
+ :data-key="context.dataKey"
34
+ :filter="context.filter ?? false"
35
+ :filter-placeholder="context.filterPlaceholder"
36
+ :filter-locale="context.filterLocale"
37
+ :filter-match-mode="context.filterMatchMode"
38
+ :fitler-fields="context.filterFields"
39
+ :append-to="context.appendTo"
40
+ :close-icon="context.closeIcon"
41
+ :display="context.display"
42
+ :max-selected-labels="context.maxSelectedLabels"
43
+ :selected-items-label="context.selectedItemsLabel"
44
+ :selection-limit="context.selectionLimit"
45
+ :show-toggle-all="context.showToggleAll"
46
+ :loading="context.loading"
47
+ :select-all="context.selectAll"
48
+ :reset-filter-on-hide="context.resetFilterOnHide"
49
+ :virtual-scroller-options="context.virtualScrollerOptions"
50
+ :auto-option-focus="context.autoOptionFocus"
51
+ :auto-filter-focus="context.autoFilterFocus"
52
+ :filter-message="context.filterMessage"
53
+ :selection-message="context.selectionMessage"
54
+ :empty-selection-message="context.emptySelectionMessage"
55
+ :empty-filter-message="context.emptyFilterMessage"
56
+ :empty-message="context.emptyMessage"
57
+ :pt="context.pt"
58
+ :pt-options="context.ptOptions"
59
+ :unstyled="unstyled"
60
+ @change="handleChange"
61
+ @blur="handleBlur"
62
+ >
63
+ <template v-for="slotName in validSlotNames" :key="slotName" #[slotName]="slotProps">
64
+ <component :is="context?.slots[slotName]" v-bind="{ ...context, ...slotProps }" />
65
+ </template>
66
+ </MultiSelect>
67
+ </div>
68
+ </template>
@@ -0,0 +1,30 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { useI18n } from "vue-i18n";
4
+ import { useFormKitSection } from "../composables";
5
+ import FormKitIcon from "./FormKitIcon.vue";
6
+ import FormKitPrefix from "./FormKitPrefix.vue";
7
+ import FormKitSuffix from "./FormKitSuffix.vue";
8
+ const props = defineProps({ context: {
9
+ type: Object,
10
+ required: true
11
+ } });
12
+ const { hasPrefix, hasPrefixIcon, hasSuffix, hasSuffixIcon } = useFormKitSection(props.context);
13
+ const { t } = useI18n();
14
+ const translated = computed(() => {
15
+ if (props.context?._value) return props.context?.trueValue ?? t("formkit.form.true", "true");
16
+ else return props.context?.falseValue ?? t("formkit.form.false", "false");
17
+ });
18
+ </script>
19
+
20
+ <template>
21
+ <div class="p-formkit p-output-boolean">
22
+ <FormKitIcon v-if="hasPrefixIcon" :icon-class="context?.iconPrefix" :on-click="context?.onIconPrefixClicked" :tooltip="context?.iconPrefixTooltip" position="prefix" />
23
+ <FormKitPrefix v-if="hasPrefix" :prefix="context?.prefix" />
24
+ <span :id="context?.id" :style="context?.attrs?.style" :class="context?.attrs?.class">
25
+ {{ translated }}
26
+ </span>
27
+ <FormKitSuffix v-if="hasSuffix" :suffix="context?.suffix" />
28
+ <FormKitIcon v-if="hasSuffixIcon" :icon-class="context?.iconSuffix" :on-click="context?.onIconSuffixClicked" :tooltip="context?.iconSuffixTooltip" position="suffix" />
29
+ </div>
30
+ </template>
@@ -0,0 +1,40 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { useI18n } from "vue-i18n";
4
+ import { useFormKitSection } from "../composables";
5
+ import FormKitIcon from "./FormKitIcon.vue";
6
+ import FormKitPrefix from "./FormKitPrefix.vue";
7
+ import FormKitSuffix from "./FormKitSuffix.vue";
8
+ const props = defineProps({ context: {
9
+ type: Object,
10
+ required: true
11
+ } });
12
+ const { hasPrefix, hasPrefixIcon, hasSuffix, hasSuffixIcon } = useFormKitSection(props.context);
13
+ const { d } = useI18n();
14
+ const converted = computed(() => {
15
+ if (props?.context?._value) {
16
+ let result = "";
17
+ const format = props?.context?.attrs?.value?.format ? props?.context?.attrs.value.format : "short";
18
+ try {
19
+ result = d(props?.context?._value, format);
20
+ }
21
+ // eslint-disable-next-line unused-imports/no-unused-vars
22
+ catch (e) {}
23
+ return result;
24
+ } else {
25
+ return "";
26
+ }
27
+ });
28
+ </script>
29
+
30
+ <template>
31
+ <div class="p-formkit p-output-date">
32
+ <FormKitIcon v-if="hasPrefixIcon" :icon-class="context?.iconPrefix" :on-click="context?.onIconPrefixClicked" :tooltip="context?.iconPrefixTooltip" position="prefix" />
33
+ <FormKitPrefix v-if="hasPrefix" :prefix="context?.prefix" />
34
+ <span :id="context?.id" :style="context?.attrs?.style" :class="context?.attrs?.class">
35
+ {{ converted }}
36
+ </span>
37
+ <FormKitSuffix v-if="hasSuffix" :suffix="context?.suffix" />
38
+ <FormKitIcon v-if="hasSuffixIcon" :icon-class="context?.iconSuffix" :on-click="context?.onIconSuffixClicked" :tooltip="context?.iconSuffixTooltip" position="suffix" />
39
+ </div>
40
+ </template>
@@ -0,0 +1,24 @@
1
+ <script setup>
2
+ import { useFormKitSection, useOutputDuration } from "../composables";
3
+ import FormKitIcon from "./FormKitIcon.vue";
4
+ import FormKitPrefix from "./FormKitPrefix.vue";
5
+ import FormKitSuffix from "./FormKitSuffix.vue";
6
+ const props = defineProps({ context: {
7
+ type: Object,
8
+ required: true
9
+ } });
10
+ const { hasPrefix, hasPrefixIcon, hasSuffix, hasSuffixIcon } = useFormKitSection(props.context);
11
+ const { formattedDuration } = useOutputDuration();
12
+ </script>
13
+
14
+ <template>
15
+ <div class="p-formkit p-output-duration">
16
+ <FormKitIcon v-if="hasPrefixIcon" :icon-class="context?.iconPrefix" :on-click="context?.onIconPrefixClicked" :tooltip="context?.iconPrefixTooltip" position="prefix" />
17
+ <FormKitPrefix v-if="hasPrefix" :prefix="context?.prefix" />
18
+ <span :id="context?.id" :style="context?.attrs?.style" :class="context?.attrs?.class">
19
+ {{ formattedDuration(context?._value) }}
20
+ </span>
21
+ <FormKitSuffix v-if="hasSuffix" :suffix="context?.suffix" />
22
+ <FormKitIcon v-if="hasSuffixIcon" :icon-class="context?.iconSuffix" :on-click="context?.onIconSuffixClicked" :tooltip="context?.iconSuffixTooltip" position="suffix" />
23
+ </div>
24
+ </template>