@zevra/ui 0.4.0 → 0.5.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 (82) hide show
  1. package/README.md +64 -1
  2. package/dist/actions.d.ts +41 -0
  3. package/dist/actions.d.ts.map +1 -0
  4. package/dist/actions.js +24 -0
  5. package/dist/actions.js.map +1 -0
  6. package/dist/catalogue.d.ts +30 -0
  7. package/dist/catalogue.d.ts.map +1 -0
  8. package/dist/catalogue.js +830 -0
  9. package/dist/catalogue.js.map +1 -0
  10. package/dist/content.d.ts +135 -0
  11. package/dist/content.d.ts.map +1 -0
  12. package/dist/content.js +85 -0
  13. package/dist/content.js.map +1 -0
  14. package/dist/css-inline.d.ts +11 -0
  15. package/dist/css-inline.d.ts.map +1 -0
  16. package/dist/css-inline.js +13 -0
  17. package/dist/css-inline.js.map +1 -0
  18. package/dist/cx.d.ts +16 -0
  19. package/dist/cx.d.ts.map +1 -0
  20. package/dist/cx.js +20 -0
  21. package/dist/cx.js.map +1 -0
  22. package/dist/data.d.ts +136 -0
  23. package/dist/data.d.ts.map +1 -0
  24. package/dist/data.js +98 -0
  25. package/dist/data.js.map +1 -0
  26. package/dist/feedback.d.ts +88 -0
  27. package/dist/feedback.d.ts.map +1 -0
  28. package/dist/feedback.js +38 -0
  29. package/dist/feedback.js.map +1 -0
  30. package/dist/forms.d.ts +120 -0
  31. package/dist/forms.d.ts.map +1 -0
  32. package/dist/forms.js +60 -0
  33. package/dist/forms.js.map +1 -0
  34. package/dist/icon-data.d.ts +6 -0
  35. package/dist/icon-data.d.ts.map +1 -0
  36. package/dist/icon-data.js +77 -0
  37. package/dist/icon-data.js.map +1 -0
  38. package/dist/icon.d.ts +33 -0
  39. package/dist/icon.d.ts.map +1 -0
  40. package/dist/icon.js +13 -0
  41. package/dist/icon.js.map +1 -0
  42. package/dist/index.d.ts +13 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +41 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/layout.d.ts +166 -0
  47. package/dist/layout.d.ts.map +1 -0
  48. package/dist/layout.js +120 -0
  49. package/dist/layout.js.map +1 -0
  50. package/dist/navigation.d.ts +150 -0
  51. package/dist/navigation.d.ts.map +1 -0
  52. package/dist/navigation.js +104 -0
  53. package/dist/navigation.js.map +1 -0
  54. package/dist/overlays.d.ts +68 -0
  55. package/dist/overlays.d.ts.map +1 -0
  56. package/dist/overlays.js +114 -0
  57. package/dist/overlays.js.map +1 -0
  58. package/dist/surfaces.d.ts +61 -0
  59. package/dist/surfaces.d.ts.map +1 -0
  60. package/dist/surfaces.js +54 -0
  61. package/dist/surfaces.js.map +1 -0
  62. package/dist/typography.d.ts +89 -0
  63. package/dist/typography.d.ts.map +1 -0
  64. package/dist/typography.js +76 -0
  65. package/dist/typography.js.map +1 -0
  66. package/package.json +36 -4
  67. package/react/actions.tsx +138 -0
  68. package/react/catalogue.tsx +1644 -0
  69. package/react/content.tsx +313 -0
  70. package/react/css-inline.ts +14 -0
  71. package/react/cx.ts +20 -0
  72. package/react/data.tsx +300 -0
  73. package/react/feedback.tsx +229 -0
  74. package/react/forms.tsx +383 -0
  75. package/react/icon-data.ts +114 -0
  76. package/react/icon.tsx +84 -0
  77. package/react/index.ts +42 -0
  78. package/react/layout.tsx +347 -0
  79. package/react/navigation.tsx +329 -0
  80. package/react/overlays.tsx +237 -0
  81. package/react/surfaces.tsx +161 -0
  82. package/react/typography.tsx +220 -0
@@ -0,0 +1,89 @@
1
+ import type { ElementType, HTMLAttributes, ReactNode } from 'react';
2
+ type Div = Omit<HTMLAttributes<HTMLElement>, 'className'>;
3
+ type Span = Omit<HTMLAttributes<HTMLSpanElement>, 'className'>;
4
+ export type TitreTaille = 'h1' | 'h2' | 'h2-sm' | 'h2-cta' | 'h3' | 'carte';
5
+ export interface HeadingProps extends Div {
6
+ taille?: TitreTaille;
7
+ /** Balise réellement rendue. Par défaut, celle qui correspond à la taille. */
8
+ as?: ElementType;
9
+ className?: string;
10
+ children?: ReactNode;
11
+ }
12
+ export declare function Heading({ taille, as, className, ...reste }: HeadingProps): import("react").JSX.Element;
13
+ export declare const H1: (p: Omit<HeadingProps, 'taille'>) => import("react").JSX.Element;
14
+ export declare const H2: (p: Omit<HeadingProps, 'taille'>) => import("react").JSX.Element;
15
+ export declare const H3: (p: Omit<HeadingProps, 'taille'>) => import("react").JSX.Element;
16
+ export declare const CardTitle: (p: Omit<HeadingProps, 'taille'>) => import("react").JSX.Element;
17
+ /** Chiffre ou mot posé pour sa PRÉSENCE, hors de la hiérarchie des titres —
18
+ * d'où le `<div>` : un chiffre géant annoncé comme titre de section pollue
19
+ * le plan du document. */
20
+ export declare function Display({ className, ...reste }: Div & {
21
+ className?: string;
22
+ }): import("react").JSX.Element;
23
+ export interface BodyProps extends Div {
24
+ taille?: 'normal' | 'lg' | 'dense';
25
+ as?: ElementType;
26
+ className?: string;
27
+ children?: ReactNode;
28
+ }
29
+ export declare function Body({ taille, as, className, ...reste }: BodyProps): import("react").JSX.Element;
30
+ /** Chapô : le paragraphe qui suit immédiatement un titre de section. */
31
+ export declare function Lead({ as, className, ...reste }: Div & {
32
+ as?: ElementType;
33
+ className?: string;
34
+ }): import("react").JSX.Element;
35
+ /** Mention légale, précision de bas de bloc. */
36
+ export declare function Note({ as, className, ...reste }: Div & {
37
+ as?: ElementType;
38
+ className?: string;
39
+ }): import("react").JSX.Element;
40
+ /** Signature de marque, sous un logo. */
41
+ export declare function Tagline({ className, ...reste }: Span & {
42
+ className?: string;
43
+ }): import("react").JSX.Element;
44
+ /** Mise en valeur dans le fil du texte. Le pendant `surSombre` existe parce
45
+ * que l'indigo d'accent devient illisible sur la bande manifeste. */
46
+ export declare function Em({ surSombre, className, ...reste }: Span & {
47
+ surSombre?: boolean;
48
+ className?: string;
49
+ }): import("react").JSX.Element;
50
+ export declare function Link({ className, ...reste }: Omit<HTMLAttributes<HTMLAnchorElement>, 'className'> & {
51
+ className?: string;
52
+ href?: string;
53
+ }): import("react").JSX.Element;
54
+ export interface KickerProps extends Div {
55
+ /** `center` centre le bloc, `stack` empile le filet AU-DESSUS du texte au
56
+ * lieu de le poser devant. */
57
+ variante?: 'center' | 'stack';
58
+ /** Le filet de spectre 56×2 devant le kicker. Premier des trois emplois
59
+ * autorisés du spectre. */
60
+ filet?: boolean;
61
+ surSombre?: boolean;
62
+ className?: string;
63
+ children?: ReactNode;
64
+ }
65
+ export declare function Kicker({ variante, filet, surSombre, className, children, ...reste }: KickerProps): import("react").JSX.Element;
66
+ /** Le filet de spectre seul. Décoratif : masqué aux lecteurs d'écran. */
67
+ export declare function Spec({ petit, surSombre, className, ...reste }: Span & {
68
+ petit?: boolean;
69
+ surSombre?: boolean;
70
+ className?: string;
71
+ }): import("react").JSX.Element;
72
+ /** Filet neutre de séparation de section. */
73
+ export declare function Rule({ className, ...reste }: Div & {
74
+ className?: string;
75
+ }): import("react").JSX.Element;
76
+ export interface MonoProps extends Span {
77
+ /** Le ton, pas la taille : `label` est le gris d'intitulé, `ink` l'encre
78
+ * pleine, `muted` le gris secondaire, `on-dark` la bande manifeste. */
79
+ ton?: 'label' | 'ink' | 'muted' | 'on-dark';
80
+ /** Le plus petit palier — badge dense, compteur de coque. */
81
+ micro?: boolean;
82
+ className?: string;
83
+ }
84
+ /** Capitales espacées. ⚠️ Réservé aux LIBELLÉS : une date ou un nom de
85
+ * fichier passés en capitales espacées deviennent illisibles et s'alignent
86
+ * mal — pour ceux-là, c'est `Meta` (bas de casse, chasse tabulaire). */
87
+ export declare function Mono({ ton, micro, className, ...reste }: MonoProps): import("react").JSX.Element;
88
+ export {};
89
+ //# sourceMappingURL=typography.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typography.d.ts","sourceRoot":"","sources":["../react/typography.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cx } from './cx.js';
3
+ const CLASSE_TITRE = {
4
+ h1: 'zv-h1',
5
+ h2: 'zv-h2',
6
+ 'h2-sm': 'zv-h2 zv-h2--sm',
7
+ 'h2-cta': 'zv-h2 zv-h2--cta',
8
+ h3: 'zv-h3',
9
+ carte: 'zv-card-title',
10
+ };
11
+ const BALISE_PAR_DEFAUT = {
12
+ h1: 'h1',
13
+ h2: 'h2',
14
+ 'h2-sm': 'h2',
15
+ 'h2-cta': 'h2',
16
+ h3: 'h3',
17
+ carte: 'h3',
18
+ };
19
+ export function Heading({ taille = 'h2', as, className, ...reste }) {
20
+ const Balise = as ?? BALISE_PAR_DEFAUT[taille];
21
+ return _jsx(Balise, { className: cx(CLASSE_TITRE[taille], className), ...reste });
22
+ }
23
+ export const H1 = (p) => _jsx(Heading, { taille: "h1", ...p });
24
+ export const H2 = (p) => _jsx(Heading, { taille: "h2", ...p });
25
+ export const H3 = (p) => _jsx(Heading, { taille: "h3", ...p });
26
+ export const CardTitle = (p) => (_jsx(Heading, { taille: "carte", ...p }));
27
+ /** Chiffre ou mot posé pour sa PRÉSENCE, hors de la hiérarchie des titres —
28
+ * d'où le `<div>` : un chiffre géant annoncé comme titre de section pollue
29
+ * le plan du document. */
30
+ export function Display({ className, ...reste }) {
31
+ return _jsx("div", { className: cx('zv-display', className), ...reste });
32
+ }
33
+ export function Body({ taille = 'normal', as, className, ...reste }) {
34
+ const Balise = as ?? 'p';
35
+ return (_jsx(Balise, { className: cx('zv-body', taille === 'lg' && 'zv-body--lg', taille === 'dense' && 'zv-body--dense', className), ...reste }));
36
+ }
37
+ /** Chapô : le paragraphe qui suit immédiatement un titre de section. */
38
+ export function Lead({ as, className, ...reste }) {
39
+ const Balise = as ?? 'p';
40
+ return _jsx(Balise, { className: cx('zv-lead', className), ...reste });
41
+ }
42
+ /** Mention légale, précision de bas de bloc. */
43
+ export function Note({ as, className, ...reste }) {
44
+ const Balise = as ?? 'p';
45
+ return _jsx(Balise, { className: cx('zv-note', className), ...reste });
46
+ }
47
+ /** Signature de marque, sous un logo. */
48
+ export function Tagline({ className, ...reste }) {
49
+ return _jsx("span", { className: cx('zv-tagline', className), ...reste });
50
+ }
51
+ /** Mise en valeur dans le fil du texte. Le pendant `surSombre` existe parce
52
+ * que l'indigo d'accent devient illisible sur la bande manifeste. */
53
+ export function Em({ surSombre, className, ...reste }) {
54
+ return (_jsx("em", { className: cx('zv-em', surSombre && 'zv-em--on-dark', className), ...reste }));
55
+ }
56
+ export function Link({ className, ...reste }) {
57
+ return _jsx("a", { className: cx('zv-link', className), ...reste });
58
+ }
59
+ export function Kicker({ variante, filet = true, surSombre, className, children, ...reste }) {
60
+ return (_jsxs("div", { className: cx('zv-kicker', variante && `zv-kicker--${variante}`, className), ...reste, children: [filet && _jsx(Spec, { surSombre: surSombre }), children] }));
61
+ }
62
+ /** Le filet de spectre seul. Décoratif : masqué aux lecteurs d'écran. */
63
+ export function Spec({ petit, surSombre, className, ...reste }) {
64
+ return (_jsx("span", { "aria-hidden": "true", className: cx('zv-spec', petit && 'zv-spec--sm', surSombre && 'zv-spec--on-dark', className), ...reste }));
65
+ }
66
+ /** Filet neutre de séparation de section. */
67
+ export function Rule({ className, ...reste }) {
68
+ return _jsx("div", { className: cx('zv-rule', className), ...reste });
69
+ }
70
+ /** Capitales espacées. ⚠️ Réservé aux LIBELLÉS : une date ou un nom de
71
+ * fichier passés en capitales espacées deviennent illisibles et s'alignent
72
+ * mal — pour ceux-là, c'est `Meta` (bas de casse, chasse tabulaire). */
73
+ export function Mono({ ton, micro, className, ...reste }) {
74
+ return (_jsx("span", { className: cx('zv-mono', ton && `zv-mono--${ton}`, micro && 'zv-mono--micro', className), ...reste }));
75
+ }
76
+ //# sourceMappingURL=typography.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typography.js","sourceRoot":"","sources":["../react/typography.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zevra/ui",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Design system Zevra « Encre & Papier » — tokens, CSS des composants et logos officiels.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -16,11 +16,24 @@
16
16
  "url": "https://github.com/zevra-tech/zevra-ui/issues"
17
17
  },
18
18
  "type": "module",
19
+ "packageManager": "pnpm@10.29.3",
19
20
  "sideEffects": [
20
21
  "*.css"
21
22
  ],
22
23
  "exports": {
23
24
  ".": "./tokens/index.js",
25
+ "./react": {
26
+ "types": "./dist/index.d.ts",
27
+ "default": "./dist/index.js"
28
+ },
29
+ "./react/catalogue": {
30
+ "types": "./dist/catalogue.d.ts",
31
+ "default": "./dist/catalogue.js"
32
+ },
33
+ "./react/css": {
34
+ "types": "./dist/css-inline.d.ts",
35
+ "default": "./dist/css-inline.js"
36
+ },
24
37
  "./css": "./src/index.css",
25
38
  "./tokens.css": "./src/tokens.css",
26
39
  "./fonts.css": "./src/fonts.css",
@@ -42,6 +55,8 @@
42
55
  "files": [
43
56
  "src",
44
57
  "tokens",
58
+ "dist",
59
+ "react",
45
60
  "logos",
46
61
  "icons",
47
62
  "demo",
@@ -49,14 +64,31 @@
49
64
  "DECISIONS.md"
50
65
  ],
51
66
  "scripts": {
52
- "test": "vitest run"
67
+ "build": "node scripts/build-icon-react.mjs && node scripts/build-css-bundle.mjs && tsc -p tsconfig.json",
68
+ "test": "npm run build && vitest run",
69
+ "prepublishOnly": "npm run build"
53
70
  },
54
71
  "devDependencies": {
72
+ "@types/react": "^19.2.18",
73
+ "@types/react-dom": "^19.2.5",
74
+ "react": "^19.2.8",
75
+ "react-dom": "^19.2.8",
76
+ "typescript": "^7.0.2",
55
77
  "vitest": "^3.2.4"
56
78
  },
57
79
  "keywords": [
58
80
  "zevra",
59
81
  "design-system",
60
- "design-tokens"
61
- ]
82
+ "design-tokens",
83
+ "react",
84
+ "components"
85
+ ],
86
+ "peerDependencies": {
87
+ "react": ">=18"
88
+ },
89
+ "peerDependenciesMeta": {
90
+ "react": {
91
+ "optional": true
92
+ }
93
+ }
62
94
  }
@@ -0,0 +1,138 @@
1
+ // Actions — boutons et liens.
2
+ //
3
+ // AUCUN « use client » : ce ne sont que des <button> et des <a> habillés. Le
4
+ // déclarer en ferait des composants client chez tous les consommateurs Next,
5
+ // et leurs pages perdraient le rendu serveur pour rien.
6
+
7
+ import type {
8
+ AnchorHTMLAttributes,
9
+ ButtonHTMLAttributes,
10
+ HTMLAttributes,
11
+ ReactNode,
12
+ } from 'react'
13
+ import { cx } from './cx.js'
14
+
15
+ /** Variantes de bouton. Une seule pleine par écran — c'est la règle de charte. */
16
+ export type BoutonVariante = 'plein' | 'fantome' | 'encre'
17
+
18
+ const VARIANTE_BOUTON: Record<BoutonVariante, string> = {
19
+ plein: 'zv-btn',
20
+ fantome: 'zv-btn--ghost',
21
+ encre: 'zv-btn--ink',
22
+ }
23
+
24
+ export interface ButtonProps
25
+ extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {
26
+ variante?: BoutonVariante
27
+ /** Hauteur réduite, pour une barre de navigation. */
28
+ compact?: boolean
29
+ /** Pleine largeur — l'appel à l'action d'un écran mobile. */
30
+ bloc?: boolean
31
+ /** Échappatoire assumée. À employer pour un ajustement de position, jamais
32
+ * pour redéfinir une couleur ou une taille : c'est par là que les apps
33
+ * recommencent à écrire leur propre charte. */
34
+ className?: string
35
+ children?: ReactNode
36
+ }
37
+
38
+ export function Button({
39
+ variante = 'plein',
40
+ compact,
41
+ bloc,
42
+ className,
43
+ type = 'button',
44
+ ...reste
45
+ }: ButtonProps) {
46
+ return (
47
+ <button
48
+ type={type}
49
+ className={cx(
50
+ VARIANTE_BOUTON[variante],
51
+ compact && 'zv-btn--sm',
52
+ bloc && 'zv-btn--block',
53
+ className,
54
+ )}
55
+ {...reste}
56
+ />
57
+ )
58
+ }
59
+
60
+ export interface ButtonLinkProps
61
+ extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className'> {
62
+ variante?: BoutonVariante
63
+ compact?: boolean
64
+ bloc?: boolean
65
+ className?: string
66
+ }
67
+
68
+ /** Le même bouton, mais qui navigue. Un <a> et un <button> ne s'échangent pas :
69
+ * l'un ouvre dans un onglet, se copie et s'indexe, l'autre non. */
70
+ export function ButtonLink({
71
+ variante = 'plein',
72
+ compact,
73
+ bloc,
74
+ className,
75
+ ...reste
76
+ }: ButtonLinkProps) {
77
+ return (
78
+ <a
79
+ className={cx(
80
+ VARIANTE_BOUTON[variante],
81
+ compact && 'zv-btn--sm',
82
+ bloc && 'zv-btn--block',
83
+ className,
84
+ )}
85
+ {...reste}
86
+ />
87
+ )
88
+ }
89
+
90
+ export interface ButtonRowProps
91
+ extends Omit<HTMLAttributes<HTMLDivElement>, 'className'> {
92
+ /** Empile les boutons et les étire — la disposition mobile. */
93
+ empile?: boolean
94
+ className?: string
95
+ }
96
+
97
+ export function ButtonRow({ empile, className, ...reste }: ButtonRowProps) {
98
+ return (
99
+ <div
100
+ className={cx('zv-btn-row', empile && 'zv-btn-row--stack', className)}
101
+ {...reste}
102
+ />
103
+ )
104
+ }
105
+
106
+ export interface LinkArrowProps
107
+ extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className'> {
108
+ /** Sur la bande manifeste, où le lien passe en blanc. */
109
+ surSombre?: boolean
110
+ className?: string
111
+ children?: ReactNode
112
+ }
113
+
114
+ /** Lien fléché. La flèche est fournie : elle fait partie du composant, pas du
115
+ * contenu — la recopier à la main a produit trois tracés différents. */
116
+ export function LinkArrow({
117
+ surSombre,
118
+ className,
119
+ children,
120
+ ...reste
121
+ }: LinkArrowProps) {
122
+ return (
123
+ <a
124
+ className={cx(
125
+ 'zv-link-arrow',
126
+ surSombre && 'zv-link-arrow--on-dark',
127
+ className,
128
+ )}
129
+ {...reste}
130
+ >
131
+ {children}
132
+ <svg viewBox="0 0 24 24" aria-hidden="true">
133
+ <path d="M5 12h14" />
134
+ <path d="M13 6l6 6-6 6" />
135
+ </svg>
136
+ </a>
137
+ )
138
+ }