@rttui/skin-anocca 1.0.13 → 1.0.15

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.
@@ -0,0 +1,136 @@
1
+ import { Canvas, Meta, Story, Source, Controls } from '@storybook/blocks';
2
+
3
+ import * as RttuiStories from './ReactTanstackTableUiStory.stories';
4
+
5
+ <Meta of={RttuiStories} />
6
+
7
+ # Column sizing
8
+ By default columns uses the size defined in the columns. By default that is 150px in tanstack table.
9
+
10
+ You can override this by setting the `size` prop on the column.
11
+ ```tsx
12
+ columnHelper.accessor("age", {
13
+ header: "Age",
14
+ size: 50,
15
+ })
16
+ ```
17
+
18
+ <Canvas of={RttuiStories.Basic} />
19
+
20
+ ### Auto crush columns
21
+
22
+ You can also use the `autoCrushColumns` prop to automatically crush columns to fit the available space.
23
+
24
+ ```tsx
25
+ <ReactTanstackTableUi
26
+ autoCrushColumns
27
+ />
28
+ ```
29
+
30
+ To prevent a perticular column from being crushed, you can set the `autoCrush` meta option to `false`.
31
+
32
+ ```tsx
33
+ columnHelper.accessor("name", {
34
+ header: "Name",
35
+ meta: { autoCrush: false },
36
+ })
37
+ ```
38
+
39
+ <Canvas of={RttuiStories.AutoCrushColumnsExceptName} />
40
+
41
+ ### Fill available space after crush
42
+
43
+ If you don't have so many columns and you want the columns to fill all the available space,
44
+ you can set the `autoCrushColumns` prop to `true` and set the `fillAvailableSpaceAfterCrush` prop to `true`.
45
+ [If you don't want a horizontal scrollbar to appear](?path=/docs/reacttanstacktableui--scrollbarwidthspecified) you also need to specify the `scrollbarWidth` prop which is the width of the vertical scrollbar.
46
+
47
+
48
+ ```tsx
49
+ <ReactTanstackTableUi
50
+ autoCrushColumns
51
+ fillAvailableSpaceAfterCrush
52
+ scrollbarWidth={16}
53
+ />
54
+ ```
55
+
56
+ To prevent a perticular column from being expanded, you can set the `fillAvailableSpaceAfterCrush` meta option to `false`.
57
+
58
+ ```ts
59
+ columnHelper.accessor("name", {
60
+ header: "Name",
61
+ meta: { fillAvailableSpaceAfterCrush: false },
62
+ })
63
+ ```
64
+
65
+ <Canvas of={RttuiStories.FillAvailableSpaceAfterCrushExceptName} />
66
+
67
+ ### Size by largest header
68
+
69
+ If you want the columns to be sized by the largest header, you can set the `crushMinSizeBy` prop to `header`.
70
+
71
+ ```tsx
72
+ <ReactTanstackTableUi crushMinSizeBy="header" />
73
+ ```
74
+
75
+ <Story of={RttuiStories.SizeByLargestHeader} />
76
+
77
+ You can also use meta to configure the crush behavior for a perticular column.
78
+
79
+ ```ts
80
+ columnHelper.accessor("age", {
81
+ header: "Age",
82
+ meta: { crushMinSizeBy: "cell" },
83
+ })
84
+ ```
85
+
86
+ <Story of={RttuiStories.SizeByLargestHeaderWithMeta} />
87
+
88
+ <br /><br />
89
+
90
+ # Column Pinning
91
+
92
+ By default columns are pinned relative to the other columns:
93
+
94
+ <Story of={RttuiStories.PinRelativeToCols} />
95
+
96
+ ```tsx
97
+ <ReactTanstackTableUi
98
+ autoCrushColumns
99
+ pinColsRelativeTo="cols"
100
+ />
101
+ ```
102
+
103
+ You can also pin columns relative to the table:
104
+
105
+ <Story of={RttuiStories.PinRelativeToTable} />
106
+
107
+ ```tsx
108
+ <ReactTanstackTableUi
109
+ autoCrushColumns
110
+ pinColsRelativeTo="table"
111
+ />
112
+ ```
113
+
114
+ # Row Pinning
115
+
116
+ By default rows are pinned relative to the other rows:
117
+
118
+ <Story of={RttuiStories.CanPinRowsRelativeToRows} />
119
+
120
+ ```tsx
121
+ <ReactTanstackTableUi
122
+ enableRowPinning
123
+ pinRowsRelativeTo="rows"
124
+ />
125
+ ```
126
+
127
+ You can also pin rows relative to the table:
128
+
129
+ <Story of={RttuiStories.CanPinRowsRelativeToTable} />
130
+
131
+ ```tsx
132
+ <ReactTanstackTableUi
133
+ enableRowPinning
134
+ pinRowsRelativeTo="table"
135
+ />
136
+ ```
@@ -0,0 +1,206 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+
3
+ import { getCoreRowModel } from "@tanstack/react-table";
4
+ import { AnoccaSkin } from "..";
5
+ import { ReactTanstackTableUi } from "./ReactTanstackTableUiStoryComponent";
6
+ import { createSourceCode } from "./createSourceCode";
7
+
8
+ // More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
9
+ const meta = {
10
+ title: "ReactTanstackTableUi",
11
+ component: ReactTanstackTableUi,
12
+ parameters: {
13
+ // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
14
+ layout: "centered",
15
+ },
16
+ // More on argTypes: https://storybook.js.org/docs/api/argtypes
17
+ argTypes: {
18
+ data: { control: "select" },
19
+ columns: { control: "select" },
20
+ pinColsRelativeTo: { control: "select", options: ["cols", "table"] },
21
+ skin: {
22
+ control: "object",
23
+ table: { disable: true },
24
+ },
25
+ },
26
+ // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#action-args
27
+ args: {
28
+ width: 600,
29
+ height: 400,
30
+ skin: AnoccaSkin,
31
+ autoCrushColumns: false,
32
+ data: "big",
33
+ columns: "few",
34
+ getCoreRowModel: getCoreRowModel(),
35
+ pinColsRelativeTo: "cols",
36
+ fillAvailableSpaceAfterCrush: false,
37
+ enableColumnPinning: true,
38
+ scrollbarWidth: 16,
39
+ getRowId: (row) => row.id,
40
+ },
41
+ } satisfies Meta<typeof ReactTanstackTableUi>;
42
+
43
+ export default meta;
44
+ type Story = StoryObj<typeof meta>;
45
+
46
+ export const Basic: Story = {
47
+ args: {
48
+ enableColumnPinning: true,
49
+ autoCrushColumns: false,
50
+ fillAvailableSpaceAfterCrush: false,
51
+ pinColsRelativeTo: "cols",
52
+ },
53
+ parameters: {
54
+ docs: {
55
+ source: { language: "tsx", code: createSourceCode() },
56
+ },
57
+ },
58
+ };
59
+
60
+ export const AutoCrushColumns: Story = {
61
+ args: {
62
+ autoCrushColumns: true,
63
+ },
64
+ parameters: {
65
+ docs: {
66
+ source: {
67
+ language: "tsx",
68
+ code: createSourceCode({ props: " autoCrushColumns" }),
69
+ },
70
+ },
71
+ },
72
+ };
73
+
74
+ export const AutoCrushColumnsExceptName: Story = {
75
+ args: {
76
+ autoCrushColumns: true,
77
+ meta: {
78
+ name: {
79
+ autoCrush: false,
80
+ },
81
+ },
82
+ },
83
+ parameters: {
84
+ docs: {
85
+ source: {
86
+ language: "tsx",
87
+ code: createSourceCode({
88
+ props: " autoCrushColumns",
89
+ nameMeta: " autoCrush: false,",
90
+ }),
91
+ },
92
+ },
93
+ },
94
+ };
95
+
96
+ export const PinRelativeToCols: Story = {
97
+ args: {
98
+ autoCrushColumns: true,
99
+ pinColsRelativeTo: "cols",
100
+ initialState: {
101
+ columnPinning: {
102
+ right: ["city"],
103
+ },
104
+ },
105
+ },
106
+ };
107
+
108
+ export const PinRelativeToTable: Story = {
109
+ args: {
110
+ autoCrushColumns: true,
111
+ pinColsRelativeTo: "table",
112
+ initialState: {
113
+ columnPinning: {
114
+ right: ["city"],
115
+ },
116
+ },
117
+ },
118
+ };
119
+
120
+ export const FillAvailableSpaceAfterCrush: Story = {
121
+ args: {
122
+ autoCrushColumns: true,
123
+ fillAvailableSpaceAfterCrush: true,
124
+ },
125
+ };
126
+
127
+ export const FillAvailableSpaceAfterCrushExceptName: Story = {
128
+ args: {
129
+ autoCrushColumns: true,
130
+ fillAvailableSpaceAfterCrush: true,
131
+ meta: {
132
+ name: {
133
+ fillAvailableSpaceAfterCrush: false,
134
+ },
135
+ },
136
+ },
137
+ parameters: {
138
+ docs: {
139
+ source: {
140
+ language: "tsx",
141
+ code: createSourceCode({
142
+ props: " autoCrushColumns\n fillAvailableSpaceAfterCrush",
143
+ nameMeta: " fillAvailableSpaceAfterCrush: false,",
144
+ }),
145
+ },
146
+ },
147
+ },
148
+ };
149
+
150
+ export const FillAvailableSpaceAfterCrushWithoutSpecifiedScrollbarWidth: Story =
151
+ {
152
+ args: {
153
+ autoCrushColumns: true,
154
+ fillAvailableSpaceAfterCrush: true,
155
+ scrollbarWidth: 0,
156
+ },
157
+ };
158
+
159
+ export const CanPinRowsRelativeToRows: Story = {
160
+ args: {
161
+ enableRowPinning: true,
162
+ enableColumnPinning: true,
163
+ data: "small",
164
+ pinRowsRelativeTo: "rows",
165
+ initialState: {
166
+ rowPinning: {
167
+ bottom: ["3"],
168
+ },
169
+ },
170
+ },
171
+ };
172
+
173
+ export const CanPinRowsRelativeToTable: Story = {
174
+ args: {
175
+ enableRowPinning: true,
176
+ enableColumnPinning: true,
177
+ data: "small",
178
+ pinRowsRelativeTo: "table",
179
+ initialState: {
180
+ rowPinning: {
181
+ bottom: ["3"],
182
+ },
183
+ },
184
+ },
185
+ };
186
+
187
+ export const SizeByLargestHeader: Story = {
188
+ args: {
189
+ autoCrushColumns: true,
190
+ crushMinSizeBy: "header",
191
+ enableColumnPinning: true,
192
+ },
193
+ };
194
+
195
+ export const SizeByLargestHeaderWithMeta: Story = {
196
+ args: {
197
+ autoCrushColumns: true,
198
+ crushMinSizeBy: "header",
199
+ enableColumnPinning: true,
200
+ meta: {
201
+ age: {
202
+ crushMinSizeBy: 'cell',
203
+ },
204
+ },
205
+ },
206
+ };
@@ -0,0 +1,113 @@
1
+ import { Box, ScopedCssBaseline, ThemeProvider, Typography } from "@mui/material";
2
+ import { useTheme } from "@mui/material/styles";
3
+ import {
4
+ decorateColumnHelper,
5
+ ReactTanstackTableUi as TableComponent,
6
+ } from "@rttui/core";
7
+ import {
8
+ ColumnDef,
9
+ ColumnMeta,
10
+ createColumnHelper,
11
+ Table,
12
+ TableOptions,
13
+ useReactTable,
14
+ } from "@tanstack/react-table";
15
+ import { HeaderPinButtons } from "../HeaderPinButtons";
16
+ import React from "react";
17
+ import { RowPinButtons } from "../RowPinButtons";
18
+ type Person = {
19
+ id: string;
20
+ name: string;
21
+ age: number;
22
+ city: string;
23
+ } & Record<`col${number}`, string>;
24
+
25
+ const smallData: Person[] = [
26
+ { id: "1", name: "John", age: 20, city: "New York" },
27
+ { id: "2", name: "Jane", age: 21, city: "Los Angeles" },
28
+ { id: "3", name: "Jim", age: 22, city: "Chicago" },
29
+ ];
30
+
31
+ const bigData: Person[] = Array.from({ length: 1000 }, (_, i) => ({
32
+ id: i.toString(),
33
+ name: `Person ${i}`,
34
+ age: 20 + i,
35
+ city: `City ${i}`,
36
+ ...Object.fromEntries(
37
+ Array.from({ length: 100 }, (_, j) => [`col${j}`, `Value ${i}-${j}`]),
38
+ ),
39
+ }));
40
+
41
+ export const ReactTanstackTableUi = (
42
+ props: {
43
+ data: "big" | "small";
44
+ columns: "many" | "few";
45
+ meta?: Record<string, ColumnMeta<Person, string>>;
46
+ } & Omit<TableOptions<Person>, "data" | "columns"> &
47
+ Omit<React.ComponentProps<typeof TableComponent>, "table">,
48
+ ) => {
49
+ const theme = useTheme();
50
+ const data: Person[] = props.data === "big" ? bigData : smallData;
51
+
52
+ const columns: ColumnDef<Person>[] = React.useMemo(() => {
53
+ const columnHelper = decorateColumnHelper(createColumnHelper<Person>(), {
54
+ header: (original) => (
55
+ <Box sx={{ display: "flex", gap: 2 }}>
56
+ {original}
57
+ {props.enableColumnPinning && <HeaderPinButtons />}
58
+ </Box>
59
+ ),
60
+ });
61
+
62
+ const fewColumns = [
63
+ columnHelper.accessor("name", {
64
+ header: "Name",
65
+ cell: (info) => (
66
+ <Box sx={{ display: "flex", gap: 2, flex: 1 }}>
67
+ <Typography variant="body2">{info.getValue()}</Typography>
68
+ <Box sx={{ flexGrow: 1 }} />
69
+ {props.enableRowPinning && <RowPinButtons row={info.row} />}
70
+ </Box>
71
+ ),
72
+ meta: props.meta?.["name"],
73
+ }),
74
+ columnHelper.accessor("age", {
75
+ header: "Age",
76
+ meta: props.meta?.["age"],
77
+ cell: (info) => <Typography variant="body2">{info.getValue()}</Typography>,
78
+ size: 50,
79
+ }),
80
+ columnHelper.accessor("city", {
81
+ header: "City",
82
+ meta: props.meta?.["city"],
83
+ cell: (info) => <Typography variant="body2">{info.getValue()}</Typography>,
84
+ }),
85
+ ];
86
+
87
+ const manyColumns = [
88
+ ...fewColumns,
89
+ ...Array.from({ length: 100 }, (_, i) =>
90
+ columnHelper.accessor(`col${i}`, {
91
+ header: `Column ${i}`,
92
+ cell: (info) => <Typography variant="body2">{info.getValue()}</Typography>,
93
+ }),
94
+ ),
95
+ ];
96
+
97
+ return props.columns === "few" ? fewColumns : manyColumns;
98
+ }, [props.columns, props.enableColumnPinning, props.enableRowPinning, props.meta]);
99
+
100
+ const table = useReactTable({
101
+ ...props,
102
+ data,
103
+ columns,
104
+ });
105
+
106
+ return (
107
+ <ScopedCssBaseline>
108
+ <ThemeProvider theme={theme}>
109
+ <TableComponent {...props} table={table as Table<unknown>} />
110
+ </ThemeProvider>
111
+ </ScopedCssBaseline>
112
+ );
113
+ };
@@ -0,0 +1,42 @@
1
+ import { Canvas, Meta, Story, Source, Controls } from '@storybook/blocks';
2
+ import { Box } from '@mui/material';
3
+
4
+ import * as ColumnPinningStories from './ReactTanstackTableUiStory.stories';
5
+
6
+ <Meta of={ColumnPinningStories} />
7
+
8
+ # ⚠️ No scrollbar width specified
9
+ We get a horizontal scrollbar because we don't specify the width of the vertical scrollbar.
10
+ ```tsx
11
+ <ReactTanstackTableUi
12
+ autoCrushColumns
13
+ fillAvailableSpaceAfterCrush
14
+ />
15
+ ```
16
+ <Box sx={{
17
+ '*::-webkit-scrollbar': { width: '16px' },
18
+ '*::-webkit-scrollbar-track': { backgroundColor: 'yellow' },
19
+ '*::-webkit-scrollbar-thumb': { backgroundColor: 'blue' },
20
+ }}
21
+ >
22
+ <Story of={ColumnPinningStories.FillAvailableSpaceAfterCrushWithoutSpecifiedScrollbarWidth} />
23
+ </Box>
24
+ <br /><br />
25
+ # ✅ Scrollbar width specified
26
+ We specify the width of the vertical scrollbar and we correctly only see a vertical scrollbar.
27
+ ```tsx
28
+ <ReactTanstackTableUi
29
+ autoCrushColumns
30
+ fillAvailableSpaceAfterCrush
31
+ scrollbarWidth={16}
32
+ />
33
+ ```
34
+ <Box sx={{
35
+ '*::-webkit-scrollbar': { width: '16px' },
36
+ '*::-webkit-scrollbar-track': { backgroundColor: 'yellow' },
37
+ '*::-webkit-scrollbar-thumb': { backgroundColor: 'blue' },
38
+ }}
39
+ >
40
+ <Story of={ColumnPinningStories.FillAvailableSpaceAfterCrushExceptName} />
41
+ </Box>
42
+
@@ -0,0 +1,53 @@
1
+ export const createSourceCode = (opts?: { hookOptions?: string, props?: string, nameMeta?: string }) => {
2
+ return `import { createColumnHelper, useReactTable, getCoreRowModel } from "@tanstack/react-table";
3
+ import { Box } from "@mui/material";
4
+ import { HeaderPinButtons } from "@rttui/skin-anocca";
5
+ import { ReactTanstackTableUi, decorateColumnHelper } from "@rttui/core";
6
+
7
+ type Person = {
8
+ id: string;
9
+ name: string;
10
+ age: number;
11
+ city: string;
12
+ };
13
+
14
+ const data: Person[] = [
15
+ { id: "1", name: "John", age: 20, city: "New York" },
16
+ { id: "2", name: "Jane", age: 21, city: "Los Angeles" },
17
+ { id: "3", name: "Jim", age: 22, city: "Chicago" },
18
+ ];
19
+
20
+ const columnHelper = decorateColumnHelper(createColumnHelper<Person>(), {
21
+ header: (original) => (
22
+ <Box sx={{ display: "flex", gap: 2 }}>
23
+ {original}
24
+ {props.enableColumnPinning && <HeaderPinButtons />}
25
+ </Box>
26
+ ),
27
+ });
28
+
29
+ const columns = [
30
+ columnHelper.accessor("name", {
31
+ header: "Name",${opts?.nameMeta ? '\n' + opts.nameMeta : ''}
32
+ }),
33
+ columnHelper.accessor("age", {
34
+ header: "Age",
35
+ size: 50,
36
+ }),
37
+ columnHelper.accessor("city", {
38
+ header: "City",
39
+ }),
40
+ ];
41
+
42
+ const table = useReactTable({
43
+ data,
44
+ columns,
45
+ getCoreRowModel: getCoreRowModel()${opts?.hookOptions ? '\n' + opts.hookOptions : ''}
46
+ });
47
+
48
+ <ReactTanstackTableUi
49
+ table={table}
50
+ enableColumnPinning${opts?.props ? '\n' + opts.props : ''}
51
+ />
52
+ `;
53
+ };
package/vite.config.ts ADDED
@@ -0,0 +1,23 @@
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react";
3
+ import path from "path";
4
+ import fs from "fs";
5
+ let base: undefined | string;
6
+
7
+ try {
8
+ const packageJson = fs.readFileSync(
9
+ path.join(__dirname, "package.json"),
10
+ "utf-8",
11
+ );
12
+ const viteBase = JSON.parse(packageJson).viteBase;
13
+ if (viteBase) {
14
+ base = viteBase;
15
+ }
16
+ } catch (e) {
17
+ // ignore
18
+ }
19
+
20
+ // https://vite.dev/config/
21
+ export default defineConfig({
22
+ plugins: [react()],
23
+ });