@dnax/ui 0.0.12 → 0.0.13
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/components/QBottomSheetFooter.vue +14 -1
- package/components/QBottomSheetHeader.vue +11 -2
- package/components/QDialog.vue +31 -3
- package/components/QDialogFooter.vue +14 -1
- package/components/QDialogHeader.vue +8 -1
- package/components/QFooter.vue +4 -0
- package/package.json +1 -1
- package/styles/main.css +26 -0
|
@@ -2,11 +2,24 @@
|
|
|
2
2
|
// QBottomSheetFooter — pied du panneau façon barre d'app (équivalent QFooter) :
|
|
3
3
|
// les actions sont embarquées dans un <q-toolbar> (min-height 50px, padding
|
|
4
4
|
// 0 12px) et alignées à droite (justify-content: flex-end — styles/main.css).
|
|
5
|
+
// no-padding retire le padding horizontal du toolbar.
|
|
5
6
|
import QToolbar from "./QToolbar.vue"
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
/** Supprime le padding du toolbar (actions collées aux bords) */
|
|
10
|
+
noPadding?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
withDefaults(defineProps<Props>(), {
|
|
14
|
+
noPadding: false,
|
|
15
|
+
})
|
|
6
16
|
</script>
|
|
7
17
|
|
|
8
18
|
<template>
|
|
9
|
-
<div
|
|
19
|
+
<div
|
|
20
|
+
class="q-bottom-sheet__footer"
|
|
21
|
+
:class="{ 'q-bottom-sheet__footer--no-padding': noPadding }"
|
|
22
|
+
>
|
|
10
23
|
<q-toolbar>
|
|
11
24
|
<slot />
|
|
12
25
|
</q-toolbar>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// QBottomSheetHeader — header du panneau façon barre d'app (équivalent QHeader) :
|
|
3
3
|
// le contenu est embarqué dans un <q-toolbar> (min-height 50px, padding 0 12px),
|
|
4
4
|
// avec titre + description + bouton fermer (équivalent DrawerHeader/DrawerTitle).
|
|
5
|
+
// no-padding retire le padding horizontal du toolbar.
|
|
5
6
|
import { inject } from "vue"
|
|
6
7
|
import { Icon } from "@iconify/vue"
|
|
7
8
|
import { icons } from "../lib/icons"
|
|
@@ -12,14 +13,22 @@ import QSpace from "./QSpace.vue"
|
|
|
12
13
|
interface Props {
|
|
13
14
|
title?: string
|
|
14
15
|
description?: string
|
|
16
|
+
/** Supprime le padding du toolbar (contenu collé aux bords) */
|
|
17
|
+
noPadding?: boolean
|
|
15
18
|
}
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
withDefaults(defineProps<Props>(), {
|
|
21
|
+
noPadding: false,
|
|
22
|
+
})
|
|
23
|
+
|
|
18
24
|
const sheet = inject(qBottomSheetKey, null)
|
|
19
25
|
</script>
|
|
20
26
|
|
|
21
27
|
<template>
|
|
22
|
-
<div
|
|
28
|
+
<div
|
|
29
|
+
class="q-bottom-sheet__header"
|
|
30
|
+
:class="{ 'q-bottom-sheet__header--no-padding': noPadding }"
|
|
31
|
+
>
|
|
23
32
|
<q-toolbar>
|
|
24
33
|
<div class="q-bottom-sheet__header-text">
|
|
25
34
|
<h2 v-if="title" class="q-bottom-sheet__title">{{ title }}</h2>
|
package/components/QDialog.vue
CHANGED
|
@@ -88,8 +88,36 @@ const onDocKeydown = (e: KeyboardEvent) => {
|
|
|
88
88
|
// « Retour » navigateur → ferme le dialog au lieu de naviguer
|
|
89
89
|
useOverlayBack(open, () => { open.value = false }, "QDialog")
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
// — Verrou du scroll de la page derrière le dialog —
|
|
92
|
+
// Compteur module-level + suivi par instance : chaque dialog verrouille au plus
|
|
93
|
+
// une fois et déverrouille au plus une fois → pile de dialogs ($q.dialog) sans
|
|
94
|
+
// déverrouillage prématuré. Verrouille html + body (iOS Safari ignore
|
|
95
|
+
// overflow:hidden sur body seul).
|
|
96
|
+
let scrollLockCount = 0
|
|
97
|
+
function setBodyScrollLock(locked: boolean) {
|
|
98
|
+
if (typeof document === "undefined") return
|
|
99
|
+
scrollLockCount = Math.max(0, scrollLockCount + (locked ? 1 : -1))
|
|
100
|
+
const on = scrollLockCount > 0
|
|
101
|
+
document.documentElement.style.overflow = on ? "hidden" : ""
|
|
102
|
+
document.body.style.overflow = on ? "hidden" : ""
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let didLock = false
|
|
106
|
+
const lockIf = (v: boolean) => {
|
|
107
|
+
if (v && !didLock) {
|
|
108
|
+
didLock = true
|
|
109
|
+
setBodyScrollLock(true)
|
|
110
|
+
}
|
|
111
|
+
else if (!v && didLock) {
|
|
112
|
+
didLock = false
|
|
113
|
+
setBodyScrollLock(false)
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
onMounted(() => lockIf(props.modelValue))
|
|
118
|
+
watch(open, lockIf)
|
|
119
|
+
onBeforeUnmount(() => {
|
|
120
|
+
if (didLock) setBodyScrollLock(false)
|
|
93
121
|
})
|
|
94
122
|
|
|
95
123
|
onMounted(() => {
|
|
@@ -98,8 +126,8 @@ onMounted(() => {
|
|
|
98
126
|
onBeforeUnmount(() => {
|
|
99
127
|
if (typeof document !== "undefined") {
|
|
100
128
|
document.removeEventListener("keydown", onDocKeydown)
|
|
101
|
-
document.body.style.overflow = ""
|
|
102
129
|
}
|
|
130
|
+
if (didLock) setBodyScrollLock(false)
|
|
103
131
|
})
|
|
104
132
|
|
|
105
133
|
const overlayClasses = computed(() => cn("q-dialog__overlay", `q-dialog__overlay--${props.position}`))
|
|
@@ -2,11 +2,24 @@
|
|
|
2
2
|
// QDialogFooter — pied de la modale façon barre d'app (équivalent QFooter) :
|
|
3
3
|
// les actions sont embarquées dans un <q-toolbar> (min-height 50px, padding
|
|
4
4
|
// 0 12px) et alignées à droite (justify-content: flex-end — styles/main.css).
|
|
5
|
+
// no-padding retire le padding horizontal du toolbar.
|
|
5
6
|
import QToolbar from "./QToolbar.vue"
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
/** Supprime le padding du toolbar (actions collées aux bords) */
|
|
10
|
+
noPadding?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
withDefaults(defineProps<Props>(), {
|
|
14
|
+
noPadding: false,
|
|
15
|
+
})
|
|
6
16
|
</script>
|
|
7
17
|
|
|
8
18
|
<template>
|
|
9
|
-
<div
|
|
19
|
+
<div
|
|
20
|
+
class="q-dialog__footer"
|
|
21
|
+
:class="{ 'q-dialog__footer--no-padding': noPadding }"
|
|
22
|
+
>
|
|
10
23
|
<q-toolbar>
|
|
11
24
|
<slot />
|
|
12
25
|
</q-toolbar>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// QDialogHeader — header de la modale façon barre d'app (équivalent QHeader) :
|
|
3
3
|
// le contenu est embarqué dans un <q-toolbar> (min-height 50px, padding 0 12px),
|
|
4
4
|
// avec titre + description + bouton fermer (équivalent DialogHeader/Title/Close).
|
|
5
|
+
// no-padding retire le padding horizontal du toolbar.
|
|
5
6
|
import { inject } from "vue"
|
|
6
7
|
import { Icon } from "@iconify/vue"
|
|
7
8
|
import { icons } from "../lib/icons"
|
|
@@ -14,17 +15,23 @@ interface Props {
|
|
|
14
15
|
description?: string
|
|
15
16
|
/** Bouton fermer */
|
|
16
17
|
showClose?: boolean
|
|
18
|
+
/** Supprime le padding du toolbar (contenu collé aux bords) */
|
|
19
|
+
noPadding?: boolean
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
const props = withDefaults(defineProps<Props>(), {
|
|
20
23
|
showClose: true,
|
|
24
|
+
noPadding: false,
|
|
21
25
|
})
|
|
22
26
|
|
|
23
27
|
const dialog = inject(qDialogKey, null)
|
|
24
28
|
</script>
|
|
25
29
|
|
|
26
30
|
<template>
|
|
27
|
-
<div
|
|
31
|
+
<div
|
|
32
|
+
class="q-dialog__header"
|
|
33
|
+
:class="{ 'q-dialog__header--no-padding': noPadding }"
|
|
34
|
+
>
|
|
28
35
|
<q-toolbar>
|
|
29
36
|
<div class="q-dialog__header-text">
|
|
30
37
|
<h2 v-if="title" class="q-dialog__title">{{ title }}</h2>
|
package/components/QFooter.vue
CHANGED
|
@@ -16,6 +16,8 @@ interface Props {
|
|
|
16
16
|
translucent?: boolean | number
|
|
17
17
|
/** Glassmorphism marqué : fond très translucide + flou fort + bordure claire */
|
|
18
18
|
glass?: boolean
|
|
19
|
+
/** Supprime le padding horizontal (éléments collés aux bords, safe-area conservée) */
|
|
20
|
+
noPadding?: boolean
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
const props = withDefaults(defineProps<Props>(), {
|
|
@@ -23,6 +25,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
23
25
|
elevated: false,
|
|
24
26
|
reveal: false,
|
|
25
27
|
bordered: false,
|
|
28
|
+
noPadding: false,
|
|
26
29
|
})
|
|
27
30
|
|
|
28
31
|
const rootEl = ref<HTMLElement | null>(null)
|
|
@@ -71,6 +74,7 @@ onBeforeUnmount(() => {
|
|
|
71
74
|
'q-footer--reveal-hidden': props.reveal && !visible,
|
|
72
75
|
'q-footer--translucent': props.translucent === true || typeof props.translucent === 'number',
|
|
73
76
|
'q-footer--glass': props.glass,
|
|
77
|
+
'q-footer--no-padding': props.noPadding,
|
|
74
78
|
}"
|
|
75
79
|
:style="translucentStyle"
|
|
76
80
|
>
|
package/package.json
CHANGED
package/styles/main.css
CHANGED
|
@@ -582,6 +582,20 @@ html.dark body {
|
|
|
582
582
|
z-index: 100;
|
|
583
583
|
}
|
|
584
584
|
|
|
585
|
+
/* no-padding : horizontal collé aux bords — safe-area conservées */
|
|
586
|
+
.q-footer--no-padding {
|
|
587
|
+
padding: 4px 0;
|
|
588
|
+
padding-bottom: 0;
|
|
589
|
+
padding-bottom: constant(safe-area-inset-bottom);
|
|
590
|
+
padding-bottom: env(safe-area-inset-bottom);
|
|
591
|
+
padding-left: 0;
|
|
592
|
+
padding-left: constant(safe-area-inset-left);
|
|
593
|
+
padding-left: env(safe-area-inset-left);
|
|
594
|
+
padding-right: 0;
|
|
595
|
+
padding-right: constant(safe-area-inset-right);
|
|
596
|
+
padding-right: env(safe-area-inset-right);
|
|
597
|
+
}
|
|
598
|
+
|
|
585
599
|
.q-footer--elevated {
|
|
586
600
|
box-shadow: 0 -2px 4px rgb(0 0 0 / 0.2);
|
|
587
601
|
}
|
|
@@ -4644,6 +4658,12 @@ html.dark body {
|
|
|
4644
4658
|
justify-content: flex-end; /* actions alignées à droite (défaut) */
|
|
4645
4659
|
}
|
|
4646
4660
|
|
|
4661
|
+
.q-bottom-sheet__footer--no-padding .q-toolbar,
|
|
4662
|
+
.q-bottom-sheet__header--no-padding .q-toolbar,
|
|
4663
|
+
.q-dialog__header--no-padding .q-toolbar {
|
|
4664
|
+
padding: 0; /* no-padding : contenu collé aux bords */
|
|
4665
|
+
}
|
|
4666
|
+
|
|
4647
4667
|
.q-bottom-sheet__panel--dark .q-bottom-sheet__header,
|
|
4648
4668
|
.q-bottom-sheet__panel--dark .q-bottom-sheet__footer {
|
|
4649
4669
|
border-color: rgb(255 255 255 / 0.12);
|
|
@@ -5847,6 +5867,8 @@ html.dark body {
|
|
|
5847
5867
|
max-width: 90vw;
|
|
5848
5868
|
max-height: 90vh;
|
|
5849
5869
|
overflow: auto;
|
|
5870
|
+
/* Le scroll du contenu ne doit jamais se chaîner à la page derrière */
|
|
5871
|
+
overscroll-behavior: contain;
|
|
5850
5872
|
background-color: #fff;
|
|
5851
5873
|
color: inherit;
|
|
5852
5874
|
border-radius: var(--q-radius);
|
|
@@ -6014,6 +6036,10 @@ html.dark body {
|
|
|
6014
6036
|
justify-content: flex-end; /* actions alignées à droite (défaut) */
|
|
6015
6037
|
}
|
|
6016
6038
|
|
|
6039
|
+
.q-dialog__footer--no-padding .q-toolbar {
|
|
6040
|
+
padding: 0; /* no-padding : actions collées aux bords */
|
|
6041
|
+
}
|
|
6042
|
+
|
|
6017
6043
|
.q-dialog__body {
|
|
6018
6044
|
min-height: 0;
|
|
6019
6045
|
padding: 4px 16px 16px;
|