@contentful/experience-design-system-cli 2.34.5-dev-build-0dbc122c.0 → 2.34.5-dev-build-7ebabd5d.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.34.5-dev-build-0dbc122c.0",
3
+ "version": "2.34.5-dev-build-7ebabd5d.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/dist/src/index.js CHANGED
@@ -21404,9 +21404,9 @@ var init_scroll_offset = __esm({
21404
21404
  });
21405
21405
 
21406
21406
  // packages/experience-design-system-cli/src/analyze/select/tui/components/FieldEditor.tsx
21407
- import React14, { useEffect as useEffect8, useState as useState15 } from "react";
21407
+ import React14, { useEffect as useEffect8, useLayoutEffect as useLayoutEffect2, useState as useState15 } from "react";
21408
21408
  import figures4 from "figures";
21409
- import { Box as Box29, Text as Text30 } from "ink";
21409
+ import { Box as Box29, measureElement, Text as Text30 } from "ink";
21410
21410
  import {
21411
21411
  CDF_PROPERTY_TYPES,
21412
21412
  CDF_PROPERTY_CATEGORIES,
@@ -21438,7 +21438,10 @@ function parseToState(json) {
21438
21438
  try {
21439
21439
  parsed = JSON.parse(json);
21440
21440
  } catch (e) {
21441
- return { state: { componentDescription: "", props: [], slots: [] }, error: String(e) };
21441
+ return {
21442
+ state: { componentDescription: "", props: [], slots: [] },
21443
+ error: String(e)
21444
+ };
21442
21445
  }
21443
21446
  if (typeof parsed !== "object" || parsed === null) {
21444
21447
  return {
@@ -21564,13 +21567,23 @@ function InlinePropField({
21564
21567
  selected,
21565
21568
  focused = false,
21566
21569
  children,
21567
- flexible = false
21570
+ flexible = false,
21571
+ width
21568
21572
  }) {
21569
- return /* @__PURE__ */ jsxs30(Box29, { gap: 1, flexShrink: flexible ? 1 : 0, flexGrow: flexible ? 1 : 0, children: [
21570
- /* @__PURE__ */ jsxs30(Text30, { color: focused ? PALETTE.warning : void 0, bold: focused, dimColor: !selected && !focused, children: [
21571
- focused ? "\u203A " : " ",
21572
- label
21573
- ] }),
21573
+ return /* @__PURE__ */ jsxs30(Box29, { width, gap: 1, flexShrink: flexible ? 1 : 0, flexGrow: flexible ? 1 : 0, flexWrap: "wrap", children: [
21574
+ /* @__PURE__ */ jsxs30(
21575
+ Text30,
21576
+ {
21577
+ color: focused ? PALETTE.warning : void 0,
21578
+ bold: focused,
21579
+ dimColor: !selected && !focused,
21580
+ wrap: "truncate-end",
21581
+ children: [
21582
+ focused ? "\u203A " : " ",
21583
+ label
21584
+ ]
21585
+ }
21586
+ ),
21574
21587
  children
21575
21588
  ] });
21576
21589
  }
@@ -21579,15 +21592,12 @@ function DefaultValueRow({
21579
21592
  active,
21580
21593
  focused
21581
21594
  }) {
21582
- return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, gap: 1, children: [
21583
- /* @__PURE__ */ jsx33(DefaultLabel, { focused }),
21584
- active ? /* @__PURE__ */ jsx33(Picker, { value: display, active: true }) : /* @__PURE__ */ jsx33(Text30, { color: PALETTE.inverse, children: display })
21585
- ] });
21586
- }
21587
- function DefaultLabel({ focused }) {
21588
- return /* @__PURE__ */ jsxs30(Text30, { color: focused ? PALETTE.warning : void 0, bold: focused, dimColor: !focused, children: [
21589
- focused ? "\u203A " : " ",
21590
- "default:"
21595
+ return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, gap: 1, flexWrap: "wrap", flexShrink: 0, children: [
21596
+ /* @__PURE__ */ jsxs30(Text30, { color: focused ? PALETTE.warning : void 0, bold: focused, dimColor: !focused, children: [
21597
+ focused ? "\u203A " : " ",
21598
+ "default:"
21599
+ ] }),
21600
+ active ? /* @__PURE__ */ jsx33(Picker, { value: display, active: true }) : /* @__PURE__ */ jsx33(Text30, { color: PALETTE.inverse, wrap: "wrap", children: display })
21591
21601
  ] });
21592
21602
  }
21593
21603
  function RowLabel({ name, selected }) {
@@ -21668,7 +21678,7 @@ function DefaultSubRow({
21668
21678
  }) {
21669
21679
  const cursor = cursorVisible ? "\u2588" : " ";
21670
21680
  if (prop.type === "richtext" || prop.type === "media" || prop.type === "link") {
21671
- return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, gap: 1, children: [
21681
+ return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, gap: 1, flexShrink: 0, children: [
21672
21682
  /* @__PURE__ */ jsxs30(Text30, { color: focused ? PALETTE.warning : void 0, bold: focused, dimColor: !focused, children: [
21673
21683
  focused ? "\u203A " : " ",
21674
21684
  "default:"
@@ -21682,7 +21692,7 @@ function DefaultSubRow({
21682
21692
  }
21683
21693
  if (prop.type === "enum") {
21684
21694
  if (prop.values.length === 0) {
21685
- return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, gap: 1, children: [
21695
+ return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, gap: 1, flexShrink: 0, children: [
21686
21696
  /* @__PURE__ */ jsxs30(Text30, { color: focused ? PALETTE.warning : void 0, bold: focused, dimColor: !focused, children: [
21687
21697
  focused ? "\u203A " : " ",
21688
21698
  "default:"
@@ -21695,8 +21705,11 @@ function DefaultSubRow({
21695
21705
  }
21696
21706
  const value = typeof prop.default === "string" ? prop.default : "";
21697
21707
  if (active) {
21698
- return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, flexDirection: "row", children: [
21699
- /* @__PURE__ */ jsx33(DefaultLabel, { focused }),
21708
+ return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, flexDirection: "row", flexShrink: 0, children: [
21709
+ /* @__PURE__ */ jsxs30(Text30, { color: focused ? PALETTE.warning : void 0, bold: focused, dimColor: !focused, children: [
21710
+ focused ? "\u203A " : " ",
21711
+ "default:"
21712
+ ] }),
21700
21713
  /* @__PURE__ */ jsxs30(Box29, { flexGrow: 1, borderStyle: "round", borderColor: PALETTE.info, paddingX: 1, children: [
21701
21714
  /* @__PURE__ */ jsx33(Text30, { children: value.slice(0, textCursor) }),
21702
21715
  /* @__PURE__ */ jsx33(Text30, { inverse: cursorVisible, children: value[textCursor] ?? cursor }),
@@ -21704,8 +21717,11 @@ function DefaultSubRow({
21704
21717
  ] })
21705
21718
  ] });
21706
21719
  }
21707
- return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, gap: 1, children: [
21708
- /* @__PURE__ */ jsx33(DefaultLabel, { focused }),
21720
+ return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, gap: 1, flexShrink: 0, children: [
21721
+ /* @__PURE__ */ jsxs30(Text30, { color: focused ? PALETTE.warning : void 0, bold: focused, dimColor: !focused, children: [
21722
+ focused ? "\u203A " : " ",
21723
+ "default:"
21724
+ ] }),
21709
21725
  /* @__PURE__ */ jsx33(Text30, { color: value ? PALETTE.inverse : void 0, dimColor: !value, children: value || "(none)" })
21710
21726
  ] });
21711
21727
  }
@@ -21720,24 +21736,40 @@ function DescriptionField({
21720
21736
  compact = false
21721
21737
  }) {
21722
21738
  const cursor = cursorVisible ? "\u2588" : " ";
21723
- const outerWidth = width === void 0 ? void 0 : Math.max(1, width - 2);
21724
- const contentWidth = outerWidth === void 0 ? void 0 : Math.max(1, outerWidth - 2);
21725
21739
  if (compact) {
21726
- return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, width: outerWidth, children: [
21740
+ return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, width, flexShrink: 0, children: [
21727
21741
  /* @__PURE__ */ jsx33(Text30, { dimColor: true, children: ` ${label}` }),
21728
21742
  /* @__PURE__ */ jsx33(Text30, { wrap: "truncate-end", color: value ? PALETTE.success : void 0, dimColor: !value, children: ` ${value || "\u2014"}` })
21729
21743
  ] });
21730
21744
  }
21731
- return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, flexDirection: "column", width: outerWidth, children: [
21745
+ return /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, flexDirection: "column", width, flexShrink: 0, children: [
21732
21746
  /* @__PURE__ */ jsxs30(Text30, { color: focused ? PALETTE.warning : void 0, bold: focused, dimColor: !focused, children: [
21733
21747
  focused ? "\u203A " : " ",
21734
21748
  label
21735
21749
  ] }),
21736
- /* @__PURE__ */ jsx33(Box29, { width: contentWidth, borderStyle: "round", borderColor: focused ? PALETTE.info : PALETTE.border, paddingX: 1, children: editing ? /* @__PURE__ */ jsxs30(Fragment10, { children: [
21737
- /* @__PURE__ */ jsx33(Text30, { children: value.slice(0, textCursor) }),
21738
- /* @__PURE__ */ jsx33(Text30, { inverse: cursorVisible, children: value[textCursor] ?? cursor }),
21739
- /* @__PURE__ */ jsx33(Text30, { children: value.slice(textCursor + 1) })
21740
- ] }) : /* @__PURE__ */ jsx33(Text30, { color: PALETTE.success, wrap: "wrap", children: value || "\u2014" }) })
21750
+ /* @__PURE__ */ jsx33(
21751
+ Box29,
21752
+ {
21753
+ flexDirection: "column",
21754
+ borderStyle: "round",
21755
+ borderColor: focused ? PALETTE.info : PALETTE.border,
21756
+ paddingX: 1,
21757
+ flexShrink: 0,
21758
+ children: editing ? /* @__PURE__ */ jsx33(EditableDescription, { cursor, cursorVisible, value, textCursor }) : /* @__PURE__ */ jsx33(Text30, { color: PALETTE.success, wrap: "wrap", children: value || "\u2014" })
21759
+ }
21760
+ )
21761
+ ] });
21762
+ }
21763
+ function EditableDescription({
21764
+ cursor,
21765
+ cursorVisible,
21766
+ value,
21767
+ textCursor
21768
+ }) {
21769
+ return /* @__PURE__ */ jsxs30(Text30, { wrap: "wrap", children: [
21770
+ value.slice(0, textCursor),
21771
+ /* @__PURE__ */ jsx33(Text30, { inverse: cursorVisible, children: cursor }),
21772
+ value.slice(textCursor)
21741
21773
  ] });
21742
21774
  }
21743
21775
  function PropRow({
@@ -21752,28 +21784,30 @@ function PropRow({
21752
21784
  valueText,
21753
21785
  width,
21754
21786
  rationale,
21787
+ showRationale,
21755
21788
  rowKey
21756
21789
  }) {
21757
21790
  const descFocused = activeField === "description";
21758
21791
  const descActive = editingField && descFocused;
21759
- return /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", width, children: [
21760
- /* @__PURE__ */ jsxs30(Box29, { gap: 1, flexWrap: "wrap", children: [
21792
+ return /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", width, flexShrink: 0, children: [
21793
+ /* @__PURE__ */ jsxs30(Box29, { gap: 1, flexWrap: "wrap", width, flexShrink: 0, children: [
21761
21794
  /* @__PURE__ */ jsx33(RowLabel, { name: prop.name, selected }),
21762
- /* @__PURE__ */ jsx33(InlinePropField, { label: "type:", selected, focused: activeField === "type", children: editingField && activeField === "type" ? /* @__PURE__ */ jsx33(Picker, { value: prop.type, active: true }) : /* @__PURE__ */ jsx33(Text30, { color: selected ? PALETTE.warning : PALETTE.inverse, children: prop.type }) }),
21763
- /* @__PURE__ */ jsx33(
21764
- InlinePropField,
21765
- {
21766
- label: "category:",
21767
- selected,
21768
- focused: activeField === "category",
21769
- flexible: editingField && activeField === "category",
21770
- children: editingField && activeField === "category" ? /* @__PURE__ */ jsx33(Text30, { color: selected ? PALETTE.warning : PALETTE.inverse, bold: true, wrap: "wrap", children: `[Enter] switch to ${categorySwitchTarget(prop.category)} property` }) : /* @__PURE__ */ jsx33(Text30, { color: selected ? PALETTE.warning : PALETTE.inverse, children: prop.category })
21771
- }
21772
- ),
21773
- /* @__PURE__ */ jsx33(InlinePropField, { label: "req:", selected, focused: activeField === "required", children: /* @__PURE__ */ jsx33(Toggle, { value: prop.required, active: editingField && activeField === "required" }) }),
21774
- prop.type === "token" && /* @__PURE__ */ jsx33(InlinePropField, { label: "kind:", selected, focused: activeField === "tokenKind", children: editingField && activeField === "tokenKind" ? /* @__PURE__ */ jsx33(Picker, { value: prop.tokenKind || DESIGN_TOKEN_TYPES2[0], active: true }) : /* @__PURE__ */ jsx33(Text30, { color: selected ? PALETTE.success : PALETTE.inverse, children: prop.tokenKind || "\u2014" }) })
21795
+ /* @__PURE__ */ jsx33(InlinePropField, { label: "type:", selected, focused: activeField === "type", children: editingField && activeField === "type" ? /* @__PURE__ */ jsx33(Picker, { value: prop.type, active: true }) : /* @__PURE__ */ jsx33(Text30, { color: selected ? PALETTE.warning : PALETTE.inverse, children: prop.type }) })
21775
21796
  ] }),
21776
- prop.type === "enum" && /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, gap: 1, flexWrap: "wrap", children: [
21797
+ /* @__PURE__ */ jsx33(
21798
+ InlinePropField,
21799
+ {
21800
+ label: "category:",
21801
+ selected,
21802
+ focused: activeField === "category",
21803
+ flexible: editingField && activeField === "category",
21804
+ width,
21805
+ children: editingField && activeField === "category" ? /* @__PURE__ */ jsx33(Text30, { color: selected ? PALETTE.warning : PALETTE.inverse, bold: true, wrap: "wrap", children: `[Enter] switch to ${categorySwitchTarget(prop.category)} property` }) : /* @__PURE__ */ jsx33(Text30, { color: selected ? PALETTE.warning : PALETTE.inverse, wrap: "wrap", children: prop.category })
21806
+ }
21807
+ ),
21808
+ /* @__PURE__ */ jsx33(InlinePropField, { label: "req:", selected, focused: activeField === "required", width, children: /* @__PURE__ */ jsx33(Toggle, { value: prop.required, active: editingField && activeField === "required" }) }),
21809
+ prop.type === "token" && /* @__PURE__ */ jsx33(InlinePropField, { label: "kind:", selected, focused: activeField === "tokenKind", width, children: editingField && activeField === "tokenKind" ? /* @__PURE__ */ jsx33(Picker, { value: prop.tokenKind || DESIGN_TOKEN_TYPES2[0], active: true }) : /* @__PURE__ */ jsx33(Text30, { color: selected ? PALETTE.success : PALETTE.inverse, wrap: "wrap", children: prop.tokenKind || "\u2014" }) }),
21810
+ prop.type === "enum" && /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, flexDirection: "column", width, flexShrink: 0, children: [
21777
21811
  /* @__PURE__ */ jsxs30(
21778
21812
  Text30,
21779
21813
  {
@@ -21786,7 +21820,7 @@ function PropRow({
21786
21820
  ]
21787
21821
  }
21788
21822
  ),
21789
- /* @__PURE__ */ jsx33(Box29, { flexGrow: 1, children: /* @__PURE__ */ jsxs30(Text30, { color: selected ? PALETTE.warning : PALETTE.inverse, wrap: "wrap", children: [
21823
+ /* @__PURE__ */ jsx33(Box29, { paddingLeft: 2, width: Math.max(1, width - 4), children: /* @__PURE__ */ jsxs30(Text30, { color: selected ? PALETTE.warning : PALETTE.inverse, wrap: "wrap", children: [
21790
21824
  "[",
21791
21825
  prop.values.join(", "),
21792
21826
  "]"
@@ -21814,7 +21848,7 @@ function PropRow({
21814
21848
  compact: !selected
21815
21849
  }
21816
21850
  ),
21817
- selected && prop.type === "token" && prop.category === "design" && /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, flexDirection: "row", gap: 1, children: [
21851
+ selected && prop.type === "token" && prop.category === "design" && /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, flexDirection: "column", width, flexShrink: 0, children: [
21818
21852
  /* @__PURE__ */ jsxs30(
21819
21853
  Text30,
21820
21854
  {
@@ -21827,9 +21861,17 @@ function PropRow({
21827
21861
  ]
21828
21862
  }
21829
21863
  ),
21830
- editingField && activeField === "allowed" ? /* @__PURE__ */ jsx33(Box29, { flexGrow: 1, borderStyle: "round", borderColor: PALETTE.info, paddingX: 1, children: /* @__PURE__ */ jsx33(Text30, { dimColor: true, children: "press [t] to edit allowed tokens" }) }) : /* @__PURE__ */ jsx33(Text30, { color: prop.allowed.length > 0 ? PALETTE.info : void 0, dimColor: prop.allowed.length === 0, children: prop.allowed.length > 0 ? prop.allowed.join(", ") : "(any)" })
21864
+ editingField && activeField === "allowed" ? /* @__PURE__ */ jsx33(Box29, { width: Math.max(1, width - 4), borderStyle: "round", borderColor: PALETTE.info, paddingX: 1, children: /* @__PURE__ */ jsx33(Text30, { dimColor: true, children: "press [t] to edit allowed tokens" }) }) : /* @__PURE__ */ jsx33(
21865
+ Text30,
21866
+ {
21867
+ color: prop.allowed.length > 0 ? PALETTE.info : void 0,
21868
+ dimColor: prop.allowed.length === 0,
21869
+ wrap: "wrap",
21870
+ children: prop.allowed.length > 0 ? prop.allowed.join(", ") : "(any)"
21871
+ }
21872
+ )
21831
21873
  ] }),
21832
- selected && rationale && rationale.trim().length > 0 && /* @__PURE__ */ jsx33(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx33(Text30, { dimColor: true, children: (() => {
21874
+ selected && showRationale && rationale && rationale.trim().length > 0 && /* @__PURE__ */ jsx33(Box29, { paddingLeft: 2, children: /* @__PURE__ */ jsx33(Text30, { dimColor: true, children: (() => {
21833
21875
  const max = Math.max(8, width - 8);
21834
21876
  const text = `~ ${rationale}`;
21835
21877
  return text.length > max ? text.slice(0, max - 1) + "\u2026" : text;
@@ -21869,10 +21911,10 @@ function SlotRow({
21869
21911
  pickerCandidates,
21870
21912
  pickerCursor
21871
21913
  }) {
21872
- return /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", width, children: [
21873
- /* @__PURE__ */ jsxs30(Box29, { gap: 1, flexWrap: "wrap", children: [
21914
+ return /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", width, flexShrink: 0, children: [
21915
+ /* @__PURE__ */ jsxs30(Box29, { gap: 1, flexWrap: "wrap", width, flexShrink: 0, children: [
21874
21916
  /* @__PURE__ */ jsx33(RowLabel, { name: slot.name, selected }),
21875
- /* @__PURE__ */ jsx33(InlinePropField, { label: "req:", selected, focused: activeField === "required", children: /* @__PURE__ */ jsx33(Toggle, { value: slot.required, active: editingField && activeField === "required" }) })
21917
+ /* @__PURE__ */ jsx33(InlinePropField, { label: "req:", selected, focused: activeField === "required", width, children: /* @__PURE__ */ jsx33(Toggle, { value: slot.required, active: editingField && activeField === "required" }) })
21876
21918
  ] }),
21877
21919
  !selected && /* @__PURE__ */ jsxs30(Box29, { paddingLeft: 2, gap: 1, flexWrap: "wrap", children: [
21878
21920
  /* @__PURE__ */ jsxs30(
@@ -22070,6 +22112,8 @@ function FieldEditor({
22070
22112
  const [parseErr] = useState15(parseError);
22071
22113
  const [listScrollStart, setListScrollStart] = useState15(0);
22072
22114
  const initialFocusScrollApplied = React14.useRef(false);
22115
+ const [rowHeights, setRowHeights] = useState15({});
22116
+ const rowMeasureRefs = React14.useRef(/* @__PURE__ */ new Map());
22073
22117
  const initialFocus = (() => {
22074
22118
  if (initialFocusTarget?.kind === "description") {
22075
22119
  return {
@@ -22174,9 +22218,21 @@ function FieldEditor({
22174
22218
  );
22175
22219
  const propGroups = React14.useMemo(
22176
22220
  () => [
22177
- { kind: "content", label: "\u2500\u2500 CONTENT PROPERTIES", indexes: contentPropIndexes },
22178
- { kind: "design", label: "\u2500\u2500 DESIGN PROPERTIES", indexes: designPropIndexes },
22179
- { kind: "hidden", label: "\u2500\u2500 OTHER / HIDDEN", indexes: hiddenPropIndexes }
22221
+ {
22222
+ kind: "content",
22223
+ label: "\u2500\u2500 CONTENT PROPERTIES",
22224
+ indexes: contentPropIndexes
22225
+ },
22226
+ {
22227
+ kind: "design",
22228
+ label: "\u2500\u2500 DESIGN PROPERTIES",
22229
+ indexes: designPropIndexes
22230
+ },
22231
+ {
22232
+ kind: "hidden",
22233
+ label: "\u2500\u2500 OTHER / HIDDEN",
22234
+ indexes: hiddenPropIndexes
22235
+ }
22180
22236
  ],
22181
22237
  [contentPropIndexes, designPropIndexes, hiddenPropIndexes]
22182
22238
  );
@@ -22263,6 +22319,12 @@ function FieldEditor({
22263
22319
  }
22264
22320
  return;
22265
22321
  }
22322
+ if (key.ctrl && input === "s") {
22323
+ initialStateRef.current = editorState;
22324
+ onDirtyChange?.(false);
22325
+ onSave();
22326
+ return;
22327
+ }
22266
22328
  const inDescriptionTextEntryForHelp = focusLevel === "field" && editingField && activeField === "description";
22267
22329
  const inStringDefaultTextEntryForHelp = focusLevel === "field" && editingField && activeField === "default" && currentProp != null && (currentProp.type === "string" || currentProp.type === "token");
22268
22330
  const inValueListTextEntry = editingValue != null;
@@ -22384,12 +22446,6 @@ function FieldEditor({
22384
22446
  }
22385
22447
  return;
22386
22448
  }
22387
- if (key.ctrl && input === "s") {
22388
- initialStateRef.current = editorState;
22389
- onDirtyChange?.(false);
22390
- onSave();
22391
- return;
22392
- }
22393
22449
  const inStringDefaultTextEntry = focusLevel === "field" && editingField && activeField === "default" && currentProp != null && (currentProp.type === "string" || currentProp.type === "token");
22394
22450
  const rationaleKeyAllowed = !key.ctrl && !key.meta && !inDescriptionTextEntry && !inComponentDescTextEntry && !inStringDefaultTextEntry && !inValueListTextEntry;
22395
22451
  if (input === propRationaleKey && rationaleKeyAllowed && onTogglePropRationale) {
@@ -22716,18 +22772,18 @@ function FieldEditor({
22716
22772
  setValueCursor((c2) => c2 - 1);
22717
22773
  return;
22718
22774
  }
22719
- if (input === "K" && valueCursor > 0) {
22720
- const nextVals = swapValues(currentValueList, valueCursor - 1, valueCursor);
22721
- setCurrentValueList(nextVals);
22722
- setValueCursor((c2) => c2 - 1);
22723
- return;
22724
- }
22725
22775
  if (key.shift && key.downArrow && valueCursor < currentValueList.length - 1) {
22726
22776
  const nextVals = swapValues(currentValueList, valueCursor, valueCursor + 1);
22727
22777
  setCurrentValueList(nextVals);
22728
22778
  setValueCursor((c2) => c2 + 1);
22729
22779
  return;
22730
22780
  }
22781
+ if (input === "K" && valueCursor > 0) {
22782
+ const nextVals = swapValues(currentValueList, valueCursor - 1, valueCursor);
22783
+ setCurrentValueList(nextVals);
22784
+ setValueCursor((c2) => c2 - 1);
22785
+ return;
22786
+ }
22731
22787
  if (input === "J" && valueCursor < currentValueList.length - 1) {
22732
22788
  const nextVals = swapValues(currentValueList, valueCursor, valueCursor + 1);
22733
22789
  setCurrentValueList(nextVals);
@@ -22813,11 +22869,19 @@ function FieldEditor({
22813
22869
  rows.push({ kind: "component-description" });
22814
22870
  for (const group of propGroups.filter((candidate) => candidate.kind !== "hidden")) {
22815
22871
  if (group.indexes.length === 0) continue;
22816
- rows.push({ kind: "header", label: `${group.label} (${group.indexes.length}) `, section: group.kind });
22872
+ rows.push({
22873
+ kind: "header",
22874
+ label: `${group.label} (${group.indexes.length}) `,
22875
+ section: group.kind
22876
+ });
22817
22877
  group.indexes.forEach((idx) => rows.push({ kind: "prop", idx }));
22818
22878
  }
22819
22879
  if (slots.length > 0) {
22820
- rows.push({ kind: "header", label: `\u2500\u2500 SLOTS (${slots.length}) `, section: "slots" });
22880
+ rows.push({
22881
+ kind: "header",
22882
+ label: `\u2500\u2500 SLOTS (${slots.length}) `,
22883
+ section: "slots"
22884
+ });
22821
22885
  slots.forEach((_, i) => rows.push({ kind: "slot", idx: i }));
22822
22886
  }
22823
22887
  const hiddenGroup = propGroups.find((group) => group.kind === "hidden");
@@ -22832,28 +22896,150 @@ function FieldEditor({
22832
22896
  const selectedRowIdx = rows.findIndex(
22833
22897
  (r) => r.kind === "prop" && !inSlots && !inComponentDesc && r.idx === propIdx || r.kind === "slot" && inSlots && r.idx === slotIdx || r.kind === "component-description" && inComponentDesc
22834
22898
  );
22835
- const visibleRows = focusLevel === "field" || initialFocusTarget ? 1 : fixedHeight ? Math.max(1, Math.floor((height - 3) / 3)) : rows.length;
22899
+ const rowKey = (row, index) => {
22900
+ const selected = row.kind === "prop" && !inSlots && !inComponentDesc && row.idx === propIdx || row.kind === "slot" && inSlots && row.idx === slotIdx || row.kind === "component-description" && inComponentDesc;
22901
+ const base = row.kind === "component-description" || row.kind === "header" ? `${row.kind}-${index}` : `${row.kind}-${row.idx}`;
22902
+ return `${base}-${selected ? "selected" : "normal"}`;
22903
+ };
22904
+ const rowHeight = (row, index) => rowHeights[rowKey(row, index)] ?? 1;
22905
+ const contentHeight = Math.max(1, height - 2 - (hasEmptyProperties ? 1 : 0) - 1);
22906
+ const visibleEnd = (start) => {
22907
+ if (focusLevel === "field") return Math.min(rows.length, start + 1);
22908
+ let used = 0;
22909
+ let end2 = start;
22910
+ while (end2 < rows.length) {
22911
+ const nextHeight = rowHeight(rows[end2], end2);
22912
+ if (end2 > start && used + nextHeight > contentHeight) break;
22913
+ used += nextHeight;
22914
+ end2 += 1;
22915
+ }
22916
+ return Math.max(start + 1, end2);
22917
+ };
22836
22918
  useEffect8(() => {
22837
22919
  if (focusLevel === "field" || selectedRowIdx < 0) return;
22838
22920
  setListScrollStart((previous) => {
22839
- const maxStart = Math.max(0, rows.length - visibleRows);
22840
22921
  if (initialFocusTarget && !initialFocusScrollApplied.current) {
22841
22922
  initialFocusScrollApplied.current = true;
22842
- return Math.min(selectedRowIdx, maxStart);
22923
+ return Math.min(selectedRowIdx, Math.max(0, rows.length - 1));
22843
22924
  }
22844
- const clamped = Math.min(previous, maxStart);
22925
+ const clamped = Math.min(previous, Math.max(0, rows.length - 1));
22926
+ const end2 = visibleEnd(clamped);
22845
22927
  if (selectedRowIdx < clamped) return selectedRowIdx;
22846
- if (selectedRowIdx >= clamped + visibleRows) {
22847
- return Math.min(maxStart, selectedRowIdx - visibleRows + 1);
22928
+ if (selectedRowIdx >= end2) {
22929
+ let start = selectedRowIdx;
22930
+ let used = rowHeight(rows[selectedRowIdx], selectedRowIdx);
22931
+ while (start > 0) {
22932
+ const previousHeight = rowHeight(rows[start - 1], start - 1);
22933
+ if (used + previousHeight > contentHeight) break;
22934
+ start -= 1;
22935
+ used += previousHeight;
22936
+ }
22937
+ return start;
22848
22938
  }
22849
22939
  return clamped;
22850
22940
  });
22851
- }, [focusLevel, rows.length, selectedRowIdx, visibleRows]);
22852
- const scrollStart = Math.min(listScrollStart, Math.max(0, rows.length - visibleRows));
22853
- const nextHeader = rows.slice(scrollStart + visibleRows).find((row) => row.kind === "header");
22941
+ }, [contentHeight, focusLevel, rowHeights, rows, selectedRowIdx]);
22942
+ const scrollStart = Math.min(listScrollStart, Math.max(0, rows.length - 1));
22943
+ const end = visibleEnd(scrollStart);
22944
+ const nextHeader = rows.slice(end).find((row) => row.kind === "header");
22854
22945
  const categoryBelow = focusLevel !== "field" && nextHeader?.kind === "header" ? nextHeader.label.replace(/^──\s*/, "").trim() : null;
22855
- const visibleRowSlice = rows.slice(scrollStart, scrollStart + visibleRows);
22946
+ const visibleRowSlice = rows.slice(scrollStart, end);
22947
+ useLayoutEffect2(() => {
22948
+ const nextHeights = {};
22949
+ for (const [key, node] of rowMeasureRefs.current) {
22950
+ const measuredHeight = measureElement(node).height;
22951
+ if (measuredHeight > 0) nextHeights[key] = measuredHeight;
22952
+ }
22953
+ setRowHeights((previous) => {
22954
+ let changed = false;
22955
+ const next = { ...previous };
22956
+ for (const [key, height2] of Object.entries(nextHeights)) {
22957
+ if (next[key] !== height2) {
22958
+ next[key] = height2;
22959
+ changed = true;
22960
+ }
22961
+ }
22962
+ return changed ? next : previous;
22963
+ });
22964
+ });
22856
22965
  const focusedSlotPickerCandidates = focusLevel === "field" && inSlots && editingValue?.mode === "add" && activeField === "allowedComponents" && projectSlotGraph && currentComponentName && currentSlot ? computeAllowedComponentCandidates(projectSlotGraph, currentComponentName, slots, currentSlot.name) : null;
22966
+ const renderRow = (row, index) => {
22967
+ const key = rowKey(row, index);
22968
+ if (row.kind === "header") {
22969
+ return /* @__PURE__ */ jsx33(Text30, { bold: true, color: PALETTE.success, children: row.label }, key);
22970
+ }
22971
+ if (row.kind === "component-description") {
22972
+ const isSelected2 = inComponentDesc && active;
22973
+ const isEditing = isSelected2 && focusLevel === "field" && editingField && activeField === "description";
22974
+ return /* @__PURE__ */ jsx33(
22975
+ DescriptionField,
22976
+ {
22977
+ value: editorState.componentDescription,
22978
+ focused: isSelected2,
22979
+ editing: isEditing,
22980
+ textCursor,
22981
+ cursorVisible,
22982
+ width: innerWidth,
22983
+ label: "description:",
22984
+ compact: !isSelected2
22985
+ },
22986
+ key
22987
+ );
22988
+ }
22989
+ if (row.kind === "prop") {
22990
+ const p = props[row.idx];
22991
+ const isSelected2 = !inSlots && !inComponentDesc && row.idx === propIdx;
22992
+ const propMeta = metadata?.props?.[p.name];
22993
+ const commonRowProps2 = createCommonRowProps(
22994
+ isSelected2,
22995
+ focusLevel,
22996
+ editingField,
22997
+ textCursor,
22998
+ valueCursor,
22999
+ cursorVisible,
23000
+ editingValue,
23001
+ valueText,
23002
+ innerWidth
23003
+ );
23004
+ return /* @__PURE__ */ jsx33(
23005
+ PropRow,
23006
+ {
23007
+ prop: p,
23008
+ ...commonRowProps2,
23009
+ activeField: isSelected2 && focusLevel === "field" ? activeField : null,
23010
+ rationale: propMeta?.rationale ?? null,
23011
+ showRationale: showInlineRationales,
23012
+ rowKey: String(row.idx)
23013
+ },
23014
+ key
23015
+ );
23016
+ }
23017
+ const s = slots[row.idx];
23018
+ const isSelected = inSlots && row.idx === slotIdx;
23019
+ const slotPickerCandidates = isSelected && editingValue?.mode === "add" && activeField === "allowedComponents" && projectSlotGraph && currentComponentName ? computeAllowedComponentCandidates(projectSlotGraph, currentComponentName, slots, s.name) : null;
23020
+ const commonRowProps = createCommonRowProps(
23021
+ isSelected,
23022
+ focusLevel,
23023
+ editingField,
23024
+ textCursor,
23025
+ valueCursor,
23026
+ cursorVisible,
23027
+ editingValue,
23028
+ valueText,
23029
+ innerWidth
23030
+ );
23031
+ return /* @__PURE__ */ jsx33(
23032
+ SlotRow,
23033
+ {
23034
+ slot: s,
23035
+ ...commonRowProps,
23036
+ activeField: isSelected && focusLevel === "field" ? activeField : null,
23037
+ pickerCandidates: slotPickerCandidates,
23038
+ pickerCursor
23039
+ },
23040
+ key
23041
+ );
23042
+ };
22857
23043
  return /* @__PURE__ */ jsxs30(
22858
23044
  FixedPanel,
22859
23045
  {
@@ -22864,7 +23050,7 @@ function FieldEditor({
22864
23050
  borderColor: hasEmptyProperties ? PALETTE.warning : PALETTE.info,
22865
23051
  children: [
22866
23052
  hasEmptyProperties && /* @__PURE__ */ jsx33(Text30, { 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." }),
22867
- /* @__PURE__ */ jsx33(Box29, { flexDirection: "column", width: innerWidth, children: focusLevel === "field" && !inComponentDesc && currentProp ? /* @__PURE__ */ jsx33(
23053
+ /* @__PURE__ */ jsx33(Box29, { flexDirection: "column", width: innerWidth, flexShrink: 0, children: focusLevel === "field" && !inComponentDesc && currentProp ? /* @__PURE__ */ jsx33(
22868
23054
  PropRow,
22869
23055
  {
22870
23056
  prop: currentProp,
@@ -22877,7 +23063,8 @@ function FieldEditor({
22877
23063
  editingValue,
22878
23064
  valueText,
22879
23065
  width: innerWidth,
22880
- rationale: metadata?.props?.[currentProp.name]?.rationale ?? null
23066
+ rationale: metadata?.props?.[currentProp.name]?.rationale ?? null,
23067
+ showRationale: showInlineRationales
22881
23068
  }
22882
23069
  ) : focusLevel === "field" && inSlots && currentSlot ? /* @__PURE__ */ jsx33(
22883
23070
  SlotRow,
@@ -22895,100 +23082,41 @@ function FieldEditor({
22895
23082
  pickerCandidates: focusedSlotPickerCandidates,
22896
23083
  pickerCursor
22897
23084
  }
22898
- ) : visibleRowSlice.map((row, i) => {
22899
- if (row.kind === "header") {
22900
- return /* @__PURE__ */ jsx33(Text30, { bold: true, color: PALETTE.success, children: row.label }, `header-${i}`);
22901
- }
22902
- if (row.kind === "component-description") {
22903
- const isSelected2 = inComponentDesc && active;
22904
- const isEditing = isSelected2 && focusLevel === "field" && editingField && activeField === "description";
22905
- const desc = editorState.componentDescription;
22906
- return /* @__PURE__ */ jsx33(
22907
- DescriptionField,
22908
- {
22909
- value: desc,
22910
- focused: isSelected2,
22911
- editing: isEditing,
22912
- textCursor,
22913
- cursorVisible,
22914
- width: innerWidth,
22915
- label: "description:",
22916
- compact: !isSelected2
22917
- },
22918
- `component-description-${i}`
22919
- );
22920
- }
22921
- if (row.kind === "prop") {
22922
- const p = props[row.idx];
22923
- const isSelected2 = !inSlots && !inComponentDesc && row.idx === propIdx;
22924
- const propMeta = metadata?.props?.[p.name];
22925
- const commonRowProps2 = createCommonRowProps(
22926
- isSelected2,
22927
- focusLevel,
22928
- editingField,
22929
- textCursor,
22930
- valueCursor,
22931
- cursorVisible,
22932
- editingValue,
22933
- valueText,
22934
- innerWidth
22935
- );
22936
- return /* @__PURE__ */ jsx33(
22937
- PropRow,
22938
- {
22939
- prop: p,
22940
- ...commonRowProps2,
22941
- activeField: isSelected2 && focusLevel === "field" ? activeField : null,
22942
- rationale: showInlineRationales ? propMeta?.rationale ?? null : null,
22943
- rowKey: String(row.idx)
22944
- },
22945
- `prop-${row.idx}`
22946
- );
22947
- }
22948
- const s = slots[row.idx];
22949
- const isSelected = inSlots && row.idx === slotIdx;
22950
- const slotPickerCandidates = isSelected && editingValue?.mode === "add" && activeField === "allowedComponents" && projectSlotGraph && currentComponentName ? computeAllowedComponentCandidates(projectSlotGraph, currentComponentName, slots, s.name) : null;
22951
- const commonRowProps = createCommonRowProps(
22952
- isSelected,
22953
- focusLevel,
22954
- editingField,
22955
- textCursor,
22956
- valueCursor,
22957
- cursorVisible,
22958
- editingValue,
22959
- valueText,
22960
- innerWidth
22961
- );
23085
+ ) : visibleRowSlice.map((row, index) => {
23086
+ const absoluteIndex = scrollStart + index;
23087
+ const key = rowKey(row, absoluteIndex);
22962
23088
  return /* @__PURE__ */ jsx33(
22963
- SlotRow,
23089
+ Box29,
22964
23090
  {
22965
- slot: s,
22966
- ...commonRowProps,
22967
- activeField: isSelected && focusLevel === "field" ? activeField : null,
22968
- pickerCandidates: slotPickerCandidates,
22969
- pickerCursor
23091
+ ref: (node) => {
23092
+ if (node) rowMeasureRefs.current.set(key, node);
23093
+ else rowMeasureRefs.current.delete(key);
23094
+ },
23095
+ width: innerWidth,
23096
+ flexShrink: 0,
23097
+ children: renderRow(row, absoluteIndex)
22970
23098
  },
22971
- `slot-${row.idx}`
23099
+ `visible-${key}`
22972
23100
  );
22973
23101
  }) }),
22974
23102
  categoryBelow && /* @__PURE__ */ jsx33(Text30, { color: PALETTE.success, bold: true, children: `(${categoryBelow} below)` }),
22975
23103
  sourceOpen && !onToggleSourceExternal && (() => {
22976
23104
  const propMeta = !inSlots && !inComponentDesc && currentProp ? metadata?.props?.[currentProp.name] : void 0;
22977
23105
  const start = propMeta?.sourceStartLine ?? null;
22978
- const end = propMeta?.sourceEndLine ?? null;
23106
+ const end2 = propMeta?.sourceEndLine ?? null;
22979
23107
  const path = metadata?.sourcePath ?? null;
22980
23108
  const src = metadata?.componentSource ?? null;
22981
23109
  const headerPath = path ?? "<unknown source path>";
22982
- if (!start || !end || !src) {
23110
+ if (!start || !end2 || !src) {
22983
23111
  return /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", borderStyle: "single", borderColor: "gray", paddingX: 1, children: [
22984
23112
  /* @__PURE__ */ jsx33(Text30, { dimColor: true, bold: true, children: `source: ${headerPath}` }),
22985
23113
  /* @__PURE__ */ jsx33(Text30, { dimColor: true, children: "(no source location captured for this prop)" }),
22986
23114
  /* @__PURE__ */ jsx33(Text30, { dimColor: true, children: "[s] close" })
22987
23115
  ] });
22988
23116
  }
22989
- const lines = src.split("\n").slice(Math.max(0, start - 1), end);
23117
+ const lines = src.split("\n").slice(Math.max(0, start - 1), end2);
22990
23118
  return /* @__PURE__ */ jsxs30(Box29, { flexDirection: "column", borderStyle: "single", borderColor: "gray", paddingX: 1, children: [
22991
- /* @__PURE__ */ jsx33(Text30, { dimColor: true, bold: true, children: `${headerPath}: lines ${start}\u2013${end}` }),
23119
+ /* @__PURE__ */ jsx33(Text30, { dimColor: true, bold: true, children: `${headerPath}: lines ${start}\u2013${end2}` }),
22992
23120
  lines.map((ln, i) => /* @__PURE__ */ jsx33(Text30, { dimColor: true, children: ln }, `source-line-${i}`)),
22993
23121
  /* @__PURE__ */ jsx33(Text30, { dimColor: true, children: "[s] close \xB7 [Esc] close" })
22994
23122
  ] });
@@ -23015,7 +23143,6 @@ function FieldEditor({
23015
23143
  /* @__PURE__ */ jsx33(Text30, { children: " " }),
23016
23144
  /* @__PURE__ */ jsx33(Text30, { bold: true, children: "Panels" }),
23017
23145
  /* @__PURE__ */ jsx33(Text30, { children: " s toggle source-view for the current prop" }),
23018
- /* @__PURE__ */ jsx33(Text30, { children: " Ctrl+S save field edits" }),
23019
23146
  /* @__PURE__ */ jsx33(Text30, { children: " " + propRationaleKey.padEnd(16) + " toggle prop rationale panel" }),
23020
23147
  /* @__PURE__ */ jsx33(Text30, { children: " " + componentRationaleKey.padEnd(16) + " toggle component rationale panel" }),
23021
23148
  /* @__PURE__ */ jsx33(Text30, { children: " ? toggle this overlay" }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentful/experience-design-system-cli",
3
- "version": "2.34.5-dev-build-0dbc122c.0",
3
+ "version": "2.34.5-dev-build-7ebabd5d.0",
4
4
  "description": "Contentful Experiences design system import CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -41,8 +41,8 @@
41
41
  "svelte": "^5.56.4",
42
42
  "ts-morph": "^27.0.2",
43
43
  "typescript": "^5.9.3",
44
- "@contentful/experience-design-system-types": "2.34.5-dev-build-0dbc122c.0",
45
- "@contentful/experience-design-system-cli-v2": "2.34.5-dev-build-0dbc122c.0"
44
+ "@contentful/experience-design-system-cli-v2": "2.34.5-dev-build-7ebabd5d.0",
45
+ "@contentful/experience-design-system-types": "2.34.5-dev-build-7ebabd5d.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@tsconfig/node24": "^24.0.4",
@@ -54,9 +54,9 @@
54
54
  "ink-testing-library": "^4.0.0",
55
55
  "typescript-eslint": "^8.67.0",
56
56
  "vitest": "^4.0.16",
57
- "@contentful/experience-design-system-extraction": "2.34.5-dev-build-0dbc122c.0",
58
- "@contentful/experience-design-system-client": "2.34.5-dev-build-0dbc122c.0",
59
- "@contentful/experience-design-system-generation": "2.34.5-dev-build-0dbc122c.0"
57
+ "@contentful/experience-design-system-client": "2.34.5-dev-build-7ebabd5d.0",
58
+ "@contentful/experience-design-system-extraction": "2.34.5-dev-build-7ebabd5d.0",
59
+ "@contentful/experience-design-system-generation": "2.34.5-dev-build-7ebabd5d.0"
60
60
  },
61
61
  "repository": {
62
62
  "type": "git",