design-system-next 2.23.1 → 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.
@@ -0,0 +1,84 @@
1
+ <template>
2
+ <spr-dropdown
3
+ :id="props.id"
4
+ ref="tableHeaderDropdown"
5
+ width="100%"
6
+ :triggers="[]"
7
+ :popper-triggers="['click']"
8
+ popper-width="448px"
9
+ no-padding
10
+ >
11
+ <div :class="props.headerClasses" @click="showDropdown">
12
+ <span> {{ props.header.name }} </span>
13
+ <span>
14
+ <Icon class="spr-text-[#4B685E] !spr-justify-normal" icon="ph:funnel-simple" height="20px" width="20px" />
15
+ </span>
16
+ </div>
17
+
18
+ <template #popper>
19
+ <spr-card class="spr-font-main" border-width="0px" :has-content-padding="false" show-header>
20
+ <template #header>
21
+ <div class="spr-w-full spr-border-0 spr-border-b spr-border-solid spr-border-color-weak spr-p-size-spacing-xs spr-flex spr-flex-row spr-justify-between spr-items-center">
22
+ <span class="spr-subheading-xs spr-capitalize">{{ props.header.name }}</span>
23
+ <spr-button size="small" variant="secondary" @click="selectAll">Select All</spr-button>
24
+ </div>
25
+ </template>
26
+ <template #content>
27
+ <div v-if="props.isSortable" class="spr-border-0 spr-border-b spr-border-solid spr-border-color-weak">
28
+ <spr-list v-model="selectedSort" class="spr-capitalize spr-body-sm-regular spr-text-color-strong [&_svg]:spr-w-[16px] [&_svg]:spr-h-[16px] [&_svg.spr-text-color-brand-base]:spr-hidden" :menu-list="props.sortOptions"/>
29
+ </div>
30
+ <div v-if="props.header.filterList && props.header.filterList.length > 0" >
31
+ <spr-list v-model="selectedFilters" class="spr-capitalize spr-body-sm-regular spr-text-color-strong [&_svg]:spr-w-[16px] [&_svg]:spr-h-[16px]" :menu-list="props.header.filterList" multi-select/>
32
+ </div>
33
+ </template>
34
+ <template #footer>
35
+ <div class="spr-ms-auto spr-flex spr-items-center spr-py-size-spacing-5xs">
36
+ <spr-button tone="success" @click="applyFilter">Apply Filter</spr-button>
37
+ </div>
38
+ </template>
39
+ </spr-card>
40
+ </template>
41
+ </spr-dropdown>
42
+ </template>
43
+
44
+ <script setup lang="ts">
45
+ import SprDropdown from '@/components/dropdown/dropdown.vue';
46
+ import SprCard from '@/components/card/card.vue';
47
+ import SprButton from '@/components/button/button.vue';
48
+ import SprList from '@/components/list/list.vue';
49
+ import Icon from '@/components/icon/icon.vue';
50
+ import {
51
+ tableHeaderDropdownEmitTypes,
52
+ tableHeaderDropdownPropTypes
53
+ } from './table-header-dropdown';
54
+ import { ref } from 'vue';
55
+ import { MenuListType } from '@/components/list/list';
56
+
57
+ const tableHeaderDropdown = ref<InstanceType<typeof SprDropdown> | null>(null);
58
+ const showDropdown = () => {
59
+ tableHeaderDropdown.value?.showDropdown();
60
+ };
61
+
62
+ const props = defineProps(tableHeaderDropdownPropTypes);
63
+ const emits = defineEmits(tableHeaderDropdownEmitTypes,);
64
+
65
+ const selectedSort = ref<MenuListType[]>([]);
66
+ const selectedFilters = ref<MenuListType[]>([]);
67
+
68
+ const applyFilter = () => {
69
+ emits('onApplyFilter', {
70
+ headerField: props.header.field,
71
+ sortBy: selectedSort.value[0] ? selectedSort.value[0].value as 'asc' | 'desc' | null : null,
72
+ appliedFilters: selectedFilters.value.reduce((acc, filter) => {
73
+ acc[filter.text] = filter.value as string;
74
+ return acc;
75
+ }, {} as Record<string, string>),
76
+ });
77
+ tableHeaderDropdown.value?.hideDropdown();
78
+ };
79
+
80
+ const selectAll = () => {
81
+ selectedFilters.value = props.header.filterList ? [...props.header.filterList] : [];
82
+ emits('onSelectAll');
83
+ };
84
+ </script>
@@ -58,6 +58,10 @@ export const tablePaginationPropTypes = {
58
58
  type: Boolean as PropType<boolean>,
59
59
  default: false,
60
60
  },
61
+ showNumberOfRowsDropdown: {
62
+ type: Boolean as PropType<boolean>,
63
+ default: true,
64
+ }
61
65
  };
62
66
 
63
67
  export const tablePaginationEmitTypes = {
@@ -1,6 +1,8 @@
1
1
  <template>
2
- <div :class="paginationClasses.baseClass">
2
+ <div :class="paginationClasses.baseClass" v-bind="$attrs">
3
+
3
4
  <spr-dropdown
5
+ v-if="showNumberOfRowsDropdown"
4
6
  :id="dropdownId"
5
7
  :menu-list="dropdownSelection"
6
8
  dropdown-type="single-select"
@@ -53,6 +55,9 @@
53
55
  </spr-button>
54
56
  </div>
55
57
  </div>
58
+ <div v-if="slots.actions" id="table_pagination_actions_slot">
59
+ <slot name="actions" />
60
+ </div>
56
61
  </div>
57
62
  </template>
58
63
 
@@ -65,8 +70,10 @@ import { useTablePagination } from './use-table-pagination';
65
70
  import SprInput from '@/components/input/input.vue';
66
71
  import SprButton from '@/components/button/button.vue';
67
72
  import SprDropdown from '@/components/dropdown/dropdown.vue';
73
+ import { useSlots } from 'vue';
68
74
 
69
75
  const emit = defineEmits(tablePaginationEmitTypes);
76
+ const slots = useSlots();
70
77
 
71
78
  const props = defineProps(tablePaginationPropTypes);
72
79
 
@@ -83,6 +90,7 @@ const {
83
90
  dropdownId,
84
91
  currentPage,
85
92
  totalPages,
93
+ showNumberOfRowsDropdown
86
94
  } = useTablePagination(props, emit);
87
95
  </script>
88
96
 
@@ -22,7 +22,7 @@ export const useTablePagination = (
22
22
  props: TablePaginationPropTypes,
23
23
  emit: SetupContext<TablePaginationEmitTypes>['emit'],
24
24
  ) => {
25
- const { selectedRowCount, totalItems, bordered, editableCurrentPage } = toRefs(props);
25
+ const { selectedRowCount, totalItems, bordered, editableCurrentPage, showNumberOfRowsDropdown } = toRefs(props);
26
26
 
27
27
  const currentPage = useVModel(props, 'currentPage', emit);
28
28
 
@@ -67,13 +67,13 @@ export const useTablePagination = (
67
67
  });
68
68
 
69
69
  const dropdownSelection = ref(props.dropdownSelection);
70
- const computeRowRange = computed(() => {
70
+ const computeRowRange = computed(() => {
71
71
  const startRow = (currentPage.value - 1) * selectedRowCount.value + 1;
72
72
  const endRow = Math.min(currentPage.value * selectedRowCount.value, totalItems.value);
73
73
  return `${startRow} - ${endRow} of ${totalItems.value}`;
74
74
  });
75
75
 
76
- const computeSelectedRowCount = computed(() => {
76
+ const computeSelectedRowCount = computed(() => {
77
77
  return `${selectedRowCount.value} Rows`;
78
78
  });
79
79
 
@@ -124,5 +124,6 @@ export const useTablePagination = (
124
124
  dropdownId,
125
125
  currentPage,
126
126
  totalPages,
127
+ showNumberOfRowsDropdown
127
128
  };
128
129
  };
@@ -2,6 +2,8 @@ import type { PropType, ExtractPropTypes } from 'vue';
2
2
  import type { ChipTitle } from '@/components/table/table-chips-title/table-chips-title';
3
3
  import type { LozengeTitle } from '@/components/table/table-lozenge-title/table-lozenge-title';
4
4
  import { type SortableEvent } from 'sortablejs';
5
+ import type { MenuListType } from '../list/list';
6
+ import type { TableHeaderFilterType } from './table-header-dropdown/table-header-dropdown';
5
7
  export const definePropType = <T>(val: unknown): PropType<T> => val as PropType<T>;
6
8
 
7
9
  export interface Header {
@@ -18,6 +20,7 @@ export interface Header {
18
20
  avatarVariant?: string;
19
21
  customTailwindClasses?: string;
20
22
  width?: string;
23
+ filterList?: MenuListType[]; // List of filter options for table header dropdown
21
24
  }
22
25
 
23
26
  export interface TableData {
@@ -183,6 +186,10 @@ export const tablePropTypes = {
183
186
  retainSelectionOnDataChange: {
184
187
  type: Boolean,
185
188
  default: false,
189
+ },
190
+ showHeaderFilter: {
191
+ type: Boolean,
192
+ default: false,
186
193
  }
187
194
  };
188
195
 
@@ -202,7 +209,8 @@ export const tableEmitTypes = {
202
209
  onDragAdd: (event: DragOnAddEvent): event is DragOnAddEvent =>
203
210
  event !== undefined && Array.isArray(event.updatedList),
204
211
  onDragRemove: (event: DragOnRemoveEvent): event is DragOnRemoveEvent =>
205
- event !== undefined && Array.isArray(event.updatedList),
212
+ event !== undefined && Array.isArray(event.updatedList),
213
+ onApplyFilter: (filter: TableHeaderFilterType) => !!filter,
206
214
  };
207
215
 
208
216
  export type TablePropTypes = ExtractPropTypes<typeof tablePropTypes>;
@@ -20,7 +20,7 @@
20
20
  <table
21
21
  :key="tableKey"
22
22
  aria-describedby="describe"
23
- class="spr-h-full spr-w-full spr-table-fixed"
23
+ class="spr-h-full spr-w-full"
24
24
  cellspacing="0"
25
25
  cellpadding="0"
26
26
  >
@@ -45,7 +45,18 @@
45
45
  :class="[getTableClasses.headerClasses(header)]"
46
46
  :style="{ width: header?.width }"
47
47
  >
48
- <div :class="getTableClasses.headerNameClass">
48
+ <!-- Header with Dropdown Filter -->
49
+ <spr-table-header-dropdown
50
+ v-if="props.showHeaderFilter"
51
+ :id="`th-dropdown-${keyHeader}`"
52
+ :header="header"
53
+ :is-sortable="true"
54
+ :header-classes="getTableClasses.headerNameClass"
55
+ :filter-options="header.filterList"
56
+ @on-apply-filter="(filters) => emit('onApplyFilter', filters)"
57
+ />
58
+ <!-- Default Header -->
59
+ <div v-else :class="getTableClasses.headerNameClass">
49
60
  <span :class="[{ 'spr-cursor-pointer': header.sort }]" @click="header.sort && sortData(header.field)">
50
61
  {{ header.name }}
51
62
  </span>
@@ -69,6 +80,9 @@
69
80
  :class="[{ 'spr-text-kangkong-700': sortField === header.field }]"
70
81
  />
71
82
  </span>
83
+ <span v-if="props.showHeaderFilter">
84
+ <Icon icon="ph:funnel-simple" height="20" width="20" class="spr-ml-size-spacing-5xs spr-text-[#4B685E]" />
85
+ </span>
72
86
  </div>
73
87
  </th>
74
88
 
@@ -213,6 +227,7 @@ import SprTableActions from '@/components/table/table-actions/table-actions.vue'
213
227
  import SprTableLozengeTitle from '@/components/table/table-lozenge-title/table-lozenge-title.vue';
214
228
  import SprTableChipsTitle from '@/components/table/table-chips-title/table-chips-title.vue';
215
229
  import SprCheckbox from '@/components/checkbox/checkbox.vue';
230
+ import SprTableHeaderDropdown from '@/components/table/table-header-dropdown/table-header-dropdown.vue';
216
231
 
217
232
  import { tablePropTypes, tableEmitTypes } from './table';
218
233
  import type { ChipTitle } from '@/components/table/table-chips-title/table-chips-title';
@@ -198,7 +198,11 @@ export const useTable = (props: TablePropTypes, emit: SetupContext<TableEmitType
198
198
 
199
199
  const getTableClasses = computed(() => {
200
200
  const tableWrapperClasses = classNames(
201
- '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 spr-font-main',
201
+ 'spr-flex spr-flex-col spr-h-full spr-border-color-weak spr-w-full spr-overflow-auto spr-rounded-border-radius-lg spr-border spr-border-solid spr-table-wrapper spr-relative spr-font-main',
202
+ {
203
+ 'spr-overflow-hidden': isDraggable.value,
204
+ 'spr-overflow-auto': !isDraggable.value,
205
+ }
202
206
  );
203
207
  const tableFooterClasses = classNames('spr-w-full spr-bottom-0 spr-left-0', {
204
208
  'spr-background-color-surface': props.variant === 'surface',
@@ -219,6 +223,7 @@ export const useTable = (props: TablePropTypes, emit: SetupContext<TableEmitType
219
223
  'spr-border-color-weak spr-border-x-0 spr-border-y spr-border-solid',
220
224
  {
221
225
  'spr-border-t-0': !slots.default,
226
+ 'spr-cursor-pointer hover:spr-background-color-hover active:spr-background-color-pressed': props.showHeaderFilter,
222
227
  },
223
228
  headerBackground,
224
229
  );