sprintify-ui 0.0.11 → 0.0.13
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 +8 -7
- package/dist/sprintify-ui.es.js +5911 -3760
- package/dist/style.css +1 -1
- package/dist/tailwindcss/index.js +1 -2
- package/dist/types/src/components/BaseCharacterCounter.vue.d.ts +143 -0
- package/dist/types/src/components/BaseHasMany.vue.d.ts +277 -0
- package/dist/types/src/components/BaseInput.vue.d.ts +39 -5
- package/dist/types/src/components/BaseLoadingCover.vue.d.ts +72 -0
- package/dist/types/src/components/{BaseMediaLibraryItem.vue.d.ts → BaseMediaItem.vue.d.ts} +26 -4
- package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +23 -15
- package/dist/types/src/components/BaseMediaPreview.vue.d.ts +97 -0
- package/dist/types/src/components/BaseModalCenter.vue.d.ts +8 -8
- package/dist/types/src/components/BaseModalSide.vue.d.ts +8 -8
- package/dist/types/src/components/BasePagination.vue.d.ts +105 -13
- package/dist/types/src/components/BaseSelect.vue.d.ts +130 -26
- package/dist/types/src/components/BaseSideNavigationItem.vue.d.ts +20 -1
- package/dist/types/src/components/BaseSwitch.vue.d.ts +15 -8
- package/dist/types/src/components/BaseTabItem.vue.d.ts +45 -4
- package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +25 -17
- package/dist/types/src/components/BaseTagAutocompleteFetch.vue.d.ts +37 -21
- package/dist/types/src/components/BaseTextareaAutoresize.vue.d.ts +175 -21
- package/dist/types/src/components/index.d.ts +30 -1
- package/dist/types/src/index.d.ts +4 -0
- package/package.json +1 -1
- package/src/components/BaseAppDialogs.vue +2 -2
- package/src/components/BaseAppNotifications.vue +1 -1
- package/src/components/BaseAutocomplete.vue +16 -18
- package/src/components/BaseBelongsTo.vue +1 -0
- package/src/components/BaseCharacterCounter.stories.js +30 -0
- package/src/components/BaseCharacterCounter.vue +60 -0
- package/src/components/BaseClipboard.vue +1 -1
- package/src/components/BaseDataIterator.stories.js +2 -2
- package/src/components/BaseDataIterator.vue +32 -38
- package/src/components/BaseDataTable.stories.js +2 -2
- package/src/components/BaseFileUploader.vue +4 -0
- package/src/components/BaseHasMany.vue +92 -0
- package/src/components/BaseInput.stories.js +46 -0
- package/src/components/BaseInput.vue +10 -2
- package/src/components/BaseInputLabel.stories.js +31 -0
- package/src/components/BaseInputLabel.vue +1 -1
- package/src/components/BaseLoadingCover.stories.js +55 -0
- package/src/components/BaseLoadingCover.vue +19 -1
- package/src/components/BaseMediaItem.stories.js +41 -0
- package/src/components/BaseMediaItem.vue +71 -0
- package/src/components/BaseMediaLibrary.stories.js +80 -0
- package/src/components/BaseMediaLibrary.vue +67 -68
- package/src/components/BaseMediaPreview.stories.js +72 -0
- package/src/components/BaseMediaPreview.vue +90 -0
- package/src/components/BaseMenu.stories.js +125 -0
- package/src/components/BaseMenu.vue +1 -1
- package/src/components/BaseModalCenter.stories.js +61 -0
- package/src/components/BaseModalCenter.vue +2 -2
- package/src/components/BaseModalSide.stories.js +55 -0
- package/src/components/BaseModalSide.vue +2 -2
- package/src/components/BaseNavbar.stories.js +150 -0
- package/src/components/BaseNavbar.vue +3 -0
- package/src/components/BaseNavbarItem.vue +1 -0
- package/src/components/BaseNavbarItemContent.vue +3 -0
- package/src/components/BasePagination.stories.js +32 -0
- package/src/components/BasePagination.vue +126 -40
- package/src/components/BasePanel.stories.js +56 -0
- package/src/components/BasePassword.stories.js +36 -0
- package/src/components/BasePassword.vue +11 -5
- package/src/components/BaseProcessRing.stories.js +27 -0
- package/src/components/BaseReadMore.stories.js +30 -0
- package/src/components/BaseReadMore.vue +1 -1
- package/src/components/BaseSelect.stories.js +67 -0
- package/src/components/BaseSelect.vue +144 -44
- package/src/components/BaseSideNavigation.stories.js +55 -0
- package/src/components/BaseSideNavigation.vue +7 -2
- package/src/components/BaseSideNavigationItem.vue +21 -5
- package/src/components/BaseSkeleton.stories.js +36 -0
- package/src/components/BaseSwitch.stories.js +101 -0
- package/src/components/BaseSwitch.vue +90 -12
- package/src/components/BaseSystemAlert.stories.js +63 -0
- package/src/components/BaseTabItem.vue +29 -6
- package/src/components/BaseTable.vue +2 -2
- package/src/components/BaseTabs.stories.js +54 -0
- package/src/components/BaseTabs.vue +3 -3
- package/src/components/BaseTagAutocomplete.stories.js +129 -0
- package/src/components/BaseTagAutocomplete.vue +155 -57
- package/src/components/BaseTagAutocompleteFetch.stories.js +130 -0
- package/src/components/BaseTagAutocompleteFetch.vue +36 -25
- package/src/components/BaseTextarea.stories.js +35 -0
- package/src/components/BaseTextarea.vue +1 -1
- package/src/components/BaseTextareaAutoresize.stories.js +49 -0
- package/src/components/BaseTextareaAutoresize.vue +83 -87
- package/src/components/HasMany.stories.js +135 -0
- package/src/components/index.ts +58 -0
- package/src/lang/en.json +2 -1
- package/src/lang/fr.json +2 -1
- package/dist/types/src/components/BasePaginationSimple.vue.d.ts +0 -25
- package/dist/types/src/components/BaseWordCount.vue.d.ts +0 -31
- package/src/components/BaseMediaLibraryItem.vue +0 -92
- package/src/components/BasePaginationSimple.vue +0 -60
- package/src/components/BaseWordCount.vue +0 -36
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import BaseNavbar from './BaseNavbar.vue';
|
|
2
|
+
import BaseNavbarItem from './BaseNavbarItem.vue';
|
|
3
|
+
import BaseAvatar from './BaseAvatar.vue';
|
|
4
|
+
import BaseMenu from './BaseMenu.vue';
|
|
5
|
+
import { Icon as BaseIcon } from '@iconify/vue';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
title: 'Layout/BaseNavbar',
|
|
9
|
+
component: BaseNavbar,
|
|
10
|
+
args: {},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const Template = (args) => ({
|
|
14
|
+
components: {
|
|
15
|
+
BaseNavbar,
|
|
16
|
+
BaseNavbarItem,
|
|
17
|
+
BaseIcon,
|
|
18
|
+
BaseAvatar,
|
|
19
|
+
BaseMenu,
|
|
20
|
+
},
|
|
21
|
+
setup() {
|
|
22
|
+
const user = {
|
|
23
|
+
email: 'jane@witify.io',
|
|
24
|
+
first_name: 'Jane',
|
|
25
|
+
last_name: 'Doe',
|
|
26
|
+
full_name: 'Jane Doe',
|
|
27
|
+
avatar_url:
|
|
28
|
+
'https://images.unsplash.com/photo-1494790108377-be9c29b29330??auto=format&fit=crop&w=200&h=200&q=80&g=face',
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const menu = [
|
|
32
|
+
{
|
|
33
|
+
label: 'Home',
|
|
34
|
+
to: '/',
|
|
35
|
+
type: 'RouterLink',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
label: 'Products',
|
|
39
|
+
to: '/',
|
|
40
|
+
count: 234,
|
|
41
|
+
type: 'RouterLink',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
label: 'Settings',
|
|
45
|
+
to: '/',
|
|
46
|
+
type: 'RouterLink',
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const userMenu = [
|
|
51
|
+
{
|
|
52
|
+
label: 'Home',
|
|
53
|
+
icon: 'heroicons:home',
|
|
54
|
+
href: 'https://google.com',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
line: true,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
label: 'Logout',
|
|
61
|
+
icon: 'heroicons:arrow-right-on-rectangle',
|
|
62
|
+
href: 'https://google.com',
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
return { args, menu, userMenu, user };
|
|
67
|
+
},
|
|
68
|
+
template: `
|
|
69
|
+
<div class="mb-40">
|
|
70
|
+
<BaseNavbar v-bind="args">
|
|
71
|
+
<template #navbar>
|
|
72
|
+
<div class="flex h-16 justify-between">
|
|
73
|
+
<!-- Left -->
|
|
74
|
+
|
|
75
|
+
<div class="flex items-center justify-center">
|
|
76
|
+
<!-- Logo -->
|
|
77
|
+
<router-link to="/" class="flex flex-shrink-0 grow items-center p-2 pl-0">
|
|
78
|
+
<img
|
|
79
|
+
class="block h-8 w-auto"
|
|
80
|
+
src="https://sprintify.witify.io/img/logo/logo-side-dark.svg"
|
|
81
|
+
alt="Sprintify"
|
|
82
|
+
/>
|
|
83
|
+
</router-link>
|
|
84
|
+
|
|
85
|
+
<!-- Links (desktop) -->
|
|
86
|
+
<div class="ml-10 hidden items-center space-x-4 md:flex">
|
|
87
|
+
<BaseNavbarItem
|
|
88
|
+
v-for="item in menu"
|
|
89
|
+
:key="item.label"
|
|
90
|
+
:item="item"
|
|
91
|
+
/>
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<!-- Right -->
|
|
96
|
+
|
|
97
|
+
<div class="hidden md:ml-6 md:flex md:items-center">
|
|
98
|
+
<!-- Profile dropdown -->
|
|
99
|
+
<BaseMenu menu-class="w-52" :items="userMenu">
|
|
100
|
+
<template #button="{ open }">
|
|
101
|
+
<div
|
|
102
|
+
class="flex rounded-full"
|
|
103
|
+
:class="[open ? 'bg-slate-700 ring-2 ring-blue-500 ring-offset-2 ring-offset-slate-700' : '']"
|
|
104
|
+
>
|
|
105
|
+
<BaseAvatar class="text-white" :user="user" />
|
|
106
|
+
</div>
|
|
107
|
+
</template>
|
|
108
|
+
</BaseMenu>
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
</template>
|
|
112
|
+
|
|
113
|
+
<template #mobile>
|
|
114
|
+
<!-- Links mobile -->
|
|
115
|
+
<div class="space-y-1 p-2">
|
|
116
|
+
<BaseNavbarItem
|
|
117
|
+
v-for="item in menu"
|
|
118
|
+
:key="item.label"
|
|
119
|
+
:item="item"
|
|
120
|
+
class="flex w-full"
|
|
121
|
+
/>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<hr class="my-4 border-slate-700" />
|
|
125
|
+
|
|
126
|
+
<!-- Profile links -->
|
|
127
|
+
<div class="p-2 pb-6">
|
|
128
|
+
<BaseAvatar
|
|
129
|
+
:user="user"
|
|
130
|
+
show-details
|
|
131
|
+
size="base"
|
|
132
|
+
class="px-3 text-white"
|
|
133
|
+
/>
|
|
134
|
+
<div class="mt-4 space-y-1">
|
|
135
|
+
<BaseNavbarItem
|
|
136
|
+
v-for="item in userMenu"
|
|
137
|
+
:key="item.label"
|
|
138
|
+
:item="item"
|
|
139
|
+
class="flex w-full"
|
|
140
|
+
/>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
</template>
|
|
144
|
+
</BaseNavbar>
|
|
145
|
+
</div>
|
|
146
|
+
`,
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
export const Demo = Template.bind({});
|
|
150
|
+
Demo.args = {};
|
|
@@ -11,6 +11,9 @@
|
|
|
11
11
|
</template>
|
|
12
12
|
|
|
13
13
|
<script lang="ts" setup>
|
|
14
|
+
import { Icon as BaseIcon } from '@iconify/vue';
|
|
15
|
+
import BaseCounter from './BaseCounter.vue';
|
|
16
|
+
|
|
14
17
|
const buttonClasses =
|
|
15
18
|
'px-3 py-2 text-left rounded-md md:text-sm flex text-base font-normal w-full';
|
|
16
19
|
const buttonInactiveClasses =
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import BasePagination from './BasePagination.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Components/BasePagination',
|
|
5
|
+
component: BasePagination,
|
|
6
|
+
args: {
|
|
7
|
+
totalVisible: 12,
|
|
8
|
+
lastPage: 20,
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const Template = (args) => ({
|
|
13
|
+
components: {
|
|
14
|
+
BasePagination,
|
|
15
|
+
},
|
|
16
|
+
setup() {
|
|
17
|
+
const modelValue = ref(10);
|
|
18
|
+
|
|
19
|
+
return { args, modelValue };
|
|
20
|
+
},
|
|
21
|
+
template: `
|
|
22
|
+
<div>
|
|
23
|
+
<BasePagination v-model="modelValue" v-bind="args"></BasePagination>
|
|
24
|
+
</div>
|
|
25
|
+
<div style="max-width: 500px;">
|
|
26
|
+
<BasePagination v-model="modelValue" v-bind="args"></BasePagination>
|
|
27
|
+
</div>
|
|
28
|
+
`,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const Demo = Template.bind({});
|
|
32
|
+
Demo.args = {};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<nav
|
|
3
3
|
v-if="lastPage > 1 || lastPage < modelValue"
|
|
4
|
-
|
|
4
|
+
ref="paginationNode"
|
|
5
|
+
class="flex items-center justify-between border-t border-slate-200"
|
|
5
6
|
>
|
|
6
|
-
<div class="-mt-px
|
|
7
|
+
<div class="flex -mt-px w-0 flex-1">
|
|
7
8
|
<button
|
|
8
9
|
type="button"
|
|
9
10
|
:disabled="modelValue == 1"
|
|
@@ -17,23 +18,25 @@
|
|
|
17
18
|
{{ $t('sui.previous') }}
|
|
18
19
|
</button>
|
|
19
20
|
</div>
|
|
20
|
-
<div class="hidden
|
|
21
|
+
<div :class="[mobileLayout ? 'hidden' : 'flex -mt-px']">
|
|
21
22
|
<button
|
|
22
|
-
v-for="i in
|
|
23
|
-
:key="i"
|
|
23
|
+
v-for="(i, index) in items"
|
|
24
|
+
:key="i + (index + '')"
|
|
24
25
|
type="button"
|
|
25
|
-
class="inline-flex items-center border-t-2 px-4 py-4 text-sm font-medium
|
|
26
|
-
:class="
|
|
27
|
-
i == modelValue
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
class="inline-flex items-center border-t-2 px-4 py-4 text-sm font-medium"
|
|
27
|
+
:class="[
|
|
28
|
+
i == modelValue ? 'border-primary-500 text-primary-500' : '',
|
|
29
|
+
i != modelValue ? 'border-transparent text-slate-500' : '',
|
|
30
|
+
i != modelValue && isClickable(i)
|
|
31
|
+
? 'hover:border-slate-300 hover:text-slate-700'
|
|
32
|
+
: '',
|
|
33
|
+
]"
|
|
34
|
+
@click="onButtonClick(i)"
|
|
32
35
|
>
|
|
33
36
|
{{ i }}
|
|
34
37
|
</button>
|
|
35
38
|
</div>
|
|
36
|
-
<div class="-mt-px
|
|
39
|
+
<div class="flex -mt-px w-0 flex-1 justify-end">
|
|
37
40
|
<button
|
|
38
41
|
:disabled="modelValue >= lastPage"
|
|
39
42
|
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"
|
|
@@ -49,34 +52,117 @@
|
|
|
49
52
|
</nav>
|
|
50
53
|
</template>
|
|
51
54
|
|
|
52
|
-
<script lang="ts">
|
|
53
|
-
import {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
<script lang="ts" setup>
|
|
56
|
+
import { useResizeObserver } from '@vueuse/core';
|
|
57
|
+
import { range } from 'lodash';
|
|
58
|
+
import { Ref } from 'vue';
|
|
59
|
+
|
|
60
|
+
const props = defineProps({
|
|
61
|
+
modelValue: {
|
|
62
|
+
default: 1,
|
|
63
|
+
required: true,
|
|
64
|
+
type: Number,
|
|
65
|
+
},
|
|
66
|
+
lastPage: {
|
|
67
|
+
required: true,
|
|
68
|
+
type: Number,
|
|
65
69
|
},
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
},
|
|
70
|
+
totalVisible: {
|
|
71
|
+
default: 10,
|
|
72
|
+
type: Number,
|
|
80
73
|
},
|
|
81
74
|
});
|
|
75
|
+
|
|
76
|
+
const emit = defineEmits(['update:model-value']);
|
|
77
|
+
|
|
78
|
+
function next() {
|
|
79
|
+
if (props.modelValue >= props.lastPage) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
emit('update:model-value', props.modelValue + 1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function previous() {
|
|
86
|
+
if (props.modelValue == 1) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
emit('update:model-value', props.modelValue - 1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const paginationNode = ref(null) as Ref<null | HTMLElement>;
|
|
93
|
+
const width = ref(800);
|
|
94
|
+
|
|
95
|
+
useResizeObserver(paginationNode, () => {
|
|
96
|
+
width.value = paginationNode.value?.clientWidth ?? 800;
|
|
97
|
+
maxButtons.value = Math.floor((width.value - 96) / 56);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
const mobileLayout = computed(() => {
|
|
101
|
+
return width.value < 600;
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const length = computed(() => {
|
|
105
|
+
return props.lastPage + 1;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const maxButtons = ref(0);
|
|
109
|
+
|
|
110
|
+
const items = computed(() => {
|
|
111
|
+
const totalVisible = props.totalVisible + 2;
|
|
112
|
+
|
|
113
|
+
if (
|
|
114
|
+
totalVisible === 0 ||
|
|
115
|
+
isNaN(length.value) ||
|
|
116
|
+
length.value > Number.MAX_SAFE_INTEGER
|
|
117
|
+
) {
|
|
118
|
+
return [];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const maxLength = Math.min(
|
|
122
|
+
Math.max(0, totalVisible) || length.value,
|
|
123
|
+
Math.max(0, maxButtons.value) || length.value,
|
|
124
|
+
length.value
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
if (length.value <= maxLength) {
|
|
128
|
+
return range(1, length.value);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const even = maxLength % 2 === 0 ? 1 : 0;
|
|
132
|
+
const left = Math.floor(maxLength / 2);
|
|
133
|
+
const right = length.value - left + 1 + even;
|
|
134
|
+
|
|
135
|
+
if (props.modelValue > left && props.modelValue < right) {
|
|
136
|
+
const firstItem = 1;
|
|
137
|
+
const lastItem = length.value;
|
|
138
|
+
const start = props.modelValue - left + 2;
|
|
139
|
+
const end = props.modelValue + left - 2 - even;
|
|
140
|
+
const secondItem = start - 1 === firstItem + 1 ? 2 : '...';
|
|
141
|
+
const beforeLastItem = end + 1 === lastItem - 1 ? end + 1 : '...';
|
|
142
|
+
|
|
143
|
+
return [1, secondItem, ...range(start, end), beforeLastItem, length.value];
|
|
144
|
+
} else if (props.modelValue === left) {
|
|
145
|
+
const end = props.modelValue + left - 1 - even;
|
|
146
|
+
return [...range(1, end), '...', length.value];
|
|
147
|
+
} else if (props.modelValue === right) {
|
|
148
|
+
const start = props.modelValue - left + 1;
|
|
149
|
+
return [1, '...', ...range(start, length.value)];
|
|
150
|
+
} else {
|
|
151
|
+
return [...range(1, left), '...', ...range(right, length.value)];
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
function isClickable(i: number | string) {
|
|
156
|
+
if (i == '...') {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function onButtonClick(i: number | string) {
|
|
163
|
+
if (!isClickable(i)) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
emit('update:model-value', i);
|
|
167
|
+
}
|
|
82
168
|
</script>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import BaseContainer from './BaseContainer.vue';
|
|
2
|
+
import BasePanel from './BasePanel.vue';
|
|
3
|
+
import BaseCard from './BaseCard.vue';
|
|
4
|
+
import BaseCardRow from './BaseCardRow.vue';
|
|
5
|
+
import BaseInputLabel from './BaseInputLabel.vue';
|
|
6
|
+
import BaseInput from './BaseInput.vue';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: 'Layout/BasePanel',
|
|
10
|
+
component: BasePanel,
|
|
11
|
+
args: {
|
|
12
|
+
title: 'General information',
|
|
13
|
+
description:
|
|
14
|
+
'Enter general user information, name and age. User must be more than 10 years old to participate.',
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const Template = (args) => ({
|
|
19
|
+
components: {
|
|
20
|
+
BaseContainer,
|
|
21
|
+
BasePanel,
|
|
22
|
+
BaseCard,
|
|
23
|
+
BaseCardRow,
|
|
24
|
+
BaseInputLabel,
|
|
25
|
+
BaseInput,
|
|
26
|
+
},
|
|
27
|
+
setup() {
|
|
28
|
+
return { args };
|
|
29
|
+
},
|
|
30
|
+
template: `
|
|
31
|
+
<div class="bg-slate-100 py-10">
|
|
32
|
+
<BaseContainer>
|
|
33
|
+
<BasePanel v-bind="args">
|
|
34
|
+
<BaseCard>
|
|
35
|
+
<BaseCardRow>
|
|
36
|
+
<div class="mb-4">
|
|
37
|
+
<BaseInputLabel label="Name" />
|
|
38
|
+
<BaseInput name="name" class="w-full" placeholder="Enter you name" />
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<div class="mb-4">
|
|
42
|
+
<BaseInputLabel label="Age" />
|
|
43
|
+
<BaseInput name="age" class="w-full" placeholder="Enter you age" />
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<button class="btn btn-primary mt-2">Submit</button>
|
|
47
|
+
</BaseCardRow>
|
|
48
|
+
</BaseCard>
|
|
49
|
+
</BasePanel>
|
|
50
|
+
</BaseContainer>
|
|
51
|
+
</div>
|
|
52
|
+
`,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export const Demo = Template.bind({});
|
|
56
|
+
Demo.args = {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import BasePassword from './BasePassword.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Form/BasePassword',
|
|
5
|
+
component: BasePassword,
|
|
6
|
+
args: {
|
|
7
|
+
required: true,
|
|
8
|
+
name: 'password',
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const Template = (args) => ({
|
|
13
|
+
components: {
|
|
14
|
+
BasePassword,
|
|
15
|
+
},
|
|
16
|
+
setup() {
|
|
17
|
+
const value = ref('');
|
|
18
|
+
return { args, value };
|
|
19
|
+
},
|
|
20
|
+
template: `
|
|
21
|
+
<form @submit.prevent="">
|
|
22
|
+
<BasePassword class="border-slate-300" v-model="value" v-bind="args"></BasePassword>
|
|
23
|
+
</form>
|
|
24
|
+
`,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export const Demo = Template.bind({});
|
|
28
|
+
Demo.args = {
|
|
29
|
+
placeholder: 'Enter your password',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const Disabled = Template.bind({});
|
|
33
|
+
Disabled.args = {
|
|
34
|
+
disabled: true,
|
|
35
|
+
placeholder: 'Enter your password',
|
|
36
|
+
};
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
class="flex rounded border border-slate-300 bg-white"
|
|
4
|
+
:class="[disabled ? 'cursor-not-allowed text-slate-300' : '']"
|
|
5
|
+
>
|
|
3
6
|
<input
|
|
4
7
|
ref="input"
|
|
5
8
|
:value="modelValue"
|
|
@@ -8,7 +11,7 @@
|
|
|
8
11
|
:disabled="disabled"
|
|
9
12
|
:placeholder="placeholder"
|
|
10
13
|
:required="required"
|
|
11
|
-
class="grow rounded-l border-none focus:ring-2 focus:ring-primary-500"
|
|
14
|
+
class="grow rounded-l rounded-r-none border-none focus:ring-2 focus:ring-primary-500 disabled:cursor-not-allowed"
|
|
12
15
|
:class="inputClass"
|
|
13
16
|
@input="onInput"
|
|
14
17
|
/>
|
|
@@ -16,15 +19,16 @@
|
|
|
16
19
|
<button
|
|
17
20
|
tabindex="-1"
|
|
18
21
|
type="button"
|
|
19
|
-
class="pr-3 text-slate-500"
|
|
22
|
+
class="pr-3 text-slate-500 disabled:cursor-not-allowed disabled:text-slate-300"
|
|
23
|
+
:disabled="disabled"
|
|
20
24
|
@click="showPassword = !showPassword"
|
|
21
25
|
>
|
|
22
26
|
<BaseIcon
|
|
23
27
|
v-if="!showPassword"
|
|
24
|
-
icon="heroicons:eye-
|
|
28
|
+
icon="heroicons:eye-slash-20-solid"
|
|
25
29
|
class="h-5 w-5"
|
|
26
30
|
/>
|
|
27
|
-
<BaseIcon v-else icon="heroicons:eye" class="h-5 w-5" />
|
|
31
|
+
<BaseIcon v-else icon="heroicons:eye-20-solid" class="h-5 w-5" />
|
|
28
32
|
</button>
|
|
29
33
|
</div>
|
|
30
34
|
</div>
|
|
@@ -33,8 +37,10 @@
|
|
|
33
37
|
<script lang="ts">
|
|
34
38
|
import { trim } from 'lodash';
|
|
35
39
|
import { defineComponent, PropType } from 'vue';
|
|
40
|
+
import { Icon as BaseIcon } from '@iconify/vue';
|
|
36
41
|
|
|
37
42
|
export default defineComponent({
|
|
43
|
+
components: { BaseIcon },
|
|
38
44
|
props: {
|
|
39
45
|
modelValue: {
|
|
40
46
|
default: '',
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import BaseProcessRing from './BaseProcessRing.vue';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Components/BaseProcessRing',
|
|
5
|
+
component: BaseProcessRing,
|
|
6
|
+
args: {
|
|
7
|
+
class: 'text-primary-500',
|
|
8
|
+
radius: 100,
|
|
9
|
+
stroke: 5,
|
|
10
|
+
progress: 0.6,
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const Template = (args) => ({
|
|
15
|
+
components: {
|
|
16
|
+
BaseProcessRing,
|
|
17
|
+
},
|
|
18
|
+
setup() {
|
|
19
|
+
return { args };
|
|
20
|
+
},
|
|
21
|
+
template: `
|
|
22
|
+
<BaseProcessRing v-bind="args"></BaseProcessRing>
|
|
23
|
+
`,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const Demo = Template.bind({});
|
|
27
|
+
Demo.args = {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import BaseReadMore from './BaseReadMore.vue';
|
|
2
|
+
import BaseContainer from './BaseContainer.vue';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Components/BaseReadMore',
|
|
6
|
+
component: BaseReadMore,
|
|
7
|
+
args: {},
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const Template = (args) => ({
|
|
11
|
+
components: {
|
|
12
|
+
BaseReadMore,
|
|
13
|
+
BaseContainer,
|
|
14
|
+
},
|
|
15
|
+
setup() {
|
|
16
|
+
return { args };
|
|
17
|
+
},
|
|
18
|
+
template: `
|
|
19
|
+
<BaseContainer size="3xl">
|
|
20
|
+
<BaseReadMore v-bind="args">
|
|
21
|
+
<p class="text-slate-600">
|
|
22
|
+
Aute incididunt laborum in sint commodo reprehenderit et aliquip aliqua proident exercitation nostrud sunt. Consectetur laborum elit do non ullamco anim fugiat laboris non aliqua consequat culpa. Veniam aliquip irure et qui dolore eiusmod exercitation elit exercitation ad excepteur reprehenderit enim. Id laboris do eu amet qui Lorem excepteur. Eiusmod eiusmod est qui minim consectetur aliqua occaecat sit tempor nulla. Velit et eiusmod id ut adipisicing occaecat deserunt.Excepteur occaecat nulla deserunt Lorem eu mollit non esse. Velit do proident adipisicing labore ipsum nostrud ipsum pariatur magna. Consequat do reprehenderit eiusmod cupidatat cupidatat cupidatat reprehenderit. Aute fugiat ex fugiat in ut enim dolore est qui. Lorem irure eiusmod eiusmod cillum aute nostrud sint aute enim aute. Aliquip aliqua quis deserunt commodo fugiat incididunt sint qui proident.
|
|
23
|
+
</p>
|
|
24
|
+
</BaseReadMore>
|
|
25
|
+
</BaseContainer>
|
|
26
|
+
`,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const Demo = Template.bind({});
|
|
30
|
+
Demo.args = {};
|
|
@@ -13,7 +13,7 @@
|
|
|
13
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
14
|
@click="showMore = true"
|
|
15
15
|
>
|
|
16
|
-
<span class="text-base font-
|
|
16
|
+
<span class="text-base font-medium">{{ $t('sui.read_more') }}</span>
|
|
17
17
|
</button>
|
|
18
18
|
</div>
|
|
19
19
|
</template>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import BaseSelect from './BaseSelect.vue';
|
|
2
|
+
import BaseInputLabel from './BaseInputLabel.vue';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Form/BaseSelect',
|
|
6
|
+
component: BaseSelect,
|
|
7
|
+
args: {
|
|
8
|
+
name: 'name',
|
|
9
|
+
class: 'w-full',
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const Template = (args) => ({
|
|
14
|
+
components: {
|
|
15
|
+
BaseSelect,
|
|
16
|
+
BaseInputLabel,
|
|
17
|
+
},
|
|
18
|
+
setup() {
|
|
19
|
+
function onSubmit() {
|
|
20
|
+
alert('submit');
|
|
21
|
+
}
|
|
22
|
+
// To test, you should try the following scenarios
|
|
23
|
+
// - valid (ex: 'javascript')
|
|
24
|
+
// - invalid (ex: 'test')
|
|
25
|
+
// - empty string ''
|
|
26
|
+
// - null
|
|
27
|
+
// - undefined
|
|
28
|
+
|
|
29
|
+
// Test on Safari AND Chrome
|
|
30
|
+
|
|
31
|
+
// For optional, make sure the default option is selected
|
|
32
|
+
// For required, try to submit, it should be prevented
|
|
33
|
+
const value = ref('test');
|
|
34
|
+
return { args, value, onSubmit };
|
|
35
|
+
},
|
|
36
|
+
template: `
|
|
37
|
+
<form @submit.prevent="onSubmit" class="border-none">
|
|
38
|
+
<BaseInputLabel :required="args.required" label="Choose your favorite programing language" />
|
|
39
|
+
<BaseSelect v-model="value" v-bind="args">
|
|
40
|
+
<option value="javascript">JavaScript</option>
|
|
41
|
+
<option value="typescript">Typescript</option>
|
|
42
|
+
<option value="golang">Golang</option>
|
|
43
|
+
</BaseSelect>
|
|
44
|
+
<button type="submit" class="btn btn-primary mt-5">Submit</button>
|
|
45
|
+
</form>
|
|
46
|
+
<pre class="mt-4 bg-slate-800 font-light text-xs p-3 rounded text-white">{{ {value} }}</pre>
|
|
47
|
+
`,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export const Optional = Template.bind({});
|
|
51
|
+
Optional.args = {
|
|
52
|
+
required: false,
|
|
53
|
+
placeholder: 'I dont like programing languages',
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const Required = Template.bind({});
|
|
57
|
+
Required.args = {
|
|
58
|
+
required: true,
|
|
59
|
+
placeholder: 'Choose a language',
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export const Disabled = Template.bind({});
|
|
63
|
+
Disabled.args = {
|
|
64
|
+
required: true,
|
|
65
|
+
placeholder: 'Choose a language',
|
|
66
|
+
disabled: true,
|
|
67
|
+
};
|