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.
- package/README.md +188 -0
- package/dist/types/src/components/BaseAlert.vue.d.ts +51 -0
- package/dist/types/src/components/BaseAutocomplete.vue.d.ts +268 -0
- package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +273 -0
- package/dist/types/src/components/BaseAvatar.vue.d.ts +126 -0
- package/dist/types/src/components/BaseBadge.vue.d.ts +94 -0
- package/dist/types/src/components/BaseBelongsTo.vue.d.ts +268 -0
- package/dist/types/src/components/BaseBoolean.vue.d.ts +64 -0
- package/dist/types/src/components/BaseBreadcrumbs.vue.d.ts +66 -0
- package/dist/types/src/components/BaseButton.vue.d.ts +23 -0
- package/dist/types/src/components/BaseCard.vue.d.ts +74 -0
- package/dist/types/src/components/BaseCardRow.vue.d.ts +16 -0
- package/dist/types/src/components/BaseClipboard.vue.d.ts +74 -0
- package/dist/types/src/components/BaseContainer.vue.d.ts +34 -0
- package/dist/types/src/components/BaseCounter.vue.d.ts +125 -0
- package/dist/types/src/components/BaseDataIterator.vue.d.ts +345 -0
- package/dist/types/src/components/BaseDataTable.vue.d.ts +657 -0
- package/dist/types/src/components/BaseDataTableToggleColumns.vue.d.ts +1281 -0
- package/dist/types/src/components/BaseDatePicker.vue.d.ts +190 -0
- package/dist/types/src/components/BaseDateSelect.vue.d.ts +171 -0
- package/dist/types/src/components/BaseDescriptionList.vue.d.ts +48 -0
- package/dist/types/src/components/BaseDescriptionListItem.vue.d.ts +49 -0
- package/dist/types/src/components/BaseDialog.vue.d.ts +160 -0
- package/dist/types/src/components/BaseFilePicker.vue.d.ts +44 -0
- package/dist/types/src/components/BaseFileUploader.vue.d.ts +220 -0
- package/dist/types/src/components/BaseInput.vue.d.ts +209 -0
- package/dist/types/src/components/BaseInputLabel.vue.d.ts +31 -0
- package/dist/types/src/components/BaseLoadingCover.vue.d.ts +166 -0
- package/dist/types/src/components/BaseLoadingPage.vue.d.ts +2 -0
- package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +269 -0
- package/dist/types/src/components/BaseMediaLibraryItem.vue.d.ts +75 -0
- package/dist/types/src/components/BaseMenu.vue.d.ts +117 -0
- package/dist/types/src/components/BaseMenuItem.vue.d.ts +147 -0
- package/dist/types/src/components/BaseModalCenter.vue.d.ts +141 -0
- package/dist/types/src/components/BaseModalSide.vue.d.ts +141 -0
- package/dist/types/src/components/BaseNavbar.vue.d.ts +79 -0
- package/dist/types/src/components/BaseNavbarItem.vue.d.ts +80 -0
- package/dist/types/src/components/BaseNavbarItemContent.vue.d.ts +127 -0
- package/dist/types/src/components/BasePagination.vue.d.ts +25 -0
- package/dist/types/src/components/BasePaginationSimple.vue.d.ts +25 -0
- package/dist/types/src/components/BasePanel.vue.d.ts +31 -0
- package/dist/types/src/components/BasePassword.vue.d.ts +66 -0
- package/dist/types/src/components/BaseProcessRing.vue.d.ts +36 -0
- package/dist/types/src/components/BaseReadMore.vue.d.ts +74 -0
- package/dist/types/src/components/BaseSelect.vue.d.ts +55 -0
- package/dist/types/src/components/BaseSideNavigation.vue.d.ts +48 -0
- package/dist/types/src/components/BaseSideNavigationItem.vue.d.ts +92 -0
- package/dist/types/src/components/BaseSkeleton.vue.d.ts +93 -0
- package/dist/types/src/components/BaseSpinner.vue.d.ts +2 -0
- package/dist/types/src/components/BaseSwitch.vue.d.ts +39 -0
- package/dist/types/src/components/BaseSystemAlert.vue.d.ts +141 -0
- package/dist/types/src/components/BaseTabItem.vue.d.ts +70 -0
- package/dist/types/src/components/BaseTable.vue.d.ts +467 -0
- package/dist/types/src/components/BaseTableColumn.vue.d.ts +164 -0
- package/dist/types/src/components/BaseTabs.vue.d.ts +48 -0
- package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +274 -0
- package/dist/types/src/components/BaseTagAutocompleteFetch.vue.d.ts +251 -0
- package/dist/types/src/components/BaseTextarea.vue.d.ts +228 -0
- package/dist/types/src/components/BaseTextareaAutoresize.vue.d.ts +44 -0
- package/dist/types/src/components/BaseTitle.vue.d.ts +45 -0
- package/dist/types/src/components/BaseWordCount.vue.d.ts +31 -0
- package/dist/types/src/components/SlotComponent.d.ts +43 -0
- package/dist/types/src/components/index.d.ts +2 -0
- package/dist/types/src/composables/breakpoints.d.ts +12 -0
- package/dist/types/src/composables/modal.d.ts +6 -0
- package/dist/types/src/constants/MyConstants.d.ts +1 -0
- package/dist/types/src/constants/index.d.ts +2 -0
- package/dist/types/src/index.d.ts +253 -0
- package/dist/types/src/types/Media.d.ts +8 -0
- package/dist/types/src/types/UploadedFile.d.ts +9 -0
- package/dist/types/src/types/User.d.ts +6 -0
- package/dist/types/src/types/types.d.ts +88 -0
- package/dist/types/src/utils/fileSizeFormat.d.ts +1 -0
- package/dist/types/src/utils/index.d.ts +4 -0
- package/dist/types/src/utils/scrollPreventer.d.ts +4 -0
- package/dist/types/src/utils/toHumanList.d.ts +1 -0
- package/package.json +99 -0
- package/src/assets/button.css +80 -0
- package/src/assets/form.css +15 -0
- package/src/assets/main.css +3 -0
- package/src/assets/pikaday.css +134 -0
- package/src/assets/tailwind.css +5 -0
- package/src/components/BaseAlert.stories.js +52 -0
- package/src/components/BaseAlert.vue +152 -0
- package/src/components/BaseAutocomplete.stories.js +127 -0
- package/src/components/BaseAutocomplete.vue +376 -0
- package/src/components/BaseAutocompleteFetch.stories.js +121 -0
- package/src/components/BaseAutocompleteFetch.vue +185 -0
- package/src/components/BaseAvatar.stories.js +39 -0
- package/src/components/BaseAvatar.vue +92 -0
- package/src/components/BaseBadge.stories.js +61 -0
- package/src/components/BaseBadge.vue +70 -0
- package/src/components/BaseBelongsTo.stories.js +130 -0
- package/src/components/BaseBelongsTo.vue +122 -0
- package/src/components/BaseBoolean.stories.js +35 -0
- package/src/components/BaseBoolean.vue +29 -0
- package/src/components/BaseBreadcrumbs.stories.js +45 -0
- package/src/components/BaseBreadcrumbs.vue +78 -0
- package/src/components/BaseButton.stories.js +80 -0
- package/src/components/BaseButton.vue +39 -0
- package/src/components/BaseCard.stories.js +61 -0
- package/src/components/BaseCard.vue +49 -0
- package/src/components/BaseCardRow.vue +34 -0
- package/src/components/BaseClipboard.stories.js +31 -0
- package/src/components/BaseClipboard.vue +96 -0
- package/src/components/BaseContainer.stories.js +34 -0
- package/src/components/BaseContainer.vue +50 -0
- package/src/components/BaseCounter.stories.js +32 -0
- package/src/components/BaseCounter.vue +72 -0
- package/src/components/BaseDataIterator.stories.js +90 -0
- package/src/components/BaseDataIterator.vue +658 -0
- package/src/components/BaseDataTable.stories.js +95 -0
- package/src/components/BaseDataTable.vue +489 -0
- package/src/components/BaseDataTableToggleColumns.vue +69 -0
- package/src/components/BaseDatePicker.stories.js +53 -0
- package/src/components/BaseDatePicker.vue +166 -0
- package/src/components/BaseDateSelect.vue +192 -0
- package/src/components/BaseDescriptionList.vue +11 -0
- package/src/components/BaseDescriptionListItem.vue +12 -0
- package/src/components/BaseDialog.vue +104 -0
- package/src/components/BaseFilePicker.vue +101 -0
- package/src/components/BaseFileUploader.vue +166 -0
- package/src/components/BaseInput.vue +82 -0
- package/src/components/BaseInputLabel.vue +26 -0
- package/src/components/BaseLoadingCover.vue +84 -0
- package/src/components/BaseLoadingPage.vue +19 -0
- package/src/components/BaseMediaLibrary.vue +281 -0
- package/src/components/BaseMediaLibraryItem.vue +92 -0
- package/src/components/BaseMenu.vue +114 -0
- package/src/components/BaseMenuItem.vue +93 -0
- package/src/components/BaseModalCenter.vue +107 -0
- package/src/components/BaseModalSide.vue +112 -0
- package/src/components/BaseNavbar.vue +72 -0
- package/src/components/BaseNavbarItem.vue +72 -0
- package/src/components/BaseNavbarItemContent.vue +57 -0
- package/src/components/BasePagination.vue +82 -0
- package/src/components/BasePaginationSimple.vue +60 -0
- package/src/components/BasePanel.vue +39 -0
- package/src/components/BasePassword.vue +73 -0
- package/src/components/BaseProcessRing.vue +56 -0
- package/src/components/BaseReadMore.vue +72 -0
- package/src/components/BaseSelect.vue +59 -0
- package/src/components/BaseSideNavigation.vue +7 -0
- package/src/components/BaseSideNavigationItem.vue +42 -0
- package/src/components/BaseSkeleton.vue +24 -0
- package/src/components/BaseSpinner.vue +47 -0
- package/src/components/BaseSwitch.vue +87 -0
- package/src/components/BaseSystemAlert.vue +86 -0
- package/src/components/BaseTabItem.vue +30 -0
- package/src/components/BaseTable.vue +781 -0
- package/src/components/BaseTableColumn.vue +109 -0
- package/src/components/BaseTabs.vue +12 -0
- package/src/components/BaseTagAutocomplete.vue +385 -0
- package/src/components/BaseTagAutocompleteFetch.vue +154 -0
- package/src/components/BaseTextarea.vue +73 -0
- package/src/components/BaseTextareaAutoresize.vue +117 -0
- package/src/components/BaseTitle.vue +80 -0
- package/src/components/BaseWordCount.vue +36 -0
- package/src/components/SlotComponent.ts +37 -0
- package/src/components/index.ts +5 -0
- package/src/composables/breakpoints.ts +6 -0
- package/src/composables/modal.ts +77 -0
- package/src/constants/MyConstants.ts +1 -0
- package/src/constants/index.ts +5 -0
- package/src/env.d.ts +15 -0
- package/src/index.ts +70 -0
- package/src/lang/en.json +56 -0
- package/src/lang/fr.json +56 -0
- package/src/types/Media.ts +9 -0
- package/src/types/UploadedFile.ts +10 -0
- package/src/types/User.ts +7 -0
- package/src/types/types.ts +112 -0
- package/src/utils/fileSizeFormat.ts +15 -0
- package/src/utils/index.ts +5 -0
- package/src/utils/scrollPreventer.ts +21 -0
- 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,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>
|