@hjmds/design-contracts 1.50.0 → 2.0.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.
Files changed (40) hide show
  1. package/dist/base-recipes.d.ts +0 -7
  2. package/dist/base-recipes.d.ts.map +1 -1
  3. package/dist/base-recipes.js +3 -7
  4. package/dist/base-recipes.js.map +1 -1
  5. package/dist/behaviors.d.ts +7 -7
  6. package/dist/catalog.d.ts +39 -8
  7. package/dist/catalog.d.ts.map +1 -1
  8. package/dist/component-recipes.d.ts +2 -0
  9. package/dist/component-recipes.d.ts.map +1 -1
  10. package/dist/component-recipes.js +2 -0
  11. package/dist/component-recipes.js.map +1 -1
  12. package/dist/date-range.d.ts +56 -8
  13. package/dist/date-range.d.ts.map +1 -1
  14. package/dist/date-range.js +37 -5
  15. package/dist/date-range.js.map +1 -1
  16. package/dist/icon-button-recipe.d.ts +0 -6
  17. package/dist/icon-button-recipe.d.ts.map +1 -1
  18. package/dist/icon-button-recipe.js +8 -11
  19. package/dist/icon-button-recipe.js.map +1 -1
  20. package/dist/screen-patterns.d.ts +8 -0
  21. package/dist/screen-patterns.d.ts.map +1 -1
  22. package/dist/screen-patterns.js +5 -0
  23. package/dist/screen-patterns.js.map +1 -1
  24. package/dist/version.d.ts +1 -1
  25. package/dist/version.d.ts.map +1 -1
  26. package/dist/version.js +1 -1
  27. package/dist/version.js.map +1 -1
  28. package/docs/generated/component-maturity.md +1 -1
  29. package/docs/generated/renderer-evidence.json +3 -3
  30. package/docs/generated/renderer-evidence.md +1 -1
  31. package/docs/generated/showcase-manifest.json +1 -1
  32. package/docs/theme-palette.md +3 -1
  33. package/docs/usage/components/auth-screen-layout.md +2 -0
  34. package/docs/usage/components/avatar.md +4 -0
  35. package/docs/usage/components/button.md +4 -3
  36. package/docs/usage/components/date-range-picker.md +9 -3
  37. package/docs/usage/components/icon-button.md +6 -6
  38. package/docs/usage/components/profile-summary.md +2 -2
  39. package/docs/usage/components/radio-group.md +8 -0
  40. package/package.json +1 -1
@@ -71,11 +71,17 @@ export declare function resolveDateRangeCellPaint(value: DateRangeValue, date: s
71
71
  * 다음 탭이 새 시작이 되긴 하지만, 완성 직후 시작 칸이 강조되면 시작일을 고치는 중으로 읽혔다(2026-10-25 실화면).
72
72
  */
73
73
  export declare function resolveDateRangeActiveEdge(value: DateRangeValue): "start" | "end" | null;
74
- /** 프리셋 길이. `days`는 오늘 포함 n일, `months`는 n개월 전 다음 날부터 오늘까지다. */
74
+ /**
75
+ * 프리셋 길이. `days`는 오늘 포함 n일, `months`는 n개월 전 다음 날부터 오늘까지, `all`은 날짜 제한 없음(빈 구간)이다.
76
+ * `all`은 2026-10-28 사용자 요청("전체가 포함되게 하면 1일, 1주일, 1개월, 3개월, 전체로 하자")으로 생겼다. 필터의
77
+ * [전체·오늘·기간 지정] 탭과 프리셋이 같은 일을 두 번 해 탭을 없애고, 전체를 프리셋 한 칸으로 옮겼다.
78
+ */
75
79
  export type DateRangePresetLength = Readonly<{
76
80
  days: number;
77
81
  } | {
78
82
  months: number;
83
+ } | {
84
+ all: true;
79
85
  }>;
80
86
  /**
81
87
  * 오늘로 끝나는 프리셋 구간(최근 7일·1개월 등). 날짜 계산은 UTC 달력 날짜로만 해 서머타임·시간대에 흔들리지 않는다.
@@ -147,29 +153,71 @@ export declare const dateRangeRecipe: {
147
153
  readonly presets: {
148
154
  readonly gap: 8;
149
155
  readonly chipSize: "small";
156
+ readonly standard: readonly [{
157
+ readonly id: "day";
158
+ readonly length: {
159
+ readonly days: 1;
160
+ };
161
+ }, {
162
+ readonly id: "week";
163
+ readonly length: {
164
+ readonly days: 7;
165
+ };
166
+ }, {
167
+ readonly id: "month";
168
+ readonly length: {
169
+ readonly months: 1;
170
+ };
171
+ }, {
172
+ readonly id: "quarter";
173
+ readonly length: {
174
+ readonly months: 3;
175
+ };
176
+ }, {
177
+ readonly id: "all";
178
+ readonly length: {
179
+ readonly all: true;
180
+ };
181
+ }];
150
182
  };
151
183
  readonly gap: 16;
184
+ readonly toggle: {
185
+ readonly icon: {
186
+ readonly collapsed: "chevronDown";
187
+ readonly expanded: "chevronUp";
188
+ };
189
+ readonly glyph: "sm";
190
+ readonly gap: 8;
191
+ };
152
192
  };
193
+ /**
194
+ * 접히는 기간 선택에서 이번 선택 뒤에 달력을 계속 펼쳐 둘지. 프리셋은 언제나 접고, 날짜 탭은 구간을 완성할 때 접는다
195
+ * (시작만 정한 첫 탭은 펼쳐 둔다). 처음에는 접힌 채 시작한다. 필터의 기본은 프리셋이고 달력은 직접 고를 때만 연다.
196
+ *
197
+ * 2026-10-28 사용자 "DateRangePicker도 접기 있게 해": 필터 영역에 둔 달력이 기간을 고른 뒤에도 늘 펼쳐져
198
+ * 목록을 밀어냈다(다에리 만난 동물). Sheet·Popover 합성 없이 본문 안에서 쓰는 접힘이고, 요약 칸이 그 버튼이다.
199
+ */
200
+ export declare function resolveDateRangeExpandedAfterSelection(next: DateRangeValue, source: "date" | "preset"): boolean;
153
201
  /** 구간이 실제로 쓸 수 있는 값인지. 제품의 제출 버튼이 읽는다. */
154
202
  export declare function isCompleteDateRange(value: DateRangeValue): boolean;
155
203
  export declare const dateRangeBehavior: {
156
- readonly controlled: readonly ["value", "defaultValue", "onValueChange"];
204
+ readonly controlled: readonly ["value", "defaultValue", "onValueChange", "expanded", "defaultExpanded", "onExpandedChange"];
157
205
  readonly inputs: readonly ["grid", "monthLabel", "hoveredDate"];
158
206
  readonly stateAxes: {
159
- readonly value: readonly ["empty", "selecting", "complete"];
207
+ readonly value: readonly ["empty", "selecting", "complete", "expanded"];
160
208
  readonly availability: readonly ["enabled", "disabled"];
161
209
  };
162
210
  readonly web: {
163
- readonly roles: readonly ["grid", "gridcell"];
211
+ readonly roles: readonly ["grid", "gridcell", "button"];
164
212
  readonly keyboard: readonly ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End", "Enter", "Space"];
165
213
  readonly focus: "roving";
166
214
  };
167
215
  readonly native: {
168
- readonly roles: readonly [];
169
- readonly states: readonly ["selected", "disabled"];
170
- readonly actions: readonly ["select"];
216
+ readonly roles: readonly ["button"];
217
+ readonly states: readonly ["selected", "disabled", "expanded"];
218
+ readonly actions: readonly ["select", "activate"];
171
219
  };
172
- readonly scenarios: readonly ["a-click-on-a-complete-range-starts-a-new-one-instead-of-guessing-which-end-to-move", "picking-an-earlier-date-while-selecting-swaps-the-two-instead-of-rejecting-it", "the-selecting-state-is-start-without-end-not-a-separate-flag", "a-hovered-date-previews-the-end-through-the-same-cell-state-function", "an-end-without-a-start-is-rejected-by-validation-not-rendered-as-something", "calendar-keeps-single-selection-this-module-never-adds-a-mode-axis-to-it", "the-range-is-one-band-between-two-filled-edges-and-a-one-day-range-has-no-band", "the-summary-marks-the-edge-being-picked-and-nothing-once-complete", "a-preset-ends-today-and-is-selected-only-while-the-value-equals-it"];
220
+ readonly scenarios: readonly ["a-click-on-a-complete-range-starts-a-new-one-instead-of-guessing-which-end-to-move", "picking-an-earlier-date-while-selecting-swaps-the-two-instead-of-rejecting-it", "the-selecting-state-is-start-without-end-not-a-separate-flag", "a-hovered-date-previews-the-end-through-the-same-cell-state-function", "an-end-without-a-start-is-rejected-by-validation-not-rendered-as-something", "calendar-keeps-single-selection-this-module-never-adds-a-mode-axis-to-it", "the-range-is-one-band-between-two-filled-edges-and-a-one-day-range-has-no-band", "the-summary-marks-the-edge-being-picked-and-nothing-once-complete", "a-preset-ends-today-and-is-selected-only-while-the-value-equals-it", "a-collapsible-picker-starts-folded-and-folds-again-after-a-preset-or-a-completing-date", "collapsing-hides-only-the-grid-presets-stay-visible", "the-all-preset-is-the-empty-range", "the-summary-is-the-toggle-and-reports-its-expanded-state"];
173
221
  };
174
222
  export declare function dateRangeSpans(value: DateRangeValue, hoveredDate?: string | null): boolean;
175
223
  //# sourceMappingURL=date-range.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"date-range.d.ts","sourceRoot":"","sources":["../src/date-range.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,2DAA2D;IAC3D,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB,CAAC,CAAC;AAEH,eAAO,MAAM,cAAc,EAAE,cAA2C,CAAC;AAEzE;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE1F,eAAO,MAAM,qBAAqB,EAAE,cAA6B,CAAC;AA6BlE,2DAA2D;AAC3D,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,QAAQ,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAQhI;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,GAAE,cAAc,GAAG,IAAW,GAAG,IAAI,CAalG;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAMjH;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,cAAc,GAAG,IAAW,GAClC,cAAc,CAUhB;AAED,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;AAEtE;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B,kBAAkB,CASpB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;CAAE,CAAC,CAAC;AAI1G,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B,kBAAkB,CASpB;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,GAAG,KAAK,GAAG,IAAI,CAIxF;AAED,8DAA8D;AAC9D,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAIpF;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,GAAG,cAAc,CAUnG;AAED,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BlB,CAAC;AAEX,0CAA0C;AAC1C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAGlE;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;CAwBO,CAAC;AAEtC,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAK1F"}
1
+ {"version":3,"file":"date-range.d.ts","sourceRoot":"","sources":["../src/date-range.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;GAUG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IACpC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,2DAA2D;IAC3D,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB,CAAC,CAAC;AAEH,eAAO,MAAM,cAAc,EAAE,cAA2C,CAAC;AAEzE;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE1F,eAAO,MAAM,qBAAqB,EAAE,cAA6B,CAAC;AA6BlE,2DAA2D;AAC3D,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,QAAQ,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAQhI;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,EAAE,KAAK,GAAE,cAAc,GAAG,IAAW,GAAG,IAAI,CAalG;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI,GAAG,OAAO,CAMjH;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,cAAc,GAAG,IAAW,GAClC,cAAc,CAUhB;AAED,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;AAEtE;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B,kBAAkB,CASpB;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;CAAE,CAAC,CAAC;AAI1G,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,MAAM,EACZ,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAC1B,kBAAkB,CASpB;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,GAAG,KAAK,GAAG,IAAI,CAIxF;AAED;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,GAAG,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC;AAIpG;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,GAAG,cAAc,CAWnG;AAED,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwClB,CAAC;AAEX;;;;;;GAMG;AACH,wBAAgB,sCAAsC,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAG/G;AAED,0CAA0C;AAC1C,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAGlE;AAED,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;CA6BO,CAAC;AAEtC,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAK1F"}
@@ -135,6 +135,8 @@ const isoOf = (date) => date.toISOString().slice(0, 10);
135
135
  */
136
136
  export function resolveDateRangePreset(today, length) {
137
137
  assertIsoCalendarDate(today, "preset today");
138
+ if ("all" in length)
139
+ return emptyDateRange;
138
140
  const [year, month, day] = today.split("-").map(Number);
139
141
  const count = "days" in length ? length.days : length.months;
140
142
  if (!Number.isInteger(count) || count < 1)
@@ -169,28 +171,54 @@ export const dateRangeRecipe = {
169
171
  value: { textVariant: "body", color: semanticColors.content.primary, placeholderColor: semanticColors.content.tertiary },
170
172
  },
171
173
  // 프리셋 칩 줄(Chip 단일 선택, 작은 크기). 요약 아래·달력 위에서 줄바꿈한다.
172
- presets: { gap: spacing.xs, chipSize: "small" },
174
+ presets: {
175
+ gap: spacing.xs,
176
+ chipSize: "small",
177
+ // 기간 필터의 표준 프리셋(2026-10-28 사용자 결정). 문구는 제품 i18n이 붙인다. 적용 버튼이 있는 시트에서는
178
+ // `all`을 칩으로 두지 않고 BottomCTA 보조 행동(전체 날짜)으로 둔다.
179
+ standard: [
180
+ { id: "day", length: { days: 1 } },
181
+ { id: "week", length: { days: 7 } },
182
+ { id: "month", length: { months: 1 } },
183
+ { id: "quarter", length: { months: 3 } },
184
+ { id: "all", length: { all: true } },
185
+ ],
186
+ },
173
187
  // 요약·프리셋·달력 사이.
174
188
  gap: spacing.md,
189
+ // 접기(`collapsible`): 요약 줄이 펼침 버튼이 되고 끝에 방향 표시가 붙는다.
190
+ toggle: { icon: { collapsed: "chevronDown", expanded: "chevronUp" }, glyph: "sm", gap: spacing.xs },
175
191
  };
192
+ /**
193
+ * 접히는 기간 선택에서 이번 선택 뒤에 달력을 계속 펼쳐 둘지. 프리셋은 언제나 접고, 날짜 탭은 구간을 완성할 때 접는다
194
+ * (시작만 정한 첫 탭은 펼쳐 둔다). 처음에는 접힌 채 시작한다. 필터의 기본은 프리셋이고 달력은 직접 고를 때만 연다.
195
+ *
196
+ * 2026-10-28 사용자 "DateRangePicker도 접기 있게 해": 필터 영역에 둔 달력이 기간을 고른 뒤에도 늘 펼쳐져
197
+ * 목록을 밀어냈다(다에리 만난 동물). Sheet·Popover 합성 없이 본문 안에서 쓰는 접힘이고, 요약 칸이 그 버튼이다.
198
+ */
199
+ export function resolveDateRangeExpandedAfterSelection(next, source) {
200
+ validateDateRange(next);
201
+ return source === "date" && (next.start === null || next.end === null);
202
+ }
176
203
  /** 구간이 실제로 쓸 수 있는 값인지. 제품의 제출 버튼이 읽는다. */
177
204
  export function isCompleteDateRange(value) {
178
205
  validateDateRange(value);
179
206
  return value.start !== null && value.end !== null;
180
207
  }
181
208
  export const dateRangeBehavior = {
182
- controlled: ["value", "defaultValue", "onValueChange"],
209
+ controlled: ["value", "defaultValue", "onValueChange", "expanded", "defaultExpanded", "onExpandedChange"],
183
210
  inputs: ["grid", "monthLabel", "hoveredDate"],
184
211
  stateAxes: {
185
- value: ["empty", "selecting", "complete"],
212
+ // "expanded" applies only with `collapsible`; DisclosureGroup keeps the same state on the value axis.
213
+ value: ["empty", "selecting", "complete", "expanded"],
186
214
  availability: ["enabled", "disabled"],
187
215
  },
188
216
  web: {
189
- roles: ["grid", "gridcell"],
217
+ roles: ["grid", "gridcell", "button"],
190
218
  keyboard: ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End", "Enter", "Space"],
191
219
  focus: "roving",
192
220
  },
193
- native: { roles: [], states: ["selected", "disabled"], actions: ["select"] },
221
+ native: { roles: ["button"], states: ["selected", "disabled", "expanded"], actions: ["select", "activate"] },
194
222
  scenarios: [
195
223
  "a-click-on-a-complete-range-starts-a-new-one-instead-of-guessing-which-end-to-move",
196
224
  "picking-an-earlier-date-while-selecting-swaps-the-two-instead-of-rejecting-it",
@@ -201,6 +229,10 @@ export const dateRangeBehavior = {
201
229
  "the-range-is-one-band-between-two-filled-edges-and-a-one-day-range-has-no-band",
202
230
  "the-summary-marks-the-edge-being-picked-and-nothing-once-complete",
203
231
  "a-preset-ends-today-and-is-selected-only-while-the-value-equals-it",
232
+ "a-collapsible-picker-starts-folded-and-folds-again-after-a-preset-or-a-completing-date",
233
+ "collapsing-hides-only-the-grid-presets-stay-visible",
234
+ "the-all-preset-is-the-empty-range",
235
+ "the-summary-is-the-toggle-and-reports-its-expanded-state",
204
236
  ],
205
237
  };
206
238
  export function dateRangeSpans(value, hoveredDate) {
@@ -1 +1 @@
1
- {"version":3,"file":"date-range.js","sourceRoot":"","sources":["../src/date-range.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertIsoCalendarDate, calendarRecipe } from \"./calendar.js\";\nimport type { BehaviorContract } from \"./behaviors.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\nimport { accentTint } from \"./colors.js\";\nimport { themeColor } from \"./color-references.js\";\nimport { spacing, stroke } from \"./foundations.js\";\n\n/**\n * 날짜 **구간** 선택. Calendar의 단일 선택과 같은 격자를 쓰되, \"지금 무엇을 고르는\n * 중인가\"라는 축이 하나 더 있다.\n *\n * Calendar에 `mode: \"single\" | \"range\"`를 넣지 않은 이유: 단일 선택의 값은\n * `string | null`이고 구간의 값은 `{start, end}`다. 한 컴포넌트가 두 값 모양을 가지면\n * 모든 소비자가 매번 좁히기(narrowing)를 해야 하고, \"range 모드인데 selectedDate를 준\"\n * 조합이 타입에 남는다. 대신 이 모듈이 **구간 판정만** 갖고 격자는 그대로 재사용한다.\n *\n * 값은 제품이 저장한다 — 이 모듈은 다음 클릭이 시작을 바꾸는지 끝을 정하는지만 답한다.\n */\nexport type DateRangeValue = Readonly<{\n start: string | null;\n /** `start`만 있고 `end`가 없는 상태가 \"고르는 중\"이다. 별도 플래그를 두지 않는다. */\n end: string | null;\n}>;\n\nexport const emptyDateRange: DateRangeValue = { start: null, end: null };\n\n/**\n * 구간이 덮을 수 있는 최대 길이. 일수가 아니라 달력 단위로 센다 — \"1년\"을 365일로 두면 윤년을 낀\n * 1월 1일~12월 31일이 막힌다. 끝은 포함이라 `{ years: 1 }`은 2026-01-01부터 2026-12-31까지다.\n * 2026-10-25 사용자 요청으로 DateRangePicker 기본값은 1년이고, `null`이면 제한하지 않는다.\n */\nexport type DateRangeLimit = Readonly<{ years?: number; months?: number; days?: number }>;\n\nexport const defaultDateRangeLimit: DateRangeLimit = { years: 1 };\n\nfunction assertDateRangeLimit(limit: DateRangeLimit): void {\n const parts = [limit.years ?? 0, limit.months ?? 0, limit.days ?? 0];\n if (parts.some((part) => !Number.isInteger(part) || part < 0) || parts.every((part) => part === 0)) {\n throw new RangeError(\"Date range limit must be non-negative whole years/months/days and not empty\");\n }\n}\n\nfunction toUtc(date: string): Date {\n return new Date(Date.UTC(Number(date.slice(0, 4)), Number(date.slice(5, 7)) - 1, Number(date.slice(8, 10))));\n}\n\nfunction toIso(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n\n/** 달을 옮기면 그 달에 없는 날(1월 31일 + 1개월)은 말일로 맞춘다. 넘겨서 다음 달로 새지 않게 한다. */\nfunction shiftIsoDate(date: string, limit: DateRangeLimit, sign: 1 | -1): string {\n const base = toUtc(date);\n const months = base.getUTCFullYear() * 12 + base.getUTCMonth() + sign * ((limit.years ?? 0) * 12 + (limit.months ?? 0));\n const year = Math.floor(months / 12);\n const month = months - year * 12;\n const lastDay = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();\n const shifted = new Date(Date.UTC(year, month, Math.min(base.getUTCDate(), lastDay)));\n shifted.setUTCDate(shifted.getUTCDate() + sign * (limit.days ?? 0));\n return toIso(shifted);\n}\n\n/** `start`를 한쪽 끝으로 둘 때 다른 끝이 올 수 있는 가장 이른·늦은 날(둘 다 포함). */\nexport function resolveDateRangeLimitBounds(start: string, limit: DateRangeLimit): Readonly<{ earliest: string; latest: string }> {\n assertIsoCalendarDate(start, \"range start\");\n assertDateRangeLimit(limit);\n const latest = toUtc(shiftIsoDate(start, limit, 1));\n latest.setUTCDate(latest.getUTCDate() - 1);\n const earliest = toUtc(shiftIsoDate(start, limit, -1));\n earliest.setUTCDate(earliest.getUTCDate() + 1);\n return { earliest: toIso(earliest), latest: toIso(latest) };\n}\n\nexport function validateDateRange(value: DateRangeValue, limit: DateRangeLimit | null = null): void {\n if (value.start !== null) assertIsoCalendarDate(value.start, \"range start\");\n if (value.end !== null) assertIsoCalendarDate(value.end, \"range end\");\n if (value.start === null && value.end !== null) {\n throw new TypeError(\"Date range cannot have an end without a start\");\n }\n if (value.start !== null && value.end !== null && value.end < value.start) {\n throw new RangeError(\"Date range end must not precede start\");\n }\n if (limit !== null && value.start !== null && value.end !== null\n && value.end > resolveDateRangeLimitBounds(value.start, limit).latest) {\n throw new RangeError(\"Date range exceeds its maximum length\");\n }\n}\n\n/**\n * 고르는 중에 이 날짜를 끝으로 고를 수 있는지. 비었거나 완성된 구간에서는 누르면 새로 시작하므로\n * 언제나 고를 수 있다. 막힌 날은 renderer가 비활성으로 그린다 — 눌렀다가 거절하면 이유를 알 수 없다.\n */\nexport function isDateWithinRangeLimit(value: DateRangeValue, date: string, limit: DateRangeLimit | null): boolean {\n assertIsoCalendarDate(date, \"date\");\n validateDateRange(value, limit);\n if (limit === null || value.start === null || value.end !== null) return true;\n const { earliest, latest } = resolveDateRangeLimitBounds(value.start, limit);\n return date >= earliest && date <= latest;\n}\n\n/**\n * 날짜 하나를 눌렀을 때의 다음 값.\n *\n * - 비어 있거나 이미 완성된 구간이면 새 구간을 **시작**한다. (완성된 구간을 다시 눌렀을\n * 때 끝을 옮기는 동작은 \"어느 쪽 끝인가\"를 추측해야 해서 넣지 않았다 — 다시 시작하는\n * 쪽이 예측 가능하다.)\n * - 고르는 중이면 **끝**을 정한다. 시작보다 앞선 날짜를 누르면 두 값을 바꿔 담는다 —\n * 거절하면 사용자가 왜 안 되는지 알 수 없다.\n */\nexport function resolveDateRangeSelection(\n current: DateRangeValue,\n date: string,\n limit: DateRangeLimit | null = null,\n): DateRangeValue {\n assertIsoCalendarDate(date, \"selected date\");\n validateDateRange(current, limit);\n // 최대 길이를 넘는 날은 renderer가 막지만, 그래도 들어오면 넘는 구간을 만들지 않고 거기서 새로 시작한다.\n if (current.start === null || current.end !== null || !isDateWithinRangeLimit(current, date, limit)) {\n return { start: date, end: null };\n }\n return date < current.start\n ? { start: date, end: current.start }\n : { start: current.start, end: date };\n}\n\nexport type DateRangeCellState = \"start\" | \"end\" | \"between\" | \"none\";\n\n/**\n * 한 칸이 구간 안에서 어떤 자리인지. 미리보기(`hoveredDate`)는 아직 확정되지 않은 끝을\n * 가리키므로 같은 함수가 처리한다 — renderer가 두 벌의 칠하기 규칙을 만들지 않게 한다.\n */\nexport function resolveDateRangeCellState(\n value: DateRangeValue,\n date: string,\n hoveredDate?: string | null,\n): DateRangeCellState {\n validateDateRange(value);\n if (value.start === null) return \"none\";\n const provisionalEnd = value.end\n ?? (hoveredDate != null && hoveredDate >= value.start ? hoveredDate : null);\n if (date === value.start && (provisionalEnd === null || date !== provisionalEnd)) return \"start\";\n if (provisionalEnd !== null && date === provisionalEnd) return \"end\";\n if (provisionalEnd !== null && date > value.start && date < provisionalEnd) return \"between\";\n return \"none\";\n}\n\n/**\n * 칸 하나를 어떻게 칠하는지. `edge`는 채운 원(시작·끝), `band`는 시작과 끝을 잇는 띠의 모양이다.\n * 띠는 시작 칸에서 끝 쪽 절반(`toEnd`), 끝 칸에서 시작 쪽 절반(`toStart`), 사이 칸 전체(`full`)를 덮는다.\n * 시작과 끝이 같은 날(하루 구간)이거나 끝이 아직 없으면 띠가 없다.\n *\n * 2026-10-25 개편(Spint 기간 시트 사용자 지적): 점 표시는 구간이 이어져 보이지 않았고, 점 줄 때문에 행이\n * 라벨 한 줄만큼 높아졌다. Material 3·Airbnb처럼 띠로 잇고 두 끝을 같은 채운 원으로 그린다.\n */\nexport type DateRangeCellPaint = Readonly<{ edge: boolean; band: \"none\" | \"full\" | \"toEnd\" | \"toStart\" }>;\n\nconst unpainted: DateRangeCellPaint = { edge: false, band: \"none\" };\n\nexport function resolveDateRangeCellPaint(\n value: DateRangeValue,\n date: string,\n hoveredDate?: string | null,\n): DateRangeCellPaint {\n const state = resolveDateRangeCellState(value, date, hoveredDate);\n if (state === \"none\") return unpainted;\n if (state === \"between\") return { edge: false, band: \"full\" };\n const provisionalEnd = value.end\n ?? (hoveredDate != null && value.start !== null && hoveredDate >= value.start ? hoveredDate : null);\n const spans = provisionalEnd !== null && provisionalEnd !== value.start;\n if (state === \"start\") return { edge: true, band: spans ? \"toEnd\" : \"none\" };\n return { edge: true, band: spans ? \"toStart\" : \"none\" };\n}\n\n/**\n * 요약 칸에서 강조할 끝. 비었으면 시작, 고르는 중이면 끝을 강조한다. 완성된 구간은 아무것도 강조하지 않는다 —\n * 다음 탭이 새 시작이 되긴 하지만, 완성 직후 시작 칸이 강조되면 시작일을 고치는 중으로 읽혔다(2026-10-25 실화면).\n */\nexport function resolveDateRangeActiveEdge(value: DateRangeValue): \"start\" | \"end\" | null {\n validateDateRange(value);\n if (value.start === null) return \"start\";\n return value.end === null ? \"end\" : null;\n}\n\n/** 프리셋 길이. `days`는 오늘 포함 n일, `months`는 n개월 전 다음 날부터 오늘까지다. */\nexport type DateRangePresetLength = Readonly<{ days: number } | { months: number }>;\n\nconst isoOf = (date: Date) => date.toISOString().slice(0, 10);\n\n/**\n * 오늘로 끝나는 프리셋 구간(최근 7일·1개월 등). 날짜 계산은 UTC 달력 날짜로만 해 서머타임·시간대에 흔들리지 않는다.\n * 달 길이가 다르면 그 달의 마지막 날로 맞춘다(3/31의 1개월 전 = 2/28, 구간은 3/1부터).\n */\nexport function resolveDateRangePreset(today: string, length: DateRangePresetLength): DateRangeValue {\n assertIsoCalendarDate(today, \"preset today\");\n const [year, month, day] = today.split(\"-\").map(Number) as [number, number, number];\n const count = \"days\" in length ? length.days : length.months;\n if (!Number.isInteger(count) || count < 1) throw new RangeError(\"Date range preset length must be a positive integer\");\n if (\"days\" in length) return { start: isoOf(new Date(Date.UTC(year, month - 1, day - (count - 1)))), end: today };\n const lastDay = new Date(Date.UTC(year, month - 1 - count + 1, 0)).getUTCDate();\n const anchor = new Date(Date.UTC(year, month - 1 - count, Math.min(day, lastDay)));\n anchor.setUTCDate(anchor.getUTCDate() + 1);\n return { start: isoOf(anchor), end: today };\n}\n\nexport const dateRangeRecipe = {\n slots: [\"root\", \"summary\", \"summaryField\", \"summaryLabel\", \"summaryValue\", \"presets\", \"band\", \"edge\"] as const,\n // 띠는 두 끝 원과 같은 브랜드색의 tint다. 처음 쓴 `interaction.selected`(surfaceSelected)는 기본 팔레트에서\n // #f0f1f3 회색이라 시트 바탕 위에서 구간이 거의 보이지 않았다(2026-10-25 Spint 실화면). 높이는 날짜 원과 같다.\n band: { background: themeColor(\"primary\", accentTint.base) },\n edge: calendarRecipe.day.selected,\n // 시작일·종료일 요약. 안내 문장 대신 \"다음에 고를 쪽\"을 강조해 지금 무엇을 누르는지 보여 준다\n // (Material 3 기간 선택 머리·Airbnb 체크인/체크아웃 칸 모티브). 값이 없으면 제품 placeholder를 쓴다.\n summary: {\n gap: spacing.xs,\n field: {\n paddingVertical: spacing.xs,\n paddingHorizontal: spacing.sm,\n radius: \"md\" as const,\n gap: spacing.xxs,\n background: semanticColors.surface.sunken,\n activeBorder: semanticColors.action.brand.background,\n activeBorderWidth: stroke.strong,\n },\n label: { textVariant: \"label\" as const, color: semanticColors.content.secondary },\n value: { textVariant: \"body\" as const, color: semanticColors.content.primary, placeholderColor: semanticColors.content.tertiary },\n },\n // 프리셋 칩 줄(Chip 단일 선택, 작은 크기). 요약 아래·달력 위에서 줄바꿈한다.\n presets: { gap: spacing.xs, chipSize: \"small\" as const },\n // 요약·프리셋·달력 사이.\n gap: spacing.md,\n} as const;\n\n/** 구간이 실제로 쓸 수 있는 값인지. 제품의 제출 버튼이 읽는다. */\nexport function isCompleteDateRange(value: DateRangeValue): boolean {\n validateDateRange(value);\n return value.start !== null && value.end !== null;\n}\n\nexport const dateRangeBehavior = {\n controlled: [\"value\", \"defaultValue\", \"onValueChange\"],\n inputs: [\"grid\", \"monthLabel\", \"hoveredDate\"],\n stateAxes: {\n value: [\"empty\", \"selecting\", \"complete\"],\n availability: [\"enabled\", \"disabled\"],\n },\n web: {\n roles: [\"grid\", \"gridcell\"],\n keyboard: [\"ArrowUp\", \"ArrowDown\", \"ArrowLeft\", \"ArrowRight\", \"Home\", \"End\", \"Enter\", \"Space\"],\n focus: \"roving\",\n },\n native: { roles: [], states: [\"selected\", \"disabled\"], actions: [\"select\"] },\n scenarios: [\n \"a-click-on-a-complete-range-starts-a-new-one-instead-of-guessing-which-end-to-move\",\n \"picking-an-earlier-date-while-selecting-swaps-the-two-instead-of-rejecting-it\",\n \"the-selecting-state-is-start-without-end-not-a-separate-flag\",\n \"a-hovered-date-previews-the-end-through-the-same-cell-state-function\",\n \"an-end-without-a-start-is-rejected-by-validation-not-rendered-as-something\",\n \"calendar-keeps-single-selection-this-module-never-adds-a-mode-axis-to-it\",\n \"the-range-is-one-band-between-two-filled-edges-and-a-one-day-range-has-no-band\",\n \"the-summary-marks-the-edge-being-picked-and-nothing-once-complete\",\n \"a-preset-ends-today-and-is-selected-only-while-the-value-equals-it\",\n ],\n} as const satisfies BehaviorContract;\n\nexport function dateRangeSpans(value: DateRangeValue, hoveredDate?: string | null): boolean {\n validateDateRange(value);\n if (value.start === null) return false;\n const end = value.end ?? (hoveredDate != null && hoveredDate >= value.start ? hoveredDate : null);\n return end !== null && end !== value.start;\n}\n"]}
1
+ {"version":3,"file":"date-range.js","sourceRoot":"","sources":["../src/date-range.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertIsoCalendarDate, calendarRecipe } from \"./calendar.js\";\nimport type { BehaviorContract } from \"./behaviors.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\nimport { accentTint } from \"./colors.js\";\nimport { themeColor } from \"./color-references.js\";\nimport { spacing, stroke } from \"./foundations.js\";\n\n/**\n * 날짜 **구간** 선택. Calendar의 단일 선택과 같은 격자를 쓰되, \"지금 무엇을 고르는\n * 중인가\"라는 축이 하나 더 있다.\n *\n * Calendar에 `mode: \"single\" | \"range\"`를 넣지 않은 이유: 단일 선택의 값은\n * `string | null`이고 구간의 값은 `{start, end}`다. 한 컴포넌트가 두 값 모양을 가지면\n * 모든 소비자가 매번 좁히기(narrowing)를 해야 하고, \"range 모드인데 selectedDate를 준\"\n * 조합이 타입에 남는다. 대신 이 모듈이 **구간 판정만** 갖고 격자는 그대로 재사용한다.\n *\n * 값은 제품이 저장한다 — 이 모듈은 다음 클릭이 시작을 바꾸는지 끝을 정하는지만 답한다.\n */\nexport type DateRangeValue = Readonly<{\n start: string | null;\n /** `start`만 있고 `end`가 없는 상태가 \"고르는 중\"이다. 별도 플래그를 두지 않는다. */\n end: string | null;\n}>;\n\nexport const emptyDateRange: DateRangeValue = { start: null, end: null };\n\n/**\n * 구간이 덮을 수 있는 최대 길이. 일수가 아니라 달력 단위로 센다 — \"1년\"을 365일로 두면 윤년을 낀\n * 1월 1일~12월 31일이 막힌다. 끝은 포함이라 `{ years: 1 }`은 2026-01-01부터 2026-12-31까지다.\n * 2026-10-25 사용자 요청으로 DateRangePicker 기본값은 1년이고, `null`이면 제한하지 않는다.\n */\nexport type DateRangeLimit = Readonly<{ years?: number; months?: number; days?: number }>;\n\nexport const defaultDateRangeLimit: DateRangeLimit = { years: 1 };\n\nfunction assertDateRangeLimit(limit: DateRangeLimit): void {\n const parts = [limit.years ?? 0, limit.months ?? 0, limit.days ?? 0];\n if (parts.some((part) => !Number.isInteger(part) || part < 0) || parts.every((part) => part === 0)) {\n throw new RangeError(\"Date range limit must be non-negative whole years/months/days and not empty\");\n }\n}\n\nfunction toUtc(date: string): Date {\n return new Date(Date.UTC(Number(date.slice(0, 4)), Number(date.slice(5, 7)) - 1, Number(date.slice(8, 10))));\n}\n\nfunction toIso(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n\n/** 달을 옮기면 그 달에 없는 날(1월 31일 + 1개월)은 말일로 맞춘다. 넘겨서 다음 달로 새지 않게 한다. */\nfunction shiftIsoDate(date: string, limit: DateRangeLimit, sign: 1 | -1): string {\n const base = toUtc(date);\n const months = base.getUTCFullYear() * 12 + base.getUTCMonth() + sign * ((limit.years ?? 0) * 12 + (limit.months ?? 0));\n const year = Math.floor(months / 12);\n const month = months - year * 12;\n const lastDay = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();\n const shifted = new Date(Date.UTC(year, month, Math.min(base.getUTCDate(), lastDay)));\n shifted.setUTCDate(shifted.getUTCDate() + sign * (limit.days ?? 0));\n return toIso(shifted);\n}\n\n/** `start`를 한쪽 끝으로 둘 때 다른 끝이 올 수 있는 가장 이른·늦은 날(둘 다 포함). */\nexport function resolveDateRangeLimitBounds(start: string, limit: DateRangeLimit): Readonly<{ earliest: string; latest: string }> {\n assertIsoCalendarDate(start, \"range start\");\n assertDateRangeLimit(limit);\n const latest = toUtc(shiftIsoDate(start, limit, 1));\n latest.setUTCDate(latest.getUTCDate() - 1);\n const earliest = toUtc(shiftIsoDate(start, limit, -1));\n earliest.setUTCDate(earliest.getUTCDate() + 1);\n return { earliest: toIso(earliest), latest: toIso(latest) };\n}\n\nexport function validateDateRange(value: DateRangeValue, limit: DateRangeLimit | null = null): void {\n if (value.start !== null) assertIsoCalendarDate(value.start, \"range start\");\n if (value.end !== null) assertIsoCalendarDate(value.end, \"range end\");\n if (value.start === null && value.end !== null) {\n throw new TypeError(\"Date range cannot have an end without a start\");\n }\n if (value.start !== null && value.end !== null && value.end < value.start) {\n throw new RangeError(\"Date range end must not precede start\");\n }\n if (limit !== null && value.start !== null && value.end !== null\n && value.end > resolveDateRangeLimitBounds(value.start, limit).latest) {\n throw new RangeError(\"Date range exceeds its maximum length\");\n }\n}\n\n/**\n * 고르는 중에 이 날짜를 끝으로 고를 수 있는지. 비었거나 완성된 구간에서는 누르면 새로 시작하므로\n * 언제나 고를 수 있다. 막힌 날은 renderer가 비활성으로 그린다 — 눌렀다가 거절하면 이유를 알 수 없다.\n */\nexport function isDateWithinRangeLimit(value: DateRangeValue, date: string, limit: DateRangeLimit | null): boolean {\n assertIsoCalendarDate(date, \"date\");\n validateDateRange(value, limit);\n if (limit === null || value.start === null || value.end !== null) return true;\n const { earliest, latest } = resolveDateRangeLimitBounds(value.start, limit);\n return date >= earliest && date <= latest;\n}\n\n/**\n * 날짜 하나를 눌렀을 때의 다음 값.\n *\n * - 비어 있거나 이미 완성된 구간이면 새 구간을 **시작**한다. (완성된 구간을 다시 눌렀을\n * 때 끝을 옮기는 동작은 \"어느 쪽 끝인가\"를 추측해야 해서 넣지 않았다 — 다시 시작하는\n * 쪽이 예측 가능하다.)\n * - 고르는 중이면 **끝**을 정한다. 시작보다 앞선 날짜를 누르면 두 값을 바꿔 담는다 —\n * 거절하면 사용자가 왜 안 되는지 알 수 없다.\n */\nexport function resolveDateRangeSelection(\n current: DateRangeValue,\n date: string,\n limit: DateRangeLimit | null = null,\n): DateRangeValue {\n assertIsoCalendarDate(date, \"selected date\");\n validateDateRange(current, limit);\n // 최대 길이를 넘는 날은 renderer가 막지만, 그래도 들어오면 넘는 구간을 만들지 않고 거기서 새로 시작한다.\n if (current.start === null || current.end !== null || !isDateWithinRangeLimit(current, date, limit)) {\n return { start: date, end: null };\n }\n return date < current.start\n ? { start: date, end: current.start }\n : { start: current.start, end: date };\n}\n\nexport type DateRangeCellState = \"start\" | \"end\" | \"between\" | \"none\";\n\n/**\n * 한 칸이 구간 안에서 어떤 자리인지. 미리보기(`hoveredDate`)는 아직 확정되지 않은 끝을\n * 가리키므로 같은 함수가 처리한다 — renderer가 두 벌의 칠하기 규칙을 만들지 않게 한다.\n */\nexport function resolveDateRangeCellState(\n value: DateRangeValue,\n date: string,\n hoveredDate?: string | null,\n): DateRangeCellState {\n validateDateRange(value);\n if (value.start === null) return \"none\";\n const provisionalEnd = value.end\n ?? (hoveredDate != null && hoveredDate >= value.start ? hoveredDate : null);\n if (date === value.start && (provisionalEnd === null || date !== provisionalEnd)) return \"start\";\n if (provisionalEnd !== null && date === provisionalEnd) return \"end\";\n if (provisionalEnd !== null && date > value.start && date < provisionalEnd) return \"between\";\n return \"none\";\n}\n\n/**\n * 칸 하나를 어떻게 칠하는지. `edge`는 채운 원(시작·끝), `band`는 시작과 끝을 잇는 띠의 모양이다.\n * 띠는 시작 칸에서 끝 쪽 절반(`toEnd`), 끝 칸에서 시작 쪽 절반(`toStart`), 사이 칸 전체(`full`)를 덮는다.\n * 시작과 끝이 같은 날(하루 구간)이거나 끝이 아직 없으면 띠가 없다.\n *\n * 2026-10-25 개편(Spint 기간 시트 사용자 지적): 점 표시는 구간이 이어져 보이지 않았고, 점 줄 때문에 행이\n * 라벨 한 줄만큼 높아졌다. Material 3·Airbnb처럼 띠로 잇고 두 끝을 같은 채운 원으로 그린다.\n */\nexport type DateRangeCellPaint = Readonly<{ edge: boolean; band: \"none\" | \"full\" | \"toEnd\" | \"toStart\" }>;\n\nconst unpainted: DateRangeCellPaint = { edge: false, band: \"none\" };\n\nexport function resolveDateRangeCellPaint(\n value: DateRangeValue,\n date: string,\n hoveredDate?: string | null,\n): DateRangeCellPaint {\n const state = resolveDateRangeCellState(value, date, hoveredDate);\n if (state === \"none\") return unpainted;\n if (state === \"between\") return { edge: false, band: \"full\" };\n const provisionalEnd = value.end\n ?? (hoveredDate != null && value.start !== null && hoveredDate >= value.start ? hoveredDate : null);\n const spans = provisionalEnd !== null && provisionalEnd !== value.start;\n if (state === \"start\") return { edge: true, band: spans ? \"toEnd\" : \"none\" };\n return { edge: true, band: spans ? \"toStart\" : \"none\" };\n}\n\n/**\n * 요약 칸에서 강조할 끝. 비었으면 시작, 고르는 중이면 끝을 강조한다. 완성된 구간은 아무것도 강조하지 않는다 —\n * 다음 탭이 새 시작이 되긴 하지만, 완성 직후 시작 칸이 강조되면 시작일을 고치는 중으로 읽혔다(2026-10-25 실화면).\n */\nexport function resolveDateRangeActiveEdge(value: DateRangeValue): \"start\" | \"end\" | null {\n validateDateRange(value);\n if (value.start === null) return \"start\";\n return value.end === null ? \"end\" : null;\n}\n\n/**\n * 프리셋 길이. `days`는 오늘 포함 n일, `months`는 n개월 전 다음 날부터 오늘까지, `all`은 날짜 제한 없음(빈 구간)이다.\n * `all`은 2026-10-28 사용자 요청(\"전체가 포함되게 하면 1일, 1주일, 1개월, 3개월, 전체로 하자\")으로 생겼다. 필터의\n * [전체·오늘·기간 지정] 탭과 프리셋이 같은 일을 두 번 해 탭을 없애고, 전체를 프리셋 한 칸으로 옮겼다.\n */\nexport type DateRangePresetLength = Readonly<{ days: number } | { months: number } | { all: true }>;\n\nconst isoOf = (date: Date) => date.toISOString().slice(0, 10);\n\n/**\n * 오늘로 끝나는 프리셋 구간(최근 7일·1개월 등). 날짜 계산은 UTC 달력 날짜로만 해 서머타임·시간대에 흔들리지 않는다.\n * 달 길이가 다르면 그 달의 마지막 날로 맞춘다(3/31의 1개월 전 = 2/28, 구간은 3/1부터).\n */\nexport function resolveDateRangePreset(today: string, length: DateRangePresetLength): DateRangeValue {\n assertIsoCalendarDate(today, \"preset today\");\n if (\"all\" in length) return emptyDateRange;\n const [year, month, day] = today.split(\"-\").map(Number) as [number, number, number];\n const count = \"days\" in length ? length.days : length.months;\n if (!Number.isInteger(count) || count < 1) throw new RangeError(\"Date range preset length must be a positive integer\");\n if (\"days\" in length) return { start: isoOf(new Date(Date.UTC(year, month - 1, day - (count - 1)))), end: today };\n const lastDay = new Date(Date.UTC(year, month - 1 - count + 1, 0)).getUTCDate();\n const anchor = new Date(Date.UTC(year, month - 1 - count, Math.min(day, lastDay)));\n anchor.setUTCDate(anchor.getUTCDate() + 1);\n return { start: isoOf(anchor), end: today };\n}\n\nexport const dateRangeRecipe = {\n slots: [\"root\", \"summary\", \"summaryField\", \"summaryLabel\", \"summaryValue\", \"presets\", \"band\", \"edge\"] as const,\n // 띠는 두 끝 원과 같은 브랜드색의 tint다. 처음 쓴 `interaction.selected`(surfaceSelected)는 기본 팔레트에서\n // #f0f1f3 회색이라 시트 바탕 위에서 구간이 거의 보이지 않았다(2026-10-25 Spint 실화면). 높이는 날짜 원과 같다.\n band: { background: themeColor(\"primary\", accentTint.base) },\n edge: calendarRecipe.day.selected,\n // 시작일·종료일 요약. 안내 문장 대신 \"다음에 고를 쪽\"을 강조해 지금 무엇을 누르는지 보여 준다\n // (Material 3 기간 선택 머리·Airbnb 체크인/체크아웃 칸 모티브). 값이 없으면 제품 placeholder를 쓴다.\n summary: {\n gap: spacing.xs,\n field: {\n paddingVertical: spacing.xs,\n paddingHorizontal: spacing.sm,\n radius: \"md\" as const,\n gap: spacing.xxs,\n background: semanticColors.surface.sunken,\n activeBorder: semanticColors.action.brand.background,\n activeBorderWidth: stroke.strong,\n },\n label: { textVariant: \"label\" as const, color: semanticColors.content.secondary },\n value: { textVariant: \"body\" as const, color: semanticColors.content.primary, placeholderColor: semanticColors.content.tertiary },\n },\n // 프리셋 칩 줄(Chip 단일 선택, 작은 크기). 요약 아래·달력 위에서 줄바꿈한다.\n presets: {\n gap: spacing.xs,\n chipSize: \"small\" as const,\n // 기간 필터의 표준 프리셋(2026-10-28 사용자 결정). 문구는 제품 i18n이 붙인다. 적용 버튼이 있는 시트에서는\n // `all`을 칩으로 두지 않고 BottomCTA 보조 행동(전체 날짜)으로 둔다.\n standard: [\n { id: \"day\", length: { days: 1 } },\n { id: \"week\", length: { days: 7 } },\n { id: \"month\", length: { months: 1 } },\n { id: \"quarter\", length: { months: 3 } },\n { id: \"all\", length: { all: true } },\n ] as const,\n },\n // 요약·프리셋·달력 사이.\n gap: spacing.md,\n // 접기(`collapsible`): 요약 줄이 펼침 버튼이 되고 끝에 방향 표시가 붙는다.\n toggle: { icon: { collapsed: \"chevronDown\", expanded: \"chevronUp\" }, glyph: \"sm\" as const, gap: spacing.xs },\n} as const;\n\n/**\n * 접히는 기간 선택에서 이번 선택 뒤에 달력을 계속 펼쳐 둘지. 프리셋은 언제나 접고, 날짜 탭은 구간을 완성할 때 접는다\n * (시작만 정한 첫 탭은 펼쳐 둔다). 처음에는 접힌 채 시작한다. 필터의 기본은 프리셋이고 달력은 직접 고를 때만 연다.\n *\n * 2026-10-28 사용자 \"DateRangePicker도 접기 있게 해\": 필터 영역에 둔 달력이 기간을 고른 뒤에도 늘 펼쳐져\n * 목록을 밀어냈다(다에리 만난 동물). Sheet·Popover 합성 없이 본문 안에서 쓰는 접힘이고, 요약 칸이 그 버튼이다.\n */\nexport function resolveDateRangeExpandedAfterSelection(next: DateRangeValue, source: \"date\" | \"preset\"): boolean {\n validateDateRange(next);\n return source === \"date\" && (next.start === null || next.end === null);\n}\n\n/** 구간이 실제로 쓸 수 있는 값인지. 제품의 제출 버튼이 읽는다. */\nexport function isCompleteDateRange(value: DateRangeValue): boolean {\n validateDateRange(value);\n return value.start !== null && value.end !== null;\n}\n\nexport const dateRangeBehavior = {\n controlled: [\"value\", \"defaultValue\", \"onValueChange\", \"expanded\", \"defaultExpanded\", \"onExpandedChange\"],\n inputs: [\"grid\", \"monthLabel\", \"hoveredDate\"],\n stateAxes: {\n // \"expanded\" applies only with `collapsible`; DisclosureGroup keeps the same state on the value axis.\n value: [\"empty\", \"selecting\", \"complete\", \"expanded\"],\n availability: [\"enabled\", \"disabled\"],\n },\n web: {\n roles: [\"grid\", \"gridcell\", \"button\"],\n keyboard: [\"ArrowUp\", \"ArrowDown\", \"ArrowLeft\", \"ArrowRight\", \"Home\", \"End\", \"Enter\", \"Space\"],\n focus: \"roving\",\n },\n native: { roles: [\"button\"], states: [\"selected\", \"disabled\", \"expanded\"], actions: [\"select\", \"activate\"] },\n scenarios: [\n \"a-click-on-a-complete-range-starts-a-new-one-instead-of-guessing-which-end-to-move\",\n \"picking-an-earlier-date-while-selecting-swaps-the-two-instead-of-rejecting-it\",\n \"the-selecting-state-is-start-without-end-not-a-separate-flag\",\n \"a-hovered-date-previews-the-end-through-the-same-cell-state-function\",\n \"an-end-without-a-start-is-rejected-by-validation-not-rendered-as-something\",\n \"calendar-keeps-single-selection-this-module-never-adds-a-mode-axis-to-it\",\n \"the-range-is-one-band-between-two-filled-edges-and-a-one-day-range-has-no-band\",\n \"the-summary-marks-the-edge-being-picked-and-nothing-once-complete\",\n \"a-preset-ends-today-and-is-selected-only-while-the-value-equals-it\",\n \"a-collapsible-picker-starts-folded-and-folds-again-after-a-preset-or-a-completing-date\",\n \"collapsing-hides-only-the-grid-presets-stay-visible\",\n \"the-all-preset-is-the-empty-range\",\n \"the-summary-is-the-toggle-and-reports-its-expanded-state\",\n ],\n} as const satisfies BehaviorContract;\n\nexport function dateRangeSpans(value: DateRangeValue, hoveredDate?: string | null): boolean {\n validateDateRange(value);\n if (value.start === null) return false;\n const end = value.end ?? (hoveredDate != null && hoveredDate >= value.start ? hoveredDate : null);\n return end !== null && end !== value.start;\n}\n"]}
@@ -124,17 +124,11 @@ export declare const iconButtonRecipe: {
124
124
  };
125
125
  readonly states: {
126
126
  readonly selected: {
127
- readonly background: Readonly<{
128
- source: "theme";
129
- key: "surfaceSelected";
130
- alpha?: number;
131
- }>;
132
127
  readonly content: Readonly<{
133
128
  source: "theme";
134
129
  key: "text";
135
130
  alpha?: number;
136
131
  }>;
137
- readonly border: null;
138
132
  };
139
133
  readonly pressedOpacity: 0.86;
140
134
  readonly disabledOpacity: 0.5;
@@ -1 +1 @@
1
- {"version":3,"file":"icon-button-recipe.d.ts","sourceRoot":"","sources":["../src/icon-button-recipe.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAY/B,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC1D,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,CAAC;AACnD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC1E;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AACtD,eAAO,MAAM,eAAe,mCAAwE,CAAC;AAErG,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+B3B;;;;;;OAMG;;;;IAEH;;;OAGG;;;;;IAEH;;;;;;OAMG;;;;;;;;;;;;;;;;;;;;;;;;CAoCJ,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG,QAAQ,CAAC;IACpD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC,CAAC;AAEH,iFAAiF;AACjF,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,qBAAqB,EAC9B,QAAQ,UAAQ,GACf,8BAA8B,CAiBhC;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,cAAc,EACpB,eAAe,GAAE,MAA8C,GAC9D,MAAM,CAGR;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,cAAc,EACpB,eAAe,GAAE,MAA8C,GAC9D,QAAQ,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAOrD;AAED,+FAA+F;AAC/F,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAKzF"}
1
+ {"version":3,"file":"icon-button-recipe.d.ts","sourceRoot":"","sources":["../src/icon-button-recipe.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAY/B,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAC1D,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,QAAQ,CAAC;AACnD,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC1E;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AACtD,eAAO,MAAM,eAAe,mCAAwE,CAAC;AAErG,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+B3B;;;;;;OAMG;;;;IAEH;;;OAGG;;;;;IAEH;;;;;;OAMG;;;;;;;;;;;;;;;;;;CA8BJ,CAAC;AAEF,MAAM,MAAM,8BAA8B,GAAG,QAAQ,CAAC;IACpD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC,CAAC;AAEH,iFAAiF;AACjF,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,qBAAqB,EAC9B,QAAQ,UAAQ,GACf,8BAA8B,CAoBhC;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,cAAc,EACpB,eAAe,GAAE,MAA8C,GAC9D,MAAM,CAGR;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,cAAc,EACpB,eAAe,GAAE,MAA8C,GAC9D,QAAQ,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAOrD;AAED,+FAA+F;AAC/F,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAKzF"}
@@ -56,27 +56,24 @@ export const iconButtonRecipe = {
56
56
  */
57
57
  badge: { size: "small", variant: "floating", glyphOverlap: stroke.strong, inlineEnd: 0 },
58
58
  states: {
59
- // `aria-pressed` / `accessibilityState.selected` already carried the toggle
60
- // state; without a paired visual every consumer painted the pressed icon
61
- // button in product styles. Mirrors `buttonRecipe.states.selected`.
62
- selected: {
63
- background: semanticColors.selection.background,
64
- content: semanticColors.selection.content,
65
- // Match Button: neutral selection does not introduce an outline.
66
- border: null,
67
- },
59
+ // 2026-10-28: the selected flower gained an unwanted surrounding plate. Selection keeps the tone's
60
+ // background/border; only foreground or the product's filled glyph conveys the persistent state.
61
+ selected: { content: semanticColors.selection.content },
68
62
  pressedOpacity: opacity.pressed,
69
63
  disabledOpacity: opacity.disabled,
70
64
  },
71
65
  };
72
66
  /** Resolve one recipe tone for non-CSS renderers without a second tone table. */
73
67
  export function resolveIconButtonPresentation(tone, palette, selected = false) {
74
- const contract = selected ? iconButtonRecipe.states.selected : iconButtonRecipe.tones[tone];
68
+ const contract = iconButtonRecipe.tones[tone];
69
+ // Filled tones keep inverse content so selecting never loses contrast against their retained fill.
70
+ const content = selected && tone !== "primary" && tone !== "danger"
71
+ ? iconButtonRecipe.states.selected.content : contract.content;
75
72
  return {
76
73
  background: contract.background === null
77
74
  ? null
78
75
  : resolveColorReference(contract.background, palette),
79
- content: resolveColorReference(contract.content, palette),
76
+ content: resolveColorReference(content, palette),
80
77
  border: contract.border === null
81
78
  ? null
82
79
  : resolveColorReference(contract.border, palette),
@@ -1 +1 @@
1
- {"version":3,"file":"icon-button-recipe.js","sourceRoot":"","sources":["../src/icon-button-recipe.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveColorReference,\n type ColorReference,\n type ColorReferencePalette,\n} from \"./color-references.js\";\nimport {\n glyph,\n opacity,\n radius,\n stroke,\n validateElevationStep,\n type GlyphSize,\n} from \"./foundations.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\nimport { counterBadgeRecipe, type CounterBadgeSize, type CounterBadgeVariant } from \"./counter-badge-recipe.js\";\n\nexport type IconButtonSize = \"small\" | \"medium\" | \"large\";\nexport type IconButtonShape = \"rounded\" | \"circle\";\nexport type IconButtonTone = \"primary\" | \"secondary\" | \"ghost\" | \"danger\";\n/**\n * Which container edge a ghost IconButton sits on (logical: `start`/`end` follow the reading direction). The\n * button keeps its full touch target but overhangs that edge so its glyph slot, not the transparent hit area,\n * sets the visible inset (2026-10-17 measured audit: glyphs sat 10–15px inside the row/header inset).\n */\nexport type IconButtonEdge = \"start\" | \"end\" | \"both\";\nexport const iconButtonEdges = [\"start\", \"end\", \"both\"] as const satisfies readonly IconButtonEdge[];\n\nexport const iconButtonRecipe = {\n slots: [\"root\", \"icon\", \"spinner\"] as const,\n defaults: { tone: \"ghost\", size: \"medium\", shape: \"rounded\" },\n tones: {\n primary: {\n background: semanticColors.action.brand.background,\n content: semanticColors.action.brand.content,\n border: null,\n },\n secondary: {\n background: semanticColors.action.neutral.background,\n content: semanticColors.action.neutral.content,\n border: semanticColors.action.neutral.border,\n },\n ghost: {\n background: null,\n content: semanticColors.content.secondary,\n border: null,\n },\n danger: {\n background: semanticColors.action.danger.background,\n content: semanticColors.action.danger.content,\n border: null,\n },\n },\n sizes: {\n small: { diameter: 36, hitSlop: 4, glyph: \"sm\" },\n medium: { diameter: 44, hitSlop: 0, glyph: \"md\" },\n large: { diameter: 52, hitSlop: 0, glyph: \"lg\" },\n },\n shapes: { rounded: \"md\", circle: \"full\" },\n /**\n * Edge alignment (2026-10-17 measured audit): a ghost IconButton at a row/header edge overhangs that edge by\n * (visible diameter − glyph slot) / 2, so the glyph slot lines up with the container inset like text does while\n * the hit area stays whole. Only `ghost` overhangs — filled and outlined tones show their frame, and the frame is\n * what aligns. Renderers read `resolveIconButtonEdgeOverhang` so a raised visible diameter (minimumVisualTarget)\n * moves the glyph slot by the same amount on Web and Native.\n */\n edge: { tones: [\"ghost\"] as const },\n /**\n * `elevation` (2026-10-23) lifts a floating control (Burntok Dock's center action) with a shadow token. Only filled\n * tones can carry it: a ghost button has no frame for the shadow to belong to (Android draws none without a fill).\n */\n elevation: { default: \"none\", tones: [\"primary\", \"secondary\", \"danger\"] as const },\n /**\n * Count badge on an IconButton (NotificationBell). 2026-10-23 web check: a medium badge at the button's top-end\n * corner (top 0, end 0) covered 82% of BurnTok's 18px heart in a small (36) bell. The badge is now the compact\n * `small` floating plate, kept on the button's end edge (it never sticks out past an `edge`-aligned inset) and\n * raised so only its `glyphOverlap` ring (the canvas-colored floating border) reaches into the glyph slot.\n * Wider counts grow toward the start along the top, not down over the glyph. See `resolveIconButtonBadgeOffset`.\n */\n badge: { size: \"small\", variant: \"floating\", glyphOverlap: stroke.strong, inlineEnd: 0 },\n states: {\n // `aria-pressed` / `accessibilityState.selected` already carried the toggle\n // state; without a paired visual every consumer painted the pressed icon\n // button in product styles. Mirrors `buttonRecipe.states.selected`.\n selected: {\n background: semanticColors.selection.background,\n content: semanticColors.selection.content,\n // Match Button: neutral selection does not introduce an outline.\n border: null,\n },\n pressedOpacity: opacity.pressed,\n disabledOpacity: opacity.disabled,\n },\n} as const satisfies {\n slots: readonly string[];\n defaults: {\n tone: IconButtonTone;\n size: IconButtonSize;\n shape: IconButtonShape;\n };\n tones: Record<\n IconButtonTone,\n { background: ColorReference | null; content: ColorReference; border: ColorReference | null }\n >;\n sizes: Record<IconButtonSize, { diameter: number; hitSlop: number; glyph: GlyphSize }>;\n shapes: Record<IconButtonShape, keyof typeof radius>;\n edge: { tones: readonly IconButtonTone[] };\n elevation: { default: \"none\"; tones: readonly IconButtonTone[] };\n badge: { size: CounterBadgeSize; variant: CounterBadgeVariant; glyphOverlap: number; inlineEnd: number };\n states: {\n selected: { background: ColorReference; content: ColorReference; border: ColorReference | null };\n pressedOpacity: number;\n disabledOpacity: number;\n };\n};\n\nexport type ResolvedIconButtonPresentation = Readonly<{\n background: string | null;\n content: string;\n border: string | null;\n}>;\n\n/** Resolve one recipe tone for non-CSS renderers without a second tone table. */\nexport function resolveIconButtonPresentation(\n tone: IconButtonTone,\n palette: ColorReferencePalette,\n selected = false,\n): ResolvedIconButtonPresentation {\n const contract: {\n background: ColorReference | null;\n content: ColorReference;\n border: ColorReference | null;\n } = selected ? iconButtonRecipe.states.selected : iconButtonRecipe.tones[tone];\n return {\n background:\n contract.background === null\n ? null\n : resolveColorReference(contract.background, palette),\n content: resolveColorReference(contract.content, palette),\n border:\n contract.border === null\n ? null\n : resolveColorReference(contract.border, palette),\n };\n}\n\n/**\n * Negative margin a ghost IconButton applies on its `edge` side(s): (visible diameter − glyph slot) / 2, e.g. 10 for\n * medium (44 − 24). 0 for tones that draw a frame. `visibleDiameter` is the rendered size after the Provider's\n * minimumVisualTarget axis (`visibleControlHeight`), so the overhang tracks what is actually drawn.\n */\nexport function resolveIconButtonEdgeOverhang(\n tone: IconButtonTone,\n size: IconButtonSize,\n visibleDiameter: number = iconButtonRecipe.sizes[size].diameter,\n): number {\n if (!(iconButtonRecipe.edge.tones as readonly IconButtonTone[]).includes(tone)) return 0;\n return Math.max(0, (visibleDiameter - glyph[iconButtonRecipe.sizes[size].glyph]) / 2);\n}\n\n/**\n * Where an IconButton's count badge sits, measured from the button's top-end corner (logical: `inlineEnd` mirrors in\n * RTL). The badge's block-end lands `badge.glyphOverlap` inside the glyph slot's top edge: blockStart = slot inset +\n * overlap − badge height, e.g. −6 for small (36 − 20 slot, 16 badge). `visibleDiameter` is the rendered size after the\n * Provider's minimumVisualTarget axis, so the badge follows the glyph slot when the button grows (Web and Native).\n */\nexport function resolveIconButtonBadgeOffset(\n size: IconButtonSize,\n visibleDiameter: number = iconButtonRecipe.sizes[size].diameter,\n): Readonly<{ blockStart: number; inlineEnd: number }> {\n const { badge } = iconButtonRecipe;\n const slotInset = Math.max(0, (visibleDiameter - glyph[iconButtonRecipe.sizes[size].glyph]) / 2);\n return {\n blockStart: slotInset + badge.glyphOverlap - counterBadgeRecipe.sizes[badge.size].height,\n inlineEnd: badge.inlineEnd,\n };\n}\n\n/** Throws for an unknown step or an elevated ghost IconButton (iconButtonRecipe.elevation). */\nexport function validateIconButtonElevation(elevation: string, tone: IconButtonTone): void {\n validateElevationStep(elevation, \"IconButton\");\n if (elevation !== \"none\" && !(iconButtonRecipe.elevation.tones as readonly string[]).includes(tone)) {\n throw new TypeError(`IconButton elevation needs a filled tone, not ${tone}`);\n }\n}\n"]}
1
+ {"version":3,"file":"icon-button-recipe.js","sourceRoot":"","sources":["../src/icon-button-recipe.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveColorReference,\n type ColorReference,\n type ColorReferencePalette,\n} from \"./color-references.js\";\nimport {\n glyph,\n opacity,\n radius,\n stroke,\n validateElevationStep,\n type GlyphSize,\n} from \"./foundations.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\nimport { counterBadgeRecipe, type CounterBadgeSize, type CounterBadgeVariant } from \"./counter-badge-recipe.js\";\n\nexport type IconButtonSize = \"small\" | \"medium\" | \"large\";\nexport type IconButtonShape = \"rounded\" | \"circle\";\nexport type IconButtonTone = \"primary\" | \"secondary\" | \"ghost\" | \"danger\";\n/**\n * Which container edge a ghost IconButton sits on (logical: `start`/`end` follow the reading direction). The\n * button keeps its full touch target but overhangs that edge so its glyph slot, not the transparent hit area,\n * sets the visible inset (2026-10-17 measured audit: glyphs sat 10–15px inside the row/header inset).\n */\nexport type IconButtonEdge = \"start\" | \"end\" | \"both\";\nexport const iconButtonEdges = [\"start\", \"end\", \"both\"] as const satisfies readonly IconButtonEdge[];\n\nexport const iconButtonRecipe = {\n slots: [\"root\", \"icon\", \"spinner\"] as const,\n defaults: { tone: \"ghost\", size: \"medium\", shape: \"rounded\" },\n tones: {\n primary: {\n background: semanticColors.action.brand.background,\n content: semanticColors.action.brand.content,\n border: null,\n },\n secondary: {\n background: semanticColors.action.neutral.background,\n content: semanticColors.action.neutral.content,\n border: semanticColors.action.neutral.border,\n },\n ghost: {\n background: null,\n content: semanticColors.content.secondary,\n border: null,\n },\n danger: {\n background: semanticColors.action.danger.background,\n content: semanticColors.action.danger.content,\n border: null,\n },\n },\n sizes: {\n small: { diameter: 36, hitSlop: 4, glyph: \"sm\" },\n medium: { diameter: 44, hitSlop: 0, glyph: \"md\" },\n large: { diameter: 52, hitSlop: 0, glyph: \"lg\" },\n },\n shapes: { rounded: \"md\", circle: \"full\" },\n /**\n * Edge alignment (2026-10-17 measured audit): a ghost IconButton at a row/header edge overhangs that edge by\n * (visible diameter − glyph slot) / 2, so the glyph slot lines up with the container inset like text does while\n * the hit area stays whole. Only `ghost` overhangs — filled and outlined tones show their frame, and the frame is\n * what aligns. Renderers read `resolveIconButtonEdgeOverhang` so a raised visible diameter (minimumVisualTarget)\n * moves the glyph slot by the same amount on Web and Native.\n */\n edge: { tones: [\"ghost\"] as const },\n /**\n * `elevation` (2026-10-23) lifts a floating control (Burntok Dock's center action) with a shadow token. Only filled\n * tones can carry it: a ghost button has no frame for the shadow to belong to (Android draws none without a fill).\n */\n elevation: { default: \"none\", tones: [\"primary\", \"secondary\", \"danger\"] as const },\n /**\n * Count badge on an IconButton (NotificationBell). 2026-10-23 web check: a medium badge at the button's top-end\n * corner (top 0, end 0) covered 82% of BurnTok's 18px heart in a small (36) bell. The badge is now the compact\n * `small` floating plate, kept on the button's end edge (it never sticks out past an `edge`-aligned inset) and\n * raised so only its `glyphOverlap` ring (the canvas-colored floating border) reaches into the glyph slot.\n * Wider counts grow toward the start along the top, not down over the glyph. See `resolveIconButtonBadgeOffset`.\n */\n badge: { size: \"small\", variant: \"floating\", glyphOverlap: stroke.strong, inlineEnd: 0 },\n states: {\n // 2026-10-28: the selected flower gained an unwanted surrounding plate. Selection keeps the tone's\n // background/border; only foreground or the product's filled glyph conveys the persistent state.\n selected: { content: semanticColors.selection.content },\n pressedOpacity: opacity.pressed,\n disabledOpacity: opacity.disabled,\n },\n} as const satisfies {\n slots: readonly string[];\n defaults: {\n tone: IconButtonTone;\n size: IconButtonSize;\n shape: IconButtonShape;\n };\n tones: Record<\n IconButtonTone,\n { background: ColorReference | null; content: ColorReference; border: ColorReference | null }\n >;\n sizes: Record<IconButtonSize, { diameter: number; hitSlop: number; glyph: GlyphSize }>;\n shapes: Record<IconButtonShape, keyof typeof radius>;\n edge: { tones: readonly IconButtonTone[] };\n elevation: { default: \"none\"; tones: readonly IconButtonTone[] };\n badge: { size: CounterBadgeSize; variant: CounterBadgeVariant; glyphOverlap: number; inlineEnd: number };\n states: {\n selected: { content: ColorReference };\n pressedOpacity: number;\n disabledOpacity: number;\n };\n};\n\nexport type ResolvedIconButtonPresentation = Readonly<{\n background: string | null;\n content: string;\n border: string | null;\n}>;\n\n/** Resolve one recipe tone for non-CSS renderers without a second tone table. */\nexport function resolveIconButtonPresentation(\n tone: IconButtonTone,\n palette: ColorReferencePalette,\n selected = false,\n): ResolvedIconButtonPresentation {\n const contract: {\n background: ColorReference | null;\n content: ColorReference;\n border: ColorReference | null;\n } = iconButtonRecipe.tones[tone];\n // Filled tones keep inverse content so selecting never loses contrast against their retained fill.\n const content = selected && tone !== \"primary\" && tone !== \"danger\"\n ? iconButtonRecipe.states.selected.content : contract.content;\n return {\n background:\n contract.background === null\n ? null\n : resolveColorReference(contract.background, palette),\n content: resolveColorReference(content, palette),\n border:\n contract.border === null\n ? null\n : resolveColorReference(contract.border, palette),\n };\n}\n\n/**\n * Negative margin a ghost IconButton applies on its `edge` side(s): (visible diameter − glyph slot) / 2, e.g. 10 for\n * medium (44 − 24). 0 for tones that draw a frame. `visibleDiameter` is the rendered size after the Provider's\n * minimumVisualTarget axis (`visibleControlHeight`), so the overhang tracks what is actually drawn.\n */\nexport function resolveIconButtonEdgeOverhang(\n tone: IconButtonTone,\n size: IconButtonSize,\n visibleDiameter: number = iconButtonRecipe.sizes[size].diameter,\n): number {\n if (!(iconButtonRecipe.edge.tones as readonly IconButtonTone[]).includes(tone)) return 0;\n return Math.max(0, (visibleDiameter - glyph[iconButtonRecipe.sizes[size].glyph]) / 2);\n}\n\n/**\n * Where an IconButton's count badge sits, measured from the button's top-end corner (logical: `inlineEnd` mirrors in\n * RTL). The badge's block-end lands `badge.glyphOverlap` inside the glyph slot's top edge: blockStart = slot inset +\n * overlap − badge height, e.g. −6 for small (36 − 20 slot, 16 badge). `visibleDiameter` is the rendered size after the\n * Provider's minimumVisualTarget axis, so the badge follows the glyph slot when the button grows (Web and Native).\n */\nexport function resolveIconButtonBadgeOffset(\n size: IconButtonSize,\n visibleDiameter: number = iconButtonRecipe.sizes[size].diameter,\n): Readonly<{ blockStart: number; inlineEnd: number }> {\n const { badge } = iconButtonRecipe;\n const slotInset = Math.max(0, (visibleDiameter - glyph[iconButtonRecipe.sizes[size].glyph]) / 2);\n return {\n blockStart: slotInset + badge.glyphOverlap - counterBadgeRecipe.sizes[badge.size].height,\n inlineEnd: badge.inlineEnd,\n };\n}\n\n/** Throws for an unknown step or an elevated ghost IconButton (iconButtonRecipe.elevation). */\nexport function validateIconButtonElevation(elevation: string, tone: IconButtonTone): void {\n validateElevationStep(elevation, \"IconButton\");\n if (elevation !== \"none\" && !(iconButtonRecipe.elevation.tones as readonly string[]).includes(tone)) {\n throw new TypeError(`IconButton elevation needs a filled tone, not ${tone}`);\n }\n}\n"]}
@@ -672,6 +672,14 @@ export declare const profileSummaryRecipe: Readonly<{
672
672
  readonly icon: "edit";
673
673
  readonly size: "small";
674
674
  }>;
675
+ /**
676
+ * 수치는 한 줄에 최대 네 칸이고 넘치면 다음 줄로 간다. 마지막 줄도 같은 칸 폭을 지켜 세로 기준선이 맞는다.
677
+ * 2026-10-28 다에리 둥지: 아래 목록 일곱 페이지를 프로필 수치로 옮기자 한 줄 일곱 칸은 라벨이 잘렸다(사용자 결정).
678
+ */
679
+ stats: Readonly<{
680
+ readonly maxPerRow: 4;
681
+ readonly rowGap: "md";
682
+ }>;
675
683
  avatarGlyphSize: 44;
676
684
  actionsLayouts: Readonly<{
677
685
  inline: Readonly<{
@@ -1 +1 @@
1
- {"version":3,"file":"screen-patterns.d.ts","sourceRoot":"","sources":["../src/screen-patterns.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"screen-patterns.d.ts","sourceRoot":"","sources":["../src/screen-patterns.ts"],"names":[],"mappings":"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"}
@@ -626,6 +626,11 @@ export const profileSummaryRecipe = Object.freeze({
626
626
  * nickname, so no separate "edit profile" button repeats either. Small ghost IconButton (36 + hitSlop 4 = 44 target).
627
627
  */
628
628
  nameEdit: Object.freeze({ icon: "edit", size: "small" }),
629
+ /**
630
+ * 수치는 한 줄에 최대 네 칸이고 넘치면 다음 줄로 간다. 마지막 줄도 같은 칸 폭을 지켜 세로 기준선이 맞는다.
631
+ * 2026-10-28 다에리 둥지: 아래 목록 일곱 페이지를 프로필 수치로 옮기자 한 줄 일곱 칸은 라벨이 잘렸다(사용자 결정).
632
+ */
633
+ stats: Object.freeze({ maxPerRow: 4, rowGap: "md" }),
629
634
  avatarGlyphSize: glyph.xxl,
630
635
  actionsLayouts: Object.freeze({
631
636
  inline: Object.freeze({ axis: "inline", gap: "xs" }),