@doneisbetter/gds-theme 3.0.1 → 3.0.2

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.
@@ -0,0 +1,226 @@
1
+ import {
2
+ applyGdsFontLane,
3
+ gdsTheme,
4
+ getGdsFontLanes,
5
+ getGdsThemePresets,
6
+ resolveGdsThemePreset
7
+ } from "./chunk-TAPLA36E.mjs";
8
+
9
+ // src/theme-runtime.ts
10
+ import { useCallback, useEffect, useState } from "react";
11
+ var defaultStorageKey = "gds-theme-preset-selection";
12
+ function isThemePresetId(value) {
13
+ return typeof value === "string" && getGdsThemePresets().some((preset) => preset.id === value);
14
+ }
15
+ function isFontLaneId(value) {
16
+ return typeof value === "string" && getGdsFontLanes().some((lane) => lane.id === value);
17
+ }
18
+ function isScheme(value) {
19
+ return value === "light" || value === "dark" || value === "auto";
20
+ }
21
+ function resolveEffectiveScheme(preset, colorScheme) {
22
+ if (preset === "dark-public" || preset === "neon-night") {
23
+ return "dark";
24
+ }
25
+ return colorScheme;
26
+ }
27
+ function createGdsThemePresetSelection(stored = {}) {
28
+ const preset = isThemePresetId(stored.preset) ? stored.preset : "default";
29
+ const requestedColorScheme = isScheme(stored.colorScheme) ? stored.colorScheme : "light";
30
+ const colorScheme = resolveEffectiveScheme(preset, requestedColorScheme);
31
+ const fontLane = isFontLaneId(stored.fontLane) ? stored.fontLane : "inter";
32
+ const brandPrimary = typeof stored.brandPrimary === "string" ? stored.brandPrimary : "blue";
33
+ const brandFlatSurfaces = typeof stored.brandFlatSurfaces === "boolean" ? stored.brandFlatSurfaces : true;
34
+ const brandEditorialSerif = typeof stored.brandEditorialSerif === "boolean" ? stored.brandEditorialSerif : false;
35
+ const runtimeKey = `${preset}-${colorScheme}-${brandPrimary}-${brandFlatSurfaces}-${brandEditorialSerif}-${fontLane}`;
36
+ return {
37
+ preset,
38
+ colorScheme,
39
+ theme: applyGdsFontLane(resolveGdsThemePreset(preset, {
40
+ brandPrimary,
41
+ brandFlatSurfaces,
42
+ brandEditorialSerif
43
+ }), fontLane),
44
+ fontLane,
45
+ runtimeKey,
46
+ brandPrimary,
47
+ brandFlatSurfaces,
48
+ brandEditorialSerif
49
+ };
50
+ }
51
+ function readStoredSelection(storageKey, initialSelection) {
52
+ if (typeof window === "undefined") {
53
+ return createGdsThemePresetSelection(initialSelection);
54
+ }
55
+ try {
56
+ const stored = window.localStorage.getItem(storageKey);
57
+ return createGdsThemePresetSelection(stored ? JSON.parse(stored) : initialSelection);
58
+ } catch {
59
+ return createGdsThemePresetSelection(initialSelection);
60
+ }
61
+ }
62
+ function persistSelection(storageKey, selection) {
63
+ if (typeof window === "undefined") {
64
+ return;
65
+ }
66
+ const stored = {
67
+ preset: selection.preset,
68
+ colorScheme: selection.colorScheme,
69
+ fontLane: selection.fontLane,
70
+ runtimeKey: selection.runtimeKey,
71
+ brandPrimary: selection.brandPrimary,
72
+ brandFlatSurfaces: selection.brandFlatSurfaces,
73
+ brandEditorialSerif: selection.brandEditorialSerif
74
+ };
75
+ try {
76
+ window.localStorage.setItem(storageKey, JSON.stringify(stored));
77
+ } catch {
78
+ }
79
+ }
80
+ function resolveDocumentScheme(selection) {
81
+ if (selection.colorScheme !== "auto") {
82
+ return selection.colorScheme;
83
+ }
84
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
85
+ }
86
+ function applyDocumentRuntime(selection) {
87
+ document.documentElement.setAttribute("data-mantine-color-scheme", resolveDocumentScheme(selection));
88
+ document.documentElement.setAttribute("data-gds-theme-runtime", selection.runtimeKey ?? `${selection.preset}-${selection.colorScheme}`);
89
+ document.documentElement.setAttribute("data-gds-font-lane", selection.fontLane);
90
+ }
91
+ function useGdsThemePresetState({
92
+ storageKey = defaultStorageKey,
93
+ initialSelection,
94
+ applyToDocument = true
95
+ } = {}) {
96
+ const [selection, setSelection] = useState(() => readStoredSelection(storageKey, initialSelection));
97
+ useEffect(() => {
98
+ if (applyToDocument) {
99
+ applyDocumentRuntime(selection);
100
+ }
101
+ persistSelection(storageKey, selection);
102
+ if (!applyToDocument || selection.colorScheme !== "auto") {
103
+ return;
104
+ }
105
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
106
+ const handleChange = () => applyDocumentRuntime(selection);
107
+ mediaQuery.addEventListener("change", handleChange);
108
+ return () => {
109
+ mediaQuery.removeEventListener("change", handleChange);
110
+ };
111
+ }, [applyToDocument, selection, storageKey]);
112
+ const setRuntimeSelection = useCallback((nextSelection) => {
113
+ setSelection(createGdsThemePresetSelection(nextSelection));
114
+ }, []);
115
+ const setPreset = useCallback((preset) => {
116
+ setSelection((current) => createGdsThemePresetSelection({ ...current, preset }));
117
+ }, []);
118
+ const setScheme = useCallback((colorScheme) => {
119
+ setSelection((current) => createGdsThemePresetSelection({ ...current, colorScheme }));
120
+ }, []);
121
+ const setFontLane = useCallback((fontLane) => {
122
+ setSelection((current) => createGdsThemePresetSelection({ ...current, fontLane }));
123
+ }, []);
124
+ const setBrandOptions = useCallback((options) => {
125
+ setSelection((current) => createGdsThemePresetSelection({ ...current, ...options }));
126
+ }, []);
127
+ const reset = useCallback(() => {
128
+ setSelection(createGdsThemePresetSelection(initialSelection));
129
+ }, [initialSelection]);
130
+ return {
131
+ selection,
132
+ setSelection: setRuntimeSelection,
133
+ setPreset,
134
+ setScheme,
135
+ setFontLane,
136
+ setBrandOptions,
137
+ reset
138
+ };
139
+ }
140
+
141
+ // src/i18n.ts
142
+ import { createContext, useContext } from "react";
143
+ var GdsI18nContext = createContext({
144
+ locale: "en",
145
+ messages: {}
146
+ });
147
+ function useGdsTranslation() {
148
+ const { messages, locale } = useContext(GdsI18nContext);
149
+ return {
150
+ t: (id, defaultMessage) => messages[id] || defaultMessage,
151
+ locale
152
+ };
153
+ }
154
+
155
+ // src/GdsProvider.tsx
156
+ import { MantineProvider, DirectionProvider, Box } from "@mantine/core";
157
+ import { ModalsProvider } from "@mantine/modals";
158
+ import { Notifications } from "@mantine/notifications";
159
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
160
+ function GdsProvider({
161
+ children,
162
+ locale = "en",
163
+ messages = {},
164
+ theme = gdsTheme,
165
+ defaultColorScheme = "light",
166
+ forceColorScheme
167
+ }) {
168
+ const isRtl = ["ar", "he"].includes(locale);
169
+ const dir = isRtl ? "rtl" : "ltr";
170
+ return /* @__PURE__ */ jsx(DirectionProvider, { initialDirection: dir, children: /* @__PURE__ */ jsx(GdsI18nContext.Provider, { value: { locale, messages }, children: /* @__PURE__ */ jsx(
171
+ MantineProvider,
172
+ {
173
+ theme,
174
+ withCssVariables: true,
175
+ withGlobalClasses: true,
176
+ defaultColorScheme,
177
+ forceColorScheme,
178
+ children: /* @__PURE__ */ jsx(ModalsProvider, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
179
+ /* @__PURE__ */ jsx(Notifications, {}),
180
+ /* @__PURE__ */ jsx(
181
+ Box,
182
+ {
183
+ dir,
184
+ mih: "100vh",
185
+ h: "100%",
186
+ bg: "var(--mantine-color-body)",
187
+ c: "var(--mantine-color-text)",
188
+ style: { transition: "background-color 120ms ease, color 120ms ease" },
189
+ children
190
+ }
191
+ )
192
+ ] }) })
193
+ }
194
+ ) }) });
195
+ }
196
+
197
+ // src/notifications.ts
198
+ import { notifications } from "@mantine/notifications";
199
+ var toneColorMap = {
200
+ success: "teal",
201
+ error: "red",
202
+ warning: "yellow",
203
+ info: "blue",
204
+ neutral: "gray"
205
+ };
206
+ function showGdsNotification({
207
+ message,
208
+ title,
209
+ tone = "info",
210
+ autoClose
211
+ }) {
212
+ notifications.show({
213
+ message,
214
+ title,
215
+ color: toneColorMap[tone],
216
+ autoClose
217
+ });
218
+ }
219
+
220
+ export {
221
+ createGdsThemePresetSelection,
222
+ useGdsThemePresetState,
223
+ useGdsTranslation,
224
+ GdsProvider,
225
+ showGdsNotification
226
+ };
package/dist/client.d.mts CHANGED
@@ -1,7 +1,38 @@
1
- export { GdsFontLane, GdsFontLaneId, GdsThemePreset, GdsThemePresetId, applyGdsFontLane, createPublicBrandTheme, extendGdsTheme, gdsDarkPublicTheme, gdsEditorialPublicTheme, gdsFlatSurfaceTheme, gdsTheme, getGdsFontLanes, getGdsThemePresets, resolveGdsFontLane, resolveGdsThemePreset, withGdsMotion } from './server.mjs';
1
+ import { GdsThemePresetId, GdsFontLaneId } from './server.mjs';
2
+ export { GdsFontLane, GdsThemePreset, applyGdsFontLane, createPublicBrandTheme, extendGdsTheme, gdsDarkPublicTheme, gdsEditorialPublicTheme, gdsFlatSurfaceTheme, gdsTheme, getGdsFontLanes, getGdsThemePresets, resolveGdsFontLane, resolveGdsThemePreset, withGdsMotion } from './server.mjs';
3
+ import { MantineThemeOverride } from '@mantine/core';
2
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
5
  import React from 'react';
4
- import { MantineThemeOverride } from '@mantine/core';
6
+
7
+ type GdsThemeScheme = 'light' | 'dark' | 'auto';
8
+ interface GdsStoredThemePresetState {
9
+ preset: GdsThemePresetId;
10
+ colorScheme: GdsThemeScheme;
11
+ fontLane: GdsFontLaneId;
12
+ runtimeKey?: string;
13
+ brandPrimary?: string;
14
+ brandFlatSurfaces?: boolean;
15
+ brandEditorialSerif?: boolean;
16
+ }
17
+ interface GdsThemePresetSelection extends GdsStoredThemePresetState {
18
+ theme: MantineThemeOverride;
19
+ }
20
+ interface UseGdsThemePresetStateOptions {
21
+ storageKey?: string;
22
+ initialSelection?: Partial<GdsStoredThemePresetState>;
23
+ applyToDocument?: boolean;
24
+ }
25
+ interface UseGdsThemePresetStateResult {
26
+ selection: GdsThemePresetSelection;
27
+ setSelection: (selection: Partial<GdsStoredThemePresetState>) => void;
28
+ setPreset: (preset: GdsThemePresetId) => void;
29
+ setScheme: (scheme: GdsThemeScheme) => void;
30
+ setFontLane: (fontLane: GdsFontLaneId) => void;
31
+ setBrandOptions: (options: Pick<GdsStoredThemePresetState, 'brandPrimary' | 'brandFlatSurfaces' | 'brandEditorialSerif'>) => void;
32
+ reset: () => void;
33
+ }
34
+ declare function createGdsThemePresetSelection(stored?: Partial<GdsStoredThemePresetState>): GdsThemePresetSelection;
35
+ declare function useGdsThemePresetState({ storageKey, initialSelection, applyToDocument, }?: UseGdsThemePresetStateOptions): UseGdsThemePresetStateResult;
5
36
 
6
37
  interface GdsProviderProps {
7
38
  children: React.ReactNode;
@@ -36,4 +67,4 @@ interface GdsNotificationOptions {
36
67
  }
37
68
  declare function showGdsNotification({ message, title, tone, autoClose, }: GdsNotificationOptions): void;
38
69
 
39
- export { type GdsNotificationOptions, type GdsNotificationTone, GdsProvider, type GdsProviderProps, showGdsNotification, useGdsTranslation };
70
+ export { GdsFontLaneId, type GdsNotificationOptions, type GdsNotificationTone, GdsProvider, type GdsProviderProps, type GdsStoredThemePresetState, GdsThemePresetId, type GdsThemePresetSelection, type GdsThemeScheme, type UseGdsThemePresetStateOptions, type UseGdsThemePresetStateResult, createGdsThemePresetSelection, showGdsNotification, useGdsThemePresetState, useGdsTranslation };
package/dist/client.d.ts CHANGED
@@ -1,7 +1,38 @@
1
- export { GdsFontLane, GdsFontLaneId, GdsThemePreset, GdsThemePresetId, applyGdsFontLane, createPublicBrandTheme, extendGdsTheme, gdsDarkPublicTheme, gdsEditorialPublicTheme, gdsFlatSurfaceTheme, gdsTheme, getGdsFontLanes, getGdsThemePresets, resolveGdsFontLane, resolveGdsThemePreset, withGdsMotion } from './server.js';
1
+ import { GdsThemePresetId, GdsFontLaneId } from './server.js';
2
+ export { GdsFontLane, GdsThemePreset, applyGdsFontLane, createPublicBrandTheme, extendGdsTheme, gdsDarkPublicTheme, gdsEditorialPublicTheme, gdsFlatSurfaceTheme, gdsTheme, getGdsFontLanes, getGdsThemePresets, resolveGdsFontLane, resolveGdsThemePreset, withGdsMotion } from './server.js';
3
+ import { MantineThemeOverride } from '@mantine/core';
2
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
5
  import React from 'react';
4
- import { MantineThemeOverride } from '@mantine/core';
6
+
7
+ type GdsThemeScheme = 'light' | 'dark' | 'auto';
8
+ interface GdsStoredThemePresetState {
9
+ preset: GdsThemePresetId;
10
+ colorScheme: GdsThemeScheme;
11
+ fontLane: GdsFontLaneId;
12
+ runtimeKey?: string;
13
+ brandPrimary?: string;
14
+ brandFlatSurfaces?: boolean;
15
+ brandEditorialSerif?: boolean;
16
+ }
17
+ interface GdsThemePresetSelection extends GdsStoredThemePresetState {
18
+ theme: MantineThemeOverride;
19
+ }
20
+ interface UseGdsThemePresetStateOptions {
21
+ storageKey?: string;
22
+ initialSelection?: Partial<GdsStoredThemePresetState>;
23
+ applyToDocument?: boolean;
24
+ }
25
+ interface UseGdsThemePresetStateResult {
26
+ selection: GdsThemePresetSelection;
27
+ setSelection: (selection: Partial<GdsStoredThemePresetState>) => void;
28
+ setPreset: (preset: GdsThemePresetId) => void;
29
+ setScheme: (scheme: GdsThemeScheme) => void;
30
+ setFontLane: (fontLane: GdsFontLaneId) => void;
31
+ setBrandOptions: (options: Pick<GdsStoredThemePresetState, 'brandPrimary' | 'brandFlatSurfaces' | 'brandEditorialSerif'>) => void;
32
+ reset: () => void;
33
+ }
34
+ declare function createGdsThemePresetSelection(stored?: Partial<GdsStoredThemePresetState>): GdsThemePresetSelection;
35
+ declare function useGdsThemePresetState({ storageKey, initialSelection, applyToDocument, }?: UseGdsThemePresetStateOptions): UseGdsThemePresetStateResult;
5
36
 
6
37
  interface GdsProviderProps {
7
38
  children: React.ReactNode;
@@ -36,4 +67,4 @@ interface GdsNotificationOptions {
36
67
  }
37
68
  declare function showGdsNotification({ message, title, tone, autoClose, }: GdsNotificationOptions): void;
38
69
 
39
- export { type GdsNotificationOptions, type GdsNotificationTone, GdsProvider, type GdsProviderProps, showGdsNotification, useGdsTranslation };
70
+ export { GdsFontLaneId, type GdsNotificationOptions, type GdsNotificationTone, GdsProvider, type GdsProviderProps, type GdsStoredThemePresetState, GdsThemePresetId, type GdsThemePresetSelection, type GdsThemeScheme, type UseGdsThemePresetStateOptions, type UseGdsThemePresetStateResult, createGdsThemePresetSelection, showGdsNotification, useGdsThemePresetState, useGdsTranslation };
package/dist/client.js CHANGED
@@ -22,6 +22,7 @@ var client_exports = {};
22
22
  __export(client_exports, {
23
23
  GdsProvider: () => GdsProvider,
24
24
  applyGdsFontLane: () => applyGdsFontLane,
25
+ createGdsThemePresetSelection: () => createGdsThemePresetSelection,
25
26
  createPublicBrandTheme: () => createPublicBrandTheme,
26
27
  extendGdsTheme: () => extendGdsTheme,
27
28
  gdsDarkPublicTheme: () => gdsDarkPublicTheme,
@@ -33,6 +34,7 @@ __export(client_exports, {
33
34
  resolveGdsFontLane: () => resolveGdsFontLane,
34
35
  resolveGdsThemePreset: () => resolveGdsThemePreset,
35
36
  showGdsNotification: () => showGdsNotification,
37
+ useGdsThemePresetState: () => useGdsThemePresetState,
36
38
  useGdsTranslation: () => useGdsTranslation,
37
39
  withGdsMotion: () => withGdsMotion
38
40
  });
@@ -378,19 +380,151 @@ function applyGdsFontLane(theme, laneId) {
378
380
  });
379
381
  }
380
382
 
383
+ // src/theme-runtime.ts
384
+ var import_react = require("react");
385
+ var defaultStorageKey = "gds-theme-preset-selection";
386
+ function isThemePresetId(value) {
387
+ return typeof value === "string" && getGdsThemePresets().some((preset) => preset.id === value);
388
+ }
389
+ function isFontLaneId(value) {
390
+ return typeof value === "string" && getGdsFontLanes().some((lane) => lane.id === value);
391
+ }
392
+ function isScheme(value) {
393
+ return value === "light" || value === "dark" || value === "auto";
394
+ }
395
+ function resolveEffectiveScheme(preset, colorScheme) {
396
+ if (preset === "dark-public" || preset === "neon-night") {
397
+ return "dark";
398
+ }
399
+ return colorScheme;
400
+ }
401
+ function createGdsThemePresetSelection(stored = {}) {
402
+ const preset = isThemePresetId(stored.preset) ? stored.preset : "default";
403
+ const requestedColorScheme = isScheme(stored.colorScheme) ? stored.colorScheme : "light";
404
+ const colorScheme = resolveEffectiveScheme(preset, requestedColorScheme);
405
+ const fontLane = isFontLaneId(stored.fontLane) ? stored.fontLane : "inter";
406
+ const brandPrimary = typeof stored.brandPrimary === "string" ? stored.brandPrimary : "blue";
407
+ const brandFlatSurfaces = typeof stored.brandFlatSurfaces === "boolean" ? stored.brandFlatSurfaces : true;
408
+ const brandEditorialSerif = typeof stored.brandEditorialSerif === "boolean" ? stored.brandEditorialSerif : false;
409
+ const runtimeKey = `${preset}-${colorScheme}-${brandPrimary}-${brandFlatSurfaces}-${brandEditorialSerif}-${fontLane}`;
410
+ return {
411
+ preset,
412
+ colorScheme,
413
+ theme: applyGdsFontLane(resolveGdsThemePreset(preset, {
414
+ brandPrimary,
415
+ brandFlatSurfaces,
416
+ brandEditorialSerif
417
+ }), fontLane),
418
+ fontLane,
419
+ runtimeKey,
420
+ brandPrimary,
421
+ brandFlatSurfaces,
422
+ brandEditorialSerif
423
+ };
424
+ }
425
+ function readStoredSelection(storageKey, initialSelection) {
426
+ if (typeof window === "undefined") {
427
+ return createGdsThemePresetSelection(initialSelection);
428
+ }
429
+ try {
430
+ const stored = window.localStorage.getItem(storageKey);
431
+ return createGdsThemePresetSelection(stored ? JSON.parse(stored) : initialSelection);
432
+ } catch {
433
+ return createGdsThemePresetSelection(initialSelection);
434
+ }
435
+ }
436
+ function persistSelection(storageKey, selection) {
437
+ if (typeof window === "undefined") {
438
+ return;
439
+ }
440
+ const stored = {
441
+ preset: selection.preset,
442
+ colorScheme: selection.colorScheme,
443
+ fontLane: selection.fontLane,
444
+ runtimeKey: selection.runtimeKey,
445
+ brandPrimary: selection.brandPrimary,
446
+ brandFlatSurfaces: selection.brandFlatSurfaces,
447
+ brandEditorialSerif: selection.brandEditorialSerif
448
+ };
449
+ try {
450
+ window.localStorage.setItem(storageKey, JSON.stringify(stored));
451
+ } catch {
452
+ }
453
+ }
454
+ function resolveDocumentScheme(selection) {
455
+ if (selection.colorScheme !== "auto") {
456
+ return selection.colorScheme;
457
+ }
458
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
459
+ }
460
+ function applyDocumentRuntime(selection) {
461
+ document.documentElement.setAttribute("data-mantine-color-scheme", resolveDocumentScheme(selection));
462
+ document.documentElement.setAttribute("data-gds-theme-runtime", selection.runtimeKey ?? `${selection.preset}-${selection.colorScheme}`);
463
+ document.documentElement.setAttribute("data-gds-font-lane", selection.fontLane);
464
+ }
465
+ function useGdsThemePresetState({
466
+ storageKey = defaultStorageKey,
467
+ initialSelection,
468
+ applyToDocument = true
469
+ } = {}) {
470
+ const [selection, setSelection] = (0, import_react.useState)(() => readStoredSelection(storageKey, initialSelection));
471
+ (0, import_react.useEffect)(() => {
472
+ if (applyToDocument) {
473
+ applyDocumentRuntime(selection);
474
+ }
475
+ persistSelection(storageKey, selection);
476
+ if (!applyToDocument || selection.colorScheme !== "auto") {
477
+ return;
478
+ }
479
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
480
+ const handleChange = () => applyDocumentRuntime(selection);
481
+ mediaQuery.addEventListener("change", handleChange);
482
+ return () => {
483
+ mediaQuery.removeEventListener("change", handleChange);
484
+ };
485
+ }, [applyToDocument, selection, storageKey]);
486
+ const setRuntimeSelection = (0, import_react.useCallback)((nextSelection) => {
487
+ setSelection(createGdsThemePresetSelection(nextSelection));
488
+ }, []);
489
+ const setPreset = (0, import_react.useCallback)((preset) => {
490
+ setSelection((current) => createGdsThemePresetSelection({ ...current, preset }));
491
+ }, []);
492
+ const setScheme = (0, import_react.useCallback)((colorScheme) => {
493
+ setSelection((current) => createGdsThemePresetSelection({ ...current, colorScheme }));
494
+ }, []);
495
+ const setFontLane = (0, import_react.useCallback)((fontLane) => {
496
+ setSelection((current) => createGdsThemePresetSelection({ ...current, fontLane }));
497
+ }, []);
498
+ const setBrandOptions = (0, import_react.useCallback)((options) => {
499
+ setSelection((current) => createGdsThemePresetSelection({ ...current, ...options }));
500
+ }, []);
501
+ const reset = (0, import_react.useCallback)(() => {
502
+ setSelection(createGdsThemePresetSelection(initialSelection));
503
+ }, [initialSelection]);
504
+ return {
505
+ selection,
506
+ setSelection: setRuntimeSelection,
507
+ setPreset,
508
+ setScheme,
509
+ setFontLane,
510
+ setBrandOptions,
511
+ reset
512
+ };
513
+ }
514
+
381
515
  // src/GdsProvider.tsx
382
516
  var import_core3 = require("@mantine/core");
383
517
  var import_modals = require("@mantine/modals");
384
518
  var import_notifications = require("@mantine/notifications");
385
519
 
386
520
  // src/i18n.ts
387
- var import_react = require("react");
388
- var GdsI18nContext = (0, import_react.createContext)({
521
+ var import_react2 = require("react");
522
+ var GdsI18nContext = (0, import_react2.createContext)({
389
523
  locale: "en",
390
524
  messages: {}
391
525
  });
392
526
  function useGdsTranslation() {
393
- const { messages, locale } = (0, import_react.useContext)(GdsI18nContext);
527
+ const { messages, locale } = (0, import_react2.useContext)(GdsI18nContext);
394
528
  return {
395
529
  t: (id, defaultMessage) => messages[id] || defaultMessage,
396
530
  locale
@@ -462,6 +596,7 @@ function showGdsNotification({
462
596
  0 && (module.exports = {
463
597
  GdsProvider,
464
598
  applyGdsFontLane,
599
+ createGdsThemePresetSelection,
465
600
  createPublicBrandTheme,
466
601
  extendGdsTheme,
467
602
  gdsDarkPublicTheme,
@@ -473,6 +608,7 @@ function showGdsNotification({
473
608
  resolveGdsFontLane,
474
609
  resolveGdsThemePreset,
475
610
  showGdsNotification,
611
+ useGdsThemePresetState,
476
612
  useGdsTranslation,
477
613
  withGdsMotion
478
614
  });
package/dist/client.mjs CHANGED
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  GdsProvider,
3
+ createGdsThemePresetSelection,
3
4
  showGdsNotification,
5
+ useGdsThemePresetState,
4
6
  useGdsTranslation
5
- } from "./chunk-7B3MG4NV.mjs";
7
+ } from "./chunk-E55P7FOX.mjs";
6
8
  import {
7
9
  applyGdsFontLane,
8
10
  createPublicBrandTheme,
@@ -20,6 +22,7 @@ import {
20
22
  export {
21
23
  GdsProvider,
22
24
  applyGdsFontLane,
25
+ createGdsThemePresetSelection,
23
26
  createPublicBrandTheme,
24
27
  extendGdsTheme,
25
28
  gdsDarkPublicTheme,
@@ -31,6 +34,7 @@ export {
31
34
  resolveGdsFontLane,
32
35
  resolveGdsThemePreset,
33
36
  showGdsNotification,
37
+ useGdsThemePresetState,
34
38
  useGdsTranslation,
35
39
  withGdsMotion
36
40
  };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { GdsFontLane, GdsFontLaneId, GdsThemePreset, GdsThemePresetId, applyGdsFontLane, createPublicBrandTheme, extendGdsTheme, gdsDarkPublicTheme, gdsEditorialPublicTheme, gdsFlatSurfaceTheme, gdsTheme, getGdsFontLanes, getGdsThemePresets, resolveGdsFontLane, resolveGdsThemePreset, withGdsMotion } from './server.mjs';
2
- export { GdsNotificationOptions, GdsNotificationTone, GdsProvider, GdsProviderProps, showGdsNotification, useGdsTranslation } from './client.mjs';
2
+ export { GdsNotificationOptions, GdsNotificationTone, GdsProvider, GdsProviderProps, GdsStoredThemePresetState, GdsThemePresetSelection, GdsThemeScheme, UseGdsThemePresetStateOptions, UseGdsThemePresetStateResult, createGdsThemePresetSelection, showGdsNotification, useGdsThemePresetState, useGdsTranslation } from './client.mjs';
3
3
  import '@mantine/core';
4
4
  import 'react/jsx-runtime';
5
5
  import 'react';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { GdsFontLane, GdsFontLaneId, GdsThemePreset, GdsThemePresetId, applyGdsFontLane, createPublicBrandTheme, extendGdsTheme, gdsDarkPublicTheme, gdsEditorialPublicTheme, gdsFlatSurfaceTheme, gdsTheme, getGdsFontLanes, getGdsThemePresets, resolveGdsFontLane, resolveGdsThemePreset, withGdsMotion } from './server.js';
2
- export { GdsNotificationOptions, GdsNotificationTone, GdsProvider, GdsProviderProps, showGdsNotification, useGdsTranslation } from './client.js';
2
+ export { GdsNotificationOptions, GdsNotificationTone, GdsProvider, GdsProviderProps, GdsStoredThemePresetState, GdsThemePresetSelection, GdsThemeScheme, UseGdsThemePresetStateOptions, UseGdsThemePresetStateResult, createGdsThemePresetSelection, showGdsNotification, useGdsThemePresetState, useGdsTranslation } from './client.js';
3
3
  import '@mantine/core';
4
4
  import 'react/jsx-runtime';
5
5
  import 'react';
package/dist/index.js CHANGED
@@ -22,6 +22,7 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  GdsProvider: () => GdsProvider,
24
24
  applyGdsFontLane: () => applyGdsFontLane,
25
+ createGdsThemePresetSelection: () => createGdsThemePresetSelection,
25
26
  createPublicBrandTheme: () => createPublicBrandTheme,
26
27
  extendGdsTheme: () => extendGdsTheme,
27
28
  gdsDarkPublicTheme: () => gdsDarkPublicTheme,
@@ -33,6 +34,7 @@ __export(index_exports, {
33
34
  resolveGdsFontLane: () => resolveGdsFontLane,
34
35
  resolveGdsThemePreset: () => resolveGdsThemePreset,
35
36
  showGdsNotification: () => showGdsNotification,
37
+ useGdsThemePresetState: () => useGdsThemePresetState,
36
38
  useGdsTranslation: () => useGdsTranslation,
37
39
  withGdsMotion: () => withGdsMotion
38
40
  });
@@ -378,19 +380,151 @@ function applyGdsFontLane(theme, laneId) {
378
380
  });
379
381
  }
380
382
 
383
+ // src/theme-runtime.ts
384
+ var import_react = require("react");
385
+ var defaultStorageKey = "gds-theme-preset-selection";
386
+ function isThemePresetId(value) {
387
+ return typeof value === "string" && getGdsThemePresets().some((preset) => preset.id === value);
388
+ }
389
+ function isFontLaneId(value) {
390
+ return typeof value === "string" && getGdsFontLanes().some((lane) => lane.id === value);
391
+ }
392
+ function isScheme(value) {
393
+ return value === "light" || value === "dark" || value === "auto";
394
+ }
395
+ function resolveEffectiveScheme(preset, colorScheme) {
396
+ if (preset === "dark-public" || preset === "neon-night") {
397
+ return "dark";
398
+ }
399
+ return colorScheme;
400
+ }
401
+ function createGdsThemePresetSelection(stored = {}) {
402
+ const preset = isThemePresetId(stored.preset) ? stored.preset : "default";
403
+ const requestedColorScheme = isScheme(stored.colorScheme) ? stored.colorScheme : "light";
404
+ const colorScheme = resolveEffectiveScheme(preset, requestedColorScheme);
405
+ const fontLane = isFontLaneId(stored.fontLane) ? stored.fontLane : "inter";
406
+ const brandPrimary = typeof stored.brandPrimary === "string" ? stored.brandPrimary : "blue";
407
+ const brandFlatSurfaces = typeof stored.brandFlatSurfaces === "boolean" ? stored.brandFlatSurfaces : true;
408
+ const brandEditorialSerif = typeof stored.brandEditorialSerif === "boolean" ? stored.brandEditorialSerif : false;
409
+ const runtimeKey = `${preset}-${colorScheme}-${brandPrimary}-${brandFlatSurfaces}-${brandEditorialSerif}-${fontLane}`;
410
+ return {
411
+ preset,
412
+ colorScheme,
413
+ theme: applyGdsFontLane(resolveGdsThemePreset(preset, {
414
+ brandPrimary,
415
+ brandFlatSurfaces,
416
+ brandEditorialSerif
417
+ }), fontLane),
418
+ fontLane,
419
+ runtimeKey,
420
+ brandPrimary,
421
+ brandFlatSurfaces,
422
+ brandEditorialSerif
423
+ };
424
+ }
425
+ function readStoredSelection(storageKey, initialSelection) {
426
+ if (typeof window === "undefined") {
427
+ return createGdsThemePresetSelection(initialSelection);
428
+ }
429
+ try {
430
+ const stored = window.localStorage.getItem(storageKey);
431
+ return createGdsThemePresetSelection(stored ? JSON.parse(stored) : initialSelection);
432
+ } catch {
433
+ return createGdsThemePresetSelection(initialSelection);
434
+ }
435
+ }
436
+ function persistSelection(storageKey, selection) {
437
+ if (typeof window === "undefined") {
438
+ return;
439
+ }
440
+ const stored = {
441
+ preset: selection.preset,
442
+ colorScheme: selection.colorScheme,
443
+ fontLane: selection.fontLane,
444
+ runtimeKey: selection.runtimeKey,
445
+ brandPrimary: selection.brandPrimary,
446
+ brandFlatSurfaces: selection.brandFlatSurfaces,
447
+ brandEditorialSerif: selection.brandEditorialSerif
448
+ };
449
+ try {
450
+ window.localStorage.setItem(storageKey, JSON.stringify(stored));
451
+ } catch {
452
+ }
453
+ }
454
+ function resolveDocumentScheme(selection) {
455
+ if (selection.colorScheme !== "auto") {
456
+ return selection.colorScheme;
457
+ }
458
+ return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
459
+ }
460
+ function applyDocumentRuntime(selection) {
461
+ document.documentElement.setAttribute("data-mantine-color-scheme", resolveDocumentScheme(selection));
462
+ document.documentElement.setAttribute("data-gds-theme-runtime", selection.runtimeKey ?? `${selection.preset}-${selection.colorScheme}`);
463
+ document.documentElement.setAttribute("data-gds-font-lane", selection.fontLane);
464
+ }
465
+ function useGdsThemePresetState({
466
+ storageKey = defaultStorageKey,
467
+ initialSelection,
468
+ applyToDocument = true
469
+ } = {}) {
470
+ const [selection, setSelection] = (0, import_react.useState)(() => readStoredSelection(storageKey, initialSelection));
471
+ (0, import_react.useEffect)(() => {
472
+ if (applyToDocument) {
473
+ applyDocumentRuntime(selection);
474
+ }
475
+ persistSelection(storageKey, selection);
476
+ if (!applyToDocument || selection.colorScheme !== "auto") {
477
+ return;
478
+ }
479
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
480
+ const handleChange = () => applyDocumentRuntime(selection);
481
+ mediaQuery.addEventListener("change", handleChange);
482
+ return () => {
483
+ mediaQuery.removeEventListener("change", handleChange);
484
+ };
485
+ }, [applyToDocument, selection, storageKey]);
486
+ const setRuntimeSelection = (0, import_react.useCallback)((nextSelection) => {
487
+ setSelection(createGdsThemePresetSelection(nextSelection));
488
+ }, []);
489
+ const setPreset = (0, import_react.useCallback)((preset) => {
490
+ setSelection((current) => createGdsThemePresetSelection({ ...current, preset }));
491
+ }, []);
492
+ const setScheme = (0, import_react.useCallback)((colorScheme) => {
493
+ setSelection((current) => createGdsThemePresetSelection({ ...current, colorScheme }));
494
+ }, []);
495
+ const setFontLane = (0, import_react.useCallback)((fontLane) => {
496
+ setSelection((current) => createGdsThemePresetSelection({ ...current, fontLane }));
497
+ }, []);
498
+ const setBrandOptions = (0, import_react.useCallback)((options) => {
499
+ setSelection((current) => createGdsThemePresetSelection({ ...current, ...options }));
500
+ }, []);
501
+ const reset = (0, import_react.useCallback)(() => {
502
+ setSelection(createGdsThemePresetSelection(initialSelection));
503
+ }, [initialSelection]);
504
+ return {
505
+ selection,
506
+ setSelection: setRuntimeSelection,
507
+ setPreset,
508
+ setScheme,
509
+ setFontLane,
510
+ setBrandOptions,
511
+ reset
512
+ };
513
+ }
514
+
381
515
  // src/GdsProvider.tsx
382
516
  var import_core3 = require("@mantine/core");
383
517
  var import_modals = require("@mantine/modals");
384
518
  var import_notifications = require("@mantine/notifications");
385
519
 
386
520
  // src/i18n.ts
387
- var import_react = require("react");
388
- var GdsI18nContext = (0, import_react.createContext)({
521
+ var import_react2 = require("react");
522
+ var GdsI18nContext = (0, import_react2.createContext)({
389
523
  locale: "en",
390
524
  messages: {}
391
525
  });
392
526
  function useGdsTranslation() {
393
- const { messages, locale } = (0, import_react.useContext)(GdsI18nContext);
527
+ const { messages, locale } = (0, import_react2.useContext)(GdsI18nContext);
394
528
  return {
395
529
  t: (id, defaultMessage) => messages[id] || defaultMessage,
396
530
  locale
@@ -462,6 +596,7 @@ function showGdsNotification({
462
596
  0 && (module.exports = {
463
597
  GdsProvider,
464
598
  applyGdsFontLane,
599
+ createGdsThemePresetSelection,
465
600
  createPublicBrandTheme,
466
601
  extendGdsTheme,
467
602
  gdsDarkPublicTheme,
@@ -473,6 +608,7 @@ function showGdsNotification({
473
608
  resolveGdsFontLane,
474
609
  resolveGdsThemePreset,
475
610
  showGdsNotification,
611
+ useGdsThemePresetState,
476
612
  useGdsTranslation,
477
613
  withGdsMotion
478
614
  });
package/dist/index.mjs CHANGED
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  GdsProvider,
3
+ createGdsThemePresetSelection,
3
4
  showGdsNotification,
5
+ useGdsThemePresetState,
4
6
  useGdsTranslation
5
- } from "./chunk-7B3MG4NV.mjs";
7
+ } from "./chunk-E55P7FOX.mjs";
6
8
  import {
7
9
  applyGdsFontLane,
8
10
  createPublicBrandTheme,
@@ -20,6 +22,7 @@ import {
20
22
  export {
21
23
  GdsProvider,
22
24
  applyGdsFontLane,
25
+ createGdsThemePresetSelection,
23
26
  createPublicBrandTheme,
24
27
  extendGdsTheme,
25
28
  gdsDarkPublicTheme,
@@ -31,6 +34,7 @@ export {
31
34
  resolveGdsFontLane,
32
35
  resolveGdsThemePreset,
33
36
  showGdsNotification,
37
+ useGdsThemePresetState,
34
38
  useGdsTranslation,
35
39
  withGdsMotion
36
40
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doneisbetter/gds-theme",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -1,88 +0,0 @@
1
- import {
2
- gdsTheme
3
- } from "./chunk-TAPLA36E.mjs";
4
-
5
- // src/i18n.ts
6
- import { createContext, useContext } from "react";
7
- var GdsI18nContext = createContext({
8
- locale: "en",
9
- messages: {}
10
- });
11
- function useGdsTranslation() {
12
- const { messages, locale } = useContext(GdsI18nContext);
13
- return {
14
- t: (id, defaultMessage) => messages[id] || defaultMessage,
15
- locale
16
- };
17
- }
18
-
19
- // src/GdsProvider.tsx
20
- import { MantineProvider, DirectionProvider, Box } from "@mantine/core";
21
- import { ModalsProvider } from "@mantine/modals";
22
- import { Notifications } from "@mantine/notifications";
23
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
24
- function GdsProvider({
25
- children,
26
- locale = "en",
27
- messages = {},
28
- theme = gdsTheme,
29
- defaultColorScheme = "light",
30
- forceColorScheme
31
- }) {
32
- const isRtl = ["ar", "he"].includes(locale);
33
- const dir = isRtl ? "rtl" : "ltr";
34
- return /* @__PURE__ */ jsx(DirectionProvider, { initialDirection: dir, children: /* @__PURE__ */ jsx(GdsI18nContext.Provider, { value: { locale, messages }, children: /* @__PURE__ */ jsx(
35
- MantineProvider,
36
- {
37
- theme,
38
- withCssVariables: true,
39
- withGlobalClasses: true,
40
- defaultColorScheme,
41
- forceColorScheme,
42
- children: /* @__PURE__ */ jsx(ModalsProvider, { children: /* @__PURE__ */ jsxs(Fragment, { children: [
43
- /* @__PURE__ */ jsx(Notifications, {}),
44
- /* @__PURE__ */ jsx(
45
- Box,
46
- {
47
- dir,
48
- mih: "100vh",
49
- h: "100%",
50
- bg: "var(--mantine-color-body)",
51
- c: "var(--mantine-color-text)",
52
- style: { transition: "background-color 120ms ease, color 120ms ease" },
53
- children
54
- }
55
- )
56
- ] }) })
57
- }
58
- ) }) });
59
- }
60
-
61
- // src/notifications.ts
62
- import { notifications } from "@mantine/notifications";
63
- var toneColorMap = {
64
- success: "teal",
65
- error: "red",
66
- warning: "yellow",
67
- info: "blue",
68
- neutral: "gray"
69
- };
70
- function showGdsNotification({
71
- message,
72
- title,
73
- tone = "info",
74
- autoClose
75
- }) {
76
- notifications.show({
77
- message,
78
- title,
79
- color: toneColorMap[tone],
80
- autoClose
81
- });
82
- }
83
-
84
- export {
85
- useGdsTranslation,
86
- GdsProvider,
87
- showGdsNotification
88
- };