tosijs-ui 1.16.19 → 1.16.21
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 +38 -0
- package/dist/data-table.js +33 -18
- package/dist/doc-system/highlight-styles.js +1 -1
- package/dist/highlight-block.js +1 -1
- package/dist/icon-svg.js +3 -4
- package/dist/icons.js +46 -8
- package/dist/iife.js +98 -98
- package/dist/iife.js.map +11 -11
- package/dist/live-theme.js +1 -1
- package/dist/router.js +53 -25
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/llms.txt +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.16.21
|
|
4
|
+
|
|
5
|
+
- **Expanding or collapsing a table row's detail no longer corrects `scrollTop` itself.**
|
|
6
|
+
tosijs 1.10.9's variable-height list keeps the row in place across the height change, so
|
|
7
|
+
`<tosi-table>` stopped measuring the row and nudging the scroll position up to three
|
|
8
|
+
times. closes board #3326
|
|
9
|
+
- **tosijs peer floor raised to `^1.10.9`**, the release that anchors the list. On an older
|
|
10
|
+
tosijs the toggled row now jumps when its detail opens or closes; upgrade tosijs alongside
|
|
11
|
+
(`dist/iife.js` already bundles 1.10.9).
|
|
12
|
+
- **The icons page points to [lucide](https://lucide.dev)** in its introduction and under
|
|
13
|
+
Icon Sources: a fork and expansion of Feather, and the place to start for more icons in
|
|
14
|
+
the same style.
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## 1.16.20
|
|
18
|
+
|
|
19
|
+
- **A registered icon with style suffixes wins over a composition rule.** `checkCircle90r`
|
|
20
|
+
drew the `check` rule over a rotated `circle`; it is now `checkCircle` turned 90°, in the
|
|
21
|
+
renderer and in `iconSvg`. A rule still applies where the whole name is not a registered
|
|
22
|
+
icon with suffixes (`checkLock90r`). closes board #3295
|
|
23
|
+
- **`defineIcons` warns when a new name it defines is also what a composition rule would
|
|
24
|
+
draw** ("icon checkFoo is also a composition rule's name; your definition wins"). Only a
|
|
25
|
+
name that reads as the rule's warns (`checkFoo`, not `checkbox` or `unlink`), and
|
|
26
|
+
overriding a name that already exists, a built-in such as `unlock` included, never does.
|
|
27
|
+
- **A redirect to a missing icon names what was asked for.** `defineIcons({ myChevron:
|
|
28
|
+
'chevronDwon' })` warned "icon chevronDwon does not exist", naming only the target; it
|
|
29
|
+
now adds "(requested as myChevron)", through stacks too. closes board #3294
|
|
30
|
+
- **Six live examples on the doc site showed nothing; a Playwright spec now fails on any
|
|
31
|
+
that does.**
|
|
32
|
+
- The table's Column Width section rendered an empty `<tosi-table>` (an `html` fence
|
|
33
|
+
meant as syntax). It is now a live before/after with a test.
|
|
34
|
+
- The router page's examples shared the page's one router, so the last to run blanked
|
|
35
|
+
the others. Basic Usage holds it on load and has links; Named Views routes when you
|
|
36
|
+
press its button, and a test checks the first example shows its route.
|
|
37
|
+
- Code meant to be read no longer runs as an empty example: the token-palette `css` on
|
|
38
|
+
highlight-block and highlight-styles, liveTheme's programmatic-control snippet, and the
|
|
39
|
+
migrating guide's setSchemaValidator lines are `:static`.
|
|
40
|
+
|
|
3
41
|
## 1.16.19
|
|
4
42
|
|
|
5
43
|
- **`iconSvg()` resolves the built-in icons that rotate or flip another.** 27 built-in
|
package/dist/data-table.js
CHANGED
|
@@ -948,10 +948,38 @@ by adding the `noreorder` attribute to the `<tosi-table>`.
|
|
|
948
948
|
|
|
949
949
|
Columns are laid out at the widths you give them, so a table whose columns add up to less
|
|
950
950
|
than its container leaves a strip of blank space on the right. Add the `full-width-header`
|
|
951
|
-
attribute and the leftover space goes to the last
|
|
951
|
+
attribute (`fullWidthHeader: true` from the creator) and the leftover space goes to the last
|
|
952
|
+
**unpinned** column instead. The same columns, without and with it:
|
|
952
953
|
|
|
953
|
-
```
|
|
954
|
-
|
|
954
|
+
```js
|
|
955
|
+
import { tosiTable } from 'tosijs-ui'
|
|
956
|
+
|
|
957
|
+
const array = [
|
|
958
|
+
{ id: 1, name: 'Ada', role: 'Analyst' },
|
|
959
|
+
{ id: 2, name: 'Grace', role: 'Admiral' },
|
|
960
|
+
{ id: 3, name: 'Margaret', role: 'Director' },
|
|
961
|
+
]
|
|
962
|
+
const columns = () => [
|
|
963
|
+
{ prop: 'id', name: 'ID', width: 60 },
|
|
964
|
+
{ prop: 'name', name: 'Name', width: 120 },
|
|
965
|
+
{ prop: 'role', name: 'Role', width: 120 },
|
|
966
|
+
]
|
|
967
|
+
const style = { display: 'block', height: '150px' }
|
|
968
|
+
preview.append(
|
|
969
|
+
tosiTable({ array, columns: columns(), style }),
|
|
970
|
+
tosiTable({ array, columns: columns(), style, fullWidthHeader: true })
|
|
971
|
+
)
|
|
972
|
+
```
|
|
973
|
+
```test
|
|
974
|
+
const roleWidth = (table) =>
|
|
975
|
+
[...table.querySelectorAll('.thead .th')].at(-1).getBoundingClientRect().width
|
|
976
|
+
test('only the full-width table stretches its last column', async () => {
|
|
977
|
+
const [plain, full] = preview.querySelectorAll('tosi-table')
|
|
978
|
+
for (let i = 0; i < 100 && !full.querySelector('.thead .th'); i++) await waitMs(20)
|
|
979
|
+
expect(full.hasAttribute('full-width-header')).toBe(true)
|
|
980
|
+
expect(Math.round(roleWidth(plain))).toBe(120)
|
|
981
|
+
expect(roleWidth(full)).toBeGreaterThan(120)
|
|
982
|
+
})
|
|
955
983
|
```
|
|
956
984
|
|
|
957
985
|
Right-pinned columns are skipped because they sit against the right edge by definition —
|
|
@@ -1742,24 +1770,11 @@ export class TosiTable extends withAttributes({
|
|
|
1742
1770
|
this._detailEls.delete(key);
|
|
1743
1771
|
}
|
|
1744
1772
|
const rowEl = this.stampedRow(raw);
|
|
1745
|
-
const top = rowEl?.getBoundingClientRect().top;
|
|
1746
1773
|
if (rowEl)
|
|
1747
1774
|
this.syncDetail(rowEl, raw);
|
|
1775
|
+
// The list anchors itself across a height change (tosijs 1.10.9), so the toggled row
|
|
1776
|
+
// keeps its place without a scrollTop correction here.
|
|
1748
1777
|
this.remeasureRows();
|
|
1749
|
-
/*
|
|
1750
|
-
Keep the toggled row where it was. A variable-height list places its rows by
|
|
1751
|
-
interpolation, so a row that changes height moves every row, itself included, by an
|
|
1752
|
-
amount that depends on how far down the list is scrolled.
|
|
1753
|
-
*/
|
|
1754
|
-
if (top !== undefined && this._scrollArea) {
|
|
1755
|
-
for (let i = 0; i < 3; i += 1) {
|
|
1756
|
-
const now = this.stampedRow(raw)?.getBoundingClientRect().top;
|
|
1757
|
-
if (now === undefined || Math.abs(now - top) < 1)
|
|
1758
|
-
break;
|
|
1759
|
-
this._scrollArea.scrollTop += now - top;
|
|
1760
|
-
this.remeasureRows();
|
|
1761
|
-
}
|
|
1762
|
-
}
|
|
1763
1778
|
this.dispatchEvent(new CustomEvent(want ? 'rowexpand' : 'rowcollapse', {
|
|
1764
1779
|
bubbles: true,
|
|
1765
1780
|
detail: { row: raw, element: element?.firstElementChild ?? null },
|
package/dist/highlight-block.js
CHANGED
package/dist/icon-svg.js
CHANGED
|
@@ -76,10 +76,9 @@ function resolve(asked, name, seen) {
|
|
|
76
76
|
seen.add(key);
|
|
77
77
|
return resolve(asked, value, seen);
|
|
78
78
|
}
|
|
79
|
-
// The renderer's order for a name that is not registered: a stack, then
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
const split = key.includes('$') || ruleDraws(key) ? null : splitSuffixes(key);
|
|
79
|
+
// The renderer's order for a name that is not registered: a stack, then suffixes on a
|
|
80
|
+
// registered icon (they win over a rule, #3295), then a rule.
|
|
81
|
+
const split = key.includes('$') ? null : splitSuffixes(key);
|
|
83
82
|
if (split &&
|
|
84
83
|
data[split.baseName] !== undefined &&
|
|
85
84
|
split.tokens.every(isGeometry)) {
|
package/dist/icons.js
CHANGED
|
@@ -11,6 +11,11 @@
|
|
|
11
11
|
e.g. `icons.chevronDown()` produces an `<svg>` element containing a downward-pointing chevron
|
|
12
12
|
icon with the class `icon-chevron-down`.
|
|
13
13
|
|
|
14
|
+
Most of the built-in icons come from [Feather](https://feathericons.com). If you want more
|
|
15
|
+
icons in the same style, [lucide](https://lucide.dev) is a fork and expansion of Feather and a
|
|
16
|
+
great place to start: its SVGs drop straight into `defineIcons()` (see
|
|
17
|
+
[Need More Icons?](#need-more-icons)).
|
|
18
|
+
|
|
14
19
|
```js
|
|
15
20
|
const { tosi, elements } = tosijs
|
|
16
21
|
import { icons, svgIcon, postNotification } from 'tosijs-ui'
|
|
@@ -202,8 +207,8 @@ probably be broken out as a standalone library to allow the use of whatever icon
|
|
|
202
207
|
|
|
203
208
|
### Need More Icons?
|
|
204
209
|
|
|
205
|
-
[lucide](https://lucide.dev) is a fork of feather that maintains the style and
|
|
206
|
-
options. Obviously it's completely compatible with this icon system and generously licensed. A
|
|
210
|
+
[lucide](https://lucide.dev) is a fork and expansion of feather that maintains the style and
|
|
211
|
+
adds a lot more options. Obviously it's completely compatible with this icon system and generously licensed. A
|
|
207
212
|
good place to find more icons in a pinch.
|
|
208
213
|
|
|
209
214
|
Concretely: lucide emits the same geometry feather does — `24×24` viewBox, `fill="none"`,
|
|
@@ -532,6 +537,7 @@ and render a `square` (in fact, `icons.square()`) as a fallback.
|
|
|
532
537
|
|
|
533
538
|
Many of these icons are sourced from [Feather Icons](https://github.com/feathericons/feather), but
|
|
534
539
|
all the icons have been processed to have integer coordinates in a `viewBox` typically scaled to 1024 × 1024.
|
|
540
|
+
For more in the same style, [lucide](https://lucide.dev) is a fork and expansion of Feather.
|
|
535
541
|
|
|
536
542
|
The corporate logos (Google, etc.) are from a variety of sources, in many cases ultimately from the
|
|
537
543
|
organizations themselves. It's up to you to use them correctly.
|
|
@@ -568,7 +574,30 @@ import { splitSuffixes, suffixNumber } from './icon-suffixes.js';
|
|
|
568
574
|
import { iconRules, spinRule, matchRule, canResolve } from './icon-rules.js';
|
|
569
575
|
export { iconRules } from './icon-rules.js';
|
|
570
576
|
export const defineIcons = (newIcons) => {
|
|
577
|
+
const data = iconData;
|
|
578
|
+
const isNew = Object.keys(newIcons).filter((name) => !data[name]);
|
|
571
579
|
Object.assign(iconData, newIcons);
|
|
580
|
+
/*
|
|
581
|
+
A defined icon always wins over a composition rule that would produce the same name, but
|
|
582
|
+
the author may not know the rule exists. Say so once, here, where the name was chosen, and
|
|
583
|
+
only for a NEW name that reads as the rule's: `checkTestShadow`, not `checkbox` or `unlink`
|
|
584
|
+
(a lowercase run is a word, not a prefix plus an icon, so icon packs stay quiet).
|
|
585
|
+
Overriding a name that already existed, a built-in such as `unlock` or `checkCircle`
|
|
586
|
+
included, is a deliberate choice of that name and never warns, so neither does defining a
|
|
587
|
+
name a second time.
|
|
588
|
+
*/
|
|
589
|
+
for (const name of isNew) {
|
|
590
|
+
const readsAsRule = iconRules.some((rule) => {
|
|
591
|
+
const matched = matchRule(rule, name);
|
|
592
|
+
if (matched == null || !canResolve(matched.baseName))
|
|
593
|
+
return false;
|
|
594
|
+
return (typeof rule.prefix !== 'string' ||
|
|
595
|
+
/[A-Z]/.test(name[rule.prefix.length]));
|
|
596
|
+
});
|
|
597
|
+
if (readsAsRule) {
|
|
598
|
+
console.warn(`icon ${name} is also a composition rule's name; your definition wins`);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
572
601
|
};
|
|
573
602
|
// Raw-markup accessors live in ./icon-svg (DOM-free) and are re-exported here.
|
|
574
603
|
export { iconSvg, iconNames } from './icon-svg.js';
|
|
@@ -872,19 +901,28 @@ export function resolveIcon(prop, parts) {
|
|
|
872
901
|
});
|
|
873
902
|
return wrapIcon(prop, parts, base, ...overlays);
|
|
874
903
|
}
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
904
|
+
/*
|
|
905
|
+
Style suffixes on a registered icon win over a composition rule (#3295): `checkCircle90r`
|
|
906
|
+
is `checkCircle` turned, not the `check` rule over `circle90r`. A rule still applies
|
|
907
|
+
when its suffixes are on an icon that only the rule makes (`spin90Loader50o`).
|
|
908
|
+
*/
|
|
880
909
|
const parsed = parseStyleSuffixes(prop);
|
|
910
|
+
const native = parsed != null && iconData[parsed.baseName];
|
|
911
|
+
if (!native) {
|
|
912
|
+
const composed = composeIcon(prop, parts);
|
|
913
|
+
if (composed)
|
|
914
|
+
return composed;
|
|
915
|
+
}
|
|
881
916
|
if (parsed) {
|
|
882
917
|
const icon = resolveIcon(parsed.baseName, parts);
|
|
883
918
|
Object.assign(icon.style, parsed.style);
|
|
884
919
|
return icon;
|
|
885
920
|
}
|
|
886
921
|
if (prop) {
|
|
887
|
-
|
|
922
|
+
// Inside a redirect, also name what the caller asked for: a typo in a defineIcons
|
|
923
|
+
// target is otherwise reported under a name that appears nowhere in their code.
|
|
924
|
+
const via = expanding.size > 0 ? ` (requested as ${[...expanding].join(' → ')})` : '';
|
|
925
|
+
console.warn(`icon ${prop} does not exist${via}`);
|
|
888
926
|
}
|
|
889
927
|
return makeIcon(iconData.square, parts);
|
|
890
928
|
}
|