@ceed/ads 1.20.2 → 1.22.0-next.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 +157 -0
- package/dist/components/DataTable/hooks.d.ts +11 -1
- package/dist/components/ProfileMenu/ProfileMenu.d.ts +1 -1
- package/dist/components/data-display/DataTable.md +71 -1
- package/dist/index.browser.js +237 -0
- package/dist/index.browser.js.map +7 -0
- package/dist/index.cjs +161 -17
- package/dist/index.js +161 -17
- package/framer/index.js +37 -37
- package/package.json +12 -3
package/README.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# @ceed/ads
|
|
2
|
+
|
|
3
|
+
Admin Design System - A React component library for Ecube Labs admin applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @ceed/ads
|
|
9
|
+
# or
|
|
10
|
+
yarn add @ceed/ads
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### With Bundler (Vite, Webpack, etc.)
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import { Button, ThemeProvider } from '@ceed/ads';
|
|
19
|
+
|
|
20
|
+
function App() {
|
|
21
|
+
return (
|
|
22
|
+
<ThemeProvider>
|
|
23
|
+
<Button variant="solid">Click me</Button>
|
|
24
|
+
</ThemeProvider>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Browser ESM (via CDN)
|
|
30
|
+
|
|
31
|
+
You can use `@ceed/ads` directly in the browser without a bundler via [esm.sh](https://esm.sh).
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<!DOCTYPE html>
|
|
35
|
+
<html>
|
|
36
|
+
<head>
|
|
37
|
+
<meta charset="UTF-8">
|
|
38
|
+
<title>@ceed/ads Browser Example</title>
|
|
39
|
+
</head>
|
|
40
|
+
<body>
|
|
41
|
+
<div id="root"></div>
|
|
42
|
+
|
|
43
|
+
<script type="module">
|
|
44
|
+
import React from 'https://esm.sh/react@18';
|
|
45
|
+
import { createRoot } from 'https://esm.sh/react-dom@18/client';
|
|
46
|
+
import { Button, ThemeProvider } from 'https://esm.sh/@ceed/ads';
|
|
47
|
+
|
|
48
|
+
const App = () => (
|
|
49
|
+
React.createElement(ThemeProvider, null,
|
|
50
|
+
React.createElement(Button, { variant: 'solid' }, 'Hello from CDN!')
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
createRoot(document.getElementById('root')).render(
|
|
55
|
+
React.createElement(App)
|
|
56
|
+
);
|
|
57
|
+
</script>
|
|
58
|
+
</body>
|
|
59
|
+
</html>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
#### With Import Maps
|
|
63
|
+
|
|
64
|
+
For cleaner imports, use [Import Maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap):
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<!DOCTYPE html>
|
|
68
|
+
<html>
|
|
69
|
+
<head>
|
|
70
|
+
<meta charset="UTF-8">
|
|
71
|
+
<title>@ceed/ads with Import Maps</title>
|
|
72
|
+
</head>
|
|
73
|
+
<body>
|
|
74
|
+
<div id="root"></div>
|
|
75
|
+
|
|
76
|
+
<script type="importmap">
|
|
77
|
+
{
|
|
78
|
+
"imports": {
|
|
79
|
+
"react": "https://esm.sh/react@18",
|
|
80
|
+
"react/jsx-runtime": "https://esm.sh/react@18/jsx-runtime",
|
|
81
|
+
"react-dom/client": "https://esm.sh/react-dom@18/client",
|
|
82
|
+
"@ceed/ads": "https://esm.sh/@ceed/ads"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<script type="module">
|
|
88
|
+
import React from 'react';
|
|
89
|
+
import { createRoot } from 'react-dom/client';
|
|
90
|
+
import { Button, ThemeProvider } from '@ceed/ads';
|
|
91
|
+
|
|
92
|
+
const App = () => (
|
|
93
|
+
React.createElement(ThemeProvider, null,
|
|
94
|
+
React.createElement(Button, { variant: 'solid' }, 'Hello from CDN!')
|
|
95
|
+
)
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
createRoot(document.getElementById('root')).render(
|
|
99
|
+
React.createElement(App)
|
|
100
|
+
);
|
|
101
|
+
</script>
|
|
102
|
+
</body>
|
|
103
|
+
</html>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
#### With JSX (using esm.sh)
|
|
107
|
+
|
|
108
|
+
esm.sh supports JSX transformation via the `?jsx-runtime=automatic` parameter:
|
|
109
|
+
|
|
110
|
+
```html
|
|
111
|
+
<!DOCTYPE html>
|
|
112
|
+
<html>
|
|
113
|
+
<head>
|
|
114
|
+
<meta charset="UTF-8">
|
|
115
|
+
<title>@ceed/ads with JSX</title>
|
|
116
|
+
</head>
|
|
117
|
+
<body>
|
|
118
|
+
<div id="root"></div>
|
|
119
|
+
|
|
120
|
+
<script type="importmap">
|
|
121
|
+
{
|
|
122
|
+
"imports": {
|
|
123
|
+
"react": "https://esm.sh/react@18",
|
|
124
|
+
"react/jsx-runtime": "https://esm.sh/react@18/jsx-runtime",
|
|
125
|
+
"react-dom/client": "https://esm.sh/react-dom@18/client",
|
|
126
|
+
"@ceed/ads": "https://esm.sh/@ceed/ads"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
</script>
|
|
130
|
+
|
|
131
|
+
<script type="module">
|
|
132
|
+
import { createRoot } from 'react-dom/client';
|
|
133
|
+
import { jsx } from 'react/jsx-runtime';
|
|
134
|
+
import { Button, Stack, ThemeProvider } from '@ceed/ads';
|
|
135
|
+
|
|
136
|
+
const App = () =>
|
|
137
|
+
jsx(ThemeProvider, {
|
|
138
|
+
children: jsx(Stack, {
|
|
139
|
+
spacing: 2,
|
|
140
|
+
children: [
|
|
141
|
+
jsx(Button, { variant: 'solid', children: 'Solid' }),
|
|
142
|
+
jsx(Button, { variant: 'outlined', children: 'Outlined' }),
|
|
143
|
+
jsx(Button, { variant: 'soft', children: 'Soft' }),
|
|
144
|
+
],
|
|
145
|
+
}),
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
createRoot(document.getElementById('root')).render(jsx(App, {}));
|
|
149
|
+
</script>
|
|
150
|
+
</body>
|
|
151
|
+
</html>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Documentation
|
|
155
|
+
|
|
156
|
+
- [Storybook](https://main--66da7aaaf87fb0b864d6afca.chromatic.com)
|
|
157
|
+
- [Confluence](https://ecubelabs.atlassian.net/wiki/spaces/HP/pages/3256123430/Design+System)
|
|
@@ -45,7 +45,7 @@ export declare function useDataTableRenderer<T extends Record<PropertyKey, unkno
|
|
|
45
45
|
focusedRowId: InferredIdType<T, GetId> | null;
|
|
46
46
|
onRowFocus: (rowId: InferredIdType<T, GetId>) => void;
|
|
47
47
|
onAllCheckboxChange: () => void;
|
|
48
|
-
onCheckboxChange: (event:
|
|
48
|
+
onCheckboxChange: (event: React.MouseEvent | React.ChangeEvent | React.KeyboardEvent, selectedModel: InferredIdType<T, GetId>) => void;
|
|
49
49
|
columns: ColumnDef<T, InferredIdType<T, GetId>>[];
|
|
50
50
|
processedColumnGroups: {
|
|
51
51
|
groups: import("./types").ProcessedColumnGroup[][];
|
|
@@ -53,4 +53,14 @@ export declare function useDataTableRenderer<T extends Record<PropertyKey, unkno
|
|
|
53
53
|
fieldsInGroupingModel: Set<keyof T>;
|
|
54
54
|
} | null;
|
|
55
55
|
onTotalSelect: () => void;
|
|
56
|
+
selectionAnchor: {
|
|
57
|
+
rowId: InferredIdType<T, GetId>;
|
|
58
|
+
rowIndex: number;
|
|
59
|
+
wasSelected: boolean;
|
|
60
|
+
} | null;
|
|
61
|
+
setSelectionAnchor: import("react").Dispatch<import("react").SetStateAction<{
|
|
62
|
+
rowId: InferredIdType<T, GetId>;
|
|
63
|
+
rowIndex: number;
|
|
64
|
+
wasSelected: boolean;
|
|
65
|
+
} | null>>;
|
|
56
66
|
};
|
|
@@ -377,12 +377,82 @@ const [selectionModel, setSelectionModel] = useState<string[]>([]);
|
|
|
377
377
|
/>;
|
|
378
378
|
```
|
|
379
379
|
|
|
380
|
+
## Keyboard Accessibility
|
|
381
|
+
|
|
382
|
+
DataTable supports keyboard interactions for improved accessibility.
|
|
383
|
+
|
|
384
|
+
### Shift+Click Range Selection
|
|
385
|
+
|
|
386
|
+
Hold the Shift key while clicking checkboxes to select or deselect a range of rows at once.
|
|
387
|
+
The selection state is applied based on the last clicked checkbox's resulting state.
|
|
388
|
+
|
|
389
|
+
```tsx
|
|
390
|
+
<Stack spacing={2}>
|
|
391
|
+
<Typography level="body-sm">
|
|
392
|
+
Hold Shift and click checkboxes to select a range of rows. The selection state is applied based on the first
|
|
393
|
+
clicked checkbox's resulting state.
|
|
394
|
+
</Typography>
|
|
395
|
+
<DataTable {...args} selectionModel={selectionModel} onSelectionModelChange={setSelectionModel} />
|
|
396
|
+
<Typography level="body-xs">Selected IDs: {selectionModel.join(', ') || 'None'}</Typography>
|
|
397
|
+
</Stack>
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
**How it works:**
|
|
401
|
+
|
|
402
|
+
1. Click a checkbox to select/deselect a row (this becomes the "anchor")
|
|
403
|
+
2. Hold Shift and click another checkbox
|
|
404
|
+
3. All rows between the anchor and the clicked row will be set to the same state
|
|
405
|
+
|
|
406
|
+
**Edge cases handled:**
|
|
407
|
+
|
|
408
|
+
- Works seamlessly with virtual scrolling (rows don't need to be visible)
|
|
409
|
+
- Selection anchor resets when data changes or page changes
|
|
410
|
+
- Respects `isRowSelectable` - non-selectable rows are skipped in range
|
|
411
|
+
|
|
412
|
+
### Keyboard Navigation
|
|
413
|
+
|
|
414
|
+
When a row has focus, use keyboard shortcuts to navigate and interact with rows.
|
|
415
|
+
|
|
416
|
+
```tsx
|
|
417
|
+
<Stack spacing={2}>
|
|
418
|
+
<Typography level="body-sm">
|
|
419
|
+
Click a row to focus, then use keyboard to navigate. Arrow Up/Down to move, Space to toggle selection,
|
|
420
|
+
Home/End to jump to first/last row, PageUp/PageDown to move by 10 rows. Hold Shift with any navigation key to
|
|
421
|
+
extend selection.
|
|
422
|
+
</Typography>
|
|
423
|
+
<DataTable {...args} selectionModel={selectionModel} onSelectionModelChange={setSelectionModel} />
|
|
424
|
+
<Typography level="body-xs">Selected IDs: {selectionModel.join(', ') || 'None'}</Typography>
|
|
425
|
+
</Stack>
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
**Supported keys:**
|
|
429
|
+
|
|
430
|
+
| Key | Action |
|
|
431
|
+
| ---------------------- | ------------------------------------------- |
|
|
432
|
+
| `↑` Arrow Up | Move focus to previous row |
|
|
433
|
+
| `↓` Arrow Down | Move focus to next row |
|
|
434
|
+
| `Space` | Toggle checkbox selection |
|
|
435
|
+
| `Home` | Move focus to first row |
|
|
436
|
+
| `End` | Move focus to last row |
|
|
437
|
+
| `Page Up` | Move focus up by 10 rows |
|
|
438
|
+
| `Page Down` | Move focus down by 10 rows |
|
|
439
|
+
| `Shift + ↑/↓` | Move focus and extend selection |
|
|
440
|
+
| `Shift + Home/End` | Jump to first/last row and extend selection |
|
|
441
|
+
| `Shift + Page Up/Down` | Move by 10 rows and extend selection |
|
|
442
|
+
|
|
443
|
+
**Notes:**
|
|
444
|
+
|
|
445
|
+
- Click any row first to establish focus
|
|
446
|
+
- Tab key skips checkboxes and moves directly between rows
|
|
447
|
+
- Works with virtual scrolling - target row is automatically scrolled into view
|
|
448
|
+
- Follows WAI-ARIA Grid pattern for accessibility
|
|
449
|
+
|
|
380
450
|
## Styles and Layout
|
|
381
451
|
|
|
382
452
|
### Back Office Style
|
|
383
453
|
|
|
384
454
|
```tsx
|
|
385
|
-
<DataTable rows={args.rows} columns={args.columns} checkboxSelection={args.checkboxSelection} hoverRow={args.hoverRow} noWrap={args.noWrap} stripe={args.stripe} stickyHeader={args.stickyHeader} slots={args.slots} slotProps={args.slotProps} selectionModel={selectionModel} onSelectionModelChange={setSelectionModel} />
|
|
455
|
+
<DataTable rows={args.rows} columns={args.columns} checkboxSelection={args.checkboxSelection} hoverRow={args.hoverRow} noWrap={args.noWrap} stripe={args.stripe} stickyHeader={args.stickyHeader} slots={args.slots} slotProps={args.slotProps} selectionModel={selectionModel} onSelectionModelChange={setSelectionModel} pagination={args.pagination} />
|
|
386
456
|
```
|
|
387
457
|
|
|
388
458
|
#### Commonly Used Table Options
|