@react-aria/collections
Advanced tools
Comparing version 3.0.0-nightly-e37ad74f5-241101 to 3.0.0-nightly-e4497fdb6-250110
@@ -148,2 +148,84 @@ | ||
} | ||
// TODO: this is pretty specific to menu, will need to check if it is generic enough | ||
// Will need to handle varying levels I assume but will revisit after I get searchable menu working for base menu | ||
// TODO: an alternative is to simply walk the collection and add all item nodes that match the filter and any sections/separators we encounter | ||
// to an array, then walk that new array and fix all the next/Prev keys while adding them to the new collection | ||
filter(filterFn) { | ||
let newCollection = new $499e2959ba1abacc$export$408d25a4e12db025(); | ||
// This tracks the absolute last node we've visited in the collection when filtering, used for setting up the filteredCollection's lastKey and | ||
// for updating the next/prevKey for every non-filtered node. | ||
let lastNode = null; | ||
for (let node of this){ | ||
if (node.type === 'section' && node.hasChildNodes) { | ||
let clonedSection = node.clone(); | ||
let lastChildInSection = null; | ||
for (let child of this.getChildren(node.key))if (filterFn(child.textValue) || child.type === 'header') { | ||
let clonedChild = child.clone(); | ||
// eslint-disable-next-line max-depth | ||
if (lastChildInSection == null) clonedSection.firstChildKey = clonedChild.key; | ||
// eslint-disable-next-line max-depth | ||
if (newCollection.firstKey == null) newCollection.firstKey = clonedSection.key; | ||
// eslint-disable-next-line max-depth | ||
if (lastChildInSection && lastChildInSection.parentKey === clonedChild.parentKey) { | ||
lastChildInSection.nextKey = clonedChild.key; | ||
clonedChild.prevKey = lastChildInSection.key; | ||
} else clonedChild.prevKey = null; | ||
clonedChild.nextKey = null; | ||
newCollection.addNode(clonedChild); | ||
lastChildInSection = clonedChild; | ||
} | ||
// Add newly filtered section to collection if it has any valid child nodes, otherwise remove it and its header if any | ||
if (lastChildInSection) { | ||
if (lastChildInSection.type !== 'header') { | ||
clonedSection.lastChildKey = lastChildInSection.key; | ||
// If the old prev section was filtered out, will need to attach to whatever came before | ||
// eslint-disable-next-line max-depth | ||
if (lastNode == null) clonedSection.prevKey = null; | ||
else if (lastNode.type === 'section' || lastNode.type === 'separator') { | ||
lastNode.nextKey = clonedSection.key; | ||
clonedSection.prevKey = lastNode.key; | ||
} | ||
clonedSection.nextKey = null; | ||
lastNode = clonedSection; | ||
newCollection.addNode(clonedSection); | ||
} else { | ||
if (newCollection.firstKey === clonedSection.key) newCollection.firstKey = null; | ||
newCollection.removeNode(lastChildInSection.key); | ||
} | ||
} | ||
} else if (node.type === 'separator') { | ||
// will need to check if previous section key exists, if it does then we add the separator to the collection. | ||
// After the full collection is created we'll need to remove it it is the last node in the section (aka no following section after the separator) | ||
let clonedSeparator = node.clone(); | ||
clonedSeparator.nextKey = null; | ||
if ((lastNode === null || lastNode === void 0 ? void 0 : lastNode.type) === 'section') { | ||
lastNode.nextKey = clonedSeparator.key; | ||
clonedSeparator.prevKey = lastNode.key; | ||
lastNode = clonedSeparator; | ||
newCollection.addNode(clonedSeparator); | ||
} | ||
} else if (filterFn(node.textValue)) { | ||
let clonedNode = node.clone(); | ||
if (newCollection.firstKey == null) newCollection.firstKey = clonedNode.key; | ||
if (lastNode != null && lastNode.type !== 'section' && lastNode.type !== 'separator' && lastNode.parentKey === clonedNode.parentKey) { | ||
lastNode.nextKey = clonedNode.key; | ||
clonedNode.prevKey = lastNode.key; | ||
} else clonedNode.prevKey = null; | ||
clonedNode.nextKey = null; | ||
newCollection.addNode(clonedNode); | ||
lastNode = clonedNode; | ||
} | ||
} | ||
if ((lastNode === null || lastNode === void 0 ? void 0 : lastNode.type) === 'separator' && lastNode.nextKey === null) { | ||
let lastSection; | ||
if (lastNode.prevKey != null) { | ||
lastSection = newCollection.getItem(lastNode.prevKey); | ||
lastSection.nextKey = null; | ||
} | ||
newCollection.removeNode(lastNode.key); | ||
lastNode = lastSection; | ||
} | ||
newCollection.lastKey = (lastNode === null || lastNode === void 0 ? void 0 : lastNode.key) || null; | ||
return newCollection; | ||
} | ||
constructor(){ | ||
@@ -150,0 +232,0 @@ this.keyMap = new Map(); |
@@ -141,2 +141,84 @@ /* | ||
} | ||
// TODO: this is pretty specific to menu, will need to check if it is generic enough | ||
// Will need to handle varying levels I assume but will revisit after I get searchable menu working for base menu | ||
// TODO: an alternative is to simply walk the collection and add all item nodes that match the filter and any sections/separators we encounter | ||
// to an array, then walk that new array and fix all the next/Prev keys while adding them to the new collection | ||
filter(filterFn) { | ||
let newCollection = new $23b9f4fcf0fe224b$export$408d25a4e12db025(); | ||
// This tracks the absolute last node we've visited in the collection when filtering, used for setting up the filteredCollection's lastKey and | ||
// for updating the next/prevKey for every non-filtered node. | ||
let lastNode = null; | ||
for (let node of this){ | ||
if (node.type === 'section' && node.hasChildNodes) { | ||
let clonedSection = node.clone(); | ||
let lastChildInSection = null; | ||
for (let child of this.getChildren(node.key))if (filterFn(child.textValue) || child.type === 'header') { | ||
let clonedChild = child.clone(); | ||
// eslint-disable-next-line max-depth | ||
if (lastChildInSection == null) clonedSection.firstChildKey = clonedChild.key; | ||
// eslint-disable-next-line max-depth | ||
if (newCollection.firstKey == null) newCollection.firstKey = clonedSection.key; | ||
// eslint-disable-next-line max-depth | ||
if (lastChildInSection && lastChildInSection.parentKey === clonedChild.parentKey) { | ||
lastChildInSection.nextKey = clonedChild.key; | ||
clonedChild.prevKey = lastChildInSection.key; | ||
} else clonedChild.prevKey = null; | ||
clonedChild.nextKey = null; | ||
newCollection.addNode(clonedChild); | ||
lastChildInSection = clonedChild; | ||
} | ||
// Add newly filtered section to collection if it has any valid child nodes, otherwise remove it and its header if any | ||
if (lastChildInSection) { | ||
if (lastChildInSection.type !== 'header') { | ||
clonedSection.lastChildKey = lastChildInSection.key; | ||
// If the old prev section was filtered out, will need to attach to whatever came before | ||
// eslint-disable-next-line max-depth | ||
if (lastNode == null) clonedSection.prevKey = null; | ||
else if (lastNode.type === 'section' || lastNode.type === 'separator') { | ||
lastNode.nextKey = clonedSection.key; | ||
clonedSection.prevKey = lastNode.key; | ||
} | ||
clonedSection.nextKey = null; | ||
lastNode = clonedSection; | ||
newCollection.addNode(clonedSection); | ||
} else { | ||
if (newCollection.firstKey === clonedSection.key) newCollection.firstKey = null; | ||
newCollection.removeNode(lastChildInSection.key); | ||
} | ||
} | ||
} else if (node.type === 'separator') { | ||
// will need to check if previous section key exists, if it does then we add the separator to the collection. | ||
// After the full collection is created we'll need to remove it it is the last node in the section (aka no following section after the separator) | ||
let clonedSeparator = node.clone(); | ||
clonedSeparator.nextKey = null; | ||
if ((lastNode === null || lastNode === void 0 ? void 0 : lastNode.type) === 'section') { | ||
lastNode.nextKey = clonedSeparator.key; | ||
clonedSeparator.prevKey = lastNode.key; | ||
lastNode = clonedSeparator; | ||
newCollection.addNode(clonedSeparator); | ||
} | ||
} else if (filterFn(node.textValue)) { | ||
let clonedNode = node.clone(); | ||
if (newCollection.firstKey == null) newCollection.firstKey = clonedNode.key; | ||
if (lastNode != null && lastNode.type !== 'section' && lastNode.type !== 'separator' && lastNode.parentKey === clonedNode.parentKey) { | ||
lastNode.nextKey = clonedNode.key; | ||
clonedNode.prevKey = lastNode.key; | ||
} else clonedNode.prevKey = null; | ||
clonedNode.nextKey = null; | ||
newCollection.addNode(clonedNode); | ||
lastNode = clonedNode; | ||
} | ||
} | ||
if ((lastNode === null || lastNode === void 0 ? void 0 : lastNode.type) === 'separator' && lastNode.nextKey === null) { | ||
let lastSection; | ||
if (lastNode.prevKey != null) { | ||
lastSection = newCollection.getItem(lastNode.prevKey); | ||
lastSection.nextKey = null; | ||
} | ||
newCollection.removeNode(lastNode.key); | ||
lastNode = lastSection; | ||
} | ||
newCollection.lastKey = (lastNode === null || lastNode === void 0 ? void 0 : lastNode.key) || null; | ||
return newCollection; | ||
} | ||
constructor(){ | ||
@@ -143,0 +225,0 @@ this.keyMap = new Map(); |
@@ -198,7 +198,4 @@ var $499e2959ba1abacc$exports = require("./BaseCollection.main.js"); | ||
constructor(type, ownerDocument){ | ||
super(ownerDocument); | ||
this.nodeType = 8 // COMMENT_NODE (we'd use ELEMENT_NODE but React DevTools will fail to get its dimensions) | ||
; | ||
this._index = 0; | ||
this.hasSetProps = false; | ||
super(ownerDocument), this.nodeType = 8 // COMMENT_NODE (we'd use ELEMENT_NODE but React DevTools will fail to get its dimensions) | ||
, this._index = 0, this.hasSetProps = false; | ||
this.node = new (0, $499e2959ba1abacc$exports.CollectionNode)(type, `react-aria-${++ownerDocument.nodeId}`); | ||
@@ -299,14 +296,4 @@ // Start a transaction so that no updates are emitted from the collection | ||
// @ts-ignore | ||
super(null); | ||
this.nodeType = 11 // DOCUMENT_FRAGMENT_NODE | ||
; | ||
this.ownerDocument = this; | ||
this.dirtyNodes = new Set(); | ||
this.isSSR = false; | ||
this.nodeId = 0; | ||
this.nodesByProps = new WeakMap(); | ||
this.isMounted = true; | ||
this.mutatedNodes = new Set(); | ||
this.subscriptions = new Set(); | ||
this.transactionCount = 0; | ||
super(null), this.nodeType = 11 // DOCUMENT_FRAGMENT_NODE | ||
, this.ownerDocument = this, this.dirtyNodes = new Set(), this.isSSR = false, this.nodeId = 0, this.nodesByProps = new WeakMap(), this.isMounted = true, this.mutatedNodes = new Set(), this.subscriptions = new Set(), this.transactionCount = 0; | ||
this.collection = collection; | ||
@@ -313,0 +300,0 @@ this.collectionMutated = true; |
@@ -192,7 +192,4 @@ import {CollectionNode as $23b9f4fcf0fe224b$export$d68d59712b04d9d1} from "./BaseCollection.module.js"; | ||
constructor(type, ownerDocument){ | ||
super(ownerDocument); | ||
this.nodeType = 8 // COMMENT_NODE (we'd use ELEMENT_NODE but React DevTools will fail to get its dimensions) | ||
; | ||
this._index = 0; | ||
this.hasSetProps = false; | ||
super(ownerDocument), this.nodeType = 8 // COMMENT_NODE (we'd use ELEMENT_NODE but React DevTools will fail to get its dimensions) | ||
, this._index = 0, this.hasSetProps = false; | ||
this.node = new (0, $23b9f4fcf0fe224b$export$d68d59712b04d9d1)(type, `react-aria-${++ownerDocument.nodeId}`); | ||
@@ -293,14 +290,4 @@ // Start a transaction so that no updates are emitted from the collection | ||
// @ts-ignore | ||
super(null); | ||
this.nodeType = 11 // DOCUMENT_FRAGMENT_NODE | ||
; | ||
this.ownerDocument = this; | ||
this.dirtyNodes = new Set(); | ||
this.isSSR = false; | ||
this.nodeId = 0; | ||
this.nodesByProps = new WeakMap(); | ||
this.isMounted = true; | ||
this.mutatedNodes = new Set(); | ||
this.subscriptions = new Set(); | ||
this.transactionCount = 0; | ||
super(null), this.nodeType = 11 // DOCUMENT_FRAGMENT_NODE | ||
, this.ownerDocument = this, this.dirtyNodes = new Set(), this.isSSR = false, this.nodeId = 0, this.nodesByProps = new WeakMap(), this.isMounted = true, this.mutatedNodes = new Set(), this.subscriptions = new Set(), this.transactionCount = 0; | ||
this.collection = collection; | ||
@@ -307,0 +294,0 @@ this.collectionMutated = true; |
@@ -35,6 +35,6 @@ import { Collection as _Collection1, Key, Node } from "@react-types/shared"; | ||
getChildren(key: Key): Iterable<Node<T>>; | ||
getKeyBefore(key: Key): Key; | ||
getKeyAfter(key: Key): Key; | ||
getFirstKey(): Key; | ||
getLastKey(): Key; | ||
getKeyBefore(key: Key): Key | null; | ||
getKeyAfter(key: Key): Key | null; | ||
getFirstKey(): Key | null; | ||
getLastKey(): Key | null; | ||
getItem(key: Key): Node<T> | null; | ||
@@ -46,2 +46,3 @@ at(): Node<T>; | ||
commit(firstKey: Key | null, lastKey: Key | null, isSSR?: boolean): void; | ||
filter(filterFn: (nodeValue: string) => boolean): BaseCollection<T>; | ||
} | ||
@@ -48,0 +49,0 @@ export interface CachedChildrenOptions<T> { |
{ | ||
"name": "@react-aria/collections", | ||
"version": "3.0.0-nightly-e37ad74f5-241101", | ||
"version": "3.0.0-nightly-e4497fdb6-250110", | ||
"description": "Spectrum UI components in React", | ||
@@ -25,5 +25,5 @@ "license": "Apache-2.0", | ||
"dependencies": { | ||
"@react-aria/ssr": "^3.0.0-nightly-e37ad74f5-241101", | ||
"@react-aria/utils": "^3.0.0-nightly-e37ad74f5-241101", | ||
"@react-types/shared": "^3.0.0-nightly-e37ad74f5-241101", | ||
"@react-aria/ssr": "3.0.0-nightly-e4497fdb6-250110", | ||
"@react-aria/utils": "3.0.0-nightly-e4497fdb6-250110", | ||
"@react-types/shared": "3.0.0-nightly-e4497fdb6-250110", | ||
"@swc/helpers": "^0.5.0", | ||
@@ -33,9 +33,8 @@ "use-sync-external-store": "^1.2.0" | ||
"peerDependencies": { | ||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0", | ||
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" | ||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", | ||
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"stableVersion": "3.0.0-alpha.5" | ||
} | ||
} |
@@ -211,2 +211,111 @@ /* | ||
} | ||
// TODO: this is pretty specific to menu, will need to check if it is generic enough | ||
// Will need to handle varying levels I assume but will revisit after I get searchable menu working for base menu | ||
// TODO: an alternative is to simply walk the collection and add all item nodes that match the filter and any sections/separators we encounter | ||
// to an array, then walk that new array and fix all the next/Prev keys while adding them to the new collection | ||
filter(filterFn: (nodeValue: string) => boolean): BaseCollection<T> { | ||
let newCollection = new BaseCollection<T>(); | ||
// This tracks the absolute last node we've visited in the collection when filtering, used for setting up the filteredCollection's lastKey and | ||
// for updating the next/prevKey for every non-filtered node. | ||
let lastNode: Mutable<CollectionNode<T>> | null = null; | ||
for (let node of this) { | ||
if (node.type === 'section' && node.hasChildNodes) { | ||
let clonedSection: Mutable<CollectionNode<T>> = (node as CollectionNode<T>).clone(); | ||
let lastChildInSection: Mutable<CollectionNode<T>> | null = null; | ||
for (let child of this.getChildren(node.key)) { | ||
if (filterFn(child.textValue) || child.type === 'header') { | ||
let clonedChild: Mutable<CollectionNode<T>> = (child as CollectionNode<T>).clone(); | ||
// eslint-disable-next-line max-depth | ||
if (lastChildInSection == null) { | ||
clonedSection.firstChildKey = clonedChild.key; | ||
} | ||
// eslint-disable-next-line max-depth | ||
if (newCollection.firstKey == null) { | ||
newCollection.firstKey = clonedSection.key; | ||
} | ||
// eslint-disable-next-line max-depth | ||
if (lastChildInSection && lastChildInSection.parentKey === clonedChild.parentKey) { | ||
lastChildInSection.nextKey = clonedChild.key; | ||
clonedChild.prevKey = lastChildInSection.key; | ||
} else { | ||
clonedChild.prevKey = null; | ||
} | ||
clonedChild.nextKey = null; | ||
newCollection.addNode(clonedChild); | ||
lastChildInSection = clonedChild; | ||
} | ||
} | ||
// Add newly filtered section to collection if it has any valid child nodes, otherwise remove it and its header if any | ||
if (lastChildInSection) { | ||
if (lastChildInSection.type !== 'header') { | ||
clonedSection.lastChildKey = lastChildInSection.key; | ||
// If the old prev section was filtered out, will need to attach to whatever came before | ||
// eslint-disable-next-line max-depth | ||
if (lastNode == null) { | ||
clonedSection.prevKey = null; | ||
} else if (lastNode.type === 'section' || lastNode.type === 'separator') { | ||
lastNode.nextKey = clonedSection.key; | ||
clonedSection.prevKey = lastNode.key; | ||
} | ||
clonedSection.nextKey = null; | ||
lastNode = clonedSection; | ||
newCollection.addNode(clonedSection); | ||
} else { | ||
if (newCollection.firstKey === clonedSection.key) { | ||
newCollection.firstKey = null; | ||
} | ||
newCollection.removeNode(lastChildInSection.key); | ||
} | ||
} | ||
} else if (node.type === 'separator') { | ||
// will need to check if previous section key exists, if it does then we add the separator to the collection. | ||
// After the full collection is created we'll need to remove it it is the last node in the section (aka no following section after the separator) | ||
let clonedSeparator: Mutable<CollectionNode<T>> = (node as CollectionNode<T>).clone(); | ||
clonedSeparator.nextKey = null; | ||
if (lastNode?.type === 'section') { | ||
lastNode.nextKey = clonedSeparator.key; | ||
clonedSeparator.prevKey = lastNode.key; | ||
lastNode = clonedSeparator; | ||
newCollection.addNode(clonedSeparator); | ||
} | ||
} else if (filterFn(node.textValue)) { | ||
let clonedNode: Mutable<CollectionNode<T>> = (node as CollectionNode<T>).clone(); | ||
if (newCollection.firstKey == null) { | ||
newCollection.firstKey = clonedNode.key; | ||
} | ||
if (lastNode != null && (lastNode.type !== 'section' && lastNode.type !== 'separator') && lastNode.parentKey === clonedNode.parentKey) { | ||
lastNode.nextKey = clonedNode.key; | ||
clonedNode.prevKey = lastNode.key; | ||
} else { | ||
clonedNode.prevKey = null; | ||
} | ||
clonedNode.nextKey = null; | ||
newCollection.addNode(clonedNode); | ||
lastNode = clonedNode; | ||
} | ||
} | ||
if (lastNode?.type === 'separator' && lastNode.nextKey === null) { | ||
let lastSection; | ||
if (lastNode.prevKey != null) { | ||
lastSection = newCollection.getItem(lastNode.prevKey) as Mutable<CollectionNode<T>>; | ||
lastSection.nextKey = null; | ||
} | ||
newCollection.removeNode(lastNode.key); | ||
lastNode = lastSection; | ||
} | ||
newCollection.lastKey = lastNode?.key || null; | ||
return newCollection; | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
320676
3779
+ Added@react-aria/ssr@3.0.0-nightly-e4497fdb6-250110(transitive)
+ Added@react-aria/utils@3.0.0-nightly-e4497fdb6-250110(transitive)
+ Added@react-stately/utils@3.0.0-nightly-e4497fdb6-250110(transitive)
+ Added@react-types/shared@3.0.0-nightly-e4497fdb6-250110(transitive)
- Removed@react-aria/ssr@3.9.7(transitive)
- Removed@react-aria/utils@3.28.0(transitive)
- Removed@react-stately/flags@3.1.0(transitive)
- Removed@react-stately/utils@3.10.5(transitive)
- Removed@react-types/shared@3.28.0(transitive)