@birdycom/omniaui-react 0.11.0 → 0.11.1

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 (143) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +21 -21
  3. package/package.json +71 -71
  4. package/src/blocks/BlockAboutTimeline.tsx +46 -46
  5. package/src/blocks/BlockAppHeader.tsx +52 -52
  6. package/src/blocks/BlockAppShell.tsx +56 -56
  7. package/src/blocks/BlockAuth.tsx +53 -53
  8. package/src/blocks/BlockAuthSplit.tsx +84 -84
  9. package/src/blocks/BlockContactGrid.tsx +71 -71
  10. package/src/blocks/BlockCta.tsx +23 -23
  11. package/src/blocks/BlockDataTable.tsx +57 -57
  12. package/src/blocks/BlockFaq.tsx +55 -55
  13. package/src/blocks/BlockFeatures.tsx +38 -38
  14. package/src/blocks/BlockFooter.tsx +50 -50
  15. package/src/blocks/BlockFormPage.tsx +26 -26
  16. package/src/blocks/BlockHero.tsx +27 -27
  17. package/src/blocks/BlockHeroCode.tsx +63 -63
  18. package/src/blocks/BlockHeroOrbit.tsx +73 -73
  19. package/src/blocks/BlockHeroSplit.tsx +28 -28
  20. package/src/blocks/BlockModuleHeader.tsx +34 -34
  21. package/src/blocks/BlockPageHero.tsx +25 -25
  22. package/src/blocks/BlockPortfolioGrid.tsx +50 -50
  23. package/src/blocks/BlockPricing.tsx +62 -62
  24. package/src/blocks/BlockProcess.tsx +50 -50
  25. package/src/blocks/BlockProductGrid.tsx +54 -54
  26. package/src/blocks/BlockProfileHeader.tsx +57 -57
  27. package/src/blocks/BlockShowcase.tsx +58 -58
  28. package/src/blocks/BlockSiteFooter.tsx +60 -60
  29. package/src/blocks/BlockSiteHeader.tsx +42 -42
  30. package/src/blocks/BlockSpotlight.tsx +58 -58
  31. package/src/blocks/BlockStats.tsx +26 -26
  32. package/src/blocks/BlockStatsCounter.tsx +31 -31
  33. package/src/blocks/BlockTeamList.tsx +48 -48
  34. package/src/blocks/BlockTwoFactor.tsx +57 -57
  35. package/src/blocks/BlockWizardDialog.tsx +101 -101
  36. package/src/components/Accordion.tsx +31 -31
  37. package/src/components/AccordionAccent.tsx +39 -39
  38. package/src/components/AffixInput.tsx +47 -47
  39. package/src/components/Alert.tsx +24 -24
  40. package/src/components/AlertDialog.tsx +60 -60
  41. package/src/components/AlphaTabs.tsx +63 -63
  42. package/src/components/Attachment.tsx +140 -140
  43. package/src/components/Avatar.tsx +32 -32
  44. package/src/components/BackLink.tsx +11 -11
  45. package/src/components/Badge.tsx +14 -14
  46. package/src/components/BarcodeInput.tsx +64 -64
  47. package/src/components/Breadcrumb.tsx +32 -32
  48. package/src/components/BrowserFrame.tsx +48 -48
  49. package/src/components/BusyOverlay.tsx +52 -52
  50. package/src/components/Button.tsx +49 -49
  51. package/src/components/Card.tsx +27 -27
  52. package/src/components/ChartLine.tsx +119 -119
  53. package/src/components/ChatComposer.tsx +73 -73
  54. package/src/components/Checkbox.tsx +14 -14
  55. package/src/components/Checklist.tsx +45 -45
  56. package/src/components/ChipFilter.tsx +60 -60
  57. package/src/components/Collapsible.tsx +43 -43
  58. package/src/components/ColorField.tsx +48 -48
  59. package/src/components/ColorSelect.tsx +49 -49
  60. package/src/components/ColumnMenu.tsx +66 -66
  61. package/src/components/Command.tsx +113 -113
  62. package/src/components/ConfirmDialog.tsx +95 -95
  63. package/src/components/CookieConsent.tsx +137 -137
  64. package/src/components/CopyField.tsx +44 -44
  65. package/src/components/Counter.tsx +21 -21
  66. package/src/components/DataTable.tsx +201 -201
  67. package/src/components/DecimalInput.tsx +87 -87
  68. package/src/components/DefinitionList.tsx +38 -38
  69. package/src/components/DocViewer.tsx +110 -110
  70. package/src/components/Dropdown.tsx +52 -52
  71. package/src/components/Dropzone.tsx +46 -46
  72. package/src/components/EmojiPicker.tsx +72 -72
  73. package/src/components/EmptyState.tsx +27 -27
  74. package/src/components/EntityCard.tsx +56 -56
  75. package/src/components/FactList.tsx +43 -43
  76. package/src/components/FilterCounts.tsx +50 -50
  77. package/src/components/FlipCard.tsx +55 -55
  78. package/src/components/FormField.tsx +54 -54
  79. package/src/components/Greeting.tsx +63 -63
  80. package/src/components/Heading.tsx +27 -27
  81. package/src/components/Icon.tsx +25 -25
  82. package/src/components/ImageZoom.tsx +51 -51
  83. package/src/components/Input.tsx +21 -21
  84. package/src/components/InputGroup.tsx +24 -24
  85. package/src/components/LanguageSelect.tsx +64 -64
  86. package/src/components/LauncherCard.tsx +50 -50
  87. package/src/components/Lightbox.tsx +83 -83
  88. package/src/components/LinkArrow.tsx +27 -27
  89. package/src/components/ListToolbar.tsx +67 -67
  90. package/src/components/Marquee.tsx +38 -38
  91. package/src/components/MediaCard.tsx +47 -47
  92. package/src/components/MediaRow.tsx +53 -53
  93. package/src/components/MediaThumb.tsx +49 -49
  94. package/src/components/Message.tsx +171 -171
  95. package/src/components/MessageThread.tsx +177 -177
  96. package/src/components/Modal.tsx +81 -81
  97. package/src/components/Navmenu.tsx +62 -62
  98. package/src/components/NextTeaser.tsx +29 -29
  99. package/src/components/NumberInput.tsx +64 -64
  100. package/src/components/OtpInput.tsx +48 -48
  101. package/src/components/PageHeader.tsx +43 -43
  102. package/src/components/Pagination.tsx +42 -42
  103. package/src/components/PasswordInput.tsx +36 -36
  104. package/src/components/PasswordRequirements.tsx +46 -46
  105. package/src/components/PhoneInput.tsx +93 -93
  106. package/src/components/Popover.tsx +34 -34
  107. package/src/components/PriceCard.tsx +83 -83
  108. package/src/components/ProductMark.tsx +35 -35
  109. package/src/components/Progress.tsx +32 -32
  110. package/src/components/ProjectCard.tsx +46 -46
  111. package/src/components/Prose.tsx +79 -79
  112. package/src/components/RecoveryCodes.tsx +65 -65
  113. package/src/components/Segmented.tsx +47 -47
  114. package/src/components/Select.tsx +27 -27
  115. package/src/components/SeverityCard.tsx +53 -53
  116. package/src/components/Sheet.tsx +62 -62
  117. package/src/components/Skeleton.tsx +12 -12
  118. package/src/components/SortableRow.tsx +46 -46
  119. package/src/components/StackCard.tsx +40 -40
  120. package/src/components/StackList.tsx +42 -42
  121. package/src/components/StatCard.tsx +49 -49
  122. package/src/components/Stepper.tsx +54 -54
  123. package/src/components/Switch.tsx +18 -18
  124. package/src/components/Table.tsx +75 -75
  125. package/src/components/TableActions.tsx +54 -54
  126. package/src/components/TableCompact.tsx +61 -61
  127. package/src/components/Tabs.tsx +45 -45
  128. package/src/components/TagInput.tsx +73 -73
  129. package/src/components/TerminalLog.tsx +63 -63
  130. package/src/components/Textarea.tsx +19 -19
  131. package/src/components/ThemeSwitch.tsx +45 -45
  132. package/src/components/TimeInput.tsx +76 -76
  133. package/src/components/Timeline.tsx +45 -45
  134. package/src/components/Toast.tsx +138 -138
  135. package/src/components/ToggleField.tsx +39 -39
  136. package/src/components/Tooltip.tsx +14 -14
  137. package/src/components/TopProgress.tsx +54 -54
  138. package/src/components/Tree.tsx +97 -97
  139. package/src/components/UpgradeBanner.tsx +62 -62
  140. package/src/components/User.tsx +31 -31
  141. package/src/components/VersionBanner.tsx +41 -41
  142. package/src/hooks.tsx +141 -141
  143. package/src/utils.ts +25 -25
@@ -1,49 +1,49 @@
1
- // File: packages/react/src/components/StatCard.tsx
2
- // Map: StatCardGrid (row of cards) -> StatCard = card (div, a or button) -> icon -> body (value + trend, label)
3
- // With `href` the card is a link, with `onClick` a button; otherwise a plain div.
4
- import { forwardRef } from "react";
5
- import type { HTMLAttributes, ReactNode } from "react";
6
- import { cx } from "../utils";
7
-
8
- /** `.oc-stat-card-grid`: responsive grid for a row of stat cards. */
9
- export const StatCardGrid = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function StatCardGrid(
10
- { className, ...rest },
11
- ref,
12
- ) {
13
- return <div ref={ref} className={cx("oc-stat-card-grid", className)} {...rest} />;
14
- });
15
-
16
- export interface StatCardProps extends Omit<HTMLAttributes<HTMLElement>, "onClick"> {
17
- value: ReactNode;
18
- label: ReactNode;
19
- icon?: ReactNode;
20
- /** Trend chip text after the value, e.g. "+12%". */
21
- trend?: ReactNode;
22
- trendDirection?: "up" | "down";
23
- tone?: "default" | "accent" | "success" | "warning";
24
- /** Colored start edge. */
25
- stripe?: boolean;
26
- href?: string;
27
- onClick?: () => void;
28
- }
29
-
30
- /** `.oc-stat-card`: compact KPI tile. */
31
- export function StatCard({ value, label, icon, trend, trendDirection = "up", tone = "default", stripe, href, onClick, className, ...rest }: StatCardProps) {
32
- const cls = cx("oc-stat-card", tone !== "default" && `oc-stat-card--${tone}`, stripe && "oc-stat-card--stripe", className);
33
- // Spans only inside the body, so the markup is also valid inside a link or button.
34
- const content = (
35
- <>
36
- {icon != null && <span className="oc-stat-card-icon" aria-hidden="true">{icon}</span>}
37
- <span className="oc-stat-card-body">
38
- <span className="oc-stat-card-value">
39
- {value}
40
- {trend != null && <span className={`oc-stat-card-trend oc-stat-card-trend--${trendDirection}`}>{trend}</span>}
41
- </span>
42
- <span className="oc-stat-card-label">{label}</span>
43
- </span>
44
- </>
45
- );
46
- if (href !== undefined) return <a className={cls} href={href} {...rest}>{content}</a>;
47
- if (onClick) return <button className={cls} type="button" onClick={onClick} {...rest}>{content}</button>;
48
- return <div className={cls} {...rest}>{content}</div>;
49
- }
1
+ // File: packages/react/src/components/StatCard.tsx
2
+ // Map: StatCardGrid (row of cards) -> StatCard = card (div, a or button) -> icon -> body (value + trend, label)
3
+ // With `href` the card is a link, with `onClick` a button; otherwise a plain div.
4
+ import { forwardRef } from "react";
5
+ import type { HTMLAttributes, ReactNode } from "react";
6
+ import { cx } from "../utils";
7
+
8
+ /** `.oc-stat-card-grid`: responsive grid for a row of stat cards. */
9
+ export const StatCardGrid = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(function StatCardGrid(
10
+ { className, ...rest },
11
+ ref,
12
+ ) {
13
+ return <div ref={ref} className={cx("oc-stat-card-grid", className)} {...rest} />;
14
+ });
15
+
16
+ export interface StatCardProps extends Omit<HTMLAttributes<HTMLElement>, "onClick"> {
17
+ value: ReactNode;
18
+ label: ReactNode;
19
+ icon?: ReactNode;
20
+ /** Trend chip text after the value, e.g. "+12%". */
21
+ trend?: ReactNode;
22
+ trendDirection?: "up" | "down";
23
+ tone?: "default" | "accent" | "success" | "warning";
24
+ /** Colored start edge. */
25
+ stripe?: boolean;
26
+ href?: string;
27
+ onClick?: () => void;
28
+ }
29
+
30
+ /** `.oc-stat-card`: compact KPI tile. */
31
+ export function StatCard({ value, label, icon, trend, trendDirection = "up", tone = "default", stripe, href, onClick, className, ...rest }: StatCardProps) {
32
+ const cls = cx("oc-stat-card", tone !== "default" && `oc-stat-card--${tone}`, stripe && "oc-stat-card--stripe", className);
33
+ // Spans only inside the body, so the markup is also valid inside a link or button.
34
+ const content = (
35
+ <>
36
+ {icon != null && <span className="oc-stat-card-icon" aria-hidden="true">{icon}</span>}
37
+ <span className="oc-stat-card-body">
38
+ <span className="oc-stat-card-value">
39
+ {value}
40
+ {trend != null && <span className={`oc-stat-card-trend oc-stat-card-trend--${trendDirection}`}>{trend}</span>}
41
+ </span>
42
+ <span className="oc-stat-card-label">{label}</span>
43
+ </span>
44
+ </>
45
+ );
46
+ if (href !== undefined) return <a className={cls} href={href} {...rest}>{content}</a>;
47
+ if (onClick) return <button className={cls} type="button" onClick={onClick} {...rest}>{content}</button>;
48
+ return <div className={cls} {...rest}>{content}</div>;
49
+ }
@@ -1,54 +1,54 @@
1
- import { forwardRef } from "react";
2
- import type { HTMLAttributes, ReactNode } from "react";
3
- import { cx } from "../utils";
4
-
5
- export interface StepperStep {
6
- label: ReactNode;
7
- /** Small text under the label, e.g. `2/4`. */
8
- meta?: ReactNode;
9
- }
10
-
11
- export interface StepperProps extends Omit<HTMLAttributes<HTMLOListElement>, "onChange"> {
12
- steps: StepperStep[];
13
- /** Index of the active step (0-based). Earlier steps are done, later ones disabled. */
14
- current: number;
15
- horizontal?: boolean;
16
- /** Called when a done step is clicked. */
17
- onStepChange?: (index: number) => void;
18
- }
19
-
20
- /** `<ol class="oc-stepper">`: done, active and upcoming steps. */
21
- export const Stepper = forwardRef<HTMLOListElement, StepperProps>(function Stepper(
22
- { steps, current, horizontal, onStepChange, className, ...rest },
23
- ref,
24
- ) {
25
- return (
26
- <ol ref={ref} className={cx("oc-stepper", horizontal && "oc-stepper--horizontal", className)} {...rest}>
27
- {steps.map((step, i) => {
28
- const done = i < current;
29
- const active = i === current;
30
- const label = <span className="oc-stepper-label">{step.label}</span>;
31
- return (
32
- <li key={i}>
33
- <button
34
- className={cx("oc-stepper-item", done && "oc-stepper-item--done", active && "oc-stepper-item--active")}
35
- type="button"
36
- aria-current={active ? "step" : undefined}
37
- disabled={i > current}
38
- onClick={() => onStepChange?.(i)}
39
- >
40
- {step.meta != null ? (
41
- <span>
42
- {label}
43
- <span className="oc-stepper-meta">{step.meta}</span>
44
- </span>
45
- ) : (
46
- label
47
- )}
48
- </button>
49
- </li>
50
- );
51
- })}
52
- </ol>
53
- );
54
- });
1
+ import { forwardRef } from "react";
2
+ import type { HTMLAttributes, ReactNode } from "react";
3
+ import { cx } from "../utils";
4
+
5
+ export interface StepperStep {
6
+ label: ReactNode;
7
+ /** Small text under the label, e.g. `2/4`. */
8
+ meta?: ReactNode;
9
+ }
10
+
11
+ export interface StepperProps extends Omit<HTMLAttributes<HTMLOListElement>, "onChange"> {
12
+ steps: StepperStep[];
13
+ /** Index of the active step (0-based). Earlier steps are done, later ones disabled. */
14
+ current: number;
15
+ horizontal?: boolean;
16
+ /** Called when a done step is clicked. */
17
+ onStepChange?: (index: number) => void;
18
+ }
19
+
20
+ /** `<ol class="oc-stepper">`: done, active and upcoming steps. */
21
+ export const Stepper = forwardRef<HTMLOListElement, StepperProps>(function Stepper(
22
+ { steps, current, horizontal, onStepChange, className, ...rest },
23
+ ref,
24
+ ) {
25
+ return (
26
+ <ol ref={ref} className={cx("oc-stepper", horizontal && "oc-stepper--horizontal", className)} {...rest}>
27
+ {steps.map((step, i) => {
28
+ const done = i < current;
29
+ const active = i === current;
30
+ const label = <span className="oc-stepper-label">{step.label}</span>;
31
+ return (
32
+ <li key={i}>
33
+ <button
34
+ className={cx("oc-stepper-item", done && "oc-stepper-item--done", active && "oc-stepper-item--active")}
35
+ type="button"
36
+ aria-current={active ? "step" : undefined}
37
+ disabled={i > current}
38
+ onClick={() => onStepChange?.(i)}
39
+ >
40
+ {step.meta != null ? (
41
+ <span>
42
+ {label}
43
+ <span className="oc-stepper-meta">{step.meta}</span>
44
+ </span>
45
+ ) : (
46
+ label
47
+ )}
48
+ </button>
49
+ </li>
50
+ );
51
+ })}
52
+ </ol>
53
+ );
54
+ });
@@ -1,18 +1,18 @@
1
- import { forwardRef } from "react";
2
- import type { InputHTMLAttributes } from "react";
3
- import { cx } from "../utils";
4
-
5
- export interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "role"> {
6
- /** Class for the wrapping label (`className` goes to the input). */
7
- labelClassName?: string;
8
- }
9
-
10
- /** `<label class="oc-switch"><input type="checkbox" role="switch">`. Works controlled (`checked`) or uncontrolled. */
11
- export const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch({ labelClassName, className, ...rest }, ref) {
12
- return (
13
- <label className={cx("oc-switch", labelClassName)}>
14
- <input ref={ref} type="checkbox" role="switch" className={className} {...rest} />
15
- <span className="oc-switch-track" />
16
- </label>
17
- );
18
- });
1
+ import { forwardRef } from "react";
2
+ import type { InputHTMLAttributes } from "react";
3
+ import { cx } from "../utils";
4
+
5
+ export interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type" | "role"> {
6
+ /** Class for the wrapping label (`className` goes to the input). */
7
+ labelClassName?: string;
8
+ }
9
+
10
+ /** `<label class="oc-switch"><input type="checkbox" role="switch">`. Works controlled (`checked`) or uncontrolled. */
11
+ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(function Switch({ labelClassName, className, ...rest }, ref) {
12
+ return (
13
+ <label className={cx("oc-switch", labelClassName)}>
14
+ <input ref={ref} type="checkbox" role="switch" className={className} {...rest} />
15
+ <span className="oc-switch-track" />
16
+ </label>
17
+ );
18
+ });
@@ -1,75 +1,75 @@
1
- import { forwardRef } from "react";
2
- import type { AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, ReactNode, TableHTMLAttributes, TdHTMLAttributes } from "react";
3
- import { cx } from "../utils";
4
-
5
- export interface TableProps extends TableHTMLAttributes<HTMLTableElement> {
6
- striped?: boolean;
7
- compact?: boolean;
8
- borderless?: boolean;
9
- sticky?: boolean;
10
- /** `<caption>` text. */
11
- caption?: ReactNode;
12
- /** Class for the `oc-table-wrap` scroll container. */
13
- wrapClassName?: string;
14
- }
15
-
16
- /** `div.oc-table-wrap > table.oc-table` */
17
- export const Table = forwardRef<HTMLTableElement, TableProps>(function Table(
18
- { striped, compact, borderless, sticky, caption, wrapClassName, className, children, ...rest },
19
- ref,
20
- ) {
21
- return (
22
- <div className={cx("oc-table-wrap", wrapClassName)}>
23
- <table
24
- ref={ref}
25
- className={cx(
26
- "oc-table",
27
- striped && "oc-table--striped",
28
- compact && "oc-table--compact",
29
- borderless && "oc-table--borderless",
30
- sticky && "oc-table--sticky",
31
- className,
32
- )}
33
- {...rest}
34
- >
35
- {caption != null && <caption>{caption}</caption>}
36
- {children}
37
- </table>
38
- </div>
39
- );
40
- });
41
-
42
- export interface TableSortProps extends AnchorHTMLAttributes<HTMLAnchorElement> {}
43
-
44
- /** `a.oc-table-sort` inside a `<th aria-sort="ascending|descending">`. */
45
- export const TableSort = forwardRef<HTMLAnchorElement, TableSortProps>(function TableSort({ className, ...rest }, ref) {
46
- return <a ref={ref} className={cx("oc-table-sort", className)} {...rest} />;
47
- });
48
-
49
- /** `td.oc-table-actions` */
50
- export function TableActions({ className, ...rest }: TdHTMLAttributes<HTMLTableCellElement>) {
51
- return <td className={cx("oc-table-actions", className)} {...rest} />;
52
- }
53
-
54
- type RowActionProps = {
55
- tone?: "default" | "destructive" | "primary" | "success";
56
- } & (
57
- | (AnchorHTMLAttributes<HTMLAnchorElement> & { href: string })
58
- | (ButtonHTMLAttributes<HTMLButtonElement> & { href?: undefined })
59
- );
60
-
61
- /** `.oc-table-row-action`: link (with `href`) or button. */
62
- export function TableRowAction({ tone = "default", className, ...props }: RowActionProps) {
63
- const cls = cx("oc-table-row-action", tone !== "default" && `oc-table-row-action--${tone}`, className);
64
- if (props.href !== undefined) return <a className={cls} {...(props as AnchorHTMLAttributes<HTMLAnchorElement>)} />;
65
- return <button type="button" className={cls} {...(props as ButtonHTMLAttributes<HTMLButtonElement>)} />;
66
- }
67
-
68
- /** Empty-state row: `<tr class="oc-table-empty"><td colspan>`; put an `<EmptyState>` inside. */
69
- export function TableEmpty({ colSpan, children, ...rest }: HTMLAttributes<HTMLTableRowElement> & { colSpan: number }) {
70
- return (
71
- <tr className="oc-table-empty" {...rest}>
72
- <td colSpan={colSpan}>{children}</td>
73
- </tr>
74
- );
75
- }
1
+ import { forwardRef } from "react";
2
+ import type { AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, ReactNode, TableHTMLAttributes, TdHTMLAttributes } from "react";
3
+ import { cx } from "../utils";
4
+
5
+ export interface TableProps extends TableHTMLAttributes<HTMLTableElement> {
6
+ striped?: boolean;
7
+ compact?: boolean;
8
+ borderless?: boolean;
9
+ sticky?: boolean;
10
+ /** `<caption>` text. */
11
+ caption?: ReactNode;
12
+ /** Class for the `oc-table-wrap` scroll container. */
13
+ wrapClassName?: string;
14
+ }
15
+
16
+ /** `div.oc-table-wrap > table.oc-table` */
17
+ export const Table = forwardRef<HTMLTableElement, TableProps>(function Table(
18
+ { striped, compact, borderless, sticky, caption, wrapClassName, className, children, ...rest },
19
+ ref,
20
+ ) {
21
+ return (
22
+ <div className={cx("oc-table-wrap", wrapClassName)}>
23
+ <table
24
+ ref={ref}
25
+ className={cx(
26
+ "oc-table",
27
+ striped && "oc-table--striped",
28
+ compact && "oc-table--compact",
29
+ borderless && "oc-table--borderless",
30
+ sticky && "oc-table--sticky",
31
+ className,
32
+ )}
33
+ {...rest}
34
+ >
35
+ {caption != null && <caption>{caption}</caption>}
36
+ {children}
37
+ </table>
38
+ </div>
39
+ );
40
+ });
41
+
42
+ export interface TableSortProps extends AnchorHTMLAttributes<HTMLAnchorElement> {}
43
+
44
+ /** `a.oc-table-sort` inside a `<th aria-sort="ascending|descending">`. */
45
+ export const TableSort = forwardRef<HTMLAnchorElement, TableSortProps>(function TableSort({ className, ...rest }, ref) {
46
+ return <a ref={ref} className={cx("oc-table-sort", className)} {...rest} />;
47
+ });
48
+
49
+ /** `td.oc-table-actions` */
50
+ export function TableActions({ className, ...rest }: TdHTMLAttributes<HTMLTableCellElement>) {
51
+ return <td className={cx("oc-table-actions", className)} {...rest} />;
52
+ }
53
+
54
+ type RowActionProps = {
55
+ tone?: "default" | "destructive" | "primary" | "success";
56
+ } & (
57
+ | (AnchorHTMLAttributes<HTMLAnchorElement> & { href: string })
58
+ | (ButtonHTMLAttributes<HTMLButtonElement> & { href?: undefined })
59
+ );
60
+
61
+ /** `.oc-table-row-action`: link (with `href`) or button. */
62
+ export function TableRowAction({ tone = "default", className, ...props }: RowActionProps) {
63
+ const cls = cx("oc-table-row-action", tone !== "default" && `oc-table-row-action--${tone}`, className);
64
+ if (props.href !== undefined) return <a className={cls} {...(props as AnchorHTMLAttributes<HTMLAnchorElement>)} />;
65
+ return <button type="button" className={cls} {...(props as ButtonHTMLAttributes<HTMLButtonElement>)} />;
66
+ }
67
+
68
+ /** Empty-state row: `<tr class="oc-table-empty"><td colspan>`; put an `<EmptyState>` inside. */
69
+ export function TableEmpty({ colSpan, children, ...rest }: HTMLAttributes<HTMLTableRowElement> & { colSpan: number }) {
70
+ return (
71
+ <tr className="oc-table-empty" {...rest}>
72
+ <td colSpan={colSpan}>{children}</td>
73
+ </tr>
74
+ );
75
+ }
@@ -1,54 +1,54 @@
1
- // File: packages/react/src/components/TableActions.tsx
2
- // Map: TableActionIcon (square icon action) -> TableActionsMenu (three dots trigger + popover menu)
3
- // The cell itself (`td.oc-table-actions`) is the existing `TableActions` in Table.tsx.
4
- // This file only adds the new parts, so the export names do not collide with it.
5
- import { forwardRef, useId } from "react";
6
- import type { AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, ReactNode } from "react";
7
- import { attrs, cx } from "../utils";
8
-
9
- export type TableActionTone = "default" | "primary" | "success" | "destructive";
10
-
11
- type IconActionProps = {
12
- /** Accessible name; also used as the hover title. */
13
- label: string;
14
- tone?: TableActionTone;
15
- children: ReactNode;
16
- } & (
17
- | (Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "children"> & { href: string })
18
- | (Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> & { href?: undefined })
19
- );
20
-
21
- /** `.oc-table-actions-icon`: a link (with `href`) or a button showing only an icon. */
22
- export function TableActionIcon({ label, tone = "default", className, children, ...props }: IconActionProps) {
23
- const cls = cx("oc-table-actions-icon", tone !== "default" && `oc-table-actions-icon--${tone}`, className);
24
- // aria-label gives the name to screen readers; title shows it on hover.
25
- const common = { className: cls, "aria-label": label, title: label };
26
- if (props.href !== undefined) {
27
- return <a {...common} {...(props as AnchorHTMLAttributes<HTMLAnchorElement>)}>{children}</a>;
28
- }
29
- return <button type="button" {...common} {...(props as ButtonHTMLAttributes<HTMLButtonElement>)}>{children}</button>;
30
- }
31
-
32
- export interface TableActionsMenuProps extends HTMLAttributes<HTMLDivElement> {
33
- /** Accessible name of the three dots trigger, e.g. "Actions for Ada". */
34
- label: string;
35
- /** Menu items: `<a class="oc-dropdown-item">`, `<button class="oc-dropdown-item">`, separators. */
36
- children: ReactNode;
37
- }
38
-
39
- /** `.oc-table-actions-more` trigger + `.oc-dropdown-menu[popover]`; the browser opens and closes it. */
40
- export const TableActionsMenu = forwardRef<HTMLDivElement, TableActionsMenuProps>(function TableActionsMenu(
41
- { label, id, className, children, ...rest },
42
- ref,
43
- ) {
44
- const auto = useId();
45
- const menuId = id ?? `oc-table-actions-menu-${auto.replace(/:/g, "")}`;
46
- return (
47
- <>
48
- <button className="oc-table-actions-more" type="button" aria-label={label} {...attrs({ popovertarget: menuId })} />
49
- <div ref={ref} id={menuId} className={cx("oc-dropdown-menu", className)} {...attrs({ popover: "" })} {...rest}>
50
- {children}
51
- </div>
52
- </>
53
- );
54
- });
1
+ // File: packages/react/src/components/TableActions.tsx
2
+ // Map: TableActionIcon (square icon action) -> TableActionsMenu (three dots trigger + popover menu)
3
+ // The cell itself (`td.oc-table-actions`) is the existing `TableActions` in Table.tsx.
4
+ // This file only adds the new parts, so the export names do not collide with it.
5
+ import { forwardRef, useId } from "react";
6
+ import type { AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, ReactNode } from "react";
7
+ import { attrs, cx } from "../utils";
8
+
9
+ export type TableActionTone = "default" | "primary" | "success" | "destructive";
10
+
11
+ type IconActionProps = {
12
+ /** Accessible name; also used as the hover title. */
13
+ label: string;
14
+ tone?: TableActionTone;
15
+ children: ReactNode;
16
+ } & (
17
+ | (Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "children"> & { href: string })
18
+ | (Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children"> & { href?: undefined })
19
+ );
20
+
21
+ /** `.oc-table-actions-icon`: a link (with `href`) or a button showing only an icon. */
22
+ export function TableActionIcon({ label, tone = "default", className, children, ...props }: IconActionProps) {
23
+ const cls = cx("oc-table-actions-icon", tone !== "default" && `oc-table-actions-icon--${tone}`, className);
24
+ // aria-label gives the name to screen readers; title shows it on hover.
25
+ const common = { className: cls, "aria-label": label, title: label };
26
+ if (props.href !== undefined) {
27
+ return <a {...common} {...(props as AnchorHTMLAttributes<HTMLAnchorElement>)}>{children}</a>;
28
+ }
29
+ return <button type="button" {...common} {...(props as ButtonHTMLAttributes<HTMLButtonElement>)}>{children}</button>;
30
+ }
31
+
32
+ export interface TableActionsMenuProps extends HTMLAttributes<HTMLDivElement> {
33
+ /** Accessible name of the three dots trigger, e.g. "Actions for Ada". */
34
+ label: string;
35
+ /** Menu items: `<a class="oc-dropdown-item">`, `<button class="oc-dropdown-item">`, separators. */
36
+ children: ReactNode;
37
+ }
38
+
39
+ /** `.oc-table-actions-more` trigger + `.oc-dropdown-menu[popover]`; the browser opens and closes it. */
40
+ export const TableActionsMenu = forwardRef<HTMLDivElement, TableActionsMenuProps>(function TableActionsMenu(
41
+ { label, id, className, children, ...rest },
42
+ ref,
43
+ ) {
44
+ const auto = useId();
45
+ const menuId = id ?? `oc-table-actions-menu-${auto.replace(/:/g, "")}`;
46
+ return (
47
+ <>
48
+ <button className="oc-table-actions-more" type="button" aria-label={label} {...attrs({ popovertarget: menuId })} />
49
+ <div ref={ref} id={menuId} className={cx("oc-dropdown-menu", className)} {...attrs({ popover: "" })} {...rest}>
50
+ {children}
51
+ </div>
52
+ </>
53
+ );
54
+ });
@@ -1,61 +1,61 @@
1
- // File: packages/react/src/components/TableCompact.tsx
2
- // Map: TableCompact = wrapper div -> table.oc-table (thead from columns, tbody from rows, tfoot from footer) or your own children
3
- // Pass `columns` + `rows` for a quick table, or put your own <table class="oc-table"> as children.
4
- import { forwardRef } from "react";
5
- import type { HTMLAttributes, ReactNode } from "react";
6
- import { cx } from "../utils";
7
-
8
- export interface TableCompactColumn {
9
- key: string;
10
- label: ReactNode;
11
- /** Right aligned, tabular figures (`data-numeric`). */
12
- numeric?: boolean;
13
- /** The cell may wrap (`data-wrap`). */
14
- wrap?: boolean;
15
- }
16
-
17
- export interface TableCompactProps extends HTMLAttributes<HTMLDivElement> {
18
- columns?: TableCompactColumn[];
19
- rows?: Array<Record<string, ReactNode>>;
20
- /** Total row: one value per column key (missing keys stay empty). */
21
- footer?: Record<string, ReactNode>;
22
- bordered?: boolean;
23
- plain?: boolean;
24
- }
25
-
26
- /** Cell attributes from the column settings. */
27
- const cellAttrs = (c: TableCompactColumn) => ({
28
- "data-numeric": c.numeric ? "" : undefined,
29
- "data-wrap": c.wrap ? "" : undefined,
30
- });
31
-
32
- /** `.oc-table-compact`: small striped table for inside cards. */
33
- export const TableCompact = forwardRef<HTMLDivElement, TableCompactProps>(function TableCompact(
34
- { columns, rows = [], footer, bordered, plain, className, children, ...rest },
35
- ref,
36
- ) {
37
- const cls = cx("oc-table-compact", bordered && "oc-table-compact--bordered", plain && "oc-table-compact--plain", className);
38
- return (
39
- <div ref={ref} className={cls} {...rest}>
40
- {columns ? (
41
- <table className="oc-table">
42
- <thead>
43
- <tr>{columns.map((c) => <th key={c.key} {...cellAttrs(c)}>{c.label}</th>)}</tr>
44
- </thead>
45
- <tbody>
46
- {rows.map((row, i) => (
47
- <tr key={i}>{columns.map((c) => <td key={c.key} {...cellAttrs(c)}>{row[c.key]}</td>)}</tr>
48
- ))}
49
- </tbody>
50
- {footer && (
51
- <tfoot>
52
- <tr>{columns.map((c) => <td key={c.key} {...cellAttrs(c)}>{footer[c.key]}</td>)}</tr>
53
- </tfoot>
54
- )}
55
- </table>
56
- ) : (
57
- children
58
- )}
59
- </div>
60
- );
61
- });
1
+ // File: packages/react/src/components/TableCompact.tsx
2
+ // Map: TableCompact = wrapper div -> table.oc-table (thead from columns, tbody from rows, tfoot from footer) or your own children
3
+ // Pass `columns` + `rows` for a quick table, or put your own <table class="oc-table"> as children.
4
+ import { forwardRef } from "react";
5
+ import type { HTMLAttributes, ReactNode } from "react";
6
+ import { cx } from "../utils";
7
+
8
+ export interface TableCompactColumn {
9
+ key: string;
10
+ label: ReactNode;
11
+ /** Right aligned, tabular figures (`data-numeric`). */
12
+ numeric?: boolean;
13
+ /** The cell may wrap (`data-wrap`). */
14
+ wrap?: boolean;
15
+ }
16
+
17
+ export interface TableCompactProps extends HTMLAttributes<HTMLDivElement> {
18
+ columns?: TableCompactColumn[];
19
+ rows?: Array<Record<string, ReactNode>>;
20
+ /** Total row: one value per column key (missing keys stay empty). */
21
+ footer?: Record<string, ReactNode>;
22
+ bordered?: boolean;
23
+ plain?: boolean;
24
+ }
25
+
26
+ /** Cell attributes from the column settings. */
27
+ const cellAttrs = (c: TableCompactColumn) => ({
28
+ "data-numeric": c.numeric ? "" : undefined,
29
+ "data-wrap": c.wrap ? "" : undefined,
30
+ });
31
+
32
+ /** `.oc-table-compact`: small striped table for inside cards. */
33
+ export const TableCompact = forwardRef<HTMLDivElement, TableCompactProps>(function TableCompact(
34
+ { columns, rows = [], footer, bordered, plain, className, children, ...rest },
35
+ ref,
36
+ ) {
37
+ const cls = cx("oc-table-compact", bordered && "oc-table-compact--bordered", plain && "oc-table-compact--plain", className);
38
+ return (
39
+ <div ref={ref} className={cls} {...rest}>
40
+ {columns ? (
41
+ <table className="oc-table">
42
+ <thead>
43
+ <tr>{columns.map((c) => <th key={c.key} {...cellAttrs(c)}>{c.label}</th>)}</tr>
44
+ </thead>
45
+ <tbody>
46
+ {rows.map((row, i) => (
47
+ <tr key={i}>{columns.map((c) => <td key={c.key} {...cellAttrs(c)}>{row[c.key]}</td>)}</tr>
48
+ ))}
49
+ </tbody>
50
+ {footer && (
51
+ <tfoot>
52
+ <tr>{columns.map((c) => <td key={c.key} {...cellAttrs(c)}>{footer[c.key]}</td>)}</tr>
53
+ </tfoot>
54
+ )}
55
+ </table>
56
+ ) : (
57
+ children
58
+ )}
59
+ </div>
60
+ );
61
+ });