@ratio-ui/core 0.1.0 → 0.2.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 (141) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -1
  3. package/dist/catalogue.json +1719 -43
  4. package/dist/components/app-shell/AppShell.d.ts +22 -0
  5. package/dist/components/app-shell/AppShell.js +39 -0
  6. package/dist/components/app-shell/context.js +5 -0
  7. package/dist/components/app-shell/index.d.ts +2 -0
  8. package/dist/components/app-shell/index.js +1 -0
  9. package/dist/components/avatar/Avatar.d.ts +22 -0
  10. package/dist/components/avatar/Avatar.js +38 -0
  11. package/dist/components/avatar/index.d.ts +2 -0
  12. package/dist/components/avatar/index.js +1 -0
  13. package/dist/components/button/Button.d.ts +37 -0
  14. package/dist/components/button/Button.js +41 -0
  15. package/dist/components/button/index.d.ts +2 -0
  16. package/dist/components/button/index.js +1 -0
  17. package/dist/components/card/Card.d.ts +33 -0
  18. package/dist/components/card/Card.js +53 -0
  19. package/dist/components/card/index.d.ts +2 -0
  20. package/dist/components/card/index.js +1 -0
  21. package/dist/components/checkbox/Checkbox.d.ts +10 -0
  22. package/dist/components/checkbox/Checkbox.js +28 -0
  23. package/dist/components/checkbox/index.d.ts +2 -0
  24. package/dist/components/checkbox/index.js +1 -0
  25. package/dist/components/data-table/DataTable.d.ts +65 -0
  26. package/dist/components/data-table/DataTable.js +141 -0
  27. package/dist/components/data-table/index.d.ts +2 -0
  28. package/dist/components/data-table/index.js +1 -0
  29. package/dist/components/definition/Definition.d.ts +14 -0
  30. package/dist/components/definition/Definition.js +29 -0
  31. package/dist/components/definition/index.d.ts +2 -0
  32. package/dist/components/definition/index.js +1 -0
  33. package/dist/components/dialog/Dialog.d.ts +44 -0
  34. package/dist/components/dialog/Dialog.js +79 -0
  35. package/dist/components/dialog/index.d.ts +2 -0
  36. package/dist/components/dialog/index.js +1 -0
  37. package/dist/components/dropdown-menu/DropdownMenu.d.ts +73 -0
  38. package/dist/components/dropdown-menu/DropdownMenu.js +116 -0
  39. package/dist/components/dropdown-menu/index.d.ts +2 -0
  40. package/dist/components/dropdown-menu/index.js +1 -0
  41. package/dist/components/empty-state/EmptyState.d.ts +15 -0
  42. package/dist/components/empty-state/EmptyState.js +30 -0
  43. package/dist/components/empty-state/index.d.ts +2 -0
  44. package/dist/components/empty-state/index.js +1 -0
  45. package/dist/components/filter-tabs/FilterTabs.d.ts +28 -0
  46. package/dist/components/filter-tabs/FilterTabs.js +37 -0
  47. package/dist/components/filter-tabs/index.d.ts +2 -0
  48. package/dist/components/filter-tabs/index.js +1 -0
  49. package/dist/components/global-search/GlobalSearch.d.ts +51 -0
  50. package/dist/components/global-search/GlobalSearch.js +144 -0
  51. package/dist/components/global-search/index.d.ts +2 -0
  52. package/dist/components/global-search/index.js +1 -0
  53. package/dist/components/icon/registry.d.ts +3 -2
  54. package/dist/components/icon/registry.js +53 -1
  55. package/dist/components/input/Input.d.ts +19 -0
  56. package/dist/components/input/Input.js +26 -0
  57. package/dist/components/input/index.d.ts +2 -0
  58. package/dist/components/input/index.js +1 -0
  59. package/dist/components/input-group/InputGroup.d.ts +42 -0
  60. package/dist/components/input-group/InputGroup.js +83 -0
  61. package/dist/components/input-group/index.d.ts +2 -0
  62. package/dist/components/input-group/index.js +1 -0
  63. package/dist/components/kbd/Kbd.d.ts +17 -0
  64. package/dist/components/kbd/Kbd.js +21 -0
  65. package/dist/components/kbd/index.d.ts +2 -0
  66. package/dist/components/kbd/index.js +1 -0
  67. package/dist/components/link-provider/LinkProvider.d.ts +29 -0
  68. package/dist/components/link-provider/LinkProvider.js +15 -0
  69. package/dist/components/link-provider/RatioLink.js +18 -0
  70. package/dist/components/link-provider/context.js +4 -0
  71. package/dist/components/link-provider/index.d.ts +2 -0
  72. package/dist/components/link-provider/index.js +1 -0
  73. package/dist/components/metric-strip/MetricStrip.d.ts +23 -0
  74. package/dist/components/metric-strip/MetricStrip.js +39 -0
  75. package/dist/components/metric-strip/index.d.ts +2 -0
  76. package/dist/components/metric-strip/index.js +1 -0
  77. package/dist/components/page-header/PageHeader.d.ts +37 -0
  78. package/dist/components/page-header/PageHeader.js +62 -0
  79. package/dist/components/page-header/index.d.ts +2 -0
  80. package/dist/components/page-header/index.js +1 -0
  81. package/dist/components/pagination/Pagination.d.ts +18 -0
  82. package/dist/components/pagination/Pagination.js +59 -0
  83. package/dist/components/pagination/index.d.ts +2 -0
  84. package/dist/components/pagination/index.js +1 -0
  85. package/dist/components/popover/Popover.d.ts +27 -0
  86. package/dist/components/popover/Popover.js +47 -0
  87. package/dist/components/popover/index.d.ts +2 -0
  88. package/dist/components/popover/index.js +1 -0
  89. package/dist/components/search-field/SearchField.d.ts +23 -0
  90. package/dist/components/search-field/SearchField.js +66 -0
  91. package/dist/components/search-field/index.d.ts +2 -0
  92. package/dist/components/search-field/index.js +1 -0
  93. package/dist/components/side-nav/SideNav.d.ts +64 -0
  94. package/dist/components/side-nav/SideNav.js +194 -0
  95. package/dist/components/side-nav/index.d.ts +2 -0
  96. package/dist/components/side-nav/index.js +1 -0
  97. package/dist/components/skeleton/Skeleton.d.ts +13 -0
  98. package/dist/components/skeleton/Skeleton.js +21 -0
  99. package/dist/components/skeleton/index.d.ts +2 -0
  100. package/dist/components/skeleton/index.js +1 -0
  101. package/dist/components/spinner/Spinner.d.ts +11 -0
  102. package/dist/components/spinner/Spinner.js +16 -0
  103. package/dist/components/spinner/index.d.ts +2 -0
  104. package/dist/components/spinner/index.js +1 -0
  105. package/dist/components/status-pill/StatusPill.d.ts +14 -0
  106. package/dist/components/status-pill/StatusPill.js +19 -0
  107. package/dist/components/status-pill/index.d.ts +2 -0
  108. package/dist/components/status-pill/index.js +1 -0
  109. package/dist/components/table/Table.d.ts +46 -0
  110. package/dist/components/table/Table.js +87 -0
  111. package/dist/components/table/index.d.ts +2 -0
  112. package/dist/components/table/index.js +1 -0
  113. package/dist/components/table-loader/TableLoader.d.ts +31 -0
  114. package/dist/components/table-loader/TableLoader.js +35 -0
  115. package/dist/components/table-loader/index.d.ts +2 -0
  116. package/dist/components/table-loader/index.js +1 -0
  117. package/dist/components/tabs/Tabs.d.ts +23 -0
  118. package/dist/components/tabs/Tabs.js +41 -0
  119. package/dist/components/tabs/index.d.ts +2 -0
  120. package/dist/components/tabs/index.js +1 -0
  121. package/dist/components/toaster/Toaster.d.ts +32 -0
  122. package/dist/components/toaster/Toaster.js +89 -0
  123. package/dist/components/toaster/index.d.ts +2 -0
  124. package/dist/components/toaster/index.js +1 -0
  125. package/dist/components/tooltip/Tooltip.d.ts +18 -0
  126. package/dist/components/tooltip/Tooltip.js +35 -0
  127. package/dist/components/tooltip/index.d.ts +2 -0
  128. package/dist/components/tooltip/index.js +1 -0
  129. package/dist/components/top-bar/StoreSwitcher.d.ts +26 -0
  130. package/dist/components/top-bar/StoreSwitcher.js +48 -0
  131. package/dist/components/top-bar/TopBar.d.ts +24 -0
  132. package/dist/components/top-bar/TopBar.js +53 -0
  133. package/dist/components/top-bar/index.d.ts +3 -0
  134. package/dist/components/top-bar/index.js +3 -0
  135. package/dist/index.d.ts +65 -1
  136. package/dist/index.js +35 -2
  137. package/dist/lib/cn.js +32 -27
  138. package/dist/lib/format.d.ts +31 -0
  139. package/dist/lib/format.js +65 -0
  140. package/dist/styles.css +1 -1
  141. package/package.json +129 -4
@@ -0,0 +1,21 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ // src/components/skeleton/Skeleton.tsx
4
+ const SHAPE_CLASSES = {
5
+ line: "rt:h-4 rt:w-full rt:rounded-sm",
6
+ block: "rt:h-24 rt:w-full rt:rounded-sm",
7
+ circle: "rt:size-8 rt:rounded-3xl"
8
+ };
9
+ /**
10
+ * A static placeholder for content that is still loading on a first load. It is hidden from assistive technology: the
11
+ * container that holds it says it is busy. Its fill and animation come from the loading tokens, so it does not move.
12
+ */
13
+ function Skeleton({ shape = "line", ...rest }) {
14
+ return /* @__PURE__ */ jsx("div", {
15
+ "data-slot": "skeleton",
16
+ "aria-hidden": "true",
17
+ ...rest,
18
+ className: cn("rt:skeleton", SHAPE_CLASSES[shape])
19
+ });
20
+ }
21
+ export { Skeleton };
@@ -0,0 +1,2 @@
1
+ import { Skeleton, SkeletonProps, SkeletonShape } from "./Skeleton.js";
2
+ export { Skeleton, type SkeletonProps, type SkeletonShape };
@@ -0,0 +1 @@
1
+ export { Skeleton } from "./Skeleton.js";
@@ -0,0 +1,11 @@
1
+ import { HTMLAttributes, JSX } from "react";
2
+ /** The props of Spinner: the HTML attributes of its span, except className, style and children, with the label. */
3
+ export type SpinnerProps = Omit<HTMLAttributes<HTMLSpanElement>, 'className' | 'style' | 'children'> & {
4
+ /** The accessible name, announced to assistive technology. Defaults to Loading. */
5
+ label?: string;
6
+ };
7
+ /**
8
+ * A small ring for a wait with no known shape. It is static until the designer answers question 5: its motion is the
9
+ * --rt-spinner-animation token, none for now, so the ring is drawn from the progress colours and the status role says what it means.
10
+ */
11
+ export declare function Spinner({ label, ...rest }: SpinnerProps): JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ // src/components/spinner/Spinner.tsx
3
+ /**
4
+ * A small ring for a wait with no known shape. It is static until the designer answers question 5: its motion is the
5
+ * --rt-spinner-animation token, none for now, so the ring is drawn from the progress colours and the status role says what it means.
6
+ */
7
+ function Spinner({ label = "Loading", ...rest }) {
8
+ return /* @__PURE__ */ jsx("span", {
9
+ "data-slot": "spinner",
10
+ role: "status",
11
+ "aria-label": label,
12
+ ...rest,
13
+ className: "rt:inline-block rt:size-4 rt:rounded-3xl rt:border-2 rt:border-progress-track rt:border-t-progress rt:spinner-motion"
14
+ });
15
+ }
16
+ export { Spinner };
@@ -0,0 +1,2 @@
1
+ import { Spinner, SpinnerProps } from "./Spinner.js";
2
+ export { Spinner, type SpinnerProps };
@@ -0,0 +1 @@
1
+ export { Spinner } from "./Spinner.js";
@@ -0,0 +1,14 @@
1
+ import { HTMLAttributes, JSX, Ref } from "react";
2
+ /** The tone of a status pill: success is green, warning is amber, neutral is plain text until the designer answers question 3. */
3
+ export type StatusPillTone = 'success' | 'warning' | 'neutral';
4
+ /** The props of StatusPill: the HTML attributes of a span, except className and style, with the tone. */
5
+ export type StatusPillProps = Omit<HTMLAttributes<HTMLSpanElement>, 'className' | 'style'> & {
6
+ /** The colour of the pill. Defaults to neutral. */
7
+ tone?: StatusPillTone;
8
+ /** The status, one word: Draft, Active, Hidden, Low, Pending. */
9
+ children: React.ReactNode;
10
+ /** Receives the rendered span. */
11
+ ref?: Ref<HTMLSpanElement>;
12
+ };
13
+ /** A 20px pill with a 4px radius and a 1px border that names the state of a row, such as a product's status in a listing. */
14
+ export declare function StatusPill({ tone, children, ref, ...rest }: StatusPillProps): JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ // src/components/status-pill/StatusPill.tsx
4
+ const TONE_CLASSES = {
5
+ success: "rt:bg-success-tint rt:text-success rt:border-success-border",
6
+ warning: "rt:bg-warning-tint rt:text-warning rt:border-warning-border",
7
+ neutral: "rt:bg-status-neutral-background rt:text-status-neutral-foreground rt:border-status-neutral-border"
8
+ };
9
+ /** A 20px pill with a 4px radius and a 1px border that names the state of a row, such as a product's status in a listing. */
10
+ function StatusPill({ tone = "neutral", children, ref, ...rest }) {
11
+ return /* @__PURE__ */ jsx("span", {
12
+ ...rest,
13
+ ref,
14
+ "data-tone": tone,
15
+ className: cn("rt:inline-flex rt:h-5 rt:w-fit rt:shrink-0 rt:items-center rt:justify-center rt:rounded-sm rt:border rt:px-2 rt:text-c2 rt:whitespace-nowrap", TONE_CLASSES[tone]),
16
+ children
17
+ });
18
+ }
19
+ export { StatusPill };
@@ -0,0 +1,2 @@
1
+ import { StatusPill, StatusPillProps, StatusPillTone } from "./StatusPill.js";
2
+ export { StatusPill, type StatusPillProps, type StatusPillTone };
@@ -0,0 +1 @@
1
+ export { StatusPill } from "./StatusPill.js";
@@ -0,0 +1,46 @@
1
+ import { ComponentProps, JSX, ReactNode } from "react";
2
+ /** The props of Table: the attributes of a table element, except className and style. */
3
+ export type TableProps = Omit<ComponentProps<'table'>, 'className' | 'style'>;
4
+ /**
5
+ * A data table in the design system's Listing look: a 36px heading row over 48px rows split by 1px hairlines, 12px uppercase headings and a fill
6
+ * on the row under the pointer. It scrolls sideways inside its own box when the columns do not fit. Compose it from
7
+ * TableHeader, TableBody, TableRow, TableHead and TableCell.
8
+ */
9
+ export declare function Table(props: TableProps): JSX.Element;
10
+ /** The props of TableHeader: the attributes of a thead element, except className and style. */
11
+ export type TableHeaderProps = Omit<ComponentProps<'thead'>, 'className' | 'style'>;
12
+ /** The heading rows of a table. Its rows take no hover fill. */
13
+ export declare function TableHeader(props: TableHeaderProps): JSX.Element;
14
+ /** The props of TableBody: the attributes of a tbody element, except className and style. */
15
+ export type TableBodyProps = Omit<ComponentProps<'tbody'>, 'className' | 'style'>;
16
+ /** The data rows of a table. Its rows take the hover fill. */
17
+ export declare function TableBody(props: TableBodyProps): JSX.Element;
18
+ /** The props of TableFooter: the attributes of a tfoot element, except className and style. */
19
+ export type TableFooterProps = Omit<ComponentProps<'tfoot'>, 'className' | 'style'>;
20
+ /** The summary rows at the foot of a table, such as totals. Its rows take no hover fill. */
21
+ export declare function TableFooter(props: TableFooterProps): JSX.Element;
22
+ /** The props of TableRow: the attributes of a tr element, except className and style, and whether the row is selected. */
23
+ export type TableRowProps = Omit<ComponentProps<'tr'>, 'className' | 'style'> & {
24
+ /** Keeps the hover fill on the row to show it is chosen, for example when its checkbox is ticked. Defaults to false. */
25
+ selected?: boolean;
26
+ };
27
+ /** One row, 48px high (36px in the heading), with a hairline under it. A body row is filled when the pointer is over it or it is selected. */
28
+ export declare function TableRow({ selected, ...rest }: TableRowProps): JSX.Element;
29
+ /** The props of TableHead: the attributes of a th element, except className and style, and the alignment of its column. */
30
+ export type TableHeadProps = Omit<ComponentProps<'th'>, 'className' | 'style'> & {
31
+ /** Aligns the heading to the right, over a column of numbers. Defaults to false, which aligns it to the left. */
32
+ numeric?: boolean;
33
+ };
34
+ /** A column heading: 12px uppercase text in the subdued colour. It is a column header unless `scope` says otherwise. */
35
+ export declare function TableHead({ numeric, scope, ...rest }: TableHeadProps): JSX.Element;
36
+ /** The props of TableCell: the attributes of a td element, except className and style, and the alignment of its column. */
37
+ export type TableCellProps = Omit<ComponentProps<'td'>, 'className' | 'style'> & {
38
+ /** Aligns the cell to the right with tabular figures, for a number. Defaults to false, which aligns it to the left. */
39
+ numeric?: boolean;
40
+ };
41
+ /** One cell. Text stays on one line; a numeric cell is right aligned with tabular figures so digits line up. */
42
+ export declare function TableCell({ numeric, ...rest }: TableCellProps): JSX.Element;
43
+ /** The props of TableCaption: the attributes of a caption element, except className and style. */
44
+ export type TableCaptionProps = Omit<ComponentProps<'caption'>, 'className' | 'style'>;
45
+ /** The table's title for assistive technology, shown under the table in the subdued colour. */
46
+ export declare function TableCaption(props: TableCaptionProps): JSX.Element;
@@ -0,0 +1,87 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { createContext, use } from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ // src/components/table/Table.tsx
5
+ const SectionContext = createContext("body");
6
+ const BoxContext = createContext(false);
7
+ /** Draws the hairline box (1px border, 8px corners) round the Table inside it. For DataTable and TableLoader; not exported from the package. */
8
+ function TableBox({ children }) {
9
+ return /* @__PURE__ */ jsx(BoxContext, {
10
+ value: true,
11
+ children
12
+ });
13
+ }
14
+ /**
15
+ * A data table in the design system's Listing look: a 36px heading row over 48px rows split by 1px hairlines, 12px uppercase headings and a fill
16
+ * on the row under the pointer. It scrolls sideways inside its own box when the columns do not fit. Compose it from
17
+ * TableHeader, TableBody, TableRow, TableHead and TableCell.
18
+ */
19
+ function Table(props) {
20
+ const boxed = use(BoxContext);
21
+ return /* @__PURE__ */ jsx("div", {
22
+ role: "region",
23
+ tabIndex: 0,
24
+ "aria-label": props["aria-label"],
25
+ "aria-labelledby": props["aria-labelledby"],
26
+ "data-boxed": boxed ? "true" : void 0,
27
+ className: cn("rt:relative rt:w-full rt:overflow-x-auto rt:focus-visible:focus-ring", boxed && "rt:rounded-lg rt:border rt:border-border"),
28
+ children: /* @__PURE__ */ jsx("table", {
29
+ className: "rt:w-full rt:border-collapse rt:caption-bottom rt:bg-background rt:text-b3 rt:text-foreground",
30
+ ...props
31
+ })
32
+ });
33
+ }
34
+ /** The heading rows of a table. Its rows take no hover fill. */
35
+ function TableHeader(props) {
36
+ return /* @__PURE__ */ jsx(SectionContext, {
37
+ value: "head",
38
+ children: /* @__PURE__ */ jsx("thead", { ...props })
39
+ });
40
+ }
41
+ /** The data rows of a table. Its rows take the hover fill. */
42
+ function TableBody(props) {
43
+ return /* @__PURE__ */ jsx(SectionContext, {
44
+ value: "body",
45
+ children: /* @__PURE__ */ jsx("tbody", { ...props })
46
+ });
47
+ }
48
+ /** The summary rows at the foot of a table, such as totals. Its rows take no hover fill. */
49
+ function TableFooter(props) {
50
+ return /* @__PURE__ */ jsx(SectionContext, {
51
+ value: "foot",
52
+ children: /* @__PURE__ */ jsx("tfoot", { ...props })
53
+ });
54
+ }
55
+ /** One row, 48px high (36px in the heading), with a hairline under it. A body row is filled when the pointer is over it or it is selected. */
56
+ function TableRow({ selected = false, ...rest }) {
57
+ const section = use(SectionContext);
58
+ const boxed = use(BoxContext);
59
+ return /* @__PURE__ */ jsx("tr", {
60
+ "data-selected": selected ? "true" : void 0,
61
+ className: cn("rt:border-b rt:border-border rt:transition-colors", section === "head" ? "rt:h-9" : "rt:h-12", boxed && section === "body" && "rt:last:border-b-0", section === "body" && "rt:hover:bg-muted rt:data-selected:bg-muted"),
62
+ ...rest
63
+ });
64
+ }
65
+ /** A column heading: 12px uppercase text in the subdued colour. It is a column header unless `scope` says otherwise. */
66
+ function TableHead({ numeric = false, scope = "col", ...rest }) {
67
+ return /* @__PURE__ */ jsx("th", {
68
+ scope,
69
+ className: cn("rt:px-2 rt:align-middle rt:text-label rt:uppercase rt:whitespace-nowrap rt:text-foreground-subdued", numeric ? "rt:text-right" : "rt:text-left"),
70
+ ...rest
71
+ });
72
+ }
73
+ /** One cell. Text stays on one line; a numeric cell is right aligned with tabular figures so digits line up. */
74
+ function TableCell({ numeric = false, ...rest }) {
75
+ return /* @__PURE__ */ jsx("td", {
76
+ className: cn("rt:px-2 rt:align-middle rt:whitespace-nowrap", numeric ? "rt:text-right rt:tabular-nums" : "rt:text-left"),
77
+ ...rest
78
+ });
79
+ }
80
+ /** The table's title for assistive technology, shown under the table in the subdued colour. */
81
+ function TableCaption(props) {
82
+ return /* @__PURE__ */ jsx("caption", {
83
+ className: "rt:py-2 rt:text-left rt:text-c1 rt:text-foreground-subdued",
84
+ ...props
85
+ });
86
+ }
87
+ export { Table, TableBody, TableBox, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
@@ -0,0 +1,2 @@
1
+ import { Table, TableBody, TableBodyProps, TableCaption, TableCaptionProps, TableCell, TableCellProps, TableFooter, TableFooterProps, TableHead, TableHeadProps, TableHeader, TableHeaderProps, TableProps, TableRow, TableRowProps } from "./Table.js";
2
+ export { Table, TableBody, type TableBodyProps, TableCaption, type TableCaptionProps, TableCell, type TableCellProps, TableFooter, type TableFooterProps, TableHead, type TableHeadProps, TableHeader, type TableHeaderProps, type TableProps, TableRow, type TableRowProps };
@@ -0,0 +1 @@
1
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "./Table.js";
@@ -0,0 +1,31 @@
1
+ import { TableProps } from "../table/Table.js";
2
+ import "../table/index.js";
3
+ import { JSX } from "react";
4
+ /** One column of the loading table: its real heading, and whether it holds numbers. */
5
+ export type TableLoaderColumn = {
6
+ /** A stable key for the column. */
7
+ id: string;
8
+ /** The heading, shown for real so the layout does not jump when the data arrives. */
9
+ header: string;
10
+ /** Aligns the heading and the placeholder to the right. Defaults to false. */
11
+ numeric?: boolean;
12
+ };
13
+ /** The props of TableLoader: the attributes of Table, plus the columns, how many rows to fake and the count line. */
14
+ export type TableLoaderProps = Omit<TableProps, 'children' | 'aria-busy'> & {
15
+ /** The columns, in order. */
16
+ columns: TableLoaderColumn[];
17
+ /** How many placeholder rows to draw. Defaults to 5. */
18
+ rows?: number;
19
+ /** How many results the first page will hold, for the count line. */
20
+ shown: number;
21
+ /** How many results there are in all. */
22
+ total: number;
23
+ /** What the results are called, in the plural: "products". */
24
+ noun: string;
25
+ };
26
+ /**
27
+ * What a table shows on its first load: the real headings over static skeleton rows, and a count line such as
28
+ * "72 of 1000 products". The table is marked busy and the fake rows are hidden from screen readers. Use it for the first
29
+ * load only; later loads keep the old rows.
30
+ */
31
+ export declare function TableLoader({ columns, rows, shown, total, noun, ...rest }: TableLoaderProps): JSX.Element;
@@ -0,0 +1,35 @@
1
+ import { formatCount } from "../../lib/format.js";
2
+ import { Table, TableBody, TableBox, TableCell, TableHead, TableHeader, TableRow } from "../table/Table.js";
3
+ import { Skeleton } from "../skeleton/Skeleton.js";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ // src/components/table-loader/TableLoader.tsx
6
+ /**
7
+ * What a table shows on its first load: the real headings over static skeleton rows, and a count line such as
8
+ * "72 of 1000 products". The table is marked busy and the fake rows are hidden from screen readers. Use it for the first
9
+ * load only; later loads keep the old rows.
10
+ */
11
+ function TableLoader({ columns, rows = 5, shown, total, noun, ...rest }) {
12
+ return /* @__PURE__ */ jsxs("div", {
13
+ "data-slot": "table-loader",
14
+ className: "rt:flex rt:w-full rt:flex-col",
15
+ children: [/* @__PURE__ */ jsx(TableBox, { children: /* @__PURE__ */ jsxs(Table, {
16
+ "aria-busy": "true",
17
+ ...rest,
18
+ children: [/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsx(TableRow, { children: columns.map((c) => /* @__PURE__ */ jsx(TableHead, {
19
+ numeric: c.numeric,
20
+ children: c.header
21
+ }, c.id)) }) }), /* @__PURE__ */ jsx(TableBody, { children: Array.from({ length: rows }, (_, i) => /* @__PURE__ */ jsx(TableRow, {
22
+ "aria-hidden": "true",
23
+ children: columns.map((c) => /* @__PURE__ */ jsx(TableCell, {
24
+ numeric: c.numeric,
25
+ children: /* @__PURE__ */ jsx(Skeleton, {})
26
+ }, c.id))
27
+ }, i)) })]
28
+ }) }), /* @__PURE__ */ jsx("p", {
29
+ role: "status",
30
+ className: "rt:py-3 rt:text-c1 rt:text-foreground-subdued",
31
+ children: `${formatCount(shown)} of ${formatCount(total)} ${noun}`
32
+ })]
33
+ });
34
+ }
35
+ export { TableLoader };
@@ -0,0 +1,2 @@
1
+ import { TableLoader, TableLoaderColumn, TableLoaderProps } from "./TableLoader.js";
2
+ export { TableLoader, type TableLoaderColumn, type TableLoaderProps };
@@ -0,0 +1 @@
1
+ export { TableLoader } from "./TableLoader.js";
@@ -0,0 +1,23 @@
1
+ import { ComponentProps, JSX } from "react";
2
+ import { Tabs } from "@base-ui/react/tabs";
3
+ /** The props of Tabs: Base UI's tabs root without className and style. */
4
+ export type TabsProps = Omit<ComponentProps<typeof Tabs.Root>, 'className' | 'style'>;
5
+ /** The props of TabsList: Base UI's tab list without className and style. */
6
+ export type TabsListProps = Omit<ComponentProps<typeof Tabs.List>, 'className' | 'style'>;
7
+ /** The props of TabsTrigger: Base UI's tab without className and style. Its value ties it to the TabsContent with the same value. */
8
+ export type TabsTriggerProps = Omit<ComponentProps<typeof Tabs.Tab>, 'className' | 'style'>;
9
+ /** The props of TabsContent: Base UI's tab panel without className and style. Its value ties it to the TabsTrigger with the same value. */
10
+ export type TabsContentProps = Omit<ComponentProps<typeof Tabs.Panel>, 'className' | 'style'>;
11
+ /**
12
+ * Sections of one page, switched by an underlined row of tabs: ABC analysis, the sections of a settings page. Holds the
13
+ * selected value, uncontrolled with defaultValue or controlled with value and onValueChange. To filter a list use
14
+ * FilterTabs, which looks like the design system's chip tab.
15
+ */
16
+ declare function Tabs$1(props: TabsProps): JSX.Element;
17
+ /** The row of tabs, with a hairline under it. Give it an aria-label that names the sections. */
18
+ export declare function TabsList(props: TabsListProps): JSX.Element;
19
+ /** One tab: 36px tall, with a 2px blue underline and a blue semibold label when selected. A disabled tab is at 50%. */
20
+ export declare function TabsTrigger(props: TabsTriggerProps): JSX.Element;
21
+ /** The panel of the tab with the same value; only the selected one is shown. */
22
+ export declare function TabsContent(props: TabsContentProps): JSX.Element;
23
+ export { Tabs$1 as Tabs };
@@ -0,0 +1,41 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Tabs } from "@base-ui/react/tabs";
4
+ // src/components/tabs/Tabs.tsx
5
+ /**
6
+ * Sections of one page, switched by an underlined row of tabs: ABC analysis, the sections of a settings page. Holds the
7
+ * selected value, uncontrolled with defaultValue or controlled with value and onValueChange. To filter a list use
8
+ * FilterTabs, which looks like the design system's chip tab.
9
+ */
10
+ function Tabs$1(props) {
11
+ return /* @__PURE__ */ jsx(Tabs.Root, {
12
+ "data-slot": "tabs",
13
+ className: cn("rt:flex rt:flex-col rt:gap-3"),
14
+ ...props
15
+ });
16
+ }
17
+ /** The row of tabs, with a hairline under it. Give it an aria-label that names the sections. */
18
+ function TabsList(props) {
19
+ return /* @__PURE__ */ jsx(Tabs.List, {
20
+ "data-slot": "tabs-list",
21
+ className: cn("rt:flex rt:items-center rt:gap-6 rt:border-b rt:border-border"),
22
+ ...props
23
+ });
24
+ }
25
+ /** One tab: 36px tall, with a 2px blue underline and a blue semibold label when selected. A disabled tab is at 50%. */
26
+ function TabsTrigger(props) {
27
+ return /* @__PURE__ */ jsx(Tabs.Tab, {
28
+ "data-slot": "tabs-trigger",
29
+ className: cn("rt:relative rt:inline-flex rt:h-9 rt:cursor-pointer rt:items-center rt:justify-center rt:gap-2 rt:whitespace-nowrap", "rt:text-b3 rt:text-tab-inactive rt:transition-colors rt:hover:text-foreground", "rt:data-active:font-semibold rt:data-active:text-primary", "rt:focus-visible:focus-ring rt:data-disabled:cursor-default rt:data-disabled:opacity-50", "rt:after:absolute rt:after:inset-x-0 rt:after:-bottom-px rt:after:h-0.5 rt:after:bg-primary rt:after:opacity-0", "rt:data-active:after:opacity-100 rt:svg:text-icon"),
30
+ ...props
31
+ });
32
+ }
33
+ /** The panel of the tab with the same value; only the selected one is shown. */
34
+ function TabsContent(props) {
35
+ return /* @__PURE__ */ jsx(Tabs.Panel, {
36
+ "data-slot": "tabs-content",
37
+ className: cn("rt:flex-1 rt:text-b3 rt:focus-visible:focus-ring"),
38
+ ...props
39
+ });
40
+ }
41
+ export { Tabs$1 as Tabs, TabsContent, TabsList, TabsTrigger };
@@ -0,0 +1,2 @@
1
+ import { Tabs, TabsContent, TabsContentProps, TabsList, TabsListProps, TabsProps, TabsTrigger, TabsTriggerProps } from "./Tabs.js";
2
+ export { Tabs, TabsContent, type TabsContentProps, TabsList, type TabsListProps, type TabsProps, TabsTrigger, type TabsTriggerProps };
@@ -0,0 +1 @@
1
+ export { Tabs, TabsContent, TabsList, TabsTrigger } from "./Tabs.js";
@@ -0,0 +1,32 @@
1
+ import { JSX, ReactNode } from "react";
2
+ /** What a toast can carry besides its title. */
3
+ export interface ToastOptions {
4
+ /** A second line under the title. */
5
+ description?: ReactNode;
6
+ /** How long it stays, in ms. Defaults to 5000; 0 keeps it until it is closed. */
7
+ timeout?: number;
8
+ }
9
+ /**
10
+ * Shows a message after an action. Call toast.success, toast.info or toast.error with the title, from anywhere; a Toaster
11
+ * must be mounted once in the app. Each is announced to screen readers through a polite live region.
12
+ */
13
+ export declare const toast: {
14
+ /** Shows a success message and returns its id. */
15
+ success: (title: ReactNode, options?: ToastOptions) => string;
16
+ /** Shows an info message and returns its id. */
17
+ info: (title: ReactNode, options?: ToastOptions) => string;
18
+ /** Shows an error message and returns its id. */
19
+ error: (title: ReactNode, options?: ToastOptions) => string;
20
+ /** Closes one toast by id, or all when none is given. */
21
+ dismiss: (id?: string) => void;
22
+ };
23
+ /** Props of Toaster. */
24
+ export interface ToasterProps {
25
+ /** The accessible name of each close button. Defaults to Close notification. */
26
+ closeLabel?: string;
27
+ }
28
+ /**
29
+ * Mounts the toast viewport, bottom right, once for the app. Messages from toast() appear in it as plain panels with the
30
+ * ring outline, stacked, with no entrance animation.
31
+ */
32
+ export declare function Toaster({ closeLabel }: ToasterProps): JSX.Element;
@@ -0,0 +1,89 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { Icon } from "../icon/Icon.js";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ import { Toast } from "@base-ui/react/toast";
5
+ // src/components/toaster/Toaster.tsx
6
+ const manager = Toast.createToastManager();
7
+ function show(type, title, options = {}) {
8
+ return manager.add({
9
+ type,
10
+ title,
11
+ description: options.description,
12
+ timeout: options.timeout,
13
+ priority: "low"
14
+ });
15
+ }
16
+ /**
17
+ * Shows a message after an action. Call toast.success, toast.info or toast.error with the title, from anywhere; a Toaster
18
+ * must be mounted once in the app. Each is announced to screen readers through a polite live region.
19
+ */
20
+ const toast = {
21
+ /** Shows a success message and returns its id. */
22
+ success: (title, options) => show("success", title, options),
23
+ /** Shows an info message and returns its id. */
24
+ info: (title, options) => show("info", title, options),
25
+ /** Shows an error message and returns its id. */
26
+ error: (title, options) => show("error", title, options),
27
+ /** Closes one toast by id, or all when none is given. */
28
+ dismiss: (id) => manager.close(id)
29
+ };
30
+ const ICONS = {
31
+ success: "check",
32
+ info: "info-circle",
33
+ error: "alert-triangle"
34
+ };
35
+ function ToastList({ closeLabel }) {
36
+ const { toasts } = Toast.useToastManager();
37
+ return /* @__PURE__ */ jsx(Fragment, { children: toasts.map((item) => {
38
+ const kind = item.type ?? "info";
39
+ return /* @__PURE__ */ jsxs(Toast.Root, {
40
+ toast: item,
41
+ "data-slot": "toast",
42
+ className: "rt:pointer-events-auto rt:flex rt:w-full rt:items-start rt:gap-3 rt:rounded-lg rt:bg-popover rt:p-3 rt:text-popover-foreground rt:shadow-ring-strong rt:forced-outline",
43
+ children: [
44
+ /* @__PURE__ */ jsx("span", {
45
+ "data-slot": "toast-icon",
46
+ className: cn("rt:flex rt:h-5 rt:items-center", kind === "error" ? "rt:text-error-icon" : "rt:text-icon"),
47
+ children: /* @__PURE__ */ jsx(Icon, {
48
+ name: ICONS[kind],
49
+ size: 16
50
+ })
51
+ }),
52
+ /* @__PURE__ */ jsxs(Toast.Content, {
53
+ className: "rt:flex rt:min-w-0 rt:flex-1 rt:flex-col rt:gap-1",
54
+ children: [/* @__PURE__ */ jsx(Toast.Title, {
55
+ "data-slot": "toast-title",
56
+ className: cn("rt:text-b4", kind === "error" ? "rt:text-error" : "rt:text-foreground-strong")
57
+ }), /* @__PURE__ */ jsx(Toast.Description, {
58
+ "data-slot": "toast-description",
59
+ className: "rt:text-b3 rt:text-foreground-subdued"
60
+ })]
61
+ }),
62
+ /* @__PURE__ */ jsx(Toast.Close, {
63
+ "aria-label": closeLabel,
64
+ "data-slot": "toast-close",
65
+ className: "rt:flex rt:size-5 rt:shrink-0 rt:items-center rt:justify-center rt:rounded-md rt:text-icon rt:transition-colors rt:hover:bg-primary-tint rt:focus-visible:focus-ring",
66
+ children: /* @__PURE__ */ jsx(Icon, {
67
+ name: "x",
68
+ size: 12
69
+ })
70
+ })
71
+ ]
72
+ }, item.id);
73
+ }) });
74
+ }
75
+ /**
76
+ * Mounts the toast viewport, bottom right, once for the app. Messages from toast() appear in it as plain panels with the
77
+ * ring outline, stacked, with no entrance animation.
78
+ */
79
+ function Toaster({ closeLabel = "Close notification" }) {
80
+ return /* @__PURE__ */ jsx(Toast.Provider, {
81
+ toastManager: manager,
82
+ children: /* @__PURE__ */ jsx(Toast.Portal, { children: /* @__PURE__ */ jsx(Toast.Viewport, {
83
+ "data-slot": "toast-viewport",
84
+ className: "rt:pointer-events-none rt:fixed rt:right-4 rt:bottom-4 rt:z-50 rt:flex rt:w-90 rt:max-w-full rt:flex-col rt:gap-2",
85
+ children: /* @__PURE__ */ jsx(ToastList, { closeLabel })
86
+ }) })
87
+ });
88
+ }
89
+ export { Toaster, toast };
@@ -0,0 +1,2 @@
1
+ import { ToastOptions, Toaster, ToasterProps, toast } from "./Toaster.js";
2
+ export { type ToastOptions, Toaster, type ToasterProps, toast };
@@ -0,0 +1 @@
1
+ export { Toaster, toast } from "./Toaster.js";
@@ -0,0 +1,18 @@
1
+ import { Tooltip } from "@base-ui/react/tooltip";
2
+ /** The props of TooltipProvider: Base UI's provider props. */
3
+ export type TooltipProviderProps = Tooltip.Provider.Props;
4
+ /** Shares the open delay between the tooltips inside it. Wrap the app, or a group of tooltips, once. The delay defaults to 0 ms. */
5
+ export declare function TooltipProvider({ delay, ...props }: TooltipProviderProps): import("react").JSX.Element;
6
+ /** The props of Tooltip: Base UI's root props, such as open, defaultOpen and onOpenChange. */
7
+ export type TooltipProps = Tooltip.Root.Props;
8
+ /** A short hint for a control or term, shown on hover and keyboard focus. Put a TooltipTrigger and a TooltipContent inside it. */
9
+ declare function Tooltip$1(props: TooltipProps): import("react").JSX.Element;
10
+ /** The props of TooltipTrigger: Base UI's trigger props, except className and style. Use render to put the trigger on your own element. */
11
+ export type TooltipTriggerProps = Omit<Tooltip.Trigger.Props, 'className' | 'style'>;
12
+ /** The element that opens the tooltip on hover and focus. It renders a button unless render says otherwise. */
13
+ export declare function TooltipTrigger(props: TooltipTriggerProps): import("react").JSX.Element;
14
+ /** The props of TooltipContent: the popup props plus where the tooltip sits. */
15
+ export type TooltipContentProps = Omit<Tooltip.Popup.Props, 'className' | 'style'> & Pick<Tooltip.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>;
16
+ /** The tooltip text: a dark panel with light text, no shadow and no animation. It sits above the trigger by default. */
17
+ export declare function TooltipContent({ side, sideOffset, align, alignOffset, children, ...props }: TooltipContentProps): import("react").JSX.Element;
18
+ export { Tooltip$1 as Tooltip };
@@ -0,0 +1,35 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { Tooltip } from "@base-ui/react/tooltip";
4
+ // src/components/tooltip/Tooltip.tsx
5
+ /** Shares the open delay between the tooltips inside it. Wrap the app, or a group of tooltips, once. The delay defaults to 0 ms. */
6
+ function TooltipProvider({ delay = 0, ...props }) {
7
+ return /* @__PURE__ */ jsx(Tooltip.Provider, {
8
+ delay,
9
+ ...props
10
+ });
11
+ }
12
+ /** A short hint for a control or term, shown on hover and keyboard focus. Put a TooltipTrigger and a TooltipContent inside it. */
13
+ function Tooltip$1(props) {
14
+ return /* @__PURE__ */ jsx(Tooltip.Root, { ...props });
15
+ }
16
+ /** The element that opens the tooltip on hover and focus. It renders a button unless render says otherwise. */
17
+ function TooltipTrigger(props) {
18
+ return /* @__PURE__ */ jsx(Tooltip.Trigger, { ...props });
19
+ }
20
+ /** The tooltip text: a dark panel with light text, no shadow and no animation. It sits above the trigger by default. */
21
+ function TooltipContent({ side = "top", sideOffset = 4, align = "center", alignOffset = 0, children, ...props }) {
22
+ return /* @__PURE__ */ jsx(Tooltip.Portal, { children: /* @__PURE__ */ jsx(Tooltip.Positioner, {
23
+ align,
24
+ alignOffset,
25
+ side,
26
+ sideOffset,
27
+ className: "rt:isolate rt:z-50",
28
+ children: /* @__PURE__ */ jsx(Tooltip.Popup, {
29
+ className: cn("rt:inline-flex rt:w-fit rt:max-w-72 rt:items-center rt:gap-1.5 rt:rounded-md rt:bg-foreground rt:px-3 rt:py-1.5 rt:text-b1 rt:text-background"),
30
+ ...props,
31
+ children
32
+ })
33
+ }) });
34
+ }
35
+ export { Tooltip$1 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
@@ -0,0 +1,2 @@
1
+ import { Tooltip, TooltipContent, TooltipContentProps, TooltipProps, TooltipProvider, TooltipProviderProps, TooltipTrigger, TooltipTriggerProps } from "./Tooltip.js";
2
+ export { Tooltip, TooltipContent, type TooltipContentProps, type TooltipProps, TooltipProvider, type TooltipProviderProps, TooltipTrigger, type TooltipTriggerProps };
@@ -0,0 +1 @@
1
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./Tooltip.js";
@@ -0,0 +1,26 @@
1
+ import { JSX } from "react";
2
+ /** One store the person can switch to. */
3
+ export type StoreOption = {
4
+ /** The value passed to onStoreChange and compared with storeId. */
5
+ id: string;
6
+ /** The store name, shown in the bar and the menu. */
7
+ name: string;
8
+ /** The store's logo; without one the avatar shows its initials. */
9
+ src?: string;
10
+ };
11
+ /** The props of StoreSwitcher. */
12
+ export type StoreSwitcherProps = {
13
+ /** The stores the person can switch between, as the app passes them. */
14
+ stores: StoreOption[];
15
+ /** The id of the current store. */
16
+ storeId: string;
17
+ /** Called with the id of the store chosen. */
18
+ onStoreChange?: (id: string) => void;
19
+ /** The caption of its menu. Defaults to Switch store. The button is named by the store name. */
20
+ label?: string;
21
+ };
22
+ /**
23
+ * The store switcher of TopBar: a square avatar, the store name and a chevron that open a menu of the stores the app
24
+ * passes. On a phone only the avatar shows. Pass it to TopBar's `storeSwitcher` slot.
25
+ */
26
+ export declare function StoreSwitcher({ stores, storeId, onStoreChange, label }: StoreSwitcherProps): JSX.Element;