openproject-primer_view_components 0.78.0 → 0.78.1

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.
@@ -38,6 +38,7 @@ export declare class TreeViewElement extends HTMLElement {
38
38
  changeSelectStrategy(newStrategy: SelectStrategy): void;
39
39
  infoFromNode(node: Element, newCheckedValue?: TreeViewCheckedValue): TreeViewNodeInfo | null;
40
40
  selectVariant(node: Element): SelectVariant;
41
+ updateHiddenFormInputs(): void;
41
42
  }
42
43
  declare global {
43
44
  interface Window {
@@ -56,28 +56,17 @@ let TreeViewElement = class TreeViewElement extends HTMLElement {
56
56
  });
57
57
  if (!somethingChanged)
58
58
  return;
59
- const newInputs = [];
60
- // eslint-disable-next-line custom-elements/no-dom-traversal-in-connectedcallback
61
- for (const node of this.querySelectorAll('[role=treeitem][aria-checked=true]')) {
62
- const newInput = this.formInputPrototype.cloneNode();
63
- newInput.removeAttribute('data-target');
64
- newInput.removeAttribute('form');
65
- const payload = {
66
- path: this.getNodePath(node),
67
- };
68
- const inputValue = this.getFormInputValueForNode(node);
69
- if (inputValue)
70
- payload.value = inputValue;
71
- newInput.value = JSON.stringify(payload);
72
- newInputs.push(newInput);
73
- }
74
- this.formInputContainer.replaceChildren(...newInputs);
59
+ this.updateHiddenFormInputs();
75
60
  });
76
61
  updateInputsObserver.observe(this, {
77
62
  childList: true,
78
63
  subtree: true,
79
64
  attributeFilter: ['aria-checked'],
80
65
  });
66
+ // Correctly initialize the form
67
+ if (this.formInputContainer) {
68
+ this.updateHiddenFormInputs();
69
+ }
81
70
  // eslint-disable-next-line github/no-then -- We don't want to wait for this to resolve, just get on with it
82
71
  customElements.whenDefined('tree-view-sub-tree-node').then(() => {
83
72
  // depends on TreeViewSubTreeNodeElement#eachAncestorSubTreeNode, which may not be defined yet
@@ -287,6 +276,24 @@ let TreeViewElement = class TreeViewElement extends HTMLElement {
287
276
  selectVariant(node) {
288
277
  return (node.getAttribute('data-select-variant') || 'none');
289
278
  }
279
+ updateHiddenFormInputs() {
280
+ const newInputs = [];
281
+ // eslint-disable-next-line custom-elements/no-dom-traversal-in-connectedcallback
282
+ for (const node of this.querySelectorAll('[role=treeitem][aria-checked=true]')) {
283
+ const newInput = this.formInputPrototype.cloneNode();
284
+ newInput.removeAttribute('data-target');
285
+ newInput.removeAttribute('form');
286
+ const payload = {
287
+ path: this.getNodePath(node),
288
+ };
289
+ const inputValue = this.getFormInputValueForNode(node);
290
+ if (inputValue)
291
+ payload.value = inputValue;
292
+ newInput.value = JSON.stringify(payload);
293
+ newInputs.push(newInput);
294
+ }
295
+ this.formInputContainer.replaceChildren(...newInputs);
296
+ }
290
297
  };
291
298
  _TreeViewElement_abortController = new WeakMap();
292
299
  _TreeViewElement_instances = new WeakSet();
@@ -45,26 +45,7 @@ export class TreeViewElement extends HTMLElement {
45
45
 
46
46
  if (!somethingChanged) return
47
47
 
48
- const newInputs = []
49
-
50
- // eslint-disable-next-line custom-elements/no-dom-traversal-in-connectedcallback
51
- for (const node of this.querySelectorAll('[role=treeitem][aria-checked=true]')) {
52
- const newInput = this.formInputPrototype.cloneNode() as HTMLInputElement
53
- newInput.removeAttribute('data-target')
54
- newInput.removeAttribute('form')
55
-
56
- const payload: {path: string[]; value?: string} = {
57
- path: this.getNodePath(node),
58
- }
59
-
60
- const inputValue = this.getFormInputValueForNode(node)
61
- if (inputValue) payload.value = inputValue
62
-
63
- newInput.value = JSON.stringify(payload)
64
- newInputs.push(newInput)
65
- }
66
-
67
- this.formInputContainer.replaceChildren(...newInputs)
48
+ this.updateHiddenFormInputs()
68
49
  })
69
50
 
70
51
  updateInputsObserver.observe(this, {
@@ -73,6 +54,11 @@ export class TreeViewElement extends HTMLElement {
73
54
  attributeFilter: ['aria-checked'],
74
55
  })
75
56
 
57
+ // Correctly initialize the form
58
+ if (this.formInputContainer) {
59
+ this.updateHiddenFormInputs()
60
+ }
61
+
76
62
  // eslint-disable-next-line github/no-then -- We don't want to wait for this to resolve, just get on with it
77
63
  customElements.whenDefined('tree-view-sub-tree-node').then(() => {
78
64
  // depends on TreeViewSubTreeNodeElement#eachAncestorSubTreeNode, which may not be defined yet
@@ -483,6 +469,29 @@ export class TreeViewElement extends HTMLElement {
483
469
  selectVariant(node: Element): SelectVariant {
484
470
  return (node.getAttribute('data-select-variant') || 'none') as SelectVariant
485
471
  }
472
+
473
+ updateHiddenFormInputs() {
474
+ const newInputs = []
475
+
476
+ // eslint-disable-next-line custom-elements/no-dom-traversal-in-connectedcallback
477
+ for (const node of this.querySelectorAll('[role=treeitem][aria-checked=true]')) {
478
+ const newInput = this.formInputPrototype.cloneNode() as HTMLInputElement
479
+ newInput.removeAttribute('data-target')
480
+ newInput.removeAttribute('form')
481
+
482
+ const payload: {path: string[]; value?: string} = {
483
+ path: this.getNodePath(node),
484
+ }
485
+
486
+ const inputValue = this.getFormInputValueForNode(node)
487
+ if (inputValue) payload.value = inputValue
488
+
489
+ newInput.value = JSON.stringify(payload)
490
+ newInputs.push(newInput)
491
+ }
492
+
493
+ this.formInputContainer.replaceChildren(...newInputs)
494
+ }
486
495
  }
487
496
 
488
497
  if (!window.customElements.get('tree-view')) {
@@ -1 +1 @@
1
- .PageHeader{border-bottom:var(--borderWidth-thin) solid var(--borderColor-muted);display:flex;flex-flow:column;margin-bottom:var(--base-size-16);padding-bottom:var(--base-size-8)}.PageHeader--withTabNav{border-bottom:none;margin-bottom:0;padding-bottom:0}.PageHeader-contextBar{height:var(--control-small-size)}.PageHeader-contextBar,.PageHeader-titleBar{align-items:center;display:flex;flex-flow:row;justify-content:flex-end;margin-bottom:var(--base-size-8)}.PageHeader-title{flex:1 1 auto;font-size:var(--text-title-size-medium)}.PageHeader-title--large{font-size:var(--text-title-size-large)}.PageHeader-description{color:var(--fgColor-muted);flex:1 auto;font-size:var(--text-body-size-medium)}.PageHeader-description--underlined-links a{-webkit-text-decoration:underline;text-decoration:underline}.PageHeader-tabNavBar{overflow:auto}.PageHeader-tabNavBar .PageHeader-tabNav{min-width:max-content}.PageHeader--withTabNav .PageHeader-description{margin-bottom:var(--base-size-16)}.PageHeader-actions{align-items:center;display:flex;justify-content:flex-end}.PageHeader-breadcrumbs{display:block;width:100%}.PageHeader-leadingAction{margin-right:var(--base-size-4);margin-top:var(--base-size-2)}.PageHeader-parentLink{flex:1 1 auto}@media screen and (min-width:543.98px){.PageHeader--noBreadcrumb .PageHeader-contextBar{display:none}}.PageHeader--noBreadcrumb .PageHeader-titleBar{line-height:var(--control-small-size)}
1
+ .PageHeader{border-bottom:var(--borderWidth-thin) solid var(--borderColor-muted);display:flex;flex-flow:column;margin-bottom:var(--base-size-16);padding-bottom:var(--base-size-8)}.PageHeader--withTabNav{border-bottom:none;margin-bottom:0;padding-bottom:0}.PageHeader-contextBar{height:var(--control-small-size)}.PageHeader-contextBar,.PageHeader-titleBar{align-items:center;display:flex;flex-flow:row;justify-content:flex-end;margin-bottom:var(--base-size-8)}.PageHeader-title{flex:1 1 auto;font-size:var(--text-title-size-medium)}.PageHeader-title--large{font-size:var(--text-title-size-large)}.PageHeader-description{color:var(--fgColor-muted);flex:1 auto;font-size:var(--text-body-size-medium)}.PageHeader-description--underlined-links a{-webkit-text-decoration:underline;text-decoration:underline}.PageHeader-tabNavBar{overflow:auto}.PageHeader-tabNavBar .PageHeader-tabNav{min-width:max-content}.PageHeader--withTabNav .PageHeader-description{margin-bottom:var(--base-size-16)}.PageHeader-actions{align-items:center;display:flex;justify-content:flex-end}.PageHeader-breadcrumbs{display:block;width:100%}.PageHeader-leadingAction{margin-right:var(--base-size-4);margin-top:var(--base-size-2)}.PageHeader-parentLink{flex:1 1 auto}@media screen and (min-width:543.98px){.PageHeader--noBreadcrumb .PageHeader-contextBar{display:none}}.PageHeader--noBreadcrumb .PageHeader-titleBar{line-height:var(--control-small-size)}.PageHeader--noBreadcrumb .PageHeader-actions{height:var(--control-small-size)}
@@ -17,6 +17,7 @@
17
17
  ".PageHeader-leadingAction",
18
18
  ".PageHeader-parentLink",
19
19
  ".PageHeader--noBreadcrumb .PageHeader-contextBar",
20
- ".PageHeader--noBreadcrumb .PageHeader-titleBar"
20
+ ".PageHeader--noBreadcrumb .PageHeader-titleBar",
21
+ ".PageHeader--noBreadcrumb .PageHeader-actions"
21
22
  ]
22
23
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YAIE,oEAAqE,CAHrE,YAAa,CAIb,gBAAiB,CAFjB,iCAAkC,CADlC,iCAIF,CAEA,wBACE,kBAAmB,CAEnB,eAAgB,CADhB,gBAEF,CAEA,uBAME,gCACF,CAEA,4CALE,kBAAmB,CAHnB,YAAa,CACb,aAAc,CACd,wBAAyB,CAEzB,gCAUF,CAEA,kBAEE,aAAc,CADd,uCAEF,CAEA,yBACE,sCACF,CAGA,wBAEE,0BAA2B,CAC3B,WAAY,CAFZ,sCAGF,CAEA,4CAEE,iCAA0B,CAA1B,yBACF,CAEA,sBACE,aACF,CAEA,yCACE,qBACF,CAEA,gDACE,iCACF,CAEA,oBAGE,kBAAmB,CADnB,YAAa,CADb,wBAGF,CAEA,wBACE,aAAc,CACd,UACF,CAEA,0BAEE,+BAAgC,CADhC,6BAEF,CAEA,uBACE,aACF,CAGA,uCACE,iDACE,YACF,CACF,CAGA,+CACE,qCACF","file":"page_header.css","sourcesContent":["/* OP PageHeader */\n\n.PageHeader {\n display: flex;\n padding-bottom: var(--base-size-8);\n margin-bottom: var(--base-size-16);\n border-bottom: var(--borderWidth-thin) solid var(--borderColor-muted);\n flex-flow: column;\n}\n\n.PageHeader--withTabNav {\n border-bottom: none;\n padding-bottom: 0;\n margin-bottom: 0;\n}\n\n.PageHeader-contextBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center;\n margin-bottom: var(--base-size-8);\n height: var(--control-small-size);\n}\n\n.PageHeader-titleBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center; /* Keep back button vertically aligned. */\n margin-bottom: var(--base-size-8);\n}\n\n.PageHeader-title {\n font-size: var(--text-title-size-medium);\n flex: 1 1 auto;\n}\n\n.PageHeader-title--large {\n font-size: var(--text-title-size-large);\n}\n\n/* One-liner of supporting text */\n.PageHeader-description {\n font-size: var(--text-body-size-medium);\n color: var(--fgColor-muted);\n flex: 1 auto;\n}\n\n.PageHeader-description--underlined-links a {\n /* Ensure the accessibility is met, given that the description is written in light grey */\n text-decoration: underline;\n}\n\n.PageHeader-tabNavBar {\n overflow: auto;\n}\n\n.PageHeader-tabNavBar .PageHeader-tabNav {\n min-width: max-content;\n}\n\n.PageHeader--withTabNav .PageHeader-description {\n margin-bottom: var(--base-size-16);\n}\n\n.PageHeader-actions {\n justify-content: flex-end;\n display: flex;\n align-items: center;\n}\n\n.PageHeader-breadcrumbs {\n display: block;\n width: 100%;\n}\n\n.PageHeader-leadingAction {\n margin-top: var(--base-size-2); /* to center align with label */\n margin-right: var(--base-size-4);\n}\n\n.PageHeader-parentLink {\n flex: 1 1 auto;\n}\n\n/* Hide the context bar on desktop when no breadcrumb is visible */\n@media screen and (min-width: 543.98px) {\n .PageHeader--noBreadcrumb .PageHeader-contextBar {\n display: none;\n }\n}\n\n/* Match the title bar height with the toggle menu button for proper vertical alignment */\n.PageHeader--noBreadcrumb .PageHeader-titleBar {\n line-height: var(--control-small-size);\n}"]}
1
+ {"version":3,"sources":["page_header.pcss"],"names":[],"mappings":"AAEA,YAIE,oEAAqE,CAHrE,YAAa,CAIb,gBAAiB,CAFjB,iCAAkC,CADlC,iCAIF,CAEA,wBACE,kBAAmB,CAEnB,eAAgB,CADhB,gBAEF,CAEA,uBAME,gCACF,CAEA,4CALE,kBAAmB,CAHnB,YAAa,CACb,aAAc,CACd,wBAAyB,CAEzB,gCAUF,CAEA,kBAEE,aAAc,CADd,uCAEF,CAEA,yBACE,sCACF,CAGA,wBAEE,0BAA2B,CAC3B,WAAY,CAFZ,sCAGF,CAEA,4CAEE,iCAA0B,CAA1B,yBACF,CAEA,sBACE,aACF,CAEA,yCACE,qBACF,CAEA,gDACE,iCACF,CAEA,oBAGE,kBAAmB,CADnB,YAAa,CADb,wBAGF,CAEA,wBACE,aAAc,CACd,UACF,CAEA,0BAEE,+BAAgC,CADhC,6BAEF,CAEA,uBACE,aACF,CAGA,uCACE,iDACE,YACF,CACF,CAIE,+CACE,qCACF,CAEA,8CACE,gCACF","file":"page_header.css","sourcesContent":["/* OP PageHeader */\n\n.PageHeader {\n display: flex;\n padding-bottom: var(--base-size-8);\n margin-bottom: var(--base-size-16);\n border-bottom: var(--borderWidth-thin) solid var(--borderColor-muted);\n flex-flow: column;\n}\n\n.PageHeader--withTabNav {\n border-bottom: none;\n padding-bottom: 0;\n margin-bottom: 0;\n}\n\n.PageHeader-contextBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center;\n margin-bottom: var(--base-size-8);\n height: var(--control-small-size);\n}\n\n.PageHeader-titleBar {\n display: flex;\n flex-flow: row;\n justify-content: flex-end;\n align-items: center; /* Keep back button vertically aligned. */\n margin-bottom: var(--base-size-8);\n}\n\n.PageHeader-title {\n font-size: var(--text-title-size-medium);\n flex: 1 1 auto;\n}\n\n.PageHeader-title--large {\n font-size: var(--text-title-size-large);\n}\n\n/* One-liner of supporting text */\n.PageHeader-description {\n font-size: var(--text-body-size-medium);\n color: var(--fgColor-muted);\n flex: 1 auto;\n}\n\n.PageHeader-description--underlined-links a {\n /* Ensure the accessibility is met, given that the description is written in light grey */\n text-decoration: underline;\n}\n\n.PageHeader-tabNavBar {\n overflow: auto;\n}\n\n.PageHeader-tabNavBar .PageHeader-tabNav {\n min-width: max-content;\n}\n\n.PageHeader--withTabNav .PageHeader-description {\n margin-bottom: var(--base-size-16);\n}\n\n.PageHeader-actions {\n justify-content: flex-end;\n display: flex;\n align-items: center;\n}\n\n.PageHeader-breadcrumbs {\n display: block;\n width: 100%;\n}\n\n.PageHeader-leadingAction {\n margin-top: var(--base-size-2); /* to center align with label */\n margin-right: var(--base-size-4);\n}\n\n.PageHeader-parentLink {\n flex: 1 1 auto;\n}\n\n/* Hide the context bar on desktop when no breadcrumb is visible */\n@media screen and (min-width: 543.98px) {\n .PageHeader--noBreadcrumb .PageHeader-contextBar {\n display: none;\n }\n}\n\n/* Match the title bar and actions height with the toggle menu button for proper vertical alignment */\n.PageHeader--noBreadcrumb {\n & .PageHeader-titleBar {\n line-height: var(--control-small-size);\n }\n\n & .PageHeader-actions {\n height: var(--control-small-size);\n }\n}"]}
@@ -91,7 +91,13 @@
91
91
  }
92
92
  }
93
93
 
94
- /* Match the title bar height with the toggle menu button for proper vertical alignment */
95
- .PageHeader--noBreadcrumb .PageHeader-titleBar {
96
- line-height: var(--control-small-size);
94
+ /* Match the title bar and actions height with the toggle menu button for proper vertical alignment */
95
+ .PageHeader--noBreadcrumb {
96
+ & .PageHeader-titleBar {
97
+ line-height: var(--control-small-size);
98
+ }
99
+
100
+ & .PageHeader-actions {
101
+ height: var(--control-small-size);
102
+ }
97
103
  }
@@ -6,7 +6,7 @@ module Primer
6
6
  module VERSION
7
7
  MAJOR = 0
8
8
  MINOR = 78
9
- PATCH = 0
9
+ PATCH = 1
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
12
12
  end
@@ -2,7 +2,7 @@
2
2
  <%= render(Primer::Alpha::Stack.new) do %>
3
3
  <%= render(Primer::Alpha::TreeView.new(form_arguments: { builder: f, name: "folder_structure" })) do |tree| %>
4
4
  <% tree.with_sub_tree(label: "src", expanded: expanded, select_variant: select_variant, value: 0) do |sub_tree| %>
5
- <% sub_tree.with_leaf(label: "button.rb", select_variant: select_variant, value: 1) %>
5
+ <% sub_tree.with_leaf(label: "button.rb", select_variant: select_variant, value: 1, checked: true) %>
6
6
  <% sub_tree.with_leaf(label: "icon_button.rb", current: true, select_variant: select_variant, value: 2) %>
7
7
  <% end %>
8
8
 
@@ -7,7 +7,7 @@
7
7
  <% end %>
8
8
 
9
9
  <% hogwarts.with_sub_tree(label: "Slytherin", select_variant: select_variant, expanded: expanded) do |hufflepuff| %>
10
- <% hufflepuff.with_leaf(label: "Draco Malfoy", select_variant: select_variant) %>
10
+ <% hufflepuff.with_leaf(label: "Draco Malfoy", select_variant: select_variant, checked: true) %>
11
11
  <% end %>
12
12
 
13
13
  <% hogwarts.with_sub_tree(label: "Hufflepuff", select_variant: select_variant, expanded: expanded) do |hufflepuff| %>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openproject-primer_view_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.78.0
4
+ version: 0.78.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Open Source
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-11-13 00:00:00.000000000 Z
12
+ date: 2025-12-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionview