@contentful/experience-design-system-cli 2.37.1-dev-build-e5882940.0 → 2.37.1-dev-build-7a46c9e6.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/app.js CHANGED
@@ -7429,6 +7429,9 @@ function PreviewBadge({
7429
7429
 
7430
7430
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/sidebar/components/GroupedSidebar.tsx
7431
7431
  import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
7432
+ function slotEdgeKey(parent, child) {
7433
+ return `${parent}\u2192${child}`;
7434
+ }
7432
7435
  var GLYPH_EXPAND_COLLAPSED = "\u25B8";
7433
7436
  var GLYPH_EXPAND_EXPANDED = "\u25BE";
7434
7437
  var GLYPH_TREE_MID = "\u251C\u2500";
@@ -7544,7 +7547,7 @@ function buildVisibleRows(props) {
7544
7547
  if (visited.has(target)) continue;
7545
7548
  visited.add(target);
7546
7549
  const isCycleMember = cycleParticipants.has(target);
7547
- out.push({ name: target, depth: cur.depth + 1, isCycleMember });
7550
+ out.push({ name: target, depth: cur.depth + 1, isCycleMember, parent: cur.name });
7548
7551
  queue.push({ name: target, depth: cur.depth + 1 });
7549
7552
  }
7550
7553
  }
@@ -7591,7 +7594,8 @@ function buildVisibleRows(props) {
7591
7594
  sharedSuffix,
7592
7595
  cycleChild: child.isCycleMember || void 0,
7593
7596
  itemIdx: childRec?.idx ?? -1,
7594
- rootName: key
7597
+ rootName: key,
7598
+ parentName: child.parent
7595
7599
  });
7596
7600
  });
7597
7601
  }
@@ -7674,13 +7678,19 @@ function buildVisibleRows(props) {
7674
7678
  injectedChildren.push({
7675
7679
  name: target,
7676
7680
  depth: parentDepth + 1,
7677
- isCycleChild: true
7681
+ isCycleChild: true,
7682
+ parent: parentName
7678
7683
  });
7679
7684
  }
7680
7685
  };
7681
7686
  emitCycleChildrenOf(root, 0);
7682
7687
  for (const c2 of closureChildren) {
7683
- injectedChildren.push({ name: c2.name, depth: c2.depth, isCycleChild: false });
7688
+ injectedChildren.push({
7689
+ name: c2.name,
7690
+ depth: c2.depth,
7691
+ isCycleChild: false,
7692
+ parent: c2.path[c2.path.length - 2] ?? root
7693
+ });
7684
7694
  emitCycleChildrenOf(c2.name, c2.depth);
7685
7695
  }
7686
7696
  const isLastAtDepth = (idx) => {
@@ -7714,7 +7724,8 @@ function buildVisibleRows(props) {
7714
7724
  sharedSuffix,
7715
7725
  cycleChild: child.isCycleChild || void 0,
7716
7726
  itemIdx: childRec?.idx ?? -1,
7717
- rootName: root
7727
+ rootName: root,
7728
+ parentName: child.parent
7718
7729
  });
7719
7730
  });
7720
7731
  }
@@ -7838,6 +7849,7 @@ function GroupedSidebar(props) {
7838
7849
  showFlatTier,
7839
7850
  viewMode,
7840
7851
  selectionStateByKey,
7852
+ excludedSlotEdges,
7841
7853
  aiFlaggedByKey,
7842
7854
  dimPredicate,
7843
7855
  visibleRows: providedRows,
@@ -7867,8 +7879,9 @@ function GroupedSidebar(props) {
7867
7879
  const rs = itemName ? renderStatusByKey?.get(itemName) : void 0;
7868
7880
  const badge = itemName ? previewBadge(previewAnnotationByKey?.get(itemName)) : null;
7869
7881
  const showInheritance = rs !== void 0 && row.kind !== "cycle" && row.kind !== "empty" && row.kind !== "group-root";
7870
- const supportsSelectionGlyph = selectionStateByKey !== void 0 && itemName !== void 0 && (row.kind === "standalone" || row.kind === "group-root" || row.kind === "group-child" || row.kind === "flat" || row.kind === "cycle");
7871
- const selState = supportsSelectionGlyph ? selectionStateByKey.get(itemName) ?? "undecided" : void 0;
7882
+ const supportsSelectionGlyph = selectionStateByKey !== void 0 && itemName !== void 0 && (row.kind === "standalone" || row.kind === "group-root" || row.kind === "group-child" || row.kind === "flat" || row.kind === "empty" || row.kind === "cycle");
7883
+ const edgeExcluded = row.kind === "group-child" && row.parentName !== void 0 && itemName !== void 0 && excludedSlotEdges?.has(slotEdgeKey(row.parentName, itemName)) === true;
7884
+ const selState = supportsSelectionGlyph ? edgeExcluded ? "undecided" : selectionStateByKey.get(itemName) ?? "undecided" : void 0;
7872
7885
  const isCycleRow = row.kind === "cycle";
7873
7886
  const selStyle = selectionGlyphStyleFor(selState, isCycleRow);
7874
7887
  const selGlyph = selStyle.glyph;
@@ -7897,7 +7910,7 @@ function GroupedSidebar(props) {
7897
7910
  color: isSelected ? PALETTE2.info : labelStyle.dim ? PALETTE2.muted : labelStyle.color,
7898
7911
  bold: isSelected || labelStyle.bold,
7899
7912
  inverse: false,
7900
- underline: isSelected && !focused,
7913
+ underline: isSelected && focused,
7901
7914
  wrap: wrapLabels ? "wrap" : "truncate",
7902
7915
  children: [
7903
7916
  " ",
@@ -8806,7 +8819,7 @@ function partitionDecisions(components, state) {
8806
8819
  if (state.get(c2.name) === "accepted") accepted.push(c2.name);
8807
8820
  else rejected.push(c2.name);
8808
8821
  }
8809
- return { accepted, rejected };
8822
+ return { accepted, rejected, excludedSlotEdges: [] };
8810
8823
  }
8811
8824
 
8812
8825
  // packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/use-scope-gate.ts
@@ -8814,6 +8827,7 @@ function useScopeGate({ components, onConfirm, onQuit }) {
8814
8827
  const { columns: totalWidth, rows: terminalRows } = useTerminalSize();
8815
8828
  const columnPlan = useMemo2(() => computeColumnWidths(totalWidth), [totalWidth]);
8816
8829
  const [decisions, setDecisions] = useState12(/* @__PURE__ */ new Map());
8830
+ const [excludedEdges, setExcludedEdges] = useState12(/* @__PURE__ */ new Set());
8817
8831
  const [nav, setNav] = useState12({ cursor: 0, scrollOffset: 0 });
8818
8832
  const [focusedColumn, setFocusedColumn] = useState12("main");
8819
8833
  const [addedComponentsCursor, setAddedComponentsCursor] = useState12(0);
@@ -8985,6 +8999,28 @@ function useScopeGate({ components, onConfirm, onQuit }) {
8985
8999
  return void 0;
8986
9000
  }
8987
9001
  };
9002
+ const focusedNestedEdge = () => {
9003
+ const row = visibleRows[safeCursor];
9004
+ if (row?.kind !== "group-child" || !row.parentName || row.itemIdx < 0) return void 0;
9005
+ const child = groupedItems[row.itemIdx]?.key;
9006
+ return child ? { parent: row.parentName, child } : void 0;
9007
+ };
9008
+ const setEdgeExcluded = (edge, excluded) => {
9009
+ setExcludedEdges((prev) => {
9010
+ const next = new Set(prev);
9011
+ const key = slotEdgeKey(edge.parent, edge.child);
9012
+ if (excluded) next.add(key);
9013
+ else next.delete(key);
9014
+ return next;
9015
+ });
9016
+ };
9017
+ const confirmedEdges = (rejected) => {
9018
+ const rejectedSet = new Set(rejected);
9019
+ return [...excludedEdges].map((key) => {
9020
+ const [parent, child] = key.split("\u2192");
9021
+ return { parent, child };
9022
+ }).filter((edge) => !rejectedSet.has(edge.parent) && !rejectedSet.has(edge.child));
9023
+ };
8988
9024
  const jumpCursorTo = (name) => {
8989
9025
  let idx = -1;
8990
9026
  for (let i = 0; i < visibleRows.length; i++) {
@@ -9084,7 +9120,10 @@ function useScopeGate({ components, onConfirm, onQuit }) {
9084
9120
  onQuit();
9085
9121
  return;
9086
9122
  case "confirm":
9087
- onConfirm(partitionDecisions(components, decisions));
9123
+ {
9124
+ const partition = partitionDecisions(components, decisions);
9125
+ onConfirm({ ...partition, excludedSlotEdges: confirmedEdges(partition.rejected) });
9126
+ }
9088
9127
  return;
9089
9128
  case "close-help":
9090
9129
  setShowHelp(false);
@@ -9132,11 +9171,18 @@ function useScopeGate({ components, onConfirm, onQuit }) {
9132
9171
  }
9133
9172
  return;
9134
9173
  case "accept": {
9174
+ const edge = focusedNestedEdge();
9175
+ if (edge) setEdgeExcluded(edge, false);
9135
9176
  const key = focusedRowKey();
9136
9177
  if (key) decide({ type: "accept", name: key });
9137
9178
  return;
9138
9179
  }
9139
9180
  case "reject": {
9181
+ const edge = focusedColumn === "main" ? focusedNestedEdge() : void 0;
9182
+ if (edge) {
9183
+ setEdgeExcluded(edge, true);
9184
+ return;
9185
+ }
9140
9186
  const key = focusedColumn === "added-components" ? addedComponents[safeAddedComponentsCursor]?.name : focusedRowKey();
9141
9187
  if (key) requestReject(key);
9142
9188
  return;
@@ -9238,6 +9284,7 @@ function useScopeGate({ components, onConfirm, onQuit }) {
9238
9284
  visibleCount,
9239
9285
  panelMaxRows,
9240
9286
  // sidebar
9287
+ excludedEdges,
9241
9288
  groupedItems,
9242
9289
  graph,
9243
9290
  hasGroupRoots,
@@ -9363,6 +9410,7 @@ function ScopeGateView({ components, onConfirm, onQuit }) {
9363
9410
  visibleCount: gate.visibleCount,
9364
9411
  showFlatTier: false,
9365
9412
  selectionStateByKey: gate.selectionStateByKey,
9413
+ excludedSlotEdges: gate.excludedEdges,
9366
9414
  aiFlaggedByKey: gate.aiFlaggedByKey,
9367
9415
  dimPredicate: gate.dimPredicate,
9368
9416
  visibleRows: gate.visibleRows,
@@ -9488,7 +9536,8 @@ function useScopeGateFlow(input, deps = realDeps2) {
9488
9536
  if (!confirmed || !cacheCheck.current) return;
9489
9537
  let current = true;
9490
9538
  void cacheCheck.current.then((cachedNames) => {
9491
- if (current) setScope({ ...confirmed, cachedNames });
9539
+ const accepted = new Set(confirmed.accepted);
9540
+ if (current) setScope({ ...confirmed, cachedNames: cachedNames.filter((name) => accepted.has(name)) });
9492
9541
  });
9493
9542
  return () => {
9494
9543
  current = false;
@@ -9541,6 +9590,8 @@ var ScopeSchema = z5.object({
9541
9590
  accepted: z5.array(z5.string()),
9542
9591
  /** Everything else at the gate, which counts as rejected. */
9543
9592
  rejected: z5.array(z5.string()),
9593
+ /** Slot edges the user removed at the gate. The child stays accepted; only that parent stops allowing it. */
9594
+ excludedSlotEdges: z5._default(z5.array(z5.object({ parent: z5.string(), child: z5.string() })), []),
9544
9595
  /**
9545
9596
  * Components the generation cache already holds, found by the check that ran while the gate was open and which has
9546
9597
  * finished (and restored them) before the wizard starts. Empty when the cache is off or the check failed.
package/dist/index.js CHANGED
@@ -10185,6 +10185,9 @@ var init_badge = __esm({
10185
10185
  import figures4 from "figures";
10186
10186
  import { Box as Box17, Text as Text19 } from "ink";
10187
10187
  import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
10188
+ function slotEdgeKey(parent, child) {
10189
+ return `${parent}\u2192${child}`;
10190
+ }
10188
10191
  function isEmpty(entry) {
10189
10192
  return Object.keys(entry.$properties ?? {}).length === 0 && Object.keys(entry.$slots ?? {}).length === 0;
10190
10193
  }
@@ -10294,7 +10297,7 @@ function buildVisibleRows(props) {
10294
10297
  if (visited.has(target)) continue;
10295
10298
  visited.add(target);
10296
10299
  const isCycleMember = cycleParticipants.has(target);
10297
- out.push({ name: target, depth: cur.depth + 1, isCycleMember });
10300
+ out.push({ name: target, depth: cur.depth + 1, isCycleMember, parent: cur.name });
10298
10301
  queue.push({ name: target, depth: cur.depth + 1 });
10299
10302
  }
10300
10303
  }
@@ -10341,7 +10344,8 @@ function buildVisibleRows(props) {
10341
10344
  sharedSuffix,
10342
10345
  cycleChild: child.isCycleMember || void 0,
10343
10346
  itemIdx: childRec?.idx ?? -1,
10344
- rootName: key
10347
+ rootName: key,
10348
+ parentName: child.parent
10345
10349
  });
10346
10350
  });
10347
10351
  }
@@ -10424,13 +10428,19 @@ function buildVisibleRows(props) {
10424
10428
  injectedChildren.push({
10425
10429
  name: target,
10426
10430
  depth: parentDepth + 1,
10427
- isCycleChild: true
10431
+ isCycleChild: true,
10432
+ parent: parentName
10428
10433
  });
10429
10434
  }
10430
10435
  };
10431
10436
  emitCycleChildrenOf(root, 0);
10432
10437
  for (const c2 of closureChildren) {
10433
- injectedChildren.push({ name: c2.name, depth: c2.depth, isCycleChild: false });
10438
+ injectedChildren.push({
10439
+ name: c2.name,
10440
+ depth: c2.depth,
10441
+ isCycleChild: false,
10442
+ parent: c2.path[c2.path.length - 2] ?? root
10443
+ });
10434
10444
  emitCycleChildrenOf(c2.name, c2.depth);
10435
10445
  }
10436
10446
  const isLastAtDepth = (idx) => {
@@ -10464,7 +10474,8 @@ function buildVisibleRows(props) {
10464
10474
  sharedSuffix,
10465
10475
  cycleChild: child.isCycleChild || void 0,
10466
10476
  itemIdx: childRec?.idx ?? -1,
10467
- rootName: root
10477
+ rootName: root,
10478
+ parentName: child.parent
10468
10479
  });
10469
10480
  });
10470
10481
  }
@@ -10588,6 +10599,7 @@ function GroupedSidebar(props) {
10588
10599
  showFlatTier,
10589
10600
  viewMode,
10590
10601
  selectionStateByKey,
10602
+ excludedSlotEdges,
10591
10603
  aiFlaggedByKey,
10592
10604
  dimPredicate,
10593
10605
  visibleRows: providedRows,
@@ -10617,8 +10629,9 @@ function GroupedSidebar(props) {
10617
10629
  const rs = itemName ? renderStatusByKey?.get(itemName) : void 0;
10618
10630
  const badge = itemName ? previewBadge(previewAnnotationByKey?.get(itemName)) : null;
10619
10631
  const showInheritance = rs !== void 0 && row.kind !== "cycle" && row.kind !== "empty" && row.kind !== "group-root";
10620
- const supportsSelectionGlyph = selectionStateByKey !== void 0 && itemName !== void 0 && (row.kind === "standalone" || row.kind === "group-root" || row.kind === "group-child" || row.kind === "flat" || row.kind === "cycle");
10621
- const selState = supportsSelectionGlyph ? selectionStateByKey.get(itemName) ?? "undecided" : void 0;
10632
+ const supportsSelectionGlyph = selectionStateByKey !== void 0 && itemName !== void 0 && (row.kind === "standalone" || row.kind === "group-root" || row.kind === "group-child" || row.kind === "flat" || row.kind === "empty" || row.kind === "cycle");
10633
+ const edgeExcluded = row.kind === "group-child" && row.parentName !== void 0 && itemName !== void 0 && excludedSlotEdges?.has(slotEdgeKey(row.parentName, itemName)) === true;
10634
+ const selState = supportsSelectionGlyph ? edgeExcluded ? "undecided" : selectionStateByKey.get(itemName) ?? "undecided" : void 0;
10622
10635
  const isCycleRow = row.kind === "cycle";
10623
10636
  const selStyle = selectionGlyphStyleFor(selState, isCycleRow);
10624
10637
  const selGlyph = selStyle.glyph;
@@ -10647,7 +10660,7 @@ function GroupedSidebar(props) {
10647
10660
  color: isSelected ? PALETTE2.info : labelStyle.dim ? PALETTE2.muted : labelStyle.color,
10648
10661
  bold: isSelected || labelStyle.bold,
10649
10662
  inverse: false,
10650
- underline: isSelected && !focused,
10663
+ underline: isSelected && focused,
10651
10664
  wrap: wrapLabels ? "wrap" : "truncate",
10652
10665
  children: [
10653
10666
  " ",
@@ -11688,7 +11701,7 @@ function partitionDecisions(components, state) {
11688
11701
  if (state.get(c2.name) === "accepted") accepted.push(c2.name);
11689
11702
  else rejected.push(c2.name);
11690
11703
  }
11691
- return { accepted, rejected };
11704
+ return { accepted, rejected, excludedSlotEdges: [] };
11692
11705
  }
11693
11706
  var init_state = __esm({
11694
11707
  "packages/experience-design-system-cli/src/tui/import/steps/07-scope-gate/state.ts"() {
@@ -11704,6 +11717,7 @@ function useScopeGate({ components, onConfirm, onQuit }) {
11704
11717
  const { columns: totalWidth, rows: terminalRows } = useTerminalSize();
11705
11718
  const columnPlan = useMemo2(() => computeColumnWidths(totalWidth), [totalWidth]);
11706
11719
  const [decisions, setDecisions] = useState12(/* @__PURE__ */ new Map());
11720
+ const [excludedEdges, setExcludedEdges] = useState12(/* @__PURE__ */ new Set());
11707
11721
  const [nav, setNav] = useState12({ cursor: 0, scrollOffset: 0 });
11708
11722
  const [focusedColumn, setFocusedColumn] = useState12("main");
11709
11723
  const [addedComponentsCursor, setAddedComponentsCursor] = useState12(0);
@@ -11875,6 +11889,28 @@ function useScopeGate({ components, onConfirm, onQuit }) {
11875
11889
  return void 0;
11876
11890
  }
11877
11891
  };
11892
+ const focusedNestedEdge = () => {
11893
+ const row = visibleRows[safeCursor];
11894
+ if (row?.kind !== "group-child" || !row.parentName || row.itemIdx < 0) return void 0;
11895
+ const child = groupedItems[row.itemIdx]?.key;
11896
+ return child ? { parent: row.parentName, child } : void 0;
11897
+ };
11898
+ const setEdgeExcluded = (edge, excluded) => {
11899
+ setExcludedEdges((prev) => {
11900
+ const next = new Set(prev);
11901
+ const key = slotEdgeKey(edge.parent, edge.child);
11902
+ if (excluded) next.add(key);
11903
+ else next.delete(key);
11904
+ return next;
11905
+ });
11906
+ };
11907
+ const confirmedEdges = (rejected) => {
11908
+ const rejectedSet = new Set(rejected);
11909
+ return [...excludedEdges].map((key) => {
11910
+ const [parent, child] = key.split("\u2192");
11911
+ return { parent, child };
11912
+ }).filter((edge) => !rejectedSet.has(edge.parent) && !rejectedSet.has(edge.child));
11913
+ };
11878
11914
  const jumpCursorTo = (name) => {
11879
11915
  let idx = -1;
11880
11916
  for (let i = 0; i < visibleRows.length; i++) {
@@ -11974,7 +12010,10 @@ function useScopeGate({ components, onConfirm, onQuit }) {
11974
12010
  onQuit();
11975
12011
  return;
11976
12012
  case "confirm":
11977
- onConfirm(partitionDecisions(components, decisions));
12013
+ {
12014
+ const partition = partitionDecisions(components, decisions);
12015
+ onConfirm({ ...partition, excludedSlotEdges: confirmedEdges(partition.rejected) });
12016
+ }
11978
12017
  return;
11979
12018
  case "close-help":
11980
12019
  setShowHelp(false);
@@ -12022,11 +12061,18 @@ function useScopeGate({ components, onConfirm, onQuit }) {
12022
12061
  }
12023
12062
  return;
12024
12063
  case "accept": {
12064
+ const edge = focusedNestedEdge();
12065
+ if (edge) setEdgeExcluded(edge, false);
12025
12066
  const key = focusedRowKey();
12026
12067
  if (key) decide({ type: "accept", name: key });
12027
12068
  return;
12028
12069
  }
12029
12070
  case "reject": {
12071
+ const edge = focusedColumn === "main" ? focusedNestedEdge() : void 0;
12072
+ if (edge) {
12073
+ setEdgeExcluded(edge, true);
12074
+ return;
12075
+ }
12030
12076
  const key = focusedColumn === "added-components" ? addedComponents[safeAddedComponentsCursor]?.name : focusedRowKey();
12031
12077
  if (key) requestReject(key);
12032
12078
  return;
@@ -12128,6 +12174,7 @@ function useScopeGate({ components, onConfirm, onQuit }) {
12128
12174
  visibleCount,
12129
12175
  panelMaxRows,
12130
12176
  // sidebar
12177
+ excludedEdges,
12131
12178
  groupedItems,
12132
12179
  graph,
12133
12180
  hasGroupRoots,
@@ -12240,6 +12287,7 @@ function ScopeGateView({ components, onConfirm, onQuit }) {
12240
12287
  visibleCount: gate.visibleCount,
12241
12288
  showFlatTier: false,
12242
12289
  selectionStateByKey: gate.selectionStateByKey,
12290
+ excludedSlotEdges: gate.excludedEdges,
12243
12291
  aiFlaggedByKey: gate.aiFlaggedByKey,
12244
12292
  dimPredicate: gate.dimPredicate,
12245
12293
  visibleRows: gate.visibleRows,
@@ -12430,7 +12478,8 @@ function useScopeGateFlow(input, deps = realDeps2) {
12430
12478
  if (!confirmed || !cacheCheck.current) return;
12431
12479
  let current = true;
12432
12480
  void cacheCheck.current.then((cachedNames) => {
12433
- if (current) setScope({ ...confirmed, cachedNames });
12481
+ const accepted = new Set(confirmed.accepted);
12482
+ if (current) setScope({ ...confirmed, cachedNames: cachedNames.filter((name) => accepted.has(name)) });
12434
12483
  });
12435
12484
  return () => {
12436
12485
  current = false;
@@ -12487,6 +12536,8 @@ var init_handoff = __esm({
12487
12536
  accepted: z5.array(z5.string()),
12488
12537
  /** Everything else at the gate, which counts as rejected. */
12489
12538
  rejected: z5.array(z5.string()),
12539
+ /** Slot edges the user removed at the gate. The child stays accepted; only that parent stops allowing it. */
12540
+ excludedSlotEdges: z5._default(z5.array(z5.object({ parent: z5.string(), child: z5.string() })), []),
12490
12541
  /**
12491
12542
  * Components the generation cache already holds, found by the check that ran while the gate was open and which has
12492
12543
  * finished (and restored them) before the wizard starts. Empty when the cache is off or the check failed.
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.37.1-dev-build-e5882940.0",
3
+ "version": "2.37.1-dev-build-7a46c9e6.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -27,6 +27,8 @@ export interface GroupedSidebarProps {
27
27
  alwaysExpanded?: boolean;
28
28
  showFlatTier?: boolean;
29
29
  selectionStateByKey?: Map<string, 'accepted' | 'rejected' | 'undecided'>;
30
+ /** `parent→child` slot edges the user removed; their nested rows render unchecked. */
31
+ excludedSlotEdges?: Set<string>;
30
32
  aiFlaggedByKey?: Map<string, boolean>;
31
33
  dimPredicate?: (componentKey: string) => boolean;
32
34
  viewMode?: 'grouped' | 'flat';
@@ -34,6 +36,7 @@ export interface GroupedSidebarProps {
34
36
  graph: ComponentGraphNode[];
35
37
  filterVisibleKeys?: Set<string>;
36
38
  }
39
+ export declare function slotEdgeKey(parent: string, child: string): string;
37
40
  type RowKind = 'cycle' | 'empty' | 'group-root' | 'group-child' | 'standalone' | 'flat' | 'flat-header';
38
41
  export interface VisibleRow {
39
42
  kind: RowKind;
@@ -45,6 +48,8 @@ export interface VisibleRow {
45
48
  cycleChild?: boolean;
46
49
  itemIdx: number;
47
50
  rootName?: string;
51
+ /** Direct parent of a nested row; identifies the slot edge the row stands for. */
52
+ parentName?: string;
48
53
  }
49
54
  export declare function buildVisibleRows(props: {
50
55
  items: GroupedSidebarItem[];
@@ -10,10 +10,17 @@ export type ScopeComponent = Omit<ScopeComponentRow, 'aiDecision' | 'aiReason' |
10
10
  slots?: ScopeComponentRow['slots'];
11
11
  };
12
12
  export type Decision = 'accepted' | 'rejected' | 'undecided';
13
+ /** One slot edge: `parent` allows `child` in a slot. */
14
+ export interface ParentChildEdge {
15
+ parent: string;
16
+ child: string;
17
+ }
13
18
  /** What the user confirmed. Becomes `ImportHandoff.scope`; the legacy wizard saves it and starts generation. */
14
19
  export interface ScopeDecisions {
15
20
  accepted: string[];
16
21
  rejected: string[];
22
+ /** Slot edges removed at the gate. The child keeps its own decision. */
23
+ excludedSlotEdges: ParentChildEdge[];
17
24
  }
18
25
  export type ScopeGateLoad = {
19
26
  ok: true;
@@ -20,6 +20,7 @@ export declare function useScopeGate({ components, onConfirm, onQuit }: UseScope
20
20
  panelLayout: import("./columns.js").ScopeGatePanelLayout;
21
21
  visibleCount: number;
22
22
  panelMaxRows: number;
23
+ excludedEdges: Set<string>;
23
24
  groupedItems: import("./graph/index.js").SidebarItem[];
24
25
  graph: import("./graph/index.js").ScopeGraph;
25
26
  hasGroupRoots: boolean;
@@ -28,6 +28,7 @@ export interface GroupedSidebarProps {
28
28
  alwaysExpanded?: boolean;
29
29
  showFlatTier?: boolean;
30
30
  selectionStateByKey?: Map<string, 'accepted' | 'rejected' | 'undecided'>;
31
+ excludedSlotEdges?: Set<string>;
31
32
  aiFlaggedByKey?: Map<string, boolean>;
32
33
  dimPredicate?: (componentKey: string) => boolean;
33
34
  viewMode?: 'grouped' | 'flat';
@@ -35,6 +36,7 @@ export interface GroupedSidebarProps {
35
36
  graph: ComponentGraphNode[];
36
37
  filterVisibleKeys?: Set<string>;
37
38
  }
39
+ export declare function slotEdgeKey(parent: string, child: string): string;
38
40
  type RowKind = 'cycle' | 'empty' | 'group-root' | 'group-child' | 'standalone' | 'flat' | 'flat-header';
39
41
  export interface VisibleRow {
40
42
  kind: RowKind;
@@ -46,6 +48,8 @@ export interface VisibleRow {
46
48
  cycleChild?: boolean;
47
49
  itemIdx: number;
48
50
  rootName?: string;
51
+ /** Direct parent of a nested row; identifies the slot edge the row stands for. */
52
+ parentName?: string;
49
53
  }
50
54
  export declare function buildVisibleRows(props: {
51
55
  items: GroupedSidebarItem[];
@@ -18,6 +18,10 @@ export interface HandoffScope {
18
18
  decisions: {
19
19
  accepted: string[];
20
20
  rejected: string[];
21
+ excludedSlotEdges: Array<{
22
+ parent: string;
23
+ child: string;
24
+ }>;
21
25
  };
22
26
  /** Components the cache check (finished and restored before the wizard started) found already generated. */
23
27
  cachedNames: string[];
@@ -1,8 +1,10 @@
1
+ import { type ParentChildEdge } from '../../session/db.js';
1
2
  export declare function runScopeGate(opts: {
2
3
  sessionId: string;
3
4
  decisions: {
4
5
  accepted: string[];
5
6
  rejected: string[];
7
+ excludedSlotEdges?: ParentChildEdge[];
6
8
  };
7
9
  onAdvanceToGenerate: (info: {
8
10
  sessionId: string;
@@ -3633,8 +3633,31 @@ function applyScopeDecisions(db, sessionId2, decisions) {
3633
3633
  ...accepted
3634
3634
  );
3635
3635
  }
3636
+ removeSlotAllowedComponents(db, sessionId2, decisions.excludedSlotEdges ?? [], rejected);
3636
3637
  db.prepare("UPDATE sessions SET updated_at = ? WHERE id = ?").run(now, sessionId2);
3637
3638
  }
3639
+ function removeSlotAllowedComponents(db, sessionId2, edges, rejectedNames) {
3640
+ if (edges.length === 0 && rejectedNames.length === 0) return;
3641
+ const componentId = db.prepare("SELECT component_id FROM raw_components WHERE session_id = ? AND name = ?");
3642
+ const removeEdge = db.prepare(
3643
+ "DELETE FROM raw_slot_allowed_components WHERE session_id = ? AND component_id = ? AND allowed_component = ?"
3644
+ );
3645
+ const removeEverywhere = db.prepare(
3646
+ "DELETE FROM raw_slot_allowed_components WHERE session_id = ? AND allowed_component = ?"
3647
+ );
3648
+ db.exec("BEGIN");
3649
+ try {
3650
+ for (const edge of edges) {
3651
+ const row = componentId.get(sessionId2, edge.parent);
3652
+ if (row) removeEdge.run(sessionId2, row.component_id, edge.child);
3653
+ }
3654
+ for (const name of rejectedNames) removeEverywhere.run(sessionId2, name);
3655
+ db.exec("COMMIT");
3656
+ } catch (e) {
3657
+ db.exec("ROLLBACK");
3658
+ throw e;
3659
+ }
3660
+ }
3638
3661
  function findLatestSessionForCommand(db, command) {
3639
3662
  return getLatestCompletedSessionForCommand(db, command);
3640
3663
  }
@@ -9864,7 +9887,7 @@ function scopeFromHandoff(handoff) {
9864
9887
  const { scope } = handoff;
9865
9888
  if (!scope) return null;
9866
9889
  return {
9867
- decisions: { accepted: scope.accepted, rejected: scope.rejected },
9890
+ decisions: { accepted: scope.accepted, rejected: scope.rejected, excludedSlotEdges: scope.excludedSlotEdges },
9868
9891
  cachedNames: scope.cachedNames
9869
9892
  };
9870
9893
  }
@@ -19395,6 +19418,9 @@ var init_Sidebar = __esm({
19395
19418
  import figures from "figures";
19396
19419
  import { Box as Box18, Text as Text19 } from "ink";
19397
19420
  import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
19421
+ function slotEdgeKey(parent, child) {
19422
+ return `${parent}\u2192${child}`;
19423
+ }
19398
19424
  function isEmpty(entry) {
19399
19425
  return Object.keys(entry.$properties ?? {}).length === 0 && Object.keys(entry.$slots ?? {}).length === 0;
19400
19426
  }
@@ -19504,7 +19530,7 @@ function buildVisibleRows(props) {
19504
19530
  if (visited.has(target)) continue;
19505
19531
  visited.add(target);
19506
19532
  const isCycleMember = cycleParticipants.has(target);
19507
- out.push({ name: target, depth: cur.depth + 1, isCycleMember });
19533
+ out.push({ name: target, depth: cur.depth + 1, isCycleMember, parent: cur.name });
19508
19534
  queue.push({ name: target, depth: cur.depth + 1 });
19509
19535
  }
19510
19536
  }
@@ -19551,7 +19577,8 @@ function buildVisibleRows(props) {
19551
19577
  sharedSuffix,
19552
19578
  cycleChild: child.isCycleMember || void 0,
19553
19579
  itemIdx: childRec?.idx ?? -1,
19554
- rootName: key
19580
+ rootName: key,
19581
+ parentName: child.parent
19555
19582
  });
19556
19583
  });
19557
19584
  }
@@ -19634,13 +19661,19 @@ function buildVisibleRows(props) {
19634
19661
  injectedChildren.push({
19635
19662
  name: target,
19636
19663
  depth: parentDepth + 1,
19637
- isCycleChild: true
19664
+ isCycleChild: true,
19665
+ parent: parentName
19638
19666
  });
19639
19667
  }
19640
19668
  };
19641
19669
  emitCycleChildrenOf(root, 0);
19642
19670
  for (const c2 of closureChildren) {
19643
- injectedChildren.push({ name: c2.name, depth: c2.depth, isCycleChild: false });
19671
+ injectedChildren.push({
19672
+ name: c2.name,
19673
+ depth: c2.depth,
19674
+ isCycleChild: false,
19675
+ parent: c2.path[c2.path.length - 2] ?? root
19676
+ });
19644
19677
  emitCycleChildrenOf(c2.name, c2.depth);
19645
19678
  }
19646
19679
  const isLastAtDepth = (idx) => {
@@ -19674,7 +19707,8 @@ function buildVisibleRows(props) {
19674
19707
  sharedSuffix,
19675
19708
  cycleChild: child.isCycleChild || void 0,
19676
19709
  itemIdx: childRec?.idx ?? -1,
19677
- rootName: root
19710
+ rootName: root,
19711
+ parentName: child.parent
19678
19712
  });
19679
19713
  });
19680
19714
  }
@@ -19798,6 +19832,7 @@ function GroupedSidebar(props) {
19798
19832
  showFlatTier,
19799
19833
  viewMode,
19800
19834
  selectionStateByKey,
19835
+ excludedSlotEdges,
19801
19836
  aiFlaggedByKey,
19802
19837
  dimPredicate,
19803
19838
  visibleRows: providedRows,
@@ -19827,8 +19862,9 @@ function GroupedSidebar(props) {
19827
19862
  const rs = itemName ? renderStatusByKey?.get(itemName) : void 0;
19828
19863
  const badge = itemName ? previewBadge(previewAnnotationByKey?.get(itemName)) : null;
19829
19864
  const showInheritance = rs !== void 0 && row.kind !== "cycle" && row.kind !== "empty" && row.kind !== "group-root";
19830
- const supportsSelectionGlyph = selectionStateByKey !== void 0 && itemName !== void 0 && (row.kind === "standalone" || row.kind === "group-root" || row.kind === "group-child" || row.kind === "flat" || row.kind === "cycle");
19831
- const selState = supportsSelectionGlyph ? selectionStateByKey.get(itemName) ?? "undecided" : void 0;
19865
+ const supportsSelectionGlyph = selectionStateByKey !== void 0 && itemName !== void 0 && (row.kind === "standalone" || row.kind === "group-root" || row.kind === "group-child" || row.kind === "flat" || row.kind === "empty" || row.kind === "cycle");
19866
+ const edgeExcluded = row.kind === "group-child" && row.parentName !== void 0 && itemName !== void 0 && excludedSlotEdges?.has(slotEdgeKey(row.parentName, itemName)) === true;
19867
+ const selState = supportsSelectionGlyph ? edgeExcluded ? "undecided" : selectionStateByKey.get(itemName) ?? "undecided" : void 0;
19832
19868
  const isCycleRow = row.kind === "cycle";
19833
19869
  const selStyle = selectionGlyphStyleFor(selState, isCycleRow);
19834
19870
  const selGlyph = selStyle.glyph;
@@ -19857,7 +19893,7 @@ function GroupedSidebar(props) {
19857
19893
  color: isSelected ? PALETTE.info : labelStyle.dim ? PALETTE.muted : labelStyle.color,
19858
19894
  bold: isSelected || labelStyle.bold,
19859
19895
  inverse: false,
19860
- underline: isSelected && !focused,
19896
+ underline: isSelected && focused,
19861
19897
  wrap: wrapLabels ? "wrap" : "truncate",
19862
19898
  children: [
19863
19899
  " ",
@@ -22261,8 +22297,8 @@ function FieldEditor({
22261
22297
  return /* @__PURE__ */ jsxs24(Box23, { flexDirection: "column", width, borderStyle: "single", borderColor: PALETTE.warning, children: [
22262
22298
  /* @__PURE__ */ jsx28(Text24, { bold: true, color: PALETTE.warning, children: "FIELD EDITOR \u2014 no fields" }),
22263
22299
  /* @__PURE__ */ jsx28(Text24, { color: PALETTE.warning, children: "\u26A0 No properties classified for this component. The LLM didn't find anything to classify." }),
22264
- /* @__PURE__ */ jsx28(Text24, { color: PALETTE.muted, children: "You can add fields manually below or reject this component." }),
22265
- /* @__PURE__ */ jsx28(Text24, { color: PALETTE.muted, children: "Enter to save \xB7 Esc to discard" })
22300
+ /* @__PURE__ */ jsx28(Text24, { color: PALETTE.muted, children: "There is nothing to edit here." }),
22301
+ /* @__PURE__ */ jsx28(Text24, { color: PALETTE.muted, children: active ? "[Esc] go back to the list" : "In the list: [r] reject this component \xB7 [a] accept it" })
22266
22302
  ] });
22267
22303
  }
22268
22304
  const hasEmptyProperties = props.length === 0 && slots.length === 0;
@@ -22477,7 +22513,7 @@ function FieldEditor({
22477
22513
  children: [
22478
22514
  hasEmptyProperties && /* @__PURE__ */ jsx28(Text24, { color: PALETTE.warning, children: "\u26A0 No properties classified for this component. The LLM didn't find anything to classify. Reject this component or add fields manually." }),
22479
22515
  header,
22480
- /* @__PURE__ */ jsx28(Box23, { flexDirection: "column", width: innerWidth, flexShrink: 0, children: focusLevel === "field" && !inComponentDesc && currentProp ? /* @__PURE__ */ jsx28(
22516
+ /* @__PURE__ */ jsx28(Box23, { flexDirection: "column", width: innerWidth, flexShrink: 0, children: focusLevel === "field" && !inComponentDesc && !inSlots && currentProp ? /* @__PURE__ */ jsx28(
22481
22517
  PropRow,
22482
22518
  {
22483
22519
  prop: currentProp,
@@ -23901,6 +23937,7 @@ function finalizeReviewSession(extractSessionId, components) {
23901
23937
  db.exec("ROLLBACK");
23902
23938
  throw error;
23903
23939
  }
23940
+ removeSlotAllowedComponents(db, extractSessionId, [], toReject);
23904
23941
  } finally {
23905
23942
  db.close();
23906
23943
  }
@@ -25270,6 +25307,28 @@ function GenerateReviewStepView({
25270
25307
  livePreviewHook.trigger();
25271
25308
  pushHistorySnapshot(next, "break-cycle-edge");
25272
25309
  };
25310
+ const handleRemoveSlotChild = (parentKey, childKey) => {
25311
+ const parent = components.find((component) => component.key === parentKey);
25312
+ if (!parent?.entry.$slots) return;
25313
+ const slots = {};
25314
+ for (const [slotName, slot] of Object.entries(parent.entry.$slots)) {
25315
+ slots[slotName] = Array.isArray(slot.$allowedComponents) ? { ...slot, $allowedComponents: slot.$allowedComponents.filter((value) => value !== childKey) } : slot;
25316
+ }
25317
+ const nextEntry = { ...parent.entry, $slots: slots };
25318
+ const next = components.map(
25319
+ (component) => component.key === parentKey ? { ...component, entry: nextEntry } : component
25320
+ );
25321
+ setComponents(next);
25322
+ const db = openPipelineDb();
25323
+ try {
25324
+ storeCDFComponents(db, extractSessionId, [{ key: parentKey, entry: nextEntry }]);
25325
+ } finally {
25326
+ db.close();
25327
+ }
25328
+ recomputeCycles(next);
25329
+ livePreviewHook.trigger();
25330
+ pushHistorySnapshot(next, "remove-slot-child");
25331
+ };
25273
25332
  const handleRejectComponent = (key) => {
25274
25333
  const rejectCascade = computeRejectCascade(key, componentGraph);
25275
25334
  const acceptCascade = computeAcceptCascade(key, componentGraph);
@@ -25598,6 +25657,11 @@ function GenerateReviewStepView({
25598
25657
  if (input === "r") {
25599
25658
  const current = components[selectedIdx];
25600
25659
  if (!current) return;
25660
+ const row = visibleRowsMemo[cursorRowIdx];
25661
+ if (row?.kind === "group-child" && row.parentName) {
25662
+ handleRemoveSlotChild(row.parentName, current.key);
25663
+ return;
25664
+ }
25601
25665
  handleRejectComponent(current.key);
25602
25666
  return;
25603
25667
  }
@@ -26243,7 +26307,6 @@ function WizardApp({
26243
26307
  tokensPath: ""
26244
26308
  });
26245
26309
  const allowEmptyDeleteAllRef = useRef8(false);
26246
- const generationCachePreflightRef = useRef8(null);
26247
26310
  const selectionToReviewStartedAtRef = useRef8(null);
26248
26311
  const credentialsReadyRef = useRef8(false);
26249
26312
  const agentAuthVerifiedRef = useRef8(false);
@@ -26730,7 +26793,6 @@ If you are using AWS Bedrock, run:
26730
26793
  rejectedCount: decisions.rejected.length
26731
26794
  }) : null;
26732
26795
  const cachePromise = Promise.resolve(new Set(handedOffCachedNames));
26733
- generationCachePreflightRef.current = { sessionId: sessionId2, promise: cachePromise };
26734
26796
  await runScopeGate({
26735
26797
  sessionId: sessionId2,
26736
26798
  decisions,
@@ -27305,7 +27367,6 @@ If using a custom host configuration, make sure the space exists on that host.`
27305
27367
  useEffect13(() => {
27306
27368
  if (state.step !== "credentials" || credentialsHandedOff.current) return;
27307
27369
  credentialsHandedOff.current = true;
27308
- if (process.env["EDS_IMPORT_SKIP_CREDENTIALS"] === "1") update({ credentialsSkipped: true });
27309
27370
  void advanceAfterCredentialsValidated();
27310
27371
  }, [state.step]);
27311
27372
  const noQuitSteps = [
@@ -99,10 +99,21 @@ export type ScopeComponentRow = {
99
99
  }>;
100
100
  };
101
101
  export declare function loadScopeComponents(db: DatabaseSync, sessionId: string): ScopeComponentRow[];
102
+ /** A parent component's slot allowing a child component. */
103
+ export interface ParentChildEdge {
104
+ parent: string;
105
+ child: string;
106
+ }
102
107
  export declare function applyScopeDecisions(db: DatabaseSync, sessionId: string, decisions: {
103
108
  accepted: string[];
104
109
  rejected: string[];
110
+ excludedSlotEdges?: ParentChildEdge[];
105
111
  }): void;
112
+ /**
113
+ * Drops excluded parent→child edges from slot allowed lists. Rejected
114
+ * components are also removed from every slot, since they will not exist.
115
+ */
116
+ export declare function removeSlotAllowedComponents(db: DatabaseSync, sessionId: string, edges: ParentChildEdge[], rejectedNames: string[]): void;
106
117
  export declare function findLatestSessionForCommand(db: DatabaseSync, command: CommandName): string | null;
107
118
  export declare function seedCDFFromPriorSession(db: DatabaseSync, targetSessionId: string): number;
108
119
  export declare function seedCDFFromPreviewResponse(db: DatabaseSync, sessionId: string, removedItems: ComponentTypeSummary[]): number;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.37.1-dev-build-e5882940.0",
3
+ "version": "2.37.1-dev-build-7a46c9e6.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.37.1-dev-build-e5882940.0",
3
+ "version": "2.37.1-dev-build-7a46c9e6.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -45,9 +45,9 @@
45
45
  "ts-morph": "^27.0.2",
46
46
  "typescript": "^5.9.3",
47
47
  "zod": "^4.6.5",
48
- "@contentful/experience-design-system-backend-pipeline": "2.37.1-dev-build-e5882940.0",
49
- "@contentful/experience-design-system-types": "2.37.1-dev-build-e5882940.0",
50
- "@contentful/experience-design-system-generation": "2.37.1-dev-build-e5882940.0"
48
+ "@contentful/experience-design-system-backend-pipeline": "2.37.1-dev-build-7a46c9e6.0",
49
+ "@contentful/experience-design-system-generation": "2.37.1-dev-build-7a46c9e6.0",
50
+ "@contentful/experience-design-system-types": "2.37.1-dev-build-7a46c9e6.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@tsconfig/node24": "^24.0.4",