@hjmds/design-contracts 0.8.2
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/README.md +208 -0
- package/dist/alert-dialog.d.ts +102 -0
- package/dist/alert-dialog.d.ts.map +1 -0
- package/dist/alert-dialog.js +136 -0
- package/dist/alert-dialog.js.map +1 -0
- package/dist/base-recipes.d.ts +184 -0
- package/dist/base-recipes.d.ts.map +1 -0
- package/dist/base-recipes.js +129 -0
- package/dist/base-recipes.js.map +1 -0
- package/dist/behaviors.d.ts +1254 -0
- package/dist/behaviors.d.ts.map +1 -0
- package/dist/behaviors.js +972 -0
- package/dist/behaviors.js.map +1 -0
- package/dist/bottom-navigation-defaults.d.ts +13 -0
- package/dist/bottom-navigation-defaults.d.ts.map +1 -0
- package/dist/bottom-navigation-defaults.js +10 -0
- package/dist/bottom-navigation-defaults.js.map +1 -0
- package/dist/bottom-navigation.d.ts +114 -0
- package/dist/bottom-navigation.d.ts.map +1 -0
- package/dist/bottom-navigation.js +223 -0
- package/dist/bottom-navigation.js.map +1 -0
- package/dist/breadcrumb.d.ts +97 -0
- package/dist/breadcrumb.d.ts.map +1 -0
- package/dist/breadcrumb.js +99 -0
- package/dist/breadcrumb.js.map +1 -0
- package/dist/calendar.d.ts +285 -0
- package/dist/calendar.d.ts.map +1 -0
- package/dist/calendar.js +297 -0
- package/dist/calendar.js.map +1 -0
- package/dist/card.d.ts +39 -0
- package/dist/card.d.ts.map +1 -0
- package/dist/card.js +50 -0
- package/dist/card.js.map +1 -0
- package/dist/carousel.d.ts +180 -0
- package/dist/carousel.d.ts.map +1 -0
- package/dist/carousel.js +172 -0
- package/dist/carousel.js.map +1 -0
- package/dist/catalog.d.ts +7158 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +220 -0
- package/dist/catalog.js.map +1 -0
- package/dist/collection.d.ts +123 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +211 -0
- package/dist/collection.js.map +1 -0
- package/dist/color-references.d.ts +46 -0
- package/dist/color-references.d.ts.map +1 -0
- package/dist/color-references.js +39 -0
- package/dist/color-references.js.map +1 -0
- package/dist/colors.d.ts +56 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +90 -0
- package/dist/colors.js.map +1 -0
- package/dist/command-palette.d.ts +240 -0
- package/dist/command-palette.d.ts.map +1 -0
- package/dist/command-palette.js +97 -0
- package/dist/command-palette.js.map +1 -0
- package/dist/component-contracts.d.ts +137 -0
- package/dist/component-contracts.d.ts.map +1 -0
- package/dist/component-contracts.js +53 -0
- package/dist/component-contracts.js.map +1 -0
- package/dist/component-definitions.d.ts +135 -0
- package/dist/component-definitions.d.ts.map +1 -0
- package/dist/component-definitions.js +142 -0
- package/dist/component-definitions.js.map +1 -0
- package/dist/component-recipes.d.ts +3583 -0
- package/dist/component-recipes.d.ts.map +1 -0
- package/dist/component-recipes.js +1503 -0
- package/dist/component-recipes.js.map +1 -0
- package/dist/component-references.d.ts +416 -0
- package/dist/component-references.d.ts.map +1 -0
- package/dist/component-references.js +140 -0
- package/dist/component-references.js.map +1 -0
- package/dist/content-state.d.ts +104 -0
- package/dist/content-state.d.ts.map +1 -0
- package/dist/content-state.js +116 -0
- package/dist/content-state.js.map +1 -0
- package/dist/counter-badge-recipe.d.ts +80 -0
- package/dist/counter-badge-recipe.d.ts.map +1 -0
- package/dist/counter-badge-recipe.js +44 -0
- package/dist/counter-badge-recipe.js.map +1 -0
- package/dist/counter-badge.d.ts +12 -0
- package/dist/counter-badge.d.ts.map +1 -0
- package/dist/counter-badge.js +21 -0
- package/dist/counter-badge.js.map +1 -0
- package/dist/data-table.d.ts +203 -0
- package/dist/data-table.d.ts.map +1 -0
- package/dist/data-table.js +182 -0
- package/dist/data-table.js.map +1 -0
- package/dist/date-picker.d.ts +268 -0
- package/dist/date-picker.d.ts.map +1 -0
- package/dist/date-picker.js +168 -0
- package/dist/date-picker.js.map +1 -0
- package/dist/description-list.d.ts +68 -0
- package/dist/description-list.d.ts.map +1 -0
- package/dist/description-list.js +85 -0
- package/dist/description-list.js.map +1 -0
- package/dist/design-system-provider.d.ts +80 -0
- package/dist/design-system-provider.d.ts.map +1 -0
- package/dist/design-system-provider.js +147 -0
- package/dist/design-system-provider.js.map +1 -0
- package/dist/evidence.d.ts +49 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +133 -0
- package/dist/evidence.js.map +1 -0
- package/dist/file-picker.d.ts +183 -0
- package/dist/file-picker.d.ts.map +1 -0
- package/dist/file-picker.js +224 -0
- package/dist/file-picker.js.map +1 -0
- package/dist/floating-action-button.d.ts +143 -0
- package/dist/floating-action-button.d.ts.map +1 -0
- package/dist/floating-action-button.js +149 -0
- package/dist/floating-action-button.js.map +1 -0
- package/dist/form.d.ts +143 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +206 -0
- package/dist/form.js.map +1 -0
- package/dist/foundations.d.ts +300 -0
- package/dist/foundations.d.ts.map +1 -0
- package/dist/foundations.js +238 -0
- package/dist/foundations.js.map +1 -0
- package/dist/grid.d.ts +75 -0
- package/dist/grid.d.ts.map +1 -0
- package/dist/grid.js +133 -0
- package/dist/grid.js.map +1 -0
- package/dist/icon-button-recipe.d.ts +99 -0
- package/dist/icon-button-recipe.d.ts.map +1 -0
- package/dist/icon-button-recipe.js +53 -0
- package/dist/icon-button-recipe.js.map +1 -0
- package/dist/icon.d.ts +41 -0
- package/dist/icon.d.ts.map +1 -0
- package/dist/icon.js +147 -0
- package/dist/icon.js.map +1 -0
- package/dist/image.d.ts +82 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +100 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +118 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +118 -0
- package/dist/layout.js.map +1 -0
- package/dist/link.d.ts +57 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +142 -0
- package/dist/link.js.map +1 -0
- package/dist/load-more.d.ts +64 -0
- package/dist/load-more.d.ts.map +1 -0
- package/dist/load-more.js +124 -0
- package/dist/load-more.js.map +1 -0
- package/dist/mentions.d.ts +67 -0
- package/dist/mentions.d.ts.map +1 -0
- package/dist/mentions.js +107 -0
- package/dist/mentions.js.map +1 -0
- package/dist/number-field.d.ts +208 -0
- package/dist/number-field.d.ts.map +1 -0
- package/dist/number-field.js +247 -0
- package/dist/number-field.js.map +1 -0
- package/dist/otp-field.d.ts +152 -0
- package/dist/otp-field.d.ts.map +1 -0
- package/dist/otp-field.js +117 -0
- package/dist/otp-field.js.map +1 -0
- package/dist/pagination.d.ts +181 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +226 -0
- package/dist/pagination.js.map +1 -0
- package/dist/password-field.d.ts +187 -0
- package/dist/password-field.d.ts.map +1 -0
- package/dist/password-field.js +120 -0
- package/dist/password-field.js.map +1 -0
- package/dist/popover.d.ts +152 -0
- package/dist/popover.d.ts.map +1 -0
- package/dist/popover.js +137 -0
- package/dist/popover.js.map +1 -0
- package/dist/progress-recipe.d.ts +43 -0
- package/dist/progress-recipe.d.ts.map +1 -0
- package/dist/progress-recipe.js +16 -0
- package/dist/progress-recipe.js.map +1 -0
- package/dist/recipes.d.ts +31 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/recipes.js +46 -0
- package/dist/recipes.js.map +1 -0
- package/dist/responsive.d.ts +27 -0
- package/dist/responsive.d.ts.map +1 -0
- package/dist/responsive.js +66 -0
- package/dist/responsive.js.map +1 -0
- package/dist/result.d.ts +111 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +97 -0
- package/dist/result.js.map +1 -0
- package/dist/selection-helpers.d.ts +16 -0
- package/dist/selection-helpers.d.ts.map +1 -0
- package/dist/selection-helpers.js +52 -0
- package/dist/selection-helpers.js.map +1 -0
- package/dist/semantic-colors.d.ts +275 -0
- package/dist/semantic-colors.d.ts.map +1 -0
- package/dist/semantic-colors.js +84 -0
- package/dist/semantic-colors.js.map +1 -0
- package/dist/sheet.d.ts +51 -0
- package/dist/sheet.d.ts.map +1 -0
- package/dist/sheet.js +69 -0
- package/dist/sheet.js.map +1 -0
- package/dist/showcase.d.ts +153 -0
- package/dist/showcase.d.ts.map +1 -0
- package/dist/showcase.js +210 -0
- package/dist/showcase.js.map +1 -0
- package/dist/side-panel.d.ts +199 -0
- package/dist/side-panel.d.ts.map +1 -0
- package/dist/side-panel.js +111 -0
- package/dist/side-panel.js.map +1 -0
- package/dist/slider.d.ts +138 -0
- package/dist/slider.d.ts.map +1 -0
- package/dist/slider.js +150 -0
- package/dist/slider.js.map +1 -0
- package/dist/splitter.d.ts +113 -0
- package/dist/splitter.d.ts.map +1 -0
- package/dist/splitter.js +99 -0
- package/dist/splitter.js.map +1 -0
- package/dist/statistic.d.ts +41 -0
- package/dist/statistic.d.ts.map +1 -0
- package/dist/statistic.js +76 -0
- package/dist/statistic.js.map +1 -0
- package/dist/steps.d.ts +196 -0
- package/dist/steps.d.ts.map +1 -0
- package/dist/steps.js +160 -0
- package/dist/steps.js.map +1 -0
- package/dist/tag.d.ts +128 -0
- package/dist/tag.d.ts.map +1 -0
- package/dist/tag.js +93 -0
- package/dist/tag.js.map +1 -0
- package/dist/timeline.d.ts +147 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +127 -0
- package/dist/timeline.js.map +1 -0
- package/dist/toast.d.ts +164 -0
- package/dist/toast.d.ts.map +1 -0
- package/dist/toast.js +529 -0
- package/dist/toast.js.map +1 -0
- package/dist/tokens.d.ts +9 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +9 -0
- package/dist/tokens.js.map +1 -0
- package/dist/tooltip.d.ts +44 -0
- package/dist/tooltip.d.ts.map +1 -0
- package/dist/tooltip.js +88 -0
- package/dist/tooltip.js.map +1 -0
- package/dist/tour.d.ts +218 -0
- package/dist/tour.d.ts.map +1 -0
- package/dist/tour.js +211 -0
- package/dist/tour.js.map +1 -0
- package/dist/transfer-list.d.ts +207 -0
- package/dist/transfer-list.d.ts.map +1 -0
- package/dist/transfer-list.js +193 -0
- package/dist/transfer-list.js.map +1 -0
- package/dist/tree-select.d.ts +78 -0
- package/dist/tree-select.d.ts.map +1 -0
- package/dist/tree-select.js +132 -0
- package/dist/tree-select.js.map +1 -0
- package/dist/tree.d.ts +206 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +223 -0
- package/dist/tree.js.map +1 -0
- package/dist/upload-item.d.ts +173 -0
- package/dist/upload-item.d.ts.map +1 -0
- package/dist/upload-item.js +156 -0
- package/dist/upload-item.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/docs/affix.md +63 -0
- package/docs/anchor.md +59 -0
- package/docs/ant-design-coverage.md +119 -0
- package/docs/app-provider.md +50 -0
- package/docs/app-rn-adoption.md +227 -0
- package/docs/architecture.md +320 -0
- package/docs/authoring-brief.md +87 -0
- package/docs/border-beam.md +66 -0
- package/docs/bottom-navigation.md +127 -0
- package/docs/breadcrumb.md +82 -0
- package/docs/calendar.md +154 -0
- package/docs/carousel.md +130 -0
- package/docs/cascader.md +93 -0
- package/docs/catalog-decision-status.md +306 -0
- package/docs/color-picker.md +72 -0
- package/docs/command-palette.md +116 -0
- package/docs/confirm-popover.md +93 -0
- package/docs/consistency-audit.md +383 -0
- package/docs/consumer-release-gate.md +90 -0
- package/docs/content-state.md +156 -0
- package/docs/context-panel.md +88 -0
- package/docs/cross-platform-core-normalization.md +118 -0
- package/docs/data-table.md +79 -0
- package/docs/date-picker.md +84 -0
- package/docs/description-list.md +75 -0
- package/docs/design-system-provider.md +139 -0
- package/docs/dropdown.md +78 -0
- package/docs/expansion-roadmap.md +285 -0
- package/docs/file-picker.md +59 -0
- package/docs/floating-action-button.md +111 -0
- package/docs/form.md +134 -0
- package/docs/generated/component-maturity.md +103 -0
- package/docs/generated/renderer-evidence.json +5597 -0
- package/docs/generated/renderer-evidence.md +132 -0
- package/docs/generated/showcase-manifest.json +3732 -0
- package/docs/icon.md +22 -0
- package/docs/identity.md +121 -0
- package/docs/image.md +84 -0
- package/docs/implementation-0.5.md +85 -0
- package/docs/layout-primitives.md +107 -0
- package/docs/layout.md +83 -0
- package/docs/library-reference-decisions.md +123 -0
- package/docs/link.md +67 -0
- package/docs/load-more.md +31 -0
- package/docs/mentions.md +82 -0
- package/docs/migration-0.2.md +108 -0
- package/docs/migration-0.3.md +72 -0
- package/docs/migration-0.5.md +82 -0
- package/docs/migration-0.6.md +197 -0
- package/docs/notification.md +54 -0
- package/docs/number-field.md +82 -0
- package/docs/otp-field.md +103 -0
- package/docs/pagination.md +139 -0
- package/docs/password-field.md +98 -0
- package/docs/popover.md +124 -0
- package/docs/promotion-candidates.md +169 -0
- package/docs/qr-code.md +69 -0
- package/docs/rating.md +58 -0
- package/docs/responsive-grid.md +90 -0
- package/docs/result.md +96 -0
- package/docs/showcase.md +97 -0
- package/docs/side-panel.md +71 -0
- package/docs/slider.md +79 -0
- package/docs/splitter.md +55 -0
- package/docs/statistic.md +16 -0
- package/docs/steps.md +115 -0
- package/docs/tag.md +57 -0
- package/docs/time-picker.md +88 -0
- package/docs/timeline.md +146 -0
- package/docs/toast.md +127 -0
- package/docs/tooltip.md +58 -0
- package/docs/tour.md +136 -0
- package/docs/transfer-list.md +94 -0
- package/docs/tree-select.md +101 -0
- package/docs/tree.md +123 -0
- package/docs/upload-item.md +68 -0
- package/docs/utility.md +53 -0
- package/docs/virtual-list.md +70 -0
- package/docs/watermark.md +58 -0
- package/package.json +402 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Products render `idle|loading|loadingMore|empty|error` content states (see
|
|
3
|
+
* `docs/expansion-roadmap.md`'s common state axis table) at two different
|
|
4
|
+
* granularities: replacing an entire screen's content, or replacing one
|
|
5
|
+
* region while the rest of the screen keeps working. That granularity is a
|
|
6
|
+
* second, orthogonal axis — `scope` — not a new content value and not the
|
|
7
|
+
* `status` axis `Result` owns (`docs/result.md`). This module is that axis
|
|
8
|
+
* plus what it forces: action emphasis and accessibility announcement scope.
|
|
9
|
+
*
|
|
10
|
+
* `loadingMore` and `complete` are excluded from `ContentStateStatus` on
|
|
11
|
+
* purpose. Both belong to `LoadMore`'s footer, which is a region by
|
|
12
|
+
* construction (a list footer is never a whole screen) and already owns its
|
|
13
|
+
* own state machine (`src/load-more.ts`). `idle` and `success` render no
|
|
14
|
+
* block at all — the caller shows real content instead.
|
|
15
|
+
*/
|
|
16
|
+
export type ContentScope = "screen" | "region";
|
|
17
|
+
export type ContentStateStatus = "loading" | "empty" | "error";
|
|
18
|
+
export type ContentStateActionDescriptor = Readonly<{
|
|
19
|
+
label: string;
|
|
20
|
+
accessibilityLabel?: string;
|
|
21
|
+
onAction(): void;
|
|
22
|
+
}>;
|
|
23
|
+
export type ContentStateLoadingDescriptor = Readonly<{
|
|
24
|
+
status: "loading";
|
|
25
|
+
scope: ContentScope;
|
|
26
|
+
/** The only accessible signal for a loading block; there is no title/action slot. */
|
|
27
|
+
loadingLabel: string;
|
|
28
|
+
}>;
|
|
29
|
+
export type ContentStateEmptyDescriptor = Readonly<{
|
|
30
|
+
status: "empty";
|
|
31
|
+
scope: ContentScope;
|
|
32
|
+
title: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
action?: ContentStateActionDescriptor;
|
|
35
|
+
}>;
|
|
36
|
+
export type ContentStateErrorDescriptor = Readonly<{
|
|
37
|
+
status: "error";
|
|
38
|
+
scope: ContentScope;
|
|
39
|
+
title: string;
|
|
40
|
+
description?: string;
|
|
41
|
+
action?: ContentStateActionDescriptor;
|
|
42
|
+
}>;
|
|
43
|
+
export type ContentStateDescriptor = ContentStateLoadingDescriptor | ContentStateEmptyDescriptor | ContentStateErrorDescriptor;
|
|
44
|
+
/**
|
|
45
|
+
* `"sole"`: this action is the only content-level way forward (`scope:
|
|
46
|
+
* "screen"`) — render it as the product's primary/filled affordance.
|
|
47
|
+
* `"optional"`: recovery is one option among several still-working controls
|
|
48
|
+
* (`scope: "region"`) — render it de-emphasized so it never competes with a
|
|
49
|
+
* screen's real primary action. Named independently of any Button tone
|
|
50
|
+
* enum: HJM's current `ghost` tone (`src/recipes.ts`) resolves to a muted
|
|
51
|
+
* content color, not the brand-tinted text this repo's product code already
|
|
52
|
+
* renders for it (`AppButton tone="link"`, see docs). Until Button's tone
|
|
53
|
+
* vocabulary grows a brand-tinted low-emphasis tone, products map
|
|
54
|
+
* `"optional"` to whatever local tone matches that description.
|
|
55
|
+
*/
|
|
56
|
+
export type ContentStateActionEmphasis = "sole" | "optional";
|
|
57
|
+
export type ContentStateWebAnnouncement = Readonly<{
|
|
58
|
+
role: "status" | "alert";
|
|
59
|
+
live: "polite" | "assertive";
|
|
60
|
+
}>;
|
|
61
|
+
export type ContentStateNativeAnnouncement = Readonly<{
|
|
62
|
+
accessibilityLiveRegion: "polite" | "assertive";
|
|
63
|
+
accessibilityRole: "progressbar" | "alert" | "text";
|
|
64
|
+
/**
|
|
65
|
+
* Region-scope failures/empties must never pull the reader away from
|
|
66
|
+
* whatever else they were doing on the screen — that would announce as a
|
|
67
|
+
* whole-screen failure. Only `scope: "screen"`, which has no sibling
|
|
68
|
+
* content to protect, may move initial accessibility focus onto this
|
|
69
|
+
* block, and even then only for `error` — `empty` is calm information
|
|
70
|
+
* (§8.4 "빈 상태는 결핍이 아니라 초대다"), not an interruption, so it never
|
|
71
|
+
* steals focus regardless of scope.
|
|
72
|
+
*/
|
|
73
|
+
moveAccessibilityFocus: boolean;
|
|
74
|
+
}>;
|
|
75
|
+
export type ResolvedContentStateAction = Readonly<{
|
|
76
|
+
label: string;
|
|
77
|
+
accessibilityLabel: string;
|
|
78
|
+
onAction(): void;
|
|
79
|
+
emphasis: ContentStateActionEmphasis;
|
|
80
|
+
}>;
|
|
81
|
+
export type ResolvedContentStateDescriptor = Readonly<{
|
|
82
|
+
status: ContentStateStatus;
|
|
83
|
+
scope: ContentScope;
|
|
84
|
+
title: string | null;
|
|
85
|
+
description: string | null;
|
|
86
|
+
loadingLabel: string | null;
|
|
87
|
+
action: ResolvedContentStateAction | null;
|
|
88
|
+
web: ContentStateWebAnnouncement;
|
|
89
|
+
native: ContentStateNativeAnnouncement;
|
|
90
|
+
}>;
|
|
91
|
+
/**
|
|
92
|
+
* `loading` descriptors carry no `title`/`description`/`action` by design —
|
|
93
|
+
* a validator that reused one blanket "title required" check across every
|
|
94
|
+
* status would reject a perfectly valid loading block. Branch on `status`
|
|
95
|
+
* before asserting copy, and never assert fields the branch doesn't declare.
|
|
96
|
+
*/
|
|
97
|
+
export declare function validateContentStateDescriptor(descriptor: ContentStateDescriptor): void;
|
|
98
|
+
export declare function resolveContentStateActionEmphasis(scope: ContentScope): ContentStateActionEmphasis;
|
|
99
|
+
export declare function resolveContentStateAnnouncement(status: ContentStateStatus, scope: ContentScope): Readonly<{
|
|
100
|
+
web: ContentStateWebAnnouncement;
|
|
101
|
+
native: ContentStateNativeAnnouncement;
|
|
102
|
+
}>;
|
|
103
|
+
export declare function resolveContentStateDescriptor(descriptor: ContentStateDescriptor): ResolvedContentStateDescriptor;
|
|
104
|
+
//# sourceMappingURL=content-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-state.d.ts","sourceRoot":"","sources":["../src/content-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
function assertCopy(value, field) {
|
|
2
|
+
if (value.trim().length === 0) {
|
|
3
|
+
throw new TypeError(`ContentState ${field} must not be empty`);
|
|
4
|
+
}
|
|
5
|
+
}
|
|
6
|
+
function assertScope(scope) {
|
|
7
|
+
if (scope !== "screen" && scope !== "region") {
|
|
8
|
+
throw new TypeError(`Unsupported ContentState scope: ${String(scope)}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function assertAction(action, field) {
|
|
12
|
+
assertCopy(action.label, `${field}.label`);
|
|
13
|
+
if (action.accessibilityLabel !== undefined) {
|
|
14
|
+
assertCopy(action.accessibilityLabel, `${field}.accessibilityLabel`);
|
|
15
|
+
}
|
|
16
|
+
if (typeof action.onAction !== "function") {
|
|
17
|
+
throw new TypeError(`ContentState ${field}.onAction must be a function`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* `loading` descriptors carry no `title`/`description`/`action` by design —
|
|
22
|
+
* a validator that reused one blanket "title required" check across every
|
|
23
|
+
* status would reject a perfectly valid loading block. Branch on `status`
|
|
24
|
+
* before asserting copy, and never assert fields the branch doesn't declare.
|
|
25
|
+
*/
|
|
26
|
+
export function validateContentStateDescriptor(descriptor) {
|
|
27
|
+
assertScope(descriptor.scope);
|
|
28
|
+
const status = descriptor.status;
|
|
29
|
+
if (status !== "loading" && status !== "empty" && status !== "error") {
|
|
30
|
+
throw new TypeError(`Unsupported ContentState status: ${String(status)}`);
|
|
31
|
+
}
|
|
32
|
+
if (descriptor.status === "loading") {
|
|
33
|
+
assertCopy(descriptor.loadingLabel, "loadingLabel");
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
assertCopy(descriptor.title, "title");
|
|
37
|
+
if (descriptor.description !== undefined) {
|
|
38
|
+
assertCopy(descriptor.description, "description");
|
|
39
|
+
}
|
|
40
|
+
if (descriptor.action)
|
|
41
|
+
assertAction(descriptor.action, "action");
|
|
42
|
+
}
|
|
43
|
+
export function resolveContentStateActionEmphasis(scope) {
|
|
44
|
+
assertScope(scope);
|
|
45
|
+
return scope === "screen" ? "sole" : "optional";
|
|
46
|
+
}
|
|
47
|
+
export function resolveContentStateAnnouncement(status, scope) {
|
|
48
|
+
assertScope(scope);
|
|
49
|
+
if (status === "loading") {
|
|
50
|
+
return {
|
|
51
|
+
web: { role: "status", live: "polite" },
|
|
52
|
+
native: {
|
|
53
|
+
accessibilityLiveRegion: "polite",
|
|
54
|
+
accessibilityRole: "progressbar",
|
|
55
|
+
moveAccessibilityFocus: false,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (status === "empty") {
|
|
60
|
+
return {
|
|
61
|
+
web: { role: "status", live: "polite" },
|
|
62
|
+
native: {
|
|
63
|
+
accessibilityLiveRegion: "polite",
|
|
64
|
+
accessibilityRole: "text",
|
|
65
|
+
moveAccessibilityFocus: false,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (status === "error") {
|
|
70
|
+
return {
|
|
71
|
+
web: { role: "alert", live: "assertive" },
|
|
72
|
+
native: {
|
|
73
|
+
accessibilityLiveRegion: "assertive",
|
|
74
|
+
accessibilityRole: "alert",
|
|
75
|
+
moveAccessibilityFocus: scope === "screen",
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
throw new TypeError(`Unsupported ContentState status: ${String(status)}`);
|
|
80
|
+
}
|
|
81
|
+
export function resolveContentStateDescriptor(descriptor) {
|
|
82
|
+
validateContentStateDescriptor(descriptor);
|
|
83
|
+
const { web, native } = resolveContentStateAnnouncement(descriptor.status, descriptor.scope);
|
|
84
|
+
if (descriptor.status === "loading") {
|
|
85
|
+
return {
|
|
86
|
+
status: "loading",
|
|
87
|
+
scope: descriptor.scope,
|
|
88
|
+
title: null,
|
|
89
|
+
description: null,
|
|
90
|
+
loadingLabel: descriptor.loadingLabel,
|
|
91
|
+
action: null,
|
|
92
|
+
web,
|
|
93
|
+
native,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const emphasis = resolveContentStateActionEmphasis(descriptor.scope);
|
|
97
|
+
const action = descriptor.action
|
|
98
|
+
? {
|
|
99
|
+
label: descriptor.action.label,
|
|
100
|
+
accessibilityLabel: descriptor.action.accessibilityLabel ?? descriptor.action.label,
|
|
101
|
+
onAction: descriptor.action.onAction,
|
|
102
|
+
emphasis,
|
|
103
|
+
}
|
|
104
|
+
: null;
|
|
105
|
+
return {
|
|
106
|
+
status: descriptor.status,
|
|
107
|
+
scope: descriptor.scope,
|
|
108
|
+
title: descriptor.title,
|
|
109
|
+
description: descriptor.description ?? null,
|
|
110
|
+
loadingLabel: null,
|
|
111
|
+
action,
|
|
112
|
+
web,
|
|
113
|
+
native,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=content-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-state.js","sourceRoot":"","sources":["../src/content-state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Products render `idle|loading|loadingMore|empty|error` content states (see\n * `docs/expansion-roadmap.md`'s common state axis table) at two different\n * granularities: replacing an entire screen's content, or replacing one\n * region while the rest of the screen keeps working. That granularity is a\n * second, orthogonal axis — `scope` — not a new content value and not the\n * `status` axis `Result` owns (`docs/result.md`). This module is that axis\n * plus what it forces: action emphasis and accessibility announcement scope.\n *\n * `loadingMore` and `complete` are excluded from `ContentStateStatus` on\n * purpose. Both belong to `LoadMore`'s footer, which is a region by\n * construction (a list footer is never a whole screen) and already owns its\n * own state machine (`src/load-more.ts`). `idle` and `success` render no\n * block at all — the caller shows real content instead.\n */\nexport type ContentScope = \"screen\" | \"region\";\n\nexport type ContentStateStatus = \"loading\" | \"empty\" | \"error\";\n\nexport type ContentStateActionDescriptor = Readonly<{\n label: string;\n accessibilityLabel?: string;\n onAction(): void;\n}>;\n\nexport type ContentStateLoadingDescriptor = Readonly<{\n status: \"loading\";\n scope: ContentScope;\n /** The only accessible signal for a loading block; there is no title/action slot. */\n loadingLabel: string;\n}>;\n\nexport type ContentStateEmptyDescriptor = Readonly<{\n status: \"empty\";\n scope: ContentScope;\n title: string;\n description?: string;\n action?: ContentStateActionDescriptor;\n}>;\n\nexport type ContentStateErrorDescriptor = Readonly<{\n status: \"error\";\n scope: ContentScope;\n title: string;\n description?: string;\n action?: ContentStateActionDescriptor;\n}>;\n\nexport type ContentStateDescriptor =\n | ContentStateLoadingDescriptor\n | ContentStateEmptyDescriptor\n | ContentStateErrorDescriptor;\n\n/**\n * `\"sole\"`: this action is the only content-level way forward (`scope:\n * \"screen\"`) — render it as the product's primary/filled affordance.\n * `\"optional\"`: recovery is one option among several still-working controls\n * (`scope: \"region\"`) — render it de-emphasized so it never competes with a\n * screen's real primary action. Named independently of any Button tone\n * enum: HJM's current `ghost` tone (`src/recipes.ts`) resolves to a muted\n * content color, not the brand-tinted text this repo's product code already\n * renders for it (`AppButton tone=\"link\"`, see docs). Until Button's tone\n * vocabulary grows a brand-tinted low-emphasis tone, products map\n * `\"optional\"` to whatever local tone matches that description.\n */\nexport type ContentStateActionEmphasis = \"sole\" | \"optional\";\n\nexport type ContentStateWebAnnouncement = Readonly<{\n role: \"status\" | \"alert\";\n live: \"polite\" | \"assertive\";\n}>;\n\nexport type ContentStateNativeAnnouncement = Readonly<{\n accessibilityLiveRegion: \"polite\" | \"assertive\";\n accessibilityRole: \"progressbar\" | \"alert\" | \"text\";\n /**\n * Region-scope failures/empties must never pull the reader away from\n * whatever else they were doing on the screen — that would announce as a\n * whole-screen failure. Only `scope: \"screen\"`, which has no sibling\n * content to protect, may move initial accessibility focus onto this\n * block, and even then only for `error` — `empty` is calm information\n * (§8.4 \"빈 상태는 결핍이 아니라 초대다\"), not an interruption, so it never\n * steals focus regardless of scope.\n */\n moveAccessibilityFocus: boolean;\n}>;\n\nexport type ResolvedContentStateAction = Readonly<{\n label: string;\n accessibilityLabel: string;\n onAction(): void;\n emphasis: ContentStateActionEmphasis;\n}>;\n\nexport type ResolvedContentStateDescriptor = Readonly<{\n status: ContentStateStatus;\n scope: ContentScope;\n title: string | null;\n description: string | null;\n loadingLabel: string | null;\n action: ResolvedContentStateAction | null;\n web: ContentStateWebAnnouncement;\n native: ContentStateNativeAnnouncement;\n}>;\n\nfunction assertCopy(value: string, field: string): void {\n if (value.trim().length === 0) {\n throw new TypeError(`ContentState ${field} must not be empty`);\n }\n}\n\nfunction assertScope(scope: ContentScope): void {\n if (scope !== \"screen\" && scope !== \"region\") {\n throw new TypeError(`Unsupported ContentState scope: ${String(scope)}`);\n }\n}\n\nfunction assertAction(\n action: ContentStateActionDescriptor,\n field: string,\n): void {\n assertCopy(action.label, `${field}.label`);\n if (action.accessibilityLabel !== undefined) {\n assertCopy(action.accessibilityLabel, `${field}.accessibilityLabel`);\n }\n if (typeof action.onAction !== \"function\") {\n throw new TypeError(`ContentState ${field}.onAction must be a function`);\n }\n}\n\n/**\n * `loading` descriptors carry no `title`/`description`/`action` by design —\n * a validator that reused one blanket \"title required\" check across every\n * status would reject a perfectly valid loading block. Branch on `status`\n * before asserting copy, and never assert fields the branch doesn't declare.\n */\nexport function validateContentStateDescriptor(\n descriptor: ContentStateDescriptor,\n): void {\n assertScope(descriptor.scope);\n const status = (descriptor as Readonly<{ status?: unknown }>).status;\n if (status !== \"loading\" && status !== \"empty\" && status !== \"error\") {\n throw new TypeError(`Unsupported ContentState status: ${String(status)}`);\n }\n if (descriptor.status === \"loading\") {\n assertCopy(descriptor.loadingLabel, \"loadingLabel\");\n return;\n }\n assertCopy(descriptor.title, \"title\");\n if (descriptor.description !== undefined) {\n assertCopy(descriptor.description, \"description\");\n }\n if (descriptor.action) assertAction(descriptor.action, \"action\");\n}\n\nexport function resolveContentStateActionEmphasis(\n scope: ContentScope,\n): ContentStateActionEmphasis {\n assertScope(scope);\n return scope === \"screen\" ? \"sole\" : \"optional\";\n}\n\nexport function resolveContentStateAnnouncement(\n status: ContentStateStatus,\n scope: ContentScope,\n): Readonly<{\n web: ContentStateWebAnnouncement;\n native: ContentStateNativeAnnouncement;\n}> {\n assertScope(scope);\n if (status === \"loading\") {\n return {\n web: { role: \"status\", live: \"polite\" },\n native: {\n accessibilityLiveRegion: \"polite\",\n accessibilityRole: \"progressbar\",\n moveAccessibilityFocus: false,\n },\n };\n }\n if (status === \"empty\") {\n return {\n web: { role: \"status\", live: \"polite\" },\n native: {\n accessibilityLiveRegion: \"polite\",\n accessibilityRole: \"text\",\n moveAccessibilityFocus: false,\n },\n };\n }\n if (status === \"error\") {\n return {\n web: { role: \"alert\", live: \"assertive\" },\n native: {\n accessibilityLiveRegion: \"assertive\",\n accessibilityRole: \"alert\",\n moveAccessibilityFocus: scope === \"screen\",\n },\n };\n }\n throw new TypeError(`Unsupported ContentState status: ${String(status)}`);\n}\n\nexport function resolveContentStateDescriptor(\n descriptor: ContentStateDescriptor,\n): ResolvedContentStateDescriptor {\n validateContentStateDescriptor(descriptor);\n const { web, native } = resolveContentStateAnnouncement(\n descriptor.status,\n descriptor.scope,\n );\n\n if (descriptor.status === \"loading\") {\n return {\n status: \"loading\",\n scope: descriptor.scope,\n title: null,\n description: null,\n loadingLabel: descriptor.loadingLabel,\n action: null,\n web,\n native,\n };\n }\n\n const emphasis = resolveContentStateActionEmphasis(descriptor.scope);\n const action: ResolvedContentStateAction | null = descriptor.action\n ? {\n label: descriptor.action.label,\n accessibilityLabel:\n descriptor.action.accessibilityLabel ?? descriptor.action.label,\n onAction: descriptor.action.onAction,\n emphasis,\n }\n : null;\n\n return {\n status: descriptor.status,\n scope: descriptor.scope,\n title: descriptor.title,\n description: descriptor.description ?? null,\n loadingLabel: null,\n action,\n web,\n native,\n };\n}\n"]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export { counterBadgeDefaults, formatCounterBadgeCount, type CounterBadgeSize, type CounterBadgeTone, type CounterBadgeVariant, } from "./counter-badge.js";
|
|
2
|
+
/** Numeric counters use a compact solid plate, distinct from status badges. */
|
|
3
|
+
export declare const counterBadgeRecipe: {
|
|
4
|
+
readonly slots: readonly ["root", "label"];
|
|
5
|
+
readonly defaults: {
|
|
6
|
+
readonly tone: "danger";
|
|
7
|
+
readonly size: "medium";
|
|
8
|
+
readonly variant: "inline";
|
|
9
|
+
readonly max: 99;
|
|
10
|
+
};
|
|
11
|
+
readonly tones: {
|
|
12
|
+
readonly danger: {
|
|
13
|
+
readonly background: Readonly<{
|
|
14
|
+
source: "theme";
|
|
15
|
+
key: "dangerFill";
|
|
16
|
+
alpha?: number;
|
|
17
|
+
}>;
|
|
18
|
+
readonly content: Readonly<{
|
|
19
|
+
source: "theme";
|
|
20
|
+
key: "onDanger";
|
|
21
|
+
alpha?: number;
|
|
22
|
+
}>;
|
|
23
|
+
};
|
|
24
|
+
readonly brand: {
|
|
25
|
+
readonly background: Readonly<{
|
|
26
|
+
source: "theme";
|
|
27
|
+
key: "primary";
|
|
28
|
+
alpha?: number;
|
|
29
|
+
}>;
|
|
30
|
+
readonly content: Readonly<{
|
|
31
|
+
source: "theme";
|
|
32
|
+
key: "onPrimary";
|
|
33
|
+
alpha?: number;
|
|
34
|
+
}>;
|
|
35
|
+
};
|
|
36
|
+
readonly neutral: {
|
|
37
|
+
readonly background: Readonly<{
|
|
38
|
+
source: "theme";
|
|
39
|
+
key: "textBody";
|
|
40
|
+
alpha?: number;
|
|
41
|
+
}>;
|
|
42
|
+
readonly content: Readonly<{
|
|
43
|
+
source: "theme";
|
|
44
|
+
key: "bg";
|
|
45
|
+
alpha?: number;
|
|
46
|
+
}>;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
readonly sizes: {
|
|
50
|
+
readonly small: {
|
|
51
|
+
readonly height: 16;
|
|
52
|
+
readonly minWidth: 16;
|
|
53
|
+
readonly paddingHorizontal: 4;
|
|
54
|
+
readonly textVariant: "caption";
|
|
55
|
+
};
|
|
56
|
+
readonly medium: {
|
|
57
|
+
readonly height: 20;
|
|
58
|
+
readonly minWidth: 20;
|
|
59
|
+
readonly paddingHorizontal: 8;
|
|
60
|
+
readonly textVariant: "caption";
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
readonly variants: {
|
|
64
|
+
readonly inline: {
|
|
65
|
+
readonly border: null;
|
|
66
|
+
readonly borderWidth: 0;
|
|
67
|
+
};
|
|
68
|
+
readonly floating: {
|
|
69
|
+
readonly border: Readonly<{
|
|
70
|
+
source: "theme";
|
|
71
|
+
key: "bg";
|
|
72
|
+
alpha?: number;
|
|
73
|
+
}>;
|
|
74
|
+
readonly borderWidth: 2;
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
readonly radius: "full";
|
|
78
|
+
readonly fontWeight: "700";
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=counter-badge-recipe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"counter-badge-recipe.d.ts","sourceRoot":"","sources":["../src/counter-badge-recipe.ts"],"names":[],"mappings":"AAiBA,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC;AAE5B,+EAA+E;AAC/E,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgE9B,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { fontWeight, radius, spacing, stroke, } from "./foundations.js";
|
|
2
|
+
import { semanticColors } from "./semantic-colors.js";
|
|
3
|
+
import { counterBadgeDefaults, } from "./counter-badge.js";
|
|
4
|
+
export { counterBadgeDefaults, formatCounterBadgeCount, } from "./counter-badge.js";
|
|
5
|
+
/** Numeric counters use a compact solid plate, distinct from status badges. */
|
|
6
|
+
export const counterBadgeRecipe = {
|
|
7
|
+
slots: ["root", "label"],
|
|
8
|
+
defaults: counterBadgeDefaults,
|
|
9
|
+
tones: {
|
|
10
|
+
danger: {
|
|
11
|
+
background: semanticColors.action.danger.background,
|
|
12
|
+
content: semanticColors.action.danger.content,
|
|
13
|
+
},
|
|
14
|
+
brand: {
|
|
15
|
+
background: semanticColors.action.brand.background,
|
|
16
|
+
content: semanticColors.action.brand.content,
|
|
17
|
+
},
|
|
18
|
+
neutral: {
|
|
19
|
+
background: semanticColors.content.body,
|
|
20
|
+
content: semanticColors.canvas,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
sizes: {
|
|
24
|
+
small: {
|
|
25
|
+
height: 16,
|
|
26
|
+
minWidth: 16,
|
|
27
|
+
paddingHorizontal: spacing.xxs,
|
|
28
|
+
textVariant: "caption",
|
|
29
|
+
},
|
|
30
|
+
medium: {
|
|
31
|
+
height: 20,
|
|
32
|
+
minWidth: 20,
|
|
33
|
+
paddingHorizontal: spacing.xs,
|
|
34
|
+
textVariant: "caption",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
variants: {
|
|
38
|
+
inline: { border: null, borderWidth: 0 },
|
|
39
|
+
floating: { border: semanticColors.canvas, borderWidth: stroke.strong },
|
|
40
|
+
},
|
|
41
|
+
radius: "full",
|
|
42
|
+
fontWeight: fontWeight.bold,
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=counter-badge-recipe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"counter-badge-recipe.js","sourceRoot":"","sources":["../src/counter-badge-recipe.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,MAAM,EACN,OAAO,EACP,MAAM,GAGP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,oBAAoB,GAIrB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,oBAAoB,EACpB,uBAAuB,GAIxB,MAAM,oBAAoB,CAAC;AAE5B,+EAA+E;AAC/E,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,CAAU;IACjC,QAAQ,EAAE,oBAAoB;IAC9B,KAAK,EAAE;QACL,MAAM,EAAE;YACN,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;YACnD,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO;SAC9C;QACD,KAAK,EAAE;YACL,UAAU,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU;YAClD,OAAO,EAAE,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO;SAC7C;QACD,OAAO,EAAE;YACP,UAAU,EAAE,cAAc,CAAC,OAAO,CAAC,IAAI;YACvC,OAAO,EAAE,cAAc,CAAC,MAAM;SAC/B;KACF;IACD,KAAK,EAAE;QACL,KAAK,EAAE;YACL,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,EAAE;YACZ,iBAAiB,EAAE,OAAO,CAAC,GAAG;YAC9B,WAAW,EAAE,SAAS;SACvB;QACD,MAAM,EAAE;YACN,MAAM,EAAE,EAAE;YACV,QAAQ,EAAE,EAAE;YACZ,iBAAiB,EAAE,OAAO,CAAC,EAAE;YAC7B,WAAW,EAAE,SAAS;SACvB;KACF;IACD,QAAQ,EAAE;QACR,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE;QACxC,QAAQ,EAAE,EAAE,MAAM,EAAE,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;KACxE;IACD,MAAM,EAAE,MAAM;IACd,UAAU,EAAE,UAAU,CAAC,IAAI;CA4B5B,CAAC","sourcesContent":["import type { ColorReference } from \"./color-references.js\";\nimport {\n fontWeight,\n radius,\n spacing,\n stroke,\n type FontWeightValue,\n type TextVariant,\n} from \"./foundations.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\nimport {\n counterBadgeDefaults,\n type CounterBadgeSize,\n type CounterBadgeTone,\n type CounterBadgeVariant,\n} from \"./counter-badge.js\";\n\nexport {\n counterBadgeDefaults,\n formatCounterBadgeCount,\n type CounterBadgeSize,\n type CounterBadgeTone,\n type CounterBadgeVariant,\n} from \"./counter-badge.js\";\n\n/** Numeric counters use a compact solid plate, distinct from status badges. */\nexport const counterBadgeRecipe = {\n slots: [\"root\", \"label\"] as const,\n defaults: counterBadgeDefaults,\n tones: {\n danger: {\n background: semanticColors.action.danger.background,\n content: semanticColors.action.danger.content,\n },\n brand: {\n background: semanticColors.action.brand.background,\n content: semanticColors.action.brand.content,\n },\n neutral: {\n background: semanticColors.content.body,\n content: semanticColors.canvas,\n },\n },\n sizes: {\n small: {\n height: 16,\n minWidth: 16,\n paddingHorizontal: spacing.xxs,\n textVariant: \"caption\",\n },\n medium: {\n height: 20,\n minWidth: 20,\n paddingHorizontal: spacing.xs,\n textVariant: \"caption\",\n },\n },\n variants: {\n inline: { border: null, borderWidth: 0 },\n floating: { border: semanticColors.canvas, borderWidth: stroke.strong },\n },\n radius: \"full\",\n fontWeight: fontWeight.bold,\n} as const satisfies {\n slots: readonly [\"root\", \"label\"];\n defaults: {\n tone: CounterBadgeTone;\n size: CounterBadgeSize;\n variant: CounterBadgeVariant;\n max: number;\n };\n tones: Record<\n CounterBadgeTone,\n { background: ColorReference; content: ColorReference }\n >;\n sizes: Record<\n CounterBadgeSize,\n {\n height: number;\n minWidth: number;\n paddingHorizontal: number;\n textVariant: TextVariant;\n }\n >;\n variants: Record<\n CounterBadgeVariant,\n { border: ColorReference | null; borderWidth: number }\n >;\n radius: keyof typeof radius;\n fontWeight: FontWeightValue;\n};\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type CounterBadgeTone = "danger" | "brand" | "neutral";
|
|
2
|
+
export type CounterBadgeSize = "small" | "medium";
|
|
3
|
+
export type CounterBadgeVariant = "inline" | "floating";
|
|
4
|
+
/** Shared defaults usable without importing the visual recipe barrel. */
|
|
5
|
+
export declare const counterBadgeDefaults: {
|
|
6
|
+
readonly tone: "danger";
|
|
7
|
+
readonly size: "medium";
|
|
8
|
+
readonly variant: "inline";
|
|
9
|
+
readonly max: 99;
|
|
10
|
+
};
|
|
11
|
+
export declare function formatCounterBadgeCount(count: number, max?: number): string | null;
|
|
12
|
+
//# sourceMappingURL=counter-badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"counter-badge.d.ts","sourceRoot":"","sources":["../src/counter-badge.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,QAAQ,CAAC;AAClD,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,UAAU,CAAC;AAExD,yEAAyE;AACzE,eAAO,MAAM,oBAAoB;;;;;CAU/B,CAAC;AAEH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,GAAG,GAAE,MAAiC,GACrC,MAAM,GAAG,IAAI,CAWf"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Shared defaults usable without importing the visual recipe barrel. */
|
|
2
|
+
export const counterBadgeDefaults = {
|
|
3
|
+
tone: "danger",
|
|
4
|
+
size: "medium",
|
|
5
|
+
variant: "inline",
|
|
6
|
+
max: 99,
|
|
7
|
+
};
|
|
8
|
+
export function formatCounterBadgeCount(count, max = counterBadgeDefaults.max) {
|
|
9
|
+
const normalizedCount = Number.isFinite(count)
|
|
10
|
+
? Math.max(0, Math.trunc(count))
|
|
11
|
+
: 0;
|
|
12
|
+
if (normalizedCount === 0)
|
|
13
|
+
return null;
|
|
14
|
+
const normalizedMax = Number.isFinite(max)
|
|
15
|
+
? Math.max(1, Math.trunc(max))
|
|
16
|
+
: counterBadgeDefaults.max;
|
|
17
|
+
return normalizedCount > normalizedMax
|
|
18
|
+
? `${normalizedMax}+`
|
|
19
|
+
: String(normalizedCount);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=counter-badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"counter-badge.js","sourceRoot":"","sources":["../src/counter-badge.ts"],"names":[],"mappings":"AAIA,yEAAyE;AACzE,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,QAAQ;IACjB,GAAG,EAAE,EAAE;CAMP,CAAC;AAEH,MAAM,UAAU,uBAAuB,CACrC,KAAa,EACb,MAAc,oBAAoB,CAAC,GAAG;IAEtC,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC5C,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC,CAAC;IACN,IAAI,eAAe,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QACxC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC;IAC7B,OAAO,eAAe,GAAG,aAAa;QACpC,CAAC,CAAC,GAAG,aAAa,GAAG;QACrB,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;AAC9B,CAAC","sourcesContent":["export type CounterBadgeTone = \"danger\" | \"brand\" | \"neutral\";\nexport type CounterBadgeSize = \"small\" | \"medium\";\nexport type CounterBadgeVariant = \"inline\" | \"floating\";\n\n/** Shared defaults usable without importing the visual recipe barrel. */\nexport const counterBadgeDefaults = {\n tone: \"danger\",\n size: \"medium\",\n variant: \"inline\",\n max: 99,\n} as const satisfies Readonly<{\n tone: CounterBadgeTone;\n size: CounterBadgeSize;\n variant: CounterBadgeVariant;\n max: number;\n}>;\n\nexport function formatCounterBadgeCount(\n count: number,\n max: number = counterBadgeDefaults.max,\n): string | null {\n const normalizedCount = Number.isFinite(count)\n ? Math.max(0, Math.trunc(count))\n : 0;\n if (normalizedCount === 0) return null;\n const normalizedMax = Number.isFinite(max)\n ? Math.max(1, Math.trunc(max))\n : counterBadgeDefaults.max;\n return normalizedCount > normalizedMax\n ? `${normalizedMax}+`\n : String(normalizedCount);\n}\n"]}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import type { AsyncCollectionState, CheckboxState, CollectionKey, CollectionSelectionModel } from "./behaviors.js";
|
|
2
|
+
export type DataTableAlign = "start" | "center" | "end";
|
|
3
|
+
export type DataTableColumnDescriptor<Key extends CollectionKey = CollectionKey> = Readonly<{
|
|
4
|
+
id: Key;
|
|
5
|
+
/** Visible column header text; also the columnheader's accessible name. */
|
|
6
|
+
header: string;
|
|
7
|
+
align?: DataTableAlign;
|
|
8
|
+
sortable?: boolean;
|
|
9
|
+
/** Layout hint only (px or flex-basis); renderers may ignore or clamp it. */
|
|
10
|
+
width?: number;
|
|
11
|
+
}>;
|
|
12
|
+
export declare const dataTableColumnDefaults: {
|
|
13
|
+
readonly align: "start";
|
|
14
|
+
readonly sortable: false;
|
|
15
|
+
};
|
|
16
|
+
export declare function validateDataTableColumns<Key extends CollectionKey>(columns: readonly DataTableColumnDescriptor<Key>[]): void;
|
|
17
|
+
/**
|
|
18
|
+
* Row identity and selection deliberately do NOT reuse `CollectionItemDescriptor`
|
|
19
|
+
* verbatim: a table row has no single visible `label`/`textValue` the way a
|
|
20
|
+
* Menu or Select item does — its "content" is however many columns the
|
|
21
|
+
* product renders per row. Only the parts of the Collection base contract
|
|
22
|
+
* that are genuinely row-shaped (`CollectionKey` identity, `disabled`) apply.
|
|
23
|
+
*/
|
|
24
|
+
export type DataTableRowDescriptor<Key extends CollectionKey = CollectionKey> = Readonly<{
|
|
25
|
+
id: Key;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
export declare function validateDataTableRows<Key extends CollectionKey>(rows: readonly DataTableRowDescriptor<Key>[]): void;
|
|
29
|
+
/** Row selection is the unmodified Collection base contract — no DataTable-only selection shape. */
|
|
30
|
+
export type DataTableSelection<Key extends CollectionKey = CollectionKey> = CollectionSelectionModel<Key>;
|
|
31
|
+
/**
|
|
32
|
+
* Header "select all" state as the same tri-state `CheckboxState` the
|
|
33
|
+
* selection column's checkbox already renders (check/dash), instead of a new
|
|
34
|
+
* `"none" | "some" | "all"` enum the recipe would have to translate again.
|
|
35
|
+
* Disabled rows are excluded from both the denominator and the count.
|
|
36
|
+
*/
|
|
37
|
+
export declare function resolveDataTableSelectAllState<Key extends CollectionKey>(rows: readonly DataTableRowDescriptor<Key>[], selectedKeys: ReadonlySet<Key>): CheckboxState;
|
|
38
|
+
/**
|
|
39
|
+
* Values are the literal `aria-sort` vocabulary (minus `"none"`, which is
|
|
40
|
+
* `null`) so the Web renderer passes them through without a translation
|
|
41
|
+
* table — the same "pass the platform value through" choice Slider makes
|
|
42
|
+
* for `valueText`.
|
|
43
|
+
*/
|
|
44
|
+
export type DataTableSortDirection = "ascending" | "descending";
|
|
45
|
+
export type DataTableSortState<Key extends CollectionKey = CollectionKey> = Readonly<{
|
|
46
|
+
columnId: Key;
|
|
47
|
+
direction: DataTableSortDirection;
|
|
48
|
+
}> | null;
|
|
49
|
+
export type DataTableSortCycle = "two-state" | "three-state";
|
|
50
|
+
export declare const dataTableDefaults: {
|
|
51
|
+
readonly sortCycle: "three-state";
|
|
52
|
+
};
|
|
53
|
+
export declare function validateDataTableSortState<Key extends CollectionKey>(state: DataTableSortState<Key>, columns: readonly DataTableColumnDescriptor<Key>[]): void;
|
|
54
|
+
/**
|
|
55
|
+
* Pure toggle: does not read or write product data. The product still owns
|
|
56
|
+
* actually re-sorting rows (Combobox's local/external filtering split is the
|
|
57
|
+
* same boundary — HJM judges intent, never executes the data operation).
|
|
58
|
+
*/
|
|
59
|
+
export declare function getNextDataTableSortState<Key extends CollectionKey>(current: DataTableSortState<Key>, columnId: Key, cycle?: DataTableSortCycle): DataTableSortState<Key>;
|
|
60
|
+
/** The whole table's row-loading status — the unmodified Collection base async contract. */
|
|
61
|
+
export type DataTableAsyncState = AsyncCollectionState;
|
|
62
|
+
export type DataTableDensity = "compact" | "regular";
|
|
63
|
+
/**
|
|
64
|
+
* Reuses `collectionItemContract`'s hover/selected/focus tokens instead of a
|
|
65
|
+
* second set of row-interaction colors — Menu, Select, and DataTable rows
|
|
66
|
+
* stay one visual vocabulary.
|
|
67
|
+
*/
|
|
68
|
+
export declare const dataTableRecipe: {
|
|
69
|
+
readonly slots: readonly ["root", "header", "headerCell", "sortButton", "sortIcon", "row", "cell", "selectionCell", "emptyState", "errorState"];
|
|
70
|
+
readonly defaults: {
|
|
71
|
+
readonly density: "regular";
|
|
72
|
+
};
|
|
73
|
+
readonly density: {
|
|
74
|
+
readonly compact: {
|
|
75
|
+
readonly paddingVertical: 8;
|
|
76
|
+
readonly paddingHorizontal: 12;
|
|
77
|
+
};
|
|
78
|
+
readonly regular: {
|
|
79
|
+
readonly paddingVertical: 12;
|
|
80
|
+
readonly paddingHorizontal: 16;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
readonly header: {
|
|
84
|
+
readonly background: Readonly<{
|
|
85
|
+
source: "theme";
|
|
86
|
+
key: "surfaceAlt";
|
|
87
|
+
alpha?: number;
|
|
88
|
+
}>;
|
|
89
|
+
readonly color: Readonly<{
|
|
90
|
+
source: "theme";
|
|
91
|
+
key: "textMuted";
|
|
92
|
+
alpha?: number;
|
|
93
|
+
}>;
|
|
94
|
+
readonly textVariant: "label";
|
|
95
|
+
readonly fontWeight: "700";
|
|
96
|
+
readonly borderBottom: Readonly<{
|
|
97
|
+
source: "theme";
|
|
98
|
+
key: "border";
|
|
99
|
+
alpha?: number;
|
|
100
|
+
}>;
|
|
101
|
+
};
|
|
102
|
+
readonly row: {
|
|
103
|
+
readonly borderBottom: Readonly<{
|
|
104
|
+
source: "theme";
|
|
105
|
+
key: "border";
|
|
106
|
+
alpha?: number;
|
|
107
|
+
}>;
|
|
108
|
+
readonly hoverBackground: Readonly<{
|
|
109
|
+
source: "theme";
|
|
110
|
+
key: "text";
|
|
111
|
+
alpha?: number;
|
|
112
|
+
}>;
|
|
113
|
+
readonly selectedBackground: Readonly<{
|
|
114
|
+
source: "theme";
|
|
115
|
+
key: "primary";
|
|
116
|
+
alpha?: number;
|
|
117
|
+
}>;
|
|
118
|
+
};
|
|
119
|
+
readonly cell: {
|
|
120
|
+
readonly color: Readonly<{
|
|
121
|
+
source: "theme";
|
|
122
|
+
key: "textBody";
|
|
123
|
+
alpha?: number;
|
|
124
|
+
}>;
|
|
125
|
+
readonly textVariant: "body";
|
|
126
|
+
};
|
|
127
|
+
readonly sortButton: {
|
|
128
|
+
readonly minTarget: 44;
|
|
129
|
+
readonly color: Readonly<{
|
|
130
|
+
source: "theme";
|
|
131
|
+
key: "textMuted";
|
|
132
|
+
alpha?: number;
|
|
133
|
+
}>;
|
|
134
|
+
readonly activeColor: Readonly<{
|
|
135
|
+
source: "theme";
|
|
136
|
+
key: "contentBrand";
|
|
137
|
+
alpha?: number;
|
|
138
|
+
}>;
|
|
139
|
+
};
|
|
140
|
+
readonly selectionCell: {
|
|
141
|
+
readonly width: 44;
|
|
142
|
+
};
|
|
143
|
+
readonly emptyState: {
|
|
144
|
+
readonly color: Readonly<{
|
|
145
|
+
source: "theme";
|
|
146
|
+
key: "textMuted";
|
|
147
|
+
alpha?: number;
|
|
148
|
+
}>;
|
|
149
|
+
readonly textVariant: "body";
|
|
150
|
+
};
|
|
151
|
+
readonly errorState: {
|
|
152
|
+
readonly color: Readonly<{
|
|
153
|
+
source: "theme";
|
|
154
|
+
key: "danger";
|
|
155
|
+
alpha?: number;
|
|
156
|
+
}>;
|
|
157
|
+
readonly textVariant: "body";
|
|
158
|
+
};
|
|
159
|
+
readonly states: {
|
|
160
|
+
readonly focus: {
|
|
161
|
+
readonly color: Readonly<{
|
|
162
|
+
source: "theme";
|
|
163
|
+
key: "contentBrand";
|
|
164
|
+
alpha?: number;
|
|
165
|
+
}>;
|
|
166
|
+
readonly width: 2;
|
|
167
|
+
readonly offset: 2;
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* No roving-tabindex grid keyboard navigation (arrow keys between cells):
|
|
173
|
+
* no product using this contract has measured demand for full ARIA-grid
|
|
174
|
+
* traversal, and it is a materially bigger accessibility surface than a
|
|
175
|
+
* sortable header button plus native checkbox/radio tab stops.
|
|
176
|
+
*/
|
|
177
|
+
export declare const dataTableBehavior: {
|
|
178
|
+
readonly controlled: readonly ["selection"];
|
|
179
|
+
readonly inputs: readonly ["columns", "rows", "sortState", "asyncState"];
|
|
180
|
+
readonly events: readonly ["onSortChange"];
|
|
181
|
+
readonly configuration: {
|
|
182
|
+
readonly sortCycle: readonly ["two-state", "three-state"];
|
|
183
|
+
};
|
|
184
|
+
readonly defaults: {
|
|
185
|
+
readonly sortCycle: "three-state";
|
|
186
|
+
};
|
|
187
|
+
readonly stateAxes: {
|
|
188
|
+
readonly value: readonly ["selected"];
|
|
189
|
+
readonly content: readonly ["idle", "loading", "loadingMore", "empty", "error"];
|
|
190
|
+
};
|
|
191
|
+
readonly web: {
|
|
192
|
+
readonly roles: readonly ["table", "row", "columnheader", "cell", "button", "checkbox", "radio"];
|
|
193
|
+
readonly keyboard: readonly ["Tab", "Enter", "Space"];
|
|
194
|
+
readonly focus: "native";
|
|
195
|
+
};
|
|
196
|
+
readonly native: {
|
|
197
|
+
readonly roles: readonly [];
|
|
198
|
+
readonly states: readonly [];
|
|
199
|
+
readonly actions: readonly [];
|
|
200
|
+
};
|
|
201
|
+
readonly scenarios: readonly ["row-selection-reuses-the-shared-collection-selection-model-unchanged", "select-all-reuses-the-shared-tri-state-checkbox-value", "async-state-reuses-the-shared-collection-async-state-unchanged", "sortable-header-is-a-button-inside-the-columnheader-not-the-header-itself", "sort-direction-values-pass-through-to-aria-sort-without-translation", "disabled-rows-are-excluded-from-select-all-accounting", "pagination-or-load-more-is-composed-beneath-the-table-not-owned-by-it", "row-expansion-is-not-owned-here-compose-the-disclosure-group-contract-per-row", "a-data-cell-exposes-at-most-one-focusable-control", "no-roving-tabindex-grid-navigation-is-implied"];
|
|
202
|
+
};
|
|
203
|
+
//# sourceMappingURL=data-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-table.d.ts","sourceRoot":"","sources":["../src/data-table.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EAEpB,aAAa,EACb,aAAa,EACb,wBAAwB,EACzB,MAAM,gBAAgB,CAAC;AAKxB,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAExD,MAAM,MAAM,yBAAyB,CAAC,GAAG,SAAS,aAAa,GAAG,aAAa,IAAI,QAAQ,CAAC;IAC1F,EAAE,EAAE,GAAG,CAAC;IACR,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;CAGuC,CAAC;AAQ5E,wBAAgB,wBAAwB,CAAC,GAAG,SAAS,aAAa,EAChE,OAAO,EAAE,SAAS,yBAAyB,CAAC,GAAG,CAAC,EAAE,GACjD,IAAI,CAgBN;AAED;;;;;;GAMG;AACH,MAAM,MAAM,sBAAsB,CAAC,GAAG,SAAS,aAAa,GAAG,aAAa,IAAI,QAAQ,CAAC;IACvF,EAAE,EAAE,GAAG,CAAC;IACR,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC,CAAC;AAEH,wBAAgB,qBAAqB,CAAC,GAAG,SAAS,aAAa,EAC7D,IAAI,EAAE,SAAS,sBAAsB,CAAC,GAAG,CAAC,EAAE,GAC3C,IAAI,CASN;AAED,oGAAoG;AACpG,MAAM,MAAM,kBAAkB,CAAC,GAAG,SAAS,aAAa,GAAG,aAAa,IACtE,wBAAwB,CAAC,GAAG,CAAC,CAAC;AAEhC;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAAC,GAAG,SAAS,aAAa,EACtE,IAAI,EAAE,SAAS,sBAAsB,CAAC,GAAG,CAAC,EAAE,EAC5C,YAAY,EAAE,WAAW,CAAC,GAAG,CAAC,GAC7B,aAAa,CAOf;AAED;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG,WAAW,GAAG,YAAY,CAAC;AAEhE,MAAM,MAAM,kBAAkB,CAAC,GAAG,SAAS,aAAa,GAAG,aAAa,IAAI,QAAQ,CAAC;IACnF,QAAQ,EAAE,GAAG,CAAC;IACd,SAAS,EAAE,sBAAsB,CAAC;CACnC,CAAC,GAAG,IAAI,CAAC;AAEV,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,aAAa,CAAC;AAE7D,eAAO,MAAM,iBAAiB;;CAEkC,CAAC;AAEjE,wBAAgB,0BAA0B,CAAC,GAAG,SAAS,aAAa,EAClE,KAAK,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAC9B,OAAO,EAAE,SAAS,yBAAyB,CAAC,GAAG,CAAC,EAAE,GACjD,IAAI,CAYN;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,SAAS,aAAa,EACjE,OAAO,EAAE,kBAAkB,CAAC,GAAG,CAAC,EAChC,QAAQ,EAAE,GAAG,EACb,KAAK,GAAE,kBAAgD,GACtD,kBAAkB,CAAC,GAAG,CAAC,CAQzB;AAED,4FAA4F;AAC5F,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AAEvD,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsF3B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;CA4BO,CAAC"}
|