sprintify-ui 0.0.179 → 0.0.180

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.
Files changed (31) hide show
  1. package/dist/sprintify-ui.es.js +7850 -7684
  2. package/dist/style.css +1 -1
  3. package/dist/types/src/components/BaseDataIterator.vue.d.ts +52 -13
  4. package/dist/types/src/components/BaseDataIteratorSectionBox.vue.d.ts +23 -0
  5. package/dist/types/src/components/BaseDataIteratorSectionButton.vue.d.ts +20 -0
  6. package/dist/types/src/components/{BaseDataTableToggleColumns.vue.d.ts → BaseDataIteratorSectionColumns.vue.d.ts} +6 -40
  7. package/dist/types/src/components/BaseDataIteratorSectionModal.vue.d.ts +29 -0
  8. package/dist/types/src/components/BaseDataTable.vue.d.ts +50 -11
  9. package/dist/types/src/components/BaseDataTableRowAction.vue.d.ts +18 -0
  10. package/dist/types/src/components/BaseMenu.vue.d.ts +9 -0
  11. package/dist/types/src/components/BaseMenuItem.vue.d.ts +9 -0
  12. package/dist/types/src/components/BaseTable.vue.d.ts +2 -17
  13. package/dist/types/src/index.d.ts +12 -0
  14. package/dist/types/src/types/index.d.ts +15 -0
  15. package/package.json +1 -1
  16. package/src/assets/main.css +23 -0
  17. package/src/components/BaseActionItem.vue +3 -1
  18. package/src/components/BaseDataIterator.vue +123 -85
  19. package/src/components/BaseDataIteratorSectionBox.vue +33 -0
  20. package/src/components/BaseDataIteratorSectionButton.vue +34 -0
  21. package/src/components/{BaseDataTableToggleColumns.vue → BaseDataIteratorSectionColumns.vue} +3 -3
  22. package/src/components/BaseDataIteratorSectionModal.vue +41 -0
  23. package/src/components/BaseDataTable.stories.js +45 -14
  24. package/src/components/BaseDataTable.vue +219 -78
  25. package/src/components/BaseDataTableRowAction.vue +28 -0
  26. package/src/components/BaseMenu.vue +7 -0
  27. package/src/components/BaseMenuItem.vue +17 -1
  28. package/src/components/BaseTable.vue +37 -85
  29. package/src/lang/en.json +3 -0
  30. package/src/lang/fr.json +3 -0
  31. package/src/types/index.ts +17 -0
@@ -7,6 +7,8 @@
7
7
  :searchable="searchable"
8
8
  :actions="actions"
9
9
  :history-mode="historyMode"
10
+ :layout="layout"
11
+ :sections="sectionsInternal"
10
12
  >
11
13
  <template
12
14
  #default="{
@@ -20,25 +22,61 @@
20
22
  }"
21
23
  >
22
24
  <BaseCard clipped class="w-full overflow-hidden">
25
+ <div v-if="newCheckedRows.length">
26
+ <div
27
+ class="flex items-center justify-between border-b border-slate-200 bg-slate-50 py-2 pl-3 pr-2 text-sm"
28
+ >
29
+ <div>
30
+ <span class="mr-3 text-slate-500"
31
+ >{{
32
+ $t('sui.x_rows_selected', {
33
+ count: newCheckedRows.length,
34
+ })
35
+ }}.</span
36
+ >
37
+ <button
38
+ type="button"
39
+ class="mr-3 inline text-slate-700 underline"
40
+ @click="uncheckAll()"
41
+ >
42
+ {{ $t('sui.deselect_all') }}
43
+ </button>
44
+ </div>
45
+ <BaseMenu
46
+ v-if="checkableActions?.length"
47
+ menu-class="w-52"
48
+ :items="checkableActions"
49
+ >
50
+ <template #button="{ open }">
51
+ <div
52
+ class="flex h-10 w-10 items-center justify-center rounded-full border border-slate-300 bg-white duration-150 hover:bg-slate-50"
53
+ :class="[
54
+ open ? 'ring-2 ring-primary-500 ring-offset-2' : false,
55
+ ]"
56
+ >
57
+ <BaseIcon icon="heroicons-solid:dots-vertical" />
58
+ </div>
59
+ </template>
60
+ </BaseMenu>
61
+ </div>
62
+ </div>
63
+
23
64
  <BaseTable
24
65
  ref="table"
66
+ :checked-rows="newCheckedRows"
25
67
  :data="items"
26
68
  :loading="loading"
27
69
  :detailed="detailed"
28
70
  :has-detailed-visible="hasDetailedVisible"
29
71
  :checkable="checkable"
30
- :checkable-actions="checkableActions"
31
- :checked-rows="checkedRows"
32
72
  :is-row-checkable="isRowCheckable"
33
73
  checkbox-position="left"
34
74
  :sort-field="sortField"
35
75
  :sort-direction="sortDirection"
36
76
  :max-height="maxHeight"
37
77
  :visible-columns="visibleColumns"
78
+ @update:checked-rows="onCheckedRowsUpdate"
38
79
  @sort="onSortChange"
39
- @check="$emit('check', $event)"
40
- @update:checked-rows="$emit('update:checked-rows', $event)"
41
- @check-all="$emit('checkAll', $event)"
42
80
  @cell-click="onCellClick"
43
81
  >
44
82
  <template #default>
@@ -52,36 +90,38 @@
52
90
  custom-key="actions"
53
91
  class="overflow-hidden"
54
92
  >
55
- <div class="flex justify-end gap-1 text-right">
93
+ <div class="flex justify-end gap-1 pr-2 text-right">
56
94
  <slot name="rowActions" :row="row" />
57
95
 
58
- <router-link
59
- v-if="editButton && editUrl"
60
- :to="editUrl(row)"
61
- :disabled="!canUpdate(row)"
62
- >
63
- <button
64
- class="btn btn-white border border-slate-300 p-2 shadow-sm"
96
+ <div class="btn-group">
97
+ <template
98
+ v-for="rowAction in visibleRowActions"
99
+ :key="rowAction.icon"
65
100
  >
66
- <BaseIcon
67
- icon="heroicons:cog-6-tooth-solid"
68
- class="text-slate-500"
69
- />
70
- </button>
71
- </router-link>
72
-
73
- <button
74
- v-if="deleteButton && deleteUrl"
75
- type="button"
76
- class="btn btn-white border border-slate-300 p-2 shadow-sm"
77
- :disabled="!canDelete(row)"
78
- @click="onDeleteClick(row)"
79
- >
80
- <BaseIcon
81
- icon="heroicons:trash-solid"
82
- class="text-slate-500"
83
- />
84
- </button>
101
+ <BaseDataTableRowAction
102
+ :row="row"
103
+ :row-action="rowAction"
104
+ ></BaseDataTableRowAction>
105
+ </template>
106
+ <BaseMenu
107
+ v-if="showRowActionMenu"
108
+ :items="rowActionMenuItems(row)"
109
+ size="sm"
110
+ >
111
+ <template #button="{ open }">
112
+ <div
113
+ class="flex h-8 w-8 items-center justify-center rounded-r border border-l-0 border-slate-300 bg-white duration-150 hover:bg-slate-50"
114
+ :class="[
115
+ open
116
+ ? 'ring-2 ring-primary-500 ring-offset-2'
117
+ : false,
118
+ ]"
119
+ >
120
+ <BaseIcon icon="heroicons-solid:dots-vertical" />
121
+ </div>
122
+ </template>
123
+ </BaseMenu>
124
+ </div>
85
125
  </div>
86
126
  </BaseTableColumn>
87
127
  </template>
@@ -139,58 +179,47 @@
139
179
  <slot name="sidebarTop" v-bind="sidebarProps"></slot>
140
180
  </template>
141
181
 
142
- <template v-if="toggleable" #sidebarBottom>
143
- <div class="mb-3">
144
- <BaseCard>
145
- <BaseCardRow size="sm">
146
- <button
147
- type="button"
148
- class="flex w-full items-center justify-between"
149
- @click="showColumnsDesktop = !showColumnsDesktop"
150
- >
151
- <h2 class="font-semibold">
152
- {{ $t('sui.columns') }}
153
- </h2>
154
-
155
- <BaseIcon
156
- :icon="
157
- showColumnsDesktop
158
- ? 'heroicons:chevron-down'
159
- : 'heroicons:chevron-up'
160
- "
161
- ></BaseIcon>
162
- </button>
163
-
164
- <div v-show="showColumnsDesktop" class="mt-4">
165
- <BaseDataTableToggleColumns
166
- v-model:visibleColumns="visibleColumns"
167
- :table="table"
168
- @update:visible-columns="onUpdateVisibleColumn"
169
- ></BaseDataTableToggleColumns>
170
- </div>
171
- </BaseCardRow>
172
- </BaseCard>
173
- </div>
182
+ <template #sidebarBottom="sidebarProps">
183
+ <slot name="sidebarBottom" v-bind="sidebarProps"></slot>
184
+ </template>
185
+
186
+ <template v-if="toggleable" #columns>
187
+ <BaseDataIteratorSectionColumns
188
+ v-model:visibleColumns="visibleColumns"
189
+ :table="table"
190
+ @update:visible-columns="onUpdateVisibleColumn"
191
+ ></BaseDataIteratorSectionColumns>
192
+ </template>
193
+
194
+ <template v-for="section in sections" :key="section.name" #[section.name]>
195
+ <slot :name="section.name" />
174
196
  </template>
175
197
  </BaseDataIterator>
176
198
  </template>
177
199
 
178
200
  <script lang="ts" setup>
179
201
  import { PropType } from 'vue';
180
- import { CollectionItem, DataTableQuery, MenuItemInterface } from '@/types';
202
+ import {
203
+ CollectionItem,
204
+ DataIteratorSection,
205
+ DataTableQuery,
206
+ MenuItemInterface,
207
+ RowAction,
208
+ } from '@/types';
181
209
  import { useDialogsStore } from '@/stores/dialogs';
182
210
  import { useNotificationsStore } from '../stores/notifications';
183
211
  import BaseDataIterator from './BaseDataIterator.vue';
184
- import { isArray } from 'lodash';
212
+ import { cloneDeep, isArray } from 'lodash';
185
213
 
186
214
  import BaseCard from './BaseCard.vue';
187
- import BaseCardRow from './BaseCardRow.vue';
188
215
  import BaseTable from './BaseTable.vue';
189
216
  import BaseTableColumn from './BaseTableColumn.vue';
190
- import BaseDataTableToggleColumns from './BaseDataTableToggleColumns.vue';
191
- import { config } from '@/index';
217
+ import BaseDataIteratorSectionColumns from './BaseDataIteratorSectionColumns.vue';
218
+ import { BaseIcon, config } from '@/index';
192
219
  import BaseEmptyState from '../svg/BaseEmptyState.vue';
193
220
  import { RouteLocationRaw } from 'vue-router';
221
+ import BaseMenu from './BaseMenu.vue';
222
+ import BaseDataTableRowAction from './BaseDataTableRowAction.vue';
194
223
 
195
224
  const i18n = useI18n();
196
225
  const router = useRouter();
@@ -365,15 +394,32 @@ const props = defineProps({
365
394
  default: undefined,
366
395
  type: Number,
367
396
  },
397
+
398
+ /**
399
+ * Layout type
400
+ */
401
+ layout: {
402
+ default: 'default',
403
+ type: String as PropType<'default' | 'compact'>,
404
+ },
405
+
406
+ sections: {
407
+ default: undefined,
408
+ type: Array as PropType<DataIteratorSection[]>,
409
+ },
410
+
411
+ rowActions: {
412
+ default: undefined,
413
+ type: Array as PropType<RowAction[]>,
414
+ },
415
+
416
+ numberOfVisibleRowActions: {
417
+ default: 2,
418
+ type: Number,
419
+ },
368
420
  });
369
421
 
370
- const emit = defineEmits([
371
- 'cell-click',
372
- 'delete',
373
- 'checkAll',
374
- 'update:checked-rows',
375
- 'check',
376
- ]);
422
+ const emit = defineEmits(['cell-click', 'delete', 'update:checked-rows']);
377
423
 
378
424
  const dataIterator = ref<null | InstanceType<typeof BaseDataIterator>>(null);
379
425
 
@@ -457,8 +503,6 @@ const onDelete = (row: CollectionItem) => {
457
503
  |--------------------------------------------------------------------------
458
504
  */
459
505
 
460
- const showColumnsDesktop = ref<boolean>(false);
461
-
462
506
  const visibleColumns = ref<number[]>([]);
463
507
 
464
508
  // Find visible columns in local storage
@@ -506,6 +550,103 @@ function onUpdateVisibleColumn() {
506
550
  );
507
551
  }
508
552
 
553
+ /*
554
+ |--------------------------------------------------------------------------
555
+ | Row Actions
556
+ |--------------------------------------------------------------------------
557
+ */
558
+
559
+ const rowActionsInternal = computed<RowAction[]>(() => {
560
+ const actions = cloneDeep(props.rowActions) ?? [];
561
+
562
+ if (props.editUrl && props.editButton) {
563
+ actions.push({
564
+ label: i18n.t('sui.edit'),
565
+ icon: 'heroicons:cog-6-tooth-solid',
566
+ to: (row: CollectionItem) => (props.editUrl ? props.editUrl(row) : ''),
567
+ disabled: (row: CollectionItem) => !canUpdate(row),
568
+ });
569
+ }
570
+
571
+ if (props.deleteUrl && props.deleteButton) {
572
+ actions.push({
573
+ label: i18n.t('sui.delete'),
574
+ icon: 'heroicons:trash-20-solid',
575
+ action: onDeleteClick,
576
+ disabled: (row: CollectionItem) => !canDelete(row),
577
+ });
578
+ }
579
+
580
+ return actions;
581
+ });
582
+
583
+ const visibleRowActions = computed<RowAction[]>(() => {
584
+ return rowActionsInternal.value.slice(0, props.numberOfVisibleRowActions);
585
+ });
586
+
587
+ const showRowActionMenu = computed<boolean>(() => {
588
+ return rowActionsInternal.value.length > props.numberOfVisibleRowActions;
589
+ });
590
+
591
+ function rowActionMenuItems(row: CollectionItem): MenuItemInterface[] {
592
+ return rowActionsInternal.value.map((action) => {
593
+ return {
594
+ label: action.label,
595
+ icon: action.icon,
596
+ disabled: action.disabled && action.disabled(row),
597
+ action: action.action
598
+ ? () => {
599
+ if (action.action) action.action(row);
600
+ }
601
+ : undefined,
602
+ to: action.to ? action.to(row) : undefined,
603
+ };
604
+ });
605
+ }
606
+
607
+ /*
608
+ |--------------------------------------------------------------------------
609
+ | Checkable
610
+ |--------------------------------------------------------------------------
611
+ */
612
+
613
+ const newCheckedRows = ref<Record<string, any>[]>([]);
614
+
615
+ watch(
616
+ () => props.checkedRows,
617
+ (checkedRows) => {
618
+ newCheckedRows.value = checkedRows;
619
+ }
620
+ );
621
+
622
+ function uncheckAll() {
623
+ table.value?.uncheckAll();
624
+ }
625
+
626
+ const sectionsInternal = computed<DataIteratorSection[]>(() => {
627
+ const sections = props.sections ?? [];
628
+
629
+ if (props.toggleable) {
630
+ return [
631
+ ...sections,
632
+ {
633
+ name: 'columns',
634
+ icon: 'heroicons:table-cells-20-solid',
635
+ title: i18n.t('sui.columns'),
636
+ closeText: i18n.t('sui.apply'),
637
+ opened: false,
638
+ },
639
+ ];
640
+ }
641
+
642
+ return sections;
643
+ });
644
+
645
+ function onCheckedRowsUpdate(checkedRows: Record<string, any>[]) {
646
+ newCheckedRows.value = checkedRows;
647
+ emit('update:checked-rows', checkedRows);
648
+ }
649
+
509
650
  /*
510
651
  |--------------------------------------------------------------------------
511
652
  | Exposed functions
@@ -0,0 +1,28 @@
1
+ <template>
2
+ <button
3
+ v-if="rowAction.action"
4
+ type="button"
5
+ class="btn btn-white border border-slate-300 p-2 shadow-sm"
6
+ :disabled="rowAction.disabled && rowAction.disabled(row)"
7
+ @click="rowAction.action ? rowAction.action(row) : null"
8
+ >
9
+ <BaseIcon :icon="rowAction.icon" class="text-slate-500" />
10
+ </button>
11
+ <router-link
12
+ v-else-if="rowAction.to"
13
+ :to="rowAction.to(row)"
14
+ :disabled="rowAction.disabled && rowAction.disabled(row)"
15
+ class="btn btn-white border border-slate-300 p-2 shadow-sm hover:bg-slate-100"
16
+ >
17
+ <BaseIcon :icon="rowAction.icon" class="text-slate-500" />
18
+ </router-link>
19
+ </template>
20
+
21
+ <script lang="ts" setup>
22
+ import { CollectionItem, RowAction } from '@/types';
23
+
24
+ defineProps<{
25
+ row: CollectionItem;
26
+ rowAction: RowAction;
27
+ }>();
28
+ </script>
@@ -46,6 +46,7 @@
46
46
  :icon="item.icon"
47
47
  :color="item.color"
48
48
  :active="active"
49
+ :size="size"
49
50
  />
50
51
  </slot>
51
52
  </MenuItem>
@@ -64,6 +65,7 @@
64
65
  :icon="item.icon"
65
66
  :color="item.color"
66
67
  :active="active"
68
+ :size="size"
67
69
  />
68
70
  </slot>
69
71
  </MenuItem>
@@ -83,6 +85,7 @@
83
85
  :icon="item.icon"
84
86
  :color="item.color"
85
87
  :active="active"
88
+ :size="size"
86
89
  />
87
90
  </slot>
88
91
  </MenuItem>
@@ -112,6 +115,10 @@ const props = defineProps({
112
115
  default: 'bottom-left',
113
116
  type: String as PropType<'bottom-left' | 'bottom-right' | 'custom'>,
114
117
  },
118
+ size: {
119
+ default: 'sm',
120
+ type: String as PropType<'xs' | 'sm' | 'md'>,
121
+ },
115
122
  });
116
123
 
117
124
  const menuPositionClass = computed(() => {
@@ -2,7 +2,7 @@
2
2
  <div :class="buttonClasses">
3
3
  <div class="flex items-center">
4
4
  <BaseIcon v-if="icon" :icon="icon" :class="iconClasses" />
5
- {{ label }}
5
+ <span :class="textSize">{{ label }}</span>
6
6
  </div>
7
7
  <div v-if="count" class="relative -top-px ml-[5px]">
8
8
  <BaseCounter
@@ -41,6 +41,10 @@ const props = defineProps({
41
41
  'dark' | 'light' | 'danger' | 'success' | 'warning'
42
42
  >,
43
43
  },
44
+ size: {
45
+ default: 'md',
46
+ type: String as PropType<'xs' | 'sm' | 'md'>,
47
+ },
44
48
  });
45
49
 
46
50
  const textColor = computed((): string => {
@@ -59,6 +63,18 @@ const textColor = computed((): string => {
59
63
  return '';
60
64
  });
61
65
 
66
+ const textSize = computed((): string => {
67
+ if (props.size == 'xs') {
68
+ return 'text-xs';
69
+ } else if (props.size == 'sm') {
70
+ return 'text-sm';
71
+ } else if (props.size == 'md') {
72
+ return 'text-base';
73
+ }
74
+
75
+ return '';
76
+ });
77
+
62
78
  const buttonClasses = computed((): string => {
63
79
  let baseClasses =
64
80
  'flex items-center justify-between w-full leading-tight py-2 text-sm text-left rounded';