@orz/ui 0.0.0-stage → 0.0.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/LICENSE +29 -0
- package/README.md +541 -2
- package/dist/components/avatar.d.ts +14 -0
- package/dist/components/avatar.d.ts.map +1 -0
- package/dist/components/avatar.js +23 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.d.ts +10 -0
- package/dist/components/badge.d.ts.map +1 -0
- package/dist/components/badge.js +26 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/button.d.ts +11 -0
- package/dist/components/button.d.ts.map +1 -0
- package/dist/components/button.js +40 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/card.d.ts +12 -0
- package/dist/components/card.d.ts.map +1 -0
- package/dist/components/card.js +25 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/color-picker.d.ts +58 -0
- package/dist/components/color-picker.d.ts.map +1 -0
- package/dist/components/color-picker.js +950 -0
- package/dist/components/color-picker.js.map +1 -0
- package/dist/components/confirm-dialog.d.ts +26 -0
- package/dist/components/confirm-dialog.d.ts.map +1 -0
- package/dist/components/confirm-dialog.js +18 -0
- package/dist/components/confirm-dialog.js.map +1 -0
- package/dist/components/dialog.d.ts +26 -0
- package/dist/components/dialog.d.ts.map +1 -0
- package/dist/components/dialog.js +149 -0
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/dropdown-menu.d.ts +30 -0
- package/dist/components/dropdown-menu.d.ts.map +1 -0
- package/dist/components/dropdown-menu.js +100 -0
- package/dist/components/dropdown-menu.js.map +1 -0
- package/dist/components/filter-menu.d.ts +98 -0
- package/dist/components/filter-menu.d.ts.map +1 -0
- package/dist/components/filter-menu.js +745 -0
- package/dist/components/filter-menu.js.map +1 -0
- package/dist/components/highlighted-input.d.ts +40 -0
- package/dist/components/highlighted-input.d.ts.map +1 -0
- package/dist/components/highlighted-input.js +95 -0
- package/dist/components/highlighted-input.js.map +1 -0
- package/dist/components/hover-card.d.ts +7 -0
- package/dist/components/hover-card.d.ts.map +1 -0
- package/dist/components/hover-card.js +22 -0
- package/dist/components/hover-card.js.map +1 -0
- package/dist/components/input.d.ts +4 -0
- package/dist/components/input.d.ts.map +1 -0
- package/dist/components/input.js +7 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/label.d.ts +5 -0
- package/dist/components/label.d.ts.map +1 -0
- package/dist/components/label.js +8 -0
- package/dist/components/label.js.map +1 -0
- package/dist/components/link-chip.d.ts +67 -0
- package/dist/components/link-chip.d.ts.map +1 -0
- package/dist/components/link-chip.js +71 -0
- package/dist/components/link-chip.js.map +1 -0
- package/dist/components/load-failure.d.ts +24 -0
- package/dist/components/load-failure.d.ts.map +1 -0
- package/dist/components/load-failure.js +27 -0
- package/dist/components/load-failure.js.map +1 -0
- package/dist/components/load-more.d.ts +15 -0
- package/dist/components/load-more.d.ts.map +1 -0
- package/dist/components/load-more.js +25 -0
- package/dist/components/load-more.js.map +1 -0
- package/dist/components/media-controls.d.ts +50 -0
- package/dist/components/media-controls.d.ts.map +1 -0
- package/dist/components/media-controls.js +71 -0
- package/dist/components/media-controls.js.map +1 -0
- package/dist/components/popover.d.ts +9 -0
- package/dist/components/popover.d.ts.map +1 -0
- package/dist/components/popover.js +82 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/query-box.d.ts +78 -0
- package/dist/components/query-box.d.ts.map +1 -0
- package/dist/components/query-box.js +332 -0
- package/dist/components/query-box.js.map +1 -0
- package/dist/components/query-highlight.d.ts +14 -0
- package/dist/components/query-highlight.d.ts.map +1 -0
- package/dist/components/query-highlight.js +132 -0
- package/dist/components/query-highlight.js.map +1 -0
- package/dist/components/select.d.ts +19 -0
- package/dist/components/select.d.ts.map +1 -0
- package/dist/components/select.js +38 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/separator.d.ts +5 -0
- package/dist/components/separator.d.ts.map +1 -0
- package/dist/components/separator.js +9 -0
- package/dist/components/separator.js.map +1 -0
- package/dist/components/sheet.d.ts +16 -0
- package/dist/components/sheet.d.ts.map +1 -0
- package/dist/components/sheet.js +41 -0
- package/dist/components/sheet.js.map +1 -0
- package/dist/components/skeleton.d.ts +3 -0
- package/dist/components/skeleton.d.ts.map +1 -0
- package/dist/components/skeleton.js +7 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/slider.d.ts +8 -0
- package/dist/components/slider.d.ts.map +1 -0
- package/dist/components/slider.js +14 -0
- package/dist/components/slider.js.map +1 -0
- package/dist/components/sonner.d.ts +4 -0
- package/dist/components/sonner.d.ts.map +1 -0
- package/dist/components/sonner.js +26 -0
- package/dist/components/sonner.js.map +1 -0
- package/dist/components/switch.d.ts +5 -0
- package/dist/components/switch.d.ts.map +1 -0
- package/dist/components/switch.js +8 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/table.d.ts +11 -0
- package/dist/components/table.d.ts.map +1 -0
- package/dist/components/table.js +28 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/tabs.d.ts +8 -0
- package/dist/components/tabs.d.ts.map +1 -0
- package/dist/components/tabs.js +18 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/textarea.d.ts +4 -0
- package/dist/components/textarea.d.ts.map +1 -0
- package/dist/components/textarea.js +7 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/theme-editor/draft.d.ts +235 -0
- package/dist/components/theme-editor/draft.d.ts.map +1 -0
- package/dist/components/theme-editor/draft.js +638 -0
- package/dist/components/theme-editor/draft.js.map +1 -0
- package/dist/components/theme-editor/export-panel.d.ts +14 -0
- package/dist/components/theme-editor/export-panel.d.ts.map +1 -0
- package/dist/components/theme-editor/export-panel.js +39 -0
- package/dist/components/theme-editor/export-panel.js.map +1 -0
- package/dist/components/theme-editor/form.d.ts +69 -0
- package/dist/components/theme-editor/form.d.ts.map +1 -0
- package/dist/components/theme-editor/form.js +350 -0
- package/dist/components/theme-editor/form.js.map +1 -0
- package/dist/components/theme-editor/import-panel.d.ts +21 -0
- package/dist/components/theme-editor/import-panel.d.ts.map +1 -0
- package/dist/components/theme-editor/import-panel.js +117 -0
- package/dist/components/theme-editor/import-panel.js.map +1 -0
- package/dist/components/theme-editor/theme-list.d.ts +23 -0
- package/dist/components/theme-editor/theme-list.d.ts.map +1 -0
- package/dist/components/theme-editor/theme-list.js +42 -0
- package/dist/components/theme-editor/theme-list.js.map +1 -0
- package/dist/components/theme-editor/token-list.d.ts +30 -0
- package/dist/components/theme-editor/token-list.d.ts.map +1 -0
- package/dist/components/theme-editor/token-list.js +124 -0
- package/dist/components/theme-editor/token-list.js.map +1 -0
- package/dist/components/theme-editor/tokens.d.ts +37 -0
- package/dist/components/theme-editor/tokens.d.ts.map +1 -0
- package/dist/components/theme-editor/tokens.js +155 -0
- package/dist/components/theme-editor/tokens.js.map +1 -0
- package/dist/components/theme-editor.d.ts +26 -0
- package/dist/components/theme-editor.d.ts.map +1 -0
- package/dist/components/theme-editor.js +467 -0
- package/dist/components/theme-editor.js.map +1 -0
- package/dist/components/theme-menu.d.ts +28 -0
- package/dist/components/theme-menu.d.ts.map +1 -0
- package/dist/components/theme-menu.js +308 -0
- package/dist/components/theme-menu.js.map +1 -0
- package/dist/components/tooltip.d.ts +11 -0
- package/dist/components/tooltip.d.ts.map +1 -0
- package/dist/components/tooltip.js +18 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/unsaved-changes-dialog.d.ts +39 -0
- package/dist/components/unsaved-changes-dialog.d.ts.map +1 -0
- package/dist/components/unsaved-changes-dialog.js +46 -0
- package/dist/components/unsaved-changes-dialog.js.map +1 -0
- package/dist/hooks/scroll-insets.d.ts +89 -0
- package/dist/hooks/scroll-insets.d.ts.map +1 -0
- package/dist/hooks/scroll-insets.js +265 -0
- package/dist/hooks/scroll-insets.js.map +1 -0
- package/dist/hooks/use-element-height.d.ts +11 -0
- package/dist/hooks/use-element-height.d.ts.map +1 -0
- package/dist/hooks/use-element-height.js +33 -0
- package/dist/hooks/use-element-height.js.map +1 -0
- package/dist/hooks/use-media-query.d.ts +22 -0
- package/dist/hooks/use-media-query.d.ts.map +1 -0
- package/dist/hooks/use-media-query.js +38 -0
- package/dist/hooks/use-media-query.js.map +1 -0
- package/dist/hooks/use-overlay-scrollbars.d.ts +31 -0
- package/dist/hooks/use-overlay-scrollbars.d.ts.map +1 -0
- package/dist/hooks/use-overlay-scrollbars.js +80 -0
- package/dist/hooks/use-overlay-scrollbars.js.map +1 -0
- package/dist/hooks/use-paged-append.d.ts +7 -0
- package/dist/hooks/use-paged-append.d.ts.map +1 -0
- package/dist/hooks/use-paged-append.js +53 -0
- package/dist/hooks/use-paged-append.js.map +1 -0
- package/dist/hooks/use-query-completion.d.ts +27 -0
- package/dist/hooks/use-query-completion.d.ts.map +1 -0
- package/dist/hooks/use-query-completion.js +100 -0
- package/dist/hooks/use-query-completion.js.map +1 -0
- package/dist/hooks/use-slash-shortcut.d.ts +9 -0
- package/dist/hooks/use-slash-shortcut.d.ts.map +1 -0
- package/dist/hooks/use-slash-shortcut.js +38 -0
- package/dist/hooks/use-slash-shortcut.js.map +1 -0
- package/dist/hooks/viewport-chrome.d.ts +50 -0
- package/dist/hooks/viewport-chrome.d.ts.map +1 -0
- package/dist/hooks/viewport-chrome.js +170 -0
- package/dist/hooks/viewport-chrome.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cell-width-table.d.ts +3 -0
- package/dist/lib/cell-width-table.d.ts.map +1 -0
- package/dist/lib/cell-width-table.js +6 -0
- package/dist/lib/cell-width-table.js.map +1 -0
- package/dist/lib/cell-width.d.ts +7 -0
- package/dist/lib/cell-width.d.ts.map +1 -0
- package/dist/lib/cell-width.js +50 -0
- package/dist/lib/cell-width.js.map +1 -0
- package/dist/lib/clipboard.d.ts +8 -0
- package/dist/lib/clipboard.d.ts.map +1 -0
- package/dist/lib/clipboard.js +19 -0
- package/dist/lib/clipboard.js.map +1 -0
- package/dist/lib/color.d.ts +40 -0
- package/dist/lib/color.d.ts.map +1 -0
- package/dist/lib/color.js +177 -0
- package/dist/lib/color.js.map +1 -0
- package/dist/lib/scroll-map.d.ts +20 -0
- package/dist/lib/scroll-map.d.ts.map +1 -0
- package/dist/lib/scroll-map.js +46 -0
- package/dist/lib/scroll-map.js.map +1 -0
- package/dist/lib/text-metrics.d.ts +33 -0
- package/dist/lib/text-metrics.d.ts.map +1 -0
- package/dist/lib/text-metrics.js +89 -0
- package/dist/lib/text-metrics.js.map +1 -0
- package/dist/lib/theme-file.d.ts +51 -0
- package/dist/lib/theme-file.d.ts.map +1 -0
- package/dist/lib/theme-file.js +511 -0
- package/dist/lib/theme-file.js.map +1 -0
- package/dist/lib/unsaved-guard.d.ts +33 -0
- package/dist/lib/unsaved-guard.d.ts.map +1 -0
- package/dist/lib/unsaved-guard.js +37 -0
- package/dist/lib/unsaved-guard.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +6 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/theme/custom.d.ts +8 -0
- package/dist/theme/custom.d.ts.map +1 -0
- package/dist/theme/custom.js +56 -0
- package/dist/theme/custom.js.map +1 -0
- package/dist/theme/index.d.ts +6 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +5 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/theme/paint-guard.d.ts +20 -0
- package/dist/theme/paint-guard.d.ts.map +1 -0
- package/dist/theme/paint-guard.js +120 -0
- package/dist/theme/paint-guard.js.map +1 -0
- package/dist/theme/picks.d.ts +22 -0
- package/dist/theme/picks.d.ts.map +1 -0
- package/dist/theme/picks.js +43 -0
- package/dist/theme/picks.js.map +1 -0
- package/dist/theme/pref.d.ts +39 -0
- package/dist/theme/pref.d.ts.map +1 -0
- package/dist/theme/pref.js +129 -0
- package/dist/theme/pref.js.map +1 -0
- package/dist/theme/provider.d.ts +41 -0
- package/dist/theme/provider.d.ts.map +1 -0
- package/dist/theme/provider.js +103 -0
- package/dist/theme/provider.js.map +1 -0
- package/dist/theme/store.d.ts +104 -0
- package/dist/theme/store.d.ts.map +1 -0
- package/dist/theme/store.js +509 -0
- package/dist/theme/store.js.map +1 -0
- package/package.json +94 -3
- package/styles.css +79 -0
- package/theme.css +186 -0
- package/vendor/shadcn-tailwind.css +664 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2
|
+
/** `{ base: { theme } }` or `{ tokens }`, the two shapes a side or its terminal takes. */
|
|
3
|
+
function sourceOk(value) {
|
|
4
|
+
if (!isObject(value))
|
|
5
|
+
return false;
|
|
6
|
+
if (value.base !== undefined) {
|
|
7
|
+
return isObject(value.base) && typeof value.base.theme === "string";
|
|
8
|
+
}
|
|
9
|
+
return isObject(value.tokens);
|
|
10
|
+
}
|
|
11
|
+
function sideOk(value) {
|
|
12
|
+
if (!sourceOk(value))
|
|
13
|
+
return false;
|
|
14
|
+
// composeTheme reads a terminal without checking it, and a side of its own
|
|
15
|
+
// tokens has nothing else to take one from.
|
|
16
|
+
if (value.terminal !== undefined)
|
|
17
|
+
return sourceOk(value.terminal);
|
|
18
|
+
return value.base !== undefined;
|
|
19
|
+
}
|
|
20
|
+
function customOk(value) {
|
|
21
|
+
if (!isObject(value))
|
|
22
|
+
return false;
|
|
23
|
+
const { id, kind, label, light, dark } = value;
|
|
24
|
+
if (typeof id !== "string" || typeof label !== "string")
|
|
25
|
+
return false;
|
|
26
|
+
if (light === undefined && dark === undefined)
|
|
27
|
+
return false;
|
|
28
|
+
// A kind this version does not know must not reach composeTheme as a UI
|
|
29
|
+
// theme: a based terminal side is also a valid based UI side.
|
|
30
|
+
const ok = kind === "terminal"
|
|
31
|
+
? sourceOk
|
|
32
|
+
: kind === undefined || kind === "ui"
|
|
33
|
+
? sideOk
|
|
34
|
+
: null;
|
|
35
|
+
if (ok === null)
|
|
36
|
+
return false;
|
|
37
|
+
return (light === undefined || ok(light)) && (dark === undefined || ok(dark));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The custom themes stored as JSON, keeping each entry whose shape
|
|
41
|
+
* `composeTheme` or `composeTerminalTheme` can read and dropping the rest;
|
|
42
|
+
* `[]` for anything that is not a JSON array.
|
|
43
|
+
*/
|
|
44
|
+
export function parseCustomThemes(raw) {
|
|
45
|
+
if (raw === null)
|
|
46
|
+
return [];
|
|
47
|
+
let parsed;
|
|
48
|
+
try {
|
|
49
|
+
parsed = JSON.parse(raw);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
return Array.isArray(parsed) ? parsed.filter(customOk) : [];
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=custom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom.js","sourceRoot":"","sources":["../../src/theme/custom.ts"],"names":[],"mappings":"AAEA,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAEvE,0FAA0F;AAC1F,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC;IACtE,CAAC;IACD,OAAO,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,MAAM,CAAC,KAAc;IAC5B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,2EAA2E;IAC3E,4CAA4C;IAC5C,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClE,OAAO,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC;AAClC,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC9B,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IAC/C,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtE,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAC5D,wEAAwE;IACxE,8DAA8D;IAC9D,MAAM,EAAE,GACN,IAAI,KAAK,UAAU;QACjB,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI;YACnC,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,IAAI,CAAC;IACb,IAAI,EAAE,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9B,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AAChF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAkB;IAClD,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC5B,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9D,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type { AnyCustomTheme, ColorScheme, CustomSide, CustomTerminal, CustomTerminalTheme, CustomTheme, Palette, TerminalPalette, TerminalTheme, TerminalTokenName, TerminalTokens, TerminalVariant, Theme, TokenName, Tokens, Variant, } from "@orz/themes";
|
|
2
|
+
export { themePaintCookieStyle, themePaintGuardScript, } from "./paint-guard.ts";
|
|
3
|
+
export { normalizePref, parseStoredPref, type ThemeMode, type ThemePick, type ThemePref, } from "./pref.ts";
|
|
4
|
+
export { ThemeProvider, useTerminalTheme, useTheme, useThemeSlots, } from "./provider.tsx";
|
|
5
|
+
export { createThemeStore, type PreviewPick, type ResolvedTerminalTheme, type ResolvedTheme, type ThemePreview, type ThemeStore, type ThemeStoreOptions, } from "./store.ts";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,cAAc,EACd,WAAW,EACX,UAAU,EACV,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,OAAO,EACP,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,KAAK,EACL,SAAS,EACT,MAAM,EACN,OAAO,GACR,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,aAAa,EACb,eAAe,EACf,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACR,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,gBAAgB,EAChB,KAAK,WAAW,EAChB,KAAK,qBAAqB,EAC1B,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { themePaintCookieStyle, themePaintGuardScript, } from "./paint-guard.js";
|
|
2
|
+
export { normalizePref, parseStoredPref, } from "./pref.js";
|
|
3
|
+
export { ThemeProvider, useTerminalTheme, useTheme, useThemeSlots, } from "./provider.js";
|
|
4
|
+
export { createThemeStore, } from "./store.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAkBA,OAAO,EACL,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,aAAa,EACb,eAAe,GAIhB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACR,aAAa,GACd,MAAM,eAAgB,CAAC;AACxB,OAAO,EACL,gBAAgB,GAOjB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ColorScheme } from "@orz/themes";
|
|
2
|
+
/** The paint cookie's value, as JSON: each side's background the UI pick can show. */
|
|
3
|
+
export type PaintBackgrounds = Partial<Record<ColorScheme, string>>;
|
|
4
|
+
/**
|
|
5
|
+
* CSS for a server to inline in `<head>`, from the value of the store's
|
|
6
|
+
* `paintCookie`: the page's background and color scheme, chosen by the OS
|
|
7
|
+
* when both sides are stored. Empty for a missing or malformed value.
|
|
8
|
+
*/
|
|
9
|
+
export declare function themePaintCookieStyle(value: string | null | undefined): string;
|
|
10
|
+
/**
|
|
11
|
+
* An inline script for `<head>` that paints the persisted theme before the
|
|
12
|
+
* bundle loads, so a dark-theme reload never flashes white. It replays the
|
|
13
|
+
* declarations the store cached under `paintKey`, so neither it nor the page
|
|
14
|
+
* needs a theme list; the store adopts the `<style>` it inserts.
|
|
15
|
+
*/
|
|
16
|
+
export declare function themePaintGuardScript({ storageKey, paintKey, }: {
|
|
17
|
+
storageKey: string;
|
|
18
|
+
paintKey?: string;
|
|
19
|
+
}): string;
|
|
20
|
+
//# sourceMappingURL=paint-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paint-guard.d.ts","sourceRoot":"","sources":["../../src/theme/paint-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAS/C,sFAAsF;AACtF,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;AAuCpE;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,CAeR;AAOD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,QAAgC,GACjC,EAAE;IACD,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,MAAM,CA2CT"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The guard's own: the canvas has the theme's background before the
|
|
3
|
+
* stylesheet does. The store's rule leaves it out, because a background on
|
|
4
|
+
* `<html>` stops body's from reaching the canvas.
|
|
5
|
+
*/
|
|
6
|
+
const PAGE_BACKGROUND = "background-color: var(--background);";
|
|
7
|
+
// A colour as a token holds one: no `;`, braces, quotes or `<`, which could
|
|
8
|
+
// close the declaration, the rule or the <style> it lands in.
|
|
9
|
+
const COLOR = /^[\w#.,%()/+\- ]{1,100}$/;
|
|
10
|
+
/** An open `(` would swallow the rest of the stylesheet as a function's arguments. */
|
|
11
|
+
function balanced(color) {
|
|
12
|
+
let depth = 0;
|
|
13
|
+
for (const c of color) {
|
|
14
|
+
if (c === "(")
|
|
15
|
+
depth++;
|
|
16
|
+
else if (c === ")" && --depth < 0)
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return depth === 0;
|
|
20
|
+
}
|
|
21
|
+
function parseBackgrounds(value) {
|
|
22
|
+
// Frameworks hand a cookie over decoded or not; the store writes it encoded.
|
|
23
|
+
for (const text of [value, safeDecode(value)]) {
|
|
24
|
+
try {
|
|
25
|
+
const parsed = JSON.parse(text);
|
|
26
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
27
|
+
return parsed;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// try the other form
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function safeDecode(value) {
|
|
37
|
+
try {
|
|
38
|
+
return decodeURIComponent(value);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* CSS for a server to inline in `<head>`, from the value of the store's
|
|
46
|
+
* `paintCookie`: the page's background and color scheme, chosen by the OS
|
|
47
|
+
* when both sides are stored. Empty for a missing or malformed value.
|
|
48
|
+
*/
|
|
49
|
+
export function themePaintCookieStyle(value) {
|
|
50
|
+
if (!value)
|
|
51
|
+
return "";
|
|
52
|
+
const backgrounds = parseBackgrounds(value);
|
|
53
|
+
const side = (scheme) => {
|
|
54
|
+
const color = backgrounds?.[scheme];
|
|
55
|
+
return typeof color === "string" && COLOR.test(color) && balanced(color)
|
|
56
|
+
? `html{background-color:${color};color-scheme:${scheme}}`
|
|
57
|
+
: "";
|
|
58
|
+
};
|
|
59
|
+
const light = side("light");
|
|
60
|
+
const dark = side("dark");
|
|
61
|
+
if (light && dark) {
|
|
62
|
+
return `${light}@media (prefers-color-scheme: dark){${dark}}`;
|
|
63
|
+
}
|
|
64
|
+
return light || dark;
|
|
65
|
+
}
|
|
66
|
+
/** Inside a `<script>`, so `<` is escaped: a key holding `</script>` would end it. */
|
|
67
|
+
function literal(value) {
|
|
68
|
+
return JSON.stringify(value).replace(/</g, "\\u003c");
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* An inline script for `<head>` that paints the persisted theme before the
|
|
72
|
+
* bundle loads, so a dark-theme reload never flashes white. It replays the
|
|
73
|
+
* declarations the store cached under `paintKey`, so neither it nor the page
|
|
74
|
+
* needs a theme list; the store adopts the `<style>` it inserts.
|
|
75
|
+
*/
|
|
76
|
+
export function themePaintGuardScript({ storageKey, paintKey = `${storageKey}-paint`, }) {
|
|
77
|
+
return `(() => {
|
|
78
|
+
try {
|
|
79
|
+
const root = document.documentElement;
|
|
80
|
+
const raw = localStorage.getItem(${literal(paintKey)});
|
|
81
|
+
if (!raw) {
|
|
82
|
+
// Written by the store before it cached declarations; it rewrites the
|
|
83
|
+
// cache on creation, so this path runs once.
|
|
84
|
+
if (localStorage.getItem(${literal(`${storageKey}-kind`)}) === "dark")
|
|
85
|
+
root.classList.add("dark");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const cache = JSON.parse(raw);
|
|
89
|
+
const pick = (side) => {
|
|
90
|
+
if (!side) return null;
|
|
91
|
+
const scheme =
|
|
92
|
+
side.light && side.dark
|
|
93
|
+
? window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
94
|
+
? "dark"
|
|
95
|
+
: "light"
|
|
96
|
+
: side.light
|
|
97
|
+
? "light"
|
|
98
|
+
: "dark";
|
|
99
|
+
return { scheme, text: side[scheme] || "" };
|
|
100
|
+
};
|
|
101
|
+
const ui = pick(cache.ui);
|
|
102
|
+
const terminal = pick(cache.terminal);
|
|
103
|
+
const style = document.createElement("style");
|
|
104
|
+
style.setAttribute("data-orz-theme", "");
|
|
105
|
+
// Doubled because a stylesheet <link> parsed after this script would
|
|
106
|
+
// otherwise outrank it on order; the store rewrites it as plain :root
|
|
107
|
+
// and moves it last.
|
|
108
|
+
style.textContent =
|
|
109
|
+
":root:root { " + [ui && ui.text, ui && ${literal(PAGE_BACKGROUND)}, terminal && terminal.text].filter(Boolean).join(" ") + " }";
|
|
110
|
+
document.head.append(style);
|
|
111
|
+
if (ui) {
|
|
112
|
+
root.classList.toggle("dark", ui.scheme === "dark");
|
|
113
|
+
root.dataset.theme = cache.ui.theme;
|
|
114
|
+
if (cache.ui.variant) root.dataset.variant = cache.ui.variant;
|
|
115
|
+
}
|
|
116
|
+
if (terminal) root.dataset.terminalTheme = cache.terminal.theme;
|
|
117
|
+
} catch {}
|
|
118
|
+
})();`;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=paint-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paint-guard.js","sourceRoot":"","sources":["../../src/theme/paint-guard.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,eAAe,GAAG,sCAAsC,CAAC;AAK/D,4EAA4E;AAC5E,8DAA8D;AAC9D,MAAM,KAAK,GAAG,0BAA0B,CAAC;AAEzC,sFAAsF;AACtF,SAAS,QAAQ,CAAC,KAAa;IAC7B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG;YAAE,KAAK,EAAE,CAAC;aAClB,IAAI,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;IAClD,CAAC;IACD,OAAO,KAAK,KAAK,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa;IACrC,6EAA6E;IAC7E,KAAK,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAC9C,IAAI,CAAC;YACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACzC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBAClD,OAAO,MAA0B,CAAC;YACpC,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qBAAqB;QACvB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAAgC;IAEhC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,MAAM,WAAW,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,CAAC,MAAmB,EAAE,EAAE;QACnC,MAAM,KAAK,GAAG,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC;QACpC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC;YACtE,CAAC,CAAC,yBAAyB,KAAK,iBAAiB,MAAM,GAAG;YAC1D,CAAC,CAAC,EAAE,CAAC;IACT,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,OAAO,GAAG,KAAK,uCAAuC,IAAI,GAAG,CAAC;IAChE,CAAC;IACD,OAAO,KAAK,IAAI,IAAI,CAAC;AACvB,CAAC;AAED,sFAAsF;AACtF,SAAS,OAAO,CAAC,KAAa;IAC5B,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,EACpC,UAAU,EACV,QAAQ,GAAG,GAAG,UAAU,QAAQ,GAIjC;IACC,OAAO;;;uCAG8B,OAAO,CAAC,QAAQ,CAAC;;;;iCAIvB,OAAO,CAAC,GAAG,UAAU,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;gDAyBd,OAAO,CAAC,eAAe,CAAC;;;;;;;;;MASlE,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ColorScheme, type TerminalTheme } from "@orz/themes";
|
|
2
|
+
import type { ThemePick } from "./pref.ts";
|
|
3
|
+
/** The palettes of `theme` that define `variantId`; `default` is on every one. */
|
|
4
|
+
export declare function schemesDefining(theme: TerminalTheme, variantId: string): ColorScheme[];
|
|
5
|
+
/**
|
|
6
|
+
* Picking a theme row: its default variant, the current mode kept as stored.
|
|
7
|
+
* The store fits the mode to a one-palette theme.
|
|
8
|
+
*/
|
|
9
|
+
export declare function pickForTheme(current: ThemePick, theme: TerminalTheme): ThemePick;
|
|
10
|
+
/**
|
|
11
|
+
* Picking a variant. Under `system` the mode stays, so a dark-only variant
|
|
12
|
+
* picked by day shows at night. A pinned mode whose palette lacks the variant
|
|
13
|
+
* moves to one that has it, or the click would show nothing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function pickForVariant(current: ThemePick, theme: TerminalTheme, variantId: string): ThemePick;
|
|
16
|
+
/**
|
|
17
|
+
* What hovering a variant shows: the pick it would commit, with the mode
|
|
18
|
+
* pinned to a palette that has the variant when the one `system` shows now
|
|
19
|
+
* does not, so hovering AMOLED by day still shows AMOLED.
|
|
20
|
+
*/
|
|
21
|
+
export declare function previewForVariant(current: ThemePick, theme: TerminalTheme, variantId: string, systemScheme: ColorScheme): ThemePick;
|
|
22
|
+
//# sourceMappingURL=picks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picks.d.ts","sourceRoot":"","sources":["../../src/theme/picks.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAGhB,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,kFAAkF;AAClF,wBAAgB,eAAe,CAC7B,KAAK,EAAE,aAAa,EACpB,SAAS,EAAE,MAAM,GAChB,WAAW,EAAE,CAMf;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,SAAS,EAClB,KAAK,EAAE,aAAa,GACnB,SAAS,CAEX;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,SAAS,EAClB,KAAK,EAAE,aAAa,EACpB,SAAS,EAAE,MAAM,GAChB,SAAS,CASX;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,SAAS,EAClB,KAAK,EAAE,aAAa,EACpB,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,WAAW,GACxB,SAAS,CAMX"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DEFAULT_VARIANT, schemesOf, } from "@orz/themes";
|
|
2
|
+
/** The palettes of `theme` that define `variantId`; `default` is on every one. */
|
|
3
|
+
export function schemesDefining(theme, variantId) {
|
|
4
|
+
return schemesOf(theme).filter((scheme) => variantId === DEFAULT_VARIANT ||
|
|
5
|
+
Object.hasOwn(theme[scheme]?.variants ?? {}, variantId));
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Picking a theme row: its default variant, the current mode kept as stored.
|
|
9
|
+
* The store fits the mode to a one-palette theme.
|
|
10
|
+
*/
|
|
11
|
+
export function pickForTheme(current, theme) {
|
|
12
|
+
return { theme: theme.id, mode: current.mode };
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Picking a variant. Under `system` the mode stays, so a dark-only variant
|
|
16
|
+
* picked by day shows at night. A pinned mode whose palette lacks the variant
|
|
17
|
+
* moves to one that has it, or the click would show nothing.
|
|
18
|
+
*/
|
|
19
|
+
export function pickForVariant(current, theme, variantId) {
|
|
20
|
+
const defining = schemesDefining(theme, variantId);
|
|
21
|
+
const mode = current.mode !== "system" && !defining.includes(current.mode)
|
|
22
|
+
? (defining[0] ?? current.mode)
|
|
23
|
+
: current.mode;
|
|
24
|
+
const pick = { theme: theme.id, mode };
|
|
25
|
+
if (variantId !== DEFAULT_VARIANT)
|
|
26
|
+
pick.variant = variantId;
|
|
27
|
+
return pick;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* What hovering a variant shows: the pick it would commit, with the mode
|
|
31
|
+
* pinned to a palette that has the variant when the one `system` shows now
|
|
32
|
+
* does not, so hovering AMOLED by day still shows AMOLED.
|
|
33
|
+
*/
|
|
34
|
+
export function previewForVariant(current, theme, variantId, systemScheme) {
|
|
35
|
+
const pick = pickForVariant(current, theme, variantId);
|
|
36
|
+
if (pick.mode !== "system")
|
|
37
|
+
return pick;
|
|
38
|
+
const defining = schemesDefining(theme, variantId);
|
|
39
|
+
if (defining.includes(systemScheme) || defining[0] === undefined)
|
|
40
|
+
return pick;
|
|
41
|
+
return { ...pick, mode: defining[0] };
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=picks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picks.js","sourceRoot":"","sources":["../../src/theme/picks.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EACf,SAAS,GAEV,MAAM,aAAa,CAAC;AAGrB,kFAAkF;AAClF,MAAM,UAAU,eAAe,CAC7B,KAAoB,EACpB,SAAiB;IAEjB,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,CAC5B,CAAC,MAAM,EAAE,EAAE,CACT,SAAS,KAAK,eAAe;QAC7B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,QAAQ,IAAI,EAAE,EAAE,SAAS,CAAC,CAC1D,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAkB,EAClB,KAAoB;IAEpB,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAkB,EAClB,KAAoB,EACpB,SAAiB;IAEjB,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACnD,MAAM,IAAI,GACR,OAAO,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC;QAC3D,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;QAC/B,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IACnB,MAAM,IAAI,GAAc,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC;IAClD,IAAI,SAAS,KAAK,eAAe;QAAE,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC;IAC5D,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAkB,EAClB,KAAoB,EACpB,SAAiB,EACjB,YAAyB;IAEzB,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IACvD,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACxC,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACnD,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC9E,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ColorScheme, type TerminalTheme, type Theme } from "@orz/themes";
|
|
2
|
+
export type ThemeMode = "system" | ColorScheme;
|
|
3
|
+
export interface ThemePick {
|
|
4
|
+
theme: string;
|
|
5
|
+
mode: ThemeMode;
|
|
6
|
+
/** One id for the whole theme; absent = "default". */
|
|
7
|
+
variant?: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ThemePref {
|
|
10
|
+
/** Present exactly when the store has a UI slot. */
|
|
11
|
+
ui?: ThemePick;
|
|
12
|
+
/** Absent = the terminal follows the UI pick. */
|
|
13
|
+
terminal?: ThemePick;
|
|
14
|
+
}
|
|
15
|
+
export interface ThemeSlots {
|
|
16
|
+
themes?: readonly Theme[];
|
|
17
|
+
terminalThemes?: readonly TerminalTheme[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The slugs `@orz/ui` stored before themes became data, so a pref saved by
|
|
21
|
+
* an app that adopts the store keeps its theme.
|
|
22
|
+
*/
|
|
23
|
+
export declare const LEGACY_THEME_PREFS: Readonly<Record<string, ThemePick>>;
|
|
24
|
+
/** The pick made valid for one theme: a possible mode, a defined variant. */
|
|
25
|
+
export declare function fitPick(pick: ThemePick, theme: TerminalTheme): ThemePick;
|
|
26
|
+
/**
|
|
27
|
+
* The pref made valid for the slots the store has. A pick naming no theme
|
|
28
|
+
* falls back to the first of `fallback`'s list, by default the slot's own.
|
|
29
|
+
*/
|
|
30
|
+
export declare function normalizePref(pref: ThemePref, slots: ThemeSlots, fallback?: ThemeSlots): ThemePref;
|
|
31
|
+
/**
|
|
32
|
+
* The stored pref in the current shape, not yet fitted to any theme list:
|
|
33
|
+
* the store keeps it as asked for, so a pick on a theme that arrives later
|
|
34
|
+
* (a custom one) survives until it does.
|
|
35
|
+
*/
|
|
36
|
+
export declare function readStoredPref(raw: string | null): ThemePref;
|
|
37
|
+
/** JSON in the current shape, else a legacy shape, else the fallback. */
|
|
38
|
+
export declare function parseStoredPref(raw: string | null, slots: ThemeSlots): ThemePref;
|
|
39
|
+
//# sourceMappingURL=pref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pref.d.ts","sourceRoot":"","sources":["../../src/theme/pref.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAClB,KAAK,KAAK,EACX,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAC/C,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,SAAS;IACxB,oDAAoD;IACpD,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,iDAAiD;IACjD,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CAC3C;AAED;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAqBlE,CAAC;AAwBF,6EAA6E;AAC7E,wBAAgB,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,aAAa,GAAG,SAAS,CAYxE;AAKD;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,UAAU,EACjB,QAAQ,GAAE,UAAkB,GAC3B,SAAS,CAwBX;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CA8B5D;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,GAAG,IAAI,EAClB,KAAK,EAAE,UAAU,GAChB,SAAS,CAEX"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { DEFAULT_VARIANT, } from "@orz/themes";
|
|
2
|
+
/**
|
|
3
|
+
* The slugs `@orz/ui` stored before themes became data, so a pref saved by
|
|
4
|
+
* an app that adopts the store keeps its theme.
|
|
5
|
+
*/
|
|
6
|
+
export const LEGACY_THEME_PREFS = {
|
|
7
|
+
system: { theme: "default", mode: "system" },
|
|
8
|
+
light: { theme: "default", mode: "light" },
|
|
9
|
+
dark: { theme: "default", mode: "dark" },
|
|
10
|
+
"pico-light": { theme: "picotera", mode: "light" },
|
|
11
|
+
"tera-dark": { theme: "picotera", mode: "dark" },
|
|
12
|
+
"solarized-light": { theme: "solarized", mode: "light" },
|
|
13
|
+
"solarized-dark": { theme: "solarized", mode: "dark" },
|
|
14
|
+
"vs-light": { theme: "vs", mode: "light" },
|
|
15
|
+
"vs-dark": { theme: "vs", mode: "dark" },
|
|
16
|
+
"github-light": { theme: "github", mode: "light" },
|
|
17
|
+
"github-dark": { theme: "github", mode: "dark" },
|
|
18
|
+
"catppuccin-latte": { theme: "catppuccin", mode: "light" },
|
|
19
|
+
"catppuccin-mocha": { theme: "catppuccin", mode: "dark" },
|
|
20
|
+
"gruvbox-light": { theme: "gruvbox", mode: "light" },
|
|
21
|
+
"gruvbox-dark": { theme: "gruvbox", mode: "dark" },
|
|
22
|
+
dracula: { theme: "dracula", mode: "dark" },
|
|
23
|
+
nord: { theme: "nord", mode: "dark" },
|
|
24
|
+
"tokyo-night": { theme: "tokyo-night", mode: "dark" },
|
|
25
|
+
"one-dark": { theme: "one-dark", mode: "dark" },
|
|
26
|
+
monokai: { theme: "monokai", mode: "dark" },
|
|
27
|
+
};
|
|
28
|
+
const MODES = ["system", "light", "dark"];
|
|
29
|
+
/** A pick from untrusted JSON, or undefined when it names no theme. */
|
|
30
|
+
function pickOf(value) {
|
|
31
|
+
if (typeof value !== "object" || value === null)
|
|
32
|
+
return undefined;
|
|
33
|
+
const { theme, mode, variant } = value;
|
|
34
|
+
if (typeof theme !== "string")
|
|
35
|
+
return undefined;
|
|
36
|
+
const pick = {
|
|
37
|
+
theme,
|
|
38
|
+
mode: MODES.includes(mode) ? mode : "system",
|
|
39
|
+
};
|
|
40
|
+
if (typeof variant === "string")
|
|
41
|
+
pick.variant = variant;
|
|
42
|
+
return pick;
|
|
43
|
+
}
|
|
44
|
+
function definesVariant(theme, id) {
|
|
45
|
+
return [theme.light, theme.dark].some((palette) => palette?.variants !== undefined && Object.hasOwn(palette.variants, id));
|
|
46
|
+
}
|
|
47
|
+
/** The pick made valid for one theme: a possible mode, a defined variant. */
|
|
48
|
+
export function fitPick(pick, theme) {
|
|
49
|
+
const mode = theme.light && theme.dark ? pick.mode : theme.light ? "light" : "dark";
|
|
50
|
+
const out = { theme: theme.id, mode };
|
|
51
|
+
if (pick.variant !== undefined &&
|
|
52
|
+
pick.variant !== DEFAULT_VARIANT &&
|
|
53
|
+
definesVariant(theme, pick.variant)) {
|
|
54
|
+
out.variant = pick.variant;
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
const SYSTEM = (theme) => fitPick({ theme: theme.id, mode: "system" }, theme);
|
|
59
|
+
/**
|
|
60
|
+
* The pref made valid for the slots the store has. A pick naming no theme
|
|
61
|
+
* falls back to the first of `fallback`'s list, by default the slot's own.
|
|
62
|
+
*/
|
|
63
|
+
export function normalizePref(pref, slots, fallback = slots) {
|
|
64
|
+
const out = {};
|
|
65
|
+
const ui = pickOf(pref.ui);
|
|
66
|
+
const terminal = pickOf(pref.terminal);
|
|
67
|
+
const uiSlot = slots.themes !== undefined && slots.themes.length > 0;
|
|
68
|
+
if (uiSlot) {
|
|
69
|
+
const themes = slots.themes;
|
|
70
|
+
const theme = ui && themes.find((t) => t.id === ui.theme);
|
|
71
|
+
out.ui =
|
|
72
|
+
ui && theme ? fitPick(ui, theme) : SYSTEM((fallback.themes ?? themes)[0]);
|
|
73
|
+
}
|
|
74
|
+
const terminalThemes = slots.terminalThemes;
|
|
75
|
+
if (terminalThemes !== undefined && terminalThemes.length > 0) {
|
|
76
|
+
const theme = terminal && terminalThemes.find((t) => t.id === terminal.theme);
|
|
77
|
+
if (terminal && theme)
|
|
78
|
+
out.terminal = fitPick(terminal, theme);
|
|
79
|
+
// Without a UI to follow, the terminal always has a pick of its own.
|
|
80
|
+
else if (!uiSlot) {
|
|
81
|
+
out.terminal = SYSTEM((fallback.terminalThemes ?? terminalThemes)[0]);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The stored pref in the current shape, not yet fitted to any theme list:
|
|
88
|
+
* the store keeps it as asked for, so a pick on a theme that arrives later
|
|
89
|
+
* (a custom one) survives until it does.
|
|
90
|
+
*/
|
|
91
|
+
export function readStoredPref(raw) {
|
|
92
|
+
let parsed = raw;
|
|
93
|
+
if (raw !== null) {
|
|
94
|
+
try {
|
|
95
|
+
parsed = JSON.parse(raw);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// a bare legacy slug is not JSON
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (typeof parsed === "string") {
|
|
102
|
+
const legacy = Object.hasOwn(LEGACY_THEME_PREFS, parsed)
|
|
103
|
+
? LEGACY_THEME_PREFS[parsed]
|
|
104
|
+
: undefined;
|
|
105
|
+
return legacy ? { ui: legacy } : {};
|
|
106
|
+
}
|
|
107
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
108
|
+
const record = parsed;
|
|
109
|
+
// The JSON shape @orz/ui stored a pick in before it had two slots.
|
|
110
|
+
if ("theme" in record) {
|
|
111
|
+
const ui = pickOf(record);
|
|
112
|
+
return ui ? { ui } : {};
|
|
113
|
+
}
|
|
114
|
+
const out = {};
|
|
115
|
+
const ui = pickOf(record.ui);
|
|
116
|
+
const terminal = pickOf(record.terminal);
|
|
117
|
+
if (ui)
|
|
118
|
+
out.ui = ui;
|
|
119
|
+
if (terminal)
|
|
120
|
+
out.terminal = terminal;
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
123
|
+
return {};
|
|
124
|
+
}
|
|
125
|
+
/** JSON in the current shape, else a legacy shape, else the fallback. */
|
|
126
|
+
export function parseStoredPref(raw, slots) {
|
|
127
|
+
return normalizePref(readStoredPref(raw), slots);
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=pref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pref.js","sourceRoot":"","sources":["../../src/theme/pref.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,GAGhB,MAAM,aAAa,CAAC;AAqBrB;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAwC;IACrE,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC5C,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE;IAC1C,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;IACxC,YAAY,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE;IAClD,WAAW,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE;IAChD,iBAAiB,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE;IACxD,gBAAgB,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE;IACtD,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE;IAC1C,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE;IACxC,cAAc,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE;IAClD,aAAa,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE;IAChD,kBAAkB,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE;IAC1D,kBAAkB,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE;IACzD,eAAe,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE;IACpD,cAAc,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;IAClD,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;IAC3C,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IACrC,aAAa,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE;IACrD,UAAU,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE;IAC/C,OAAO,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;CAC5C,CAAC;AAEF,MAAM,KAAK,GAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAE9D,uEAAuE;AACvE,SAAS,MAAM,CAAC,KAAc;IAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAClE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,KAAgC,CAAC;IAClE,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChD,MAAM,IAAI,GAAc;QACtB,KAAK;QACL,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAE,IAAkB,CAAC,CAAC,CAAC,QAAQ;KAC5D,CAAC;IACF,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,cAAc,CAAC,KAAoB,EAAE,EAAU;IACtD,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CACnC,CAAC,OAAO,EAAE,EAAE,CACV,OAAO,EAAE,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CACzE,CAAC;AACJ,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,OAAO,CAAC,IAAe,EAAE,KAAoB;IAC3D,MAAM,IAAI,GACR,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;IACzE,MAAM,GAAG,GAAc,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC;IACjD,IACE,IAAI,CAAC,OAAO,KAAK,SAAS;QAC1B,IAAI,CAAC,OAAO,KAAK,eAAe;QAChC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,EACnC,CAAC;QACD,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;IAC7B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,MAAM,GAAG,CAAC,KAAoB,EAAE,EAAE,CACtC,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,KAAK,CAAC,CAAC;AAEtD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAe,EACf,KAAiB,EACjB,QAAQ,GAAe,KAAK;IAE5B,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3B,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAErE,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,KAAK,CAAC,MAA0B,CAAC;QAChD,MAAM,KAAK,GAAG,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1D,GAAG,CAAC,EAAE;YACJ,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;IAC5C,IAAI,cAAc,KAAK,SAAS,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9D,MAAM,KAAK,GACT,QAAQ,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC;QAClE,IAAI,QAAQ,IAAI,KAAK;YAAE,GAAG,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC/D,qEAAqE;aAChE,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,cAAc,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,GAAkB;IAC/C,IAAI,MAAM,GAAY,GAAG,CAAC;IAC1B,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3B,CAAC;QAAC,MAAM,CAAC;YACP,iCAAiC;QACnC,CAAC;IACH,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC;YACtD,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC;YAC5B,CAAC,CAAC,SAAS,CAAC;QACd,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,CAAC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClD,MAAM,MAAM,GAAG,MAAiC,CAAC;QACjD,mEAAmE;QACnE,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;YACtB,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1B,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1B,CAAC;QACD,MAAM,GAAG,GAAc,EAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC7B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzC,IAAI,EAAE;YAAE,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC;QACpB,IAAI,QAAQ;YAAE,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACtC,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,eAAe,CAC7B,GAAkB,EAClB,KAAiB;IAEjB,OAAO,aAAa,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { AnyCustomTheme, ColorScheme, TerminalTheme, Theme } from "@orz/themes";
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
import type { ThemePref } from "./pref.ts";
|
|
4
|
+
import type { ResolvedTerminalTheme, ThemePreview, ThemeStore } from "./store.ts";
|
|
5
|
+
export declare function ThemeProvider({ store, children, }: {
|
|
6
|
+
store: ThemeStore;
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
9
|
+
interface CustomThemeControls {
|
|
10
|
+
preview: (next: ThemePreview | null) => void;
|
|
11
|
+
customThemes: readonly AnyCustomTheme[];
|
|
12
|
+
setCustomThemes: (next: readonly AnyCustomTheme[]) => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The provider's UI theme, as shown (a preview included); `pref` is the
|
|
16
|
+
* committed pick. Outside a provider it answers the default theme under
|
|
17
|
+
* system, light, and ignores `setPref`, `preview` and `setCustomThemes`, so a
|
|
18
|
+
* primitive rendered on its own still renders.
|
|
19
|
+
*/
|
|
20
|
+
export declare function useTheme(): {
|
|
21
|
+
pref: ThemePref;
|
|
22
|
+
themes: readonly Theme[];
|
|
23
|
+
theme: Theme;
|
|
24
|
+
colorScheme: ColorScheme;
|
|
25
|
+
variant: string;
|
|
26
|
+
setPref: (next: ThemePref) => void;
|
|
27
|
+
} & CustomThemeControls;
|
|
28
|
+
/** The provider's terminal theme as shown, ready for `xtermTheme(tokens)`. */
|
|
29
|
+
export declare function useTerminalTheme(): ResolvedTerminalTheme & {
|
|
30
|
+
themes: readonly TerminalTheme[];
|
|
31
|
+
} & CustomThemeControls;
|
|
32
|
+
/**
|
|
33
|
+
* Which slots the provider's store has, which the two hooks cannot say: each
|
|
34
|
+
* falls back where its slot is missing. Outside a provider: the UI slot only.
|
|
35
|
+
*/
|
|
36
|
+
export declare function useThemeSlots(): {
|
|
37
|
+
ui: boolean;
|
|
38
|
+
terminal: boolean;
|
|
39
|
+
};
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/theme/provider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EACX,aAAa,EAEb,KAAK,EACN,MAAM,aAAa,CAAC;AAErB,OAAO,EAEL,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EACV,qBAAqB,EAErB,YAAY,EACZ,UAAU,EACX,MAAM,YAAY,CAAC;AAIpB,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,QAAQ,GACT,EAAE;IACD,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,+BAEA;AA4BD,UAAU,mBAAmB;IAC3B,OAAO,EAAE,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,YAAY,EAAE,SAAS,cAAc,EAAE,CAAC;IACxC,eAAe,EAAE,CAAC,IAAI,EAAE,SAAS,cAAc,EAAE,KAAK,IAAI,CAAC;CAC5D;AAoBD;;;;;GAKG;AACH,wBAAgB,QAAQ,IAAI;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;CACpC,GAAG,mBAAmB,CAwBtB;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,IAAI,qBAAqB,GAAG;IAC1D,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;CAClC,GAAG,mBAAmB,CAoBtB;AAID;;;GAGG;AACH,wBAAgB,aAAa,IAAI;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAalE"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { defaultTheme } from "@orz/themes/themes/default";
|
|
3
|
+
import { createContext, useContext, useMemo, useSyncExternalStore, } from "react";
|
|
4
|
+
const ThemeContext = createContext(null);
|
|
5
|
+
export function ThemeProvider({ store, children, }) {
|
|
6
|
+
return _jsx(ThemeContext, { value: store, children: children });
|
|
7
|
+
}
|
|
8
|
+
const noop = () => { };
|
|
9
|
+
const subscribeNowhere = () => noop;
|
|
10
|
+
// What a primitive rendered outside any provider (or under a terminal-only
|
|
11
|
+
// store) paints with: the stylesheet's own :root baseline.
|
|
12
|
+
const FALLBACK_PREF = { ui: { theme: "default", mode: "system" } };
|
|
13
|
+
const FALLBACK_THEMES = [defaultTheme];
|
|
14
|
+
const FALLBACK_RESOLVED = {
|
|
15
|
+
theme: defaultTheme,
|
|
16
|
+
colorScheme: "light",
|
|
17
|
+
variant: "default",
|
|
18
|
+
};
|
|
19
|
+
const FALLBACK_TERMINAL = {
|
|
20
|
+
following: true,
|
|
21
|
+
theme: defaultTheme,
|
|
22
|
+
colorScheme: "light",
|
|
23
|
+
variant: "default",
|
|
24
|
+
tokens: defaultTheme.light.terminal,
|
|
25
|
+
};
|
|
26
|
+
const fallbackPref = () => FALLBACK_PREF;
|
|
27
|
+
const fallbackResolved = () => FALLBACK_RESOLVED;
|
|
28
|
+
const fallbackTerminal = () => FALLBACK_TERMINAL;
|
|
29
|
+
const fallbackThemes = () => FALLBACK_THEMES;
|
|
30
|
+
const NO_CUSTOM_THEMES = Object.freeze([]);
|
|
31
|
+
const fallbackCustomThemes = () => NO_CUSTOM_THEMES;
|
|
32
|
+
/** What both hooks add for a picker or an editor: preview and the custom list. */
|
|
33
|
+
function useCustomThemeControls(store, subscribe) {
|
|
34
|
+
const getCustomThemes = store?.getCustomThemes ?? fallbackCustomThemes;
|
|
35
|
+
const customThemes = useSyncExternalStore(subscribe, getCustomThemes, getCustomThemes);
|
|
36
|
+
return {
|
|
37
|
+
preview: store?.preview ?? noop,
|
|
38
|
+
customThemes,
|
|
39
|
+
setCustomThemes: store?.setCustomThemes ?? noop,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The provider's UI theme, as shown (a preview included); `pref` is the
|
|
44
|
+
* committed pick. Outside a provider it answers the default theme under
|
|
45
|
+
* system, light, and ignores `setPref`, `preview` and `setCustomThemes`, so a
|
|
46
|
+
* primitive rendered on its own still renders.
|
|
47
|
+
*/
|
|
48
|
+
export function useTheme() {
|
|
49
|
+
const store = useContext(ThemeContext);
|
|
50
|
+
const subscribe = store?.subscribe ?? subscribeNowhere;
|
|
51
|
+
const getPref = store?.getPref ?? fallbackPref;
|
|
52
|
+
// Read apart from the pref: under "system" an OS switch changes the
|
|
53
|
+
// resolved theme while the pref snapshot stays the same.
|
|
54
|
+
const getResolved = store
|
|
55
|
+
? () => store.getResolved() ?? FALLBACK_RESOLVED
|
|
56
|
+
: fallbackResolved;
|
|
57
|
+
const getThemes = store && store.getThemes().length > 0 ? store.getThemes : fallbackThemes;
|
|
58
|
+
const pref = useSyncExternalStore(subscribe, getPref, getPref);
|
|
59
|
+
const resolved = useSyncExternalStore(subscribe, getResolved, getResolved);
|
|
60
|
+
const themes = useSyncExternalStore(subscribe, getThemes, getThemes);
|
|
61
|
+
const controls = useCustomThemeControls(store, subscribe);
|
|
62
|
+
return {
|
|
63
|
+
...controls,
|
|
64
|
+
pref,
|
|
65
|
+
themes,
|
|
66
|
+
theme: resolved.theme,
|
|
67
|
+
colorScheme: resolved.colorScheme,
|
|
68
|
+
variant: resolved.variant,
|
|
69
|
+
setPref: store?.setPref ?? noop,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** The provider's terminal theme as shown, ready for `xtermTheme(tokens)`. */
|
|
73
|
+
export function useTerminalTheme() {
|
|
74
|
+
const store = useContext(ThemeContext);
|
|
75
|
+
const subscribe = store?.subscribe ?? subscribeNowhere;
|
|
76
|
+
const getTerminal = store?.getTerminal ?? fallbackTerminal;
|
|
77
|
+
// A UI-only store's terminal follows the UI, so its list is the UI's.
|
|
78
|
+
const getThemes = !store
|
|
79
|
+
? fallbackThemes
|
|
80
|
+
: store.getTerminalThemes().length > 0
|
|
81
|
+
? store.getTerminalThemes
|
|
82
|
+
: store.getThemes;
|
|
83
|
+
const terminal = useSyncExternalStore(subscribe, getTerminal, getTerminal);
|
|
84
|
+
const themes = useSyncExternalStore(subscribe, getThemes, getThemes);
|
|
85
|
+
const { preview, customThemes, setCustomThemes } = useCustomThemeControls(store, subscribe);
|
|
86
|
+
return useMemo(() => ({ ...terminal, themes, preview, customThemes, setCustomThemes }), [terminal, themes, preview, customThemes, setCustomThemes]);
|
|
87
|
+
}
|
|
88
|
+
const OUTSIDE_SLOTS = { ui: true, terminal: false };
|
|
89
|
+
/**
|
|
90
|
+
* Which slots the provider's store has, which the two hooks cannot say: each
|
|
91
|
+
* falls back where its slot is missing. Outside a provider: the UI slot only.
|
|
92
|
+
*/
|
|
93
|
+
export function useThemeSlots() {
|
|
94
|
+
const store = useContext(ThemeContext);
|
|
95
|
+
// A store's slots are fixed when it is created.
|
|
96
|
+
return useMemo(() => store
|
|
97
|
+
? {
|
|
98
|
+
ui: store.getThemes().length > 0,
|
|
99
|
+
terminal: store.getTerminalThemes().length > 0,
|
|
100
|
+
}
|
|
101
|
+
: OUTSIDE_SLOTS, [store]);
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=provider.js.map
|