mypgs 1.5.1 → 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 (108) hide show
  1. package/AGENTS.md +8 -5
  2. package/README.md +1 -1
  3. package/assets/javascript/_imports.js +4 -0
  4. package/assets/javascript/_pgs.js +58 -0
  5. package/assets/javascript/base/_darkmode.js +27 -105
  6. package/assets/javascript/base/_svg.js +103 -0
  7. package/assets/javascript/components/_accordion.js +2 -2
  8. package/assets/javascript/components/_menu.js +1 -3
  9. package/assets/javascript/components/_modals.js +159 -136
  10. package/assets/javascript/components/_notifications.js +19 -9
  11. package/assets/javascript/components/_search.js +391 -0
  12. package/assets/javascript/components/_slides.js +66 -32
  13. package/assets/javascript/components/_stepTabs.js +4 -4
  14. package/assets/javascript/components/_steps.js +2 -2
  15. package/assets/javascript/components/_summary.js +2 -2
  16. package/assets/javascript/functions/_formValidate.js +97 -53
  17. package/assets/javascript/functions/_scrollY.js +10 -10
  18. package/assets/javascript/index.js +2 -0
  19. package/assets/javascript/layout/_header.js +29 -7
  20. package/assets/scss/base/_color.scss +5 -5
  21. package/assets/scss/base/_html.scss +2 -2
  22. package/assets/scss/base/_variables.scss +4 -2
  23. package/assets/scss/components/_dropdown.scss +2 -1
  24. package/assets/scss/components/_form.scss +2 -2
  25. package/assets/scss/components/_logo.scss +2 -2
  26. package/assets/scss/components/_menu.scss +20 -27
  27. package/assets/scss/components/_modals.scss +11 -1
  28. package/assets/scss/components/_notification.scss +23 -30
  29. package/assets/scss/components/_search.scss +140 -0
  30. package/assets/scss/index.scss +2 -2
  31. package/assets/scss/layout/_header.scss +1 -1
  32. package/assets/scss/layout/_pageShell.scss +19 -15
  33. package/assets/scss/mixin/_mx-form.scss +7 -7
  34. package/{templates/html → demo}/demo.html +1 -1
  35. package/demo/demo.js +240 -0
  36. package/dist/css/index.css +188 -125
  37. package/dist/css/index.css.map +1 -1
  38. package/dist/css/index.min.css +1 -1
  39. package/dist/index.d.ts +70 -0
  40. package/dist/javascript/index.js +1038 -405
  41. package/dist/javascript/index.js.map +1 -1
  42. package/dist/javascript/index.min.js +1 -1
  43. package/docs/componenti-e-markup.md +62 -27
  44. package/docs/components/accordion.md +61 -0
  45. package/docs/components/badges.md +67 -0
  46. package/docs/components/breadcumbs.md +43 -0
  47. package/docs/components/button.md +59 -0
  48. package/docs/components/card.md +50 -0
  49. package/docs/components/dropdown.md +135 -0
  50. package/docs/components/form.md +113 -0
  51. package/docs/components/logo.md +36 -0
  52. package/docs/components/menu.md +90 -0
  53. package/docs/components/modal.md +131 -0
  54. package/docs/components/notification.md +81 -0
  55. package/docs/components/search.md +117 -0
  56. package/docs/components/slides.md +85 -0
  57. package/docs/components/stepTabs.md +93 -0
  58. package/docs/components/steps.md +56 -0
  59. package/docs/components/summary.md +49 -0
  60. package/docs/components/table.md +42 -0
  61. package/docs/components/tooltip.md +53 -0
  62. package/docs/helper-javascript.md +71 -3
  63. package/docs/layout/body.md +41 -0
  64. package/docs/layout/flex.md +116 -0
  65. package/docs/layout/footer.md +71 -0
  66. package/docs/layout/grid.md +116 -0
  67. package/docs/layout/header.md +116 -0
  68. package/docs/layout/pageShell.md +94 -0
  69. package/docs/layout/section.md +69 -0
  70. package/docs/patterns/cookieConsent.md +89 -0
  71. package/package.json +2 -1
  72. package/scripts/generate-component-docs.js +557 -0
  73. package/templates/html/components/accordion.html +33 -4
  74. package/templates/html/components/badges.html +23 -0
  75. package/templates/html/components/breadcumbs.html +14 -0
  76. package/templates/html/components/button.html +22 -0
  77. package/templates/html/components/card.html +20 -0
  78. package/templates/html/components/dropdown.html +34 -0
  79. package/templates/html/components/form.html +82 -4
  80. package/templates/html/components/logo.html +22 -1
  81. package/templates/html/components/menu.html +40 -1
  82. package/templates/html/components/modal.html +44 -0
  83. package/templates/html/components/notification.html +68 -32
  84. package/templates/html/components/search.html +107 -0
  85. package/templates/html/components/slides.html +43 -0
  86. package/templates/html/components/stepTabs.html +47 -0
  87. package/templates/html/components/steps.html +24 -0
  88. package/templates/html/components/summary.html +27 -0
  89. package/templates/html/components/table.html +12 -0
  90. package/templates/html/components/tooltip.html +35 -0
  91. package/templates/html/layout/body.html +20 -5
  92. package/templates/html/layout/flex.html +20 -0
  93. package/templates/html/layout/footer.html +29 -1
  94. package/templates/html/layout/grid.html +20 -0
  95. package/templates/html/layout/header.html +52 -5
  96. package/templates/html/layout/pageShell.html +19 -0
  97. package/templates/html/layout/section.html +32 -10
  98. package/templates/html/patterns/cookieConsent.html +31 -0
  99. package/templates/react/components/form.jsx +3 -3
  100. package/templates/react/components/logo.jsx +1 -1
  101. package/templates/react/components/notification.jsx +4 -4
  102. package/templates/react/components/{searchbar.jsx → search.jsx} +9 -7
  103. package/templates/react/patterns/footer.jsx +1 -1
  104. package/templates/react/patterns/header.jsx +16 -10
  105. package/assets/scss/components/_searchbar.scss +0 -70
  106. package/templates/html/components/searchbar.html +0 -29
  107. package/templates/html/demo.js +0 -137
  108. /package/{templates/html → demo}/demo.css +0 -0
@@ -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
  }
@@ -4,6 +4,7 @@ export { pgs } from "./_pgs.js";
4
4
 
5
5
  //= BASE
6
6
  import "./base/_darkmode.js";
7
+ import "./base/_svg.js";
7
8
  import "./base/_object.js";
8
9
 
9
10
  //= CN
@@ -11,6 +12,7 @@ import "./components/_accordion.js";
11
12
  import "./components/_dropdown.js";
12
13
  import "./components/_menu.js"
13
14
  import "./components/_modals.js";
15
+ import "./components/_search.js";
14
16
  import "./components/_slides.js"
15
17
  import "./components/_steps.js";
16
18
  import "./components/_stepTabs.js";
@@ -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
 
@@ -93,9 +96,32 @@ function headerHeight() {
93
96
  document.documentElement.style.setProperty("--heightOfHeader", `${height}px`);
94
97
  document.documentElement.style.setProperty("--heightOfHeaderScroll", `${scrollHeight}px`);
95
98
  }
96
- headerHeight()
97
- window.addEventListener("resize", headerHeight);
98
- window.addEventListener("scroll", headerHeight);
99
+
100
+ // Il modulo può essere caricato nel footer: rimanda il primo calcolo al frame
101
+ // successivo, quando il browser ha già composto l'header, senza aspettare il
102
+ // caricamento completo della pagina.
103
+ let headerHeightRafId = 0;
104
+ function scheduleHeaderHeight() {
105
+ if (headerHeightRafId) return;
106
+
107
+ headerHeightRafId = requestAnimationFrame(() => {
108
+ headerHeightRafId = 0;
109
+ headerHeight();
110
+ });
111
+ }
112
+
113
+ if (header) {
114
+ const headerHeightObserver = new ResizeObserver(scheduleHeaderHeight);
115
+ headerHeightObserver.observe(header);
116
+
117
+ // Un font web può modificare la larghezza del menu e quindi l'altezza
118
+ // dell'header, anche dopo il primo frame.
119
+ document.fonts?.ready?.then(scheduleHeaderHeight);
120
+ }
121
+
122
+ scheduleHeaderHeight();
123
+ window.addEventListener("resize", scheduleHeaderHeight);
124
+ window.addEventListener("scroll", scheduleHeaderHeight, { passive: true });
99
125
 
100
126
 
101
127
 
@@ -125,7 +151,3 @@ window.addEventListener("scroll", () => {
125
151
 
126
152
  });
127
153
 
128
-
129
-
130
-
131
-
@@ -5,7 +5,7 @@
5
5
  :root {
6
6
  color-scheme: light;
7
7
 
8
- &[data-darkmode=true] {
8
+ &[pgs-state~=darkmode] {
9
9
  color-scheme: dark;
10
10
  }
11
11
 
@@ -21,10 +21,10 @@
21
21
  --color-white-transparent: color-mix(in srgb, var(--color-white) 50%, transparent 100%);
22
22
  --color-black-transparent: color-mix(in srgb, var(--color-black) 50%, transparent 100%);
23
23
  --color-text: light-dark(#4a4a4a, #e3e3e3);
24
- --color-box: light-dark(#F8F8F8, #3A3A3A);
25
- --color-boxDark: light-dark(#3A3A3A, #F8F8F8);
26
- --color-box-transparent: light-dark(color-mix(in srgb, #eeeeee 50%, transparent 50%), color-mix(in srgb, #3A3A3A 50%, transparent 50%));
27
- --color-boxDark-transparent: light-dark(color-mix(in srgb, #3A3A3A 50%, transparent 50%), color-mix(in srgb, #eeeeee 50%, transparent 50%));
24
+ --color-box: light-dark(#F8F8F8, #222121);
25
+ --color-boxDark: light-dark(#222121, #F8F8F8);
26
+ --color-box-transparent: light-dark(color-mix(in srgb, #eeeeee 50%, transparent 50%), color-mix(in srgb, #222121 50%, transparent 50%));
27
+ --color-boxDark-transparent: light-dark(color-mix(in srgb, #222121 50%, transparent 50%), color-mix(in srgb, #eeeeee 50%, transparent 50%));
28
28
  --color-linkBackgorud: light-dark(#a0dbff, #002a44);
29
29
  --color-background: light-dark(#ffffff, #080808);
30
30
  --color-whiteFixed: #FFFFFF;
@@ -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,7 +19,8 @@
19
19
  --text-shadow: 0px 0px 50px #000000;
20
20
  --backdrop: #0000003e;
21
21
  --blur: blur(20px);
22
- --page-top: calc(var(--heightOfHeaderScroll) + (var(--gap-elements)*2));
22
+ --page-top: calc(var(--heightOfHeader) + var(--heightOfHeader));
23
+ --page-topScroll: calc(var(--heightOfHeaderScroll) + var(--heightOfHeader));
23
24
  --page-width: 1280px;
24
25
  --page-space: clamp(var(--padding-page), calc((100% - var(--section-width)) / 2 + var(--padding-page)), 100%);
25
26
  --gap-texts: 1.0rem;
@@ -32,7 +33,8 @@
32
33
  --fa-size: inherit;
33
34
  --focus-visible: 3px solid var(--color-link);
34
35
 
35
- --heightOfHeader: 13.3rem; ///preload fittizio
36
+ --heightOfHeader: 6.8rem; ///preload fittizio
37
+ --heightOfHeaderScroll: 6.8rem; ///preload fittizio
36
38
 
37
39
  //- mobile
38
40
  @media (max-width: $mobile) {
@@ -3,6 +3,7 @@
3
3
  --dropdown-background: var(--color-box);
4
4
  --dropdown-color: var(--color-black);
5
5
  --dropdown-border: var(--border-complete);
6
+ --dropdown-borderRadius: var(--dropdown-padding);
6
7
  --dropdown-padding: 1rem;
7
8
  --dropdown-inline-size: max-content;
8
9
  --dropdown-max-inline-size: min(400px, calc(100vw - 16px));
@@ -28,7 +29,7 @@
28
29
  overflow: auto;
29
30
  padding: var(--dropdown-padding);
30
31
  border: var(--dropdown-border);
31
- border-radius: calc(var(--border-radius-input) + var(--dropdown-padding));
32
+ border-radius: var(--dropdown-borderRadius);
32
33
  background: var(--dropdown-background);
33
34
  color: var(--dropdown-color);
34
35
  }
@@ -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
  }
@@ -8,12 +8,12 @@
8
8
  --logo-finter: invert(1) hue-rotate(180deg) brightness(1.5);
9
9
 
10
10
  //== DARKMODE
11
- @at-root [data-darkmode=true] [pgs~="logo-darkmode"] [pgs~="logo-image"] {
11
+ @at-root [pgs-state~=darkmode] #{&}[pgs-option~="logoDarkmode"] [pgs~="logo-image"] {
12
12
  filter: var(--logo-finter);
13
13
  }
14
14
 
15
15
  //== FIXED DARKMODE
16
- &[pgs~="logo-darkmodeFixed"][pgs~="logo-darkmode"] [pgs~="logo-image"] {
16
+ &[pgs-option~="logoDarkmodeFixed"] [pgs~="logo-image"] {
17
17
  filter: var(--logo-finter);
18
18
  }
19
19
 
@@ -10,10 +10,6 @@
10
10
  row-gap: 1.0rem;
11
11
  flex-wrap: nowrap;
12
12
 
13
- ul {
14
- display: none;
15
- }
16
-
17
13
  //== Content
18
14
  >li {
19
15
  >a {
@@ -30,6 +26,20 @@
30
26
  li {
31
27
  width: -webkit-fill-available;
32
28
  }
29
+
30
+ &[pgs-state~=open]>ul {
31
+ display: flex;
32
+ }
33
+ }
34
+
35
+ //== submenu
36
+ ul {
37
+ display: none;
38
+ flex-direction: column;
39
+ gap: var(--gap-texts);
40
+ --dropdown-borderRadius: calc(var(--border-radius-input) + var(--dropdown-padding));
41
+ --dropdown-background: var(--color-box-transparent);
42
+ --dropdown-display: flex;
33
43
  }
34
44
  }
35
45
 
@@ -45,8 +55,12 @@
45
55
  cursor: pointer;
46
56
  translate: -15px;
47
57
 
48
- &[aria-expanded="true"] span {
49
- rotate: 180deg;
58
+ &[aria-expanded="true"] {
59
+ --button-background: var(--color-primary);
60
+
61
+ span {
62
+ rotate: 180deg;
63
+ }
50
64
  }
51
65
 
52
66
  span {
@@ -67,25 +81,9 @@
67
81
 
68
82
  //=== Sub menu
69
83
  >li:has(ul) {
70
- --dropdown-display: flex;
71
84
  display: flex;
72
85
  gap: 0.2rem;
73
86
  flex-wrap: nowrap;
74
-
75
- >a {
76
- border-radius: var(--border-radius-input);
77
- // box-shadow: var(--box-shadow);
78
- }
79
-
80
- ul {
81
- li a {
82
- min-width: 100% !important;
83
- }
84
- }
85
-
86
- &[pgs-state~=open]>ul {
87
- display: flex;
88
- }
89
87
  }
90
88
  }
91
89
  }
@@ -112,13 +110,8 @@
112
110
  align-items: center;
113
111
  position: relative;
114
112
 
115
- >a {
116
- max-width: calc(100% - var(--gap-texts) - 40px);
117
- }
118
-
119
113
  >ul {
120
114
  flex-basis: 100%;
121
- // --dropdown-maxwidth: 100%;
122
115
  }
123
116
 
124
117
  &:not([pgs-state~=open]) ul {
@@ -79,7 +79,7 @@ dialog[pgs~="modal-dialog"] {
79
79
  &:has([pgs~="modal-dialog-content-scroll"]) {
80
80
  max-height: calc(90svh - var(--heightOfHeader));
81
81
  overflow: hidden;
82
-
82
+
83
83
  [pgs~="modal-dialog-content-scroll"] {
84
84
  padding-top: calc(var(--padding) / 2);
85
85
  overflow: auto;
@@ -101,6 +101,16 @@ dialog[pgs~="modal-dialog"] {
101
101
  }
102
102
 
103
103
  //#OPTION
104
+ //== topLevel
105
+ &[pgs-option~="topLevel"] {
106
+ align-items: center;
107
+ padding-inline: 1rem;
108
+
109
+ [pgs~="modal-dialog-content"] {
110
+ width: min(600px, 100%);
111
+ }
112
+ }
113
+
104
114
  //== LEFT
105
115
  &[pgs-option~="left"] {
106
116
  [pgs~="modal-dialog-content"] {
@@ -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
  }