design-system-next 1.8.2 → 1.9.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.js +4434 -4047
- package/dist/design-system-next.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 +9 -671
- package/src/assets/styles/tailwind.css +2 -2
- package/src/components/calendar-cell/use-calendar-cell.ts +1 -1
- package/src/components/checkbox/checkbox.ts +5 -1
- package/src/components/checkbox/checkbox.vue +1 -1
- package/src/components/checkbox/use-checkbox.ts +8 -10
- package/src/components/date-picker/date-picker.ts +8 -1
- package/src/components/date-picker/date-picker.vue +6 -1
- package/src/components/dropdown/dropdown.ts +45 -17
- package/src/components/dropdown/dropdown.vue +35 -27
- package/src/components/dropdown/use-dropdown.ts +38 -87
- package/src/components/input/input.ts +38 -6
- package/src/components/input/input.vue +4 -1
- package/src/components/input/use-input.ts +17 -13
- package/src/components/list/list.ts +34 -0
- package/src/components/list/list.vue +64 -0
- package/src/components/list/use-list.ts +149 -0
- package/src/components/modal/modal.ts +12 -7
- package/src/components/modal/modal.vue +74 -34
- package/src/components/modal/use-modal.ts +69 -35
|
@@ -66,7 +66,7 @@ export const useCalendarCell = (props: CalendarCellPropTypes) => {
|
|
|
66
66
|
|
|
67
67
|
const getCalendarCellClassess = computed(() => {
|
|
68
68
|
const calendarCellWrapper =
|
|
69
|
-
'spr-flex spr-items-center spr-gap-size-spacing-3xs spr-relative spr-w-[217px] spr-rounded-md spr-border-2 spr-p-3 spr-transition-all hover:spr-shadow-md';
|
|
69
|
+
'spr-flex spr-items-center spr-gap-size-spacing-3xs spr-relative spr-max-w-[217px] spr-rounded-md spr-border-2 spr-p-3 spr-transition-all hover:spr-shadow-md';
|
|
70
70
|
|
|
71
71
|
const statusCellClasses = classNames({
|
|
72
72
|
'spr-border-dashed': props.status === 'pending',
|
|
@@ -5,7 +5,7 @@ export const definePropType = <T>(val: unknown): PropType<T> => val as PropType<
|
|
|
5
5
|
export const checkboxPropTypes = {
|
|
6
6
|
modelValue: {
|
|
7
7
|
type: Boolean,
|
|
8
|
-
|
|
8
|
+
default: false,
|
|
9
9
|
},
|
|
10
10
|
label: {
|
|
11
11
|
type: String,
|
|
@@ -19,6 +19,10 @@ export const checkboxPropTypes = {
|
|
|
19
19
|
type: Boolean,
|
|
20
20
|
default: false,
|
|
21
21
|
},
|
|
22
|
+
checked: {
|
|
23
|
+
type: Boolean,
|
|
24
|
+
default: true,
|
|
25
|
+
},
|
|
22
26
|
};
|
|
23
27
|
|
|
24
28
|
export const checkboxEmitTypes = {};
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
<div class="spr-relative spr-flex spr-items-center">
|
|
4
4
|
<input
|
|
5
5
|
type="checkbox"
|
|
6
|
-
:checked="props.modelValue"
|
|
7
6
|
:class="checkboxClasses.inputCheckboxClasses"
|
|
8
7
|
:disabled="props.disabled"
|
|
8
|
+
:checked="props.modelValue || props.checked"
|
|
9
9
|
@change="handleCheckbox"
|
|
10
10
|
/>
|
|
11
11
|
<span :class="checkboxClasses.inputCheckboxCheckIconClasses">
|
|
@@ -13,12 +13,8 @@ interface CheckboxClasses {
|
|
|
13
13
|
descriptionClasses: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
interface CheckboxEvent extends Event {
|
|
17
|
-
target: HTMLInputElement;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
16
|
export const useCheckbox = (props: CheckboxPropTypes, emit: SetupContext<CheckboxEmitTypes>['emit']) => {
|
|
21
|
-
const { modelValue, disabled } = toRefs(props);
|
|
17
|
+
const { modelValue, disabled, checked } = toRefs(props);
|
|
22
18
|
|
|
23
19
|
const checkboxClasses: ComputedRef<CheckboxClasses> = computed(() => {
|
|
24
20
|
const baseClasses = classNames(
|
|
@@ -33,8 +29,8 @@ export const useCheckbox = (props: CheckboxPropTypes, emit: SetupContext<Checkbo
|
|
|
33
29
|
'spr-h-5 spr-w-5 spr-appearance-none spr-rounded-[2.5px] spr-border-color-supporting spr-border-[1.25px] spr-border-solid',
|
|
34
30
|
'spr-transition spr-duration-150 spr-ease-in-out',
|
|
35
31
|
{
|
|
36
|
-
'spr-background-color-brand-base spr-border-color-brand-base': modelValue.value,
|
|
37
|
-
'spr-border-color-disabled spr-background-color-base spr-cursor-not-allowed': disabled.value,
|
|
32
|
+
'spr-background-color-brand-base spr-border-color-brand-base': modelValue.value || checked.value,
|
|
33
|
+
'spr-border-color-disabled spr-background-color-base spr-cursor-not-allowed': disabled.value || checked.value,
|
|
38
34
|
'spr-cursor-pointer': !disabled.value,
|
|
39
35
|
},
|
|
40
36
|
);
|
|
@@ -42,7 +38,7 @@ export const useCheckbox = (props: CheckboxPropTypes, emit: SetupContext<Checkbo
|
|
|
42
38
|
const inputCheckboxCheckIconClasses = classNames(
|
|
43
39
|
'spr-flex spr-items-center spr-justify-center spr-pointer-events-none spr-absolute spr-left-1/2 spr-top-1/2 -spr-translate-x-1/2 -spr-translate-y-1/2 spr-transform spr-font-bold spr-opacity-0',
|
|
44
40
|
{
|
|
45
|
-
'spr-opacity-100': modelValue.value,
|
|
41
|
+
'spr-opacity-100': modelValue.value || checked.value,
|
|
46
42
|
'spr-text-color-inverted-strong': !disabled.value,
|
|
47
43
|
'spr-text-color-on-fill-disabled': disabled.value,
|
|
48
44
|
},
|
|
@@ -65,8 +61,10 @@ export const useCheckbox = (props: CheckboxPropTypes, emit: SetupContext<Checkbo
|
|
|
65
61
|
};
|
|
66
62
|
});
|
|
67
63
|
|
|
68
|
-
const handleCheckbox = (
|
|
69
|
-
|
|
64
|
+
const handleCheckbox = (event: Event): void => {
|
|
65
|
+
if (event.target instanceof HTMLInputElement) {
|
|
66
|
+
emit('update:modelValue', event.target.checked);
|
|
67
|
+
}
|
|
70
68
|
};
|
|
71
69
|
|
|
72
70
|
return {
|
|
@@ -4,10 +4,12 @@ export const definePropType = <T>(val: unknown): PropType<T> => val as PropType<
|
|
|
4
4
|
|
|
5
5
|
export const REST_DAYS_TYPES = ['su', 'mo', 'tu', 'we', 'th', 'fr', 'sa'] as const;
|
|
6
6
|
|
|
7
|
+
const POPPER_STRATEGY_TYPES = ['fixed', 'absolute'] as const;
|
|
8
|
+
|
|
7
9
|
export const datePickerPropTypes = {
|
|
8
10
|
id: {
|
|
9
11
|
type: String,
|
|
10
|
-
|
|
12
|
+
required: true,
|
|
11
13
|
},
|
|
12
14
|
modelValue: {
|
|
13
15
|
type: String,
|
|
@@ -70,6 +72,11 @@ export const datePickerPropTypes = {
|
|
|
70
72
|
type: String,
|
|
71
73
|
default: '100%',
|
|
72
74
|
},
|
|
75
|
+
popperStrategy: {
|
|
76
|
+
type: String,
|
|
77
|
+
validator: (value: 'fixed' | 'absolute') => POPPER_STRATEGY_TYPES.includes(value),
|
|
78
|
+
default: 'absolute',
|
|
79
|
+
},
|
|
73
80
|
};
|
|
74
81
|
|
|
75
82
|
export type RestDayType = (typeof REST_DAYS_TYPES)[number];
|
|
@@ -9,11 +9,16 @@
|
|
|
9
9
|
:popper-hide-triggers="[]"
|
|
10
10
|
:auto-hide="false"
|
|
11
11
|
:disabled="isDatePickerPopperDisabled"
|
|
12
|
+
:container="`#${props.id}`"
|
|
13
|
+
:strategy="
|
|
14
|
+
props.popperStrategy === 'fixed' || props.popperStrategy === 'absolute' ? props.popperStrategy : 'absolute'
|
|
15
|
+
"
|
|
16
|
+
:delay="0"
|
|
12
17
|
:style="{
|
|
13
18
|
width: props.width,
|
|
14
19
|
}"
|
|
15
20
|
>
|
|
16
|
-
<div class="spr-grid spr-gap-2">
|
|
21
|
+
<div :id="props.id" class="spr-grid spr-gap-2">
|
|
17
22
|
<label v-if="props.label" :for="props.id" :class="datePickerClasses.labelClasses">
|
|
18
23
|
{{ props.label }}
|
|
19
24
|
</label>
|
|
@@ -2,8 +2,9 @@ import type { PropType, ExtractPropTypes } from 'vue';
|
|
|
2
2
|
|
|
3
3
|
export const definePropType = <T>(val: unknown): PropType<T> => val as PropType<T>;
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
|
|
5
|
+
const GROUPED_ITEMS_BY_TYPES = ['A-Z', 'Z-A'] as const;
|
|
6
|
+
|
|
7
|
+
const PLACEMENTS_TYPES = [
|
|
7
8
|
'auto',
|
|
8
9
|
'auto-start',
|
|
9
10
|
'auto-end',
|
|
@@ -21,41 +22,68 @@ const PLACEMENTS = [
|
|
|
21
22
|
'left-end',
|
|
22
23
|
] as const;
|
|
23
24
|
|
|
25
|
+
const POPPER_STRATEGY_TYPES = ['fixed', 'absolute'] as const;
|
|
26
|
+
|
|
24
27
|
export type DropdownMenuType = {
|
|
25
28
|
text: string;
|
|
26
29
|
value: string;
|
|
27
30
|
};
|
|
28
31
|
|
|
29
32
|
export const dropdownPropTypes = {
|
|
30
|
-
|
|
31
|
-
type:
|
|
33
|
+
id: {
|
|
34
|
+
type: String,
|
|
32
35
|
required: true,
|
|
33
|
-
default: [],
|
|
34
36
|
},
|
|
35
|
-
|
|
36
|
-
type: Array
|
|
37
|
-
default: [],
|
|
37
|
+
modelValue: {
|
|
38
|
+
type: Array as PropType<string[]>,
|
|
39
|
+
default: () => [],
|
|
38
40
|
},
|
|
39
|
-
|
|
40
|
-
type:
|
|
41
|
-
validator: (value: (typeof DROPDOWN_TYPES)[number]) => DROPDOWN_TYPES.includes(value),
|
|
41
|
+
menuList: {
|
|
42
|
+
type: Array as PropType<{ text: string; value: string }[]>,
|
|
42
43
|
required: true,
|
|
43
|
-
default:
|
|
44
|
+
default: [],
|
|
44
45
|
},
|
|
45
|
-
|
|
46
|
+
searchString: {
|
|
46
47
|
type: String,
|
|
47
|
-
|
|
48
|
-
default: 'bottom',
|
|
48
|
+
default: '',
|
|
49
49
|
},
|
|
50
|
-
|
|
50
|
+
multiSelect: {
|
|
51
51
|
type: Boolean,
|
|
52
52
|
default: false,
|
|
53
53
|
},
|
|
54
|
+
placement: {
|
|
55
|
+
type: String as PropType<(typeof PLACEMENTS_TYPES)[number]>,
|
|
56
|
+
validator: (value: (typeof PLACEMENTS_TYPES)[number]) => PLACEMENTS_TYPES.includes(value),
|
|
57
|
+
default: 'bottom',
|
|
58
|
+
},
|
|
59
|
+
groupItemsBy: {
|
|
60
|
+
type: String as PropType<(typeof GROUPED_ITEMS_BY_TYPES)[number]>,
|
|
61
|
+
validator: (value: (typeof GROUPED_ITEMS_BY_TYPES)[number] | undefined) => {
|
|
62
|
+
return value === undefined || GROUPED_ITEMS_BY_TYPES.includes(value);
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
wrapperPosition: {
|
|
66
|
+
type: String,
|
|
67
|
+
default: 'relative',
|
|
68
|
+
},
|
|
69
|
+
width: {
|
|
70
|
+
type: String,
|
|
71
|
+
default: '100%',
|
|
72
|
+
},
|
|
73
|
+
popperWidth: {
|
|
74
|
+
type: String,
|
|
75
|
+
default: '100%',
|
|
76
|
+
},
|
|
77
|
+
popperStrategy: {
|
|
78
|
+
type: String,
|
|
79
|
+
validator: (value: 'fixed' | 'absolute') => POPPER_STRATEGY_TYPES.includes(value),
|
|
80
|
+
default: 'absolute',
|
|
81
|
+
},
|
|
54
82
|
};
|
|
55
83
|
|
|
56
84
|
export const dropdownEmitTypes = {
|
|
57
85
|
'get-selected-item': Object,
|
|
58
|
-
'
|
|
86
|
+
'infinite-scroll-trigger': Boolean,
|
|
59
87
|
};
|
|
60
88
|
|
|
61
89
|
export type DropdownPropTypes = ExtractPropTypes<typeof dropdownPropTypes>;
|
|
@@ -1,40 +1,49 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Menu
|
|
3
|
-
v-model:shown="
|
|
4
|
-
class="spr-w-fit"
|
|
3
|
+
v-model:shown="dropdownPopperState"
|
|
5
4
|
aria-id="dropdown-wrapper"
|
|
6
5
|
distance="4"
|
|
7
6
|
:placement="props.placement"
|
|
8
7
|
:triggers="[]"
|
|
9
8
|
:popper-hide-triggers="[]"
|
|
9
|
+
:auto-hide="false"
|
|
10
|
+
:container="`#${props.id}`"
|
|
11
|
+
:strategy="
|
|
12
|
+
props.popperStrategy === 'fixed' || props.popperStrategy === 'absolute' ? props.popperStrategy : 'absolute'
|
|
13
|
+
"
|
|
14
|
+
:delay="0"
|
|
15
|
+
:style="{
|
|
16
|
+
position: props.wrapperPosition,
|
|
17
|
+
width: props.width,
|
|
18
|
+
}"
|
|
10
19
|
>
|
|
11
|
-
<div @click="
|
|
20
|
+
<div @click="dropdownPopperState = true">
|
|
12
21
|
<slot />
|
|
13
22
|
</div>
|
|
14
23
|
|
|
24
|
+
<div
|
|
25
|
+
:id="props.id"
|
|
26
|
+
:style="{
|
|
27
|
+
width: props.popperWidth,
|
|
28
|
+
}"
|
|
29
|
+
></div>
|
|
30
|
+
|
|
15
31
|
<template #popper>
|
|
16
|
-
<div class="spr-grid spr-gap-0.5">
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
},
|
|
25
|
-
]"
|
|
26
|
-
@click="handleSelectedItem(item)"
|
|
27
|
-
>
|
|
28
|
-
<spr-checkbox v-if="props.dropdownType === 'multi-select'" v-model="checkboxModels[item.text]" />
|
|
29
|
-
<div class="spr-flex spr-w-full spr-items-center">
|
|
30
|
-
<span class="spr-text-xs">{{ item.text }}</span>
|
|
31
|
-
</div>
|
|
32
|
-
<Icon
|
|
33
|
-
v-if="props.dropdownType === 'single-select' && isItemSelected(item)"
|
|
34
|
-
class="spr-text-color-brand-base spr-w-[1.39em]"
|
|
35
|
-
icon="ph:check"
|
|
32
|
+
<div ref="dropdownRef" class="spr-grid spr-max-h-[300px] spr-gap-0.5 spr-overflow-y-auto spr-p-2">
|
|
33
|
+
<template v-if="dropdownMenuList.length > 0">
|
|
34
|
+
<SprList
|
|
35
|
+
v-model="preSelectedItems"
|
|
36
|
+
:menu-list="dropdownMenuList"
|
|
37
|
+
:group-items-by="props.groupItemsBy"
|
|
38
|
+
:multi-select="props.multiSelect"
|
|
39
|
+
@get-selected-item="handleSelectedItem"
|
|
36
40
|
/>
|
|
37
|
-
</
|
|
41
|
+
</template>
|
|
42
|
+
<template v-else>
|
|
43
|
+
<div class="spr-flex spr-items-center spr-justify-center spr-p-2 spr-text-center">
|
|
44
|
+
<span class="spr-body-sm-regular spr-m-0">No results found</span>
|
|
45
|
+
</div>
|
|
46
|
+
</template>
|
|
38
47
|
</div>
|
|
39
48
|
</template>
|
|
40
49
|
</Menu>
|
|
@@ -42,19 +51,18 @@
|
|
|
42
51
|
|
|
43
52
|
<script lang="ts" setup>
|
|
44
53
|
import { Menu } from 'floating-vue';
|
|
45
|
-
import { Icon } from '@iconify/vue';
|
|
46
54
|
|
|
47
55
|
import 'floating-vue/dist/style.css';
|
|
48
56
|
|
|
49
57
|
import { dropdownPropTypes, dropdownEmitTypes } from './dropdown';
|
|
50
58
|
import { useDropdown } from './use-dropdown';
|
|
51
59
|
|
|
52
|
-
import
|
|
60
|
+
import SprList from '../list/list.vue';
|
|
53
61
|
|
|
54
62
|
const props = defineProps(dropdownPropTypes);
|
|
55
63
|
const emit = defineEmits(dropdownEmitTypes);
|
|
56
64
|
|
|
57
|
-
const {
|
|
65
|
+
const { dropdownPopperState, dropdownRef, preSelectedItems, dropdownMenuList, handleSelectedItem } = useDropdown(
|
|
58
66
|
props,
|
|
59
67
|
emit,
|
|
60
68
|
);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { ref, toRefs, onMounted, watch
|
|
2
|
-
|
|
3
|
-
import classNames from 'classnames';
|
|
1
|
+
import { ref, toRefs, onMounted, watch } from 'vue';
|
|
2
|
+
import { onClickOutside, useInfiniteScroll } from '@vueuse/core';
|
|
4
3
|
|
|
5
4
|
import type { SetupContext } from 'vue';
|
|
6
5
|
import type { DropdownPropTypes, DropdownEmitTypes } from './dropdown';
|
|
@@ -11,115 +10,67 @@ interface SelectedItem {
|
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
export const useDropdown = (props: DropdownPropTypes, emit: SetupContext<DropdownEmitTypes>['emit']) => {
|
|
14
|
-
const {
|
|
15
|
-
|
|
16
|
-
const dropdownItemBaseClasses: ComputedRef<string> = computed(() => {
|
|
17
|
-
return classNames(
|
|
18
|
-
'spr-flex spr-cursor-pointer spr-items-center spr-justify-between spr-gap-1.5 spr-rounded-lg spr-p-2',
|
|
19
|
-
'spr-transition spr-duration-150 spr-ease-in-out',
|
|
20
|
-
'hover:spr-background-color-hover',
|
|
21
|
-
'active:spr-background-color-single-active active:spr-scale-95',
|
|
22
|
-
);
|
|
23
|
-
});
|
|
13
|
+
const { modelValue, menuList, searchString, multiSelect } = toRefs(props);
|
|
24
14
|
|
|
25
|
-
const
|
|
15
|
+
const dropdownPopperState = ref<boolean>(false);
|
|
26
16
|
|
|
27
|
-
|
|
28
|
-
handlePopperState();
|
|
29
|
-
});
|
|
17
|
+
const dropdownRef = ref<HTMLDivElement | null>(null);
|
|
30
18
|
|
|
31
|
-
const
|
|
32
|
-
const isMultiSelect = computed(() => dropdownType.value === 'multi-select');
|
|
19
|
+
const preSelectedItems = ref<Array<string>>([]);
|
|
33
20
|
|
|
34
|
-
const
|
|
21
|
+
const initialMenuList = ref<{ text: string; value: string }[]>([]);
|
|
22
|
+
const dropdownMenuList = ref<{ text: string; value: string }[]>([]);
|
|
35
23
|
|
|
36
24
|
const handleSelectedItem = (item: SelectedItem) => {
|
|
37
|
-
if (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
selectedItems.value = [item];
|
|
41
|
-
|
|
42
|
-
emit('get-selected-item', selectedItems.value[0]);
|
|
25
|
+
if (!multiSelect.value) {
|
|
26
|
+
dropdownPopperState.value = false;
|
|
43
27
|
}
|
|
44
28
|
|
|
45
|
-
|
|
46
|
-
const index = selectedItems.value.findIndex((selectedItem: SelectedItem) => selectedItem.value === item.value);
|
|
47
|
-
|
|
48
|
-
if (index === -1) {
|
|
49
|
-
checkboxModels.value[item.text] = true;
|
|
50
|
-
selectedItems.value.push(item);
|
|
51
|
-
} else {
|
|
52
|
-
checkboxModels.value[item.text] = false;
|
|
53
|
-
selectedItems.value.splice(index, 1);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
emit('get-selected-item', selectedItems.value);
|
|
57
|
-
}
|
|
29
|
+
emit('get-selected-item', item);
|
|
58
30
|
};
|
|
59
31
|
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return (selectedItems.value[0] as SelectedItem).text === item.text;
|
|
32
|
+
const setDropdownMenuList = () => {
|
|
33
|
+
initialMenuList.value = menuList.value;
|
|
34
|
+
dropdownMenuList.value = initialMenuList.value;
|
|
66
35
|
};
|
|
67
36
|
|
|
68
|
-
const
|
|
37
|
+
const handleSearch = () => {
|
|
38
|
+
if (menuList.value && menuList.value.length > 0) {
|
|
39
|
+
dropdownMenuList.value = initialMenuList.value.filter((item) => {
|
|
40
|
+
const searchTerm = searchString.value.toLowerCase();
|
|
69
41
|
|
|
70
|
-
|
|
71
|
-
if (menu.value && menu.value.length > 0) {
|
|
72
|
-
menu.value.forEach((item) => {
|
|
73
|
-
checkboxModels.value = Object.assign({}, checkboxModels.value, {
|
|
74
|
-
[item.text]: false,
|
|
75
|
-
});
|
|
42
|
+
return item.text.toLowerCase().includes(searchTerm) || item.value.toLowerCase().includes(searchTerm);
|
|
76
43
|
});
|
|
77
44
|
}
|
|
78
45
|
};
|
|
79
46
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const item = menu.value.find((menuItem) => menuItem.text === preSelectedItem);
|
|
84
|
-
|
|
85
|
-
if (item) {
|
|
86
|
-
if (isMultiSelect.value) {
|
|
87
|
-
checkboxModels.value[item.text] = true;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
selectedItems.value.push(item);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
if (isSingleSelect.value) {
|
|
95
|
-
if (selectedItems.value.length > 0) {
|
|
96
|
-
emit('get-selected-item', selectedItems.value[0]);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
47
|
+
watch(searchString, () => {
|
|
48
|
+
handleSearch();
|
|
49
|
+
});
|
|
99
50
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
};
|
|
51
|
+
onClickOutside(dropdownRef, () => {
|
|
52
|
+
dropdownPopperState.value = false;
|
|
53
|
+
});
|
|
105
54
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
55
|
+
useInfiniteScroll(
|
|
56
|
+
dropdownRef,
|
|
57
|
+
() => {
|
|
58
|
+
emit('infinite-scroll-trigger', true);
|
|
59
|
+
},
|
|
60
|
+
{ distance: 10 },
|
|
61
|
+
);
|
|
109
62
|
|
|
110
63
|
onMounted(() => {
|
|
111
|
-
|
|
64
|
+
preSelectedItems.value = modelValue.value;
|
|
112
65
|
|
|
113
|
-
|
|
114
|
-
setPreSelectedItems();
|
|
115
|
-
handlePopperState();
|
|
66
|
+
setDropdownMenuList();
|
|
116
67
|
});
|
|
117
68
|
|
|
118
69
|
return {
|
|
119
|
-
|
|
120
|
-
|
|
70
|
+
dropdownPopperState,
|
|
71
|
+
dropdownRef,
|
|
72
|
+
preSelectedItems,
|
|
73
|
+
dropdownMenuList,
|
|
121
74
|
handleSelectedItem,
|
|
122
|
-
isItemSelected,
|
|
123
|
-
checkboxModels,
|
|
124
75
|
};
|
|
125
76
|
};
|
|
@@ -5,8 +5,28 @@ export const definePropType = <T>(val: unknown): PropType<T> => val as PropType<
|
|
|
5
5
|
const TRAILING_SIZES = ['xs', 'sm', 'md'] as const;
|
|
6
6
|
|
|
7
7
|
export const INPUT_TYPES = [
|
|
8
|
-
'button',
|
|
9
|
-
'
|
|
8
|
+
'button',
|
|
9
|
+
'checkbox',
|
|
10
|
+
'color',
|
|
11
|
+
'date',
|
|
12
|
+
'datetime-local',
|
|
13
|
+
'email',
|
|
14
|
+
'file',
|
|
15
|
+
'hidden',
|
|
16
|
+
'image',
|
|
17
|
+
'month',
|
|
18
|
+
'number',
|
|
19
|
+
'password',
|
|
20
|
+
'radio',
|
|
21
|
+
'range',
|
|
22
|
+
'reset',
|
|
23
|
+
'search',
|
|
24
|
+
'submit',
|
|
25
|
+
'tel',
|
|
26
|
+
'text',
|
|
27
|
+
'time',
|
|
28
|
+
'url',
|
|
29
|
+
'week',
|
|
10
30
|
] as const;
|
|
11
31
|
|
|
12
32
|
export const inputPropTypes = {
|
|
@@ -16,7 +36,11 @@ export const inputPropTypes = {
|
|
|
16
36
|
},
|
|
17
37
|
modelValue: {
|
|
18
38
|
type: String,
|
|
19
|
-
|
|
39
|
+
default: '',
|
|
40
|
+
},
|
|
41
|
+
value: {
|
|
42
|
+
type: String,
|
|
43
|
+
default: '',
|
|
20
44
|
},
|
|
21
45
|
label: {
|
|
22
46
|
type: String,
|
|
@@ -43,6 +67,14 @@ export const inputPropTypes = {
|
|
|
43
67
|
type: Boolean,
|
|
44
68
|
default: false,
|
|
45
69
|
},
|
|
70
|
+
minLength: {
|
|
71
|
+
type: Number,
|
|
72
|
+
default: 0,
|
|
73
|
+
},
|
|
74
|
+
maxLength: {
|
|
75
|
+
type: Number,
|
|
76
|
+
default: 0,
|
|
77
|
+
},
|
|
46
78
|
error: {
|
|
47
79
|
type: Boolean,
|
|
48
80
|
default: false,
|
|
@@ -54,16 +86,16 @@ export const inputPropTypes = {
|
|
|
54
86
|
},
|
|
55
87
|
helperText: {
|
|
56
88
|
type: String,
|
|
57
|
-
default: ''
|
|
89
|
+
default: '',
|
|
58
90
|
},
|
|
59
91
|
helperIcon: {
|
|
60
92
|
type: String,
|
|
61
|
-
default: null
|
|
93
|
+
default: null,
|
|
62
94
|
},
|
|
63
95
|
displayHelper: {
|
|
64
96
|
type: Boolean,
|
|
65
97
|
default: false,
|
|
66
|
-
}
|
|
98
|
+
},
|
|
67
99
|
};
|
|
68
100
|
|
|
69
101
|
export const inputEmitTypes = {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<label v-if="props.label" :for="id" :class="inputClasses.labelClasses">
|
|
4
4
|
{{ props.label }}
|
|
5
5
|
</label>
|
|
6
|
+
|
|
6
7
|
<div class="spr-relative">
|
|
7
8
|
<div v-if="$slots.prefix" :class="inputClasses.prefixSlotClasses">
|
|
8
9
|
<slot name="prefix" />
|
|
@@ -12,8 +13,10 @@
|
|
|
12
13
|
:placeholder="props.placeholder"
|
|
13
14
|
:disabled="props.disabled"
|
|
14
15
|
:readonly="props.readonly"
|
|
15
|
-
:value="props.modelValue"
|
|
16
|
+
:value="props.modelValue ? props.modelValue : props.value"
|
|
16
17
|
:type="props.type"
|
|
18
|
+
:minlength="props.minLength"
|
|
19
|
+
:maxlength="props.maxLength"
|
|
17
20
|
@input="onInput"
|
|
18
21
|
/>
|
|
19
22
|
<div v-if="$slots.trailing" :class="inputClasses.trailingSlotClasses">
|
|
@@ -32,7 +32,7 @@ export const useInput = (
|
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
const inputTextClasses = classNames(
|
|
35
|
-
'spr-block spr-w-full spr-px-size-spacing-2xs spr-py-size-spacing-4xs spr-rounded-border-radius-md spr-outline-none spr-ring-0',
|
|
35
|
+
'spr-block spr-h-9 spr-w-full spr-px-size-spacing-2xs spr-py-size-spacing-4xs spr-rounded-border-radius-md spr-outline-none spr-ring-0 spr-box-border',
|
|
36
36
|
'spr-text-color-strong spr-font-size-200 [font-weight:inherit]',
|
|
37
37
|
'spr-border spr-border-solid',
|
|
38
38
|
'placeholder:spr-text-mushroom-300',
|
|
@@ -44,7 +44,7 @@ export const useInput = (
|
|
|
44
44
|
disabled.value,
|
|
45
45
|
'spr-pr-[5%]': slots.icon,
|
|
46
46
|
'spr-pl-size-spacing-lg': slots.prefix,
|
|
47
|
-
|
|
47
|
+
'!spr-pl-size-spacing-3xl': props.type === 'url',
|
|
48
48
|
'spr-pr-[93%] sm:spr-pr-[85%]': offsetSize.value === 'xs' && slots.trailing,
|
|
49
49
|
'spr-pr-[90%] sm:spr-pr-[80%]': offsetSize.value === 'sm' && slots.trailing,
|
|
50
50
|
'spr-pr-[50%]': offsetSize.value === 'md' && slots.trailing,
|
|
@@ -77,20 +77,24 @@ export const useInput = (
|
|
|
77
77
|
},
|
|
78
78
|
);
|
|
79
79
|
|
|
80
|
-
const helperClasses = classNames(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
);
|
|
80
|
+
const helperClasses = classNames({
|
|
81
|
+
'spr-text-color-danger-base': error.value,
|
|
82
|
+
'spr-text-color-supporting': !error.value,
|
|
83
|
+
});
|
|
86
84
|
|
|
87
|
-
return {
|
|
85
|
+
return {
|
|
86
|
+
baseClasses,
|
|
87
|
+
labelClasses,
|
|
88
|
+
inputTextClasses,
|
|
89
|
+
iconSlotClasses,
|
|
90
|
+
prefixSlotClasses,
|
|
91
|
+
trailingSlotClasses,
|
|
92
|
+
helperClasses,
|
|
93
|
+
};
|
|
88
94
|
});
|
|
89
95
|
|
|
90
|
-
const onInput = (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
modelValue.value = target.value;
|
|
96
|
+
const onInput = () => {
|
|
97
|
+
emit('update:modelValue', modelValue.value);
|
|
94
98
|
};
|
|
95
99
|
|
|
96
100
|
return {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { PropType, ExtractPropTypes } from 'vue';
|
|
2
|
+
|
|
3
|
+
export const definePropType = <T>(val: unknown): PropType<T> => val as PropType<T>;
|
|
4
|
+
|
|
5
|
+
const GROUPED_ITEMS_BY_TYPES = ['A-Z', 'Z-A'] as const;
|
|
6
|
+
|
|
7
|
+
export const listPropTypes = {
|
|
8
|
+
modelValue: {
|
|
9
|
+
type: Array as PropType<string[]>,
|
|
10
|
+
default: () => [],
|
|
11
|
+
},
|
|
12
|
+
menuList: {
|
|
13
|
+
type: Array as PropType<{ text: string; value: string }[]>,
|
|
14
|
+
required: true,
|
|
15
|
+
default: [],
|
|
16
|
+
},
|
|
17
|
+
groupItemsBy: {
|
|
18
|
+
type: String as PropType<(typeof GROUPED_ITEMS_BY_TYPES)[number]>,
|
|
19
|
+
validator: (value: (typeof GROUPED_ITEMS_BY_TYPES)[number] | undefined) => {
|
|
20
|
+
return value === undefined || GROUPED_ITEMS_BY_TYPES.includes(value);
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
multiSelect: {
|
|
24
|
+
type: Boolean,
|
|
25
|
+
default: false,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const listEmitTypes = {
|
|
30
|
+
'get-selected-item': Object,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type ListPropTypes = ExtractPropTypes<typeof listPropTypes>;
|
|
34
|
+
export type ListEmitTypes = typeof listEmitTypes;
|