@1024pix/pix-ui 48.8.1 → 49.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/addon/components/{pix-collapsible.hbs → pix-accordions.hbs} +8 -8
  2. package/addon/components/{pix-collapsible.js → pix-accordions.js} +4 -4
  3. package/addon/components/pix-app-layout.hbs +1 -1
  4. package/addon/components/{pix-navigation.js → pix-app-layout.js} +4 -4
  5. package/addon/components/{pix-banner.hbs → pix-banner-alert.hbs} +5 -5
  6. package/addon/components/{pix-banner.js → pix-banner-alert.js} +1 -1
  7. package/addon/components/pix-navigation.hbs +1 -1
  8. package/addon/components/pix-notification-alert.hbs +13 -0
  9. package/addon/components/{pix-message.js → pix-notification-alert.js} +1 -1
  10. package/addon/components/{pix-progress-gauge.hbs → pix-progress-bar.hbs} +4 -4
  11. package/addon/components/{pix-progress-gauge.js → pix-progress-bar.js} +5 -5
  12. package/addon/components/pix-select-list.hbs +86 -0
  13. package/addon/components/pix-select-list.js +42 -0
  14. package/addon/components/pix-select.hbs +15 -87
  15. package/addon/components/pix-select.js +0 -36
  16. package/addon/components/pix-structure-switcher.hbs +40 -0
  17. package/addon/components/pix-structure-switcher.js +57 -0
  18. package/addon/components/{pix-toggle.hbs → pix-toggle-button.hbs} +3 -3
  19. package/addon/components/{pix-toggle.js → pix-toggle-button.js} +4 -4
  20. package/addon/styles/{_pix-collapsible.scss → _pix-accordions.scss} +8 -8
  21. package/addon/styles/_pix-app-layout.scss +22 -1
  22. package/addon/styles/{_pix-banner.scss → _pix-banner-alert.scss} +1 -1
  23. package/addon/styles/_pix-navigation.scss +0 -16
  24. package/addon/styles/{_pix-message.scss → _pix-notification-alert.scss} +6 -6
  25. package/addon/styles/{_pix-progress-gauge.scss → _pix-progress-bar.scss} +24 -24
  26. package/addon/styles/_pix-select-list.scss +75 -0
  27. package/addon/styles/_pix-select.scss +1 -67
  28. package/addon/styles/_pix-structure-switcher.scss +64 -0
  29. package/addon/styles/{_pix-toggle.scss → _pix-toggle-button.scss} +2 -2
  30. package/addon/styles/addon.scss +7 -5
  31. package/app/components/pix-accordions.js +1 -0
  32. package/app/components/pix-banner-alert.js +1 -0
  33. package/app/components/pix-notification-alert.js +1 -0
  34. package/app/components/{pix-progress-gauge.js → pix-progress-bar.js} +1 -1
  35. package/app/components/pix-select-list.js +1 -0
  36. package/app/components/pix-structure-switcher.js +1 -0
  37. package/app/components/pix-toggle-button.js +1 -0
  38. package/package.json +3 -2
  39. package/addon/components/pix-message.hbs +0 -13
  40. package/app/components/pix-banner.js +0 -1
  41. package/app/components/pix-collapsible.js +0 -1
  42. package/app/components/pix-message.js +0 -1
  43. package/app/components/pix-toggle.js +0 -1
@@ -1,18 +1,18 @@
1
- <div class="pix-collapsible">
1
+ <div class="pix-accordions">
2
2
 
3
3
  <button
4
- class="pix-collapsible__title"
4
+ class="pix-accordions__title"
5
5
  type="button"
6
- {{on "click" this.toggleCollapsible}}
6
+ {{on "click" this.toggleAccordions}}
7
7
  aria-controls={{this.contentId}}
8
8
  aria-expanded={{if this.isUnCollapsed "true" "false"}}
9
9
  ...attributes
10
10
  >
11
11
 
12
- <span class="pix-collapsible-title__container">
12
+ <span class="pix-accordions-title__container">
13
13
  {{#if @iconName}}
14
14
  <PixIcon
15
- class="pix-collapsible-title__icon"
15
+ class="pix-accordions-title__icon"
16
16
  @name={{@iconName}}
17
17
  @plainIcon={{@plainIcon}}
18
18
  @ariaHidden={{true}}
@@ -22,14 +22,14 @@
22
22
  {{yield to="title"}}
23
23
  </span>
24
24
 
25
- <span class="pix-collapsible-title__container">
25
+ <span class="pix-accordions-title__container">
26
26
  {{#if @tagContent}}
27
27
  <PixTag @color={{@tagColor}}>
28
28
  {{@tagContent}}
29
29
  </PixTag>
30
30
  {{/if}}
31
31
  <PixIcon
32
- class="pix-collapsible-title-container__toggle-icon"
32
+ class="pix-accordions-title-container__toggle-icon"
33
33
  @ariaHidden={{true}}
34
34
  @name="{{if this.isCollapsed 'chevronBottom' 'chevronTop'}}"
35
35
  />
@@ -38,7 +38,7 @@
38
38
 
39
39
  <div
40
40
  id={{this.contentId}}
41
- class="pix-collapsible__content"
41
+ class="pix-accordions__content"
42
42
  aria-hidden={{if this.isCollapsed "true" "false"}}
43
43
  >
44
44
  {{#if this.isContentRendered}}
@@ -3,9 +3,9 @@ import { tracked } from '@glimmer/tracking';
3
3
  import { action } from '@ember/object';
4
4
  import { guidFor } from '@ember/object/internals';
5
5
 
6
- export default class PixCollapsible extends Component {
7
- text = 'pix-collapsible';
8
- contentId = 'pix-collapsible-' + guidFor(this);
6
+ export default class PixAccordions extends Component {
7
+ text = 'pix-accordions';
8
+ contentId = 'pix-accordions-' + guidFor(this);
9
9
 
10
10
  @tracked isCollapsed = true;
11
11
  @tracked hasUnCollapsedOnce = false;
@@ -19,7 +19,7 @@ export default class PixCollapsible extends Component {
19
19
  }
20
20
 
21
21
  @action
22
- toggleCollapsible() {
22
+ toggleAccordions() {
23
23
  this.isCollapsed = !this.isCollapsed;
24
24
  this.hasUnCollapsedOnce = true;
25
25
  }
@@ -1,3 +1,3 @@
1
- <div class="pix-app-layout">
1
+ <div class={{this.classNames}} ...attributes>
2
2
  {{yield}}
3
3
  </div>
@@ -1,20 +1,20 @@
1
1
  import Component from '@glimmer/component';
2
2
  import { warn } from '@ember/debug';
3
3
 
4
- export default class PixNavigation extends Component {
4
+ export default class PixAppLayout extends Component {
5
5
  get variant() {
6
6
  const value = this.args.variant ?? 'primary';
7
7
  warn(
8
- `PixNavigation: @variant "${value}" should be certif, orga or primary`,
8
+ `PixAppLayout: @variant "${value}" should be certif, orga or primary`,
9
9
  ['primary', 'orga', 'certif'].includes(value),
10
10
  {
11
- id: 'pix-ui.pix-navigation.variant.not-valid',
11
+ id: 'pix-ui.pix-app-layout.variant.not-valid',
12
12
  },
13
13
  );
14
14
 
15
15
  return value;
16
16
  }
17
17
  get classNames() {
18
- return ['pix-navigation', `pix-navigation--${this.variant}`].join(' ');
18
+ return ['pix-app-layout', `pix-app-layout--${this.variant}`].join(' ');
19
19
  }
20
20
  }
@@ -1,17 +1,17 @@
1
1
  {{#if this.displayBanner}}
2
- <div class="pix-banner pix-banner--{{this.type}}" role="alert" ...attributes>
2
+ <div class="pix-banner-alert pix-banner-alert--{{this.type}}" role="alert" ...attributes>
3
3
  <PixIcon
4
4
  @name={{this.icon}}
5
5
  @plainIcon={{true}}
6
6
  @ariaHidden={{true}}
7
- class="pix-banner__icon"
7
+ class="pix-banner-alert__icon"
8
8
  />
9
9
  <div>
10
10
  {{yield}}
11
11
  {{#if this.displayAction}}
12
12
  {{#if this.isExternalLink}}
13
13
  <a
14
- class="pix-banner__action"
14
+ class="pix-banner-alert__action"
15
15
  href={{@actionUrl}}
16
16
  target="_blank"
17
17
  rel="noopener noreferrer"
@@ -20,12 +20,12 @@
20
20
  <PixIcon @name="openNew" class="external-link" />
21
21
  </a>
22
22
  {{else}}
23
- <LinkTo class="pix-banner__action" @route={{@actionUrl}}>{{@actionLabel}}</LinkTo>
23
+ <LinkTo class="pix-banner-alert__action" @route={{@actionUrl}}>{{@actionLabel}}</LinkTo>
24
24
  {{/if}}
25
25
  {{/if}}
26
26
  </div>
27
27
  {{#if this.canCloseBanner}}
28
- <div class="pix-banner__close">
28
+ <div class="pix-banner-alert__close">
29
29
  <PixIconButton
30
30
  @ariaLabel="Fermer"
31
31
  @iconName="close"
@@ -26,7 +26,7 @@ const icons = {
26
26
  [TYPE_COMMUNICATION_CERTIF]: 'campaign',
27
27
  };
28
28
 
29
- export default class PixBanner extends Component {
29
+ export default class PixBannerAlert extends Component {
30
30
  @tracked isBannerVisible = true;
31
31
  get type() {
32
32
  return types.includes(this.args.type) ? this.args.type : TYPE_INFO;
@@ -1,4 +1,4 @@
1
- <aside ...attributes class={{this.classNames}}>
1
+ <aside ...attributes class="pix-navigation">
2
2
  <header class="pix-navigation__brand">{{yield to="brand"}}</header>
3
3
  <nav class="pix-navigation__nav" aria-label={{@navigationAriaLabel}}>{{yield
4
4
  to="navElements"
@@ -0,0 +1,13 @@
1
+ <p class="pix-notification-alert {{concat 'pix-notification-alert--' this.type}}" ...attributes>
2
+ {{#if @withIcon}}
3
+ <PixIcon
4
+ @name={{this.iconName}}
5
+ @ariaHidden={{true}}
6
+ @plainIcon={{true}}
7
+ class="pix-notification-alert__icon"
8
+ />
9
+ {{/if}}
10
+ <span class="pix-notification-alert__content">
11
+ {{yield}}
12
+ </span>
13
+ </p>
@@ -5,7 +5,7 @@ const TYPE_SUCCESS = 'success';
5
5
  const TYPE_WARNING = 'warning';
6
6
  const TYPE_ERROR = 'error';
7
7
 
8
- export default class PixMessage extends Component {
8
+ export default class PixNotificationAlert extends Component {
9
9
  get type() {
10
10
  const correctTypes = [TYPE_INFO, TYPE_SUCCESS, TYPE_WARNING, TYPE_ERROR];
11
11
 
@@ -1,19 +1,19 @@
1
1
  <div
2
- class="progress-gauge {{this.themeMode}} {{this.colorClass}}"
2
+ class="progress-bar {{this.themeMode}} {{this.colorClass}}"
3
3
  aria-hidden={{if @isDecorative "true"}}
4
4
  ...attributes
5
5
  >
6
6
  {{#unless @hidePercentage}}
7
- <div class="progress-gauge__text" role="presentation">{{this.percentageValue}}</div>
7
+ <div class="progress-bar__text" role="presentation">{{this.percentageValue}}</div>
8
8
  {{/unless}}
9
9
  <label for={{this.id}} class="screen-reader-only">{{@label}}</label>
10
10
  <progress
11
- class="progress-gauge__bar"
11
+ class="progress-bar__bar"
12
12
  id={{this.id}}
13
13
  max="100"
14
14
  value={{this.value}}
15
15
  >{{this.value}}%</progress>
16
16
  {{#if @subtitle}}
17
- <p class="progress-gauge__sub-title">{{@subtitle}}</p>
17
+ <p class="progress-bar__sub-title">{{@subtitle}}</p>
18
18
  {{/if}}
19
19
  </div>
@@ -1,7 +1,7 @@
1
1
  import Component from '@glimmer/component';
2
2
  import { guidFor } from '@ember/object/internals';
3
3
 
4
- export default class PixProgressGauge extends Component {
4
+ export default class PixProgressBar extends Component {
5
5
  get id() {
6
6
  return guidFor(this);
7
7
  }
@@ -10,7 +10,7 @@ export default class PixProgressGauge extends Component {
10
10
  if (Number(this.args.value) <= 0) return 0;
11
11
  if (Number(this.args.value) > 100) return 100;
12
12
  if (!this.args.value) {
13
- throw new Error('ERROR in PixProgressGauge component, @value param is not provided.');
13
+ throw new Error('ERROR in PixProgressBar component, @value param is not provided.');
14
14
  }
15
15
  return Number(this.args.value);
16
16
  }
@@ -23,7 +23,7 @@ export default class PixProgressGauge extends Component {
23
23
  const thereIsNoLabel = !this.args.label || !this.args.label.trim();
24
24
 
25
25
  if (thereIsNoLabel && !this.args.isDecorative) {
26
- throw new Error('ERROR in PixProgressGauge component, @label param is not provided.');
26
+ throw new Error('ERROR in PixProgressBar component, @label param is not provided.');
27
27
  }
28
28
  return this.args.label;
29
29
  }
@@ -36,7 +36,7 @@ export default class PixProgressGauge extends Component {
36
36
  ? this.args.themeMode
37
37
  : 'light';
38
38
 
39
- return `progress-gauge--theme-${themeMode}`;
39
+ return `progress-bar--theme-${themeMode}`;
40
40
  }
41
41
 
42
42
  get colorClass() {
@@ -53,6 +53,6 @@ export default class PixProgressGauge extends Component {
53
53
  const color =
54
54
  this.args.color && availableColor.includes(this.args.color) ? this.args.color : 'primary';
55
55
 
56
- return `progress-gauge--content-${color}`;
56
+ return `progress-bar--content-${color}`;
57
57
  }
58
58
  }
@@ -0,0 +1,86 @@
1
+ <ul role="listbox" id={{@listId}} class="pix-select_list" ...attributes>
2
+ <li
3
+ class="pix-select-list-category__option{{unless
4
+ @value
5
+ ' pix-select-list-category__option--selected'
6
+ }}{{unless @displayDefaultOption ' pix-select-list-category__option--hidden'}}"
7
+ role="option"
8
+ tabindex={{if this.isDefaultOptionHidden "-1" "0"}}
9
+ aria-selected={{if @value "false" "true"}}
10
+ {{on "click" (fn @onChange @defaultOption)}}
11
+ {{on-enter-action (fn @onChange @defaultOption)}}
12
+ {{on-space-action (fn @onChange @defaultOption)}}
13
+ >
14
+ {{@defaultOptionValue}}
15
+ </li>
16
+ {{#if this.results}}
17
+ {{#if this.displayCategory}}
18
+ {{#each this.results as |element index|}}
19
+ <ul
20
+ class="pix-select-list-category"
21
+ role="group"
22
+ aria-labelledby={{if this.displayCategory (concat "cat-" @selectId "-" index)}}
23
+ >
24
+ {{#if this.displayCategory}}
25
+ <li
26
+ class="pix-select-list-category__name"
27
+ role="presentation"
28
+ id={{concat "cat-" @selectId "-" index}}
29
+ title={{element.label}}
30
+ >
31
+ {{element.category}}
32
+ </li>
33
+ {{/if}}
34
+
35
+ {{#each element.options as |option|}}
36
+ {{! template-lint-disable require-context-role }}
37
+ {{!https://www.w3.org/WAI/ARIA/apg/example-index/listbox/listbox-grouped.html}}
38
+ <li
39
+ class="pix-select-list-category__option{{if
40
+ (eq option.value @value)
41
+ ' pix-select-list-category__option--selected'
42
+ }}"
43
+ role="option"
44
+ tabindex={{if @isExpanded "0" "-1"}}
45
+ title={{option.label}}
46
+ aria-selected={{if (eq option.value @value) "true" "false"}}
47
+ {{on "click" (fn @onChange option)}}
48
+ {{on-enter-action (fn @onChange option)}}
49
+ {{on-space-action (fn @onChange option)}}
50
+ >
51
+ {{option.label}}
52
+
53
+ {{#if (eq option.value @value)}}
54
+ <PixIcon @name="check" role="presentation" />
55
+ {{/if}}
56
+ </li>
57
+ {{/each}}
58
+ </ul>
59
+ {{/each}}
60
+ {{else}}
61
+ {{#each this.results as |option|}}
62
+ <li
63
+ class="pix-select-list-category__option{{if
64
+ (eq option.value @value)
65
+ ' pix-select-list-category__option--selected'
66
+ }}"
67
+ role="option"
68
+ tabindex={{if @isExpanded "0" "-1"}}
69
+ aria-selected={{if (eq option.value @value) "true" "false"}}
70
+ title={{option.label}}
71
+ {{on "click" (fn @onChange option)}}
72
+ {{on-enter-action (fn @onChange option)}}
73
+ {{on-space-action (fn @onChange option)}}
74
+ >
75
+ {{option.label}}
76
+
77
+ {{#if (eq option.value @value)}}
78
+ <PixIcon @name="check" role="presentation" />
79
+ {{/if}}
80
+ </li>
81
+ {{/each}}
82
+ {{/if}}
83
+ {{else}}
84
+ <li class="pix-select-list__empty-search-message">{{@emptySearchMessage}}</li>
85
+ {{/if}}
86
+ </ul>
@@ -0,0 +1,42 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ export default class PixSelectList extends Component {
4
+ constructor(...args) {
5
+ super(...args);
6
+
7
+ const categories = [];
8
+
9
+ this.args.options.forEach((element) => {
10
+ if (!categories.includes(element.category) && element.category !== undefined) {
11
+ categories.push(element.category);
12
+ }
13
+ });
14
+ this.displayCategory = categories.length > 0;
15
+ }
16
+
17
+ get isDefaultOptionHidden() {
18
+ return !this.args.isExpanded || this.args.hideDefaultOption;
19
+ }
20
+ get results() {
21
+ let results = [];
22
+ let options = this.args.options;
23
+
24
+ if (this.args.searchValue) {
25
+ options = this.args.options.filter((option) =>
26
+ option.label.toLowerCase().includes(this.args.searchValue.toLowerCase()),
27
+ );
28
+ }
29
+
30
+ if (!this.displayCategory) return options;
31
+
32
+ options.forEach(({ category, value, label }) => {
33
+ const categoryIndex = results.findIndex((result) => result.category === category);
34
+ if (categoryIndex !== -1) {
35
+ results[categoryIndex].options.push({ value, label });
36
+ } else {
37
+ results.push({ category, options: [{ label, value }] });
38
+ }
39
+ });
40
+ return results;
41
+ }
42
+ }
@@ -51,7 +51,7 @@
51
51
  </button>
52
52
  <div
53
53
  {{popover}}
54
- class="pix-select__dropdown{{unless this.isExpanded ' pix-select__dropdown--closed'}}"
54
+ class="pix-select__dropdown {{unless this.isExpanded ' pix-select__dropdown--closed'}}"
55
55
  {{on "transitionend" this.focus}}
56
56
  >
57
57
  {{#if @isSearchable}}
@@ -68,92 +68,20 @@
68
68
  />
69
69
  </div>
70
70
  {{/if}}
71
- <ul role="listbox" id={{this.listId}} class="pix-select__options">
72
- <li
73
- class="pix-select-options-category__option{{unless
74
- @value
75
- ' pix-select-options-category__option--selected'
76
- }}{{unless this.displayDefaultOption ' pix-select-options-category__option--hidden'}}"
77
- role="option"
78
- tabindex={{if this.isDefaultOptionHidden "-1" "0"}}
79
- aria-selected={{if @value "false" "true"}}
80
- {{on "click" (fn this.onChange this.defaultOption)}}
81
- {{on-enter-action (fn this.onChange this.defaultOption)}}
82
- {{on-space-action (fn this.onChange this.defaultOption)}}
83
- >
84
- {{@placeholder}}
85
- </li>
86
- {{#if this.results}}
87
- {{#if this.displayCategory}}
88
- {{#each this.results as |element index|}}
89
- <ul
90
- class="pix-select-options__category"
91
- role="group"
92
- aria-labelledby={{if
93
- this.displayCategory
94
- (concat "cat-" this.selectId "-" index)
95
- }}
96
- >
97
- {{#if this.displayCategory}}
98
- <li
99
- class="pix-select-options-category__name"
100
- role="presentation"
101
- id={{concat "cat-" this.selectId "-" index}}
102
- >
103
- {{element.category}}
104
- </li>
105
- {{/if}}
106
-
107
- {{#each element.options as |option|}}
108
- {{! template-lint-disable require-context-role }}
109
- {{!https://www.w3.org/WAI/ARIA/apg/example-index/listbox/listbox-grouped.html}}
110
- <li
111
- class="pix-select-options-category__option{{if
112
- (eq option.value @value)
113
- ' pix-select-options-category__option--selected'
114
- }}"
115
- role="option"
116
- tabindex={{if this.isExpanded "0" "-1"}}
117
- aria-selected={{if (eq option.value @value) "true" "false"}}
118
- {{on "click" (fn this.onChange option)}}
119
- {{on-enter-action (fn this.onChange option)}}
120
- {{on-space-action (fn this.onChange option)}}
121
- >
122
- {{option.label}}
123
-
124
- {{#if (eq option.value @value)}}
125
- <PixIcon @name="check" role="presentation" />
126
- {{/if}}
127
- </li>
128
- {{/each}}
129
- </ul>
130
- {{/each}}
131
- {{else}}
132
- {{#each this.results as |option|}}
133
- <li
134
- class="pix-select-options-category__option{{if
135
- (eq option.value @value)
136
- ' pix-select-options-category__option--selected'
137
- }}"
138
- role="option"
139
- tabindex={{if this.isExpanded "0" "-1"}}
140
- aria-selected={{if (eq option.value @value) "true" "false"}}
141
- {{on "click" (fn this.onChange option)}}
142
- {{on-enter-action (fn this.onChange option)}}
143
- {{on-space-action (fn this.onChange this.defaultOption)}}
144
- >
145
- {{option.label}}
146
-
147
- {{#if (eq option.value @value)}}
148
- <PixIcon @name="check" role="presentation" />
149
- {{/if}}
150
- </li>
151
- {{/each}}
152
- {{/if}}
153
- {{else}}
154
- <li class="pix-select__empty-search-message">{{@emptySearchMessage}}</li>
155
- {{/if}}
156
- </ul>
71
+ <PixSelectList
72
+ @hideDefaultOption={{@hideDefaultOption}}
73
+ @listId={{this.listId}}
74
+ @value={{@value}}
75
+ @displayDefaultOption={{this.displayDefaultOption}}
76
+ @searchValue={{this.searchValue}}
77
+ @onChange={{this.onChange}}
78
+ @defaultOption={{this.defaultOption}}
79
+ @selectId={{this.selectId}}
80
+ @isExpanded={{this.isExpanded}}
81
+ @options={{@options}}
82
+ @defaultOptionValue={{@placeholder}}
83
+ @emptySearchMessage={{@emptySearchMessage}}
84
+ />
157
85
  </div>
158
86
  </PopperJS>
159
87
  {{#if @errorMessage}}
@@ -12,19 +12,10 @@ export default class PixSelect extends Component {
12
12
  constructor(...args) {
13
13
  super(...args);
14
14
 
15
- const categories = [];
16
-
17
15
  this.searchId = 'search-input-' + guidFor(this);
18
16
  this.selectId = this.args.id ? this.args.id : 'select-' + guidFor(this);
19
17
  this.listId = `listbox-${this.selectId}`;
20
18
 
21
- this.args.options.forEach((element) => {
22
- if (!categories.includes(element.category) && element.category !== undefined) {
23
- categories.push(element.category);
24
- }
25
- });
26
- this.displayCategory = categories.length > 0;
27
-
28
19
  if (!this.args.isComputeWidthDisabled) {
29
20
  this.elementHelper.waitForElement(this.listId).then((elementList) => {
30
21
  const baseFontRemRatio = Number(
@@ -43,10 +34,6 @@ export default class PixSelect extends Component {
43
34
  return !this.searchValue && !this.args.hideDefaultOption;
44
35
  }
45
36
 
46
- get isDefaultOptionHidden() {
47
- return !this.isExpanded || this.args.hideDefaultOption;
48
- }
49
-
50
37
  get className() {
51
38
  const classes = ['pix-select-button'];
52
39
  if (this.args.className) {
@@ -75,29 +62,6 @@ export default class PixSelect extends Component {
75
62
  };
76
63
  }
77
64
 
78
- get results() {
79
- let results = [];
80
- let options = this.args.options;
81
-
82
- if (this.searchValue) {
83
- options = this.args.options.filter((option) =>
84
- option.label.toLowerCase().includes(this.searchValue.toLowerCase()),
85
- );
86
- }
87
-
88
- if (!this.displayCategory) return options;
89
-
90
- options.forEach(({ category, value, label }) => {
91
- const categoryIndex = results.findIndex((result) => result.category === category);
92
- if (categoryIndex !== -1) {
93
- results[categoryIndex].options.push({ value, label });
94
- } else {
95
- results.push({ category, options: [{ label, value }] });
96
- }
97
- });
98
- return results;
99
- }
100
-
101
65
  @action
102
66
  toggleDropdown(event) {
103
67
  if (this.isExpanded) {
@@ -0,0 +1,40 @@
1
+ <div
2
+ id="container-{{this.switcherId}}"
3
+ class="pix-structure-switcher"
4
+ {{on-click-outside this.closeMenu}}
5
+ {{on-arrow-down-up-action this.listId this.openMenu this.isMenuOpen}}
6
+ {{on-escape-action this.closeMenu this.switcherId}}
7
+ {{on "keydown" this.lockTab}}
8
+ ...attributes
9
+ >
10
+ <PopperJS @placement="right-end" as |reference popover|>
11
+
12
+ <PixButton
13
+ {{reference}}
14
+ @size="small"
15
+ @variant="secondary"
16
+ aria-controls={{this.listId}}
17
+ id={{this.switcherId}}
18
+ @triggerAction={{this.toggleMenu}}
19
+ aria-expanded={{this.isMenuOpen}}
20
+ >{{@label}}</PixButton>
21
+ <div
22
+ {{popover}}
23
+ class="pix-select__dropdown {{unless this.isMenuOpen 'pix-select__dropdown--closed'}}"
24
+ >
25
+ <PixSelectList
26
+ aria-labelledby={{this.switcherId}}
27
+ {{on "transitionend" this.focus}}
28
+ @hideDefaultOption={{true}}
29
+ @listId={{this.listId}}
30
+ @selectId={{this.switcherId}}
31
+ @value={{@value}}
32
+ @onChange={{this.onSelectListChange}}
33
+ @defaultOption={{@defaultOption}}
34
+ @isExpanded={{this.isMenuOpen}}
35
+ @options={{@structures}}
36
+ @defaultOptionValue={{@label}}
37
+ />
38
+ </div>
39
+ </PopperJS>
40
+ </div>
@@ -0,0 +1,57 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { action } from '@ember/object';
4
+ import { guidFor } from '@ember/object/internals';
5
+ import { inject as service } from '@ember/service';
6
+
7
+ export default class PixStructureSwitcher extends Component {
8
+ @service elementHelper;
9
+
10
+ constructor(...args) {
11
+ super(...args);
12
+ this.switcherId = 'structure-switcher-' + guidFor(this);
13
+ this.listId = `listbox-${this.switcherId}`;
14
+ this.elementHelper.waitForElement(`container-${this.switcherId}`).then((element) => {
15
+ this.rootElement = element;
16
+ });
17
+ }
18
+
19
+ @tracked
20
+ isMenuOpen = false;
21
+
22
+ @action
23
+ toggleMenu() {
24
+ this.isMenuOpen = !this.isMenuOpen;
25
+ }
26
+
27
+ @action
28
+ onSelectListChange(structure, event) {
29
+ this.args.onChange(structure);
30
+ this.closeMenu(event);
31
+ document.getElementById(this.switcherId).focus();
32
+ }
33
+
34
+ @action
35
+ openMenu(event) {
36
+ event.preventDefault();
37
+ this.isMenuOpen = true;
38
+ }
39
+
40
+ @action
41
+ closeMenu(event) {
42
+ event.preventDefault();
43
+ this.isMenuOpen = false;
44
+ }
45
+
46
+ @action
47
+ lockTab(event) {
48
+ if (event.code === 'Tab' && this.isMenuOpen) {
49
+ event.preventDefault();
50
+ }
51
+ }
52
+
53
+ @action
54
+ focus() {
55
+ document.getElementById(this.listId).querySelector("[aria-selected='true']").focus();
56
+ }
57
+ }