@massimo-cassandro/minimo 0.10.11 → 0.11.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 (27) hide show
  1. package/design-tokens/components/snackbar.minimo.tokens.jsonc +106 -12
  2. package/design-tokens/shadows.minimo.tokens.jsonc +19 -0
  3. package/design-tokens/z-index.minimo.tokens.jsonc +4 -0
  4. package/design-tokens-src/_readme.md +1 -1
  5. package/design-tokens-src/badge.minimo.tokens.mjs +36 -0
  6. package/design-tokens-src/btn-close.minimo.tokens.mjs +101 -0
  7. package/design-tokens-src/components/snackbar.minimo.tokens.mjs +113 -21
  8. package/design-tokens-src/flex-grid.minimo.tokens.mjs +18 -0
  9. package/design-tokens-src/shadows.minimo.tokens.mjs +16 -0
  10. package/design-tokens-src/z-index.minimo.tokens.mjs +14 -0
  11. package/design-tokens-utilities/build-tokens-src/transforms.mjs +2 -1
  12. package/package.json +1 -1
  13. package/src/components/snackbar/snackbar.js +56 -62
  14. package/src/components/snackbar/snackbar.module.css +79 -49
  15. package/src/css/buttons/btn-close.css +3 -2
  16. package/src/css/forms/forms.css +1 -0
  17. package/src/custom-properties.css +22 -4
  18. package/src/web-components/s-datatable-component/docs.md +187 -0
  19. package/src/web-components/s-datatable-component/s-datatable-component.js +517 -0
  20. package/src/web-components/{simple-datatable/simple-datatable.module.css → s-datatable-component/s-datatable-component.module.css} +1 -1
  21. package/src/web-components/{simple-datatable → s-datatable-component}/src/parse-cols.js +1 -1
  22. package/design-tokens-src/badge.minimo.tokens.jsonc +0 -36
  23. package/design-tokens-src/btn-close.minimo.tokens.jsonc +0 -101
  24. package/design-tokens-src/flex-grid.minimo.tokens.jsonc +0 -18
  25. package/design-tokens-src/gradients-shadowes.minimo.tokens.jsonc +0 -4
  26. package/design-tokens-src/z-index.minimo.tokens.jsonc +0 -8
  27. package/src/web-components/simple-datatable/simple-datatable.js +0 -218
@@ -0,0 +1,517 @@
1
+ import { DataTable } from 'simple-datatables';
2
+
3
+ import { parseCols } from './src/parse-cols.js';
4
+
5
+ import * as styles from './s-datatable-component.module.css';
6
+
7
+ import caretLeftIcon from '../../icons/caret-left.svg?inline';
8
+ import caretRightIcon from '../../icons/caret-right.svg?inline';
9
+
10
+
11
+ /**
12
+ * Impementazione di simple-datatable (https://fiduswriter.github.io/simple-datatables/documentation/)
13
+ * per generare una tabella da dati json e da un oggetto `cols` di configurazione
14
+ *
15
+ * ─────────────────────────────────────────────────────────────────────────────
16
+ * PARAMETRI
17
+ * ─────────────────────────────────────────────────────────────────────────────
18
+ * Tutti i parametri sono leggibili sia da attributo HTML che da script (init).
19
+ * Ordine di precedenza: script > attributo HTML > default interno.
20
+ *
21
+ * @typedef {object} ColDefinition
22
+ * @property {string} _heading Intestazione della colonna (obbligatorio).
23
+ * @property {string} _field Chiave del campo nell'oggetto dato (obbligatorio).
24
+ * @property {string} [_title] Testo del tooltip sull'intestazione.
25
+ * @property {string} [_renderTpl] Template HTML per il contenuto della cella.
26
+ * I segnaposto `[[key]]` vengono sostituiti con i
27
+ * valori corrispondenti dell'oggetto riga.
28
+ * @property {'id'|'email'|'boolean'|'sf_datetime'} [_renderMode]
29
+ * Modalità di visualizzazione predefinita:
30
+ * - `id` – colonna numerica, non ricercabile, allineata a destra
31
+ * - `email` – inserisce andate a capo prima e dopo la `@`
32
+ * - `boolean` – icona segno di spunta / croce con colore semantico
33
+ * - `sf_datetime` – data e ora da oggetto Symfony (con pre-elaborazione in `_load`)
34
+ *
35
+ * @param {string} json URL da cui recuperare i dati (struttura attesa: `{ data: [...] }`).
36
+ * Ignorato se `data` è presente.
37
+ * Eventuali altre chiavi aggiuntive (oltre a `data`) vengono ignorate
38
+ *
39
+ * @param {Array<object>} data Dati inline, come array di oggetti plain.
40
+ * Ha precedenza su `json` se entrambi sono specificati.
41
+ * Come attributo HTML è utile principalmente in contesti SSR
42
+ * (Twig, Blade, ecc.) dove il JSON viene serializzato server-side;
43
+ * per grandi dataset è preferibile `json`.
44
+ *
45
+ * @param {ColDefinition[]} cols Definizione delle colonne. Le chiavi con prefisso `_` sono
46
+ * proprietà di questo componente; le restanti vengono passate
47
+ * direttamente a simple-datatables (es. `sortable`, `searchable`).
48
+ * Default: `[]`
49
+ *
50
+ * @param {number} perPage Numero di righe per pagina.
51
+ * Default: `25`
52
+ */
53
+
54
+
55
+
56
+ /**
57
+ * getNestedValue
58
+ *
59
+ * Legge un valore da un oggetto tramite un percorso di chiavi separate da punto.
60
+ * Supporta sia chiavi semplici ('commessa') che composte ('owner.nome').
61
+ * Restituisce undefined se una chiave intermedia non esiste.
62
+ *
63
+ * Esempi:
64
+ * getNestedValue(row, 'commessa') → row.commessa
65
+ * getNestedValue(row, 'owner.nome') → row.owner.nome
66
+ * getNestedValue(row, 'ciclo.ciclo') → row.ciclo.ciclo
67
+ */
68
+ function getNestedValue(obj, path) {
69
+ return path.split('.').reduce((acc, key) => acc?.[key], obj);
70
+ }
71
+
72
+
73
+
74
+ class SimpleDatatableAdapter extends HTMLElement {
75
+ constructor() {
76
+ super();
77
+ // this.attachShadow({ mode: 'open' }); // commentare per light dom
78
+
79
+ this._config = null;
80
+ this._initCalledProgrammatically = false;
81
+ this._isConnected = false;
82
+ this._loadStarted = false;
83
+
84
+ /** Riferimento all'istanza DataTable di simple-datatables */
85
+ this._dt = null;
86
+
87
+ /** Filtro da applicare dopo il prossimo reload (vedi reload()) */
88
+ this._pendingSearch = null;
89
+ this._loadGeneration = 0;
90
+
91
+ // Handler bound per poterli rimuovere in disconnectedCallback
92
+ this._onSearch = this._handleSearch.bind(this);
93
+ this._onMultiSearch = this._handleMultiSearch.bind(this);
94
+ this._onReload = this._handleReload.bind(this);
95
+ }
96
+
97
+
98
+ // ─── Lifecycle ──────────────────────────────────────────────────────────────
99
+
100
+ async connectedCallback() {
101
+ this._isConnected = true;
102
+
103
+ // Registra i listener sugli eventi globali
104
+ document.addEventListener('datatable:search', this._onSearch);
105
+ document.addEventListener('datatable:multisearch', this._onMultiSearch);
106
+ document.addEventListener('datatable:reload', this._onReload);
107
+
108
+ if (this._initCalledProgrammatically) {
109
+ if (!this._loadStarted) this._load();
110
+ return;
111
+ }
112
+
113
+ this._load();
114
+ }
115
+
116
+ disconnectedCallback() {
117
+ document.removeEventListener('datatable:search', this._onSearch);
118
+ document.removeEventListener('datatable:multisearch', this._onMultiSearch);
119
+ document.removeEventListener('datatable:reload', this._onReload);
120
+ }
121
+
122
+
123
+ // ─── API pubblica ────────────────────────────────────────────────────────────
124
+
125
+ /**
126
+ * Avvia il componente via script, passando la configurazione come oggetto.
127
+ * Può essere chiamato sia prima che dopo l'inserimento nel DOM.
128
+ *
129
+ * I parametri non inclusi in `config` vengono letti dall'attributo HTML
130
+ * corrispondente, se presente — consentendo un mix dei due approcci:
131
+ *
132
+ * <s-datatable
133
+ * cols='[{"_heading":"Nome","_field":"name"}]'
134
+ * ></s-datatable>
135
+ *
136
+ * el.init({ json: '/api/data.json', perPage: 20 });
137
+ * // → json e perPage da script, cols dall'attributo
138
+ *
139
+ * Per ignorare esplicitamente un attributo esistente e forzare il default
140
+ * interno, passare il valore `null` nel config:
141
+ *
142
+ * el.init({ json: '/api/data.json', cols: null });
143
+ * // → cols = null (l'attributo viene ignorato)
144
+ */
145
+ init(config = {}) {
146
+ this._config = config;
147
+ this._initCalledProgrammatically = true;
148
+
149
+ // Azzera il flag di caricamento: init() chiamato esplicitamente deve
150
+ // sempre ripartire, anche se connectedCallback aveva già tentato un
151
+ // _load() prematuro (es. quando domBuilder appende l'elemento al DOM
152
+ // prima che la configurazione sia disponibile).
153
+ this._loadStarted = false;
154
+ this._loadGeneration++;
155
+
156
+ if (this._isConnected) {
157
+ this._load();
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Ricerca testuale su una o più colonne.
163
+ * @param {string} term
164
+ * @param {number[]} [columns] indici di colonna; se omesso cerca su tutto
165
+ */
166
+ search(term, columns) {
167
+ if (!this._dt) return;
168
+ this._dt.search(term, columns);
169
+ }
170
+
171
+ /**
172
+ * Ricerca multi-colonna con query indipendenti.
173
+ * @param {Array<{ terms: string[], columns?: number[] }>} queries
174
+ */
175
+ multiSearch(queries) {
176
+ if (!this._dt) return;
177
+ this._dt.multiSearch(queries);
178
+ }
179
+
180
+ /**
181
+ * Ricarica i dati (eventualmente da un nuovo URL e/o con nuove colonne),
182
+ * con possibilità di applicare un filtro contestuale al termine del fetch.
183
+ *
184
+ * @param {object} [overrides]
185
+ * @param {string} [overrides.json] Nuovo URL dati (ignorato se `data` è presente)
186
+ * @param {Array} [overrides.data] Dati inline (array di oggetti); ha precedenza su `json`
187
+ * @param {Array} [overrides.cols] Nuove colonne
188
+ * @param {object} [overrides.search] Filtro da applicare dopo il caricamento.
189
+ * Formati supportati:
190
+ * - { term, columns? } → ricerca semplice (search)
191
+ * - { queries: [{terms, columns?}, …] } → ricerca multipla (multiSearch)
192
+ * I due si escludono: se presente `queries` → multiSearch, altrimenti search.
193
+ */
194
+ async reload(overrides = {}) {
195
+ if (overrides.json) this._setParam('json', overrides.json);
196
+ if (overrides.data !== undefined) this._setParam('data', overrides.data);
197
+ if (overrides.cols) this._setParam('cols', overrides.cols);
198
+
199
+ // Memorizza il filtro pendente: verrà applicato dentro datatable.init,
200
+ // dopo che simple-datatables ha terminato di renderizzare i nuovi dati.
201
+ this._pendingSearch = overrides.search ?? null;
202
+
203
+ this._loadStarted = false;
204
+ this._loadGeneration++;
205
+ await this._load();
206
+ }
207
+
208
+
209
+ // ─── Helpers interni ─────────────────────────────────────────────────────────
210
+
211
+ /**
212
+ * Risolve il valore di un parametro fondendo le tre sorgenti possibili.
213
+ *
214
+ * Ordine di precedenza (dal più al meno prioritario):
215
+ * 1. _config – valore passato via init() o _setParam().
216
+ * Se presente e !== undefined sovrascrive sempre l'attributo.
217
+ * Passare esplicitamente `null` per ignorare l'attributo e
218
+ * ricevere il defaultValue.
219
+ * 2. Attributo HTML – se il valore inizia con [ o { viene auto-parsato
220
+ * da JSON (utile per cols, che può stare nell'attributo).
221
+ * 3. defaultValue – fallback finale.
222
+ *
223
+ * Esempi con config = { json: '/api/x.json' } e attr cols='[…]':
224
+ * _getParam('json') → '/api/x.json' (da config)
225
+ * _getParam('cols') → [… parsed …] (da attributo, auto-JSON)
226
+ * _getParam('perPage', 25)→ 25 (default)
227
+ *
228
+ * Per ignorare esplicitamente un attributo, passare null nel config:
229
+ * init({ cols: null }) → _getParam('cols') restituisce null,
230
+ * l'attributo viene saltato.
231
+ */
232
+ _getParam(name, defaultValue = null) {
233
+ // 1. Config da script (undefined = chiave assente → scendi di livello)
234
+ if (this._config && this._config[name] !== undefined) {
235
+ return this._config[name];
236
+ }
237
+
238
+ // 2. Attributo HTML
239
+ const attr = this.getAttribute(name);
240
+ if (attr !== null) {
241
+ // Auto-parse JSON per array e oggetti (es. cols='[…]')
242
+ const trimmed = attr.trim();
243
+ if (trimmed.startsWith('[') || trimmed.startsWith('{')) {
244
+ try { return JSON.parse(trimmed); } catch { /* restituisce la stringa grezza */ }
245
+ }
246
+ return attr;
247
+ }
248
+
249
+ // 3. Default interno
250
+ return defaultValue;
251
+ }
252
+
253
+ _setParam(name, value) {
254
+ if (!this._config) this._config = {};
255
+ this._config[name] = value;
256
+ }
257
+
258
+ /**
259
+ * Ritorna true se questo elemento è il target dell'evento.
260
+ * Se detail.target è assente, risponde sempre;
261
+ * altrimenti solo se corrisponde all'id dell'elemento.
262
+ */
263
+ _isTarget(detail) {
264
+ return !detail.target || detail.target === this.id;
265
+ }
266
+
267
+
268
+ // ─── Handler eventi globali ──────────────────────────────────────────────────
269
+
270
+ _handleSearch(e) {
271
+ if (!this._isTarget(e.detail)) return;
272
+ const { term = '', columns } = e.detail;
273
+ this.search(term, columns);
274
+ }
275
+
276
+ _handleMultiSearch(e) {
277
+ if (!this._isTarget(e.detail)) return;
278
+ const { queries = [] } = e.detail;
279
+ this.multiSearch(queries);
280
+ }
281
+
282
+ _handleReload(e) {
283
+ if (!this._isTarget(e.detail)) return;
284
+ // Propaga `data` solo se esplicitamente presente nel detail
285
+ const overrides = { ...e.detail };
286
+ this.reload(overrides);
287
+ }
288
+
289
+
290
+ // ─── Caricamento dati ────────────────────────────────────────────────────────
291
+
292
+ async _load() {
293
+ if (this._loadStarted) return;
294
+ this._loadStarted = true;
295
+ const generation = this._loadGeneration;
296
+
297
+ this.innerHTML = '<div class="spinner"><span class="visually-hidden">Caricamento dati...</span></div>';
298
+
299
+ const inlineData = this._getParam('data');
300
+ const jsonUrl = this._getParam('json');
301
+ const cols = this._getParam('cols', []);
302
+
303
+ if (inlineData == null && !jsonUrl) {
304
+ if (this._initCalledProgrammatically) {
305
+ // eslint-disable-next-line no-console
306
+ console.error('[s-datatable] Nessuna sorgente dati: specificare `data` o `json`.');
307
+ }
308
+ this.innerHTML = '';
309
+ return;
310
+ }
311
+
312
+ try {
313
+ // Risolvi i dati grezzi: inline `data` ha precedenza su `json`
314
+ let rawData;
315
+ if (inlineData != null) {
316
+ rawData = Array.isArray(inlineData) ? inlineData : [];
317
+ } else {
318
+ const response = await fetch(jsonUrl);
319
+ const parsed = await response.json();
320
+ rawData = parsed.data;
321
+ }
322
+
323
+ this.headings = cols.map(item =>
324
+ item._title
325
+ ? `<abbr title="${item._title}">${item._heading}</abbr>`
326
+ : item._heading
327
+ );
328
+
329
+ this.data = rawData.map((row, idx) => ({
330
+ attributes: { 'data-jidx': idx },
331
+
332
+ cells: cols.map((col_item, col_idx) => {
333
+ let value = getNestedValue(row, col_item._field);
334
+
335
+ if (col_item._renderTpl) {
336
+ value = decodeURIComponent(col_item._renderTpl).replace(
337
+ /\[\[(.*?)\]\]/g,
338
+ (match, key) => {
339
+ const resolved = getNestedValue(row, key);
340
+ const pathParts = key.split('.');
341
+ const parentObj = pathParts.length > 1
342
+ ? getNestedValue(row, pathParts.slice(0, -1).join('.'))
343
+ : row;
344
+
345
+ // Segnala solo se il padre esiste ma la chiave foglia manca
346
+ // (errore di configurazione). Se il padre è null il dato è
347
+ // semplicemente assente (es. Symfony restituisce owner: null).
348
+ if (parentObj != null && !Object.prototype.hasOwnProperty.call(parentObj, pathParts.at(-1))) {
349
+ // eslint-disable-next-line no-console
350
+ console.error(`[s-datatable] Chiave "${key}" non trovata nella struttura dati (colonna ${col_idx})`);
351
+ }
352
+
353
+ return resolved ?? '';
354
+ }
355
+ );
356
+ } else if (col_item._renderMode === 'sf_datetime' && value != null) {
357
+ value = value.date.replace(' ', 'T') +
358
+ (value.timezone === 'UTC' ? 'Z' : '');
359
+ }
360
+
361
+ return value;
362
+ })
363
+ }));
364
+
365
+ this.columns = cols.map((col_settings, idx) => {
366
+ col_settings = parseCols(col_settings);
367
+
368
+ return {
369
+ ...(Object.fromEntries(
370
+ Object.entries(col_settings).filter(([key]) => !key.startsWith('_'))
371
+ )),
372
+ select: idx,
373
+ type: col_settings.type ?? 'string',
374
+ searchable: col_settings.searchable ?? true,
375
+ sortable: col_settings.sortable ?? true,
376
+ };
377
+ });
378
+
379
+ } catch (err) {
380
+ /* eslint-disable no-console */
381
+ if (jsonUrl) console.error(jsonUrl);
382
+ console.error(err);
383
+ /* eslint-enable no-console */
384
+ }
385
+
386
+ if (generation !== this._loadGeneration) return;
387
+ this._render();
388
+ }
389
+
390
+
391
+ // ─── Render ──────────────────────────────────────────────────────────────────
392
+
393
+ _render() {
394
+ // Distrugge l'istanza precedente prima di ricrearla (es. dopo reload)
395
+ if (this._dt) {
396
+ this._dt.destroy();
397
+ this._dt = null;
398
+ }
399
+
400
+ this.innerHTML = '';
401
+ const table = document.createElement('table');
402
+ this.appendChild(table);
403
+
404
+ const perPage = +this._getParam('perPage', 25);
405
+
406
+ this._dt = new DataTable(table, {
407
+ locale: 'it',
408
+ searchable: true,
409
+ sortable: true,
410
+ fixedHeight: false,
411
+ fixedColumns: false,
412
+ paging: true,
413
+ perPage,
414
+ pagerDelta: 2,
415
+ perPageSelect: false,
416
+
417
+ labels: {
418
+ placeholder: 'Cerca...',
419
+ searchTitle: 'Cerca nella tabella',
420
+ pageTitle: 'Pagina {page}',
421
+ perPage: 'Righe per pagina',
422
+ noRows: 'Nessun record trovato',
423
+ info: 'Stai visualizzando le righe da {start} a {end}, su un totale di {rows}',
424
+ noResults: 'Nessun risultato per la ricerca',
425
+ },
426
+
427
+ classes: {
428
+ wrapper : styles.datatableWrapper,
429
+ container : 'table-responsive',
430
+ loading : 'datatable-loading', // ??
431
+
432
+ // barra superiore
433
+ top : styles.topArea,
434
+ search : styles.searchWrapper,
435
+ input : 'form-control form-control-sm',
436
+ // dropdown : 'datatable-dropdown', // selettore righe per pagina, disattivato
437
+
438
+ empty : styles.empty,
439
+
440
+ // table
441
+ table : `table table-bordered ${styles.table}`,
442
+ // buttons in thead per il sort
443
+ sorter : `btn-reset ${styles.sortBtn}`,
444
+ ascending : styles.sortAscending,
445
+ descending : styles.sortDescending,
446
+
447
+ // area inferiore
448
+ bottom : styles.bottomArea,
449
+ // info text
450
+ info : styles.info,
451
+
452
+ // pagination
453
+ // pagination : styles.paginationNav,
454
+ paginationList : styles.paginationList,
455
+ paginationListItem : styles.paginationListItem,
456
+ paginationListItemLink : styles.paginationListItemBtn,
457
+ // hidden : 'datatable-hidden',
458
+ disabled : styles.paginationDisabled,
459
+ active : styles.paginationActive,
460
+
461
+ // cursor: 'datatable-cursor',
462
+ // dropdown: 'datatable-dropdown',
463
+ // ellipsis: 'datatable-ellipsis',
464
+ // filter: 'datatable-filter',
465
+ // filterActive: 'datatable-filter-active',
466
+ // headercontainer: 'datatable-headercontainer',
467
+ // selector: 'datatable-selector',
468
+ },
469
+
470
+ columns: this.columns,
471
+ data: {
472
+ headings: this.headings,
473
+ data: this.data
474
+ }
475
+ });
476
+
477
+ this._dt.on('datatable.init', () => {
478
+ const pagination = this.querySelector(`.${styles.paginationList}`);
479
+ if (!pagination) return;
480
+
481
+ const items = pagination.querySelectorAll(`.${styles.paginationListItem}`);
482
+ if (!items.length) return;
483
+
484
+ pagination.querySelector(
485
+ `.${styles.paginationListItem}:first-child .${styles.paginationListItemBtn}`
486
+ ).innerHTML = caretLeftIcon;
487
+
488
+ pagination.querySelector(
489
+ `.${styles.paginationListItem}:last-child .${styles.paginationListItemBtn}`
490
+ ).innerHTML = caretRightIcon;
491
+
492
+ pagination.querySelectorAll(`.${styles.paginationListItemBtn}:has(svg)`)
493
+ .forEach(btn => btn.classList.add(styles.hasSvg));
494
+
495
+ // Applica eventuale filtro contestuale passato via reload({ search: … })
496
+ // Lo facciamo qui, dentro datatable.init, per essere certi che
497
+ // simple-datatables abbia completato il render dei nuovi dati.
498
+ if (this._pendingSearch) {
499
+ const ps = this._pendingSearch;
500
+ this._pendingSearch = null;
501
+
502
+ if (ps.queries) {
503
+ this._dt.multiSearch(ps.queries);
504
+ } else if (ps.term !== undefined) {
505
+ this._dt.search(ps.term, ps.columns);
506
+ }
507
+ }
508
+ });
509
+
510
+ } // end _render
511
+
512
+ } // end component
513
+
514
+
515
+ if (!customElements.get('s-datatable')) {
516
+ customElements.define('s-datatable', SimpleDatatableAdapter);
517
+ }
@@ -1,4 +1,4 @@
1
- /* frontend/src/web-components/simple-datatable.module.css */
1
+ /* frontend/src/web-components/s-datatable-component.module.css */
2
2
 
3
3
  /* import delle custom properties gestito da jit-props */
4
4
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  import { classnames } from '../../../../index.js';
6
6
 
7
- import * as styles from '../simple-datatable.module.css';
7
+ import * as styles from '../s-datatable-component.module.css';
8
8
 
9
9
  import checkIcon from '../../../icons/check-bold.svg?inline';
10
10
  import xIcon from '../../../icons/x-bold.svg?inline';
@@ -1,36 +0,0 @@
1
- {
2
- "badge": {
3
- "background": {
4
- "color": {
5
- "$value": "{primary.100}",
6
- "$type": "color"
7
- }
8
- },
9
- "color": {
10
- "$value": "{primary.100-fg}",
11
- "$type": "color"
12
- },
13
- "font": {
14
- "size": {
15
- "$value": "{font.size.xs}",
16
- "$type": "dimension"
17
- },
18
- "weight": {
19
- "$value": "{font.weight.semibold}",
20
- "$type": "number"
21
- }
22
- },
23
- "lg": {
24
- "font": {
25
- "size": {
26
- "$value": "{font.size.base}",
27
- "$type": "dimension"
28
- },
29
- "weight": {
30
- "$value": "{badge.font.weight}",
31
- "$type": "number"
32
- }
33
- }
34
- }
35
- } // end badge
36
- }
@@ -1,101 +0,0 @@
1
- {
2
- "btn": {
3
- "close": {
4
- "size": {
5
- "$value": "1.5rem",
6
- "$type": "dimension"
7
- },
8
- "padding": {
9
- "$value": "3px",
10
- "$type": "dimension"
11
- },
12
- "border": {
13
- "width": {
14
- "$value": "2px",
15
- "$type": "dimension"
16
- },
17
- "color": {
18
- "$value": "{btn.close.icon.color}",
19
- "$type": "color"
20
- },
21
- "radius": {
22
- "$value": "50%",
23
- "$type": "dimension"
24
- }
25
-
26
- },
27
- "background": {
28
- "color": {
29
- "$value": "{body.background.color}",
30
- "$type": "color"
31
- },
32
-
33
- },
34
- "icon": {
35
- "color": {
36
- "$value": "{text.color}",
37
- "$type": "color"
38
- },
39
- "bar": {
40
- "size": {
41
- "$value": "2px",
42
- "$type": "dimension"
43
- }
44
- }
45
-
46
- },
47
-
48
- "hover": {
49
- "background": {
50
- "color": {
51
- "$value": "{btn.close.icon.color}",
52
- "$type": "color"
53
- }
54
- },
55
- "border": {
56
- "color": {
57
- "$value": "{btn.close.icon.color}",
58
- "$type": "color"
59
- }
60
- },
61
- "icon": {
62
- "color": {
63
- "$value": "{btn.close.background.color}",
64
- "$type": "color"
65
- }
66
- }
67
- },
68
-
69
- "focus": {
70
- "outline": {
71
- "width": {
72
- "$value": "2px",
73
- "$type": "dimension"
74
- },
75
- "offset": {
76
- "$value": "2px",
77
- "$type": "dimension"
78
- },
79
- "color": {
80
- "$value": "{link.focus.outline.color}",
81
- "$type": "color"
82
- }
83
- }
84
- },
85
- "active": {
86
- "background": {
87
- "color": {
88
- "$value": "{btn.close.background.color}",
89
- "$type": "color"
90
- }
91
- },
92
- "icon": {
93
- "color": {
94
- "$value": "{link.active.color}",
95
- "$type": "color"
96
- }
97
- }
98
- }
99
- } // end close
100
- } // end btn
101
- }
@@ -1,18 +0,0 @@
1
- {
2
- "flex-grid": {
3
- "gap": {
4
- "$value": "1.5rem",
5
- "$type": "dimension"
6
- }
7
- },
8
- "grid": {
9
- "cols": {
10
- "$value": 3,
11
- "$type": "number"
12
- },
13
- "min-col-width": {
14
- "$value": "6rem",
15
- "$type": "dimension"
16
- }
17
- }
18
- }
@@ -1,4 +0,0 @@
1
- {}
2
-
3
-
4
- // --box-shadow-base: 0 0 1.2rem #00000040;