@neovici/cosmoz-treenode-navigator 3.1.1 → 4.0.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.
@@ -1,516 +1,315 @@
1
- import '@polymer/polymer/lib/elements/custom-style';
2
- import '@polymer/paper-input/paper-input';
3
- import '@polymer/paper-button/paper-button';
4
- import '@polymer/paper-icon-button/paper-icon-button';
5
- import '@polymer/iron-icons/iron-icons';
6
- import '@polymer/iron-list/iron-list';
1
+ import { component, useEffect, useState, useMemo, useCallback } from 'haunted';
2
+ import { html } from 'lit-html';
3
+ import { when } from 'lit/directives/when.js';
7
4
 
8
- import { PolymerElement } from '@polymer/polymer/polymer-element';
9
- import { html } from '@polymer/polymer/lib/utils/html-tag';
5
+ import '@neovici/cosmoz-input';
6
+ import '@neovici/cosmoz-autocomplete';
7
+ import { notifyProperty } from '@neovici/cosmoz-utils/lib/hooks/use-notify-property';
10
8
 
11
- import { Tree } from '@neovici/cosmoz-tree';
12
- import { translatable } from '@neovici/cosmoz-i18next';
9
+ import {
10
+ computeDataPlane,
11
+ computeRowClass,
12
+ computeSearching,
13
+ getNodeName,
14
+ hasChildren,
15
+ nodeStyles,
16
+ normalizeNodes,
17
+ onNodeDblClicked,
18
+ renderLevel,
19
+ showGlobalSearchBtn
20
+ } from './helpers';
13
21
 
14
- /**
15
- Navigator through object with treelike datastructure.
22
+ const TreenodeNavigator = host => {
23
+ const {
24
+ /**
25
+ * The main node structure
26
+ */
27
+ tree,
28
+ /**
29
+ * Placeholder for search field.
30
+ */
31
+ searchPlaceholder,
32
+ /**
33
+ * Text displayed when local search has finished
34
+ * to suggest a search on the entire tree
35
+ */
36
+ searchGlobalPlaceholder,
37
+ /**
38
+ * Minimum length of searchValue to trigger a search
39
+ */
40
+ searchMinLength,
41
+ nodePath
42
+ } = host,
43
+ /**
44
+ * The path of the opened node
45
+ */
46
+ [openNodePath, setOpenNodePath] = useState(''),
47
+ /**
48
+ * The nodes on the path of the opened node
49
+ */
50
+ [nodesOnOpenNodePath, setNodesOnOpenNodePath] = useState([]),
51
+ /**
52
+ * The highlighted (focused) node
53
+ * This is the node which is currently selected in the list
54
+ */
55
+ [highlightedNode, setHighlightedNode] = useState(),
56
+ /**
57
+ * The search string
58
+ */
59
+ [searchValue, setSearchValue] = useState(''),
60
+ /**
61
+ * The currently displayed node list
62
+ */
63
+ dataPlane = useMemo(() => {
64
+ return computeDataPlane(
65
+ computeSearching(searchValue, searchMinLength),
66
+ searchValue,
67
+ renderLevel(openNodePath, tree),
68
+ tree
69
+ );
70
+ }, [tree, openNodePath, highlightedNode, searchValue]),
71
+ /**
72
+ * Opens a node (renderLevel) based on a given path
73
+ * @param {object} clickedNode - The clicked node
74
+ * @return {undefined}
75
+ */
76
+ openNode = useCallback(clickedNode => {
77
+ if (hasChildren(clickedNode)) {
78
+ setOpenNodePath(clickedNode.path);
79
+ setSearchValue('');
80
+ }
81
+ if (!clickedNode) {
82
+ setOpenNodePath('');
83
+ setSearchValue('');
84
+ setHighlightedNode(null);
85
+ }
86
+ }, []),
87
+ /**
88
+ * Returns true, if the path of a node should be visible in the view
89
+ * @param {Number} index - The node's current index in the list
90
+ * @param {Object} parentSectionName - The nodes current parent section name
91
+ * @return {Boolean} - If the path should be visible
92
+ */
93
+ renderSection = (index, parentSectionName) => {
94
+ const _dataPlane = computeDataPlane(
95
+ computeSearching(searchValue, searchMinLength),
96
+ searchValue,
97
+ renderLevel(openNodePath, tree),
98
+ tree
99
+ );
100
+ if (
101
+ !computeSearching(searchValue, searchMinLength) ||
102
+ index == null ||
103
+ _dataPlane == null ||
104
+ index >= _dataPlane.length ||
105
+ parentSectionName == null
106
+ ) {
107
+ return false;
108
+ }
109
+ if (index === 0) {
110
+ return true;
111
+ }
112
+ const prevItem = _dataPlane[index - 1];
113
+ return prevItem.parentSectionName !== parentSectionName;
114
+ };
115
+
116
+ useEffect(() => {
117
+ if (!openNodePath) {
118
+ notifyProperty(host, 'highlightedNodePath', '');
119
+ notifyProperty(host, 'nodesOnNodePath', []);
120
+ return;
121
+ }
122
+ setNodesOnOpenNodePath(
123
+ normalizeNodes(tree.getPathNodes(openNodePath).filter(item => item))
124
+ );
125
+ }, [openNodePath]);
16
126
 
17
- @demo demo/index.html
18
- @demo demo/rtl.html rtl issue
127
+ useEffect(() => {
128
+ if (!openNodePath) {
129
+ notifyProperty(host, 'highlightedNodePath', '');
130
+ return;
131
+ }
132
+ setNodesOnOpenNodePath(
133
+ normalizeNodes(tree.getPathNodes(openNodePath).filter(item => item))
134
+ );
135
+ }, [openNodePath]);
19
136
 
20
- @appliesMixin translatable
21
- */
22
- class CosmozTreenodeNavigator extends translatable(PolymerElement) {
23
- /* eslint-disable-next-line max-lines-per-function */
24
- static get template() {
25
- return html`
26
- <style>
27
- :host {
28
- --cosmoz-treenode-navigator-select-node-icon-color: var(--primary-color, white);
29
- --cosmoz-treenode-navigator-list-item-focused-color: #f0f8ff;
30
- }
137
+ useEffect(() => {
138
+ if (nodePath !== undefined) {
139
+ host.dispatchEvent(
140
+ new CustomEvent('select-node', {
141
+ detail: {}
142
+ })
143
+ );
144
+ }
145
+ }, [nodePath]);
31
146
 
32
- #header {
33
- margin: 0 16px;
34
- }
147
+ useEffect(() => {
148
+ notifyProperty(
149
+ host,
150
+ 'highlightedNodePath',
151
+ !highlightedNode ? '' : highlightedNode.path
152
+ );
153
+ }, [highlightedNode]);
35
154
 
36
- #header a {
37
- text-decoration: none;
38
- color: inherit;
39
- }
155
+ return html`
156
+ <style>
157
+ :host {
158
+ --cosmoz-treenode-navigator-select-node-icon-color: var(
159
+ --primary-color,
160
+ white
161
+ );
162
+ --cosmoz-treenode-navigator-list-item-focused-color: #f0f8ff;
163
+ }
40
164
 
41
- .path {
42
- display: flex;
43
- align-items: center;
44
- flex-wrap: wrap;
45
- }
165
+ #header {
166
+ margin: 0 16px;
167
+ }
46
168
 
47
- .section {
48
- background-color: #f5f5f5;
49
- padding: 5px;
50
- }
169
+ #header a {
170
+ text-decoration: none;
171
+ color: inherit;
172
+ }
51
173
 
52
- .slash {
53
- margin: 0 2px;
54
- }
174
+ .icon {
175
+ display: inline-block;
176
+ position: relative;
177
+ padding: 8px;
178
+ outline: none;
179
+ user-select: none;
180
+ cursor: pointer;
181
+ z-index: 0;
182
+ line-height: 1;
183
+ width: 40px;
184
+ height: 40px;
185
+ box-sizing: border-box;
186
+ }
55
187
 
56
- .pointer {
57
- cursor: pointer;
58
- }
188
+ .path {
189
+ display: flex;
190
+ align-items: center;
191
+ flex-wrap: wrap;
192
+ }
59
193
 
60
- iron-list {
61
- height: var(--cosmoz-treenode-navigator-list-height, 50vh);
62
- }
194
+ .slash {
195
+ margin: 0 2px;
196
+ }
63
197
 
64
- .node-item {
65
- font-family: 'Roboto', 'Noto', sans-serif;
66
- @apply --paper-font-common-base;
67
- -webkit-font-smoothing: antialiased;
68
- padding: 6px 12px;
69
- font-size: 16px;
70
- font-weight: 400;
71
- line-height: 24px;
72
- height: 40px;
73
- display: flex;
74
- align-items: center;
75
- }
198
+ .pointer {
199
+ cursor: pointer;
200
+ }
76
201
 
77
- .node-item.selected {
78
- transition: background-color 0.2s ease-out;
79
- -moz-transition: background-color 0.2s ease-out;
80
- -o-transition: background-color 0.2s ease-out;
81
- background-color: var(--cosmoz-treenode-navigator-list-item-focused-color);
82
- }
202
+ cosmoz-listbox {
203
+ box-shadow: none;
204
+ display: block;
205
+ height: var(--cosmoz-treenode-navigator-list-height, 50vh);
206
+ position: static;
207
+ width: 100%;
208
+ }
83
209
 
84
- .node-item.selected paper-icon-button {
85
- transition: color 0.8s ease-out;
86
- -moz-transition: color 0.8s ease-out;
87
- -o-transition: color 0.8s ease-out;
88
- color: var(--cosmoz-treenode-navigator-select-node-icon-color);
89
- }
90
- </style>
210
+ .btn-ghost {
211
+ background: transparent;
212
+ border: none;
213
+ cursor: pointer;
214
+ margin: 0 0.29em;
215
+ padding: 0.7em 0.57em;
216
+ text-transform: uppercase;
217
+ }
218
+ </style>
91
219
  <div id="header">
92
220
  <h3 class="path">
93
- <paper-icon-button data-path on-click="openNode" icon="home"></paper-icon-button>
94
- <template is="dom-repeat" items="[[ _nodesOnOpenNodePath ]]" as="node">
95
- <span class="slash">/</span>
96
- <span class="pointer" tabindex="0" data-path$="[[ node.path ]]" on-click="openNode" on-keydown="_clickOnEnterOrSpace">[[ _getNodeName(node) ]]
97
- </span>
98
- </template>
221
+ <span class="icon" @click=${ () => openNode() }>
222
+ <svg
223
+ viewBox="0 0 24 24"
224
+ preserveAspectRatio="xMidYMid meet"
225
+ focusable="false"
226
+ style="pointer-events: none; display: block; width: 100%; height: 100%;"
227
+ >
228
+ <g><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"></path></g>
229
+ </svg>
230
+ </span>
231
+ ${ nodesOnOpenNodePath.map(node => {
232
+ return html` <span class="slash">/</span>
233
+ <span class="pointer" tabindex="0" @click="${ () => openNode(node) }"
234
+ >${ getNodeName(node) }</span
235
+ >`;
236
+ }) }
99
237
  </h3>
100
- <paper-input tabindex="0" id="searchInput" label="[[ searchPlaceholder ]]" title$="[[ searchPlaceholder ]]" value="{{ searchValue }}">
101
- <paper-icon-button icon="clear" slot="suffix" hidden$="[[ !_search ]]" on-click="_clearSearch"></paper-icon-button>
102
- </paper-input>
238
+ <cosmoz-input
239
+ tabindex="0"
240
+ .value=${ searchValue }
241
+ .placeholder="${ searchPlaceholder }"
242
+ .label="${ searchPlaceholder }"
243
+ @input="${ ({ target }) => setSearchValue(target.value) }"
244
+ />
103
245
  </div>
104
- <iron-list id="ironList" items="[[ dataPlane ]]" as="node" selected-item="{{ highlightedNode }}" selection-enabled>
105
- <template>
106
- <div tabindex$="[[ tabIndex ]]">
107
- <div hidden$="[[ !_renderSection(_search, index, dataPlane, node.parentSectionName) ]]" class="section">[[ node.parentSectionName ]]
108
- </div>
109
- <div class$="[[_computeRowClass('node-item pointer', selected)]]">
110
- <div style="flex: auto" on-dblclick="_onNodeDblClicked">[[ node.name ]]</div>
111
- <paper-icon-button hidden$="[[ !hasChildren(node) ]]" icon="icons:arrow-forward" data-path$="[[ node.path ]]" on-click="openNode">
112
- </paper-icon-button>
113
- </div>
114
- </div>
115
- </template>
116
- </iron-list>
117
- <paper-button hidden$="[[ !_showGlobalSearchBtn(_search, _openNodePath) ]]" on-click="tryGlobalSearch">[[ searchGlobalPlaceholder ]]
118
- </paper-button>
119
- `;
120
- }
121
-
122
- static get is() {
123
- return 'cosmoz-treenode-navigator';
124
- }
246
+ ${ when(
247
+ tree,
248
+ () => html`
249
+ <cosmoz-listbox
250
+ .query="${ searchValue }"
251
+ .items="${ dataPlane }"
252
+ .textual="${ item => item.name }"
253
+ .itemRenderer=${ (node, index) => html`
254
+ <div class="node-item-wrapper">
255
+ <style>
256
+ ${ nodeStyles }
257
+ </style>
258
+ ${ when(
259
+ renderSection(index, node.parentSectionName),
260
+ () => html`
261
+ <div class="section">${ node.parentSectionName }</div>
262
+ `
263
+ ) }
264
+ <div
265
+ class="${ computeRowClass(
266
+ 'node-item pointer',
267
+ node,
268
+ highlightedNode
269
+ ) }"
270
+ @click="${ () => setHighlightedNode(node) }"
271
+ @dblclick="${ e => onNodeDblClicked(e, host) }"
272
+ >
273
+ <div style="flex: auto">${ node.name }</div>
274
+ ${ when(
275
+ hasChildren(node),
276
+ () => html`
277
+ <span class="icon" @click="${ () => openNode(node) }">
278
+ <svg
279
+ viewBox="0 0 24 24"
280
+ preserveAspectRatio="xMidYMid meet"
281
+ focusable="false"
282
+ style="pointer-events: none; display: block; width: 100%; height: 100%;"
283
+ >
284
+ <g>
285
+ <path
286
+ d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"
287
+ ></path>
288
+ </g>
289
+ </svg>
290
+ </span>
291
+ `
292
+ ) }
293
+ </div>
294
+ </div>
295
+ ` }
296
+ </cosmoz-listbox>`
297
+ ) }
298
+ ${ when(
299
+ showGlobalSearchBtn(
300
+ computeSearching(searchValue, searchMinLength),
301
+ openNodePath
302
+ ),
303
+ () => html`
304
+ <button class="btn-ghost" @click="${ () => setOpenNodePath('') }">
305
+ ${ searchGlobalPlaceholder }
306
+ </button>
307
+ `
308
+ ) }
309
+ `;
310
+ };
125
311
 
126
- /* eslint-disable-next-line max-lines-per-function */
127
- static get properties() {
128
- return {
129
- /*
130
- * The main node structure
131
- */
132
- tree: {
133
- type: Tree
134
- },
135
- /*
136
- * The currently displayed node list
137
- */
138
- dataPlane: {
139
- type: Array,
140
- notify: true,
141
- computed: '_computeDataPlane(_search, searchValue, _renderedLevel, tree)'
142
- },
143
- /*
144
- * The selected node
145
- */
146
- selectedNode: {
147
- type: Object,
148
- computed: '_getNode(nodePath, tree)',
149
- notify: true
150
- },
151
- /*
152
- * The path of the selected node
153
- * This is the node which was highlighted and after the user tapped the select button
154
- */
155
- nodePath: {
156
- type: String,
157
- value: '',
158
- notify: true,
159
- observer: '_nodePathChanged'
160
- },
161
- /*
162
- * The nodes on the path of the selected node
163
- */
164
- nodesOnNodePath: {
165
- type: Array,
166
- computed: '_getTreePathParts(nodePath, tree)',
167
- notify: true
168
- },
169
- /*
170
- * The highlighted (focused) node
171
- * This is the node which is currently selected in the list
172
- */
173
- highlightedNode: {
174
- type: Object,
175
- observer: '_highlightedNodeChanged'
176
- },
177
- /*
178
- * The path string of highlighted (focused) node
179
- */
180
- highlightedNodePath: {
181
- type: String,
182
- notify: true
183
- },
184
- /*
185
- * The search string
186
- */
187
- searchValue: {
188
- type: String,
189
- value: ''
190
- },
191
- /*
192
- * Placeholder for search field.
193
- */
194
- searchPlaceholder: {
195
- type: String,
196
- value: 'Search'
197
- },
198
- /*
199
- * Text displayed when local search has finished
200
- * to suggest a search on the entire tree
201
- */
202
- searchGlobalPlaceholder: {
203
- type: String,
204
- value: 'Click to search again but globally.'
205
- },
206
- /*
207
- * Minimum length of searchValue to trigger a search
208
- */
209
- searchMinLength: {
210
- type: Number,
211
- value: 1
212
- },
213
-
214
- /** PRIVATE */
215
-
216
- /*
217
- * Nodes (children) to be displayed when opening a node
218
- */
219
- _renderedLevel: {
220
- type: Array,
221
- computed: '_renderLevel(_openNodePath, tree)'
222
- },
223
- /*
224
- * The path of the opened node
225
- */
226
- _openNodePath: {
227
- type: String,
228
- value: ''
229
- },
230
- /*
231
- * The nodes on the path of the opened node
232
- */
233
- _nodesOnOpenNodePath: {
234
- type: Array,
235
- computed: '_getTreePathParts(_openNodePath, tree)'
236
- },
237
- /*
238
- * Whether a search should be executed
239
- */
240
- _search: {
241
- type: Boolean,
242
- computed: '_computeSearching(searchValue, searchMinLength)'
243
- }
244
- };
245
- }
246
- /**
247
- * Selects the doubled clicked node and dispatches an node-dblclicked event.
248
- * @param {Event} event The triggering event
249
- * @return {undefined}
250
- */
251
- _onNodeDblClicked(event) {
252
- this.$.ironList.selectIndex(event.model.index);
253
- this.dispatchEvent(new CustomEvent('node-dblclicked', {
254
- composed: true,
255
- bubbles: false,
256
- detail: {
257
- model: event.model
258
- }
259
- }));
260
- }
261
- /**
262
- * Focusses the search input.
263
- * @return {undefined}
264
- */
265
- focus() {
266
- this.$.searchInput.focus();
267
- }
268
- /**
269
- * Returns the found nodes based on a search string and a given tree to be searched
270
- * @param {Boolean} searching - If true, a search should be executed
271
- * @param {String} searchString - The search string
272
- * @param {Array} renderedLevel - The node list on which the search should be executed
273
- * @param {Tree} tree - The main tree
274
- * @return {Array} - The found nodes
275
- */
276
- _computeDataPlane(searching, searchString, renderedLevel, tree) {
277
- if (searching && tree) {
278
- const results = tree.searchNodes(searchString, renderedLevel, false);
279
- return this._normalizeNodes(results);
280
- }
281
- return renderedLevel;
282
- }
283
- /**
284
- * Returns a node array with the children of a node on the given path
285
- * If the node doesn't have children, the node gets returned
286
- * @param {String} pathLocator - The separated address parts of a node
287
- * @param {Tree} tree - The main tree
288
- * @return {Array} - Nodes
289
- */
290
- _renderLevel(pathLocator, tree) {
291
- if (!tree) {
292
- return;
293
- }
294
- const node = tree.getNodeByPathLocator(pathLocator),
295
- children = tree.getChildren(node),
296
- level = tree.hasChildren(node) ? children : node,
297
- sortFunc = (a, b) => {
298
- // First sort based on "folder" status (containing children)
299
- if (this.hasChildren(a)) {
300
- if (!this.hasChildren(b)) {
301
- return -1;
302
- }
303
- } else if (this.hasChildren(b)) {
304
- return 1;
305
- }
306
- // Then sort on searchProperty
307
- const val1 = a[this.tree.searchProperty],
308
- val2 = b[this.tree.searchProperty];
309
-
310
- if (val1 > val2) {
311
- return 1;
312
- }
313
- if (val1 < val2) {
314
- return -1;
315
- }
316
- return 0;
317
- };
318
-
319
- return this._normalizeNodes(level).sort(sortFunc);
320
- }
321
- /**
322
- * Normalizes and returns an Array of nodes
323
- * with the properties name, path, parentSectionName, children
324
- * @param {Array} nodes - The input nodes
325
- * @return {Array} - The normalized nodes
326
- */
327
- _normalizeNodes(nodes) {
328
- if (!Array.isArray(nodes)) {
329
- return [];
330
- }
331
- return nodes.map(node => {
332
- if (!node) {
333
- return node;
334
- }
335
- const path = node.pathLocator || node.path,
336
- pathLocatorSeparator = this.tree.pathLocatorSeparator,
337
- parentPath = path.includes(pathLocatorSeparator) ? path.substring(0, path.lastIndexOf(pathLocatorSeparator)) : path;
338
- return {
339
- name: node[this.tree.searchProperty],
340
- path,
341
- children: node[this.tree.childProperty],
342
- parentSectionName: this.tree.getPathString(parentPath, this.tree.searchProperty)
343
- };
344
- });
345
- }
346
- /**
347
- * Returns a node based on a given path locator.
348
- * If pathLocator is empty or not defined, null gets returned.
349
- * If pathLocator is only partly valid, the last valid node gets returned.
350
- * @param {String} pathLocator - The separated address parts of a node
351
- * @param {Tree} tree - The main tree
352
- * @return {Object} - The found node
353
- */
354
- _getNode(pathLocator, tree) {
355
- if (!tree || !pathLocator) {
356
- return null;
357
- }
358
-
359
- const node = this.tree.getNodeByPathLocator(pathLocator);
360
- let nodes;
361
-
362
- if (!node) {
363
- nodes = tree.getPathNodes(pathLocator).filter(n => n != null);
364
- }
365
- return nodes && nodes.length > 0 ? nodes.pop() : node;
366
- }
367
- /**
368
- * Returns the nodes on a path specified by a given path locator
369
- * @param {String} pathLocator - The separated address parts of a node
370
- * @param {Tree} tree - The main tree
371
- * @return {Array} - The found nodes or empty array
372
- */
373
- _getTreePathParts(pathLocator, tree) {
374
- if (!tree || !pathLocator) {
375
- return [];
376
- }
377
- return this._normalizeNodes(tree.getPathNodes(pathLocator));
378
- }
379
- /**
380
- * Clears the search input
381
- * @param {Event} e - The trigger event
382
- * @return {undefined}
383
- */
384
- _clearSearch(e) {
385
- e.preventDefault();
386
- e.stopPropagation();
387
- this.searchValue = '';
388
- }
389
- /**
390
- * Returns the name of a given node
391
- * @param {Object} node - The node
392
- * @return {String} - The name
393
- */
394
- _getNodeName(node) {
395
- return node[this.tree.searchProperty];
396
- }
397
- /**
398
- * Sets the highlightedNodePath when highlightedNode changed
399
- * @param {Object} node - The highlighted node
400
- * @return {undefined}
401
- */
402
- _highlightedNodeChanged(node) {
403
- if (!node) {
404
- this.highlightedNodePath = '';
405
- return;
406
- }
407
- this.highlightedNodePath = node.path;
408
- }
409
- /**
410
- * Returns true if a given node has children
411
- * @param {Object} node - The node
412
- * @return {Boolean} - True if node has children
413
- */
414
- hasChildren(node) {
415
- return this.tree.hasChildren(node);
416
- }
417
- /**
418
- * Opens a node (renderLevel) based on a given path
419
- * @param {Event} e - The triggering event
420
- * @param {Event} e.currentTarget.dataset.path - The path locator attribute
421
- * @return {undefined}
422
- */
423
- openNode(e) {
424
- this._openNodePath = e.currentTarget.dataset.path;
425
- this.searchValue = '';
426
- e.currentTarget.parentElement.blur();
427
-
428
- // stop event propagation to prevent iron-list trying to select the current item while it will be removed
429
- e.preventDefault();
430
- e.stopPropagation();
431
- }
432
- /**
433
- * Gets called if the selected node (path) has changed
434
- * @param {String} path - The path of the newly selected node
435
- * @return {undefined}
436
- */
437
- _nodePathChanged(path) {
438
- if (!path) {
439
- this.highlightedNodePath = '';
440
- return;
441
- }
442
- this.highlightedNodePath = path;
443
- }
444
- /**
445
- * Returns true, if the button should be visible
446
- * @param {Boolean} searching - If a search is currently executed
447
- * @param {String} openNodeLevelPath - The open node level
448
- * @return {Boolean} - The visibility of the button
449
- */
450
- _showGlobalSearchBtn(searching, openNodeLevelPath) {
451
- return searching && openNodeLevelPath !== '';
452
- }
453
- /**
454
- * Triggers a global search
455
- * @return {undefined}
456
- */
457
- tryGlobalSearch() {
458
- this._openNodePath = '';
459
- }
460
- /**
461
- * Returns true, if a search string is eligable to trigger a search
462
- * @param {String} value - The search string
463
- * @param {Number} searchMinLength - The minimum length of value to be valid
464
- * @return {Boolean} - If a search should be triggered
465
- */
466
- _computeSearching(value, searchMinLength) {
467
- return value && value.length >= searchMinLength && value !== '';
468
- }
469
- /**
470
- * Returns true, if the path of a node should be visible in the view
471
- * @param {Boolean} searching - If a search is currently executed
472
- * @param {Number} index - The node's current index in the list
473
- * @param {Array} dataPlane - The node list
474
- * @param {Object} parentSectionName - The nodes current parent section name
475
- * @return {Boolean} - If the path should be visible
476
- */
477
- _renderSection(searching, index, dataPlane, parentSectionName) {
478
- if (!searching || index == null || dataPlane == null || index >= dataPlane.length || parentSectionName == null) {
479
- return false;
480
- }
481
- if (index === 0) {
482
- return true;
483
- }
484
- const prevItem = dataPlane[index - 1];
485
- if (prevItem.parentSectionName === parentSectionName) {
486
- return false;
487
- }
488
- return true;
489
- }
490
- /**
491
- * Triggers a click event on the currentTarget
492
- * if space or enter key was pressed
493
- * @param {Event} e - The event
494
- * @return {undefined}
495
- */
496
- _clickOnEnterOrSpace(e) {
497
- if (e.keyCode === 13 || e.keyCode === 32) {
498
- // enter or space pressed!
499
- const fnName = 'click',
500
- target = e.currentTarget,
501
- // eslint-disable-next-line no-new-func
502
- fn = new Function('target', 'fnName', 'return target.' + fnName + '()');
503
- fn(target, fnName);
504
- }
505
- }
506
- /**
507
- * Returns the classes of a row based its selection state
508
- * @param {String} classes - The default classes
509
- * @param {Boolean} selected - If the row is currently selected
510
- * @return {String} - The CSS classes
511
- */
512
- _computeRowClass(classes, selected) {
513
- return selected ? classes + ' selected' : classes;
514
- }
515
- }
516
- customElements.define(CosmozTreenodeNavigator.is, CosmozTreenodeNavigator);
312
+ customElements.define(
313
+ 'cosmoz-treenode-navigator',
314
+ component(TreenodeNavigator)
315
+ );