@octavius2929-personal/design-system 0.22.1 → 0.23.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/dist/index.d.cts CHANGED
@@ -633,6 +633,22 @@ declare const schemas: {
633
633
  };
634
634
  type SchemaName = keyof typeof schemas;
635
635
  declare const schemaNames: SchemaName[];
636
+ /**
637
+ * Núcleo platform-agnostic del tema: estado resuelto + acciones. Web y native
638
+ * lo extienden con sus extras de plataforma (web: `themeClass`; native:
639
+ * `colorTokens` + `tokens`). Una sola fuente para la forma común.
640
+ */
641
+ interface ThemeState {
642
+ schema: SchemaName;
643
+ /** Modo efectivo ya resuelto (nunca "system"). */
644
+ mode: Mode;
645
+ /** La preferencia cruda elegida (puede ser "system"). */
646
+ preference: ModePreference;
647
+ setSchema: (schema: SchemaName) => void;
648
+ setMode: (mode: ModePreference) => void;
649
+ toggleMode: () => void;
650
+ cycleMode: () => void;
651
+ }
636
652
 
637
653
  declare const colorVars: {
638
654
  bg1: `var(--${string})`;
@@ -1500,19 +1516,8 @@ declare const iconCatalog: {
1500
1516
  Icon: Icon;
1501
1517
  }[];
1502
1518
 
1503
- interface ThemeContextValue {
1504
- schema: SchemaName;
1505
- /** Modo efectivo ya resuelto (nunca "system"). */
1506
- mode: Mode;
1507
- /** La preferencia cruda elegida (puede ser "system"). */
1508
- preference: ModePreference;
1519
+ interface ThemeContextValue extends ThemeState {
1509
1520
  themeClass: string;
1510
- setSchema: (schema: SchemaName) => void;
1511
- setMode: (mode: ModePreference) => void;
1512
- /** Alterna binario claro↔oscuro a partir del modo efectivo. */
1513
- toggleMode: () => void;
1514
- /** Rota por los cuatro modos en orden. */
1515
- cycleMode: () => void;
1516
1521
  }
1517
1522
  interface ThemeProviderProps {
1518
1523
  children: ReactNode;
package/dist/index.d.ts CHANGED
@@ -633,6 +633,22 @@ declare const schemas: {
633
633
  };
634
634
  type SchemaName = keyof typeof schemas;
635
635
  declare const schemaNames: SchemaName[];
636
+ /**
637
+ * Núcleo platform-agnostic del tema: estado resuelto + acciones. Web y native
638
+ * lo extienden con sus extras de plataforma (web: `themeClass`; native:
639
+ * `colorTokens` + `tokens`). Una sola fuente para la forma común.
640
+ */
641
+ interface ThemeState {
642
+ schema: SchemaName;
643
+ /** Modo efectivo ya resuelto (nunca "system"). */
644
+ mode: Mode;
645
+ /** La preferencia cruda elegida (puede ser "system"). */
646
+ preference: ModePreference;
647
+ setSchema: (schema: SchemaName) => void;
648
+ setMode: (mode: ModePreference) => void;
649
+ toggleMode: () => void;
650
+ cycleMode: () => void;
651
+ }
636
652
 
637
653
  declare const colorVars: {
638
654
  bg1: `var(--${string})`;
@@ -1500,19 +1516,8 @@ declare const iconCatalog: {
1500
1516
  Icon: Icon;
1501
1517
  }[];
1502
1518
 
1503
- interface ThemeContextValue {
1504
- schema: SchemaName;
1505
- /** Modo efectivo ya resuelto (nunca "system"). */
1506
- mode: Mode;
1507
- /** La preferencia cruda elegida (puede ser "system"). */
1508
- preference: ModePreference;
1519
+ interface ThemeContextValue extends ThemeState {
1509
1520
  themeClass: string;
1510
- setSchema: (schema: SchemaName) => void;
1511
- setMode: (mode: ModePreference) => void;
1512
- /** Alterna binario claro↔oscuro a partir del modo efectivo. */
1513
- toggleMode: () => void;
1514
- /** Rota por los cuatro modos en orden. */
1515
- cycleMode: () => void;
1516
1521
  }
1517
1522
  interface ThemeProviderProps {
1518
1523
  children: ReactNode;
package/dist/index.js CHANGED
@@ -280,7 +280,16 @@ var tintaSchema = {
280
280
  var schemas = { tinta: tintaSchema };
281
281
  var schemaNames2 = Object.keys(schemas);
282
282
  var colorTokenNames = Object.keys(schemas.tinta.light.color);
283
+ function isSchemaName(x) {
284
+ return typeof x === "string" && Object.hasOwn(schemas, x);
285
+ }
283
286
  var modeNames2 = ["light", "dark", "sepia", "contrast"];
287
+ function isMode(x) {
288
+ return typeof x === "string" && modeNames2.includes(x);
289
+ }
290
+ function isModePreference(x) {
291
+ return x === "system" || isMode(x);
292
+ }
284
293
  var SYSTEM_MODE_PRECEDENCE = [
285
294
  { query: "(prefers-contrast: more)", mode: "contrast" },
286
295
  { query: "(prefers-color-scheme: dark)", mode: "dark" }
@@ -288,14 +297,36 @@ var SYSTEM_MODE_PRECEDENCE = [
288
297
  function resolveMode(preference, systemMode) {
289
298
  return preference === "system" ? systemMode : preference;
290
299
  }
300
+ function sanitizePersisted(raw) {
301
+ if (!raw || typeof raw !== "object") return {};
302
+ const clean = {};
303
+ if (isSchemaName(raw.schema)) clean.schema = raw.schema;
304
+ if (isModePreference(raw.preference)) clean.preference = raw.preference;
305
+ return clean;
306
+ }
291
307
  function useThemeStore(options, storage, system) {
292
308
  const { defaultSchema = "tinta", defaultMode = "light" } = options;
293
- const [persisted] = useState2(() => storage.read());
309
+ const [persisted] = useState2(() => sanitizePersisted(storage.read()));
294
310
  const [schema, setSchema] = useState2(persisted?.schema ?? defaultSchema);
295
311
  const [preference, setPreference] = useState2(
296
312
  persisted?.preference ?? defaultMode
297
313
  );
298
314
  const [systemMode, setSystemMode] = useState2(() => system.get());
315
+ const [hydrated, setHydrated] = useState2(() => !storage.hydrate);
316
+ useEffect2(() => {
317
+ if (!storage.hydrate) return;
318
+ let active2 = true;
319
+ void storage.hydrate().then((raw) => {
320
+ if (!active2) return;
321
+ const clean = sanitizePersisted(raw);
322
+ if (clean.schema) setSchema(clean.schema);
323
+ if (clean.preference) setPreference(clean.preference);
324
+ setHydrated(true);
325
+ });
326
+ return () => {
327
+ active2 = false;
328
+ };
329
+ }, [storage]);
299
330
  useEffect2(() => {
300
331
  if (preference !== "system") return;
301
332
  const update = () => setSystemMode(system.get());
@@ -304,14 +335,17 @@ function useThemeStore(options, storage, system) {
304
335
  }, [preference, system]);
305
336
  const mode = resolveMode(preference, systemMode);
306
337
  useEffect2(() => {
338
+ if (!hydrated) return;
307
339
  storage.write({ schema, preference });
308
- }, [schema, preference, storage]);
340
+ }, [schema, preference, storage, hydrated]);
309
341
  return useMemo3(
310
342
  () => ({
311
343
  schema,
312
344
  mode,
313
345
  preference,
314
- colorTokens: schemas[schema][mode].color,
346
+ // Guard defensivo: un schema/modo inesperado (default inválido del caller) cae a
347
+ // tinta/light en vez de indexar `undefined` y crashear.
348
+ colorTokens: schemas[schema]?.[mode]?.color ?? schemas.tinta.light.color,
315
349
  setSchema,
316
350
  setMode: setPreference,
317
351
  toggleMode: () => setPreference(mode === "dark" ? "light" : "dark"),
@@ -1798,7 +1832,17 @@ function useStyles18({
1798
1832
 
1799
1833
  // src/components/select/index.tsx
1800
1834
  import { jsx as jsx31, jsxs as jsxs18 } from "react/jsx-runtime";
1801
- var Select = forwardRef20(function Select2({ options, value, onChange, placeholder: placeholder2, label: label7, disabled: disabled3, ...rest }, ref) {
1835
+ var Select = forwardRef20(function Select2({
1836
+ options,
1837
+ value,
1838
+ onChange,
1839
+ placeholder: placeholder2,
1840
+ label: label7,
1841
+ disabled: disabled3,
1842
+ "aria-label": ariaLabel,
1843
+ "aria-labelledby": ariaLabelledBy,
1844
+ ...rest
1845
+ }, ref) {
1802
1846
  const [open, setOpen] = useState6(false);
1803
1847
  const [activeIndex, setActiveIndex] = useState6(0);
1804
1848
  const rootRef = useRef3(null);
@@ -1810,6 +1854,7 @@ var Select = forwardRef20(function Select2({ options, value, onChange, placehold
1810
1854
  const baseId = useId3();
1811
1855
  const labelId = `${baseId}-label`;
1812
1856
  const optionId = (index) => `${baseId}-option-${index}`;
1857
+ const triggerLabelledBy = [label7 ? labelId : null, ariaLabelledBy].filter(Boolean).join(" ") || void 0;
1813
1858
  const {
1814
1859
  root: root24,
1815
1860
  label: labelClass,
@@ -1889,7 +1934,8 @@ var Select = forwardRef20(function Select2({ options, value, onChange, placehold
1889
1934
  disabled: disabled3,
1890
1935
  "aria-haspopup": "listbox",
1891
1936
  "aria-expanded": open,
1892
- "aria-labelledby": label7 ? labelId : void 0,
1937
+ "aria-label": ariaLabel,
1938
+ "aria-labelledby": triggerLabelledBy,
1893
1939
  "aria-activedescendant": open ? optionId(activeIndex) : void 0,
1894
1940
  onClick: () => {
1895
1941
  if (disabled3) return;