openproject-primer_view_components 0.45.0 → 0.46.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1 @@
1
- .SubHeader{align-items:center;display:grid;grid-template-areas:"left middle right" "bottom bottom bottom";grid-template-columns:auto 1fr auto;margin-bottom:16px}.SubHeader--expandedSearch{grid-template-areas:"left left left" "bottom bottom bottom"}.SubHeader-rightPane{align-items:center;column-gap:12px;display:flex;grid-area:right}.SubHeader-middlePane{grid-area:middle;text-align:center}.SubHeader-bottomPane{grid-area:bottom}.SubHeader-leftPane{align-items:center;display:flex;gap:12px;grid-area:left;width:100%}.SubHeader-filterContainer{display:flex;gap:8px;width:100%}
1
+ .SubHeader{align-items:center;display:grid;grid-template-areas:"left middle right" "bottom bottom bottom";grid-template-columns:auto 1fr auto;margin-bottom:16px}.SubHeader--expandedSearch{grid-template-areas:"left left left" "bottom bottom bottom"}.SubHeader-rightPane{align-items:center;column-gap:12px;display:flex;grid-area:right}.SubHeader-middlePane{grid-area:middle;text-align:center}.SubHeader-bottomPane{grid-area:bottom}.SubHeader-leftPane{align-items:center;display:flex;gap:12px;grid-area:left;width:100%}:is(.SubHeader-leftPane [class*=FormControl-input-width--]):not(.FormControl-input-width--auto){width:100vw}.SubHeader-filterContainer{display:flex;gap:8px;width:100%}.SubHeader-filterInput_hiddenClearButton+button.FormControl-input-trailingAction{display:none}
@@ -7,6 +7,8 @@
7
7
  ".SubHeader-middlePane",
8
8
  ".SubHeader-bottomPane",
9
9
  ".SubHeader-leftPane",
10
- ".SubHeader-filterContainer"
10
+ ":is(.SubHeader-leftPane [class*=FormControl-input-width--]):not(.FormControl-input-width--auto)",
11
+ ".SubHeader-filterContainer",
12
+ ".SubHeader-filterInput_hiddenClearButton+button.FormControl-input-trailingAction"
11
13
  ]
12
14
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["sub_header.pcss"],"names":[],"mappings":"AAEA,WAII,kBAAmB,CAHnB,YAAa,CACb,8DAA+D,CAC/D,mCAAoC,CAEpC,kBACJ,CAEA,2BACI,2DACJ,CAEA,qBAGI,kBAAmB,CACnB,eAAgB,CAFhB,YAAa,CADb,eAIJ,CAEA,sBACI,gBAAiB,CACjB,iBACJ,CAEA,sBACI,gBACJ,CAEA,oBAGI,kBAAmB,CADnB,YAAa,CAGb,QAAS,CAJT,cAAe,CAGf,UAEJ,CAEA,2BACI,YAAa,CAEb,OAAQ,CADR,UAEJ","file":"sub_header.css","sourcesContent":["/* CSS for SubHeader */\n\n.SubHeader {\n display: grid;\n grid-template-areas: \"left middle right\" \"bottom bottom bottom\";\n grid-template-columns: auto 1fr auto;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.SubHeader--expandedSearch {\n grid-template-areas: \"left left left\" \"bottom bottom bottom\";\n}\n\n.SubHeader-rightPane {\n grid-area: right;\n display: flex;\n align-items: center;\n column-gap: 12px;\n}\n\n.SubHeader-middlePane {\n grid-area: middle;\n text-align: center;\n}\n\n.SubHeader-bottomPane {\n grid-area: bottom;\n}\n\n.SubHeader-leftPane {\n grid-area: left;\n display: flex;\n align-items: center;\n width: 100%;\n gap: 12px;\n}\n\n.SubHeader-filterContainer {\n display: flex;\n width: 100%;\n gap: 8px;\n}\n"]}
1
+ {"version":3,"sources":["sub_header.pcss"],"names":[],"mappings":"AAEA,WAII,kBAAmB,CAHnB,YAAa,CACb,8DAA+D,CAC/D,mCAAoC,CAEpC,kBACJ,CAEA,2BACI,2DACJ,CAEA,qBAGI,kBAAmB,CACnB,eAAgB,CAFhB,YAAa,CADb,eAIJ,CAEA,sBACI,gBAAiB,CACjB,iBACJ,CAEA,sBACI,gBACJ,CAEA,oBAGI,kBAAmB,CADnB,YAAa,CAGb,QAAS,CAJT,cAAe,CAGf,UAUJ,CAJQ,gGACI,WACJ,CAIR,2BACI,YAAa,CAEb,OAAQ,CADR,UAEJ,CAEA,iFACE,YACF","file":"sub_header.css","sourcesContent":["/* CSS for SubHeader */\n\n.SubHeader {\n display: grid;\n grid-template-areas: \"left middle right\" \"bottom bottom bottom\";\n grid-template-columns: auto 1fr auto;\n align-items: center;\n margin-bottom: 16px;\n}\n\n.SubHeader--expandedSearch {\n grid-template-areas: \"left left left\" \"bottom bottom bottom\";\n}\n\n.SubHeader-rightPane {\n grid-area: right;\n display: flex;\n align-items: center;\n column-gap: 12px;\n}\n\n.SubHeader-middlePane {\n grid-area: middle;\n text-align: center;\n}\n\n.SubHeader-bottomPane {\n grid-area: bottom;\n}\n\n.SubHeader-leftPane {\n grid-area: left;\n display: flex;\n align-items: center;\n width: 100%;\n gap: 12px;\n\n /* Since the container is not full width (due to the grid around it)\n we want it to grow, and then be limited by the max-width of the \"FormControl-input-width--xy\" class */\n & [class*='FormControl-input-width--'] {\n &:not(.FormControl-input-width--auto) {\n width: 100vw;\n }\n }\n}\n\n.SubHeader-filterContainer {\n display: flex;\n width: 100%;\n gap: 8px;\n}\n\n.SubHeader-filterInput_hiddenClearButton + button.FormControl-input-trailingAction {\n display: none;\n}\n"]}
@@ -34,6 +34,14 @@
34
34
  align-items: center;
35
35
  width: 100%;
36
36
  gap: 12px;
37
+
38
+ /* Since the container is not full width (due to the grid around it)
39
+ we want it to grow, and then be limited by the max-width of the "FormControl-input-width--xy" class */
40
+ & [class*='FormControl-input-width--'] {
41
+ &:not(.FormControl-input-width--auto) {
42
+ width: 100vw;
43
+ }
44
+ }
37
45
  }
38
46
 
39
47
  .SubHeader-filterContainer {
@@ -41,3 +49,7 @@
41
49
  width: 100%;
42
50
  gap: 8px;
43
51
  }
52
+
53
+ .SubHeader-filterInput_hiddenClearButton + button.FormControl-input-trailingAction {
54
+ display: none;
55
+ }
@@ -38,19 +38,36 @@ module Primer
38
38
  renders_one :filter_input, lambda { |name:, label:, **system_arguments|
39
39
  system_arguments[:classes] = class_names(
40
40
  system_arguments[:classes],
41
- "SubHeader-filterInput"
41
+ "SubHeader-filterInput",
42
+ "SubHeader-filterInput_hiddenClearButton"
42
43
  )
43
44
  system_arguments[:placeholder] ||= I18n.t("button_filter")
44
45
  system_arguments[:leading_visual] ||= { icon: :search }
45
46
  system_arguments[:visually_hide_label] ||= true
47
+ system_arguments[:input_width] ||= :medium
46
48
 
47
49
  system_arguments[:data] ||= {}
48
50
  system_arguments[:data][:target]= "sub-header.filterInput"
49
51
 
52
+ system_arguments[:show_clear_button] = true if system_arguments[:show_clear_button].nil?
53
+
54
+ if system_arguments[:show_clear_button]
55
+ system_arguments[:data] = merge_data(
56
+ system_arguments,
57
+ {
58
+ data: {
59
+ action: <<~JS
60
+ input:sub-header#toggleFilterInputClearButton
61
+ focus:sub-header#toggleFilterInputClearButton
62
+ JS
63
+ }
64
+ }
65
+ )
66
+ end
50
67
 
51
68
  @mobile_filter_trigger = Primer::Beta::IconButton.new(icon: system_arguments[:leading_visual][:icon],
52
69
  display: [:inline_flex, :none],
53
- aria: {label: label },
70
+ aria: { label: label },
54
71
  "data-action": "click:sub-header#expandFilterInput",
55
72
  "data-targets": HIDDEN_FILTER_TARGET_SELECTOR)
56
73
 
@@ -1,9 +1,13 @@
1
1
  declare class SubHeaderElement extends HTMLElement {
2
- filterInput: HTMLElement;
2
+ filterInput: HTMLInputElement;
3
3
  hiddenItemsOnExpandedFilter: HTMLElement[];
4
4
  shownItemsOnExpandedFilter: HTMLElement[];
5
+ connectedCallback(): void;
6
+ setupFilterInputClearButton(): void;
7
+ toggleFilterInputClearButton(): void;
5
8
  expandFilterInput(): void;
6
9
  collapseFilterInput(): void;
10
+ private waitForCondition;
7
11
  }
8
12
  declare global {
9
13
  interface Window {
@@ -6,6 +6,22 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { controller, target, targets } from '@github/catalyst';
8
8
  let SubHeaderElement = class SubHeaderElement extends HTMLElement {
9
+ connectedCallback() {
10
+ this.setupFilterInputClearButton();
11
+ }
12
+ setupFilterInputClearButton() {
13
+ this.waitForCondition(() => Boolean(this.filterInput), () => {
14
+ this.toggleFilterInputClearButton();
15
+ });
16
+ }
17
+ toggleFilterInputClearButton() {
18
+ if (this.filterInput.value.length > 0) {
19
+ this.filterInput.classList.remove('SubHeader-filterInput_hiddenClearButton');
20
+ }
21
+ else {
22
+ this.filterInput.classList.add('SubHeader-filterInput_hiddenClearButton');
23
+ }
24
+ }
9
25
  expandFilterInput() {
10
26
  for (const item of this.hiddenItemsOnExpandedFilter) {
11
27
  item.classList.add('d-none');
@@ -25,6 +41,22 @@ let SubHeaderElement = class SubHeaderElement extends HTMLElement {
25
41
  }
26
42
  this.classList.remove('SubHeader--expandedSearch');
27
43
  }
44
+ // Waits for condition to return true. If it returns false initially, this function creates a
45
+ // MutationObserver that calls body() whenever the contents of the component change.
46
+ waitForCondition(condition, body) {
47
+ if (condition()) {
48
+ body();
49
+ }
50
+ else {
51
+ const mutationObserver = new MutationObserver(() => {
52
+ if (condition()) {
53
+ body();
54
+ mutationObserver.disconnect();
55
+ }
56
+ });
57
+ mutationObserver.observe(this, { childList: true, subtree: true });
58
+ }
59
+ }
28
60
  };
29
61
  __decorate([
30
62
  target
@@ -2,10 +2,31 @@ import {controller, target, targets} from '@github/catalyst'
2
2
 
3
3
  @controller
4
4
  class SubHeaderElement extends HTMLElement {
5
- @target filterInput: HTMLElement
5
+ @target filterInput: HTMLInputElement
6
6
  @targets hiddenItemsOnExpandedFilter: HTMLElement[]
7
7
  @targets shownItemsOnExpandedFilter: HTMLElement[]
8
8
 
9
+ connectedCallback() {
10
+ this.setupFilterInputClearButton()
11
+ }
12
+
13
+ setupFilterInputClearButton() {
14
+ this.waitForCondition(
15
+ () => Boolean(this.filterInput),
16
+ () => {
17
+ this.toggleFilterInputClearButton()
18
+ },
19
+ )
20
+ }
21
+
22
+ toggleFilterInputClearButton() {
23
+ if (this.filterInput.value.length > 0) {
24
+ this.filterInput.classList.remove('SubHeader-filterInput_hiddenClearButton')
25
+ } else {
26
+ this.filterInput.classList.add('SubHeader-filterInput_hiddenClearButton')
27
+ }
28
+ }
29
+
9
30
  expandFilterInput() {
10
31
  for (const item of this.hiddenItemsOnExpandedFilter) {
11
32
  item.classList.add('d-none')
@@ -31,6 +52,23 @@ class SubHeaderElement extends HTMLElement {
31
52
 
32
53
  this.classList.remove('SubHeader--expandedSearch')
33
54
  }
55
+
56
+ // Waits for condition to return true. If it returns false initially, this function creates a
57
+ // MutationObserver that calls body() whenever the contents of the component change.
58
+ private waitForCondition(condition: () => boolean, body: () => void) {
59
+ if (condition()) {
60
+ body()
61
+ } else {
62
+ const mutationObserver = new MutationObserver(() => {
63
+ if (condition()) {
64
+ body()
65
+ mutationObserver.disconnect()
66
+ }
67
+ })
68
+
69
+ mutationObserver.observe(this, {childList: true, subtree: true})
70
+ }
71
+ }
34
72
  }
35
73
 
36
74
  declare global {
@@ -5,7 +5,7 @@ module Primer
5
5
  module ViewComponents
6
6
  module VERSION
7
7
  MAJOR = 0
8
- MINOR = 45
8
+ MINOR = 46
9
9
  PATCH = 0
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
@@ -11,10 +11,23 @@ module Primer
11
11
  # @param show_filter_input toggle
12
12
  # @param show_filter_button toggle
13
13
  # @param show_action_button toggle
14
+ # @param show_clear_button toggle
14
15
  # @param text text
15
- def playground(show_filter_input: true, show_filter_button: true, show_action_button: true, text: nil)
16
+ # @param value text
17
+ def playground(
18
+ show_filter_input: true,
19
+ show_clear_button: true,
20
+ show_filter_button: true,
21
+ show_action_button: true,
22
+ text: nil,
23
+ value: nil
24
+ )
16
25
  render(Primer::OpenProject::SubHeader.new) do |component|
17
- component.with_filter_input(name: "filter", label: "Filter") if show_filter_input
26
+ component.with_filter_input(
27
+ name: "filter",
28
+ label: "Filter",
29
+ show_clear_button: show_clear_button,
30
+ value: value) if show_filter_input
18
31
  component.with_filter_button do |button|
19
32
  button.with_trailing_visual_counter(count: "15")
20
33
  "Filter"
data/static/classes.json CHANGED
@@ -591,6 +591,9 @@
591
591
  "SubHeader-filterContainer": [
592
592
  "Primer::OpenProject::SubHeader"
593
593
  ],
594
+ "SubHeader-filterInput_hiddenClearButton": [
595
+ "Primer::OpenProject::SubHeader"
596
+ ],
594
597
  "SubHeader-leftPane": [
595
598
  "Primer::OpenProject::SubHeader"
596
599
  ],
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.45.0
4
+ version: 0.46.0
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: 2024-09-09 00:00:00.000000000 Z
12
+ date: 2024-09-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionview