sprintify-ui 0.6.33 → 0.6.35
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/dist/sprintify-ui.es.js +12984 -12888
- package/dist/style.css +1 -1
- package/dist/tailwindcss/button.js +3 -2
- package/dist/tailwindcss/theme.js +14 -7
- package/dist/types/src/components/BaseButtonGroup.vue.d.ts +9 -0
- package/dist/types/src/components/BaseDataIterator.vue.d.ts +3 -3
- package/dist/types/src/components/BaseDataIteratorSectionButton.vue.d.ts +2 -2
- package/dist/types/src/components/BaseDataIteratorSectionColumns.vue.d.ts +8 -8
- package/dist/types/src/components/BaseDataTable.vue.d.ts +3 -3
- package/dist/types/src/components/BaseDataTableRowAction.vue.d.ts +4 -3
- package/dist/types/src/components/BaseDatePicker.vue.d.ts +10 -0
- package/dist/types/src/components/BaseDateSelect.vue.d.ts +9 -0
- package/dist/types/src/components/BaseInput.vue.d.ts +18 -0
- package/dist/types/src/components/BasePassword.vue.d.ts +13 -0
- package/dist/types/src/components/BaseRichText.vue.d.ts +9 -0
- package/dist/types/src/components/BaseTable.vue.d.ts +3 -3
- package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +11 -2
- package/dist/types/src/components/BaseTextarea.vue.d.ts +18 -0
- package/dist/types/src/components/BaseTextareaAutoresize.vue.d.ts +12 -2
- package/dist/types/src/stories/PageInputSizes.vue.d.ts +2 -0
- package/dist/types/src/utils/slots.d.ts +1 -0
- package/package.json +1 -1
- package/src/assets/base-rich-text.css +148 -26
- package/src/components/BaseButton.vue +3 -2
- package/src/components/BaseButtonGroup.vue +37 -9
- package/src/components/BaseColor.vue +29 -31
- package/src/components/BaseDataIterator.stories.js +8 -1
- package/src/components/BaseDataIterator.vue +36 -76
- package/src/components/BaseDataIteratorSectionButton.vue +8 -19
- package/src/components/BaseDataTable.vue +25 -18
- package/src/components/BaseDataTableRowAction.vue +8 -7
- package/src/components/BaseDatePicker.stories.js +23 -0
- package/src/components/BaseDatePicker.vue +71 -11
- package/src/components/BaseDateSelect.stories.js +25 -1
- package/src/components/BaseDateSelect.vue +80 -101
- package/src/components/BaseDraggable.vue +5 -1
- package/src/components/BaseDropdownAutocomplete.stories.js +30 -15
- package/src/components/BaseHasMany.stories.js +22 -1
- package/src/components/BaseInput.stories.js +4 -4
- package/src/components/BaseInput.vue +61 -15
- package/src/components/BaseMediaPicturesItem.vue +2 -2
- package/src/components/BasePassword.stories.js +25 -0
- package/src/components/BasePassword.vue +35 -55
- package/src/components/BaseRichText.stories.js +6 -0
- package/src/components/BaseRichText.vue +12 -2
- package/src/components/BaseSelect.vue +5 -0
- package/src/components/BaseTable.vue +2 -1
- package/src/components/BaseTagAutocomplete.stories.js +1 -1
- package/src/components/BaseTagAutocomplete.vue +143 -88
- package/src/components/BaseTagAutocompleteFetch.stories.js +22 -1
- package/src/components/BaseTextarea.stories.js +25 -0
- package/src/components/BaseTextarea.vue +34 -3
- package/src/components/BaseTextareaAutoresize.stories.js +27 -2
- package/src/components/BaseTextareaAutoresize.vue +28 -9
- package/src/composables/inputSize.ts +5 -1
- package/src/stories/InputSizes.stories.js +22 -0
- package/src/stories/PageInputSizes.vue +205 -0
- package/src/utils/slots.ts +13 -0
|
@@ -1,50 +1,25 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
:placeholder="placeholder"
|
|
16
|
-
:required="requiredInternal"
|
|
17
|
-
class="grow rounded-l rounded-r-none border-none focus:ring-2 focus:ring-primary-500 disabled:cursor-not-allowed"
|
|
18
|
-
@input="onInput"
|
|
19
|
-
>
|
|
20
|
-
<div class="flex shrink-0 pl-3">
|
|
21
|
-
<button
|
|
22
|
-
tabindex="-1"
|
|
23
|
-
type="button"
|
|
24
|
-
class="pr-3 text-slate-500 disabled:cursor-not-allowed disabled:text-slate-300"
|
|
25
|
-
:disabled="disabled"
|
|
26
|
-
@click="showPassword = !showPassword"
|
|
27
|
-
>
|
|
28
|
-
<BaseIcon
|
|
29
|
-
v-if="!showPassword"
|
|
30
|
-
icon="heroicons:eye-slash-20-solid"
|
|
31
|
-
class="h-5 w-5"
|
|
32
|
-
/>
|
|
33
|
-
<BaseIcon
|
|
34
|
-
v-else
|
|
35
|
-
icon="heroicons:eye-20-solid"
|
|
36
|
-
class="h-5 w-5"
|
|
37
|
-
/>
|
|
38
|
-
</button>
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
2
|
+
<BaseInput
|
|
3
|
+
ref="input"
|
|
4
|
+
:model-value="modelValue"
|
|
5
|
+
:type="showPassword ? 'text' : 'password'"
|
|
6
|
+
:disabled="disabled"
|
|
7
|
+
:placeholder="placeholder"
|
|
8
|
+
:size="size"
|
|
9
|
+
:icon-right="showPassword ? 'heroicons:eye-20-solid' : 'heroicons:eye-slash-20-solid'"
|
|
10
|
+
@icon-right-click="onIconRightClick"
|
|
11
|
+
@update:model-value="onUpdateModelValue"
|
|
12
|
+
@focus="onFocus"
|
|
13
|
+
@blur="onBlur"
|
|
14
|
+
/>
|
|
41
15
|
</template>
|
|
42
16
|
|
|
43
17
|
<script lang="ts" setup>
|
|
44
|
-
import { trim } from 'lodash';
|
|
45
|
-
import { Icon as BaseIcon } from '@iconify/vue';
|
|
46
18
|
import { PropType } from 'vue';
|
|
47
|
-
import {
|
|
19
|
+
import { Size } from '@/utils/sizes';
|
|
20
|
+
import BaseInput from './BaseInput.vue';
|
|
21
|
+
|
|
22
|
+
const emit = defineEmits(['update:modelValue', 'blur', 'focus']);
|
|
48
23
|
|
|
49
24
|
const props = defineProps({
|
|
50
25
|
modelValue: {
|
|
@@ -55,6 +30,10 @@ const props = defineProps({
|
|
|
55
30
|
default: false,
|
|
56
31
|
type: Boolean,
|
|
57
32
|
},
|
|
33
|
+
size: {
|
|
34
|
+
default: undefined,
|
|
35
|
+
type: String as PropType<Size>,
|
|
36
|
+
},
|
|
58
37
|
name: {
|
|
59
38
|
default: undefined,
|
|
60
39
|
type: String,
|
|
@@ -75,21 +54,10 @@ const props = defineProps({
|
|
|
75
54
|
|
|
76
55
|
const input = ref<HTMLInputElement | null>(null);
|
|
77
56
|
|
|
78
|
-
const emit = defineEmits(['update:modelValue']);
|
|
79
|
-
|
|
80
|
-
const { nameInternal, requiredInternal, hasErrorInternal, emitUpdate } =
|
|
81
|
-
useField({
|
|
82
|
-
name: computed(() => props.name),
|
|
83
|
-
required: computed(() => props.required),
|
|
84
|
-
hasError: computed(() => props.hasError),
|
|
85
|
-
emit: emit,
|
|
86
|
-
});
|
|
87
|
-
|
|
88
57
|
const showPassword = ref(false);
|
|
89
58
|
|
|
90
|
-
function
|
|
91
|
-
|
|
92
|
-
emitUpdate(trim(value));
|
|
59
|
+
function onIconRightClick() {
|
|
60
|
+
showPassword.value = !showPassword.value;
|
|
93
61
|
}
|
|
94
62
|
|
|
95
63
|
function focus() {
|
|
@@ -100,6 +68,18 @@ function blur() {
|
|
|
100
68
|
input.value?.blur();
|
|
101
69
|
}
|
|
102
70
|
|
|
71
|
+
function onUpdateModelValue(value: string) {
|
|
72
|
+
emit('update:modelValue', value);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function onBlur() {
|
|
76
|
+
emit('blur');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function onFocus() {
|
|
80
|
+
emit('focus');
|
|
81
|
+
}
|
|
82
|
+
|
|
103
83
|
defineExpose({
|
|
104
84
|
focus,
|
|
105
85
|
blur,
|
|
@@ -2,6 +2,8 @@ import BaseRichText from './BaseRichText.vue';
|
|
|
2
2
|
import ShowValue from '@/../.storybook/components/ShowValue.vue';
|
|
3
3
|
import { createFieldStory } from '@/../.storybook/utils';
|
|
4
4
|
|
|
5
|
+
const sizes = ['xs', 'sm', 'md'];
|
|
6
|
+
|
|
5
7
|
const toolbarOptions = [
|
|
6
8
|
'full',
|
|
7
9
|
'essential',
|
|
@@ -28,6 +30,10 @@ export default {
|
|
|
28
30
|
placeholder: 'Describe your complete life in 4 sentences...',
|
|
29
31
|
},
|
|
30
32
|
argTypes: {
|
|
33
|
+
size: {
|
|
34
|
+
control: { type: 'select' },
|
|
35
|
+
options: sizes,
|
|
36
|
+
},
|
|
31
37
|
theme: {
|
|
32
38
|
control: { type: 'select' },
|
|
33
39
|
options: ['snow', 'bubble', ''],
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
class="base-rich-text relative"
|
|
4
|
-
:class="[
|
|
4
|
+
:class="[
|
|
5
|
+
hasErrorInternal ? 'error' : '',
|
|
6
|
+
sizeInternal == 'sm' ? 'base-rich-text-sm' : '',
|
|
7
|
+
sizeInternal == 'xs' ? 'base-rich-text-xs' : '',
|
|
8
|
+
]"
|
|
5
9
|
>
|
|
6
10
|
<quill-editor
|
|
7
11
|
:name="nameInternal"
|
|
@@ -25,6 +29,7 @@ import { useField } from '@/composables/field';
|
|
|
25
29
|
|
|
26
30
|
import { QuillEditor } from '@vueup/vue-quill';
|
|
27
31
|
import Delta from 'quill-delta';
|
|
32
|
+
import { Size } from '@/utils/sizes';
|
|
28
33
|
|
|
29
34
|
|
|
30
35
|
const props = defineProps({
|
|
@@ -38,6 +43,10 @@ const props = defineProps({
|
|
|
38
43
|
type: String as PropType<'' | 'snow' | 'bubble'>,
|
|
39
44
|
default: 'snow',
|
|
40
45
|
},
|
|
46
|
+
size: {
|
|
47
|
+
default: undefined,
|
|
48
|
+
type: String as PropType<Size>,
|
|
49
|
+
},
|
|
41
50
|
toolbar: {
|
|
42
51
|
type: [String, Array, Object] as PropType<
|
|
43
52
|
string | unknown[] | Record<string, any> | undefined
|
|
@@ -74,10 +83,11 @@ const props = defineProps({
|
|
|
74
83
|
|
|
75
84
|
const emit = defineEmits(['update:modelValue']);
|
|
76
85
|
|
|
77
|
-
const { nameInternal, requiredInternal, hasErrorInternal, emitUpdate } =
|
|
86
|
+
const { nameInternal, requiredInternal, hasErrorInternal, emitUpdate, sizeInternal } =
|
|
78
87
|
useField({
|
|
79
88
|
name: computed(() => props.name),
|
|
80
89
|
required: computed(() => props.required),
|
|
90
|
+
size: computed(() => props.size),
|
|
81
91
|
hasError: computed(() => props.hasError),
|
|
82
92
|
emit: emit,
|
|
83
93
|
});
|
|
@@ -209,6 +209,10 @@ const classes = computed(() => {
|
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
|
|
212
|
+
// For placeholder
|
|
213
|
+
|
|
214
|
+
const fontWeight = props.modelValue ? 'font-normal' : 'font-light';
|
|
215
|
+
|
|
212
216
|
const disabled = 'disabled:cursor-not-allowed disabled:text-slate-300 disabled:opacity-100';
|
|
213
217
|
const error = hasErrorInternal.value ? 'border-red-600' : 'border-slate-300';
|
|
214
218
|
const textColor = !props.modelValue && requiredInternal ? 'text-slate-400' : '';
|
|
@@ -222,6 +226,7 @@ const classes = computed(() => {
|
|
|
222
226
|
return twMerge([
|
|
223
227
|
base,
|
|
224
228
|
focusClass,
|
|
229
|
+
fontWeight,
|
|
225
230
|
disabled,
|
|
226
231
|
error,
|
|
227
232
|
textColor,
|
|
@@ -286,6 +286,7 @@ import SlotComponent from './SlotComponent';
|
|
|
286
286
|
import { useResizeObserver, useScroll } from '@vueuse/core';
|
|
287
287
|
import { debounce, isArray } from 'lodash';
|
|
288
288
|
import BaseSpinnerLarge from '../svg/BaseSpinnerLarge.vue';
|
|
289
|
+
import { Size } from '@/utils/sizes';
|
|
289
290
|
|
|
290
291
|
const checkboxStyle =
|
|
291
292
|
'disabled:bg-slate-100 group-hover:shadow-md disabled:border-slate-300 disabled:cursor-not-allowed duration-300 cursor-pointer focus:ring-blue-300 border border-slate-300 shadow h-[18px] w-[18px] rounded';
|
|
@@ -371,7 +372,7 @@ const props = defineProps({
|
|
|
371
372
|
type: Number,
|
|
372
373
|
},
|
|
373
374
|
size: {
|
|
374
|
-
type: String as PropType<
|
|
375
|
+
type: String as PropType<Size>,
|
|
375
376
|
default: 'md',
|
|
376
377
|
},
|
|
377
378
|
});
|
|
@@ -3,7 +3,7 @@ import BaseTagAutocomplete from './BaseTagAutocomplete.vue';
|
|
|
3
3
|
import ShowValue from '@/../.storybook/components/ShowValue.vue';
|
|
4
4
|
import BaseAppNotifications from './BaseAppNotifications.vue';
|
|
5
5
|
|
|
6
|
-
const sizes = ['xs', 'sm', '
|
|
6
|
+
const sizes = ['xs', 'sm', 'md'];
|
|
7
7
|
|
|
8
8
|
export default {
|
|
9
9
|
title: 'Form/BaseTagAutocomplete',
|
|
@@ -1,63 +1,44 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div ref="autocomplete">
|
|
3
|
-
<div
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
:
|
|
14
|
-
:remove-option="removeOption"
|
|
15
|
-
:disabled="disabled"
|
|
3
|
+
<div :class="wrapperClass">
|
|
4
|
+
<slot
|
|
5
|
+
name="items"
|
|
6
|
+
:items="normalizedModelValue"
|
|
7
|
+
:remove-option="removeOption"
|
|
8
|
+
:disabled="disabled"
|
|
9
|
+
>
|
|
10
|
+
<div
|
|
11
|
+
v-for="selection in normalizedModelValue"
|
|
12
|
+
:key="selection.value ? selection.value : 'null'"
|
|
13
|
+
:class="selectionClass(selection)"
|
|
16
14
|
>
|
|
17
|
-
<div
|
|
18
|
-
|
|
19
|
-
:key="selection.value ? selection.value : 'null'"
|
|
20
|
-
class="p-0.5"
|
|
21
|
-
>
|
|
22
|
-
<div
|
|
23
|
-
class="flex items-stretch rounded border"
|
|
24
|
-
:class="[
|
|
25
|
-
disabled ? 'cursor-not-allowed opacity-60' : '',
|
|
26
|
-
selectionClass(selection),
|
|
27
|
-
]"
|
|
28
|
-
>
|
|
29
|
-
<div :class="[selectionLabelClass]">
|
|
30
|
-
{{ selection.label }}
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<button
|
|
34
|
-
v-if="!disabled"
|
|
35
|
-
type="button"
|
|
36
|
-
class="flex shrink-0 appearance-none items-center justify-center border-0 bg-transparent pl-1 pr-3 text-xs outline-none"
|
|
37
|
-
@click="removeOption(selection)"
|
|
38
|
-
>
|
|
39
|
-
✕
|
|
40
|
-
</button>
|
|
41
|
-
</div>
|
|
15
|
+
<div>
|
|
16
|
+
{{ selection.label }}
|
|
42
17
|
</div>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
type="text"
|
|
50
|
-
:placeholder="placeholder ? placeholder : t('sui.select_an_item')"
|
|
51
|
-
class="w-full min-w-[50px] border-none p-0 pl-1 shadow-none outline-none focus:border-none focus:shadow-none focus:outline-none focus:ring-0 disabled:cursor-not-allowed"
|
|
52
|
-
:class="[inputClass]"
|
|
53
|
-
autocomplete="off"
|
|
54
|
-
:disabled="disabled"
|
|
55
|
-
@click="open"
|
|
56
|
-
@input="onTextInput"
|
|
57
|
-
@keydown="onTextKeydown"
|
|
18
|
+
|
|
19
|
+
<button
|
|
20
|
+
type="button"
|
|
21
|
+
tabindex="-1"
|
|
22
|
+
:class="selectionDeleteClasses"
|
|
23
|
+
@click="removeOption(selection)"
|
|
58
24
|
>
|
|
25
|
+
✕
|
|
26
|
+
</button>
|
|
59
27
|
</div>
|
|
60
|
-
</
|
|
28
|
+
</slot>
|
|
29
|
+
|
|
30
|
+
<input
|
|
31
|
+
ref="inputElement"
|
|
32
|
+
:value="keywords"
|
|
33
|
+
type="text"
|
|
34
|
+
:placeholder="placeholder ? placeholder : t('sui.select_an_item')"
|
|
35
|
+
:class="inputClasses"
|
|
36
|
+
autocomplete="off"
|
|
37
|
+
:disabled="disabled"
|
|
38
|
+
@focus="open"
|
|
39
|
+
@input="onTextInput"
|
|
40
|
+
@keydown="onTextKeydown"
|
|
41
|
+
>
|
|
61
42
|
</div>
|
|
62
43
|
|
|
63
44
|
<div class="relative">
|
|
@@ -116,7 +97,7 @@ import { useNotificationsStore } from '@/stores/notifications';
|
|
|
116
97
|
import BaseAutocompleteDrawer from './BaseAutocompleteDrawer.vue';
|
|
117
98
|
import { twMerge } from 'tailwind-merge';
|
|
118
99
|
import { t } from '@/i18n';
|
|
119
|
-
import { Size } from '@/utils/sizes';
|
|
100
|
+
import { Size, sizes } from '@/utils/sizes';
|
|
120
101
|
|
|
121
102
|
const notifications = useNotificationsStore();
|
|
122
103
|
|
|
@@ -141,6 +122,7 @@ const props = defineProps({
|
|
|
141
122
|
default: undefined,
|
|
142
123
|
type: String,
|
|
143
124
|
},
|
|
125
|
+
|
|
144
126
|
placeholder: {
|
|
145
127
|
default: undefined,
|
|
146
128
|
type: String,
|
|
@@ -178,7 +160,7 @@ const props = defineProps({
|
|
|
178
160
|
type: Boolean,
|
|
179
161
|
},
|
|
180
162
|
size: {
|
|
181
|
-
default:
|
|
163
|
+
default: undefined,
|
|
182
164
|
type: String as PropType<Size>,
|
|
183
165
|
},
|
|
184
166
|
dropdownShow: {
|
|
@@ -193,6 +175,10 @@ const props = defineProps({
|
|
|
193
175
|
default: '',
|
|
194
176
|
type: [String, Array] as PropType<string | string[]>,
|
|
195
177
|
},
|
|
178
|
+
visibleFocus: {
|
|
179
|
+
default: true,
|
|
180
|
+
type: Boolean,
|
|
181
|
+
},
|
|
196
182
|
});
|
|
197
183
|
|
|
198
184
|
const emit = defineEmits([
|
|
@@ -203,9 +189,10 @@ const emit = defineEmits([
|
|
|
203
189
|
'scrollBottom',
|
|
204
190
|
]);
|
|
205
191
|
|
|
206
|
-
const { hasErrorInternal, emitUpdate } = useField({
|
|
192
|
+
const { hasErrorInternal, emitUpdate, sizeInternal } = useField({
|
|
207
193
|
name: computed(() => props.name),
|
|
208
194
|
required: computed(() => props.required),
|
|
195
|
+
size: computed(() => props.size),
|
|
209
196
|
hasError: computed(() => props.hasError),
|
|
210
197
|
emit: emit,
|
|
211
198
|
});
|
|
@@ -218,6 +205,31 @@ const hasOptions = useHasOptions(
|
|
|
218
205
|
computed(() => true)
|
|
219
206
|
);
|
|
220
207
|
|
|
208
|
+
onMounted(() => {
|
|
209
|
+
window.addEventListener('keydown', onWindowKeydown);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
onBeforeUnmount(() => {
|
|
213
|
+
window.removeEventListener('keydown', onWindowKeydown);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
function onWindowKeydown(event: KeyboardEvent) {
|
|
217
|
+
|
|
218
|
+
if (!opened.value) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const key = event.key;
|
|
223
|
+
|
|
224
|
+
if (key === 'Tab') {
|
|
225
|
+
close();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (key === 'Escape') {
|
|
229
|
+
close();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
221
233
|
let openOfFocusTimeout = 0;
|
|
222
234
|
|
|
223
235
|
onMounted(() => {
|
|
@@ -283,6 +295,7 @@ function open() {
|
|
|
283
295
|
function close() {
|
|
284
296
|
shouldFilter.value = false;
|
|
285
297
|
opened.value = false;
|
|
298
|
+
selectionToDelete.value = null;
|
|
286
299
|
blur();
|
|
287
300
|
emit('close');
|
|
288
301
|
}
|
|
@@ -392,6 +405,11 @@ const attemptRemoveLastSelection = () => {
|
|
|
392
405
|
};
|
|
393
406
|
|
|
394
407
|
const removeOption = (option: NormalizedOption) => {
|
|
408
|
+
|
|
409
|
+
if (props.disabled) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
|
|
395
413
|
focus();
|
|
396
414
|
let newModelValue = cloneDeep(normalizedModelValue.value);
|
|
397
415
|
newModelValue = newModelValue.filter((v) => v.value != option.value);
|
|
@@ -401,49 +419,86 @@ const removeOption = (option: NormalizedOption) => {
|
|
|
401
419
|
// Element Classes
|
|
402
420
|
|
|
403
421
|
const wrapperClass = computed(() => {
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
422
|
+
const base = 'relative z-[1] input-rounded border bg-white flex flex-wrap';
|
|
423
|
+
const error = hasErrorInternal.value ? 'border-red-600' : 'border-slate-300'
|
|
424
|
+
const height = {
|
|
425
|
+
'xs': 'min-h-control-xs gap-0.5 p-0.5',
|
|
426
|
+
'sm': 'min-h-control-sm gap-0.5 p-0.5',
|
|
427
|
+
'md': 'min-h-control-md gap-1 p-1',
|
|
428
|
+
}[sizeInternal.value];
|
|
429
|
+
|
|
430
|
+
const focus = opened.value ? 'input-focus border-blue-300' : '';
|
|
431
|
+
|
|
432
|
+
return twMerge(base, error, height, focus, props.twContainer);
|
|
411
433
|
});
|
|
412
434
|
|
|
413
|
-
const
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
435
|
+
const innerHeight = computed(() => {
|
|
436
|
+
const height = {
|
|
437
|
+
'xs': 'h-[calc(theme(spacing.control-xs)_-_theme(spacing[0.5])_-_theme(spacing[0.5])_-_2px)]',
|
|
438
|
+
'sm': 'h-[calc(theme(spacing.control-sm)_-_theme(spacing[0.5])_-_theme(spacing[0.5])_-_2px)]',
|
|
439
|
+
'md': 'h-[calc(theme(spacing.control-md)_-_theme(spacing.1)_-_theme(spacing.1)_-_2px)]',
|
|
440
|
+
}[sizeInternal.value];
|
|
441
|
+
|
|
442
|
+
return height;
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
const inputClasses = computed(() => {
|
|
446
|
+
const base = 'grow min-w-[50px] py-0 border-none shadow-none outline-none bg-transparent';
|
|
447
|
+
const focus = 'focus:border-none focus:shadow-none focus:outline-none focus:ring-0';
|
|
448
|
+
const disabled = 'disabled:cursor-not-allowed';
|
|
449
|
+
const sizeConfig = sizes[sizeInternal.value];
|
|
450
|
+
|
|
451
|
+
const padding = {
|
|
452
|
+
'xs': 'pl-1.5',
|
|
453
|
+
'sm': 'pl-2',
|
|
454
|
+
'md': 'pl-2.5',
|
|
455
|
+
}[sizeInternal.value];
|
|
456
|
+
|
|
457
|
+
return [base, padding, innerHeight.value, focus, disabled, sizeConfig.fontSize];
|
|
422
458
|
});
|
|
423
459
|
|
|
424
460
|
const selectionClass = (selection: NormalizedOption): string => {
|
|
461
|
+
|
|
462
|
+
const base = 'flex items-center rounded border';
|
|
463
|
+
|
|
464
|
+
const fontSize = {
|
|
465
|
+
'xs': 'text-xs',
|
|
466
|
+
'sm': 'text-xs',
|
|
467
|
+
'md': 'text-sm',
|
|
468
|
+
}[sizeInternal.value];
|
|
469
|
+
|
|
470
|
+
const padding = {
|
|
471
|
+
'xs': 'pl-2',
|
|
472
|
+
'sm': 'pl-2',
|
|
473
|
+
'md': 'pl-3',
|
|
474
|
+
}[sizeInternal.value];
|
|
475
|
+
|
|
476
|
+
let color = 'bg-slate-200 border-slate-300';
|
|
477
|
+
|
|
425
478
|
if (
|
|
426
479
|
selectionToDelete.value &&
|
|
427
480
|
selectionToDelete.value.value == selection.value
|
|
428
481
|
) {
|
|
429
|
-
|
|
482
|
+
color = 'bg-red-200 border-red-300 text-red-800';
|
|
430
483
|
}
|
|
431
|
-
|
|
484
|
+
|
|
485
|
+
const disabled = props.disabled ? 'cursor-not-allowed opacity-60' : '';
|
|
486
|
+
|
|
487
|
+
return twMerge(base, innerHeight.value, padding, color, disabled, fontSize);
|
|
432
488
|
};
|
|
433
489
|
|
|
434
|
-
const
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
return classes;
|
|
490
|
+
const selectionDeleteClasses = computed(() => {
|
|
491
|
+
const base = 'flex shrink-0 appearance-none items-center justify-center border-0 bg-transparent outline-none';
|
|
492
|
+
|
|
493
|
+
const padding = {
|
|
494
|
+
'xs': 'pl-1 pr-2',
|
|
495
|
+
'sm': 'pl-1 pr-2',
|
|
496
|
+
'md': 'pl-1 pr-3',
|
|
497
|
+
}[sizeInternal.value];
|
|
498
|
+
|
|
499
|
+
const disabled = props.disabled ? 'cursor-not-allowed opacity-60' : '';
|
|
500
|
+
|
|
501
|
+
return twMerge(base, padding, disabled);
|
|
447
502
|
});
|
|
448
503
|
|
|
449
504
|
defineExpose({
|
|
@@ -3,10 +3,17 @@ import ShowValue from '@/../.storybook/components/ShowValue.vue';
|
|
|
3
3
|
import { createFieldStory } from '../../.storybook/utils';
|
|
4
4
|
import BaseAppNotifications from './BaseAppNotifications.vue';
|
|
5
5
|
|
|
6
|
+
const sizes = ['xs', 'sm', 'md'];
|
|
7
|
+
|
|
6
8
|
export default {
|
|
7
9
|
title: 'Form/BaseTagAutocompleteFetch',
|
|
8
10
|
component: BaseTagAutocompleteFetch,
|
|
9
|
-
argTypes: {
|
|
11
|
+
argTypes: {
|
|
12
|
+
size: {
|
|
13
|
+
control: { type: 'select' },
|
|
14
|
+
options: sizes,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
10
17
|
args: {
|
|
11
18
|
url: 'https://effettandem.com/api/content/articles',
|
|
12
19
|
labelKey: 'title',
|
|
@@ -56,6 +63,20 @@ Maximum.args = {
|
|
|
56
63
|
max: 3,
|
|
57
64
|
};
|
|
58
65
|
|
|
66
|
+
export const Sizes = (args) => ({
|
|
67
|
+
components: { BaseTagAutocompleteFetch },
|
|
68
|
+
setup() {
|
|
69
|
+
const value = ref([]);
|
|
70
|
+
return { args, sizes, value };
|
|
71
|
+
},
|
|
72
|
+
template: `
|
|
73
|
+
<div v-for="size in sizes" class="mb-1">
|
|
74
|
+
<p class="text-xs text-slate-600 leading-tight">{{ size }}</p>
|
|
75
|
+
<BaseTagAutocompleteFetch v-model="value" v-bind="args" :size="size"></BaseTagAutocompleteFetch>
|
|
76
|
+
</div>
|
|
77
|
+
`,
|
|
78
|
+
});
|
|
79
|
+
|
|
59
80
|
export const SlotOption = (args) => {
|
|
60
81
|
return {
|
|
61
82
|
components: { BaseTagAutocompleteFetch },
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { createFieldStory } from '../../.storybook/utils';
|
|
2
2
|
import BaseTextarea from './BaseTextarea.vue';
|
|
3
3
|
|
|
4
|
+
const sizes = ['xs', 'sm', 'md'];
|
|
5
|
+
|
|
4
6
|
export default {
|
|
5
7
|
title: 'Form/BaseTextarea',
|
|
6
8
|
component: BaseTextarea,
|
|
7
9
|
args: {
|
|
8
10
|
placeholder: 'Describe your complete life in 4 sentences...',
|
|
9
11
|
},
|
|
12
|
+
argTypes: {
|
|
13
|
+
size: {
|
|
14
|
+
control: { type: 'select' },
|
|
15
|
+
options: sizes,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
10
18
|
};
|
|
11
19
|
|
|
12
20
|
const Template = (args) => ({
|
|
@@ -42,6 +50,23 @@ export const Field = createFieldStory({
|
|
|
42
50
|
label: 'Biography',
|
|
43
51
|
});
|
|
44
52
|
|
|
53
|
+
const TemplateSizes = (args) => ({
|
|
54
|
+
components: { BaseTextarea },
|
|
55
|
+
setup() {
|
|
56
|
+
const value = ref(null);
|
|
57
|
+
const sizes = ['xs', 'sm', 'md'];
|
|
58
|
+
return { args, value, sizes };
|
|
59
|
+
},
|
|
60
|
+
template: `
|
|
61
|
+
<div v-for="size in sizes" :key="size" class="mb-4">
|
|
62
|
+
<p class="text-xs text-slate-600 leading-tight mb-1">{{ size }}</p>
|
|
63
|
+
<BaseTextarea v-model="value" v-bind="args" :size="size" class="w-full"></BaseTextarea>
|
|
64
|
+
</div>
|
|
65
|
+
`,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export const Sizes = TemplateSizes.bind({});
|
|
69
|
+
|
|
45
70
|
const FocusTemplate = (args) => ({
|
|
46
71
|
components: { BaseTextarea },
|
|
47
72
|
setup() {
|