@octavius2929-personal/design-system 0.22.1 → 0.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.
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"),