gesso-framework 0.6.29 → 0.7.0

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/dist/{FunctionComponent-CHtojpp7.d.ts → FunctionComponent-Czkex8fp.d.ts} +358 -114
  3. package/dist/{serveChannels-BlEag7WU.js → WorkerPorts-m_hLRoPj.js} +8 -240
  4. package/dist/WorkerPorts-m_hLRoPj.js.map +1 -0
  5. package/dist/agent/index.d.ts +53 -2
  6. package/dist/agent/index.js +5 -4
  7. package/dist/agent/index.js.map +1 -1
  8. package/dist/app-De3z58x7.js +638 -0
  9. package/dist/app-De3z58x7.js.map +1 -0
  10. package/dist/computed-_cYcdczA.js +577 -0
  11. package/dist/computed-_cYcdczA.js.map +1 -0
  12. package/dist/createComponent-DJads88q.js +47 -0
  13. package/dist/createComponent-DJads88q.js.map +1 -0
  14. package/dist/{index-DZbSb8IN.d.ts → index-BENndtaH.d.ts} +222 -96
  15. package/dist/index.d.ts +4 -5
  16. package/dist/index.js +440 -6645
  17. package/dist/index.js.map +1 -1
  18. package/dist/jsx/jsx-runtime.d.ts +8 -5
  19. package/dist/jsx/jsx-runtime.js +15 -6
  20. package/dist/jsx/jsx-runtime.js.map +1 -1
  21. package/dist/{persisted-fUzIU8FZ.js → persisted-8meJmsOh.js} +4 -576
  22. package/dist/persisted-8meJmsOh.js.map +1 -0
  23. package/dist/remote/index.d.ts +2 -2
  24. package/dist/remote/index.js +2 -1
  25. package/dist/remote/index.js.map +1 -1
  26. package/dist/{remote-BoB8zh7z.js → remote-B4bjdTzg.js} +19 -4
  27. package/dist/remote-B4bjdTzg.js.map +1 -0
  28. package/dist/render-cydQ10Nd.js +6795 -0
  29. package/dist/render-cydQ10Nd.js.map +1 -0
  30. package/dist/serveChannels-DReCmRxO.js +241 -0
  31. package/dist/serveChannels-DReCmRxO.js.map +1 -0
  32. package/dist/{createComponent-3n1ZSql8.js → show-D0MevHaV.js} +2 -46
  33. package/dist/show-D0MevHaV.js.map +1 -0
  34. package/dist/{ui-CHtNccR8.d.ts → tools-BFBwuinE.d.ts} +351 -8
  35. package/dist/{webmcp-CdDq2nzS.js → webmcp-D7IlA0fu.js} +3 -3
  36. package/dist/webmcp-D7IlA0fu.js.map +1 -0
  37. package/dist/worker/index.d.ts +3 -4
  38. package/dist/worker/index.js +5 -3
  39. package/dist/worker/index.js.map +1 -1
  40. package/package.json +2 -2
  41. package/dist/ChannelProtocol-ByNoHujM.d.ts +0 -247
  42. package/dist/app-Yig59Ygf.js +0 -326
  43. package/dist/app-Yig59Ygf.js.map +0 -1
  44. package/dist/createComponent-3n1ZSql8.js.map +0 -1
  45. package/dist/persisted-fUzIU8FZ.js.map +0 -1
  46. package/dist/remote-BoB8zh7z.js.map +0 -1
  47. package/dist/serveChannels-BlEag7WU.js.map +0 -1
  48. package/dist/webmcp-CdDq2nzS.js.map +0 -1
@@ -0,0 +1,241 @@
1
+ import { b as isChannelClientMessage, o as servePorts, w as viewKeys, y as diffProjection } from "./WorkerPorts-m_hLRoPj.js";
2
+ import { d as requirePlainData, i as serveAgentPort, o as agentSurface } from "./remote-B4bjdTzg.js";
3
+ import { Subscription } from "rxjs";
4
+ //#region src/channel/provide.ts
5
+ /**
6
+ * Publishes a channel from the thread that owns its data.
7
+ *
8
+ * Each view key is subscribed, diffed against what the other side last
9
+ * saw, and sent as patches. Whatever produced the observable — a bare
10
+ * subject or a stack of layers — stays here; only plain data crosses.
11
+ *
12
+ * Keys are subscribed on the first sync request, so a channel nobody
13
+ * is watching costs nothing.
14
+ */
15
+ function provide(token, source, port) {
16
+ return new ProvidedChannel(token, source, port);
17
+ }
18
+ var ProvidedChannel = class {
19
+ token;
20
+ source;
21
+ port;
22
+ subscriptions = new Subscription();
23
+ /**
24
+ * What the other side is known to hold, seeded from the token's
25
+ * initial value — which the replica also starts from, so an app
26
+ * whose first emission equals the initial sends nothing at all.
27
+ */
28
+ previous = /* @__PURE__ */ new Map();
29
+ checked = /* @__PURE__ */ new Set();
30
+ /**
31
+ * Patches a running command has published and not yet sent. A command
32
+ * that moves five view keys used to post five messages, each cloned
33
+ * across the barrier and applied by the replica on its own; they now
34
+ * leave together, as one message, the moment the command returns.
35
+ *
36
+ * Only a command's: a patch published anywhere else (a timer, a
37
+ * recalculation the application thread schedules) is posted at once,
38
+ * because nothing marks where that work ends but the end of the turn,
39
+ * and waiting for that would leave a caller that has just run it
40
+ * synchronously, a test above all, looking at a port with nothing on
41
+ * it yet.
42
+ */
43
+ pending = [];
44
+ /** How many commands are running, nested ones counted. */
45
+ commanding = 0;
46
+ synced = false;
47
+ constructor(token, source, port) {
48
+ this.token = token;
49
+ this.source = source;
50
+ this.port = port;
51
+ for (const key of viewKeys(token)) this.previous.set(key, token.initial[key]);
52
+ this.port.onmessage = (event) => this.receive(event.data);
53
+ }
54
+ receive(data) {
55
+ if (!isChannelClientMessage(data)) return;
56
+ try {
57
+ if (data.type === "channel:sync") {
58
+ this.sync();
59
+ return;
60
+ }
61
+ this.commanding++;
62
+ try {
63
+ this.runCommand(data.command, data.payload, data.rest);
64
+ } finally {
65
+ this.commanding--;
66
+ if (this.commanding === 0) this.sendPending();
67
+ }
68
+ } catch (error) {
69
+ this.post({
70
+ type: "channel:error",
71
+ message: error instanceof Error ? error.message : String(error),
72
+ stack: error instanceof Error ? error.stack : void 0
73
+ });
74
+ }
75
+ }
76
+ runCommand(name, payload, rest) {
77
+ const handler = this.source.commands?.[name];
78
+ if (handler === void 0) {
79
+ const names = Object.keys(this.source.commands ?? {}).sort().join(", ");
80
+ throw new Error(`Channel '${this.token.name}' has no command '${name}'. Declared commands: ${names.length > 0 ? names : "(none)"}.`);
81
+ }
82
+ handler(payload, ...rest ?? []);
83
+ }
84
+ sync() {
85
+ if (this.synced) {
86
+ this.resend();
87
+ return;
88
+ }
89
+ this.synced = true;
90
+ for (const key of viewKeys(this.token)) {
91
+ const observable = this.source.view[key];
92
+ if (observable === void 0) {
93
+ this.post({
94
+ type: "channel:error",
95
+ message: `Channel '${this.token.name}' declares view key '${key}' but nothing was provided for it.`
96
+ });
97
+ continue;
98
+ }
99
+ this.subscriptions.add(observable.subscribe({
100
+ next: (value) => this.publish(key, value),
101
+ error: (error) => this.post({
102
+ type: "channel:error",
103
+ message: `Channel '${this.token.name}' view key '${key}' errored: ${error instanceof Error ? error.message : String(error)}`,
104
+ stack: error instanceof Error ? error.stack : void 0
105
+ })
106
+ }));
107
+ }
108
+ }
109
+ publish(key, value) {
110
+ if (!this.checked.has(key)) {
111
+ this.checked.add(key);
112
+ try {
113
+ requirePlainData(this.token.name, key, value);
114
+ } catch (error) {
115
+ this.post({
116
+ type: "channel:error",
117
+ message: error instanceof Error ? error.message : String(error),
118
+ stack: error instanceof Error ? error.stack : void 0
119
+ });
120
+ return;
121
+ }
122
+ }
123
+ const patches = diffProjection(key, this.previous.get(key), value);
124
+ this.previous.set(key, value);
125
+ if (patches.length === 0) return;
126
+ if (this.commanding === 0) {
127
+ this.post({
128
+ type: "channel:patch",
129
+ patches
130
+ });
131
+ return;
132
+ }
133
+ for (const patch of patches) this.pending.push(patch);
134
+ }
135
+ /** Puts the patches a command has published so far on the wire now. */
136
+ sendPending() {
137
+ if (this.pending.length === 0) return;
138
+ const patches = this.pending;
139
+ this.pending = [];
140
+ const message = {
141
+ type: "channel:patch",
142
+ patches
143
+ };
144
+ this.port.postMessage(message);
145
+ }
146
+ /** Re-sends every key in full, for a client that reattached. */
147
+ resend() {
148
+ const patches = [];
149
+ for (const [key, value] of this.previous) patches.push({
150
+ op: "set",
151
+ projection: key,
152
+ path: [],
153
+ value
154
+ });
155
+ if (patches.length > 0) this.post({
156
+ type: "channel:patch",
157
+ patches
158
+ });
159
+ }
160
+ /**
161
+ * Sends any other message, after the patches published before it: the
162
+ * order on the wire is the order things happened in, batched or not.
163
+ */
164
+ post(message) {
165
+ this.sendPending();
166
+ this.port.postMessage(message);
167
+ }
168
+ dispose() {
169
+ this.sendPending();
170
+ this.subscriptions.unsubscribe();
171
+ this.port.onmessage = null;
172
+ }
173
+ };
174
+ //#endregion
175
+ //#region src/channel/serveChannels.ts
176
+ /**
177
+ * One served channel, with its source checked against its token.
178
+ *
179
+ * `ServedChannel` is erased on purpose, so one list can hold channels
180
+ * of every shape; the cost is that a view key the token declares and
181
+ * the source forgets is found at startup, by the error `provide`
182
+ * reports, rather than by the compiler. This is the typed seam: the
183
+ * source must hold an Observable for every key of the token's view and
184
+ * a handler for every command, and each handler takes the arguments
185
+ * the token declares, so none of them needs an annotation.
186
+ *
187
+ * serveChannels([
188
+ * serve(Catalog, { view: catalog, commands: { add: name => catalog.add(name) } })
189
+ * ]);
190
+ *
191
+ * The view may be any object with the right observables on it, which
192
+ * is often the domain object itself when its properties are named
193
+ * after the keys. Only the declared keys are read from it.
194
+ */
195
+ function serve(token, source) {
196
+ return {
197
+ token,
198
+ source
199
+ };
200
+ }
201
+ /**
202
+ * Publishes channels from an application worker.
203
+ *
204
+ * Call it synchronously at the top level of the worker module, before
205
+ * any await, so no handshake is missed:
206
+ *
207
+ * const catalog = new CatalogViewModel(new CatalogDomain(new OpfsStore()));
208
+ * serveChannels([
209
+ * serve(Catalog, { view: { products: catalog.products$ }, commands: { … } })
210
+ * ]);
211
+ *
212
+ * Everything above this call is the application's own — plain classes,
213
+ * plain observables, no framework import. This function is the entire
214
+ * seam between it and the view.
215
+ *
216
+ * Returns a function that stops serving and disposes what it provided.
217
+ */
218
+ function serveChannels(channels, host) {
219
+ const byName = /* @__PURE__ */ new Map();
220
+ for (const served of channels) byName.set(served.token.name, served);
221
+ const provided = [];
222
+ const stop = servePorts((key, port) => {
223
+ if (key === "gesso:agent") {
224
+ serveAgentPort(port, (confirm) => agentSurface(channels, { confirm }));
225
+ return true;
226
+ }
227
+ const served = byName.get(key);
228
+ if (served === void 0) return false;
229
+ provided.push(provide(served.token, served.source, port));
230
+ return true;
231
+ }, () => [...byName.keys()], host);
232
+ return () => {
233
+ stop();
234
+ for (const channel of provided) channel.dispose();
235
+ provided.length = 0;
236
+ };
237
+ }
238
+ //#endregion
239
+ export { provide as i, serveChannels as n, ProvidedChannel as r, serve as t };
240
+
241
+ //# sourceMappingURL=serveChannels-DReCmRxO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serveChannels-DReCmRxO.js","names":[],"sources":["../src/channel/provide.ts","../src/channel/serveChannels.ts"],"sourcesContent":["import { Subscription, type Observable } from 'rxjs';\n\nimport { diffProjection, type Patch } from './StorePatch';\nimport { isChannelClientMessage, type ChannelHostMessage, type ChannelPort } from './ChannelProtocol';\nimport { requirePlainData } from './plainData';\nimport { viewKeys, type ChannelToken, type CommandMap } from './ChannelToken';\n\n/** What the owning thread supplies for a channel. */\nexport interface ChannelSource<View extends object, Commands extends object> {\n /** One observable per declared view key. */\n view: { readonly [K in keyof View]: Observable<View[K]> };\n /** One handler per declared command. */\n commands?: Commands;\n}\n\n/**\n * Publishes a channel from the thread that owns its data.\n *\n * Each view key is subscribed, diffed against what the other side last\n * saw, and sent as patches. Whatever produced the observable — a bare\n * subject or a stack of layers — stays here; only plain data crosses.\n *\n * Keys are subscribed on the first sync request, so a channel nobody\n * is watching costs nothing.\n */\nexport function provide<View extends object, Commands extends object>(\n token: ChannelToken<View, Commands>,\n source: ChannelSource<View, Commands>,\n port: ChannelPort\n): ProvidedChannel {\n return new ProvidedChannel(\n token as ChannelToken<object, CommandMap>,\n source as ChannelSource<object, CommandMap>,\n port\n );\n}\n\nexport class ProvidedChannel {\n private readonly subscriptions = new Subscription();\n /**\n * What the other side is known to hold, seeded from the token's\n * initial value — which the replica also starts from, so an app\n * whose first emission equals the initial sends nothing at all.\n */\n private readonly previous = new Map<string, unknown>();\n private readonly checked = new Set<string>();\n /**\n * Patches a running command has published and not yet sent. A command\n * that moves five view keys used to post five messages, each cloned\n * across the barrier and applied by the replica on its own; they now\n * leave together, as one message, the moment the command returns.\n *\n * Only a command's: a patch published anywhere else (a timer, a\n * recalculation the application thread schedules) is posted at once,\n * because nothing marks where that work ends but the end of the turn,\n * and waiting for that would leave a caller that has just run it\n * synchronously, a test above all, looking at a port with nothing on\n * it yet.\n */\n private pending: Patch[] = [];\n /** How many commands are running, nested ones counted. */\n private commanding = 0;\n\n private synced = false;\n\n constructor(\n private readonly token: ChannelToken<object, CommandMap>,\n private readonly source: ChannelSource<object, CommandMap>,\n private readonly port: ChannelPort\n ) {\n for (const key of viewKeys(token)) {\n this.previous.set(key, (token.initial as Record<string, unknown>)[key]);\n }\n this.port.onmessage = event => this.receive(event.data);\n }\n\n private receive(data: unknown): void {\n if (!isChannelClientMessage(data)) {\n return;\n }\n try {\n if (data.type === 'channel:sync') {\n this.sync();\n return;\n }\n this.commanding++;\n try {\n this.runCommand(data.command, data.payload, data.rest);\n } finally {\n // Before an error is reported below: the patches it published\n // happened first, and the wire says so.\n this.commanding--;\n if (this.commanding === 0) {\n this.sendPending();\n }\n }\n } catch (error) {\n // Reported rather than thrown: this runs on the thread that owns\n // the data, and a throw here would leave the view waiting for a\n // patch that never comes, with nothing said about why.\n this.post({\n type: 'channel:error',\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined\n });\n }\n }\n\n private runCommand(name: string, payload: unknown, rest?: readonly unknown[]): void {\n const handler = this.source.commands?.[name];\n if (handler === undefined) {\n const names = Object.keys(this.source.commands ?? {})\n .sort()\n .join(', ');\n throw new Error(\n `Channel '${this.token.name}' has no command '${name}'. ` +\n `Declared commands: ${names.length > 0 ? names : '(none)'}.`\n );\n }\n // Spread rather than passed as one payload: a command carries as\n // many arguments as it declares. A client that sent none beyond\n // the first sends no `rest`, so this is the single-argument call\n // it always was.\n (handler as (...args: unknown[]) => void)(payload, ...(rest ?? []));\n }\n\n private sync(): void {\n if (this.synced) {\n this.resend();\n return;\n }\n this.synced = true;\n\n for (const key of viewKeys(this.token)) {\n const observable = (this.source.view as Record<string, Observable<unknown> | undefined>)[key];\n if (observable === undefined) {\n this.post({\n type: 'channel:error',\n message: `Channel '${this.token.name}' declares view key '${key}' but nothing was provided for it.`\n });\n continue;\n }\n this.subscriptions.add(\n observable.subscribe({\n next: value => this.publish(key, value),\n error: (error: unknown) =>\n this.post({\n type: 'channel:error',\n message: `Channel '${this.token.name}' view key '${key}' errored: ${\n error instanceof Error ? error.message : String(error)\n }`,\n stack: error instanceof Error ? error.stack : undefined\n })\n })\n );\n }\n }\n\n private publish(key: string, value: unknown): void {\n if (!this.checked.has(key)) {\n this.checked.add(key);\n try {\n // Once per key, on the first value: a design mistake, caught at\n // startup rather than felt as slowness later. See `plainData`.\n requirePlainData(this.token.name, key, value);\n } catch (error) {\n // Reported, not rethrown. This runs inside an observer's `next`,\n // and RxJS routes a throw there to its unhandled-error hook\n // rather than back to the subscriber — so a throw would surface\n // as a stray async error on this thread and say nothing at all\n // on the thread that needs to know.\n this.post({\n type: 'channel:error',\n message: error instanceof Error ? error.message : String(error),\n stack: error instanceof Error ? error.stack : undefined\n });\n return;\n }\n }\n const patches = diffProjection(key, this.previous.get(key), value);\n this.previous.set(key, value);\n if (patches.length === 0) {\n return;\n }\n if (this.commanding === 0) {\n this.post({ type: 'channel:patch', patches });\n return;\n }\n for (const patch of patches) {\n this.pending.push(patch);\n }\n }\n\n /** Puts the patches a command has published so far on the wire now. */\n private sendPending(): void {\n if (this.pending.length === 0) {\n return;\n }\n const patches = this.pending;\n this.pending = [];\n const message: ChannelHostMessage = { type: 'channel:patch', patches };\n this.port.postMessage(message);\n }\n\n /** Re-sends every key in full, for a client that reattached. */\n private resend(): void {\n const patches: Patch[] = [];\n for (const [key, value] of this.previous) {\n patches.push({ op: 'set', projection: key, path: [], value });\n }\n if (patches.length > 0) {\n this.post({ type: 'channel:patch', patches });\n }\n }\n\n /**\n * Sends any other message, after the patches published before it: the\n * order on the wire is the order things happened in, batched or not.\n */\n private post(message: ChannelHostMessage): void {\n this.sendPending();\n this.port.postMessage(message);\n }\n\n dispose(): void {\n // What was published before the end is delivered, as it was when\n // every patch left at once.\n this.sendPending();\n this.subscriptions.unsubscribe();\n this.port.onmessage = null;\n }\n}\n","import type { Observable } from 'rxjs';\n\nimport { agentSurface } from '../agent/AgentSurface';\nimport { AGENT_PORT, serveAgentPort } from '../agent/remote';\nimport { servePorts, type PortHost } from '../worker/WorkerPorts';\nimport { provide, type ChannelSource, ProvidedChannel } from './provide';\nimport type { ChannelPort } from './ChannelProtocol';\nimport type { ChannelToken, Command, CommandMap } from './ChannelToken';\n\n/**\n * One channel a worker offers: its token and what feeds it.\n *\n * Types erased structurally, for the same reason `ChannelRegistration`\n * erases them — a list of channels has no single generic\n * instantiation, and making every caller cast to reach one is worse\n * than describing what is actually needed.\n */\nexport interface ServedChannel {\n token: { name: string; initial: object };\n source: {\n view: Record<string, Observable<unknown>>;\n commands?: Record<string, Command>;\n };\n}\n\n/**\n * One served channel, with its source checked against its token.\n *\n * `ServedChannel` is erased on purpose, so one list can hold channels\n * of every shape; the cost is that a view key the token declares and\n * the source forgets is found at startup, by the error `provide`\n * reports, rather than by the compiler. This is the typed seam: the\n * source must hold an Observable for every key of the token's view and\n * a handler for every command, and each handler takes the arguments\n * the token declares, so none of them needs an annotation.\n *\n * serveChannels([\n * serve(Catalog, { view: catalog, commands: { add: name => catalog.add(name) } })\n * ]);\n *\n * The view may be any object with the right observables on it, which\n * is often the domain object itself when its properties are named\n * after the keys. Only the declared keys are read from it.\n */\nexport function serve<View extends object, Commands extends object>(\n token: ChannelToken<View, Commands>,\n source: ChannelSource<View, Commands>\n): ServedChannel {\n return { token, source: source as unknown as ServedChannel['source'] };\n}\n\n/**\n * Publishes channels from an application worker.\n *\n * Call it synchronously at the top level of the worker module, before\n * any await, so no handshake is missed:\n *\n * const catalog = new CatalogViewModel(new CatalogDomain(new OpfsStore()));\n * serveChannels([\n * serve(Catalog, { view: { products: catalog.products$ }, commands: { … } })\n * ]);\n *\n * Everything above this call is the application's own — plain classes,\n * plain observables, no framework import. This function is the entire\n * seam between it and the view.\n *\n * Returns a function that stops serving and disposes what it provided.\n */\nexport function serveChannels(channels: readonly ServedChannel[], host?: PortHost): () => void {\n const byName = new Map<string, ServedChannel>();\n for (const served of channels) {\n byName.set(served.token.name, served);\n }\n const provided: ProvidedChannel[] = [];\n\n const stop = servePorts(\n (key, port) => {\n if (key === AGENT_PORT) {\n // An agent asking, through the page, what this worker serves.\n // Imported rather than loaded on demand: a worker built as an\n // IIFE, which is Vite's default, cannot split off a chunk, and\n // a dynamic import here failed every such build.\n serveAgentPort(port, confirm => agentSurface(channels, { confirm }));\n return true;\n }\n const served = byName.get(key);\n if (served === undefined) {\n // Declined rather than answered, so a worker serving more than\n // one kind of thing can pass the handshake along. `servePorts`\n // reports it if nothing takes it.\n return false;\n }\n provided.push(\n provide(\n served.token as ChannelToken<object, CommandMap>,\n served.source as unknown as ChannelSource<object, CommandMap>,\n port as unknown as ChannelPort\n )\n );\n return true;\n },\n () => [...byName.keys()],\n host\n );\n\n return () => {\n stop();\n for (const channel of provided) {\n channel.dispose();\n }\n provided.length = 0;\n };\n}\n"],"mappings":"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"}
@@ -205,50 +205,6 @@ function keyed(child, key) {
205
205
  };
206
206
  }
207
207
  //#endregion
208
- //#region src/metadata.ts
209
- const metadataStore = /* @__PURE__ */ new WeakMap();
210
- function getComponentMetadata(constructor) {
211
- let metadata = metadataStore.get(constructor);
212
- if (metadata === void 0) {
213
- metadata = {
214
- tag: constructor.name,
215
- inputs: /* @__PURE__ */ new Set(),
216
- states: /* @__PURE__ */ new Set(),
217
- injects: /* @__PURE__ */ new Map(),
218
- channels: /* @__PURE__ */ new Map()
219
- };
220
- metadataStore.set(constructor, metadata);
221
- }
222
- return metadata;
223
- }
224
- //#endregion
225
- //#region src/createComponent.ts
226
- /**
227
- * Creates a ComponentElement for use as a child of a UiElement.
228
- *
229
- * Column(
230
- * createComponent(Counter, { label: 'Count' }),
231
- * createComponent(TodoItem, { todo }, todo.id)
232
- * )
233
- *
234
- * The component may be a class extending Component or a function
235
- * `(props, ctx) => UiChild`. Props are typed from the component: a
236
- * class's `input()` fields, or a function's `Inputs<P>` parameter. A
237
- * misspelled prop, a value of the wrong type, and a missing required
238
- * prop are compile errors; props may be omitted only when none is
239
- * required.
240
- */
241
- function createComponent(component, ...args) {
242
- const [props, key] = args;
243
- return {
244
- kind: "component",
245
- tag: getComponentMetadata(component).tag,
246
- component,
247
- props: props ?? {},
248
- key
249
- };
250
- }
251
- //#endregion
252
- export { Each as a, show as i, getComponentMetadata as n, each as o, Show as r, createComponent as t };
208
+ export { each as i, show as n, Each as r, Show as t };
253
209
 
254
- //# sourceMappingURL=createComponent-3n1ZSql8.js.map
210
+ //# sourceMappingURL=show-D0MevHaV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"show-D0MevHaV.js","names":["keyed","EMPTY","EMPTY"],"sources":["../src/each.ts","../src/show.ts"],"sourcesContent":["import { Observable, defer, distinctUntilChanged, map, of } from 'rxjs';\n\nimport { isComponentLikeElement, isObservable, type UiChild, type UiElement } from 'gesso-core';\n\n/**\n * What gives a row its identity: the name of a field holding it, or a\n * function returning it. Omitting it keys by index, which is what the\n * builder falls back to and what `each` warns about.\n */\nexport type EachKey<T> = (keyof T & string) | ((item: T, index: number) => string | number);\n\nexport interface EachProps<T> {\n /** The list: a cell, any Observable of one, or a plain array. */\n readonly of: Observable<readonly T[]> | readonly T[];\n /** Identity per row. See `EachKey`. */\n readonly by?: EachKey<T>;\n /** What one row draws as. */\n readonly children: (item: T, index: number) => UiChild;\n}\n\n/**\n * A keyed list.\n *\n * <Each of={rows} by=\"id\">{row => <Row row={row} />}</Each>\n *\n * The `map`, the change check and the keying, which every screen in\n * both applications wrote by hand: forty blocks of\n * `map(items => items.map(item => <Row key={item.id} />))`, each of\n * which rebuilt every row's element on every emission of the list.\n *\n * A row's element is built once and kept while the row is in the list\n * and its value has not changed, so a list that re-emits equal data\n * builds nothing and reconciles nothing: the result is the same array,\n * and the change check downstream ends the emission there. A row whose\n * value changed is rebuilt alone; the key keeps its node and its\n * component instance, so only what changed is written.\n *\n * `key` is set from `by` on the element the function returns, so a row\n * component is written without one. An element that carries its own key\n * keeps it.\n *\n * `LazyColumn` is the same shape for a list long enough that only the\n * visible rows should exist. This is the short-list case, and the two\n * read alike on purpose.\n */\nexport function Each<T>(props: EachProps<T>): Observable<readonly UiChild[]> {\n return each(props.of, props.by, props.children);\n}\n\n/**\n * The function form of `Each`, for a list built outside a tag:\n *\n * const rows = each(tracks, 'id', track => <ItemRow item={track} />);\n */\nexport function each<T>(\n source: Observable<readonly T[]> | readonly T[],\n by: EachKey<T> | undefined,\n render: (item: T, index: number) => UiChild\n): Observable<readonly UiChild[]> {\n const keyOf = keyFunction(by);\n const dynamic = isObservable(source);\n const items = dynamic ? (source as Observable<readonly T[]>) : of(source as readonly T[]);\n if (by === undefined && dynamic) {\n warnIndexKeyed(render);\n }\n // Whether the row function took the index. One that did not is\n // unaffected by its row moving, so a reorder or a removal reuses\n // every element it already built; one that did has to be asked again\n // for a row that moved, since the index is part of what it drew.\n const positional = render.length >= 2;\n return defer(() => {\n const held = new Map<string | number, Row<T>>();\n let previous: readonly UiChild[] | null = null;\n let generation = 0;\n return items.pipe(\n map(list => {\n previous = reconcile(held, previous, ++generation, list, keyOf, render, positional);\n return previous;\n }),\n distinctUntilChanged()\n );\n });\n}\n\n/** One row's element, and what it was built from. */\ninterface Row<T> {\n item: T;\n index: number;\n child: UiChild;\n /** The pass that last saw this key; anything older has left the list. */\n generation: number;\n}\n\n/**\n * Builds the children for one emission, reusing every row it can.\n *\n * The result is the previous array itself when nothing about the list\n * changed, so the `distinctUntilChanged` above it ends the emission and\n * the builder is never entered. A new array is allocated at the first\n * row that differs and not before, which is what keeps an unchanged\n * emission free rather than merely cheap.\n */\nfunction reconcile<T>(\n held: Map<string | number, Row<T>>,\n previous: readonly UiChild[] | null,\n generation: number,\n list: readonly T[],\n keyOf: (item: T, index: number) => string | number,\n render: (item: T, index: number) => UiChild,\n positional: boolean\n): readonly UiChild[] {\n let next: UiChild[] | null = null;\n for (let index = 0; index < list.length; index++) {\n const item = list[index] as T;\n const key = keyOf(item, index);\n const row = held.get(key);\n if (row !== undefined && row.generation === generation) {\n throw new Error(`Duplicate key '${String(key)}' in a list: two rows claim the same identity.`);\n }\n let child: UiChild;\n if (row !== undefined && Object.is(row.item, item) && (!positional || row.index === index)) {\n child = row.child;\n row.index = index;\n row.generation = generation;\n } else {\n child = keyed(render(item, index), key);\n if (row === undefined) {\n held.set(key, { item, index, child, generation });\n } else {\n row.item = item;\n row.index = index;\n row.child = child;\n row.generation = generation;\n }\n }\n if (next === null && (previous === null || index >= previous.length || previous[index] !== child)) {\n next = previous === null ? [] : previous.slice(0, index);\n }\n next?.push(child);\n }\n for (const [key, row] of held) {\n if (row.generation !== generation) {\n held.delete(key);\n }\n }\n if (next === null && previous !== null && previous.length !== list.length) {\n // Nothing before the end changed and the list got shorter: the\n // rows that remain are the ones already in `previous`.\n next = previous.slice(0, list.length);\n }\n return next ?? previous ?? EMPTY;\n}\n\nconst EMPTY: readonly UiChild[] = [];\n\nfunction keyFunction<T>(by: EachKey<T> | undefined): (item: T, index: number) => string | number {\n if (by === undefined) {\n return (_item, index) => index;\n }\n if (typeof by === 'function') {\n return by;\n }\n return item => (item as Record<string, unknown>)[by] as string | number;\n}\n\n/**\n * Puts the row's key on the element the render function returned.\n *\n * An element that named its own key keeps it, since the author meant\n * something by it. An observable row cannot carry one at all: its\n * fragment anchor is identified by position, so a list of them\n * reorders wrongly, and it is worth saying so rather than leaving a\n * reorder to look like corruption.\n */\nfunction keyed(child: UiChild, key: string | number): UiChild {\n if (isComponentLikeElement(child)) {\n return child.key === undefined || child.key === null ? { ...child, key } : child;\n }\n if (isObservable(child)) {\n throw new Error(\n `A row of a list is an observable, which cannot carry the key '${String(key)}'. ` +\n `Return an element or a component from the row function and bind the observable inside it.`\n );\n }\n const element = child as UiElement;\n const existing = element.props.key;\n if (existing !== undefined && existing !== null) {\n return element;\n }\n return { ...element, props: { ...element.props, key } };\n}\n\n/** Said once: every unkeyed list has the same problem and the same fix. */\nlet warnedAboutIndexKeys = false;\n\nfunction warnIndexKeyed(render: (item: never, index: number) => UiChild): void {\n if (warnedAboutIndexKeys) {\n return;\n }\n warnedAboutIndexKeys = true;\n const what = render.name === '' ? 'a list' : `the list drawn by '${render.name}'`;\n console.warn(\n `${what} is keyed by index, because \\`each\\` was given no \\`by\\`. A row inserted or removed ` +\n `anywhere but the end then shifts every row after it onto a different node: state moves between rows, ` +\n `a text field keeps the wrong value, and an animation runs on the wrong element. ` +\n `Pass \\`by\\` naming what identifies a row: by=\"id\", or by={row => row.id}.`\n );\n}\n","import { Observable, defer, distinctUntilChanged, map, of } from 'rxjs';\n\nimport { isComponentLikeElement, isObservable, type UiChild, type UiElement } from 'gesso-core';\n\nexport interface ShowProps {\n /** The condition: a cell, any Observable, or a plain value. */\n readonly when: Observable<unknown> | unknown;\n /** What to draw while it is truthy. */\n readonly children: () => UiChild;\n /** What to draw while it is not. Nothing, by default. */\n readonly otherwise?: () => UiChild;\n}\n\n/**\n * One child, while a condition holds.\n *\n * <Show when={liked}>{() => <Icon path={ICONS.heart} />}</Show>\n *\n * `{cond && <x />}` already works when `cond` is a plain value, because\n * JSX drops a `false` child. A reactive `cond` had to become\n * `cond.pipe(map(on => (on ? [<x key=\"x\" />] : [])))`, which is the\n * fifty-six-block idiom in the two applications, and the discontinuity\n * between the two forms is the surprise this removes.\n *\n * The child is built once, on the first frame it is shown, and kept\n * while it is shown: a condition that emits `true` again draws nothing\n * and reconciles nothing. It carries a stable key, so the node it\n * built is the node it gets back when the condition returns, and it\n * adds no node of its own: what a `Show` puts under its parent is the\n * child, or nothing, and never a wrapper that layout would have to\n * account for.\n *\n * Anything inside it that changes is bound as usual. The function is\n * not re-run when the *data* changes, only when the condition does, so\n * a `Show` whose child shows a value binds that value rather than\n * reading it.\n */\nexport function Show(props: ShowProps): Observable<readonly UiChild[]> {\n return show(props.when, props.children, props.otherwise);\n}\n\n/**\n * The function form of `Show`:\n *\n * {show(liked, () => <Icon path={ICONS.heart} />)}\n */\nexport function show(\n when: Observable<unknown> | unknown,\n children: () => UiChild,\n otherwise?: () => UiChild\n): Observable<readonly UiChild[]> {\n const condition = isObservable(when) ? (when as Observable<unknown>) : of(when);\n return defer(() => {\n let shown: readonly UiChild[] | null = null;\n let hidden: readonly UiChild[] | null = null;\n return condition.pipe(\n map(value => Boolean(value)),\n distinctUntilChanged(),\n map(on => {\n if (on) {\n shown ??= [keyed(children(), 'when')];\n return shown;\n }\n hidden ??= otherwise === undefined ? EMPTY : [keyed(otherwise(), 'otherwise')];\n return hidden;\n })\n );\n });\n}\n\nconst EMPTY: readonly UiChild[] = [];\n\n/**\n * Gives the branch its stable key, so returning to it returns to the\n * node it built. An element that named its own key keeps it.\n */\nfunction keyed(child: UiChild, key: string): UiChild {\n if (isComponentLikeElement(child)) {\n return child.key === undefined || child.key === null ? { ...child, key } : child;\n }\n if (isObservable(child)) {\n return child;\n }\n const element = child as UiElement;\n const existing = element.props.key;\n if (existing !== undefined && existing !== null) {\n return element;\n }\n return { ...element, props: { ...element.props, key } };\n}\n"],"mappings":"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"}