tosijs-ui 1.16.22 → 1.16.23

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/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.16.23
4
+
5
+ - **`rule:icon` applies an icon composition rule explicitly.** A `:` marks the boundary
6
+ between a rule's prefix and the icon it applies to. `checkSquare` is a registered icon, so
7
+ it draws that icon; `check:square` is the `check` rule over `square`. The explicit form
8
+ always applies the rule, needs no capital after the prefix (`check:Square` is the same), and
9
+ takes suffixes and stacking as usual (`spin90:loader40s`, `un:lock$shield`). A `:` is not
10
+ valid in an identifier, so write `icons['check:square']()` or
11
+ `<tosi-icon icon="check:square">`, and it works in the `caption:icon` option strings of
12
+ `<tosi-select>` and `<tosi-segmented>` (`done=Done:check:square`), whose caption now ends at
13
+ the first colon. Names without a `:` resolve exactly as before. `defineIcons` warns when
14
+ it defines a `rule:icon` name, since the definition then wins over the rule.
15
+ - **The kitchen-sink style testbed is no longer bound into the ePub or print.** It stays on
16
+ the site; it is a component showcase, not reading. Docs-only: no API or rendering moved.
17
+
3
18
  ## 1.16.22
4
19
 
5
20
  Three site options asked for by adopters, and a review pass over the documentation.
@@ -0,0 +1,2 @@
1
+ /** `caption:icon` split at the first colon, both trimmed; the icon is '' when absent. */
2
+ export declare function splitCaptionIcon(text: string): [string, string];
@@ -0,0 +1,12 @@
1
+ /*
2
+ `caption:icon` in the option strings of `<tosi-select>` and `<tosi-segmented>`, split in ONE
3
+ place. The caption ends at the FIRST colon, because an icon name may hold one itself: an
4
+ explicit composition rule (`check:square`) is still an icon name.
5
+ */
6
+ /** `caption:icon` split at the first colon, both trimmed; the icon is '' when absent. */
7
+ export function splitCaptionIcon(text) {
8
+ const colon = text.indexOf(':');
9
+ return colon === -1
10
+ ? [text.trim(), '']
11
+ : [text.slice(0, colon).trim(), text.slice(colon + 1).trim()];
12
+ }
@@ -21,7 +21,13 @@ export declare function canResolve(name: string): boolean;
21
21
  */
22
22
  export declare const spinRule: IconRule;
23
23
  export declare const iconRules: IconRule[];
24
- /** The icon a rule would apply to in `name`, or null if the rule does not match it. */
24
+ /**
25
+ * The icon a rule would apply to in `name`, or null if the rule does not match it.
26
+ *
27
+ * A `:` makes the boundary explicit: `check:box` is the `check` rule applied to `box`, with
28
+ * no camelCase guess, so it never reads as an icon called `checkBox`. Everything before the
29
+ * first `:` must be the whole prefix (`spin90:loader`, `un:lock`).
30
+ */
25
31
  export declare function matchRule(rule: IconRule, name: string): {
26
32
  baseName: string;
27
33
  match: RegExpMatchArray | string;
@@ -55,8 +55,27 @@ export const iconRules = [
55
55
  apply: (baseName) => `search80s30x30y$${baseName}50o`,
56
56
  },
57
57
  ];
58
- /** The icon a rule would apply to in `name`, or null if the rule does not match it. */
58
+ /**
59
+ * The icon a rule would apply to in `name`, or null if the rule does not match it.
60
+ *
61
+ * A `:` makes the boundary explicit: `check:box` is the `check` rule applied to `box`, with
62
+ * no camelCase guess, so it never reads as an icon called `checkBox`. Everything before the
63
+ * first `:` must be the whole prefix (`spin90:loader`, `un:lock`).
64
+ */
59
65
  export function matchRule(rule, name) {
66
+ const colon = name.indexOf(':');
67
+ if (colon !== -1) {
68
+ const head = name.slice(0, colon);
69
+ const tail = name.slice(colon + 1);
70
+ if (!tail)
71
+ return null;
72
+ const baseName = tail[0].toLowerCase() + tail.slice(1);
73
+ if (rule.prefix instanceof RegExp) {
74
+ const m = head.match(new RegExp(rule.prefix.source + '$'));
75
+ return m && m.index === 0 ? { baseName, match: m } : null;
76
+ }
77
+ return head === rule.prefix ? { baseName, match: rule.prefix } : null;
78
+ }
60
79
  if (rule.prefix instanceof RegExp) {
61
80
  const m = name.match(new RegExp(rule.prefix.source + '(.+)$'));
62
81
  if (!m)
package/dist/icon-svg.js CHANGED
@@ -60,6 +60,9 @@ export function iconSvg(name) {
60
60
  return undefined;
61
61
  return resolve(name, key, new Set());
62
62
  }
63
+ // How to call the creator for a name: `icons.lock()`, or `icons['check:box']()` for a name
64
+ // that is not an identifier.
65
+ const creatorCall = (name) => /^[A-Za-z_$][\w$]*$/.test(name) ? `icons.${name}()` : `icons['${name}']()`;
63
66
  function resolve(asked, name, seen) {
64
67
  const key = stripEscape(name);
65
68
  const value = data[key];
@@ -81,7 +84,7 @@ function resolve(asked, name, seen) {
81
84
  const what = key === stripEscape(asked) ? `"${key}"` : `it resolves to "${key}", which`;
82
85
  if (isComposition(key)) {
83
86
  throw new Error(`iconSvg("${asked}"): ${what} is not a single SVG (a stack, a rule, or a style ` +
84
- `suffix other than rotation or flip). Render it with icons.${stripEscape(asked)}() ` +
87
+ `suffix other than rotation or flip). Render it with ${creatorCall(stripEscape(asked))} ` +
85
88
  `where there is a DOM.`);
86
89
  }
87
90
  throw new Error(`iconSvg("${asked}"): it redirects to "${key}", which is not a registered icon`);
package/dist/icons.js CHANGED
@@ -442,6 +442,24 @@ The overlay rules are just string rewrites — for example, `unFoo`
442
442
  becomes `slash25o$foo75s75o`. **Overlay icons should have a square
443
443
  viewBox** for best results on non-square base icons.
444
444
 
445
+ #### Explicit rules: `rule:icon`
446
+
447
+ `checkSquare` is ambiguous: it is a registered icon, and it also reads as
448
+ the `check` rule over `square`. A registered icon wins, so it draws the
449
+ icon. Put a `:` at the boundary to ask for the rule: `check:square`,
450
+ `un:lock`, `spin90:loader`. The explicit form applies the rule (unless
451
+ you `defineIcons` that exact name, which warns), needs no capital letter
452
+ after the prefix, and takes suffixes and stacking
453
+ as usual (`spin90:loader40s`, `un:lock$shield`). A `:` is not valid in a
454
+ JavaScript identifier, so write `icons['check:square']()`, or
455
+ `<tosi-icon icon="check:square">`.
456
+
457
+ ```html
458
+ <tosi-icon icon="checkSquare" size="48"></tosi-icon>
459
+ <tosi-icon icon="check:square" size="48"></tosi-icon>
460
+ <tosi-icon icon="un:lock" size="48"></tosi-icon>
461
+ ```
462
+
445
463
  ### Custom rules
446
464
 
447
465
  `iconRules` is a mutable array. Each rule has a `prefix` (string or
@@ -593,6 +611,7 @@ export const defineIcons = (newIcons) => {
593
611
  if (matched == null || !canResolve(matched.baseName))
594
612
  return false;
595
613
  return (typeof rule.prefix !== 'string' ||
614
+ name.includes(':') ||
596
615
  /[A-Z]/.test(name[rule.prefix.length]));
597
616
  });
598
617
  if (readsAsRule) {