@workjournal/shared 2.9.0 → 2.10.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/__tests__/theme.test.d.ts +2 -0
- package/dist/__tests__/theme.test.d.ts.map +1 -0
- package/dist/__tests__/theme.test.js +50 -0
- package/dist/__tests__/theme.test.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/theme.d.ts +45 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +47 -0
- package/dist/theme.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/theme.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { isThemePreference, resolveTheme, THEME_INIT_SCRIPT, THEME_PREFERENCES, THEME_STORAGE_KEY, } from '../theme.js';
|
|
3
|
+
describe('isThemePreference', () => {
|
|
4
|
+
it('accepts the three valid preferences', () => {
|
|
5
|
+
expect(isThemePreference('system')).toBe(true);
|
|
6
|
+
expect(isThemePreference('light')).toBe(true);
|
|
7
|
+
expect(isThemePreference('dark')).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
it('rejects anything else', () => {
|
|
10
|
+
expect(isThemePreference('Dark')).toBe(false);
|
|
11
|
+
expect(isThemePreference('')).toBe(false);
|
|
12
|
+
expect(isThemePreference(null)).toBe(false);
|
|
13
|
+
expect(isThemePreference(undefined)).toBe(false);
|
|
14
|
+
expect(isThemePreference(0)).toBe(false);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
describe('resolveTheme', () => {
|
|
18
|
+
it('returns the explicit preference regardless of the OS signal', () => {
|
|
19
|
+
expect(resolveTheme('light', true)).toBe('light');
|
|
20
|
+
expect(resolveTheme('light', false)).toBe('light');
|
|
21
|
+
expect(resolveTheme('dark', true)).toBe('dark');
|
|
22
|
+
expect(resolveTheme('dark', false)).toBe('dark');
|
|
23
|
+
});
|
|
24
|
+
it('follows the OS signal when preference is system', () => {
|
|
25
|
+
expect(resolveTheme('system', true)).toBe('dark');
|
|
26
|
+
expect(resolveTheme('system', false)).toBe('light');
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe('theme constants', () => {
|
|
30
|
+
it('cycles system -> light -> dark', () => {
|
|
31
|
+
expect(THEME_PREFERENCES).toEqual(['system', 'light', 'dark']);
|
|
32
|
+
});
|
|
33
|
+
it('hard-codes the storage key inside the bootstrap script (no drift)', () => {
|
|
34
|
+
// The init script can't interpolate the constant at runtime in every
|
|
35
|
+
// build target, so it inlines the literal — guard the two against drift.
|
|
36
|
+
expect(THEME_INIT_SCRIPT).toContain(`'${THEME_STORAGE_KEY}'`);
|
|
37
|
+
});
|
|
38
|
+
it('bootstrap script toggles the dark class and swallows errors', () => {
|
|
39
|
+
expect(THEME_INIT_SCRIPT).toContain("classList.toggle('dark'");
|
|
40
|
+
expect(THEME_INIT_SCRIPT).toContain('catch');
|
|
41
|
+
expect(THEME_INIT_SCRIPT).toContain('prefers-color-scheme: dark');
|
|
42
|
+
});
|
|
43
|
+
it('bootstrap script normalizes untrusted storage values to system', () => {
|
|
44
|
+
// Must mirror the runtime isThemePreference fallback so pre-paint and
|
|
45
|
+
// hydrated results never disagree (CR #694).
|
|
46
|
+
expect(THEME_INIT_SCRIPT).toContain("p!=='light'&&p!=='dark'&&p!=='system'");
|
|
47
|
+
expect(THEME_INIT_SCRIPT).toContain("p='system'");
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=theme.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.test.js","sourceRoot":"","sources":["../../src/__tests__/theme.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export { proposeWorkspaceNameFromEmail } from './propose-workspace-name.js';
|
|
|
7
7
|
export { isReservedSlug, MAX_NAME_LENGTH, MAX_SLUG_LENGTH, RESERVED_SLUGS, slugify, } from './slug.js';
|
|
8
8
|
export type { ClientOption, InterfaceOption } from './support-labels.js';
|
|
9
9
|
export { CLIENT_OPTIONS, INTERFACE_OPTIONS, isClientOption, isInterfaceOption, } from './support-labels.js';
|
|
10
|
+
export type { ResolvedTheme, ThemePreference } from './theme.js';
|
|
11
|
+
export { isThemePreference, resolveTheme, THEME_INIT_SCRIPT, THEME_PREFERENCES, THEME_STORAGE_KEY, } from './theme.js';
|
|
10
12
|
export type { FeatureFlag } from './tiers.js';
|
|
11
13
|
export { canUseFeature, canUseFeatureForCode } from './tiers.js';
|
|
12
14
|
export type { AcceptInvitationRequest, AcceptLegalRequest, ApiError, CreateEntryRequest, CreateInvitationRequest, CreateJournalRequest, CreatePromptRequest, CreateTagRequest, CreateWorkspaceRequest, Entry, EntrySummary, EntryWithNeighbors, Invitation, Journal, JournalContributor, JournalContributorRow, JournalContributorWithEmail, JournalPromptInfo, JournalTagAssignment, PaginatedResponse, Prompt, RagSearchRequest, RagSearchResponse, RagSearchResult, SharedJournal, Tag, TagWithAssignment, Tier, TierCode, UpdateEntryRequest, UpdateJournalRequest, UpdatePromptRequest, UpdateTagRequest, UserProfile, Workspace, } from './types.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EACN,SAAS,EACT,WAAW,EACX,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,GACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EACN,UAAU,EACV,aAAa,EACb,OAAO,EACP,SAAS,EACT,aAAa,EACb,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,GACT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EACN,cAAc,EACd,eAAe,EACf,eAAe,EACf,cAAc,EACd,OAAO,GACP,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACN,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,iBAAiB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACjE,YAAY,EACX,uBAAuB,EACvB,kBAAkB,EAClB,QAAQ,EACR,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,EACL,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,OAAO,EACP,kBAAkB,EAClB,qBAAqB,EACrB,2BAA2B,EAC3B,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,MAAM,EACN,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,GAAG,EACH,iBAAiB,EACjB,IAAI,EACJ,QAAQ,EACR,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EACX,SAAS,GACT,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EACN,SAAS,EACT,WAAW,EACX,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,GACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EACN,UAAU,EACV,aAAa,EACb,OAAO,EACP,SAAS,EACT,aAAa,EACb,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,GACT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EACN,cAAc,EACd,eAAe,EACf,eAAe,EACf,cAAc,EACd,OAAO,GACP,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACN,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,iBAAiB,GACjB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,EACN,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,GACjB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACjE,YAAY,EACX,uBAAuB,EACvB,kBAAkB,EAClB,QAAQ,EACR,kBAAkB,EAClB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,EACL,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,OAAO,EACP,kBAAkB,EAClB,qBAAqB,EACrB,2BAA2B,EAC3B,iBAAiB,EACjB,oBAAoB,EACpB,iBAAiB,EACjB,MAAM,EACN,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,aAAa,EACb,GAAG,EACH,iBAAiB,EACjB,IAAI,EACJ,QAAQ,EACR,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,EACX,SAAS,GACT,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,5 +4,6 @@ export { AAD_STRING, isOpaqueToken, KEY_LEN, NONCE_LEN, resolveBearer, TAG_LEN,
|
|
|
4
4
|
export { proposeWorkspaceNameFromEmail } from './propose-workspace-name.js';
|
|
5
5
|
export { isReservedSlug, MAX_NAME_LENGTH, MAX_SLUG_LENGTH, RESERVED_SLUGS, slugify, } from './slug.js';
|
|
6
6
|
export { CLIENT_OPTIONS, INTERFACE_OPTIONS, isClientOption, isInterfaceOption, } from './support-labels.js';
|
|
7
|
+
export { isThemePreference, resolveTheme, THEME_INIT_SCRIPT, THEME_PREFERENCES, THEME_STORAGE_KEY, } from './theme.js';
|
|
7
8
|
export { canUseFeature, canUseFeatureForCode } from './tiers.js';
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACN,SAAS,EACT,WAAW,EACX,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,GACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EACN,UAAU,EACV,aAAa,EACb,OAAO,EACP,SAAS,EACT,aAAa,EACb,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,GACT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EACN,cAAc,EACd,eAAe,EACf,eAAe,EACf,cAAc,EACd,OAAO,GACP,MAAM,WAAW,CAAC;AAEnB,OAAO,EACN,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,iBAAiB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACN,SAAS,EACT,WAAW,EACX,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,uBAAuB,EACvB,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,YAAY,GACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EACN,UAAU,EACV,aAAa,EACb,OAAO,EACP,SAAS,EACT,aAAa,EACb,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,GACT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,6BAA6B,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EACN,cAAc,EACd,eAAe,EACf,eAAe,EACf,cAAc,EACd,OAAO,GACP,MAAM,WAAW,CAAC;AAEnB,OAAO,EACN,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,iBAAiB,GACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACN,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,GACjB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/theme.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme (light / dark) contract shared by every browser surface.
|
|
3
|
+
*
|
|
4
|
+
* `apps/web` (React / Tailwind v4) and `apps/landing` (Astro / plain CSS) both
|
|
5
|
+
* activate dark mode by toggling the `.dark` class on `<html>` — the design
|
|
6
|
+
* system's `tokens.css` carries the full `.dark` palette. The two surfaces must
|
|
7
|
+
* agree on the localStorage key and the system/light/dark resolution semantics
|
|
8
|
+
* or a user who sets dark on the app and opens the marketing site sees the
|
|
9
|
+
* wrong theme. Single-sourcing those primitives here makes that drift
|
|
10
|
+
* impossible — same rationale as `connections.ts`.
|
|
11
|
+
*/
|
|
12
|
+
/** What the user picked. `system` defers to the OS `prefers-color-scheme`. */
|
|
13
|
+
export type ThemePreference = 'system' | 'light' | 'dark';
|
|
14
|
+
/** The concrete theme actually applied to the DOM. */
|
|
15
|
+
export type ResolvedTheme = 'light' | 'dark';
|
|
16
|
+
/** localStorage key holding the persisted {@link ThemePreference}. */
|
|
17
|
+
export declare const THEME_STORAGE_KEY = "wj-theme";
|
|
18
|
+
/** The three selectable preferences, in cycle order (toggle steps through these). */
|
|
19
|
+
export declare const THEME_PREFERENCES: readonly ThemePreference[];
|
|
20
|
+
/** Narrow an untrusted value (e.g. a localStorage read) to a {@link ThemePreference}. */
|
|
21
|
+
export declare function isThemePreference(value: unknown): value is ThemePreference;
|
|
22
|
+
/**
|
|
23
|
+
* Collapse a preference + the current OS dark-mode signal into the concrete
|
|
24
|
+
* theme to apply. `prefersDark` is the value of
|
|
25
|
+
* `matchMedia('(prefers-color-scheme: dark)').matches`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveTheme(preference: ThemePreference, prefersDark: boolean): ResolvedTheme;
|
|
28
|
+
/**
|
|
29
|
+
* Blocking bootstrap script, inlined in the document `<head>` of every surface
|
|
30
|
+
* BEFORE first paint to prevent a flash of the wrong theme (FOUC). It reads the
|
|
31
|
+
* persisted preference and applies `.dark` synchronously; the runtime provider
|
|
32
|
+
* / toggle takes over once hydrated. Kept dependency-free and self-contained so
|
|
33
|
+
* it can run as a plain inline `<script>`.
|
|
34
|
+
*
|
|
35
|
+
* The literal key here mirrors {@link THEME_STORAGE_KEY}; both must stay in
|
|
36
|
+
* sync (the constant can't be interpolated into a surface's static HTML head in
|
|
37
|
+
* every build target, so this string hard-codes it — tested in theme.test.ts).
|
|
38
|
+
*
|
|
39
|
+
* Untrusted storage values are normalized to a valid preference (fallback
|
|
40
|
+
* `system`) before resolving, so the pre-paint result matches the runtime
|
|
41
|
+
* provider's {@link isThemePreference}-guarded logic exactly — otherwise a junk
|
|
42
|
+
* value + OS-dark would paint light then flip, reintroducing the FOUC.
|
|
43
|
+
*/
|
|
44
|
+
export declare const THEME_INIT_SCRIPT = "(function(){try{var p=localStorage.getItem('wj-theme');if(p!=='light'&&p!=='dark'&&p!=='system')p='system';var d=p==='dark'||(p==='system'&&window.matchMedia('(prefers-color-scheme: dark)').matches);document.documentElement.classList.toggle('dark',d);}catch(e){}})();";
|
|
45
|
+
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAE1D,sDAAsD;AACtD,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7C,sEAAsE;AACtE,eAAO,MAAM,iBAAiB,aAAa,CAAC;AAE5C,qFAAqF;AACrF,eAAO,MAAM,iBAAiB,EAAE,SAAS,eAAe,EAAgC,CAAC;AAEzF,yFAAyF;AACzF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAE1E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,OAAO,GAAG,aAAa,CAG7F;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,gRAA4R,CAAC"}
|
package/dist/theme.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme (light / dark) contract shared by every browser surface.
|
|
3
|
+
*
|
|
4
|
+
* `apps/web` (React / Tailwind v4) and `apps/landing` (Astro / plain CSS) both
|
|
5
|
+
* activate dark mode by toggling the `.dark` class on `<html>` — the design
|
|
6
|
+
* system's `tokens.css` carries the full `.dark` palette. The two surfaces must
|
|
7
|
+
* agree on the localStorage key and the system/light/dark resolution semantics
|
|
8
|
+
* or a user who sets dark on the app and opens the marketing site sees the
|
|
9
|
+
* wrong theme. Single-sourcing those primitives here makes that drift
|
|
10
|
+
* impossible — same rationale as `connections.ts`.
|
|
11
|
+
*/
|
|
12
|
+
/** localStorage key holding the persisted {@link ThemePreference}. */
|
|
13
|
+
export const THEME_STORAGE_KEY = 'wj-theme';
|
|
14
|
+
/** The three selectable preferences, in cycle order (toggle steps through these). */
|
|
15
|
+
export const THEME_PREFERENCES = ['system', 'light', 'dark'];
|
|
16
|
+
/** Narrow an untrusted value (e.g. a localStorage read) to a {@link ThemePreference}. */
|
|
17
|
+
export function isThemePreference(value) {
|
|
18
|
+
return value === 'system' || value === 'light' || value === 'dark';
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Collapse a preference + the current OS dark-mode signal into the concrete
|
|
22
|
+
* theme to apply. `prefersDark` is the value of
|
|
23
|
+
* `matchMedia('(prefers-color-scheme: dark)').matches`.
|
|
24
|
+
*/
|
|
25
|
+
export function resolveTheme(preference, prefersDark) {
|
|
26
|
+
if (preference === 'system')
|
|
27
|
+
return prefersDark ? 'dark' : 'light';
|
|
28
|
+
return preference;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Blocking bootstrap script, inlined in the document `<head>` of every surface
|
|
32
|
+
* BEFORE first paint to prevent a flash of the wrong theme (FOUC). It reads the
|
|
33
|
+
* persisted preference and applies `.dark` synchronously; the runtime provider
|
|
34
|
+
* / toggle takes over once hydrated. Kept dependency-free and self-contained so
|
|
35
|
+
* it can run as a plain inline `<script>`.
|
|
36
|
+
*
|
|
37
|
+
* The literal key here mirrors {@link THEME_STORAGE_KEY}; both must stay in
|
|
38
|
+
* sync (the constant can't be interpolated into a surface's static HTML head in
|
|
39
|
+
* every build target, so this string hard-codes it — tested in theme.test.ts).
|
|
40
|
+
*
|
|
41
|
+
* Untrusted storage values are normalized to a valid preference (fallback
|
|
42
|
+
* `system`) before resolving, so the pre-paint result matches the runtime
|
|
43
|
+
* provider's {@link isThemePreference}-guarded logic exactly — otherwise a junk
|
|
44
|
+
* value + OS-dark would paint light then flip, reintroducing the FOUC.
|
|
45
|
+
*/
|
|
46
|
+
export const THEME_INIT_SCRIPT = `(function(){try{var p=localStorage.getItem('${THEME_STORAGE_KEY}');if(p!=='light'&&p!=='dark'&&p!=='system')p='system';var d=p==='dark'||(p==='system'&&window.matchMedia('(prefers-color-scheme: dark)').matches);document.documentElement.classList.toggle('dark',d);}catch(e){}})();`;
|
|
47
|
+
//# sourceMappingURL=theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,sEAAsE;AACtE,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAE5C,qFAAqF;AACrF,MAAM,CAAC,MAAM,iBAAiB,GAA+B,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAEzF,yFAAyF;AACzF,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC/C,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,CAAC;AACpE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,UAA2B,EAAE,WAAoB;IAC7E,IAAI,UAAU,KAAK,QAAQ;QAAE,OAAO,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IACnE,OAAO,UAAU,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,+CAA+C,iBAAiB,yNAAyN,CAAC"}
|