@saasmakers/ui 2.1.4 → 2.1.5
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,17 +46,15 @@ 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
|
|
50
|
-
const { isDesktopBrowser, isIos } = useDevice()
|
|
49
|
+
const { isDesktopBrowser } = useDevice()
|
|
51
50
|
|
|
52
|
-
const
|
|
53
|
-
|
|
51
|
+
const { isTypingOnIos, onBlur: onIosUppercaseBlur, onFocus: onIosUppercaseFocus, usesIosUppercaseKeyboard } = useIosUppercase({
|
|
52
|
+
enabled: () => {
|
|
53
|
+
const isProseField = props.type === 'text' || props.type === 'search'
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const hideCssUppercase = computed(() => {
|
|
59
|
-
return iosUppercaseTyping.value && focused.value
|
|
55
|
+
return props.uppercase && isProseField && !props.lowercaseOnly && !props.slugOnly
|
|
56
|
+
},
|
|
57
|
+
modelValue,
|
|
60
58
|
})
|
|
61
59
|
|
|
62
60
|
onMounted(() => {
|
|
@@ -78,8 +76,7 @@ function focus() {
|
|
|
78
76
|
}
|
|
79
77
|
|
|
80
78
|
function onFieldBlur(event: FocusEvent) {
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
onIosUppercaseBlur()
|
|
83
80
|
syncModelValueFromTarget(event.target)
|
|
84
81
|
|
|
85
82
|
if (props.trim) {
|
|
@@ -90,16 +87,7 @@ function onFieldBlur(event: FocusEvent) {
|
|
|
90
87
|
}
|
|
91
88
|
|
|
92
89
|
function onFieldFocus(event: FocusEvent) {
|
|
93
|
-
|
|
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
|
-
|
|
90
|
+
onIosUppercaseFocus()
|
|
103
91
|
emit('focus', event)
|
|
104
92
|
}
|
|
105
93
|
|
|
@@ -216,12 +204,12 @@ defineExpose({
|
|
|
216
204
|
:id="id"
|
|
217
205
|
ref="input"
|
|
218
206
|
:autocomplete="autocomplete ? 'on' : 'off'"
|
|
219
|
-
:autocapitalize="
|
|
207
|
+
:autocapitalize="usesIosUppercaseKeyboard ? 'characters' : undefined"
|
|
220
208
|
v-bind="autofocus ? { 'data-autofocus': '' } : {}"
|
|
221
209
|
class="h-full w-full appearance-none items-center rounded-lg font-medium tracking-tight outline-none placeholder-gray-600 dark:placeholder-gray-400"
|
|
222
210
|
:class="{
|
|
223
|
-
'uppercase': uppercase && !
|
|
224
|
-
'placeholder:uppercase':
|
|
211
|
+
'uppercase': uppercase && !isTypingOnIos,
|
|
212
|
+
'placeholder:uppercase': isTypingOnIos,
|
|
225
213
|
'field-disabled': disabled,
|
|
226
214
|
'focus:placeholder-gray-900 hover:placeholder-gray-900 dark:focus:placeholder-gray-100 dark:hover:placeholder-gray-100': !disabled,
|
|
227
215
|
'text-gray-900 dark:text-gray-100': !lineThrough,
|
|
@@ -30,15 +30,11 @@ const emit = defineEmits<{
|
|
|
30
30
|
const id = useId()
|
|
31
31
|
const modelValue = defineModel<FieldTextarea['modelValue']>({ default: '' })
|
|
32
32
|
const textarea = ref<HTMLTextAreaElement>()
|
|
33
|
-
const
|
|
34
|
-
const { isDesktopBrowser, isIos } = useDevice()
|
|
33
|
+
const { isDesktopBrowser } = useDevice()
|
|
35
34
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const hideCssUppercase = computed(() => {
|
|
41
|
-
return iosUppercaseTyping.value && focused.value
|
|
35
|
+
const { isTypingOnIos, onBlur: onIosUppercaseBlur, onFocus: onIosUppercaseFocus, usesIosUppercaseKeyboard } = useIosUppercase({
|
|
36
|
+
enabled: () => props.uppercase,
|
|
37
|
+
modelValue,
|
|
42
38
|
})
|
|
43
39
|
|
|
44
40
|
onMounted(() => {
|
|
@@ -48,8 +44,7 @@ onMounted(() => {
|
|
|
48
44
|
})
|
|
49
45
|
|
|
50
46
|
function onFieldBlur(event: FocusEvent) {
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
onIosUppercaseBlur()
|
|
53
48
|
syncModelValueFromTarget(event.target)
|
|
54
49
|
emit('blur', event, modelValue.value || '')
|
|
55
50
|
}
|
|
@@ -58,18 +53,6 @@ function onFieldClick(event: MouseEvent) {
|
|
|
58
53
|
emit('click', event, modelValue.value || '')
|
|
59
54
|
}
|
|
60
55
|
|
|
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
|
-
|
|
73
56
|
function syncModelValueFromTarget(target: EventTarget | null) {
|
|
74
57
|
if (!(target instanceof HTMLTextAreaElement)) {
|
|
75
58
|
return
|
|
@@ -100,11 +83,11 @@ function syncModelValueFromTarget(target: EventTarget | null) {
|
|
|
100
83
|
ref="textarea"
|
|
101
84
|
v-model="modelValue"
|
|
102
85
|
v-bind="{ 'data-enable-grammarly': 'false' }"
|
|
103
|
-
:autocapitalize="
|
|
86
|
+
:autocapitalize="usesIosUppercaseKeyboard ? 'characters' : undefined"
|
|
104
87
|
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"
|
|
105
88
|
:class="{
|
|
106
|
-
'uppercase': uppercase && !
|
|
107
|
-
'placeholder:uppercase':
|
|
89
|
+
'uppercase': uppercase && !isTypingOnIos,
|
|
90
|
+
'placeholder:uppercase': isTypingOnIos,
|
|
108
91
|
'field-disabled': disabled,
|
|
109
92
|
'focus:placeholder-gray-900 hover:placeholder-gray-900 dark:focus:placeholder-gray-100 dark:hover:placeholder-gray-100': !disabled,
|
|
110
93
|
'px-sm py-2.5': padding && size === 'sm',
|
|
@@ -127,7 +110,7 @@ function syncModelValueFromTarget(target: EventTarget | null) {
|
|
|
127
110
|
spellcheck="false"
|
|
128
111
|
@blur="onFieldBlur"
|
|
129
112
|
@click="onFieldClick"
|
|
130
|
-
@focus="
|
|
113
|
+
@focus="onIosUppercaseFocus"
|
|
131
114
|
/>
|
|
132
115
|
|
|
133
116
|
<FieldMessage
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export default function useDevice() {
|
|
2
2
|
const { isIOS, isNative } = useCapacitor()
|
|
3
|
-
const
|
|
3
|
+
const isIosDevice = ref(false)
|
|
4
4
|
|
|
5
5
|
const isDesktopBrowser = computed(() => {
|
|
6
6
|
if (typeof navigator === 'undefined') {
|
|
@@ -20,24 +20,16 @@ export default function useDevice() {
|
|
|
20
20
|
})
|
|
21
21
|
|
|
22
22
|
onMounted(() => {
|
|
23
|
-
|
|
23
|
+
isIosDevice.value = isIOS.value || isIosBrowser()
|
|
24
24
|
})
|
|
25
25
|
|
|
26
26
|
return {
|
|
27
27
|
isDesktopBrowser,
|
|
28
|
-
|
|
28
|
+
isIosDevice,
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function
|
|
33
|
-
if (isNativeIos) {
|
|
34
|
-
return true
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (typeof navigator === 'undefined') {
|
|
38
|
-
return false
|
|
39
|
-
}
|
|
40
|
-
|
|
32
|
+
function isIosBrowser() {
|
|
41
33
|
if (/iPad|iPhone|iPod/.test(navigator.userAgent)) {
|
|
42
34
|
return true
|
|
43
35
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// iOS WebKit drops keyboard suggestions while `text-transform: uppercase` is active,
|
|
2
|
+
// so the transform is lifted during typing and the value itself is uppercased instead.
|
|
3
|
+
export default function useIosUppercase(options: {
|
|
4
|
+
enabled: MaybeRefOrGetter<boolean>
|
|
5
|
+
modelValue: Ref<string>
|
|
6
|
+
}) {
|
|
7
|
+
const { isIosDevice } = useDevice()
|
|
8
|
+
const focused = ref(false)
|
|
9
|
+
|
|
10
|
+
const usesIosUppercaseKeyboard = computed(() => {
|
|
11
|
+
return toValue(options.enabled) && isIosDevice.value
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const isTypingOnIos = computed(() => {
|
|
15
|
+
return usesIosUppercaseKeyboard.value && focused.value
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
function onFocus() {
|
|
19
|
+
if (usesIosUppercaseKeyboard.value) {
|
|
20
|
+
options.modelValue.value = options.modelValue.value.toUpperCase()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
focused.value = true
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function onBlur() {
|
|
27
|
+
focused.value = false
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
isTypingOnIos,
|
|
32
|
+
onBlur,
|
|
33
|
+
onFocus,
|
|
34
|
+
usesIosUppercaseKeyboard,
|
|
35
|
+
}
|
|
36
|
+
}
|