@studiolxd/brand 49.23.1 → 49.24.1

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/CHANGELOG.md CHANGED
@@ -7,6 +7,61 @@ 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.24.1] — 2026-10-04
11
+
12
+ > **Patch.** `AppShell` y `ChatShell` ya no rompen la hidratación por debajo del punto de ruptura de
13
+ > escritorio (encargo de Homenize: Next.js 16 con SSR, a 1000px de ancho, React 19 daba «Hydration
14
+ > failed because the server rendered HTML didn't match the client» en cada carga). Sin cambios de API.
15
+
16
+ ### El ancho se lee sin desajustar el HTML del servidor
17
+
18
+ - El servidor no conoce el ancho y pinta la versión de escritorio; el primer render del cliente leía
19
+ `matchMedia` en el estado inicial y, por debajo de `breakpoint.lg`, pintaba el cajón: otro
20
+ `aria-label`/`aria-expanded` en el botón de menú, otra clase, `data-state`, `inert` y `tabIndex` en
21
+ el `aside` de la `Sidebar`, y el asa de redimensión de menos.
22
+ - Nuevo hook interno `useMediaQuery` (`src/stories/constants/media-query.ts`) sobre
23
+ `useSyncExternalStore`, con una instantánea de servidor fija (`null`, «todavía no se sabe»): servidor
24
+ y render de hidratación pintan lo mismo, y React vuelve a pintar con el valor real nada más hidratar.
25
+ Un render solo de cliente lee el valor real desde el principio.
26
+ - `AppShell` y `ChatShell` publican la forma que han tomado en **`data-layout`** (`column`/`drawer`);
27
+ sin el atributo, aún no la saben. Por debajo de lg, su hoja esconde la columna mientras falte el
28
+ atributo —y el `AppShell` deja el glifo de menú en «menú»—, así que el HTML del servidor ya se ve
29
+ como el cajón cerrado: ni parpadeo ni salto de maquetación al hidratar.
30
+ - Una vez montado, todo igual: en escritorio la barra abierta y redimensionable; en móvil el cajón
31
+ cerrado, con `inert`, foco, `aria-expanded` y `aria-controls`.
32
+ - Revisados sin cambios: `SiteHeader` (el panel lo resuelve el CSS), `OrgSwitcher`, `Carousel` y
33
+ `ConversationThread` (solo leen `prefers-reduced-motion` dentro de efectos) y `Chart` (mide con
34
+ `ResizeObserver` tras montar). Las versiones nativas no hidratan y no tienen `AppShell`.
35
+ - Test nuevo (`AppShell.hydration.test.tsx`): `renderToString` + `hydrateRoot` del `AppShell` con
36
+ `AppHeader` y `Sidebar`, y del `ChatShell`, a 1000px y a 1280px, sin ningún `console.error` ni
37
+ error recuperable.
38
+
39
+ ## [49.24.0] — 2026-10-04
40
+
41
+ > **Minor.** Disparador propio y ancla sin disparador en `ColorPicker`, a petición de creator (la barra
42
+ > de texto enriquecido y la celda de una tabla). Sin tocar nada, todo sigue igual.
43
+
44
+ ### `ColorPicker`: `trigger` y `anchor`
45
+
46
+ - **`trigger`**: un elemento propio como disparador en lugar de la muestra —un `Toggle` con glifo y
47
+ `ColorSwatch size="sm"`, un `Button`—, con el patrón del `trigger` de `Popover`/`Menu` y las props
48
+ por `render` (`useRender`, como `Button`). Recibe `id`, `aria-haspopup="dialog"`, `aria-expanded`,
49
+ `aria-controls`, `aria-label`/`aria-labelledby`, `aria-invalid`, `disabled` y la descripción con el
50
+ valor (`colorPicker.value`/`empty`); lo que el elemento ya traiga gana, salvo la descripción, que se
51
+ suma, y `disabled`. El `ref` del selector se suma al suyo. El foco vuelve a él al cerrar. No lee
52
+ `colorPicker.trigger`: se nombra por sí mismo o por `aria-label`/la etiqueta.
53
+ - **`anchor`**: coloca el panel contra otro elemento (la prop `anchor` de `Popover`). Sin `trigger`
54
+ no se pinta ninguna muestra: el panel se abre con `open` controlado, y al cerrarse el foco vuelve a
55
+ donde estaba antes de abrir.
56
+ - `ColorPickerField` reenvía las dos; con `trigger`, la etiqueta sigue nombrando el elemento.
57
+ - Stories «Con disparador propio» y «Anclado sin disparador», y sus `Test — …`.
58
+
59
+ ### `Popover`: `anchor`, y `trigger` opcional
60
+
61
+ - **`anchor`** (tipo `PopoverAnchor`): la prop `anchor` del Positioner de Base UI, tal cual.
62
+ - **`trigger` pasa a opcional**: sin él no se pinta disparador y el panel se abre con `open` contra
63
+ `anchor`.
64
+
10
65
  ## [49.23.1] — 2026-10-04
11
66
 
12
67
  > **Patch.** `appHeader` pasa a ser **opcional** en `BrandMessages`. En 49.23.0 entró obligatorio y un
@@ -7,61 +7,62 @@ import { Popover as i } from "../popover.js";
7
7
  import { Slider as a } from "../slider.js";
8
8
  import { t as o } from "./css-properties.js";
9
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";
10
+ import { cloneElement as c, forwardRef as l, useCallback as u, useId as d, useRef as f, useState as p } from "react";
11
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
12
+ import { useRender as g } from "@base-ui/react/use-render";
13
+ import { useDirection as _ } from "@base-ui/react/direction-provider";
13
14
  //#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({
15
+ var v = 1, y = 10, b = (e) => Math.min(100, Math.max(0, e)), x = l(function({ hueColor: e, saturation: t, brightness: n, onChange: r, onCommit: i, label: a, roleDescription: s, valueText: c, disabled: l = !1 }, d) {
16
+ let p = _() === "rtl", h = f(null), g = f(null), x = f({
16
17
  s: 0,
17
18
  v: 0
18
19
  }), S = o({
19
- "--color-picker-area-x": `${m ? 100 - t : t}%`,
20
+ "--color-picker-area-x": `${p ? 100 - t : t}%`,
20
21
  "--color-picker-area-y": `${100 - n}%`,
21
22
  "--color-picker-area-hue": e
22
- }), C = l((e) => {
23
- y.current = e, S(e);
23
+ }), C = u((e) => {
24
+ h.current = e, S(e);
24
25
  }, [S]), w = (e) => {
25
26
  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
27
  return {
27
- s: v((m ? 1 - n : n) * 100),
28
- v: v((1 - r) * 100)
28
+ s: b((p ? 1 - n : n) * 100),
29
+ v: b((1 - r) * 100)
29
30
  };
30
31
  }, T = () => {
31
- ((typeof f == "function" ? null : f?.current) ?? y.current?.querySelector("[role=\"slider\"]"))?.focus({ preventScroll: !0 });
32
+ ((typeof d == "function" ? null : d?.current) ?? h.current?.querySelector("[role=\"slider\"]"))?.focus({ preventScroll: !0 });
32
33
  }, E = (e) => {
33
- if (u || e.button !== 0) return;
34
+ if (l || e.button !== 0) return;
34
35
  e.preventDefault();
35
36
  try {
36
37
  e.currentTarget.setPointerCapture?.(e.pointerId);
37
38
  } catch {}
38
- b.current = e.pointerId, T();
39
+ g.current = e.pointerId, T();
39
40
  let t = w(e);
40
41
  x.current = t, r(t);
41
42
  }, D = (e) => {
42
- if (b.current !== e.pointerId) return;
43
+ if (g.current !== e.pointerId) return;
43
44
  let t = w(e);
44
45
  x.current = t, r(t);
45
46
  }, O = (e) => {
46
- if (b.current === e.pointerId) {
47
- b.current = null;
47
+ if (g.current === e.pointerId) {
48
+ g.current = null;
48
49
  try {
49
50
  e.currentTarget.releasePointerCapture?.(e.pointerId);
50
51
  } catch {}
51
52
  i(x.current);
52
53
  }
53
54
  }, k = (e) => {
54
- if (u) return;
55
- let a = e.shiftKey ? _ : g, { s: o, v: s } = {
55
+ if (l) return;
56
+ let a = e.shiftKey ? y : v, { s: o, v: s } = {
56
57
  s: t,
57
58
  v: n
58
59
  };
59
60
  switch (e.key) {
60
61
  case "ArrowRight":
61
- o += m ? -a : a;
62
+ o += p ? -a : a;
62
63
  break;
63
64
  case "ArrowLeft":
64
- o += m ? a : -a;
65
+ o += p ? a : -a;
65
66
  break;
66
67
  case "ArrowUp":
67
68
  s += a;
@@ -70,10 +71,10 @@ var g = 1, _ = 10, v = (e) => Math.min(100, Math.max(0, e)), y = c(function({ hu
70
71
  s -= a;
71
72
  break;
72
73
  case "PageUp":
73
- e.shiftKey ? o += _ : s += _;
74
+ e.shiftKey ? o += y : s += y;
74
75
  break;
75
76
  case "PageDown":
76
- e.shiftKey ? o -= _ : s -= _;
77
+ e.shiftKey ? o -= y : s -= y;
77
78
  break;
78
79
  case "Home":
79
80
  e.ctrlKey || e.metaKey ? s = 0 : o = 0;
@@ -85,37 +86,37 @@ var g = 1, _ = 10, v = (e) => Math.min(100, Math.max(0, e)), y = c(function({ hu
85
86
  }
86
87
  e.preventDefault();
87
88
  let c = {
88
- s: v(o),
89
- v: v(s)
89
+ s: b(o),
90
+ v: b(s)
90
91
  };
91
92
  r(c), i(c);
92
93
  };
93
- return /* @__PURE__ */ p("div", {
94
+ return /* @__PURE__ */ m("div", {
94
95
  ref: C,
95
96
  className: "color-picker__area",
96
- "data-direction": m ? "rtl" : "ltr",
97
- "data-disabled": u ? "" : void 0,
97
+ "data-direction": p ? "rtl" : "ltr",
98
+ "data-disabled": l ? "" : void 0,
98
99
  onPointerDown: E,
99
100
  onPointerMove: D,
100
101
  onPointerUp: O,
101
102
  onPointerCancel: O,
102
- children: /* @__PURE__ */ p("div", {
103
- ref: f,
103
+ children: /* @__PURE__ */ m("div", {
104
+ ref: d,
104
105
  className: "color-picker__area-thumb",
105
106
  role: "slider",
106
- tabIndex: u ? -1 : 0,
107
+ tabIndex: l ? -1 : 0,
107
108
  "aria-label": a,
108
109
  "aria-roledescription": s,
109
110
  "aria-valuemin": 0,
110
111
  "aria-valuemax": 100,
111
112
  "aria-valuenow": Math.round(t),
112
113
  "aria-valuetext": c,
113
- "aria-disabled": u || void 0,
114
+ "aria-disabled": l || void 0,
114
115
  onKeyDown: k
115
116
  })
116
117
  });
117
- }), b = (e, t, n) => Math.min(n, Math.max(t, e));
118
- function x(e) {
118
+ }), S = (e, t, n) => Math.min(n, Math.max(t, e));
119
+ function C(e) {
119
120
  let t = e.trim().replace(/^#/, "");
120
121
  if (!/^[0-9a-f]+$/i.test(t)) return null;
121
122
  let n;
@@ -130,12 +131,12 @@ function x(e) {
130
131
  a: n.length === 8 ? r(3) / 255 : 1
131
132
  };
132
133
  }
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;
134
+ var w = (e) => S(Math.round(e), 0, 255).toString(16).padStart(2, "0");
135
+ function T({ r: e, g: t, b: n, a: r }, i) {
136
+ let a = `#${w(e)}${w(t)}${w(n)}`;
137
+ return i ? `${a}${w(S(r, 0, 1) * 255)}` : a;
137
138
  }
138
- function w({ r: e, g: t, b: n, a: r }) {
139
+ function E({ r: e, g: t, b: n, a: r }) {
139
140
  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
141
  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
142
  h: l,
@@ -144,8 +145,8 @@ function w({ r: e, g: t, b: n, a: r }) {
144
145
  a: r
145
146
  };
146
147
  }
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;
148
+ function D({ h: e, s: t, v: n, a: r }) {
149
+ let i = (e % 360 + 360) % 360, a = S(t, 0, 100) / 100, o = S(n, 0, 100) / 100, s = o * a, c = s * (1 - Math.abs(i / 60 % 2 - 1)), l = o - s, u;
149
150
  return u = i < 60 ? [
150
151
  s,
151
152
  c,
@@ -174,21 +175,21 @@ function T({ h: e, s: t, v: n, a: r }) {
174
175
  r: (u[0] + l) * 255,
175
176
  g: (u[1] + l) * 255,
176
177
  b: (u[2] + l) * 255,
177
- a: b(r, 0, 1)
178
+ a: S(r, 0, 1)
178
179
  };
179
180
  }
180
- function E(e) {
181
- let t = x(e);
182
- return t ? w(t) : null;
181
+ function O(e) {
182
+ let t = C(e);
183
+ return t ? E(t) : null;
183
184
  }
184
- function D(e, t) {
185
- return C(T(e), t);
185
+ function k(e, t) {
186
+ return T(D(e), t);
186
187
  }
187
- function O(e, t) {
188
- let n = x(e);
189
- return n ? C(n, t) : null;
188
+ function A(e, t) {
189
+ let n = C(e);
190
+ return n ? T(n, t) : null;
190
191
  }
191
- function k() {
192
+ function ee() {
192
193
  return [
193
194
  0,
194
195
  60,
@@ -197,7 +198,7 @@ function k() {
197
198
  240,
198
199
  300,
199
200
  360
200
- ].map((e) => D({
201
+ ].map((e) => k({
201
202
  h: e,
202
203
  s: 100,
203
204
  v: 100,
@@ -206,205 +207,228 @@ function k() {
206
207
  }
207
208
  //#endregion
208
209
  //#region src/stories/molecules/ColorPicker/ColorPicker.tsx
209
- var A = {
210
+ var j = {
210
211
  h: 0,
211
212
  s: 0,
212
213
  v: 0,
213
214
  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,
215
+ }, te = l(function({ value: l, defaultValue: v = null, onValueChange: y, onValueCommitted: b, alpha: S = !1, presets: C, clearable: w = !1, onClear: T, open: E, defaultOpen: D = !1, onOpenChange: te, size: M = "md", disabled: N = !1, error: P = !1, locale: ne = "es-ES", id: re, name: F, "aria-label": I, "aria-labelledby": L, "aria-describedby": ie, dialogLabel: ae, clearLabel: oe, trigger: R, anchor: z, className: se }, B) {
216
+ let V = e("colorPicker"), H = _() === "rtl", [ce, U] = p(D), W = E ?? ce, G = l !== void 0, [le, ue] = p(v), K = G ? l : le, q = K ? A(K, S) : null, [J, de] = p(() => q && O(q) || j), [fe, pe] = p(q);
217
+ q !== fe && (pe(q), q && k(J, S) !== q && de(O(q) ?? j));
218
+ let me = k(J, S), he = k({
219
+ ...J,
219
220
  a: 1
220
- }, !1), Y = l((e, t) => {
221
- let n = b ? e : {
221
+ }, !1), Y = u((e, t) => {
222
+ let n = S ? e : {
222
223
  ...e,
223
224
  a: 1
224
225
  };
225
- q(n);
226
- let r = D(n, b);
227
- H || U(r), _?.(r), t && v?.(r);
226
+ de(n);
227
+ let r = k(n, S);
228
+ G || ue(r), y?.(r), t && b?.(r);
228
229
  }, [
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;
230
+ S,
231
+ G,
232
+ y,
233
+ b
234
+ ]), [X, Z] = p(null), [ge, _e] = p(W);
235
+ W !== ge && (_e(W), W || Z(null));
236
+ let ve = (e, t) => {
237
+ let n = A(e, S), r = n ? O(n) : null;
237
238
  return r ? (Y(r, t), !0) : !1;
238
- }, me = (e) => {
239
+ }, ye = (e) => {
239
240
  let t = e.target.value;
240
241
  Z(t);
241
242
  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,
243
+ (n === 6 || S && n === 8) && ve(t, !0);
244
+ }, be = () => {
245
+ X !== null && ve(X, !0), Z(null);
246
+ }, xe = () => {
247
+ G || ue(null), T?.(), E === void 0 && U(!1);
248
+ }, Se = (e, t) => {
249
+ e && N || (E === void 0 && U(e), te?.(e, t));
250
+ }, Ce = f(null), Q = d(), we = o({
251
+ "--color-picker-hue-gradient": `linear-gradient(to ${H ? "left" : "right"}, ${ee().join(", ")})`,
252
+ "--color-picker-alpha-gradient": `linear-gradient(to ${H ? "left" : "right"}, transparent, ${he})`
253
+ }), Te = (e) => Y({
254
+ ...J,
254
255
  s: e.s,
255
256
  v: e.v
256
- }, !1), xe = (e) => Y({
257
- ...K,
257
+ }, !1), Ee = (e) => Y({
258
+ ...J,
258
259
  s: e.s,
259
260
  v: e.v
260
- }, !0), Se = (x ?? []).map((e) => ({
261
+ }, !0), De = (C ?? []).map((e) => ({
261
262
  ...e,
262
- hex: O(e.color, b)
263
- })).filter((e) => e.hex !== null), Ce = [
263
+ hex: A(e.color, S)
264
+ })).filter((e) => e.hex !== null), Oe = [
264
265
  "color-picker",
265
266
  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,
267
+ P ? "color-picker--error" : "",
268
+ se ?? ""
269
+ ].filter(Boolean).join(" "), ke = [Q, ie].filter(Boolean).join(" "), Ae = /* @__PURE__ */ h("button", {
270
+ ref: B,
271
+ id: re,
271
272
  type: "button",
272
273
  className: "color-picker__trigger",
273
- disabled: ee,
274
- "aria-label": I ?? (L ? void 0 : R("trigger")),
274
+ disabled: N,
275
+ "aria-label": I ?? (L ? void 0 : V("trigger")),
275
276
  "aria-labelledby": I ? void 0 : L,
276
- "aria-describedby": we,
277
+ "aria-describedby": ke,
277
278
  "aria-haspopup": "dialog",
278
- "aria-expanded": V,
279
- "aria-invalid": N || void 0,
280
- children: [/* @__PURE__ */ p(s, {
281
- color: W,
279
+ "aria-expanded": W,
280
+ "aria-invalid": P || void 0,
281
+ children: [/* @__PURE__ */ m(s, {
282
+ color: K,
282
283
  className: "color-picker__swatch"
283
- }), /* @__PURE__ */ p(t, {
284
- id: ve,
285
- children: W ? R("value")(G ?? W) : R("empty")
284
+ }), /* @__PURE__ */ m(t, {
285
+ id: Q,
286
+ children: K ? V("value")(q ?? K) : V("empty")
286
287
  })]
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
- ]
288
+ }), je = R?.props ?? {}, Me = g({
289
+ render: R && c(R, {
290
+ disabled: N || je.disabled || void 0,
291
+ "aria-describedby": [ke, je["aria-describedby"]].filter(Boolean).join(" ")
292
+ }),
293
+ ref: B,
294
+ enabled: R !== void 0,
295
+ props: {
296
+ id: re,
297
+ "aria-label": I,
298
+ "aria-labelledby": I ? void 0 : L,
299
+ "aria-haspopup": "dialog",
300
+ "aria-expanded": W,
301
+ "aria-invalid": P || void 0
302
+ }
303
+ }), $;
304
+ return Me ? $ = Me : z === void 0 && ($ = Ae), /* @__PURE__ */ h("div", {
305
+ className: Oe,
306
+ children: [
307
+ F && /* @__PURE__ */ m("input", {
308
+ type: "hidden",
309
+ name: F,
310
+ value: q ?? ""
311
+ }),
312
+ R && /* @__PURE__ */ m(t, {
313
+ id: Q,
314
+ children: K ? V("value")(q ?? K) : V("empty")
315
+ }),
316
+ /* @__PURE__ */ m(i, {
317
+ trigger: $,
318
+ anchor: z,
319
+ label: V("dialog", ae),
320
+ open: W,
321
+ onOpenChange: Se,
322
+ side: "bottom",
323
+ align: "start",
324
+ initialFocus: Ce,
325
+ className: "color-picker__popover",
326
+ children: /* @__PURE__ */ h("div", {
327
+ ref: we,
328
+ className: "color-picker__panel",
329
+ children: [
330
+ /* @__PURE__ */ m(x, {
331
+ ref: Ce,
332
+ hueColor: k({
333
+ h: J.h,
334
+ s: 100,
335
+ v: 100,
336
+ a: 1
337
+ }, !1),
338
+ saturation: J.s,
339
+ brightness: J.v,
340
+ onChange: Te,
341
+ onCommit: Ee,
342
+ label: V("area"),
343
+ roleDescription: V("areaDescription"),
344
+ valueText: V("areaValue")(Math.round(J.s), Math.round(J.v))
345
+ }),
346
+ /* @__PURE__ */ m(a, {
347
+ className: "color-picker__channel color-picker__channel--hue",
348
+ label: V("hue"),
349
+ min: 0,
350
+ max: 360,
351
+ step: 1,
352
+ value: Math.round(J.h),
353
+ format: {
354
+ style: "unit",
355
+ unit: "degree"
356
+ },
357
+ locale: ne,
358
+ onValueChange: (e) => Y({
359
+ ...J,
360
+ h: e
361
+ }, !1),
362
+ onValueCommitted: (e) => Y({
363
+ ...J,
364
+ h: e
365
+ }, !0)
366
+ }),
367
+ S && /* @__PURE__ */ m(a, {
368
+ className: "color-picker__channel color-picker__channel--alpha",
369
+ label: V("alpha"),
370
+ min: 0,
371
+ max: 100,
372
+ step: 1,
373
+ value: Math.round(J.a * 100),
374
+ format: {
375
+ style: "unit",
376
+ unit: "percent"
377
+ },
378
+ locale: ne,
379
+ onValueChange: (e) => Y({
380
+ ...J,
381
+ a: e / 100
382
+ }, !1),
383
+ onValueCommitted: (e) => Y({
384
+ ...J,
385
+ a: e / 100
386
+ }, !0)
387
+ }),
388
+ /* @__PURE__ */ m(r, {
389
+ className: "color-picker__hex",
390
+ type: "text",
391
+ size: M,
392
+ "aria-label": V("hex"),
393
+ autoComplete: "off",
394
+ spellCheck: !1,
395
+ maxLength: S ? 9 : 7,
396
+ value: X ?? me,
397
+ onChange: ye,
398
+ onBlur: be,
399
+ onKeyDown: (e) => {
400
+ e.key === "Enter" && (e.preventDefault(), be());
401
+ }
402
+ }),
403
+ De.length > 0 && /* @__PURE__ */ m("div", {
404
+ className: "color-picker__presets",
405
+ role: "group",
406
+ "aria-label": V("presets"),
407
+ children: De.map((e) => /* @__PURE__ */ m("button", {
408
+ type: "button",
409
+ className: "color-picker__preset",
410
+ title: e.title,
411
+ "aria-label": e.title,
412
+ "aria-pressed": e.hex === me,
413
+ onClick: () => Y(O(e.hex) ?? j, !0),
414
+ children: /* @__PURE__ */ m(s, {
415
+ color: e.hex,
416
+ className: "color-picker__preset-swatch"
417
+ })
418
+ }, `${e.hex}-${e.title}`))
419
+ }),
420
+ w && /* @__PURE__ */ m(n, {
421
+ variant: "ghost",
422
+ size: "sm",
423
+ className: "color-picker__clear",
424
+ onClick: xe,
425
+ children: V("clear", oe)
426
+ })
427
+ ]
428
+ })
405
429
  })
406
- })]
430
+ ]
407
431
  });
408
432
  });
409
433
  //#endregion
410
- export { j as t };
434
+ export { te as t };
@@ -0,0 +1,12 @@
1
+ import { useCallback as e, useSyncExternalStore as t } from "react";
2
+ //#region src/stories/constants/media-query.ts
3
+ var n = () => null;
4
+ function r(r) {
5
+ return t(e((e) => {
6
+ if (typeof window.matchMedia != "function") return () => {};
7
+ let t = window.matchMedia(r);
8
+ return t.addEventListener("change", e), () => t.removeEventListener("change", e);
9
+ }, [r]), () => typeof window.matchMedia == "function" ? window.matchMedia(r).matches : null, n);
10
+ }
11
+ //#endregion
12
+ export { r as t };
@@ -8,9 +8,25 @@ import './Popover.css';
8
8
  * forma a mano.
9
9
  */
10
10
  export type PopoverChangeDetails = Parameters<NonNullable<React.ComponentProps<typeof BasePopover.Root>['onOpenChange']>>[1];
11
+ /**
12
+ * Elemento contra el que se coloca el panel cuando no es el disparador. Es la
13
+ * prop `anchor` del Positioner de Base UI, tal cual: un elemento, un `ref`, un
14
+ * elemento virtual o una función que lo devuelva.
15
+ */
16
+ export type PopoverAnchor = React.ComponentProps<typeof BasePopover.Positioner>['anchor'];
11
17
  export interface PopoverProps {
12
- /** Elemento que abre el panel. Recibe las props del disparador vía `render`. */
13
- trigger: ReactNode;
18
+ /**
19
+ * Elemento que abre el panel. Recibe las props del disparador vía `render`.
20
+ * Sin él no se pinta disparador: el panel se abre con `open` y se coloca
21
+ * contra `anchor`.
22
+ */
23
+ trigger?: ReactNode;
24
+ /**
25
+ * Coloca el panel contra otro elemento que no es el disparador —o, sin
26
+ * disparador, contra el único que hay—. Por defecto, el disparador. Sin
27
+ * disparador, al cerrarse el foco vuelve a donde estaba antes de abrir.
28
+ */
29
+ anchor?: PopoverAnchor;
14
30
  /** Contenido del panel. */
15
31
  children: ReactNode;
16
32
  /**
@@ -74,4 +90,4 @@ export interface PopoverProps {
74
90
  * mantener el panel abierto cuando el clic cae en algo que el motor no
75
91
  * reconoce como suyo.
76
92
  */
77
- export declare function Popover({ trigger, children, label, open, defaultOpen, onOpenChange, onPointerDownOutside, onFocusOutside, onEscapeKeyDown, side, align, sideOffset, initialFocus, container, className, }: PopoverProps): import("react/jsx-runtime").JSX.Element;
93
+ export declare function Popover({ trigger, anchor, children, label, open, defaultOpen, onOpenChange, onPointerDownOutside, onFocusOutside, onEscapeKeyDown, side, align, sideOffset, initialFocus, container, className, }: PopoverProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Lee una media query **sin romper la hidratación**.
3
+ *
4
+ * El servidor no conoce el ancho de la ventana. Si el primer render del
5
+ * cliente leyera `matchMedia` (en el `useState` inicial, por ejemplo), pintaría
6
+ * otro marcado que el servidor y React 19 tiraría la hidratación con «server
7
+ * rendered HTML didn't match the client». Con `useSyncExternalStore` el
8
+ * servidor y el render de hidratación leen la misma instantánea fija —`null`,
9
+ * «todavía no se sabe»— y React vuelve a pintar con el valor real nada más
10
+ * hidratar. Un render solo de cliente (sin SSR) lee el valor real desde el
11
+ * primer momento.
12
+ *
13
+ * Mientras valga `null`, el componente pinta su forma de partida y es su CSS,
14
+ * con la misma media query, quien la corrige a la vista: así no hay parpadeo
15
+ * entre el HTML del servidor y el render hidratado.
16
+ *
17
+ * Sin `matchMedia` en el entorno, `null` siempre.
18
+ */
19
+ export declare function useMediaQuery(query: string): boolean | null;
@@ -1,4 +1,5 @@
1
- import type { PopoverChangeDetails } from '../../atoms/Popover/Popover';
1
+ import type { ReactElement } from 'react';
2
+ import type { PopoverAnchor, PopoverChangeDetails } from '../../atoms/Popover/Popover';
2
3
  import './ColorPicker.css';
3
4
  /**
4
5
  * El cromo del selector de color. Ninguno trae el castellano puesto: salen
@@ -115,6 +116,24 @@ export interface ColorPickerProps {
115
116
  dialogLabel?: string;
116
117
  /** Texto de «Quitar color». **Sin default**: sin él, `colorPicker.clear`. */
117
118
  clearLabel?: string;
119
+ /**
120
+ * Disparador propio en lugar de la muestra: un `Toggle` con icono, un
121
+ * `Button`… Como el `trigger` de `Popover`, recibe las props del disparador
122
+ * por `render`, así que tiene que reenviarlas (y el `ref`) a su elemento.
123
+ * El selector le añade `id`, `disabled`, `aria-haspopup`, `aria-expanded`,
124
+ * `aria-invalid`, `aria-label` / `aria-labelledby` y la descripción con el
125
+ * valor actual; lo que el elemento ya traiga gana, salvo la descripción, que
126
+ * se suma, y `disabled`, que basta con que lo diga uno. Lo que pinte dentro
127
+ * (y su `pressed`, si es un `Toggle`) lo decide quien lo usa.
128
+ */
129
+ trigger?: ReactElement<Record<string, unknown>>;
130
+ /**
131
+ * Coloca el panel contra un elemento que no es el disparador —la celda de una
132
+ * tabla— (la prop `anchor` de `Popover`). Sin `trigger`, no se pinta ningún
133
+ * disparador: el panel se abre solo con `open`, y al cerrarse el foco vuelve
134
+ * a donde estaba antes de abrir.
135
+ */
136
+ anchor?: PopoverAnchor;
118
137
  /** Se añade DESPUÉS de las clases propias. */
119
138
  className?: string;
120
139
  }
@@ -125,6 +144,6 @@ export interface ColorPickerProps {
125
144
  *
126
145
  * Todo es Base UI salvo el área 2D: el `Popover` (foco, portal, cierre), las
127
146
  * bandas (`Slider`) y el campo (`Input`) son los de brand. El `ref` va al
128
- * disparador.
147
+ * disparador, sea la muestra o el `trigger` propio.
129
148
  */
130
149
  export declare const ColorPicker: import("react").ForwardRefExoticComponent<ColorPickerProps & import("react").RefAttributes<HTMLButtonElement>>;
@@ -1 +1 @@
1
- .app-shell{--app-shell-sidebar-width:var(--sidebar-width);--app-shell-banner-height:0px;--app-shell-chrome-block-start:calc(var(--app-shell-banner-height) + var(--app-header-height) + env(safe-area-inset-top));flex-direction:column;block-size:100dvh;display:flex;overflow:clip}.app-shell__banner{flex-shrink:0}.app-shell__body{flex:1;min-block-size:0;display:flex;position:relative}.app-shell__content{min-inline-size:0;padding-inline:var(--section-padding-inline);padding-block:var(--section-padding-block-lg);flex:1;padding-block-end:max(var(--section-padding-block-lg), env(safe-area-inset-bottom));padding-inline-end:max(var(--section-padding-inline), env(safe-area-inset-right));overflow:auto}.app-shell__content.app-shell__content--flush{padding-block:0;padding-inline:0;padding-block-end:env(safe-area-inset-bottom);padding-inline-end:env(safe-area-inset-right)}.app-shell__backdrop{inset:0;background-color:var(--sidebar-backdrop-bg);opacity:var(--sidebar-backdrop-opacity);z-index:var(--sidebar-backdrop-z-index);position:fixed;inset-block-start:var(--app-shell-chrome-block-start)}.app-shell:has(.app-header__logo) .sidebar__header{display:none}
1
+ .app-shell{--app-shell-sidebar-width:var(--sidebar-width);--app-shell-banner-height:0px;--app-shell-chrome-block-start:calc(var(--app-shell-banner-height) + var(--app-header-height) + env(safe-area-inset-top));flex-direction:column;block-size:100dvh;display:flex;overflow:clip}.app-shell__banner{flex-shrink:0}.app-shell__body{flex:1;min-block-size:0;display:flex;position:relative}.app-shell__content{min-inline-size:0;padding-inline:var(--section-padding-inline);padding-block:var(--section-padding-block-lg);flex:1;padding-block-end:max(var(--section-padding-block-lg), env(safe-area-inset-bottom));padding-inline-end:max(var(--section-padding-inline), env(safe-area-inset-right));overflow:auto}.app-shell__content.app-shell__content--flush{padding-block:0;padding-inline:0;padding-block-end:env(safe-area-inset-bottom);padding-inline-end:env(safe-area-inset-right)}.app-shell__backdrop{inset:0;background-color:var(--sidebar-backdrop-bg);opacity:var(--sidebar-backdrop-opacity);z-index:var(--sidebar-backdrop-z-index);position:fixed;inset-block-start:var(--app-shell-chrome-block-start)}.app-shell:has(.app-header__logo) .sidebar__header{display:none}@media (width<=1023.98px){.app-shell:not([data-layout]) .sidebar{display:none}.app-shell:not([data-layout]) .app-header .menu-button .icon__line{opacity:1;transform:none}}
package/dist/app-shell.js CHANGED
@@ -5,94 +5,88 @@ import { SkipLink as t } from "./skip-link.js";
5
5
  import { t as n } from "./_shared/css-properties.js";
6
6
  import { TooltipProvider as r } from "./tooltip.js";
7
7
  import { n as i, t as a } from "./_shared/appshellcontext.js";
8
- import { useCallback as o, useEffect as s, useMemo as c, useState as l } from "react";
9
- import { jsx as u, jsxs as d } from "react/jsx-runtime";
8
+ import { t as o } from "./_shared/media-query.js";
9
+ import { useCallback as s, useEffect as c, useMemo as l, useState as u } from "react";
10
+ import { jsx as d, jsxs as f } from "react/jsx-runtime";
10
11
  //#region src/stories/sections/AppShell/AppShell.tsx
11
- var f = "(min-width: 1024px)";
12
- function p() {
13
- let [e, t] = l(() => typeof window > "u" || typeof window.matchMedia != "function" ? !0 : window.matchMedia(f).matches);
14
- return s(() => {
15
- if (typeof window.matchMedia != "function") return;
16
- let e = window.matchMedia(f), n = () => t(e.matches);
17
- return n(), e.addEventListener("change", n), () => e.removeEventListener("change", n);
18
- }, []), e;
19
- }
20
- function m({ banner: i, header: f, sidebar: m, children: h, contentFlush: g = !1, defaultSidebar: _ = "open", sidebarState: v, onSidebarChange: y, defaultSidebarWidth: b, onSidebarWidthChange: x, skipLabel: S }) {
21
- let C = e("appShell"), w = p(), [T, E] = l(_), [D, O] = l(!1), [k, A] = l(b), j = w ? v ?? T : D ? "open" : "closed", M = o((e) => {
22
- w ? (E(e), y?.(e)) : O(e === "open");
23
- }, [w, y]), N = o(() => M(j === "open" ? "closed" : "open"), [M, j]), P = o(() => M("closed"), [M]), F = o((e) => {
24
- A(e), x?.(e);
25
- }, [x]);
26
- s(() => {
27
- if (w || !D) return;
12
+ var p = "(min-width: 1024px)";
13
+ function m({ banner: i, header: m, sidebar: h, children: g, contentFlush: _ = !1, defaultSidebar: v = "open", sidebarState: y, onSidebarChange: b, defaultSidebarWidth: x, onSidebarWidthChange: S, skipLabel: C }) {
14
+ let w = e("appShell"), T = o(p), E = T ?? !0, [D, O] = u(v), [k, A] = u(!1), [j, M] = u(x), N = E ? y ?? D : k ? "open" : "closed", P = s((e) => {
15
+ E ? (O(e), b?.(e)) : A(e === "open");
16
+ }, [E, b]), F = s(() => P(N === "open" ? "closed" : "open"), [P, N]), I = s(() => P("closed"), [P]), L = s((e) => {
17
+ M(e), S?.(e);
18
+ }, [S]);
19
+ c(() => {
20
+ if (E || !k) return;
28
21
  let e = (e) => {
29
- e.key === "Escape" && O(!1);
22
+ e.key === "Escape" && A(!1);
30
23
  };
31
24
  document.addEventListener("keydown", e);
32
25
  let t = document.body.style.overflow;
33
26
  return document.body.style.overflow = "hidden", () => {
34
27
  document.removeEventListener("keydown", e), document.body.style.overflow = t;
35
28
  };
36
- }, [w, D]);
37
- let I = c(() => ({
38
- sidebar: j,
39
- setSidebar: M,
40
- sidebarWidth: k ?? 0,
41
- setSidebarWidth: F,
42
- toggleSidebar: N,
43
- closeSidebar: P,
44
- isDesktop: w
29
+ }, [E, k]);
30
+ let R = l(() => ({
31
+ sidebar: N,
32
+ setSidebar: P,
33
+ sidebarWidth: j ?? 0,
34
+ setSidebarWidth: L,
35
+ toggleSidebar: F,
36
+ closeSidebar: I,
37
+ isDesktop: E
45
38
  }), [
46
- j,
47
- M,
48
- k,
49
- F,
50
39
  N,
51
40
  P,
52
- w
53
- ]), [L, R] = l(0), z = o((e) => {
41
+ j,
42
+ L,
43
+ F,
44
+ I,
45
+ E
46
+ ]), [z, B] = u(0), V = s((e) => {
54
47
  if (!e) return;
55
- let t = () => R(e.getBoundingClientRect().height);
48
+ let t = () => B(e.getBoundingClientRect().height);
56
49
  if (t(), typeof ResizeObserver > "u") return;
57
50
  let n = new ResizeObserver(t);
58
51
  return n.observe(e), () => {
59
- n.disconnect(), R(0);
52
+ n.disconnect(), B(0);
60
53
  };
61
- }, []), B = n({
62
- "--app-shell-sidebar-width": k ? `${k}px` : void 0,
63
- "--app-shell-banner-height": i ? `${L}px` : void 0
64
- }), V = !w && D;
65
- return /* @__PURE__ */ u(a.Provider, {
66
- value: I,
67
- children: /* @__PURE__ */ d(r, { children: [/* @__PURE__ */ u(t, {
54
+ }, []), H = n({
55
+ "--app-shell-sidebar-width": j ? `${j}px` : void 0,
56
+ "--app-shell-banner-height": i ? `${z}px` : void 0
57
+ }), U = !E && k;
58
+ return /* @__PURE__ */ d(a.Provider, {
59
+ value: R,
60
+ children: /* @__PURE__ */ f(r, { children: [/* @__PURE__ */ d(t, {
68
61
  href: "#main-content",
69
- children: C("skipToContent", S)
70
- }), /* @__PURE__ */ d("div", {
71
- ref: B,
62
+ children: w("skipToContent", C)
63
+ }), /* @__PURE__ */ f("div", {
64
+ ref: H,
72
65
  className: "app-shell",
73
- "data-sidebar": j,
66
+ "data-sidebar": N,
67
+ "data-layout": T === null ? void 0 : E ? "column" : "drawer",
74
68
  children: [
75
- i && /* @__PURE__ */ u("div", {
76
- ref: z,
69
+ i && /* @__PURE__ */ d("div", {
70
+ ref: V,
77
71
  className: "app-shell__banner",
78
72
  children: i
79
73
  }),
80
- f,
81
- /* @__PURE__ */ d("div", {
74
+ m,
75
+ /* @__PURE__ */ f("div", {
82
76
  className: "app-shell__body",
83
77
  children: [
84
- m,
85
- V && /* @__PURE__ */ u("div", {
78
+ h,
79
+ U && /* @__PURE__ */ d("div", {
86
80
  className: "app-shell__backdrop",
87
- onClick: P,
81
+ onClick: I,
88
82
  "aria-hidden": "true"
89
83
  }),
90
- /* @__PURE__ */ u("main", {
84
+ /* @__PURE__ */ d("main", {
91
85
  id: "main-content",
92
86
  tabIndex: -1,
93
- className: g ? "app-shell__content app-shell__content--flush" : "app-shell__content",
94
- inert: V || void 0,
95
- children: h
87
+ className: _ ? "app-shell__content app-shell__content--flush" : "app-shell__content",
88
+ inert: U || void 0,
89
+ children: g
96
90
  })
97
91
  ]
98
92
  })
@@ -1 +1 @@
1
- .chat-shell{background-color:var(--chat-shell-bg);flex-direction:column;block-size:100%;min-block-size:0;display:flex;position:relative}.chat-shell .chat-shell__drawer,.chat-shell .sheet__overlay{position:absolute}.chat-shell .chat-shell__drawer{--sheet-inline-size:100%;--sheet-padding-block:0;--sheet-padding-inline:0;--sheet-gap:0;overflow:visible}.chat-shell__drawer .sheet__body{gap:var(--chat-shell-drawer-gap);flex-direction:column;min-block-size:0;display:flex}.chat-shell__drawer-list{flex:1;min-block-size:0;overflow-y:auto}.chat-shell__list{inline-size:var(--chat-shell-list-width);flex-shrink:0;block-size:100%;overflow-y:auto}.chat-shell.chat-shell--with-list{gap:var(--chat-shell-gap);flex-direction:row}.chat-shell__main{flex-direction:column;flex:1;min-block-size:0;display:flex}.chat-shell__header{justify-content:space-between;align-items:center;gap:var(--chat-shell-header-gap);flex-shrink:0;display:flex}.chat-shell__list-trigger{flex-shrink:0;align-self:flex-start}.chat-shell__header-content{justify-content:space-between;align-items:center;gap:var(--chat-shell-header-gap);flex:1;min-inline-size:0;display:flex}.chat-shell__thread{--conversation-thread-padding-inline:var(--chat-shell-thread-padding-inline);min-block-size:0;padding-block:var(--chat-shell-thread-padding-block);flex-direction:column;flex:1;display:flex;overflow-y:auto}.chat-shell__composer{flex-shrink:0}
1
+ .chat-shell{background-color:var(--chat-shell-bg);flex-direction:column;block-size:100%;min-block-size:0;display:flex;position:relative}.chat-shell .chat-shell__drawer,.chat-shell .sheet__overlay{position:absolute}.chat-shell .chat-shell__drawer{--sheet-inline-size:100%;--sheet-padding-block:0;--sheet-padding-inline:0;--sheet-gap:0;overflow:visible}.chat-shell__drawer .sheet__body{gap:var(--chat-shell-drawer-gap);flex-direction:column;min-block-size:0;display:flex}.chat-shell__drawer-list{flex:1;min-block-size:0;overflow-y:auto}.chat-shell__list{inline-size:var(--chat-shell-list-width);flex-shrink:0;block-size:100%;overflow-y:auto}.chat-shell.chat-shell--with-list{gap:var(--chat-shell-gap);flex-direction:row}.chat-shell__main{flex-direction:column;flex:1;min-block-size:0;display:flex}.chat-shell__header{justify-content:space-between;align-items:center;gap:var(--chat-shell-header-gap);flex-shrink:0;display:flex}.chat-shell__list-trigger{flex-shrink:0;align-self:flex-start}.chat-shell__header-content{justify-content:space-between;align-items:center;gap:var(--chat-shell-header-gap);flex:1;min-inline-size:0;display:flex}.chat-shell__thread{--conversation-thread-padding-inline:var(--chat-shell-thread-padding-inline);min-block-size:0;padding-block:var(--chat-shell-thread-padding-block);flex-direction:column;flex:1;display:flex;overflow-y:auto}.chat-shell__composer{flex-shrink:0}@media (width<=1023.98px){.chat-shell:not([data-layout]) .chat-shell__list{display:none}.chat-shell.chat-shell--with-list:not([data-layout]){flex-direction:column}}
@@ -4,50 +4,47 @@ import { n as e } from "./_shared/brandmessagescontext.js";
4
4
  import { Icon as t } from "./icon.js";
5
5
  import { Button as n } from "./button.js";
6
6
  import { Sheet as r } from "./sheet.js";
7
- import { forwardRef as i, useCallback as a, useEffect as o, useState as s } from "react";
7
+ import { t as i } from "./_shared/media-query.js";
8
+ import { forwardRef as a, useCallback as o, useState as s } from "react";
8
9
  import { jsx as c, jsxs as l } from "react/jsx-runtime";
9
10
  //#region src/stories/templates/ChatShell/ChatShell.tsx
10
- var u = "(min-width: 1024px)", d = i(function({ list: i, header: d, children: f, composer: p, listLabel: m, listTriggerLabel: h, listOpen: g, onListOpenChange: _, className: v, ...y }, b) {
11
- let x = e("chatShell"), [S, C] = s(() => typeof window > "u" ? !0 : window.matchMedia(u).matches), [w, T] = s(!1), [E, D] = s(null), O = a((e) => {
11
+ var u = "(min-width: 1024px)", d = a(function({ list: a, header: d, children: f, composer: p, listLabel: m, listTriggerLabel: h, listOpen: g, onListOpenChange: _, className: v, ...y }, b) {
12
+ let x = e("chatShell"), S = i(u), C = S ?? !0, [w, T] = s(!1), [E, D] = s(null), O = o((e) => {
12
13
  D(e), typeof b == "function" ? b(e) : b && (b.current = e);
13
- }, [b]);
14
- o(() => {
15
- let e = window.matchMedia(u), t = () => {
16
- C(e.matches), e.matches && T(!1);
17
- };
18
- return t(), e.addEventListener("change", t), () => e.removeEventListener("change", t);
19
- }, []);
20
- let k = a((e) => {
14
+ }, [b]), [k, A] = s(S);
15
+ S !== k && (A(S), S && T(!1));
16
+ let j = o((e) => {
21
17
  g === void 0 && T(e), _?.(e);
22
- }, [g, _]), A = !S && (g ?? w), j = i != null && S, M = i != null && !S;
18
+ }, [g, _]), M = !C && (g ?? w), N = a != null && C, P = a != null && !C;
23
19
  return /* @__PURE__ */ l("div", {
24
20
  ref: O,
25
21
  className: [
26
22
  "chat-shell",
27
- j ? "chat-shell--with-list" : "",
23
+ N ? "chat-shell--with-list" : "",
28
24
  v ?? ""
29
25
  ].filter(Boolean).join(" "),
26
+ "data-layout": S === null ? void 0 : C ? "column" : "drawer",
30
27
  ...y,
31
28
  children: [
32
- j && /* @__PURE__ */ c("aside", {
29
+ N && /* @__PURE__ */ c("aside", {
33
30
  className: "chat-shell__list",
34
31
  "aria-label": x("list", m),
35
- children: i
32
+ children: a
36
33
  }),
37
34
  /* @__PURE__ */ l("div", {
38
35
  className: "chat-shell__main",
39
36
  children: [
40
- (d || M) && /* @__PURE__ */ l("header", {
37
+ (d || P) && /* @__PURE__ */ l("header", {
41
38
  className: "chat-shell__header",
42
- children: [M && /* @__PURE__ */ c(n, {
39
+ children: [P && /* @__PURE__ */ c(n, {
43
40
  variant: "ghost",
44
41
  size: "sm",
45
42
  iconOnly: !0,
46
43
  "aria-label": x("listTrigger", h),
47
44
  "aria-haspopup": "dialog",
48
- "aria-expanded": A,
45
+ "aria-expanded": M,
49
46
  className: "chat-shell__list-trigger",
50
- onClick: () => k(!0),
47
+ onClick: () => j(!0),
51
48
  children: /* @__PURE__ */ c(t, {
52
49
  name: "layout-sidebar",
53
50
  size: "sm"
@@ -67,10 +64,10 @@ var u = "(min-width: 1024px)", d = i(function({ list: i, header: d, children: f,
67
64
  })
68
65
  ]
69
66
  }),
70
- M && /* @__PURE__ */ l(r, {
67
+ P && /* @__PURE__ */ l(r, {
71
68
  side: "left",
72
- open: A,
73
- onOpenChange: k,
69
+ open: M,
70
+ onOpenChange: j,
74
71
  title: x("list", m),
75
72
  titleHidden: !0,
76
73
  container: E ?? void 0,
@@ -85,7 +82,7 @@ var u = "(min-width: 1024px)", d = i(function({ list: i, header: d, children: f,
85
82
  "aria-label": x("listTrigger", h),
86
83
  "aria-expanded": !0,
87
84
  className: "chat-shell__list-trigger",
88
- onClick: () => k(!1),
85
+ onClick: () => j(!1),
89
86
  children: /* @__PURE__ */ c(t, {
90
87
  name: "layout-sidebar",
91
88
  size: "sm"
@@ -93,7 +90,7 @@ var u = "(min-width: 1024px)", d = i(function({ list: i, header: d, children: f,
93
90
  })
94
91
  }), /* @__PURE__ */ c("div", {
95
92
  className: "chat-shell__drawer-list",
96
- children: i
93
+ children: a
97
94
  })]
98
95
  })
99
96
  ]
package/dist/popover.js CHANGED
@@ -12,26 +12,27 @@ function a() {
12
12
  let e = document.documentElement;
13
13
  return i(getComputedStyle(e).getPropertyValue("--popover-offset").trim());
14
14
  }
15
- function o({ trigger: i, children: o, label: s, open: c, defaultOpen: l, onOpenChange: u, onPointerDownOutside: d, onFocusOutside: f, onEscapeKeyDown: p, side: m = "bottom", align: h = "start", sideOffset: g, initialFocus: _, container: v, className: y }) {
16
- let b = e(v);
15
+ function o({ trigger: i, anchor: o, children: s, label: c, open: l, defaultOpen: u, onOpenChange: d, onPointerDownOutside: f, onFocusOutside: p, onEscapeKeyDown: m, side: h = "bottom", align: g = "start", sideOffset: _, initialFocus: v, container: y, className: b }) {
16
+ let x = e(y);
17
17
  return /* @__PURE__ */ n(r.Root, {
18
- open: c,
19
- defaultOpen: l,
18
+ open: l,
19
+ defaultOpen: u,
20
20
  onOpenChange: (e, t) => {
21
- e || (t.reason === "outside-press" ? d?.(t) : t.reason === "focus-out" ? f?.(t) : t.reason === "escape-key" && p?.(t)), u?.(e, t);
21
+ e || (t.reason === "outside-press" ? f?.(t) : t.reason === "focus-out" ? p?.(t) : t.reason === "escape-key" && m?.(t)), d?.(e, t);
22
22
  },
23
- children: [/* @__PURE__ */ t(r.Trigger, { render: i }), /* @__PURE__ */ t(r.Portal, {
24
- container: b,
23
+ children: [i !== void 0 && /* @__PURE__ */ t(r.Trigger, { render: i }), /* @__PURE__ */ t(r.Portal, {
24
+ container: x,
25
25
  children: /* @__PURE__ */ t(r.Positioner, {
26
26
  className: "popover__positioner",
27
- side: m,
28
- align: h,
29
- sideOffset: g ?? a,
27
+ anchor: o,
28
+ side: h,
29
+ align: g,
30
+ sideOffset: _ ?? a,
30
31
  children: /* @__PURE__ */ t(r.Popup, {
31
- "aria-label": s,
32
- initialFocus: _,
33
- className: ["popover", y].filter(Boolean).join(" "),
34
- children: o
32
+ "aria-label": c,
33
+ initialFocus: v,
34
+ className: ["popover", b].filter(Boolean).join(" "),
35
+ children: s
35
36
  })
36
37
  })
37
38
  })]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiolxd/brand",
3
- "version": "49.23.1",
3
+ "version": "49.24.1",
4
4
  "description": "El sistema de diseño de Studio LXD: componentes React, tokens y documentación de la suite SLXD.",
5
5
  "repository": {
6
6
  "type": "git",