@timeax/digital-service-engine 0.3.1 → 0.3.3

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.
@@ -100,7 +100,7 @@ function useAuthorsSlice(params) {
100
100
  });
101
101
  const refreshAuthors = React3.useCallback(async () => {
102
102
  setAuthors((s) => ({ ...s, loading: true }));
103
- const res = await backend.authors.refresh(workspaceId);
103
+ const res = await backend.authors.refresh({ workspaceId });
104
104
  if (res.ok) {
105
105
  setAuthors({
106
106
  data: res.value,
@@ -134,21 +134,29 @@ function usePermissionsSlice(params) {
134
134
  loading: false,
135
135
  updatedAt: initialPermissions ? runtime.now() : void 0
136
136
  });
137
- const refreshPermissions = React4.useCallback(async () => {
138
- setPermissions((s) => ({ ...s, loading: true }));
139
- const res = await backend.permissions.refresh(workspaceId, actor);
140
- if (res.ok) {
141
- setPermissions({
142
- data: res.value,
143
- loading: false,
144
- updatedAt: runtime.now()
137
+ const refreshPermissions = React4.useCallback(
138
+ async (params2) => {
139
+ setPermissions((s) => ({ ...s, loading: true }));
140
+ const res = await backend.permissions.refresh({
141
+ workspaceId,
142
+ actorId: actor.id,
143
+ branchId: params2 == null ? void 0 : params2.branchId,
144
+ since: params2 == null ? void 0 : params2.since
145
145
  });
146
- return res;
147
- } else {
148
- setLoadableError2(setPermissions, res.error);
149
- return res;
150
- }
151
- }, [backend.permissions, workspaceId, actor, runtime]);
146
+ if (res.ok) {
147
+ setPermissions({
148
+ data: res.value,
149
+ loading: false,
150
+ updatedAt: runtime.now()
151
+ });
152
+ return res;
153
+ } else {
154
+ setLoadableError2(setPermissions, res.error);
155
+ return res;
156
+ }
157
+ },
158
+ [backend.permissions, workspaceId, actor.id, runtime]
159
+ );
152
160
  const invalidatePermissions = React4.useCallback(() => {
153
161
  setPermissions((s) => ({ ...s, updatedAt: void 0 }));
154
162
  }, []);
@@ -217,7 +225,7 @@ function useBranchesSlice(params) {
217
225
  const refreshBranches = React5.useCallback(async () => {
218
226
  var _a;
219
227
  setBranches((s) => ({ ...s, loading: true }));
220
- const res = await backend.branches.refresh(workspaceId);
228
+ const res = await backend.branches.refresh({ workspaceId });
221
229
  if (!res.ok) {
222
230
  setBranches((s) => ({ ...s, loading: false, error: res.error }));
223
231
  return res;
@@ -252,11 +260,11 @@ function useBranchesSlice(params) {
252
260
  };
253
261
  }
254
262
  setParticipants((s) => ({ ...s, loading: true }));
255
- const res = await backend.access.refreshParticipants(
263
+ const res = await backend.access.refreshParticipants({
256
264
  workspaceId,
257
265
  branchId,
258
- { since: (_b = params2 == null ? void 0 : params2.since) != null ? _b : participants.updatedAt }
259
- );
266
+ since: (_b = params2 == null ? void 0 : params2.since) != null ? _b : participants.updatedAt
267
+ });
260
268
  if (res.ok) {
261
269
  setParticipants({
262
270
  data: res.value,
@@ -571,23 +579,29 @@ function useServicesSlice(params) {
571
579
  loading: false,
572
580
  updatedAt: initialServices ? runtime.now() : void 0
573
581
  });
574
- const refreshServices = React7.useCallback(async () => {
575
- setServices((s) => ({ ...s, loading: true }));
576
- const res = await backend.services.refresh(workspaceId, {
577
- since: services.updatedAt
578
- });
579
- if (!res.ok) {
580
- setLoadableError5(setServices, res.error);
581
- return res;
582
- }
583
- const map = toServiceMap(res.value);
584
- setServices({
585
- data: map != null ? map : {},
586
- loading: false,
587
- updatedAt: runtime.now()
588
- });
589
- return { ok: true, value: map != null ? map : {} };
590
- }, [backend.services, workspaceId, services.updatedAt, runtime]);
582
+ const refreshServices = React7.useCallback(
583
+ async (params2) => {
584
+ var _a;
585
+ setServices((s) => ({ ...s, loading: true }));
586
+ const res = await backend.services.refresh({
587
+ workspaceId,
588
+ branchId: params2 == null ? void 0 : params2.branchId,
589
+ since: (_a = params2 == null ? void 0 : params2.since) != null ? _a : services.updatedAt
590
+ });
591
+ if (!res.ok) {
592
+ setLoadableError5(setServices, res.error);
593
+ return res;
594
+ }
595
+ const map = toServiceMap(res.value);
596
+ setServices({
597
+ data: map != null ? map : {},
598
+ loading: false,
599
+ updatedAt: runtime.now()
600
+ });
601
+ return { ok: true, value: map != null ? map : {} };
602
+ },
603
+ [backend.services, workspaceId, services.updatedAt, runtime]
604
+ );
591
605
  const invalidateServices = React7.useCallback(() => {
592
606
  setServices((s) => ({ ...s, updatedAt: void 0 }));
593
607
  }, []);
@@ -2040,6 +2054,7 @@ function useWorkspaceBoot2(params) {
2040
2054
  setCurrentBranchId,
2041
2055
  refreshAuthors,
2042
2056
  refreshPermissions,
2057
+ refreshPermissionsWithBranch,
2043
2058
  refreshBranches,
2044
2059
  refreshServices,
2045
2060
  refreshParticipants,
@@ -2178,8 +2193,11 @@ function useWorkspaceBoot2(params) {
2178
2193
  const branchId = (_b = resolveActiveBranch(opts == null ? void 0 : opts.branchId)) != null ? _b : opts == null ? void 0 : opts.branchId;
2179
2194
  if ((_c = opts == null ? void 0 : opts.includeWorkspaceData) != null ? _c : true) {
2180
2195
  tasks.push(["authors", refreshAuthors]);
2181
- tasks.push(["permissions", refreshPermissions]);
2182
- tasks.push(["services", refreshServices]);
2196
+ tasks.push([
2197
+ "permissions",
2198
+ () => refreshPermissionsWithBranch(branchId)
2199
+ ]);
2200
+ tasks.push(["services", () => refreshServices(branchId)]);
2183
2201
  }
2184
2202
  if (!branchId) {
2185
2203
  markBranchScopedNoBranch();
@@ -2310,6 +2328,7 @@ function useWorkspaceBoot2(params) {
2310
2328
  refreshComments,
2311
2329
  refreshParticipants,
2312
2330
  refreshPermissions,
2331
+ refreshPermissionsWithBranch,
2313
2332
  refreshPolicies,
2314
2333
  refreshServices,
2315
2334
  refreshSnapshotPointers,
@@ -2569,8 +2588,9 @@ function WorkspaceProvider(props) {
2569
2588
  setCurrentBranchId: branchesSlice.setCurrentBranchId,
2570
2589
  refreshAuthors: authorsSlice.refreshAuthors,
2571
2590
  refreshPermissions: permissionsSlice.refreshPermissions,
2591
+ refreshPermissionsWithBranch: (branchId) => permissionsSlice.refreshPermissions({ branchId }),
2572
2592
  refreshBranches: branchesSlice.refreshBranches,
2573
- refreshServices: servicesSlice.refreshServices,
2593
+ refreshServices: (branchId) => servicesSlice.refreshServices({ branchId }),
2574
2594
  refreshParticipants: (branchId) => branchesSlice.refreshParticipants({ branchId }),
2575
2595
  refreshTemplates: (branchId) => templatesSlice.refreshTemplates({ branchId }),
2576
2596
  refreshSnapshotPointers: (branchId) => snapshotsSlice.refreshSnapshotPointersForBranch(branchId),
@@ -7479,13 +7499,7 @@ function duplicate(ctx, ref, opts = {}) {
7479
7499
  try {
7480
7500
  let newId2 = "";
7481
7501
  ctx.transact("duplicate", () => {
7482
- if (ref.kind === "tag") {
7483
- newId2 = duplicateTag(ctx, ref.id, opts);
7484
- } else if (ref.kind === "field") {
7485
- newId2 = duplicateField(ctx, ref.id, opts);
7486
- } else {
7487
- newId2 = duplicateOption(ctx, ref.fieldId, ref.id, opts);
7488
- }
7502
+ newId2 = duplicateInPlace(ctx, ref, opts);
7489
7503
  });
7490
7504
  return newId2;
7491
7505
  } catch (err) {
@@ -7493,6 +7507,74 @@ function duplicate(ctx, ref, opts = {}) {
7493
7507
  throw err;
7494
7508
  }
7495
7509
  }
7510
+ function duplicateMany(ctx, ids, opts = {}) {
7511
+ const ordered = Array.from(new Set((ids != null ? ids : []).map((id) => String(id))));
7512
+ if (!ordered.length) return [];
7513
+ const snapBefore = ctx.makeSnapshot("duplicateMany:before");
7514
+ try {
7515
+ const created = [];
7516
+ ctx.transact("duplicateMany", () => {
7517
+ var _a, _b, _c;
7518
+ const props = ctx.getProps();
7519
+ const selectedFields = /* @__PURE__ */ new Set();
7520
+ for (const id of ordered) {
7521
+ if (ctx.isFieldId(id) && ((_a = props.fields) != null ? _a : []).some((f) => f.id === id)) {
7522
+ selectedFields.add(id);
7523
+ }
7524
+ }
7525
+ for (const id of ordered) {
7526
+ if (ctx.isTagId(id)) {
7527
+ if (!((_b = ctx.getProps().filters) != null ? _b : []).some((t) => t.id === id)) continue;
7528
+ created.push(
7529
+ duplicateInPlace(ctx, { kind: "tag", id }, opts)
7530
+ );
7531
+ continue;
7532
+ }
7533
+ if (ctx.isFieldId(id)) {
7534
+ if (!((_c = ctx.getProps().fields) != null ? _c : []).some((f) => f.id === id)) continue;
7535
+ created.push(
7536
+ duplicateInPlace(ctx, { kind: "field", id }, opts)
7537
+ );
7538
+ continue;
7539
+ }
7540
+ if (ctx.isOptionId(id)) {
7541
+ const owner = ownerFieldOfOption(ctx.getProps(), id);
7542
+ if (!owner) continue;
7543
+ if (selectedFields.has(owner.fieldId)) continue;
7544
+ created.push(
7545
+ duplicateInPlace(
7546
+ ctx,
7547
+ { kind: "option", fieldId: owner.fieldId, id },
7548
+ opts
7549
+ )
7550
+ );
7551
+ }
7552
+ }
7553
+ });
7554
+ return created;
7555
+ } catch (err) {
7556
+ ctx.loadSnapshot(snapBefore, "undo");
7557
+ throw err;
7558
+ }
7559
+ }
7560
+ function duplicateInPlace(ctx, ref, opts = {}) {
7561
+ if (ref.kind === "tag") {
7562
+ return duplicateTag(ctx, ref.id, opts);
7563
+ }
7564
+ if (ref.kind === "field") {
7565
+ return duplicateField(ctx, ref.id, opts);
7566
+ }
7567
+ return duplicateOption(ctx, ref.fieldId, ref.id, opts);
7568
+ }
7569
+ function ownerFieldOfOption(props, optionId) {
7570
+ var _a, _b;
7571
+ for (const field of (_a = props.fields) != null ? _a : []) {
7572
+ if (((_b = field.options) != null ? _b : []).some((o) => o.id === optionId)) {
7573
+ return { fieldId: field.id };
7574
+ }
7575
+ }
7576
+ return null;
7577
+ }
7496
7578
  function duplicateTag(ctx, tagId, opts) {
7497
7579
  var _a, _b, _c, _d;
7498
7580
  const props = ctx.getProps();
@@ -7779,6 +7861,129 @@ function ensureServiceExists(opts, id) {
7779
7861
  }
7780
7862
 
7781
7863
  // src/react/canvas/editor/editor-nodes.ts
7864
+ var RELATION_MAP_KEYS = [
7865
+ "includes_for_buttons",
7866
+ "excludes_for_buttons",
7867
+ "includes_for_options",
7868
+ "excludes_for_options"
7869
+ ];
7870
+ function stripDeletedIds(ids) {
7871
+ const ordered = Array.from(new Set((ids != null ? ids : []).map((id) => String(id))));
7872
+ return { ordered, set: new Set(ordered) };
7873
+ }
7874
+ function cleanTagRelationsForDeleted(p, deleted) {
7875
+ var _a;
7876
+ for (const t of (_a = p.filters) != null ? _a : []) {
7877
+ if (t.bind_id && deleted.has(String(t.bind_id))) delete t.bind_id;
7878
+ if (t.includes) {
7879
+ const next = t.includes.filter((x) => !deleted.has(String(x)));
7880
+ if (next.length) t.includes = next;
7881
+ else delete t.includes;
7882
+ }
7883
+ if (t.excludes) {
7884
+ const next = t.excludes.filter((x) => !deleted.has(String(x)));
7885
+ if (next.length) t.excludes = next;
7886
+ else delete t.excludes;
7887
+ }
7888
+ }
7889
+ }
7890
+ function cleanFieldBindsForDeleted(p, deleted) {
7891
+ var _a;
7892
+ for (const f of (_a = p.fields) != null ? _a : []) {
7893
+ const bind = f.bind_id;
7894
+ if (!bind) continue;
7895
+ if (Array.isArray(bind)) {
7896
+ const next = bind.filter((x) => !deleted.has(String(x)));
7897
+ if (next.length) f.bind_id = next;
7898
+ else delete f.bind_id;
7899
+ continue;
7900
+ }
7901
+ if (deleted.has(String(bind))) delete f.bind_id;
7902
+ }
7903
+ }
7904
+ function cleanRelationMapsForDeleted(p, deleted) {
7905
+ var _a;
7906
+ for (const key of RELATION_MAP_KEYS) {
7907
+ const map = p[key];
7908
+ if (!map) continue;
7909
+ for (const mapKey of Object.keys(map)) {
7910
+ if (deleted.has(String(mapKey))) {
7911
+ delete map[mapKey];
7912
+ continue;
7913
+ }
7914
+ const next = ((_a = map[mapKey]) != null ? _a : []).filter(
7915
+ (item) => !deleted.has(String(item))
7916
+ );
7917
+ if (next.length) map[mapKey] = next;
7918
+ else delete map[mapKey];
7919
+ }
7920
+ if (!Object.keys(map).length) delete p[key];
7921
+ }
7922
+ }
7923
+ function cleanOrderForTagsForDeleted(p, deleted) {
7924
+ var _a, _b;
7925
+ const map = p.order_for_tags;
7926
+ if (!map) return;
7927
+ const fieldIds = new Set(((_a = p.fields) != null ? _a : []).map((f) => String(f.id)));
7928
+ for (const key of Object.keys(map)) {
7929
+ if (deleted.has(String(key))) {
7930
+ delete map[key];
7931
+ continue;
7932
+ }
7933
+ const next = ((_b = map[key]) != null ? _b : []).filter(
7934
+ (fid) => !deleted.has(String(fid)) && fieldIds.has(String(fid))
7935
+ );
7936
+ if (next.length) map[key] = next;
7937
+ else delete map[key];
7938
+ }
7939
+ if (!Object.keys(map).length) delete p.order_for_tags;
7940
+ }
7941
+ function cleanNoticesForDeleted(p, deleted) {
7942
+ var _a;
7943
+ if (!((_a = p.notices) == null ? void 0 : _a.length)) return;
7944
+ p.notices = p.notices.filter((n) => {
7945
+ const target = n.target;
7946
+ if (!target || target.scope === "global") return true;
7947
+ if (target.scope === "node" && deleted.has(String(target.node_id))) {
7948
+ return false;
7949
+ }
7950
+ return true;
7951
+ });
7952
+ if (!p.notices.length) delete p.notices;
7953
+ }
7954
+ function applyDeleteCleanup(p, deleted) {
7955
+ cleanTagRelationsForDeleted(p, deleted);
7956
+ cleanFieldBindsForDeleted(p, deleted);
7957
+ cleanRelationMapsForDeleted(p, deleted);
7958
+ cleanOrderForTagsForDeleted(p, deleted);
7959
+ cleanNoticesForDeleted(p, deleted);
7960
+ }
7961
+ function removeOptionInPlace(p, optionId) {
7962
+ var _a;
7963
+ const owner = ownerOfOption(p, optionId);
7964
+ if (!owner) return false;
7965
+ const f = ((_a = p.fields) != null ? _a : []).find((x) => x.id === owner.fieldId);
7966
+ if (!(f == null ? void 0 : f.options)) return false;
7967
+ const before = f.options.length;
7968
+ f.options = f.options.filter((o) => o.id !== optionId);
7969
+ return f.options.length !== before;
7970
+ }
7971
+ function removeFieldInPlace(p, fieldId) {
7972
+ var _a, _b, _c, _d, _e;
7973
+ const field = ((_a = p.fields) != null ? _a : []).find((f) => f.id === fieldId);
7974
+ if (!field) return [];
7975
+ const deleted = [fieldId, ...((_b = field.options) != null ? _b : []).map((o) => String(o.id))];
7976
+ const before = ((_c = p.fields) != null ? _c : []).length;
7977
+ p.fields = ((_d = p.fields) != null ? _d : []).filter((f) => f.id !== fieldId);
7978
+ clearFieldButtonReceiverMaps(p, fieldId);
7979
+ return ((_e = p.fields) != null ? _e : []).length !== before ? deleted : [];
7980
+ }
7981
+ function removeTagInPlace(p, tagId) {
7982
+ var _a, _b, _c;
7983
+ const before = ((_a = p.filters) != null ? _a : []).length;
7984
+ p.filters = ((_b = p.filters) != null ? _b : []).filter((t) => t.id !== tagId);
7985
+ return ((_c = p.filters) != null ? _c : []).length !== before;
7986
+ }
7782
7987
  function reLabel(ctx, id, nextLabel) {
7783
7988
  const label = String(nextLabel != null ? nextLabel : "").trim();
7784
7989
  ctx.exec({
@@ -7913,22 +8118,9 @@ function removeOption(ctx, optionId) {
7913
8118
  ctx.exec({
7914
8119
  name: "removeOption",
7915
8120
  do: () => ctx.patchProps((p) => {
7916
- var _a;
7917
- const owner = ownerOfOption(p, optionId);
7918
- if (!owner) return;
7919
- const f = ((_a = p.fields) != null ? _a : []).find((x) => x.id === owner.fieldId);
7920
- if (!(f == null ? void 0 : f.options)) return;
7921
- f.options = f.options.filter((o) => o.id !== optionId);
7922
- const maps = [
7923
- "includes_for_options",
7924
- "excludes_for_options"
7925
- ];
7926
- for (const m of maps) {
7927
- const map = p[m];
7928
- if (!map) continue;
7929
- if (map[optionId]) delete map[optionId];
7930
- if (!Object.keys(map).length) delete p[m];
7931
- }
8121
+ const removed = removeOptionInPlace(p, optionId);
8122
+ if (!removed) return;
8123
+ applyDeleteCleanup(p, /* @__PURE__ */ new Set([optionId]));
7932
8124
  }),
7933
8125
  undo: () => ctx.undo()
7934
8126
  });
@@ -8117,21 +8309,10 @@ function removeTag(ctx, id) {
8117
8309
  ctx.exec({
8118
8310
  name: "removeTag",
8119
8311
  do: () => ctx.patchProps((p) => {
8120
- var _a, _b, _c, _d, _e;
8121
8312
  prevSlice = cloneDeep3(p);
8122
- p.filters = ((_a = p.filters) != null ? _a : []).filter((t) => t.id !== id);
8123
- for (const t of (_b = p.filters) != null ? _b : []) {
8124
- if (t.bind_id === id) delete t.bind_id;
8125
- t.includes = ((_c = t.includes) != null ? _c : []).filter((x) => x !== id);
8126
- t.excludes = ((_d = t.excludes) != null ? _d : []).filter((x) => x !== id);
8127
- }
8128
- for (const f of (_e = p.fields) != null ? _e : []) {
8129
- if (Array.isArray(f.bind_id)) {
8130
- f.bind_id = f.bind_id.filter((x) => x !== id);
8131
- } else if (f.bind_id === id) {
8132
- delete f.bind_id;
8133
- }
8134
- }
8313
+ const removed = removeTagInPlace(p, id);
8314
+ if (!removed) return;
8315
+ applyDeleteCleanup(p, /* @__PURE__ */ new Set([id]));
8135
8316
  }),
8136
8317
  undo: () => ctx.replaceProps(prevSlice)
8137
8318
  });
@@ -8199,58 +8380,23 @@ function removeField(ctx, id) {
8199
8380
  ctx.exec({
8200
8381
  name: "removeField",
8201
8382
  do: () => ctx.patchProps((p) => {
8202
- var _a, _b, _c, _d, _e, _f;
8203
8383
  prevSlice = cloneDeep3(p);
8204
- p.fields = ((_a = p.fields) != null ? _a : []).filter((f) => f.id !== id);
8205
- clearFieldButtonReceiverMaps(p, id);
8206
- for (const mapKey of [
8207
- "includes_for_buttons",
8208
- "excludes_for_buttons"
8209
- ]) {
8210
- const m = p[mapKey];
8211
- if (!m) continue;
8212
- for (const k of Object.keys(m)) {
8213
- m[k] = ((_b = m[k]) != null ? _b : []).filter((fid) => fid !== id);
8214
- if (!((_c = m[k]) == null ? void 0 : _c.length)) delete m[k];
8215
- }
8216
- }
8217
- for (const t of (_d = p.filters) != null ? _d : []) {
8218
- t.includes = ((_e = t.includes) != null ? _e : []).filter((x) => x !== id);
8219
- t.excludes = ((_f = t.excludes) != null ? _f : []).filter((x) => x !== id);
8220
- }
8384
+ const removedIds = removeFieldInPlace(p, id);
8385
+ if (!removedIds.length) return;
8386
+ applyDeleteCleanup(p, new Set(removedIds));
8221
8387
  }),
8222
8388
  undo: () => ctx.replaceProps(prevSlice)
8223
8389
  });
8224
8390
  }
8225
8391
  function remove(ctx, id) {
8392
+ const key = String(id);
8226
8393
  if (ctx.isTagId(id)) {
8227
8394
  ctx.exec({
8228
8395
  name: "removeTag",
8229
8396
  do: () => ctx.patchProps((p) => {
8230
- var _a, _b, _c, _d, _e, _f, _g, _h;
8231
- p.filters = ((_a = p.filters) != null ? _a : []).filter((t) => t.id !== id);
8232
- for (const t of (_b = p.filters) != null ? _b : []) {
8233
- if (t.bind_id === id) delete t.bind_id;
8234
- t.includes = ((_c = t.includes) != null ? _c : []).filter((x) => x !== id);
8235
- t.excludes = ((_d = t.excludes) != null ? _d : []).filter((x) => x !== id);
8236
- }
8237
- for (const f of (_e = p.fields) != null ? _e : []) {
8238
- if (Array.isArray(f.bind_id)) {
8239
- f.bind_id = f.bind_id.filter((x) => x !== id);
8240
- } else if (f.bind_id === id) {
8241
- delete f.bind_id;
8242
- }
8243
- }
8244
- if ((_f = p.order_for_tags) == null ? void 0 : _f[id]) delete p.order_for_tags[id];
8245
- for (const k of Object.keys((_g = p.order_for_tags) != null ? _g : {})) {
8246
- p.order_for_tags[k] = ((_h = p.order_for_tags[k]) != null ? _h : []).filter(
8247
- (fid) => {
8248
- var _a2;
8249
- return ((_a2 = p.fields) != null ? _a2 : []).some((f) => f.id === fid);
8250
- }
8251
- );
8252
- if (!p.order_for_tags[k].length) delete p.order_for_tags[k];
8253
- }
8397
+ const removed = removeTagInPlace(p, key);
8398
+ if (!removed) return;
8399
+ applyDeleteCleanup(p, /* @__PURE__ */ new Set([key]));
8254
8400
  }),
8255
8401
  undo: () => ctx.undo()
8256
8402
  });
@@ -8260,42 +8406,67 @@ function remove(ctx, id) {
8260
8406
  ctx.exec({
8261
8407
  name: "removeField",
8262
8408
  do: () => ctx.patchProps((p) => {
8263
- var _a, _b, _c, _d, _e, _f, _g, _h;
8264
- p.fields = ((_a = p.fields) != null ? _a : []).filter((f) => f.id !== id);
8265
- for (const t of (_b = p.filters) != null ? _b : []) {
8266
- t.includes = ((_c = t.includes) != null ? _c : []).filter((x) => x !== id);
8267
- t.excludes = ((_d = t.excludes) != null ? _d : []).filter((x) => x !== id);
8268
- }
8269
- for (const k of Object.keys((_e = p.order_for_tags) != null ? _e : {})) {
8270
- p.order_for_tags[k] = ((_f = p.order_for_tags[k]) != null ? _f : []).filter(
8271
- (fid) => fid !== id
8272
- );
8273
- if (!p.order_for_tags[k].length) delete p.order_for_tags[k];
8274
- }
8275
- const maps = [
8276
- "includes_for_options",
8277
- "excludes_for_options"
8278
- ];
8279
- for (const m of maps) {
8280
- const map = p[m];
8281
- if (!map) continue;
8282
- for (const key of Object.keys(map)) {
8283
- map[key] = ((_g = map[key]) != null ? _g : []).filter((fid) => fid !== id);
8284
- if (!((_h = map[key]) == null ? void 0 : _h.length)) delete map[key];
8285
- }
8286
- if (!Object.keys(map).length) delete p[m];
8287
- }
8409
+ const removedIds = removeFieldInPlace(p, key);
8410
+ if (!removedIds.length) return;
8411
+ applyDeleteCleanup(p, new Set(removedIds));
8288
8412
  }),
8289
8413
  undo: () => ctx.undo()
8290
8414
  });
8291
8415
  return;
8292
8416
  }
8293
8417
  if (ctx.isOptionId(id)) {
8294
- removeOption(ctx, id);
8418
+ ctx.exec({
8419
+ name: "removeOption",
8420
+ do: () => ctx.patchProps((p) => {
8421
+ const removed = removeOptionInPlace(p, key);
8422
+ if (!removed) return;
8423
+ applyDeleteCleanup(p, /* @__PURE__ */ new Set([key]));
8424
+ }),
8425
+ undo: () => ctx.undo()
8426
+ });
8295
8427
  return;
8296
8428
  }
8297
8429
  throw new Error("remove: unknown id prefix");
8298
8430
  }
8431
+ function removeMany(ctx, ids) {
8432
+ const { ordered } = stripDeletedIds(ids);
8433
+ if (!ordered.length) return;
8434
+ ctx.transact("removeMany", () => {
8435
+ ctx.patchProps((p) => {
8436
+ var _a, _b, _c;
8437
+ const existingFieldIds = new Set(((_a = p.fields) != null ? _a : []).map((f) => String(f.id)));
8438
+ const existingTagIds = new Set(((_b = p.filters) != null ? _b : []).map((t) => String(t.id)));
8439
+ const existingOptionIds = new Set(
8440
+ ((_c = p.fields) != null ? _c : []).flatMap((f) => {
8441
+ var _a2;
8442
+ return ((_a2 = f.options) != null ? _a2 : []).map((o) => String(o.id));
8443
+ })
8444
+ );
8445
+ const fieldIds = ordered.filter((id) => ctx.isFieldId(id) && existingFieldIds.has(id));
8446
+ const fieldIdSet = new Set(fieldIds);
8447
+ const tagIds = ordered.filter((id) => ctx.isTagId(id) && existingTagIds.has(id));
8448
+ const optionIds = ordered.filter((id) => {
8449
+ if (!ctx.isOptionId(id) || !existingOptionIds.has(id)) return false;
8450
+ const owner = ownerOfOption(p, id);
8451
+ if (!owner) return false;
8452
+ return !fieldIdSet.has(String(owner.fieldId));
8453
+ });
8454
+ const deleted = /* @__PURE__ */ new Set();
8455
+ for (const optionId of optionIds) {
8456
+ if (removeOptionInPlace(p, optionId)) deleted.add(optionId);
8457
+ }
8458
+ for (const fieldId of fieldIds) {
8459
+ const removedIds = removeFieldInPlace(p, fieldId);
8460
+ for (const rid of removedIds) deleted.add(rid);
8461
+ }
8462
+ for (const tagId of tagIds) {
8463
+ if (removeTagInPlace(p, tagId)) deleted.add(tagId);
8464
+ }
8465
+ if (!deleted.size) return;
8466
+ applyDeleteCleanup(p, deleted);
8467
+ });
8468
+ });
8469
+ }
8299
8470
  function getNode(ctx, id) {
8300
8471
  var _a, _b, _c, _d;
8301
8472
  const props = ctx.getProps();
@@ -9540,6 +9711,9 @@ var Editor = class {
9540
9711
  duplicate(ref, opts = {}) {
9541
9712
  return duplicate(this.moduleCtx(), ref, opts);
9542
9713
  }
9714
+ duplicateMany(ids, opts = {}) {
9715
+ return duplicateMany(this.moduleCtx(), ids, opts);
9716
+ }
9543
9717
  reLabel(id, nextLabel) {
9544
9718
  return reLabel(this.moduleCtx(), id, nextLabel);
9545
9719
  }
@@ -9603,6 +9777,260 @@ var Editor = class {
9603
9777
  remove(id) {
9604
9778
  return remove(this.moduleCtx(), id);
9605
9779
  }
9780
+ removeMany(ids) {
9781
+ return removeMany(this.moduleCtx(), ids);
9782
+ }
9783
+ clearServiceMany(ids) {
9784
+ const ordered = Array.from(new Set((ids != null ? ids : []).map((id) => String(id))));
9785
+ if (!ordered.length) return;
9786
+ this.transact("clearServiceMany", () => {
9787
+ this.patchProps((p) => {
9788
+ var _a, _b, _c, _d;
9789
+ for (const id of ordered) {
9790
+ if (this.isTagId(id)) {
9791
+ const t = ((_a = p.filters) != null ? _a : []).find((x) => x.id === id);
9792
+ if (t && "service_id" in t) delete t.service_id;
9793
+ continue;
9794
+ }
9795
+ if (this.isFieldId(id)) {
9796
+ const f = ((_b = p.fields) != null ? _b : []).find((x) => x.id === id);
9797
+ if (f && "service_id" in f) delete f.service_id;
9798
+ continue;
9799
+ }
9800
+ if (this.isOptionId(id)) {
9801
+ const own = ownerOfOption(p, id);
9802
+ if (!own) continue;
9803
+ const f = ((_c = p.fields) != null ? _c : []).find((x) => x.id === own.fieldId);
9804
+ const o = (_d = f == null ? void 0 : f.options) == null ? void 0 : _d.find((x) => x.id === id);
9805
+ if (o && "service_id" in o) delete o.service_id;
9806
+ }
9807
+ }
9808
+ });
9809
+ });
9810
+ }
9811
+ rebindMany(ids, targetTagId, opts) {
9812
+ const ordered = Array.from(new Set((ids != null ? ids : []).map((id) => String(id))));
9813
+ if (!ordered.length) return;
9814
+ this.transact("rebindMany", () => {
9815
+ this.patchProps((p) => {
9816
+ var _a, _b, _c;
9817
+ const targetExists = ((_a = p.filters) != null ? _a : []).some((t) => t.id === targetTagId);
9818
+ if (!targetExists) return;
9819
+ for (const id of ordered) {
9820
+ if (this.isFieldId(id)) {
9821
+ const f = ((_b = p.fields) != null ? _b : []).find((x) => x.id === id);
9822
+ if (!f) continue;
9823
+ f.bind_id = targetTagId;
9824
+ continue;
9825
+ }
9826
+ if (this.isTagId(id)) {
9827
+ const t = ((_c = p.filters) != null ? _c : []).find((x) => x.id === id);
9828
+ if (!t) continue;
9829
+ if (!(opts == null ? void 0 : opts.allowTagCycles) && wouldCreateTagCycle(this.moduleCtx(), p, targetTagId, id)) {
9830
+ continue;
9831
+ }
9832
+ t.bind_id = targetTagId;
9833
+ }
9834
+ }
9835
+ });
9836
+ });
9837
+ }
9838
+ includeMany(receiverId, ids) {
9839
+ const accepted = Array.from(new Set((ids != null ? ids : []).map((id) => String(id)))).filter((id) => id !== receiverId).filter((id) => this.getNode(id).data != null);
9840
+ if (!accepted.length) return;
9841
+ include(this.moduleCtx(), receiverId, accepted);
9842
+ }
9843
+ excludeMany(receiverId, ids) {
9844
+ const accepted = Array.from(new Set((ids != null ? ids : []).map((id) => String(id)))).filter((id) => id !== receiverId).filter((id) => this.getNode(id).data != null);
9845
+ if (!accepted.length) return;
9846
+ exclude(this.moduleCtx(), receiverId, accepted);
9847
+ }
9848
+ clearRelationsMany(ids, mode = "both") {
9849
+ const selected = new Set(Array.from(new Set((ids != null ? ids : []).map((id) => String(id)))));
9850
+ if (!selected.size) return;
9851
+ this.transact("clearRelationsMany", () => {
9852
+ this.patchProps((p) => {
9853
+ var _a, _b, _c;
9854
+ const clearOwned = mode === "owned" || mode === "both";
9855
+ const clearIncoming = mode === "incoming" || mode === "both";
9856
+ for (const t of (_a = p.filters) != null ? _a : []) {
9857
+ if (clearOwned && selected.has(t.id)) {
9858
+ delete t.includes;
9859
+ delete t.excludes;
9860
+ }
9861
+ if (clearIncoming) {
9862
+ if (t.includes) {
9863
+ t.includes = t.includes.filter((x) => !selected.has(String(x)));
9864
+ if (!t.includes.length) delete t.includes;
9865
+ }
9866
+ if (t.excludes) {
9867
+ t.excludes = t.excludes.filter((x) => !selected.has(String(x)));
9868
+ if (!t.excludes.length) delete t.excludes;
9869
+ }
9870
+ }
9871
+ }
9872
+ const maps = [
9873
+ "includes_for_buttons",
9874
+ "excludes_for_buttons",
9875
+ "includes_for_options",
9876
+ "excludes_for_options"
9877
+ ];
9878
+ for (const k of maps) {
9879
+ const map = p[k];
9880
+ if (!map) continue;
9881
+ for (const key of Object.keys(map)) {
9882
+ if (clearOwned && selected.has(String(key))) {
9883
+ delete map[key];
9884
+ continue;
9885
+ }
9886
+ if (clearIncoming) {
9887
+ map[key] = ((_b = map[key]) != null ? _b : []).filter((x) => !selected.has(String(x)));
9888
+ if (!((_c = map[key]) == null ? void 0 : _c.length)) delete map[key];
9889
+ }
9890
+ }
9891
+ if (!Object.keys(map).length) delete p[k];
9892
+ }
9893
+ });
9894
+ });
9895
+ }
9896
+ renameLabelsMany(ids, input) {
9897
+ var _a, _b;
9898
+ const ordered = Array.from(new Set((ids != null ? ids : []).map((id) => String(id))));
9899
+ if (!ordered.length) return;
9900
+ const prefix = (_a = input.prefix) != null ? _a : "";
9901
+ const suffix = (_b = input.suffix) != null ? _b : "";
9902
+ this.transact("renameLabelsMany", () => {
9903
+ this.patchProps((p) => {
9904
+ var _a2, _b2, _c, _d, _e, _f, _g;
9905
+ for (const id of ordered) {
9906
+ if (this.isTagId(id)) {
9907
+ const t = ((_a2 = p.filters) != null ? _a2 : []).find((x) => x.id === id);
9908
+ if (t) t.label = `${prefix}${(_b2 = t.label) != null ? _b2 : ""}${suffix}`.trim();
9909
+ continue;
9910
+ }
9911
+ if (this.isFieldId(id)) {
9912
+ const f = ((_c = p.fields) != null ? _c : []).find((x) => x.id === id);
9913
+ if (f) f.label = `${prefix}${(_d = f.label) != null ? _d : ""}${suffix}`.trim();
9914
+ continue;
9915
+ }
9916
+ if (this.isOptionId(id)) {
9917
+ const own = ownerOfOption(p, id);
9918
+ if (!own) continue;
9919
+ const f = ((_e = p.fields) != null ? _e : []).find((x) => x.id === own.fieldId);
9920
+ const o = (_f = f == null ? void 0 : f.options) == null ? void 0 : _f.find((x) => x.id === id);
9921
+ if (o) o.label = `${prefix}${(_g = o.label) != null ? _g : ""}${suffix}`.trim();
9922
+ }
9923
+ }
9924
+ });
9925
+ });
9926
+ }
9927
+ setPricingRoleMany(ids, role) {
9928
+ const ordered = Array.from(new Set((ids != null ? ids : []).map((id) => String(id))));
9929
+ if (!ordered.length) return;
9930
+ this.transact("setPricingRoleMany", () => {
9931
+ for (const id of ordered) {
9932
+ if (this.isFieldId(id) || this.isOptionId(id)) {
9933
+ this.setService(id, { pricing_role: role });
9934
+ }
9935
+ }
9936
+ });
9937
+ }
9938
+ clearFieldDefaultsMany(ids) {
9939
+ const ordered = Array.from(new Set((ids != null ? ids : []).map((id) => String(id))));
9940
+ if (!ordered.length) return;
9941
+ this.transact("clearFieldDefaultsMany", () => {
9942
+ this.patchProps((p) => {
9943
+ var _a;
9944
+ for (const id of ordered) {
9945
+ if (!this.isFieldId(id)) continue;
9946
+ const f = ((_a = p.fields) != null ? _a : []).find((x) => x.id === id);
9947
+ if (f && "defaults" in f) delete f.defaults;
9948
+ }
9949
+ });
9950
+ });
9951
+ }
9952
+ clearFieldValidationMany(ids) {
9953
+ const ordered = Array.from(new Set((ids != null ? ids : []).map((id) => String(id))));
9954
+ if (!ordered.length) return;
9955
+ this.transact("clearFieldValidationMany", () => {
9956
+ this.patchProps((p) => {
9957
+ var _a;
9958
+ for (const id of ordered) {
9959
+ if (!this.isFieldId(id)) continue;
9960
+ const f = ((_a = p.fields) != null ? _a : []).find((x) => x.id === id);
9961
+ if (f && "validation" in f) delete f.validation;
9962
+ }
9963
+ });
9964
+ });
9965
+ }
9966
+ autoCreateOptionsMany(ids, makeOption) {
9967
+ const ordered = Array.from(new Set((ids != null ? ids : []).map((id) => String(id))));
9968
+ if (!ordered.length) return;
9969
+ this.transact("autoCreateOptionsMany", () => {
9970
+ this.patchProps((p) => {
9971
+ var _a, _b, _c, _d;
9972
+ for (const id of ordered) {
9973
+ if (!this.isFieldId(id)) continue;
9974
+ const f = ((_a = p.fields) != null ? _a : []).find((x) => x.id === id);
9975
+ if (!f) continue;
9976
+ const opts = (_b = f.options) != null ? _b : f.options = [];
9977
+ if (opts.length > 0) continue;
9978
+ const next = (_c = makeOption == null ? void 0 : makeOption(id)) != null ? _c : { label: "Option label", value: "option" };
9979
+ opts.push({
9980
+ id: (_d = next.id) != null ? _d : this.moduleCtx().genId("o"),
9981
+ label: next.label,
9982
+ value: next.value
9983
+ });
9984
+ }
9985
+ });
9986
+ });
9987
+ }
9988
+ clearAllOptionsMany(ids) {
9989
+ var _a, _b;
9990
+ const ordered = Array.from(new Set((ids != null ? ids : []).map((id) => String(id))));
9991
+ if (!ordered.length) return;
9992
+ const optionIds = [];
9993
+ const props = this.getProps();
9994
+ for (const id of ordered) {
9995
+ if (!this.isFieldId(id)) continue;
9996
+ const f = ((_a = props.fields) != null ? _a : []).find((x) => x.id === id);
9997
+ for (const o of (_b = f == null ? void 0 : f.options) != null ? _b : []) optionIds.push(o.id);
9998
+ }
9999
+ if (!optionIds.length) return;
10000
+ removeMany(this.moduleCtx(), optionIds);
10001
+ }
10002
+ removeNoticesForNodes(ids) {
10003
+ const selected = new Set(Array.from(new Set((ids != null ? ids : []).map((id) => String(id)))));
10004
+ if (!selected.size) return;
10005
+ this.transact("removeNoticesForNodes", () => {
10006
+ this.patchProps((p) => {
10007
+ var _a;
10008
+ if (!((_a = p.notices) == null ? void 0 : _a.length)) return;
10009
+ p.notices = p.notices.filter((n) => {
10010
+ const target = n.target;
10011
+ if (!target || target.scope === "global") return true;
10012
+ if (target.scope === "node") return !selected.has(String(target.node_id));
10013
+ return true;
10014
+ });
10015
+ if (!p.notices.length) delete p.notices;
10016
+ });
10017
+ });
10018
+ }
10019
+ setNoticesVisibilityForNodes(ids, type) {
10020
+ const selected = new Set(Array.from(new Set((ids != null ? ids : []).map((id) => String(id)))));
10021
+ if (!selected.size) return;
10022
+ this.transact("setNoticesVisibilityForNodes", () => {
10023
+ this.patchProps((p) => {
10024
+ var _a;
10025
+ for (const n of (_a = p.notices) != null ? _a : []) {
10026
+ const target = n.target;
10027
+ if ((target == null ? void 0 : target.scope) === "node" && selected.has(String(target.node_id))) {
10028
+ n.type = type;
10029
+ }
10030
+ }
10031
+ });
10032
+ });
10033
+ }
9606
10034
  getNode(id) {
9607
10035
  return getNode(this.moduleCtx(), id);
9608
10036
  }
@@ -9846,9 +10274,8 @@ var Editor = class {
9846
10274
  Array.isArray(canvas.selection) ? canvas.selection : Array.from(canvas.selection)
9847
10275
  );
9848
10276
  }
9849
- } else {
9850
- this.api.refreshGraph();
9851
10277
  }
10278
+ this.api.refreshGraph();
9852
10279
  this.emit("editor:change", { props: s.props, reason, snapshot: s });
9853
10280
  }
9854
10281
  pushHistory(snap) {
@@ -10936,12 +11363,12 @@ function useCanvasOwned(initialProps, canvasOpts, builderOpts) {
10936
11363
  // src/react/workspace/context/hooks/use-canvas.ts
10937
11364
  import * as React16 from "react";
10938
11365
  import { useMemo as useMemo15 } from "react";
10939
- function deriveSelectionInfo(props, ids) {
11366
+ function deriveSelectionInfo(nodeMap, ids) {
10940
11367
  const tags = [];
10941
11368
  const fields = [];
10942
11369
  const options = [];
10943
11370
  for (const id of ids) {
10944
- const node = props.get(id);
11371
+ const node = nodeMap.get(id);
10945
11372
  if (!node) continue;
10946
11373
  if (node.kind == "tag") {
10947
11374
  tags.push(id);
@@ -10968,6 +11395,49 @@ function deriveSelectionInfo(props, ids) {
10968
11395
  optionIds: uniq2(options)
10969
11396
  };
10970
11397
  }
11398
+ function noticeTargetsSelection(notice, selected) {
11399
+ const target = notice.target;
11400
+ if (target.scope === "global") return false;
11401
+ return selected.has(String(target.node_id));
11402
+ }
11403
+ function deriveSelectionCapabilities(props, selectionInfo) {
11404
+ var _a, _b, _c;
11405
+ const selected = new Set(selectionInfo.ids.map(String));
11406
+ const fields = (_a = props == null ? void 0 : props.fields) != null ? _a : [];
11407
+ const tags = (_b = props == null ? void 0 : props.filters) != null ? _b : [];
11408
+ const notices = (_c = props == null ? void 0 : props.notices) != null ? _c : [];
11409
+ const hasSelectedFieldWithOptions = fields.some(
11410
+ (f) => {
11411
+ var _a2, _b2;
11412
+ return selected.has(String(f.id)) && ((_b2 = (_a2 = f.options) == null ? void 0 : _a2.length) != null ? _b2 : 0) > 0;
11413
+ }
11414
+ );
11415
+ const hasServiceBearingNodes = tags.some(
11416
+ (t) => selected.has(String(t.id)) && t.service_id !== void 0 && t.service_id !== null
11417
+ ) || fields.some(
11418
+ (f) => selected.has(String(f.id)) && f.service_id !== void 0 && f.service_id !== null
11419
+ ) || fields.some(
11420
+ (f) => {
11421
+ var _a2;
11422
+ return ((_a2 = f.options) != null ? _a2 : []).some(
11423
+ (o) => selected.has(String(o.id)) && o.service_id !== void 0 && o.service_id !== null
11424
+ );
11425
+ }
11426
+ );
11427
+ const hasNoticesForSelection = notices.some(
11428
+ (n) => noticeTargetsSelection(n, selected)
11429
+ );
11430
+ return {
11431
+ hasTags: selectionInfo.tagIds.length > 0,
11432
+ hasFields: selectionInfo.fieldIds.length > 0,
11433
+ hasOptions: selectionInfo.optionIds.length > 0,
11434
+ hasServiceBearingNodes,
11435
+ hasSelectedFieldWithOptions,
11436
+ hasNoticesForSelection,
11437
+ canIncludeExcludeTargets: selectionInfo.tagIds.length + selectionInfo.fieldIds.length + selectionInfo.optionIds.length > 0,
11438
+ canRebind: selectionInfo.fieldIds.length > 0 || selectionInfo.tagIds.length > 0
11439
+ };
11440
+ }
10971
11441
  function tagBindIds(tag) {
10972
11442
  const bind = tag.bind_id;
10973
11443
  if (!bind) return [];
@@ -11107,7 +11577,11 @@ function useCanvas() {
11107
11577
  });
11108
11578
  return off;
11109
11579
  }, [api]);
11110
- const selector = useMemo15(() => createNodeIndex(api.builder), [props]);
11580
+ const selector = useMemo15(() => createNodeIndex(api.builder), [api.builder, props]);
11581
+ const selectionCapabilities = React16.useMemo(
11582
+ () => deriveSelectionCapabilities(props, selectionInfo),
11583
+ [props, selectionInfo]
11584
+ );
11111
11585
  return React16.useMemo(
11112
11586
  () => ({
11113
11587
  api,
@@ -11116,6 +11590,7 @@ function useCanvas() {
11116
11590
  props,
11117
11591
  selection,
11118
11592
  selectionInfo,
11593
+ selectionCapabilities,
11119
11594
  selector,
11120
11595
  activeId,
11121
11596
  setActive
@@ -11127,6 +11602,7 @@ function useCanvas() {
11127
11602
  props,
11128
11603
  selection,
11129
11604
  selectionInfo,
11605
+ selectionCapabilities,
11130
11606
  selector,
11131
11607
  activeId,
11132
11608
  setActive
@@ -11940,8 +12416,8 @@ function createMemoryWorkspaceBackend(opts) {
11940
12416
  };
11941
12417
  void initStore();
11942
12418
  const authorsBase = {
11943
- list: async (workspaceId) => {
11944
- if (workspaceId !== info.id)
12419
+ list: async (ctx) => {
12420
+ if (ctx.workspaceId !== info.id)
11945
12421
  return fail("not_found", "Workspace not found.");
11946
12422
  return ok(Array.from(store.authors.values()));
11947
12423
  },
@@ -11949,8 +12425,8 @@ function createMemoryWorkspaceBackend(opts) {
11949
12425
  const a = store.authors.get(authorId);
11950
12426
  return ok(a != null ? a : null);
11951
12427
  },
11952
- refresh: async (workspaceId) => {
11953
- if (workspaceId !== info.id)
12428
+ refresh: async (ctx) => {
12429
+ if (ctx.workspaceId !== info.id)
11954
12430
  return fail("not_found", "Workspace not found.");
11955
12431
  return ok(Array.from(store.authors.values()));
11956
12432
  }
@@ -11962,18 +12438,18 @@ function createMemoryWorkspaceBackend(opts) {
11962
12438
  []
11963
12439
  );
11964
12440
  const permissionsBase = {
11965
- get: async (workspaceId, actor) => {
12441
+ get: async (ctx) => {
11966
12442
  var _a, _b;
11967
- if (workspaceId !== info.id)
12443
+ if (ctx.workspaceId !== info.id)
11968
12444
  return fail("not_found", "Workspace not found.");
11969
- const seeded = (_b = (_a = store.permissionsByActor.get(actor.id)) != null ? _a : store.permissionsByActor.get("*")) != null ? _b : void 0;
12445
+ const seeded = (_b = (_a = store.permissionsByActor.get(ctx.actorId)) != null ? _a : store.permissionsByActor.get("*")) != null ? _b : void 0;
11970
12446
  return ok(seeded != null ? seeded : permissivePermissions());
11971
12447
  },
11972
- refresh: async (workspaceId, actor) => {
12448
+ refresh: async (ctx) => {
11973
12449
  var _a, _b;
11974
- if (workspaceId !== info.id)
12450
+ if (ctx.workspaceId !== info.id)
11975
12451
  return fail("not_found", "Workspace not found.");
11976
- const seeded = (_b = (_a = store.permissionsByActor.get(actor.id)) != null ? _a : store.permissionsByActor.get("*")) != null ? _b : void 0;
12452
+ const seeded = (_b = (_a = store.permissionsByActor.get(ctx.actorId)) != null ? _a : store.permissionsByActor.get("*")) != null ? _b : void 0;
11977
12453
  return ok(seeded != null ? seeded : permissivePermissions());
11978
12454
  }
11979
12455
  };
@@ -11984,8 +12460,8 @@ function createMemoryWorkspaceBackend(opts) {
11984
12460
  []
11985
12461
  );
11986
12462
  const branchesBase = {
11987
- list: async (workspaceId) => {
11988
- if (workspaceId !== info.id)
12463
+ list: async (ctx) => {
12464
+ if (ctx.workspaceId !== info.id)
11989
12465
  return fail("not_found", "Workspace not found.");
11990
12466
  return ok(Array.from(store.branches.values()));
11991
12467
  },
@@ -12091,8 +12567,8 @@ function createMemoryWorkspaceBackend(opts) {
12091
12567
  store.policiesByBranch.delete(branchId);
12092
12568
  return ok(void 0);
12093
12569
  },
12094
- refresh: async (workspaceId) => {
12095
- if (workspaceId !== info.id)
12570
+ refresh: async (ctx) => {
12571
+ if (ctx.workspaceId !== info.id)
12096
12572
  return fail("not_found", "Workspace not found.");
12097
12573
  return ok(Array.from(store.branches.values()));
12098
12574
  }
@@ -12104,18 +12580,18 @@ function createMemoryWorkspaceBackend(opts) {
12104
12580
  ["create", "setMain", "merge", "delete"]
12105
12581
  );
12106
12582
  const accessBase = {
12107
- listParticipants: async (workspaceId, branchId) => {
12583
+ listParticipants: async (ctx) => {
12108
12584
  var _a;
12109
- if (workspaceId !== info.id)
12585
+ if (ctx.workspaceId !== info.id)
12110
12586
  return fail("not_found", "Workspace not found.");
12111
- const list = (_a = store.participantsByBranch.get(branchId)) != null ? _a : [];
12587
+ const list = (_a = store.participantsByBranch.get(ctx.branchId)) != null ? _a : [];
12112
12588
  return ok(list);
12113
12589
  },
12114
- refreshParticipants: async (workspaceId, branchId) => {
12590
+ refreshParticipants: async (ctx) => {
12115
12591
  var _a;
12116
- if (workspaceId !== info.id)
12592
+ if (ctx.workspaceId !== info.id)
12117
12593
  return fail("not_found", "Workspace not found.");
12118
- const list = (_a = store.participantsByBranch.get(branchId)) != null ? _a : [];
12594
+ const list = (_a = store.participantsByBranch.get(ctx.branchId)) != null ? _a : [];
12119
12595
  return ok(list);
12120
12596
  }
12121
12597
  };
@@ -12126,14 +12602,14 @@ function createMemoryWorkspaceBackend(opts) {
12126
12602
  []
12127
12603
  );
12128
12604
  const servicesBase = {
12129
- get: async (workspaceId) => {
12130
- if (workspaceId !== info.id)
12605
+ get: async (ctx) => {
12606
+ if (ctx.workspaceId !== info.id)
12131
12607
  return fail("not_found", "Workspace not found.");
12132
12608
  if (!store.services) return ok([]);
12133
12609
  return ok(store.services);
12134
12610
  },
12135
- refresh: async (workspaceId) => {
12136
- if (workspaceId !== info.id)
12611
+ refresh: async (ctx) => {
12612
+ if (ctx.workspaceId !== info.id)
12137
12613
  return fail("not_found", "Workspace not found.");
12138
12614
  if (!store.services) return ok([]);
12139
12615
  return ok(store.services);
@@ -13813,6 +14289,7 @@ export {
13813
14289
  WorkspaceProvider,
13814
14290
  createMemoryWorkspaceBackend,
13815
14291
  createPollAdapter,
14292
+ deriveSelectionCapabilities,
13816
14293
  useCanvas,
13817
14294
  useCanvasAPI,
13818
14295
  useCanvasFromBuilder,