sprintify-ui 0.2.22 → 0.2.24

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 +2267 -2143
  2. package/dist/style.css +1 -1
  3. package/dist/types/src/components/BaseBadge.vue.d.ts +6 -0
  4. package/dist/types/src/components/BaseBreadcrumbs.vue.d.ts +11 -1
  5. package/dist/types/src/components/BaseDataIterator.vue.d.ts +15 -0
  6. package/dist/types/src/components/BaseDataIteratorSectionButton.vue.d.ts +8 -0
  7. package/dist/types/src/components/BaseDataIteratorSectionColumns.vue.d.ts +20 -0
  8. package/dist/types/src/components/BaseDataTable.vue.d.ts +21 -0
  9. package/dist/types/src/components/BaseDataTableRowAction.vue.d.ts +11 -1
  10. package/dist/types/src/components/BaseTable.vue.d.ts +9 -0
  11. package/dist/types/src/components/BaseTableColumn.vue.d.ts +1 -1
  12. package/dist/types/src/index.d.ts +2 -0
  13. package/package.json +1 -1
  14. package/src/components/BaseBadge.vue +10 -1
  15. package/src/components/BaseBreadcrumbs.stories.js +7 -2
  16. package/src/components/BaseBreadcrumbs.vue +23 -18
  17. package/src/components/BaseDataIterator.vue +49 -12
  18. package/src/components/BaseDataIteratorSectionButton.vue +16 -5
  19. package/src/components/BaseDataTable.stories.js +65 -35
  20. package/src/components/BaseDataTable.vue +38 -6
  21. package/src/components/BaseDataTableRowAction.vue +23 -4
  22. package/src/components/BaseHeader.stories.js +6 -0
  23. package/src/components/BaseHeader.vue +12 -9
  24. package/src/components/BaseMenu.stories.js +4 -0
  25. package/src/components/BaseMenuItem.vue +44 -17
  26. package/src/components/BaseTable.vue +34 -16
  27. package/src/components/BaseTableColumn.vue +1 -1
  28. package/src/index.ts +4 -1
  29. package/src/lang/en.json +2 -1
  30. package/src/lang/fr.json +2 -1
  31. package/src/utils/colors.ts +1 -1
@@ -8,6 +8,7 @@
8
8
  :actions="actions"
9
9
  :history-mode="historyMode"
10
10
  :layout="layout"
11
+ :size="size"
11
12
  :sections="sectionsInternal"
12
13
  :scroll-top-on-fetch="maxHeight ? false : scrollTopOnFetch"
13
14
  @fetch="onFetch"
@@ -40,7 +41,7 @@
40
41
  }}.</span>
41
42
  <button
42
43
  type="button"
43
- class="mr-3 inline text-slate-700 underline"
44
+ class="mr-3 inline text-slate-800 underline underline-offset-1 decoration-slate-400 decoration-2 decoration-dashed"
44
45
  @click="uncheckAll()"
45
46
  >
46
47
  {{ t('sui.deselect_all') }}
@@ -53,12 +54,19 @@
53
54
  >
54
55
  <template #button="{ open }">
55
56
  <div
56
- class="flex h-10 w-10 items-center justify-center rounded-full border border-slate-300 bg-white duration-150 hover:bg-slate-50"
57
+ class="flex h-10 px-4 items-center justify-center btn pl-3"
57
58
  :class="[
58
59
  open ? 'ring-2 ring-primary-500 ring-offset-2' : false,
59
60
  ]"
60
61
  >
61
- <BaseIcon icon="heroicons-solid:dots-vertical" />
62
+ <BaseIcon
63
+ icon="heroicons-solid:dots-vertical"
64
+ class="mr-2"
65
+ />
66
+
67
+ <span class="font-semibold">
68
+ {{ t('sui.bulk_actions') }}
69
+ </span>
62
70
  </div>
63
71
  </template>
64
72
  </BaseMenu>
@@ -79,6 +87,7 @@
79
87
  :sort-direction="sortDirection"
80
88
  :max-height="maxHeight"
81
89
  :visible-columns="visibleColumns"
90
+ :size="size"
82
91
  @update:checked-rows="onCheckedRowsUpdate"
83
92
  @sort="onSortChange"
84
93
  @cell-click="onCellClick"
@@ -103,16 +112,28 @@
103
112
  <BaseDataTableRowAction
104
113
  :row="row"
105
114
  :row-action="rowAction"
115
+ :size="size"
106
116
  />
107
117
  </template>
108
118
  <BaseMenu
109
119
  v-if="showRowActionMenu"
110
120
  :items="rowActionMenuItems(row)"
111
121
  size="sm"
112
- button-class="btn flex h-8 w-8 p-0 items-center justify-center"
122
+ :tw-button="[
123
+ 'btn flex p-0 items-center justify-center',
124
+ {
125
+ 'py-1.5 px-2': size == 'sm',
126
+ 'p-2': size == 'md'
127
+ }
128
+ ]"
113
129
  >
114
130
  <template #button>
115
- <BaseIcon icon="heroicons-solid:dots-vertical" />
131
+ <BaseIcon
132
+ icon="heroicons-solid:dots-vertical"
133
+ :class="{
134
+ 'h-3 w-3': size == 'sm'
135
+ }"
136
+ />
116
137
  </template>
117
138
  </BaseMenu>
118
139
  </div>
@@ -416,12 +437,23 @@ const props = defineProps({
416
437
 
417
438
  /**
418
439
  * Layout type
440
+ *
441
+ * default: Layout with a sidebar
442
+ * compact: Layout without a sidebar, this is the default layout for mobile, even if you don't specify it
419
443
  */
420
444
  layout: {
421
445
  default: 'default',
422
446
  type: String as PropType<'default' | 'compact'>,
423
447
  },
424
448
 
449
+ /**
450
+ * Overall size and spacing of the component
451
+ */
452
+ size: {
453
+ default: 'md',
454
+ type: String as PropType<'sm' | 'md'>,
455
+ },
456
+
425
457
  sections: {
426
458
  default: undefined,
427
459
  type: Array as PropType<DataIteratorSection[]>,
@@ -665,7 +697,7 @@ const sectionsInternal = computed<DataIteratorSection[]>(() => {
665
697
  ...sections,
666
698
  {
667
699
  name: 'columns',
668
- icon: 'heroicons:table-cells-20-solid',
700
+ icon: 'heroicons:view-columns',
669
701
  title: t('sui.columns'),
670
702
  closeText: t('sui.apply'),
671
703
  opened: false,
@@ -2,33 +2,52 @@
2
2
  <button
3
3
  v-if="rowAction.action"
4
4
  type="button"
5
- class="btn btn-white border border-slate-300 p-2 shadow-sm"
5
+ class="btn btn-white border border-slate-300 shadow-sm"
6
+ :class="{
7
+ 'py-1.5 px-2': size === 'sm',
8
+ 'p-2': size === 'md',
9
+ }"
6
10
  :disabled="rowAction.disabled && rowAction.disabled(row)"
7
11
  @click="rowAction.action ? rowAction.action(row) : null"
8
12
  >
9
13
  <BaseIcon
10
14
  :icon="rowAction.icon"
11
15
  class="text-slate-500"
16
+ :class="{
17
+ 'h-3 w-3': size == 'sm'
18
+ }"
12
19
  />
13
20
  </button>
14
21
  <RouterLink
15
22
  v-else-if="rowAction.to"
16
23
  :to="rowAction.to(row)"
17
24
  :disabled="rowAction.disabled && rowAction.disabled(row)"
18
- class="btn btn-white border border-slate-300 p-2 shadow-sm hover:bg-slate-100"
25
+ class="btn btn-white border border-slate-300 shadow-sm hover:bg-slate-100"
26
+ :class="{
27
+ 'py-1.5 px-2': size === 'sm',
28
+ 'p-2': size === 'md',
29
+ }"
19
30
  >
20
31
  <BaseIcon
21
32
  :icon="rowAction.icon"
22
33
  class="text-slate-500"
34
+ :class="{
35
+ 'h-3 w-3': size == 'sm'
36
+ }"
23
37
  />
24
38
  </RouterLink>
25
39
  </template>
26
40
 
27
41
  <script lang="ts" setup>
28
42
  import { CollectionItem, RowAction } from '@/types';
43
+ import { BaseIcon } from '.';
29
44
 
30
- defineProps<{
45
+ withDefaults(defineProps<{
31
46
  row: CollectionItem;
32
47
  rowAction: RowAction;
33
- }>();
48
+ size?: 'sm' | 'md';
49
+ }>(), {
50
+ size: 'md',
51
+ });
52
+
34
53
  </script>
@@ -3,6 +3,12 @@ import BaseHeader from './BaseHeader.vue';
3
3
  export default {
4
4
  title: 'Layout/BaseHeader',
5
5
  component: BaseHeader,
6
+ argTypes: {
7
+ layout: {
8
+ control: { type: 'select' },
9
+ options: ['default', 'compact'],
10
+ },
11
+ },
6
12
  };
7
13
 
8
14
  const Template = (args) => ({
@@ -3,10 +3,11 @@
3
3
  <BaseBreadcrumbs
4
4
  v-if="breadcrumbs"
5
5
  :breadcrumbs="breadcrumbs"
6
- class="mb-2"
6
+ :size="compactLayout ? 'sm' : 'md'"
7
+ class="lg:mb-1 mb-2"
7
8
  />
8
9
 
9
- <div class="lg:flex lg:items-center lg:justify-between">
10
+ <div class="lg:flex lg:items-top lg:justify-between">
10
11
  <div class="min-w-0 flex-1">
11
12
  <div class="flex flex-col xs:flex-row xs:flex-wrap xs:items-center">
12
13
  <h2
@@ -35,8 +36,8 @@
35
36
  </div>
36
37
  <h3
37
38
  v-if="subtitle"
38
- class="mt-1 leading-tight text-slate-500"
39
- :class="[compactLayout ? 'text-sm' : 'truncate text-base']"
39
+ class="mt-1 leading-tight text-slate-500 text-sm"
40
+ :class="[compactLayout ? '' : 'truncate text-base']"
40
41
  >
41
42
  {{ subtitle }}
42
43
  </h3>
@@ -45,18 +46,18 @@
45
46
  class="flex"
46
47
  :class="[
47
48
  compactLayout
48
- ? 'mt-1 flex-col'
49
- : 'mt-0 flex-row flex-wrap space-x-6',
49
+ ? 'mt-2 flex-col'
50
+ : 'mt-2 flex-row flex-wrap space-x-4',
50
51
  ]"
51
52
  >
52
53
  <div
53
54
  v-for="attribute in attributes"
54
55
  :key="attribute.label"
55
- class="mt-2 flex items-center text-sm text-slate-500"
56
+ class="flex items-center text-sm text-slate-500"
56
57
  >
57
58
  <BaseIcon
58
59
  :icon="attribute.icon"
59
- class="mr-1.5 h-5 w-5 flex-shrink-0 text-slate-400"
60
+ class="mr-1.5 h-4 w-4 flex-shrink-0 text-slate-400"
60
61
  aria-hidden="true"
61
62
  />
62
63
  {{ attribute.label }}
@@ -64,7 +65,9 @@
64
65
  </div>
65
66
  </div>
66
67
 
67
- <div class="mt-5">
68
+ <div
69
+ class="mt-4 lg:mt-0"
70
+ >
68
71
  <div
69
72
  class="flex gap-2"
70
73
  :class="{
@@ -13,6 +13,10 @@ export default {
13
13
  control: { type: 'select' },
14
14
  options: ['bottom-left', 'bottom-right'],
15
15
  },
16
+ size: {
17
+ control: { type: 'select' },
18
+ options: ['xs', 'sm', 'md'],
19
+ }
16
20
  },
17
21
  };
18
22
 
@@ -1,12 +1,16 @@
1
1
  <template>
2
- <div :class="buttonClasses">
2
+ <div
3
+ :style="buttonStyles"
4
+ class="rounded leading-tight"
5
+ :class="[active ? 'bg-slate-100' : 'bg-white']"
6
+ >
3
7
  <div class="flex items-center">
4
8
  <BaseIcon
5
9
  v-if="icon"
6
10
  :icon="icon"
7
- :class="iconClasses"
11
+ :class="[iconClasses]"
8
12
  />
9
- <span :class="textSize">{{ label }}</span>
13
+ <span :class="[textClasses, textColor]">{{ label }}</span>
10
14
  </div>
11
15
  <div
12
16
  v-if="count"
@@ -16,13 +20,14 @@
16
20
  :count="count"
17
21
  :max-digit="2"
18
22
  :color="color"
23
+ :size="size"
19
24
  />
20
25
  </div>
21
26
  </div>
22
27
  </template>
23
28
 
24
29
  <script lang="ts" setup>
25
- import { PropType } from 'vue';
30
+ import { PropType, StyleValue } from 'vue';
26
31
  import BaseCounter from './BaseCounter.vue';
27
32
  import { ActionColors } from '@/types';
28
33
 
@@ -73,7 +78,7 @@ const textColor = computed((): string => {
73
78
  return '';
74
79
  });
75
80
 
76
- const textSize = computed((): string => {
81
+ const textClasses = computed((): string => {
77
82
  if (props.size == 'xs') {
78
83
  return 'text-xs';
79
84
  } else if (props.size == 'sm') {
@@ -85,25 +90,47 @@ const textSize = computed((): string => {
85
90
  return '';
86
91
  });
87
92
 
88
- const buttonClasses = computed((): string => {
89
- let baseClasses =
90
- 'flex items-center justify-between w-full leading-tight py-2 text-sm text-left rounded';
93
+ const buttonStyles = computed((): StyleValue => {
91
94
 
92
- baseClasses += ' ' + textColor.value;
95
+ let paddingY = 0.5;
96
+ let paddingLeft = 1;
97
+ let paddingRight = 1;
93
98
 
94
- if (!props.active) {
95
- baseClasses += ' bg-white';
96
- } else {
97
- baseClasses += ' bg-slate-100';
99
+ const baseStyles = {
100
+ display: 'flex',
101
+ alignItems: 'center',
102
+ justifyContent: 'space-between',
103
+ width: '100%',
104
+ lineHeight: '1.25rem',
105
+ text: 'left',
106
+ paddingTop: '',
107
+ paddingBottom: '',
108
+ paddingLeft: '',
109
+ paddingRight: '',
98
110
  }
99
111
 
100
112
  if (props.icon) {
101
- baseClasses += ' pl-2 pr-4';
102
- } else {
103
- baseClasses += ' px-4';
113
+ paddingLeft = 0.5;
114
+ paddingRight = 1;
104
115
  }
105
116
 
106
- return baseClasses;
117
+ if (props.size == 'xs') {
118
+ paddingY = 0.3;
119
+ if (props.icon) {
120
+ paddingRight = 0.75;
121
+ }
122
+ } else if (props.size == 'sm') {
123
+ paddingY = 0.5;
124
+ } else if (props.size == 'md') {
125
+ paddingY = 0.5;
126
+ }
127
+
128
+ baseStyles.paddingLeft = paddingLeft + 'rem';
129
+ baseStyles.paddingRight = paddingRight + 'rem';
130
+ baseStyles.paddingTop = paddingY + 'rem';
131
+ baseStyles.paddingBottom = paddingY + 'rem';
132
+
133
+ return baseStyles;
107
134
  });
108
135
 
109
136
  const iconClasses = computed((): string => {
@@ -55,7 +55,7 @@
55
55
  column.style,
56
56
  index == 0 ? firstColStyles(true) : {},
57
57
  ]"
58
- class="th group py-2 pl-3 pr-3 text-left"
58
+ class="th group text-left px-3 py-2"
59
59
  :class="{
60
60
  'cursor-pointer': column.sortable,
61
61
  }"
@@ -69,7 +69,13 @@
69
69
  column.sortable && currentSortColumn === column,
70
70
  }"
71
71
  >
72
- <span class="whitespace-nowrap text-xs text-slate-500">
72
+ <span
73
+ class="whitespace-nowrap text-slate-600"
74
+ :class="{
75
+ 'text-[12px]': size == 'sm',
76
+ 'text-xs': size == 'md',
77
+ }"
78
+ >
73
79
  {{ column.label }}
74
80
  </span>
75
81
  <div
@@ -90,14 +96,14 @@
90
96
  :opacity="!isAsc ? '0.5' : '1'"
91
97
  fill="currentColor"
92
98
  d="M8.71 12.29L11.3 9.7a.996.996 0 0 1 1.41 0l2.59 2.59c.63.63.18 1.71-.71 1.71H9.41c-.89 0-1.33-1.08-.7-1.71z"
93
- />
99
+ ></path>
94
100
  </g>
95
101
  <g transform="translate(0 3)">
96
102
  <path
97
103
  :opacity="isAsc ? '0.5' : '1'"
98
104
  fill="currentColor"
99
105
  d="m8.71 11.71l2.59 2.59c.39.39 1.02.39 1.41 0l2.59-2.59c.63-.63.18-1.71-.71-1.71H9.41c-.89 0-1.33 1.08-.7 1.71z"
100
- />
106
+ ></path>
101
107
  </g>
102
108
  </svg>
103
109
  </div>
@@ -151,8 +157,8 @@
151
157
  <td
152
158
  v-if="checkable && checkboxPosition === 'left'"
153
159
  class="group z-[1] cursor-pointer bg-white pl-3"
154
- :style="checkStyles(false)"
155
160
  :class="borderBottomClasses(index, row)"
161
+ :style="checkStyles(false)"
156
162
  @click="checkRow(row, index, $event as MouseEvent)"
157
163
  >
158
164
  <div class="flex items-center">
@@ -174,26 +180,34 @@
174
180
  scoped
175
181
  name="default"
176
182
  tag="td"
177
- class="bg-white py-3 pl-3 pr-3 text-sm"
178
- :style="[
179
- column.style,
180
- colindex === 0 ? firstColStyles(false) : {},
181
- ]"
183
+ class="bg-white text-sm"
182
184
  :class="[
183
185
  borderBottomClasses(index, row),
184
186
  column.clickable ? 'cursor-pointer' : '',
187
+ {
188
+ 'py-0.5 px-3': size == 'sm',
189
+ 'py-2 px-3': size == 'md',
190
+ }
191
+ ]"
192
+ :style="[
193
+ column.style,
194
+ colindex === 0 ? firstColStyles(false) : {}
185
195
  ]"
186
196
  :data-label="column.label"
187
197
  :props="{ row, column, index, colindex, toggleDetails }"
188
- @click="
189
- onColumnClick(row, column, index, colindex, $event)
190
- "
198
+ @click="onColumnClick(row, column, index, colindex, $event)"
191
199
  />
192
200
 
193
201
  <td
194
202
  v-if="checkable && checkboxPosition === 'right'"
195
- class="group cursor-pointer pr-3"
196
- :class="borderBottomClasses(index, row)"
203
+ class="group cursor-pointer"
204
+ :class="[
205
+ borderBottomClasses(index, row),
206
+ {
207
+ 'px-3 py-1': size == 'sm',
208
+ 'p-3': size == 'md',
209
+ }
210
+ ]"
197
211
  align="right"
198
212
  @click="checkRow(row, index, $event as MouseEvent)"
199
213
  >
@@ -214,7 +228,6 @@
214
228
  >
215
229
  <td
216
230
  :colspan="columnCount"
217
- class="td"
218
231
  :class="borderBottomDetailClasses(index)"
219
232
  >
220
233
  <slot
@@ -361,6 +374,10 @@ const props = defineProps({
361
374
  default: undefined,
362
375
  type: Number,
363
376
  },
377
+ size: {
378
+ type: String as PropType<'sm' | 'md'>,
379
+ default: 'md',
380
+ },
364
381
  });
365
382
 
366
383
  const emit = defineEmits([
@@ -375,6 +392,7 @@ const emit = defineEmits([
375
392
  ]);
376
393
 
377
394
  const visibleDetailRows = ref<Row[]>([]);
395
+ // eslint-disable-next-line vue/no-setup-props-destructure
378
396
  const newCheckedRows = ref<Row[]>([...props.checkedRows]);
379
397
  const lastCheckedRowIndex = ref<number | null>(null);
380
398
  const currentSortColumn = ref<BaseTableColumn | null>(null);
@@ -95,7 +95,7 @@ export default defineComponent({
95
95
  style() {
96
96
  return {
97
97
  width: this.width ? this.width + 'px' : undefined,
98
- padding: this.padding ? this.padding : '0.5rem 0.75rem',
98
+ padding: this.padding ? this.padding : undefined,
99
99
  };
100
100
  },
101
101
  },
package/src/index.ts CHANGED
@@ -19,11 +19,12 @@ import { Region } from './types/Region';
19
19
  import { useI18nStore } from './stores/i18n';
20
20
 
21
21
  export interface Options {
22
- // eslint-disable-next-line @typescript-eslint/ban-types
23
22
  http?: AxiosInstance;
24
23
  upload_url?: string;
25
24
  locales?: Locales;
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
26
  formatQueryString?: (params: Record<string, any>) => string;
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
28
  parseQueryString?: (params: string) => Record<string, any>;
28
29
  countries?: Country[];
29
30
  regions?: Region[];
@@ -36,12 +37,14 @@ const config = {
36
37
  fr: 'Français',
37
38
  } as Locales,
38
39
  upload_url: '/api/upload',
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
39
41
  formatQueryString(params: Record<string, any>) {
40
42
  return QueryString.stringify(params, {
41
43
  arrayFormat: 'comma',
42
44
  encode: import.meta.env.PROD ? true : false,
43
45
  });
44
46
  },
47
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
48
  parseQueryString(params: string): Record<string, any> {
46
49
  return QueryString.parse(params);
47
50
  },
package/src/lang/en.json CHANGED
@@ -12,6 +12,7 @@
12
12
  "apply_filters": "Apply filters",
13
13
  "authentication_code": "Authentication code",
14
14
  "autocomplete_placeholder": "Type to start your search",
15
+ "bulk_actions": "Bulk actions",
15
16
  "cancel": "Cancel",
16
17
  "city": "City",
17
18
  "clear": "Clear",
@@ -85,4 +86,4 @@
85
86
  "you_can_upload_up_to_n_files": "You can upload one file at most|You can upload up to {count} files",
86
87
  "you_cannot_select_more_than_x_items": "You can't select more than one item|You can't select more than {count} items"
87
88
  }
88
- }
89
+ }
package/src/lang/fr.json CHANGED
@@ -12,6 +12,7 @@
12
12
  "apply_filters": "Appliquer les filtres",
13
13
  "authentication_code": "Code d'authentification",
14
14
  "autocomplete_placeholder": "Taper pour lancer votre recherche",
15
+ "bulk_actions": "Actions en lot",
15
16
  "cancel": "Annuler",
16
17
  "city": "Ville",
17
18
  "clear": "Effacer",
@@ -85,4 +86,4 @@
85
86
  "you_can_upload_up_to_n_files": "Vous pouvez télécharger un fichier au maximum|Vous pouvez télécharger jusqu'à {count} fichiers",
86
87
  "you_cannot_select_more_than_x_items": "Vous ne pouvez pas sélectionner plus de un élément|Vous ne pouvez pas sélectionner plus de {count} éléments"
87
88
  }
88
- }
89
+ }
@@ -31,7 +31,7 @@ export const palette: Record<string, ColorPalette> = {
31
31
  },
32
32
  gray: {
33
33
  low: {
34
- backgroundColor: colors.slate[100],
34
+ backgroundColor: colors.slate[200],
35
35
  textColor: colors.slate[800],
36
36
  borderColor: colors.slate[300],
37
37
  },