@lloyal-labs/ui 0.1.0-alpha.10
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/LICENSE +107 -0
- package/dist/assets.d.ts +18 -0
- package/dist/assets.d.ts.map +1 -0
- package/dist/assets.js +83 -0
- package/dist/assets.js.map +1 -0
- package/dist/fold.d.ts +211 -0
- package/dist/fold.d.ts.map +1 -0
- package/dist/fold.js +320 -0
- package/dist/fold.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/lightbox.d.ts +21 -0
- package/dist/lightbox.d.ts.map +1 -0
- package/dist/lightbox.js +43 -0
- package/dist/lightbox.js.map +1 -0
- package/dist/markdown.d.ts +12 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +34 -0
- package/dist/markdown.js.map +1 -0
- package/dist/prose.d.ts +57 -0
- package/dist/prose.d.ts.map +1 -0
- package/dist/prose.js +176 -0
- package/dist/prose.js.map +1 -0
- package/dist/provider.d.ts +43 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +172 -0
- package/dist/provider.js.map +1 -0
- package/package.json +66 -0
package/dist/prose.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The headings, links and heading ids of a markdown body, read with the grammar
|
|
3
|
+
* that renders it. `Markdown` draws prose through remark; what a view derives
|
|
4
|
+
* from the same prose — an outline, citation chips, the id a heading is given —
|
|
5
|
+
* comes from the same parser, so what the outline names is what the page shows,
|
|
6
|
+
* by construction: a heading's `text` here is the string its rendered element
|
|
7
|
+
* contains, inline markup and all resolved.
|
|
8
|
+
*
|
|
9
|
+
* Two grammars are used on purpose, split by concern. Headings and links
|
|
10
|
+
* (`headingsOf`, `linksOf`) come from remark, memoized, and parsed in the two
|
|
11
|
+
* pieces the streaming view renders — the finished blocks and the block under
|
|
12
|
+
* the caret — so a fact read per token costs one block's parse. The
|
|
13
|
+
* streaming boundary (`splitStreaming`) comes from marked's block lexer, which
|
|
14
|
+
* runs on every token over the whole buffer and is fifteen times cheaper — and
|
|
15
|
+
* a boundary it misjudges costs one extra parse of one block, never a wrong
|
|
16
|
+
* document, so it need not agree with the renderer to the byte.
|
|
17
|
+
*
|
|
18
|
+
* Framework-free: a node script, the Ink view and the browser page read the
|
|
19
|
+
* same headings and links.
|
|
20
|
+
*
|
|
21
|
+
* @packageDocumentation
|
|
22
|
+
* @category UI
|
|
23
|
+
*/
|
|
24
|
+
import { lexer } from 'marked';
|
|
25
|
+
import { unified } from 'unified';
|
|
26
|
+
import remarkParse from 'remark-parse';
|
|
27
|
+
import remarkGfm from 'remark-gfm';
|
|
28
|
+
import remarkMath from 'remark-math';
|
|
29
|
+
import { toString } from 'mdast-util-to-string';
|
|
30
|
+
/** The url schemes a link may carry: react-markdown's own rule (micromark's `sanitizeUri` without the encode
|
|
31
|
+
* step — https://github.com/remarkjs/react-markdown, `defaultUrlTransform`), restated here because that module
|
|
32
|
+
* imports React at scope and this one is framework-free. */
|
|
33
|
+
const SAFE_PROTOCOL = /^(https?|ircs?|mailto|xmpp)$/i;
|
|
34
|
+
/** The ONE url policy of a harness view: the content plane's scheme (`attachment://…`) is admitted, a relative
|
|
35
|
+
* url or a safe scheme passes, anything else (`javascript:`, `data:`) is stripped to `''`. `Markdown` renders
|
|
36
|
+
* through it and `linksOf` reports through it, so a citation built from a link carries the href the page
|
|
37
|
+
* carries. */
|
|
38
|
+
export function admitUrl(url) {
|
|
39
|
+
if (url.startsWith('attachment://'))
|
|
40
|
+
return url;
|
|
41
|
+
const colon = url.indexOf(':');
|
|
42
|
+
const questionMark = url.indexOf('?');
|
|
43
|
+
const numberSign = url.indexOf('#');
|
|
44
|
+
const slash = url.indexOf('/');
|
|
45
|
+
if (colon === -1 || // no protocol: relative
|
|
46
|
+
(slash !== -1 && colon > slash) || // the first colon is not a protocol's
|
|
47
|
+
(questionMark !== -1 && colon > questionMark) ||
|
|
48
|
+
(numberSign !== -1 && colon > numberSign) ||
|
|
49
|
+
SAFE_PROTOCOL.test(url.slice(0, colon)))
|
|
50
|
+
return url;
|
|
51
|
+
return '';
|
|
52
|
+
}
|
|
53
|
+
/** The renderer's grammar, exactly: `Markdown` parses with these two plugins, so a `$…$` span is math here as
|
|
54
|
+
* it is there, never emphasis. */
|
|
55
|
+
const parser = unified().use(remarkParse).use(remarkGfm).use(remarkMath);
|
|
56
|
+
/** Parsed texts, most recent last. A body is parsed in two pieces (see {@link nodesOf}), and a canvas reads the
|
|
57
|
+
* settled body, its exchanges and the sections in one pass, so a small memo would thrash; an unbounded one
|
|
58
|
+
* would pin every body a session ever showed. */
|
|
59
|
+
const parsed = new Map();
|
|
60
|
+
const KEEP = 32;
|
|
61
|
+
function rootOf(markdown) {
|
|
62
|
+
const hit = parsed.get(markdown);
|
|
63
|
+
if (hit) {
|
|
64
|
+
parsed.delete(markdown);
|
|
65
|
+
parsed.set(markdown, hit);
|
|
66
|
+
return hit;
|
|
67
|
+
}
|
|
68
|
+
const root = parser.parse(markdown);
|
|
69
|
+
parsed.set(markdown, root);
|
|
70
|
+
if (parsed.size > KEEP)
|
|
71
|
+
parsed.delete(parsed.keys().next().value);
|
|
72
|
+
return root;
|
|
73
|
+
}
|
|
74
|
+
function* walk(nodes) {
|
|
75
|
+
for (const node of nodes) {
|
|
76
|
+
yield node;
|
|
77
|
+
if ('children' in node && Array.isArray(node.children))
|
|
78
|
+
yield* walk(node.children);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Every node of a body with where it starts, parsed the way the streaming view renders it: the finished
|
|
82
|
+
* blocks as one piece, kept while they stand, and the block under the caret as another, parsed fresh. A fact
|
|
83
|
+
* read per token — the outline of a section as it streams — then costs one block's parse, not the body's;
|
|
84
|
+
* and a settled body costs its parse once. The pieces are {@link splitStreaming}'s, so a body it refuses to
|
|
85
|
+
* split (a reference definition, display math) is one piece, and no block is ever read across the seam. The
|
|
86
|
+
* offsets count into the body with its line endings normalised to `\n`, as the split normalises them. */
|
|
87
|
+
function* nodesOf(markdown) {
|
|
88
|
+
const { head, tail } = splitStreaming(markdown);
|
|
89
|
+
for (const node of walk(rootOf(head).children))
|
|
90
|
+
yield { node, offset: node.position?.start.offset ?? 0 };
|
|
91
|
+
for (const node of walk(rootOf(tail).children))
|
|
92
|
+
yield { node, offset: head.length + (node.position?.start.offset ?? 0) };
|
|
93
|
+
}
|
|
94
|
+
/** Every heading in document order. */
|
|
95
|
+
export function headingsOf(markdown) {
|
|
96
|
+
const out = [];
|
|
97
|
+
for (const { node, offset } of nodesOf(markdown)) {
|
|
98
|
+
if (node.type === 'heading')
|
|
99
|
+
out.push({ depth: node.depth, text: toString(node), offset });
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
/** Every link in document order, as the renderer draws them: inline links, the bare urls GFM links, and
|
|
104
|
+
* reference-style links resolved through their definitions — the FIRST definition of an identifier, as
|
|
105
|
+
* CommonMark resolves it (an unresolved reference renders as text and is not a link). Each href has passed
|
|
106
|
+
* {@link admitUrl}, so a link whose scheme the renderer strips is reported with the same empty href. */
|
|
107
|
+
export function linksOf(markdown) {
|
|
108
|
+
const definitions = new Map();
|
|
109
|
+
for (const { node } of nodesOf(markdown)) {
|
|
110
|
+
if (node.type === 'definition' && !definitions.has(node.identifier))
|
|
111
|
+
definitions.set(node.identifier, node.url);
|
|
112
|
+
}
|
|
113
|
+
const out = [];
|
|
114
|
+
for (const { node, offset } of nodesOf(markdown)) {
|
|
115
|
+
if (node.type === 'link')
|
|
116
|
+
out.push({ href: admitUrl(node.url), text: toString(node), offset });
|
|
117
|
+
else if (node.type === 'linkReference') {
|
|
118
|
+
const href = definitions.get(node.identifier);
|
|
119
|
+
if (href !== undefined)
|
|
120
|
+
out.push({ href: admitUrl(href), text: toString(node), offset });
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
125
|
+
const slugify = (text) => text.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '').slice(0, 60) || 'h';
|
|
126
|
+
/** The id each heading is given under `prefix`, in document order — the ONE derivation, so an outline that
|
|
127
|
+
* names an anchor and the prose that carries it cannot disagree. A repeated heading is numbered from its
|
|
128
|
+
* second appearance, and the number is taken against the ids already given out, not the slug's count: `A`,
|
|
129
|
+
* `A`, `A-2` become `a`, `a-2`, `a-2-2`, never two `a-2`s. A renderer assigns these to its heading elements
|
|
130
|
+
* in the same order. */
|
|
131
|
+
export function anchorsOf(headings, prefix) {
|
|
132
|
+
const given = new Set();
|
|
133
|
+
return headings.map((h) => {
|
|
134
|
+
const base = `${prefix}-${slugify(h.text)}`;
|
|
135
|
+
let anchor = base;
|
|
136
|
+
for (let n = 2; given.has(anchor); n++)
|
|
137
|
+
anchor = `${base}-${n}`;
|
|
138
|
+
given.add(anchor);
|
|
139
|
+
return { anchor, text: h.text, depth: h.depth };
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/** Where streaming prose stops being finished. Everything up to the last block CommonMark recognises is
|
|
143
|
+
* complete, parsed once and kept while it stands; the last block is the one still being written, parsed per
|
|
144
|
+
* token. The boundaries are marked's — a spec-tested block tokenizer, used here only to find where the last
|
|
145
|
+
* block starts: a loose list is one block, a fence owns its blank lines. A block boundary this misjudges
|
|
146
|
+
* would cost one extra parse of one block, never a wrong document — except for two constructs marked does not
|
|
147
|
+
* see the way the renderer does, where the split is refused and the whole buffer is the tail:
|
|
148
|
+
* - a reference definition (anywhere, a blockquote included) resolves links in EARLIER blocks, so a head
|
|
149
|
+
* rendered without it would show those references as text;
|
|
150
|
+
* - a display equation (`$$…$$`) may span a blank line, which marked reads as a block boundary; cut there,
|
|
151
|
+
* the renderer would draw an equation, a paragraph and an empty equation — and nothing short of the
|
|
152
|
+
* renderer's grammar can say where one opens (a `$$` in inline code is not a delimiter; `$$$$` is).
|
|
153
|
+
* A document that carries either is rendered whole: the split is refused for the document's whole life, and
|
|
154
|
+
* the cost of that is paid only by documents with display math or reference definitions. */
|
|
155
|
+
export function splitStreaming(markdown) {
|
|
156
|
+
// marked reports raw text with line endings normalised; normalise first so head + tail is the text parsed.
|
|
157
|
+
const text = markdown.replace(/\r\n?/g, '\n');
|
|
158
|
+
const tokens = lexer(text);
|
|
159
|
+
if (tokens.length < 2 || text.includes('$$') || hasDefinition(tokens))
|
|
160
|
+
return { head: '', tail: text };
|
|
161
|
+
const cut = text.length - tokens[tokens.length - 1].raw.length;
|
|
162
|
+
return { head: text.slice(0, cut), tail: text.slice(cut) };
|
|
163
|
+
}
|
|
164
|
+
/** A reference definition at any depth of marked's token tree — a blockquote or list nests its own. */
|
|
165
|
+
function hasDefinition(tokens) {
|
|
166
|
+
for (const t of tokens) {
|
|
167
|
+
if (t.type === 'def')
|
|
168
|
+
return true;
|
|
169
|
+
if (t.tokens && hasDefinition(t.tokens))
|
|
170
|
+
return true;
|
|
171
|
+
if (t.items && hasDefinition(t.items))
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=prose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prose.js","sourceRoot":"","sources":["../src/prose.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import type { Availability, Bridge, Projection, WireStatus } from '@lloyal-labs/binding';
|
|
3
|
+
export interface Harness<E, C, S extends object> {
|
|
4
|
+
bridge: Bridge<E, C, S>;
|
|
5
|
+
projection: Projection<S>;
|
|
6
|
+
}
|
|
7
|
+
/** The one projection over a bridge — the provider's, shared with a consumer outside React (a history adapter). */
|
|
8
|
+
export declare function projectionFor<E, C, S extends object>(bridge: Bridge<E, C, S>, initialState: S, reduce: (state: S, ev: E) => S): Projection<S>;
|
|
9
|
+
export declare function HarnessProvider<E, C, S extends object>({ bridge, initialState, reduce, children }: {
|
|
10
|
+
bridge: Bridge<E, C, S>;
|
|
11
|
+
initialState: S;
|
|
12
|
+
reduce: (state: S, ev: E) => S;
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
}): ReactElement;
|
|
15
|
+
/** The provider's bridge and projection, for a consumer outside the hooks (a history adapter). */
|
|
16
|
+
export declare function useHarness<E = unknown, C = unknown, S extends object = object>(): Harness<E, C, S>;
|
|
17
|
+
/** Read a derivation of the folded state, memoized per fold. */
|
|
18
|
+
export declare function useProjection<S extends object, T>(select: (state: S) => T): T;
|
|
19
|
+
/** Dispatch a command to the harness. */
|
|
20
|
+
export declare function useSend<C>(): (command: C) => void;
|
|
21
|
+
/** The wire's status. A bridge without `onStatus` (in-process) reads 'connected' forever. */
|
|
22
|
+
export declare function useConnection(): WireStatus;
|
|
23
|
+
/**
|
|
24
|
+
* Whether this harness can take work, and if not, why — the question a view actually asks.
|
|
25
|
+
*
|
|
26
|
+
* Derived from the transport's status and the host's session phase, because neither answers it
|
|
27
|
+
* alone: a queued reader's socket is healthy, and an ended session is followed by a close that
|
|
28
|
+
* reads as a network failure. Prefer this to {@link useConnection}, which is the transport fact
|
|
29
|
+
* on its own.
|
|
30
|
+
*/
|
|
31
|
+
export declare function useAvailability(): Availability;
|
|
32
|
+
/**
|
|
33
|
+
* Ask the placement for a working harness — or null where this bridge cannot provide one.
|
|
34
|
+
*
|
|
35
|
+
* A view knows WHEN recovery is wanted and never what it costs: a browser opens a new connection
|
|
36
|
+
* because a served host cannot re-admit an existing one; a desktop shell starts a new engine while
|
|
37
|
+
* its renderer's IPC link stays up throughout. Same button, different price, and the view pays
|
|
38
|
+
* neither.
|
|
39
|
+
*/
|
|
40
|
+
export declare function useRecover(): (() => void) | null;
|
|
41
|
+
/** The content plane's origin, or null on a bridge without one. */
|
|
42
|
+
export declare function useContentOrigin(): string | null;
|
|
43
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAErD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAgB,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvG,MAAM,WAAW,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,MAAM;IAC7C,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACxB,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;CAC3B;AASD,mHAAmH;AACnH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAO7I;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,MAAM,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE;IAClG,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACxB,YAAY,EAAE,CAAC,CAAC;IAChB,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;IAC/B,QAAQ,EAAE,SAAS,CAAC;CACrB,GAAG,YAAY,CAGf;AAED,kGAAkG;AAClG,wBAAgB,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,SAAS,MAAM,GAAG,MAAM,KAAK,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAIlG;AAID,gEAAgE;AAChE,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAc7E;AAED,yCAAyC;AACzC,wBAAgB,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI,CAGjD;AAqCD,6FAA6F;AAC7F,wBAAgB,aAAa,IAAI,UAAU,CAI1C;AA4CD;;;;;;;GAOG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAI9C;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAGhD;AAED,mEAAmE;AACnE,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAGhD"}
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The projection, in React: a provider that connects a bridge once, and hooks
|
|
3
|
+
* that read the fold, the wire's status, the command sink and the content
|
|
4
|
+
* plane's origin. One projection per provider; a remount under the same bridge
|
|
5
|
+
* reattaches to the running fold, it never re-subscribes or resets.
|
|
6
|
+
*
|
|
7
|
+
* `useProjection(select)` memoizes per fold: the state is immutable between
|
|
8
|
+
* events, so a named selector returns the SAME reference until the next fold —
|
|
9
|
+
* what `useSyncExternalStore` needs. The contract: a selector with a stable
|
|
10
|
+
* identity may build objects; an inline selector must return a primitive.
|
|
11
|
+
*
|
|
12
|
+
* The folded state must be an OBJECT, and a new one on every event. Both halves
|
|
13
|
+
* are load-bearing and neither is a style preference: the memo is a `WeakMap`
|
|
14
|
+
* keyed by the snapshot, so a scalar or `null` state is not a legal key at all,
|
|
15
|
+
* and a state mutated in place keeps its identity and so keeps returning the
|
|
16
|
+
* selection cached against the previous fold. `S extends object` states the
|
|
17
|
+
* first half to the compiler. The second is a discipline the type system cannot
|
|
18
|
+
* carry, which is why it is written here.
|
|
19
|
+
*
|
|
20
|
+
* @category UI
|
|
21
|
+
*/
|
|
22
|
+
import { createContext, createElement, useContext, useMemo, useSyncExternalStore } from 'react';
|
|
23
|
+
import { connectProjection, availabilityOf } from '@lloyal-labs/binding';
|
|
24
|
+
// `object`, not `unknown`, is what the erased context can say now that `S` is
|
|
25
|
+
// constrained — the hooks below cast back out of it exactly as before.
|
|
26
|
+
const HarnessContext = createContext(null);
|
|
27
|
+
/** One projection per bridge, for the life of the page: a React remount under the same bridge reattaches. */
|
|
28
|
+
const projections = new WeakMap();
|
|
29
|
+
/** The one projection over a bridge — the provider's, shared with a consumer outside React (a history adapter). */
|
|
30
|
+
export function projectionFor(bridge, initialState, reduce) {
|
|
31
|
+
let projection = projections.get(bridge);
|
|
32
|
+
if (!projection) {
|
|
33
|
+
projection = connectProjection(bridge, initialState, reduce);
|
|
34
|
+
projections.set(bridge, projection);
|
|
35
|
+
}
|
|
36
|
+
return projection;
|
|
37
|
+
}
|
|
38
|
+
export function HarnessProvider({ bridge, initialState, reduce, children }) {
|
|
39
|
+
const value = useMemo(() => ({ bridge, projection: projectionFor(bridge, initialState, reduce) }), [bridge]);
|
|
40
|
+
return createElement(HarnessContext.Provider, { value: value }, children);
|
|
41
|
+
}
|
|
42
|
+
/** The provider's bridge and projection, for a consumer outside the hooks (a history adapter). */
|
|
43
|
+
export function useHarness() {
|
|
44
|
+
const h = useContext(HarnessContext);
|
|
45
|
+
if (!h)
|
|
46
|
+
throw new Error('useHarness: no HarnessProvider above this component');
|
|
47
|
+
return h;
|
|
48
|
+
}
|
|
49
|
+
const derived = new WeakMap();
|
|
50
|
+
/** Read a derivation of the folded state, memoized per fold. */
|
|
51
|
+
export function useProjection(select) {
|
|
52
|
+
const { projection } = useHarness();
|
|
53
|
+
const read = () => {
|
|
54
|
+
const state = projection.getSnapshot();
|
|
55
|
+
let memo = derived.get(state);
|
|
56
|
+
if (!memo) {
|
|
57
|
+
memo = new Map();
|
|
58
|
+
derived.set(state, memo);
|
|
59
|
+
}
|
|
60
|
+
const key = select;
|
|
61
|
+
if (!memo.has(key))
|
|
62
|
+
memo.set(key, select(state));
|
|
63
|
+
return memo.get(key);
|
|
64
|
+
};
|
|
65
|
+
return useSyncExternalStore(projection.subscribe, read, read);
|
|
66
|
+
}
|
|
67
|
+
/** Dispatch a command to the harness. */
|
|
68
|
+
export function useSend() {
|
|
69
|
+
const { bridge } = useHarness();
|
|
70
|
+
return bridge.send;
|
|
71
|
+
}
|
|
72
|
+
/** One status per bridge, for the life of the page. React reads `getSnapshot`
|
|
73
|
+
* during render, so the status it reads must outlive the render that reads it:
|
|
74
|
+
* the bridge is told once, here, and every renderer of it shares that one
|
|
75
|
+
* answer. A bridge without `onStatus` (in-process) never leaves 'connected'. */
|
|
76
|
+
const statuses = new WeakMap();
|
|
77
|
+
function statusFor(bridge) {
|
|
78
|
+
let store = statuses.get(bridge);
|
|
79
|
+
if (!store) {
|
|
80
|
+
let status = 'connected';
|
|
81
|
+
const listeners = new Set();
|
|
82
|
+
bridge.onStatus?.((next) => {
|
|
83
|
+
status = next;
|
|
84
|
+
for (const notify of listeners)
|
|
85
|
+
notify();
|
|
86
|
+
});
|
|
87
|
+
store = {
|
|
88
|
+
subscribe(notify) {
|
|
89
|
+
listeners.add(notify);
|
|
90
|
+
return () => { listeners.delete(notify); };
|
|
91
|
+
},
|
|
92
|
+
getSnapshot: () => status,
|
|
93
|
+
};
|
|
94
|
+
statuses.set(bridge, store);
|
|
95
|
+
}
|
|
96
|
+
return store;
|
|
97
|
+
}
|
|
98
|
+
/** The status a server render reads: no wire has been asked yet. */
|
|
99
|
+
const connected = () => 'connected';
|
|
100
|
+
/** The wire's status. A bridge without `onStatus` (in-process) reads 'connected' forever. */
|
|
101
|
+
export function useConnection() {
|
|
102
|
+
const { bridge } = useHarness();
|
|
103
|
+
const wire = statusFor(bridge);
|
|
104
|
+
return useSyncExternalStore(wire.subscribe, wire.getSnapshot, connected);
|
|
105
|
+
}
|
|
106
|
+
/** One derivation per bridge, for the life of the page — the same reason the status has one. */
|
|
107
|
+
const availabilities = new WeakMap();
|
|
108
|
+
function availabilityFor(bridge) {
|
|
109
|
+
let store = availabilities.get(bridge);
|
|
110
|
+
if (!store) {
|
|
111
|
+
// A bridge with no droppable link is up, and one with no session plane has a single implicit
|
|
112
|
+
// session that is live: nothing queues it and nothing reaps it, so "waiting" and "ended" are not
|
|
113
|
+
// states it can be in. This is the ONE place a placement difference is stated; the derivation
|
|
114
|
+
// itself knows no placements.
|
|
115
|
+
let wire = 'connected';
|
|
116
|
+
let session = bridge.onSession ? null : { phase: 'live' };
|
|
117
|
+
let value = availabilityOf(session, wire);
|
|
118
|
+
const listeners = new Set();
|
|
119
|
+
const settle = () => {
|
|
120
|
+
const next = availabilityOf(session, wire);
|
|
121
|
+
if (next === value)
|
|
122
|
+
return;
|
|
123
|
+
value = next;
|
|
124
|
+
for (const notify of listeners)
|
|
125
|
+
notify();
|
|
126
|
+
};
|
|
127
|
+
bridge.onStatus?.((next) => { wire = next; settle(); });
|
|
128
|
+
bridge.onSession?.((next) => { session = next; settle(); });
|
|
129
|
+
store = {
|
|
130
|
+
subscribe(notify) {
|
|
131
|
+
listeners.add(notify);
|
|
132
|
+
return () => { listeners.delete(notify); };
|
|
133
|
+
},
|
|
134
|
+
getSnapshot: () => value,
|
|
135
|
+
};
|
|
136
|
+
availabilities.set(bridge, store);
|
|
137
|
+
}
|
|
138
|
+
return store;
|
|
139
|
+
}
|
|
140
|
+
/** What a server render reads: nothing has been asked of either plane yet. */
|
|
141
|
+
const starting = () => 'connecting';
|
|
142
|
+
/**
|
|
143
|
+
* Whether this harness can take work, and if not, why — the question a view actually asks.
|
|
144
|
+
*
|
|
145
|
+
* Derived from the transport's status and the host's session phase, because neither answers it
|
|
146
|
+
* alone: a queued reader's socket is healthy, and an ended session is followed by a close that
|
|
147
|
+
* reads as a network failure. Prefer this to {@link useConnection}, which is the transport fact
|
|
148
|
+
* on its own.
|
|
149
|
+
*/
|
|
150
|
+
export function useAvailability() {
|
|
151
|
+
const { bridge } = useHarness();
|
|
152
|
+
const store = availabilityFor(bridge);
|
|
153
|
+
return useSyncExternalStore(store.subscribe, store.getSnapshot, starting);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Ask the placement for a working harness — or null where this bridge cannot provide one.
|
|
157
|
+
*
|
|
158
|
+
* A view knows WHEN recovery is wanted and never what it costs: a browser opens a new connection
|
|
159
|
+
* because a served host cannot re-admit an existing one; a desktop shell starts a new engine while
|
|
160
|
+
* its renderer's IPC link stays up throughout. Same button, different price, and the view pays
|
|
161
|
+
* neither.
|
|
162
|
+
*/
|
|
163
|
+
export function useRecover() {
|
|
164
|
+
const { bridge } = useHarness();
|
|
165
|
+
return useMemo(() => (bridge.recover ? () => bridge.recover() : null), [bridge]);
|
|
166
|
+
}
|
|
167
|
+
/** The content plane's origin, or null on a bridge without one. */
|
|
168
|
+
export function useContentOrigin() {
|
|
169
|
+
const { bridge } = useHarness();
|
|
170
|
+
return bridge.contentOrigin?.() ?? null;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lloyal-labs/ui",
|
|
3
|
+
"version": "0.1.0-alpha.10",
|
|
4
|
+
"description": "The view side of a harness: the projection provider and hooks over a bridge, the generic agent fold, and the prose and figure primitives",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./fold": {
|
|
14
|
+
"types": "./dist/fold.d.ts",
|
|
15
|
+
"default": "./dist/fold.js"
|
|
16
|
+
},
|
|
17
|
+
"./prose": {
|
|
18
|
+
"types": "./dist/prose.d.ts",
|
|
19
|
+
"default": "./dist/prose.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/lloyal-ai/hdk.git",
|
|
28
|
+
"directory": "packages/ui"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/lloyal-ai/hdk/tree/main/packages/ui#readme",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/lloyal-ai/hdk/issues"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"ui",
|
|
36
|
+
"react",
|
|
37
|
+
"harness",
|
|
38
|
+
"projection",
|
|
39
|
+
"markdown"
|
|
40
|
+
],
|
|
41
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
42
|
+
"files": [
|
|
43
|
+
"dist/",
|
|
44
|
+
"LICENSE"
|
|
45
|
+
],
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsc -p tsconfig.json"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@lloyal-labs/binding": "0.2.0-alpha.6",
|
|
51
|
+
"@lloyal-labs/media": "0.2.0-alpha.6",
|
|
52
|
+
"@types/mdast": "^4.0.4",
|
|
53
|
+
"katex": "^0.16.22",
|
|
54
|
+
"marked": "^18.0.13",
|
|
55
|
+
"mdast-util-to-string": "^4.0.0",
|
|
56
|
+
"react-markdown": "^10.1.0",
|
|
57
|
+
"rehype-katex": "^7.0.1",
|
|
58
|
+
"remark-gfm": "^4.0.1",
|
|
59
|
+
"remark-math": "^6.0.0",
|
|
60
|
+
"remark-parse": "^11.0.0",
|
|
61
|
+
"unified": "^11.0.5"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"react": "^18.3.0 || ^19.0.0"
|
|
65
|
+
}
|
|
66
|
+
}
|