@ktortu/aaa 0.9.6 → 0.9.8
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/dialog/dialog.css +85 -30
- package/fesm2022/ktortu-aaa-cdk.mjs +5 -0
- package/fesm2022/ktortu-aaa-cdk.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-dialog.mjs +172 -59
- package/fesm2022/ktortu-aaa-dialog.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-forms.mjs +173 -69
- package/fesm2022/ktortu-aaa-forms.mjs.map +1 -1
- package/forms/multi-select/multi-select.css +3 -53
- package/forms/styles/select-panel.css +81 -40
- package/package.json +1 -1
- package/themes/theme-catppuccin.css +3 -1
- package/themes/theme-cyberpunk.css +1 -1
- package/types/ktortu-aaa-cdk.d.ts +5 -0
- package/types/ktortu-aaa-dialog.d.ts +38 -28
- package/types/ktortu-aaa-forms.d.ts +51 -10
package/dialog/dialog.css
CHANGED
|
@@ -54,8 +54,16 @@
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
/* ============ Dimensionnement du pane overlay (panelClass: kt-dialog) ============ */
|
|
57
|
+
/* Le PLAFOND réel vient de la config (`KT_DIALOG_AAA_DEFAULTS.maxWidth = var(--dialog-max-width)`),
|
|
58
|
+
posé en STYLE INLINE sur le pane par l'overlay CDK. Indispensable : le CDK injecte à
|
|
59
|
+
l'exécution `.cdk-overlay-pane { max-width: 100% }` HORS layer, qui bat toute règle de cette
|
|
60
|
+
feuille quand elle est importée via layer(kt-aaa). La règle ci-dessous n'est qu'une
|
|
61
|
+
CEINTURE-BRETELLES pour un import SANS layer (spécificité 0,2,0 > 0,1,0).
|
|
62
|
+
Mode centré (défaut) : la classe .kt-dialog--centered ne porte VOLONTAIREMENT aucune règle
|
|
63
|
+
interne — hook public, symétrique de --fullscreen/--sheet, qui permet aux devs de
|
|
64
|
+
cibler/identifier le mode centré en CSS. Ne pas la supprimer. */
|
|
57
65
|
.cdk-overlay-pane.kt-dialog {
|
|
58
|
-
inline-size: var(--dialog-max-width);
|
|
66
|
+
max-inline-size: var(--dialog-max-width);
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
/* ============ Surface = conteneur CDK (porte role="dialog") ============ */
|
|
@@ -63,6 +71,7 @@
|
|
|
63
71
|
display: flex;
|
|
64
72
|
flex-direction: column;
|
|
65
73
|
box-sizing: border-box;
|
|
74
|
+
inline-size: 100%;
|
|
66
75
|
/* Reflow AAA (1.4.10) : conteneur plafonné en hauteur ; le contenu long ([ktDialogContent])
|
|
67
76
|
scrolle verticalement (jamais en 2D), titre et actions restant visibles. */
|
|
68
77
|
max-block-size: var(--dialog-max-height);
|
|
@@ -255,6 +264,9 @@
|
|
|
255
264
|
/* ===================== PLEIN ÉCRAN (kt-dialog--fullscreen) =====================
|
|
256
265
|
Surface bord-à-bord ; [ktDialogHeader] devient la top app bar. */
|
|
257
266
|
.cdk-overlay-pane.kt-dialog--fullscreen {
|
|
267
|
+
/* Retune le token lu par le style inline du pane (config `maxWidth`) : bord-à-bord. */
|
|
268
|
+
--dialog-max-width: 100vw;
|
|
269
|
+
|
|
258
270
|
inline-size: 100vw;
|
|
259
271
|
max-inline-size: 100vw;
|
|
260
272
|
}
|
|
@@ -288,53 +300,97 @@
|
|
|
288
300
|
padding-block-end: max(var(--dialog-pad), env(safe-area-inset-bottom, 0px));
|
|
289
301
|
}
|
|
290
302
|
|
|
291
|
-
/* ===================== BOTTOM-SHEET (kt-dialog--sheet) =====================
|
|
292
|
-
|
|
293
|
-
|
|
303
|
+
/* ===================== BOTTOM-SHEET (kt-dialog--sheet) — ADR-0005 =====================
|
|
304
|
+
Le CONTENEUR est un scroller plein écran à snap : le spacer (un écran) porte le snap « fermé »,
|
|
305
|
+
la carte (.kt-dialog-container__layout) le snap « ouvert ». Le drag-to-dismiss s'attrape
|
|
306
|
+
PARTOUT au toucher (scroll natif, arbitrage par latching avec [ktDialogContent]) ;
|
|
307
|
+
entrée/sortie = scrolls programmatiques (KtDialogContainer). Tokens --kt-sheet-* partagés. */
|
|
308
|
+
.cdk-overlay-pane.kt-dialog--sheet {
|
|
309
|
+
/* Retune le token lu par le style inline du pane (config `maxWidth`) : pleine largeur.
|
|
310
|
+
(Le conteneur est en position:fixed — seul le token du pane doit suivre.) */
|
|
311
|
+
--dialog-max-width: 100%;
|
|
312
|
+
}
|
|
294
313
|
.cdk-overlay-pane.kt-dialog--sheet .cdk-dialog-container {
|
|
295
314
|
position: fixed;
|
|
296
|
-
inset:
|
|
315
|
+
inset: 0;
|
|
316
|
+
display: block;
|
|
297
317
|
inline-size: 100%;
|
|
298
318
|
max-inline-size: 100%;
|
|
319
|
+
max-block-size: none;
|
|
320
|
+
overflow-y: auto;
|
|
321
|
+
scroll-snap-type: y mandatory;
|
|
322
|
+
/* Pas de scroll chaining vers la page (l'overlay CDK bloque déjà — ceinture et bretelles). */
|
|
323
|
+
overscroll-behavior: contain;
|
|
324
|
+
/* Le scroller EST le geste : pas de barre de défilement visible sur l'overlay. */
|
|
325
|
+
scrollbar-width: none;
|
|
326
|
+
background: transparent;
|
|
327
|
+
border: 0;
|
|
328
|
+
border-radius: 0;
|
|
329
|
+
box-shadow: none;
|
|
330
|
+
backdrop-filter: none;
|
|
331
|
+
transform: none;
|
|
332
|
+
animation: none;
|
|
333
|
+
transition: none;
|
|
334
|
+
/* Le scroller DOIT capter le tactile (`pointer-events: auto`, hérité du pane). Un
|
|
335
|
+
`pointer-events: none` (pour laisser les taps traverser vers le backdrop CDK) EMPÊCHE iOS
|
|
336
|
+
Safari de défiler ce conteneur au doigt : le geste de drag-to-dismiss fuit alors vers la
|
|
337
|
+
page (pull-to-refresh) et la sheet ne se ferme jamais. Même choix que le popup du Select.
|
|
338
|
+
Le scrim sombre reste le backdrop CDK (derrière ce conteneur transparent) ; la fermeture
|
|
339
|
+
au tap-extérieur est portée par le spacer (`(click)` → `onScrimClick`), le verrou de scroll
|
|
340
|
+
du fond par `KtBodyScrollLock` (cf. `KtDialogContainer`). */
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/* Spacer de dismiss : un écran entier au-dessus de la carte (snap « fermé »). Cliquable pour
|
|
344
|
+
fermer (tap-extérieur, façon backdrop) ET saisissable au doigt pour le drag (scroll natif). */
|
|
345
|
+
.cdk-overlay-pane.kt-dialog--sheet .kt-dialog-container__spacer {
|
|
346
|
+
block-size: 100%;
|
|
347
|
+
scroll-snap-align: start;
|
|
348
|
+
scroll-snap-stop: always;
|
|
349
|
+
cursor: default;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* La carte : reprend la surface du dialog (déplacée du conteneur, devenu scroller). */
|
|
353
|
+
.cdk-overlay-pane.kt-dialog--sheet .kt-dialog-container__layout {
|
|
354
|
+
scroll-snap-align: end;
|
|
355
|
+
scroll-snap-stop: always;
|
|
356
|
+
display: flex;
|
|
357
|
+
flex-direction: column;
|
|
358
|
+
box-sizing: border-box;
|
|
359
|
+
inline-size: 100%;
|
|
299
360
|
max-block-size: var(--kt-sheet-max-block-size, 85svh);
|
|
361
|
+
overflow: hidden;
|
|
362
|
+
color: var(--dialog-fg);
|
|
363
|
+
background: var(--dialog-bg);
|
|
364
|
+
border: var(--dialog-border-width) solid var(--dialog-border-color);
|
|
300
365
|
border-block-end: 0;
|
|
301
366
|
border-start-start-radius: var(--kt-sheet-radius, 16px);
|
|
302
367
|
border-start-end-radius: var(--kt-sheet-radius, 16px);
|
|
303
368
|
border-end-start-radius: 0;
|
|
304
369
|
border-end-end-radius: 0;
|
|
305
370
|
box-shadow: var(--kt-sheet-shadow, 0 -4px 16px rgb(0 0 0 / 12%));
|
|
306
|
-
|
|
307
|
-
translate: 0 0;
|
|
308
|
-
/* Entrée : glissement du bas (keyframe PARTAGÉE kt-sheet-in, cf. foundation.css). */
|
|
309
|
-
animation: kt-sheet-in var(--kt-sheet-anim-duration, 120ms) ease;
|
|
310
|
-
transition: translate var(--kt-sheet-anim-duration, 120ms) ease;
|
|
311
|
-
}
|
|
312
|
-
.cdk-overlay-pane.kt-dialog--sheet .cdk-dialog-container.kt-dialog-sheet--dragging,
|
|
313
|
-
.cdk-overlay-pane.kt-dialog--sheet .cdk-dialog-container.kt-dialog-container--dragging {
|
|
314
|
-
transition: none;
|
|
371
|
+
backdrop-filter: var(--dialog-backdrop-filter, none);
|
|
315
372
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
373
|
+
|
|
374
|
+
/* Relais flex vers l'hôte projeté : la carte remplace le conteneur comme colonne
|
|
375
|
+
(header/actions fixes, [ktDialogContent] seul scrollable). */
|
|
376
|
+
.cdk-overlay-pane.kt-dialog--sheet .kt-dialog-container__layout > * {
|
|
377
|
+
display: flex;
|
|
378
|
+
flex-direction: column;
|
|
379
|
+
flex: 1 1 auto;
|
|
380
|
+
min-block-size: 0;
|
|
319
381
|
}
|
|
320
382
|
|
|
321
|
-
/* Poignée
|
|
322
|
-
|
|
323
|
-
|
|
383
|
+
/* Poignée DÉCORATIVE auto-rendue par le conteneur (ADR-0005) : simple affordance « ceci se
|
|
384
|
+
tire » — la sheet s'attrape partout. Ni cursor grab (mensonger : pas de drag souris), ni
|
|
385
|
+
touch-action (le geste EST le scroll), ni cible 44px (ce n'est plus un contrôle).
|
|
386
|
+
Opt-out : panelClass additionnel `kt-dialog--no-handle` à l'ouverture. */
|
|
324
387
|
.cdk-overlay-pane.kt-dialog--sheet .kt-dialog-container__sheet-handle {
|
|
325
388
|
display: flex;
|
|
326
389
|
align-items: center;
|
|
327
390
|
justify-content: center;
|
|
328
391
|
flex: none;
|
|
329
|
-
block-size:
|
|
330
|
-
cursor: grab;
|
|
331
|
-
touch-action: none; /* le geste ne déclenche pas le scroll de la page */
|
|
332
|
-
}
|
|
333
|
-
.cdk-overlay-pane.kt-dialog--sheet [ktDialogSheetHandle]:active,
|
|
334
|
-
.cdk-overlay-pane.kt-dialog--sheet .kt-dialog-container__sheet-handle:active {
|
|
335
|
-
cursor: grabbing;
|
|
392
|
+
block-size: 28px;
|
|
336
393
|
}
|
|
337
|
-
.cdk-overlay-pane.kt-dialog--sheet [ktDialogSheetHandle]::before,
|
|
338
394
|
.cdk-overlay-pane.kt-dialog--sheet .kt-dialog-container__sheet-handle::before {
|
|
339
395
|
content: '';
|
|
340
396
|
inline-size: 2.25rem;
|
|
@@ -343,9 +399,8 @@
|
|
|
343
399
|
background: var(--kt-sheet-grab-color, var(--kt-outline, #c4c7c5));
|
|
344
400
|
}
|
|
345
401
|
|
|
346
|
-
/* Mouvement réduit : pas de
|
|
402
|
+
/* Mouvement réduit : pas de fondu (WCAG 2.3.3). La sheet gère le sien en JS (scroll instantané). */
|
|
347
403
|
@media (prefers-reduced-motion: reduce) {
|
|
348
|
-
.cdk-overlay-pane.kt-dialog--sheet .cdk-dialog-container,
|
|
349
404
|
.cdk-overlay-pane.kt-dialog--fullscreen .cdk-dialog-container {
|
|
350
405
|
transition: none;
|
|
351
406
|
translate: 0 0;
|
|
@@ -14,6 +14,11 @@ import { map } from 'rxjs';
|
|
|
14
14
|
* gère que le glissement. Le gating « écran compact uniquement » reste à l'appelant (signal `isCompact`
|
|
15
15
|
* de `KtViewport`) — la primitive est volontairement agnostique.
|
|
16
16
|
*
|
|
17
|
+
* @deprecated ADR-0005 — les sheets de la lib (Select compact, Dialog `sheet`) sont désormais des
|
|
18
|
+
* scrollers à snap : le drag-to-dismiss « attrapable partout » et l'arbitrage avec le scroll
|
|
19
|
+
* interne sont NATIFS ; cette primitive « poignée + translate » n'a plus de consommateur interne.
|
|
20
|
+
* Sera supprimée dans une prochaine version majeure.
|
|
21
|
+
*
|
|
17
22
|
* @param opts Élément à translater, callback de fermeture, classe de drag et seuil optionnel.
|
|
18
23
|
* @returns Un contrôleur {@link KtSheetDrag} (`start` à brancher sur `pointerdown`, `destroy` au teardown).
|
|
19
24
|
* @example
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ktortu-aaa-cdk.mjs","sources":["../../../../projects/ktortu/aaa/cdk/sheet/sheet-drag.ts","../../../../projects/ktortu/aaa/cdk/sheet/body-scroll-lock.ts","../../../../projects/ktortu/aaa/cdk/breakpoints/breakpoints.ts","../../../../projects/ktortu/aaa/cdk/breakpoints/viewport.ts","../../../../projects/ktortu/aaa/cdk/id-generator.ts","../../../../projects/ktortu/aaa/cdk/audit.ts","../../../../projects/ktortu/aaa/cdk/ktortu-aaa-cdk.ts"],"sourcesContent":["/** Contrôleur de drag-to-dismiss d'une bottom-sheet. À câbler sur le `pointerdown` de la poignée. */\nexport interface KtSheetDrag {\n /** Démarre le suivi du glissement ; à brancher sur le `pointerdown` de la poignée. */\n start(event: PointerEvent): void;\n /** Détache les écouteurs et réinitialise l'état ; à appeler à la destruction. */\n destroy(): void;\n}\n\nexport interface KtSheetDragOptions {\n /** Élément translaté pendant le glissement (la feuille elle-même). Lu à chaque `start`. */\n pane: () => HTMLElement | null;\n /** Fermeture déclenchée quand le seuil est franchi (ex. `expanded.set(false)` / `dialogRef.close()`). */\n onDismiss: () => void;\n /** Classe togglée sur le pane pendant le drag (coupe la transition CSS du glissement). */\n draggingClass: string;\n /** Fraction de la hauteur de la feuille au-delà de laquelle on ferme (défaut 0.25). */\n threshold?: number;\n}\n\n/**\n * Drag-to-dismiss vertical (vers le BAS uniquement) d'une bottom-sheet, factorisé entre le Select\n * (popup Popover) et le Dialog (pane CDK). Chaque appelant ne fournit que SON élément à translater\n * et SON callback de fermeture.\n *\n * Geste DOUBLÉ côté appelant par Échap + bouton Fermer + tap-extérieur (WCAG 2.5.1) : ce module ne\n * gère que le glissement. Le gating « écran compact uniquement » reste à l'appelant (signal `isCompact`\n * de `KtViewport`) — la primitive est volontairement agnostique.\n *\n * @param opts Élément à translater, callback de fermeture, classe de drag et seuil optionnel.\n * @returns Un contrôleur {@link KtSheetDrag} (`start` à brancher sur `pointerdown`, `destroy` au teardown).\n * @example\n * ```ts\n * const drag = createKtSheetDrag({\n * pane: () => paneEl(),\n * onDismiss: () => dialogRef.close(),\n * draggingClass: 'kt-sheet--dragging',\n * });\n * // <div class=\"handle\" (pointerdown)=\"drag.start($event)\"></div>\n * ```\n */\nexport function createKtSheetDrag(opts: KtSheetDragOptions): KtSheetDrag {\n const threshold = opts.threshold ?? 0.25;\n let startY = 0;\n let pane: HTMLElement | null = null;\n let handle: HTMLElement | null = null;\n let ownerDoc: Document | null = null;\n\n const cleanupListeners = (): void => {\n if (!ownerDoc) return;\n ownerDoc.removeEventListener('pointermove', onMove);\n ownerDoc.removeEventListener('pointerup', onEnd);\n ownerDoc.removeEventListener('pointercancel', onEnd);\n };\n\n const onMove = (event: PointerEvent): void => {\n if (!pane) return;\n const dy = Math.max(0, event.clientY - startY); // on ne tire que vers le bas\n pane.style.translate = `0 ${dy}px`;\n };\n\n const onEnd = (event: PointerEvent): void => {\n if (!pane || !handle) return;\n cleanupListeners();\n\n const dragged = event.clientY - startY;\n const dismiss = dragged > pane.getBoundingClientRect().height * threshold;\n // WCAG 2.3.3 : sous prefers-reduced-motion, on applique l'état final SANS animation.\n const reduceMotion = !!ownerDoc?.defaultView?.matchMedia?.('(prefers-reduced-motion: reduce)').matches;\n\n if (reduceMotion) {\n // draggingClass (transition coupée) encore présente : la translation finale est instantanée,\n // puis on retire la classe (aucun changement de valeur ⇒ aucune animation déclenchée).\n pane.style.translate = dismiss ? '0 100%' : '';\n pane.classList.remove(opts.draggingClass);\n } else {\n pane.classList.remove(opts.draggingClass); // réactive la transition CSS (glissement / snap-back)\n pane.style.translate = dismiss ? '0 100%' : ''; // dismiss : glisse jusqu'en bas ; sinon snap-back à 0\n }\n if (dismiss) opts.onDismiss();\n\n pane = null;\n handle = null;\n ownerDoc = null;\n };\n\n return {\n start(event: PointerEvent): void {\n if (event.button !== 0) return;\n const el = opts.pane();\n if (!el) return;\n handle = event.currentTarget as HTMLElement;\n ownerDoc = handle.ownerDocument;\n // La poignée ne doit PAS voler le focus (sinon un close-on-blur fermerait prématurément).\n event.preventDefault();\n startY = event.clientY;\n pane = el;\n pane.classList.add(opts.draggingClass);\n // Écoute au niveau du document : un pointer qui sort de la poignée (petite cible) ou une\n // capture perdue n'interrompt plus le suivi du glissement ni le snap-back.\n ownerDoc.addEventListener('pointermove', onMove);\n ownerDoc.addEventListener('pointerup', onEnd);\n ownerDoc.addEventListener('pointercancel', onEnd);\n },\n destroy(): void {\n cleanupListeners();\n pane = null;\n handle = null;\n ownerDoc = null;\n },\n };\n}\n","import { DOCUMENT } from '@angular/common';\nimport { Injectable, inject } from '@angular/core';\n\n/**\n * Verrou de défilement du `<body>` à COMPTEUR DE RÉFÉRENCES, partagé (`providedIn: 'root'`).\n *\n * Plusieurs surfaces modales simultanées (sheets, popups) peuvent verrouiller le scroll du fond :\n * `overflow: hidden` n'est posé qu'au premier `lock()` et restauré (à sa valeur d'origine) qu'au\n * dernier `unlock()`. Sans ce compteur, deux consommateurs par-instance se désynchronisent — la\n * fermeture du premier restaure le scroll alors que le second est encore ouvert.\n */\n@Injectable({ providedIn: 'root' })\nexport class KtBodyScrollLock {\n private readonly doc = inject(DOCUMENT);\n private count = 0;\n private previousOverflow = '';\n\n /** Pose un verrou (premier appelant : mémorise puis force `overflow: hidden`). */\n lock(): void {\n if (this.count === 0) {\n this.previousOverflow = this.doc.body.style.overflow;\n this.doc.body.style.overflow = 'hidden';\n }\n this.count++;\n }\n\n /** Relâche un verrou ; restaure l'`overflow` d'origine quand le dernier consommateur relâche. */\n unlock(): void {\n if (this.count === 0) return;\n this.count--;\n if (this.count === 0) {\n this.doc.body.style.overflow = this.previousOverflow;\n }\n }\n}\n","import { InjectionToken, Provider } from '@angular/core';\n\n/**\n * Valeur d'un palier de breakpoint, CONFIGURABLE PAR APPLICATION :\n * - un **nombre** = largeur (px) à partir de laquelle le palier commence ; la lib en dérive une\n * media query LARGEUR SEULE (bornes calculées par rapport au palier suivant) ;\n * - une **chaîne** = media query complète du palier, utilisée VERBATIM (échappatoire pour un critère\n * non-largeur : `orientation`, `pointer`, ratio…).\n */\nexport type KtBreakpointValue = number | string;\n\n/**\n * Seuils responsive de la lib, surchargeables par appli via `provideKtBreakpoints`. Sémantique\n * « plancher de palier » : chaque valeur indique où le palier COMMENCE → 3 bandes mutuellement\n * exclusives (`mobile` < `tablet` < `desktop`).\n */\nexport interface KtBreakpoints {\n /** Plancher du mobile (typiquement 0). */\n mobile: KtBreakpointValue;\n /** Largeur où commence la tablette (= plafond mobile). */\n tablet: KtBreakpointValue;\n /** Largeur où commence le desktop (= plafond tablette). */\n desktop: KtBreakpointValue;\n}\n\n/** Défauts : bascule bottom-sheet sous 600px (aligné sur l'ancien `MOBILE_QUERY`). */\nexport const KT_DEFAULT_BREAKPOINTS: KtBreakpoints = { mobile: 0, tablet: 600, desktop: 1024 };\n\n/** Token des seuils responsive. Défaut = `KT_DEFAULT_BREAKPOINTS` ; surchargé par `provideKtBreakpoints`. */\nexport const KT_BREAKPOINTS = new InjectionToken<KtBreakpoints>('KT_BREAKPOINTS', {\n providedIn: 'root',\n factory: () => KT_DEFAULT_BREAKPOINTS,\n});\n\n/**\n * À ajouter aux `providers` de `app.config.ts`. Fusionne avec les défauts → surcharge partielle OK.\n * @param overrides Seuils à surcharger ; les clés absentes gardent leur défaut `KT_DEFAULT_BREAKPOINTS`.\n * @returns Provider liant `KT_BREAKPOINTS` aux seuils fusionnés.\n * @example provideKtBreakpoints({ tablet: 768, desktop: 1200 })\n * @example provideKtBreakpoints({ tablet: '(min-width: 768px) and (orientation: landscape)' })\n */\nexport function provideKtBreakpoints(overrides: Partial<KtBreakpoints>): Provider {\n return { provide: KT_BREAKPOINTS, useValue: { ...KT_DEFAULT_BREAKPOINTS, ...overrides } };\n}\n\n/** Trois chaînes de media queries résolues, prêtes pour `matchMedia` / `BreakpointObserver`. */\nexport interface KtBreakpointMedia {\n /** Media query de la bande mobile. */\n mobile: string;\n /** Media query de la bande tablette. */\n tablet: string;\n /** Media query de la bande desktop. */\n desktop: string;\n}\n\n/** Évite le chevauchement d'1px entre deux bandes adjacentes (max-width juste sous le plancher suivant). */\nconst EPSILON = 0.02;\n\nfunction minWidth(v: number): string {\n return `(min-width: ${v}px)`;\n}\n\nfunction maxWidth(nextFloor: number): string {\n return `(max-width: ${nextFloor - EPSILON}px)`;\n}\n\n/** `not all` ne matche jamais : repli sûr (= desktop) si une bande numérique se retrouve sans borne. */\nfunction join(...parts: string[]): string {\n return parts.filter(Boolean).join(' and ') || 'not all';\n}\n\n/**\n * Convertit les seuils (nombres et/ou chaînes) en 3 media queries. Un palier-chaîne est repris\n * verbatim ; un palier-nombre devient la bande `[plancher courant .. plancher suivant[`. Si le\n * plancher suivant est une chaîne (pas de borne numérique), la bande reste ouverte de ce côté.\n * @param bp Seuils responsive à convertir (nombres et/ou chaînes).\n * @returns Les trois media queries résolues (`mobile`, `tablet`, `desktop`).\n * @example resolveKtBreakpointMedia(KT_DEFAULT_BREAKPOINTS)\n */\nexport function resolveKtBreakpointMedia(bp: KtBreakpoints): KtBreakpointMedia {\n const { mobile, tablet, desktop } = bp;\n\n return {\n mobile:\n typeof mobile === 'string'\n ? mobile\n : join(mobile > 0 ? minWidth(mobile) : '', typeof tablet === 'number' ? maxWidth(tablet) : ''),\n tablet:\n typeof tablet === 'string'\n ? tablet\n : join(minWidth(tablet), typeof desktop === 'number' ? maxWidth(desktop) : ''),\n desktop: typeof desktop === 'string' ? desktop : minWidth(desktop),\n };\n}\n","import { Injectable, Signal, inject } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { BreakpointObserver } from '@angular/cdk/layout';\nimport { map } from 'rxjs';\nimport { KT_BREAKPOINTS, resolveKtBreakpointMedia } from './breakpoints';\n\n/**\n * Expose l'état responsive courant en SIGNALS, dérivé des seuils configurés par l'appli\n * (`KT_BREAKPOINTS` / `provideKtBreakpoints`). Fondé sur `BreakpointObserver` (`@angular/cdk/layout`,\n * déjà dépendance) : SSR-safe (`matches: false` côté serveur → desktop par défaut) et nettoyage des\n * listeners géré par le CDK.\n *\n * À injecter aussi bien dans les composants de la lib (bascule bottom-sheet) que dans le code des\n * applis consommatrices pour leur propre layout responsive.\n */\n@Injectable({ providedIn: 'root' })\nexport class KtViewport {\n private readonly observer = inject(BreakpointObserver);\n\n /** Media queries résolues (largeur dérivée ou verbatim selon le token) — utile pour miroir CSS. */\n readonly media = resolveKtBreakpointMedia(inject(KT_BREAKPOINTS));\n\n /** Le viewport est dans la bande mobile. */\n readonly isMobile = this.matches(this.media.mobile);\n /** Le viewport est dans la bande tablette. */\n readonly isTablet = this.matches(this.media.tablet);\n /** Le viewport est dans la bande desktop. */\n readonly isDesktop = this.matches(this.media.desktop);\n /** Alias de `isMobile` : palier où les composants de la lib basculent en bottom-sheet. */\n readonly isCompact = this.isMobile;\n\n private matches(query: string): Signal<boolean> {\n return toSignal(this.observer.observe(query).pipe(map((state) => state.matches)), {\n initialValue: false,\n });\n }\n}\n","import { Injectable } from '@angular/core';\n\n/**\n * Génère des identifiants numériques incrémentaux uniques au sein de l'application, soit globalement,\n * soit par préfixe (compteur dédié). Sert à construire des `anchor-name` / `id` stables et distincts.\n *\n * @example\n * ```ts\n * const idGen = inject(KtIdGenerator);\n * const anchor = `--kt-menu-anchor-${idGen.generateId('menu')}`;\n * ```\n */\n@Injectable({\n // Stryker disable next-line all: `providedIn` doit rester statiquement analysable par l'AOT (NG1010).\n providedIn: 'root',\n})\nexport class KtIdGenerator {\n private readonly counters = new Map<string, number>();\n private nextGlobalId = 0;\n\n /**\n * Renvoie le prochain identifiant. Sans `prefix`, utilise le compteur global ; avec `prefix`,\n * utilise un compteur dédié à ce préfixe (séquences indépendantes).\n * @param prefix Clé optionnelle de compteur ; chaque préfixe a sa propre séquence.\n * @returns Le compteur courant (number) pour la portée demandée, avant incrément.\n */\n generateId(prefix?: string): number {\n if (!prefix) {\n return this.nextGlobalId++;\n }\n const current = this.counters.get(prefix) ?? 0;\n this.counters.set(prefix, current + 1);\n return current;\n }\n}\n","import { InjectionToken, isDevMode } from '@angular/core';\n\n/**\n * InjectionToken permettant d'activer ou désactiver les audits d'accessibilité à l'exécution\n * (gardes-fous console.warn en mode dev). Activé par défaut si `isDevMode()` est vrai.\n */\nexport const KT_AUDIT_ENABLED = new InjectionToken<boolean>('KT_AUDIT_ENABLED', {\n providedIn: 'root',\n factory: () => isDevMode(),\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ktortu-aaa-cdk.mjs","sources":["../../../../projects/ktortu/aaa/cdk/sheet/sheet-drag.ts","../../../../projects/ktortu/aaa/cdk/sheet/body-scroll-lock.ts","../../../../projects/ktortu/aaa/cdk/breakpoints/breakpoints.ts","../../../../projects/ktortu/aaa/cdk/breakpoints/viewport.ts","../../../../projects/ktortu/aaa/cdk/id-generator.ts","../../../../projects/ktortu/aaa/cdk/audit.ts","../../../../projects/ktortu/aaa/cdk/ktortu-aaa-cdk.ts"],"sourcesContent":["/** Contrôleur de drag-to-dismiss d'une bottom-sheet. À câbler sur le `pointerdown` de la poignée. */\nexport interface KtSheetDrag {\n /** Démarre le suivi du glissement ; à brancher sur le `pointerdown` de la poignée. */\n start(event: PointerEvent): void;\n /** Détache les écouteurs et réinitialise l'état ; à appeler à la destruction. */\n destroy(): void;\n}\n\nexport interface KtSheetDragOptions {\n /** Élément translaté pendant le glissement (la feuille elle-même). Lu à chaque `start`. */\n pane: () => HTMLElement | null;\n /** Fermeture déclenchée quand le seuil est franchi (ex. `expanded.set(false)` / `dialogRef.close()`). */\n onDismiss: () => void;\n /** Classe togglée sur le pane pendant le drag (coupe la transition CSS du glissement). */\n draggingClass: string;\n /** Fraction de la hauteur de la feuille au-delà de laquelle on ferme (défaut 0.25). */\n threshold?: number;\n}\n\n/**\n * Drag-to-dismiss vertical (vers le BAS uniquement) d'une bottom-sheet, factorisé entre le Select\n * (popup Popover) et le Dialog (pane CDK). Chaque appelant ne fournit que SON élément à translater\n * et SON callback de fermeture.\n *\n * Geste DOUBLÉ côté appelant par Échap + bouton Fermer + tap-extérieur (WCAG 2.5.1) : ce module ne\n * gère que le glissement. Le gating « écran compact uniquement » reste à l'appelant (signal `isCompact`\n * de `KtViewport`) — la primitive est volontairement agnostique.\n *\n * @deprecated ADR-0005 — les sheets de la lib (Select compact, Dialog `sheet`) sont désormais des\n * scrollers à snap : le drag-to-dismiss « attrapable partout » et l'arbitrage avec le scroll\n * interne sont NATIFS ; cette primitive « poignée + translate » n'a plus de consommateur interne.\n * Sera supprimée dans une prochaine version majeure.\n *\n * @param opts Élément à translater, callback de fermeture, classe de drag et seuil optionnel.\n * @returns Un contrôleur {@link KtSheetDrag} (`start` à brancher sur `pointerdown`, `destroy` au teardown).\n * @example\n * ```ts\n * const drag = createKtSheetDrag({\n * pane: () => paneEl(),\n * onDismiss: () => dialogRef.close(),\n * draggingClass: 'kt-sheet--dragging',\n * });\n * // <div class=\"handle\" (pointerdown)=\"drag.start($event)\"></div>\n * ```\n */\nexport function createKtSheetDrag(opts: KtSheetDragOptions): KtSheetDrag {\n const threshold = opts.threshold ?? 0.25;\n let startY = 0;\n let pane: HTMLElement | null = null;\n let handle: HTMLElement | null = null;\n let ownerDoc: Document | null = null;\n\n const cleanupListeners = (): void => {\n if (!ownerDoc) return;\n ownerDoc.removeEventListener('pointermove', onMove);\n ownerDoc.removeEventListener('pointerup', onEnd);\n ownerDoc.removeEventListener('pointercancel', onEnd);\n };\n\n const onMove = (event: PointerEvent): void => {\n if (!pane) return;\n const dy = Math.max(0, event.clientY - startY); // on ne tire que vers le bas\n pane.style.translate = `0 ${dy}px`;\n };\n\n const onEnd = (event: PointerEvent): void => {\n if (!pane || !handle) return;\n cleanupListeners();\n\n const dragged = event.clientY - startY;\n const dismiss = dragged > pane.getBoundingClientRect().height * threshold;\n // WCAG 2.3.3 : sous prefers-reduced-motion, on applique l'état final SANS animation.\n const reduceMotion = !!ownerDoc?.defaultView?.matchMedia?.('(prefers-reduced-motion: reduce)').matches;\n\n if (reduceMotion) {\n // draggingClass (transition coupée) encore présente : la translation finale est instantanée,\n // puis on retire la classe (aucun changement de valeur ⇒ aucune animation déclenchée).\n pane.style.translate = dismiss ? '0 100%' : '';\n pane.classList.remove(opts.draggingClass);\n } else {\n pane.classList.remove(opts.draggingClass); // réactive la transition CSS (glissement / snap-back)\n pane.style.translate = dismiss ? '0 100%' : ''; // dismiss : glisse jusqu'en bas ; sinon snap-back à 0\n }\n if (dismiss) opts.onDismiss();\n\n pane = null;\n handle = null;\n ownerDoc = null;\n };\n\n return {\n start(event: PointerEvent): void {\n if (event.button !== 0) return;\n const el = opts.pane();\n if (!el) return;\n handle = event.currentTarget as HTMLElement;\n ownerDoc = handle.ownerDocument;\n // La poignée ne doit PAS voler le focus (sinon un close-on-blur fermerait prématurément).\n event.preventDefault();\n startY = event.clientY;\n pane = el;\n pane.classList.add(opts.draggingClass);\n // Écoute au niveau du document : un pointer qui sort de la poignée (petite cible) ou une\n // capture perdue n'interrompt plus le suivi du glissement ni le snap-back.\n ownerDoc.addEventListener('pointermove', onMove);\n ownerDoc.addEventListener('pointerup', onEnd);\n ownerDoc.addEventListener('pointercancel', onEnd);\n },\n destroy(): void {\n cleanupListeners();\n pane = null;\n handle = null;\n ownerDoc = null;\n },\n };\n}\n","import { DOCUMENT } from '@angular/common';\nimport { Injectable, inject } from '@angular/core';\n\n/**\n * Verrou de défilement du `<body>` à COMPTEUR DE RÉFÉRENCES, partagé (`providedIn: 'root'`).\n *\n * Plusieurs surfaces modales simultanées (sheets, popups) peuvent verrouiller le scroll du fond :\n * `overflow: hidden` n'est posé qu'au premier `lock()` et restauré (à sa valeur d'origine) qu'au\n * dernier `unlock()`. Sans ce compteur, deux consommateurs par-instance se désynchronisent — la\n * fermeture du premier restaure le scroll alors que le second est encore ouvert.\n */\n@Injectable({ providedIn: 'root' })\nexport class KtBodyScrollLock {\n private readonly doc = inject(DOCUMENT);\n private count = 0;\n private previousOverflow = '';\n\n /** Pose un verrou (premier appelant : mémorise puis force `overflow: hidden`). */\n lock(): void {\n if (this.count === 0) {\n this.previousOverflow = this.doc.body.style.overflow;\n this.doc.body.style.overflow = 'hidden';\n }\n this.count++;\n }\n\n /** Relâche un verrou ; restaure l'`overflow` d'origine quand le dernier consommateur relâche. */\n unlock(): void {\n if (this.count === 0) return;\n this.count--;\n if (this.count === 0) {\n this.doc.body.style.overflow = this.previousOverflow;\n }\n }\n}\n","import { InjectionToken, Provider } from '@angular/core';\n\n/**\n * Valeur d'un palier de breakpoint, CONFIGURABLE PAR APPLICATION :\n * - un **nombre** = largeur (px) à partir de laquelle le palier commence ; la lib en dérive une\n * media query LARGEUR SEULE (bornes calculées par rapport au palier suivant) ;\n * - une **chaîne** = media query complète du palier, utilisée VERBATIM (échappatoire pour un critère\n * non-largeur : `orientation`, `pointer`, ratio…).\n */\nexport type KtBreakpointValue = number | string;\n\n/**\n * Seuils responsive de la lib, surchargeables par appli via `provideKtBreakpoints`. Sémantique\n * « plancher de palier » : chaque valeur indique où le palier COMMENCE → 3 bandes mutuellement\n * exclusives (`mobile` < `tablet` < `desktop`).\n */\nexport interface KtBreakpoints {\n /** Plancher du mobile (typiquement 0). */\n mobile: KtBreakpointValue;\n /** Largeur où commence la tablette (= plafond mobile). */\n tablet: KtBreakpointValue;\n /** Largeur où commence le desktop (= plafond tablette). */\n desktop: KtBreakpointValue;\n}\n\n/** Défauts : bascule bottom-sheet sous 600px (aligné sur l'ancien `MOBILE_QUERY`). */\nexport const KT_DEFAULT_BREAKPOINTS: KtBreakpoints = { mobile: 0, tablet: 600, desktop: 1024 };\n\n/** Token des seuils responsive. Défaut = `KT_DEFAULT_BREAKPOINTS` ; surchargé par `provideKtBreakpoints`. */\nexport const KT_BREAKPOINTS = new InjectionToken<KtBreakpoints>('KT_BREAKPOINTS', {\n providedIn: 'root',\n factory: () => KT_DEFAULT_BREAKPOINTS,\n});\n\n/**\n * À ajouter aux `providers` de `app.config.ts`. Fusionne avec les défauts → surcharge partielle OK.\n * @param overrides Seuils à surcharger ; les clés absentes gardent leur défaut `KT_DEFAULT_BREAKPOINTS`.\n * @returns Provider liant `KT_BREAKPOINTS` aux seuils fusionnés.\n * @example provideKtBreakpoints({ tablet: 768, desktop: 1200 })\n * @example provideKtBreakpoints({ tablet: '(min-width: 768px) and (orientation: landscape)' })\n */\nexport function provideKtBreakpoints(overrides: Partial<KtBreakpoints>): Provider {\n return { provide: KT_BREAKPOINTS, useValue: { ...KT_DEFAULT_BREAKPOINTS, ...overrides } };\n}\n\n/** Trois chaînes de media queries résolues, prêtes pour `matchMedia` / `BreakpointObserver`. */\nexport interface KtBreakpointMedia {\n /** Media query de la bande mobile. */\n mobile: string;\n /** Media query de la bande tablette. */\n tablet: string;\n /** Media query de la bande desktop. */\n desktop: string;\n}\n\n/** Évite le chevauchement d'1px entre deux bandes adjacentes (max-width juste sous le plancher suivant). */\nconst EPSILON = 0.02;\n\nfunction minWidth(v: number): string {\n return `(min-width: ${v}px)`;\n}\n\nfunction maxWidth(nextFloor: number): string {\n return `(max-width: ${nextFloor - EPSILON}px)`;\n}\n\n/** `not all` ne matche jamais : repli sûr (= desktop) si une bande numérique se retrouve sans borne. */\nfunction join(...parts: string[]): string {\n return parts.filter(Boolean).join(' and ') || 'not all';\n}\n\n/**\n * Convertit les seuils (nombres et/ou chaînes) en 3 media queries. Un palier-chaîne est repris\n * verbatim ; un palier-nombre devient la bande `[plancher courant .. plancher suivant[`. Si le\n * plancher suivant est une chaîne (pas de borne numérique), la bande reste ouverte de ce côté.\n * @param bp Seuils responsive à convertir (nombres et/ou chaînes).\n * @returns Les trois media queries résolues (`mobile`, `tablet`, `desktop`).\n * @example resolveKtBreakpointMedia(KT_DEFAULT_BREAKPOINTS)\n */\nexport function resolveKtBreakpointMedia(bp: KtBreakpoints): KtBreakpointMedia {\n const { mobile, tablet, desktop } = bp;\n\n return {\n mobile:\n typeof mobile === 'string'\n ? mobile\n : join(mobile > 0 ? minWidth(mobile) : '', typeof tablet === 'number' ? maxWidth(tablet) : ''),\n tablet:\n typeof tablet === 'string'\n ? tablet\n : join(minWidth(tablet), typeof desktop === 'number' ? maxWidth(desktop) : ''),\n desktop: typeof desktop === 'string' ? desktop : minWidth(desktop),\n };\n}\n","import { Injectable, Signal, inject } from '@angular/core';\nimport { toSignal } from '@angular/core/rxjs-interop';\nimport { BreakpointObserver } from '@angular/cdk/layout';\nimport { map } from 'rxjs';\nimport { KT_BREAKPOINTS, resolveKtBreakpointMedia } from './breakpoints';\n\n/**\n * Expose l'état responsive courant en SIGNALS, dérivé des seuils configurés par l'appli\n * (`KT_BREAKPOINTS` / `provideKtBreakpoints`). Fondé sur `BreakpointObserver` (`@angular/cdk/layout`,\n * déjà dépendance) : SSR-safe (`matches: false` côté serveur → desktop par défaut) et nettoyage des\n * listeners géré par le CDK.\n *\n * À injecter aussi bien dans les composants de la lib (bascule bottom-sheet) que dans le code des\n * applis consommatrices pour leur propre layout responsive.\n */\n@Injectable({ providedIn: 'root' })\nexport class KtViewport {\n private readonly observer = inject(BreakpointObserver);\n\n /** Media queries résolues (largeur dérivée ou verbatim selon le token) — utile pour miroir CSS. */\n readonly media = resolveKtBreakpointMedia(inject(KT_BREAKPOINTS));\n\n /** Le viewport est dans la bande mobile. */\n readonly isMobile = this.matches(this.media.mobile);\n /** Le viewport est dans la bande tablette. */\n readonly isTablet = this.matches(this.media.tablet);\n /** Le viewport est dans la bande desktop. */\n readonly isDesktop = this.matches(this.media.desktop);\n /** Alias de `isMobile` : palier où les composants de la lib basculent en bottom-sheet. */\n readonly isCompact = this.isMobile;\n\n private matches(query: string): Signal<boolean> {\n return toSignal(this.observer.observe(query).pipe(map((state) => state.matches)), {\n initialValue: false,\n });\n }\n}\n","import { Injectable } from '@angular/core';\n\n/**\n * Génère des identifiants numériques incrémentaux uniques au sein de l'application, soit globalement,\n * soit par préfixe (compteur dédié). Sert à construire des `anchor-name` / `id` stables et distincts.\n *\n * @example\n * ```ts\n * const idGen = inject(KtIdGenerator);\n * const anchor = `--kt-menu-anchor-${idGen.generateId('menu')}`;\n * ```\n */\n@Injectable({\n // Stryker disable next-line all: `providedIn` doit rester statiquement analysable par l'AOT (NG1010).\n providedIn: 'root',\n})\nexport class KtIdGenerator {\n private readonly counters = new Map<string, number>();\n private nextGlobalId = 0;\n\n /**\n * Renvoie le prochain identifiant. Sans `prefix`, utilise le compteur global ; avec `prefix`,\n * utilise un compteur dédié à ce préfixe (séquences indépendantes).\n * @param prefix Clé optionnelle de compteur ; chaque préfixe a sa propre séquence.\n * @returns Le compteur courant (number) pour la portée demandée, avant incrément.\n */\n generateId(prefix?: string): number {\n if (!prefix) {\n return this.nextGlobalId++;\n }\n const current = this.counters.get(prefix) ?? 0;\n this.counters.set(prefix, current + 1);\n return current;\n }\n}\n","import { InjectionToken, isDevMode } from '@angular/core';\n\n/**\n * InjectionToken permettant d'activer ou désactiver les audits d'accessibilité à l'exécution\n * (gardes-fous console.warn en mode dev). Activé par défaut si `isDevMode()` est vrai.\n */\nexport const KT_AUDIT_ENABLED = new InjectionToken<boolean>('KT_AUDIT_ENABLED', {\n providedIn: 'root',\n factory: () => isDevMode(),\n});\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DialogRef, DEFAULT_DIALOG_CONFIG, CdkDialogContainer, Dialog, DIALOG_DATA } from '@angular/cdk/dialog';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { inject, ElementRef, Renderer2, afterNextRender, Directive, input, isDevMode,
|
|
4
|
-
import { KtIdGenerator,
|
|
3
|
+
import { inject, ElementRef, Renderer2, afterNextRender, Directive, input, isDevMode, PLATFORM_ID, DestroyRef, signal, ChangeDetectionStrategy, Component, ViewContainerRef, Injectable } from '@angular/core';
|
|
4
|
+
import { KtIdGenerator, KtBodyScrollLock, KtViewport } from '@ktortu/aaa/cdk';
|
|
5
5
|
import { isPlatformBrowser } from '@angular/common';
|
|
6
6
|
import * as i1 from '@angular/cdk/portal';
|
|
7
7
|
import { PortalModule } from '@angular/cdk/portal';
|
|
@@ -255,54 +255,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
|
|
|
255
255
|
args: [{ selector: '[ktDialogFocusInitial]' }]
|
|
256
256
|
}] });
|
|
257
257
|
/**
|
|
258
|
-
*
|
|
259
|
-
*
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
* présentation `sheet` / `centered-sheet`. Le drag n'est actif que si le dialog est EFFECTIVEMENT
|
|
264
|
-
* en mode sheet (la pane porte `kt-dialog--sheet`) — pas de dépendance au viewport : un `sheet`
|
|
265
|
-
* toujours-bottom-sheet se drague aussi à la souris.
|
|
266
|
-
*
|
|
267
|
-
* @example
|
|
268
|
-
* ```html
|
|
269
|
-
* <div ktDialogContent>
|
|
270
|
-
* <div ktDialogSheetHandle></div>
|
|
271
|
-
* …
|
|
272
|
-
* </div>
|
|
273
|
-
* ```
|
|
258
|
+
* @deprecated ADR-0005 — la poignée est désormais RENDUE AUTOMATIQUEMENT par `KtDialogContainer`
|
|
259
|
+
* en présentation `sheet` (opt-out : panelClass additionnel `kt-dialog--no-handle`), et le
|
|
260
|
+
* drag-to-dismiss s'attrape sur TOUTE la surface de la sheet (scroll-snap natif). Cette
|
|
261
|
+
* directive est INERTE et son hôte est masqué (évite une double poignée) : retirez-la de vos
|
|
262
|
+
* templates. Sera supprimée dans une prochaine version majeure.
|
|
274
263
|
*/
|
|
275
264
|
class KtDialogSheetHandle {
|
|
276
|
-
dialogRef = inject(DialogRef, { optional: true });
|
|
277
|
-
host = inject(ElementRef).nativeElement;
|
|
278
|
-
destroyRef = inject(DestroyRef);
|
|
279
|
-
// La feuille translatée = le conteneur CDK (position:fixed en mode sheet), trouvé en remontant.
|
|
280
|
-
drag = createKtSheetDrag({
|
|
281
|
-
pane: () => this.host.closest('.cdk-dialog-container'),
|
|
282
|
-
onDismiss: () => this.dialogRef?.close(),
|
|
283
|
-
draggingClass: 'kt-dialog-sheet--dragging',
|
|
284
|
-
});
|
|
285
265
|
constructor() {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const pane = this.host.closest('.cdk-overlay-pane');
|
|
291
|
-
if (!pane?.classList.contains('kt-dialog--sheet'))
|
|
292
|
-
return;
|
|
293
|
-
this.drag.start(event);
|
|
266
|
+
if (isDevMode()) {
|
|
267
|
+
console.warn('[ktDialogSheetHandle] déprécié (ADR-0005) : la poignée est rendue automatiquement en ' +
|
|
268
|
+
'présentation sheet et le drag s’attrape partout — retirez la directive de votre template.');
|
|
269
|
+
}
|
|
294
270
|
}
|
|
295
271
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtDialogSheetHandle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
296
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.1", type: KtDialogSheetHandle, isStandalone: true, selector: "[ktDialogSheetHandle]", host: { attributes: { "aria-hidden": "true" },
|
|
272
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.1", type: KtDialogSheetHandle, isStandalone: true, selector: "[ktDialogSheetHandle]", host: { attributes: { "aria-hidden": "true" }, styleAttribute: "display: none" }, ngImport: i0 });
|
|
297
273
|
}
|
|
298
274
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtDialogSheetHandle, decorators: [{
|
|
299
275
|
type: Directive,
|
|
300
276
|
args: [{
|
|
301
277
|
selector: '[ktDialogSheetHandle]',
|
|
302
278
|
host: {
|
|
303
|
-
'(pointerdown)': 'onStart($event)',
|
|
304
|
-
'(mousedown)': '$event.preventDefault()',
|
|
305
279
|
'aria-hidden': 'true',
|
|
280
|
+
style: 'display: none',
|
|
306
281
|
},
|
|
307
282
|
}]
|
|
308
283
|
}], ctorParameters: () => [] });
|
|
@@ -331,6 +306,12 @@ const KT_DIALOG_AAA_DEFAULTS = {
|
|
|
331
306
|
hasBackdrop: true,
|
|
332
307
|
panelClass: 'kt-dialog',
|
|
333
308
|
backdropClass: 'kt-dialog__backdrop',
|
|
309
|
+
/* Plafond de largeur posé en STYLE INLINE sur le pane par l'overlay (canal prévu par le CDK).
|
|
310
|
+
Indispensable : le CDK injecte à l'exécution `.cdk-overlay-pane { max-width: 100% }` HORS
|
|
311
|
+
layer, qui bat toute règle de la lib importée via layer() — seul un style inline gagne.
|
|
312
|
+
La custom property garde la thémisation ; `--fullscreen`/`--sheet` la retunent sur leur
|
|
313
|
+
pane (cf. dialog.css). */
|
|
314
|
+
maxWidth: 'var(--dialog-max-width)',
|
|
334
315
|
};
|
|
335
316
|
/**
|
|
336
317
|
* Enregistre les valeurs par défaut AAA du dialog au niveau application.
|
|
@@ -391,8 +372,16 @@ class KtDialogContainer extends CdkDialogContainer {
|
|
|
391
372
|
elementRef = inject(ElementRef);
|
|
392
373
|
host = this.elementRef.nativeElement;
|
|
393
374
|
platformId = inject(PLATFORM_ID);
|
|
375
|
+
destroyRef = inject(DestroyRef);
|
|
376
|
+
bodyScrollLock = inject(KtBodyScrollLock);
|
|
394
377
|
isClosing = signal(false, /* @ts-ignore */
|
|
395
378
|
...(ngDevMode ? [{ debugName: "isClosing" }] : /* istanbul ignore next */ []));
|
|
379
|
+
// --- Sheet scroll-snap (ADR-0005) : détection du snap « fermé » + fermeture différée ---
|
|
380
|
+
/** Armé quand l'ouverture a dépassé 50px : un repos à ~0 est alors forcément le snap « fermé ». */
|
|
381
|
+
sheetArmed = false;
|
|
382
|
+
/** Fermeture réelle en attente du repos au snap « fermé » (sortie programmatique animée). */
|
|
383
|
+
pendingSheetClose = null;
|
|
384
|
+
sheetCloseTimer;
|
|
396
385
|
/** Premier id de la file `aria-labelledby` exposée par `CdkDialogContainer`. Le membre
|
|
397
386
|
`_ariaLabelledByQueue` est interne au CDK (préfixe `_`) : on l'encapsule ICI, gardé, pour que
|
|
398
387
|
le binding de template ne lise jamais l'interne directement. Si une montée du CDK retire ou
|
|
@@ -416,6 +405,8 @@ class KtDialogContainer extends CdkDialogContainer {
|
|
|
416
405
|
// - aria-describedby orphelin → on RETIRE l'attribut (pas de description fournie) ;
|
|
417
406
|
// - aucun nom accessible (ni titre ni aria-label) → warn dev (WCAG 4.1.2).
|
|
418
407
|
afterNextRender(() => {
|
|
408
|
+
if (this.isSheet())
|
|
409
|
+
this.initSheetGesture();
|
|
419
410
|
const doc = this.host.ownerDocument;
|
|
420
411
|
const describedBy = this.host.getAttribute('aria-describedby');
|
|
421
412
|
if (describedBy && !doc.getElementById(describedBy)) {
|
|
@@ -433,6 +424,82 @@ class KtDialogContainer extends CdkDialogContainer {
|
|
|
433
424
|
isSheet() {
|
|
434
425
|
return this._config.panelClass?.includes('kt-dialog--sheet') ?? false;
|
|
435
426
|
}
|
|
427
|
+
/** Poignée décorative auto-rendue en présentation sheet. Opt-out : panelClass `kt-dialog--no-handle`. */
|
|
428
|
+
showSheetHandle() {
|
|
429
|
+
return !this._config.panelClass?.includes('kt-dialog--no-handle');
|
|
430
|
+
}
|
|
431
|
+
/** Tap sur le spacer (zone extérieure à la carte) = fermeture, façon backdrop. Le conteneur
|
|
432
|
+
captant désormais le tactile (pointer-events auto, requis pour le drag iOS), le clic ne
|
|
433
|
+
traverse plus vers le backdrop CDK : on porte donc ICI la fermeture au tap-extérieur, en
|
|
434
|
+
respectant `disableClose` (comme le faisait le backdropClick natif). Un drag n'émet pas de
|
|
435
|
+
`click` (le navigateur le supprime après un scroll) : seul un vrai tap ferme. */
|
|
436
|
+
onScrimClick() {
|
|
437
|
+
if (this._config.disableClose || this.isClosing())
|
|
438
|
+
return;
|
|
439
|
+
this.dialogRef.close();
|
|
440
|
+
}
|
|
441
|
+
/** Sheet scroll-snap : écouteurs (détection du repos + garde molette) et scroll d'ENTRÉE
|
|
442
|
+
programmatique vers le snap « ouvert ». Appelé au premier rendu, en présentation sheet. */
|
|
443
|
+
initSheetGesture() {
|
|
444
|
+
const host = this.host;
|
|
445
|
+
host.addEventListener('scroll', this.onSheetScroll);
|
|
446
|
+
host.addEventListener('wheel', this.onSheetWheel, { passive: false });
|
|
447
|
+
// Verrou de scroll du fond (compteur partagé) : sans lui, le fond défile SOUS la sheet et,
|
|
448
|
+
// sur iOS, le geste de dismiss déclenche le pull-to-refresh de la page. La stratégie `block`
|
|
449
|
+
// du CDK ne suffit pas ici (non appliquée / non fiable sur iOS) — même approche que le Select.
|
|
450
|
+
this.bodyScrollLock.lock();
|
|
451
|
+
this.destroyRef.onDestroy(() => {
|
|
452
|
+
clearTimeout(this.sheetCloseTimer);
|
|
453
|
+
host.removeEventListener('scroll', this.onSheetScroll);
|
|
454
|
+
host.removeEventListener('wheel', this.onSheetWheel);
|
|
455
|
+
this.bodyScrollLock.unlock();
|
|
456
|
+
});
|
|
457
|
+
host.scrollTop = 0;
|
|
458
|
+
requestAnimationFrame(() => {
|
|
459
|
+
host.scrollTo?.({
|
|
460
|
+
top: host.scrollHeight - host.clientHeight,
|
|
461
|
+
behavior: this.prefersReducedMotion() ? 'auto' : 'smooth',
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
prefersReducedMotion() {
|
|
466
|
+
return this.host.ownerDocument.defaultView?.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;
|
|
467
|
+
}
|
|
468
|
+
/** Détection du snap « fermé » par position de scroll (ni scrollsnapchange ni scrollend — cf.
|
|
469
|
+
ADR-0005). Un repos à ~0 finalise la fermeture en attente, ou EST une fermeture par geste. */
|
|
470
|
+
onSheetScroll = () => {
|
|
471
|
+
const top = this.host.scrollTop;
|
|
472
|
+
if (top > 50)
|
|
473
|
+
this.sheetArmed = true;
|
|
474
|
+
if (!this.sheetArmed || top > 1)
|
|
475
|
+
return;
|
|
476
|
+
const pending = this.pendingSheetClose;
|
|
477
|
+
if (pending) {
|
|
478
|
+
this.pendingSheetClose = null;
|
|
479
|
+
clearTimeout(this.sheetCloseTimer);
|
|
480
|
+
pending();
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
// Dismissal par geste : transite par le close intercepté (animation déjà « jouée » par le doigt).
|
|
484
|
+
if (!this.isClosing())
|
|
485
|
+
this.dialogRef.close();
|
|
486
|
+
};
|
|
487
|
+
/** La molette ne ferme JAMAIS la sheet (pas de geste souris — ADR-0005) : seuls les scrollers
|
|
488
|
+
INTERNES peuvent consommer, dans leurs bornes (générique : un dialog peut imbriquer
|
|
489
|
+
plusieurs zones scrollables). */
|
|
490
|
+
onSheetWheel = (event) => {
|
|
491
|
+
let el = event.target;
|
|
492
|
+
while (el && el !== this.host) {
|
|
493
|
+
if (el.scrollHeight > el.clientHeight + 1) {
|
|
494
|
+
const canScrollDown = el.scrollTop + el.clientHeight < el.scrollHeight - 1;
|
|
495
|
+
const canScrollUp = el.scrollTop > 0;
|
|
496
|
+
if ((event.deltaY > 0 && canScrollDown) || (event.deltaY < 0 && canScrollUp))
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
el = el.parentElement;
|
|
500
|
+
}
|
|
501
|
+
event.preventDefault();
|
|
502
|
+
};
|
|
436
503
|
animateAndClose(result, originalCloseFn) {
|
|
437
504
|
if (this.isClosing())
|
|
438
505
|
return;
|
|
@@ -441,17 +508,37 @@ class KtDialogContainer extends CdkDialogContainer {
|
|
|
441
508
|
originalCloseFn(result);
|
|
442
509
|
return;
|
|
443
510
|
}
|
|
444
|
-
//
|
|
445
|
-
|
|
446
|
-
|
|
511
|
+
// Sheet scroll-snap : la sortie est un scroll programmatique vers le snap « fermé » ;
|
|
512
|
+
// onSheetScroll finalise au repos. Déjà en bas (geste abouti, jsdom, reduced-motion) :
|
|
513
|
+
// fermeture immédiate. Fallback : timeout (scroll lisse interrompu).
|
|
514
|
+
if (this.isSheet()) {
|
|
515
|
+
if (this.host.scrollTop <= 1) {
|
|
516
|
+
originalCloseFn(result);
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
this.sheetArmed = true;
|
|
520
|
+
this.pendingSheetClose = () => originalCloseFn(result);
|
|
521
|
+
this.host.scrollTo?.({ top: 0, behavior: this.prefersReducedMotion() ? 'auto' : 'smooth' });
|
|
522
|
+
clearTimeout(this.sheetCloseTimer);
|
|
523
|
+
this.sheetCloseTimer = setTimeout(() => {
|
|
524
|
+
const pending = this.pendingSheetClose;
|
|
525
|
+
this.pendingSheetClose = null;
|
|
526
|
+
pending?.();
|
|
527
|
+
}, 400);
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
// Récupérer la durée de transition configurée en CSS (ex: "150ms" ou "0.2s"). Vue lue via
|
|
531
|
+
// ownerDocument.defaultView (pas le global `window`) : cohérent avec prefersReducedMotion() et
|
|
532
|
+
// sûr indépendamment du garde de plateforme — si la vue manque, durée 0 → fermeture immédiate.
|
|
533
|
+
const durationStr = this.host.ownerDocument.defaultView?.getComputedStyle(this.host).transitionDuration || '0s';
|
|
447
534
|
const durationMs = parseFloat(durationStr) * (durationStr.includes('ms') ? 1 : 1000);
|
|
448
535
|
if (durationMs === 0) {
|
|
449
536
|
originalCloseFn(result);
|
|
450
537
|
return;
|
|
451
538
|
}
|
|
452
|
-
// Écouter la fin de la transition
|
|
539
|
+
// Écouter la fin de la transition (opacity pour le dialog classique, translate pour la sheet)
|
|
453
540
|
const onTransitionEnd = (event) => {
|
|
454
|
-
if (event.target === this.host && event.propertyName === 'translate') {
|
|
541
|
+
if (event.target === this.host && (event.propertyName === 'translate' || event.propertyName === 'opacity')) {
|
|
455
542
|
this.host.removeEventListener('transitionend', onTransitionEnd);
|
|
456
543
|
originalCloseFn(result);
|
|
457
544
|
}
|
|
@@ -464,8 +551,21 @@ class KtDialogContainer extends CdkDialogContainer {
|
|
|
464
551
|
}, durationMs + 50);
|
|
465
552
|
}
|
|
466
553
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: KtDialogContainer, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
467
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
554
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: KtDialogContainer, isStandalone: true, selector: "kt-dialog-container", host: { attributes: { "tabindex": "-1" }, properties: { "attr.id": "_config.id || null", "attr.role": "_config.role", "attr.aria-modal": "_config.ariaModal", "attr.aria-labelledby": "_config.ariaLabel ? null : ariaLabelledBy", "attr.aria-label": "_config.ariaLabel", "attr.aria-describedby": "_config.ariaDescribedBy || null", "class.kt-dialog-container--sheet": "isSheet()", "class.kt-dialog-container--closing": "isClosing()" }, classAttribute: "cdk-dialog-container kt-dialog-container" }, usesInheritance: true, ngImport: i0, template: `
|
|
555
|
+
<!-- Sheet scroll-snap (ADR-0005) : le conteneur est le SCROLLER, le spacer porte le snap
|
|
556
|
+
« fermé » (un écran) et la carte (layout) le snap « ouvert ». -->
|
|
557
|
+
@if (isSheet()) {
|
|
558
|
+
<!-- Spacer = zone de tap-extérieur (ferme, comme un backdrop) ET surface de drag (scroll natif).
|
|
559
|
+
Le conteneur capte le tactile (pointer-events auto) : le clic ne traverse plus vers le
|
|
560
|
+
backdrop CDK, la fermeture au tap est donc portée ici (disableClose respecté). -->
|
|
561
|
+
<div class="kt-dialog-container__spacer" aria-hidden="true" (click)="onScrimClick()"></div>
|
|
562
|
+
}
|
|
468
563
|
<div class="kt-dialog-container__layout">
|
|
564
|
+
@if (isSheet() && showSheetHandle()) {
|
|
565
|
+
<!-- Poignée DÉCORATIVE auto-rendue : la sheet s'attrape partout (opt-out :
|
|
566
|
+
panelClass additionnel 'kt-dialog--no-handle' à l'ouverture). -->
|
|
567
|
+
<div class="kt-dialog-container__sheet-handle" aria-hidden="true"></div>
|
|
568
|
+
}
|
|
469
569
|
<ng-template cdkPortalOutlet></ng-template>
|
|
470
570
|
</div>
|
|
471
571
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: PortalModule }, { kind: "directive", type: i1.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -489,7 +589,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
|
|
|
489
589
|
'[class.kt-dialog-container--closing]': 'isClosing()',
|
|
490
590
|
},
|
|
491
591
|
template: `
|
|
592
|
+
<!-- Sheet scroll-snap (ADR-0005) : le conteneur est le SCROLLER, le spacer porte le snap
|
|
593
|
+
« fermé » (un écran) et la carte (layout) le snap « ouvert ». -->
|
|
594
|
+
@if (isSheet()) {
|
|
595
|
+
<!-- Spacer = zone de tap-extérieur (ferme, comme un backdrop) ET surface de drag (scroll natif).
|
|
596
|
+
Le conteneur capte le tactile (pointer-events auto) : le clic ne traverse plus vers le
|
|
597
|
+
backdrop CDK, la fermeture au tap est donc portée ici (disableClose respecté). -->
|
|
598
|
+
<div class="kt-dialog-container__spacer" aria-hidden="true" (click)="onScrimClick()"></div>
|
|
599
|
+
}
|
|
492
600
|
<div class="kt-dialog-container__layout">
|
|
601
|
+
@if (isSheet() && showSheetHandle()) {
|
|
602
|
+
<!-- Poignée DÉCORATIVE auto-rendue : la sheet s'attrape partout (opt-out :
|
|
603
|
+
panelClass additionnel 'kt-dialog--no-handle' à l'ouverture). -->
|
|
604
|
+
<div class="kt-dialog-container__sheet-handle" aria-hidden="true"></div>
|
|
605
|
+
}
|
|
493
606
|
<ng-template cdkPortalOutlet></ng-template>
|
|
494
607
|
</div>
|
|
495
608
|
`,
|
|
@@ -589,6 +702,21 @@ function defineKtDialog() {
|
|
|
589
702
|
};
|
|
590
703
|
}
|
|
591
704
|
|
|
705
|
+
/**
|
|
706
|
+
* Import ergonomique de toute la famille dialog en une fois :
|
|
707
|
+
* `imports: [KtDialogImports]` au lieu d'énumérer chaque directive structurelle.
|
|
708
|
+
*/
|
|
709
|
+
const KtDialogImports = [
|
|
710
|
+
KtDialogHeader,
|
|
711
|
+
KtDialogTitle,
|
|
712
|
+
KtDialogDescription,
|
|
713
|
+
KtDialogContent,
|
|
714
|
+
KtDialogActions,
|
|
715
|
+
KtDialogClose,
|
|
716
|
+
KtDialogFocusInitial,
|
|
717
|
+
KtDialogSheetHandle,
|
|
718
|
+
];
|
|
719
|
+
|
|
592
720
|
const alertDialog = defineKtDialog();
|
|
593
721
|
/**
|
|
594
722
|
* Composant interne d'alerte générique.
|
|
@@ -821,21 +949,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImpor
|
|
|
821
949
|
}]
|
|
822
950
|
}] });
|
|
823
951
|
|
|
824
|
-
/**
|
|
825
|
-
* Import ergonomique de toute la famille dialog en une fois :
|
|
826
|
-
* `imports: [KtDialogImports]` au lieu d'énumérer chaque directive structurelle.
|
|
827
|
-
*/
|
|
828
|
-
const KtDialogImports = [
|
|
829
|
-
KtDialogHeader,
|
|
830
|
-
KtDialogTitle,
|
|
831
|
-
KtDialogDescription,
|
|
832
|
-
KtDialogContent,
|
|
833
|
-
KtDialogActions,
|
|
834
|
-
KtDialogClose,
|
|
835
|
-
KtDialogFocusInitial,
|
|
836
|
-
KtDialogSheetHandle,
|
|
837
|
-
];
|
|
838
|
-
|
|
839
952
|
/**
|
|
840
953
|
* Generated bundle index. Do not edit.
|
|
841
954
|
*/
|