sprintify-ui 0.0.9 → 0.0.11

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 (51) hide show
  1. package/README.md +14 -3
  2. package/dist/sprintify-ui.es.js +3851 -6637
  3. package/dist/style.css +2 -2
  4. package/dist/tailwindcss/index.js +283 -32
  5. package/dist/types/src/components/BaseAutocomplete.vue.d.ts +0 -1
  6. package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +0 -1
  7. package/dist/types/src/components/BaseBelongsTo.vue.d.ts +13 -3
  8. package/dist/types/src/components/BaseDataTable.vue.d.ts +95 -64
  9. package/dist/types/src/components/BaseDialog.vue.d.ts +8 -8
  10. package/dist/types/src/components/BaseFilePicker.vue.d.ts +3 -3
  11. package/dist/types/src/components/BaseLoadingCover.vue.d.ts +12 -12
  12. package/dist/types/src/components/BaseMenuItem.vue.d.ts +4 -4
  13. package/dist/types/src/components/BaseNavbarItemContent.vue.d.ts +4 -4
  14. package/dist/types/src/components/BaseTableColumn.vue.d.ts +4 -4
  15. package/dist/types/src/svg/BaseEmptyState.vue.d.ts +2 -0
  16. package/dist/types/src/{components/BaseSpinner.vue.d.ts → svg/BaseSpinnerLarge.vue.d.ts} +0 -0
  17. package/dist/types/src/svg/BaseSpinnerSmall.vue.d.ts +44 -0
  18. package/dist/types/src/types/types.d.ts +1 -1
  19. package/package.json +4 -2
  20. package/src/assets/form.css +1 -10
  21. package/src/assets/main.css +0 -1
  22. package/src/assets/tailwind.css +3 -5
  23. package/src/components/BaseAutocomplete.stories.js +7 -4
  24. package/src/components/BaseAutocomplete.vue +44 -15
  25. package/src/components/BaseAutocompleteFetch.stories.js +6 -3
  26. package/src/components/BaseAutocompleteFetch.vue +8 -3
  27. package/src/components/BaseBelongsTo.stories.js +9 -4
  28. package/src/components/BaseBelongsTo.vue +1 -0
  29. package/src/components/BaseButton.stories.js +11 -3
  30. package/src/components/BaseCard.vue +1 -1
  31. package/src/components/BaseDataIterator.stories.js +102 -3
  32. package/src/components/BaseDataIterator.vue +44 -12
  33. package/src/components/BaseDataTable.stories.js +149 -2
  34. package/src/components/BaseDataTable.vue +34 -28
  35. package/src/components/BaseDataTableToggleColumns.vue +1 -1
  36. package/src/components/BaseDateSelect.vue +6 -2
  37. package/src/components/BaseDescriptionListItem.vue +40 -4
  38. package/src/components/BaseDialog.stories.js +51 -0
  39. package/src/components/BaseDialog.vue +13 -7
  40. package/src/components/BaseFilePicker.stories.js +51 -0
  41. package/src/components/BaseFilePicker.vue +6 -6
  42. package/src/components/BaseFileUploader.stories.js +80 -0
  43. package/src/components/BaseFileUploader.vue +12 -3
  44. package/src/components/BaseLoadingCover.vue +8 -16
  45. package/src/components/BaseTable.vue +42 -29
  46. package/src/components/BaseTableColumn.vue +2 -2
  47. package/src/svg/BaseEmptyState.vue +34 -0
  48. package/src/{components/BaseSpinner.vue → svg/BaseSpinnerLarge.vue} +0 -0
  49. package/src/svg/BaseSpinnerSmall.vue +9 -0
  50. package/src/types/types.ts +1 -1
  51. package/src/assets/button.css +0 -80
@@ -0,0 +1,80 @@
1
+ import BaseFileUploader from './BaseFileUploader.vue';
2
+ import BaseLoadingCover from './BaseLoadingCover.vue';
3
+ import BaseAppNotifications from './BaseAppNotifications.vue';
4
+ import { Icon as BaseIcon } from '@iconify/vue';
5
+
6
+ export default {
7
+ title: 'Form/BaseFileUploader',
8
+ component: BaseFileUploader,
9
+ args: {
10
+ buttonClass: 'w-full',
11
+ acceptedExtensions: ['jpg', 'png'],
12
+ maxSize: 1024 * 200, // 200kb
13
+ url: 'https://dummyjson.com/posts/add',
14
+ },
15
+ };
16
+
17
+ const Template = (args) => ({
18
+ components: {
19
+ BaseFileUploader,
20
+ BaseIcon,
21
+ BaseLoadingCover,
22
+ BaseAppNotifications,
23
+ },
24
+ setup() {
25
+ return { args };
26
+ },
27
+ template: `
28
+ <BaseFileUploader v-bind="args">
29
+ <template #default="{ dragging, disabled, uploading, selecting }">
30
+ <div
31
+ class="flex w-full items-center space-x-4 rounded-lg border-2 border-dashed border-slate-200 p-5 duration-100"
32
+ :class="[
33
+ dragging ? 'bg-slate-100' : 'bg-white',
34
+ disabled ? 'bg-slate-100 cursor-not-allowed' : 'hover:bg-slate-50',
35
+ ]"
36
+ >
37
+ <div class="rounded-full bg-slate-200 p-2">
38
+ <BaseIcon
39
+ icon="heroicons:arrow-up-on-square"
40
+ class="h-6 w-6"
41
+ :class="[disabled ? 'text-slate-400' : 'text-slate-500']"
42
+ />
43
+ </div>
44
+ <div class="text-left">
45
+ <p
46
+ class="mb-0 text-sm font-medium leading-tight"
47
+ :class="[disabled ? 'text-slate-400' : 'text-slate-900']"
48
+ >
49
+ {{ $t("sui.drop_or_click_to_upload") }}
50
+ </p>
51
+ <p class="text-sm text-slate-500 mt-1">Max 200kb</p>
52
+ <p class="text-sm text-slate-500">.jpg, .png</p>
53
+ </div>
54
+ </div>
55
+ </template>
56
+ <template #loading="{ dragging, disabled, uploading, selecting }">
57
+ <BaseLoadingCover
58
+ :model-value="args.loading || uploading || selecting"
59
+ :delay="0"
60
+ icon-class="text-primary-600 w-6 h-6"
61
+ backdrop-class="bg-white opacity-60"
62
+ />
63
+ </template>
64
+ </BaseFileUploader>
65
+ <BaseAppNotifications></BaseAppNotifications>
66
+ `,
67
+ });
68
+
69
+ export const Demo = Template.bind({});
70
+ Demo.args = {};
71
+
72
+ export const Disabled = Template.bind({});
73
+ Disabled.args = {
74
+ disabled: true,
75
+ };
76
+
77
+ export const Loading = Template.bind({});
78
+ Loading.args = {
79
+ loading: true,
80
+ };
@@ -4,7 +4,7 @@
4
4
  :button-class="buttonClass"
5
5
  :disabled="uploading || disabled"
6
6
  :accept="accept"
7
- @upload="onPictureUpload"
7
+ @select="onFileSelect"
8
8
  >
9
9
  <template #default="slotProps">
10
10
  <slot
@@ -22,6 +22,7 @@
22
22
  :disabled="slotProps.disabled"
23
23
  >
24
24
  <BaseLoadingCover
25
+ :delay="0"
25
26
  icon-class="text-primary-600 w-6 h-6"
26
27
  :model-value="loading || uploading || slotProps.selecting"
27
28
  />
@@ -37,6 +38,8 @@ import { PropType } from 'vue';
37
38
  import { UploadedFile } from '@/types/UploadedFile';
38
39
  import { toHumanList, fileSizeFormat } from '../utils';
39
40
  import { useNotificationsStore } from '../stores/notifications';
41
+ import BaseLoadingCover from './BaseLoadingCover.vue';
42
+ import BaseFilePicker from './BaseFilePicker.vue';
40
43
 
41
44
  const http = config.http;
42
45
  const i18n = useI18n();
@@ -88,8 +91,11 @@ const emit = defineEmits([
88
91
 
89
92
  const uploading = ref(false);
90
93
 
91
- async function onPictureUpload(file: File) {
94
+ async function onFileSelect(file: File) {
95
+ uploading.value = true;
96
+
92
97
  if (!(await props.beforeUpload())) {
98
+ uploading.value = false;
93
99
  return;
94
100
  }
95
101
 
@@ -102,6 +108,8 @@ async function onPictureUpload(file: File) {
102
108
  x: fileSizeFormat(props.maxSize),
103
109
  }),
104
110
  });
111
+
112
+ uploading.value = false;
105
113
  return;
106
114
  }
107
115
 
@@ -124,6 +132,8 @@ async function onPictureUpload(file: File) {
124
132
  toHumanList(props.acceptedExtensions, i18n.t('sui.or')) +
125
133
  '.',
126
134
  });
135
+
136
+ uploading.value = false;
127
137
  return;
128
138
  }
129
139
  }
@@ -132,7 +142,6 @@ async function onPictureUpload(file: File) {
132
142
 
133
143
  formData.append('file', file);
134
144
 
135
- uploading.value = true;
136
145
  emit('upload:start');
137
146
 
138
147
  const response = await http.post(props.url ?? config.upload_url, formData);
@@ -12,25 +12,17 @@
12
12
  class="absolute inset-0 flex h-full w-full items-center justify-center"
13
13
  >
14
14
  <div class="absolute h-full w-full" :class="backdropClass" />
15
- <svg
16
- v-if="icon == 'line'"
17
- class="animate-spin"
18
- :class="iconClass"
19
- viewBox="0 0 24 24"
20
- >
21
- <path
22
- fill="currentColor"
23
- d="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z"
24
- />
25
- </svg>
26
- <BaseSpinner v-else-if="icon == 'spinner'" :class="iconClass" />
15
+
16
+ <BaseSpinnerSmall v-if="size == 'sm'" :class="iconClass" />
17
+ <BaseSpinnerLarge v-else-if="size == 'lg'" :class="iconClass" />
27
18
  </div>
28
19
  </Transition>
29
20
  </template>
30
21
 
31
22
  <script lang="ts" setup>
32
23
  import { PropType } from 'vue';
33
- import BaseSpinner from './BaseSpinner.vue';
24
+ import BaseSpinnerSmall from '../svg/BaseSpinnerSmall.vue';
25
+ import BaseSpinnerLarge from '../svg/BaseSpinnerLarge.vue';
34
26
 
35
27
  const props = defineProps({
36
28
  modelValue: {
@@ -45,9 +37,9 @@ const props = defineProps({
45
37
  default: 'text-blue-500 w-10 h-10',
46
38
  type: String,
47
39
  },
48
- icon: {
49
- default: 'line',
50
- type: String as PropType<'line' | 'spinner'>,
40
+ size: {
41
+ default: 'sm',
42
+ type: String as PropType<'sm' | 'lg'>,
51
43
  },
52
44
  duration: {
53
45
  default: 'duration-300',
@@ -6,7 +6,7 @@
6
6
 
7
7
  <div class="flex flex-col">
8
8
  <div
9
- class="isolate overflow-x-auto overflow-y-auto"
9
+ class="overflow-x-auto overflow-y-auto"
10
10
  :style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }"
11
11
  >
12
12
  <div class="inline-block min-w-full align-middle">
@@ -17,17 +17,19 @@
17
17
  <th v-if="showDetailRowIcon" class="th" />
18
18
  <th
19
19
  v-if="checkable && checkboxPosition === 'left'"
20
- class="th pl-3"
20
+ class="th py-0 pl-3"
21
21
  align="left"
22
22
  >
23
- <input
24
- type="checkbox"
25
- autocomplete="off"
26
- :checked="isAllChecked"
27
- :disabled="isAllUncheckable"
28
- :class="checkboxStyle"
29
- @change="checkAll"
30
- />
23
+ <div class="flex items-center">
24
+ <input
25
+ type="checkbox"
26
+ autocomplete="off"
27
+ :checked="isAllChecked"
28
+ :disabled="isAllUncheckable"
29
+ :class="checkboxStyle"
30
+ @change="checkAll"
31
+ />
32
+ </div>
31
33
  </th>
32
34
  <th
33
35
  v-for="(column, index) in visibleColumns"
@@ -166,14 +168,16 @@
166
168
  class="pl-3"
167
169
  :class="borderBottomClasses(index, row)"
168
170
  >
169
- <input
170
- type="checkbox"
171
- autocomplete="off"
172
- :disabled="!isRowCheckable(row)"
173
- :checked="isRowChecked(row)"
174
- :class="checkboxStyle"
175
- @click="checkRow(row, index, $event as MouseEvent)"
176
- />
171
+ <div class="flex items-center">
172
+ <input
173
+ type="checkbox"
174
+ autocomplete="off"
175
+ :disabled="!isRowCheckable(row)"
176
+ :checked="isRowChecked(row)"
177
+ :class="checkboxStyle"
178
+ @click="checkRow(row, index, $event as MouseEvent)"
179
+ />
180
+ </div>
177
181
  </td>
178
182
 
179
183
  <SlotComponent
@@ -239,12 +243,25 @@
239
243
  </table>
240
244
 
241
245
  <slot name="loading">
242
- <BaseLoadingCover
243
- :delay="0"
244
- :model-value="loading"
245
- backdrop-class="bg-white bg-opacity-50"
246
- />
247
- <div v-if="loading" class="h-[300px]" />
246
+ <Transition
247
+ enter-active-class="transition ease-out duration-200"
248
+ enter-from-class="opacity-0"
249
+ enter-to-class="opacity-100"
250
+ leave-active-class="transition ease-in duration-200"
251
+ leave-from-class="opacity-100"
252
+ leave-to-class="opacity-0"
253
+ >
254
+ <div
255
+ v-if="loading"
256
+ class="absolute inset-0 flex h-full w-full items-start justify-center"
257
+ >
258
+ <div class="absolute h-full w-full bg-white bg-opacity-60" />
259
+
260
+ <div class="pt-20">
261
+ <BaseSpinnerLarge class="h-10 w-10 text-blue-500" />
262
+ </div>
263
+ </div>
264
+ </Transition>
248
265
  </slot>
249
266
  </div>
250
267
  </div>
@@ -266,8 +283,8 @@ import { BaseTableColumn, MenuItemInterface, Row } from '@/types/types';
266
283
  import SlotComponent from './SlotComponent';
267
284
  import { useResizeObserver } from '@vueuse/core';
268
285
  import { debounce, isArray } from 'lodash';
269
- import BaseLoadingCover from './BaseLoadingCover.vue';
270
286
  import BaseMenu from './BaseMenu.vue';
287
+ import BaseSpinnerLarge from '../svg/BaseSpinnerLarge.vue';
271
288
 
272
289
  const checkboxStyle =
273
290
  'disabled:bg-slate-100 disabled:border-slate-300 disabled:cursor-not-allowed border-slate-400 rounded';
@@ -406,10 +423,6 @@ const visibleColumns = computed(() => {
406
423
  return false;
407
424
  }
408
425
 
409
- if (column.alwaysVisible) {
410
- return true;
411
- }
412
-
413
426
  if (!isArray(props.visibleColumns)) {
414
427
  return true;
415
428
  }
@@ -44,9 +44,9 @@ export default defineComponent({
44
44
  type: Boolean,
45
45
  default: true,
46
46
  },
47
- alwaysVisible: {
47
+ toggle: {
48
48
  type: Boolean,
49
- default: false,
49
+ default: true,
50
50
  },
51
51
  optional: {
52
52
  type: Boolean,
@@ -0,0 +1,34 @@
1
+ <template>
2
+ <svg viewBox="0 0 150 150" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path
4
+ class="text-slate-100"
5
+ d="M75 150C116.421 150 150 116.421 150 75C150 33.5786 116.421 0 75 0C33.5786 0 0 33.5786 0 75C0 116.421 33.5786 150 75 150Z"
6
+ fill="currentColor"
7
+ />
8
+ <path
9
+ class="text-white"
10
+ d="M120 150H30V53C34.242 52.9952 38.3089 51.308 41.3084 48.3085C44.308 45.3089 45.9952 41.242 46 37H104C103.996 39.1014 104.408 41.1828 105.213 43.1238C106.018 45.0648 107.2 46.8268 108.691 48.308C110.172 49.7991 111.934 50.9816 113.875 51.787C115.817 52.5924 117.898 53.0047 120 53V150Z"
11
+ fill="currentColor"
12
+ />
13
+ <path
14
+ class="text-slate-300"
15
+ d="M75 102C88.2548 102 99 91.2548 99 78C99 64.7452 88.2548 54 75 54C61.7452 54 51 64.7452 51 78C51 91.2548 61.7452 102 75 102Z"
16
+ fill="currentColor"
17
+ />
18
+ <path
19
+ class="text-white"
20
+ d="M83.4853 89.3138L75 80.8286L66.5147 89.3138L63.6863 86.4854L72.1716 78.0001L63.6863 69.5148L66.5147 66.6864L75 75.1717L83.4853 66.6864L86.3137 69.5148L77.8284 78.0001L86.3137 86.4854L83.4853 89.3138Z"
21
+ fill="currentColor"
22
+ />
23
+ <path
24
+ class="text-slate-200"
25
+ d="M88 108H62C60.3431 108 59 109.343 59 111C59 112.657 60.3431 114 62 114H88C89.6569 114 91 112.657 91 111C91 109.343 89.6569 108 88 108Z"
26
+ fill="currentColor"
27
+ />
28
+ <path
29
+ class="text-slate-200"
30
+ d="M97 120H53C51.3431 120 50 121.343 50 123C50 124.657 51.3431 126 53 126H97C98.6569 126 100 124.657 100 123C100 121.343 98.6569 120 97 120Z"
31
+ fill="currentColor"
32
+ />
33
+ </svg>
34
+ </template>
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <svg class="animate-spin" viewBox="0 0 24 24">
3
+ <path fill="currentColor" d="M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z" />
4
+ </svg>
5
+ </template>
6
+
7
+ <script lang="ts" setup></script>
8
+
9
+ <style scoped></style>
@@ -99,7 +99,7 @@ export interface BaseTableColumn {
99
99
  searchable: boolean;
100
100
  sortable: boolean;
101
101
  visible: boolean;
102
- alwaysVisible: boolean;
102
+ toggle: boolean;
103
103
  optional: boolean;
104
104
  width: number;
105
105
  style: {
@@ -1,80 +0,0 @@
1
- .btn {
2
- @apply text-center relative inline-block cursor-pointer select-none rounded-md border px-4 py-2.5 text-sm transition-colors duration-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50;
3
- @apply btn-default;
4
- }
5
-
6
- .btn.btn-xs {
7
- @apply px-2 py-1 text-xs leading-4;
8
- }
9
-
10
- .btn.btn-sm {
11
- @apply px-3 py-2 text-sm leading-4;
12
- }
13
-
14
- .btn.btn-md {
15
- @apply px-4 py-2.5 text-sm;
16
- }
17
-
18
- .btn.btn-lg {
19
- @apply px-5 py-3 text-base;
20
- }
21
-
22
- .btn.btn-xl {
23
- @apply px-6 py-4 text-base;
24
- }
25
-
26
- .btn-default {
27
- @apply border-slate-300 bg-white text-slate-600 hover:bg-slate-100 focus-visible:ring-primary-500 disabled:hover:bg-white;
28
- }
29
-
30
- .btn.btn-primary {
31
- @apply border-transparent bg-primary-500 text-white hover:bg-primary-700 focus-visible:ring-primary-500 disabled:hover:bg-primary-500;
32
- }
33
-
34
- .btn.btn-secondary {
35
- @apply border-transparent bg-primary-200 text-primary-700 hover:bg-primary-100 focus-visible:ring-primary-500 disabled:hover:bg-primary-100;
36
- }
37
-
38
- .btn.btn-secondary-outline {
39
- @apply border-primary-400 bg-primary-200 text-primary-700 hover:bg-primary-100 focus-visible:ring-primary-500 disabled:hover:bg-primary-100;
40
- }
41
-
42
- .btn.btn-slate-100 {
43
- @apply border-transparent bg-slate-100 text-slate-700 hover:bg-slate-200 focus-visible:ring-slate-300 disabled:hover:bg-slate-50;
44
- }
45
-
46
- .btn.btn-slate-100-outline {
47
- @apply border-slate-200 bg-slate-100 text-slate-700 hover:bg-slate-50 focus-visible:ring-slate-300 disabled:hover:bg-slate-50;
48
- }
49
-
50
- .btn.btn-slate-200 {
51
- @apply border-transparent bg-slate-200 text-slate-800 hover:bg-slate-300 focus-visible:ring-slate-300 disabled:hover:bg-slate-50;
52
- }
53
-
54
- .btn.btn-slate-200-outline {
55
- @apply border-slate-300 bg-slate-200 text-slate-800 hover:bg-slate-300 focus-visible:ring-slate-300 disabled:hover:bg-slate-50;
56
- }
57
-
58
- .btn.btn-white {
59
- @apply border-transparent bg-white text-slate-600 hover:bg-slate-100 focus-visible:ring-primary-500 disabled:hover:bg-white;
60
- }
61
-
62
- .btn.btn-white-outline {
63
- @apply btn-default;
64
- }
65
-
66
- .btn.btn-white-outline-primary {
67
- @apply border-primary-400 bg-white text-primary-600 hover:bg-primary-100 focus-visible:ring-primary-500 disabled:hover:bg-white;
68
- }
69
-
70
- .btn.btn-black {
71
- @apply border-transparent bg-slate-900 text-white hover:bg-slate-800 focus-visible:ring-slate-900 disabled:hover:bg-slate-900;
72
- }
73
-
74
- .btn.btn-danger {
75
- @apply border-transparent bg-red-600 text-white hover:bg-red-700 focus-visible:ring-red-300 disabled:hover:bg-red-600;
76
- }
77
-
78
- .btn.btn-warning {
79
- @apply border-transparent bg-yellow-400 text-yellow-900 hover:bg-yellow-200 focus-visible:ring-yellow-300 disabled:hover:bg-yellow-300;
80
- }