@1024pix/pix-ui 11.1.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 (196) hide show
  1. package/.buildpacks +2 -0
  2. package/.circleci/config.yml +22 -0
  3. package/.gitattributes +7 -0
  4. package/.github/workflows/auto-merge.yml +26 -0
  5. package/.github/workflows/deploy-storybook.yml +21 -0
  6. package/.github/workflows/npm-publish.yml +23 -0
  7. package/.github/workflows/on-dev-merge.yml +33 -0
  8. package/.nvmrc +1 -0
  9. package/.prettierignore +1 -0
  10. package/.prettierrc.json +12 -0
  11. package/.storybook/fonts.css +1 -0
  12. package/.storybook/main.js +10 -0
  13. package/.storybook/manager.js +6 -0
  14. package/.storybook/preview.js +37 -0
  15. package/.storybook/storybook-custom-theme.js +37 -0
  16. package/CHANGELOG.md +469 -0
  17. package/CNAME +1 -0
  18. package/LICENSE.md +9 -0
  19. package/README.md +58 -0
  20. package/addon/components/pix-background-header.hbs +7 -0
  21. package/addon/components/pix-background-header.js +5 -0
  22. package/addon/components/pix-banner.hbs +16 -0
  23. package/addon/components/pix-banner.js +43 -0
  24. package/addon/components/pix-block.hbs +5 -0
  25. package/addon/components/pix-block.js +11 -0
  26. package/addon/components/pix-button-base.js +27 -0
  27. package/addon/components/pix-button-link.hbs +16 -0
  28. package/addon/components/pix-button-link.js +10 -0
  29. package/addon/components/pix-button-upload.hbs +11 -0
  30. package/addon/components/pix-button-upload.js +20 -0
  31. package/addon/components/pix-button.hbs +43 -0
  32. package/addon/components/pix-button.js +54 -0
  33. package/addon/components/pix-collapsible.hbs +29 -0
  34. package/addon/components/pix-collapsible.js +27 -0
  35. package/addon/components/pix-filter-banner.hbs +28 -0
  36. package/addon/components/pix-filter-banner.js +13 -0
  37. package/addon/components/pix-icon-button.hbs +11 -0
  38. package/addon/components/pix-icon-button.js +33 -0
  39. package/addon/components/pix-input-code.hbs +24 -0
  40. package/addon/components/pix-input-code.js +133 -0
  41. package/addon/components/pix-input-password.hbs +43 -0
  42. package/addon/components/pix-input-password.js +34 -0
  43. package/addon/components/pix-input.hbs +30 -0
  44. package/addon/components/pix-input.js +26 -0
  45. package/addon/components/pix-message.hbs +8 -0
  46. package/addon/components/pix-message.js +30 -0
  47. package/addon/components/pix-multi-select.hbs +70 -0
  48. package/addon/components/pix-multi-select.js +162 -0
  49. package/addon/components/pix-progress-gauge.hbs +19 -0
  50. package/addon/components/pix-progress-gauge.js +29 -0
  51. package/addon/components/pix-radio-button.hbs +12 -0
  52. package/addon/components/pix-radio-button.js +5 -0
  53. package/addon/components/pix-return-to.hbs +15 -0
  54. package/addon/components/pix-return-to.js +20 -0
  55. package/addon/components/pix-select.hbs +55 -0
  56. package/addon/components/pix-select.js +58 -0
  57. package/addon/components/pix-selectable-tag.hbs +10 -0
  58. package/addon/components/pix-selectable-tag.js +13 -0
  59. package/addon/components/pix-stars.hbs +16 -0
  60. package/addon/components/pix-stars.js +27 -0
  61. package/addon/components/pix-tag.hbs +3 -0
  62. package/addon/components/pix-tag.js +11 -0
  63. package/addon/components/pix-textarea.hbs +21 -0
  64. package/addon/components/pix-textarea.js +17 -0
  65. package/addon/components/pix-tooltip-deprecated.hbs +18 -0
  66. package/addon/components/pix-tooltip-deprecated.js +26 -0
  67. package/addon/components/pix-tooltip.hbs +18 -0
  68. package/addon/components/pix-tooltip.js +17 -0
  69. package/addon/styles/_breakpoints.scss +17 -0
  70. package/addon/styles/_colors.scss +87 -0
  71. package/addon/styles/_fonts.scss +10 -0
  72. package/addon/styles/_form.scss +68 -0
  73. package/addon/styles/_pix-background-header.scss +20 -0
  74. package/addon/styles/_pix-banner.scss +67 -0
  75. package/addon/styles/_pix-block.scss +29 -0
  76. package/addon/styles/_pix-button-base.scss +137 -0
  77. package/addon/styles/_pix-button-link.scss +4 -0
  78. package/addon/styles/_pix-button-upload.scss +5 -0
  79. package/addon/styles/_pix-button.scss +40 -0
  80. package/addon/styles/_pix-collapsible.scss +82 -0
  81. package/addon/styles/_pix-filter-banner.scss +74 -0
  82. package/addon/styles/_pix-icon-button.scss +60 -0
  83. package/addon/styles/_pix-input-code.scss +71 -0
  84. package/addon/styles/_pix-input-password.scss +68 -0
  85. package/addon/styles/_pix-input.scss +93 -0
  86. package/addon/styles/_pix-message.scss +35 -0
  87. package/addon/styles/_pix-multi-select.scss +182 -0
  88. package/addon/styles/_pix-progress-gauge.scss +119 -0
  89. package/addon/styles/_pix-radio-button.scss +72 -0
  90. package/addon/styles/_pix-return-to.scss +64 -0
  91. package/addon/styles/_pix-select.scss +71 -0
  92. package/addon/styles/_pix-selectable-tag.scss +86 -0
  93. package/addon/styles/_pix-stars.scss +43 -0
  94. package/addon/styles/_pix-tag.scss +69 -0
  95. package/addon/styles/_pix-textarea.scss +39 -0
  96. package/addon/styles/_pix-tooltip.scss +196 -0
  97. package/addon/styles/_reset-css.scss +36 -0
  98. package/addon/styles/_spacing.scss +9 -0
  99. package/addon/styles/addon.scss +41 -0
  100. package/app/components/pix-background-header.js +1 -0
  101. package/app/components/pix-banner.js +1 -0
  102. package/app/components/pix-block.js +1 -0
  103. package/app/components/pix-button-link.js +1 -0
  104. package/app/components/pix-button-upload.js +1 -0
  105. package/app/components/pix-button.js +1 -0
  106. package/app/components/pix-collapsible.js +1 -0
  107. package/app/components/pix-filter-banner.js +1 -0
  108. package/app/components/pix-icon-button.js +1 -0
  109. package/app/components/pix-input-code.js +1 -0
  110. package/app/components/pix-input-password.js +1 -0
  111. package/app/components/pix-input.js +1 -0
  112. package/app/components/pix-message.js +1 -0
  113. package/app/components/pix-multi-select.js +1 -0
  114. package/app/components/pix-progress-gauge.js +1 -0
  115. package/app/components/pix-radio-button.js +1 -0
  116. package/app/components/pix-return-to.js +1 -0
  117. package/app/components/pix-select.js +1 -0
  118. package/app/components/pix-selectable-tag.js +1 -0
  119. package/app/components/pix-stars.js +1 -0
  120. package/app/components/pix-tag.js +1 -0
  121. package/app/components/pix-textarea.js +1 -0
  122. package/app/components/pix-tooltip-deprecated.js +1 -0
  123. package/app/components/pix-tooltip.js +1 -0
  124. package/app/stories/form.stories.js +91 -0
  125. package/app/stories/form.stories.mdx +16 -0
  126. package/app/stories/pix-background-header.stories.js +19 -0
  127. package/app/stories/pix-background-header.stories.mdx +36 -0
  128. package/app/stories/pix-banner.stories.js +89 -0
  129. package/app/stories/pix-banner.stories.mdx +107 -0
  130. package/app/stories/pix-block.stories.js +20 -0
  131. package/app/stories/pix-block.stories.mdx +44 -0
  132. package/app/stories/pix-button-link.stories.js +125 -0
  133. package/app/stories/pix-button-link.stories.mdx +57 -0
  134. package/app/stories/pix-button-upload.stories.js +85 -0
  135. package/app/stories/pix-button-upload.stories.mdx +39 -0
  136. package/app/stories/pix-button.stories.js +253 -0
  137. package/app/stories/pix-button.stories.mdx +99 -0
  138. package/app/stories/pix-collapsible.stories.js +56 -0
  139. package/app/stories/pix-collapsible.stories.mdx +39 -0
  140. package/app/stories/pix-filter-banner.stories.js +51 -0
  141. package/app/stories/pix-filter-banner.stories.mdx +33 -0
  142. package/app/stories/pix-icon-button.stories.js +95 -0
  143. package/app/stories/pix-icon-button.stories.mdx +90 -0
  144. package/app/stories/pix-input-code.stories.js +74 -0
  145. package/app/stories/pix-input-code.stories.mdx +46 -0
  146. package/app/stories/pix-input-password.stories.js +89 -0
  147. package/app/stories/pix-input-password.stories.mdx +69 -0
  148. package/app/stories/pix-input.stories.js +94 -0
  149. package/app/stories/pix-input.stories.mdx +57 -0
  150. package/app/stories/pix-message.stories.js +57 -0
  151. package/app/stories/pix-message.stories.mdx +71 -0
  152. package/app/stories/pix-multi-select.stories.js +199 -0
  153. package/app/stories/pix-multi-select.stories.mdx +55 -0
  154. package/app/stories/pix-progress-gauge.stories.js +78 -0
  155. package/app/stories/pix-progress-gauge.stories.mdx +43 -0
  156. package/app/stories/pix-radio-button.stories.js +71 -0
  157. package/app/stories/pix-radio-button.stories.mdx +49 -0
  158. package/app/stories/pix-return-to.stories.js +45 -0
  159. package/app/stories/pix-return-to.stories.mdx +41 -0
  160. package/app/stories/pix-select.stories.js +140 -0
  161. package/app/stories/pix-select.stories.mdx +57 -0
  162. package/app/stories/pix-selectable-tag.stories.js +91 -0
  163. package/app/stories/pix-selectable-tag.stories.mdx +55 -0
  164. package/app/stories/pix-stars.stories.js +43 -0
  165. package/app/stories/pix-stars.stories.mdx +35 -0
  166. package/app/stories/pix-tag.stories.js +56 -0
  167. package/app/stories/pix-tag.stories.mdx +46 -0
  168. package/app/stories/pix-textarea.stories.js +59 -0
  169. package/app/stories/pix-textarea.stories.mdx +36 -0
  170. package/app/stories/pix-tooltip-deprecated.stories.js +136 -0
  171. package/app/stories/pix-tooltip-deprecated.stories.mdx +143 -0
  172. package/app/stories/pix-tooltip.stories.js +157 -0
  173. package/app/stories/pix-tooltip.stories.mdx +183 -0
  174. package/app/styles/app.scss +0 -0
  175. package/config/environment.js +5 -0
  176. package/docs/architecture.stories.mdx +106 -0
  177. package/docs/assets/accessibility-storybook.png +0 -0
  178. package/docs/assets/screen-pix-storybook.png +0 -0
  179. package/docs/breaking-changes.stories.mdx +90 -0
  180. package/docs/changelog.stories.mdx +6 -0
  181. package/docs/create-component.stories.mdx +118 -0
  182. package/docs/design-system.stories.mdx +20 -0
  183. package/docs/good-practices-a11y.stories.mdx +48 -0
  184. package/docs/good-practices-design.stories.mdx +71 -0
  185. package/docs/good-practices-responsive.stories.mdx +51 -0
  186. package/docs/good-practices-style-css.stories.mdx +40 -0
  187. package/docs/good-practices-tests.stories.mdx +9 -0
  188. package/docs/make-a-release.stories.mdx +66 -0
  189. package/docs/pull_request_template.md +14 -0
  190. package/docs/storybook.stories.mdx +44 -0
  191. package/docs/use-component.stories.mdx +89 -0
  192. package/docs/use-install.stories.mdx +37 -0
  193. package/index.js +5 -0
  194. package/package.json +121 -0
  195. package/scalingo.json +17 -0
  196. package/servers.conf.erb +30 -0
@@ -0,0 +1,70 @@
1
+ <div class="pix-multi-select" ...attributes {{on-click-outside this.hideDropDown capture=true}}>
2
+
3
+ {{#if this.label}}
4
+ <label for={{@id}} class="pix-multi-select__label">{{this.label}}</label>
5
+ {{/if}}
6
+
7
+ {{#if @isSearchable}}
8
+ <label class="pix-multi-select-header {{if this.isBig "pix-multi-select-header--big"}}">
9
+
10
+ <span class="pix-multi-select-header__title">{{@title}}</span>
11
+ <FaIcon @icon="search" class="pix-multi-select-header__search-icon" />
12
+
13
+ <input
14
+ id={{@id}}
15
+ type="text"
16
+ name={{@id}}
17
+ placeholder={{this.placeholder}}
18
+ autocomplete="off"
19
+ {{on "input" this.updateSearch}}
20
+ {{on "focus" this.focusDropdown}}
21
+ class="pix-multi-select-header__search-input"
22
+ />
23
+
24
+ </label>
25
+ {{else}}
26
+ <button
27
+ id={{@id}}
28
+ type="button"
29
+ class="pix-multi-select-header {{if this.isBig "pix-multi-select-header--big"}}"
30
+ {{on "click" this.toggleDropDown}}
31
+ >
32
+ {{@title}}
33
+ <FaIcon
34
+ class="pix-multi-select-header__dropdown-icon
35
+ {{if this.isExpanded " pix-multi-select-header__dropdown-icon--expand"}}"
36
+ @icon={{if this.isExpanded "chevron-up" "chevron-down"}}
37
+ />
38
+ </button>
39
+ {{/if}}
40
+
41
+ <ul class="pix-multi-select-list {{unless this.isExpanded "pix-multi-select-list--hidden"}}">
42
+ {{#if (gt this.results.length 0)}}
43
+ {{#each this.results as |option|}}
44
+ <li class="pix-multi-select-list__item">
45
+ <input
46
+ class="pix-multi-select-list__checkbox
47
+ {{if @isSearchable " pix-multi-select-list__checkbox--searchable"}}"
48
+ type="checkbox"
49
+ checked={{option.checked}}
50
+ id={{concat @id "-" option.value}}
51
+ name={{option.label}}
52
+ value={{option.value}}
53
+ {{on "change" this.onSelect}}
54
+ />
55
+ <label for={{concat @id "-" option.value}}>
56
+ {{yield option}}
57
+ </label>
58
+ </li>
59
+ {{/each}}
60
+ {{else if this.isLoadingOptions}}
61
+ <li
62
+ class="pix-multi-select-list__item pix-multi-select-list__item--no-result"
63
+ >{{@loadingMessage}}</li>
64
+ {{else}}
65
+ <li
66
+ class="pix-multi-select-list__item pix-multi-select-list__item--no-result"
67
+ >{{@emptyMessage}}</li>
68
+ {{/if}}
69
+ </ul>
70
+ </div>
@@ -0,0 +1,162 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ import { action } from '@ember/object';
4
+ import { tracked } from '@glimmer/tracking';
5
+
6
+ function sortOptionsByCheckedFirst(a, b) {
7
+ if (a.checked && b.checked) return 0;
8
+ if (a.checked) return -1;
9
+ if (b.checked) return 1;
10
+ return 0;
11
+ }
12
+
13
+ function removeCapitalizeAndDiacritics(string) {
14
+ return string
15
+ .normalize('NFD')
16
+ .replace(/[\u0300-\u036f]/g, '')
17
+ .toLowerCase();
18
+ }
19
+
20
+ export default class PixMultiSelect extends Component {
21
+ @tracked isExpanded = false;
22
+ @tracked searchData;
23
+
24
+ @tracked options = [];
25
+ @tracked isLoadingOptions = false;
26
+
27
+ constructor(...args) {
28
+ super(...args);
29
+ const { onLoadOptions, selected } = this.args;
30
+
31
+ if (onLoadOptions) {
32
+ this.isLoadingOptions = true;
33
+ onLoadOptions().then((options = []) => {
34
+ this.options = options;
35
+ this._setDisplayedOptions(selected, true);
36
+ this.isLoadingOptions = false;
37
+ });
38
+ } else {
39
+ this.options = [...(this.args.options || [])];
40
+ this._setDisplayedOptions(selected, true);
41
+ }
42
+ }
43
+
44
+ get label() {
45
+ const labelIsDefined = this.args.label && this.args.label.trim();
46
+ const idIsNotDefined = this.args.id && !this.args.id.trim();
47
+
48
+ if (labelIsDefined && idIsNotDefined) {
49
+ throw new Error(
50
+ 'ERROR in PixMultiSelect component, @id param is necessary when giving @label'
51
+ );
52
+ }
53
+ return this.args.label || null;
54
+ }
55
+
56
+ get isBig() {
57
+ return this.args.size === 'big';
58
+ }
59
+
60
+ get results() {
61
+ if (this.args.isSearchable && this.searchData) {
62
+ return this.options.filter(({ label }) => this._search(label));
63
+ }
64
+ return this.options;
65
+ }
66
+
67
+ get placeholder() {
68
+ const { selected, placeholder } = this.args;
69
+ if (selected?.length > 0) {
70
+ const selectedOptionLabels = this.options
71
+ .filter(({ value, label }) => {
72
+ const hasOption = selected.includes(value);
73
+ return hasOption && Boolean(label);
74
+ })
75
+ .map(({ label }) => label)
76
+ .join(', ');
77
+ return selectedOptionLabels;
78
+ }
79
+ return placeholder;
80
+ }
81
+
82
+ _setDisplayedOptions(selected, shouldSort) {
83
+ const options = this.options.map((option) => ({
84
+ ...option,
85
+ checked: selected ? selected.includes(option.value) : false,
86
+ }));
87
+
88
+ if (shouldSort && this.args.isSearchable) {
89
+ options.sort(sortOptionsByCheckedFirst);
90
+ }
91
+
92
+ this.options = options;
93
+ }
94
+
95
+ _search(label) {
96
+ if (this.args.strictSearch) {
97
+ return label.includes(this.searchData);
98
+ }
99
+ return removeCapitalizeAndDiacritics(label).includes(this.searchData);
100
+ }
101
+
102
+ @action
103
+ onSelect(event) {
104
+ let selected = [...(this.args.selected || [])];
105
+ if (event.target.checked) {
106
+ selected.push(event.target.value);
107
+ } else {
108
+ selected = selected.filter((value) => value !== event.target.value);
109
+ }
110
+
111
+ this._setDisplayedOptions(selected, false);
112
+
113
+ if (this.args.onSelect) {
114
+ this.args.onSelect(selected);
115
+ }
116
+ }
117
+
118
+ @action
119
+ toggleDropDown() {
120
+ if (this.isExpanded) {
121
+ this.hideDropDown();
122
+ } else {
123
+ this.showDropDown();
124
+ }
125
+ }
126
+
127
+ @action
128
+ showDropDown() {
129
+ if (this.isExpanded) return;
130
+ this.isExpanded = true;
131
+ this._setDisplayedOptions(this.args.selected, true);
132
+ }
133
+
134
+ @action
135
+ hideDropDown(event) {
136
+ if (!this.isExpanded) return;
137
+
138
+ if (event) {
139
+ event.stopPropagation();
140
+ event.preventDefault();
141
+ }
142
+ this.isExpanded = false;
143
+ }
144
+
145
+ @action
146
+ focusDropdown() {
147
+ if (this.args.isSearchable && this.args.showOptionsOnInput) {
148
+ this.showDropDown();
149
+ }
150
+ }
151
+
152
+ @action
153
+ updateSearch(event) {
154
+ this.searchData = this.args.strictSearch
155
+ ? event.target.value
156
+ : removeCapitalizeAndDiacritics(event.target.value);
157
+ this.isExpanded = true;
158
+ if (!event.target.value) {
159
+ this._setDisplayedOptions(this.args.selected, true);
160
+ }
161
+ }
162
+ }
@@ -0,0 +1,19 @@
1
+ <div
2
+ class="progress-gauge
3
+ {{this.progressGaugeClass}}
4
+ {{if @isArrowLeft "progress-gauge--tooltip-left"}}"
5
+ ...attributes
6
+ >
7
+ <div class="progress-gauge__referrer"></div>
8
+ <div class="progress-gauge__marker" aria-hidden="true" style={{this.valueGaugeStyle}}></div>
9
+
10
+ {{#if @tooltipText}}
11
+ <div class="progress-gauge__tooltip-wrapper" style={{this.valueGaugeStyle}}>
12
+ <span class="progress-gauge__tooltip">{{@tooltipText}}</span>
13
+ </div>
14
+ {{/if}}
15
+
16
+ {{#if this.hasSubtitle}}
17
+ <p class="progress-gauge__sub-title">{{@subtitle}}</p>
18
+ {{/if}}
19
+ </div>
@@ -0,0 +1,29 @@
1
+ import Component from '@glimmer/component';
2
+ import { htmlSafe } from '@ember/string';
3
+
4
+ export default class PixProgressGauge extends Component {
5
+ get progressValue() {
6
+ if (!this.args.value || this.args.value < 0) {
7
+ return 0;
8
+ }
9
+
10
+ return this.args.value > 100 ? 100 : this.args.value;
11
+ }
12
+
13
+ get valueGaugeStyle() {
14
+ return htmlSafe(`width: ${this.progressValue}%`);
15
+ }
16
+
17
+ get hasSubtitle() {
18
+ return !!this.args.subtitle;
19
+ }
20
+
21
+ get progressGaugeClass() {
22
+ const availableColor = ['yellow', 'white'];
23
+
24
+ const color =
25
+ this.args.color && availableColor.includes(this.args.color) ? this.args.color : `yellow`;
26
+
27
+ return `progress-gauge--${color}`;
28
+ }
29
+ }
@@ -0,0 +1,12 @@
1
+ <div class="pix-radio-button">
2
+ <label class="{{if @isDisabled " pix-radio-button--disabled"}}">
3
+ <input
4
+ disabled={{@isDisabled}}
5
+ aria-disabled="{{@isDisabled}}"
6
+ type="radio"
7
+ value={{@value}}
8
+ ...attributes
9
+ />
10
+ {{@label}}
11
+ </label>
12
+ </div>
@@ -0,0 +1,5 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ export default class PixRadioButton extends Component {
4
+ text = 'pix-radio-button';
5
+ }
@@ -0,0 +1,15 @@
1
+ <LinkTo
2
+ @route={{this.route}}
3
+ @models={{if @model (array @model) this.defaultModel}}
4
+ class="pix-return-to pix-return-to--{{this.shade}}"
5
+ ...attributes
6
+ >
7
+
8
+ {{#if (has-block)}}
9
+ <span aria-hidden="true" class="pix-return-to__icon"><FaIcon @icon="arrow-left" /></span>
10
+ <span class="pix-return-to__text"> {{yield}} </span>
11
+ {{else}}
12
+ <span title="Flèche de retour" class="pix-return-to__icon"><FaIcon @icon="arrow-left" /></span>
13
+ {{/if}}
14
+
15
+ </LinkTo>
@@ -0,0 +1,20 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ export default class PixReturnTo extends Component {
4
+ text = 'pix-return-to';
5
+ availableShade = ['black', 'white', 'blue'];
6
+ defaultModel = [];
7
+
8
+ get route() {
9
+ const routeParam = this.args.route;
10
+ if (routeParam == undefined || routeParam.trim() == '') {
11
+ throw new Error('ERROR in PixReturnTo component, @route param is not provided');
12
+ }
13
+ return routeParam;
14
+ }
15
+
16
+ get shade() {
17
+ const shadeParam = this.args.shade;
18
+ return this.availableShade.includes(shadeParam) ? shadeParam : this.availableShade[0];
19
+ }
20
+ }
@@ -0,0 +1,55 @@
1
+ <div class="pix-select">
2
+
3
+ {{#if this.label}}
4
+ <label for={{@id}} class="pix-select__label">{{this.label}}</label>
5
+ {{/if}}
6
+
7
+ {{#if @isSearchable}}
8
+
9
+ <input
10
+ id={{@id}}
11
+ list="{{this.datalistId}}"
12
+ {{on "input" this.onChange}}
13
+ class="{{if this.isValid "pix-select--is-valid"}} {{if this.isBig "pix-select--big"}}"
14
+ ...attributes
15
+ />
16
+
17
+ <datalist id={{this.datalistId}}>
18
+ {{#each @options as |opt|}}
19
+ <option label={{opt.label}}>{{opt.label}}</option>
20
+ {{/each}}
21
+ </datalist>
22
+
23
+ {{else}}
24
+
25
+ <select
26
+ id={{@id}}
27
+ class="{{if this.isBig "pix-select--big"}}"
28
+ {{on "change" this.onChange}}
29
+ ...attributes
30
+ >
31
+ {{#if (not-eq @emptyOptionLabel undefined)}}
32
+ {{#if @emptyOptionNotSelectable}}
33
+ <option value="" hidden>{{@emptyOptionLabel}}</option>
34
+ {{else}}
35
+ <option value="">{{@emptyOptionLabel}}</option>
36
+ {{/if}}
37
+ {{/if}}
38
+ {{#each @options as |opt|}}
39
+ {{#if (eq @selectedOption opt.value)}}
40
+ {{! https://github.com/emberjs/ember.js/issues/15484
41
+ ember-prop-modifier let us fix a bug about selected attribute in FireFox }}
42
+ <option value={{opt.value}} {{prop selected="true"}}>
43
+ {{opt.label}}
44
+ </option>
45
+ {{else}}
46
+ <option value={{opt.value}}>
47
+ {{opt.label}}
48
+ </option>
49
+ {{/if}}
50
+ {{/each}}
51
+ </select>
52
+ <FaIcon class="pix-select__icon" @icon="chevron-down" />
53
+
54
+ {{/if}}
55
+ </div>
@@ -0,0 +1,58 @@
1
+ import Component from '@glimmer/component';
2
+ import { guidFor } from '@ember/object/internals';
3
+ import { tracked } from '@glimmer/tracking';
4
+ import { action } from '@ember/object';
5
+
6
+ export default class PixSelect extends Component {
7
+ @tracked isValueAValidOption = false;
8
+
9
+ constructor() {
10
+ super(...arguments);
11
+
12
+ if (this.args.isSearchable) {
13
+ this.datalistId = 'pix-select-list-' + guidFor(this);
14
+ }
15
+ }
16
+
17
+ get label() {
18
+ const labelIsDefined = this.args.label?.trim();
19
+ const idIsNotDefined = !this.args.id?.trim();
20
+
21
+ if (labelIsDefined && idIsNotDefined) {
22
+ throw new Error('ERROR in PixSelect component, @id param is necessary when giving @label');
23
+ }
24
+ return this.args.label || null;
25
+ }
26
+
27
+ get isBig() {
28
+ return this.args.size === 'big';
29
+ }
30
+
31
+ get isValid() {
32
+ return this.args.isValidationActive && this.isValueAValidOption;
33
+ }
34
+
35
+ @action
36
+ onChange(event) {
37
+ if (this.args.onChange) {
38
+ this.args.onChange(event);
39
+ }
40
+
41
+ if (!this.args.isSearchable || !this.args.options) {
42
+ return;
43
+ }
44
+
45
+ if (this.args.isValidationActive) {
46
+ this.isValueAValidOption = _checkIfValueIsAValidOption({
47
+ value: event.target.value,
48
+ options: this.args.options,
49
+ });
50
+ }
51
+ }
52
+ }
53
+
54
+ function _checkIfValueIsAValidOption({ value, options }) {
55
+ return value
56
+ ? options.some((option) => option.label.toLowerCase() === value.toLowerCase())
57
+ : false;
58
+ }
@@ -0,0 +1,10 @@
1
+ <div class="pix-selectable-tag {{if this.isChecked " pix-selectable-tag--checked"}}">
2
+ <input
3
+ type="checkbox"
4
+ id={{@id}}
5
+ onChange={{this.toggleIsChecked}}
6
+ checked={{this.isChecked}}
7
+ ...attributes
8
+ />
9
+ <label for={{@id}}>{{@label}}</label>
10
+ </div>
@@ -0,0 +1,13 @@
1
+ import Component from '@glimmer/component';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { action } from '@ember/object';
4
+
5
+ export default class PixSelectableTag extends Component {
6
+ @tracked isChecked = this.args.checked;
7
+
8
+ @action
9
+ toggleIsChecked() {
10
+ this.isChecked = !this.isChecked;
11
+ return this.args.onChange(this.isChecked);
12
+ }
13
+ }
@@ -0,0 +1,16 @@
1
+ <div class={{this.pixStarsClass}} ...attributes>
2
+ <span class="sr-only">{{@alt}}</span>
3
+ {{#each this.stars as |star|}}
4
+ <svg class="pix-stars__{{star}}" data-test-status={{star}} viewBox="0 0 36 36">
5
+ <defs>
6
+ <linearGradient id="pix-stars-default" x1="68.643%" y1="0%" x2="68.643%" y2="100%">
7
+ <stop stop-color="#FEDC41" offset="0%"></stop>
8
+ <stop stop-color="#FF9F00" offset="100%"></stop>
9
+ </linearGradient>
10
+ </defs>
11
+ <path
12
+ d="M8.423 35.82c-.761.507-1.765-.125-1.635-1.03l1.619-11.335L.311 15.36a1.059 1.059 0 01.6-1.796l11.268-1.61L17.027.642c.367-.856 1.58-.856 1.946 0l4.848 11.31 11.269 1.61a1.059 1.059 0 01.599 1.797l-8.096 8.096 1.62 11.334c.129.906-.875 1.538-1.636 1.03L18 29.436 8.423 35.82z"
13
+ ></path>
14
+ </svg>
15
+ {{/each}}
16
+ </div>
@@ -0,0 +1,27 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ const STAR_ACQUIRED = 'acquired';
4
+ const STAR_UNACQUIRED = 'unacquired';
5
+
6
+ export default class PixStars extends Component {
7
+ get pixStarsClass() {
8
+ if (!this.args.color) return 'pix-stars';
9
+ return `pix-stars pix-stars--${this.args.color}`;
10
+ }
11
+
12
+ get stars() {
13
+ const { count = 0, total = 0 } = this.args;
14
+
15
+ const starsTotal = total || count;
16
+
17
+ const stars = [];
18
+ for (let index = 0; index < starsTotal; index++) {
19
+ if (index < count) {
20
+ stars[index] = STAR_ACQUIRED;
21
+ } else {
22
+ stars[index] = STAR_UNACQUIRED;
23
+ }
24
+ }
25
+ return stars;
26
+ }
27
+ }
@@ -0,0 +1,3 @@
1
+ <div class="pix-tag {{this.classes}}" ...attributes>
2
+ {{yield}}
3
+ </div>
@@ -0,0 +1,11 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ export default class PixTag extends Component {
4
+ get classes() {
5
+ const { color, compact } = this.args;
6
+ const classes = [];
7
+ if (color) classes.push(`pix-tag--${color}`);
8
+ if (compact) classes.push(`pix-tag--compact`);
9
+ return classes.join(' ');
10
+ }
11
+ }
@@ -0,0 +1,21 @@
1
+ <div class="pix-textarea">
2
+
3
+ {{#if this.label}}
4
+ <label for={{@id}} class="pix-textarea__label">{{this.label}}</label>
5
+ {{/if}}
6
+
7
+ <Textarea
8
+ id={{@id}}
9
+ @value={{@value}}
10
+ maxlength={{if @maxlength @maxlength}}
11
+ class="{{if @errorMessage "pix-textarea--error"}}"
12
+ ...attributes
13
+ />
14
+ {{#if @maxlength}}
15
+ <p>{{this.textLengthIndicator}} / {{@maxlength}}</p>
16
+ {{/if}}
17
+
18
+ {{#if @errorMessage}}
19
+ <label for={{this.id}} class="pix-textarea__error-message">{{@errorMessage}}</label>
20
+ {{/if}}
21
+ </div>
@@ -0,0 +1,17 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ export default class PixTextarea extends Component {
4
+ get textLengthIndicator() {
5
+ return this.args.value ? this.args.value.length : 0;
6
+ }
7
+
8
+ get label() {
9
+ const labelIsDefined = this.args.label?.trim();
10
+ const idIsNotDefined = !this.args.id?.trim();
11
+
12
+ if (labelIsDefined && idIsNotDefined) {
13
+ throw new Error('ERROR in PixTextarea component, @id param is necessary when giving @label');
14
+ }
15
+ return this.args.label || null;
16
+ }
17
+ }
@@ -0,0 +1,18 @@
1
+ <span class="pix-tooltip" ...attributes>
2
+
3
+ {{yield}}
4
+
5
+ {{#if @text}}
6
+ <span
7
+ id={{@id}}
8
+ role="tooltip"
9
+ class="pix-tooltip__content pix-tooltip__content--{{this.position}}
10
+ {{if @isInline "pix-tooltip__content--inline"}}
11
+ {{if @isLight "pix-tooltip__content--light"}}
12
+ {{if @isWide "pix-tooltip__content--wide"}}"
13
+ >
14
+ {{this.text}}
15
+ </span>
16
+ {{/if}}
17
+
18
+ </span>
@@ -0,0 +1,26 @@
1
+ import Component from '@glimmer/component';
2
+ import { htmlSafe } from '@ember/template';
3
+
4
+ export default class PixTooltipDeprecated extends Component {
5
+ get position() {
6
+ const correctsPosition = [
7
+ 'top',
8
+ 'right',
9
+ 'bottom',
10
+ 'bottom-left',
11
+ 'bottom-right',
12
+ 'left',
13
+ 'top-left',
14
+ 'top-right',
15
+ ];
16
+ return correctsPosition.includes(this.args.position) ? this.args.position : 'top';
17
+ }
18
+
19
+ get text() {
20
+ if (this.args.unescapeHtml) {
21
+ return htmlSafe(this.args.text);
22
+ } else {
23
+ return this.args.text;
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,18 @@
1
+ <span class="pix-tooltip" ...attributes>
2
+ {{#if (has-block "triggerElement")}}
3
+ {{yield to="triggerElement"}}
4
+ {{/if}}
5
+
6
+ {{#if (has-block "tooltip")}}
7
+ <span
8
+ id={{@id}}
9
+ role="tooltip"
10
+ class="pix-tooltip__content pix-tooltip__content--{{this.position}}
11
+ {{if @isInline "pix-tooltip__content--inline"}}
12
+ {{if @isLight "pix-tooltip__content--light"}}
13
+ {{if @isWide "pix-tooltip__content--wide"}}"
14
+ >
15
+ {{yield to="tooltip"}}
16
+ </span>
17
+ {{/if}}
18
+ </span>
@@ -0,0 +1,17 @@
1
+ import Component from '@glimmer/component';
2
+
3
+ export default class PixTooltip extends Component {
4
+ get position() {
5
+ const correctsPosition = [
6
+ 'top',
7
+ 'right',
8
+ 'bottom',
9
+ 'bottom-left',
10
+ 'bottom-right',
11
+ 'left',
12
+ 'top-left',
13
+ 'top-right',
14
+ ];
15
+ return correctsPosition.includes(this.args.position) ? this.args.position : 'top';
16
+ }
17
+ }