design-system-next 2.26.2 → 2.26.6
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 +95 -68
- package/dist/design-system-next.es.js +5289 -5194
- package/dist/design-system-next.es.js.gz +0 -0
- package/dist/design-system-next.umd.js +11 -11
- 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 -2
- package/src/components/calendar/calendar.vue +16 -2
- package/src/components/calendar/use-calendar.ts +4 -1
- package/src/components/list/list-item/list-item.ts +60 -60
- package/src/components/list/list.ts +6 -2
- package/src/components/list/list.vue +34 -7
- package/src/components/list/use-list.ts +48 -8
- 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/select/select-multiple/select-multiple.ts +4 -0
- package/src/components/select/select-multiple/select-multiple.vue +1 -0
- package/src/components/select/select-multiple/use-select-multiple.ts +12 -1
|
@@ -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;
|
|
@@ -125,8 +125,12 @@ export const listPropTypes = {
|
|
|
125
125
|
},
|
|
126
126
|
allowDeselect: {
|
|
127
127
|
type: Boolean,
|
|
128
|
-
default: false
|
|
129
|
-
}
|
|
128
|
+
default: false,
|
|
129
|
+
},
|
|
130
|
+
allowSelectAll: {
|
|
131
|
+
type: Boolean,
|
|
132
|
+
default: false,
|
|
133
|
+
},
|
|
130
134
|
};
|
|
131
135
|
|
|
132
136
|
export const listEmitTypes = {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="spr-font-main">
|
|
3
3
|
<!-- Header Section -->
|
|
4
|
-
<template
|
|
4
|
+
<template
|
|
5
|
+
v-if="props.searchableMenu || props.displayListItemSelected || (props.multiSelect && props.allowSelectAll)"
|
|
6
|
+
>
|
|
5
7
|
<div :class="listClasses.headerClasses" :style="stickyOffsetStyle">
|
|
6
8
|
<spr-input-search
|
|
7
9
|
v-if="props.searchableMenu"
|
|
@@ -10,12 +12,34 @@
|
|
|
10
12
|
autocomplete="off"
|
|
11
13
|
@keyup="handleSearchKeyup"
|
|
12
14
|
/>
|
|
13
|
-
<
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
<slot name="list-controls">
|
|
16
|
+
<div
|
|
17
|
+
v-if="
|
|
18
|
+
props.supportingDisplayText ||
|
|
19
|
+
props.displayListItemSelected ||
|
|
20
|
+
(props.multiSelect && props.allowSelectAll)
|
|
21
|
+
"
|
|
22
|
+
:class="listClasses.listControlsClasses"
|
|
23
|
+
>
|
|
24
|
+
<span
|
|
25
|
+
v-if="props.supportingDisplayText || props.displayListItemSelected"
|
|
26
|
+
class="spr-label-sm-medium spr-text-color-base spr-block"
|
|
27
|
+
>
|
|
28
|
+
{{ props.supportingDisplayText || `${selectedItems.length} Selected` }}
|
|
29
|
+
</span>
|
|
30
|
+
|
|
31
|
+
<spr-button
|
|
32
|
+
v-if="props.multiSelect && props.allowSelectAll"
|
|
33
|
+
id="select-all-button"
|
|
34
|
+
:class="{ 'spr-ml-auto': true }"
|
|
35
|
+
variant="secondary"
|
|
36
|
+
size="small"
|
|
37
|
+
@click="handleSelectAll"
|
|
38
|
+
>
|
|
39
|
+
{{ hasSelectedItems ? 'Unselect All' : 'Select All' }}
|
|
40
|
+
</spr-button>
|
|
41
|
+
</div>
|
|
42
|
+
</slot>
|
|
19
43
|
</div>
|
|
20
44
|
</template>
|
|
21
45
|
|
|
@@ -103,6 +127,7 @@
|
|
|
103
127
|
import { Icon } from '@iconify/vue';
|
|
104
128
|
|
|
105
129
|
import SprInputSearch from '@/components/input/input-search/input-search.vue';
|
|
130
|
+
import SprButton from '@/components/button/button.vue';
|
|
106
131
|
import ListItem from './list-item/list-item.vue';
|
|
107
132
|
|
|
108
133
|
import { listPropTypes, listEmitTypes } from './list';
|
|
@@ -119,9 +144,11 @@ const {
|
|
|
119
144
|
localizedMenuList,
|
|
120
145
|
groupedMenuList,
|
|
121
146
|
hasGroupedItems,
|
|
147
|
+
hasSelectedItems,
|
|
122
148
|
isItemSelected,
|
|
123
149
|
getListItemClasses,
|
|
124
150
|
handleSelectedItem,
|
|
151
|
+
handleSelectAll,
|
|
125
152
|
handleSearchKeyup,
|
|
126
153
|
} = useList(props, emit);
|
|
127
154
|
</script>
|
|
@@ -9,6 +9,8 @@ import type { ListPropTypes, ListEmitTypes, MenuListType, GroupedMenuListType }
|
|
|
9
9
|
interface ListClasses {
|
|
10
10
|
headerClasses: string;
|
|
11
11
|
listItemClasses: string;
|
|
12
|
+
borderClasses: string;
|
|
13
|
+
listControlsClasses: string;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>['emit']) => {
|
|
@@ -23,13 +25,17 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
|
|
|
23
25
|
disabledUnselectedItems,
|
|
24
26
|
stickySearchOffset,
|
|
25
27
|
allowDeselect,
|
|
28
|
+
allowSelectAll,
|
|
26
29
|
} = toRefs(props);
|
|
27
30
|
|
|
28
31
|
const listClasses: ComputedRef<ListClasses> = computed(() => {
|
|
32
|
+
const borderClasses = classNames('spr-border-color-weak spr-border spr-border-solid');
|
|
33
|
+
|
|
29
34
|
const headerClasses = classNames(
|
|
30
35
|
'spr-sticky spr-z-20',
|
|
31
36
|
'spr-grid spr-gap-3 spr-bg-white-50 spr-px-size-spacing-3xs spr-py-size-spacing-2xs',
|
|
32
|
-
|
|
37
|
+
borderClasses,
|
|
38
|
+
'spr-border-x-0 spr-border-b spr-border-t-0',
|
|
33
39
|
);
|
|
34
40
|
|
|
35
41
|
const listItemClasses = classNames(
|
|
@@ -39,7 +45,9 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
|
|
|
39
45
|
'active:spr-background-color-single-active active:spr-scale-[.98]',
|
|
40
46
|
);
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
const listControlsClasses = classNames('spr-flex spr-w-full spr-items-center');
|
|
49
|
+
|
|
50
|
+
return { headerClasses, listItemClasses, borderClasses, listControlsClasses };
|
|
43
51
|
});
|
|
44
52
|
|
|
45
53
|
const stickyOffsetStyle = computed(() => ({
|
|
@@ -375,7 +383,7 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
|
|
|
375
383
|
const getListItemClasses = (item: MenuListType) => ({
|
|
376
384
|
[listClasses.value.listItemClasses]: !item.disabled && !(disabledUnselectedItems.value && !isItemSelected(item)),
|
|
377
385
|
'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':
|
|
386
|
+
'spr-cursor-not-allowed spr-flex spr-items-center spr-justify-between spr-gap-1.5 spr-rounded-lg':
|
|
379
387
|
item.disabled || (disabledUnselectedItems.value && !isItemSelected(item)),
|
|
380
388
|
'spr-p-size-spacing-3xs': !props.lozenge,
|
|
381
389
|
'spr-py-size-spacing-3xs spr-px-size-spacing-4xs': props.lozenge,
|
|
@@ -527,13 +535,13 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
|
|
|
527
535
|
} else {
|
|
528
536
|
handleSingleSelect(item);
|
|
529
537
|
}
|
|
530
|
-
}
|
|
538
|
+
}
|
|
531
539
|
};
|
|
532
540
|
|
|
533
541
|
const handleDeselect = (item: MenuListType) => {
|
|
534
542
|
if (selectedItems.value.length === 0 || !isItemSelected(item)) {
|
|
535
|
-
selectedItems.value = [item];
|
|
536
|
-
emit('get-single-selected-item', item);
|
|
543
|
+
selectedItems.value = [item];
|
|
544
|
+
emit('get-single-selected-item', item);
|
|
537
545
|
} else {
|
|
538
546
|
selectedItems.value = [];
|
|
539
547
|
emit('get-single-deselected-item', item);
|
|
@@ -542,8 +550,8 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
|
|
|
542
550
|
|
|
543
551
|
const handleSingleSelect = (item: MenuListType) => {
|
|
544
552
|
selectedItems.value = [item];
|
|
545
|
-
if (item.onClickFn) item.onClickFn();
|
|
546
|
-
emit('get-single-selected-item', item);
|
|
553
|
+
if (item.onClickFn) item.onClickFn();
|
|
554
|
+
emit('get-single-selected-item', item);
|
|
547
555
|
};
|
|
548
556
|
// #endregion - Helper Methods
|
|
549
557
|
|
|
@@ -640,6 +648,36 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
|
|
|
640
648
|
event.preventDefault();
|
|
641
649
|
};
|
|
642
650
|
|
|
651
|
+
// Computed property to check if any items are selected
|
|
652
|
+
const hasSelectedItems = computed(() => {
|
|
653
|
+
if (!multiSelect.value || !allowSelectAll.value) return false;
|
|
654
|
+
return selectedItems.value.length > 0;
|
|
655
|
+
});
|
|
656
|
+
|
|
657
|
+
// Function to handle select/unselect all items
|
|
658
|
+
const handleSelectAll = () => {
|
|
659
|
+
if (!multiSelect.value || !allowSelectAll.value) return;
|
|
660
|
+
|
|
661
|
+
const currentItems = hasGroupedItems.value
|
|
662
|
+
? groupedMenuList.value.flatMap((group) => group.items)
|
|
663
|
+
: localizedMenuList.value;
|
|
664
|
+
|
|
665
|
+
// Filter out disabled items
|
|
666
|
+
const enabledItems = currentItems.filter((item) => !item.disabled);
|
|
667
|
+
|
|
668
|
+
if (hasSelectedItems.value) {
|
|
669
|
+
// If any items are selected, unselect all items completely
|
|
670
|
+
selectedItems.value = [];
|
|
671
|
+
// Also clear any preserved or API selected items
|
|
672
|
+
apiSelectedList.value = [];
|
|
673
|
+
emit('update:modelValue', []);
|
|
674
|
+
} else {
|
|
675
|
+
// If no items are selected, select all enabled items
|
|
676
|
+
selectedItems.value = [...enabledItems];
|
|
677
|
+
emit('update:modelValue', [...enabledItems]);
|
|
678
|
+
}
|
|
679
|
+
};
|
|
680
|
+
|
|
643
681
|
return {
|
|
644
682
|
listClasses,
|
|
645
683
|
stickyOffsetStyle,
|
|
@@ -650,10 +688,12 @@ export const useList = (props: ListPropTypes, emit: SetupContext<ListEmitTypes>[
|
|
|
650
688
|
apiSelectedList,
|
|
651
689
|
isParentMenu,
|
|
652
690
|
hasGroupedItems,
|
|
691
|
+
hasSelectedItems,
|
|
653
692
|
isItemSelected,
|
|
654
693
|
getListItemClasses,
|
|
655
694
|
handleSearch,
|
|
656
695
|
handleSelectedItem,
|
|
696
|
+
handleSelectAll,
|
|
657
697
|
trackNewlySelectedItems,
|
|
658
698
|
handleSearchKeyup,
|
|
659
699
|
};
|
|
@@ -1,65 +1,74 @@
|
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
+
description?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const radioGroupedPropTypes = {
|
|
13
|
+
id: {
|
|
14
|
+
type: String,
|
|
15
|
+
required: true,
|
|
16
|
+
},
|
|
17
|
+
modelValue: {
|
|
18
|
+
type: [String, Number, Boolean],
|
|
19
|
+
},
|
|
20
|
+
name: {
|
|
21
|
+
type: String,
|
|
22
|
+
required: true,
|
|
23
|
+
},
|
|
24
|
+
options: {
|
|
25
|
+
type: Array as PropType<RadioOption[]>,
|
|
26
|
+
required: true,
|
|
27
|
+
default: () => [],
|
|
28
|
+
},
|
|
29
|
+
disabled: {
|
|
30
|
+
type: Boolean,
|
|
31
|
+
default: false,
|
|
32
|
+
},
|
|
33
|
+
description: {
|
|
34
|
+
type: String,
|
|
35
|
+
},
|
|
36
|
+
fullWidth: {
|
|
37
|
+
type: Boolean,
|
|
38
|
+
default: false,
|
|
39
|
+
},
|
|
40
|
+
bordered: {
|
|
41
|
+
type: Boolean,
|
|
42
|
+
default: false,
|
|
43
|
+
},
|
|
44
|
+
displayHelper: {
|
|
45
|
+
type: Boolean,
|
|
46
|
+
default: false,
|
|
47
|
+
},
|
|
48
|
+
helperIcon: {
|
|
49
|
+
type: String,
|
|
50
|
+
default: null,
|
|
51
|
+
},
|
|
52
|
+
helperText: {
|
|
53
|
+
type: String,
|
|
54
|
+
default: '',
|
|
55
|
+
},
|
|
56
|
+
error: {
|
|
57
|
+
type: Boolean,
|
|
58
|
+
default: false,
|
|
59
|
+
},
|
|
60
|
+
horizontalAlign: {
|
|
61
|
+
type: String as PropType<'left' | 'center' | 'right'>,
|
|
62
|
+
default: 'left',
|
|
63
|
+
},
|
|
64
|
+
choiceBox: {
|
|
65
|
+
type: Boolean,
|
|
66
|
+
default: false,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const radioGroupedEmitTypes = ['update:modelValue'];
|
|
71
|
+
|
|
72
|
+
export type RadioGroupedPropTypes = ExtractPropTypes<typeof radioGroupedPropTypes>;
|
|
73
|
+
|
|
74
|
+
export type RadioGroupedEmitTypes = typeof radioGroupedEmitTypes;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div :class="['spr-relative']">
|
|
2
|
+
<div :class="['spr-relative', { 'spr-w-full': props.choiceBox || props.fullWidth }]">
|
|
3
3
|
<div :class="radioGroupedClasses.containerClasses">
|
|
4
4
|
<spr-radio
|
|
5
5
|
v-for="(option, index) in renderOptions()"
|
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
:name="props.name"
|
|
10
10
|
:value="option.value"
|
|
11
11
|
:disabled="isOptionDisabled(option)"
|
|
12
|
+
:choice-box="props.choiceBox"
|
|
13
|
+
:full-width="props.fullWidth || props.choiceBox"
|
|
14
|
+
:description="option.description"
|
|
12
15
|
>
|
|
13
16
|
{{ option.text }}
|
|
14
17
|
</spr-radio>
|
|
@@ -1,62 +1,63 @@
|
|
|
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, choiceBox } = 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
|
+
choiceBox,
|
|
62
|
+
};
|
|
63
|
+
};
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
:class="radioClasses.baseClasses"
|
|
4
|
+
@click="radioRef?.click()"
|
|
5
|
+
@mouseenter="isHovered = true"
|
|
6
|
+
@mouseleave="isHovered = false"
|
|
7
|
+
>
|
|
3
8
|
<input
|
|
4
9
|
:id="props.id"
|
|
5
10
|
ref="radioRef"
|
|
@@ -8,7 +13,7 @@
|
|
|
8
13
|
:name="props.name"
|
|
9
14
|
:value="props.value"
|
|
10
15
|
:disabled="props.disabled"
|
|
11
|
-
:class="radioClasses.
|
|
16
|
+
:class="radioClasses.baseInputClasses"
|
|
12
17
|
/>
|
|
13
18
|
<label
|
|
14
19
|
ref="radioRef"
|
|
@@ -25,8 +30,9 @@
|
|
|
25
30
|
'spr-text-xs spr-font-normal spr-leading-4 spr-text-mushroom-600',
|
|
26
31
|
{ 'spr-text-color-disabled': props.disabled },
|
|
27
32
|
]"
|
|
28
|
-
>{{ props.description }}</span
|
|
29
33
|
>
|
|
34
|
+
{{ props.description }}
|
|
35
|
+
</span>
|
|
30
36
|
</div>
|
|
31
37
|
</label>
|
|
32
38
|
</div>
|
|
@@ -42,7 +48,7 @@ const props = defineProps(radioPropTypes);
|
|
|
42
48
|
const emit = defineEmits(radioEmitTypes);
|
|
43
49
|
const slots = useSlots();
|
|
44
50
|
|
|
45
|
-
const { proxyValue, radioRef, radioClasses } = useRadioButton(props, emit, slots);
|
|
51
|
+
const { proxyValue, radioRef, radioClasses, isHovered } = useRadioButton(props, emit, slots);
|
|
46
52
|
</script>
|
|
47
53
|
|
|
48
54
|
<style scoped>
|