@volverjs/ui-vue 0.0.1-beta.5 → 0.0.1-beta.8
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 +61 -2
- package/dist/components/VvButton/vv-button.es.js +56 -58
- package/dist/components/VvButton/vv-button.umd.js +1 -1
- package/dist/components/VvCheckGroup/vv-check-group.es.js +221 -203
- package/dist/components/VvCheckGroup/vv-check-group.umd.js +2 -2
- package/dist/components/VvInputText/VvInputText.d.ts +14 -0
- package/dist/components/VvInputText/VvInputText.vue.d.ts +36 -1
- package/dist/components/VvInputText/VvInputTextActions.d.ts +3 -0
- package/dist/components/VvInputText/vv-input-text.es.js +509 -380
- package/dist/components/VvInputText/vv-input-text.umd.js +2 -2
- package/dist/components/VvNativeSelect/vv-native-select.es.js +180 -161
- package/dist/components/VvNativeSelect/vv-native-select.umd.js +2 -2
- package/dist/components/VvRadioGroup/vv-radio-group.es.js +211 -193
- package/dist/components/VvRadioGroup/vv-radio-group.umd.js +2 -2
- package/dist/components/VvSelect/vv-select.es.js +189 -171
- package/dist/components/VvSelect/vv-select.umd.js +2 -2
- package/dist/components/VvTextarea/VvTextarea.d.ts +43 -22
- package/dist/components/VvTextarea/VvTextarea.vue.d.ts +140 -85
- package/dist/components/VvTextarea/vv-textarea.es.js +364 -288
- package/dist/components/VvTextarea/vv-textarea.umd.js +2 -2
- package/dist/composables/debouncedInput/useDebouncedInput.d.ts +2 -0
- package/dist/composables/icons/useComponentIcons.d.ts +6 -0
- package/dist/composables/textLimit/useTextLimit.d.ts +14 -0
- package/dist/composables/useModifiers.d.ts +3 -2
- package/dist/icons.es.js +3 -3
- package/dist/icons.umd.js +1 -1
- package/dist/props/index.d.ts +42 -0
- package/dist/stories/utils.d.ts +5 -0
- package/dist/ui-vue.es.js +417 -401
- package/dist/ui-vue.umd.js +2 -2
- package/package.json +3 -1
- package/src/assets/icons/detailed.json +1 -1
- package/src/assets/icons/normal.json +1 -1
- package/src/assets/icons/simple.json +1 -1
- package/src/components/VvButton/VvButton.vue +1 -2
- package/src/components/VvInputText/VvInputText.ts +19 -2
- package/src/components/VvInputText/VvInputText.vue +123 -149
- package/src/components/VvInputText/VvInputTextActions.ts +151 -0
- package/src/components/VvTextarea/VvTextarea.ts +25 -16
- package/src/components/VvTextarea/VvTextarea.vue +89 -93
- package/src/components/common/HintSlot.ts +31 -13
- package/src/composables/debouncedInput/useDebouncedInput.ts +19 -0
- package/src/composables/icons/useComponentIcons.ts +35 -0
- package/src/composables/textLimit/useTextLimit.ts +44 -0
- package/src/composables/useModifiers.ts +47 -1
- package/src/props/index.ts +39 -0
- package/src/stories/InputText/InputTextMaxLength.stories.mdx +21 -0
- package/src/stories/Textarea/Textarea.stories.mdx +33 -51
- package/src/stories/Textarea/TextareaAutoclear.stories.mdx +23 -0
- package/src/stories/Textarea/TextareaAutocomplete.stories.mdx +10 -2
- package/src/stories/Textarea/TextareaAutofocus.stories.mdx +5 -1
- package/src/stories/Textarea/TextareaDebounce.stories.mdx +23 -0
- package/src/stories/Textarea/TextareaDisabled.stories.mdx +5 -1
- package/src/stories/Textarea/TextareaError.stories.mdx +6 -3
- package/src/stories/Textarea/TextareaErrorLabel.stories.mdx +37 -0
- package/src/stories/Textarea/TextareaFloating.stories.mdx +7 -2
- package/src/stories/Textarea/TextareaHintLabel.stories.mdx +5 -1
- package/src/stories/Textarea/TextareaIcon.stories.mdx +5 -1
- package/src/stories/Textarea/TextareaIconPosition.stories.mdx +9 -1
- package/src/stories/Textarea/TextareaId.stories.mdx +19 -0
- package/src/stories/Textarea/TextareaLabel.stories.mdx +5 -1
- package/src/stories/Textarea/TextareaLimit.stories.mdx +50 -0
- package/src/stories/Textarea/TextareaLoading.stories.mdx +6 -3
- package/src/stories/Textarea/TextareaLoadingLabel.stories.mdx +23 -0
- package/src/stories/Textarea/TextareaMaxLength.stories.mdx +6 -2
- package/src/stories/Textarea/TextareaMinLength.stories.mdx +5 -1
- package/src/stories/Textarea/TextareaModifiers.stories.mdx +24 -0
- package/src/stories/Textarea/TextareaName.stories.mdx +23 -0
- package/src/stories/Textarea/TextareaPlaceholder.stories.mdx +5 -1
- package/src/stories/Textarea/TextareaReadonly.stories.mdx +5 -1
- package/src/stories/Textarea/TextareaRequired.stories.mdx +22 -0
- package/src/stories/Textarea/TextareaResizable.stories.mdx +22 -0
- package/src/stories/Textarea/TextareaRowsCols.stories.mdx +9 -1
- package/src/stories/Textarea/TextareaValid.stories.mdx +7 -4
- package/src/stories/Textarea/TextareaValidLabel.stories.mdx +35 -0
- package/src/stories/stories.scss +11 -0
- package/src/stories/utils.ts +12 -0
- package/src/stories/volver-ui-vue.stories.mdx +7 -1
- package/dist/components/VvInputText/useInputNumber.d.ts +0 -16
- package/dist/components/VvInputText/useInputPassword.d.ts +0 -16
- package/src/components/VvInputText/useInputNumber.ts +0 -40
- package/src/components/VvInputText/useInputPassword.ts +0 -38
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
</template>
|
|
47
47
|
|
|
48
48
|
<script setup lang="ts">
|
|
49
|
-
import { useAttrs
|
|
49
|
+
import { useAttrs } from 'vue'
|
|
50
50
|
|
|
51
51
|
import { computed } from 'vue'
|
|
52
52
|
import { v4 as uuidv4 } from 'uuid'
|
|
@@ -64,7 +64,6 @@ import { toButtonRefs } from './useButtonGroupProps'
|
|
|
64
64
|
//Props, emits, attrs, slots
|
|
65
65
|
const props = defineProps(VvButtonProps)
|
|
66
66
|
const attrs = useAttrs()
|
|
67
|
-
const slots = useSlots()
|
|
68
67
|
|
|
69
68
|
//Data
|
|
70
69
|
const btnName = attrs?.name || uuidv4()
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ExtractPropTypes } from 'vue'
|
|
2
|
+
import {
|
|
3
|
+
ValidProps,
|
|
4
|
+
ErrorProps,
|
|
5
|
+
HintProps,
|
|
6
|
+
LoadingProps,
|
|
7
|
+
ModifiersProps,
|
|
8
|
+
LimitProps
|
|
9
|
+
} from '../../props'
|
|
2
10
|
import { TYPES, ICON_POSITIONS } from './constants'
|
|
3
11
|
|
|
4
12
|
export const VvInputTextEvents = ['update:modelValue', 'focus', 'blur']
|
|
@@ -8,6 +16,8 @@ export const VvInputTextProps = {
|
|
|
8
16
|
...ErrorProps,
|
|
9
17
|
...HintProps,
|
|
10
18
|
...LoadingProps,
|
|
19
|
+
...ModifiersProps,
|
|
20
|
+
...LimitProps,
|
|
11
21
|
modelValue: null,
|
|
12
22
|
type: {
|
|
13
23
|
type: String,
|
|
@@ -45,5 +55,12 @@ export const VvInputTextProps = {
|
|
|
45
55
|
* True = label flottante
|
|
46
56
|
*/
|
|
47
57
|
floating: Boolean,
|
|
48
|
-
debounce: Number
|
|
58
|
+
debounce: Number,
|
|
59
|
+
/**
|
|
60
|
+
* Se true, attiva la possibilità di cancellare il testo nella textarea
|
|
61
|
+
*/
|
|
62
|
+
autoclear: Boolean
|
|
49
63
|
}
|
|
64
|
+
|
|
65
|
+
type VvInputTextPropsType = typeof VvInputTextProps
|
|
66
|
+
export type VvInputTextPropsTypes = ExtractPropTypes<VvInputTextPropsType>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-bind="vvInputTextProps" :class="
|
|
3
|
-
<label v-if="label" :for="
|
|
2
|
+
<div v-bind="vvInputTextProps" :class="inputTextClass">
|
|
3
|
+
<label v-if="label" :for="inputTextId">{{ label }}</label>
|
|
4
4
|
<div class="vv-input-text__wrapper">
|
|
5
5
|
<!-- @slot icon-left to replace icon left -->
|
|
6
6
|
<slot v-if="hasIconLeft" name="icon-left" v-bind="iconSlotProps">
|
|
@@ -11,43 +11,34 @@
|
|
|
11
11
|
v-bind="innerInputProps"
|
|
12
12
|
v-model="inputTextData"
|
|
13
13
|
@input="emit('input', $event)" />
|
|
14
|
+
<!-- autoclear text button -->
|
|
15
|
+
<button
|
|
16
|
+
v-if="autoclear && textLength > 0"
|
|
17
|
+
class="vv-button vv-button--ghost"
|
|
18
|
+
@click="clearInputText">
|
|
19
|
+
<vv-icon name="clear-field" />
|
|
20
|
+
</button>
|
|
14
21
|
<!-- @slot icon-right to replace icon right -->
|
|
15
22
|
<slot name="icon-right" v-bind="iconSlotProps">
|
|
16
|
-
<!-- default password icon -->
|
|
17
23
|
<template v-if="isPassword">
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
:disabled="isActionsDisabled"
|
|
22
|
-
@click.prevent="toggleShowHidePassword">
|
|
23
|
-
<vv-icon :name="inputRightIcon" />
|
|
24
|
-
</button>
|
|
25
|
-
</div>
|
|
24
|
+
<PasswordInputActions
|
|
25
|
+
@action-password-on="showPassword = true"
|
|
26
|
+
@action-password-off="showPassword = false" />
|
|
26
27
|
</template>
|
|
27
|
-
<!-- default number icon -->
|
|
28
28
|
<template v-else-if="isNumber">
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class="vv-input-text__action-chevron vv-input-text__action-chevron-up"
|
|
33
|
-
:disabled="isActionsDisabled"
|
|
34
|
-
@click.prevent="stepUp()"></button>
|
|
35
|
-
<button
|
|
36
|
-
type="button"
|
|
37
|
-
class="vv-input-text__action-chevron"
|
|
38
|
-
:disabled="isActionsDisabled"
|
|
39
|
-
@click.prevent="stepDown()"></button>
|
|
40
|
-
</div>
|
|
29
|
+
<NumberInputActions
|
|
30
|
+
@action-step-up="stepUp"
|
|
31
|
+
@action-step-down="stepDown" />
|
|
41
32
|
</template>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
<vv-icon :name="inputRightIcon" />
|
|
33
|
+
<template v-else-if="hasIconRight || defaultRightIcon">
|
|
34
|
+
<vv-icon :name="icon || defaultRightIcon" />
|
|
45
35
|
</template>
|
|
46
36
|
</slot>
|
|
37
|
+
<span v-if="limit" class="vv-input-text__limit">
|
|
38
|
+
<slot name="limit"> {{ formattedTextLimitLength }} </slot>
|
|
39
|
+
</span>
|
|
47
40
|
</div>
|
|
48
|
-
<HintSlot
|
|
49
|
-
:id="inputAriaAttrs['aria-describedby']"
|
|
50
|
-
class="vv-input-text__hint" />
|
|
41
|
+
<HintSlot :id="inputTextDescribedBy" class="vv-input-text__hint" />
|
|
51
42
|
</div>
|
|
52
43
|
</template>
|
|
53
44
|
|
|
@@ -59,7 +50,7 @@ import {
|
|
|
59
50
|
ref,
|
|
60
51
|
toRefs,
|
|
61
52
|
onMounted,
|
|
62
|
-
|
|
53
|
+
unref,
|
|
63
54
|
type HTMLAttributes,
|
|
64
55
|
type InputHTMLAttributes
|
|
65
56
|
} from 'vue'
|
|
@@ -69,17 +60,17 @@ import { VvInputTextEvents, VvInputTextProps } from './VvInputText'
|
|
|
69
60
|
//Componenti
|
|
70
61
|
import VvIcon from '../../components/VvIcon/VvIcon.vue'
|
|
71
62
|
import HintSlotFactory from '../common/HintSlot'
|
|
63
|
+
import VvInputTextActionsFactory from './VvInputTextActions'
|
|
72
64
|
|
|
73
65
|
//Constanti
|
|
74
66
|
import INPUT from './constants'
|
|
75
67
|
|
|
76
68
|
//Composables
|
|
77
|
-
import {
|
|
78
|
-
import { useInputPassword } from './useInputPassword'
|
|
79
|
-
import { useInputNumber } from './useInputNumber'
|
|
80
|
-
import { useComponentIcons } from '../../composables/icons/useComponentIcons'
|
|
69
|
+
import { useComponentIcon } from '../../composables/icons/useComponentIcons'
|
|
81
70
|
import { useComponentFocus } from '../../composables/focus/useComponentFocus'
|
|
82
|
-
import {
|
|
71
|
+
import { useDebouncedInput } from '../../composables/debouncedInput/useDebouncedInput'
|
|
72
|
+
import { useTextLimit } from '../../composables/textLimit/useTextLimit'
|
|
73
|
+
import { toBem } from '@/composables/useModifiers'
|
|
83
74
|
|
|
84
75
|
//Props, Emits, Slots e Attrs
|
|
85
76
|
const props = defineProps(VvInputTextProps)
|
|
@@ -91,41 +82,51 @@ const attrs = useAttrs()
|
|
|
91
82
|
const input = ref()
|
|
92
83
|
|
|
93
84
|
//Data
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
label,
|
|
106
|
-
modelValue
|
|
107
|
-
} = toRefs(props)
|
|
85
|
+
const { icon, iconPosition, label, modelValue, autoclear, limit } =
|
|
86
|
+
toRefs(props)
|
|
87
|
+
const inputTextId = props.id || props.name
|
|
88
|
+
const inputTextLabeledBy = `${props.name}-label`
|
|
89
|
+
const inputTextDescribedBy = `${props.name}-hint`
|
|
90
|
+
//BUG - https://www.samanthaming.com/tidbits/88-css-placeholder-shown/
|
|
91
|
+
const inputTextPlaceholder = computed(() =>
|
|
92
|
+
props.floating && ObjectUtilities.isEmpty(props.placeholder)
|
|
93
|
+
? ' '
|
|
94
|
+
: props.placeholder
|
|
95
|
+
)
|
|
108
96
|
|
|
109
|
-
//
|
|
110
|
-
const
|
|
97
|
+
//Debounce input
|
|
98
|
+
const inputTextData = useDebouncedInput(modelValue, props.debounce, emit)
|
|
111
99
|
|
|
112
|
-
//
|
|
113
|
-
const
|
|
114
|
-
|
|
100
|
+
//Gestione input tipo password
|
|
101
|
+
const showPassword = ref(false)
|
|
102
|
+
const isPassword = computed(() => props.type === INPUT.TYPES.PASSWORD)
|
|
103
|
+
|
|
104
|
+
//Gestione input tipo NUMBER
|
|
105
|
+
const isNumber = computed(() => props.type === INPUT.TYPES.NUMBER)
|
|
106
|
+
function stepUp() {
|
|
107
|
+
const _max = props.max as number
|
|
108
|
+
if (!isActionsDisabled.value && inputTextData.value + 1 <= _max) {
|
|
109
|
+
input.value.stepUp()
|
|
110
|
+
inputTextData.value = unref(input.value).value
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function stepDown() {
|
|
114
|
+
const _min = props.min as number
|
|
115
|
+
if (!isActionsDisabled.value && inputTextData.value - 1 <= _min) {
|
|
116
|
+
input.value.stepDown()
|
|
117
|
+
inputTextData.value = unref(input.value).value
|
|
118
|
+
}
|
|
119
|
+
}
|
|
115
120
|
|
|
116
121
|
//Gestione ICONE
|
|
117
|
-
const
|
|
118
|
-
const iconSlots = {
|
|
122
|
+
const { hasIconLeft, hasIconRight } = useComponentIcon(icon, iconPosition, {
|
|
119
123
|
iconLeft: slots['icon-left'],
|
|
120
124
|
iconRight: slots['icon-right']
|
|
121
|
-
}
|
|
122
|
-
const
|
|
123
|
-
const inputRightIcon = computed(() => {
|
|
124
|
-
if (hasIconRight.value) return props.icon
|
|
125
|
-
|
|
125
|
+
})
|
|
126
|
+
const defaultRightIcon = computed(() => {
|
|
126
127
|
switch (props.type) {
|
|
127
128
|
case INPUT.TYPES.PASSWORD:
|
|
128
|
-
return
|
|
129
|
+
return INPUT.TYPES_ICON.PASSWORD_OFF
|
|
129
130
|
case INPUT.TYPES.COLOR:
|
|
130
131
|
return INPUT.TYPES_ICON.COLOR
|
|
131
132
|
case INPUT.TYPES.DATE:
|
|
@@ -140,53 +141,40 @@ const inputRightIcon = computed(() => {
|
|
|
140
141
|
}
|
|
141
142
|
})
|
|
142
143
|
|
|
143
|
-
//
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
const {
|
|
150
|
-
isPassword,
|
|
151
|
-
isPasswordVisible,
|
|
152
|
-
passwordButtonIcon,
|
|
153
|
-
toggleShowHidePassword
|
|
154
|
-
} = useInputPassword(inputPswProps)
|
|
155
|
-
|
|
156
|
-
//Gestione input tipo NUMBER
|
|
157
|
-
const inputNumberProps = {
|
|
158
|
-
disabled,
|
|
159
|
-
readonly,
|
|
160
|
-
type,
|
|
161
|
-
inputTemplateRef: input
|
|
162
|
-
}
|
|
163
|
-
const { isNumber, stepUp, stepDown } = useInputNumber(
|
|
164
|
-
inputTextData,
|
|
165
|
-
inputNumberProps
|
|
166
|
-
)
|
|
144
|
+
//Conteggio battute
|
|
145
|
+
const { textLength, formattedTextLimitLength } = useTextLimit(inputTextData, {
|
|
146
|
+
mode: props.limit,
|
|
147
|
+
upperLimit: props.maxlength || 0
|
|
148
|
+
})
|
|
167
149
|
|
|
168
150
|
//Input FOCUS
|
|
169
151
|
const { focused } = useComponentFocus(input, emit)
|
|
170
152
|
|
|
153
|
+
//Component computed
|
|
154
|
+
const isActionsDisabled = computed(() => props.disabled || props.readonly)
|
|
155
|
+
|
|
171
156
|
//Styles & Bindings
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
(
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
157
|
+
const inputTextClass = computed(() => {
|
|
158
|
+
const _hasIconRigth =
|
|
159
|
+
hasIconRight.value || ObjectUtilities.isNotEmpty(defaultRightIcon.value)
|
|
160
|
+
const _isFloating =
|
|
161
|
+
props.floating && ObjectUtilities.isNotEmpty(props.label)
|
|
162
|
+
const _isDirty = ObjectUtilities.isNotEmpty(modelValue?.value)
|
|
163
|
+
|
|
164
|
+
return [
|
|
165
|
+
toBem('vv-input-text', {
|
|
166
|
+
modifiers: props.modifiers,
|
|
167
|
+
readonly: props.readonly,
|
|
168
|
+
valid: props.valid,
|
|
169
|
+
invalid: props.error,
|
|
170
|
+
loading: props.loading,
|
|
171
|
+
iconLeft: hasIconLeft,
|
|
172
|
+
iconRight: _hasIconRigth,
|
|
173
|
+
floating: _isFloating,
|
|
174
|
+
dirty: _isDirty
|
|
175
|
+
}),
|
|
176
|
+
attrs.class
|
|
177
|
+
]
|
|
190
178
|
})
|
|
191
179
|
const vvInputTextProps = computed(() => {
|
|
192
180
|
const { style } = attrs
|
|
@@ -199,55 +187,31 @@ const vvInputTextProps = computed(() => {
|
|
|
199
187
|
} as HTMLAttributes
|
|
200
188
|
})
|
|
201
189
|
const innerInputProps = computed(() => {
|
|
202
|
-
const
|
|
203
|
-
id,
|
|
204
|
-
name,
|
|
205
|
-
type,
|
|
206
|
-
autocomplete,
|
|
207
|
-
minlength,
|
|
208
|
-
maxlength,
|
|
209
|
-
min,
|
|
210
|
-
max,
|
|
211
|
-
step,
|
|
212
|
-
disabled,
|
|
213
|
-
readonly,
|
|
214
|
-
floating,
|
|
215
|
-
placeholder
|
|
216
|
-
} = props
|
|
217
|
-
|
|
218
|
-
const _id = id || name
|
|
219
|
-
const _type = isPassword.value && isPasswordVisible.value ? 'text' : type
|
|
220
|
-
//BUG - https://www.samanthaming.com/tidbits/88-css-placeholder-shown/
|
|
221
|
-
const _placeholder =
|
|
222
|
-
floating && ObjectUtilities.isEmpty(placeholder) ? ' ' : placeholder
|
|
223
|
-
|
|
224
|
-
return {
|
|
225
|
-
id: _id,
|
|
226
|
-
type: _type,
|
|
227
|
-
placeholder: _placeholder,
|
|
228
|
-
name,
|
|
229
|
-
autocomplete,
|
|
230
|
-
disabled,
|
|
231
|
-
readonly,
|
|
232
|
-
minlength,
|
|
233
|
-
maxlength,
|
|
234
|
-
min,
|
|
235
|
-
max,
|
|
236
|
-
step,
|
|
237
|
-
...inputAriaAttrs.value
|
|
238
|
-
} as InputHTMLAttributes
|
|
239
|
-
})
|
|
240
|
-
const inputAriaAttrs = computed(() => {
|
|
241
|
-
const { name } = attrs
|
|
190
|
+
const _type = isPassword.value && showPassword.value ? 'text' : props.type
|
|
242
191
|
const ariaAttrs = ObjectUtilities.pickBy(attrs, (k: string) =>
|
|
243
192
|
k.startsWith('aria-')
|
|
244
193
|
)
|
|
194
|
+
|
|
245
195
|
return {
|
|
246
|
-
|
|
247
|
-
|
|
196
|
+
id: inputTextId,
|
|
197
|
+
type: _type,
|
|
198
|
+
placeholder: inputTextPlaceholder.value,
|
|
199
|
+
name: props.name,
|
|
200
|
+
autocomplete: props.autocomplete,
|
|
201
|
+
disabled: props.disabled,
|
|
202
|
+
readonly: props.readonly,
|
|
203
|
+
minlength: props.minlength,
|
|
204
|
+
maxlength: props.maxlength,
|
|
205
|
+
min: props.min,
|
|
206
|
+
max: props.max,
|
|
207
|
+
step: props.step,
|
|
248
208
|
'aria-invalid': props.error,
|
|
209
|
+
'aria-valid': !props.valid,
|
|
210
|
+
'aria-labeledby': inputTextLabeledBy,
|
|
211
|
+
'aria-describedby': inputTextDescribedBy,
|
|
212
|
+
'aria-errormessage': inputTextDescribedBy,
|
|
249
213
|
...ariaAttrs
|
|
250
|
-
}
|
|
214
|
+
} as InputHTMLAttributes
|
|
251
215
|
})
|
|
252
216
|
|
|
253
217
|
//Slot props
|
|
@@ -260,8 +224,18 @@ const iconSlotProps = computed(() => {
|
|
|
260
224
|
}
|
|
261
225
|
})
|
|
262
226
|
|
|
263
|
-
//
|
|
227
|
+
//Other components
|
|
264
228
|
const HintSlot = HintSlotFactory(props, slots)
|
|
229
|
+
const PasswordInputActions = VvInputTextActionsFactory(
|
|
230
|
+
INPUT.TYPES.PASSWORD,
|
|
231
|
+
props
|
|
232
|
+
)
|
|
233
|
+
const NumberInputActions = VvInputTextActionsFactory(INPUT.TYPES.NUMBER, props)
|
|
234
|
+
|
|
235
|
+
//Methods
|
|
236
|
+
function clearInputText() {
|
|
237
|
+
inputTextData.value = null
|
|
238
|
+
}
|
|
265
239
|
|
|
266
240
|
onMounted(() => {
|
|
267
241
|
if (props.autofocus) focused.value = true
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/* eslint-disable vue/one-component-per-file */
|
|
2
|
+
import type { VvInputTextPropsTypes } from './VvInputText'
|
|
3
|
+
import { computed, type Component } from 'vue'
|
|
4
|
+
|
|
5
|
+
import { h, ref, defineComponent } from 'vue'
|
|
6
|
+
import VvIcon from '../VvIcon/VvIcon.vue'
|
|
7
|
+
import { TYPES, TYPES_ICON } from './constants'
|
|
8
|
+
|
|
9
|
+
const VvInputPasswordAction = defineComponent({
|
|
10
|
+
components: {
|
|
11
|
+
VvIcon
|
|
12
|
+
},
|
|
13
|
+
props: {
|
|
14
|
+
disabled: Boolean
|
|
15
|
+
},
|
|
16
|
+
setup(props, { emit }) {
|
|
17
|
+
const active = ref(false)
|
|
18
|
+
const activeIcon = computed(() =>
|
|
19
|
+
active.value ? TYPES_ICON.PASSWORD_OFF : TYPES_ICON.PASSWORD_ON
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
function onClick() {
|
|
23
|
+
if (!props.disabled) {
|
|
24
|
+
active.value = !active.value
|
|
25
|
+
emit(
|
|
26
|
+
active.value ? 'action-password-on' : 'action-password-off'
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
activeIcon,
|
|
33
|
+
onClick
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
render() {
|
|
37
|
+
const icon = h(VvIcon, { name: this.activeIcon })
|
|
38
|
+
|
|
39
|
+
return h(
|
|
40
|
+
'button',
|
|
41
|
+
{
|
|
42
|
+
disabled: this.disabled,
|
|
43
|
+
class: ['vv-input-text__action'],
|
|
44
|
+
onClick: this.onClick
|
|
45
|
+
},
|
|
46
|
+
icon
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
const VvInputStepAction = defineComponent({
|
|
51
|
+
components: {
|
|
52
|
+
VvIcon
|
|
53
|
+
},
|
|
54
|
+
props: {
|
|
55
|
+
disabled: Boolean,
|
|
56
|
+
mode: {
|
|
57
|
+
type: String,
|
|
58
|
+
validator: (v: string) => ['up', 'down'].includes(v),
|
|
59
|
+
default: 'up'
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
setup(props, { emit }) {
|
|
63
|
+
function onClick() {
|
|
64
|
+
if (!props.disabled) {
|
|
65
|
+
emit(
|
|
66
|
+
props.mode === 'up' ? 'action-step-up' : 'action-step-down'
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
onClick
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
render() {
|
|
76
|
+
return h('button', {
|
|
77
|
+
class: [
|
|
78
|
+
'vv-input-text__action-chevron',
|
|
79
|
+
this.mode === 'up' && 'vv-input-text__action-chevron-up'
|
|
80
|
+
],
|
|
81
|
+
disabled: this.disabled,
|
|
82
|
+
onClick: this.onClick
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
export default function VvInputTextActionsFactory(
|
|
88
|
+
type: string,
|
|
89
|
+
parentProps: VvInputTextPropsTypes
|
|
90
|
+
): Component {
|
|
91
|
+
return {
|
|
92
|
+
name: 'VvInputTextActions',
|
|
93
|
+
components: {
|
|
94
|
+
VvIcon,
|
|
95
|
+
VvInputPasswordAction,
|
|
96
|
+
VvInputStepAction
|
|
97
|
+
},
|
|
98
|
+
setup() {
|
|
99
|
+
const isDisabled = computed(() => {
|
|
100
|
+
return parentProps.disabled || parentProps.readonly
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
isDisabled
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
render() {
|
|
108
|
+
let _actions = null
|
|
109
|
+
switch (type) {
|
|
110
|
+
case TYPES.PASSWORD: {
|
|
111
|
+
const { onActionPasswordOn, onActionPasswordOff } =
|
|
112
|
+
this.$attrs
|
|
113
|
+
_actions = [
|
|
114
|
+
h(VvInputPasswordAction, {
|
|
115
|
+
disabled: this.isDisabled,
|
|
116
|
+
onActionPasswordOn,
|
|
117
|
+
onActionPasswordOff
|
|
118
|
+
})
|
|
119
|
+
]
|
|
120
|
+
break
|
|
121
|
+
}
|
|
122
|
+
case TYPES.NUMBER: {
|
|
123
|
+
const { onActionStepUp, onActionStepDown } = this.$attrs
|
|
124
|
+
_actions = [
|
|
125
|
+
h(VvInputStepAction, {
|
|
126
|
+
mode: 'up',
|
|
127
|
+
disabled: this.isDisabled,
|
|
128
|
+
onActionStepUp,
|
|
129
|
+
onActionStepDown
|
|
130
|
+
}),
|
|
131
|
+
h(VvInputStepAction, {
|
|
132
|
+
mode: 'down',
|
|
133
|
+
disabled: this.isDisabled,
|
|
134
|
+
onActionStepUp,
|
|
135
|
+
onActionStepDown
|
|
136
|
+
})
|
|
137
|
+
]
|
|
138
|
+
break
|
|
139
|
+
}
|
|
140
|
+
default: {
|
|
141
|
+
_actions = null
|
|
142
|
+
break
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return Array.isArray(_actions)
|
|
147
|
+
? h('div', { class: 'vv-input-text__actions-group' }, _actions)
|
|
148
|
+
: _actions
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import type { ExtractPropTypes } from 'vue'
|
|
1
2
|
import {
|
|
2
3
|
ValidProps,
|
|
3
4
|
ErrorProps,
|
|
4
5
|
HintProps,
|
|
5
6
|
LoadingProps,
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
ModifiersProps,
|
|
8
|
+
LimitProps,
|
|
9
|
+
InputProps,
|
|
10
|
+
DebounceProps
|
|
8
11
|
} from '../../props'
|
|
9
12
|
import { ICON_POSITIONS, WRAP } from './constants'
|
|
10
13
|
|
|
@@ -15,17 +18,13 @@ export const VvTextareaProps = {
|
|
|
15
18
|
...ErrorProps,
|
|
16
19
|
...HintProps,
|
|
17
20
|
...LoadingProps,
|
|
18
|
-
...
|
|
19
|
-
...
|
|
21
|
+
...ModifiersProps,
|
|
22
|
+
...LimitProps,
|
|
23
|
+
...InputProps,
|
|
24
|
+
...DebounceProps,
|
|
20
25
|
modelValue: null,
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
autocomplete: { type: String, default: 'off' },
|
|
24
|
-
autofocus: Boolean,
|
|
25
|
-
minlength: Number,
|
|
26
|
-
maxlength: Number,
|
|
27
|
-
label: String,
|
|
28
|
-
placeholder: String,
|
|
26
|
+
cols: { type: Number, default: 50 },
|
|
27
|
+
rows: { type: Number, default: 5 },
|
|
29
28
|
/**
|
|
30
29
|
* Nome dell'icona
|
|
31
30
|
* @see DsIcon
|
|
@@ -44,12 +43,22 @@ export const VvTextareaProps = {
|
|
|
44
43
|
* True = label flottante
|
|
45
44
|
*/
|
|
46
45
|
floating: Boolean,
|
|
47
|
-
debounce: Number,
|
|
48
|
-
cols: { type: Number, default: 50 },
|
|
49
|
-
rows: { type: Number, default: 5 },
|
|
50
46
|
/**
|
|
51
47
|
* Specifica come il testo sarà wrappato
|
|
52
48
|
* @see Documentation https://www.w3schools.com/tags/att_textarea_wrap.asp
|
|
53
49
|
*/
|
|
54
|
-
wrap: { type: String, default: WRAP.soft }
|
|
50
|
+
wrap: { type: String, default: WRAP.soft },
|
|
51
|
+
/**
|
|
52
|
+
* Se true, attiva la possibilità di cancellare il testo nella textarea
|
|
53
|
+
*/
|
|
54
|
+
autoclear: Boolean,
|
|
55
|
+
/**
|
|
56
|
+
* Se true, la textbox può essere ridimensionata verticalmente.
|
|
57
|
+
* @description
|
|
58
|
+
* Il resize è pilotato via css. Al momento è attivo solamente il resize verticale
|
|
59
|
+
*/
|
|
60
|
+
resizable: Boolean
|
|
55
61
|
}
|
|
62
|
+
|
|
63
|
+
type VvTextareaPropsType = typeof VvTextareaProps
|
|
64
|
+
export type VvTextareaPropsTypes = ExtractPropTypes<VvTextareaPropsType>
|