design-system-next 2.26.1 → 2.26.3
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/design-system-next.es.d.ts +252 -134
- package/dist/design-system-next.es.js +4794 -4724
- package/dist/design-system-next.es.js.gz +0 -0
- package/dist/design-system-next.umd.js +12 -12
- package/dist/design-system-next.umd.js.gz +0 -0
- package/dist/main.css +1 -1
- package/dist/main.css.gz +0 -0
- package/package.json +1 -1
- package/src/components/input/input-contact-number/input-contact-number.vue +5 -7
- package/src/components/input/input-currency/input-currency.ts +11 -15
- package/src/components/input/input-currency/input-currency.vue +4 -0
- package/src/components/input/input-currency/use-input-currency.ts +76 -107
- package/src/components/input/input-dropdown/input-dropdown.vue +4 -0
- package/src/components/input/input-search/input-search.vue +4 -0
- package/src/components/input/input.ts +1 -0
- package/src/components/input/input.vue +2 -1
- package/src/components/input/use-input.ts +5 -0
- package/src/components/list/list-item/list-item.ts +60 -60
- package/src/components/list/use-list.ts +6 -6
- package/src/components/{radio-grouped → radio/radio-grouped}/radio-grouped.ts +74 -65
- package/src/components/{radio-grouped → radio/radio-grouped}/radio-grouped.vue +4 -1
- package/src/components/{radio-grouped → radio/radio-grouped}/use-radio-grouped.ts +63 -62
- package/src/components/radio/radio.ts +4 -0
- package/src/components/radio/radio.vue +10 -4
- package/src/components/radio/use-radio.ts +16 -2
- package/src/components/table/table.vue +14 -11
|
@@ -44,10 +44,18 @@ export const inputCurrencyPropTypes = {
|
|
|
44
44
|
type: Number,
|
|
45
45
|
default: 2,
|
|
46
46
|
},
|
|
47
|
+
baseValue: {
|
|
48
|
+
type: Number,
|
|
49
|
+
default: undefined,
|
|
50
|
+
},
|
|
47
51
|
displayAsCode: {
|
|
48
52
|
type: Boolean,
|
|
49
53
|
default: true,
|
|
50
54
|
},
|
|
55
|
+
displayAsSymbol: {
|
|
56
|
+
type: Boolean,
|
|
57
|
+
default: false,
|
|
58
|
+
},
|
|
51
59
|
disableRounding: {
|
|
52
60
|
type: Boolean,
|
|
53
61
|
default: false,
|
|
@@ -66,19 +74,8 @@ export const inputCurrencyEmitTypes = {
|
|
|
66
74
|
typeof value.symbol === 'string' &&
|
|
67
75
|
(value.numericValue === null || (typeof value.numericValue === 'number' && !isNaN(value.numericValue))) &&
|
|
68
76
|
(value.rawValue === null || typeof value.rawValue === 'string'),
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
Array.isArray(value) &&
|
|
72
|
-
value.every(
|
|
73
|
-
(item) =>
|
|
74
|
-
item !== null &&
|
|
75
|
-
typeof item === 'object' &&
|
|
76
|
-
typeof item.title === 'string' &&
|
|
77
|
-
typeof item.message === 'string',
|
|
78
|
-
)
|
|
79
|
-
);
|
|
80
|
-
},
|
|
81
|
-
getNumericValue: (value: number): value is number => typeof value === 'number' && !isNaN(value),
|
|
77
|
+
getCurrencyValue: (value: number | null): value is number | null =>
|
|
78
|
+
value === null || (typeof value === 'number' && !isNaN(value)),
|
|
82
79
|
};
|
|
83
80
|
|
|
84
81
|
export interface InputCurrencyEmit {
|
|
@@ -92,8 +89,7 @@ export interface InputCurrencyEmit {
|
|
|
92
89
|
rawValue: string | null;
|
|
93
90
|
},
|
|
94
91
|
): void;
|
|
95
|
-
(event: '
|
|
96
|
-
(event: 'getNumericValue', value: number): void;
|
|
92
|
+
(event: 'getCurrencyValue', value: number | null): void;
|
|
97
93
|
}
|
|
98
94
|
|
|
99
95
|
export type InputCurrencyPropTypes = ExtractPropTypes<typeof inputCurrencyPropTypes>;
|
|
@@ -22,10 +22,10 @@ export const useInputCurrency = (props: InputCurrencyPropTypes, emit: SetupConte
|
|
|
22
22
|
preSelectedCurrency,
|
|
23
23
|
disabledCountryCurrency,
|
|
24
24
|
disabled,
|
|
25
|
-
autoFormat,
|
|
26
25
|
maxDecimals,
|
|
27
26
|
minDecimals,
|
|
28
27
|
disableRounding,
|
|
28
|
+
baseValue,
|
|
29
29
|
} = toRefs(props);
|
|
30
30
|
|
|
31
31
|
const inputCurrencyClasses: ComputedRef<InputCurrencyClasses> = computed(() => {
|
|
@@ -121,97 +121,35 @@ export const useInputCurrency = (props: InputCurrencyPropTypes, emit: SetupConte
|
|
|
121
121
|
return cleaned || null;
|
|
122
122
|
});
|
|
123
123
|
|
|
124
|
-
/**
|
|
125
|
-
* Derive the default fraction digits for a currency using Intl metadata.
|
|
126
|
-
* Falls back to 2 when unavailable.
|
|
127
|
-
*/
|
|
128
|
-
const getCurrencyFractionDigits = (code: string): number => {
|
|
129
|
-
try {
|
|
130
|
-
const fmt = new Intl.NumberFormat('en', { style: 'currency', currency: code });
|
|
131
|
-
const resolved = fmt.resolvedOptions();
|
|
132
|
-
if (resolved && typeof resolved.minimumFractionDigits === 'number') {
|
|
133
|
-
return resolved.minimumFractionDigits;
|
|
134
|
-
}
|
|
135
|
-
} catch {
|
|
136
|
-
/* ignore */
|
|
137
|
-
}
|
|
138
|
-
return 2;
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const currentCurrencyFractionDigits = computed(() => getCurrencyFractionDigits(selected.value.currency));
|
|
142
|
-
|
|
143
124
|
const effectiveMinDecimals = computed(() => {
|
|
144
|
-
// Minimum is the
|
|
125
|
+
// Minimum is just the user's minDecimals value
|
|
145
126
|
const userMin = Math.min(Math.max(0, minDecimals.value), 6);
|
|
146
|
-
return Math.min(6, Math.max(0,
|
|
127
|
+
return Math.min(6, Math.max(0, userMin));
|
|
147
128
|
});
|
|
148
129
|
|
|
149
130
|
const effectiveMaxDecimals = computed(() => {
|
|
150
|
-
// Use
|
|
151
|
-
const native = currentCurrencyFractionDigits.value; // e.g. JPY => 0, USD => 2
|
|
131
|
+
// Use the user-provided maxDecimals value directly (clamped to 0-6)
|
|
152
132
|
const userMax = Math.min(Math.max(0, maxDecimals.value), 6);
|
|
153
|
-
// If user sets max below native, keep native to respect currency standard.
|
|
154
|
-
const adjustedMax = Math.max(native, userMax);
|
|
155
133
|
// Ensure max >= min
|
|
156
|
-
return Math.max(
|
|
134
|
+
return Math.max(userMax, effectiveMinDecimals.value);
|
|
157
135
|
});
|
|
158
136
|
|
|
159
|
-
const clampFractionDigits = (frac: string): string => frac.slice(0, effectiveMaxDecimals.value);
|
|
160
|
-
|
|
161
137
|
const formatNumberForBlur = (value: number): string => {
|
|
162
138
|
const fmt = buildNumberFormat(effectiveMinDecimals.value, effectiveMaxDecimals.value);
|
|
163
|
-
//
|
|
164
|
-
const parts = fmt.formatToParts(value)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
*/
|
|
175
|
-
const handleFormatDisplay = (raw: string): string => {
|
|
176
|
-
if (!autoFormat.value) return raw;
|
|
177
|
-
if (!raw) return '';
|
|
178
|
-
// Detect user decimal char as either '.' or last ','
|
|
179
|
-
let work = raw;
|
|
180
|
-
// Strip spaces
|
|
181
|
-
work = work.replace(/\s+/g, '');
|
|
182
|
-
// Allow only digits, separators, minus
|
|
183
|
-
work = work.replace(/[^0-9,.-]/g, '');
|
|
184
|
-
let sign = '';
|
|
185
|
-
if (work.startsWith('-')) {
|
|
186
|
-
sign = '-';
|
|
187
|
-
work = work.slice(1);
|
|
188
|
-
}
|
|
189
|
-
const lastDot = work.lastIndexOf('.');
|
|
190
|
-
const lastComma = work.lastIndexOf(',');
|
|
191
|
-
const lastSep = Math.max(lastDot, lastComma);
|
|
192
|
-
let intPart: string;
|
|
193
|
-
let fracPart = '';
|
|
194
|
-
if (lastSep !== -1) {
|
|
195
|
-
intPart = work.slice(0, lastSep).replace(/[.,]/g, '');
|
|
196
|
-
fracPart = work.slice(lastSep + 1);
|
|
197
|
-
} else {
|
|
198
|
-
intPart = work.replace(/[.,]/g, '');
|
|
199
|
-
}
|
|
200
|
-
if (!/^[0-9]*$/.test(intPart) || !/^[0-9]*$/.test(fracPart)) return raw;
|
|
201
|
-
const truncatedFrac = clampFractionDigits(fracPart);
|
|
202
|
-
const intNumber = Number(intPart || '0');
|
|
203
|
-
// Use Intl just for grouping integer portion
|
|
204
|
-
const fmtInt = buildNumberFormat(0, 0);
|
|
205
|
-
const groupedInt = fmtInt
|
|
206
|
-
.formatToParts(intNumber)
|
|
207
|
-
.filter((p) => p.type === 'integer' || p.type === 'group')
|
|
208
|
-
.map((p) => p.value)
|
|
209
|
-
.join('');
|
|
210
|
-
if (truncatedFrac.length > 0 || lastSep !== -1) {
|
|
211
|
-
// Use current locale decimal symbol
|
|
212
|
-
return sign + groupedInt + localeSeparators.value.decimal + truncatedFrac;
|
|
139
|
+
// Format the number and get parts
|
|
140
|
+
const parts = fmt.formatToParts(value);
|
|
141
|
+
|
|
142
|
+
// Extract only numeric parts (number, decimal, group)
|
|
143
|
+
let result = '';
|
|
144
|
+
for (const part of parts) {
|
|
145
|
+
if (part.type === 'currency') {
|
|
146
|
+
// Skip currency symbol/code
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
result += part.value;
|
|
213
150
|
}
|
|
214
|
-
|
|
151
|
+
|
|
152
|
+
return result.trim();
|
|
215
153
|
};
|
|
216
154
|
|
|
217
155
|
/**
|
|
@@ -258,39 +196,42 @@ export const useInputCurrency = (props: InputCurrencyPropTypes, emit: SetupConte
|
|
|
258
196
|
return formatNumberForBlur(numeric);
|
|
259
197
|
};
|
|
260
198
|
|
|
261
|
-
const handleCurrencyInput = (event:
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
let raw = inputEl.value;
|
|
199
|
+
const handleCurrencyInput = (event: Event) => {
|
|
200
|
+
const target = event.target as HTMLInputElement;
|
|
201
|
+
let raw = target.value;
|
|
265
202
|
|
|
203
|
+
// Remove spaces
|
|
266
204
|
raw = raw.replace(/\s+/g, '');
|
|
267
205
|
|
|
268
|
-
|
|
206
|
+
// Only allow digits and dots (.) as decimal separator
|
|
207
|
+
// Reject commas (,) during typing - they will be added during formatting on blur
|
|
208
|
+
raw = raw.replace(/[^0-9.]/g, '');
|
|
269
209
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
210
|
+
// Handle multiple dots (keep only the last one as decimal separator)
|
|
211
|
+
const lastDot = raw.lastIndexOf('.');
|
|
212
|
+
if (lastDot !== -1) {
|
|
213
|
+
const beforeDecimal = raw.slice(0, lastDot).replace(/\./g, '');
|
|
214
|
+
const afterDecimal = raw.slice(lastDot + 1).replace(/\./g, '');
|
|
215
|
+
raw = beforeDecimal + '.' + afterDecimal;
|
|
273
216
|
}
|
|
274
217
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
218
|
+
// Just update the value without formatting during typing
|
|
219
|
+
// Formatting happens on blur to avoid cursor jumping
|
|
220
|
+
modelValue.value = raw;
|
|
221
|
+
// Emit numeric value while typing (null for empty, parsed value otherwise)
|
|
222
|
+
const parsedNumeric = raw === '' ? null : Number(raw);
|
|
223
|
+
// Only emit if it's a valid number (not NaN) or null
|
|
224
|
+
if (parsedNumeric === null || !isNaN(parsedNumeric)) {
|
|
225
|
+
emit('getCurrencyValue', parsedNumeric);
|
|
281
226
|
}
|
|
282
|
-
|
|
283
|
-
// Do not truncate fractional digits while typing; allow user to input freely.
|
|
284
|
-
const formatted = handleFormatDisplay(sign + raw);
|
|
285
|
-
|
|
286
|
-
modelValue.value = formatted;
|
|
287
|
-
|
|
288
|
-
emit('getCurrencyErrors', []);
|
|
289
227
|
};
|
|
290
228
|
|
|
291
229
|
const handleBlur = () => {
|
|
292
|
-
//
|
|
293
|
-
if (modelValue.value) {
|
|
230
|
+
// If input is empty and baseValue is provided, use baseValue
|
|
231
|
+
if (!modelValue.value && baseValue && baseValue.value !== undefined) {
|
|
232
|
+
modelValue.value = formatNumberForBlur(baseValue.value);
|
|
233
|
+
} else if (modelValue.value) {
|
|
234
|
+
// Format only if there is a value
|
|
294
235
|
let out = modelValue.value;
|
|
295
236
|
|
|
296
237
|
out = formatOnBlur(out);
|
|
@@ -306,7 +247,11 @@ export const useInputCurrency = (props: InputCurrencyPropTypes, emit: SetupConte
|
|
|
306
247
|
rawValue: rawNumericString.value,
|
|
307
248
|
});
|
|
308
249
|
|
|
309
|
-
|
|
250
|
+
// Emit the numeric value after blur (null for empty, numeric value otherwise)
|
|
251
|
+
// Use setTimeout to ensure the formatted value is set before emitting
|
|
252
|
+
setTimeout(() => {
|
|
253
|
+
emit('getCurrencyValue', numericValue.value ?? null);
|
|
254
|
+
}, 0);
|
|
310
255
|
};
|
|
311
256
|
|
|
312
257
|
const handleSelectedCurrency = (currencyRaw: unknown) => {
|
|
@@ -370,7 +315,7 @@ export const useInputCurrency = (props: InputCurrencyPropTypes, emit: SetupConte
|
|
|
370
315
|
// Re-format current input according to new currency fraction rules only if currency actually changed
|
|
371
316
|
if (preSwitchNumeric !== null && previousCurrency !== found.currency) {
|
|
372
317
|
modelValue.value = formatNumberForBlur(preSwitchNumeric);
|
|
373
|
-
emit('
|
|
318
|
+
emit('getCurrencyValue', preSwitchNumeric);
|
|
374
319
|
}
|
|
375
320
|
}
|
|
376
321
|
};
|
|
@@ -379,7 +324,12 @@ export const useInputCurrency = (props: InputCurrencyPropTypes, emit: SetupConte
|
|
|
379
324
|
popperState.value = state;
|
|
380
325
|
};
|
|
381
326
|
|
|
382
|
-
const dropdownDisplayText = computed(() =>
|
|
327
|
+
const dropdownDisplayText = computed(() => {
|
|
328
|
+
if (props.displayAsSymbol) {
|
|
329
|
+
return selected.value.symbol;
|
|
330
|
+
}
|
|
331
|
+
return props.displayAsCode ? selected.value.currency : selected.value.symbol;
|
|
332
|
+
});
|
|
383
333
|
|
|
384
334
|
// #region - Set Currency Options
|
|
385
335
|
// Collect currency codes first so we can derive ambiguity and symbols deterministically.
|
|
@@ -508,13 +458,32 @@ export const useInputCurrency = (props: InputCurrencyPropTypes, emit: SetupConte
|
|
|
508
458
|
handleSelectedCurrency(preSelectedCurrency.value);
|
|
509
459
|
if (modelValue.value && numericValue.value !== null) {
|
|
510
460
|
modelValue.value = formatNumberForBlur(numericValue.value);
|
|
511
|
-
emit('
|
|
461
|
+
emit('getCurrencyValue', numericValue.value);
|
|
512
462
|
emit('getSelectedCurrencyMeta', {
|
|
513
463
|
currency: selected.value.currency,
|
|
514
464
|
symbol: selected.value.symbol,
|
|
515
465
|
numericValue: numericValue.value,
|
|
516
466
|
rawValue: rawNumericString.value,
|
|
517
467
|
});
|
|
468
|
+
} else if (!modelValue.value && baseValue && baseValue.value !== undefined) {
|
|
469
|
+
// If empty on mount and baseValue is provided, use it
|
|
470
|
+
modelValue.value = formatNumberForBlur(baseValue.value);
|
|
471
|
+
emit('getCurrencyValue', baseValue.value);
|
|
472
|
+
emit('getSelectedCurrencyMeta', {
|
|
473
|
+
currency: selected.value.currency,
|
|
474
|
+
symbol: selected.value.symbol,
|
|
475
|
+
numericValue: baseValue.value,
|
|
476
|
+
rawValue: String(baseValue.value),
|
|
477
|
+
});
|
|
478
|
+
} else {
|
|
479
|
+
// Always emit null for empty on mount
|
|
480
|
+
emit('getCurrencyValue', null);
|
|
481
|
+
emit('getSelectedCurrencyMeta', {
|
|
482
|
+
currency: selected.value.currency,
|
|
483
|
+
symbol: selected.value.symbol,
|
|
484
|
+
numericValue: null,
|
|
485
|
+
rawValue: null,
|
|
486
|
+
});
|
|
518
487
|
}
|
|
519
488
|
});
|
|
520
489
|
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
v-bind="$attrs"
|
|
4
4
|
:class="{ 'spr-cursor-pointer': $attrs.readonly === '' || $attrs.readonly === 'true' || $attrs.readonly }"
|
|
5
5
|
>
|
|
6
|
+
<template v-for="(_, slotName) in $slots" #[slotName]>
|
|
7
|
+
<slot :name="slotName" />
|
|
8
|
+
</template>
|
|
9
|
+
|
|
6
10
|
<template #icon>
|
|
7
11
|
<Icon icon="ph:caret-down" />
|
|
8
12
|
</template>
|
|
@@ -101,6 +101,7 @@ export const inputPropTypes = {
|
|
|
101
101
|
|
|
102
102
|
export const inputEmitTypes = {
|
|
103
103
|
'update:modelValue': (value: string | number): boolean => typeof value === 'string' || typeof value === 'number',
|
|
104
|
+
blur: (event: Event): boolean => event instanceof Event,
|
|
104
105
|
};
|
|
105
106
|
|
|
106
107
|
export type InputEmitTypes = { 'update:modelValue': typeof inputEmitTypes };
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
:disabled="props.disabled"
|
|
25
25
|
:readonly="props.readonly"
|
|
26
26
|
@input="onInput"
|
|
27
|
+
@blur="onBlur"
|
|
27
28
|
/>
|
|
28
29
|
<div v-if="$slots.trailing" :class="inputClasses.trailingSlotClasses">
|
|
29
30
|
<slot name="trailing" />
|
|
@@ -59,7 +60,7 @@ const emit = defineEmits(inputEmitTypes);
|
|
|
59
60
|
const props = defineProps(inputPropTypes);
|
|
60
61
|
const slots = useSlots();
|
|
61
62
|
|
|
62
|
-
const { inputClasses, inputTextRef, onInput, disableClickEvent, currentLength } = useInput(props, emit, slots);
|
|
63
|
+
const { inputClasses, inputTextRef, onInput, onBlur, disableClickEvent, currentLength } = useInput(props, emit, slots);
|
|
63
64
|
</script>
|
|
64
65
|
|
|
65
66
|
<style scoped>
|
|
@@ -161,6 +161,10 @@ export const useInput = (
|
|
|
161
161
|
modelValue.value = value;
|
|
162
162
|
};
|
|
163
163
|
|
|
164
|
+
const onBlur = (event: Event) => {
|
|
165
|
+
emit('blur', event);
|
|
166
|
+
};
|
|
167
|
+
|
|
164
168
|
const disableClickEvent = (event: Event) => {
|
|
165
169
|
if (disabled.value) {
|
|
166
170
|
event.preventDefault();
|
|
@@ -172,6 +176,7 @@ export const useInput = (
|
|
|
172
176
|
inputTextRef,
|
|
173
177
|
inputClasses,
|
|
174
178
|
onInput,
|
|
179
|
+
onBlur,
|
|
175
180
|
disableClickEvent,
|
|
176
181
|
currentLength,
|
|
177
182
|
hasCharLimit,
|
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
import type { PropType, ExtractPropTypes } from 'vue';
|
|
2
|
-
import type { MenuListType } from '../list';
|
|
3
|
-
|
|
4
|
-
export const listItemPropTypes = {
|
|
5
|
-
item: {
|
|
6
|
-
type: Object as PropType<MenuListType>,
|
|
7
|
-
required: true,
|
|
8
|
-
},
|
|
9
|
-
isSelected: {
|
|
10
|
-
type: Boolean,
|
|
11
|
-
required: true,
|
|
12
|
-
},
|
|
13
|
-
classes: {
|
|
14
|
-
type: [String, Array, Object] as PropType<string | string[] | Record<string, boolean>>,
|
|
15
|
-
required: true,
|
|
16
|
-
},
|
|
17
|
-
multiSelect: {
|
|
18
|
-
type: Boolean,
|
|
19
|
-
default: false,
|
|
20
|
-
},
|
|
21
|
-
lozenge: {
|
|
22
|
-
type: Boolean,
|
|
23
|
-
default: false,
|
|
24
|
-
},
|
|
25
|
-
ladderized: {
|
|
26
|
-
type: Boolean,
|
|
27
|
-
default: false,
|
|
28
|
-
},
|
|
29
|
-
noCheck: {
|
|
30
|
-
type: Boolean,
|
|
31
|
-
default: false,
|
|
32
|
-
},
|
|
33
|
-
itemIcon: {
|
|
34
|
-
type: String,
|
|
35
|
-
default: '',
|
|
36
|
-
},
|
|
37
|
-
itemIconTone: {
|
|
38
|
-
type: String,
|
|
39
|
-
default: 'plain',
|
|
40
|
-
},
|
|
41
|
-
itemIconFill: {
|
|
42
|
-
type: Boolean,
|
|
43
|
-
default: false,
|
|
44
|
-
},
|
|
45
|
-
disabledUnselectedItems: {
|
|
46
|
-
type: Boolean,
|
|
47
|
-
default: false,
|
|
48
|
-
},
|
|
49
|
-
radioList: {
|
|
50
|
-
type: Boolean,
|
|
51
|
-
default: false,
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export const listItemEmitTypes = {
|
|
56
|
-
select: () => true,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export type ListItemPropTypes = ExtractPropTypes<typeof listItemPropTypes>;
|
|
60
|
-
export type ListItemEmitTypes = typeof listItemEmitTypes;
|
|
1
|
+
import type { PropType, ExtractPropTypes } from 'vue';
|
|
2
|
+
import type { MenuListType } from '../list';
|
|
3
|
+
|
|
4
|
+
export const listItemPropTypes = {
|
|
5
|
+
item: {
|
|
6
|
+
type: Object as PropType<MenuListType>,
|
|
7
|
+
required: true,
|
|
8
|
+
},
|
|
9
|
+
isSelected: {
|
|
10
|
+
type: Boolean,
|
|
11
|
+
required: true,
|
|
12
|
+
},
|
|
13
|
+
classes: {
|
|
14
|
+
type: [String, Array, Object] as PropType<string | string[] | Record<string, boolean>>,
|
|
15
|
+
required: true,
|
|
16
|
+
},
|
|
17
|
+
multiSelect: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false,
|
|
20
|
+
},
|
|
21
|
+
lozenge: {
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: false,
|
|
24
|
+
},
|
|
25
|
+
ladderized: {
|
|
26
|
+
type: Boolean,
|
|
27
|
+
default: false,
|
|
28
|
+
},
|
|
29
|
+
noCheck: {
|
|
30
|
+
type: Boolean,
|
|
31
|
+
default: false,
|
|
32
|
+
},
|
|
33
|
+
itemIcon: {
|
|
34
|
+
type: String,
|
|
35
|
+
default: '',
|
|
36
|
+
},
|
|
37
|
+
itemIconTone: {
|
|
38
|
+
type: String,
|
|
39
|
+
default: 'plain',
|
|
40
|
+
},
|
|
41
|
+
itemIconFill: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
default: false,
|
|
44
|
+
},
|
|
45
|
+
disabledUnselectedItems: {
|
|
46
|
+
type: Boolean,
|
|
47
|
+
default: false,
|
|
48
|
+
},
|
|
49
|
+
radioList: {
|
|
50
|
+
type: Boolean,
|
|
51
|
+
default: false,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const listItemEmitTypes = {
|
|
56
|
+
select: () => true,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type ListItemPropTypes = ExtractPropTypes<typeof listItemPropTypes>;
|
|
60
|
+
export type ListItemEmitTypes = typeof listItemEmitTypes;
|
|
@@ -375,7 +375,7 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
|
|
|
375
375
|
const getListItemClasses = (item: MenuListType) => ({
|
|
376
376
|
[listClasses.value.listItemClasses]: !item.disabled && !(disabledUnselectedItems.value && !isItemSelected(item)),
|
|
377
377
|
'spr-background-color-single-active': isItemSelected(item) && !item.disabled && !noCheck.value,
|
|
378
|
-
'spr-cursor-not-allowed spr-flex spr-items-center spr-gap-1.5 spr-rounded-lg':
|
|
378
|
+
'spr-cursor-not-allowed spr-flex spr-items-center spr-justify-between spr-gap-1.5 spr-rounded-lg':
|
|
379
379
|
item.disabled || (disabledUnselectedItems.value && !isItemSelected(item)),
|
|
380
380
|
'spr-p-size-spacing-3xs': !props.lozenge,
|
|
381
381
|
'spr-py-size-spacing-3xs spr-px-size-spacing-4xs': props.lozenge,
|
|
@@ -527,13 +527,13 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
|
|
|
527
527
|
} else {
|
|
528
528
|
handleSingleSelect(item);
|
|
529
529
|
}
|
|
530
|
-
}
|
|
530
|
+
}
|
|
531
531
|
};
|
|
532
532
|
|
|
533
533
|
const handleDeselect = (item: MenuListType) => {
|
|
534
534
|
if (selectedItems.value.length === 0 || !isItemSelected(item)) {
|
|
535
|
-
selectedItems.value = [item];
|
|
536
|
-
emit('get-single-selected-item', item);
|
|
535
|
+
selectedItems.value = [item];
|
|
536
|
+
emit('get-single-selected-item', item);
|
|
537
537
|
} else {
|
|
538
538
|
selectedItems.value = [];
|
|
539
539
|
emit('get-single-deselected-item', item);
|
|
@@ -542,8 +542,8 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
|
|
|
542
542
|
|
|
543
543
|
const handleSingleSelect = (item: MenuListType) => {
|
|
544
544
|
selectedItems.value = [item];
|
|
545
|
-
if (item.onClickFn) item.onClickFn();
|
|
546
|
-
emit('get-single-selected-item', item);
|
|
545
|
+
if (item.onClickFn) item.onClickFn();
|
|
546
|
+
emit('get-single-selected-item', item);
|
|
547
547
|
};
|
|
548
548
|
// #endregion - Helper Methods
|
|
549
549
|
|