@ai-ecoverse/slicc-spectrum 1.23.2 → 1.24.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.
package/dist/slicc-ui.js CHANGED
@@ -8549,6 +8549,7 @@ var ModelElement = class extends i2 {
8549
8549
  connectedCallback() {
8550
8550
  super.connectedCallback();
8551
8551
  this.#bind();
8552
+ this.requestUpdate();
8552
8553
  }
8553
8554
  disconnectedCallback() {
8554
8555
  super.disconnectedCallback();
@@ -19195,11 +19196,58 @@ var bridge = `(() => {
19195
19196
  });
19196
19197
  post({ type: 'slicc-ready' });
19197
19198
  })();`;
19198
- function frameDocument(source, color, name) {
19199
+ function literal(value) {
19200
+ try {
19201
+ return JSON.stringify(value ?? null).replace(/</g, "\\u003c");
19202
+ } catch {
19203
+ return "null";
19204
+ }
19205
+ }
19206
+ function store(state) {
19207
+ return `(() => {
19208
+ let state = ${literal(state)};
19209
+ const tag = Math.random().toString(36).slice(2);
19210
+ const pending = new Map();
19211
+ let next = 0;
19212
+ const call = (method, args) => new Promise((resolve, reject) => {
19213
+ const id = tag + ':' + ++next;
19214
+ pending.set(id, { resolve, reject });
19215
+ try {
19216
+ parent.postMessage({ type: 'slicc-call', id, method, args }, '*');
19217
+ } catch (error) {
19218
+ pending.delete(id);
19219
+ reject(error);
19220
+ }
19221
+ });
19222
+ addEventListener('message', (event) => {
19223
+ if (event.source !== parent) return;
19224
+ const message = event.data || {};
19225
+ const waiting = message.type === 'slicc-result' && pending.get(message.id);
19226
+ if (!waiting) return;
19227
+ pending.delete(message.id);
19228
+ if (typeof message.error === 'string') waiting.reject(new Error(message.error));
19229
+ else waiting.resolve(message.value);
19230
+ });
19231
+ Object.assign(window.slicc, {
19232
+ readFile: (path) => call('readFile', [path]),
19233
+ exists: (path) => call('exists', [path]),
19234
+ getState: () => state,
19235
+ setState(value) {
19236
+ try {
19237
+ state = JSON.parse(JSON.stringify(value === undefined ? null : value));
19238
+ } catch (error) {
19239
+ return Promise.reject(error);
19240
+ }
19241
+ return call('setState', [state]).then(() => undefined);
19242
+ },
19243
+ });
19244
+ })();`;
19245
+ }
19246
+ function frameDocument(source, color, name, state) {
19199
19247
  const scheme = `<style>${sprinkleTokens}${sprinkle_theme_default}</style>`;
19200
19248
  const light = `<script>document.documentElement.classList.toggle('theme-light', ${color === "light"});<\/script>`;
19201
19249
  const script = `<script data-name="${name.replace(/"/g, "&quot;")}">${bridge}<\/script>`;
19202
- const injection = light + scheme + script;
19250
+ const injection = light + scheme + script + (state ? `<script>${store(state.value)}<\/script>` : "");
19203
19251
  const head2 = source.match(/<head\b[^>]*>/i);
19204
19252
  if (!head2 || head2.index === void 0) return injection + source;
19205
19253
  const at = head2.index + head2[0].length;
@@ -19229,6 +19277,12 @@ async function frameFonts(files, base) {
19229
19277
  (font) => Boolean(font.data)
19230
19278
  );
19231
19279
  }
19280
+ var sprinkleMethods = /* @__PURE__ */ new Set([
19281
+ "readFile",
19282
+ "exists",
19283
+ "getState",
19284
+ "setState"
19285
+ ]);
19232
19286
  var grip = w`<svg class="grip" viewBox="0 0 8 14" width="8" height="14" aria-hidden="true">${[2, 7, 12].flatMap((y7) => [2, 6].map((x5) => w`<circle cx=${x5} cy=${y7} r="1.25"></circle>`))}</svg>`;
19233
19287
  var SliccSprinkle = class extends ThemedElement {
19234
19288
  static properties = {
@@ -19328,11 +19382,52 @@ var SliccSprinkle = class extends ThemedElement {
19328
19382
  source.postMessage({ type: "slicc-fonts", fonts }, "*");
19329
19383
  } else if (data.type === "slicc-size" && typeof data.height === "number") {
19330
19384
  this.height = data.height;
19385
+ } else if (data.type === "slicc-call") {
19386
+ await this.#call(source, data);
19387
+ }
19388
+ };
19389
+ async #call(source, data) {
19390
+ const port = this.model?.sprinkles;
19391
+ if (!port?.call || typeof data.method !== "string" || !sprinkleMethods.has(data.method)) return;
19392
+ const method = data.method;
19393
+ const args2 = Array.isArray(data.args) ? data.args : [];
19394
+ if (method === "setState") this.#held.value = args2[0] ?? null;
19395
+ try {
19396
+ const value = await port.call(this.sprinkle, method, args2);
19397
+ source.postMessage({ type: "slicc-result", id: data.id, value }, "*");
19398
+ } catch (error) {
19399
+ const message = error instanceof Error ? error.message : String(error);
19400
+ source.postMessage({ type: "slicc-result", id: data.id, error: message }, "*");
19331
19401
  }
19402
+ }
19403
+ #held = {
19404
+ port: null,
19405
+ id: "",
19406
+ ready: false,
19407
+ value: null
19332
19408
  };
19409
+ #hold(port, ask, id) {
19410
+ const held = { port, id, ready: false, value: null };
19411
+ this.#held = held;
19412
+ this.#frame = { key: "", doc: "" };
19413
+ const settle = (value) => {
19414
+ held.value = value ?? null;
19415
+ held.ready = true;
19416
+ if (this.#held === held) this.requestUpdate();
19417
+ };
19418
+ ask.call(port, id, "getState", []).then(settle, () => settle(null));
19419
+ }
19420
+ willUpdate(changed) {
19421
+ super.willUpdate(changed);
19422
+ const port = this.model?.sprinkles;
19423
+ if (port?.call && (this.#held.port !== port || this.#held.id !== this.sprinkle))
19424
+ this.#hold(port, port.call, this.sprinkle);
19425
+ }
19333
19426
  #dips = new Dips();
19427
+ #focusLater = false;
19334
19428
  focus() {
19335
- this.focusOn("iframe");
19429
+ if (this.model?.sprinkles.call && !this.#held.ready) this.#focusLater = true;
19430
+ else this.focusOn("iframe");
19336
19431
  }
19337
19432
  subscribe(model) {
19338
19433
  this.#dips = dipsOf(this) ?? this.#dips;
@@ -19357,16 +19452,22 @@ var SliccSprinkle = class extends ThemedElement {
19357
19452
  return this.model?.sprinkles.list().find((candidate) => candidate.id === this.sprinkle);
19358
19453
  }
19359
19454
  #frame = { key: "", doc: "" };
19360
- #document(data) {
19361
- const key2 = `${data.name}
19455
+ #document(data, state) {
19456
+ const key2 = `${!!state}
19457
+ ${data.name}
19362
19458
  ${data.html}`;
19363
19459
  if (this.#frame.key !== key2)
19364
- this.#frame = { key: key2, doc: frameDocument(data.html, this.color, data.name) };
19460
+ this.#frame = { key: key2, doc: frameDocument(data.html, this.color, data.name, state) };
19365
19461
  return this.#frame.doc;
19366
19462
  }
19367
19463
  updated(changed) {
19368
19464
  super.updated(changed);
19369
- this.renderRoot.querySelector("iframe")?.contentWindow?.postMessage({ type: "slicc-theme", color: this.color }, "*");
19465
+ const frame = this.renderRoot.querySelector("iframe");
19466
+ frame?.contentWindow?.postMessage({ type: "slicc-theme", color: this.color }, "*");
19467
+ if (frame && this.#focusLater) {
19468
+ this.#focusLater = false;
19469
+ frame.focus();
19470
+ }
19370
19471
  }
19371
19472
  render() {
19372
19473
  const data = this.#data;
@@ -19378,8 +19479,11 @@ ${data.html}`;
19378
19479
  <sp-action-button size="s" quiet @click=${() => this.#send("show-surface", `sprinkle:${data.id}`)}>Show</sp-action-button>
19379
19480
  </div>`;
19380
19481
  }
19482
+ const bridged = !!this.model?.sprinkles.call;
19483
+ if (bridged && !this.#held.ready) return b``;
19484
+ const state = bridged ? this.#held : void 0;
19381
19485
  const style = `color-scheme:${this.color};${this.inline ? `height:${this.height}px;` : ""}`;
19382
- const frame = b`<iframe title=${data.title} sandbox="allow-scripts" style=${style} .srcdoc=${this.#document(data)}></iframe>`;
19486
+ const frame = b`<iframe title=${data.title} sandbox="allow-scripts" style=${style} .srcdoc=${this.#document(data, state)}></iframe>`;
19383
19487
  if (!this.inline) return frame;
19384
19488
  return b`<div class="handle" draggable="true" title="Drag into the dock or a rail to open as a panel" @dragstart=${this.#drag}>
19385
19489
  ${grip}
@@ -31320,20 +31424,20 @@ function canParticipateWithNode(capture, node) {
31320
31424
  throw new Error("Unexpected path");
31321
31425
  }
31322
31426
  function cloneCapturingGroup(obj, originMap, up, up2) {
31323
- const store = Array.isArray(obj) ? [] : {};
31427
+ const store2 = Array.isArray(obj) ? [] : {};
31324
31428
  for (const [key2, value] of Object.entries(obj)) {
31325
31429
  if (key2 === "parent") {
31326
- store.parent = Array.isArray(up) ? up2 : up;
31430
+ store2.parent = Array.isArray(up) ? up2 : up;
31327
31431
  } else if (value && typeof value === "object") {
31328
- store[key2] = cloneCapturingGroup(value, originMap, store, up);
31432
+ store2[key2] = cloneCapturingGroup(value, originMap, store2, up);
31329
31433
  } else {
31330
31434
  if (key2 === "type" && value === "CapturingGroup") {
31331
- originMap.set(store, originMap.get(obj) ?? obj);
31435
+ originMap.set(store2, originMap.get(obj) ?? obj);
31332
31436
  }
31333
- store[key2] = value;
31437
+ store2[key2] = value;
31334
31438
  }
31335
31439
  }
31336
- return store;
31440
+ return store2;
31337
31441
  }
31338
31442
  function createRecursion(ref) {
31339
31443
  const node = O2(ref);
@@ -64848,8 +64952,8 @@ function buildSoaNodeStore(snapshot) {
64848
64952
  childIdsFlat
64849
64953
  };
64850
64954
  }
64851
- function sweepOpenVisibleCountsSoa(store) {
64852
- const { nodeCount, rootId, flattenEmptyDirectories, depthAndFlags, subtreeNodeCount, visibleSubtreeCount, childStart, childCount, childIdsFlat } = store;
64955
+ function sweepOpenVisibleCountsSoa(store2) {
64956
+ const { nodeCount, rootId, flattenEmptyDirectories, depthAndFlags, subtreeNodeCount, visibleSubtreeCount, childStart, childCount, childIdsFlat } = store2;
64853
64957
  for (let id = nodeCount - 1; id >= 1; id -= 1) {
64854
64958
  if ((depthAndFlags[id] & KIND_MASK) === 0) continue;
64855
64959
  const base = childStart[id];