sprintify-ui 0.0.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 (176) hide show
  1. package/README.md +188 -0
  2. package/dist/types/src/components/BaseAlert.vue.d.ts +51 -0
  3. package/dist/types/src/components/BaseAutocomplete.vue.d.ts +268 -0
  4. package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +273 -0
  5. package/dist/types/src/components/BaseAvatar.vue.d.ts +126 -0
  6. package/dist/types/src/components/BaseBadge.vue.d.ts +94 -0
  7. package/dist/types/src/components/BaseBelongsTo.vue.d.ts +268 -0
  8. package/dist/types/src/components/BaseBoolean.vue.d.ts +64 -0
  9. package/dist/types/src/components/BaseBreadcrumbs.vue.d.ts +66 -0
  10. package/dist/types/src/components/BaseButton.vue.d.ts +23 -0
  11. package/dist/types/src/components/BaseCard.vue.d.ts +74 -0
  12. package/dist/types/src/components/BaseCardRow.vue.d.ts +16 -0
  13. package/dist/types/src/components/BaseClipboard.vue.d.ts +74 -0
  14. package/dist/types/src/components/BaseContainer.vue.d.ts +34 -0
  15. package/dist/types/src/components/BaseCounter.vue.d.ts +125 -0
  16. package/dist/types/src/components/BaseDataIterator.vue.d.ts +345 -0
  17. package/dist/types/src/components/BaseDataTable.vue.d.ts +657 -0
  18. package/dist/types/src/components/BaseDataTableToggleColumns.vue.d.ts +1281 -0
  19. package/dist/types/src/components/BaseDatePicker.vue.d.ts +190 -0
  20. package/dist/types/src/components/BaseDateSelect.vue.d.ts +171 -0
  21. package/dist/types/src/components/BaseDescriptionList.vue.d.ts +48 -0
  22. package/dist/types/src/components/BaseDescriptionListItem.vue.d.ts +49 -0
  23. package/dist/types/src/components/BaseDialog.vue.d.ts +160 -0
  24. package/dist/types/src/components/BaseFilePicker.vue.d.ts +44 -0
  25. package/dist/types/src/components/BaseFileUploader.vue.d.ts +220 -0
  26. package/dist/types/src/components/BaseInput.vue.d.ts +209 -0
  27. package/dist/types/src/components/BaseInputLabel.vue.d.ts +31 -0
  28. package/dist/types/src/components/BaseLoadingCover.vue.d.ts +166 -0
  29. package/dist/types/src/components/BaseLoadingPage.vue.d.ts +2 -0
  30. package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +269 -0
  31. package/dist/types/src/components/BaseMediaLibraryItem.vue.d.ts +75 -0
  32. package/dist/types/src/components/BaseMenu.vue.d.ts +117 -0
  33. package/dist/types/src/components/BaseMenuItem.vue.d.ts +147 -0
  34. package/dist/types/src/components/BaseModalCenter.vue.d.ts +141 -0
  35. package/dist/types/src/components/BaseModalSide.vue.d.ts +141 -0
  36. package/dist/types/src/components/BaseNavbar.vue.d.ts +79 -0
  37. package/dist/types/src/components/BaseNavbarItem.vue.d.ts +80 -0
  38. package/dist/types/src/components/BaseNavbarItemContent.vue.d.ts +127 -0
  39. package/dist/types/src/components/BasePagination.vue.d.ts +25 -0
  40. package/dist/types/src/components/BasePaginationSimple.vue.d.ts +25 -0
  41. package/dist/types/src/components/BasePanel.vue.d.ts +31 -0
  42. package/dist/types/src/components/BasePassword.vue.d.ts +66 -0
  43. package/dist/types/src/components/BaseProcessRing.vue.d.ts +36 -0
  44. package/dist/types/src/components/BaseReadMore.vue.d.ts +74 -0
  45. package/dist/types/src/components/BaseSelect.vue.d.ts +55 -0
  46. package/dist/types/src/components/BaseSideNavigation.vue.d.ts +48 -0
  47. package/dist/types/src/components/BaseSideNavigationItem.vue.d.ts +92 -0
  48. package/dist/types/src/components/BaseSkeleton.vue.d.ts +93 -0
  49. package/dist/types/src/components/BaseSpinner.vue.d.ts +2 -0
  50. package/dist/types/src/components/BaseSwitch.vue.d.ts +39 -0
  51. package/dist/types/src/components/BaseSystemAlert.vue.d.ts +141 -0
  52. package/dist/types/src/components/BaseTabItem.vue.d.ts +70 -0
  53. package/dist/types/src/components/BaseTable.vue.d.ts +467 -0
  54. package/dist/types/src/components/BaseTableColumn.vue.d.ts +164 -0
  55. package/dist/types/src/components/BaseTabs.vue.d.ts +48 -0
  56. package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +274 -0
  57. package/dist/types/src/components/BaseTagAutocompleteFetch.vue.d.ts +251 -0
  58. package/dist/types/src/components/BaseTextarea.vue.d.ts +228 -0
  59. package/dist/types/src/components/BaseTextareaAutoresize.vue.d.ts +44 -0
  60. package/dist/types/src/components/BaseTitle.vue.d.ts +45 -0
  61. package/dist/types/src/components/BaseWordCount.vue.d.ts +31 -0
  62. package/dist/types/src/components/SlotComponent.d.ts +43 -0
  63. package/dist/types/src/components/index.d.ts +2 -0
  64. package/dist/types/src/composables/breakpoints.d.ts +12 -0
  65. package/dist/types/src/composables/modal.d.ts +6 -0
  66. package/dist/types/src/constants/MyConstants.d.ts +1 -0
  67. package/dist/types/src/constants/index.d.ts +2 -0
  68. package/dist/types/src/index.d.ts +253 -0
  69. package/dist/types/src/types/Media.d.ts +8 -0
  70. package/dist/types/src/types/UploadedFile.d.ts +9 -0
  71. package/dist/types/src/types/User.d.ts +6 -0
  72. package/dist/types/src/types/types.d.ts +88 -0
  73. package/dist/types/src/utils/fileSizeFormat.d.ts +1 -0
  74. package/dist/types/src/utils/index.d.ts +4 -0
  75. package/dist/types/src/utils/scrollPreventer.d.ts +4 -0
  76. package/dist/types/src/utils/toHumanList.d.ts +1 -0
  77. package/package.json +99 -0
  78. package/src/assets/button.css +80 -0
  79. package/src/assets/form.css +15 -0
  80. package/src/assets/main.css +3 -0
  81. package/src/assets/pikaday.css +134 -0
  82. package/src/assets/tailwind.css +5 -0
  83. package/src/components/BaseAlert.stories.js +52 -0
  84. package/src/components/BaseAlert.vue +152 -0
  85. package/src/components/BaseAutocomplete.stories.js +127 -0
  86. package/src/components/BaseAutocomplete.vue +376 -0
  87. package/src/components/BaseAutocompleteFetch.stories.js +121 -0
  88. package/src/components/BaseAutocompleteFetch.vue +185 -0
  89. package/src/components/BaseAvatar.stories.js +39 -0
  90. package/src/components/BaseAvatar.vue +92 -0
  91. package/src/components/BaseBadge.stories.js +61 -0
  92. package/src/components/BaseBadge.vue +70 -0
  93. package/src/components/BaseBelongsTo.stories.js +130 -0
  94. package/src/components/BaseBelongsTo.vue +122 -0
  95. package/src/components/BaseBoolean.stories.js +35 -0
  96. package/src/components/BaseBoolean.vue +29 -0
  97. package/src/components/BaseBreadcrumbs.stories.js +45 -0
  98. package/src/components/BaseBreadcrumbs.vue +78 -0
  99. package/src/components/BaseButton.stories.js +80 -0
  100. package/src/components/BaseButton.vue +39 -0
  101. package/src/components/BaseCard.stories.js +61 -0
  102. package/src/components/BaseCard.vue +49 -0
  103. package/src/components/BaseCardRow.vue +34 -0
  104. package/src/components/BaseClipboard.stories.js +31 -0
  105. package/src/components/BaseClipboard.vue +96 -0
  106. package/src/components/BaseContainer.stories.js +34 -0
  107. package/src/components/BaseContainer.vue +50 -0
  108. package/src/components/BaseCounter.stories.js +32 -0
  109. package/src/components/BaseCounter.vue +72 -0
  110. package/src/components/BaseDataIterator.stories.js +90 -0
  111. package/src/components/BaseDataIterator.vue +658 -0
  112. package/src/components/BaseDataTable.stories.js +95 -0
  113. package/src/components/BaseDataTable.vue +489 -0
  114. package/src/components/BaseDataTableToggleColumns.vue +69 -0
  115. package/src/components/BaseDatePicker.stories.js +53 -0
  116. package/src/components/BaseDatePicker.vue +166 -0
  117. package/src/components/BaseDateSelect.vue +192 -0
  118. package/src/components/BaseDescriptionList.vue +11 -0
  119. package/src/components/BaseDescriptionListItem.vue +12 -0
  120. package/src/components/BaseDialog.vue +104 -0
  121. package/src/components/BaseFilePicker.vue +101 -0
  122. package/src/components/BaseFileUploader.vue +166 -0
  123. package/src/components/BaseInput.vue +82 -0
  124. package/src/components/BaseInputLabel.vue +26 -0
  125. package/src/components/BaseLoadingCover.vue +84 -0
  126. package/src/components/BaseLoadingPage.vue +19 -0
  127. package/src/components/BaseMediaLibrary.vue +281 -0
  128. package/src/components/BaseMediaLibraryItem.vue +92 -0
  129. package/src/components/BaseMenu.vue +114 -0
  130. package/src/components/BaseMenuItem.vue +93 -0
  131. package/src/components/BaseModalCenter.vue +107 -0
  132. package/src/components/BaseModalSide.vue +112 -0
  133. package/src/components/BaseNavbar.vue +72 -0
  134. package/src/components/BaseNavbarItem.vue +72 -0
  135. package/src/components/BaseNavbarItemContent.vue +57 -0
  136. package/src/components/BasePagination.vue +82 -0
  137. package/src/components/BasePaginationSimple.vue +60 -0
  138. package/src/components/BasePanel.vue +39 -0
  139. package/src/components/BasePassword.vue +73 -0
  140. package/src/components/BaseProcessRing.vue +56 -0
  141. package/src/components/BaseReadMore.vue +72 -0
  142. package/src/components/BaseSelect.vue +59 -0
  143. package/src/components/BaseSideNavigation.vue +7 -0
  144. package/src/components/BaseSideNavigationItem.vue +42 -0
  145. package/src/components/BaseSkeleton.vue +24 -0
  146. package/src/components/BaseSpinner.vue +47 -0
  147. package/src/components/BaseSwitch.vue +87 -0
  148. package/src/components/BaseSystemAlert.vue +86 -0
  149. package/src/components/BaseTabItem.vue +30 -0
  150. package/src/components/BaseTable.vue +781 -0
  151. package/src/components/BaseTableColumn.vue +109 -0
  152. package/src/components/BaseTabs.vue +12 -0
  153. package/src/components/BaseTagAutocomplete.vue +385 -0
  154. package/src/components/BaseTagAutocompleteFetch.vue +154 -0
  155. package/src/components/BaseTextarea.vue +73 -0
  156. package/src/components/BaseTextareaAutoresize.vue +117 -0
  157. package/src/components/BaseTitle.vue +80 -0
  158. package/src/components/BaseWordCount.vue +36 -0
  159. package/src/components/SlotComponent.ts +37 -0
  160. package/src/components/index.ts +5 -0
  161. package/src/composables/breakpoints.ts +6 -0
  162. package/src/composables/modal.ts +77 -0
  163. package/src/constants/MyConstants.ts +1 -0
  164. package/src/constants/index.ts +5 -0
  165. package/src/env.d.ts +15 -0
  166. package/src/index.ts +70 -0
  167. package/src/lang/en.json +56 -0
  168. package/src/lang/fr.json +56 -0
  169. package/src/types/Media.ts +9 -0
  170. package/src/types/UploadedFile.ts +10 -0
  171. package/src/types/User.ts +7 -0
  172. package/src/types/types.ts +112 -0
  173. package/src/utils/fileSizeFormat.ts +15 -0
  174. package/src/utils/index.ts +5 -0
  175. package/src/utils/scrollPreventer.ts +21 -0
  176. package/src/utils/toHumanList.ts +20 -0
@@ -0,0 +1,57 @@
1
+ <template>
2
+ <div :class="classes">
3
+ <div class="flex grow items-center">
4
+ <Icon v-if="icon" :icon="icon" :class="iconClasses" />
5
+ {{ label }}
6
+ </div>
7
+ <div v-if="count" class="relative -top-px ml-[5px]">
8
+ <BaseCounter :count="count" :max-digit="2" :color="'primary'" />
9
+ </div>
10
+ </div>
11
+ </template>
12
+
13
+ <script lang="ts" setup>
14
+ const buttonClasses =
15
+ 'px-3 py-2 text-left rounded-md md:text-sm flex text-base font-normal w-full';
16
+ const buttonInactiveClasses =
17
+ 'hover:bg-slate-700 hover:text-white text-slate-300';
18
+ const buttonActiveClasses = 'bg-slate-900 text-white';
19
+
20
+ const props = defineProps({
21
+ label: {
22
+ default: undefined,
23
+ type: String,
24
+ },
25
+ icon: {
26
+ default: undefined,
27
+ type: String,
28
+ },
29
+ active: {
30
+ default: false,
31
+ type: Boolean,
32
+ },
33
+ count: {
34
+ default: undefined,
35
+ type: Number,
36
+ },
37
+ });
38
+
39
+ const classes = computed(() => {
40
+ return [
41
+ buttonClasses,
42
+ props.active ? buttonActiveClasses : buttonInactiveClasses,
43
+ ];
44
+ });
45
+
46
+ const iconClasses = computed((): string => {
47
+ let baseClasses = ' w-5 h-5 shrink-0 mr-2 leading-none inline-block';
48
+
49
+ if (props.active) {
50
+ baseClasses += ' text-white';
51
+ } else {
52
+ baseClasses += ' text-slate-300';
53
+ }
54
+
55
+ return baseClasses;
56
+ });
57
+ </script>
@@ -0,0 +1,82 @@
1
+ <template>
2
+ <nav
3
+ v-if="lastPage > 1 || lastPage < modelValue"
4
+ class="flex items-center justify-between border-t border-slate-200 px-4 sm:px-0"
5
+ >
6
+ <div class="-mt-px flex w-0 flex-1">
7
+ <button
8
+ type="button"
9
+ :disabled="modelValue == 1"
10
+ class="inline-flex items-center border-t-2 border-transparent px-1 py-4 text-sm font-medium text-slate-500 hover:enabled:border-slate-300 hover:enabled:text-slate-700 disabled:cursor-not-allowed disabled:opacity-60"
11
+ @click="previous()"
12
+ >
13
+ <Icon
14
+ class="mr-3 h-5 w-5 text-slate-400"
15
+ icon="heroicons-solid:arrow-narrow-left"
16
+ />
17
+ {{ $t('sui.previous') }}
18
+ </button>
19
+ </div>
20
+ <div class="hidden md:-mt-px md:flex">
21
+ <button
22
+ v-for="i in lastPage"
23
+ :key="i"
24
+ type="button"
25
+ class="inline-flex items-center border-t-2 px-4 py-4 text-sm font-medium hover:border-slate-300 hover:text-slate-700"
26
+ :class="
27
+ i == modelValue
28
+ ? 'border-primary-500 text-primary-600'
29
+ : 'border-transparent text-slate-500 hover:border-slate-300 hover:text-slate-700'
30
+ "
31
+ @click="$emit('model-value:update', i)"
32
+ >
33
+ {{ i }}
34
+ </button>
35
+ </div>
36
+ <div class="-mt-px flex w-0 flex-1 justify-end">
37
+ <button
38
+ :disabled="modelValue >= lastPage"
39
+ class="inline-flex items-center border-t-2 border-transparent px-1 py-4 text-sm font-medium text-slate-500 hover:enabled:border-slate-300 hover:enabled:text-slate-700 disabled:cursor-not-allowed disabled:opacity-60"
40
+ @click="next()"
41
+ >
42
+ {{ $t('sui.next') }}
43
+ <Icon
44
+ class="ml-3 h-5 w-5 text-slate-400"
45
+ icon="heroicons-solid:arrow-narrow-right"
46
+ />
47
+ </button>
48
+ </div>
49
+ </nav>
50
+ </template>
51
+
52
+ <script lang="ts">
53
+ import { defineComponent } from 'vue';
54
+
55
+ export default defineComponent({
56
+ props: {
57
+ modelValue: {
58
+ required: true,
59
+ type: Number,
60
+ },
61
+ lastPage: {
62
+ required: true,
63
+ type: Number,
64
+ },
65
+ },
66
+ emits: ['model-value:update'],
67
+ methods: {
68
+ next() {
69
+ if (this.modelValue >= this.lastPage) {
70
+ return;
71
+ }
72
+ this.$emit('model-value:update', this.modelValue + 1);
73
+ },
74
+ previous() {
75
+ if (this.modelValue == 1) {
76
+ return;
77
+ }
78
+ this.$emit('model-value:update', this.modelValue - 1);
79
+ },
80
+ },
81
+ });
82
+ </script>
@@ -0,0 +1,60 @@
1
+ <template>
2
+ <nav
3
+ v-if="lastPage > 1 || lastPage < modelValue"
4
+ class="flex items-center space-x-1 sm:px-0"
5
+ >
6
+ <button
7
+ type="button"
8
+ :disabled="modelValue == 1"
9
+ class="flex h-8 w-8 items-center justify-center rounded-md border border-slate-300 text-sm font-medium text-slate-400 outline-none hover:enabled:border-slate-400 hover:enabled:text-slate-700 disabled:cursor-not-allowed disabled:border-transparent disabled:opacity-60"
10
+ @click="previous()"
11
+ >
12
+ <Icon
13
+ class="h-5 w-5 text-slate-400"
14
+ icon="heroicons-solid:chevron-left"
15
+ />
16
+ </button>
17
+ <button
18
+ :disabled="modelValue >= lastPage"
19
+ class="flex h-8 w-8 items-center justify-center rounded-md border border-slate-300 text-sm font-medium text-slate-400 outline-none hover:enabled:border-slate-400 hover:enabled:text-slate-700 disabled:cursor-not-allowed disabled:border-transparent disabled:opacity-60"
20
+ @click="next()"
21
+ >
22
+ <Icon
23
+ class="h-5 w-5 text-slate-400"
24
+ icon="heroicons-solid:chevron-right"
25
+ />
26
+ </button>
27
+ </nav>
28
+ </template>
29
+
30
+ <script lang="ts">
31
+ import { defineComponent } from 'vue';
32
+
33
+ export default defineComponent({
34
+ props: {
35
+ modelValue: {
36
+ required: true,
37
+ type: Number,
38
+ },
39
+ lastPage: {
40
+ required: true,
41
+ type: Number,
42
+ },
43
+ },
44
+ emits: ['model-value:update'],
45
+ methods: {
46
+ next() {
47
+ if (this.modelValue >= this.lastPage) {
48
+ return;
49
+ }
50
+ this.$emit('model-value:update', this.modelValue + 1);
51
+ },
52
+ previous() {
53
+ if (this.modelValue == 1) {
54
+ return;
55
+ }
56
+ this.$emit('model-value:update', this.modelValue - 1);
57
+ },
58
+ },
59
+ });
60
+ </script>
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <div
3
+ class="pb-8 md:grid md:grid-cols-3 md:gap-8"
4
+ :class="[bordered ? 'mb-8 border-b border-slate-300' : '']"
5
+ >
6
+ <div class="px-4 md:col-span-1 md:px-0">
7
+ <h3 class="text-lg font-medium leading-tight text-slate-900">
8
+ {{ title }}
9
+ </h3>
10
+ <p v-if="description" class="mt-2 text-sm leading-tight text-slate-500">
11
+ {{ description }}
12
+ </p>
13
+ </div>
14
+ <div class="mt-5 md:col-span-2 md:mt-0">
15
+ <slot />
16
+ </div>
17
+ </div>
18
+ </template>
19
+
20
+ <script lang="ts">
21
+ import { defineComponent } from 'vue';
22
+
23
+ export default defineComponent({
24
+ props: {
25
+ title: {
26
+ required: true,
27
+ type: String,
28
+ },
29
+ description: {
30
+ default: null,
31
+ type: String,
32
+ },
33
+ bordered: {
34
+ default: false,
35
+ type: Boolean,
36
+ },
37
+ },
38
+ });
39
+ </script>
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <div class="flex border bg-white">
3
+ <input
4
+ ref="input"
5
+ :value="modelValue"
6
+ :type="showPassword ? 'text' : 'password'"
7
+ :name="name"
8
+ :disabled="disabled"
9
+ :placeholder="placeholder"
10
+ :required="required"
11
+ class="grow rounded-l border-none focus:ring-2 focus:ring-primary-500"
12
+ :class="inputClass"
13
+ @input="onInput"
14
+ />
15
+ <div class="flex shrink-0 pl-3">
16
+ <button
17
+ tabindex="-1"
18
+ type="button"
19
+ class="pr-3 text-slate-500"
20
+ @click="showPassword = !showPassword"
21
+ >
22
+ <Icon v-if="!showPassword" icon="heroicons:eye-off" class="h-5 w-5" />
23
+ <Icon v-else icon="heroicons:eye" class="h-5 w-5" />
24
+ </button>
25
+ </div>
26
+ </div>
27
+ </template>
28
+
29
+ <script lang="ts">
30
+ import { trim } from 'lodash';
31
+ import { defineComponent, PropType } from 'vue';
32
+
33
+ export default defineComponent({
34
+ props: {
35
+ modelValue: {
36
+ default: '',
37
+ type: [String, null] as PropType<string | null>,
38
+ },
39
+ disabled: {
40
+ default: false,
41
+ type: Boolean,
42
+ },
43
+ name: {
44
+ default: undefined,
45
+ type: String,
46
+ },
47
+ placeholder: {
48
+ default: undefined,
49
+ type: String,
50
+ },
51
+ required: {
52
+ default: undefined,
53
+ type: Boolean,
54
+ },
55
+ inputClass: {
56
+ default: '',
57
+ type: String,
58
+ },
59
+ },
60
+ emits: ['update:modelValue'],
61
+ data() {
62
+ return {
63
+ showPassword: false,
64
+ };
65
+ },
66
+ methods: {
67
+ onInput(event: any) {
68
+ const value = event.target.value + '';
69
+ this.$emit('update:modelValue', trim(value));
70
+ },
71
+ },
72
+ });
73
+ </script>
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <svg :height="radius * 2" :width="radius * 2">
3
+ <circle
4
+ stroke="currentColor"
5
+ :stroke-dasharray="`${circumference} ${circumference}`"
6
+ :style="{ strokeDashoffset: strokeDashoffset }"
7
+ :stroke-width="stroke"
8
+ fill="transparent"
9
+ :r="normalizedRadius"
10
+ :cx="radius"
11
+ :cy="radius"
12
+ />
13
+ </svg>
14
+ </template>
15
+
16
+ <script lang="ts">
17
+ import { defineComponent } from 'vue';
18
+
19
+ export default defineComponent({
20
+ props: {
21
+ radius: {
22
+ default: 10,
23
+ type: Number,
24
+ },
25
+ stroke: {
26
+ default: 1,
27
+ type: Number,
28
+ },
29
+ progress: {
30
+ default: 0.5,
31
+ type: Number,
32
+ },
33
+ },
34
+ computed: {
35
+ normalizedRadius(): number {
36
+ return this.radius - this.stroke * 2;
37
+ },
38
+ circumference(): number {
39
+ return this.normalizedRadius * 2 * Math.PI;
40
+ },
41
+ strokeDashoffset(): number {
42
+ const offset =
43
+ this.circumference - Math.min(1, this.progress) * this.circumference;
44
+ return offset;
45
+ },
46
+ },
47
+ });
48
+ </script>
49
+
50
+ <style scoped>
51
+ circle {
52
+ transition: stroke-dashoffset 0.35s;
53
+ transform: rotate(-90deg);
54
+ transform-origin: 50% 50%;
55
+ }
56
+ </style>
@@ -0,0 +1,72 @@
1
+ <template>
2
+ <div>
3
+ <p
4
+ ref="content"
5
+ class="overflow-hidden whitespace-pre-line"
6
+ :style="showMore ? undefined : lineClampStyle"
7
+ >
8
+ <slot />
9
+ </p>
10
+ <button
11
+ v-if="!showMore && isClamped"
12
+ type="button"
13
+ class="mt-1 inline appearance-none border-b border-dashed border-slate-400 bg-transparent px-0.5 py-0 text-slate-900 hover:text-slate-600"
14
+ @click="showMore = true"
15
+ >
16
+ <span class="text-base font-semibold">{{ $t('sui.read_more') }}</span>
17
+ </button>
18
+ </div>
19
+ </template>
20
+
21
+ <script lang="ts" setup>
22
+ import { useMutationObserver } from '@vueuse/core';
23
+ import { Ref, StyleValue } from 'vue';
24
+
25
+ const content = ref(null) as Ref<null | HTMLParagraphElement>;
26
+
27
+ const props = defineProps({
28
+ maxLines: {
29
+ default: 3,
30
+ type: Number,
31
+ },
32
+ });
33
+
34
+ const showMore = ref(false);
35
+ const isClamped = ref(false);
36
+
37
+ const lineClampStyle = computed((): StyleValue | undefined => {
38
+ return {
39
+ display: '-webkit-box',
40
+ '-webkit-line-clamp': props.maxLines,
41
+ '-webkit-box-orient': 'vertical',
42
+ };
43
+ });
44
+
45
+ onMounted(() => {
46
+ init();
47
+
48
+ useMutationObserver(
49
+ content.value,
50
+ () => {
51
+ showMore.value = false;
52
+ nextTick(() => {
53
+ init();
54
+ });
55
+ },
56
+ {
57
+ childList: true,
58
+ subtree: true,
59
+ }
60
+ );
61
+ });
62
+
63
+ function init() {
64
+ const el = content.value;
65
+
66
+ if (!el) {
67
+ return;
68
+ }
69
+
70
+ isClamped.value = el.scrollHeight > el.clientHeight;
71
+ }
72
+ </script>
@@ -0,0 +1,59 @@
1
+ <template>
2
+ <select
3
+ :value="modelValue"
4
+ :name="name"
5
+ :disabled="disabled"
6
+ :required="required"
7
+ class="rounded"
8
+ @change="onChange($event)"
9
+ >
10
+ <option v-if="required" selected disabled hidden value="">
11
+ {{ placeholder ? placeholder : $t('sui.select_an_option') }}
12
+ </option>
13
+ <slot />
14
+ </select>
15
+ </template>
16
+
17
+ <script lang="ts">
18
+ import { defineComponent, PropType } from 'vue';
19
+ import { get } from 'lodash';
20
+
21
+ export default defineComponent({
22
+ props: {
23
+ modelValue: {
24
+ default: null,
25
+ type: [String, Number, null] as PropType<string | number | null>,
26
+ },
27
+ name: {
28
+ default: undefined,
29
+ type: String,
30
+ },
31
+ placeholder: {
32
+ default: '',
33
+ type: String,
34
+ },
35
+ disabled: {
36
+ default: false,
37
+ type: Boolean,
38
+ },
39
+ required: {
40
+ default: false,
41
+ type: Boolean,
42
+ },
43
+ },
44
+ emits: ['update:modelValue'],
45
+ methods: {
46
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
47
+ onChange(event: Event): any {
48
+ if (event === null) {
49
+ this.$emit('update:modelValue', null);
50
+ }
51
+ const value = get(event, 'target.value', null);
52
+ if (value === null) {
53
+ this.$emit('update:modelValue', null);
54
+ }
55
+ this.$emit('update:modelValue', value);
56
+ },
57
+ },
58
+ });
59
+ </script>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <nav class="space-y-1" aria-label="Sidebar">
3
+ <slot />
4
+ </nav>
5
+ </template>
6
+
7
+ <script setup lang="ts"></script>
@@ -0,0 +1,42 @@
1
+ <template>
2
+ <router-link v-slot="{ href, navigate, isActive }" :to="to" custom>
3
+ <a
4
+ :href="disabled ? undefined : href"
5
+ :disabled="disabled"
6
+ class="flex items-center rounded-md px-3 py-2 text-sm font-medium"
7
+ :class="[
8
+ isActive
9
+ ? 'bg-slate-300 bg-opacity-60 text-black'
10
+ : 'text-slate-600 hover:bg-slate-200 hover:bg-opacity-70 hover:text-slate-900',
11
+ disabled ? 'cursor-not-allowed opacity-60' : '',
12
+ ]"
13
+ @click.prevent="onClick(navigate)"
14
+ >
15
+ <slot />
16
+ </a>
17
+ </router-link>
18
+ </template>
19
+
20
+ <script lang="ts" setup>
21
+ import { PropType } from 'vue';
22
+ import { RouteLocationRaw } from 'vue-router';
23
+
24
+ const props = defineProps({
25
+ to: {
26
+ required: true,
27
+ type: [Object, String] as PropType<RouteLocationRaw>,
28
+ },
29
+ disabled: {
30
+ default: false,
31
+ type: Boolean,
32
+ },
33
+ });
34
+
35
+ const onClick = (navigate: () => void) => {
36
+ if (props.disabled) {
37
+ return;
38
+ }
39
+
40
+ navigate();
41
+ };
42
+ </script>
@@ -0,0 +1,24 @@
1
+ <template>
2
+ <div class="relative isolate overflow-hidden rounded" :class="[background]">
3
+ <div
4
+ class="absolute inset-0 -translate-x-full animate-[shimmer_2s_infinite] border-t border-white/80 bg-gradient-to-r from-transparent via-white/80 to-transparent"
5
+ :style="{
6
+ animationDelay: delay,
7
+ }"
8
+ ></div>
9
+ <slot></slot>
10
+ </div>
11
+ </template>
12
+
13
+ <script lang="ts" setup>
14
+ defineProps({
15
+ delay: {
16
+ default: '0s',
17
+ type: String,
18
+ },
19
+ background: {
20
+ default: 'bg-slate-200',
21
+ type: String,
22
+ },
23
+ });
24
+ </script>
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <svg
3
+ class="spinner h-20 w-20"
4
+ viewBox="0 0 66 66"
5
+ xmlns="http://www.w3.org/2000/svg"
6
+ >
7
+ <circle
8
+ class="path"
9
+ fill="transparent"
10
+ stroke-width="2"
11
+ cx="33"
12
+ cy="33"
13
+ r="30"
14
+ stroke="url(#gradient)"
15
+ />
16
+ <linearGradient id="gradient">
17
+ <stop offset="50%" stop-color="#2563eb" stop-opacity="1" />
18
+ <stop offset="65%" stop-color="#2563eb" stop-opacity=".5" />
19
+ <stop offset="100%" stop-color="#2563eb" stop-opacity="0" />
20
+ </linearGradient>
21
+ </svg>
22
+ </template>
23
+
24
+ <script lang="ts">
25
+ import { defineComponent } from 'vue';
26
+
27
+ export default defineComponent({});
28
+ </script>
29
+
30
+ <style scoped>
31
+ .spinner {
32
+ animation: rotate 1s linear infinite;
33
+ -webkit-animation: rotate 1s linear infinite;
34
+ -moz-animation: rotate 1s linear infinite;
35
+ }
36
+
37
+ @keyframes rotate {
38
+ to {
39
+ transform: rotate(360deg);
40
+ }
41
+ }
42
+
43
+ .path {
44
+ stroke-dasharray: 170;
45
+ stroke-dashoffset: 20;
46
+ }
47
+ </style>