@studiolxd/brand 49.21.0 → 49.23.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 (40) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/dist/_shared/colorpicker.js +410 -0
  3. package/dist/_shared/tokens.js +62 -0
  4. package/dist/_types/atoms/ColorSwatch/ColorSwatch.d.ts +35 -0
  5. package/dist/_types/messages/BrandMessages.d.ts +5 -1
  6. package/dist/_types/messages/index.d.ts +1 -1
  7. package/dist/_types/molecules/ColorPicker/ColorArea.d.ts +51 -0
  8. package/dist/_types/molecules/ColorPicker/ColorPicker.d.ts +130 -0
  9. package/dist/_types/molecules/ColorPicker/colorModel.d.ts +54 -0
  10. package/dist/_types/molecules/ColorPickerField/ColorPickerField.d.ts +26 -0
  11. package/dist/_types/sections/AppHeader/AppHeader.d.ts +37 -2
  12. package/dist/app-header.css +1 -1
  13. package/dist/app-header.js +34 -21
  14. package/dist/app-shell.css +1 -1
  15. package/dist/brand.css +137 -1
  16. package/dist/color-picker-field.css +1 -0
  17. package/dist/color-picker-field.js +46 -0
  18. package/dist/color-picker.js +3 -0
  19. package/dist/color-swatch.css +1 -0
  20. package/dist/color-swatch.js +29 -0
  21. package/dist/colorpicker.css +1 -0
  22. package/dist/tokens.css +146 -1
  23. package/package.json +16 -1
  24. package/src/tokens/components/color-swatch.css +22 -0
  25. package/src/tokens/components/color-swatch.ts +7 -0
  26. package/src/tokens/index.css +3 -0
  27. package/src/tokens/molecules/color-picker-field.css +19 -0
  28. package/src/tokens/molecules/color-picker-field.ts +4 -0
  29. package/src/tokens/molecules/color-picker.css +63 -0
  30. package/src/tokens/molecules/color-picker.ts +8 -0
  31. package/src/tokens/scss/_index.legacy.scss +3 -0
  32. package/src/tokens/scss/_index.scss +3 -0
  33. package/src/tokens/scss/components/_color-swatch.scss +12 -0
  34. package/src/tokens/scss/molecules/_color-picker-field.scss +9 -0
  35. package/src/tokens/scss/molecules/_color-picker.scss +50 -0
  36. package/src/tokens/surface-dark-derived.css +8 -0
  37. package/src/tokens/surface-invert.css +14 -0
  38. package/src/tokens/surface-light.css +14 -0
  39. package/src/tokens/surface-public.css +2 -0
  40. package/src/tokens/tokens.json +62 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,76 @@ El paquete sigue [semver](https://semver.org/lang/es/): **patch** para bug fixes
7
7
  regeneración de `dist`, **minor** para componentes/props/variantes/tokens nuevos, **major**
8
8
  para breaking changes.
9
9
 
10
+ ## [49.23.0] — 2026-10-04
11
+
12
+ > **Minor.** Ranura `logo` en `AppHeader`, a petición de Homenize. Espacio nuevo `appHeader` en
13
+ > `BrandMessages` (una clave, `logo`): el catálogo de cada app tiene que añadirla para compilar.
14
+
15
+ ### Logo en la cabecera de la aplicación
16
+
17
+ - **`logo`**: la marca del producto entre el botón de menú y `start`. Toma el alto de contenido de la
18
+ barra (`--app-header-content-height`, 40px) y el ancho de su proporción: el `Logo` del sistema a
19
+ cualquier talla, un SVG con `viewBox` o un `<img>` de cualquier proporción, sin darle medidas. Sin
20
+ `logo`, la barra queda exactamente igual que antes.
21
+ - **`logoHref`** (por defecto `/`) y **`renderLogoLink`** para el router del producto, con el mismo
22
+ contrato que `SiteHeader`: recibe `href`, `className`, `aria-label` y `children`. Tipo nuevo
23
+ exportado: `AppHeaderLogoLinkProps`.
24
+ - **`logoLabel`**, o sin él **`appHeader.logo`** del `BrandMessagesProvider` («Homenize, ir al
25
+ inicio»), como `siteHeader.logo`. Solo se lee con `logo`. Tipo nuevo: `AppHeaderMessages`.
26
+ - **Una marca a la vez con el `Sidebar`.** La cabecera está siempre a la vista, encima de la columna y
27
+ del cajón, así que el `logo` va en uno solo —mejor en la cabecera, que se ve también en rail y con la
28
+ sidebar cerrada—. Si llegan los dos, dentro de un `AppShell` manda el de la cabecera: el armazón
29
+ oculta `.sidebar__header` mientras el `AppHeader` lleve `logo` (`:has`, sin JS, sin parpadeo en SSR).
30
+ - Stories: `AppHeader` «Con logo», «Con una marca de producto», «Con logo (móvil)»; `AppShell` «Con logo
31
+ en la cabecera». Tests de story (orden, enlace, 40px de alto con `Logo xxl`, imagen 4:1 a 160×40, sin
32
+ logo nada cambia, sidebar sin marca) y unitarios (`AppHeader.test.tsx`).
33
+
34
+ ## [49.22.0] — 2026-10-04
35
+
36
+ > **Minor.** Muestra y selector de color: `ColorSwatch`, `ColorPicker` y `ColorPickerField`, sin
37
+ > dependencias nuevas (Base UI y un área 2D propia). Espacio nuevo `colorPicker` en `BrandMessages`.
38
+
39
+ ### Muestra y selector de color
40
+
41
+ Creator pintaba unas 17 muestras a mano y cuatro selectores con `react-color`, fuera del sistema.
42
+ Ahora tiene sus piezas:
43
+
44
+ - **`ColorSwatch`** (átomo, `@studiolxd/brand/color-swatch`): enseña un color CSS cualquiera que viene
45
+ de un documento, sobre un damero que solo asoma donde el color es transparente. Tallas `sm`/`md`/`lg`
46
+ (16/24/48), `label` → `role="img"`; sin él, decorativa. **Sin `style`**: el color va en el `fill`
47
+ de un SVG (atributo de presentación), así que llega en el HTML del servidor y la CSP no lo descarta.
48
+ - **`ColorPicker`** (molécula, `@studiolxd/brand/color-picker`): la muestra como disparador, a la
49
+ talla de los campos, que abre un `Popover` con el área de saturación y brillo, la banda de tono, la
50
+ de opacidad (`alpha`), el campo hex, los predefinidos (`presets`, con `title`) y «Quitar color»
51
+ (`clearable` + `onClear`). Emite siempre hex en minúsculas, `#rrggbb` o `#rrggbbaa`;
52
+ `onValueChange` en cada paso y `onValueCommitted` al terminar el gesto.
53
+ - **Apertura controlada**: `open`, `defaultOpen` y `onOpenChange(open, details)`, con la forma del
54
+ `Popover`, en `ColorPicker` y `ColorPickerField`. Por defecto elegir no cierra el panel; quien
55
+ quiera cerrarlo al elegir —la celda de una tabla— lo hace en `onValueCommitted`.
56
+ - **`ColorPickerField`** (molécula, `@studiolxd/brand/color-picker-field`): el selector con etiqueta,
57
+ ayuda y error, como `DatePickerField`.
58
+
59
+ Todo es Base UI —el `Popover`, el `Slider` para las bandas, el `Input` para el hex— salvo el **área 2D**,
60
+ que Base UI no tiene: un único `role="slider"` con `aria-roledescription` y `aria-valuetext`
61
+ (saturación y brillo), con teclado en los dos ejes, puntero con captura, RTL por el
62
+ `DirectionProvider` de Base UI y la posición escrita por el CSSOM (`useCssProperties`). La conversión
63
+ hex ↔ HSV son funciones puras propias, con sus pruebas. Sin versión nativa: ninguna app nativa la
64
+ ha pedido.
65
+
66
+ ### Tokens
67
+
68
+ Tres conjuntos nuevos: `tokens/component/color-swatch.json`, `tokens/molecule/color-picker.json` y
69
+ `color-picker-field.json`, con sus pares `surface-dark-*` por la regla de derivación. **Ningún color
70
+ nuevo**: el damero es `color.white` + `color.grey-light`, los degradados del área son `color.white` y
71
+ `color.black` (el modelo HSV) y el degradado de tono sale del propio modelo, no de una lista de hex.
72
+
73
+ ### Internacionalización
74
+
75
+ Un espacio nuevo en `BrandMessages`: **`colorPicker`** (`trigger`, `value(hex)`, `empty`, `dialog`,
76
+ `area`, `areaDescription`, `areaValue(saturación, brillo)`, `hue`, `alpha`, `hex`, `presets`,
77
+ `clear`). **Una aplicación que no lo rellene no compila**, que es el contrato de siempre. La tabla de
78
+ Foundations › Internacionalización queda actualizada.
79
+
10
80
  ## [49.21.0] — 2026-10-04
11
81
 
12
82
  > **Minor, solo nativo.** `Banner`, `Menu`/`ContextMenu`, `Tabs`, `DatePickerField` y `PageIntro` en SwiftUI (iOS y
@@ -0,0 +1,410 @@
1
+ import '../colorpicker.css';
2
+ import { n as e } from "./brandmessagescontext.js";
3
+ import { VisuallyHidden as t } from "../visually-hidden.js";
4
+ import { Button as n } from "../button.js";
5
+ import { Input as r } from "../input.js";
6
+ import { Popover as i } from "../popover.js";
7
+ import { Slider as a } from "../slider.js";
8
+ import { t as o } from "./css-properties.js";
9
+ import { ColorSwatch as s } from "../color-swatch.js";
10
+ import { forwardRef as c, useCallback as l, useId as u, useRef as d, useState as f } from "react";
11
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
12
+ import { useDirection as h } from "@base-ui/react/direction-provider";
13
+ //#region src/stories/molecules/ColorPicker/ColorArea.tsx
14
+ var g = 1, _ = 10, v = (e) => Math.min(100, Math.max(0, e)), y = c(function({ hueColor: e, saturation: t, brightness: n, onChange: r, onCommit: i, label: a, roleDescription: s, valueText: c, disabled: u = !1 }, f) {
15
+ let m = h() === "rtl", y = d(null), b = d(null), x = d({
16
+ s: 0,
17
+ v: 0
18
+ }), S = o({
19
+ "--color-picker-area-x": `${m ? 100 - t : t}%`,
20
+ "--color-picker-area-y": `${100 - n}%`,
21
+ "--color-picker-area-hue": e
22
+ }), C = l((e) => {
23
+ y.current = e, S(e);
24
+ }, [S]), w = (e) => {
25
+ let t = e.currentTarget.getBoundingClientRect(), n = t.width ? (e.clientX - t.left) / t.width : 0, r = t.height ? (e.clientY - t.top) / t.height : 0;
26
+ return {
27
+ s: v((m ? 1 - n : n) * 100),
28
+ v: v((1 - r) * 100)
29
+ };
30
+ }, T = () => {
31
+ ((typeof f == "function" ? null : f?.current) ?? y.current?.querySelector("[role=\"slider\"]"))?.focus({ preventScroll: !0 });
32
+ }, E = (e) => {
33
+ if (u || e.button !== 0) return;
34
+ e.preventDefault();
35
+ try {
36
+ e.currentTarget.setPointerCapture?.(e.pointerId);
37
+ } catch {}
38
+ b.current = e.pointerId, T();
39
+ let t = w(e);
40
+ x.current = t, r(t);
41
+ }, D = (e) => {
42
+ if (b.current !== e.pointerId) return;
43
+ let t = w(e);
44
+ x.current = t, r(t);
45
+ }, O = (e) => {
46
+ if (b.current === e.pointerId) {
47
+ b.current = null;
48
+ try {
49
+ e.currentTarget.releasePointerCapture?.(e.pointerId);
50
+ } catch {}
51
+ i(x.current);
52
+ }
53
+ }, k = (e) => {
54
+ if (u) return;
55
+ let a = e.shiftKey ? _ : g, { s: o, v: s } = {
56
+ s: t,
57
+ v: n
58
+ };
59
+ switch (e.key) {
60
+ case "ArrowRight":
61
+ o += m ? -a : a;
62
+ break;
63
+ case "ArrowLeft":
64
+ o += m ? a : -a;
65
+ break;
66
+ case "ArrowUp":
67
+ s += a;
68
+ break;
69
+ case "ArrowDown":
70
+ s -= a;
71
+ break;
72
+ case "PageUp":
73
+ e.shiftKey ? o += _ : s += _;
74
+ break;
75
+ case "PageDown":
76
+ e.shiftKey ? o -= _ : s -= _;
77
+ break;
78
+ case "Home":
79
+ e.ctrlKey || e.metaKey ? s = 0 : o = 0;
80
+ break;
81
+ case "End":
82
+ e.ctrlKey || e.metaKey ? s = 100 : o = 100;
83
+ break;
84
+ default: return;
85
+ }
86
+ e.preventDefault();
87
+ let c = {
88
+ s: v(o),
89
+ v: v(s)
90
+ };
91
+ r(c), i(c);
92
+ };
93
+ return /* @__PURE__ */ p("div", {
94
+ ref: C,
95
+ className: "color-picker__area",
96
+ "data-direction": m ? "rtl" : "ltr",
97
+ "data-disabled": u ? "" : void 0,
98
+ onPointerDown: E,
99
+ onPointerMove: D,
100
+ onPointerUp: O,
101
+ onPointerCancel: O,
102
+ children: /* @__PURE__ */ p("div", {
103
+ ref: f,
104
+ className: "color-picker__area-thumb",
105
+ role: "slider",
106
+ tabIndex: u ? -1 : 0,
107
+ "aria-label": a,
108
+ "aria-roledescription": s,
109
+ "aria-valuemin": 0,
110
+ "aria-valuemax": 100,
111
+ "aria-valuenow": Math.round(t),
112
+ "aria-valuetext": c,
113
+ "aria-disabled": u || void 0,
114
+ onKeyDown: k
115
+ })
116
+ });
117
+ }), b = (e, t, n) => Math.min(n, Math.max(t, e));
118
+ function x(e) {
119
+ let t = e.trim().replace(/^#/, "");
120
+ if (!/^[0-9a-f]+$/i.test(t)) return null;
121
+ let n;
122
+ if (t.length === 3 || t.length === 4) n = t.split("").map((e) => e + e).join("");
123
+ else if (t.length === 6 || t.length === 8) n = t;
124
+ else return null;
125
+ let r = (e) => parseInt(n.slice(e * 2, e * 2 + 2), 16);
126
+ return {
127
+ r: r(0),
128
+ g: r(1),
129
+ b: r(2),
130
+ a: n.length === 8 ? r(3) / 255 : 1
131
+ };
132
+ }
133
+ var S = (e) => b(Math.round(e), 0, 255).toString(16).padStart(2, "0");
134
+ function C({ r: e, g: t, b: n, a: r }, i) {
135
+ let a = `#${S(e)}${S(t)}${S(n)}`;
136
+ return i ? `${a}${S(b(r, 0, 1) * 255)}` : a;
137
+ }
138
+ function w({ r: e, g: t, b: n, a: r }) {
139
+ let i = e / 255, a = t / 255, o = n / 255, s = Math.max(i, a, o), c = s - Math.min(i, a, o), l = 0;
140
+ return c !== 0 && (l = s === i ? (a - o) / c % 6 : s === a ? (o - i) / c + 2 : (i - a) / c + 4, l *= 60, l < 0 && (l += 360)), {
141
+ h: l,
142
+ s: s === 0 ? 0 : c / s * 100,
143
+ v: s * 100,
144
+ a: r
145
+ };
146
+ }
147
+ function T({ h: e, s: t, v: n, a: r }) {
148
+ let i = (e % 360 + 360) % 360, a = b(t, 0, 100) / 100, o = b(n, 0, 100) / 100, s = o * a, c = s * (1 - Math.abs(i / 60 % 2 - 1)), l = o - s, u;
149
+ return u = i < 60 ? [
150
+ s,
151
+ c,
152
+ 0
153
+ ] : i < 120 ? [
154
+ c,
155
+ s,
156
+ 0
157
+ ] : i < 180 ? [
158
+ 0,
159
+ s,
160
+ c
161
+ ] : i < 240 ? [
162
+ 0,
163
+ c,
164
+ s
165
+ ] : i < 300 ? [
166
+ c,
167
+ 0,
168
+ s
169
+ ] : [
170
+ s,
171
+ 0,
172
+ c
173
+ ], {
174
+ r: (u[0] + l) * 255,
175
+ g: (u[1] + l) * 255,
176
+ b: (u[2] + l) * 255,
177
+ a: b(r, 0, 1)
178
+ };
179
+ }
180
+ function E(e) {
181
+ let t = x(e);
182
+ return t ? w(t) : null;
183
+ }
184
+ function D(e, t) {
185
+ return C(T(e), t);
186
+ }
187
+ function O(e, t) {
188
+ let n = x(e);
189
+ return n ? C(n, t) : null;
190
+ }
191
+ function k() {
192
+ return [
193
+ 0,
194
+ 60,
195
+ 120,
196
+ 180,
197
+ 240,
198
+ 300,
199
+ 360
200
+ ].map((e) => D({
201
+ h: e,
202
+ s: 100,
203
+ v: 100,
204
+ a: 1
205
+ }, !1));
206
+ }
207
+ //#endregion
208
+ //#region src/stories/molecules/ColorPicker/ColorPicker.tsx
209
+ var A = {
210
+ h: 0,
211
+ s: 0,
212
+ v: 0,
213
+ a: 1
214
+ }, j = c(function({ value: c, defaultValue: g = null, onValueChange: _, onValueCommitted: v, alpha: b = !1, presets: x, clearable: S = !1, onClear: C, open: w, defaultOpen: T = !1, onOpenChange: j, size: M = "md", disabled: ee = !1, error: N = !1, locale: P = "es-ES", id: te, name: F, "aria-label": I, "aria-labelledby": L, "aria-describedby": ne, dialogLabel: re, clearLabel: ie, className: ae }, oe) {
215
+ let R = e("colorPicker"), z = h() === "rtl", [se, B] = f(T), V = w ?? se, H = c !== void 0, [ce, U] = f(g), W = H ? c : ce, G = W ? O(W, b) : null, [K, q] = f(() => G && E(G) || A), [le, ue] = f(G);
216
+ G !== le && (ue(G), G && D(K, b) !== G && q(E(G) ?? A));
217
+ let J = D(K, b), de = D({
218
+ ...K,
219
+ a: 1
220
+ }, !1), Y = l((e, t) => {
221
+ let n = b ? e : {
222
+ ...e,
223
+ a: 1
224
+ };
225
+ q(n);
226
+ let r = D(n, b);
227
+ H || U(r), _?.(r), t && v?.(r);
228
+ }, [
229
+ b,
230
+ H,
231
+ _,
232
+ v
233
+ ]), [X, Z] = f(null), [fe, pe] = f(V);
234
+ V !== fe && (pe(V), V || Z(null));
235
+ let Q = (e, t) => {
236
+ let n = O(e, b), r = n ? E(n) : null;
237
+ return r ? (Y(r, t), !0) : !1;
238
+ }, me = (e) => {
239
+ let t = e.target.value;
240
+ Z(t);
241
+ let n = t.trim().replace(/^#/, "").length;
242
+ (n === 6 || b && n === 8) && Q(t, !0);
243
+ }, $ = () => {
244
+ X !== null && Q(X, !0), Z(null);
245
+ }, he = () => {
246
+ H || U(null), C?.(), w === void 0 && B(!1);
247
+ }, ge = (e, t) => {
248
+ e && ee || (w === void 0 && B(e), j?.(e, t));
249
+ }, _e = d(null), ve = u(), ye = o({
250
+ "--color-picker-hue-gradient": `linear-gradient(to ${z ? "left" : "right"}, ${k().join(", ")})`,
251
+ "--color-picker-alpha-gradient": `linear-gradient(to ${z ? "left" : "right"}, transparent, ${de})`
252
+ }), be = (e) => Y({
253
+ ...K,
254
+ s: e.s,
255
+ v: e.v
256
+ }, !1), xe = (e) => Y({
257
+ ...K,
258
+ s: e.s,
259
+ v: e.v
260
+ }, !0), Se = (x ?? []).map((e) => ({
261
+ ...e,
262
+ hex: O(e.color, b)
263
+ })).filter((e) => e.hex !== null), Ce = [
264
+ "color-picker",
265
+ M === "md" ? "" : `color-picker--${M}`,
266
+ N ? "color-picker--error" : "",
267
+ ae ?? ""
268
+ ].filter(Boolean).join(" "), we = [ve, ne].filter(Boolean).join(" "), Te = /* @__PURE__ */ m("button", {
269
+ ref: oe,
270
+ id: te,
271
+ type: "button",
272
+ className: "color-picker__trigger",
273
+ disabled: ee,
274
+ "aria-label": I ?? (L ? void 0 : R("trigger")),
275
+ "aria-labelledby": I ? void 0 : L,
276
+ "aria-describedby": we,
277
+ "aria-haspopup": "dialog",
278
+ "aria-expanded": V,
279
+ "aria-invalid": N || void 0,
280
+ children: [/* @__PURE__ */ p(s, {
281
+ color: W,
282
+ className: "color-picker__swatch"
283
+ }), /* @__PURE__ */ p(t, {
284
+ id: ve,
285
+ children: W ? R("value")(G ?? W) : R("empty")
286
+ })]
287
+ });
288
+ return /* @__PURE__ */ m("div", {
289
+ className: Ce,
290
+ children: [F && /* @__PURE__ */ p("input", {
291
+ type: "hidden",
292
+ name: F,
293
+ value: G ?? ""
294
+ }), /* @__PURE__ */ p(i, {
295
+ trigger: Te,
296
+ label: R("dialog", re),
297
+ open: V,
298
+ onOpenChange: ge,
299
+ side: "bottom",
300
+ align: "start",
301
+ initialFocus: _e,
302
+ className: "color-picker__popover",
303
+ children: /* @__PURE__ */ m("div", {
304
+ ref: ye,
305
+ className: "color-picker__panel",
306
+ children: [
307
+ /* @__PURE__ */ p(y, {
308
+ ref: _e,
309
+ hueColor: D({
310
+ h: K.h,
311
+ s: 100,
312
+ v: 100,
313
+ a: 1
314
+ }, !1),
315
+ saturation: K.s,
316
+ brightness: K.v,
317
+ onChange: be,
318
+ onCommit: xe,
319
+ label: R("area"),
320
+ roleDescription: R("areaDescription"),
321
+ valueText: R("areaValue")(Math.round(K.s), Math.round(K.v))
322
+ }),
323
+ /* @__PURE__ */ p(a, {
324
+ className: "color-picker__channel color-picker__channel--hue",
325
+ label: R("hue"),
326
+ min: 0,
327
+ max: 360,
328
+ step: 1,
329
+ value: Math.round(K.h),
330
+ format: {
331
+ style: "unit",
332
+ unit: "degree"
333
+ },
334
+ locale: P,
335
+ onValueChange: (e) => Y({
336
+ ...K,
337
+ h: e
338
+ }, !1),
339
+ onValueCommitted: (e) => Y({
340
+ ...K,
341
+ h: e
342
+ }, !0)
343
+ }),
344
+ b && /* @__PURE__ */ p(a, {
345
+ className: "color-picker__channel color-picker__channel--alpha",
346
+ label: R("alpha"),
347
+ min: 0,
348
+ max: 100,
349
+ step: 1,
350
+ value: Math.round(K.a * 100),
351
+ format: {
352
+ style: "unit",
353
+ unit: "percent"
354
+ },
355
+ locale: P,
356
+ onValueChange: (e) => Y({
357
+ ...K,
358
+ a: e / 100
359
+ }, !1),
360
+ onValueCommitted: (e) => Y({
361
+ ...K,
362
+ a: e / 100
363
+ }, !0)
364
+ }),
365
+ /* @__PURE__ */ p(r, {
366
+ className: "color-picker__hex",
367
+ type: "text",
368
+ size: M,
369
+ "aria-label": R("hex"),
370
+ autoComplete: "off",
371
+ spellCheck: !1,
372
+ maxLength: b ? 9 : 7,
373
+ value: X ?? J,
374
+ onChange: me,
375
+ onBlur: $,
376
+ onKeyDown: (e) => {
377
+ e.key === "Enter" && (e.preventDefault(), $());
378
+ }
379
+ }),
380
+ Se.length > 0 && /* @__PURE__ */ p("div", {
381
+ className: "color-picker__presets",
382
+ role: "group",
383
+ "aria-label": R("presets"),
384
+ children: Se.map((e) => /* @__PURE__ */ p("button", {
385
+ type: "button",
386
+ className: "color-picker__preset",
387
+ title: e.title,
388
+ "aria-label": e.title,
389
+ "aria-pressed": e.hex === J,
390
+ onClick: () => Y(E(e.hex) ?? A, !0),
391
+ children: /* @__PURE__ */ p(s, {
392
+ color: e.hex,
393
+ className: "color-picker__preset-swatch"
394
+ })
395
+ }, `${e.hex}-${e.title}`))
396
+ }),
397
+ S && /* @__PURE__ */ p(n, {
398
+ variant: "ghost",
399
+ size: "sm",
400
+ className: "color-picker__clear",
401
+ onClick: he,
402
+ children: R("clear", ie)
403
+ })
404
+ ]
405
+ })
406
+ })]
407
+ });
408
+ });
409
+ //#endregion
410
+ export { j as t };
@@ -687,6 +687,15 @@ var e = {
687
687
  "--collapsible-focus-ring-width": "2px",
688
688
  "--collapsible-focus-ring-offset": "1px",
689
689
  "--collapsible-focus-ring-color": "#111e30",
690
+ "--color-swatch-size-sm": "16px",
691
+ "--color-swatch-size-md": "24px",
692
+ "--color-swatch-size-lg": "48px",
693
+ "--color-swatch-border-width": "1px",
694
+ "--color-swatch-border-color": "#d0d0d0",
695
+ "--color-swatch-border-radius": "0px",
696
+ "--color-swatch-checker-color": "#d0d0d0",
697
+ "--color-swatch-checker-bg": "#ffffff",
698
+ "--color-swatch-checker-size": "0.5rem",
690
699
  "--columns-gap-md": "2rem",
691
700
  "--columns-gap-lg": "4rem",
692
701
  "--columns-stack-gap-md": "2rem",
@@ -2429,6 +2438,59 @@ var e = {
2429
2438
  "--clock-widget-elapsed-label-font-size": "0.875rem",
2430
2439
  "--clock-widget-elapsed-label-color": "#4a4a4a",
2431
2440
  "--clock-widget-footer-margin-block-start": "0.5rem",
2441
+ "--color-picker-field-gap": "0.5rem",
2442
+ "--color-picker-field-helper-font-family": "\"Google Sans Flex\", system-ui, sans-serif",
2443
+ "--color-picker-field-helper-font-size": "0.875rem",
2444
+ "--color-picker-field-helper-font-weight": "300",
2445
+ "--color-picker-field-helper-line-height": "1.5",
2446
+ "--color-picker-field-helper-color": "#111e30",
2447
+ "--color-picker-trigger-size": "2.5rem",
2448
+ "--color-picker-trigger-sm-size": "2rem",
2449
+ "--color-picker-trigger-lg-size": "3rem",
2450
+ "--color-picker-trigger-padding": "0.25rem",
2451
+ "--color-picker-trigger-bg": "#ffffff",
2452
+ "--color-picker-trigger-border-width": "1px",
2453
+ "--color-picker-trigger-border-style": "solid",
2454
+ "--color-picker-trigger-border-color": "#111e30",
2455
+ "--color-picker-trigger-border-radius": "0px",
2456
+ "--color-picker-trigger-cursor": "pointer",
2457
+ "--color-picker-trigger-focus-border-color": "#111e30",
2458
+ "--color-picker-trigger-focus-ring-width": "2px",
2459
+ "--color-picker-trigger-focus-ring-inset-offset": "1px",
2460
+ "--color-picker-trigger-focus-ring-color": "#111e30",
2461
+ "--color-picker-trigger-error-border-color": "#b30000",
2462
+ "--color-picker-trigger-error-focus-ring-color": "#b30000",
2463
+ "--color-picker-trigger-disabled-bg": "#f2f2f2",
2464
+ "--color-picker-trigger-disabled-border-color": "#d0d0d0",
2465
+ "--color-picker-trigger-disabled-cursor": "not-allowed",
2466
+ "--color-picker-trigger-disabled-opacity": "0.4",
2467
+ "--color-picker-panel-gap": "0.75rem",
2468
+ "--color-picker-panel-inline-size": "calc(8 * 24px + 7 * 0.5rem)",
2469
+ "--color-picker-area-block-size": "calc(6 * 24px + 5 * 0.5rem)",
2470
+ "--color-picker-area-border-width": "1px",
2471
+ "--color-picker-area-border-color": "#d0d0d0",
2472
+ "--color-picker-area-saturation-start": "#ffffff",
2473
+ "--color-picker-area-brightness-end": "#000000",
2474
+ "--color-picker-area-cursor": "crosshair",
2475
+ "--color-picker-channel-track-size": "0.75rem",
2476
+ "--color-picker-thumb-size": "16px",
2477
+ "--color-picker-thumb-border-width": "2px",
2478
+ "--color-picker-thumb-border-color": "#ffffff",
2479
+ "--color-picker-thumb-outline-width": "1px",
2480
+ "--color-picker-thumb-outline-color": "#111e30",
2481
+ "--color-picker-thumb-border-radius": "0px",
2482
+ "--color-picker-thumb-focus-ring-width": "2px",
2483
+ "--color-picker-thumb-focus-ring-offset": "2px",
2484
+ "--color-picker-thumb-focus-ring-color": "#111e30",
2485
+ "--color-picker-preset-size": "24px",
2486
+ "--color-picker-preset-gap": "0.5rem",
2487
+ "--color-picker-preset-cursor": "pointer",
2488
+ "--color-picker-preset-focus-ring-width": "2px",
2489
+ "--color-picker-preset-focus-ring-offset": "2px",
2490
+ "--color-picker-preset-focus-ring-color": "#111e30",
2491
+ "--color-picker-preset-selected-ring-width": "2px",
2492
+ "--color-picker-preset-selected-ring-offset": "1px",
2493
+ "--color-picker-preset-selected-ring-color": "#111e30",
2432
2494
  "--command-palette-max-height": "min(24rem, 60vh)",
2433
2495
  "--command-palette-input-padding-block": "0.75rem",
2434
2496
  "--command-palette-input-padding-inline": "0.5rem",
@@ -0,0 +1,35 @@
1
+ import './ColorSwatch.css';
2
+ export interface ColorSwatchProps {
3
+ /**
4
+ * El color que se enseña: **cualquier color CSS** (`#111e30`, `#11223380`,
5
+ * `rgb(…)`, `transparent`, un nombre). Viene del documento, así que no se
6
+ * valida: lo que el navegador no entiende se pinta como vacío. Sin color
7
+ * (`null`, `undefined` o cadena vacía) solo asoma el damero.
8
+ */
9
+ color?: string | null;
10
+ /** Talla: `sm` (16px), `md` (24px, por defecto) o `lg` (48px). */
11
+ size?: 'sm' | 'md' | 'lg';
12
+ /**
13
+ * Nombre accesible. Con él la muestra es una imagen con nombre
14
+ * (`role="img"`): «Lavanda», «Color de fondo: #baabff». Sin él es
15
+ * decorativa (`aria-hidden`), que es lo correcto cuando el color ya se dice
16
+ * en el texto de al lado.
17
+ */
18
+ label?: string;
19
+ /** Se añade DESPUÉS de las clases propias. */
20
+ className?: string;
21
+ }
22
+ /**
23
+ * Una muestra de color: enseña un color que viene de un documento —el de un
24
+ * tema, una categoría, una celda—, sin interacción. Para elegirlo,
25
+ * `ColorPicker`.
26
+ *
27
+ * Detrás del color va siempre un damero, que solo se ve cuando el color tiene
28
+ * transparencia: así `transparent` o `#ffffff80` no se confunden con el blanco.
29
+ *
30
+ * **Sin atributo `style`.** El color llega al HTML como atributo de
31
+ * presentación de SVG (`fill`), que la CSP `style-src 'self'` no bloquea y que
32
+ * ya está en el primer render del servidor; el damero sale de la hoja, con
33
+ * tokens.
34
+ */
35
+ export declare function ColorSwatch({ color, size, label, className }: ColorSwatchProps): import("react/jsx-runtime").JSX.Element;
@@ -16,6 +16,7 @@ import type { SiteSearchMessages } from '../organisms/SiteSearch/SiteSearch';
16
16
  import type { FilterBarMessages } from '../molecules/FilterBar/FilterBar';
17
17
  import type { CalendarMessages } from '../molecules/Calendar/Calendar';
18
18
  import type { DatePickerMessages } from '../molecules/DatePicker/DatePicker';
19
+ import type { ColorPickerMessages } from '../molecules/ColorPicker/ColorPicker';
19
20
  import type { TimeSelectMessages } from '../atoms/TimeSelect/TimeSelect';
20
21
  import type { FileUploadMessages } from '../atoms/FileUpload/FileUpload';
21
22
  import type { ImageCropDialogMessages } from '../molecules/ImageCropDialog/ImageCropDialog';
@@ -35,6 +36,7 @@ import type { NotificationPanelMessages } from '../molecules/NotificationPanel/N
35
36
  import type { MenuButtonMessages } from '../atoms/MenuButton/MenuButton';
36
37
  import type { AppRootMessages } from '../sections/AppRoot/AppRoot';
37
38
  import type { AppShellMessages } from '../sections/AppShell/AppShell';
39
+ import type { AppHeaderMessages } from '../sections/AppHeader/AppHeader';
38
40
  import type { SidebarMessages } from '../sections/Sidebar/Sidebar';
39
41
  import type { SidebarNavMessages } from '../molecules/SidebarNav/SidebarNav';
40
42
  import type { SiteNavMessages } from '../molecules/SiteNav/SiteNav';
@@ -121,6 +123,7 @@ export interface BrandMessages {
121
123
  filterBar: FilterBarMessages;
122
124
  calendar: CalendarMessages;
123
125
  datePicker: DatePickerMessages;
126
+ colorPicker: ColorPickerMessages;
124
127
  timeSelect: TimeSelectMessages;
125
128
  fileUpload: FileUploadMessages;
126
129
  imageCropDialog: ImageCropDialogMessages;
@@ -140,6 +143,7 @@ export interface BrandMessages {
140
143
  menuButton: MenuButtonMessages;
141
144
  appRoot: AppRootMessages;
142
145
  appShell: AppShellMessages;
146
+ appHeader: AppHeaderMessages;
143
147
  sidebar: SidebarMessages;
144
148
  sidebarNav: SidebarNavMessages;
145
149
  siteNav: SiteNavMessages;
@@ -187,4 +191,4 @@ export interface BrandMessages {
187
191
  connectorExternalSignIn: ConnectorExternalSignInMessages;
188
192
  connectorRejection: ConnectorRejectionMessages;
189
193
  }
190
- export type { PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, SiteSearchMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, ClockWidgetMessages, HeatmapMessages, OrgChartMessages, PlanningGridMessages, RecurrenceFieldMessages, TimelineMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, MessageComposerMessages, ConversationListMessages, ConversationThreadMessages, TypingIndicatorMessages, AnnotationThreadMessages, ChatShellMessages, UntrustedTextMessages, ConnectorRequestSummaryMessages, ConnectorConsentMessages, ConnectorSignInMessages, ConnectorExternalSignInMessages, ConnectorRejectionMessages, };
194
+ export type { PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, SiteSearchMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, ColorPickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, AppHeaderMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, ClockWidgetMessages, HeatmapMessages, OrgChartMessages, PlanningGridMessages, RecurrenceFieldMessages, TimelineMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, MessageComposerMessages, ConversationListMessages, ConversationThreadMessages, TypingIndicatorMessages, AnnotationThreadMessages, ChatShellMessages, UntrustedTextMessages, ConnectorRequestSummaryMessages, ConnectorConsentMessages, ConnectorSignInMessages, ConnectorExternalSignInMessages, ConnectorRejectionMessages, };
@@ -2,4 +2,4 @@ export { BrandMessagesProvider } from './BrandMessagesProvider';
2
2
  export type { BrandMessagesProviderProps } from './BrandMessagesProvider';
3
3
  export { useBrandMessages } from './BrandMessagesContext';
4
4
  export type { BrandMessagesReader } from './BrandMessagesContext';
5
- export type { BrandMessages, PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, SiteSearchMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, ClockWidgetMessages, HeatmapMessages, OrgChartMessages, PlanningGridMessages, RecurrenceFieldMessages, TimelineMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, MessageComposerMessages, ConversationListMessages, ConversationThreadMessages, TypingIndicatorMessages, AnnotationThreadMessages, ChatShellMessages, UntrustedTextMessages, ConnectorRequestSummaryMessages, ConnectorConsentMessages, ConnectorSignInMessages, ConnectorExternalSignInMessages, ConnectorRejectionMessages, } from './BrandMessages';
5
+ export type { BrandMessages, PaginationMessages, TableMessages, DataTableMessages, InputFieldMessages, PasswordFieldMessages, SelectMessages, MultiSelectMessages, NumberInputMessages, OtpInputMessages, InputPhoneMessages, AsyncSelectMessages, AsyncMultiSelectMessages, DocsSearchMessages, SearchFormMessages, SiteSearchMessages, FilterBarMessages, CalendarMessages, DatePickerMessages, ColorPickerMessages, TimeSelectMessages, FileUploadMessages, ImageCropDialogMessages, AvatarUploadMessages, ModalMessages, SheetMessages, ConfirmDialogMessages, AlertMessages, BannerMessages, ToasterMessages, ConsentMessages, CommandPaletteMessages, AppLauncherMessages, FloatingDockMessages, NotificationButtonMessages, NotificationPanelMessages, MenuButtonMessages, AppRootMessages, AppShellMessages, AppHeaderMessages, SidebarMessages, SidebarNavMessages, SiteNavMessages, SiteHeaderMessages, UserMenuMessages, OrgSwitcherMessages, BreadcrumbMessages, TableOfContentsMessages, PrevNextNavMessages, PublicPageShellMessages, OnboardingShellMessages, CopyMessages, CodeBlockMessages, DotsButtonMessages, ProgressBarMessages, SpinnerMessages, SliderMessages, TreeViewMessages, ClockWidgetMessages, HeatmapMessages, OrgChartMessages, PlanningGridMessages, RecurrenceFieldMessages, TimelineMessages, UptimeBarsMessages, ChartMessages, StepperMessages, CarouselMessages, LanguageSwitcherMessages, ProjectCardMessages, LegalFooterMessages, CalendarRosterMessages, CalendarPlannerMessages, NotificationListMessages, MessageComposerMessages, ConversationListMessages, ConversationThreadMessages, TypingIndicatorMessages, AnnotationThreadMessages, ChatShellMessages, UntrustedTextMessages, ConnectorRequestSummaryMessages, ConnectorConsentMessages, ConnectorSignInMessages, ConnectorExternalSignInMessages, ConnectorRejectionMessages, } from './BrandMessages';