@wallarm-org/design-system 1.22.0 → 1.22.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/dist/components/SettingsHeader/SettingsHeaderBreadcrumbs.js +1 -1
- package/dist/components/SettingsHeader/SettingsHeaderHeading.js +1 -1
- package/dist/components/Switch/SwitchControl.js +1 -1
- package/dist/components/Table/StickyGroupParent.js +1 -1
- package/dist/components/Table/TableMasterCellActions.js +2 -1
- package/dist/components/Table/TableRow.js +1 -1
- package/dist/components/Table/classes.js +1 -1
- package/dist/components/Table/hooks/useMasterCell.d.ts +2 -1
- package/dist/components/Table/hooks/useMasterCell.js +2 -1
- package/dist/components/Table/mocks.d.ts +1 -0
- package/dist/components/Table/mocks.js +33 -10
- package/dist/metadata/components.json +9 -4
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ const SettingsHeaderBreadcrumbs = ({ ref, children, className, ...props })=>{
|
|
|
8
8
|
ref: ref,
|
|
9
9
|
"data-testid": testId,
|
|
10
10
|
"data-slot": "settings-header-breadcrumbs",
|
|
11
|
-
className: cn(className),
|
|
11
|
+
className: cn('ml-[-4px]', className),
|
|
12
12
|
children: children
|
|
13
13
|
});
|
|
14
14
|
};
|
|
@@ -8,7 +8,7 @@ const SettingsHeaderHeading = ({ ref, children, className, ...props })=>{
|
|
|
8
8
|
ref: ref,
|
|
9
9
|
"data-testid": testId,
|
|
10
10
|
"data-slot": "settings-header-heading",
|
|
11
|
-
className: cn('flex items-
|
|
11
|
+
className: cn('flex items-center justify-between gap-16 w-full', className),
|
|
12
12
|
children: children
|
|
13
13
|
});
|
|
14
14
|
};
|
|
@@ -21,7 +21,7 @@ const SwitchControl = ()=>{
|
|
|
21
21
|
className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 text-white pointer-events-none z-0"
|
|
22
22
|
}),
|
|
23
23
|
/*#__PURE__*/ jsx(Switch.Thumb, {
|
|
24
|
-
className: cn('w-16 h-12', 'bg-icon-primary-alt rounded-4 shadow-sm transition-all relative z-
|
|
24
|
+
className: cn('w-16 h-12', 'bg-icon-primary-alt rounded-4 shadow-sm transition-all relative z-[9]', 'translate-x-4', 'data-[state=checked]:translate-x-14')
|
|
25
25
|
})
|
|
26
26
|
]
|
|
27
27
|
});
|
|
@@ -104,7 +104,7 @@ const StickyGroupParent = ({ tableWidth, headerHeight })=>{
|
|
|
104
104
|
disablePinnedShadow: true
|
|
105
105
|
}),
|
|
106
106
|
dataCells.slice(1).map((cell)=>/*#__PURE__*/ jsx(Td, {
|
|
107
|
-
className: cn('border-b border-border-primary-light bg-bg-surface-2 overlay', 'group-hover/row:overlay-states-primary-hover group-data-[selected]/row:overlay-states-primary-active'),
|
|
107
|
+
className: cn('border-b border-border-primary-light bg-bg-surface-2 overlay', 'group-hover/row:overlay-states-primary-hover group-data-[selected]/row:overlay-states-primary-active', 'group-data-[preview-active]/row:overlay-states-primary-hover group-has-[[data-state=open]]/row:overlay-states-primary-hover'),
|
|
108
108
|
style: {
|
|
109
109
|
width: cell.column.getSize()
|
|
110
110
|
},
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "../../utils/cn.js";
|
|
3
3
|
const TableMasterCellActions = ({ children })=>/*#__PURE__*/ jsx("div", {
|
|
4
|
-
|
|
4
|
+
"data-master-cell-action": "",
|
|
5
|
+
className: cn('shrink-0 pl-4 pr-4 flex items-center gap-2', 'opacity-0 pointer-events-none', 'group-hover/row:opacity-100 group-hover/row:pointer-events-auto', 'group-data-[selected]/row:opacity-100 group-data-[selected]/row:pointer-events-auto', 'group-data-[preview-active]/row:opacity-100 group-data-[preview-active]/row:pointer-events-auto', 'has-[[data-state=open]]:opacity-100 has-[[data-state=open]]:pointer-events-auto', '[&_[data-state=open]]:overlay [&_[data-state=open]]:overlay-states-primary-hover'),
|
|
5
6
|
children: children
|
|
6
7
|
});
|
|
7
8
|
TableMasterCellActions.displayName = 'TableMasterCellActions';
|
|
@@ -71,7 +71,7 @@ const TableRowInner = ({ row, ref, 'data-index': dataIndex })=>{
|
|
|
71
71
|
lastRow: isLastRow
|
|
72
72
|
}),
|
|
73
73
|
dataCells.slice(1).map((cell)=>/*#__PURE__*/ jsx(Td, {
|
|
74
|
-
className: cn('border-b border-border-primary-light bg-bg-surface-2 overlay', 'group-hover/row:overlay-states-primary-hover group-data-[selected]/row:overlay-states-primary-active', isLastRow && 'border-b-0'),
|
|
74
|
+
className: cn('border-b border-border-primary-light bg-bg-surface-2 overlay', 'group-hover/row:overlay-states-primary-hover group-data-[selected]/row:overlay-states-primary-active', 'group-data-[preview-active]/row:overlay-states-primary-hover group-has-[[data-state=open]]/row:overlay-states-primary-hover', isLastRow && 'border-b-0'),
|
|
75
75
|
style: {
|
|
76
76
|
width: cell.column.getSize()
|
|
77
77
|
},
|
|
@@ -38,7 +38,7 @@ const tableHeadCellVariants = cva(cn(tableCellBase, 'pl-16 pr-4 py-4 text-xs fon
|
|
|
38
38
|
dragging: false
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
|
-
const tableBodyCellVariants = cva(cn(tableCellBase, 'px-16 py-8 text-sm text-text-primary', 'bg-bg-surface-2', 'align-top', 'group-hover/row:overlay-states-primary-hover', 'group-data-[selected]/row:overlay-states-primary-active', 'group-data-[selected]/row:group-hover/row:overlay-states-primary-hover', 'group-data-[preview-active]/row:overlay-states-primary-
|
|
41
|
+
const tableBodyCellVariants = cva(cn(tableCellBase, 'px-16 py-8 text-sm text-text-primary', 'bg-bg-surface-2', 'align-top', 'group-hover/row:overlay-states-primary-hover', 'group-data-[selected]/row:overlay-states-primary-active', 'group-data-[selected]/row:group-hover/row:overlay-states-primary-hover', 'group-data-[preview-active]/row:overlay-states-primary-hover', 'group-has-[[data-state=open]]/row:overlay-states-primary-hover', '[&:has([data-state=open][data-part=context-trigger])]:ring-2', '[&:has([data-state=open][data-part=context-trigger])]:ring-inset', '[&:has([data-state=open][data-part=context-trigger])]:ring-border-strong-brand', '[&:has([data-part=context-trigger])]:p-0', '[&_[data-part=context-trigger]]:w-full', '[&_[data-part=context-trigger]]:px-16 [&_[data-part=context-trigger]]:py-8', '[&_[data-part=context-trigger]]:text-left [&_[data-part=context-trigger]]:outline-none'), {
|
|
42
42
|
variants: {
|
|
43
43
|
pinned: {
|
|
44
44
|
true: 'sticky z-10',
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MouseEvent } from 'react';
|
|
1
2
|
import type { RowData } from '@tanstack/react-table';
|
|
2
3
|
/**
|
|
3
4
|
* Encapsulates master cell click logic for a body cell.
|
|
@@ -7,7 +8,7 @@ export declare const useMasterCell: <T extends RowData>(columnId: string, rowId:
|
|
|
7
8
|
/** Master cell click is enabled */
|
|
8
9
|
isMasterTrigger: boolean;
|
|
9
10
|
/** Fire master cell click for this row */
|
|
10
|
-
handleClick: () => void;
|
|
11
|
+
handleClick: (e: MouseEvent) => void;
|
|
11
12
|
/** Tooltip text for master cell hover */
|
|
12
13
|
tooltipText: string | undefined;
|
|
13
14
|
};
|
|
@@ -4,7 +4,8 @@ const useMasterCell = (columnId, rowId)=>{
|
|
|
4
4
|
const { masterColumnId, onMasterCellClick } = useTableContext();
|
|
5
5
|
const isMasterColumn = columnId === masterColumnId;
|
|
6
6
|
const hasMasterClick = isMasterColumn && !!onMasterCellClick;
|
|
7
|
-
const handleClick = useCallback(()=>{
|
|
7
|
+
const handleClick = useCallback((e)=>{
|
|
8
|
+
if (e.target.closest('[data-master-cell-action]')) return;
|
|
8
9
|
onMasterCellClick?.(rowId);
|
|
9
10
|
}, [
|
|
10
11
|
onMasterCellClick,
|
|
@@ -12,6 +12,7 @@ import { Ip, IpAddress, IpCountry, IpProvider, sourceLabels } from "../Ip/index.
|
|
|
12
12
|
import { Link } from "../Link/index.js";
|
|
13
13
|
import { OverflowTooltip, OverflowTooltipContent, OverflowTooltipTrigger } from "../OverflowTooltip/index.js";
|
|
14
14
|
import { HStack, VStack } from "../Stack/index.js";
|
|
15
|
+
import { Switch, SwitchControl } from "../Switch/index.js";
|
|
15
16
|
import { Text } from "../Text/index.js";
|
|
16
17
|
import { createTableColumnHelper } from "./lib/index.js";
|
|
17
18
|
const securityEvents = [
|
|
@@ -36,7 +37,8 @@ const securityEvents = [
|
|
|
36
37
|
cweId: 'CWE-287',
|
|
37
38
|
lastSeen: '5 days ago',
|
|
38
39
|
endpointMethod: 'POST',
|
|
39
|
-
endpointPath: '/api/v1/payments'
|
|
40
|
+
endpointPath: '/api/v1/payments',
|
|
41
|
+
state: true
|
|
40
42
|
},
|
|
41
43
|
{
|
|
42
44
|
id: '2',
|
|
@@ -59,7 +61,8 @@ const securityEvents = [
|
|
|
59
61
|
cweId: 'CWE-416',
|
|
60
62
|
lastSeen: '6 days ago',
|
|
61
63
|
endpointMethod: 'PUT',
|
|
62
|
-
endpointPath: '/api/v1/users/profile'
|
|
64
|
+
endpointPath: '/api/v1/users/profile',
|
|
65
|
+
state: false
|
|
63
66
|
},
|
|
64
67
|
{
|
|
65
68
|
id: '3',
|
|
@@ -82,7 +85,8 @@ const securityEvents = [
|
|
|
82
85
|
cweId: 'CWE-89',
|
|
83
86
|
lastSeen: '7 days ago',
|
|
84
87
|
endpointMethod: 'GET',
|
|
85
|
-
endpointPath: '/api/v1/users/:id'
|
|
88
|
+
endpointPath: '/api/v1/users/:id',
|
|
89
|
+
state: true
|
|
86
90
|
},
|
|
87
91
|
{
|
|
88
92
|
id: '4',
|
|
@@ -105,7 +109,8 @@ const securityEvents = [
|
|
|
105
109
|
cweId: 'CWE-22',
|
|
106
110
|
lastSeen: '1 week ago',
|
|
107
111
|
endpointMethod: 'GET',
|
|
108
|
-
endpointPath: '/api/v1/errors/debug'
|
|
112
|
+
endpointPath: '/api/v1/errors/debug',
|
|
113
|
+
state: true
|
|
109
114
|
},
|
|
110
115
|
{
|
|
111
116
|
id: '5',
|
|
@@ -128,7 +133,8 @@ const securityEvents = [
|
|
|
128
133
|
cweId: 'CWE-200',
|
|
129
134
|
lastSeen: '4 days ago',
|
|
130
135
|
endpointMethod: 'POST',
|
|
131
|
-
endpointPath: '/api/v1/auth/login'
|
|
136
|
+
endpointPath: '/api/v1/auth/login',
|
|
137
|
+
state: false
|
|
132
138
|
},
|
|
133
139
|
{
|
|
134
140
|
id: '6',
|
|
@@ -151,7 +157,8 @@ const securityEvents = [
|
|
|
151
157
|
cweId: 'CWE-352',
|
|
152
158
|
lastSeen: '2 days ago',
|
|
153
159
|
endpointMethod: 'POST',
|
|
154
|
-
endpointPath: '/api/v1/files/upload'
|
|
160
|
+
endpointPath: '/api/v1/files/upload',
|
|
161
|
+
state: true
|
|
155
162
|
},
|
|
156
163
|
{
|
|
157
164
|
id: '7',
|
|
@@ -174,7 +181,8 @@ const securityEvents = [
|
|
|
174
181
|
cweId: 'CWE-125',
|
|
175
182
|
lastSeen: '3 days ago',
|
|
176
183
|
endpointMethod: 'GET',
|
|
177
|
-
endpointPath: '/api/v1/images/proxy'
|
|
184
|
+
endpointPath: '/api/v1/images/proxy',
|
|
185
|
+
state: false
|
|
178
186
|
},
|
|
179
187
|
{
|
|
180
188
|
id: '8',
|
|
@@ -197,7 +205,8 @@ const securityEvents = [
|
|
|
197
205
|
cweId: 'CWE-134',
|
|
198
206
|
lastSeen: '4 days ago',
|
|
199
207
|
endpointMethod: 'GET',
|
|
200
|
-
endpointPath: '/api/v1/auth/redirect'
|
|
208
|
+
endpointPath: '/api/v1/auth/redirect',
|
|
209
|
+
state: true
|
|
201
210
|
},
|
|
202
211
|
{
|
|
203
212
|
id: '9',
|
|
@@ -220,7 +229,8 @@ const securityEvents = [
|
|
|
220
229
|
cweId: 'CWE-79',
|
|
221
230
|
lastSeen: '1 day ago',
|
|
222
231
|
endpointMethod: 'DELETE',
|
|
223
|
-
endpointPath: '/api/v1/users/:id'
|
|
232
|
+
endpointPath: '/api/v1/users/:id',
|
|
233
|
+
state: false
|
|
224
234
|
},
|
|
225
235
|
{
|
|
226
236
|
id: '10',
|
|
@@ -243,7 +253,8 @@ const securityEvents = [
|
|
|
243
253
|
cweId: 'CWE-89',
|
|
244
254
|
lastSeen: '3 days ago',
|
|
245
255
|
endpointMethod: 'PATCH',
|
|
246
|
-
endpointPath: '/api/v1/content'
|
|
256
|
+
endpointPath: '/api/v1/content',
|
|
257
|
+
state: true
|
|
247
258
|
}
|
|
248
259
|
];
|
|
249
260
|
const securityColumnHelper = createTableColumnHelper();
|
|
@@ -274,6 +285,14 @@ const securityColumns = [
|
|
|
274
285
|
]
|
|
275
286
|
})
|
|
276
287
|
}),
|
|
288
|
+
securityColumnHelper.accessor('state', {
|
|
289
|
+
header: 'State',
|
|
290
|
+
size: 100,
|
|
291
|
+
cell: ({ getValue })=>/*#__PURE__*/ jsx(Switch, {
|
|
292
|
+
checked: getValue(),
|
|
293
|
+
children: /*#__PURE__*/ jsx(SwitchControl, {})
|
|
294
|
+
})
|
|
295
|
+
}),
|
|
277
296
|
securityColumnHelper.accessor('requests', {
|
|
278
297
|
header: 'Requests',
|
|
279
298
|
size: 160,
|
|
@@ -671,6 +690,10 @@ const SecurityPreviewContent = ({ row })=>/*#__PURE__*/ jsxs(VStack, {
|
|
|
671
690
|
size: "medium",
|
|
672
691
|
children: row.original.status
|
|
673
692
|
}),
|
|
693
|
+
/*#__PURE__*/ jsx(Switch, {
|
|
694
|
+
checked: row.original.state,
|
|
695
|
+
children: /*#__PURE__*/ jsx(SwitchControl, {})
|
|
696
|
+
}),
|
|
674
697
|
/*#__PURE__*/ jsx(InlineCodeSnippet, {
|
|
675
698
|
code: row.original.parameter,
|
|
676
699
|
size: "sm",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
3
|
-
"generatedAt": "2026-09-
|
|
2
|
+
"version": "1.22.0",
|
|
3
|
+
"generatedAt": "2026-09-22T02:19:24.344Z",
|
|
4
4
|
"components": [
|
|
5
5
|
{
|
|
6
6
|
"name": "Accordion",
|
|
@@ -65577,7 +65577,7 @@
|
|
|
65577
65577
|
"examples": [
|
|
65578
65578
|
{
|
|
65579
65579
|
"name": "Full",
|
|
65580
|
-
"code": "() => {\n const [search, setSearch] = useState('');\n\n return (\n <SettingsHeader>\n <SettingsHeaderBreadcrumbs>\n <Breadcrumbs>\n <BreadcrumbsItem href='/settings'>Settings</BreadcrumbsItem>\n <BreadcrumbsItem>Service accounts</BreadcrumbsItem>\n </Breadcrumbs>\n </SettingsHeaderBreadcrumbs>\n\n <SettingsHeaderHeading>\n <div className='flex flex-col'>\n <SettingsHeaderTitle>Service accounts</SettingsHeaderTitle>\n <SettingsHeaderDescription>\n Identities for automation and API access — they sign in with keys or tokens instead of a\n password.\n </SettingsHeaderDescription>\n </div>\n <SettingsHeaderActions>\n <Button variant='primary' color='brand'>\n Create service account\n </Button>\n </SettingsHeaderActions>\n </SettingsHeaderHeading>\n\n <SettingsHeaderFilters>\n <SearchInput\n value={search}\n onChange={setSearch}\n placeholder='Search name'\n className='w-[320px]'\n />\n <SegmentedTabs defaultValue='all'>\n <SegmentedTabsList>\n <SegmentedTabsTrigger value='all'>\n All <NumericBadge>1</NumericBadge>\n </SegmentedTabsTrigger>\n <SegmentedTabsTrigger value='active'>\n Active <NumericBadge>1</NumericBadge>\n </SegmentedTabsTrigger>\n <SegmentedTabsTrigger value='deactivated'>\n Deactivated <NumericBadge>1</NumericBadge>\n </SegmentedTabsTrigger>\n </SegmentedTabsList>\n </SegmentedTabs>\n </SettingsHeaderFilters>\n </SettingsHeader>\n );\n}",
|
|
65580
|
+
"code": "() => {\n const [search, setSearch] = useState('');\n\n return (\n <SettingsHeader>\n <SettingsHeaderBreadcrumbs>\n <Breadcrumbs>\n <BreadcrumbsItem href='/settings'>Settings</BreadcrumbsItem>\n <BreadcrumbsItem>Service accounts</BreadcrumbsItem>\n </Breadcrumbs>\n </SettingsHeaderBreadcrumbs>\n\n <SettingsHeaderHeading>\n <div className='flex flex-col'>\n <SettingsHeaderTitle>Service accounts</SettingsHeaderTitle>\n <SettingsHeaderDescription>\n Identities for automation and API access — they sign in with keys or tokens instead of a\n password.\n </SettingsHeaderDescription>\n </div>\n <SettingsHeaderActions>\n <Button size='medium' variant='primary' color='brand'>\n Create service account\n </Button>\n </SettingsHeaderActions>\n </SettingsHeaderHeading>\n\n <SettingsHeaderFilters>\n <SearchInput\n value={search}\n onChange={setSearch}\n placeholder='Search name'\n className='w-[320px]'\n />\n <SegmentedTabs defaultValue='all'>\n <SegmentedTabsList>\n <SegmentedTabsTrigger value='all'>\n All <NumericBadge>1</NumericBadge>\n </SegmentedTabsTrigger>\n <SegmentedTabsTrigger value='active'>\n Active <NumericBadge>1</NumericBadge>\n </SegmentedTabsTrigger>\n <SegmentedTabsTrigger value='deactivated'>\n Deactivated <NumericBadge>1</NumericBadge>\n </SegmentedTabsTrigger>\n </SegmentedTabsList>\n </SegmentedTabs>\n </SettingsHeaderFilters>\n </SettingsHeader>\n );\n}",
|
|
65581
65581
|
"description": "All three rows: breadcrumbs, heading with description and action, and a filter bar with search and segmented tabs."
|
|
65582
65582
|
},
|
|
65583
65583
|
{
|
|
@@ -65587,7 +65587,7 @@
|
|
|
65587
65587
|
},
|
|
65588
65588
|
{
|
|
65589
65589
|
"name": "WithBreadcrumbsAndActions",
|
|
65590
|
-
"code": "() => (\n <SettingsHeader>\n <SettingsHeaderBreadcrumbs>\n <Breadcrumbs>\n <BreadcrumbsItem href='/settings'>Settings</BreadcrumbsItem>\n <BreadcrumbsItem>Integrations</BreadcrumbsItem>\n </Breadcrumbs>\n </SettingsHeaderBreadcrumbs>\n\n <SettingsHeaderHeading>\n <div className='flex flex-col'>\n <SettingsHeaderTitle>Integrations</SettingsHeaderTitle>\n <SettingsHeaderDescription>\n Connect third-party services to your workspace.\n </SettingsHeaderDescription>\n </div>\n <SettingsHeaderActions>\n <Button
|
|
65590
|
+
"code": "() => (\n <SettingsHeader>\n <SettingsHeaderBreadcrumbs>\n <Breadcrumbs>\n <BreadcrumbsItem href='/settings'>Settings</BreadcrumbsItem>\n <BreadcrumbsItem>Integrations</BreadcrumbsItem>\n </Breadcrumbs>\n </SettingsHeaderBreadcrumbs>\n\n <SettingsHeaderHeading>\n <div className='flex flex-col'>\n <SettingsHeaderTitle>Integrations</SettingsHeaderTitle>\n <SettingsHeaderDescription>\n Connect third-party services to your workspace.\n </SettingsHeaderDescription>\n </div>\n <SettingsHeaderActions>\n <Button size='medium' variant='primary' color='brand'>\n Add integration\n </Button>\n </SettingsHeaderActions>\n </SettingsHeaderHeading>\n </SettingsHeader>\n)",
|
|
65591
65591
|
"description": "Breadcrumbs, heading with multiple action buttons, no filter bar."
|
|
65592
65592
|
},
|
|
65593
65593
|
{
|
|
@@ -88889,6 +88889,11 @@
|
|
|
88889
88889
|
"code": "() => {\n const [sorting, setSorting] = useState<TableSortingState>([]);\n const [activeRowId, setActiveRowId] = useState<string | null>(null);\n\n const data = useMemo(\n () =>\n Array.from({ length: 4 }, (_, batch) =>\n securityEvents.map(row => ({\n ...row,\n id: `${row.id}-${batch}`,\n objectName: batch === 0 ? row.objectName : `${row.objectName} (${batch + 1})`,\n })),\n ).flat(),\n [],\n );\n\n const columns = useMemo<TableColumnDef<SecurityEvent>[]>(\n () =>\n securityColumns.map((col, i) =>\n i === 0\n ? {\n ...col,\n cell: ({ row }: { row: { original: SecurityEvent } }) => (\n <Text size='xs'>{row.original.objectName}</Text>\n ),\n }\n : col,\n ),\n [],\n );\n\n const handleMasterCellClick = useCallback((rowId: string) => {\n setActiveRowId(prev => (prev === rowId ? null : rowId));\n }, []);\n\n const activeRow = useMemo(() => data.find(d => d.id === activeRowId), [data, activeRowId]);\n\n return (\n <>\n <Table\n className='max-w-920'\n data={data}\n columns={columns}\n getRowId={row => row.id}\n sorting={sorting}\n onSortingChange={setSorting}\n onMasterCellClick={handleMasterCellClick}\n activeRowId={activeRowId}\n />\n <Drawer\n open={!!activeRow}\n onOpenChange={open => {\n if (!open) setActiveRowId(null);\n }}\n modal={false}\n overlay={false}\n closeOnOutsideClick={false}\n width={960}\n >\n <DrawerContent>\n {activeRow ? (\n renderSecurityPreviewHeader({ original: activeRow })\n ) : (\n <DrawerHeader>\n <span />\n </DrawerHeader>\n )}\n <DrawerBody>\n {activeRow && renderSecurityPreviewContent({ original: activeRow })}\n </DrawerBody>\n </DrawerContent>\n </Drawer>\n </>\n );\n}",
|
|
88890
88890
|
"description": "`onMasterCellClick` with `activeRowId`: the master cell opens a `Drawer` and the row it\nbelongs to stays marked while the panel is open."
|
|
88891
88891
|
},
|
|
88892
|
+
{
|
|
88893
|
+
"name": "MasterCellWithActionsAndDrawer",
|
|
88894
|
+
"code": "() => {\n const [sorting, setSorting] = useState<TableSortingState>([]);\n const [activeRowId, setActiveRowId] = useState<string | null>(null);\n\n const data = useMemo(() => multiplySecurityEvents(), []);\n\n const columns = useMemo<TableColumnDef<SecurityEvent>[]>(\n () =>\n securityColumns.map((col, i) =>\n i === 0\n ? {\n ...col,\n cell: ({ row }: { row: { original: SecurityEvent } }) => (\n <Text size='xs'>{row.original.objectName}</Text>\n ),\n meta: {\n ...col.meta,\n resizeType: 'resize',\n renderMenuAction: (row: { original: SecurityEvent }) => (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant='ghost' color='neutral' size='small' aria-label='More'>\n <Ellipsis />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent>\n <DropdownMenuItem\n onSelect={() => navigator.clipboard.writeText(row.original.objectName)}\n >\n <DropdownMenuItemIcon>\n <Copy />\n </DropdownMenuItemIcon>\n <DropdownMenuItemText>Copy name</DropdownMenuItemText>\n </DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem onSelect={() => onShowOnly(row.original.objectName)}>\n <DropdownMenuItemIcon>\n <Filter />\n </DropdownMenuItemIcon>\n <DropdownMenuItemText>Show only</DropdownMenuItemText>\n </DropdownMenuItem>\n <DropdownMenuItem onSelect={() => onExclude(row.original.objectName)}>\n <DropdownMenuItemIcon>\n <FilterX />\n </DropdownMenuItemIcon>\n <DropdownMenuItemText>Exclude</DropdownMenuItemText>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ),\n },\n }\n : col,\n ),\n [],\n );\n\n const handleMasterCellClick = useCallback((rowId: string) => {\n setActiveRowId(prev => (prev === rowId ? null : rowId));\n }, []);\n\n const activeRow = useMemo(() => data.find(d => d.id === activeRowId), [data, activeRowId]);\n\n return (\n <>\n <Table\n className='max-w-920'\n data={data}\n columns={columns}\n getRowId={row => row.id}\n sorting={sorting}\n onSortingChange={setSorting}\n onMasterCellClick={handleMasterCellClick}\n activeRowId={activeRowId}\n />\n <Drawer\n open={!!activeRow}\n onOpenChange={open => {\n if (!open) setActiveRowId(null);\n }}\n modal={false}\n overlay={false}\n closeOnOutsideClick={false}\n width={960}\n >\n <DrawerContent>\n {activeRow ? (\n renderSecurityPreviewHeader({ original: activeRow })\n ) : (\n <DrawerHeader>\n <span />\n </DrawerHeader>\n )}\n <DrawerBody>\n {activeRow && renderSecurityPreviewContent({ original: activeRow })}\n </DrawerBody>\n </DrawerContent>\n </Drawer>\n </>\n );\n}",
|
|
88895
|
+
"description": "Master cell with both an action menu and a drawer:\nclicking the cell body opens the drawer, clicking the action button opens the menu\nwithout triggering the drawer."
|
|
88896
|
+
},
|
|
88892
88897
|
{
|
|
88893
88898
|
"name": "FullFeatured",
|
|
88894
88899
|
"code": "() => {\n const data = useMemo(() => createLargeGroupedData(12, 50), []);\n\n const [sorting, setSorting] = useState<TableSortingState>([{ id: 'lastEdited', desc: true }]);\n const [rowSelection, setRowSelection] = useState<TableRowSelectionState>({});\n const [columnSizing, setColumnSizing] = useState<TableColumnSizingState>({});\n const [columnPinning, setColumnPinning] = useState<TableColumnPinningState>({\n left: ['objectName'],\n });\n const [columnOrder, setColumnOrder] = useState<string[]>([]);\n const [columnVisibility, setColumnVisibility] = useState<TableVisibilityState>({});\n const [expanded, setExpanded] = useState<TableExpandedState>({\n 'group-0': true,\n 'group-1': true,\n });\n\n return (\n <Table<SecurityHeaderEntry>\n className='h-500'\n data={data}\n columns={fullFeaturedColumns}\n getRowId={row => row.id}\n getSubRows={row => row.children}\n // Grouping\n expanded={expanded}\n onExpandedChange={setExpanded}\n // Sorting\n sorting={sorting}\n onSortingChange={setSorting}\n // Row selection\n rowSelection={rowSelection}\n onRowSelectionChange={setRowSelection}\n // Column resizing\n columnSizing={columnSizing}\n onColumnSizingChange={setColumnSizing}\n // Column pinning\n columnPinning={columnPinning}\n onColumnPinningChange={setColumnPinning}\n // Column DnD ordering\n columnOrder={columnOrder}\n onColumnOrderChange={setColumnOrder}\n // Column visibility + settings\n columnVisibility={columnVisibility}\n onColumnVisibilityChange={setColumnVisibility}\n defaultColumnVisibility={{}}\n defaultColumnOrder={headerColumnIds}\n // Virtual scrolling\n virtualized='container'\n >\n <TableActionBar>\n <Button variant='ghost' color='neutral-alt' onClick={onDuplicate}>\n <Copy /> Duplicate\n </Button>\n <Button color='brand' onClick={onDelete}>\n <Trash2 /> Delete\n </Button>\n </TableActionBar>\n </Table>\n );\n}",
|