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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/app/assets/javascripts/components/primer/alpha/tree_view/tree_view.d.ts +6 -2
  4. data/app/assets/javascripts/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.d.ts +2 -0
  5. data/app/assets/javascripts/primer_view_components.js +1 -1
  6. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  7. data/app/assets/styles/primer_view_components.css +1 -1
  8. data/app/assets/styles/primer_view_components.css.map +1 -1
  9. data/app/components/primer/alpha/tree_view/node.html.erb +5 -1
  10. data/app/components/primer/alpha/tree_view/node.rb +7 -1
  11. data/app/components/primer/alpha/tree_view/sub_tree_node.rb +1 -1
  12. data/app/components/primer/alpha/tree_view/tree_view.d.ts +6 -2
  13. data/app/components/primer/alpha/tree_view/tree_view.js +52 -2
  14. data/app/components/primer/alpha/tree_view/tree_view.ts +67 -3
  15. data/app/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.d.ts +2 -0
  16. data/app/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.js +11 -0
  17. data/app/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.ts +12 -0
  18. data/app/components/primer/alpha/tree_view.css +1 -1
  19. data/app/components/primer/alpha/tree_view.css.json +1 -0
  20. data/app/components/primer/alpha/tree_view.css.map +1 -1
  21. data/app/components/primer/alpha/tree_view.pcss +7 -0
  22. data/app/components/primer/alpha/tree_view.rb +15 -1
  23. data/app/components/primer/open_project/filterable_tree_view/sub_tree.rb +14 -4
  24. data/app/components/primer/open_project/filterable_tree_view.rb +26 -2
  25. data/lib/primer/view_components/version.rb +2 -2
  26. data/previews/primer/alpha/tree_view_preview/default.html.erb +1 -1
  27. data/previews/primer/alpha/tree_view_preview/form_input.html.erb +4 -4
  28. data/previews/primer/alpha/tree_view_preview/multi_select.html.erb +10 -0
  29. data/previews/primer/alpha/tree_view_preview/single_select.html.erb +10 -0
  30. data/previews/primer/alpha/tree_view_preview.rb +38 -4
  31. data/previews/primer/open_project/filterable_tree_view_preview/form_input.html.erb +15 -15
  32. data/previews/primer/open_project/filterable_tree_view_preview/playground.html.erb +15 -15
  33. data/previews/primer/open_project/filterable_tree_view_preview.rb +6 -2
  34. data/static/arguments.json +1 -1
  35. data/static/constants.json +1 -0
  36. data/static/info_arch.json +28 -2
  37. data/static/previews.json +26 -0
  38. metadata +4 -2
@@ -23,7 +23,11 @@
23
23
  <%= leading_visual %>
24
24
  <% end %>
25
25
  <span class="TreeViewItemContentText"><%= text_content %></span>
26
- <% if trailing_visual? %>
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,
@@ -155,7 +155,7 @@ module Primer
155
155
  node_variant: node_variant
156
156
  )
157
157
 
158
- return if @node.select_variant == :none
158
+ return unless @node.select_variant == :multiple
159
159
 
160
160
  @node.merge_system_arguments!(
161
161
  data: {
@@ -1,5 +1,5 @@
1
- import { SelectStrategy, TreeViewSubTreeNodeElement } from './tree_view_sub_tree_node_element';
2
- import type { TreeViewNodeType, TreeViewCheckedValue, TreeViewNodeInfo } from '../../shared_events';
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.nodeHasCheckBox(node)) {
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 {TreeViewNodeType, TreeViewCheckedValue, TreeViewNodeInfo} from '../../shared_events'
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.nodeHasCheckBox(node)) {
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 results in the checking or unchecking of all its children recursively,
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, "FilteredTreeView does not support asynchronous loading"
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, "FilteredTreeView does not support asynchronous loading"
44
+ raise ArgumentError, "FilterableTreeView does not support asynchronous loading"
35
45
  end
36
46
  end
37
47
  end