@massimo-cassandro/minimo 1.7.2 → 1.8.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 (122) hide show
  1. package/design-tokens/tokens/size.minimo.tokens.jsonc +16 -16
  2. package/index.js +3 -2
  3. package/package.json +1 -1
  4. package/src/components/TODO form-multiselect/form-multiselect.css +40 -0
  5. package/src/components/TODO form-multiselect/form-multiselect.js +83 -0
  6. package/src/components/TODO vanilla-cookie-consent/cookie-consent.css +20 -0
  7. package/src/components/TODO vanilla-cookie-consent/cookie-consent.js +76 -0
  8. package/src/components/TODO vanilla-cookie-consent/render-cookie-list.js +32 -0
  9. package/src/components/TODO vanilla-cookie-consent/src/cookie-list.js +85 -0
  10. package/src/components/TODO vanilla-cookie-consent/src/it-translation.js +38 -0
  11. package/src/components/TODO vanilla-cookie-consent/src/run-analytics.js +54 -0
  12. package/src/components/TODO vanilla-cookie-consent/src/run-recaptcha.js +71 -0
  13. package/src/components/modal-alert/TODO modal-alert-demo/demo.css +63 -0
  14. package/src/components/modal-alert/TODO modal-alert-demo/demo.js +155 -0
  15. package/src/components/modal-popup/modal-popup.js +2 -1
  16. package/src/components/slide-up-down-toggle/slide-up-down-toggle.js +246 -0
  17. package/src/components/slide-up-down-toggle/slide-up-down-toggle.module.css +97 -0
  18. package/src/components/snackbar/snackbar.js +2 -1
  19. package/src/components/spinner/spinner.js +2 -1
  20. package/src/components/unsplash-page/TODO unsplash-page-demo/README.md +194 -0
  21. package/src/components/unsplash-page/TODO unsplash-page-demo/changelog.md +5 -0
  22. package/src/components/unsplash-page/TODO unsplash-page-demo/unsplash-page/demo.js +15 -0
  23. package/src/components/unsplash-page/TODO unsplash-page-demo/unsplash-page/rollup.config.mjs +26 -0
  24. package/src/components/unsplash-page/TODO unsplash-page-demo/unsplash-page/unsplash-page-demo.min.js +3 -0
  25. package/src/web-components/TODO json-table/README.md +67 -0
  26. package/src/web-components/TODO json-table/TODO.md +12 -0
  27. package/src/web-components/TODO json-table/_work/OLD/docs/custom-props-list.md +69 -0
  28. package/src/web-components/TODO json-table/_work/OLD/script/create-css-custom-props-doc.mjs +113 -0
  29. package/src/web-components/TODO json-table/_work/OLD/script/src/custom-props-end.md +4 -0
  30. package/src/web-components/TODO json-table/_work/OLD/script/src/custom-props-start.md +30 -0
  31. package/src/web-components/TODO json-table/_work/OLD/src/css/icons.module.css +22 -0
  32. package/src/web-components/TODO json-table/_work/OLD/src/css/info.module.css +42 -0
  33. package/src/web-components/TODO json-table/_work/OLD/src/css/main-wrapper.module.css +4 -0
  34. package/src/web-components/TODO json-table/_work/OLD/src/css/table.module.css +154 -0
  35. package/src/web-components/TODO json-table/_work/OLD/src/css/utility.module.css +9 -0
  36. package/src/web-components/TODO json-table/_work/OLD/src/icons/false.svg +1 -0
  37. package/src/web-components/TODO json-table/_work/OLD/src/icons/search-arrows.svg +1 -0
  38. package/src/web-components/TODO json-table/_work/OLD/src/icons/true.svg +1 -0
  39. package/src/web-components/TODO json-table/_work/OLD/src/index.js +56 -0
  40. package/src/web-components/TODO json-table/_work/OLD/src/js/default-columns-data-types.js +172 -0
  41. package/src/web-components/TODO json-table/_work/OLD/src/js/defaults.js +156 -0
  42. package/src/web-components/TODO json-table/_work/OLD/src/js/info-section.js +31 -0
  43. package/src/web-components/TODO json-table/_work/OLD/src/js/listeners.js +17 -0
  44. package/src/web-components/TODO json-table/_work/OLD/src/js/main-builder.js +26 -0
  45. package/src/web-components/TODO json-table/_work/OLD/src/js/parse-params.js +121 -0
  46. package/src/web-components/TODO json-table/_work/OLD/src/js/set-column-classname.js +22 -0
  47. package/src/web-components/TODO json-table/_work/OLD/src/js/table-builder.js +64 -0
  48. package/src/web-components/TODO json-table/_work/OLD/src/js/table-foot.js +8 -0
  49. package/src/web-components/TODO json-table/_work/OLD/src/js/table-head.js +47 -0
  50. package/src/web-components/TODO json-table/_work/OLD/src/js/table-row.js +83 -0
  51. package/src/web-components/TODO json-table/_work/OLD/src/js/utilities.js +5 -0
  52. package/src/web-components/TODO json-table/_work/__json-table-react/index.js +4 -0
  53. package/src/web-components/TODO json-table/_work/__json-table-react/src/build-page-array.js +73 -0
  54. package/src/web-components/TODO json-table/_work/__json-table-react/src/columns-data-types.js +73 -0
  55. package/src/web-components/TODO json-table/_work/__json-table-react/src/defaults.js +50 -0
  56. package/src/web-components/TODO json-table/_work/__json-table-react/src/download-excel.js +156 -0
  57. package/src/web-components/TODO json-table/_work/__json-table-react/src/set-className.js +19 -0
  58. package/src/web-components/TODO json-table/_work/__json-table-react/src/set-download-filename.js +17 -0
  59. package/src/web-components/TODO json-table/_work/__json-table-react/src/table-to-csv.js +48 -0
  60. package/src/web-components/TODO json-table/_work/archived/table-to-csv.js +48 -0
  61. package/src/web-components/TODO json-table/_work/arrow.svg +3 -0
  62. package/src/web-components/TODO json-table/_work/da decidere/get-cell-data.js +18 -0
  63. package/src/web-components/TODO json-table/_work/download-button.js +29 -0
  64. package/src/web-components/TODO json-table/_work/download-excel.js +155 -0
  65. package/src/web-components/TODO json-table/_work/pagination-array-builder.js +73 -0
  66. package/src/web-components/TODO json-table/_work/pagination.js +37 -0
  67. package/src/web-components/TODO json-table/_work/set-download-filename.js +19 -0
  68. package/src/web-components/TODO json-table/_work/table-info.js +24 -0
  69. package/src/web-components/TODO json-table/demo/README.md +66 -0
  70. package/src/web-components/TODO json-table/demo/assets/link-simple.svg +1 -0
  71. package/src/web-components/TODO json-table/demo/demo-data/json-static-table-demo-data.js +512 -0
  72. package/src/web-components/TODO json-table/demo/demo.css +32 -0
  73. package/src/web-components/TODO json-table/demo/demo.js +24 -0
  74. package/src/web-components/TODO json-table/demo/js/demo-ajax-table.js +165 -0
  75. package/src/web-components/TODO json-table/demo/js/demo-static-table.js +180 -0
  76. package/src/web-components/TODO json-table/demo/webpack-modules/css-rules.mjs +122 -0
  77. package/src/web-components/TODO json-table/demo/webpack-modules/get-jsConfig-aliases.mjs +33 -0
  78. package/src/web-components/TODO json-table/demo/webpack-modules/svg-rules.mjs +108 -0
  79. package/src/web-components/TODO json-table/demo/webpack-modules/svgo.config.mjs +26 -0
  80. package/src/web-components/TODO json-table/demo/webpack.config.mjs +333 -0
  81. package/src/web-components/TODO json-table/docs/custom-props-list.md +74 -0
  82. package/src/web-components/TODO json-table/docs-builder/create-css-custom-props-doc.mjs +157 -0
  83. package/src/web-components/TODO json-table/docs-builder/src/custom-props-end.md +6 -0
  84. package/src/web-components/TODO json-table/docs-builder/src/custom-props-start.md +29 -0
  85. package/src/web-components/TODO json-table/src/TODO.md +1 -0
  86. package/src/web-components/TODO json-table/src/__json-table-react/build-page-array.js +73 -0
  87. package/src/web-components/TODO json-table/src/__json-table-react/columns-data-types.js +73 -0
  88. package/src/web-components/TODO json-table/src/__json-table-react/defaults.js +50 -0
  89. package/src/web-components/TODO json-table/src/__json-table-react/download-excel.js +156 -0
  90. package/src/web-components/TODO json-table/src/__json-table-react/set-className.js +19 -0
  91. package/src/web-components/TODO json-table/src/__json-table-react/set-download-filename.js +17 -0
  92. package/src/web-components/TODO json-table/src/__json-table-react/table-to-csv.js +48 -0
  93. package/src/web-components/TODO json-table/src/css/custom-media.css +16 -0
  94. package/src/web-components/TODO json-table/src/css/icons.module.css +22 -0
  95. package/src/web-components/TODO json-table/src/css/info-section.module.css +78 -0
  96. package/src/web-components/TODO json-table/src/css/main-builder.module.css +6 -0
  97. package/src/web-components/TODO json-table/src/css/table.module.css +172 -0
  98. package/src/web-components/TODO json-table/src/css/utility.module.css +9 -0
  99. package/src/web-components/TODO json-table/src/icons/arrow-down-bold.svg +1 -0
  100. package/src/web-components/TODO json-table/src/icons/false.svg +1 -0
  101. package/src/web-components/TODO json-table/src/icons/true.svg +1 -0
  102. package/src/web-components/TODO json-table/src/index.js +125 -0
  103. package/src/web-components/TODO json-table/src/js/default-columns-data-types.js +172 -0
  104. package/src/web-components/TODO json-table/src/js/defaults.js +510 -0
  105. package/src/web-components/TODO json-table/src/js/get-ajax-data.js +72 -0
  106. package/src/web-components/TODO json-table/src/js/info-section.js +39 -0
  107. package/src/web-components/TODO json-table/src/js/init-ajax-table.js +30 -0
  108. package/src/web-components/TODO json-table/src/js/init-static-table.js +18 -0
  109. package/src/web-components/TODO json-table/src/js/main-builder.js +87 -0
  110. package/src/web-components/TODO json-table/src/js/parse-data-row.js +123 -0
  111. package/src/web-components/TODO json-table/src/js/parse-params.js +118 -0
  112. package/src/web-components/TODO json-table/src/js/set-search-listener.js +62 -0
  113. package/src/web-components/TODO json-table/src/js/set-sort-listeners.js +115 -0
  114. package/src/web-components/TODO json-table/src/js/static-data-sorting.js +23 -0
  115. package/src/web-components/TODO json-table/src/js/table-builder.js +45 -0
  116. package/src/web-components/TODO json-table/src/js/table-row.js +43 -0
  117. package/src/web-components/TODO json-table/src/js/table-tfoot.js +9 -0
  118. package/src/web-components/TODO json-table/src/js/table-thead.js +91 -0
  119. package/src/web-components/TODO json-table/src/js/update-info.js +42 -0
  120. package/src/web-components/TODO json-table/src/js/utilities.js +5 -0
  121. package/src/web-components/s-datatable-component/s-datatable-component.js +2 -1
  122. package/src/web-components/s-datatable-component/src/parse-cols.js +2 -1
@@ -0,0 +1,155 @@
1
+ import mAlert from '../src/modal-alert.js';
2
+
3
+ const custom_defaults = {
4
+
5
+ //settings to be applied to all dialog types
6
+ globals: {
7
+ onOpen: () => {
8
+ // console.log('open'); // eslint-disable-line
9
+ document.body.classList.add('modal-alert-is-open');
10
+ },
11
+ onClose: () => {
12
+ // console.log('close'); // eslint-disable-line
13
+ document.body.classList.remove('modal-alert-is-open');
14
+ },
15
+ cssFile: null
16
+ },
17
+
18
+ success: {
19
+ title: 'Done!',
20
+ mes: null,
21
+ ok_btn_text: 'OK',
22
+ heading_class: 'text-success',
23
+ ok_btn_class: 'btn',
24
+ timer: 4000, // ms
25
+ },
26
+ error: {
27
+ title: 'An error has occurred',
28
+ mes: null,
29
+ ok_btn_text: 'OK',
30
+ heading_class: null,
31
+ text_class: null,
32
+ ok_btn_class: 'btn',
33
+ timer: null,
34
+ },
35
+ warning: {
36
+ title: 'Attention!',
37
+ mes: null,
38
+ ok_btn_text: 'OK',
39
+ heading_class: null,
40
+ text_class: null,
41
+ ok_btn_class: 'btn',
42
+ timer: null,
43
+ },
44
+ info: {
45
+ title: null,
46
+ mes: null,
47
+ ok_btn_text: 'OK',
48
+ heading_class: null,
49
+ text_class: null,
50
+ ok_btn_class: 'btn',
51
+ timer: null,
52
+ },
53
+ confirm: {
54
+ title: 'Do you confirm?',
55
+ mes: null,
56
+ ok_btn_text: 'OK',
57
+ cancel_btn_text: 'Cancel',
58
+ cancel_focus: true, // false to give focus to the ok button
59
+ heading_class: null,
60
+ text_class: null,
61
+ ok_btn_class: 'btn btn-outline',
62
+ cancel_btn_class: 'btn',
63
+ callback: null,
64
+ timer: null,
65
+ }
66
+ };
67
+
68
+ document.querySelector('.demo-success').addEventListener('click', () => {
69
+ mAlert({
70
+ type : 'success',
71
+ mes: 'Lorem ipsum dolor sit amet',
72
+ callback: () => alert('callback')
73
+ }, custom_defaults);
74
+ }, false);
75
+
76
+ document.querySelector('.demo-info').addEventListener('click', () => {
77
+ mAlert({
78
+ type : 'info',
79
+ title: 'Info',
80
+ mes: '<strong>Lorem ipsum</strong> dolor sit amet'
81
+ }, custom_defaults);
82
+ }, false);
83
+
84
+ document.querySelector('.demo-error').addEventListener('click', () => {
85
+ mAlert({
86
+ type : 'error'
87
+ }, custom_defaults);
88
+ }, false);
89
+
90
+ document.querySelector('.demo-error-extra-btn').addEventListener('click', () => {
91
+ mAlert({
92
+ type : 'error',
93
+ ok_btn_class: 'btn btn-error btn btn-outline',
94
+ extra_btn: '<button type="button" data-malert-result="extra-btn-result" class="btn btn-error extra-btn">Extra btn</button>',
95
+ extra_btn_selector: '.extra-btn',
96
+ extra_btn_focus: true,
97
+ callback: result => alert(result === 'extra-btn-result'? 'Extra button pressed' : 'OK button pressed')
98
+ }, custom_defaults);
99
+ }, false);
100
+
101
+ document.querySelector('.demo-warning').addEventListener('click', () => {
102
+ mAlert({
103
+ type : 'warning',
104
+ mes: '<p>Quo dolorum cumque quo placeat aperiam doloribus dolorum animi. Sunt et dolores quas autem. Porro inventore ratione. Ex facere doloremque. Consectetur enim dolor. Sint ut facere quidem et et dicta natus itaque.</p> <p>Odit in eos repellat exercitationem tempore blanditiis voluptate. Dignissimos est tempora qui ducimus at et expedita esse.</p>'
105
+ }, custom_defaults);
106
+ }, false);
107
+
108
+ document.querySelector('.demo-confirm').addEventListener('click', () => {
109
+ mAlert({
110
+ type : 'confirm',
111
+ callback: result => alert(`${result? 'OK' : 'Cancel'} button pressed`)
112
+ }, custom_defaults);
113
+ }, false);
114
+
115
+
116
+ // forms
117
+ // Confirm on form submit
118
+ document.getElementById('test-form').addEventListener('submit', e => {
119
+ let choiceIsNeeded = true;
120
+
121
+ if(choiceIsNeeded) {
122
+ e.preventDefault();
123
+ mAlert({
124
+ type : 'confirm',
125
+ title: 'A choice is needed',
126
+ mes: 'Some message...',
127
+ ok_btn_text: 'Continue submit',
128
+ cancel_btn_text: 'Stop',
129
+ callback: result => {
130
+ if(result) {
131
+ alert('submit');
132
+ e.target.submit();
133
+ } else {
134
+ alert('submit canceled');
135
+ }
136
+ }
137
+ }, custom_defaults);
138
+ }
139
+
140
+ }, false);
141
+
142
+ // Error on form submit
143
+ document.getElementById('test-form2').addEventListener('submit', e => {
144
+ let isError = true;
145
+
146
+ if(isError) {
147
+ e.preventDefault();
148
+ mAlert({
149
+ type : 'error',
150
+ title: 'Oh my! There is an error...',
151
+ mes: 'Some message'
152
+ }, custom_defaults);
153
+ }
154
+
155
+ }, false);
@@ -1,7 +1,8 @@
1
1
  import { domBuilder } from '../../utilities/dom-builder/dom-builder.js';
2
2
  import { classnames } from '../../utilities/classnames.js';
3
3
  import { spinner } from '../spinner/spinner.js';
4
- import * as styles from './modal-popup.module.css';
4
+ import * as _modalCss from './modal-popup.module.css';
5
+ const styles = /** @type {Record<string, string>} */ (/** @type {any} */ (_modalCss).default ?? _modalCss);
5
6
 
6
7
 
7
8
  // https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement
@@ -0,0 +1,246 @@
1
+ // @ts-check
2
+
3
+ import * as _css from './slide-up-down-toggle.module.css';
4
+
5
+ /*
6
+ * css-loader exposes class names differently depending on webpack config:
7
+ * modules.namedExport: true → named exports → import * as _css → _css.slide
8
+ * default (namedExport off) → default export → import styles → styles.slide
9
+ * (= _css.default.slide)
10
+ * The fallback chain below handles both without changing any other code.
11
+ */
12
+ const styles = { slide: _css.slide ?? /** @type {any} */ (_css).default?.slide ?? 'slide' };
13
+
14
+ /**
15
+ * @module slide-up-down-toggle
16
+ *
17
+ * Collapse/expand animation driven by CSS — JS only toggles a data attribute
18
+ * and manages a lightweight wrapper element. No pixel measurement anywhere.
19
+ *
20
+ * ─── How it works ─────────────────────────────────────────────────────────────
21
+ *
22
+ * The CSS module uses `interpolate-size: allow-keywords` (height: auto
23
+ * transitions), `allow-discrete` (display: none transition), and
24
+ * `@starting-style` (entry animation from display: none). See the CSS file
25
+ * for a full explanation of each feature.
26
+ *
27
+ * ─── wrap: true (default) ─────────────────────────────────────────────────────
28
+ *
29
+ * JS wraps the target in a generated <div class="slide"> and animates that
30
+ * wrapper. The target element is completely untouched and can have any
31
+ * display value, padding, margin, or flex/grid layout.
32
+ *
33
+ * // target is free to be flex, have padding, etc.
34
+ * slideToggle(document.querySelector('#panel'));
35
+ *
36
+ * Initial collapsed state — add data-slide="closed" to the TARGET in HTML
37
+ * before any JS call. The first call transfers it to the generated wrapper:
38
+ *
39
+ * <div id="panel" data-slide="closed">
40
+ * <div class="d-flex p-3">…content…</div>
41
+ * </div>
42
+ *
43
+ * ─── wrap: false ──────────────────────────────────────────────────────────────
44
+ *
45
+ * JS adds the .slide class directly to the target. The target must be a plain
46
+ * block container with no padding, flex or grid of its own. All layout must
47
+ * live on an inner child element.
48
+ *
49
+ * <!-- target: plain wrapper, no padding -->
50
+ * <div id="panel" data-slide="closed">
51
+ * <!-- inner: all layout here -->
52
+ * <div class="d-flex p-3">…content…</div>
53
+ * </div>
54
+ *
55
+ * slideToggle(document.querySelector('#panel'), { wrap: false });
56
+ *
57
+ * ─── Options ──────────────────────────────────────────────────────────────────
58
+ *
59
+ * @typedef {{ wrap?: boolean, duration?: number, callback?: (() => void) | null }} SlideOptions
60
+ *
61
+ * wrap {boolean} default true — auto-generate wrapper (see above)
62
+ * duration {number} ms — overrides --slide-duration CSS var;
63
+ * if omitted the CSS value is used
64
+ * callback {() => void|null} default null — invoked after the transition ends
65
+ *
66
+ * ─── Return value ─────────────────────────────────────────────────────────────
67
+ *
68
+ * All three functions return a Promise<void> that resolves when the transition ends.
69
+ */
70
+
71
+ /**
72
+ * Default option values — single source of truth used in every slide function.
73
+ * @type {Required<SlideOptions>}
74
+ */
75
+ const DEFAULT_OPTIONS = {
76
+ wrap: true,
77
+ duration: /** @type {any} */ (undefined),
78
+ callback: null,
79
+ };
80
+
81
+ /**
82
+ * Maps each target element to its slide element (generated wrapper or the
83
+ * target itself). Checked on every call so the setup runs only once per target.
84
+ * @type {WeakMap<HTMLElement, HTMLElement>}
85
+ */
86
+ const registry = new WeakMap();
87
+
88
+ /**
89
+ * Returns the slide element for `target`, creating it on the first call.
90
+ *
91
+ * wrap: true — inserts a <div class="slide"> before the target, moves the
92
+ * target inside it, and transfers any existing data-slide value.
93
+ * Resolves after a requestAnimationFrame so the browser paints
94
+ * the wrapper's initial state before any transition-triggering
95
+ * attribute change. (offsetHeight forces layout but not a paint —
96
+ * only rAF guarantees a rendered frame as the transition origin.)
97
+ * wrap: false — adds the .slide class directly to the target. Resolves immediately
98
+ * since the element was already in the DOM.
99
+ *
100
+ * @param {HTMLElement} target
101
+ * @param {boolean} wrap
102
+ * @returns {Promise<HTMLElement>} the element that carries .slide and data-slide
103
+ */
104
+ async function getSlideEl(target, wrap) {
105
+ if (registry.has(target)) return /** @type {HTMLElement} */ (registry.get(target));
106
+
107
+ let el;
108
+ if (wrap) {
109
+ el = document.createElement('div');
110
+ el.classList.add(styles.slide);
111
+ // transfer only 'closed' state to the wrapper; 'open' is the default for
112
+ // visible elements and must NOT be set — it would trigger @starting-style
113
+ // on insertion, causing an unwanted height:0 entry animation
114
+ if ('slide' in target.dataset) {
115
+ if (target.dataset.slide === 'closed') el.dataset.slide = 'closed';
116
+ delete target.dataset.slide;
117
+ }
118
+ target.replaceWith(el);
119
+ el.appendChild(target);
120
+ // two nested rAFs are required: the outer one fires before the first paint
121
+ // (wrapper inserted but not yet rendered), the inner one fires after that
122
+ // paint — only then does the browser have a committed "previous style" to
123
+ // use as the transition origin. A single rAF or offsetHeight is not enough
124
+ // because both still execute before the first paint completes.
125
+ await new Promise(r => requestAnimationFrame(() => requestAnimationFrame(r)));
126
+ } else {
127
+ // read computed display BEFORE adding .slide, which would alter it
128
+ const startsHidden = window.getComputedStyle(target).display === 'none';
129
+ target.classList.add(styles.slide);
130
+ el = target;
131
+
132
+ if (startsHidden && !('slide' in target.dataset)) {
133
+ // remove inline display: none so .slide and its [data-slide] rules own visibility;
134
+ // CSS-based display: none from other rules may still conflict — wrap: true avoids this
135
+ if (target.style.display === 'none') {
136
+ target.style.removeProperty('display');
137
+ }
138
+ target.dataset.slide = 'closed';
139
+ }
140
+ }
141
+
142
+ registry.set(target, el);
143
+ return el;
144
+ }
145
+
146
+ /**
147
+ * Waits for the `height` transition on `el` to complete.
148
+ * Called AFTER the state attribute has been set so the transition is already
149
+ * running; transitionend fires at the end of the animation duration.
150
+ * Optionally sets --slide-duration to override the CSS default.
151
+ *
152
+ * @param {HTMLElement} el
153
+ * @param {number | undefined} duration
154
+ * @returns {Promise<void>}
155
+ */
156
+ async function awaitHeight(el, duration) {
157
+ if (duration !== undefined) {
158
+ el.style.setProperty('--slide-duration', `${duration}ms`);
159
+ }
160
+ await /** @type {Promise<void>} */ (new Promise(resolve => {
161
+ /** @param {TransitionEvent} e */
162
+ const handler = (e) => {
163
+ if (e.propertyName === 'height') {
164
+ el.removeEventListener('transitionend', handler);
165
+ resolve();
166
+ }
167
+ };
168
+ el.addEventListener('transitionend', handler);
169
+ }));
170
+ }
171
+
172
+ /**
173
+ * Tears down the slide setup for `target`.
174
+ *
175
+ * wrap was true — removes the generated wrapper and restores the target
176
+ * to its original position in the DOM.
177
+ * wrap was false — removes the .slide class and the data-slide attribute
178
+ * from the target.
179
+ *
180
+ * In both cases --slide-duration is removed from the slide element.
181
+ *
182
+ * @param {HTMLElement} target
183
+ */
184
+ export function disposeSliding(target) {
185
+ if (!registry.has(target)) return;
186
+ const el = /** @type {HTMLElement} */ (registry.get(target));
187
+
188
+ el.style.removeProperty('--slide-duration');
189
+
190
+ if (el !== target) {
191
+ el.replaceWith(target); // remove wrapper, put target back
192
+ } else {
193
+ target.classList.remove(styles.slide);
194
+ delete target.dataset.slide;
195
+ }
196
+
197
+ registry.delete(target);
198
+ }
199
+
200
+ /**
201
+ * Collapses `target`.
202
+ * CSS animates height to 0, then snaps display to none.
203
+ *
204
+ * @param {HTMLElement} target
205
+ * @param {SlideOptions} [options]
206
+ * @returns {Promise<void>}
207
+ */
208
+ export async function slideUp(target, options = {}) {
209
+ const { wrap, duration, callback } = { ...DEFAULT_OPTIONS, ...options };
210
+ const el = await getSlideEl(target, wrap);
211
+ el.dataset.slide = 'closed';
212
+ await awaitHeight(el, duration);
213
+ callback?.();
214
+ }
215
+
216
+ /**
217
+ * Expands `target`.
218
+ * display snaps to block, then CSS animates height from 0 (via @starting-style) to auto.
219
+ *
220
+ * @param {HTMLElement} target
221
+ * @param {SlideOptions} [options]
222
+ * @returns {Promise<void>}
223
+ */
224
+ export async function slideDown(target, options = {}) {
225
+ const { wrap, duration, callback } = { ...DEFAULT_OPTIONS, ...options };
226
+ const el = await getSlideEl(target, wrap);
227
+ el.dataset.slide = 'open';
228
+ await awaitHeight(el, duration);
229
+ callback?.();
230
+ }
231
+
232
+ /**
233
+ * Toggles the collapsed/expanded state of `target`.
234
+ * Reads the current data-slide value on the slide element to decide direction.
235
+ *
236
+ * @param {HTMLElement} target
237
+ * @param {SlideOptions} [options]
238
+ * @returns {Promise<void>}
239
+ */
240
+ export async function slideToggle(target, options = {}) {
241
+ const { wrap } = { ...DEFAULT_OPTIONS, ...options };
242
+ const el = await getSlideEl(target, wrap);
243
+ return el.dataset.slide === 'closed'
244
+ ? slideDown(target, options)
245
+ : slideUp(target, options);
246
+ }
@@ -0,0 +1,97 @@
1
+ /*
2
+ * CSS Module for slide-up-down-toggle.js
3
+ *
4
+ * Three modern CSS features work together to animate height without JS measurement:
5
+ *
6
+ * interpolate-size: allow-keywords
7
+ * Enables transitioning to/from `height: auto` — the browser resolves the
8
+ * intrinsic size, so JS never reads offsetHeight or scrollHeight.
9
+ *
10
+ * transition-behavior: allow-discrete (via `allow-discrete` in shorthand)
11
+ * Allows `display` to participate in a transition. On collapse: height
12
+ * animates to 0, then `display: none` snaps at the very end. On expand:
13
+ * `display: block` snaps at the very start, then height animates to auto.
14
+ *
15
+ * @starting-style
16
+ * Defines the initial state for elements entering from `display: none`.
17
+ * Without it, the browser has no "before" value to transition from and
18
+ * the expand animation would not play.
19
+ *
20
+ * ─── Usage ────────────────────────────────────────────────────────────────────
21
+ *
22
+ * wrap: true (default)
23
+ * JS generates a wrapper <div class="slide"> around the target.
24
+ * The target element is completely free — any display, padding, margin.
25
+ * No changes to HTML required; initial open state is the default.
26
+ * For an element that should start collapsed, add data-slide="closed" to
27
+ * the target BEFORE calling any slide function — JS transfers it to the wrapper.
28
+ *
29
+ * wrap: false
30
+ * JS adds .slide directly to the target element.
31
+ * The target must be a plain block wrapper (no padding, no flex/grid).
32
+ * All layout, padding and margin must live on an inner child element.
33
+ * Initial collapsed state: add data-slide="closed" directly to the target in HTML.
34
+ *
35
+ * ─── FOUC prevention ──────────────────────────────────────────────────────────
36
+ *
37
+ * Elements with data-slide="closed" are hidden via a :global rule below,
38
+ * so they start invisible even before JS adds the .slide class.
39
+ *
40
+ * ─── Duration override ────────────────────────────────────────────────────────
41
+ *
42
+ * Set --slide-duration on the element or pass `duration` in JS options:
43
+ * style="--slide-duration: 300ms"
44
+ */
45
+
46
+ /* applied to the animation wrapper (generated or the target itself) */
47
+ .slide {
48
+ interpolate-size: allow-keywords;
49
+ /*
50
+ * !important overrides any external display: none (inline or CSS rule without !important).
51
+ * .slide[data-slide='closed'] below has higher specificity (0,2,0 vs 0,1,0) so its
52
+ * display: none !important still wins when the element is collapsed.
53
+ */
54
+ /* stylelint-disable-next-line declaration-no-important */
55
+ display: block !important;
56
+ height: auto;
57
+ overflow: hidden;
58
+ transition:
59
+ height var(--slide-duration, 500ms) ease,
60
+ display var(--slide-duration, 500ms) allow-discrete;
61
+ }
62
+
63
+ /* collapsed state: height animates to 0, then display snaps to none */
64
+ .slide[data-slide='closed'] {
65
+ /* stylelint-disable-next-line declaration-no-important */
66
+ display: none !important;
67
+ height: 0;
68
+ }
69
+
70
+ /*
71
+ * Entry state for the expand transition.
72
+ * When .slide transitions from display:none → display:block, the browser needs
73
+ * a starting value for height. @starting-style provides height:0 so the
74
+ * animation plays from zero to auto instead of snapping instantly.
75
+ */
76
+ /*
77
+ * @starting-style targets only [data-slide='open'] — not :not([data-slide='closed']).
78
+ * The broader selector would also match newly inserted wrappers (which have no
79
+ * data-slide attribute), causing an unwanted entry animation from height:0 that
80
+ * conflicts with the first collapse call and makes the transition invisible.
81
+ * Using [data-slide='open'] restricts this to the expand animation triggered by
82
+ * slideDown(), which always sets data-slide="open" on a previously hidden element.
83
+ */
84
+ @starting-style {
85
+ .slide[data-slide='open'] {
86
+ height: 0;
87
+ }
88
+ }
89
+
90
+ /*
91
+ * FOUC prevention — global, no class required.
92
+ * Hides elements with data-slide="closed" before JS has run and added .slide.
93
+ * Uses :global so CSS Modules does not hash this selector.
94
+ */
95
+ :global([data-slide='closed']) {
96
+ display: none;
97
+ }
@@ -1,6 +1,7 @@
1
1
  import { domBuilder } from '../../utilities/dom-builder/dom-builder.js';
2
2
  import { classnames } from '../../utilities/classnames.js';
3
- import * as styles from './snackbar.module.css';
3
+ import * as _snackbarCss from './snackbar.module.css';
4
+ const styles = /** @type {Record<string, string>} */ (/** @type {any} */ (_snackbarCss).default ?? _snackbarCss);
4
5
 
5
6
  /*
6
7
  References
@@ -1,4 +1,5 @@
1
- import * as styles from './spinner.module.css';
1
+ import * as _spinnerCss from './spinner.module.css';
2
+ const styles = /** @type {Record<string, string>} */ (/** @type {any} */ (_spinnerCss).default ?? _spinnerCss);
2
3
 
3
4
  // The spinner class depends on the spinner type in use; the corresponding CSS file must be included.
4
5
  // TODO: system for configuring the spinner type to allow multiple spinner types in the same project