@superblocksteam/library 2.0.165-next.0 → 2.0.166-next.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/lib/index.js CHANGED
@@ -1,11 +1,12 @@
1
1
  import { n as consoleLogAttributes, t as LibraryEarlyConsoleBuffer } from "../early-console-buffer-DMR1SCsN.js";
2
- import { A as Section, C as iframeMessageHandler, D as createManagedPropsList, E as isEditMode, O as Prop, S as getParentOrigin, T as sendMessageImmediately, _ as generateId, a as tracker, b as editorBridge, c as resolveById, d as useSuperblocksContext, f as useSuperblocksDataTags, g as embedStore, h as useSuperblocksUser, i as getContextFromTraceHeaders, k as PropsCategory, l as SuperblocksContextProvider, m as useSuperblocksProfiles, n as root_store_default, o as addNewPromise, p as useSuperblocksGroups, r as createIframeSpan, s as rejectById, t as ORCHESTRATOR_EXECUTE_RESPONSE_SIZE_LIMIT_FLAG, u as getAppMode, v as sendNotification, w as isEmbeddedBySuperblocksFirstParty, x as getEditStore, y as colors } from "../root-store-CtsStoaR.js";
2
+ import { C as iframeMessageHandler, E as isEditMode, S as getParentOrigin, T as sendMessageImmediately, _ as generateId, a as tracker, b as editorBridge, c as resolveById, d as useSuperblocksContext, f as useSuperblocksDataTags, g as embedStore, h as useSuperblocksUser, i as getContextFromTraceHeaders, l as SuperblocksContextProvider, m as useSuperblocksProfiles, n as root_store_default, o as addNewPromise, p as useSuperblocksGroups, r as createIframeSpan, s as rejectById, t as ORCHESTRATOR_EXECUTE_RESPONSE_SIZE_LIMIT_FLAG, u as getAppMode, v as sendNotification, w as isEmbeddedBySuperblocksFirstParty, x as getEditStore, y as colors } from "../root-store-BYYXPQRA.js";
3
3
  import { n as initTracerProviderWithOrigin } from "../utils-DXaAwgS_.js";
4
- import { r as updateSdkApiSourceCode, t as discoverAndRegisterSdkApis } from "../sdk-api-discovery-DdbqEI70.js";
5
- import { a as FixWithClarkButton, c as ErrorContent, d as ErrorMessage$1, f as ErrorStack, g as StyledClarkIcon, h as SecondaryButton, i as getWidgetRectAnchorName, l as ErrorDetails, m as ErrorTitle, n as useJSXContext, o as ActionsContainer, p as ErrorSummary, r as getWidgetAnchorName, s as ErrorContainer, u as ErrorIconContainer } from "../jsx-wrapper-BGGZod5X.js";
4
+ import { r as updateSdkApiSourceCode, t as discoverAndRegisterSdkApis } from "../sdk-api-discovery-DvvsdT1z.js";
5
+ import { a as FixWithClarkButton, c as ErrorContent, d as ErrorMessage$1, f as ErrorStack, g as StyledClarkIcon, h as SecondaryButton, i as getWidgetRectAnchorName, l as ErrorDetails, m as ErrorTitle, n as useJSXContext, o as ActionsContainer, p as ErrorSummary, r as getWidgetAnchorName, s as ErrorContainer, u as ErrorIconContainer } from "../jsx-wrapper-1kyr6-x3.js";
6
+ import { PropsCategory } from "@superblocksteam/library-shared/props";
6
7
  import { action, computed, makeAutoObservable, makeObservable, observable, reaction, when } from "mobx";
7
8
  import { UNSAFE_DataRouterContext, generatePath, useLocation, useNavigate, useParams, useRouteError } from "react-router";
8
- import { NATIVE_COMPONENT_TYPES, NO_SELECT_ATTRIBUTE, Property, SELECTOR_ID_ATTRIBUTE, SOURCE_ID_ATTRIBUTE, URL_PARAMS, generateSourceId, getBindingIdentifier, getDevServerAuthorizationRejectionReason, hasCompactJwtShape } from "@superblocksteam/library-shared";
9
+ import { NATIVE_COMPONENT_TYPES, NO_SELECT_ATTRIBUTE, Property, SELECTOR_ID_ATTRIBUTE, SOURCE_ID_ATTRIBUTE, URL_PARAMS, getBindingIdentifier, getDevServerAuthorizationRejectionReason, hasCompactJwtShape } from "@superblocksteam/library-shared";
9
10
  import * as React$1 from "react";
10
11
  import React, { Suspense, createElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
11
12
  import { isEqual } from "lodash";
@@ -239,6 +240,324 @@ function installDynamicImportErrorReporter(options = {}) {
239
240
  };
240
241
  }
241
242
  //#endregion
243
+ //#region src/lib/user-facing/properties-panel/props-builder.ts
244
+ var Section = class Section {
245
+ props = {};
246
+ propertiesPanelConfig = {};
247
+ constructor(category) {
248
+ this.category = category;
249
+ }
250
+ static category(category) {
251
+ return new Section(category);
252
+ }
253
+ children(props) {
254
+ if (props instanceof CompositeProp || props instanceof RecordProp) this.props = {
255
+ ...this.props,
256
+ ...props.getProps()
257
+ };
258
+ else if (props instanceof UnionProp) this.props = {
259
+ ...this.props,
260
+ ...props.getProps()
261
+ };
262
+ else this.props = {
263
+ ...this.props,
264
+ ...props
265
+ };
266
+ return this;
267
+ }
268
+ add = this.children;
269
+ /** @deprecated Panel configuration is accepted for source compatibility and ignored. */
270
+ propertiesPanel(_config) {
271
+ return this;
272
+ }
273
+ get name() {
274
+ switch (this.category) {
275
+ case PropsCategory.Content: return "Content";
276
+ case PropsCategory.Routing: return "Routing";
277
+ case PropsCategory.Interaction: return "Interaction";
278
+ case PropsCategory.Layout: return "Layout";
279
+ case PropsCategory.Appearance: return "Appearance";
280
+ case PropsCategory.Permissions: return "Permissions";
281
+ case PropsCategory.EventHandlers: return "Actions";
282
+ case PropsCategory.Styles: return "Styles";
283
+ default: return "Uncategorized";
284
+ }
285
+ }
286
+ };
287
+ var Prop = class Prop {
288
+ prop;
289
+ constructor(typeString) {
290
+ this.prop = {
291
+ path: "",
292
+ dataType: typeString
293
+ };
294
+ }
295
+ static unset() {
296
+ return new Prop("any");
297
+ }
298
+ static string() {
299
+ return new Prop("string");
300
+ }
301
+ static number() {
302
+ return new Prop("number");
303
+ }
304
+ static boolean() {
305
+ return new Prop("boolean");
306
+ }
307
+ static array() {
308
+ return new Prop("array");
309
+ }
310
+ static any() {
311
+ return new Prop("any");
312
+ }
313
+ static jsx() {
314
+ return new Prop("jsx");
315
+ }
316
+ static literal(value) {
317
+ switch (typeof value) {
318
+ case "string": return Prop.string().default(value);
319
+ case "number": return Prop.number().default(value);
320
+ case "boolean": return Prop.boolean().default(value);
321
+ default: throw new Error(`Invalid literal value: ${value}`);
322
+ }
323
+ }
324
+ static eventHandler() {
325
+ return new Prop("eventHandler");
326
+ }
327
+ static function(implementation) {
328
+ return new FunctionProp(implementation);
329
+ }
330
+ /**
331
+ * Creates a composite property, which is a property that contains nested properties. For example,
332
+ * the following composite property:
333
+ *
334
+ * ```ts
335
+ * const prop = Prop.composite({
336
+ * name: Prop.string(),
337
+ * age: Prop.number(),
338
+ * });
339
+ * ```
340
+ *
341
+ * is equivalent to the following type:
342
+ *
343
+ * ```ts
344
+ * type Prop = {
345
+ * name: string;
346
+ * age: number;
347
+ * };
348
+ * ```
349
+ */
350
+ static composite(props) {
351
+ return new CompositeProp(props);
352
+ }
353
+ /**
354
+ * Creates a record property, which is a record that maps string keys to the nestedproperties. For example,
355
+ * the following record property:
356
+ *
357
+ * ```ts
358
+ * const prop = Prop.record({
359
+ * name: Prop.string(),
360
+ * age: Prop.number(),
361
+ * });
362
+ * ```
363
+ *
364
+ * is equivalent to the following type:
365
+ *
366
+ * ```ts
367
+ * type Prop = Record<string, {
368
+ * name: string;
369
+ * age: number;
370
+ * }>;
371
+ * ```
372
+ */
373
+ static record(props) {
374
+ return new RecordProp(props);
375
+ }
376
+ static union(props) {
377
+ return new UnionProp(props.shared, props.variants);
378
+ }
379
+ default(de) {
380
+ this.prop.default = de;
381
+ return this;
382
+ }
383
+ contextual(computedArgs) {
384
+ this.prop.contextual = true;
385
+ this.prop.computedArgs = computedArgs;
386
+ return this;
387
+ }
388
+ setName(name) {
389
+ this.prop.path = name;
390
+ return this;
391
+ }
392
+ /** @deprecated Panel configuration is accepted for source compatibility and ignored. */
393
+ propertiesPanel(_schema) {
394
+ return this;
395
+ }
396
+ /** @deprecated Panel metadata is accepted for source compatibility and ignored. */
397
+ setDisplayProperty(_property, _value) {
398
+ return this;
399
+ }
400
+ /** @deprecated Panel relations are accepted for source compatibility and ignored. */
401
+ dependsOn(_relations) {
402
+ return this;
403
+ }
404
+ getRelations() {
405
+ return [];
406
+ }
407
+ hasPropertiesPanelDisplay() {
408
+ return false;
409
+ }
410
+ toDefinition(_props) {}
411
+ docs(docs) {
412
+ this.prop.docs = docs;
413
+ return this;
414
+ }
415
+ build() {
416
+ return this.prop;
417
+ }
418
+ get type() {
419
+ return this.prop.dataType;
420
+ }
421
+ get path() {
422
+ return this.prop.path;
423
+ }
424
+ };
425
+ /**
426
+ * See {@link Prop.composite}
427
+ */
428
+ var CompositeProp = class extends Prop {
429
+ typeString = "composite";
430
+ nestedProps;
431
+ constructor(props) {
432
+ super("composite");
433
+ this.nestedProps = props;
434
+ }
435
+ getProps() {
436
+ return this.nestedProps;
437
+ }
438
+ propertiesPanelChildrenDisplayMode() {}
439
+ };
440
+ /**
441
+ * See {@link Prop.record}
442
+ */
443
+ var RecordProp = class extends Prop {
444
+ typeString = "recordOf";
445
+ nestedProps;
446
+ constructor(props) {
447
+ super("recordOf");
448
+ this.nestedProps = props;
449
+ }
450
+ getProps() {
451
+ return this.nestedProps;
452
+ }
453
+ };
454
+ var FunctionProp = class extends Prop {
455
+ typeString = "function";
456
+ constructor(implementation) {
457
+ super("function");
458
+ this.default(implementation);
459
+ }
460
+ /** @deprecated Action panel metadata is accepted for source compatibility and ignored. */
461
+ actionPanel(_panel) {
462
+ return this;
463
+ }
464
+ getActionPanel() {}
465
+ };
466
+ var UnionProp = class extends Prop {
467
+ typeString = "union";
468
+ shared;
469
+ variants;
470
+ constructor(shared, variants) {
471
+ super("any");
472
+ this.shared = shared;
473
+ this.variants = variants;
474
+ }
475
+ getProps() {
476
+ const props = { ...this.shared };
477
+ for (const variant of this.variants) for (const [key, prop] of Object.entries(variant)) if (!Object.hasOwn(props, key)) props[key] = prop;
478
+ return props;
479
+ }
480
+ };
481
+ function buildCompositeDefault(prop, name, parentDefault) {
482
+ const defaultThroughParent = parentDefault?.[name];
483
+ const selfDefault = prop.build().default;
484
+ let propDefault = defaultThroughParent ?? selfDefault;
485
+ if (!propDefault && typeof parentDefault === "function") propDefault = function getNestedDefault(s) {
486
+ return parentDefault.call(this, s)?.[name];
487
+ };
488
+ return propDefault;
489
+ }
490
+ function buildPropLeafDefault(prop, name, parentDefault) {
491
+ const defaultThroughParent = parentDefault?.[name];
492
+ let propDefault = prop.build().default ?? defaultThroughParent;
493
+ if (!propDefault && typeof parentDefault === "function") propDefault = function getNestedDefault(s) {
494
+ return parentDefault.call(this, s)?.[name];
495
+ };
496
+ return propDefault;
497
+ }
498
+ /**
499
+ * Core traversal function that walks through all properties in sections
500
+ * and calls the provided callback for each leaf property.
501
+ */
502
+ function traverseProps(sections, onProp, parentPath = "") {
503
+ const processProps = ({ props, parentPath, parentDefault }) => {
504
+ for (const [name, prop] of Object.entries(props)) {
505
+ if (!prop) continue;
506
+ const fullPath = parentPath ? `${parentPath}.${name}` : name;
507
+ if (prop instanceof CompositeProp) {
508
+ const compositeDefault = buildCompositeDefault(prop, name, parentDefault);
509
+ processProps({
510
+ props: prop.nestedProps,
511
+ parentPath: fullPath,
512
+ parentDefault: compositeDefault
513
+ });
514
+ } else if (prop instanceof RecordProp) {
515
+ const recordPath = `${fullPath}.*`;
516
+ processProps({
517
+ props: prop.nestedProps,
518
+ parentPath: recordPath,
519
+ parentDefault: prop.build().default
520
+ });
521
+ } else if (prop instanceof Section) processProps({
522
+ props: prop.props,
523
+ parentPath
524
+ });
525
+ else if (prop instanceof UnionProp) {
526
+ const sharedKeys = Object.keys(prop.shared);
527
+ processProps({
528
+ props: prop.shared,
529
+ parentPath: fullPath
530
+ });
531
+ for (const variant of prop.variants) processProps({
532
+ props: Object.fromEntries(Object.entries(variant).filter(([key]) => !sharedKeys.includes(key))),
533
+ parentPath: fullPath
534
+ });
535
+ } else if (prop instanceof Prop) onProp(prop, fullPath, name, parentDefault);
536
+ else console.warn("Invalid prop type", {
537
+ name,
538
+ prop
539
+ });
540
+ }
541
+ };
542
+ for (const section of Object.values(sections)) processProps({
543
+ props: section.props,
544
+ parentPath,
545
+ parentDefault: void 0
546
+ });
547
+ }
548
+ function createManagedPropsList(sections, parentPath = "") {
549
+ const managedPropsList = [];
550
+ traverseProps(sections, (prop, fullPath, name, parentDefault) => {
551
+ let configuredProp = prop.setName(fullPath);
552
+ const propDefault = buildPropLeafDefault(prop, name, parentDefault);
553
+ if (propDefault !== void 0) configuredProp = configuredProp.default(propDefault);
554
+ const builtProp = configuredProp.build();
555
+ if (builtProp.dataType === "internal") return;
556
+ managedPropsList.push({ ...builtProp });
557
+ }, parentPath);
558
+ return managedPropsList;
559
+ }
560
+ //#endregion
242
561
  //#region src/lib/internal-details/sb-wrapper.tsx
243
562
  /**
244
563
  * Register a component to be used with the framework.
@@ -261,15 +580,7 @@ const registerComponentInternal = (Component, propertiesDefinition) => {
261
580
  root_store_default.componentRegistry.addEditorConfig(type, defaultEditorConfig);
262
581
  }
263
582
  const chainableComponent = {
264
- addEditorTemplate: (templateConfig) => {
265
- const catalog = templateConfig.catalog ?? {
266
- displayName: type,
267
- category: "MISC"
268
- };
269
- root_store_default.componentRegistry.addEditorTemplate(type, {
270
- ...templateConfig,
271
- catalog
272
- });
583
+ addEditorTemplate: (_templateConfig) => {
273
584
  return chainableComponent;
274
585
  },
275
586
  editorConfig: (config) => {
@@ -1779,6 +2090,46 @@ function BuildErrorModal({ isOpen, error, onClose }) {
1779
2090
  });
1780
2091
  }
1781
2092
  //#endregion
2093
+ //#region src/edit-mode/dev-server-token-delivery.ts
2094
+ /**
2095
+ * Socket identity and pod TokenManager delivery are different stores.
2096
+ * `updateAuthorization` only reports whether the iframe socket changed;
2097
+ * this tracker decides whether `/_sb_update_token` still needs to run.
2098
+ */
2099
+ function createDevServerTokenDelivery() {
2100
+ let deliveredAuthorization;
2101
+ let inFlightAuthorization;
2102
+ return {
2103
+ decide(authorizationChanged, installedAuthorization) {
2104
+ if (!installedAuthorization) return authorizationChanged ? { action: "abort" } : { action: "skip" };
2105
+ if (!authorizationChanged) {
2106
+ if (installedAuthorization === inFlightAuthorization || installedAuthorization === deliveredAuthorization) return { action: "skip" };
2107
+ return {
2108
+ action: "post",
2109
+ abortInFlight: false
2110
+ };
2111
+ }
2112
+ return {
2113
+ action: "post",
2114
+ abortInFlight: true
2115
+ };
2116
+ },
2117
+ markAborted() {
2118
+ inFlightAuthorization = void 0;
2119
+ },
2120
+ markDelivered(authorization) {
2121
+ deliveredAuthorization = authorization;
2122
+ if (inFlightAuthorization === authorization) inFlightAuthorization = void 0;
2123
+ },
2124
+ markFailed(authorization) {
2125
+ if (inFlightAuthorization === authorization) inFlightAuthorization = void 0;
2126
+ },
2127
+ markStarted(authorization) {
2128
+ inFlightAuthorization = authorization;
2129
+ }
2130
+ };
2131
+ }
2132
+ //#endregion
1782
2133
  //#region src/edit-mode/features/ai-store.ts
1783
2134
  var AiManager = class {
1784
2135
  _isTaggingEnabled = true;
@@ -1954,7 +2305,7 @@ var AsyncSocket = class {
1954
2305
  //#region src/edit-mode/authorization-metrics.ts
1955
2306
  let devServerAuthorizationEvents;
1956
2307
  function recordDevServerAuthorizationEvent(event, attributes) {
1957
- if (!devServerAuthorizationEvents) devServerAuthorizationEvents = metrics.getMeter("superblocks-library").createCounter("dev_server_authorization_events_total", { description: "Count of dev-server authorization compatibility, rejection, and retry-exhaustion events" });
2308
+ if (!devServerAuthorizationEvents) devServerAuthorizationEvents = metrics.getMeter("superblocks-library").createCounter("dev_server_authorization_events_total", { description: "Count of dev-server authorization compatibility, rejection, refresh, and retry-exhaustion events" });
1958
2309
  devServerAuthorizationEvents.add(1, {
1959
2310
  event,
1960
2311
  ...attributes
@@ -2128,23 +2479,37 @@ var OperationAPI = class {
2128
2479
  /**
2129
2480
  * Updates the authorization token for the socket connection.
2130
2481
  * This is called when the token is refreshed in the parent window.
2482
+ * Returns true only when the installed authorization changes.
2131
2483
  */
2132
2484
  updateAuthorization(newAuthorization, { allowLegacyAuthorization } = {}) {
2485
+ const revokesInstalledLegacyAuthorization = allowLegacyAuthorization === false && this.currentAuthorizationAllowsLegacy;
2486
+ if (newAuthorization === this.currentAuthorization && !revokesInstalledLegacyAuthorization) return false;
2133
2487
  const rejectionReason = newAuthorization ? getDevServerAuthorizationRejectionReason(newAuthorization, this.applicationId) : void 0;
2134
2488
  const acceptsLegacyAuthorization = newAuthorization !== void 0 && rejectionReason !== void 0 && (allowLegacyAuthorization ?? this.currentAuthorizationAllowsLegacy) && isUnexpiredLegacyAuthorization(newAuthorization) && (!this.currentAuthorization || !isDevServerAuthorization(this.currentAuthorization, this.applicationId));
2135
2489
  if (allowLegacyAuthorization === false) this.currentAuthorizationAllowsLegacy = false;
2136
2490
  if (newAuthorization === void 0 && allowLegacyAuthorization === false && this.currentAuthorization && isDevServerAuthorization(this.currentAuthorization, this.applicationId)) return false;
2137
2491
  if (newAuthorization && rejectionReason !== void 0 && !acceptsLegacyAuthorization) {
2492
+ let authorizationChanged = false;
2138
2493
  recordDevServerAuthorizationEvent("authorization_rejected", { reason: rejectionReason });
2139
2494
  if (this.currentAuthorization && !this.currentAuthorizationAllowsLegacy && !isDevServerAuthorization(this.currentAuthorization, this.applicationId)) {
2140
2495
  this.currentAuthorization = void 0;
2141
2496
  this.currentAuthorizationAllowsLegacy = false;
2142
2497
  this.isocket?.setAuthorization(void 0);
2498
+ authorizationChanged = true;
2143
2499
  }
2144
2500
  console.warn("[internal] [OperationAPI] Ignoring invalid dev server authorization", consoleLogAttributes({
2145
2501
  "application.id": this.applicationId,
2146
2502
  "error.type": rejectionReason
2147
2503
  }));
2504
+ return authorizationChanged;
2505
+ }
2506
+ if (newAuthorization !== void 0 && rejectionReason === void 0 && this.applicationId !== void 0 && !shouldUseAuthorizationCandidate(this.currentAuthorization, newAuthorization, this.applicationId)) {
2507
+ recordDevServerAuthorizationEvent("authorization_downgrade_ignored");
2508
+ console.warn("[internal] [OperationAPI] Ignoring older dev server authorization", consoleLogAttributes({
2509
+ "application.id": this.applicationId,
2510
+ "authorization.candidate_expiration_ms": getAuthorizationExpirationMs(newAuthorization),
2511
+ "authorization.installed_expiration_ms": getAuthorizationExpirationMs(this.currentAuthorization)
2512
+ }));
2148
2513
  return false;
2149
2514
  }
2150
2515
  if (acceptsLegacyAuthorization) recordDevServerAuthorizationEvent("legacy_authorization_accepted");
@@ -2157,6 +2522,9 @@ var OperationAPI = class {
2157
2522
  } else console.warn("[internal] [OperationAPI] Cannot update authorization: socket not yet initialized");
2158
2523
  return true;
2159
2524
  }
2525
+ getCurrentAuthorization() {
2526
+ return this.currentAuthorization;
2527
+ }
2160
2528
  handleAuthorizationFailure(error, { applicationId, connectionStartTime, connectionTarget, connectionType }) {
2161
2529
  if (this.authorizationRefreshApplicationId !== applicationId) {
2162
2530
  this.resetAuthorizationRefresh();
@@ -2453,161 +2821,19 @@ async function connectSocket(serverUrl, { peerId, userId, applicationId, getAuth
2453
2821
  //#endregion
2454
2822
  //#region src/edit-mode/features/operation-store.ts
2455
2823
  var OperationManager = class {
2456
- pendingTransactions = [];
2457
- waitingForBatch = false;
2458
- batchOperations = [];
2459
- batchOperationTransactionId;
2460
- visibleSourceIds = [];
2461
- constructor() {
2462
- makeAutoObservable(this);
2463
- }
2464
- get allPendingTransactions() {
2465
- return this.pendingTransactions;
2466
- }
2467
- get pendingDeleteOperations() {
2468
- return this.pendingTransactions.filter((t) => t.type === "editor:deleteComponents");
2469
- }
2470
- get hasPendingOperations() {
2471
- return this.pendingTransactions.length > 0;
2472
- }
2473
- get allNames() {
2474
- return [];
2475
- }
2476
- @action executeOrAddToBatch(operation, addTransaction = true) {
2477
- const transactionId = this.batchOperationTransactionId ?? generateId();
2478
- const payload = this.waitingForBatch ? operation.payload : {
2479
- ...operation.payload,
2824
+ deleteComponents(sourceIds) {
2825
+ editorBridge.editOpRequest("editor:deleteComponents", {
2826
+ elements: sourceIds.map((sourceId) => ({ source: { id: sourceId } })),
2480
2827
  transaction: {
2481
- id: transactionId,
2828
+ id: generateId(),
2482
2829
  origin: "LIBRARY"
2483
2830
  }
2484
- };
2485
- const opWithId = {
2486
- ...operation,
2487
- id: transactionId,
2488
- payload
2489
- };
2490
- if (addTransaction) this.addPendingTransaction(opWithId);
2491
- if (this.waitingForBatch) this.batchOperations.push(opWithId);
2492
- else switch (operation.type) {
2493
- case "editor:moveComponent": return editorBridge.editOpRequest("editor:moveComponent", payload);
2494
- case "editor:createComponent": return editorBridge.editOpRequest("editor:createComponent", payload);
2495
- case "editor:deleteComponents": return editorBridge.editOpRequest("editor:deleteComponents", payload);
2496
- }
2497
- }
2498
- @action addPendingTransaction(transaction) {
2499
- this.pendingTransactions.push(transaction);
2500
- }
2501
- @action clearPendingTransactions(transactionIds) {
2502
- const toClear = new Set(transactionIds);
2503
- const { cleared, remaining } = this.pendingTransactions.reduce((acc, transaction) => {
2504
- if (toClear.has(transaction.id)) acc.cleared.push(transaction);
2505
- else acc.remaining.push(transaction);
2506
- return acc;
2507
- }, {
2508
- cleared: [],
2509
- remaining: []
2510
- });
2511
- this.pendingTransactions = remaining;
2512
- cleared.forEach((transaction) => {
2513
- if (transaction.callback) transaction.callback();
2514
2831
  });
2515
2832
  }
2516
- @action batchUpdate(performOperations) {
2517
- this.waitingForBatch = true;
2518
- this.batchOperationTransactionId = generateId();
2519
- performOperations();
2520
- editorBridge.editOpRequest("editor:batchUpdate", {
2521
- updates: this.batchOperations.map((op) => ({
2522
- type: op.type,
2523
- payload: op.payload
2524
- })),
2525
- transaction: {
2526
- origin: "LIBRARY",
2527
- id: this.batchOperationTransactionId
2528
- }
2529
- });
2530
- this.waitingForBatch = false;
2531
- this.batchOperations = [];
2532
- this.batchOperationTransactionId = void 0;
2533
- }
2534
- @action createComponent(payload) {
2535
- this.executeOrAddToBatch({
2536
- type: "editor:createComponent",
2537
- payload
2538
- });
2539
- }
2540
- @action dropComponent(action) {
2541
- const { from, to, propsToChange } = action;
2542
- const payload = {
2543
- from,
2544
- to,
2545
- changedProps: propsToChange ?? {}
2546
- };
2547
- this.executeOrAddToBatch({
2548
- type: "editor:moveComponent",
2549
- payload
2550
- });
2551
- }
2552
- @action deleteComponents(sourceIds) {
2553
- const payload = { elements: sourceIds.map((sourceId) => ({ source: { id: sourceId } })) };
2554
- this.executeOrAddToBatch({
2555
- type: "editor:deleteComponents",
2556
- payload
2557
- }, false);
2558
- }
2559
- acknowledgeEditOperation(operation) {
2560
- if (!("transaction" in operation.payload) || !operation.payload.transaction?.id) {
2561
- console.error("No transaction id in edit operation", operation);
2562
- return;
2563
- }
2564
- const addOperation = (operation, batchTransactionId) => {
2565
- switch (operation.type) {
2566
- case "editor:createComponent": {
2567
- const { type, payload } = operation;
2568
- this.addPendingTransaction({
2569
- type,
2570
- id: batchTransactionId ?? payload.transaction.id,
2571
- payload
2572
- });
2573
- break;
2574
- }
2575
- case "editor:deleteComponents": {
2576
- const { type, payload } = operation;
2577
- this.addPendingTransaction({
2578
- type,
2579
- id: batchTransactionId ?? payload.transaction.id,
2580
- payload
2581
- });
2582
- break;
2583
- }
2584
- case "editor:moveComponent": {
2585
- const { type, payload } = operation;
2586
- this.addPendingTransaction({
2587
- type,
2588
- id: batchTransactionId ?? payload.transaction.id,
2589
- payload
2590
- });
2591
- break;
2592
- }
2593
- default: console.error("Unknown edit operation", operation);
2594
- }
2595
- };
2596
- if (operation.type === "editor:batchUpdate") {
2597
- const { payload } = operation;
2598
- if (!payload.transaction?.id) {
2599
- console.error("No transaction id in batch", operation);
2600
- return;
2601
- }
2602
- for (const update of payload.updates) addOperation(update, payload.transaction.id);
2603
- } else addOperation(operation);
2604
- }
2833
+ acknowledgeEditOperation(_operation) {}
2605
2834
  async ensureFilesSynced() {
2606
2835
  await source_update_api_default.ensureFilesSynced();
2607
2836
  }
2608
- generateSourceId() {
2609
- return generateSourceId();
2610
- }
2611
2837
  };
2612
2838
  //#endregion
2613
2839
  //#region src/edit-mode/runtime-graph/observable-graph.ts
@@ -2654,7 +2880,6 @@ var RuntimeComponentNode = class {
2654
2880
  isSbComponent;
2655
2881
  isHtmlElement;
2656
2882
  noSelect;
2657
- props;
2658
2883
  constructor(store, params) {
2659
2884
  this.store = store;
2660
2885
  this.sourceId = params.sourceId;
@@ -2663,10 +2888,7 @@ var RuntimeComponentNode = class {
2663
2888
  this.isSbComponent = params.isSbComponent;
2664
2889
  this.isHtmlElement = params.isHtmlElement;
2665
2890
  this.noSelect = params.noSelect;
2666
- makeAutoObservable(this, {
2667
- type: observable.ref,
2668
- props: observable.ref
2669
- });
2891
+ makeAutoObservable(this, { type: observable.ref });
2670
2892
  }
2671
2893
  get firstRenderedTag() {
2672
2894
  if (this?.isHtmlElement) return this.selectorId;
@@ -2757,13 +2979,9 @@ var RuntimeTrackingStore = class {
2757
2979
  }
2758
2980
  return this.jsxNodes[selectorId]?.nearestSelectableAncestor;
2759
2981
  }
2760
- updatePropsForComponent(selectorId, props) {
2761
- const componentNode = this.jsxNodes[selectorId];
2762
- if (componentNode) {
2763
- componentNode.props = props;
2764
- if (props.disabled) this.disabledComponents.add(selectorId);
2765
- else this.disabledComponents.delete(selectorId);
2766
- }
2982
+ setComponentDisabled(selectorId, disabled) {
2983
+ if (this.jsxNodes[selectorId]) if (disabled) this.disabledComponents.add(selectorId);
2984
+ else this.disabledComponents.delete(selectorId);
2767
2985
  }
2768
2986
  getComponent(selectorId) {
2769
2987
  return this.jsxNodes[selectorId];
@@ -4211,6 +4429,7 @@ if (isEditMode()) {
4211
4429
  let tokenUpdateGeneration = 0;
4212
4430
  let tokenUpdateAbortController = null;
4213
4431
  let devServerTokenUpdateQueue = Promise.resolve();
4432
+ const tokenDelivery = createDevServerTokenDelivery();
4214
4433
  const postDevServerAuthorization = async (authorization, generation, signal) => {
4215
4434
  const maxAttempts = 3;
4216
4435
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
@@ -4222,11 +4441,15 @@ if (isEditMode()) {
4222
4441
  signal
4223
4442
  });
4224
4443
  if (generation !== tokenUpdateGeneration) return;
4225
- if (response.ok) return;
4444
+ if (response.ok) {
4445
+ tokenDelivery.markDelivered(authorization);
4446
+ return;
4447
+ }
4226
4448
  throw new Error(`status ${response.status}`);
4227
4449
  } catch (error) {
4228
4450
  if (generation !== tokenUpdateGeneration) return;
4229
4451
  if (attempt === maxAttempts) {
4452
+ tokenDelivery.markFailed(authorization);
4230
4453
  console.warn("[internal] [iframe-wrappers] failed to update dev-server token", error);
4231
4454
  return;
4232
4455
  }
@@ -4235,13 +4458,20 @@ if (isEditMode()) {
4235
4458
  }
4236
4459
  };
4237
4460
  const updateDevServerAuthorization = (authorization, allowLegacyAuthorization) => {
4238
- if (!source_update_api_default.updateAuthorization(authorization, { allowLegacyAuthorization })) return;
4461
+ const authorizationChanged = source_update_api_default.updateAuthorization(authorization, { allowLegacyAuthorization });
4462
+ const installedAuthorization = source_update_api_default.getCurrentAuthorization();
4463
+ const decision = tokenDelivery.decide(authorizationChanged, installedAuthorization);
4464
+ if (decision.action === "skip") return;
4239
4465
  const generation = ++tokenUpdateGeneration;
4240
- tokenUpdateAbortController?.abort();
4241
- if (!authorization) return;
4466
+ if (decision.action !== "post" || decision.abortInFlight) {
4467
+ tokenUpdateAbortController?.abort();
4468
+ tokenDelivery.markAborted();
4469
+ }
4470
+ if (decision.action !== "post" || !installedAuthorization) return;
4242
4471
  const abortController = new AbortController();
4243
4472
  tokenUpdateAbortController = abortController;
4244
- devServerTokenUpdateQueue = devServerTokenUpdateQueue.catch(() => void 0).then(() => postDevServerAuthorization(authorization, generation, abortController.signal));
4473
+ tokenDelivery.markStarted(installedAuthorization);
4474
+ devServerTokenUpdateQueue = devServerTokenUpdateQueue.catch(() => void 0).then(() => postDevServerAuthorization(installedAuthorization, generation, abortController.signal));
4245
4475
  };
4246
4476
  const handleTokenUpdate = ({ data }) => {
4247
4477
  const { authorization } = data.payload;