diff --git a/documents/src/pages/elements/combo-box.md b/documents/src/pages/elements/combo-box.md
index 48448fbdf4..f4ffd2cb75 100644
--- a/documents/src/pages/elements/combo-box.md
+++ b/documents/src/pages/elements/combo-box.md
@@ -233,25 +233,29 @@ comboBox.data = [
{ label: 'Brazil', value: 'br' },
{ label: 'Argentina', value: 'ar' }
];
-const customFilter = (comboBox) => {
+const createCustomFilter = (comboBox) => {
let query = '';
let queryRegExp;
const getRegularExpressionOfQuery = () => {
if (comboBox.query !== query || !queryRegExp) {
query = comboBox.query || '';
+ // Non-word characters are escaped to prevent ReDoS attack.
+ // This serves as a demo only.
+ // For production, use a proven implementation instead.
queryRegExp = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
}
return queryRegExp;
};
return (item) => {
+ const value = item.value;
+ const label = item.label;
const regex = getRegularExpressionOfQuery();
- const result = query === item.value || regex.test(item.label);
- regex.lastIndex = 0; // do not forget to reset last index
+ const result = regex.test(value) || regex.test(label);
return result;
};
};
-comboBox.filter = customFilter(comboBox);
+comboBox.filter = createCustomFilter(comboBox);
```
```css
.wrapper {
@@ -270,7 +274,7 @@ comboBox.filter = customFilter(comboBox);
const comboBox = document.querySelector('ef-combo-box');
// Make a scoped re-usable filter for performance
-const customFilter = (comboBox) => {
+const createCustomFilter = (comboBox) => {
let query = ''; // reference query string for validating queryRegExp cache state
let queryRegExp; // cache RegExp
@@ -280,6 +284,9 @@ const customFilter = (comboBox) => {
const getRegularExpressionOfQuery = () => {
if (comboBox.query !== query || !queryRegExp) {
query = comboBox.query || '';
+ // Non-word characters are escaped to prevent ReDoS attack.
+ // This serves as a demo only.
+ // For production, use a proven implementation instead.
queryRegExp = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
}
return queryRegExp;
@@ -287,24 +294,24 @@ const customFilter = (comboBox) => {
// return scoped custom filter
return (item) => {
+ const value = item.value;
+ const label = item.label;
const regex = getRegularExpressionOfQuery();
- const result = query === item.value || regex.test(item.label);
- regex.lastIndex = 0; // do not forget to reset last index
+ const result = regex.test(value) || regex.test(label);
return result;
};
};
-comboBox.filter = customFilter(comboBox);
+comboBox.filter = createCustomFilter(comboBox);
```
```typescript
-import { ItemData } from '@refinitiv-ui/elements/item';
-import { ComboBox, ComboBoxFilter } from '@refinitiv-ui/elements/combo-box';
+import type { ComboBox, ComboBoxFilter } from '@refinitiv-ui/elements/combo-box';
const comboBox = document.querySelector('ef-combo-box');
// Make a scoped re-usable filter for performance
-const customFilter = (comboBox: ComboBox): ComboBoxFilter => {
+const createCustomFilter = (comboBox: ComboBox): ComboBoxFilter => {
let query = ''; // reference query string for validating queryRegExp cache state
let queryRegExp: RegExp; // cache RegExp
@@ -314,26 +321,30 @@ const customFilter = (comboBox: ComboBox): ComboBoxFilter => {
const getRegularExpressionOfQuery = () => {
if (comboBox.query !== query || !queryRegExp) {
query = comboBox.query || '';
+ // Non-word characters are escaped to prevent ReDoS attack.
+ // This serves as a demo only.
+ // For production, use a proven implementation instead.
queryRegExp = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
}
return queryRegExp;
};
// return scoped custom filter
- return (item: ItemData) => {
+ return (item) => {
+ const value = item.value as string;
+ const label = item.label as string;
const regex = getRegularExpressionOfQuery();
- const result = query === item.value || regex.test(item.label as string);
- regex.lastIndex = 0; // do not forget to reset last index
+ const result = regex.test(value) || regex.test(label);
return result;
};
};
if (comboBox) {
- comboBox.filter = customFilter(comboBox);
+ comboBox.filter = createCustomFilter(comboBox);
}
```
-@> Regardless of filter configuration Combo Box always treats `type: 'header'` items as group headers, which persist as long as at least one item within the group is visible.
+@> Regardless of filter configuration, Combo Box always treats `type: 'header'` items as group headers, which persist as long as at least one item within the group is visible.
## Asynchronous filtering
@@ -395,6 +406,9 @@ comboBox.filter = null;
// A function to make request. In real life scenario it may wrap fetch
const request = (query, value) => {
+ // Non-word characters are escaped to prevent ReDoS attack.
+ // This serves as a demo only.
+ // For production, use a proven implementation instead.
const regex = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
// Always keep a promise to let Combo Box know that the data is loading
@@ -410,13 +424,11 @@ const request = (query, value) => {
selected: true,
hidden: query ? !regex.test(item.label) : false
}));
- regex.lastIndex = 0;
continue;
}
if (query && regex.test(item.label)) {
filterData.push(item);
- regex.lastIndex = 0;
}
}
}
diff --git a/documents/src/pages/elements/tree-select.md b/documents/src/pages/elements/tree-select.md
index c4db151b2d..8fee93e880 100644
--- a/documents/src/pages/elements/tree-select.md
+++ b/documents/src/pages/elements/tree-select.md
@@ -366,12 +366,148 @@ setTimeout(() => { el.opened = true; }, 1000);
*> If the number of selected items is likely to be large, pills may not be a good choice for display or performance.
## Filtering
-Tree select has built in text filtering and selection editing.
+
+Tree Select has built in text filtering applied on item's `label` property and selection editing.
By clicking the `Selected` button, Tree Select allows the items to be filtered by selected state, and that subset to be operated on in isolation from the main item list.
-For custom filtering, Tree Select provides an identical interface as Combo Box. You provide a predicate function that tests an item. Please consult the [Combo Box docs](./elements/combo-box) for details on how to construct a compatible filter.
+To customise filtering, provide a predicate function testing each item to `filter` property. A typical example is to apply filter on multiple data properties (e.g. `label` and `value` as in the example below).
+
+::
+```javascript
+::import-elements::
+const treeSelect = document.querySelector('ef-tree-select');
+treeSelect.data = [
+ { label: 'EMEA', value: 'emea', expanded: true, items: [
+ { label: 'France', value: 'fr' },
+ { label: 'Russian Federation', value: 'ru' },
+ { label: 'Spain', value: 'es' },
+ { label: 'United Kingdom', value: 'gb' }
+ ]},
+ { label: 'APAC', value: 'apac', expanded: true, items: [
+ { label: 'China', value: 'ch' },
+ { label: 'Australia', value: 'au' },
+ { label: 'India', value: 'in' },
+ { label: 'Thailand', value: 'th' }
+ ]},
+ { label: 'AMERS', value: 'amers', expanded: true, items: [
+ { label: 'Canada', value: 'ca' },
+ { label: 'United States', value: 'us' },
+ { label: 'Brazil', value: 'br' },
+ { label: 'Argentina', value: 'ar' }
+ ]}
+];
+const createCustomFilter = (treeSelect) => {
+ let query = '';
+ let queryRegExp;
+ const getRegularExpressionOfQuery = () => {
+ if (treeSelect.query !== query || !queryRegExp) {
+ query = treeSelect.query || '';
+ // Non-word characters are escaped to prevent ReDoS attack.
+ // This serves as a demo only.
+ // For production, use a proven implementation instead.
+ queryRegExp = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
+ }
+ return queryRegExp;
+ };
+ return (item, treeManager) => {
+ const treeNode = treeManager.getTreeNode(item);
+ const { label, value } = treeNode;
+ const regex = getRegularExpressionOfQuery();
+ const result = regex.test(value) || regex.test(label);
+ return result;
+ };
+};
+treeSelect.filter = createCustomFilter(treeSelect);
+```
+```css
+.wrapper {
+ padding: 5px;
+ height: 300px;
+}
+```
+```html
+
+
+
+```
+::
+
+```javascript
+const treeSelect = document.querySelector('ef-tree-select');
+
+// Make a scoped re-usable filter for performance
+const createCustomFilter = (treeSelect) => {
+ let query = ''; // reference query string for validating queryRegExp cache state
+ let queryRegExp; // cache RegExp
+
+ // Get current RegExp, or renew if out of date
+ // this is fetched on demand by filter/renderer
+ // only created once per query
+ const getRegularExpressionOfQuery = () => {
+ if (treeSelect.query !== query || !queryRegExp) {
+ query = treeSelect.query || '';
+ // Non-word characters are escaped to prevent ReDoS attack.
+ // This serves as a demo only.
+ // For production, use a proven implementation instead.
+ queryRegExp = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
+ }
+ return queryRegExp;
+ };
+
+ // return scoped custom filter
+ return (item, treeManager) => {
+ const treeNode = treeManager.getTreeNode(item);
+ const { label, value } = treeNode;
+ const regex = getRegularExpressionOfQuery();
+ const result = regex.test(value) || regex.test(label);
+ return result;
+ };
+};
+
+treeSelect.filter = createCustomFilter(treeSelect);
+```
+
+```typescript
+import type { TreeSelect, TreeSelectFilter } from '@refinitiv-ui/elements/tree-select';
+
+const tree = document.querySelector('ef-tree');
+
+// Make a scoped re-usable filter for performance
+const createCustomFilter = (treeSelect: TreeSelect): TreeSelectFilter => {
+ let query = ''; // reference query string for validating queryRegExp cache state
+ let queryRegExp: RegExp; // cache RegExp
+
+ // Get current RegExp, or renew if out of date
+ // this is fetched on demand by filter/renderer
+ // only created once per query
+ const getRegularExpressionOfQuery = () => {
+ if (treeSelect.query !== query || !queryRegExp) {
+ query = treeSelect.query || '';
+ // Non-word characters are escaped to prevent ReDoS attack.
+ // This serves as a demo only.
+ // For production, use a proven implementation instead.
+ queryRegExp = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
+ }
+ return queryRegExp;
+ };
+
+ // return scoped custom filter
+ return (item, treeManager) => {
+ const treeNode = treeManager.getTreeNode(item)!;
+ const { label, value } = treeNode;
+ const regex = getRegularExpressionOfQuery();
+ const result = regex.test(value) || regex.test(label);
+ return result;
+ };
+};
+
+if (treeSelect) {
+ treeSelect.filter = createCustomFilter(treeSelect);
+}
+```
+@> Regardless of filter configuration, Tree Select always shows parent items as long as at least one of their child is visible.
## Limiting Selected Items
Tree Select offers a convenient way to limit the number of selected items using `max` property. If users attempt to select more items than the specified limit, "Done" button will be automatically disabled.
@@ -690,7 +826,7 @@ ef-tree-select {
## Accessibility
::a11y-intro::
-Tree select is assigned `role="combo-box"` and it supports similar aria attributes as Combo box such as `aria-multiselectable`, `aria-label` or `aria-labelledby`. It has a modal which has `role="dialog"` and it contains Tree, its filter and controls. When opened, focus is managed within the dialog itself.
+Tree Select is assigned `role="combo-box"` and it supports similar aria attributes as Combo box such as `aria-multiselectable`, `aria-label` or `aria-labelledby`. It has a modal which has `role="dialog"` and it contains Tree, its filter and controls. When opened, focus is managed within the dialog itself.
`ef-tree-select` has already managed role and keyboard navigation but you should set accessible name to the element by using `aria-label` or `aria-labelledby`.
diff --git a/documents/src/pages/elements/tree.md b/documents/src/pages/elements/tree.md
index b297588331..c518adc3fb 100644
--- a/documents/src/pages/elements/tree.md
+++ b/documents/src/pages/elements/tree.md
@@ -604,7 +604,161 @@ export const createTreeRenderer = (
tree.renderer = createTreeRenderer(tree)
```
+## Filtering
+
+Filtering happens when `query` property or attribute is not empty. By Default, the filter is applied on the data `label` property. Developers may wish to do their own filtering by implementing the `filter` property. A typical example is to apply filter on multiple data properties e.g. `label` and `value`.
+
+::
+```javascript
+::import-elements::
+const tree = document.querySelector('ef-tree');
+tree.data = [
+ { label: 'EMEA', value: 'emea', expanded: true, items: [
+ { label: 'France', value: 'fr' },
+ { label: 'Russian Federation', value: 'ru' },
+ { label: 'Spain', value: 'es' },
+ { label: 'United Kingdom', value: 'gb' }
+ ]},
+ { label: 'APAC', value: 'apac', expanded: true, items: [
+ { label: 'China', value: 'ch' },
+ { label: 'Australia', value: 'au' },
+ { label: 'India', value: 'in' },
+ { label: 'Thailand', value: 'th' }
+ ]},
+ { label: 'AMERS', value: 'amers', expanded: true, items: [
+ { label: 'Canada', value: 'ca' },
+ { label: 'United States', value: 'us' },
+ { label: 'Brazil', value: 'br' },
+ { label: 'Argentina', value: 'ar' }
+ ]}
+];
+const createCustomFilter = (tree) => {
+ let query = '';
+ let queryRegExp;
+ const getRegularExpressionOfQuery = () => {
+ if (tree.query !== query || !queryRegExp) {
+ query = tree.query || '';
+ // Non-word characters are escaped to prevent ReDoS attack.
+ // This serves as a demo only.
+ // For production, use a proven implementation instead.
+ queryRegExp = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
+ }
+ return queryRegExp;
+ };
+ return (item, manager) => {
+ const treeNode = manager.getTreeNode(item);
+ const { label, value } = treeNode;
+ const regex = getRegularExpressionOfQuery();
+ const result = regex.test(value) || regex.test(label);
+ return result;
+ };
+};
+tree.filter = createCustomFilter(tree);
+
+const input = document.getElementById('query');
+input.addEventListener('value-changed', e => {
+ tree.query = e.detail.value;
+});
+```
+```css
+.wrapper {
+ padding: 5px;
+ width: 300px;
+ height: 430px;
+}
+
+#query {
+ width: 200px;
+}
+```
+```html
+
+
+
+
+
+
+```
+::
+
+```javascript
+const tree = document.querySelector('ef-tree');
+
+// Make a scoped re-usable filter for performance
+const createCustomFilter = (tree) => {
+ let query = ''; // reference query string for validating queryRegExp cache state
+ let queryRegExp; // cache RegExp
+
+ // Get current RegExp, or renew if out of date
+ // this is fetched on demand by filter/renderer
+ // only created once per query
+ const getRegularExpressionOfQuery = () => {
+ if (tree.query !== query || !queryRegExp) {
+ query = tree.query || '';
+ // Non-word characters are escaped to prevent ReDoS attack.
+ // This serves as a demo only.
+ // For production, use a proven implementation instead.
+ queryRegExp = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
+ }
+ return queryRegExp;
+ };
+
+ // return scoped custom filter
+ return (item, manager) => {
+ const treeNode = manager.getTreeNode(item);
+ const { label, value } = treeNode;
+ const regex = getRegularExpressionOfQuery();
+ const result = regex.test(value) || regex.test(label);
+ return result;
+ };
+};
+
+tree.filter = createCustomFilter(tree);
+```
+
+```typescript
+import type { Tree, TreeFilter } from '@refinitiv-ui/elements/tree';
+
+const tree = document.querySelector('ef-tree');
+
+// Make a scoped re-usable filter for performance
+const createCustomFilter = (tree: Tree): TreeFilter => {
+ let query = ''; // reference query string for validating queryRegExp cache state
+ let queryRegExp: RegExp; // cache RegExp
+
+ // Get current RegExp, or renew if out of date
+ // this is fetched on demand by filter/renderer
+ // only created once per query
+ const getRegularExpressionOfQuery = () => {
+ if (tree.query !== query || !queryRegExp) {
+ query = tree.query || '';
+ // Non-word characters are escaped to prevent ReDoS attack.
+ // This serves as a demo only.
+ // For production, use a proven implementation instead.
+ queryRegExp = new RegExp(query.replace(/(\W)/g, '\\$1'), 'i');
+ }
+ return queryRegExp;
+ };
+
+ // return scoped custom filter
+ return (item, manager) => {
+ const treeNode = manager.getTreeNode(item)!;
+ const { label, value } = treeNode;
+ const regex = getRegularExpressionOfQuery();
+ const result = regex.test(value) || regex.test(label);
+ return result;
+ };
+};
+
+if (tree) {
+ tree.filter = createCustomFilter(tree);
+}
+```
+
+@> Regardless of filter configuration, Tree always shows parent items as long as at least one of their child is visible.
+
## Accessibility
+
::a11y-intro::
`ef-tree` is assigned `role="tree"` and can include properties such as `aria-multiselectable`, `aria-label`, or `aria-labelledby`. It receives focus once at host and it is navigable through items using `Up` and `Down` arrow keys and expandable or collapsable using `Left` and `Right`. Each item is assigned `role="treeitem"` and can include properties such as `aria-selected` or `aria-checked` in `multiple` mode.
diff --git a/packages/elements/src/combo-box/__demo__/index.html b/packages/elements/src/combo-box/__demo__/index.html
index d3a3713520..711017c7fc 100644
--- a/packages/elements/src/combo-box/__demo__/index.html
+++ b/packages/elements/src/combo-box/__demo__/index.html
@@ -170,10 +170,10 @@
// return scoped custom filter
return (item) => {
+ const value = item.value;
+ const label = item.label;
const regex = getRegularExpressionOfQuery();
- // test on label or value
- const result = query === item.value || regex.test(item.label);
- regex.lastIndex = 0; // do not forget to reset last index
+ const result = regex.test(value) || regex.test(label);
return result;
};
};
@@ -314,13 +314,11 @@
hidden: query ? !regex.test(item.label) : false
})
);
- regex.lastIndex = 0;
continue;
}
if (query && regex.test(item.label)) {
filterData.push(item);
- regex.lastIndex = 0;
}
}
}
diff --git a/packages/elements/src/combo-box/__test__/__snapshots__/combo-box.filter.test.snap.js b/packages/elements/src/combo-box/__test__/__snapshots__/combo-box.filter.test.snap.js
index eaec676f66..8ce4157e5d 100644
--- a/packages/elements/src/combo-box/__test__/__snapshots__/combo-box.filter.test.snap.js
+++ b/packages/elements/src/combo-box/__test__/__snapshots__/combo-box.filter.test.snap.js
@@ -125,3 +125,62 @@ snapshots["combo-box/Filter Can Filter Data Default filter filters data: changed
`;
/* end snapshot combo-box/Filter Can Filter Data Default filter filters data: changed */
+snapshots["combo-box/Filter Can Filter Data Should be able to use custom filter function"] =
+`
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+/* end snapshot combo-box/Filter Can Filter Data Should be able to use custom filter function */
+
diff --git a/packages/elements/src/combo-box/__test__/combo-box.filter.test.js b/packages/elements/src/combo-box/__test__/combo-box.filter.test.js
index 5f24fd8f03..6a43e29abc 100644
--- a/packages/elements/src/combo-box/__test__/combo-box.filter.test.js
+++ b/packages/elements/src/combo-box/__test__/combo-box.filter.test.js
@@ -1,3 +1,5 @@
+import escapeStringRegexp from 'escape-string-regexp';
+
import '@refinitiv-ui/elements/combo-box';
import '@refinitiv-ui/elemental-theme/light/ef-combo-box';
@@ -40,5 +42,37 @@ describe('combo-box/Filter', function () {
expect(el.query).to.equal(textInput, 'Query should be the same as input text: "Aland Islands"');
await expect(el).shadowDom.to.equalSnapshot(snapshotIgnore);
});
+
+ it('Should be able to use custom filter function', async function () {
+ const el = await fixture('');
+ el.data = getData();
+ await elementUpdated(el);
+
+ const createCustomFilter = (comboBox) => {
+ let query = '';
+ let queryRegExp;
+ // Items could be filtered with case-insensitive partial match of both labels & values.
+ const getRegularExpressionOfQuery = () => {
+ if (comboBox.query !== query || !queryRegExp) {
+ query = comboBox.query || '';
+ queryRegExp = new RegExp(escapeStringRegexp(query), 'i');
+ }
+ return queryRegExp;
+ };
+ return (item) => {
+ const value = item.value;
+ const label = item.label;
+ const regex = getRegularExpressionOfQuery();
+ const result = regex.test(value) || regex.test(label);
+ return result;
+ };
+ };
+ el.filter = createCustomFilter(el);
+ const textInput = 'ax';
+ await setInputEl(el, textInput);
+ await elementUpdated(el);
+ expect(el.query).to.equal(textInput, `Query should be the same as input text: "${textInput}"`);
+ await expect(el).shadowDom.to.equalSnapshot(snapshotIgnore);
+ });
});
});
diff --git a/packages/elements/src/combo-box/helpers/filter.ts b/packages/elements/src/combo-box/helpers/filter.ts
index 49dfda94cc..367f106afb 100644
--- a/packages/elements/src/combo-box/helpers/filter.ts
+++ b/packages/elements/src/combo-box/helpers/filter.ts
@@ -40,8 +40,6 @@ export const createDefaultFilter = (el: ComboBox<
const regex = getRegularExpressionOfQuery();
const result = regex.test(label);
- // this example uses global scope, so the index needs resetting
- regex.lastIndex = 0;
return result;
};
};
diff --git a/packages/elements/src/combo-box/index.ts b/packages/elements/src/combo-box/index.ts
index 37a63b234f..c31ad9d79c 100644
--- a/packages/elements/src/combo-box/index.ts
+++ b/packages/elements/src/combo-box/index.ts
@@ -114,13 +114,13 @@ export class ComboBox extends FormFieldElement {
* Set this to null when data is filtered externally, eg XHR
* @type {ComboBoxFilter | null}
*/
- @property({ type: Function, attribute: false })
+ @property({ attribute: false })
public filter: ComboBoxFilter | null = createDefaultFilter(this);
/**
* Renderer used to render list item elements
*/
- @property({ type: Function, attribute: false })
+ @property({ attribute: false })
public renderer = createComboBoxRenderer(this);
private _multiple = false;
diff --git a/packages/elements/src/list/elements/list.ts b/packages/elements/src/list/elements/list.ts
index ceb70706bd..173e602f0f 100644
--- a/packages/elements/src/list/elements/list.ts
+++ b/packages/elements/src/list/elements/list.ts
@@ -86,7 +86,7 @@ export class List extends ControlElement {
/**
* Renderer used to render list item elements
*/
- @property({ type: Function, attribute: false })
+ @property({ attribute: false })
public renderer = createListRenderer(this);
/**
diff --git a/packages/elements/src/swing-gauge/index.ts b/packages/elements/src/swing-gauge/index.ts
index 08670a89e0..661fdded65 100644
--- a/packages/elements/src/swing-gauge/index.ts
+++ b/packages/elements/src/swing-gauge/index.ts
@@ -196,7 +196,7 @@ export class SwingGauge extends ResponsiveElement {
* Custom value formatter
* @type {SwingGaugeValueFormatter}
*/
- @property({ type: Function, attribute: false })
+ @property({ attribute: false })
public valueFormatter: SwingGaugeValueFormatter = this.defaultValueFormatter;
/**
diff --git a/packages/elements/src/tooltip/index.ts b/packages/elements/src/tooltip/index.ts
index 95ecc4447a..2fdca34f72 100644
--- a/packages/elements/src/tooltip/index.ts
+++ b/packages/elements/src/tooltip/index.ts
@@ -115,7 +115,7 @@ class Tooltip extends BasicElement {
* Return `true` if the target matches
* @type {TooltipCondition}
*/
- @property({ type: Function, attribute: false })
+ @property({ attribute: false })
public condition: TooltipCondition | undefined;
/**
@@ -124,7 +124,7 @@ class Tooltip extends BasicElement {
* If the content is not present, tooltip will not be displayed
* @type {TooltipRenderer}
*/
- @property({ type: Function, attribute: false })
+ @property({ attribute: false })
public renderer: TooltipRenderer | undefined;
/**
diff --git a/packages/elements/src/tree-select/__demo__/countries.js b/packages/elements/src/tree-select/__demo__/countries.js
index 1a5841bb27..bf1995dca1 100644
--- a/packages/elements/src/tree-select/__demo__/countries.js
+++ b/packages/elements/src/tree-select/__demo__/countries.js
@@ -1,5 +1,5 @@
/* eslint-disable */
-const treeCollection = [
+export const countries = [
{
value: 'AFR',
label: 'Africa',
diff --git a/packages/elements/src/tree-select/__demo__/index.html b/packages/elements/src/tree-select/__demo__/index.html
index 3a2126c148..0a8065f7ba 100644
--- a/packages/elements/src/tree-select/__demo__/index.html
+++ b/packages/elements/src/tree-select/__demo__/index.html
@@ -3,7 +3,6 @@
Tree Select
-
+
+
+
+ Items could be filtered with case-insensitive partial match of both labels & values.
+ There is a debounce rate of 500ms applied.
+