@hjmds/design-contracts 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +208 -0
- package/dist/alert-dialog.d.ts +102 -0
- package/dist/alert-dialog.d.ts.map +1 -0
- package/dist/alert-dialog.js +136 -0
- package/dist/alert-dialog.js.map +1 -0
- package/dist/base-recipes.d.ts +184 -0
- package/dist/base-recipes.d.ts.map +1 -0
- package/dist/base-recipes.js +129 -0
- package/dist/base-recipes.js.map +1 -0
- package/dist/behaviors.d.ts +1254 -0
- package/dist/behaviors.d.ts.map +1 -0
- package/dist/behaviors.js +972 -0
- package/dist/behaviors.js.map +1 -0
- package/dist/bottom-navigation-defaults.d.ts +13 -0
- package/dist/bottom-navigation-defaults.d.ts.map +1 -0
- package/dist/bottom-navigation-defaults.js +10 -0
- package/dist/bottom-navigation-defaults.js.map +1 -0
- package/dist/bottom-navigation.d.ts +114 -0
- package/dist/bottom-navigation.d.ts.map +1 -0
- package/dist/bottom-navigation.js +223 -0
- package/dist/bottom-navigation.js.map +1 -0
- package/dist/breadcrumb.d.ts +97 -0
- package/dist/breadcrumb.d.ts.map +1 -0
- package/dist/breadcrumb.js +99 -0
- package/dist/breadcrumb.js.map +1 -0
- package/dist/calendar.d.ts +285 -0
- package/dist/calendar.d.ts.map +1 -0
- package/dist/calendar.js +297 -0
- package/dist/calendar.js.map +1 -0
- package/dist/card.d.ts +39 -0
- package/dist/card.d.ts.map +1 -0
- package/dist/card.js +50 -0
- package/dist/card.js.map +1 -0
- package/dist/carousel.d.ts +180 -0
- package/dist/carousel.d.ts.map +1 -0
- package/dist/carousel.js +172 -0
- package/dist/carousel.js.map +1 -0
- package/dist/catalog.d.ts +7158 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +220 -0
- package/dist/catalog.js.map +1 -0
- package/dist/collection.d.ts +123 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/collection.js +211 -0
- package/dist/collection.js.map +1 -0
- package/dist/color-references.d.ts +46 -0
- package/dist/color-references.d.ts.map +1 -0
- package/dist/color-references.js +39 -0
- package/dist/color-references.js.map +1 -0
- package/dist/colors.d.ts +56 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +90 -0
- package/dist/colors.js.map +1 -0
- package/dist/command-palette.d.ts +240 -0
- package/dist/command-palette.d.ts.map +1 -0
- package/dist/command-palette.js +97 -0
- package/dist/command-palette.js.map +1 -0
- package/dist/component-contracts.d.ts +137 -0
- package/dist/component-contracts.d.ts.map +1 -0
- package/dist/component-contracts.js +53 -0
- package/dist/component-contracts.js.map +1 -0
- package/dist/component-definitions.d.ts +135 -0
- package/dist/component-definitions.d.ts.map +1 -0
- package/dist/component-definitions.js +142 -0
- package/dist/component-definitions.js.map +1 -0
- package/dist/component-recipes.d.ts +3583 -0
- package/dist/component-recipes.d.ts.map +1 -0
- package/dist/component-recipes.js +1503 -0
- package/dist/component-recipes.js.map +1 -0
- package/dist/component-references.d.ts +416 -0
- package/dist/component-references.d.ts.map +1 -0
- package/dist/component-references.js +140 -0
- package/dist/component-references.js.map +1 -0
- package/dist/content-state.d.ts +104 -0
- package/dist/content-state.d.ts.map +1 -0
- package/dist/content-state.js +116 -0
- package/dist/content-state.js.map +1 -0
- package/dist/counter-badge-recipe.d.ts +80 -0
- package/dist/counter-badge-recipe.d.ts.map +1 -0
- package/dist/counter-badge-recipe.js +44 -0
- package/dist/counter-badge-recipe.js.map +1 -0
- package/dist/counter-badge.d.ts +12 -0
- package/dist/counter-badge.d.ts.map +1 -0
- package/dist/counter-badge.js +21 -0
- package/dist/counter-badge.js.map +1 -0
- package/dist/data-table.d.ts +203 -0
- package/dist/data-table.d.ts.map +1 -0
- package/dist/data-table.js +182 -0
- package/dist/data-table.js.map +1 -0
- package/dist/date-picker.d.ts +268 -0
- package/dist/date-picker.d.ts.map +1 -0
- package/dist/date-picker.js +168 -0
- package/dist/date-picker.js.map +1 -0
- package/dist/description-list.d.ts +68 -0
- package/dist/description-list.d.ts.map +1 -0
- package/dist/description-list.js +85 -0
- package/dist/description-list.js.map +1 -0
- package/dist/design-system-provider.d.ts +80 -0
- package/dist/design-system-provider.d.ts.map +1 -0
- package/dist/design-system-provider.js +147 -0
- package/dist/design-system-provider.js.map +1 -0
- package/dist/evidence.d.ts +49 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +133 -0
- package/dist/evidence.js.map +1 -0
- package/dist/file-picker.d.ts +183 -0
- package/dist/file-picker.d.ts.map +1 -0
- package/dist/file-picker.js +224 -0
- package/dist/file-picker.js.map +1 -0
- package/dist/floating-action-button.d.ts +143 -0
- package/dist/floating-action-button.d.ts.map +1 -0
- package/dist/floating-action-button.js +149 -0
- package/dist/floating-action-button.js.map +1 -0
- package/dist/form.d.ts +143 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.js +206 -0
- package/dist/form.js.map +1 -0
- package/dist/foundations.d.ts +300 -0
- package/dist/foundations.d.ts.map +1 -0
- package/dist/foundations.js +238 -0
- package/dist/foundations.js.map +1 -0
- package/dist/grid.d.ts +75 -0
- package/dist/grid.d.ts.map +1 -0
- package/dist/grid.js +133 -0
- package/dist/grid.js.map +1 -0
- package/dist/icon-button-recipe.d.ts +99 -0
- package/dist/icon-button-recipe.d.ts.map +1 -0
- package/dist/icon-button-recipe.js +53 -0
- package/dist/icon-button-recipe.js.map +1 -0
- package/dist/icon.d.ts +41 -0
- package/dist/icon.d.ts.map +1 -0
- package/dist/icon.js +147 -0
- package/dist/icon.js.map +1 -0
- package/dist/image.d.ts +82 -0
- package/dist/image.d.ts.map +1 -0
- package/dist/image.js +100 -0
- package/dist/image.js.map +1 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -0
- package/dist/index.js.map +1 -0
- package/dist/layout.d.ts +118 -0
- package/dist/layout.d.ts.map +1 -0
- package/dist/layout.js +118 -0
- package/dist/layout.js.map +1 -0
- package/dist/link.d.ts +57 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +142 -0
- package/dist/link.js.map +1 -0
- package/dist/load-more.d.ts +64 -0
- package/dist/load-more.d.ts.map +1 -0
- package/dist/load-more.js +124 -0
- package/dist/load-more.js.map +1 -0
- package/dist/mentions.d.ts +67 -0
- package/dist/mentions.d.ts.map +1 -0
- package/dist/mentions.js +107 -0
- package/dist/mentions.js.map +1 -0
- package/dist/number-field.d.ts +208 -0
- package/dist/number-field.d.ts.map +1 -0
- package/dist/number-field.js +247 -0
- package/dist/number-field.js.map +1 -0
- package/dist/otp-field.d.ts +152 -0
- package/dist/otp-field.d.ts.map +1 -0
- package/dist/otp-field.js +117 -0
- package/dist/otp-field.js.map +1 -0
- package/dist/pagination.d.ts +181 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +226 -0
- package/dist/pagination.js.map +1 -0
- package/dist/password-field.d.ts +187 -0
- package/dist/password-field.d.ts.map +1 -0
- package/dist/password-field.js +120 -0
- package/dist/password-field.js.map +1 -0
- package/dist/popover.d.ts +152 -0
- package/dist/popover.d.ts.map +1 -0
- package/dist/popover.js +137 -0
- package/dist/popover.js.map +1 -0
- package/dist/progress-recipe.d.ts +43 -0
- package/dist/progress-recipe.d.ts.map +1 -0
- package/dist/progress-recipe.js +16 -0
- package/dist/progress-recipe.js.map +1 -0
- package/dist/recipes.d.ts +31 -0
- package/dist/recipes.d.ts.map +1 -0
- package/dist/recipes.js +46 -0
- package/dist/recipes.js.map +1 -0
- package/dist/responsive.d.ts +27 -0
- package/dist/responsive.d.ts.map +1 -0
- package/dist/responsive.js +66 -0
- package/dist/responsive.js.map +1 -0
- package/dist/result.d.ts +111 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js +97 -0
- package/dist/result.js.map +1 -0
- package/dist/selection-helpers.d.ts +16 -0
- package/dist/selection-helpers.d.ts.map +1 -0
- package/dist/selection-helpers.js +52 -0
- package/dist/selection-helpers.js.map +1 -0
- package/dist/semantic-colors.d.ts +275 -0
- package/dist/semantic-colors.d.ts.map +1 -0
- package/dist/semantic-colors.js +84 -0
- package/dist/semantic-colors.js.map +1 -0
- package/dist/sheet.d.ts +51 -0
- package/dist/sheet.d.ts.map +1 -0
- package/dist/sheet.js +69 -0
- package/dist/sheet.js.map +1 -0
- package/dist/showcase.d.ts +153 -0
- package/dist/showcase.d.ts.map +1 -0
- package/dist/showcase.js +210 -0
- package/dist/showcase.js.map +1 -0
- package/dist/side-panel.d.ts +199 -0
- package/dist/side-panel.d.ts.map +1 -0
- package/dist/side-panel.js +111 -0
- package/dist/side-panel.js.map +1 -0
- package/dist/slider.d.ts +138 -0
- package/dist/slider.d.ts.map +1 -0
- package/dist/slider.js +150 -0
- package/dist/slider.js.map +1 -0
- package/dist/splitter.d.ts +113 -0
- package/dist/splitter.d.ts.map +1 -0
- package/dist/splitter.js +99 -0
- package/dist/splitter.js.map +1 -0
- package/dist/statistic.d.ts +41 -0
- package/dist/statistic.d.ts.map +1 -0
- package/dist/statistic.js +76 -0
- package/dist/statistic.js.map +1 -0
- package/dist/steps.d.ts +196 -0
- package/dist/steps.d.ts.map +1 -0
- package/dist/steps.js +160 -0
- package/dist/steps.js.map +1 -0
- package/dist/tag.d.ts +128 -0
- package/dist/tag.d.ts.map +1 -0
- package/dist/tag.js +93 -0
- package/dist/tag.js.map +1 -0
- package/dist/timeline.d.ts +147 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +127 -0
- package/dist/timeline.js.map +1 -0
- package/dist/toast.d.ts +164 -0
- package/dist/toast.d.ts.map +1 -0
- package/dist/toast.js +529 -0
- package/dist/toast.js.map +1 -0
- package/dist/tokens.d.ts +9 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +9 -0
- package/dist/tokens.js.map +1 -0
- package/dist/tooltip.d.ts +44 -0
- package/dist/tooltip.d.ts.map +1 -0
- package/dist/tooltip.js +88 -0
- package/dist/tooltip.js.map +1 -0
- package/dist/tour.d.ts +218 -0
- package/dist/tour.d.ts.map +1 -0
- package/dist/tour.js +211 -0
- package/dist/tour.js.map +1 -0
- package/dist/transfer-list.d.ts +207 -0
- package/dist/transfer-list.d.ts.map +1 -0
- package/dist/transfer-list.js +193 -0
- package/dist/transfer-list.js.map +1 -0
- package/dist/tree-select.d.ts +78 -0
- package/dist/tree-select.d.ts.map +1 -0
- package/dist/tree-select.js +132 -0
- package/dist/tree-select.js.map +1 -0
- package/dist/tree.d.ts +206 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +223 -0
- package/dist/tree.js.map +1 -0
- package/dist/upload-item.d.ts +173 -0
- package/dist/upload-item.d.ts.map +1 -0
- package/dist/upload-item.js +156 -0
- package/dist/upload-item.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +3 -0
- package/dist/version.js.map +1 -0
- package/docs/affix.md +63 -0
- package/docs/anchor.md +59 -0
- package/docs/ant-design-coverage.md +119 -0
- package/docs/app-provider.md +50 -0
- package/docs/app-rn-adoption.md +227 -0
- package/docs/architecture.md +320 -0
- package/docs/authoring-brief.md +87 -0
- package/docs/border-beam.md +66 -0
- package/docs/bottom-navigation.md +127 -0
- package/docs/breadcrumb.md +82 -0
- package/docs/calendar.md +154 -0
- package/docs/carousel.md +130 -0
- package/docs/cascader.md +93 -0
- package/docs/catalog-decision-status.md +306 -0
- package/docs/color-picker.md +72 -0
- package/docs/command-palette.md +116 -0
- package/docs/confirm-popover.md +93 -0
- package/docs/consistency-audit.md +383 -0
- package/docs/consumer-release-gate.md +90 -0
- package/docs/content-state.md +156 -0
- package/docs/context-panel.md +88 -0
- package/docs/cross-platform-core-normalization.md +118 -0
- package/docs/data-table.md +79 -0
- package/docs/date-picker.md +84 -0
- package/docs/description-list.md +75 -0
- package/docs/design-system-provider.md +139 -0
- package/docs/dropdown.md +78 -0
- package/docs/expansion-roadmap.md +285 -0
- package/docs/file-picker.md +59 -0
- package/docs/floating-action-button.md +111 -0
- package/docs/form.md +134 -0
- package/docs/generated/component-maturity.md +103 -0
- package/docs/generated/renderer-evidence.json +5597 -0
- package/docs/generated/renderer-evidence.md +132 -0
- package/docs/generated/showcase-manifest.json +3732 -0
- package/docs/icon.md +22 -0
- package/docs/identity.md +121 -0
- package/docs/image.md +84 -0
- package/docs/implementation-0.5.md +85 -0
- package/docs/layout-primitives.md +107 -0
- package/docs/layout.md +83 -0
- package/docs/library-reference-decisions.md +123 -0
- package/docs/link.md +67 -0
- package/docs/load-more.md +31 -0
- package/docs/mentions.md +82 -0
- package/docs/migration-0.2.md +108 -0
- package/docs/migration-0.3.md +72 -0
- package/docs/migration-0.5.md +82 -0
- package/docs/migration-0.6.md +197 -0
- package/docs/notification.md +54 -0
- package/docs/number-field.md +82 -0
- package/docs/otp-field.md +103 -0
- package/docs/pagination.md +139 -0
- package/docs/password-field.md +98 -0
- package/docs/popover.md +124 -0
- package/docs/promotion-candidates.md +169 -0
- package/docs/qr-code.md +69 -0
- package/docs/rating.md +58 -0
- package/docs/responsive-grid.md +90 -0
- package/docs/result.md +96 -0
- package/docs/showcase.md +97 -0
- package/docs/side-panel.md +71 -0
- package/docs/slider.md +79 -0
- package/docs/splitter.md +55 -0
- package/docs/statistic.md +16 -0
- package/docs/steps.md +115 -0
- package/docs/tag.md +57 -0
- package/docs/time-picker.md +88 -0
- package/docs/timeline.md +146 -0
- package/docs/toast.md +127 -0
- package/docs/tooltip.md +58 -0
- package/docs/tour.md +136 -0
- package/docs/transfer-list.md +94 -0
- package/docs/tree-select.md +101 -0
- package/docs/tree.md +123 -0
- package/docs/upload-item.md +68 -0
- package/docs/utility.md +53 -0
- package/docs/virtual-list.md +70 -0
- package/docs/watermark.md +58 -0
- package/package.json +402 -0
package/dist/calendar.js
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { control, fontWeight, glyph, opacity, spacing, stroke } from "./foundations.js";
|
|
2
|
+
import { focusIndicatorContract } from "./component-contracts.js";
|
|
3
|
+
import { semanticColors } from "./semantic-colors.js";
|
|
4
|
+
const ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
5
|
+
const ISO_MONTH_PATTERN = /^\d{4}-(0[1-9]|1[0-2])$/;
|
|
6
|
+
const GRID_COLUMNS = 7;
|
|
7
|
+
function assertNonEmpty(value, field) {
|
|
8
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
9
|
+
throw new TypeError(`Calendar ${field} must not be empty`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The grid never parses or computes dates — month/leap-year/timezone
|
|
14
|
+
* arithmetic stays product-owned (see docs/calendar.md). This only checks the
|
|
15
|
+
* "YYYY-MM-DD" shape products already use as their KBO schedule date key.
|
|
16
|
+
*/
|
|
17
|
+
export function isIsoCalendarDate(value) {
|
|
18
|
+
return typeof value === "string" && ISO_DATE_PATTERN.test(value);
|
|
19
|
+
}
|
|
20
|
+
export function assertIsoCalendarDate(value, field) {
|
|
21
|
+
if (!isIsoCalendarDate(value)) {
|
|
22
|
+
throw new TypeError(`Calendar ${field} must be an ISO "YYYY-MM-DD" date string`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function isIsoCalendarMonth(value) {
|
|
26
|
+
return typeof value === "string" && ISO_MONTH_PATTERN.test(value);
|
|
27
|
+
}
|
|
28
|
+
export function assertIsoCalendarMonth(value, field) {
|
|
29
|
+
if (!isIsoCalendarMonth(value)) {
|
|
30
|
+
throw new TypeError(`Calendar ${field} must be an ISO "YYYY-MM" month string`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function validateCalendarGridDescriptor(grid) {
|
|
34
|
+
if (grid.cells.length === 0 || grid.cells.length % GRID_COLUMNS !== 0) {
|
|
35
|
+
throw new RangeError("Calendar grid cells must be a non-empty multiple of seven");
|
|
36
|
+
}
|
|
37
|
+
if (grid.weekdayLabels.length !== GRID_COLUMNS) {
|
|
38
|
+
throw new RangeError("Calendar weekdayLabels must have exactly seven entries");
|
|
39
|
+
}
|
|
40
|
+
grid.weekdayLabels.forEach((label, index) => assertNonEmpty(label, `weekdayLabels[${index}]`));
|
|
41
|
+
assertIsoCalendarDate(grid.todayDate, "todayDate");
|
|
42
|
+
const seen = new Set();
|
|
43
|
+
for (const cell of grid.cells) {
|
|
44
|
+
if (cell.date === undefined)
|
|
45
|
+
continue;
|
|
46
|
+
assertIsoCalendarDate(cell.date, "cell date");
|
|
47
|
+
if (seen.has(cell.date)) {
|
|
48
|
+
throw new TypeError(`Duplicate Calendar cell date: ${cell.date}`);
|
|
49
|
+
}
|
|
50
|
+
seen.add(cell.date);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function validateCalendarMonthNavigation(navigation) {
|
|
54
|
+
const month = navigation.focusedMonth ?? navigation.defaultFocusedMonth;
|
|
55
|
+
if (month !== undefined)
|
|
56
|
+
assertIsoCalendarMonth(month, "focusedMonth");
|
|
57
|
+
}
|
|
58
|
+
export function validateCalendarSelection(selection) {
|
|
59
|
+
const selected = selection.selectedDate ?? selection.defaultSelectedDate;
|
|
60
|
+
if (selected != null)
|
|
61
|
+
assertIsoCalendarDate(selected, "selectedDate");
|
|
62
|
+
}
|
|
63
|
+
export function validateCalendarDescriptor(descriptor) {
|
|
64
|
+
validateCalendarGridDescriptor(descriptor.grid);
|
|
65
|
+
assertNonEmpty(descriptor.monthLabel, "monthLabel");
|
|
66
|
+
validateCalendarMonthNavigation(descriptor);
|
|
67
|
+
validateCalendarSelection(descriptor);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Resolves per-cell semantic state against a selection supplied separately
|
|
71
|
+
* from the raw grid (mirroring `resolveSelectSelectedItem`'s separation of
|
|
72
|
+
* source data from selection state) — the same grid page renders identically
|
|
73
|
+
* whether it is hosted by Calendar or by DatePicker's popover/sheet.
|
|
74
|
+
*/
|
|
75
|
+
export function resolveCalendarGridDescriptor(grid, selectedDate, options) {
|
|
76
|
+
validateCalendarGridDescriptor(grid);
|
|
77
|
+
if (typeof options.composeAccessibleName !== "function") {
|
|
78
|
+
throw new TypeError("Calendar composeAccessibleName must be a function");
|
|
79
|
+
}
|
|
80
|
+
return grid.cells.map((cell, index) => {
|
|
81
|
+
const row = Math.floor(index / GRID_COLUMNS) + 1;
|
|
82
|
+
const column = (index % GRID_COLUMNS) + 1;
|
|
83
|
+
if (cell.date === undefined) {
|
|
84
|
+
return { row, column, filler: true };
|
|
85
|
+
}
|
|
86
|
+
const isToday = cell.date === grid.todayDate;
|
|
87
|
+
const isSelected = cell.date === selectedDate;
|
|
88
|
+
const disabled = cell.disabled ?? false;
|
|
89
|
+
const nameInfo = cell.content === undefined
|
|
90
|
+
? { date: cell.date, isToday, isSelected, disabled }
|
|
91
|
+
: { date: cell.date, isToday, isSelected, disabled, content: cell.content };
|
|
92
|
+
const accessibleName = options.composeAccessibleName(nameInfo);
|
|
93
|
+
if (typeof accessibleName !== "string" || accessibleName.trim().length === 0) {
|
|
94
|
+
throw new TypeError("Calendar composeAccessibleName must return a non-empty string");
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
...cell,
|
|
98
|
+
date: cell.date,
|
|
99
|
+
row,
|
|
100
|
+
column,
|
|
101
|
+
isToday,
|
|
102
|
+
isSelected,
|
|
103
|
+
selectable: !disabled,
|
|
104
|
+
accessibleName,
|
|
105
|
+
};
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
/** Top-level entry point: validates the descriptor and resolves its grid page. */
|
|
109
|
+
export function resolveCalendarDescriptor(descriptor, options) {
|
|
110
|
+
validateCalendarDescriptor(descriptor);
|
|
111
|
+
const selectedDate = descriptor.selectedDate ?? descriptor.defaultSelectedDate ?? null;
|
|
112
|
+
return resolveCalendarGridDescriptor(descriptor.grid, selectedDate, options);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* ArrowLeft/Right flip under RTL, matching `getSelectionNavigationIntent`'s
|
|
116
|
+
* `direction` parameter.
|
|
117
|
+
*/
|
|
118
|
+
export function getCalendarNavigationIntent(key, direction = "ltr") {
|
|
119
|
+
if (key === "Home")
|
|
120
|
+
return "first-of-week";
|
|
121
|
+
if (key === "End")
|
|
122
|
+
return "last-of-week";
|
|
123
|
+
if (key === "ArrowDown")
|
|
124
|
+
return "next-week";
|
|
125
|
+
if (key === "ArrowUp")
|
|
126
|
+
return "previous-week";
|
|
127
|
+
if (key === "ArrowRight")
|
|
128
|
+
return direction === "rtl" ? "previous-day" : "next-day";
|
|
129
|
+
if (key === "ArrowLeft")
|
|
130
|
+
return direction === "rtl" ? "next-day" : "previous-day";
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Pure index arithmetic over the fixed seven-column page. Unlike
|
|
135
|
+
* `getCollectionNavigationTarget`, this does NOT skip disabled dates —
|
|
136
|
+
* per the WAI-ARIA date picker dialog pattern, arrow-key focus must land
|
|
137
|
+
* predictably (down always moves exactly one row) even on a disabled date;
|
|
138
|
+
* only the *activate* action is expected to no-op there. Moving past the
|
|
139
|
+
* edge of this page returns an `overflow` signal instead of wrapping, since
|
|
140
|
+
* HJM does not know the adjacent month's shape — the product pages the
|
|
141
|
+
* month and refocuses the corresponding day.
|
|
142
|
+
*/
|
|
143
|
+
export function getCalendarNavigationTarget(grid, currentDate, intent) {
|
|
144
|
+
validateCalendarGridDescriptor(grid);
|
|
145
|
+
const currentIndex = grid.cells.findIndex((cell) => cell.date === currentDate);
|
|
146
|
+
if (currentIndex < 0) {
|
|
147
|
+
throw new RangeError(`Calendar currentDate is not part of this grid page: ${currentDate}`);
|
|
148
|
+
}
|
|
149
|
+
const findDated = (from, step) => {
|
|
150
|
+
for (let index = from; index >= 0 && index < grid.cells.length; index += step) {
|
|
151
|
+
if (grid.cells[index]?.date !== undefined)
|
|
152
|
+
return index;
|
|
153
|
+
}
|
|
154
|
+
return undefined;
|
|
155
|
+
};
|
|
156
|
+
const rowStart = Math.floor(currentIndex / GRID_COLUMNS) * GRID_COLUMNS;
|
|
157
|
+
const rowEnd = rowStart + GRID_COLUMNS - 1;
|
|
158
|
+
if (intent === "first-of-week") {
|
|
159
|
+
const found = findDated(rowStart, 1);
|
|
160
|
+
return found !== undefined && found <= rowEnd
|
|
161
|
+
? { date: grid.cells[found].date }
|
|
162
|
+
: { overflow: "before" };
|
|
163
|
+
}
|
|
164
|
+
if (intent === "last-of-week") {
|
|
165
|
+
const found = findDated(rowEnd, -1);
|
|
166
|
+
return found !== undefined && found >= rowStart
|
|
167
|
+
? { date: grid.cells[found].date }
|
|
168
|
+
: { overflow: "after" };
|
|
169
|
+
}
|
|
170
|
+
const forward = intent === "next-day" || intent === "next-week";
|
|
171
|
+
const stride = intent === "next-week" || intent === "previous-week" ? GRID_COLUMNS : 1;
|
|
172
|
+
const step = forward ? 1 : -1;
|
|
173
|
+
const target = currentIndex + step * stride;
|
|
174
|
+
if (target < 0)
|
|
175
|
+
return { overflow: "before" };
|
|
176
|
+
if (target >= grid.cells.length)
|
|
177
|
+
return { overflow: "after" };
|
|
178
|
+
if (grid.cells[target]?.date !== undefined)
|
|
179
|
+
return { date: grid.cells[target].date };
|
|
180
|
+
// Landed on a filler (only reachable for a week-step into a partially
|
|
181
|
+
// filled edge row): keep scanning the same direction for the nearest real
|
|
182
|
+
// date rather than asking a renderer to interpret a blank cell.
|
|
183
|
+
const resolved = findDated(target, step);
|
|
184
|
+
return resolved !== undefined
|
|
185
|
+
? { date: grid.cells[resolved].date }
|
|
186
|
+
: { overflow: forward ? "after" : "before" };
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* `today` and `selected` are visually independent (a non-selected today and
|
|
190
|
+
* a selected past day must both read clearly) and neither is color-only:
|
|
191
|
+
* today gets a persistent border, selected gets a filled background, and
|
|
192
|
+
* both remain in `accessibleName`/`isToday`/`isSelected` for assistive tech.
|
|
193
|
+
*/
|
|
194
|
+
export const calendarRecipe = {
|
|
195
|
+
slots: [
|
|
196
|
+
"root",
|
|
197
|
+
"header",
|
|
198
|
+
"monthLabel",
|
|
199
|
+
"previousMonth",
|
|
200
|
+
"nextMonth",
|
|
201
|
+
"weekdayRow",
|
|
202
|
+
"weekdayLabel",
|
|
203
|
+
"grid",
|
|
204
|
+
"week",
|
|
205
|
+
"day",
|
|
206
|
+
"dayLabel",
|
|
207
|
+
"content",
|
|
208
|
+
],
|
|
209
|
+
defaults: { size: "medium" },
|
|
210
|
+
header: {
|
|
211
|
+
gap: spacing.xs,
|
|
212
|
+
monthLabel: {
|
|
213
|
+
textVariant: "title",
|
|
214
|
+
fontWeight: fontWeight.bold,
|
|
215
|
+
color: semanticColors.content.primary,
|
|
216
|
+
},
|
|
217
|
+
navButton: { diameter: control.buttonHeight.medium, color: semanticColors.content.secondary },
|
|
218
|
+
navIcon: { previous: "chevronStart", next: "chevronEnd" },
|
|
219
|
+
},
|
|
220
|
+
weekdayLabel: {
|
|
221
|
+
textVariant: "label",
|
|
222
|
+
color: semanticColors.content.secondary,
|
|
223
|
+
},
|
|
224
|
+
sizes: {
|
|
225
|
+
medium: { cellDiameter: control.minTouchTarget, textVariant: "body", glyph: "sm" },
|
|
226
|
+
large: { cellDiameter: glyph.xxl, textVariant: "bodyLarge", glyph: "md" },
|
|
227
|
+
},
|
|
228
|
+
day: {
|
|
229
|
+
radius: "full",
|
|
230
|
+
label: { color: semanticColors.content.body, numericVariant: "tabular" },
|
|
231
|
+
outsideFocusedMonthOpacity: opacity.muted,
|
|
232
|
+
disabledOpacity: opacity.disabled,
|
|
233
|
+
today: { border: semanticColors.border.focus, borderWidth: stroke.default },
|
|
234
|
+
selected: {
|
|
235
|
+
background: semanticColors.action.brand.background,
|
|
236
|
+
content: semanticColors.action.brand.content,
|
|
237
|
+
},
|
|
238
|
+
focus: focusIndicatorContract,
|
|
239
|
+
},
|
|
240
|
+
};
|
|
241
|
+
/**
|
|
242
|
+
* Calendar is `shared`, not `adaptive`: the grid is always visible inline
|
|
243
|
+
* (no popup/Sheet choice to make). Web gets `grid` role + roving-tabindex
|
|
244
|
+
* arrow keys; Native has no composite-widget equivalent, so each date is
|
|
245
|
+
* simply an independently focusable/tappable element and month paging goes
|
|
246
|
+
* through the always-present previous/next buttons on both platforms — same
|
|
247
|
+
* result (the user reaches and picks a date), different path, matching the
|
|
248
|
+
* `beta → stable(adaptive)` gate's standard even though this component
|
|
249
|
+
* itself is not adaptive.
|
|
250
|
+
*/
|
|
251
|
+
export const calendarBehavior = {
|
|
252
|
+
controlled: [
|
|
253
|
+
"selectedDate",
|
|
254
|
+
"defaultSelectedDate",
|
|
255
|
+
"onSelectionChange",
|
|
256
|
+
"focusedMonth",
|
|
257
|
+
"defaultFocusedMonth",
|
|
258
|
+
"onFocusedMonthChange",
|
|
259
|
+
],
|
|
260
|
+
inputs: ["grid", "monthLabel"],
|
|
261
|
+
stateAxes: {
|
|
262
|
+
availability: ["enabled", "disabled"],
|
|
263
|
+
value: ["selected"],
|
|
264
|
+
},
|
|
265
|
+
web: {
|
|
266
|
+
roles: ["grid", "row", "gridcell", "button"],
|
|
267
|
+
keyboard: [
|
|
268
|
+
"Tab",
|
|
269
|
+
"Enter",
|
|
270
|
+
"Space",
|
|
271
|
+
"ArrowUp",
|
|
272
|
+
"ArrowDown",
|
|
273
|
+
"ArrowLeft",
|
|
274
|
+
"ArrowRight",
|
|
275
|
+
"Home",
|
|
276
|
+
"End",
|
|
277
|
+
],
|
|
278
|
+
focus: "roving",
|
|
279
|
+
},
|
|
280
|
+
native: {
|
|
281
|
+
roles: ["button"],
|
|
282
|
+
states: ["disabled", "selected"],
|
|
283
|
+
actions: ["activate"],
|
|
284
|
+
},
|
|
285
|
+
scenarios: [
|
|
286
|
+
"today-and-selected-are-independent-and-both-non-color-marked",
|
|
287
|
+
"disabled-dates-remain-focusable-but-never-activate",
|
|
288
|
+
"arrow-keys-move-by-day-and-week-inside-the-visible-month-page",
|
|
289
|
+
"home-and-end-move-to-the-first-and-last-dated-cell-of-the-focused-row",
|
|
290
|
+
"moving-past-the-visible-grid-edge-requests-a-month-change-instead-of-wrapping",
|
|
291
|
+
"filler-cells-carry-no-accessible-name-and-are-hidden-from-assistive-tech",
|
|
292
|
+
"every-dated-cell-accessible-name-is-composed-by-the-product",
|
|
293
|
+
"changing-the-focused-month-never-changes-or-clears-the-selection",
|
|
294
|
+
"range-selection-is-not-part-of-the-contract",
|
|
295
|
+
],
|
|
296
|
+
};
|
|
297
|
+
//# sourceMappingURL=calendar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar.js","sourceRoot":"","sources":["../src/calendar.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ColorReference } from \"./color-references.js\";\nimport type { BehaviorContract, WebKeyboardKey } from \"./behaviors.js\";\nimport type { DesignSystemDirection } from \"./design-system-provider.js\";\nimport type { SemanticIconName } from \"./icon.js\";\nimport { control, fontWeight, glyph, opacity, spacing, stroke, type FontWeightValue, type GlyphSize, type TextVariant } from \"./foundations.js\";\nimport { focusIndicatorContract } from \"./component-contracts.js\";\nimport { semanticColors } from \"./semantic-colors.js\";\n\nconst ISO_DATE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst ISO_MONTH_PATTERN = /^\\d{4}-(0[1-9]|1[0-2])$/;\nconst GRID_COLUMNS = 7;\n\nfunction assertNonEmpty(value: string, field: string): void {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new TypeError(`Calendar ${field} must not be empty`);\n }\n}\n\n/**\n * The grid never parses or computes dates — month/leap-year/timezone\n * arithmetic stays product-owned (see docs/calendar.md). This only checks the\n * \"YYYY-MM-DD\" shape products already use as their KBO schedule date key.\n */\nexport function isIsoCalendarDate(value: string): boolean {\n return typeof value === \"string\" && ISO_DATE_PATTERN.test(value);\n}\n\nexport function assertIsoCalendarDate(value: string, field: string): void {\n if (!isIsoCalendarDate(value)) {\n throw new TypeError(`Calendar ${field} must be an ISO \"YYYY-MM-DD\" date string`);\n }\n}\n\nexport function isIsoCalendarMonth(value: string): boolean {\n return typeof value === \"string\" && ISO_MONTH_PATTERN.test(value);\n}\n\nexport function assertIsoCalendarMonth(value: string, field: string): void {\n if (!isIsoCalendarMonth(value)) {\n throw new TypeError(`Calendar ${field} must be an ISO \"YYYY-MM\" month string`);\n }\n}\n\n/**\n * One visible cell. A cell with no `date` is a pure filler that keeps the\n * seven-column alignment (a leading/trailing blank before day 1 or after the\n * month's last day) — it is never focusable, selectable, or announced.\n * `content` is an opaque product payload (Yajalal's per-day game count, a\n * dot, anything) the renderer's cell-content slot receives untouched; the\n * grid never inspects it.\n */\nexport type CalendarDateCellDescriptor<Content = unknown> = Readonly<{\n date?: string;\n /** The date exists but falls outside the month currently in focus (a leading/trailing day from an adjacent month). Still selectable unless `disabled`. */\n outsideFocusedMonth?: boolean;\n disabled?: boolean;\n content?: Content;\n}>;\n\nexport type CalendarWeekdayLabels = readonly [\n string,\n string,\n string,\n string,\n string,\n string,\n string,\n];\n\n/**\n * Raw product data for one visible month page. HJM does not compute which\n * dates belong to a month or the leading/trailing blanks — the product\n * already owns that arithmetic (see `buildCalendarCells` in Yajalal's\n * schedule explorer). HJM only validates the row-major seven-column shape\n * and resolves per-cell semantic state on top of it.\n */\nexport type CalendarGridDescriptor<Content = unknown> = Readonly<{\n /** Row-major, seven columns per row (one per weekday), so length must be a positive multiple of seven. */\n cells: readonly CalendarDateCellDescriptor<Content>[];\n /** Localized short weekday labels in the same column order as `cells`, e.g. [\"일\",\"월\",\"화\",\"수\",\"목\",\"금\",\"토\"]. */\n weekdayLabels: CalendarWeekdayLabels;\n /** ISO date of \"today\" per the product's clock. The grid never calls `Date.now()` itself. */\n todayDate: string;\n}>;\n\nexport function validateCalendarGridDescriptor<Content>(\n grid: CalendarGridDescriptor<Content>,\n): void {\n if (grid.cells.length === 0 || grid.cells.length % GRID_COLUMNS !== 0) {\n throw new RangeError(\"Calendar grid cells must be a non-empty multiple of seven\");\n }\n if (grid.weekdayLabels.length !== GRID_COLUMNS) {\n throw new RangeError(\"Calendar weekdayLabels must have exactly seven entries\");\n }\n grid.weekdayLabels.forEach((label, index) => assertNonEmpty(label, `weekdayLabels[${index}]`));\n assertIsoCalendarDate(grid.todayDate, \"todayDate\");\n const seen = new Set<string>();\n for (const cell of grid.cells) {\n if (cell.date === undefined) continue;\n assertIsoCalendarDate(cell.date, \"cell date\");\n if (seen.has(cell.date)) {\n throw new TypeError(`Duplicate Calendar cell date: ${cell.date}`);\n }\n seen.add(cell.date);\n }\n}\n\n/**\n * A cursor's committed value and the one displayed month page are\n * independent controlled axes, mirroring `SelectSelection`/`SelectOpenState`\n * in spirit: paging the visible month never clears or moves the selection.\n */\nexport type CalendarMonthChangeReason = \"previous\" | \"next\" | \"jump\";\n\nexport type CalendarMonthNavigation =\n | Readonly<{\n focusedMonth: string;\n defaultFocusedMonth?: never;\n onFocusedMonthChange(month: string, reason: CalendarMonthChangeReason): void;\n }>\n | Readonly<{\n focusedMonth?: never;\n defaultFocusedMonth?: string;\n onFocusedMonthChange?: (month: string, reason: CalendarMonthChangeReason) => void;\n }>;\n\nexport function validateCalendarMonthNavigation(navigation: CalendarMonthNavigation): void {\n const month = navigation.focusedMonth ?? navigation.defaultFocusedMonth;\n if (month !== undefined) assertIsoCalendarMonth(month, \"focusedMonth\");\n}\n\n/**\n * Single committed date only. Range selection is deliberately excluded — no\n * Yajalal or BurnTok flow has measured demand for it (see docs/calendar.md).\n */\nexport type CalendarSelection =\n | Readonly<{\n selectedDate: string | null;\n defaultSelectedDate?: never;\n onSelectionChange(date: string | null): void;\n }>\n | Readonly<{\n selectedDate?: never;\n defaultSelectedDate?: string | null;\n onSelectionChange?: (date: string | null) => void;\n }>;\n\nexport function validateCalendarSelection(selection: CalendarSelection): void {\n const selected = selection.selectedDate ?? selection.defaultSelectedDate;\n if (selected != null) assertIsoCalendarDate(selected, \"selectedDate\");\n}\n\nexport type CalendarDescriptor<Content = unknown> = Readonly<{\n grid: CalendarGridDescriptor<Content>;\n /** Product-formatted heading copy (\"2026년 8월\"); the grid never formats a date itself. */\n monthLabel: string;\n}> &\n CalendarMonthNavigation &\n CalendarSelection;\n\nexport function validateCalendarDescriptor<Content>(\n descriptor: CalendarDescriptor<Content>,\n): void {\n validateCalendarGridDescriptor(descriptor.grid);\n assertNonEmpty(descriptor.monthLabel, \"monthLabel\");\n validateCalendarMonthNavigation(descriptor);\n validateCalendarSelection(descriptor);\n}\n\nexport type CalendarAccessibleNameInfo<Content = unknown> = Readonly<{\n date: string;\n isToday: boolean;\n isSelected: boolean;\n disabled: boolean;\n content?: Content;\n}>;\n\n/**\n * \"8월 19일 수요일, 경기 2개, 선택됨\" is assembled by the product from its own\n * `content` payload and locale/grammar — the same reason Steps takes\n * `composeAccessibleName` instead of assembling copy itself.\n */\nexport type ComposeCalendarAccessibleName<Content = unknown> = (\n info: CalendarAccessibleNameInfo<Content>,\n) => string;\n\nexport type ResolvedCalendarDateCell<Content = unknown> = CalendarDateCellDescriptor<Content> &\n Readonly<{\n date: string;\n /** 1-indexed. */\n row: number;\n /** 1-indexed, 1..7. */\n column: number;\n isToday: boolean;\n isSelected: boolean;\n /** `false` when disabled — the cell stays focusable (see `getCalendarNavigationTarget`) but must never commit or close on activate. */\n selectable: boolean;\n accessibleName: string;\n }>;\n\nexport type ResolvedCalendarFillerCell = Readonly<{\n date?: never;\n row: number;\n column: number;\n filler: true;\n}>;\n\nexport type ResolvedCalendarGridCell<Content = unknown> =\n | ResolvedCalendarDateCell<Content>\n | ResolvedCalendarFillerCell;\n\n/**\n * Resolves per-cell semantic state against a selection supplied separately\n * from the raw grid (mirroring `resolveSelectSelectedItem`'s separation of\n * source data from selection state) — the same grid page renders identically\n * whether it is hosted by Calendar or by DatePicker's popover/sheet.\n */\nexport function resolveCalendarGridDescriptor<Content>(\n grid: CalendarGridDescriptor<Content>,\n selectedDate: string | null,\n options: Readonly<{ composeAccessibleName: ComposeCalendarAccessibleName<Content> }>,\n): readonly ResolvedCalendarGridCell<Content>[] {\n validateCalendarGridDescriptor(grid);\n if (typeof options.composeAccessibleName !== \"function\") {\n throw new TypeError(\"Calendar composeAccessibleName must be a function\");\n }\n\n return grid.cells.map((cell, index) => {\n const row = Math.floor(index / GRID_COLUMNS) + 1;\n const column = (index % GRID_COLUMNS) + 1;\n if (cell.date === undefined) {\n return { row, column, filler: true as const };\n }\n const isToday = cell.date === grid.todayDate;\n const isSelected = cell.date === selectedDate;\n const disabled = cell.disabled ?? false;\n const nameInfo: CalendarAccessibleNameInfo<Content> =\n cell.content === undefined\n ? { date: cell.date, isToday, isSelected, disabled }\n : { date: cell.date, isToday, isSelected, disabled, content: cell.content };\n const accessibleName = options.composeAccessibleName(nameInfo);\n if (typeof accessibleName !== \"string\" || accessibleName.trim().length === 0) {\n throw new TypeError(\"Calendar composeAccessibleName must return a non-empty string\");\n }\n return {\n ...cell,\n date: cell.date,\n row,\n column,\n isToday,\n isSelected,\n selectable: !disabled,\n accessibleName,\n };\n });\n}\n\n/** Top-level entry point: validates the descriptor and resolves its grid page. */\nexport function resolveCalendarDescriptor<Content>(\n descriptor: CalendarDescriptor<Content>,\n options: Readonly<{ composeAccessibleName: ComposeCalendarAccessibleName<Content> }>,\n): readonly ResolvedCalendarGridCell<Content>[] {\n validateCalendarDescriptor(descriptor);\n const selectedDate = descriptor.selectedDate ?? descriptor.defaultSelectedDate ?? null;\n return resolveCalendarGridDescriptor(descriptor.grid, selectedDate, options);\n}\n\nexport type CalendarNavigationIntent =\n | \"next-day\"\n | \"previous-day\"\n | \"next-week\"\n | \"previous-week\"\n | \"first-of-week\"\n | \"last-of-week\";\n\n/**\n * ArrowLeft/Right flip under RTL, matching `getSelectionNavigationIntent`'s\n * `direction` parameter.\n */\nexport function getCalendarNavigationIntent(\n key: WebKeyboardKey,\n direction: DesignSystemDirection = \"ltr\",\n): CalendarNavigationIntent | undefined {\n if (key === \"Home\") return \"first-of-week\";\n if (key === \"End\") return \"last-of-week\";\n if (key === \"ArrowDown\") return \"next-week\";\n if (key === \"ArrowUp\") return \"previous-week\";\n if (key === \"ArrowRight\") return direction === \"rtl\" ? \"previous-day\" : \"next-day\";\n if (key === \"ArrowLeft\") return direction === \"rtl\" ? \"next-day\" : \"previous-day\";\n return undefined;\n}\n\nexport type CalendarNavigationResult =\n | Readonly<{ date: string; overflow?: never }>\n | Readonly<{ date?: never; overflow: \"before\" | \"after\" }>;\n\n/**\n * Pure index arithmetic over the fixed seven-column page. Unlike\n * `getCollectionNavigationTarget`, this does NOT skip disabled dates —\n * per the WAI-ARIA date picker dialog pattern, arrow-key focus must land\n * predictably (down always moves exactly one row) even on a disabled date;\n * only the *activate* action is expected to no-op there. Moving past the\n * edge of this page returns an `overflow` signal instead of wrapping, since\n * HJM does not know the adjacent month's shape — the product pages the\n * month and refocuses the corresponding day.\n */\nexport function getCalendarNavigationTarget<Content>(\n grid: CalendarGridDescriptor<Content>,\n currentDate: string,\n intent: CalendarNavigationIntent,\n): CalendarNavigationResult {\n validateCalendarGridDescriptor(grid);\n const currentIndex = grid.cells.findIndex((cell) => cell.date === currentDate);\n if (currentIndex < 0) {\n throw new RangeError(`Calendar currentDate is not part of this grid page: ${currentDate}`);\n }\n\n const findDated = (from: number, step: number): number | undefined => {\n for (let index = from; index >= 0 && index < grid.cells.length; index += step) {\n if (grid.cells[index]?.date !== undefined) return index;\n }\n return undefined;\n };\n\n const rowStart = Math.floor(currentIndex / GRID_COLUMNS) * GRID_COLUMNS;\n const rowEnd = rowStart + GRID_COLUMNS - 1;\n\n if (intent === \"first-of-week\") {\n const found = findDated(rowStart, 1);\n return found !== undefined && found <= rowEnd\n ? { date: grid.cells[found]!.date! }\n : { overflow: \"before\" };\n }\n if (intent === \"last-of-week\") {\n const found = findDated(rowEnd, -1);\n return found !== undefined && found >= rowStart\n ? { date: grid.cells[found]!.date! }\n : { overflow: \"after\" };\n }\n\n const forward = intent === \"next-day\" || intent === \"next-week\";\n const stride = intent === \"next-week\" || intent === \"previous-week\" ? GRID_COLUMNS : 1;\n const step = forward ? 1 : -1;\n const target = currentIndex + step * stride;\n if (target < 0) return { overflow: \"before\" };\n if (target >= grid.cells.length) return { overflow: \"after\" };\n if (grid.cells[target]?.date !== undefined) return { date: grid.cells[target]!.date! };\n // Landed on a filler (only reachable for a week-step into a partially\n // filled edge row): keep scanning the same direction for the nearest real\n // date rather than asking a renderer to interpret a blank cell.\n const resolved = findDated(target, step);\n return resolved !== undefined\n ? { date: grid.cells[resolved]!.date! }\n : { overflow: forward ? \"after\" : \"before\" };\n}\n\nexport type CalendarSize = \"medium\" | \"large\";\n\n/**\n * `today` and `selected` are visually independent (a non-selected today and\n * a selected past day must both read clearly) and neither is color-only:\n * today gets a persistent border, selected gets a filled background, and\n * both remain in `accessibleName`/`isToday`/`isSelected` for assistive tech.\n */\nexport const calendarRecipe = {\n slots: [\n \"root\",\n \"header\",\n \"monthLabel\",\n \"previousMonth\",\n \"nextMonth\",\n \"weekdayRow\",\n \"weekdayLabel\",\n \"grid\",\n \"week\",\n \"day\",\n \"dayLabel\",\n \"content\",\n ] as const,\n defaults: { size: \"medium\" },\n header: {\n gap: spacing.xs,\n monthLabel: {\n textVariant: \"title\",\n fontWeight: fontWeight.bold,\n color: semanticColors.content.primary,\n },\n navButton: { diameter: control.buttonHeight.medium, color: semanticColors.content.secondary },\n navIcon: { previous: \"chevronStart\", next: \"chevronEnd\" },\n },\n weekdayLabel: {\n textVariant: \"label\",\n color: semanticColors.content.secondary,\n },\n sizes: {\n medium: { cellDiameter: control.minTouchTarget, textVariant: \"body\", glyph: \"sm\" },\n large: { cellDiameter: glyph.xxl, textVariant: \"bodyLarge\", glyph: \"md\" },\n },\n day: {\n radius: \"full\" as const,\n label: { color: semanticColors.content.body, numericVariant: \"tabular\" },\n outsideFocusedMonthOpacity: opacity.muted,\n disabledOpacity: opacity.disabled,\n today: { border: semanticColors.border.focus, borderWidth: stroke.default },\n selected: {\n background: semanticColors.action.brand.background,\n content: semanticColors.action.brand.content,\n },\n focus: focusIndicatorContract,\n },\n} as const satisfies {\n slots: readonly string[];\n defaults: { size: CalendarSize };\n header: {\n gap: number;\n monthLabel: { textVariant: TextVariant; fontWeight: FontWeightValue; color: ColorReference };\n navButton: { diameter: number; color: ColorReference };\n navIcon: { previous: SemanticIconName; next: SemanticIconName };\n };\n weekdayLabel: { textVariant: TextVariant; color: ColorReference };\n sizes: Record<CalendarSize, { cellDiameter: number; textVariant: TextVariant; glyph: GlyphSize }>;\n day: {\n radius: \"full\";\n label: { color: ColorReference; numericVariant: \"tabular\" };\n outsideFocusedMonthOpacity: number;\n disabledOpacity: number;\n today: { border: ColorReference; borderWidth: number };\n selected: { background: ColorReference; content: ColorReference };\n focus: typeof focusIndicatorContract;\n };\n};\n\n/**\n * Calendar is `shared`, not `adaptive`: the grid is always visible inline\n * (no popup/Sheet choice to make). Web gets `grid` role + roving-tabindex\n * arrow keys; Native has no composite-widget equivalent, so each date is\n * simply an independently focusable/tappable element and month paging goes\n * through the always-present previous/next buttons on both platforms — same\n * result (the user reaches and picks a date), different path, matching the\n * `beta → stable(adaptive)` gate's standard even though this component\n * itself is not adaptive.\n */\nexport const calendarBehavior = {\n controlled: [\n \"selectedDate\",\n \"defaultSelectedDate\",\n \"onSelectionChange\",\n \"focusedMonth\",\n \"defaultFocusedMonth\",\n \"onFocusedMonthChange\",\n ],\n inputs: [\"grid\", \"monthLabel\"],\n stateAxes: {\n availability: [\"enabled\", \"disabled\"],\n value: [\"selected\"],\n },\n web: {\n roles: [\"grid\", \"row\", \"gridcell\", \"button\"],\n keyboard: [\n \"Tab\",\n \"Enter\",\n \"Space\",\n \"ArrowUp\",\n \"ArrowDown\",\n \"ArrowLeft\",\n \"ArrowRight\",\n \"Home\",\n \"End\",\n ],\n focus: \"roving\",\n },\n native: {\n roles: [\"button\"],\n states: [\"disabled\", \"selected\"],\n actions: [\"activate\"],\n },\n scenarios: [\n \"today-and-selected-are-independent-and-both-non-color-marked\",\n \"disabled-dates-remain-focusable-but-never-activate\",\n \"arrow-keys-move-by-day-and-week-inside-the-visible-month-page\",\n \"home-and-end-move-to-the-first-and-last-dated-cell-of-the-focused-row\",\n \"moving-past-the-visible-grid-edge-requests-a-month-change-instead-of-wrapping\",\n \"filler-cells-carry-no-accessible-name-and-are-hidden-from-assistive-tech\",\n \"every-dated-cell-accessible-name-is-composed-by-the-product\",\n \"changing-the-focused-month-never-changes-or-clears-the-selection\",\n \"range-selection-is-not-part-of-the-contract\",\n ],\n} as const satisfies BehaviorContract;\n"]}
|
package/dist/card.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type CardHeadingLevel = 2 | 3 | 4;
|
|
2
|
+
/**
|
|
3
|
+
* Shared Card anatomy. Renderers own their host nodes (`article` on Web,
|
|
4
|
+
* `View` on Native), while these slots and defaults stay identical.
|
|
5
|
+
*/
|
|
6
|
+
export declare const cardRecipe: {
|
|
7
|
+
readonly slots: readonly ["root", "media", "body", "header", "leading", "title", "description", "content", "actions"];
|
|
8
|
+
readonly defaults: {
|
|
9
|
+
readonly tone: "default";
|
|
10
|
+
readonly selected: false;
|
|
11
|
+
readonly bordered: true;
|
|
12
|
+
readonly headingLevel: 3;
|
|
13
|
+
readonly padding: "md";
|
|
14
|
+
};
|
|
15
|
+
readonly selectedTone: "accent";
|
|
16
|
+
readonly body: {
|
|
17
|
+
readonly padding: 16;
|
|
18
|
+
readonly gap: 8;
|
|
19
|
+
};
|
|
20
|
+
readonly header: {
|
|
21
|
+
readonly gap: 12;
|
|
22
|
+
};
|
|
23
|
+
readonly title: {
|
|
24
|
+
readonly variant: "title";
|
|
25
|
+
readonly tone: "primary";
|
|
26
|
+
readonly emphasis: "strong";
|
|
27
|
+
};
|
|
28
|
+
readonly description: {
|
|
29
|
+
readonly variant: "body";
|
|
30
|
+
readonly tone: "muted";
|
|
31
|
+
readonly emphasis: "regular";
|
|
32
|
+
};
|
|
33
|
+
readonly actions: {
|
|
34
|
+
readonly gap: 12;
|
|
35
|
+
readonly paddingHorizontal: 16;
|
|
36
|
+
readonly paddingBottom: 16;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEzC;;;GAGG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2EtB,CAAC"}
|
package/dist/card.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { spacing } from "./foundations.js";
|
|
2
|
+
import { surfaceDefaults, } from "./base-recipes.js";
|
|
3
|
+
/**
|
|
4
|
+
* Shared Card anatomy. Renderers own their host nodes (`article` on Web,
|
|
5
|
+
* `View` on Native), while these slots and defaults stay identical.
|
|
6
|
+
*/
|
|
7
|
+
export const cardRecipe = {
|
|
8
|
+
slots: [
|
|
9
|
+
"root",
|
|
10
|
+
"media",
|
|
11
|
+
"body",
|
|
12
|
+
"header",
|
|
13
|
+
"leading",
|
|
14
|
+
"title",
|
|
15
|
+
"description",
|
|
16
|
+
"content",
|
|
17
|
+
"actions",
|
|
18
|
+
],
|
|
19
|
+
defaults: {
|
|
20
|
+
tone: surfaceDefaults.tone,
|
|
21
|
+
selected: false,
|
|
22
|
+
bordered: true,
|
|
23
|
+
headingLevel: 3,
|
|
24
|
+
padding: "md",
|
|
25
|
+
},
|
|
26
|
+
selectedTone: "accent",
|
|
27
|
+
body: {
|
|
28
|
+
padding: spacing.md,
|
|
29
|
+
gap: spacing.xs,
|
|
30
|
+
},
|
|
31
|
+
header: {
|
|
32
|
+
gap: spacing.sm,
|
|
33
|
+
},
|
|
34
|
+
title: {
|
|
35
|
+
variant: "title",
|
|
36
|
+
tone: "primary",
|
|
37
|
+
emphasis: "strong",
|
|
38
|
+
},
|
|
39
|
+
description: {
|
|
40
|
+
variant: "body",
|
|
41
|
+
tone: "muted",
|
|
42
|
+
emphasis: "regular",
|
|
43
|
+
},
|
|
44
|
+
actions: {
|
|
45
|
+
gap: spacing.sm,
|
|
46
|
+
paddingHorizontal: spacing.md,
|
|
47
|
+
paddingBottom: spacing.md,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=card.js.map
|
package/dist/card.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.js","sourceRoot":"","sources":["../src/card.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EACL,eAAe,GAGhB,MAAM,mBAAmB,CAAC;AAI3B;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,KAAK,EAAE;QACL,MAAM;QACN,OAAO;QACP,MAAM;QACN,QAAQ;QACR,SAAS;QACT,OAAO;QACP,aAAa;QACb,SAAS;QACT,SAAS;KACD;IACV,QAAQ,EAAE;QACR,IAAI,EAAE,eAAe,CAAC,IAAI;QAC1B,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,CAAC;QACf,OAAO,EAAE,IAAI;KACd;IACD,YAAY,EAAE,QAAQ;IACtB,IAAI,EAAE;QACJ,OAAO,EAAE,OAAO,CAAC,EAAE;QACnB,GAAG,EAAE,OAAO,CAAC,EAAE;KAChB;IACD,MAAM,EAAE;QACN,GAAG,EAAE,OAAO,CAAC,EAAE;KAChB;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,GAAG,EAAE,OAAO,CAAC,EAAE;QACf,iBAAiB,EAAE,OAAO,CAAC,EAAE;QAC7B,aAAa,EAAE,OAAO,CAAC,EAAE;KAC1B;CAkCF,CAAC","sourcesContent":["import { spacing } from \"./foundations.js\";\nimport {\n surfaceDefaults,\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 \"body\",\n \"header\",\n \"leading\",\n \"title\",\n \"description\",\n \"content\",\n \"actions\",\n ] as const,\n defaults: {\n tone: surfaceDefaults.tone,\n selected: false,\n bordered: true,\n headingLevel: 3,\n padding: \"md\",\n },\n selectedTone: \"accent\",\n body: {\n padding: spacing.md,\n gap: spacing.xs,\n },\n header: {\n gap: spacing.sm,\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 gap: spacing.sm,\n paddingHorizontal: spacing.md,\n paddingBottom: spacing.md,\n },\n} as const satisfies {\n slots: readonly [\n \"root\",\n \"media\",\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 padding: SurfacePadding;\n };\n selectedTone: SurfaceTone;\n body: { padding: number; gap: number };\n header: { gap: number };\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"]}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ant Design Carousel's infinite loop and default autoplay are intentionally
|
|
3
|
+
* not reproduced — both remove the one thing this contract treats as
|
|
4
|
+
* non-negotiable: a reliable answer to "where am I, and where does it end".
|
|
5
|
+
* See docs/carousel.md for the accessibility rationale on every point below.
|
|
6
|
+
*/
|
|
7
|
+
export type CarouselSlideDescriptor<Id extends string = string> = Readonly<{
|
|
8
|
+
id: Id;
|
|
9
|
+
/** Accessible name for the slide, e.g. "8/19 두산 vs LG". The slide's visual content is product-owned. */
|
|
10
|
+
label: string;
|
|
11
|
+
}>;
|
|
12
|
+
export type CarouselAutoplayConfig = Readonly<{
|
|
13
|
+
/** Minimum time a slide stays current before an automatic advance. */
|
|
14
|
+
intervalMs: number;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* Renderer-facing prop shape only — mirrors SelectSelection's controlled/
|
|
18
|
+
* uncontrolled duality, but the resolver below always takes a concrete,
|
|
19
|
+
* already-resolved `currentKey` (see CarouselDescriptor) so validation and
|
|
20
|
+
* position math never have to branch on which mode the product chose.
|
|
21
|
+
*/
|
|
22
|
+
export type ControlledCarouselSelection<Id extends string = string> = Readonly<{
|
|
23
|
+
currentKey: Id;
|
|
24
|
+
defaultCurrentKey?: never;
|
|
25
|
+
onCurrentKeyChange(key: Id): void;
|
|
26
|
+
}>;
|
|
27
|
+
export type UncontrolledCarouselSelection<Id extends string = string> = Readonly<{
|
|
28
|
+
currentKey?: never;
|
|
29
|
+
defaultCurrentKey?: Id;
|
|
30
|
+
onCurrentKeyChange?: (key: Id) => void;
|
|
31
|
+
}>;
|
|
32
|
+
export type CarouselSelection<Id extends string = string> = ControlledCarouselSelection<Id> | UncontrolledCarouselSelection<Id>;
|
|
33
|
+
export type CarouselDescriptor<Id extends string = string> = Readonly<{
|
|
34
|
+
slides: readonly CarouselSlideDescriptor<Id>[];
|
|
35
|
+
currentKey: Id;
|
|
36
|
+
/** Absent by default. Autoplay is opt-in — see docs/carousel.md. */
|
|
37
|
+
autoplay?: CarouselAutoplayConfig;
|
|
38
|
+
}>;
|
|
39
|
+
export declare function validateCarouselSlide<Id extends string>(slide: CarouselSlideDescriptor<Id>): void;
|
|
40
|
+
export declare function validateCarouselAutoplayConfig(autoplay: CarouselAutoplayConfig): void;
|
|
41
|
+
export declare function validateCarouselDescriptor<Id extends string>(descriptor: CarouselDescriptor<Id>): void;
|
|
42
|
+
export type CarouselAccessibleNameInfo = Readonly<{
|
|
43
|
+
position: number;
|
|
44
|
+
total: number;
|
|
45
|
+
label: string;
|
|
46
|
+
}>;
|
|
47
|
+
/**
|
|
48
|
+
* Same reason Steps and Timeline do not assemble their own accessible name:
|
|
49
|
+
* counter-word grammar and phrase order are product-owned copy decisions.
|
|
50
|
+
*/
|
|
51
|
+
export type ComposeCarouselAccessibleName = (info: CarouselAccessibleNameInfo) => string;
|
|
52
|
+
export type ResolvedCarouselSlideDescriptor<Id extends string = string> = CarouselSlideDescriptor<Id> & Readonly<{
|
|
53
|
+
/** 1-indexed so position and label both preserve reading order for renderers. */
|
|
54
|
+
position: number;
|
|
55
|
+
total: number;
|
|
56
|
+
current: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* True for every slide but the current one. A renderer must exclude an
|
|
59
|
+
* inert slide's interactive content from both focus and the
|
|
60
|
+
* accessibility tree — a hidden slide whose link can still receive
|
|
61
|
+
* focus is worse than one that is simply unreachable until the user
|
|
62
|
+
* advances to it (see docs/carousel.md).
|
|
63
|
+
*/
|
|
64
|
+
inert: boolean;
|
|
65
|
+
accessibleName: string;
|
|
66
|
+
}>;
|
|
67
|
+
export type ResolveCarouselOptions = Readonly<{
|
|
68
|
+
composeAccessibleName: ComposeCarouselAccessibleName;
|
|
69
|
+
}>;
|
|
70
|
+
/**
|
|
71
|
+
* Attaches order, current/inert, and the composed accessible name used by
|
|
72
|
+
* both the slide group and its indicator dot — one composer, reused for
|
|
73
|
+
* every render target, the same way Steps reuses a single composer.
|
|
74
|
+
*/
|
|
75
|
+
export declare function resolveCarouselDescriptor<Id extends string>(descriptor: CarouselDescriptor<Id>, options: ResolveCarouselOptions): readonly ResolvedCarouselSlideDescriptor<Id>[];
|
|
76
|
+
export type CarouselNavigationIntent = "next" | "previous" | "first" | "last";
|
|
77
|
+
/**
|
|
78
|
+
* Clamps at the first/last slide instead of wrapping — infinite loop is out
|
|
79
|
+
* of scope (see docs/carousel.md), so there is no modulo here at all, unlike
|
|
80
|
+
* getCollectionNavigationTarget's `loop` parameter elsewhere in this package.
|
|
81
|
+
*/
|
|
82
|
+
export declare function getCarouselNavigationTarget<Id extends string>(descriptor: CarouselDescriptor<Id>, intent: CarouselNavigationIntent): Id;
|
|
83
|
+
export type CarouselAutoplayInputs = Readonly<{
|
|
84
|
+
/** True whenever a platform reduce-motion preference is active. */
|
|
85
|
+
reducedMotion: boolean;
|
|
86
|
+
/** Renderer-combined pointer hover, focus-within, and drag signal. */
|
|
87
|
+
paused: boolean;
|
|
88
|
+
}>;
|
|
89
|
+
/**
|
|
90
|
+
* Autoplay is never active without an explicit config, under reduce motion,
|
|
91
|
+
* or while the user is hovering, focusing, or dragging the carousel — the
|
|
92
|
+
* three guards the brief requires are one function so a renderer cannot wire
|
|
93
|
+
* an autoplay timer that forgets one of them.
|
|
94
|
+
*/
|
|
95
|
+
export declare function isCarouselAutoplayActive(autoplay: CarouselAutoplayConfig | undefined, inputs: CarouselAutoplayInputs): boolean;
|
|
96
|
+
export declare const carouselBehaviorDefaults: {
|
|
97
|
+
readonly autoplay: false;
|
|
98
|
+
};
|
|
99
|
+
export declare const carouselBehavior: {
|
|
100
|
+
readonly controlled: readonly ["currentKey", "defaultCurrentKey", "onCurrentKeyChange"];
|
|
101
|
+
readonly inputs: readonly ["autoplay", "reducedMotion", "dragged"];
|
|
102
|
+
readonly defaults: {
|
|
103
|
+
readonly autoplay: false;
|
|
104
|
+
};
|
|
105
|
+
readonly stateAxes: {
|
|
106
|
+
readonly interaction: readonly ["idle", "dragged"];
|
|
107
|
+
readonly value: readonly ["selected"];
|
|
108
|
+
};
|
|
109
|
+
readonly web: {
|
|
110
|
+
readonly roles: readonly ["region", "group"];
|
|
111
|
+
readonly keyboard: readonly ["Tab", "Enter", "Space", "ArrowLeft", "ArrowRight"];
|
|
112
|
+
readonly focus: "roving";
|
|
113
|
+
};
|
|
114
|
+
readonly native: {
|
|
115
|
+
readonly roles: readonly ["adjustable"];
|
|
116
|
+
readonly states: readonly ["selected"];
|
|
117
|
+
readonly actions: readonly ["increment", "decrement"];
|
|
118
|
+
};
|
|
119
|
+
readonly scenarios: readonly ["current-position-is-announced-with-a-readable-name-not-dots-alone", "inactive-slide-content-is-excluded-from-focus-and-the-accessibility-tree", "previous-next-and-dot-controls-stay-in-tab-order-regardless-of-current-slide", "arrow-keys-move-one-slide-on-web-swipe-moves-one-slide-on-native", "boundary-slides-clamp-instead-of-wrapping-because-loop-is-out-of-scope", "autoplay-is-opt-in-and-off-by-default", "autoplay-never-runs-when-reduced-motion-is-active", "autoplay-pauses-on-hover-focus-or-drag-and-does-not-announce-automatic-transitions"];
|
|
120
|
+
};
|
|
121
|
+
export type CarouselSize = "medium";
|
|
122
|
+
export declare const carouselRecipe: {
|
|
123
|
+
readonly slots: readonly ["root", "track", "slide", "dots", "dot", "previousControl", "nextControl"];
|
|
124
|
+
readonly defaults: {
|
|
125
|
+
readonly size: "medium";
|
|
126
|
+
};
|
|
127
|
+
readonly sizes: {
|
|
128
|
+
readonly medium: {
|
|
129
|
+
readonly gap: 12;
|
|
130
|
+
readonly controlHitTarget: 44;
|
|
131
|
+
readonly controlIcon: "sm";
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
readonly dot: {
|
|
135
|
+
readonly diameter: 8;
|
|
136
|
+
readonly hitTarget: 44;
|
|
137
|
+
readonly color: {
|
|
138
|
+
readonly inactive: Readonly<{
|
|
139
|
+
source: "theme";
|
|
140
|
+
key: "textWeak";
|
|
141
|
+
alpha?: number;
|
|
142
|
+
}>;
|
|
143
|
+
readonly current: Readonly<{
|
|
144
|
+
source: "theme";
|
|
145
|
+
key: "contentBrand";
|
|
146
|
+
alpha?: number;
|
|
147
|
+
}>;
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
/** Previous/next chrome is composed from IconButton (ghost tone) rather than owning new button visuals. */
|
|
151
|
+
readonly control: {
|
|
152
|
+
readonly icons: {
|
|
153
|
+
readonly previous: "chevronStart";
|
|
154
|
+
readonly next: "chevronEnd";
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
readonly states: {
|
|
158
|
+
readonly focus: {
|
|
159
|
+
readonly color: Readonly<{
|
|
160
|
+
source: "theme";
|
|
161
|
+
key: "contentBrand";
|
|
162
|
+
alpha?: number;
|
|
163
|
+
}>;
|
|
164
|
+
readonly width: 2;
|
|
165
|
+
readonly offset: 2;
|
|
166
|
+
};
|
|
167
|
+
readonly draggedOpacity: 0.64;
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Manual slide-to-slide movement crossfades rather than snapping under
|
|
171
|
+
* Reduce Motion, reusing the existing "context" preset instead of a new
|
|
172
|
+
* token — autoplay itself simply does not run at all (isCarouselAutoplayActive).
|
|
173
|
+
*/
|
|
174
|
+
readonly transition: {
|
|
175
|
+
readonly duration: 320;
|
|
176
|
+
readonly easing: "emphasized";
|
|
177
|
+
readonly reducedMotion: "opacity";
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
//# sourceMappingURL=carousel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["../src/carousel.ts"],"names":[],"mappings":"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"}
|