design-system-next 2.5.1 → 2.7.1

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.
@@ -161,9 +161,23 @@
161
161
  'active:spr-background-color-single-active active:spr-scale-90': true,
162
162
  }"
163
163
  >
164
- <Icon v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title" :icon="parentLink.icon" class="spr-h-[1.25em] spr-w-[1.25em]" />
165
- <Icon v-else-if="props.activeNav.parentNav === parentLink.title" :icon="`${parentLink.icon}-fill`" class="spr-text-kangkong-700 spr-h-[1.25em] spr-w-[1.25em]" />
166
- <Icon v-else icon="ph:globe" />
164
+ <template v-if="parentLink.icon && parentLink.icon.includes('https://')">
165
+ <img
166
+ v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title"
167
+ :src="parentLink.icon"
168
+ :alt="`${parentLink.title} icon`"
169
+ class="spr-h-[1.25em] spr-w-[1.25em] spr-max-w-[1.25em]" />
170
+ <img
171
+ v-else-if="props.activeNav.parentNav === parentLink.title"
172
+ :src="parentLink.icon.replace(/\.(svg|png|jpg)$/, '-fill.$1')"
173
+ :alt="`${parentLink.title} icon`"
174
+ class="spr-h-[1.25em] spr-w-[1.25em] spr-max-w-[1.25em]" />
175
+ </template>
176
+ <template v-else>
177
+ <Icon v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title" :icon="parentLink.icon" class="spr-h-[1.25em] spr-w-[1.25em]" />
178
+ <Icon v-else-if="props.activeNav.parentNav === parentLink.title" :icon="`${parentLink.icon}-fill`" class="spr-text-kangkong-700 spr-h-[1.25em] spr-w-[1.25em]" />
179
+ <Icon v-else icon="ph:globe" />
180
+ </template>
167
181
  </div>
168
182
 
169
183
  <template #popper>
@@ -317,9 +331,23 @@
317
331
  }"
318
332
  @click="handleRedirect(parentLink, parentLink.title, '', '')"
319
333
  >
320
- <Icon v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title" :icon="parentLink.icon" class="spr-h-[1.25em] spr-w-[1.25em]" />
321
- <Icon v-else-if="props.activeNav.parentNav === parentLink.title" :icon="`${parentLink.icon}-fill`" class="spr-text-kangkong-700 spr-h-[1.25em] spr-w-[1.25em]" />
322
- <Icon v-else icon="ph:globe" />
334
+ <template v-if="parentLink.icon && parentLink.icon.includes('https://')">
335
+ <img
336
+ v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title"
337
+ :src="parentLink.icon"
338
+ :alt="`${parentLink.title} icon`"
339
+ class="spr-h-[1.25em] spr-w-[1.25em] spr-max-w-[1.25em]" />
340
+ <img
341
+ v-else-if="props.activeNav.parentNav === parentLink.title"
342
+ :src="parentLink.icon.replace(/\.(svg|png|jpg)$/, '-fill.$1')"
343
+ :alt="`${parentLink.title} icon`"
344
+ class="spr-h-[1.25em] spr-w-[1.25em] spr-max-w-[1.25em]" />
345
+ </template>
346
+ <template v-else>
347
+ <Icon v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title" :icon="parentLink.icon" class="spr-h-[1.25em] spr-w-[1.25em]" />
348
+ <Icon v-else-if="props.activeNav.parentNav === parentLink.title" :icon="`${parentLink.icon}-fill`" class="spr-text-kangkong-700 spr-h-[1.25em] spr-w-[1.25em]" />
349
+ <Icon v-else icon="ph:globe" />
350
+ </template>
323
351
  </div>
324
352
  </Tooltip>
325
353
  </template>
@@ -358,9 +386,23 @@
358
386
  'active:spr-background-color-single-active active:spr-scale-90': true,
359
387
  }"
360
388
  >
361
- <Icon v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title" :icon="parentLink.icon" class="spr-h-[1.25em] spr-w-[1.25em]" />
362
- <Icon v-else-if="props.activeNav.parentNav === parentLink.title" :icon="`${parentLink.icon}-fill`" class="spr-text-kangkong-700 spr-h-[1.25em] spr-w-[1.25em]" />
363
- <Icon v-else icon="ph:globe" />
389
+ <template v-if="parentLink.icon && parentLink.icon.includes('https://')">
390
+ <img
391
+ v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title"
392
+ :src="parentLink.icon"
393
+ :alt="`${parentLink.title} icon`"
394
+ class="spr-h-[1.25em] spr-w-[1.25em] spr-max-w-[1.25em]" />
395
+ <img
396
+ v-else-if="props.activeNav.parentNav === parentLink.title"
397
+ :src="parentLink.icon.replace(/\.(svg|png|jpg)$/, '-fill.$1')"
398
+ :alt="`${parentLink.title} icon`"
399
+ class="spr-h-[1.25em] spr-w-[1.25em] spr-max-w-[1.25em]" />
400
+ </template>
401
+ <template v-else>
402
+ <Icon v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title" :icon="parentLink.icon" class="spr-h-[1.25em] spr-w-[1.25em]" />
403
+ <Icon v-else-if="props.activeNav.parentNav === parentLink.title" :icon="`${parentLink.icon}-fill`" class="spr-text-kangkong-700 spr-h-[1.25em] spr-w-[1.25em]" />
404
+ <Icon v-else icon="ph:globe" />
405
+ </template>
364
406
  </div>
365
407
 
366
408
  <template #popper>
@@ -510,9 +552,23 @@
510
552
  }"
511
553
  @click="handleRedirect(parentLink, parentLink.title, '', '')"
512
554
  >
513
- <Icon v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title" :icon="parentLink.icon" class="spr-h-[1.25em] spr-w-[1.25em]" />
514
- <Icon v-else-if="props.activeNav.parentNav === parentLink.title" :icon="`${parentLink.icon}-fill`" class="spr-text-kangkong-700 spr-h-[1.25em] spr-w-[1.25em]" />
515
- <Icon v-else icon="ph:globe" />
555
+ <template v-if="parentLink.icon && parentLink.icon.includes('https://')">
556
+ <img
557
+ v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title"
558
+ :src="parentLink.icon"
559
+ :alt="`${parentLink.title} icon`"
560
+ class="spr-h-[1.25em] spr-w-[1.25em] spr-max-w-[1.25em]" />
561
+ <img
562
+ v-else-if="props.activeNav.parentNav === parentLink.title"
563
+ :src="parentLink.icon.replace(/\.(svg|png|jpg)$/, '-fill.$1')"
564
+ :alt="`${parentLink.title} icon`"
565
+ class="spr-h-[1.25em] spr-w-[1.25em] spr-max-w-[1.25em]" />
566
+ </template>
567
+ <template v-else>
568
+ <Icon v-if="parentLink.icon && props.activeNav.parentNav !== parentLink.title" :icon="parentLink.icon" class="spr-h-[1.25em] spr-w-[1.25em]" />
569
+ <Icon v-else-if="props.activeNav.parentNav === parentLink.title" :icon="`${parentLink.icon}-fill`" class="spr-text-kangkong-700 spr-h-[1.25em] spr-w-[1.25em]" />
570
+ <Icon v-else icon="ph:globe" />
571
+ </template>
516
572
  </div>
517
573
  </Tooltip>
518
574
  </template>
@@ -616,6 +672,7 @@
616
672
  instant-move
617
673
  >
618
674
  <div
675
+ id="sidenav_user_menu"
619
676
  :class="[
620
677
  'spr-background-color spr-flex spr-h-[36px] spr-w-[36px] spr-cursor-pointer spr-items-center spr-justify-center spr-rounded-full',
621
678
  'spr-border-color-weak spr-border spr-border-solid',
@@ -671,6 +728,7 @@
671
728
  <template v-for="(userMenuItem, userMenuItemIndex) in props.userMenu.items" :key="userMenuItemIndex">
672
729
  <div
673
730
  v-if="!userMenuItem.hidden"
731
+ :id="`usermenu_${generateId(userMenuItem.title)}`"
674
732
  :class="[
675
733
  'spr-flex spr-cursor-pointer spr-gap-2 spr-p-2 spr-align-middle spr-duration-150 spr-ease-in-out',
676
734
  'hover:spr-background-color-hover',
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div
3
3
  v-if="isOpen && hasBackdrop"
4
- class="spr-w-screen spr-h-screen spr-bg-mushroom-700/60 spr-fixed spr-top-0 spr-left-0 spr-z-[4000]"
4
+ class="spr-fixed spr-left-0 spr-top-0 spr-z-[4000] spr-h-screen spr-w-screen spr-bg-mushroom-700/60"
5
5
  ></div>
6
6
  <Transition
7
7
  name="sidepanel"
@@ -21,40 +21,30 @@
21
21
  aria-describedby="sidepanel-content"
22
22
  :class="[
23
23
  sidepanelSizesClasses,
24
- 'spr-h-[calc(100vh-32px)] spr-bg-white-50 spr-rounded-border-radius-xl spr-fixed spr-right-4 spr-z-[4000] spr-min-h-[200px] spr-flex spr-flex-col spr-top-1/2 spr-translate-y-[-50%] spr-drop-shadow',
24
+ 'spr-fixed spr-right-4 spr-top-1/2 spr-z-[4000] spr-flex spr-h-full spr-min-h-[200px] spr-translate-y-[-50%] spr-flex-col spr-rounded-border-radius-xl spr-bg-white-50 spr-drop-shadow',
25
25
  ]"
26
26
  :style="{ height: typeof height === 'number' ? `${height}px` : height }"
27
27
  >
28
28
  <template v-if="!hideHeader">
29
- <div
30
- v-if="!$slots.header"
31
- class="spr-flex spr-justify-between spr-tw-min-h-12 spr-p-4 spr-border-0 spr-border-b spr-border-solid spr-border-mushroom-200 spr-text-color-strong"
29
+ <div
30
+ v-if="!$slots.header"
31
+ class="spr-tw-min-h-12 spr-text-color-strong spr-flex spr-justify-between spr-border-0 spr-border-b spr-border-solid spr-border-mushroom-200 spr-p-4"
32
32
  >
33
- <div
34
- id="sidepanel-title"
35
- class="spr-subheading-xs"
36
- >
33
+ <div id="sidepanel-title" class="spr-subheading-xs">
37
34
  {{ headerTitle }}
38
35
  </div>
39
- <Icon
40
- class="spr-cursor-pointer spr-w-5 spr-h-5 spr-text-color-weak"
41
- icon="ph:x"
42
- @click="handleClose"
43
- />
36
+ <Icon class="spr-text-color-weak spr-h-5 spr-w-5 spr-cursor-pointer" icon="ph:x" @click="handleClose" />
44
37
  </div>
45
38
  <div v-else>
46
39
  <slot name="header"></slot>
47
40
  </div>
48
41
  </template>
49
- <div
50
- id="sidepanel-content"
51
- :class="['spr-overflow-y-auto spr-h-full', {'spr-mb-[52px]': $slots.footer}]"
52
- >
42
+ <div id="sidepanel-content" :class="['spr-h-full spr-overflow-y-auto']">
53
43
  <slot />
54
44
  </div>
55
45
  <div
56
46
  v-if="$slots.footer"
57
- class="spr-absolute spr-bottom-0 spr-left-0 spr-w-full spr-rounded-b-border-radius-xl spr-border-0 spr-border-t spr-border-solid spr-border-mushroom-200 spr-bg-white-50 spr-py-3"
47
+ class="spr-bottom-0 spr-left-0 spr-w-full spr-rounded-b-border-radius-xl spr-border-0 spr-border-t spr-border-solid spr-border-mushroom-200 spr-bg-white-50 spr-py-3"
58
48
  >
59
49
  <slot name="footer"></slot>
60
50
  </div>
@@ -71,11 +61,8 @@ import { sidepanelPropTypes, sidepanelEmitTypes } from './sidepanel';
71
61
  const props = defineProps(sidepanelPropTypes);
72
62
  const emit = defineEmits(sidepanelEmitTypes);
73
63
 
74
- const {
75
- sidepanelRef,
76
- sidepanelSizesClasses,
77
- sidepanelMidState,
78
- sidepanelStartEndState,
79
- handleClose,
80
- } = useSidepanel(props, emit);
64
+ const { sidepanelRef, sidepanelSizesClasses, sidepanelMidState, sidepanelStartEndState, handleClose } = useSidepanel(
65
+ props,
66
+ emit,
67
+ );
81
68
  </script>
@@ -6,13 +6,13 @@
6
6
  @click="handleClick"
7
7
  >
8
8
  <div class="spr-flex spr-flex-auto spr-items-center">
9
- <Icon
10
- v-if="showIcon"
11
- :icon="snackIcon"
12
- :width="iconSize"
13
- :height="iconSize"
14
- :class="[snackToneCssClass, 'spr-mr-size-spacing-3xs']"
15
- />
9
+ <Icon
10
+ v-if="showIcon"
11
+ :icon="snackIcon"
12
+ :width="iconSize"
13
+ :height="iconSize"
14
+ :class="[snackToneCssClass, 'spr-mr-size-spacing-3xs spr-flex-shrink-0']"
15
+ />
16
16
  <label>{{ text }}</label>
17
17
  </div>
18
18
  <template v-if="showAction">
@@ -27,7 +27,7 @@
27
27
  <spr-button
28
28
  v-if="actionIconProps"
29
29
  icon-only
30
- :class="['!spr-p-size-spacing-4xs hover:spr-cursor-pointer', { 'spr-mr-2': actionText !== ''}]"
30
+ :class="['!spr-p-size-spacing-4xs hover:spr-cursor-pointer', { 'spr-mr-2': actionText !== '' }]"
31
31
  size="small"
32
32
  variant="secondary"
33
33
  :tone="actionIconProps.tone"
@@ -17,14 +17,18 @@
17
17
  </template>
18
18
  </spr-table-actions>
19
19
  </div>
20
-
21
20
  <div :class="getTableClasses.tableBackgroundClasses">
22
- <table aria-describedby="describe" class="spr-w-full spr-table-fixed" cellspacing="0" cellpadding="0">
21
+ <table aria-describedby="describe" class="spr-h-full spr-w-full spr-table-fixed" cellspacing="0" cellpadding="0">
23
22
  <thead>
24
23
  <tr v-if="!(props.removeHeaderOnEmpty && sortedData.length <= 0)">
25
24
  <th v-if="props.isMultiSelect" :class="[getTableClasses.multiselectClass, getTableClasses.headerClasses]">
26
- <div class="spr-flex spr-justify-center spr-items-center">
27
- <spr-checkbox label="" :checked="isAllSelected" @update:model-value="handleSelectAll"/>
25
+ <div class="spr-flex spr-items-center spr-justify-center">
26
+ <spr-checkbox
27
+ label=""
28
+ :checked="isAllSelected || isIndeterminate"
29
+ :indeterminate="isIndeterminate"
30
+ @update:model-value="handleSelectAll"
31
+ />
28
32
  </div>
29
33
  </th>
30
34
  <th v-for="(header, keyHeader) in headers" :key="keyHeader" :class="[getTableClasses.headerClasses]">
@@ -61,9 +65,12 @@
61
65
  @mouseover="$emit('onHover', { active: true, data: item })"
62
66
  @mouseleave="$emit('onHover', { active: false, data: item })"
63
67
  >
64
- <td v-if="props.isMultiSelect" :class="[getTableClasses.multiselectClass, getTableClasses.multiselectRowClass]">
65
- <div class="spr-flex spr-justify-center spr-items-center">
66
- <spr-checkbox label="" :checked="isRowSelected(item)" @update:model-value="handleSelect(item)"/>
68
+ <td
69
+ v-if="props.isMultiSelect"
70
+ :class="[getTableClasses.multiselectClass, getTableClasses.multiselectRowClass]"
71
+ >
72
+ <div class="spr-flex spr-items-center spr-justify-center">
73
+ <spr-checkbox label="" :checked="isRowSelected(item)" @update:model-value="handleSelect(item)" />
67
74
  </div>
68
75
  </td>
69
76
  <td v-for="(column, headerKey) in headers" :key="headerKey" :class="getTableClasses.tableDataClasses">
@@ -184,12 +191,13 @@ const {
184
191
  getTableClasses,
185
192
  getEmptyStateSize,
186
193
  isAllSelected,
187
-
194
+ isIndeterminate,
195
+
188
196
  isRowSelected,
189
197
  sortData,
190
198
  updateSearchField,
191
199
  handleRowClick,
192
200
  handleSelect,
193
- handleSelectAll
201
+ handleSelectAll,
194
202
  } = useTable(props, emit, slots);
195
203
  </script>
@@ -19,6 +19,11 @@ export const useTable = (props: TablePropTypes, emit: SetupContext<TableEmitType
19
19
  return selectedData.value.length === sortedData.value.length;
20
20
  });
21
21
 
22
+ const isIndeterminate = computed(() => {
23
+ if (selectedData.value.length === 0) return false;
24
+ return selectedData.value.length > 0 && selectedData.value.length < sortedData.value.length;
25
+ });
26
+
22
27
  const sortedData = computed(() => {
23
28
  if (!sortField.value || sortOrder.value) return dataTable.value;
24
29
 
@@ -74,7 +79,7 @@ export const useTable = (props: TablePropTypes, emit: SetupContext<TableEmitType
74
79
 
75
80
  const getTableClasses = computed(() => {
76
81
  const tableWrapperClasses = classNames(
77
- 'spr-border-color-weak spr-w-full spr-overflow-hidden spr-rounded-border-radius-lg spr-border spr-border-solid spr-table-wrapper spr-relative spr-h-max',
82
+ 'spr-flex spr-flex-col spr-h-full spr-border-color-weak spr-w-full spr-overflow-hidden spr-rounded-border-radius-lg spr-border spr-border-solid spr-table-wrapper spr-relative',
78
83
  );
79
84
  const tableFooterClasses = classNames('spr-w-full spr-bottom-0 spr-left-0', {
80
85
  'spr-background-color-surface': props.variant === 'surface',
@@ -113,10 +118,7 @@ export const useTable = (props: TablePropTypes, emit: SetupContext<TableEmitType
113
118
 
114
119
  const tableBackgroundClasses = classNames('spr-h-full');
115
120
 
116
- const tableBodyClasses = classNames({
117
- 'spr-overflow-y-auto spr-h-[calc(85vh-150px)] md:spr-h-[calc(75vh-150px)] sm:spr-h-[calc(70vh-150px)]':
118
- fullHeight.value && slots.footer, // Adjust tbody height for header/footer
119
- 'spr-overflow-y-auto spr-h-[75vh]': fullHeight.value && !slots.footer, // Adjust tbody height for header/footer
121
+ const tableBodyClasses = classNames('spr-overflow-y-auto spr-h-full', {
120
122
  'spr-h-[250px]': !fullHeight.value && slots.footer,
121
123
  'spr-h-[360px]': !fullHeight.value && !slots.footer,
122
124
  });
@@ -170,10 +172,10 @@ export const useTable = (props: TablePropTypes, emit: SetupContext<TableEmitType
170
172
  };
171
173
 
172
174
  const handleSelectAll = () => {
173
- if (isAllSelected.value) {
175
+ if (isAllSelected.value || isIndeterminate.value) {
174
176
  selectedData.value = [];
175
177
  } else {
176
- selectedData.value = sortedData.value;
178
+ selectedData.value = [...sortedData.value];
177
179
  }
178
180
  };
179
181
 
@@ -210,5 +212,6 @@ export const useTable = (props: TablePropTypes, emit: SetupContext<TableEmitType
210
212
  selectedData,
211
213
  isAllSelected,
212
214
  isRowSelected,
215
+ isIndeterminate,
213
216
  };
214
217
  };