@saasmakers/ui 2.0.61 → 2.0.63
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/assets/styles/base.css +10 -0
- package/app/components/auth/AuthEmailConnect.vue +1 -0
- package/app/components/auth/AuthSocialConnect.vue +11 -2
- package/app/components/bases/BaseButton.vue +20 -7
- package/app/components/fields/FieldInput.vue +26 -14
- package/app/components/fields/FieldTextarea.vue +9 -0
- package/app/composables/useDevice.ts +12 -1
- package/app/types/bases.d.ts +1 -3
- package/package.json +1 -1
|
@@ -4,6 +4,16 @@ html,
|
|
|
4
4
|
body {
|
|
5
5
|
scrollbar-gutter: stable;
|
|
6
6
|
touch-action: manipulation;
|
|
7
|
+
-webkit-touch-callout: none;
|
|
8
|
+
-webkit-user-select: none;
|
|
9
|
+
user-select: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
input,
|
|
13
|
+
textarea,
|
|
14
|
+
[contenteditable='true'] {
|
|
15
|
+
-webkit-user-select: text;
|
|
16
|
+
user-select: text;
|
|
7
17
|
}
|
|
8
18
|
|
|
9
19
|
/* Theme backgrounds */
|
|
@@ -141,14 +141,23 @@ function processGoogleCallback(event: MessageEvent) {
|
|
|
141
141
|
<img
|
|
142
142
|
v-if="provider === 'apple'"
|
|
143
143
|
:alt="t('appleLogo')"
|
|
144
|
-
class="
|
|
144
|
+
class="dark:invert"
|
|
145
|
+
:class="{
|
|
146
|
+
'mr-2 w-4': size === 'xs' || size === 'sm',
|
|
147
|
+
'mr-2.5 w-4.5': size === 'base',
|
|
148
|
+
'mr-2.5 w-5': size === 'lg',
|
|
149
|
+
}"
|
|
145
150
|
src="/images/auth/AuthSocialConnect/apple.svg"
|
|
146
151
|
>
|
|
147
152
|
|
|
148
153
|
<img
|
|
149
154
|
v-else-if="provider === 'google'"
|
|
150
155
|
:alt="t('googleLogo')"
|
|
151
|
-
class="
|
|
156
|
+
:class="{
|
|
157
|
+
'mr-2 w-4': size === 'xs' || size === 'sm',
|
|
158
|
+
'mr-2.5 w-4.5': size === 'base',
|
|
159
|
+
'mr-2.5 w-5': size === 'lg',
|
|
160
|
+
}"
|
|
152
161
|
src="/images/auth/AuthSocialConnect/google.svg"
|
|
153
162
|
>
|
|
154
163
|
</BaseButton>
|
|
@@ -37,6 +37,23 @@ const hasFixedSize = computed(() => {
|
|
|
37
37
|
return props.shape === 'square' || props.shape === 'circle'
|
|
38
38
|
})
|
|
39
39
|
|
|
40
|
+
const contentSize = computed((): BaseSize => {
|
|
41
|
+
switch (props.size) {
|
|
42
|
+
case 'lg': {
|
|
43
|
+
return 'base'
|
|
44
|
+
}
|
|
45
|
+
case 'sm': {
|
|
46
|
+
return 'xs'
|
|
47
|
+
}
|
|
48
|
+
case 'xs': {
|
|
49
|
+
return '2xs'
|
|
50
|
+
}
|
|
51
|
+
default: {
|
|
52
|
+
return 'sm'
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
|
|
40
57
|
function onClick(event: MouseEvent) {
|
|
41
58
|
if (!props.loading) {
|
|
42
59
|
if (props.confirmation) {
|
|
@@ -69,12 +86,10 @@ function onClick(event: MouseEvent) {
|
|
|
69
86
|
'shadow-sm': !light,
|
|
70
87
|
'rounded-lg': shape !== 'circle',
|
|
71
88
|
'rounded-full': shape === 'circle',
|
|
72
|
-
'h-6 w-6': size === '2xs' && hasFixedSize,
|
|
73
89
|
'h-8 w-8': size === 'xs' && hasFixedSize && !confirming,
|
|
74
90
|
'h-10 w-10': size === 'sm' && hasFixedSize && !confirming,
|
|
75
91
|
'h-12 w-12': size === 'base' && hasFixedSize && !confirming,
|
|
76
92
|
'h-14 w-14': size === 'lg' && hasFixedSize && !confirming,
|
|
77
|
-
'h-16 w-16': size === 'xl' && hasFixedSize && !confirming,
|
|
78
93
|
'border-gray-900 dark:border-gray-100 bg-gray-900 dark:bg-gray-100 text-white dark:text-black': color === 'black' && !light,
|
|
79
94
|
'hover:bg-black dark:hover:bg-white hover:text-white dark:hover:text-black': color === 'black' && !light && !disabled && !loading,
|
|
80
95
|
'border-gray-900 dark:border-gray-100 text-gray-900 dark:text-gray-100': color === 'black' && light,
|
|
@@ -98,12 +113,10 @@ function onClick(event: MouseEvent) {
|
|
|
98
113
|
'border-white dark:border-gray-900 text-white dark:text-black': color === 'white' && light,
|
|
99
114
|
'hover:border-black dark:hover:border-white hover:text-black dark:hover:text-white': color !== 'white' && light && !disabled && !loading,
|
|
100
115
|
'hover:bg-white dark:hover:bg-gray-900 hover:text-gray-800 dark:hover:text-gray-200': color === 'white' && light && !disabled && !loading,
|
|
101
|
-
'h-6 px-3': size === '2xs' && (!hasFixedSize || confirming),
|
|
102
116
|
'h-8 px-4': size === 'xs' && (!hasFixedSize || confirming),
|
|
103
117
|
'h-10 px-5': size === 'sm' && (!hasFixedSize || confirming),
|
|
104
118
|
'h-12 px-6': size === 'base' && (!hasFixedSize || confirming),
|
|
105
|
-
'h-
|
|
106
|
-
'h-14 px-7': size === 'xl' && (!hasFixedSize || confirming),
|
|
119
|
+
'h-14 px-6.5': size === 'lg' && (!hasFixedSize || confirming),
|
|
107
120
|
}"
|
|
108
121
|
:disabled="disabled"
|
|
109
122
|
:to="to"
|
|
@@ -121,7 +134,7 @@ function onClick(event: MouseEvent) {
|
|
|
121
134
|
:color="iconColor"
|
|
122
135
|
:icon="confirming ? undefined : icon"
|
|
123
136
|
:reverse="reverse"
|
|
124
|
-
:size="
|
|
137
|
+
:size="contentSize"
|
|
125
138
|
:text="confirming ? t('confirm') : text"
|
|
126
139
|
/>
|
|
127
140
|
</span>
|
|
@@ -130,7 +143,7 @@ function onClick(event: MouseEvent) {
|
|
|
130
143
|
v-if="loading"
|
|
131
144
|
class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2"
|
|
132
145
|
:color="!background ? 'black' : light ? color : color === 'white' ? 'indigo' : 'white'"
|
|
133
|
-
:size="
|
|
146
|
+
:size="contentSize"
|
|
134
147
|
/>
|
|
135
148
|
</component>
|
|
136
149
|
</template>
|
|
@@ -67,6 +67,8 @@ function focus() {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
function onFieldBlur(event: FocusEvent) {
|
|
70
|
+
syncModelValueFromTarget(event.target)
|
|
71
|
+
|
|
70
72
|
if (props.trim) {
|
|
71
73
|
modelValue.value = modelValue.value.toString().trim()
|
|
72
74
|
}
|
|
@@ -79,23 +81,12 @@ function onFieldFocus(event: FocusEvent) {
|
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
function onFieldInput(event: Event) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (props.type === 'number' && props.max && Number.parseInt(value) > props.max) {
|
|
85
|
-
value = props.max.toString()
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (props.slugOnly) {
|
|
89
|
-
value = value.toString().toLowerCase().replace(/[^a-z0-9_-]/g, '')
|
|
90
|
-
}
|
|
91
|
-
else if (props.lowercaseOnly) {
|
|
92
|
-
value = value.toString().toLowerCase()
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
modelValue.value = value
|
|
84
|
+
syncModelValueFromTarget(event.target)
|
|
96
85
|
}
|
|
97
86
|
|
|
98
87
|
function onFieldKeyDown(event: KeyboardEvent) {
|
|
88
|
+
syncModelValueFromTarget(event.target)
|
|
89
|
+
|
|
99
90
|
const value = (event.target as HTMLInputElement).value
|
|
100
91
|
|
|
101
92
|
if (['Control', 'Escape'].includes(event.key)) {
|
|
@@ -138,6 +129,27 @@ function onTogglePasswordVisibility() {
|
|
|
138
129
|
showPassword.value = !showPassword.value
|
|
139
130
|
}
|
|
140
131
|
|
|
132
|
+
function syncModelValueFromTarget(target: EventTarget | null) {
|
|
133
|
+
if (!(target instanceof HTMLInputElement)) {
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let value = target.value
|
|
138
|
+
|
|
139
|
+
if (props.type === 'number' && props.max && Number.parseInt(value) > props.max) {
|
|
140
|
+
value = props.max.toString()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (props.slugOnly) {
|
|
144
|
+
value = value.toString().toLowerCase().replace(/[^a-z0-9_-]/g, '')
|
|
145
|
+
}
|
|
146
|
+
else if (props.lowercaseOnly) {
|
|
147
|
+
value = value.toString().toLowerCase()
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
modelValue.value = value
|
|
151
|
+
}
|
|
152
|
+
|
|
141
153
|
defineExpose({
|
|
142
154
|
blur,
|
|
143
155
|
focus,
|
|
@@ -39,12 +39,21 @@ onMounted(() => {
|
|
|
39
39
|
})
|
|
40
40
|
|
|
41
41
|
function onFieldBlur(event: FocusEvent) {
|
|
42
|
+
syncModelValueFromTarget(event.target)
|
|
42
43
|
emit('blur', event, modelValue.value || '')
|
|
43
44
|
}
|
|
44
45
|
|
|
45
46
|
function onFieldClick(event: MouseEvent) {
|
|
46
47
|
emit('click', event, modelValue.value || '')
|
|
47
48
|
}
|
|
49
|
+
|
|
50
|
+
function syncModelValueFromTarget(target: EventTarget | null) {
|
|
51
|
+
if (!(target instanceof HTMLTextAreaElement)) {
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
modelValue.value = target.value
|
|
56
|
+
}
|
|
48
57
|
</script>
|
|
49
58
|
|
|
50
59
|
<template>
|
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
export default function useDevice() {
|
|
2
|
+
const { isNative } = useCapacitor()
|
|
3
|
+
|
|
2
4
|
const isDesktopBrowser = computed(() => {
|
|
3
5
|
if (typeof navigator === 'undefined') {
|
|
4
6
|
return true
|
|
5
7
|
}
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
if (isNative.value) {
|
|
10
|
+
return false
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Chromium Client Hints — unavailable on Safari / Firefox / iOS WebKit
|
|
14
|
+
if (navigator.userAgentData) {
|
|
15
|
+
return !navigator.userAgentData.mobile
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return !/Android|iPad|iPhone|iPod|Mobile/i.test(navigator.userAgent)
|
|
8
19
|
})
|
|
9
20
|
|
|
10
21
|
return { isDesktopBrowser }
|
package/app/types/bases.d.ts
CHANGED
|
@@ -71,11 +71,9 @@ export interface BaseButton {
|
|
|
71
71
|
export type BaseButtonShape = 'circle' | 'default' | 'square'
|
|
72
72
|
|
|
73
73
|
export type BaseButtonSize
|
|
74
|
-
= | '
|
|
75
|
-
| 'base'
|
|
74
|
+
= | 'base'
|
|
76
75
|
| 'lg'
|
|
77
76
|
| 'sm'
|
|
78
|
-
| 'xl'
|
|
79
77
|
| 'xs'
|
|
80
78
|
|
|
81
79
|
export type BaseButtonType = 'button' | 'reset' | 'submit'
|