@ktortu/aaa 0.9.0 → 0.9.2
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/README.md +5 -3
- package/fesm2022/ktortu-aaa-button.mjs +10 -2
- package/fesm2022/ktortu-aaa-button.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-card.mjs +14 -5
- package/fesm2022/ktortu-aaa-card.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-cdk.mjs +50 -2
- package/fesm2022/ktortu-aaa-cdk.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-dialog.mjs +80 -39
- package/fesm2022/ktortu-aaa-dialog.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-disclosure.mjs +201 -0
- package/fesm2022/ktortu-aaa-disclosure.mjs.map +1 -0
- package/fesm2022/ktortu-aaa-forms.mjs +525 -149
- package/fesm2022/ktortu-aaa-forms.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-i18n.mjs +27 -2
- package/fesm2022/ktortu-aaa-i18n.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-menu.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-progress-bar.mjs +91 -0
- package/fesm2022/ktortu-aaa-progress-bar.mjs.map +1 -0
- package/fesm2022/ktortu-aaa-snackbar.mjs +478 -0
- package/fesm2022/ktortu-aaa-snackbar.mjs.map +1 -0
- package/fesm2022/ktortu-aaa-tabs.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-tooltip.mjs +20 -30
- package/fesm2022/ktortu-aaa-tooltip.mjs.map +1 -1
- package/fesm2022/ktortu-aaa.mjs +2 -0
- package/fesm2022/ktortu-aaa.mjs.map +1 -1
- package/forms/checkbox/checkbox-group.css +0 -8
- package/forms/chips/chip-list.css +5 -0
- package/forms/field/field.css +16 -0
- package/forms/radio/radio-group.css +1 -9
- package/forms/styles/field-box.css +14 -6
- package/forms/styles/field-pending.css +46 -0
- package/forms/styles/select-panel.css +4 -0
- package/package.json +13 -1
- package/progress-bar/progress-bar.css +127 -0
- package/snackbar/snackbar-tokens.css +53 -0
- package/snackbar/snackbar.css +175 -0
- package/styles/disclosure.css +6 -0
- package/styles/forms.css +1 -0
- package/styles/progress-bar.css +5 -0
- package/styles/snackbar.css +9 -0
- package/styles/styles.css +3 -0
- package/themes/theme-cyberpunk.css +11 -0
- package/tooltip/tooltip.css +1 -1
- package/types/ktortu-aaa-button.d.ts +2 -0
- package/types/ktortu-aaa-card.d.ts +3 -0
- package/types/ktortu-aaa-cdk.d.ts +27 -1
- package/types/ktortu-aaa-dialog.d.ts +89 -34
- package/types/ktortu-aaa-disclosure.d.ts +112 -0
- package/types/ktortu-aaa-forms.d.ts +238 -30
- package/types/ktortu-aaa-i18n.d.ts +3 -0
- package/types/ktortu-aaa-progress-bar.d.ts +27 -0
- package/types/ktortu-aaa-snackbar.d.ts +218 -0
- package/types/ktortu-aaa-tooltip.d.ts +0 -1
- package/types/ktortu-aaa.d.ts +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ktortu-aaa-tabs.mjs","sources":["../../../../projects/ktortu/aaa/tabs/tab-scroller.ts","../../../../projects/ktortu/aaa/tabs/tabs-config.ts","../../../../projects/ktortu/aaa/tabs/tab-scroller-pager.ts","../../../../projects/ktortu/aaa/tabs/tab-scroll.ts","../../../../projects/ktortu/aaa/tabs/ktortu-aaa-tabs.ts"],"sourcesContent":["import {\n Directive,\n DOCUMENT,\n DestroyRef,\n ElementRef,\n afterNextRender,\n afterRenderEffect,\n computed,\n inject,\n signal,\n} from '@angular/core';\nimport { TabList } from '@angular/aria/tabs';\n\n/** Cible de défilement calculée en phase de lecture, appliquée en phase d'écriture. */\ntype ScrollTarget = { axis: 'left' | 'top'; value: number };\n\n/** Métriques de débordement de la liste d'onglets, mesurées de façon impérative. */\ninterface ScrollMetrics {\n /** Reste-t-il du contenu hors-champ côté début (gauche en LTR / droite en RTL ; haut si vertical) ? */\n canStart: boolean;\n /** Reste-t-il du contenu hors-champ côté fin ? */\n canEnd: boolean;\n /** La liste déborde-t-elle (taille de défilement > taille visible) ? */\n overflowing: boolean;\n /** Axe courant. */\n vertical: boolean;\n}\n\nconst EMPTY_METRICS: ScrollMetrics = { canStart: false, canEnd: false, overflowing: false, vertical: false };\n\n/** Tolérance d'1px : arrondis sub-pixel, zoom navigateur. */\nconst EPS = 1;\n\n/** Fraction de la zone visible parcourue par un « page » de pagination (chevauchement d'un onglet). */\nconst PAGE_RATIO = 0.8;\n\n/**\n * Pilote le **débordement** d'une liste d'onglets `@angular/aria/tabs` (cf. tabs.css). Deux rôles :\n *\n * 1. **Scroll-into-view** : amène l'onglet sélectionné dans la vue au montage et lors d'un changement\n * de sélection programmatique (ce que le CSS seul ne fait pas), en respectant `prefers-reduced-motion`.\n * 2. **Pagination** : expose un état réactif (`canScrollStart()`, `canScrollEnd()`, `overflowing()`,\n * `orientation()`) et une méthode `scrollByPage()`, pour brancher des boutons chevrons (cf. le\n * composant clé-en-main `KtTabScrollerPager`, ou des boutons custom via `exportAs: 'ktTabScroller'`).\n *\n * Opt-in, à poser sur `[ngTabList]` :\n *\n * @example\n * ```html\n * <ul ngTabList ktTabScroller #s=\"ktTabScroller\" [(selectedTab)]=\"tab\"> … </ul>\n * <button (click)=\"s.scrollByPage('start')\" [disabled]=\"!s.canScrollStart()\">‹</button>\n * ```\n */\n@Directive({\n selector: '[ngTabList][ktTabScroller]',\n exportAs: 'ktTabScroller',\n host: {\n // Marqueur CSS : pagination réactive active → la scrollbar native est masquée (cf. tabs.css).\n '[attr.data-kt-tab-scroller]': '\"\"',\n },\n})\nexport class KtTabScroller {\n private readonly list = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n private readonly tabList = inject(TabList);\n private readonly doc = inject(DOCUMENT);\n private readonly destroyRef = inject(DestroyRef);\n /** Préférence « réduire les animations », lue à chaud (absente possible en SSR/jsdom). */\n private readonly reducedMotion = this.doc.defaultView?.matchMedia?.('(prefers-reduced-motion: reduce)');\n\n /**\n * Métriques de débordement. Mises à jour UNIQUEMENT depuis des callbacks navigateur\n * (`afterNextRender`, `scroll`, `ResizeObserver`, `MutationObserver`) — jamais depuis le corps\n * d'un effet réactif, pour rester conforme (pas d'écriture de signal dans un effet).\n */\n private readonly metrics = signal<ScrollMetrics>(EMPTY_METRICS);\n\n /** Reste-t-il du contenu hors-champ côté début (à brancher sur le bouton « précédent ») ? */\n readonly canScrollStart = computed(() => this.metrics().canStart);\n /** Reste-t-il du contenu hors-champ côté fin (à brancher sur le bouton « suivant ») ? */\n readonly canScrollEnd = computed(() => this.metrics().canEnd);\n /** La liste déborde-t-elle ? (utile pour masquer toute la barre de pagination). */\n readonly overflowing = computed(() => this.metrics().overflowing);\n /** Axe courant, dérivé de l'orientation `@angular/aria`. */\n readonly orientation = computed<'horizontal' | 'vertical'>(() =>\n this.metrics().vertical ? 'vertical' : 'horizontal',\n );\n\n constructor() {\n // 1. Scroll-into-view (phasé : mesure en `earlyRead`, scroll en `write`, pas de reflow forcé).\n // Le `scrollTo` émet un événement `scroll` → remeasure via le listener (aucun `set` ici).\n afterRenderEffect({\n earlyRead: () => this.computeScrollTarget(),\n write: (target) => {\n const t = target();\n if (!t) return;\n this.list.scrollTo({ [t.axis]: t.value, behavior: this.scrollBehavior() });\n },\n });\n\n // 2. Mesure initiale + observateurs (browser-only ; `afterNextRender` ne tourne pas en SSR).\n afterNextRender(() => {\n const view = this.doc.defaultView;\n if (!view) return;\n this.remeasure();\n\n const onScroll = () => this.remeasure();\n this.list.addEventListener('scroll', onScroll, { passive: true });\n\n // ResizeObserver : viewport ET contenu (les onglets qui changent de largeur). Référencé en\n // global (jamais instancié en SSR puisque dans `afterNextRender`).\n const ro = new ResizeObserver(() => this.remeasure());\n const observeAll = () => {\n ro.disconnect();\n ro.observe(this.list);\n for (const child of Array.from(this.list.children)) ro.observe(child);\n };\n observeAll();\n\n // MutationObserver : onglets ajoutés/retirés (@for) → re-observer + remeasure.\n const mo = new MutationObserver(() => {\n observeAll();\n this.remeasure();\n });\n mo.observe(this.list, { childList: true });\n\n this.destroyRef.onDestroy(() => {\n this.list.removeEventListener('scroll', onScroll);\n ro.disconnect();\n mo.disconnect();\n });\n });\n }\n\n /**\n * Fait défiler d'environ une « page » (≈ {@link PAGE_RATIO} de la zone visible) vers le début ou la\n * fin. `behavior` respecte `prefers-reduced-motion`. Le navigateur sature au min/max ; les boutons\n * câblés sont `disabled` aux extrémités, donc l'appel n'a pas lieu à vide.\n */\n scrollByPage(dir: 'start' | 'end'): void {\n const el = this.list;\n const sign = dir === 'end' ? 1 : -1;\n if (this.metrics().vertical) {\n el.scrollBy({ top: sign * el.clientHeight * PAGE_RATIO, behavior: this.scrollBehavior() });\n return;\n }\n // RTL : le sens d'écriture inverse le signe de `scrollLeft`.\n const rtlSign = this.isRtl() ? -1 : 1;\n el.scrollBy({ left: sign * rtlSign * el.clientWidth * PAGE_RATIO, behavior: this.scrollBehavior() });\n }\n\n /** Met à jour le signal de métriques. Appelé depuis des callbacks navigateur (jamais un effet). */\n private remeasure(): void {\n this.metrics.set(this.measure());\n }\n\n /** Mesure le débordement (lecture pure de géométrie, n'écrit rien). */\n private measure(): ScrollMetrics {\n const el = this.list;\n const vertical = this.isVertical();\n\n if (vertical) {\n const { scrollTop, scrollHeight, clientHeight } = el;\n const max = scrollHeight - clientHeight;\n return { vertical: true, overflowing: max > EPS, canStart: scrollTop > EPS, canEnd: scrollTop < max - EPS };\n }\n\n const { scrollLeft, scrollWidth, clientWidth } = el;\n const max = scrollWidth - clientWidth;\n const rtl = this.isRtl();\n // Distances logiques indépendantes du signe de `scrollLeft` (négatif en RTL sur les navigateurs récents).\n const fromStart = rtl ? -scrollLeft : scrollLeft;\n const fromEnd = max - Math.abs(scrollLeft);\n return { vertical: false, overflowing: max > EPS, canStart: fromStart > EPS, canEnd: fromEnd > EPS };\n }\n\n private isVertical(): boolean {\n return (\n this.list.getAttribute('aria-orientation') === 'vertical' || this.list.getAttribute('orientation') === 'vertical'\n );\n }\n\n private isRtl(): boolean {\n return this.doc.defaultView?.getComputedStyle(this.list).direction === 'rtl';\n }\n\n /**\n * `auto` si l'utilisateur a demandé à réduire les animations (WCAG 2.3.3 AAA), `smooth` sinon.\n * Passer un `behavior` explicite à `scrollTo`/`scrollBy` écrase la propriété CSS `scroll-behavior`,\n * d'où la nécessité de répliquer ici la décision que le CSS prend via `prefers-reduced-motion`.\n */\n private scrollBehavior(): ScrollBehavior {\n return this.reducedMotion?.matches ? 'auto' : 'smooth';\n }\n\n /**\n * Calcule l'offset à atteindre pour amener l'onglet actif dans la vue, ou `null` s'il est déjà\n * visible (ou s'il n'y a aucun onglet sélectionné). Lit `selectedTab()` → dépendance réactive.\n */\n private computeScrollTarget(): ScrollTarget | null {\n const selected = this.tabList.findTab(this.tabList.selectedTab())?.element;\n if (!selected) return null;\n\n const container = this.list;\n if (this.isVertical()) {\n const selectedTop = selected.offsetTop;\n const selectedBottom = selectedTop + selected.offsetHeight;\n const containerTop = container.scrollTop;\n const containerBottom = containerTop + container.clientHeight;\n\n if (selectedTop < containerTop) return { axis: 'top', value: selectedTop };\n if (selectedBottom > containerBottom) return { axis: 'top', value: selectedBottom - container.clientHeight };\n return null;\n }\n\n const selectedLeft = selected.offsetLeft;\n const selectedRight = selectedLeft + selected.offsetWidth;\n const containerLeft = container.scrollLeft;\n const containerRight = containerLeft + container.clientWidth;\n\n if (selectedLeft < containerLeft) return { axis: 'left', value: selectedLeft };\n if (selectedRight > containerRight) return { axis: 'left', value: selectedRight - container.clientWidth };\n return null;\n }\n}\n","import { InjectionToken } from '@angular/core';\n\n/** Défauts applicables à tous les `kt-tab-scroller` (surchargeables par instance via les inputs).\n Lib neutre i18n : les textes sont fournis par le consommateur (ici en une fois).\n Fourni en `Partial` : un consommateur n'override que ce qu'il veut.\n Calqué sur `KT_FIELD_CONFIG`/`KT_CHIPS_CONFIG`. */\nexport interface KtTabsConfig {\n /** `aria-label` du chevron de pagination « onglets précédents ». Défaut : `'Previous tabs'`. */\n previousLabel: string;\n /** `aria-label` du chevron de pagination « onglets suivants ». Défaut : `'Next tabs'`. */\n nextLabel: string;\n}\n\nexport const KT_TABS_CONFIG = new InjectionToken<Partial<KtTabsConfig>>('KT_TABS_CONFIG');\n","import {\n ChangeDetectionStrategy,\n Component,\n DOCUMENT,\n ElementRef,\n afterNextRender,\n computed,\n contentChild,\n inject,\n input,\n signal,\n} from '@angular/core';\n\nimport { KtButton } from '@ktortu/aaa/button';\nimport { KtTabScroller } from './tab-scroller';\nimport { KT_TABS_CONFIG } from './tabs-config';\n\n/**\n * Composant clé-en-main : enveloppe une liste d'onglets `@angular/aria/tabs` débordante de deux\n * **chevrons de pagination** accessibles (style Material). Il ne contient aucune logique propre :\n * il lit l'état réactif de la directive headless {@link KtTabScroller} (à poser sur le `ngTabList`\n * projeté) et câble deux boutons {@link KtButton}.\n *\n * @example\n * ```html\n * <kt-tab-scroller>\n * <ul ngTabList ktTabScroller [(selectedTab)]=\"tab\">\n * @for (t of tabs; track t) { <li ngTab [value]=\"t\">…</li> }\n * </ul>\n * </kt-tab-scroller>\n * ```\n */\n@Component({\n selector: 'kt-tab-scroller',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [KtButton],\n host: {\n '[attr.data-orientation]': 'scroller().orientation()',\n '[attr.data-overflowing]': 'scroller().overflowing() ? \"\" : null',\n },\n template: `\n <button\n ktButton\n type=\"button\"\n mode=\"text\"\n iconOnly\n class=\"kt-tab-scroller__chevron kt-tab-scroller__chevron--start\"\n [icon]=\"startIcon()\"\n [ariaLabel]=\"previousLabel()\"\n [disabled]=\"!scroller().canScrollStart()\"\n (click)=\"scroller().scrollByPage('start')\"\n ></button>\n\n <div class=\"kt-tab-scroller__viewport\">\n <ng-content select=\"[ngTabList]\" />\n </div>\n\n <button\n ktButton\n type=\"button\"\n mode=\"text\"\n iconOnly\n class=\"kt-tab-scroller__chevron kt-tab-scroller__chevron--end\"\n [icon]=\"endIcon()\"\n [ariaLabel]=\"nextLabel()\"\n [disabled]=\"!scroller().canScrollEnd()\"\n (click)=\"scroller().scrollByPage('end')\"\n ></button>\n `,\n})\nexport class KtTabScrollerPager {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n private readonly doc = inject(DOCUMENT);\n\n /** Défauts d'app (provider global `KT_TABS_CONFIG`) ; les inputs ci-dessous priment dessus. */\n private readonly config = inject(KT_TABS_CONFIG, { optional: true });\n\n /** La directive headless posée sur le `ngTabList` projeté (`descendants` car dans le viewport). */\n protected readonly scroller = contentChild.required(KtTabScroller, { descendants: true });\n\n /** Sens de lecture (figé au montage : le RTL inverse les chevrons gauche/droite). */\n private readonly dir = signal<'ltr' | 'rtl'>('ltr');\n\n protected readonly startIcon = computed(() => {\n if (this.scroller().orientation() === 'vertical') return 'expand_less';\n return this.dir() === 'rtl' ? 'chevron_right' : 'chevron_left';\n });\n protected readonly endIcon = computed(() => {\n if (this.scroller().orientation() === 'vertical') return 'expand_more';\n return this.dir() === 'rtl' ? 'chevron_left' : 'chevron_right';\n });\n\n /**\n * Noms accessibles des chevrons (`aria-label`). Résolution `input ?? KT_TABS_CONFIG ?? défaut`,\n * comme partout dans la lib (cf. `KT_FIELD_CONFIG`/`KT_CHIPS_CONFIG`). Défauts en anglais : lib\n * neutre i18n, les textes sont fournis par le consommateur (provider global ou binding).\n */\n /**\n * `aria-label` du chevron « onglets précédents ».\n * @default config.previousLabel ?? 'Previous tabs'\n */\n readonly previousLabel = input(this.config?.previousLabel ?? 'Previous tabs');\n /**\n * `aria-label` du chevron « onglets suivants ».\n * @default config.nextLabel ?? 'Next tabs'\n */\n readonly nextLabel = input(this.config?.nextLabel ?? 'Next tabs');\n\n constructor() {\n afterNextRender(() => {\n if (this.doc.defaultView?.getComputedStyle(this.host).direction === 'rtl') this.dir.set('rtl');\n });\n }\n}\n","import { Directive } from '@angular/core';\nimport { KtTabScroller } from './tab-scroller';\n\n/**\n * @deprecated Utilisez {@link KtTabScroller} (sélecteur `[ktTabScroller]`) : même défilement de\n * l'onglet sélectionné dans la vue, plus la pagination par chevrons. `ktTabScroll` reste un **alias\n * fonctionnel** (il applique `KtTabScroller` comme directive hôte) et sera retiré dans une version\n * majeure ultérieure.\n *\n * Note : depuis cette version, une liste pilotée par `ktTabScroll`/`ktTabScroller` masque sa\n * scrollbar native par défaut (les chevrons / ombres prennent le relais). Réafficher la barre via\n * `--tab-scroller-scrollbar: thin`.\n */\n@Directive({\n selector: '[ngTabList][ktTabScroll]',\n exportAs: 'ktTabScroll',\n hostDirectives: [KtTabScroller],\n})\nexport class KtTabScroll {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.KtTabScroller"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ktortu-aaa-tabs.mjs","sources":["../../../../projects/ktortu/aaa/tabs/tab-scroller.ts","../../../../projects/ktortu/aaa/tabs/tabs-config.ts","../../../../projects/ktortu/aaa/tabs/tab-scroller-pager.ts","../../../../projects/ktortu/aaa/tabs/tab-scroll.ts","../../../../projects/ktortu/aaa/tabs/ktortu-aaa-tabs.ts"],"sourcesContent":["import {\n Directive,\n DOCUMENT,\n DestroyRef,\n ElementRef,\n afterNextRender,\n afterRenderEffect,\n computed,\n inject,\n signal,\n} from '@angular/core';\nimport { TabList } from '@angular/aria/tabs';\n\n/** Cible de défilement calculée en phase de lecture, appliquée en phase d'écriture. */\ninterface ScrollTarget {\n axis: 'left' | 'top';\n value: number;\n}\n\n/** Métriques de débordement de la liste d'onglets, mesurées de façon impérative. */\ninterface ScrollMetrics {\n /** Reste-t-il du contenu hors-champ côté début (gauche en LTR / droite en RTL ; haut si vertical) ? */\n canStart: boolean;\n /** Reste-t-il du contenu hors-champ côté fin ? */\n canEnd: boolean;\n /** La liste déborde-t-elle (taille de défilement > taille visible) ? */\n overflowing: boolean;\n /** Axe courant. */\n vertical: boolean;\n}\n\nconst EMPTY_METRICS: ScrollMetrics = { canStart: false, canEnd: false, overflowing: false, vertical: false };\n\n/** Tolérance d'1px : arrondis sub-pixel, zoom navigateur. */\nconst EPS = 1;\n\n/** Fraction de la zone visible parcourue par un « page » de pagination (chevauchement d'un onglet). */\nconst PAGE_RATIO = 0.8;\n\n/**\n * Pilote le **débordement** d'une liste d'onglets `@angular/aria/tabs` (cf. tabs.css). Deux rôles :\n *\n * 1. **Scroll-into-view** : amène l'onglet sélectionné dans la vue au montage et lors d'un changement\n * de sélection programmatique (ce que le CSS seul ne fait pas), en respectant `prefers-reduced-motion`.\n * 2. **Pagination** : expose un état réactif (`canScrollStart()`, `canScrollEnd()`, `overflowing()`,\n * `orientation()`) et une méthode `scrollByPage()`, pour brancher des boutons chevrons (cf. le\n * composant clé-en-main `KtTabScrollerPager`, ou des boutons custom via `exportAs: 'ktTabScroller'`).\n *\n * Opt-in, à poser sur `[ngTabList]` :\n *\n * @example\n * ```html\n * <ul ngTabList ktTabScroller #s=\"ktTabScroller\" [(selectedTab)]=\"tab\"> … </ul>\n * <button (click)=\"s.scrollByPage('start')\" [disabled]=\"!s.canScrollStart()\">‹</button>\n * ```\n */\n@Directive({\n selector: '[ngTabList][ktTabScroller]',\n exportAs: 'ktTabScroller',\n host: {\n // Marqueur CSS : pagination réactive active → la scrollbar native est masquée (cf. tabs.css).\n '[attr.data-kt-tab-scroller]': '\"\"',\n },\n})\nexport class KtTabScroller {\n private readonly list = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n private readonly tabList = inject(TabList);\n private readonly doc = inject(DOCUMENT);\n private readonly destroyRef = inject(DestroyRef);\n /** Préférence « réduire les animations », lue à chaud (absente possible en SSR/jsdom). */\n private readonly reducedMotion = this.doc.defaultView?.matchMedia?.('(prefers-reduced-motion: reduce)');\n\n /**\n * Métriques de débordement. Mises à jour UNIQUEMENT depuis des callbacks navigateur\n * (`afterNextRender`, `scroll`, `ResizeObserver`, `MutationObserver`) — jamais depuis le corps\n * d'un effet réactif, pour rester conforme (pas d'écriture de signal dans un effet).\n */\n private readonly metrics = signal<ScrollMetrics>(EMPTY_METRICS);\n\n /** Reste-t-il du contenu hors-champ côté début (à brancher sur le bouton « précédent ») ? */\n readonly canScrollStart = computed(() => this.metrics().canStart);\n /** Reste-t-il du contenu hors-champ côté fin (à brancher sur le bouton « suivant ») ? */\n readonly canScrollEnd = computed(() => this.metrics().canEnd);\n /** La liste déborde-t-elle ? (utile pour masquer toute la barre de pagination). */\n readonly overflowing = computed(() => this.metrics().overflowing);\n /** Axe courant, dérivé de l'orientation `@angular/aria`. */\n readonly orientation = computed<'horizontal' | 'vertical'>(() =>\n this.metrics().vertical ? 'vertical' : 'horizontal',\n );\n\n constructor() {\n // 1. Scroll-into-view (phasé : mesure en `earlyRead`, scroll en `write`, pas de reflow forcé).\n // Le `scrollTo` émet un événement `scroll` → remeasure via le listener (aucun `set` ici).\n afterRenderEffect({\n earlyRead: () => this.computeScrollTarget(),\n write: (target) => {\n const t = target();\n if (!t) return;\n this.list.scrollTo({ [t.axis]: t.value, behavior: this.scrollBehavior() });\n },\n });\n\n // 2. Mesure initiale + observateurs (browser-only ; `afterNextRender` ne tourne pas en SSR).\n afterNextRender(() => {\n const view = this.doc.defaultView;\n if (!view) return;\n this.remeasure();\n\n const onScroll = () => this.remeasure();\n this.list.addEventListener('scroll', onScroll, { passive: true });\n\n // ResizeObserver : viewport ET contenu (les onglets qui changent de largeur). Référencé en\n // global (jamais instancié en SSR puisque dans `afterNextRender`).\n const ro = new ResizeObserver(() => this.remeasure());\n const observeAll = () => {\n ro.disconnect();\n ro.observe(this.list);\n for (const child of Array.from(this.list.children)) ro.observe(child);\n };\n observeAll();\n\n // MutationObserver : onglets ajoutés/retirés (@for) → re-observer + remeasure.\n const mo = new MutationObserver(() => {\n observeAll();\n this.remeasure();\n });\n mo.observe(this.list, { childList: true });\n\n this.destroyRef.onDestroy(() => {\n this.list.removeEventListener('scroll', onScroll);\n ro.disconnect();\n mo.disconnect();\n });\n });\n }\n\n /**\n * Fait défiler d'environ une « page » (≈ {@link PAGE_RATIO} de la zone visible) vers le début ou la\n * fin. `behavior` respecte `prefers-reduced-motion`. Le navigateur sature au min/max ; les boutons\n * câblés sont `disabled` aux extrémités, donc l'appel n'a pas lieu à vide.\n */\n scrollByPage(dir: 'start' | 'end'): void {\n const el = this.list;\n const sign = dir === 'end' ? 1 : -1;\n if (this.metrics().vertical) {\n el.scrollBy({ top: sign * el.clientHeight * PAGE_RATIO, behavior: this.scrollBehavior() });\n return;\n }\n // RTL : le sens d'écriture inverse le signe de `scrollLeft`.\n const rtlSign = this.isRtl() ? -1 : 1;\n el.scrollBy({ left: sign * rtlSign * el.clientWidth * PAGE_RATIO, behavior: this.scrollBehavior() });\n }\n\n /** Met à jour le signal de métriques. Appelé depuis des callbacks navigateur (jamais un effet). */\n private remeasure(): void {\n this.metrics.set(this.measure());\n }\n\n /** Mesure le débordement (lecture pure de géométrie, n'écrit rien). */\n private measure(): ScrollMetrics {\n const el = this.list;\n const vertical = this.isVertical();\n\n if (vertical) {\n const { scrollTop, scrollHeight, clientHeight } = el;\n const max = scrollHeight - clientHeight;\n return { vertical: true, overflowing: max > EPS, canStart: scrollTop > EPS, canEnd: scrollTop < max - EPS };\n }\n\n const { scrollLeft, scrollWidth, clientWidth } = el;\n const max = scrollWidth - clientWidth;\n const rtl = this.isRtl();\n // Distances logiques indépendantes du signe de `scrollLeft` (négatif en RTL sur les navigateurs récents).\n const fromStart = rtl ? -scrollLeft : scrollLeft;\n const fromEnd = max - Math.abs(scrollLeft);\n return { vertical: false, overflowing: max > EPS, canStart: fromStart > EPS, canEnd: fromEnd > EPS };\n }\n\n private isVertical(): boolean {\n return (\n this.list.getAttribute('aria-orientation') === 'vertical' || this.list.getAttribute('orientation') === 'vertical'\n );\n }\n\n private isRtl(): boolean {\n return this.doc.defaultView?.getComputedStyle(this.list).direction === 'rtl';\n }\n\n /**\n * `auto` si l'utilisateur a demandé à réduire les animations (WCAG 2.3.3 AAA), `smooth` sinon.\n * Passer un `behavior` explicite à `scrollTo`/`scrollBy` écrase la propriété CSS `scroll-behavior`,\n * d'où la nécessité de répliquer ici la décision que le CSS prend via `prefers-reduced-motion`.\n */\n private scrollBehavior(): ScrollBehavior {\n return this.reducedMotion?.matches ? 'auto' : 'smooth';\n }\n\n /**\n * Calcule l'offset à atteindre pour amener l'onglet actif dans la vue, ou `null` s'il est déjà\n * visible (ou s'il n'y a aucun onglet sélectionné). Lit `selectedTab()` → dépendance réactive.\n */\n private computeScrollTarget(): ScrollTarget | null {\n const selected = this.tabList.findTab(this.tabList.selectedTab())?.element;\n if (!selected) return null;\n\n const container = this.list;\n if (this.isVertical()) {\n const selectedTop = selected.offsetTop;\n const selectedBottom = selectedTop + selected.offsetHeight;\n const containerTop = container.scrollTop;\n const containerBottom = containerTop + container.clientHeight;\n\n if (selectedTop < containerTop) return { axis: 'top', value: selectedTop };\n if (selectedBottom > containerBottom) return { axis: 'top', value: selectedBottom - container.clientHeight };\n return null;\n }\n\n const selectedLeft = selected.offsetLeft;\n const selectedRight = selectedLeft + selected.offsetWidth;\n const containerLeft = container.scrollLeft;\n const containerRight = containerLeft + container.clientWidth;\n\n if (selectedLeft < containerLeft) return { axis: 'left', value: selectedLeft };\n if (selectedRight > containerRight) return { axis: 'left', value: selectedRight - container.clientWidth };\n return null;\n }\n}\n","import { InjectionToken } from '@angular/core';\n\n/** Défauts applicables à tous les `kt-tab-scroller` (surchargeables par instance via les inputs).\n Lib neutre i18n : les textes sont fournis par le consommateur (ici en une fois).\n Fourni en `Partial` : un consommateur n'override que ce qu'il veut.\n Calqué sur `KT_FIELD_CONFIG`/`KT_CHIPS_CONFIG`. */\nexport interface KtTabsConfig {\n /** `aria-label` du chevron de pagination « onglets précédents ». Défaut : `'Previous tabs'`. */\n previousLabel: string;\n /** `aria-label` du chevron de pagination « onglets suivants ». Défaut : `'Next tabs'`. */\n nextLabel: string;\n}\n\nexport const KT_TABS_CONFIG = new InjectionToken<Partial<KtTabsConfig>>('KT_TABS_CONFIG');\n","import {\n ChangeDetectionStrategy,\n Component,\n DOCUMENT,\n ElementRef,\n afterNextRender,\n computed,\n contentChild,\n inject,\n input,\n signal,\n} from '@angular/core';\n\nimport { KtButton } from '@ktortu/aaa/button';\nimport { KtTabScroller } from './tab-scroller';\nimport { KT_TABS_CONFIG } from './tabs-config';\n\n/**\n * Composant clé-en-main : enveloppe une liste d'onglets `@angular/aria/tabs` débordante de deux\n * **chevrons de pagination** accessibles (style Material). Il ne contient aucune logique propre :\n * il lit l'état réactif de la directive headless {@link KtTabScroller} (à poser sur le `ngTabList`\n * projeté) et câble deux boutons {@link KtButton}.\n *\n * @example\n * ```html\n * <kt-tab-scroller>\n * <ul ngTabList ktTabScroller [(selectedTab)]=\"tab\">\n * @for (t of tabs; track t) { <li ngTab [value]=\"t\">…</li> }\n * </ul>\n * </kt-tab-scroller>\n * ```\n */\n@Component({\n selector: 'kt-tab-scroller',\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [KtButton],\n host: {\n '[attr.data-orientation]': 'scroller().orientation()',\n '[attr.data-overflowing]': 'scroller().overflowing() ? \"\" : null',\n },\n template: `\n <button\n ktButton\n type=\"button\"\n mode=\"text\"\n iconOnly\n class=\"kt-tab-scroller__chevron kt-tab-scroller__chevron--start\"\n [icon]=\"startIcon()\"\n [ariaLabel]=\"previousLabel()\"\n [disabled]=\"!scroller().canScrollStart()\"\n (click)=\"scroller().scrollByPage('start')\"\n ></button>\n\n <div class=\"kt-tab-scroller__viewport\">\n <ng-content select=\"[ngTabList]\" />\n </div>\n\n <button\n ktButton\n type=\"button\"\n mode=\"text\"\n iconOnly\n class=\"kt-tab-scroller__chevron kt-tab-scroller__chevron--end\"\n [icon]=\"endIcon()\"\n [ariaLabel]=\"nextLabel()\"\n [disabled]=\"!scroller().canScrollEnd()\"\n (click)=\"scroller().scrollByPage('end')\"\n ></button>\n `,\n})\nexport class KtTabScrollerPager {\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n private readonly doc = inject(DOCUMENT);\n\n /** Défauts d'app (provider global `KT_TABS_CONFIG`) ; les inputs ci-dessous priment dessus. */\n private readonly config = inject(KT_TABS_CONFIG, { optional: true });\n\n /** La directive headless posée sur le `ngTabList` projeté (`descendants` car dans le viewport). */\n protected readonly scroller = contentChild.required(KtTabScroller, { descendants: true });\n\n /** Sens de lecture (figé au montage : le RTL inverse les chevrons gauche/droite). */\n private readonly dir = signal<'ltr' | 'rtl'>('ltr');\n\n protected readonly startIcon = computed(() => {\n if (this.scroller().orientation() === 'vertical') return 'expand_less';\n return this.dir() === 'rtl' ? 'chevron_right' : 'chevron_left';\n });\n protected readonly endIcon = computed(() => {\n if (this.scroller().orientation() === 'vertical') return 'expand_more';\n return this.dir() === 'rtl' ? 'chevron_left' : 'chevron_right';\n });\n\n /**\n * Noms accessibles des chevrons (`aria-label`). Résolution `input ?? KT_TABS_CONFIG ?? défaut`,\n * comme partout dans la lib (cf. `KT_FIELD_CONFIG`/`KT_CHIPS_CONFIG`). Défauts en anglais : lib\n * neutre i18n, les textes sont fournis par le consommateur (provider global ou binding).\n */\n /**\n * `aria-label` du chevron « onglets précédents ».\n * @default config.previousLabel ?? 'Previous tabs'\n */\n readonly previousLabel = input(this.config?.previousLabel ?? 'Previous tabs');\n /**\n * `aria-label` du chevron « onglets suivants ».\n * @default config.nextLabel ?? 'Next tabs'\n */\n readonly nextLabel = input(this.config?.nextLabel ?? 'Next tabs');\n\n constructor() {\n afterNextRender(() => {\n if (this.doc.defaultView?.getComputedStyle(this.host).direction === 'rtl') this.dir.set('rtl');\n });\n }\n}\n","import { Directive } from '@angular/core';\nimport { KtTabScroller } from './tab-scroller';\n\n/**\n * @deprecated Utilisez {@link KtTabScroller} (sélecteur `[ktTabScroller]`) : même défilement de\n * l'onglet sélectionné dans la vue, plus la pagination par chevrons. `ktTabScroll` reste un **alias\n * fonctionnel** (il applique `KtTabScroller` comme directive hôte) et sera retiré dans une version\n * majeure ultérieure.\n *\n * Note : depuis cette version, une liste pilotée par `ktTabScroll`/`ktTabScroller` masque sa\n * scrollbar native par défaut (les chevrons / ombres prennent le relais). Réafficher la barre via\n * `--tab-scroller-scrollbar: thin`.\n */\n@Directive({\n selector: '[ngTabList][ktTabScroll]',\n exportAs: 'ktTabScroll',\n hostDirectives: [KtTabScroller],\n})\nexport class KtTabScroll {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i1.KtTabScroller"],"mappings":";;;;;AA+BA,MAAM,aAAa,GAAkB,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE;AAE5G;AACA,MAAM,GAAG,GAAG,CAAC;AAEb;AACA,MAAM,UAAU,GAAG,GAAG;AAEtB;;;;;;;;;;;;;;;;AAgBG;MASU,aAAa,CAAA;AACP,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC,CAAC,aAAa;AAChE,IAAA,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;AACzB,IAAA,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;AACtB,IAAA,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;;AAE/B,IAAA,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,UAAU,GAAG,kCAAkC,CAAC;AAEvG;;;;AAIG;IACc,OAAO,GAAG,MAAM,CAAgB,aAAa;gFAAC;;IAGtD,cAAc,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,QAAQ;uFAAC;;IAExD,YAAY,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM;qFAAC;;IAEpD,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,WAAW;oFAAC;;AAExD,IAAA,WAAW,GAAG,QAAQ,CAA4B,MACzD,IAAI,CAAC,OAAO,EAAE,CAAC,QAAQ,GAAG,UAAU,GAAG,YAAY;oFACpD;AAED,IAAA,WAAA,GAAA;;;AAGE,QAAA,iBAAiB,CAAC;AAChB,YAAA,SAAS,EAAE,MAAM,IAAI,CAAC,mBAAmB,EAAE;AAC3C,YAAA,KAAK,EAAE,CAAC,MAAM,KAAI;AAChB,gBAAA,MAAM,CAAC,GAAG,MAAM,EAAE;AAClB,gBAAA,IAAI,CAAC,CAAC;oBAAE;gBACR,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YAC5E,CAAC;AACF,SAAA,CAAC;;QAGF,eAAe,CAAC,MAAK;AACnB,YAAA,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW;AACjC,YAAA,IAAI,CAAC,IAAI;gBAAE;YACX,IAAI,CAAC,SAAS,EAAE;YAEhB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE;AACvC,YAAA,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;;AAIjE,YAAA,MAAM,EAAE,GAAG,IAAI,cAAc,CAAC,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;YACrD,MAAM,UAAU,GAAG,MAAK;gBACtB,EAAE,CAAC,UAAU,EAAE;AACf,gBAAA,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;AACrB,gBAAA,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;AAAE,oBAAA,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;AACvE,YAAA,CAAC;AACD,YAAA,UAAU,EAAE;;AAGZ,YAAA,MAAM,EAAE,GAAG,IAAI,gBAAgB,CAAC,MAAK;AACnC,gBAAA,UAAU,EAAE;gBACZ,IAAI,CAAC,SAAS,EAAE;AAClB,YAAA,CAAC,CAAC;AACF,YAAA,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAE1C,YAAA,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAK;gBAC7B,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC;gBACjD,EAAE,CAAC,UAAU,EAAE;gBACf,EAAE,CAAC,UAAU,EAAE;AACjB,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;IACJ;AAEA;;;;AAIG;AACH,IAAA,YAAY,CAAC,GAAoB,EAAA;AAC/B,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI;AACpB,QAAA,MAAM,IAAI,GAAG,GAAG,KAAK,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;AACnC,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YAC3B,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,IAAI,GAAG,EAAE,CAAC,YAAY,GAAG,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YAC1F;QACF;;AAEA,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC;QACrC,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,GAAG,EAAE,CAAC,WAAW,GAAG,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;IACtG;;IAGQ,SAAS,GAAA;QACf,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;IAClC;;IAGQ,OAAO,GAAA;AACb,QAAA,MAAM,EAAE,GAAG,IAAI,CAAC,IAAI;AACpB,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,EAAE;QAElC,IAAI,QAAQ,EAAE;YACZ,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,GAAG,EAAE;AACpD,YAAA,MAAM,GAAG,GAAG,YAAY,GAAG,YAAY;YACvC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,GAAG,GAAG,EAAE,QAAQ,EAAE,SAAS,GAAG,GAAG,EAAE,MAAM,EAAE,SAAS,GAAG,GAAG,GAAG,GAAG,EAAE;QAC7G;QAEA,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,EAAE;AACnD,QAAA,MAAM,GAAG,GAAG,WAAW,GAAG,WAAW;AACrC,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE;;AAExB,QAAA,MAAM,SAAS,GAAG,GAAG,GAAG,CAAC,UAAU,GAAG,UAAU;QAChD,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;QAC1C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,GAAG,GAAG,EAAE,QAAQ,EAAE,SAAS,GAAG,GAAG,EAAE,MAAM,EAAE,OAAO,GAAG,GAAG,EAAE;IACtG;IAEQ,UAAU,GAAA;QAChB,QACE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,KAAK,UAAU;IAErH;IAEQ,KAAK,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,KAAK;IAC9E;AAEA;;;;AAIG;IACK,cAAc,GAAA;AACpB,QAAA,OAAO,IAAI,CAAC,aAAa,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ;IACxD;AAEA;;;AAGG;IACK,mBAAmB,GAAA;AACzB,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,EAAE,OAAO;AAC1E,QAAA,IAAI,CAAC,QAAQ;AAAE,YAAA,OAAO,IAAI;AAE1B,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI;AAC3B,QAAA,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE;AACrB,YAAA,MAAM,WAAW,GAAG,QAAQ,CAAC,SAAS;AACtC,YAAA,MAAM,cAAc,GAAG,WAAW,GAAG,QAAQ,CAAC,YAAY;AAC1D,YAAA,MAAM,YAAY,GAAG,SAAS,CAAC,SAAS;AACxC,YAAA,MAAM,eAAe,GAAG,YAAY,GAAG,SAAS,CAAC,YAAY;YAE7D,IAAI,WAAW,GAAG,YAAY;gBAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE;YAC1E,IAAI,cAAc,GAAG,eAAe;AAAE,gBAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,GAAG,SAAS,CAAC,YAAY,EAAE;AAC5G,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,MAAM,YAAY,GAAG,QAAQ,CAAC,UAAU;AACxC,QAAA,MAAM,aAAa,GAAG,YAAY,GAAG,QAAQ,CAAC,WAAW;AACzD,QAAA,MAAM,aAAa,GAAG,SAAS,CAAC,UAAU;AAC1C,QAAA,MAAM,cAAc,GAAG,aAAa,GAAG,SAAS,CAAC,WAAW;QAE5D,IAAI,YAAY,GAAG,aAAa;YAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE;QAC9E,IAAI,aAAa,GAAG,cAAc;AAAE,YAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,SAAS,CAAC,WAAW,EAAE;AACzG,QAAA,OAAO,IAAI;IACb;uGAjKW,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAb,aAAa,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,4BAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,2BAAA,EAAA,MAAA,EAAA,EAAA,EAAA,QAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAb,aAAa,EAAA,UAAA,EAAA,CAAA;kBARzB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,4BAA4B;AACtC,oBAAA,QAAQ,EAAE,eAAe;AACzB,oBAAA,IAAI,EAAE;;AAEJ,wBAAA,6BAA6B,EAAE,IAAI;AACpC,qBAAA;AACF,iBAAA;;;MClDY,cAAc,GAAG,IAAI,cAAc,CAAwB,gBAAgB;;ACIxF;;;;;;;;;;;;;;AAcG;MAuCU,kBAAkB,CAAA;AACZ,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC,CAAC,aAAa;AAChE,IAAA,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;;IAGtB,MAAM,GAAG,MAAM,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;AAGjD,IAAA,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;;IAGxE,GAAG,GAAG,MAAM,CAAgB,KAAK;4EAAC;AAEhC,IAAA,SAAS,GAAG,QAAQ,CAAC,MAAK;QAC3C,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,KAAK,UAAU;AAAE,YAAA,OAAO,aAAa;AACtE,QAAA,OAAO,IAAI,CAAC,GAAG,EAAE,KAAK,KAAK,GAAG,eAAe,GAAG,cAAc;IAChE,CAAC;kFAAC;AACiB,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;QACzC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,KAAK,UAAU;AAAE,YAAA,OAAO,aAAa;AACtE,QAAA,OAAO,IAAI,CAAC,GAAG,EAAE,KAAK,KAAK,GAAG,cAAc,GAAG,eAAe;IAChE,CAAC;gFAAC;AAEF;;;;AAIG;AACH;;;AAGG;IACM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,IAAI,eAAe;sFAAC;AAC7E;;;AAGG;IACM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,IAAI,WAAW;kFAAC;AAEjE,IAAA,WAAA,GAAA;QACE,eAAe,CAAC,MAAK;AACnB,YAAA,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,KAAK,KAAK;AAAE,gBAAA,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC;AAChG,QAAA,CAAC,CAAC;IACJ;uGA1CW,kBAAkB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAlB,kBAAkB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,uBAAA,EAAA,0BAAA,EAAA,uBAAA,EAAA,wCAAA,EAAA,EAAA,EAAA,OAAA,EAAA,CAAA,EAAA,YAAA,EAAA,UAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAQuB,aAAa,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAtCvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAjCS,QAAQ,EAAA,QAAA,EAAA,+BAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,OAAA,EAAA,MAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,MAAA,EAAA,SAAA,EAAA,MAAA,EAAA,cAAA,EAAA,UAAA,EAAA,qBAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAmCP,kBAAkB,EAAA,UAAA,EAAA,CAAA;kBAtC9B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,iBAAiB;oBAC3B,eAAe,EAAE,uBAAuB,CAAC,MAAM;oBAC/C,OAAO,EAAE,CAAC,QAAQ,CAAC;AACnB,oBAAA,IAAI,EAAE;AACJ,wBAAA,yBAAyB,EAAE,0BAA0B;AACrD,wBAAA,yBAAyB,EAAE,sCAAsC;AAClE,qBAAA;AACD,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BT,EAAA,CAAA;AACF,iBAAA;AASqD,SAAA,CAAA,EAAA,cAAA,EAAA,MAAA,EAAA,EAAA,cAAA,EAAA,EAAA,QAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,YAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,UAAA,CAAA,MAAA,aAAa,CAAA,EAAA,EAAA,GAAE,EAAE,WAAW,EAAE,IAAI,EAAE,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,aAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,eAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,SAAA,EAAA,CAAA,EAAA,IAAA,EAAA,EAAA,CAAA,KAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,KAAA,EAAA,WAAA,EAAA,QAAA,EAAA,KAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;AC3E1F;;;;;;;;;AASG;MAMU,WAAW,CAAA;uGAAX,WAAW,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAX,WAAW,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,0BAAA,EAAA,QAAA,EAAA,CAAA,aAAA,CAAA,EAAA,cAAA,EAAA,CAAA,EAAA,SAAA,EAAAA,aAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAX,WAAW,EAAA,UAAA,EAAA,CAAA;kBALvB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,0BAA0B;AACpC,oBAAA,QAAQ,EAAE,aAAa;oBACvB,cAAc,EAAE,CAAC,aAAa,CAAC;AAChC,iBAAA;;;ACjBD;;AAEG;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { InjectionToken, inject, ElementRef, Renderer2, ViewContainerRef,
|
|
3
|
+
import { InjectionToken, inject, ElementRef, Renderer2, ViewContainerRef, PLATFORM_ID, input, booleanAttribute, computed, signal, effect, TemplateRef, isDevMode, Directive } from '@angular/core';
|
|
4
4
|
import { KtIdGenerator } from '@ktortu/aaa/cdk';
|
|
5
5
|
|
|
6
6
|
const KT_TOOLTIP_CONFIG = new InjectionToken('KT_TOOLTIP_CONFIG');
|
|
@@ -33,7 +33,6 @@ class KtTooltip {
|
|
|
33
33
|
host = inject(ElementRef);
|
|
34
34
|
renderer = inject(Renderer2);
|
|
35
35
|
vcr = inject(ViewContainerRef);
|
|
36
|
-
ngZone = inject(NgZone);
|
|
37
36
|
platformId = inject(PLATFORM_ID);
|
|
38
37
|
/** Contenu de l'infobulle : texte simple (injecté en `textContent`) ou `TemplateRef` non interactif. */
|
|
39
38
|
ktTooltip = input.required(/* @ts-ignore */
|
|
@@ -67,7 +66,8 @@ class KtTooltip {
|
|
|
67
66
|
}, /* @ts-ignore */
|
|
68
67
|
...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
|
|
69
68
|
// Retourner null retire l'attribut (même astuce que aria-disabled dans button).
|
|
70
|
-
//
|
|
69
|
+
// aria-describedby n'est posé sur le déclencheur que lorsque le tooltip est affiché : sinon il
|
|
70
|
+
// référencerait un nœud absent du DOM (création lazy), donnant une référence pendante aux AT.
|
|
71
71
|
describedById = computed(() => (this.isActive() && this.isShown() ? this.tooltipId : null), /* @ts-ignore */
|
|
72
72
|
...(ngDevMode ? [{ debugName: "describedById" }] : /* istanbul ignore next */ []));
|
|
73
73
|
tip = null;
|
|
@@ -126,27 +126,19 @@ class KtTooltip {
|
|
|
126
126
|
show() {
|
|
127
127
|
if (!this.isActive())
|
|
128
128
|
return;
|
|
129
|
-
this.
|
|
130
|
-
|
|
131
|
-
this.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
}, this.showDelay());
|
|
141
|
-
});
|
|
129
|
+
clearTimeout(this.hideTimer);
|
|
130
|
+
this.showTimer = setTimeout(() => {
|
|
131
|
+
if (this.isShown())
|
|
132
|
+
return;
|
|
133
|
+
this.isShown.set(true);
|
|
134
|
+
if (!this.supportsAnchor) {
|
|
135
|
+
this.registerFallbackListeners();
|
|
136
|
+
}
|
|
137
|
+
}, this.showDelay());
|
|
142
138
|
}
|
|
143
139
|
hide() {
|
|
144
|
-
this.
|
|
145
|
-
|
|
146
|
-
this.hideTimer = setTimeout(() => {
|
|
147
|
-
this.ngZone.run(() => this.dismiss());
|
|
148
|
-
}, this.hideDelay());
|
|
149
|
-
});
|
|
140
|
+
clearTimeout(this.showTimer);
|
|
141
|
+
this.hideTimer = setTimeout(() => this.dismiss(), this.hideDelay());
|
|
150
142
|
}
|
|
151
143
|
onEscape(event) {
|
|
152
144
|
if (!this.isShown())
|
|
@@ -317,14 +309,12 @@ class KtTooltip {
|
|
|
317
309
|
this.clearFallbackListeners();
|
|
318
310
|
if (this.supportsAnchor || !isPlatformBrowser(this.platformId))
|
|
319
311
|
return;
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
this.fallbackListeners.push(() => window.removeEventListener('scroll', onScrollOrResize, { capture: true }), () => window.removeEventListener('resize', onScrollOrResize));
|
|
327
|
-
});
|
|
312
|
+
const onScrollOrResize = () => {
|
|
313
|
+
this.positionFallback();
|
|
314
|
+
};
|
|
315
|
+
window.addEventListener('scroll', onScrollOrResize, { passive: true, capture: true });
|
|
316
|
+
window.addEventListener('resize', onScrollOrResize);
|
|
317
|
+
this.fallbackListeners.push(() => window.removeEventListener('scroll', onScrollOrResize, { capture: true }), () => window.removeEventListener('resize', onScrollOrResize));
|
|
328
318
|
}
|
|
329
319
|
clearFallbackListeners() {
|
|
330
320
|
for (const remove of this.fallbackListeners)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ktortu-aaa-tooltip.mjs","sources":["../../../../projects/ktortu/aaa/tooltip/tooltip.ts","../../../../projects/ktortu/aaa/tooltip/ktortu-aaa-tooltip.ts"],"sourcesContent":["import { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport {\n Directive,\n ElementRef,\n EmbeddedViewRef,\n InjectionToken,\n NgZone,\n OnDestroy,\n Provider,\n Renderer2,\n TemplateRef,\n ViewContainerRef,\n booleanAttribute,\n computed,\n effect,\n inject,\n input,\n isDevMode,\n signal,\n PLATFORM_ID,\n} from '@angular/core';\nimport { KtIdGenerator } from '@ktortu/aaa/cdk';\n\nexport type KtTooltipPosition = 'top' | 'bottom' | 'left' | 'right';\n\n/** Défauts d'infobulle (délais, position) injectables via `provideKtTooltip` / `KT_TOOLTIP_CONFIG`. */\nexport interface KtTooltipConfig {\n /** Délai (ms) avant apparition au survol/focus. */\n showDelay: number;\n /** Délai (ms) avant masquage (laisse le temps d'atteindre l'infobulle, WCAG « hoverable »). */\n hideDelay: number;\n /** Position de l'infobulle autour de la cible. */\n position: KtTooltipPosition;\n}\n\nexport const KT_TOOLTIP_CONFIG = new InjectionToken<Partial<KtTooltipConfig>>('KT_TOOLTIP_CONFIG');\n\n/**\n * Fournit des défauts d'infobulle (délais, position) pour un sous-arbre ou l'application entière.\n *\n * @example\n * ```ts\n * providers: [provideKtTooltip({ showDelay: 300, position: 'bottom' })]\n * ```\n */\nexport function provideKtTooltip(config: Partial<KtTooltipConfig>): Provider {\n return { provide: KT_TOOLTIP_CONFIG, useValue: config };\n}\n\n/**\n * Infobulle accessible posée sur n'importe quel élément focusable/survolable.\n * Apparaît au survol et au focus, reste « hoverable » (WCAG 1.4.13) et se ferme\n * par Échap. Le contenu peut être un texte simple ou un `TemplateRef` **non interactif**\n * (un `role=\"tooltip\"` ne doit pas contenir de lien/bouton/champ).\n *\n * @example\n * ```html\n * <button ktTooltip=\"Enregistrer le brouillon\">Enregistrer</button>\n * <span ktTooltip=\"Aide\" tooltipPosition=\"right\" [showDelay]=\"300\">?</span>\n * ```\n */\n@Directive({\n selector: '[ktTooltip]',\n host: {\n '[attr.aria-describedby]': 'describedById()',\n '(mouseenter)': 'show()',\n '(mouseleave)': 'hide()',\n '(focusin)': 'show()',\n '(focusout)': 'hide()',\n '(keydown.escape)': 'onEscape($event)',\n },\n})\nexport class KtTooltip implements OnDestroy {\n private readonly config = inject(KT_TOOLTIP_CONFIG, { optional: true });\n private readonly doc = inject(DOCUMENT);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly renderer = inject(Renderer2);\n private readonly vcr = inject(ViewContainerRef);\n private readonly ngZone = inject(NgZone);\n private readonly platformId = inject(PLATFORM_ID);\n\n /** Contenu de l'infobulle : texte simple (injecté en `textContent`) ou `TemplateRef` non interactif. */\n readonly ktTooltip = input.required<string | TemplateRef<unknown>>();\n /** Position de l'infobulle autour de la cible. @default 'top' (ou KT_TOOLTIP_CONFIG.position) */\n readonly tooltipPosition = input<KtTooltipPosition>(this.config?.position ?? 'top');\n /** Désactive l'affichage de l'infobulle. @default false */\n readonly tooltipDisabled = input<boolean, unknown>(false, { transform: booleanAttribute });\n /** Délai (ms) avant apparition au survol/focus. @default 150 (ou KT_TOOLTIP_CONFIG.showDelay) */\n readonly showDelay = input<number>(this.config?.showDelay ?? 150);\n /** Délai (ms) avant masquage ; laisse le temps d'amener le pointeur sur l'infobulle (WCAG « hoverable »). @default 100 (ou KT_TOOLTIP_CONFIG.hideDelay) */\n readonly hideDelay = input<number>(this.config?.hideDelay ?? 100);\n\n private readonly idGen = inject(KtIdGenerator);\n private readonly uid = this.idGen.generateId('tooltip');\n private readonly tooltipId = `kt-tooltip-${this.uid}`;\n /** Id du noeud `role=\"tooltip\"`. Public : sert aux liaisons d'accessibilité (`aria-describedby`) du déclencheur. */\n readonly idForA11y = this.tooltipId;\n private readonly anchorName = `--kt-tooltip-anchor-${this.uid}`;\n\n /** Vrai quand l'infobulle est susceptible de s'afficher (contenu non vide et non désactivée).\n Public : lu par `KtField` pour câbler `aria-describedby` du contrôle sur l'infobulle d'aide. */\n readonly isActive = computed(() => {\n if (this.tooltipDisabled()) return false;\n\n const content = this.ktTooltip();\n if (typeof content === 'string') return content.trim().length > 0;\n return true;\n });\n\n // Retourner null retire l'attribut (même astuce que aria-disabled dans button).\n // Corrigé : aria-describedby n'est présent sur le déclencheur que si le tooltip est affiché.\n protected describedById = computed(() => (this.isActive() && this.isShown() ? this.tooltipId : null));\n\n private tip: HTMLElement | null = null;\n private view: EmbeddedViewRef<unknown> | null = null;\n private listeners: (() => void)[] = [];\n private showTimer: ReturnType<typeof setTimeout> | undefined;\n private hideTimer: ReturnType<typeof setTimeout> | undefined;\n private readonly isShown = signal(false);\n private _supportsAnchor: boolean | null = null;\n private get supportsAnchor(): boolean {\n if (this._supportsAnchor === null) {\n this._supportsAnchor =\n isPlatformBrowser(this.platformId) &&\n typeof CSS !== 'undefined' &&\n typeof CSS.supports === 'function' &&\n CSS.supports('anchor-name: --x');\n }\n return this._supportsAnchor;\n }\n private fallbackListeners: (() => void)[] = [];\n private activeTemplate: TemplateRef<unknown> | null = null;\n private escListener: (() => void) | null = null;\n\n constructor() {\n // Ancre le déclencheur. setProperty (et non Renderer2.setStyle) car les propriétés\n // CSS à tiret ne sont appliquées qu'ainsi de façon fiable.\n if (isPlatformBrowser(this.platformId)) {\n this.host.nativeElement.style.setProperty('anchor-name', this.anchorName);\n }\n\n // Gestion réactive du cycle de vie du DOM du Tooltip\n effect(() => {\n if (!isPlatformBrowser(this.platformId)) return;\n\n // Création lazy : uniquement si actif ET affiché\n if (!this.isActive() || !this.isShown()) {\n this.destroyTip();\n return;\n }\n\n const tip = this.ensureTip();\n this.registerEscapeListener();\n this.syncContent();\n\n try {\n tip.showPopover?.();\n } catch {\n // Ignorer si déjà ouvert ou non supporté\n }\n\n if (!this.supportsAnchor) {\n this.positionFallback();\n }\n });\n }\n\n ngOnDestroy(): void {\n this.destroyTip();\n }\n\n protected show(): void {\n if (!this.isActive()) return;\n\n this.ngZone.runOutsideAngular(() => {\n clearTimeout(this.hideTimer);\n this.showTimer = setTimeout(() => {\n this.ngZone.run(() => {\n if (this.isShown()) return;\n\n this.isShown.set(true);\n\n if (!this.supportsAnchor) {\n this.registerFallbackListeners();\n }\n });\n }, this.showDelay());\n });\n }\n\n protected hide(): void {\n this.ngZone.runOutsideAngular(() => {\n clearTimeout(this.showTimer);\n this.hideTimer = setTimeout(() => {\n this.ngZone.run(() => this.dismiss());\n }, this.hideDelay());\n });\n }\n\n protected onEscape(event: Event): void {\n if (!this.isShown()) return;\n\n // Dismiss sans déplacer le pointeur (WCAG 1.4.13) ; on n'annule pas l'action native.\n this.dismiss();\n event.stopPropagation();\n }\n\n private dismiss(): void {\n if (!this.isShown()) return;\n\n this.isShown.set(false);\n }\n\n private ensureTip(): HTMLElement {\n if (this.tip) return this.tip;\n\n const tip = this.renderer.createElement('div') as HTMLElement;\n this.renderer.setAttribute(tip, 'role', 'tooltip');\n this.renderer.setAttribute(tip, 'id', this.tooltipId);\n // manual : on gère nous-mêmes Échap et la fermeture au survol/blur.\n this.renderer.setAttribute(tip, 'popover', 'manual');\n this.renderer.addClass(tip, 'kt-tooltip');\n // setProperty natif : indispensable pour une propriété CSS à tiret.\n tip.style.setProperty('position-anchor', this.anchorName);\n // Top-layer : ajouté au body, immunisé contre overflow/z-index.\n this.renderer.appendChild(this.doc.body, tip);\n\n // Hoverable : passer le pointeur du trigger au tooltip ne le ferme pas.\n this.listeners.push(\n this.renderer.listen(tip, 'mouseenter', () => clearTimeout(this.hideTimer)),\n this.renderer.listen(tip, 'mouseleave', () => this.hide()),\n );\n\n this.tip = tip;\n return tip;\n }\n\n private registerEscapeListener(): void {\n if (this.escListener) return;\n this.escListener = this.renderer.listen('document', 'keydown.escape', (event: KeyboardEvent) => {\n if (this.isShown()) {\n this.dismiss();\n event.stopPropagation();\n }\n });\n }\n\n private syncContent(): void {\n if (!this.tip) return;\n\n this.renderer.setAttribute(this.tip, 'data-position', this.tooltipPosition());\n\n const content = this.ktTooltip();\n\n if (content instanceof TemplateRef) {\n if (this.activeTemplate === content) return;\n this.clearContent();\n this.activeTemplate = content;\n\n this.view = this.vcr.createEmbeddedView(content);\n this.view.detectChanges();\n for (const node of this.view.rootNodes) {\n this.renderer.appendChild(this.tip, node);\n }\n if (isDevMode()) {\n this.warnIfInteractive();\n }\n return;\n }\n\n this.clearContent();\n this.renderer.setProperty(this.tip, 'textContent', content);\n }\n\n private clearContent(): void {\n if (this.view) {\n this.view.destroy();\n this.view = null;\n }\n this.activeTemplate = null;\n if (this.tip) {\n this.renderer.setProperty(this.tip, 'textContent', '');\n }\n }\n\n // Garde-fou a11y : un role=\"tooltip\" ne doit pas contenir d'éléments focusables.\n private warnIfInteractive(): void {\n if (!this.tip) return;\n\n const interactive = this.tip.querySelector('a[href], button, input, select, textarea, [tabindex]');\n if (!interactive) return;\n\n console.warn(\n `[ktTooltip] Un role=\"tooltip\" ne doit pas contenir d'éléments interactifs ` +\n `(<${interactive.nodeName.toLowerCase()}>). Utilisez plutôt un toggletip ou un <dialog>.`,\n );\n }\n\n private destroyTip(): void {\n clearTimeout(this.showTimer);\n clearTimeout(this.hideTimer);\n\n for (const unlisten of this.listeners) unlisten();\n this.listeners = [];\n this.clearFallbackListeners();\n\n if (this.escListener) {\n this.escListener();\n this.escListener = null;\n }\n\n this.view?.destroy();\n this.view = null;\n this.activeTemplate = null;\n\n if (this.tip) {\n try {\n this.tip.hidePopover?.();\n } catch {\n // Ignorer si déjà fermé ou non supporté\n }\n this.tip.remove();\n this.tip = null;\n }\n\n if (this.isShown()) {\n this.isShown.set(false);\n }\n }\n\n private positionFallback(): void {\n if (!this.tip) return;\n const triggerEl = this.host.nativeElement;\n const triggerRect = triggerEl.getBoundingClientRect();\n const tooltipRect = this.tip.getBoundingClientRect();\n const position = this.tooltipPosition();\n const gap = 8;\n\n let top = 0;\n let left = 0;\n\n if (position === 'top') {\n top = triggerRect.top - tooltipRect.height - gap;\n left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;\n } else if (position === 'bottom') {\n top = triggerRect.bottom + gap;\n left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;\n } else if (position === 'left') {\n top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;\n left = triggerRect.left - tooltipRect.width - gap;\n } else if (position === 'right') {\n top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;\n left = triggerRect.right + gap;\n }\n\n const viewWidth = window.innerWidth;\n const viewHeight = window.innerHeight;\n\n if (left < 4) left = 4;\n if (left + tooltipRect.width > viewWidth - 4) {\n left = viewWidth - tooltipRect.width - 4;\n }\n if (top < 4) {\n if (position === 'top') {\n top = triggerRect.bottom + gap;\n } else {\n top = 4;\n }\n }\n if (top + tooltipRect.height > viewHeight - 4) {\n if (position === 'bottom') {\n top = triggerRect.top - tooltipRect.height - gap;\n } else {\n top = viewHeight - tooltipRect.height - 4;\n }\n }\n\n this.tip.style.position = 'fixed';\n this.tip.style.top = `${top}px`;\n this.tip.style.left = `${left}px`;\n this.tip.style.margin = '0';\n }\n\n private registerFallbackListeners(): void {\n this.clearFallbackListeners();\n if (this.supportsAnchor || !isPlatformBrowser(this.platformId)) return;\n\n this.ngZone.runOutsideAngular(() => {\n const onScrollOrResize = () => {\n this.positionFallback();\n };\n window.addEventListener('scroll', onScrollOrResize, { passive: true, capture: true });\n window.addEventListener('resize', onScrollOrResize);\n\n this.fallbackListeners.push(\n () => window.removeEventListener('scroll', onScrollOrResize, { capture: true }),\n () => window.removeEventListener('resize', onScrollOrResize),\n );\n });\n }\n\n private clearFallbackListeners(): void {\n for (const remove of this.fallbackListeners) remove();\n this.fallbackListeners = [];\n }\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-tooltip.mjs","sources":["../../../../projects/ktortu/aaa/tooltip/tooltip.ts","../../../../projects/ktortu/aaa/tooltip/ktortu-aaa-tooltip.ts"],"sourcesContent":["import { DOCUMENT, isPlatformBrowser } from '@angular/common';\nimport {\n Directive,\n ElementRef,\n EmbeddedViewRef,\n InjectionToken,\n OnDestroy,\n Provider,\n Renderer2,\n TemplateRef,\n ViewContainerRef,\n booleanAttribute,\n computed,\n effect,\n inject,\n input,\n isDevMode,\n signal,\n PLATFORM_ID,\n} from '@angular/core';\nimport { KtIdGenerator } from '@ktortu/aaa/cdk';\n\nexport type KtTooltipPosition = 'top' | 'bottom' | 'left' | 'right';\n\n/** Défauts d'infobulle (délais, position) injectables via `provideKtTooltip` / `KT_TOOLTIP_CONFIG`. */\nexport interface KtTooltipConfig {\n /** Délai (ms) avant apparition au survol/focus. */\n showDelay: number;\n /** Délai (ms) avant masquage (laisse le temps d'atteindre l'infobulle, WCAG « hoverable »). */\n hideDelay: number;\n /** Position de l'infobulle autour de la cible. */\n position: KtTooltipPosition;\n}\n\nexport const KT_TOOLTIP_CONFIG = new InjectionToken<Partial<KtTooltipConfig>>('KT_TOOLTIP_CONFIG');\n\n/**\n * Fournit des défauts d'infobulle (délais, position) pour un sous-arbre ou l'application entière.\n *\n * @example\n * ```ts\n * providers: [provideKtTooltip({ showDelay: 300, position: 'bottom' })]\n * ```\n */\nexport function provideKtTooltip(config: Partial<KtTooltipConfig>): Provider {\n return { provide: KT_TOOLTIP_CONFIG, useValue: config };\n}\n\n/**\n * Infobulle accessible posée sur n'importe quel élément focusable/survolable.\n * Apparaît au survol et au focus, reste « hoverable » (WCAG 1.4.13) et se ferme\n * par Échap. Le contenu peut être un texte simple ou un `TemplateRef` **non interactif**\n * (un `role=\"tooltip\"` ne doit pas contenir de lien/bouton/champ).\n *\n * @example\n * ```html\n * <button ktTooltip=\"Enregistrer le brouillon\">Enregistrer</button>\n * <span ktTooltip=\"Aide\" tooltipPosition=\"right\" [showDelay]=\"300\">?</span>\n * ```\n */\n@Directive({\n selector: '[ktTooltip]',\n host: {\n '[attr.aria-describedby]': 'describedById()',\n '(mouseenter)': 'show()',\n '(mouseleave)': 'hide()',\n '(focusin)': 'show()',\n '(focusout)': 'hide()',\n '(keydown.escape)': 'onEscape($event)',\n },\n})\nexport class KtTooltip implements OnDestroy {\n private readonly config = inject(KT_TOOLTIP_CONFIG, { optional: true });\n private readonly doc = inject(DOCUMENT);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly renderer = inject(Renderer2);\n private readonly vcr = inject(ViewContainerRef);\n private readonly platformId = inject(PLATFORM_ID);\n\n /** Contenu de l'infobulle : texte simple (injecté en `textContent`) ou `TemplateRef` non interactif. */\n readonly ktTooltip = input.required<string | TemplateRef<unknown>>();\n /** Position de l'infobulle autour de la cible. @default 'top' (ou KT_TOOLTIP_CONFIG.position) */\n readonly tooltipPosition = input<KtTooltipPosition>(this.config?.position ?? 'top');\n /** Désactive l'affichage de l'infobulle. @default false */\n readonly tooltipDisabled = input<boolean, unknown>(false, { transform: booleanAttribute });\n /** Délai (ms) avant apparition au survol/focus. @default 150 (ou KT_TOOLTIP_CONFIG.showDelay) */\n readonly showDelay = input<number>(this.config?.showDelay ?? 150);\n /** Délai (ms) avant masquage ; laisse le temps d'amener le pointeur sur l'infobulle (WCAG « hoverable »). @default 100 (ou KT_TOOLTIP_CONFIG.hideDelay) */\n readonly hideDelay = input<number>(this.config?.hideDelay ?? 100);\n\n private readonly idGen = inject(KtIdGenerator);\n private readonly uid = this.idGen.generateId('tooltip');\n private readonly tooltipId = `kt-tooltip-${this.uid}`;\n /** Id du noeud `role=\"tooltip\"`. Public : sert aux liaisons d'accessibilité (`aria-describedby`) du déclencheur. */\n readonly idForA11y = this.tooltipId;\n private readonly anchorName = `--kt-tooltip-anchor-${this.uid}`;\n\n /** Vrai quand l'infobulle est susceptible de s'afficher (contenu non vide et non désactivée).\n Public : lu par `KtField` pour câbler `aria-describedby` du contrôle sur l'infobulle d'aide. */\n readonly isActive = computed(() => {\n if (this.tooltipDisabled()) return false;\n\n const content = this.ktTooltip();\n if (typeof content === 'string') return content.trim().length > 0;\n return true;\n });\n\n // Retourner null retire l'attribut (même astuce que aria-disabled dans button).\n // aria-describedby n'est posé sur le déclencheur que lorsque le tooltip est affiché : sinon il\n // référencerait un nœud absent du DOM (création lazy), donnant une référence pendante aux AT.\n protected describedById = computed(() => (this.isActive() && this.isShown() ? this.tooltipId : null));\n\n private tip: HTMLElement | null = null;\n private view: EmbeddedViewRef<unknown> | null = null;\n private listeners: (() => void)[] = [];\n private showTimer: ReturnType<typeof setTimeout> | undefined;\n private hideTimer: ReturnType<typeof setTimeout> | undefined;\n private readonly isShown = signal(false);\n private _supportsAnchor: boolean | null = null;\n private get supportsAnchor(): boolean {\n if (this._supportsAnchor === null) {\n this._supportsAnchor =\n isPlatformBrowser(this.platformId) &&\n typeof CSS !== 'undefined' &&\n typeof CSS.supports === 'function' &&\n CSS.supports('anchor-name: --x');\n }\n return this._supportsAnchor;\n }\n private fallbackListeners: (() => void)[] = [];\n private activeTemplate: TemplateRef<unknown> | null = null;\n private escListener: (() => void) | null = null;\n\n constructor() {\n // Ancre le déclencheur. setProperty (et non Renderer2.setStyle) car les propriétés\n // CSS à tiret ne sont appliquées qu'ainsi de façon fiable.\n if (isPlatformBrowser(this.platformId)) {\n this.host.nativeElement.style.setProperty('anchor-name', this.anchorName);\n }\n\n // Gestion réactive du cycle de vie du DOM du Tooltip\n effect(() => {\n if (!isPlatformBrowser(this.platformId)) return;\n\n // Création lazy : uniquement si actif ET affiché\n if (!this.isActive() || !this.isShown()) {\n this.destroyTip();\n return;\n }\n\n const tip = this.ensureTip();\n this.registerEscapeListener();\n this.syncContent();\n\n try {\n tip.showPopover?.();\n } catch {\n // Ignorer si déjà ouvert ou non supporté\n }\n\n if (!this.supportsAnchor) {\n this.positionFallback();\n }\n });\n }\n\n ngOnDestroy(): void {\n this.destroyTip();\n }\n\n protected show(): void {\n if (!this.isActive()) return;\n\n clearTimeout(this.hideTimer);\n this.showTimer = setTimeout(() => {\n if (this.isShown()) return;\n\n this.isShown.set(true);\n\n if (!this.supportsAnchor) {\n this.registerFallbackListeners();\n }\n }, this.showDelay());\n }\n\n protected hide(): void {\n clearTimeout(this.showTimer);\n this.hideTimer = setTimeout(() => this.dismiss(), this.hideDelay());\n }\n\n protected onEscape(event: Event): void {\n if (!this.isShown()) return;\n\n // Dismiss sans déplacer le pointeur (WCAG 1.4.13) ; on n'annule pas l'action native.\n this.dismiss();\n event.stopPropagation();\n }\n\n private dismiss(): void {\n if (!this.isShown()) return;\n\n this.isShown.set(false);\n }\n\n private ensureTip(): HTMLElement {\n if (this.tip) return this.tip;\n\n const tip = this.renderer.createElement('div') as HTMLElement;\n this.renderer.setAttribute(tip, 'role', 'tooltip');\n this.renderer.setAttribute(tip, 'id', this.tooltipId);\n // manual : on gère nous-mêmes Échap et la fermeture au survol/blur.\n this.renderer.setAttribute(tip, 'popover', 'manual');\n this.renderer.addClass(tip, 'kt-tooltip');\n // setProperty natif : indispensable pour une propriété CSS à tiret.\n tip.style.setProperty('position-anchor', this.anchorName);\n // Top-layer : ajouté au body, immunisé contre overflow/z-index.\n this.renderer.appendChild(this.doc.body, tip);\n\n // Hoverable : passer le pointeur du trigger au tooltip ne le ferme pas.\n this.listeners.push(\n this.renderer.listen(tip, 'mouseenter', () => clearTimeout(this.hideTimer)),\n this.renderer.listen(tip, 'mouseleave', () => this.hide()),\n );\n\n this.tip = tip;\n return tip;\n }\n\n private registerEscapeListener(): void {\n if (this.escListener) return;\n this.escListener = this.renderer.listen('document', 'keydown.escape', (event: KeyboardEvent) => {\n if (this.isShown()) {\n this.dismiss();\n event.stopPropagation();\n }\n });\n }\n\n private syncContent(): void {\n if (!this.tip) return;\n\n this.renderer.setAttribute(this.tip, 'data-position', this.tooltipPosition());\n\n const content = this.ktTooltip();\n\n if (content instanceof TemplateRef) {\n if (this.activeTemplate === content) return;\n this.clearContent();\n this.activeTemplate = content;\n\n this.view = this.vcr.createEmbeddedView(content);\n this.view.detectChanges();\n for (const node of this.view.rootNodes) {\n this.renderer.appendChild(this.tip, node);\n }\n if (isDevMode()) {\n this.warnIfInteractive();\n }\n return;\n }\n\n this.clearContent();\n this.renderer.setProperty(this.tip, 'textContent', content);\n }\n\n private clearContent(): void {\n if (this.view) {\n this.view.destroy();\n this.view = null;\n }\n this.activeTemplate = null;\n if (this.tip) {\n this.renderer.setProperty(this.tip, 'textContent', '');\n }\n }\n\n // Garde-fou a11y : un role=\"tooltip\" ne doit pas contenir d'éléments focusables.\n private warnIfInteractive(): void {\n if (!this.tip) return;\n\n const interactive = this.tip.querySelector('a[href], button, input, select, textarea, [tabindex]');\n if (!interactive) return;\n\n console.warn(\n `[ktTooltip] Un role=\"tooltip\" ne doit pas contenir d'éléments interactifs ` +\n `(<${interactive.nodeName.toLowerCase()}>). Utilisez plutôt un toggletip ou un <dialog>.`,\n );\n }\n\n private destroyTip(): void {\n clearTimeout(this.showTimer);\n clearTimeout(this.hideTimer);\n\n for (const unlisten of this.listeners) unlisten();\n this.listeners = [];\n this.clearFallbackListeners();\n\n if (this.escListener) {\n this.escListener();\n this.escListener = null;\n }\n\n this.view?.destroy();\n this.view = null;\n this.activeTemplate = null;\n\n if (this.tip) {\n try {\n this.tip.hidePopover?.();\n } catch {\n // Ignorer si déjà fermé ou non supporté\n }\n this.tip.remove();\n this.tip = null;\n }\n\n if (this.isShown()) {\n this.isShown.set(false);\n }\n }\n\n private positionFallback(): void {\n if (!this.tip) return;\n const triggerEl = this.host.nativeElement;\n const triggerRect = triggerEl.getBoundingClientRect();\n const tooltipRect = this.tip.getBoundingClientRect();\n const position = this.tooltipPosition();\n const gap = 8;\n\n let top = 0;\n let left = 0;\n\n if (position === 'top') {\n top = triggerRect.top - tooltipRect.height - gap;\n left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;\n } else if (position === 'bottom') {\n top = triggerRect.bottom + gap;\n left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;\n } else if (position === 'left') {\n top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;\n left = triggerRect.left - tooltipRect.width - gap;\n } else if (position === 'right') {\n top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;\n left = triggerRect.right + gap;\n }\n\n const viewWidth = window.innerWidth;\n const viewHeight = window.innerHeight;\n\n if (left < 4) left = 4;\n if (left + tooltipRect.width > viewWidth - 4) {\n left = viewWidth - tooltipRect.width - 4;\n }\n if (top < 4) {\n if (position === 'top') {\n top = triggerRect.bottom + gap;\n } else {\n top = 4;\n }\n }\n if (top + tooltipRect.height > viewHeight - 4) {\n if (position === 'bottom') {\n top = triggerRect.top - tooltipRect.height - gap;\n } else {\n top = viewHeight - tooltipRect.height - 4;\n }\n }\n\n this.tip.style.position = 'fixed';\n this.tip.style.top = `${top}px`;\n this.tip.style.left = `${left}px`;\n this.tip.style.margin = '0';\n }\n\n private registerFallbackListeners(): void {\n this.clearFallbackListeners();\n if (this.supportsAnchor || !isPlatformBrowser(this.platformId)) return;\n\n const onScrollOrResize = () => {\n this.positionFallback();\n };\n window.addEventListener('scroll', onScrollOrResize, { passive: true, capture: true });\n window.addEventListener('resize', onScrollOrResize);\n\n this.fallbackListeners.push(\n () => window.removeEventListener('scroll', onScrollOrResize, { capture: true }),\n () => window.removeEventListener('resize', onScrollOrResize),\n );\n }\n\n private clearFallbackListeners(): void {\n for (const remove of this.fallbackListeners) remove();\n this.fallbackListeners = [];\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;MAkCa,iBAAiB,GAAG,IAAI,cAAc,CAA2B,mBAAmB;AAEjG;;;;;;;AAOG;AACG,SAAU,gBAAgB,CAAC,MAAgC,EAAA;IAC/D,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,EAAE;AACzD;AAEA;;;;;;;;;;;AAWG;MAYU,SAAS,CAAA;IACH,MAAM,GAAG,MAAM,CAAC,iBAAiB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACtD,IAAA,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;AACtB,IAAA,IAAI,GAAG,MAAM,CAA0B,UAAU,CAAC;AAClD,IAAA,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC;AAC5B,IAAA,GAAG,GAAG,MAAM,CAAC,gBAAgB,CAAC;AAC9B,IAAA,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC;;IAGxC,SAAS,GAAG,KAAK,CAAC,QAAQ;kFAAiC;;IAE3D,eAAe,GAAG,KAAK,CAAoB,IAAI,CAAC,MAAM,EAAE,QAAQ,IAAI,KAAK;wFAAC;;IAE1E,eAAe,GAAG,KAAK,CAAmB,KAAK,uFAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;;IAEjF,SAAS,GAAG,KAAK,CAAS,IAAI,CAAC,MAAM,EAAE,SAAS,IAAI,GAAG;kFAAC;;IAExD,SAAS,GAAG,KAAK,CAAS,IAAI,CAAC,MAAM,EAAE,SAAS,IAAI,GAAG;kFAAC;AAEhD,IAAA,KAAK,GAAG,MAAM,CAAC,aAAa,CAAC;IAC7B,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC;AACtC,IAAA,SAAS,GAAG,CAAA,WAAA,EAAc,IAAI,CAAC,GAAG,EAAE;;AAE5C,IAAA,SAAS,GAAG,IAAI,CAAC,SAAS;AAClB,IAAA,UAAU,GAAG,CAAA,oBAAA,EAAuB,IAAI,CAAC,GAAG,EAAE;AAE/D;AACmG;AAC1F,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAK;QAChC,IAAI,IAAI,CAAC,eAAe,EAAE;AAAE,YAAA,OAAO,KAAK;AAExC,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE;QAChC,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;AACjE,QAAA,OAAO,IAAI;IACb,CAAC;iFAAC;;;;IAKQ,aAAa,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,QAAQ,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;sFAAC;IAE7F,GAAG,GAAuB,IAAI;IAC9B,IAAI,GAAoC,IAAI;IAC5C,SAAS,GAAmB,EAAE;AAC9B,IAAA,SAAS;AACT,IAAA,SAAS;IACA,OAAO,GAAG,MAAM,CAAC,KAAK;gFAAC;IAChC,eAAe,GAAmB,IAAI;AAC9C,IAAA,IAAY,cAAc,GAAA;AACxB,QAAA,IAAI,IAAI,CAAC,eAAe,KAAK,IAAI,EAAE;AACjC,YAAA,IAAI,CAAC,eAAe;AAClB,gBAAA,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC;oBAClC,OAAO,GAAG,KAAK,WAAW;AAC1B,oBAAA,OAAO,GAAG,CAAC,QAAQ,KAAK,UAAU;AAClC,oBAAA,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC;QACpC;QACA,OAAO,IAAI,CAAC,eAAe;IAC7B;IACQ,iBAAiB,GAAmB,EAAE;IACtC,cAAc,GAAgC,IAAI;IAClD,WAAW,GAAwB,IAAI;AAE/C,IAAA,WAAA,GAAA;;;AAGE,QAAA,IAAI,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;AACtC,YAAA,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,WAAW,CAAC,aAAa,EAAE,IAAI,CAAC,UAAU,CAAC;QAC3E;;QAGA,MAAM,CAAC,MAAK;AACV,YAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC;gBAAE;;AAGzC,YAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE;gBACvC,IAAI,CAAC,UAAU,EAAE;gBACjB;YACF;AAEA,YAAA,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE;YAC5B,IAAI,CAAC,sBAAsB,EAAE;YAC7B,IAAI,CAAC,WAAW,EAAE;AAElB,YAAA,IAAI;AACF,gBAAA,GAAG,CAAC,WAAW,IAAI;YACrB;AAAE,YAAA,MAAM;;YAER;AAEA,YAAA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;gBACxB,IAAI,CAAC,gBAAgB,EAAE;YACzB;AACF,QAAA,CAAC,CAAC;IACJ;IAEA,WAAW,GAAA;QACT,IAAI,CAAC,UAAU,EAAE;IACnB;IAEU,IAAI,GAAA;AACZ,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAAE;AAEtB,QAAA,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;AAC5B,QAAA,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,MAAK;YAC/B,IAAI,IAAI,CAAC,OAAO,EAAE;gBAAE;AAEpB,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;AAEtB,YAAA,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE;gBACxB,IAAI,CAAC,yBAAyB,EAAE;YAClC;AACF,QAAA,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;IACtB;IAEU,IAAI,GAAA;AACZ,QAAA,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;AAC5B,QAAA,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;IACrE;AAEU,IAAA,QAAQ,CAAC,KAAY,EAAA;AAC7B,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YAAE;;QAGrB,IAAI,CAAC,OAAO,EAAE;QACd,KAAK,CAAC,eAAe,EAAE;IACzB;IAEQ,OAAO,GAAA;AACb,QAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YAAE;AAErB,QAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;IACzB;IAEQ,SAAS,GAAA;QACf,IAAI,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC,GAAG;QAE7B,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAgB;QAC7D,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC;AAClD,QAAA,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;;QAErD,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC;QACpD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,YAAY,CAAC;;QAEzC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,iBAAiB,EAAE,IAAI,CAAC,UAAU,CAAC;;AAEzD,QAAA,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC;;QAG7C,IAAI,CAAC,SAAS,CAAC,IAAI,CACjB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAC3E,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAC3D;AAED,QAAA,IAAI,CAAC,GAAG,GAAG,GAAG;AACd,QAAA,OAAO,GAAG;IACZ;IAEQ,sBAAsB,GAAA;QAC5B,IAAI,IAAI,CAAC,WAAW;YAAE;AACtB,QAAA,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,gBAAgB,EAAE,CAAC,KAAoB,KAAI;AAC7F,YAAA,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE;gBAClB,IAAI,CAAC,OAAO,EAAE;gBACd,KAAK,CAAC,eAAe,EAAE;YACzB;AACF,QAAA,CAAC,CAAC;IACJ;IAEQ,WAAW,GAAA;QACjB,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE;AAEf,QAAA,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC;AAE7E,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE;AAEhC,QAAA,IAAI,OAAO,YAAY,WAAW,EAAE;AAClC,YAAA,IAAI,IAAI,CAAC,cAAc,KAAK,OAAO;gBAAE;YACrC,IAAI,CAAC,YAAY,EAAE;AACnB,YAAA,IAAI,CAAC,cAAc,GAAG,OAAO;YAE7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,OAAO,CAAC;AAChD,YAAA,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;YACzB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;gBACtC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC;YAC3C;YACA,IAAI,SAAS,EAAE,EAAE;gBACf,IAAI,CAAC,iBAAiB,EAAE;YAC1B;YACA;QACF;QAEA,IAAI,CAAC,YAAY,EAAE;AACnB,QAAA,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,CAAC;IAC7D;IAEQ,YAAY,GAAA;AAClB,QAAA,IAAI,IAAI,CAAC,IAAI,EAAE;AACb,YAAA,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;AACnB,YAAA,IAAI,CAAC,IAAI,GAAG,IAAI;QAClB;AACA,QAAA,IAAI,CAAC,cAAc,GAAG,IAAI;AAC1B,QAAA,IAAI,IAAI,CAAC,GAAG,EAAE;AACZ,YAAA,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,EAAE,CAAC;QACxD;IACF;;IAGQ,iBAAiB,GAAA;QACvB,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE;QAEf,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,sDAAsD,CAAC;AAClG,QAAA,IAAI,CAAC,WAAW;YAAE;QAElB,OAAO,CAAC,IAAI,CACV,CAAA,0EAAA,CAA4E;YAC1E,CAAA,EAAA,EAAK,WAAW,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAA,gDAAA,CAAkD,CAC5F;IACH;IAEQ,UAAU,GAAA;AAChB,QAAA,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;AAC5B,QAAA,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC;AAE5B,QAAA,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS;AAAE,YAAA,QAAQ,EAAE;AACjD,QAAA,IAAI,CAAC,SAAS,GAAG,EAAE;QACnB,IAAI,CAAC,sBAAsB,EAAE;AAE7B,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE;YACpB,IAAI,CAAC,WAAW,EAAE;AAClB,YAAA,IAAI,CAAC,WAAW,GAAG,IAAI;QACzB;AAEA,QAAA,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE;AACpB,QAAA,IAAI,CAAC,IAAI,GAAG,IAAI;AAChB,QAAA,IAAI,CAAC,cAAc,GAAG,IAAI;AAE1B,QAAA,IAAI,IAAI,CAAC,GAAG,EAAE;AACZ,YAAA,IAAI;AACF,gBAAA,IAAI,CAAC,GAAG,CAAC,WAAW,IAAI;YAC1B;AAAE,YAAA,MAAM;;YAER;AACA,YAAA,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE;AACjB,YAAA,IAAI,CAAC,GAAG,GAAG,IAAI;QACjB;AAEA,QAAA,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE;AAClB,YAAA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;QACzB;IACF;IAEQ,gBAAgB,GAAA;QACtB,IAAI,CAAC,IAAI,CAAC,GAAG;YAAE;AACf,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa;AACzC,QAAA,MAAM,WAAW,GAAG,SAAS,CAAC,qBAAqB,EAAE;QACrD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE;AACpD,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,EAAE;QACvC,MAAM,GAAG,GAAG,CAAC;QAEb,IAAI,GAAG,GAAG,CAAC;QACX,IAAI,IAAI,GAAG,CAAC;AAEZ,QAAA,IAAI,QAAQ,KAAK,KAAK,EAAE;YACtB,GAAG,GAAG,WAAW,CAAC,GAAG,GAAG,WAAW,CAAC,MAAM,GAAG,GAAG;AAChD,YAAA,IAAI,GAAG,WAAW,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC,KAAK,GAAG,WAAW,CAAC,KAAK,IAAI,CAAC;QACvE;AAAO,aAAA,IAAI,QAAQ,KAAK,QAAQ,EAAE;AAChC,YAAA,GAAG,GAAG,WAAW,CAAC,MAAM,GAAG,GAAG;AAC9B,YAAA,IAAI,GAAG,WAAW,CAAC,IAAI,GAAG,CAAC,WAAW,CAAC,KAAK,GAAG,WAAW,CAAC,KAAK,IAAI,CAAC;QACvE;AAAO,aAAA,IAAI,QAAQ,KAAK,MAAM,EAAE;AAC9B,YAAA,GAAG,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,IAAI,CAAC;YACrE,IAAI,GAAG,WAAW,CAAC,IAAI,GAAG,WAAW,CAAC,KAAK,GAAG,GAAG;QACnD;AAAO,aAAA,IAAI,QAAQ,KAAK,OAAO,EAAE;AAC/B,YAAA,GAAG,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,IAAI,CAAC;AACrE,YAAA,IAAI,GAAG,WAAW,CAAC,KAAK,GAAG,GAAG;QAChC;AAEA,QAAA,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU;AACnC,QAAA,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW;QAErC,IAAI,IAAI,GAAG,CAAC;YAAE,IAAI,GAAG,CAAC;QACtB,IAAI,IAAI,GAAG,WAAW,CAAC,KAAK,GAAG,SAAS,GAAG,CAAC,EAAE;YAC5C,IAAI,GAAG,SAAS,GAAG,WAAW,CAAC,KAAK,GAAG,CAAC;QAC1C;AACA,QAAA,IAAI,GAAG,GAAG,CAAC,EAAE;AACX,YAAA,IAAI,QAAQ,KAAK,KAAK,EAAE;AACtB,gBAAA,GAAG,GAAG,WAAW,CAAC,MAAM,GAAG,GAAG;YAChC;iBAAO;gBACL,GAAG,GAAG,CAAC;YACT;QACF;QACA,IAAI,GAAG,GAAG,WAAW,CAAC,MAAM,GAAG,UAAU,GAAG,CAAC,EAAE;AAC7C,YAAA,IAAI,QAAQ,KAAK,QAAQ,EAAE;gBACzB,GAAG,GAAG,WAAW,CAAC,GAAG,GAAG,WAAW,CAAC,MAAM,GAAG,GAAG;YAClD;iBAAO;gBACL,GAAG,GAAG,UAAU,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC;YAC3C;QACF;QAEA,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO;QACjC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,CAAA,EAAG,GAAG,CAAA,EAAA,CAAI;QAC/B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAA,EAAG,IAAI,CAAA,EAAA,CAAI;QACjC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG;IAC7B;IAEQ,yBAAyB,GAAA;QAC/B,IAAI,CAAC,sBAAsB,EAAE;QAC7B,IAAI,IAAI,CAAC,cAAc,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE;QAEhE,MAAM,gBAAgB,GAAG,MAAK;YAC5B,IAAI,CAAC,gBAAgB,EAAE;AACzB,QAAA,CAAC;AACD,QAAA,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AACrF,QAAA,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,CAAC;AAEnD,QAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CACzB,MAAM,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAC/E,MAAM,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAC7D;IACH;IAEQ,sBAAsB,GAAA;AAC5B,QAAA,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,iBAAiB;AAAE,YAAA,MAAM,EAAE;AACrD,QAAA,IAAI,CAAC,iBAAiB,GAAG,EAAE;IAC7B;uGAlUW,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAT,SAAS,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,iBAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,SAAA,EAAA,EAAA,YAAA,EAAA,QAAA,EAAA,YAAA,EAAA,QAAA,EAAA,SAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,kBAAA,EAAA,EAAA,UAAA,EAAA,EAAA,uBAAA,EAAA,iBAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAT,SAAS,EAAA,UAAA,EAAA,CAAA;kBAXrB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,aAAa;AACvB,oBAAA,IAAI,EAAE;AACJ,wBAAA,yBAAyB,EAAE,iBAAiB;AAC5C,wBAAA,cAAc,EAAE,QAAQ;AACxB,wBAAA,cAAc,EAAE,QAAQ;AACxB,wBAAA,WAAW,EAAE,QAAQ;AACrB,wBAAA,YAAY,EAAE,QAAQ;AACtB,wBAAA,kBAAkB,EAAE,kBAAkB;AACvC,qBAAA;AACF,iBAAA;;;ACtED;;AAEG;;;;"}
|
package/fesm2022/ktortu-aaa.mjs
CHANGED
|
@@ -5,8 +5,10 @@ export * from '@ktortu/aaa/dialog';
|
|
|
5
5
|
export * from '@ktortu/aaa/forms';
|
|
6
6
|
export * from '@ktortu/aaa/i18n';
|
|
7
7
|
export * from '@ktortu/aaa/menu';
|
|
8
|
+
export * from '@ktortu/aaa/snackbar';
|
|
8
9
|
export * from '@ktortu/aaa/tabs';
|
|
9
10
|
export * from '@ktortu/aaa/tooltip';
|
|
11
|
+
export * from '@ktortu/aaa/progress-bar';
|
|
10
12
|
|
|
11
13
|
/*
|
|
12
14
|
* Public API Surface of @ktortu/aaa
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ktortu-aaa.mjs","sources":["../../../../projects/ktortu/aaa/src/public-api.ts","../../../../projects/ktortu/aaa/src/ktortu-aaa.ts"],"sourcesContent":["/*\n * Public API Surface of @ktortu/aaa\n */\nexport * from '@ktortu/aaa/button';\nexport * from '@ktortu/aaa/card';\nexport * from '@ktortu/aaa/cdk';\nexport * from '@ktortu/aaa/dialog';\nexport * from '@ktortu/aaa/forms';\nexport * from '@ktortu/aaa/i18n';\nexport * from '@ktortu/aaa/menu';\nexport * from '@ktortu/aaa/tabs';\nexport * from '@ktortu/aaa/tooltip';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ktortu-aaa.mjs","sources":["../../../../projects/ktortu/aaa/src/public-api.ts","../../../../projects/ktortu/aaa/src/ktortu-aaa.ts"],"sourcesContent":["/*\n * Public API Surface of @ktortu/aaa\n */\nexport * from '@ktortu/aaa/button';\nexport * from '@ktortu/aaa/card';\nexport * from '@ktortu/aaa/cdk';\nexport * from '@ktortu/aaa/dialog';\nexport * from '@ktortu/aaa/forms';\nexport * from '@ktortu/aaa/i18n';\nexport * from '@ktortu/aaa/menu';\nexport * from '@ktortu/aaa/snackbar';\nexport * from '@ktortu/aaa/tabs';\nexport * from '@ktortu/aaa/tooltip';\nexport * from '@ktortu/aaa/progress-bar';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;;;;;;AAAA;;AAEG;;ACFH;;AAEG"}
|
|
@@ -21,14 +21,6 @@
|
|
|
21
21
|
color: var(--field-required-color, var(--kt-danger, #8c1d18));
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/* Disposition des options : pilotable par token (colonne par défaut, ligne possible). */
|
|
25
|
-
.kt-checkbox-group__options {
|
|
26
|
-
display: flex;
|
|
27
|
-
flex-direction: var(--checkbox-group-direction, column);
|
|
28
|
-
flex-wrap: wrap;
|
|
29
|
-
gap: var(--checkbox-group-gap, 0.25rem);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
24
|
.kt-checkbox-group__hint {
|
|
33
25
|
margin: 0;
|
|
34
26
|
font-size: var(--field-hint-font-size, 0.8125rem);
|
|
@@ -52,6 +52,11 @@
|
|
|
52
52
|
/* Texte réservé aux lecteurs d'écran (live region des retraits). */
|
|
53
53
|
.kt-chip-list__status {
|
|
54
54
|
position: absolute;
|
|
55
|
+
/* Ancrée au coin de l'hôte : sans `inset`, un `position: absolute` sans ancêtre positionné
|
|
56
|
+
retombe sur sa position STATIQUE (bas de la liste). Dans un conteneur scrollable, ce 1px
|
|
57
|
+
atterrit loin dans le document et crée une 2ᵉ barre de défilement fantôme. */
|
|
58
|
+
inset-block-start: 0;
|
|
59
|
+
inset-inline-start: 0;
|
|
55
60
|
inline-size: 1px;
|
|
56
61
|
block-size: 1px;
|
|
57
62
|
padding: 0;
|
package/forms/field/field.css
CHANGED
|
@@ -71,6 +71,22 @@
|
|
|
71
71
|
color: var(--field-error-color, #8c1d18);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/* Copie visually-hidden du texte d'aide : présente en permanence dans l'arbre d'accessibilité
|
|
75
|
+
(technique clip), contrairement à la bulle du tooltip créée à la volée → aria-describedby du
|
|
76
|
+
contrôle résout toujours sa cible (pas de référence pendante pour les lecteurs d'écran). */
|
|
77
|
+
.kt-field__help-description {
|
|
78
|
+
position: absolute;
|
|
79
|
+
inset-block-start: 0;
|
|
80
|
+
inset-inline-start: 0;
|
|
81
|
+
inline-size: 1px;
|
|
82
|
+
block-size: 1px;
|
|
83
|
+
padding: 0;
|
|
84
|
+
margin: -1px;
|
|
85
|
+
overflow: hidden;
|
|
86
|
+
clip-path: inset(50%);
|
|
87
|
+
white-space: nowrap;
|
|
88
|
+
}
|
|
89
|
+
|
|
74
90
|
/* Apparition d'un message d'erreur : token de BASCULE (non déclaré => aucune animation).
|
|
75
91
|
Sur le MESSAGE (inséré à l'invalidation) — PAS sur le conteneur, qui vit en permanence
|
|
76
92
|
(région live). Keyframes de thème : transform/opacity/filter seulement (les spans sont
|
|
@@ -21,14 +21,6 @@
|
|
|
21
21
|
color: var(--field-required-color, var(--kt-danger, #8c1d18));
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
/* Disposition des options : pilotable par token (colonne par défaut, ligne possible). */
|
|
25
|
-
.kt-radio-group__options {
|
|
26
|
-
display: flex;
|
|
27
|
-
flex-direction: var(--radio-group-direction, row);
|
|
28
|
-
flex-wrap: wrap;
|
|
29
|
-
gap: var(--radio-group-gap, 1rem);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
24
|
.kt-radio-group__hint {
|
|
33
25
|
margin: 0;
|
|
34
26
|
font-size: var(--field-hint-font-size, 0.8125rem);
|
|
@@ -52,4 +44,4 @@
|
|
|
52
44
|
animation: none;
|
|
53
45
|
}
|
|
54
46
|
}
|
|
55
|
-
}
|
|
47
|
+
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Temporal (Date/Time/DateTime/YearMonth/Instant), qui réutilise la même `.kt-field-box`.
|
|
4
4
|
Globale + classes namespacées : partagée entre plusieurs composants, donc non scopable. */
|
|
5
5
|
kt-text-field,
|
|
6
|
+
kt-password-field,
|
|
6
7
|
kt-text-area,
|
|
7
8
|
kt-number-field,
|
|
8
9
|
kt-date-field,
|
|
@@ -131,12 +132,14 @@
|
|
|
131
132
|
|
|
132
133
|
/* Le bouton « effacer » est une icône INTERNE de la lib : toujours Material Symbols,
|
|
133
134
|
indépendante de --kt-icon-font (sinon un override consommateur casserait la croix). */
|
|
134
|
-
.kt-field-box__clear .kt-field-box__icon
|
|
135
|
+
.kt-field-box__clear .kt-field-box__icon,
|
|
136
|
+
.kt-field-box__toggle .kt-field-box__icon {
|
|
135
137
|
font-family: 'Material Symbols Outlined';
|
|
136
138
|
font-weight: normal;
|
|
137
139
|
}
|
|
138
140
|
|
|
139
|
-
.kt-field-box__clear
|
|
141
|
+
.kt-field-box__clear,
|
|
142
|
+
.kt-field-box__toggle {
|
|
140
143
|
display: inline-flex;
|
|
141
144
|
align-items: center;
|
|
142
145
|
justify-content: center;
|
|
@@ -151,7 +154,8 @@
|
|
|
151
154
|
}
|
|
152
155
|
|
|
153
156
|
/* Cible tactile AAA 44x44px étendue via un pseudo-élément transparent */
|
|
154
|
-
.kt-field-box__clear::after
|
|
157
|
+
.kt-field-box__clear::after,
|
|
158
|
+
.kt-field-box__toggle::after {
|
|
155
159
|
content: '';
|
|
156
160
|
position: absolute;
|
|
157
161
|
top: 50%;
|
|
@@ -161,11 +165,13 @@
|
|
|
161
165
|
height: 44px;
|
|
162
166
|
}
|
|
163
167
|
|
|
164
|
-
.kt-field-box__clear:hover
|
|
168
|
+
.kt-field-box__clear:hover,
|
|
169
|
+
.kt-field-box__toggle:hover {
|
|
165
170
|
color: var(--field-color, inherit);
|
|
166
171
|
}
|
|
167
172
|
|
|
168
|
-
.kt-field-box__clear:focus-visible
|
|
173
|
+
.kt-field-box__clear:focus-visible,
|
|
174
|
+
.kt-field-box__toggle:focus-visible {
|
|
169
175
|
outline: 2px solid var(--field-border-color-focus, #0b57d0);
|
|
170
176
|
outline-offset: 1px;
|
|
171
177
|
}
|
|
@@ -221,7 +227,9 @@
|
|
|
221
227
|
font-size: var(--field-font-size, 1rem);
|
|
222
228
|
font-weight: 400;
|
|
223
229
|
color: var(--field-hint-color, #5f6368);
|
|
224
|
-
transition:
|
|
230
|
+
transition:
|
|
231
|
+
transform 0.15s ease,
|
|
232
|
+
color 0.15s ease;
|
|
225
233
|
}
|
|
226
234
|
|
|
227
235
|
/* RTL : `transform-origin` n'accepte pas de mot-clé logique → on bascule l'origine de la mise à
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
@layer kt-aaa.components {
|
|
2
|
+
/* Spinner « validation asynchrone en cours » par défaut.
|
|
3
|
+
|
|
4
|
+
100 % CSS (pseudo-élément, aucun markup) et piloté par l'attribut `[data-pending]` posé par les
|
|
5
|
+
contrôles quand leur input `pending` est vrai (l'accessibilité passe par `aria-busy`, indépendant).
|
|
6
|
+
|
|
7
|
+
Entièrement surchargeable / suppressible côté consommateur :
|
|
8
|
+
- retailler/recolorer via les tokens `--field-spinner-*` ;
|
|
9
|
+
- supprimer : kt-text-field .kt-field-box[data-pending]::after { content: none; }
|
|
10
|
+
- remplacer par sa propre affordance (le hook `[data-pending]` reste disponible). */
|
|
11
|
+
@keyframes kt-field-spin {
|
|
12
|
+
to {
|
|
13
|
+
transform: rotate(1turn);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.kt-field-box[data-pending]::after,
|
|
18
|
+
.kt-switch-field[data-pending] .kt-switch-row::after,
|
|
19
|
+
.kt-checkbox-field[data-pending] .kt-checkbox::after,
|
|
20
|
+
.kt-radio-group-field[data-pending] .kt-radio-group__legend::after,
|
|
21
|
+
.kt-checkbox-group-field[data-pending] .kt-checkbox-group__legend::after {
|
|
22
|
+
content: '';
|
|
23
|
+
display: inline-block;
|
|
24
|
+
flex: none;
|
|
25
|
+
vertical-align: middle;
|
|
26
|
+
inline-size: var(--field-spinner-size, 1em);
|
|
27
|
+
block-size: var(--field-spinner-size, 1em);
|
|
28
|
+
margin-inline-start: var(--field-spinner-gap, 0.5rem);
|
|
29
|
+
border: var(--field-spinner-width, 2px) solid var(--field-spinner-track, currentColor);
|
|
30
|
+
border-top-color: var(--field-spinner-color, var(--field-border-color-focus, #1a73e8));
|
|
31
|
+
border-radius: 50%;
|
|
32
|
+
opacity: var(--field-spinner-opacity, 0.7);
|
|
33
|
+
animation: kt-field-spin var(--field-spinner-duration, 0.7s) linear infinite;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Respect de prefers-reduced-motion : on fige la rotation (le cercle reste visible comme indicateur). */
|
|
37
|
+
@media (prefers-reduced-motion: reduce) {
|
|
38
|
+
.kt-field-box[data-pending]::after,
|
|
39
|
+
.kt-switch-field[data-pending] .kt-switch-row::after,
|
|
40
|
+
.kt-checkbox-field[data-pending] .kt-checkbox::after,
|
|
41
|
+
.kt-radio-group-field[data-pending] .kt-radio-group__legend::after,
|
|
42
|
+
.kt-checkbox-group-field[data-pending] .kt-checkbox-group__legend::after {
|
|
43
|
+
animation: none;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -178,6 +178,10 @@
|
|
|
178
178
|
/* Texte réservé aux lecteurs d'écran (live region du nombre de résultats). */
|
|
179
179
|
.kt-select__sr-only {
|
|
180
180
|
position: absolute;
|
|
181
|
+
/* Ancrée au coin : sinon ce 1px `absolute` retombe sur sa position statique et, dans un
|
|
182
|
+
conteneur scrollable, étire le document → barre de défilement fantôme. */
|
|
183
|
+
inset-block-start: 0;
|
|
184
|
+
inset-inline-start: 0;
|
|
181
185
|
inline-size: 1px;
|
|
182
186
|
block-size: 1px;
|
|
183
187
|
padding: 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ktortu/aaa",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "Bibliothèque de composants Angular headless + thémés par tokens CSS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -73,6 +73,10 @@
|
|
|
73
73
|
"types": "./types/ktortu-aaa-dialog.d.ts",
|
|
74
74
|
"default": "./fesm2022/ktortu-aaa-dialog.mjs"
|
|
75
75
|
},
|
|
76
|
+
"./disclosure": {
|
|
77
|
+
"types": "./types/ktortu-aaa-disclosure.d.ts",
|
|
78
|
+
"default": "./fesm2022/ktortu-aaa-disclosure.mjs"
|
|
79
|
+
},
|
|
76
80
|
"./forms": {
|
|
77
81
|
"types": "./types/ktortu-aaa-forms.d.ts",
|
|
78
82
|
"default": "./fesm2022/ktortu-aaa-forms.mjs"
|
|
@@ -85,6 +89,14 @@
|
|
|
85
89
|
"types": "./types/ktortu-aaa-menu.d.ts",
|
|
86
90
|
"default": "./fesm2022/ktortu-aaa-menu.mjs"
|
|
87
91
|
},
|
|
92
|
+
"./progress-bar": {
|
|
93
|
+
"types": "./types/ktortu-aaa-progress-bar.d.ts",
|
|
94
|
+
"default": "./fesm2022/ktortu-aaa-progress-bar.mjs"
|
|
95
|
+
},
|
|
96
|
+
"./snackbar": {
|
|
97
|
+
"types": "./types/ktortu-aaa-snackbar.d.ts",
|
|
98
|
+
"default": "./fesm2022/ktortu-aaa-snackbar.mjs"
|
|
99
|
+
},
|
|
88
100
|
"./tabs": {
|
|
89
101
|
"types": "./types/ktortu-aaa-tabs.d.ts",
|
|
90
102
|
"default": "./fesm2022/ktortu-aaa-tabs.mjs"
|