@saasmakers/ui 2.0.77 → 2.0.79
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.
|
@@ -18,6 +18,7 @@ const visible = defineModel<boolean>({ default: false })
|
|
|
18
18
|
const contentRef = ref<HTMLElement>()
|
|
19
19
|
const panelRef = ref<HTMLElement>()
|
|
20
20
|
const { release: onAfterLeave } = useDialog(visible, panelRef)
|
|
21
|
+
const { isKeyboardOpen, keyboardInset } = useKeyboardInset()
|
|
21
22
|
|
|
22
23
|
const drag = reactive({
|
|
23
24
|
closing: false,
|
|
@@ -32,6 +33,17 @@ const closeThreshold = computed(() => {
|
|
|
32
33
|
return (panelRef.value?.offsetHeight ?? 320) * closeThresholdRatio
|
|
33
34
|
})
|
|
34
35
|
|
|
36
|
+
// Use `bottom` (not transform) so keyboard lift does not fight drag-to-dismiss.
|
|
37
|
+
const panelStyle = computed(() => {
|
|
38
|
+
return {
|
|
39
|
+
bottom: `${keyboardInset.value}px`,
|
|
40
|
+
maxHeight: isKeyboardOpen.value
|
|
41
|
+
? `calc(100dvh - ${keyboardInset.value}px - env(safe-area-inset-top))`
|
|
42
|
+
: undefined,
|
|
43
|
+
transform: drag.closing ? 'translateY(100%)' : drag.offset > 0 ? `translateY(${drag.offset}px)` : undefined,
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
35
47
|
function onBackdropClick() {
|
|
36
48
|
if (props.closeOnBackdrop) {
|
|
37
49
|
onClose()
|
|
@@ -210,15 +222,14 @@ watch(visible, (isVisible) => {
|
|
|
210
222
|
ref="panelRef"
|
|
211
223
|
:aria-label="props['aria-label']"
|
|
212
224
|
aria-modal="true"
|
|
213
|
-
class="layout-bottom-sheet fixed bottom-0 left-0 right-0 z-[60] mx-auto max-h-[85dvh] max-w-screen-md flex flex-col rounded-t-2xl bg-white text-gray-900 app-text shadow-lg outline-none
|
|
225
|
+
class="layout-bottom-sheet fixed bottom-0 left-0 right-0 z-[60] mx-auto max-h-[85dvh] max-w-screen-md flex flex-col rounded-t-2xl bg-white text-gray-900 app-text shadow-lg outline-none dark:bg-gray-900 dark:text-gray-100"
|
|
214
226
|
:class="{
|
|
227
|
+
'safe-bottom': !isKeyboardOpen,
|
|
215
228
|
'transition-none motion-reduce:transition-none': drag.isDragging,
|
|
216
|
-
'transition-transform duration-
|
|
229
|
+
'transition-[bottom,max-height,transform] duration-250 ease-out motion-reduce:transition-none motion-reduce:duration-0': !drag.isDragging,
|
|
217
230
|
}"
|
|
231
|
+
:style="panelStyle"
|
|
218
232
|
role="dialog"
|
|
219
|
-
:style="{
|
|
220
|
-
transform: drag.closing ? 'translateY(100%)' : drag.offset > 0 ? `translateY(${drag.offset}px)` : undefined,
|
|
221
|
-
}"
|
|
222
233
|
tabindex="-1"
|
|
223
234
|
@transitionend="onPanelTransitionEnd"
|
|
224
235
|
>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { PluginListenerHandle } from '@capacitor/core'
|
|
2
|
+
import { Keyboard } from '@capacitor/keyboard'
|
|
3
|
+
|
|
4
|
+
// Tracks the on-screen keyboard height on iOS Capacitor only.
|
|
5
|
+
// With Keyboard.resize = 'none', the WebView does not shrink; consumers shift
|
|
6
|
+
// fixed UI (e.g. bottom sheets) with this inset so it moves with the keyboard
|
|
7
|
+
// animation instead of jumping after it finishes. Android keeps soft-input
|
|
8
|
+
// resize, so applying the inset there would double-offset.
|
|
9
|
+
export default function useKeyboardInset() {
|
|
10
|
+
const { isIOS, isPluginAvailable } = useCapacitor()
|
|
11
|
+
const keyboardInset = ref(0)
|
|
12
|
+
|
|
13
|
+
const isKeyboardOpen = computed(() => {
|
|
14
|
+
return keyboardInset.value > 0
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const listenerHandles: PluginListenerHandle[] = []
|
|
18
|
+
|
|
19
|
+
onMounted(async () => {
|
|
20
|
+
if (!import.meta.client || !isIOS.value || !isPluginAvailable('Keyboard')) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
listenerHandles.push(
|
|
25
|
+
await Keyboard.addListener('keyboardWillShow', (info) => {
|
|
26
|
+
keyboardInset.value = info.keyboardHeight
|
|
27
|
+
}),
|
|
28
|
+
await Keyboard.addListener('keyboardWillHide', () => {
|
|
29
|
+
keyboardInset.value = 0
|
|
30
|
+
}),
|
|
31
|
+
)
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
onBeforeUnmount(() => {
|
|
35
|
+
for (const handle of listenerHandles) {
|
|
36
|
+
void handle.remove()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
listenerHandles.length = 0
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
isKeyboardOpen,
|
|
44
|
+
keyboardInset,
|
|
45
|
+
}
|
|
46
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saasmakers/ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.79",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Reusable Nuxt UI components for SaaS Makers projects",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@capacitor/core": "8.4.0",
|
|
29
|
+
"@capacitor/keyboard": "8.0.6",
|
|
29
30
|
"@capacitor/preferences": "8.0.1",
|
|
30
31
|
"@capgo/capacitor-social-login": "8.3.22",
|
|
31
32
|
"@nuxt/icon": "2.2.3",
|