mypgs 1.5.0 → 1.6.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 (48) hide show
  1. package/AGENTS.md +6 -3
  2. package/README.md +22 -373
  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/_menu.js +1 -3
  8. package/assets/javascript/components/_search.js +391 -0
  9. package/assets/javascript/index.js +2 -0
  10. package/assets/javascript/layout/_header.js +26 -7
  11. package/assets/scss/base/_color.scss +8 -15
  12. package/assets/scss/base/_general.scss +36 -48
  13. package/assets/scss/base/_heading.scss +14 -16
  14. package/assets/scss/base/_variables.scss +4 -2
  15. package/assets/scss/components/_card.scss +10 -0
  16. package/assets/scss/components/_dropdown.scss +2 -1
  17. package/assets/scss/components/_logo.scss +2 -2
  18. package/assets/scss/components/_menu.scss +20 -27
  19. package/assets/scss/components/_modals.scss +11 -1
  20. package/assets/scss/components/_search.scss +134 -0
  21. package/assets/scss/index.scss +8 -4
  22. package/assets/scss/layout/_header.scss +1 -1
  23. package/assets/scss/layout/_pageShell.scss +1 -0
  24. package/dist/css/index.css +658 -620
  25. package/dist/css/index.css.map +1 -1
  26. package/dist/css/index.min.css +1 -1
  27. package/dist/index.d.ts +78 -0
  28. package/dist/javascript/index.js +904 -370
  29. package/dist/javascript/index.js.map +1 -1
  30. package/dist/javascript/index.min.js +1 -1
  31. package/docs/componenti-e-markup.md +90 -0
  32. package/docs/convenzioni.md +12 -0
  33. package/docs/export-e-sviluppo.md +109 -0
  34. package/docs/helper-javascript.md +127 -0
  35. package/docs/utilizzo-css-scss.md +36 -0
  36. package/package.json +1 -6
  37. package/plugins/vite-plugin-pgs.d.ts +10 -0
  38. package/templates/html/components/logo.html +1 -1
  39. package/templates/html/components/menu.html +13 -1
  40. package/templates/html/components/{searchbar.html → search.html} +7 -5
  41. package/templates/html/demo.js +1 -8
  42. package/templates/html/layout/header.html +11 -5
  43. package/templates/react/components/logo.jsx +1 -1
  44. package/templates/react/components/{searchbar.jsx → search.jsx} +9 -7
  45. package/templates/react/patterns/header.jsx +16 -10
  46. package/assets/scss/components/_searchbar.scss +0 -70
  47. package/react.d.ts +0 -11
  48. package/react.js +0 -1
package/AGENTS.md CHANGED
@@ -8,7 +8,7 @@ This guide is for any AI/Codex agent that initializes or modifies a project base
8
8
 
9
9
  - HTML `pgs` attributes as the contract between markup, SCSS, and JavaScript;
10
10
  - SCSS sources with base styles, layouts, components, patterns, CSS variables, and mixins;
11
- - JavaScript modules for recurring behaviors such as accordions, dropdowns, menus, modals, slides, steps, step tabs, notifications, header, cookie consent, and dark mode;
11
+ - JavaScript modules for recurring behaviors such as accordions, dropdowns, menus, modals, search suggestions, slides, steps, step tabs, notifications, header, cookie consent, and dark mode;
12
12
  - example HTML templates in `templates/`;
13
13
  - compiled assets in `dist/`.
14
14
 
@@ -26,7 +26,7 @@ Write custom code only when the pattern does not exist, or when you are adding a
26
26
  ## 2. General Usage Rules
27
27
 
28
28
  - Use `mypgs` as the first choice for layouts, components, helpers, variables, utilities, and available patterns.
29
- - Do not recreate existing components from scratch: buttons, forms, dropdowns, modals, menus, slides, accordions, steps, stepTabs, notifications, tooltips, tables, searchbars, logos, headers, footers, and cookie consent.
29
+ - Do not recreate existing components from scratch: buttons, forms, dropdowns, modals, menus, slides, accordions, steps, stepTabs, notifications, tooltips, tables, search, logos, headers, footers, and cookie consent.
30
30
  - Do not duplicate logic already handled by the `mypgs` JS modules, such as modal open/close, accordion state, Popover API dropdowns, step tabs, notifications, or form validation.
31
31
  - Keep `pgs` tokens in markup, SCSS selectors, and JS queries consistent.
32
32
  - Prefer composing `pgs` tokens over adding new CSS classes.
@@ -52,6 +52,7 @@ Files analyzed:
52
52
  - `assets/javascript/components/_steps.js`
53
53
  - `assets/javascript/components/_stepTabs.js`
54
54
  - `assets/javascript/components/_notifications.js`
55
+ - `assets/javascript/components/_search.js`
55
56
  - `assets/javascript/functions/_formValidate.js`
56
57
  - `assets/javascript/functions/_scrollY.js`
57
58
  - `assets/javascript/patterns/_header.js`
@@ -74,6 +75,7 @@ Patterns found:
74
75
  - Components use a root token and child tokens with a consistent prefix. Use `templates/html/components/` as the canonical markup source.
75
76
 
76
77
  - Runtime states use `pgs-state`, for example `open`, `is-active`, `is-completed`, `is-locked`, `success`, `error`, `warning`, and `info`.
78
+ - La ricerca componibile usa esclusivamente `pgs="search"` come root grafico e comportamentale e il figlio opzionale `pgs="search-suggestions"`. La sorgente dati si configura tramite `pgs.search.api(element)?.configure({ source })` e deve restare indipendente dal backend.
77
79
  - Configurable options use `pgs-option`, with simple tokens or values inside square brackets. Prefer copying the current option syntax from the relevant template rather than duplicating examples in this guide.
78
80
 
79
81
  - Naming is mostly camelCase for compound tokens (`menuHorizontal`, `buttonStrong`, `flexColumnElements`) and kebab-like for component sub-elements (`accordion-button`, `modal-dialog-content`, `cookieConsent-actionAccept`).
@@ -186,6 +188,7 @@ Recommended direct access:
186
188
  ```js
187
189
  pgs.notification.toast.success("Saved");
188
190
  pgs.modal.api(modalEl)?.open();
191
+ pgs.search.api(searchEl)?.setSource(async ({ query, signal }) => []);
189
192
  ```
190
193
 
191
194
  `assets/javascript/_imports.js` registers modules with `pgs.registerModules`:
@@ -224,7 +227,7 @@ Use the templates as the single source of truth for component and layout markup.
224
227
  Canonical template references:
225
228
 
226
229
  - Layouts: `templates/html/layout/body.html`, `templates/html/layout/flex.html`, `templates/html/layout/grid.html`, `templates/html/layout/pageShell.html`, `templates/html/layout/section.html`
227
- - Components: `templates/html/components/accordion.html`, `templates/html/components/breadcumbs.html`, `templates/html/components/button.html`, `templates/html/components/card.html`, `templates/html/components/dropdown.html`, `templates/html/components/form.html`, `templates/html/components/logo.html`, `templates/html/components/menu.html`, `templates/html/components/modal.html`, `templates/html/components/notification.html`, `templates/html/components/searchbar.html`, `templates/html/components/slides.html`, `templates/html/components/stepTabs.html`, `templates/html/components/steps.html`, `templates/html/components/table.html`, `templates/html/components/tooltip.html`
230
+ - Components: `templates/html/components/accordion.html`, `templates/html/components/breadcumbs.html`, `templates/html/components/button.html`, `templates/html/components/card.html`, `templates/html/components/dropdown.html`, `templates/html/components/form.html`, `templates/html/components/logo.html`, `templates/html/components/menu.html`, `templates/html/components/modal.html`, `templates/html/components/notification.html`, `templates/html/components/search.html`, `templates/html/components/slides.html`, `templates/html/components/stepTabs.html`, `templates/html/components/steps.html`, `templates/html/components/table.html`, `templates/html/components/tooltip.html`
228
231
  - Patterns: `templates/html/patterns/cookieConsent.html`, `templates/html/patterns/footer.html`, `templates/html/patterns/header.html`
229
232
  - Complete demo assembly. DO NOT use this for inspiration. It is only used to show all the modules: `templates/demo.html`
230
233
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  `mypgs` e' una libreria frontend condivisa per costruire interfacce coerenti tramite attributi `pgs`, SCSS sorgenti, componenti UI e comportamenti JavaScript riutilizzabili.
4
4
 
5
- La libreria nasce come base di design system: layout, spacing, colori, bottoni, form, menu, modali, dropdown, slides, notifiche e pattern ricorrenti vengono definiti una volta sola e riusati nei progetti.
5
+ La libreria nasce come base di design system: layout, spacing, colori, bottoni, form, menu, modali, dropdown, ricerca con suggerimenti, slides, notifiche e pattern ricorrenti vengono definiti una volta sola e riusati nei progetti.
6
6
 
7
7
  ## Cosa contiene
8
8
 
@@ -12,40 +12,35 @@ La libreria nasce come base di design system: layout, spacing, colori, bottoni,
12
12
  - `dist/css/`: CSS compilato.
13
13
  - `dist/javascript/`: bundle JavaScript compilato.
14
14
  - `dist/index.d.ts`: dichiarazioni TypeScript esportate dal pacchetto.
15
- - `AI_GUIDELINES.md`: guida operativa per AI/Codex.
16
- - `AI_GUIDELINES_EN.md`: versione inglese della guida.
15
+ - `AGENTS.md`: guida operativa per AI.
17
16
 
18
17
  ## Installazione
19
18
 
20
- Da registry npm:
19
+ Da registry **npm**:
21
20
 
22
21
  ```bash
23
22
  npm install mypgs
24
23
  ```
25
24
 
26
- ## Uso rapido
27
-
28
- Importa JavaScript e CSS compilato nell'entrypoint del progetto:
25
+ ### JavaScript
29
26
 
30
27
  ```js
31
28
  import "mypgs";
32
- import "mypgs/style.css";
33
29
  ```
34
30
 
35
31
  Se ti serve accedere direttamente all'helper:
36
32
 
37
33
  ```js
38
34
  import { pgs } from "mypgs";
39
- import "mypgs/style.css";
40
35
  ```
41
36
 
42
- In progetti React/TSX con Vite, abilita i tipi JSX e il plugin che converte `pgsHtml` in `pgs`:
37
+ **React/TSX con Vite:**
43
38
 
44
- ```ts
45
- import "mypgs/react";
46
- ```
39
+ Configura il plugin che converte `pgsHtml` in `pgs`:
47
40
 
48
41
  ```ts
42
+ // vite.config.ts
43
+ import { defineConfig } from 'vite'
49
44
  import react from "@vitejs/plugin-react";
50
45
  import pgsVite from "mypgs/vite-plugin-pgs";
51
46
 
@@ -54,19 +49,7 @@ export default {
54
49
  };
55
50
  ```
56
51
 
57
- Markup minimo consigliato:
58
-
59
- ```html
60
- <html lang="it" pgs="htmlBase initP">
61
- <body pgs="bodyBase bodyImg bodyText bodyHeading">
62
- <main pgs="main"></main>
63
- </body>
64
- </html>
65
- ```
66
-
67
- `initP` e' importante: molti layout, componenti e pattern SCSS sono definiti sotto `[pgs~=initP]`.
68
-
69
- ## Uso SCSS sorgente
52
+ ### SCSS
70
53
 
71
54
  Se il progetto vuole compilare un CSS unico, importa gli SCSS sorgenti:
72
55
 
@@ -82,356 +65,22 @@ Se servono solo i mixin:
82
65
  @use "../../node_modules/mypgs/assets/scss/mixin/mixin.scss" as * ;
83
66
  ```
84
67
 
85
- La libreria espone molte custom properties da preferire agli hardcode, per esempio:
86
-
87
- ```scss
88
- :root {
89
- --color-primary: #5c7d6f;
90
- --padding: 30px;
91
- --gap-texts: 1rem;
92
- --gap-elements: 4rem;
93
- --border-radius: 4.5rem;
94
- --border-radius-input: 2.25rem;
95
- }
96
- ```
97
-
98
- Override consigliato:
68
+ ### Markup
99
69
 
100
- ```scss
101
- #danger-action {
102
- --button-background: var(--color-error);
103
- --button-color: var(--color-whiteFixed);
104
- }
105
- ```
106
-
107
- Evita di riscrivere da zero padding, gap, border-radius o colori se esiste gia' una variabile o un token PGS adatto.
108
-
109
- ## Il sistema `pgs`
110
-
111
- Il markup usa token separati da spazio dentro l'attributo `pgs`:
70
+ `initP` e' importante: tutti i layout, componenti e pattern SCSS sono definiti sotto `[pgs~=initP]`.
112
71
 
113
72
  ```html
114
- <button pgs="button buttonStrong" type="button">Salva</button>
115
- <section pgs="section flexColumnElements"></section>
116
- ```
117
-
118
- Gli stessi token collegano HTML, SCSS e JavaScript.
119
-
120
- ### Helper JavaScript
121
-
122
- `pgs(root)` permette di cercare e modificare token PGS senza scrivere selettori manuali:
123
-
124
- ```js
125
- const modal = pgs(document).querySelector("modal");
126
-
127
- pgs(modal).contains("modal");
128
- pgs(modal).add("custom-token");
129
- pgs(modal).remove("custom-token");
130
- pgs(modal).toggle("custom-token", true);
131
- ```
132
-
133
- Stati runtime:
134
-
135
- ```js
136
- pgs(modal).state.add("open");
137
- pgs(modal).state.toggle("open", false);
138
- pgs(modal).state.contains("open");
139
- ```
140
-
141
- Opzioni:
142
-
143
- ```js
144
- pgs(modal).option.contains("history");
145
- pgs(modal).option.getValueBrackets("containerID");
146
- ```
147
-
148
- Esempio markup con opzioni:
149
-
150
- ```html
151
- <div pgs="modal" pgs-option="containerID[modal-container]"></div>
152
- <div pgs="slides" pgs-option="singleScroll shadowDesktop"></div>
153
- ```
154
-
155
- ## JavaScript inizializzato automaticamente
156
-
157
- Importando `mypgs`, l'entrypoint inizializza:
158
-
159
- - helper globale `pgs`
160
- - dark mode
161
- - gestione object SVG
162
- - accordion
163
- - dropdown
164
- - menu
165
- - modali
166
- - slides
167
- - steps
168
- - step tabs
169
- - notifiche
170
- - header
171
- - cookie consent
172
-
173
- I componenti inizializzati usano `WeakMap` interne per esporre API di istanza.
174
-
175
- ## API dei moduli
176
-
177
- I moduli principali sono registrati in `assets/javascript/_imports.js` in due modi.
178
-
179
- ### Registro diretto
180
-
181
- Serve per usare i moduli direttamente da `pgs`:
182
-
183
- ```js
184
- pgs.registerModules({
185
- accordion: PGS_accordion,
186
- dropdown: PGS_dropdown,
187
- menu: PGS_menu,
188
- modal: PGS_modal,
189
- notification: PGS_notification,
190
- slides: PGS_slides,
191
- stepTabs: PGS_stepTabs,
192
- steps: PGS_steps,
193
- formValidate: PGS_formValidate,
194
- scrollHorizontal: PGS_scrollHorizontal,
195
- });
196
- ```
197
-
198
- Uso consigliato:
199
-
200
- ```js
201
- pgs.notification.toast.success("Salvato");
202
- pgs.modal.api(modalEl)?.open();
203
- pgs.dropdown.api(dropdownEl)?.close();
204
- pgs.slides.api(slidesEl)?.next();
205
- ```
206
-
207
- Shortcut disponibili dopo `import "mypgs"`:
208
-
209
- - `pgs.accordion`
210
- - `pgs.dropdown`
211
- - `pgs.menu`
212
- - `pgs.modal`
213
- - `pgs.notification`
214
- - `pgs.slides`
215
- - `pgs.stepTabs`
216
- - `pgs.steps`
217
- - `pgs.formValidate`
218
- - `pgs.scrollHorizontal`
219
-
220
- ## Struttura dei moduli componente
221
-
222
- I componenti con istanze seguono questo schema:
223
-
224
- ```js
225
- export const PGS_modal = {
226
- init: PGS_modal_init,
227
- api: PGS_modal_api
228
- };
229
- ```
230
-
231
- - `PGS_name`: nome ufficiale del modulo per il registro legacy.
232
- - `init`: inizializza o reinizializza markup, utile dopo contenuti dinamici.
233
- - `api`: recupera l'API di una singola istanza gia' inizializzata.
234
-
235
- Esempio:
236
-
237
- ```js
238
- pgs.modal.init();
239
- pgs.modal.init(container);
240
- pgs.modal.api(modalEl)?.open();
241
- ```
242
-
243
- `PGS_notification` e' un caso diverso: funziona piu' come service/helper e espone `alert`, `toast` e `trigger`.
244
-
245
- ## Componenti e markup
246
-
247
- I template completi sono in `templates/html/components/`, `templates/html/patterns/` e `templates/html/layout/`. Usa quei file come sorgente di riferimento prima di creare markup nuovo.
248
-
249
- ## Componenti disponibili
250
-
251
- Layout e utility:
252
-
253
- - `main`
254
- - `section`
255
- - `sectionFull`
256
- - `sectionMax`
257
- - `sectionNoPadding`
258
- - `container`
259
- - `pageShell`
260
- - `aside`
261
- - `flexColumn`
262
- - `flexColumnTexts`
263
- - `flexColumnElements`
264
- - `flexColumnSections`
265
- - `flexRow`
266
- - `grid-*`
267
- - `gapTexts`
268
- - `gapElements`
269
- - `gapSections`
270
- - `card`
271
- - `boxtext`
272
-
273
- Componenti:
274
-
275
- - `button`
276
- - `buttonStrong`
277
- - `buttonIcon`
278
- - `buttonMini`
279
- - `buttonBig`
280
- - `buttonClose`
281
- - `form`
282
- - `input`
283
- - `textarea`
284
- - `select`
285
- - `toggle`
286
- - `checkbox`
287
- - `radio`
288
- - `dropdown`
289
- - `tooltip`
290
- - `modal`
291
- - `accordion`
292
- - `slides`
293
- - `steps`
294
- - `stepTabs`
295
- - `notification`
296
- - `toast`
297
- - `table`
298
- - `breadcrumb`
299
- - `searchbar`
300
- - `logo`
301
- - `menuHorizontal`
302
- - `menuVertical`
303
- - `menuFooter`
304
-
305
- Pattern:
306
-
307
- - `header`
308
- - `footer`
309
- - `cookieConsent`
310
-
311
- ## Export npm
312
-
313
- Il pacchetto espone:
314
-
315
- ```json
316
- {
317
- ".": {
318
- "types": "./dist/index.d.ts",
319
- "import": "./assets/javascript/index.js",
320
- "default": "./dist/javascript/index.js"
321
- },
322
- "./style.css": "./dist/css/index.css",
323
- "./style.min.css": "./dist/css/index.min.css",
324
- "./react": {
325
- "types": "./react.d.ts",
326
- "import": "./react.js",
327
- "default": "./react.js"
328
- },
329
- "./vite-plugin-pgs": {
330
- "types": "./plugins/vite-plugin-pgs.d.ts",
331
- "import": "./plugins/vite-plugin-pgs.js",
332
- "default": "./plugins/vite-plugin-pgs.js"
333
- }
334
- }
335
- ```
336
-
337
- Uso compilato:
338
-
339
- ```js
340
- import "mypgs";
341
- import "mypgs/style.css";
342
- ```
343
-
344
- Uso sorgente SCSS:
345
-
346
- ```scss
347
- @use "sass:meta";
348
- @use "../../node_modules/mypgs/assets/scss/mixin/mixin.scss" as * ;
349
- @include meta.load-css("../../node_modules/mypgs/assets/scss/index.scss");
350
- ```
351
-
352
- ## Sviluppo
353
-
354
- Build una tantum:
355
-
356
- ```bash
357
- npm run start
358
- ```
359
-
360
- Build in watch mode:
361
-
362
- ```bash
363
- npm run "start watch"
364
- ```
365
-
366
- Creare un pacchetto locale:
367
-
368
- ```bash
369
- npm pack
370
- ```
371
-
372
- Flusso consigliato quando modifichi la libreria:
373
-
374
- 1. modifica i sorgenti in `assets/`;
375
- 2. aggiorna template o documentazione se cambia il modo d'uso;
376
- 3. ricompila con `npm run start`;
377
- 4. verifica `dist/`;
378
- 5. crea il pacchetto con `npm pack`;
379
- 6. installa il `.tgz` nel progetto che consuma la libreria.
380
-
381
- Nota: se la build Webpack fallisce, non modificare manualmente `dist/javascript` come sorgente primaria. Sistema la toolchain e rigenera gli asset compilati.
382
-
383
- ## Aggiungere un nuovo modulo
384
-
385
- Esempio componente:
386
-
387
- ```js
388
- export function PGS_myComponent_init(root = document) {
389
- pgs(root).querySelectorAll("myComponent").forEach((element) => {
390
- // init
391
- });
392
- }
393
-
394
- export function PGS_myComponent_api(element) {
395
- // return instance API
396
- }
397
-
398
- export const PGS_myComponent = {
399
- PGS_name: "PGS_myComponent",
400
- init: PGS_myComponent_init,
401
- api: PGS_myComponent_api
402
- };
403
- ```
404
-
405
- Registrazione in `assets/javascript/_imports.js`:
406
-
407
- ```js
408
- import { PGS_myComponent } from "./components/_myComponent.js";
409
-
410
- pgs.registerImport({
411
- PGS_myComponent,
412
- });
413
-
414
- pgs.registerModules({
415
- myComponent: PGS_myComponent,
416
- });
417
- ```
418
-
419
- Uso:
420
-
421
- ```js
422
- pgs.myComponent.init();
423
- pgs.myComponent.api(element);
73
+ <html lang="it" pgs="htmlBase initP">
74
+ <body pgs="bodyBase bodyImg bodyText bodyHeading">
75
+ <main pgs="main"></main>
76
+ </body>
77
+ </html>
424
78
  ```
425
79
 
426
- ## Convenzioni
80
+ ## Documentazione
427
81
 
428
- - Usa `pgs` come prima scelta per markup, layout, componenti e comportamenti.
429
- - Mantieni coerenti i token tra template, SCSS e JS.
430
- - Usa `pgs-state` per stati runtime.
431
- - Usa `pgs-option` per opzioni dichiarative.
432
- - Preferisci custom properties e mixin a CSS hardcoded.
433
- - Non duplicare componenti gia' presenti nella libreria.
434
- - Non inventare API: verifica i sorgenti in `assets/javascript/`.
435
- - Mantieni in `mypgs` solo stili e comportamenti riutilizzabili.
436
- - Mantieni nel progetto finale le personalizzazioni specifiche del progetto.
437
- - Aggiorna `AI_GUIDELINES.md` quando introduci pattern importanti.
82
+ - [Utilizzo CSS/SCSS](docs/utilizzo-css-scss.md)
83
+ - [Helper JavaScript](docs/helper-javascript.md)
84
+ - [Componenti e markup](docs/componenti-e-markup.md)
85
+ - [Export npm e sviluppo](docs/export-e-sviluppo.md)
86
+ - [Convenzioni](docs/convenzioni.md)
@@ -1,10 +1,12 @@
1
1
  import { pgs } from "./_pgs.js";
2
2
 
3
+ import { PGS_svg } from "./base/_svg.js";
3
4
  import { PGS_accordion } from "./components/_accordion.js";
4
5
  import { PGS_dropdown } from "./components/_dropdown.js";
5
6
  import { PGS_menu } from "./components/_menu.js";
6
7
  import { PGS_modal } from "./components/_modals.js";
7
8
  import { PGS_notification } from "./components/_notifications.js";
9
+ import { PGS_search } from "./components/_search.js";
8
10
  import { PGS_slides } from "./components/_slides.js";
9
11
  import { PGS_stepTabs } from "./components/_stepTabs.js";
10
12
  import { PGS_steps } from "./components/_steps.js";
@@ -13,11 +15,13 @@ import { PGS_formValidate } from "./functions/_formValidate.js";
13
15
  import { PGS_scrollHorizontal } from "./functions/_scrollY.js";
14
16
 
15
17
  pgs.registerModules({
18
+ svg: PGS_svg,
16
19
  accordion: PGS_accordion,
17
20
  dropdown: PGS_dropdown,
18
21
  menu: PGS_menu,
19
22
  modal: PGS_modal,
20
23
  notification: PGS_notification,
24
+ search: PGS_search,
21
25
  slides: PGS_slides,
22
26
  stepTabs: PGS_stepTabs,
23
27
  steps: PGS_steps,
@@ -185,10 +185,56 @@ export function pgs(root) {
185
185
  function createOption(attribute) {
186
186
  if (!canAttr) return undefined;
187
187
 
188
+ const read = () => (root.getAttribute(attribute) || "").match(/[^\s[\]]+(?:\[[^\]]*\])?/g) || [];
189
+ const write = values => root.setAttribute(attribute, values.join(" "));
190
+ const getKey = value => String(value).trim().match(/^[^\s[\]]+/)?.[0] || "";
191
+ const getValues = values => values
192
+ .flat()
193
+ .flatMap(value => String(value).match(/[^\s[\]]+(?:\[[^\]]*\])?/g) || [])
194
+ .filter(Boolean);
195
+
188
196
  function api() {
189
197
  return api;
190
198
  }
191
199
 
200
+ api.add = function (...values) {
201
+ const current = read();
202
+
203
+ getValues(values).forEach(value => {
204
+ if (!current.includes(value)) current.push(value);
205
+ });
206
+
207
+ write(current);
208
+ return api;
209
+ };
210
+
211
+ api.remove = function (...values) {
212
+ const keys = getValues(values).map(getKey).filter(Boolean);
213
+ write(read().filter(value => !keys.includes(getKey(value))));
214
+ return api;
215
+ };
216
+
217
+ api.toggle = function (value, force) {
218
+ const key = getKey(value);
219
+ if (!key) return false;
220
+
221
+ const exists = api.contains(key);
222
+
223
+ if (force !== undefined) {
224
+ if (force && !exists) api.add(value);
225
+ if (!force && exists) api.remove(key);
226
+ return !!force;
227
+ }
228
+
229
+ if (exists) {
230
+ api.remove(key);
231
+ return false;
232
+ }
233
+
234
+ api.add(value);
235
+ return true;
236
+ };
237
+
192
238
  api.contains = function (key) {
193
239
  const source = root.getAttribute(attribute) || "";
194
240
  const safeKey = String(key).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -208,6 +254,18 @@ export function pgs(root) {
208
254
  return match ? match[1] : undefined;
209
255
  };
210
256
 
257
+ api.setValueBrackets = function (key, value = "") {
258
+ const optionKey = getKey(key);
259
+ if (!optionKey) return api;
260
+
261
+ const option = `${optionKey}[${String(value).trim()}]`;
262
+ const options = read().filter(item => getKey(item) !== optionKey);
263
+
264
+ options.push(option);
265
+ write(options);
266
+ return api;
267
+ };
268
+
211
269
  Object.defineProperty(api, "value", {
212
270
  get() { return root.getAttribute(attribute); },
213
271
  set(v) { root.setAttribute(attribute, v); }