tosijs-ui 1.5.9 → 1.5.11

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/dist/icons.d.ts CHANGED
@@ -8,9 +8,11 @@ export interface IconRule {
8
8
  prefix: string | RegExp;
9
9
  apply: (baseName: string, match: RegExpMatchArray | string, parts: ElementPart[]) => Element | string | null;
10
10
  }
11
- /** Returns icon name safe for suffix concatenation (appends _ if name ends in digit) */
12
- export declare const safeIconSuffix: (name: string) => string;
13
11
  export declare const iconRules: IconRule[];
12
+ /** Wrap icon elements in a composite container (for custom function rules) */
13
+ export declare function wrapIcon(prop: string, parts: ElementPart[], ...children: Element[]): HTMLSpanElement;
14
+ /** Resolve an icon name through the full pipeline (redirects, suffixes, rules, stacking) */
15
+ export declare function resolveIcon(prop: string, parts: ElementPart[]): Element;
14
16
  export declare const icons: SVGIconMap;
15
17
  export declare class SvgIcon extends WebComponent {
16
18
  static preferredTagName: string;
package/dist/icons.js CHANGED
@@ -428,7 +428,9 @@ viewBox** for best results on non-square base icons.
428
428
  `iconRules` is a mutable array. Each rule has a `prefix` (string or
429
429
  RegExp) and an `apply` function that returns a **string** (resolved
430
430
  through the full pipeline), an **Element** (used directly), or **null**
431
- (skip to next rule):
431
+ (skip to next rule).
432
+
433
+ String rewrites are the simplest — just return a composition string:
432
434
 
433
435
  // String rewrite: addFoo → plus75o_0000ffS$foo75s50o
434
436
  iconRules.push({
@@ -436,16 +438,51 @@ through the full pipeline), an **Element** (used directly), or **null**
436
438
  apply: (baseName) => `plus75o_0000ffS$${baseName}75s50o`,
437
439
  })
438
440
 
439
- // Function rule with side effects (like spin)
441
+ Function rules can use `resolveIcon()` and `wrapIcon()` (both exported)
442
+ for more control:
443
+
444
+ // Function rule: glowNNFoo → foo with brightness filter
440
445
  iconRules.push({
441
446
  prefix: /^glow(\d+)/,
442
447
  apply: (baseName, match, parts) => {
443
448
  const icon = resolveIcon(baseName, parts)
444
449
  icon.style.filter = `brightness(${match[1]}%)`
445
- return icon
450
+ return wrapIcon(baseName, parts, icon)
446
451
  },
447
452
  })
448
453
 
454
+ - `resolveIcon(name, parts)` — resolve any icon name through the full
455
+ pipeline (redirects, suffixes, rules, stacking)
456
+ - `wrapIcon(name, parts, ...children)` — wrap elements in a composite
457
+ container with proper sizing, `pointer-events: none`, and `data-icon`
458
+
459
+ ### Building an icon vocabulary
460
+
461
+ You don't need to spell out the DSL every time. The real power is in
462
+ defining named patterns that become your application's icon language.
463
+ For example, a `remove` prefix that overlays a trash icon:
464
+
465
+ iconRules.push({
466
+ prefix: 'remove',
467
+ apply: (baseName) =>
468
+ `trash75o_actionColorS$${baseName}50o`,
469
+ })
470
+
471
+ Now `removeUser`, `removeFile`, `removeProject` all just work — and
472
+ they're consistent. If you redesign the trash icon or change
473
+ `--action-color`, every "remove" icon updates automatically.
474
+
475
+ You can also use `defineIcons` for one-off named compositions:
476
+
477
+ defineIcons({
478
+ cloudSync: 'spin120Loader40s_30x$cloud',
479
+ secureShield: 'lock50s75o_10y$shield',
480
+ newFile: 'plus75o60s25x25y$file',
481
+ })
482
+
483
+ Then just use `icons.cloudSync()` or `<tosi-icon icon="cloudSync">` —
484
+ the composition is invisible to consumers of the icon.
485
+
449
486
  ### Composites and `svg2DataUrl`
450
487
 
451
488
  Composed icons (stacked, overlay rules) are wrapped in a `<span>`, not
@@ -536,8 +573,8 @@ export const svg2DataUrl = (icon, fill, stroke, strokeWidth) => {
536
573
  const text = encodeURIComponent(svg.outerHTML);
537
574
  return `url(data:image/svg+xml;charset=UTF-8,${text})`;
538
575
  };
539
- /** Returns icon name safe for suffix concatenation (appends _ if name ends in digit) */
540
- export const safeIconSuffix = (name) => /\d$/.test(name) ? name + '_' : name;
576
+ // Appends _ to names ending in digits to prevent suffix ambiguity
577
+ const safeIconSuffix = (name) => /\d$/.test(name) ? name + '_' : name;
541
578
  export const iconRules = [
542
579
  {
543
580
  prefix: /^spin(_?\d+)/,
@@ -564,19 +601,19 @@ export const iconRules = [
564
601
  },
565
602
  {
566
603
  prefix: 'un',
567
- apply: (baseName) => `slash25o$${safeIconSuffix(baseName)}75s75o`,
604
+ apply: (baseName) => `slash25o$${baseName}75s75o`,
568
605
  },
569
606
  {
570
607
  prefix: 'check',
571
- apply: (baseName) => `check75o_00aa00S$${safeIconSuffix(baseName)}75s50o`,
608
+ apply: (baseName) => `check75o_00aa00S$${baseName}75s50o`,
572
609
  },
573
610
  {
574
611
  prefix: 'cancel',
575
- apply: (baseName) => `x75o_cc0000S$${safeIconSuffix(baseName)}75s50o`,
612
+ apply: (baseName) => `x75o_cc0000S$${baseName}75s50o`,
576
613
  },
577
614
  {
578
615
  prefix: 'search',
579
- apply: (baseName) => `search80s30x30y$${safeIconSuffix(baseName)}50o`,
616
+ apply: (baseName) => `search80s30x30y$${baseName}50o`,
580
617
  },
581
618
  ];
582
619
  function makeIcon(spec, parts) {
@@ -605,7 +642,8 @@ function makeIcon(spec, parts) {
605
642
  svg.style.height = varDefault.tosiIconSize('16px');
606
643
  return svg;
607
644
  }
608
- function wrapIcon(prop, parts, ...children) {
645
+ /** Wrap icon elements in a composite container (for custom function rules) */
646
+ export function wrapIcon(prop, parts, ...children) {
609
647
  const wrapper = elements.span({
610
648
  class: 'tosi-icon-composite',
611
649
  dataIcon: prop,
@@ -660,7 +698,7 @@ function composeIcon(prop, parts) {
660
698
  // Only apply if baseName can actually resolve to an icon
661
699
  if (!canResolve(baseName))
662
700
  continue;
663
- const result = rule.apply(baseName, match, parts);
701
+ const result = rule.apply(safeIconSuffix(baseName), match, parts);
664
702
  if (typeof result === 'string')
665
703
  return resolveIcon(result, parts);
666
704
  if (result)
@@ -756,7 +794,10 @@ function parseStyleSuffixes(name) {
756
794
  }
757
795
  return { baseName, style };
758
796
  }
759
- function resolveIcon(prop, parts) {
797
+ /** Resolve an icon name through the full pipeline (redirects, suffixes, rules, stacking) */
798
+ export function resolveIcon(prop, parts) {
799
+ if (prop.endsWith('_'))
800
+ prop = prop.slice(0, -1);
760
801
  const data = iconData;
761
802
  // Direct match or redirect chain
762
803
  let name = prop;