scb-wc 0.1.71 → 0.1.73

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/README.md CHANGED
@@ -85,17 +85,19 @@ Vill du selfhosta kan du istället importera:
85
85
  import 'scb-wc/scb-wc-selfhost.css';
86
86
  ```
87
87
 
88
- Då används paketets egna fontfiler under `node_modules/scb-wc/fonts/`.
88
+ Då används paketets egna fontfiler under `node_modules/scb-wc/fonts/`. Material Symbols är inte hela Google-fonten här. Selfhost-filen innehåller alla ikoner som visas under `Foundations/Icons (ikoner)` i Storybook. Listan kommer från paketets `icons.json`. Fonten behåller stöd för både fyllda och ofyllda varianter.
89
89
 
90
90
  ### Optimera Material Symbols med eget ikon-subset
91
91
 
92
- Vill du selfhosta bara de Material Symbols-ikoner din app använder kan du generera en liten ikonfont i din app:
92
+ Det här är bara för appar som behöver Material Symbols utöver paketets `icons.json`. Då använder du `scb-wc-core.css` + ditt genererade `scb-wc-icons.css` i stället för `scb-wc-selfhost.css`.
93
+
94
+ Skapa en ikonlista i appens rot. Om du vill ersätta paketets selfhost-lista, kopiera paketets `icons.json` och lägg till dina egna ikon-namn:
93
95
 
94
96
  ```sh
95
97
  npx scb-wc subset-icons --icons ./src/scb-icons.json --out ./public/scb-icons
96
98
  ```
97
99
 
98
- Om `--icons` utelämnas används paketets standardlista `icons.json`. Kommandot skapar `scb-wc-icons.css`, en lokal fontfil och en kopia av ikonlistan i målmappen. Ladda då den fontlösa bas-CSS:en plus den genererade ikon-CSS:en:
100
+ Om `--icons` utelämnas används paketets standardlista `icons.json`. Om du skickar in en egen fil lägger kommandot till några basikoner, men inte hela paketets ikonlista. Kommandot skapar `scb-wc-icons.css`, en lokal fontfil och en kopia av ikonlistan i målmappen. Ladda då den fontlösa bas-CSS:en plus den genererade ikon-CSS:en:
99
101
 
100
102
  ```js
101
103
  import 'scb-wc/scb-wc-core.css';
@@ -103,6 +105,8 @@ import '/scb-icons/scb-wc-icons.css';
103
105
  import 'scb-wc/scb-typography.css';
104
106
  ```
105
107
 
108
+ För MVC/MPA räcker det normalt att använda `scb-wc-selfhost.css`, eftersom den redan pekar på paketets selfhostade fontfiler.
109
+
106
110
  ---
107
111
 
108
112
  ## Alternativ 2: Använd i MVC/MPA via `<script type="module">`
@@ -131,22 +135,23 @@ Kör sedan:
131
135
  npm run ui:install
132
136
  ```
133
137
 
134
- Det kopierar hela `node_modules/scb-wc/mvc/` till `wwwroot/ui/` i din applikation (komponenter, vendor och CSS).
138
+ Det kopierar hela `node_modules/scb-wc/mvc/` till `wwwroot/ui/` i din applikation (komponenter, vendor, CSS och fonts).
135
139
 
136
- ### 2.2) Ladda filer i din layout (Razor, .cshtml, klassisk MVC)
140
+ ### 2.2) Ladda filer i layouten (Razor, .cshtml, klassisk MVC)
137
141
 
138
- Du kan byta till `~/ui/scb-wc-selfhost.css` om du vill selfhosta fonterna (mappen `ui/fonts/` kopieras av `ui:install`).
142
+ Exemplet använder selfhost-läget. Lägg CSS i `<head>` och ladda bara de komponentskript som sidan använder.
139
143
 
140
144
  ```html
141
- <!-- Lägg helst i <head> -->
142
- <link rel="stylesheet" href="~/ui/scb-wc.css" />
145
+ <!-- Global layout, helst i <head> -->
146
+ <link rel="stylesheet" href="~/ui/scb-wc-selfhost.css" />
143
147
  <link rel="stylesheet" href="~/ui/scb-typography.css" />
144
148
 
145
- <!-- Ladda ENDAST de komponenter du använder på sidan, gärna precis före </body> -->
146
- <script type="module" src="~/ui/components/scb-link/scb-link.js"></script>
149
+ <!-- Ladda bara de komponenter sidan använder -->
147
150
  <script type="module" src="~/ui/components/scb-button/scb-button.js"></script>
148
151
  ```
149
152
 
153
+ `~/ui/scb-wc-selfhost.css` laddar Inter och paketets Material Symbols-subset från `~/ui/fonts/`.
154
+
150
155
  ### 2.3) CI/CD‑exempel
151
156
 
152
157
  Kör samma script i din pipeline:
package/bin/scb-wc.mjs CHANGED
@@ -21,7 +21,7 @@ const defaultSubsetOutDir = 'public/scb-icons';
21
21
  const defaultSubsetCssFile = 'scb-wc-icons.css';
22
22
  const defaultSubsetFontBase = 'material-symbols-outlined-subset';
23
23
  const materialSymbolsCssUrl = 'https://fonts.googleapis.com/css2';
24
- const materialSymbolsFamilyQuery = 'Material Symbols Outlined:opsz,wght,FILL,GRAD@24,400,0,0';
24
+ const materialSymbolsFamilyQuery = 'Material Symbols Outlined:opsz,wght,FILL,GRAD@20..48,400,0..1,0';
25
25
  const requiredIconNames = [
26
26
  'arrow_back',
27
27
  'arrow_forward',
@@ -108,7 +108,7 @@ function parseFlags(args) {
108
108
  fail(`Ogiltigt argument: ${arg}`);
109
109
  }
110
110
 
111
- if (key === 'dry-run' || key === 'help') {
111
+ if (key === 'dry-run' || key === 'help' || key === 'no-required-icons' || key === 'allow-empty') {
112
112
  flags[key] = true;
113
113
  continue;
114
114
  }
@@ -161,8 +161,9 @@ function readIconList(iconsPath) {
161
161
  return list.map((icon) => String(icon ?? '').trim()).filter(Boolean);
162
162
  }
163
163
 
164
- function normalizeIconNames(iconNames) {
165
- const normalized = Array.from(new Set([...requiredIconNames, ...iconNames]))
164
+ function normalizeIconNames(iconNames, { includeRequired = true } = {}) {
165
+ const baseIconNames = includeRequired ? requiredIconNames : [];
166
+ const normalized = Array.from(new Set([...baseIconNames, ...iconNames]))
166
167
  .map((icon) => icon.trim())
167
168
  .filter(Boolean)
168
169
  .sort((a, b) => a.localeCompare(b));
@@ -191,7 +192,8 @@ function requestUrl(url, redirects = 5) {
191
192
  url,
192
193
  {
193
194
  headers: {
194
- 'User-Agent': `${packageJson.name}/${packageJson.version} subset-icons`,
195
+ Accept: 'text/css,*/*;q=0.1',
196
+ 'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124 Safari/537.36',
195
197
  },
196
198
  },
197
199
  (response) => {
@@ -264,6 +266,19 @@ function findFontSources(cssText) {
264
266
  }));
265
267
  }
266
268
 
269
+ function writeEmptySubsetFiles({ iconNames, outDir, cssFile }) {
270
+ fs.mkdirSync(outDir, { recursive: true });
271
+
272
+ const header = [
273
+ '/* Generated by `npx scb-wc subset-icons`. */',
274
+ '/* Icons: none */',
275
+ '',
276
+ ].join('\n');
277
+
278
+ fs.writeFileSync(path.join(outDir, cssFile), `${header}`, 'utf8');
279
+ fs.writeFileSync(path.join(outDir, 'icons.json'), `${JSON.stringify(iconNames, null, 2)}\n`, 'utf8');
280
+ }
281
+
267
282
  async function writeSubsetFiles({ cssText, iconNames, outDir, cssFile }) {
268
283
  const sources = findFontSources(cssText);
269
284
  if (!sources.length) {
@@ -299,6 +314,10 @@ async function runSubsetIcons(args) {
299
314
  return;
300
315
  }
301
316
 
317
+ if (flags.preset) {
318
+ fail('--preset stöds inte längre. Använd --icons för att ange ikonlista.');
319
+ }
320
+
302
321
  const iconsPath = flags.icons ?? resolveDefaultIconsPath();
303
322
  const outDir = path.resolve(process.cwd(), flags.out ?? defaultSubsetOutDir);
304
323
  const cssFile = flags['css-file'] ?? defaultSubsetCssFile;
@@ -312,8 +331,13 @@ async function runSubsetIcons(args) {
312
331
  fail('--display måste vara auto, block, swap, fallback eller optional.');
313
332
  }
314
333
 
315
- const iconNames = normalizeIconNames(readIconList(iconsPath));
316
- const cssUrl = buildMaterialSymbolsUrl(iconNames, display);
334
+ const iconNames = normalizeIconNames(readIconList(iconsPath), {
335
+ includeRequired: !flags['no-required-icons'],
336
+ });
337
+
338
+ if (!iconNames.length && !flags['allow-empty']) {
339
+ fail('Ikonlistan är tom. Lägg till ikoner eller använd --allow-empty.');
340
+ }
317
341
 
318
342
  if (flags['dry-run']) {
319
343
  console.log(`Skulle skapa Material Symbols-subset med ${iconNames.length} ikoner.`);
@@ -323,6 +347,14 @@ async function runSubsetIcons(args) {
323
347
  return;
324
348
  }
325
349
 
350
+ if (!iconNames.length) {
351
+ writeEmptySubsetFiles({ iconNames, outDir, cssFile });
352
+ console.log(`Skapade tom ikon-CSS i ${outDir}`);
353
+ console.log(`Ladda CSS-filen: ${path.join(outDir, cssFile)}`);
354
+ return;
355
+ }
356
+
357
+ const cssUrl = buildMaterialSymbolsUrl(iconNames, display);
326
358
  const cssText = await fetchText(cssUrl);
327
359
  await writeSubsetFiles({ cssText, iconNames, outDir, cssFile });
328
360
  console.log(`Skapade ikon-subset med ${iconNames.length} ikoner i ${outDir}`);
@@ -739,6 +739,9 @@ namespace ScbBlazor
739
739
  Type = dto.Type ?? string.Empty,
740
740
  Variant = dto.Variant ?? string.Empty,
741
741
  Direction = dto.Direction ?? string.Empty,
742
+ Title = dto.Title ?? string.Empty,
743
+ Subtitle = dto.Subtitle ?? string.Empty,
744
+ SupportingText = dto.SupportingText ?? string.Empty,
742
745
  CardHref = dto.CardHref ?? string.Empty,
743
746
 
744
747
  MediaType = dto.MediaType ?? string.Empty,
@@ -2974,6 +2977,9 @@ namespace ScbBlazor
2974
2977
  public string Type { get; set; } = string.Empty;
2975
2978
  public string Variant { get; set; } = string.Empty;
2976
2979
  public string Direction { get; set; } = string.Empty;
2980
+ public string Title { get; set; } = string.Empty;
2981
+ public string Subtitle { get; set; } = string.Empty;
2982
+ public string SupportingText { get; set; } = string.Empty;
2977
2983
  public string CardHref { get; set; } = string.Empty;
2978
2984
 
2979
2985
  public string MediaType { get; set; } = string.Empty;
@@ -3840,6 +3846,9 @@ namespace ScbBlazor
3840
3846
  public string? Type { get; set; }
3841
3847
  public string? Variant { get; set; }
3842
3848
  public string? Direction { get; set; }
3849
+ public string? Title { get; set; }
3850
+ public string? Subtitle { get; set; }
3851
+ public string? SupportingText { get; set; }
3843
3852
  public string? CardHref { get; set; }
3844
3853
 
3845
3854
  public string? MediaType { get; set; }
@@ -308,4 +308,4 @@ import"../../vendor/vendor-material.js";import{_ as y,b as v,g as w,h as d,p as
308
308
  transition: none;
309
309
  }
310
310
  }
311
- `,g);a([d({type:String})],r.prototype,"label",void 0);a([d({type:String})],r.prototype,"variant",void 0);a([d({type:String,reflect:!0})],r.prototype,"size",void 0);a([d({type:Boolean,reflect:!0})],r.prototype,"open",void 0);a([d({type:Boolean,reflect:!0})],r.prototype,"disabled",void 0);a([d({type:String,reflect:!0})],r.prototype,"spacing",void 0);a([d({type:String,attribute:"spacing-top",reflect:!0})],r.prototype,"spacingTop",void 0);a([d({type:String,attribute:"spacing-bottom",reflect:!0})],r.prototype,"spacingBottom",void 0);a([d({type:String,attribute:"spacing-left",reflect:!0})],r.prototype,"spacingLeft",void 0);a([d({type:String,attribute:"spacing-right",reflect:!0})],r.prototype,"spacingRight",void 0);a([d({type:String,attribute:"menu-gap"})],r.prototype,"menuGap",void 0);a([d({type:String})],r.prototype,"width",void 0);a([d({type:String,attribute:"min-width"})],r.prototype,"minWidth",void 0);a([d({type:String,attribute:"max-width"})],r.prototype,"maxWidth",void 0);a([d({type:String,attribute:"data-index"})],r.prototype,"dataIndex",void 0);a([d({type:String,attribute:"aria-current"})],r.prototype,"ariaCurrent",void 0);a([b("[data-scb-dropdown-trigger]")],r.prototype,"_triggerEl",void 0);a([b("slot")],r.prototype,"_slotEl",void 0);a([b(".panel-surface")],r.prototype,"_panelSurfaceEl",void 0);a([b(".panel-inner")],r.prototype,"_panelInnerEl",void 0);r=a([w("scb-dropdown")],r);
311
+ `,g);a([d({type:String})],r.prototype,"label",void 0);a([d({type:String})],r.prototype,"variant",void 0);a([d({type:String,reflect:!0})],r.prototype,"size",void 0);a([d({type:Boolean,reflect:!0})],r.prototype,"open",void 0);a([d({type:Boolean,reflect:!0})],r.prototype,"disabled",void 0);a([d({type:String,reflect:!0})],r.prototype,"spacing",void 0);a([d({type:String,attribute:"spacing-top",reflect:!0})],r.prototype,"spacingTop",void 0);a([d({type:String,attribute:"spacing-bottom",reflect:!0})],r.prototype,"spacingBottom",void 0);a([d({type:String,attribute:"spacing-left",reflect:!0})],r.prototype,"spacingLeft",void 0);a([d({type:String,attribute:"spacing-right",reflect:!0})],r.prototype,"spacingRight",void 0);a([d({type:String,attribute:"menu-gap"})],r.prototype,"menuGap",void 0);a([d({type:String})],r.prototype,"width",void 0);a([d({type:String,attribute:"min-width"})],r.prototype,"minWidth",void 0);a([d({type:String,attribute:"max-width"})],r.prototype,"maxWidth",void 0);a([d({type:String,attribute:"data-index"})],r.prototype,"dataIndex",void 0);a([d({type:String,attribute:"aria-current"})],r.prototype,"ariaCurrent",void 0);a([b("[data-scb-dropdown-trigger]")],r.prototype,"_triggerEl",void 0);a([b("slot")],r.prototype,"_slotEl",void 0);a([b(".panel-surface")],r.prototype,"_panelSurfaceEl",void 0);a([b(".panel-inner")],r.prototype,"_panelInnerEl",void 0);r=a([w("scb-dropdown")],r);export{r as ScbDropdown};