@openproject/primer-view-components 0.85.0 → 0.86.0-rc.d6cb0e8f5
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.
- package/app/assets/javascripts/primer_view_components.js +1 -1
- package/app/assets/javascripts/primer_view_components.js.map +1 -1
- package/app/assets/styles/primer_view_components.css +1 -1
- package/app/assets/styles/primer_view_components.css.map +1 -1
- package/app/components/primer/alpha/tree_view.css +1 -1
- package/app/components/primer/alpha/tree_view.css.json +4 -1
- package/app/components/primer/open_project/filterable_tree_view.css +1 -0
- package/app/components/primer/open_project/filterable_tree_view.css.json +14 -0
- package/app/components/primer/open_project/filterable_tree_view.js +294 -5
- package/package.json +1 -1
- package/static/arguments.json +22 -0
- package/static/audited_at.json +1 -0
- package/static/classes.json +9 -0
- package/static/constants.json +9 -0
- package/static/info_arch.json +123 -1
- package/static/previews.json +39 -0
- package/static/statuses.json +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
.TreeViewRootUlStyles{list-style:none;margin:0;padding:0}.TreeViewRootUlStyles .TreeViewItem{outline:none}:is(.TreeViewRootUlStyles .TreeViewItem):focus-visible>div{box-shadow:var(--boxShadow-thick) var(--fgColor-accent)}@media (forced-colors:active){:is(.TreeViewRootUlStyles .TreeViewItem):focus-visible>div{outline:2px solid HighlightText;outline-offset:-2}}
|
|
1
|
+
.TreeViewRootUlStyles{list-style:none;margin:0;padding:0}.TreeViewRootUlStyles .TreeViewItem{outline:none}:is(.TreeViewRootUlStyles .TreeViewItem):focus-visible>div{box-shadow:var(--boxShadow-thick) var(--fgColor-accent)}@media (forced-colors:active){:is(.TreeViewRootUlStyles .TreeViewItem):focus-visible>div{outline:2px solid HighlightText;outline-offset:-2}}.TreeViewRootUlStyles .TreeViewItemContainer{--level:1;--toggle-width:1rem;--min-item-height:2rem;border-radius:var(--borderRadius-medium);color:var(--fgColor-default);display:grid;font-size:var(--text-body-size-medium);grid-template-areas:"spacer leadingAction toggle content trailingAction";grid-template-columns:var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr var(--trailing-action-width);position:relative;width:100%;--leading-action-width:calc(var(--has-leading-action, 0)*1.5rem);--trailing-action-width:calc(var(--has-trailing-action, 0)*1.5rem);--spacer-width:calc((var(--level) - 1)*(var(--toggle-width)/2))}:is(.TreeViewRootUlStyles .TreeViewItemContainer):has([data-has-leading-action]){--has-leading-action:1}:is(.TreeViewRootUlStyles .TreeViewItemContainer):has([data-has-trailing-action]){--has-trailing-action:1}:is(.TreeViewRootUlStyles .TreeViewItemContainer):hover{background-color:var(--control-transparent-bgColor-hover)}@media (forced-colors:active){:is(.TreeViewRootUlStyles .TreeViewItemContainer):hover{outline:2px solid #0000;outline-offset:-2px}}@media (pointer:coarse){.TreeViewRootUlStyles .TreeViewItemContainer{--toggle-width:1.5rem;--min-item-height:2.75rem}}:is(.TreeViewRootUlStyles .TreeViewItemContainer):has(.TreeViewFailureMessage):hover{background-color:initial;cursor:default}@media (forced-colors:active){:is(.TreeViewRootUlStyles .TreeViewItemContainer):has(.TreeViewFailureMessage):hover{outline:none}}:is(.TreeViewRootUlStyles .TreeViewItemContainer):has([role=treeitem]:focus-visible){box-shadow:var(--boxShadow-thick) var(--fgColor-accent)}.TreeViewRootUlStyles:where([data-omit-spacer=true]) .TreeViewItemContainer{grid-template-columns:0 0 0 1fr}.TreeViewRootUlStyles .TreeViewItem>.TreeViewItemContainer:has(.TreeViewItemContent[aria-current=true]){background-color:var(--control-transparent-bgColor-selected)}:is(.TreeViewRootUlStyles .TreeViewItem>.TreeViewItemContainer:has(.TreeViewItemContent[aria-current=true])):after{background-color:var(--fgColor-accent);border-radius:var(--borderRadius-medium);content:"";height:1.5rem;left:calc(var(--base-size-8)*-1);position:absolute;top:calc(50% - var(--base-size-12));width:.25rem}@media (forced-colors:active){:is(.TreeViewRootUlStyles .TreeViewItem>.TreeViewItemContainer:has(.TreeViewItemContent[aria-current=true])):after{background-color:HighlightText}}.TreeViewRootUlStyles .TreeViewItemToggle{align-items:flex-start;color:var(--fgColor-muted);cursor:pointer;display:flex;grid-area:toggle;height:100%;justify-content:center;padding-top:calc(var(--min-item-height)/2 - var(--base-size-12)/2)}.TreeViewRootUlStyles .TreeViewItemToggleHover:hover{background-color:var(--control-transparent-bgColor-hover)}.TreeViewRootUlStyles .TreeViewItemToggleEnd{border-bottom-left-radius:var(--borderRadius-medium);border-top-left-radius:var(--borderRadius-medium)}.TreeViewRootUlStyles a.TreeViewItemContent:hover,.TreeViewRootUlStyles button.TreeViewItemContent:hover{-webkit-text-decoration:underline;text-decoration:underline;text-decoration-color:var(--control-fgColor-rest)}.TreeViewRootUlStyles :has(.TreeViewItemContent[aria-disabled=true]){cursor:not-allowed}.TreeViewRootUlStyles .TreeViewItemContent{align-items:center;cursor:pointer;display:flex;gap:var(--stack-gap-condensed);grid-area:content;height:100%;line-height:var(--custom-line-height,var(--text-body-lineHeight-medium,1.4285));outline:none;padding:0 var(--base-size-8);padding-bottom:calc((var(--min-item-height) - var(--custom-line-height, 1.3rem))/2);padding-top:calc((var(--min-item-height) - var(--custom-line-height, 1.3rem))/2)}.TreeViewRootUlStyles .TreeViewItemContent,:is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItemCheckbox{background-color:initial;border:none;text-align:left;touch-action:manipulation;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}:is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItemCheckbox{border-radius:var(--borderRadius-medium);color:var(--control-fgColor-rest);position:relative;transition:background 33.333ms linear}[aria-checked=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox{background:var(--control-checked-bgColor-rest);border-color:var(--control-checked-borderColor-rest);transition:background-color,border-color 80ms cubic-bezier(.32,0,.67,0) 0s}:is([aria-checked=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox):before{animation:checkmarkIn 80ms cubic-bezier(.65,0,.35,1) 80ms forwards;transition:visibility 0s linear 0s;visibility:visible}[aria-checked=false]:is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItem-singleSelectCheckmark{visibility:hidden}[aria-checked=mixed]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox{background:var(--control-checked-bgColor-rest);border-color:var(--control-checked-borderColor-rest);transition:background-color,border-color 80ms cubic-bezier(.32,0,.67,0) 0s}:is([aria-checked=mixed]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox):before{animation:checkmarkIn 80ms cubic-bezier(.65,0,.35,1) 80ms forwards;clip-path:none;mask-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMCIgaGVpZ2h0PSIyIiBmaWxsPSJub25lIiB2aWV3Qm94PSIwIDAgMTAgMiI+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMCAxYTEgMSAwIDAgMSAxLTFoOGExIDEgMCAxIDEgMCAySDFhMSAxIDAgMCAxLTEtMSIgY2xpcC1ydWxlPSJldmVub2RkIi8+PC9zdmc+");visibility:visible}[aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent){pointer-events:none}[aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItemContentText{color:var(--control-fgColor-disabled)}:is([aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItemVisual) svg,[aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItemVisual{fill:var(--control-fgColor-disabled)}@media (hover:hover){:is([aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox):hover{cursor:not-allowed}[aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent):hover{background-color:initial;cursor:not-allowed}}.TreeViewRootUlStyles .TreeViewItemContentText{color:var(--control-fgColor-rest);flex:1 1 auto;width:0}.TreeViewRootUlStyles:where([data-truncate-text=true]) .TreeViewItemContentText{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.TreeViewRootUlStyles:where([data-truncate-text=false]) .TreeViewItemContentText{word-break:break-word}.TreeViewRootUlStyles .TreeViewItemVisual{align-items:center;color:var(--fgColor-muted);display:flex;height:var(--custom-line-height,1.3rem)}.TreeViewRootUlStyles .TreeViewItemLeadingAction{color:var(--fgColor-muted);display:flex;grid-area:leadingAction}:is(.TreeViewRootUlStyles .TreeViewItemLeadingAction)>button{flex-shrink:1}.TreeViewRootUlStyles .TreeViewItemTrailingAction{color:var(--fgColor-muted);display:flex;grid-area:trailingAction}:is(.TreeViewRootUlStyles .TreeViewItemTrailingAction)>button{flex-shrink:1}.TreeViewRootUlStyles .TreeViewItemLevelLine{border-color:var(--borderColor-muted);border-right:var(--borderWidth-thin) solid;height:100%;width:100%}@media (hover:hover){.TreeViewRootUlStyles .TreeViewItemLevelLine{border-color:#0000}.TreeViewRootUlStyles:focus-within .TreeViewItemLevelLine,.TreeViewRootUlStyles:hover .TreeViewItemLevelLine{border-color:var(--borderColor-muted)}}.TreeViewRootUlStyles .TreeViewVisuallyHidden{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0,0,0,0);border-width:0;white-space:nowrap}.TreeViewSkeletonItemContainerStyle{align-items:center;column-gap:.5rem;display:flex;height:2rem}@media (pointer:coarse){.TreeViewSkeletonItemContainerStyle{height:2.75rem}}.TreeViewSkeletonItemContainerStyle:nth-of-type(5n+1){--tree-item-loading-width:67%}.TreeViewSkeletonItemContainerStyle:nth-of-type(5n+2){--tree-item-loading-width:47%}.TreeViewSkeletonItemContainerStyle:nth-of-type(5n+3){--tree-item-loading-width:73%}.TreeViewSkeletonItemContainerStyle:nth-of-type(5n+4){--tree-item-loading-width:64%}.TreeViewSkeletonItemContainerStyle:nth-of-type(5n+5){--tree-item-loading-width:50%}.TreeItemSkeletonTextStyles{width:var(--tree-item-loading-width,67%)}.TreeViewFailureMessage{align-items:center;display:grid;gap:.5rem;grid-template-columns:auto 1fr;width:100%}
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
".TreeViewRootUlStyles",
|
|
5
5
|
".TreeViewRootUlStyles .TreeViewItem",
|
|
6
6
|
":is(.TreeViewRootUlStyles .TreeViewItem):focus-visible>div",
|
|
7
|
-
"[data-has-leading-action]:is(.TreeViewRootUlStyles .TreeViewItem)",
|
|
8
7
|
".TreeViewRootUlStyles .TreeViewItemContainer",
|
|
8
|
+
":is(.TreeViewRootUlStyles .TreeViewItemContainer):has([data-has-leading-action])",
|
|
9
|
+
":is(.TreeViewRootUlStyles .TreeViewItemContainer):has([data-has-trailing-action])",
|
|
9
10
|
":is(.TreeViewRootUlStyles .TreeViewItemContainer):hover",
|
|
10
11
|
":is(.TreeViewRootUlStyles .TreeViewItemContainer):has(.TreeViewFailureMessage):hover",
|
|
11
12
|
":is(.TreeViewRootUlStyles .TreeViewItemContainer):has([role=treeitem]:focus-visible)",
|
|
@@ -37,6 +38,8 @@
|
|
|
37
38
|
".TreeViewRootUlStyles .TreeViewItemVisual",
|
|
38
39
|
".TreeViewRootUlStyles .TreeViewItemLeadingAction",
|
|
39
40
|
":is(.TreeViewRootUlStyles .TreeViewItemLeadingAction)>button",
|
|
41
|
+
".TreeViewRootUlStyles .TreeViewItemTrailingAction",
|
|
42
|
+
":is(.TreeViewRootUlStyles .TreeViewItemTrailingAction)>button",
|
|
40
43
|
".TreeViewRootUlStyles .TreeViewItemLevelLine",
|
|
41
44
|
".TreeViewRootUlStyles:focus-within .TreeViewItemLevelLine",
|
|
42
45
|
".TreeViewRootUlStyles:hover .TreeViewItemLevelLine",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
filterable-tree-view{display:flex;flex-direction:column;max-height:inherit;overflow:hidden}.FilterableTreeViewLayout{flex:1;min-height:0}.FilterableTreeViewTreeContainer{flex:1;min-height:0;overflow-y:auto}::highlight(primer-filterable-tree-view-search-results){background-color:var(--bgColor-attention-muted)}filterable-tree-view mark{background-color:var(--bgColor-attention-muted);color:inherit}.FilterableTreeViewLoadingSkeleton{display:none}filterable-tree-view[data-loading] .FilterableTreeViewLoadingSkeleton{display:block}filterable-tree-view[data-loading] [data-target~="filterable-tree-view.noResultsMessage"],filterable-tree-view[data-loading] tree-view{display:none}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "open_project/filterable_tree_view",
|
|
3
|
+
"selectors": [
|
|
4
|
+
"filterable-tree-view",
|
|
5
|
+
".FilterableTreeViewLayout",
|
|
6
|
+
".FilterableTreeViewTreeContainer",
|
|
7
|
+
"::highlight(primer-filterable-tree-view-search-results)",
|
|
8
|
+
"filterable-tree-view mark",
|
|
9
|
+
".FilterableTreeViewLoadingSkeleton",
|
|
10
|
+
"filterable-tree-view[data-loading] .FilterableTreeViewLoadingSkeleton",
|
|
11
|
+
"filterable-tree-view[data-loading] [data-target~=\"filterable-tree-view.noResultsMessage\"]",
|
|
12
|
+
"filterable-tree-view[data-loading] tree-view"
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -15,26 +15,57 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
15
15
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
16
16
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
17
17
|
};
|
|
18
|
-
var _FilterableTreeViewElement_instances, _FilterableTreeViewElement_filterFn, _FilterableTreeViewElement_abortController, _FilterableTreeViewElement_stateMap, _FilterableTreeViewElement_handleTreeViewEvent, _FilterableTreeViewElement_handleTreeViewNodeChecked, _FilterableTreeViewElement_restoreNodeState, _FilterableTreeViewElement_handleFilterModeEvent, _FilterableTreeViewElement_handleFilterInputEvent, _FilterableTreeViewElement_handleIncludeSubItemsCheckBoxEvent, _FilterableTreeViewElement_includeSubItems, _FilterableTreeViewElement_includeSubItemsUnder, _FilterableTreeViewElement_restoreAllNodeStates, _FilterableTreeViewElement_applyFilterOptions, _FilterableTreeViewElement_applyHighlights, _FilterableTreeViewElement_applyManualHighlights, _FilterableTreeViewElement_removeHighlights;
|
|
18
|
+
var _FilterableTreeViewElement_instances, _FilterableTreeViewElement_filterFn, _FilterableTreeViewElement_abortController, _FilterableTreeViewElement_stateMap, _FilterableTreeViewElement_debounceTimer, _FilterableTreeViewElement_fetchAbortController, _FilterableTreeViewElement_expansionSnapshot, _FilterableTreeViewElement_selectedModeSnapshot, _FilterableTreeViewElement_checkedNodeIds, _FilterableTreeViewElement_checkedNodeFormPayloads, _FilterableTreeViewElement_isFiltered, _FilterableTreeViewElement_src_get, _FilterableTreeViewElement_isAsyncMode_get, _FilterableTreeViewElement_handleTreeViewEvent, _FilterableTreeViewElement_updateCheckedNodeIds, _FilterableTreeViewElement_handleTreeViewNodeChecked, _FilterableTreeViewElement_restoreNodeState, _FilterableTreeViewElement_handleFilterModeEvent, _FilterableTreeViewElement_undoClientSideFilter, _FilterableTreeViewElement_handleFilterInputEvent, _FilterableTreeViewElement_handleIncludeSubItemsCheckBoxEvent, _FilterableTreeViewElement_includeSubItems, _FilterableTreeViewElement_includeSubItemsUnder, _FilterableTreeViewElement_restoreAllNodeStates, _FilterableTreeViewElement_scheduleAsyncFetch, _FilterableTreeViewElement_fetchAndReplaceTree, _FilterableTreeViewElement_captureExpansionState, _FilterableTreeViewElement_applyExpansionSnapshot, _FilterableTreeViewElement_snapshotExpansionState, _FilterableTreeViewElement_restoreExpansionState, _FilterableTreeViewElement_restoreSelectionState, _FilterableTreeViewElement_expandAllSubTrees, _FilterableTreeViewElement_applyAsyncHighlights, _FilterableTreeViewElement_updateRetainedSelections, _FilterableTreeViewElement_applyFilterOptions, _FilterableTreeViewElement_applyHighlights, _FilterableTreeViewElement_applyManualHighlights, _FilterableTreeViewElement_removeHighlights;
|
|
19
19
|
import { controller, target } from '@github/catalyst';
|
|
20
20
|
import { TreeViewElement } from '../alpha/tree_view/tree_view';
|
|
21
21
|
import { TreeViewSubTreeNodeElement } from '../alpha/tree_view/tree_view_sub_tree_node_element';
|
|
22
|
+
const ASYNC_DEBOUNCE_MS = 300;
|
|
22
23
|
let FilterableTreeViewElement = class FilterableTreeViewElement extends HTMLElement {
|
|
23
24
|
constructor() {
|
|
24
25
|
super(...arguments);
|
|
25
26
|
_FilterableTreeViewElement_instances.add(this);
|
|
26
27
|
_FilterableTreeViewElement_filterFn.set(this, void 0);
|
|
27
28
|
_FilterableTreeViewElement_abortController.set(this, void 0);
|
|
28
|
-
_FilterableTreeViewElement_stateMap.set(this, new Map()
|
|
29
|
+
_FilterableTreeViewElement_stateMap.set(this, new Map()
|
|
30
|
+
// Async mode state
|
|
31
|
+
);
|
|
32
|
+
// Async mode state
|
|
33
|
+
_FilterableTreeViewElement_debounceTimer.set(this, null);
|
|
34
|
+
_FilterableTreeViewElement_fetchAbortController.set(this, null
|
|
35
|
+
// nodeId → wasExpanded: taken once before the first filter query is entered, cleared when filter is removed
|
|
36
|
+
);
|
|
37
|
+
// nodeId → wasExpanded: taken once before the first filter query is entered, cleared when filter is removed
|
|
38
|
+
_FilterableTreeViewElement_expansionSnapshot.set(this, null
|
|
39
|
+
// nodeId → wasExpanded: taken before entering "selected" mode, cleared when leaving it
|
|
40
|
+
);
|
|
41
|
+
// nodeId → wasExpanded: taken before entering "selected" mode, cleared when leaving it
|
|
42
|
+
_FilterableTreeViewElement_selectedModeSnapshot.set(this, null
|
|
43
|
+
// nodeId → checkedValue: persists across tree replacements, updated on every treeViewNodeChecked event
|
|
44
|
+
);
|
|
45
|
+
// nodeId → checkedValue: persists across tree replacements, updated on every treeViewNodeChecked event
|
|
46
|
+
_FilterableTreeViewElement_checkedNodeIds.set(this, new Map()
|
|
47
|
+
// nodeId → form payload: mirrors #checkedNodeIds but stores the data needed to synthesise a hidden
|
|
48
|
+
// form input for nodes that are checked but not currently in the DOM (e.g. filtered out).
|
|
49
|
+
);
|
|
50
|
+
// nodeId → form payload: mirrors #checkedNodeIds but stores the data needed to synthesise a hidden
|
|
51
|
+
// form input for nodes that are checked but not currently in the DOM (e.g. filtered out).
|
|
52
|
+
_FilterableTreeViewElement_checkedNodeFormPayloads.set(this, new Map());
|
|
53
|
+
_FilterableTreeViewElement_isFiltered.set(this, false);
|
|
29
54
|
}
|
|
30
55
|
connectedCallback() {
|
|
31
56
|
const { signal } = (__classPrivateFieldSet(this, _FilterableTreeViewElement_abortController, new AbortController(), "f"));
|
|
32
57
|
this.addEventListener('treeViewNodeChecked', this, { signal });
|
|
33
58
|
this.addEventListener('itemActivated', this, { signal });
|
|
34
59
|
this.addEventListener('input', this, { signal });
|
|
60
|
+
if (__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "a", _FilterableTreeViewElement_isAsyncMode_get)) {
|
|
61
|
+
void __classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_fetchAndReplaceTree).call(this);
|
|
62
|
+
}
|
|
35
63
|
}
|
|
36
64
|
disconnectedCallback() {
|
|
37
65
|
__classPrivateFieldGet(this, _FilterableTreeViewElement_abortController, "f").abort();
|
|
66
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_fetchAbortController, "f")?.abort();
|
|
67
|
+
if (__classPrivateFieldGet(this, _FilterableTreeViewElement_debounceTimer, "f") !== null)
|
|
68
|
+
clearTimeout(__classPrivateFieldGet(this, _FilterableTreeViewElement_debounceTimer, "f"));
|
|
38
69
|
}
|
|
39
70
|
handleEvent(event) {
|
|
40
71
|
if (event.target === this.filterModeControl) {
|
|
@@ -56,6 +87,7 @@ let FilterableTreeViewElement = class FilterableTreeViewElement extends HTMLElem
|
|
|
56
87
|
get treeView() {
|
|
57
88
|
return this.treeViewList.closest('tree-view');
|
|
58
89
|
}
|
|
90
|
+
// ─── End async mode ─────────────────────────────────────────────────────────
|
|
59
91
|
set filterFn(newFn) {
|
|
60
92
|
__classPrivateFieldSet(this, _FilterableTreeViewElement_filterFn, newFn, "f");
|
|
61
93
|
}
|
|
@@ -144,17 +176,63 @@ let FilterableTreeViewElement = class FilterableTreeViewElement extends HTMLElem
|
|
|
144
176
|
_FilterableTreeViewElement_filterFn = new WeakMap();
|
|
145
177
|
_FilterableTreeViewElement_abortController = new WeakMap();
|
|
146
178
|
_FilterableTreeViewElement_stateMap = new WeakMap();
|
|
179
|
+
_FilterableTreeViewElement_debounceTimer = new WeakMap();
|
|
180
|
+
_FilterableTreeViewElement_fetchAbortController = new WeakMap();
|
|
181
|
+
_FilterableTreeViewElement_expansionSnapshot = new WeakMap();
|
|
182
|
+
_FilterableTreeViewElement_selectedModeSnapshot = new WeakMap();
|
|
183
|
+
_FilterableTreeViewElement_checkedNodeIds = new WeakMap();
|
|
184
|
+
_FilterableTreeViewElement_checkedNodeFormPayloads = new WeakMap();
|
|
185
|
+
_FilterableTreeViewElement_isFiltered = new WeakMap();
|
|
147
186
|
_FilterableTreeViewElement_instances = new WeakSet();
|
|
187
|
+
_FilterableTreeViewElement_src_get = function _FilterableTreeViewElement_src_get() {
|
|
188
|
+
return this.getAttribute('src');
|
|
189
|
+
};
|
|
190
|
+
_FilterableTreeViewElement_isAsyncMode_get = function _FilterableTreeViewElement_isAsyncMode_get() {
|
|
191
|
+
return !!__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "a", _FilterableTreeViewElement_src_get);
|
|
192
|
+
};
|
|
148
193
|
_FilterableTreeViewElement_handleTreeViewEvent = function _FilterableTreeViewElement_handleTreeViewEvent(origEvent) {
|
|
149
194
|
const event = origEvent;
|
|
150
195
|
// NOTE: This event only fires if someone actually activates the check mark, i.e. does not fire
|
|
151
196
|
// when calling this.treeView.setNodeCheckedValue.
|
|
152
197
|
switch (origEvent.type) {
|
|
153
198
|
case 'treeViewNodeChecked':
|
|
199
|
+
// Always track checked node IDs before delegating, so async replacements can restore selection.
|
|
200
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_updateCheckedNodeIds).call(this, event);
|
|
154
201
|
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_handleTreeViewNodeChecked).call(this, event);
|
|
155
202
|
break;
|
|
156
203
|
}
|
|
157
204
|
};
|
|
205
|
+
_FilterableTreeViewElement_updateCheckedNodeIds = function _FilterableTreeViewElement_updateCheckedNodeIds(event) {
|
|
206
|
+
if (!__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "a", _FilterableTreeViewElement_isAsyncMode_get))
|
|
207
|
+
return;
|
|
208
|
+
for (const nodeInfo of event.detail) {
|
|
209
|
+
const node = nodeInfo.node;
|
|
210
|
+
const nodeId = node.getAttribute('data-node-id');
|
|
211
|
+
if (nodeId) {
|
|
212
|
+
if (nodeInfo.checkedValue === 'false') {
|
|
213
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_checkedNodeIds, "f").delete(nodeId);
|
|
214
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_checkedNodeFormPayloads, "f").delete(nodeId);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
// In single-select mode, TreeView clears the previous selection internally
|
|
218
|
+
// (via checkOnlyAtPath) but the treeViewNodeChecked event only contains the
|
|
219
|
+
// newly selected node. Clear our tracked state so #restoreSelectionState does
|
|
220
|
+
// not re-check previously selected nodes after a tree replacement.
|
|
221
|
+
if (node.getAttribute('data-select-variant') === 'single') {
|
|
222
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_checkedNodeIds, "f").clear();
|
|
223
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_checkedNodeFormPayloads, "f").clear();
|
|
224
|
+
}
|
|
225
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_checkedNodeIds, "f").set(nodeId, nodeInfo.checkedValue);
|
|
226
|
+
const payload = { path: nodeInfo.path };
|
|
227
|
+
const dataValue = node.getAttribute('data-value');
|
|
228
|
+
if (dataValue)
|
|
229
|
+
payload.value = dataValue;
|
|
230
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_checkedNodeFormPayloads, "f").set(nodeId, payload);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_updateRetainedSelections).call(this);
|
|
235
|
+
};
|
|
158
236
|
_FilterableTreeViewElement_handleTreeViewNodeChecked = function _FilterableTreeViewElement_handleTreeViewNodeChecked(event) {
|
|
159
237
|
if (!this.treeView)
|
|
160
238
|
return;
|
|
@@ -199,19 +277,57 @@ _FilterableTreeViewElement_restoreNodeState = function _FilterableTreeViewElemen
|
|
|
199
277
|
_FilterableTreeViewElement_handleFilterModeEvent = function _FilterableTreeViewElement_handleFilterModeEvent(event) {
|
|
200
278
|
if (event.type !== 'itemActivated')
|
|
201
279
|
return;
|
|
202
|
-
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "
|
|
280
|
+
if (__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "a", _FilterableTreeViewElement_isAsyncMode_get)) {
|
|
281
|
+
if (this.filterMode === 'selected') {
|
|
282
|
+
// "selected" mode is client-side: snapshot expansion state before the filter collapses nodes,
|
|
283
|
+
// then apply client-side filter without a server round-trip.
|
|
284
|
+
__classPrivateFieldSet(this, _FilterableTreeViewElement_selectedModeSnapshot, __classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_captureExpansionState).call(this), "f");
|
|
285
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_applyFilterOptions).call(this);
|
|
286
|
+
}
|
|
287
|
+
else if (__classPrivateFieldGet(this, _FilterableTreeViewElement_selectedModeSnapshot, "f") !== null && this.queryString.length === 0) {
|
|
288
|
+
// Leaving "selected" mode with no active query: undo client-side filter and restore expansion
|
|
289
|
+
// state without a server round-trip (the full tree is already in the DOM).
|
|
290
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_undoClientSideFilter).call(this);
|
|
291
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_applyExpansionSnapshot).call(this, __classPrivateFieldGet(this, _FilterableTreeViewElement_selectedModeSnapshot, "f"));
|
|
292
|
+
__classPrivateFieldSet(this, _FilterableTreeViewElement_selectedModeSnapshot, null, "f");
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
// "all" mode with an active query, or switching away from a custom mode: use async fetch.
|
|
296
|
+
__classPrivateFieldSet(this, _FilterableTreeViewElement_selectedModeSnapshot, null, "f");
|
|
297
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_scheduleAsyncFetch).call(this);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_applyFilterOptions).call(this);
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
_FilterableTreeViewElement_undoClientSideFilter = function _FilterableTreeViewElement_undoClientSideFilter() {
|
|
305
|
+
for (const el of this.querySelectorAll('tree-view li[hidden], tree-view-sub-tree-node[hidden]')) {
|
|
306
|
+
el.removeAttribute('hidden');
|
|
307
|
+
}
|
|
203
308
|
};
|
|
204
309
|
_FilterableTreeViewElement_handleFilterInputEvent = function _FilterableTreeViewElement_handleFilterInputEvent(event) {
|
|
205
310
|
if (event.type !== 'input')
|
|
206
311
|
return;
|
|
207
|
-
|
|
312
|
+
// "selected" mode is always client-side – the server doesn't know the selection state.
|
|
313
|
+
if (__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "a", _FilterableTreeViewElement_isAsyncMode_get) && this.filterMode !== 'selected') {
|
|
314
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_scheduleAsyncFetch).call(this);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_applyFilterOptions).call(this);
|
|
318
|
+
}
|
|
208
319
|
};
|
|
209
320
|
_FilterableTreeViewElement_handleIncludeSubItemsCheckBoxEvent = function _FilterableTreeViewElement_handleIncludeSubItemsCheckBoxEvent(event) {
|
|
210
321
|
if (!this.treeView)
|
|
211
322
|
return;
|
|
212
323
|
if (event.type !== 'input')
|
|
213
324
|
return;
|
|
214
|
-
|
|
325
|
+
// In async mode, toggling include-sub-items does not require a server round-trip: the client
|
|
326
|
+
// handles the visual state entirely (checking/disabling visible descendants). The flag will be
|
|
327
|
+
// included automatically in the next filter request triggered by a query or filter-mode change.
|
|
328
|
+
if (!__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "a", _FilterableTreeViewElement_isAsyncMode_get)) {
|
|
329
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_applyFilterOptions).call(this);
|
|
330
|
+
}
|
|
215
331
|
if (this.includeSubItemsCheckBox.checked) {
|
|
216
332
|
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_includeSubItems).call(this);
|
|
217
333
|
}
|
|
@@ -247,6 +363,179 @@ _FilterableTreeViewElement_restoreAllNodeStates = function _FilterableTreeViewEl
|
|
|
247
363
|
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_restoreNodeState).call(this, subTree);
|
|
248
364
|
}
|
|
249
365
|
};
|
|
366
|
+
_FilterableTreeViewElement_scheduleAsyncFetch = function _FilterableTreeViewElement_scheduleAsyncFetch() {
|
|
367
|
+
if (__classPrivateFieldGet(this, _FilterableTreeViewElement_debounceTimer, "f") !== null)
|
|
368
|
+
clearTimeout(__classPrivateFieldGet(this, _FilterableTreeViewElement_debounceTimer, "f"));
|
|
369
|
+
__classPrivateFieldSet(this, _FilterableTreeViewElement_debounceTimer, setTimeout(() => {
|
|
370
|
+
__classPrivateFieldSet(this, _FilterableTreeViewElement_debounceTimer, null, "f");
|
|
371
|
+
void __classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_fetchAndReplaceTree).call(this);
|
|
372
|
+
}, ASYNC_DEBOUNCE_MS), "f");
|
|
373
|
+
};
|
|
374
|
+
_FilterableTreeViewElement_fetchAndReplaceTree = async function _FilterableTreeViewElement_fetchAndReplaceTree() {
|
|
375
|
+
const src = __classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "a", _FilterableTreeViewElement_src_get);
|
|
376
|
+
if (!src)
|
|
377
|
+
return;
|
|
378
|
+
const query = this.queryString;
|
|
379
|
+
const filterMode = this.filterMode || 'all';
|
|
380
|
+
const includeSubItems = this.includeSubItemsCheckBox?.checked ?? false;
|
|
381
|
+
// Snapshot expansion state the first time the user enters a filter query
|
|
382
|
+
if (!__classPrivateFieldGet(this, _FilterableTreeViewElement_isFiltered, "f") && query.length > 0) {
|
|
383
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_snapshotExpansionState).call(this);
|
|
384
|
+
__classPrivateFieldSet(this, _FilterableTreeViewElement_isFiltered, true, "f");
|
|
385
|
+
}
|
|
386
|
+
else if (__classPrivateFieldGet(this, _FilterableTreeViewElement_isFiltered, "f") && query.length === 0) {
|
|
387
|
+
__classPrivateFieldSet(this, _FilterableTreeViewElement_isFiltered, false, "f");
|
|
388
|
+
}
|
|
389
|
+
// Remember which filter state this particular request was for so we apply
|
|
390
|
+
// the correct post-processing even if the user types quickly.
|
|
391
|
+
const requestWasFiltered = query.length > 0;
|
|
392
|
+
// Abort any in-flight request
|
|
393
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_fetchAbortController, "f")?.abort();
|
|
394
|
+
const { signal } = (__classPrivateFieldSet(this, _FilterableTreeViewElement_fetchAbortController, new AbortController(), "f"));
|
|
395
|
+
const url = new URL(src, window.location.href);
|
|
396
|
+
url.searchParams.set('query', query);
|
|
397
|
+
url.searchParams.set('filter_mode', filterMode);
|
|
398
|
+
url.searchParams.set('include_sub_items', String(includeSubItems));
|
|
399
|
+
// Send currently-checked node IDs so the server can apply include-sub-items
|
|
400
|
+
// logic even for nodes that are no longer visible due to filtering / pagination.
|
|
401
|
+
for (const nodeId of __classPrivateFieldGet(this, _FilterableTreeViewElement_checkedNodeIds, "f").keys()) {
|
|
402
|
+
url.searchParams.append('checked_ids[]', nodeId);
|
|
403
|
+
}
|
|
404
|
+
this.setAttribute('data-loading', '');
|
|
405
|
+
this.setAttribute('aria-busy', 'true');
|
|
406
|
+
try {
|
|
407
|
+
const response = await fetch(url.toString(), {
|
|
408
|
+
signal,
|
|
409
|
+
headers: { Accept: 'text/html' },
|
|
410
|
+
credentials: 'same-origin',
|
|
411
|
+
method: 'GET',
|
|
412
|
+
});
|
|
413
|
+
if (!response.ok)
|
|
414
|
+
return;
|
|
415
|
+
const html = await response.text();
|
|
416
|
+
const doc = new DOMParser().parseFromString(html, 'text/html');
|
|
417
|
+
const newTreeView = doc.querySelector('tree-view');
|
|
418
|
+
if (!newTreeView)
|
|
419
|
+
return;
|
|
420
|
+
const oldTreeView = this.treeViewList?.closest('tree-view');
|
|
421
|
+
if (!oldTreeView)
|
|
422
|
+
return;
|
|
423
|
+
// Invalidate old stateMap entries – the referenced DOM nodes no longer exist after replacement.
|
|
424
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_stateMap, "f").clear();
|
|
425
|
+
oldTreeView.replaceWith(newTreeView);
|
|
426
|
+
// Catalyst re-resolves @target treeViewList dynamically on next access.
|
|
427
|
+
// Restore checked state for all nodes that now appear in the new tree.
|
|
428
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_restoreSelectionState).call(this);
|
|
429
|
+
// Re-apply include-sub-items visually if the checkbox is still checked.
|
|
430
|
+
if (includeSubItems) {
|
|
431
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_includeSubItems).call(this);
|
|
432
|
+
}
|
|
433
|
+
if (requestWasFiltered) {
|
|
434
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_expandAllSubTrees).call(this);
|
|
435
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_applyAsyncHighlights).call(this, query);
|
|
436
|
+
const hasResults = !!this.treeViewList?.querySelector('[role=treeitem]');
|
|
437
|
+
this.noResultsMessage.toggleAttribute('hidden', hasResults);
|
|
438
|
+
this.treeViewList?.toggleAttribute('hidden', !hasResults);
|
|
439
|
+
}
|
|
440
|
+
else {
|
|
441
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_removeHighlights).call(this);
|
|
442
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_restoreExpansionState).call(this);
|
|
443
|
+
this.noResultsMessage.setAttribute('hidden', 'hidden');
|
|
444
|
+
this.treeViewList?.removeAttribute('hidden');
|
|
445
|
+
}
|
|
446
|
+
// Synthesise form inputs for nodes that are checked but absent from the current DOM
|
|
447
|
+
// (e.g. filtered out). Must run after restoreSelectionState so we know what is in the DOM.
|
|
448
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_updateRetainedSelections).call(this);
|
|
449
|
+
}
|
|
450
|
+
catch (e) {
|
|
451
|
+
if (e.name === 'AbortError')
|
|
452
|
+
return;
|
|
453
|
+
throw e;
|
|
454
|
+
}
|
|
455
|
+
finally {
|
|
456
|
+
this.removeAttribute('data-loading');
|
|
457
|
+
this.setAttribute('aria-busy', 'false');
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
_FilterableTreeViewElement_captureExpansionState = function _FilterableTreeViewElement_captureExpansionState() {
|
|
461
|
+
const snapshot = new Map();
|
|
462
|
+
for (const treeitem of this.querySelectorAll('[role=treeitem][data-node-id][data-node-type=sub-tree]')) {
|
|
463
|
+
snapshot.set(treeitem.getAttribute('data-node-id'), treeitem.getAttribute('aria-expanded') === 'true');
|
|
464
|
+
}
|
|
465
|
+
return snapshot;
|
|
466
|
+
};
|
|
467
|
+
_FilterableTreeViewElement_applyExpansionSnapshot = function _FilterableTreeViewElement_applyExpansionSnapshot(snapshot) {
|
|
468
|
+
for (const [nodeId, wasExpanded] of snapshot) {
|
|
469
|
+
const treeitem = this.querySelector(`[role=treeitem][data-node-id="${CSS.escape(nodeId)}"]`);
|
|
470
|
+
const subTreeNode = treeitem?.closest('tree-view-sub-tree-node');
|
|
471
|
+
if (subTreeNode) {
|
|
472
|
+
if (wasExpanded) {
|
|
473
|
+
subTreeNode.expand();
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
subTreeNode.collapse();
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
_FilterableTreeViewElement_snapshotExpansionState = function _FilterableTreeViewElement_snapshotExpansionState() {
|
|
482
|
+
__classPrivateFieldSet(this, _FilterableTreeViewElement_expansionSnapshot, __classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_captureExpansionState).call(this), "f");
|
|
483
|
+
};
|
|
484
|
+
_FilterableTreeViewElement_restoreExpansionState = function _FilterableTreeViewElement_restoreExpansionState() {
|
|
485
|
+
if (!__classPrivateFieldGet(this, _FilterableTreeViewElement_expansionSnapshot, "f"))
|
|
486
|
+
return;
|
|
487
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_applyExpansionSnapshot).call(this, __classPrivateFieldGet(this, _FilterableTreeViewElement_expansionSnapshot, "f"));
|
|
488
|
+
__classPrivateFieldSet(this, _FilterableTreeViewElement_expansionSnapshot, null, "f");
|
|
489
|
+
};
|
|
490
|
+
_FilterableTreeViewElement_restoreSelectionState = function _FilterableTreeViewElement_restoreSelectionState() {
|
|
491
|
+
if (!this.treeView)
|
|
492
|
+
return;
|
|
493
|
+
for (const treeitem of this.querySelectorAll('[role=treeitem][data-node-id]')) {
|
|
494
|
+
const nodeId = treeitem.getAttribute('data-node-id');
|
|
495
|
+
const savedValue = __classPrivateFieldGet(this, _FilterableTreeViewElement_checkedNodeIds, "f").get(nodeId);
|
|
496
|
+
if (savedValue !== undefined) {
|
|
497
|
+
this.treeView.setNodeCheckedValue(treeitem, savedValue);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
_FilterableTreeViewElement_expandAllSubTrees = function _FilterableTreeViewElement_expandAllSubTrees() {
|
|
502
|
+
for (const subTreeNode of this.querySelectorAll('tree-view-sub-tree-node')) {
|
|
503
|
+
subTreeNode.expand();
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
_FilterableTreeViewElement_applyAsyncHighlights = function _FilterableTreeViewElement_applyAsyncHighlights(query) {
|
|
507
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_removeHighlights).call(this);
|
|
508
|
+
const ranges = [];
|
|
509
|
+
for (const treeitem of this.querySelectorAll('[role=treeitem]')) {
|
|
510
|
+
const result = this.defaultFilterFn(treeitem, query, 'all');
|
|
511
|
+
if (result)
|
|
512
|
+
ranges.push(...result);
|
|
513
|
+
}
|
|
514
|
+
if (ranges.length > 0)
|
|
515
|
+
__classPrivateFieldGet(this, _FilterableTreeViewElement_instances, "m", _FilterableTreeViewElement_applyHighlights).call(this, ranges);
|
|
516
|
+
};
|
|
517
|
+
_FilterableTreeViewElement_updateRetainedSelections = function _FilterableTreeViewElement_updateRetainedSelections() {
|
|
518
|
+
// Only relevant when a form is wired up.
|
|
519
|
+
const prototype = this.treeView?.formInputPrototype;
|
|
520
|
+
if (!prototype)
|
|
521
|
+
return;
|
|
522
|
+
// Remove previously injected retained inputs.
|
|
523
|
+
for (const el of this.querySelectorAll('[data-filterable-tree-view-retained]')) {
|
|
524
|
+
el.remove();
|
|
525
|
+
}
|
|
526
|
+
for (const [nodeId, payload] of __classPrivateFieldGet(this, _FilterableTreeViewElement_checkedNodeFormPayloads, "f")) {
|
|
527
|
+
// Nodes currently in the DOM are already covered by TreeView's updateHiddenFormInputs.
|
|
528
|
+
const inDom = !!this.querySelector(`[role=treeitem][data-node-id="${CSS.escape(nodeId)}"]`);
|
|
529
|
+
if (inDom)
|
|
530
|
+
continue;
|
|
531
|
+
const input = document.createElement('input');
|
|
532
|
+
input.type = 'hidden';
|
|
533
|
+
input.name = prototype.name;
|
|
534
|
+
input.value = JSON.stringify(payload);
|
|
535
|
+
input.setAttribute('data-filterable-tree-view-retained', '');
|
|
536
|
+
this.appendChild(input);
|
|
537
|
+
}
|
|
538
|
+
};
|
|
250
539
|
_FilterableTreeViewElement_applyFilterOptions = function _FilterableTreeViewElement_applyFilterOptions() {
|
|
251
540
|
if (!this.treeView)
|
|
252
541
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openproject/primer-view-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.86.0-rc.d6cb0e8f5",
|
|
4
4
|
"description": "ViewComponents of the Primer Design System for OpenProject",
|
|
5
5
|
"main": "app/assets/javascripts/primer_view_components.js",
|
|
6
6
|
"module": "app/components/primer/primer.js",
|
package/static/arguments.json
CHANGED
|
@@ -3757,6 +3757,22 @@
|
|
|
3757
3757
|
}
|
|
3758
3758
|
]
|
|
3759
3759
|
},
|
|
3760
|
+
{
|
|
3761
|
+
"component": "TreeView::TrailingAction",
|
|
3762
|
+
"status": "alpha",
|
|
3763
|
+
"a11y_reviewed": false,
|
|
3764
|
+
"short_name": "TreeViewTrailingAction",
|
|
3765
|
+
"source": "https://github.com/primer/view_components/tree/main/app/components/primer/alpha/tree_view/trailing_action.rb",
|
|
3766
|
+
"lookbook": "https://primer.style/view-components/lookbook/inspect/primer/alpha/tree_view/trailing_action/default/",
|
|
3767
|
+
"parameters": [
|
|
3768
|
+
{
|
|
3769
|
+
"name": "action",
|
|
3770
|
+
"type": "ViewComponent::Base",
|
|
3771
|
+
"default": "N/A",
|
|
3772
|
+
"description": "A component or other renderable to use as the action button etc."
|
|
3773
|
+
}
|
|
3774
|
+
]
|
|
3775
|
+
},
|
|
3760
3776
|
{
|
|
3761
3777
|
"component": "TreeView::Visual",
|
|
3762
3778
|
"status": "alpha",
|
|
@@ -6151,6 +6167,12 @@
|
|
|
6151
6167
|
"source": "https://github.com/primer/view_components/tree/main/app/components/primer/open_project/filterable_tree_view.rb",
|
|
6152
6168
|
"lookbook": "https://primer.style/view-components/lookbook/inspect/primer/open_project/filterable_tree_view/default/",
|
|
6153
6169
|
"parameters": [
|
|
6170
|
+
{
|
|
6171
|
+
"name": "src",
|
|
6172
|
+
"type": "String",
|
|
6173
|
+
"default": "`nil`",
|
|
6174
|
+
"description": "URL of the server endpoint that returns a filtered `<tree-view>` HTML fragment. When set, activates async (server-side) filtering mode. See \"Async loading strategy\" above."
|
|
6175
|
+
},
|
|
6154
6176
|
{
|
|
6155
6177
|
"name": "tree_view_arguments",
|
|
6156
6178
|
"type": "Hash",
|
package/static/audited_at.json
CHANGED
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
"Primer::Alpha::TreeView::SubTree": "",
|
|
85
85
|
"Primer::Alpha::TreeView::SubTreeContainer": "",
|
|
86
86
|
"Primer::Alpha::TreeView::SubTreeNode": "",
|
|
87
|
+
"Primer::Alpha::TreeView::TrailingAction": "",
|
|
87
88
|
"Primer::Alpha::TreeView::Visual": "",
|
|
88
89
|
"Primer::Alpha::UnderlineNav": "",
|
|
89
90
|
"Primer::Alpha::UnderlinePanels": "",
|
package/static/classes.json
CHANGED
|
@@ -271,6 +271,15 @@
|
|
|
271
271
|
"DragHandle": [
|
|
272
272
|
"Primer::OpenProject::DragHandle"
|
|
273
273
|
],
|
|
274
|
+
"FilterableTreeViewLayout": [
|
|
275
|
+
"Primer::OpenProject::FilterableTreeView"
|
|
276
|
+
],
|
|
277
|
+
"FilterableTreeViewLoadingSkeleton": [
|
|
278
|
+
"Primer::OpenProject::FilterableTreeView"
|
|
279
|
+
],
|
|
280
|
+
"FilterableTreeViewTreeContainer": [
|
|
281
|
+
"Primer::OpenProject::FilterableTreeView"
|
|
282
|
+
],
|
|
274
283
|
"FormControl": [
|
|
275
284
|
"Primer::Alpha::TextField"
|
|
276
285
|
],
|
package/static/constants.json
CHANGED
|
@@ -852,6 +852,7 @@
|
|
|
852
852
|
"SubTree": "Primer::Alpha::TreeView::SubTree",
|
|
853
853
|
"SubTreeContainer": "Primer::Alpha::TreeView::SubTreeContainer",
|
|
854
854
|
"SubTreeNode": "Primer::Alpha::TreeView::SubTreeNode",
|
|
855
|
+
"TrailingAction": "Primer::Alpha::TreeView::TrailingAction",
|
|
855
856
|
"Visual": "Primer::Alpha::TreeView::Visual"
|
|
856
857
|
},
|
|
857
858
|
"Primer::Alpha::TreeView::Icon": {
|
|
@@ -918,6 +919,9 @@
|
|
|
918
919
|
"descendants"
|
|
919
920
|
]
|
|
920
921
|
},
|
|
922
|
+
"Primer::Alpha::TreeView::TrailingAction": {
|
|
923
|
+
"GeneratedSlotMethods": "Primer::Alpha::TreeView::TrailingAction::GeneratedSlotMethods"
|
|
924
|
+
},
|
|
921
925
|
"Primer::Alpha::TreeView::Visual": {
|
|
922
926
|
"GeneratedSlotMethods": "Primer::Alpha::TreeView::Visual::GeneratedSlotMethods"
|
|
923
927
|
},
|
|
@@ -1820,6 +1824,11 @@
|
|
|
1820
1824
|
"label": "No results"
|
|
1821
1825
|
},
|
|
1822
1826
|
"GeneratedSlotMethods": "Primer::OpenProject::FilterableTreeView::GeneratedSlotMethods",
|
|
1827
|
+
"SUPPORTED_SELECT_VARIANTS": [
|
|
1828
|
+
"multiple",
|
|
1829
|
+
"single",
|
|
1830
|
+
"none"
|
|
1831
|
+
],
|
|
1823
1832
|
"SubTree": "Primer::OpenProject::FilterableTreeView::SubTree"
|
|
1824
1833
|
},
|
|
1825
1834
|
"Primer::OpenProject::FilterableTreeView::SubTree": {
|