tosijs-ui 1.16.31 → 1.16.32
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 +93 -0
- package/bin/resolve-site-config.ts +29 -0
- package/bin/tunnel.ts +10 -0
- package/dist/affix.d.ts +97 -0
- package/dist/affix.js +445 -0
- package/dist/crud.d.ts +22 -0
- package/dist/crud.js +68 -5
- package/dist/data-table.js +10 -0
- package/dist/doc-browser.d.ts +6 -0
- package/dist/doc-browser.js +155 -115
- package/dist/doc-system/doc-search.d.ts +43 -0
- package/dist/doc-system/doc-search.js +194 -0
- package/dist/doc-system/doc-system.js +5 -0
- package/dist/doc-system/site/dev-server.js +10 -1
- package/dist/doc-system/site/device-revocation.d.ts +13 -1
- package/dist/doc-system/site/device-revocation.js +51 -13
- package/dist/editable-rect.d.ts +1 -1
- package/dist/form.d.ts +1 -1
- package/dist/iife.js +118 -112
- package/dist/iife.js.map +17 -14
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/live-example/component.d.ts +39 -15
- package/dist/live-example/component.js +42 -50
- package/dist/live-example/styles.d.ts +37 -14
- package/dist/live-example/styles.js +52 -37
- package/dist/notifications.js +11 -4
- package/dist/palette.d.ts +90 -0
- package/dist/palette.js +898 -0
- package/dist/schema-form.d.ts +2 -1
- package/dist/schema-form.js +23 -8
- package/dist/search-field.js +0 -12
- package/dist/segmented.d.ts +1 -1
- package/dist/tab-selector.d.ts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/llms.txt +5 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,98 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.16.32
|
|
4
|
+
|
|
5
|
+
Two new components, a doc search that ranks, and live examples whose toolbar no longer covers
|
|
6
|
+
what they draw. Nothing an adopter has to change: the toolbar and the search are doc-site
|
|
7
|
+
behaviour, and both components are new. One thing to know if you embed the doc browser in an
|
|
8
|
+
app: it now opens its search on Cmd/Ctrl-K. If your page owns that key, pass
|
|
9
|
+
`createDocBrowser({ searchShortcut: '' })` (or another key).
|
|
10
|
+
|
|
11
|
+
`dist/iife.js` grows by about 7 KB gzip (496.4 KB to 503.4 KB, +1.4%): the palette is 9.1 KB
|
|
12
|
+
gzip and the affix 5.0 KB. The ESM path pays only for what it imports.
|
|
13
|
+
|
|
14
|
+
### New components
|
|
15
|
+
|
|
16
|
+
- **`<tosi-palette>`** (`tosiPalette`): a command palette. A compact search-field trigger
|
|
17
|
+
opens a centred modal of ranked results. Results come from `sources` (sync, or async with a
|
|
18
|
+
spinner and a `timeout`, 10s by default; each keystroke aborts the last search), are drawn
|
|
19
|
+
per `kind` by `renderers` (or a default row: icon, highlighted title, one-line description,
|
|
20
|
+
path), ranked by `score` and grouped by `group` (or by your own `rank`), with `quickLinks`
|
|
21
|
+
before anything is typed. Arrow keys, Enter and Escape drive it, `shortcut: 'mod+k'` opens it
|
|
22
|
+
from anywhere (a shortcut with an unknown modifier is ignored, with a console warning, rather
|
|
23
|
+
than binding the bare key), `multiline` makes the query a growing prompt, and choosing fires `action`.
|
|
24
|
+
`trigger` is `field` (the default, which shrinks to its icon below `compactWidth`, 160px),
|
|
25
|
+
`icon`, or `none` for a palette opened only by `open()` or its shortcut. Its colours come
|
|
26
|
+
from the theme's root `--tosi-text` / `--tosi-bg` / `--tosi-accent`, so a recoloured header
|
|
27
|
+
does not make its results invisible. The dialog sets its own line height, wrapping and font
|
|
28
|
+
size, so a header's do not reach it. The palette footer's Close is a button, for a phone,
|
|
29
|
+
which has no Escape key; on a touch screen the arrow/Enter cues and the Esc hint are hidden.
|
|
30
|
+
The ✕ that clears the query is hidden until something is typed.
|
|
31
|
+
- **`<tosi-affix>`** (`tosiAffix`): fixes a fixture (`slot="fixture"`) to an edge of its
|
|
32
|
+
content, in the FloatPosition vocabulary: the first letter is the edge, the second the
|
|
33
|
+
alignment, so `en` is the right edge, top-aligned. Outside (the default) it takes a grid cell
|
|
34
|
+
beside the content, so it never covers it and an ancestor's overflow cannot clip it; `inside`
|
|
35
|
+
puts it within the content against that edge. `fallback` (e.g. `"s inside"`) is used while
|
|
36
|
+
the fixture is longer than its edge. Setting `position`/`inside` sets where it is wanted,
|
|
37
|
+
reading them gives where it is, the `placed` attribute reflects it, and a `reposition` event
|
|
38
|
+
fires when it changes. It looks finished with no styling: a flex column on a side edge, a row
|
|
39
|
+
on top or bottom, the theme's inset background and spacing, outer corners rounded
|
|
40
|
+
(`--tosi-affix-bg/gap/padding/radius`, `::part(fixture)`).
|
|
41
|
+
|
|
42
|
+
### Doc system
|
|
43
|
+
|
|
44
|
+
- **Search ranks pages, in the header.** The sidebar's nav filter (a substring test that hid
|
|
45
|
+
pages and ranked nothing) is replaced by a palette in the header bar: the site's search
|
|
46
|
+
field while there is room, its icon when the header is narrow, and Cmd/Ctrl-K on every page,
|
|
47
|
+
`{"header": false}` pages included. Pages are ranked by rough relevance (title, then
|
|
48
|
+
headings, keywords, description, opening paragraph, body), and a matching heading becomes a
|
|
49
|
+
deep link. A query word matches only the start of a word, camelCase split ("date" finds
|
|
50
|
+
`tosiDate`, not "update"), a whole word or its plural outranks a prefix, and a word used
|
|
51
|
+
often counts for more than one used once. A word matched in one heading no longer counts for
|
|
52
|
+
the next query word. The trigger looks like the search field it replaced (the site's
|
|
53
|
+
pill-shaped input), and the active row is a tint of the theme's accent. The ranking is
|
|
54
|
+
exported as `buildDocIndex` / `searchDocs` from `tosijs-ui/doc-system/doc-search`, with
|
|
55
|
+
section anchors taken from the renderer's own heading ids. `createDocBrowser({ searchShortcut })` sets the key
|
|
56
|
+
that opens the search, `''` for none.
|
|
57
|
+
- **A live example's toolbar sits beside the preview**, outside its outline, instead of a
|
|
58
|
+
pocket bar over the preview's top-right corner (which covered whatever the example drew
|
|
59
|
+
there, the crud example's New button for one). It moves inside along the bottom when the
|
|
60
|
+
column is taller than the preview, and when the example is maximized. The run-tests check
|
|
61
|
+
shows the test status; the owl handle is gone.
|
|
62
|
+
- Below 600px of header the link icons fold into the settings (⋮) menu, so an upright phone
|
|
63
|
+
has room for the title and the search.
|
|
64
|
+
|
|
65
|
+
### Fixed
|
|
66
|
+
|
|
67
|
+
- `<tosi-crud>` has a Close button (and `close()`) that returns to the list. Under 720px (the
|
|
68
|
+
doc preview included) an open record replaces the list instead of squeezing into a 210px
|
|
69
|
+
column beside it, and the component fills a container with a height. A store that can only
|
|
70
|
+
list no longer shows New, Save and Delete where the page styles `button` with a `display`.
|
|
71
|
+
Without a schema, New starts from the fields the listed rows have instead of an empty form.
|
|
72
|
+
- Boolean columns from a schema asked for icons named "✓" and "✗", which do not exist; they
|
|
73
|
+
use `check` and `x`.
|
|
74
|
+
- `<tosi-table>` with no `columns` and data that arrived later showed no columns: it now
|
|
75
|
+
infers them once there is a row.
|
|
76
|
+
- `<tosi-schema-form>` with no schema kept the schema inferred from an empty value forever, and
|
|
77
|
+
threw "unobserve failed, listener not found" every time it left the page.
|
|
78
|
+
|
|
79
|
+
### Dependencies
|
|
80
|
+
|
|
81
|
+
- The optional `happy-dom` peer is now `^21.0.4` (was `^20.7.0`), and tosijs-ui's own tests
|
|
82
|
+
run on 21.0.4. Every happy-dom from 17.0.0 to 21.0.3 is affected by
|
|
83
|
+
[GHSA-834v-8h66-3h79](https://github.com/advisories/GHSA-834v-8h66-3h79) (an unsanitized
|
|
84
|
+
import alias leads to host code execution), and there is no fixed 20.x. It matters only if
|
|
85
|
+
you use `tosijs-ui/test-setup` or build ePubs; then upgrade to 21.0.4. Its one breaking
|
|
86
|
+
change is that CSS and iframe loading are off by default, which neither relies on.
|
|
87
|
+
|
|
88
|
+
### Tunnel
|
|
89
|
+
|
|
90
|
+
- A workspace no longer makes a request wait on the box for the revoked-device list. A
|
|
91
|
+
copy up to ten minutes old is used at once and refreshed behind, and when the list becomes
|
|
92
|
+
unreadable the dev server says so, and why. `tosijs-tunnel` refuses flag combinations it
|
|
93
|
+
used to ignore silently: `--share-ttl` with `--global` or without `--link --share`, and
|
|
94
|
+
`--label` anywhere but on a `--link --global` edit link.
|
|
95
|
+
|
|
3
96
|
## 1.16.31
|
|
4
97
|
|
|
5
98
|
**Tunnel users: each browser needs one new `tosijs-tunnel --link --global`.** The edit cookie
|
|
@@ -422,6 +422,35 @@ export interface Argv {
|
|
|
422
422
|
rest: string[]
|
|
423
423
|
}
|
|
424
424
|
|
|
425
|
+
/**
|
|
426
|
+
* `tosijs-tunnel` flag combinations that would otherwise be silently ignored, each with what to
|
|
427
|
+
* do instead (1.16.31 review). A flag that changes nothing is a promise the bin does not keep.
|
|
428
|
+
*/
|
|
429
|
+
export function tunnelFlagProblems(args: {
|
|
430
|
+
has: (name: string) => boolean
|
|
431
|
+
flag: (name: string) => string | undefined
|
|
432
|
+
}): string[] {
|
|
433
|
+
const problems: string[] = []
|
|
434
|
+
const link = args.has('link')
|
|
435
|
+
const share = args.has('share')
|
|
436
|
+
const global = args.has('global')
|
|
437
|
+
if (args.flag('share-ttl') !== undefined) {
|
|
438
|
+
if (global)
|
|
439
|
+
problems.push(
|
|
440
|
+
'--share-ttl does not apply to --global links: they always expire after 5 minutes. For a longer-lived view link, use --link --share --share-ttl=… without --global.'
|
|
441
|
+
)
|
|
442
|
+
else if (!(link && share))
|
|
443
|
+
problems.push('--share-ttl only applies to --link --share.')
|
|
444
|
+
}
|
|
445
|
+
if (args.flag('label') !== undefined) {
|
|
446
|
+
if (!(link && global) || share)
|
|
447
|
+
problems.push(
|
|
448
|
+
'--label names the device a --link --global EDIT link is for; it does nothing elsewhere.'
|
|
449
|
+
)
|
|
450
|
+
}
|
|
451
|
+
return problems
|
|
452
|
+
}
|
|
453
|
+
|
|
425
454
|
/**
|
|
426
455
|
* Parse `argv` against `spec`. Prints usage and exits on `--help` (0) or on an
|
|
427
456
|
* unrecognised flag (1); returns a reader otherwise.
|
package/bin/tunnel.ts
CHANGED
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
parseDeviceListing,
|
|
49
49
|
DEVICE_LISTING_SEPARATOR,
|
|
50
50
|
DEVICE_ID_PATTERN,
|
|
51
|
+
tunnelFlagProblems,
|
|
51
52
|
} from './resolve-site-config.ts'
|
|
52
53
|
|
|
53
54
|
const { has, flag } = parseArgv(process.argv.slice(2), {
|
|
@@ -81,6 +82,15 @@ const { has, flag } = parseArgv(process.argv.slice(2), {
|
|
|
81
82
|
` --port= --local-port= --remote-port= override the resolved ports`,
|
|
82
83
|
})
|
|
83
84
|
|
|
85
|
+
{
|
|
86
|
+
const problems = tunnelFlagProblems({ has, flag })
|
|
87
|
+
if (problems.length) {
|
|
88
|
+
for (const problem of problems) console.error(`\n${problem}`)
|
|
89
|
+
console.error('')
|
|
90
|
+
process.exit(1)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
84
94
|
const siteConfig = await resolveSiteConfig()
|
|
85
95
|
|
|
86
96
|
const preview = siteConfig.preview
|
package/dist/affix.d.ts
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Component, ElementCreator, PartsMap } from 'tosijs';
|
|
2
|
+
export type AffixPosition = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw' | 'en' | 'wn' | 'es' | 'ws';
|
|
3
|
+
export interface AffixPlacement {
|
|
4
|
+
position: AffixPosition;
|
|
5
|
+
inside: boolean;
|
|
6
|
+
}
|
|
7
|
+
/** `position` as written, or the default when it is not one. */
|
|
8
|
+
export declare function affixPosition(value: unknown): AffixPosition;
|
|
9
|
+
/** `"s inside"` → `{position: 's', inside: true}`; '' → null (no fallback). */
|
|
10
|
+
export declare function parsePlacement(value: unknown): AffixPlacement | null;
|
|
11
|
+
/** `{position: 's', inside: true}` → `"s inside"`. */
|
|
12
|
+
export declare const describePlacement: ({ position, inside }: AffixPlacement) => string;
|
|
13
|
+
type Track = 1 | 2 | 3;
|
|
14
|
+
type Align = 'start' | 'center' | 'end';
|
|
15
|
+
/**
|
|
16
|
+
* The grid cell and alignment for a placement. Outside, the fixture takes the cell on its
|
|
17
|
+
* edge, hugging the content; inside, it shares the content's cell, against that edge.
|
|
18
|
+
*/
|
|
19
|
+
export declare function affixCell({ position, inside }: AffixPlacement): {
|
|
20
|
+
row: Track;
|
|
21
|
+
column: Track;
|
|
22
|
+
alignSelf: Align;
|
|
23
|
+
justifySelf: Align;
|
|
24
|
+
direction: string;
|
|
25
|
+
edge: "n" | "s" | "e" | "w";
|
|
26
|
+
};
|
|
27
|
+
interface AffixParts extends PartsMap {
|
|
28
|
+
content: HTMLSlotElement;
|
|
29
|
+
fixture: HTMLSlotElement;
|
|
30
|
+
}
|
|
31
|
+
export declare class TosiAffix extends Component<AffixParts> {
|
|
32
|
+
static initAttributes: Record<string, unknown>;
|
|
33
|
+
/** Where the fixture goes when the wanted place does not fit: `"s inside"`, or '' for nowhere. */
|
|
34
|
+
fallback: string;
|
|
35
|
+
static preferredTagName: string;
|
|
36
|
+
static shadowStyleSpec: {
|
|
37
|
+
':host': {
|
|
38
|
+
display: string;
|
|
39
|
+
gridTemplateColumns: string;
|
|
40
|
+
gridTemplateRows: string;
|
|
41
|
+
'--tosi-affix-direction': string;
|
|
42
|
+
};
|
|
43
|
+
':host([hidden])': {
|
|
44
|
+
display: string;
|
|
45
|
+
};
|
|
46
|
+
':host > [part="content"]': {
|
|
47
|
+
display: string;
|
|
48
|
+
gridArea: string;
|
|
49
|
+
minWidth: string;
|
|
50
|
+
minHeight: string;
|
|
51
|
+
position: string;
|
|
52
|
+
};
|
|
53
|
+
':host > [part="fixture"]': {
|
|
54
|
+
display: string;
|
|
55
|
+
flexDirection: string;
|
|
56
|
+
alignItems: string;
|
|
57
|
+
zIndex: string;
|
|
58
|
+
gap: string;
|
|
59
|
+
padding: string;
|
|
60
|
+
background: string;
|
|
61
|
+
color: string;
|
|
62
|
+
};
|
|
63
|
+
':host > [part="fixture"][hidden]': {
|
|
64
|
+
display: string;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
content: () => HTMLSlotElement[];
|
|
68
|
+
private _wanted;
|
|
69
|
+
private _placed;
|
|
70
|
+
private _wantedLength;
|
|
71
|
+
private _observer;
|
|
72
|
+
/** Where the fixture is (set: where it should be). */
|
|
73
|
+
get position(): AffixPosition;
|
|
74
|
+
set position(value: string);
|
|
75
|
+
/** Whether the fixture is inside the content (set: whether it should be). */
|
|
76
|
+
get inside(): boolean;
|
|
77
|
+
set inside(value: boolean | string);
|
|
78
|
+
/** Where the fixture should be, whatever fits. */
|
|
79
|
+
get wanted(): AffixPlacement;
|
|
80
|
+
/** An empty fixture slot is hidden, so it takes no room and draws no background. */
|
|
81
|
+
private syncEmpty;
|
|
82
|
+
handleSlotChange: () => void;
|
|
83
|
+
connectedCallback(): void;
|
|
84
|
+
private _observed;
|
|
85
|
+
observeContent: () => void;
|
|
86
|
+
disconnectedCallback(): void;
|
|
87
|
+
/** The fixture's and the content's lengths along `edge`, as laid out now. */
|
|
88
|
+
private lengths;
|
|
89
|
+
/** Choose where the fixture goes, lay it out there, and announce a change. */
|
|
90
|
+
place: () => void;
|
|
91
|
+
/** Lay the fixture out at `placement`, and announce it if that is a change. */
|
|
92
|
+
private layout;
|
|
93
|
+
private apply;
|
|
94
|
+
render(): void;
|
|
95
|
+
}
|
|
96
|
+
export declare const tosiAffix: ElementCreator<TosiAffix>;
|
|
97
|
+
export {};
|