mypgs 1.6.0 → 2.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 (88) hide show
  1. package/AGENTS.md +2 -2
  2. package/assets/javascript/components/_accordion.js +2 -2
  3. package/assets/javascript/components/_modals.js +159 -136
  4. package/assets/javascript/components/_notifications.js +19 -9
  5. package/assets/javascript/components/_search.js +2 -2
  6. package/assets/javascript/components/_slides.js +66 -32
  7. package/assets/javascript/components/_stepTabs.js +4 -4
  8. package/assets/javascript/components/_steps.js +2 -2
  9. package/assets/javascript/components/_summary.js +2 -2
  10. package/assets/javascript/functions/_formValidate.js +97 -53
  11. package/assets/javascript/functions/_scrollY.js +10 -10
  12. package/assets/javascript/layout/_header.js +3 -0
  13. package/assets/scss/base/_html.scss +2 -2
  14. package/assets/scss/base/_variables.scss +2 -2
  15. package/assets/scss/components/_form.scss +2 -2
  16. package/assets/scss/components/_notification.scss +23 -30
  17. package/assets/scss/components/_search.scss +27 -21
  18. package/assets/scss/layout/_pageShell.scss +18 -15
  19. package/assets/scss/mixin/_mx-form.scss +7 -7
  20. package/{templates/html → demo}/demo.html +1 -1
  21. package/demo/demo.js +240 -0
  22. package/dist/css/index.css +86 -92
  23. package/dist/css/index.css.map +1 -1
  24. package/dist/css/index.min.css +1 -1
  25. package/dist/javascript/index.js +356 -255
  26. package/dist/javascript/index.js.map +1 -1
  27. package/dist/javascript/index.min.js +1 -1
  28. package/docs/componenti-e-markup.md +26 -27
  29. package/docs/components/accordion.md +61 -0
  30. package/docs/components/badges.md +67 -0
  31. package/docs/components/breadcumbs.md +43 -0
  32. package/docs/components/button.md +59 -0
  33. package/docs/components/card.md +50 -0
  34. package/docs/components/dropdown.md +135 -0
  35. package/docs/components/form.md +113 -0
  36. package/docs/components/logo.md +36 -0
  37. package/docs/components/menu.md +90 -0
  38. package/docs/components/modal.md +131 -0
  39. package/docs/components/notification.md +81 -0
  40. package/docs/components/search.md +117 -0
  41. package/docs/components/slides.md +85 -0
  42. package/docs/components/stepTabs.md +93 -0
  43. package/docs/components/steps.md +56 -0
  44. package/docs/components/summary.md +49 -0
  45. package/docs/components/table.md +42 -0
  46. package/docs/components/tooltip.md +53 -0
  47. package/docs/helper-javascript.md +68 -3
  48. package/docs/layout/body.md +41 -0
  49. package/docs/layout/flex.md +116 -0
  50. package/docs/layout/footer.md +71 -0
  51. package/docs/layout/grid.md +116 -0
  52. package/docs/layout/header.md +116 -0
  53. package/docs/layout/pageShell.md +94 -0
  54. package/docs/layout/section.md +69 -0
  55. package/docs/patterns/cookieConsent.md +89 -0
  56. package/package.json +2 -1
  57. package/scripts/generate-component-docs.js +557 -0
  58. package/templates/html/components/accordion.html +33 -4
  59. package/templates/html/components/badges.html +23 -0
  60. package/templates/html/components/breadcumbs.html +14 -0
  61. package/templates/html/components/button.html +22 -0
  62. package/templates/html/components/card.html +20 -0
  63. package/templates/html/components/dropdown.html +34 -0
  64. package/templates/html/components/form.html +82 -4
  65. package/templates/html/components/logo.html +21 -0
  66. package/templates/html/components/menu.html +33 -6
  67. package/templates/html/components/modal.html +44 -0
  68. package/templates/html/components/notification.html +68 -32
  69. package/templates/html/components/search.html +76 -0
  70. package/templates/html/components/slides.html +43 -0
  71. package/templates/html/components/stepTabs.html +47 -0
  72. package/templates/html/components/steps.html +24 -0
  73. package/templates/html/components/summary.html +27 -0
  74. package/templates/html/components/table.html +12 -0
  75. package/templates/html/components/tooltip.html +35 -0
  76. package/templates/html/layout/body.html +20 -5
  77. package/templates/html/layout/flex.html +20 -0
  78. package/templates/html/layout/footer.html +29 -1
  79. package/templates/html/layout/grid.html +20 -0
  80. package/templates/html/layout/header.html +41 -0
  81. package/templates/html/layout/pageShell.html +19 -0
  82. package/templates/html/layout/section.html +32 -10
  83. package/templates/html/patterns/cookieConsent.html +31 -0
  84. package/templates/react/components/form.jsx +3 -3
  85. package/templates/react/components/notification.jsx +4 -4
  86. package/templates/react/patterns/footer.jsx +1 -1
  87. package/templates/html/demo.js +0 -130
  88. /package/{templates/html → demo}/demo.css +0 -0
@@ -1,6 +1,6 @@
1
1
  const API = new WeakMap();
2
2
 
3
- export function PGS_stepTabs_init(root = document) {
3
+ function PGS_stepTabs_init(root = document) {
4
4
  pgs(root).querySelectorAll("stepTabs").forEach(tabsWizard => {
5
5
  if (tabsWizard.dataset.stepTabsInitialized === "true") return;
6
6
  tabsWizard.dataset.stepTabsInitialized = "true";
@@ -32,7 +32,7 @@ export function PGS_stepTabs_init(root = document) {
32
32
  const dot = document.createElement("button");
33
33
  dot.type = "button";
34
34
  pgs(dot).add("stepTabs-dots-dot");
35
- dot.setAttribute("data-step", index);
35
+ pgs(dot).option.setValueBrackets("step", index);
36
36
  dot.innerHTML = `<i class="fa-solid ${iconClass}"></i>`;
37
37
 
38
38
  dot.addEventListener("click", () => {
@@ -97,7 +97,7 @@ export function PGS_stepTabs_init(root = document) {
97
97
  //= INIT
98
98
  goTo(0, false);
99
99
 
100
- //= data-tab-locked
100
+ //= tab-locked
101
101
  const observer = new MutationObserver(() => {
102
102
  if (isRendering) return;
103
103
  updateControls();
@@ -135,7 +135,7 @@ export function PGS_stepTabs_init(root = document) {
135
135
 
136
136
  PGS_stepTabs_init()
137
137
 
138
- export function PGS_stepTabs_api(selector) {
138
+ function PGS_stepTabs_api(selector) {
139
139
  return API.get(selector);
140
140
  }
141
141
 
@@ -1,6 +1,6 @@
1
1
  const API = new WeakMap();
2
2
 
3
- export function PGS_steps_init(root = document) {
3
+ function PGS_steps_init(root = document) {
4
4
  pgs(root).querySelectorAll("steps").forEach(steps => {
5
5
  if (API.has(steps)) return;
6
6
 
@@ -43,7 +43,7 @@ export function PGS_steps_init(root = document) {
43
43
  PGS_steps_init()
44
44
 
45
45
  //# API
46
- export function PGS_steps_api(selector) {
46
+ function PGS_steps_api(selector) {
47
47
  return API.get(selector);
48
48
  }
49
49
 
@@ -20,7 +20,7 @@ function directPgsChild(element, token) {
20
20
  return Array.from(element.children).find(child => pgs(child).contains(token));
21
21
  }
22
22
 
23
- export function PGS_summary_init(root = document) {
23
+ function PGS_summary_init(root = document) {
24
24
  pgs(root).querySelectorAll("summary").forEach((summary) => {
25
25
  if (API.has(summary)) return;
26
26
 
@@ -95,7 +95,7 @@ export function PGS_summary_init(root = document) {
95
95
  PGS_summary_init();
96
96
 
97
97
  //# API
98
- export function PGS_summary_api(selector) {
98
+ function PGS_summary_api(selector) {
99
99
  return API.get(selector);
100
100
  }
101
101
 
@@ -1,40 +1,43 @@
1
+ import { pgs } from "../_pgs.js";
1
2
  import { PGS_notification } from "../components/_notifications.js";
2
3
 
3
4
 
4
5
  export class PGS_formValidate {
5
- constructor({ form } = {}) {
6
+ #message = {};
7
+ #insideValidatedCallback = false;
8
+
9
+ constructor(form, options = {}) {
10
+ if (!options || typeof options !== "object" || Array.isArray(options)) {
11
+ throw new TypeError("options must be an object");
12
+ }
13
+
6
14
  this.container = form;
7
15
  this._rules = [];
8
- // pgs(this.container).add("formError");
16
+ this.message = {
17
+ fieldError: "Please complete this field.",
18
+ fieldsError: "Please complete all required fields.",
19
+ success: "Submitted successfully."
20
+ };
21
+
22
+ if (options.message !== undefined) this.message = options.message;
23
+ this.container?.setAttribute("novalidate", "");
9
24
  }
10
25
 
11
- //+ ADD
12
- addError(field, i) {
13
- field.setAttribute("data-form-field-status", "error");
14
- if (i == 0) field.scrollIntoView();
15
-
16
- let message = field.getAttribute("data-form-field-message");
17
-
18
- if (i == 0 && message) PGS_notification.toast.error(message);
19
- else if (i == 0) PGS_notification.toast.error("Compila tutti i campi!");
26
+ get message() {
27
+ return { ...this.#message };
20
28
  }
21
29
 
22
- //+ REMOVE
23
- removeError(field) {
24
- field.setAttribute("data-form-field-status", "");
25
- }
30
+ set message(value) {
31
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
32
+ throw new TypeError("message must be an object");
33
+ }
26
34
 
27
- #removeErrorOnClick(allFields) {
28
- allFields.forEach(element => {
29
- element.addEventListener("click", e => this.removeError(element))
30
- });
35
+ this.#message = { ...this.#message, ...value };
31
36
  }
32
37
 
33
- // + --------------------------
34
- // + Helpers
35
- // + --------------------------
36
- help = {
37
- // supporta sia required nativo, sia data-required="true"
38
+ // - Helpers
39
+ #help = {
40
+ // supporta sia required nativo
38
41
  isRequired(field) {
39
42
  if (!field) return false;
40
43
 
@@ -77,26 +80,26 @@ export class PGS_formValidate {
77
80
  if (input.type === "hidden") return false;
78
81
  if (input.type === "checkbox" || input.type === "radio" || input.type === "file") return false;
79
82
 
80
- // valida solo se required (o data-required="true")
81
- if (!this.help.isRequired(input)) return false;
83
+ // valida solo se required
84
+ if (!this.#help.isRequired(input)) return false;
82
85
 
83
- return this.help.isEmptyTextLike(input);
86
+ return this.#help.isEmptyTextLike(input);
84
87
  });
85
88
 
86
89
  //== TEXTAREA
87
90
  // required vuote
88
91
  const textareas = Array.from(container.querySelectorAll("textarea")).filter((ta) => {
89
92
  if (ta.disabled) return false;
90
- if (!this.help.isRequired(ta)) return false;
91
- return this.help.isEmptyTextLike(ta);
93
+ if (!this.#help.isRequired(ta)) return false;
94
+ return this.#help.isEmptyTextLike(ta);
92
95
  });
93
96
 
94
97
  //== SELECT
95
98
  // required vuoti
96
99
  const selects = Array.from(container.querySelectorAll("select")).filter((sel) => {
97
100
  if (sel.disabled) return false;
98
- if (!this.help.isRequired(sel)) return false;
99
- return this.help.isEmptySelect(sel);
101
+ if (!this.#help.isRequired(sel)) return false;
102
+ return this.#help.isEmptySelect(sel);
100
103
  });
101
104
 
102
105
  //== RADIO
@@ -104,8 +107,8 @@ export class PGS_formValidate {
104
107
  const radios = Array.from(container.querySelectorAll('input[type="radio"]')).filter((r) => !r.disabled);
105
108
  const requiredRadioGroups = new Map(); // name -> [elements]
106
109
  for (const r of radios) {
107
- if (!this.help.isRequired(r)) continue;
108
- const name = this.help.getGroupName(r);
110
+ if (!this.#help.isRequired(r)) continue;
111
+ const name = this.#help.getGroupName(r);
109
112
  if (!name) continue;
110
113
  if (!requiredRadioGroups.has(name)) requiredRadioGroups.set(name, []);
111
114
  requiredRadioGroups.get(name).push(r);
@@ -126,9 +129,9 @@ export class PGS_formValidate {
126
129
  const requiredCheckboxSingles = [];
127
130
  const requiredCheckboxGroups = new Map(); // name -> [elements]
128
131
  for (const c of checkboxes) {
129
- if (!this.help.isRequired(c)) continue;
132
+ if (!this.#help.isRequired(c)) continue;
130
133
 
131
- const name = this.help.getGroupName(c);
134
+ const name = this.#help.getGroupName(c);
132
135
  if (!name) {
133
136
  // checkbox senza name: trattala come singola required
134
137
  if (!c.checked) requiredCheckboxSingles.push(c);
@@ -151,7 +154,7 @@ export class PGS_formValidate {
151
154
  // required: se vuoi includerlo
152
155
  const fileInputs = Array.from(container.querySelectorAll('input[type="file"]')).filter((f) => {
153
156
  if (f.disabled) return false;
154
- if (!this.help.isRequired(f)) return false;
157
+ if (!this.#help.isRequired(f)) return false;
155
158
  return !(f.files && f.files.length > 0);
156
159
  });
157
160
 
@@ -167,12 +170,37 @@ export class PGS_formValidate {
167
170
  ruleInvalidFields
168
171
  ];
169
172
 
170
- return invalidFields.flat();
173
+ return [...new Set(invalidFields.flat())];
174
+ }
175
+
176
+ //+ ADD
177
+ addFieldError(field, i = 0, total = 1) {
178
+ pgs(field).option.add("error");
179
+ if (i === 0) field.scrollIntoView();
180
+
181
+ if (i !== 0) return;
182
+
183
+ if (total > 1) {
184
+ PGS_notification.toast.error(this.message.fieldsError);
185
+ return;
186
+ }
187
+
188
+ const message = pgs(field).option.getValueBrackets("message");
189
+ PGS_notification.toast.error(message || this.message.fieldError);
190
+ }
191
+
192
+ //+ REMOVE
193
+ removeFieldError(field) {
194
+ pgs(field).option.remove("error");
195
+ }
196
+
197
+ // + SUCCESS
198
+ success(text = this.message.success) {
199
+ if (this.#insideValidatedCallback || this.validate() === true) PGS_notification.toast.success(text)
171
200
  }
172
201
 
173
- // + -------------------------
174
- // + VALIDATE
175
- // + -------------------------
202
+
203
+ // + VALIDATE
176
204
  validate() {
177
205
  const invalid = this.#inputValue(this.container);
178
206
  const allFields = this.container.querySelectorAll("input, textarea, select")
@@ -183,34 +211,50 @@ export class PGS_formValidate {
183
211
 
184
212
  //== per radio/checkbox in gruppo:
185
213
  // rimuovi l'errore solo sull'elemento che lo ospita (qui: se presente)
186
- for (const el of allFields) { if (!invalid.includes(el)) this.removeError(el); }
214
+ for (const el of allFields) { if (!invalid.includes(el)) this.removeFieldError(el); }
187
215
 
188
216
  //== aggiungo errori dove serve
189
- invalid.forEach((el, i) => this.addError(el, i))
217
+ invalid.forEach((el, i) => this.addFieldError(el, i, invalid.length))
190
218
 
191
219
  //== rimuove l'errore al click
192
- this.#removeErrorOnClick(allFields)
220
+ allFields.forEach(element => element.addEventListener("click", e => this.removeFieldError(element)));
193
221
 
194
222
  //== status form
195
223
  if (invalid.length) {
196
- this.container.setAttribute("data-form-status", "error");
224
+ pgs(this.container).option.remove("success").add("error");
197
225
  return false;
198
226
  } else {
199
- this.container.setAttribute("data-form-status", "success");
227
+ pgs(this.container).option.remove("error").add("success");
200
228
  return true;
201
229
  }
202
230
  }
203
231
 
204
- ifSuccess(text = "Inviato con successo") {
205
- if (this.validate() == true) PGS_notification.toast.success(text)
232
+ // + EVENT VALIDATOR
233
+ validator(callback, eventName = "submit") {
234
+ if (typeof callback !== "function") throw new TypeError("callback must be a function");
235
+ if (typeof eventName !== "string" || !eventName.trim()) throw new TypeError("eventName must be a non-empty string");
236
+
237
+ this.container.addEventListener(eventName, event => {
238
+ event.preventDefault();
239
+ if (!this.validate()) return;
240
+
241
+ this.#insideValidatedCallback = true;
242
+
243
+ try {
244
+ this.success();
245
+ callback(event);
246
+ } finally {
247
+ this.#insideValidatedCallback = false;
248
+ }
249
+ });
250
+
251
+ return this;
206
252
  }
207
253
 
208
- // + -------------------------
209
- // + ADD RULE
210
- // + -------------------------
211
- addNewRule(container) {
212
- if (typeof container !== "function") throw new Error("Rule must be a function");
213
- this._rules.push(container);
254
+ // + ADD RULE
255
+ addNewRule(rule) {
256
+ if (typeof rule !== "function") throw new Error("Rule must be a function");
257
+ this._rules.push(rule);
214
258
  return this;
215
259
  }
216
260
  }
@@ -1,4 +1,4 @@
1
- export function PGS_scrollHorizontal(querySelector, dataSpeed) {
1
+ export function PGS_scrollHorizontal(element, speed) {
2
2
  // Se hai più contenitori, selezionali tutti:
3
3
  // Semplice "singleton" per stimare se la sorgente è trackpad
4
4
  const TrackpadDetector = (() => {
@@ -40,10 +40,7 @@ export function PGS_scrollHorizontal(querySelector, dataSpeed) {
40
40
 
41
41
  //= Scorrimento orizzontale con rotella (evita il trackpad)
42
42
 
43
- let el = querySelector
44
- el.addEventListener('wheel', (e) => {
45
- const speed = dataSpeed;
46
-
43
+ const onWheel = (e) => {
47
44
  //== lascia lo scroll naturale del trackpad
48
45
  if (TrackpadDetector.update(e)) return;
49
46
 
@@ -54,11 +51,11 @@ export function PGS_scrollHorizontal(querySelector, dataSpeed) {
54
51
  //== Converti delta in px per lo shift orizzontale
55
52
  let delta = e.deltaY;
56
53
  if (e.deltaMode === 1) delta *= 16;
57
- else if (e.deltaMode === 2) delta *= el.clientHeight;
54
+ else if (e.deltaMode === 2) delta *= element.clientHeight;
58
55
 
59
56
  //== Verifica se il contenitore può ancora scrollare orizzontalmente
60
- const atStart = el.scrollLeft <= 0;
61
- const atEnd = el.scrollLeft + el.clientWidth >= el.scrollWidth - 1;
57
+ const atStart = element.scrollLeft <= 0;
58
+ const atEnd = element.scrollLeft + element.clientWidth >= element.scrollWidth - 1;
62
59
  const scrollingRight = delta > 0;
63
60
  const scrollingLeft = delta < 0;
64
61
  const canScrollHoriz =
@@ -72,6 +69,9 @@ export function PGS_scrollHorizontal(querySelector, dataSpeed) {
72
69
  e.preventDefault();
73
70
 
74
71
  //== rotella giù => destra
75
- el.scrollLeft += delta * speed;
76
- }, { passive: false });
72
+ element.scrollLeft += delta * speed;
73
+ };
74
+
75
+ element.addEventListener('wheel', onWheel, { passive: false });
76
+ return () => element.removeEventListener('wheel', onWheel);
77
77
  }
@@ -8,7 +8,10 @@ function PGS_header(selectHeader = document) {
8
8
 
9
9
  const headerElements = pgs(header).querySelectorAll("header-element");
10
10
 
11
+ if (!headerElements.length) console.log('For the header to work correctly, insert "header-element" under "header"');
11
12
  if (!headerElements.length) return;
13
+
14
+
12
15
 
13
16
  headerElements.forEach(selectHeader => {
14
17
 
@@ -5,14 +5,14 @@
5
5
  margin: 0;
6
6
  padding: 0;
7
7
  box-sizing: border-box;
8
- scroll-margin-top: calc(var(--heightOfHeader) + 5vh);
8
+ scroll-margin-top: var(--page-topScroll);
9
9
 
10
10
  // Reset properties
11
11
  * {
12
12
  margin: 0;
13
13
  padding: 0;
14
14
  box-sizing: border-box;
15
- scroll-margin-top: calc(var(--heightOfHeader) + 5vh);
15
+ scroll-margin-top: var(--page-topScroll);
16
16
  }
17
17
 
18
18
  &:root,
@@ -19,8 +19,8 @@
19
19
  --text-shadow: 0px 0px 50px #000000;
20
20
  --backdrop: #0000003e;
21
21
  --blur: blur(20px);
22
- --page-top: calc(var(--heightOfHeader) + (var(--gap-elements)*2));
23
- --page-topScroll: calc(var(--heightOfHeaderScroll) + (var(--gap-elements)*2));
22
+ --page-top: calc(var(--heightOfHeader) + var(--heightOfHeader));
23
+ --page-topScroll: calc(var(--heightOfHeaderScroll) + var(--heightOfHeader));
24
24
  --page-width: 1280px;
25
25
  --page-space: clamp(var(--padding-page), calc((100% - var(--section-width)) / 2 + var(--padding-page)), 100%);
26
26
  --gap-texts: 1.0rem;
@@ -50,6 +50,6 @@
50
50
  @include form();
51
51
  }
52
52
 
53
- [pgs~=formError] {
54
- @include formError();
53
+ [pgs~=formValidate] {
54
+ @include formValidate();
55
55
  }
@@ -3,34 +3,7 @@
3
3
  //= NOTIFICATION GROUP / TRIGGER
4
4
  [pgs~="notificationTrigger"] {}
5
5
 
6
- //= NOTIFICATION STYLE
7
- @mixin notification($position: center) {
8
- @if ($position ==center) {
9
- inset-inline: 0;
10
- top: calc(var(--heightOfHeader) + 10px);
11
-
12
- @at-root body:has(header[data-header-scroll="true"]) #{&} {
13
- top: 10px;
14
- }
15
- }
16
-
17
- @else if($position ==right) {
18
- top: calc(var(--heightOfHeader) + 10px);
19
- right: 10px;
20
-
21
- @at-root body:has(header[data-header-scroll="true"]) #{&} {
22
- top: 0;
23
- }
24
- }
25
-
26
- @else if($position ==bottom) {
27
- bottom: 10px;
28
- right: 10px;
29
- }
30
- }
31
-
32
- [pgs~="notification"],
33
- [pgs~="toast"] {
6
+ [pgs~="notification"] {
34
7
  display: flex;
35
8
  flex-direction: column;
36
9
  gap: var(--gap-texts);
@@ -183,10 +156,30 @@
183
156
  }
184
157
  }
185
158
 
186
- [pgs~="notification"] {
159
+ //= NOTIFICATION STYLE
160
+ @mixin notification($position: center) {
161
+ $size: 1.0rem;
162
+
163
+ @if ($position ==center) {
164
+ inset-inline: 0;
165
+ top: calc(var(--heightOfHeaderScroll) + $size);
166
+ }
167
+
168
+ @else if($position ==right) {
169
+ top: calc(var(--heightOfHeaderScroll) + $size);
170
+ right: $size;
171
+ }
172
+
173
+ @else if($position ==bottom) {
174
+ inset-inline: 0;
175
+ bottom: $size;
176
+ }
177
+ }
178
+
179
+ [pgs~="notification"]:not([pgs-option~="toast"]) {
187
180
  @include notification(right);
188
181
  }
189
182
 
190
- [pgs~="toast"] {
183
+ [pgs~="notification"][pgs-option~="toast"] {
191
184
  @include notification(center);
192
185
  }
@@ -5,9 +5,9 @@
5
5
  --search-suggestions-color: var(--color-text);
6
6
  --search-suggestions-border: var(--border-complete);
7
7
  --search-suggestions-borderRadius: var(--border-radius-input);
8
- --search-suggestions-box-shadow: var(--box-shadow);
8
+ --search-suggestions-boxShadow: var(--box-shadow);
9
9
  --search-suggestions-gap: 0;
10
- --search-suggestions-max-height: 32rem;
10
+ --search-suggestions-maxHeight: 32rem;
11
11
  --search-suggestions-offset: .5rem;
12
12
  --search-suggestions-padding: .5rem;
13
13
  --search-suggestions-item-padding: 1rem;
@@ -15,12 +15,12 @@
15
15
  --search-suggestions-item-selected-color: var(--color-whiteFixed);
16
16
  position: relative;
17
17
  @include flexRow(nowrap);
18
+ @include button_header();
18
19
  flex: 1;
19
20
  width: 100%;
20
21
  overflow: visible;
21
22
  margin-inline: auto;
22
23
  padding: 0;
23
- @include button_header();
24
24
 
25
25
  @media (min-width: $mobile) {
26
26
  min-width: 21.4rem;
@@ -67,30 +67,33 @@
67
67
  outline: var(--focus-visible);
68
68
  }
69
69
 
70
- &:not([pgs-state~="open"])>[pgs~="search-suggestions"] {
71
- display: none;
72
- }
70
+ @mixin _color($varColor) {
71
+ background: var(#{$varColor}-background);
72
+ color: var(#{$varColor}-color);
73
73
 
74
- &[pgs-state~="open"]>[pgs~="search-suggestions"] {
75
- display: flex;
74
+ i {
75
+ color: var(#{$varColor}-color);
76
+ --fa-primary-color: var(#{$varColor}-color);
77
+ --fa-secondary-color: var(#{$varColor}-color);
78
+ }
76
79
  }
77
80
 
78
- >[pgs~="search-suggestions"] {
81
+ [pgs~="search-suggestions"] {
82
+ display: none;
79
83
  position: absolute;
80
84
  inset: calc(100% + var(--search-suggestions-offset)) 0 auto;
81
85
  z-index: 1000;
82
86
  flex-direction: column;
83
87
  gap: var(--search-suggestions-gap);
84
- max-height: var(--search-suggestions-max-height);
88
+ max-height: var(--search-suggestions-maxHeight);
85
89
  overflow-y: auto;
86
90
  padding: var(--search-suggestions-padding);
87
91
  margin: 0;
88
92
  list-style: none;
89
93
  border: var(--search-suggestions-border);
90
94
  border-radius: calc(var(--search-suggestions-borderRadius) + var(--search-suggestions-padding));
91
- background: var(--search-suggestions-background);
92
- color: var(--search-suggestions-color);
93
- box-shadow: var(--search-suggestions-box-shadow);
95
+ box-shadow: var(--search-suggestions-boxShadow);
96
+ @include _color(--search-suggestions);
94
97
 
95
98
  [pgs~="search-suggestions-item"] {
96
99
  padding: var(--search-suggestions-item-padding);
@@ -100,8 +103,7 @@
100
103
 
101
104
  &[aria-selected="true"],
102
105
  &:hover {
103
- background: var(--search-suggestions-item-selected-background);
104
- color: var(--search-suggestions-item-selected-color);
106
+ @include _color(--search-suggestions-item-selected);
105
107
  }
106
108
 
107
109
  &[aria-disabled="true"] {
@@ -110,17 +112,21 @@
110
112
  }
111
113
  }
112
114
 
113
- &:has([pgs~="search-suggestions-item"]:hover) [pgs~="search-suggestions-item"][aria-selected="true"] {
114
- background: var(--search-suggestions-background);
115
- color: var(--search-suggestions-color);
115
+ &:has([pgs~="search-suggestions-item"]:hover) {
116
+ [pgs~="search-suggestions-item"][aria-selected="true"] {
117
+ @include _color(--search-suggestions);
116
118
 
117
- &:hover {
118
- background: var(--search-suggestions-item-selected-background);
119
- color: var(--search-suggestions-item-selected-color);
119
+ &:hover {
120
+ @include _color(--search-suggestions-item-selected);
121
+ }
120
122
  }
121
123
  }
122
124
  }
123
125
 
126
+ &[pgs-state~="open"] [pgs~="search-suggestions"] {
127
+ display: flex;
128
+ }
129
+
124
130
  @at-root dialog #{&} {
125
131
  max-width: calc(100% - var(--padding-page) * 2);
126
132
  height: max-content;
@@ -18,9 +18,12 @@ $pageShell-test-gap: 4rem;
18
18
  }
19
19
 
20
20
  [pgs~="pageShell"] {
21
- --pageShell-aside-sticky-top: 0;
21
+ --pageShell-width: calc(var(--pageShell-content-width) + (var(--padding-page) * 2));
22
+ --pageShell-content-width: var(--page-width);
22
23
  --pageShell-aside-width: #{$aside-size};
23
- --pageShell-content-width: 500px;
24
+ --pageShell-aside-sticky-top: 0;
25
+ --pageShell-paddingInline: var(--padding-page);
26
+ --pageShell-paddingTop: var(--page-top);
24
27
  --pageShell-gap: var(--gap-elements);
25
28
  display: flex;
26
29
  flex-wrap: wrap;
@@ -29,17 +32,17 @@ $pageShell-test-gap: 4rem;
29
32
  align-items: start;
30
33
  justify-content: center;
31
34
  width: 100%;
32
- max-width: calc(var(--page-width) + (var(--padding-page) * 2));
33
- padding-inline: var(--padding-page);
35
+ max-width: var(--pageShell-width);
36
+ padding-inline: var(--pageShell-paddingInline);
34
37
  container-type: inline-size;
35
38
 
36
39
  [pgs~="pageShell-content"] {
37
40
  grid-area: content;
38
- flex: 999 1 var(--pageShell-content-width);
39
- min-width: min(100%, var(--pageShell-content-width));
40
- width: min(100%, var(--page-width));
41
- max-width: var(--page-width);
42
- padding-top: var(--page-top);
41
+ flex: 999 1 $content-size;
42
+ min-width: min(100%, $content-size);
43
+ width: min(100%, var(--pageShell-content-width));
44
+ max-width: var(--pageShell-content-width);
45
+ padding-top: var(--pageShell-paddingTop);
43
46
  padding-bottom: var(--gap-elements);
44
47
  }
45
48
 
@@ -56,7 +59,7 @@ $pageShell-test-gap: 4rem;
56
59
  overscroll-behavior: contain;
57
60
  scrollbar-gutter: stable;
58
61
  scrollbar-width: none;
59
- padding-top: var(--page-top);
62
+ padding-top: var(--pageShell-paddingTop);
60
63
  padding-bottom: var(--gap-elements);
61
64
  flex: 1 1 var(--pageShell-aside-width);
62
65
  min-width: min(100%, var(--pageShell-aside-width));
@@ -82,7 +85,7 @@ $pageShell-test-gap: 4rem;
82
85
  overscroll-behavior: contain;
83
86
  scrollbar-gutter: stable;
84
87
  scrollbar-width: none;
85
- padding-top: var(--page-top);
88
+ padding-top: var(--pageShell-paddingTop);
86
89
  padding-bottom: calc(var(--gap-elements)*2);
87
90
 
88
91
  &::-webkit-scrollbar {
@@ -116,11 +119,11 @@ $pageShell-test-gap: 4rem;
116
119
  }
117
120
 
118
121
  &:has(> [pgs~="pageShell-aside"]) {
119
- max-width: calc(var(--page-width) + var(--pageShell-aside-width) + var(--pageShell-gap) + (var(--padding-page) * 2));
122
+ --pageShell-width: calc(var(--pageShell-content-width) + var(--pageShell-aside-width) + var(--pageShell-gap) + (var(--padding-page) * 2));
120
123
  }
121
124
 
122
125
  &:has(> [pgs~="pageShell-aside"] ~ [pgs~="pageShell-aside"]) {
123
- max-width: calc(var(--page-width) + (var(--pageShell-aside-width) * 2) + (var(--pageShell-gap) * 2) + (var(--padding-page) * 2));
126
+ --pageShell-width: calc(var(--pageShell-content-width) + (var(--pageShell-aside-width) * 2) + (var(--pageShell-gap) * 2) + (var(--padding-page) * 2));
124
127
  }
125
128
 
126
129
  //== RESPONSIVE ==//
@@ -150,7 +153,7 @@ $pageShell-test-gap: 4rem;
150
153
  &:has(> [pgs~="pageShell-aside"]):has(> [pgs~="pageShell-content"] + [pgs~="pageShell-aside"]) {
151
154
  @container (max-width: calc(#{$aside-size} + #{$content-size} + #{$aside-size} + (#{$pageShell-test-gap} * 2))) {
152
155
  display: grid;
153
- grid-template-columns: var(--pageShell-aside-width) minmax(0, var(--page-width));
156
+ grid-template-columns: var(--pageShell-aside-width) minmax(0, var(--pageShell-content-width));
154
157
  grid-template-areas:
155
158
  "asideLeft content"
156
159
  "asideLeft asideRight";
@@ -179,7 +182,7 @@ $pageShell-test-gap: 4rem;
179
182
  }
180
183
 
181
184
  @container (max-width: #{$content-size}) {
182
- padding-top: var(--page-top);
185
+ padding-top: var(--pageShell-paddingTop);
183
186
 
184
187
  [pgs~="pageShell-content"],
185
188
  [pgs~="pageShell-aside"] {