@lar-works/design-system 0.1.0 → 0.1.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.
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export type ThemePreference = 'system' | 'light' | 'dark';
|
|
2
2
|
export interface ThemeController {
|
|
3
3
|
/** Applies the stored preference before the first render, so the page never flashes the other theme. */
|
|
4
|
-
initialize()
|
|
4
|
+
initialize: () => void;
|
|
5
5
|
/** The current preference and a setter that stores and applies it, kept in step across tabs. */
|
|
6
|
-
useTheme()
|
|
6
|
+
useTheme: () => readonly [ThemePreference, (value: ThemePreference) => void];
|
|
7
7
|
}
|
|
8
8
|
export declare function isThemePreference(value: string): value is ThemePreference;
|
|
9
9
|
/**
|
|
@@ -38,9 +38,7 @@ function createThemeController(storageKey) {
|
|
|
38
38
|
}
|
|
39
39
|
return {
|
|
40
40
|
initialize: () => applyThemePreference(read()),
|
|
41
|
-
useTheme()
|
|
42
|
-
return [useSyncExternalStore(subscribe, read, () => "system"), set];
|
|
43
|
-
}
|
|
41
|
+
useTheme: () => [useSyncExternalStore(subscribe, read, () => "system"), set]
|
|
44
42
|
};
|
|
45
43
|
}
|
|
46
44
|
function applyThemePreference(preference) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Theme.js","names":[],"sources":["../../src/foundations/Theme.ts"],"sourcesContent":["import { useSyncExternalStore } from 'react';\n\nexport type ThemePreference = 'system' | 'light' | 'dark';\n\nexport interface ThemeController {\n /** Applies the stored preference before the first render, so the page never flashes the other theme. */\n initialize()
|
|
1
|
+
{"version":3,"file":"Theme.js","names":[],"sources":["../../src/foundations/Theme.ts"],"sourcesContent":["import { useSyncExternalStore } from 'react';\n\nexport type ThemePreference = 'system' | 'light' | 'dark';\n\nexport interface ThemeController {\n /** Applies the stored preference before the first render, so the page never flashes the other theme. */\n initialize: () => void;\n /** The current preference and a setter that stores and applies it, kept in step across tabs. */\n useTheme: () => readonly [ThemePreference, (value: ThemePreference) => void];\n}\n\nexport function isThemePreference(value: string): value is ThemePreference {\n return value === 'system' || value === 'light' || value === 'dark';\n}\n\n/** The page backgrounds, which Safari and installed web apps extend into their own chrome. */\nconst themeColors = { light: '#fcfcfc', dark: '#0a0a0a' } as const;\n\n/**\n * The light/dark preference of one app, stored under `storageKey` in localStorage. The preference sets `.light` or\n * `.dark` on <html> (nothing follows the system) and points the page's `theme-color` metas at the matching background.\n */\nexport function createThemeController(storageKey: string): ThemeController {\n const changeEvent = `${storageKey}-change`;\n\n function read(): ThemePreference {\n const stored = window.localStorage.getItem(storageKey);\n\n return stored && isThemePreference(stored) ? stored : 'system';\n }\n\n function set(preference: ThemePreference): void {\n window.localStorage.setItem(storageKey, preference);\n applyThemePreference(preference);\n window.dispatchEvent(new Event(changeEvent));\n }\n\n function subscribe(onChange: () => void): () => void {\n function handleStorageChange(event: StorageEvent): void {\n if (event.key !== storageKey) return;\n\n applyThemePreference(read());\n onChange();\n }\n\n window.addEventListener(changeEvent, onChange);\n window.addEventListener('storage', handleStorageChange);\n\n return () => {\n window.removeEventListener(changeEvent, onChange);\n window.removeEventListener('storage', handleStorageChange);\n };\n }\n\n return {\n initialize: () => applyThemePreference(read()),\n useTheme: () => [useSyncExternalStore(subscribe, read, () => 'system' as const), set] as const,\n };\n}\n\nfunction applyThemePreference(preference: ThemePreference): void {\n document.documentElement.classList.remove('light', 'dark');\n\n if (preference !== 'system') document.documentElement.classList.add(preference);\n\n for (const meta of document.querySelectorAll<HTMLMetaElement>('meta[name=\"theme-color\"]')) {\n const scheme = meta.getAttribute('media')?.includes('dark') ? 'dark' : 'light';\n\n meta.content = themeColors[preference === 'system' ? scheme : preference];\n }\n}\n"],"mappings":";;AAWA,SAAgB,kBAAkB,OAAyC;CACvE,OAAO,UAAU,YAAY,UAAU,WAAW,UAAU;AAChE;;AAGA,MAAM,cAAc;CAAE,OAAO;CAAW,MAAM;AAAU;;;;;AAMxD,SAAgB,sBAAsB,YAAqC;CACvE,MAAM,cAAc,GAAG,WAAW;CAElC,SAAS,OAAwB;EAC7B,MAAM,SAAS,OAAO,aAAa,QAAQ,UAAU;EAErD,OAAO,UAAU,kBAAkB,MAAM,IAAI,SAAS;CAC1D;CAEA,SAAS,IAAI,YAAmC;EAC5C,OAAO,aAAa,QAAQ,YAAY,UAAU;EAClD,qBAAqB,UAAU;EAC/B,OAAO,cAAc,IAAI,MAAM,WAAW,CAAC;CAC/C;CAEA,SAAS,UAAU,UAAkC;EACjD,SAAS,oBAAoB,OAA2B;GACpD,IAAI,MAAM,QAAQ,YAAY;GAE9B,qBAAqB,KAAK,CAAC;GAC3B,SAAS;EACb;EAEA,OAAO,iBAAiB,aAAa,QAAQ;EAC7C,OAAO,iBAAiB,WAAW,mBAAmB;EAEtD,aAAa;GACT,OAAO,oBAAoB,aAAa,QAAQ;GAChD,OAAO,oBAAoB,WAAW,mBAAmB;EAC7D;CACJ;CAEA,OAAO;EACH,kBAAkB,qBAAqB,KAAK,CAAC;EAC7C,gBAAgB,CAAC,qBAAqB,WAAW,YAAY,QAAiB,GAAG,GAAG;CACxF;AACJ;AAEA,SAAS,qBAAqB,YAAmC;CAC7D,SAAS,gBAAgB,UAAU,OAAO,SAAS,MAAM;CAEzD,IAAI,eAAe,UAAU,SAAS,gBAAgB,UAAU,IAAI,UAAU;CAE9E,KAAK,MAAM,QAAQ,SAAS,iBAAkC,4BAA0B,GAAG;EACvF,MAAM,SAAS,KAAK,aAAa,OAAO,CAAC,EAAE,SAAS,MAAM,IAAI,SAAS;EAEvE,KAAK,UAAU,YAAY,eAAe,WAAW,SAAS;CAClE;AACJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lar-works/design-system",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Lar's design system: tokens, base styles and every visual component the Lar web apps use.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -51,12 +51,12 @@
|
|
|
51
51
|
"tailwindcss": "^4.3.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@lar-works/config": "0.1.
|
|
54
|
+
"@lar-works/config": "0.1.1",
|
|
55
55
|
"@storybook/addon-a11y": "10.6.6",
|
|
56
56
|
"@storybook/addon-docs": "10.6.6",
|
|
57
57
|
"@storybook/addon-themes": "10.6.6",
|
|
58
58
|
"@storybook/react-vite": "10.6.6",
|
|
59
|
-
"@tailwindcss/vite": "^4.3.
|
|
59
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
60
60
|
"@testing-library/jest-dom": "^7.0.1",
|
|
61
61
|
"@testing-library/react": "^16.3.3",
|
|
62
62
|
"@testing-library/user-event": "^14.6.8",
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"react": "^19.3.1",
|
|
69
69
|
"react-dom": "^19.3.1",
|
|
70
70
|
"storybook": "10.6.6",
|
|
71
|
-
"tailwindcss": "^4.3.
|
|
71
|
+
"tailwindcss": "^4.3.3",
|
|
72
72
|
"typescript": "^7.0.2",
|
|
73
73
|
"vite": "npm:@voidzero-dev/vite-plus-core@1.5.0",
|
|
74
74
|
"vite-plus": "1.5.0"
|
package/src/foundations/Theme.ts
CHANGED
|
@@ -4,9 +4,9 @@ export type ThemePreference = 'system' | 'light' | 'dark';
|
|
|
4
4
|
|
|
5
5
|
export interface ThemeController {
|
|
6
6
|
/** Applies the stored preference before the first render, so the page never flashes the other theme. */
|
|
7
|
-
initialize()
|
|
7
|
+
initialize: () => void;
|
|
8
8
|
/** The current preference and a setter that stores and applies it, kept in step across tabs. */
|
|
9
|
-
useTheme()
|
|
9
|
+
useTheme: () => readonly [ThemePreference, (value: ThemePreference) => void];
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export function isThemePreference(value: string): value is ThemePreference {
|
|
@@ -54,11 +54,7 @@ export function createThemeController(storageKey: string): ThemeController {
|
|
|
54
54
|
|
|
55
55
|
return {
|
|
56
56
|
initialize: () => applyThemePreference(read()),
|
|
57
|
-
useTheme()
|
|
58
|
-
const preference = useSyncExternalStore(subscribe, read, () => 'system' as const);
|
|
59
|
-
|
|
60
|
-
return [preference, set] as const;
|
|
61
|
-
},
|
|
57
|
+
useTheme: () => [useSyncExternalStore(subscribe, read, () => 'system' as const), set] as const,
|
|
62
58
|
};
|
|
63
59
|
}
|
|
64
60
|
|