@multiplatform.one/theme 6.4.2 → 6.6.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/package.json +5 -5
- package/src/dates.spec.ts +158 -1
- package/src/dates.ts +37 -0
- package/src/devWarn.ts +36 -0
- package/src/numbers.spec.ts +112 -0
- package/src/numbers.ts +26 -8
- package/src/theme/cookies.spec.ts +84 -0
- package/src/theme/cookies.ts +61 -13
- package/src/theme/index.ts +1 -0
- package/src/theme/radiusClass.ts +51 -0
- package/src/theme/readableColor.spec.ts +115 -0
- package/src/theme/readableColor.ts +51 -30
- package/src/theme/resolveKnobs.spec.ts +46 -2
- package/types/dates.d.ts +82 -2
- package/types/dates.d.ts.map +1 -1
- package/types/devWarn.d.ts +35 -0
- package/types/devWarn.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/numbers.d.ts +74 -0
- package/types/numbers.d.ts.map +1 -0
- package/types/theme/colorRules.d.ts +1 -1
- package/types/theme/cookies.d.ts +18 -4
- package/types/theme/cookies.d.ts.map +1 -1
- package/types/theme/defaults/fonts.d.ts +2 -2
- package/types/theme/index.d.ts +1 -0
- package/types/theme/index.d.ts.map +1 -1
- package/types/theme/knobs.d.ts +23 -0
- package/types/theme/knobs.d.ts.map +1 -1
- package/types/theme/presets.d.ts +15 -0
- package/types/theme/presets.d.ts.map +1 -1
- package/types/theme/radiusClass.d.ts +44 -0
- package/types/theme/radiusClass.d.ts.map +1 -0
- package/types/theme/readableColor.d.ts +18 -6
- package/types/theme/readableColor.d.ts.map +1 -1
- package/types/theme/recipes.d.ts +10 -1
- package/types/theme/recipes.d.ts.map +1 -1
- package/types/theme/resolveKnobs.d.ts +12 -1
- package/types/theme/resolveKnobs.d.ts.map +1 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Radius-class declarations (D-09 / LC-60).
|
|
3
|
+
*
|
|
4
|
+
* Most parts prove they obey the radius knob by simply going square at
|
|
5
|
+
* `borderRadius:none`. A few legitimately do not — an ornamental dot has no
|
|
6
|
+
* arc for the knob to move (R-PILL), and an avatar's circle is the object's
|
|
7
|
+
* identity rather than a style (R-IDENTITY). Those parts must SAY SO on the
|
|
8
|
+
* node, because the alternative — a probe that skips anything that looks
|
|
9
|
+
* round — silently exempts real KNOB-TOTALITY defects (LC-18).
|
|
10
|
+
*
|
|
11
|
+
* The declaration is only half the contract: the `radius:none` sweep
|
|
12
|
+
* validates it against the registry GENERATED from the spec's radius-class
|
|
13
|
+
* table (`scripts/radius-identity-registry.mjs`), so a class this file cannot
|
|
14
|
+
* spell, or an R-IDENTITY part the spec never adjudicated, still fails. This
|
|
15
|
+
* module is the writing end; `docs/theme-propagation-spec.md` is the registry.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The radius classes whose parts stay round at `borderRadius:none`.
|
|
20
|
+
*
|
|
21
|
+
* - `R-PILL` — a pill/circle at every radius value (ornamental dots, badge
|
|
22
|
+
* indicators, icon wells). Size still tracks the size knob.
|
|
23
|
+
* - `R-IDENTITY` — the shape IS the part's identity (Avatar, brand marks).
|
|
24
|
+
* Membership is enumerated in the spec table and enforced per part.
|
|
25
|
+
*/
|
|
26
|
+
export type KnobImmuneRadiusClass = "R-PILL" | "R-IDENTITY";
|
|
27
|
+
|
|
28
|
+
export interface RadiusClassDeclaration {
|
|
29
|
+
"data-radius-class": KnobImmuneRadiusClass;
|
|
30
|
+
"data-radius-part": string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Declare a knob-immune shape so the `radius:none` sweep can license it.
|
|
35
|
+
*
|
|
36
|
+
* Spread onto the outermost node of the shape — a declaration covers its own
|
|
37
|
+
* anatomy, so inner painted parts (an avatar's image/fallback) inherit it.
|
|
38
|
+
*
|
|
39
|
+
* @param radiusClass the class the spec's Radius table assigns the part
|
|
40
|
+
* @param part the part name as the spec writes it (the R-IDENTITY registry
|
|
41
|
+
* is matched by this name)
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* <Frame {...radiusClassProps("R-IDENTITY", "Avatar")} circular />
|
|
45
|
+
*/
|
|
46
|
+
export function radiusClassProps(
|
|
47
|
+
radiusClass: KnobImmuneRadiusClass,
|
|
48
|
+
part: string,
|
|
49
|
+
): RadiusClassDeclaration {
|
|
50
|
+
return { "data-radius-class": radiusClass, "data-radius-part": part };
|
|
51
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { resolveAccentTintedSurface } from "./readableColor";
|
|
3
|
+
import { contrastRatio, normalizeToHex, relativeLuminance } from "./colorRules";
|
|
4
|
+
|
|
5
|
+
// The stock accent ramp (defaults/accent.ts) as the theme resolves it.
|
|
6
|
+
const lightAccent = [
|
|
7
|
+
"hsla(250, 50%, 62%, 1)",
|
|
8
|
+
"hsla(250, 50%, 58%, 1)",
|
|
9
|
+
"hsla(250, 50%, 54%, 1)",
|
|
10
|
+
"hsla(250, 50%, 48%, 1)",
|
|
11
|
+
"hsla(250, 50%, 46%, 1)",
|
|
12
|
+
"hsla(250, 50%, 44%, 1)",
|
|
13
|
+
"hsla(250, 50%, 42%, 1)",
|
|
14
|
+
"hsla(250, 50%, 40%, 1)",
|
|
15
|
+
"hsla(250, 50%, 38%, 1)",
|
|
16
|
+
"hsla(250, 50%, 36%, 1)",
|
|
17
|
+
"hsla(250, 50%, 95%, 1)",
|
|
18
|
+
"hsla(250, 50%, 98%, 1)",
|
|
19
|
+
];
|
|
20
|
+
const darkAccent = [
|
|
21
|
+
"hsla(250, 50%, 35%, 1)",
|
|
22
|
+
"hsla(250, 50%, 38%, 1)",
|
|
23
|
+
"hsla(250, 50%, 41%, 1)",
|
|
24
|
+
"hsla(250, 50%, 43%, 1)",
|
|
25
|
+
"hsla(250, 50%, 46%, 1)",
|
|
26
|
+
"hsla(250, 50%, 49%, 1)",
|
|
27
|
+
"hsla(250, 50%, 52%, 1)",
|
|
28
|
+
"hsla(250, 50%, 54%, 1)",
|
|
29
|
+
"hsla(250, 50%, 57%, 1)",
|
|
30
|
+
"hsla(250, 50%, 60%, 1)",
|
|
31
|
+
"hsla(250, 50%, 90%, 1)",
|
|
32
|
+
"hsla(250, 50%, 95%, 1)",
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const lightPaper = "#ffffff";
|
|
36
|
+
const lightInk = "#242226";
|
|
37
|
+
const darkPaper = "#161519";
|
|
38
|
+
const darkInk = "#f0eff1";
|
|
39
|
+
|
|
40
|
+
const lum = (raw: string) => relativeLuminance(normalizeToHex(raw)!);
|
|
41
|
+
|
|
42
|
+
describe("resolveAccentTintedSurface", () => {
|
|
43
|
+
it("takes the ramp's pale surface end in a light scheme", () => {
|
|
44
|
+
const tint = resolveAccentTintedSurface({
|
|
45
|
+
steps: lightAccent,
|
|
46
|
+
paper: lightPaper,
|
|
47
|
+
ink: lightInk,
|
|
48
|
+
});
|
|
49
|
+
expect(tint).toBe(lightAccent[10]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("takes the ramp's deep surface end in a dark scheme", () => {
|
|
53
|
+
const tint = resolveAccentTintedSurface({ steps: darkAccent, paper: darkPaper, ink: darkInk });
|
|
54
|
+
expect(tint).toBe(darkAccent[0]);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// The bug this rule replaced: keying the pick off a SURFACE token let a tint
|
|
58
|
+
// sub-theme (which re-ramps surfaces) slide the chip a step per tint. Scheme
|
|
59
|
+
// polarity comes from the paper/ink anchors, which a tint leaves alone.
|
|
60
|
+
it("does not drift when surrounding surfaces are re-ramped by a tint", () => {
|
|
61
|
+
const untinted = resolveAccentTintedSurface({
|
|
62
|
+
steps: lightAccent,
|
|
63
|
+
paper: lightPaper,
|
|
64
|
+
ink: lightInk,
|
|
65
|
+
});
|
|
66
|
+
for (const tintedPaper of ["#fffce8", "#fff8f8", "#f2fbf5"]) {
|
|
67
|
+
expect(
|
|
68
|
+
resolveAccentTintedSurface({ steps: lightAccent, paper: tintedPaper, ink: lightInk }),
|
|
69
|
+
).toBe(untinted);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("stays a SURFACE tier — never the solid an accent CTA takes", () => {
|
|
74
|
+
// The solid is accentBackground (= the ramp's mid, palette-shape solid).
|
|
75
|
+
const lightSolid = lightAccent[2];
|
|
76
|
+
const darkSolid = darkAccent[9];
|
|
77
|
+
expect(
|
|
78
|
+
resolveAccentTintedSurface({ steps: lightAccent, paper: lightPaper, ink: lightInk }),
|
|
79
|
+
).not.toBe(lightSolid);
|
|
80
|
+
expect(
|
|
81
|
+
resolveAccentTintedSurface({ steps: darkAccent, paper: darkPaper, ink: darkInk }),
|
|
82
|
+
).not.toBe(darkSolid);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("keeps a luminance-picked label readable on the tint in both schemes", () => {
|
|
86
|
+
const cases = [
|
|
87
|
+
{ steps: lightAccent, paper: lightPaper, ink: lightInk },
|
|
88
|
+
{ steps: darkAccent, paper: darkPaper, ink: darkInk },
|
|
89
|
+
];
|
|
90
|
+
for (const c of cases) {
|
|
91
|
+
const tint = resolveAccentTintedSurface(c)!;
|
|
92
|
+
const best = Math.max(
|
|
93
|
+
contrastRatio(lum(tint), lum(c.paper)),
|
|
94
|
+
contrastRatio(lum(tint), lum(c.ink)),
|
|
95
|
+
);
|
|
96
|
+
expect(best).toBeGreaterThanOrEqual(4.5);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("returns undefined when the accent ramp or an anchor is missing", () => {
|
|
101
|
+
expect(
|
|
102
|
+
resolveAccentTintedSurface({ steps: [], paper: lightPaper, ink: lightInk }),
|
|
103
|
+
).toBeUndefined();
|
|
104
|
+
expect(
|
|
105
|
+
resolveAccentTintedSurface({ steps: lightAccent, paper: undefined, ink: lightInk }),
|
|
106
|
+
).toBeUndefined();
|
|
107
|
+
expect(
|
|
108
|
+
resolveAccentTintedSurface({
|
|
109
|
+
steps: Array.from({ length: 12 }, () => "var(--nope)"),
|
|
110
|
+
paper: lightPaper,
|
|
111
|
+
ink: lightInk,
|
|
112
|
+
}),
|
|
113
|
+
).toBeUndefined();
|
|
114
|
+
});
|
|
115
|
+
});
|
|
@@ -102,41 +102,62 @@ export function useAccentOnSurface(): string {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
|
-
* Accent
|
|
106
|
-
*
|
|
107
|
-
* strength rather than as a solid
|
|
108
|
-
*
|
|
105
|
+
* Accent SURFACE tier of the accent ramp, mirrored by scheme — the fill for a
|
|
106
|
+
* selected/current chip that must carry the accent language at SURFACE
|
|
107
|
+
* strength rather than as a solid (LC-05: selection is accent; the ViewSwitcher
|
|
108
|
+
* rider pins segmented-control strength at "tinted", not the solid an accent
|
|
109
|
+
* CTA takes).
|
|
109
110
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
111
|
+
* The step is a declared ramp POSITION, the same way the neutral ramp declares
|
|
112
|
+
* its tiers (surface `$color2`, UI background `$color3`-`$color5`, text
|
|
113
|
+
* `$color11`-`$color12`): the accent ramp's surface end is its palest step in a
|
|
114
|
+
* light scheme and its deepest in a dark one, so the chip reads as a tinted
|
|
115
|
+
* surface on either page. Scheme polarity comes from the paper/ink ANCHORS,
|
|
116
|
+
* never from a surface token — a tint re-ramps surfaces, and keying off one
|
|
117
|
+
* made this pick drift a step per tint (measured: the chip slid from the pale
|
|
118
|
+
* accent to the palest accent under a yellow tint).
|
|
115
119
|
*
|
|
116
|
-
* Returns `undefined` when the accent ramp is absent or unparseable
|
|
117
|
-
*
|
|
120
|
+
* Returns `undefined` when the accent ramp is absent or unparseable (tint
|
|
121
|
+
* sub-themes without an accent ramp) — callers keep their neutral default
|
|
122
|
+
* rather than render an unthemed chip.
|
|
118
123
|
*/
|
|
119
|
-
|
|
124
|
+
// Ramp positions (1-based) of the accent surface tier per scheme.
|
|
125
|
+
const ACCENT_SURFACE_STEP_LIGHT = 11;
|
|
126
|
+
const ACCENT_SURFACE_STEP_DARK = 1;
|
|
127
|
+
|
|
128
|
+
export interface ResolveAccentTintedSurfaceInput {
|
|
129
|
+
/** Accent ramp steps 1..12, as raw color values; holes allowed. */
|
|
130
|
+
steps: (string | undefined)[];
|
|
131
|
+
/** Scheme paper anchor (`$color1`). */
|
|
132
|
+
paper?: string;
|
|
133
|
+
/** Scheme ink anchor (`$color12`). */
|
|
134
|
+
ink?: string;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** Pure resolver behind {@link useAccentTintedSurface} — see its docs. */
|
|
138
|
+
export function resolveAccentTintedSurface({
|
|
139
|
+
steps,
|
|
140
|
+
paper,
|
|
141
|
+
ink,
|
|
142
|
+
}: ResolveAccentTintedSurfaceInput): string | undefined {
|
|
143
|
+
const paperHex = paper ? normalizeToHex(paper) : null;
|
|
144
|
+
const inkHex = ink ? normalizeToHex(ink) : null;
|
|
145
|
+
if (!paperHex || !inkHex) return undefined;
|
|
146
|
+
const isLight = relativeLuminance(paperHex) > relativeLuminance(inkHex);
|
|
147
|
+
const step = steps[(isLight ? ACCENT_SURFACE_STEP_LIGHT : ACCENT_SURFACE_STEP_DARK) - 1];
|
|
148
|
+
if (!step || !normalizeToHex(step)) return undefined;
|
|
149
|
+
return step;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function useAccentTintedSurface(): string | undefined {
|
|
120
153
|
const theme = useTamaguiTheme() as unknown as Record<string, { val?: unknown } | undefined>;
|
|
121
|
-
const
|
|
154
|
+
const paper = resolveTokenValue(theme, "color1");
|
|
155
|
+
const ink = resolveTokenValue(theme, "color12");
|
|
122
156
|
const steps: (string | undefined)[] = [];
|
|
123
157
|
for (let i = 1; i <= 12; i++) steps.push(resolveTokenValue(theme, `accent${i}`));
|
|
124
158
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
125
|
-
return useMemo(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
let best: string | undefined;
|
|
130
|
-
let bestDelta = Number.POSITIVE_INFINITY;
|
|
131
|
-
for (const step of steps) {
|
|
132
|
-
const hex = step ? normalizeToHex(step) : null;
|
|
133
|
-
if (!step || !hex) continue;
|
|
134
|
-
const delta = Math.abs(relativeLuminance(hex) - target);
|
|
135
|
-
if (delta < bestDelta) {
|
|
136
|
-
bestDelta = delta;
|
|
137
|
-
best = step;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
return best;
|
|
141
|
-
}, [neutral, steps.join("|")]);
|
|
159
|
+
return useMemo(
|
|
160
|
+
() => resolveAccentTintedSurface({ steps, paper, ink }),
|
|
161
|
+
[paper, ink, steps.join("|")],
|
|
162
|
+
);
|
|
142
163
|
}
|
|
@@ -18,8 +18,13 @@ import {
|
|
|
18
18
|
import type { Knobs } from "./knobs";
|
|
19
19
|
import type { KnobProps } from "./recipes";
|
|
20
20
|
import { cornerSmoothClassName } from "./cornerSmoothing";
|
|
21
|
-
import { defaultPreset, boldPreset } from "./presets";
|
|
22
|
-
import {
|
|
21
|
+
import { defaultPreset, boldPreset, heroPreset } from "./presets";
|
|
22
|
+
import {
|
|
23
|
+
applyDensity,
|
|
24
|
+
capContainerRadius,
|
|
25
|
+
resolveKnobs,
|
|
26
|
+
resolvePageTitleScale,
|
|
27
|
+
} from "./resolveKnobs";
|
|
23
28
|
import {
|
|
24
29
|
normalizeToHex,
|
|
25
30
|
relativeLuminance,
|
|
@@ -47,6 +52,7 @@ const expectedKnobPropKeys: (keyof KnobProps)[] = [
|
|
|
47
52
|
"gapLg",
|
|
48
53
|
"sizeToken",
|
|
49
54
|
"heading",
|
|
55
|
+
"pageTitle",
|
|
50
56
|
"body",
|
|
51
57
|
"textWeight",
|
|
52
58
|
"transition",
|
|
@@ -731,6 +737,44 @@ describe("resolveKnobs", () => {
|
|
|
731
737
|
});
|
|
732
738
|
});
|
|
733
739
|
|
|
740
|
+
// ── pageTitleScale (D-11 hero-H1 dial) ──────────────────────
|
|
741
|
+
|
|
742
|
+
describe("pageTitleScale knob", () => {
|
|
743
|
+
it("defaults to the moderate page-title step ($8 = 32px)", () => {
|
|
744
|
+
expect(resolveKnobs(defaultKnobs).knobProps.pageTitle).toEqual({ size: "$8" });
|
|
745
|
+
});
|
|
746
|
+
|
|
747
|
+
it('"display" re-opens the hero step ($10 = 64px)', () => {
|
|
748
|
+
expect(resolveKnobs(knobsWith({ pageTitleScale: "display" })).knobProps.pageTitle).toEqual({
|
|
749
|
+
size: "$10",
|
|
750
|
+
});
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
it("an omitted knob still resolves moderate (preset constructions predate the dial)", () => {
|
|
754
|
+
const { pageTitleScale: _omitted, ...withoutDial } = defaultKnobs;
|
|
755
|
+
expect(resolveKnobs(withoutDial as Knobs).knobProps.pageTitle).toEqual({ size: "$8" });
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
it("resolvePageTitleScale is the one table both channels read", () => {
|
|
759
|
+
expect(resolvePageTitleScale("moderate")).toEqual({ size: "$8" });
|
|
760
|
+
expect(resolvePageTitleScale("display")).toEqual({ size: "$10" });
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
it("product presets ship moderate; `hero` is the only display opt-in", () => {
|
|
764
|
+
expect(defaultPreset.knobs.pageTitleScale).toBe("moderate");
|
|
765
|
+
expect(boldPreset.knobs.pageTitleScale).toBe("moderate");
|
|
766
|
+
expect(heroPreset.knobs.pageTitleScale).toBe("display");
|
|
767
|
+
expect(resolveKnobs(heroPreset.knobs).knobProps.pageTitle).toEqual({ size: "$10" });
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
it("`hero` differs from the default preset in nothing but the title step", () => {
|
|
771
|
+
const { pageTitleScale: _hero, ...heroRest } = heroPreset.knobs;
|
|
772
|
+
const { pageTitleScale: _default, ...defaultRest } = defaultPreset.knobs;
|
|
773
|
+
expect(heroRest).toEqual(defaultRest);
|
|
774
|
+
expect(heroPreset.theme).toBe(defaultPreset.theme);
|
|
775
|
+
});
|
|
776
|
+
});
|
|
777
|
+
|
|
734
778
|
// ── animation ─────────────────────────────────────────────
|
|
735
779
|
|
|
736
780
|
describe("animation knob", () => {
|
package/types/dates.d.ts
CHANGED
|
@@ -12,6 +12,11 @@
|
|
|
12
12
|
* current year elided (`year: "auto"`)
|
|
13
13
|
* - editing surfaces → compact absolute with the year always shown
|
|
14
14
|
* ("Jul 1, 2026") — pickers are precision contexts
|
|
15
|
+
* - calendar chrome → the day/month/time-of-day registers below
|
|
16
|
+
* (weekday and month names, "2 PM" hour ticks,
|
|
17
|
+
* "2:00 PM" times, "Tuesday, March 10" day names)
|
|
18
|
+
* - date axis ticks → compact absolute with `year: "never"`, because
|
|
19
|
+
* the surrounding chrome already states the year
|
|
15
20
|
* No default may emit verbose locale output with seconds.
|
|
16
21
|
*/
|
|
17
22
|
export type DateInput = Date | string | number | null | undefined;
|
|
@@ -19,9 +24,11 @@ export interface AbsoluteDateFormatOptions {
|
|
|
19
24
|
/**
|
|
20
25
|
* `"auto"` (default) elides the current year — the display register for
|
|
21
26
|
* tables, feeds, and system events. `"always"` keeps it — the editing
|
|
22
|
-
* register for picker display values.
|
|
27
|
+
* register for picker display values. `"never"` drops it — the axis-tick
|
|
28
|
+
* register, where a wider label would collide with its neighbours and the
|
|
29
|
+
* period header carries the year.
|
|
23
30
|
*/
|
|
24
|
-
year?: "auto" | "always";
|
|
31
|
+
year?: "auto" | "always" | "never";
|
|
25
32
|
/** Include the time component ("Aug 9, 3:30 PM"). Default false. */
|
|
26
33
|
withTime?: boolean;
|
|
27
34
|
/** BCP-47 locale forwarded to Intl. Default: system locale. */
|
|
@@ -31,6 +38,24 @@ export interface AbsoluteDateFormatOptions {
|
|
|
31
38
|
}
|
|
32
39
|
/** ISO date-only shape ("YYYY-MM-DD"). */
|
|
33
40
|
export declare const ISO_DATE_ONLY: RegExp;
|
|
41
|
+
/**
|
|
42
|
+
* Parse a date value onto the LOCAL calendar day it names — the canonical
|
|
43
|
+
* parse for anything that will be positioned on a day grid (calendar cells,
|
|
44
|
+
* Gantt bars, date axes) rather than merely formatted.
|
|
45
|
+
*
|
|
46
|
+
* A date-only string ("YYYY-MM-DD") is a calendar date carrying no timezone,
|
|
47
|
+
* which is how Frappe sends `Date` fields. ECMA-262 parses that form as UTC
|
|
48
|
+
* midnight, so every zone west of UTC reads it as the *previous* local day,
|
|
49
|
+
* and no zone but UTC lands it on the local midnight that day-grid math tests
|
|
50
|
+
* for. Those are built from local parts instead.
|
|
51
|
+
*
|
|
52
|
+
* Values that carry a time ("YYYY-MM-DD HH:MM:SS", ISO with an offset, epoch
|
|
53
|
+
* millis) are genuine instants and keep the timezone-aware parse untouched.
|
|
54
|
+
*
|
|
55
|
+
* Returns null for empty and unparseable input, and for out-of-range parts
|
|
56
|
+
* ("2026-13-45") rather than silently rolling them into the next month.
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseCalendarDate(value: DateInput): Date | null;
|
|
34
59
|
/**
|
|
35
60
|
* Compact absolute date — the house register for every absolute date.
|
|
36
61
|
* "Jul 1" / "Jul 1, 2025" (year auto-elided when current), or with
|
|
@@ -49,4 +74,59 @@ export declare function formatAbsoluteDateTime(value: DateInput, options?: Omit<
|
|
|
49
74
|
* feed/social register (LC-12), selected by `timestampStyle: "relative"`.
|
|
50
75
|
*/
|
|
51
76
|
export declare function formatRelativeTimestamp(value: DateInput, now?: number): string;
|
|
77
|
+
/** Clock-time shape ("HH:MM" / "HH:MM:SS") — how Frappe `Time` values arrive. */
|
|
78
|
+
export declare const CLOCK_TIME: RegExp;
|
|
79
|
+
export interface TimeOfDayFormatOptions {
|
|
80
|
+
/** BCP-47 locale forwarded to Intl. Default: system locale. */
|
|
81
|
+
locale?: string;
|
|
82
|
+
/** Minutes ride along by default; `false` is the hour-tick register. */
|
|
83
|
+
minutes?: boolean;
|
|
84
|
+
/** Pin the 12/24-hour clock. Default: whatever the locale uses. */
|
|
85
|
+
hour12?: boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Time-of-day register ("2:00 PM", or "2 PM" with `minutes: false` for
|
|
89
|
+
* hour ticks) — calendar time grids, Frappe `Time` fields, and
|
|
90
|
+
* "last updated" chrome. Accepts a clock-time string as well as a date,
|
|
91
|
+
* and never emits seconds.
|
|
92
|
+
*/
|
|
93
|
+
export declare function formatTimeOfDay(value: DateInput, options?: TimeOfDayFormatOptions): string;
|
|
94
|
+
export interface DayLongFormatOptions {
|
|
95
|
+
locale?: string;
|
|
96
|
+
/** Lead with the weekday ("Tuesday, March 10"). Default true. */
|
|
97
|
+
weekday?: boolean;
|
|
98
|
+
/** Append the year ("Tuesday, March 10, 2026"). Default false. */
|
|
99
|
+
year?: boolean;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Long day register ("Tuesday, March 10") — calendar day headers and the
|
|
103
|
+
* accessible names that read a date aloud, where the compact absolute
|
|
104
|
+
* register is too terse to speak.
|
|
105
|
+
*/
|
|
106
|
+
export declare function formatDayLong(value: DateInput, options?: DayLongFormatOptions): string;
|
|
107
|
+
export interface MonthYearFormatOptions {
|
|
108
|
+
locale?: string;
|
|
109
|
+
/** `"short"` ("Mar 2026", the tick register) or `"long"` ("March 2026"). */
|
|
110
|
+
month?: "short" | "long";
|
|
111
|
+
}
|
|
112
|
+
/** Month-year register ("Mar 2026") — period headers and month axis ticks. */
|
|
113
|
+
export declare function formatMonthYear(value: DateInput, options?: MonthYearFormatOptions): string;
|
|
114
|
+
/** Day-of-month register ("10") — the densest date axis tick. */
|
|
115
|
+
export declare function formatDayOfMonth(value: DateInput, options?: {
|
|
116
|
+
locale?: string;
|
|
117
|
+
}): string;
|
|
118
|
+
export interface WeekdayNamesOptions {
|
|
119
|
+
locale?: string;
|
|
120
|
+
/** `"short"` ("Mon"), `"long"` ("Monday") or `"narrow"` ("M"). */
|
|
121
|
+
style?: "short" | "long" | "narrow";
|
|
122
|
+
/** Week start, 0 = Sunday (default) — the index base callers rely on. */
|
|
123
|
+
firstDay?: number;
|
|
124
|
+
}
|
|
125
|
+
/** Weekday names for calendar chrome, in week order from `firstDay`. */
|
|
126
|
+
export declare function getWeekdayNames(options?: WeekdayNamesOptions): string[];
|
|
127
|
+
/** Month names for calendar chrome and picker headers, January first. */
|
|
128
|
+
export declare function getMonthNames(options?: {
|
|
129
|
+
locale?: string;
|
|
130
|
+
style?: "long" | "short";
|
|
131
|
+
}): string[];
|
|
52
132
|
//# sourceMappingURL=dates.d.ts.map
|
package/types/dates.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dates.d.ts","sourceRoot":"","sources":["../src/dates.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dates.d.ts","sourceRoot":"","sources":["../src/dates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAElE,MAAM,WAAW,yBAAyB;IACxC;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACnC,oEAAoE;IACpE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sEAAsE;IACtE,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED,0CAA0C;AAC1C,eAAO,MAAM,aAAa,QAAwB,CAAC;AAyBnD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAkB/D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE,yBAA8B,GACtC,MAAM,CA0BR;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,SAAS,EAChB,OAAO,GAAE,IAAI,CAAC,yBAAyB,EAAE,UAAU,CAAM,GACxD,MAAM,CAER;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,CAgB1F;AAED,iFAAiF;AACjF,eAAO,MAAM,UAAU,QAAqC,CAAC;AAE7D,MAAM,WAAW,sBAAsB;IACrC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,mEAAmE;IACnE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM,CAuB9F;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAa1F;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE,sBAA2B,GAAG,MAAM,CAW9F;AAED,iEAAiE;AACjE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CAU5F;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,OAAO,GAAE,mBAAwB,GAAG,MAAM,EAAE,CAO3E;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAC3B,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAO,GAC1D,MAAM,EAAE,CAIV"}
|
package/types/devWarn.d.ts
CHANGED
|
@@ -16,6 +16,41 @@ export type DevWarnDetail = {
|
|
|
16
16
|
region?: string;
|
|
17
17
|
[key: string]: unknown;
|
|
18
18
|
};
|
|
19
|
+
/**
|
|
20
|
+
* LC-57 GUARDRAIL-CLEAN-STORIES allowlist entry, declared as a Storybook story
|
|
21
|
+
* parameter (`parameters.guardrailSpecimen`).
|
|
22
|
+
*
|
|
23
|
+
* Catalog stories emit zero `[theme]` guardrail warnings at rest. A story whose
|
|
24
|
+
* whole purpose is to demonstrate the warned state (a disabled-dial specimen, a
|
|
25
|
+
* pager boundary case) is allowlisted by declaring itself:
|
|
26
|
+
*
|
|
27
|
+
* ```ts
|
|
28
|
+
* export const Disabled: Story = {
|
|
29
|
+
* parameters: {
|
|
30
|
+
* guardrailSpecimen: {
|
|
31
|
+
* warns: ["bare-disabled"],
|
|
32
|
+
* reason: "Demonstrates the disabled dial; Stepper has no disabledReason plumbing.",
|
|
33
|
+
* } satisfies GuardrailSpecimenParameter,
|
|
34
|
+
* },
|
|
35
|
+
* };
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* Semantics, pinned:
|
|
39
|
+
* - `warns` is the CLOSED set of codes the story may emit at rest. An emitted
|
|
40
|
+
* code outside the set still FAILs the story.
|
|
41
|
+
* - A declared code that happens not to fire passes — component improvements
|
|
42
|
+
* must never break an allowlist entry.
|
|
43
|
+
* - The declaration NEVER suppresses the console warning — the warn still
|
|
44
|
+
* fires; only the warn-harvester tolerates it (explicit, never tacit).
|
|
45
|
+
* - Harvesters (`p-results/story-hygiene/verify.mjs`) read this parameter off
|
|
46
|
+
* the rendered story and fail CLOSED when parameters cannot be read at all.
|
|
47
|
+
*/
|
|
48
|
+
export type GuardrailSpecimenParameter = {
|
|
49
|
+
/** Warn codes this story may emit at rest — a closed set, not a wildcard. */
|
|
50
|
+
warns: DevWarnCode[];
|
|
51
|
+
/** Why the warned state is the story's subject (recorded per LC-57). */
|
|
52
|
+
reason: string;
|
|
53
|
+
};
|
|
19
54
|
/**
|
|
20
55
|
* Emit a once-per-key console warning in non-production builds.
|
|
21
56
|
*/
|
package/types/devWarn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devWarn.d.ts","sourceRoot":"","sources":["../src/devWarn.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"devWarn.d.ts","sourceRoot":"","sources":["../src/devWarn.ts"],"names":[],"mappings":"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"}
|
package/types/index.d.ts
CHANGED
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,eAAe,CAAC;AAG9B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,qBAAqB,CAAC;AACpC,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,eAAe,CAAC;AAG9B,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical number / currency registers (LC-12 render channel, Axiom 9).
|
|
3
|
+
*
|
|
4
|
+
* One formatter owns every number the catalog renders — table aggregates,
|
|
5
|
+
* KPI values, report cells, chart value labels — so the same data class
|
|
6
|
+
* never speaks in two voices ("15400" in a group header beside "15,400" in
|
|
7
|
+
* the cell two rows below).
|
|
8
|
+
*
|
|
9
|
+
* Content class picks the register:
|
|
10
|
+
* - cardinal / aggregate → `formatNumber` (grouped, ≤2 fraction digits)
|
|
11
|
+
* - money → `formatCurrency` (grouped, 2 fraction digits;
|
|
12
|
+
* `fractionDigits: "auto"` elides a whole-value
|
|
13
|
+
* `.00` for summary tiles)
|
|
14
|
+
* - rate → `formatPercent` (value already carries percent
|
|
15
|
+
* units: 94.2 → "94.2%")
|
|
16
|
+
*
|
|
17
|
+
* Not covered (declared exemptions): chart AXIS tick labels, whose
|
|
18
|
+
* density-driven register is owned by `charts/math.ts#formatAxisTick`;
|
|
19
|
+
* app-land `useFormatNumber` / `useFormatCurrency` (i18n package), which
|
|
20
|
+
* bind the active UI language outside the catalog; and machine formats
|
|
21
|
+
* (export/serialization).
|
|
22
|
+
*/
|
|
23
|
+
export type NumberInput = number | string | null | undefined;
|
|
24
|
+
export interface NumberFormatOptions {
|
|
25
|
+
/** BCP-47 locale forwarded to Intl. Default: system locale. */
|
|
26
|
+
locale?: string;
|
|
27
|
+
/** Pins min and max fraction digits together (fixed-precision columns). */
|
|
28
|
+
precision?: number;
|
|
29
|
+
minimumFractionDigits?: number;
|
|
30
|
+
/** House cap for the cardinal register. Default 2. */
|
|
31
|
+
maximumFractionDigits?: number;
|
|
32
|
+
/** Thousands grouping. Default true. */
|
|
33
|
+
grouping?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface CurrencyFormatOptions extends NumberFormatOptions {
|
|
36
|
+
/** ISO 4217 code, e.g. "USD" — renders through Intl's currency style. */
|
|
37
|
+
currency?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Currency symbol as handed over by Frappe-style adapters. Resolved to an
|
|
40
|
+
* ISO code when known, otherwise prefixed literally.
|
|
41
|
+
*/
|
|
42
|
+
symbol?: string;
|
|
43
|
+
/**
|
|
44
|
+
* `"always"` (default) pins 2 fraction digits — the money register that
|
|
45
|
+
* keeps columns aligned. `"auto"` drops them for whole values — the
|
|
46
|
+
* summary-tile register (KPI cards read "$48,250", not "$48,250.00")
|
|
47
|
+
* while still showing cents when a value has them.
|
|
48
|
+
*/
|
|
49
|
+
fractionDigits?: "always" | "auto";
|
|
50
|
+
}
|
|
51
|
+
export type PercentFormatOptions = NumberFormatOptions;
|
|
52
|
+
/**
|
|
53
|
+
* ISO 4217 code for a currency symbol (or a code passed straight through).
|
|
54
|
+
* `undefined` when the symbol has no known code — callers prefix it.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveCurrencyCode(symbol: string | undefined): string | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Cardinal / aggregate register — grouped digits, at most two fraction
|
|
59
|
+
* digits ("15,400", "5,133.33"). Empty input renders "" and an unparseable
|
|
60
|
+
* string passes through unchanged (honest passthrough — never invents).
|
|
61
|
+
*/
|
|
62
|
+
export declare function formatNumber(value: NumberInput, options?: NumberFormatOptions): string;
|
|
63
|
+
/**
|
|
64
|
+
* Money register — grouped digits with two fraction digits, rendered with
|
|
65
|
+
* the currency's own symbol placement when the code is known ("$15,400.00",
|
|
66
|
+
* "₹15,400.00") and symbol-prefixed otherwise.
|
|
67
|
+
*/
|
|
68
|
+
export declare function formatCurrency(value: NumberInput, options?: CurrencyFormatOptions): string;
|
|
69
|
+
/**
|
|
70
|
+
* Rate register — the value already carries percent units (94.2 → "94.2%"),
|
|
71
|
+
* never a 0..1 ratio; ratios are converted by the caller that owns the unit.
|
|
72
|
+
*/
|
|
73
|
+
export declare function formatPercent(value: NumberInput, options?: PercentFormatOptions): string;
|
|
74
|
+
//# sourceMappingURL=numbers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numbers.d.ts","sourceRoot":"","sources":["../src/numbers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAE7D,MAAM,WAAW,mBAAmB;IAClC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,sDAAsD;IACtD,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB;IAChE,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;CACpC;AAED,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,CAAC;AAcvD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAIlF;AAyCD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,GAAE,mBAAwB,GAAG,MAAM,CAQ1F;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,GAAE,qBAA0B,GAAG,MAAM,CA8B9F;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAK5F"}
|
|
@@ -55,7 +55,7 @@ export interface ButtonColorConfig extends ComponentColorConfig {
|
|
|
55
55
|
}
|
|
56
56
|
export declare const buttonColors: ButtonColorConfig;
|
|
57
57
|
export declare const inputColors: ComponentColorConfig;
|
|
58
|
-
export declare function $color(step: ColorStep): "$
|
|
58
|
+
export declare function $color(step: ColorStep): "$color3" | "$color1" | "$color2" | "$color12" | "$color7" | "$color4" | "$color5" | "$color11" | "$color6" | "$color8" | "$color9" | "$color10";
|
|
59
59
|
export interface SemanticGroup {
|
|
60
60
|
key: string;
|
|
61
61
|
label: string;
|
package/types/theme/cookies.d.ts
CHANGED
|
@@ -26,13 +26,27 @@ export declare function splitCookieValue(value: string): string[];
|
|
|
26
26
|
export declare function joinSplitCookieValues(chunks: string[]): string;
|
|
27
27
|
/**
|
|
28
28
|
* Read the overrides cookie value, handling chunked cookies.
|
|
29
|
-
*
|
|
29
|
+
*
|
|
30
|
+
* Accepts BOTH value shapes a cookie jar can deliver:
|
|
31
|
+
* - already-parsed OBJECTS — react-cookie's `useCookies()` jar
|
|
32
|
+
* (universal-cookie) auto-JSON-parses every cookie value it can (its
|
|
33
|
+
* `readCookie` tries `JSON.parse` unless `doNotParse` is set), so a
|
|
34
|
+
* single-chunk overrides cookie arrives here as an object, not a string;
|
|
35
|
+
* - raw JSON STRINGS — direct `document.cookie` / SSR cookie-header reads
|
|
36
|
+
* (`loadPresetOverrides`), and multi-chunk payloads on every path (a
|
|
37
|
+
* fragment of a split JSON document does not parse on its own, so even
|
|
38
|
+
* universal-cookie leaves those chunks as strings).
|
|
39
|
+
*
|
|
40
|
+
* Anything else (numbers, arrays, mixed chunk types, malformed JSON) reads
|
|
41
|
+
* as no overrides, and every parsed payload is shape-validated before use.
|
|
30
42
|
*/
|
|
31
|
-
export declare function readOverridesCookie(cookies: Record<string,
|
|
43
|
+
export declare function readOverridesCookie(cookies: Record<string, unknown>): Partial<Knobs>;
|
|
32
44
|
/**
|
|
33
|
-
* Read the preset name from the cookie.
|
|
45
|
+
* Read the preset name from the cookie. universal-cookie auto-JSON-parses
|
|
46
|
+
* jar values, so a numeric-looking name would arrive as a number — preset
|
|
47
|
+
* names are strings by contract, anything else reads as no preset.
|
|
34
48
|
*/
|
|
35
|
-
export declare function readPresetCookie(cookies: Record<string,
|
|
49
|
+
export declare function readPresetCookie(cookies: Record<string, unknown>): string | undefined;
|
|
36
50
|
/**
|
|
37
51
|
* Write the preset name cookie.
|
|
38
52
|
* Returns the cookie key and value for the caller to pass to setCookie.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/theme/cookies.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAMrC,6CAA6C;AAC7C,eAAO,MAAM,YAAY,cAAc,CAAC;AAExC,sDAAsD;AACtD,eAAO,MAAM,qBAAqB,UAAU,CAAC;AAY7C;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASxD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAE9D;
|
|
1
|
+
{"version":3,"file":"cookies.d.ts","sourceRoot":"","sources":["../../src/theme/cookies.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAMrC,6CAA6C;AAC7C,eAAO,MAAM,YAAY,cAAc,CAAC;AAExC,sDAAsD;AACtD,eAAO,MAAM,qBAAqB,UAAU,CAAC;AAY7C;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASxD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAE9D;AAyCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAwBpF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CAGrF;AAMD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAEpF;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG;IAC/D,KAAK,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7C,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAgBA;AAMD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAQ5E;AAMD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,EAAE,CAM7C;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,CAQtE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAC9C,OAAO,CAAC,KAAK,CAAC,CAGhB"}
|