@react-stately/table 3.12.3 → 3.13.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.
Files changed (55) hide show
  1. package/LICENSE +201 -0
  2. package/dist/Cell.main.js.map +1 -1
  3. package/dist/Cell.module.js.map +1 -1
  4. package/dist/Column.main.js +1 -1
  5. package/dist/Column.main.js.map +1 -1
  6. package/dist/Column.mjs +1 -1
  7. package/dist/Column.module.js +1 -1
  8. package/dist/Column.module.js.map +1 -1
  9. package/dist/Row.main.js.map +1 -1
  10. package/dist/Row.module.js.map +1 -1
  11. package/dist/TableBody.main.js.map +1 -1
  12. package/dist/TableBody.module.js.map +1 -1
  13. package/dist/TableCollection.main.js +33 -17
  14. package/dist/TableCollection.main.js.map +1 -1
  15. package/dist/TableCollection.mjs +33 -17
  16. package/dist/TableCollection.module.js +33 -17
  17. package/dist/TableCollection.module.js.map +1 -1
  18. package/dist/TableColumnLayout.main.js +2 -2
  19. package/dist/TableColumnLayout.main.js.map +1 -1
  20. package/dist/TableColumnLayout.mjs +2 -2
  21. package/dist/TableColumnLayout.module.js +2 -2
  22. package/dist/TableColumnLayout.module.js.map +1 -1
  23. package/dist/TableHeader.main.js.map +1 -1
  24. package/dist/TableHeader.module.js.map +1 -1
  25. package/dist/TableUtils.main.js +1 -1
  26. package/dist/TableUtils.main.js.map +1 -1
  27. package/dist/TableUtils.mjs +1 -1
  28. package/dist/TableUtils.module.js +1 -1
  29. package/dist/TableUtils.module.js.map +1 -1
  30. package/dist/types.d.ts +8 -8
  31. package/dist/types.d.ts.map +1 -1
  32. package/dist/useTableColumnResizeState.main.js.map +1 -1
  33. package/dist/useTableColumnResizeState.module.js.map +1 -1
  34. package/dist/useTableState.main.js +4 -3
  35. package/dist/useTableState.main.js.map +1 -1
  36. package/dist/useTableState.mjs +4 -3
  37. package/dist/useTableState.module.js +4 -3
  38. package/dist/useTableState.module.js.map +1 -1
  39. package/dist/useTreeGridState.main.js +5 -5
  40. package/dist/useTreeGridState.main.js.map +1 -1
  41. package/dist/useTreeGridState.mjs +5 -5
  42. package/dist/useTreeGridState.module.js +5 -5
  43. package/dist/useTreeGridState.module.js.map +1 -1
  44. package/package.json +13 -12
  45. package/src/Cell.ts +1 -1
  46. package/src/Column.ts +2 -2
  47. package/src/Row.ts +1 -1
  48. package/src/TableBody.ts +1 -1
  49. package/src/TableCollection.ts +23 -19
  50. package/src/TableColumnLayout.ts +2 -2
  51. package/src/TableHeader.ts +1 -1
  52. package/src/TableUtils.ts +17 -6
  53. package/src/useTableColumnResizeState.ts +1 -1
  54. package/src/useTableState.ts +3 -3
  55. package/src/useTreeGridState.ts +12 -11
@@ -95,7 +95,7 @@ function $ee65a0057fd99531$var$convertExpanded(expanded) {
95
95
  }
96
96
  function $ee65a0057fd99531$var$generateTreeGridCollection(nodes, opts) {
97
97
  let { expandedKeys: expandedKeys = new Set() } = opts;
98
- let body;
98
+ let body = null;
99
99
  let flattenedRows = [];
100
100
  let columnCount = 0;
101
101
  let userColumnCount = 0;
@@ -157,7 +157,7 @@ function $ee65a0057fd99531$var$generateTreeGridCollection(nodes, opts) {
157
157
  // via .childNodes returns the same object as the one found via keyMap look up
158
158
  Object.assign(node, newProps);
159
159
  keyMap.set(node.key, node);
160
- let lastNode;
160
+ let lastNode = null;
161
161
  let rowIndex = 0;
162
162
  for (let child of node.childNodes)if (!(child.type === 'item' && expandedKeys !== 'all' && !expandedKeys.has(node.key))) {
163
163
  if (child.parentKey == null) // if child is a cell/expanded row/column and the parent key isn't already established by the collection, match child node to parent row
@@ -173,15 +173,15 @@ function $ee65a0057fd99531$var$generateTreeGridCollection(nodes, opts) {
173
173
  }
174
174
  if (lastNode) lastNode.nextKey = null;
175
175
  };
176
- let last;
177
- topLevelRows.forEach((node, i)=>{
176
+ let last = null;
177
+ for (let [i, node] of topLevelRows.entries()){
178
178
  visitNode(node, i);
179
179
  if (last) {
180
180
  last.nextKey = node.key;
181
181
  node.prevKey = last.key;
182
182
  } else node.prevKey = null;
183
183
  last = node;
184
- });
184
+ }
185
185
  if (last) last.nextKey = null;
186
186
  return {
187
187
  keyMap: keyMap,
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-stately/table/src/useTreeGridState.ts"],"sourcesContent":["/*\n * Copyright 2023 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {CollectionBuilder} from '@react-stately/collections';\nimport {GridNode} from '@react-types/grid';\nimport {Key} from '@react-types/shared';\nimport {ReactElement, useMemo} from 'react';\nimport {TableCollection} from './TableCollection';\nimport {tableNestedRows} from '@react-stately/flags';\nimport {TableState, TableStateProps, useTableState} from './useTableState';\nimport {useControlledState} from '@react-stately/utils';\n\nexport interface TreeGridState<T> extends TableState<T> {\n /** A set of keys for items that are expanded. */\n expandedKeys: 'all' | Set<Key>,\n /** Toggles the expanded state for a row by its key. */\n toggleKey(key: Key): void,\n /** The key map containing nodes representing the collection's tree grid structure. */\n keyMap: Map<Key, GridNode<T>>,\n /** The number of leaf columns provided by the user. */\n userColumnCount: number\n}\n\nexport interface TreeGridStateProps<T> extends Omit<TableStateProps<T>, 'collection'> {\n /** The currently expanded keys in the collection (controlled). */\n UNSTABLE_expandedKeys?: 'all' | Iterable<Key>,\n /** The initial expanded keys in the collection (uncontrolled). */\n UNSTABLE_defaultExpandedKeys?: 'all' | Iterable<Key>,\n /** Handler that is called when items are expanded or collapsed. */\n UNSTABLE_onExpandedChange?: (keys: Set<Key>) => any\n}\n\n/**\n * Provides state management for a tree grid component. Handles building a collection\n * of columns and rows from props. In addition, it tracks and manages expanded rows, row selection, and sort order changes.\n */\nexport function UNSTABLE_useTreeGridState<T extends object>(props: TreeGridStateProps<T>): TreeGridState<T> {\n let {\n selectionMode = 'none',\n showSelectionCheckboxes,\n showDragButtons,\n UNSTABLE_expandedKeys: propExpandedKeys,\n UNSTABLE_defaultExpandedKeys: propDefaultExpandedKeys,\n UNSTABLE_onExpandedChange,\n children\n } = props;\n\n if (!tableNestedRows()) {\n throw new Error('Feature flag for table nested rows must be enabled to use useTreeGridState.');\n }\n\n let [expandedKeys, setExpandedKeys] = useControlledState(\n propExpandedKeys ? convertExpanded(propExpandedKeys) : undefined,\n propDefaultExpandedKeys ? convertExpanded(propDefaultExpandedKeys) : new Set(),\n UNSTABLE_onExpandedChange\n );\n\n let context = useMemo(() => ({\n showSelectionCheckboxes: showSelectionCheckboxes && selectionMode !== 'none',\n showDragButtons: showDragButtons,\n selectionMode,\n columns: []\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }), [children, showSelectionCheckboxes, selectionMode, showDragButtons]);\n\n let builder = useMemo(() => new CollectionBuilder<T>(), []);\n let nodes = useMemo(() => builder.build({children: children as ReactElement<any>[]}, context), [builder, children, context]);\n let treeGridCollection = useMemo(() => {\n return generateTreeGridCollection<T>(nodes, {showSelectionCheckboxes, showDragButtons, expandedKeys});\n }, [nodes, showSelectionCheckboxes, showDragButtons, expandedKeys]);\n\n let onToggle = (key: Key) => {\n setExpandedKeys(toggleKey(expandedKeys, key, treeGridCollection));\n };\n\n let collection = useMemo(() => {\n return new TableCollection(treeGridCollection.tableNodes, null, context);\n }, [context, treeGridCollection.tableNodes]);\n\n let tableState = useTableState({...props, collection});\n return {\n ...tableState,\n keyMap: treeGridCollection.keyMap,\n userColumnCount: treeGridCollection.userColumnCount,\n expandedKeys,\n toggleKey: onToggle\n };\n}\n\nfunction toggleKey<T>(currentExpandedKeys: 'all' | Set<Key>, key: Key, collection: TreeGridCollection<T>): Set<Key> {\n let updatedExpandedKeys: Set<Key>;\n if (currentExpandedKeys === 'all') {\n updatedExpandedKeys = new Set(collection.flattenedRows.filter(row => row.props.UNSTABLE_childItems || row.props.children.length > collection.userColumnCount).map(row => row.key));\n updatedExpandedKeys.delete(key);\n } else {\n updatedExpandedKeys = new Set(currentExpandedKeys);\n if (updatedExpandedKeys.has(key)) {\n updatedExpandedKeys.delete(key);\n } else {\n updatedExpandedKeys.add(key);\n }\n }\n\n return updatedExpandedKeys;\n}\n\nfunction convertExpanded(expanded: 'all' | Iterable<Key>): 'all' | Set<Key> {\n if (!expanded) {\n return new Set<Key>();\n }\n\n return expanded === 'all'\n ? 'all'\n : new Set(expanded);\n}\n\ninterface TreeGridCollectionOptions {\n showSelectionCheckboxes?: boolean,\n showDragButtons?: boolean,\n expandedKeys: 'all' | Set<Key>\n}\n\ninterface TreeGridCollection<T> {\n keyMap: Map<Key, GridNode<T>>,\n tableNodes: GridNode<T>[],\n flattenedRows: GridNode<T>[],\n userColumnCount: number\n}\nfunction generateTreeGridCollection<T>(nodes, opts: TreeGridCollectionOptions): TreeGridCollection<T> {\n let {\n expandedKeys = new Set()\n } = opts;\n\n let body: GridNode<T>;\n let flattenedRows = [];\n let columnCount = 0;\n let userColumnCount = 0;\n let originalColumns = [];\n let keyMap = new Map();\n\n if (opts?.showSelectionCheckboxes) {\n columnCount++;\n }\n\n if (opts?.showDragButtons) {\n columnCount++;\n }\n\n let topLevelRows = [];\n let visit = (node: GridNode<T>) => {\n switch (node.type) {\n case 'body':\n body = node;\n keyMap.set(body.key, body);\n break;\n case 'column':\n if (!node.hasChildNodes) {\n userColumnCount++;\n }\n break;\n case 'item':\n topLevelRows.push(node);\n return;\n }\n\n for (let child of node.childNodes) {\n visit(child);\n }\n };\n\n for (let node of nodes) {\n if (node.type === 'column') {\n originalColumns.push(node);\n }\n visit(node);\n }\n columnCount += userColumnCount;\n\n // Update each grid node in the treegrid table with values specific to a treegrid structure. Also store a set of flattened row nodes for TableCollection to consume\n let globalRowCount = 0;\n let visitNode = (node: GridNode<T>, i?: number) => {\n // Clone row node and its children so modifications to the node for treegrid specific values aren't applied on the nodes provided\n // to TableCollection. Index, level, and parent keys are all changed to reflect a flattened row structure rather than the treegrid structure\n // values automatically calculated via CollectionBuilder\n if (node.type === 'item') {\n let childNodes = [];\n for (let child of node.childNodes) {\n if (child.type === 'cell') {\n let cellClone = {...child};\n if (cellClone.index + 1 === columnCount) {\n cellClone.nextKey = null;\n }\n childNodes.push({...cellClone});\n }\n }\n let clone = {...node, childNodes: childNodes, parentKey: body.key, level: 1, index: globalRowCount++};\n flattenedRows.push(clone);\n }\n\n let newProps = {};\n\n // Assign indexOfType to cells and rows for aria-posinset\n if (node.type !== 'placeholder' && node.type !== 'column') {\n newProps['indexOfType'] = i;\n }\n\n // Use Object.assign instead of spread to preserve object reference for keyMap. Also ensures retrieving nodes\n // via .childNodes returns the same object as the one found via keyMap look up\n Object.assign(node, newProps);\n keyMap.set(node.key, node);\n\n let lastNode: GridNode<T>;\n let rowIndex = 0;\n for (let child of node.childNodes) {\n if (!(child.type === 'item' && expandedKeys !== 'all' && !expandedKeys.has(node.key))) {\n if (child.parentKey == null) {\n // if child is a cell/expanded row/column and the parent key isn't already established by the collection, match child node to parent row\n child.parentKey = node.key;\n }\n\n if (lastNode) {\n lastNode.nextKey = child.key;\n child.prevKey = lastNode.key;\n } else {\n child.prevKey = null;\n }\n\n if (child.type === 'item') {\n visitNode(child, rowIndex++);\n } else {\n // We enforce that the cells come before rows so can just reuse cell index\n visitNode(child, child.index);\n }\n\n lastNode = child;\n }\n }\n\n if (lastNode) {\n lastNode.nextKey = null;\n }\n };\n\n let last: GridNode<T>;\n topLevelRows.forEach((node: GridNode<T>, i) => {\n visitNode(node as GridNode<T>, i);\n\n if (last) {\n last.nextKey = node.key;\n node.prevKey = last.key;\n } else {\n node.prevKey = null;\n }\n\n last = node;\n });\n\n if (last) {\n last.nextKey = null;\n }\n\n return {\n keyMap,\n userColumnCount,\n flattenedRows,\n tableNodes: [...originalColumns, {...body, childNodes: flattenedRows}]\n };\n}\n"],"names":[],"version":3,"file":"useTreeGridState.module.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-stately/table/src/useTreeGridState.ts"],"sourcesContent":["/*\n * Copyright 2023 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {CollectionBuilder} from '@react-stately/collections';\nimport {GridNode} from '@react-types/grid';\nimport {Key} from '@react-types/shared';\nimport {ReactElement, useMemo} from 'react';\nimport {TableCollection} from './TableCollection';\nimport {tableNestedRows} from '@react-stately/flags';\nimport {TableState, TableStateProps, useTableState} from './useTableState';\nimport {useControlledState} from '@react-stately/utils';\n\nexport interface TreeGridState<T> extends TableState<T> {\n /** A set of keys for items that are expanded. */\n expandedKeys: 'all' | Set<Key>,\n /** Toggles the expanded state for a row by its key. */\n toggleKey(key: Key): void,\n /** The key map containing nodes representing the collection's tree grid structure. */\n keyMap: Map<Key, GridNode<T>>,\n /** The number of leaf columns provided by the user. */\n userColumnCount: number\n}\n\nexport interface TreeGridStateProps<T> extends Omit<TableStateProps<T>, 'collection'> {\n /** The currently expanded keys in the collection (controlled). */\n UNSTABLE_expandedKeys?: 'all' | Iterable<Key>,\n /** The initial expanded keys in the collection (uncontrolled). */\n UNSTABLE_defaultExpandedKeys?: 'all' | Iterable<Key>,\n /** Handler that is called when items are expanded or collapsed. */\n UNSTABLE_onExpandedChange?: (keys: Set<Key>) => any\n}\n\n/**\n * Provides state management for a tree grid component. Handles building a collection\n * of columns and rows from props. In addition, it tracks and manages expanded rows, row selection, and sort order changes.\n */\nexport function UNSTABLE_useTreeGridState<T extends object>(props: TreeGridStateProps<T>): TreeGridState<T> {\n let {\n selectionMode = 'none',\n showSelectionCheckboxes,\n showDragButtons,\n UNSTABLE_expandedKeys: propExpandedKeys,\n UNSTABLE_defaultExpandedKeys: propDefaultExpandedKeys,\n UNSTABLE_onExpandedChange,\n children\n } = props;\n\n if (!tableNestedRows()) {\n throw new Error('Feature flag for table nested rows must be enabled to use useTreeGridState.');\n }\n\n let [expandedKeys, setExpandedKeys] = useControlledState(\n propExpandedKeys ? convertExpanded(propExpandedKeys) : undefined,\n propDefaultExpandedKeys ? convertExpanded(propDefaultExpandedKeys) : new Set(),\n UNSTABLE_onExpandedChange\n );\n\n let context = useMemo(() => ({\n showSelectionCheckboxes: showSelectionCheckboxes && selectionMode !== 'none',\n showDragButtons: showDragButtons,\n selectionMode,\n columns: []\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }), [children, showSelectionCheckboxes, selectionMode, showDragButtons]);\n\n let builder = useMemo(() => new CollectionBuilder<T>(), []);\n let nodes = useMemo(() => builder.build({children: children as ReactElement<any>[]}, context), [builder, children, context]);\n let treeGridCollection = useMemo(() => {\n return generateTreeGridCollection<T>(nodes, {showSelectionCheckboxes, showDragButtons, expandedKeys});\n }, [nodes, showSelectionCheckboxes, showDragButtons, expandedKeys]);\n\n let onToggle = (key: Key) => {\n setExpandedKeys(toggleKey(expandedKeys, key, treeGridCollection));\n };\n\n let collection = useMemo(() => {\n return new TableCollection(treeGridCollection.tableNodes, null, context);\n }, [context, treeGridCollection.tableNodes]);\n\n let tableState = useTableState({...props, collection});\n return {\n ...tableState,\n keyMap: treeGridCollection.keyMap,\n userColumnCount: treeGridCollection.userColumnCount,\n expandedKeys,\n toggleKey: onToggle\n };\n}\n\nfunction toggleKey<T>(currentExpandedKeys: 'all' | Set<Key>, key: Key, collection: TreeGridCollection<T>): Set<Key> {\n let updatedExpandedKeys: Set<Key>;\n if (currentExpandedKeys === 'all') {\n updatedExpandedKeys = new Set(collection.flattenedRows.filter(row => row.props.UNSTABLE_childItems || row.props.children.length > collection.userColumnCount).map(row => row.key));\n updatedExpandedKeys.delete(key);\n } else {\n updatedExpandedKeys = new Set(currentExpandedKeys);\n if (updatedExpandedKeys.has(key)) {\n updatedExpandedKeys.delete(key);\n } else {\n updatedExpandedKeys.add(key);\n }\n }\n\n return updatedExpandedKeys;\n}\n\nfunction convertExpanded(expanded: 'all' | Iterable<Key>): 'all' | Set<Key> {\n if (!expanded) {\n return new Set<Key>();\n }\n\n return expanded === 'all'\n ? 'all'\n : new Set(expanded);\n}\n\ninterface TreeGridCollectionOptions {\n showSelectionCheckboxes?: boolean,\n showDragButtons?: boolean,\n expandedKeys: 'all' | Set<Key>\n}\n\ninterface TreeGridCollection<T> {\n keyMap: Map<Key, GridNode<T>>,\n tableNodes: GridNode<T>[],\n flattenedRows: GridNode<T>[],\n userColumnCount: number\n}\nfunction generateTreeGridCollection<T>(nodes, opts: TreeGridCollectionOptions): TreeGridCollection<T> {\n let {\n expandedKeys = new Set()\n } = opts;\n\n let body: GridNode<T> | null = null;\n let flattenedRows: GridNode<T>[] = [];\n let columnCount = 0;\n let userColumnCount = 0;\n let originalColumns: GridNode<T>[] = [];\n let keyMap = new Map();\n\n if (opts?.showSelectionCheckboxes) {\n columnCount++;\n }\n\n if (opts?.showDragButtons) {\n columnCount++;\n }\n\n let topLevelRows: GridNode<T>[] = [];\n let visit = (node: GridNode<T>) => {\n switch (node.type) {\n case 'body':\n body = node;\n keyMap.set(body.key, body);\n break;\n case 'column':\n if (!node.hasChildNodes) {\n userColumnCount++;\n }\n break;\n case 'item':\n topLevelRows.push(node);\n return;\n }\n\n for (let child of node.childNodes) {\n visit(child);\n }\n };\n\n for (let node of nodes) {\n if (node.type === 'column') {\n originalColumns.push(node);\n }\n visit(node);\n }\n\n columnCount += userColumnCount;\n\n // Update each grid node in the treegrid table with values specific to a treegrid structure. Also store a set of flattened row nodes for TableCollection to consume\n let globalRowCount = 0;\n let visitNode = (node: GridNode<T>, i?: number) => {\n // Clone row node and its children so modifications to the node for treegrid specific values aren't applied on the nodes provided\n // to TableCollection. Index, level, and parent keys are all changed to reflect a flattened row structure rather than the treegrid structure\n // values automatically calculated via CollectionBuilder\n if (node.type === 'item') {\n let childNodes: GridNode<T>[] = [];\n for (let child of node.childNodes) {\n if (child.type === 'cell') {\n let cellClone = {...child};\n if (cellClone.index + 1 === columnCount) {\n cellClone.nextKey = null;\n }\n childNodes.push({...cellClone});\n }\n }\n let clone: GridNode<T> = {...node, childNodes: childNodes, parentKey: body!.key, level: 1, index: globalRowCount++};\n flattenedRows.push(clone);\n }\n\n let newProps = {};\n\n // Assign indexOfType to cells and rows for aria-posinset\n if (node.type !== 'placeholder' && node.type !== 'column') {\n newProps['indexOfType'] = i;\n }\n\n // Use Object.assign instead of spread to preserve object reference for keyMap. Also ensures retrieving nodes\n // via .childNodes returns the same object as the one found via keyMap look up\n Object.assign(node, newProps);\n keyMap.set(node.key, node);\n\n let lastNode: GridNode<T> | null = null;\n let rowIndex = 0;\n for (let child of node.childNodes) {\n if (!(child.type === 'item' && expandedKeys !== 'all' && !expandedKeys.has(node.key))) {\n if (child.parentKey == null) {\n // if child is a cell/expanded row/column and the parent key isn't already established by the collection, match child node to parent row\n child.parentKey = node.key;\n }\n\n if (lastNode) {\n lastNode.nextKey = child.key;\n child.prevKey = lastNode.key;\n } else {\n child.prevKey = null;\n }\n\n if (child.type === 'item') {\n visitNode(child, rowIndex++);\n } else {\n // We enforce that the cells come before rows so can just reuse cell index\n visitNode(child, child.index);\n }\n\n lastNode = child;\n }\n }\n\n if (lastNode) {\n lastNode.nextKey = null;\n }\n };\n\n let last: GridNode<T> | null = null;\n for (let [i, node] of topLevelRows.entries()) {\n visitNode(node as GridNode<T>, i);\n\n if (last) {\n last.nextKey = node.key;\n node.prevKey = last.key;\n } else {\n node.prevKey = null;\n }\n\n last = node;\n }\n\n if (last) {\n last.nextKey = null;\n }\n\n return {\n keyMap,\n userColumnCount,\n flattenedRows,\n tableNodes: [...originalColumns, {...body!, childNodes: flattenedRows}]\n };\n}\n"],"names":[],"version":3,"file":"useTreeGridState.module.js.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-stately/table",
3
- "version": "3.12.3",
3
+ "version": "3.13.0",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -22,20 +22,21 @@
22
22
  "url": "https://github.com/adobe/react-spectrum"
23
23
  },
24
24
  "dependencies": {
25
- "@react-stately/collections": "^3.11.0",
26
- "@react-stately/flags": "^3.0.4",
27
- "@react-stately/grid": "^3.9.3",
28
- "@react-stately/selection": "^3.17.0",
29
- "@react-stately/utils": "^3.10.4",
30
- "@react-types/grid": "^3.2.9",
31
- "@react-types/shared": "^3.25.0",
32
- "@react-types/table": "^3.10.2",
25
+ "@react-stately/collections": "^3.12.0",
26
+ "@react-stately/flags": "^3.0.5",
27
+ "@react-stately/grid": "^3.10.0",
28
+ "@react-stately/selection": "^3.18.0",
29
+ "@react-stately/utils": "^3.10.5",
30
+ "@react-types/grid": "^3.2.10",
31
+ "@react-types/shared": "^3.26.0",
32
+ "@react-types/table": "^3.10.3",
33
33
  "@swc/helpers": "^0.5.0"
34
34
  },
35
35
  "peerDependencies": {
36
- "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0"
36
+ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
37
37
  },
38
38
  "publishConfig": {
39
39
  "access": "public"
40
- }
41
- }
40
+ },
41
+ "gitHead": "71f0ef23053f9e03ee7e97df736e8b083e006849"
42
+ }
package/src/Cell.ts CHANGED
@@ -14,7 +14,7 @@ import {CellProps} from '@react-types/table';
14
14
  import {JSX, ReactElement} from 'react';
15
15
  import {PartialNode} from '@react-stately/collections';
16
16
 
17
- function Cell(props: CellProps): ReactElement { // eslint-disable-line @typescript-eslint/no-unused-vars
17
+ function Cell(props: CellProps): ReactElement | null { // eslint-disable-line @typescript-eslint/no-unused-vars
18
18
  return null;
19
19
  }
20
20
 
package/src/Column.ts CHANGED
@@ -16,7 +16,7 @@ import {GridNode} from '@react-types/grid';
16
16
  import {PartialNode} from '@react-stately/collections';
17
17
  import React, {JSX, ReactElement} from 'react';
18
18
 
19
- function Column<T>(props: ColumnProps<T>): ReactElement { // eslint-disable-line @typescript-eslint/no-unused-vars
19
+ function Column<T>(props: ColumnProps<T>): ReactElement | null { // eslint-disable-line @typescript-eslint/no-unused-vars
20
20
  return null;
21
21
  }
22
22
 
@@ -28,7 +28,7 @@ Column.getCollectionNode = function* getCollectionNode<T>(props: ColumnProps<T>,
28
28
 
29
29
  let fullNodes = yield {
30
30
  type: 'column',
31
- hasChildNodes: !!childColumns || (title && React.Children.count(children) > 0),
31
+ hasChildNodes: !!childColumns || (!!title && React.Children.count(children) > 0),
32
32
  rendered,
33
33
  textValue,
34
34
  props,
package/src/Row.ts CHANGED
@@ -15,7 +15,7 @@ import {PartialNode} from '@react-stately/collections';
15
15
  import React, {JSX, ReactElement} from 'react';
16
16
  import {RowProps} from '@react-types/table';
17
17
 
18
- function Row<T>(props: RowProps<T>): ReactElement { // eslint-disable-line @typescript-eslint/no-unused-vars
18
+ function Row<T>(props: RowProps<T>): ReactElement | null { // eslint-disable-line @typescript-eslint/no-unused-vars
19
19
  return null;
20
20
  }
21
21
 
package/src/TableBody.ts CHANGED
@@ -14,7 +14,7 @@ import {PartialNode} from '@react-stately/collections';
14
14
  import React, {JSX, ReactElement} from 'react';
15
15
  import {TableBodyProps} from '@react-types/table';
16
16
 
17
- function TableBody<T>(props: TableBodyProps<T>): ReactElement { // eslint-disable-line @typescript-eslint/no-unused-vars
17
+ function TableBody<T>(props: TableBodyProps<T>): ReactElement | null { // eslint-disable-line @typescript-eslint/no-unused-vars
18
18
  return null;
19
19
  }
20
20
 
@@ -40,7 +40,7 @@ export function buildHeaderRows<T>(keyMap: Map<Key, GridNode<T>>, columnNodes: G
40
40
  let col = [column];
41
41
 
42
42
  while (parentKey) {
43
- let parent: GridNode<T> = keyMap.get(parentKey);
43
+ let parent: GridNode<T> | undefined = keyMap.get(parentKey);
44
44
  if (!parent) {
45
45
  break;
46
46
  }
@@ -50,6 +50,7 @@ export function buildHeaderRows<T>(keyMap: Map<Key, GridNode<T>>, columnNodes: G
50
50
  // than the previous column, than we need to shift the parent
51
51
  // in the previous column so it's level with the current column.
52
52
  if (seen.has(parent)) {
53
+ parent.colspan ??= 0;
53
54
  parent.colspan++;
54
55
 
55
56
  let {column, index} = seen.get(parent);
@@ -82,7 +83,7 @@ export function buildHeaderRows<T>(keyMap: Map<Key, GridNode<T>>, columnNodes: G
82
83
  }
83
84
 
84
85
  let maxLength = Math.max(...columns.map(c => c.length));
85
- let headerRows = Array(maxLength).fill(0).map(() => []);
86
+ let headerRows: GridNode<T>[][] = Array(maxLength).fill(0).map(() => []);
86
87
 
87
88
  // Convert columns into rows.
88
89
  let colIndex = 0;
@@ -92,7 +93,7 @@ export function buildHeaderRows<T>(keyMap: Map<Key, GridNode<T>>, columnNodes: G
92
93
  if (item) {
93
94
  // Fill the space up until the current column with a placeholder
94
95
  let row = headerRows[i];
95
- let rowLength = row.reduce((p, c) => p + c.colspan, 0);
96
+ let rowLength = row.reduce((p, c) => p + (c.colspan ?? 1), 0);
96
97
  if (rowLength < colIndex) {
97
98
  let placeholder: GridNode<T> = {
98
99
  type: 'placeholder',
@@ -104,7 +105,7 @@ export function buildHeaderRows<T>(keyMap: Map<Key, GridNode<T>>, columnNodes: G
104
105
  level: i,
105
106
  hasChildNodes: false,
106
107
  childNodes: [],
107
- textValue: null
108
+ textValue: ''
108
109
  };
109
110
 
110
111
  // eslint-disable-next-line max-depth
@@ -135,7 +136,7 @@ export function buildHeaderRows<T>(keyMap: Map<Key, GridNode<T>>, columnNodes: G
135
136
  // Add placeholders at the end of each row that is shorter than the maximum
136
137
  let i = 0;
137
138
  for (let row of headerRows) {
138
- let rowLength = row.reduce((p, c) => p + c.colspan, 0);
139
+ let rowLength = row.reduce((p, c) => p + (c.colspan ?? 1), 0);
139
140
  if (rowLength < columnNodes.length) {
140
141
  let placeholder: GridNode<T> = {
141
142
  type: 'placeholder',
@@ -147,7 +148,7 @@ export function buildHeaderRows<T>(keyMap: Map<Key, GridNode<T>>, columnNodes: G
147
148
  level: i,
148
149
  hasChildNodes: false,
149
150
  childNodes: [],
150
- textValue: null,
151
+ textValue: '',
151
152
  prevKey: row[row.length - 1].key
152
153
  };
153
154
 
@@ -167,7 +168,7 @@ export function buildHeaderRows<T>(keyMap: Map<Key, GridNode<T>>, columnNodes: G
167
168
  level: 0,
168
169
  hasChildNodes: true,
169
170
  childNodes,
170
- textValue: null
171
+ textValue: ''
171
172
  };
172
173
 
173
174
  return row;
@@ -181,9 +182,9 @@ export class TableCollection<T> extends GridCollection<T> implements ITableColle
181
182
  body: GridNode<T>;
182
183
  _size: number = 0;
183
184
 
184
- constructor(nodes: Iterable<GridNode<T>>, prev?: ITableCollection<T>, opts?: GridCollectionOptions) {
185
+ constructor(nodes: Iterable<GridNode<T>>, prev?: ITableCollection<T> | null, opts?: GridCollectionOptions) {
185
186
  let rowHeaderColumnKeys: Set<Key> = new Set();
186
- let body: GridNode<T>;
187
+ let body: GridNode<T> | null = null;
187
188
  let columns: GridNode<T>[] = [];
188
189
  // Add cell for selection checkboxes if needed.
189
190
  if (opts?.showSelectionCheckboxes) {
@@ -225,7 +226,7 @@ export class TableCollection<T> extends GridCollection<T> implements ITableColle
225
226
  columns.unshift(rowHeaderColumn);
226
227
  }
227
228
 
228
- let rows = [];
229
+ let rows: GridNode<T>[] = [];
229
230
  let columnKeyMap = new Map();
230
231
  let visit = (node: GridNode<T>) => {
231
232
  switch (node.type) {
@@ -268,13 +269,16 @@ export class TableCollection<T> extends GridCollection<T> implements ITableColle
268
269
  });
269
270
  this.columns = columns;
270
271
  this.rowHeaderColumnKeys = rowHeaderColumnKeys;
271
- this.body = body;
272
+ this.body = body!;
272
273
  this.headerRows = headerRows;
273
- this._size = [...body.childNodes].length;
274
+ this._size = [...body!.childNodes].length;
274
275
 
275
276
  // Default row header column to the first one.
276
277
  if (this.rowHeaderColumnKeys.size === 0) {
277
- this.rowHeaderColumnKeys.add(this.columns.find(column => !column.props?.isDragButtonCell && !column.props?.isSelectionCell).key);
278
+ let col = this.columns.find(column => !column.props?.isDragButtonCell && !column.props?.isSelectionCell);
279
+ if (col) {
280
+ this.rowHeaderColumnKeys.add(col.key);
281
+ }
278
282
  }
279
283
  }
280
284
 
@@ -292,24 +296,24 @@ export class TableCollection<T> extends GridCollection<T> implements ITableColle
292
296
 
293
297
  getKeyBefore(key: Key) {
294
298
  let node = this.keyMap.get(key);
295
- return node ? node.prevKey : null;
299
+ return node?.prevKey ?? null;
296
300
  }
297
301
 
298
302
  getKeyAfter(key: Key) {
299
303
  let node = this.keyMap.get(key);
300
- return node ? node.nextKey : null;
304
+ return node?.nextKey ?? null;
301
305
  }
302
306
 
303
307
  getFirstKey() {
304
- return getFirstItem(this.body.childNodes)?.key;
308
+ return getFirstItem(this.body.childNodes)?.key ?? null;
305
309
  }
306
310
 
307
311
  getLastKey() {
308
- return getLastItem(this.body.childNodes)?.key;
312
+ return getLastItem(this.body.childNodes)?.key ?? null;
309
313
  }
310
314
 
311
315
  getItem(key: Key) {
312
- return this.keyMap.get(key);
316
+ return this.keyMap.get(key) ?? null;
313
317
  }
314
318
 
315
319
  at(idx: number) {
@@ -339,7 +343,7 @@ export class TableCollection<T> extends GridCollection<T> implements ITableColle
339
343
  // Otherwise combine the text of each of the row header columns.
340
344
  let rowHeaderColumnKeys = this.rowHeaderColumnKeys;
341
345
  if (rowHeaderColumnKeys) {
342
- let text = [];
346
+ let text: string[] = [];
343
347
  for (let cell of row.childNodes) {
344
348
  let column = this.columns[cell.index];
345
349
  if (rowHeaderColumnKeys.has(column.key) && cell.textValue) {
@@ -54,7 +54,7 @@ export class TableColumnLayout<T> {
54
54
  if (uncontrolledColumns.has(col.key)) {
55
55
  return [col.key, uncontrolledWidths.get(col.key)];
56
56
  } else {
57
- return [col.key, controlledColumns.get(col.key).props.width];
57
+ return [col.key, controlledColumns.get(col.key)!.props.width];
58
58
  }
59
59
  }));
60
60
  }
@@ -91,7 +91,7 @@ export class TableColumnLayout<T> {
91
91
  freeze = false;
92
92
  } else if (freeze) {
93
93
  // freeze columns to the left to their previous pixel value
94
- newWidths.set(column.key, prevColumnWidths.get(column.key));
94
+ newWidths.set(column.key, prevColumnWidths.get(column.key) ?? 0);
95
95
  } else {
96
96
  newWidths.set(column.key, column.props.width ?? uncontrolledWidths.get(column.key));
97
97
  }
@@ -15,7 +15,7 @@ import {PartialNode} from '@react-stately/collections';
15
15
  import React, {JSX, ReactElement} from 'react';
16
16
  import {TableHeaderProps} from '@react-types/table';
17
17
 
18
- function TableHeader<T>(props: TableHeaderProps<T>): ReactElement { // eslint-disable-line @typescript-eslint/no-unused-vars
18
+ function TableHeader<T>(props: TableHeaderProps<T>): ReactElement | null { // eslint-disable-line @typescript-eslint/no-unused-vars
19
19
  return null;
20
20
  }
21
21
 
package/src/TableUtils.ts CHANGED
@@ -44,7 +44,7 @@ export function parseStaticWidth(width: number | string, tableWidth: number): nu
44
44
  }
45
45
 
46
46
 
47
- export function getMaxWidth(maxWidth: number | string, tableWidth: number): number {
47
+ export function getMaxWidth(maxWidth: number | string | null | undefined, tableWidth: number): number {
48
48
  return maxWidth != null
49
49
  ? parseStaticWidth(maxWidth, tableWidth)
50
50
  : Number.MAX_SAFE_INTEGER;
@@ -63,7 +63,18 @@ export interface IColumn {
63
63
  maxWidth?: number | string,
64
64
  width?: number | string,
65
65
  defaultWidth?: number | string,
66
- key?: Key
66
+ key: Key
67
+ }
68
+
69
+ interface FlexItem {
70
+ frozen: boolean,
71
+ baseSize: number,
72
+ hypotheticalMainSize: number,
73
+ min: number,
74
+ max: number,
75
+ flex: number,
76
+ targetMainSize: number,
77
+ violation: number
67
78
  }
68
79
 
69
80
  /**
@@ -93,12 +104,12 @@ export interface IColumn {
93
104
  */
94
105
  export function calculateColumnSizes(availableWidth: number, columns: IColumn[], changedColumns: Map<Key, ColumnSize>, getDefaultWidth, getDefaultMinWidth) {
95
106
  let hasNonFrozenItems = false;
96
- let flexItems = columns.map((column, index) => {
107
+ let flexItems: FlexItem[] = columns.map((column, index) => {
97
108
  let width = changedColumns.get(column.key) != null ? changedColumns.get(column.key) : column.width ?? column.defaultWidth ?? getDefaultWidth?.(index) ?? '1fr';
98
109
  let frozen = false;
99
110
  let baseSize = 0;
100
111
  let flex = 0;
101
- let targetMainSize = null;
112
+ let targetMainSize = 0;
102
113
  if (isStatic(width)) {
103
114
  baseSize = parseStaticWidth(width, availableWidth);
104
115
  frozen = true;
@@ -232,7 +243,7 @@ export function calculateColumnSizes(availableWidth: number, columns: IColumn[],
232
243
  return cascadeRounding(flexItems);
233
244
  }
234
245
 
235
- function cascadeRounding(flexItems): number[] {
246
+ function cascadeRounding(flexItems: FlexItem[]): number[] {
236
247
  /*
237
248
  Given an array of floats that sum to an integer, this rounds the floats
238
249
  and returns an array of integers with the same sum.
@@ -240,7 +251,7 @@ function cascadeRounding(flexItems): number[] {
240
251
 
241
252
  let fpTotal = 0;
242
253
  let intTotal = 0;
243
- let roundedArray = [];
254
+ let roundedArray: number[] = [];
244
255
  flexItems.forEach(function (item) {
245
256
  let float = item.targetMainSize;
246
257
  let integer = Math.round(float + fpTotal) - intTotal;
@@ -108,7 +108,7 @@ export function useTableColumnResizeState<T>(props: TableColumnResizeStateProps<
108
108
 
109
109
  let updateResizedColumns = useCallback((key: Key, width: number): Map<Key, ColumnSize> => {
110
110
  let newSizes = columnLayout.resizeColumnWidth(state.collection, uncontrolledWidths, key, width);
111
- let map = new Map(Array.from(uncontrolledColumns).map(([key]) => [key, newSizes.get(key)]));
111
+ let map = new Map(Array.from(uncontrolledColumns).map(([key]) => [key, newSizes.get(key)!]));
112
112
  map.set(key, width);
113
113
  setUncontrolledWidths(map);
114
114
  return newSizes;
@@ -24,7 +24,7 @@ export interface TableState<T> extends GridState<T, ITableCollection<T>> {
24
24
  /** Whether the row selection checkboxes should be displayed. */
25
25
  showSelectionCheckboxes: boolean,
26
26
  /** The current sorted column and direction. */
27
- sortDescriptor: SortDescriptor,
27
+ sortDescriptor: SortDescriptor | null,
28
28
  /** Calls the provided onSortChange handler with the provided column key and sort direction. */
29
29
  sort(columnKey: Key, direction?: 'ascending' | 'descending'): void,
30
30
  /** Whether keyboard navigation is disabled, such as when the arrow keys should be handled by a component within a cell. */
@@ -94,11 +94,11 @@ export function useTableState<T extends object>(props: TableStateProps<T>): Tabl
94
94
  disabledKeys,
95
95
  selectionManager,
96
96
  showSelectionCheckboxes: props.showSelectionCheckboxes || false,
97
- sortDescriptor: props.sortDescriptor,
97
+ sortDescriptor: props.sortDescriptor ?? null,
98
98
  isKeyboardNavigationDisabled: collection.size === 0 || isKeyboardNavigationDisabled,
99
99
  setKeyboardNavigationDisabled,
100
100
  sort(columnKey: Key, direction?: 'ascending' | 'descending') {
101
- props.onSortChange({
101
+ props.onSortChange?.({
102
102
  column: columnKey,
103
103
  direction: direction ?? (props.sortDescriptor?.column === columnKey
104
104
  ? OPPOSITE_SORT_DIRECTION[props.sortDescriptor.direction]
@@ -140,11 +140,11 @@ function generateTreeGridCollection<T>(nodes, opts: TreeGridCollectionOptions):
140
140
  expandedKeys = new Set()
141
141
  } = opts;
142
142
 
143
- let body: GridNode<T>;
144
- let flattenedRows = [];
143
+ let body: GridNode<T> | null = null;
144
+ let flattenedRows: GridNode<T>[] = [];
145
145
  let columnCount = 0;
146
146
  let userColumnCount = 0;
147
- let originalColumns = [];
147
+ let originalColumns: GridNode<T>[] = [];
148
148
  let keyMap = new Map();
149
149
 
150
150
  if (opts?.showSelectionCheckboxes) {
@@ -155,7 +155,7 @@ function generateTreeGridCollection<T>(nodes, opts: TreeGridCollectionOptions):
155
155
  columnCount++;
156
156
  }
157
157
 
158
- let topLevelRows = [];
158
+ let topLevelRows: GridNode<T>[] = [];
159
159
  let visit = (node: GridNode<T>) => {
160
160
  switch (node.type) {
161
161
  case 'body':
@@ -183,6 +183,7 @@ function generateTreeGridCollection<T>(nodes, opts: TreeGridCollectionOptions):
183
183
  }
184
184
  visit(node);
185
185
  }
186
+
186
187
  columnCount += userColumnCount;
187
188
 
188
189
  // Update each grid node in the treegrid table with values specific to a treegrid structure. Also store a set of flattened row nodes for TableCollection to consume
@@ -192,7 +193,7 @@ function generateTreeGridCollection<T>(nodes, opts: TreeGridCollectionOptions):
192
193
  // to TableCollection. Index, level, and parent keys are all changed to reflect a flattened row structure rather than the treegrid structure
193
194
  // values automatically calculated via CollectionBuilder
194
195
  if (node.type === 'item') {
195
- let childNodes = [];
196
+ let childNodes: GridNode<T>[] = [];
196
197
  for (let child of node.childNodes) {
197
198
  if (child.type === 'cell') {
198
199
  let cellClone = {...child};
@@ -202,7 +203,7 @@ function generateTreeGridCollection<T>(nodes, opts: TreeGridCollectionOptions):
202
203
  childNodes.push({...cellClone});
203
204
  }
204
205
  }
205
- let clone = {...node, childNodes: childNodes, parentKey: body.key, level: 1, index: globalRowCount++};
206
+ let clone: GridNode<T> = {...node, childNodes: childNodes, parentKey: body!.key, level: 1, index: globalRowCount++};
206
207
  flattenedRows.push(clone);
207
208
  }
208
209
 
@@ -218,7 +219,7 @@ function generateTreeGridCollection<T>(nodes, opts: TreeGridCollectionOptions):
218
219
  Object.assign(node, newProps);
219
220
  keyMap.set(node.key, node);
220
221
 
221
- let lastNode: GridNode<T>;
222
+ let lastNode: GridNode<T> | null = null;
222
223
  let rowIndex = 0;
223
224
  for (let child of node.childNodes) {
224
225
  if (!(child.type === 'item' && expandedKeys !== 'all' && !expandedKeys.has(node.key))) {
@@ -250,8 +251,8 @@ function generateTreeGridCollection<T>(nodes, opts: TreeGridCollectionOptions):
250
251
  }
251
252
  };
252
253
 
253
- let last: GridNode<T>;
254
- topLevelRows.forEach((node: GridNode<T>, i) => {
254
+ let last: GridNode<T> | null = null;
255
+ for (let [i, node] of topLevelRows.entries()) {
255
256
  visitNode(node as GridNode<T>, i);
256
257
 
257
258
  if (last) {
@@ -262,7 +263,7 @@ function generateTreeGridCollection<T>(nodes, opts: TreeGridCollectionOptions):
262
263
  }
263
264
 
264
265
  last = node;
265
- });
266
+ }
266
267
 
267
268
  if (last) {
268
269
  last.nextKey = null;
@@ -272,6 +273,6 @@ function generateTreeGridCollection<T>(nodes, opts: TreeGridCollectionOptions):
272
273
  keyMap,
273
274
  userColumnCount,
274
275
  flattenedRows,
275
- tableNodes: [...originalColumns, {...body, childNodes: flattenedRows}]
276
+ tableNodes: [...originalColumns, {...body!, childNodes: flattenedRows}]
276
277
  };
277
278
  }