@ktortu/aaa 0.1.0-beta.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.
Files changed (74) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +151 -0
  3. package/button/button-tokens.css +152 -0
  4. package/button/button.css +319 -0
  5. package/card/card-tokens.css +49 -0
  6. package/card/card.css +200 -0
  7. package/cdk/styles/foundation.css +83 -0
  8. package/cdk/styles/tabs.css +276 -0
  9. package/dialog/dialog.css +350 -0
  10. package/fesm2022/ktortu-aaa-button.mjs +128 -0
  11. package/fesm2022/ktortu-aaa-button.mjs.map +1 -0
  12. package/fesm2022/ktortu-aaa-card.mjs +209 -0
  13. package/fesm2022/ktortu-aaa-card.mjs.map +1 -0
  14. package/fesm2022/ktortu-aaa-cdk.mjs +183 -0
  15. package/fesm2022/ktortu-aaa-cdk.mjs.map +1 -0
  16. package/fesm2022/ktortu-aaa-dialog.mjs +512 -0
  17. package/fesm2022/ktortu-aaa-dialog.mjs.map +1 -0
  18. package/fesm2022/ktortu-aaa-forms.mjs +3215 -0
  19. package/fesm2022/ktortu-aaa-forms.mjs.map +1 -0
  20. package/fesm2022/ktortu-aaa-menu.mjs +315 -0
  21. package/fesm2022/ktortu-aaa-menu.mjs.map +1 -0
  22. package/fesm2022/ktortu-aaa-tabs.mjs +79 -0
  23. package/fesm2022/ktortu-aaa-tabs.mjs.map +1 -0
  24. package/fesm2022/ktortu-aaa-tooltip.mjs +356 -0
  25. package/fesm2022/ktortu-aaa-tooltip.mjs.map +1 -0
  26. package/fesm2022/ktortu-aaa.mjs +17 -0
  27. package/fesm2022/ktortu-aaa.mjs.map +1 -0
  28. package/forms/checkbox/checkbox-group.css +55 -0
  29. package/forms/checkbox/checkbox.css +216 -0
  30. package/forms/chips/chip-list.css +70 -0
  31. package/forms/chips/chip.css +92 -0
  32. package/forms/chips/tokens.css +102 -0
  33. package/forms/field/field.css +87 -0
  34. package/forms/multi-select/multi-select.css +136 -0
  35. package/forms/radio/radio-group.css +55 -0
  36. package/forms/radio/radio.css +165 -0
  37. package/forms/styles/field-box.css +171 -0
  38. package/forms/styles/select-panel.css +464 -0
  39. package/forms/styles/tokens.css +67 -0
  40. package/forms/switch/switch.css +188 -0
  41. package/menu/menu-tokens.css +58 -0
  42. package/menu/menu.css +224 -0
  43. package/package.json +96 -0
  44. package/styles/button.css +6 -0
  45. package/styles/card.css +6 -0
  46. package/styles/dialog.css +6 -0
  47. package/styles/forms.css +13 -0
  48. package/styles/foundation.css +7 -0
  49. package/styles/menu.css +6 -0
  50. package/styles/styles.css +24 -0
  51. package/styles/tabs.css +5 -0
  52. package/styles/tooltip.css +5 -0
  53. package/themes/theme-ant.css +44 -0
  54. package/themes/theme-architecte.css +83 -0
  55. package/themes/theme-aurora.css +97 -0
  56. package/themes/theme-bootstrap.css +46 -0
  57. package/themes/theme-carbon.css +49 -0
  58. package/themes/theme-catppuccin.css +66 -0
  59. package/themes/theme-cyberpunk.css +211 -0
  60. package/themes/theme-fluent.css +45 -0
  61. package/themes/theme-material-you.css +74 -0
  62. package/themes/theme-material.css +48 -0
  63. package/themes/theme-primer.css +46 -0
  64. package/themes/theme-vegetal.css +78 -0
  65. package/tooltip/tooltip.css +129 -0
  66. package/types/ktortu-aaa-button.d.ts +70 -0
  67. package/types/ktortu-aaa-card.d.ts +143 -0
  68. package/types/ktortu-aaa-cdk.d.ts +110 -0
  69. package/types/ktortu-aaa-dialog.d.ts +286 -0
  70. package/types/ktortu-aaa-forms.d.ts +1574 -0
  71. package/types/ktortu-aaa-menu.d.ts +171 -0
  72. package/types/ktortu-aaa-tabs.d.ts +27 -0
  73. package/types/ktortu-aaa-tooltip.d.ts +90 -0
  74. package/types/ktortu-aaa.d.ts +8 -0
@@ -0,0 +1,74 @@
1
+ /* Thème « Material You » (light) — LA démo du DYNAMIC COLOR par tokens seuls.
2
+ Différence avec le thème « Material 3 » (baseline statique) : ici, TOUTE la palette
3
+ DÉRIVE d'un unique seed (--myou-seed) via les couleurs relatives CSS
4
+ (`oklch(from var(--myou-seed) L C h)`). Changer le seed recolore tout le système —
5
+ c'est le principe Material You (couleur extraite du fond d'écran).
6
+
7
+ Garantie AA PAR CONSTRUCTION (équivalent du système tonal M3) : le seed ne fournit
8
+ que la TEINTE (h) — la luminosité L et le chroma C de chaque rôle sont FIGÉS ici,
9
+ calqués sur les tons M3 (40 pour les fills, 90+ pour les surfaces, 10-25 pour les
10
+ textes). Les ratios restent donc valides quel que soit le seed.
11
+ NB : les tokens étant déclarés (et donc calculés) sur <html>, le seed se surcharge
12
+ à CE niveau (autre règle ou style inline sur html) — pas sur un sous-arbre.
13
+
14
+ Le danger reste la palette d'erreur M3 STATIQUE (#b3261e) : conforme au vrai
15
+ Material You, qui ne dérive pas l'erreur du seed. */
16
+ [data-theme='material-you'] {
17
+ /* ============ LE token : tout dérive de lui ============ */
18
+ --myou-seed: #0b6e63; /* teal — essayez #7c4dff, #b3261e, #386a20… */
19
+
20
+ /* ============ Socle (tons M3 figés, teinte du seed) ============ */
21
+ --kt-surface: oklch(from var(--myou-seed) 0.985 0.008 h); /* tone ~98, teinté */
22
+ --kt-on-surface: oklch(from var(--myou-seed) 0.22 0.02 h); /* tone ~10 */
23
+ --kt-muted: oklch(from var(--myou-seed) 0.42 0.03 h); /* neutral-variant ~30 */
24
+ --kt-outline: oklch(from var(--myou-seed) 0.55 0.03 h); /* tone ~50 (3:1 non-texte) */
25
+ --kt-outline-strong: oklch(from var(--myou-seed) 0.45 0.04 h);
26
+ --kt-primary: oklch(from var(--myou-seed) 0.46 0.09 h); /* tone ~40 : blanc ≥ 6:1 */
27
+ --kt-danger: #b3261e; /* erreur M3 statique (non dérivée — fidèle à You) */
28
+ --kt-neutral: oklch(from var(--myou-seed) 0.4 0.02 h); /* neutre teinté, blanc ≥ 7:1 */
29
+ --kt-focus-ring-color: oklch(from var(--myou-seed) 0.46 0.09 h);
30
+ --kt-font: 'Roboto', system-ui, sans-serif;
31
+
32
+ /* ============ Géométrie : rondeurs expressives ============ */
33
+ --kt-control-radius: 12px;
34
+ --btn-radius: 999px; /* pilule M3 */
35
+ --kt-sheet-radius: 28px;
36
+
37
+ /* ============ Champs : surface-container teintée (la signature You) ============ */
38
+ --field-bg: oklch(from var(--myou-seed) 0.94 0.02 h); /* tone ~94 */
39
+ --field-focus-ring: color-mix(in srgb, oklch(from var(--myou-seed) 0.46 0.09 h) 55%, transparent);
40
+ --field-transition: border-color 150ms ease;
41
+
42
+ /* ============ Boutons : containers/fg dérivés par la lib depuis les 3 bases ============ */
43
+ --btn-tonal-weight: 18%; /* containers un peu plus présents que le défaut */
44
+ /* on-containers teintés par le seed (tone ~25 sur container ~90 : ≥ 8:1 par construction) —
45
+ les défauts statiques de la lib resteraient AA mais d'une teinte étrangère au seed. */
46
+ --btn-on-primary-container: oklch(from var(--myou-seed) 0.25 0.06 h);
47
+ --btn-on-neutral-container: oklch(from var(--myou-seed) 0.25 0.02 h);
48
+
49
+ /* ============ Caret + sélection ============ */
50
+ --field-caret-color: oklch(from var(--myou-seed) 0.46 0.09 h);
51
+ --kt-selection-bg: oklch(from var(--myou-seed) 0.88 0.05 h); /* container ~tone 90 */
52
+ --kt-selection-fg: oklch(from var(--myou-seed) 0.25 0.05 h);
53
+
54
+ /* ============ Select / tooltip ============ */
55
+ --select-popup-bg: oklch(from var(--myou-seed) 0.97 0.01 h);
56
+ --select-popup-shadow: 0 4px 16px oklch(from var(--myou-seed) 0.3 0.04 h / 25%);
57
+ --kt-sheet-scrim: oklch(from var(--myou-seed) 0.2 0.03 h / 50%);
58
+ --kt-sheet-shadow: 0 -4px 16px oklch(from var(--myou-seed) 0.3 0.04 h / 22%); /* élévation M3 teintée */
59
+ --tooltip-bg: oklch(from var(--myou-seed) 0.27 0.03 h);
60
+ --tooltip-fg: oklch(from var(--myou-seed) 0.96 0.01 h);
61
+
62
+ /* ============ Dialog (M3 expressive : rayon hérité de la feuille, sans bord) ============ */
63
+ --dialog-bg: oklch(from var(--myou-seed) 0.97 0.01 h); /* surface-container teinté */
64
+ --dialog-radius: 28px;
65
+ --dialog-border-width: 0;
66
+
67
+ /* ============ Card (M3 expressive : surfaces teintées du seed, rayon 16) ============ */
68
+ --card-radius: 16px;
69
+ --card-bg: oklch(from var(--myou-seed) 0.97 0.01 h);
70
+ --card-filled-bg: oklch(from var(--myou-seed) 0.94 0.02 h);
71
+ --card-shadow: 0 1px 3px oklch(from var(--myou-seed) 0.3 0.04 h / 20%);
72
+ --card-shadow-hover: 0 2px 8px oklch(from var(--myou-seed) 0.3 0.04 h / 26%);
73
+ --card-transition: box-shadow 150ms ease;
74
+ }
@@ -0,0 +1,48 @@
1
+ /* Thème « Material 3 » (baseline light) — palette M3 officielle (seed #6750A4).
2
+ Uniquement des redéclarations de tokens : champs outlined 4px, boutons pilule
3
+ (bascule --btn-radius prévue par le contrat), surfaces teintées M3. */
4
+ [data-theme='material'] {
5
+ /* ============ Socle (rôles M3 baseline) ============ */
6
+ --kt-primary: #6750a4; /* primary — on-primary blanc ~5.6:1 */
7
+ --kt-neutral: #625b71; /* secondary — blanc ~6.9:1 */
8
+ --kt-danger: #b3261e; /* error (= défaut lib, explicite) */
9
+ --kt-surface: #fef7ff;
10
+ --kt-on-surface: #1d1b20;
11
+ --kt-muted: #49454f; /* on-surface-variant, ~9:1 */
12
+ --kt-outline: #79747e;
13
+ --kt-outline-strong: #49454f;
14
+ --kt-font: 'Roboto', system-ui, sans-serif;
15
+
16
+ /* ============ Géométrie ============ */
17
+ --kt-control-radius: 4px; /* champs outlined M3 (extra-small) */
18
+ --btn-radius: 999px; /* boutons pilule + icon-only cercle ; n'affecte pas les champs */
19
+ --chip-radius: 8px;
20
+
21
+ /* ============ Boutons ============ */
22
+ --btn-font-weight: 500; /* label-large M3 (rétrofit lot 6) */
23
+ /* on-containers M3 sur les containers dérivés (≈ primary/secondary-container). */
24
+ --btn-on-primary-container: #21005d;
25
+ --btn-on-neutral-container: #1d192b;
26
+
27
+ /* ============ Champs ============ */
28
+ --field-transition: border-color 150ms ease; /* state transitions M3 (rétrofit lot 3) */
29
+
30
+ /* ============ Select / tooltip ============ */
31
+ --select-popup-bg: #f3edf7; /* surface-container */
32
+ --tooltip-bg: #322f35; /* inverse-surface */
33
+ --tooltip-fg: #f5eff7; /* inverse-on-surface */
34
+
35
+ /* ============ Dialog (M3 : grand rayon, élévation, sans bord) ============ */
36
+ --dialog-bg: #f3edf7; /* surface-container-high */
37
+ --dialog-radius: 28px;
38
+ --dialog-border-width: 0;
39
+ --dialog-shadow: 0 8px 24px rgb(29 27 32 / 22%);
40
+
41
+ /* ============ Card (M3 : surface-container, rayon 12, élévation douce) ============ */
42
+ --card-radius: 12px;
43
+ --card-bg: #f3edf7; /* surface-container */
44
+ --card-filled-bg: #ece6f0; /* surface-container-high */
45
+ --card-shadow: 0 1px 3px rgb(29 27 32 / 16%), 0 1px 2px rgb(29 27 32 / 12%);
46
+ --card-shadow-hover: 0 2px 6px rgb(29 27 32 / 22%);
47
+ --card-transition: box-shadow 150ms ease;
48
+ }
@@ -0,0 +1,46 @@
1
+ /* Thème « GitHub Primer » (light) — palette Primer officielle.
2
+ Uniquement des redéclarations de tokens : radius 6px uniforme, ombres subtiles
3
+ (inset sur les champs, 1px sous les boutons), accent #0969da.
4
+ NB : on garde --kt-control-height: 44px (cible tactile de la lib) plutôt que
5
+ les 32px de Primer — exigence d'accessibilité du projet. */
6
+ [data-theme='primer'] {
7
+ /* ============ Socle ============ */
8
+ --kt-primary: #0969da; /* accent.fg — blanc ~5.2:1 */
9
+ --kt-danger: #cf222e; /* danger.fg */
10
+ --kt-neutral: #57606a; /* fg.muted historique — blanc ~6.3:1 */
11
+ --kt-surface: #ffffff;
12
+ --kt-on-surface: #1f2328; /* fg.default */
13
+ --kt-muted: #59636e; /* fg.muted, ~5.7:1 */
14
+ --kt-outline: #d0d7de; /* border.default */
15
+ --kt-outline-strong: #818b98;
16
+ --kt-focus-ring-color: #0969da;
17
+ /* Stack système GitHub authentique (le produit n'embarque pas de webfont). */
18
+ --kt-font: -apple-system, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;
19
+
20
+ /* ============ Géométrie ============ */
21
+ --kt-control-radius: 6px;
22
+ --btn-radius: 6px; /* 6px uniforme toutes tailles (pas de radius par taille chez Primer) */
23
+
24
+ /* ============ Boutons ============ */
25
+ --btn-tonal-weight: 12%; /* containers plus discrets, à la Primer */
26
+ --btn-font-weight: 500; /* les boutons GitHub sont en medium (rétrofit lot 6) */
27
+
28
+ /* ============ Ombres ============ */
29
+ --field-shadow: inset 0 1px 0 rgb(31 35 40 / 4%); /* inner shadow subtile des inputs Primer */
30
+ --btn-shadow: 0 1px 0 rgb(31 35 40 / 4%); /* hérite vers hover/focus via le fallback chaîné */
31
+ --select-popup-shadow: 0 8px 24px rgb(140 149 159 / 20%); /* shadow.medium */
32
+
33
+ /* ============ Tooltip ============ */
34
+ --tooltip-bg: #25292e;
35
+ --tooltip-fg: #ffffff;
36
+
37
+ /* ============ Dialog (GitHub : rayon 12, bord net) ============ */
38
+ --dialog-radius: 12px;
39
+ --dialog-border-color: #d0d7de;
40
+
41
+ /* ============ Card (GitHub Box : rayon 6, filet + ombre discrète) ============ */
42
+ --card-radius: 6px;
43
+ --card-border-color: #d0d7de;
44
+ --card-filled-bg: #f6f8fa; /* canvas.subtle */
45
+ --card-shadow: 0 1px 0 rgb(31 35 40 / 4%), 0 1px 3px rgb(31 35 40 / 6%);
46
+ }
@@ -0,0 +1,78 @@
1
+ /* Thème « Végétal » (light) — conçu pour une app agricole (gestion de plantations,
2
+ biosolutions) : utilisable en extérieur (light, contrastes solides en plein soleil),
3
+ palette naturelle — crème lin, vert feuille, terracotta (alerte organique, pas un rouge
4
+ d'erreur criard), brun écorce — formes organiques (champs 12px, boutons pilule « graine »),
5
+ ombres douces vert-de-gris. Uniquement des redéclarations de tokens. */
6
+ [data-theme='vegetal'] {
7
+ /* ============ Socle ============ */
8
+ --kt-primary: #36743f; /* vert feuille — blanc 5.6:1, texte sur crème 5.1:1 */
9
+ --kt-danger: #b04a2e; /* terracotta — blanc 5.4:1 */
10
+ --kt-neutral: #6b5d4a; /* brun écorce — blanc 6.4:1 */
11
+ --kt-surface: #f5f3e8; /* crème lin */
12
+ --kt-on-surface: #2a3326; /* vert mousse très foncé, ~12:1 */
13
+ --kt-muted: #5b6a51; /* vert-de-gris, 5.2:1 */
14
+ --kt-outline: #7d8a69; /* tige sèche (3.2:1 non-texte) */
15
+ --kt-outline-strong: #5b6a51;
16
+ --kt-focus-ring-color: #36743f;
17
+ --kt-font: 'Quicksand', ui-rounded, 'Trebuchet MS', sans-serif; /* arrondie, organique */
18
+
19
+ /* Gouttière organique : thumb tige sèche (outline) sur une rainure crème un ton sous le lin. */
20
+ --kt-scrollbar-color: #7d8a69 #e7e3d2;
21
+
22
+ /* ============ Géométrie organique ============ */
23
+ --kt-control-radius: 12px; /* champs galets */
24
+ --btn-radius: 999px; /* boutons graine (pilule) + icon-only cercle */
25
+ --btn-corner-shape: squircle; /* superellipse : la pilule devient une « gousse » charnue */
26
+ --chip-radius: 14px 4px 14px 4px; /* chips en FEUILLE (haut-gauche/bas-droite ronds) */
27
+ --kt-sheet-radius: 20px;
28
+
29
+ /* ============ Champs ============ */
30
+ --field-bg: #fdfcf5; /* papier clair, en relief sur le lin */
31
+ /* Forme FEUILLE : radius par coin (haut-gauche/bas-droite ronds, les deux autres pincés).
32
+ Possible depuis toujours — les tokens radius acceptent 4 valeurs (audit lot 6). */
33
+ --field-radius: 16px 4px 16px 4px;
34
+ --field-shadow-focus: 0 2px 10px rgb(54 116 63 / 22%); /* halo de sève discret */
35
+ --field-transition: border-color 150ms ease, box-shadow 150ms ease; /* sève qui monte en douceur */
36
+ --field-caret-color: #36743f;
37
+ --kt-selection-bg: #36743f;
38
+ --kt-selection-fg: #ffffff;
39
+
40
+ /* ============ Boutons ============ */
41
+ --btn-tonal-weight: 18%; /* containers « jeune pousse » un peu présents */
42
+ --btn-on-primary-container: #1f4a28;
43
+ --btn-on-danger-container: #6e2a18;
44
+ --btn-on-neutral-container: #3a3328;
45
+ --btn-shadow: 0 1px 3px rgb(42 51 38 / 14%); /* légère assise, comme posé sur la terre */
46
+ --btn-shadow-hover: 0 4px 14px rgb(54 116 63 / 22%); /* halo de sève au survol */
47
+ --btn-transition: transform 150ms ease, box-shadow 150ms ease;
48
+ --btn-transform-hover: translateY(-2px) scale(1.01); /* la pousse lève ET gonfle */
49
+ --btn-transform-active: scale(0.98);
50
+
51
+ /* ============ Select / tooltip ============ */
52
+ --select-popup-bg: #fdfcf5;
53
+ --select-popup-shadow: 0 8px 24px rgb(42 51 38 / 18%);
54
+ --kt-sheet-scrim: rgb(42 51 38 / 40%);
55
+ --kt-sheet-shadow: 0 -8px 24px rgb(42 51 38 / 18%); /* assise douce vert-de-gris */
56
+ --tooltip-bg: #33402c; /* sous-bois */
57
+ --tooltip-fg: #eef2e4;
58
+
59
+ /* ============ Dialog (organique : feuille à l'échelle du dialog, ombre douce héritée) ============ */
60
+ --dialog-radius: 24px 6px 24px 6px;
61
+ --dialog-border-color: #cfd6bf;
62
+
63
+ /* ============ Card : FEUILLE organique (coins asymétriques, assise teintée sève, se déploie) ============ */
64
+ --card-radius: 20px 6px 20px 6px;
65
+ --card-bg: #fdfcf5;
66
+ --card-filled-bg: #eef0e2;
67
+ --card-shadow: 0 4px 16px rgb(54 116 63 / 14%), 0 1px 3px rgb(42 51 38 / 10%); /* assise + sève */
68
+ --card-shadow-hover: 0 10px 26px rgb(54 116 63 / 20%), 0 2px 6px rgb(42 51 38 / 12%);
69
+ --card-transition: transform 150ms ease, box-shadow 150ms ease;
70
+ --card-transform-hover: translateY(-2px) scale(1.01); /* la feuille se déploie */
71
+ }
72
+
73
+ /* Profondeur de feuille sur les boutons FILLED : voile SOMBRE subtil en bas-droite (assombrit
74
+ => contraste du label blanc préservé), empilé sous le voile d'état. Filled uniquement (sur
75
+ transparent il ferait une bavure). Disabled : la lib force background-image: none. */
76
+ [data-theme='vegetal'] [ktButton][data-mode='filled'] {
77
+ --btn-fill-image: linear-gradient(155deg, transparent 50%, rgb(18 38 22 / 16%));
78
+ }
@@ -0,0 +1,129 @@
1
+ @layer kt-aaa.components {
2
+ /* Styles de la directive Tooltip ([ktTooltip]) — Popover API + CSS Anchor Positioning.
3
+ Global obligatoire : l'élément tooltip est ajouté au <body> (top-layer), hors de toute vue. */
4
+
5
+ .kt-tooltip {
6
+ /* Même architecture que le reste de la lib : tokens --tooltip-* dérivés du socle --kt-*
7
+ (fallbacks en dur si le socle n'est pas chargé). Surcharger un --kt-* rethématise donc
8
+ le tooltip en même temps que les champs, boutons et dialog. */
9
+ --tooltip-bg: var(--kt-surface, #ffffff);
10
+ --tooltip-fg: var(--kt-on-surface, #1f1f1f);
11
+ --tooltip-border-color: var(--kt-outline, #c4c7c5);
12
+ --tooltip-radius: 6px;
13
+ --tooltip-pad-block: 0.4rem;
14
+ --tooltip-pad-inline: 0.6rem;
15
+ --tooltip-gap: 0.5rem; /* distance trigger ↔ tooltip */
16
+ --tooltip-max-width: 18rem;
17
+
18
+ margin: 0;
19
+ width: max-content;
20
+ max-width: var(--tooltip-max-width);
21
+ padding: var(--tooltip-pad-block) var(--tooltip-pad-inline);
22
+ border: 1px solid var(--tooltip-border-color);
23
+ border-radius: var(--tooltip-radius);
24
+ background: var(--tooltip-bg);
25
+ color: var(--tooltip-fg);
26
+ font-size: 0.85rem;
27
+ line-height: 1.35;
28
+ white-space: pre-line; /* Interprète les \n et les sauts de ligne dans les chaînes de texte */
29
+ box-shadow: 0 4px 12px color-mix(in srgb, #000 25%, transparent);
30
+ pointer-events: auto; /* requis pour le « hoverable » (WCAG 1.4.13) */
31
+ user-select: text; /* Corrigé : Permet la sélection et traduction du texte */
32
+ cursor: default;
33
+ }
34
+
35
+ /* Placement piloté par l'attribut data-position posé par la directive. */
36
+ .kt-tooltip[data-position='top'] {
37
+ position-area: top;
38
+ justify-self: anchor-center;
39
+ margin-bottom: var(--tooltip-gap);
40
+ position-try-fallbacks: --flip-bottom;
41
+ }
42
+ .kt-tooltip[data-position='bottom'] {
43
+ position-area: bottom;
44
+ justify-self: anchor-center;
45
+ margin-top: var(--tooltip-gap);
46
+ position-try-fallbacks: --flip-top;
47
+ }
48
+ .kt-tooltip[data-position='left'] {
49
+ position-area: left;
50
+ align-self: anchor-center;
51
+ margin-right: var(--tooltip-gap);
52
+ position-try-fallbacks: --flip-right;
53
+ }
54
+ .kt-tooltip[data-position='right'] {
55
+ position-area: right;
56
+ align-self: anchor-center;
57
+ margin-left: var(--tooltip-gap);
58
+ position-try-fallbacks: --flip-left;
59
+ }
60
+
61
+ /* Retournement automatique près des bords du viewport. */
62
+ @position-try --flip-bottom {
63
+ position-area: bottom;
64
+ margin: var(--tooltip-gap) 0 0 0;
65
+ }
66
+ @position-try --flip-top {
67
+ position-area: top;
68
+ margin: 0 0 var(--tooltip-gap) 0;
69
+ }
70
+ @position-try --flip-right {
71
+ position-area: right;
72
+ margin: 0 0 0 var(--tooltip-gap);
73
+ }
74
+ @position-try --flip-left {
75
+ position-area: left;
76
+ margin: 0 var(--tooltip-gap) 0 0;
77
+ }
78
+
79
+ /* Contenu riche non-interactif (listes de champs manquants, règles de mot de passe…). */
80
+ .kt-tooltip :is(ul, ol) {
81
+ margin: 0.25rem 0 0;
82
+ padding-left: 1.1rem;
83
+ }
84
+ .kt-tooltip li {
85
+ margin: 0.1rem 0;
86
+ }
87
+ .kt-tooltip p {
88
+ margin: 0.25rem 0 0;
89
+ }
90
+ .kt-tooltip strong {
91
+ display: block;
92
+ }
93
+
94
+ /* Transition en top-layer : display/overlay sont discrets → allow-discrete + @starting-style.
95
+ --tooltip-anim-duration : token de BASCULE (non déclaré => 120ms). Durée seule — le shorthand
96
+ reste en dur (les parts overlay/display allow-discrete sont structurelles). */
97
+ .kt-tooltip {
98
+ opacity: 0;
99
+ scale: 0.96;
100
+ transition:
101
+ opacity var(--tooltip-anim-duration, 120ms) ease,
102
+ scale var(--tooltip-anim-duration, 120ms) ease,
103
+ overlay var(--tooltip-anim-duration, 120ms) allow-discrete,
104
+ display var(--tooltip-anim-duration, 120ms) allow-discrete;
105
+ }
106
+ .kt-tooltip:popover-open {
107
+ opacity: 1;
108
+ scale: 1;
109
+ }
110
+ @starting-style {
111
+ .kt-tooltip:popover-open {
112
+ opacity: 0;
113
+ scale: 0.96;
114
+ }
115
+ }
116
+
117
+ @media (prefers-reduced-motion: reduce) {
118
+ .kt-tooltip {
119
+ transition: none;
120
+ scale: 1;
121
+ }
122
+ @starting-style {
123
+ .kt-tooltip:popover-open {
124
+ opacity: 1;
125
+ scale: 1;
126
+ }
127
+ }
128
+ }
129
+ }
@@ -0,0 +1,70 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { InjectionToken, AfterViewInit } from '@angular/core';
3
+
4
+ /** Axe "emphase" (apparence). */
5
+ type KtButtonMode = 'filled' | 'tonal' | 'outlined' | 'text';
6
+ /** Axe "intention" (couleur sémantique). */
7
+ type KtButtonColor = 'primary' | 'neutral' | 'danger';
8
+ /** Taille (la cible md ~44-48px vise le confort tactile / AAA). */
9
+ type KtButtonSize = 'sm' | 'md' | 'lg';
10
+ interface KtButtonConfig {
11
+ disabledInteractive: boolean;
12
+ mode: KtButtonMode;
13
+ color: KtButtonColor;
14
+ size: KtButtonSize;
15
+ }
16
+ declare const KT_BUTTON_CONFIG: InjectionToken<Partial<KtButtonConfig>>;
17
+ /**
18
+ * Bouton ou lien stylé par la directive `ktButton`. À poser sur un `<button>`
19
+ * (action) ou un `<a>` (navigation) — l'accessibilité s'adapte automatiquement
20
+ * (un `<a>` désactivé bascule sur `aria-disabled` plutôt que `disabled`).
21
+ *
22
+ * @example
23
+ * ```html
24
+ * <button ktButton mode="filled" color="primary">Enregistrer</button>
25
+ * <a ktButton mode="text" href="/aide">Aide</a>
26
+ * <button ktButton iconOnly icon="close" ariaLabel="Fermer"></button>
27
+ * ```
28
+ */
29
+ declare class KtButton implements AfterViewInit {
30
+ private readonly config;
31
+ private readonly host;
32
+ private readonly platformId;
33
+ private readonly viewInitialized;
34
+ protected readonly isLink: boolean;
35
+ private readonly nativeAriaLabel;
36
+ /** Emphase visuelle du bouton (apparence, ≠ `type`). @default 'filled' (ou KT_BUTTON_CONFIG.mode) */
37
+ readonly mode: _angular_core.InputSignal<KtButtonMode>;
38
+ /** Intention sémantique (couleur). @default 'primary' (ou KT_BUTTON_CONFIG.color) */
39
+ readonly color: _angular_core.InputSignal<KtButtonColor>;
40
+ /** Taille ; `md` vise une cible tactile ~44-48px. @default 'md' (ou KT_BUTTON_CONFIG.size) */
41
+ readonly size: _angular_core.InputSignal<KtButtonSize>;
42
+ /** Étire le bouton sur toute la largeur disponible. @default false */
43
+ readonly fullWidth: _angular_core.InputSignal<boolean>;
44
+ /** Bouton carré sans texte ; impose un nom accessible via `ariaLabel`. @default false */
45
+ readonly iconOnly: _angular_core.InputSignalWithTransform<boolean, unknown>;
46
+ /** Nom accessible. Obligatoire si `iconOnly` ; à défaut, l'`aria-label` natif est préservé. */
47
+ readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
48
+ /** Attribut HTML natif (comportement formulaire), distinct de `mode`. @default 'button' */
49
+ readonly type: _angular_core.InputSignal<"button" | "submit" | "reset">;
50
+ /** Affiche l'état de chargement et rend le bouton inerte (`aria-busy`). @default false */
51
+ readonly loading: _angular_core.InputSignal<boolean>;
52
+ /** Nom de l'icône (rendu via CSS `data-icon`). */
53
+ readonly icon: _angular_core.InputSignal<string | undefined>;
54
+ /** Position de l'icône relative au texte. @default 'start' */
55
+ readonly iconPosition: _angular_core.InputSignal<"start" | "end">;
56
+ /** Désactive le bouton. @default false */
57
+ readonly disabled: _angular_core.InputSignal<boolean>;
58
+ /** Garde le bouton focusable même désactivé (via `aria-disabled`). @default false (ou KT_BUTTON_CONFIG.disabledInteractive) */
59
+ readonly disabledInteractive: _angular_core.InputSignal<boolean>;
60
+ protected readonly isDisabled: _angular_core.Signal<boolean>;
61
+ protected readonly resolvedAriaLabel: _angular_core.Signal<string | null>;
62
+ constructor();
63
+ ngAfterViewInit(): void;
64
+ protected haltDisabledEvents(event: Event): void;
65
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<KtButton, never>;
66
+ 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
+ }
68
+
69
+ export { KT_BUTTON_CONFIG, KtButton };
70
+ export type { KtButtonColor, KtButtonConfig, KtButtonMode, KtButtonSize };
@@ -0,0 +1,143 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken } from '@angular/core';
3
+
4
+ /**
5
+ * En-tête de la carte (rangée flex : média/avatar + titre + éventuelle action). Marqueur
6
+ * structurel sans logique — la mise en forme vit dans `card.css` via `[ktCardHeader]`.
7
+ * L'ÉTIQUETTE accessible reste le titre fourni par le consommateur (`<h3 id>` + `aria-labelledby`
8
+ * sur l'hôte), comme [ktDialogTitle] pour le dialog : on sépare layout et sémantique.
9
+ *
10
+ * @example
11
+ * ```html
12
+ * <header ktCardHeader><h3 id="t1">Titre</h3></header>
13
+ * ```
14
+ */
15
+ declare class KtCardHeader {
16
+ static ɵfac: i0.ɵɵFactoryDeclaration<KtCardHeader, never>;
17
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KtCardHeader, "[ktCardHeader]", never, {}, {}, never, never, true, never>;
18
+ }
19
+ /**
20
+ * Média pleine largeur (image/vidéo). Marqueur structurel sans logique : `card.css` lui donne le
21
+ * full-bleed (marge négative = padding de la carte) et `[ktCard]` clippe au rayon quand un média
22
+ * est présent. À envelopper autour d'un `<img ngSrc>` (NgOptimizedImage).
23
+ *
24
+ * @example
25
+ * ```html
26
+ * <div ktCardMedia><img ngSrc="cover.jpg" width="400" height="200" alt="" /></div>
27
+ * ```
28
+ */
29
+ declare class KtCardMedia {
30
+ static ɵfac: i0.ɵɵFactoryDeclaration<KtCardMedia, never>;
31
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KtCardMedia, "[ktCardMedia]", never, {}, {}, never, never, true, never>;
32
+ }
33
+ /**
34
+ * Corps de la carte. Marqueur structurel sans logique : la mise en forme (rythme vertical) vit
35
+ * dans `card.css` via `[ktCardContent]`.
36
+ *
37
+ * @example
38
+ * ```html
39
+ * <div ktCardContent>Texte de la carte.</div>
40
+ * ```
41
+ */
42
+ declare class KtCardContent {
43
+ static ɵfac: i0.ɵɵFactoryDeclaration<KtCardContent, never>;
44
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KtCardContent, "[ktCardContent]", never, {}, {}, never, never, true, never>;
45
+ }
46
+ /**
47
+ * Barre d'actions de la carte (rangée de boutons/liens). Marqueur structurel sans logique :
48
+ * la mise en forme (flex, gap, épinglée en pied) vit dans `card.css` via `[ktCardActions]`.
49
+ *
50
+ * @example
51
+ * ```html
52
+ * <footer ktCardActions><button ktButton>Action</button></footer>
53
+ * ```
54
+ */
55
+ declare class KtCardActions {
56
+ static ɵfac: i0.ɵɵFactoryDeclaration<KtCardActions, never>;
57
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KtCardActions, "[ktCardActions]", never, {}, {}, never, never, true, never>;
58
+ }
59
+ /**
60
+ * Lien (ou bouton) PRIMAIRE d'une carte interactive : pattern « lien étiré » (Inclusive
61
+ * Components). Un pseudo-élément `::after` couvre toute la carte (cf. `card.css`) → toute la
62
+ * surface est cliquable, SANS imbriquer de contrôles interactifs (anti-pattern WCAG 4.1.2). Les
63
+ * actions secondaires de la carte repassent au-dessus du lien (z-index dans `card.css`).
64
+ *
65
+ * UN SEUL [ktCardLink] par carte. Le focus clavier est porté sur ce lien ; l'anneau de focus est
66
+ * relayé sur toute la carte (`[ktCard]:has([ktCardLink]:focus-visible)`).
67
+ *
68
+ * Quand la carte ancêtre est `disabled`, le lien sort de l'ordre de tabulation (`tabindex="-1"`)
69
+ * et est annoncé `aria-disabled` : une carte inerte ne piège pas le focus clavier (WCAG 2.4.3).
70
+ */
71
+ declare class KtCardLink {
72
+ private readonly host;
73
+ /**
74
+ * Carte ancêtre, injectée optionnellement via `inject(Card, { optional: true })` (DI par
75
+ * hiérarchie d'éléments) : `null` si [ktCardLink] est utilisé hors d'une [ktCard]. Sert à relayer
76
+ * l'état `disabled` de la carte (aria-disabled / tabindex) sans planter hors contexte.
77
+ */
78
+ protected readonly card: KtCard | null;
79
+ handleClick(event: Event): void;
80
+ constructor();
81
+ static ɵfac: i0.ɵɵFactoryDeclaration<KtCardLink, never>;
82
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KtCardLink, "a[ktCardLink], button[ktCardLink]", never, {}, {}, never, never, true, never>;
83
+ }
84
+
85
+ /** Axe "apparence" de la surface. */
86
+ type KtCardVariant = 'elevated' | 'outlined' | 'filled';
87
+ /** Défauts applicables à toutes les `[ktCard]` (surchargeables par carte via les inputs). */
88
+ interface KtCardConfig {
89
+ /** Apparence par défaut de la surface. */
90
+ variant: KtCardVariant;
91
+ }
92
+ declare const KT_CARD_CONFIG: InjectionToken<Partial<KtCardConfig>>;
93
+ /**
94
+ * Carte : SURFACE de contenu. Directive (pas de composant) posée sur l'élément SÉMANTIQUE choisi
95
+ * par le consommateur (`<article>`, `<section>`, `<li>`, `<a>`…) — la lib n'impose jamais de
96
+ * wrapper non sémantique ni de rôle (cf. précédent Dialog : la sémantique appartient à l'hôte).
97
+ *
98
+ * Trois axes pilotés en `data-*` (même contrat que ktButton) :
99
+ * - variant : data-variant = elevated | outlined | filled (apparence)
100
+ * - interactive : data-interactive (affordance hover/focus — PAS un rôle ; la cible cliquable
101
+ * est un [ktCardLink], lien/bouton primaire au lien étiré)
102
+ * - disabled : data-disabled (surface inerte)
103
+ *
104
+ * La mise en forme (layout des marqueurs, lien étiré, états) vit dans `card.css` ; les couleurs
105
+ * et la géométrie dérivent du socle `--kt-*` via `card-tokens.css`.
106
+ *
107
+ * @example
108
+ * ```html
109
+ * <article ktCard variant="outlined" interactive>
110
+ * <div ktCardContent>
111
+ * <h3 id="t1">Titre</h3>
112
+ * <a ktCardLink routerLink="/detail" aria-labelledby="t1">Voir le détail</a>
113
+ * </div>
114
+ * </article>
115
+ * ```
116
+ */
117
+ declare class KtCard {
118
+ private readonly config;
119
+ private readonly host;
120
+ /** Référence réactive sur le lien primaire de la carte */
121
+ readonly cardLink: i0.Signal<KtCardLink | undefined>;
122
+ /** Apparence de la surface : `elevated` | `outlined` | `filled`. @default 'elevated' (ou `KT_CARD_CONFIG.variant`) */
123
+ readonly variant: i0.InputSignal<KtCardVariant>;
124
+ /**
125
+ * Affordance visuelle d'élément cliquable (hover/focus). N'AJOUTE pas de rôle : un lien/bouton
126
+ * primaire ([ktCardLink]) porte l'interaction et le nom accessible. @default false
127
+ */
128
+ readonly interactive: i0.InputSignalWithTransform<boolean, unknown>;
129
+ /** Rend la surface inerte (état `data-disabled`). @default false */
130
+ readonly disabled: i0.InputSignalWithTransform<boolean, unknown>;
131
+ constructor();
132
+ static ɵfac: i0.ɵɵFactoryDeclaration<KtCard, never>;
133
+ static ɵdir: i0.ɵɵDirectiveDeclaration<KtCard, "[ktCard]", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; }, {}, ["cardLink"], never, true, never>;
134
+ }
135
+
136
+ /**
137
+ * Import ergonomique de toute la famille card en une fois :
138
+ * `imports: [KT_CARD]` au lieu d'énumérer chaque directive.
139
+ */
140
+ declare const KT_CARD: readonly [typeof KtCard, typeof KtCardHeader, typeof KtCardMedia, typeof KtCardContent, typeof KtCardActions, typeof KtCardLink];
141
+
142
+ export { KT_CARD, KT_CARD_CONFIG, KtCard, KtCardActions, KtCardContent, KtCardHeader, KtCardLink, KtCardMedia };
143
+ export type { KtCardConfig, KtCardVariant };