design-system-next 2.23.0 → 2.24.2
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 +28 -6
- package/dist/design-system-next.es.js +7544 -7332
- 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/App.vue +89 -1
- package/src/components/date-picker/date-picker.vue +2 -2
- package/src/components/date-picker/use-date-picker.ts +41 -33
- package/src/components/dropdown/dropdown.ts +6 -2
- package/src/components/dropdown/dropdown.vue +8 -1
- package/src/components/dropdown/use-dropdown.ts +13 -0
- package/src/components/list/list-item/list-item.ts +60 -60
- package/src/components/radio-grouped/radio-grouped.ts +65 -65
- package/src/components/radio-grouped/use-radio-grouped.ts +62 -62
- package/src/components/sidepanel/sidepanel.ts +4 -0
- package/src/components/sidepanel/sidepanel.vue +3 -1
- package/src/components/sidepanel/use-sidepanel.ts +3 -2
- package/src/components/table/table-header-dropdown/table-header-dropdown.ts +48 -0
- package/src/components/table/table-header-dropdown/table-header-dropdown.vue +84 -0
- package/src/components/table/table-pagination/table-pagination.ts +4 -0
- package/src/components/table/table-pagination/table-pagination.vue +9 -1
- package/src/components/table/table-pagination/use-table-pagination.ts +4 -3
- package/src/components/table/table.ts +9 -1
- package/src/components/table/table.vue +17 -2
- package/src/components/table/use-table.ts +6 -1
package/src/App.vue
CHANGED
|
@@ -1,3 +1,91 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div class="spr-h-[600px] spr-w-[75%]">
|
|
3
|
+
<spr-table
|
|
4
|
+
action
|
|
5
|
+
:headers="headers"
|
|
6
|
+
:data-table="data"
|
|
7
|
+
is-multi-select
|
|
8
|
+
:selected-key-id="'name'"
|
|
9
|
+
show-header-filter
|
|
10
|
+
@on-apply-filter="(filters) => console.log(filters)"
|
|
11
|
+
/>
|
|
12
|
+
</div>
|
|
3
13
|
</template>
|
|
14
|
+
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
import SprTable from './components/table/table.vue';
|
|
17
|
+
import { ref } from 'vue';
|
|
18
|
+
import { Header } from './components/table/table';
|
|
19
|
+
|
|
20
|
+
const headers = ref<Header[]>([
|
|
21
|
+
{ field: 'name', name: 'Role Name', sort: false, hasAvatar: true, hasSubtext: true, width: '250px',
|
|
22
|
+
filterList: [
|
|
23
|
+
{ text: 'Role 11', value: 'role11' },
|
|
24
|
+
{ text: 'Role 12', value: 'role12' },
|
|
25
|
+
{ text: 'Role 13', value: 'role13' },
|
|
26
|
+
{ text: 'Role 14', value: 'role14' },
|
|
27
|
+
{ text: 'Role 15', value: 'role15' }
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
{ field: 'firstUpdate', name: 'Date', sort: false, hasAvatar: false, hasSubtext: false, width: '150px',
|
|
31
|
+
filterList: [
|
|
32
|
+
{ text: 'Jan 10, 2025', value: 'jan10' },
|
|
33
|
+
{ text: 'Jan 11, 2025', value: 'jan11' },
|
|
34
|
+
{ text: 'Jan 12, 2025', value: 'jan12' },
|
|
35
|
+
{ text: 'Jan 13, 2025', value: 'jan13' },
|
|
36
|
+
{ text: 'Jan 14, 2025', value: 'jan14' }
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{ field: 'lastUpdate', name: 'Date', sort: false, hasAvatar: false, hasSubtext: false, width: '150px',
|
|
40
|
+
filterList: [
|
|
41
|
+
{ text: 'Dec 10, 2025', value: 'dec10' },
|
|
42
|
+
{ text: 'Dec 11, 2025', value: 'dec11' },
|
|
43
|
+
{ text: 'Dec 12, 2025', value: 'dec12' },
|
|
44
|
+
{ text: 'Dec 13, 2025', value: 'dec13' },
|
|
45
|
+
{ text: 'Dec 14, 2025', value: 'dec14' }
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{ field: 'note', name: 'Note', sort: false, hasAvatar: false, hasSubtext: true, width: '300px',
|
|
49
|
+
filterList: [
|
|
50
|
+
{ text: 'Note 11', value: 'note11' },
|
|
51
|
+
{ text: 'Note 12', value: 'note12' },
|
|
52
|
+
{ text: 'Note 13', value: 'note13' },
|
|
53
|
+
{ text: 'Note 14', value: 'note14' },
|
|
54
|
+
{ text: 'Note 15', value: 'note15' }
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
{ field: 'status', name: 'Status', sort: false, hasAvatar: false, hasSubtext: true, width: '200px',
|
|
58
|
+
filterList: [
|
|
59
|
+
{ text: 'Success', value: 'success' },
|
|
60
|
+
{ text: 'Pending', value: 'pending' },
|
|
61
|
+
{ text: 'Error', value: 'error' }
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
const data = ref([
|
|
67
|
+
// 40 more elements
|
|
68
|
+
...Array.from({ length: 50 }, (_, i) => ({
|
|
69
|
+
name: {
|
|
70
|
+
title: `Role ${i + 11}`,
|
|
71
|
+
subtext: `Subtext for role ${i + 11}`,
|
|
72
|
+
},
|
|
73
|
+
firstUpdate: {
|
|
74
|
+
title: `Jan ${10 + i}, 2025`,
|
|
75
|
+
subtext: `Subtext for date ${10 + i}`,
|
|
76
|
+
},
|
|
77
|
+
lastUpdate: {
|
|
78
|
+
title: `Dec ${10 + i}, 2025`,
|
|
79
|
+
subtext: `Subtext for date ${10 + i}`,
|
|
80
|
+
},
|
|
81
|
+
note: {
|
|
82
|
+
title: `Note ${i + 11}`,
|
|
83
|
+
subtext: `Subtext for role ${i + 11}`,
|
|
84
|
+
},
|
|
85
|
+
status: {
|
|
86
|
+
title: ['Success', 'Pending', 'Error'][(i + 1) % 3],
|
|
87
|
+
subtext: `Status subtext ${i + 11}`,
|
|
88
|
+
},
|
|
89
|
+
})),
|
|
90
|
+
]);
|
|
91
|
+
</script>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
:placement="props.placement"
|
|
8
8
|
:triggers="[]"
|
|
9
9
|
:popper-hide-triggers="[]"
|
|
10
|
-
:auto-hide="
|
|
10
|
+
:auto-hide="true"
|
|
11
11
|
:disabled="isDatePickerPopperDisabled"
|
|
12
12
|
:container="props.popperContainer ? props.popperContainer : `#${props.id}`"
|
|
13
13
|
:strategy="
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<slot :handle-click="handleSlotClick">
|
|
27
27
|
<div
|
|
28
28
|
ref="datePickerRef"
|
|
29
|
-
:class="datePickerClasses.datePickerBaseInputClasses"
|
|
29
|
+
:class="[datePickerClasses.datePickerBaseInputClasses, 'spr-relative spr-z-10']"
|
|
30
30
|
@click="datePopperState = true"
|
|
31
31
|
>
|
|
32
32
|
<div class="spr-flex spr-h-full spr-items-center spr-gap-1.5">
|
|
@@ -494,6 +494,7 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
494
494
|
handleConvertMonthIfValid();
|
|
495
495
|
calendarTabUpdateCalendar();
|
|
496
496
|
emitDateFormats();
|
|
497
|
+
emitPartialInputValue();
|
|
497
498
|
|
|
498
499
|
datePickerErrors.value = [];
|
|
499
500
|
|
|
@@ -563,6 +564,7 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
563
564
|
handleConvertMonthIfValid();
|
|
564
565
|
calendarTabUpdateCalendar();
|
|
565
566
|
emitDateFormats();
|
|
567
|
+
emitPartialInputValue();
|
|
566
568
|
|
|
567
569
|
datePickerErrors.value = [];
|
|
568
570
|
|
|
@@ -696,14 +698,8 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
696
698
|
|
|
697
699
|
handleValidateDate();
|
|
698
700
|
|
|
699
|
-
//
|
|
700
|
-
|
|
701
|
-
emit('getInputValue', null);
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
if (monthInput.value && dateInput.value && yearInput.value) {
|
|
705
|
-
emitInputValue();
|
|
706
|
-
}
|
|
701
|
+
// Emit the partial date value as user types
|
|
702
|
+
emitPartialInputValue();
|
|
707
703
|
};
|
|
708
704
|
|
|
709
705
|
const handleDateInput = () => {
|
|
@@ -717,14 +713,8 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
717
713
|
|
|
718
714
|
handleValidateDate();
|
|
719
715
|
|
|
720
|
-
//
|
|
721
|
-
|
|
722
|
-
emit('getInputValue', null);
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
if (monthInput.value && dateInput.value && yearInput.value) {
|
|
726
|
-
emitInputValue();
|
|
727
|
-
}
|
|
716
|
+
// Emit the partial date value as user types
|
|
717
|
+
emitPartialInputValue();
|
|
728
718
|
};
|
|
729
719
|
|
|
730
720
|
const handleYearInput = () => {
|
|
@@ -736,20 +726,8 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
736
726
|
|
|
737
727
|
emit('getDateErrors', datePickerErrors.value);
|
|
738
728
|
|
|
739
|
-
//
|
|
740
|
-
|
|
741
|
-
// Only validate if yearInput is 4 digits (full year)
|
|
742
|
-
if (yearInput.value.length === 4) {
|
|
743
|
-
handleValidateDate();
|
|
744
|
-
|
|
745
|
-
if (!monthInput.value && !dateInput.value && !yearInput.value) {
|
|
746
|
-
emit('getInputValue', null);
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
if (monthInput.value && dateInput.value && yearInput.value) {
|
|
750
|
-
emitInputValue();
|
|
751
|
-
}
|
|
752
|
-
}
|
|
729
|
+
// Emit the partial date value as user types
|
|
730
|
+
emitPartialInputValue();
|
|
753
731
|
};
|
|
754
732
|
|
|
755
733
|
const handleConvertMonthIfValid = () => {
|
|
@@ -846,6 +824,36 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
846
824
|
}
|
|
847
825
|
};
|
|
848
826
|
|
|
827
|
+
const emitPartialInputValue = () => {
|
|
828
|
+
// Convert month to numeric format if it's text
|
|
829
|
+
let emittedMonth = monthInput.value;
|
|
830
|
+
|
|
831
|
+
if (monthInput.value) {
|
|
832
|
+
const isNumeric = !isNaN(Number(monthInput.value)) && !isNaN(parseFloat(monthInput.value));
|
|
833
|
+
|
|
834
|
+
if (!isNumeric) {
|
|
835
|
+
const monthIsValid = monthsList.value.find(
|
|
836
|
+
(_month: MonthsList) => _month.text.toLowerCase() === monthInput.value.toLowerCase(),
|
|
837
|
+
);
|
|
838
|
+
|
|
839
|
+
if (monthIsValid) {
|
|
840
|
+
emittedMonth =
|
|
841
|
+
monthIsValid.monthValue < 10 ? `0${monthIsValid.monthValue + 1}` : `${monthIsValid.monthValue + 1}`;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// Build the partial date string with zeros for empty fields
|
|
847
|
+
const partialMonth = emittedMonth || '0';
|
|
848
|
+
const partialDate = dateInput.value || '0';
|
|
849
|
+
const partialYear = yearInput.value || '0';
|
|
850
|
+
|
|
851
|
+
const partialDateString = `${partialMonth}-${partialDate}-${partialYear}`;
|
|
852
|
+
|
|
853
|
+
// Emit the partial date string
|
|
854
|
+
emit('getInputValue', partialDateString);
|
|
855
|
+
};
|
|
856
|
+
|
|
849
857
|
const emitDateFormats = () => {
|
|
850
858
|
if (monthInput.value && dateInput.value && yearInput.value) {
|
|
851
859
|
const monthIsValid = monthsList.value.find(
|
|
@@ -934,8 +942,8 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
934
942
|
};
|
|
935
943
|
|
|
936
944
|
const handleSlotClick = () => {
|
|
937
|
-
if(disabled.value || readonly.value) return;
|
|
938
|
-
datePopperState.value = true;
|
|
945
|
+
if (disabled.value || readonly.value) return;
|
|
946
|
+
datePopperState.value = true;
|
|
939
947
|
};
|
|
940
948
|
|
|
941
949
|
watch(datePopperState, (newValue) => {
|
|
@@ -1037,6 +1045,6 @@ export const useDatePicker = (props: DatePickerPropTypes, emit: SetupContext<Dat
|
|
|
1037
1045
|
handleTabClick,
|
|
1038
1046
|
handleBackspace,
|
|
1039
1047
|
clearDate,
|
|
1040
|
-
handleSlotClick
|
|
1048
|
+
handleSlotClick,
|
|
1041
1049
|
};
|
|
1042
1050
|
};
|
|
@@ -141,13 +141,17 @@ export const dropdownPropTypes = {
|
|
|
141
141
|
type: Boolean,
|
|
142
142
|
default: false,
|
|
143
143
|
},
|
|
144
|
+
noPadding: {
|
|
145
|
+
type: Boolean,
|
|
146
|
+
default: false,
|
|
147
|
+
}
|
|
144
148
|
};
|
|
145
149
|
|
|
146
150
|
export const dropdownEmitTypes = {
|
|
147
|
-
'infinite-scroll-trigger':
|
|
151
|
+
'infinite-scroll-trigger': (value: boolean) => typeof value === 'boolean',
|
|
148
152
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
149
153
|
'update:modelValue': (_value: unknown) => true, // Accept any type of value
|
|
150
|
-
'popper-state':
|
|
154
|
+
'popper-state': (state: boolean) => typeof state === 'boolean',
|
|
151
155
|
};
|
|
152
156
|
|
|
153
157
|
export type DropdownPropTypes = ExtractPropTypes<typeof dropdownPropTypes>;
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
<template #popper>
|
|
33
33
|
<template v-if="$slots.popper">
|
|
34
34
|
<div
|
|
35
|
-
class="spr-overflow-y-auto spr-overflow-x-hidden spr-p-4"
|
|
35
|
+
:class="['spr-overflow-y-auto spr-overflow-x-hidden', !props.noPadding && 'spr-p-4']"
|
|
36
36
|
:style="{
|
|
37
37
|
width: props.popperInnerWidth,
|
|
38
38
|
}"
|
|
@@ -111,5 +111,12 @@ const {
|
|
|
111
111
|
dropdownValue,
|
|
112
112
|
removeCurrentLevelInBackLabel,
|
|
113
113
|
isLadderizedSearch,
|
|
114
|
+
showDropdown,
|
|
115
|
+
hideDropdown,
|
|
114
116
|
} = useDropdown(props, emit);
|
|
117
|
+
|
|
118
|
+
defineExpose({
|
|
119
|
+
showDropdown,
|
|
120
|
+
hideDropdown,
|
|
121
|
+
});
|
|
115
122
|
</script>
|
|
@@ -82,6 +82,17 @@ export const useDropdown = (props: DropdownPropTypes, emit: SetupContext<Dropdow
|
|
|
82
82
|
const dropdownPopperState = ref<boolean>(false);
|
|
83
83
|
const isDropdownPopperDisabled = computed(() => disabled.value);
|
|
84
84
|
|
|
85
|
+
// Exposed methods to show/hide dropdown. This is for custom trigger handling for custom dropdown.
|
|
86
|
+
// To use these methods, set :triggers="[]" on the SprDropdown component to disable default triggers. (reference: https://floating-vue.starpad.dev/api/#shown)
|
|
87
|
+
/* #region - Exposed Methods */
|
|
88
|
+
const showDropdown = () => {
|
|
89
|
+
dropdownPopperState.value = true;
|
|
90
|
+
};
|
|
91
|
+
const hideDropdown = () => {
|
|
92
|
+
dropdownPopperState.value = false;
|
|
93
|
+
};
|
|
94
|
+
/* #endregion - Exposed Methods */
|
|
95
|
+
|
|
85
96
|
const isLadderizedSearch = computed(
|
|
86
97
|
() => ladderized.value && searchString.value !== '' && normalizedValue.value.length === 0,
|
|
87
98
|
);
|
|
@@ -503,5 +514,7 @@ export const useDropdown = (props: DropdownPropTypes, emit: SetupContext<Dropdow
|
|
|
503
514
|
dropdownValue: compatPreSelectedItems, // Use compatible format for lists
|
|
504
515
|
removeCurrentLevelInBackLabel,
|
|
505
516
|
isLadderizedSearch,
|
|
517
|
+
showDropdown,
|
|
518
|
+
hideDropdown,
|
|
506
519
|
};
|
|
507
520
|
};
|
|
@@ -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;
|
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
import type { PropType, ExtractPropTypes } from 'vue';
|
|
2
|
-
|
|
3
|
-
export const definePropType = <T>(val: unknown): PropType<T> => val as PropType<T>;
|
|
4
|
-
|
|
5
|
-
export interface RadioOption {
|
|
6
|
-
text: string;
|
|
7
|
-
value: string | number | boolean;
|
|
8
|
-
disabled?: boolean;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const radioGroupedPropTypes = {
|
|
12
|
-
id: {
|
|
13
|
-
type: String,
|
|
14
|
-
required: true,
|
|
15
|
-
},
|
|
16
|
-
modelValue: {
|
|
17
|
-
type: [String, Number, Boolean],
|
|
18
|
-
},
|
|
19
|
-
name: {
|
|
20
|
-
type: String,
|
|
21
|
-
required: true,
|
|
22
|
-
},
|
|
23
|
-
options: {
|
|
24
|
-
type: Array as PropType<RadioOption[]>,
|
|
25
|
-
required: true,
|
|
26
|
-
default: () => [],
|
|
27
|
-
},
|
|
28
|
-
disabled: {
|
|
29
|
-
type: Boolean,
|
|
30
|
-
default: false,
|
|
31
|
-
},
|
|
32
|
-
description: {
|
|
33
|
-
type: String,
|
|
34
|
-
},
|
|
35
|
-
bordered: {
|
|
36
|
-
type: Boolean,
|
|
37
|
-
default: false,
|
|
38
|
-
},
|
|
39
|
-
displayHelper: {
|
|
40
|
-
type: Boolean,
|
|
41
|
-
default: false,
|
|
42
|
-
},
|
|
43
|
-
helperIcon: {
|
|
44
|
-
type: String,
|
|
45
|
-
default: null,
|
|
46
|
-
},
|
|
47
|
-
helperText: {
|
|
48
|
-
type: String,
|
|
49
|
-
default: '',
|
|
50
|
-
},
|
|
51
|
-
error: {
|
|
52
|
-
type: Boolean,
|
|
53
|
-
default: false,
|
|
54
|
-
},
|
|
55
|
-
horizontalAlign: {
|
|
56
|
-
type: String as PropType<'left' | 'center' | 'right'>,
|
|
57
|
-
default: 'left',
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
export const radioGroupedEmitTypes = ['update:modelValue'];
|
|
62
|
-
|
|
63
|
-
export type RadioGroupedPropTypes = ExtractPropTypes<typeof radioGroupedPropTypes>;
|
|
64
|
-
|
|
65
|
-
export type RadioGroupedEmitTypes = typeof radioGroupedEmitTypes;
|
|
1
|
+
import type { PropType, ExtractPropTypes } from 'vue';
|
|
2
|
+
|
|
3
|
+
export const definePropType = <T>(val: unknown): PropType<T> => val as PropType<T>;
|
|
4
|
+
|
|
5
|
+
export interface RadioOption {
|
|
6
|
+
text: string;
|
|
7
|
+
value: string | number | boolean;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const radioGroupedPropTypes = {
|
|
12
|
+
id: {
|
|
13
|
+
type: String,
|
|
14
|
+
required: true,
|
|
15
|
+
},
|
|
16
|
+
modelValue: {
|
|
17
|
+
type: [String, Number, Boolean],
|
|
18
|
+
},
|
|
19
|
+
name: {
|
|
20
|
+
type: String,
|
|
21
|
+
required: true,
|
|
22
|
+
},
|
|
23
|
+
options: {
|
|
24
|
+
type: Array as PropType<RadioOption[]>,
|
|
25
|
+
required: true,
|
|
26
|
+
default: () => [],
|
|
27
|
+
},
|
|
28
|
+
disabled: {
|
|
29
|
+
type: Boolean,
|
|
30
|
+
default: false,
|
|
31
|
+
},
|
|
32
|
+
description: {
|
|
33
|
+
type: String,
|
|
34
|
+
},
|
|
35
|
+
bordered: {
|
|
36
|
+
type: Boolean,
|
|
37
|
+
default: false,
|
|
38
|
+
},
|
|
39
|
+
displayHelper: {
|
|
40
|
+
type: Boolean,
|
|
41
|
+
default: false,
|
|
42
|
+
},
|
|
43
|
+
helperIcon: {
|
|
44
|
+
type: String,
|
|
45
|
+
default: null,
|
|
46
|
+
},
|
|
47
|
+
helperText: {
|
|
48
|
+
type: String,
|
|
49
|
+
default: '',
|
|
50
|
+
},
|
|
51
|
+
error: {
|
|
52
|
+
type: Boolean,
|
|
53
|
+
default: false,
|
|
54
|
+
},
|
|
55
|
+
horizontalAlign: {
|
|
56
|
+
type: String as PropType<'left' | 'center' | 'right'>,
|
|
57
|
+
default: 'left',
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const radioGroupedEmitTypes = ['update:modelValue'];
|
|
62
|
+
|
|
63
|
+
export type RadioGroupedPropTypes = ExtractPropTypes<typeof radioGroupedPropTypes>;
|
|
64
|
+
|
|
65
|
+
export type RadioGroupedEmitTypes = typeof radioGroupedEmitTypes;
|
|
@@ -1,62 +1,62 @@
|
|
|
1
|
-
import { toRefs, computed, ComputedRef } from 'vue';
|
|
2
|
-
import { useVModel } from '@vueuse/core';
|
|
3
|
-
|
|
4
|
-
import classNames from 'classnames';
|
|
5
|
-
|
|
6
|
-
import type { SetupContext } from 'vue';
|
|
7
|
-
import type { RadioGroupedPropTypes, RadioGroupedEmitTypes, RadioOption } from './radio-grouped';
|
|
8
|
-
|
|
9
|
-
interface RadioGroupedClasses {
|
|
10
|
-
containerClasses: string;
|
|
11
|
-
helperClasses: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const useRadioGrouped = (props: RadioGroupedPropTypes, emit: SetupContext<RadioGroupedEmitTypes>['emit']) => {
|
|
15
|
-
const { disabled, horizontalAlign, displayHelper, error } = toRefs(props);
|
|
16
|
-
|
|
17
|
-
const radioGroupedClasses: ComputedRef<RadioGroupedClasses> = computed(() => {
|
|
18
|
-
const alignmentMap = {
|
|
19
|
-
left: 'spr-justify-start',
|
|
20
|
-
center: 'spr-justify-center',
|
|
21
|
-
right: 'spr-justify-end',
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const containerClasses = classNames('spr-flex spr-flex-col spr-gap-2', {
|
|
25
|
-
[alignmentMap[horizontalAlign.value as keyof typeof alignmentMap]]: true,
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const helperClasses = classNames(
|
|
29
|
-
'spr-flex spr-items-center spr-gap-1 spr-mt-size-spacing-2xs spr-body-sm-regular',
|
|
30
|
-
{
|
|
31
|
-
'spr-text-mushroom-600': !error.value,
|
|
32
|
-
'spr-text-color-danger-base': error.value,
|
|
33
|
-
},
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
containerClasses,
|
|
38
|
-
helperClasses,
|
|
39
|
-
};
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const proxyValue = useVModel(props, 'modelValue', emit);
|
|
43
|
-
|
|
44
|
-
const renderOptions = (): RadioOption[] => {
|
|
45
|
-
return props.options || [];
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const isOptionDisabled = (option: RadioOption): boolean => {
|
|
49
|
-
return disabled.value || (option.disabled ?? false);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
return {
|
|
53
|
-
radioGroupedClasses,
|
|
54
|
-
proxyValue,
|
|
55
|
-
renderOptions,
|
|
56
|
-
isOptionDisabled,
|
|
57
|
-
disabled,
|
|
58
|
-
displayHelper,
|
|
59
|
-
horizontalAlign,
|
|
60
|
-
error,
|
|
61
|
-
};
|
|
62
|
-
};
|
|
1
|
+
import { toRefs, computed, ComputedRef } from 'vue';
|
|
2
|
+
import { useVModel } from '@vueuse/core';
|
|
3
|
+
|
|
4
|
+
import classNames from 'classnames';
|
|
5
|
+
|
|
6
|
+
import type { SetupContext } from 'vue';
|
|
7
|
+
import type { RadioGroupedPropTypes, RadioGroupedEmitTypes, RadioOption } from './radio-grouped';
|
|
8
|
+
|
|
9
|
+
interface RadioGroupedClasses {
|
|
10
|
+
containerClasses: string;
|
|
11
|
+
helperClasses: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const useRadioGrouped = (props: RadioGroupedPropTypes, emit: SetupContext<RadioGroupedEmitTypes>['emit']) => {
|
|
15
|
+
const { disabled, horizontalAlign, displayHelper, error } = toRefs(props);
|
|
16
|
+
|
|
17
|
+
const radioGroupedClasses: ComputedRef<RadioGroupedClasses> = computed(() => {
|
|
18
|
+
const alignmentMap = {
|
|
19
|
+
left: 'spr-justify-start',
|
|
20
|
+
center: 'spr-justify-center',
|
|
21
|
+
right: 'spr-justify-end',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const containerClasses = classNames('spr-flex spr-flex-col spr-gap-2', {
|
|
25
|
+
[alignmentMap[horizontalAlign.value as keyof typeof alignmentMap]]: true,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const helperClasses = classNames(
|
|
29
|
+
'spr-flex spr-items-center spr-gap-1 spr-mt-size-spacing-2xs spr-body-sm-regular',
|
|
30
|
+
{
|
|
31
|
+
'spr-text-mushroom-600': !error.value,
|
|
32
|
+
'spr-text-color-danger-base': error.value,
|
|
33
|
+
},
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
containerClasses,
|
|
38
|
+
helperClasses,
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const proxyValue = useVModel(props, 'modelValue', emit);
|
|
43
|
+
|
|
44
|
+
const renderOptions = (): RadioOption[] => {
|
|
45
|
+
return props.options || [];
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const isOptionDisabled = (option: RadioOption): boolean => {
|
|
49
|
+
return disabled.value || (option.disabled ?? false);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
radioGroupedClasses,
|
|
54
|
+
proxyValue,
|
|
55
|
+
renderOptions,
|
|
56
|
+
isOptionDisabled,
|
|
57
|
+
disabled,
|
|
58
|
+
displayHelper,
|
|
59
|
+
horizontalAlign,
|
|
60
|
+
error,
|
|
61
|
+
};
|
|
62
|
+
};
|