@saasmakers/ui 0.1.71 → 0.1.73
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/app/components/bases/BaseChart.vue +0 -1
- package/app/components/bases/BaseTags.vue +13 -13
- package/app/components/fields/FieldCheckbox.vue +3 -24
- package/app/components/fields/FieldDays.vue +6 -6
- package/app/components/fields/FieldEmojis.vue +4 -5
- package/app/components/fields/FieldInput.vue +10 -20
- package/app/components/fields/FieldSelect.vue +9 -9
- package/app/components/fields/FieldTabs.vue +12 -10
- package/app/components/fields/FieldTextarea.vue +8 -28
- package/app/components/fields/FieldTime.vue +6 -12
- package/app/composables/useChartist.ts +37 -26
- package/app/types/fields.d.ts +2 -2
- package/app/types/global.d.ts +1 -1
- package/nuxt.config.ts +3 -3
- package/package.json +2 -3
- package/uno.config.ts +3 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { BaseTags } from '../../types/bases'
|
|
3
3
|
|
|
4
|
-
const props = withDefaults(defineProps<BaseTags
|
|
4
|
+
const props = withDefaults(defineProps<Omit<BaseTags, 'value'>>(), {
|
|
5
5
|
active: false,
|
|
6
6
|
clickable: true,
|
|
7
7
|
draggable: false,
|
|
@@ -14,21 +14,21 @@ const props = withDefaults(defineProps<BaseTags>(), {
|
|
|
14
14
|
selectableUnique: false,
|
|
15
15
|
size: 'base',
|
|
16
16
|
tags: () => [],
|
|
17
|
-
value: () => [],
|
|
18
17
|
wrap: false,
|
|
19
18
|
})
|
|
20
19
|
|
|
21
20
|
const emit = defineEmits<{
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
'update:modelValue': [value: (number | string)[]]
|
|
21
|
+
attach: [event: MouseEvent, tagId?: number | string]
|
|
22
|
+
back: [event: MouseEvent]
|
|
23
|
+
click: [event: MouseEvent]
|
|
24
|
+
create: [event: FocusEvent | KeyboardEvent, name: string]
|
|
25
|
+
detach: [event: MouseEvent, tagId?: number | string]
|
|
26
|
+
remove: [event: MouseEvent, tagId?: number | string]
|
|
27
|
+
update: [event: FocusEvent | KeyboardEvent, name: string, tagId?: number | string]
|
|
30
28
|
}>()
|
|
31
29
|
|
|
30
|
+
const modelValue = defineModel<(number | string)[]>({ default: () => [] })
|
|
31
|
+
|
|
32
32
|
const keyForTagCreation = ref(Date.now())
|
|
33
33
|
const keyForTagUpdate = ref(Date.now())
|
|
34
34
|
const root = ref<HTMLDivElement>()
|
|
@@ -91,7 +91,7 @@ function onShowAllTags() {
|
|
|
91
91
|
|
|
92
92
|
function onTagClick(event: MouseEvent, tagId?: number | string) {
|
|
93
93
|
if (props.selectable && tagId) {
|
|
94
|
-
let value = [...
|
|
94
|
+
let value = [...modelValue.value]
|
|
95
95
|
|
|
96
96
|
if (value.includes(tagId)) {
|
|
97
97
|
value.splice(value.indexOf(tagId), 1)
|
|
@@ -106,7 +106,7 @@ function onTagClick(event: MouseEvent, tagId?: number | string) {
|
|
|
106
106
|
emit('attach', event, tagId)
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
modelValue.value = value
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -184,7 +184,7 @@ function onRemoveTag(event: MouseEvent, tagId?: number | string) {
|
|
|
184
184
|
<BaseTag
|
|
185
185
|
:id="tag.id || tagIndex"
|
|
186
186
|
:key="`${tag.id}_${tagIndex}`"
|
|
187
|
-
:active="tag.id &&
|
|
187
|
+
:active="tag.id && modelValue.includes(tag.id) || tag.active"
|
|
188
188
|
:avatar="tag.avatar"
|
|
189
189
|
:circle="tag.circle"
|
|
190
190
|
:clickable="clickable"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { FieldCheckbox } from '../../types/fields'
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
withDefaults(defineProps<Omit<FieldCheckbox, 'modelValue'>>(), {
|
|
5
5
|
description: '',
|
|
6
6
|
disabled: false,
|
|
7
7
|
fullWidth: false,
|
|
@@ -10,7 +10,6 @@ const props = withDefaults(defineProps<FieldCheckbox>(), {
|
|
|
10
10
|
labelIcon: undefined,
|
|
11
11
|
lineThrough: false,
|
|
12
12
|
loading: false,
|
|
13
|
-
modelValue: false,
|
|
14
13
|
required: false,
|
|
15
14
|
size: 'base',
|
|
16
15
|
truncate: false,
|
|
@@ -18,27 +17,9 @@ const props = withDefaults(defineProps<FieldCheckbox>(), {
|
|
|
18
17
|
validation: undefined,
|
|
19
18
|
})
|
|
20
19
|
|
|
21
|
-
const
|
|
22
|
-
'update:modelValue': [value: boolean ]
|
|
23
|
-
}>()
|
|
20
|
+
const modelValue = defineModel<FieldCheckbox['modelValue']>({ default: false })
|
|
24
21
|
|
|
25
|
-
const input = ref<HTMLInputElement>()
|
|
26
22
|
const uuid = ref(`${Math.floor((1 + Math.random()) * 0x100000)}`)
|
|
27
|
-
|
|
28
|
-
const value = computed({
|
|
29
|
-
get() {
|
|
30
|
-
return props.modelValue
|
|
31
|
-
},
|
|
32
|
-
set(value) {
|
|
33
|
-
emit('update:modelValue', value || false)
|
|
34
|
-
},
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
function onFieldChange(event: Event) {
|
|
38
|
-
const value = (event.target as HTMLInputElement).checked
|
|
39
|
-
|
|
40
|
-
emit('update:modelValue', value)
|
|
41
|
-
}
|
|
42
23
|
</script>
|
|
43
24
|
|
|
44
25
|
<template>
|
|
@@ -51,8 +32,7 @@ function onFieldChange(event: Event) {
|
|
|
51
32
|
<input
|
|
52
33
|
v-if="!loading"
|
|
53
34
|
:id="uuid"
|
|
54
|
-
|
|
55
|
-
v-model="value"
|
|
35
|
+
v-model="modelValue"
|
|
56
36
|
class="cursor-pointer border border-gray-300 rounded-lg accent-indigo-700 transition-shadow flex-initial dark:border-gray-700 focus:border-gray-500 hover:border-gray-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-indigo-500/40 dark:focus:border-gray-500 dark:hover:border-gray-600"
|
|
57
37
|
:class="{
|
|
58
38
|
'disabled:opacity-50 disabled:cursor-not-allowed': disabled,
|
|
@@ -64,7 +44,6 @@ function onFieldChange(event: Event) {
|
|
|
64
44
|
}"
|
|
65
45
|
:disabled="disabled"
|
|
66
46
|
type="checkbox"
|
|
67
|
-
@change="onFieldChange"
|
|
68
47
|
>
|
|
69
48
|
|
|
70
49
|
<BaseSpinner
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { FieldDays } from '../../types/fields'
|
|
3
3
|
|
|
4
|
-
const props = withDefaults(defineProps<FieldDays>(), { modelValue: () => [] })
|
|
5
|
-
|
|
6
4
|
const emit = defineEmits<{
|
|
7
|
-
|
|
8
|
-
'update:modelValue': [value: number[]]
|
|
5
|
+
change: [event: MouseEvent, value: number[]]
|
|
9
6
|
}>()
|
|
10
7
|
|
|
11
8
|
const { t } = useI18n()
|
|
12
9
|
|
|
10
|
+
const modelValue = defineModel<FieldDays['modelValue']>({ default: () => [] })
|
|
11
|
+
|
|
13
12
|
const daysToDisplay = computed(() => {
|
|
14
13
|
return [
|
|
15
14
|
{
|
|
@@ -44,12 +43,13 @@ const daysToDisplay = computed(() => {
|
|
|
44
43
|
})
|
|
45
44
|
|
|
46
45
|
function onUpdateDays(event: MouseEvent, day: number) {
|
|
47
|
-
const days = [...
|
|
46
|
+
const days = [...modelValue.value]
|
|
48
47
|
|
|
49
48
|
days.includes(day) ? days.splice(days.indexOf(day), 1) : days.push(day)
|
|
50
49
|
|
|
50
|
+
modelValue.value = days
|
|
51
|
+
|
|
51
52
|
emit('change', event, days)
|
|
52
|
-
emit('update:modelValue', days)
|
|
53
53
|
}
|
|
54
54
|
</script>
|
|
55
55
|
|
|
@@ -3,16 +3,15 @@ import type { FieldEmojis } from '../../types/fields'
|
|
|
3
3
|
import { emojis } from '@saasmakers/shared'
|
|
4
4
|
import { refDebounced } from '@vueuse/core'
|
|
5
5
|
|
|
6
|
-
withDefaults(defineProps<FieldEmojis>(), { modelValue: undefined })
|
|
7
|
-
|
|
8
6
|
const emit = defineEmits<{
|
|
9
|
-
|
|
10
|
-
'update:modelValue': [value: string]
|
|
7
|
+
click: [event: MouseEvent, emoji: string]
|
|
11
8
|
}>()
|
|
12
9
|
|
|
13
10
|
const { locale, t } = useI18n()
|
|
14
11
|
const { normalizeText } = useLayerUtils()
|
|
15
12
|
|
|
13
|
+
const modelValue = defineModel<FieldEmojis['modelValue']>({ default: '' })
|
|
14
|
+
|
|
16
15
|
const searchRaw = ref('')
|
|
17
16
|
const searchQuery = refDebounced(searchRaw, 250)
|
|
18
17
|
|
|
@@ -43,7 +42,7 @@ const emojisFiltered = computed(() => {
|
|
|
43
42
|
|
|
44
43
|
function onEmojiClick(event: MouseEvent, emoji?: string) {
|
|
45
44
|
emit('click', event, emoji || '')
|
|
46
|
-
|
|
45
|
+
modelValue.value = emoji || ''
|
|
47
46
|
}
|
|
48
47
|
</script>
|
|
49
48
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { FieldInput } from '../../types/fields'
|
|
3
3
|
|
|
4
|
-
const props = withDefaults(defineProps<FieldInput
|
|
4
|
+
const props = withDefaults(defineProps<Omit<FieldInput, 'modelValue'>>(), {
|
|
5
5
|
alignment: 'left',
|
|
6
6
|
autocomplete: true,
|
|
7
7
|
autofocus: false,
|
|
@@ -18,7 +18,6 @@ const props = withDefaults(defineProps<FieldInput>(), {
|
|
|
18
18
|
lowercaseOnly: false,
|
|
19
19
|
max: undefined,
|
|
20
20
|
min: undefined,
|
|
21
|
-
modelValue: '',
|
|
22
21
|
placeholder: '',
|
|
23
22
|
required: false,
|
|
24
23
|
size: 'base',
|
|
@@ -28,11 +27,10 @@ const props = withDefaults(defineProps<FieldInput>(), {
|
|
|
28
27
|
})
|
|
29
28
|
|
|
30
29
|
const emit = defineEmits<{
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
'update:modelValue': [value: string ]
|
|
30
|
+
blur: [event: FocusEvent]
|
|
31
|
+
focus: [event: FocusEvent]
|
|
32
|
+
keyup: [event: KeyboardEvent, value: string ]
|
|
33
|
+
submit: [event: KeyboardEvent, value: string ]
|
|
36
34
|
}>()
|
|
37
35
|
|
|
38
36
|
defineSlots<{
|
|
@@ -41,6 +39,8 @@ defineSlots<{
|
|
|
41
39
|
label?: () => VNode[]
|
|
42
40
|
}>()
|
|
43
41
|
|
|
42
|
+
const modelValue = defineModel<FieldInput['modelValue']>({ default: '' })
|
|
43
|
+
|
|
44
44
|
const input = ref<HTMLInputElement>()
|
|
45
45
|
const uuid = ref(`${Math.floor((1 + Math.random()) * 0x100000)}`)
|
|
46
46
|
|
|
@@ -52,15 +52,6 @@ onMounted(() => {
|
|
|
52
52
|
}
|
|
53
53
|
})
|
|
54
54
|
|
|
55
|
-
const value = computed({
|
|
56
|
-
get() {
|
|
57
|
-
return props.modelValue
|
|
58
|
-
},
|
|
59
|
-
set(value) {
|
|
60
|
-
emit('update:modelValue', value || '')
|
|
61
|
-
},
|
|
62
|
-
})
|
|
63
|
-
|
|
64
55
|
function blur() {
|
|
65
56
|
if (input.value) {
|
|
66
57
|
input.value.blur()
|
|
@@ -92,7 +83,7 @@ function onFieldInput(event: Event) {
|
|
|
92
83
|
value = value.toString().toLowerCase()
|
|
93
84
|
}
|
|
94
85
|
|
|
95
|
-
|
|
86
|
+
modelValue.value = value
|
|
96
87
|
}
|
|
97
88
|
|
|
98
89
|
function onFieldKeyDown(event: KeyboardEvent) {
|
|
@@ -102,7 +93,7 @@ function onFieldKeyDown(event: KeyboardEvent) {
|
|
|
102
93
|
blur()
|
|
103
94
|
}
|
|
104
95
|
|
|
105
|
-
else if (event.key === 'Enter' &&
|
|
96
|
+
else if (event.key === 'Enter' && modelValue.value) {
|
|
106
97
|
emit('submit', event, value)
|
|
107
98
|
}
|
|
108
99
|
|
|
@@ -120,7 +111,6 @@ function onFieldKeyDown(event: KeyboardEvent) {
|
|
|
120
111
|
emit('keyup', event, value)
|
|
121
112
|
}
|
|
122
113
|
|
|
123
|
-
// Expose
|
|
124
114
|
defineExpose({ focus })
|
|
125
115
|
</script>
|
|
126
116
|
|
|
@@ -160,7 +150,6 @@ defineExpose({ focus })
|
|
|
160
150
|
<input
|
|
161
151
|
:id="uuid"
|
|
162
152
|
ref="input"
|
|
163
|
-
v-model="value"
|
|
164
153
|
:autocomplete="autocomplete ? 'on' : 'off'"
|
|
165
154
|
class="h-full w-full flex-1 appearance-none items-center rounded-lg outline-none placeholder-gray-600 dark:placeholder-gray-400 focus:placeholder-gray-900 hover:placeholder-gray-900 dark:focus:placeholder-gray-100 dark:hover:placeholder-gray-100"
|
|
166
155
|
:class="{
|
|
@@ -190,6 +179,7 @@ defineExpose({ focus })
|
|
|
190
179
|
:placeholder="placeholder"
|
|
191
180
|
spellcheck="false"
|
|
192
181
|
:type="type"
|
|
182
|
+
:value="modelValue"
|
|
193
183
|
@blur="onFieldBlur"
|
|
194
184
|
@focus="onFieldFocus"
|
|
195
185
|
@input="onFieldInput"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { FieldSelect, FieldSelectOption } from '../../types/fields'
|
|
3
3
|
import { vOnClickOutside } from '@vueuse/components'
|
|
4
4
|
|
|
5
|
-
const props = withDefaults(defineProps<FieldSelect
|
|
5
|
+
const props = withDefaults(defineProps<Omit<FieldSelect, 'modelValue'>>(), {
|
|
6
6
|
border: 'full',
|
|
7
7
|
caret: true,
|
|
8
8
|
columns: () => [],
|
|
@@ -13,7 +13,6 @@ const props = withDefaults(defineProps<FieldSelect>(), {
|
|
|
13
13
|
label: '',
|
|
14
14
|
labelIcon: undefined,
|
|
15
15
|
maxHeight: 'xs',
|
|
16
|
-
modelValue: undefined,
|
|
17
16
|
openOnHover: false,
|
|
18
17
|
options: () => [],
|
|
19
18
|
padding: true,
|
|
@@ -24,15 +23,16 @@ const props = withDefaults(defineProps<FieldSelect>(), {
|
|
|
24
23
|
})
|
|
25
24
|
|
|
26
25
|
const emit = defineEmits<{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
'update:modelValue': [value: string]
|
|
26
|
+
change: [event: MouseEvent, value: string]
|
|
27
|
+
click: [event: MouseEvent, value: string]
|
|
28
|
+
optionClick: [event: MouseEvent, value: string]
|
|
31
29
|
}>()
|
|
32
30
|
|
|
33
31
|
const { getIcon } = useLayerIcons()
|
|
34
32
|
const { fadeIn } = useMotion()
|
|
35
33
|
|
|
34
|
+
const modelValue = defineModel<FieldSelect['modelValue']>({ default: '' })
|
|
35
|
+
|
|
36
36
|
const opened = ref(false)
|
|
37
37
|
const uuid = ref(`${Math.floor((1 + Math.random()) * 0x100000)}`)
|
|
38
38
|
|
|
@@ -66,7 +66,7 @@ const computedOptions = computed(() => {
|
|
|
66
66
|
|
|
67
67
|
const selectedOption = computed(() => {
|
|
68
68
|
return computedOptions.value.find((option) => {
|
|
69
|
-
return option.value ===
|
|
69
|
+
return option.value === modelValue.value
|
|
70
70
|
})
|
|
71
71
|
})
|
|
72
72
|
|
|
@@ -75,9 +75,9 @@ function reset() {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function selectOption(event: MouseEvent, value: string) {
|
|
78
|
-
|
|
79
|
-
emit('update:modelValue', value)
|
|
78
|
+
modelValue.value = value
|
|
80
79
|
|
|
80
|
+
emit('change', event, value)
|
|
81
81
|
reset()
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
import type { FieldTabs, FieldTabsAction } from '../../types/fields'
|
|
3
3
|
import { NuxtLinkLocale } from '#components'
|
|
4
4
|
|
|
5
|
-
const props = withDefaults(defineProps<FieldTabs
|
|
5
|
+
const props = withDefaults(defineProps<Omit<FieldTabs, 'modelValue'>>(), {
|
|
6
6
|
minimizeOnMobile: false,
|
|
7
|
-
modelValue: undefined,
|
|
8
7
|
multiple: false,
|
|
9
8
|
size: 'base',
|
|
10
9
|
tabs: undefined,
|
|
@@ -12,36 +11,39 @@ const props = withDefaults(defineProps<FieldTabs>(), {
|
|
|
12
11
|
})
|
|
13
12
|
|
|
14
13
|
const emit = defineEmits<{
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
'update:modelValue': [value?: Array<number | string> | number | string]
|
|
14
|
+
change: [event: MouseEvent, tabValue: number | string, action: FieldTabsAction, activeTabs: Array<number | string>]
|
|
15
|
+
click: [event: MouseEvent, tabValue: number | string, activeTabs: Array<number | string>]
|
|
18
16
|
}>()
|
|
19
17
|
|
|
18
|
+
const modelValue = defineModel<FieldTabs['modelValue']>({ default: () => [] })
|
|
19
|
+
|
|
20
20
|
function onTabClick(event: MouseEvent, tabValue: number | string) {
|
|
21
21
|
let activeTabs = [tabValue]
|
|
22
22
|
|
|
23
23
|
// When multiple values are not allowed and tab is not already active
|
|
24
|
-
if (!props.multiple &&
|
|
24
|
+
if (!props.multiple && modelValue.value !== tabValue) {
|
|
25
25
|
emit('change', event, tabValue, 'added', activeTabs)
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// When multiple values are allowed
|
|
29
29
|
if (props.multiple) {
|
|
30
30
|
// Remove the tab when already active
|
|
31
|
-
if (Array.isArray(
|
|
32
|
-
activeTabs =
|
|
31
|
+
if (Array.isArray(modelValue.value) && modelValue.value.includes(tabValue)) {
|
|
32
|
+
activeTabs = modelValue.value.filter(item => item !== tabValue)
|
|
33
33
|
|
|
34
34
|
emit('change', event, tabValue, 'removed', activeTabs)
|
|
35
35
|
}
|
|
36
36
|
// Push the tab when not already active
|
|
37
37
|
else {
|
|
38
|
-
activeTabs = Array.isArray(
|
|
38
|
+
activeTabs = Array.isArray(modelValue.value) ? [...modelValue.value, tabValue] : [tabValue]
|
|
39
|
+
|
|
39
40
|
emit('change', event, tabValue, 'added', activeTabs)
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
modelValue.value = props.multiple ? activeTabs : tabValue
|
|
45
|
+
|
|
43
46
|
emit('click', event, tabValue, activeTabs)
|
|
44
|
-
emit('update:modelValue', props.multiple ? activeTabs : tabValue)
|
|
45
47
|
}
|
|
46
48
|
</script>
|
|
47
49
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { FieldTextarea } from '../../types/fields'
|
|
3
3
|
|
|
4
|
-
const props = withDefaults(defineProps<FieldTextarea
|
|
4
|
+
const props = withDefaults(defineProps<Omit<FieldTextarea, 'modelValue'>>(), {
|
|
5
5
|
autofocus: false,
|
|
6
6
|
background: 'gray',
|
|
7
7
|
border: true,
|
|
@@ -12,7 +12,6 @@ const props = withDefaults(defineProps<FieldTextarea>(), {
|
|
|
12
12
|
label: '',
|
|
13
13
|
labelIcon: undefined,
|
|
14
14
|
loading: false,
|
|
15
|
-
modelValue: '',
|
|
16
15
|
padding: true,
|
|
17
16
|
placeholder: '',
|
|
18
17
|
required: false,
|
|
@@ -23,25 +22,17 @@ const props = withDefaults(defineProps<FieldTextarea>(), {
|
|
|
23
22
|
})
|
|
24
23
|
|
|
25
24
|
const emit = defineEmits<{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
'update:modelValue': [value: string]
|
|
25
|
+
blur: [event: FocusEvent, value: string]
|
|
26
|
+
click: [event: MouseEvent, value: string]
|
|
29
27
|
}>()
|
|
30
28
|
|
|
29
|
+
const modelValue = defineModel<FieldTextarea['modelValue']>({ default: '' })
|
|
30
|
+
|
|
31
31
|
const textarea = ref<HTMLTextAreaElement>()
|
|
32
32
|
const uuid = ref(`${Math.floor((1 + Math.random()) * 0x100000)}`)
|
|
33
33
|
|
|
34
34
|
const { isDesktopBrowser } = useDevice()
|
|
35
35
|
|
|
36
|
-
const value = computed({
|
|
37
|
-
get() {
|
|
38
|
-
return `${props.modelValue}`
|
|
39
|
-
},
|
|
40
|
-
set(value) {
|
|
41
|
-
emit('update:modelValue', value)
|
|
42
|
-
},
|
|
43
|
-
})
|
|
44
|
-
|
|
45
36
|
onMounted(() => {
|
|
46
37
|
if (props.autofocus && textarea.value && isDesktopBrowser.value) {
|
|
47
38
|
textarea.value.focus()
|
|
@@ -49,21 +40,11 @@ onMounted(() => {
|
|
|
49
40
|
})
|
|
50
41
|
|
|
51
42
|
function onFieldBlur(event: FocusEvent) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
emit('blur', event, value)
|
|
43
|
+
emit('blur', event, modelValue.value || '')
|
|
55
44
|
}
|
|
56
45
|
|
|
57
46
|
function onFieldClick(event: MouseEvent) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
emit('click', event, value)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function onFieldInput() {
|
|
64
|
-
const value = textarea.value?.value || ''
|
|
65
|
-
|
|
66
|
-
emit('update:modelValue', value)
|
|
47
|
+
emit('click', event, modelValue.value || '')
|
|
67
48
|
}
|
|
68
49
|
</script>
|
|
69
50
|
|
|
@@ -86,7 +67,7 @@ function onFieldInput() {
|
|
|
86
67
|
<textarea
|
|
87
68
|
:id="uuid"
|
|
88
69
|
ref="textarea"
|
|
89
|
-
v-model="
|
|
70
|
+
v-model="modelValue"
|
|
90
71
|
v-bind="{ 'data-enable-grammarly': 'false' }"
|
|
91
72
|
class="w-full flex-1 appearance-none rounded-lg text-gray-900 font-medium tracking-tight uppercase outline-none dark:text-gray-100 placeholder-gray-600 dark:placeholder-gray-400 focus:placeholder-gray-900 hover:placeholder-gray-900 dark:focus:placeholder-gray-100 dark:hover:placeholder-gray-100"
|
|
92
73
|
:class="{
|
|
@@ -110,7 +91,6 @@ function onFieldInput() {
|
|
|
110
91
|
spellcheck="false"
|
|
111
92
|
@blur="onFieldBlur"
|
|
112
93
|
@click="onFieldClick"
|
|
113
|
-
@input="onFieldInput"
|
|
114
94
|
/>
|
|
115
95
|
|
|
116
96
|
<FieldMessage
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
import type { FieldTime } from '../../types/fields'
|
|
3
3
|
|
|
4
|
-
const props = withDefaults(defineProps<FieldTime
|
|
4
|
+
const props = withDefaults(defineProps<Omit<FieldTime, 'modelValue'>>(), {
|
|
5
5
|
background: 'gray',
|
|
6
6
|
description: '',
|
|
7
7
|
disabled: false,
|
|
@@ -10,7 +10,6 @@ const props = withDefaults(defineProps<FieldTime>(), {
|
|
|
10
10
|
id: undefined,
|
|
11
11
|
label: '',
|
|
12
12
|
labelIcon: undefined,
|
|
13
|
-
modelValue: '',
|
|
14
13
|
name: undefined,
|
|
15
14
|
required: false,
|
|
16
15
|
size: 'base',
|
|
@@ -18,21 +17,16 @@ const props = withDefaults(defineProps<FieldTime>(), {
|
|
|
18
17
|
})
|
|
19
18
|
|
|
20
19
|
const emit = defineEmits<{
|
|
21
|
-
|
|
22
|
-
'update:modelValue': [value: string, name?: string]
|
|
20
|
+
blur: [event: FocusEvent, value: string, name?: string]
|
|
23
21
|
}>()
|
|
24
22
|
|
|
23
|
+
const modelValue = defineModel<FieldTime['modelValue']>({ default: '' })
|
|
24
|
+
|
|
25
25
|
const root = ref<HTMLDivElement>()
|
|
26
26
|
const uuid = ref(`${Math.floor((1 + Math.random()) * 0x100000)}`)
|
|
27
27
|
|
|
28
28
|
function onFieldBlur(event: FocusEvent) {
|
|
29
|
-
emit('blur', event,
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function onFieldInput() {
|
|
33
|
-
const value = root.value?.querySelector('input')?.value || ''
|
|
34
|
-
|
|
35
|
-
emit('update:modelValue', value, props.name)
|
|
29
|
+
emit('blur', event, modelValue.value, props.name)
|
|
36
30
|
}
|
|
37
31
|
</script>
|
|
38
32
|
|
|
@@ -52,6 +46,7 @@ function onFieldInput() {
|
|
|
52
46
|
<div class="item-center h-[42px] flex overflow-hidden border border-gray-200 rounded-lg pl-3 pr-2 dark:border-gray-800 focus-within:border-gray-400 hover:border-gray-300 dark:focus-within:border-gray-600 dark:hover:border-gray-700">
|
|
53
47
|
<input
|
|
54
48
|
:id="`${id}`"
|
|
49
|
+
v-model="modelValue"
|
|
55
50
|
class="text-sm outline-none"
|
|
56
51
|
:class="{
|
|
57
52
|
'bg-gray-100 dark:bg-gray-900': background === 'gray',
|
|
@@ -59,7 +54,6 @@ function onFieldInput() {
|
|
|
59
54
|
}"
|
|
60
55
|
type="time"
|
|
61
56
|
@blur="onFieldBlur"
|
|
62
|
-
@input="onFieldInput"
|
|
63
57
|
>
|
|
64
58
|
</div>
|
|
65
59
|
|
|
@@ -1,36 +1,42 @@
|
|
|
1
|
+
import type { AreaDrawEvent, BarChartOptions, BarDrawEvent, BaseChart, DrawEvent, LineDrawEvent, Options } from 'chartist'
|
|
2
|
+
import { easings } from 'chartist'
|
|
3
|
+
|
|
1
4
|
export default function useChartist() {
|
|
5
|
+
type EasingType = keyof typeof easings | number[]
|
|
6
|
+
|
|
2
7
|
const progressiveLinePlugin = (params: {
|
|
3
8
|
animateArea?: boolean
|
|
4
9
|
delay?: number
|
|
5
10
|
duration?: number
|
|
6
|
-
easing?:
|
|
11
|
+
easing?: EasingType
|
|
7
12
|
stagger?: number
|
|
8
13
|
} = {}) => {
|
|
9
14
|
const {
|
|
10
15
|
animateArea = true,
|
|
11
16
|
delay = 0,
|
|
12
17
|
duration = 500,
|
|
13
|
-
easing =
|
|
18
|
+
easing = easings.easeOutQuart,
|
|
14
19
|
stagger = 0,
|
|
15
20
|
} = params
|
|
16
21
|
|
|
17
|
-
return (chart:
|
|
18
|
-
chart.on('draw', (ctx:
|
|
22
|
+
return (chart: BaseChart) => {
|
|
23
|
+
chart.on('draw', (ctx: DrawEvent) => {
|
|
19
24
|
const begin = delay + (stagger ? stagger * (ctx.seriesIndex ?? 0) : 0)
|
|
20
25
|
|
|
21
26
|
// Animation for line charts
|
|
22
27
|
if (ctx.type === 'line') {
|
|
23
|
-
const
|
|
28
|
+
const lineCtx = ctx as LineDrawEvent
|
|
29
|
+
const node = lineCtx.element.getNode<SVGPathElement>()
|
|
24
30
|
const length = node.getTotalLength()
|
|
25
31
|
|
|
26
32
|
// Set the stroke dasharray and dashoffset
|
|
27
|
-
|
|
33
|
+
lineCtx.element.attr({
|
|
28
34
|
'stroke-dasharray': `${length}px ${length}px`,
|
|
29
35
|
'stroke-dashoffset': `${length}px`,
|
|
30
36
|
})
|
|
31
37
|
|
|
32
38
|
// Animate the stroke dashoffset to 0
|
|
33
|
-
|
|
39
|
+
lineCtx.element.animate({
|
|
34
40
|
'stroke-dashoffset': {
|
|
35
41
|
begin,
|
|
36
42
|
dur: duration,
|
|
@@ -42,67 +48,72 @@ export default function useChartist() {
|
|
|
42
48
|
}, false)
|
|
43
49
|
|
|
44
50
|
// Clean up the dash attributes after it finishes
|
|
45
|
-
const total = delay + duration + (stagger ? stagger * (
|
|
51
|
+
const total = delay + duration + (stagger ? stagger * (lineCtx.seriesIndex ?? 0) : 0)
|
|
46
52
|
|
|
47
53
|
window.setTimeout(() => {
|
|
48
|
-
|
|
49
|
-
'stroke-dasharray':
|
|
50
|
-
'stroke-dashoffset':
|
|
54
|
+
lineCtx.element.attr({
|
|
55
|
+
'stroke-dasharray': undefined,
|
|
56
|
+
'stroke-dashoffset': undefined,
|
|
51
57
|
})
|
|
52
58
|
}, total + 30)
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
// Animation for area charts
|
|
56
62
|
if (animateArea && ctx.type === 'area') {
|
|
57
|
-
ctx
|
|
63
|
+
const areaCtx = ctx as AreaDrawEvent
|
|
64
|
+
|
|
65
|
+
areaCtx.element.animate({
|
|
58
66
|
// eslint-disable-next-line id-length -- SVG path attribute
|
|
59
67
|
d: {
|
|
60
68
|
begin,
|
|
61
69
|
dur: duration,
|
|
62
70
|
easing,
|
|
63
71
|
fill: 'freeze',
|
|
64
|
-
from:
|
|
72
|
+
from: areaCtx.path
|
|
65
73
|
.clone()
|
|
66
74
|
.scale(1, 0)
|
|
67
|
-
.translate(0,
|
|
75
|
+
.translate(0, areaCtx.chartRect.height())
|
|
68
76
|
.stringify(),
|
|
69
|
-
to:
|
|
77
|
+
to: areaCtx.path.stringify(),
|
|
70
78
|
},
|
|
71
79
|
}, false)
|
|
72
80
|
}
|
|
73
81
|
|
|
74
82
|
// Animation for bar charts
|
|
75
83
|
if (ctx.type === 'bar') {
|
|
76
|
-
const
|
|
84
|
+
const barCtx = ctx as BarDrawEvent
|
|
85
|
+
// Access private options property via type assertion
|
|
86
|
+
const chartOptions = (chart as unknown as { options?: Options & Partial<BarChartOptions> }).options
|
|
87
|
+
const horizontal = !!(chartOptions as BarChartOptions | undefined)?.horizontalBars
|
|
77
88
|
|
|
78
89
|
// For vertical bars, y1 is baseline, y2 is top. For horizontal, x1 is baseline, x2 is end.
|
|
79
|
-
const from = horizontal ?
|
|
80
|
-
const to = horizontal ?
|
|
90
|
+
const from = horizontal ? barCtx.x1 : barCtx.y1
|
|
91
|
+
const to = horizontal ? barCtx.x2 : barCtx.y2
|
|
81
92
|
|
|
82
93
|
// Start collapsed at baseline
|
|
83
94
|
if (horizontal) {
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
barCtx.element.attr({ x2: from })
|
|
96
|
+
barCtx.element.animate({
|
|
86
97
|
x2: {
|
|
87
98
|
begin,
|
|
88
99
|
dur: duration,
|
|
89
100
|
easing,
|
|
90
101
|
fill: 'freeze',
|
|
91
|
-
from,
|
|
92
|
-
to,
|
|
102
|
+
from: String(from),
|
|
103
|
+
to: String(to),
|
|
93
104
|
},
|
|
94
105
|
}, false)
|
|
95
106
|
}
|
|
96
107
|
else {
|
|
97
|
-
|
|
98
|
-
|
|
108
|
+
barCtx.element.attr({ y2: from })
|
|
109
|
+
barCtx.element.animate({
|
|
99
110
|
y2: {
|
|
100
111
|
begin,
|
|
101
112
|
dur: duration,
|
|
102
113
|
easing,
|
|
103
114
|
fill: 'freeze',
|
|
104
|
-
from,
|
|
105
|
-
to,
|
|
115
|
+
from: String(from),
|
|
116
|
+
to: String(to),
|
|
106
117
|
},
|
|
107
118
|
}, false)
|
|
108
119
|
}
|
package/app/types/fields.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export interface FieldInput {
|
|
|
46
46
|
lowercaseOnly?: boolean
|
|
47
47
|
max?: number
|
|
48
48
|
min?: number
|
|
49
|
-
modelValue
|
|
49
|
+
modelValue: string
|
|
50
50
|
placeholder?: string
|
|
51
51
|
required?: boolean
|
|
52
52
|
size?: FieldSize
|
|
@@ -171,7 +171,7 @@ export interface FieldTime {
|
|
|
171
171
|
id: number | string
|
|
172
172
|
label?: BaseTextText
|
|
173
173
|
labelIcon?: string
|
|
174
|
-
modelValue
|
|
174
|
+
modelValue: string
|
|
175
175
|
name?: string
|
|
176
176
|
required?: boolean
|
|
177
177
|
size?: FieldSize
|
package/app/types/global.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type * as Fields from './fields'
|
|
|
5
5
|
declare module '@vue/runtime-core' {
|
|
6
6
|
interface ComponentCustomProperties {
|
|
7
7
|
vHotkey?: Record<string, (event?: KeyboardEvent | MouseEvent) => void>
|
|
8
|
-
vTooltip?: Record<string,
|
|
8
|
+
vTooltip?: Record<string, unknown> | string
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
|
package/nuxt.config.ts
CHANGED
|
@@ -25,7 +25,7 @@ export default defineNuxtConfig({
|
|
|
25
25
|
},
|
|
26
26
|
},
|
|
27
27
|
|
|
28
|
-
// --> COMPONENTS, CSS
|
|
28
|
+
// --> COMPONENTS, CSS & MODULES <--
|
|
29
29
|
|
|
30
30
|
components: [
|
|
31
31
|
{
|
|
@@ -116,8 +116,8 @@ export default defineNuxtConfig({
|
|
|
116
116
|
|
|
117
117
|
unocss: {
|
|
118
118
|
nuxtLayers: true,
|
|
119
|
-
presets: uno.presets
|
|
120
|
-
rules: uno.rules
|
|
119
|
+
presets: uno.presets,
|
|
120
|
+
rules: uno.rules,
|
|
121
121
|
theme: uno.theme,
|
|
122
122
|
},
|
|
123
123
|
})
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saasmakers/ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.73",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Reusable Nuxt UI components for SaaS Makers projects",
|
|
7
7
|
"license": "MIT",
|
|
@@ -34,7 +34,6 @@
|
|
|
34
34
|
"@nuxtjs/robots": "5.5.6",
|
|
35
35
|
"@nuxtjs/sitemap": "7.4.7",
|
|
36
36
|
"@pinia/nuxt": "0.11.2",
|
|
37
|
-
"@types/chartist": "1.0.4",
|
|
38
37
|
"@unocss/nuxt": "66.5.4",
|
|
39
38
|
"@unocss/reset": "66.5.10",
|
|
40
39
|
"@vuelidate/core": "2.0.3",
|
|
@@ -55,7 +54,7 @@
|
|
|
55
54
|
"devDependencies": {
|
|
56
55
|
"nuxt": "4.2.1",
|
|
57
56
|
"typescript": "5.9.3",
|
|
58
|
-
"@saasmakers/shared": "0.1.
|
|
57
|
+
"@saasmakers/shared": "0.1.4"
|
|
59
58
|
},
|
|
60
59
|
"scripts": {
|
|
61
60
|
"dev": "nuxi dev",
|
package/uno.config.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { Preset } from 'unocss'
|
|
1
2
|
import { defineConfig, presetWind3 } from 'unocss'
|
|
2
3
|
|
|
3
|
-
export const presets = [presetWind3()]
|
|
4
|
+
export const presets: Preset[] = [presetWind3()]
|
|
4
5
|
|
|
5
6
|
export const rules: Array<[string, Record<string, string>]> = [
|
|
6
7
|
[
|
|
@@ -185,7 +186,7 @@ export const theme = {
|
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
export default defineConfig({
|
|
188
|
-
presets
|
|
189
|
+
presets,
|
|
189
190
|
rules,
|
|
190
191
|
theme,
|
|
191
192
|
})
|