@massimo-cassandro/minimo 0.12.16 → 0.13.1

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/index.js CHANGED
@@ -14,3 +14,4 @@ export { innerNav } from './src/components/inner-nav/inner-nav.js';
14
14
  export { overlay, removeOverlay } from './src/components/overlay/overlay.js';
15
15
  export { sf_macro } from './src/components/sf-macro/sf-macro.js';
16
16
  export { snackbar } from './src/components/snackbar/snackbar.js';
17
+ export { unsplashPageJS } from './src/components/unsplash-page/unsplash-page.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massimo-cassandro/minimo",
3
- "version": "0.12.16",
3
+ "version": "0.13.1",
4
4
  "description": "Light css framework & utilities",
5
5
  "type": "module",
6
6
  "homepage": "https://github.com/massimo-cassandro/minimo#readme",
@@ -0,0 +1,2 @@
1
+ riscrivere css con sizes
2
+ rivedere js
@@ -0,0 +1,65 @@
1
+
2
+ export async function fetchUnsplashData(settings) {
3
+
4
+ const default_settings = {
5
+ unsplash_data_url: null
6
+ };
7
+
8
+ settings = {...default_settings, ...settings};
9
+
10
+ try {
11
+
12
+ if(!settings.unsplash_data_url) {
13
+ throw new Error( 'Unsplash data url must be defined' );
14
+ }
15
+
16
+ const imgData = await (async () => {
17
+ const response = await fetch(settings.unsplash_data_url);
18
+ if (!response.ok) {
19
+ /* eslint-disable no-console */
20
+ console.error('Ajax error on: ' + settings.unsplash_data_url);
21
+ console.error(response);
22
+ /* eslint-enable no-console */
23
+ throw new Error( `Loading error: ${response.status}` );
24
+ }
25
+ const data = await response.json();
26
+ return data;
27
+ })()
28
+ .then(data => {
29
+
30
+ // console.log(data);
31
+
32
+ // used data
33
+ return {
34
+ id : data.id,
35
+ color : data.color,
36
+ width : data.width,
37
+ height : data.height,
38
+ // description : data.description,
39
+ // location : data.location.name,
40
+ alt_description : data.alt_description,
41
+ date : data.created_at,
42
+ base_url : data.urls.raw,
43
+ unsplash_url : data.links.html,
44
+ author : data.user.name?? data.user.username,
45
+ author_profile : data.user.links.html,
46
+ blur_hash : data.blur_hash,
47
+ image_description : (() => {
48
+ let location = data.location.name,
49
+ description = data.description?? data.alt_description;
50
+ if(data.description && location) {
51
+ location = (new RegExp(location, 'i')).test(description)? null : location;
52
+ }
53
+ return [description, location]
54
+ .filter(i => i != null).join (' / ');
55
+ })()
56
+
57
+ };
58
+ });
59
+
60
+ return imgData;
61
+
62
+ } catch(e) {
63
+ console.error( e ); // eslint-disable-line
64
+ }
65
+ }
@@ -0,0 +1,55 @@
1
+ export const breakpoints = [
2
+ {
3
+ name: 'xxl',
4
+ mq: '(min-width: 1400px)',
5
+ w: 1920,
6
+ h: 1080,
7
+ dpr2: false
8
+ },
9
+ {
10
+ name: 'xl',
11
+ mq: '(min-width: 1200px) and (max-width: 1399px)',
12
+ w: 1400,
13
+ h: 788,
14
+ dpr2: false
15
+ },
16
+ {
17
+ name: 'lg',
18
+ mq: '(min-width: 992px) and (max-width: 1199px)',
19
+ w: 1200,
20
+ h: 675,
21
+ dpr2: false
22
+ },
23
+ {
24
+ name: 'md',
25
+ ar: '16/9',
26
+ mq: '(min-width: 768px) and (max-width: 991px)',
27
+ w: 992,
28
+ h: 558,
29
+ dpr2: true
30
+ },
31
+ {
32
+ name: 'sm',
33
+ ar: '16/9',
34
+ mq: '(min-width: 576px) and (max-width: 767px)',
35
+ w: 768,
36
+ h: 432,
37
+ dpr2: true
38
+ },
39
+ {
40
+ name: 'xs-portrait',
41
+ ar: '16/9',
42
+ mq: '(orientation: portrait) and (max-width: 575px)',
43
+ w: 324,
44
+ h: 576,
45
+ dpr2: true
46
+ },
47
+ {
48
+ name: 'xs-landscape',
49
+ ar: '16/9',
50
+ mq: '(orientation: landscape) and (max-width: 575px)',
51
+ w: 576,
52
+ h: 324,
53
+ dpr2: true
54
+ }
55
+ ];
@@ -0,0 +1,14 @@
1
+ /* reset padding e margin */
2
+ /* tenuto separato in caso di conflitti con altre impostazioni */
3
+
4
+ html, body {
5
+ height: 100%;
6
+ padding: 0;
7
+ margin: 0;
8
+
9
+ }
10
+
11
+ *, *::before, *::after {
12
+ /* stylelint-disable declaration-no-important */
13
+ box-sizing: border-box !important;
14
+ }
@@ -0,0 +1,146 @@
1
+ import imageIcon from '../../icons/image-duotone.svg';
2
+ import arrowIcon from '../icons/arrow-fat-lines-left-duotone.svg';
3
+ import { breakpoints } from './img-breakpoints.js';
4
+ import { fetchUnsplashData } from './fetch-unsplash-data.js';
5
+ import { decode } from 'blurhash';
6
+
7
+ export function unsplashPageJS(settings) {
8
+
9
+ const default_settings = {
10
+ targetElement : null,
11
+ className : null,
12
+ unsplashDataUrl : null,
13
+ utmSource : null,
14
+ title : null,
15
+ text : null,
16
+ backLink : null,
17
+ hidePhotoLink : true,
18
+ cssModulesObj : null
19
+ },
20
+ required_settings = ['targetElement', 'unsplashDataUrl', 'utmSource', 'title'];
21
+
22
+ settings = {...default_settings, ...settings};
23
+
24
+
25
+ try {
26
+
27
+ if(required_settings
28
+ .map(i => settings[i])
29
+ .filter(i => i !== null && i !== '').length !== required_settings.length) {
30
+
31
+ throw new Error( `I parametri ${required_settings.map(i => `\`${i}\``).join(',')} sono obbligatori` );
32
+ }
33
+
34
+
35
+ const cssClass = classname => settings.cssModulesObj? settings.cssModulesObj[classname] : classname;
36
+
37
+ settings.targetElement.innerHTML = `<div class="${cssClass('upContainer') + (settings.className? ` ${settings.className}` : '')}"></div>`;
38
+ const container = settings.targetElement.querySelector('.' + cssClass('upContainer'));
39
+ container.innerHTML = `<div class="${cssClass('upLoaderWrapper')}"><div class="${cssClass('upLoader')}"></div></div>`;
40
+
41
+ fetchUnsplashData({unsplash_data_url: settings.unsplashDataUrl})
42
+ .then(photo => {
43
+
44
+ const pixels = decode(photo.blur_hash, container.offsetWidth, container.offsetHeight);
45
+
46
+ const canvas = document.createElement('canvas');
47
+ canvas.className = cssClass('upCanvas');
48
+ canvas.width = container.offsetWidth;
49
+ canvas.height = container.offsetHeight;
50
+ const ctx = canvas.getContext('2d');
51
+ const imageData = ctx.createImageData(container.offsetWidth, container.offsetHeight);
52
+ imageData.data.set(pixels);
53
+ ctx.putImageData(imageData, 0, 0);
54
+
55
+
56
+ container.insertAdjacentElement('afterbegin', canvas);
57
+
58
+ const formats = ['avif', 'webp', 'pjpg']; // `fm` parameter, in order of use
59
+
60
+ container.insertAdjacentHTML('beforeend',
61
+ '<picture>' +
62
+ breakpoints.map((brk, idx) => {
63
+
64
+ const is_last_brk = idx === breakpoints.length - 1;
65
+ return formats.map(fmt => {
66
+ const is_default_fmt = fmt === formats.at(-1);
67
+
68
+ // https://unsplash.com/documentation#supported-parameters
69
+ // https://docs.imgix.com/apis/rendering/size/w
70
+ // https://docs.imgix.com/apis/rendering/size/h
71
+ // https://docs.imgix.com/apis/rendering/size/ar
72
+ // https://docs.imgix.com/apis/rendering/size/fit
73
+ // https://docs.imgix.com/apis/rendering/size/crop
74
+ // https://docs.imgix.com/apis/rendering/format/q
75
+
76
+ let url = photo.base_url + (/\?/.test(photo.base_url)? '&' : '?') +
77
+ 'fit=crop&crop=focalpoint' + // top, bottom, left, right, faces, focalpoint, edges, and entropy
78
+ '&q=60' +
79
+ `&w=${brk.w}&h=${brk.h}` +
80
+ `&fm=${fmt}`;
81
+
82
+ if(is_last_brk && is_default_fmt) {
83
+
84
+ return '<img ' +
85
+ `class="${cssClass('unsplashPhoto')}" `+
86
+ `src="${url}" `+
87
+ `srcset="${url}${brk.dpr2? ` 1x, ${url}&dpr=2 2x` : ''}" `+
88
+ `alt="${photo.alt_description?? `${photo.author} / Unsplash`}" `+
89
+ `width="${brk.w}" height="${brk.h}">`;
90
+
91
+ } else {
92
+ return '<source ' +
93
+ `srcset="${url}${brk.dpr2? ` 1x, ${url}&dpr=2 2x` : ''}" `+
94
+ (!is_default_fmt? `type="image/${fmt}" ` : '')+
95
+ `media="${brk.mq}" `+
96
+ `width="${brk.w}" height="${brk.h}">`;
97
+ }
98
+ }).join('');
99
+ }).join('') +
100
+ '</picture>'
101
+ ); // end insert <picture>
102
+
103
+ const img = container.querySelector('.' + cssClass('unsplashPhoto'));
104
+ img.onload = () => {
105
+ container.querySelector('.' + cssClass('upLoaderWrapper'))?.remove();
106
+ container.classList.add(cssClass('show'));
107
+
108
+ container.insertAdjacentHTML('beforeend', `<div class="${cssClass('upMessageBox')}">
109
+ <div class="${cssClass('upMessage')}">
110
+ <h1>${settings.title}</h1>
111
+ ${settings.text? `<p>${settings.text}</p>` : ''}
112
+ ${settings.backLink ? `<p class="${cssClass('upBackLink')}">${settings.backLink}</p>` : ''}
113
+
114
+ <div class="${cssClass('upArrowWrapper')}" role="button">
115
+ <img src="${arrowIcon}" alt="Icona freccia">
116
+ </div>
117
+ </div>
118
+
119
+ <div class="${cssClass('upCredits')}">
120
+ <em>${photo.image_description}</em>
121
+ <span>Photo
122
+ <a href="${`${photo.author_profile}?utmSource=${settings.utmSource}&utm_medium=referral`}">
123
+ ${photo.author} / Unsplash
124
+ </a>
125
+ </span>
126
+ </div>
127
+ </div>
128
+ <div class="${cssClass('unsplashPhotoLink')}${settings.hidePhotoLink? ` ${cssClass('upShowOnHover')}` : ''}">
129
+ <a href="${`${photo.unsplash_url}?utm_source=${settings.utmSource}&utm_medium=referral`}" target="_blank" rel="noopener noreferrer">
130
+ <img src="${imageIcon}" alt="Icona immagine" />
131
+ </a>
132
+ </div>`);
133
+
134
+ container.querySelector('.' + cssClass('upArrowWrapper')).addEventListener('click', e => {
135
+ e.target.closest(`.${cssClass('upMessage')}`).classList.toggle(cssClass('hidden'));
136
+ }, false);
137
+
138
+ }; // end img.onload
139
+
140
+ }); // end .then
141
+
142
+ } catch(e) {
143
+ console.error( e ); // eslint-disable-line
144
+ }
145
+
146
+ }
@@ -0,0 +1,323 @@
1
+ /*
2
+ PERSONALIZZAZIONE
3
+ custom properties (valori di default):
4
+
5
+ Basic props:
6
+ --up-bg-color: hsl(0deg 0% 0% / .7);
7
+ --up-text-color: #fff;
8
+ --up-line-height: 1.4;
9
+ --up-font-family: sans-serif;
10
+ --up-font-size: 1rem;
11
+ --up-font-variation-settings: unset;
12
+ --up-font-weight: 400;
13
+
14
+ Credits box
15
+ --up-credits-font-size: .8em;
16
+ --up-credits-font-weight: 400;
17
+ --up-credits-line-height: 1.3;
18
+
19
+ H1
20
+ --up-h1-color: var(--up-text-color);
21
+ --up-h1-font-size: 2rem;
22
+ --up-h1-font-variation-settings: unset;
23
+ --up-h1-font-weight: 700;
24
+ --up-h1-line-height: 1.25;
25
+
26
+ icons:
27
+ --up-icon-box-bg: var(--up-link-color);
28
+ --up-icon-fill-color: #333;
29
+ --up-icon-hover-box-bg: #fff;
30
+
31
+ links:
32
+ --up-link-color: #fc0;
33
+ --up-link-decoration: none;
34
+ --up-link-hover-color: #fc0;
35
+ --up-link-hover-decoration: underline;
36
+
37
+ loader:
38
+ --up-loader-color: hsl(0deg 0% 100% / .6);
39
+
40
+ */
41
+
42
+
43
+ /* stylelint-disable declaration-no-important */
44
+
45
+ .bodyNoScroll {
46
+ padding: 0 !important;
47
+ margin: 0 !important;
48
+ overflow: hidden !important;
49
+
50
+
51
+ }
52
+ /* stylelint-enable declaration-no-important */
53
+
54
+ .upContainer {
55
+
56
+ position: relative;
57
+ width: 100dvw;
58
+ height: 100dvh;
59
+
60
+
61
+ font-family: var(--up-font-family, sans-serif);
62
+ font-size: var(--up-font-size, 1rem);
63
+ font-variation-settings: var(--up-font-variation-settings, unset);
64
+ font-weight: var(--up-font-weight, 400);
65
+ line-height: var(--up-line-height, 1.4);
66
+
67
+ background-color: #333;
68
+
69
+ a:is(:link, :visited) {
70
+ color: var(--up-link-color, #fc0);
71
+ text-decoration: var(--up-link-decoration, none);
72
+
73
+ @media (hover: hover) {
74
+ &:hover {
75
+ color: var(--up-link-hover-color, #fc0);
76
+ text-decoration: var(--up-link-hover-decoration, underline);
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ .upCanvas {
83
+ position: absolute;
84
+ /* z-index: -1; */
85
+ width: 100%;
86
+ height: 100%;
87
+ }
88
+
89
+ .unsplashPhoto { /* img */
90
+ position: relative;
91
+ z-index: 0;
92
+ display: block;
93
+ width: 100dvw;
94
+ height: 100dvh;
95
+ object-fit: cover;
96
+ object-position: center;
97
+
98
+ /* font-size: 1.2rem; */
99
+ /* color: #999; */
100
+ /* text-align: center; */
101
+
102
+ }
103
+
104
+ .unsplashPhoto, .upCredits {
105
+ opacity: 0;
106
+ transition: opacity .3s linear;
107
+
108
+ .show & {
109
+ opacity: 1;
110
+ }
111
+ }
112
+
113
+ .upMessageBox {
114
+ position: absolute;
115
+ bottom: 0;
116
+ display: flex;
117
+ flex-flow: column nowrap;
118
+ gap: 3rem;
119
+ align-items: center;
120
+ justify-content: center;
121
+ width: 100%;
122
+ overflow: hidden;
123
+ }
124
+
125
+ .upMessage, .upCredits {
126
+ color: var(--up-text-color, #fff);
127
+ background-color: var(--up-bg-color, hsl(0deg 0% 0% / .7));
128
+ }
129
+
130
+ .upMessage {
131
+ position: relative;
132
+ width: max-content;
133
+ max-width: 90dvw;
134
+ padding: 1rem 2rem;
135
+ text-align: center;
136
+ transition: translate .3s ease-in-out;
137
+
138
+ h1 {
139
+ margin: 0;
140
+ font-size: var(--up-h1-font-size, 2rem);
141
+ font-variation-settings: var(--up-h1-font-variation-settings, unset);
142
+ font-weight: var(--up-h1-font-weight, 700);
143
+ line-height: var(--up-h1-line-height, 1.25);
144
+ color: var(--up-h1-color, var(--up-text-color, #fff));
145
+ }
146
+
147
+ p {
148
+ margin: .5rem 0 0;
149
+ }
150
+
151
+ @media screen and (min-width: 768px) {
152
+ max-width: 60dvw;
153
+ }
154
+
155
+ .upBackLink {
156
+ margin-top: 1rem;
157
+ }
158
+
159
+ .upArrowWrapper {
160
+ --arrow-size: 2rem;
161
+ --arrow-position: calc(var(--arrow-size) * .25 * -1);
162
+
163
+ position: absolute;
164
+ bottom: var(--arrow-position);
165
+ left: var(--arrow-position);
166
+ width: var(--arrow-size);
167
+ height: var(--arrow-size);
168
+ color: var(--up-icon-fill-color, #333);
169
+ cursor: w-resize;
170
+ background-color: var(--up-icon-box-bg, var(--up-link-color, #fc0));
171
+ border-radius: 50%;
172
+ /* transition: all .2s ease-in-out; */
173
+ /* duration | easing-function | delay | iteration-count | direction | name */
174
+ animation: .2s ease-in 2s 2 reverse icon-shaking;
175
+
176
+ @media (hover: hover) {
177
+ &:hover {
178
+ background-color: var(--up-icon-hover-box-bg, #fff);
179
+ }
180
+ }
181
+
182
+ img {
183
+ display: block;
184
+ width: 100%;
185
+ height: 100%;
186
+ }
187
+ }
188
+
189
+ &.hidden {
190
+ translate: calc(-1 * (50dvw + 50% - 2rem));
191
+ .upArrowWrapper {
192
+ right: var(--arrow-position);
193
+ left: auto;
194
+ cursor: e-resize;
195
+ rotate: .5turn;
196
+ }
197
+ }
198
+
199
+ }
200
+
201
+ @keyframes icon-shaking {
202
+ 0% { transform: translateX(0); }
203
+ 40% { transform: translateX(20px); }
204
+ 80% { transform: translateX(-5px); }
205
+ 100% { transform: translateX(0); }
206
+ }
207
+
208
+ .upCredits {
209
+ display: flex;
210
+ flex-flow: column wrap;
211
+ gap: .5rem;
212
+ align-items: center;
213
+ justify-content: center;
214
+ width: 100%;
215
+ padding: .2rem 1rem;
216
+ font-size: var(--up-credits-font-size, .8em);
217
+ font-weight: var(--up-credits-font-weight, 400);
218
+ line-height: var(--up-credits-line-height, 1.3);
219
+
220
+
221
+ @media screen and (min-width: 768px) {
222
+ flex-direction: row;
223
+ justify-content: space-between;
224
+ }
225
+ }
226
+
227
+
228
+ /* link a scomparsa alla pagina della foto */
229
+ .unsplashPhotoLink {
230
+ position: absolute;
231
+ top: 1rem;
232
+ right: 1rem;
233
+
234
+ a {
235
+ display: flex;
236
+ align-items: center;
237
+ justify-content: center;
238
+ width: 2.5rem;
239
+ aspect-ratio: 1;
240
+ padding: 4px;
241
+ color: #fff;
242
+ background-color: rgb(0 0 0 / .5);
243
+ border-radius: 50%;
244
+
245
+ &:active {
246
+ color: var(--up-icon-fill-color, #333);
247
+ background-color: var(--up-icon-box-bg, var(--up-link-color, #fc0));
248
+
249
+ img {
250
+ filter: none;
251
+ opacity: 1;
252
+ }
253
+ }
254
+ }
255
+ img {
256
+ display: block;
257
+ filter: brightness(0) invert(1);
258
+ opacity: .6;
259
+ }
260
+
261
+ @media (hover: hover) {
262
+
263
+ .show &:hover {
264
+ img {
265
+ opacity: 1;
266
+ }
267
+ }
268
+
269
+ &.upShowOnHover {
270
+ opacity: 0;
271
+ .show &:hover {
272
+ opacity: 1;
273
+ }
274
+ }
275
+ }
276
+ }
277
+
278
+
279
+ /* https://wweb.dev/resources/loader-generator/ */
280
+ .upLoaderWrapper {
281
+
282
+ position: absolute;
283
+ top: 40%;
284
+ left: 50%;
285
+ /* z-index: -1; */
286
+ transform: translate(-50%, -50%);
287
+ }
288
+ .upLoader {
289
+ width: 80px;
290
+ aspect-ratio: 1;
291
+ background: conic-gradient(#000, var(--up-loader-color, hsl(0deg 0% 100% / .6))) content-box;
292
+ border-radius: 50%;
293
+ /* stylelint-disable-next-line property-no-vendor-prefix */
294
+ -webkit-mask:
295
+ repeating-conic-gradient(
296
+ #0000 0deg,
297
+ #000 1deg calc(360deg / 10 - 10deg - 1deg),
298
+ #0000 calc(360deg / 10 - 10deg) calc(360deg / 10)
299
+ ),
300
+ radial-gradient(
301
+ farthest-side,
302
+ #0000 calc(98% - 10px),
303
+ #000 calc(100% - 10px)
304
+ );
305
+ mask:
306
+ repeating-conic-gradient(
307
+ #0000 0deg,
308
+ #000 1deg calc(360deg / 10 - 10deg - 1deg),
309
+ #0000 calc(360deg / 10 - 10deg) calc(360deg / 10)
310
+ ),
311
+ radial-gradient(
312
+ farthest-side,
313
+ #0000 calc(98% - 10px),
314
+ #000 calc(100% - 10px)
315
+ );
316
+
317
+ /* stylelint-disable-next-line property-no-vendor-prefix */
318
+ -webkit-mask-composite: destination-in;
319
+ mask-composite: intersect;
320
+ animation: spin 1000ms infinite steps(10);
321
+ }
322
+ @keyframes spin { to { transform: rotate(1turn); } }
323
+
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M152,80v96H120v48L24,128l96-96V80Z" opacity="0.2"></path><path d="M152,72H128V32a8,8,0,0,0-13.66-5.66l-96,96a8,8,0,0,0,0,11.32l96,96A8,8,0,0,0,128,224V184h24a8,8,0,0,0,8-8V80A8,8,0,0,0,152,72Zm-8,96H120a8,8,0,0,0-8,8v28.69L35.31,128,112,51.31V80a8,8,0,0,0,8,8h24Zm80-88v96a8,8,0,0,1-16,0V80a8,8,0,0,1,16,0Zm-32,0v96a8,8,0,0,1-16,0V80a8,8,0,0,1,16,0Z"></path></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M224,56V178.06l-39.72-39.72a8,8,0,0,0-11.31,0L147.31,164,97.66,114.34a8,8,0,0,0-11.32,0L32,168.69V56a8,8,0,0,1,8-8H216A8,8,0,0,1,224,56Z" opacity="0.2"></path><path d="M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,16V158.75l-26.07-26.06a16,16,0,0,0-22.63,0l-20,20-44-44a16,16,0,0,0-22.62,0L40,149.37V56ZM40,172l52-52,80,80H40Zm176,28H194.63l-36-36,20-20L216,181.38V200ZM144,100a12,12,0,1,1,12,12A12,12,0,0,1,144,100Z"></path></svg>