openproject-primer_view_components 0.70.5 → 0.71.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 +6 -0
- data/app/assets/javascripts/components/primer/alpha/segmented_control.d.ts +2 -2
- data/app/assets/javascripts/components/primer/open_project/filterable_tree_view.d.ts +29 -0
- data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view.d.ts +11 -1
- data/app/assets/javascripts/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.d.ts +5 -1
- data/app/assets/javascripts/components/primer/primer.d.ts +1 -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/segmented_control.d.ts +2 -2
- data/app/components/primer/alpha/segmented_control.js +12 -0
- data/app/components/primer/alpha/segmented_control.ts +16 -1
- data/app/components/primer/alpha/stack.css +1 -1
- data/app/components/primer/alpha/stack.css.json +5 -1
- data/app/components/primer/alpha/stack.css.map +1 -1
- data/app/components/primer/alpha/stack.pcss +13 -0
- data/app/components/primer/alpha/stack.rb +2 -1
- data/app/components/primer/open_project/filterable_tree_view/sub_tree.rb +39 -0
- data/app/components/primer/open_project/filterable_tree_view.d.ts +29 -0
- data/app/components/primer/open_project/filterable_tree_view.html.erb +28 -0
- data/app/components/primer/open_project/filterable_tree_view.js +409 -0
- data/app/components/primer/open_project/filterable_tree_view.rb +254 -0
- data/app/components/primer/open_project/filterable_tree_view.ts +492 -0
- data/app/components/primer/open_project/tree_view/node.rb +19 -3
- data/app/components/primer/open_project/tree_view/sub_tree_node.rb +14 -4
- data/app/components/primer/open_project/tree_view/tree_view.d.ts +11 -1
- data/app/components/primer/open_project/tree_view/tree_view.js +120 -20
- data/app/components/primer/open_project/tree_view/tree_view.ts +137 -18
- data/app/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.d.ts +5 -1
- data/app/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.js +27 -4
- data/app/components/primer/open_project/tree_view/tree_view_sub_tree_node_element.ts +36 -5
- data/app/components/primer/open_project/tree_view.css +1 -1
- data/app/components/primer/open_project/tree_view.css.json +9 -0
- data/app/components/primer/open_project/tree_view.css.map +1 -1
- data/app/components/primer/open_project/tree_view.html.erb +4 -0
- data/app/components/primer/open_project/tree_view.pcss +48 -0
- data/app/components/primer/open_project/tree_view.rb +6 -1
- data/app/components/primer/primer.d.ts +1 -0
- data/app/components/primer/primer.js +1 -0
- data/app/components/primer/primer.ts +1 -0
- data/app/lib/primer/forms/base_component.rb +1 -1
- data/app/lib/primer/forms/dsl/text_field_input.rb +2 -0
- data/config/locales/en.yml +20 -0
- data/lib/primer/view_components/version.rb +2 -2
- data/previews/primer/open_project/filterable_tree_view_preview/_custom_select_js.html.erb +62 -0
- data/previews/primer/open_project/filterable_tree_view_preview/custom_checkbox_text.html.erb +26 -0
- data/previews/primer/open_project/filterable_tree_view_preview/custom_no_results_text.html.erb +28 -0
- data/previews/primer/open_project/filterable_tree_view_preview/custom_segmented_control.html.erb +31 -0
- data/previews/primer/open_project/filterable_tree_view_preview/default.html.erb +26 -0
- data/previews/primer/open_project/filterable_tree_view_preview/form_input.html.erb +32 -0
- data/previews/primer/open_project/filterable_tree_view_preview/playground.html.erb +26 -0
- data/previews/primer/open_project/filterable_tree_view_preview.rb +125 -0
- data/previews/primer/open_project/tree_view_preview/buttons.html.erb +4 -4
- data/previews/primer/open_project/tree_view_preview/default.html.erb +4 -4
- data/previews/primer/open_project/tree_view_preview/leaf_node_playground.html.erb +1 -1
- data/previews/primer/open_project/tree_view_preview/links.html.erb +4 -4
- data/previews/primer/open_project/tree_view_preview.rb +18 -8
- data/static/arguments.json +89 -3
- data/static/audited_at.json +2 -0
- data/static/constants.json +40 -1
- data/static/info_arch.json +220 -3
- data/static/previews.json +86 -0
- data/static/statuses.json +2 -0
- metadata +18 -2
@@ -7,6 +7,8 @@ import type {TreeViewNodeInfo} from '../../shared_events'
|
|
7
7
|
|
8
8
|
type LoadingState = 'loading' | 'error' | 'success'
|
9
9
|
|
10
|
+
export type SelectStrategy = 'self' | 'descendants' | 'mixed_descendants'
|
11
|
+
|
10
12
|
@controller
|
11
13
|
export class TreeViewSubTreeNodeElement extends HTMLElement {
|
12
14
|
@target node: HTMLElement
|
@@ -70,7 +72,7 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
70
72
|
)
|
71
73
|
|
72
74
|
const checkedMutationObserver = new MutationObserver(() => {
|
73
|
-
if (this.selectStrategy !== '
|
75
|
+
if (this.selectStrategy !== 'mixed_descendants') return
|
74
76
|
|
75
77
|
let checkType = 'unknown'
|
76
78
|
|
@@ -127,8 +129,12 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
127
129
|
this.#update()
|
128
130
|
}
|
129
131
|
|
130
|
-
get selectStrategy():
|
131
|
-
return this.node.getAttribute('data-select-strategy') || 'descendants'
|
132
|
+
get selectStrategy(): SelectStrategy {
|
133
|
+
return (this.node.getAttribute('data-select-strategy') || 'descendants') as SelectStrategy
|
134
|
+
}
|
135
|
+
|
136
|
+
get level(): number {
|
137
|
+
return parseInt(this.node.getAttribute('aria-level') || '0')
|
132
138
|
}
|
133
139
|
|
134
140
|
disconnectedCallback() {
|
@@ -211,6 +217,12 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
211
217
|
}
|
212
218
|
}
|
213
219
|
|
220
|
+
*eachDirectDescendantSubTreeNode(): Generator<TreeViewSubTreeNodeElement> {
|
221
|
+
for (const subTree of this.subTree.querySelectorAll(':scope > tree-view-sub-tree-node')) {
|
222
|
+
yield subTree as TreeViewSubTreeNodeElement
|
223
|
+
}
|
224
|
+
}
|
225
|
+
|
214
226
|
*eachDescendantNode(): Generator<Element> {
|
215
227
|
for (const node of this.subTree.querySelectorAll('[role=treeitem]')) {
|
216
228
|
yield node
|
@@ -299,6 +311,11 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
299
311
|
|
300
312
|
switch (event.key) {
|
301
313
|
case 'Enter':
|
314
|
+
if (this.treeView?.getNodeDisabledValue(node)) {
|
315
|
+
event.preventDefault()
|
316
|
+
break
|
317
|
+
}
|
318
|
+
|
302
319
|
// eslint-disable-next-line no-restricted-syntax
|
303
320
|
event.stopPropagation()
|
304
321
|
|
@@ -324,6 +341,11 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
324
341
|
break
|
325
342
|
|
326
343
|
case ' ':
|
344
|
+
if (this.treeView?.getNodeDisabledValue(node)) {
|
345
|
+
event.preventDefault()
|
346
|
+
break
|
347
|
+
}
|
348
|
+
|
327
349
|
if (this.#checkboxElement) {
|
328
350
|
// eslint-disable-next-line no-restricted-syntax
|
329
351
|
event.stopPropagation()
|
@@ -344,6 +366,11 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
344
366
|
}
|
345
367
|
|
346
368
|
#handleCheckboxEvent(event: Event) {
|
369
|
+
if (this.treeView?.getNodeDisabledValue(this.node)) {
|
370
|
+
event.preventDefault()
|
371
|
+
return
|
372
|
+
}
|
373
|
+
|
347
374
|
if (event.type !== 'click') return
|
348
375
|
|
349
376
|
this.toggleChecked()
|
@@ -354,13 +381,13 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
354
381
|
}
|
355
382
|
|
356
383
|
toggleChecked() {
|
357
|
-
const checkValue = this.node
|
384
|
+
const checkValue = this.treeView?.getNodeCheckedValue(this.node) || 'false'
|
358
385
|
const newCheckValue = checkValue === 'false' ? 'true' : 'false'
|
359
386
|
const nodeInfos: TreeViewNodeInfo[] = []
|
360
387
|
const rootInfo = this.treeView?.infoFromNode(this.node, newCheckValue)
|
361
388
|
if (rootInfo) nodeInfos.push(rootInfo)
|
362
389
|
|
363
|
-
if (this.selectStrategy === 'descendants') {
|
390
|
+
if (this.selectStrategy === 'descendants' || this.selectStrategy === 'mixed_descendants') {
|
364
391
|
for (const node of this.eachDescendantNode()) {
|
365
392
|
const info = this.treeView?.infoFromNode(node, newCheckValue)
|
366
393
|
if (info) nodeInfos.push(info)
|
@@ -439,6 +466,10 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
|
|
439
466
|
get #checkboxElement(): HTMLElement | null {
|
440
467
|
return this.querySelector('.TreeViewItemCheckbox')
|
441
468
|
}
|
469
|
+
|
470
|
+
changeSelectStrategy(newStrategy: SelectStrategy) {
|
471
|
+
this.node.setAttribute('data-select-strategy', newStrategy)
|
472
|
+
}
|
442
473
|
}
|
443
474
|
|
444
475
|
if (!window.customElements.get('tree-view-sub-tree-node')) {
|
@@ -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 .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}.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=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}}:is(.TreeViewRootUlStyles .TreeViewItemContent) ::highlight(primer-filterable-tree-view-search-results){background-color:var(--label-yellow-bgColor-active);color:var(--fgColor-default)}:is(.TreeViewRootUlStyles .TreeViewItemContent) mark{background-color:var(--label-yellow-bgColor-active);color:var(--fgColor-default)}.TreeViewRootUlStyles .TreeViewItemContentText{color:var(--control-fgColor-rest);flex:1 1 auto;-webkit-user-select: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%}
|
@@ -17,12 +17,21 @@
|
|
17
17
|
".TreeViewRootUlStyles .TreeViewItemToggleEnd",
|
18
18
|
".TreeViewRootUlStyles a.TreeViewItemContent:hover",
|
19
19
|
".TreeViewRootUlStyles button.TreeViewItemContent:hover",
|
20
|
+
".TreeViewRootUlStyles :has(.TreeViewItemContent[aria-disabled=true])",
|
20
21
|
".TreeViewRootUlStyles .TreeViewItemContent",
|
21
22
|
":is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItemCheckbox",
|
22
23
|
"[aria-checked=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox",
|
23
24
|
":is([aria-checked=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox):before",
|
24
25
|
"[aria-checked=mixed]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox",
|
25
26
|
":is([aria-checked=mixed]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox):before",
|
27
|
+
"[aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent)",
|
28
|
+
"[aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItemContentText",
|
29
|
+
":is([aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItemVisual) svg",
|
30
|
+
"[aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .TreeViewItemVisual",
|
31
|
+
":is([aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent) .FormControl-checkbox):hover",
|
32
|
+
"[aria-disabled=true]:is(.TreeViewRootUlStyles .TreeViewItemContent):hover",
|
33
|
+
":is(.TreeViewRootUlStyles .TreeViewItemContent) ::highlight(primer-filterable-tree-view-search-results)",
|
34
|
+
":is(.TreeViewRootUlStyles .TreeViewItemContent) mark",
|
26
35
|
".TreeViewRootUlStyles .TreeViewItemContentText",
|
27
36
|
".TreeViewRootUlStyles:where([data-truncate-text=true]) .TreeViewItemContentText",
|
28
37
|
".TreeViewRootUlStyles:where([data-truncate-text=false]) .TreeViewItemContentText",
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["tree_view.pcss"],"names":[],"mappings":"AAEA,sBAGE,eAAgB,CADhB,QAAS,CADT,SA+RF,CA9QE,oCACE,YAeF,CAbE,2DACE,uDAOF,CALE,8BAHF,2DAII,+BAAgC,CAEhC,iBAEJ,CADE,CAGF,kEACE,sBACF,CAGF,6CACE,SAAU,CACV,mBAAoB,CACpB,sBAAuB,CAOvB,wCAAyC,CADzC,4BAA6B,CAH7B,YAAa,CAEb,sCAAuC,CAIvC,yDAA0D,CAD1D,6FAA8F,CAN9F,iBAAkB,CAElB,UAAW,CAOX,gEAAmE,CACnE,+DA4BF,CA1BE,wDACE,yDAMF,CAJE,8BAHF,wDAII,uBAA8B,CAC9B,mBAEJ,CADE,CAGF,wBA1BF,6CA2BI,qBAAsB,CACtB,yBAeJ,CAdE,CAEA,qFAEE,wBAA6B,CAD7B,cAMF,CAHE,8BAJF,qFAKI,YAEJ,CADE,CAGF,qFACE,uDACF,CAGF,4EACE,+BACF,CAGA,wGACE,4DAwBF,CApBE,mHAaE,sCAAuC,CACvC,wCAAyC,CARzC,UAAW,CADX,aAAc,CAFd,gCAAmC,CAFnC,iBAAkB,CAClB,mCAAoC,CAEpC,YAeF,CAHE,8BAhBF,mHAiBI,8BAEJ,CADE,CAIJ,0CAWE,sBAAuB,CAHvB,0BAA2B,CAI3B,cAAe,CAXf,YAAa,CAQb,gBAAiB,CAPjB,WAAY,CAQZ,sBAAuB,CAHvB,kEAMF,CAEA,qDACE,yDACF,CAEA,6CAEE,oDAAqD,CADrD,iDAEF,CAGA,yGACE,iCAA0B,CAA1B,yBAA0B,CAC1B,iDACF,CAEA,2CAWE,cAAe,CAVf,YAAa,CAmBb,8BAA+B,CAD/B,iBAAkB,CAjBlB,WAAY,CAgBZ,+EAAkF,CAdlF,YAAa,CADb,4BAA6B,CAc7B,mFAAsF,CAFtF,gFAkDF,CA3CE,iHAfA,wBAA6B,CAC7B,WAAY,CAHZ,eAAgB,CAIhB,yBAA0B,CAH1B,wBAAiB,CAAjB,gBAAiB,CAIjB,uCAuBA,CAXA,sEAOE,wCAAyC,CALzC,iCAAkC,CADlC,iBAAkB,CAOlB,qCAGF,CAGE,yFACE,8CAA+C,CAC/C,oDAAqD,CACrD,0EAQF,CALE,qGAGE,kEAAwE,CADxE,kCAAmC,CADnC,kBAGF,CAKF,0FACE,8CAA+C,CAC/C,oDAAqD,CACrD,0EASF,CANE,sGAGE,kEAAwE,CACxE,cAAe,CAFf,wUAAia,CADja,kBAIF,CAKN,+CACE,iCAAkC,CAClC,aAAc,CACd,OACF,CAEA,gFACE,eAAgB,CAChB,sBAAuB,CACvB,kBACF,CAEA,iFAEE,qBACF,CAEA,0CAOE,kBAAmB,CADnB,0BAA2B,CAL3B,YAAa,CAIb,uCAGF,CAEA,iDAEE,0BAA2B,CAD3B,YAAa,CAEb,uBAKF,CAHE,6DACE,aACF,CAGF,6CAQE,qCAAsC,CACtC,0CAA2C,CAP3C,WAAY,CADZ,UASF,CAQA,qBACE,6CACE,kBACF,CAEA,6GAEE,qCACF,CACF,CAEA,8CAGE,UAAW,CAGX,WAAY,CACZ,eAAgB,CAHhB,SAAU,CAHV,iBAAkB,CAClB,SAAU,CAMV,kBAAsB,CAEtB,cAAe,CADf,kBAEF,CAGF,oCAEE,kBAAmB,CACnB,gBAAkB,CAFlB,YAAa,CAGb,WAyBF,CAvBE,wBANF,oCAOI,cAsBJ,CArBE,CAEA,sDACE,6BACF,CAEA,sDACE,6BACF,CAEA,sDACE,6BACF,CAEA,sDACE,6BACF,CAEA,sDACE,6BACF,CAGF,4BACE,wCACF,CAEA,wBAKE,kBAAmB,CAJnB,YAAa,CAEb,SAAW,CADX,8BAA+B,CAE/B,UAEF","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 & .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\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":"AAEA,sBAGE,eAAgB,CADhB,QAAS,CADT,SA+UF,CA9TE,oCACE,YAeF,CAbE,2DACE,uDAOF,CALE,8BAHF,2DAII,+BAAgC,CAEhC,iBAEJ,CADE,CAGF,kEACE,sBACF,CAGF,6CACE,SAAU,CACV,mBAAoB,CACpB,sBAAuB,CAOvB,wCAAyC,CADzC,4BAA6B,CAH7B,YAAa,CAEb,sCAAuC,CAIvC,yDAA0D,CAD1D,6FAA8F,CAN9F,iBAAkB,CAElB,UAAW,CAOX,gEAAmE,CACnE,+DA4BF,CA1BE,wDACE,yDAMF,CAJE,8BAHF,wDAII,uBAA8B,CAC9B,mBAEJ,CADE,CAGF,wBA1BF,6CA2BI,qBAAsB,CACtB,yBAeJ,CAdE,CAEA,qFAEE,wBAA6B,CAD7B,cAMF,CAHE,8BAJF,qFAKI,YAEJ,CADE,CAGF,qFACE,uDACF,CAGF,4EACE,+BACF,CAGA,wGACE,4DAwBF,CApBE,mHAaE,sCAAuC,CACvC,wCAAyC,CARzC,UAAW,CADX,aAAc,CAFd,gCAAmC,CAFnC,iBAAkB,CAClB,mCAAoC,CAEpC,YAeF,CAHE,8BAhBF,mHAiBI,8BAEJ,CADE,CAIJ,0CAWE,sBAAuB,CAHvB,0BAA2B,CAI3B,cAAe,CAXf,YAAa,CAQb,gBAAiB,CAPjB,WAAY,CAQZ,sBAAuB,CAHvB,kEAMF,CAEA,qDACE,yDACF,CAEA,6CAEE,oDAAqD,CADrD,iDAEF,CAGA,yGACE,iCAA0B,CAA1B,yBAA0B,CAC1B,iDACF,CAEA,qEACE,kBACF,CAEA,2CAWE,cAAe,CAVf,YAAa,CAmBb,8BAA+B,CAD/B,iBAAkB,CAjBlB,WAAY,CAgBZ,+EAAkF,CAdlF,YAAa,CADb,4BAA6B,CAc7B,mFAAsF,CAFtF,gFA2FF,CApFE,iHAfA,wBAA6B,CAC7B,WAAY,CAHZ,eAAgB,CAIhB,yBAA0B,CAH1B,wBAAiB,CAAjB,gBAAiB,CAIjB,uCAuBA,CAXA,sEAOE,wCAAyC,CALzC,iCAAkC,CADlC,iBAAkB,CAOlB,qCAGF,CAGE,yFACE,8CAA+C,CAC/C,oDAAqD,CACrD,0EAQF,CALE,qGAGE,kEAAwE,CADxE,kCAAmC,CADnC,kBAGF,CAKF,0FACE,8CAA+C,CAC/C,oDAAqD,CACrD,0EASF,CANE,sGAGE,kEAAwE,CACxE,cAAe,CAFf,wUAAia,CADja,kBAIF,CAIJ,oEACE,mBA4BF,CA1BE,6FACE,qCACF,CAKE,yLACE,oCACF,CAIA,qBACE,qGACE,kBACF,CAKF,0EAEE,wBAA6B,CAD7B,kBAEF,CAPA,CAWJ,wGACE,mDAAoD,CACpD,4BACF,CAEA,qDACE,mDAAoD,CACpD,4BACF,CAGF,+CACE,iCAAkC,CAClC,aAAc,CAId,wBAAyB,CAHzB,OAIF,CAEA,gFACE,eAAgB,CAChB,sBAAuB,CACvB,kBACF,CAEA,iFAEE,qBACF,CAEA,0CAOE,kBAAmB,CADnB,0BAA2B,CAL3B,YAAa,CAIb,uCAGF,CAEA,iDAEE,0BAA2B,CAD3B,YAAa,CAEb,uBAKF,CAHE,6DACE,aACF,CAGF,6CAQE,qCAAsC,CACtC,0CAA2C,CAP3C,WAAY,CADZ,UASF,CAQA,qBACE,6CACE,kBACF,CAEA,6GAEE,qCACF,CACF,CAEA,8CAGE,UAAW,CAGX,WAAY,CACZ,eAAgB,CAHhB,SAAU,CAHV,iBAAkB,CAClB,SAAU,CAMV,kBAAsB,CAEtB,cAAe,CADf,kBAEF,CAGF,oCAEE,kBAAmB,CACnB,gBAAkB,CAFlB,YAAa,CAGb,WAyBF,CAvBE,wBANF,oCAOI,cAsBJ,CArBE,CAEA,sDACE,6BACF,CAEA,sDACE,6BACF,CAEA,sDACE,6BACF,CAEA,sDACE,6BACF,CAEA,sDACE,6BACF,CAGF,4BACE,wCACF,CAEA,wBAKE,kBAAmB,CAJnB,YAAa,CAEb,SAAW,CADX,8BAA+B,CAE/B,UAEF","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 & svg {\n fill: var(--control-fgColor-disabled);\n }\n }\n\n & .FormControl-checkbox {\n @media (hover: hover) {\n &:hover {\n cursor: not-allowed;\n }\n }\n }\n\n @media (hover: hover) {\n &:hover {\n cursor: not-allowed;\n background-color: transparent;\n }\n }\n }\n\n & ::highlight(primer-filterable-tree-view-search-results) {\n background-color: var(--label-yellow-bgColor-active);\n color: var(--fgColor-default);\n }\n\n & mark {\n background-color: var(--label-yellow-bgColor-active);\n color: var(--fgColor-default);\n }\n }\n\n & .TreeViewItemContentText {\n color: var(--control-fgColor-rest);\n flex: 1 1 auto;\n width: 0;\n /* Do not remove, as otherwise the filter result of the filterableTreeView will not be shown in Safari\n see: https://bugs.webkit.org/show_bug.cgi?id=278455 */\n -webkit-user-select: auto;\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,4 +1,8 @@
|
|
1
1
|
<tree-view>
|
2
|
+
<% if acts_as_form_input? %>
|
3
|
+
<%= @form_arguments[:builder].hidden_field(@form_arguments[:name], multiple: true, skip_default_ids: true, form: "", data: { target: "tree-view.formInputPrototype" }) %>
|
4
|
+
<div data-target="tree-view.formInputContainer"></div>
|
5
|
+
<% end %>
|
2
6
|
<%= render(Primer::BaseComponent.new(**@system_arguments)) do %>
|
3
7
|
<% nodes.each do |node| %>
|
4
8
|
<%= node %>
|
@@ -143,6 +143,10 @@
|
|
143
143
|
text-decoration-color: var(--control-fgColor-rest);
|
144
144
|
}
|
145
145
|
|
146
|
+
& :has(.TreeViewItemContent[aria-disabled=true]) {
|
147
|
+
cursor: not-allowed;
|
148
|
+
}
|
149
|
+
|
146
150
|
& .TreeViewItemContent {
|
147
151
|
display: flex;
|
148
152
|
height: 100%;
|
@@ -208,12 +212,56 @@
|
|
208
212
|
}
|
209
213
|
}
|
210
214
|
}
|
215
|
+
|
216
|
+
&[aria-disabled="true"] {
|
217
|
+
pointer-events: none;
|
218
|
+
|
219
|
+
& .TreeViewItemContentText {
|
220
|
+
color: var(--control-fgColor-disabled);
|
221
|
+
}
|
222
|
+
|
223
|
+
& .TreeViewItemVisual {
|
224
|
+
fill: var(--control-fgColor-disabled);
|
225
|
+
|
226
|
+
& svg {
|
227
|
+
fill: var(--control-fgColor-disabled);
|
228
|
+
}
|
229
|
+
}
|
230
|
+
|
231
|
+
& .FormControl-checkbox {
|
232
|
+
@media (hover: hover) {
|
233
|
+
&:hover {
|
234
|
+
cursor: not-allowed;
|
235
|
+
}
|
236
|
+
}
|
237
|
+
}
|
238
|
+
|
239
|
+
@media (hover: hover) {
|
240
|
+
&:hover {
|
241
|
+
cursor: not-allowed;
|
242
|
+
background-color: transparent;
|
243
|
+
}
|
244
|
+
}
|
245
|
+
}
|
246
|
+
|
247
|
+
& ::highlight(primer-filterable-tree-view-search-results) {
|
248
|
+
background-color: var(--label-yellow-bgColor-active);
|
249
|
+
color: var(--fgColor-default);
|
250
|
+
}
|
251
|
+
|
252
|
+
& mark {
|
253
|
+
background-color: var(--label-yellow-bgColor-active);
|
254
|
+
color: var(--fgColor-default);
|
255
|
+
}
|
211
256
|
}
|
212
257
|
|
213
258
|
& .TreeViewItemContentText {
|
214
259
|
color: var(--control-fgColor-rest);
|
215
260
|
flex: 1 1 auto;
|
216
261
|
width: 0;
|
262
|
+
/* Do not remove, as otherwise the filter result of the filterableTreeView will not be shown in Safari
|
263
|
+
see: https://bugs.webkit.org/show_bug.cgi?id=278455 */
|
264
|
+
-webkit-user-select: auto;
|
217
265
|
}
|
218
266
|
|
219
267
|
&:where([data-truncate-text='true']) .TreeViewItemContentText {
|
@@ -406,8 +406,9 @@ module Primer
|
|
406
406
|
|
407
407
|
# @param node_variant [Symbol] The variant to use for this node. <%= one_of(Primer::OpenProject::TreeView::NODE_VARIANT_OPTIONS) %>
|
408
408
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>.
|
409
|
-
def initialize(node_variant: DEFAULT_NODE_VARIANT, **system_arguments)
|
409
|
+
def initialize(node_variant: DEFAULT_NODE_VARIANT, form_arguments: {}, **system_arguments)
|
410
410
|
@system_arguments = deny_tag_argument(**system_arguments)
|
411
|
+
@form_arguments = form_arguments
|
411
412
|
|
412
413
|
@node_variant = fetch_or_fallback(NODE_VARIANT_OPTIONS, node_variant, DEFAULT_NODE_VARIANT)
|
413
414
|
|
@@ -419,6 +420,10 @@ module Primer
|
|
419
420
|
)
|
420
421
|
end
|
421
422
|
|
423
|
+
def acts_as_form_input?
|
424
|
+
@form_arguments[:builder] && @form_arguments[:name]
|
425
|
+
end
|
426
|
+
|
422
427
|
private
|
423
428
|
|
424
429
|
def before_render
|
@@ -37,3 +37,4 @@ import './open_project/tree_view/tree_view';
|
|
37
37
|
import './open_project/tree_view/tree_view_icon_pair_element';
|
38
38
|
import './open_project/tree_view/tree_view_sub_tree_node_element';
|
39
39
|
import './open_project/tree_view/tree_view_include_fragment_element';
|
40
|
+
import './open_project/filterable_tree_view';
|
@@ -37,3 +37,4 @@ import './open_project/tree_view/tree_view';
|
|
37
37
|
import './open_project/tree_view/tree_view_icon_pair_element';
|
38
38
|
import './open_project/tree_view/tree_view_sub_tree_node_element';
|
39
39
|
import './open_project/tree_view/tree_view_include_fragment_element';
|
40
|
+
import './open_project/filterable_tree_view';
|
@@ -37,3 +37,4 @@ import './open_project/tree_view/tree_view'
|
|
37
37
|
import './open_project/tree_view/tree_view_icon_pair_element'
|
38
38
|
import './open_project/tree_view/tree_view_sub_tree_node_element'
|
39
39
|
import './open_project/tree_view/tree_view_include_fragment_element'
|
40
|
+
import './open_project/filterable_tree_view'
|
@@ -41,6 +41,8 @@ module Primer
|
|
41
41
|
add_input_data(:target, "primer-text-field.inputElement #{system_arguments.dig(:data, :target) || ''}")
|
42
42
|
add_input_classes("FormControl-inset") if inset?
|
43
43
|
add_input_classes("FormControl-monospace") if monospace?
|
44
|
+
|
45
|
+
yield(self) if block_given?
|
44
46
|
end
|
45
47
|
|
46
48
|
alias show_clear_button? show_clear_button
|
@@ -0,0 +1,20 @@
|
|
1
|
+
en:
|
2
|
+
button_back: "Back"
|
3
|
+
button_cancel: "Cancel"
|
4
|
+
button_close: "Close"
|
5
|
+
button_delete: "Delete"
|
6
|
+
button_delete_permanently: "Delete permanently"
|
7
|
+
button_filter: "Filter"
|
8
|
+
button_save: "Save"
|
9
|
+
|
10
|
+
filterable_tree_view:
|
11
|
+
filter_mode:
|
12
|
+
all: "All"
|
13
|
+
label: "Filter mode"
|
14
|
+
selected: "Selected"
|
15
|
+
include_sub_items: "Include sub-items"
|
16
|
+
no_results_text: "No results"
|
17
|
+
|
18
|
+
label_title: "Title"
|
19
|
+
label_loading: "Loading..."
|
20
|
+
label_more: "More"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
<script>
|
2
|
+
function ready(fn) {
|
3
|
+
if (document.readyState !== 'loading') {
|
4
|
+
fn()
|
5
|
+
} else {
|
6
|
+
document.addEventListener('DOMContentLoaded', fn)
|
7
|
+
}
|
8
|
+
}
|
9
|
+
|
10
|
+
ready(() => {
|
11
|
+
const filterableTreeView = document.querySelector('filterable-tree-view')
|
12
|
+
filterableTreeView.filterFn = (node, query, filterMode) => {
|
13
|
+
const ranges = []
|
14
|
+
|
15
|
+
if (query.length > 0) {
|
16
|
+
const lowercaseQuery = query.toLowerCase()
|
17
|
+
const treeWalker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT)
|
18
|
+
let currentNode = treeWalker.nextNode()
|
19
|
+
|
20
|
+
while (currentNode) {
|
21
|
+
const lowercaseNodeText = currentNode.textContent?.toLocaleLowerCase() || ''
|
22
|
+
let startIndex = 0
|
23
|
+
|
24
|
+
while (startIndex < lowercaseNodeText.length) {
|
25
|
+
const index = lowercaseNodeText.indexOf(lowercaseQuery, startIndex)
|
26
|
+
if (index === -1) break
|
27
|
+
|
28
|
+
const range = new Range()
|
29
|
+
range.setStart(currentNode, index)
|
30
|
+
range.setEnd(currentNode, index + lowercaseQuery.length)
|
31
|
+
ranges.push(range)
|
32
|
+
|
33
|
+
startIndex = index + lowercaseQuery.length
|
34
|
+
}
|
35
|
+
|
36
|
+
currentNode = treeWalker.nextNode()
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
if (ranges.length === 0 && query.length > 0) {
|
41
|
+
return null
|
42
|
+
}
|
43
|
+
|
44
|
+
switch (filterMode) {
|
45
|
+
case 'teacher': {
|
46
|
+
// Only match nodes that are teachers
|
47
|
+
if (!node.dataset.path.includes('Students')) {
|
48
|
+
return ranges
|
49
|
+
}
|
50
|
+
|
51
|
+
break
|
52
|
+
}
|
53
|
+
|
54
|
+
case 'all': {
|
55
|
+
return ranges
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
return null
|
60
|
+
}
|
61
|
+
})
|
62
|
+
</script>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%= render(Primer::OpenProject::FilterableTreeView.new(include_sub_items_check_box_arguments: { name: :include_sub_items, label: "Including pupils" })) do |tree| %>
|
2
|
+
<% tree.with_sub_tree(label: "Students", expanded: expanded) do |hogwarts| %>
|
3
|
+
<% hogwarts.with_sub_tree(label: "Ravenclaw", expanded: expanded) do |ravenclaw| %>
|
4
|
+
<% ravenclaw.with_leaf(label: "Luna Lovegood") %>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<% hogwarts.with_sub_tree(label: "Slytherin", expanded: expanded) do |hufflepuff| %>
|
8
|
+
<% hufflepuff.with_leaf(label: "Draco Malfoy") %>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% hogwarts.with_sub_tree(label: "Hufflepuff", expanded: expanded) do |hufflepuff| %>
|
12
|
+
<% hufflepuff.with_leaf(label: "Susan Bones") %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<% hogwarts.with_sub_tree(label: "Gryffindor", expanded: expanded) do |hufflepuff| %>
|
16
|
+
<% hufflepuff.with_leaf(label: "Harry Potter") %>
|
17
|
+
<% hufflepuff.with_leaf(label: "Ronald Weasley") %>
|
18
|
+
<% hufflepuff.with_leaf(label: "Hermione Granger") %>
|
19
|
+
<% end %>
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
<% tree.with_leaf(label: "Albus Dumbledore") %>
|
23
|
+
<% tree.with_leaf(label: "Minerva McGonagall") %>
|
24
|
+
<% tree.with_leaf(label: "Severus Snape") %>
|
25
|
+
<% tree.with_leaf(label: "Rubeus Hagrid") %>
|
26
|
+
<% end %>
|
data/previews/primer/open_project/filterable_tree_view_preview/custom_no_results_text.html.erb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
<%= render(Primer::OpenProject::FilterableTreeView.new(
|
2
|
+
filter_input_arguments: {placeholder: "Search me!", name: "filter", label: "Filter", visually_hide_label: true},
|
3
|
+
no_results_node_arguments: { label: "All wizards and witches have left the building" })) do |tree| %>
|
4
|
+
<% tree.with_sub_tree(label: "Students", expanded: expanded) do |hogwarts| %>
|
5
|
+
<% hogwarts.with_sub_tree(label: "Ravenclaw", expanded: expanded) do |ravenclaw| %>
|
6
|
+
<% ravenclaw.with_leaf(label: "Luna Lovegood") %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<% hogwarts.with_sub_tree(label: "Slytherin", expanded: expanded) do |hufflepuff| %>
|
10
|
+
<% hufflepuff.with_leaf(label: "Draco Malfoy") %>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<% hogwarts.with_sub_tree(label: "Hufflepuff", expanded: expanded) do |hufflepuff| %>
|
14
|
+
<% hufflepuff.with_leaf(label: "Susan Bones") %>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<% hogwarts.with_sub_tree(label: "Gryffindor", expanded: expanded) do |hufflepuff| %>
|
18
|
+
<% hufflepuff.with_leaf(label: "Harry Potter") %>
|
19
|
+
<% hufflepuff.with_leaf(label: "Ronald Weasley") %>
|
20
|
+
<% hufflepuff.with_leaf(label: "Hermione Granger") %>
|
21
|
+
<% end %>
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<% tree.with_leaf(label: "Albus Dumbledore") %>
|
25
|
+
<% tree.with_leaf(label: "Minerva McGonagall") %>
|
26
|
+
<% tree.with_leaf(label: "Severus Snape") %>
|
27
|
+
<% tree.with_leaf(label: "Rubeus Hagrid") %>
|
28
|
+
<% end %>
|
data/previews/primer/open_project/filterable_tree_view_preview/custom_segmented_control.html.erb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
<%= render(Primer::OpenProject::FilterableTreeView.new) do |tree| %>
|
2
|
+
<% tree.with_filter_mode(name: "teacher", label: "Teacher") %>
|
3
|
+
<% tree.with_filter_mode(name: "all", label: "All", selected: true) %>
|
4
|
+
|
5
|
+
<% tree.with_sub_tree(label: "Students", expanded: expanded) do |hogwarts| %>
|
6
|
+
<% hogwarts.with_sub_tree(label: "Ravenclaw", expanded: expanded) do |ravenclaw| %>
|
7
|
+
<% ravenclaw.with_leaf(label: "Luna Lovegood") %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% hogwarts.with_sub_tree(label: "Slytherin", expanded: expanded) do |hufflepuff| %>
|
11
|
+
<% hufflepuff.with_leaf(label: "Draco Malfoy") %>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<% hogwarts.with_sub_tree(label: "Hufflepuff", expanded: expanded) do |hufflepuff| %>
|
15
|
+
<% hufflepuff.with_leaf(label: "Susan Bones") %>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<% hogwarts.with_sub_tree(label: "Gryffindor", expanded: expanded) do |hufflepuff| %>
|
19
|
+
<% hufflepuff.with_leaf(label: "Harry Potter") %>
|
20
|
+
<% hufflepuff.with_leaf(label: "Ronald Weasley") %>
|
21
|
+
<% hufflepuff.with_leaf(label: "Hermione Granger") %>
|
22
|
+
<% end %>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<% tree.with_leaf(label: "Albus Dumbledore") %>
|
26
|
+
<% tree.with_leaf(label: "Minerva McGonagall") %>
|
27
|
+
<% tree.with_leaf(label: "Severus Snape") %>
|
28
|
+
<% tree.with_leaf(label: "Rubeus Hagrid") %>
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<%= render partial: "primer/open_project/filterable_tree_view_preview/custom_select_js", locals: { } %>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%= render(Primer::OpenProject::FilterableTreeView.new) do |tree| %>
|
2
|
+
<% tree.with_sub_tree(label: "Students", expanded: expanded) do |hogwarts| %>
|
3
|
+
<% hogwarts.with_sub_tree(label: "Ravenclaw", expanded: expanded) do |ravenclaw| %>
|
4
|
+
<% ravenclaw.with_leaf(label: "Luna Lovegood") %>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<% hogwarts.with_sub_tree(label: "Slytherin", expanded: expanded) do |hufflepuff| %>
|
8
|
+
<% hufflepuff.with_leaf(label: "Draco Malfoy") %>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% hogwarts.with_sub_tree(label: "Hufflepuff", expanded: expanded) do |hufflepuff| %>
|
12
|
+
<% hufflepuff.with_leaf(label: "Susan Bones") %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<% hogwarts.with_sub_tree(label: "Gryffindor", expanded: expanded) do |hufflepuff| %>
|
16
|
+
<% hufflepuff.with_leaf(label: "Harry Potter") %>
|
17
|
+
<% hufflepuff.with_leaf(label: "Ronald Weasley") %>
|
18
|
+
<% hufflepuff.with_leaf(label: "Hermione Granger") %>
|
19
|
+
<% end %>
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
<% tree.with_leaf(label: "Albus Dumbledore") %>
|
23
|
+
<% tree.with_leaf(label: "Minerva McGonagall") %>
|
24
|
+
<% tree.with_leaf(label: "Severus Snape") %>
|
25
|
+
<% tree.with_leaf(label: "Rubeus Hagrid") %>
|
26
|
+
<% end %>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<%= form_with(url: primer_view_components.generic_form_submission_path(format: :json)) do |f| %>
|
2
|
+
<%= render(Primer::Alpha::Stack.new) do %>
|
3
|
+
<%= render(Primer::OpenProject::FilterableTreeView.new(form_arguments: { builder: f, name: "characters" })) do |tree| %>
|
4
|
+
<% tree.with_sub_tree(label: "Students", expanded: expanded) do |hogwarts| %>
|
5
|
+
<% hogwarts.with_sub_tree(label: "Ravenclaw", expanded: expanded) do |ravenclaw| %>
|
6
|
+
<% ravenclaw.with_leaf(label: "Luna Lovegood") %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<% hogwarts.with_sub_tree(label: "Slytherin", expanded: expanded) do |hufflepuff| %>
|
10
|
+
<% hufflepuff.with_leaf(label: "Draco Malfoy") %>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<% hogwarts.with_sub_tree(label: "Hufflepuff", expanded: expanded) do |hufflepuff| %>
|
14
|
+
<% hufflepuff.with_leaf(label: "Susan Bones") %>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<% hogwarts.with_sub_tree(label: "Gryffindor", expanded: expanded) do |hufflepuff| %>
|
18
|
+
<% hufflepuff.with_leaf(label: "Harry Potter") %>
|
19
|
+
<% hufflepuff.with_leaf(label: "Ronald Weasley") %>
|
20
|
+
<% hufflepuff.with_leaf(label: "Hermione Granger") %>
|
21
|
+
<% end %>
|
22
|
+
<% end %>
|
23
|
+
|
24
|
+
<% tree.with_leaf(label: "Albus Dumbledore") %>
|
25
|
+
<% tree.with_leaf(label: "Minerva McGonagall") %>
|
26
|
+
<% tree.with_leaf(label: "Severus Snape") %>
|
27
|
+
<% tree.with_leaf(label: "Rubeus Hagrid") %>
|
28
|
+
<% end %>
|
29
|
+
|
30
|
+
<%= render(Primer::Alpha::SubmitButton.new(name: :submit, label: "Submit")) %>
|
31
|
+
<% end %>
|
32
|
+
<% end %>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%= render(Primer::OpenProject::FilterableTreeView.new) do |tree| %>
|
2
|
+
<% tree.with_sub_tree(label: "Students", expanded: expanded) do |hogwarts| %>
|
3
|
+
<% hogwarts.with_sub_tree(label: "Ravenclaw", expanded: expanded) do |ravenclaw| %>
|
4
|
+
<% ravenclaw.with_leaf(label: "Luna Lovegood") %>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<% hogwarts.with_sub_tree(label: "Slytherin", expanded: expanded) do |hufflepuff| %>
|
8
|
+
<% hufflepuff.with_leaf(label: "Draco Malfoy") %>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% hogwarts.with_sub_tree(label: "Hufflepuff", expanded: expanded) do |hufflepuff| %>
|
12
|
+
<% hufflepuff.with_leaf(label: "Susan Bones") %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<% hogwarts.with_sub_tree(label: "Gryffindor", expanded: expanded) do |hufflepuff| %>
|
16
|
+
<% hufflepuff.with_leaf(label: "Harry Potter") %>
|
17
|
+
<% hufflepuff.with_leaf(label: "Ronald Weasley") %>
|
18
|
+
<% hufflepuff.with_leaf(label: "Hermione Granger") %>
|
19
|
+
<% end %>
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
<% tree.with_leaf(label: "Albus Dumbledore") %>
|
23
|
+
<% tree.with_leaf(label: "Minerva McGonagall") %>
|
24
|
+
<% tree.with_leaf(label: "Severus Snape") %>
|
25
|
+
<% tree.with_leaf(label: "Rubeus Hagrid") %>
|
26
|
+
<% end %>
|