@ktortu/aaa 0.1.0-beta.0 → 0.9.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 +23 -7
- package/cdk/styles/tabs.css +100 -21
- package/fesm2022/ktortu-aaa-button.mjs +18 -11
- package/fesm2022/ktortu-aaa-button.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-card.mjs +29 -4
- package/fesm2022/ktortu-aaa-card.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-cdk.mjs +58 -15
- package/fesm2022/ktortu-aaa-cdk.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-dialog.mjs +69 -12
- package/fesm2022/ktortu-aaa-dialog.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-forms.mjs +455 -260
- package/fesm2022/ktortu-aaa-forms.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-i18n.mjs +114 -0
- package/fesm2022/ktortu-aaa-i18n.mjs.map +1 -0
- package/fesm2022/ktortu-aaa-menu.mjs +38 -13
- package/fesm2022/ktortu-aaa-menu.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-tabs.mjs +319 -42
- package/fesm2022/ktortu-aaa-tabs.mjs.map +1 -1
- package/fesm2022/ktortu-aaa-tooltip.mjs +3 -2
- package/fesm2022/ktortu-aaa-tooltip.mjs.map +1 -1
- package/fesm2022/ktortu-aaa.mjs +1 -0
- package/fesm2022/ktortu-aaa.mjs.map +1 -1
- package/forms/radio/radio-group.css +3 -3
- package/forms/styles/field-box.css +150 -2
- package/forms/styles/tokens.css +3 -0
- package/menu/menu.css +8 -4
- package/package.json +5 -1
- package/types/ktortu-aaa-button.d.ts +22 -8
- package/types/ktortu-aaa-card.d.ts +24 -4
- package/types/ktortu-aaa-cdk.d.ts +38 -0
- package/types/ktortu-aaa-dialog.d.ts +45 -9
- package/types/ktortu-aaa-forms.d.ts +336 -149
- package/types/ktortu-aaa-i18n.d.ts +74 -0
- package/types/ktortu-aaa-menu.d.ts +15 -8
- package/types/ktortu-aaa-tabs.d.ts +130 -13
- package/types/ktortu-aaa-tooltip.d.ts +5 -0
- package/types/ktortu-aaa.d.ts +1 -0
|
@@ -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/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/tabs';\nexport * from '@ktortu/aaa/tooltip';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;;;;AAAA;;AAEG;;ACFH;;AAEG"}
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
/* Disposition des options : pilotable par token (colonne par défaut, ligne possible). */
|
|
25
25
|
.kt-radio-group__options {
|
|
26
26
|
display: flex;
|
|
27
|
-
flex-direction: var(--radio-group-direction,
|
|
27
|
+
flex-direction: var(--radio-group-direction, row);
|
|
28
28
|
flex-wrap: wrap;
|
|
29
|
-
gap: var(--radio-group-gap,
|
|
29
|
+
gap: var(--radio-group-gap, 1rem);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
.kt-radio-group__hint {
|
|
@@ -52,4 +52,4 @@
|
|
|
52
52
|
animation: none;
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
}
|
|
55
|
+
}
|
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
@layer kt-aaa.components {
|
|
2
|
-
/* Boîte de contrôle partagée par les champs simples (TextField, NumberField)
|
|
2
|
+
/* Boîte de contrôle partagée par les champs simples (TextField, NumberField) et la famille
|
|
3
|
+
Temporal (Date/Time/DateTime/YearMonth/Instant), qui réutilise la même `.kt-field-box`.
|
|
3
4
|
Globale + classes namespacées : partagée entre plusieurs composants, donc non scopable. */
|
|
4
5
|
kt-text-field,
|
|
5
|
-
kt-
|
|
6
|
+
kt-text-area,
|
|
7
|
+
kt-number-field,
|
|
8
|
+
kt-date-field,
|
|
9
|
+
kt-time-field,
|
|
10
|
+
kt-date-time-field,
|
|
11
|
+
kt-year-month-field,
|
|
12
|
+
kt-instant-field,
|
|
13
|
+
kt-select,
|
|
14
|
+
kt-multi-select {
|
|
6
15
|
display: block;
|
|
16
|
+
/* Largeur pilotable d'un coup via --field-width. Défaut `auto` : remplit le conteneur en
|
|
17
|
+
contexte bloc (formulaire), se dimensionne au contenu en flex. Surcharger sur :root ou un
|
|
18
|
+
conteneur pour fixer tous les champs (ex. --field-width: 320px). */
|
|
19
|
+
width: var(--field-width, auto);
|
|
7
20
|
}
|
|
8
21
|
|
|
9
22
|
.kt-field-box {
|
|
@@ -168,4 +181,139 @@
|
|
|
168
181
|
field-sizing: content;
|
|
169
182
|
resize: vertical;
|
|
170
183
|
}
|
|
184
|
+
|
|
185
|
+
/* =========================================================================
|
|
186
|
+
Apparence OUTLINE (opt-in via [appearance]="'outline'" ou KT_FIELD_CONFIG).
|
|
187
|
+
Label flottant qui se loge dans la bordure haute de la boîte (façon Material).
|
|
188
|
+
Rendu GLOBAL (et non dans field.css scopé) car il référence .kt-field-box*,
|
|
189
|
+
contenu PROJETÉ depuis le composant de champ — inatteignable en CSS scopé.
|
|
190
|
+
L'apparence par défaut (fill) n'est jamais touchée.
|
|
191
|
+
========================================================================= */
|
|
192
|
+
kt-field[data-appearance='outline'] {
|
|
193
|
+
position: relative;
|
|
194
|
+
margin-top: 0.5rem; /* espace pour le label une fois flotté au-dessus de la bordure */
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* Le header (label + aide) recouvre la boîte sans réserver de hauteur en flux. */
|
|
198
|
+
kt-field[data-appearance='outline'] .kt-field__header {
|
|
199
|
+
position: absolute;
|
|
200
|
+
inset: 0 0 auto 0;
|
|
201
|
+
height: var(--field-min-height, 44px);
|
|
202
|
+
margin: 0;
|
|
203
|
+
padding-inline: var(--field-padding-x, 0.75rem);
|
|
204
|
+
z-index: 1;
|
|
205
|
+
pointer-events: none; /* la boîte/l'input dessous restent cliquables */
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/* Label au repos = position « placeholder » (centré verticalement dans la boîte). */
|
|
209
|
+
kt-field[data-appearance='outline'] .kt-field__label {
|
|
210
|
+
position: absolute;
|
|
211
|
+
inset-inline-start: var(--field-padding-x, 0.75rem);
|
|
212
|
+
top: 50%;
|
|
213
|
+
transform: translateY(-50%);
|
|
214
|
+
transform-origin: left center;
|
|
215
|
+
max-width: calc(100% - 2 * var(--field-padding-x, 0.75rem));
|
|
216
|
+
overflow: hidden;
|
|
217
|
+
white-space: nowrap;
|
|
218
|
+
text-overflow: ellipsis;
|
|
219
|
+
background: transparent;
|
|
220
|
+
padding-inline: 0.25rem;
|
|
221
|
+
font-size: var(--field-font-size, 1rem);
|
|
222
|
+
font-weight: 400;
|
|
223
|
+
color: var(--field-hint-color, #5f6368);
|
|
224
|
+
transition: transform 0.15s ease, color 0.15s ease;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* RTL : `transform-origin` n'accepte pas de mot-clé logique → on bascule l'origine de la mise à
|
|
228
|
+
l'échelle vers le bord de départ (droite en RTL) pour rester aligné sur `inset-inline-start`. */
|
|
229
|
+
[dir='rtl'] kt-field[data-appearance='outline'] .kt-field__label {
|
|
230
|
+
transform-origin: right center;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/* Bouton d'aide : recliquable et calé à droite du header. */
|
|
234
|
+
kt-field[data-appearance='outline'] .kt-field__help {
|
|
235
|
+
margin-inline-start: auto;
|
|
236
|
+
pointer-events: auto;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/* Label flotté — DEUX règles séparées à dessein (dégradation gracieuse) : la 1re (focus / always)
|
|
240
|
+
reste valide même si le moteur ne supporte pas `:has()`. Une seule pseudo-classe inconnue dans une
|
|
241
|
+
liste de sélecteurs invaliderait TOUTE la liste → le label ne flotterait jamais, focus compris.
|
|
242
|
+
La 2nde ajoute les cas qui exigent `:has()` (input rempli, select `[data-filled]`). Les inputs
|
|
243
|
+
date/heure n'ayant pas de placeholder CSS, `:not(:placeholder-shown)` les garde flottés en permanence. */
|
|
244
|
+
kt-field[data-appearance='outline'][data-float-label='always'] .kt-field__label,
|
|
245
|
+
kt-field[data-appearance='outline']:focus-within .kt-field__label {
|
|
246
|
+
transform: translateY(-50%) translateY(calc(var(--field-min-height, 44px) / -2)) scale(0.75);
|
|
247
|
+
color: var(--field-label-color, inherit);
|
|
248
|
+
/* Fond du label flotté : masque la ligne d'outline sous le label. Défaut : fond PLEIN du champ.
|
|
249
|
+
Le consommateur peut poser un gradient (ex. `linear-gradient(transparent 50%, var(--field-bg) 50%)`)
|
|
250
|
+
via le token --field-label-float-bg. */
|
|
251
|
+
background: var(--field-label-float-bg, var(--field-bg, #fff));
|
|
252
|
+
}
|
|
253
|
+
kt-field[data-appearance='outline']:has(.kt-field-box[data-filled]) .kt-field__label,
|
|
254
|
+
kt-field[data-appearance='outline']:has(.kt-field-box__input:not(:placeholder-shown)) .kt-field__label {
|
|
255
|
+
transform: translateY(-50%) translateY(calc(var(--field-min-height, 44px) / -2)) scale(0.75);
|
|
256
|
+
color: var(--field-label-color, inherit);
|
|
257
|
+
background: var(--field-label-float-bg, var(--field-bg, #fff));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* Bordure de l'outline : token dédié (état de repos). Surcharge possible indépendamment du
|
|
261
|
+
mode `fill`. Les états hover/focus/invalid gardent leurs propres tokens (réaffirmés ici
|
|
262
|
+
pour rester prioritaires sur la règle de repos). */
|
|
263
|
+
kt-field[data-appearance='outline'] .kt-field-box {
|
|
264
|
+
border-color: var(--field-outline-border-color, var(--field-border-color, #c4c7c5));
|
|
265
|
+
}
|
|
266
|
+
kt-field[data-appearance='outline'] .kt-field-box:hover {
|
|
267
|
+
border-color: var(--field-border-color-hover, #5f6368);
|
|
268
|
+
}
|
|
269
|
+
kt-field[data-appearance='outline'] .kt-field-box:focus-within {
|
|
270
|
+
border-color: var(--field-border-color-focus, #0b57d0);
|
|
271
|
+
}
|
|
272
|
+
kt-field[data-appearance='outline'] .kt-field-box[data-invalid] {
|
|
273
|
+
border-color: var(--field-error-color, #b3261e);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* En outline AUTO, le label flottant tient lieu de placeholder au repos : on masque le placeholder
|
|
277
|
+
propre du select (sinon doublon avec le label en position « placeholder »). En ALWAYS, le label
|
|
278
|
+
est déjà en haut → on laisse le placeholder du select s'afficher. */
|
|
279
|
+
kt-field[data-appearance='outline']:not([data-float-label='always']) .kt-select__placeholder {
|
|
280
|
+
visibility: hidden;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/* En outline, le placeholder natif ne s'affiche QUE lorsque le label flotte : au repos le label
|
|
284
|
+
tient lieu de placeholder (sinon les deux se superposeraient). Masqué par défaut, révélé au
|
|
285
|
+
focus ou en floatLabel='always'. (Quand le champ est rempli, le navigateur ne le rend pas.) */
|
|
286
|
+
kt-field[data-appearance='outline'] .kt-field-box__input::placeholder {
|
|
287
|
+
color: transparent;
|
|
288
|
+
}
|
|
289
|
+
kt-field[data-appearance='outline']:focus-within .kt-field-box__input::placeholder,
|
|
290
|
+
kt-field[data-appearance='outline'][data-float-label='always'] .kt-field-box__input::placeholder {
|
|
291
|
+
color: var(--field-placeholder-color, var(--field-hint-color, #5f6368));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/* Accent au focus / état d'erreur. */
|
|
295
|
+
kt-field[data-appearance='outline']:focus-within .kt-field__label {
|
|
296
|
+
color: var(--field-border-color-focus, #0b57d0);
|
|
297
|
+
}
|
|
298
|
+
kt-field[data-appearance='outline']:has(.kt-field-box[data-invalid]) .kt-field__label {
|
|
299
|
+
color: var(--field-error-color, #b3261e);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
@media (prefers-reduced-motion: reduce) {
|
|
303
|
+
kt-field[data-appearance='outline'] .kt-field__label {
|
|
304
|
+
transition: none;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/* Contraste forcé (Windows High Contrast) : le fond du label flotté masque la bordure ; un gradient
|
|
309
|
+
custom `--field-label-float-bg` serait ignoré → on force une couleur système opaque pour garantir
|
|
310
|
+
le « notch ». Au repos le label est transparent (non listé), donc rien à forcer. */
|
|
311
|
+
@media (forced-colors: active) {
|
|
312
|
+
kt-field[data-appearance='outline'][data-float-label='always'] .kt-field__label,
|
|
313
|
+
kt-field[data-appearance='outline']:focus-within .kt-field__label,
|
|
314
|
+
kt-field[data-appearance='outline']:has(.kt-field-box[data-filled]) .kt-field__label,
|
|
315
|
+
kt-field[data-appearance='outline']:has(.kt-field-box__input:not(:placeholder-shown)) .kt-field__label {
|
|
316
|
+
background: Canvas;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
171
319
|
}
|
package/forms/styles/tokens.css
CHANGED
|
@@ -35,6 +35,9 @@
|
|
|
35
35
|
--field-padding-y: 0.5rem;
|
|
36
36
|
--field-gap: 0.375rem;
|
|
37
37
|
--field-control-gap: 0.5rem;
|
|
38
|
+
/* Largeur du champ : un seul réglage pilote tous les champs. Défaut `auto` (remplit le
|
|
39
|
+
conteneur en bloc, se dimensionne au contenu en flex). Ex. global : --field-width: 320px. */
|
|
40
|
+
--field-width: auto;
|
|
38
41
|
|
|
39
42
|
/* Typo */
|
|
40
43
|
--field-font-size: var(--kt-control-font);
|
package/menu/menu.css
CHANGED
|
@@ -42,8 +42,11 @@
|
|
|
42
42
|
[ktMenu] {
|
|
43
43
|
position: fixed;
|
|
44
44
|
inset: auto;
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
/* Dropdown sous le déclencheur, aligné sur son bord inline-start. On utilise `position-area`
|
|
46
|
+
et NON la fonction `anchor()` : `anchor()` résout mal une ancre imbriquée dans un sous-arbre
|
|
47
|
+
déjà ancré → les sous-menus s'EMPILENT dès le 3ᵉ niveau. `position-area` cascade correctement
|
|
48
|
+
à n'importe quelle profondeur (validé Chrome 125+ / Firefox 147+ / Safari 26+). */
|
|
49
|
+
position-area: block-end span-inline-end;
|
|
47
50
|
margin-block-start: var(--kt-menu-offset, 0.25rem);
|
|
48
51
|
/* Bascule de côté / au-dessus si le bas/droite manque de place. */
|
|
49
52
|
position-try-fallbacks:
|
|
@@ -61,8 +64,9 @@
|
|
|
61
64
|
--_submenu-offset: calc(
|
|
62
65
|
var(--kt-menu-padding, 0.25rem) + var(--kt-menu-border-width, 1px) + var(--kt-menu-submenu-gap, 0.375rem)
|
|
63
66
|
);
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
/* À l'inline-end de l'item parent, aligné sur son haut. `position-area` (et non `anchor()`)
|
|
68
|
+
pour cascader correctement à toute profondeur — cf. note sur le menu racine ci-dessus. */
|
|
69
|
+
position-area: inline-end span-block-end;
|
|
66
70
|
margin-block-start: 0;
|
|
67
71
|
margin-inline-start: var(--_submenu-offset);
|
|
68
72
|
position-try-fallbacks:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ktortu/aaa",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Bibliothèque de composants Angular headless + thémés par tokens CSS.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"angular",
|
|
@@ -77,6 +77,10 @@
|
|
|
77
77
|
"types": "./types/ktortu-aaa-forms.d.ts",
|
|
78
78
|
"default": "./fesm2022/ktortu-aaa-forms.mjs"
|
|
79
79
|
},
|
|
80
|
+
"./i18n": {
|
|
81
|
+
"types": "./types/ktortu-aaa-i18n.d.ts",
|
|
82
|
+
"default": "./fesm2022/ktortu-aaa-i18n.mjs"
|
|
83
|
+
},
|
|
80
84
|
"./menu": {
|
|
81
85
|
"types": "./types/ktortu-aaa-menu.d.ts",
|
|
82
86
|
"default": "./fesm2022/ktortu-aaa-menu.mjs"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { InjectionToken, AfterViewInit } from '@angular/core';
|
|
2
|
+
import { InjectionToken, AfterViewInit, Provider } from '@angular/core';
|
|
3
3
|
|
|
4
4
|
/** Axe "emphase" (apparence). */
|
|
5
5
|
type KtButtonMode = 'filled' | 'tonal' | 'outlined' | 'text';
|
|
@@ -7,13 +7,27 @@ type KtButtonMode = 'filled' | 'tonal' | 'outlined' | 'text';
|
|
|
7
7
|
type KtButtonColor = 'primary' | 'neutral' | 'danger';
|
|
8
8
|
/** Taille (la cible md ~44-48px vise le confort tactile / AAA). */
|
|
9
9
|
type KtButtonSize = 'sm' | 'md' | 'lg';
|
|
10
|
+
/** Défauts applicables à tous les `[ktButton]` (surchargeables par bouton via les inputs). */
|
|
10
11
|
interface KtButtonConfig {
|
|
12
|
+
/** Garde le bouton focusable même désactivé (via `aria-disabled`). */
|
|
11
13
|
disabledInteractive: boolean;
|
|
14
|
+
/** Emphase visuelle par défaut (apparence). */
|
|
12
15
|
mode: KtButtonMode;
|
|
16
|
+
/** Intention sémantique par défaut (couleur). */
|
|
13
17
|
color: KtButtonColor;
|
|
18
|
+
/** Taille par défaut. */
|
|
14
19
|
size: KtButtonSize;
|
|
15
20
|
}
|
|
16
21
|
declare const KT_BUTTON_CONFIG: InjectionToken<Partial<KtButtonConfig>>;
|
|
22
|
+
/**
|
|
23
|
+
* Fournit des défauts de bouton (mode/couleur/taille…) pour un sous-arbre ou l'application entière.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* providers: [provideKtButton({ mode: 'tonal', size: 'lg' })]
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
declare function provideKtButton(config: Partial<KtButtonConfig>): Provider;
|
|
17
31
|
/**
|
|
18
32
|
* Bouton ou lien stylé par la directive `ktButton`. À poser sur un `<button>`
|
|
19
33
|
* (action) ou un `<a>` (navigation) — l'accessibilité s'adapte automatiquement
|
|
@@ -40,23 +54,23 @@ declare class KtButton implements AfterViewInit {
|
|
|
40
54
|
/** Taille ; `md` vise une cible tactile ~44-48px. @default 'md' (ou KT_BUTTON_CONFIG.size) */
|
|
41
55
|
readonly size: _angular_core.InputSignal<KtButtonSize>;
|
|
42
56
|
/** Étire le bouton sur toute la largeur disponible. @default false */
|
|
43
|
-
readonly fullWidth: _angular_core.
|
|
57
|
+
readonly fullWidth: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
44
58
|
/** Bouton carré sans texte ; impose un nom accessible via `ariaLabel`. @default false */
|
|
45
59
|
readonly iconOnly: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
46
|
-
/** Nom accessible. Obligatoire si `iconOnly
|
|
60
|
+
/** Nom accessible. **Obligatoire si `iconOnly`** ; à défaut, l'`aria-label` natif est préservé. @default undefined */
|
|
47
61
|
readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
|
|
48
62
|
/** Attribut HTML natif (comportement formulaire), distinct de `mode`. @default 'button' */
|
|
49
63
|
readonly type: _angular_core.InputSignal<"button" | "submit" | "reset">;
|
|
50
64
|
/** Affiche l'état de chargement et rend le bouton inerte (`aria-busy`). @default false */
|
|
51
|
-
readonly loading: _angular_core.
|
|
52
|
-
/** Nom de l'icône (rendu via CSS `data-icon`). */
|
|
65
|
+
readonly loading: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
66
|
+
/** Nom de l'icône (rendu via CSS `data-icon`). @default undefined */
|
|
53
67
|
readonly icon: _angular_core.InputSignal<string | undefined>;
|
|
54
68
|
/** Position de l'icône relative au texte. @default 'start' */
|
|
55
69
|
readonly iconPosition: _angular_core.InputSignal<"start" | "end">;
|
|
56
70
|
/** Désactive le bouton. @default false */
|
|
57
|
-
readonly disabled: _angular_core.
|
|
71
|
+
readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
58
72
|
/** Garde le bouton focusable même désactivé (via `aria-disabled`). @default false (ou KT_BUTTON_CONFIG.disabledInteractive) */
|
|
59
|
-
readonly disabledInteractive: _angular_core.
|
|
73
|
+
readonly disabledInteractive: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
60
74
|
protected readonly isDisabled: _angular_core.Signal<boolean>;
|
|
61
75
|
protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
|
|
62
76
|
constructor();
|
|
@@ -66,5 +80,5 @@ declare class KtButton implements AfterViewInit {
|
|
|
66
80
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<KtButton, "button[ktButton], a[ktButton]", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "fullWidth": { "alias": "fullWidth"; "required": false; "isSignal": true; }; "iconOnly": { "alias": "iconOnly"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "type": { "alias": "type"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; "iconPosition": { "alias": "iconPosition"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "disabledInteractive": { "alias": "disabledInteractive"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
67
81
|
}
|
|
68
82
|
|
|
69
|
-
export { KT_BUTTON_CONFIG, KtButton };
|
|
83
|
+
export { KT_BUTTON_CONFIG, KtButton, provideKtButton };
|
|
70
84
|
export type { KtButtonColor, KtButtonConfig, KtButtonMode, KtButtonSize };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { InjectionToken, Provider } from '@angular/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* En-tête de la carte (rangée flex : média/avatar + titre + éventuelle action). Marqueur
|
|
@@ -67,6 +67,16 @@ declare class KtCardActions {
|
|
|
67
67
|
*
|
|
68
68
|
* Quand la carte ancêtre est `disabled`, le lien sort de l'ordre de tabulation (`tabindex="-1"`)
|
|
69
69
|
* et est annoncé `aria-disabled` : une carte inerte ne piège pas le focus clavier (WCAG 2.4.3).
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```html
|
|
73
|
+
* <article ktCard interactive>
|
|
74
|
+
* <div ktCardContent>
|
|
75
|
+
* <h3 id="t1">Titre</h3>
|
|
76
|
+
* <a ktCardLink routerLink="/detail" aria-labelledby="t1">Voir le détail</a>
|
|
77
|
+
* </div>
|
|
78
|
+
* </article>
|
|
79
|
+
* ```
|
|
70
80
|
*/
|
|
71
81
|
declare class KtCardLink {
|
|
72
82
|
private readonly host;
|
|
@@ -90,6 +100,15 @@ interface KtCardConfig {
|
|
|
90
100
|
variant: KtCardVariant;
|
|
91
101
|
}
|
|
92
102
|
declare const KT_CARD_CONFIG: InjectionToken<Partial<KtCardConfig>>;
|
|
103
|
+
/**
|
|
104
|
+
* Fournit des défauts de carte (apparence de surface) pour un sous-arbre ou l'application entière.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* providers: [provideKtCard({ variant: 'outlined' })]
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
declare function provideKtCard(config: Partial<KtCardConfig>): Provider;
|
|
93
112
|
/**
|
|
94
113
|
* Carte : SURFACE de contenu. Directive (pas de composant) posée sur l'élément SÉMANTIQUE choisi
|
|
95
114
|
* par le consommateur (`<article>`, `<section>`, `<li>`, `<a>`…) — la lib n'impose jamais de
|
|
@@ -117,6 +136,7 @@ declare const KT_CARD_CONFIG: InjectionToken<Partial<KtCardConfig>>;
|
|
|
117
136
|
declare class KtCard {
|
|
118
137
|
private readonly config;
|
|
119
138
|
private readonly host;
|
|
139
|
+
private readonly platformId;
|
|
120
140
|
/** Référence réactive sur le lien primaire de la carte */
|
|
121
141
|
readonly cardLink: i0.Signal<KtCardLink | undefined>;
|
|
122
142
|
/** Apparence de la surface : `elevated` | `outlined` | `filled`. @default 'elevated' (ou `KT_CARD_CONFIG.variant`) */
|
|
@@ -135,9 +155,9 @@ declare class KtCard {
|
|
|
135
155
|
|
|
136
156
|
/**
|
|
137
157
|
* Import ergonomique de toute la famille card en une fois :
|
|
138
|
-
* `imports: [
|
|
158
|
+
* `imports: [KtCardImports]` au lieu d'énumérer chaque directive.
|
|
139
159
|
*/
|
|
140
|
-
declare const
|
|
160
|
+
declare const KtCardImports: readonly [typeof KtCard, typeof KtCardHeader, typeof KtCardMedia, typeof KtCardContent, typeof KtCardActions, typeof KtCardLink];
|
|
141
161
|
|
|
142
|
-
export {
|
|
162
|
+
export { KT_CARD_CONFIG, KtCard, KtCardActions, KtCardContent, KtCardHeader, KtCardImports, KtCardLink, KtCardMedia, provideKtCard };
|
|
143
163
|
export type { KtCardConfig, KtCardVariant };
|
|
@@ -4,7 +4,9 @@ import * as _ktortu_aaa_cdk from '@ktortu/aaa/cdk';
|
|
|
4
4
|
|
|
5
5
|
/** Contrôleur de drag-to-dismiss d'une bottom-sheet. À câbler sur le `pointerdown` de la poignée. */
|
|
6
6
|
interface KtSheetDrag {
|
|
7
|
+
/** Démarre le suivi du glissement ; à brancher sur le `pointerdown` de la poignée. */
|
|
7
8
|
start(event: PointerEvent): void;
|
|
9
|
+
/** Détache les écouteurs et réinitialise l'état ; à appeler à la destruction. */
|
|
8
10
|
destroy(): void;
|
|
9
11
|
}
|
|
10
12
|
interface KtSheetDragOptions {
|
|
@@ -25,6 +27,18 @@ interface KtSheetDragOptions {
|
|
|
25
27
|
* Geste DOUBLÉ côté appelant par Échap + bouton Fermer + tap-extérieur (WCAG 2.5.1) : ce module ne
|
|
26
28
|
* gère que le glissement. Le gating « écran compact uniquement » reste à l'appelant (signal `isCompact`
|
|
27
29
|
* de `KtViewport`) — la primitive est volontairement agnostique.
|
|
30
|
+
*
|
|
31
|
+
* @param opts Élément à translater, callback de fermeture, classe de drag et seuil optionnel.
|
|
32
|
+
* @returns Un contrôleur {@link KtSheetDrag} (`start` à brancher sur `pointerdown`, `destroy` au teardown).
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* const drag = createKtSheetDrag({
|
|
36
|
+
* pane: () => paneEl(),
|
|
37
|
+
* onDismiss: () => dialogRef.close(),
|
|
38
|
+
* draggingClass: 'kt-sheet--dragging',
|
|
39
|
+
* });
|
|
40
|
+
* // <div class="handle" (pointerdown)="drag.start($event)"></div>
|
|
41
|
+
* ```
|
|
28
42
|
*/
|
|
29
43
|
declare function createKtSheetDrag(opts: KtSheetDragOptions): KtSheetDrag;
|
|
30
44
|
|
|
@@ -55,20 +69,28 @@ declare const KT_DEFAULT_BREAKPOINTS: KtBreakpoints;
|
|
|
55
69
|
declare const KT_BREAKPOINTS: InjectionToken<KtBreakpoints>;
|
|
56
70
|
/**
|
|
57
71
|
* À ajouter aux `providers` de `app.config.ts`. Fusionne avec les défauts → surcharge partielle OK.
|
|
72
|
+
* @param overrides Seuils à surcharger ; les clés absentes gardent leur défaut `KT_DEFAULT_BREAKPOINTS`.
|
|
73
|
+
* @returns Provider liant `KT_BREAKPOINTS` aux seuils fusionnés.
|
|
58
74
|
* @example provideKtBreakpoints({ tablet: 768, desktop: 1200 })
|
|
59
75
|
* @example provideKtBreakpoints({ tablet: '(min-width: 768px) and (orientation: landscape)' })
|
|
60
76
|
*/
|
|
61
77
|
declare function provideKtBreakpoints(overrides: Partial<KtBreakpoints>): Provider;
|
|
62
78
|
/** Trois chaînes de media queries résolues, prêtes pour `matchMedia` / `BreakpointObserver`. */
|
|
63
79
|
interface KtBreakpointMedia {
|
|
80
|
+
/** Media query de la bande mobile. */
|
|
64
81
|
mobile: string;
|
|
82
|
+
/** Media query de la bande tablette. */
|
|
65
83
|
tablet: string;
|
|
84
|
+
/** Media query de la bande desktop. */
|
|
66
85
|
desktop: string;
|
|
67
86
|
}
|
|
68
87
|
/**
|
|
69
88
|
* Convertit les seuils (nombres et/ou chaînes) en 3 media queries. Un palier-chaîne est repris
|
|
70
89
|
* verbatim ; un palier-nombre devient la bande `[plancher courant .. plancher suivant[`. Si le
|
|
71
90
|
* plancher suivant est une chaîne (pas de borne numérique), la bande reste ouverte de ce côté.
|
|
91
|
+
* @param bp Seuils responsive à convertir (nombres et/ou chaînes).
|
|
92
|
+
* @returns Les trois media queries résolues (`mobile`, `tablet`, `desktop`).
|
|
93
|
+
* @example resolveKtBreakpointMedia(KT_DEFAULT_BREAKPOINTS)
|
|
72
94
|
*/
|
|
73
95
|
declare function resolveKtBreakpointMedia(bp: KtBreakpoints): KtBreakpointMedia;
|
|
74
96
|
|
|
@@ -98,9 +120,25 @@ declare class KtViewport {
|
|
|
98
120
|
static ɵprov: i0.ɵɵInjectableDeclaration<KtViewport>;
|
|
99
121
|
}
|
|
100
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Génère des identifiants numériques incrémentaux uniques au sein de l'application, soit globalement,
|
|
125
|
+
* soit par préfixe (compteur dédié). Sert à construire des `anchor-name` / `id` stables et distincts.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```ts
|
|
129
|
+
* const idGen = inject(KtIdGenerator);
|
|
130
|
+
* const anchor = `--kt-menu-anchor-${idGen.generateId('menu')}`;
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
101
133
|
declare class KtIdGenerator {
|
|
102
134
|
private readonly counters;
|
|
103
135
|
private nextGlobalId;
|
|
136
|
+
/**
|
|
137
|
+
* Renvoie le prochain identifiant. Sans `prefix`, utilise le compteur global ; avec `prefix`,
|
|
138
|
+
* utilise un compteur dédié à ce préfixe (séquences indépendantes).
|
|
139
|
+
* @param prefix Clé optionnelle de compteur ; chaque préfixe a sa propre séquence.
|
|
140
|
+
* @returns Le compteur courant (number) pour la portée demandée, avant incrément.
|
|
141
|
+
*/
|
|
104
142
|
generateId(prefix?: string): number;
|
|
105
143
|
static ɵfac: i0.ɵɵFactoryDeclaration<KtIdGenerator, never>;
|
|
106
144
|
static ɵprov: i0.ɵɵInjectableDeclaration<KtIdGenerator>;
|
|
@@ -23,7 +23,10 @@ declare class KtDialogTitle {
|
|
|
23
23
|
private readonly host;
|
|
24
24
|
private readonly renderer;
|
|
25
25
|
private readonly idGen;
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Id de l'hôte câblé en `aria-labelledby` : préserve un id fourni par le consommateur, sinon en génère un.
|
|
28
|
+
* @default `host.id` ?? `dialogRef.config.ariaLabelledBy` ?? `kt-dialog-title-<généré>`
|
|
29
|
+
*/
|
|
27
30
|
readonly id: string;
|
|
28
31
|
constructor();
|
|
29
32
|
static ɵfac: i0.ɵɵFactoryDeclaration<KtDialogTitle, never>;
|
|
@@ -50,7 +53,10 @@ declare class KtDialogDescription implements OnInit, OnDestroy {
|
|
|
50
53
|
private readonly host;
|
|
51
54
|
private readonly renderer;
|
|
52
55
|
private readonly idGen;
|
|
53
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* Id de l'hôte câblé en `aria-describedby` : préserve un id fourni par le consommateur, sinon en génère un.
|
|
58
|
+
* @default `host.id` ?? `dialogRef.config.ariaDescribedBy` ?? `kt-dialog-desc-<généré>`
|
|
59
|
+
*/
|
|
54
60
|
readonly id: string;
|
|
55
61
|
constructor();
|
|
56
62
|
ngOnInit(): void;
|
|
@@ -190,12 +196,28 @@ declare class KtDialogSheetHandle {
|
|
|
190
196
|
* Pour focaliser un élément précis à l'ouverture (ex. éviter un bouton destructeur),
|
|
191
197
|
* passez `autoFocus: '[ktDialogFocusInitial]'` dans la config d'ouverture et posez la
|
|
192
198
|
* directive `ktDialogFocusInitial` sur la cible.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```ts
|
|
202
|
+
* // valeur de base, généralement consommée via provideKtDialogDefaults()
|
|
203
|
+
* provideKtDialogDefaults({ ...KT_DIALOG_AAA_DEFAULTS });
|
|
204
|
+
* ```
|
|
193
205
|
*/
|
|
194
206
|
declare const KT_DIALOG_AAA_DEFAULTS: DialogConfig;
|
|
195
207
|
/**
|
|
196
208
|
* Enregistre les valeurs par défaut AAA du dialog au niveau application.
|
|
197
209
|
* À ajouter aux `providers` de `app.config.ts`. `overrides` permet d'ajuster sans
|
|
198
210
|
* tout réécrire (ex. `provideKtDialogDefaults({ maxWidth: '40rem' })`).
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* ```ts
|
|
214
|
+
* // app.config.ts
|
|
215
|
+
* export const appConfig: ApplicationConfig = {
|
|
216
|
+
* providers: [provideKtDialogDefaults({ maxWidth: '40rem' })],
|
|
217
|
+
* };
|
|
218
|
+
* ```
|
|
219
|
+
* @param overrides Surcharges partielles fusionnées par-dessus `KT_DIALOG_AAA_DEFAULTS`.
|
|
220
|
+
* @returns Un `Provider` pour le token `DEFAULT_DIALOG_CONFIG`.
|
|
199
221
|
*/
|
|
200
222
|
declare function provideKtDialogDefaults(overrides?: Partial<DialogConfig>): Provider;
|
|
201
223
|
/**
|
|
@@ -215,6 +237,15 @@ type KtDialogPresentation = 'centered' | 'fullscreen' | 'sheet' | 'centered-full
|
|
|
215
237
|
* `centered-*`, l'appelant fournit `compact` (= `KtViewport.isCompact()`, largeur seule) — centré
|
|
216
238
|
* sur desktop, plein écran / sheet sur écran compact. Fonction pure (testable sans DOM).
|
|
217
239
|
* Appelée par `injectKtDialogOpener` à chaque ouverture ; exportée pour un usage direct éventuel.
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* ```ts
|
|
243
|
+
* resolveKtDialogPanelClass('sheet'); // ['kt-dialog', 'kt-dialog--sheet']
|
|
244
|
+
* resolveKtDialogPanelClass('centered-sheet', true); // bottom-sheet sur écran compact
|
|
245
|
+
* ```
|
|
246
|
+
* @param presentation Présentation choisie par le dev (responsive comprise). Défaut `'centered'`.
|
|
247
|
+
* @param compact `true` quand l'écran est compact (= `KtViewport.isCompact()`), pour résoudre les variantes `centered-*`. Défaut `false`.
|
|
248
|
+
* @returns La liste des classes CSS de la présentation concrète résolue.
|
|
218
249
|
*/
|
|
219
250
|
declare function resolveKtDialogPanelClass(presentation?: KtDialogPresentation, compact?: boolean): string[];
|
|
220
251
|
|
|
@@ -235,7 +266,7 @@ declare function resolveKtDialogPanelClass(presentation?: KtDialogPresentation,
|
|
|
235
266
|
*/
|
|
236
267
|
declare function injectKtDialogData<T>(): T;
|
|
237
268
|
/** Config d'ouverture sans le champ `data` (fourni séparément, typé), enrichie de `presentation`. */
|
|
238
|
-
type
|
|
269
|
+
type KtDialogOpenerConfig<D, R, C> = Omit<DialogConfig<D, DialogRef<R, C>>, 'data'> & {
|
|
239
270
|
/** Présentation du dialog (cf. `KtDialogPresentation`) — choisie par le dev. Résolue à CHAQUE
|
|
240
271
|
ouverture : les variantes responsive lisent le signal d'écran compact. Défaut : `'centered'`.
|
|
241
272
|
Combinée à un éventuel `panelClass` additionnel. */
|
|
@@ -258,15 +289,20 @@ type OpenerConfig<D, R, C> = Omit<DialogConfig<D, DialogRef<R, C>>, 'data'> & {
|
|
|
258
289
|
* // dans un composant/service consommateur
|
|
259
290
|
* private readonly openRename = injectRenameDialog();
|
|
260
291
|
* rename() { this.openRename({ currentName: 'X' }).closed.subscribe(n => { n: string | undefined }); }
|
|
292
|
+
*
|
|
293
|
+
* @param component Composant à monter dans le dialog.
|
|
294
|
+
* @param baseConfig Config d'ouverture par défaut (sans `data`), enrichie de `presentation` ; fusionnée à chaque ouverture.
|
|
295
|
+
* @returns Une closure d'ouverture typée : `() => DialogRef` (sans data) ou `(data, config?) => DialogRef` (avec data).
|
|
261
296
|
*/
|
|
262
|
-
declare function injectKtDialogOpener<C, R = unknown>(component: ComponentType<C>, baseConfig?:
|
|
263
|
-
declare function injectKtDialogOpener<C, D, R = unknown>(component: ComponentType<C>, baseConfig?:
|
|
297
|
+
declare function injectKtDialogOpener<C, R = unknown>(component: ComponentType<C>, baseConfig?: KtDialogOpenerConfig<void, R, C>): () => DialogRef<R, C>;
|
|
298
|
+
declare function injectKtDialogOpener<C, D, R = unknown>(component: ComponentType<C>, baseConfig?: KtDialogOpenerConfig<D, R, C>): (data: D, config?: KtDialogOpenerConfig<D, R, C>) => DialogRef<R, C>;
|
|
264
299
|
|
|
265
300
|
declare class KtDialogContainer extends CdkDialogContainer implements OnInit {
|
|
266
301
|
private readonly dialogRef;
|
|
267
302
|
private readonly elementRef;
|
|
268
303
|
private readonly host;
|
|
269
304
|
private readonly platformId;
|
|
305
|
+
private readonly destroyRef;
|
|
270
306
|
protected readonly isClosing: i0.WritableSignal<boolean>;
|
|
271
307
|
constructor();
|
|
272
308
|
ngOnInit(): void;
|
|
@@ -278,9 +314,9 @@ declare class KtDialogContainer extends CdkDialogContainer implements OnInit {
|
|
|
278
314
|
|
|
279
315
|
/**
|
|
280
316
|
* Import ergonomique de toute la famille dialog en une fois :
|
|
281
|
-
* `imports: [
|
|
317
|
+
* `imports: [KtDialogImports]` au lieu d'énumérer chaque directive structurelle.
|
|
282
318
|
*/
|
|
283
|
-
declare const
|
|
319
|
+
declare const KtDialogImports: readonly [typeof KtDialogHeader, typeof KtDialogTitle, typeof KtDialogDescription, typeof KtDialogContent, typeof KtDialogActions, typeof KtDialogClose, typeof KtDialogFocusInitial, typeof KtDialogSheetHandle];
|
|
284
320
|
|
|
285
|
-
export {
|
|
286
|
-
export type { KtDialogPresentation };
|
|
321
|
+
export { KT_DIALOG_AAA_DEFAULTS, KtDialogActions, KtDialogClose, KtDialogContainer, KtDialogContent, KtDialogDescription, KtDialogFocusInitial, KtDialogHeader, KtDialogImports, KtDialogSheetHandle, KtDialogTitle, injectKtDialogData, injectKtDialogOpener, provideKtDialogDefaults, resolveKtDialogPanelClass };
|
|
322
|
+
export type { KtDialogOpenerConfig, KtDialogPresentation };
|