Skip to content

Commit f9c2ba8

Browse files
authored
refactor: Simplify iterNodes implementation (#1689)
Moved filter logic into native TreeWalker implementation for better performance and readability. Removed support for open shadow root traversal. Radios now resolve siblings within their rootNode scope instead of the main document root.
1 parent f8740f2 commit f9c2ba8

File tree

3 files changed

+40
-34
lines changed

3 files changed

+40
-34
lines changed

src/components/common/mixins/combo-box.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,18 +115,20 @@ export abstract class IgcBaseComboBoxLikeComponent extends LitElement {
115115
}
116116

117117
export function getItems<T extends HTMLElement>(root: Node, tagName: string) {
118-
return iterNodes<T>(root, 'SHOW_ELEMENT', (item) => item.matches(tagName));
118+
return iterNodes<T>(root, {
119+
show: 'SHOW_ELEMENT',
120+
filter: (item) => item.matches(tagName),
121+
});
119122
}
120123

121124
export function getActiveItems<T extends HTMLElement & { disabled: boolean }>(
122125
root: Node,
123126
tagName: string
124127
) {
125-
return iterNodes<T>(
126-
root,
127-
'SHOW_ELEMENT',
128-
(item) => item.matches(tagName) && !item.disabled
129-
);
128+
return iterNodes<T>(root, {
129+
show: 'SHOW_ELEMENT',
130+
filter: (item) => item.matches(tagName) && !item.disabled,
131+
});
130132
}
131133

132134
export function getNextActiveItem<

src/components/common/util.ts

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -100,36 +100,40 @@ export function isDefined<T = unknown>(value: T) {
100100
return value !== undefined;
101101
}
102102

103-
export function* iterNodes<T = Node>(
103+
export type IterNodesOptions<T = Node> = {
104+
show?: keyof typeof NodeFilter;
105+
filter?: (node: T) => boolean;
106+
};
107+
108+
function createNodeFilter<T extends Node>(predicate: (node: T) => boolean) {
109+
return {
110+
acceptNode: (node: T): number =>
111+
!predicate || predicate(node)
112+
? NodeFilter.FILTER_ACCEPT
113+
: NodeFilter.FILTER_SKIP,
114+
};
115+
}
116+
117+
export function* iterNodes<T extends Node>(
104118
root: Node,
105-
whatToShow?: keyof typeof NodeFilter,
106-
filter?: (node: T) => boolean
119+
options?: IterNodesOptions<T>
107120
): Generator<T> {
108121
if (!isDefined(globalThis.document)) {
109122
return;
110123
}
111124

112-
const iter = globalThis.document.createTreeWalker(
113-
root,
114-
NodeFilter[whatToShow ?? 'SHOW_ALL']
115-
);
116-
117-
let node = iter.nextNode() as T;
125+
const whatToShow = options?.show
126+
? NodeFilter[options.show]
127+
: NodeFilter.SHOW_ALL;
118128

119-
while (node) {
120-
if (filter) {
121-
if (filter(node)) {
122-
yield node;
123-
}
124-
} else {
125-
yield node;
126-
}
129+
const nodeFilter = options?.filter
130+
? createNodeFilter(options.filter)
131+
: undefined;
127132

128-
if (isElement(node) && node.shadowRoot && node.shadowRoot.mode === 'open') {
129-
yield* iterNodes(node.shadowRoot, whatToShow, filter);
130-
}
133+
const treeWalker = document.createTreeWalker(root, whatToShow, nodeFilter);
131134

132-
node = iter.nextNode() as T;
135+
while (treeWalker.nextNode()) {
136+
yield treeWalker.currentNode as T;
133137
}
134138
}
135139

src/components/radio/utils.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { iterNodes } from '../common/util.js';
1+
import { type IterNodesOptions, getRoot, iterNodes } from '../common/util.js';
22
import type IgcRadioComponent from './radio.js';
33

44
type RadioQueryResult = {
@@ -36,13 +36,13 @@ export function getGroup(member: IgcRadioComponent) {
3636
return result;
3737
}
3838

39-
const iterator = iterNodes<IgcRadioComponent>(
40-
globalThis.document.documentElement,
41-
'SHOW_ELEMENT',
42-
(radio) => radio.matches(member.tagName) && radio.name === member.name
43-
);
39+
const options: IterNodesOptions<IgcRadioComponent> = {
40+
show: 'SHOW_ELEMENT',
41+
filter: (radio) =>
42+
radio.matches(member.tagName) && radio.name === member.name,
43+
};
4444

45-
for (const each of iterator) {
45+
for (const each of iterNodes<IgcRadioComponent>(getRoot(member), options)) {
4646
result.radios.push(each);
4747

4848
if (!each.disabled) {

0 commit comments

Comments
 (0)