openproject-primer_view_components 0.73.1 → 0.74.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/app/assets/javascripts/components/primer/alpha/tree_view/tree_view.d.ts +6 -2
- data/app/assets/javascripts/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.d.ts +2 -0
- data/app/assets/javascripts/primer_view_components.js +1 -1
- data/app/assets/javascripts/primer_view_components.js.map +1 -1
- data/app/assets/styles/primer_view_components.css +1 -1
- data/app/assets/styles/primer_view_components.css.map +1 -1
- data/app/components/primer/alpha/tree_view/node.html.erb +5 -1
- data/app/components/primer/alpha/tree_view/node.rb +7 -1
- data/app/components/primer/alpha/tree_view/sub_tree_node.rb +1 -1
- data/app/components/primer/alpha/tree_view/tree_view.d.ts +6 -2
- data/app/components/primer/alpha/tree_view/tree_view.js +52 -2
- data/app/components/primer/alpha/tree_view/tree_view.ts +67 -3
- data/app/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.d.ts +2 -0
- data/app/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.js +11 -0
- data/app/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.ts +12 -0
- data/app/components/primer/alpha/tree_view.css +1 -1
- data/app/components/primer/alpha/tree_view.css.json +1 -0
- data/app/components/primer/alpha/tree_view.css.map +1 -1
- data/app/components/primer/alpha/tree_view.pcss +7 -0
- data/app/components/primer/alpha/tree_view.rb +15 -1
- data/app/components/primer/open_project/filterable_tree_view/sub_tree.rb +14 -4
- data/app/components/primer/open_project/filterable_tree_view.rb +26 -2
- data/lib/primer/view_components/version.rb +2 -2
- data/previews/primer/alpha/tree_view_preview/default.html.erb +1 -1
- data/previews/primer/alpha/tree_view_preview/form_input.html.erb +4 -4
- data/previews/primer/alpha/tree_view_preview/multi_select.html.erb +10 -0
- data/previews/primer/alpha/tree_view_preview/single_select.html.erb +10 -0
- data/previews/primer/alpha/tree_view_preview.rb +38 -4
- data/previews/primer/open_project/filterable_tree_view_preview/form_input.html.erb +15 -15
- data/previews/primer/open_project/filterable_tree_view_preview/playground.html.erb +15 -15
- data/previews/primer/open_project/filterable_tree_view_preview.rb +6 -2
- data/static/arguments.json +1 -1
- data/static/constants.json +1 -0
- data/static/info_arch.json +28 -2
- data/static/previews.json +26 -0
- metadata +4 -2
@@ -23,7 +23,11 @@
|
|
23
23
|
<%= leading_visual %>
|
24
24
|
<% end %>
|
25
25
|
<span class="TreeViewItemContentText"><%= text_content %></span>
|
26
|
-
<% if
|
26
|
+
<% if @select_variant == :single %>
|
27
|
+
<span class="TreeViewItemVisual" aria-hidden="true">
|
28
|
+
<%= render(Primer::Beta::Octicon.new(icon: :check, classes: "TreeViewItem-singleSelectCheckmark")) %>
|
29
|
+
</span>
|
30
|
+
<% elsif trailing_visual? %>
|
27
31
|
<%= trailing_visual %>
|
28
32
|
<% end %>
|
29
33
|
<% end %>
|
@@ -56,6 +56,7 @@ module Primer
|
|
56
56
|
|
57
57
|
DEFAULT_SELECT_VARIANT = :none
|
58
58
|
SELECT_VARIANT_OPTIONS = [
|
59
|
+
:single,
|
59
60
|
:multiple,
|
60
61
|
DEFAULT_SELECT_VARIANT
|
61
62
|
].freeze
|
@@ -128,7 +129,8 @@ module Primer
|
|
128
129
|
@content_arguments, {
|
129
130
|
data: {
|
130
131
|
value: value,
|
131
|
-
path: @path.to_json
|
132
|
+
path: @path.to_json,
|
133
|
+
select_variant: @select_variant
|
132
134
|
}
|
133
135
|
}
|
134
136
|
)
|
@@ -169,6 +171,10 @@ module Primer
|
|
169
171
|
private
|
170
172
|
|
171
173
|
def before_render
|
174
|
+
if trailing_visual? && select_variant == :single
|
175
|
+
raise ArgumentError, "Trailing visuals can't be used in combination with single select mode as the icon is reserved."
|
176
|
+
end
|
177
|
+
|
172
178
|
if leading_action?
|
173
179
|
@content_arguments[:data] = merge_data(
|
174
180
|
@content_arguments,
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import { SelectStrategy, TreeViewSubTreeNodeElement } from './tree_view_sub_tree_node_element';
|
2
|
-
import type {
|
1
|
+
import { SelectStrategy, SelectVariant, TreeViewSubTreeNodeElement } from './tree_view_sub_tree_node_element';
|
2
|
+
import type { TreeViewCheckedValue, TreeViewNodeInfo, TreeViewNodeType } from '../../shared_events';
|
3
3
|
export declare class TreeViewElement extends HTMLElement {
|
4
4
|
#private;
|
5
5
|
formInputContainer: HTMLElement;
|
@@ -9,16 +9,19 @@ export declare class TreeViewElement extends HTMLElement {
|
|
9
9
|
rootSubTreeNodes(): NodeListOf<TreeViewSubTreeNodeElement>;
|
10
10
|
disconnectedCallback(): void;
|
11
11
|
handleEvent(event: Event): void;
|
12
|
+
handleSingleSelection(event: Event, node: Element): void;
|
12
13
|
getFormInputValueForNode(node: Element): string | null;
|
13
14
|
getNodePath(node: Element): string[];
|
14
15
|
getNodeType(node: Element): TreeViewNodeType | null;
|
15
16
|
markCurrentAtPath(path: string[]): void;
|
16
17
|
get currentNode(): HTMLLIElement | null;
|
18
|
+
get activeNodes(): NodeListOf<Element>;
|
17
19
|
expandAtPath(path: string[]): void;
|
18
20
|
collapseAtPath(path: string[]): void;
|
19
21
|
toggleAtPath(path: string[]): void;
|
20
22
|
checkAtPath(path: string[]): void;
|
21
23
|
uncheckAtPath(path: string[]): void;
|
24
|
+
checkOnlyAtPath(path: string[]): void;
|
22
25
|
toggleCheckedAtPath(path: string[]): void;
|
23
26
|
checkedValueAtPath(path: string[]): TreeViewCheckedValue;
|
24
27
|
disabledValueAtPath(path: string[]): boolean;
|
@@ -34,6 +37,7 @@ export declare class TreeViewElement extends HTMLElement {
|
|
34
37
|
expandAncestorsForNode(node: HTMLElement): void;
|
35
38
|
changeSelectStrategy(newStrategy: SelectStrategy): void;
|
36
39
|
infoFromNode(node: Element, newCheckedValue?: TreeViewCheckedValue): TreeViewNodeInfo | null;
|
40
|
+
selectVariant(node: Element): SelectVariant;
|
37
41
|
}
|
38
42
|
declare global {
|
39
43
|
interface Window {
|
@@ -15,7 +15,7 @@ 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 _TreeViewElement_instances, _TreeViewElement_abortController, _TreeViewElement_autoExpandFrom, _TreeViewElement_eventIsActivation, _TreeViewElement_nodeForEvent, _TreeViewElement_handleNodeEvent, _TreeViewElement_eventIsCheckboxToggle, _TreeViewElement_handleCheckboxToggle, _TreeViewElement_handleNodeActivated, _TreeViewElement_handleNodeFocused, _TreeViewElement_handleNodeKeyboardEvent;
|
18
|
+
var _TreeViewElement_instances, _TreeViewElement_abortController, _TreeViewElement_autoExpandFrom, _TreeViewElement_eventIsActivation, _TreeViewElement_nodeForEvent, _TreeViewElement_handleNodeEvent, _TreeViewElement_eventIsCheckboxToggle, _TreeViewElement_handleCheckboxToggle, _TreeViewElement_eventIsSingleSelection, _TreeViewElement_handleNodeActivated, _TreeViewElement_handleNodeFocused, _TreeViewElement_handleNodeKeyboardEvent;
|
19
19
|
import { controller, target } from '@github/catalyst';
|
20
20
|
import { useRovingTabIndex } from './tree_view_roving_tab_index';
|
21
21
|
let TreeViewElement = class TreeViewElement extends HTMLElement {
|
@@ -99,6 +99,34 @@ let TreeViewElement = class TreeViewElement extends HTMLElement {
|
|
99
99
|
__classPrivateFieldGet(this, _TreeViewElement_instances, "m", _TreeViewElement_handleNodeEvent).call(this, node, event);
|
100
100
|
}
|
101
101
|
}
|
102
|
+
handleSingleSelection(event, node) {
|
103
|
+
if (this.getNodeDisabledValue(node)) {
|
104
|
+
event.preventDefault();
|
105
|
+
return;
|
106
|
+
}
|
107
|
+
// do not emit activation events for buttons and anchors, since it is assumed any activation
|
108
|
+
// behavior for these element types is user- or browser-defined
|
109
|
+
if (!(node instanceof HTMLDivElement))
|
110
|
+
return;
|
111
|
+
const path = this.getNodePath(node);
|
112
|
+
const nodeInfo = this.infoFromNode(node, 'true');
|
113
|
+
const checkSuccess = this.dispatchEvent(new CustomEvent('treeViewBeforeNodeChecked', {
|
114
|
+
bubbles: true,
|
115
|
+
cancelable: true,
|
116
|
+
detail: [nodeInfo],
|
117
|
+
}));
|
118
|
+
if (!checkSuccess)
|
119
|
+
return;
|
120
|
+
const currentlyChecked = !this.getNodeCheckedValue(node);
|
121
|
+
// disallow unchecking checked item in single-select mode
|
122
|
+
if (!currentlyChecked) {
|
123
|
+
this.checkOnlyAtPath(path);
|
124
|
+
}
|
125
|
+
this.dispatchEvent(new CustomEvent('treeViewNodeChecked', {
|
126
|
+
bubbles: true,
|
127
|
+
detail: [nodeInfo],
|
128
|
+
}));
|
129
|
+
}
|
102
130
|
getFormInputValueForNode(node) {
|
103
131
|
return node.getAttribute('data-value');
|
104
132
|
}
|
@@ -123,6 +151,9 @@ let TreeViewElement = class TreeViewElement extends HTMLElement {
|
|
123
151
|
get currentNode() {
|
124
152
|
return this.querySelector('[aria-current=true]');
|
125
153
|
}
|
154
|
+
get activeNodes() {
|
155
|
+
return document.querySelectorAll('[aria-checked="true"]');
|
156
|
+
}
|
126
157
|
expandAtPath(path) {
|
127
158
|
const node = this.subTreeAtPath(path);
|
128
159
|
if (!node)
|
@@ -153,6 +184,12 @@ let TreeViewElement = class TreeViewElement extends HTMLElement {
|
|
153
184
|
return;
|
154
185
|
this.setNodeCheckedValue(node, 'false');
|
155
186
|
}
|
187
|
+
checkOnlyAtPath(path) {
|
188
|
+
for (const el of this.activeNodes) {
|
189
|
+
this.uncheckAtPath(this.getNodePath(el));
|
190
|
+
}
|
191
|
+
this.checkAtPath(path);
|
192
|
+
}
|
156
193
|
toggleCheckedAtPath(path) {
|
157
194
|
const node = this.nodeAtPath(path);
|
158
195
|
if (!node)
|
@@ -246,6 +283,9 @@ let TreeViewElement = class TreeViewElement extends HTMLElement {
|
|
246
283
|
previousCheckedValue: checkedValue,
|
247
284
|
};
|
248
285
|
}
|
286
|
+
selectVariant(node) {
|
287
|
+
return (node.getAttribute('data-select-variant') || 'none');
|
288
|
+
}
|
249
289
|
};
|
250
290
|
_TreeViewElement_abortController = new WeakMap();
|
251
291
|
_TreeViewElement_instances = new WeakSet();
|
@@ -272,6 +312,9 @@ _TreeViewElement_handleNodeEvent = function _TreeViewElement_handleNodeEvent(nod
|
|
272
312
|
if (__classPrivateFieldGet(this, _TreeViewElement_instances, "m", _TreeViewElement_eventIsCheckboxToggle).call(this, event, node)) {
|
273
313
|
__classPrivateFieldGet(this, _TreeViewElement_instances, "m", _TreeViewElement_handleCheckboxToggle).call(this, event, node);
|
274
314
|
}
|
315
|
+
else if (__classPrivateFieldGet(this, _TreeViewElement_instances, "m", _TreeViewElement_eventIsSingleSelection).call(this, event, node)) {
|
316
|
+
this.handleSingleSelection(event, node);
|
317
|
+
}
|
275
318
|
else if (__classPrivateFieldGet(this, _TreeViewElement_instances, "m", _TreeViewElement_eventIsActivation).call(this, event)) {
|
276
319
|
__classPrivateFieldGet(this, _TreeViewElement_instances, "m", _TreeViewElement_handleNodeActivated).call(this, event, node);
|
277
320
|
}
|
@@ -317,6 +360,9 @@ _TreeViewElement_handleCheckboxToggle = function _TreeViewElement_handleCheckbox
|
|
317
360
|
detail: [nodeInfo],
|
318
361
|
}));
|
319
362
|
};
|
363
|
+
_TreeViewElement_eventIsSingleSelection = function _TreeViewElement_eventIsSingleSelection(event, node) {
|
364
|
+
return event.type === 'click' && this.selectVariant(node) === 'single';
|
365
|
+
};
|
320
366
|
_TreeViewElement_handleNodeActivated = function _TreeViewElement_handleNodeActivated(event, node) {
|
321
367
|
if (this.getNodeDisabledValue(node)) {
|
322
368
|
event.preventDefault();
|
@@ -359,7 +405,7 @@ _TreeViewElement_handleNodeKeyboardEvent = function _TreeViewElement_handleNodeK
|
|
359
405
|
event.preventDefault();
|
360
406
|
break;
|
361
407
|
}
|
362
|
-
if (this.
|
408
|
+
if (this.selectVariant(node) === 'multiple') {
|
363
409
|
event.preventDefault();
|
364
410
|
if (this.getNodeCheckedValue(node) === 'true') {
|
365
411
|
this.setNodeCheckedValue(node, 'false');
|
@@ -368,6 +414,10 @@ _TreeViewElement_handleNodeKeyboardEvent = function _TreeViewElement_handleNodeK
|
|
368
414
|
this.setNodeCheckedValue(node, 'true');
|
369
415
|
}
|
370
416
|
}
|
417
|
+
else if (this.selectVariant(node) === 'single') {
|
418
|
+
event.preventDefault();
|
419
|
+
this.checkOnlyAtPath(this.getNodePath(node));
|
420
|
+
}
|
371
421
|
else if (node instanceof HTMLAnchorElement) {
|
372
422
|
// simulate click on space
|
373
423
|
node.click();
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import {controller, target} from '@github/catalyst'
|
2
|
-
import {SelectStrategy, TreeViewSubTreeNodeElement} from './tree_view_sub_tree_node_element'
|
2
|
+
import {SelectStrategy, SelectVariant, TreeViewSubTreeNodeElement} from './tree_view_sub_tree_node_element'
|
3
3
|
import {useRovingTabIndex} from './tree_view_roving_tab_index'
|
4
|
-
import type {
|
4
|
+
import type {TreeViewCheckedValue, TreeViewNodeInfo, TreeViewNodeType} from '../../shared_events'
|
5
5
|
|
6
6
|
@controller
|
7
7
|
export class TreeViewElement extends HTMLElement {
|
@@ -124,6 +124,8 @@ export class TreeViewElement extends HTMLElement {
|
|
124
124
|
#handleNodeEvent(node: Element, event: Event) {
|
125
125
|
if (this.#eventIsCheckboxToggle(event, node)) {
|
126
126
|
this.#handleCheckboxToggle(event, node)
|
127
|
+
} else if (this.#eventIsSingleSelection(event, node)) {
|
128
|
+
this.handleSingleSelection(event, node)
|
127
129
|
} else if (this.#eventIsActivation(event)) {
|
128
130
|
this.#handleNodeActivated(event, node)
|
129
131
|
} else if (event.type === 'focusin') {
|
@@ -177,6 +179,48 @@ export class TreeViewElement extends HTMLElement {
|
|
177
179
|
)
|
178
180
|
}
|
179
181
|
|
182
|
+
#eventIsSingleSelection(event: Event, node: Element) {
|
183
|
+
return event.type === 'click' && this.selectVariant(node) === 'single'
|
184
|
+
}
|
185
|
+
|
186
|
+
handleSingleSelection(event: Event, node: Element) {
|
187
|
+
if (this.getNodeDisabledValue(node)) {
|
188
|
+
event.preventDefault()
|
189
|
+
return
|
190
|
+
}
|
191
|
+
|
192
|
+
// do not emit activation events for buttons and anchors, since it is assumed any activation
|
193
|
+
// behavior for these element types is user- or browser-defined
|
194
|
+
if (!(node instanceof HTMLDivElement)) return
|
195
|
+
|
196
|
+
const path = this.getNodePath(node)
|
197
|
+
const nodeInfo = this.infoFromNode(node, 'true')
|
198
|
+
|
199
|
+
const checkSuccess = this.dispatchEvent(
|
200
|
+
new CustomEvent('treeViewBeforeNodeChecked', {
|
201
|
+
bubbles: true,
|
202
|
+
cancelable: true,
|
203
|
+
detail: [nodeInfo],
|
204
|
+
}),
|
205
|
+
)
|
206
|
+
|
207
|
+
if (!checkSuccess) return
|
208
|
+
|
209
|
+
const currentlyChecked = !this.getNodeCheckedValue(node)
|
210
|
+
|
211
|
+
// disallow unchecking checked item in single-select mode
|
212
|
+
if (!currentlyChecked) {
|
213
|
+
this.checkOnlyAtPath(path)
|
214
|
+
}
|
215
|
+
|
216
|
+
this.dispatchEvent(
|
217
|
+
new CustomEvent('treeViewNodeChecked', {
|
218
|
+
bubbles: true,
|
219
|
+
detail: [nodeInfo],
|
220
|
+
}),
|
221
|
+
)
|
222
|
+
}
|
223
|
+
|
180
224
|
#handleNodeActivated(event: Event, node: Element) {
|
181
225
|
if (this.getNodeDisabledValue(node)) {
|
182
226
|
event.preventDefault()
|
@@ -231,7 +275,7 @@ export class TreeViewElement extends HTMLElement {
|
|
231
275
|
break
|
232
276
|
}
|
233
277
|
|
234
|
-
if (this.
|
278
|
+
if (this.selectVariant(node) === 'multiple') {
|
235
279
|
event.preventDefault()
|
236
280
|
|
237
281
|
if (this.getNodeCheckedValue(node) === 'true') {
|
@@ -239,6 +283,10 @@ export class TreeViewElement extends HTMLElement {
|
|
239
283
|
} else {
|
240
284
|
this.setNodeCheckedValue(node, 'true')
|
241
285
|
}
|
286
|
+
} else if (this.selectVariant(node) === 'single') {
|
287
|
+
event.preventDefault()
|
288
|
+
|
289
|
+
this.checkOnlyAtPath(this.getNodePath(node))
|
242
290
|
} else if (node instanceof HTMLAnchorElement) {
|
243
291
|
// simulate click on space
|
244
292
|
node.click()
|
@@ -279,6 +327,10 @@ export class TreeViewElement extends HTMLElement {
|
|
279
327
|
return this.querySelector('[aria-current=true]')
|
280
328
|
}
|
281
329
|
|
330
|
+
get activeNodes() {
|
331
|
+
return document.querySelectorAll('[aria-checked="true"]')
|
332
|
+
}
|
333
|
+
|
282
334
|
expandAtPath(path: string[]) {
|
283
335
|
const node = this.subTreeAtPath(path)
|
284
336
|
if (!node) return
|
@@ -314,6 +366,14 @@ export class TreeViewElement extends HTMLElement {
|
|
314
366
|
this.setNodeCheckedValue(node, 'false')
|
315
367
|
}
|
316
368
|
|
369
|
+
checkOnlyAtPath(path: string[]) {
|
370
|
+
for (const el of this.activeNodes) {
|
371
|
+
this.uncheckAtPath(this.getNodePath(el))
|
372
|
+
}
|
373
|
+
|
374
|
+
this.checkAtPath(path)
|
375
|
+
}
|
376
|
+
|
317
377
|
toggleCheckedAtPath(path: string[]) {
|
318
378
|
const node = this.nodeAtPath(path)
|
319
379
|
if (!node) return
|
@@ -420,6 +480,10 @@ export class TreeViewElement extends HTMLElement {
|
|
420
480
|
previousCheckedValue: checkedValue,
|
421
481
|
}
|
422
482
|
}
|
483
|
+
|
484
|
+
selectVariant(node: Element): SelectVariant {
|
485
|
+
return (node.getAttribute('data-select-variant') || 'none') as SelectVariant
|
486
|
+
}
|
423
487
|
}
|
424
488
|
|
425
489
|
if (!window.customElements.get('tree-view')) {
|
@@ -3,6 +3,7 @@ import { TreeViewIncludeFragmentElement } from './tree_view_include_fragment_ele
|
|
3
3
|
import { TreeViewElement } from './tree_view';
|
4
4
|
type LoadingState = 'loading' | 'error' | 'success';
|
5
5
|
export type SelectStrategy = 'self' | 'descendants' | 'mixed_descendants';
|
6
|
+
export type SelectVariant = 'none' | 'single' | 'multiple';
|
6
7
|
export declare class TreeViewSubTreeNodeElement extends HTMLElement {
|
7
8
|
#private;
|
8
9
|
node: HTMLElement;
|
@@ -21,6 +22,7 @@ export declare class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
21
22
|
get loadingState(): LoadingState;
|
22
23
|
set loadingState(newState: LoadingState);
|
23
24
|
get selectStrategy(): SelectStrategy;
|
25
|
+
get selectVariant(): SelectVariant;
|
24
26
|
get level(): number;
|
25
27
|
disconnectedCallback(): void;
|
26
28
|
handleEvent(event: Event): void;
|
@@ -97,6 +97,9 @@ let TreeViewSubTreeNodeElement = class TreeViewSubTreeNodeElement extends HTMLEl
|
|
97
97
|
get selectStrategy() {
|
98
98
|
return (this.node.getAttribute('data-select-strategy') || 'descendants');
|
99
99
|
}
|
100
|
+
get selectVariant() {
|
101
|
+
return (this.node.getAttribute('data-select-variant') || 'none');
|
102
|
+
}
|
100
103
|
get level() {
|
101
104
|
return parseInt(this.node.getAttribute('aria-level') || '0');
|
102
105
|
}
|
@@ -289,6 +292,10 @@ _TreeViewSubTreeNodeElement_handleKeyboardEvent = function _TreeViewSubTreeNodeE
|
|
289
292
|
if (__classPrivateFieldGet(this, _TreeViewSubTreeNodeElement_instances, "a", _TreeViewSubTreeNodeElement_checkboxElement_get)) {
|
290
293
|
this.toggleChecked();
|
291
294
|
}
|
295
|
+
else if (this.selectVariant === 'single') {
|
296
|
+
// Follow the standard implementation of TreeView and select that item
|
297
|
+
this.treeView.handleSingleSelection(event, node);
|
298
|
+
}
|
292
299
|
else if (!this.treeView?.nodeHasNativeAction(node)) {
|
293
300
|
// toggle only if this node isn't eg. an anchor or button
|
294
301
|
this.toggle();
|
@@ -315,6 +322,10 @@ _TreeViewSubTreeNodeElement_handleKeyboardEvent = function _TreeViewSubTreeNodeE
|
|
315
322
|
event.preventDefault();
|
316
323
|
this.toggleChecked();
|
317
324
|
}
|
325
|
+
else if (this.selectVariant === 'single') {
|
326
|
+
// Follow the standard implementation of TreeView and select that item
|
327
|
+
this.treeView.handleSingleSelection(event, node);
|
328
|
+
}
|
318
329
|
else {
|
319
330
|
if (node instanceof HTMLAnchorElement) {
|
320
331
|
// simulate click on space for anchors (buttons already handle this natively)
|
@@ -9,6 +9,8 @@ type LoadingState = 'loading' | 'error' | 'success'
|
|
9
9
|
|
10
10
|
export type SelectStrategy = 'self' | 'descendants' | 'mixed_descendants'
|
11
11
|
|
12
|
+
export type SelectVariant = 'none' | 'single' | 'multiple'
|
13
|
+
|
12
14
|
@controller
|
13
15
|
export class TreeViewSubTreeNodeElement extends HTMLElement {
|
14
16
|
@target node: HTMLElement
|
@@ -133,6 +135,10 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
133
135
|
return (this.node.getAttribute('data-select-strategy') || 'descendants') as SelectStrategy
|
134
136
|
}
|
135
137
|
|
138
|
+
get selectVariant(): SelectVariant {
|
139
|
+
return (this.node.getAttribute('data-select-variant') || 'none') as SelectVariant
|
140
|
+
}
|
141
|
+
|
136
142
|
get level(): number {
|
137
143
|
return parseInt(this.node.getAttribute('aria-level') || '0')
|
138
144
|
}
|
@@ -321,6 +327,9 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
321
327
|
|
322
328
|
if (this.#checkboxElement) {
|
323
329
|
this.toggleChecked()
|
330
|
+
} else if (this.selectVariant === 'single') {
|
331
|
+
// Follow the standard implementation of TreeView and select that item
|
332
|
+
this.treeView.handleSingleSelection(event, node)
|
324
333
|
} else if (!this.treeView?.nodeHasNativeAction(node)) {
|
325
334
|
// toggle only if this node isn't eg. an anchor or button
|
326
335
|
this.toggle()
|
@@ -352,6 +361,9 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
352
361
|
event.preventDefault()
|
353
362
|
|
354
363
|
this.toggleChecked()
|
364
|
+
} else if (this.selectVariant === 'single') {
|
365
|
+
// Follow the standard implementation of TreeView and select that item
|
366
|
+
this.treeView.handleSingleSelection(event, node)
|
355
367
|
} else {
|
356
368
|
if (node instanceof HTMLAnchorElement) {
|
357
369
|
// simulate click on space for anchors (buttons already handle this natively)
|
@@ -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}}[data-has-leading-action]:is(.TreeViewRootUlStyles .TreeViewItem){--has-leading-action:1}.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";grid-template-columns:var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr;position:relative;width:100%;--leading-action-width:calc(var(--has-leading-action, 0)*1.5rem);--spacer-width:calc((var(--level) - 1)*(var(--toggle-width)/2))}: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{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=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 .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%}
|
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}}[data-has-leading-action]:is(.TreeViewRootUlStyles .TreeViewItem){--has-leading-action:1}.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";grid-template-columns:var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr;position:relative;width:100%;--leading-action-width:calc(var(--has-leading-action, 0)*1.5rem);--spacer-width:calc((var(--level) - 1)*(var(--toggle-width)/2))}: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{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 .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%}
|
@@ -22,6 +22,7 @@
|
|
22
22
|
":is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItemCheckbox",
|
23
23
|
"[aria-checked=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox",
|
24
24
|
":is([aria-checked=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox):before",
|
25
|
+
"[aria-checked=false]:is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItem-singleSelectCheckmark",
|
25
26
|
"[aria-checked=mixed]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox",
|
26
27
|
":is([aria-checked=mixed]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox):before",
|
27
28
|
"[aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent)",
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["tree_view.pcss"],"names":[],"mappings":"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","file":"tree_view.css","sourcesContent":["/* stylelint-disable selector-max-type -- Copied from primer/react */\n\n.TreeViewRootUlStyles {\n padding: 0;\n margin: 0;\n list-style: none;\n\n /*\n * WARNING: This is a performance optimization.\n *\n * We define styles for the tree items at the root level of the tree\n * to avoid recomputing the styles for each item when the tree updates.\n * We're sacrificing maintainability for performance because TreeView\n * needs to be performant enough to handle large trees (thousands of items).\n *\n * This is intended to be a temporary solution until we can improve the\n * performance of our styling patterns.\n *\n * Do NOT copy this pattern without understanding the tradeoffs.\n */\n & .TreeViewItem {\n outline: none;\n\n &:focus-visible > div {\n box-shadow: var(--boxShadow-thick) var(--fgColor-accent);\n\n @media (forced-colors: active) {\n outline: 2px solid HighlightText;\n /* stylelint-disable-next-line declaration-property-value-no-unknown -- Copied from primer/react */\n outline-offset: -2;\n }\n }\n\n &[data-has-leading-action] {\n --has-leading-action: 1;\n }\n }\n\n & .TreeViewItemContainer {\n --level: 1;\n --toggle-width: 1rem;\n --min-item-height: 2rem;\n\n position: relative;\n display: grid;\n width: 100%;\n font-size: var(--text-body-size-medium);\n color: var(--fgColor-default);\n border-radius: var(--borderRadius-medium);\n grid-template-columns: var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr;\n grid-template-areas: 'spacer leadingAction toggle content';\n\n --leading-action-width: calc(var(--has-leading-action, 0) * 1.5rem);\n --spacer-width: calc(calc(var(--level) - 1) * (var(--toggle-width) / 2));\n\n &:hover {\n background-color: var(--control-transparent-bgColor-hover);\n\n @media (forced-colors: active) {\n outline: 2px solid transparent;\n outline-offset: -2px;\n }\n }\n\n @media (pointer: coarse) {\n --toggle-width: 1.5rem;\n --min-item-height: 2.75rem;\n }\n\n &:has(.TreeViewFailureMessage):hover {\n cursor: default;\n background-color: transparent;\n\n @media (forced-colors: active) {\n outline: none;\n }\n }\n\n &:has([role='treeitem']:focus-visible) {\n box-shadow: var(--boxShadow-thick) var(--fgColor-accent);\n }\n }\n\n &:where([data-omit-spacer='true']) .TreeViewItemContainer {\n grid-template-columns: 0 0 0 1fr;\n }\n\n /* stylelint-disable-next-line selector-max-specificity */\n & .TreeViewItem > .TreeViewItemContainer:has(.TreeViewItemContent[aria-current='true']) {\n background-color: var(--control-transparent-bgColor-selected);\n\n /* Current item indicator */\n /* stylelint-disable-next-line selector-max-specificity -- Copied from primer/react */\n &::after {\n position: absolute;\n top: calc(50% - var(--base-size-12));\n left: calc(-1 * var(--base-size-8));\n width: 0.25rem;\n height: 1.5rem;\n content: '';\n\n /*\n * Use fgColor accent for consistency across all themes. Using the \"correct\" variable,\n * --bgColor-accent-emphasis, causes vrt failures for dark high contrast mode\n */\n /* stylelint-disable-next-line primer/colors */\n background-color: var(--fgColor-accent);\n border-radius: var(--borderRadius-medium);\n\n @media (forced-colors: active) {\n background-color: HighlightText;\n }\n }\n }\n\n & .TreeViewItemToggle {\n display: flex;\n height: 100%;\n\n /* The toggle should appear vertically centered for single-line items, but remain at the top for items that wrap\n across more lines. */\n /* stylelint-disable-next-line primer/spacing */\n padding-top: calc(var(--min-item-height) / 2 - var(--base-size-12) / 2);\n color: var(--fgColor-muted);\n grid-area: toggle;\n justify-content: center;\n align-items: flex-start;\n cursor: pointer;\n }\n\n & .TreeViewItemToggleHover:hover {\n background-color: var(--control-transparent-bgColor-hover);\n }\n\n & .TreeViewItemToggleEnd {\n border-top-left-radius: var(--borderRadius-medium);\n border-bottom-left-radius: var(--borderRadius-medium);\n }\n\n /* stylelint-disable-next-line selector-no-qualifying-type */\n & a.TreeViewItemContent:hover, button.TreeViewItemContent:hover {\n text-decoration: underline;\n text-decoration-color: var(--control-fgColor-rest);\n }\n\n & :has(.TreeViewItemContent[aria-disabled=\"true\"]) {\n cursor: not-allowed;\n }\n\n & .TreeViewItemContent {\n display: flex;\n height: 100%;\n padding: 0 var(--base-size-8);\n outline: none;\n text-align: left;\n user-select: none;\n background-color: transparent;\n border: none;\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n cursor: pointer;\n\n /* The dynamic top and bottom padding to maintain the minimum item height for single line items */\n /* stylelint-disable-next-line primer/spacing */\n padding-top: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2);\n /* stylelint-disable-next-line primer/spacing */\n padding-bottom: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2);\n line-height: var(--custom-line-height, var(--text-body-lineHeight-medium, 1.4285));\n grid-area: content;\n gap: var(--stack-gap-condensed);\n\n & .TreeViewItemCheckbox {\n position: relative;\n color: var(--control-fgColor-rest);\n text-align: left;\n user-select: none;\n background-color: transparent;\n border: none;\n border-radius: var(--borderRadius-medium);\n transition: background 33.333ms linear;\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n }\n\n &[aria-checked='true'] {\n & .FormControl-checkbox {\n background: var(--control-checked-bgColor-rest);\n border-color: var(--control-checked-borderColor-rest);\n transition: background-color, border-color 80ms cubic-bezier(0.32, 0, 0.67, 0) 0ms; /* unchecked -> checked */\n\n /* stylelint-disable-next-line max-nesting-depth, selector-max-specificity -- Copied from primer/react */\n &::before {\n visibility: visible;\n transition: visibility 0s linear 0s;\n animation: checkmarkIn 80ms cubic-bezier(0.65, 0, 0.35, 1) forwards 80ms;\n }\n }\n }\n\n &[aria-checked='mixed'] {\n & .FormControl-checkbox {\n background: var(--control-checked-bgColor-rest);\n border-color: var(--control-checked-borderColor-rest);\n transition: background-color, border-color 80ms cubic-bezier(0.32, 0, 0.67, 0) 0ms; /* unchecked -> checked */\n\n /* stylelint-disable-next-line max-nesting-depth, selector-max-specificity -- Copied from primer/react */\n &::before {\n visibility: visible;\n mask-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMiIgdmlld0JveD0iMCAwIDEwIDIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMCAxQzAgMC40NDc3MTUgMC40NDc3MTUgMCAxIDBIOUM5LjU1MjI5IDAgMTAgMC40NDc3MTUgMTAgMUMxMCAxLjU1MjI4IDkuNTUyMjkgMiA5IDJIMUMwLjQ0NzcxNSAyIDAgMS41NTIyOCAwIDFaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K');\n animation: checkmarkIn 80ms cubic-bezier(0.65, 0, 0.35, 1) forwards 80ms;\n clip-path: none;\n }\n }\n }\n\n &[aria-disabled='true'] {\n pointer-events: none;\n\n & .TreeViewItemContentText {\n color: var(--control-fgColor-disabled);\n }\n\n & .TreeViewItemVisual {\n fill: var(--control-fgColor-disabled);\n\n /* stylelint-disable-next-line max-nesting-depth, selector-max-compound-selectors, selector-max-specificity */\n & svg {\n fill: var(--control-fgColor-disabled);\n }\n }\n\n & .FormControl-checkbox {\n /* stylelint-disable-next-line max-nesting-depth */\n @media (hover: hover) {\n /* stylelint-disable-next-line max-nesting-depth, selector-max-specificity */\n &:hover {\n cursor: not-allowed;\n }\n }\n }\n\n @media (hover: hover) {\n /* stylelint-disable-next-line max-nesting-depth */\n &:hover {\n cursor: not-allowed;\n background-color: transparent;\n }\n }\n }\n }\n\n & .TreeViewItemContentText {\n color: var(--control-fgColor-rest);\n flex: 1 1 auto;\n width: 0;\n }\n\n &:where([data-truncate-text='true']) .TreeViewItemContentText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n &:where([data-truncate-text='false']) .TreeViewItemContentText {\n /* stylelint-disable-next-line declaration-property-value-keyword-no-deprecated -- Copied from primer/react */\n word-break: break-word;\n }\n\n & .TreeViewItemVisual {\n display: flex;\n\n /* The visual icons should appear vertically centered for single-line items, but remain at the top for items that wrap\n across more lines. */\n height: var(--custom-line-height, 1.3rem);\n color: var(--fgColor-muted);\n align-items: center;\n }\n\n & .TreeViewItemLeadingAction {\n display: flex;\n color: var(--fgColor-muted);\n grid-area: leadingAction;\n\n & > button {\n flex-shrink: 1;\n }\n }\n\n & .TreeViewItemLevelLine {\n width: 100%;\n height: 100%;\n\n /*\n * On devices without hover, the nesting indicator lines\n * appear at all times.\n */\n border-color: var(--borderColor-muted);\n border-right: var(--borderWidth-thin) solid;\n }\n\n /*\n * On devices with :hover support, the nesting indicator lines\n * fade in when the user mouses over the entire component,\n * or when there's focus inside the component. This makes\n * sure the component remains simple when not in use.\n */\n @media (hover: hover) {\n .TreeViewItemLevelLine {\n border-color: transparent;\n }\n\n &:hover .TreeViewItemLevelLine,\n &:focus-within .TreeViewItemLevelLine {\n border-color: var(--borderColor-muted);\n }\n }\n\n & .TreeViewVisuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n /* stylelint-disable-next-line primer/spacing */\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n }\n}\n\n.TreeViewSkeletonItemContainerStyle {\n display: flex;\n align-items: center;\n column-gap: 0.5rem;\n height: 2rem;\n\n @media (pointer: coarse) {\n height: 2.75rem;\n }\n\n &:nth-of-type(5n + 1) {\n --tree-item-loading-width: 67%;\n }\n\n &:nth-of-type(5n + 2) {\n --tree-item-loading-width: 47%;\n }\n\n &:nth-of-type(5n + 3) {\n --tree-item-loading-width: 73%;\n }\n\n &:nth-of-type(5n + 4) {\n --tree-item-loading-width: 64%;\n }\n\n &:nth-of-type(5n + 5) {\n --tree-item-loading-width: 50%;\n }\n}\n\n.TreeItemSkeletonTextStyles {\n width: var(--tree-item-loading-width, 67%);\n}\n\n.TreeViewFailureMessage {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: 0.5rem;\n width: 100%;\n align-items: center;\n}\n"]}
|
1
|
+
{"version":3,"sources":["tree_view.pcss"],"names":[],"mappings":"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","file":"tree_view.css","sourcesContent":["/* stylelint-disable selector-max-type -- Copied from primer/react */\n\n.TreeViewRootUlStyles {\n padding: 0;\n margin: 0;\n list-style: none;\n\n /*\n * WARNING: This is a performance optimization.\n *\n * We define styles for the tree items at the root level of the tree\n * to avoid recomputing the styles for each item when the tree updates.\n * We're sacrificing maintainability for performance because TreeView\n * needs to be performant enough to handle large trees (thousands of items).\n *\n * This is intended to be a temporary solution until we can improve the\n * performance of our styling patterns.\n *\n * Do NOT copy this pattern without understanding the tradeoffs.\n */\n & .TreeViewItem {\n outline: none;\n\n &:focus-visible > div {\n box-shadow: var(--boxShadow-thick) var(--fgColor-accent);\n\n @media (forced-colors: active) {\n outline: 2px solid HighlightText;\n /* stylelint-disable-next-line declaration-property-value-no-unknown -- Copied from primer/react */\n outline-offset: -2;\n }\n }\n\n &[data-has-leading-action] {\n --has-leading-action: 1;\n }\n }\n\n & .TreeViewItemContainer {\n --level: 1;\n --toggle-width: 1rem;\n --min-item-height: 2rem;\n\n position: relative;\n display: grid;\n width: 100%;\n font-size: var(--text-body-size-medium);\n color: var(--fgColor-default);\n border-radius: var(--borderRadius-medium);\n grid-template-columns: var(--spacer-width) var(--leading-action-width) var(--toggle-width) 1fr;\n grid-template-areas: 'spacer leadingAction toggle content';\n\n --leading-action-width: calc(var(--has-leading-action, 0) * 1.5rem);\n --spacer-width: calc(calc(var(--level) - 1) * (var(--toggle-width) / 2));\n\n &:hover {\n background-color: var(--control-transparent-bgColor-hover);\n\n @media (forced-colors: active) {\n outline: 2px solid transparent;\n outline-offset: -2px;\n }\n }\n\n @media (pointer: coarse) {\n --toggle-width: 1.5rem;\n --min-item-height: 2.75rem;\n }\n\n &:has(.TreeViewFailureMessage):hover {\n cursor: default;\n background-color: transparent;\n\n @media (forced-colors: active) {\n outline: none;\n }\n }\n\n &:has([role='treeitem']:focus-visible) {\n box-shadow: var(--boxShadow-thick) var(--fgColor-accent);\n }\n }\n\n &:where([data-omit-spacer='true']) .TreeViewItemContainer {\n grid-template-columns: 0 0 0 1fr;\n }\n\n /* stylelint-disable-next-line selector-max-specificity */\n & .TreeViewItem > .TreeViewItemContainer:has(.TreeViewItemContent[aria-current='true']) {\n background-color: var(--control-transparent-bgColor-selected);\n\n /* Current item indicator */\n /* stylelint-disable-next-line selector-max-specificity -- Copied from primer/react */\n &::after {\n position: absolute;\n top: calc(50% - var(--base-size-12));\n left: calc(-1 * var(--base-size-8));\n width: 0.25rem;\n height: 1.5rem;\n content: '';\n\n /*\n * Use fgColor accent for consistency across all themes. Using the \"correct\" variable,\n * --bgColor-accent-emphasis, causes vrt failures for dark high contrast mode\n */\n /* stylelint-disable-next-line primer/colors */\n background-color: var(--fgColor-accent);\n border-radius: var(--borderRadius-medium);\n\n @media (forced-colors: active) {\n background-color: HighlightText;\n }\n }\n }\n\n & .TreeViewItemToggle {\n display: flex;\n height: 100%;\n\n /* The toggle should appear vertically centered for single-line items, but remain at the top for items that wrap\n across more lines. */\n /* stylelint-disable-next-line primer/spacing */\n padding-top: calc(var(--min-item-height) / 2 - var(--base-size-12) / 2);\n color: var(--fgColor-muted);\n grid-area: toggle;\n justify-content: center;\n align-items: flex-start;\n cursor: pointer;\n }\n\n & .TreeViewItemToggleHover:hover {\n background-color: var(--control-transparent-bgColor-hover);\n }\n\n & .TreeViewItemToggleEnd {\n border-top-left-radius: var(--borderRadius-medium);\n border-bottom-left-radius: var(--borderRadius-medium);\n }\n\n /* stylelint-disable-next-line selector-no-qualifying-type */\n & a.TreeViewItemContent:hover, button.TreeViewItemContent:hover {\n text-decoration: underline;\n text-decoration-color: var(--control-fgColor-rest);\n }\n\n & :has(.TreeViewItemContent[aria-disabled=\"true\"]) {\n cursor: not-allowed;\n }\n\n & .TreeViewItemContent {\n display: flex;\n height: 100%;\n padding: 0 var(--base-size-8);\n outline: none;\n text-align: left;\n user-select: none;\n background-color: transparent;\n border: none;\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n cursor: pointer;\n\n /* The dynamic top and bottom padding to maintain the minimum item height for single line items */\n /* stylelint-disable-next-line primer/spacing */\n padding-top: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2);\n /* stylelint-disable-next-line primer/spacing */\n padding-bottom: calc((var(--min-item-height) - var(--custom-line-height, 1.3rem)) / 2);\n line-height: var(--custom-line-height, var(--text-body-lineHeight-medium, 1.4285));\n grid-area: content;\n gap: var(--stack-gap-condensed);\n\n & .TreeViewItemCheckbox {\n position: relative;\n color: var(--control-fgColor-rest);\n text-align: left;\n user-select: none;\n background-color: transparent;\n border: none;\n border-radius: var(--borderRadius-medium);\n transition: background 33.333ms linear;\n touch-action: manipulation;\n -webkit-tap-highlight-color: transparent;\n }\n\n &[aria-checked='true'] {\n & .FormControl-checkbox {\n background: var(--control-checked-bgColor-rest);\n border-color: var(--control-checked-borderColor-rest);\n transition: background-color, border-color 80ms cubic-bezier(0.32, 0, 0.67, 0) 0ms; /* unchecked -> checked */\n\n /* stylelint-disable-next-line max-nesting-depth, selector-max-specificity -- Copied from primer/react */\n &::before {\n visibility: visible;\n transition: visibility 0s linear 0s;\n animation: checkmarkIn 80ms cubic-bezier(0.65, 0, 0.35, 1) forwards 80ms;\n }\n }\n }\n\n &[aria-checked='false'] {\n /* singleselect checkmark */\n & .TreeViewItem-singleSelectCheckmark {\n visibility: hidden;\n }\n }\n\n &[aria-checked='mixed'] {\n & .FormControl-checkbox {\n background: var(--control-checked-bgColor-rest);\n border-color: var(--control-checked-borderColor-rest);\n transition: background-color, border-color 80ms cubic-bezier(0.32, 0, 0.67, 0) 0ms; /* unchecked -> checked */\n\n /* stylelint-disable-next-line max-nesting-depth, selector-max-specificity -- Copied from primer/react */\n &::before {\n visibility: visible;\n mask-image: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAiIGhlaWdodD0iMiIgdmlld0JveD0iMCAwIDEwIDIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMCAxQzAgMC40NDc3MTUgMC40NDc3MTUgMCAxIDBIOUM5LjU1MjI5IDAgMTAgMC40NDc3MTUgMTAgMUMxMCAxLjU1MjI4IDkuNTUyMjkgMiA5IDJIMUMwLjQ0NzcxNSAyIDAgMS41NTIyOCAwIDFaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4K');\n animation: checkmarkIn 80ms cubic-bezier(0.65, 0, 0.35, 1) forwards 80ms;\n clip-path: none;\n }\n }\n }\n\n &[aria-disabled='true'] {\n pointer-events: none;\n\n & .TreeViewItemContentText {\n color: var(--control-fgColor-disabled);\n }\n\n & .TreeViewItemVisual {\n fill: var(--control-fgColor-disabled);\n\n /* stylelint-disable-next-line max-nesting-depth, selector-max-compound-selectors, selector-max-specificity */\n & svg {\n fill: var(--control-fgColor-disabled);\n }\n }\n\n & .FormControl-checkbox {\n /* stylelint-disable-next-line max-nesting-depth */\n @media (hover: hover) {\n /* stylelint-disable-next-line max-nesting-depth, selector-max-specificity */\n &:hover {\n cursor: not-allowed;\n }\n }\n }\n\n @media (hover: hover) {\n /* stylelint-disable-next-line max-nesting-depth */\n &:hover {\n cursor: not-allowed;\n background-color: transparent;\n }\n }\n }\n }\n\n & .TreeViewItemContentText {\n color: var(--control-fgColor-rest);\n flex: 1 1 auto;\n width: 0;\n }\n\n &:where([data-truncate-text='true']) .TreeViewItemContentText {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n &:where([data-truncate-text='false']) .TreeViewItemContentText {\n /* stylelint-disable-next-line declaration-property-value-keyword-no-deprecated -- Copied from primer/react */\n word-break: break-word;\n }\n\n & .TreeViewItemVisual {\n display: flex;\n\n /* The visual icons should appear vertically centered for single-line items, but remain at the top for items that wrap\n across more lines. */\n height: var(--custom-line-height, 1.3rem);\n color: var(--fgColor-muted);\n align-items: center;\n }\n\n & .TreeViewItemLeadingAction {\n display: flex;\n color: var(--fgColor-muted);\n grid-area: leadingAction;\n\n & > button {\n flex-shrink: 1;\n }\n }\n\n & .TreeViewItemLevelLine {\n width: 100%;\n height: 100%;\n\n /*\n * On devices without hover, the nesting indicator lines\n * appear at all times.\n */\n border-color: var(--borderColor-muted);\n border-right: var(--borderWidth-thin) solid;\n }\n\n /*\n * On devices with :hover support, the nesting indicator lines\n * fade in when the user mouses over the entire component,\n * or when there's focus inside the component. This makes\n * sure the component remains simple when not in use.\n */\n @media (hover: hover) {\n .TreeViewItemLevelLine {\n border-color: transparent;\n }\n\n &:hover .TreeViewItemLevelLine,\n &:focus-within .TreeViewItemLevelLine {\n border-color: var(--borderColor-muted);\n }\n }\n\n & .TreeViewVisuallyHidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n /* stylelint-disable-next-line primer/spacing */\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0;\n }\n}\n\n.TreeViewSkeletonItemContainerStyle {\n display: flex;\n align-items: center;\n column-gap: 0.5rem;\n height: 2rem;\n\n @media (pointer: coarse) {\n height: 2.75rem;\n }\n\n &:nth-of-type(5n + 1) {\n --tree-item-loading-width: 67%;\n }\n\n &:nth-of-type(5n + 2) {\n --tree-item-loading-width: 47%;\n }\n\n &:nth-of-type(5n + 3) {\n --tree-item-loading-width: 73%;\n }\n\n &:nth-of-type(5n + 4) {\n --tree-item-loading-width: 64%;\n }\n\n &:nth-of-type(5n + 5) {\n --tree-item-loading-width: 50%;\n }\n}\n\n.TreeItemSkeletonTextStyles {\n width: var(--tree-item-loading-width, 67%);\n}\n\n.TreeViewFailureMessage {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: 0.5rem;\n width: 100%;\n align-items: center;\n}\n"]}
|
@@ -197,6 +197,13 @@
|
|
197
197
|
}
|
198
198
|
}
|
199
199
|
|
200
|
+
&[aria-checked='false'] {
|
201
|
+
/* singleselect checkmark */
|
202
|
+
& .TreeViewItem-singleSelectCheckmark {
|
203
|
+
visibility: hidden;
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
200
207
|
&[aria-checked='mixed'] {
|
201
208
|
& .FormControl-checkbox {
|
202
209
|
background: var(--control-checked-bgColor-rest);
|
@@ -240,6 +240,14 @@ module Primer
|
|
240
240
|
#
|
241
241
|
# Nodes can be checked via the keyboard by pressing the space key.
|
242
242
|
#
|
243
|
+
# ## Single-select mode
|
244
|
+
#
|
245
|
+
# By passing `select_variant: :single` to both sub-tree and leaf nodes:
|
246
|
+
# - Nodes become selectable and can be toggled via keyboard (space key).
|
247
|
+
# - A selected node displays a checkmark at the end of the line.
|
248
|
+
# Note: This checkmark conflicts with the `trailing_visual_icon` slot,
|
249
|
+
# so both cannot be used simultaneously.
|
250
|
+
#
|
243
251
|
# ## Node tags
|
244
252
|
#
|
245
253
|
# `TreeView`s support three different node variants, `:anchor`, `:button`, and `:div` (the default), which controls
|
@@ -259,13 +267,19 @@ module Primer
|
|
259
267
|
# |:---------------|:-------------|:------------|:--------------------------|
|
260
268
|
# |Enter/space |none |div |Expands/collapses |
|
261
269
|
# |Enter/space |none |anchor/button|Activates anchor/button |
|
270
|
+
# |Enter/space |single |div |Selects |
|
271
|
+
# |Enter/space |single |anchor/button|N/A (not allowed) |
|
262
272
|
# |Enter/space |multiple |div |Checks or unchecks |
|
263
273
|
# |Enter/space |multiple |anchor/button|N/A (not allowed) |
|
264
274
|
# |Left/right arrow|none |div |Expands/collapses |
|
265
275
|
# |Left/right arrow|none |anchor/button|Expands/collapses |
|
276
|
+
# |Left/right arrow|single |div |Expands/collapses |
|
277
|
+
# |Left/right arrow|single |anchor/button|N/A (not allowed) |
|
266
278
|
# |Left/right arrow|multiple |div |Expands/collapses |
|
267
279
|
# |Left/right arrow|multiple |anchor/button|N/A (not allowed) |
|
268
280
|
# |Click |none |div |Expands/collapses |
|
281
|
+
# |Click |single |div |Selects |
|
282
|
+
# |Click |single |anchor/button|N/A (not allowed) |
|
269
283
|
# |Click |multiple |div |Checks or unchecks |
|
270
284
|
# |Click |multiple |anchor/button|N/A (not allowed) |
|
271
285
|
#
|
@@ -351,7 +365,7 @@ module Primer
|
|
351
365
|
# )
|
352
366
|
# ```
|
353
367
|
#
|
354
|
-
# Because checking or unchecking a sub-tree
|
368
|
+
# Because checking or unchecking a sub-tree may result in the checking or unchecking of all its children recursively,
|
355
369
|
# both the `treeViewNodeChecked` and `treeViewBeforeNodeChecked` events provide an array of `TreeViewNodeInfo`
|
356
370
|
# objects, which contain entries for every modified node in the tree.
|
357
371
|
class TreeView < Primer::Component
|
@@ -9,29 +9,39 @@ module Primer
|
|
9
9
|
# should not be used directly.
|
10
10
|
class SubTree < Primer::Alpha::TreeView::SubTree
|
11
11
|
def with_sub_tree(**system_arguments, &block)
|
12
|
+
system_arguments[:select_variant] ||= :multiple
|
13
|
+
|
14
|
+
if system_arguments[:select_variant] != :multiple && system_arguments[:select_variant] != :single
|
15
|
+
raise ArgumentError, "FilterableTreeView only supports `:multiple` or `:single` as select_variant"
|
16
|
+
end
|
17
|
+
|
12
18
|
super(
|
13
19
|
sub_tree_component_klass: self.class,
|
14
20
|
**system_arguments,
|
15
|
-
select_variant: :multiple,
|
16
21
|
select_strategy: :self,
|
17
22
|
&block
|
18
23
|
)
|
19
24
|
end
|
20
25
|
|
21
26
|
def with_leaf(**system_arguments, &block)
|
27
|
+
system_arguments[:select_variant] ||= :multiple
|
28
|
+
|
29
|
+
if system_arguments[:select_variant] != :multiple && system_arguments[:select_variant] != :single
|
30
|
+
raise ArgumentError, "FilterableTreeView only supports `:multiple` or `:single` as select_variant"
|
31
|
+
end
|
32
|
+
|
22
33
|
super(
|
23
34
|
**system_arguments,
|
24
|
-
select_variant: :multiple,
|
25
35
|
&block
|
26
36
|
)
|
27
37
|
end
|
28
38
|
|
29
39
|
def with_loading_spinner(**system_arguments)
|
30
|
-
raise ArgumentError, "
|
40
|
+
raise ArgumentError, "FilterableTreeView does not support asynchronous loading"
|
31
41
|
end
|
32
42
|
|
33
43
|
def with_loading_skeleton(**system_arguments)
|
34
|
-
raise ArgumentError, "
|
44
|
+
raise ArgumentError, "FilterableTreeView does not support asynchronous loading"
|
35
45
|
end
|
36
46
|
end
|
37
47
|
end
|