@wallarm-org/design-system 0.49.0 → 0.50.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.
- package/dist/components/Drawer/DrawerResizeHandle.js +2 -0
- package/dist/components/OverflowList/OverflowList.helpers.d.ts +30 -0
- package/dist/components/OverflowList/OverflowList.helpers.js +16 -0
- package/dist/components/OverflowList/OverflowList.js +33 -28
- package/dist/components/Select/SelectSeparator.d.ts +5 -2
- package/dist/components/Select/SelectSeparator.js +9 -4
- package/dist/components/Select/index.d.ts +1 -1
- package/dist/components/Table/TableResizeHandler.js +1 -0
- package/dist/components/Table/mocks.js +40 -10
- package/dist/hooks/useOverflowItems.helpers.d.ts +15 -0
- package/dist/hooks/useOverflowItems.helpers.js +19 -0
- package/dist/hooks/useOverflowItems.js +80 -64
- package/dist/metadata/components.json +316 -4
- package/package.json +1 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Fallback width (px) reserved for the "+N" overflow indicator until the real
|
|
2
|
+
* indicator has been measured. Passed to `useOverflowItems.reserveSpace`. */
|
|
3
|
+
export declare const OVERFLOW_RESERVE_SPACE = 80;
|
|
4
|
+
/**
|
|
5
|
+
* Shallow item-by-item equality for two lists. Order-sensitive — items must
|
|
6
|
+
* match at the same index. Used to guard `onOverflow` from re-firing when the
|
|
7
|
+
* hidden set keeps a fresh array identity but the same contents. A `null`
|
|
8
|
+
* previous list is treated as "not equal".
|
|
9
|
+
*/
|
|
10
|
+
export declare function areItemsShallowEqual<T>(prev: T[] | null, next: T[]): boolean;
|
|
11
|
+
export interface ResolveVisibleItemsParams<T> {
|
|
12
|
+
/** Full source list, in order. */
|
|
13
|
+
items: T[];
|
|
14
|
+
/** Items the overflow engine decided are visible. */
|
|
15
|
+
visibleItems: T[];
|
|
16
|
+
/** Items the overflow engine collapsed into the indicator. */
|
|
17
|
+
hiddenItems: T[];
|
|
18
|
+
/** Minimum number of items to keep visible regardless of available space. */
|
|
19
|
+
minVisibleItems: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Applies the `minVisibleItems` floor to the overflow engine's output. When the
|
|
23
|
+
* engine collapses below the floor (and the list is long enough), force the
|
|
24
|
+
* first `minVisibleItems` to stay visible and recompute the hidden tail.
|
|
25
|
+
* Otherwise the engine's split is returned untouched (same references).
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolveVisibleItems<T>({ items, visibleItems, hiddenItems, minVisibleItems, }: ResolveVisibleItemsParams<T>): {
|
|
28
|
+
visibleItems: T[];
|
|
29
|
+
hiddenItems: T[];
|
|
30
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const OVERFLOW_RESERVE_SPACE = 80;
|
|
2
|
+
function areItemsShallowEqual(prev, next) {
|
|
3
|
+
if (!prev || prev.length !== next.length) return false;
|
|
4
|
+
return next.every((item, index)=>item === prev[index]);
|
|
5
|
+
}
|
|
6
|
+
function resolveVisibleItems({ items, visibleItems, hiddenItems, minVisibleItems }) {
|
|
7
|
+
if (visibleItems.length < minVisibleItems && items.length >= minVisibleItems) return {
|
|
8
|
+
visibleItems: items.slice(0, minVisibleItems),
|
|
9
|
+
hiddenItems: items.slice(minVisibleItems)
|
|
10
|
+
};
|
|
11
|
+
return {
|
|
12
|
+
visibleItems,
|
|
13
|
+
hiddenItems
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export { OVERFLOW_RESERVE_SPACE, areItemsShallowEqual, resolveVisibleItems };
|
|
@@ -1,48 +1,52 @@
|
|
|
1
1
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { memo, useCallback, useMemo } from "react";
|
|
2
|
+
import { memo, useCallback, useEffect, useMemo, useRef } from "react";
|
|
3
3
|
import { useOverflowItems } from "../../hooks/index.js";
|
|
4
4
|
import { cn } from "../../utils/cn.js";
|
|
5
|
+
import { OVERFLOW_RESERVE_SPACE, areItemsShallowEqual, resolveVisibleItems } from "./OverflowList.helpers.js";
|
|
5
6
|
const OverflowListComponent = ({ items, itemRenderer, overflowRenderer, className, collapseFrom = 'end', minVisibleItems = 0, alwaysRenderOverflow = false, onOverflow, ...props })=>{
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const indexMap = useMemo(()=>{
|
|
8
|
+
const map = new Map();
|
|
9
|
+
items.forEach((item, index)=>{
|
|
10
|
+
if (!map.has(item)) map.set(item, index);
|
|
11
|
+
});
|
|
12
|
+
return map;
|
|
9
13
|
}, [
|
|
10
|
-
items
|
|
14
|
+
items
|
|
15
|
+
]);
|
|
16
|
+
const memoizedItemRenderer = useCallback((item)=>itemRenderer(item, indexMap.get(item) ?? 0), [
|
|
17
|
+
indexMap,
|
|
11
18
|
itemRenderer
|
|
12
19
|
]);
|
|
13
|
-
const memoizedMeasurementRenderer = useCallback((item)=>
|
|
14
|
-
|
|
15
|
-
return itemRenderer(item, index);
|
|
16
|
-
}, [
|
|
17
|
-
items,
|
|
20
|
+
const memoizedMeasurementRenderer = useCallback((item)=>itemRenderer(item, indexMap.get(item) ?? 0), [
|
|
21
|
+
indexMap,
|
|
18
22
|
itemRenderer
|
|
19
23
|
]);
|
|
20
24
|
const { containerRef, visibleItems, hiddenItems, MeasurementContainer } = useOverflowItems({
|
|
21
25
|
items,
|
|
22
26
|
renderItem: memoizedMeasurementRenderer,
|
|
23
27
|
overflowRenderer: (items)=>overflowRenderer(items),
|
|
24
|
-
reserveSpace:
|
|
28
|
+
reserveSpace: OVERFLOW_RESERVE_SPACE
|
|
25
29
|
});
|
|
26
|
-
const finalVisibleItems = useMemo(()=>{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
items
|
|
33
|
-
]);
|
|
34
|
-
const finalHiddenItems = useMemo(()=>{
|
|
35
|
-
if (finalVisibleItems.length !== visibleItems.length) return items.slice(finalVisibleItems.length);
|
|
36
|
-
return hiddenItems;
|
|
37
|
-
}, [
|
|
38
|
-
finalVisibleItems.length,
|
|
39
|
-
visibleItems.length,
|
|
30
|
+
const { visibleItems: finalVisibleItems, hiddenItems: finalHiddenItems } = useMemo(()=>resolveVisibleItems({
|
|
31
|
+
items,
|
|
32
|
+
visibleItems,
|
|
33
|
+
hiddenItems,
|
|
34
|
+
minVisibleItems
|
|
35
|
+
}), [
|
|
40
36
|
items,
|
|
41
|
-
|
|
37
|
+
visibleItems,
|
|
38
|
+
hiddenItems,
|
|
39
|
+
minVisibleItems
|
|
42
40
|
]);
|
|
43
41
|
const finalHiddenCount = finalHiddenItems.length;
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
const prevHiddenRef = useRef(null);
|
|
43
|
+
useEffect(()=>{
|
|
44
|
+
if (!onOverflow || 0 === finalHiddenItems.length) {
|
|
45
|
+
prevHiddenRef.current = finalHiddenItems;
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (!areItemsShallowEqual(prevHiddenRef.current, finalHiddenItems)) onOverflow(finalHiddenItems);
|
|
49
|
+
prevHiddenRef.current = finalHiddenItems;
|
|
46
50
|
}, [
|
|
47
51
|
finalHiddenItems,
|
|
48
52
|
onOverflow
|
|
@@ -65,6 +69,7 @@ const OverflowListComponent = ({ items, itemRenderer, overflowRenderer, classNam
|
|
|
65
69
|
/*#__PURE__*/ jsx(MeasurementContainer, {}),
|
|
66
70
|
/*#__PURE__*/ jsxs("div", {
|
|
67
71
|
ref: containerRef,
|
|
72
|
+
"data-slot": "overflow-list",
|
|
68
73
|
className: cn('flex w-full min-w-0', className),
|
|
69
74
|
...props,
|
|
70
75
|
children: [
|
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
import type { FC } from 'react';
|
|
2
|
-
export
|
|
1
|
+
import type { FC, HTMLAttributes, Ref } from 'react';
|
|
2
|
+
export type SelectSeparatorProps = HTMLAttributes<HTMLHRElement> & {
|
|
3
|
+
ref?: Ref<HTMLHRElement>;
|
|
4
|
+
};
|
|
5
|
+
export declare const SelectSeparator: FC<SelectSeparatorProps>;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from "../../utils/cn.js";
|
|
2
3
|
import { useTestId } from "../../utils/testId.js";
|
|
3
|
-
|
|
4
|
-
const SelectSeparator = ()=>{
|
|
4
|
+
const SelectSeparator = ({ className, ref, ...props })=>{
|
|
5
5
|
const testId = useTestId('separator');
|
|
6
|
-
return /*#__PURE__*/ jsx(
|
|
7
|
-
|
|
6
|
+
return /*#__PURE__*/ jsx("hr", {
|
|
7
|
+
ref: ref,
|
|
8
|
+
"data-slot": "select-separator",
|
|
9
|
+
"data-testid": testId,
|
|
10
|
+
"aria-orientation": "horizontal",
|
|
11
|
+
className: cn('mx-8 my-4 h-px bg-border-primary border-none', className),
|
|
12
|
+
...props
|
|
8
13
|
});
|
|
9
14
|
};
|
|
10
15
|
SelectSeparator.displayName = 'SelectSeparator';
|
|
@@ -15,5 +15,5 @@ export { SelectOptionIndicator } from './SelectOptionIndicator';
|
|
|
15
15
|
export { SelectOptionText } from './SelectOptionText';
|
|
16
16
|
export { SelectPositioner } from './SelectPositioner';
|
|
17
17
|
export { SelectSearchInput } from './SelectSearchInput';
|
|
18
|
-
export { SelectSeparator } from './SelectSeparator';
|
|
18
|
+
export { SelectSeparator, type SelectSeparatorProps } from './SelectSeparator';
|
|
19
19
|
export type { SelectDataItem } from './types';
|
|
@@ -9,6 +9,7 @@ const TableResizeHandler = ({ header })=>{
|
|
|
9
9
|
onMouseDown: header.getResizeHandler(),
|
|
10
10
|
onTouchStart: header.getResizeHandler(),
|
|
11
11
|
className: cn(tableResizeHandlerVariants()),
|
|
12
|
+
"data-slot": "resize-handle",
|
|
12
13
|
"data-testid": testId,
|
|
13
14
|
"data-resizing": header.column.getIsResizing() || void 0,
|
|
14
15
|
tabIndex: -1
|
|
@@ -20,7 +20,10 @@ const securityEvents = [
|
|
|
20
20
|
objectName: 'Rate limiting abuse on the payment endpoint',
|
|
21
21
|
tags: [
|
|
22
22
|
'api-abuse',
|
|
23
|
-
'account-takeover'
|
|
23
|
+
'account-takeover',
|
|
24
|
+
'credential-stuffing',
|
|
25
|
+
'scanner',
|
|
26
|
+
'brute-force'
|
|
24
27
|
],
|
|
25
28
|
isActive: false,
|
|
26
29
|
requests: 22000,
|
|
@@ -40,7 +43,10 @@ const securityEvents = [
|
|
|
40
43
|
objectName: 'Mass assignment vulnerability in user profile',
|
|
41
44
|
tags: [
|
|
42
45
|
'api-abuse',
|
|
43
|
-
'account-takeover'
|
|
46
|
+
'account-takeover',
|
|
47
|
+
'credential-stuffing',
|
|
48
|
+
'scanner',
|
|
49
|
+
'brute-force'
|
|
44
50
|
],
|
|
45
51
|
isActive: false,
|
|
46
52
|
requests: 25000,
|
|
@@ -60,7 +66,10 @@ const securityEvents = [
|
|
|
60
66
|
objectName: 'Insecure direct object reference in user data',
|
|
61
67
|
tags: [
|
|
62
68
|
'api-abuse',
|
|
63
|
-
'account-takeover'
|
|
69
|
+
'account-takeover',
|
|
70
|
+
'credential-stuffing',
|
|
71
|
+
'scanner',
|
|
72
|
+
'brute-force'
|
|
64
73
|
],
|
|
65
74
|
isActive: true,
|
|
66
75
|
requests: 30000,
|
|
@@ -80,7 +89,10 @@ const securityEvents = [
|
|
|
80
89
|
objectName: 'Improper error handling leading to info leak',
|
|
81
90
|
tags: [
|
|
82
91
|
'api-abuse',
|
|
83
|
-
'account-takeover'
|
|
92
|
+
'account-takeover',
|
|
93
|
+
'credential-stuffing',
|
|
94
|
+
'scanner',
|
|
95
|
+
'brute-force'
|
|
84
96
|
],
|
|
85
97
|
isActive: true,
|
|
86
98
|
requests: 35000,
|
|
@@ -100,7 +112,10 @@ const securityEvents = [
|
|
|
100
112
|
objectName: 'Broken authentication in the login API',
|
|
101
113
|
tags: [
|
|
102
114
|
'api-abuse',
|
|
103
|
-
'account-takeover'
|
|
115
|
+
'account-takeover',
|
|
116
|
+
'credential-stuffing',
|
|
117
|
+
'scanner',
|
|
118
|
+
'brute-force'
|
|
104
119
|
],
|
|
105
120
|
isActive: true,
|
|
106
121
|
requests: 20000,
|
|
@@ -120,7 +135,10 @@ const securityEvents = [
|
|
|
120
135
|
objectName: 'Lack of resource validation in file upload',
|
|
121
136
|
tags: [
|
|
122
137
|
'api-abuse',
|
|
123
|
-
'account-takeover'
|
|
138
|
+
'account-takeover',
|
|
139
|
+
'credential-stuffing',
|
|
140
|
+
'scanner',
|
|
141
|
+
'brute-force'
|
|
124
142
|
],
|
|
125
143
|
isActive: false,
|
|
126
144
|
requests: 40000,
|
|
@@ -140,7 +158,10 @@ const securityEvents = [
|
|
|
140
158
|
objectName: 'Server-side request forgery in image proxy',
|
|
141
159
|
tags: [
|
|
142
160
|
'api-abuse',
|
|
143
|
-
'account-takeover'
|
|
161
|
+
'account-takeover',
|
|
162
|
+
'credential-stuffing',
|
|
163
|
+
'scanner',
|
|
164
|
+
'brute-force'
|
|
144
165
|
],
|
|
145
166
|
isActive: false,
|
|
146
167
|
requests: 50000,
|
|
@@ -160,7 +181,10 @@ const securityEvents = [
|
|
|
160
181
|
objectName: 'Unvalidated redirects and forwards in auth flow',
|
|
161
182
|
tags: [
|
|
162
183
|
'api-abuse',
|
|
163
|
-
'account-takeover'
|
|
184
|
+
'account-takeover',
|
|
185
|
+
'credential-stuffing',
|
|
186
|
+
'scanner',
|
|
187
|
+
'brute-force'
|
|
164
188
|
],
|
|
165
189
|
isActive: true,
|
|
166
190
|
requests: 75000,
|
|
@@ -180,7 +204,10 @@ const securityEvents = [
|
|
|
180
204
|
objectName: 'SQL injection in the user ID',
|
|
181
205
|
tags: [
|
|
182
206
|
'api-abuse',
|
|
183
|
-
'account-takeover'
|
|
207
|
+
'account-takeover',
|
|
208
|
+
'credential-stuffing',
|
|
209
|
+
'scanner',
|
|
210
|
+
'brute-force'
|
|
184
211
|
],
|
|
185
212
|
isActive: false,
|
|
186
213
|
requests: 15000,
|
|
@@ -200,7 +227,10 @@ const securityEvents = [
|
|
|
200
227
|
objectName: "Cross-site scripting in the API endpoint",
|
|
201
228
|
tags: [
|
|
202
229
|
'api-abuse',
|
|
203
|
-
'account-takeover'
|
|
230
|
+
'account-takeover',
|
|
231
|
+
'credential-stuffing',
|
|
232
|
+
'scanner',
|
|
233
|
+
'brute-force'
|
|
204
234
|
],
|
|
205
235
|
isActive: false,
|
|
206
236
|
requests: 18000,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface CalculateVisibleCountParams {
|
|
2
|
+
/** Width of each item in source order (px). */
|
|
3
|
+
itemWidths: number[];
|
|
4
|
+
/** Gap between flex children of the container (px). */
|
|
5
|
+
gap: number;
|
|
6
|
+
/** Available width of the container (px). */
|
|
7
|
+
availableWidth: number;
|
|
8
|
+
/** Measured width of the '+N' indicator (px); fallback — reserveSpace. */
|
|
9
|
+
indicatorWidth: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Pure arithmetic: how many leading items fit before an overflow indicator
|
|
13
|
+
* is required. Does not touch the DOM — safe to call on every resize frame.
|
|
14
|
+
*/
|
|
15
|
+
export declare function calculateVisibleCount({ itemWidths, gap, availableWidth, indicatorWidth, }: CalculateVisibleCountParams): number;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
function calculateVisibleCount({ itemWidths, gap, availableWidth, indicatorWidth }) {
|
|
2
|
+
if (0 === itemWidths.length) return 0;
|
|
3
|
+
if (availableWidth <= 0) return itemWidths.length;
|
|
4
|
+
let total = 0;
|
|
5
|
+
for(let i = 0; i < itemWidths.length; i++)total += (itemWidths[i] ?? 0) + (i > 0 ? gap : 0);
|
|
6
|
+
if (total <= availableWidth) return itemWidths.length;
|
|
7
|
+
const maxWidth = availableWidth - indicatorWidth - gap;
|
|
8
|
+
let accumulated = 0;
|
|
9
|
+
let count = 0;
|
|
10
|
+
for(let i = 0; i < itemWidths.length; i++){
|
|
11
|
+
const widthWithGap = (itemWidths[i] ?? 0) + (i > 0 ? gap : 0);
|
|
12
|
+
if (accumulated + widthWithGap <= maxWidth || 0 === i) {
|
|
13
|
+
accumulated += widthWithGap;
|
|
14
|
+
count++;
|
|
15
|
+
} else break;
|
|
16
|
+
}
|
|
17
|
+
return Math.max(count, 1);
|
|
18
|
+
}
|
|
19
|
+
export { calculateVisibleCount };
|
|
@@ -1,93 +1,109 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useLayoutEffect, useRef, useState } from "react";
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useLayoutEffect, useRef, useState } from "react";
|
|
3
|
+
import { calculateVisibleCount } from "./useOverflowItems.helpers.js";
|
|
3
4
|
function useOverflowItems({ items, renderItem, renderMeasurementItem, overflowRenderer, reserveSpace = 60 }) {
|
|
4
5
|
const containerRef = useRef(null);
|
|
5
6
|
const [visibleCount, setVisibleCount] = useState(items.length);
|
|
6
|
-
const [measurements, setMeasurements] = useState([]);
|
|
7
7
|
const measurementRefs = useRef([]);
|
|
8
|
+
const indicatorRef = useRef(null);
|
|
9
|
+
const cacheRef = useRef({
|
|
10
|
+
widths: [],
|
|
11
|
+
gap: 0,
|
|
12
|
+
indicatorWidth: reserveSpace
|
|
13
|
+
});
|
|
14
|
+
const recompute = useCallback(()=>{
|
|
15
|
+
const container = containerRef.current;
|
|
16
|
+
if (!container) return;
|
|
17
|
+
const { widths, gap, indicatorWidth } = cacheRef.current;
|
|
18
|
+
if (0 === widths.length) return;
|
|
19
|
+
const next = calculateVisibleCount({
|
|
20
|
+
itemWidths: widths,
|
|
21
|
+
gap,
|
|
22
|
+
availableWidth: container.offsetWidth,
|
|
23
|
+
indicatorWidth
|
|
24
|
+
});
|
|
25
|
+
setVisibleCount((prev)=>prev === next ? prev : next);
|
|
26
|
+
}, []);
|
|
8
27
|
useLayoutEffect(()=>{
|
|
28
|
+
const container = containerRef.current;
|
|
9
29
|
if (0 === items.length) {
|
|
30
|
+
cacheRef.current = {
|
|
31
|
+
widths: [],
|
|
32
|
+
gap: 0,
|
|
33
|
+
indicatorWidth: reserveSpace
|
|
34
|
+
};
|
|
10
35
|
setVisibleCount(0);
|
|
11
|
-
setMeasurements([]);
|
|
12
36
|
return;
|
|
13
37
|
}
|
|
14
|
-
const
|
|
15
|
-
|
|
38
|
+
const gap = container ? Number.parseFloat(getComputedStyle(container).gap || '0') || 0 : 0;
|
|
39
|
+
const widths = measurementRefs.current.slice(0, items.length).map((ref)=>ref?.offsetWidth ?? 0);
|
|
40
|
+
const indicatorWidth = indicatorRef.current?.offsetWidth || reserveSpace;
|
|
41
|
+
cacheRef.current = {
|
|
42
|
+
widths,
|
|
43
|
+
gap,
|
|
44
|
+
indicatorWidth
|
|
45
|
+
};
|
|
46
|
+
recompute();
|
|
16
47
|
}, [
|
|
17
|
-
items
|
|
48
|
+
items,
|
|
49
|
+
renderItem,
|
|
50
|
+
renderMeasurementItem,
|
|
51
|
+
overflowRenderer,
|
|
52
|
+
reserveSpace,
|
|
53
|
+
recompute
|
|
18
54
|
]);
|
|
19
55
|
useLayoutEffect(()=>{
|
|
20
56
|
const container = containerRef.current;
|
|
21
|
-
if (!container
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (!itemWidth) continue;
|
|
32
|
-
const widthWithGap = itemWidth + (i > 0 ? gap : 0);
|
|
33
|
-
const needsIndicator = i < measurements.length - 1;
|
|
34
|
-
let dynamicReserveSpace = reserveSpace;
|
|
35
|
-
if (needsIndicator && overflowRenderer) try {
|
|
36
|
-
const tempDiv = document.createElement('div');
|
|
37
|
-
tempDiv.style.cssText = 'position: absolute; visibility: hidden; top: -9999px;';
|
|
38
|
-
tempDiv.style.font = computedStyles.font;
|
|
39
|
-
document.body.appendChild(tempDiv);
|
|
40
|
-
const overflowItem = items[0];
|
|
41
|
-
if (overflowItem) {
|
|
42
|
-
const overflowElement = overflowRenderer([
|
|
43
|
-
overflowItem
|
|
44
|
-
]);
|
|
45
|
-
if (overflowElement && 'object' == typeof overflowElement) tempDiv.textContent = '+1';
|
|
46
|
-
}
|
|
47
|
-
dynamicReserveSpace = Math.max(reserveSpace, tempDiv.offsetWidth + gap);
|
|
48
|
-
document.body.removeChild(tempDiv);
|
|
49
|
-
} catch {}
|
|
50
|
-
const maxWidth = availableWidth - (needsIndicator ? dynamicReserveSpace : 0);
|
|
51
|
-
if (accumulatedWidth + widthWithGap <= maxWidth || 0 === i) {
|
|
52
|
-
count++;
|
|
53
|
-
accumulatedWidth += widthWithGap;
|
|
54
|
-
} else break;
|
|
55
|
-
}
|
|
56
|
-
setVisibleCount(count || 1);
|
|
57
|
-
};
|
|
58
|
-
calculateVisibleItems();
|
|
59
|
-
const resizeObserver = new ResizeObserver(calculateVisibleItems);
|
|
60
|
-
resizeObserver.observe(container);
|
|
57
|
+
if (!container) return;
|
|
58
|
+
let frame = 0;
|
|
59
|
+
const observer = new ResizeObserver(()=>{
|
|
60
|
+
if (frame) return;
|
|
61
|
+
frame = requestAnimationFrame(()=>{
|
|
62
|
+
frame = 0;
|
|
63
|
+
recompute();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
observer.observe(container);
|
|
61
67
|
return ()=>{
|
|
62
|
-
|
|
68
|
+
if (frame) cancelAnimationFrame(frame);
|
|
69
|
+
observer.disconnect();
|
|
63
70
|
};
|
|
64
71
|
}, [
|
|
65
|
-
|
|
66
|
-
items,
|
|
67
|
-
reserveSpace,
|
|
68
|
-
overflowRenderer
|
|
72
|
+
recompute
|
|
69
73
|
]);
|
|
70
74
|
const visibleItems = items.slice(0, visibleCount);
|
|
71
75
|
const hiddenItems = items.slice(visibleCount);
|
|
72
76
|
const hiddenCount = hiddenItems.length;
|
|
73
|
-
const MeasurementContainer = ()=>{
|
|
77
|
+
const MeasurementContainer = useCallback(()=>{
|
|
74
78
|
if (0 === items.length) return null;
|
|
75
79
|
const renderMeasure = renderMeasurementItem || renderItem;
|
|
76
|
-
return /*#__PURE__*/
|
|
80
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
77
81
|
className: "absolute invisible pointer-events-none",
|
|
78
82
|
"aria-hidden": "true",
|
|
79
|
-
children:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
children: [
|
|
84
|
+
items.map((item, index)=>{
|
|
85
|
+
const key = `${index}`;
|
|
86
|
+
return /*#__PURE__*/ jsx("div", {
|
|
87
|
+
ref: (el)=>{
|
|
88
|
+
measurementRefs.current[index] = el;
|
|
89
|
+
},
|
|
90
|
+
className: "inline-flex",
|
|
91
|
+
children: renderMeasure(item)
|
|
92
|
+
}, key);
|
|
93
|
+
}),
|
|
94
|
+
overflowRenderer && /*#__PURE__*/ jsx("div", {
|
|
95
|
+
ref: indicatorRef,
|
|
85
96
|
className: "inline-flex",
|
|
86
|
-
children:
|
|
87
|
-
}
|
|
88
|
-
|
|
97
|
+
children: overflowRenderer(items)
|
|
98
|
+
})
|
|
99
|
+
]
|
|
89
100
|
});
|
|
90
|
-
}
|
|
101
|
+
}, [
|
|
102
|
+
items,
|
|
103
|
+
renderItem,
|
|
104
|
+
renderMeasurementItem,
|
|
105
|
+
overflowRenderer
|
|
106
|
+
]);
|
|
91
107
|
return {
|
|
92
108
|
containerRef,
|
|
93
109
|
visibleItems,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
3
|
-
"generatedAt": "2026-05-
|
|
2
|
+
"version": "0.49.0",
|
|
3
|
+
"generatedAt": "2026-05-28T10:44:10.989Z",
|
|
4
4
|
"components": [
|
|
5
5
|
{
|
|
6
6
|
"name": "Accordion",
|
|
@@ -18174,6 +18174,11 @@
|
|
|
18174
18174
|
"code": "() => {\n return (\n <VStack gap={12}>\n <Drawer width={800}>\n <DrawerTrigger asChild>\n <Button>Open Resizable Drawer (as number)</Button>\n </DrawerTrigger>\n\n <DrawerContent>\n <DrawerResizeHandle />\n <DrawerHeader>\n <DrawerTitle>Resizable Drawer</DrawerTitle>\n </DrawerHeader>\n\n <DrawerBody>\n <div className='py-12'>\n <p className='mb-16'>Drag the left edge to resize this drawer.</p>\n <ContentPlaceholder height={300} />\n </div>\n </DrawerBody>\n </DrawerContent>\n </Drawer>\n\n <Drawer width='900px'>\n <DrawerTrigger asChild>\n <Button>Open Resizable Drawer (900px)</Button>\n </DrawerTrigger>\n\n <DrawerContent>\n <DrawerResizeHandle />\n <DrawerHeader>\n <DrawerTitle>Resizable Drawer with \"900px\" width</DrawerTitle>\n </DrawerHeader>\n\n <DrawerBody>\n <div className='py-12'>\n <p className='mb-16'>Width is set as \"900px\" string. Drag the left edge to resize.</p>\n <ContentPlaceholder height={300} />\n </div>\n </DrawerBody>\n </DrawerContent>\n </Drawer>\n\n <Drawer width='50%'>\n <DrawerTrigger asChild>\n <Button>Open Resizable Drawer (50%)</Button>\n </DrawerTrigger>\n\n <DrawerContent>\n <DrawerResizeHandle />\n <DrawerHeader>\n <DrawerTitle>Resizable Drawer with 50% width</DrawerTitle>\n </DrawerHeader>\n\n <DrawerBody>\n <div className='py-12'>\n <p className='mb-16'>\n Width is set as \"50%\". Drag the left edge to resize - it will convert to pixels.\n </p>\n <ContentPlaceholder height={300} />\n </div>\n </DrawerBody>\n </DrawerContent>\n </Drawer>\n </VStack>\n );\n}",
|
|
18175
18175
|
"description": "Resizable drawer"
|
|
18176
18176
|
},
|
|
18177
|
+
{
|
|
18178
|
+
"name": "ResizableWithOverflowList",
|
|
18179
|
+
"code": "() => {\n const [open, setOpen] = useState(true);\n\n return (\n <Drawer width={480} open={open} onOpenChange={setOpen}>\n <DrawerTrigger asChild>\n <Button>Open Resizable Drawer with OverflowList</Button>\n </DrawerTrigger>\n <DrawerContent>\n <DrawerResizeHandle />\n <DrawerHeader>\n <DrawerTitle>Resizable Drawer with OverflowList</DrawerTitle>\n </DrawerHeader>\n <DrawerBody>\n <p className='mb-16'>Drag the left edge — the tag list reflows live.</p>\n <Attribute>\n <AttributeLabel>Attack types</AttributeLabel>\n <AttributeValue>\n <OverflowList\n className='gap-4'\n items={DRAWER_TAGS}\n itemRenderer={item => <Tag key={item}>{item}</Tag>}\n overflowRenderer={renderDrawerOverflow}\n />\n </AttributeValue>\n </Attribute>\n </DrawerBody>\n </DrawerContent>\n </Drawer>\n );\n}",
|
|
18180
|
+
"description": "Resizable drawer with an OverflowList — drag the left edge to reflow tags."
|
|
18181
|
+
},
|
|
18177
18182
|
{
|
|
18178
18183
|
"name": "Scrollable",
|
|
18179
18184
|
"code": "() => {\n return (\n <Drawer>\n <DrawerTrigger asChild>\n <Button>Open Drawer with Scroll</Button>\n </DrawerTrigger>\n\n <DrawerContent>\n <DrawerHeader>\n <DrawerTitle>Scrollable Content</DrawerTitle>\n </DrawerHeader>\n\n <DrawerBody>\n <div className='flex flex-col gap-16 py-12'>\n {Array.from({ length: 20 }).map((_, i) => (\n <ContentPlaceholder key={i} height={100} />\n ))}\n </div>\n </DrawerBody>\n\n <DrawerFooter>\n <DrawerClose asChild>\n <Button variant='ghost' color='neutral' size='large'>\n Close\n </Button>\n </DrawerClose>\n <Button variant='primary' color='brand' size='large'>\n Confirm\n </Button>\n </DrawerFooter>\n </DrawerContent>\n </Drawer>\n );\n}",
|
|
@@ -30600,7 +30605,33 @@
|
|
|
30600
30605
|
],
|
|
30601
30606
|
"variants": [],
|
|
30602
30607
|
"subComponents": [],
|
|
30603
|
-
"examples": [
|
|
30608
|
+
"examples": [
|
|
30609
|
+
{
|
|
30610
|
+
"name": "Basic",
|
|
30611
|
+
"code": "() => (\n <div className='w-640'>\n <OverflowList\n className='gap-4'\n items={TAGS}\n itemRenderer={item => <Tag key={item}>{item}</Tag>}\n overflowRenderer={renderOverflowPopover}\n />\n </div>\n)",
|
|
30612
|
+
"description": "Basic list — all items fit in a wide container."
|
|
30613
|
+
},
|
|
30614
|
+
{
|
|
30615
|
+
"name": "Collapsed",
|
|
30616
|
+
"code": "() => (\n <div className='w-200'>\n <OverflowList\n className='gap-4'\n items={TAGS}\n itemRenderer={item => <Tag key={item}>{item}</Tag>}\n overflowRenderer={renderOverflowPopover}\n />\n </div>\n)",
|
|
30617
|
+
"description": "Narrow container — most items collapse into \"+N\"."
|
|
30618
|
+
},
|
|
30619
|
+
{
|
|
30620
|
+
"name": "CollapseFromStart",
|
|
30621
|
+
"code": "() => (\n <div className='w-240'>\n <OverflowList\n className='gap-4'\n collapseFrom='start'\n items={TAGS}\n itemRenderer={item => <Tag key={item}>{item}</Tag>}\n overflowRenderer={renderOverflowPopover}\n />\n </div>\n)",
|
|
30622
|
+
"description": "Collapse from the start of the list."
|
|
30623
|
+
},
|
|
30624
|
+
{
|
|
30625
|
+
"name": "MinVisibleItems",
|
|
30626
|
+
"code": "() => (\n <div className='w-160 overflow-hidden rounded-2 border border-border-primary p-12'>\n <OverflowList\n className='gap-4'\n minVisibleItems={1}\n items={TAGS}\n itemRenderer={item => (\n <Tag key={item} className='shrink-0 whitespace-nowrap'>\n {item}\n </Tag>\n )}\n overflowRenderer={renderOverflowPopoverInline}\n />\n </div>\n)",
|
|
30627
|
+
"description": "Guaranteed minimum number of visible items. The container is deliberately\nnarrow: `minVisibleItems={1}` keeps at least one tag visible (the rest\ncollapse into \"+N\") even when the space is tight."
|
|
30628
|
+
},
|
|
30629
|
+
{
|
|
30630
|
+
"name": "ResizableContainer",
|
|
30631
|
+
"code": "() => (\n <div\n data-testid='resizable-wrapper'\n className='overflow-hidden rounded-2 border border-border-primary p-12'\n style={{ width: 500, minWidth: 80, maxWidth: 800, resize: 'horizontal' }}\n >\n <OverflowList\n className='gap-4'\n items={TAGS}\n itemRenderer={item => <Tag key={item}>{item}</Tag>}\n overflowRenderer={renderOverflowPopover}\n />\n </div>\n)",
|
|
30632
|
+
"description": "Resizable container: drag the bottom-right corner of the box to see the list\nreflow live. The data-testid is used by E2E to resize programmatically."
|
|
30633
|
+
}
|
|
30634
|
+
]
|
|
30604
30635
|
},
|
|
30605
30636
|
{
|
|
30606
30637
|
"name": "OverflowTooltip",
|
|
@@ -37765,7 +37796,283 @@
|
|
|
37765
37796
|
"importPath": "@wallarm-org/design-system/Select",
|
|
37766
37797
|
"props": [],
|
|
37767
37798
|
"variants": [],
|
|
37768
|
-
"subComponents": [
|
|
37799
|
+
"subComponents": [
|
|
37800
|
+
{
|
|
37801
|
+
"name": "SelectSeparator",
|
|
37802
|
+
"props": [
|
|
37803
|
+
{
|
|
37804
|
+
"name": "defaultChecked",
|
|
37805
|
+
"type": "boolean | undefined",
|
|
37806
|
+
"required": false
|
|
37807
|
+
},
|
|
37808
|
+
{
|
|
37809
|
+
"name": "defaultValue",
|
|
37810
|
+
"type": "string | number | readonly string[] | undefined",
|
|
37811
|
+
"required": false
|
|
37812
|
+
},
|
|
37813
|
+
{
|
|
37814
|
+
"name": "suppressContentEditableWarning",
|
|
37815
|
+
"type": "boolean | undefined",
|
|
37816
|
+
"required": false
|
|
37817
|
+
},
|
|
37818
|
+
{
|
|
37819
|
+
"name": "suppressHydrationWarning",
|
|
37820
|
+
"type": "boolean | undefined",
|
|
37821
|
+
"required": false
|
|
37822
|
+
},
|
|
37823
|
+
{
|
|
37824
|
+
"name": "accessKey",
|
|
37825
|
+
"type": "string | undefined",
|
|
37826
|
+
"required": false
|
|
37827
|
+
},
|
|
37828
|
+
{
|
|
37829
|
+
"name": "autoCapitalize",
|
|
37830
|
+
"type": "\"off\" | \"none\" | \"on\" | \"sentences\" | \"words\" | \"characters\" | (string & {}) | undefined",
|
|
37831
|
+
"required": false
|
|
37832
|
+
},
|
|
37833
|
+
{
|
|
37834
|
+
"name": "autoFocus",
|
|
37835
|
+
"type": "boolean | undefined",
|
|
37836
|
+
"required": false
|
|
37837
|
+
},
|
|
37838
|
+
{
|
|
37839
|
+
"name": "contentEditable",
|
|
37840
|
+
"type": "Booleanish | \"inherit\" | \"plaintext-only\" | undefined",
|
|
37841
|
+
"required": false
|
|
37842
|
+
},
|
|
37843
|
+
{
|
|
37844
|
+
"name": "contextMenu",
|
|
37845
|
+
"type": "string | undefined",
|
|
37846
|
+
"required": false
|
|
37847
|
+
},
|
|
37848
|
+
{
|
|
37849
|
+
"name": "dir",
|
|
37850
|
+
"type": "string | undefined",
|
|
37851
|
+
"required": false
|
|
37852
|
+
},
|
|
37853
|
+
{
|
|
37854
|
+
"name": "draggable",
|
|
37855
|
+
"type": "Booleanish | undefined",
|
|
37856
|
+
"required": false
|
|
37857
|
+
},
|
|
37858
|
+
{
|
|
37859
|
+
"name": "enterKeyHint",
|
|
37860
|
+
"type": "\"enter\" | \"done\" | \"go\" | \"next\" | \"previous\" | \"search\" | \"send\" | undefined",
|
|
37861
|
+
"required": false
|
|
37862
|
+
},
|
|
37863
|
+
{
|
|
37864
|
+
"name": "hidden",
|
|
37865
|
+
"type": "boolean | undefined",
|
|
37866
|
+
"required": false
|
|
37867
|
+
},
|
|
37868
|
+
{
|
|
37869
|
+
"name": "id",
|
|
37870
|
+
"type": "string | undefined",
|
|
37871
|
+
"required": false
|
|
37872
|
+
},
|
|
37873
|
+
{
|
|
37874
|
+
"name": "lang",
|
|
37875
|
+
"type": "string | undefined",
|
|
37876
|
+
"required": false
|
|
37877
|
+
},
|
|
37878
|
+
{
|
|
37879
|
+
"name": "nonce",
|
|
37880
|
+
"type": "string | undefined",
|
|
37881
|
+
"required": false
|
|
37882
|
+
},
|
|
37883
|
+
{
|
|
37884
|
+
"name": "slot",
|
|
37885
|
+
"type": "string | undefined",
|
|
37886
|
+
"required": false
|
|
37887
|
+
},
|
|
37888
|
+
{
|
|
37889
|
+
"name": "spellCheck",
|
|
37890
|
+
"type": "Booleanish | undefined",
|
|
37891
|
+
"required": false
|
|
37892
|
+
},
|
|
37893
|
+
{
|
|
37894
|
+
"name": "tabIndex",
|
|
37895
|
+
"type": "number | undefined",
|
|
37896
|
+
"required": false
|
|
37897
|
+
},
|
|
37898
|
+
{
|
|
37899
|
+
"name": "title",
|
|
37900
|
+
"type": "string | undefined",
|
|
37901
|
+
"required": false
|
|
37902
|
+
},
|
|
37903
|
+
{
|
|
37904
|
+
"name": "translate",
|
|
37905
|
+
"type": "\"yes\" | \"no\" | undefined",
|
|
37906
|
+
"required": false
|
|
37907
|
+
},
|
|
37908
|
+
{
|
|
37909
|
+
"name": "radioGroup",
|
|
37910
|
+
"type": "string | undefined",
|
|
37911
|
+
"required": false
|
|
37912
|
+
},
|
|
37913
|
+
{
|
|
37914
|
+
"name": "role",
|
|
37915
|
+
"type": "AriaRole | undefined",
|
|
37916
|
+
"required": false
|
|
37917
|
+
},
|
|
37918
|
+
{
|
|
37919
|
+
"name": "about",
|
|
37920
|
+
"type": "string | undefined",
|
|
37921
|
+
"required": false
|
|
37922
|
+
},
|
|
37923
|
+
{
|
|
37924
|
+
"name": "content",
|
|
37925
|
+
"type": "string | undefined",
|
|
37926
|
+
"required": false
|
|
37927
|
+
},
|
|
37928
|
+
{
|
|
37929
|
+
"name": "datatype",
|
|
37930
|
+
"type": "string | undefined",
|
|
37931
|
+
"required": false
|
|
37932
|
+
},
|
|
37933
|
+
{
|
|
37934
|
+
"name": "inlist",
|
|
37935
|
+
"type": "any",
|
|
37936
|
+
"required": false
|
|
37937
|
+
},
|
|
37938
|
+
{
|
|
37939
|
+
"name": "prefix",
|
|
37940
|
+
"type": "string | undefined",
|
|
37941
|
+
"required": false
|
|
37942
|
+
},
|
|
37943
|
+
{
|
|
37944
|
+
"name": "property",
|
|
37945
|
+
"type": "string | undefined",
|
|
37946
|
+
"required": false
|
|
37947
|
+
},
|
|
37948
|
+
{
|
|
37949
|
+
"name": "rel",
|
|
37950
|
+
"type": "string | undefined",
|
|
37951
|
+
"required": false
|
|
37952
|
+
},
|
|
37953
|
+
{
|
|
37954
|
+
"name": "resource",
|
|
37955
|
+
"type": "string | undefined",
|
|
37956
|
+
"required": false
|
|
37957
|
+
},
|
|
37958
|
+
{
|
|
37959
|
+
"name": "rev",
|
|
37960
|
+
"type": "string | undefined",
|
|
37961
|
+
"required": false
|
|
37962
|
+
},
|
|
37963
|
+
{
|
|
37964
|
+
"name": "typeof",
|
|
37965
|
+
"type": "string | undefined",
|
|
37966
|
+
"required": false
|
|
37967
|
+
},
|
|
37968
|
+
{
|
|
37969
|
+
"name": "vocab",
|
|
37970
|
+
"type": "string | undefined",
|
|
37971
|
+
"required": false
|
|
37972
|
+
},
|
|
37973
|
+
{
|
|
37974
|
+
"name": "autoCorrect",
|
|
37975
|
+
"type": "string | undefined",
|
|
37976
|
+
"required": false
|
|
37977
|
+
},
|
|
37978
|
+
{
|
|
37979
|
+
"name": "autoSave",
|
|
37980
|
+
"type": "string | undefined",
|
|
37981
|
+
"required": false
|
|
37982
|
+
},
|
|
37983
|
+
{
|
|
37984
|
+
"name": "color",
|
|
37985
|
+
"type": "string | undefined",
|
|
37986
|
+
"required": false
|
|
37987
|
+
},
|
|
37988
|
+
{
|
|
37989
|
+
"name": "itemProp",
|
|
37990
|
+
"type": "string | undefined",
|
|
37991
|
+
"required": false
|
|
37992
|
+
},
|
|
37993
|
+
{
|
|
37994
|
+
"name": "itemScope",
|
|
37995
|
+
"type": "boolean | undefined",
|
|
37996
|
+
"required": false
|
|
37997
|
+
},
|
|
37998
|
+
{
|
|
37999
|
+
"name": "itemType",
|
|
38000
|
+
"type": "string | undefined",
|
|
38001
|
+
"required": false
|
|
38002
|
+
},
|
|
38003
|
+
{
|
|
38004
|
+
"name": "itemID",
|
|
38005
|
+
"type": "string | undefined",
|
|
38006
|
+
"required": false
|
|
38007
|
+
},
|
|
38008
|
+
{
|
|
38009
|
+
"name": "itemRef",
|
|
38010
|
+
"type": "string | undefined",
|
|
38011
|
+
"required": false
|
|
38012
|
+
},
|
|
38013
|
+
{
|
|
38014
|
+
"name": "results",
|
|
38015
|
+
"type": "number | undefined",
|
|
38016
|
+
"required": false
|
|
38017
|
+
},
|
|
38018
|
+
{
|
|
38019
|
+
"name": "security",
|
|
38020
|
+
"type": "string | undefined",
|
|
38021
|
+
"required": false
|
|
38022
|
+
},
|
|
38023
|
+
{
|
|
38024
|
+
"name": "unselectable",
|
|
38025
|
+
"type": "\"off\" | \"on\" | undefined",
|
|
38026
|
+
"required": false
|
|
38027
|
+
},
|
|
38028
|
+
{
|
|
38029
|
+
"name": "popover",
|
|
38030
|
+
"type": "\"\" | \"auto\" | \"manual\" | \"hint\" | undefined",
|
|
38031
|
+
"required": false
|
|
38032
|
+
},
|
|
38033
|
+
{
|
|
38034
|
+
"name": "popoverTargetAction",
|
|
38035
|
+
"type": "\"toggle\" | \"show\" | \"hide\" | undefined",
|
|
38036
|
+
"required": false
|
|
38037
|
+
},
|
|
38038
|
+
{
|
|
38039
|
+
"name": "popoverTarget",
|
|
38040
|
+
"type": "string | undefined",
|
|
38041
|
+
"required": false
|
|
38042
|
+
},
|
|
38043
|
+
{
|
|
38044
|
+
"name": "inert",
|
|
38045
|
+
"type": "boolean | undefined",
|
|
38046
|
+
"required": false,
|
|
38047
|
+
"description": "@see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert"
|
|
38048
|
+
},
|
|
38049
|
+
{
|
|
38050
|
+
"name": "inputMode",
|
|
38051
|
+
"type": "\"none\" | \"search\" | \"text\" | \"tel\" | \"url\" | \"email\" | \"numeric\" | \"decimal\" | undefined",
|
|
38052
|
+
"required": false,
|
|
38053
|
+
"description": "Hints at the type of data that might be entered by the user while editing the element or its contents"
|
|
38054
|
+
},
|
|
38055
|
+
{
|
|
38056
|
+
"name": "is",
|
|
38057
|
+
"type": "string | undefined",
|
|
38058
|
+
"required": false,
|
|
38059
|
+
"description": "Specify that a standard HTML element should behave like a defined custom built-in element"
|
|
38060
|
+
},
|
|
38061
|
+
{
|
|
38062
|
+
"name": "exportparts",
|
|
38063
|
+
"type": "string | undefined",
|
|
38064
|
+
"required": false,
|
|
38065
|
+
"description": "@see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/exportparts}"
|
|
38066
|
+
},
|
|
38067
|
+
{
|
|
38068
|
+
"name": "part",
|
|
38069
|
+
"type": "string | undefined",
|
|
38070
|
+
"required": false,
|
|
38071
|
+
"description": "@see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/part}"
|
|
38072
|
+
}
|
|
38073
|
+
]
|
|
38074
|
+
}
|
|
38075
|
+
],
|
|
37769
38076
|
"examples": [
|
|
37770
38077
|
{
|
|
37771
38078
|
"name": "Basic",
|
|
@@ -51627,6 +51934,11 @@
|
|
|
51627
51934
|
"name": "ColumnResizing",
|
|
51628
51935
|
"code": "() => {\n const [columnSizing, setColumnSizing] = useState<TableColumnSizingState>({});\n\n return (\n <Table\n data={securityEvents}\n columns={securityColumns}\n getRowId={row => row.id}\n columnSizing={columnSizing}\n onColumnSizingChange={setColumnSizing}\n />\n );\n}"
|
|
51629
51936
|
},
|
|
51937
|
+
{
|
|
51938
|
+
"name": "ColumnResizingWithOverflowList",
|
|
51939
|
+
"code": "() => {\n const [columnSizing, setColumnSizing] = useState<TableColumnSizingState>({});\n\n const columns = useMemo<TableColumnDef<SecurityEvent>[]>(\n () => [\n ...securityColumns.slice(0, 1),\n securityColumnHelper.display({\n id: 'tags',\n header: 'Tags',\n size: 240,\n cell: ({ row }) => (\n <OverflowList\n className='gap-4'\n items={row.original.tags}\n itemRenderer={(item: string) => <Tag key={item}>{item}</Tag>}\n overflowRenderer={renderTableTagsOverflow}\n />\n ),\n }),\n ...securityColumns.slice(1),\n ],\n [],\n );\n\n return (\n <Table\n data={securityEvents}\n columns={columns}\n getRowId={row => row.id}\n columnSizing={columnSizing}\n onColumnSizingChange={setColumnSizing}\n />\n );\n}",
|
|
51940
|
+
"description": "Resizable column whose cell hosts an OverflowList — resize it to reflow tags."
|
|
51941
|
+
},
|
|
51630
51942
|
{
|
|
51631
51943
|
"name": "ColumnResizingWithPinning",
|
|
51632
51944
|
"code": "() => {\n const [columnSizing, setColumnSizing] = useState<TableColumnSizingState>({});\n const [columnPinning, setColumnPinning] = useState<TableColumnPinningState>({\n left: ['objectName'],\n });\n\n return (\n <Table\n className='max-w-920'\n data={securityEvents}\n columns={securityColumns}\n getRowId={row => row.id}\n columnSizing={columnSizing}\n onColumnSizingChange={setColumnSizing}\n columnPinning={columnPinning}\n onColumnPinningChange={setColumnPinning}\n />\n );\n}"
|