@saasmakers/ui 2.1.2 → 2.1.4
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.
|
@@ -46,7 +46,18 @@ const id = useId()
|
|
|
46
46
|
const modelValue = defineModel<FieldInput['modelValue']>({ default: '' })
|
|
47
47
|
const input = ref<HTMLInputElement>()
|
|
48
48
|
const showPassword = ref(false)
|
|
49
|
-
const
|
|
49
|
+
const focused = ref(false)
|
|
50
|
+
const { isDesktopBrowser, isIos } = useDevice()
|
|
51
|
+
|
|
52
|
+
const iosUppercaseTyping = computed(() => {
|
|
53
|
+
const isProseField = props.type === 'text' || props.type === 'search'
|
|
54
|
+
|
|
55
|
+
return props.uppercase && isIos.value && isProseField && !props.lowercaseOnly && !props.slugOnly
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const hideCssUppercase = computed(() => {
|
|
59
|
+
return iosUppercaseTyping.value && focused.value
|
|
60
|
+
})
|
|
50
61
|
|
|
51
62
|
onMounted(() => {
|
|
52
63
|
if (props.autofocus && input.value && isDesktopBrowser.value) {
|
|
@@ -67,6 +78,8 @@ function focus() {
|
|
|
67
78
|
}
|
|
68
79
|
|
|
69
80
|
function onFieldBlur(event: FocusEvent) {
|
|
81
|
+
focused.value = false
|
|
82
|
+
|
|
70
83
|
syncModelValueFromTarget(event.target)
|
|
71
84
|
|
|
72
85
|
if (props.trim) {
|
|
@@ -77,6 +90,16 @@ function onFieldBlur(event: FocusEvent) {
|
|
|
77
90
|
}
|
|
78
91
|
|
|
79
92
|
function onFieldFocus(event: FocusEvent) {
|
|
93
|
+
if (iosUppercaseTyping.value) {
|
|
94
|
+
const uppercased = modelValue.value.toString().toUpperCase()
|
|
95
|
+
|
|
96
|
+
if (uppercased !== modelValue.value) {
|
|
97
|
+
modelValue.value = uppercased
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
focused.value = true
|
|
102
|
+
|
|
80
103
|
emit('focus', event)
|
|
81
104
|
}
|
|
82
105
|
|
|
@@ -193,10 +216,12 @@ defineExpose({
|
|
|
193
216
|
:id="id"
|
|
194
217
|
ref="input"
|
|
195
218
|
:autocomplete="autocomplete ? 'on' : 'off'"
|
|
219
|
+
:autocapitalize="iosUppercaseTyping ? 'characters' : undefined"
|
|
196
220
|
v-bind="autofocus ? { 'data-autofocus': '' } : {}"
|
|
197
221
|
class="h-full w-full appearance-none items-center rounded-lg font-medium tracking-tight outline-none placeholder-gray-600 dark:placeholder-gray-400"
|
|
198
222
|
:class="{
|
|
199
|
-
'uppercase': uppercase,
|
|
223
|
+
'uppercase': uppercase && !hideCssUppercase,
|
|
224
|
+
'placeholder:uppercase': hideCssUppercase,
|
|
200
225
|
'field-disabled': disabled,
|
|
201
226
|
'focus:placeholder-gray-900 hover:placeholder-gray-900 dark:focus:placeholder-gray-100 dark:hover:placeholder-gray-100': !disabled,
|
|
202
227
|
'text-gray-900 dark:text-gray-100': !lineThrough,
|
|
@@ -30,7 +30,16 @@ const emit = defineEmits<{
|
|
|
30
30
|
const id = useId()
|
|
31
31
|
const modelValue = defineModel<FieldTextarea['modelValue']>({ default: '' })
|
|
32
32
|
const textarea = ref<HTMLTextAreaElement>()
|
|
33
|
-
const
|
|
33
|
+
const focused = ref(false)
|
|
34
|
+
const { isDesktopBrowser, isIos } = useDevice()
|
|
35
|
+
|
|
36
|
+
const iosUppercaseTyping = computed(() => {
|
|
37
|
+
return props.uppercase && isIos.value
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const hideCssUppercase = computed(() => {
|
|
41
|
+
return iosUppercaseTyping.value && focused.value
|
|
42
|
+
})
|
|
34
43
|
|
|
35
44
|
onMounted(() => {
|
|
36
45
|
if (props.autofocus && textarea.value && isDesktopBrowser.value) {
|
|
@@ -39,6 +48,8 @@ onMounted(() => {
|
|
|
39
48
|
})
|
|
40
49
|
|
|
41
50
|
function onFieldBlur(event: FocusEvent) {
|
|
51
|
+
focused.value = false
|
|
52
|
+
|
|
42
53
|
syncModelValueFromTarget(event.target)
|
|
43
54
|
emit('blur', event, modelValue.value || '')
|
|
44
55
|
}
|
|
@@ -47,6 +58,18 @@ function onFieldClick(event: MouseEvent) {
|
|
|
47
58
|
emit('click', event, modelValue.value || '')
|
|
48
59
|
}
|
|
49
60
|
|
|
61
|
+
function onFieldFocus() {
|
|
62
|
+
if (iosUppercaseTyping.value) {
|
|
63
|
+
const uppercased = modelValue.value.toString().toUpperCase()
|
|
64
|
+
|
|
65
|
+
if (uppercased !== modelValue.value) {
|
|
66
|
+
modelValue.value = uppercased
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
focused.value = true
|
|
71
|
+
}
|
|
72
|
+
|
|
50
73
|
function syncModelValueFromTarget(target: EventTarget | null) {
|
|
51
74
|
if (!(target instanceof HTMLTextAreaElement)) {
|
|
52
75
|
return
|
|
@@ -77,9 +100,11 @@ function syncModelValueFromTarget(target: EventTarget | null) {
|
|
|
77
100
|
ref="textarea"
|
|
78
101
|
v-model="modelValue"
|
|
79
102
|
v-bind="{ 'data-enable-grammarly': 'false' }"
|
|
103
|
+
:autocapitalize="iosUppercaseTyping ? 'characters' : undefined"
|
|
80
104
|
class="w-full flex-1 appearance-none rounded-lg text-gray-900 font-medium tracking-tight outline-none dark:text-gray-100 placeholder-gray-600 dark:placeholder-gray-400"
|
|
81
105
|
:class="{
|
|
82
|
-
'uppercase': uppercase,
|
|
106
|
+
'uppercase': uppercase && !hideCssUppercase,
|
|
107
|
+
'placeholder:uppercase': hideCssUppercase,
|
|
83
108
|
'field-disabled': disabled,
|
|
84
109
|
'focus:placeholder-gray-900 hover:placeholder-gray-900 dark:focus:placeholder-gray-100 dark:hover:placeholder-gray-100': !disabled,
|
|
85
110
|
'px-sm py-2.5': padding && size === 'sm',
|
|
@@ -102,6 +127,7 @@ function syncModelValueFromTarget(target: EventTarget | null) {
|
|
|
102
127
|
spellcheck="false"
|
|
103
128
|
@blur="onFieldBlur"
|
|
104
129
|
@click="onFieldClick"
|
|
130
|
+
@focus="onFieldFocus"
|
|
105
131
|
/>
|
|
106
132
|
|
|
107
133
|
<FieldMessage
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export default function useDevice() {
|
|
2
|
-
const { isNative } = useCapacitor()
|
|
2
|
+
const { isIOS, isNative } = useCapacitor()
|
|
3
|
+
const isIos = ref(false)
|
|
3
4
|
|
|
4
5
|
const isDesktopBrowser = computed(() => {
|
|
5
6
|
if (typeof navigator === 'undefined') {
|
|
@@ -18,5 +19,29 @@ export default function useDevice() {
|
|
|
18
19
|
return !/Android|iPad|iPhone|iPod|Mobile/i.test(navigator.userAgent)
|
|
19
20
|
})
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
onMounted(() => {
|
|
23
|
+
isIos.value = detectIosDevice(isIOS.value)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
isDesktopBrowser,
|
|
28
|
+
isIos,
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function detectIosDevice(isNativeIos: boolean) {
|
|
33
|
+
if (isNativeIos) {
|
|
34
|
+
return true
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (typeof navigator === 'undefined') {
|
|
38
|
+
return false
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// iPadOS 13+ uses a Macintosh user agent. Several touch points separate it from a Mac.
|
|
46
|
+
return navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1
|
|
22
47
|
}
|