tosijs-ui 1.16.16 → 1.16.18
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 +42 -0
- package/dist/icons.js +59 -21
- package/dist/iife.js +78 -78
- package/dist/iife.js.map +7 -7
- package/dist/live-example/code-transform.d.ts +5 -5
- package/dist/live-example/code-transform.js +12 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/llms.txt +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.16.18
|
|
4
|
+
|
|
5
|
+
- **A `defineIcons` name for a stacked composition draws the stack.** `defineIcons({
|
|
6
|
+
cloudSync: 'spin120Loader40s_30x$cloud' })` made `icons.cloudSync()` draw the placeholder
|
|
7
|
+
square and log "icon cloudSync does not exist", although the same string used directly as
|
|
8
|
+
an icon name worked. The icons page documents exactly this pattern for building an app's
|
|
9
|
+
icon vocabulary, so every such name was silently a square, in every version since
|
|
10
|
+
composites shipped. A redirect's target now goes through the whole icon pipeline, stacking
|
|
11
|
+
included. closes #224, reported by tosijs-virta.
|
|
12
|
+
- **A named composite answers to its name.** Its `data-icon` is the name you defined
|
|
13
|
+
(`cloudSync`), not the composition it stands for, and suffixes and rules apply to it as
|
|
14
|
+
to any icon (`cloudSync50o`, `spin90CloudSync`).
|
|
15
|
+
- **A redirect cycle says so.** `a: 'b'` with `b: 'a'` now logs "icon a redirects in a
|
|
16
|
+
cycle" and draws the placeholder, instead of claiming the icon does not exist; a
|
|
17
|
+
composite that names itself (`a: 'a$check'`) draws the placeholder in place of the
|
|
18
|
+
cycling layer. A long redirect chain that ends in a drawing is no longer cut off at ten
|
|
19
|
+
hops.
|
|
20
|
+
- The named-composition example on the icons page is now a live example with a test, so
|
|
21
|
+
the documented pattern is checked on every build.
|
|
22
|
+
|
|
23
|
+
## 1.16.17
|
|
24
|
+
|
|
25
|
+
- **The pinned tjs-lang is 0.14.0-rc.5; it was 0.13.13.** That is the devDependency this
|
|
26
|
+
package builds and tests with, and `TJS_VERSION`, which sites without their own copy load
|
|
27
|
+
from a CDN. What it turns on for `tjs` and `ts` examples on those sites, all of it
|
|
28
|
+
feature-detected in 1.16.16: examples written as modules run (`export` is removed), a
|
|
29
|
+
console line shows its own value and offers the JavaScript it became, and a built-in
|
|
30
|
+
`tjs` example that declares a function gains a **Docs** tab beside its code, generated
|
|
31
|
+
from its signatures.
|
|
32
|
+
- **What can break, and how to stay where you were.** tjs-lang 0.14 refuses some code that
|
|
33
|
+
0.13 accepted, with no compatibility switch: `||` in a type (a union is spelled `|`),
|
|
34
|
+
`unsafe var` and `unsafe eval`, and a `wasm` block that cannot compile, among others. Its
|
|
35
|
+
[changelog](https://github.com/tonioloewald/tjs-lang/blob/main/CHANGELOG.md) lists them
|
|
36
|
+
under "what breaks". A `tjs` example using one of those stops compiling on a site that
|
|
37
|
+
loads tjs-lang from the CDN. To keep the old transpiler, install `tjs-lang@0.13.13` in
|
|
38
|
+
your project: the build copies the installed tjs-lang next to your pages and the page
|
|
39
|
+
prefers that copy to the CDN. A site that already installs its own tjs-lang is
|
|
40
|
+
unaffected.
|
|
41
|
+
- The transpiler bundle a page with `tjs` or `ts` examples downloads is larger: 169 kB to
|
|
42
|
+
195 kB gzip. `dist/iife.js` is unchanged, and pages without such examples load neither.
|
|
43
|
+
- The peer range is unchanged (`^0.13.1 || ^0.14.0-rc.5`).
|
|
44
|
+
|
|
3
45
|
## 1.16.16
|
|
4
46
|
|
|
5
47
|
For tjs-lang's book (GitHub #216 item 3 and #210 item 5), plus one change to `llms.txt`.
|
package/dist/icons.js
CHANGED
|
@@ -485,16 +485,36 @@ Now `removeUser`, `removeFile`, `removeProject` all just work — and
|
|
|
485
485
|
they're consistent. If you redesign the trash icon or change
|
|
486
486
|
`--action-color`, every "remove" icon updates automatically.
|
|
487
487
|
|
|
488
|
-
You can also use `defineIcons` for one-off named compositions
|
|
488
|
+
You can also use `defineIcons` for one-off named compositions. Then just
|
|
489
|
+
use `icons.cloudSync()` or `<tosi-icon icon="cloudSync">`: the composition
|
|
490
|
+
is invisible to consumers of the icon.
|
|
489
491
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
secureShield: 'lock50s75o_10y$shield',
|
|
493
|
-
newFile: 'plus75o60s25x25y$file',
|
|
494
|
-
})
|
|
492
|
+
```js
|
|
493
|
+
import { defineIcons, icons } from 'tosijs-ui'
|
|
495
494
|
|
|
496
|
-
|
|
497
|
-
|
|
495
|
+
defineIcons({
|
|
496
|
+
cloudSync: 'spin120Loader40s_30x$cloud',
|
|
497
|
+
secureShield: 'lock50s75o_10y$shield',
|
|
498
|
+
newFile: 'plus75o60s25x25y$file',
|
|
499
|
+
})
|
|
500
|
+
|
|
501
|
+
preview.style.setProperty('--tosi-icon-size', '48px')
|
|
502
|
+
preview.append(icons.cloudSync(), icons.secureShield(), icons.newFile())
|
|
503
|
+
```
|
|
504
|
+
```test
|
|
505
|
+
test('named compositions draw their composites, not the placeholder', () => {
|
|
506
|
+
// A spin layer is a composite of its own, so count only the outer ones.
|
|
507
|
+
const composites = preview.querySelectorAll(':scope > .tosi-icon-composite')
|
|
508
|
+
expect([...composites].map((icon) => icon.dataset.icon)).toEqual([
|
|
509
|
+
'cloudSync',
|
|
510
|
+
'secureShield',
|
|
511
|
+
'newFile',
|
|
512
|
+
])
|
|
513
|
+
for (const composite of composites) {
|
|
514
|
+
expect(composite.querySelectorAll('svg').length).toBeGreaterThan(1)
|
|
515
|
+
}
|
|
516
|
+
})
|
|
517
|
+
```
|
|
498
518
|
|
|
499
519
|
### Composites and `svg2DataUrl`
|
|
500
520
|
|
|
@@ -767,7 +787,8 @@ function composeIcon(prop, parts) {
|
|
|
767
787
|
}
|
|
768
788
|
return null;
|
|
769
789
|
}
|
|
770
|
-
|
|
790
|
+
// Redirect names being resolved right now, so a redirect cycle ends instead of recursing.
|
|
791
|
+
const expanding = new Set();
|
|
771
792
|
// Style suffixes — value then letter code:
|
|
772
793
|
// 50o (opacity), 75s (scale), 20x (translateX%), _10y (translateY%)
|
|
773
794
|
// 90r (rotate 90°), _45r (rotate -45°), 0f (flipH), 1f (flipV)
|
|
@@ -857,24 +878,41 @@ export function resolveIcon(prop, parts) {
|
|
|
857
878
|
const data = iconData;
|
|
858
879
|
// Direct match or redirect chain
|
|
859
880
|
let name = prop;
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
if (!spec)
|
|
863
|
-
break;
|
|
881
|
+
const seen = new Set();
|
|
882
|
+
for (let spec = data[name]; spec; spec = data[name]) {
|
|
864
883
|
if (spec.startsWith('<'))
|
|
865
884
|
return makeIcon(spec, parts);
|
|
885
|
+
seen.add(name);
|
|
866
886
|
name = spec;
|
|
887
|
+
if (seen.has(name)) {
|
|
888
|
+
console.warn(`icon ${prop} redirects in a cycle`);
|
|
889
|
+
return makeIcon(iconData.square, parts);
|
|
890
|
+
}
|
|
867
891
|
}
|
|
868
892
|
if (name !== prop) {
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
893
|
+
/*
|
|
894
|
+
A redirect's target goes through the WHOLE pipeline, stacking included. Handling rules
|
|
895
|
+
and suffixes here and leaving `$` to the checks below tested `prop`, which has no `$`, so
|
|
896
|
+
every named composite drew the placeholder (#224). `expanding` stops a redirect that
|
|
897
|
+
names itself (`a: 'a$b'`) from recursing forever.
|
|
898
|
+
*/
|
|
899
|
+
if (!expanding.has(prop)) {
|
|
900
|
+
expanding.add(prop);
|
|
901
|
+
try {
|
|
902
|
+
const icon = resolveIcon(name, parts);
|
|
903
|
+
// A named composite answers to its name, not to the composition it stands for.
|
|
904
|
+
if (icon.classList.contains('tosi-icon-composite')) {
|
|
905
|
+
;
|
|
906
|
+
icon.dataset.icon = prop;
|
|
907
|
+
}
|
|
908
|
+
return icon;
|
|
909
|
+
}
|
|
910
|
+
finally {
|
|
911
|
+
expanding.delete(prop);
|
|
912
|
+
}
|
|
877
913
|
}
|
|
914
|
+
console.warn(`icon ${prop} redirects in a cycle`);
|
|
915
|
+
return makeIcon(iconData.square, parts);
|
|
878
916
|
}
|
|
879
917
|
// Stack: foo$bar$baz → baz on bottom, bar on top, foo on top
|
|
880
918
|
if (prop.includes('$')) {
|