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,73 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<textarea
|
|
3
|
+
:value="modelValue"
|
|
4
|
+
:type="type"
|
|
5
|
+
:name="name"
|
|
6
|
+
:placeholder="placeholder"
|
|
7
|
+
:disabled="disabled"
|
|
8
|
+
:required="required"
|
|
9
|
+
:rows="rows"
|
|
10
|
+
class="mb-0 block rounded"
|
|
11
|
+
@input="$emit('update:modelValue', transformInputValue($event))"
|
|
12
|
+
/>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script lang="ts" setup>
|
|
16
|
+
import { get, isString, trim } from 'lodash';
|
|
17
|
+
import { PropType } from 'vue';
|
|
18
|
+
|
|
19
|
+
defineProps({
|
|
20
|
+
modelValue: {
|
|
21
|
+
required: true,
|
|
22
|
+
type: [String, undefined] as PropType<string | undefined>,
|
|
23
|
+
},
|
|
24
|
+
type: {
|
|
25
|
+
type: String,
|
|
26
|
+
default: 'text',
|
|
27
|
+
},
|
|
28
|
+
autocomplete: {
|
|
29
|
+
default: true,
|
|
30
|
+
type: Boolean,
|
|
31
|
+
},
|
|
32
|
+
preventSubmit: {
|
|
33
|
+
default: false,
|
|
34
|
+
type: Boolean,
|
|
35
|
+
},
|
|
36
|
+
name: {
|
|
37
|
+
default: undefined,
|
|
38
|
+
type: String,
|
|
39
|
+
},
|
|
40
|
+
placeholder: {
|
|
41
|
+
default: '',
|
|
42
|
+
type: String,
|
|
43
|
+
},
|
|
44
|
+
disabled: {
|
|
45
|
+
default: false,
|
|
46
|
+
type: Boolean,
|
|
47
|
+
},
|
|
48
|
+
required: {
|
|
49
|
+
default: false,
|
|
50
|
+
type: Boolean,
|
|
51
|
+
},
|
|
52
|
+
rows: {
|
|
53
|
+
default: undefined,
|
|
54
|
+
type: Number,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
defineEmits(['update:modelValue']);
|
|
59
|
+
|
|
60
|
+
function transformInputValue(event: Event | null): string | null {
|
|
61
|
+
if (event === null) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const value = get(event, 'target.value', null);
|
|
66
|
+
|
|
67
|
+
if (isString(value)) {
|
|
68
|
+
return trim(value);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return '';
|
|
72
|
+
}
|
|
73
|
+
</script>
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div ref="wrapper" class="wrapper">
|
|
3
|
+
<textarea
|
|
4
|
+
:value="modelValue"
|
|
5
|
+
:name="name"
|
|
6
|
+
:placeholder="placeholder"
|
|
7
|
+
rows="1"
|
|
8
|
+
class="focus:outline-none focus:ring-0"
|
|
9
|
+
@input="onInput"
|
|
10
|
+
@keyup="onKeyUp"
|
|
11
|
+
@keydown="onKeyDown"
|
|
12
|
+
@focus="onFocus"
|
|
13
|
+
/>
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script lang="ts">
|
|
18
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
19
|
+
import { defineComponent, inject } from 'vue';
|
|
20
|
+
|
|
21
|
+
const keys = {} as { [key: string]: boolean };
|
|
22
|
+
|
|
23
|
+
export default defineComponent({
|
|
24
|
+
props: {
|
|
25
|
+
modelValue: {
|
|
26
|
+
default: '',
|
|
27
|
+
type: String,
|
|
28
|
+
},
|
|
29
|
+
placeholder: {
|
|
30
|
+
default: '',
|
|
31
|
+
type: String,
|
|
32
|
+
},
|
|
33
|
+
name: {
|
|
34
|
+
required: true,
|
|
35
|
+
type: String,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
emits: ['update:modelValue', 'submit', 'focus', 'input'],
|
|
39
|
+
setup() {
|
|
40
|
+
const mobile = inject('mobile') as boolean;
|
|
41
|
+
return {
|
|
42
|
+
mobile,
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
watch: {
|
|
46
|
+
modelValue(value: string) {
|
|
47
|
+
this.updateReplicatedValue(value);
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
methods: {
|
|
51
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
52
|
+
onInput(e: any) {
|
|
53
|
+
const value = e.target.value ?? '';
|
|
54
|
+
this.$emit('update:modelValue', value);
|
|
55
|
+
this.$emit('input', e);
|
|
56
|
+
this.updateReplicatedValue(value);
|
|
57
|
+
},
|
|
58
|
+
updateReplicatedValue(value: string) {
|
|
59
|
+
const wrapper = this.$refs.wrapper as HTMLElement;
|
|
60
|
+
wrapper.dataset.replicatedValue = value;
|
|
61
|
+
},
|
|
62
|
+
onKeyDown(event: any) {
|
|
63
|
+
keys[event.key as number] = true;
|
|
64
|
+
|
|
65
|
+
if (keys['Enter'] && !keys['Shift'] && !this.mobile) {
|
|
66
|
+
this.$emit('submit');
|
|
67
|
+
event.preventDefault();
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
onKeyUp(event: any) {
|
|
71
|
+
delete keys[event.key];
|
|
72
|
+
},
|
|
73
|
+
onFocus(event: any) {
|
|
74
|
+
this.$emit('focus', event);
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<style lang="postcss" scoped>
|
|
81
|
+
.wrapper {
|
|
82
|
+
/* easy way to plop the elements on top of each other and have them both sized based on the tallest one's height */
|
|
83
|
+
display: grid;
|
|
84
|
+
}
|
|
85
|
+
.wrapper::after {
|
|
86
|
+
/* Note the weird space! Needed to prevent jumpy behavior */
|
|
87
|
+
content: attr(data-replicated-value) ' ';
|
|
88
|
+
|
|
89
|
+
/* This is how textarea text behaves */
|
|
90
|
+
white-space: pre-wrap;
|
|
91
|
+
|
|
92
|
+
/* Hidden from view, clicks, and screen readers */
|
|
93
|
+
visibility: hidden;
|
|
94
|
+
}
|
|
95
|
+
.wrapper > textarea {
|
|
96
|
+
/* You could leave this, but after a user resizes, then it ruins the auto sizing */
|
|
97
|
+
resize: none;
|
|
98
|
+
|
|
99
|
+
@apply focus:outline-none;
|
|
100
|
+
@apply focus-visible:outline-none;
|
|
101
|
+
}
|
|
102
|
+
.wrapper > textarea,
|
|
103
|
+
.wrapper::after {
|
|
104
|
+
/* Identical styling required!! */
|
|
105
|
+
padding: 0.5rem;
|
|
106
|
+
font: inherit;
|
|
107
|
+
|
|
108
|
+
@apply text-base;
|
|
109
|
+
@apply max-h-28;
|
|
110
|
+
@apply border-transparent;
|
|
111
|
+
@apply bg-slate-100;
|
|
112
|
+
@apply rounded-lg;
|
|
113
|
+
|
|
114
|
+
/* Place on top of each other */
|
|
115
|
+
grid-area: 1 / 1 / 2 / 2;
|
|
116
|
+
}
|
|
117
|
+
</style>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="flex w-full space-x-4">
|
|
3
|
+
<div v-if="back">
|
|
4
|
+
<router-link
|
|
5
|
+
:to="back"
|
|
6
|
+
class="block rounded-full border border-slate-200 bg-white p-2 shadow duration-150 hover:bg-slate-100"
|
|
7
|
+
>
|
|
8
|
+
<Icon class="h-6 w-6" icon="mdi:chevron-left" />
|
|
9
|
+
</router-link>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="grow sm:flex sm:items-start">
|
|
12
|
+
<div class="sm:flex-auto">
|
|
13
|
+
<component :is="`h${level}`" :class="titleClass">
|
|
14
|
+
{{ title }}
|
|
15
|
+
</component>
|
|
16
|
+
<p v-if="subtitle" :class="subtitleClass">
|
|
17
|
+
{{ subtitle }}
|
|
18
|
+
</p>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none">
|
|
21
|
+
<slot name="actions" />
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script lang="ts">
|
|
28
|
+
import { defineComponent, PropType } from 'vue';
|
|
29
|
+
import { RouteLocationRaw } from 'vue-router';
|
|
30
|
+
|
|
31
|
+
export default defineComponent({
|
|
32
|
+
props: {
|
|
33
|
+
title: {
|
|
34
|
+
required: true,
|
|
35
|
+
type: String,
|
|
36
|
+
},
|
|
37
|
+
subtitle: {
|
|
38
|
+
default: '',
|
|
39
|
+
type: String,
|
|
40
|
+
},
|
|
41
|
+
level: {
|
|
42
|
+
default: 1,
|
|
43
|
+
type: Number,
|
|
44
|
+
},
|
|
45
|
+
back: {
|
|
46
|
+
default: '',
|
|
47
|
+
type: [String, Object] as PropType<RouteLocationRaw>,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
computed: {
|
|
51
|
+
titleClass(): string {
|
|
52
|
+
let classes =
|
|
53
|
+
'font-display md:leading-tight font-semibold text-slate-900';
|
|
54
|
+
|
|
55
|
+
if (this.level == 1) {
|
|
56
|
+
classes += ' md:text-3xl text-3xl leading-9';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (this.level == 2) {
|
|
60
|
+
classes += ' md:text-xl text-xl leading-6';
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return classes;
|
|
64
|
+
},
|
|
65
|
+
subtitleClass(): string {
|
|
66
|
+
let classes = 'mt-1 text-slate-600';
|
|
67
|
+
|
|
68
|
+
if (this.level == 1) {
|
|
69
|
+
classes += ' text-base leading-5';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (this.level == 2) {
|
|
73
|
+
classes += ' text-base leading-5';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return classes;
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
</script>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-if="max && (!min || text.length >= min)"
|
|
4
|
+
class="text-sm"
|
|
5
|
+
:class="{
|
|
6
|
+
'text-slate-500': text.length <= max,
|
|
7
|
+
'text-red-600': text.length > max,
|
|
8
|
+
}"
|
|
9
|
+
>
|
|
10
|
+
{{ text.length }}/{{ max }}
|
|
11
|
+
</div>
|
|
12
|
+
<div v-if="min && text.length < min" class="text-sm text-red-600">
|
|
13
|
+
{{ $t('sui.min_x_characters', { x: min }) }} ({{ text.length }}/{{ min }})
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script lang="ts">
|
|
18
|
+
import { defineComponent } from 'vue';
|
|
19
|
+
|
|
20
|
+
export default defineComponent({
|
|
21
|
+
props: {
|
|
22
|
+
text: {
|
|
23
|
+
required: true,
|
|
24
|
+
type: String,
|
|
25
|
+
},
|
|
26
|
+
min: {
|
|
27
|
+
default: undefined,
|
|
28
|
+
type: Number,
|
|
29
|
+
},
|
|
30
|
+
max: {
|
|
31
|
+
default: undefined,
|
|
32
|
+
type: Number,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
</script>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { DefineComponent, defineComponent, h } from 'vue';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Base component to manually render the slot of component
|
|
5
|
+
*/
|
|
6
|
+
export default defineComponent({
|
|
7
|
+
name: 'SlotComponent',
|
|
8
|
+
props: {
|
|
9
|
+
component: {
|
|
10
|
+
type: Object,
|
|
11
|
+
required: true,
|
|
12
|
+
},
|
|
13
|
+
name: {
|
|
14
|
+
type: String,
|
|
15
|
+
default: 'default',
|
|
16
|
+
},
|
|
17
|
+
props: {
|
|
18
|
+
required: true,
|
|
19
|
+
type: Object,
|
|
20
|
+
},
|
|
21
|
+
tag: {
|
|
22
|
+
type: String,
|
|
23
|
+
default: 'div',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
render() {
|
|
27
|
+
let slots = (this.component as DefineComponent).$slots;
|
|
28
|
+
|
|
29
|
+
if (slots == undefined) {
|
|
30
|
+
slots = (this.component as DefineComponent).slots;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const slot = slots[this.name](this.props);
|
|
34
|
+
|
|
35
|
+
return h(this.tag, {}, slot);
|
|
36
|
+
},
|
|
37
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { disableScroll, enableScroll } from 'src/utils';
|
|
2
|
+
import { Ref } from 'vue';
|
|
3
|
+
|
|
4
|
+
export function useModal(
|
|
5
|
+
modelValue: Ref<boolean>,
|
|
6
|
+
scrollable: Ref<HTMLElement | null>,
|
|
7
|
+
emit: any
|
|
8
|
+
) {
|
|
9
|
+
const mounted = ref(false);
|
|
10
|
+
|
|
11
|
+
watch(
|
|
12
|
+
() => modelValue.value,
|
|
13
|
+
() => {
|
|
14
|
+
init();
|
|
15
|
+
},
|
|
16
|
+
{ immediate: true }
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
onMounted(() => {
|
|
20
|
+
mounted.value = true;
|
|
21
|
+
init();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
onBeforeUnmount(() => {
|
|
25
|
+
deactivate();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
function init() {
|
|
29
|
+
if (!mounted.value) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (modelValue.value) {
|
|
34
|
+
activate();
|
|
35
|
+
} else {
|
|
36
|
+
deactivate();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function activate() {
|
|
41
|
+
disableScroll(scrollable.value);
|
|
42
|
+
window.addEventListener('keydown', onKeydown);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function deactivate() {
|
|
46
|
+
enableScroll();
|
|
47
|
+
window.removeEventListener('keydown', onKeydown);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function onKeydown(event: KeyboardEvent) {
|
|
51
|
+
if (event.code == 'Escape') {
|
|
52
|
+
if (modelValue) {
|
|
53
|
+
close();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const animationClasses = ref('');
|
|
59
|
+
|
|
60
|
+
function refuseAnimation() {
|
|
61
|
+
animationClasses.value = '';
|
|
62
|
+
setTimeout(() => {
|
|
63
|
+
animationClasses.value = 'animate-shake';
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function close() {
|
|
68
|
+
animationClasses.value = '';
|
|
69
|
+
emit('update:modelValue', false);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
close,
|
|
74
|
+
refuseAnimation,
|
|
75
|
+
animationClasses,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const MAGIC_NUM = 100
|
package/src/env.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
2
|
+
|
|
3
|
+
declare module '*.vue' {
|
|
4
|
+
import { DefineComponent } from 'vue';
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
|
|
6
|
+
const component: DefineComponent<{}, {}, any>;
|
|
7
|
+
export default component;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare global {
|
|
11
|
+
interface Window {
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
route: (name: string, options?: any) => string;
|
|
14
|
+
}
|
|
15
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import axios, { AxiosInstance } from 'axios';
|
|
2
|
+
import { App } from 'vue';
|
|
3
|
+
import * as components from './components';
|
|
4
|
+
import QueryString from 'qs';
|
|
5
|
+
import { createI18n, I18n } from 'vue-i18n';
|
|
6
|
+
import en from '@/lang/en.json';
|
|
7
|
+
import fr from '@/lang/fr.json';
|
|
8
|
+
|
|
9
|
+
const messages = { en, fr };
|
|
10
|
+
|
|
11
|
+
interface SprintifyUIConfig {
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
13
|
+
i18n?: I18n<typeof messages, {}, {}, string, true>;
|
|
14
|
+
http?: AxiosInstance;
|
|
15
|
+
upload_url?: string;
|
|
16
|
+
formatQueryString?: (params: Record<string, any>) => string;
|
|
17
|
+
parseQueryString?: (params: string) => Record<string, any>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const pluginConfig = {
|
|
21
|
+
i18n: createI18n({
|
|
22
|
+
messages: { en, fr },
|
|
23
|
+
}),
|
|
24
|
+
http: axios.create(),
|
|
25
|
+
upload_url: '/api/upload',
|
|
26
|
+
formatQueryString(params: Record<string, any>) {
|
|
27
|
+
return QueryString.stringify(params, {
|
|
28
|
+
arrayFormat: 'comma',
|
|
29
|
+
encode: import.meta.env.PROD ? true : false,
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
parseQueryString(params: string): Record<string, any> {
|
|
33
|
+
return QueryString.parse(params);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function install(app: App, config: SprintifyUIConfig) {
|
|
38
|
+
for (const key in components) {
|
|
39
|
+
// @ts-expect-error Will throw
|
|
40
|
+
app.component(key, components[key]);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (config.i18n) {
|
|
44
|
+
pluginConfig.i18n = config.i18n;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (config.http) {
|
|
48
|
+
pluginConfig.http = config.http;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (config.upload_url) {
|
|
52
|
+
pluginConfig.upload_url = config.upload_url;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (config.formatQueryString) {
|
|
56
|
+
pluginConfig.formatQueryString = config.formatQueryString;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (config.parseQueryString) {
|
|
60
|
+
pluginConfig.parseQueryString = config.parseQueryString;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default { install };
|
|
65
|
+
|
|
66
|
+
export * from './components';
|
|
67
|
+
export * from './constants';
|
|
68
|
+
export * from './utils';
|
|
69
|
+
|
|
70
|
+
export { pluginConfig as config };
|
package/src/lang/en.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sui": {
|
|
3
|
+
"and": "and",
|
|
4
|
+
"apply_filters": "Apply filters",
|
|
5
|
+
"autocomplete_placeholder": "Type to start your search",
|
|
6
|
+
"cancel": "Cancel",
|
|
7
|
+
"clear": "Clear",
|
|
8
|
+
"click_or_select_date": "Click or select date",
|
|
9
|
+
"click_to_copy": "Click to copy",
|
|
10
|
+
"columns": "Columns",
|
|
11
|
+
"confirm": "Confirm",
|
|
12
|
+
"copied": "Copied",
|
|
13
|
+
"create_new": "Create new",
|
|
14
|
+
"day": "Day",
|
|
15
|
+
"delete_record": "Delete the record",
|
|
16
|
+
"delete_record_description": "Are you sure to delete this record? This action is irreversible.",
|
|
17
|
+
"deselect_all": "Deselect all",
|
|
18
|
+
"drop_or_click_to_upload": "Drop or click to upload",
|
|
19
|
+
"error": "Error",
|
|
20
|
+
"file_must_be_of_type": "The file must be of type",
|
|
21
|
+
"filters": "Filters",
|
|
22
|
+
"min_x_characters": "{x} characters minimum",
|
|
23
|
+
"month": "Month",
|
|
24
|
+
"next": "Next",
|
|
25
|
+
"next_month": "Next month",
|
|
26
|
+
"nothing_found": "Nothing found",
|
|
27
|
+
"or": "or",
|
|
28
|
+
"pagination_detail": "{page} records of {total}",
|
|
29
|
+
"previous": "Previous",
|
|
30
|
+
"previous_month": "Previous month",
|
|
31
|
+
"read_more": "Read more",
|
|
32
|
+
"remove": "Remove",
|
|
33
|
+
"remove_file": "Remove file?",
|
|
34
|
+
"remove_file_description": "Are you sure you want to remove the file? This action is irreversible.",
|
|
35
|
+
"select_an_item": "Select an item",
|
|
36
|
+
"select_an_option": "Select an option",
|
|
37
|
+
"success": "Success",
|
|
38
|
+
"the_file_size_must_not_exceed_x": "The file size must not exceed {x}",
|
|
39
|
+
"the_file_type_is_invalid": "The file type is invalid",
|
|
40
|
+
"type_to_start_your_search": "Type to start your search",
|
|
41
|
+
"up_to_x": "Up to {x}",
|
|
42
|
+
"whoops": "Whoops",
|
|
43
|
+
"x_rows_selected": "1 item selected | {count} items selected",
|
|
44
|
+
"year": "Year",
|
|
45
|
+
"yes_delete": "Yes, delete",
|
|
46
|
+
"you_can_upload_up_to_n_files": "You can upload one file at most|You can upload up to {count} files",
|
|
47
|
+
"you_cannot_select_more_than_x_items": "You can't select more than one item|You can't select more than {x} items",
|
|
48
|
+
"units": {
|
|
49
|
+
"b": "B",
|
|
50
|
+
"gb": "GB",
|
|
51
|
+
"kb": "kB",
|
|
52
|
+
"mb": "MB",
|
|
53
|
+
"tb": "TB"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
package/src/lang/fr.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sui": {
|
|
3
|
+
"and": "et",
|
|
4
|
+
"apply_filters": "Appliquer les filtres",
|
|
5
|
+
"autocomplete_placeholder": "Tapez pour lancer votre recherche",
|
|
6
|
+
"cancel": "Annuler",
|
|
7
|
+
"clear": "Effacer",
|
|
8
|
+
"click_or_select_date": "Cliquez ou sélectionnez la date",
|
|
9
|
+
"click_to_copy": "Cliquez pour copier",
|
|
10
|
+
"columns": "Colonnes",
|
|
11
|
+
"confirm": "Confirmer",
|
|
12
|
+
"copied": "Copié",
|
|
13
|
+
"create_new": "Créer un nouveau",
|
|
14
|
+
"day": "Jour",
|
|
15
|
+
"delete_record": "Supprimer l'item",
|
|
16
|
+
"delete_record_description": "Voulez-vous vraiment supprimer cet item ? \nCette action est irréversible.",
|
|
17
|
+
"deselect_all": "Tout déselectionner",
|
|
18
|
+
"drop_or_click_to_upload": "Déposez ou cliquez pour télécharger",
|
|
19
|
+
"error": "Erreur",
|
|
20
|
+
"file_must_be_of_type": "Le fichier doit être de type",
|
|
21
|
+
"filters": "Filtres",
|
|
22
|
+
"min_x_characters": "{x} caractères minimum",
|
|
23
|
+
"month": "Mois",
|
|
24
|
+
"next": "Suivant",
|
|
25
|
+
"next_month": "Mois prochain",
|
|
26
|
+
"nothing_found": "Rien n'a été trouvé",
|
|
27
|
+
"or": "ou",
|
|
28
|
+
"pagination_detail": "{page} items de {total}",
|
|
29
|
+
"previous": "Précédent",
|
|
30
|
+
"previous_month": "Mois précédent",
|
|
31
|
+
"read_more": "Lire la suite",
|
|
32
|
+
"remove": "Retirer",
|
|
33
|
+
"remove_file": "Retirer le fichier?",
|
|
34
|
+
"remove_file_description": "Voulez-vous vraiment supprimer le fichier ? \nCette action est irréversible.",
|
|
35
|
+
"select_an_item": "Sélectionner un élément",
|
|
36
|
+
"select_an_option": "Sélectionner une option",
|
|
37
|
+
"success": "Succès",
|
|
38
|
+
"the_file_size_must_not_exceed_x": "La taille du fichier ne doit pas dépasser {x}",
|
|
39
|
+
"the_file_type_is_invalid": "Le type de fichier n'est pas valide",
|
|
40
|
+
"type_to_start_your_search": "Tapez pour lancer votre recherche",
|
|
41
|
+
"up_to_x": "Jusqu'à {x}",
|
|
42
|
+
"whoops": "Oups",
|
|
43
|
+
"x_rows_selected": "1 item sélectionné | \n{count} items sélectionnés",
|
|
44
|
+
"year": "An",
|
|
45
|
+
"yes_delete": "Oui, supprimer",
|
|
46
|
+
"you_can_upload_up_to_n_files": "Vous pouvez télécharger un fichier au maximum|Vous pouvez télécharger jusqu'à {count} fichiers",
|
|
47
|
+
"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 {x} éléments",
|
|
48
|
+
"units": {
|
|
49
|
+
"b": "o",
|
|
50
|
+
"gb": "Go",
|
|
51
|
+
"kb": "Ko",
|
|
52
|
+
"mb": "Mo",
|
|
53
|
+
"tb": "To"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|