@mitcsutt/kiln-ui 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/components/display/CodeBlock/CodeBlock.d.ts +44 -3
  2. package/dist/components/display/CodeBlock/CodeBlock.js +54 -49
  3. package/dist/components/display/CodeBlock/CodeBlock.js.map +1 -1
  4. package/dist/components/display/CodeBlock/CodeBlock.module.js +4 -3
  5. package/dist/components/display/CodeBlock/CodeBlock.module.js.map +1 -1
  6. package/dist/components/display/CodeBlock/index.d.ts +1 -1
  7. package/dist/components/display/List/List.d.ts +8 -0
  8. package/dist/components/display/List/List.js +5 -4
  9. package/dist/components/display/List/List.js.map +1 -1
  10. package/dist/components/display/List/List.module.js.map +1 -1
  11. package/dist/components/display/List/index.d.ts +1 -1
  12. package/dist/components/display/Media/Media.d.ts +2 -0
  13. package/dist/components/display/Media/Media.js +41 -25
  14. package/dist/components/display/Media/Media.js.map +1 -1
  15. package/dist/components/display/Table/Table.d.ts +17 -0
  16. package/dist/components/display/Table/Table.js +13 -10
  17. package/dist/components/display/Table/Table.js.map +1 -1
  18. package/dist/components/display/Table/Table.module.js.map +1 -1
  19. package/dist/components/display/Table/index.d.ts +1 -1
  20. package/dist/components/layout/Box/Box.d.ts +12 -3
  21. package/dist/components/layout/Box/Box.js +11 -10
  22. package/dist/components/layout/Box/Box.js.map +1 -1
  23. package/dist/components/layout/Box/Box.module.js.map +1 -1
  24. package/dist/components/layout/ScrollArea/ScrollArea.d.ts +36 -0
  25. package/dist/components/layout/ScrollArea/ScrollArea.js +25 -0
  26. package/dist/components/layout/ScrollArea/ScrollArea.js.map +1 -0
  27. package/dist/components/layout/ScrollArea/ScrollArea.module.js +6 -0
  28. package/dist/components/layout/ScrollArea/ScrollArea.module.js.map +1 -0
  29. package/dist/components/layout/ScrollArea/index.d.ts +2 -0
  30. package/dist/components/layout/Section/Section.d.ts +11 -2
  31. package/dist/components/layout/Section/Section.js +10 -9
  32. package/dist/components/layout/Section/Section.js.map +1 -1
  33. package/dist/components/layout/Section/Section.module.js.map +1 -1
  34. package/dist/highlight/index.d.ts +18 -0
  35. package/dist/highlight/index.js +103 -0
  36. package/dist/highlight/index.js.map +1 -0
  37. package/dist/index.d.ts +5 -3
  38. package/dist/index.js +102 -101
  39. package/dist/styles.css +1 -1
  40. package/dist/utils/newlines.d.ts +2 -0
  41. package/dist/utils/newlines.js +10 -0
  42. package/dist/utils/newlines.js.map +1 -0
  43. package/package.json +13 -2
  44. package/skills/design-rules/SKILL.md +1 -0
  45. package/skills/layout-composition/SKILL.md +2 -0
  46. package/skills/layout-composition/references/box.md +21 -1
  47. package/skills/layout-composition/references/scroll-area.md +68 -0
  48. package/skills/layout-composition/references/section.md +2 -1
  49. package/skills/setup-and-theming/SKILL.md +1 -0
@@ -3,7 +3,11 @@ import type { CategoryColor } from '../../../utils/tokens.js';
3
3
  import { type VisibilityProps } from '../../../utils/visibility.js';
4
4
  export type TableDensity = 'compact' | 'regular';
5
5
  export type TableVariant = 'rules' | 'plain';
6
+ /** `surface` and `raised` set the table on one sheet, like `Card`'s `outline` and `raised`. */
7
+ export type TableSurface = 'none' | 'surface' | 'raised';
6
8
  export type TableAlign = 'start' | 'center' | 'end';
9
+ /** Where body and footer cells sit in a row taller than their content. */
10
+ export type TableVerticalAlign = 'middle' | 'baseline' | 'top';
7
11
  export type TableSort = 'asc' | 'desc' | 'none';
8
12
  /** `fill` takes the spare width (the name column); `min` shrinks to its content. */
9
13
  export type TableColumnWidth = 'fill' | 'min';
@@ -12,8 +16,21 @@ export interface TableProps extends TableHTMLAttributes<HTMLTableElement> {
12
16
  density?: TableDensity;
13
17
  /** `rules` (default): a hairline under every row. `plain`: only the header rule. */
14
18
  variant?: TableVariant;
19
+ /**
20
+ * Where cell content sits when a row's cells differ in height (a flag and a tag beside plain
21
+ * figures). `baseline` (the default) lines up the first line of text across the row;
22
+ * `middle` centres every cell, so figures sit level with a name that has a flag or a tag beside
23
+ * or under it; `top` pins each cell to the row's top. Header cells always sit on the header rule.
24
+ */
25
+ valign?: TableVerticalAlign;
15
26
  /** Alternate row fills. Off by default — rules usually read better. */
16
27
  striped?: boolean;
28
+ /**
29
+ * Set the table on a sheet so its rows read as rows, not text on the page: `surface` is the
30
+ * surface fill inside a hairline edge, `raised` stands on the theme's surface shadow. Rows run
31
+ * edge to edge, clipped to the sheet's corners, with a little more air. Default `none`.
32
+ */
33
+ surface?: TableSurface;
17
34
  /**
18
35
  * Keep the header visible while rows scroll. The wrapper becomes the scroll container
19
36
  * (capped by `--table-max-height`, default 70vh), since a horizontally scrolling wrapper
@@ -5,22 +5,25 @@ import i from "./Table.module.js";
5
5
  import { forwardRef as a } from "react";
6
6
  import { jsx as o, jsxs as s } from "react/jsx-runtime";
7
7
  //#region src/components/display/Table/Table.tsx
8
- var c = a(function({ density: t = "regular", variant: n = "rules", striped: r = !1, stickyHeader: a = !1, label: s, className: c, ...l }, u) {
8
+ var c = a(function({ density: t = "regular", variant: n = "rules", valign: r = "baseline", striped: a = !1, surface: s = "none", stickyHeader: c = !1, label: l, className: u, ...d }, f) {
9
9
  return /* @__PURE__ */ o("div", {
10
10
  className: i.scroll,
11
11
  "data-kiln-component": "",
12
- "data-sticky-header": a || void 0,
13
- role: s ? "region" : void 0,
14
- "aria-label": s,
15
- tabIndex: s ? 0 : void 0,
12
+ "data-surface": s === "none" ? void 0 : s,
13
+ "data-sticky-header": c || void 0,
14
+ role: l ? "region" : void 0,
15
+ "aria-label": l,
16
+ tabIndex: l ? 0 : void 0,
16
17
  children: /* @__PURE__ */ o("table", {
17
- ref: u,
18
- className: e(i.table, c),
18
+ ref: f,
19
+ className: e(i.table, u),
19
20
  "data-density": t,
20
21
  "data-variant": n,
21
- "data-striped": r || void 0,
22
- "data-sticky-header": a || void 0,
23
- ...l
22
+ "data-valign": r,
23
+ "data-striped": a || void 0,
24
+ "data-surface": s === "none" ? void 0 : s,
25
+ "data-sticky-header": c || void 0,
26
+ ...d
24
27
  })
25
28
  });
26
29
  }), l = a(function({ className: t, ...n }, r) {
@@ -1 +1 @@
1
- {"version":3,"file":"Table.js","names":["styles","Table_module_default","TableRoot","forwardRef","rest","stickyHeader","label","cx","className","density","variant","striped","TableHead","TableBody","TableFoot","TableRow","highlighted","interactive","muted","color","ARIA_SORT","TableHeaderCell","sortable","sort","onSort","visibilityClass","align","numeric","width","children","jsx","ChevronUpIcon","ChevronDownIcon","TableCell","shared","rowHeader","thRest","TableCaption","Table"],"sources":["../../../../src/components/display/Table/Table.tsx"],"sourcesContent":["import {\n forwardRef,\n type HTMLAttributes,\n type TableHTMLAttributes,\n type TdHTMLAttributes,\n type ThHTMLAttributes,\n} from 'react'\nimport { cx } from '#utils/cx'\nimport type { CategoryColor } from '#utils/tokens'\nimport { visibilityClass, type VisibilityProps } from '#utils/visibility'\nimport { ChevronDownIcon, ChevronUpIcon } from '#icons'\nimport styles from './Table.module.css'\n\nexport type TableDensity = 'compact' | 'regular'\nexport type TableVariant = 'rules' | 'plain'\nexport type TableAlign = 'start' | 'center' | 'end'\nexport type TableSort = 'asc' | 'desc' | 'none'\n/** `fill` takes the spare width (the name column); `min` shrinks to its content. */\nexport type TableColumnWidth = 'fill' | 'min'\n\nexport interface TableProps extends TableHTMLAttributes<HTMLTableElement> {\n /** Row height. Default `regular`. */\n density?: TableDensity\n /** `rules` (default): a hairline under every row. `plain`: only the header rule. */\n variant?: TableVariant\n /** Alternate row fills. Off by default — rules usually read better. */\n striped?: boolean\n /**\n * Keep the header visible while rows scroll. The wrapper becomes the scroll container\n * (capped by `--table-max-height`, default 70vh), since a horizontally scrolling wrapper\n * would otherwise trap a page-sticky header.\n */\n stickyHeader?: boolean\n /**\n * Name for the scroll container. When set, the wrapper becomes a focusable, labelled\n * region so keyboard users can scroll a wide table.\n */\n label?: string\n}\n\n/**\n * A semantic data table with numeric columns that line up, sortable headers and a footer for\n * totals.\n *\n * @remarks\n * `Table` is a real `<table>` with Kiln's styles: rules between rows, numeric columns in tabular\n * figures, and a wrapper that scrolls sideways on narrow screens instead of breaking the layout.\n *\n * ## Density, stripes and sticky headers\n *\n * `density=\"compact\"` for dense data, `striped` for alternating fills (rules usually read better),\n * and `stickyHeader` to keep the header in view while the rows scroll inside the table.\n *\n * @privateRemarks\n * A semantic, styled data table: project boards, ledgers, audit logs. The wrapper scrolls\n * horizontally on narrow screens; `ref` and native props go to the `<table>`.\n *\n * <Table><Table.Head><Table.Row><Table.HeaderCell>Project</Table.HeaderCell>…</Table.Row></Table.Head>…</Table>\n */\nconst TableRoot = forwardRef<HTMLTableElement, TableProps>(function Table(\n {\n density = 'regular',\n variant = 'rules',\n striped = false,\n stickyHeader = false,\n label,\n className,\n ...rest\n },\n ref,\n) {\n return (\n <div\n className={styles.scroll}\n data-kiln-component=\"\"\n data-sticky-header={stickyHeader || undefined}\n role={label ? 'region' : undefined}\n aria-label={label}\n tabIndex={label ? 0 : undefined}\n >\n <table\n ref={ref}\n className={cx(styles.table, className)}\n data-density={density}\n data-variant={variant}\n data-striped={striped || undefined}\n data-sticky-header={stickyHeader || undefined}\n {...rest}\n />\n </div>\n )\n})\n\nconst TableHead = forwardRef<HTMLTableSectionElement, HTMLAttributes<HTMLTableSectionElement>>(\n function TableHead({ className, ...rest }, ref) {\n return <thead ref={ref} className={cx(styles.head, className)} {...rest} />\n },\n)\n\nconst TableBody = forwardRef<HTMLTableSectionElement, HTMLAttributes<HTMLTableSectionElement>>(\n function TableBody({ className, ...rest }, ref) {\n return <tbody ref={ref} className={cx(styles.body, className)} {...rest} />\n },\n)\n\n/** Totals row(s). Set above a strong rule. */\nconst TableFoot = forwardRef<HTMLTableSectionElement, HTMLAttributes<HTMLTableSectionElement>>(\n function TableFoot({ className, ...rest }, ref) {\n return <tfoot ref={ref} className={cx(styles.foot, className)} {...rest} />\n },\n)\n\nexport interface TableRowProps extends Omit<HTMLAttributes<HTMLTableRowElement>, 'color'> {\n /** `--color-highlight` fill — \"you\", your project, the circled line. */\n highlighted?: boolean\n /** Hover fill for rows that respond to clicks (put the real link in a cell). */\n interactive?: boolean\n /** Out of play (eliminated, archived, past): every ink drops to the muted step, which still reads. */\n muted?: boolean\n /** A categorical colour drawn as a rail at the row's start: whose row it is, matching their `Tag`. */\n color?: CategoryColor\n}\n\nconst TableRow = forwardRef<HTMLTableRowElement, TableRowProps>(function TableRow(\n { highlighted = false, interactive = false, muted = false, color, className, ...rest },\n ref,\n) {\n return (\n <tr\n ref={ref}\n className={cx(styles.row, className)}\n data-highlighted={highlighted || undefined}\n data-interactive={interactive || undefined}\n data-muted={muted || undefined}\n data-color={color}\n {...rest}\n />\n )\n})\n\nexport interface TableHeaderCellProps\n extends Omit<ThHTMLAttributes<HTMLTableCellElement>, 'align' | 'width'>, VisibilityProps {\n align?: TableAlign\n /** Numeric column: right-aligned with tabular figures. */\n numeric?: boolean\n /** Column sizing: `fill` takes the spare width, `min` shrinks to fit. Default: automatic. */\n width?: TableColumnWidth\n /** Current sort of this column. With `onSort`, the label becomes a button and `aria-sort` is set. */\n sort?: TableSort\n /** Called when the sort button is pressed. Decide the next direction yourself. */\n onSort?: () => void\n}\n\nconst ARIA_SORT = { asc: 'ascending', desc: 'descending', none: 'none' } as const\n\nconst TableHeaderCell = forwardRef<HTMLTableCellElement, TableHeaderCellProps>(\n function TableHeaderCell(\n {\n align,\n numeric = false,\n width,\n sort,\n onSort,\n hideBelow,\n hideAbove,\n scope = 'col',\n className,\n children,\n ...rest\n },\n ref,\n ) {\n const sortable = sort !== undefined && onSort !== undefined\n return (\n <th\n ref={ref}\n scope={scope}\n className={cx(styles.headerCell, visibilityClass({ hideBelow, hideAbove }), className)}\n data-align={align ?? (numeric ? 'end' : undefined)}\n data-numeric={numeric || undefined}\n data-width={width}\n data-sort={sortable ? sort : undefined}\n aria-sort={sort !== undefined ? ARIA_SORT[sort] : undefined}\n {...rest}\n >\n {sortable ? (\n <button type=\"button\" className={styles.sortButton} onClick={onSort}>\n {children}\n <span className={styles.sortGlyph} aria-hidden=\"true\">\n {sort === 'asc' ? <ChevronUpIcon /> : <ChevronDownIcon />}\n </span>\n </button>\n ) : (\n children\n )}\n </th>\n )\n },\n)\n\n/**\n * Hide a column on small screens: put the same `hideBelow` on its HeaderCell and on\n * every Cell in that column (cells are `display: none`, so the columns stay aligned).\n */\nexport interface TableCellProps\n extends Omit<TdHTMLAttributes<HTMLTableCellElement>, 'align'>, VisibilityProps {\n align?: TableAlign\n /** Figures: right-aligned, tabular, in the theme's numeric face (mono in Ledger). */\n numeric?: boolean\n /** Render as `<th scope=\"row\">` — the cell that names the row (project, client). */\n rowHeader?: boolean\n}\n\nconst TableCell = forwardRef<HTMLTableCellElement, TableCellProps>(function TableCell(\n { align, numeric = false, rowHeader = false, hideBelow, hideAbove, className, ...rest },\n ref,\n) {\n const shared = {\n className: cx(styles.cell, visibilityClass({ hideBelow, hideAbove }), className),\n 'data-align': align ?? (numeric ? 'end' : undefined),\n 'data-numeric': numeric || undefined,\n 'data-row-header': rowHeader || undefined,\n }\n if (rowHeader) {\n const { scope = 'row', ...thRest } = rest as ThHTMLAttributes<HTMLTableCellElement>\n return <th ref={ref} scope={scope} {...shared} {...thRest} />\n }\n return <td ref={ref} {...shared} {...rest} />\n})\n\nconst TableCaption = forwardRef<HTMLTableCaptionElement, HTMLAttributes<HTMLTableCaptionElement>>(\n function TableCaption({ className, ...rest }, ref) {\n return <caption ref={ref} className={cx(styles.caption, className)} {...rest} />\n },\n)\n\nexport const Table = Object.assign(TableRoot, {\n Head: TableHead,\n Body: TableBody,\n Foot: TableFoot,\n Row: TableRow,\n HeaderCell: TableHeaderCell,\n Cell: TableCell,\n Caption: TableCaption,\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"Table.js","names":["styles","Table_module_default","TableRoot","forwardRef","rest","surface","stickyHeader","label","cx","className","density","variant","valign","striped","TableHead","TableBody","TableFoot","TableRow","highlighted","interactive","muted","color","ARIA_SORT","TableHeaderCell","sortable","sort","onSort","visibilityClass","align","numeric","width","children","jsx","ChevronUpIcon","ChevronDownIcon","TableCell","shared","rowHeader","thRest","TableCaption","Table"],"sources":["../../../../src/components/display/Table/Table.tsx"],"sourcesContent":["import {\n forwardRef,\n type HTMLAttributes,\n type TableHTMLAttributes,\n type TdHTMLAttributes,\n type ThHTMLAttributes,\n} from 'react'\nimport { cx } from '#utils/cx'\nimport type { CategoryColor } from '#utils/tokens'\nimport { visibilityClass, type VisibilityProps } from '#utils/visibility'\nimport { ChevronDownIcon, ChevronUpIcon } from '#icons'\nimport styles from './Table.module.css'\n\nexport type TableDensity = 'compact' | 'regular'\nexport type TableVariant = 'rules' | 'plain'\n/** `surface` and `raised` set the table on one sheet, like `Card`'s `outline` and `raised`. */\nexport type TableSurface = 'none' | 'surface' | 'raised'\nexport type TableAlign = 'start' | 'center' | 'end'\n/** Where body and footer cells sit in a row taller than their content. */\nexport type TableVerticalAlign = 'middle' | 'baseline' | 'top'\nexport type TableSort = 'asc' | 'desc' | 'none'\n/** `fill` takes the spare width (the name column); `min` shrinks to its content. */\nexport type TableColumnWidth = 'fill' | 'min'\n\nexport interface TableProps extends TableHTMLAttributes<HTMLTableElement> {\n /** Row height. Default `regular`. */\n density?: TableDensity\n /** `rules` (default): a hairline under every row. `plain`: only the header rule. */\n variant?: TableVariant\n /**\n * Where cell content sits when a row's cells differ in height (a flag and a tag beside plain\n * figures). `baseline` (the default) lines up the first line of text across the row;\n * `middle` centres every cell, so figures sit level with a name that has a flag or a tag beside\n * or under it; `top` pins each cell to the row's top. Header cells always sit on the header rule.\n */\n valign?: TableVerticalAlign\n /** Alternate row fills. Off by default — rules usually read better. */\n striped?: boolean\n /**\n * Set the table on a sheet so its rows read as rows, not text on the page: `surface` is the\n * surface fill inside a hairline edge, `raised` stands on the theme's surface shadow. Rows run\n * edge to edge, clipped to the sheet's corners, with a little more air. Default `none`.\n */\n surface?: TableSurface\n /**\n * Keep the header visible while rows scroll. The wrapper becomes the scroll container\n * (capped by `--table-max-height`, default 70vh), since a horizontally scrolling wrapper\n * would otherwise trap a page-sticky header.\n */\n stickyHeader?: boolean\n /**\n * Name for the scroll container. When set, the wrapper becomes a focusable, labelled\n * region so keyboard users can scroll a wide table.\n */\n label?: string\n}\n\n/**\n * A semantic data table with numeric columns that line up, sortable headers and a footer for\n * totals.\n *\n * @remarks\n * `Table` is a real `<table>` with Kiln's styles: rules between rows, numeric columns in tabular\n * figures, and a wrapper that scrolls sideways on narrow screens instead of breaking the layout.\n *\n * ## Density, stripes and sticky headers\n *\n * `density=\"compact\"` for dense data, `striped` for alternating fills (rules usually read better),\n * and `stickyHeader` to keep the header in view while the rows scroll inside the table.\n *\n * ## On a surface\n *\n * On a busy page, or a theme whose canvas has a texture, `surface=\"surface\"` sets the table on one\n * sheet, and `surface=\"raised\"` stands it on the theme's surface shadow. Rows run edge to edge and\n * get a little more air: a highlighted row is a band across the sheet, a categorical rail is the\n * row's edge, and the sheet scrolls sideways with the table.\n *\n * @privateRemarks\n * A semantic, styled data table: project boards, ledgers, audit logs. The wrapper scrolls\n * horizontally on narrow screens; `ref` and native props go to the `<table>`.\n *\n * <Table><Table.Head><Table.Row><Table.HeaderCell>Project</Table.HeaderCell>…</Table.Row></Table.Head>…</Table>\n */\nconst TableRoot = forwardRef<HTMLTableElement, TableProps>(function Table(\n {\n density = 'regular',\n variant = 'rules',\n valign = 'baseline',\n striped = false,\n surface = 'none',\n stickyHeader = false,\n label,\n className,\n ...rest\n },\n ref,\n) {\n return (\n <div\n className={styles.scroll}\n data-kiln-component=\"\"\n data-surface={surface === 'none' ? undefined : surface}\n data-sticky-header={stickyHeader || undefined}\n role={label ? 'region' : undefined}\n aria-label={label}\n tabIndex={label ? 0 : undefined}\n >\n <table\n ref={ref}\n className={cx(styles.table, className)}\n data-density={density}\n data-variant={variant}\n data-valign={valign}\n data-striped={striped || undefined}\n data-surface={surface === 'none' ? undefined : surface}\n data-sticky-header={stickyHeader || undefined}\n {...rest}\n />\n </div>\n )\n})\n\nconst TableHead = forwardRef<HTMLTableSectionElement, HTMLAttributes<HTMLTableSectionElement>>(\n function TableHead({ className, ...rest }, ref) {\n return <thead ref={ref} className={cx(styles.head, className)} {...rest} />\n },\n)\n\nconst TableBody = forwardRef<HTMLTableSectionElement, HTMLAttributes<HTMLTableSectionElement>>(\n function TableBody({ className, ...rest }, ref) {\n return <tbody ref={ref} className={cx(styles.body, className)} {...rest} />\n },\n)\n\n/** Totals row(s). Set above a strong rule. */\nconst TableFoot = forwardRef<HTMLTableSectionElement, HTMLAttributes<HTMLTableSectionElement>>(\n function TableFoot({ className, ...rest }, ref) {\n return <tfoot ref={ref} className={cx(styles.foot, className)} {...rest} />\n },\n)\n\nexport interface TableRowProps extends Omit<HTMLAttributes<HTMLTableRowElement>, 'color'> {\n /** `--color-highlight` fill — \"you\", your project, the circled line. */\n highlighted?: boolean\n /** Hover fill for rows that respond to clicks (put the real link in a cell). */\n interactive?: boolean\n /** Out of play (eliminated, archived, past): every ink drops to the muted step, which still reads. */\n muted?: boolean\n /** A categorical colour drawn as a rail at the row's start: whose row it is, matching their `Tag`. */\n color?: CategoryColor\n}\n\nconst TableRow = forwardRef<HTMLTableRowElement, TableRowProps>(function TableRow(\n { highlighted = false, interactive = false, muted = false, color, className, ...rest },\n ref,\n) {\n return (\n <tr\n ref={ref}\n className={cx(styles.row, className)}\n data-highlighted={highlighted || undefined}\n data-interactive={interactive || undefined}\n data-muted={muted || undefined}\n data-color={color}\n {...rest}\n />\n )\n})\n\nexport interface TableHeaderCellProps\n extends Omit<ThHTMLAttributes<HTMLTableCellElement>, 'align' | 'width'>, VisibilityProps {\n align?: TableAlign\n /** Numeric column: right-aligned with tabular figures. */\n numeric?: boolean\n /** Column sizing: `fill` takes the spare width, `min` shrinks to fit. Default: automatic. */\n width?: TableColumnWidth\n /** Current sort of this column. With `onSort`, the label becomes a button and `aria-sort` is set. */\n sort?: TableSort\n /** Called when the sort button is pressed. Decide the next direction yourself. */\n onSort?: () => void\n}\n\nconst ARIA_SORT = { asc: 'ascending', desc: 'descending', none: 'none' } as const\n\nconst TableHeaderCell = forwardRef<HTMLTableCellElement, TableHeaderCellProps>(\n function TableHeaderCell(\n {\n align,\n numeric = false,\n width,\n sort,\n onSort,\n hideBelow,\n hideAbove,\n scope = 'col',\n className,\n children,\n ...rest\n },\n ref,\n ) {\n const sortable = sort !== undefined && onSort !== undefined\n return (\n <th\n ref={ref}\n scope={scope}\n className={cx(styles.headerCell, visibilityClass({ hideBelow, hideAbove }), className)}\n data-align={align ?? (numeric ? 'end' : undefined)}\n data-numeric={numeric || undefined}\n data-width={width}\n data-sort={sortable ? sort : undefined}\n aria-sort={sort !== undefined ? ARIA_SORT[sort] : undefined}\n {...rest}\n >\n {sortable ? (\n <button type=\"button\" className={styles.sortButton} onClick={onSort}>\n {children}\n <span className={styles.sortGlyph} aria-hidden=\"true\">\n {sort === 'asc' ? <ChevronUpIcon /> : <ChevronDownIcon />}\n </span>\n </button>\n ) : (\n children\n )}\n </th>\n )\n },\n)\n\n/**\n * Hide a column on small screens: put the same `hideBelow` on its HeaderCell and on\n * every Cell in that column (cells are `display: none`, so the columns stay aligned).\n */\nexport interface TableCellProps\n extends Omit<TdHTMLAttributes<HTMLTableCellElement>, 'align'>, VisibilityProps {\n align?: TableAlign\n /** Figures: right-aligned, tabular, in the theme's numeric face (mono in Ledger). */\n numeric?: boolean\n /** Render as `<th scope=\"row\">` — the cell that names the row (project, client). */\n rowHeader?: boolean\n}\n\nconst TableCell = forwardRef<HTMLTableCellElement, TableCellProps>(function TableCell(\n { align, numeric = false, rowHeader = false, hideBelow, hideAbove, className, ...rest },\n ref,\n) {\n const shared = {\n className: cx(styles.cell, visibilityClass({ hideBelow, hideAbove }), className),\n 'data-align': align ?? (numeric ? 'end' : undefined),\n 'data-numeric': numeric || undefined,\n 'data-row-header': rowHeader || undefined,\n }\n if (rowHeader) {\n const { scope = 'row', ...thRest } = rest as ThHTMLAttributes<HTMLTableCellElement>\n return <th ref={ref} scope={scope} {...shared} {...thRest} />\n }\n return <td ref={ref} {...shared} {...rest} />\n})\n\nconst TableCaption = forwardRef<HTMLTableCaptionElement, HTMLAttributes<HTMLTableCaptionElement>>(\n function TableCaption({ className, ...rest }, ref) {\n return <caption ref={ref} className={cx(styles.caption, className)} {...rest} />\n },\n)\n\nexport const Table = Object.assign(TableRoot, {\n Head: TableHead,\n Body: TableBody,\n Foot: TableFoot,\n Row: TableRow,\n HeaderCell: TableHeaderCell,\n Cell: TableCell,\n Caption: TableCaption,\n})\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Table.module.js","names":["scroll","table","caption","headerCell","cell","body","row","foot","head","sortButton","sortGlyph","Table_module_default"],"sources":["../../../../src/components/display/Table/Table.module.css"],"sourcesContent":["/*\n * Component tokens (themes may set any of these on [data-theme]):\n * --table-head-font default var(--font-text) — Fiesta sets its display caps\n * --table-head-numeric-font numeric header cells, default var(--table-head-font, var(--font-text))\n * --table-head-size default var(--text-sm)\n * --table-head-weight default var(--label-weight)\n * --table-head-transform default var(--heading-transform)\n * --table-head-bg default var(--color-canvas) — only painted when stickyHeader\n * --table-max-height default 70vh — scroll height when stickyHeader\n * --table-rail-width default var(--space-1) — the categorical rail of a `color` row\n * --table-foot-rule the rule over totals, default var(--border-width-strong) solid\n * var(--color-line-strong) — Ledger draws the accountant's double rule\n * --highlight-tone-{positive,caution,critical,info}-text, --highlight-accent-text\n * tone text inside a highlighted row (shared with List). Default:\n * the tone text mixed 25% toward --color-highlight-ink.\n *\n * Headers are labels, so they're set in the text face (monospace as decoration for small\n * labels is banned in DESIGN §2); figures below them carry the numeric face.\n */\n.scroll {\n inline-size: 100%;\n min-inline-size: 0;\n overflow-x: auto;\n overscroll-behavior-x: contain;\n}\n.scroll[data-sticky-header] {\n overflow: auto;\n max-block-size: var(--table-max-height, 70vh);\n}\n.scroll:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 2px;\n}\n\n.table {\n --_py: var(--space-2);\n --_px: var(--space-3);\n\n inline-size: 100%;\n border-collapse: separate;\n border-spacing: 0;\n font-family: var(--font-text);\n font-size: var(--text-sm);\n line-height: var(--leading-snug);\n color: var(--color-ink);\n}\n.table[data-density='compact'] {\n --_py: var(--space-1);\n --_px: var(--space-2);\n}\n\n.caption {\n caption-side: top;\n padding-block-end: var(--space-3);\n color: var(--color-ink-muted);\n font-size: var(--text-sm);\n text-align: start;\n}\n\n/* ── Cells ─────────────────────────────────────────────────────────────── */\n\n.headerCell,\n.cell {\n padding: var(--_py) var(--_px);\n text-align: start;\n vertical-align: baseline;\n}\n.headerCell:first-child,\n.cell:first-child {\n padding-inline-start: var(--space-2);\n}\n.headerCell:last-child,\n.cell:last-child {\n padding-inline-end: var(--space-2);\n}\n/* Figure columns are narrow; tighter gutters keep a 10-column figures table on a phone. */\n:is(.headerCell, .cell)[data-numeric] {\n padding-inline: var(--space-2);\n}\n.headerCell abbr {\n text-decoration: none;\n cursor: help;\n}\n:is(.headerCell, .cell)[data-align='center'] {\n text-align: center;\n}\n:is(.headerCell, .cell)[data-align='end'] {\n text-align: end;\n}\n\n.headerCell {\n padding-block: var(--_py);\n color: var(--color-ink-muted);\n font-family: var(--table-head-font, var(--font-text));\n font-size: var(--table-head-size, var(--text-sm));\n font-weight: var(--table-head-weight, var(--label-weight));\n letter-spacing: var(--label-tracking);\n text-transform: var(--table-head-transform, var(--heading-transform));\n white-space: nowrap;\n vertical-align: bottom;\n border-block-end: var(--border-width-strong) solid var(--color-line-strong);\n}\n\n.headerCell[data-numeric] {\n font-family: var(--table-head-numeric-font, var(--table-head-font, var(--font-text)));\n font-variant-numeric: tabular-nums lining-nums;\n}\n.headerCell[data-width='fill'] {\n inline-size: 100%;\n}\n.headerCell[data-width='min'] {\n inline-size: 1%;\n}\n\n.cell[data-numeric] {\n font-family: var(--font-numeric);\n font-stretch: var(--numeric-stretch);\n font-variant-numeric: tabular-nums lining-nums;\n white-space: nowrap;\n}\n.cell[data-row-header] {\n font-weight: var(--label-weight);\n}\n\n/* ── Rows ──────────────────────────────────────────────────────────────── */\n\n.table[data-variant='rules'] .body .cell {\n border-block-end: var(--border-width) solid var(--color-line);\n}\n.table[data-variant='rules'] .body > .row:last-child > .cell {\n border-block-end-color: var(--color-line-strong);\n}\n\n.table[data-striped] .body > .row:nth-child(even) > .cell {\n background: var(--color-surface-sunken);\n}\n\n/*\n * A highlighted row re-points the colour roles for its cells' content, so a muted date,\n * a tone-coloured Numeral or a LiveIndicator stays legible on the highlight fill (gold in\n * Fiesta night, where the ordinary tone texts are pale). Same approach as Section's\n * inverse band: the row publishes its fill/ink and tone texts under private names, and\n * the cells swap the roles — setting e.g. --tone-positive-text from itself on one element\n * would be a var() cycle.\n */\n.row[data-highlighted] {\n --_band-fill: var(--color-highlight);\n --_band-ink: var(--color-highlight-ink);\n --_band-positive: var(\n --highlight-tone-positive-text,\n color-mix(in oklab, var(--tone-positive-text) 75%, var(--color-highlight-ink))\n );\n --_band-caution: var(\n --highlight-tone-caution-text,\n color-mix(in oklab, var(--tone-caution-text) 75%, var(--color-highlight-ink))\n );\n --_band-critical: var(\n --highlight-tone-critical-text,\n color-mix(in oklab, var(--tone-critical-text) 75%, var(--color-highlight-ink))\n );\n --_band-info: var(\n --highlight-tone-info-text,\n color-mix(in oklab, var(--tone-info-text) 75%, var(--color-highlight-ink))\n );\n --_band-accent: var(\n --highlight-accent-text,\n color-mix(in oklab, var(--color-accent-text) 75%, var(--color-highlight-ink))\n );\n}\n.row[data-highlighted] > .cell {\n --color-ink: var(--_band-ink);\n --color-ink-muted: color-mix(in oklab, var(--_band-ink), var(--_band-fill) 25%);\n --color-ink-subtle: color-mix(in oklab, var(--_band-ink), var(--_band-fill) 35%);\n --tone-positive-text: var(--_band-positive);\n --tone-caution-text: var(--_band-caution);\n --tone-critical-text: var(--_band-critical);\n --tone-info-text: var(--_band-info);\n --color-accent-text: var(--_band-accent);\n /* Soft fills (a soft Badge or Tag) tint the band, like Section's accent band, so the\n re-pointed tone texts above stay legible on them in every mode. */\n --tone-positive-soft: color-mix(in oklab, var(--_band-positive) 8%, var(--_band-fill));\n --tone-caution-soft: color-mix(in oklab, var(--_band-caution) 8%, var(--_band-fill));\n --tone-critical-soft: color-mix(in oklab, var(--_band-critical) 8%, var(--_band-fill));\n --tone-info-soft: color-mix(in oklab, var(--_band-info) 8%, var(--_band-fill));\n --color-accent-soft: color-mix(in oklab, var(--_band-accent) 8%, var(--_band-fill));\n\n background: var(--_band-fill);\n color: var(--_band-ink);\n}\n/* Round the ends of a highlighted row so the fill reads as a marker, not a stripe. */\n.row[data-highlighted] > .cell:first-child {\n border-start-start-radius: var(--radius-field);\n border-end-start-radius: var(--radius-field);\n}\n.row[data-highlighted] > .cell:last-child {\n border-start-end-radius: var(--radius-field);\n border-end-end-radius: var(--radius-field);\n}\n\n.row[data-interactive] {\n cursor: pointer;\n}\n\n/* Muted: out of play. Every ink drops to the muted step, which still clears AA. */\n.row[data-muted] > .cell {\n --color-ink: var(--color-ink-muted);\n\n color: var(--color-ink-muted);\n}\n\n/* A categorical rail at the row's start: whose row it is, in their Tag's colour. */\n.row[data-color] > .cell:first-child {\n position: relative;\n padding-inline-start: calc(var(--space-2) + var(--space-2));\n}\n.row[data-color] > .cell:first-child::before {\n content: '';\n position: absolute;\n inset-block: var(--space-1);\n inset-inline-start: 0;\n inline-size: var(--table-rail-width, var(--space-1));\n border-radius: var(--radius-chip);\n background: var(--_cat);\n}\n.row[data-color='1'] {\n --_cat: var(--color-cat-1);\n}\n.row[data-color='2'] {\n --_cat: var(--color-cat-2);\n}\n.row[data-color='3'] {\n --_cat: var(--color-cat-3);\n}\n.row[data-color='4'] {\n --_cat: var(--color-cat-4);\n}\n.row[data-color='5'] {\n --_cat: var(--color-cat-5);\n}\n.row[data-color='6'] {\n --_cat: var(--color-cat-6);\n}\n.row[data-color='7'] {\n --_cat: var(--color-cat-7);\n}\n.row[data-color='8'] {\n --_cat: var(--color-cat-8);\n}\n.row > .cell {\n transition: background-color var(--dur-1) var(--ease-out);\n}\n@media (hover: hover) {\n .row[data-interactive]:not([data-highlighted]):hover > .cell {\n background: var(--color-surface-sunken);\n }\n}\n\n.foot > :first-child > .cell {\n border-block-start: var(\n --table-foot-rule,\n var(--border-width-strong) solid var(--color-line-strong)\n );\n}\n.foot .cell {\n font-weight: var(--label-weight);\n}\n/* The totals rule replaces the last row's hairline rather than stacking under it. */\n.table[data-variant='rules'] .body:has(+ .foot) > .row:last-child > .cell {\n border-block-end-width: 0;\n}\n\n/* ── Sticky header ─────────────────────────────────────────────────────── */\n\n.table[data-sticky-header] .head .headerCell {\n position: sticky;\n inset-block-start: 0;\n z-index: 1;\n background: var(--table-head-bg, var(--color-canvas));\n}\n\n/* ── Sort button ───────────────────────────────────────────────────────── */\n\n.sortButton {\n display: inline-flex;\n align-items: center;\n gap: 0.25em;\n margin: calc(var(--space-1) * -1);\n padding: var(--space-1);\n border: 0;\n border-radius: var(--radius-field);\n background: transparent;\n color: inherit;\n font: inherit;\n letter-spacing: inherit;\n text-transform: inherit;\n cursor: pointer;\n transition: color var(--dur-1) var(--ease-out);\n}\n.headerCell[data-align='end'] .sortButton {\n flex-direction: row-reverse;\n}\n@media (hover: hover) {\n .sortButton:hover {\n color: var(--color-ink);\n }\n}\n.sortButton:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 0;\n}\n.sortGlyph {\n display: inline-flex;\n font-size: 1.1em;\n opacity: 0;\n transition: opacity var(--dur-1) var(--ease-out);\n}\n.headerCell:is([data-sort='asc'], [data-sort='desc']) {\n color: var(--color-ink);\n}\n.headerCell:is([data-sort='asc'], [data-sort='desc']) .sortGlyph,\n.sortButton:hover .sortGlyph,\n.sortButton:focus-visible .sortGlyph {\n opacity: 1;\n}\n.headerCell[data-sort='none'] .sortButton:is(:hover, :focus-visible) .sortGlyph {\n opacity: 0.45;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Table.module.js","names":["scroll","table","caption","headerCell","cell","body","row","foot","head","sortButton","sortGlyph","Table_module_default"],"sources":["../../../../src/components/display/Table/Table.module.css"],"sourcesContent":["/*\n * Component tokens (themes may set any of these on [data-theme]):\n * --table-head-font default var(--font-text) — Fiesta sets its display caps\n * --table-head-numeric-font numeric header cells, default var(--table-head-font, var(--font-text))\n * --table-head-size default var(--text-sm)\n * --table-head-weight default var(--label-weight)\n * --table-head-transform default var(--heading-transform)\n * --table-head-bg default var(--color-canvas), the sheet's fill on a `surface`\n * table — only painted when stickyHeader\n * --table-max-height default 70vh — scroll height when stickyHeader\n * --table-rail-width default var(--space-1) — the categorical rail of a `color` row\n * --table-surface-bg default var(--color-surface), var(--color-surface-raised) when `raised`\n * --table-surface-radius default var(--radius-surface) — the sheet of a `surface` table\n * --table-foot-rule the rule over totals, default var(--border-width-strong) solid\n * var(--color-line-strong) — Ledger draws the accountant's double rule\n * --highlight-tone-{positive,caution,critical,info}-text, --highlight-accent-text\n * tone text inside a highlighted row (shared with List). Default:\n * the tone text mixed 25% toward --color-highlight-ink.\n *\n * Headers are labels, so they're set in the text face (monospace as decoration for small\n * labels is banned in DESIGN §2); figures below them carry the numeric face.\n */\n.scroll {\n inline-size: 100%;\n min-inline-size: 0;\n overflow-x: auto;\n overscroll-behavior-x: contain;\n}\n.scroll[data-sticky-header] {\n overflow: auto;\n max-block-size: var(--table-max-height, 70vh);\n}\n/*\n * On a surface: the wrapper is the sheet, with Card's edges (`outline` for surface, `raised`\n * for raised), so it scrolls sideways with the table and rows read as rows on a textured or\n * busy canvas. Rows run edge to edge and the scroll container clips them to its radius, so a\n * highlighted row is a band across the sheet and a categorical rail sits flush with the\n * sheet's inner edge, following its corners on the first and last rows.\n */\n.scroll[data-surface] {\n --_sheet-bg: var(--table-surface-bg, var(--color-surface));\n\n border: var(--border-width) solid var(--color-line);\n border-radius: var(--table-surface-radius, var(--radius-surface));\n background: var(--_sheet-bg);\n}\n.scroll[data-surface='raised'] {\n --_sheet-bg: var(--table-surface-bg, var(--color-surface-raised));\n\n border-color: var(--color-line-strong);\n box-shadow: var(--shadow-surface);\n}\n.scroll:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 2px;\n}\n\n.table {\n --_py: var(--space-2);\n --_px: var(--space-3);\n --_edge: var(--space-2);\n --_row-radius: var(--radius-field);\n --_valign: baseline;\n\n inline-size: 100%;\n border-collapse: separate;\n border-spacing: 0;\n font-family: var(--font-text);\n font-size: var(--text-sm);\n line-height: var(--leading-snug);\n color: var(--color-ink);\n}\n.table[data-valign='middle'] {\n --_valign: middle;\n}\n.table[data-valign='top'] {\n --_valign: top;\n}\n.table[data-density='compact'] {\n --_py: var(--space-1);\n --_px: var(--space-2);\n}\n/* On a sheet rows get more air, and the end cells a wider inset so text clears the edge. */\n.table[data-surface] {\n --_py: var(--space-3);\n --_edge: var(--space-4);\n --_row-radius: 0px;\n}\n.table[data-surface][data-density='compact'] {\n --_py: var(--space-2);\n}\n\n.caption {\n caption-side: top;\n padding-block-end: var(--space-3);\n color: var(--color-ink-muted);\n font-size: var(--text-sm);\n text-align: start;\n}\n/* On a sheet the caption lines up with the first column instead of the sheet's edge. */\n.table[data-surface] > .caption {\n padding-block-start: var(--space-3);\n padding-inline: var(--_edge);\n}\n\n/* ── Cells ─────────────────────────────────────────────────────────────── */\n\n.headerCell,\n.cell {\n padding: var(--_py) var(--_px);\n text-align: start;\n vertical-align: var(--_valign);\n}\n.headerCell:first-child,\n.cell:first-child {\n padding-inline-start: var(--_edge);\n}\n.headerCell:last-child,\n.cell:last-child {\n padding-inline-end: var(--_edge);\n}\n/* Figure columns are narrow; tighter gutters keep a 10-column figures table on a phone. */\n:is(.headerCell, .cell)[data-numeric] {\n padding-inline: var(--space-2);\n}\n.headerCell abbr {\n text-decoration: none;\n cursor: help;\n}\n:is(.headerCell, .cell)[data-align='center'] {\n text-align: center;\n}\n:is(.headerCell, .cell)[data-align='end'] {\n text-align: end;\n}\n\n.headerCell {\n padding-block: var(--_py);\n color: var(--color-ink-muted);\n font-family: var(--table-head-font, var(--font-text));\n font-size: var(--table-head-size, var(--text-sm));\n font-weight: var(--table-head-weight, var(--label-weight));\n letter-spacing: var(--label-tracking);\n text-transform: var(--table-head-transform, var(--heading-transform));\n white-space: nowrap;\n vertical-align: bottom;\n border-block-end: var(--border-width-strong) solid var(--color-line-strong);\n}\n\n.headerCell[data-numeric] {\n font-family: var(--table-head-numeric-font, var(--table-head-font, var(--font-text)));\n font-variant-numeric: tabular-nums lining-nums;\n}\n.headerCell[data-width='fill'] {\n inline-size: 100%;\n}\n.headerCell[data-width='min'] {\n inline-size: 1%;\n}\n\n.cell[data-numeric] {\n font-family: var(--font-numeric);\n font-stretch: var(--numeric-stretch);\n font-variant-numeric: tabular-nums lining-nums;\n white-space: nowrap;\n}\n.cell[data-row-header] {\n font-weight: var(--label-weight);\n}\n\n/* ── Rows ──────────────────────────────────────────────────────────────── */\n\n.table[data-variant='rules'] .body .cell {\n border-block-end: var(--border-width) solid var(--color-line);\n}\n.table[data-variant='rules'] .body > .row:last-child > .cell {\n border-block-end-color: var(--color-line-strong);\n}\n/* On a sheet, its edge closes the table: no closing rule just inside it. */\n.table[data-surface][data-variant='rules'] .body:last-child > .row:last-child > .cell {\n border-block-end-color: transparent;\n}\n\n.table[data-striped] .body > .row:nth-child(even) > .cell {\n background: var(--color-surface-sunken);\n}\n\n/*\n * A highlighted row re-points the colour roles for its cells' content, so a muted date,\n * a tone-coloured Numeral or a LiveIndicator stays legible on the highlight fill (gold in\n * Fiesta night, where the ordinary tone texts are pale). Same approach as Section's\n * inverse band: the row publishes its fill/ink and tone texts under private names, and\n * the cells swap the roles — setting e.g. --tone-positive-text from itself on one element\n * would be a var() cycle.\n */\n.row[data-highlighted] {\n --_band-fill: var(--color-highlight);\n --_band-ink: var(--color-highlight-ink);\n --_band-positive: var(\n --highlight-tone-positive-text,\n color-mix(in oklab, var(--tone-positive-text) 75%, var(--color-highlight-ink))\n );\n --_band-caution: var(\n --highlight-tone-caution-text,\n color-mix(in oklab, var(--tone-caution-text) 75%, var(--color-highlight-ink))\n );\n --_band-critical: var(\n --highlight-tone-critical-text,\n color-mix(in oklab, var(--tone-critical-text) 75%, var(--color-highlight-ink))\n );\n --_band-info: var(\n --highlight-tone-info-text,\n color-mix(in oklab, var(--tone-info-text) 75%, var(--color-highlight-ink))\n );\n --_band-accent: var(\n --highlight-accent-text,\n color-mix(in oklab, var(--color-accent-text) 75%, var(--color-highlight-ink))\n );\n}\n.row[data-highlighted] > .cell {\n --color-ink: var(--_band-ink);\n --color-ink-muted: color-mix(in oklab, var(--_band-ink), var(--_band-fill) 25%);\n --color-ink-subtle: color-mix(in oklab, var(--_band-ink), var(--_band-fill) 35%);\n --tone-positive-text: var(--_band-positive);\n --tone-caution-text: var(--_band-caution);\n --tone-critical-text: var(--_band-critical);\n --tone-info-text: var(--_band-info);\n --color-accent-text: var(--_band-accent);\n /* Soft fills (a soft Badge or Tag) tint the band, like Section's accent band, so the\n re-pointed tone texts above stay legible on them in every mode. */\n --tone-positive-soft: color-mix(in oklab, var(--_band-positive) 8%, var(--_band-fill));\n --tone-caution-soft: color-mix(in oklab, var(--_band-caution) 8%, var(--_band-fill));\n --tone-critical-soft: color-mix(in oklab, var(--_band-critical) 8%, var(--_band-fill));\n --tone-info-soft: color-mix(in oklab, var(--_band-info) 8%, var(--_band-fill));\n --color-accent-soft: color-mix(in oklab, var(--_band-accent) 8%, var(--_band-fill));\n\n background: var(--_band-fill);\n color: var(--_band-ink);\n}\n/* Round the ends of a highlighted row so the fill reads as a marker, not a stripe. */\n.row[data-highlighted] > .cell:first-child {\n border-start-start-radius: var(--_row-radius);\n border-end-start-radius: var(--_row-radius);\n}\n.row[data-highlighted] > .cell:last-child {\n border-start-end-radius: var(--_row-radius);\n border-end-end-radius: var(--_row-radius);\n}\n\n.row[data-interactive] {\n cursor: pointer;\n}\n\n/* Muted: out of play. Every ink drops to the muted step, which still clears AA. */\n.row[data-muted] > .cell {\n --color-ink: var(--color-ink-muted);\n\n color: var(--color-ink-muted);\n}\n\n/* A categorical rail at the row's start: whose row it is, in their Tag's colour. */\n.row[data-color] > .cell:first-child {\n position: relative;\n padding-inline-start: calc(var(--_edge) + var(--space-2));\n}\n.row[data-color] > .cell:first-child::before {\n content: '';\n position: absolute;\n inset-block: var(--space-1);\n inset-inline-start: 0;\n inline-size: var(--table-rail-width, var(--space-1));\n border-radius: var(--radius-chip);\n background: var(--_cat);\n}\n/* On a sheet the rail is an edge of the row: full height, square, and over the rule below it. */\n.table[data-surface] .row[data-color] > .cell:first-child::before {\n inset-block: 0;\n border-radius: 0;\n}\n.table[data-surface][data-variant='rules'] .body .row[data-color] > .cell:first-child::before {\n inset-block-end: calc(var(--border-width) * -1);\n}\n.row[data-color='1'] {\n --_cat: var(--color-cat-1);\n}\n.row[data-color='2'] {\n --_cat: var(--color-cat-2);\n}\n.row[data-color='3'] {\n --_cat: var(--color-cat-3);\n}\n.row[data-color='4'] {\n --_cat: var(--color-cat-4);\n}\n.row[data-color='5'] {\n --_cat: var(--color-cat-5);\n}\n.row[data-color='6'] {\n --_cat: var(--color-cat-6);\n}\n.row[data-color='7'] {\n --_cat: var(--color-cat-7);\n}\n.row[data-color='8'] {\n --_cat: var(--color-cat-8);\n}\n.row > .cell {\n transition: background-color var(--dur-1) var(--ease-out);\n}\n@media (hover: hover) {\n .row[data-interactive]:not([data-highlighted]):hover > .cell {\n background: var(--color-surface-sunken);\n }\n}\n\n.foot > :first-child > .cell {\n border-block-start: var(\n --table-foot-rule,\n var(--border-width-strong) solid var(--color-line-strong)\n );\n}\n.foot .cell {\n font-weight: var(--label-weight);\n}\n/* The totals rule replaces the last row's hairline rather than stacking under it. */\n.table[data-variant='rules'] .body:has(+ .foot) > .row:last-child > .cell {\n border-block-end-width: 0;\n}\n\n/* ── Sticky header ─────────────────────────────────────────────────────── */\n\n.table[data-sticky-header] .head .headerCell {\n position: sticky;\n inset-block-start: 0;\n z-index: 1;\n background: var(--table-head-bg, var(--color-canvas));\n}\n.table[data-surface][data-sticky-header] .head .headerCell {\n background: var(--table-head-bg, var(--_sheet-bg));\n}\n\n/* ── Sort button ───────────────────────────────────────────────────────── */\n\n.sortButton {\n display: inline-flex;\n align-items: center;\n gap: 0.25em;\n margin: calc(var(--space-1) * -1);\n padding: var(--space-1);\n border: 0;\n border-radius: var(--radius-field);\n background: transparent;\n color: inherit;\n font: inherit;\n letter-spacing: inherit;\n text-transform: inherit;\n cursor: pointer;\n transition: color var(--dur-1) var(--ease-out);\n}\n.headerCell[data-align='end'] .sortButton {\n flex-direction: row-reverse;\n}\n@media (hover: hover) {\n .sortButton:hover {\n color: var(--color-ink);\n }\n}\n.sortButton:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 0;\n}\n.sortGlyph {\n display: inline-flex;\n font-size: 1.1em;\n opacity: 0;\n transition: opacity var(--dur-1) var(--ease-out);\n}\n.headerCell:is([data-sort='asc'], [data-sort='desc']) {\n color: var(--color-ink);\n}\n.headerCell:is([data-sort='asc'], [data-sort='desc']) .sortGlyph,\n.sortButton:hover .sortGlyph,\n.sortButton:focus-visible .sortGlyph {\n opacity: 1;\n}\n.headerCell[data-sort='none'] .sortButton:is(:hover, :focus-visible) .sortGlyph {\n opacity: 0.45;\n}\n"],"mappings":""}
@@ -1,2 +1,2 @@
1
1
  export { Table } from './Table.js';
2
- export type { TableProps, TableDensity, TableVariant, TableAlign, TableSort, TableColumnWidth, TableRowProps, TableHeaderCellProps, TableCellProps, } from './Table.js';
2
+ export type { TableProps, TableDensity, TableVariant, TableSurface, TableAlign, TableVerticalAlign, TableSort, TableColumnWidth, TableRowProps, TableHeaderCellProps, TableCellProps, } from './Table.js';
@@ -3,7 +3,7 @@ import { type Responsive } from '../../../utils/responsive.js';
3
3
  import { type Space, type CategoryColor } from '../../../utils/tokens.js';
4
4
  import { type VisibilityProps } from '../../../utils/visibility.js';
5
5
  export type BoxElement = 'div' | 'span' | 'section' | 'article' | 'aside' | 'header' | 'footer' | 'li';
6
- export type BoxSurface = 'none' | 'canvas' | 'surface' | 'sunken' | 'raised' | 'inverse' | `cat-${CategoryColor}`;
6
+ export type BoxSurface = 'none' | 'canvas' | 'surface' | 'sunken' | 'raised' | 'inverse' | 'accent' | `cat-${CategoryColor}`;
7
7
  export type BoxRadius = 'none' | 'field' | 'surface' | 'media';
8
8
  export interface BoxProps extends HTMLAttributes<HTMLElement>, VisibilityProps {
9
9
  /** Padding on every side. Responsive. */
@@ -13,10 +13,19 @@ export interface BoxProps extends HTMLAttributes<HTMLElement>, VisibilityProps {
13
13
  /** Block (top/bottom) padding; overrides `padding` on that axis. Responsive. */
14
14
  paddingY?: Responsive<Space>;
15
15
  /**
16
- * Background fill. `inverse` and the categorical `cat-1` to `cat-8` (one person's or team's
17
- * colour, matching their `Tag`) also re-point ink and line colours for its children.
16
+ * Background fill. `inverse`, `accent` and the categorical `cat-1` to `cat-8` (one person's or
17
+ * team's colour, matching their `Tag`) also re-point ink, line and accent colours for its
18
+ * children, so they stay legible on the fill.
18
19
  */
19
20
  surface?: BoxSurface;
21
+ /**
22
+ * On an `inverse`, `accent` or categorical fill, re-point the status tones too, so tone text
23
+ * and soft tone fills (a `Stat` delta, a toned `Numeral` or `Text`, a soft `Badge`) stay AA on
24
+ * the fill. On `accent` and categorical fills tone text becomes the fill's ink, so the sign,
25
+ * glyph or label carries the status; on `inverse` each tone keeps its hue. Off by default, so
26
+ * tones keep the page's colours. No effect on other surfaces.
27
+ */
28
+ adaptTones?: boolean;
20
29
  /** Hairline border in `--color-line`. One edge treatment per element — a border *or* a fill. */
21
30
  border?: boolean;
22
31
  /** Corner radius, by role. */
@@ -6,18 +6,19 @@ import a from "./Box.module.js";
6
6
  import { forwardRef as o } from "react";
7
7
  import { jsx as s } from "react/jsx-runtime";
8
8
  //#region src/components/layout/Box/Box.tsx
9
- var c = o(function({ padding: o, paddingX: c, paddingY: l, surface: u = "none", border: d = !1, radius: f = "none", as: p = "div", hideBelow: m, hideAbove: h, className: g, style: _, ...v }, y) {
10
- return /* @__PURE__ */ s(p, {
11
- ref: y,
9
+ var c = o(function({ padding: o, paddingX: c, paddingY: l, surface: u = "none", adaptTones: d = !1, border: f = !1, radius: p = "none", as: m = "div", hideBelow: h, hideAbove: g, className: _, style: v, ...y }, b) {
10
+ return /* @__PURE__ */ s(m, {
11
+ ref: b,
12
12
  className: e(a.box, i({
13
- hideBelow: m,
14
- hideAbove: h
15
- }), g),
13
+ hideBelow: h,
14
+ hideAbove: g
15
+ }), _),
16
16
  "data-surface": u === "none" ? void 0 : u,
17
- "data-border": d || void 0,
18
- "data-radius": f === "none" ? void 0 : f,
19
- style: t(n("box-p", o, r), n("box-px", c, r), n("box-py", l, r), _),
20
- ...v
17
+ "data-adapt-tones": d || void 0,
18
+ "data-border": f || void 0,
19
+ "data-radius": p === "none" ? void 0 : p,
20
+ style: t(n("box-p", o, r), n("box-px", c, r), n("box-py", l, r), v),
21
+ ...y
21
22
  });
22
23
  });
23
24
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"Box.js","names":["styles","Box_module_default","Box","forwardRef","Comp","rest","cx","visibilityClass","className","surface","border","radius","mergeStyles","responsiveVars","padding","space","paddingX","paddingY","style"],"sources":["../../../../src/components/layout/Box/Box.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes } from 'react'\nimport { cx } from '#utils/cx'\nimport { mergeStyles, responsiveVars, type Responsive } from '#utils/responsive'\nimport { space, type Space, type CategoryColor } from '#utils/tokens'\nimport styles from './Box.module.css'\nimport { visibilityClass, type VisibilityProps } from '#utils/visibility'\n\nexport type BoxElement =\n 'div' | 'span' | 'section' | 'article' | 'aside' | 'header' | 'footer' | 'li'\nexport type BoxSurface =\n 'none' | 'canvas' | 'surface' | 'sunken' | 'raised' | 'inverse' | `cat-${CategoryColor}`\nexport type BoxRadius = 'none' | 'field' | 'surface' | 'media'\n\nexport interface BoxProps extends HTMLAttributes<HTMLElement>, VisibilityProps {\n /** Padding on every side. Responsive. */\n padding?: Responsive<Space>\n /** Inline (left/right) padding; overrides `padding` on that axis. Responsive. */\n paddingX?: Responsive<Space>\n /** Block (top/bottom) padding; overrides `padding` on that axis. Responsive. */\n paddingY?: Responsive<Space>\n /**\n * Background fill. `inverse` and the categorical `cat-1` to `cat-8` (one person's or team's\n * colour, matching their `Tag`) also re-point ink and line colours for its children.\n */\n surface?: BoxSurface\n /** Hairline border in `--color-line`. One edge treatment per element — a border *or* a fill. */\n border?: boolean\n /** Corner radius, by role. */\n radius?: BoxRadius\n as?: BoxElement\n}\n\n/**\n * Padding, a surface and an edge, and nothing else. The escape hatch when no other layout fits.\n *\n * @remarks\n * `Box` adds padding, a background surface, a border and a radius to its content. Reach for\n * `Stack`, `Inline` or `Grid` to arrange things, and for `Card` when something is a self-contained\n * object. `Box` is for the wells and frames left over.\n *\n * @privateRemarks\n * The escape hatch: padding, a surface and an edge — nothing else. Reach for\n * Stack/Inline/Grid for arrangement and Card for self-contained objects first.\n *\n * <Box padding={{ base: 4, md: 5 }} surface=\"sunken\" radius=\"surface\">…</Box>\n */\nexport const Box = forwardRef<HTMLElement, BoxProps>(function Box(\n {\n padding,\n paddingX,\n paddingY,\n surface = 'none',\n border = false,\n radius = 'none',\n as: Comp = 'div',\n hideBelow,\n hideAbove,\n className,\n style,\n ...rest\n },\n ref,\n) {\n return (\n <Comp\n // @ts-expect-error — polymorphic ref across a union of intrinsic elements is safe here\n ref={ref}\n className={cx(styles.box, visibilityClass({ hideBelow, hideAbove }), className)}\n data-surface={surface === 'none' ? undefined : surface}\n data-border={border || undefined}\n data-radius={radius === 'none' ? undefined : radius}\n style={mergeStyles(\n responsiveVars('box-p', padding, space),\n responsiveVars('box-px', paddingX, space),\n responsiveVars('box-py', paddingY, space),\n style,\n )}\n {...rest}\n />\n )\n})\n"],"mappings":";;;;;;;;AA8CA,IAAaE,IAAMC,EAAkC,SACnD,EACE,YACA,aACA,aACA,aAAU,QACV,YAAS,IACT,YAAS,QACT,IAAIC,IAAO,OACX,cACA,cACA,cACA,UACA,GAAGC,KAEL,GACA;CACA,OACE,kBAACD,GAAD;EAEO;EACL,WAAWE,EAAGN,EAAO,KAAKO,EAAgB;GAAE;GAAW;EAAU,CAAC,GAAGC,CAAS;EAC9E,gBAAcC,MAAY,SAAS,KAAA,IAAYA;EAC/C,eAAaC,KAAU,KAAA;EACvB,eAAaC,MAAW,SAAS,KAAA,IAAYA;EAC7C,OAAOC,EACLC,EAAe,SAASC,GAASC,CAAK,GACtCF,EAAe,UAAUG,GAAUD,CAAK,GACxCF,EAAe,UAAUI,GAAUF,CAAK,GACxCG,CACF;EACA,GAAIb;CACL,CAAA;AAEL,CAAC"}
1
+ {"version":3,"file":"Box.js","names":["styles","Box_module_default","Box","forwardRef","Comp","rest","cx","visibilityClass","className","surface","adaptTones","border","radius","mergeStyles","responsiveVars","padding","space","paddingX","paddingY","style"],"sources":["../../../../src/components/layout/Box/Box.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes } from 'react'\nimport { cx } from '#utils/cx'\nimport { mergeStyles, responsiveVars, type Responsive } from '#utils/responsive'\nimport { space, type Space, type CategoryColor } from '#utils/tokens'\nimport styles from './Box.module.css'\nimport { visibilityClass, type VisibilityProps } from '#utils/visibility'\n\nexport type BoxElement =\n 'div' | 'span' | 'section' | 'article' | 'aside' | 'header' | 'footer' | 'li'\nexport type BoxSurface =\n | 'none'\n | 'canvas'\n | 'surface'\n | 'sunken'\n | 'raised'\n | 'inverse'\n | 'accent'\n | `cat-${CategoryColor}`\nexport type BoxRadius = 'none' | 'field' | 'surface' | 'media'\n\nexport interface BoxProps extends HTMLAttributes<HTMLElement>, VisibilityProps {\n /** Padding on every side. Responsive. */\n padding?: Responsive<Space>\n /** Inline (left/right) padding; overrides `padding` on that axis. Responsive. */\n paddingX?: Responsive<Space>\n /** Block (top/bottom) padding; overrides `padding` on that axis. Responsive. */\n paddingY?: Responsive<Space>\n /**\n * Background fill. `inverse`, `accent` and the categorical `cat-1` to `cat-8` (one person's or\n * team's colour, matching their `Tag`) also re-point ink, line and accent colours for its\n * children, so they stay legible on the fill.\n */\n surface?: BoxSurface\n /**\n * On an `inverse`, `accent` or categorical fill, re-point the status tones too, so tone text\n * and soft tone fills (a `Stat` delta, a toned `Numeral` or `Text`, a soft `Badge`) stay AA on\n * the fill. On `accent` and categorical fills tone text becomes the fill's ink, so the sign,\n * glyph or label carries the status; on `inverse` each tone keeps its hue. Off by default, so\n * tones keep the page's colours. No effect on other surfaces.\n */\n adaptTones?: boolean\n /** Hairline border in `--color-line`. One edge treatment per element — a border *or* a fill. */\n border?: boolean\n /** Corner radius, by role. */\n radius?: BoxRadius\n as?: BoxElement\n}\n\n/**\n * Padding, a surface and an edge, and nothing else. The escape hatch when no other layout fits.\n *\n * @remarks\n * `Box` adds padding, a background surface, a border and a radius to its content. Reach for\n * `Stack`, `Inline` or `Grid` to arrange things, and for `Card` when something is a self-contained\n * object. `Box` is for the wells and frames left over.\n *\n * @privateRemarks\n * The escape hatch: padding, a surface and an edge — nothing else. Reach for\n * Stack/Inline/Grid for arrangement and Card for self-contained objects first.\n *\n * <Box padding={{ base: 4, md: 5 }} surface=\"sunken\" radius=\"surface\">…</Box>\n */\nexport const Box = forwardRef<HTMLElement, BoxProps>(function Box(\n {\n padding,\n paddingX,\n paddingY,\n surface = 'none',\n adaptTones = false,\n border = false,\n radius = 'none',\n as: Comp = 'div',\n hideBelow,\n hideAbove,\n className,\n style,\n ...rest\n },\n ref,\n) {\n return (\n <Comp\n // @ts-expect-error — polymorphic ref across a union of intrinsic elements is safe here\n ref={ref}\n className={cx(styles.box, visibilityClass({ hideBelow, hideAbove }), className)}\n data-surface={surface === 'none' ? undefined : surface}\n data-adapt-tones={adaptTones || undefined}\n data-border={border || undefined}\n data-radius={radius === 'none' ? undefined : radius}\n style={mergeStyles(\n responsiveVars('box-p', padding, space),\n responsiveVars('box-px', paddingX, space),\n responsiveVars('box-py', paddingY, space),\n style,\n )}\n {...rest}\n />\n )\n})\n"],"mappings":";;;;;;;;AA8DA,IAAaE,IAAMC,EAAkC,SACnD,EACE,YACA,aACA,aACA,aAAU,QACV,gBAAa,IACb,YAAS,IACT,YAAS,QACT,IAAIC,IAAO,OACX,cACA,cACA,cACA,UACA,GAAGC,KAEL,GACA;CACA,OACE,kBAACD,GAAD;EAEO;EACL,WAAWE,EAAGN,EAAO,KAAKO,EAAgB;GAAE;GAAW;EAAU,CAAC,GAAGC,CAAS;EAC9E,gBAAcC,MAAY,SAAS,KAAA,IAAYA;EAC/C,oBAAkBC,KAAc,KAAA;EAChC,eAAaC,KAAU,KAAA;EACvB,eAAaC,MAAW,SAAS,KAAA,IAAYA;EAC7C,OAAOC,EACLC,EAAe,SAASC,GAASC,CAAK,GACtCF,EAAe,UAAUG,GAAUD,CAAK,GACxCF,EAAe,UAAUI,GAAUF,CAAK,GACxCG,CACF;EACA,GAAId;CACL,CAAA;AAEL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Box.module.js","names":["box","Box_module_default"],"sources":["../../../../src/components/layout/Box/Box.module.css"],"sourcesContent":["/*\n * Responsive pattern: see layout/Stack/Stack.module.css. Axis padding (--box-px/-py)\n * falls back to the all-sides value (--box-p) per breakpoint.\n *\n * --box-fill / --box-on (read-only): the fill and ink of an `inverse` Box.\n */\n.box {\n --_p: var(--box-p-base, 0px);\n --_px: var(--box-px-base, var(--_p));\n --_py: var(--box-py-base, var(--_p));\n\n display: block;\n min-inline-size: 0;\n padding-block: var(--_py);\n padding-inline: var(--_px);\n}\n\n@media (min-width: 40em) {\n .box {\n --_p: var(--box-p-sm, 0px);\n --_px: var(--box-px-sm, var(--_p));\n --_py: var(--box-py-sm, var(--_p));\n }\n}\n@media (min-width: 48em) {\n .box {\n --_p: var(--box-p-md, 0px);\n --_px: var(--box-px-md, var(--_p));\n --_py: var(--box-py-md, var(--_p));\n }\n}\n@media (min-width: 64em) {\n .box {\n --_p: var(--box-p-lg, 0px);\n --_px: var(--box-px-lg, var(--_p));\n --_py: var(--box-py-lg, var(--_p));\n }\n}\n@media (min-width: 80em) {\n .box {\n --_p: var(--box-p-xl, 0px);\n --_px: var(--box-px-xl, var(--_p));\n --_py: var(--box-py-xl, var(--_p));\n }\n}\n\n/* Surfaces */\n.box[data-surface='canvas'] {\n background-color: var(--color-canvas);\n background-image: var(--canvas-image);\n background-size: var(--canvas-image-size);\n color: var(--color-ink);\n}\n.box[data-surface='surface'] {\n background-color: var(--color-surface);\n color: var(--color-ink);\n}\n.box[data-surface='sunken'] {\n background-color: var(--color-surface-sunken);\n color: var(--color-ink);\n}\n.box[data-surface='raised'] {\n background-color: var(--color-surface-raised);\n color: var(--color-ink);\n}\n/* Inverse and categorical fills re-point the colour roles for descendants — same approach as Section. */\n.box[data-surface='inverse'] {\n --box-fill: var(--color-surface-inverse);\n --box-on: var(--color-ink-inverse);\n}\n.box[data-surface='cat-1'] {\n --box-fill: var(--color-cat-1);\n}\n.box[data-surface='cat-2'] {\n --box-fill: var(--color-cat-2);\n}\n.box[data-surface='cat-3'] {\n --box-fill: var(--color-cat-3);\n}\n.box[data-surface='cat-4'] {\n --box-fill: var(--color-cat-4);\n}\n.box[data-surface='cat-5'] {\n --box-fill: var(--color-cat-5);\n}\n.box[data-surface='cat-6'] {\n --box-fill: var(--color-cat-6);\n}\n.box[data-surface='cat-7'] {\n --box-fill: var(--color-cat-7);\n}\n.box[data-surface='cat-8'] {\n --box-fill: var(--color-cat-8);\n}\n.box[data-surface^='cat-'] {\n --box-on: var(--color-cat-ink);\n}\n.box:is([data-surface='inverse'], [data-surface^='cat-']) {\n --color-ink: var(--box-on);\n --color-ink-muted: color-mix(in oklab, var(--box-on) 76%, var(--box-fill));\n --color-ink-subtle: color-mix(in oklab, var(--box-on) 60%, var(--box-fill));\n --color-line: color-mix(in oklab, var(--box-on) 22%, var(--box-fill));\n --color-line-strong: color-mix(in oklab, var(--box-on) 45%, var(--box-fill));\n --color-canvas: var(--box-fill);\n --color-surface: color-mix(in oklab, var(--box-on) 7%, var(--box-fill));\n --color-surface-sunken: color-mix(in oklab, var(--box-on) 12%, var(--box-fill));\n --color-surface-raised: color-mix(in oklab, var(--box-on) 4%, var(--box-fill));\n --color-focus: var(--box-on);\n --color-accent-text: var(--box-on);\n --canvas-image: none;\n\n background-color: var(--box-fill);\n color: var(--box-on);\n}\n/* A categorical fill only clears AA against its own ink: no headroom for muted steps. */\n.box[data-surface^='cat-'] {\n --color-ink-muted: var(--box-on);\n --color-ink-subtle: var(--box-on);\n --color-surface: var(--box-fill);\n --color-surface-sunken: var(--box-fill);\n --color-surface-raised: var(--box-fill);\n}\n.box:is([data-surface='inverse'], [data-surface^='cat-']) > * {\n --color-surface-inverse: var(--box-on);\n --color-ink-inverse: var(--box-fill);\n}\n\n.box[data-border] {\n border: var(--border-width) solid var(--color-line);\n}\n\n.box[data-radius='field'] {\n border-radius: var(--radius-field);\n}\n.box[data-radius='surface'] {\n border-radius: var(--radius-surface);\n}\n.box[data-radius='media'] {\n border-radius: var(--radius-media);\n}\n\n/* `hidden` wins over the display above (author CSS otherwise beats the UA [hidden] rule). */\n.box[hidden] {\n display: none;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Box.module.js","names":["box","Box_module_default"],"sources":["../../../../src/components/layout/Box/Box.module.css"],"sourcesContent":["/*\n * Responsive pattern: see layout/Stack/Stack.module.css. Axis padding (--box-px/-py)\n * falls back to the all-sides value (--box-p) per breakpoint.\n *\n * --box-fill / --box-on (read-only): the fill and ink of an `inverse`, `accent` or categorical Box.\n */\n.box {\n --_p: var(--box-p-base, 0px);\n --_px: var(--box-px-base, var(--_p));\n --_py: var(--box-py-base, var(--_p));\n\n display: block;\n min-inline-size: 0;\n padding-block: var(--_py);\n padding-inline: var(--_px);\n}\n\n@media (min-width: 40em) {\n .box {\n --_p: var(--box-p-sm, 0px);\n --_px: var(--box-px-sm, var(--_p));\n --_py: var(--box-py-sm, var(--_p));\n }\n}\n@media (min-width: 48em) {\n .box {\n --_p: var(--box-p-md, 0px);\n --_px: var(--box-px-md, var(--_p));\n --_py: var(--box-py-md, var(--_p));\n }\n}\n@media (min-width: 64em) {\n .box {\n --_p: var(--box-p-lg, 0px);\n --_px: var(--box-px-lg, var(--_p));\n --_py: var(--box-py-lg, var(--_p));\n }\n}\n@media (min-width: 80em) {\n .box {\n --_p: var(--box-p-xl, 0px);\n --_px: var(--box-px-xl, var(--_p));\n --_py: var(--box-py-xl, var(--_p));\n }\n}\n\n/* Surfaces */\n.box[data-surface='canvas'] {\n background-color: var(--color-canvas);\n background-image: var(--canvas-image);\n background-size: var(--canvas-image-size);\n color: var(--color-ink);\n}\n.box[data-surface='surface'] {\n background-color: var(--color-surface);\n color: var(--color-ink);\n}\n.box[data-surface='sunken'] {\n background-color: var(--color-surface-sunken);\n color: var(--color-ink);\n}\n.box[data-surface='raised'] {\n background-color: var(--color-surface-raised);\n color: var(--color-ink);\n}\n/* Inverse, accent and categorical fills re-point the colour roles for descendants — same approach as Section. */\n.box[data-surface='inverse'] {\n --box-fill: var(--color-surface-inverse);\n --box-on: var(--color-ink-inverse);\n}\n.box[data-surface='accent'] {\n --box-fill: var(--color-accent);\n --box-on: var(--color-accent-ink);\n}\n.box[data-surface='cat-1'] {\n --box-fill: var(--color-cat-1);\n}\n.box[data-surface='cat-2'] {\n --box-fill: var(--color-cat-2);\n}\n.box[data-surface='cat-3'] {\n --box-fill: var(--color-cat-3);\n}\n.box[data-surface='cat-4'] {\n --box-fill: var(--color-cat-4);\n}\n.box[data-surface='cat-5'] {\n --box-fill: var(--color-cat-5);\n}\n.box[data-surface='cat-6'] {\n --box-fill: var(--color-cat-6);\n}\n.box[data-surface='cat-7'] {\n --box-fill: var(--color-cat-7);\n}\n.box[data-surface='cat-8'] {\n --box-fill: var(--color-cat-8);\n}\n.box[data-surface^='cat-'] {\n --box-on: var(--color-cat-ink);\n}\n.box:is([data-surface='inverse'], [data-surface='accent'], [data-surface^='cat-']) {\n --color-ink: var(--box-on);\n --color-ink-muted: color-mix(in oklab, var(--box-on) 76%, var(--box-fill));\n --color-ink-subtle: color-mix(in oklab, var(--box-on) 60%, var(--box-fill));\n --color-line: color-mix(in oklab, var(--box-on) 22%, var(--box-fill));\n --color-line-strong: color-mix(in oklab, var(--box-on) 45%, var(--box-fill));\n --color-canvas: var(--box-fill);\n --color-surface: color-mix(in oklab, var(--box-on) 7%, var(--box-fill));\n --color-surface-sunken: color-mix(in oklab, var(--box-on) 12%, var(--box-fill));\n --color-surface-raised: color-mix(in oklab, var(--box-on) 4%, var(--box-fill));\n --color-focus: var(--box-on);\n --color-accent-text: var(--box-on);\n --canvas-image: none;\n\n background-color: var(--box-fill);\n color: var(--box-on);\n}\n/* An accent or categorical fill only clears AA against its own ink: no headroom for muted steps. */\n.box:is([data-surface='accent'], [data-surface^='cat-']) {\n --color-ink-muted: var(--box-on);\n --color-ink-subtle: var(--box-on);\n --color-surface: var(--box-fill);\n --color-surface-sunken: var(--box-fill);\n --color-surface-raised: var(--box-fill);\n}\n.box:is([data-surface='inverse'], [data-surface^='cat-']) > * {\n --color-surface-inverse: var(--box-on);\n --color-ink-inverse: var(--box-fill);\n}\n/* On an accent fill the accent itself becomes the fill's ink, so a primary action still stands out. */\n.box[data-surface='accent'] > * {\n --color-accent: var(--box-on);\n --color-accent-hover: color-mix(in oklab, var(--box-on) 82%, var(--box-fill));\n --color-accent-ink: var(--box-fill);\n --color-accent-soft: color-mix(in oklab, var(--box-on) 12%, var(--box-fill));\n}\n\n/*\n * Opt-in (`adaptTones`, so existing bands keep the page's tones): status tones follow the band,\n * like the accent text does. An accent or categorical fill only clears AA against its own ink,\n * so tone text there is that ink (the sign, glyph or label carries the status) and soft tone\n * fills are the fill itself, like the nested surfaces. An inverse band has headroom, so each\n * tone keeps its hue, mixed toward the band's ink until it reads on the fill.\n * Solid tone fills keep their own ink and need no change.\n */\n.box[data-adapt-tones]:is([data-surface='accent'], [data-surface^='cat-']) {\n --tone-positive-text: var(--box-on);\n --tone-caution-text: var(--box-on);\n --tone-critical-text: var(--box-on);\n --tone-info-text: var(--box-on);\n --tone-positive-soft: var(--box-fill);\n --tone-caution-soft: var(--box-fill);\n --tone-critical-soft: var(--box-fill);\n --tone-info-soft: var(--box-fill);\n}\n.box[data-adapt-tones][data-surface='inverse'] {\n --tone-positive-text: color-mix(in oklab, var(--tone-positive) 40%, var(--box-on));\n --tone-caution-text: color-mix(in oklab, var(--tone-caution) 40%, var(--box-on));\n --tone-critical-text: color-mix(in oklab, var(--tone-critical) 40%, var(--box-on));\n --tone-info-text: color-mix(in oklab, var(--tone-info) 40%, var(--box-on));\n --tone-positive-soft: color-mix(in oklab, var(--tone-positive) 18%, var(--box-fill));\n --tone-caution-soft: color-mix(in oklab, var(--tone-caution) 18%, var(--box-fill));\n --tone-critical-soft: color-mix(in oklab, var(--tone-critical) 18%, var(--box-fill));\n --tone-info-soft: color-mix(in oklab, var(--tone-info) 18%, var(--box-fill));\n}\n\n.box[data-border] {\n border: var(--border-width) solid var(--color-line);\n}\n\n.box[data-radius='field'] {\n border-radius: var(--radius-field);\n}\n.box[data-radius='surface'] {\n border-radius: var(--radius-surface);\n}\n.box[data-radius='media'] {\n border-radius: var(--radius-media);\n}\n\n/* `hidden` wins over the display above (author CSS otherwise beats the UA [hidden] rule). */\n.box[hidden] {\n display: none;\n}\n"],"mappings":""}
@@ -0,0 +1,36 @@
1
+ import { type HTMLAttributes } from 'react';
2
+ import { type VisibilityProps } from '../../../utils/visibility.js';
3
+ export type ScrollAreaAxis = 'x' | 'y' | 'both';
4
+ export interface ScrollAreaProps extends HTMLAttributes<HTMLDivElement>, VisibilityProps {
5
+ /**
6
+ * Names the area. With a name (this, or `aria-labelledby`) it becomes a labelled region that
7
+ * keyboard users can focus and scroll with the arrow keys.
8
+ */
9
+ label?: string;
10
+ /**
11
+ * Which way it scrolls. On `x` and `both` the content keeps its natural width, so a row of cards
12
+ * scrolls instead of squeezing. `y` and `both` scroll once a parent gives the area a height (a
13
+ * grid row, a pane). Default `x`.
14
+ */
15
+ axis?: ScrollAreaAxis;
16
+ }
17
+ /**
18
+ * A scroll container for content wider or taller than the page, such as a bracket, a timeline or
19
+ * a wide board, that keyboard users can reach and scroll.
20
+ *
21
+ * @remarks
22
+ * `ScrollArea` lets one wide thing scroll on its own instead of pushing the page sideways. Give it
23
+ * a `label` and it's a named region in the tab order, so someone without a mouse or touch screen
24
+ * can focus it and scroll with the arrow keys. The scrollbar takes the theme's line colour.
25
+ *
26
+ * A data table doesn't need one: `Table` scrolls sideways itself, and takes the same `label`.
27
+ *
28
+ * @privateRemarks
29
+ * The labelled, focusable scroll wrapper Table already has, for anything that isn't a table
30
+ * (axe's scrollable-region-focusable). Focusable only when named, so an unnamed one never adds
31
+ * an anonymous tab stop. `role` is an expression, which jsx-a11y's no-noninteractive-tabindex
32
+ * exempts (allowExpressionValues), so the tabIndex stays lint-clean.
33
+ *
34
+ * <ScrollArea label="Knockout bracket"><Bracket /></ScrollArea>
35
+ */
36
+ export declare const ScrollArea: import("react").ForwardRefExoticComponent<ScrollAreaProps & import("react").RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,25 @@
1
+ import { cx as e } from "../../../utils/cx.js";
2
+ import { visibilityClass as t } from "../../../utils/visibility.js";
3
+ import n from "./ScrollArea.module.js";
4
+ import { forwardRef as r } from "react";
5
+ import { jsx as i } from "react/jsx-runtime";
6
+ //#region src/components/layout/ScrollArea/ScrollArea.tsx
7
+ var a = r(function({ label: r, axis: a = "x", hideBelow: o, hideAbove: s, className: c, ...l }, u) {
8
+ let d = r !== void 0 || l["aria-labelledby"] !== void 0;
9
+ return /* @__PURE__ */ i("div", {
10
+ ref: u,
11
+ className: e(n.scrollArea, t({
12
+ hideBelow: o,
13
+ hideAbove: s
14
+ }), c),
15
+ "data-axis": a,
16
+ role: d ? "region" : void 0,
17
+ "aria-label": r,
18
+ tabIndex: d ? 0 : void 0,
19
+ ...l
20
+ });
21
+ });
22
+ //#endregion
23
+ export { a as ScrollArea };
24
+
25
+ //# sourceMappingURL=ScrollArea.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScrollArea.js","names":["styles","ScrollArea_module_default","ScrollArea","forwardRef","rest","named","label","cx","visibilityClass","className","axis"],"sources":["../../../../src/components/layout/ScrollArea/ScrollArea.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes } from 'react'\nimport { cx } from '#utils/cx'\nimport { visibilityClass, type VisibilityProps } from '#utils/visibility'\nimport styles from './ScrollArea.module.css'\n\nexport type ScrollAreaAxis = 'x' | 'y' | 'both'\n\nexport interface ScrollAreaProps extends HTMLAttributes<HTMLDivElement>, VisibilityProps {\n /**\n * Names the area. With a name (this, or `aria-labelledby`) it becomes a labelled region that\n * keyboard users can focus and scroll with the arrow keys.\n */\n label?: string\n /**\n * Which way it scrolls. On `x` and `both` the content keeps its natural width, so a row of cards\n * scrolls instead of squeezing. `y` and `both` scroll once a parent gives the area a height (a\n * grid row, a pane). Default `x`.\n */\n axis?: ScrollAreaAxis\n}\n\n/**\n * A scroll container for content wider or taller than the page, such as a bracket, a timeline or\n * a wide board, that keyboard users can reach and scroll.\n *\n * @remarks\n * `ScrollArea` lets one wide thing scroll on its own instead of pushing the page sideways. Give it\n * a `label` and it's a named region in the tab order, so someone without a mouse or touch screen\n * can focus it and scroll with the arrow keys. The scrollbar takes the theme's line colour.\n *\n * A data table doesn't need one: `Table` scrolls sideways itself, and takes the same `label`.\n *\n * @privateRemarks\n * The labelled, focusable scroll wrapper Table already has, for anything that isn't a table\n * (axe's scrollable-region-focusable). Focusable only when named, so an unnamed one never adds\n * an anonymous tab stop. `role` is an expression, which jsx-a11y's no-noninteractive-tabindex\n * exempts (allowExpressionValues), so the tabIndex stays lint-clean.\n *\n * <ScrollArea label=\"Knockout bracket\"><Bracket /></ScrollArea>\n */\nexport const ScrollArea = forwardRef<HTMLDivElement, ScrollAreaProps>(function ScrollArea(\n { label, axis = 'x', hideBelow, hideAbove, className, ...rest },\n ref,\n) {\n const named = label !== undefined || rest['aria-labelledby'] !== undefined\n return (\n <div\n ref={ref}\n className={cx(styles.scrollArea, visibilityClass({ hideBelow, hideAbove }), className)}\n data-axis={axis}\n role={named ? 'region' : undefined}\n aria-label={label}\n tabIndex={named ? 0 : undefined}\n {...rest}\n />\n )\n})\n"],"mappings":";;;;;;AAwCA,IAAaE,IAAaC,EAA4C,SACpE,EAAE,UAAO,UAAO,KAAK,cAAW,cAAW,cAAW,GAAGC,KACzD,GACA;CACA,IAAMC,IAAQC,MAAU,KAAA,KAAaF,EAAK,uBAAuB,KAAA;CACjE,OACE,kBAAC,OAAD;EACO;EACL,WAAWG,EAAGP,EAAO,YAAYQ,EAAgB;GAAE;GAAW;EAAU,CAAC,GAAGC,CAAS;EACrF,aAAWC;EACX,MAAML,IAAQ,WAAW,KAAA;EACzB,cAAYC;EACZ,UAAUD,IAAQ,IAAI,KAAA;EACtB,GAAID;CACL,CAAA;AAEL,CAAC"}
@@ -0,0 +1,6 @@
1
+ //#region src/components/layout/ScrollArea/ScrollArea.module.css
2
+ var e = "kiln-ScrollArea__scrollArea", t = { scrollArea: e };
3
+ //#endregion
4
+ export { t as default, e as scrollArea };
5
+
6
+ //# sourceMappingURL=ScrollArea.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScrollArea.module.js","names":["scrollArea","ScrollArea_module_default"],"sources":["../../../../src/components/layout/ScrollArea/ScrollArea.module.css"],"sourcesContent":["/*\n * Component tokens (themes may set any of these on [data-theme]):\n * --scroll-area-thumb default var(--color-line-strong) — the scrollbar's thumb\n *\n * Scrolling stays inside the area on its own axis (overscroll-behavior), so reaching the end\n * of a wide bracket doesn't swipe the browser back a page.\n */\n.scrollArea {\n display: block;\n min-inline-size: 0;\n max-inline-size: 100%;\n overflow-x: auto;\n overflow-y: hidden;\n overscroll-behavior-x: contain;\n scrollbar-width: thin;\n scrollbar-color: var(--scroll-area-thumb, var(--color-line-strong)) transparent;\n}\n.scrollArea[data-axis='y'] {\n overflow-x: hidden;\n overflow-y: auto;\n overscroll-behavior-x: auto;\n overscroll-behavior-y: contain;\n}\n.scrollArea[data-axis='both'] {\n overflow: auto;\n overscroll-behavior: contain;\n}\n/*\n * Sideways, the content keeps at least its natural width instead of squeezing to fit, so a row\n * of cards scrolls rather than shrinking; content narrower than the area still fills it.\n */\n.scrollArea:not([data-axis='y']) > * {\n min-inline-size: max-content;\n}\n.scrollArea:focus-visible {\n outline: 2px solid var(--color-focus);\n outline-offset: 2px;\n}\n\n/* `hidden` wins over the display above (author CSS otherwise beats the UA [hidden] rule). */\n.scrollArea[hidden] {\n display: none;\n}\n"],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export { ScrollArea } from './ScrollArea.js';
2
+ export type { ScrollAreaProps, ScrollAreaAxis } from './ScrollArea.js';
@@ -17,6 +17,14 @@ export interface SectionProps extends HTMLAttributes<HTMLElement>, VisibilityPro
17
17
  * stay legible.
18
18
  */
19
19
  surface?: SectionSurface;
20
+ /**
21
+ * On an `inverse`, `accent` or categorical band, re-point the status tones too, so tone text
22
+ * and soft tone fills (a `Stat` delta, a toned `Numeral` or `Text`, a soft `Badge`) stay AA on
23
+ * the band. On `accent` and categorical bands tone text becomes the band's ink, so the sign,
24
+ * glyph or label carries the status; on `inverse` each tone keeps its hue. Off by default, so
25
+ * tones keep the page's colours. No effect on other surfaces.
26
+ */
27
+ adaptTones?: boolean;
20
28
  /** A hairline across the full bleed at the top, bottom or both edges. */
21
29
  divider?: SectionDivider;
22
30
  as?: SectionElement;
@@ -34,8 +42,9 @@ export interface SectionProps extends HTMLAttributes<HTMLElement>, VisibilityPro
34
42
  *
35
43
  * `surface` is `canvas`, `surface`, `sunken`, `inverse`, `accent`, or a categorical `cat-1` to
36
44
  * `cat-8` (a band in one person's or team's colour, matching their `Tag`). On `inverse`, `accent`
37
- * and the categorical bands, the colour roles flip for everything inside, so text, links, focus rings and buttons stay
38
- * legible with no extra props. `divider` adds a rule at the `top`, `bottom` or `both`.
45
+ * and the categorical bands, the colour roles flip for everything inside, so text, links, focus
46
+ * rings and buttons stay legible with no extra props. Add `adaptTones` to flip the status tones
47
+ * too. `divider` adds a rule at the `top`, `bottom` or `both`.
39
48
  *
40
49
  * @privateRemarks
41
50
  * A full-bleed band of vertical rhythm. Put a `Container` inside for width.
@@ -6,17 +6,18 @@ import a from "./Section.module.js";
6
6
  import { forwardRef as o } from "react";
7
7
  import { jsx as s } from "react/jsx-runtime";
8
8
  //#region src/components/layout/Section/Section.tsx
9
- var c = o(function({ space: o, surface: c, divider: l, as: u = "section", hideBelow: d, hideAbove: f, className: p, style: m, ...h }, g) {
10
- return /* @__PURE__ */ s(u, {
11
- ref: g,
9
+ var c = o(function({ space: o, surface: c, adaptTones: l = !1, divider: u, as: d = "section", hideBelow: f, hideAbove: p, className: m, style: h, ...g }, _) {
10
+ return /* @__PURE__ */ s(d, {
11
+ ref: _,
12
12
  className: e(a.section, i({
13
- hideBelow: d,
14
- hideAbove: f
15
- }), p),
13
+ hideBelow: f,
14
+ hideAbove: p
15
+ }), m),
16
16
  "data-surface": c,
17
- "data-divider": l,
18
- style: t(n("section-space", o, r), m),
19
- ...h
17
+ "data-adapt-tones": l || void 0,
18
+ "data-divider": u,
19
+ style: t(n("section-space", o, r), h),
20
+ ...g
20
21
  });
21
22
  });
22
23
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"Section.js","names":["styles","Section_module_default","Section","forwardRef","spaceProp","Comp","rest","cx","visibilityClass","className","surface","divider","mergeStyles","responsiveVars","space","style"],"sources":["../../../../src/components/layout/Section/Section.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes } from 'react'\nimport { cx } from '#utils/cx'\nimport { mergeStyles, responsiveVars, type Responsive } from '#utils/responsive'\nimport { space, type Space, type CategoryColor } from '#utils/tokens'\nimport styles from './Section.module.css'\nimport { visibilityClass, type VisibilityProps } from '#utils/visibility'\n\nexport type SectionElement = 'section' | 'div' | 'article' | 'aside' | 'header' | 'footer'\nexport type SectionSurface =\n 'canvas' | 'surface' | 'sunken' | 'inverse' | 'accent' | `cat-${CategoryColor}`\nexport type SectionDivider = 'top' | 'bottom' | 'both'\n\nexport interface SectionProps extends HTMLAttributes<HTMLElement>, VisibilityProps {\n /**\n * Block padding (top and bottom), as a step on the space scale. Responsive.\n * Vary it: adjacent sections should not share the same step. Default `8`.\n */\n space?: Responsive<Space>\n /**\n * Full-bleed band colour. Omit to stay transparent on the canvas. `inverse`, `accent` and\n * the categorical `cat-1` to `cat-8` re-point the ink, line and focus colours so children\n * stay legible.\n */\n surface?: SectionSurface\n /** A hairline across the full bleed at the top, bottom or both edges. */\n divider?: SectionDivider\n as?: SectionElement\n}\n\n/**\n * A full-bleed band of vertical space, with an optional surface and rules. Put a Container inside\n * it for width.\n *\n * @remarks\n * `Section` is how a page gets its rhythm: each band pads itself top and bottom with a step from\n * the space scale, and can paint a surface across the full width. Width is the `Container`'s job,\n * so a section is almost always `Section` then `Container`.\n *\n * ## Surfaces and bands\n *\n * `surface` is `canvas`, `surface`, `sunken`, `inverse`, `accent`, or a categorical `cat-1` to\n * `cat-8` (a band in one person's or team's colour, matching their `Tag`). On `inverse`, `accent`\n * and the categorical bands, the colour roles flip for everything inside, so text, links, focus rings and buttons stay\n * legible with no extra props. `divider` adds a rule at the `top`, `bottom` or `both`.\n *\n * @privateRemarks\n * A full-bleed band of vertical rhythm. Put a `Container` inside for width.\n *\n * <Section space={{ base: 7, md: 9 }} surface=\"sunken\" divider=\"both\">\n * <Container>…</Container>\n * </Section>\n */\nexport const Section = forwardRef<HTMLElement, SectionProps>(function Section(\n {\n space: spaceProp,\n surface,\n divider,\n as: Comp = 'section',\n hideBelow,\n hideAbove,\n className,\n style,\n ...rest\n },\n ref,\n) {\n return (\n <Comp\n // @ts-expect-error — polymorphic ref across a union of intrinsic elements is safe here\n ref={ref}\n className={cx(styles.section, visibilityClass({ hideBelow, hideAbove }), className)}\n data-surface={surface}\n data-divider={divider}\n style={mergeStyles(responsiveVars('section-space', spaceProp, space), style)}\n {...rest}\n />\n )\n})\n"],"mappings":";;;;;;;;AAoDA,IAAaE,IAAUC,EAAsC,SAC3D,EACE,OAAOC,GACP,YACA,YACA,IAAIC,IAAO,WACX,cACA,cACA,cACA,UACA,GAAGC,KAEL,GACA;CACA,OACE,kBAACD,GAAD;EAEO;EACL,WAAWE,EAAGP,EAAO,SAASQ,EAAgB;GAAE;GAAW;EAAU,CAAC,GAAGC,CAAS;EAClF,gBAAcC;EACd,gBAAcC;EACd,OAAOC,EAAYC,EAAe,iBAAiBT,GAAWU,CAAK,GAAGC,CAAK;EAC3E,GAAIT;CACL,CAAA;AAEL,CAAC"}
1
+ {"version":3,"file":"Section.js","names":["styles","Section_module_default","Section","forwardRef","spaceProp","Comp","rest","cx","visibilityClass","className","surface","adaptTones","divider","mergeStyles","responsiveVars","space","style"],"sources":["../../../../src/components/layout/Section/Section.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes } from 'react'\nimport { cx } from '#utils/cx'\nimport { mergeStyles, responsiveVars, type Responsive } from '#utils/responsive'\nimport { space, type Space, type CategoryColor } from '#utils/tokens'\nimport styles from './Section.module.css'\nimport { visibilityClass, type VisibilityProps } from '#utils/visibility'\n\nexport type SectionElement = 'section' | 'div' | 'article' | 'aside' | 'header' | 'footer'\nexport type SectionSurface =\n 'canvas' | 'surface' | 'sunken' | 'inverse' | 'accent' | `cat-${CategoryColor}`\nexport type SectionDivider = 'top' | 'bottom' | 'both'\n\nexport interface SectionProps extends HTMLAttributes<HTMLElement>, VisibilityProps {\n /**\n * Block padding (top and bottom), as a step on the space scale. Responsive.\n * Vary it: adjacent sections should not share the same step. Default `8`.\n */\n space?: Responsive<Space>\n /**\n * Full-bleed band colour. Omit to stay transparent on the canvas. `inverse`, `accent` and\n * the categorical `cat-1` to `cat-8` re-point the ink, line and focus colours so children\n * stay legible.\n */\n surface?: SectionSurface\n /**\n * On an `inverse`, `accent` or categorical band, re-point the status tones too, so tone text\n * and soft tone fills (a `Stat` delta, a toned `Numeral` or `Text`, a soft `Badge`) stay AA on\n * the band. On `accent` and categorical bands tone text becomes the band's ink, so the sign,\n * glyph or label carries the status; on `inverse` each tone keeps its hue. Off by default, so\n * tones keep the page's colours. No effect on other surfaces.\n */\n adaptTones?: boolean\n /** A hairline across the full bleed at the top, bottom or both edges. */\n divider?: SectionDivider\n as?: SectionElement\n}\n\n/**\n * A full-bleed band of vertical space, with an optional surface and rules. Put a Container inside\n * it for width.\n *\n * @remarks\n * `Section` is how a page gets its rhythm: each band pads itself top and bottom with a step from\n * the space scale, and can paint a surface across the full width. Width is the `Container`'s job,\n * so a section is almost always `Section` then `Container`.\n *\n * ## Surfaces and bands\n *\n * `surface` is `canvas`, `surface`, `sunken`, `inverse`, `accent`, or a categorical `cat-1` to\n * `cat-8` (a band in one person's or team's colour, matching their `Tag`). On `inverse`, `accent`\n * and the categorical bands, the colour roles flip for everything inside, so text, links, focus\n * rings and buttons stay legible with no extra props. Add `adaptTones` to flip the status tones\n * too. `divider` adds a rule at the `top`, `bottom` or `both`.\n *\n * @privateRemarks\n * A full-bleed band of vertical rhythm. Put a `Container` inside for width.\n *\n * <Section space={{ base: 7, md: 9 }} surface=\"sunken\" divider=\"both\">\n * <Container>…</Container>\n * </Section>\n */\nexport const Section = forwardRef<HTMLElement, SectionProps>(function Section(\n {\n space: spaceProp,\n surface,\n adaptTones = false,\n divider,\n as: Comp = 'section',\n hideBelow,\n hideAbove,\n className,\n style,\n ...rest\n },\n ref,\n) {\n return (\n <Comp\n // @ts-expect-error — polymorphic ref across a union of intrinsic elements is safe here\n ref={ref}\n className={cx(styles.section, visibilityClass({ hideBelow, hideAbove }), className)}\n data-surface={surface}\n data-adapt-tones={adaptTones || undefined}\n data-divider={divider}\n style={mergeStyles(responsiveVars('section-space', spaceProp, space), style)}\n {...rest}\n />\n )\n})\n"],"mappings":";;;;;;;;AA6DA,IAAaE,IAAUC,EAAsC,SAC3D,EACE,OAAOC,GACP,YACA,gBAAa,IACb,YACA,IAAIC,IAAO,WACX,cACA,cACA,cACA,UACA,GAAGC,KAEL,GACA;CACA,OACE,kBAACD,GAAD;EAEO;EACL,WAAWE,EAAGP,EAAO,SAASQ,EAAgB;GAAE;GAAW;EAAU,CAAC,GAAGC,CAAS;EAClF,gBAAcC;EACd,oBAAkBC,KAAc,KAAA;EAChC,gBAAcC;EACd,OAAOC,EAAYC,EAAe,iBAAiBV,GAAWW,CAAK,GAAGC,CAAK;EAC3E,GAAIV;CACL,CAAA;AAEL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Section.module.js","names":["section","Section_module_default"],"sources":["../../../../src/components/layout/Section/Section.module.css"],"sourcesContent":["/*\n * Responsive pattern: see layout/Stack/Stack.module.css.\n *\n * Component tokens:\n * --section-fill / --section-on (read-only) the band's fill and ink on inverse/accent\n * --section-space-default block padding when `space` is unset (default var(--space-8))\n * --section-divider-color hairline colour for `divider` (default var(--color-line))\n */\n.section {\n --_space: var(--section-space-base, var(--section-space-default, var(--space-8)));\n --_rule: var(--border-width) solid var(--section-divider-color, var(--color-line));\n\n display: block;\n position: relative;\n min-inline-size: 0;\n padding-block: var(--_space);\n}\n\n@media (min-width: 40em) {\n .section {\n --_space: var(--section-space-sm, var(--section-space-default, var(--space-8)));\n }\n}\n@media (min-width: 48em) {\n .section {\n --_space: var(--section-space-md, var(--section-space-default, var(--space-8)));\n }\n}\n@media (min-width: 64em) {\n .section {\n --_space: var(--section-space-lg, var(--section-space-default, var(--space-8)));\n }\n}\n@media (min-width: 80em) {\n .section {\n --_space: var(--section-space-xl, var(--section-space-default, var(--space-8)));\n }\n}\n\n.section[data-divider='top'],\n.section[data-divider='both'] {\n border-block-start: var(--_rule);\n}\n.section[data-divider='bottom'],\n.section[data-divider='both'] {\n border-block-end: var(--_rule);\n}\n\n/* Surfaces */\n.section[data-surface='canvas'] {\n background-color: var(--color-canvas);\n background-image: var(--canvas-image);\n background-size: var(--canvas-image-size);\n color: var(--color-ink);\n}\n.section[data-surface='surface'] {\n background-color: var(--color-surface);\n color: var(--color-ink);\n}\n.section[data-surface='sunken'] {\n background-color: var(--color-surface-sunken);\n color: var(--color-ink);\n}\n\n/*\n * Inverse and accent bands re-point the colour roles for every descendant, so text,\n * hairlines, focus rings and nested controls (an outline or solid Button) stay legible\n * without per-child props. Mixes are taken against the band's own fill.\n *\n * Swapping a pair (e.g. ink <-> ink-inverse) can't happen on one element — it would be\n * a var() cycle — so the band publishes its fill/ink as --section-fill/--section-on and\n * the swapped roles are set on its children.\n */\n.section[data-surface='inverse'] {\n --section-fill: var(--color-surface-inverse);\n --section-on: var(--color-ink-inverse);\n}\n.section[data-surface='accent'] {\n --section-fill: var(--color-accent);\n --section-on: var(--color-accent-ink);\n}\n.section[data-surface='cat-1'] {\n --section-fill: var(--color-cat-1);\n}\n.section[data-surface='cat-2'] {\n --section-fill: var(--color-cat-2);\n}\n.section[data-surface='cat-3'] {\n --section-fill: var(--color-cat-3);\n}\n.section[data-surface='cat-4'] {\n --section-fill: var(--color-cat-4);\n}\n.section[data-surface='cat-5'] {\n --section-fill: var(--color-cat-5);\n}\n.section[data-surface='cat-6'] {\n --section-fill: var(--color-cat-6);\n}\n.section[data-surface='cat-7'] {\n --section-fill: var(--color-cat-7);\n}\n.section[data-surface='cat-8'] {\n --section-fill: var(--color-cat-8);\n}\n.section[data-surface^='cat-'] {\n --section-on: var(--color-cat-ink);\n}\n.section:is([data-surface='inverse'], [data-surface='accent'], [data-surface^='cat-']) {\n --color-ink: var(--section-on);\n --color-ink-muted: color-mix(in oklab, var(--section-on) 76%, var(--section-fill));\n --color-ink-subtle: color-mix(in oklab, var(--section-on) 60%, var(--section-fill));\n --color-line: color-mix(in oklab, var(--section-on) 22%, var(--section-fill));\n --color-line-strong: color-mix(in oklab, var(--section-on) 45%, var(--section-fill));\n --color-canvas: var(--section-fill);\n --color-surface: color-mix(in oklab, var(--section-on) 7%, var(--section-fill));\n --color-surface-sunken: color-mix(in oklab, var(--section-on) 12%, var(--section-fill));\n --color-surface-raised: color-mix(in oklab, var(--section-on) 4%, var(--section-fill));\n --color-focus: var(--section-on);\n --color-accent-text: var(--section-on);\n --canvas-image: none;\n\n background-color: var(--section-fill);\n color: var(--section-on);\n}\n/* An accent or categorical fill only clears AA against its own ink, so there is no headroom\n for muted/subtle steps there: secondary text uses the full band ink, and nested\n surfaces stay the band fill (edges come from the line tokens) so text on them keeps AA. */\n.section:is([data-surface='accent'], [data-surface^='cat-']) {\n --color-ink-muted: var(--section-on);\n --color-ink-subtle: var(--section-on);\n --color-surface: var(--section-fill);\n --color-surface-sunken: var(--section-fill);\n --color-surface-raised: var(--section-fill);\n}\n.section[data-surface='inverse'] > * {\n --color-surface-inverse: var(--section-on);\n --color-ink-inverse: var(--section-fill);\n}\n/* On an accent band the accent itself becomes the band's ink, so a primary action still stands out. */\n.section[data-surface='accent'] > * {\n --color-accent: var(--section-on);\n --color-accent-hover: color-mix(in oklab, var(--section-on) 82%, var(--section-fill));\n --color-accent-ink: var(--section-fill);\n --color-accent-soft: color-mix(in oklab, var(--section-on) 12%, var(--section-fill));\n}\n\n/* `hidden` wins over the display above (author CSS otherwise beats the UA [hidden] rule). */\n.section[hidden] {\n display: none;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"Section.module.js","names":["section","Section_module_default"],"sources":["../../../../src/components/layout/Section/Section.module.css"],"sourcesContent":["/*\n * Responsive pattern: see layout/Stack/Stack.module.css.\n *\n * Component tokens:\n * --section-fill / --section-on (read-only) the band's fill and ink on inverse/accent\n * --section-space-default block padding when `space` is unset (default var(--space-8))\n * --section-divider-color hairline colour for `divider` (default var(--color-line))\n */\n.section {\n --_space: var(--section-space-base, var(--section-space-default, var(--space-8)));\n --_rule: var(--border-width) solid var(--section-divider-color, var(--color-line));\n\n display: block;\n position: relative;\n min-inline-size: 0;\n padding-block: var(--_space);\n}\n\n@media (min-width: 40em) {\n .section {\n --_space: var(--section-space-sm, var(--section-space-default, var(--space-8)));\n }\n}\n@media (min-width: 48em) {\n .section {\n --_space: var(--section-space-md, var(--section-space-default, var(--space-8)));\n }\n}\n@media (min-width: 64em) {\n .section {\n --_space: var(--section-space-lg, var(--section-space-default, var(--space-8)));\n }\n}\n@media (min-width: 80em) {\n .section {\n --_space: var(--section-space-xl, var(--section-space-default, var(--space-8)));\n }\n}\n\n.section[data-divider='top'],\n.section[data-divider='both'] {\n border-block-start: var(--_rule);\n}\n.section[data-divider='bottom'],\n.section[data-divider='both'] {\n border-block-end: var(--_rule);\n}\n\n/* Surfaces */\n.section[data-surface='canvas'] {\n background-color: var(--color-canvas);\n background-image: var(--canvas-image);\n background-size: var(--canvas-image-size);\n color: var(--color-ink);\n}\n.section[data-surface='surface'] {\n background-color: var(--color-surface);\n color: var(--color-ink);\n}\n.section[data-surface='sunken'] {\n background-color: var(--color-surface-sunken);\n color: var(--color-ink);\n}\n\n/*\n * Inverse and accent bands re-point the colour roles for every descendant, so text,\n * hairlines, focus rings and nested controls (an outline or solid Button) stay legible\n * without per-child props. Mixes are taken against the band's own fill.\n *\n * Swapping a pair (e.g. ink <-> ink-inverse) can't happen on one element — it would be\n * a var() cycle — so the band publishes its fill/ink as --section-fill/--section-on and\n * the swapped roles are set on its children.\n */\n.section[data-surface='inverse'] {\n --section-fill: var(--color-surface-inverse);\n --section-on: var(--color-ink-inverse);\n}\n.section[data-surface='accent'] {\n --section-fill: var(--color-accent);\n --section-on: var(--color-accent-ink);\n}\n.section[data-surface='cat-1'] {\n --section-fill: var(--color-cat-1);\n}\n.section[data-surface='cat-2'] {\n --section-fill: var(--color-cat-2);\n}\n.section[data-surface='cat-3'] {\n --section-fill: var(--color-cat-3);\n}\n.section[data-surface='cat-4'] {\n --section-fill: var(--color-cat-4);\n}\n.section[data-surface='cat-5'] {\n --section-fill: var(--color-cat-5);\n}\n.section[data-surface='cat-6'] {\n --section-fill: var(--color-cat-6);\n}\n.section[data-surface='cat-7'] {\n --section-fill: var(--color-cat-7);\n}\n.section[data-surface='cat-8'] {\n --section-fill: var(--color-cat-8);\n}\n.section[data-surface^='cat-'] {\n --section-on: var(--color-cat-ink);\n}\n.section:is([data-surface='inverse'], [data-surface='accent'], [data-surface^='cat-']) {\n --color-ink: var(--section-on);\n --color-ink-muted: color-mix(in oklab, var(--section-on) 76%, var(--section-fill));\n --color-ink-subtle: color-mix(in oklab, var(--section-on) 60%, var(--section-fill));\n --color-line: color-mix(in oklab, var(--section-on) 22%, var(--section-fill));\n --color-line-strong: color-mix(in oklab, var(--section-on) 45%, var(--section-fill));\n --color-canvas: var(--section-fill);\n --color-surface: color-mix(in oklab, var(--section-on) 7%, var(--section-fill));\n --color-surface-sunken: color-mix(in oklab, var(--section-on) 12%, var(--section-fill));\n --color-surface-raised: color-mix(in oklab, var(--section-on) 4%, var(--section-fill));\n --color-focus: var(--section-on);\n --color-accent-text: var(--section-on);\n --canvas-image: none;\n\n background-color: var(--section-fill);\n color: var(--section-on);\n}\n/* An accent or categorical fill only clears AA against its own ink, so there is no headroom\n for muted/subtle steps there: secondary text uses the full band ink, and nested\n surfaces stay the band fill (edges come from the line tokens) so text on them keeps AA. */\n.section:is([data-surface='accent'], [data-surface^='cat-']) {\n --color-ink-muted: var(--section-on);\n --color-ink-subtle: var(--section-on);\n --color-surface: var(--section-fill);\n --color-surface-sunken: var(--section-fill);\n --color-surface-raised: var(--section-fill);\n}\n.section[data-surface='inverse'] > * {\n --color-surface-inverse: var(--section-on);\n --color-ink-inverse: var(--section-fill);\n}\n/* On an accent band the accent itself becomes the band's ink, so a primary action still stands out. */\n.section[data-surface='accent'] > * {\n --color-accent: var(--section-on);\n --color-accent-hover: color-mix(in oklab, var(--section-on) 82%, var(--section-fill));\n --color-accent-ink: var(--section-fill);\n --color-accent-soft: color-mix(in oklab, var(--section-on) 12%, var(--section-fill));\n}\n\n/*\n * Opt-in (`adaptTones`, so existing bands keep the page's tones): status tones follow the band,\n * like the accent text does. An accent or categorical fill only clears AA against its own ink,\n * so tone text there is that ink (the sign, glyph or label carries the status) and soft tone\n * fills are the fill itself, like the nested surfaces. An inverse band has headroom, so each\n * tone keeps its hue, mixed toward the band's ink until it reads on the fill.\n * Solid tone fills keep their own ink and need no change.\n */\n.section[data-adapt-tones]:is([data-surface='accent'], [data-surface^='cat-']) {\n --tone-positive-text: var(--section-on);\n --tone-caution-text: var(--section-on);\n --tone-critical-text: var(--section-on);\n --tone-info-text: var(--section-on);\n --tone-positive-soft: var(--section-fill);\n --tone-caution-soft: var(--section-fill);\n --tone-critical-soft: var(--section-fill);\n --tone-info-soft: var(--section-fill);\n}\n.section[data-adapt-tones][data-surface='inverse'] {\n --tone-positive-text: color-mix(in oklab, var(--tone-positive) 40%, var(--section-on));\n --tone-caution-text: color-mix(in oklab, var(--tone-caution) 40%, var(--section-on));\n --tone-critical-text: color-mix(in oklab, var(--tone-critical) 40%, var(--section-on));\n --tone-info-text: color-mix(in oklab, var(--tone-info) 40%, var(--section-on));\n --tone-positive-soft: color-mix(in oklab, var(--tone-positive) 18%, var(--section-fill));\n --tone-caution-soft: color-mix(in oklab, var(--tone-caution) 18%, var(--section-fill));\n --tone-critical-soft: color-mix(in oklab, var(--tone-critical) 18%, var(--section-fill));\n --tone-info-soft: color-mix(in oklab, var(--tone-info) 18%, var(--section-fill));\n}\n\n/* `hidden` wins over the display above (author CSS otherwise beats the UA [hidden] rule). */\n.section[hidden] {\n display: none;\n}\n"],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import type { CodeToken } from '../components/display/CodeBlock/index.js';
2
+ /** The languages `highlight` understands, with their usual aliases. */
3
+ export type HighlightLanguage = 'js' | 'javascript' | 'jsx' | 'ts' | 'typescript' | 'tsx';
4
+ /**
5
+ * Tokens for `CodeBlock`'s `tokens` prop: one array per line of `code`, each token tagged with
6
+ * what it is (keyword, string, comment…) so the theme colours it. Resolves to `undefined` for a
7
+ * language it doesn't know, which `CodeBlock` shows as plain code.
8
+ *
9
+ * @remarks
10
+ * Install `shiki` alongside kiln-ui to use it. Call it wherever your code is ready: in a server
11
+ * component or at build time, so the browser downloads no highlighter, or in the browser, where
12
+ * Shiki and the grammar load on the first call.
13
+ *
14
+ * @example
15
+ * const tokens = await highlight(source, 'tsx')
16
+ * return <CodeBlock code={source} language="TSX" tokens={tokens} />
17
+ */
18
+ export declare function highlight(code: string, language: string): Promise<CodeToken[][] | undefined>;