design-system-next 2.9.4 → 2.9.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.
Binary file
@@ -1,7 +1,7 @@
1
1
  declare const _default: {
2
2
  "name": "design-system-next",
3
3
  "private": false,
4
- "version": "2.9.4",
4
+ "version": "2.9.6",
5
5
  "main": "./dist/design-system-next.js",
6
6
  "module": "./dist/design-system-next.js",
7
7
  "repository": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "design-system-next",
3
3
  "private": false,
4
- "version": "2.9.4",
4
+ "version": "2.9.6",
5
5
  "main": "./dist/design-system-next.js",
6
6
  "module": "./dist/design-system-next.js",
7
7
  "repository": {
package/src/App.vue CHANGED
@@ -1,82 +1,3 @@
1
1
  <template>
2
- <spr-select-multiple
3
- id="sample-select"
4
- v-model="selectModel"
5
- label="Multi-Select Label"
6
- placeholder="Select an option"
7
- :options="options"
8
- />
9
- <br />
10
- {{ selectModel }}
11
- <br />
12
- <br />
13
- {{ options }}
14
-
15
- <br />
16
- <br />
17
-
18
- <br />
19
- <br />
20
-
21
- <br />
22
- <br />
23
-
24
- <br />
25
- <br />
26
-
27
- <button @click="addMoreOptions">Add more option</button>
2
+ <div>Test Component Here</div>
28
3
  </template>
29
-
30
- <script setup>
31
- import { ref } from 'vue';
32
-
33
- import SprSelectMultiple from './components/select/select-multiple/select-multiple.vue';
34
-
35
- const selectModel = ref('');
36
-
37
- const options = ref([
38
- { text: 'Apple', value: 'apple' },
39
- { text: 'Banana', value: 'banana' },
40
- { text: 'Cherry', value: 'cherry' },
41
- { text: 'Date', value: 'date' },
42
- { text: 'Elderberry', value: 'elderberry' },
43
- { text: 'Fig', value: 'fig' },
44
- { text: 'Grape', value: 'grape' },
45
- { text: 'Nectarine', value: 'nectarine' },
46
- { text: 'Orange', value: 'orange' },
47
- { text: 'Papaya', value: 'papaya' },
48
- { text: '89 Quince', value: '50' },
49
- ]);
50
-
51
- let pagination = ref({
52
- currentPage: 1,
53
- totalPages: 0,
54
- });
55
-
56
- const addMoreOptions = async () => {
57
- try {
58
- const response = await fetch(`https://api.thedogapi.com/v1/breeds?page=${pagination.value.currentPage}&limit=10`);
59
-
60
- if (!response.ok) {
61
- throw new Error('Network response was not ok');
62
- }
63
-
64
- const optionsResponse = await response.json();
65
-
66
- if (optionsResponse.length) {
67
- options.value = [
68
- ...(options.value || []),
69
- ...optionsResponse.map((optionItem) => ({
70
- text: optionItem.name,
71
- value: optionItem.id,
72
- })),
73
- ];
74
- }
75
- // Do not clear options if no new options are fetched
76
-
77
- pagination.value.currentPage += 1;
78
- } catch (error) {
79
- console.error('There was a problem with the fetch operation:', error);
80
- }
81
- };
82
- </script>
@@ -5,24 +5,28 @@
5
5
  <div :class="[getCalendarClasses.headerWrapper]">
6
6
  <div class="spr-flex spr-items-center spr-justify-center spr-gap-size-spacing-3xs">
7
7
  <div class="spr-flex">
8
- <spr-button variant="tertiary" has-icon @click="prevWeek">
8
+ <spr-button id="calendar-prev-week" variant="tertiary" has-icon @click="prevWeek">
9
9
  <Icon icon="ph:caret-left-fill" class="spr-text-color-success-base" />
10
10
  </spr-button>
11
- <spr-button variant="tertiary" has-icon @click="nextWeek">
11
+ <spr-button id="calendar-next-week" variant="tertiary" has-icon @click="nextWeek">
12
12
  <Icon icon="ph:caret-right-fill" class="spr-text-color-success-base" />
13
13
  </spr-button>
14
14
  </div>
15
15
  <div class="spr-heading-xs">{{ weekRangeDisplay }}</div>
16
16
  </div>
17
17
 
18
- <spr-button variant="secondary" size="large" @click="goToToday"> Today </spr-button>
18
+ <spr-button id="calendar-today" variant="secondary" size="large" @click="goToToday"> Today </spr-button>
19
19
  </div>
20
20
  <!-- Filters -->
21
21
  <slot name="filter" />
22
22
 
23
23
  <div ref="tableBodyRef" class="spr-table-wrapper spr-h-[calc(100vh-12rem)] spr-w-full spr-overflow-auto">
24
24
  <div class="spr-pb-size-spacing-lg">
25
- <table aria-describedby="calendar" :class="[getCalendarClasses.calendarTable, 'spr-relative']">
25
+ <table
26
+ id="table-calendar"
27
+ aria-describedby="calendar"
28
+ :class="[getCalendarClasses.calendarTable, 'spr-relative']"
29
+ >
26
30
  <!-- Calendar Header -->
27
31
  <thead class="spr-bg-white spr-sticky spr-top-0 spr-z-20">
28
32
  <tr>
@@ -30,6 +34,7 @@
30
34
  <div :class="getCalendarClasses.headerContent">
31
35
  <div>Employee Name</div>
32
36
  <div
37
+ id="calendar-sort-button"
33
38
  :class="['spr-flex spr-cursor-pointer spr-flex-row spr-items-center spr-p-size-spacing-6xs']"
34
39
  @click="handleSorting"
35
40
  >
@@ -128,8 +133,8 @@
128
133
  <spr-calendar-cell type="restday" fullwidth />
129
134
  </div>
130
135
  <div
131
- class="spr-flex spr-flex-col spr-items-center spr-justify-start"
132
136
  v-else
137
+ class="spr-flex spr-flex-col spr-items-center spr-justify-start"
133
138
  @click="
134
139
  onCellClick({
135
140
  employeeId: employee.id,
@@ -25,6 +25,7 @@ export const selectLadderizedPropTypes = {
25
25
  id: {
26
26
  type: String,
27
27
  required: true,
28
+ default: 'select-ladderized',
28
29
  },
29
30
  modelValue: {
30
31
  type: Array as PropType<string[]>,
@@ -25,6 +25,7 @@
25
25
  >
26
26
  <div @click="handleOptionsToggle">
27
27
  <spr-input
28
+ :id="`input-${props.id}`"
28
29
  v-model="inputText"
29
30
  class="spr-cursor-pointer"
30
31
  :placeholder="props.placeholder"
@@ -1,164 +1,164 @@
1
- import { ref, toRefs, computed, watch } from 'vue';
2
- import { useVModel, useDebounceFn, onClickOutside } from '@vueuse/core';
3
-
4
- import type { SelectLadderizedPropTypes } from './select-ladderized';
5
-
6
- import type { MenuListType } from '@/components/list/list';
7
-
8
- export const useSelectLadderized = (
9
- props: SelectLadderizedPropTypes,
10
- emit: (event: string, ...args: unknown[]) => void,
11
- ) => {
12
- const { options, disabled } = toRefs(props);
13
-
14
- const ladderizedClasses = computed(() => ({
15
- baseClasses: 'spr-flex spr-flex-col spr-gap-size-spacing-4xs',
16
- labelClasses: 'spr-body-sm-regular spr-text-color-strong spr-block',
17
- }));
18
-
19
- // Popper Variables
20
- const ladderizedSelectPopperState = ref(false);
21
- const ladderizedSelectRef = ref(null);
22
- const isLadderizedSelectPopperDisabled = computed(() => disabled.value);
23
-
24
- // Ladderized Select Model
25
- const ladderizedSelectModel = useVModel(props, 'modelValue', emit);
26
- const ladderizedSelectOptions = computed(() => options.value);
27
-
28
- // Input Variables
29
- const inputText = ref<string>('');
30
- const isSearching = ref(false);
31
- const wasCleared = ref(false);
32
-
33
- const isLeafNode = (item: MenuListType): boolean => {
34
- return !item.sublevel || item.sublevel.length === 0;
35
- };
36
-
37
- // Helper to find the path to a selected value in the menu tree
38
- const findPathToValue = (items: MenuListType[], value: string | number, path: string[] = []): string[] | null => {
39
- for (const item of items) {
40
- const newPath = [...path, item.text];
41
-
42
- if (item.value === value) {
43
- return newPath;
44
- }
45
-
46
- if (item.sublevel) {
47
- const result = findPathToValue(item.sublevel, value, newPath);
48
-
49
- if (result) return result;
50
- }
51
- }
52
-
53
- return null;
54
- };
55
-
56
- const handleSelectedLadderizedItem = (selectedItems: string[], selectedItem?: MenuListType) => {
57
- wasCleared.value = false;
58
- ladderizedSelectModel.value = selectedItems;
59
-
60
- let itemToCheck = selectedItem;
61
-
62
- // Fallback: if selectedItem is not provided, try to find it from the value
63
- if (!itemToCheck && selectedItems.length > 0) {
64
- const findItemByValue = (items: MenuListType[], value: string | number): MenuListType | undefined => {
65
- for (const item of items) {
66
- if (item.value === value) return item;
67
-
68
- if (item.sublevel) {
69
- const found = findItemByValue(item.sublevel, value);
70
-
71
- if (found) return found;
72
- }
73
- }
74
-
75
- return undefined;
76
- };
77
-
78
- itemToCheck = findItemByValue(ladderizedSelectOptions.value, selectedItems[selectedItems.length - 1]);
79
- }
80
-
81
- if (itemToCheck) {
82
- const path = findPathToValue(ladderizedSelectOptions.value, itemToCheck.value);
83
-
84
- inputText.value = path ? path.join(' > ') : itemToCheck.text || '';
85
-
86
- if (isLeafNode(itemToCheck)) {
87
- ladderizedSelectPopperState.value = false;
88
- }
89
- } else if (selectedItems.length === 0 && !wasCleared.value) {
90
- inputText.value = '';
91
- }
92
- };
93
-
94
- const handleSearch = () => {
95
- isSearching.value = true;
96
-
97
- debouncedEmitSearch();
98
- };
99
-
100
- const debouncedEmitSearch = useDebounceFn(() => {
101
- // Optionally emit search event here if needed
102
- }, 300);
103
-
104
- const handleClear = () => {
105
- wasCleared.value = true;
106
-
107
- inputText.value = '';
108
-
109
- emit('update:modelValue', []);
110
- };
111
-
112
- const handleOptionsToggle = () => {
113
- ladderizedSelectPopperState.value = true;
114
-
115
- isSearching.value = false;
116
- };
117
-
118
- // Watch for changes in modelValue to update inputText
119
- watch(
120
- () => ladderizedSelectModel.value,
121
- (newVal) => {
122
- if (wasCleared.value) {
123
- inputText.value = '';
124
- wasCleared.value = false;
125
- return;
126
- }
127
-
128
- if (Array.isArray(newVal) && newVal.length > 0) {
129
- // Treat the array as a single path for ladderized select
130
- let currentLevel = ladderizedSelectOptions.value;
131
-
132
- const pathTexts: string[] = [];
133
-
134
- for (const value of newVal) {
135
- const found = currentLevel.find((item) => item.value === value);
136
- if (!found) break;
137
- pathTexts.push(found.text);
138
- currentLevel = found.sublevel || [];
139
- }
140
-
141
- inputText.value = pathTexts.join(' > ');
142
- }
143
- },
144
- { immediate: true },
145
- );
146
-
147
- onClickOutside(ladderizedSelectRef, () => {
148
- ladderizedSelectPopperState.value = false;
149
- });
150
-
151
- return {
152
- ladderizedClasses,
153
- ladderizedSelectPopperState,
154
- ladderizedSelectRef,
155
- ladderizedSelectOptions,
156
- isLadderizedSelectPopperDisabled,
157
- ladderizedSelectModel,
158
- inputText,
159
- handleSelectedLadderizedItem,
160
- handleSearch,
161
- handleClear,
162
- handleOptionsToggle,
163
- };
164
- };
1
+ import { ref, toRefs, computed, watch } from 'vue';
2
+ import { useVModel, useDebounceFn, onClickOutside } from '@vueuse/core';
3
+
4
+ import type { SelectLadderizedPropTypes } from './select-ladderized';
5
+
6
+ import type { MenuListType } from '@/components/list/list';
7
+
8
+ export const useSelectLadderized = (
9
+ props: SelectLadderizedPropTypes,
10
+ emit: (event: string, ...args: unknown[]) => void,
11
+ ) => {
12
+ const { options, disabled } = toRefs(props);
13
+
14
+ const ladderizedClasses = computed(() => ({
15
+ baseClasses: 'spr-flex spr-flex-col spr-gap-size-spacing-4xs',
16
+ labelClasses: 'spr-body-sm-regular spr-text-color-strong spr-block',
17
+ }));
18
+
19
+ // Popper Variables
20
+ const ladderizedSelectPopperState = ref(false);
21
+ const ladderizedSelectRef = ref(null);
22
+ const isLadderizedSelectPopperDisabled = computed(() => disabled.value);
23
+
24
+ // Ladderized Select Model
25
+ const ladderizedSelectModel = useVModel(props, 'modelValue', emit);
26
+ const ladderizedSelectOptions = computed(() => options.value);
27
+
28
+ // Input Variables
29
+ const inputText = ref<string>('');
30
+ const isSearching = ref(false);
31
+ const wasCleared = ref(false);
32
+
33
+ const isLeafNode = (item: MenuListType): boolean => {
34
+ return !item.sublevel || item.sublevel.length === 0;
35
+ };
36
+
37
+ // Helper to find the path to a selected value in the menu tree
38
+ const findPathToValue = (items: MenuListType[], value: string | number, path: string[] = []): string[] | null => {
39
+ for (const item of items) {
40
+ const newPath = [...path, item.text];
41
+
42
+ if (item.value === value) {
43
+ return newPath;
44
+ }
45
+
46
+ if (item.sublevel) {
47
+ const result = findPathToValue(item.sublevel, value, newPath);
48
+
49
+ if (result) return result;
50
+ }
51
+ }
52
+
53
+ return null;
54
+ };
55
+
56
+ const handleSelectedLadderizedItem = (selectedItems: string[], selectedItem?: MenuListType) => {
57
+ wasCleared.value = false;
58
+ ladderizedSelectModel.value = selectedItems;
59
+
60
+ let itemToCheck = selectedItem;
61
+
62
+ // Fallback: if selectedItem is not provided, try to find it from the value
63
+ if (!itemToCheck && selectedItems.length > 0) {
64
+ const findItemByValue = (items: MenuListType[], value: string | number): MenuListType | undefined => {
65
+ for (const item of items) {
66
+ if (item.value === value) return item;
67
+
68
+ if (item.sublevel) {
69
+ const found = findItemByValue(item.sublevel, value);
70
+
71
+ if (found) return found;
72
+ }
73
+ }
74
+
75
+ return undefined;
76
+ };
77
+
78
+ itemToCheck = findItemByValue(ladderizedSelectOptions.value, selectedItems[selectedItems.length - 1]);
79
+ }
80
+
81
+ if (itemToCheck) {
82
+ const path = findPathToValue(ladderizedSelectOptions.value, itemToCheck.value);
83
+
84
+ inputText.value = path ? path.join(' > ') : itemToCheck.text || '';
85
+
86
+ if (isLeafNode(itemToCheck)) {
87
+ ladderizedSelectPopperState.value = false;
88
+ }
89
+ } else if (selectedItems.length === 0 && !wasCleared.value) {
90
+ inputText.value = '';
91
+ }
92
+ };
93
+
94
+ const handleSearch = () => {
95
+ isSearching.value = true;
96
+
97
+ debouncedEmitSearch();
98
+ };
99
+
100
+ const debouncedEmitSearch = useDebounceFn(() => {
101
+ // Optionally emit search event here if needed
102
+ }, 300);
103
+
104
+ const handleClear = () => {
105
+ wasCleared.value = true;
106
+
107
+ inputText.value = '';
108
+
109
+ emit('update:modelValue', []);
110
+ };
111
+
112
+ const handleOptionsToggle = () => {
113
+ ladderizedSelectPopperState.value = true;
114
+
115
+ isSearching.value = false;
116
+ };
117
+
118
+ // Watch for changes in modelValue to update inputText
119
+ watch(
120
+ () => ladderizedSelectModel.value,
121
+ (newVal) => {
122
+ if (wasCleared.value) {
123
+ inputText.value = '';
124
+ wasCleared.value = false;
125
+ return;
126
+ }
127
+
128
+ if (Array.isArray(newVal) && newVal.length > 0) {
129
+ // Treat the array as a single path for ladderized select
130
+ let currentLevel = ladderizedSelectOptions.value;
131
+
132
+ const pathTexts: string[] = [];
133
+
134
+ for (const value of newVal) {
135
+ const found = currentLevel.find((item) => item.value === value);
136
+ if (!found) break;
137
+ pathTexts.push(found.text);
138
+ currentLevel = found.sublevel || [];
139
+ }
140
+
141
+ inputText.value = pathTexts.join(' > ');
142
+ }
143
+ },
144
+ { immediate: true },
145
+ );
146
+
147
+ onClickOutside(ladderizedSelectRef, () => {
148
+ ladderizedSelectPopperState.value = false;
149
+ });
150
+
151
+ return {
152
+ ladderizedClasses,
153
+ ladderizedSelectPopperState,
154
+ ladderizedSelectRef,
155
+ ladderizedSelectOptions,
156
+ isLadderizedSelectPopperDisabled,
157
+ ladderizedSelectModel,
158
+ inputText,
159
+ handleSelectedLadderizedItem,
160
+ handleSearch,
161
+ handleClear,
162
+ handleOptionsToggle,
163
+ };
164
+ };
@@ -29,6 +29,7 @@ export const multiSelectPropTypes = {
29
29
  id: {
30
30
  type: String,
31
31
  required: true,
32
+ default: 'multi-select',
32
33
  },
33
34
  modelValue: {
34
35
  type: Array as PropType<(string | number | Record<string, unknown>)[]>,
@@ -26,6 +26,7 @@
26
26
  <div ref="multiSelectRef">
27
27
  <div @click="handleOptionsToggle">
28
28
  <spr-input
29
+ :id="`input-${props.id}`"
29
30
  v-model="inputText"
30
31
  :class="{
31
32
  'spr-cursor-pointer': true,
@@ -29,6 +29,7 @@ export const selectPropTypes = {
29
29
  id: {
30
30
  type: String,
31
31
  required: true,
32
+ default: 'select',
32
33
  },
33
34
  modelValue: {
34
35
  type: [String, Number, Object, Array] as PropType<
@@ -26,6 +26,7 @@
26
26
  <div ref="selectRef">
27
27
  <div @click="handleOptionsToggle">
28
28
  <spr-input
29
+ :id="`input-${props.id}`"
29
30
  v-model="inputText"
30
31
  :class="{
31
32
  'spr-cursor-pointer': !props.searchable,