@astryxdesign/core 0.1.5-canary.efe7cc3 → 0.1.5
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/AlertDialog/useImperativeAlertDialog.d.ts +2 -0
- package/dist/AlertDialog/useImperativeAlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/useImperativeAlertDialog.js +2 -0
- package/dist/Lightbox/useLightbox.d.ts +1 -0
- package/dist/Lightbox/useLightbox.d.ts.map +1 -1
- package/dist/Lightbox/useLightbox.js +1 -0
- package/dist/Link/Link.d.ts +2 -0
- package/dist/Link/Link.d.ts.map +1 -1
- package/dist/Link/Link.js +2 -0
- package/dist/Overlay/useOverlay.d.ts +3 -0
- package/dist/Overlay/useOverlay.d.ts.map +1 -1
- package/dist/Overlay/useOverlay.js +3 -0
- package/dist/Table/index.d.ts +0 -2
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +0 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts +1 -1
- package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +1 -1
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +3 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts.map +1 -1
- package/dist/VisuallyHidden/VisuallyHidden.js +3 -0
- package/dist/astryx.umd.js +53 -53
- package/dist/astryx.umd.js.map +4 -4
- package/package.json +1 -1
- package/src/AlertDialog/useImperativeAlertDialog.tsx +2 -0
- package/src/Lightbox/useLightbox.tsx +1 -0
- package/src/Link/Link.tsx +2 -0
- package/src/Overlay/useOverlay.tsx +3 -0
- package/src/Table/index.ts +0 -5
- package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +1 -1
- package/src/VisuallyHidden/VisuallyHidden.tsx +3 -0
- package/dist/Table/plugins/groupedRows/index.d.ts +0 -3
- package/dist/Table/plugins/groupedRows/index.d.ts.map +0 -1
- package/dist/Table/plugins/groupedRows/index.js +0 -3
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts +0 -78
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +0 -1
- package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +0 -250
- package/src/Table/plugins/groupedRows/index.ts +0 -7
- package/src/Table/plugins/groupedRows/useTableGroupedRows.test.tsx +0 -231
- package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +0 -349
- package/src/Table/useTableGroupedRows.doc.mjs +0 -71
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/core",
|
|
3
|
-
"version": "0.1.5
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"displayName": "XDS Core",
|
|
5
5
|
"description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -36,6 +36,7 @@ export interface ImperativeAlertDialogReturn {
|
|
|
36
36
|
* @example
|
|
37
37
|
* ```
|
|
38
38
|
* const alert = useImperativeAlertDialog();
|
|
39
|
+
*
|
|
39
40
|
* const handleDelete = () => {
|
|
40
41
|
* alert.show({
|
|
41
42
|
* title: 'Delete item?',
|
|
@@ -44,6 +45,7 @@ export interface ImperativeAlertDialogReturn {
|
|
|
44
45
|
* onAction: async () => { await deleteItem(); alert.hide(); },
|
|
45
46
|
* });
|
|
46
47
|
* };
|
|
48
|
+
*
|
|
47
49
|
* return (
|
|
48
50
|
* <>
|
|
49
51
|
* <button onClick={handleDelete}>Delete</button>
|
package/src/Link/Link.tsx
CHANGED
|
@@ -274,6 +274,8 @@ export interface LinkProps extends BaseProps<
|
|
|
274
274
|
* <Link href="/settings" color="secondary">Settings</Link>
|
|
275
275
|
* <Link href="/privacy" hasUnderline>Privacy Policy</Link>
|
|
276
276
|
* <Link label="Close dialog" href="/home"><Icon icon="x" /></Link>
|
|
277
|
+
*
|
|
278
|
+
* // Inline link inside text — inherits the surrounding type/size:
|
|
277
279
|
* <Text type="large">
|
|
278
280
|
* Read our <Link href="/terms" type="inherit">terms</Link> first.
|
|
279
281
|
* </Text>
|
|
@@ -149,6 +149,7 @@ export interface UseOverlayResult {
|
|
|
149
149
|
* showOn: 'hover',
|
|
150
150
|
* content: <Button label="Quick view" variant="ghost" />,
|
|
151
151
|
* });
|
|
152
|
+
*
|
|
152
153
|
* <Card ref={overlay.containerRef} {...overlay.containerProps}>
|
|
153
154
|
* <Layout content={...} />
|
|
154
155
|
* {overlay.element}
|
|
@@ -157,7 +158,9 @@ export interface UseOverlayResult {
|
|
|
157
158
|
*
|
|
158
159
|
* @example
|
|
159
160
|
* ```
|
|
161
|
+
* // Callback mode — render on demand
|
|
160
162
|
* const overlay = useOverlay({ showOn: 'hover' });
|
|
163
|
+
*
|
|
161
164
|
* <div ref={overlay.containerRef} {...overlay.containerProps}>
|
|
162
165
|
* <img src={src} />
|
|
163
166
|
* {overlay.renderOverlay(<Button label="Quick view" />)}
|
package/src/Table/index.ts
CHANGED
|
@@ -26,7 +26,6 @@ export {useTableColumnSettings} from './plugins/columnSettings';
|
|
|
26
26
|
export {useTableColumnSettingsState} from './plugins/columnSettings';
|
|
27
27
|
export {useTableColumnResize} from './plugins/columnResize';
|
|
28
28
|
export {useTableStickyColumns} from './plugins/stickyColumns';
|
|
29
|
-
export {useTableGroupedRows} from './plugins/groupedRows';
|
|
30
29
|
export {
|
|
31
30
|
useTableRowExpansion,
|
|
32
31
|
useTableRowExpansionState,
|
|
@@ -103,10 +102,6 @@ export type {
|
|
|
103
102
|
export type {UseTableColumnResizeConfig} from './plugins/columnResize';
|
|
104
103
|
export type {UseTableStickyColumnsConfig} from './plugins/stickyColumns';
|
|
105
104
|
export type {UseTableRowExpansionConfig} from './plugins/rowExpansion';
|
|
106
|
-
export type {
|
|
107
|
-
UseTableGroupedRowsConfig,
|
|
108
|
-
UseTableGroupedRowsResult,
|
|
109
|
-
} from './plugins/groupedRows';
|
|
110
105
|
export type {
|
|
111
106
|
UseTableFilteringConfig,
|
|
112
107
|
TableFilterState,
|
|
@@ -109,7 +109,7 @@ export interface UseTableRowExpansionStateResult<
|
|
|
109
109
|
* computing the expand-all state.
|
|
110
110
|
*
|
|
111
111
|
* @example
|
|
112
|
-
* ```
|
|
112
|
+
* ```tsx
|
|
113
113
|
* const [expandedKeys, setExpandedKeys] = useState<Set<string>>(new Set());
|
|
114
114
|
* const {data, expansionConfig} = useTableRowExpansionState({
|
|
115
115
|
* baseData: tree,
|
|
@@ -79,9 +79,12 @@ const styles = stylex.create({
|
|
|
79
79
|
*
|
|
80
80
|
* @example
|
|
81
81
|
* ```
|
|
82
|
+
* // Accessible name for an icon-only button
|
|
82
83
|
* <IconButton icon="trash" label="">
|
|
83
84
|
* <VisuallyHidden>Delete incident</VisuallyHidden>
|
|
84
85
|
* </IconButton>
|
|
86
|
+
*
|
|
87
|
+
* // Live region for announcements
|
|
85
88
|
* <VisuallyHidden as="div" aria-live="polite">
|
|
86
89
|
* {`Moved ${task} to ${column}`}
|
|
87
90
|
* </VisuallyHidden>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/Table/plugins/groupedRows/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAC1D,YAAY,EACV,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,uBAAuB,CAAC"}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file useTableGroupedRows.tsx
|
|
3
|
-
* @input React, StyleX, Icon, Table types + the flat data array
|
|
4
|
-
* @output Exports useTableGroupedRows hook + config/result types
|
|
5
|
-
* @position Grouped-rows plugin; consumed by Table via plugins prop
|
|
6
|
-
*
|
|
7
|
-
* SYNC: When modified, update these files to stay in sync:
|
|
8
|
-
* - /packages/core/src/Table/index.ts (exports)
|
|
9
|
-
*/
|
|
10
|
-
import { type ReactNode } from 'react';
|
|
11
|
-
import type { TablePlugin } from '../../types';
|
|
12
|
-
/** Configuration for {@link useTableGroupedRows}. */
|
|
13
|
-
export interface UseTableGroupedRowsConfig<T extends Record<string, unknown>> {
|
|
14
|
-
/** The flat data to group. */
|
|
15
|
-
data: T[];
|
|
16
|
-
/** Derive the group key for a row. Rows with the same key share a section. */
|
|
17
|
-
groupBy: (item: T) => string;
|
|
18
|
-
/** Set of currently-collapsed group keys. */
|
|
19
|
-
collapsedGroups: Set<string>;
|
|
20
|
-
/** Called with a group key when its header is toggled. */
|
|
21
|
-
onToggleGroup: (groupKey: string) => void;
|
|
22
|
-
/**
|
|
23
|
-
* Custom renderer for a group header's content (right of the chevron).
|
|
24
|
-
* Defaults to `<groupKey> (<count>)`.
|
|
25
|
-
*/
|
|
26
|
-
renderGroupHeader?: (groupKey: string, count: number, collapsed: boolean) => ReactNode;
|
|
27
|
-
/** Stable key for a real row. Falls back to a positional key when omitted. */
|
|
28
|
-
getRowKey?: (item: T) => string;
|
|
29
|
-
/** Explicit group ordering; groups not listed keep first-seen order after these. */
|
|
30
|
-
groupOrder?: string[];
|
|
31
|
-
}
|
|
32
|
-
export interface UseTableGroupedRowsResult<T extends Record<string, unknown>> {
|
|
33
|
-
/** Ready-to-use plugin for `<Table plugins>`. */
|
|
34
|
-
plugin: TablePlugin<T>;
|
|
35
|
-
/** Flattened rows: `[header, ...visibleRows, header, ...visibleRows]`. */
|
|
36
|
-
data: T[];
|
|
37
|
-
/**
|
|
38
|
-
* Row-key resolver (also keys synthetic headers as `__group_<key>`). Pass to
|
|
39
|
-
* `<Table idKey>` — named for parallelism with the Table prop:
|
|
40
|
-
* `<Table idKey={grouped.idKey} />`.
|
|
41
|
-
*/
|
|
42
|
-
idKey: (item: T) => string;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Groups a flat data array into collapsible section rows. Each distinct
|
|
46
|
-
* `groupBy` value becomes a full-width section-header row with a chevron
|
|
47
|
-
* toggle, the group label, and a member count; collapsing hides that group's
|
|
48
|
-
* data rows while keeping the header visible.
|
|
49
|
-
*
|
|
50
|
-
* Mirrors {@link useTableRowExpansionState}: the consumer owns the
|
|
51
|
-
* `collapsedGroups` set and this hook returns `{data, plugin, idKey}` —
|
|
52
|
-
* pass all three to `<Table>`.
|
|
53
|
-
*
|
|
54
|
-
* @example
|
|
55
|
-
* ```tsx
|
|
56
|
-
* const [collapsed, setCollapsed] = useState<Set<string>>(new Set());
|
|
57
|
-
* const grouped = useTableGroupedRows({
|
|
58
|
-
* data: rows,
|
|
59
|
-
* groupBy: r => r.team,
|
|
60
|
-
* collapsedGroups: collapsed,
|
|
61
|
-
* onToggleGroup: key =>
|
|
62
|
-
* setCollapsed(prev => {
|
|
63
|
-
* const next = new Set(prev);
|
|
64
|
-
* next.has(key) ? next.delete(key) : next.add(key);
|
|
65
|
-
* return next;
|
|
66
|
-
* }),
|
|
67
|
-
* getRowKey: r => r.id,
|
|
68
|
-
* });
|
|
69
|
-
* <Table
|
|
70
|
-
* data={grouped.data}
|
|
71
|
-
* columns={columns}
|
|
72
|
-
* idKey={grouped.idKey}
|
|
73
|
-
* plugins={{grouped: grouped.plugin}}
|
|
74
|
-
* />;
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
export declare function useTableGroupedRows<T extends Record<string, unknown>>(config: UseTableGroupedRowsConfig<T>): UseTableGroupedRowsResult<T>;
|
|
78
|
-
//# sourceMappingURL=useTableGroupedRows.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useTableGroupedRows.d.ts","sourceRoot":"","sources":["../../../../src/Table/plugins/groupedRows/useTableGroupedRows.tsx"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,EAAuB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAQ3D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,aAAa,CAAC;AAoD7C,qDAAqD;AACrD,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1E,8BAA8B;IAC9B,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,8EAA8E;IAC9E,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAC7B,6CAA6C;IAC7C,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7B,0DAA0D;IAC1D,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,OAAO,KACf,SAAS,CAAC;IACf,8EAA8E;IAC9E,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;IAChC,oFAAoF;IACpF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC1E,iDAAiD;IACjD,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,0EAA0E;IAC1E,IAAI,EAAE,CAAC,EAAE,CAAC;IACV;;;;OAIG;IACH,KAAK,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAC;CAC5B;AA6DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnE,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC,GACnC,yBAAyB,CAAC,CAAC,CAAC,CA8I9B"}
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
'use client';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @file useTableGroupedRows.tsx
|
|
7
|
-
* @input React, StyleX, Icon, Table types + the flat data array
|
|
8
|
-
* @output Exports useTableGroupedRows hook + config/result types
|
|
9
|
-
* @position Grouped-rows plugin; consumed by Table via plugins prop
|
|
10
|
-
*
|
|
11
|
-
* SYNC: When modified, update these files to stay in sync:
|
|
12
|
-
* - /packages/core/src/Table/index.ts (exports)
|
|
13
|
-
*/
|
|
14
|
-
import { useCallback, useMemo } from 'react';
|
|
15
|
-
import * as stylex from '@stylexjs/stylex';
|
|
16
|
-
import "../../../theme/tokens.stylex.js";
|
|
17
|
-
import { spacingVars, colorVars, fontWeightVars } from "../../../theme/tokens.stylex.js";
|
|
18
|
-
import { Icon } from "../../../Icon/index.js";
|
|
19
|
-
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
|
|
20
|
-
// A synthetic group-header row injected into the flattened data. Real rows
|
|
21
|
-
// never carry this marker.
|
|
22
|
-
const GROUP_HEADER = Symbol('tableGroupHeader');
|
|
23
|
-
function isGroupHeader(item) {
|
|
24
|
-
return typeof item === 'object' && item !== null && item[GROUP_HEADER] === true;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Proxy handler: any field access beyond the marker fields resolves to `''`
|
|
28
|
-
// so user cell renderers (`item.name.toUpperCase()`) never throw on a header.
|
|
29
|
-
const HEADER_PROXY_HANDLER = {
|
|
30
|
-
// eslint-disable-next-line @typescript-eslint/promise-function-async -- Proxy get trap, not a promise-returning fn
|
|
31
|
-
get(t, prop) {
|
|
32
|
-
if (prop === GROUP_HEADER || prop === 'groupKey' || prop === 'count') {
|
|
33
|
-
return t[prop];
|
|
34
|
-
}
|
|
35
|
-
return prop in t ? t[prop] : '';
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Build a synthetic header row wrapped in a Proxy so arbitrary field access
|
|
41
|
-
* from user cell renderers (e.g. `item.name.toUpperCase()`) resolves to `''`
|
|
42
|
-
* instead of throwing — BaseTable evaluates `col.renderCell(item)` on every
|
|
43
|
-
* row (including synthetic headers) before `transformBodyRow` can replace the
|
|
44
|
-
* row's cells. `transformBodyRow` then discards those cells and renders a
|
|
45
|
-
* single full-width header cell.
|
|
46
|
-
*/
|
|
47
|
-
function makeHeader(groupKey, count) {
|
|
48
|
-
const target = {
|
|
49
|
-
[GROUP_HEADER]: true,
|
|
50
|
-
groupKey,
|
|
51
|
-
count
|
|
52
|
-
};
|
|
53
|
-
return new Proxy(target, HEADER_PROXY_HANDLER);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** Configuration for {@link useTableGroupedRows}. */
|
|
57
|
-
|
|
58
|
-
const styles = {
|
|
59
|
-
headerRow: {
|
|
60
|
-
kkrTdU: "x1ypdohk",
|
|
61
|
-
kfSwDN: "x87ps6o",
|
|
62
|
-
kWkggS: "xwmxj5m",
|
|
63
|
-
kt9PQ7: "xso031l",
|
|
64
|
-
kfdmCh: "x1q0q8m5",
|
|
65
|
-
kL6WhQ: "xw8gpjh",
|
|
66
|
-
$$css: true
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Groups a flat data array into collapsible section rows. Each distinct
|
|
72
|
-
* `groupBy` value becomes a full-width section-header row with a chevron
|
|
73
|
-
* toggle, the group label, and a member count; collapsing hides that group's
|
|
74
|
-
* data rows while keeping the header visible.
|
|
75
|
-
*
|
|
76
|
-
* Mirrors {@link useTableRowExpansionState}: the consumer owns the
|
|
77
|
-
* `collapsedGroups` set and this hook returns `{data, plugin, idKey}` —
|
|
78
|
-
* pass all three to `<Table>`.
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* ```tsx
|
|
82
|
-
* const [collapsed, setCollapsed] = useState<Set<string>>(new Set());
|
|
83
|
-
* const grouped = useTableGroupedRows({
|
|
84
|
-
* data: rows,
|
|
85
|
-
* groupBy: r => r.team,
|
|
86
|
-
* collapsedGroups: collapsed,
|
|
87
|
-
* onToggleGroup: key =>
|
|
88
|
-
* setCollapsed(prev => {
|
|
89
|
-
* const next = new Set(prev);
|
|
90
|
-
* next.has(key) ? next.delete(key) : next.add(key);
|
|
91
|
-
* return next;
|
|
92
|
-
* }),
|
|
93
|
-
* getRowKey: r => r.id,
|
|
94
|
-
* });
|
|
95
|
-
* <Table
|
|
96
|
-
* data={grouped.data}
|
|
97
|
-
* columns={columns}
|
|
98
|
-
* idKey={grouped.idKey}
|
|
99
|
-
* plugins={{grouped: grouped.plugin}}
|
|
100
|
-
* />;
|
|
101
|
-
* ```
|
|
102
|
-
*/
|
|
103
|
-
export function useTableGroupedRows(config) {
|
|
104
|
-
const {
|
|
105
|
-
data,
|
|
106
|
-
groupBy,
|
|
107
|
-
collapsedGroups,
|
|
108
|
-
onToggleGroup,
|
|
109
|
-
renderGroupHeader,
|
|
110
|
-
getRowKey: getRowKeyProp,
|
|
111
|
-
groupOrder
|
|
112
|
-
} = config;
|
|
113
|
-
const flattened = useMemo(() => {
|
|
114
|
-
if (data.length === 0) {
|
|
115
|
-
return [];
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Group preserving first-seen order.
|
|
119
|
-
const groups = new Map();
|
|
120
|
-
for (const item of data) {
|
|
121
|
-
const key = groupBy(item);
|
|
122
|
-
const bucket = groups.get(key);
|
|
123
|
-
if (bucket) {
|
|
124
|
-
bucket.push(item);
|
|
125
|
-
} else {
|
|
126
|
-
groups.set(key, [item]);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Determine iteration order.
|
|
131
|
-
let keys = [...groups.keys()];
|
|
132
|
-
if (groupOrder && groupOrder.length > 0) {
|
|
133
|
-
const ordered = groupOrder.filter(k => groups.has(k));
|
|
134
|
-
const rest = keys.filter(k => !groupOrder.includes(k));
|
|
135
|
-
keys = [...ordered, ...rest];
|
|
136
|
-
}
|
|
137
|
-
const out = [];
|
|
138
|
-
for (const key of keys) {
|
|
139
|
-
const rows = groups.get(key) ?? [];
|
|
140
|
-
out.push(makeHeader(key, rows.length));
|
|
141
|
-
if (!collapsedGroups.has(key)) {
|
|
142
|
-
out.push(...rows);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return out;
|
|
146
|
-
}, [data, groupBy, collapsedGroups, groupOrder]);
|
|
147
|
-
|
|
148
|
-
// Positional fallback index, built once per flattened array so key lookup
|
|
149
|
-
// stays O(1) instead of O(n) per row (which would make table keying O(n²)).
|
|
150
|
-
const positionByItem = useMemo(() => {
|
|
151
|
-
if (getRowKeyProp) {
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
const map = new Map();
|
|
155
|
-
for (let i = 0; i < flattened.length; i++) {
|
|
156
|
-
map.set(flattened[i], i);
|
|
157
|
-
}
|
|
158
|
-
return map;
|
|
159
|
-
}, [flattened, getRowKeyProp]);
|
|
160
|
-
const idKey = useCallback(item => {
|
|
161
|
-
if (isGroupHeader(item)) {
|
|
162
|
-
return `__group_${item.groupKey}`;
|
|
163
|
-
}
|
|
164
|
-
if (getRowKeyProp) {
|
|
165
|
-
return getRowKeyProp(item);
|
|
166
|
-
}
|
|
167
|
-
return String(positionByItem?.get(item) ?? -1);
|
|
168
|
-
}, [getRowKeyProp, positionByItem]);
|
|
169
|
-
const plugin = useMemo(() => ({
|
|
170
|
-
// Replace a header row's pre-rendered cells with one full-width cell.
|
|
171
|
-
transformBodyRow(props, item) {
|
|
172
|
-
if (!isGroupHeader(item)) {
|
|
173
|
-
return props;
|
|
174
|
-
}
|
|
175
|
-
const header = item;
|
|
176
|
-
const collapsed = collapsedGroups.has(header.groupKey);
|
|
177
|
-
const toggle = () => onToggleGroup(header.groupKey);
|
|
178
|
-
const content = renderGroupHeader ? renderGroupHeader(header.groupKey, header.count, collapsed) : /*#__PURE__*/_jsxDEV("span", {
|
|
179
|
-
...{
|
|
180
|
-
className: "x2mo6ok x1tgivj0"
|
|
181
|
-
},
|
|
182
|
-
children: [header.groupKey, ' ', /*#__PURE__*/_jsxDEV("span", {
|
|
183
|
-
...{
|
|
184
|
-
className: "x1sodnla xv1l7n4"
|
|
185
|
-
},
|
|
186
|
-
children: ["(", header.count, ")"]
|
|
187
|
-
}, void 0, true)]
|
|
188
|
-
}, void 0, true);
|
|
189
|
-
return {
|
|
190
|
-
...props,
|
|
191
|
-
htmlProps: {
|
|
192
|
-
...props.htmlProps,
|
|
193
|
-
// Convenience: clicking anywhere on the row toggles it. The chevron
|
|
194
|
-
// button below is the accessible, keyboard-operable control, so the
|
|
195
|
-
// row keeps its implicit `row` role (no role override here).
|
|
196
|
-
onClick: toggle,
|
|
197
|
-
'aria-expanded': !collapsed
|
|
198
|
-
},
|
|
199
|
-
styles: [...props.styles, styles.headerRow],
|
|
200
|
-
children:
|
|
201
|
-
/*#__PURE__*/
|
|
202
|
-
// colSpan larger than the column count is clamped by the browser
|
|
203
|
-
// to the actual number of columns, so the header always spans the
|
|
204
|
-
// full width without the plugin knowing the column count.
|
|
205
|
-
_jsxDEV("td", {
|
|
206
|
-
colSpan: 999,
|
|
207
|
-
...{
|
|
208
|
-
className: "xce4md1 x1vsv5vr x1t818jl"
|
|
209
|
-
},
|
|
210
|
-
children: /*#__PURE__*/_jsxDEV("span", {
|
|
211
|
-
...{
|
|
212
|
-
className: "x78zum5 x6s0dn4 xzye2dw"
|
|
213
|
-
},
|
|
214
|
-
children: [/*#__PURE__*/_jsxDEV("button", {
|
|
215
|
-
type: "button",
|
|
216
|
-
...{
|
|
217
|
-
className: "x3nfvp2 x6s0dn4 xl56j7k x2lah0s x1717udv x1ghz6dp x1ypdohk xv9yike x1cqbx0l"
|
|
218
|
-
},
|
|
219
|
-
onClick: e => {
|
|
220
|
-
e.stopPropagation();
|
|
221
|
-
toggle();
|
|
222
|
-
},
|
|
223
|
-
"aria-label": collapsed ? `Expand group ${header.groupKey}` : `Collapse group ${header.groupKey}`,
|
|
224
|
-
"aria-expanded": !collapsed,
|
|
225
|
-
children: /*#__PURE__*/_jsxDEV("span", {
|
|
226
|
-
...{
|
|
227
|
-
0: {
|
|
228
|
-
className: "x3nfvp2 x11xpdln xx6bhzk"
|
|
229
|
-
},
|
|
230
|
-
1: {
|
|
231
|
-
className: "x3nfvp2 x11xpdln xx6bhzk x1iffjtl"
|
|
232
|
-
}
|
|
233
|
-
}[!!!collapsed << 0],
|
|
234
|
-
children: /*#__PURE__*/_jsxDEV(Icon, {
|
|
235
|
-
icon: "chevronRight",
|
|
236
|
-
size: "xsm"
|
|
237
|
-
}, void 0, false)
|
|
238
|
-
}, void 0, false)
|
|
239
|
-
}, void 0, false), content]
|
|
240
|
-
}, void 0, true)
|
|
241
|
-
}, void 0, false)
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
}), [collapsedGroups, onToggleGroup, renderGroupHeader]);
|
|
245
|
-
return {
|
|
246
|
-
plugin,
|
|
247
|
-
data: flattened,
|
|
248
|
-
idKey
|
|
249
|
-
};
|
|
250
|
-
}
|