@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.
- package/design-tokens/tokens/size.minimo.tokens.jsonc +16 -16
- package/index.js +3 -2
- package/package.json +1 -1
- package/src/components/TODO form-multiselect/form-multiselect.css +40 -0
- package/src/components/TODO form-multiselect/form-multiselect.js +83 -0
- package/src/components/TODO vanilla-cookie-consent/cookie-consent.css +20 -0
- package/src/components/TODO vanilla-cookie-consent/cookie-consent.js +76 -0
- package/src/components/TODO vanilla-cookie-consent/render-cookie-list.js +32 -0
- package/src/components/TODO vanilla-cookie-consent/src/cookie-list.js +85 -0
- package/src/components/TODO vanilla-cookie-consent/src/it-translation.js +38 -0
- package/src/components/TODO vanilla-cookie-consent/src/run-analytics.js +54 -0
- package/src/components/TODO vanilla-cookie-consent/src/run-recaptcha.js +71 -0
- package/src/components/modal-alert/TODO modal-alert-demo/demo.css +63 -0
- package/src/components/modal-alert/TODO modal-alert-demo/demo.js +155 -0
- package/src/components/modal-popup/modal-popup.js +2 -1
- package/src/components/slide-up-down-toggle/slide-up-down-toggle.js +246 -0
- package/src/components/slide-up-down-toggle/slide-up-down-toggle.module.css +97 -0
- package/src/components/snackbar/snackbar.js +2 -1
- package/src/components/spinner/spinner.js +2 -1
- package/src/components/unsplash-page/TODO unsplash-page-demo/README.md +194 -0
- package/src/components/unsplash-page/TODO unsplash-page-demo/changelog.md +5 -0
- package/src/components/unsplash-page/TODO unsplash-page-demo/unsplash-page/demo.js +15 -0
- package/src/components/unsplash-page/TODO unsplash-page-demo/unsplash-page/rollup.config.mjs +26 -0
- package/src/components/unsplash-page/TODO unsplash-page-demo/unsplash-page/unsplash-page-demo.min.js +3 -0
- package/src/web-components/TODO json-table/README.md +67 -0
- package/src/web-components/TODO json-table/TODO.md +12 -0
- package/src/web-components/TODO json-table/_work/OLD/docs/custom-props-list.md +69 -0
- package/src/web-components/TODO json-table/_work/OLD/script/create-css-custom-props-doc.mjs +113 -0
- package/src/web-components/TODO json-table/_work/OLD/script/src/custom-props-end.md +4 -0
- package/src/web-components/TODO json-table/_work/OLD/script/src/custom-props-start.md +30 -0
- package/src/web-components/TODO json-table/_work/OLD/src/css/icons.module.css +22 -0
- package/src/web-components/TODO json-table/_work/OLD/src/css/info.module.css +42 -0
- package/src/web-components/TODO json-table/_work/OLD/src/css/main-wrapper.module.css +4 -0
- package/src/web-components/TODO json-table/_work/OLD/src/css/table.module.css +154 -0
- package/src/web-components/TODO json-table/_work/OLD/src/css/utility.module.css +9 -0
- package/src/web-components/TODO json-table/_work/OLD/src/icons/false.svg +1 -0
- package/src/web-components/TODO json-table/_work/OLD/src/icons/search-arrows.svg +1 -0
- package/src/web-components/TODO json-table/_work/OLD/src/icons/true.svg +1 -0
- package/src/web-components/TODO json-table/_work/OLD/src/index.js +56 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/default-columns-data-types.js +172 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/defaults.js +156 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/info-section.js +31 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/listeners.js +17 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/main-builder.js +26 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/parse-params.js +121 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/set-column-classname.js +22 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/table-builder.js +64 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/table-foot.js +8 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/table-head.js +47 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/table-row.js +83 -0
- package/src/web-components/TODO json-table/_work/OLD/src/js/utilities.js +5 -0
- package/src/web-components/TODO json-table/_work/__json-table-react/index.js +4 -0
- package/src/web-components/TODO json-table/_work/__json-table-react/src/build-page-array.js +73 -0
- package/src/web-components/TODO json-table/_work/__json-table-react/src/columns-data-types.js +73 -0
- package/src/web-components/TODO json-table/_work/__json-table-react/src/defaults.js +50 -0
- package/src/web-components/TODO json-table/_work/__json-table-react/src/download-excel.js +156 -0
- package/src/web-components/TODO json-table/_work/__json-table-react/src/set-className.js +19 -0
- package/src/web-components/TODO json-table/_work/__json-table-react/src/set-download-filename.js +17 -0
- package/src/web-components/TODO json-table/_work/__json-table-react/src/table-to-csv.js +48 -0
- package/src/web-components/TODO json-table/_work/archived/table-to-csv.js +48 -0
- package/src/web-components/TODO json-table/_work/arrow.svg +3 -0
- package/src/web-components/TODO json-table/_work/da decidere/get-cell-data.js +18 -0
- package/src/web-components/TODO json-table/_work/download-button.js +29 -0
- package/src/web-components/TODO json-table/_work/download-excel.js +155 -0
- package/src/web-components/TODO json-table/_work/pagination-array-builder.js +73 -0
- package/src/web-components/TODO json-table/_work/pagination.js +37 -0
- package/src/web-components/TODO json-table/_work/set-download-filename.js +19 -0
- package/src/web-components/TODO json-table/_work/table-info.js +24 -0
- package/src/web-components/TODO json-table/demo/README.md +66 -0
- package/src/web-components/TODO json-table/demo/assets/link-simple.svg +1 -0
- package/src/web-components/TODO json-table/demo/demo-data/json-static-table-demo-data.js +512 -0
- package/src/web-components/TODO json-table/demo/demo.css +32 -0
- package/src/web-components/TODO json-table/demo/demo.js +24 -0
- package/src/web-components/TODO json-table/demo/js/demo-ajax-table.js +165 -0
- package/src/web-components/TODO json-table/demo/js/demo-static-table.js +180 -0
- package/src/web-components/TODO json-table/demo/webpack-modules/css-rules.mjs +122 -0
- package/src/web-components/TODO json-table/demo/webpack-modules/get-jsConfig-aliases.mjs +33 -0
- package/src/web-components/TODO json-table/demo/webpack-modules/svg-rules.mjs +108 -0
- package/src/web-components/TODO json-table/demo/webpack-modules/svgo.config.mjs +26 -0
- package/src/web-components/TODO json-table/demo/webpack.config.mjs +333 -0
- package/src/web-components/TODO json-table/docs/custom-props-list.md +74 -0
- package/src/web-components/TODO json-table/docs-builder/create-css-custom-props-doc.mjs +157 -0
- package/src/web-components/TODO json-table/docs-builder/src/custom-props-end.md +6 -0
- package/src/web-components/TODO json-table/docs-builder/src/custom-props-start.md +29 -0
- package/src/web-components/TODO json-table/src/TODO.md +1 -0
- package/src/web-components/TODO json-table/src/__json-table-react/build-page-array.js +73 -0
- package/src/web-components/TODO json-table/src/__json-table-react/columns-data-types.js +73 -0
- package/src/web-components/TODO json-table/src/__json-table-react/defaults.js +50 -0
- package/src/web-components/TODO json-table/src/__json-table-react/download-excel.js +156 -0
- package/src/web-components/TODO json-table/src/__json-table-react/set-className.js +19 -0
- package/src/web-components/TODO json-table/src/__json-table-react/set-download-filename.js +17 -0
- package/src/web-components/TODO json-table/src/__json-table-react/table-to-csv.js +48 -0
- package/src/web-components/TODO json-table/src/css/custom-media.css +16 -0
- package/src/web-components/TODO json-table/src/css/icons.module.css +22 -0
- package/src/web-components/TODO json-table/src/css/info-section.module.css +78 -0
- package/src/web-components/TODO json-table/src/css/main-builder.module.css +6 -0
- package/src/web-components/TODO json-table/src/css/table.module.css +172 -0
- package/src/web-components/TODO json-table/src/css/utility.module.css +9 -0
- package/src/web-components/TODO json-table/src/icons/arrow-down-bold.svg +1 -0
- package/src/web-components/TODO json-table/src/icons/false.svg +1 -0
- package/src/web-components/TODO json-table/src/icons/true.svg +1 -0
- package/src/web-components/TODO json-table/src/index.js +125 -0
- package/src/web-components/TODO json-table/src/js/default-columns-data-types.js +172 -0
- package/src/web-components/TODO json-table/src/js/defaults.js +510 -0
- package/src/web-components/TODO json-table/src/js/get-ajax-data.js +72 -0
- package/src/web-components/TODO json-table/src/js/info-section.js +39 -0
- package/src/web-components/TODO json-table/src/js/init-ajax-table.js +30 -0
- package/src/web-components/TODO json-table/src/js/init-static-table.js +18 -0
- package/src/web-components/TODO json-table/src/js/main-builder.js +87 -0
- package/src/web-components/TODO json-table/src/js/parse-data-row.js +123 -0
- package/src/web-components/TODO json-table/src/js/parse-params.js +118 -0
- package/src/web-components/TODO json-table/src/js/set-search-listener.js +62 -0
- package/src/web-components/TODO json-table/src/js/set-sort-listeners.js +115 -0
- package/src/web-components/TODO json-table/src/js/static-data-sorting.js +23 -0
- package/src/web-components/TODO json-table/src/js/table-builder.js +45 -0
- package/src/web-components/TODO json-table/src/js/table-row.js +43 -0
- package/src/web-components/TODO json-table/src/js/table-tfoot.js +9 -0
- package/src/web-components/TODO json-table/src/js/table-thead.js +91 -0
- package/src/web-components/TODO json-table/src/js/update-info.js +42 -0
- package/src/web-components/TODO json-table/src/js/utilities.js +5 -0
- package/src/web-components/s-datatable-component/s-datatable-component.js +2 -1
- 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
|
|
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
|
|
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
|
|
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
|