@massimo-cassandro/minimo 1.44.0 → 1.45.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.
@@ -0,0 +1,11 @@
1
+ # Custom media builder
2
+
3
+ Genera il file css delle @custom-media a partire da un modulo JS che esporta
4
+ (default) un oggetto { nome: media-query } e un un secondo oggetto breakpoint.js
5
+ per la condivisione dei breakpoiunt in js, vedi `src/custom-media.js`.
6
+
7
+ Uso da riga di comando (percorsi relativi alla directory corrente):
8
+
9
+ ```bash
10
+ node custom-media-builder.mjs [--src=./app/css/custom-media.js] [--dest=<src con estensione .css>]
11
+ ```
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+
3
+ /* eslint-disable no-console */
4
+ import fs from 'fs';
5
+ import path from 'path';
6
+ import process from 'process';
7
+ import { pathToFileURL } from 'url';
8
+
9
+ /**
10
+ * Genera il file css delle @custom-media.
11
+ * Il file viene riscritto solo se il contenuto è cambiato,
12
+ * per non attivare inutilmente il watcher di webpack.
13
+ *
14
+ * @param {object} [options]
15
+ * @param {string} [options.src] modulo JS con l'export default delle custom media
16
+ * @param {string} [options.dest] file css da generare (default: file in `src` con estensione cambiata in `.css`)
17
+ * @returns {Promise<boolean>} `true` se il file è stato riscritto
18
+ *
19
+ * @example
20
+ * await buildCustomMedia({
21
+ * src: './app/css/custom-media.js',
22
+ * dest: './app/css/custom-media.css',
23
+ * });
24
+ */
25
+ export async function buildCustomMedia({
26
+ src = './app/css/custom-media.js',
27
+ dest = null,
28
+ } = {}) {
29
+
30
+ const srcPath = path.resolve(src),
31
+ destPath = path.resolve(dest ?? srcPath.replace(/\.m?js$/, '.css'));
32
+
33
+ const { default: customMedia } = await import(pathToFileURL(srcPath).href);
34
+
35
+ if (!customMedia || typeof customMedia !== 'object') {
36
+ throw new Error(`${src}: export default mancante o non valido`);
37
+ }
38
+
39
+ const rows = Object.entries(customMedia).map(([name, query]) => {
40
+ if (typeof query !== 'string' || !query.trim()) {
41
+ throw new Error(`${src}: valore non valido per "${name}"`);
42
+ }
43
+ return `@custom-media --${name.replace(/^--/, '')} ${query.trim()};`;
44
+ });
45
+
46
+ const content = '/* File generato da custom-media-builder.mjs a partire da ' +
47
+ `${path.basename(srcPath)}. Eventuali modifich andranno perdute */\n\n` +
48
+ rows.join('\n') + '\n';
49
+
50
+ if (fs.existsSync(destPath) && fs.readFileSync(destPath, 'utf8') === content) {
51
+ return false;
52
+ }
53
+
54
+ fs.writeFileSync(destPath, content);
55
+ return true;
56
+ }
57
+
58
+ // esecuzione da riga di comando
59
+ if (process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) {
60
+ const args = Object.fromEntries(
61
+ process.argv.slice(2)
62
+ .map(arg => arg.match(/^--(src|dest)=(.+)$/))
63
+ .filter(Boolean)
64
+ .map(([, key, value]) => [key, value])
65
+ );
66
+
67
+ try {
68
+ const written = await buildCustomMedia(args);
69
+ console.log(written ? 'custom media: file aggiornato' : 'custom media: nessuna modifica');
70
+ } catch (err) {
71
+ console.error(err.message);
72
+ process.exit(1);
73
+ }
74
+ }
@@ -1,8 +1,8 @@
1
1
  {#
2
- Bootstrap 5 Symfony form layout
2
+ minimo form layout (ex bs5)
3
3
  =======================================
4
4
  Massimo Cassandro
5
- https://github.com/massimo-cassandro/symfony-bootstrap-form-theme
5
+ v. 2.1
6
6
  #}
7
7
 
8
8
  {#
@@ -112,11 +112,17 @@
112
112
  {% set params = {} %}
113
113
  {%- endif -%}
114
114
  {%- if params.container_attr is not defined %}
115
- {% set params = params|merge({container_attr: {}}) %}
115
+ {% set params = params|merge({container_attr: {} }) %}
116
116
  {%- endif -%}
117
117
 
118
118
  {% set params = params|merge({
119
- container_attr: params.container_attr|merge({ class: (params.container_attr.class|default('') ~ (compound|default()? ' form-collection-fset form-group' : ' form-group'))|trim })
119
+ container_attr: params.container_attr
120
+ |merge({
121
+ class: (
122
+ container_class|default('') ~ ' ' ~
123
+ params.container_attr.class|default('') ~
124
+ (compound|default()? ' form-collection-fset form-group' : ' form-group')
125
+ )|trim })
120
126
  }) %}
121
127
 
122
128
  {%- if disabled is defined and disabled %}
@@ -31,6 +31,7 @@
31
31
  "create-favicons": "npx create-favicons --dir=./app/favicons",
32
32
  "python server": "python3 -m http.server [[port8000]] # --directory __dirname__ # 8000 = default port",
33
33
  "node server": "node serve # richiede ‘npm i serve’",
34
+ "build custom media": "npx custom-media-builder --src=./app/css/custom-media.js",
34
35
  "build tokens": "npx buildTokens --config ./app/css/tokens-config.mjs",
35
36
  "check unresolved props": "npx checkUnresolvedProps --config ./app/css/tokens-config.mjs",
36
37
  "find orphan css classes": "npx findOrphanCssClasses --config ./app/css/orphan-css-classes.config.mjs",
@@ -458,6 +458,7 @@ done
458
458
  MINIMO_PKG_DIR=./node_modules/@massimo-cassandro/minimo
459
459
 
460
460
  force_cat "${MINIMO_PKG_DIR}/src/custom-properties.css" "${FRONTEND_INSTALL_PATH}/css/minimo-custom-properties.css"
461
+ force_cat "${MINIMO_PKG_DIR}/src/custom-media.js" "${FRONTEND_INSTALL_PATH}/css/custom-media.js"
461
462
  force_cat "${MINIMO_PKG_DIR}/src/custom-media.css" "${FRONTEND_INSTALL_PATH}/css/custom-media.css"
462
463
 
463
464
  # entry css principale del progetto: copia diretta di minimo.css
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@massimo-cassandro/minimo",
3
- "version": "1.44.0",
3
+ "version": "1.45.0",
4
4
  "description": "Light css framework & utilities",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -34,6 +34,7 @@
34
34
  "upd@m": "dev-tools/upd@m/index.mjs",
35
35
  "svgIconsTools": "dev-tools/svg-icons-tools/index.mjs",
36
36
  "create-favicons": "dev-tools/create-favicons/index.mjs",
37
+ "custom-media-builder": "dev-tools/custom-media-builder/custom-media-builder.mjs",
37
38
  "starter-kit": "dev-tools/starter-kit/starter-install.sh"
38
39
  },
39
40
  "repository": {
@@ -47,6 +48,7 @@
47
48
  "build-margin-padding-css": "node ./scripts/build-margin-padding-css.mjs",
48
49
  "generate:types": "node ./scripts/generate-class-types.mjs",
49
50
  "prepublishOnly": "npm run generate:types",
51
+ "build custom media": "node ./dev-tools/custom-media-builder/custom-media-builder.mjs --src=./src/custom-media.js",
50
52
  "check unresolved props": "node ./dev-tools/design-tokens-builder/check-unresolved-custom-props.mjs --config ./design-tokens/tokens-config.mjs",
51
53
  "test": "node --test \"test/**/*.test.mjs\"",
52
54
  "test sideEffects tree-shaking": "node ./test/sideEffects-tree-shaking/run-test.mjs",
@@ -151,6 +151,7 @@ input[type='checkbox'] {
151
151
  display: block;
152
152
  padding-left: 1.5em;
153
153
  margin-block-start: var(--size-sm);
154
+ break-inside: avoid;
154
155
 
155
156
  .form-check-input {
156
157
  float: left;
@@ -1,40 +1,17 @@
1
- /* TODO valutare rinomina dei breakpoint in nomi semantici (es. dsk/lap/tab/mob,
2
- vedi scripts/build-margin-padding-css.mjs) per coerenza con la scala `sizes`,
3
- che usa la stessa nomenclatura xs/sm/md/lg/xl e genera ambiguità nelle
4
- utility responsive. Non banale: i tier attuali (xxlarge/xlarge/large/medium/
5
- small, con varianti -only/-down) sono numerosi e in parte sovrapposti (es.
6
- "large" = "small desktop") e non si riducono in modo pulito a poche
7
- categorie semantiche; inoltre il nome è usato in molti file (grid.css,
8
- display.css, visibility.css, text.css, sf-macro.css, json-table, oltre ai
9
- file margin-padding-*-media.css) ed è parte di un template pensato per
10
- essere personalizzato dall'utente: rinominarlo qui non aggiorna le copie
11
- già in uso nei progetti che lo hanno importato. */
12
-
13
- /*
14
- 90rem : 1440px xxlarge (large desktop)
15
- 80rem : 1280px xlarge (desktop)
16
- 64rem : 1024px large (small desktop)
17
- 47.5rem : 760px medium (tablet)
18
- 25rem : 400px small (phone)
19
-
20
- tablet alt:
21
- 53.75rem : 860px medium (tablet)
22
- */
1
+ /* File generato da custom-media-builder.mjs a partire da custom-media.js: NON MODIFICARE DIRETTAMENTE */
23
2
 
24
3
  @custom-media --media-xxlarge-viewport-up (width >= 90rem);
25
4
  @custom-media --media-xlarge-viewport-up (width >= 80rem);
26
5
  @custom-media --media-large-viewport-up (width >= 64rem);
27
6
  @custom-media --media-medium-viewport-up (width >= 47.5rem);
28
7
  @custom-media --media-small-viewport-up (width >= 25rem);
29
-
30
8
  @custom-media --media-xxlarge-viewport-only (width >= 90rem);
31
- @custom-media --media-xlarge-viewport-only (64rem < width <= 80rem);
32
- @custom-media --media-large-viewport-only (64rem < width <= 80rem);
33
- @custom-media --media-medium-viewport-only (47.5rem < width <= 64rem);
34
- @custom-media --media-small-viewport-only (width <= 47.5rem);
35
-
36
- @custom-media --media-xxlarge-viewport-down (max-width: 90rem);
37
- @custom-media --media-xlarge-viewport-down (max-width: 80rem);
38
- @custom-media --media-large-viewport-down (max-width: 64rem);
39
- @custom-media --media-medium-viewport-down (max-width: 47.5rem);
40
- @custom-media --media-small-viewport-down (max-width: 25rem);
9
+ @custom-media --media-xlarge-viewport-only (80rem <= width < 90rem);
10
+ @custom-media --media-large-viewport-only (64rem <= width < 80rem);
11
+ @custom-media --media-medium-viewport-only (47.5rem <= width < 64rem);
12
+ @custom-media --media-small-viewport-only (width < 47.5rem);
13
+ @custom-media --media-xxlarge-viewport-down (width < 90rem);
14
+ @custom-media --media-xlarge-viewport-down (width < 80rem);
15
+ @custom-media --media-large-viewport-down (width < 64rem);
16
+ @custom-media --media-medium-viewport-down (width < 47.5rem);
17
+ @custom-media --media-small-viewport-down (width < 25rem);
@@ -0,0 +1,72 @@
1
+ /*
2
+ Definizioni delle custom media del progetto: unica fonte dei breakpoint,
3
+ usata sia per generare custom-media.css (vedi custom-media-builder.mjs,
4
+ `npm run "build custom media"`) sia direttamente in JS.
5
+
6
+ NB: dopo ogni modifica rigenerare custom-media.css (la generazione è
7
+ comunque eseguita all'avvio delle build webpack DEV e PROD).
8
+
9
+ I valori sono duplicati nei `media` scritti a mano dei template Twig
10
+ (home.html.twig e home_incl/hero.incl.html.twig): vanno aggiornati a mano.
11
+
12
+ 90rem : 1440px xxlarge (large desktop)
13
+ 80rem : 1280px xlarge (desktop)
14
+ 64rem : 1024px large (small desktop)
15
+ 47.5rem : 760px medium (tablet)
16
+ 25rem : 400px small (phone)
17
+
18
+ tablet alt:
19
+ 53.75rem : 860px medium (tablet)
20
+ */
21
+
22
+ /* TODO valutare rinomina dei breakpoint in nomi semantici (es. dsk/lap/tab/mob,
23
+ vedi scripts/build-margin-padding-css.mjs) per coerenza con la scala `sizes`,
24
+ che usa la stessa nomenclatura xs/sm/md/lg/xl e genera ambiguità nelle
25
+ utility responsive. Non banale: i tier attuali (xxlarge/xlarge/large/medium/
26
+ small, con varianti -only/-down) sono numerosi e in parte sovrapposti (es.
27
+ "large" = "small desktop") e non si riducono in modo pulito a poche
28
+ categorie semantiche; inoltre il nome è usato in molti file (grid.css,
29
+ display.css, visibility.css, text.css, sf-macro.css, json-table, oltre ai
30
+ file margin-padding-*-media.css) ed è parte di un template pensato per
31
+ essere personalizzato dall'utente: rinominarlo qui non aggiorna le copie
32
+ già in uso nei progetti che lo hanno importato. */
33
+
34
+ export const breakpoints = {
35
+ xxlarge: '90rem',
36
+ xlarge: '80rem',
37
+ large: '64rem',
38
+ medium: '47.5rem',
39
+ small: '25rem',
40
+ };
41
+
42
+ const bp = breakpoints;
43
+
44
+ /**
45
+ * Custom media del progetto: chiave = nome della custom media (senza `--`),
46
+ * valore = media query.
47
+ *
48
+ * @example
49
+ * import customMedia from './custom-media.js';
50
+ * const mql = matchMedia(customMedia['media-medium-viewport-up']); // '(width >= 47.5rem)'
51
+ */
52
+ const customMedia = {
53
+ 'media-xxlarge-viewport-up': `(width >= ${bp.xxlarge})`,
54
+ 'media-xlarge-viewport-up': `(width >= ${bp.xlarge})`,
55
+ 'media-large-viewport-up': `(width >= ${bp.large})`,
56
+ 'media-medium-viewport-up': `(width >= ${bp.medium})`,
57
+ 'media-small-viewport-up': `(width >= ${bp.small})`,
58
+
59
+ 'media-xxlarge-viewport-only': `(width >= ${bp.xxlarge})`,
60
+ 'media-xlarge-viewport-only': `(${bp.xlarge} <= width < ${bp.xxlarge})`,
61
+ 'media-large-viewport-only': `(${bp.large} <= width < ${bp.xlarge})`,
62
+ 'media-medium-viewport-only': `(${bp.medium} <= width < ${bp.large})`,
63
+ 'media-small-viewport-only': `(width < ${bp.medium})`,
64
+
65
+ 'media-xxlarge-viewport-down': `(width < ${bp.xxlarge})`,
66
+ 'media-xlarge-viewport-down': `(width < ${bp.xlarge})`,
67
+ 'media-large-viewport-down': `(width < ${bp.large})`,
68
+ 'media-medium-viewport-down': `(width < ${bp.medium})`,
69
+ 'media-small-viewport-down': `(width < ${bp.small})`,
70
+ };
71
+
72
+ export default customMedia;