@robr0/design-system 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 (39) hide show
  1. package/README.md +6 -4
  2. package/components/Breadcrumb/Breadcrumb.css +9 -1
  3. package/components/Button/Button.d.ts +32 -16
  4. package/components/Button/Button.js +66 -58
  5. package/components/Card/Card.d.ts +17 -5
  6. package/components/Card/Card.js +101 -80
  7. package/components/Checkbox/Checkbox.d.ts +24 -12
  8. package/components/Checkbox/Checkbox.js +99 -85
  9. package/components/Combobox/Combobox.d.ts +19 -7
  10. package/components/Combobox/Combobox.js +18 -9
  11. package/components/DateInput/DateInput.d.ts +18 -21
  12. package/components/DateInput/DateInput.js +71 -63
  13. package/components/DatePicker/DatePicker.d.ts +9 -2
  14. package/components/DatePicker/DatePicker.js +127 -129
  15. package/components/Dialog/Dialog.d.ts +15 -4
  16. package/components/Dialog/Dialog.js +133 -116
  17. package/components/Drawer/Drawer.d.ts +15 -4
  18. package/components/Drawer/Drawer.js +133 -119
  19. package/components/Dropdown/Dropdown.d.ts +24 -8
  20. package/components/Dropdown/Dropdown.js +226 -186
  21. package/components/FileInput/FileInput.d.ts +13 -17
  22. package/components/FileInput/FileInput.js +177 -158
  23. package/components/Input/Input.d.ts +23 -22
  24. package/components/Input/Input.js +87 -65
  25. package/components/RadioButton/RadioButton.d.ts +26 -13
  26. package/components/RadioButton/RadioButton.js +95 -70
  27. package/components/SelectionCard/SelectionCard.d.ts +10 -4
  28. package/components/SelectionCard/SelectionCard.js +72 -56
  29. package/components/Slider/Slider.d.ts +19 -10
  30. package/components/Slider/Slider.js +50 -40
  31. package/components/Table/Table.d.ts +10 -2
  32. package/components/Table/Table.js +58 -58
  33. package/components/Textarea/Textarea.d.ts +21 -22
  34. package/components/Textarea/Textarea.js +77 -68
  35. package/components/ToggleGroup/ToggleGroup.d.ts +18 -8
  36. package/components/ToggleGroup/ToggleGroup.js +61 -44
  37. package/components/ToggleSwitch/ToggleSwitch.d.ts +17 -9
  38. package/components/ToggleSwitch/ToggleSwitch.js +57 -44
  39. package/package.json +1 -1
@@ -1,76 +1,101 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import "react";
2
+ import React from "react";
3
3
  import "./RadioButton.css";
4
- const RadioButton = ({
5
- label,
6
- checked = false,
7
- disabled = false,
8
- value = "",
9
- onChange,
10
- className = "",
11
- ariaLabel
12
- }) => {
13
- const baseClass = "ds-radio";
14
- const checkedClass = checked ? `${baseClass}--checked` : "";
15
- const disabledClass = disabled ? `${baseClass}--disabled` : "";
16
- const classes = [baseClass, checkedClass, disabledClass, className].filter(Boolean).join(" ");
17
- const handleClick = () => {
18
- if (!disabled && onChange) {
19
- onChange(value);
20
- }
21
- };
22
- const handleKeyDown = (e) => {
23
- if (e.key === " " || e.key === "Enter") {
24
- e.preventDefault();
25
- handleClick();
26
- }
27
- };
28
- return /* @__PURE__ */ jsxs(
29
- "div",
30
- {
31
- className: classes,
32
- onClick: handleClick,
33
- onKeyDown: handleKeyDown,
34
- role: "radio",
35
- "aria-checked": checked,
36
- "aria-disabled": disabled,
37
- "aria-label": ariaLabel || label,
38
- tabIndex: disabled ? -1 : 0,
39
- children: [
40
- /* @__PURE__ */ jsx("div", { className: `${baseClass}__circle`, children: /* @__PURE__ */ jsx("div", { className: `${baseClass}__dot` }) }),
41
- label && /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: label })
42
- ]
43
- }
44
- );
45
- };
46
- const RadioGroup = ({
47
- label,
48
- value,
49
- name,
50
- options,
51
- direction = "vertical",
52
- onChange,
53
- className = ""
54
- }) => {
55
- const baseClass = "ds-radio-group";
56
- const directionClass = `${baseClass}--${direction}`;
57
- const classes = [baseClass, directionClass, className].filter(Boolean).join(" ");
58
- return /* @__PURE__ */ jsxs("div", { className: classes, role: "radiogroup", "aria-label": label, children: [
59
- label && /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: label }),
60
- /* @__PURE__ */ jsx("div", { className: `${baseClass}__options`, children: options.map((option) => /* @__PURE__ */ jsx(
61
- RadioButton,
4
+ const RadioButton = React.forwardRef(
5
+ ({
6
+ label,
7
+ checked = false,
8
+ disabled = false,
9
+ value = "",
10
+ onValueChange,
11
+ onChange,
12
+ className = "",
13
+ ariaLabel,
14
+ name: _name,
15
+ onClick,
16
+ onKeyDown,
17
+ ...rest
18
+ }, ref) => {
19
+ const baseClass = "ds-radio";
20
+ const classes = [
21
+ baseClass,
22
+ checked ? `${baseClass}--checked` : "",
23
+ disabled ? `${baseClass}--disabled` : "",
24
+ className
25
+ ].filter(Boolean).join(" ");
26
+ const select = () => {
27
+ if (disabled) return;
28
+ onValueChange?.(value);
29
+ onChange?.(value);
30
+ };
31
+ const handleClick = (e) => {
32
+ onClick?.(e);
33
+ select();
34
+ };
35
+ const handleKeyDown = (e) => {
36
+ onKeyDown?.(e);
37
+ if (e.key === " " || e.key === "Enter") {
38
+ e.preventDefault();
39
+ select();
40
+ }
41
+ };
42
+ return /* @__PURE__ */ jsxs(
43
+ "div",
62
44
  {
63
- label: option.label,
64
- value: option.value,
65
- name,
66
- checked: value === option.value,
67
- disabled: option.disabled,
68
- onChange
69
- },
70
- option.value
71
- )) })
72
- ] });
73
- };
45
+ ...rest,
46
+ ref,
47
+ className: classes,
48
+ onClick: handleClick,
49
+ onKeyDown: handleKeyDown,
50
+ role: "radio",
51
+ "aria-checked": checked,
52
+ "aria-disabled": disabled,
53
+ "aria-label": ariaLabel || rest["aria-label"] || label,
54
+ tabIndex: disabled ? -1 : 0,
55
+ children: [
56
+ /* @__PURE__ */ jsx("div", { className: `${baseClass}__circle`, children: /* @__PURE__ */ jsx("div", { className: `${baseClass}__dot` }) }),
57
+ label && /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: label })
58
+ ]
59
+ }
60
+ );
61
+ }
62
+ );
63
+ RadioButton.displayName = "RadioButton";
64
+ const RadioGroup = React.forwardRef(
65
+ ({
66
+ label,
67
+ value,
68
+ name: _name,
69
+ options,
70
+ direction = "vertical",
71
+ onValueChange,
72
+ onChange,
73
+ className = "",
74
+ ...rest
75
+ }, ref) => {
76
+ const baseClass = "ds-radio-group";
77
+ const classes = [baseClass, `${baseClass}--${direction}`, className].filter(Boolean).join(" ");
78
+ const handleSelect = (next) => {
79
+ onValueChange?.(next);
80
+ onChange?.(next);
81
+ };
82
+ return /* @__PURE__ */ jsxs("div", { ...rest, ref, className: classes, role: "radiogroup", "aria-label": label, children: [
83
+ label && /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: label }),
84
+ /* @__PURE__ */ jsx("div", { className: `${baseClass}__options`, children: options.map((option) => /* @__PURE__ */ jsx(
85
+ RadioButton,
86
+ {
87
+ label: option.label,
88
+ value: option.value,
89
+ checked: value === option.value,
90
+ disabled: option.disabled,
91
+ onValueChange: handleSelect
92
+ },
93
+ option.value
94
+ )) })
95
+ ] });
96
+ }
97
+ );
98
+ RadioGroup.displayName = "RadioGroup";
74
99
  export {
75
100
  RadioButton,
76
101
  RadioGroup
@@ -9,18 +9,24 @@ export interface SelectionCardOption {
9
9
  /** Whether this option is disabled */
10
10
  disabled?: boolean;
11
11
  }
12
- export interface SelectionCardProps {
12
+ /** Props owned by SelectionCard itself — everything else falls through to the group. */
13
+ type SelectionCardOwnProps = {
13
14
  /** Selection mode — radio (single), checkbox (multi), or toggle (each card is an on/off switch) */
14
15
  mode?: 'radio' | 'checkbox' | 'toggle';
15
16
  /** Available options */
16
17
  options: SelectionCardOption[];
17
18
  /** Currently selected value(s) — string for radio, string[] for checkbox */
18
19
  value?: string | string[];
19
- /** Callback when selection changes returns string for radio, string[] for checkbox */
20
- onChange?: (value: string | string[]) => void;
20
+ /** Called with the next selection — a string in radio mode, an array otherwise */
21
+ onValueChange?: (value: string | string[]) => void;
21
22
  /** Group name (used for aria-label on the group) */
22
23
  name?: string;
23
24
  /** Additional CSS classes */
24
25
  className?: string;
26
+ /** @deprecated Use `onValueChange` instead. */
27
+ onChange?: (value: string | string[]) => void;
28
+ };
29
+ export interface SelectionCardProps extends SelectionCardOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof SelectionCardOwnProps> {
25
30
  }
26
- export declare const SelectionCard: ({ mode, options, value, onChange, name, className, }: SelectionCardProps) => React.JSX.Element;
31
+ export declare const SelectionCard: React.ForwardRefExoticComponent<SelectionCardProps & React.RefAttributes<HTMLDivElement>>;
32
+ export {};
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import "react";
2
+ import React from "react";
3
3
  import "./SelectionCard.css";
4
4
  const CheckIcon = () => /* @__PURE__ */ jsx(
5
5
  "svg",
@@ -22,64 +22,80 @@ const CheckIcon = () => /* @__PURE__ */ jsx(
22
22
  )
23
23
  }
24
24
  );
25
- const SelectionCard = ({
26
- mode = "radio",
27
- options,
28
- value,
29
- onChange,
30
- name,
31
- className = ""
32
- }) => {
33
- const baseClass = "ds-selection-card";
34
- const selectedValues = Array.isArray(value) ? value : value !== void 0 ? [value] : [];
35
- const isSelected = (optionValue) => selectedValues.includes(optionValue);
36
- const handleSelect = (option) => {
37
- if (option.disabled || !onChange) return;
38
- if (mode === "radio") {
39
- onChange(option.value);
40
- } else {
41
- const newValues = isSelected(option.value) ? selectedValues.filter((v) => v !== option.value) : [...selectedValues, option.value];
42
- onChange(newValues);
43
- }
44
- };
45
- const handleKeyDown = (e, option) => {
46
- if (e.key === " " || e.key === "Enter") {
47
- e.preventDefault();
48
- handleSelect(option);
49
- }
50
- };
51
- const groupRole = mode === "radio" ? "radiogroup" : "group";
52
- const itemRole = mode === "radio" ? "radio" : mode === "toggle" ? "switch" : "checkbox";
53
- const groupClasses = [`${baseClass}-group`, className].filter(Boolean).join(" ");
54
- return /* @__PURE__ */ jsx("div", { className: groupClasses, role: groupRole, "aria-label": name, children: options.map((option) => {
55
- const selected = isSelected(option.value);
56
- const cardClasses = [
57
- baseClass,
58
- selected ? `${baseClass}--selected` : "",
59
- option.disabled ? `${baseClass}--disabled` : ""
60
- ].filter(Boolean).join(" ");
61
- return /* @__PURE__ */ jsxs(
25
+ const SelectionCard = React.forwardRef(
26
+ ({ mode = "radio", options, value, onValueChange, onChange, name, className = "", ...rest }, ref) => {
27
+ const baseClass = "ds-selection-card";
28
+ const selectedValues = Array.isArray(value) ? value : value !== void 0 ? [value] : [];
29
+ const isSelected = (optionValue) => selectedValues.includes(optionValue);
30
+ const handleSelect = (option) => {
31
+ if (option.disabled) return;
32
+ const next = mode === "radio" ? option.value : isSelected(option.value) ? selectedValues.filter((v) => v !== option.value) : [...selectedValues, option.value];
33
+ onValueChange?.(next);
34
+ onChange?.(next);
35
+ };
36
+ const handleKeyDown = (e, option) => {
37
+ if (e.key === " " || e.key === "Enter") {
38
+ e.preventDefault();
39
+ handleSelect(option);
40
+ }
41
+ };
42
+ const groupRole = mode === "radio" ? "radiogroup" : "group";
43
+ const itemRole = mode === "radio" ? "radio" : mode === "toggle" ? "switch" : "checkbox";
44
+ const groupClasses = [`${baseClass}-group`, className].filter(Boolean).join(" ");
45
+ return /* @__PURE__ */ jsx(
62
46
  "div",
63
47
  {
64
- className: cardClasses,
65
- role: itemRole,
66
- "aria-checked": selected,
67
- "aria-disabled": option.disabled,
68
- tabIndex: option.disabled ? -1 : 0,
69
- onClick: () => handleSelect(option),
70
- onKeyDown: (e) => handleKeyDown(e, option),
71
- children: [
72
- /* @__PURE__ */ jsxs("div", { className: `${baseClass}__content`, children: [
73
- /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: option.label }),
74
- option.description && /* @__PURE__ */ jsx("span", { className: `${baseClass}__description`, children: option.description })
75
- ] }),
76
- /* @__PURE__ */ jsx("div", { className: `${baseClass}__indicator`, children: mode === "radio" ? /* @__PURE__ */ jsx("div", { className: `${baseClass}__radio`, children: /* @__PURE__ */ jsx("div", { className: `${baseClass}__radio-dot` }) }) : mode === "toggle" ? /* @__PURE__ */ jsx("div", { className: `${baseClass}__toggle ${selected ? "" : `${baseClass}__toggle--off`}`, children: /* @__PURE__ */ jsx("div", { className: `${baseClass}__toggle-thumb`, children: /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded ds-selection-card__toggle-icon", "aria-hidden": "true", children: "check" }) }) }) : /* @__PURE__ */ jsx("div", { className: `${baseClass}__checkbox`, children: /* @__PURE__ */ jsx(CheckIcon, {}) }) })
77
- ]
78
- },
79
- option.value
48
+ ...rest,
49
+ ref,
50
+ className: groupClasses,
51
+ role: groupRole,
52
+ "aria-label": name || rest["aria-label"],
53
+ children: options.map((option) => {
54
+ const selected = isSelected(option.value);
55
+ const cardClasses = [
56
+ baseClass,
57
+ selected ? `${baseClass}--selected` : "",
58
+ option.disabled ? `${baseClass}--disabled` : ""
59
+ ].filter(Boolean).join(" ");
60
+ return /* @__PURE__ */ jsxs(
61
+ "div",
62
+ {
63
+ className: cardClasses,
64
+ role: itemRole,
65
+ "aria-checked": selected,
66
+ "aria-disabled": option.disabled,
67
+ tabIndex: option.disabled ? -1 : 0,
68
+ onClick: () => handleSelect(option),
69
+ onKeyDown: (e) => handleKeyDown(e, option),
70
+ children: [
71
+ /* @__PURE__ */ jsxs("div", { className: `${baseClass}__content`, children: [
72
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: option.label }),
73
+ option.description && /* @__PURE__ */ jsx("span", { className: `${baseClass}__description`, children: option.description })
74
+ ] }),
75
+ /* @__PURE__ */ jsx("div", { className: `${baseClass}__indicator`, children: mode === "radio" ? /* @__PURE__ */ jsx("div", { className: `${baseClass}__radio`, children: /* @__PURE__ */ jsx("div", { className: `${baseClass}__radio-dot` }) }) : mode === "toggle" ? /* @__PURE__ */ jsx(
76
+ "div",
77
+ {
78
+ className: `${baseClass}__toggle ${selected ? "" : `${baseClass}__toggle--off`}`,
79
+ children: /* @__PURE__ */ jsx("div", { className: `${baseClass}__toggle-thumb`, children: /* @__PURE__ */ jsx(
80
+ "span",
81
+ {
82
+ className: "material-symbols-rounded ds-selection-card__toggle-icon",
83
+ "aria-hidden": "true",
84
+ children: "check"
85
+ }
86
+ ) })
87
+ }
88
+ ) : /* @__PURE__ */ jsx("div", { className: `${baseClass}__checkbox`, children: /* @__PURE__ */ jsx(CheckIcon, {}) }) })
89
+ ]
90
+ },
91
+ option.value
92
+ );
93
+ })
94
+ }
80
95
  );
81
- }) });
82
- };
96
+ }
97
+ );
98
+ SelectionCard.displayName = "SelectionCard";
83
99
  export {
84
100
  SelectionCard
85
101
  };
@@ -1,5 +1,6 @@
1
1
  import { default as React } from 'react';
2
- export interface SliderProps {
2
+ /** Props owned by Slider itself — everything else falls through to the <input type="range">. */
3
+ type SliderOwnProps = {
3
4
  /** Current value */
4
5
  value?: number;
5
6
  /** Minimum value */
@@ -8,18 +9,26 @@ export interface SliderProps {
8
9
  max?: number;
9
10
  /** Step increment */
10
11
  step?: number;
11
- /** Disabled state */
12
- disabled?: boolean;
13
- /** Size */
12
+ /** Component size (not the native character-width `size` attribute) */
14
13
  size?: 'default' | 'compact';
15
- /** Change handler */
16
- onChange?: (value: number) => void;
17
- /** Accessible label */
18
- ariaLabel?: string;
19
- /** Additional CSS classes */
14
+ /**
15
+ * Convenience callback receiving the numeric value directly.
16
+ * Fires alongside `onChange`, which keeps the standard React event signature
17
+ * so form libraries work unmodified.
18
+ */
19
+ onValueChange?: (value: number) => void;
20
+ /** Additional CSS classes — applied to the wrapper, not the <input> */
20
21
  className?: string;
22
+ /** @deprecated Pass the native `aria-label` attribute instead. */
23
+ ariaLabel?: string;
24
+ };
25
+ export interface SliderProps extends SliderOwnProps, Omit<React.ComponentPropsWithoutRef<'input'>, keyof SliderOwnProps | 'type'> {
21
26
  }
22
27
  /**
23
28
  * Slider allows selecting a value from within a given range.
29
+ *
30
+ * Forwards a ref to the underlying `<input type="range">` and spreads
31
+ * unrecognised props onto it.
24
32
  */
25
- export declare const Slider: ({ value, min, max, step, disabled, size, onChange, ariaLabel, className, }: SliderProps) => React.JSX.Element;
33
+ export declare const Slider: React.ForwardRefExoticComponent<SliderProps & React.RefAttributes<HTMLInputElement>>;
34
+ export {};
@@ -1,46 +1,56 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import "react";
2
+ import React from "react";
3
3
  import "./Slider.css";
4
- const Slider = ({
5
- value = 50,
6
- min = 0,
7
- max = 100,
8
- step = 1,
9
- disabled = false,
10
- size = "default",
11
- onChange,
12
- ariaLabel = "Slider",
13
- className = ""
14
- }) => {
15
- const baseClass = "ds-slider";
16
- const classes = [
17
- baseClass,
18
- `${baseClass}--${size}`,
19
- disabled ? `${baseClass}--disabled` : "",
20
- className
21
- ].filter(Boolean).join(" ");
22
- const percentage = (value - min) / (max - min) * 100;
23
- const handleChange = (e) => {
24
- onChange?.(Number(e.target.value));
25
- };
26
- return /* @__PURE__ */ jsx("div", { className: classes, children: /* @__PURE__ */ jsx(
27
- "input",
28
- {
29
- type: "range",
30
- className: `${baseClass}__input`,
31
- value,
32
- min,
33
- max,
34
- step,
35
- disabled,
36
- onChange: handleChange,
37
- "aria-label": ariaLabel,
38
- style: {
39
- background: `linear-gradient(to right, var(--color-action-primary-bg) ${percentage}%, var(--color-bg-container-secondary) ${percentage}%)`
4
+ const Slider = React.forwardRef(
5
+ ({
6
+ value = 50,
7
+ min = 0,
8
+ max = 100,
9
+ step = 1,
10
+ disabled = false,
11
+ size = "default",
12
+ onChange,
13
+ onValueChange,
14
+ ariaLabel = "Slider",
15
+ className = "",
16
+ style,
17
+ ...rest
18
+ }, ref) => {
19
+ const baseClass = "ds-slider";
20
+ const classes = [
21
+ baseClass,
22
+ `${baseClass}--${size}`,
23
+ disabled ? `${baseClass}--disabled` : "",
24
+ className
25
+ ].filter(Boolean).join(" ");
26
+ const percentage = (value - min) / (max - min) * 100;
27
+ const handleChange = (e) => {
28
+ onChange?.(e);
29
+ onValueChange?.(Number(e.target.value));
30
+ };
31
+ return /* @__PURE__ */ jsx("div", { className: classes, children: /* @__PURE__ */ jsx(
32
+ "input",
33
+ {
34
+ ...rest,
35
+ ref,
36
+ type: "range",
37
+ className: `${baseClass}__input`,
38
+ value,
39
+ min,
40
+ max,
41
+ step,
42
+ disabled,
43
+ onChange: handleChange,
44
+ "aria-label": ariaLabel || rest["aria-label"],
45
+ style: {
46
+ background: `linear-gradient(to right, var(--color-action-primary-bg) ${percentage}%, var(--color-bg-container-secondary) ${percentage}%)`,
47
+ ...style
48
+ }
40
49
  }
41
- }
42
- ) });
43
- };
50
+ ) });
51
+ }
52
+ );
53
+ Slider.displayName = "Slider";
44
54
  export {
45
55
  Slider
46
56
  };
@@ -15,7 +15,8 @@ export interface TableRow {
15
15
  /** Cell values keyed by column key — each accepts any React node */
16
16
  cells: Record<string, React.ReactNode>;
17
17
  }
18
- export interface TableProps {
18
+ /** Props owned by Table itself — everything else falls through to the <table>. */
19
+ type TableOwnProps = {
19
20
  /** Column definitions */
20
21
  columns: TableColumn[];
21
22
  /** Row data */
@@ -36,10 +37,17 @@ export interface TableProps {
36
37
  captionHidden?: boolean;
37
38
  /** Additional CSS classes */
38
39
  className?: string;
40
+ };
41
+ export interface TableProps extends TableOwnProps, Omit<React.ComponentPropsWithoutRef<'table'>, keyof TableOwnProps> {
39
42
  }
40
43
  /**
41
44
  * Table component from Figma design system.
42
45
  * Data table with flexible cell content — supports text, icons,
43
46
  * inputs, buttons, and any other React nodes inside cells.
47
+ *
48
+ * Forwards a ref to the `<table>` element and spreads unrecognised props onto
49
+ * it. When `bordered`, the table is wrapped in a container div — the ref and
50
+ * spread props still target the inner `<table>`.
44
51
  */
45
- export declare const Table: ({ columns, rows, size, striped, bordered, caption, captionHidden, className, }: TableProps) => React.JSX.Element;
52
+ export declare const Table: React.ForwardRefExoticComponent<TableProps & React.RefAttributes<HTMLTableElement>>;
53
+ export {};
@@ -1,65 +1,65 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import "react";
2
+ import React from "react";
3
3
  import "./Table.css";
4
- const Table = ({
5
- columns,
6
- rows,
7
- size = "default",
8
- striped = false,
9
- bordered = false,
10
- caption,
11
- captionHidden = false,
12
- className = ""
13
- }) => {
14
- const baseClass = "ds-table";
15
- const sizeClass = `${baseClass}--${size}`;
16
- const stripedClass = striped ? `${baseClass}--striped` : "";
17
- const borderedClass = bordered ? `${baseClass}--bordered` : "";
18
- const classes = [baseClass, sizeClass, stripedClass, borderedClass, className].filter(Boolean).join(" ");
19
- const table = /* @__PURE__ */ jsxs("table", { className: classes, children: [
20
- caption && /* @__PURE__ */ jsx(
21
- "caption",
22
- {
23
- className: captionHidden ? `${baseClass}__caption--hidden` : `${baseClass}__caption`,
24
- children: caption
25
- }
26
- ),
27
- /* @__PURE__ */ jsx("thead", { className: `${baseClass}__head`, children: /* @__PURE__ */ jsx("tr", { className: `${baseClass}__row ${baseClass}__row--header`, children: columns.map((col) => /* @__PURE__ */ jsx(
28
- "th",
29
- {
30
- className: `${baseClass}__header-cell`,
31
- scope: "col",
32
- style: {
33
- width: col.width,
34
- textAlign: col.align || "left"
4
+ const Table = React.forwardRef(
5
+ ({
6
+ columns,
7
+ rows,
8
+ size = "default",
9
+ striped = false,
10
+ bordered = false,
11
+ caption,
12
+ captionHidden = false,
13
+ className = "",
14
+ ...rest
15
+ }, ref) => {
16
+ const baseClass = "ds-table";
17
+ const classes = [
18
+ baseClass,
19
+ `${baseClass}--${size}`,
20
+ striped ? `${baseClass}--striped` : "",
21
+ bordered ? `${baseClass}--bordered` : "",
22
+ className
23
+ ].filter(Boolean).join(" ");
24
+ const table = /* @__PURE__ */ jsxs("table", { ...rest, ref, className: classes, children: [
25
+ caption && /* @__PURE__ */ jsx(
26
+ "caption",
27
+ {
28
+ className: captionHidden ? `${baseClass}__caption--hidden` : `${baseClass}__caption`,
29
+ children: caption
30
+ }
31
+ ),
32
+ /* @__PURE__ */ jsx("thead", { className: `${baseClass}__head`, children: /* @__PURE__ */ jsx("tr", { className: `${baseClass}__row ${baseClass}__row--header`, children: columns.map((col) => /* @__PURE__ */ jsx(
33
+ "th",
34
+ {
35
+ className: `${baseClass}__header-cell`,
36
+ scope: "col",
37
+ style: {
38
+ width: col.width,
39
+ textAlign: col.align || "left"
40
+ },
41
+ children: col.header
35
42
  },
36
- children: col.header
37
- },
38
- col.key
39
- )) }) }),
40
- /* @__PURE__ */ jsx("tbody", { className: `${baseClass}__body`, children: rows.map((row) => /* @__PURE__ */ jsx("tr", { className: `${baseClass}__row`, children: columns.map((col) => /* @__PURE__ */ jsx(
41
- "td",
42
- {
43
- className: `${baseClass}__cell`,
44
- children: /* @__PURE__ */ jsx(
45
- "div",
46
- {
47
- className: `${baseClass}__cell-content`,
48
- style: {
49
- justifyContent: col.align === "center" ? "center" : col.align === "right" ? "flex-end" : "flex-start"
50
- },
51
- children: row.cells[col.key]
52
- }
53
- )
54
- },
55
- col.key
56
- )) }, row.id)) })
57
- ] });
58
- if (bordered) {
59
- return /* @__PURE__ */ jsx("div", { className: `${baseClass}__wrapper`, children: table });
43
+ col.key
44
+ )) }) }),
45
+ /* @__PURE__ */ jsx("tbody", { className: `${baseClass}__body`, children: rows.map((row) => /* @__PURE__ */ jsx("tr", { className: `${baseClass}__row`, children: columns.map((col) => /* @__PURE__ */ jsx("td", { className: `${baseClass}__cell`, children: /* @__PURE__ */ jsx(
46
+ "div",
47
+ {
48
+ className: `${baseClass}__cell-content`,
49
+ style: {
50
+ justifyContent: col.align === "center" ? "center" : col.align === "right" ? "flex-end" : "flex-start"
51
+ },
52
+ children: row.cells[col.key]
53
+ }
54
+ ) }, col.key)) }, row.id)) })
55
+ ] });
56
+ if (bordered) {
57
+ return /* @__PURE__ */ jsx("div", { className: `${baseClass}__wrapper`, children: table });
58
+ }
59
+ return table;
60
60
  }
61
- return table;
62
- };
61
+ );
62
+ Table.displayName = "Table";
63
63
  export {
64
64
  Table
65
65
  };