@knpkv/rly 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -3
- package/dist/{Dialog-B9Ub_gMT.js → Dialog-CU66FqWD.js} +325 -257
- package/dist/Dialog-CU66FqWD.js.map +1 -0
- package/dist/{PortalProvider-CN_81Fy3.js → PortalProvider-op07u8na.js} +20 -18
- package/dist/PortalProvider-op07u8na.js.map +1 -0
- package/dist/components.css +1 -1
- package/dist/dts/foundations/Icon.d.ts +1 -1
- package/dist/dts/foundations/Icon.d.ts.map +1 -1
- package/dist/dts/internal/composedFocus.d.ts +11 -0
- package/dist/dts/internal/composedFocus.d.ts.map +1 -0
- package/dist/dts/internal/relaySummon.d.ts +50 -0
- package/dist/dts/internal/relaySummon.d.ts.map +1 -0
- package/dist/dts/patterns/RelayComposer.d.ts +65 -0
- package/dist/dts/patterns/RelayComposer.d.ts.map +1 -0
- package/dist/dts/patterns/RelayDock.d.ts.map +1 -1
- package/dist/dts/patterns/RelayLauncher.d.ts +32 -1
- package/dist/dts/patterns/RelayLauncher.d.ts.map +1 -1
- package/dist/dts/patterns/RelayPanel.d.ts +91 -0
- package/dist/dts/patterns/RelayPanel.d.ts.map +1 -0
- package/dist/dts/patterns/index.d.ts +6 -2
- package/dist/dts/patterns/index.d.ts.map +1 -1
- package/dist/dts/tokens/fonts.d.ts +13 -0
- package/dist/dts/tokens/fonts.d.ts.map +1 -0
- package/dist/dts/tokens/index.d.ts +2 -0
- package/dist/dts/tokens/index.d.ts.map +1 -1
- package/dist/fonts.css +7 -2
- package/dist/foundations/index.js +1 -1
- package/dist/index.js +6 -6
- package/dist/patterns/index.js +2 -2
- package/dist/{patterns-ChmGSFqO.js → patterns-CDBnXTUD.js} +1705 -1280
- package/dist/patterns-CDBnXTUD.js.map +1 -0
- package/dist/primitives/index.js +3 -3
- package/dist/{primitives-Bd6WhE78.js → primitives-DgQybTyq.js} +254 -322
- package/dist/primitives-DgQybTyq.js.map +1 -0
- package/dist/tokens/index.js +2 -2
- package/dist/{tokens-B075JP3Z.js → tokens-Cf0jXIRg.js} +14 -8
- package/dist/tokens-Cf0jXIRg.js.map +1 -0
- package/package.json +1 -1
- package/registry/components.json +206 -1
- package/registry/search.json +45 -0
- package/dist/Dialog-B9Ub_gMT.js.map +0 -1
- package/dist/PortalProvider-CN_81Fy3.js.map +0 -1
- package/dist/patterns-ChmGSFqO.js.map +0 -1
- package/dist/primitives-Bd6WhE78.js.map +0 -1
- package/dist/tokens-B075JP3Z.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"primitives-DgQybTyq.js","names":["root","item","style","styles","validateItems","root","style","styles","root","defaultSize","near","style","styles","percent","root","style","styles","root","unknown","near","style","styles","Predicate.isFunction","_Fragment","root","tonePrimary","toneSecondary","toneTertiary","style","styles","root","style","styles","Select","styles","root","item","style","styles","RadixRadioGroup","styles","decodeRlyTheme","Icon","requireText","cssClass","isFunction","defineVariants","classNames","RLY_SELECT_DEFAULT_VARIANTS","Field","Select$1","Fragment$1","ChartLegend_module_default","style$8","name","RLY_SERIES","rlySeriesColor","series","validateItems$1","ids","item","items","id","ChartLegend","props","label","className","Divider_module_default","style$7","RLY_DIVIDER_VARIANTS","RLY_DIVIDER_DEFAULT_VARIANTS","Divider","decorative","accessibleLabel","orientation","strength","LimitTrack_module_default","style$6","RLY_LIMIT_TRACK_VARIANTS","RLY_LIMIT_TRACK_DEFAULT_VARIANTS","readingOf","value","requireFinite","limitTrackTone","mark","near","reading","percent$1","LimitTrack","rawValue","nearMark","accessible","accessibleValueText","valueText","meter","projection","projected","size","stale","Notice_module_default","style$5","RLY_NOTICE_VARIANTS","RLY_NOTICE_DEFAULT_VARIANTS","toneIcons","Notice","glyph","icon","tone","role","announce","action","BIN_SIZES","DAY","groupStarts","starts","first","count","validateColumns","index","column","columns","previous","stackOrder","order","segment","narrowestBar","from","span","narrowest","last","width","chooseBinSize","preferred","minBar","days","binRates","average","sum","bins","bin","binColumns","group","values","seen","segments","left","right","stacked","selectBin","selection","extend","moveFocus","clamp","next","key","current","chartTicks","labelWidth","ticks","x","StackedBars_module_default","style$4","LABEL_WIDTH","LABEL_GAP","ANNOUNCE_AFTER","MIN_TARGET","attachRef","ref","cleanup","element","useInlineSize","setSize","useState","fallback","useCallback","detach","callerRef","observer","entry","percent","level","nearLevel","axisFraction","at","to","Band","band","window","StackedBars","instructionsId","useId","binSize","useMemo","rates","max","total","nearLabels","bands","noReading","noReadingLabel","axisStart","axisEnd","setLabelWidth","axisRef","useRef","cursor","setCursor","pendingTap","setPendingTap","pointerType","emitted","announceRequest","setAnnounceRequest","emit","request","onSelectionChange","selectedFrom","selectedTo","own","announcement","setAnnouncement","description","describeSelection","binOf","focus","useEffect","timer","useLayoutEffect","axisHeight","setAxisHeight","labels","widest","tallest","onKeyDown","event","end","start","shaded","selectionStart","selectionEnd","selected","focusedBin","plotHeight","height","insetX","insetY","focusSlot","formatScale","slot","inSelection","touch","rate","top","tick","formatTick","text","instructions","Surface_module_default","style$3","RLY_SURFACE_VARIANTS","RLY_SURFACE_DEFAULT_VARIANTS","Surface","createElement","as","form","padding","children","Text_module_default","style$2","RLY_TEXT_VARIANTS","RLY_TEXT_DEFAULT_VARIANTS","defaultElement","variant","Text","ThemeSelect_module_default","themeLabels","themeOptions","RLY_THEME_NAMES","ThemeSelect","onChange","theme","onValueChange","labelVisibility","controlProps","ToggleGroup_module_default","style$1","RLY_TOGGLE_GROUP_VARIANTS","RLY_TOGGLE_GROUP_DEFAULT_VARIANTS","stepOf","validateItems","itemValue","ToggleGroup","ariaLabel","options","choose","step","RadioGroup","TrackKey_module_default","style","RLY_TRACK_KEY_MARKS","TrackKey","marks"],"sources":["../src/primitives/ChartLegend.module.css","../src/primitives/ChartLegend.tsx","../src/primitives/Divider.module.css","../src/primitives/Divider.tsx","../src/primitives/LimitTrack.module.css","../src/primitives/LimitTrack.tsx","../src/primitives/Notice.module.css","../src/primitives/Notice.tsx","../src/internal/chart.ts","../src/primitives/StackedBars.module.css","../src/primitives/StackedBars.tsx","../src/primitives/Surface.module.css","../src/primitives/Surface.tsx","../src/primitives/Text.module.css","../src/primitives/Text.tsx","../src/primitives/ThemeSelect.module.css","../src/primitives/ThemeSelect.tsx","../src/primitives/ToggleGroup.module.css","../src/primitives/ToggleGroup.tsx","../src/primitives/TrackKey.module.css","../src/primitives/TrackKey.tsx"],"sourcesContent":["@layer rly.components {\n .root {\n color: var(--rly-color-text-1);\n display: flex;\n flex-wrap: wrap;\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n gap: var(--rly-space-6) var(--rly-space-16);\n list-style: none;\n margin: 0;\n padding: 0;\n }\n .item {\n align-items: center;\n display: inline-flex;\n gap: var(--rly-space-6);\n min-inline-size: 0;\n }\n .swatch {\n block-size: var(--rly-space-12);\n border-radius: 2px;\n flex: none;\n inline-size: var(--rly-space-12);\n }\n}\n","import type { ComponentPropsWithRef, ReactElement } from \"react\"\nimport { classNames, cssClass, requireText } from \"../internal/component.js\"\nimport styles from \"./ChartLegend.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\n/** Chart series slots in assignment order, then the neutral remainder for folded series. */\nexport const RLY_SERIES: readonly [1, 2, 3, 4, 5, 6, 7, 8, \"other\"] = [1, 2, 3, 4, 5, 6, 7, 8, \"other\"]\nexport type RlySeries = (typeof RLY_SERIES)[number]\n\n/** The CSS colour of a series slot, for SVG fills and swatches alike. */\nexport const rlySeriesColor = (series: RlySeries): string => `var(--rly-color-series-${series})`\n\n/** One series in a legend: a stable id, the caller's words, and its colour slot. */\nexport interface RlyChartLegendItem {\n readonly id: string\n readonly label: string\n readonly series: RlySeries\n}\n\ntype ChartLegendBaseProps = Omit<ComponentPropsWithRef<\"ul\">, \"aria-label\" | \"children\">\nexport type ChartLegendProps = ChartLegendBaseProps & {\n /** Names the list for assistive technology, for example \"Bookings by colour\". */\n readonly label: string\n /** The series visible in the chart right now; keep each id on the same slot across updates. */\n readonly items: ReadonlyArray<RlyChartLegendItem>\n}\n\nconst validateItems = (items: ReadonlyArray<RlyChartLegendItem>): void => {\n const ids = new Set<string>()\n for (const item of items) {\n const id = requireText(item.id, \"ChartLegend item id\")\n if (ids.has(id)) throw new Error(`ChartLegend item ids must be unique: ${id}`)\n ids.add(id)\n }\n}\n\n/** Which colour is which series. Shown with every multi-series chart; renders nothing without series. */\nexport const ChartLegend = ({ className, items, label, ...props }: ChartLegendProps): ReactElement | null => {\n validateItems(items)\n return items.length === 0 ? null : (\n <ul\n {...props}\n aria-label={requireText(label, \"ChartLegend label\")}\n className={classNames(style(\"root\"), className)}\n // Flex styling with no list markers drops list semantics in WebKit, so the role is explicit.\n role=\"list\"\n >\n {items.map((item) => (\n <li className={style(\"item\")} key={item.id}>\n <span\n aria-hidden=\"true\"\n className={style(\"swatch\")}\n data-series={String(item.series)}\n style={{ background: rlySeriesColor(item.series) }}\n />\n {requireText(item.label, \"ChartLegend item label\")}\n </li>\n ))}\n </ul>\n )\n}\n","@layer rly.components {\n .root {\n flex: none;\n }\n .horizontal {\n block-size: 1px;\n inline-size: 100%;\n }\n .vertical {\n align-self: stretch;\n inline-size: 1px;\n min-block-size: var(--rly-space-20);\n }\n .subtle {\n background: var(--rly-color-border-1);\n }\n .strong {\n background: var(--rly-color-border-2);\n }\n}\n","import type { ComponentPropsWithRef, ReactElement } from \"react\"\nimport { classNames, cssClass, defineVariants, requireText } from \"../internal/component.js\"\nimport styles from \"./Divider.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\nexport const RLY_DIVIDER_VARIANTS = defineVariants({\n orientation: {\n horizontal: { className: style(\"horizontal\"), purpose: \"Separate stacked content\", tokens: [\"space-0\"] },\n vertical: { className: style(\"vertical\"), purpose: \"Separate adjacent content\", tokens: [\"space-0\"] }\n },\n strength: {\n subtle: { className: style(\"subtle\"), purpose: \"Quiet structural boundary\", tokens: [\"color-border-1\"] },\n strong: { className: style(\"strong\"), purpose: \"Explicit structural boundary\", tokens: [\"color-border-2\"] }\n }\n})\nexport const RLY_DIVIDER_DEFAULT_VARIANTS = defineVariants({ orientation: \"horizontal\", strength: \"subtle\" })\nexport type RlyDividerOrientation = keyof typeof RLY_DIVIDER_VARIANTS.orientation\nexport type RlyDividerStrength = keyof typeof RLY_DIVIDER_VARIANTS.strength\ntype DividerBaseProps = Omit<ComponentPropsWithRef<\"div\">, \"aria-label\" | \"children\" | \"role\">\nexport type DividerProps = DividerBaseProps & {\n readonly orientation?: RlyDividerOrientation\n readonly strength?: RlyDividerStrength\n} & ({ readonly decorative?: true; readonly label?: never } | { readonly decorative: false; readonly label: string })\n\n/** Separate content visually or, when explicitly labelled, semantically. */\nexport const Divider = ({\n className,\n decorative = true,\n label,\n orientation = \"horizontal\",\n strength = \"subtle\",\n ...props\n}: DividerProps): ReactElement => {\n if (!decorative && label === undefined) throw new Error(\"Semantic Divider label must contain visible text\")\n const accessibleLabel = decorative || label === undefined ? undefined : requireText(label, \"Semantic Divider label\")\n return (\n <div\n {...props}\n aria-hidden={decorative ? \"true\" : undefined}\n aria-label={accessibleLabel}\n aria-orientation={decorative ? undefined : orientation}\n className={classNames(\n style(\"root\"),\n RLY_DIVIDER_VARIANTS.orientation[orientation].className,\n RLY_DIVIDER_VARIANTS.strength[strength].className,\n className\n )}\n role={decorative ? \"presentation\" : \"separator\"}\n />\n )\n}\n","@layer rly.components {\n .root {\n --rly-limit-track-ink: var(--rly-color-text-2);\n background: var(--rly-color-surface-3);\n border-radius: var(--rly-radius-tag);\n display: block;\n inline-size: 100%;\n min-inline-size: var(--rly-space-48);\n overflow: hidden;\n position: relative;\n }\n .defaultSize {\n block-size: var(--rly-space-12);\n }\n .slim {\n block-size: var(--rly-space-6);\n }\n .fill {\n background: var(--rly-limit-track-ink, var(--rly-color-text-2));\n inset-block: 0;\n inset-inline-start: 0;\n position: absolute;\n }\n .root[data-tone=\"near\"] {\n --rly-limit-track-ink: var(--rly-color-held-ink);\n }\n .root[data-tone=\"full\"] {\n --rly-limit-track-ink: var(--rly-color-blocked-ink);\n }\n /*\n * An old reading's empty track carries a faint 135° hatch, so even a 0% reading shows its age.\n * It differs from no reading by angle (45°) and by the solid edge.\n */\n .root[data-stale=\"true\"] {\n background: repeating-linear-gradient(135deg, var(--rly-color-border-2) 0 1px, transparent 1px 5px)\n var(--rly-color-surface-3);\n }\n /* Old readings are hatched in the same ink, so the tone survives and the age is still visible. */\n .root[data-stale=\"true\"] .fill {\n background: repeating-linear-gradient(\n 135deg,\n var(--rly-limit-track-ink, var(--rly-color-text-2)) 0 3px,\n transparent 3px 6px\n );\n }\n /*\n * No reading is not an empty limit: a faint full-width hatch inside a dashed edge, so it never reads\n * as 0%, and stays distinct from a stale reading, which hatches only its fill in the tone's ink.\n */\n .root[data-tone=\"unknown\"] {\n background: repeating-linear-gradient(45deg, var(--rly-color-border-2) 0 1px, transparent 1px 5px)\n var(--rly-color-surface-3);\n outline: 1px dashed var(--rly-color-border-2);\n outline-offset: -1px;\n }\n .projection {\n border-block: 2px dotted var(--rly-color-held-ink);\n box-sizing: border-box;\n inset-block: 25%;\n position: absolute;\n }\n /* A dark core on a light halo, so the mark reads over the empty track and over every fill. */\n .near {\n background: var(--rly-color-text-1);\n box-shadow:\n -1px 0 0 var(--rly-color-surface-1),\n 1px 0 0 var(--rly-color-surface-1);\n inline-size: 1px; /* stripe-ok: the near mark, a 1px data tick across the track */\n inset-block: 0;\n position: absolute;\n }\n /* The Storybook toolbar's forced-colours mode maps the tokens to system colours too; draw the same edge. */\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .root {\n outline: 1px solid CanvasText;\n outline-offset: -1px;\n }\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .root[data-tone=\"unknown\"] {\n outline-style: dashed;\n }\n @media (forced-colors: active) {\n /*\n * The system palette paints the empty track as Canvas, so an inset edge keeps the 0–100% scale\n * visible without changing the track's geometry.\n */\n .root {\n outline: 1px solid CanvasText;\n outline-offset: -1px;\n }\n .root[data-stale=\"true\"] {\n background: repeating-linear-gradient(135deg, CanvasText 0 1px, Canvas 1px 5px);\n forced-color-adjust: none;\n }\n .root[data-tone=\"unknown\"] {\n background: repeating-linear-gradient(45deg, CanvasText 0 1px, Canvas 1px 5px);\n forced-color-adjust: none;\n outline-style: dashed;\n }\n /* Keep the halo: forced colours drop box-shadow, and the tokens already map to system colours. */\n .near {\n forced-color-adjust: none;\n }\n /* Preserve the age cue with the user's palette when the browser removes background images. */\n .root[data-stale=\"true\"] .fill {\n background: repeating-linear-gradient(135deg, CanvasText 0 3px, Canvas 3px 6px);\n forced-color-adjust: none;\n }\n }\n}\n","import type { ComponentPropsWithRef, ReactElement } from \"react\"\nimport { classNames, cssClass, defineVariants, requireText } from \"../internal/component.js\"\nimport styles from \"./LimitTrack.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\nexport const RLY_LIMIT_TRACK_VARIANTS = defineVariants({\n size: {\n default: {\n className: style(\"defaultSize\"),\n purpose: \"A limit beside its numbers\",\n tokens: [\"space-12\", \"radius-tag\"]\n },\n slim: { className: style(\"slim\"), purpose: \"A limit inside a dense row\", tokens: [\"space-6\", \"radius-tag\"] }\n }\n})\nexport const RLY_LIMIT_TRACK_DEFAULT_VARIANTS = defineVariants({ size: \"default\" })\nexport type RlyLimitTrackSize = keyof typeof RLY_LIMIT_TRACK_VARIANTS.size\n/** How full a limit is: no reading, comfortable, past the near mark, or at the limit. */\nexport type RlyLimitTrackTone = \"unknown\" | \"ok\" | \"near\" | \"full\"\n\n/** A reading that is not a finite number (for example a failed division) is no reading at all. */\nconst readingOf = (value: number | null): number | null => (value !== null && Number.isFinite(value) ? value : null)\n\nconst requireFinite = (value: number, label: string): number => {\n if (!Number.isFinite(value)) throw new Error(`${label} must be a finite number`)\n return value\n}\n\n/**\n * Tone of a reading in percent against the near mark; 100% and above is full, a non-finite reading\n * is unknown, and a non-finite near mark throws, as it does on the component.\n */\nexport const limitTrackTone = (value: number | null, near: number): RlyLimitTrackTone => {\n const mark = requireFinite(near, \"limitTrackTone near\")\n const reading = readingOf(value)\n return reading === null ? \"unknown\" : reading >= 100 ? \"full\" : reading >= mark ? \"near\" : \"ok\"\n}\n\nconst percent = (value: number): number => Math.min(100, Math.max(0, value))\n\ntype LimitTrackBaseProps = Omit<ComponentPropsWithRef<\"span\">, \"aria-label\" | \"children\" | \"role\">\nexport type LimitTrackProps = LimitTrackBaseProps & {\n /**\n * Latest reading in percent of the limit; `null` when there is none. Values past 100 fill the track.\n * A non-finite value is drawn and announced as no reading.\n */\n readonly value: number | null\n /** Where the caller expects the limit to stand later (for example at its reset), in percent. Non-finite draws none. */\n readonly projected?: number\n /** The near-limit mark in percent. Defaults to 80; a non-finite mark throws. */\n readonly near?: number\n /** The reading is old: it says how full the limit was, not how full it is. */\n readonly stale?: boolean\n readonly size?: RlyLimitTrackSize\n} & (\n | { readonly decorative?: true; readonly label?: never; readonly valueText?: never }\n | { readonly decorative: false; readonly label: string; readonly valueText: string }\n )\n\n/**\n * A 0–100% limit track. The solid fill is the latest reading, a dotted extension shows a projected\n * level the caller computed, and a hairline marks the near threshold. A stale reading is hatched.\n * Decorative by default, because the caller prints the number beside it. A decorative track hides\n * everything it draws, so that adjacent text must also say when the reading is old and what the\n * projection is (for example \"61%, old reading\" or \"84%, about 103% at reset\"). Pass\n * `decorative={false}` with a label and the caller's own words for the value to expose it as a meter.\n * An unknown reading draws a faint full-width hatch in a dashed edge, never an empty (0%) track, and\n * when announced is a named image with the label and value description, without a numeric range.\n */\nexport const LimitTrack = ({\n className,\n decorative = true,\n label,\n near = 80,\n projected,\n size = RLY_LIMIT_TRACK_DEFAULT_VARIANTS.size,\n stale = false,\n value: rawValue,\n valueText,\n ...props\n}: LimitTrackProps): ReactElement => {\n const value = readingOf(rawValue)\n const nearMark = requireFinite(near, \"LimitTrack near\")\n // An explicit `decorative={false}` is a promise to announce the track; a missing label or value\n // text (possible from untyped callers) throws instead of quietly hiding it.\n const accessible = !decorative\n const accessibleLabel = accessible ? requireText(label ?? \"\", \"LimitTrack label\") : undefined\n const accessibleValueText = accessible ? requireText(valueText ?? \"\", \"LimitTrack valueText\") : undefined\n const meter = accessible && value !== null\n const projection =\n value !== null && projected !== undefined && Number.isFinite(projected) && projected > value\n ? { start: percent(value), length: percent(projected) - percent(value) }\n : null\n return (\n <span\n {...props}\n aria-hidden={accessible ? undefined : \"true\"}\n aria-label={accessible && !meter ? `${accessibleLabel}: ${accessibleValueText}` : accessibleLabel}\n aria-valuemax={meter ? 100 : undefined}\n aria-valuemin={meter ? 0 : undefined}\n aria-valuenow={meter && value !== null ? percent(value) : undefined}\n aria-valuetext={meter ? accessibleValueText : undefined}\n className={classNames(style(\"root\"), RLY_LIMIT_TRACK_VARIANTS.size[size].className, className)}\n data-stale={stale ? \"true\" : undefined}\n data-tone={limitTrackTone(value, nearMark)}\n role={accessible ? (meter ? \"meter\" : \"img\") : undefined}\n >\n {value === null ? null : (\n <span className={style(\"fill\")} data-part=\"fill\" style={{ inlineSize: `${percent(value)}%` }} />\n )}\n {projection === null ? null : (\n <span\n className={style(\"projection\")}\n data-part=\"projection\"\n style={{ inlineSize: `${projection.length}%`, insetInlineStart: `${projection.start}%` }}\n />\n )}\n <span\n className={style(\"near\")}\n data-part=\"near\"\n style={{ insetInlineStart: `min(${percent(nearMark)}%, 100% - 1px)` }}\n />\n </span>\n )\n}\n","@layer rly.components {\n .root {\n align-items: flex-start;\n /* Every tone keeps an edge, so the box survives forced colors, which drop backgrounds. */\n background: var(--rly-color-surface-1);\n border: 1px solid var(--rly-notice-ink, var(--rly-color-border-1));\n color: var(--rly-color-text-1);\n border-radius: var(--rly-radius-control);\n box-sizing: border-box;\n display: flex;\n flex-wrap: wrap;\n font: var(--rly-type-body-weight) var(--rly-type-body-size) / var(--rly-type-body-line-height)\n var(--rly-type-body-font);\n /* Row gap absorbs the action's negative block margin when it wraps below the message. */\n gap: var(--rly-space-16) var(--rly-space-12);\n margin: var(--rly-space-0);\n max-inline-size: 100%;\n padding: var(--rly-space-12);\n }\n\n /*\n * The tone colours the icon and the even border; the message stays in text ink on the plain\n * surface, so a notice never reads as a coloured sentence or a tinted pill.\n */\n .neutral {\n --rly-notice-ink: var(--rly-color-text-2);\n }\n .positive {\n --rly-notice-ink: var(--rly-color-success-ink);\n }\n .critical {\n --rly-notice-ink: var(--rly-color-blocked-ink);\n }\n .caution {\n --rly-notice-ink: var(--rly-color-held-ink);\n }\n .progress {\n --rly-notice-ink: var(--rly-color-deploying-ink);\n }\n\n .icon {\n color: var(--rly-notice-ink, var(--rly-color-text-2));\n display: inline-flex;\n flex: none;\n /* Center the 16px glyph on the first line box. */\n padding-block-start: calc((1lh - 16px) / 2);\n }\n\n .lead {\n align-items: flex-start;\n display: flex;\n flex: 1 1 13.3em;\n gap: var(--rly-space-12);\n min-inline-size: var(--rly-space-0);\n }\n\n .message {\n flex: 1 1 0;\n min-inline-size: var(--rly-space-0);\n overflow-wrap: break-word;\n }\n .message > :first-child {\n margin-block-start: var(--rly-space-0);\n }\n .message > :last-child {\n margin-block-end: var(--rly-space-0);\n }\n\n .action {\n align-items: center;\n display: flex;\n flex-wrap: wrap;\n gap: var(--rly-space-8);\n /* Centre a compact control on the first text line without growing one-line notices. */\n margin-block: calc((1lh - var(--rly-control-height-dense)) / 2);\n margin-inline-start: auto;\n }\n}\n","import type { ComponentPropsWithRef, ReactElement, ReactNode } from \"react\"\nimport { Icon, type RlyIconName } from \"../foundations/Icon.js\"\nimport { classNames, cssClass, defineVariants } from \"../internal/component.js\"\nimport styles from \"./Notice.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\n\nexport const RLY_NOTICE_VARIANTS = defineVariants({\n tone: {\n neutral: {\n className: style(\"neutral\"),\n purpose: \"Neutral context\",\n tokens: [\"color-text-2\", \"color-border-1\"]\n },\n positive: {\n className: style(\"positive\"),\n purpose: \"Completed outcome\",\n tokens: [\"color-success-ink\"]\n },\n critical: {\n className: style(\"critical\"),\n purpose: \"Failure that needs attention\",\n tokens: [\"color-blocked-ink\"]\n },\n caution: {\n className: style(\"caution\"),\n purpose: \"Limitation or warning\",\n tokens: [\"color-held-ink\"]\n },\n progress: {\n className: style(\"progress\"),\n purpose: \"Work in progress\",\n tokens: [\"color-deploying-ink\"]\n }\n }\n})\n\nexport const RLY_NOTICE_DEFAULT_VARIANTS = defineVariants({ tone: \"neutral\" })\nexport type RlyNoticeTone = keyof typeof RLY_NOTICE_VARIANTS.tone\nexport type RlyNoticeAnnouncement = \"off\" | \"polite\" | \"assertive\"\n\n// Neutral encodes nothing, so it carries no glyph unless the caller asks for one.\nconst toneIcons = {\n neutral: undefined,\n positive: \"check\",\n critical: \"alert\",\n caution: \"clock\",\n progress: \"loader\"\n} satisfies Readonly<Record<RlyNoticeTone, RlyIconName | undefined>>\n\nexport type NoticeProps = Omit<ComponentPropsWithRef<\"div\">, \"aria-live\" | \"children\"> & {\n readonly action?: ReactNode\n readonly announce?: RlyNoticeAnnouncement\n readonly children: ReactNode\n readonly icon?: RlyIconName\n readonly tone?: RlyNoticeTone\n}\n\n/**\n * Say one sentence of context or outcome inline, between controls and content.\n * Use `StatePanel` instead when the state needs a title and replaces a region.\n * The caller owns lifecycle: there is no dismiss control.\n *\n * The tone icon is decorative, so `children` must state the tone in words\n * (\"Sync failed: …\"), not rely on color and glyph.\n *\n * `announce` makes the notice a live region. A polite status region reliably announces\n * changes only once it is already mounted: mount it persistently and swap its children.\n * An assertive alert may announce as soon as it is inserted. Keep `announce=\"off\"`\n * for static text.\n *\n * @example\n * <Notice tone=\"caution\">Jira is read-only for this week.</Notice>\n * <Notice announce=\"assertive\" tone=\"critical\" action={<Button size=\"compact\">Retry</Button>}>\n * Clockify rejected the entry.\n * </Notice>\n */\nexport const Notice = ({\n action,\n announce = \"off\",\n children,\n className,\n icon,\n tone = \"neutral\",\n ...props\n}: NoticeProps): ReactElement => {\n const glyph = icon ?? toneIcons[tone]\n // An announcing region owns its role; otherwise the caller's role (for example \"note\") stands.\n const role = announce === \"assertive\" ? \"alert\" : announce === \"polite\" ? \"status\" : props.role\n\n return (\n <div\n {...props}\n aria-live={announce === \"off\" ? undefined : announce}\n className={classNames(style(\"root\"), RLY_NOTICE_VARIANTS.tone[tone].className, className)}\n role={role}\n >\n {/* Icon and message never separate; only the action wraps below them. */}\n <div className={style(\"lead\")}>\n {glyph === undefined ? null : (\n <span aria-hidden=\"true\" className={style(\"icon\")}>\n <Icon decorative name={glyph} size=\"small\" />\n </span>\n )}\n <div className={style(\"message\")}>{children}</div>\n </div>\n {action === undefined ? null : <div className={style(\"action\")}>{action}</div>}\n </div>\n )\n}\n","import type { RlySeries } from \"../primitives/ChartLegend.js\"\n\n/** One series' value in one column. */\nexport interface RlyChartSegment {\n readonly id: string\n readonly series: RlySeries\n /** A non-negative finite amount; zero, negative and non-finite values (`NaN`, ±Infinity) draw nothing. */\n readonly value: number\n}\n\n/** One period on the time axis, in epoch milliseconds, with its stacked values. */\nexport interface RlyChartColumn {\n readonly start: number\n readonly end: number\n readonly segments: ReadonlyArray<RlyChartSegment>\n}\n\n/** Consecutive columns drawn as one bar: `first`..`last` are column indices. */\nexport interface RlyChartBin {\n readonly first: number\n readonly last: number\n readonly start: number\n readonly end: number\n readonly total: number\n readonly segments: ReadonlyArray<RlyChartSegment & { readonly offset: number }>\n}\n\n/** An inclusive range of column indices. */\nexport interface RlyChartSelection {\n readonly from: number\n readonly to: number\n}\n\n/** An axis label: at a bin's start, or the one end-anchored label at the axis end. */\nexport type RlyChartTick = { readonly anchor: \"start\"; readonly index: number } | { readonly anchor: \"end\" }\n\n/**\n * Bin sizes that divide a day evenly. Bins group every N columns, so for hourly columns starting on\n * an hour boundary they line up with clock hours; an offset start, gaps or a DST day shift them.\n */\nconst BIN_SIZES: ReadonlyArray<number> = [1, 2, 3, 6, 12, 24]\n\nconst DAY = 24\n\n/** Where each bin starts, in column indices; a short trailing remainder joins the bin before it. */\nconst groupStarts = (count: number, size: number): ReadonlyArray<number> => {\n const starts: Array<number> = []\n for (let first = 0; first < count; first += size) starts.push(first)\n if (count % size > 0 && starts.length > 1) starts.pop()\n return starts\n}\n\n/** Fail loudly on columns that cannot share one time axis: each must start at or after the previous end. */\nexport const validateColumns = (columns: ReadonlyArray<RlyChartColumn>): void => {\n for (const [index, column] of columns.entries()) {\n const previous = columns[index - 1]\n if (column.end < column.start || (previous !== undefined && column.start < previous.end)) {\n throw new Error(`StackedBars columns must be in time order without overlaps; column ${index} is not`)\n }\n }\n}\n\n/**\n * One stack order for the whole chart: each series id in the order it first appears across all\n * columns. Every bin stacks in this order, so a series keeps its place from bar to bar.\n */\nexport const stackOrder = (columns: ReadonlyArray<RlyChartColumn>): ReadonlyMap<string, number> => {\n const order = new Map<string, number>()\n for (const column of columns) {\n for (const segment of column.segments) if (!order.has(segment.id)) order.set(segment.id, order.size)\n }\n return order\n}\n\n/** The narrowest bar, in pixels, that binning `columns` by `size` draws on the shared time axis. */\nconst narrowestBar = (columns: ReadonlyArray<RlyChartColumn>, size: number, width: number): number => {\n const from = columns[0]?.start ?? 0\n const span = Math.max(1, (columns[columns.length - 1]?.end ?? from) - from)\n const starts = groupStarts(columns.length, size)\n // A loop, not Math.min(...), so a long history (150,000 columns) cannot overflow the call stack.\n let narrowest = Number.POSITIVE_INFINITY\n for (const [index, first] of starts.entries()) {\n const last = (starts[index + 1] ?? columns.length) - 1\n narrowest = Math.min(narrowest, (((columns[last]?.end ?? from) - (columns[first]?.start ?? from)) / span) * width)\n }\n return narrowest\n}\n\n/**\n * The smallest bin size whose every bar, measured on the shared time axis, is at least `minBar`\n * pixels wide, so uneven or sparse periods are measured as drawn. Past a day per bar it grows in\n * whole days (24 columns at a time); failing all, one bin holds everything.\n */\nexport const chooseBinSize = (width: number, columns: ReadonlyArray<RlyChartColumn>, minBar = 6): number => {\n if (columns.length === 0) return 1\n const preferred = BIN_SIZES.find((size) => narrowestBar(columns, size, width) >= minBar)\n if (preferred !== undefined) return preferred\n // Whole days, smallest first, so the finest size that keeps every bar wide enough wins.\n for (let days = 2; days * DAY < columns.length; days += 1) {\n if (narrowestBar(columns, days * DAY, width) >= minBar) return days * DAY\n }\n return columns.length\n}\n\n/**\n * Per bin, the factor that turns its total into a rate per nominal bin (`size` columns of average\n * length), so a folded or longer bin stands as tall as its spending rate, not its raw sum. Bar areas\n * then match totals on the time-proportional axis.\n */\nexport const binRates = (\n bins: ReadonlyArray<RlyChartBin>,\n columns: ReadonlyArray<RlyChartColumn>,\n size: number\n): ReadonlyArray<number> => {\n // The mean of the columns' own lengths, so a gap between periods never inflates a rate.\n const average = Math.max(1, columns.reduce((sum, column) => sum + Math.max(0, column.end - column.start), 0)) /\n Math.max(1, columns.length)\n return bins.map((bin) => (average * size) / Math.max(1, bin.end - bin.start))\n}\n\n/**\n * Group columns into bins of `size`, merging segments by id and stacking every bin in the chart's\n * one `stackOrder`. A short trailing remainder joins the bin before it, so the last bar is never\n * narrower than the rest.\n */\nexport const binColumns = (columns: ReadonlyArray<RlyChartColumn>, size: number): ReadonlyArray<RlyChartBin> => {\n const bins: Array<RlyChartBin> = []\n const order = stackOrder(columns)\n const starts = groupStarts(columns.length, size)\n for (const [index, first] of starts.entries()) {\n const group = columns.slice(first, starts[index + 1] ?? columns.length)\n const values = new Map<string, RlyChartSegment>()\n for (const segment of group.flatMap((column) => column.segments)) {\n // A failed reading (NaN, ±Infinity) is no reading, so it cannot poison the totals or the scale.\n if (!Number.isFinite(segment.value) || segment.value <= 0) continue\n // The first-seen segment keeps its fields; later ones only add their value.\n const seen = values.get(segment.id)\n values.set(segment.id, seen === undefined ? segment : { ...seen, value: seen.value + segment.value })\n }\n const ordered = [...values.values()].sort(\n (left, right) => (order.get(left.id) ?? 0) - (order.get(right.id) ?? 0)\n )\n const segments = ordered.reduce<Array<RlyChartBin[\"segments\"][number]>>(\n (stacked, segment) => [...stacked, { ...segment, offset: stacked.reduce((sum, { value }) => sum + value, 0) }],\n []\n )\n bins.push({\n end: group[group.length - 1]?.end ?? 0,\n first,\n last: first + group.length - 1,\n segments,\n start: group[0]?.start ?? 0,\n total: segments.reduce((sum, { value }) => sum + value, 0)\n })\n }\n return bins\n}\n\n/** Select one bin, or with `extend` grow an existing selection to cover it. Unknown bins change nothing. */\nexport const selectBin = (\n selection: RlyChartSelection | null,\n bins: ReadonlyArray<RlyChartBin>,\n index: number,\n extend: boolean\n): RlyChartSelection | null => {\n const bin = bins[index]\n if (bin === undefined) return selection\n if (!extend || selection === null) return { from: bin.first, to: bin.last }\n return { from: Math.min(selection.from, bin.first), to: Math.max(selection.to, bin.last) }\n}\n\n/** The bin a navigation key moves focus to, or `null` for any other key. */\nexport const moveFocus = (key: string, current: number, last: number): number | null => {\n const clamp = (next: number): number => Math.max(0, Math.min(last, next))\n switch (key) {\n case \"ArrowLeft\":\n return clamp(current - 1)\n case \"ArrowRight\":\n return clamp(current + 1)\n case \"Home\":\n return 0\n case \"End\":\n return last\n default:\n return null\n }\n}\n\n/**\n * Ticks at least `labelWidth` apart, from each bin's start in pixels on the shared time axis, so\n * uneven bins never crowd their labels. The last bin always gets an end-anchored tick, so the axis\n * says where it ends without a label clipping at the edge; ticks crowding it are dropped. One bin\n * gets its start and end when both fit, else its start alone.\n */\nexport const chartTicks = (\n starts: ReadonlyArray<number>,\n width: number,\n labelWidth: number\n): ReadonlyArray<RlyChartTick> => {\n if (starts.length === 0) return []\n if (starts.length === 1) {\n return width >= 2 * labelWidth\n ? [{ anchor: \"start\", index: 0 }, { anchor: \"end\" }]\n : [{ anchor: \"start\", index: 0 }]\n }\n // Start ticks leave room for the end label, so no bin is labelled twice.\n const regular = starts.reduce<ReadonlyArray<{ readonly anchor: \"start\"; readonly index: number }>>(\n (ticks, x, index) => {\n const previous = ticks.at(-1)\n const previousX = previous === undefined ? Number.NEGATIVE_INFINITY : (starts[previous.index] ?? 0)\n return x - previousX >= labelWidth && x + labelWidth <= width - labelWidth\n ? [...ticks, { anchor: \"start\", index }]\n : ticks\n },\n []\n )\n return [...regular, { anchor: \"end\" }]\n}\n","@layer rly.components {\n /* `--rly-stacked-bars-gap` colours the gap between bars; a chart on another surface sets it to that background. */\n .root {\n display: grid;\n gap: var(--rly-space-8);\n min-inline-size: 0;\n }\n .band {\n display: grid;\n gap: var(--rly-space-2);\n }\n .bandLabel,\n .scale,\n .tick {\n color: var(--rly-color-text-2);\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n }\n .bandPlot {\n background: var(--rly-color-surface-2);\n block-size: var(--rly-space-24);\n display: block;\n inline-size: 100%;\n }\n .level {\n fill: var(--rly-color-text-3);\n }\n .level[data-tone=\"near\"] {\n fill: var(--rly-color-held-ink);\n }\n .level[data-tone=\"full\"] {\n fill: var(--rly-color-blocked-ink);\n }\n .unknown {\n fill: var(--rly-color-surface-3);\n }\n .near {\n stroke: var(--rly-color-text-3);\n stroke-dasharray: 2 3;\n vector-effect: non-scaling-stroke;\n }\n .plot {\n border-radius: var(--rly-radius-tag);\n position: relative;\n }\n .plot:focus-visible {\n outline: var(--rly-focus-ring-width) solid var(--rly-color-focus);\n outline-offset: var(--rly-focus-ring-offset);\n }\n .bars {\n block-size: 100%;\n display: block;\n inline-size: 100%;\n overflow: visible;\n }\n /* A 2px background-coloured edge (1px each side) separates neighbouring bars and stacked segments at any scale. */\n .segment {\n stroke: var(--rly-stacked-bars-gap, var(--rly-color-surface-1));\n stroke-width: 2px;\n vector-effect: non-scaling-stroke;\n }\n .hit {\n cursor: pointer;\n fill: transparent;\n }\n .selection {\n fill: var(--rly-color-surface-3);\n }\n /*\n * The selection's outline, drawn over the bars, so a selected bar shows it at any height: a 2px\n * ink line on a 6px background halo, which stays visible where the bar is the ink colour too.\n */\n .selectionHalo {\n fill: none;\n pointer-events: none;\n stroke: var(--rly-stacked-bars-gap, var(--rly-color-surface-1));\n stroke-width: 6px;\n vector-effect: non-scaling-stroke;\n }\n .selectionEdge {\n fill: none;\n pointer-events: none;\n stroke: var(--rly-color-text-1);\n stroke-width: 2px;\n vector-effect: non-scaling-stroke;\n }\n /*\n * The window shading sits under the selection and bars; its dashed edges mark where it starts and\n * ends. Neutral ink, not the focus colour, so it never reads as a focus ring.\n */\n .window {\n fill: color-mix(in srgb, var(--rly-color-text-3) 12%, transparent);\n stroke: var(--rly-color-text-2);\n stroke-dasharray: 3 3;\n stroke-width: 1px;\n vector-effect: non-scaling-stroke;\n }\n .windowEdge {\n fill: none;\n pointer-events: none;\n stroke: var(--rly-color-text-2);\n stroke-dasharray: 3 3;\n stroke-width: 1px;\n vector-effect: non-scaling-stroke;\n }\n .keys {\n display: flex;\n flex-wrap: wrap;\n gap: var(--rly-space-4) var(--rly-space-16);\n list-style: none;\n margin: 0;\n padding: 0;\n }\n .windowKey {\n align-items: center;\n color: var(--rly-color-text-2);\n display: flex;\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n gap: var(--rly-space-6);\n margin: 0;\n }\n .windowSwatch {\n background: color-mix(in srgb, var(--rly-color-text-3) 12%, transparent);\n block-size: var(--rly-space-12);\n border: 1px dashed var(--rly-color-text-2);\n flex: none;\n inline-size: var(--rly-space-12);\n }\n .nearSwatch {\n block-size: 0;\n border-block-start: 1px dashed var(--rly-color-text-3);\n flex: none;\n inline-size: var(--rly-space-12);\n }\n .unknownSwatch {\n background: var(--rly-color-surface-3);\n block-size: var(--rly-space-12);\n border: 1px solid var(--rly-color-border-2);\n flex: none;\n inline-size: var(--rly-space-12);\n }\n .focusRing {\n fill: none;\n pointer-events: none;\n stroke: none;\n vector-effect: non-scaling-stroke;\n }\n .plot:focus-visible .focusRing {\n stroke: var(--rly-color-focus);\n stroke-width: var(--rly-focus-ring-width);\n }\n .axis {\n block-size: var(--rly-type-meta-line-height);\n position: relative;\n }\n /*\n * A label never runs past the axis. Start labels are spaced by their measured width and stay on\n * one line; the end label wraps when it alone is wider than the chart, and the axis grows to fit.\n */\n .tick {\n inset-block-start: 0;\n max-inline-size: 100%;\n position: absolute;\n white-space: nowrap;\n }\n .tick[data-anchor=\"end\"] {\n inline-size: max-content;\n text-align: end;\n white-space: normal;\n }\n .barsClip {\n clip-path: inset(0);\n }\n .hidden {\n block-size: 1px;\n clip-path: inset(50%);\n inline-size: 1px;\n margin: 0;\n overflow: hidden;\n position: absolute;\n white-space: nowrap;\n }\n @media (forced-colors: active) {\n .segment {\n stroke: Canvas;\n }\n .window,\n .windowEdge,\n .selectionEdge {\n fill: none;\n stroke: CanvasText;\n }\n .selection {\n fill: none;\n }\n .selectionHalo {\n stroke: Canvas;\n }\n .windowSwatch {\n background: none;\n border-color: CanvasText;\n }\n /* No-reading stretches lose their fill; a dotted outline keeps them apart from the empty track. */\n .unknown {\n fill: none;\n stroke: CanvasText;\n stroke-dasharray: 1 3;\n vector-effect: non-scaling-stroke;\n }\n .nearSwatch,\n .unknownSwatch {\n border-color: CanvasText;\n }\n .unknownSwatch {\n background: none;\n border-style: dotted;\n }\n }\n\n /* The Storybook forced-colours toolbar draws the same overrides as the real mode. */\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .segment {\n stroke: Canvas;\n }\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .window,\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .windowEdge,\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .selectionEdge {\n fill: none;\n stroke: CanvasText;\n }\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .selection {\n fill: none;\n }\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .selectionHalo {\n stroke: Canvas;\n }\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .windowSwatch {\n background: none;\n border-color: CanvasText;\n }\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .unknown {\n fill: none;\n stroke: CanvasText;\n stroke-dasharray: 1 3;\n vector-effect: non-scaling-stroke;\n }\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .nearSwatch,\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .unknownSwatch {\n border-color: CanvasText;\n }\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .unknownSwatch {\n background: none;\n border-style: dotted;\n }\n}\n","import type { ComponentPropsWithRef, KeyboardEvent, ReactElement, Ref, RefCallback } from \"react\"\nimport { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from \"react\"\nimport { classNames, cssClass, requireText } from \"../internal/component.js\"\nimport * as Predicate from \"../internal/predicates.js\"\nimport {\n binColumns,\n binRates,\n chartTicks,\n chooseBinSize,\n moveFocus,\n type RlyChartColumn,\n type RlyChartSelection,\n selectBin,\n validateColumns\n} from \"../internal/chart.js\"\nimport { rlySeriesColor } from \"./ChartLegend.js\"\nimport styles from \"./StackedBars.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\nexport type { RlyChartBin, RlyChartColumn, RlyChartSegment, RlyChartSelection } from \"../internal/chart.js\"\n\n/** A level over time above the bars, on the same axis; `level: null` is a stretch with no reading. */\nexport interface RlyStepBand {\n readonly id: string\n readonly label: string\n readonly segments: ReadonlyArray<{ readonly from: number; readonly to: number; readonly level: number | null }>\n /** A dashed mark at `level` percent, named in the key under the axis by `label` (\"Near the limit, 80%\"). */\n readonly near?: RlyBandMark\n}\n\n/** A level worth marking on a band, with the key text that names it. */\nexport interface RlyBandMark {\n readonly level: number\n readonly label: string\n}\n\n/** A stretch of the time axis to shade behind the bars and bands, named in a key under the axis. */\nexport interface RlyChartWindow {\n readonly from: number\n readonly to: number\n /** What the stretch is, for example \"Current 5-hour window, resets 14:57\". */\n readonly label: string\n}\n\ntype StackedBarsBaseProps = Omit<ComponentPropsWithRef<\"div\">, \"aria-label\" | \"children\" | \"onChange\">\nexport type StackedBarsProps = StackedBarsBaseProps & {\n /** Names the chart, for example \"Spend by booking\". */\n readonly label: string\n /** How to read and operate the chart, in the caller's words; read after the label. */\n readonly instructions: string\n /**\n * Periods in time order, none overlapping (gaps are fine); anything else throws\n * an error naming the column. Bins group every N columns, so hourly columns starting on the hour bin\n * on clock hours.\n */\n readonly columns: ReadonlyArray<RlyChartColumn>\n /** Bands of limit levels drawn above the bars, sharing their time axis. */\n readonly bands?: ReadonlyArray<RlyStepBand>\n /** A stretch of time to shade across the bands and bars, such as the current limit window. */\n readonly window?: RlyChartWindow\n /** Key text for band stretches with no reading (\"No reading\"); required when any band has one. */\n readonly noReadingLabel?: string\n /**\n * The caption for the scale: the tallest bar's rate per `binSize` columns. Bars plot rates, so a\n * folded or longer bin reads true against \"per N hours\".\n */\n readonly formatScale: (max: number, binSize: number) => string\n /** The axis label for an instant: a bin's start, or the axis end for the right-hand label. */\n readonly formatTick: (at: number, binSize: number) => string\n readonly selection: RlyChartSelection | null\n readonly onSelectionChange: (selection: RlyChartSelection | null) => void\n /** What the selection means, announced politely once a selection the user made settles. */\n readonly describeSelection: (selection: RlyChartSelection | null) => string\n /** Plot height in pixels, without bands and axis; never under 24, since every bar is a pointer target. */\n readonly height?: number\n}\n\n/** The room an axis label gets until the rendered labels have been measured. */\nconst LABEL_WIDTH = 72\nconst LABEL_GAP = 8\nconst ANNOUNCE_AFTER = 500\nconst MIN_TARGET = 24\n\n/**\n * Hand the element to a caller's object or callback ref and return how to detach it: a React 19\n * callback ref's own cleanup when it returns one, otherwise the ref called (or set) with null.\n */\nconst attachRef = (ref: Ref<HTMLDivElement> | undefined, element: HTMLDivElement): (() => void) => {\n if (Predicate.isFunction(ref)) {\n const cleanup = ref(element)\n return Predicate.isFunction(cleanup) ? cleanup : () => ref(null)\n }\n if (ref === null || ref === undefined) return () => undefined\n ref.current = element\n return () => {\n ref.current = null\n }\n}\n\n/** Measures the root's inline size while still handing the root to the caller's ref. */\nconst useInlineSize = (\n fallback: number,\n callerRef: Ref<HTMLDivElement> | undefined\n): readonly [number, RefCallback<HTMLDivElement>] => {\n const [size, setSize] = useState(fallback)\n const ref = useCallback(\n (element: HTMLDivElement | null) => {\n if (element === null) return\n const detach = attachRef(callerRef, element)\n const observer = new ResizeObserver(([entry]) => {\n if (entry !== undefined) setSize(entry.contentRect.width)\n })\n observer.observe(element)\n return () => {\n observer.disconnect()\n detach()\n }\n },\n [callerRef]\n )\n return [size, ref]\n}\n\n/** A stretch of the plot on the shared 0–1000 time scale. */\ninterface AxisSpan {\n readonly x: number\n readonly width: number\n}\n\n/** A band level as a drawable percentage: clamped to 0–100, and a non-finite reading is no reading. */\nconst percent = (level: number): number | null => (Number.isFinite(level) ? Math.min(100, Math.max(0, level)) : null)\n\n/** A near mark must be a finite percentage; it is clamped onto the band so its line stays drawable. */\nconst nearLevel = (level: number): number => {\n if (!Number.isFinite(level)) throw new Error(\"StackedBars near level must be a finite percentage\")\n return Math.min(100, Math.max(0, level))\n}\n\n/** Where an instant falls on the time axis, from 0 to 1, clamped to the drawn range. */\nconst axisFraction = (at: number, from: number, to: number): number =>\n Math.max(0, Math.min(1, (at - from) / Math.max(1, to - from)))\n\nconst Band = ({\n band,\n from,\n to,\n window\n}: {\n readonly band: RlyStepBand\n readonly from: number\n readonly to: number\n readonly window: RlyChartWindow | undefined\n}) => {\n const x = (at: number): number => axisFraction(at, from, to) * 1000\n const near = band.near === undefined ? undefined : nearLevel(band.near.level)\n return (\n <div className={style(\"band\")} data-band={band.id}>\n <span className={style(\"bandLabel\")}>{requireText(band.label, \"StackedBars band label\")}</span>\n <svg aria-hidden=\"true\" className={style(\"bandPlot\")} preserveAspectRatio=\"none\" viewBox=\"0 0 1000 100\">\n {window === undefined ? null : (\n <rect\n className={style(\"window\")}\n data-part=\"window\"\n height={100}\n width={Math.max(0, x(window.to) - x(window.from))}\n x={x(window.from)}\n />\n )}\n {band.segments.map((segment, index) => {\n const left = x(segment.from)\n const width = x(segment.to) - left\n if (width <= 0) return null\n const reading = segment.level === null ? null : percent(segment.level)\n if (reading === null) {\n return (\n <rect className={style(\"unknown\")} height={100} key={`${index}:${segment.from}`} width={width} x={left} />\n )\n }\n const level = reading\n return (\n <rect\n className={style(\"level\")}\n data-tone={level >= 100 ? \"full\" : near !== undefined && level >= near ? \"near\" : \"ok\"}\n height={level}\n key={`${index}:${segment.from}`}\n width={width}\n x={left}\n y={100 - level}\n />\n )\n })}\n {near === undefined ? null : (\n <line className={style(\"near\")} x1={0} x2={1000} y1={100 - near} y2={100 - near} />\n )}\n {/* The window's edges again over the levels, so a full or unknown stretch never hides it. */}\n {window === undefined ? null : (\n <rect\n className={style(\"windowEdge\")}\n data-part=\"window-edge\"\n height={100}\n width={Math.max(0, x(window.to) - x(window.from))}\n x={x(window.from)}\n />\n )}\n </svg>\n </div>\n )\n}\n\n/**\n * Stacked values per period on a time axis, with optional limit bands above. Bars, bands, the window\n * and the selection share one time scale, so a short final bin is drawn narrower. Narrow containers\n * bin periods so every bar's hit area stays at least 24px wide, a full pointer target (the drawn\n * fill is 2px narrower, for the gap); the selection keeps its columns across rebinning.\n * One tab stop: ←/→ move and select, Shift extends, Home/End jump, Escape clears. Click selects;\n * Shift+click, or a second touch tap elsewhere, extends. The SVG is hidden from assistive technology,\n * so callers render the same data beside it: a table at a readable resolution (a row per day for a\n * week of hours), a table of each band's intervals, and a `describeSelection` that names every\n * series' value in the span, so arrowing through the plot reaches each period's numbers.\n */\nexport const StackedBars = ({\n bands = [],\n className,\n columns,\n describeSelection,\n formatScale,\n formatTick,\n height = 180,\n instructions,\n label,\n noReadingLabel,\n onSelectionChange,\n ref: callerRef,\n selection,\n window,\n ...props\n}: StackedBarsProps): ReactElement => {\n validateColumns(columns)\n const [width, ref] = useInlineSize(720, callerRef)\n const instructionsId = useId()\n // Bars are pointer targets, so each is at least 24px wide (WCAG 2.2 target size).\n const binSize = chooseBinSize(width, columns, MIN_TARGET)\n const bins = useMemo(() => binColumns(columns, binSize), [columns, binSize])\n // Heights are rates per nominal bin, so a longer (folded) bin is not taller just for holding more time.\n const rates = binRates(bins, columns, binSize)\n const max = Math.max(0, ...bins.map(({ total }, index) => total * (rates[index] ?? 1)))\n // Everything the bands draw is named in the key: each distinct near mark, and \"no reading\" if any.\n const nearLabels = [\n ...new Set(\n bands.flatMap((band) => (band.near === undefined ? [] : [requireText(band.near.label, \"StackedBars near label\")]))\n )\n ]\n const hasNoReading = bands.some((band) =>\n band.segments.some((segment) => segment.level === null || percent(segment.level) === null)\n )\n const noReading = hasNoReading\n ? requireText(noReadingLabel ?? \"\", \"StackedBars noReadingLabel (a band has a stretch with no reading)\")\n : undefined\n const axisStart = columns[0]?.start ?? 0\n const axisEnd = columns[columns.length - 1]?.end ?? axisStart\n // Ticks are spaced by the widest label actually rendered, so a long format or enlarged text\n // spreads them out instead of overlapping them.\n const [labelWidth, setLabelWidth] = useState(LABEL_WIDTH)\n const axisRef = useRef<HTMLDivElement>(null)\n const ticks = chartTicks(\n bins.map((bin) => axisFraction(bin.start, axisStart, axisEnd) * width),\n width,\n labelWidth\n )\n // The keyboard cursor is a column, so a click or a resize that rebins keeps it on the same time.\n const [cursor, setCursor] = useState<number | null>(null)\n // The first touch tap's column, so a rebin between taps still compares the same instant.\n const [pendingTap, setPendingTap] = useState<number | null>(null)\n // Only a touch tap may extend by tapping again; a mouse extends with Shift.\n const pointerType = useRef(\"mouse\")\n // The selection this chart last asked for. A different one arriving means its owner replaced it,\n // so the keyboard cursor and any half-made touch span belong to a gesture that no longer exists.\n const emitted = useRef<RlyChartSelection | null>(selection)\n // Each selection the user makes asks for one announcement; mounting and data refreshes ask for none.\n const [announceRequest, setAnnounceRequest] = useState(0)\n const emit = (next: RlyChartSelection | null): void => {\n emitted.current = next\n setAnnounceRequest((request) => request + 1)\n onSelectionChange(next)\n }\n const selectedFrom = selection?.from\n const selectedTo = selection?.to\n useEffect(() => {\n const own = emitted.current\n const replaced = own === null ? selectedFrom !== undefined : own.from !== selectedFrom || own.to !== selectedTo\n if (replaced) {\n setCursor(null)\n setPendingTap(null)\n }\n emitted.current =\n selectedFrom === undefined || selectedTo === undefined ? null : { from: selectedFrom, to: selectedTo }\n }, [selectedFrom, selectedTo])\n const [announcement, setAnnouncement] = useState(\"\")\n // Read when the announcement fires, so it names the selection the owner settled on.\n const description = useRef(\"\")\n description.current = describeSelection(selection)\n const binOf = (column: number): number => Math.min(bins.length - 1, Math.floor(column / binSize))\n const focus = cursor === null ? null : binOf(cursor)\n\n useEffect(() => {\n if (announceRequest === 0) return\n // Empty the region while the new words settle, so returning to the last announced selection is\n // announced again rather than left as an unchanged region.\n setAnnouncement(\"\")\n const timer = setTimeout(() => setAnnouncement(description.current), ANNOUNCE_AFTER)\n return () => clearTimeout(timer)\n }, [announceRequest])\n\n // A new binning or axis brings new labels; measure them afresh so shorter ones pack closer again.\n useLayoutEffect(() => {\n setLabelWidth(LABEL_WIDTH)\n }, [binSize, axisStart, axisEnd])\n\n // The end label may wrap when it is wider than the chart, so the axis grows to its tallest label.\n const [axisHeight, setAxisHeight] = useState<number | undefined>(undefined)\n useLayoutEffect(() => {\n const labels = [...(axisRef.current?.querySelectorAll<HTMLElement>(\"[data-anchor]\") ?? [])]\n const widest = Math.max(0, ...labels.map((label) => label.scrollWidth))\n if (widest + LABEL_GAP > labelWidth) setLabelWidth(widest + LABEL_GAP)\n const tallest = Math.max(0, ...labels.map((label) => label.offsetHeight))\n if (tallest > 0 && tallest !== axisHeight) setAxisHeight(tallest)\n })\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {\n if (event.key === \"Escape\") {\n if (selection === null) return\n event.preventDefault()\n setCursor(null)\n setPendingTap(null)\n emit(null)\n return\n }\n // An empty chart has nothing to move to, so the browser keeps Home, End and the arrows.\n if (bins.length === 0) return\n const current = focus ?? (selection === null ? bins.length - 1 : binOf(selection.to))\n const next = moveFocus(event.key, current, bins.length - 1)\n if (next === null) return\n event.preventDefault()\n setCursor(bins[next]?.first ?? null)\n // The keyboard now owns the anchor, so a later tap starts a new touch span.\n setPendingTap(null)\n emit(selectBin(selection, bins, next, event.shiftKey))\n }\n\n const from = columns[0]?.start ?? 0\n const to = columns[columns.length - 1]?.end ?? from\n // One time scale for everything drawn: the bands' 0–1000 viewBox, from the first column's start.\n const x = (at: number): number => axisFraction(at, from, to) * 1000\n const span = (start: number, end: number): AxisSpan => ({\n width: Math.max(0, x(end) - x(start)),\n x: x(start)\n })\n const shaded = window === undefined ? null : span(window.from, window.to)\n // The selection is drawn from its own columns, so it survives a resize that rebins them: a fill\n // behind the bars, and its edges again above them, so a tall selected bar still shows it.\n const selectionStart = selection === null ? undefined : columns[Math.max(0, selection.from)]\n const selectionEnd = selection === null ? undefined : columns[Math.min(columns.length - 1, selection.to)]\n const selected =\n selectionStart === undefined || selectionEnd === undefined ? null : span(selectionStart.start, selectionEnd.end)\n const focusedBin = focus === null ? undefined : bins[focus]\n // The ring sits inside its bin by half its 2px stroke (in viewBox units), so on the last bin it\n // never merges with the plot's own focus outline.\n const plotHeight = Math.max(MIN_TARGET, height)\n const insetX = 1000 / Math.max(1, width)\n const insetY = 100 / plotHeight\n const focusSlot = focusedBin === undefined ? null : span(focusedBin.start, focusedBin.end)\n\n return (\n <div {...props} className={classNames(style(\"root\"), className)} ref={ref}>\n {bands.map((band) => (\n <Band band={band} from={from} key={band.id} to={to} window={window} />\n ))}\n {/* Above the plot, in flow: an overlay caption was overdrawn by tall bars in a short plot. */}\n <span className={style(\"scale\")}>{formatScale(max, binSize)}</span>\n <div\n aria-describedby={instructionsId}\n aria-label={requireText(label, \"StackedBars label\")}\n aria-roledescription=\"chart\"\n className={style(\"plot\")}\n onBlur={() => setCursor(null)}\n onKeyDown={onKeyDown}\n role=\"group\"\n style={{ blockSize: `${plotHeight}px` }}\n tabIndex={0}\n >\n <svg aria-hidden=\"true\" className={style(\"bars\")} preserveAspectRatio=\"none\" viewBox=\"0 0 1000 100\">\n {shaded === null || shaded.width <= 0 ? null : (\n <rect className={style(\"window\")} data-part=\"window\" height={100} width={shaded.width} x={shaded.x} />\n )}\n {selected === null || selected.width <= 0 ? null : (\n <rect\n className={style(\"selection\")}\n data-part=\"selection\"\n height={100}\n width={selected.width}\n x={selected.x}\n />\n )}\n {/* Clipped to the plot, so the gap strokes on the outer bars never notch past its edges. */}\n <g className={style(\"barsClip\")}>\n {bins.map((bin, index) => {\n const slot = span(bin.start, bin.end)\n const inSelection = selection !== null && bin.last >= selection.from && bin.first <= selection.to\n return (\n <g\n data-bin={index}\n data-focused={focus === index ? \"true\" : undefined}\n data-selected={inSelection ? \"true\" : undefined}\n key={bin.first}\n onClick={(event) => {\n const touch = pointerType.current === \"touch\"\n // A second tap extends only a live selection; a cleared one starts a new gesture.\n const extend =\n event.shiftKey ||\n (touch &&\n selection !== null &&\n pendingTap !== null &&\n // The first tap must still anchor the live selection; a replaced one starts over.\n pendingTap >= selection.from &&\n pendingTap <= selection.to &&\n (pendingTap < bin.first || pendingTap > bin.last))\n emit(selectBin(selection, bins, index, extend))\n setCursor(bin.first)\n setPendingTap(touch && !extend ? bin.first : null)\n }}\n onPointerDown={(event) => {\n pointerType.current = event.pointerType\n }}\n >\n <rect className={style(\"hit\")} height={100} width={slot.width} x={slot.x} />\n {bin.segments.map((segment) => {\n const rate = rates[index] ?? 1\n const top = max === 0 ? 0 : (((segment.offset + segment.value) * rate) / max) * 88\n const size = max === 0 ? 0 : ((segment.value * rate) / max) * 88\n return (\n <rect\n className={style(\"segment\")}\n data-series={String(segment.series)}\n fill={rlySeriesColor(segment.series)}\n height={size}\n key={segment.id}\n width={slot.width}\n x={slot.x}\n y={100 - top}\n />\n )\n })}\n </g>\n )\n })}\n </g>\n {selected === null || selected.width <= 0 ? null : (\n <>\n {/* A background halo under the edge, so it reads as a double line on bars of any colour. */}\n <rect\n className={style(\"selectionHalo\")}\n data-part=\"selection-halo\"\n height={100}\n width={selected.width}\n x={selected.x}\n />\n <rect\n className={style(\"selectionEdge\")}\n data-part=\"selection-edge\"\n height={100}\n width={selected.width}\n x={selected.x}\n />\n </>\n )}\n {/* The window's edges again over the bars, so a narrow window stays visible where bars cover its fill. */}\n {shaded === null || shaded.width <= 0 ? null : (\n <rect\n className={style(\"windowEdge\")}\n data-part=\"window-edge\"\n height={100}\n width={shaded.width}\n x={shaded.x}\n />\n )}\n {/* One focus ring above every bar and the window's edge, so neither breaks the ring. */}\n {focusSlot === null ? null : (\n <rect\n className={style(\"focusRing\")}\n data-part=\"focus-ring\"\n height={Math.max(0, 100 - 2 * insetY)}\n width={Math.max(0, focusSlot.width - 2 * insetX)}\n x={focusSlot.x + insetX}\n y={insetY}\n />\n )}\n </svg>\n </div>\n <div\n aria-hidden=\"true\"\n className={style(\"axis\")}\n ref={axisRef}\n style={axisHeight === undefined ? undefined : { blockSize: `${axisHeight}px` }}\n >\n {ticks.map((tick) => {\n const at = tick.anchor === \"end\" ? axisEnd : bins[tick.index]?.start\n if (at === undefined) return null\n return (\n <span\n className={style(\"tick\")}\n data-anchor={tick.anchor}\n key={tick.anchor === \"end\" ? \"end\" : tick.index}\n // Physical sides, like the SVG's x axis, so labels stay under their bars in right-to-left text.\n style={tick.anchor === \"end\" ? { right: 0 } : { left: `${x(at) / 10}%` }}\n >\n {formatTick(at, binSize)}\n </span>\n )\n })}\n </div>\n {window === undefined && nearLabels.length === 0 && noReading === undefined ? null : (\n // Markerless flex lists lose list semantics in WebKit, so the role is restated.\n <ul className={style(\"keys\")} role=\"list\">\n {window === undefined ? null : (\n <li className={style(\"windowKey\")}>\n <span aria-hidden=\"true\" className={style(\"windowSwatch\")} />\n {requireText(window.label, \"StackedBars window label\")}\n </li>\n )}\n {nearLabels.map((text) => (\n <li className={style(\"windowKey\")} key={text}>\n <span aria-hidden=\"true\" className={style(\"nearSwatch\")} />\n {text}\n </li>\n ))}\n {noReading === undefined ? null : (\n <li className={style(\"windowKey\")}>\n <span aria-hidden=\"true\" className={style(\"unknownSwatch\")} />\n {noReading}\n </li>\n )}\n </ul>\n )}\n <p className={style(\"hidden\")} id={instructionsId}>\n {requireText(instructions, \"StackedBars instructions\")}\n </p>\n <p aria-live=\"polite\" className={style(\"hidden\")}>\n {announcement}\n </p>\n </div>\n )\n}\n","@layer rly.components {\n .root {\n box-sizing: border-box;\n color: var(--rly-color-text-1);\n max-inline-size: 100%;\n min-inline-size: var(--rly-space-0);\n }\n\n .tonePrimary {\n background: var(--rly-color-surface-1);\n border: 1px solid var(--rly-color-border-1);\n }\n .toneSecondary {\n background: var(--rly-color-surface-2);\n }\n .toneTertiary {\n background: var(--rly-color-surface-3);\n }\n .shapeCard {\n border-radius: var(--rly-radius-control);\n }\n .shapeGrouped {\n border-radius: var(--rly-radius-group);\n }\n .paddingNone {\n padding: var(--rly-space-0);\n }\n .paddingCompact {\n padding: var(--rly-space-16);\n }\n .paddingDefault {\n padding: var(--rly-space-24);\n }\n .paddingSpacious {\n padding: var(--rly-space-32);\n }\n\n /* Forced colours drop the tint that sets a secondary or tertiary surface apart; an edge keeps it. */\n @media (forced-colors: active) {\n .toneSecondary,\n .toneTertiary {\n border: 1px solid CanvasText;\n }\n }\n\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .toneSecondary,\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .toneTertiary {\n border: 1px solid CanvasText;\n }\n}\n","import { createElement, type ComponentPropsWithoutRef, type ReactElement, type ReactNode, type Ref } from \"react\"\nimport { classNames, cssClass, defineVariants } from \"../internal/component.js\"\nimport styles from \"./Surface.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\nexport const RLY_SURFACE_VARIANTS = defineVariants({\n tone: {\n primary: {\n className: style(\"tonePrimary\"),\n purpose: \"Primary bordered surface\",\n tokens: [\"color-surface-1\", \"color-border-1\"]\n },\n secondary: { className: style(\"toneSecondary\"), purpose: \"Quiet secondary surface\", tokens: [\"color-surface-2\"] },\n tertiary: { className: style(\"toneTertiary\"), purpose: \"Inset tertiary surface\", tokens: [\"color-surface-3\"] }\n },\n form: {\n card: { className: style(\"shapeCard\"), purpose: \"Standard card geometry\", tokens: [\"radius-control\"] },\n grouped: { className: style(\"shapeGrouped\"), purpose: \"Grouped content geometry\", tokens: [\"radius-group\"] }\n },\n padding: {\n none: { className: style(\"paddingNone\"), purpose: \"Caller-owned internal layout\", tokens: [\"space-0\"] },\n compact: { className: style(\"paddingCompact\"), purpose: \"Dense supporting content\", tokens: [\"space-16\"] },\n default: { className: style(\"paddingDefault\"), purpose: \"Standard content\", tokens: [\"space-24\"] },\n spacious: { className: style(\"paddingSpacious\"), purpose: \"Prominent grouped content\", tokens: [\"space-32\"] }\n }\n})\nexport const RLY_SURFACE_DEFAULT_VARIANTS = defineVariants({ tone: \"primary\", form: \"card\", padding: \"default\" })\nexport type RlySurfaceTone = keyof typeof RLY_SURFACE_VARIANTS.tone\nexport type RlySurfaceForm = keyof typeof RLY_SURFACE_VARIANTS.form\nexport type RlySurfacePadding = keyof typeof RLY_SURFACE_VARIANTS.padding\nexport type RlySurfaceElement = \"div\" | \"section\" | \"article\" | \"aside\"\n\ntype RefTarget<Value> = Value extends Ref<infer Target> ? Target : never\ntype ExactRef<Expected, Value> =\n Value extends Ref<Expected> ? (Expected extends RefTarget<Value> ? Value : never) : never\n\nexport type SurfaceProps<\n Element extends RlySurfaceElement = \"div\",\n ElementRef extends Ref<HTMLElementTagNameMap[Element]> = Ref<HTMLElementTagNameMap[Element]>\n> = Omit<ComponentPropsWithoutRef<Element>, \"children\" | \"color\"> & {\n readonly as?: Element\n readonly children: ReactNode\n readonly padding?: RlySurfacePadding\n readonly ref?: ExactRef<HTMLElementTagNameMap[Element], ElementRef>\n readonly form?: RlySurfaceForm\n readonly tone?: RlySurfaceTone\n}\n\n/** Render a quiet, non-interactive structural surface without elevation semantics. */\nexport const Surface = <\n const Element extends RlySurfaceElement = \"div\",\n ElementRef extends Ref<HTMLElementTagNameMap[Element]> = Ref<HTMLElementTagNameMap[Element]>\n>({\n as,\n children,\n className,\n form = \"card\",\n padding = \"default\",\n ref,\n tone = \"primary\",\n ...props\n}: SurfaceProps<Element, ElementRef>): ReactElement =>\n createElement(\n as ?? \"div\",\n {\n ...props,\n className: classNames(\n style(\"root\"),\n RLY_SURFACE_VARIANTS.tone[tone].className,\n RLY_SURFACE_VARIANTS.form[form].className,\n RLY_SURFACE_VARIANTS.padding[padding].className,\n className\n ),\n ref\n },\n children\n )\n","@layer rly.components {\n .root {\n margin: var(--rly-space-0);\n min-inline-size: var(--rly-space-0);\n overflow-wrap: break-word;\n }\n\n .verdict,\n .pageTitle,\n .sectionTitle,\n .cardTitle {\n text-wrap: balance;\n }\n\n .bodyLarge,\n .body {\n text-wrap: pretty;\n }\n\n .verdict {\n font: var(--rly-type-verdict-weight) var(--rly-type-verdict-size) / var(--rly-type-verdict-line-height)\n var(--rly-type-verdict-font);\n letter-spacing: var(--rly-type-verdict-tracking);\n }\n\n .pageTitle {\n font: var(--rly-type-page-title-weight) var(--rly-type-page-title-size) / var(--rly-type-page-title-line-height)\n var(--rly-type-page-title-font);\n letter-spacing: var(--rly-type-page-title-tracking);\n }\n\n .sectionTitle {\n font: var(--rly-type-section-title-weight) var(--rly-type-section-title-size) /\n var(--rly-type-section-title-line-height) var(--rly-type-section-title-font);\n letter-spacing: var(--rly-type-section-title-tracking);\n }\n\n .cardTitle {\n font: var(--rly-type-card-title-weight) var(--rly-type-card-title-size) / var(--rly-type-card-title-line-height)\n var(--rly-type-card-title-font);\n letter-spacing: var(--rly-type-card-title-tracking);\n }\n\n .bodyLarge {\n font: var(--rly-type-body-large-weight) var(--rly-type-body-large-size) / var(--rly-type-body-large-line-height)\n var(--rly-type-body-large-font);\n letter-spacing: var(--rly-type-body-large-tracking);\n }\n\n .body {\n font: var(--rly-type-body-weight) var(--rly-type-body-size) / var(--rly-type-body-line-height)\n var(--rly-type-body-font);\n letter-spacing: var(--rly-type-body-tracking);\n }\n\n .label {\n font: var(--rly-type-label-weight) var(--rly-type-label-size) / var(--rly-type-label-line-height)\n var(--rly-type-label-font);\n letter-spacing: var(--rly-type-label-tracking);\n }\n\n .meta {\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n letter-spacing: var(--rly-type-meta-tracking);\n }\n\n .code {\n font: var(--rly-type-code-weight) var(--rly-type-code-size) / var(--rly-type-code-line-height)\n var(--rly-type-code-font);\n font-variant-numeric: tabular-nums;\n letter-spacing: var(--rly-type-code-tracking);\n white-space: pre-wrap;\n }\n\n .tonePrimary {\n color: var(--rly-color-text-1);\n }\n .toneSecondary {\n color: var(--rly-color-text-2);\n }\n .toneTertiary {\n color: var(--rly-color-text-3);\n }\n .toneInherit {\n color: inherit;\n }\n}\n","import {\n createElement,\n type ComponentPropsWithoutRef,\n type HTMLAttributes,\n type ReactElement,\n type ReactNode,\n type Ref\n} from \"react\"\nimport { classNames, cssClass, defineVariants } from \"../internal/component.js\"\nimport styles from \"./Text.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\n\nexport const RLY_TEXT_VARIANTS = defineVariants({\n variant: {\n verdict: { className: style(\"verdict\"), purpose: \"One restrained verdict thesis\", tokens: [\"type-verdict\"] },\n \"page-title\": { className: style(\"pageTitle\"), purpose: \"Primary page title\", tokens: [\"type-page-title\"] },\n \"section-title\": { className: style(\"sectionTitle\"), purpose: \"Section heading\", tokens: [\"type-section-title\"] },\n \"card-title\": { className: style(\"cardTitle\"), purpose: \"Card or panel heading\", tokens: [\"type-card-title\"] },\n \"body-large\": { className: style(\"bodyLarge\"), purpose: \"Leading explanatory copy\", tokens: [\"type-body-large\"] },\n body: { className: style(\"body\"), purpose: \"Default interface copy\", tokens: [\"type-body\"] },\n label: { className: style(\"label\"), purpose: \"Control and metadata labels\", tokens: [\"type-label\"] },\n meta: { className: style(\"meta\"), purpose: \"Supporting metadata\", tokens: [\"type-meta\"] },\n code: { className: style(\"code\"), purpose: \"Code and tabular data\", tokens: [\"type-code\"] }\n },\n tone: {\n primary: { className: style(\"tonePrimary\"), purpose: \"Primary readable text\", tokens: [\"color-text-1\"] },\n secondary: { className: style(\"toneSecondary\"), purpose: \"Supporting text\", tokens: [\"color-text-2\"] },\n tertiary: { className: style(\"toneTertiary\"), purpose: \"Restricted tertiary text\", tokens: [\"color-text-3\"] },\n inherit: { className: style(\"toneInherit\"), purpose: \"Inherit semantic context\", tokens: [] }\n }\n})\n\nexport const RLY_TEXT_DEFAULT_VARIANTS = defineVariants({ variant: \"body\", tone: \"primary\" })\nexport type RlyTextVariant = keyof typeof RLY_TEXT_VARIANTS.variant\nexport type RlyTextTone = keyof typeof RLY_TEXT_VARIANTS.tone\nexport type RlyTextElement =\n | \"h1\"\n | \"h2\"\n | \"h3\"\n | \"h4\"\n | \"h5\"\n | \"h6\"\n | \"p\"\n | \"span\"\n | \"strong\"\n | \"small\"\n | \"code\"\n | \"pre\"\n | \"time\"\n | \"li\"\n | \"dt\"\n | \"dd\"\n\ntype HeadingVariant = \"page-title\" | \"section-title\" | \"card-title\"\ntype HeadingElement = \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"span\"\ntype OtherVariant = Exclude<RlyTextVariant, HeadingVariant>\ntype RefTarget<Value> = Value extends Ref<infer Target> ? Target : never\ntype ExactRef<Expected, Value> =\n Value extends Ref<Expected> ? (Expected extends RefTarget<Value> ? Value : never) : never\ntype TextOwnProps = {\n readonly children: ReactNode\n readonly tone?: RlyTextTone\n}\ntype ExplicitVariantProps<Element extends RlyTextElement> =\n { readonly variant?: OtherVariant } | (Element extends HeadingElement ? { readonly variant: HeadingVariant } : never)\ntype ExplicitTextProps<Element extends RlyTextElement, ElementRef extends Ref<HTMLElementTagNameMap[Element]>> = Omit<\n ComponentPropsWithoutRef<Element>,\n \"as\" | \"children\" | \"color\"\n> &\n TextOwnProps &\n ExplicitVariantProps<Element> & {\n readonly as: Element\n readonly ref?: ExactRef<HTMLElementTagNameMap[Element], ElementRef>\n }\ntype ImplicitTextProps = Omit<HTMLAttributes<HTMLElement>, \"children\" | \"color\"> &\n TextOwnProps & {\n readonly as?: never\n readonly ref?: never\n readonly variant?: OtherVariant\n }\nexport type TextProps<\n Element extends RlyTextElement = RlyTextElement,\n ElementRef extends Ref<HTMLElementTagNameMap[Element]> = Ref<HTMLElementTagNameMap[Element]>\n> = ExplicitTextProps<Element, ElementRef> | ImplicitTextProps\n\ntype TextComponent = <\n const Element extends RlyTextElement = RlyTextElement,\n ElementRef extends Ref<HTMLElementTagNameMap[Element]> = Ref<HTMLElementTagNameMap[Element]>\n>(\n props: TextProps<Element, ElementRef>\n) => ReactElement\ntype TextRuntimeProps = Omit<HTMLAttributes<HTMLElement>, \"color\"> &\n TextOwnProps & {\n readonly as?: RlyTextElement\n readonly ref?: Ref<HTMLElement>\n readonly variant?: RlyTextVariant\n }\n\nconst defaultElement = (variant: RlyTextVariant): RlyTextElement =>\n variant === \"code\" ? \"code\" : variant === \"verdict\" ? \"p\" : variant === \"label\" || variant === \"meta\" ? \"span\" : \"p\"\n\n/** Render semantic typography while keeping visual role separate from document structure. */\nconst renderText = ({\n as,\n children,\n className,\n ref,\n tone = RLY_TEXT_DEFAULT_VARIANTS.tone,\n variant = RLY_TEXT_DEFAULT_VARIANTS.variant,\n ...props\n}: TextRuntimeProps): ReactElement =>\n createElement(\n as ?? defaultElement(variant),\n {\n ...props,\n className: classNames(\n style(\"root\"),\n RLY_TEXT_VARIANTS.variant[variant].className,\n RLY_TEXT_VARIANTS.tone[tone].className,\n className\n ),\n ref\n },\n children\n )\n\nexport const Text: TextComponent = renderText\n","@layer rly.components {\n /* A header control sizes to its longest option instead of filling the row. */\n .intrinsic {\n inline-size: max-content;\n min-inline-size: calc(var(--rly-space-96) + var(--rly-space-48));\n }\n}\n","import type { ReactElement } from \"react\"\nimport { decodeRlyTheme, RLY_THEME_NAMES, type RlyTheme } from \"../foundations/ThemeProvider.js\"\nimport { Field } from \"./Field.js\"\nimport { classNames, cssClass } from \"../internal/component.js\"\nimport { RLY_SELECT_DEFAULT_VARIANTS, type RlySelectOption, type RlySelectSize, Select } from \"./Select.js\"\nimport styles from \"./ThemeSelect.module.css\"\n\nconst themeLabels = {\n system: \"System\",\n light: \"Light\",\n dark: \"Dark\"\n} satisfies Readonly<Record<RlyTheme, string>>\n\nconst themeOptions: ReadonlyArray<RlySelectOption> = RLY_THEME_NAMES.map((value) => ({\n label: themeLabels[value],\n value\n}))\n\nexport type RlyThemeSelectLabelVisibility = \"visible\" | \"hidden\"\n\nexport interface ThemeSelectProps {\n readonly className?: string\n readonly label?: string\n readonly labelVisibility?: RlyThemeSelectLabelVisibility\n readonly onValueChange: (theme: RlyTheme) => void\n readonly size?: RlySelectSize\n readonly value: RlyTheme\n}\n\n/**\n * Let the viewer choose the system, light, or dark theme. Controlled; pair it with\n * `useStoredTheme` to remember the choice. Built on rly `Select` so every dropdown in\n * a product looks and behaves the same.\n *\n * Settings pages show the label and fill the field width. Compact headers pass\n * `labelVisibility=\"hidden\"`, which keeps the name for assistive technology through\n * `aria-label` and sizes the trigger to its longest option. Dense by default, like the\n * controls beside it in a header.\n *\n * @example\n * const [theme, setTheme] = useStoredTheme(\"jcf_theme\", browserStorage)\n * <ThemeSelect labelVisibility=\"hidden\" onValueChange={setTheme} value={theme} />\n */\nexport const ThemeSelect = ({\n className,\n label = \"Appearance\",\n labelVisibility = \"visible\",\n onValueChange,\n size = RLY_SELECT_DEFAULT_VARIANTS.size,\n value\n}: ThemeSelectProps): ReactElement => {\n const onChange = (next: string): void => {\n // Select only reports values from themeOptions, so decoding always succeeds.\n const theme = decodeRlyTheme(next)\n if (theme !== undefined) onValueChange(theme)\n }\n\n if (labelVisibility === \"hidden\") {\n return (\n <Select\n aria-label={label}\n className={classNames(cssClass(styles, \"intrinsic\"), className)}\n onValueChange={onChange}\n options={themeOptions}\n size={size}\n value={value}\n />\n )\n }\n return (\n <Field {...(className === undefined ? {} : { className })} label={label} size={size}>\n {(controlProps) => (\n <Select {...controlProps} onValueChange={onChange} options={themeOptions} size={size} value={value} />\n )}\n </Field>\n )\n}\n","@layer rly.components {\n /*\n * One outlined row of options, like the controls beside it: no tinted track, 1px dividers. The\n * outline is painted over the options' edges instead of taking room from them, so each option keeps\n * the full control height and touch target. The row never wraps (dividers would strand on a second\n * line); a row wider than its container scrolls inside it.\n */\n .root {\n border-radius: var(--rly-radius-tag);\n display: inline-flex;\n max-inline-size: 100%;\n outline: 1px solid var(--rly-color-border-2);\n outline-offset: -1px;\n overflow-x: auto;\n }\n\n .item {\n appearance: none;\n background: transparent;\n border: var(--rly-space-0);\n color: var(--rly-color-text-2);\n cursor: pointer;\n /* Options keep their label width; a row too wide for its container scrolls instead. */\n flex-shrink: 0;\n font: inherit;\n padding-inline: var(--rly-space-12);\n white-space: nowrap;\n }\n\n .item + .item {\n border-inline-start: 1px solid var(--rly-color-border-2);\n }\n\n .item[data-state=\"checked\"] {\n background: var(--rly-color-surface-3);\n color: var(--rly-color-text-1);\n }\n\n .item:focus-visible {\n outline: var(--rly-focus-ring-width) solid var(--rly-color-focus);\n outline-offset: calc(-1 * var(--rly-focus-ring-width));\n }\n\n /* Each option is at least as tall and as wide as its size token, which grows to the 44px touch\n target under a coarse pointer, so even a one-character option is a full target. */\n .dense .item,\n .compact .item {\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n }\n\n .dense .item {\n min-block-size: var(--rly-control-height-dense);\n min-inline-size: var(--rly-control-height-dense);\n padding-inline: var(--rly-space-8);\n }\n\n .compact .item {\n min-block-size: var(--rly-control-height-compact);\n min-inline-size: var(--rly-control-height-compact);\n }\n\n .defaultSize .item {\n font: var(--rly-type-label-weight) var(--rly-type-label-size) / var(--rly-type-label-line-height)\n var(--rly-type-label-font);\n min-block-size: var(--rly-control-height-default);\n min-inline-size: var(--rly-control-height-default);\n }\n\n @media (hover: hover) {\n .item:not([data-state=\"checked\"]):hover {\n background: var(--rly-color-surface-2);\n color: var(--rly-color-text-1);\n }\n }\n\n /* Forced colours: the selected option keeps a ring, since the fill that marks it is dropped. */\n @media (forced-colors: active) {\n .item[data-state=\"checked\"] {\n outline: 2px solid CanvasText;\n outline-offset: -2px;\n }\n /* Focused and checked: the focus ring wins, in the system highlight and outside the checked ring. */\n .item[data-state=\"checked\"]:focus-visible {\n outline: var(--rly-focus-ring-width) solid Highlight;\n outline-offset: var(--rly-focus-ring-offset);\n }\n }\n\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .item[data-state=\"checked\"] {\n outline: 2px solid CanvasText;\n outline-offset: -2px;\n }\n\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .item[data-state=\"checked\"]:focus-visible {\n outline: var(--rly-focus-ring-width) solid Highlight;\n outline-offset: var(--rly-focus-ring-offset);\n }\n}\n","import { type ComponentPropsWithRef, type KeyboardEvent, type ReactElement, useRef } from \"react\"\nimport { RadioGroup as RadixRadioGroup } from \"radix-ui\"\nimport { classNames, cssClass, defineVariants, requireText } from \"../internal/component.js\"\nimport styles from \"./ToggleGroup.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\n\nexport const RLY_TOGGLE_GROUP_VARIANTS = defineVariants({\n size: {\n dense: {\n className: style(\"dense\"),\n purpose: \"Tool-density choice beside dense controls; the default\",\n tokens: [\"control-height-dense\", \"type-meta\", \"radius-tag\"]\n },\n compact: {\n className: style(\"compact\"),\n purpose: \"Filter rows beside compact controls\",\n tokens: [\"control-height-compact\", \"type-meta\", \"radius-tag\"]\n },\n default: {\n className: style(\"defaultSize\"),\n purpose: \"Standard view and filter choices\",\n tokens: [\"control-height-default\", \"type-label\", \"radius-tag\"]\n }\n }\n})\n\nexport const RLY_TOGGLE_GROUP_DEFAULT_VARIANTS = defineVariants({ size: \"dense\" })\nexport type RlyToggleGroupSize = keyof typeof RLY_TOGGLE_GROUP_VARIANTS.size\n\n/** One visibly labelled option. */\nexport interface RlyToggleItem {\n readonly label: string\n readonly value: string\n}\n\n/** Props for a controlled, single-select segmented choice. */\nexport type ToggleGroupProps = Omit<\n ComponentPropsWithRef<\"div\">,\n \"aria-label\" | \"children\" | \"defaultValue\" | \"dir\" | \"onChange\"\n> & {\n /** Accessible name for the group, such as the filter it sets. */\n readonly \"aria-label\": string\n readonly items: ReadonlyArray<RlyToggleItem>\n readonly onValueChange: (value: string) => void\n readonly size?: RlyToggleGroupSize\n readonly value: string\n}\n\n/** How far an arrow key moves the choice; null for any other key. */\nconst stepOf = (key: string): -1 | 1 | null =>\n key === \"ArrowLeft\" || key === \"ArrowUp\" ? -1 : key === \"ArrowRight\" || key === \"ArrowDown\" ? 1 : null\n\nconst validateItems = (items: ReadonlyArray<RlyToggleItem>, value: string): void => {\n const values = new Set<string>()\n for (const item of items) {\n const itemValue = requireText(item.value, \"ToggleGroup item value\")\n requireText(item.label, `ToggleGroup item label for ${itemValue}`)\n if (values.has(itemValue)) throw new Error(`ToggleGroup item values must be unique: ${itemValue}`)\n values.add(itemValue)\n }\n if (!values.has(value)) throw new Error(`ToggleGroup value must identify an option: ${value}`)\n}\n\n/**\n * Choose one of a few peer options, such as a range or a measure, as a radio group: exactly one\n * option is always on, pressing it again changes nothing, and arrow keys move to the next option\n * and choose it.\n */\nexport const ToggleGroup = ({\n \"aria-label\": ariaLabel,\n className,\n items,\n onValueChange,\n ref,\n size = RLY_TOGGLE_GROUP_DEFAULT_VARIANTS.size,\n value,\n ...props\n}: ToggleGroupProps): ReactElement => {\n const accessibleLabel = requireText(ariaLabel, \"ToggleGroup aria-label\")\n validateItems(items, value)\n const options = useRef(new Map<string, HTMLButtonElement>())\n // Radix moves focus a tick after the key and only chooses while the key is still down, so a quick\n // tap would move focus without choosing. Arrows are handled here: the next option is chosen and\n // focused in the same keystroke, wrapping at the ends.\n const choose = (event: KeyboardEvent<HTMLButtonElement>, from: number) => {\n const step = stepOf(event.key)\n if (step === null) return\n event.preventDefault()\n const next = items[(from + step + items.length) % items.length]\n if (next === undefined) return\n // Landing on the chosen option (a group of one, or focus that had wandered off it) is no change\n // to report, but focus still moves there.\n if (next.value !== value) onValueChange(next.value)\n options.current.get(next.value)?.focus()\n }\n return (\n <RadixRadioGroup.Root\n {...props}\n aria-label={accessibleLabel}\n className={classNames(style(\"root\"), RLY_TOGGLE_GROUP_VARIANTS.size[size].className, className)}\n loop\n onValueChange={onValueChange}\n orientation=\"horizontal\"\n ref={ref}\n value={value}\n >\n {items.map((item, index) => (\n <RadixRadioGroup.Item\n className={style(\"item\")}\n key={item.value}\n onKeyDown={(event) => choose(event, index)}\n ref={(element) => {\n if (element === null) options.current.delete(item.value)\n else options.current.set(item.value, element)\n }}\n value={item.value}\n >\n {item.label}\n </RadixRadioGroup.Item>\n ))}\n </RadixRadioGroup.Root>\n )\n}\n","@layer rly.components {\n .root {\n color: var(--rly-color-text-2);\n display: flex;\n flex-wrap: wrap;\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n gap: var(--rly-space-6) var(--rly-space-16);\n list-style: none;\n margin: 0;\n padding: 0;\n }\n .item {\n align-items: center;\n display: inline-flex;\n gap: var(--rly-space-6);\n }\n /* Same two-tone mark as LimitTrack. */\n .near {\n background: var(--rly-color-text-1);\n box-shadow:\n -1px 0 0 var(--rly-color-surface-1),\n 1px 0 0 var(--rly-color-surface-1);\n block-size: var(--rly-space-12);\n inline-size: 1px; /* stripe-ok: the near mark's key swatch, a 1px data tick */\n }\n .projected {\n border-block: 2px dotted var(--rly-color-held-ink);\n block-size: var(--rly-space-6);\n box-sizing: border-box;\n inline-size: var(--rly-space-16);\n }\n .stale {\n background: repeating-linear-gradient(135deg, var(--rly-color-text-2) 0 3px, transparent 3px 6px);\n block-size: var(--rly-space-8);\n border-radius: var(--rly-radius-tag);\n inline-size: var(--rly-space-16);\n }\n /* Same faint hatch and dashed edge as a LimitTrack with no reading. */\n .unknown {\n background: repeating-linear-gradient(45deg, var(--rly-color-border-2) 0 1px, transparent 1px 5px)\n var(--rly-color-surface-3);\n block-size: var(--rly-space-8);\n border-radius: var(--rly-radius-tag);\n inline-size: var(--rly-space-16);\n outline: 1px dashed var(--rly-color-border-2);\n outline-offset: -1px;\n }\n /* The Storybook toolbar's forced-colours mode: the same edges as under the media query. */\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .stale {\n outline: 1px solid CanvasText;\n outline-offset: -1px;\n }\n :where([data-forced-colors=\"active\"], [data-rly-forced-colors=\"active\"]) .unknown {\n outline: 1px dashed CanvasText;\n }\n @media (forced-colors: active) {\n /* Keep the halo: forced colours drop box-shadow, and the tokens already map to system colours. */\n .near {\n forced-color-adjust: none;\n }\n /* Match the system-colour hatch on stale LimitTracks. */\n .stale {\n background: repeating-linear-gradient(135deg, CanvasText 0 3px, Canvas 3px 6px);\n forced-color-adjust: none;\n outline: 1px solid CanvasText;\n outline-offset: -1px;\n }\n .unknown {\n background: repeating-linear-gradient(45deg, CanvasText 0 1px, Canvas 1px 5px);\n forced-color-adjust: none;\n outline: 1px dashed CanvasText;\n }\n }\n}\n","import type { ComponentPropsWithRef, ReactElement } from \"react\"\nimport { classNames, cssClass, requireText } from \"../internal/component.js\"\nimport styles from \"./TrackKey.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\n/** The marks a LimitTrack can draw. */\nexport const RLY_TRACK_KEY_MARKS: readonly [\"near\", \"projected\", \"stale\", \"unknown\"] = [\n \"near\",\n \"projected\",\n \"stale\",\n \"unknown\"\n]\nexport type RlyTrackKeyMark = (typeof RLY_TRACK_KEY_MARKS)[number]\n\n/** One mark and the caller's words for it. */\nexport interface RlyTrackKeyItem {\n readonly mark: RlyTrackKeyMark\n readonly label: string\n}\n\ntype TrackKeyBaseProps = Omit<ComponentPropsWithRef<\"ul\">, \"aria-label\" | \"children\">\nexport type TrackKeyProps = TrackKeyBaseProps & {\n /** Names the list for assistive technology, for example \"What the track marks mean\". */\n readonly label: string\n /** Only the marks the tracks above actually draw, in reading order. */\n readonly items: ReadonlyArray<RlyTrackKeyItem>\n}\n\n/** One line under a set of LimitTracks explaining their marks; each mark sits before its own words. */\nexport const TrackKey = ({ className, items, label, ...props }: TrackKeyProps): ReactElement => {\n if (items.length === 0) throw new Error(\"TrackKey needs at least one mark to explain\")\n const marks = new Set<RlyTrackKeyMark>()\n for (const item of items) {\n if (marks.has(item.mark)) throw new Error(`TrackKey marks must be unique: ${item.mark}`)\n marks.add(item.mark)\n }\n return (\n // Flex styling with no list markers drops list semantics in WebKit, so the role is explicit.\n <ul\n {...props}\n aria-label={requireText(label, \"TrackKey label\")}\n className={classNames(style(\"root\"), className)}\n role=\"list\"\n >\n {items.map((item) => (\n <li className={style(\"item\")} key={item.mark}>\n <span aria-hidden=\"true\" className={style(item.mark)} data-mark={item.mark} />\n {requireText(item.label, \"TrackKey item label\")}\n </li>\n ))}\n </ul>\n )\n}\n"],"mappings":"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"}
|
package/dist/tokens/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as e, i as t, n, o as r, r as i,
|
|
2
|
-
export {
|
|
1
|
+
import { a as e, i as t, n, o as r, r as i, s as a, t as o } from "../tokens-Cf0jXIRg.js";
|
|
2
|
+
export { o as RLY_COLOR_TOKEN_NAMES, n as RLY_CONTROL_HEIGHT_TOKEN_NAMES, a as RLY_FONT_FACES, i as RLY_MOTION_TOKEN_NAMES, t as RLY_RADIUS_TOKEN_NAMES, e as RLY_SPACE_TOKEN_NAMES, r as RLY_TYPE_TOKEN_NAMES };
|
|
3
3
|
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
//#region src/tokens/
|
|
2
|
-
var e =
|
|
1
|
+
//#region src/tokens/fonts.ts
|
|
2
|
+
var e = [{
|
|
3
|
+
family: "Geist Variable",
|
|
4
|
+
file: "geist-latin-wght-normal.woff2"
|
|
5
|
+
}, {
|
|
6
|
+
family: "Geist Mono Variable",
|
|
7
|
+
file: "geist-mono-latin-wght-normal.woff2"
|
|
8
|
+
}], t = (e) => e, n = t(/* @__PURE__ */ "canvas.surface-1.surface-2.surface-3.text-1.text-2.text-3.border-1.border-2.action-background.action-foreground.focus.agent.success-ink.success-tint.blocked-ink.blocked-tint.held-ink.held-tint.deploying-ink.deploying-tint.service-codecommit.service-codepipeline.service-jira.service-confluence.service-clockify.series-1.series-2.series-3.series-4.series-5.series-6.series-7.series-8.series-other".split(".")), r = t([
|
|
3
9
|
"0",
|
|
4
10
|
"2",
|
|
5
11
|
"4",
|
|
@@ -15,14 +21,14 @@ var e = (e) => e, t = e(/* @__PURE__ */ "canvas.surface-1.surface-2.surface-3.te
|
|
|
15
21
|
"64",
|
|
16
22
|
"80",
|
|
17
23
|
"96"
|
|
18
|
-
]),
|
|
24
|
+
]), i = t([
|
|
19
25
|
"tag",
|
|
20
26
|
"field",
|
|
21
27
|
"control",
|
|
22
28
|
"group",
|
|
23
29
|
"overlay",
|
|
24
30
|
"round"
|
|
25
|
-
]),
|
|
31
|
+
]), a = t([
|
|
26
32
|
"verdict",
|
|
27
33
|
"page-title",
|
|
28
34
|
"section-title",
|
|
@@ -32,18 +38,18 @@ var e = (e) => e, t = e(/* @__PURE__ */ "canvas.surface-1.surface-2.surface-3.te
|
|
|
32
38
|
"label",
|
|
33
39
|
"meta",
|
|
34
40
|
"code"
|
|
35
|
-
]),
|
|
41
|
+
]), o = t([
|
|
36
42
|
"fast",
|
|
37
43
|
"standard",
|
|
38
44
|
"deliberate",
|
|
39
45
|
"slow"
|
|
40
|
-
]),
|
|
46
|
+
]), s = t([
|
|
41
47
|
"dense",
|
|
42
48
|
"compact",
|
|
43
49
|
"default",
|
|
44
50
|
"principal"
|
|
45
51
|
]);
|
|
46
52
|
//#endregion
|
|
47
|
-
export {
|
|
53
|
+
export { r as a, i, s as n, a as o, o as r, e as s, n as t };
|
|
48
54
|
|
|
49
|
-
//# sourceMappingURL=tokens-
|
|
55
|
+
//# sourceMappingURL=tokens-Cf0jXIRg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokens-Cf0jXIRg.js","names":["RLY_FONT_FACES","tokenNames","names","RLY_COLOR_TOKEN_NAMES","RLY_SPACE_TOKEN_NAMES","RLY_RADIUS_TOKEN_NAMES","RLY_TYPE_TOKEN_NAMES","RLY_MOTION_TOKEN_NAMES","RLY_CONTROL_HEIGHT_TOKEN_NAMES"],"sources":["../src/tokens/fonts.ts","../src/tokens/semantic-tokens.ts"],"sourcesContent":["/** One web font rly's styles.css loads: its CSS family and the woff2 file a shell preloads. */\nexport interface RlyFontFace {\n readonly family: string\n readonly file: string\n}\n\n/**\n * Every web font rly's styles.css loads, as Fontsource names the files. The faces use\n * `font-display: optional`, so a shell must preload each of these files (from its own origin, with\n * `crossorigin`) for Geist to render on first load; otherwise the metric-matched fallback stays for\n * that page view and nothing swaps. Shells read this list instead of hardcoding file names.\n */\nexport const RLY_FONT_FACES: readonly [RlyFontFace, RlyFontFace] = [\n { family: \"Geist Variable\", file: \"geist-latin-wght-normal.woff2\" },\n { family: \"Geist Mono Variable\", file: \"geist-mono-latin-wght-normal.woff2\" }\n]\n","// @generated by scripts/generate-contract.ts; do not edit.\nconst tokenNames = <const Names extends ReadonlyArray<string>>(names: Names): Names => names\n\nexport const RLY_COLOR_TOKEN_NAMES = tokenNames([\n \"canvas\",\n \"surface-1\",\n \"surface-2\",\n \"surface-3\",\n \"text-1\",\n \"text-2\",\n \"text-3\",\n \"border-1\",\n \"border-2\",\n \"action-background\",\n \"action-foreground\",\n \"focus\",\n \"agent\",\n \"success-ink\",\n \"success-tint\",\n \"blocked-ink\",\n \"blocked-tint\",\n \"held-ink\",\n \"held-tint\",\n \"deploying-ink\",\n \"deploying-tint\",\n \"service-codecommit\",\n \"service-codepipeline\",\n \"service-jira\",\n \"service-confluence\",\n \"service-clockify\",\n \"series-1\",\n \"series-2\",\n \"series-3\",\n \"series-4\",\n \"series-5\",\n \"series-6\",\n \"series-7\",\n \"series-8\",\n \"series-other\"\n])\nexport type RlyColorToken = (typeof RLY_COLOR_TOKEN_NAMES)[number]\n\nexport const RLY_SPACE_TOKEN_NAMES = tokenNames([\n \"0\",\n \"2\",\n \"4\",\n \"6\",\n \"8\",\n \"12\",\n \"16\",\n \"20\",\n \"24\",\n \"32\",\n \"40\",\n \"48\",\n \"64\",\n \"80\",\n \"96\"\n])\nexport type RlySpaceToken = (typeof RLY_SPACE_TOKEN_NAMES)[number]\n\nexport const RLY_RADIUS_TOKEN_NAMES = tokenNames([\n \"tag\",\n \"field\",\n \"control\",\n \"group\",\n \"overlay\",\n \"round\"\n])\nexport type RlyRadiusToken = (typeof RLY_RADIUS_TOKEN_NAMES)[number]\n\nexport const RLY_TYPE_TOKEN_NAMES = tokenNames([\n \"verdict\",\n \"page-title\",\n \"section-title\",\n \"card-title\",\n \"body-large\",\n \"body\",\n \"label\",\n \"meta\",\n \"code\"\n])\nexport type RlyTypeToken = (typeof RLY_TYPE_TOKEN_NAMES)[number]\n\nexport const RLY_MOTION_TOKEN_NAMES = tokenNames([\n \"fast\",\n \"standard\",\n \"deliberate\",\n \"slow\"\n])\nexport type RlyMotionToken = (typeof RLY_MOTION_TOKEN_NAMES)[number]\n\nexport const RLY_CONTROL_HEIGHT_TOKEN_NAMES = tokenNames([\n \"dense\",\n \"compact\",\n \"default\",\n \"principal\"\n])\nexport type RlyControlHeightToken = (typeof RLY_CONTROL_HEIGHT_TOKEN_NAMES)[number]\n"],"mappings":";AAYA,IAAaA,IAAsD,CACjE;CAAE,QAAQ;CAAkB,MAAM;AAAgC,GAClE;CAAE,QAAQ;CAAuB,MAAM;AAAqC,CAC9E,GCdMC,KAAyD,MAAwBC,GAE1EC,IAAwBF,EAAW,uaAoChD,CAAC,GAGYG,IAAwBH,EAAW;CAC9C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,GAGYI,IAAyBJ,EAAW;CAC/C;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,GAGYK,IAAuBL,EAAW;CAC7C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC,GAGYM,IAAyBN,EAAW;CAC/C;CACA;CACA;CACA;AACF,CAAC,GAGYO,IAAiCP,EAAW;CACvD;CACA;CACA;CACA;AACF,CAAC"}
|
package/package.json
CHANGED
package/registry/components.json
CHANGED
|
@@ -3540,6 +3540,95 @@
|
|
|
3540
3540
|
"status": "stable",
|
|
3541
3541
|
"variants": []
|
|
3542
3542
|
},
|
|
3543
|
+
{
|
|
3544
|
+
"accessibility": {
|
|
3545
|
+
"automatedChecks": true,
|
|
3546
|
+
"requirements": [
|
|
3547
|
+
"Provide a programmatic name for interactive or informative content",
|
|
3548
|
+
"Preserve keyboard access, focus visibility, and color-independent meaning"
|
|
3549
|
+
],
|
|
3550
|
+
"standard": "WCAG 2.2 AA"
|
|
3551
|
+
},
|
|
3552
|
+
"capabilities": [
|
|
3553
|
+
"agent",
|
|
3554
|
+
"write"
|
|
3555
|
+
],
|
|
3556
|
+
"category": "pattern",
|
|
3557
|
+
"compatibleTokens": [
|
|
3558
|
+
"color",
|
|
3559
|
+
"motion",
|
|
3560
|
+
"radius",
|
|
3561
|
+
"space",
|
|
3562
|
+
"type"
|
|
3563
|
+
],
|
|
3564
|
+
"docs": {
|
|
3565
|
+
"autogenerated": true,
|
|
3566
|
+
"storyId": "patterns-relaycomposer--draft",
|
|
3567
|
+
"storyPath": "?path=/story/patterns-relaycomposer--draft"
|
|
3568
|
+
},
|
|
3569
|
+
"example": "import { RelayComposer } from \"@knpkv/rly/patterns\"",
|
|
3570
|
+
"exports": [
|
|
3571
|
+
{
|
|
3572
|
+
"kind": "value",
|
|
3573
|
+
"name": "RelayComposer"
|
|
3574
|
+
},
|
|
3575
|
+
{
|
|
3576
|
+
"kind": "type",
|
|
3577
|
+
"name": "RelayComposerProps"
|
|
3578
|
+
},
|
|
3579
|
+
{
|
|
3580
|
+
"kind": "type",
|
|
3581
|
+
"name": "RlyRelayContextRef"
|
|
3582
|
+
},
|
|
3583
|
+
{
|
|
3584
|
+
"kind": "type",
|
|
3585
|
+
"name": "RlyRelayDraft"
|
|
3586
|
+
},
|
|
3587
|
+
{
|
|
3588
|
+
"kind": "type",
|
|
3589
|
+
"name": "RlyRelayDraftStorage"
|
|
3590
|
+
},
|
|
3591
|
+
{
|
|
3592
|
+
"kind": "type",
|
|
3593
|
+
"name": "RlyRelaySubmission"
|
|
3594
|
+
},
|
|
3595
|
+
{
|
|
3596
|
+
"kind": "value",
|
|
3597
|
+
"name": "useRelayDraft"
|
|
3598
|
+
},
|
|
3599
|
+
{
|
|
3600
|
+
"kind": "type",
|
|
3601
|
+
"name": "UseRelayDraftOptions"
|
|
3602
|
+
}
|
|
3603
|
+
],
|
|
3604
|
+
"files": {
|
|
3605
|
+
"source": "src/patterns/RelayComposer.tsx",
|
|
3606
|
+
"story": "stories/patterns/RelayComposer.stories.tsx",
|
|
3607
|
+
"styles": [
|
|
3608
|
+
"src/patterns/RelayComposer.module.css"
|
|
3609
|
+
],
|
|
3610
|
+
"tests": [
|
|
3611
|
+
"test/patterns/RelayComposer.test.tsx"
|
|
3612
|
+
]
|
|
3613
|
+
},
|
|
3614
|
+
"importPath": "@knpkv/rly/patterns",
|
|
3615
|
+
"name": "RelayComposer",
|
|
3616
|
+
"props": {
|
|
3617
|
+
"defaults": {},
|
|
3618
|
+
"types": [
|
|
3619
|
+
"RelayComposerProps"
|
|
3620
|
+
]
|
|
3621
|
+
},
|
|
3622
|
+
"purpose": "Write to Relay: an auto-growing message box with context refs, a run preset, send and stop, and drafts kept per object",
|
|
3623
|
+
"slots": [],
|
|
3624
|
+
"states": [
|
|
3625
|
+
"busy",
|
|
3626
|
+
"default",
|
|
3627
|
+
"draft"
|
|
3628
|
+
],
|
|
3629
|
+
"status": "experimental",
|
|
3630
|
+
"variants": []
|
|
3631
|
+
},
|
|
3543
3632
|
{
|
|
3544
3633
|
"accessibility": {
|
|
3545
3634
|
"automatedChecks": true,
|
|
@@ -3696,9 +3785,21 @@
|
|
|
3696
3785
|
"kind": "type",
|
|
3697
3786
|
"name": "RlyRelayShortcut"
|
|
3698
3787
|
},
|
|
3788
|
+
{
|
|
3789
|
+
"kind": "type",
|
|
3790
|
+
"name": "RlyRelaySummon"
|
|
3791
|
+
},
|
|
3699
3792
|
{
|
|
3700
3793
|
"kind": "value",
|
|
3701
3794
|
"name": "useRelayShortcut"
|
|
3795
|
+
},
|
|
3796
|
+
{
|
|
3797
|
+
"kind": "value",
|
|
3798
|
+
"name": "useRelaySummon"
|
|
3799
|
+
},
|
|
3800
|
+
{
|
|
3801
|
+
"kind": "type",
|
|
3802
|
+
"name": "UseRelaySummonOptions"
|
|
3702
3803
|
}
|
|
3703
3804
|
],
|
|
3704
3805
|
"files": {
|
|
@@ -3709,7 +3810,9 @@
|
|
|
3709
3810
|
],
|
|
3710
3811
|
"tests": [
|
|
3711
3812
|
"test/patterns/RelayLauncher.css.test.ts",
|
|
3712
|
-
"test/patterns/RelayLauncher.test.tsx"
|
|
3813
|
+
"test/patterns/RelayLauncher.summon.test.tsx",
|
|
3814
|
+
"test/patterns/RelayLauncher.test.tsx",
|
|
3815
|
+
"test/patterns/relaySummon.test.ts"
|
|
3713
3816
|
]
|
|
3714
3817
|
},
|
|
3715
3818
|
"importPath": "@knpkv/rly/patterns",
|
|
@@ -3819,6 +3922,108 @@
|
|
|
3819
3922
|
"status": "experimental",
|
|
3820
3923
|
"variants": []
|
|
3821
3924
|
},
|
|
3925
|
+
{
|
|
3926
|
+
"accessibility": {
|
|
3927
|
+
"automatedChecks": true,
|
|
3928
|
+
"requirements": [
|
|
3929
|
+
"Provide a programmatic name for interactive or informative content",
|
|
3930
|
+
"Preserve keyboard access, focus visibility, and color-independent meaning"
|
|
3931
|
+
],
|
|
3932
|
+
"standard": "WCAG 2.2 AA"
|
|
3933
|
+
},
|
|
3934
|
+
"capabilities": [
|
|
3935
|
+
"agent",
|
|
3936
|
+
"overlay"
|
|
3937
|
+
],
|
|
3938
|
+
"category": "pattern",
|
|
3939
|
+
"compatibleTokens": [
|
|
3940
|
+
"color",
|
|
3941
|
+
"motion",
|
|
3942
|
+
"radius",
|
|
3943
|
+
"space",
|
|
3944
|
+
"type"
|
|
3945
|
+
],
|
|
3946
|
+
"docs": {
|
|
3947
|
+
"autogenerated": true,
|
|
3948
|
+
"storyId": "patterns-relaypanel--overlay",
|
|
3949
|
+
"storyPath": "?path=/story/patterns-relaypanel--overlay"
|
|
3950
|
+
},
|
|
3951
|
+
"example": "import { RelayPanel } from \"@knpkv/rly/patterns\"",
|
|
3952
|
+
"exports": [
|
|
3953
|
+
{
|
|
3954
|
+
"kind": "value",
|
|
3955
|
+
"name": "RelayPanel"
|
|
3956
|
+
},
|
|
3957
|
+
{
|
|
3958
|
+
"kind": "type",
|
|
3959
|
+
"name": "RelayPanelProps"
|
|
3960
|
+
},
|
|
3961
|
+
{
|
|
3962
|
+
"kind": "value",
|
|
3963
|
+
"name": "RLY_RELAY_PANEL_PRESENTATIONS"
|
|
3964
|
+
},
|
|
3965
|
+
{
|
|
3966
|
+
"kind": "value",
|
|
3967
|
+
"name": "RLY_RELAY_PANEL_WIDTH"
|
|
3968
|
+
},
|
|
3969
|
+
{
|
|
3970
|
+
"kind": "type",
|
|
3971
|
+
"name": "RlyRelayPanelPin"
|
|
3972
|
+
},
|
|
3973
|
+
{
|
|
3974
|
+
"kind": "type",
|
|
3975
|
+
"name": "RlyRelayPanelPresentation"
|
|
3976
|
+
},
|
|
3977
|
+
{
|
|
3978
|
+
"kind": "type",
|
|
3979
|
+
"name": "RlyRelayPanelTab"
|
|
3980
|
+
},
|
|
3981
|
+
{
|
|
3982
|
+
"kind": "type",
|
|
3983
|
+
"name": "RlyRelayPresentation"
|
|
3984
|
+
},
|
|
3985
|
+
{
|
|
3986
|
+
"kind": "type",
|
|
3987
|
+
"name": "RlyRelayScope"
|
|
3988
|
+
},
|
|
3989
|
+
{
|
|
3990
|
+
"kind": "value",
|
|
3991
|
+
"name": "useRelayPresentation"
|
|
3992
|
+
},
|
|
3993
|
+
{
|
|
3994
|
+
"kind": "type",
|
|
3995
|
+
"name": "UseRelayPresentationOptions"
|
|
3996
|
+
}
|
|
3997
|
+
],
|
|
3998
|
+
"files": {
|
|
3999
|
+
"source": "src/patterns/RelayPanel.tsx",
|
|
4000
|
+
"story": "stories/patterns/RelayPanel.stories.tsx",
|
|
4001
|
+
"styles": [
|
|
4002
|
+
"src/patterns/RelayPanel.module.css"
|
|
4003
|
+
],
|
|
4004
|
+
"tests": [
|
|
4005
|
+
"test/patterns/RelayPanel.test.tsx"
|
|
4006
|
+
]
|
|
4007
|
+
},
|
|
4008
|
+
"importPath": "@knpkv/rly/patterns",
|
|
4009
|
+
"name": "RelayPanel",
|
|
4010
|
+
"props": {
|
|
4011
|
+
"defaults": {},
|
|
4012
|
+
"types": [
|
|
4013
|
+
"RelayPanelProps"
|
|
4014
|
+
]
|
|
4015
|
+
},
|
|
4016
|
+
"purpose": "Frame Relay as a non-modal overlay, a pinned column or a full-screen dialog, with its header, tabs, freshness line, body and footer",
|
|
4017
|
+
"slots": [],
|
|
4018
|
+
"states": [
|
|
4019
|
+
"default",
|
|
4020
|
+
"fullscreen",
|
|
4021
|
+
"overlay",
|
|
4022
|
+
"pinned"
|
|
4023
|
+
],
|
|
4024
|
+
"status": "experimental",
|
|
4025
|
+
"variants": []
|
|
4026
|
+
},
|
|
3822
4027
|
{
|
|
3823
4028
|
"accessibility": {
|
|
3824
4029
|
"automatedChecks": true,
|