tosijs-ui 1.16.3 → 1.16.5
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 +95 -0
- package/dist/data-table.d.ts +4 -4
- package/dist/data-table.js +23 -4
- package/dist/doc-browser.js +79 -7
- package/dist/doc-system/site/site-config.d.ts +2 -2
- package/dist/float.d.ts +6 -0
- package/dist/float.js +7 -0
- package/dist/iife.js +110 -103
- package/dist/iife.js.map +12 -12
- package/dist/live-example/component.d.ts +114 -26
- package/dist/live-example/component.js +617 -70
- package/dist/live-example/example-console.js +1 -1
- package/dist/live-example/execution.d.ts +28 -0
- package/dist/live-example/execution.js +52 -5
- package/dist/live-example/styles.d.ts +42 -21
- package/dist/live-example/styles.js +54 -29
- package/dist/live-example/types.d.ts +0 -1
- package/dist/pop-float.d.ts +5 -0
- package/dist/pop-float.js +50 -4
- 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,100 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.16.5
|
|
4
|
+
|
|
5
|
+
A patch, mostly found by using the doc site on an iPhone: menus that stay on screen as Safari's
|
|
6
|
+
toolbars come and go, a code panel that fits the visible screen, and a REPL that completes as
|
|
7
|
+
you type (touchably, case-insensitively, with `$` and `$$`). Also quiet under tosijs 1.10.7's
|
|
8
|
+
long-list advice, and `pinnedTopRows` now works from the element creator. `dist/iife.js` grows
|
|
9
|
+
by 3.6 kB gzip (478.7 → 482.2 kB), including the move to tosijs 1.10.7, which it bundles.
|
|
10
|
+
|
|
11
|
+
**One read-side change to check for:** `<tosi-table>`'s `pinnedTopRows` and `pinnedBottomRows`
|
|
12
|
+
now read as `null` rather than `undefined` when unset (typed `any[] | null`). That is what makes
|
|
13
|
+
them work when passed to the element creator. Code that tested `table.pinnedTopRows ===
|
|
14
|
+
undefined` should test `== null` instead; truthiness checks are unaffected.
|
|
15
|
+
|
|
16
|
+
### `$` and `$$` in the REPL
|
|
17
|
+
|
|
18
|
+
As in a browser console: `$('.thing')` returns the first match and `$$('.thing')` an array of all
|
|
19
|
+
of them, within the example's own preview. An example's own `$`, or a page's jQuery, takes
|
|
20
|
+
precedence.
|
|
21
|
+
|
|
22
|
+
### The Console tab's REPL completes as you type
|
|
23
|
+
|
|
24
|
+
Typing a name, or a dot after a value, opens a list of suggestions above the prompt: the
|
|
25
|
+
value's properties (prototype chain included) or the names in scope (the example's own,
|
|
26
|
+
`preview`, `console`, the page's modules, globals). Tap one, or use ↓/↑ and Enter; Tab takes the
|
|
27
|
+
highlighted or first suggestion, and Escape closes the list. Rows are touch-sized, so it works
|
|
28
|
+
on a phone, where there is no Tab key and no browser console at all. Matching ignores case, and
|
|
29
|
+
the field turns off iOS's auto-capitalisation and autocorrect; the example's own names rank
|
|
30
|
+
above globals.
|
|
31
|
+
|
|
32
|
+
### Quiet under tosijs 1.10.7's long-list advice; `pinnedTopRows` works from the creator
|
|
33
|
+
|
|
34
|
+
tosijs 1.10.7 warns once about any list binding of more than 10 items that has neither
|
|
35
|
+
`virtual` nor a `nonVirtualReason`. tosijs-ui builds some lists its users can't reach, so it now
|
|
36
|
+
gives the reason itself:
|
|
37
|
+
|
|
38
|
+
- `<tosi-table>`'s pinned rows, which are always on screen;
|
|
39
|
+
- its body under `rowHeight: 0`, which is the author choosing to render every row (the table's
|
|
40
|
+
own warning still fires past 1,000 rows);
|
|
41
|
+
- the doc browser's flat nav in `routing: 'query'`.
|
|
42
|
+
|
|
43
|
+
While testing this, `tosiTable({ pinnedTopRows: [...] })` (and `pinnedBottomRows`) turned out to
|
|
44
|
+
be silently ignored when passed to the element creator: the getter returned `undefined` when
|
|
45
|
+
unset, so tosijs set an attribute instead. It now returns `null` when unset, and the creator
|
|
46
|
+
works (see the note at the top of these notes). The dev dependency moves to tosijs 1.10.7; the peer range is unchanged (`^1.10.3`).
|
|
47
|
+
|
|
48
|
+
### Menus stay inside the screen on iPhone as Safari's toolbars come and go
|
|
49
|
+
|
|
50
|
+
A menu's room was measured once, when it opened. Mobile Safari then shows and hides its toolbars
|
|
51
|
+
(and the keyboard comes and goes) as you touch the page, which changes the visible area without
|
|
52
|
+
a window resize, so a menu measured a moment earlier ran under the toolbar. Open floats (menus,
|
|
53
|
+
tooltips, hint lists) are now re-fitted to their anchor whenever the visible viewport changes.
|
|
54
|
+
Draggable floats are left where they are. Reported by the maintainer on an iPhone (the other
|
|
55
|
+
half of #2460).
|
|
56
|
+
|
|
57
|
+
### The Console tab's REPL is reachable on iPhone
|
|
58
|
+
|
|
59
|
+
A full-screen example (the code panel, or maximized) was sized `100vh`, which on iPhone Safari is
|
|
60
|
+
the height without the browser toolbar, so the bottom of the panel sat under it, and that is
|
|
61
|
+
where the Console tab's REPL input lives. It is now sized to the visible viewport (`100dvh`).
|
|
62
|
+
|
|
63
|
+
## 1.16.4
|
|
64
|
+
|
|
65
|
+
A patch: the example console becomes a tab with a REPL, test-only examples render on deployed
|
|
66
|
+
sites, and the doc nav search gets a clear button in every browser. The console's move from a
|
|
67
|
+
panel under the preview to a tab changes how live examples look; it ships as a patch because
|
|
68
|
+
live examples are a developer-facing tool. It does remove the panel's styling hooks: the
|
|
69
|
+
`[part="console"]` element, the `-has-console` class, and `console` from the `ExampleParts`
|
|
70
|
+
type. Nothing in tosijs-ui used them, and a site that styled the 1.16.2 panel should restyle
|
|
71
|
+
`.example-console` in the tab instead. `dist/iife.js` grows by 1.7 kB gzip (477.0 → 478.7 kB).
|
|
72
|
+
|
|
73
|
+
### The example console is a tab, and a REPL
|
|
74
|
+
|
|
75
|
+
What an example logs now appears in a **Console** tab beside its code, instead of a panel under
|
|
76
|
+
its preview, so the preview is never squeezed. The tab is also a REPL: type an expression and
|
|
77
|
+
press Enter to evaluate it inside the example's own scope (its top-level variables and
|
|
78
|
+
functions, `preview`, its `console`, the page's modules), as in the browser's console: input
|
|
79
|
+
gives its value, `await` works, Shift+Enter adds a line, and ↑/↓ recall what you've entered.
|
|
80
|
+
The REPL costs nothing until it's used: the first input re-runs the example once to give it
|
|
81
|
+
the example's scope. The error that stopped an
|
|
82
|
+
example appears there too. `exampleConsole: false` and `{"console": false}` still turn it off.
|
|
83
|
+
|
|
84
|
+
### A test-only example shows its results on deployed sites too
|
|
85
|
+
|
|
86
|
+
A ` ```test ` fence with nothing beside it shows its results as its body, but it ran its tests
|
|
87
|
+
only when the page's test toggle was on. That toggle is off by default anywhere but localhost,
|
|
88
|
+
so on every deployed site the example was an empty box. It now always runs its tests, because
|
|
89
|
+
they are its content; ordinary examples still follow the toggle.
|
|
90
|
+
|
|
91
|
+
### The doc navigation search has a clear button in every browser
|
|
92
|
+
|
|
93
|
+
The doc system's nav search relied on `type="search"` for its clear (✕) button, which browsers
|
|
94
|
+
draw inconsistently: Chromium only while the field is focused, Safari while it has text, and
|
|
95
|
+
Firefox never. It now has its own ✕, shown whenever there's text, with the native one hidden so
|
|
96
|
+
there's never two. Escape clears it as well.
|
|
97
|
+
|
|
3
98
|
## 1.16.3
|
|
4
99
|
|
|
5
100
|
A patch: iPhone menus that stay reachable, a Docs tab for live examples, and a way to declare
|
package/dist/data-table.d.ts
CHANGED
|
@@ -243,10 +243,10 @@ export declare class TosiTable extends TosiTable_base {
|
|
|
243
243
|
private _nonRepeatingGroupedRowCells;
|
|
244
244
|
private _pinnedTopRows?;
|
|
245
245
|
private _pinnedBottomRows?;
|
|
246
|
-
get pinnedTopRows(): any[] |
|
|
247
|
-
set pinnedTopRows(rows: any[] | undefined);
|
|
248
|
-
get pinnedBottomRows(): any[] |
|
|
249
|
-
set pinnedBottomRows(rows: any[] | undefined);
|
|
246
|
+
get pinnedTopRows(): any[] | null;
|
|
247
|
+
set pinnedTopRows(rows: any[] | null | undefined);
|
|
248
|
+
get pinnedBottomRows(): any[] | null;
|
|
249
|
+
set pinnedBottomRows(rows: any[] | null | undefined);
|
|
250
250
|
get effectivePinnedTopData(): any[];
|
|
251
251
|
get effectivePinnedBottomData(): any[];
|
|
252
252
|
private get effectiveBaseData();
|
package/dist/data-table.js
CHANGED
|
@@ -1578,15 +1578,20 @@ export class TosiTable extends withAttributes({
|
|
|
1578
1578
|
// count-based slicing.
|
|
1579
1579
|
_pinnedTopRows;
|
|
1580
1580
|
_pinnedBottomRows;
|
|
1581
|
+
/*
|
|
1582
|
+
`null`, not `undefined`, when unset: tosijs's element creator assigns a prop as a PROPERTY only
|
|
1583
|
+
when the instance's current value isn't `undefined`, and otherwise as an attribute — so
|
|
1584
|
+
`tosiTable({ pinnedTopRows: [...] })` was silently ignored (tosijs board #2464).
|
|
1585
|
+
*/
|
|
1581
1586
|
get pinnedTopRows() {
|
|
1582
|
-
return this._pinnedTopRows;
|
|
1587
|
+
return this._pinnedTopRows ?? null;
|
|
1583
1588
|
}
|
|
1584
1589
|
set pinnedTopRows(rows) {
|
|
1585
1590
|
this._pinnedTopRows = rows ? tosiValue(rows) : undefined;
|
|
1586
1591
|
this.queueRender();
|
|
1587
1592
|
}
|
|
1588
1593
|
get pinnedBottomRows() {
|
|
1589
|
-
return this._pinnedBottomRows;
|
|
1594
|
+
return this._pinnedBottomRows ?? null;
|
|
1590
1595
|
}
|
|
1591
1596
|
set pinnedBottomRows(rows) {
|
|
1592
1597
|
this._pinnedBottomRows = rows ? tosiValue(rows) : undefined;
|
|
@@ -2364,7 +2369,11 @@ export class TosiTable extends withAttributes({
|
|
|
2364
2369
|
the visible data, so they have no parity, and blanking their non-repeating cells
|
|
2365
2370
|
would empty a pinned header/summary row purely because it is not in `firstRows`.
|
|
2366
2371
|
*/
|
|
2367
|
-
(_elements, item) => this.buildRow(item, cols, stickyInfo, rowClass, false),
|
|
2372
|
+
(_elements, item) => this.buildRow(item, cols, stickyInfo, rowClass, false),
|
|
2373
|
+
// tosijs warns about long unvirtualised lists (1.10.7); the author can't reach this one
|
|
2374
|
+
{
|
|
2375
|
+
nonVirtualReason: 'pinned rows are always on screen, so every one is rendered (a handful by design)',
|
|
2376
|
+
});
|
|
2368
2377
|
return div({
|
|
2369
2378
|
class: `tbody tbody-${region}`,
|
|
2370
2379
|
role: 'rowgroup',
|
|
@@ -3338,7 +3347,17 @@ export class TosiTable extends withAttributes({
|
|
|
3338
3347
|
// The visible-rows listBinding is bound directly to .scroll-area so
|
|
3339
3348
|
// virtualisation observes the same scroll container that sticky cells
|
|
3340
3349
|
// stick against.
|
|
3341
|
-
const visibleBinding = this.rowData.visible.listBinding((_elements, item) => this.buildRow(item, cols, stickyInfo), this.rowHeight > 0
|
|
3350
|
+
const visibleBinding = this.rowData.visible.listBinding((_elements, item) => this.buildRow(item, cols, stickyInfo), this.rowHeight > 0
|
|
3351
|
+
? { virtual: { height: this.rowHeight } }
|
|
3352
|
+
: /*
|
|
3353
|
+
`rowHeight: 0` IS the author saying "render every row" (documented for small tables
|
|
3354
|
+
and variable row heights), so say so to tosijs rather than have it warn about a choice
|
|
3355
|
+
already made. A table big enough for that to hurt still gets <tosi-table>'s own
|
|
3356
|
+
warning past NON_VIRTUAL_ROW_ADVICE rows (#84).
|
|
3357
|
+
*/
|
|
3358
|
+
{
|
|
3359
|
+
nonVirtualReason: 'rowHeight: 0 — the author chose to render every row (<tosi-table> warns past 1,000)',
|
|
3360
|
+
});
|
|
3342
3361
|
this._scrollArea = div({ class: 'scroll-area', part: 'visibleRows' }, ...[
|
|
3343
3362
|
this._head,
|
|
3344
3363
|
this._tbodyTop,
|
package/dist/doc-browser.js
CHANGED
|
@@ -344,6 +344,44 @@ function logoMark(logo, projectLinks) {
|
|
|
344
344
|
mark.classList.add('logo-mark');
|
|
345
345
|
return mark;
|
|
346
346
|
}
|
|
347
|
+
// The nav search box: the field, and its own clear button over the field's right end.
|
|
348
|
+
const navSearchStyleSpec = {
|
|
349
|
+
'.nav-search': {
|
|
350
|
+
position: 'relative',
|
|
351
|
+
margin: '5px',
|
|
352
|
+
},
|
|
353
|
+
'.nav-search input[type="search"]': {
|
|
354
|
+
width: '100%',
|
|
355
|
+
boxSizing: 'border-box',
|
|
356
|
+
// room for the clear button, so text never runs under it
|
|
357
|
+
paddingRight: varDefault.touchSize('44px'),
|
|
358
|
+
},
|
|
359
|
+
'.nav-search input[type="search"]::-webkit-search-cancel-button': {
|
|
360
|
+
display: 'none',
|
|
361
|
+
},
|
|
362
|
+
'.nav-search .nav-search-clear': {
|
|
363
|
+
position: 'absolute',
|
|
364
|
+
right: 0,
|
|
365
|
+
top: 0,
|
|
366
|
+
bottom: 0,
|
|
367
|
+
display: 'inline-flex',
|
|
368
|
+
alignItems: 'center',
|
|
369
|
+
justifyContent: 'center',
|
|
370
|
+
width: varDefault.touchSize('44px'),
|
|
371
|
+
padding: 0,
|
|
372
|
+
border: 'none',
|
|
373
|
+
boxShadow: 'none',
|
|
374
|
+
background: 'transparent',
|
|
375
|
+
color: 'inherit',
|
|
376
|
+
opacity: '0.5',
|
|
377
|
+
},
|
|
378
|
+
'.nav-search .nav-search-clear:hover, .nav-search .nav-search-clear:focus-visible': {
|
|
379
|
+
opacity: '1',
|
|
380
|
+
},
|
|
381
|
+
'.nav-search .nav-search-clear[hidden]': {
|
|
382
|
+
display: 'none',
|
|
383
|
+
},
|
|
384
|
+
};
|
|
347
385
|
const logoMarkStyleSpec = {
|
|
348
386
|
'.logo-mark': {
|
|
349
387
|
height: 'var(--tosi-logo-mark-size, 32px)',
|
|
@@ -565,8 +603,32 @@ export function createDocBrowser(options) {
|
|
|
565
603
|
// section; while typing, matching sections expand via the needle branch.
|
|
566
604
|
refreshNav(true);
|
|
567
605
|
});
|
|
606
|
+
/*
|
|
607
|
+
The nav search's clear (✕) button. `type="search"` alone gave a clear affordance only in
|
|
608
|
+
some browsers and some states: Chromium shows its ✕ only while the field is focused, Safari
|
|
609
|
+
while it has text, Firefox never. So the field has its own, shown whenever there is text,
|
|
610
|
+
and the native one is hidden so there is never two. Escape clears too.
|
|
611
|
+
*/
|
|
612
|
+
const updateSearchClear = () => {
|
|
613
|
+
searchClear.hidden = searchField.value === '';
|
|
614
|
+
};
|
|
615
|
+
const clearSearch = () => {
|
|
616
|
+
searchField.value = '';
|
|
617
|
+
updateSearchClear();
|
|
618
|
+
filterDocs();
|
|
619
|
+
searchField.focus();
|
|
620
|
+
};
|
|
621
|
+
const searchInput = () => {
|
|
622
|
+
updateSearchClear();
|
|
623
|
+
filterDocs();
|
|
624
|
+
};
|
|
625
|
+
const searchKeydown = (event) => {
|
|
626
|
+
if (event.key === 'Escape' && searchField.value !== '') {
|
|
627
|
+
event.preventDefault();
|
|
628
|
+
clearSearch();
|
|
629
|
+
}
|
|
630
|
+
};
|
|
568
631
|
const searchField = input({
|
|
569
|
-
slot: 'nav',
|
|
570
632
|
placeholder: 'search',
|
|
571
633
|
// A placeholder is not a label: it is not a reliable accessible name, and it
|
|
572
634
|
// disappears the moment anything is typed. This is the only text input in the
|
|
@@ -574,12 +636,18 @@ export function createDocBrowser(options) {
|
|
|
574
636
|
// site built with `tosijs-ui/site`.
|
|
575
637
|
'aria-label': 'Search documentation',
|
|
576
638
|
type: 'search',
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
margin: '5px',
|
|
580
|
-
},
|
|
581
|
-
onInput: filterDocs,
|
|
639
|
+
onInput: searchInput,
|
|
640
|
+
onKeydown: searchKeydown,
|
|
582
641
|
});
|
|
642
|
+
const searchClear = button({
|
|
643
|
+
type: 'button',
|
|
644
|
+
class: 'nav-search-clear',
|
|
645
|
+
title: 'Clear search',
|
|
646
|
+
'aria-label': 'Clear search',
|
|
647
|
+
hidden: true,
|
|
648
|
+
onClick: clearSearch,
|
|
649
|
+
}, icons.x());
|
|
650
|
+
const searchBox = div({ slot: 'nav', class: 'nav-search' }, searchField, searchClear);
|
|
583
651
|
// Memory routing is decoupled from the page URL, so it ignores browser
|
|
584
652
|
// back/forward (the host owns history, if any).
|
|
585
653
|
if (!memoryRouting) {
|
|
@@ -1422,6 +1490,9 @@ export function createDocBrowser(options) {
|
|
|
1422
1490
|
idPath: 'filename',
|
|
1423
1491
|
hiddenProp: 'hidden',
|
|
1424
1492
|
value: app.docs,
|
|
1493
|
+
// the flat nav (query routing) lists every doc so the search can filter it and a
|
|
1494
|
+
// reader can scan it; the site's author can't reach this binding to say so
|
|
1495
|
+
nonVirtualReason: 'doc navigation: every doc is listed so search can filter it',
|
|
1425
1496
|
},
|
|
1426
1497
|
}, template(a({
|
|
1427
1498
|
class: 'doc-link',
|
|
@@ -1462,7 +1533,7 @@ export function createDocBrowser(options) {
|
|
|
1462
1533
|
// The sidenav has just introduced itself; give it the layout the doc asked for.
|
|
1463
1534
|
applyFullScreen();
|
|
1464
1535
|
},
|
|
1465
|
-
},
|
|
1536
|
+
}, searchBox, navContent, div({
|
|
1466
1537
|
style: {
|
|
1467
1538
|
position: 'relative',
|
|
1468
1539
|
overflowY: 'scroll',
|
|
@@ -1475,6 +1546,7 @@ export function createDocBrowser(options) {
|
|
|
1475
1546
|
StyleSheet('test-indicators', testIndicatorStyleSpec);
|
|
1476
1547
|
// Header brand-mark sizing (icon / <img> / inline-<svg>), one CSS var each.
|
|
1477
1548
|
StyleSheet('doc-logo-mark', logoMarkStyleSpec);
|
|
1549
|
+
StyleSheet('doc-nav-search', navSearchStyleSpec);
|
|
1478
1550
|
// Floating widget for test status
|
|
1479
1551
|
const testWidget = button({
|
|
1480
1552
|
class: 'test-widget',
|
|
@@ -130,8 +130,8 @@ export interface SiteConfig {
|
|
|
130
130
|
*/
|
|
131
131
|
liveExamples?: 'auto' | 'opt-in';
|
|
132
132
|
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
133
|
+
* Give live examples a Console tab: what the example logs, and a REPL in its scope (default
|
|
134
|
+
* `true`; a tab since 1.16.4, a panel under the preview in 1.16.2–1.16.3). `false` turns it off site-wide;
|
|
135
135
|
* logs still reach the browser's devtools. One example opts out with the fence option
|
|
136
136
|
* `{"console": false}`.
|
|
137
137
|
*/
|
package/dist/float.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ElementCreator } from 'tosijs';
|
|
2
|
+
import type { FloatPosition } from './pop-float.js';
|
|
2
3
|
declare const TosiFloat_base: import("tosijs").WithAttributes<{
|
|
3
4
|
drag: boolean;
|
|
4
5
|
remainOnResize: "hide" | "remove" | "remain";
|
|
@@ -12,6 +13,11 @@ export declare class TosiFloat extends TosiFloat_base {
|
|
|
12
13
|
* (the page, or a scroller containing it) triggers `remainOnScroll`. `null`: any scroll does.
|
|
13
14
|
*/
|
|
14
15
|
anchor: Element | null;
|
|
16
|
+
/**
|
|
17
|
+
* The position it was asked for against its anchor (set by `positionFloat`), so it can be
|
|
18
|
+
* re-fitted when the visible viewport changes. `null`: never positioned against an anchor.
|
|
19
|
+
*/
|
|
20
|
+
anchorPosition: FloatPosition | null;
|
|
15
21
|
content: HTMLSlotElement;
|
|
16
22
|
static shadowStyleSpec: {
|
|
17
23
|
':host': {
|
package/dist/float.js
CHANGED
|
@@ -106,6 +106,13 @@ export class TosiFloat extends withAttributes({
|
|
|
106
106
|
* (the page, or a scroller containing it) triggers `remainOnScroll`. `null`: any scroll does.
|
|
107
107
|
*/
|
|
108
108
|
anchor = null;
|
|
109
|
+
/**
|
|
110
|
+
* The position it was asked for against its anchor (set by `positionFloat`), so it can be
|
|
111
|
+
* re-fitted when the visible viewport changes. `null`: never positioned against an anchor.
|
|
112
|
+
*/
|
|
113
|
+
// typed FloatPosition, not string: as `string` it accepted the CSS position '' / 'fixed'
|
|
114
|
+
// that a shadowed variable stored there (1.16.5 review B1), and the compiler said nothing
|
|
115
|
+
anchorPosition = null;
|
|
109
116
|
content = slot();
|
|
110
117
|
static shadowStyleSpec = {
|
|
111
118
|
':host': {
|