@hjmds/design-contracts 1.39.0 → 1.41.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/agreement.d.ts +2 -2
- package/dist/base-recipes.d.ts +11 -3
- package/dist/base-recipes.d.ts.map +1 -1
- package/dist/base-recipes.js +9 -4
- package/dist/base-recipes.js.map +1 -1
- package/dist/behaviors.d.ts +4 -4
- package/dist/card.d.ts +1 -1
- package/dist/card.js +1 -1
- package/dist/card.js.map +1 -1
- package/dist/catalog.d.ts +119 -85
- package/dist/catalog.d.ts.map +1 -1
- package/dist/choice-row.d.ts +26 -0
- package/dist/choice-row.d.ts.map +1 -0
- package/dist/choice-row.js +24 -0
- package/dist/choice-row.js.map +1 -0
- package/dist/colors.d.ts +2 -0
- package/dist/colors.d.ts.map +1 -1
- package/dist/colors.js +3 -1
- package/dist/colors.js.map +1 -1
- package/dist/command-palette.d.ts +2 -2
- package/dist/component-contracts.d.ts +2 -2
- package/dist/component-contracts.js +2 -2
- package/dist/component-contracts.js.map +1 -1
- package/dist/component-recipes.d.ts +76 -64
- package/dist/component-recipes.d.ts.map +1 -1
- package/dist/component-recipes.js +18 -16
- package/dist/component-recipes.js.map +1 -1
- package/dist/data-table.d.ts +1 -1
- package/dist/floating-action-button.d.ts +14 -2
- package/dist/floating-action-button.d.ts.map +1 -1
- package/dist/floating-action-button.js +5 -3
- package/dist/floating-action-button.js.map +1 -1
- package/dist/icon-button-recipe.d.ts +2 -2
- package/dist/icon-button-recipe.js +3 -3
- package/dist/icon-button-recipe.js.map +1 -1
- package/dist/menubar.d.ts +2 -2
- package/dist/palette-contrast.d.ts.map +1 -1
- package/dist/palette-contrast.js +2 -0
- package/dist/palette-contrast.js.map +1 -1
- package/dist/semantic-colors.d.ts +18 -1
- package/dist/semantic-colors.d.ts.map +1 -1
- package/dist/semantic-colors.js +7 -1
- package/dist/semantic-colors.js.map +1 -1
- package/dist/sidebar.d.ts +2 -2
- package/dist/time-picker.d.ts +16 -4
- package/dist/time-picker.d.ts.map +1 -1
- package/dist/time-picker.js +26 -5
- package/dist/time-picker.js.map +1 -1
- package/dist/toggle-group.d.ts +3 -3
- package/dist/toggle-group.js +3 -3
- package/dist/toggle-group.js.map +1 -1
- package/dist/transfer-list.d.ts +2 -2
- package/dist/tree.d.ts +2 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/docs/ant-design-coverage.md +6 -1
- package/docs/brand-boundary.md +1 -0
- package/docs/floating-action-button.md +6 -4
- package/docs/generated/component-maturity.md +1 -1
- package/docs/generated/renderer-evidence.json +3 -3
- package/docs/generated/renderer-evidence.md +1 -1
- package/docs/generated/showcase-manifest.json +1 -1
- package/docs/optional-adapters.md +1 -1
- package/docs/theme-palette.md +60 -0
- package/docs/time-picker.md +21 -0
- package/docs/toast.md +11 -0
- package/docs/usage/FINDING.md +71 -0
- package/docs/usage/README.md +5 -3
- package/docs/usage/SELECTION.md +8 -2
- package/docs/usage/components/bottom-navigation.md +5 -0
- package/docs/usage/components/card.md +2 -2
- package/docs/usage/components/chart.md +3 -1
- package/docs/usage/components/chip.md +1 -1
- package/docs/usage/components/choice-row.md +77 -0
- package/docs/usage/components/floating-action-button.md +5 -4
- package/docs/usage/components/image.md +18 -3
- package/docs/usage/components/keyboard-avoidance-context.md +3 -3
- package/docs/usage/components/segmented-control.md +1 -1
- package/docs/usage/components/sheet.md +1 -0
- package/docs/usage/components/surface.md +7 -1
- package/docs/usage/components/tabs.md +5 -0
- package/docs/usage/components/time-picker.md +20 -2
- package/docs/usage/components/toggle-group.md +5 -0
- package/docs/usage/compositions/save-feedback.md +43 -21
- package/docs/usage/tokens/color.md +17 -3
- package/package.json +7 -1
package/dist/agreement.d.ts
CHANGED
|
@@ -118,12 +118,12 @@ export declare const agreementRecipe: {
|
|
|
118
118
|
};
|
|
119
119
|
readonly selectedBackground: Readonly<{
|
|
120
120
|
source: "theme";
|
|
121
|
-
key: "
|
|
121
|
+
key: "surfaceSelected";
|
|
122
122
|
alpha?: number;
|
|
123
123
|
}>;
|
|
124
124
|
readonly selectedIndicator: Readonly<{
|
|
125
125
|
source: "theme";
|
|
126
|
-
key: "
|
|
126
|
+
key: "text";
|
|
127
127
|
alpha?: number;
|
|
128
128
|
}>;
|
|
129
129
|
readonly danger: Readonly<{
|
package/dist/base-recipes.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export type ButtonShape = "rounded" | "pill";
|
|
|
9
9
|
*/
|
|
10
10
|
export type ButtonAlign = "center" | "leading";
|
|
11
11
|
export type ButtonSize = keyof typeof control.buttonHeight;
|
|
12
|
-
export type SurfaceTone = "default" | "raised" | "accent" | "sunken" | "subtle";
|
|
12
|
+
export type SurfaceTone = "default" | "raised" | "accent" | "sunken" | "subtle" | "selected";
|
|
13
13
|
export type SurfacePadding = "none" | keyof typeof spacing;
|
|
14
14
|
export type SurfaceRadius = keyof typeof radius;
|
|
15
15
|
export type FieldVariant = "surface" | "inset";
|
|
@@ -72,8 +72,8 @@ export declare const buttonRecipe: {
|
|
|
72
72
|
*/
|
|
73
73
|
readonly states: {
|
|
74
74
|
readonly selected: {
|
|
75
|
-
readonly background: "
|
|
76
|
-
readonly content: "
|
|
75
|
+
readonly background: "surfaceSelected";
|
|
76
|
+
readonly content: "text";
|
|
77
77
|
readonly border: null;
|
|
78
78
|
};
|
|
79
79
|
};
|
|
@@ -172,6 +172,14 @@ export declare const surfaceRecipe: {
|
|
|
172
172
|
readonly borderAlways: true;
|
|
173
173
|
readonly clipsContent: true;
|
|
174
174
|
};
|
|
175
|
+
readonly selected: {
|
|
176
|
+
readonly background: "surfaceSelected";
|
|
177
|
+
readonly border: "borderControl";
|
|
178
|
+
readonly borderAlpha: 1;
|
|
179
|
+
readonly elevated: false;
|
|
180
|
+
readonly borderAlways: true;
|
|
181
|
+
readonly clipsContent: true;
|
|
182
|
+
};
|
|
175
183
|
readonly subtle: {
|
|
176
184
|
readonly background: "bg";
|
|
177
185
|
readonly border: "border";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-recipes.d.ts","sourceRoot":"","sources":["../src/base-recipes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAc,MAAM,EAAE,OAAO,EAAc,MAAM,kBAAkB,CAAC;AAGpF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAC/E,uEAAuE;AACvE,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,CAAC;AACjD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;AAC7C;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC/C,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,OAAO,CAAC,YAAY,CAAC;AAC3D,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"base-recipes.d.ts","sourceRoot":"","sources":["../src/base-recipes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAc,MAAM,EAAE,OAAO,EAAc,MAAM,kBAAkB,CAAC;AAGpF,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;AAC/E,uEAAuE;AACvE,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,QAAQ,CAAC;AACjD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;AAC7C;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;AAC/C,MAAM,MAAM,UAAU,GAAG,MAAM,OAAO,OAAO,CAAC,YAAY,CAAC;AAC3D,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;AAC7F,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,OAAO,OAAO,CAAC;AAC3D,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,MAAM,CAAC;AAChD,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,CAAC;AAC/C,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAErD,4EAA4E;AAC5E,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAgBvB;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4BH;;;;;;;;;;;OAWG;;;;;;CAoCJ,CAAC;AAEF,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,gBAAgB,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAI3G;AAED;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AAClD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,MAAM,CAIpF;AAED,yFAAyF;AACzF,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAEzE;AAED,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6DzB,CAAC;AAEF,6CAA6C;AAC7C,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8BtB;;;;OAIG;uCAC+B,MAAM,GAAG,IAAI;;;;;;;;;;;;;;;;;;;;;;;IAqB/C;;;;;;;;;;;;OAYG;;;;;CAwCJ,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;CAU3B,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;CAM3B,CAAC"}
|
package/dist/base-recipes.js
CHANGED
|
@@ -22,8 +22,8 @@ export const buttonRecipe = {
|
|
|
22
22
|
* consumer painted the selected background in product styles.
|
|
23
23
|
*/
|
|
24
24
|
states: {
|
|
25
|
-
//
|
|
26
|
-
selected: { background: "
|
|
25
|
+
// Persistent toggles share the neutral selection pair (2026-10-23); focus stays independent.
|
|
26
|
+
selected: { background: "surfaceSelected", content: "text", border: null },
|
|
27
27
|
},
|
|
28
28
|
sizes: {
|
|
29
29
|
small: {
|
|
@@ -100,8 +100,8 @@ export const surfaceRecipe = {
|
|
|
100
100
|
// rounded corner, which consumers were fixing in product styles.
|
|
101
101
|
clipsContent: false,
|
|
102
102
|
},
|
|
103
|
-
//
|
|
104
|
-
//
|
|
103
|
+
// Resting surfaces keep canvas fills; elevation and borders carry hierarchy.
|
|
104
|
+
// Persistent selection has its own neutral tone below.
|
|
105
105
|
sunken: {
|
|
106
106
|
background: "bg",
|
|
107
107
|
border: "border",
|
|
@@ -118,6 +118,11 @@ export const surfaceRecipe = {
|
|
|
118
118
|
borderAlways: true,
|
|
119
119
|
clipsContent: true,
|
|
120
120
|
},
|
|
121
|
+
// Selected cards need their own surface role, without repurposing a brand accent.
|
|
122
|
+
selected: {
|
|
123
|
+
background: "surfaceSelected", border: "borderControl", borderAlpha: 1,
|
|
124
|
+
elevated: false, borderAlways: true, clipsContent: true,
|
|
125
|
+
},
|
|
121
126
|
subtle: {
|
|
122
127
|
background: "bg",
|
|
123
128
|
border: "border",
|
package/dist/base-recipes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-recipes.js","sourceRoot":"","sources":["../src/base-recipes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAmBpF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,CAAU;IACnF,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAW;IAC7G,8FAA8F;IAC9F,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE;IAC3F,KAAK,EAAE;QACL,OAAO,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;QAC/F,0EAA0E;QAC1E,uEAAuE;QACvE,SAAS,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,IAAI,EAAE;QAClG,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;QACxF,MAAM,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;QAChG,2EAA2E;QAC3E,0DAA0D;QAC1D,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE;KACxF;IACD;;;;OAIG;IACH,MAAM,EAAE;QACN,6FAA6F;QAC7F,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE;KACtE;IACD,KAAK,EAAE;QACL,KAAK,EAAE;YACL,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK;YAClC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK;YACpC,iBAAiB,EAAE,OAAO,CAAC,EAAE;YAC7B,WAAW,EAAE,OAAO;SACrB;QACD,MAAM,EAAE;YACN,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,MAAM;YACnC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,MAAM;YACrC,iBAAiB,EAAE,OAAO,CAAC,EAAE;YAC7B,WAAW,EAAE,MAAM;SACpB;QACD,KAAK,EAAE;YACL,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK;YAClC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK;YACpC,iBAAiB,EAAE,OAAO,CAAC,EAAE;YAC7B,WAAW,EAAE,WAAW;SACzB;KACF;IACD,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE;IACvC,MAAM,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;IACnD,OAAO,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;IACzC;;;;;;;;;;;OAWG;IACH,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;CAmCnE,CAAC;AAEF,wEAAwE;AACxE,MAAM,UAAU,kBAAkB,CAAC,UAA4B,EAAE,IAAgB,EAAE,IAAgB;IACjG,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,QAAQ;QAAE,MAAM,IAAI,SAAS,CAAC,2BAA2B,CAAC,CAAC;IACvG,IAAI,UAAU,KAAK,MAAM,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,CAAC,CAAC;IAC3E,OAAO,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC;AASD,MAAM,UAAU,yBAAyB,CAAC,IAAgB,EAAE,IAAgB;IAC1E,MAAM,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,YAAY,CAAC,UAAU,KAAK,IAAI,IAAI,YAAY,CAAC,MAAM,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC;IAC/E,OAAO,YAAY,CAAC,iBAAiB,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,iBAAiB,CAAC;AACtF,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,uBAAuB,CAAC,SAAkB;IACxD,OAAO,SAAS,IAAI,YAAY,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC;AACjG,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO,EAAE;QACP,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,KAAK;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;KACnB;IACD,MAAM,EAAE;QACN,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;QAClB,yEAAyE;QACzE,wEAAwE;QACxE,iEAAiE;QACjE,YAAY,EAAE,KAAK;KACpB;IACD,yEAAyE;IACzE,uDAAuD;IACvD,MAAM,EAAE;QACN,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,KAAK;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;KACnB;IACD,MAAM,EAAE;QACN,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,KAAK;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;KACnB;IACD,MAAM,EAAE;QACN,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,KAAK;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;KACnB;CAWF,CAAC;AAKF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,KAAK,EAAE;QACL,MAAM;QACN,OAAO;QACP,SAAS;QACT,SAAS;QACT,OAAO;QACP,UAAU;QACV,MAAM;QACN,OAAO;KACC;IACV,QAAQ,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAW;IAC1E,QAAQ,EAAE;QACR,sGAAsG;QACtG,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;QAC7B,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;KAC5B;IACD,MAAM,EAAE;QACN,MAAM,EAAE,IAAI;QACZ,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,MAAM;KACb;IACD,MAAM,EAAE;QACN,IAAI,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE;QACjC,OAAO,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE;QACnC,iHAAiH;QACjH,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,EAAE;KAC9C;IACD,SAAS,EAAE,OAAO,CAAC,cAAc;IACjC,kBAAkB,EAAE,EAAE;IACtB;;;;OAIG;IACH,wBAAwB,EAAE,IAAqB;IAC/C,WAAW,EAAE,CAAC;IACd,cAAc,EAAE,CAAC;IACjB,eAAe,EAAE,CAAC;IAClB,iBAAiB,EAAE,OAAO,CAAC,EAAE;IAC7B,eAAe,EAAE,OAAO,CAAC,EAAE;IAC3B,WAAW,EAAE,MAAM;IACnB,KAAK,EAAE;QACL,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,MAAM;QACnB,UAAU,EAAE,UAAU,CAAC,MAAM;QAC7B,GAAG,EAAE,OAAO,CAAC,EAAE;KAChB;IACD,OAAO,EAAE;QACP,SAAS,EAAE,WAAW;QACtB,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,OAAO;QACpB,GAAG,EAAE,CAAC;KACP;IACD,WAAW,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE;IACnC,eAAe,EAAE,GAAG;IACpB;;;;;;;;;;;;OAYG;IACH,aAAa,EAAE;QACb,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;QAC5B,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;KAC7B;CAoCF,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,KAAK;CAMhB,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE;IACjC,KAAK,EAAE,MAAM;CAId,CAAC","sourcesContent":["import type { ThemeColors } from \"./colors.js\";\nimport { control, fontWeight, radius, spacing, typography } from \"./foundations.js\";\nimport type { FontWeightValue, TextVariant } from \"./foundations.js\";\n\nexport type ButtonTone = \"primary\" | \"secondary\" | \"ghost\" | \"danger\" | \"link\";\n/** Corner geometry of the control frame. Mirrors `IconButtonShape`. */\nexport type ButtonAppearance = \"flat\" | \"raised\";\nexport type ButtonShape = \"rounded\" | \"pill\";\n/**\n * Where the label sits inside the frame. `center` is the action default;\n * `leading` is for a full-width row action whose label reads as list copy.\n */\nexport type ButtonAlign = \"center\" | \"leading\";\nexport type ButtonSize = keyof typeof control.buttonHeight;\nexport type SurfaceTone = \"default\" | \"raised\" | \"accent\" | \"sunken\" | \"subtle\";\nexport type SurfacePadding = \"none\" | keyof typeof spacing;\nexport type SurfaceRadius = keyof typeof radius;\nexport type FieldVariant = \"surface\" | \"inset\";\nexport type FieldShape = \"medium\" | \"large\" | \"full\";\n\n/** Small renderer entry point for the three foundational visual recipes. */\nexport const buttonRecipe = {\n slots: [\"root\", \"face\", \"side\", \"leading\", \"label\", \"trailing\", \"spinner\"] as const,\n defaults: { tone: \"primary\", size: \"medium\", shape: \"rounded\", align: \"center\", appearance: \"flat\" } as const,\n // A solid underside belongs to the button, rather than a product's second press/state engine.\n raised: { depths: { small: 3, medium: 4, large: 5 }, sideShade: 0.25, settleDuration: 120 },\n tones: {\n primary: { background: \"primary\", content: \"onPrimary\", border: null, paddingHorizontal: null },\n // The outline is a border role, not a text color. Drawing it in `textSub`\n // made a resting control read heavier than the selected one beside it.\n secondary: { background: \"bg\", content: \"text\", border: \"borderControl\", paddingHorizontal: null },\n ghost: { background: null, content: \"textMuted\", border: null, paddingHorizontal: null },\n danger: { background: \"dangerFill\", content: \"onDanger\", border: null, paddingHorizontal: null },\n // A link-tone control is inline copy, so the size axis' horizontal padding\n // would push it out of alignment with the text around it.\n link: { background: null, content: \"contentBrand\", border: null, paddingHorizontal: 0 },\n },\n /**\n * Visual treatment for a control that is also a toggle. `accessibilityState`\n * / `aria-pressed` already expressed the state; without a paired visual every\n * consumer painted the selected background in product styles.\n */\n states: {\n // Selected reactions use content color, without adding an outline (2026-10-10 user request).\n selected: { background: \"bg\", content: \"contentBrand\", border: null },\n },\n sizes: {\n small: {\n height: control.buttonHeight.small,\n hitSlop: control.buttonHitSlop.small,\n paddingHorizontal: spacing.sm,\n textVariant: \"label\",\n },\n medium: {\n height: control.buttonHeight.medium,\n hitSlop: control.buttonHitSlop.medium,\n paddingHorizontal: spacing.md,\n textVariant: \"body\",\n },\n large: {\n height: control.buttonHeight.large,\n hitSlop: control.buttonHitSlop.large,\n paddingHorizontal: spacing.lg,\n textVariant: \"bodyLarge\",\n },\n },\n shapes: { rounded: \"md\", pill: \"full\" },\n aligns: { center: \"center\", leading: \"flex-start\" },\n opacity: { disabled: 0.5, pressed: 0.86 },\n /**\n * 긴 라벨의 처리 규칙. 지금까지 이 판단이 없어서 Web은 무한히 줄바꿈하고 RN은 한 줄로\n * 잘렸다 — 같은 번역문이 두 표면에서 다르게 보였다.\n *\n * 자르지 않고 **두 줄까지 접는다**. 잘린 행동 라벨(\"삭제하...\"))은 무엇을 하는 버튼인지\n * 잃는다. 대신 무제한 줄바꿈도 막는다 — 하단 CTA 행처럼 버튼이 남의 레이아웃을 밀어내는\n * 자리가 있고, 두 줄을 넘는 라벨은 레이아웃이 아니라 카피의 문제다.\n *\n * 큰 글자 설정에서는 상한을 **푼다**. 사용자가 키운 글자에서 두 줄로 자르면 내용이\n * 사라지고, 그건 WCAG 1.4.4를 어긴다. 제품 카피가 아니라 사용자 설정이 원인이기 때문에\n * 같은 규칙을 적용할 수 없다.\n */\n label: { overflow: \"wrap\", maxLines: 2, liftCapOnLargeText: true },\n} as const satisfies {\n slots: readonly string[];\n defaults: { tone: ButtonTone; size: ButtonSize; shape: ButtonShape; align: ButtonAlign; appearance: ButtonAppearance };\n raised: { depths: Record<ButtonSize, number>; sideShade: number; settleDuration: number };\n tones: Record<\n ButtonTone,\n {\n background: keyof ThemeColors | null;\n content: keyof ThemeColors;\n border: keyof ThemeColors | null;\n /** `null` keeps the size axis' padding. */\n paddingHorizontal: number | null;\n }\n >;\n states: {\n selected: {\n background: keyof ThemeColors;\n content: keyof ThemeColors;\n border: keyof ThemeColors | null;\n };\n };\n sizes: Record<\n ButtonSize,\n {\n height: number;\n hitSlop: number;\n paddingHorizontal: number;\n textVariant: TextVariant;\n }\n >;\n shapes: Record<ButtonShape, keyof typeof radius>;\n aligns: Record<ButtonAlign, \"center\" | \"flex-start\">;\n opacity: { disabled: number; pressed: number };\n label: { overflow: \"wrap\"; maxLines: number; liftCapOnLargeText: boolean };\n};\n\n/** Raised paint never adds a frame to a frameless ghost/link action. */\nexport function resolveButtonDepth(appearance: ButtonAppearance, tone: ButtonTone, size: ButtonSize): number {\n if (appearance !== \"flat\" && appearance !== \"raised\") throw new TypeError(\"Unknown Button appearance\");\n if (appearance === \"flat\" || tone === \"ghost\" || tone === \"link\") return 0;\n return buttonRecipe.raised.depths[size];\n}\n\n/**\n * Edge alignment for a ghost text Button at a row/header edge (2026-10-17 measured audit: a sort trigger's chevron\n * sat 29px from the edge against a 16px inset). Same rule as `resolveIconButtonEdgeOverhang`: a frameless control\n * overhangs the edge by its own inline padding so its label/glyph, not the transparent box, sets the inset.\n * Framed tones (primary, secondary, danger) align their frame instead, and `link` already has no padding: 0.\n */\nexport type ButtonEdge = \"start\" | \"end\" | \"both\";\nexport function resolveButtonEdgeOverhang(tone: ButtonTone, size: ButtonSize): number {\n const toneContract = buttonRecipe.tones[tone];\n if (toneContract.background !== null || toneContract.border !== null) return 0;\n return toneContract.paddingHorizontal ?? buttonRecipe.sizes[size].paddingHorizontal;\n}\n\n/** Resolves the label's line cap for one resolved environment. `null` means uncapped. */\nexport function resolveButtonLabelLines(largeText: boolean): number | null {\n return largeText && buttonRecipe.label.liftCapOnLargeText ? null : buttonRecipe.label.maxLines;\n}\n\nexport const surfaceRecipe = {\n default: {\n background: \"bg\",\n border: \"border\",\n borderAlpha: 1,\n elevated: false,\n borderAlways: true,\n clipsContent: true,\n },\n raised: {\n background: \"bg\",\n border: \"border\",\n borderAlpha: 1,\n elevated: true,\n borderAlways: true,\n // An elevated surface must not clip: `overflow: hidden` cuts off its own\n // shadow. Every other tone clips so a child image cannot spill past the\n // rounded corner, which consumers were fixing in product styles.\n clipsContent: false,\n },\n // White surfaces retain a boundary; tonal fills were removed at the user\n // review, so elevation and border now carry hierarchy.\n sunken: {\n background: \"bg\",\n border: \"border\",\n borderAlpha: 1,\n elevated: false,\n borderAlways: true,\n clipsContent: true,\n },\n accent: {\n background: \"bg\",\n border: \"primary\",\n borderAlpha: 1,\n elevated: false,\n borderAlways: true,\n clipsContent: true,\n },\n subtle: {\n background: \"bg\",\n border: \"border\",\n borderAlpha: 1,\n elevated: false,\n borderAlways: true,\n clipsContent: true,\n },\n} as const satisfies Record<\n SurfaceTone,\n {\n background: keyof ThemeColors;\n border: keyof ThemeColors;\n borderAlpha: number;\n elevated: boolean;\n clipsContent: boolean;\n borderAlways: boolean;\n }\n>;\n\n/** Text placement inside a field control. */\nexport type FieldAlign = \"start\" | \"center\";\n\nexport const fieldRecipe = {\n slots: [\n \"root\",\n \"label\",\n \"control\",\n \"leading\",\n \"input\",\n \"trailing\",\n \"hint\",\n \"error\",\n ] as const,\n defaults: { variant: \"surface\", shape: \"medium\", align: \"start\" } as const,\n variants: {\n // Input interiors stay on the canvas; focus is conveyed by the blue outline, not a grey or blue fill.\n surface: { background: \"bg\" },\n inset: { background: \"bg\" },\n },\n shapes: {\n medium: \"md\",\n large: \"lg\",\n full: \"full\",\n },\n states: {\n idle: { border: \"borderControl\" },\n focused: { border: \"contentBrand\" },\n // Error and focus can share a hue in a product palette; thickness keeps validation distinct without color alone.\n invalid: { border: \"danger\", borderWidth: 2 },\n },\n minHeight: control.minTouchTarget,\n multilineMinHeight: 80,\n /**\n * Upper bound for a growing multiline field, expressed in visible lines. A\n * consumer otherwise reaches for `inputStyle={{ maxHeight }}`, which moves a\n * recipe-owned dimension into product code. `null` keeps unbounded growth.\n */\n multilineMaxVisibleLines: null as number | null,\n borderWidth: 1,\n focusRingWidth: 2,\n focusRingOffset: 2,\n paddingHorizontal: spacing.md,\n paddingVertical: spacing.sm,\n textVariant: \"body\",\n label: {\n color: \"textBody\",\n textVariant: \"body\",\n fontWeight: fontWeight.medium,\n gap: spacing.xs,\n },\n support: {\n hintColor: \"textMuted\",\n errorColor: \"danger\",\n textVariant: \"label\",\n gap: 6,\n },\n placeholder: { color: \"textMuted\" },\n disabledOpacity: 0.6,\n /**\n * Which slots `disabledOpacity` fades (2026-10-06). Label and control dim; the\n * hint and the error keep their contrast, because they are the text that says\n * why the field is locked or what to fix. Renderers used to fade the whole\n * frame, so the small support text (`support.textVariant`) — already the\n * lowest-contrast text in the field — lost contrast too. Fading nothing was\n * rejected: the label and the control are what tell the user the field is off.\n *\n * Every field-family input follows this scope. The amount is the component\n * recipe's own `states.disabledOpacity` where it has one (SearchField,\n * PasswordField, OtpField, NumberField, Select); otherwise this recipe's\n * `disabledOpacity` (TextField, TextArea, Field, Combobox, DatePicker, TagsInput).\n */\n disabledScope: {\n dimmed: [\"label\", \"control\"],\n unchanged: [\"hint\", \"error\"],\n },\n} as const satisfies {\n slots: readonly string[];\n defaults: { variant: FieldVariant; shape: FieldShape; align: FieldAlign };\n variants: Record<FieldVariant, { background: keyof ThemeColors }>;\n shapes: Record<FieldShape, keyof typeof radius>;\n states: Record<\"idle\" | \"focused\", { border: keyof ThemeColors }> & {\n invalid: { border: keyof ThemeColors; borderWidth: number };\n };\n minHeight: number;\n multilineMinHeight: number;\n multilineMaxVisibleLines: number | null;\n borderWidth: number;\n focusRingWidth: number;\n focusRingOffset: number;\n paddingHorizontal: number;\n paddingVertical: number;\n textVariant: keyof typeof typography;\n label: {\n color: keyof ThemeColors;\n textVariant: keyof typeof typography;\n fontWeight: FontWeightValue;\n gap: number;\n };\n support: {\n hintColor: keyof ThemeColors;\n errorColor: keyof ThemeColors;\n textVariant: keyof typeof typography;\n gap: number;\n };\n placeholder: { color: keyof ThemeColors };\n disabledOpacity: number;\n disabledScope: {\n dimmed: readonly (\"label\" | \"control\")[];\n unchanged: readonly (\"hint\" | \"error\")[];\n };\n};\n\n/**\n * Renderer-neutral Surface geometry. Tone colors stay in `surfaceRecipe` for\n * compatibility; these axes make the previously implicit Web/Native defaults\n * explicit without changing that public recipe shape.\n */\nexport const surfaceDefaults = {\n tone: \"default\",\n padding: \"none\",\n radius: \"lg\",\n bordered: false,\n} as const satisfies {\n tone: SurfaceTone;\n padding: SurfacePadding;\n radius: SurfaceRadius;\n bordered: boolean;\n};\n\nexport const surfaceGeometry = {\n paddings: { none: 0, ...spacing },\n radii: radius,\n} as const satisfies {\n paddings: Record<SurfacePadding, number>;\n radii: Record<SurfaceRadius, number>;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"base-recipes.js","sourceRoot":"","sources":["../src/base-recipes.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAmBpF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,CAAU;IACnF,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAW;IAC7G,8FAA8F;IAC9F,MAAM,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE;IAC3F,KAAK,EAAE;QACL,OAAO,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;QAC/F,0EAA0E;QAC1E,uEAAuE;QACvE,SAAS,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,iBAAiB,EAAE,IAAI,EAAE;QAClG,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;QACxF,MAAM,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE;QAChG,2EAA2E;QAC3E,0DAA0D;QAC1D,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC,EAAE;KACxF;IACD;;;;OAIG;IACH,MAAM,EAAE;QACN,6FAA6F;QAC7F,QAAQ,EAAE,EAAE,UAAU,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;KAC3E;IACD,KAAK,EAAE;QACL,KAAK,EAAE;YACL,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK;YAClC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK;YACpC,iBAAiB,EAAE,OAAO,CAAC,EAAE;YAC7B,WAAW,EAAE,OAAO;SACrB;QACD,MAAM,EAAE;YACN,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,MAAM;YACnC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,MAAM;YACrC,iBAAiB,EAAE,OAAO,CAAC,EAAE;YAC7B,WAAW,EAAE,MAAM;SACpB;QACD,KAAK,EAAE;YACL,MAAM,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK;YAClC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK;YACpC,iBAAiB,EAAE,OAAO,CAAC,EAAE;YAC7B,WAAW,EAAE,WAAW;SACzB;KACF;IACD,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE;IACvC,MAAM,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,YAAY,EAAE;IACnD,OAAO,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE;IACzC;;;;;;;;;;;OAWG;IACH,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE;CAmCnE,CAAC;AAEF,wEAAwE;AACxE,MAAM,UAAU,kBAAkB,CAAC,UAA4B,EAAE,IAAgB,EAAE,IAAgB;IACjG,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,QAAQ;QAAE,MAAM,IAAI,SAAS,CAAC,2BAA2B,CAAC,CAAC;IACvG,IAAI,UAAU,KAAK,MAAM,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,CAAC,CAAC;IAC3E,OAAO,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC;AASD,MAAM,UAAU,yBAAyB,CAAC,IAAgB,EAAE,IAAgB;IAC1E,MAAM,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,YAAY,CAAC,UAAU,KAAK,IAAI,IAAI,YAAY,CAAC,MAAM,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC;IAC/E,OAAO,YAAY,CAAC,iBAAiB,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,iBAAiB,CAAC;AACtF,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,uBAAuB,CAAC,SAAkB;IACxD,OAAO,SAAS,IAAI,YAAY,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,QAAQ,CAAC;AACjG,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,OAAO,EAAE;QACP,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,KAAK;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;KACnB;IACD,MAAM,EAAE;QACN,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;QAClB,yEAAyE;QACzE,wEAAwE;QACxE,iEAAiE;QACjE,YAAY,EAAE,KAAK;KACpB;IACD,6EAA6E;IAC7E,uDAAuD;IACvD,MAAM,EAAE;QACN,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,KAAK;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;KACnB;IACD,MAAM,EAAE;QACN,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,SAAS;QACjB,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,KAAK;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;KACnB;IACD,kFAAkF;IAClF,QAAQ,EAAE;QACR,UAAU,EAAE,iBAAiB,EAAE,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,CAAC;QACtE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI;KACxD;IACD,MAAM,EAAE;QACN,UAAU,EAAE,IAAI;QAChB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,CAAC;QACd,QAAQ,EAAE,KAAK;QACf,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;KACnB;CAWF,CAAC;AAKF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,KAAK,EAAE;QACL,MAAM;QACN,OAAO;QACP,SAAS;QACT,SAAS;QACT,OAAO;QACP,UAAU;QACV,MAAM;QACN,OAAO;KACC;IACV,QAAQ,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAW;IAC1E,QAAQ,EAAE;QACR,sGAAsG;QACtG,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;QAC7B,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;KAC5B;IACD,MAAM,EAAE;QACN,MAAM,EAAE,IAAI;QACZ,KAAK,EAAE,IAAI;QACX,IAAI,EAAE,MAAM;KACb;IACD,MAAM,EAAE;QACN,IAAI,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE;QACjC,OAAO,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE;QACnC,iHAAiH;QACjH,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,EAAE;KAC9C;IACD,SAAS,EAAE,OAAO,CAAC,cAAc;IACjC,kBAAkB,EAAE,EAAE;IACtB;;;;OAIG;IACH,wBAAwB,EAAE,IAAqB;IAC/C,WAAW,EAAE,CAAC;IACd,cAAc,EAAE,CAAC;IACjB,eAAe,EAAE,CAAC;IAClB,iBAAiB,EAAE,OAAO,CAAC,EAAE;IAC7B,eAAe,EAAE,OAAO,CAAC,EAAE;IAC3B,WAAW,EAAE,MAAM;IACnB,KAAK,EAAE;QACL,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,MAAM;QACnB,UAAU,EAAE,UAAU,CAAC,MAAM;QAC7B,GAAG,EAAE,OAAO,CAAC,EAAE;KAChB;IACD,OAAO,EAAE;QACP,SAAS,EAAE,WAAW;QACtB,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,OAAO;QACpB,GAAG,EAAE,CAAC;KACP;IACD,WAAW,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE;IACnC,eAAe,EAAE,GAAG;IACpB;;;;;;;;;;;;OAYG;IACH,aAAa,EAAE;QACb,MAAM,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC;QAC5B,SAAS,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;KAC7B;CAoCF,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,MAAM;IACf,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,KAAK;CAMhB,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,OAAO,EAAE;IACjC,KAAK,EAAE,MAAM;CAId,CAAC","sourcesContent":["import type { ThemeColors } from \"./colors.js\";\nimport { control, fontWeight, radius, spacing, typography } from \"./foundations.js\";\nimport type { FontWeightValue, TextVariant } from \"./foundations.js\";\n\nexport type ButtonTone = \"primary\" | \"secondary\" | \"ghost\" | \"danger\" | \"link\";\n/** Corner geometry of the control frame. Mirrors `IconButtonShape`. */\nexport type ButtonAppearance = \"flat\" | \"raised\";\nexport type ButtonShape = \"rounded\" | \"pill\";\n/**\n * Where the label sits inside the frame. `center` is the action default;\n * `leading` is for a full-width row action whose label reads as list copy.\n */\nexport type ButtonAlign = \"center\" | \"leading\";\nexport type ButtonSize = keyof typeof control.buttonHeight;\nexport type SurfaceTone = \"default\" | \"raised\" | \"accent\" | \"sunken\" | \"subtle\" | \"selected\";\nexport type SurfacePadding = \"none\" | keyof typeof spacing;\nexport type SurfaceRadius = keyof typeof radius;\nexport type FieldVariant = \"surface\" | \"inset\";\nexport type FieldShape = \"medium\" | \"large\" | \"full\";\n\n/** Small renderer entry point for the three foundational visual recipes. */\nexport const buttonRecipe = {\n slots: [\"root\", \"face\", \"side\", \"leading\", \"label\", \"trailing\", \"spinner\"] as const,\n defaults: { tone: \"primary\", size: \"medium\", shape: \"rounded\", align: \"center\", appearance: \"flat\" } as const,\n // A solid underside belongs to the button, rather than a product's second press/state engine.\n raised: { depths: { small: 3, medium: 4, large: 5 }, sideShade: 0.25, settleDuration: 120 },\n tones: {\n primary: { background: \"primary\", content: \"onPrimary\", border: null, paddingHorizontal: null },\n // The outline is a border role, not a text color. Drawing it in `textSub`\n // made a resting control read heavier than the selected one beside it.\n secondary: { background: \"bg\", content: \"text\", border: \"borderControl\", paddingHorizontal: null },\n ghost: { background: null, content: \"textMuted\", border: null, paddingHorizontal: null },\n danger: { background: \"dangerFill\", content: \"onDanger\", border: null, paddingHorizontal: null },\n // A link-tone control is inline copy, so the size axis' horizontal padding\n // would push it out of alignment with the text around it.\n link: { background: null, content: \"contentBrand\", border: null, paddingHorizontal: 0 },\n },\n /**\n * Visual treatment for a control that is also a toggle. `accessibilityState`\n * / `aria-pressed` already expressed the state; without a paired visual every\n * consumer painted the selected background in product styles.\n */\n states: {\n // Persistent toggles share the neutral selection pair (2026-10-23); focus stays independent.\n selected: { background: \"surfaceSelected\", content: \"text\", border: null },\n },\n sizes: {\n small: {\n height: control.buttonHeight.small,\n hitSlop: control.buttonHitSlop.small,\n paddingHorizontal: spacing.sm,\n textVariant: \"label\",\n },\n medium: {\n height: control.buttonHeight.medium,\n hitSlop: control.buttonHitSlop.medium,\n paddingHorizontal: spacing.md,\n textVariant: \"body\",\n },\n large: {\n height: control.buttonHeight.large,\n hitSlop: control.buttonHitSlop.large,\n paddingHorizontal: spacing.lg,\n textVariant: \"bodyLarge\",\n },\n },\n shapes: { rounded: \"md\", pill: \"full\" },\n aligns: { center: \"center\", leading: \"flex-start\" },\n opacity: { disabled: 0.5, pressed: 0.86 },\n /**\n * 긴 라벨의 처리 규칙. 지금까지 이 판단이 없어서 Web은 무한히 줄바꿈하고 RN은 한 줄로\n * 잘렸다 — 같은 번역문이 두 표면에서 다르게 보였다.\n *\n * 자르지 않고 **두 줄까지 접는다**. 잘린 행동 라벨(\"삭제하...\"))은 무엇을 하는 버튼인지\n * 잃는다. 대신 무제한 줄바꿈도 막는다 — 하단 CTA 행처럼 버튼이 남의 레이아웃을 밀어내는\n * 자리가 있고, 두 줄을 넘는 라벨은 레이아웃이 아니라 카피의 문제다.\n *\n * 큰 글자 설정에서는 상한을 **푼다**. 사용자가 키운 글자에서 두 줄로 자르면 내용이\n * 사라지고, 그건 WCAG 1.4.4를 어긴다. 제품 카피가 아니라 사용자 설정이 원인이기 때문에\n * 같은 규칙을 적용할 수 없다.\n */\n label: { overflow: \"wrap\", maxLines: 2, liftCapOnLargeText: true },\n} as const satisfies {\n slots: readonly string[];\n defaults: { tone: ButtonTone; size: ButtonSize; shape: ButtonShape; align: ButtonAlign; appearance: ButtonAppearance };\n raised: { depths: Record<ButtonSize, number>; sideShade: number; settleDuration: number };\n tones: Record<\n ButtonTone,\n {\n background: keyof ThemeColors | null;\n content: keyof ThemeColors;\n border: keyof ThemeColors | null;\n /** `null` keeps the size axis' padding. */\n paddingHorizontal: number | null;\n }\n >;\n states: {\n selected: {\n background: keyof ThemeColors;\n content: keyof ThemeColors;\n border: keyof ThemeColors | null;\n };\n };\n sizes: Record<\n ButtonSize,\n {\n height: number;\n hitSlop: number;\n paddingHorizontal: number;\n textVariant: TextVariant;\n }\n >;\n shapes: Record<ButtonShape, keyof typeof radius>;\n aligns: Record<ButtonAlign, \"center\" | \"flex-start\">;\n opacity: { disabled: number; pressed: number };\n label: { overflow: \"wrap\"; maxLines: number; liftCapOnLargeText: boolean };\n};\n\n/** Raised paint never adds a frame to a frameless ghost/link action. */\nexport function resolveButtonDepth(appearance: ButtonAppearance, tone: ButtonTone, size: ButtonSize): number {\n if (appearance !== \"flat\" && appearance !== \"raised\") throw new TypeError(\"Unknown Button appearance\");\n if (appearance === \"flat\" || tone === \"ghost\" || tone === \"link\") return 0;\n return buttonRecipe.raised.depths[size];\n}\n\n/**\n * Edge alignment for a ghost text Button at a row/header edge (2026-10-17 measured audit: a sort trigger's chevron\n * sat 29px from the edge against a 16px inset). Same rule as `resolveIconButtonEdgeOverhang`: a frameless control\n * overhangs the edge by its own inline padding so its label/glyph, not the transparent box, sets the inset.\n * Framed tones (primary, secondary, danger) align their frame instead, and `link` already has no padding: 0.\n */\nexport type ButtonEdge = \"start\" | \"end\" | \"both\";\nexport function resolveButtonEdgeOverhang(tone: ButtonTone, size: ButtonSize): number {\n const toneContract = buttonRecipe.tones[tone];\n if (toneContract.background !== null || toneContract.border !== null) return 0;\n return toneContract.paddingHorizontal ?? buttonRecipe.sizes[size].paddingHorizontal;\n}\n\n/** Resolves the label's line cap for one resolved environment. `null` means uncapped. */\nexport function resolveButtonLabelLines(largeText: boolean): number | null {\n return largeText && buttonRecipe.label.liftCapOnLargeText ? null : buttonRecipe.label.maxLines;\n}\n\nexport const surfaceRecipe = {\n default: {\n background: \"bg\",\n border: \"border\",\n borderAlpha: 1,\n elevated: false,\n borderAlways: true,\n clipsContent: true,\n },\n raised: {\n background: \"bg\",\n border: \"border\",\n borderAlpha: 1,\n elevated: true,\n borderAlways: true,\n // An elevated surface must not clip: `overflow: hidden` cuts off its own\n // shadow. Every other tone clips so a child image cannot spill past the\n // rounded corner, which consumers were fixing in product styles.\n clipsContent: false,\n },\n // Resting surfaces keep canvas fills; elevation and borders carry hierarchy.\n // Persistent selection has its own neutral tone below.\n sunken: {\n background: \"bg\",\n border: \"border\",\n borderAlpha: 1,\n elevated: false,\n borderAlways: true,\n clipsContent: true,\n },\n accent: {\n background: \"bg\",\n border: \"primary\",\n borderAlpha: 1,\n elevated: false,\n borderAlways: true,\n clipsContent: true,\n },\n // Selected cards need their own surface role, without repurposing a brand accent.\n selected: {\n background: \"surfaceSelected\", border: \"borderControl\", borderAlpha: 1,\n elevated: false, borderAlways: true, clipsContent: true,\n },\n subtle: {\n background: \"bg\",\n border: \"border\",\n borderAlpha: 1,\n elevated: false,\n borderAlways: true,\n clipsContent: true,\n },\n} as const satisfies Record<\n SurfaceTone,\n {\n background: keyof ThemeColors;\n border: keyof ThemeColors;\n borderAlpha: number;\n elevated: boolean;\n clipsContent: boolean;\n borderAlways: boolean;\n }\n>;\n\n/** Text placement inside a field control. */\nexport type FieldAlign = \"start\" | \"center\";\n\nexport const fieldRecipe = {\n slots: [\n \"root\",\n \"label\",\n \"control\",\n \"leading\",\n \"input\",\n \"trailing\",\n \"hint\",\n \"error\",\n ] as const,\n defaults: { variant: \"surface\", shape: \"medium\", align: \"start\" } as const,\n variants: {\n // Input interiors stay on the canvas; focus is conveyed by the blue outline, not a grey or blue fill.\n surface: { background: \"bg\" },\n inset: { background: \"bg\" },\n },\n shapes: {\n medium: \"md\",\n large: \"lg\",\n full: \"full\",\n },\n states: {\n idle: { border: \"borderControl\" },\n focused: { border: \"contentBrand\" },\n // Error and focus can share a hue in a product palette; thickness keeps validation distinct without color alone.\n invalid: { border: \"danger\", borderWidth: 2 },\n },\n minHeight: control.minTouchTarget,\n multilineMinHeight: 80,\n /**\n * Upper bound for a growing multiline field, expressed in visible lines. A\n * consumer otherwise reaches for `inputStyle={{ maxHeight }}`, which moves a\n * recipe-owned dimension into product code. `null` keeps unbounded growth.\n */\n multilineMaxVisibleLines: null as number | null,\n borderWidth: 1,\n focusRingWidth: 2,\n focusRingOffset: 2,\n paddingHorizontal: spacing.md,\n paddingVertical: spacing.sm,\n textVariant: \"body\",\n label: {\n color: \"textBody\",\n textVariant: \"body\",\n fontWeight: fontWeight.medium,\n gap: spacing.xs,\n },\n support: {\n hintColor: \"textMuted\",\n errorColor: \"danger\",\n textVariant: \"label\",\n gap: 6,\n },\n placeholder: { color: \"textMuted\" },\n disabledOpacity: 0.6,\n /**\n * Which slots `disabledOpacity` fades (2026-10-06). Label and control dim; the\n * hint and the error keep their contrast, because they are the text that says\n * why the field is locked or what to fix. Renderers used to fade the whole\n * frame, so the small support text (`support.textVariant`) — already the\n * lowest-contrast text in the field — lost contrast too. Fading nothing was\n * rejected: the label and the control are what tell the user the field is off.\n *\n * Every field-family input follows this scope. The amount is the component\n * recipe's own `states.disabledOpacity` where it has one (SearchField,\n * PasswordField, OtpField, NumberField, Select); otherwise this recipe's\n * `disabledOpacity` (TextField, TextArea, Field, Combobox, DatePicker, TagsInput).\n */\n disabledScope: {\n dimmed: [\"label\", \"control\"],\n unchanged: [\"hint\", \"error\"],\n },\n} as const satisfies {\n slots: readonly string[];\n defaults: { variant: FieldVariant; shape: FieldShape; align: FieldAlign };\n variants: Record<FieldVariant, { background: keyof ThemeColors }>;\n shapes: Record<FieldShape, keyof typeof radius>;\n states: Record<\"idle\" | \"focused\", { border: keyof ThemeColors }> & {\n invalid: { border: keyof ThemeColors; borderWidth: number };\n };\n minHeight: number;\n multilineMinHeight: number;\n multilineMaxVisibleLines: number | null;\n borderWidth: number;\n focusRingWidth: number;\n focusRingOffset: number;\n paddingHorizontal: number;\n paddingVertical: number;\n textVariant: keyof typeof typography;\n label: {\n color: keyof ThemeColors;\n textVariant: keyof typeof typography;\n fontWeight: FontWeightValue;\n gap: number;\n };\n support: {\n hintColor: keyof ThemeColors;\n errorColor: keyof ThemeColors;\n textVariant: keyof typeof typography;\n gap: number;\n };\n placeholder: { color: keyof ThemeColors };\n disabledOpacity: number;\n disabledScope: {\n dimmed: readonly (\"label\" | \"control\")[];\n unchanged: readonly (\"hint\" | \"error\")[];\n };\n};\n\n/**\n * Renderer-neutral Surface geometry. Tone colors stay in `surfaceRecipe` for\n * compatibility; these axes make the previously implicit Web/Native defaults\n * explicit without changing that public recipe shape.\n */\nexport const surfaceDefaults = {\n tone: \"default\",\n padding: \"none\",\n radius: \"lg\",\n bordered: false,\n} as const satisfies {\n tone: SurfaceTone;\n padding: SurfacePadding;\n radius: SurfaceRadius;\n bordered: boolean;\n};\n\nexport const surfaceGeometry = {\n paddings: { none: 0, ...spacing },\n radii: radius,\n} as const satisfies {\n paddings: Record<SurfacePadding, number>;\n radii: Record<SurfaceRadius, number>;\n};\n"]}
|
package/dist/behaviors.d.ts
CHANGED
|
@@ -1343,7 +1343,7 @@ export declare const behaviorRegistry: {
|
|
|
1343
1343
|
};
|
|
1344
1344
|
readonly timePicker: {
|
|
1345
1345
|
readonly controlled: readonly ["value", "onValueChange"];
|
|
1346
|
-
readonly inputs: readonly ["labels", "minuteStep", "isTimeUnavailable", "presentation"];
|
|
1346
|
+
readonly inputs: readonly ["labels", "minuteStep", "isTimeUnavailable", "presentation", "selectionStyle"];
|
|
1347
1347
|
readonly stateAxes: {
|
|
1348
1348
|
readonly availability: readonly ["enabled", "disabled", "readOnly"];
|
|
1349
1349
|
readonly value: readonly ["empty", "partial", "selected"];
|
|
@@ -1356,12 +1356,12 @@ export declare const behaviorRegistry: {
|
|
|
1356
1356
|
readonly dismiss: readonly ["action", "escape", "outside", "blur"];
|
|
1357
1357
|
};
|
|
1358
1358
|
readonly native: {
|
|
1359
|
-
readonly roles: readonly ["button", "dialog", "radio"];
|
|
1359
|
+
readonly roles: readonly ["button", "dialog", "radio", "adjustable"];
|
|
1360
1360
|
readonly states: readonly ["disabled", "expanded", "checked"];
|
|
1361
|
-
readonly actions: readonly ["activate", "dismiss"];
|
|
1361
|
+
readonly actions: readonly ["activate", "dismiss", "increment", "decrement"];
|
|
1362
1362
|
readonly dismiss: readonly ["action", "back", "outside"];
|
|
1363
1363
|
};
|
|
1364
|
-
readonly scenarios: readonly ["two-columns-share-one-draft-and-overlay", "column-selection-never-dismisses", "confirm-commits-a-complete-available-HH:mm", "cancel-discards-edits", "external-value-reconciles-draft", "inline-parent-owns-confirmation", "unavailable-options-never-activate", "midnight-is-a-valid-value"];
|
|
1364
|
+
readonly scenarios: readonly ["two-columns-share-one-draft-and-overlay", "column-selection-never-dismisses", "confirm-commits-a-complete-available-HH:mm", "cancel-discards-edits", "external-value-reconciles-draft", "inline-parent-owns-confirmation", "unavailable-options-never-activate", "midnight-is-a-valid-value", "wheel-centers-available-slots-without-initial-commit", "wheel-adjustment-preserves-confirm-and-cancel"];
|
|
1365
1365
|
};
|
|
1366
1366
|
readonly sidePanel: {
|
|
1367
1367
|
readonly controlled: readonly ["open", "defaultOpen", "onOpenChange", "dismissPolicy"];
|
package/dist/card.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare const cardRecipe: {
|
|
|
13
13
|
readonly badgesAlign: "start";
|
|
14
14
|
readonly padding: "md";
|
|
15
15
|
};
|
|
16
|
-
readonly selectedTone: "
|
|
16
|
+
readonly selectedTone: "selected";
|
|
17
17
|
readonly interaction: {
|
|
18
18
|
readonly disabledOpacity: 0.5;
|
|
19
19
|
readonly pressedOpacity: 0.86;
|
package/dist/card.js
CHANGED
|
@@ -31,7 +31,7 @@ export const cardRecipe = {
|
|
|
31
31
|
badgesAlign: "start",
|
|
32
32
|
padding: "md",
|
|
33
33
|
},
|
|
34
|
-
selectedTone: "
|
|
34
|
+
selectedTone: "selected",
|
|
35
35
|
// BurnTok's compact 3-column picker (2026-10-10) needs the whole card to activate.
|
|
36
36
|
// Reuse control state opacity instead of a product Pressable with a second visual contract.
|
|
37
37
|
interaction: { disabledOpacity: buttonRecipe.opacity.disabled, pressedOpacity: buttonRecipe.opacity.pressed },
|
package/dist/card.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.js","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,YAAY,GAGb,MAAM,mBAAmB,CAAC;AAI3B;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,KAAK,EAAE;QACL,MAAM;QACN,OAAO;QACP,iBAAiB;QACjB,uBAAuB;QACvB,aAAa;QACb,QAAQ;QACR,aAAa;QACb,MAAM;QACN,QAAQ;QACR,SAAS;QACT,OAAO;QACP,aAAa;QACb,SAAS;QACT,SAAS;KACD;IACV,QAAQ,EAAE;QACR,8EAA8E;QAC9E,0EAA0E;QAC1E,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,CAAC;QACf,WAAW,EAAE,OAAO;QACpB,OAAO,EAAE,IAAI;KACd;IACD,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"card.js","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,YAAY,GAGb,MAAM,mBAAmB,CAAC;AAI3B;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,KAAK,EAAE;QACL,MAAM;QACN,OAAO;QACP,iBAAiB;QACjB,uBAAuB;QACvB,aAAa;QACb,QAAQ;QACR,aAAa;QACb,MAAM;QACN,QAAQ;QACR,SAAS;QACT,OAAO;QACP,aAAa;QACb,SAAS;QACT,SAAS;KACD;IACV,QAAQ,EAAE;QACR,8EAA8E;QAC9E,0EAA0E;QAC1E,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,CAAC;QACf,WAAW,EAAE,OAAO;QACpB,OAAO,EAAE,IAAI;KACd;IACD,YAAY,EAAE,UAAU;IACxB,mFAAmF;IACnF,4FAA4F;IAC5F,WAAW,EAAE,EAAE,eAAe,EAAE,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,cAAc,EAAE,YAAY,CAAC,OAAO,CAAC,OAAO,EAAE;IAC7G,wGAAwG;IACxG,WAAW,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,cAAc,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE;IACxF,8FAA8F;IAC9F,mFAAmF;IACnF,eAAe,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,UAAU,EAAE,SAAS,EAAE;IACvE,SAAS,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,EAAE;IAClD,IAAI,EAAE;QACJ,OAAO,EAAE,OAAO,CAAC,EAAE;QACnB,GAAG,EAAE,OAAO,CAAC,EAAE;KAChB;IACD,MAAM,EAAE;QACN,GAAG,EAAE,OAAO,CAAC,EAAE;QACf,+FAA+F;QAC/F,UAAU,EAAE,QAAQ;KACrB;IACD,KAAK,EAAE;QACL,OAAO,EAAE,OAAO;QAChB,IAAI,EAAE,SAAS;QACf,QAAQ,EAAE,QAAQ;KACnB;IACD,WAAW,EAAE;QACX,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,SAAS;KACpB;IACD,OAAO,EAAE;QACP,+FAA+F;QAC/F,GAAG,EAAE,OAAO,CAAC,EAAE;QACf,iBAAiB,EAAE,OAAO,CAAC,EAAE;QAC7B,aAAa,EAAE,OAAO,CAAC,EAAE;KAC1B;CA4CF,CAAC","sourcesContent":["import { control, glyph, spacing } from \"./foundations.js\";\nimport {\n buttonRecipe,\n type SurfacePadding,\n type SurfaceTone,\n} from \"./base-recipes.js\";\n\nexport type CardHeadingLevel = 2 | 3 | 4;\n\n/**\n * Shared Card anatomy. Renderers own their host nodes (`article` on Web,\n * `View` on Native), while these slots and defaults stay identical.\n */\nexport const cardRecipe = {\n slots: [\n \"root\",\n \"media\",\n \"backgroundMedia\",\n \"backgroundInteraction\",\n \"mediaBadges\",\n \"badges\",\n \"mediaAction\",\n \"body\",\n \"header\",\n \"leading\",\n \"title\",\n \"description\",\n \"content\",\n \"actions\",\n ] as const,\n defaults: {\n // Today Baseball's schedule cards establish the shared raised card treatment.\n // Keep plain Surface defaults independent so layout containers stay flat.\n tone: \"raised\",\n selected: false,\n bordered: true,\n headingLevel: 3,\n badgesAlign: \"start\",\n padding: \"md\",\n },\n selectedTone: \"selected\",\n // BurnTok's compact 3-column picker (2026-10-10) needs the whole card to activate.\n // Reuse control state opacity instead of a product Pressable with a second visual contract.\n interaction: { disabledOpacity: buttonRecipe.opacity.disabled, pressedOpacity: buttonRecipe.opacity.pressed },\n // A playable cover is one target beside independent creator/comment actions (BurnTok screen migration).\n mediaAction: { inset: spacing.sm, diameter: control.minTouchTarget, iconSize: glyph.sm },\n // Decorative artwork needs fixed contrast independent of brand onPrimary (which can be dark).\n // A 60% black scrim keeps white card text readable even over a white source image.\n backgroundMedia: { scrim: \"rgba(0, 0, 0, 0.6)\", foreground: \"#ffffff\" },\n quotation: { gap: spacing.xs, markSize: glyph.md },\n body: {\n padding: spacing.md,\n gap: spacing.xs,\n },\n header: {\n gap: spacing.sm,\n // Short copy and independent commands share one vertical center (BurnTok profile, 2026-10-20).\n alignItems: \"center\",\n },\n title: {\n variant: \"title\",\n tone: \"primary\",\n emphasis: \"strong\",\n },\n description: {\n variant: \"body\",\n tone: \"muted\",\n emphasis: \"regular\",\n },\n actions: {\n // Button groups share the 8px actionGroupRecipe contract in both renderers (2026-10-21 audit).\n gap: spacing.xs,\n paddingHorizontal: spacing.md,\n paddingBottom: spacing.md,\n },\n} as const satisfies {\n slots: readonly [\n \"root\",\n \"media\",\n \"backgroundMedia\",\n \"backgroundInteraction\",\n \"mediaBadges\",\n \"badges\",\n \"mediaAction\",\n \"body\",\n \"header\",\n \"leading\",\n \"title\",\n \"description\",\n \"content\",\n \"actions\",\n ];\n defaults: {\n tone: SurfaceTone;\n selected: boolean;\n bordered: boolean;\n headingLevel: CardHeadingLevel;\n badgesAlign: \"start\" | \"center\";\n padding: SurfacePadding;\n };\n selectedTone: SurfaceTone;\n interaction: { disabledOpacity: number; pressedOpacity: number };\n mediaAction: { inset: number; diameter: number; iconSize: number };\n backgroundMedia: { scrim: string; foreground: string };\n quotation: { gap: number; markSize: number };\n body: { padding: number; gap: number };\n header: { gap: number; alignItems: \"center\" };\n title: {\n variant: \"title\";\n tone: \"primary\";\n emphasis: \"strong\";\n };\n description: {\n variant: \"body\";\n tone: \"muted\";\n emphasis: \"regular\";\n };\n actions: { gap: number; paddingHorizontal: number; paddingBottom: number };\n};\n"]}
|