@vestow/theme 0.1.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.
@@ -0,0 +1,90 @@
1
+ /**
2
+ * `definePreset()` — ghi đè token lúc CHẠY, cùng vai với `definePreset` của
3
+ * PrimeVue. Không dependency, không framework.
4
+ *
5
+ * VÌ SAO CÓ, KHI CSS ĐÃ GHI ĐÈ ĐƯỢC. Viết `:root { --primary: … }` trong file
6
+ * CSS của app vẫn là cách gọn nhất và nên là mặc định. Cái này giải đúng một ca
7
+ * mà CSS tĩnh không giải được: giá trị chỉ biết LÚC CHẠY — màu thương hiệu đọc
8
+ * từ API, theme người dùng lưu trong tài khoản, bản xem trước trong trình dựng
9
+ * theme. Ngoài ca đó thì đừng dùng.
10
+ *
11
+ * GIÁ TRỊ LÀ CHUỖI CSS, JS KHÔNG HIỂU NÓ. Cố ý. Token ở đây viết bằng
12
+ * `color-mix(in oklab, …)` và `oklch(from …)`; mô hình hoá lại mấy phép đó
13
+ * trong JS là viết lại một engine màu, và đã đo được là nó ra số khác trình
14
+ * duyệt — quét trong sRGB cho 4,57 trong khi giá trị thật là 4,19. Nên JS chỉ
15
+ * bê nguyên chuỗi; trình duyệt vẫn là chỗ tính.
16
+ *
17
+ * KHÔNG CHẠM `document` Ở TẦNG MODULE, cùng kỷ luật với `controller.ts`: package
18
+ * này phải import được trong SSR. Mọi thứ đụng DOM nằm trong hàm.
19
+ *
20
+ * CHỖ NÓ VỚI KHÔNG TỚI. Preset ghi ở `:root`, nên nó KHÔNG đè được token mà một
21
+ * rule khác khai lại trên phần tử CON. Khai báo trực tiếp trên một phần tử luôn
22
+ * thắng giá trị thừa kế, bất kể điểm đặc hiệu. Ba chỗ có thật, đã đo:
23
+ *
24
+ * - `TokenTable` lồng `.light` / `.dark` để vẽ ô màu hai chế độ cạnh nhau
25
+ * (160 ô trên một trang component). Preset đổi `:root` thì ô màu GIỮ
26
+ * NGUYÊN — đúng ý: bảng đó tài liệu hoá giá trị khai trong CSS.
27
+ * - `--popover` và ba token nữa mà trục menu khai lại trên `.ui-menu`.
28
+ * - 19 dòng `--button-*` mà `surfaces.css` khai lại trên `.ui-button` ở theme
29
+ * kính.
30
+ *
31
+ * Đó là cái giá đã ghi ở CLAUDE.md ("tầng token component CẮT ĐỨT mọi phép ghi
32
+ * đè theo phạm vi"), không phải lỗi mới.
33
+ */
34
+ import type { TokenName, TokenTree } from './token-names.js';
35
+ /**
36
+ * Cho phép cả tên ngoài danh sách: app có quyền khai biến của riêng nó.
37
+ *
38
+ * Mẫu `--${string}` chứ KHÔNG phải `string & {}`. Hai lý do, và cái thứ hai là
39
+ * bắt buộc:
40
+ *
41
+ * 1. `& {}` giữ được gợi ý tự động, nhưng mẫu template literal cũng giữ.
42
+ * 2. `string & {}` mở ra một index signature nhận MỌI khoá chuỗi, nên
43
+ * `Partial<Record<…, string>> & TokenTree` sẽ đòi `button` vừa là chuỗi vừa
44
+ * là object — một kiểu không giá trị nào thoả. Siết về `--*` thì hai nửa
45
+ * không còn khoá chung, vì không nhánh nào của cây bắt đầu bằng `--`.
46
+ */
47
+ type AnyToken = TokenName | `--${string}`;
48
+ /**
49
+ * Nhận CẢ HAI dạng khoá trong cùng một object, và không có gì mơ hồ: tên custom
50
+ * property luôn bắt đầu bằng `--`, còn một nhánh của cây thì không bao giờ.
51
+ *
52
+ * { '--button-radius': '2px' } // phẳng, đúng tên CSS
53
+ * { button: { radius: '2px' } } // cây, dạng `button.border.radius`
54
+ *
55
+ * Dạng phẳng KHÔNG bỏ đi: nó là thứ duy nhất viết được một tên tính lúc chạy,
56
+ * và nó đọc thẳng ra tên CSS thật nên khi debug thì khỏi phải dịch ngược.
57
+ */
58
+ export type TokenMap = Partial<Record<AnyToken, string>> & TokenTree;
59
+ export interface Preset {
60
+ /** Ghi cho cả hai chế độ sáng và tối. */
61
+ base?: TokenMap;
62
+ /** Chỉ chế độ sáng — tức khi `<html>` KHÔNG mang class `dark`. */
63
+ light?: TokenMap;
64
+ /** Chỉ chế độ tối. */
65
+ dark?: TokenMap;
66
+ }
67
+ /**
68
+ * Dựng đoạn CSS của preset. Thuần tuý — không đụng DOM, chạy được ở server.
69
+ *
70
+ * Dùng nó khi render phía server: nhúng kết quả vào một thẻ `<style>` mang
71
+ * `id="woodblock-preset"` ngay trong HTML trả về. Trang sẽ không chớp màu, và
72
+ * `definePreset()` ở phía trình duyệt sẽ nhận lại đúng thẻ đó thay vì thêm thẻ
73
+ * thứ hai.
74
+ */
75
+ export declare function presetToCss(preset: Preset): string;
76
+ /** `id` của thẻ `<style>` mà preset ghi vào. Phía SSR dùng lại đúng chuỗi này. */
77
+ export declare const PRESET_STYLE_ID = "woodblock-preset";
78
+ /**
79
+ * Ghi preset vào `<head>`. Gọi lại được: lần sau thay nội dung thẻ cũ chứ không
80
+ * cộng dồn.
81
+ *
82
+ * Gọi TRƯỚC khi mount app. Gọi sau thì lần vẽ đầu dùng token mặc định rồi mới
83
+ * nhảy sang giá trị của preset — thấy rõ một nhịp chớp màu. Muốn chắc chắn
84
+ * không chớp thì đừng dùng hàm này, dùng `presetToCss()` và nhúng lúc SSR.
85
+ */
86
+ export declare function definePreset(preset: Preset): void;
87
+ /** Gỡ preset, trả token về đúng giá trị khai trong CSS. */
88
+ export declare function clearPreset(): void;
89
+ export {};
90
+ //# sourceMappingURL=preset.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../src/preset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAE5D;;;;;;;;;;;GAWG;AACH,KAAK,QAAQ,GAAG,SAAS,GAAG,KAAK,MAAM,EAAE,CAAA;AAEzC;;;;;;;;;GASG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;AAEpE,MAAM,WAAW,MAAM;IACrB,yCAAyC;IACzC,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,kEAAkE;IAClE,KAAK,CAAC,EAAE,QAAQ,CAAA;IAChB,sBAAsB;IACtB,IAAI,CAAC,EAAE,QAAQ,CAAA;CAChB;AA6CD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAUlD;AAED,kFAAkF;AAClF,eAAO,MAAM,eAAe,qBAAqB,CAAA;AAEjD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAgBjD;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,IAAI,IAAI,CAKlC"}
package/dist/preset.js ADDED
@@ -0,0 +1,86 @@
1
+ /**
2
+ * `:root` lặp 5 lần cho ra (0,5,0).
3
+ *
4
+ * Con số 5 là ĐO, không phải chọn cho tròn: rule đặc hiệu nhất đang khai token
5
+ * ở tầng `:root` là `.light[data-chart="teal"]` lặp ba lần trong `charts.css`,
6
+ * tức (0,4,0). Preset phải hơn nó, nếu không nó thua im lặng — đúng cái bẫy
7
+ * `styles.css` đã dính một lần và phải lặp attribute ba lần để thoát.
8
+ *
9
+ * Đo lại khi thêm trục theme mới:
10
+ *
11
+ * grep -hoP '^[^{@\s][^{]*(?=\{)' css/*.css css/components/*.css
12
+ */
13
+ const ROOT = ':root:root:root:root:root';
14
+ /**
15
+ * Làm phẳng cây về đúng tên CSS. Khoá `$` là giá trị của chính nhánh nên nó
16
+ * KHÔNG góp một đoạn tên; một chuỗi đặt thẳng vào nhánh là lối tắt cho `$`.
17
+ */
18
+ function flatten(node, prefix, out) {
19
+ for (const [key, value] of Object.entries(node)) {
20
+ if (value === undefined)
21
+ continue;
22
+ // Khoá phẳng chỉ hợp lệ ở tầng ngoài cùng — bên trong cây thì `--x` không
23
+ // phải một đoạn tên, và nối nó vào là ra một tên không tồn tại.
24
+ const name = key.startsWith('--') ? key : key === '$' ? prefix : `${prefix}-${key}`;
25
+ if (typeof value === 'string')
26
+ out.set(name, value);
27
+ else
28
+ flatten(value, name, out);
29
+ }
30
+ }
31
+ function block(selector, tokens) {
32
+ const flat = new Map();
33
+ flatten(tokens, '-', flat);
34
+ const lines = [...flat].map(([name, value]) => ` ${name}: ${value};`);
35
+ return lines.length === 0 ? '' : `${selector} {\n${lines.join('\n')}\n}`;
36
+ }
37
+ /**
38
+ * Dựng đoạn CSS của preset. Thuần tuý — không đụng DOM, chạy được ở server.
39
+ *
40
+ * Dùng nó khi render phía server: nhúng kết quả vào một thẻ `<style>` mang
41
+ * `id="woodblock-preset"` ngay trong HTML trả về. Trang sẽ không chớp màu, và
42
+ * `definePreset()` ở phía trình duyệt sẽ nhận lại đúng thẻ đó thay vì thêm thẻ
43
+ * thứ hai.
44
+ */
45
+ export function presetToCss(preset) {
46
+ return [
47
+ block(ROOT, preset.base ?? {}),
48
+ // `:not(.dark)` chứ không phải `.light`: chế độ sáng là mặc định, `<html>`
49
+ // không mang class nào. Cùng cách `tokens.css` viết `:root, .light`.
50
+ block(`${ROOT}:not(.dark)`, preset.light ?? {}),
51
+ block(`${ROOT}.dark`, preset.dark ?? {}),
52
+ ]
53
+ .filter(Boolean)
54
+ .join('\n\n');
55
+ }
56
+ /** `id` của thẻ `<style>` mà preset ghi vào. Phía SSR dùng lại đúng chuỗi này. */
57
+ export const PRESET_STYLE_ID = 'woodblock-preset';
58
+ /**
59
+ * Ghi preset vào `<head>`. Gọi lại được: lần sau thay nội dung thẻ cũ chứ không
60
+ * cộng dồn.
61
+ *
62
+ * Gọi TRƯỚC khi mount app. Gọi sau thì lần vẽ đầu dùng token mặc định rồi mới
63
+ * nhảy sang giá trị của preset — thấy rõ một nhịp chớp màu. Muốn chắc chắn
64
+ * không chớp thì đừng dùng hàm này, dùng `presetToCss()` và nhúng lúc SSR.
65
+ */
66
+ export function definePreset(preset) {
67
+ if (typeof document === 'undefined')
68
+ return;
69
+ const css = presetToCss(preset);
70
+ let style = document.getElementById(PRESET_STYLE_ID);
71
+ if (style === null) {
72
+ style = document.createElement('style');
73
+ style.id = PRESET_STYLE_ID;
74
+ // Cuối `<head>`: điểm đặc hiệu đã đủ thắng, nhưng đứng sau thì hoà cũng
75
+ // thắng — rẻ và không hại gì.
76
+ document.head.append(style);
77
+ }
78
+ style.textContent = css;
79
+ }
80
+ /** Gỡ preset, trả token về đúng giá trị khai trong CSS. */
81
+ export function clearPreset() {
82
+ if (typeof document === 'undefined')
83
+ return;
84
+ document.getElementById(PRESET_STYLE_ID)?.remove();
85
+ }
86
+ //# sourceMappingURL=preset.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preset.js","sourceRoot":"","sources":["../src/preset.ts"],"names":[],"mappings":"AAsEA;;;;;;;;;;;GAWG;AACH,MAAM,IAAI,GAAG,2BAA2B,CAAA;AAExC;;;GAGG;AACH,SAAS,OAAO,CAAC,IAAY,EAAE,MAAc,EAAE,GAAwB;IACrE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,IAAI,KAAK,KAAK,SAAS;YACrB,SAAQ;QAEV,0EAA0E;QAC1E,gEAAgE;QAChE,MAAM,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,CAAA;QAEnF,IAAI,OAAO,KAAK,KAAK,QAAQ;YAC3B,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;;YAEpB,OAAO,CAAC,KAAe,EAAE,IAAI,EAAE,GAAG,CAAC,CAAA;IACvC,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,QAAgB,EAAE,MAAgB;IAC/C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAA;IACtC,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;IAE1B,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,KAAK,KAAK,GAAG,CAAC,CAAA;IAEtE,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,QAAQ,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAA;AAC1E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO;QACL,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QAC9B,2EAA2E;QAC3E,qEAAqE;QACrE,KAAK,CAAC,GAAG,IAAI,aAAa,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/C,KAAK,CAAC,GAAG,IAAI,OAAO,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;KACzC;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,MAAM,CAAC,CAAA;AACjB,CAAC;AAED,kFAAkF;AAClF,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAA;AAEjD;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc;IACzC,IAAI,OAAO,QAAQ,KAAK,WAAW;QACjC,OAAM;IAER,MAAM,GAAG,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;IAC/B,IAAI,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,CAAA;IAEpD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;QACvC,KAAK,CAAC,EAAE,GAAG,eAAe,CAAA;QAC1B,wEAAwE;QACxE,8BAA8B;QAC9B,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAC7B,CAAC;IAED,KAAK,CAAC,WAAW,GAAG,GAAG,CAAA;AACzB,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,WAAW;IACzB,IAAI,OAAO,QAAQ,KAAK,WAAW;QACjC,OAAM;IAER,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;AACpD,CAAC"}
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Danh mục ba trục giao diện, và quy ước chúng được ghi lên DOM.
3
+ *
4
+ * Đây là DỮ LIỆU thuần — không import framework nào, không đụng `document`.
5
+ * Vue composable, React hook hay Angular service đều đọc chung file này, nên
6
+ * thêm một bảng màu là mọi framework thấy ngay, không phải chép danh sách.
7
+ */
8
+ export type ColorMode = 'light' | 'dark' | 'system';
9
+ export declare const colorModes: readonly ColorMode[];
10
+ export declare function isColorMode(value: unknown): value is ColorMode;
11
+ /**
12
+ * Bảng màu của thư viện. `hyperion` là bộ token gốc trong tokens.css; bốn bảng
13
+ * còn lại nằm ở palettes.css và được chọn qua thuộc tính `data-palette`.
14
+ */
15
+ export type PaletteId = 'hyperion' | 'solar' | 'nebula' | 'aurora' | 'eclipse';
16
+ export interface PaletteOption {
17
+ id: PaletteId;
18
+ name: string;
19
+ description: string;
20
+ /** Ba màu xem trước: chính, nhạt, đậm. */
21
+ swatches: [string, string, string];
22
+ }
23
+ export declare const palettes: readonly PaletteOption[];
24
+ export declare function isPaletteId(value: unknown): value is PaletteId;
25
+ /**
26
+ * Kiểu bề mặt. `solid` là mặc định; `glass` bật hiệu ứng kính khai trong
27
+ * surfaces.css. Đây là TRỤC RIÊNG, chồng lên bảng màu — Solar + glass hay
28
+ * Nebula + glass đều dùng được.
29
+ */
30
+ export type SurfaceId = 'solid' | 'glass';
31
+ export interface SurfaceOption {
32
+ id: SurfaceId;
33
+ name: string;
34
+ description: string;
35
+ }
36
+ export declare const surfaces: readonly SurfaceOption[];
37
+ export declare function isSurfaceId(value: unknown): value is SurfaceId;
38
+ /**
39
+ * Trục HÌNH KHỐI — bo góc, độ đậm của đường kẻ, độ thoáng của control.
40
+ *
41
+ * Trục thứ tư, độc lập với ba trục kia: `palette` nói về sắc, chế độ màu nói về
42
+ * sáng/tối, `surface` nói về vật liệu, còn cái này nói về hình. Khối CSS nằm ở
43
+ * `styles.css`, chọn bằng thuộc tính `data-style`.
44
+ *
45
+ * TÁM giá trị, và chúng là TỔ HỢP của đúng ba núm vặn — bo góc, độ đậm đường
46
+ * kẻ, độ thoáng của control — chứ không phải tám thiết kế rời. Bảng đối chiếu
47
+ * đầy đủ ở đầu `styles.css`.
48
+ *
49
+ * Điều kiện kết nạp vẫn nguyên: một style phải dựng được từ token ĐÃ CÓ NGƯỜI
50
+ * ĐỌC. Tám khối trong `styles.css` không khai một token mới nào, nên con số tám
51
+ * không kéo theo cái giá mà "bản cạn kiệt kiểu PrimeVue" phải trả. Style thứ
52
+ * chín mà phải đẻ token mới thì đó là dấu hiệu dừng lại.
53
+ *
54
+ * `vega` chính là `default` cũ và `nova` chính là `flat` cũ, giữ nguyên từng
55
+ * con số. Ai từng lưu `flat` sẽ bị `isStyleId` từ chối rồi rơi lui về `vega` —
56
+ * `readStored` không xoá khoá nên chỉ mất một lần chọn lại.
57
+ */
58
+ export type StyleId = 'vega' | 'nova' | 'maia' | 'lyra' | 'mira' | 'luma' | 'sera' | 'rhea';
59
+ export interface StyleOption {
60
+ id: StyleId;
61
+ name: string;
62
+ description: string;
63
+ }
64
+ export declare const styleVariants: readonly StyleOption[];
65
+ export declare function isStyleId(value: unknown): value is StyleId;
66
+ /**
67
+ * Mục menu đang trỏ tới trông thế nào.
68
+ *
69
+ * Trục nhỏ nhất trong bảy trục, và nó chỉ đổi HAI token — `--menu-accent` và
70
+ * `--menu-accent-foreground`, mà `menu-styles.ts` đọc. Không đụng `--accent`
71
+ * chung: Sidebar và Calendar cũng đọc token đó.
72
+ */
73
+ export type MenuAccentId = 'subtle' | 'solid' | 'muted';
74
+ export interface MenuAccentOption {
75
+ id: MenuAccentId;
76
+ name: string;
77
+ description: string;
78
+ }
79
+ export declare const menuAccents: readonly MenuAccentOption[];
80
+ export declare function isMenuAccentId(value: unknown): value is MenuAccentId;
81
+ /**
82
+ * Mặt menu lấy màu ở đâu.
83
+ *
84
+ * `default` là mặt `--popover` như mọi overlay khác. `inverted` lật menu sang
85
+ * phía đối diện của chế độ đang bật — menu tối trên giao diện sáng, menu sáng
86
+ * trên giao diện tối. shadcn gọi hai giá trị này là nhóm "Color" của hàng
87
+ * "Menu".
88
+ *
89
+ * VÌ SAO KHÔNG ĐẺ TOKEN MỚI: khối CSS đặt lại `--popover` và bạn bè NGAY TRÊN
90
+ * phần tử menu (`.ui-menu`), nên nó chỉ có hiệu lực bên trong menu — Popover và
91
+ * Tooltip vốn cũng đọc `--popover` thì không dịch một pixel nào. Đây là chỗ
92
+ * khác `--menu-accent`: token đó buộc phải tách ra vì `--accent` bị đọc bởi
93
+ * những phần tử NGOÀI menu, còn ở đây phạm vi đã tự khoanh bằng cây DOM.
94
+ *
95
+ * Vì khai trên chính phần tử chứ không phải trên `:root`, trục này KHÔNG dính
96
+ * cái bẫy độ đặc hiệu của `styles.css` / `charts.css` / `bases.css` — khai báo
97
+ * trực tiếp luôn thắng giá trị thừa kế, không cần lặp attribute ba lần.
98
+ */
99
+ export type MenuColorId = 'default' | 'inverted';
100
+ export interface MenuColorOption {
101
+ id: MenuColorId;
102
+ name: string;
103
+ description: string;
104
+ }
105
+ export declare const menuColors: readonly MenuColorOption[];
106
+ export declare function isMenuColorId(value: unknown): value is MenuColorId;
107
+ /**
108
+ * Mặt menu đục hay trong. Nhóm "Appearance" của hàng "Menu" bên shadcn.
109
+ *
110
+ * KHÔNG có tác dụng khi `surface` đang là `glass`, và đó là cố ý: theme kính đã
111
+ * làm mọi mặt `bg-popover` trong mờ rồi, bật thêm là chồng kính lên kính — đúng
112
+ * điều tài liệu Liquid Glass của Apple dặn đừng làm. Khối CSS tự loại mình ra
113
+ * bằng `:root:not([data-surface="glass"])`; xem `menus.css`.
114
+ */
115
+ export type MenuAppearanceId = 'solid' | 'translucent';
116
+ export interface MenuAppearanceOption {
117
+ id: MenuAppearanceId;
118
+ name: string;
119
+ description: string;
120
+ }
121
+ export declare const menuAppearances: readonly MenuAppearanceOption[];
122
+ export declare function isMenuAppearanceId(value: unknown): value is MenuAppearanceId;
123
+ /**
124
+ * Họ màu của nhóm TRUNG TÍNH — nền trang, card, viền, chữ mờ.
125
+ *
126
+ * Tách khỏi `palette` vì hai câu hỏi khác nhau: `palette` chọn sắc CHÍNH, còn
127
+ * cái này chọn xám nào đỡ nó. shadcn gọi hai thứ đó là "Theme" và "Base Color".
128
+ *
129
+ * `slate` là mặc định — nó chính là giá trị trong `tokens.css`, nên không có
130
+ * khối CSS nào, cùng lẽ với `hyperion` / `solid` / `default` / `theme`.
131
+ */
132
+ export type BaseId = 'slate' | 'zinc' | 'stone' | 'mist' | 'taupe' | 'olive' | 'mauve' | 'neutral';
133
+ export interface BaseOption {
134
+ id: BaseId;
135
+ name: string;
136
+ description: string;
137
+ /** Một ô màu xem trước — nấc 500 của họ, ở chroma mà trục ám màu dựng ra. */
138
+ swatch: string;
139
+ }
140
+ export declare const bases: readonly BaseOption[];
141
+ export declare function isBaseId(value: unknown): value is BaseId;
142
+ /**
143
+ * Bộ màu cho năm chuỗi dữ liệu của biểu đồ.
144
+ *
145
+ * `theme` KHÔNG phải một bộ — nó là "đừng ghi đè", để `palettes.css` quyết định
146
+ * như hôm nay. Cùng khuôn với `auto` của ô chọn bo góc ở trang `/create`.
147
+ *
148
+ * Năm bộ còn lại chính là năm bộ mà năm bảng màu đang dùng, tách ra thành trục
149
+ * riêng chứ không nghĩ mới: chúng đã chạy thật và đã đo. Vì sao cần tách — một
150
+ * dashboard theo bảng Solar vẫn có thể muốn biểu đồ đơn sắc để in đen trắng.
151
+ */
152
+ export type ChartId = 'theme' | 'blue' | 'amber' | 'violet' | 'teal' | 'neutral';
153
+ export interface ChartOption {
154
+ id: ChartId;
155
+ name: string;
156
+ description: string;
157
+ /**
158
+ * Ba màu xem trước — chuỗi 1, 3 và 5 của bộ ở chế độ SÁNG.
159
+ *
160
+ * `theme` không có: nó không phải một bộ màu mà là "để bảng màu quyết định",
161
+ * nên vẽ ba ô màu cho nó là hứa sai. Cùng cách `auto` của ô chọn bo góc.
162
+ */
163
+ swatches?: [string, string, string];
164
+ }
165
+ export declare const chartPalettes: readonly ChartOption[];
166
+ export declare function isChartId(value: unknown): value is ChartId;
167
+ /**
168
+ * Giá trị mặc định của mỗi trục. `hyperion` và `solid` KHÔNG có khối CSS nào
169
+ * (`[data-palette]` / `[data-surface]`), nên controller gỡ hẳn thuộc tính thay
170
+ * vì ghi giá trị — tránh khai một khối rỗng chỉ để không làm gì.
171
+ */
172
+ export declare const defaults: {
173
+ readonly colorMode: "system";
174
+ readonly palette: "hyperion";
175
+ readonly surface: "solid";
176
+ readonly style: "vega";
177
+ readonly chart: "theme";
178
+ readonly base: "slate";
179
+ readonly menuAccent: "subtle";
180
+ readonly menuColor: "default";
181
+ readonly menuAppearance: "solid";
182
+ };
183
+ /**
184
+ * Khoá localStorage. Mỗi trục một khoá riêng — đừng gộp vào một object JSON,
185
+ * cũng đừng bật `persist` của Pinia lên trên: hai bản ghi cùng một giá trị dưới
186
+ * hai khoá rồi sẽ trôi khỏi nhau và không biết bên nào đúng.
187
+ */
188
+ export declare const storageKeys: {
189
+ readonly colorMode: "hyperion-color-mode";
190
+ readonly palette: "hyperion-palette";
191
+ readonly surface: "hyperion-surface";
192
+ readonly style: "hyperion-style";
193
+ readonly chart: "hyperion-chart-palette";
194
+ readonly base: "hyperion-base";
195
+ readonly menuAccent: "hyperion-menu-accent";
196
+ readonly menuColor: "hyperion-menu-color";
197
+ readonly menuAppearance: "hyperion-menu-appearance";
198
+ };
199
+ /**
200
+ * Cách mỗi trục hiện diện trên `<html>`. CSS bám vào đúng những cái tên này,
201
+ * nên đổi ở đây là phải đổi cả trong `tokens.css` / `palettes.css` /
202
+ * `surfaces.css`.
203
+ */
204
+ export declare const domTargets: {
205
+ /** Chế độ tối là CLASS, không phải `data-*`: `.dark` lồng được vào một vùng. */
206
+ readonly darkClass: "dark";
207
+ /** Cặp với `.dark` — dùng để ép một vùng về theme sáng (trang docs cần). */
208
+ readonly lightClass: "light";
209
+ readonly paletteAttribute: "data-palette";
210
+ readonly surfaceAttribute: "data-surface";
211
+ /**
212
+ * Trục hình khối — nay là trục THỨ TƯ đầy đủ, ngang hàng ba cái trên: có
213
+ * `defaults.style`, có `storageKeys.style`, nằm trong `ThemeState`, và
214
+ * controller ghi nó lên `<html>`. Bản trước chỉ khai mỗi tên chuỗi ở đây vì
215
+ * chỗ dùng duy nhất là khung xem trước cục bộ của `/create`.
216
+ *
217
+ * Vẫn dùng được ở phạm vi CỤC BỘ: đặt `data-style` lên một khối con thì khai
218
+ * báo trực tiếp thắng giá trị thừa kế, đúng như `.light` ép một vùng về theme
219
+ * sáng cho bảng Tokens. Hai cách dùng không đụng nhau.
220
+ *
221
+ * Lưu ý cho ca cục bộ đó: `tokens.css` tính năm nấc `--radius-sm…2xl` bằng
222
+ * `calc()` từ `--radius`, mà `calc()` giải NGAY tại phần tử mang khai báo —
223
+ * nên selector khai năm nấc phải bao gồm `[data-style]`, nếu không một khối
224
+ * lồng đổi `--radius` sẽ im lặng không có tác dụng. Xem ghi chú tại chỗ trong
225
+ * `tokens.css`.
226
+ */
227
+ readonly styleAttribute: "data-style";
228
+ /** Trục màu biểu đồ. `charts.css` bám vào đúng chuỗi này. */
229
+ readonly chartAttribute: "data-chart";
230
+ /** Trục họ trung tính. `bases.css` bám vào đúng chuỗi này. */
231
+ readonly baseAttribute: "data-base";
232
+ /** Trục highlight của menu. `menus.css` bám vào đúng chuỗi này. */
233
+ readonly menuAccentAttribute: "data-menu-accent";
234
+ /** Trục màu mặt menu. `menus.css` bám vào đúng chuỗi này. */
235
+ readonly menuColorAttribute: "data-menu-color";
236
+ /** Trục vật liệu mặt menu. `menus.css` bám vào đúng chuỗi này. */
237
+ readonly menuAppearanceAttribute: "data-menu-appearance";
238
+ };
239
+ export interface ThemeState {
240
+ colorMode: ColorMode;
241
+ palette: PaletteId;
242
+ surface: SurfaceId;
243
+ style: StyleId;
244
+ chart: ChartId;
245
+ base: BaseId;
246
+ menuAccent: MenuAccentId;
247
+ menuColor: MenuColorId;
248
+ menuAppearance: MenuAppearanceId;
249
+ /** Chế độ tối đang có hiệu lực — đã giải `system` ra thật. */
250
+ isDark: boolean;
251
+ }
252
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}