@starterlib/ui 0.2.0 → 0.3.0
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 +52 -16
- package/fesm2022/starterlib-ui-interactions.mjs +296 -0
- package/fesm2022/starterlib-ui-interactions.mjs.map +1 -0
- package/fesm2022/starterlib-ui-surfaces.mjs +1106 -11
- package/fesm2022/starterlib-ui-surfaces.mjs.map +1 -1
- package/fesm2022/starterlib-ui.mjs +1032 -105
- package/fesm2022/starterlib-ui.mjs.map +1 -1
- package/package.json +16 -3
- package/types/starterlib-ui-interactions.d.ts +162 -0
- package/types/starterlib-ui-surfaces.d.ts +607 -16
- package/types/starterlib-ui.d.ts +652 -23
package/README.md
CHANGED
|
@@ -14,29 +14,53 @@ des dependances de pair : c'est l'application qui les installe, et elles doivent
|
|
|
14
14
|
etre **identiques dans l'hote et dans chaque remote**. Deux versions du socle
|
|
15
15
|
dans le meme navigateur, ce sont deux jeux de jetons d'injection.
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## Trois points d'entree
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
Un composant sort du tronc quand il traine un pair lourd, et seulement alors ;
|
|
20
|
+
le point d'entree secondaire ou il va se choisit ensuite par ce qu'il EST pour
|
|
21
|
+
qui l'emploie.
|
|
21
22
|
|
|
22
|
-
| Point d'entree
|
|
23
|
-
|
|
|
24
|
-
| `@starterlib/ui`
|
|
25
|
-
| `@starterlib/ui/surfaces`
|
|
23
|
+
| Point d'entree | Contenu | Ce qu'il traine | Gzippe |
|
|
24
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------- | ------- |
|
|
25
|
+
| `@starterlib/ui` | le tronc : etats, texte, actions, structure, transverses | `@angular/router`, deja exige par `core` | 22,4 Ko |
|
|
26
|
+
| `@starterlib/ui/surfaces` | ce qui se pose AU-DESSUS de la page : menu, dialogues, tiroirs, messages ephemeres | `@angular/cdk`, `@angular/aria/menu` | 7,1 Ko |
|
|
27
|
+
| `@starterlib/ui/interactions` | ce qui fait PARTIE de la page et traine Aria ou une surface : onglets, navigation laterale | `@angular/aria`, qui exige lui-meme `@angular/cdk` | 2,0 Ko |
|
|
26
28
|
|
|
27
29
|
```ts
|
|
28
|
-
import { StButton,
|
|
29
|
-
import {
|
|
30
|
+
import { StButton, StAppShell } from '@starterlib/ui';
|
|
31
|
+
import { StDialog, StToast } from '@starterlib/ui/surfaces';
|
|
32
|
+
import { StTabs, StTabPanel, StTabContent } from '@starterlib/ui/interactions';
|
|
30
33
|
```
|
|
31
34
|
|
|
32
35
|
⚠️ Un paquet partage en federation **ne s'elague pas** : declare singleton, il
|
|
33
36
|
est charge en entier des qu'un remote le reference. La separation n'a donc pas
|
|
34
|
-
pour but le poids
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
pour but le poids, mais le **train de singletons** : une application qui
|
|
38
|
+
n'affiche ni menu, ni dialogue, ni onglets ne charge ni le CDK ni Aria, et n'a
|
|
39
|
+
pas a se redeployer quand ils montent de version.
|
|
40
|
+
|
|
41
|
+
`@angular/cdk` et `@angular/aria` sont des pairs **optionnels** : le tronc ne les
|
|
42
|
+
importe pas. Ils deviennent obligatoires des le premier import d'un point
|
|
43
|
+
d'entree secondaire, et leur absence se voit alors a la resolution, pas a
|
|
44
|
+
l'execution. ⚠️ `@angular/aria` exige `@angular/cdk` a la version EXACTE : les
|
|
45
|
+
deux montent ensemble.
|
|
46
|
+
|
|
47
|
+
⚠️ **En federation, chaque point d'entree se partage SEPAREMENT.** Ce sont trois
|
|
48
|
+
specificateurs de module distincts : partager `@starterlib/ui` ne couvre ni
|
|
49
|
+
`surfaces` ni `interactions`. Omis de la configuration, chaque remote en embarque
|
|
50
|
+
sa propre copie — et la regle `singleton: true, strictVersion: true` qui protege
|
|
51
|
+
le tronc ne protege plus rien au-dessus.
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
// federation.config.mjs de l'hote ET de chaque remote
|
|
55
|
+
shared: {
|
|
56
|
+
'@starterlib/ui': { singleton: true, strictVersion: true },
|
|
57
|
+
'@starterlib/ui/surfaces': { singleton: true, strictVersion: true },
|
|
58
|
+
'@starterlib/ui/interactions': { singleton: true, strictVersion: true },
|
|
59
|
+
// ...
|
|
60
|
+
}
|
|
61
|
+
```
|
|
37
62
|
|
|
38
|
-
|
|
39
|
-
`ui/surfaces`. Voir `docs/adr/0003-points-d-entree-decoupes-par-dependance.md`.
|
|
63
|
+
Voir `docs/adr/0003-points-d-entree-decoupes-par-dependance.md`.
|
|
40
64
|
|
|
41
65
|
## Configuration — une fois, dans l'hote
|
|
42
66
|
|
|
@@ -111,9 +135,21 @@ Vague 1 : etats (`st-spinner`, `st-skeleton`, `st-empty`, `st-error`,
|
|
|
111
135
|
`st-heading`), donnees (`st-money`, `st-date`, `st-relative-time`, `st-masked`,
|
|
112
136
|
`st-code`, `st-count`), actions (`st-button`, `st-icon-button`, `st-link`,
|
|
113
137
|
`st-button-group`), indicateurs (`st-badge`, `st-status-pill`, `st-tag`,
|
|
114
|
-
`st-avatar`), iconographie (`st-icon`).
|
|
138
|
+
`st-avatar`), iconographie (`st-icon`). `st-menu` est passe sous `ui/surfaces`.
|
|
139
|
+
|
|
140
|
+
Vague 2 :
|
|
141
|
+
|
|
142
|
+
- **Tronc** — structure (`st-app-shell`, `st-header`, `st-skip-link`, `st-page-title`,
|
|
143
|
+
`st-breadcrumb`, `st-section`, `st-card`, `st-divider`), retour (`st-banner`,
|
|
144
|
+
`st-inline-message`), transverses (`st-theme-toggle`,
|
|
145
|
+
`st-lang-switch`, `st-copy-button`, `st-timer`, `st-logo`).
|
|
146
|
+
- **`ui/surfaces`** — `StDialog` (dialogue, tiroir, feuille inferieure),
|
|
147
|
+
`StConfirmDialog`, `StToast`, `st-idle-warning`, `stTooltip`, `st-popover`.
|
|
148
|
+
- **`ui/interactions`** — `st-tabs`, `st-tab-panel`, `stTabContent`, `st-sidenav`,
|
|
149
|
+
`stSidenavToggle`.
|
|
115
150
|
|
|
116
|
-
Inventaire
|
|
151
|
+
Inventaire et regles de la suite : `docs/plan-librairie.md` et
|
|
152
|
+
`docs/audit-vague-2-2026-09-17.md` du depot.
|
|
117
153
|
|
|
118
154
|
## Regles tenues par les composants
|
|
119
155
|
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, model, computed, ChangeDetectionStrategy, Component, Directive, inject, signal, viewChild, effect, DestroyRef } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/aria/tabs';
|
|
4
|
+
import { TabList, Tab, Tabs, TabPanel, TabContent } from '@angular/aria/tabs';
|
|
5
|
+
import { BreakpointObserver } from '@angular/cdk/layout';
|
|
6
|
+
import { NgTemplateOutlet } from '@angular/common';
|
|
7
|
+
import { ST_LIBELLES } from '@starterlib/ui';
|
|
8
|
+
import { StDialog } from '@starterlib/ui/surfaces';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Onglets, sur les primitives `@angular/aria/tabs`.
|
|
12
|
+
*
|
|
13
|
+
* ```html
|
|
14
|
+
* <st-tabs etiquette="Compte" [onglets]="onglets" [(selection)]="onglet">
|
|
15
|
+
* <st-tab-panel valeur="operations">
|
|
16
|
+
* <ng-template stTabContent><app-operations /></ng-template>
|
|
17
|
+
* </st-tab-panel>
|
|
18
|
+
* <st-tab-panel valeur="virements">
|
|
19
|
+
* <ng-template stTabContent><app-virements /></ng-template>
|
|
20
|
+
* </st-tab-panel>
|
|
21
|
+
* </st-tabs>
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* ⚠️ **La liste d'onglets est rendue par le composant, a partir de donnees**, et
|
|
25
|
+
* non projetee. Les primitives d'Aria relient un onglet a sa liste par
|
|
26
|
+
* INJECTION, et un contenu projete garde l'injecteur de l'endroit ou il est
|
|
27
|
+
* ecrit : c'est la lecon de `st-menu`, ou des elements projetes ne
|
|
28
|
+
* s'enregistraient jamais. Rendue ici, la liste est a coup sur sous la bonne
|
|
29
|
+
* primitive — et ses valeurs peuvent etre dites en francais.
|
|
30
|
+
*
|
|
31
|
+
* Les PANNEAUX, eux, sont projetes : ecrits directement sous `st-tabs`, leur
|
|
32
|
+
* injecteur parent est celui de l'hote, qui porte la primitive `Tabs`.
|
|
33
|
+
*
|
|
34
|
+
* ⚠️ **Activation manuelle par defaut.** En activation automatique, chaque
|
|
35
|
+
* fleche SELECTIONNE l'onglet atteint ; son contenu differe se rend, et charge
|
|
36
|
+
* ses donnees. Parcourir cinq onglets au clavier lancerait cinq requetes pour en
|
|
37
|
+
* lire un. En manuelle, les fleches deplacent le focus et Entree ou Espace
|
|
38
|
+
* selectionne. `automatique` reste le bon choix quand les panneaux sont deja la
|
|
39
|
+
* et s'affichent sans delai.
|
|
40
|
+
*/
|
|
41
|
+
class StTabs {
|
|
42
|
+
onglets = input.required(/* @ts-ignore */
|
|
43
|
+
...(ngDevMode ? [{ debugName: "onglets" }] : /* istanbul ignore next */ []));
|
|
44
|
+
/** Nom accessible de la liste : sans lui, plusieurs listes d'onglets se confondent. */
|
|
45
|
+
etiquette = input.required(/* @ts-ignore */
|
|
46
|
+
...(ngDevMode ? [{ debugName: "etiquette" }] : /* istanbul ignore next */ []));
|
|
47
|
+
activation = input('manuelle', /* @ts-ignore */
|
|
48
|
+
...(ngDevMode ? [{ debugName: "activation" }] : /* istanbul ignore next */ []));
|
|
49
|
+
orientation = input('horizontale', /* @ts-ignore */
|
|
50
|
+
...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
51
|
+
/** Valeur de l'onglet selectionne. `undefined` : le premier onglet disponible. */
|
|
52
|
+
selection = model(undefined, /* @ts-ignore */
|
|
53
|
+
...(ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []));
|
|
54
|
+
/**
|
|
55
|
+
* ⚠️ Toujours un onglet selectionne. Le motif ARIA l'exige : une liste sans
|
|
56
|
+
* selection n'affiche aucun panneau, et la page parait vide sans raison.
|
|
57
|
+
*/
|
|
58
|
+
selectionEffective = computed(() => this.selection() ?? this.onglets().find((onglet) => onglet.desactive !== true)?.valeur, /* @ts-ignore */
|
|
59
|
+
...(ngDevMode ? [{ debugName: "selectionEffective" }] : /* istanbul ignore next */ []));
|
|
60
|
+
modeAria = computed(() => this.activation() === 'automatique' ? 'follow' : 'explicit', /* @ts-ignore */
|
|
61
|
+
...(ngDevMode ? [{ debugName: "modeAria" }] : /* istanbul ignore next */ []));
|
|
62
|
+
orientationAria = computed(() => this.orientation() === 'verticale' ? 'vertical' : 'horizontal', /* @ts-ignore */
|
|
63
|
+
...(ngDevMode ? [{ debugName: "orientationAria" }] : /* istanbul ignore next */ []));
|
|
64
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTabs, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
65
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StTabs, isStandalone: true, selector: "st-tabs", inputs: { onglets: { classPropertyName: "onglets", publicName: "onglets", isSignal: true, isRequired: true, transformFunction: null }, etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: true, transformFunction: null }, activation: { classPropertyName: "activation", publicName: "activation", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, selection: { classPropertyName: "selection", publicName: "selection", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selection: "selectionChange" }, host: { properties: { "attr.data-orientation": "orientation()" }, classAttribute: "st-tabs" }, hostDirectives: [{ directive: i1.Tabs }], ngImport: i0, template: "<div\n class=\"st-tabs__liste\"\n ngTabList\n [attr.aria-label]=\"etiquette()\"\n [selectionMode]=\"modeAria()\"\n [orientation]=\"orientationAria()\"\n [selectedTab]=\"selectionEffective()\"\n (selectedTabChange)=\"selection.set($event)\"\n>\n @for (onglet of onglets(); track onglet.valeur) {\n <button\n class=\"st-tabs__onglet\"\n type=\"button\"\n ngTab\n [value]=\"onglet.valeur\"\n [disabled]=\"onglet.desactive === true\"\n >\n {{ onglet.libelle }}\n </button>\n }\n</div>\n\n<div class=\"st-tabs__panneaux\">\n <ng-content />\n</div>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}:host([data-orientation=verticale]){display:flex;gap:var(--st-espacement-4)}.st-tabs__liste{display:flex;gap:var(--st-espacement-1);border-block-end:1px solid var(--st-couleur-bordure)}:host([data-orientation=verticale]) .st-tabs__liste{flex-direction:column;border-block-end:0;border-inline-end:1px solid var(--st-couleur-bordure)}.st-tabs__panneaux{flex:1 1 auto;min-inline-size:0}.st-tabs__onglet:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-tabs__onglet{min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-4);font:inherit;color:var(--st-couleur-texte-discret);cursor:pointer;background:none;border:0;border-block-end:3px solid transparent}.st-tabs__onglet:hover{color:var(--st-couleur-texte)}.st-tabs__onglet[aria-selected=true]{font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte);border-block-end-color:var(--st-couleur-primaire)}.st-tabs__onglet[aria-disabled=true]{color:var(--st-couleur-texte-desactive);cursor:not-allowed}@media(forced-colors:active){.st-tabs__onglet[aria-selected=true]{border-block-end-color:Highlight}}\n"], dependencies: [{ kind: "directive", type: TabList, selector: "[ngTabList]", inputs: ["orientation", "wrap", "softDisabled", "focusMode", "selectionMode", "selectedTab", "disabled"], outputs: ["selectedTabChange"], exportAs: ["ngTabList"] }, { kind: "directive", type: Tab, selector: "[ngTab]", inputs: ["id", "disabled", "value"], exportAs: ["ngTab"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
66
|
+
}
|
|
67
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTabs, decorators: [{
|
|
68
|
+
type: Component,
|
|
69
|
+
args: [{ selector: 'st-tabs', changeDetection: ChangeDetectionStrategy.OnPush, imports: [TabList, Tab], hostDirectives: [Tabs], host: {
|
|
70
|
+
class: 'st-tabs',
|
|
71
|
+
'[attr.data-orientation]': 'orientation()',
|
|
72
|
+
}, template: "<div\n class=\"st-tabs__liste\"\n ngTabList\n [attr.aria-label]=\"etiquette()\"\n [selectionMode]=\"modeAria()\"\n [orientation]=\"orientationAria()\"\n [selectedTab]=\"selectionEffective()\"\n (selectedTabChange)=\"selection.set($event)\"\n>\n @for (onglet of onglets(); track onglet.valeur) {\n <button\n class=\"st-tabs__onglet\"\n type=\"button\"\n ngTab\n [value]=\"onglet.valeur\"\n [disabled]=\"onglet.desactive === true\"\n >\n {{ onglet.libelle }}\n </button>\n }\n</div>\n\n<div class=\"st-tabs__panneaux\">\n <ng-content />\n</div>\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}:host([data-orientation=verticale]){display:flex;gap:var(--st-espacement-4)}.st-tabs__liste{display:flex;gap:var(--st-espacement-1);border-block-end:1px solid var(--st-couleur-bordure)}:host([data-orientation=verticale]) .st-tabs__liste{flex-direction:column;border-block-end:0;border-inline-end:1px solid var(--st-couleur-bordure)}.st-tabs__panneaux{flex:1 1 auto;min-inline-size:0}.st-tabs__onglet:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}.st-tabs__onglet{min-block-size:var(--st-cible-tactile-min);padding:var(--st-espacement-2) var(--st-espacement-4);font:inherit;color:var(--st-couleur-texte-discret);cursor:pointer;background:none;border:0;border-block-end:3px solid transparent}.st-tabs__onglet:hover{color:var(--st-couleur-texte)}.st-tabs__onglet[aria-selected=true]{font-weight:var(--st-graisse-semi);color:var(--st-couleur-texte);border-block-end-color:var(--st-couleur-primaire)}.st-tabs__onglet[aria-disabled=true]{color:var(--st-couleur-texte-desactive);cursor:not-allowed}@media(forced-colors:active){.st-tabs__onglet[aria-selected=true]{border-block-end-color:Highlight}}\n"] }]
|
|
73
|
+
}], propDecorators: { onglets: [{ type: i0.Input, args: [{ isSignal: true, alias: "onglets", required: true }] }], etiquette: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquette", required: true }] }], activation: [{ type: i0.Input, args: [{ isSignal: true, alias: "activation", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], selection: [{ type: i0.Input, args: [{ isSignal: true, alias: "selection", required: false }] }, { type: i0.Output, args: ["selectionChange"] }] } });
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Panneau d'un onglet, relie par sa `valeur`.
|
|
77
|
+
*
|
|
78
|
+
* ⚠️ La primitive d'Aria ne masque RIEN : elle pose `inert` sur le panneau
|
|
79
|
+
* inactif, ce qui le retire de l'arbre d'accessibilite et du clavier, mais le
|
|
80
|
+
* laisse a l'ecran. Sa documentation le dit en une ligne. Sans le style de ce
|
|
81
|
+
* composant, tous les panneaux s'affichaient empiles, muets et intouchables.
|
|
82
|
+
*/
|
|
83
|
+
/* eslint-disable-next-line @typescript-eslint/no-extraneous-class --
|
|
84
|
+
Vide par construction : tout le comportement vient de la primitive d'Aria
|
|
85
|
+
composee en directive d'hote. La classe porte le selecteur et le style du
|
|
86
|
+
socle, rien d'autre ; y ajouter un membre pour satisfaire la regle serait
|
|
87
|
+
inventer de l'API. */
|
|
88
|
+
class StTabPanel {
|
|
89
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTabPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
90
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.6", type: StTabPanel, isStandalone: true, selector: "st-tab-panel", host: { classAttribute: "st-tab-panel" }, hostDirectives: [{ directive: i1.TabPanel, inputs: ["value", "valeur"] }], ngImport: i0, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host{display:block;padding-block:var(--st-espacement-4)}:host([inert]){display:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
91
|
+
}
|
|
92
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTabPanel, decorators: [{
|
|
93
|
+
type: Component,
|
|
94
|
+
args: [{ selector: 'st-tab-panel', changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [{ directive: TabPanel, inputs: ['value: valeur'] }], host: { class: 'st-tab-panel' }, template: "<ng-content />\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host:focus-visible{outline:2px solid var(--st-couleur-anneau-focus);outline-offset:2px}:host{display:block;padding-block:var(--st-espacement-4)}:host([inert]){display:none}\n"] }]
|
|
95
|
+
}] });
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Contenu differe d'un panneau : rendu a la premiere selection de son onglet.
|
|
99
|
+
*
|
|
100
|
+
* Un ecran a cinq onglets ne charge ainsi que celui qu'on regarde. Voir
|
|
101
|
+
* l'activation manuelle de `st-tabs` : c'est ce qui empeche qu'un simple
|
|
102
|
+
* parcours au clavier les rende tous.
|
|
103
|
+
*/
|
|
104
|
+
/* eslint-disable-next-line @typescript-eslint/no-extraneous-class --
|
|
105
|
+
Vide par construction : tout le comportement vient de la primitive d'Aria
|
|
106
|
+
composee en directive d'hote. La classe porte le selecteur et le style du
|
|
107
|
+
socle, rien d'autre ; y ajouter un membre pour satisfaire la regle serait
|
|
108
|
+
inventer de l'API. */
|
|
109
|
+
class StTabContent {
|
|
110
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTabContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
111
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.6", type: StTabContent, isStandalone: true, selector: "ng-template[stTabContent]", hostDirectives: [{ directive: i1.TabContent }], ngImport: i0 });
|
|
112
|
+
}
|
|
113
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StTabContent, decorators: [{
|
|
114
|
+
type: Directive,
|
|
115
|
+
args: [{
|
|
116
|
+
selector: 'ng-template[stTabContent]',
|
|
117
|
+
hostDirectives: [TabContent],
|
|
118
|
+
}]
|
|
119
|
+
}] });
|
|
120
|
+
|
|
121
|
+
/** Au-dela, la navigation tient a cote du contenu. Meme seuil que `st-app-shell`. */
|
|
122
|
+
const ECRAN_LARGE = '(min-width: 64rem)';
|
|
123
|
+
let compteur = 0;
|
|
124
|
+
/**
|
|
125
|
+
* Navigation laterale : une region a cote du contenu sur grand ecran, un tiroir
|
|
126
|
+
* sur petit ecran.
|
|
127
|
+
*
|
|
128
|
+
* ```html
|
|
129
|
+
* <st-app-shell>
|
|
130
|
+
* <button entete stButton [stSidenavToggle]="navigation">Menu</button>
|
|
131
|
+
* <st-sidenav navigation #navigation etiquette="Navigation principale">
|
|
132
|
+
* <a routerLink="/comptes">Comptes</a>
|
|
133
|
+
* </st-sidenav>
|
|
134
|
+
* …
|
|
135
|
+
* </st-app-shell>
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* ⚠️ **Deux modes, jamais confondus.** Persistante, c'est une REGION de la page :
|
|
139
|
+
* aucun piege, rien a ouvrir. Modale, c'est un TIROIR, donc un `StDialog` — role,
|
|
140
|
+
* piegeage du focus, Echap, retour du focus au bouton — et non une region
|
|
141
|
+
* glissee par-dessus la page avec un peu de CSS, qui laisserait le clavier
|
|
142
|
+
* parcourir la page cachee dessous.
|
|
143
|
+
*
|
|
144
|
+
* ⚠️ **Elle porte son propre `<nav>`, et un seul a la fois.** Sur petit ecran,
|
|
145
|
+
* la region en ligne DISPARAIT quand le tiroir prend le relais : laissee en
|
|
146
|
+
* place, elle resterait un repere de navigation vide, que le lecteur d'ecran
|
|
147
|
+
* proposerait sans rien y trouver.
|
|
148
|
+
*
|
|
149
|
+
* Un lien suivi dans le tiroir le ferme : `StDialog` se ferme a toute navigation
|
|
150
|
+
* du routeur.
|
|
151
|
+
*/
|
|
152
|
+
class StSidenav {
|
|
153
|
+
dialogues = inject(StDialog);
|
|
154
|
+
libelles = inject(ST_LIBELLES);
|
|
155
|
+
/**
|
|
156
|
+
* Nom du repere. `null` : « Navigation principale », du dictionnaire. A
|
|
157
|
+
* renseigner des qu'une page compte deux navigations, qui doivent se
|
|
158
|
+
* distinguer.
|
|
159
|
+
*/
|
|
160
|
+
etiquette = input(null, /* @ts-ignore */
|
|
161
|
+
...(ngDevMode ? [{ debugName: "etiquette" }] : /* istanbul ignore next */ []));
|
|
162
|
+
etiquetteLue = computed(() => this.etiquette() ?? this.libelles().navigationPrincipale, /* @ts-ignore */
|
|
163
|
+
...(ngDevMode ? [{ debugName: "etiquetteLue" }] : /* istanbul ignore next */ []));
|
|
164
|
+
/** `auto` : persistante sur grand ecran, tiroir en dessous. */
|
|
165
|
+
mode = input('auto', /* @ts-ignore */
|
|
166
|
+
...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
167
|
+
identifiant = `st-sidenav-${(compteur += 1).toString()}`;
|
|
168
|
+
ecranLarge = signal(false, /* @ts-ignore */
|
|
169
|
+
...(ngDevMode ? [{ debugName: "ecranLarge" }] : /* istanbul ignore next */ []));
|
|
170
|
+
/** Mode reellement applique. Lu par le bouton, qui ne s'affiche qu'en tiroir. */
|
|
171
|
+
modeEffectif = computed(() => {
|
|
172
|
+
const mode = this.mode();
|
|
173
|
+
if (mode !== 'auto')
|
|
174
|
+
return mode;
|
|
175
|
+
return this.ecranLarge() ? 'persistant' : 'modal';
|
|
176
|
+
}, /* @ts-ignore */
|
|
177
|
+
...(ngDevMode ? [{ debugName: "modeEffectif" }] : /* istanbul ignore next */ []));
|
|
178
|
+
ouvertInterne = signal(false, /* @ts-ignore */
|
|
179
|
+
...(ngDevMode ? [{ debugName: "ouvertInterne" }] : /* istanbul ignore next */ []));
|
|
180
|
+
ouvert = this.ouvertInterne.asReadonly();
|
|
181
|
+
// Nomme autrement que la variable `#contenu` du gabarit, qui la masquerait.
|
|
182
|
+
gabarit = viewChild.required('contenu', /* @ts-ignore */
|
|
183
|
+
...(ngDevMode ? [{ debugName: "gabarit" }] : /* istanbul ignore next */ []));
|
|
184
|
+
reference = null;
|
|
185
|
+
constructor() {
|
|
186
|
+
const abonnement = inject(BreakpointObserver)
|
|
187
|
+
.observe(ECRAN_LARGE)
|
|
188
|
+
.subscribe((etat) => {
|
|
189
|
+
this.ecranLarge.set(etat.matches);
|
|
190
|
+
});
|
|
191
|
+
// Un ecran qui s'elargit pendant que le tiroir est ouvert : la navigation
|
|
192
|
+
// redevient une region, et le tiroir n'a plus de raison d'etre.
|
|
193
|
+
effect(() => {
|
|
194
|
+
if (this.modeEffectif() === 'persistant')
|
|
195
|
+
this.fermer();
|
|
196
|
+
});
|
|
197
|
+
inject(DestroyRef).onDestroy(() => {
|
|
198
|
+
abonnement.unsubscribe();
|
|
199
|
+
this.fermer();
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
ouvrir() {
|
|
203
|
+
if (this.modeEffectif() !== 'modal' || this.reference !== null)
|
|
204
|
+
return;
|
|
205
|
+
const reference = this.dialogues.ouvrir(this.gabarit(), {
|
|
206
|
+
cote: 'debut',
|
|
207
|
+
etiquette: this.etiquetteLue(),
|
|
208
|
+
});
|
|
209
|
+
this.reference = reference;
|
|
210
|
+
this.ouvertInterne.set(true);
|
|
211
|
+
void reference.ferme.then(() => {
|
|
212
|
+
if (this.reference !== reference)
|
|
213
|
+
return;
|
|
214
|
+
this.reference = null;
|
|
215
|
+
this.ouvertInterne.set(false);
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
fermer() {
|
|
219
|
+
const reference = this.reference;
|
|
220
|
+
if (reference === null)
|
|
221
|
+
return;
|
|
222
|
+
this.reference = null;
|
|
223
|
+
this.ouvertInterne.set(false);
|
|
224
|
+
reference.fermer();
|
|
225
|
+
}
|
|
226
|
+
basculer() {
|
|
227
|
+
if (this.ouvertInterne())
|
|
228
|
+
this.fermer();
|
|
229
|
+
else
|
|
230
|
+
this.ouvrir();
|
|
231
|
+
}
|
|
232
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSidenav, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
233
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: StSidenav, isStandalone: true, selector: "st-sidenav", inputs: { etiquette: { classPropertyName: "etiquette", publicName: "etiquette", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-mode": "modeEffectif()" }, classAttribute: "st-sidenav" }, viewQueries: [{ propertyName: "gabarit", first: true, predicate: ["contenu"], descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template #contenu>\n <nav class=\"st-sidenav__navigation\" [attr.id]=\"identifiant\" [attr.aria-label]=\"etiquetteLue()\">\n <ng-content />\n </nav>\n</ng-template>\n\n@if (modeEffectif() === 'persistant') {\n <ng-container [ngTemplateOutlet]=\"contenu\" />\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}:host([data-mode=modal]){display:none}.st-sidenav__navigation{display:flex;flex-direction:column;gap:var(--st-espacement-1);padding:var(--st-espacement-4)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
234
|
+
}
|
|
235
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSidenav, decorators: [{
|
|
236
|
+
type: Component,
|
|
237
|
+
args: [{ selector: 'st-sidenav', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet], host: {
|
|
238
|
+
class: 'st-sidenav',
|
|
239
|
+
'[attr.data-mode]': 'modeEffectif()',
|
|
240
|
+
}, template: "<ng-template #contenu>\n <nav class=\"st-sidenav__navigation\" [attr.id]=\"identifiant\" [attr.aria-label]=\"etiquetteLue()\">\n <ng-content />\n </nav>\n</ng-template>\n\n@if (modeEffectif() === 'persistant') {\n <ng-container [ngTemplateOutlet]=\"contenu\" />\n}\n", styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block}:host([data-mode=modal]){display:none}.st-sidenav__navigation{display:flex;flex-direction:column;gap:var(--st-espacement-1);padding:var(--st-espacement-4)}\n"] }]
|
|
241
|
+
}], ctorParameters: () => [], propDecorators: { etiquette: [{ type: i0.Input, args: [{ isSignal: true, alias: "etiquette", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], gabarit: [{ type: i0.ViewChild, args: ['contenu', { isSignal: true }] }] } });
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Bouton qui ouvre la navigation en tiroir.
|
|
245
|
+
*
|
|
246
|
+
* ⚠️ **Masque quand la navigation est persistante.** Un bouton « Menu » qui ne
|
|
247
|
+
* fait rien, parce que la navigation est deja affichee a cote, est un arret de
|
|
248
|
+
* tabulation inutile et une promesse non tenue.
|
|
249
|
+
*
|
|
250
|
+
* ⚠️ `aria-expanded` suit l'ouverture du tiroir : sans lui, rien ne dit a qui
|
|
251
|
+
* n'en voit pas l'effet que le bouton a agi.
|
|
252
|
+
*/
|
|
253
|
+
class StSidenavToggle {
|
|
254
|
+
stSidenavToggle = input.required(/* @ts-ignore */
|
|
255
|
+
...(ngDevMode ? [{ debugName: "stSidenavToggle" }] : /* istanbul ignore next */ []));
|
|
256
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSidenavToggle, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
257
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.6", type: StSidenavToggle, isStandalone: true, selector: "[stSidenavToggle]", inputs: { stSidenavToggle: { classPropertyName: "stSidenavToggle", publicName: "stSidenavToggle", isSignal: true, isRequired: true, transformFunction: null } }, host: { attributes: { "aria-haspopup": "dialog" }, listeners: { "click": "stSidenavToggle().basculer()" }, properties: { "attr.aria-expanded": "stSidenavToggle().ouvert()", "attr.hidden": "stSidenavToggle().modeEffectif() === \"modal\" ? null : \"\"" } }, ngImport: i0 });
|
|
258
|
+
}
|
|
259
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: StSidenavToggle, decorators: [{
|
|
260
|
+
type: Directive,
|
|
261
|
+
args: [{
|
|
262
|
+
selector: '[stSidenavToggle]',
|
|
263
|
+
host: {
|
|
264
|
+
'aria-haspopup': 'dialog',
|
|
265
|
+
'[attr.aria-expanded]': 'stSidenavToggle().ouvert()',
|
|
266
|
+
'[attr.hidden]': 'stSidenavToggle().modeEffectif() === "modal" ? null : ""',
|
|
267
|
+
'(click)': 'stSidenavToggle().basculer()',
|
|
268
|
+
},
|
|
269
|
+
}]
|
|
270
|
+
}], propDecorators: { stSidenavToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "stSidenavToggle", required: true }] }] } });
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* @starterlib/ui/interactions — les composants montes sur Angular Aria qui ne
|
|
274
|
+
* se posent pas au-dessus de la page.
|
|
275
|
+
*
|
|
276
|
+
* ⚠️ Un point d'entree separe pour la meme raison que `ui/surfaces` : ce qui vit
|
|
277
|
+
* ici traine `@angular/aria`, pair optionnel. Laisse dans le tronc, il entrerait
|
|
278
|
+
* dans le train de singletons de chaque application. Mais ce n'est pas une
|
|
279
|
+
* surface : des onglets font partie de la page. Le ranger sous `ui/surfaces`
|
|
280
|
+
* aurait fait mentir le nom, et l'ADR 0003 aurait perdu sa lisibilite (audit de
|
|
281
|
+
* la vague 2, decision 5.1).
|
|
282
|
+
*
|
|
283
|
+
* ⚠️ En federation, ce point d'entree se partage SEPAREMENT : c'est un
|
|
284
|
+
* specificateur de module distinct.
|
|
285
|
+
*
|
|
286
|
+
* ```ts
|
|
287
|
+
* import { StTabs, StTabPanel, StTabContent } from '@starterlib/ui/interactions';
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Generated bundle index. Do not edit.
|
|
293
|
+
*/
|
|
294
|
+
|
|
295
|
+
export { StSidenav, StSidenavToggle, StTabContent, StTabPanel, StTabs };
|
|
296
|
+
//# sourceMappingURL=starterlib-ui-interactions.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"starterlib-ui-interactions.mjs","sources":["../../../../packages/ui/interactions/src/lib/onglets/st-tabs.ts","../../../../packages/ui/interactions/src/lib/onglets/st-tabs.html","../../../../packages/ui/interactions/src/lib/onglets/st-tab-panel.ts","../../../../packages/ui/interactions/src/lib/onglets/st-tab-panel.html","../../../../packages/ui/interactions/src/lib/onglets/st-tab-content.ts","../../../../packages/ui/interactions/src/lib/navigation/st-sidenav.ts","../../../../packages/ui/interactions/src/lib/navigation/st-sidenav.html","../../../../packages/ui/interactions/src/lib/navigation/st-sidenav-toggle.ts","../../../../packages/ui/interactions/src/public-api.ts","../../../../packages/ui/interactions/src/starterlib-ui-interactions.ts"],"names":[],"mappings":";;;;;;;;;AAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8BG;MAaU,MAAM,CAAA;IACR,OAAO,GAAG,KAAK,CAAC,QAAQ;gFAAqB;;IAG7C,SAAS,GAAG,KAAK,CAAC,QAAQ;kFAAU;IAEpC,UAAU,GAAG,KAAK,CAAoB,UAAU;mFAAC;IACjD,WAAW,GAAG,KAAK,CAAsB,aAAa;oFAAC;;IAGvD,SAAS,GAAG,KAAK,CAAqB,SAAS;kFAAC;AAEzD;;;AAGG;AACgB,IAAA,kBAAkB,GAAG,QAAQ,CAC9C,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,EAAE,MAAM;2FAC7F;AAEkB,IAAA,QAAQ,GAAG,QAAQ,CAAC,MACrC,IAAI,CAAC,UAAU,EAAE,KAAK,aAAa,GAAG,QAAQ,GAAG,UAAU;iFAC5D;AAEkB,IAAA,eAAe,GAAG,QAAQ,CAAC,MAC5C,IAAI,CAAC,WAAW,EAAE,KAAK,WAAW,GAAG,UAAU,GAAG,YAAY;wFAC/D;uGA1BU,MAAM,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAN,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAM,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,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,UAAA,EAAA,EAAA,iBAAA,EAAA,YAAA,EAAA,UAAA,EAAA,YAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,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,OAAA,EAAA,EAAA,SAAA,EAAA,iBAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,uBAAA,EAAA,eAAA,EAAA,EAAA,cAAA,EAAA,SAAA,EAAA,EAAA,cAAA,EAAA,CAAA,EAAA,SAAA,EAAA,EAAA,CAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECzDnB,mlBAyBA,EAAA,MAAA,EAAA,CAAA,2yCAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDyBY,OAAO,2NAAE,GAAG,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,IAAA,EAAA,UAAA,EAAA,OAAA,CAAA,EAAA,QAAA,EAAA,CAAA,OAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAOX,MAAM,EAAA,UAAA,EAAA,CAAA;kBAZlB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,SAAS,EAAA,eAAA,EAGF,uBAAuB,CAAC,MAAM,WACtC,CAAC,OAAO,EAAE,GAAG,CAAC,EAAA,cAAA,EACP,CAAC,IAAI,CAAC,EAAA,IAAA,EAChB;AACJ,wBAAA,KAAK,EAAE,SAAS;AAChB,wBAAA,yBAAyB,EAAE,eAAe;AAC3C,qBAAA,EAAA,QAAA,EAAA,mlBAAA,EAAA,MAAA,EAAA,CAAA,2yCAAA,CAAA,EAAA;;;AEpDH;;;;;;;AAOG;AASH;;;;AAIwB;MACX,UAAU,CAAA;uGAAV,UAAU,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAV,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAU,6LCxBvB,kBACA,EAAA,MAAA,EAAA,CAAA,6VAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FDuBa,UAAU,EAAA,UAAA,EAAA,CAAA;kBAbtB,SAAS;+BACE,cAAc,EAAA,eAAA,EAGP,uBAAuB,CAAC,MAAM,kBAC/B,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,eAAe,CAAC,EAAE,CAAC,QAC9D,EAAE,KAAK,EAAE,cAAc,EAAE,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,6VAAA,CAAA,EAAA;;;AEdjC;;;;;;AAMG;AAKH;;;;AAIwB;MACX,YAAY,CAAA;uGAAZ,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAZ,YAAY,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,2BAAA,EAAA,cAAA,EAAA,CAAA,EAAA,SAAA,EAAA,EAAA,CAAA,UAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAZ,YAAY,EAAA,UAAA,EAAA,CAAA;kBATxB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,2BAA2B;oBACrC,cAAc,EAAE,CAAC,UAAU,CAAC;AAC7B,iBAAA;;;ACMD;AACA,MAAM,WAAW,GAAG,oBAAoB;AAExC,IAAI,QAAQ,GAAG,CAAC;AAEhB;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;MAYU,SAAS,CAAA;AACH,IAAA,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC;AAC5B,IAAA,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC;AAE/C;;;;AAIG;IACM,SAAS,GAAG,KAAK,CAAgB,IAAI;kFAAC;AAE5B,IAAA,YAAY,GAAG,QAAQ,CACxC,MAAM,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,oBAAoB;qFAC/D;;IAGQ,IAAI,GAAG,KAAK,CAAmB,MAAM;6EAAC;IAEtC,WAAW,GAAG,CAAA,WAAA,EAAc,CAAC,QAAQ,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAA,CAAE;IAEhD,UAAU,GAAG,MAAM,CAAC,KAAK;mFAAC;;AAGlC,IAAA,YAAY,GAAG,QAAQ,CAAoC,MAAK;AACvE,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE;QACxB,IAAI,IAAI,KAAK,MAAM;AAAE,YAAA,OAAO,IAAI;AAChC,QAAA,OAAO,IAAI,CAAC,UAAU,EAAE,GAAG,YAAY,GAAG,OAAO;IACnD,CAAC;qFAAC;IAEe,aAAa,GAAG,MAAM,CAAC,KAAK;sFAAC;AACrC,IAAA,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE;;AAGhC,IAAA,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAuB,SAAS;gFAAC;IAEtE,SAAS,GAAwC,IAAI;AAE7D,IAAA,WAAA,GAAA;AACE,QAAA,MAAM,UAAU,GAAG,MAAM,CAAC,kBAAkB;aACzC,OAAO,CAAC,WAAW;AACnB,aAAA,SAAS,CAAC,CAAC,IAAI,KAAI;YAClB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;AACnC,QAAA,CAAC,CAAC;;;QAIJ,MAAM,CAAC,MAAK;AACV,YAAA,IAAI,IAAI,CAAC,YAAY,EAAE,KAAK,YAAY;gBAAE,IAAI,CAAC,MAAM,EAAE;AACzD,QAAA,CAAC,CAAC;AAEF,QAAA,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,MAAK;YAChC,UAAU,CAAC,WAAW,EAAE;YACxB,IAAI,CAAC,MAAM,EAAE;AACf,QAAA,CAAC,CAAC;IACJ;IAEA,MAAM,GAAA;QACJ,IAAI,IAAI,CAAC,YAAY,EAAE,KAAK,OAAO,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;YAAE;AAEhE,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE;AACtD,YAAA,IAAI,EAAE,OAAO;AACb,YAAA,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE;AAC/B,SAAA,CAAC;AACF,QAAA,IAAI,CAAC,SAAS,GAAG,SAAS;AAC1B,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC;AAE5B,QAAA,KAAK,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,MAAK;AAC7B,YAAA,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS;gBAAE;AAClC,YAAA,IAAI,CAAC,SAAS,GAAG,IAAI;AACrB,YAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;AAC/B,QAAA,CAAC,CAAC;IACJ;IAEA,MAAM,GAAA;AACJ,QAAA,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS;QAChC,IAAI,SAAS,KAAK,IAAI;YAAE;AACxB,QAAA,IAAI,CAAC,SAAS,GAAG,IAAI;AACrB,QAAA,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC;QAC7B,SAAS,CAAC,MAAM,EAAE;IACpB;IAEA,QAAQ,GAAA;QACN,IAAI,IAAI,CAAC,aAAa,EAAE;YAAE,IAAI,CAAC,MAAM,EAAE;;YAClC,IAAI,CAAC,MAAM,EAAE;IACpB;uGApFW,SAAS,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAT,SAAS,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,YAAA,EAAA,MAAA,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,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,gBAAA,EAAA,gBAAA,EAAA,EAAA,cAAA,EAAA,YAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,SAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,SAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC/DtB,kRASA,EAAA,MAAA,EAAA,CAAA,+VAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDgDY,gBAAgB,EAAA,QAAA,EAAA,oBAAA,EAAA,MAAA,EAAA,CAAA,yBAAA,EAAA,kBAAA,EAAA,0BAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAMf,SAAS,EAAA,UAAA,EAAA,CAAA;kBAXrB,SAAS;+BACE,YAAY,EAAA,eAAA,EAGL,uBAAuB,CAAC,MAAM,WACtC,CAAC,gBAAgB,CAAC,EAAA,IAAA,EACrB;AACJ,wBAAA,KAAK,EAAE,YAAY;AACnB,wBAAA,kBAAkB,EAAE,gBAAgB;AACrC,qBAAA,EAAA,QAAA,EAAA,kRAAA,EAAA,MAAA,EAAA,CAAA,+VAAA,CAAA,EAAA;yRAmCmE,SAAS,EAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;AE7F/E;;;;;;;;;AASG;MAUU,eAAe,CAAA;IACjB,eAAe,GAAG,KAAK,CAAC,QAAQ;wFAAa;uGAD3C,eAAe,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAf,eAAe,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,eAAA,EAAA,EAAA,iBAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,eAAA,EAAA,QAAA,EAAA,EAAA,SAAA,EAAA,EAAA,OAAA,EAAA,8BAAA,EAAA,EAAA,UAAA,EAAA,EAAA,oBAAA,EAAA,4BAAA,EAAA,aAAA,EAAA,8DAAA,EAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAAf,eAAe,EAAA,UAAA,EAAA,CAAA;kBAT3B,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,mBAAmB;AAC7B,oBAAA,IAAI,EAAE;AACJ,wBAAA,eAAe,EAAE,QAAQ;AACzB,wBAAA,sBAAsB,EAAE,4BAA4B;AACpD,wBAAA,eAAe,EAAE,0DAA0D;AAC3E,wBAAA,SAAS,EAAE,8BAA8B;AAC1C,qBAAA;AACF,iBAAA;;;ACrBD;;;;;;;;;;;;;;;;;AAiBG;;ACjBH;;AAEG;;"}
|