@sfxcode/formkit-primevue 4.1.2 → 4.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/PrimeListbox.d.vue.ts +5 -0
- package/dist/components/PrimeListbox.vue +244 -1
- package/dist/components/PrimeListbox.vue.d.ts +5 -0
- package/dist/definitions/index.js +1 -1
- package/dist/definitions/index.mjs +1 -1
- package/dist/definitions/input.js +2 -2
- package/dist/definitions/input.mjs +2 -2
- package/package.json +1 -1
|
@@ -26,6 +26,11 @@ export interface FormKitPrimeListboxProps {
|
|
|
26
26
|
tabindex?: ListboxProps['tabindex'];
|
|
27
27
|
ariaLabel?: ListboxProps['ariaLabel'];
|
|
28
28
|
ariaLabelledby?: ListboxProps['ariaLabelledby'];
|
|
29
|
+
displayMode?: 'single' | 'transfer';
|
|
30
|
+
transferLeftHeaderText?: string;
|
|
31
|
+
transferRightHeaderText?: string;
|
|
32
|
+
transferHeaderClass?: string;
|
|
33
|
+
transferAll?: boolean;
|
|
29
34
|
}
|
|
30
35
|
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
31
36
|
context: {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { FormKitFrameworkContext } from '@formkit/core'
|
|
3
3
|
import type { ListboxProps } from 'primevue/listbox'
|
|
4
4
|
import type { PropType } from 'vue'
|
|
5
|
+
import { computed, ref, watch } from 'vue'
|
|
5
6
|
import { useFormKitInput } from '../composables'
|
|
6
7
|
|
|
7
8
|
export interface FormKitPrimeListboxProps {
|
|
@@ -29,6 +30,11 @@ export interface FormKitPrimeListboxProps {
|
|
|
29
30
|
tabindex?: ListboxProps['tabindex']
|
|
30
31
|
ariaLabel?: ListboxProps['ariaLabel']
|
|
31
32
|
ariaLabelledby?: ListboxProps['ariaLabelledby']
|
|
33
|
+
displayMode?: 'single' | 'transfer'
|
|
34
|
+
transferLeftHeaderText?: string
|
|
35
|
+
transferRightHeaderText?: string
|
|
36
|
+
transferHeaderClass?: string
|
|
37
|
+
transferAll?: boolean
|
|
32
38
|
}
|
|
33
39
|
|
|
34
40
|
const props = defineProps({
|
|
@@ -39,10 +45,97 @@ const props = defineProps({
|
|
|
39
45
|
})
|
|
40
46
|
|
|
41
47
|
const { validSlotNames, unstyled, isInvalid, handleInput, handleBlur, modelValue } = useFormKitInput(props.context)
|
|
48
|
+
|
|
49
|
+
// Transfer List functionality
|
|
50
|
+
const optionValueKey = computed(() => {
|
|
51
|
+
const key = props.context.optionValue
|
|
52
|
+
return typeof key === 'string' ? key : null
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// Helper function to convert values to full objects
|
|
56
|
+
function valuesToObjects(values: any[]): any[] {
|
|
57
|
+
if (!optionValueKey.value)
|
|
58
|
+
return values
|
|
59
|
+
const options = props.context?.options || []
|
|
60
|
+
return values.map((val: any) => {
|
|
61
|
+
if (typeof val === 'object')
|
|
62
|
+
return val
|
|
63
|
+
return options.find((opt: any) => opt[optionValueKey.value!] === val) || val
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Initialize targetItems by converting any values to full objects
|
|
68
|
+
const initialTargetItems = Array.isArray(modelValue.value) ? valuesToObjects(modelValue.value) : []
|
|
69
|
+
const targetItems = ref<any[]>(initialTargetItems)
|
|
70
|
+
const sourceSelection = ref<any[]>([])
|
|
71
|
+
const targetSelection = ref<any[]>([])
|
|
72
|
+
|
|
73
|
+
const transferHeaderClass = computed(() => {
|
|
74
|
+
return props.context.transferHeaderClass || 'text-base font-semibold'
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
const sourceItems = computed(() => {
|
|
78
|
+
const options = props.context?.options || []
|
|
79
|
+
if (!Array.isArray(options))
|
|
80
|
+
return []
|
|
81
|
+
|
|
82
|
+
return options.filter((item: any) => {
|
|
83
|
+
const itemValue = optionValueKey.value && typeof item === 'object' ? item[optionValueKey.value] : item
|
|
84
|
+
return !targetItems.value.some((t: any) => {
|
|
85
|
+
const targetValue = optionValueKey.value && typeof t === 'object' ? t[optionValueKey.value] : t
|
|
86
|
+
return targetValue === itemValue
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
function transferSelected() {
|
|
92
|
+
// sourceSelection now contains full objects since we removed optionValue
|
|
93
|
+
targetItems.value = [...targetItems.value, ...sourceSelection.value]
|
|
94
|
+
sourceSelection.value = []
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function transferAll() {
|
|
98
|
+
targetItems.value = [...targetItems.value, ...sourceItems.value]
|
|
99
|
+
sourceSelection.value = []
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function removeSelected() {
|
|
103
|
+
// targetSelection now contains full objects since we removed optionValue
|
|
104
|
+
targetItems.value = targetItems.value.filter((item: any) => {
|
|
105
|
+
const itemValue = optionValueKey.value && typeof item === 'object' ? item[optionValueKey.value] : item
|
|
106
|
+
return !targetSelection.value.some((sel: any) => {
|
|
107
|
+
const selValue = optionValueKey.value && typeof sel === 'object' ? sel[optionValueKey.value] : sel
|
|
108
|
+
return selValue === itemValue
|
|
109
|
+
})
|
|
110
|
+
})
|
|
111
|
+
targetSelection.value = []
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function removeAll() {
|
|
115
|
+
targetItems.value = []
|
|
116
|
+
targetSelection.value = []
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
watch(targetItems, (newVal) => {
|
|
120
|
+
modelValue.value = newVal
|
|
121
|
+
handleInput(newVal)
|
|
122
|
+
}, { deep: true })
|
|
123
|
+
|
|
124
|
+
// Watch for external changes to modelValue and update targetItems
|
|
125
|
+
watch(() => modelValue.value, (newVal) => {
|
|
126
|
+
if (props.context.displayMode === 'transfer' && Array.isArray(newVal)) {
|
|
127
|
+
const converted = valuesToObjects(newVal)
|
|
128
|
+
// Only update if the values are actually different to avoid infinite loops
|
|
129
|
+
if (JSON.stringify(converted) !== JSON.stringify(targetItems.value)) {
|
|
130
|
+
targetItems.value = converted
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}, { deep: true })
|
|
42
134
|
</script>
|
|
43
135
|
|
|
44
136
|
<template>
|
|
45
|
-
|
|
137
|
+
<!-- Single Mode (default) -->
|
|
138
|
+
<div v-if="!context.displayMode || context.displayMode === 'single'" class="p-formkit">
|
|
46
139
|
<Listbox
|
|
47
140
|
:id="context.id"
|
|
48
141
|
v-model="modelValue"
|
|
@@ -83,4 +176,154 @@ const { validSlotNames, unstyled, isInvalid, handleInput, handleBlur, modelValue
|
|
|
83
176
|
</template>
|
|
84
177
|
</Listbox>
|
|
85
178
|
</div>
|
|
179
|
+
|
|
180
|
+
<!-- Transfer Mode -->
|
|
181
|
+
<div
|
|
182
|
+
v-if="context.displayMode === 'transfer'"
|
|
183
|
+
class="p-formkit-transfer"
|
|
184
|
+
style="display: flex; align-items: stretch; gap: 1rem; width: 100%;"
|
|
185
|
+
>
|
|
186
|
+
<!-- Source List -->
|
|
187
|
+
<div style="display: flex; flex-direction: column; flex: 1; gap: 0.5rem; min-width: 0;">
|
|
188
|
+
<span
|
|
189
|
+
v-if="context.transferLeftHeaderText"
|
|
190
|
+
:class="transferHeaderClass"
|
|
191
|
+
>{{ context.transferLeftHeaderText }}</span>
|
|
192
|
+
<Listbox
|
|
193
|
+
:id="`${context.id}-transfer-source`"
|
|
194
|
+
v-model="sourceSelection"
|
|
195
|
+
v-bind="context?.attrs"
|
|
196
|
+
:disabled="!!context?.disabled"
|
|
197
|
+
:readonly="context?.attrs.readonly ?? false"
|
|
198
|
+
:list-style="context?.attrs.style"
|
|
199
|
+
:class="context?.attrs?.class"
|
|
200
|
+
:invalid="isInvalid"
|
|
201
|
+
:tabindex="context?.attrs.tabindex"
|
|
202
|
+
:aria-label="context?.attrs.ariaLabel"
|
|
203
|
+
:aria-labelledby="context?.attrs.ariaLabelledby"
|
|
204
|
+
:options="sourceItems"
|
|
205
|
+
:option-label="context.optionLabel"
|
|
206
|
+
:option-disabled="context.optionDisabled"
|
|
207
|
+
:option-group-label="context.optionGroupLabel"
|
|
208
|
+
:option-group-children="context.optionGroupChildren"
|
|
209
|
+
:data-key="context.dataKey"
|
|
210
|
+
:multiple="true"
|
|
211
|
+
:filter="context.filter ?? false"
|
|
212
|
+
:filter-icon="context.filterIcon"
|
|
213
|
+
:filter-placeholder="context.filterPlaceholder"
|
|
214
|
+
:filter-locale="context.filterLocale"
|
|
215
|
+
:filter-match-mode="context.filterMatchMode"
|
|
216
|
+
:auto-option-focus="context.autoOptionFocus ?? true"
|
|
217
|
+
:select-on-focus="context.selectOnFocus ?? false"
|
|
218
|
+
:meta-key-selection="context.metaKeySelection ?? false"
|
|
219
|
+
:virtual-scroller-options="context.virtualScrollerOptions"
|
|
220
|
+
:pt="context.pt"
|
|
221
|
+
:pt-options="context.ptOptions"
|
|
222
|
+
:unstyled="unstyled"
|
|
223
|
+
@blur="handleBlur"
|
|
224
|
+
>
|
|
225
|
+
<template v-for="slotName in validSlotNames" :key="slotName" #[slotName]="slotProps">
|
|
226
|
+
<component :is="context?.slots[slotName]" v-bind="{ ...context, ...slotProps }" />
|
|
227
|
+
</template>
|
|
228
|
+
</Listbox>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<!-- Transfer Buttons -->
|
|
232
|
+
<div style="display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.5rem;">
|
|
233
|
+
<Button
|
|
234
|
+
icon="pi pi-angle-right"
|
|
235
|
+
severity="secondary"
|
|
236
|
+
outlined
|
|
237
|
+
:disabled="sourceSelection.length === 0"
|
|
238
|
+
aria-label="Move selected to target"
|
|
239
|
+
@click="transferSelected"
|
|
240
|
+
/>
|
|
241
|
+
<Button
|
|
242
|
+
v-if="context.transferAll"
|
|
243
|
+
icon="pi pi-angle-double-right"
|
|
244
|
+
severity="secondary"
|
|
245
|
+
outlined
|
|
246
|
+
:disabled="sourceItems.length === 0"
|
|
247
|
+
aria-label="Move all to target"
|
|
248
|
+
@click="transferAll"
|
|
249
|
+
/>
|
|
250
|
+
<Button
|
|
251
|
+
icon="pi pi-angle-left"
|
|
252
|
+
severity="secondary"
|
|
253
|
+
outlined
|
|
254
|
+
:disabled="targetSelection.length === 0"
|
|
255
|
+
aria-label="Move selected to source"
|
|
256
|
+
@click="removeSelected"
|
|
257
|
+
/>
|
|
258
|
+
<Button
|
|
259
|
+
v-if="context.transferAll"
|
|
260
|
+
icon="pi pi-angle-double-left"
|
|
261
|
+
severity="secondary"
|
|
262
|
+
outlined
|
|
263
|
+
:disabled="targetItems.length === 0"
|
|
264
|
+
aria-label="Move all to source"
|
|
265
|
+
@click="removeAll"
|
|
266
|
+
/>
|
|
267
|
+
</div>
|
|
268
|
+
|
|
269
|
+
<!-- Target List -->
|
|
270
|
+
<div style="display: flex; flex-direction: column; flex: 1; gap: 0.5rem; min-width: 0;">
|
|
271
|
+
<span
|
|
272
|
+
v-if="context.transferRightHeaderText"
|
|
273
|
+
:class="transferHeaderClass"
|
|
274
|
+
>{{ context.transferRightHeaderText }}</span>
|
|
275
|
+
<Listbox
|
|
276
|
+
:id="`${context.id}-transfer-target`"
|
|
277
|
+
v-model="targetSelection"
|
|
278
|
+
v-bind="context?.attrs"
|
|
279
|
+
:disabled="!!context?.disabled"
|
|
280
|
+
:readonly="context?.attrs.readonly ?? false"
|
|
281
|
+
:list-style="context?.attrs.style"
|
|
282
|
+
:class="context?.attrs?.class"
|
|
283
|
+
:invalid="isInvalid"
|
|
284
|
+
:tabindex="context?.attrs.tabindex"
|
|
285
|
+
:aria-label="context?.attrs.ariaLabel"
|
|
286
|
+
:aria-labelledby="context?.attrs.ariaLabelledby"
|
|
287
|
+
:options="targetItems"
|
|
288
|
+
:option-label="context.optionLabel"
|
|
289
|
+
:option-disabled="context.optionDisabled"
|
|
290
|
+
:option-group-label="context.optionGroupLabel"
|
|
291
|
+
:option-group-children="context.optionGroupChildren"
|
|
292
|
+
:data-key="context.dataKey"
|
|
293
|
+
:multiple="true"
|
|
294
|
+
:filter="context.filter ?? false"
|
|
295
|
+
:filter-icon="context.filterIcon"
|
|
296
|
+
:filter-placeholder="context.filterPlaceholder"
|
|
297
|
+
:filter-locale="context.filterLocale"
|
|
298
|
+
:filter-match-mode="context.filterMatchMode"
|
|
299
|
+
:auto-option-focus="context.autoOptionFocus ?? true"
|
|
300
|
+
:select-on-focus="context.selectOnFocus ?? false"
|
|
301
|
+
:meta-key-selection="context.metaKeySelection ?? false"
|
|
302
|
+
:virtual-scroller-options="context.virtualScrollerOptions"
|
|
303
|
+
:pt="context.pt"
|
|
304
|
+
:pt-options="context.ptOptions"
|
|
305
|
+
:unstyled="unstyled"
|
|
306
|
+
@blur="handleBlur"
|
|
307
|
+
>
|
|
308
|
+
<template v-for="slotName in validSlotNames" :key="slotName" #[slotName]="slotProps">
|
|
309
|
+
<component :is="context?.slots[slotName]" v-bind="{ ...context, ...slotProps }" />
|
|
310
|
+
</template>
|
|
311
|
+
</Listbox>
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
86
314
|
</template>
|
|
315
|
+
|
|
316
|
+
<style scoped>
|
|
317
|
+
.p-formkit-transfer {
|
|
318
|
+
min-width: 600px;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.p-formkit-transfer :deep(.p-listbox) {
|
|
322
|
+
width: 100%;
|
|
323
|
+
height: 100%;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.p-formkit-transfer :deep(.p-listbox-list-container) {
|
|
327
|
+
max-height: none;
|
|
328
|
+
}
|
|
329
|
+
</style>
|
|
@@ -26,6 +26,11 @@ export interface FormKitPrimeListboxProps {
|
|
|
26
26
|
tabindex?: ListboxProps['tabindex'];
|
|
27
27
|
ariaLabel?: ListboxProps['ariaLabel'];
|
|
28
28
|
ariaLabelledby?: ListboxProps['ariaLabelledby'];
|
|
29
|
+
displayMode?: 'single' | 'transfer';
|
|
30
|
+
transferLeftHeaderText?: string;
|
|
31
|
+
transferRightHeaderText?: string;
|
|
32
|
+
transferHeaderClass?: string;
|
|
33
|
+
transferAll?: boolean;
|
|
29
34
|
}
|
|
30
35
|
declare const __VLS_export: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
31
36
|
context: {
|
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.primeOutputs = exports.primeInputs = void 0;
|
|
7
7
|
var _input = require("./input");
|
|
8
8
|
var _output = require("./output");
|
|
9
|
-
var _repeater = require("./repeater
|
|
9
|
+
var _repeater = require("./repeater");
|
|
10
10
|
const primeInputs = exports.primeInputs = {
|
|
11
11
|
primeAutoComplete: _input.primeAutoCompleteDefinition,
|
|
12
12
|
primeInputText: _input.primeInputTextDefinition,
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
primeOutputReferenceDefinition,
|
|
33
33
|
primeOutputTextDefinition
|
|
34
34
|
} from "./output.mjs";
|
|
35
|
-
import { primeRepeaterDefinition } from "./repeater.
|
|
35
|
+
import { primeRepeaterDefinition } from "./repeater.mjs";
|
|
36
36
|
export const primeInputs = {
|
|
37
37
|
primeAutoComplete: primeAutoCompleteDefinition,
|
|
38
38
|
primeInputText: primeInputTextDefinition,
|
|
@@ -27,7 +27,7 @@ var _PrimeTextarea = _interopRequireDefault(require("../components/PrimeTextarea
|
|
|
27
27
|
var _PrimeToggleButton = _interopRequireDefault(require("../components/PrimeToggleButton.vue"));
|
|
28
28
|
var _PrimeToggleSwitch = _interopRequireDefault(require("../components/PrimeToggleSwitch.vue"));
|
|
29
29
|
var _PrimeTreeSelect = _interopRequireDefault(require("../components/PrimeTreeSelect.vue"));
|
|
30
|
-
var _repeater = require("./repeater
|
|
30
|
+
var _repeater = require("./repeater");
|
|
31
31
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
32
32
|
const primeAutoCompleteDefinition = exports.primeAutoCompleteDefinition = (0, _vue.createInput)(_PrimeAutoComplete.default, {
|
|
33
33
|
props: ["pt", "ptOptions", "unstyled", "Select", "multiple", "typeahead", "optionLabel", "options", "size", "minLength", "placeholder", "fluid", "separators"],
|
|
@@ -74,7 +74,7 @@ const primeMultiSelectDefinition = exports.primeMultiSelectDefinition = (0, _vue
|
|
|
74
74
|
family: "PrimeInput"
|
|
75
75
|
});
|
|
76
76
|
const primeListboxDefinition = exports.primeListboxDefinition = (0, _vue.createInput)(_PrimeListbox.default, {
|
|
77
|
-
props: ["pt", "ptOptions", "unstyled", "options", "optionLabel", "optionValue", "multiple", "filter", "filterIcon", "filterPlaceholder", "filterLocale", "filterMatchMode", "autoOptionFocus", "selectOnFocus", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "dataKey", "metaKeySelection", "virtualScrollerOptions"],
|
|
77
|
+
props: ["pt", "ptOptions", "unstyled", "options", "optionLabel", "optionValue", "multiple", "filter", "filterIcon", "filterPlaceholder", "filterLocale", "filterMatchMode", "autoOptionFocus", "selectOnFocus", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "dataKey", "metaKeySelection", "virtualScrollerOptions", "displayMode", "transferLeftHeaderText", "transferRightHeaderText", "transferHeaderClass", "transferAll"],
|
|
78
78
|
family: "PrimeInput"
|
|
79
79
|
});
|
|
80
80
|
const primeDatePickerDefinition = exports.primeDatePickerDefinition = (0, _vue.createInput)(_PrimeDatePicker.default, {
|
|
@@ -21,7 +21,7 @@ import PrimeTextarea from "../components/PrimeTextarea.vue";
|
|
|
21
21
|
import PrimeToggleButton from "../components/PrimeToggleButton.vue";
|
|
22
22
|
import PrimeToggleSwitch from "../components/PrimeToggleSwitch.vue";
|
|
23
23
|
import PrimeTreeSelect from "../components/PrimeTreeSelect.vue";
|
|
24
|
-
import { primeRepeaterDefinition } from "./repeater.
|
|
24
|
+
import { primeRepeaterDefinition } from "./repeater.mjs";
|
|
25
25
|
export const primeAutoCompleteDefinition = createInput(PrimeAutoComplete, {
|
|
26
26
|
props: ["pt", "ptOptions", "unstyled", "Select", "multiple", "typeahead", "optionLabel", "options", "size", "minLength", "placeholder", "fluid", "separators"],
|
|
27
27
|
family: "PrimeInput"
|
|
@@ -67,7 +67,7 @@ export const primeMultiSelectDefinition = createInput(PrimeMultiSelect, {
|
|
|
67
67
|
family: "PrimeInput"
|
|
68
68
|
});
|
|
69
69
|
export const primeListboxDefinition = createInput(PrimeListbox, {
|
|
70
|
-
props: ["pt", "ptOptions", "unstyled", "options", "optionLabel", "optionValue", "multiple", "filter", "filterIcon", "filterPlaceholder", "filterLocale", "filterMatchMode", "autoOptionFocus", "selectOnFocus", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "dataKey", "metaKeySelection", "virtualScrollerOptions"],
|
|
70
|
+
props: ["pt", "ptOptions", "unstyled", "options", "optionLabel", "optionValue", "multiple", "filter", "filterIcon", "filterPlaceholder", "filterLocale", "filterMatchMode", "autoOptionFocus", "selectOnFocus", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "dataKey", "metaKeySelection", "virtualScrollerOptions", "displayMode", "transferLeftHeaderText", "transferRightHeaderText", "transferHeaderClass", "transferAll"],
|
|
71
71
|
family: "PrimeInput"
|
|
72
72
|
});
|
|
73
73
|
export const primeDatePickerDefinition = createInput(PrimeDatePicker, {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sfxcode/formkit-primevue",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "4.1.
|
|
4
|
+
"version": "4.1.7",
|
|
5
5
|
"packageManager": "pnpm@11.0.9+sha512.34ce82e6780233cf9cad8685029a8f81d2e06196c5a9bad98879f7424940c6817c4e4524fb7d38b8553ceed48b9758b8ebaf1abd3600c232c4c8cf7366086f38",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Tom",
|