@nanisoft/prism-ui 0.5.1 → 0.7.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/.tsbuildinfo +1 -1
- package/dist/blocks/cta-01/cta.d.ts +66 -6
- package/dist/blocks/cta-01/cta.d.ts.map +1 -1
- package/dist/blocks/cta-01/cta.js +8 -3
- package/dist/blocks/cta-01/index.d.ts +1 -0
- package/dist/blocks/cta-01/index.d.ts.map +1 -1
- package/dist/blocks/feature-grid-01/feature-grid.d.ts +57 -6
- package/dist/blocks/feature-grid-01/feature-grid.d.ts.map +1 -1
- package/dist/blocks/feature-grid-01/feature-grid.js +12 -2
- package/dist/blocks/feature-grid-01/index.d.ts +1 -0
- package/dist/blocks/feature-grid-01/index.d.ts.map +1 -1
- package/dist/blocks/hero-01/hero.d.ts +30 -1
- package/dist/blocks/hero-01/hero.d.ts.map +1 -1
- package/dist/blocks/hero-01/hero.js +14 -2
- package/dist/blocks/index.d.ts +10 -0
- package/dist/blocks/index.d.ts.map +1 -1
- package/dist/blocks/index.js +9 -0
- package/dist/blocks/instrument-panel-01/index.d.ts +3 -0
- package/dist/blocks/instrument-panel-01/index.d.ts.map +1 -0
- package/dist/blocks/instrument-panel-01/index.js +1 -0
- package/dist/blocks/instrument-panel-01/instrument-panel.d.ts +114 -0
- package/dist/blocks/instrument-panel-01/instrument-panel.d.ts.map +1 -0
- package/dist/blocks/instrument-panel-01/instrument-panel.js +64 -0
- package/dist/blocks/logo-strip-01/index.d.ts +3 -0
- package/dist/blocks/logo-strip-01/index.d.ts.map +1 -0
- package/dist/blocks/logo-strip-01/index.js +1 -0
- package/dist/blocks/logo-strip-01/logo-strip.d.ts +84 -0
- package/dist/blocks/logo-strip-01/logo-strip.d.ts.map +1 -0
- package/dist/blocks/logo-strip-01/logo-strip.js +40 -0
- package/dist/blocks/note-grid-01/index.d.ts +3 -0
- package/dist/blocks/note-grid-01/index.d.ts.map +1 -0
- package/dist/blocks/note-grid-01/index.js +1 -0
- package/dist/blocks/note-grid-01/note-grid.d.ts +79 -0
- package/dist/blocks/note-grid-01/note-grid.d.ts.map +1 -0
- package/dist/blocks/note-grid-01/note-grid.js +37 -0
- package/dist/blocks/pricing-01/pricing.js +1 -1
- package/dist/blocks/process-rail-01/index.d.ts +3 -0
- package/dist/blocks/process-rail-01/index.d.ts.map +1 -0
- package/dist/blocks/process-rail-01/index.js +1 -0
- package/dist/blocks/process-rail-01/process-rail.d.ts +99 -0
- package/dist/blocks/process-rail-01/process-rail.d.ts.map +1 -0
- package/dist/blocks/process-rail-01/process-rail.js +58 -0
- package/dist/blocks/product-grid-01/index.d.ts +3 -0
- package/dist/blocks/product-grid-01/index.d.ts.map +1 -0
- package/dist/blocks/product-grid-01/index.js +1 -0
- package/dist/blocks/product-grid-01/product-grid.d.ts +114 -0
- package/dist/blocks/product-grid-01/product-grid.d.ts.map +1 -0
- package/dist/blocks/product-grid-01/product-grid.js +51 -0
- package/dist/blocks/site-footer/index.d.ts +3 -0
- package/dist/blocks/site-footer/index.d.ts.map +1 -0
- package/dist/blocks/site-footer/index.js +1 -0
- package/dist/blocks/site-footer/site-footer.d.ts +135 -0
- package/dist/blocks/site-footer/site-footer.d.ts.map +1 -0
- package/dist/blocks/site-footer/site-footer.js +41 -0
- package/dist/blocks/site-header/index.d.ts +3 -0
- package/dist/blocks/site-header/index.d.ts.map +1 -0
- package/dist/blocks/site-header/index.js +1 -0
- package/dist/blocks/site-header/site-header.d.ts +142 -0
- package/dist/blocks/site-header/site-header.d.ts.map +1 -0
- package/dist/blocks/site-header/site-header.js +46 -0
- package/dist/blocks/stack-grid-01/index.d.ts +3 -0
- package/dist/blocks/stack-grid-01/index.d.ts.map +1 -0
- package/dist/blocks/stack-grid-01/index.js +1 -0
- package/dist/blocks/stack-grid-01/stack-grid.d.ts +118 -0
- package/dist/blocks/stack-grid-01/stack-grid.d.ts.map +1 -0
- package/dist/blocks/stack-grid-01/stack-grid.js +49 -0
- package/dist/blocks/status-ledger-01/index.d.ts +3 -0
- package/dist/blocks/status-ledger-01/index.d.ts.map +1 -0
- package/dist/blocks/status-ledger-01/index.js +1 -0
- package/dist/blocks/status-ledger-01/status-ledger.d.ts +131 -0
- package/dist/blocks/status-ledger-01/status-ledger.d.ts.map +1 -0
- package/dist/blocks/status-ledger-01/status-ledger.js +80 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +180 -0
- package/dist/components/index.d.ts +11 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +6 -0
- package/dist/components/ui/card.d.ts +25 -0
- package/dist/components/ui/card.d.ts.map +1 -1
- package/dist/components/ui/card.js +25 -0
- package/dist/components/ui/cta-link.d.ts +45 -0
- package/dist/components/ui/cta-link.d.ts.map +1 -0
- package/dist/components/ui/cta-link.js +81 -0
- package/dist/components/ui/diagram.d.ts +154 -0
- package/dist/components/ui/diagram.d.ts.map +1 -0
- package/dist/components/ui/diagram.js +150 -0
- package/dist/components/ui/fact-list.d.ts +90 -0
- package/dist/components/ui/fact-list.d.ts.map +1 -0
- package/dist/components/ui/fact-list.js +38 -0
- package/dist/components/ui/product-mark.d.ts +115 -0
- package/dist/components/ui/product-mark.d.ts.map +1 -0
- package/dist/components/ui/product-mark.js +82 -0
- package/dist/components/ui/product-switcher.d.ts +108 -0
- package/dist/components/ui/product-switcher.d.ts.map +1 -0
- package/dist/components/ui/product-switcher.js +47 -0
- package/dist/components/ui/prose.d.ts +88 -0
- package/dist/components/ui/prose.d.ts.map +1 -0
- package/dist/components/ui/prose.js +53 -0
- package/dist/components/ui/section.d.ts +24 -1
- package/dist/components/ui/section.d.ts.map +1 -1
- package/dist/components/ui/section.js +11 -2
- package/dist/components/ui/slider.d.ts.map +1 -1
- package/dist/components/ui/slider.js +7 -1
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -0
- package/dist/pages/blog-post-page/index.d.ts +174 -0
- package/dist/pages/blog-post-page/index.d.ts.map +1 -0
- package/dist/pages/blog-post-page/index.js +49 -0
- package/dist/pages/docs-shell/docs-shell.d.ts +250 -0
- package/dist/pages/docs-shell/docs-shell.d.ts.map +1 -0
- package/dist/pages/docs-shell/docs-shell.js +197 -0
- package/dist/pages/docs-shell/index.d.ts +3 -0
- package/dist/pages/docs-shell/index.d.ts.map +1 -0
- package/dist/pages/docs-shell/index.js +1 -0
- package/dist/pages/index.d.ts +13 -2
- package/dist/pages/index.d.ts.map +1 -1
- package/dist/pages/index.js +10 -2
- package/dist/pages/not-found-page/index.d.ts +112 -0
- package/dist/pages/not-found-page/index.d.ts.map +1 -0
- package/dist/pages/not-found-page/index.js +46 -0
- package/dist/provider/provider.d.ts +5 -0
- package/dist/provider/provider.d.ts.map +1 -1
- package/dist/provider/provider.js +129 -38
- package/dist/provider/theme-script.d.ts +41 -3
- package/dist/provider/theme-script.d.ts.map +1 -1
- package/dist/provider/theme-script.js +68 -17
- package/dist/styles.css +555 -12
- package/dist/theming/index.d.ts +132 -2
- package/dist/theming/index.d.ts.map +1 -1
- package/dist/theming/index.js +127 -1
- package/package.json +14 -4
package/dist/theming/index.d.ts
CHANGED
|
@@ -14,6 +14,57 @@ export declare const MODES: readonly ["light", "dark"];
|
|
|
14
14
|
export type Mode = (typeof MODES)[number];
|
|
15
15
|
export declare const PACK_ATTRIBUTE = "data-pack";
|
|
16
16
|
export declare const DEFAULT_STORAGE_KEY = "prism-theme";
|
|
17
|
+
/**
|
|
18
|
+
* The root attribute that records where the active pack and mode came from.
|
|
19
|
+
*
|
|
20
|
+
* This is a contract, not markup. The boot script is its only writer, and the
|
|
21
|
+
* provider never touches it, because two writers would make the recorded origin
|
|
22
|
+
* a race rather than a record. The value is always one of `THEME_ORIGINS` and is
|
|
23
|
+
* written on every path the script reaches, including a stored value that could
|
|
24
|
+
* not be parsed: an absent attribute cannot be told from an unread one, and a
|
|
25
|
+
* theme that fell through to the default is exactly the case a reader needs to
|
|
26
|
+
* see named.
|
|
27
|
+
*
|
|
28
|
+
* It is not `data-theme`, which `MIGRATION.md` retires. It carries the
|
|
29
|
+
* provenance of a resolution, never a pack.
|
|
30
|
+
*/
|
|
31
|
+
export declare const THEME_ORIGIN_ATTRIBUTE = "data-theme-origin";
|
|
32
|
+
/**
|
|
33
|
+
* The closed set the boot script may write to `THEME_ORIGIN_ATTRIBUTE`.
|
|
34
|
+
*
|
|
35
|
+
* - `stored` a valid `{ pack, mode }` pair was in the key this line writes.
|
|
36
|
+
* - `legacy` the key was empty and a key this line no longer writes held a
|
|
37
|
+
* recoverable mode, so that decision was taken and carried over.
|
|
38
|
+
* - `unparsed` the key held a value that is not a pair. The theme fell
|
|
39
|
+
* through whole, and the value was left in place, because it is
|
|
40
|
+
* the only record that this reader ever chose anything.
|
|
41
|
+
* - `document` the key was empty and the root element's own attributes
|
|
42
|
+
* supplied the theme.
|
|
43
|
+
* - `default` neither did, so the consumer's own defaults apply.
|
|
44
|
+
*
|
|
45
|
+
* `legacy` and `unparsed` are why the set is five and not three: a
|
|
46
|
+
* three-value set records that the theme came from somewhere but cannot
|
|
47
|
+
* distinguish "never chose" from "chose, and the value no longer parses", which
|
|
48
|
+
* is the one distinction a storage migration has to be retired against.
|
|
49
|
+
*/
|
|
50
|
+
export declare const THEME_ORIGINS: readonly ["stored", "legacy", "document", "default", "unparsed"];
|
|
51
|
+
export type ThemeOrigin = (typeof THEME_ORIGINS)[number];
|
|
52
|
+
/**
|
|
53
|
+
* Keys earlier lines of this package wrote and this line does not.
|
|
54
|
+
*
|
|
55
|
+
* `prism-theme-mode` was the shared chrome key: the mode setter wrote it, and
|
|
56
|
+
* only the mode setter, as a bare `'light'` or `'dark'` string, because the pack
|
|
57
|
+
* was fixed per site and the mode was the one choice that travelled across
|
|
58
|
+
* sites. The value is not a `{ pack, mode }` pair and can never collide with one
|
|
59
|
+
* this line writes, so reading it costs nothing and recovers a real decision.
|
|
60
|
+
*
|
|
61
|
+
* The list is the migration's own expiry. Every key in it is a clause the boot
|
|
62
|
+
* script carries and prices, and the migration is retired by deleting the last
|
|
63
|
+
* entry: the clause's live population is then empty, the gate reports it, and
|
|
64
|
+
* the byte ceiling's generation allowance falls to zero with it. Nothing here
|
|
65
|
+
* is bounded by a date or a version number.
|
|
66
|
+
*/
|
|
67
|
+
export declare const LEGACY_MODE_STORAGE_KEYS: readonly ["prism-theme-mode"];
|
|
17
68
|
/**
|
|
18
69
|
* Reads a persisted `{ pack, mode }` object.
|
|
19
70
|
*
|
|
@@ -27,15 +78,94 @@ export declare function parseStoredTheme(raw: string | null): {
|
|
|
27
78
|
mode: Mode;
|
|
28
79
|
} | null;
|
|
29
80
|
/**
|
|
30
|
-
*
|
|
81
|
+
* What `resolveTheme` was given, and nothing else.
|
|
82
|
+
*
|
|
83
|
+
* The three readers are all the same question asked of different state: what
|
|
84
|
+
* does this reader believe, what has the server rendered, and what is the
|
|
85
|
+
* consumer's own default. `stored` and `legacy` are raw strings exactly as the
|
|
86
|
+
* store holds them, so a corrupt value is visible to the rule rather than
|
|
87
|
+
* normalised away by a caller.
|
|
88
|
+
*/
|
|
89
|
+
export type ThemeResolutionInput = {
|
|
90
|
+
/** Raw contents of the key this line writes, or `null` when it is absent. */
|
|
91
|
+
stored: string | null;
|
|
92
|
+
/** Raw contents of one key this line no longer writes, or `null`. */
|
|
93
|
+
legacy: string | null;
|
|
94
|
+
/** `data-pack` on the root element as rendered, valid or not. */
|
|
95
|
+
documentPack: string | null;
|
|
96
|
+
/** Whether the root element carries `.dark` as rendered. */
|
|
97
|
+
documentDark: boolean;
|
|
98
|
+
defaultPack: PackId;
|
|
99
|
+
defaultMode: Mode;
|
|
100
|
+
};
|
|
101
|
+
export type ThemeResolution = {
|
|
102
|
+
pack: PackId;
|
|
103
|
+
mode: Mode;
|
|
104
|
+
/** Which source named the pair, for `THEME_ORIGIN_ATTRIBUTE`. */
|
|
105
|
+
origin: ThemeOrigin;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* The one resolution rule. `PrismProvider` calls it, and the boot script
|
|
109
|
+
* implements it as a string, and the equivalence gate runs both over one table
|
|
110
|
+
* because the string cannot import it.
|
|
111
|
+
*
|
|
112
|
+
* A serialised function is not a way to share it. The build minifies, a renamed
|
|
113
|
+
* identifier inside the script's own `try` would throw there and the catch
|
|
114
|
+
* would fail open, leaving a silent no-op on every page; so the honest shape is
|
|
115
|
+
* one implementation plus a gate that can fail, not two copies that look
|
|
116
|
+
* aligned.
|
|
117
|
+
*
|
|
118
|
+
* The order, and why each step is where it is:
|
|
119
|
+
*
|
|
120
|
+
* 1. A valid pair in the key this line writes wins outright. A decision
|
|
121
|
+
* recorded as a pair is a decision, and it is the only source that names
|
|
122
|
+
* both axes at once.
|
|
123
|
+
* 2. A value that is present but is not a pair falls through WHOLE. It is not
|
|
124
|
+
* repaired field by field, because a half-applied pair is a theme neither
|
|
125
|
+
* the reader nor the server chose, and because repairing it would make the
|
|
126
|
+
* two readers disagree about what "a valid mode" means. The value is also
|
|
127
|
+
* not cleared: it is the only record that this reader ever chose, and the
|
|
128
|
+
* origin is `unparsed` so a reader can see that it is there and unusable.
|
|
129
|
+
* 3. Only an absent key reaches the keys this line no longer writes. A present
|
|
130
|
+
* but unusable value is a record of an intent and outranks an older one.
|
|
131
|
+
* 4. The root element's own attributes, which is what a server rendered and
|
|
132
|
+
* what must survive hydration rather than flash to the default.
|
|
133
|
+
* 5. The consumer's defaults, which is the site's decision, not the reader's.
|
|
134
|
+
*
|
|
135
|
+
* Every step names its own source, so the pack and the mode always come from
|
|
136
|
+
* the same one. That is the whole-vs-half property, and it is structural rather
|
|
137
|
+
* than a check.
|
|
138
|
+
*/
|
|
139
|
+
export declare function resolveTheme({ stored, legacy, documentPack, documentDark, defaultPack, defaultMode, }: ThemeResolutionInput): ThemeResolution;
|
|
140
|
+
/**
|
|
141
|
+
* The first key in `LEGACY_MODE_STORAGE_KEYS` that holds a recoverable mode.
|
|
142
|
+
*
|
|
143
|
+
* Returned with the key that held it, because the recovery has to retire that
|
|
144
|
+
* key and no other. Order is the list's order, and the list is short enough
|
|
145
|
+
* that the loop is not worth a comment about its cost.
|
|
146
|
+
*/
|
|
147
|
+
export declare function readLegacyMode(read: (key: string) => string | null): {
|
|
148
|
+
key: string;
|
|
149
|
+
mode: Mode;
|
|
150
|
+
} | null;
|
|
151
|
+
/**
|
|
152
|
+
* Turns a pack and a mode into the markup attributes that express them.
|
|
31
153
|
*
|
|
32
154
|
* Returns attributes, never CSS values: a Server Component spreads the result
|
|
33
155
|
* onto `<html>` and gets the declarative form with no client runtime. `default`
|
|
34
156
|
* is expressed by omitting `data-pack`; light is expressed by omitting `dark`.
|
|
157
|
+
*
|
|
158
|
+
* `mode` is optional because a server cannot know the reader's mode, and a
|
|
159
|
+
* required one is that impossibility written into the type: the only way to ask
|
|
160
|
+
* for a boundary with no mode class of its own would be to pass `'light'` as a
|
|
161
|
+
* guess, and the guess is wrong for half of them. Omitting it is the honest
|
|
162
|
+
* spelling of "wear the mode of the element carrying `.dark`", which is what the
|
|
163
|
+
* token build's descendant selector implements. `pack` stays required, because an
|
|
164
|
+
* element carrying neither axis is not a theme boundary.
|
|
35
165
|
*/
|
|
36
166
|
export declare function themeAttributes({ pack, mode, }: {
|
|
37
167
|
pack: PackId;
|
|
38
|
-
mode
|
|
168
|
+
mode?: Mode;
|
|
39
169
|
}): {
|
|
40
170
|
'data-pack'?: string;
|
|
41
171
|
className?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theming/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,KAAK,mEAAoE,CAAA;AACtF,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,CAAA;AAE3C,eAAO,MAAM,KAAK,4BAA6B,CAAA;AAC/C,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,CAAA;AAEzC,eAAO,MAAM,cAAc,cAAc,CAAA;AACzC,eAAO,MAAM,mBAAmB,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theming/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,KAAK,mEAAoE,CAAA;AACtF,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,CAAA;AAE3C,eAAO,MAAM,KAAK,4BAA6B,CAAA;AAC/C,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,CAAA;AAEzC,eAAO,MAAM,cAAc,cAAc,CAAA;AACzC,eAAO,MAAM,mBAAmB,gBAAgB,CAAA;AAEhD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,sBAAsB,sBAAsB,CAAA;AAEzD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,aAAa,kEAAmE,CAAA;AAC7F,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,wBAAwB,+BAAgC,CAAA;AAUrE;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,CAgBxF;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,6EAA6E;IAC7E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,qEAAqE;IACrE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,iEAAiE;IACjE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,4DAA4D;IAC5D,YAAY,EAAE,OAAO,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,IAAI,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,IAAI,CAAA;IACV,iEAAiE;IACjE,MAAM,EAAE,WAAW,CAAA;CACpB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,GACZ,EAAE,oBAAoB,GAAG,eAAe,CAoBxC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GACnC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GAAG,IAAI,CAMpC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,IAAI,GACL,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,IAAI,CAAA;CACZ,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAK/C"}
|
package/dist/theming/index.js
CHANGED
|
@@ -12,6 +12,56 @@ export const PACKS = ['default', 'blush', 'mint', 'lavender', 'sky', 'peach'];
|
|
|
12
12
|
export const MODES = ['light', 'dark'];
|
|
13
13
|
export const PACK_ATTRIBUTE = 'data-pack';
|
|
14
14
|
export const DEFAULT_STORAGE_KEY = 'prism-theme';
|
|
15
|
+
/**
|
|
16
|
+
* The root attribute that records where the active pack and mode came from.
|
|
17
|
+
*
|
|
18
|
+
* This is a contract, not markup. The boot script is its only writer, and the
|
|
19
|
+
* provider never touches it, because two writers would make the recorded origin
|
|
20
|
+
* a race rather than a record. The value is always one of `THEME_ORIGINS` and is
|
|
21
|
+
* written on every path the script reaches, including a stored value that could
|
|
22
|
+
* not be parsed: an absent attribute cannot be told from an unread one, and a
|
|
23
|
+
* theme that fell through to the default is exactly the case a reader needs to
|
|
24
|
+
* see named.
|
|
25
|
+
*
|
|
26
|
+
* It is not `data-theme`, which `MIGRATION.md` retires. It carries the
|
|
27
|
+
* provenance of a resolution, never a pack.
|
|
28
|
+
*/
|
|
29
|
+
export const THEME_ORIGIN_ATTRIBUTE = 'data-theme-origin';
|
|
30
|
+
/**
|
|
31
|
+
* The closed set the boot script may write to `THEME_ORIGIN_ATTRIBUTE`.
|
|
32
|
+
*
|
|
33
|
+
* - `stored` a valid `{ pack, mode }` pair was in the key this line writes.
|
|
34
|
+
* - `legacy` the key was empty and a key this line no longer writes held a
|
|
35
|
+
* recoverable mode, so that decision was taken and carried over.
|
|
36
|
+
* - `unparsed` the key held a value that is not a pair. The theme fell
|
|
37
|
+
* through whole, and the value was left in place, because it is
|
|
38
|
+
* the only record that this reader ever chose anything.
|
|
39
|
+
* - `document` the key was empty and the root element's own attributes
|
|
40
|
+
* supplied the theme.
|
|
41
|
+
* - `default` neither did, so the consumer's own defaults apply.
|
|
42
|
+
*
|
|
43
|
+
* `legacy` and `unparsed` are why the set is five and not three: a
|
|
44
|
+
* three-value set records that the theme came from somewhere but cannot
|
|
45
|
+
* distinguish "never chose" from "chose, and the value no longer parses", which
|
|
46
|
+
* is the one distinction a storage migration has to be retired against.
|
|
47
|
+
*/
|
|
48
|
+
export const THEME_ORIGINS = ['stored', 'legacy', 'document', 'default', 'unparsed'];
|
|
49
|
+
/**
|
|
50
|
+
* Keys earlier lines of this package wrote and this line does not.
|
|
51
|
+
*
|
|
52
|
+
* `prism-theme-mode` was the shared chrome key: the mode setter wrote it, and
|
|
53
|
+
* only the mode setter, as a bare `'light'` or `'dark'` string, because the pack
|
|
54
|
+
* was fixed per site and the mode was the one choice that travelled across
|
|
55
|
+
* sites. The value is not a `{ pack, mode }` pair and can never collide with one
|
|
56
|
+
* this line writes, so reading it costs nothing and recovers a real decision.
|
|
57
|
+
*
|
|
58
|
+
* The list is the migration's own expiry. Every key in it is a clause the boot
|
|
59
|
+
* script carries and prices, and the migration is retired by deleting the last
|
|
60
|
+
* entry: the clause's live population is then empty, the gate reports it, and
|
|
61
|
+
* the byte ceiling's generation allowance falls to zero with it. Nothing here
|
|
62
|
+
* is bounded by a date or a version number.
|
|
63
|
+
*/
|
|
64
|
+
export const LEGACY_MODE_STORAGE_KEYS = ['prism-theme-mode'];
|
|
15
65
|
function isPack(value) {
|
|
16
66
|
return typeof value === 'string' && PACKS.includes(value);
|
|
17
67
|
}
|
|
@@ -44,11 +94,87 @@ export function parseStoredTheme(raw) {
|
|
|
44
94
|
return { pack, mode };
|
|
45
95
|
}
|
|
46
96
|
/**
|
|
47
|
-
*
|
|
97
|
+
* The one resolution rule. `PrismProvider` calls it, and the boot script
|
|
98
|
+
* implements it as a string, and the equivalence gate runs both over one table
|
|
99
|
+
* because the string cannot import it.
|
|
100
|
+
*
|
|
101
|
+
* A serialised function is not a way to share it. The build minifies, a renamed
|
|
102
|
+
* identifier inside the script's own `try` would throw there and the catch
|
|
103
|
+
* would fail open, leaving a silent no-op on every page; so the honest shape is
|
|
104
|
+
* one implementation plus a gate that can fail, not two copies that look
|
|
105
|
+
* aligned.
|
|
106
|
+
*
|
|
107
|
+
* The order, and why each step is where it is:
|
|
108
|
+
*
|
|
109
|
+
* 1. A valid pair in the key this line writes wins outright. A decision
|
|
110
|
+
* recorded as a pair is a decision, and it is the only source that names
|
|
111
|
+
* both axes at once.
|
|
112
|
+
* 2. A value that is present but is not a pair falls through WHOLE. It is not
|
|
113
|
+
* repaired field by field, because a half-applied pair is a theme neither
|
|
114
|
+
* the reader nor the server chose, and because repairing it would make the
|
|
115
|
+
* two readers disagree about what "a valid mode" means. The value is also
|
|
116
|
+
* not cleared: it is the only record that this reader ever chose, and the
|
|
117
|
+
* origin is `unparsed` so a reader can see that it is there and unusable.
|
|
118
|
+
* 3. Only an absent key reaches the keys this line no longer writes. A present
|
|
119
|
+
* but unusable value is a record of an intent and outranks an older one.
|
|
120
|
+
* 4. The root element's own attributes, which is what a server rendered and
|
|
121
|
+
* what must survive hydration rather than flash to the default.
|
|
122
|
+
* 5. The consumer's defaults, which is the site's decision, not the reader's.
|
|
123
|
+
*
|
|
124
|
+
* Every step names its own source, so the pack and the mode always come from
|
|
125
|
+
* the same one. That is the whole-vs-half property, and it is structural rather
|
|
126
|
+
* than a check.
|
|
127
|
+
*/
|
|
128
|
+
export function resolveTheme({ stored, legacy, documentPack, documentDark, defaultPack, defaultMode, }) {
|
|
129
|
+
const pair = parseStoredTheme(stored);
|
|
130
|
+
if (pair)
|
|
131
|
+
return { pack: pair.pack, mode: pair.mode, origin: 'stored' };
|
|
132
|
+
const renderedPack = isPack(documentPack) ? documentPack : null;
|
|
133
|
+
const renderedMode = documentDark ? 'dark' : null;
|
|
134
|
+
const fromDocument = () => ({
|
|
135
|
+
pack: renderedPack ?? defaultPack,
|
|
136
|
+
mode: renderedMode ?? defaultMode,
|
|
137
|
+
origin: 'document',
|
|
138
|
+
});
|
|
139
|
+
// A value the store holds with content, and `parseStoredTheme` did not accept.
|
|
140
|
+
const held = stored !== null && stored !== '';
|
|
141
|
+
if (held)
|
|
142
|
+
return { ...fromDocument(), origin: 'unparsed' };
|
|
143
|
+
if (isMode(legacy))
|
|
144
|
+
return { pack: defaultPack, mode: legacy, origin: 'legacy' };
|
|
145
|
+
if (renderedPack !== null || renderedMode !== null)
|
|
146
|
+
return fromDocument();
|
|
147
|
+
return { pack: defaultPack, mode: defaultMode, origin: 'default' };
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The first key in `LEGACY_MODE_STORAGE_KEYS` that holds a recoverable mode.
|
|
151
|
+
*
|
|
152
|
+
* Returned with the key that held it, because the recovery has to retire that
|
|
153
|
+
* key and no other. Order is the list's order, and the list is short enough
|
|
154
|
+
* that the loop is not worth a comment about its cost.
|
|
155
|
+
*/
|
|
156
|
+
export function readLegacyMode(read) {
|
|
157
|
+
for (const key of LEGACY_MODE_STORAGE_KEYS) {
|
|
158
|
+
const value = read(key);
|
|
159
|
+
if (isMode(value))
|
|
160
|
+
return { key, mode: value };
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Turns a pack and a mode into the markup attributes that express them.
|
|
48
166
|
*
|
|
49
167
|
* Returns attributes, never CSS values: a Server Component spreads the result
|
|
50
168
|
* onto `<html>` and gets the declarative form with no client runtime. `default`
|
|
51
169
|
* is expressed by omitting `data-pack`; light is expressed by omitting `dark`.
|
|
170
|
+
*
|
|
171
|
+
* `mode` is optional because a server cannot know the reader's mode, and a
|
|
172
|
+
* required one is that impossibility written into the type: the only way to ask
|
|
173
|
+
* for a boundary with no mode class of its own would be to pass `'light'` as a
|
|
174
|
+
* guess, and the guess is wrong for half of them. Omitting it is the honest
|
|
175
|
+
* spelling of "wear the mode of the element carrying `.dark`", which is what the
|
|
176
|
+
* token build's descendant selector implements. `pack` stays required, because an
|
|
177
|
+
* element carrying neither axis is not a theme boundary.
|
|
52
178
|
*/
|
|
53
179
|
export function themeAttributes({ pack, mode, }) {
|
|
54
180
|
const attributes = {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nanisoft/prism-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Prism's React component, block and page library.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"clsx": "^2.1.1",
|
|
76
76
|
"lucide-react": "^0.545.0",
|
|
77
77
|
"tailwind-merge": "^3.3.1",
|
|
78
|
-
"@nanisoft/prism-tokens": "0.
|
|
78
|
+
"@nanisoft/prism-tokens": "0.6.0"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@tailwindcss/postcss": "^4.3.3",
|
|
@@ -100,9 +100,19 @@
|
|
|
100
100
|
"scripts": {
|
|
101
101
|
"sync": "node scripts/sync-registry.mjs",
|
|
102
102
|
"validate": "node scripts/validate-registry.mjs",
|
|
103
|
-
"build": "node scripts/build.mjs && pnpm sync && pnpm validate && shadcn build && node scripts/check-surface.mjs",
|
|
104
|
-
"check": "node scripts/validate-registry.mjs && node scripts/check-surface.mjs && node scripts/check-client-budget.mjs",
|
|
103
|
+
"build": "node scripts/build.mjs && pnpm sync && pnpm validate && node scripts/check-catalogue.mjs && shadcn build && node scripts/check-surface.mjs && node scripts/check-focus-indicators.mjs && node scripts/check-item-docs.mjs && node scripts/check-block-copy.mjs && node scripts/check-item-category.mjs && node scripts/check-block-imports.mjs",
|
|
104
|
+
"check": "node scripts/validate-registry.mjs && node scripts/check-catalogue.mjs && node scripts/check-surface.mjs && node scripts/check-focus-indicators.mjs && node scripts/check-pack-boundary.mjs && node scripts/check-vector-ink.mjs && node scripts/check-client-budget.mjs && node scripts/check-theme-resolution.mjs && node scripts/check-boot-budget.mjs && node scripts/check-item-docs.mjs && node scripts/check-block-copy.mjs && node scripts/check-item-category.mjs && node scripts/check-block-imports.mjs",
|
|
105
|
+
"check:vector-ink": "node scripts/check-vector-ink.mjs",
|
|
105
106
|
"check:client-budget": "node scripts/check-client-budget.mjs",
|
|
107
|
+
"check:pack-boundary": "node scripts/check-pack-boundary.mjs",
|
|
108
|
+
"check:theme-resolution": "node scripts/check-theme-resolution.mjs",
|
|
109
|
+
"check:boot-budget": "node scripts/check-boot-budget.mjs",
|
|
110
|
+
"check:catalogue": "node scripts/check-catalogue.mjs",
|
|
111
|
+
"check:focus-indicators": "node scripts/check-focus-indicators.mjs",
|
|
112
|
+
"check:item-docs": "node scripts/check-item-docs.mjs",
|
|
113
|
+
"check:block-copy": "node scripts/check-block-copy.mjs",
|
|
114
|
+
"check:item-category": "node scripts/check-item-category.mjs",
|
|
115
|
+
"check:block-imports": "node scripts/check-block-imports.mjs",
|
|
106
116
|
"test": "vitest run",
|
|
107
117
|
"typecheck": "tsc --noEmit"
|
|
108
118
|
}
|