@hjmds/design-contracts 1.41.2 → 1.43.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/affix.d.ts +18 -0
- package/dist/affix.d.ts.map +1 -1
- package/dist/affix.js +13 -1
- package/dist/affix.js.map +1 -1
- package/dist/alert-dialog.d.ts +32 -0
- package/dist/alert-dialog.d.ts.map +1 -1
- package/dist/alert-dialog.js +52 -0
- package/dist/alert-dialog.js.map +1 -1
- package/dist/behaviors.d.ts +6 -5
- package/dist/behaviors.d.ts.map +1 -1
- package/dist/behaviors.js +1 -1
- package/dist/behaviors.js.map +1 -1
- package/dist/catalog.d.ts +168 -15
- package/dist/catalog.d.ts.map +1 -1
- package/dist/catalog.js +4 -4
- package/dist/catalog.js.map +1 -1
- package/dist/character-count.d.ts +103 -0
- package/dist/character-count.d.ts.map +1 -0
- package/dist/character-count.js +68 -0
- package/dist/character-count.js.map +1 -0
- package/dist/chart.d.ts +30 -0
- package/dist/chart.d.ts.map +1 -1
- package/dist/chart.js +18 -0
- package/dist/chart.js.map +1 -1
- package/dist/collection-rail.d.ts +13 -1
- package/dist/collection-rail.d.ts.map +1 -1
- package/dist/collection-rail.js +9 -2
- package/dist/collection-rail.js.map +1 -1
- package/dist/communication.d.ts +25 -0
- package/dist/communication.d.ts.map +1 -1
- package/dist/communication.js +3 -0
- package/dist/communication.js.map +1 -1
- package/dist/component-recipes.d.ts +172 -2
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +122 -8
- package/dist/component-recipes.js.map +1 -1
- package/dist/design-system-provider.d.ts +13 -2
- package/dist/design-system-provider.d.ts.map +1 -1
- package/dist/design-system-provider.js +19 -3
- package/dist/design-system-provider.js.map +1 -1
- package/dist/foundations.d.ts +15 -0
- package/dist/foundations.d.ts.map +1 -1
- package/dist/foundations.js +7 -0
- package/dist/foundations.js.map +1 -1
- package/dist/icon-button-recipe.d.ts +33 -0
- package/dist/icon-button-recipe.d.ts.map +1 -1
- package/dist/icon-button-recipe.js +36 -1
- package/dist/icon-button-recipe.js.map +1 -1
- package/dist/image.d.ts +13 -0
- package/dist/image.d.ts.map +1 -1
- package/dist/image.js +17 -0
- package/dist/image.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/recipes.d.ts +1 -1
- package/dist/recipes.d.ts.map +1 -1
- package/dist/recipes.js +1 -1
- package/dist/recipes.js.map +1 -1
- package/dist/screen-patterns.d.ts +95 -0
- package/dist/screen-patterns.d.ts.map +1 -1
- package/dist/screen-patterns.js +83 -2
- package/dist/screen-patterns.js.map +1 -1
- package/dist/selection-helpers.d.ts +6 -0
- package/dist/selection-helpers.d.ts.map +1 -1
- package/dist/selection-helpers.js +12 -0
- package/dist/selection-helpers.js.map +1 -1
- package/dist/sidebar.d.ts +17 -2
- package/dist/sidebar.d.ts.map +1 -1
- package/dist/sidebar.js +8 -2
- package/dist/sidebar.js.map +1 -1
- package/dist/steps.d.ts +19 -19
- package/dist/steps.d.ts.map +1 -1
- package/dist/steps.js +21 -9
- package/dist/steps.js.map +1 -1
- package/dist/timeline.d.ts +41 -0
- package/dist/timeline.d.ts.map +1 -1
- package/dist/timeline.js +47 -1
- package/dist/timeline.js.map +1 -1
- package/dist/top.d.ts +21 -2
- package/dist/top.d.ts.map +1 -1
- package/dist/top.js +17 -1
- package/dist/top.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/affix.md +7 -0
- package/docs/avatar-fallback.md +19 -0
- package/docs/brand-boundary.md +24 -2
- package/docs/chart.md +7 -0
- package/docs/collection-rail.md +4 -1
- package/docs/generated/component-maturity.md +1 -1
- package/docs/generated/renderer-evidence.json +10 -6
- package/docs/generated/renderer-evidence.md +1 -1
- package/docs/generated/showcase-manifest.json +12 -5
- package/docs/image.md +5 -0
- package/docs/list-row.md +8 -0
- package/docs/optional-adapters.md +3 -0
- package/docs/overlay-stack.md +27 -0
- package/docs/screen-patterns.md +39 -2
- package/docs/sidebar.md +15 -0
- package/docs/steps.md +23 -19
- package/docs/theme-palette.md +3 -3
- package/docs/theming.md +1 -0
- package/docs/timeline.md +18 -1
- package/docs/top.md +7 -0
- package/docs/usage/README.md +9 -2
- package/docs/usage/components/affix.md +18 -4
- package/docs/usage/components/alert-dialog.md +28 -0
- package/docs/usage/components/avatar.md +30 -9
- package/docs/usage/components/badge.md +20 -5
- package/docs/usage/components/chart.md +19 -1
- package/docs/usage/components/chat-message.md +5 -0
- package/docs/usage/components/chat-room-actions.md +58 -0
- package/docs/usage/components/chat-room-create.md +58 -0
- package/docs/usage/components/chat-room-details.md +58 -0
- package/docs/usage/components/chat-room-invite.md +58 -0
- package/docs/usage/components/chat-room-members.md +58 -0
- package/docs/usage/components/chat-room-profile.md +58 -0
- package/docs/usage/components/checkbox-group.md +24 -1
- package/docs/usage/components/choice-row.md +19 -4
- package/docs/usage/components/composition-layout.md +6 -2
- package/docs/usage/components/counter-badge.md +2 -2
- package/docs/usage/components/design-system-provider.md +2 -1
- package/docs/usage/components/divider.md +12 -1
- package/docs/usage/components/field.md +51 -0
- package/docs/usage/components/icon-button.md +48 -4
- package/docs/usage/components/icon-tile.md +13 -2
- package/docs/usage/components/image.md +25 -0
- package/docs/usage/components/list-row.md +8 -4
- package/docs/usage/components/list.md +1 -1
- package/docs/usage/components/notification-item.md +5 -1
- package/docs/usage/components/permission-screen.md +25 -4
- package/docs/usage/components/screen-layout.md +27 -1
- package/docs/usage/components/segmented-control.md +16 -3
- package/docs/usage/components/select.md +1 -0
- package/docs/usage/components/settings-screen.md +5 -4
- package/docs/usage/components/sheet.md +2 -1
- package/docs/usage/components/sidebar.md +34 -6
- package/docs/usage/components/steps.md +29 -8
- package/docs/usage/components/surface.md +2 -1
- package/docs/usage/components/text-area.md +2 -1
- package/docs/usage/components/timeline.md +25 -4
- package/docs/usage/components/top.md +15 -2
- package/docs/usage/compositions/chat-room.md +110 -0
- package/docs/usage/screens/common-settings.md +3 -2
- package/docs/usage/screens/flow-permission.md +3 -3
- package/docs/usage/tokens/elevation-opacity.md +14 -2
- package/package.json +7 -1
|
@@ -113,9 +113,20 @@ export type DesignSystemProviderValue = Readonly<{
|
|
|
113
113
|
/** Optional to preserve existing pre-resolved provider values. */
|
|
114
114
|
designProfile?: HjmDesignProfile;
|
|
115
115
|
}>;
|
|
116
|
+
/**
|
|
117
|
+
* How a nested provider's `brandPalette` meets the inherited one. `replace` (default, the scope reset contract)
|
|
118
|
+
* starts the subtree from the HJM defaults plus only the supplied roles. `extend` merges the supplied roles over the
|
|
119
|
+
* inherited palette per theme, so a sub-scope names only the roles it changes. 2026-10-23: BurnTok web/app
|
|
120
|
+
* ThemeProviders accumulated outer overrides by hand and Diairy built `shoreBrandPaletteWith()` to get this.
|
|
121
|
+
*/
|
|
122
|
+
export type ProviderBrandPaletteMode = "replace" | "extend";
|
|
123
|
+
export declare const providerBrandPaletteDefaults: {
|
|
124
|
+
readonly mode: "replace";
|
|
125
|
+
};
|
|
126
|
+
export declare function validateProviderBrandPaletteMode(mode: unknown): asserts mode is ProviderBrandPaletteMode;
|
|
116
127
|
/** A resolved-value bridge still owns its current color scope. Preserve it for nested
|
|
117
|
-
* providers. An explicit brandPalette
|
|
118
|
-
export declare function resolveProviderBrandPalette(inherited: ResolveDesignSystemEnvironmentOptions["brandPalette"], supplied: ResolveDesignSystemEnvironmentOptions["brandPalette"], value?: DesignSystemProviderValue): ResolveDesignSystemEnvironmentOptions["brandPalette"];
|
|
128
|
+
* providers. An explicit brandPalette replaces the inherited overrides unless `mode` is `extend`. */
|
|
129
|
+
export declare function resolveProviderBrandPalette(inherited: ResolveDesignSystemEnvironmentOptions["brandPalette"], supplied: ResolveDesignSystemEnvironmentOptions["brandPalette"], value?: DesignSystemProviderValue, mode?: ProviderBrandPaletteMode): ResolveDesignSystemEnvironmentOptions["brandPalette"];
|
|
119
130
|
/**
|
|
120
131
|
* Runtime boundary for the resolved palette a renderer receives, including one
|
|
121
132
|
* merged from a partial `brandPalette`: after merging, every semantic role a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"design-system-provider.d.ts","sourceRoot":"","sources":["../src/design-system-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAKL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAErB;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG,KAAK,GAAG,KAAK,CAAC;AAElD;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,qBAAqB,GAAG,OAAO,CAE1E;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,mBAAmB,EAAE,OAAO,GAC3B,MAAM,CAER;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,mBAAmB,GAAG,aAAa,GAAG,SAAS,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,SAAS,MAAM,EAAE,OAAO,SAAS,MAAM,EACtF,OAAO,EAAE,mBAAmB,EAC5B,UAAU,EAAE,QAAQ,CAAC;IAAE,WAAW,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,GACnE,WAAW,GAAG,OAAO,CAEvB;AAED,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,yEAAyE;IACzE,OAAO,CAAC,EAAE,mBAAmB,CAAC;CAC/B,CAAC,CAAC;AAEH,eAAO,MAAM,+BAA+B;;;;;;;CAc1C,CAAC;AAEH,MAAM,MAAM,+BAA+B,GAAG,QAAQ,CAAC;IACrD,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,qBAAqB,CAAC;IACjC,SAAS,EAAE,qBAAqB,CAAC;IACjC,aAAa,EAAE,OAAO,CAAC;IACvB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,OAAO,EAAE,mBAAmB,CAAC;CAC9B,CAAC,CAAC;AAEH,MAAM,MAAM,qCAAqC,GAAG,QAAQ,CAAC;IAC3D;;;;;OAKG;IACH,WAAW,EAAE,aAAa,CAAC;IAC3B,2FAA2F;IAC3F,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACxC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF;6FACyF;IACzF,aAAa,CAAC,EAAE,gBAAgB,CAAC;IACjC,4FAA4F;IAC5F,MAAM,CAAC,EAAE,+BAA+B,CAAC;CAC1C,CAAC,CAAC;AAEH,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAC/C,WAAW,EAAE,+BAA+B,CAAC;IAC7C,4DAA4D;IAC5D,OAAO,EAAE,qBAAqB,CAAC;IAC/B,kEAAkE;IAClE,aAAa,CAAC,EAAE,gBAAgB,CAAC;CAClC,CAAC,CAAC;AAEH;
|
|
1
|
+
{"version":3,"file":"design-system-provider.d.ts","sourceRoot":"","sources":["../src/design-system-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,12 +37,28 @@ export const designSystemEnvironmentDefaults = {
|
|
|
37
37
|
minimumVisualTarget: false,
|
|
38
38
|
density: "comfortable",
|
|
39
39
|
};
|
|
40
|
+
export const providerBrandPaletteDefaults = { mode: "replace" };
|
|
41
|
+
export function validateProviderBrandPaletteMode(mode) {
|
|
42
|
+
if (mode !== "replace" && mode !== "extend")
|
|
43
|
+
throw new TypeError(`Unsupported brandPaletteMode: ${String(mode)}`);
|
|
44
|
+
}
|
|
40
45
|
/** A resolved-value bridge still owns its current color scope. Preserve it for nested
|
|
41
|
-
* providers. An explicit brandPalette
|
|
42
|
-
export function resolveProviderBrandPalette(inherited, supplied, value) {
|
|
46
|
+
* providers. An explicit brandPalette replaces the inherited overrides unless `mode` is `extend`. */
|
|
47
|
+
export function resolveProviderBrandPalette(inherited, supplied, value, mode = providerBrandPaletteDefaults.mode) {
|
|
48
|
+
validateProviderBrandPaletteMode(mode);
|
|
43
49
|
if (value !== undefined)
|
|
44
50
|
return { ...inherited, [value.environment.theme]: value.palette.theme };
|
|
45
|
-
|
|
51
|
+
if (supplied === undefined || inherited === undefined)
|
|
52
|
+
return supplied ?? inherited;
|
|
53
|
+
if (mode === "replace")
|
|
54
|
+
return supplied;
|
|
55
|
+
const merged = {};
|
|
56
|
+
for (const theme of ["light", "dark"]) {
|
|
57
|
+
if (inherited[theme] === undefined && supplied[theme] === undefined)
|
|
58
|
+
continue;
|
|
59
|
+
merged[theme] = { ...inherited[theme], ...supplied[theme] };
|
|
60
|
+
}
|
|
61
|
+
return merged;
|
|
46
62
|
}
|
|
47
63
|
const themeColorKeys = Object.keys(THEMES.light);
|
|
48
64
|
const accentColorKeys = Object.keys(ACCENTS.light);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"design-system-provider.js","sourceRoot":"","sources":["../src/design-system-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import type { HjmDesignProfile } from \"./design-profile.js\";\nimport type { ColorReferencePalette } from \"./color-references.js\";\nimport { control, largeTextThreshold } from \"./foundations.js\";\nimport {\n ACCENTS,\n THEMES,\n accentFill,\n isThemePreference,\n type ResolvedTheme,\n type ThemeColors,\n type ThemePreference,\n} from \"./colors.js\";\n\n/**\n * Canonical logical direction. Existing public component-specific names stay\n * source-compatible as aliases of this type instead of redeclaring the union.\n */\nexport type DesignSystemDirection = \"ltr\" | \"rtl\";\n\n/**\n * A continuous OS/user font-scale multiplier (iOS Dynamic Type, Android font\n * size, browser zoom) — not `ShowcaseTextScale`'s closed `1 | 1.5 | 2`, which\n * only names Showcase's five fixture stories, or `description-list.ts`'s\n * local layout clamp. This is the single upstream signal both now consume.\n */\nexport type DesignSystemTextScale = number;\n\n/**\n * Whether a resolved `textScale` has crossed into large-text layout. A\n * stylesheet cannot compare numbers, so the provider resolves the axis once and\n * publishes the result for surfaces that can only match a flag (#20).\n */\nexport function isLargeTextScale(textScale: DesignSystemTextScale): boolean {\n return Number.isFinite(textScale) && textScale >= largeTextThreshold;\n}\n\n/**\n * Visible height a compact control paints under a product's target-size policy.\n *\n * The compact recipes stay at 36 and reach the 44pt target through hit slop,\n * which satisfies WCAG 2.5.8 but not the stricter iOS/Android guidance some\n * products commit to. `minimumVisualTarget` turns that commitment into one\n * resolved axis, so both renderers compute the same geometry instead of each\n * consumer re-adding `minHeight` in product styles. It lives beside the axis\n * rather than in `foundations` because it is a policy over a token, not a token.\n */\nexport function visibleControlHeight(\n recipeHeight: number,\n minimumVisualTarget: boolean,\n): number {\n return minimumVisualTarget ? Math.max(recipeHeight, control.minTouchTarget) : recipeHeight;\n}\n\n/**\n * 한 화면 안에서 목록·메뉴·표가 각각 다른 밀도로 그려지던 문제를 하나의 축으로 모은다.\n * 지금까지는 `ListRow density`, `Menu density`, DataTable의 행 높이가 서로 모르는 값이라\n * 제품이 세 군데를 따로 맞췄다. 컴포넌트의 명시적 prop이 언제나 이 축을 이긴다 —\n * 전역값은 기본이지 강제가 아니다.\n *\n * OS 신호가 없다. 밀도는 제품의 입장(같은 화면에 얼마나 담을 것인가)이지 사용자 설정이\n * 아니라서 `system*` 짝을 두지 않았다. 반대로 큰 글자 설정은 사용자 설정이므로\n * `textScale`이 큰 상태에서 `compact`를 쓰는 것은 제품이 스스로 막아야 한다.\n */\nexport type DesignSystemDensity = \"comfortable\" | \"compact\";\n\n/**\n * 전역 밀도를 컴포넌트마다 다른 밀도 어휘로 옮긴다. 컴포넌트의 명시적 prop이 언제나\n * 이긴다 — 전역값은 기본이지 강제가 아니다. 어휘를 하나로 통일하지 않은 이유: 목록의\n * `relaxed`와 표의 `regular`는 같은 말이 아니고, 억지로 합치면 둘 중 하나가 거짓말을 한다.\n */\nexport function resolveDensityDefault<Comfortable extends string, Compact extends string>(\n density: DesignSystemDensity,\n vocabulary: Readonly<{ comfortable: Comfortable; compact: Compact }>,\n): Comfortable | Compact {\n return density === \"compact\" ? vocabulary.compact : vocabulary.comfortable;\n}\n\nexport type DesignSystemEnvironmentInput = Readonly<{\n theme?: ThemePreference;\n direction?: DesignSystemDirection;\n textScale?: DesignSystemTextScale;\n reducedMotion?: boolean;\n /**\n * Paint the minimum touch target as visible control geometry instead of\n * reaching it with hit slop. This is a product accessibility stance, not an\n * OS signal, so it has no `system*` counterpart.\n */\n minimumVisualTarget?: boolean;\n /** Default row/menu/table density for everything below this provider. */\n density?: DesignSystemDensity;\n}>;\n\nexport const designSystemEnvironmentDefaults = {\n theme: \"system\",\n direction: \"ltr\",\n textScale: 1,\n reducedMotion: false,\n minimumVisualTarget: false,\n density: \"comfortable\",\n} as const satisfies Readonly<{\n theme: ThemePreference;\n direction: DesignSystemDirection;\n textScale: DesignSystemTextScale;\n reducedMotion: boolean;\n minimumVisualTarget: boolean;\n density: DesignSystemDensity;\n}>;\n\nexport type ResolvedDesignSystemEnvironment = Readonly<{\n theme: ResolvedTheme;\n direction: DesignSystemDirection;\n textScale: DesignSystemTextScale;\n reducedMotion: boolean;\n minimumVisualTarget: boolean;\n density: DesignSystemDensity;\n}>;\n\nexport type ResolveDesignSystemEnvironmentOptions = Readonly<{\n /**\n * The platform's current OS-level scheme, consulted only when `theme`\n * resolves to `\"system\"`. Renderers detect this themselves\n * (`Appearance.getColorScheme()`, `matchMedia('(prefers-color-scheme)')`)\n * — this package never queries the OS.\n */\n systemTheme: ResolvedTheme;\n /** Optional OS/renderer signals used when neither input nor a parent supplies the axis. */\n systemDirection?: DesignSystemDirection;\n systemTextScale?: DesignSystemTextScale;\n systemReducedMotion?: boolean;\n /**\n * Product brand colors layered over the HJM semantic keys. The key set is\n * unchanged, so recipes and contrast rules keep applying. Without this entry\n * point a consumer has to build its own token layer and override the CSS\n * variables, which is a copy of the canonical palette. Only the supplied\n * keys are replaced; the rest keep the HJM defaults.\n */\n brandPalette?: Readonly<Partial<Record<ResolvedTheme, Readonly<Partial<ThemeColors>>>>>;\n /** Use defineHjmDesignProfile once at the product boundary; importing its registry\n * here at runtime would force every granular component to bundle all reference packs. */\n designProfile?: HjmDesignProfile;\n /** A nested renderer inherits the already-resolved parent before consulting OS defaults. */\n parent?: ResolvedDesignSystemEnvironment;\n}>;\n\nexport type DesignSystemProviderValue = Readonly<{\n environment: ResolvedDesignSystemEnvironment;\n /** Palette consumed directly by `resolveColorReference`. */\n palette: ColorReferencePalette;\n /** Optional to preserve existing pre-resolved provider values. */\n designProfile?: HjmDesignProfile;\n}>;\n\n/** A resolved-value bridge still owns its current color scope. Preserve it for nested\n * providers. An explicit brandPalette still replaces the inherited overrides (scope reset contract). */\nexport function resolveProviderBrandPalette(\n inherited: ResolveDesignSystemEnvironmentOptions[\"brandPalette\"],\n supplied: ResolveDesignSystemEnvironmentOptions[\"brandPalette\"],\n value?: DesignSystemProviderValue,\n): ResolveDesignSystemEnvironmentOptions[\"brandPalette\"] {\n if (value !== undefined) return { ...inherited, [value.environment.theme]: value.palette.theme };\n return supplied ?? inherited;\n}\n\nconst themeColorKeys = Object.keys(THEMES.light) as readonly (keyof typeof THEMES.light)[];\nconst accentColorKeys = Object.keys(ACCENTS.light) as readonly (keyof typeof ACCENTS.light)[];\nconst sixDigitHexColor = /^#[0-9a-f]{6}$/i;\n\nfunction assertColorRecord(\n value: unknown,\n keys: readonly string[],\n field: string,\n): asserts value is Readonly<Record<string, string>> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n throw new TypeError(`DesignSystemProviderValue ${field} must be a color record`);\n }\n const record = value as Readonly<Record<string, unknown>>;\n for (const key of keys) {\n const color = record[key];\n if (typeof color !== \"string\" || !sixDigitHexColor.test(color)) {\n throw new TypeError(\n `DesignSystemProviderValue ${field}.${key} must be a six-digit hex color`,\n );\n }\n }\n}\n\n/**\n * Runtime boundary for the resolved palette a renderer receives, including one\n * merged from a partial `brandPalette`: after merging, every semantic role a\n * recipe reads must be present, and alpha composition requires six-digit hex.\n * Brand rules: docs/brand-boundary.md.\n */\nexport function validateDesignSystemProviderValue(\n value: DesignSystemProviderValue,\n): void {\n if (value === null || typeof value !== \"object\") {\n throw new TypeError(\"DesignSystemProviderValue must be an object\");\n }\n if (value.environment === null || typeof value.environment !== \"object\") {\n throw new TypeError(\"DesignSystemProviderValue environment must be an object\");\n }\n validateResolvedDesignSystemEnvironment(value.environment);\n const palette = value.palette;\n if (palette === null || typeof palette !== \"object\") {\n throw new TypeError(\"DesignSystemProviderValue palette must be an object\");\n }\n assertColorRecord(palette.theme, themeColorKeys, \"palette.theme\");\n assertColorRecord(\n palette.statusAccents,\n accentColorKeys,\n \"palette.statusAccents\",\n );\n assertColorRecord(\n palette.statusAccentFills,\n accentColorKeys,\n \"palette.statusAccentFills\",\n );\n}\n\nfunction assertBoolean(value: boolean, field: string): void {\n if (typeof value !== \"boolean\") {\n throw new TypeError(`DesignSystemEnvironment ${field} must be a boolean`);\n }\n}\n\nfunction assertDirection(value: DesignSystemDirection, field: string): void {\n if (value !== \"ltr\" && value !== \"rtl\") {\n throw new TypeError(`Unsupported DesignSystemEnvironment ${field}: ${String(value)}`);\n }\n}\n\nfunction assertTextScale(value: DesignSystemTextScale, field: string): void {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n throw new RangeError(\n `DesignSystemEnvironment ${field} must be a finite number greater than 0`,\n );\n }\n}\n\nfunction assertDensity(value: unknown, field: string): asserts value is DesignSystemDensity {\n if (value !== \"comfortable\" && value !== \"compact\") {\n throw new TypeError(`Unsupported DesignSystemEnvironment ${field}: ${String(value)}`);\n }\n}\n\nexport function validateDesignSystemEnvironmentInput(\n input: DesignSystemEnvironmentInput,\n): void {\n if (input.theme !== undefined && !isThemePreference(input.theme)) {\n throw new TypeError(`Unsupported DesignSystemEnvironment theme: ${String(input.theme)}`);\n }\n if (\n input.direction !== undefined &&\n input.direction !== \"ltr\" &&\n input.direction !== \"rtl\"\n ) {\n throw new TypeError(\n `Unsupported DesignSystemEnvironment direction: ${String(input.direction)}`,\n );\n }\n if (input.textScale !== undefined) {\n assertTextScale(input.textScale, \"textScale\");\n }\n if (input.reducedMotion !== undefined) {\n assertBoolean(input.reducedMotion, \"reducedMotion\");\n }\n if (input.minimumVisualTarget !== undefined) {\n assertBoolean(input.minimumVisualTarget, \"minimumVisualTarget\");\n }\n if (input.density !== undefined) {\n assertDensity(input.density, \"density\");\n }\n}\n\n/**\n * A parent has already crossed the system-preference boundary. Unlike the\n * partial input validator, this rejects `\"system\"`, missing axes, and every\n * malformed resolved value instead of silently resolving them again.\n */\nexport function validateResolvedDesignSystemEnvironment(\n environment: ResolvedDesignSystemEnvironment,\n): void {\n if (environment.theme !== \"light\" && environment.theme !== \"dark\") {\n throw new TypeError(\n `Unsupported ResolvedDesignSystemEnvironment theme: ${String(environment.theme)}`,\n );\n }\n assertDirection(environment.direction, \"parent direction\");\n assertTextScale(environment.textScale, \"parent textScale\");\n assertBoolean(environment.reducedMotion, \"parent reducedMotion\");\n assertBoolean(environment.minimumVisualTarget, \"parent minimumVisualTarget\");\n assertDensity(environment.density, \"parent density\");\n}\n\n/**\n * Merges partial signals with safe defaults and resolves `\"system\"` against\n * the renderer-supplied `systemTheme`. This — not a React/RN context, which\n * this package cannot own — is the entire portable contract behind antd\n * `ConfigProvider`: see docs/design-system-provider.md for what was\n * deliberately left to the renderer.\n */\nexport function resolveDesignSystemEnvironment(\n input: DesignSystemEnvironmentInput,\n options: ResolveDesignSystemEnvironmentOptions,\n): ResolvedDesignSystemEnvironment {\n validateDesignSystemEnvironmentInput(input);\n if (options.systemTheme !== \"light\" && options.systemTheme !== \"dark\") {\n throw new TypeError(`Unsupported DesignSystemEnvironment systemTheme: ${String(options.systemTheme)}`);\n }\n if (options.systemDirection !== undefined) {\n assertDirection(options.systemDirection, \"systemDirection\");\n }\n if (options.systemTextScale !== undefined) {\n assertTextScale(options.systemTextScale, \"systemTextScale\");\n }\n if (options.systemReducedMotion !== undefined) {\n assertBoolean(options.systemReducedMotion, \"systemReducedMotion\");\n }\n if (options.parent !== undefined) {\n validateResolvedDesignSystemEnvironment(options.parent);\n }\n\n const theme =\n input.theme ?? options.parent?.theme ?? designSystemEnvironmentDefaults.theme;\n return {\n theme: theme === \"system\" ? options.systemTheme : theme,\n direction:\n input.direction ??\n options.parent?.direction ??\n options.systemDirection ??\n designSystemEnvironmentDefaults.direction,\n textScale:\n input.textScale ??\n options.parent?.textScale ??\n options.systemTextScale ??\n designSystemEnvironmentDefaults.textScale,\n reducedMotion:\n input.reducedMotion ??\n options.parent?.reducedMotion ??\n options.systemReducedMotion ??\n designSystemEnvironmentDefaults.reducedMotion,\n minimumVisualTarget:\n input.minimumVisualTarget ??\n options.parent?.minimumVisualTarget ??\n designSystemEnvironmentDefaults.minimumVisualTarget,\n density:\n input.density ??\n options.parent?.density ??\n designSystemEnvironmentDefaults.density,\n };\n}\n\n/**\n * Resolves the portable Provider value without owning React/RN Context. A\n * renderer stores this object in its own context and feeds `palette` directly\n * to recipe color resolution.\n */\nexport function resolveDesignSystemProviderValue(\n input: DesignSystemEnvironmentInput,\n options: ResolveDesignSystemEnvironmentOptions,\n): DesignSystemProviderValue {\n const environment = resolveDesignSystemEnvironment(input, options);\n const brandOverride = options.brandPalette?.[environment.theme];\n const basePalette = options.designProfile?.palette[environment.theme] ?? THEMES[environment.theme];\n const value = {\n environment,\n ...(options.designProfile === undefined ? {} : { designProfile: options.designProfile }),\n palette: {\n theme: brandOverride === undefined\n ? basePalette\n : { ...basePalette, ...brandOverride },\n statusAccents: ACCENTS[environment.theme],\n statusAccentFills: accentFill,\n },\n };\n validateDesignSystemProviderValue(value);\n return value;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"design-system-provider.js","sourceRoot":"","sources":["../src/design-system-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import type { HjmDesignProfile } from \"./design-profile.js\";\nimport type { ColorReferencePalette } from \"./color-references.js\";\nimport { control, largeTextThreshold } from \"./foundations.js\";\nimport {\n ACCENTS,\n THEMES,\n accentFill,\n isThemePreference,\n type ResolvedTheme,\n type ThemeColors,\n type ThemePreference,\n} from \"./colors.js\";\n\n/**\n * Canonical logical direction. Existing public component-specific names stay\n * source-compatible as aliases of this type instead of redeclaring the union.\n */\nexport type DesignSystemDirection = \"ltr\" | \"rtl\";\n\n/**\n * A continuous OS/user font-scale multiplier (iOS Dynamic Type, Android font\n * size, browser zoom) — not `ShowcaseTextScale`'s closed `1 | 1.5 | 2`, which\n * only names Showcase's five fixture stories, or `description-list.ts`'s\n * local layout clamp. This is the single upstream signal both now consume.\n */\nexport type DesignSystemTextScale = number;\n\n/**\n * Whether a resolved `textScale` has crossed into large-text layout. A\n * stylesheet cannot compare numbers, so the provider resolves the axis once and\n * publishes the result for surfaces that can only match a flag (#20).\n */\nexport function isLargeTextScale(textScale: DesignSystemTextScale): boolean {\n return Number.isFinite(textScale) && textScale >= largeTextThreshold;\n}\n\n/**\n * Visible height a compact control paints under a product's target-size policy.\n *\n * The compact recipes stay at 36 and reach the 44pt target through hit slop,\n * which satisfies WCAG 2.5.8 but not the stricter iOS/Android guidance some\n * products commit to. `minimumVisualTarget` turns that commitment into one\n * resolved axis, so both renderers compute the same geometry instead of each\n * consumer re-adding `minHeight` in product styles. It lives beside the axis\n * rather than in `foundations` because it is a policy over a token, not a token.\n */\nexport function visibleControlHeight(\n recipeHeight: number,\n minimumVisualTarget: boolean,\n): number {\n return minimumVisualTarget ? Math.max(recipeHeight, control.minTouchTarget) : recipeHeight;\n}\n\n/**\n * 한 화면 안에서 목록·메뉴·표가 각각 다른 밀도로 그려지던 문제를 하나의 축으로 모은다.\n * 지금까지는 `ListRow density`, `Menu density`, DataTable의 행 높이가 서로 모르는 값이라\n * 제품이 세 군데를 따로 맞췄다. 컴포넌트의 명시적 prop이 언제나 이 축을 이긴다 —\n * 전역값은 기본이지 강제가 아니다.\n *\n * OS 신호가 없다. 밀도는 제품의 입장(같은 화면에 얼마나 담을 것인가)이지 사용자 설정이\n * 아니라서 `system*` 짝을 두지 않았다. 반대로 큰 글자 설정은 사용자 설정이므로\n * `textScale`이 큰 상태에서 `compact`를 쓰는 것은 제품이 스스로 막아야 한다.\n */\nexport type DesignSystemDensity = \"comfortable\" | \"compact\";\n\n/**\n * 전역 밀도를 컴포넌트마다 다른 밀도 어휘로 옮긴다. 컴포넌트의 명시적 prop이 언제나\n * 이긴다 — 전역값은 기본이지 강제가 아니다. 어휘를 하나로 통일하지 않은 이유: 목록의\n * `relaxed`와 표의 `regular`는 같은 말이 아니고, 억지로 합치면 둘 중 하나가 거짓말을 한다.\n */\nexport function resolveDensityDefault<Comfortable extends string, Compact extends string>(\n density: DesignSystemDensity,\n vocabulary: Readonly<{ comfortable: Comfortable; compact: Compact }>,\n): Comfortable | Compact {\n return density === \"compact\" ? vocabulary.compact : vocabulary.comfortable;\n}\n\nexport type DesignSystemEnvironmentInput = Readonly<{\n theme?: ThemePreference;\n direction?: DesignSystemDirection;\n textScale?: DesignSystemTextScale;\n reducedMotion?: boolean;\n /**\n * Paint the minimum touch target as visible control geometry instead of\n * reaching it with hit slop. This is a product accessibility stance, not an\n * OS signal, so it has no `system*` counterpart.\n */\n minimumVisualTarget?: boolean;\n /** Default row/menu/table density for everything below this provider. */\n density?: DesignSystemDensity;\n}>;\n\nexport const designSystemEnvironmentDefaults = {\n theme: \"system\",\n direction: \"ltr\",\n textScale: 1,\n reducedMotion: false,\n minimumVisualTarget: false,\n density: \"comfortable\",\n} as const satisfies Readonly<{\n theme: ThemePreference;\n direction: DesignSystemDirection;\n textScale: DesignSystemTextScale;\n reducedMotion: boolean;\n minimumVisualTarget: boolean;\n density: DesignSystemDensity;\n}>;\n\nexport type ResolvedDesignSystemEnvironment = Readonly<{\n theme: ResolvedTheme;\n direction: DesignSystemDirection;\n textScale: DesignSystemTextScale;\n reducedMotion: boolean;\n minimumVisualTarget: boolean;\n density: DesignSystemDensity;\n}>;\n\nexport type ResolveDesignSystemEnvironmentOptions = Readonly<{\n /**\n * The platform's current OS-level scheme, consulted only when `theme`\n * resolves to `\"system\"`. Renderers detect this themselves\n * (`Appearance.getColorScheme()`, `matchMedia('(prefers-color-scheme)')`)\n * — this package never queries the OS.\n */\n systemTheme: ResolvedTheme;\n /** Optional OS/renderer signals used when neither input nor a parent supplies the axis. */\n systemDirection?: DesignSystemDirection;\n systemTextScale?: DesignSystemTextScale;\n systemReducedMotion?: boolean;\n /**\n * Product brand colors layered over the HJM semantic keys. The key set is\n * unchanged, so recipes and contrast rules keep applying. Without this entry\n * point a consumer has to build its own token layer and override the CSS\n * variables, which is a copy of the canonical palette. Only the supplied\n * keys are replaced; the rest keep the HJM defaults.\n */\n brandPalette?: Readonly<Partial<Record<ResolvedTheme, Readonly<Partial<ThemeColors>>>>>;\n /** Use defineHjmDesignProfile once at the product boundary; importing its registry\n * here at runtime would force every granular component to bundle all reference packs. */\n designProfile?: HjmDesignProfile;\n /** A nested renderer inherits the already-resolved parent before consulting OS defaults. */\n parent?: ResolvedDesignSystemEnvironment;\n}>;\n\nexport type DesignSystemProviderValue = Readonly<{\n environment: ResolvedDesignSystemEnvironment;\n /** Palette consumed directly by `resolveColorReference`. */\n palette: ColorReferencePalette;\n /** Optional to preserve existing pre-resolved provider values. */\n designProfile?: HjmDesignProfile;\n}>;\n\n/**\n * How a nested provider's `brandPalette` meets the inherited one. `replace` (default, the scope reset contract)\n * starts the subtree from the HJM defaults plus only the supplied roles. `extend` merges the supplied roles over the\n * inherited palette per theme, so a sub-scope names only the roles it changes. 2026-10-23: BurnTok web/app\n * ThemeProviders accumulated outer overrides by hand and Diairy built `shoreBrandPaletteWith()` to get this.\n */\nexport type ProviderBrandPaletteMode = \"replace\" | \"extend\";\nexport const providerBrandPaletteDefaults = { mode: \"replace\" } as const satisfies { mode: ProviderBrandPaletteMode };\n\nexport function validateProviderBrandPaletteMode(mode: unknown): asserts mode is ProviderBrandPaletteMode {\n if (mode !== \"replace\" && mode !== \"extend\") throw new TypeError(`Unsupported brandPaletteMode: ${String(mode)}`);\n}\n\n/** A resolved-value bridge still owns its current color scope. Preserve it for nested\n * providers. An explicit brandPalette replaces the inherited overrides unless `mode` is `extend`. */\nexport function resolveProviderBrandPalette(\n inherited: ResolveDesignSystemEnvironmentOptions[\"brandPalette\"],\n supplied: ResolveDesignSystemEnvironmentOptions[\"brandPalette\"],\n value?: DesignSystemProviderValue,\n mode: ProviderBrandPaletteMode = providerBrandPaletteDefaults.mode,\n): ResolveDesignSystemEnvironmentOptions[\"brandPalette\"] {\n validateProviderBrandPaletteMode(mode);\n if (value !== undefined) return { ...inherited, [value.environment.theme]: value.palette.theme };\n if (supplied === undefined || inherited === undefined) return supplied ?? inherited;\n if (mode === \"replace\") return supplied;\n const merged: Partial<Record<ResolvedTheme, Readonly<Partial<ThemeColors>>>> = {};\n for (const theme of [\"light\", \"dark\"] as const) {\n if (inherited[theme] === undefined && supplied[theme] === undefined) continue;\n merged[theme] = { ...inherited[theme], ...supplied[theme] };\n }\n return merged;\n}\n\nconst themeColorKeys = Object.keys(THEMES.light) as readonly (keyof typeof THEMES.light)[];\nconst accentColorKeys = Object.keys(ACCENTS.light) as readonly (keyof typeof ACCENTS.light)[];\nconst sixDigitHexColor = /^#[0-9a-f]{6}$/i;\n\nfunction assertColorRecord(\n value: unknown,\n keys: readonly string[],\n field: string,\n): asserts value is Readonly<Record<string, string>> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n throw new TypeError(`DesignSystemProviderValue ${field} must be a color record`);\n }\n const record = value as Readonly<Record<string, unknown>>;\n for (const key of keys) {\n const color = record[key];\n if (typeof color !== \"string\" || !sixDigitHexColor.test(color)) {\n throw new TypeError(\n `DesignSystemProviderValue ${field}.${key} must be a six-digit hex color`,\n );\n }\n }\n}\n\n/**\n * Runtime boundary for the resolved palette a renderer receives, including one\n * merged from a partial `brandPalette`: after merging, every semantic role a\n * recipe reads must be present, and alpha composition requires six-digit hex.\n * Brand rules: docs/brand-boundary.md.\n */\nexport function validateDesignSystemProviderValue(\n value: DesignSystemProviderValue,\n): void {\n if (value === null || typeof value !== \"object\") {\n throw new TypeError(\"DesignSystemProviderValue must be an object\");\n }\n if (value.environment === null || typeof value.environment !== \"object\") {\n throw new TypeError(\"DesignSystemProviderValue environment must be an object\");\n }\n validateResolvedDesignSystemEnvironment(value.environment);\n const palette = value.palette;\n if (palette === null || typeof palette !== \"object\") {\n throw new TypeError(\"DesignSystemProviderValue palette must be an object\");\n }\n assertColorRecord(palette.theme, themeColorKeys, \"palette.theme\");\n assertColorRecord(\n palette.statusAccents,\n accentColorKeys,\n \"palette.statusAccents\",\n );\n assertColorRecord(\n palette.statusAccentFills,\n accentColorKeys,\n \"palette.statusAccentFills\",\n );\n}\n\nfunction assertBoolean(value: boolean, field: string): void {\n if (typeof value !== \"boolean\") {\n throw new TypeError(`DesignSystemEnvironment ${field} must be a boolean`);\n }\n}\n\nfunction assertDirection(value: DesignSystemDirection, field: string): void {\n if (value !== \"ltr\" && value !== \"rtl\") {\n throw new TypeError(`Unsupported DesignSystemEnvironment ${field}: ${String(value)}`);\n }\n}\n\nfunction assertTextScale(value: DesignSystemTextScale, field: string): void {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n throw new RangeError(\n `DesignSystemEnvironment ${field} must be a finite number greater than 0`,\n );\n }\n}\n\nfunction assertDensity(value: unknown, field: string): asserts value is DesignSystemDensity {\n if (value !== \"comfortable\" && value !== \"compact\") {\n throw new TypeError(`Unsupported DesignSystemEnvironment ${field}: ${String(value)}`);\n }\n}\n\nexport function validateDesignSystemEnvironmentInput(\n input: DesignSystemEnvironmentInput,\n): void {\n if (input.theme !== undefined && !isThemePreference(input.theme)) {\n throw new TypeError(`Unsupported DesignSystemEnvironment theme: ${String(input.theme)}`);\n }\n if (\n input.direction !== undefined &&\n input.direction !== \"ltr\" &&\n input.direction !== \"rtl\"\n ) {\n throw new TypeError(\n `Unsupported DesignSystemEnvironment direction: ${String(input.direction)}`,\n );\n }\n if (input.textScale !== undefined) {\n assertTextScale(input.textScale, \"textScale\");\n }\n if (input.reducedMotion !== undefined) {\n assertBoolean(input.reducedMotion, \"reducedMotion\");\n }\n if (input.minimumVisualTarget !== undefined) {\n assertBoolean(input.minimumVisualTarget, \"minimumVisualTarget\");\n }\n if (input.density !== undefined) {\n assertDensity(input.density, \"density\");\n }\n}\n\n/**\n * A parent has already crossed the system-preference boundary. Unlike the\n * partial input validator, this rejects `\"system\"`, missing axes, and every\n * malformed resolved value instead of silently resolving them again.\n */\nexport function validateResolvedDesignSystemEnvironment(\n environment: ResolvedDesignSystemEnvironment,\n): void {\n if (environment.theme !== \"light\" && environment.theme !== \"dark\") {\n throw new TypeError(\n `Unsupported ResolvedDesignSystemEnvironment theme: ${String(environment.theme)}`,\n );\n }\n assertDirection(environment.direction, \"parent direction\");\n assertTextScale(environment.textScale, \"parent textScale\");\n assertBoolean(environment.reducedMotion, \"parent reducedMotion\");\n assertBoolean(environment.minimumVisualTarget, \"parent minimumVisualTarget\");\n assertDensity(environment.density, \"parent density\");\n}\n\n/**\n * Merges partial signals with safe defaults and resolves `\"system\"` against\n * the renderer-supplied `systemTheme`. This — not a React/RN context, which\n * this package cannot own — is the entire portable contract behind antd\n * `ConfigProvider`: see docs/design-system-provider.md for what was\n * deliberately left to the renderer.\n */\nexport function resolveDesignSystemEnvironment(\n input: DesignSystemEnvironmentInput,\n options: ResolveDesignSystemEnvironmentOptions,\n): ResolvedDesignSystemEnvironment {\n validateDesignSystemEnvironmentInput(input);\n if (options.systemTheme !== \"light\" && options.systemTheme !== \"dark\") {\n throw new TypeError(`Unsupported DesignSystemEnvironment systemTheme: ${String(options.systemTheme)}`);\n }\n if (options.systemDirection !== undefined) {\n assertDirection(options.systemDirection, \"systemDirection\");\n }\n if (options.systemTextScale !== undefined) {\n assertTextScale(options.systemTextScale, \"systemTextScale\");\n }\n if (options.systemReducedMotion !== undefined) {\n assertBoolean(options.systemReducedMotion, \"systemReducedMotion\");\n }\n if (options.parent !== undefined) {\n validateResolvedDesignSystemEnvironment(options.parent);\n }\n\n const theme =\n input.theme ?? options.parent?.theme ?? designSystemEnvironmentDefaults.theme;\n return {\n theme: theme === \"system\" ? options.systemTheme : theme,\n direction:\n input.direction ??\n options.parent?.direction ??\n options.systemDirection ??\n designSystemEnvironmentDefaults.direction,\n textScale:\n input.textScale ??\n options.parent?.textScale ??\n options.systemTextScale ??\n designSystemEnvironmentDefaults.textScale,\n reducedMotion:\n input.reducedMotion ??\n options.parent?.reducedMotion ??\n options.systemReducedMotion ??\n designSystemEnvironmentDefaults.reducedMotion,\n minimumVisualTarget:\n input.minimumVisualTarget ??\n options.parent?.minimumVisualTarget ??\n designSystemEnvironmentDefaults.minimumVisualTarget,\n density:\n input.density ??\n options.parent?.density ??\n designSystemEnvironmentDefaults.density,\n };\n}\n\n/**\n * Resolves the portable Provider value without owning React/RN Context. A\n * renderer stores this object in its own context and feeds `palette` directly\n * to recipe color resolution.\n */\nexport function resolveDesignSystemProviderValue(\n input: DesignSystemEnvironmentInput,\n options: ResolveDesignSystemEnvironmentOptions,\n): DesignSystemProviderValue {\n const environment = resolveDesignSystemEnvironment(input, options);\n const brandOverride = options.brandPalette?.[environment.theme];\n const basePalette = options.designProfile?.palette[environment.theme] ?? THEMES[environment.theme];\n const value = {\n environment,\n ...(options.designProfile === undefined ? {} : { designProfile: options.designProfile }),\n palette: {\n theme: brandOverride === undefined\n ? basePalette\n : { ...basePalette, ...brandOverride },\n statusAccents: ACCENTS[environment.theme],\n statusAccentFills: accentFill,\n },\n };\n validateDesignSystemProviderValue(value);\n return value;\n}\n"]}
|
package/dist/foundations.d.ts
CHANGED
|
@@ -331,4 +331,19 @@ export declare const shadow: {
|
|
|
331
331
|
readonly offsetY: 8;
|
|
332
332
|
};
|
|
333
333
|
};
|
|
334
|
+
/**
|
|
335
|
+
* Public elevation steps: `none` or a `shadow` token. 2026-10-23: Burntok kept a RaisedControl View under HJM controls
|
|
336
|
+
* and passed `shadow-lg ring-2` classes to IconButton/Surface because their layoutStyle cannot carry a shadow. Steps
|
|
337
|
+
* name the existing tokens (design profiles override them) instead of opening a free shadow style.
|
|
338
|
+
*/
|
|
339
|
+
export type ElevationStep = "none" | keyof typeof shadow;
|
|
340
|
+
export declare const elevationSteps: readonly ["none", "raised", "floating", "overlay"];
|
|
341
|
+
/** Android `elevation` when no design profile supplies shadow tokens (the existing raised 4 / floating 8 fallbacks). */
|
|
342
|
+
export declare const nativeElevationFallback: {
|
|
343
|
+
readonly none: 0;
|
|
344
|
+
readonly raised: 4;
|
|
345
|
+
readonly floating: 8;
|
|
346
|
+
readonly overlay: 16;
|
|
347
|
+
};
|
|
348
|
+
export declare function validateElevationStep(step: string, owner: string): asserts step is ElevationStep;
|
|
334
349
|
//# sourceMappingURL=foundations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foundations.d.ts","sourceRoot":"","sources":["../src/foundations.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"foundations.d.ts","sourceRoot":"","sources":["../src/foundations.ts"],"names":[],"mappings":"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"}
|
package/dist/foundations.js
CHANGED
|
@@ -299,4 +299,11 @@ export const shadow = {
|
|
|
299
299
|
offsetY: 8,
|
|
300
300
|
},
|
|
301
301
|
};
|
|
302
|
+
export const elevationSteps = ["none", "raised", "floating", "overlay"];
|
|
303
|
+
/** Android `elevation` when no design profile supplies shadow tokens (the existing raised 4 / floating 8 fallbacks). */
|
|
304
|
+
export const nativeElevationFallback = { none: 0, raised: 4, floating: 8, overlay: 16 };
|
|
305
|
+
export function validateElevationStep(step, owner) {
|
|
306
|
+
if (!elevationSteps.includes(step))
|
|
307
|
+
throw new TypeError(`Unsupported ${owner} elevation: ${step}`);
|
|
308
|
+
}
|
|
302
309
|
//# sourceMappingURL=foundations.js.map
|
package/dist/foundations.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"foundations.js","sourceRoot":"","sources":["../src/foundations.ts"],"names":[],"mappings":"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","sourcesContent":["/** Numeric units are consumed as CSS pixels on web and density-independent points on native. */\nexport const spacing = {\n xxs: 4,\n xs: 8,\n sm: 12,\n md: 16,\n lg: 20,\n xl: 24,\n xxl: 32,\n xxxl: 40,\n} as const;\n\nexport const radius = {\n sm: 8,\n md: 12,\n lg: 16,\n xl: 24,\n full: 999,\n} as const;\n\n/**\n * Ordered fallbacks keep the contract platform-neutral: Web renderers join\n * the list as a CSS stack, while native renderers request the first named\n * family (or their OS default mapping), rather than receiving a CSS stack.\n */\nexport const fontFamily = {\n // Pretendard is bundled by HJM (Web `@hjmds/react/fonts/pretendard.css`, Native `@hjmds/react-native/fonts`)\n // so every device renders the same face (2026-10-17: Inter/Pretendard were listed but never loaded, so the\n // result depended on what each device had installed). System fonts remain the fallback until it loads.\n ui: [\n \"Pretendard Variable\",\n \"Pretendard\",\n \"-apple-system\",\n \"BlinkMacSystemFont\",\n \"Segoe UI\",\n \"sans-serif\",\n ],\n // Chrome ignores ui-monospace and cannot address SF Mono as \"SFMono-Regular\", so name the macOS/\n // Windows monospace faces before the generic fallback (2026-10-17: Chrome rendered code in Courier).\n code: [\n \"ui-monospace\",\n \"SFMono-Regular\",\n \"SF Mono\",\n \"Menlo\",\n \"Monaco\",\n \"Cascadia Mono\",\n \"Consolas\",\n \"Liberation Mono\",\n \"monospace\",\n ],\n} as const;\n\nexport type FontFamily = keyof typeof fontFamily;\n\n/**\n * Native has no variable-weight selection on every platform, so each weight is its own registered face.\n * Keys match the asset map exported by `@hjmds/react-native/fonts`; 400 doubles as the family name inputs use.\n */\nexport const pretendardNativeFaces = {\n \"400\": \"Pretendard\",\n \"500\": \"Pretendard-Medium\",\n \"600\": \"Pretendard-SemiBold\",\n \"700\": \"Pretendard-Bold\",\n \"800\": \"Pretendard-ExtraBold\",\n} as const;\n\n/** Nearest bundled face for a CSS/RN font weight (\"normal\", \"bold\", 100–900). */\nexport function resolvePretendardNativeFace(weight: string | number | undefined): (typeof pretendardNativeFaces)[keyof typeof pretendardNativeFaces] {\n const numeric = weight === undefined || weight === \"normal\" ? 400 : weight === \"bold\" ? 700 : Number(weight);\n const steps = [400, 500, 600, 700, 800] as const;\n const nearest = Number.isFinite(numeric) ? steps.reduce((best, step) => Math.abs(step - numeric) < Math.abs(best - numeric) ? step : best, 400) : 400;\n return pretendardNativeFaces[String(nearest) as keyof typeof pretendardNativeFaces];\n}\n\n/** Display/reading roles are optional so existing ui/code product profiles retain their fonts. */\nexport type FontRole = \"ui\" | \"display\" | \"reading\" | \"code\";\nexport type FontFamilyRoles = Readonly<{ ui: readonly string[]; code: readonly string[]; display?: readonly string[]; reading?: readonly string[] }>;\n\nexport function resolveFontFamilyStack(families: FontFamilyRoles, role: FontRole): readonly string[] {\n if (![\"ui\", \"display\", \"reading\", \"code\"].includes(role)) throw new TypeError(\"Unsupported font role\");\n // Unspecified reading/display follow the current ui stack, rather than a\n // frozen neutral stack that would silently undo an app's existing ui override.\n return families[role] ?? families.ui;\n}\n\n\n/** String weights translate unchanged to CSS and React Native text styles. */\nexport const fontWeight = {\n regular: \"400\",\n medium: \"500\",\n semibold: \"600\",\n bold: \"700\",\n heavy: \"800\",\n} as const;\n\nexport type FontWeight = keyof typeof fontWeight;\nexport type FontWeightValue = (typeof fontWeight)[FontWeight];\n\n/** Numeric tracking uses CSS pixels on Web and density-independent points on Native. */\nexport const letterSpacing = {\n tight: -0.2,\n normal: 0,\n wide: 0.2,\n} as const;\n\nexport type LetterSpacing = keyof typeof letterSpacing;\n\n/** Renderers map the shared intent to `font-variant-numeric` / `fontVariant`. */\nexport const numeric = {\n proportional: \"proportional-nums\",\n tabular: \"tabular-nums\",\n} as const;\n\nexport type NumericVariant = keyof typeof numeric;\n\nexport const typography = {\n caption: { fontSize: 11, lineHeight: 16, fontWeight: fontWeight.regular },\n // Label (form labels, section subtitles) stays 500 between body 400 and the titles: at 600 it competed\n // with titles, and Text rendered it 400 outside a profile, too weak against body (2026-10-17 user decision).\n label: { fontSize: 12, lineHeight: 18, fontWeight: fontWeight.medium },\n body: { fontSize: 14, lineHeight: 20, fontWeight: fontWeight.regular },\n bodyLarge: { fontSize: 16, lineHeight: 24, fontWeight: fontWeight.regular },\n // Title steps are medium (2026-10-17 user review: 800, then 700, then 600 still read too heavy —\n // \"굵기 좀더 줄여\").\n title: { fontSize: 18, lineHeight: 26, fontWeight: fontWeight.medium },\n titleLarge: { fontSize: 20, lineHeight: 28, fontWeight: fontWeight.medium },\n // `heading` is the largest text HJM draws. 2026-10-17 user decision (\"글자 너무 커\", \"큰 글자 정책은 없애\"):\n // the 40/32 display tier looked far too big on the service-intro screen and was removed; design profiles\n // reject any type step above this size (design-profile.ts `merge`).\n heading: { fontSize: 24, lineHeight: 32, fontWeight: fontWeight.medium },\n} as const;\n\nexport type TextVariant = keyof typeof typography;\n\n/** Visual variants choose a default family role; semantics and sizes remain independent. */\nexport function resolveTextFontRole(variant: TextVariant, role?: FontRole): FontRole {\n if (role !== undefined) {\n if (![\"ui\", \"display\", \"reading\", \"code\"].includes(role)) throw new TypeError(\"Unsupported font role\");\n return role;\n }\n if (variant === \"body\" || variant === \"bodyLarge\") return \"reading\";\n if (variant === \"title\" || variant === \"titleLarge\" || variant === \"heading\") return \"display\";\n return \"ui\";\n}\n\n\n/**\n * Document heading hierarchy without widening the established `TextVariant`\n * union. Every level reuses a semantic text style, so no heading exceeds `typography.heading`.\n */\nexport const heading = {\n /**\n * @deprecated Same as `level3` since the display tier was removed (2026-10-17 user decision, \"큰 글자\n * 정책은 없애\"; it was 40/48/600). Kept so existing consumers keep compiling; use `level3`.\n */\n level1: typography.heading,\n /** @deprecated Same as `level3` since the display tier was removed (was 32/40/600); use `level3`. */\n level2: typography.heading,\n level3: typography.heading,\n level4: typography.titleLarge,\n level5: typography.title,\n} as const;\n\nexport type HeadingLevel = keyof typeof heading;\n\n/** Glyphs include icons and avatars; they do not inherit paragraph line-height. */\nexport const glyph = {\n xs: 14,\n sm: 20,\n md: 24,\n lg: 28,\n xl: 32,\n xxl: 44,\n xxxl: 48,\n} as const;\n\nexport type GlyphSize = keyof typeof glyph;\n\nexport const motion = {\n fast: 120,\n normal: 200,\n slow: 320,\n} as const;\n\n/**\n * Curves are stored as normalized cubic-bezier tuples so CSS and native\n * animation drivers can translate the same motion intent without sharing a\n * renderer dependency.\n */\nexport const easing = {\n standard: [0.2, 0, 0, 1],\n enter: [0, 0, 0, 1],\n exit: [0.3, 0, 1, 1],\n emphasized: [0.2, 0, 0, 1],\n} as const;\n\nexport type ReducedMotionBehavior = \"instant\" | \"opacity\" | \"static\";\n\n/** Shared transition intent; renderers translate easing tuples to their animation API. */\nexport const motionPreset = {\n micro: {\n duration: motion.fast,\n easing: \"standard\",\n reducedMotion: \"instant\",\n },\n enter: {\n duration: motion.normal,\n easing: \"enter\",\n reducedMotion: \"opacity\",\n },\n exit: {\n duration: motion.fast,\n easing: \"exit\",\n reducedMotion: \"instant\",\n },\n context: {\n duration: motion.slow,\n easing: \"emphasized\",\n reducedMotion: \"opacity\",\n },\n} as const satisfies Record<\n \"micro\" | \"enter\" | \"exit\" | \"context\",\n {\n duration: number;\n easing: keyof typeof easing;\n reducedMotion: ReducedMotionBehavior;\n }\n>;\n\n/** Native renderers may use these values directly; web renderers use easing. */\nexport const spring = {\n responsive: { stiffness: 760, damping: 52, mass: 1 },\n expressive: { stiffness: 520, damping: 38, mass: 1 },\n} as const;\n\n/** Reusable state strengths. Components still decide which states are valid. */\nexport const opacity = {\n disabled: 0.5,\n muted: 0.72,\n pressed: 0.86,\n dragged: 0.64,\n} as const;\n\n/** Overlaying the content color at these strengths creates predictable states. */\nexport const stateLayer = {\n hover: 0.06,\n focus: 0.08,\n pressed: 0.1,\n selected: 0.1,\n} as const;\n\nexport const stroke = {\n subtle: 1,\n default: 1,\n strong: 2,\n focus: 2,\n} as const;\n\nexport const control = {\n minTouchTarget: 44,\n buttonHeight: {\n small: 36,\n medium: 44,\n large: 52,\n },\n buttonHitSlop: {\n small: 4,\n medium: 0,\n large: 0,\n },\n fieldHeight: 44,\n chipHeight: {\n small: 36,\n medium: 44,\n },\n selectionIndicator: 24,\n} as const;\n\n/**\n * Font scale at which components switch to a large-text layout. One decision,\n * previously two literals in `segmentedControlRecipe` and `topBarRecipe`; see\n * issue #20 for why it sits with the tokens instead of beside the scale axis.\n */\nexport const largeTextThreshold = 1.6;\n\n/** Product renderers may narrow these widths, but should not invent new rhythm. */\nexport const layout = {\n pagePadding: {\n compact: spacing.md,\n regular: spacing.lg,\n spacious: spacing.xl,\n },\n sectionGap: spacing.xl,\n contentGap: spacing.md,\n rowHeight: {\n singleLine: 56,\n twoLine: 68,\n },\n readingMaxWidth: 720,\n contentMaxWidth: 1200,\n} as const;\n\n/** Width thresholds use CSS pixels on Web and density-independent points on Native. */\nexport const breakpoint = {\n compact: 0,\n medium: 600,\n expanded: 960,\n wide: 1280,\n} as const;\n\n/** Shared stacking intent. Values remain sparse to leave room for app layers. */\nexport const layer = {\n base: 0,\n sticky: 100,\n dropdown: 400,\n overlay: 800,\n modal: 900,\n tooltip: 950,\n toast: 1000,\n} as const;\n\nexport const overlay = {\n scrim: 0.6,\n veil: 0.25,\n} as const;\n\nexport type BackdropReference = Readonly<{\n color: \"#000000\";\n opacity: number;\n}>;\n\n/** Fixed backdrop contracts avoid renderer-specific names such as CSS `scrim`. */\nexport const backdrop = {\n modal: { color: \"#000000\", opacity: overlay.scrim },\n veil: { color: \"#000000\", opacity: overlay.veil },\n} as const satisfies Record<\"modal\" | \"veil\", BackdropReference>;\n\nexport const scrim = `rgba(0, 0, 0, ${overlay.scrim})`;\n\n/** Renderers translate this contract to box-shadow or native shadow/elevation properties. */\nexport const shadow = {\n raised: {\n color: \"#000000\",\n opacity: 0.08,\n radius: 4,\n offsetY: 1,\n },\n floating: {\n color: \"#000000\",\n opacity: 0.12,\n radius: 12,\n offsetY: 4,\n },\n overlay: {\n color: \"#000000\",\n opacity: 0.16,\n radius: 24,\n offsetY: 8,\n },\n} as const;\n"]}
|
|
1
|
+
{"version":3,"file":"foundations.js","sourceRoot":"","sources":["../src/foundations.ts"],"names":[],"mappings":"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","sourcesContent":["/** Numeric units are consumed as CSS pixels on web and density-independent points on native. */\nexport const spacing = {\n xxs: 4,\n xs: 8,\n sm: 12,\n md: 16,\n lg: 20,\n xl: 24,\n xxl: 32,\n xxxl: 40,\n} as const;\n\nexport const radius = {\n sm: 8,\n md: 12,\n lg: 16,\n xl: 24,\n full: 999,\n} as const;\n\n/**\n * Ordered fallbacks keep the contract platform-neutral: Web renderers join\n * the list as a CSS stack, while native renderers request the first named\n * family (or their OS default mapping), rather than receiving a CSS stack.\n */\nexport const fontFamily = {\n // Pretendard is bundled by HJM (Web `@hjmds/react/fonts/pretendard.css`, Native `@hjmds/react-native/fonts`)\n // so every device renders the same face (2026-10-17: Inter/Pretendard were listed but never loaded, so the\n // result depended on what each device had installed). System fonts remain the fallback until it loads.\n ui: [\n \"Pretendard Variable\",\n \"Pretendard\",\n \"-apple-system\",\n \"BlinkMacSystemFont\",\n \"Segoe UI\",\n \"sans-serif\",\n ],\n // Chrome ignores ui-monospace and cannot address SF Mono as \"SFMono-Regular\", so name the macOS/\n // Windows monospace faces before the generic fallback (2026-10-17: Chrome rendered code in Courier).\n code: [\n \"ui-monospace\",\n \"SFMono-Regular\",\n \"SF Mono\",\n \"Menlo\",\n \"Monaco\",\n \"Cascadia Mono\",\n \"Consolas\",\n \"Liberation Mono\",\n \"monospace\",\n ],\n} as const;\n\nexport type FontFamily = keyof typeof fontFamily;\n\n/**\n * Native has no variable-weight selection on every platform, so each weight is its own registered face.\n * Keys match the asset map exported by `@hjmds/react-native/fonts`; 400 doubles as the family name inputs use.\n */\nexport const pretendardNativeFaces = {\n \"400\": \"Pretendard\",\n \"500\": \"Pretendard-Medium\",\n \"600\": \"Pretendard-SemiBold\",\n \"700\": \"Pretendard-Bold\",\n \"800\": \"Pretendard-ExtraBold\",\n} as const;\n\n/** Nearest bundled face for a CSS/RN font weight (\"normal\", \"bold\", 100–900). */\nexport function resolvePretendardNativeFace(weight: string | number | undefined): (typeof pretendardNativeFaces)[keyof typeof pretendardNativeFaces] {\n const numeric = weight === undefined || weight === \"normal\" ? 400 : weight === \"bold\" ? 700 : Number(weight);\n const steps = [400, 500, 600, 700, 800] as const;\n const nearest = Number.isFinite(numeric) ? steps.reduce((best, step) => Math.abs(step - numeric) < Math.abs(best - numeric) ? step : best, 400) : 400;\n return pretendardNativeFaces[String(nearest) as keyof typeof pretendardNativeFaces];\n}\n\n/** Display/reading roles are optional so existing ui/code product profiles retain their fonts. */\nexport type FontRole = \"ui\" | \"display\" | \"reading\" | \"code\";\nexport type FontFamilyRoles = Readonly<{ ui: readonly string[]; code: readonly string[]; display?: readonly string[]; reading?: readonly string[] }>;\n\nexport function resolveFontFamilyStack(families: FontFamilyRoles, role: FontRole): readonly string[] {\n if (![\"ui\", \"display\", \"reading\", \"code\"].includes(role)) throw new TypeError(\"Unsupported font role\");\n // Unspecified reading/display follow the current ui stack, rather than a\n // frozen neutral stack that would silently undo an app's existing ui override.\n return families[role] ?? families.ui;\n}\n\n\n/** String weights translate unchanged to CSS and React Native text styles. */\nexport const fontWeight = {\n regular: \"400\",\n medium: \"500\",\n semibold: \"600\",\n bold: \"700\",\n heavy: \"800\",\n} as const;\n\nexport type FontWeight = keyof typeof fontWeight;\nexport type FontWeightValue = (typeof fontWeight)[FontWeight];\n\n/** Numeric tracking uses CSS pixels on Web and density-independent points on Native. */\nexport const letterSpacing = {\n tight: -0.2,\n normal: 0,\n wide: 0.2,\n} as const;\n\nexport type LetterSpacing = keyof typeof letterSpacing;\n\n/** Renderers map the shared intent to `font-variant-numeric` / `fontVariant`. */\nexport const numeric = {\n proportional: \"proportional-nums\",\n tabular: \"tabular-nums\",\n} as const;\n\nexport type NumericVariant = keyof typeof numeric;\n\nexport const typography = {\n caption: { fontSize: 11, lineHeight: 16, fontWeight: fontWeight.regular },\n // Label (form labels, section subtitles) stays 500 between body 400 and the titles: at 600 it competed\n // with titles, and Text rendered it 400 outside a profile, too weak against body (2026-10-17 user decision).\n label: { fontSize: 12, lineHeight: 18, fontWeight: fontWeight.medium },\n body: { fontSize: 14, lineHeight: 20, fontWeight: fontWeight.regular },\n bodyLarge: { fontSize: 16, lineHeight: 24, fontWeight: fontWeight.regular },\n // Title steps are medium (2026-10-17 user review: 800, then 700, then 600 still read too heavy —\n // \"굵기 좀더 줄여\").\n title: { fontSize: 18, lineHeight: 26, fontWeight: fontWeight.medium },\n titleLarge: { fontSize: 20, lineHeight: 28, fontWeight: fontWeight.medium },\n // `heading` is the largest text HJM draws. 2026-10-17 user decision (\"글자 너무 커\", \"큰 글자 정책은 없애\"):\n // the 40/32 display tier looked far too big on the service-intro screen and was removed; design profiles\n // reject any type step above this size (design-profile.ts `merge`).\n heading: { fontSize: 24, lineHeight: 32, fontWeight: fontWeight.medium },\n} as const;\n\nexport type TextVariant = keyof typeof typography;\n\n/** Visual variants choose a default family role; semantics and sizes remain independent. */\nexport function resolveTextFontRole(variant: TextVariant, role?: FontRole): FontRole {\n if (role !== undefined) {\n if (![\"ui\", \"display\", \"reading\", \"code\"].includes(role)) throw new TypeError(\"Unsupported font role\");\n return role;\n }\n if (variant === \"body\" || variant === \"bodyLarge\") return \"reading\";\n if (variant === \"title\" || variant === \"titleLarge\" || variant === \"heading\") return \"display\";\n return \"ui\";\n}\n\n\n/**\n * Document heading hierarchy without widening the established `TextVariant`\n * union. Every level reuses a semantic text style, so no heading exceeds `typography.heading`.\n */\nexport const heading = {\n /**\n * @deprecated Same as `level3` since the display tier was removed (2026-10-17 user decision, \"큰 글자\n * 정책은 없애\"; it was 40/48/600). Kept so existing consumers keep compiling; use `level3`.\n */\n level1: typography.heading,\n /** @deprecated Same as `level3` since the display tier was removed (was 32/40/600); use `level3`. */\n level2: typography.heading,\n level3: typography.heading,\n level4: typography.titleLarge,\n level5: typography.title,\n} as const;\n\nexport type HeadingLevel = keyof typeof heading;\n\n/** Glyphs include icons and avatars; they do not inherit paragraph line-height. */\nexport const glyph = {\n xs: 14,\n sm: 20,\n md: 24,\n lg: 28,\n xl: 32,\n xxl: 44,\n xxxl: 48,\n} as const;\n\nexport type GlyphSize = keyof typeof glyph;\n\nexport const motion = {\n fast: 120,\n normal: 200,\n slow: 320,\n} as const;\n\n/**\n * Curves are stored as normalized cubic-bezier tuples so CSS and native\n * animation drivers can translate the same motion intent without sharing a\n * renderer dependency.\n */\nexport const easing = {\n standard: [0.2, 0, 0, 1],\n enter: [0, 0, 0, 1],\n exit: [0.3, 0, 1, 1],\n emphasized: [0.2, 0, 0, 1],\n} as const;\n\nexport type ReducedMotionBehavior = \"instant\" | \"opacity\" | \"static\";\n\n/** Shared transition intent; renderers translate easing tuples to their animation API. */\nexport const motionPreset = {\n micro: {\n duration: motion.fast,\n easing: \"standard\",\n reducedMotion: \"instant\",\n },\n enter: {\n duration: motion.normal,\n easing: \"enter\",\n reducedMotion: \"opacity\",\n },\n exit: {\n duration: motion.fast,\n easing: \"exit\",\n reducedMotion: \"instant\",\n },\n context: {\n duration: motion.slow,\n easing: \"emphasized\",\n reducedMotion: \"opacity\",\n },\n} as const satisfies Record<\n \"micro\" | \"enter\" | \"exit\" | \"context\",\n {\n duration: number;\n easing: keyof typeof easing;\n reducedMotion: ReducedMotionBehavior;\n }\n>;\n\n/** Native renderers may use these values directly; web renderers use easing. */\nexport const spring = {\n responsive: { stiffness: 760, damping: 52, mass: 1 },\n expressive: { stiffness: 520, damping: 38, mass: 1 },\n} as const;\n\n/** Reusable state strengths. Components still decide which states are valid. */\nexport const opacity = {\n disabled: 0.5,\n muted: 0.72,\n pressed: 0.86,\n dragged: 0.64,\n} as const;\n\n/** Overlaying the content color at these strengths creates predictable states. */\nexport const stateLayer = {\n hover: 0.06,\n focus: 0.08,\n pressed: 0.1,\n selected: 0.1,\n} as const;\n\nexport const stroke = {\n subtle: 1,\n default: 1,\n strong: 2,\n focus: 2,\n} as const;\n\nexport const control = {\n minTouchTarget: 44,\n buttonHeight: {\n small: 36,\n medium: 44,\n large: 52,\n },\n buttonHitSlop: {\n small: 4,\n medium: 0,\n large: 0,\n },\n fieldHeight: 44,\n chipHeight: {\n small: 36,\n medium: 44,\n },\n selectionIndicator: 24,\n} as const;\n\n/**\n * Font scale at which components switch to a large-text layout. One decision,\n * previously two literals in `segmentedControlRecipe` and `topBarRecipe`; see\n * issue #20 for why it sits with the tokens instead of beside the scale axis.\n */\nexport const largeTextThreshold = 1.6;\n\n/** Product renderers may narrow these widths, but should not invent new rhythm. */\nexport const layout = {\n pagePadding: {\n compact: spacing.md,\n regular: spacing.lg,\n spacious: spacing.xl,\n },\n sectionGap: spacing.xl,\n contentGap: spacing.md,\n rowHeight: {\n singleLine: 56,\n twoLine: 68,\n },\n readingMaxWidth: 720,\n contentMaxWidth: 1200,\n} as const;\n\n/** Width thresholds use CSS pixels on Web and density-independent points on Native. */\nexport const breakpoint = {\n compact: 0,\n medium: 600,\n expanded: 960,\n wide: 1280,\n} as const;\n\n/** Shared stacking intent. Values remain sparse to leave room for app layers. */\nexport const layer = {\n base: 0,\n sticky: 100,\n dropdown: 400,\n overlay: 800,\n modal: 900,\n tooltip: 950,\n toast: 1000,\n} as const;\n\nexport const overlay = {\n scrim: 0.6,\n veil: 0.25,\n} as const;\n\nexport type BackdropReference = Readonly<{\n color: \"#000000\";\n opacity: number;\n}>;\n\n/** Fixed backdrop contracts avoid renderer-specific names such as CSS `scrim`. */\nexport const backdrop = {\n modal: { color: \"#000000\", opacity: overlay.scrim },\n veil: { color: \"#000000\", opacity: overlay.veil },\n} as const satisfies Record<\"modal\" | \"veil\", BackdropReference>;\n\nexport const scrim = `rgba(0, 0, 0, ${overlay.scrim})`;\n\n/** Renderers translate this contract to box-shadow or native shadow/elevation properties. */\nexport const shadow = {\n raised: {\n color: \"#000000\",\n opacity: 0.08,\n radius: 4,\n offsetY: 1,\n },\n floating: {\n color: \"#000000\",\n opacity: 0.12,\n radius: 12,\n offsetY: 4,\n },\n overlay: {\n color: \"#000000\",\n opacity: 0.16,\n radius: 24,\n offsetY: 8,\n },\n} as const;\n\n/**\n * Public elevation steps: `none` or a `shadow` token. 2026-10-23: Burntok kept a RaisedControl View under HJM controls\n * and passed `shadow-lg ring-2` classes to IconButton/Surface because their layoutStyle cannot carry a shadow. Steps\n * name the existing tokens (design profiles override them) instead of opening a free shadow style.\n */\nexport type ElevationStep = \"none\" | keyof typeof shadow;\nexport const elevationSteps = [\"none\", \"raised\", \"floating\", \"overlay\"] as const satisfies readonly ElevationStep[];\n/** Android `elevation` when no design profile supplies shadow tokens (the existing raised 4 / floating 8 fallbacks). */\nexport const nativeElevationFallback = { none: 0, raised: 4, floating: 8, overlay: 16 } as const satisfies Record<ElevationStep, number>;\n\nexport function validateElevationStep(step: string, owner: string): asserts step is ElevationStep {\n if (!(elevationSteps as readonly string[]).includes(step)) throw new TypeError(`Unsupported ${owner} elevation: ${step}`);\n}\n"]}
|
|
@@ -101,6 +101,27 @@ export declare const iconButtonRecipe: {
|
|
|
101
101
|
readonly edge: {
|
|
102
102
|
readonly tones: readonly ["ghost"];
|
|
103
103
|
};
|
|
104
|
+
/**
|
|
105
|
+
* `elevation` (2026-10-23) lifts a floating control (Burntok Dock's center action) with a shadow token. Only filled
|
|
106
|
+
* tones can carry it: a ghost button has no frame for the shadow to belong to (Android draws none without a fill).
|
|
107
|
+
*/
|
|
108
|
+
readonly elevation: {
|
|
109
|
+
readonly default: "none";
|
|
110
|
+
readonly tones: readonly ["primary", "secondary", "danger"];
|
|
111
|
+
};
|
|
112
|
+
/**
|
|
113
|
+
* Count badge on an IconButton (NotificationBell). 2026-10-23 web check: a medium badge at the button's top-end
|
|
114
|
+
* corner (top 0, end 0) covered 82% of BurnTok's 18px heart in a small (36) bell. The badge is now the compact
|
|
115
|
+
* `small` floating plate, kept on the button's end edge (it never sticks out past an `edge`-aligned inset) and
|
|
116
|
+
* raised so only its `glyphOverlap` ring (the canvas-colored floating border) reaches into the glyph slot.
|
|
117
|
+
* Wider counts grow toward the start along the top, not down over the glyph. See `resolveIconButtonBadgeOffset`.
|
|
118
|
+
*/
|
|
119
|
+
readonly badge: {
|
|
120
|
+
readonly size: "small";
|
|
121
|
+
readonly variant: "floating";
|
|
122
|
+
readonly glyphOverlap: 2;
|
|
123
|
+
readonly inlineEnd: 0;
|
|
124
|
+
};
|
|
104
125
|
readonly states: {
|
|
105
126
|
readonly selected: {
|
|
106
127
|
readonly background: Readonly<{
|
|
@@ -132,4 +153,16 @@ export declare function resolveIconButtonPresentation(tone: IconButtonTone, pale
|
|
|
132
153
|
* minimumVisualTarget axis (`visibleControlHeight`), so the overhang tracks what is actually drawn.
|
|
133
154
|
*/
|
|
134
155
|
export declare function resolveIconButtonEdgeOverhang(tone: IconButtonTone, size: IconButtonSize, visibleDiameter?: number): number;
|
|
156
|
+
/**
|
|
157
|
+
* Where an IconButton's count badge sits, measured from the button's top-end corner (logical: `inlineEnd` mirrors in
|
|
158
|
+
* RTL). The badge's block-end lands `badge.glyphOverlap` inside the glyph slot's top edge: blockStart = slot inset +
|
|
159
|
+
* overlap − badge height, e.g. −6 for small (36 − 20 slot, 16 badge). `visibleDiameter` is the rendered size after the
|
|
160
|
+
* Provider's minimumVisualTarget axis, so the badge follows the glyph slot when the button grows (Web and Native).
|
|
161
|
+
*/
|
|
162
|
+
export declare function resolveIconButtonBadgeOffset(size: IconButtonSize, visibleDiameter?: number): Readonly<{
|
|
163
|
+
blockStart: number;
|
|
164
|
+
inlineEnd: number;
|
|
165
|
+
}>;
|
|
166
|
+
/** Throws for an unknown step or an elevated ghost IconButton (iconButtonRecipe.elevation). */
|
|
167
|
+
export declare function validateIconButtonElevation(elevation: string, tone: IconButtonTone): void;
|
|
135
168
|
//# sourceMappingURL=icon-button-recipe.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon-button-recipe.d.ts","sourceRoot":"","sources":["../src/icon-button-recipe.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"icon-button-recipe.d.ts","sourceRoot":"","sources":["../src/icon-button-recipe.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAY/B,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC1D,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,CAAC;AACnD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC1E;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AACtD,eAAO,MAAM,eAAe,mCAAwE,CAAC;AAErG,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+B3B;;;;;;OAMG;;;;IAEH;;;OAGG;;;;;IAEH;;;;;;OAMG;;;;;;;;;;;;;;;;;;;;;;;;CAoCJ,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG,QAAQ,CAAC;IACpD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC,CAAC;AAEH,iFAAiF;AACjF,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,qBAAqB,EAC9B,QAAQ,UAAQ,GACf,8BAA8B,CAiBhC;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,cAAc,EACpB,eAAe,GAAE,MAA8C,GAC9D,MAAM,CAGR;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,cAAc,EACpB,eAAe,GAAE,MAA8C,GAC9D,QAAQ,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAOrD;AAED,+FAA+F;AAC/F,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAKzF"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { resolveColorReference, } from "./color-references.js";
|
|
2
|
-
import { glyph, opacity, radius, } from "./foundations.js";
|
|
2
|
+
import { glyph, opacity, radius, stroke, validateElevationStep, } from "./foundations.js";
|
|
3
3
|
import { semanticColors } from "./semantic-colors.js";
|
|
4
|
+
import { counterBadgeRecipe } from "./counter-badge-recipe.js";
|
|
4
5
|
export const iconButtonEdges = ["start", "end", "both"];
|
|
5
6
|
export const iconButtonRecipe = {
|
|
6
7
|
slots: ["root", "icon", "spinner"],
|
|
@@ -41,6 +42,19 @@ export const iconButtonRecipe = {
|
|
|
41
42
|
* moves the glyph slot by the same amount on Web and Native.
|
|
42
43
|
*/
|
|
43
44
|
edge: { tones: ["ghost"] },
|
|
45
|
+
/**
|
|
46
|
+
* `elevation` (2026-10-23) lifts a floating control (Burntok Dock's center action) with a shadow token. Only filled
|
|
47
|
+
* tones can carry it: a ghost button has no frame for the shadow to belong to (Android draws none without a fill).
|
|
48
|
+
*/
|
|
49
|
+
elevation: { default: "none", tones: ["primary", "secondary", "danger"] },
|
|
50
|
+
/**
|
|
51
|
+
* Count badge on an IconButton (NotificationBell). 2026-10-23 web check: a medium badge at the button's top-end
|
|
52
|
+
* corner (top 0, end 0) covered 82% of BurnTok's 18px heart in a small (36) bell. The badge is now the compact
|
|
53
|
+
* `small` floating plate, kept on the button's end edge (it never sticks out past an `edge`-aligned inset) and
|
|
54
|
+
* raised so only its `glyphOverlap` ring (the canvas-colored floating border) reaches into the glyph slot.
|
|
55
|
+
* Wider counts grow toward the start along the top, not down over the glyph. See `resolveIconButtonBadgeOffset`.
|
|
56
|
+
*/
|
|
57
|
+
badge: { size: "small", variant: "floating", glyphOverlap: stroke.strong, inlineEnd: 0 },
|
|
44
58
|
states: {
|
|
45
59
|
// `aria-pressed` / `accessibilityState.selected` already carried the toggle
|
|
46
60
|
// state; without a paired visual every consumer painted the pressed icon
|
|
@@ -78,4 +92,25 @@ export function resolveIconButtonEdgeOverhang(tone, size, visibleDiameter = icon
|
|
|
78
92
|
return 0;
|
|
79
93
|
return Math.max(0, (visibleDiameter - glyph[iconButtonRecipe.sizes[size].glyph]) / 2);
|
|
80
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Where an IconButton's count badge sits, measured from the button's top-end corner (logical: `inlineEnd` mirrors in
|
|
97
|
+
* RTL). The badge's block-end lands `badge.glyphOverlap` inside the glyph slot's top edge: blockStart = slot inset +
|
|
98
|
+
* overlap − badge height, e.g. −6 for small (36 − 20 slot, 16 badge). `visibleDiameter` is the rendered size after the
|
|
99
|
+
* Provider's minimumVisualTarget axis, so the badge follows the glyph slot when the button grows (Web and Native).
|
|
100
|
+
*/
|
|
101
|
+
export function resolveIconButtonBadgeOffset(size, visibleDiameter = iconButtonRecipe.sizes[size].diameter) {
|
|
102
|
+
const { badge } = iconButtonRecipe;
|
|
103
|
+
const slotInset = Math.max(0, (visibleDiameter - glyph[iconButtonRecipe.sizes[size].glyph]) / 2);
|
|
104
|
+
return {
|
|
105
|
+
blockStart: slotInset + badge.glyphOverlap - counterBadgeRecipe.sizes[badge.size].height,
|
|
106
|
+
inlineEnd: badge.inlineEnd,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/** Throws for an unknown step or an elevated ghost IconButton (iconButtonRecipe.elevation). */
|
|
110
|
+
export function validateIconButtonElevation(elevation, tone) {
|
|
111
|
+
validateElevationStep(elevation, "IconButton");
|
|
112
|
+
if (elevation !== "none" && !iconButtonRecipe.elevation.tones.includes(tone)) {
|
|
113
|
+
throw new TypeError(`IconButton elevation needs a filled tone, not ${tone}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
81
116
|
//# sourceMappingURL=icon-button-recipe.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"icon-button-recipe.js","sourceRoot":"","sources":["../src/icon-button-recipe.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveColorReference,\n type ColorReference,\n type ColorReferencePalette,\n} from \"./color-references.js\";\nimport {\n glyph,\n opacity,\n radius,\n type GlyphSize,\n} from \"./foundations.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\n\nexport type IconButtonSize = \"small\" | \"medium\" | \"large\";\nexport type IconButtonShape = \"rounded\" | \"circle\";\nexport type IconButtonTone = \"primary\" | \"secondary\" | \"ghost\" | \"danger\";\n/**\n * Which container edge a ghost IconButton sits on (logical: `start`/`end` follow the reading direction). The\n * button keeps its full touch target but overhangs that edge so its glyph slot, not the transparent hit area,\n * sets the visible inset (2026-10-17 measured audit: glyphs sat 10–15px inside the row/header inset).\n */\nexport type IconButtonEdge = \"start\" | \"end\" | \"both\";\nexport const iconButtonEdges = [\"start\", \"end\", \"both\"] as const satisfies readonly IconButtonEdge[];\n\nexport const iconButtonRecipe = {\n slots: [\"root\", \"icon\", \"spinner\"] as const,\n defaults: { tone: \"ghost\", size: \"medium\", shape: \"rounded\" },\n tones: {\n primary: {\n background: semanticColors.action.brand.background,\n content: semanticColors.action.brand.content,\n border: null,\n },\n secondary: {\n background: semanticColors.action.neutral.background,\n content: semanticColors.action.neutral.content,\n border: semanticColors.action.neutral.border,\n },\n ghost: {\n background: null,\n content: semanticColors.content.secondary,\n border: null,\n },\n danger: {\n background: semanticColors.action.danger.background,\n content: semanticColors.action.danger.content,\n border: null,\n },\n },\n sizes: {\n small: { diameter: 36, hitSlop: 4, glyph: \"sm\" },\n medium: { diameter: 44, hitSlop: 0, glyph: \"md\" },\n large: { diameter: 52, hitSlop: 0, glyph: \"lg\" },\n },\n shapes: { rounded: \"md\", circle: \"full\" },\n /**\n * Edge alignment (2026-10-17 measured audit): a ghost IconButton at a row/header edge overhangs that edge by\n * (visible diameter − glyph slot) / 2, so the glyph slot lines up with the container inset like text does while\n * the hit area stays whole. Only `ghost` overhangs — filled and outlined tones show their frame, and the frame is\n * what aligns. Renderers read `resolveIconButtonEdgeOverhang` so a raised visible diameter (minimumVisualTarget)\n * moves the glyph slot by the same amount on Web and Native.\n */\n edge: { tones: [\"ghost\"] as const },\n states: {\n // `aria-pressed` / `accessibilityState.selected` already carried the toggle\n // state; without a paired visual every consumer painted the pressed icon\n // button in product styles. Mirrors `buttonRecipe.states.selected`.\n selected: {\n background: semanticColors.selection.background,\n content: semanticColors.selection.content,\n // Match Button: neutral selection does not introduce an outline.\n border: null,\n },\n pressedOpacity: opacity.pressed,\n disabledOpacity: opacity.disabled,\n },\n} as const satisfies {\n slots: readonly string[];\n defaults: {\n tone: IconButtonTone;\n size: IconButtonSize;\n shape: IconButtonShape;\n };\n tones: Record<\n IconButtonTone,\n { background: ColorReference | null; content: ColorReference; border: ColorReference | null }\n >;\n sizes: Record<IconButtonSize, { diameter: number; hitSlop: number; glyph: GlyphSize }>;\n shapes: Record<IconButtonShape, keyof typeof radius>;\n edge: { tones: readonly IconButtonTone[] };\n states: {\n selected: { background: ColorReference; content: ColorReference; border: ColorReference | null };\n pressedOpacity: number;\n disabledOpacity: number;\n };\n};\n\nexport type ResolvedIconButtonPresentation = Readonly<{\n background: string | null;\n content: string;\n border: string | null;\n}>;\n\n/** Resolve one recipe tone for non-CSS renderers without a second tone table. */\nexport function resolveIconButtonPresentation(\n tone: IconButtonTone,\n palette: ColorReferencePalette,\n selected = false,\n): ResolvedIconButtonPresentation {\n const contract: {\n background: ColorReference | null;\n content: ColorReference;\n border: ColorReference | null;\n } = selected ? iconButtonRecipe.states.selected : iconButtonRecipe.tones[tone];\n return {\n background:\n contract.background === null\n ? null\n : resolveColorReference(contract.background, palette),\n content: resolveColorReference(contract.content, palette),\n border:\n contract.border === null\n ? null\n : resolveColorReference(contract.border, palette),\n };\n}\n\n/**\n * Negative margin a ghost IconButton applies on its `edge` side(s): (visible diameter − glyph slot) / 2, e.g. 10 for\n * medium (44 − 24). 0 for tones that draw a frame. `visibleDiameter` is the rendered size after the Provider's\n * minimumVisualTarget axis (`visibleControlHeight`), so the overhang tracks what is actually drawn.\n */\nexport function resolveIconButtonEdgeOverhang(\n tone: IconButtonTone,\n size: IconButtonSize,\n visibleDiameter: number = iconButtonRecipe.sizes[size].diameter,\n): number {\n if (!(iconButtonRecipe.edge.tones as readonly IconButtonTone[]).includes(tone)) return 0;\n return Math.max(0, (visibleDiameter - glyph[iconButtonRecipe.sizes[size].glyph]) / 2);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"icon-button-recipe.js","sourceRoot":"","sources":["../src/icon-button-recipe.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveColorReference,\n type ColorReference,\n type ColorReferencePalette,\n} from \"./color-references.js\";\nimport {\n glyph,\n opacity,\n radius,\n stroke,\n validateElevationStep,\n type GlyphSize,\n} from \"./foundations.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\nimport { counterBadgeRecipe, type CounterBadgeSize, type CounterBadgeVariant } from \"./counter-badge-recipe.js\";\n\nexport type IconButtonSize = \"small\" | \"medium\" | \"large\";\nexport type IconButtonShape = \"rounded\" | \"circle\";\nexport type IconButtonTone = \"primary\" | \"secondary\" | \"ghost\" | \"danger\";\n/**\n * Which container edge a ghost IconButton sits on (logical: `start`/`end` follow the reading direction). The\n * button keeps its full touch target but overhangs that edge so its glyph slot, not the transparent hit area,\n * sets the visible inset (2026-10-17 measured audit: glyphs sat 10–15px inside the row/header inset).\n */\nexport type IconButtonEdge = \"start\" | \"end\" | \"both\";\nexport const iconButtonEdges = [\"start\", \"end\", \"both\"] as const satisfies readonly IconButtonEdge[];\n\nexport const iconButtonRecipe = {\n slots: [\"root\", \"icon\", \"spinner\"] as const,\n defaults: { tone: \"ghost\", size: \"medium\", shape: \"rounded\" },\n tones: {\n primary: {\n background: semanticColors.action.brand.background,\n content: semanticColors.action.brand.content,\n border: null,\n },\n secondary: {\n background: semanticColors.action.neutral.background,\n content: semanticColors.action.neutral.content,\n border: semanticColors.action.neutral.border,\n },\n ghost: {\n background: null,\n content: semanticColors.content.secondary,\n border: null,\n },\n danger: {\n background: semanticColors.action.danger.background,\n content: semanticColors.action.danger.content,\n border: null,\n },\n },\n sizes: {\n small: { diameter: 36, hitSlop: 4, glyph: \"sm\" },\n medium: { diameter: 44, hitSlop: 0, glyph: \"md\" },\n large: { diameter: 52, hitSlop: 0, glyph: \"lg\" },\n },\n shapes: { rounded: \"md\", circle: \"full\" },\n /**\n * Edge alignment (2026-10-17 measured audit): a ghost IconButton at a row/header edge overhangs that edge by\n * (visible diameter − glyph slot) / 2, so the glyph slot lines up with the container inset like text does while\n * the hit area stays whole. Only `ghost` overhangs — filled and outlined tones show their frame, and the frame is\n * what aligns. Renderers read `resolveIconButtonEdgeOverhang` so a raised visible diameter (minimumVisualTarget)\n * moves the glyph slot by the same amount on Web and Native.\n */\n edge: { tones: [\"ghost\"] as const },\n /**\n * `elevation` (2026-10-23) lifts a floating control (Burntok Dock's center action) with a shadow token. Only filled\n * tones can carry it: a ghost button has no frame for the shadow to belong to (Android draws none without a fill).\n */\n elevation: { default: \"none\", tones: [\"primary\", \"secondary\", \"danger\"] as const },\n /**\n * Count badge on an IconButton (NotificationBell). 2026-10-23 web check: a medium badge at the button's top-end\n * corner (top 0, end 0) covered 82% of BurnTok's 18px heart in a small (36) bell. The badge is now the compact\n * `small` floating plate, kept on the button's end edge (it never sticks out past an `edge`-aligned inset) and\n * raised so only its `glyphOverlap` ring (the canvas-colored floating border) reaches into the glyph slot.\n * Wider counts grow toward the start along the top, not down over the glyph. See `resolveIconButtonBadgeOffset`.\n */\n badge: { size: \"small\", variant: \"floating\", glyphOverlap: stroke.strong, inlineEnd: 0 },\n states: {\n // `aria-pressed` / `accessibilityState.selected` already carried the toggle\n // state; without a paired visual every consumer painted the pressed icon\n // button in product styles. Mirrors `buttonRecipe.states.selected`.\n selected: {\n background: semanticColors.selection.background,\n content: semanticColors.selection.content,\n // Match Button: neutral selection does not introduce an outline.\n border: null,\n },\n pressedOpacity: opacity.pressed,\n disabledOpacity: opacity.disabled,\n },\n} as const satisfies {\n slots: readonly string[];\n defaults: {\n tone: IconButtonTone;\n size: IconButtonSize;\n shape: IconButtonShape;\n };\n tones: Record<\n IconButtonTone,\n { background: ColorReference | null; content: ColorReference; border: ColorReference | null }\n >;\n sizes: Record<IconButtonSize, { diameter: number; hitSlop: number; glyph: GlyphSize }>;\n shapes: Record<IconButtonShape, keyof typeof radius>;\n edge: { tones: readonly IconButtonTone[] };\n elevation: { default: \"none\"; tones: readonly IconButtonTone[] };\n badge: { size: CounterBadgeSize; variant: CounterBadgeVariant; glyphOverlap: number; inlineEnd: number };\n states: {\n selected: { background: ColorReference; content: ColorReference; border: ColorReference | null };\n pressedOpacity: number;\n disabledOpacity: number;\n };\n};\n\nexport type ResolvedIconButtonPresentation = Readonly<{\n background: string | null;\n content: string;\n border: string | null;\n}>;\n\n/** Resolve one recipe tone for non-CSS renderers without a second tone table. */\nexport function resolveIconButtonPresentation(\n tone: IconButtonTone,\n palette: ColorReferencePalette,\n selected = false,\n): ResolvedIconButtonPresentation {\n const contract: {\n background: ColorReference | null;\n content: ColorReference;\n border: ColorReference | null;\n } = selected ? iconButtonRecipe.states.selected : iconButtonRecipe.tones[tone];\n return {\n background:\n contract.background === null\n ? null\n : resolveColorReference(contract.background, palette),\n content: resolveColorReference(contract.content, palette),\n border:\n contract.border === null\n ? null\n : resolveColorReference(contract.border, palette),\n };\n}\n\n/**\n * Negative margin a ghost IconButton applies on its `edge` side(s): (visible diameter − glyph slot) / 2, e.g. 10 for\n * medium (44 − 24). 0 for tones that draw a frame. `visibleDiameter` is the rendered size after the Provider's\n * minimumVisualTarget axis (`visibleControlHeight`), so the overhang tracks what is actually drawn.\n */\nexport function resolveIconButtonEdgeOverhang(\n tone: IconButtonTone,\n size: IconButtonSize,\n visibleDiameter: number = iconButtonRecipe.sizes[size].diameter,\n): number {\n if (!(iconButtonRecipe.edge.tones as readonly IconButtonTone[]).includes(tone)) return 0;\n return Math.max(0, (visibleDiameter - glyph[iconButtonRecipe.sizes[size].glyph]) / 2);\n}\n\n/**\n * Where an IconButton's count badge sits, measured from the button's top-end corner (logical: `inlineEnd` mirrors in\n * RTL). The badge's block-end lands `badge.glyphOverlap` inside the glyph slot's top edge: blockStart = slot inset +\n * overlap − badge height, e.g. −6 for small (36 − 20 slot, 16 badge). `visibleDiameter` is the rendered size after the\n * Provider's minimumVisualTarget axis, so the badge follows the glyph slot when the button grows (Web and Native).\n */\nexport function resolveIconButtonBadgeOffset(\n size: IconButtonSize,\n visibleDiameter: number = iconButtonRecipe.sizes[size].diameter,\n): Readonly<{ blockStart: number; inlineEnd: number }> {\n const { badge } = iconButtonRecipe;\n const slotInset = Math.max(0, (visibleDiameter - glyph[iconButtonRecipe.sizes[size].glyph]) / 2);\n return {\n blockStart: slotInset + badge.glyphOverlap - counterBadgeRecipe.sizes[badge.size].height,\n inlineEnd: badge.inlineEnd,\n };\n}\n\n/** Throws for an unknown step or an elevated ghost IconButton (iconButtonRecipe.elevation). */\nexport function validateIconButtonElevation(elevation: string, tone: IconButtonTone): void {\n validateElevationStep(elevation, \"IconButton\");\n if (elevation !== \"none\" && !(iconButtonRecipe.elevation.tones as readonly string[]).includes(tone)) {\n throw new TypeError(`IconButton elevation needs a filled tone, not ${tone}`);\n }\n}\n"]}
|
package/dist/image.d.ts
CHANGED
|
@@ -95,5 +95,18 @@ export declare const imageRecipe: {
|
|
|
95
95
|
};
|
|
96
96
|
readonly radius: "md";
|
|
97
97
|
};
|
|
98
|
+
/**
|
|
99
|
+
* Press target that opens ImageViewer from product media (ImageViewerTrigger). 2026-10-23: the portfolio site
|
|
100
|
+
* (`App.tsx` raw button) and Spint (`MarkPhoto`, `ComposeScreen` Pressable + Image) each wrapped an image to open the
|
|
101
|
+
* viewer, with their own name, focus ring and cursor. The trigger owns the button semantics, the image-frame
|
|
102
|
+
* radius for the focus ring, the zoom cursor and the pressed opacity; the media stays decorative inside it.
|
|
103
|
+
*/
|
|
104
|
+
export declare const imageViewerTriggerRecipe: {
|
|
105
|
+
readonly radius: "md";
|
|
106
|
+
readonly cursor: "zoom-in";
|
|
107
|
+
readonly pressedOpacity: 0.86;
|
|
108
|
+
readonly disabledOpacity: 0.5;
|
|
109
|
+
};
|
|
110
|
+
export declare function validateImageViewerTriggerLabel(label: string): void;
|
|
98
111
|
export {};
|
|
99
112
|
//# sourceMappingURL=image.d.ts.map
|
package/dist/image.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AACpD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtE,MAAM,MAAM,mBAAmB,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE9D,sGAAsG;AACtG,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EAClD,QAAQ,EAAE,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EACrD,IAAI,EAAE,mBAAmB;;;;;;;;EAiB1B;AAED,eAAO,MAAM,aAAa;;CAEsB,CAAC;AAEjD,KAAK,eAAe,GAAG,QAAQ,CAAC;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,QAAQ,CAAC;CAChB,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG,eAAe,GACrD,QAAQ,CAAC;IAAE,UAAU,CAAC,EAAE,IAAI,CAAC;IAAC,kBAAkB,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC;AAE9D,MAAM,MAAM,0BAA0B,GAAG,eAAe,GACtD,QAAQ,CAAC;IAAE,UAAU,EAAE,KAAK,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE9D,MAAM,MAAM,eAAe,GACvB,yBAAyB,GACzB,0BAA0B,CAAC;AAE/B,MAAM,MAAM,uBAAuB,GAC/B,CAAC,QAAQ,CAAC,IAAI,CAAC,yBAAyB,EAAE,oBAAoB,CAAC,CAAC,GAC9D,QAAQ,CAAC;IAAE,kBAAkB,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,CAAC,GAC3C,QAAQ,CAAC,0BAA0B,CAAC,CAAC;AAgBzC,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI,CA6BzE;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,eAAe,GAC1B,uBAAuB,CAgBzB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAI7E;AAED;;;;;GAKG;AACH,wBAAgB,sCAAsC,CACpD,UAAU,EAAE,uBAAuB,GAClC,MAAM,GAAG,SAAS,CAEpB;AAKD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB;;;;CAIe,CAAC;AAE9C,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;CAYd,CAAC;AAEX;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;;;CAK3B,CAAC;AAEX,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEnE"}
|
package/dist/image.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { semanticColors } from "./semantic-colors.js";
|
|
2
|
+
import { opacity } from "./foundations.js";
|
|
2
3
|
/** Exact image inspection sizes use layout units, not device physical pixels (Utilverse ADR-0020). */
|
|
3
4
|
export function resolveImageInspectionGeometry(image, viewport, mode) {
|
|
4
5
|
if (![image.width, image.height, viewport.width, viewport.height].every(value => Number.isFinite(value) && value > 0)) {
|
|
@@ -116,4 +117,20 @@ export const imageRecipe = {
|
|
|
116
117
|
},
|
|
117
118
|
radius: "md",
|
|
118
119
|
};
|
|
120
|
+
/**
|
|
121
|
+
* Press target that opens ImageViewer from product media (ImageViewerTrigger). 2026-10-23: the portfolio site
|
|
122
|
+
* (`App.tsx` raw button) and Spint (`MarkPhoto`, `ComposeScreen` Pressable + Image) each wrapped an image to open the
|
|
123
|
+
* viewer, with their own name, focus ring and cursor. The trigger owns the button semantics, the image-frame
|
|
124
|
+
* radius for the focus ring, the zoom cursor and the pressed opacity; the media stays decorative inside it.
|
|
125
|
+
*/
|
|
126
|
+
export const imageViewerTriggerRecipe = {
|
|
127
|
+
radius: imageRecipe.radius,
|
|
128
|
+
cursor: "zoom-in",
|
|
129
|
+
pressedOpacity: opacity.pressed,
|
|
130
|
+
disabledOpacity: opacity.disabled,
|
|
131
|
+
};
|
|
132
|
+
export function validateImageViewerTriggerLabel(label) {
|
|
133
|
+
if (typeof label !== "string" || label.trim().length === 0)
|
|
134
|
+
throw new TypeError("ImageViewerTrigger needs a localized label");
|
|
135
|
+
}
|
|
119
136
|
//# sourceMappingURL=image.js.map
|