sprintify-ui 0.7.11 → 0.8.0

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 (44) hide show
  1. package/dist/sprintify-ui.es.js +10481 -10348
  2. package/dist/style.css +1 -1
  3. package/dist/types/components/BaseDataIterator.vue.d.ts +50 -4
  4. package/dist/types/components/BaseDataIteratorSectionColumns.vue.d.ts +156 -68
  5. package/dist/types/components/BaseDataTable.vue.d.ts +86 -6
  6. package/dist/types/components/BaseDataTableTemplate.vue.d.ts +44 -28
  7. package/dist/types/components/BaseTable.vue.d.ts +30 -7
  8. package/dist/types/components/BaseTableCell.vue.d.ts +19 -1
  9. package/dist/types/components/BaseTableColumn.vue.d.ts +50 -3
  10. package/dist/types/components/BaseTableHead.vue.d.ts +6 -5
  11. package/dist/types/components/BaseTableHeader.vue.d.ts +12 -2
  12. package/dist/types/components/BaseTableRow.vue.d.ts +5 -0
  13. package/dist/types/composables/isFirstColumn.d.ts +4 -0
  14. package/dist/types/composables/isLastColumn.d.ts +4 -0
  15. package/dist/types/composables/paginatedData.d.ts +5 -5
  16. package/dist/types/services/table/types.d.ts +6 -5
  17. package/dist/types/types/index.d.ts +7 -2
  18. package/dist/types/utils/getApiData.d.ts +1 -1
  19. package/package.json +2 -1
  20. package/src/assets/main.css +0 -1
  21. package/src/components/BaseAvatar.vue +1 -0
  22. package/src/components/BaseDataIterator.stories.js +96 -1
  23. package/src/components/BaseDataIterator.vue +135 -11
  24. package/src/components/BaseDataIteratorSectionColumns.vue +2 -2
  25. package/src/components/BaseDataTable.stories.js +140 -50
  26. package/src/components/BaseDataTable.vue +82 -48
  27. package/src/components/BaseDataTableTemplate.vue +207 -372
  28. package/src/components/BaseTable.stories.js +57 -15
  29. package/src/components/BaseTable.vue +71 -9
  30. package/src/components/BaseTableBody.vue +1 -1
  31. package/src/components/BaseTableCell.vue +94 -36
  32. package/src/components/BaseTableColumn.vue +25 -2
  33. package/src/components/BaseTableHead.vue +17 -5
  34. package/src/components/BaseTableHeader.vue +39 -10
  35. package/src/components/BaseTableRow.vue +27 -6
  36. package/src/composables/isFirstColumn.ts +31 -0
  37. package/src/composables/isLastColumn.ts +31 -0
  38. package/src/composables/paginatedData.ts +22 -10
  39. package/src/services/table/classes.ts +13 -9
  40. package/src/services/table/types.ts +6 -5
  41. package/src/stories/List.stories.js +5 -1
  42. package/src/types/index.ts +7 -2
  43. package/src/utils/getApiData.ts +1 -1
  44. package/src/assets/base-table.css +0 -17
@@ -5,9 +5,10 @@ import BaseSelect from './BaseSelect.vue';
5
5
  import BaseBadge from './BaseBadge.vue';
6
6
  import BaseAppSnackbars from './BaseAppSnackbars.vue';
7
7
  import BaseAppDialogs from './BaseAppDialogs.vue';
8
- import { onBeforeUnmount } from 'vue';
8
+ import { computed, onBeforeUnmount } from 'vue';
9
9
  import { DateTime } from 'luxon';
10
- import { templateDataTable } from '../../.storybook/utils';
10
+ import { options, templateDataTable } from '../../.storybook/utils';
11
+ import { cloneDeep } from 'lodash';
11
12
 
12
13
  export default {
13
14
  title: 'Data/BaseDataTable',
@@ -45,41 +46,9 @@ const templateComponents = {
45
46
  BaseAppDialogs,
46
47
  };
47
48
 
48
- const template = `
49
- <div class="font-mono text-sm bg-black px-2 py-1 rounded text-white">Last fetch: {{ lastFetch?.getTime() }} (should update on each fetch)</div>
50
- <br/>
51
- ${templateDataTable}
52
- <BaseAppSnackbars></BaseAppSnackbars>
53
- <BaseAppDialogs></BaseAppDialogs>
54
- `;
55
-
56
- const templateSetup = (args) => {
57
- function onCellClick() {
58
- alert('cell click!');
59
- }
60
-
61
- const lastFetch = ref(null);
62
-
63
- function onFetch() {
64
- lastFetch.value = new Date();
65
- }
66
-
67
- return { args, onCellClick, ownerIsVisible: true, onFetch, lastFetch, DateTime };
68
- };
69
-
70
- const Template = (args) => ({
71
- components: templateComponents,
72
- setup() {
73
- return templateSetup(args);
74
- },
75
- template: template,
76
- });
77
-
78
- export const Demo = Template.bind({});
79
-
80
- Demo.args = {
81
- showUrl() {
82
- return '/';
49
+ const componentProps = {
50
+ rowTo(row) {
51
+ return `/articles/${row.id}`;
83
52
  },
84
53
  editUrl() {
85
54
  return '/';
@@ -131,7 +100,6 @@ Demo.args = {
131
100
  alert('hit');
132
101
  },
133
102
  },
134
-
135
103
  ],
136
104
  sections: [
137
105
  {
@@ -143,20 +111,44 @@ Demo.args = {
143
111
  ],
144
112
  };
145
113
 
114
+ const template = `
115
+ <div class="font-mono text-sm bg-black px-2 py-1 rounded text-white">Last fetch: {{ lastFetch?.getTime() }} (should update on each fetch)</div>
116
+ <br/>
117
+ ${templateDataTable}
118
+ <BaseAppSnackbars></BaseAppSnackbars>
119
+ <BaseAppDialogs></BaseAppDialogs>
120
+ `;
121
+
122
+ const templateSetup = (args) => {
123
+ function onRowClick(...args) {
124
+ console.log("Row clicked!");
125
+ console.log(JSON.parse(JSON.stringify(args)));
126
+ }
127
+
128
+ const lastFetch = ref(null);
129
+
130
+ function onFetch() {
131
+ lastFetch.value = new Date();
132
+ }
133
+
134
+ return { args, onRowClick, ownerIsVisible: true, onFetch, lastFetch, DateTime };
135
+ };
136
+
137
+ const Template = (args) => ({
138
+ components: templateComponents,
139
+ setup() {
140
+ return templateSetup(args);
141
+ },
142
+ template: template,
143
+ });
144
+
145
+ export const Demo = Template.bind({});
146
+ Demo.args = componentProps;
147
+
146
148
  export const Small = Template.bind({});
147
149
  Small.args = {
148
- editUrl() {
149
- return '/';
150
- },
151
- deleteUrl() {
152
- return '/';
153
- },
154
150
  size: 'sm',
155
- searchable: true,
156
- toggleable: true,
157
- actions: [],
158
- };
159
-
151
+ }
160
152
 
161
153
  const VIfOnBaseTableColumn = (args) => ({
162
154
  components: templateComponents,
@@ -234,4 +226,102 @@ Simple.args = {
234
226
  searchable: false,
235
227
  toggleable: false,
236
228
  actions: [],
237
- };
229
+ };
230
+
231
+ const LocalTemplate = (args) => ({
232
+ components: templateComponents,
233
+ setup() {
234
+
235
+ const baseDataTableRef = ref(null);
236
+
237
+ const onCellClick = (...args) => {
238
+ alert('Cell clicked! View console log for details.');
239
+ console.log(JSON.parse(JSON.stringify(args)));
240
+ };
241
+
242
+ const filteredItems = computed(() => {
243
+ return options
244
+ .filter((item) => {
245
+ const type = baseDataTableRef.value?.query.filter?.type ?? '';
246
+
247
+ if (!type) {
248
+ return true;
249
+ }
250
+
251
+ return item.type === type;
252
+ });
253
+ });
254
+
255
+ return { args, filteredItems, baseDataTableRef, onCellClick };
256
+ },
257
+ template: `<BaseDataTable ref="baseDataTableRef" v-bind="args" :items="filteredItems">
258
+ <BaseTableColumn
259
+ v-slot="{ row }"
260
+ label="Label"
261
+ sortable
262
+ field="label"
263
+ :toggle="false"
264
+ >
265
+ <div class="max-w-sm">
266
+ <div class="font-medium text-slate-900">
267
+ {{ row.label }}
268
+ </div>
269
+ <p class="text-xs leading-tight text-slate-500">
270
+ {{ row.value ?? '-' }}
271
+ </p>
272
+ </div>
273
+ </BaseTableColumn>
274
+
275
+ <BaseTableColumn
276
+ v-slot="{ row }"
277
+ label="Value"
278
+ field="value"
279
+ :toggle="true"
280
+ :toggle-default="false"
281
+ sortable
282
+ customKey="value"
283
+ >
284
+ <p>{{ row.value }}</p>
285
+ </BaseTableColumn>
286
+
287
+ <BaseTableColumn
288
+ v-slot="{ row }"
289
+ label="Type"
290
+ field="type"
291
+ sortable
292
+ @click="onCellClick"
293
+ >
294
+ <p>{{ row.type }}</p>
295
+ </BaseTableColumn>
296
+
297
+ <template #filters="{ query, updateQueryValue }">
298
+ <div class="space-y-3">
299
+ <div>
300
+ <p class="mb-1 text-sm">
301
+ Type
302
+ </p>
303
+ <BaseSelect
304
+ :model-value="query.filter.type ?? null"
305
+ class="w-full rounded border-slate-300"
306
+ placeholder="-"
307
+ @update:model-value="updateQueryValue('filter.type', $event)"
308
+ >
309
+ <option value="jedi">
310
+ Jedi
311
+ </option>
312
+ <option value="sith">
313
+ Sith
314
+ </option>
315
+ </BaseSelect>
316
+ </div>
317
+ </div>
318
+ </template>
319
+ </BaseDataTable>`,
320
+ });
321
+
322
+ export const Local = LocalTemplate.bind({});
323
+ const localProps = cloneDeep(componentProps);
324
+ localProps.url = null;
325
+ localProps.perPage = 4;
326
+ localProps.rowTo = undefined;
327
+ Local.args = localProps;
@@ -1,6 +1,8 @@
1
1
  <template>
2
2
  <BaseDataIterator
3
- ref="dataIterator"
3
+ ref="dataIteratorRef"
4
+ :items="items"
5
+ :per-page="perPage"
4
6
  :url="url"
5
7
  :url-query="urlQuery"
6
8
  :default-query="defaultQuery"
@@ -15,17 +17,7 @@
15
17
  @fetch="onFetch"
16
18
  @will-scroll-top="onWillScrollTop"
17
19
  >
18
- <template
19
- #default="{
20
- items,
21
- loading,
22
- sortField,
23
- sortDirection,
24
- onSortChange,
25
- error,
26
- firstLoad,
27
- }"
28
- >
20
+ <template #default="dataIteratorProps">
29
21
  <BaseCard
30
22
  clipped
31
23
  class="w-full overflow-hidden"
@@ -77,21 +69,22 @@
77
69
  <BaseDataTableTemplate
78
70
  ref="table"
79
71
  :checked-rows="newCheckedRows"
80
- :data="items"
81
- :loading="loading"
72
+ :data="dataIteratorProps.items"
73
+ :loading="dataIteratorProps.loading"
82
74
  :detailed="detailed"
83
75
  :has-detailed-visible="hasDetailedVisible"
84
76
  :checkable="checkable"
85
77
  :is-row-checkable="isRowCheckable"
86
- checkbox-position="left"
87
- :sort-field="sortField"
88
- :sort-direction="sortDirection"
78
+ :sort-field="dataIteratorProps.sortField"
79
+ :sort-direction="dataIteratorProps.sortDirection"
89
80
  :max-height="maxHeight"
90
81
  :visible-columns="visibleColumns"
91
82
  :size="sizeInternal.size.value"
83
+ :row-to="rowToInternal"
84
+ :row-href="rowHref"
92
85
  @update:checked-rows="onCheckedRowsUpdate"
93
- @sort="onSortChange"
94
- @cell-click="onCellClick"
86
+ @sort="dataIteratorProps.onSortChange"
87
+ @row-click="onRowClick"
95
88
  >
96
89
  <template #default>
97
90
  <slot />
@@ -100,11 +93,11 @@
100
93
  v-slot="{ row }"
101
94
  :visible="rowActionsInternal.length"
102
95
  :toggle="false"
103
- :clickable="false"
96
+ ignore-row-interactions
104
97
  custom-key="actions"
105
98
  class="overflow-hidden"
106
99
  >
107
- <div class="flex justify-end gap-1 pr-2 text-right">
100
+ <div class="flex justify-end gap-1 text-right w-full">
108
101
  <div class="btn-group">
109
102
  <template
110
103
  v-for="rowAction in visibleRowActions"
@@ -150,7 +143,7 @@
150
143
 
151
144
  <template #empty>
152
145
  <div
153
- v-if="error"
146
+ v-if="dataIteratorProps.error"
154
147
  class="flex items-center justify-center py-16"
155
148
  >
156
149
  <div class="flex flex-col items-center justify-center">
@@ -164,7 +157,7 @@
164
157
  </div>
165
158
  </div>
166
159
  <div
167
- v-else-if="firstLoad"
160
+ v-else-if="dataIteratorProps.firstLoad"
168
161
  class="flex items-center justify-center py-16"
169
162
  >
170
163
  <div class="flex flex-col items-center">
@@ -258,8 +251,6 @@ import { useInputSize } from '@/composables/inputSize';
258
251
  import BaseButton from './BaseButton.vue';
259
252
  import BaseDataTableTemplate from './BaseDataTableTemplate.vue';
260
253
 
261
- const router = useRouter();
262
-
263
254
  const http = config.http;
264
255
 
265
256
  const dialogs = useDialogsStore();
@@ -268,12 +259,29 @@ const snackbars = useSnackbarsStore();
268
259
  const table = ref<null | InstanceType<typeof BaseDataTableTemplate>>(null);
269
260
 
270
261
  const props = defineProps({
262
+
263
+ /**
264
+ * Data table items
265
+ */
266
+ items: {
267
+ default: undefined,
268
+ type: Array as PropType<CollectionItem[] | undefined>,
269
+ },
270
+
271
+ /**
272
+ * Per page (only when using local data)
273
+ */
274
+ perPage: {
275
+ default: 16,
276
+ type: Number,
277
+ },
278
+
271
279
  /**
272
280
  * Base URL from which to make requests
273
281
  */
274
282
  url: {
275
- required: true,
276
- type: String,
283
+ default: undefined,
284
+ type: String as PropType<string | undefined>,
277
285
  },
278
286
 
279
287
  /**
@@ -303,6 +311,25 @@ const props = defineProps({
303
311
  >,
304
312
  },
305
313
 
314
+ rowTo: {
315
+ default: undefined,
316
+ type: Function as PropType<
317
+ ((row: CollectionItem) => RouteLocationRaw) | undefined
318
+ >,
319
+ },
320
+
321
+ rowHref: {
322
+ default: undefined,
323
+ type: Function as PropType<
324
+ ((row: CollectionItem) => string) | undefined
325
+ >,
326
+ },
327
+
328
+ onRowClick: {
329
+ default: undefined,
330
+ type: Function as PropType<(row: CollectionItem, index: number, event: MouseEvent) => void>,
331
+ },
332
+
306
333
  /**
307
334
  * Show/Hide edit button
308
335
  */
@@ -466,16 +493,25 @@ const props = defineProps({
466
493
  type: String as PropType<Size>,
467
494
  },
468
495
 
496
+ /**
497
+ * Data iterator sections
498
+ */
469
499
  sections: {
470
500
  default: undefined,
471
501
  type: Array as PropType<DataIteratorSection[]>,
472
502
  },
473
503
 
504
+ /**
505
+ * Row actions
506
+ */
474
507
  rowActions: {
475
508
  default: undefined,
476
509
  type: Array as PropType<RowAction[]>,
477
510
  },
478
511
 
512
+ /**
513
+ * Number of visible row actions
514
+ */
479
515
  numberOfVisibleRowActions: {
480
516
  default: 2,
481
517
  type: Number,
@@ -489,6 +525,9 @@ const props = defineProps({
489
525
  type: Boolean,
490
526
  },
491
527
 
528
+ /**
529
+ * Filters position
530
+ */
492
531
  filtersPosition: {
493
532
  default: 'section',
494
533
  type: String as PropType<'top' | 'section'>,
@@ -508,26 +547,21 @@ const menuSize = computed(() => {
508
547
  })
509
548
 
510
549
  const emit = defineEmits([
511
- 'cell-click',
512
550
  'delete',
513
551
  'update:checked-rows',
514
552
  'fetch',
515
553
  ]);
516
554
 
517
- const dataIterator = ref<null | InstanceType<typeof BaseDataIterator>>(null);
555
+ const dataIteratorRef = ref<null | InstanceType<typeof BaseDataIterator>>(null);
518
556
 
519
- /*
520
- |--------------------------------------------------------------------------
521
- | Handlers
522
- |--------------------------------------------------------------------------
523
- */
524
-
525
- function onCellClick(payload: CollectionItem) {
557
+ const rowToInternal = computed(() => {
526
558
  if (props.showUrl) {
527
- router.push(props.showUrl(payload));
559
+ console.warn('showUrl is deprecated, use rowTo instead');
560
+ return props.showUrl;
528
561
  }
529
- emit('cell-click', payload);
530
- }
562
+
563
+ return props.rowTo;
564
+ });
531
565
 
532
566
  /*
533
567
  |--------------------------------------------------------------------------
@@ -596,7 +630,7 @@ const onDelete = (row: CollectionItem) => {
596
630
  |--------------------------------------------------------------------------
597
631
  */
598
632
 
599
- const visibleColumns = ref<number[]>([]);
633
+ const visibleColumns = ref<string[]>([]);
600
634
 
601
635
  // Find visible columns in local storage
602
636
  const VISIBLE_COLUMNS_LOCAL_STORAGE = 'sprintify.visible_columns.';
@@ -605,7 +639,7 @@ const VISIBLE_COLUMNS_LOCAL_STORAGE_KEY =
605
639
 
606
640
  const visibleColumnsFromStorage = JSON.parse(
607
641
  localStorage.getItem(VISIBLE_COLUMNS_LOCAL_STORAGE_KEY) + ''
608
- ) as number[];
642
+ ) as string[];
609
643
 
610
644
  // If found, set visibleColumns
611
645
  if (
@@ -759,10 +793,10 @@ function onWillScrollTop() {
759
793
  if (props.maxHeight) {
760
794
  table.value?.scrollTop();
761
795
 
762
- const top = dataIterator.value?.$el?.getBoundingClientRect()?.top ?? 0;
796
+ const top = dataIteratorRef.value?.$el?.getBoundingClientRect()?.top ?? 0;
763
797
 
764
798
  if (top < 0) {
765
- dataIterator.value?.scrollIntoView();
799
+ dataIteratorRef.value?.scrollIntoView();
766
800
  }
767
801
  }
768
802
  }
@@ -786,21 +820,21 @@ function onFetch(
786
820
  */
787
821
 
788
822
  function fetch() {
789
- if (!dataIterator.value) {
823
+ if (!dataIteratorRef.value) {
790
824
  return;
791
825
  }
792
- dataIterator.value.fetch();
826
+ dataIteratorRef.value.fetch();
793
827
  }
794
828
 
795
829
  function fetchWithoutLoading() {
796
- if (!dataIterator.value) {
830
+ if (!dataIteratorRef.value) {
797
831
  return;
798
832
  }
799
- dataIterator.value.fetchWithoutLoading();
833
+ dataIteratorRef.value.fetchWithoutLoading();
800
834
  }
801
835
 
802
836
  const dataIteratorQuery = computed((): DataTableQuery | null => {
803
- return dataIterator.value?.query ?? null;
837
+ return dataIteratorRef.value?.query ?? null;
804
838
  });
805
839
 
806
840
  defineExpose({