@multiplatform.one/table-primitives 6.1.0 → 6.4.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.
@@ -1,7 +1,9 @@
1
1
  /**
2
2
  * Table primitives tests - 5 focused tests for Task Group 1.
3
3
  *
4
- * Note: Tamagui + React Native Web renders elements with `tag="table"` etc.
4
+ * Note: tamagui 2.0.0-rc derives the DOM element from the `render` prop —
5
+ * the primitives emit REAL <table>/<thead>/<tbody>/<tfoot>/<tr>/<th>/<td>/
6
+ * <caption> elements on web (task 8.5 of the table first-principles spec).
5
7
  */
6
8
 
7
9
  import { renderWithProviders } from "@multiplatform.one/test-utils";
@@ -9,7 +11,7 @@ import { describe, expect, it } from "vitest";
9
11
  import { Table } from "./index";
10
12
 
11
13
  describe("Table Primitives", () => {
12
- it("renders semantic HTML structure via tag attributes (table, thead, tbody, tfoot, tr, td, th, caption)", () => {
14
+ it("renders real semantic HTML elements (table, thead, tbody, tfoot, tr, td, th, caption)", () => {
13
15
  const { container } = renderWithProviders(
14
16
  <Table>
15
17
  <Table.Caption>Test Caption</Table.Caption>
@@ -31,23 +33,41 @@ describe("Table Primitives", () => {
31
33
  </Table>,
32
34
  );
33
35
 
34
- expect(container.querySelector('[tag="table"]')).not.toBeNull();
35
- expect(container.querySelector('[tag="thead"]')).not.toBeNull();
36
- expect(container.querySelector('[tag="tbody"]')).not.toBeNull();
37
- expect(container.querySelector('[tag="tfoot"]')).not.toBeNull();
38
- expect(container.querySelectorAll('[tag="tr"]').length).toBe(3);
39
- expect(container.querySelector('[tag="td"]')).not.toBeNull();
40
- expect(container.querySelector('[tag="th"]')).not.toBeNull();
41
- expect(container.querySelector('[tag="caption"]')).not.toBeNull();
42
-
43
- expect(container.querySelector(".is_Table")).not.toBeNull();
44
- expect(container.querySelector(".is_TableHead")).not.toBeNull();
45
- expect(container.querySelector(".is_TableBody")).not.toBeNull();
46
- expect(container.querySelector(".is_TableFoot")).not.toBeNull();
47
- expect(container.querySelector(".is_TableRow")).not.toBeNull();
48
- expect(container.querySelector(".is_TableCell")).not.toBeNull();
49
- expect(container.querySelector(".is_TableHeaderCell")).not.toBeNull();
50
- expect(container.querySelector(".is_TableCaption")).not.toBeNull();
36
+ expect(container.querySelector("table")).not.toBeNull();
37
+ expect(container.querySelector("thead")).not.toBeNull();
38
+ expect(container.querySelector("tbody")).not.toBeNull();
39
+ expect(container.querySelector("tfoot")).not.toBeNull();
40
+ expect(container.querySelectorAll("tr").length).toBe(3);
41
+ expect(container.querySelector("td")).not.toBeNull();
42
+ expect(container.querySelector("th")).not.toBeNull();
43
+ expect(container.querySelector("caption")).not.toBeNull();
44
+
45
+ // the `render` prop must not leak into the DOM as an attribute
46
+ expect(container.querySelector("[render]")).toBeNull();
47
+
48
+ // strict nesting validity (SSR contract): sections/rows/cells directly
49
+ // under their required parents — no wrapper elements in between
50
+ expect(container.querySelector("table > thead > tr > th")).not.toBeNull();
51
+ expect(container.querySelector("table > tbody > tr > td")).not.toBeNull();
52
+ expect(container.querySelector("table > tfoot > tr > td")).not.toBeNull();
53
+ expect(container.querySelector("table > caption")).not.toBeNull();
54
+
55
+ // explicit ARIA roles survive display overrides (flex displayMode)
56
+ expect(container.querySelector("table")?.getAttribute("role")).toBe("table");
57
+ expect(container.querySelector("thead")?.getAttribute("role")).toBe("rowgroup");
58
+ expect(container.querySelector("tbody")?.getAttribute("role")).toBe("rowgroup");
59
+ expect(container.querySelector("tfoot")?.getAttribute("role")).toBe("rowgroup");
60
+ expect(container.querySelector("td")?.getAttribute("role")).toBe("cell");
61
+ expect(container.querySelector("th")?.getAttribute("role")).toBe("columnheader");
62
+
63
+ expect(container.querySelector("table.is_Table")).not.toBeNull();
64
+ expect(container.querySelector("thead.is_TableHead")).not.toBeNull();
65
+ expect(container.querySelector("tbody.is_TableBody")).not.toBeNull();
66
+ expect(container.querySelector("tfoot.is_TableFoot")).not.toBeNull();
67
+ expect(container.querySelector("tr.is_TableRow")).not.toBeNull();
68
+ expect(container.querySelector("td.is_TableCell")).not.toBeNull();
69
+ expect(container.querySelector("th.is_TableHeaderCell")).not.toBeNull();
70
+ expect(container.querySelector("caption.is_TableCaption")).not.toBeNull();
51
71
  });
52
72
 
53
73
  it("applies intent props on Table.Row with Theme wrapping", () => {
@@ -80,7 +100,7 @@ describe("Table Primitives", () => {
80
100
  </Table>,
81
101
  );
82
102
 
83
- const rows = withIntent.querySelectorAll('[tag="tr"]');
103
+ const rows = withIntent.querySelectorAll("tr");
84
104
  expect(rows.length).toBe(4);
85
105
 
86
106
  expect(withIntent.textContent).toContain("Accent row");
@@ -88,10 +108,19 @@ describe("Table Primitives", () => {
88
108
  expect(withIntent.textContent).toContain("Warning row");
89
109
  expect(withIntent.textContent).toContain("Success row");
90
110
 
91
- const intentThemeWrappers = withIntent.querySelectorAll(".is_Theme");
92
- const normalThemeWrappers = withoutIntent.querySelectorAll(".is_Theme");
93
-
94
- expect(intentThemeWrappers.length).toBeGreaterThan(normalThemeWrappers.length);
111
+ // The intent theme class lands on the <tr> itself (scopes the theme CSS
112
+ // variables) a Theme span wrapper between <tbody> and <tr> would be
113
+ // invalid HTML and break SSR (parsers foster-parent it out of the table).
114
+ expect(withIntent.querySelector("tr.t_accent")).not.toBeNull();
115
+ expect(withIntent.querySelector("tr.t_error")).not.toBeNull();
116
+ expect(withIntent.querySelector("tr.t_warning")).not.toBeNull();
117
+ expect(withIntent.querySelector("tr.t_success")).not.toBeNull();
118
+ for (const row of withIntent.querySelectorAll("tr")) {
119
+ expect(row.parentElement?.tagName).toBe("TBODY");
120
+ }
121
+
122
+ const plainRow = withoutIntent.querySelector("tr");
123
+ expect(plainRow?.classList.contains("t_error")).toBe(false);
95
124
  });
96
125
 
97
126
  it("spreads knobProps from useResolvedKnobs on Table root", () => {
@@ -105,7 +134,7 @@ describe("Table Primitives", () => {
105
134
  </Table>,
106
135
  );
107
136
 
108
- const table = container.querySelector('[tag="table"]');
137
+ const table = container.querySelector("table");
109
138
  expect(table).not.toBeNull();
110
139
  expect(table?.textContent).toContain("Content");
111
140
 
@@ -124,13 +153,13 @@ describe("Table Primitives", () => {
124
153
  </Table>,
125
154
  );
126
155
 
127
- const caption = container.querySelector('[tag="caption"]');
156
+ const caption = container.querySelector("caption");
128
157
  expect(caption).not.toBeNull();
129
158
  expect(caption?.textContent).toContain("Monthly Sales Report");
130
159
  expect(caption?.classList.contains("is_TableCaption")).toBe(true);
131
160
 
132
- const table = container.querySelector('[tag="table"]');
133
- expect(table?.querySelector('[tag="caption"]')).not.toBeNull();
161
+ const table = container.querySelector("table");
162
+ expect(table?.querySelector("caption")).not.toBeNull();
134
163
  });
135
164
 
136
165
  it("exposes compound component API (Head, Body, Row, Cell, HeaderCell, Foot, Caption)", () => {
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Table primitives — styled semantic table components.
3
+ *
4
+ * Layer 1 only: depends on theme + Tamagui (no forms, no data-table).
5
+ * Consumed by @multiplatform.one/table, @multiplatform.one/forms, etc.
6
+ */
7
+ import type { SizeTokens } from "tamagui";
8
+ export { TableCellContext, useIsInTableCell, useTableCellContext } from "./tableCellContext";
9
+ export type { TableCellContextValue } from "./tableCellContext";
10
+ type AlignCells = {
11
+ y: "center" | "start" | "end";
12
+ x: "center" | "start" | "end";
13
+ };
14
+ /**
15
+ * Element rendering: tamagui 2.0.0-rc derives the DOM element from the
16
+ * `render` prop (`tag:` passes through as a plain attribute), so every
17
+ * primitive sets `render:` to emit real `<table>/<thead>/<tbody>/<tfoot>/
18
+ * <tr>/<th>/<td>/<caption>` elements on web. On native `render` is inert
19
+ * (skipProps) and the components stay RN Views in the flex displayMode.
20
+ *
21
+ * Explicit ARIA roles stay on every element: consumers restyle these
22
+ * elements (`displayMode="flex"`, sticky cells), and browsers drop the
23
+ * implicit table roles when a table element's display is overridden.
24
+ */
25
+ /** Table Components */
26
+ declare const Row: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
27
+ elevation?: number | SizeTokens | undefined;
28
+ transparent?: boolean | undefined;
29
+ fullscreen?: boolean | undefined;
30
+ circular?: boolean | undefined;
31
+ elevate?: boolean | undefined;
32
+ bordered?: boolean | undefined;
33
+ chromeless?: boolean | "all" | undefined;
34
+ rowLocation?: "middle" | "first" | "last" | undefined;
35
+ displayMode?: "table" | "flex" | undefined;
36
+ }, import("@tamagui/web").StaticConfigPublic>;
37
+ declare const Cell: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
38
+ elevation?: number | SizeTokens | undefined;
39
+ transparent?: boolean | undefined;
40
+ cellWidth?: number | "auto" | SizeTokens | undefined;
41
+ cellHeight?: SizeTokens | undefined;
42
+ fullscreen?: boolean | undefined;
43
+ circular?: boolean | undefined;
44
+ elevate?: boolean | undefined;
45
+ bordered?: boolean | undefined;
46
+ chromeless?: boolean | "all" | undefined;
47
+ displayMode?: "table" | "flex" | undefined;
48
+ alignCells?: AlignCells | undefined;
49
+ cellLocation?: "middle" | "first" | "last" | undefined;
50
+ }, import("@tamagui/web").StaticConfigPublic>;
51
+ declare const HeaderCell: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
52
+ elevation?: number | SizeTokens | undefined;
53
+ transparent?: boolean | undefined;
54
+ cellWidth?: number | "auto" | SizeTokens | undefined;
55
+ cellHeight?: SizeTokens | undefined;
56
+ fullscreen?: boolean | undefined;
57
+ circular?: boolean | undefined;
58
+ elevate?: boolean | undefined;
59
+ bordered?: boolean | undefined;
60
+ chromeless?: boolean | "all" | undefined;
61
+ displayMode?: "table" | "flex" | undefined;
62
+ alignHeaderCells?: AlignCells | undefined;
63
+ cellLocation?: "middle" | "first" | "last" | undefined;
64
+ }, import("@tamagui/web").StaticConfigPublic>;
65
+ declare const TableBody: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
66
+ elevation?: number | SizeTokens | undefined;
67
+ transparent?: boolean | undefined;
68
+ fullscreen?: boolean | undefined;
69
+ circular?: boolean | undefined;
70
+ elevate?: boolean | undefined;
71
+ bordered?: boolean | undefined;
72
+ chromeless?: boolean | "all" | undefined;
73
+ displayMode?: "table" | "flex" | undefined;
74
+ }, import("@tamagui/web").StaticConfigPublic>;
75
+ declare const TableHead: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
76
+ elevation?: number | SizeTokens | undefined;
77
+ transparent?: boolean | undefined;
78
+ fullscreen?: boolean | undefined;
79
+ circular?: boolean | undefined;
80
+ elevate?: boolean | undefined;
81
+ bordered?: boolean | undefined;
82
+ chromeless?: boolean | "all" | undefined;
83
+ displayMode?: "table" | "flex" | undefined;
84
+ }, import("@tamagui/web").StaticConfigPublic>;
85
+ declare const TableFoot: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
86
+ elevation?: number | SizeTokens | undefined;
87
+ transparent?: boolean | undefined;
88
+ fullscreen?: boolean | undefined;
89
+ circular?: boolean | undefined;
90
+ elevate?: boolean | undefined;
91
+ bordered?: boolean | undefined;
92
+ chromeless?: boolean | "all" | undefined;
93
+ displayMode?: "table" | "flex" | undefined;
94
+ }, import("@tamagui/web").StaticConfigPublic>;
95
+ declare const TableCaption: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
96
+ elevation?: number | import("@tamagui/core").SizeTokens | undefined;
97
+ transparent?: boolean | undefined;
98
+ fullscreen?: boolean | undefined;
99
+ circular?: boolean | undefined;
100
+ elevate?: boolean | undefined;
101
+ bordered?: boolean | undefined;
102
+ chromeless?: boolean | "all" | undefined;
103
+ }, import("@tamagui/web").StaticConfigPublic>;
104
+ declare const TableComp: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
105
+ elevation?: number | SizeTokens | undefined;
106
+ transparent?: boolean | undefined;
107
+ cellWidth?: SizeTokens | undefined;
108
+ cellHeight?: SizeTokens | undefined;
109
+ fullscreen?: boolean | undefined;
110
+ circular?: boolean | undefined;
111
+ elevate?: boolean | undefined;
112
+ bordered?: boolean | undefined;
113
+ chromeless?: boolean | "all" | undefined;
114
+ displayMode?: "table" | "flex" | undefined;
115
+ alignHeaderCells?: any;
116
+ alignCells?: any;
117
+ }, import("@tamagui/web").StaticConfigPublic>;
118
+ export interface ThemedRowProps extends React.ComponentProps<typeof Row> {
119
+ accent?: boolean;
120
+ error?: boolean;
121
+ warning?: boolean;
122
+ success?: boolean;
123
+ }
124
+ /**
125
+ * SP-EDGE row density: the `space` knob scales cell padding (row density)
126
+ * without adding an outer row inset (LC-18 / theme-propagation-spec SP-EDGE).
127
+ * `medium` matches the pre-knob defaults so default rendering is unchanged.
128
+ */
129
+ export declare function getTableCellPadding(space: string): {
130
+ paddingHorizontal: string;
131
+ paddingVertical: string;
132
+ };
133
+ /**
134
+ * Responsive layout mode for the Table primitive.
135
+ * - `table`: always render the semantic table (default — Layer-1 consumers
136
+ * like markdown tables and DataTable's grid own their responsive handling)
137
+ * - `cards`: render each body row as a stacked card of label/value pairs
138
+ * - `auto`: table on `$sm` and up, cards below (W11 compact class)
139
+ */
140
+ export type TableLayout = "table" | "cards" | "auto";
141
+ export interface ThemedTableProps extends React.ComponentProps<typeof TableComp> {
142
+ /** Responsive layout — see {@link TableLayout}. Default `table`. */
143
+ layout?: TableLayout;
144
+ }
145
+ declare function ThemedTableComp({ layout, ...props }: ThemedTableProps): import("react/jsx-runtime").JSX.Element;
146
+ declare function ThemedTableHead(props: React.ComponentProps<typeof TableHead>): import("react/jsx-runtime").JSX.Element;
147
+ declare function ThemedRow({ accent, error, warning, success, ...props }: ThemedRowProps): import("react/jsx-runtime").JSX.Element;
148
+ declare function ThemedCell({ children, style, ...props }: React.ComponentProps<typeof Cell>): import("react/jsx-runtime").JSX.Element;
149
+ declare function ThemedHeaderCell({ children, style, ...props }: React.ComponentProps<typeof HeaderCell>): import("react/jsx-runtime").JSX.Element;
150
+ export declare const Table: typeof ThemedTableComp & {
151
+ Head: typeof ThemedTableHead;
152
+ Body: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
153
+ elevation?: number | SizeTokens | undefined;
154
+ transparent?: boolean | undefined;
155
+ fullscreen?: boolean | undefined;
156
+ circular?: boolean | undefined;
157
+ elevate?: boolean | undefined;
158
+ bordered?: boolean | undefined;
159
+ chromeless?: boolean | "all" | undefined;
160
+ displayMode?: "table" | "flex" | undefined;
161
+ }, import("@tamagui/web").StaticConfigPublic>;
162
+ Row: typeof ThemedRow;
163
+ Cell: typeof ThemedCell;
164
+ HeaderCell: typeof ThemedHeaderCell;
165
+ Foot: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
166
+ elevation?: number | SizeTokens | undefined;
167
+ transparent?: boolean | undefined;
168
+ fullscreen?: boolean | undefined;
169
+ circular?: boolean | undefined;
170
+ elevate?: boolean | undefined;
171
+ bordered?: boolean | undefined;
172
+ chromeless?: boolean | "all" | undefined;
173
+ displayMode?: "table" | "flex" | undefined;
174
+ }, import("@tamagui/web").StaticConfigPublic>;
175
+ Caption: import("tamagui").TamaguiComponent<import("@tamagui/web").TamaDefer, import("tamagui").TamaguiElement, import("@tamagui/core").RNTamaguiViewNonStyleProps, import("@tamagui/web").StackStyleBase, {
176
+ elevation?: number | import("@tamagui/core").SizeTokens | undefined;
177
+ transparent?: boolean | undefined;
178
+ fullscreen?: boolean | undefined;
179
+ circular?: boolean | undefined;
180
+ elevate?: boolean | undefined;
181
+ bordered?: boolean | undefined;
182
+ chromeless?: boolean | "all" | undefined;
183
+ }, import("@tamagui/web").StaticConfigPublic>;
184
+ };
185
+ export type TableProps = ThemedTableProps;
186
+ export type TableRowProps = ThemedRowProps;
187
+ export type TableCellProps = React.ComponentProps<typeof Cell>;
188
+ export type TableHeaderCellProps = React.ComponentProps<typeof HeaderCell>;
189
+ export type TableBodyProps = React.ComponentProps<typeof TableBody>;
190
+ export type TableHeadProps = React.ComponentProps<typeof TableHead>;
191
+ export type TableFootProps = React.ComponentProps<typeof TableFoot>;
192
+ export type TableCaptionProps = React.ComponentProps<typeof TableCaption>;
193
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * TableCellContext — shared between table-primitives, @multiplatform.one/table, and forms.
3
+ *
4
+ * Forms re-exports this context so field components can detect table cells
5
+ * and use chromeless rendering.
6
+ */
7
+ export interface TableCellContextValue {
8
+ /** Whether the component is rendered inside a table cell */
9
+ inTableCell: boolean;
10
+ /** Whether the cell is in a header row */
11
+ isHeader?: boolean;
12
+ /** Whether the cell is editable */
13
+ editable?: boolean;
14
+ }
15
+ export declare const TableCellContext: import("react").Context<TableCellContextValue>;
16
+ export declare function useTableCellContext(): TableCellContextValue;
17
+ export declare function useIsInTableCell(): boolean;
18
+ //# sourceMappingURL=tableCellContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tableCellContext.d.ts","sourceRoot":"","sources":["../src/tableCellContext.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,WAAW,EAAE,OAAO,CAAC;IACrB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAQD,eAAO,MAAM,gBAAgB,gDAAqD,CAAC;AAEnF,wBAAgB,mBAAmB,IAAI,qBAAqB,CAE3D;AAED,wBAAgB,gBAAgB,IAAI,OAAO,CAG1C"}
@@ -1,183 +0,0 @@
1
- var import_test_utils = require("@multiplatform.one/test-utils");
2
- var import_vitest = require("vitest");
3
- var import_index = require("./index.cjs");
4
- var import_jsx_runtime = require("react/jsx-runtime");
5
- (0, import_vitest.describe)("Table Primitives", () => {
6
- (0, import_vitest.it)("renders semantic HTML structure via tag attributes (table, thead, tbody, tfoot, tr, td, th, caption)", () => {
7
- const {
8
- container
9
- } = (0, import_test_utils.renderWithProviders)(/* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_index.Table, {
10
- children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Caption, {
11
- children: "Test Caption"
12
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Head, {
13
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Row, {
14
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.HeaderCell, {
15
- children: "Header"
16
- })
17
- })
18
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Body, {
19
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Row, {
20
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
21
- children: "Cell"
22
- })
23
- })
24
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Foot, {
25
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Row, {
26
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
27
- children: "Footer"
28
- })
29
- })
30
- })]
31
- }));
32
- (0, import_vitest.expect)(container.querySelector('[tag="table"]')).not.toBeNull();
33
- (0, import_vitest.expect)(container.querySelector('[tag="thead"]')).not.toBeNull();
34
- (0, import_vitest.expect)(container.querySelector('[tag="tbody"]')).not.toBeNull();
35
- (0, import_vitest.expect)(container.querySelector('[tag="tfoot"]')).not.toBeNull();
36
- (0, import_vitest.expect)(container.querySelectorAll('[tag="tr"]').length).toBe(3);
37
- (0, import_vitest.expect)(container.querySelector('[tag="td"]')).not.toBeNull();
38
- (0, import_vitest.expect)(container.querySelector('[tag="th"]')).not.toBeNull();
39
- (0, import_vitest.expect)(container.querySelector('[tag="caption"]')).not.toBeNull();
40
- (0, import_vitest.expect)(container.querySelector(".is_Table")).not.toBeNull();
41
- (0, import_vitest.expect)(container.querySelector(".is_TableHead")).not.toBeNull();
42
- (0, import_vitest.expect)(container.querySelector(".is_TableBody")).not.toBeNull();
43
- (0, import_vitest.expect)(container.querySelector(".is_TableFoot")).not.toBeNull();
44
- (0, import_vitest.expect)(container.querySelector(".is_TableRow")).not.toBeNull();
45
- (0, import_vitest.expect)(container.querySelector(".is_TableCell")).not.toBeNull();
46
- (0, import_vitest.expect)(container.querySelector(".is_TableHeaderCell")).not.toBeNull();
47
- (0, import_vitest.expect)(container.querySelector(".is_TableCaption")).not.toBeNull();
48
- });
49
- (0, import_vitest.it)("applies intent props on Table.Row with Theme wrapping", () => {
50
- const {
51
- container: withIntent
52
- } = (0, import_test_utils.renderWithProviders)(/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table, {
53
- children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_index.Table.Body, {
54
- children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Row, {
55
- accent: true,
56
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
57
- children: "Accent row"
58
- })
59
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Row, {
60
- error: true,
61
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
62
- children: "Error row"
63
- })
64
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Row, {
65
- warning: true,
66
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
67
- children: "Warning row"
68
- })
69
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Row, {
70
- success: true,
71
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
72
- children: "Success row"
73
- })
74
- })]
75
- })
76
- }));
77
- const {
78
- container: withoutIntent
79
- } = (0, import_test_utils.renderWithProviders)(/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table, {
80
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Body, {
81
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Row, {
82
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
83
- children: "Normal row"
84
- })
85
- })
86
- })
87
- }));
88
- const rows = withIntent.querySelectorAll('[tag="tr"]');
89
- (0, import_vitest.expect)(rows.length).toBe(4);
90
- (0, import_vitest.expect)(withIntent.textContent).toContain("Accent row");
91
- (0, import_vitest.expect)(withIntent.textContent).toContain("Error row");
92
- (0, import_vitest.expect)(withIntent.textContent).toContain("Warning row");
93
- (0, import_vitest.expect)(withIntent.textContent).toContain("Success row");
94
- const intentThemeWrappers = withIntent.querySelectorAll(".is_Theme");
95
- const normalThemeWrappers = withoutIntent.querySelectorAll(".is_Theme");
96
- (0, import_vitest.expect)(intentThemeWrappers.length).toBeGreaterThan(normalThemeWrappers.length);
97
- });
98
- (0, import_vitest.it)("spreads knobProps from useResolvedKnobs on Table root", () => {
99
- const {
100
- container
101
- } = (0, import_test_utils.renderWithProviders)(/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table, {
102
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Body, {
103
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Row, {
104
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
105
- children: "Content"
106
- })
107
- })
108
- })
109
- }));
110
- const table = container.querySelector('[tag="table"]');
111
- (0, import_vitest.expect)(table).not.toBeNull();
112
- (0, import_vitest.expect)(table?.textContent).toContain("Content");
113
- (0, import_vitest.expect)(table?.classList.contains("is_Table")).toBe(true);
114
- });
115
- (0, import_vitest.it)("renders Table.Caption as a caption element", () => {
116
- const {
117
- container
118
- } = (0, import_test_utils.renderWithProviders)(/* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_index.Table, {
119
- children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Caption, {
120
- children: "Monthly Sales Report"
121
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Body, {
122
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Row, {
123
- children: /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
124
- children: "Data"
125
- })
126
- })
127
- })]
128
- }));
129
- const caption = container.querySelector('[tag="caption"]');
130
- (0, import_vitest.expect)(caption).not.toBeNull();
131
- (0, import_vitest.expect)(caption?.textContent).toContain("Monthly Sales Report");
132
- (0, import_vitest.expect)(caption?.classList.contains("is_TableCaption")).toBe(true);
133
- const table = container.querySelector('[tag="table"]');
134
- (0, import_vitest.expect)(table?.querySelector('[tag="caption"]')).not.toBeNull();
135
- });
136
- (0, import_vitest.it)("exposes compound component API (Head, Body, Row, Cell, HeaderCell, Foot, Caption)", () => {
137
- (0, import_vitest.expect)(import_index.Table.Head).toBeDefined();
138
- (0, import_vitest.expect)(import_index.Table.Body).toBeDefined();
139
- (0, import_vitest.expect)(import_index.Table.Row).toBeDefined();
140
- (0, import_vitest.expect)(import_index.Table.Cell).toBeDefined();
141
- (0, import_vitest.expect)(import_index.Table.HeaderCell).toBeDefined();
142
- (0, import_vitest.expect)(import_index.Table.Foot).toBeDefined();
143
- (0, import_vitest.expect)(import_index.Table.Caption).toBeDefined();
144
- const {
145
- getByText
146
- } = (0, import_test_utils.renderWithProviders)(/* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_index.Table, {
147
- children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Caption, {
148
- children: "Caption"
149
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Head, {
150
- children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_index.Table.Row, {
151
- children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.HeaderCell, {
152
- children: "H1"
153
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.HeaderCell, {
154
- children: "H2"
155
- })]
156
- })
157
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Body, {
158
- children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_index.Table.Row, {
159
- children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
160
- children: "A1"
161
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
162
- children: "A2"
163
- })]
164
- })
165
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Foot, {
166
- children: /* @__PURE__ */(0, import_jsx_runtime.jsxs)(import_index.Table.Row, {
167
- children: [/* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
168
- children: "F1"
169
- }), /* @__PURE__ */(0, import_jsx_runtime.jsx)(import_index.Table.Cell, {
170
- children: "F2"
171
- })]
172
- })
173
- })]
174
- }));
175
- (0, import_vitest.expect)(getByText("Caption")).toBeDefined();
176
- (0, import_vitest.expect)(getByText("H1")).toBeDefined();
177
- (0, import_vitest.expect)(getByText("H2")).toBeDefined();
178
- (0, import_vitest.expect)(getByText("A1")).toBeDefined();
179
- (0, import_vitest.expect)(getByText("A2")).toBeDefined();
180
- (0, import_vitest.expect)(getByText("F1")).toBeDefined();
181
- (0, import_vitest.expect)(getByText("F2")).toBeDefined();
182
- });
183
- });