@ttoss/components 1.30.6 → 1.31.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.
package/README.md CHANGED
@@ -20,6 +20,71 @@ pnpm add @ttoss/components @ttoss/ui @emotion/react @ttoss/react-hooks
20
20
 
21
21
  You can check all the components of the library `@ttoss/ui` on the [Storybook](https://storybook.ttoss.dev/?path=/story/components).
22
22
 
23
+ ### List
24
+
25
+ The `List` component is a React component that renders an unordered list `(<ul>)` and accepts
26
+ `ListItem` as its children. Each ListItem can contain any React content, including other components.
27
+
28
+ ```tsx
29
+ import React from 'react';
30
+ import { List, ListItem } from '@ttoss/components/List';
31
+
32
+ const MyComponent = () => (
33
+ <List>
34
+ <ListItem>Item 1</ListItem>
35
+ <ListItem>Item 2</ListItem>
36
+ <ListItem>Item 3</ListItem>
37
+ <ListItem>
38
+ <CustomComponent />
39
+ </ListItem>
40
+ </List>
41
+ );
42
+ ```
43
+
44
+ In this example, `List` is used to render an `<ul>` list with four items. The last item contains a custom React component (CustomComponent), demonstrating that ListItem can receive any React content as its children.
45
+
46
+ This is a basic example of how to use the `List` component with `ListItem`. You can customize the content and styles as needed to fit your project requirements.
47
+
48
+ ### Markdown
49
+
50
+ Markdown uses [react-markdown](https://remarkjs.github.io/react-markdown/) under the hood, so the props are the same. You can update the elements as you want. Ex:
51
+
52
+ ```tsx
53
+ const MARKDOWN_CONTENT = `
54
+ # Heading 1
55
+ ## Heading 2
56
+ ### Heading 3
57
+ #### Heading 4
58
+ ##### Heading 5
59
+
60
+ Lorem ipsum dolor sit, amet consectetur adipisicing elit. Odit quasi dolorum aperiam fugiat earum expedita non eligendi similique id minus explicabo, eum facere nihil aspernatur libero! Sapiente aliquid tenetur dolor.
61
+
62
+ - Item 1
63
+ - Item 2
64
+ - Item 3
65
+
66
+ ![Alt Text](https://fastly.picsum.photos/id/436/200/300.jpg?hmac=OuJRsPTZRaNZhIyVFbzDkMYMyORVpV86q5M8igEfM3Y "Alt Text")
67
+
68
+ [Google](https://google.com)
69
+ `;
70
+
71
+ const Component = () => {
72
+ return (
73
+ <Markdown
74
+ components={{
75
+ a: ({ children, ...props }) => (
76
+ <Link {...props} quiet>
77
+ {children}
78
+ </Link>
79
+ ),
80
+ }}
81
+ >
82
+ {MARKDOWN_CONTENT}
83
+ </Markdown>
84
+ );
85
+ };
86
+ ```
87
+
23
88
  ### Modal
24
89
 
25
90
  Modal uses [react-modal](https://reactcommunity.org/react-modal/) under the hood, so the props are the same. The only difference is that the styles are theme-aware. You can [style the modal](https://reactcommunity.org/react-modal/styles/) using theme tokens, except that [array as value](https://theme-ui.com/sx-prop#responsive-values) don't work.
@@ -82,46 +147,6 @@ const Component = () => {
82
147
  };
83
148
  ```
84
149
 
85
- ### Markdown
86
-
87
- Markdown uses [react-markdown](https://remarkjs.github.io/react-markdown/) under the hood, so the props are the same. You can update the elements as you want. Ex:
88
-
89
- ```tsx
90
- const MARKDOWN_CONTENT = `
91
- # Heading 1
92
- ## Heading 2
93
- ### Heading 3
94
- #### Heading 4
95
- ##### Heading 5
96
-
97
- Lorem ipsum dolor sit, amet consectetur adipisicing elit. Odit quasi dolorum aperiam fugiat earum expedita non eligendi similique id minus explicabo, eum facere nihil aspernatur libero! Sapiente aliquid tenetur dolor.
98
-
99
- - Item 1
100
- - Item 2
101
- - Item 3
102
-
103
- ![Alt Text](https://fastly.picsum.photos/id/436/200/300.jpg?hmac=OuJRsPTZRaNZhIyVFbzDkMYMyORVpV86q5M8igEfM3Y "Alt Text")
104
-
105
- [Google](https://google.com)
106
- `;
107
-
108
- const Component = () => {
109
- return (
110
- <Markdown
111
- components={{
112
- a: ({ children, ...props }) => (
113
- <Link {...props} quiet>
114
- {children}
115
- </Link>
116
- ),
117
- }}
118
- >
119
- {MARKDOWN_CONTENT}
120
- </Markdown>
121
- );
122
- };
123
- ```
124
-
125
150
  ### Search
126
151
 
127
152
  `Search` is a component that integrates an input field with debouncing functionality, making it ideal for search bars where you want to limit the rate of search queries based on user input.
@@ -155,3 +180,195 @@ const SearchComponent = () => {
155
180
  ```
156
181
 
157
182
  In this example, the `Search` component receives the current search text and a handler function to update this text. The `loading` prop can be used to display a loading indicator, and the `debounce` prop controls the debounce delay.
183
+
184
+ ### Table
185
+
186
+ The `Table` component is a flexible and customizable table that supports sorting, filtering, and pagination. It is designed to be easy to use and integrate with your data sources. It exports all [TanStack Table](https://tanstack.com/table/latest) hooks and methods.
187
+
188
+ #### Basic Usage
189
+
190
+ ```tsx
191
+ import * as React from 'react';
192
+ import {
193
+ Table,
194
+ TableBody,
195
+ TableCell,
196
+ TableFooter,
197
+ TableHead,
198
+ TableHeader,
199
+ TableRow,
200
+ createColumnHelper,
201
+ flexRender,
202
+ getCoreRowModel,
203
+ useReactTable,
204
+ } from '@ttoss/components/table';
205
+
206
+ type Person = {
207
+ firstName: string;
208
+ lastName: string;
209
+ age: number;
210
+ visits: number;
211
+ status: string;
212
+ progress: number;
213
+ };
214
+
215
+ const defaultData: Person[] = [
216
+ {
217
+ firstName: 'tanner',
218
+ lastName: 'linsley',
219
+ age: 24,
220
+ visits: 100,
221
+ status: 'In Relationship',
222
+ progress: 50,
223
+ },
224
+ {
225
+ firstName: 'tandy',
226
+ lastName: 'miller',
227
+ age: 40,
228
+ visits: 40,
229
+ status: 'Single',
230
+ progress: 80,
231
+ },
232
+ {
233
+ firstName: 'joe',
234
+ lastName: 'dirte',
235
+ age: 45,
236
+ visits: 20,
237
+ status: 'Complicated',
238
+ progress: 10,
239
+ },
240
+ ];
241
+
242
+ const columnHelper = createColumnHelper<Person>();
243
+
244
+ const columns = [
245
+ columnHelper.accessor('firstName', {
246
+ cell: (info) => {
247
+ return info.getValue();
248
+ },
249
+ footer: (info) => {
250
+ return info.column.id;
251
+ },
252
+ }),
253
+ columnHelper.accessor(
254
+ (row) => {
255
+ return row.lastName;
256
+ },
257
+ {
258
+ id: 'lastName',
259
+ cell: (info) => {
260
+ return <i>{info.getValue()}</i>;
261
+ },
262
+ header: () => {
263
+ return <span>Last Name</span>;
264
+ },
265
+ footer: (info) => {
266
+ return info.column.id;
267
+ },
268
+ }
269
+ ),
270
+ columnHelper.accessor('age', {
271
+ header: () => {
272
+ return 'Age';
273
+ },
274
+ cell: (info) => {
275
+ return info.renderValue();
276
+ },
277
+ footer: (info) => {
278
+ return info.column.id;
279
+ },
280
+ }),
281
+ columnHelper.accessor('visits', {
282
+ header: () => {
283
+ return <span>Visits</span>;
284
+ },
285
+ footer: (info) => {
286
+ return info.column.id;
287
+ },
288
+ }),
289
+ columnHelper.accessor('status', {
290
+ header: 'Status',
291
+ footer: (info) => {
292
+ return info.column.id;
293
+ },
294
+ }),
295
+ columnHelper.accessor('progress', {
296
+ header: 'Profile Progress',
297
+ footer: (info) => {
298
+ return info.column.id;
299
+ },
300
+ }),
301
+ ];
302
+
303
+ const RenderTable = () => {
304
+ const [data] = React.useState(() => {
305
+ return [...defaultData];
306
+ });
307
+
308
+ const table = useReactTable({
309
+ data,
310
+ columns,
311
+ getCoreRowModel: getCoreRowModel(),
312
+ });
313
+
314
+ return (
315
+ <Table>
316
+ <TableHead>
317
+ {table.getHeaderGroups().map((headerGroup) => {
318
+ return (
319
+ <TableRow key={headerGroup.id}>
320
+ {headerGroup.headers.map((header) => {
321
+ return (
322
+ <TableHeader key={header.id}>
323
+ {header.isPlaceholder
324
+ ? null
325
+ : flexRender(
326
+ header.column.columnDef.header,
327
+ header.getContext()
328
+ )}
329
+ </TableHeader>
330
+ );
331
+ })}
332
+ </TableRow>
333
+ );
334
+ })}
335
+ </TableHead>
336
+ <TableBody>
337
+ {table.getRowModel().rows.map((row) => {
338
+ return (
339
+ <TableRow key={row.id}>
340
+ {row.getVisibleCells().map((cell) => {
341
+ return (
342
+ <TableCell key={cell.id}>
343
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
344
+ </TableCell>
345
+ );
346
+ })}
347
+ </TableRow>
348
+ );
349
+ })}
350
+ </TableBody>
351
+ <TableFooter>
352
+ {table.getFooterGroups().map((footerGroup) => {
353
+ return (
354
+ <TableRow key={footerGroup.id}>
355
+ {footerGroup.headers.map((header) => {
356
+ return (
357
+ <TableHeader key={header.id}>
358
+ {header.isPlaceholder
359
+ ? null
360
+ : flexRender(
361
+ header.column.columnDef.footer,
362
+ header.getContext()
363
+ )}
364
+ </TableHeader>
365
+ );
366
+ })}
367
+ </TableRow>
368
+ );
369
+ })}
370
+ </TableFooter>
371
+ </Table>
372
+ );
373
+ };
374
+ ```
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+
3
+ interface ListProps extends React.HTMLProps<HTMLUListElement> {
4
+ children: React.ReactNode;
5
+ }
6
+ declare const List: React.ForwardRefExoticComponent<Omit<ListProps, "ref"> & React.RefAttributes<HTMLUListElement>>;
7
+
8
+ interface ListItemProps extends React.HTMLProps<HTMLLIElement> {
9
+ children: React.ReactNode;
10
+ }
11
+ declare const ListItem: React.ForwardRefExoticComponent<Omit<ListItemProps, "ref"> & React.RefAttributes<HTMLLIElement>>;
12
+
13
+ export { List, ListItem, type ListItemProps, type ListProps };
@@ -0,0 +1,14 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { BoxProps } from '@ttoss/ui';
3
+ export * from '@tanstack/react-table';
4
+
5
+ declare const Table: (props: BoxProps) => react_jsx_runtime.JSX.Element;
6
+ declare const TableHead: (props: BoxProps) => react_jsx_runtime.JSX.Element;
7
+ declare const TableBody: (props: BoxProps) => react_jsx_runtime.JSX.Element;
8
+ declare const TableRow: (props: BoxProps) => react_jsx_runtime.JSX.Element;
9
+ declare const TableCell: (props: BoxProps) => react_jsx_runtime.JSX.Element;
10
+ declare const TableHeader: (props: BoxProps) => react_jsx_runtime.JSX.Element;
11
+ declare const TableCaption: (props: BoxProps) => react_jsx_runtime.JSX.Element;
12
+ declare const TableFooter: (props: BoxProps) => react_jsx_runtime.JSX.Element;
13
+
14
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
@@ -0,0 +1,33 @@
1
+ /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+
3
+ // src/components/List/List.tsx
4
+ import * as React from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ var List = /*#__PURE__*/React.forwardRef(({
7
+ children,
8
+ ...props
9
+ }, ref) => {
10
+ return /* @__PURE__ */jsx("ul", {
11
+ ...props,
12
+ ref,
13
+ children
14
+ });
15
+ });
16
+ List.displayName = "List";
17
+
18
+ // src/components/List/ListItem.tsx
19
+ import * as React2 from "react";
20
+ import { jsx as jsx2 } from "react/jsx-runtime";
21
+ var ListItem = /*#__PURE__*/React2.forwardRef((props, ref) => {
22
+ const {
23
+ children,
24
+ ...rest
25
+ } = props;
26
+ return /* @__PURE__ */jsx2("li", {
27
+ ...rest,
28
+ ref,
29
+ children
30
+ });
31
+ });
32
+ ListItem.displayName = "ListItem";
33
+ export { List, ListItem };
@@ -0,0 +1,55 @@
1
+ /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+
3
+ // src/components/Table.tsx
4
+ import { Box } from "@ttoss/ui";
5
+ export * from "@tanstack/react-table";
6
+ import { jsx } from "react/jsx-runtime";
7
+ var Table = props => {
8
+ return /* @__PURE__ */jsx(Box, {
9
+ as: "table",
10
+ ...props
11
+ });
12
+ };
13
+ var TableHead = props => {
14
+ return /* @__PURE__ */jsx(Box, {
15
+ as: "thead",
16
+ ...props
17
+ });
18
+ };
19
+ var TableBody = props => {
20
+ return /* @__PURE__ */jsx(Box, {
21
+ as: "tbody",
22
+ ...props
23
+ });
24
+ };
25
+ var TableRow = props => {
26
+ return /* @__PURE__ */jsx(Box, {
27
+ as: "tr",
28
+ ...props
29
+ });
30
+ };
31
+ var TableCell = props => {
32
+ return /* @__PURE__ */jsx(Box, {
33
+ as: "td",
34
+ ...props
35
+ });
36
+ };
37
+ var TableHeader = props => {
38
+ return /* @__PURE__ */jsx(Box, {
39
+ as: "th",
40
+ ...props
41
+ });
42
+ };
43
+ var TableCaption = props => {
44
+ return /* @__PURE__ */jsx(Box, {
45
+ as: "caption",
46
+ ...props
47
+ });
48
+ };
49
+ var TableFooter = props => {
50
+ return /* @__PURE__ */jsx(Box, {
51
+ as: "tfoot",
52
+ ...props
53
+ });
54
+ };
55
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
package/dist/esm/index.js CHANGED
@@ -249,10 +249,10 @@ var Search = ({
249
249
  const debouncedValue = useDebounce(text, 500);
250
250
  React4.useEffect(() => {
251
251
  onChange(debouncedValue);
252
- }, [debouncedValue]);
252
+ }, [debouncedValue, onChange]);
253
253
  return /* @__PURE__ */jsx6(Input, {
254
254
  leadingIcon: loading ? "loading" : "search",
255
- value: text,
255
+ defaultValue: text,
256
256
  onChange: e => {
257
257
  return setText(e.target.value);
258
258
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/components",
3
- "version": "1.30.6",
3
+ "version": "1.31.1",
4
4
  "description": "React components for ttoss ecosystem.",
5
5
  "author": "ttoss",
6
6
  "contributors": [
@@ -16,6 +16,14 @@
16
16
  ".": {
17
17
  "types": "./dist/index.d.ts",
18
18
  "import": "./dist/esm/index.js"
19
+ },
20
+ "./list": {
21
+ "types": "./dist/List.d.ts",
22
+ "import": "./dist/esm/List.js"
23
+ },
24
+ "./table": {
25
+ "types": "./dist/components/Table.d.ts",
26
+ "import": "./dist/esm/components/Table.js"
19
27
  }
20
28
  },
21
29
  "files": [
@@ -25,6 +33,7 @@
25
33
  "sideEffects": false,
26
34
  "dependencies": {
27
35
  "@emotion/css": "^11.11.2",
36
+ "@tanstack/react-table": "^8.15.3",
28
37
  "@theme-ui/css": "^0.16.2",
29
38
  "@types/react-modal": "^3.16.3",
30
39
  "react-accessible-accordion": "^5.0.0",
@@ -47,8 +56,8 @@
47
56
  "tsup": "^8.0.2",
48
57
  "@ttoss/config": "^1.31.5",
49
58
  "@ttoss/react-icons": "^0.3.1",
50
- "@ttoss/test-utils": "^2.1.1",
51
59
  "@ttoss/react-hooks": "^1.25.3",
60
+ "@ttoss/test-utils": "^2.1.1",
52
61
  "@ttoss/ui": "^4.1.4"
53
62
  },
54
63
  "keywords": [
@@ -0,0 +1,17 @@
1
+ import * as React from 'react';
2
+
3
+ export interface ListProps extends React.HTMLProps<HTMLUListElement> {
4
+ children: React.ReactNode;
5
+ }
6
+
7
+ export const List = React.forwardRef<HTMLUListElement, ListProps>(
8
+ ({ children, ...props }, ref) => {
9
+ return (
10
+ <ul {...props} ref={ref}>
11
+ {children}
12
+ </ul>
13
+ );
14
+ }
15
+ );
16
+
17
+ List.displayName = 'List';
@@ -0,0 +1,18 @@
1
+ import * as React from 'react';
2
+
3
+ export interface ListItemProps extends React.HTMLProps<HTMLLIElement> {
4
+ children: React.ReactNode;
5
+ }
6
+
7
+ export const ListItem = React.forwardRef<HTMLLIElement, ListItemProps>(
8
+ (props, ref) => {
9
+ const { children, ...rest } = props;
10
+ return (
11
+ <li {...rest} ref={ref}>
12
+ {children}
13
+ </li>
14
+ );
15
+ }
16
+ );
17
+
18
+ ListItem.displayName = 'ListItem';
@@ -0,0 +1,2 @@
1
+ export * from './List';
2
+ export * from './ListItem';
@@ -21,12 +21,12 @@ export const Search = ({
21
21
 
22
22
  React.useEffect(() => {
23
23
  onChange(debouncedValue);
24
- }, [debouncedValue]);
24
+ }, [debouncedValue, onChange]);
25
25
 
26
26
  return (
27
27
  <Input
28
28
  leadingIcon={loading ? 'loading' : 'search'}
29
- value={text}
29
+ defaultValue={text}
30
30
  onChange={(e) => {
31
31
  return setText(e.target.value);
32
32
  }}
@@ -0,0 +1,36 @@
1
+ import { Box, BoxProps } from '@ttoss/ui';
2
+
3
+ // eslint-disable-next-line react-refresh/only-export-components
4
+ export * from '@tanstack/react-table';
5
+
6
+ export const Table = (props: BoxProps) => {
7
+ return <Box as="table" {...props} />;
8
+ };
9
+
10
+ export const TableHead = (props: BoxProps) => {
11
+ return <Box as="thead" {...props} />;
12
+ };
13
+
14
+ export const TableBody = (props: BoxProps) => {
15
+ return <Box as="tbody" {...props} />;
16
+ };
17
+
18
+ export const TableRow = (props: BoxProps) => {
19
+ return <Box as="tr" {...props} />;
20
+ };
21
+
22
+ export const TableCell = (props: BoxProps) => {
23
+ return <Box as="td" {...props} />;
24
+ };
25
+
26
+ export const TableHeader = (props: BoxProps) => {
27
+ return <Box as="th" {...props} />;
28
+ };
29
+
30
+ export const TableCaption = (props: BoxProps) => {
31
+ return <Box as="caption" {...props} />;
32
+ };
33
+
34
+ export const TableFooter = (props: BoxProps) => {
35
+ return <Box as="tfoot" {...props} />;
36
+ };