@almadar/ui 2.50.0 → 2.51.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/avl/index.js CHANGED
@@ -22072,7 +22072,9 @@ var CodeBlock = React125__default.memo(
22072
22072
  showLanguageBadge = true,
22073
22073
  maxHeight = "60vh",
22074
22074
  foldable: foldableProp,
22075
- className
22075
+ className,
22076
+ editable = false,
22077
+ onChange
22076
22078
  }) => {
22077
22079
  const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
22078
22080
  const isOrb = language === "orb";
@@ -22243,7 +22245,37 @@ var CodeBlock = React125__default.memo(
22243
22245
  ]
22244
22246
  }
22245
22247
  ),
22246
- /* @__PURE__ */ jsx(
22248
+ editable ? (
22249
+ /* GAP-51: editable mode — composes the Textarea atom. Plain text editing,
22250
+ no Prism highlighting overlay (follow-up). The textarea is uncontrolled
22251
+ on the value side: we pass `code` as the initial value and forward
22252
+ every keystroke via onChange — the consumer is responsible for
22253
+ debouncing and re-deriving `code` only after the user stops typing
22254
+ so the cursor doesn't fight a re-render. */
22255
+ /* @__PURE__ */ jsx(
22256
+ Textarea,
22257
+ {
22258
+ defaultValue: code,
22259
+ onChange: (e) => onChange?.(e.target.value),
22260
+ spellCheck: false,
22261
+ style: {
22262
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
22263
+ fontSize: "13px",
22264
+ lineHeight: "1.5",
22265
+ backgroundColor: "#1e1e1e",
22266
+ color: "#e6e6e6",
22267
+ borderRadius: hasHeader ? "0 0 0.5rem 0.5rem" : "0.5rem",
22268
+ border: "none",
22269
+ padding: "1rem",
22270
+ resize: "none",
22271
+ minHeight: "160px",
22272
+ maxHeight,
22273
+ width: "100%",
22274
+ outline: "none"
22275
+ }
22276
+ }
22277
+ )
22278
+ ) : /* @__PURE__ */ jsx(
22247
22279
  "div",
22248
22280
  {
22249
22281
  ref: scrollRef,
@@ -22263,7 +22295,7 @@ var CodeBlock = React125__default.memo(
22263
22295
  )
22264
22296
  ] });
22265
22297
  },
22266
- (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable
22298
+ (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange
22267
22299
  );
22268
22300
  CodeBlock.displayName = "CodeBlock";
22269
22301
 
@@ -44581,7 +44613,7 @@ var Timeline = ({
44581
44613
  title && /* @__PURE__ */ jsx(Typography, { variant: "h5", weight: "semibold", children: title }),
44582
44614
  /* @__PURE__ */ jsx(VStack, { gap: "none", className: "relative", children: items.map((item, idx) => {
44583
44615
  const status = item.status || "pending";
44584
- const style = STATUS_STYLES3[status];
44616
+ const style = STATUS_STYLES3[status] || STATUS_STYLES3.pending;
44585
44617
  const ItemIcon = item.icon || style.icon;
44586
44618
  const isLast = idx === items.length - 1;
44587
44619
  return /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "relative", children: [
@@ -46435,6 +46467,9 @@ function OrbitalProvider({
46435
46467
  );
46436
46468
  }
46437
46469
  OrbitalProvider.displayName = "OrbitalProvider";
46470
+
46471
+ // runtime/OrbPreview.tsx
46472
+ init_useEventBus();
46438
46473
  function useResolvedSchema(schema, pageName) {
46439
46474
  const [loading, setLoading] = useState(true);
46440
46475
  const [error, setError] = useState(null);
@@ -47204,7 +47239,7 @@ function SlotBridge() {
47204
47239
  }, [slots, render, clear]);
47205
47240
  return null;
47206
47241
  }
47207
- function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
47242
+ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback }) {
47208
47243
  const slotsActions = useSlotsActions();
47209
47244
  const bridge = useServerBridge();
47210
47245
  const entityStore = useEntityStore();
@@ -47245,10 +47280,11 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
47245
47280
  const fallback = setTimeout(() => {
47246
47281
  if (!initSentRef.current) {
47247
47282
  sendEvent("INIT");
47283
+ onLocalFallback?.();
47248
47284
  }
47249
47285
  }, 5e3);
47250
47286
  return () => clearTimeout(fallback);
47251
- }, [traits2, orbitalNames, sendEvent]);
47287
+ }, [traits2, orbitalNames, sendEvent, onLocalFallback]);
47252
47288
  useEffect(() => {
47253
47289
  if (!bridge.connected || !orbitalNames?.length || initSentRef.current) return;
47254
47290
  initSentRef.current = true;
@@ -47294,7 +47330,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
47294
47330
  }, [bridge.connected, orbitalNames, bridge.sendEvent, slotsActions]);
47295
47331
  return null;
47296
47332
  }
47297
- function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate }) {
47333
+ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback }) {
47298
47334
  const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
47299
47335
  const allPageTraits = useMemo(() => {
47300
47336
  if (pageName && traits2.length > 0) return traits2;
@@ -47334,7 +47370,15 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate }) {
47334
47370
  }
47335
47371
  }, [mockKey, serverUrl, mockData, entityStore]);
47336
47372
  const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsx(SlotsProvider, { children: /* @__PURE__ */ jsxs(EntitySchemaProvider, { entities: Array.from(allEntities.values()), children: [
47337
- /* @__PURE__ */ jsx(TraitInitializer, { traits: allPageTraits, orbitalNames: serverUrl ? orbitalNames : void 0, onNavigate }),
47373
+ /* @__PURE__ */ jsx(
47374
+ TraitInitializer,
47375
+ {
47376
+ traits: allPageTraits,
47377
+ orbitalNames: serverUrl ? orbitalNames : void 0,
47378
+ onNavigate,
47379
+ onLocalFallback
47380
+ }
47381
+ ),
47338
47382
  /* @__PURE__ */ jsx(SlotBridge, {}),
47339
47383
  /* @__PURE__ */ jsx(Box, { className: "min-h-full p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) })
47340
47384
  ] }) }) });
@@ -47351,6 +47395,16 @@ function OrbPreview({
47351
47395
  className,
47352
47396
  serverUrl
47353
47397
  }) {
47398
+ const [localFallback, setLocalFallback] = useState(false);
47399
+ const eventBus = useEventBus();
47400
+ const handleLocalFallback = useCallback(() => {
47401
+ if (localFallback) return;
47402
+ setLocalFallback(true);
47403
+ eventBus.emit("UI:NOTIFY", {
47404
+ message: "Preview server unreachable \u2014 running locally without server-side state.",
47405
+ severity: "warning"
47406
+ });
47407
+ }, [localFallback, eventBus]);
47354
47408
  const parseResult = useMemo(() => {
47355
47409
  let parsed;
47356
47410
  if (typeof schema === "string") {
@@ -47408,13 +47462,26 @@ function OrbPreview({
47408
47462
  el.addEventListener("click", handler, true);
47409
47463
  return () => el.removeEventListener("click", handler, true);
47410
47464
  }, [pages, handleNavigate]);
47411
- return /* @__PURE__ */ jsx(
47465
+ return /* @__PURE__ */ jsxs(
47412
47466
  Box,
47413
47467
  {
47414
47468
  ref: containerRef,
47415
47469
  className: `overflow-auto border border-[var(--color-border)] rounded-[var(--radius-md)] ${className ?? ""}`,
47416
47470
  style: { height },
47417
- children: /* @__PURE__ */ jsx(OrbitalProvider, { initialData: effectiveMockData, skipTheme: true, verification: true, children: /* @__PURE__ */ jsx(UISlotProvider, { children: /* @__PURE__ */ jsx(SchemaRunner, { schema: parsedSchema, serverUrl, mockData: effectiveMockData, pageName: currentPage, onNavigate: handleNavigate }) }) })
47471
+ children: [
47472
+ localFallback && /* @__PURE__ */ jsx(Box, { className: "px-3 py-2 bg-[var(--color-warning)] bg-opacity-10 border-b border-[var(--color-warning)] flex items-center gap-2", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "text-[var(--color-warning-foreground)] flex-1", children: "Preview server unreachable \u2014 running locally. Server-side state and persistence are disabled." }) }),
47473
+ /* @__PURE__ */ jsx(OrbitalProvider, { initialData: effectiveMockData, skipTheme: true, verification: true, children: /* @__PURE__ */ jsx(UISlotProvider, { children: /* @__PURE__ */ jsx(
47474
+ SchemaRunner,
47475
+ {
47476
+ schema: parsedSchema,
47477
+ serverUrl,
47478
+ mockData: effectiveMockData,
47479
+ pageName: currentPage,
47480
+ onNavigate: handleNavigate,
47481
+ onLocalFallback: handleLocalFallback
47482
+ }
47483
+ ) }) })
47484
+ ]
47418
47485
  }
47419
47486
  );
47420
47487
  }
@@ -48292,6 +48359,11 @@ function OrbInspector({ node, schema, editable = false, onSchemaChange, onClose
48292
48359
  ] }),
48293
48360
  /* @__PURE__ */ jsx(Box, { className: "flex-1 overflow-y-auto", children: activeTab === "code" ? (
48294
48361
  /* ── Code Tab ── */
48362
+ /* GAP-51: when editable, the CodeBlock molecule renders the existing
48363
+ Textarea atom internally and forwards keystrokes via UI:CODE_CHANGE
48364
+ on the EventBus. The consumer (builder workspace) listens, debounces,
48365
+ parses via safeParseOrbitalSchema, and calls setSchema. Read-only
48366
+ consumers (editable=false) see the existing syntax-highlighted view. */
48295
48367
  /* @__PURE__ */ jsx(Box, { className: "p-2", children: /* @__PURE__ */ jsx(
48296
48368
  CodeBlock,
48297
48369
  {
@@ -48299,7 +48371,9 @@ function OrbInspector({ node, schema, editable = false, onSchemaChange, onClose
48299
48371
  language: "orb",
48300
48372
  showCopyButton: true,
48301
48373
  showLanguageBadge: true,
48302
- maxHeight: "100%"
48374
+ maxHeight: "100%",
48375
+ editable,
48376
+ onChange: editable ? (code) => eventBus.emit("UI:CODE_CHANGE", { code }) : void 0
48303
48377
  }
48304
48378
  ) })
48305
48379
  ) : (
@@ -48592,6 +48666,7 @@ function FlowCanvasInner({
48592
48666
  height = 500,
48593
48667
  onNodeClick,
48594
48668
  onLevelChange,
48669
+ onOrbitalDoubleClick,
48595
48670
  initialOrbital,
48596
48671
  initialLevel,
48597
48672
  initialSelectedNode,
@@ -48668,8 +48743,16 @@ function FlowCanvasInner({
48668
48743
  setExpandedOrbital(d.orbitalName ?? node.id);
48669
48744
  setLevel("expanded");
48670
48745
  onLevelChange?.("expanded", d.orbitalName ?? node.id);
48746
+ return;
48747
+ }
48748
+ if (level === "expanded") {
48749
+ const d = node.data;
48750
+ const orbitalName = d.orbitalName ?? node.id;
48751
+ if (orbitalName && onOrbitalDoubleClick) {
48752
+ onOrbitalDoubleClick(orbitalName);
48753
+ }
48671
48754
  }
48672
- }, [level, onLevelChange, atBehaviorLevel, composeLevel]);
48755
+ }, [level, onLevelChange, onOrbitalDoubleClick, atBehaviorLevel, composeLevel]);
48673
48756
  const handleNodeClick = useCallback((_, node) => {
48674
48757
  const nodeData = node.data;
48675
48758
  if (level === "expanded") {
@@ -48764,10 +48847,10 @@ function FlowCanvasInner({
48764
48847
  return /* @__PURE__ */ jsx(ScreenSizeContext.Provider, { value: screenSize, children: /* @__PURE__ */ jsx(PatternSelectionContext.Provider, { value: patternSelectionValue, children: /* @__PURE__ */ jsxs(
48765
48848
  Box,
48766
48849
  {
48767
- className: `flex ${className ?? ""}`,
48850
+ className: `flex h-full ${className ?? ""}`,
48768
48851
  style: { width, height },
48769
48852
  children: [
48770
- /* @__PURE__ */ jsxs(Box, { className: "relative flex-1 min-w-0", children: [
48853
+ /* @__PURE__ */ jsxs(Box, { className: "relative flex-1 min-w-0 h-full", children: [
48771
48854
  /* @__PURE__ */ jsxs(
48772
48855
  ReactFlow,
48773
48856
  {
@@ -48784,6 +48867,7 @@ function FlowCanvasInner({
48784
48867
  minZoom: 0.1,
48785
48868
  maxZoom: 2,
48786
48869
  fitView: true,
48870
+ fitViewOptions: { padding: 0.15 },
48787
48871
  nodesDraggable: true,
48788
48872
  elementsSelectable: true,
48789
48873
  proOptions: { hideAttribution: true },
@@ -49203,7 +49287,8 @@ var AvlOrbitalsCosmicZoom = ({
49203
49287
  color = "var(--color-primary, #4A90D9)",
49204
49288
  animated = true,
49205
49289
  width = "100%",
49206
- height = 450
49290
+ height = 450,
49291
+ highlightedOrbital
49207
49292
  }) => {
49208
49293
  const parsedSchema = useMemo(() => {
49209
49294
  if (typeof schemaProp === "string") return JSON.parse(schemaProp);
@@ -49257,43 +49342,49 @@ var AvlOrbitalsCosmicZoom = ({
49257
49342
  containerH
49258
49343
  }
49259
49344
  ),
49260
- orbitalViews.map((view) => /* @__PURE__ */ jsx(
49261
- Box,
49262
- {
49263
- role: "button",
49264
- tabIndex: 0,
49265
- onClick: () => handleSelect(view.name),
49266
- onKeyDown: (e) => {
49267
- if (e.key === "Enter" || e.key === " ") handleSelect(view.name);
49268
- },
49269
- "aria-label": `Orbital: ${view.name}`,
49270
- position: "absolute",
49271
- style: {
49272
- left: view.cx - UNIT_DISPLAY_W / 2,
49273
- top: view.cy - UNIT_DISPLAY_H / 2,
49274
- width: UNIT_DISPLAY_W,
49275
- height: UNIT_DISPLAY_H,
49276
- cursor: "pointer",
49277
- transition: "transform 0.2s ease, filter 0.2s ease",
49278
- transform: selected === view.name ? "scale(1.05)" : "scale(1)",
49279
- filter: selected && selected !== view.name ? "opacity(0.5)" : "none",
49280
- zIndex: selected === view.name ? 10 : 1
49345
+ orbitalViews.map((view) => {
49346
+ const isHighlighted = view.name === highlightedOrbital;
49347
+ return /* @__PURE__ */ jsx(
49348
+ Box,
49349
+ {
49350
+ role: "button",
49351
+ tabIndex: 0,
49352
+ onClick: () => handleSelect(view.name),
49353
+ onKeyDown: (e) => {
49354
+ if (e.key === "Enter" || e.key === " ") handleSelect(view.name);
49355
+ },
49356
+ "aria-label": `Orbital: ${view.name}${isHighlighted ? " (highlighted)" : ""}`,
49357
+ position: "absolute",
49358
+ style: {
49359
+ left: view.cx - UNIT_DISPLAY_W / 2,
49360
+ top: view.cy - UNIT_DISPLAY_H / 2,
49361
+ width: UNIT_DISPLAY_W,
49362
+ height: UNIT_DISPLAY_H,
49363
+ cursor: "pointer",
49364
+ transition: "transform 0.2s ease, filter 0.2s ease, box-shadow 0.3s ease",
49365
+ transform: selected === view.name ? "scale(1.05)" : "scale(1)",
49366
+ filter: selected && selected !== view.name ? "opacity(0.5)" : "none",
49367
+ // GAP-52: persistent highlight ring (independent from user selection)
49368
+ boxShadow: isHighlighted ? `0 0 0 3px ${color}, 0 0 24px 4px ${color}` : "none",
49369
+ borderRadius: isHighlighted ? "12px" : void 0,
49370
+ zIndex: isHighlighted ? 11 : selected === view.name ? 10 : 1
49371
+ },
49372
+ children: /* @__PURE__ */ jsx(
49373
+ AvlOrbitalUnit,
49374
+ {
49375
+ entityName: view.entityName,
49376
+ fields: view.fieldCount,
49377
+ persistence: view.persistence,
49378
+ traits: view.traits,
49379
+ pages: view.pages,
49380
+ color,
49381
+ animated: animated && (selected === view.name || isHighlighted)
49382
+ }
49383
+ )
49281
49384
  },
49282
- children: /* @__PURE__ */ jsx(
49283
- AvlOrbitalUnit,
49284
- {
49285
- entityName: view.entityName,
49286
- fields: view.fieldCount,
49287
- persistence: view.persistence,
49288
- traits: view.traits,
49289
- pages: view.pages,
49290
- color,
49291
- animated: animated && selected === view.name
49292
- }
49293
- )
49294
- },
49295
- view.name
49296
- )),
49385
+ view.name
49386
+ );
49387
+ }),
49297
49388
  selectedView && /* @__PURE__ */ jsx(
49298
49389
  InfoPanel,
49299
49390
  {
@@ -9209,7 +9209,9 @@ var CodeBlock = React90__namespace.default.memo(
9209
9209
  showLanguageBadge = true,
9210
9210
  maxHeight = "60vh",
9211
9211
  foldable: foldableProp,
9212
- className
9212
+ className,
9213
+ editable = false,
9214
+ onChange
9213
9215
  }) => {
9214
9216
  const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
9215
9217
  const isOrb = language === "orb";
@@ -9380,7 +9382,37 @@ var CodeBlock = React90__namespace.default.memo(
9380
9382
  ]
9381
9383
  }
9382
9384
  ),
9383
- /* @__PURE__ */ jsxRuntime.jsx(
9385
+ editable ? (
9386
+ /* GAP-51: editable mode — composes the Textarea atom. Plain text editing,
9387
+ no Prism highlighting overlay (follow-up). The textarea is uncontrolled
9388
+ on the value side: we pass `code` as the initial value and forward
9389
+ every keystroke via onChange — the consumer is responsible for
9390
+ debouncing and re-deriving `code` only after the user stops typing
9391
+ so the cursor doesn't fight a re-render. */
9392
+ /* @__PURE__ */ jsxRuntime.jsx(
9393
+ Textarea,
9394
+ {
9395
+ defaultValue: code,
9396
+ onChange: (e) => onChange?.(e.target.value),
9397
+ spellCheck: false,
9398
+ style: {
9399
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
9400
+ fontSize: "13px",
9401
+ lineHeight: "1.5",
9402
+ backgroundColor: "#1e1e1e",
9403
+ color: "#e6e6e6",
9404
+ borderRadius: hasHeader ? "0 0 0.5rem 0.5rem" : "0.5rem",
9405
+ border: "none",
9406
+ padding: "1rem",
9407
+ resize: "none",
9408
+ minHeight: "160px",
9409
+ maxHeight,
9410
+ width: "100%",
9411
+ outline: "none"
9412
+ }
9413
+ }
9414
+ )
9415
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
9384
9416
  "div",
9385
9417
  {
9386
9418
  ref: scrollRef,
@@ -9400,7 +9432,7 @@ var CodeBlock = React90__namespace.default.memo(
9400
9432
  )
9401
9433
  ] });
9402
9434
  },
9403
- (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable
9435
+ (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange
9404
9436
  );
9405
9437
  CodeBlock.displayName = "CodeBlock";
9406
9438
  init_Typography();
@@ -34914,7 +34946,7 @@ var Timeline = ({
34914
34946
  title && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h5", weight: "semibold", children: title }),
34915
34947
  /* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "none", className: "relative", children: items.map((item, idx) => {
34916
34948
  const status = item.status || "pending";
34917
- const style = STATUS_STYLES3[status];
34949
+ const style = STATUS_STYLES3[status] || STATUS_STYLES3.pending;
34918
34950
  const ItemIcon = item.icon || style.icon;
34919
34951
  const isLast = idx === items.length - 1;
34920
34952
  return /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "md", align: "start", className: "relative", children: [
@@ -9164,7 +9164,9 @@ var CodeBlock = React90__default.memo(
9164
9164
  showLanguageBadge = true,
9165
9165
  maxHeight = "60vh",
9166
9166
  foldable: foldableProp,
9167
- className
9167
+ className,
9168
+ editable = false,
9169
+ onChange
9168
9170
  }) => {
9169
9171
  const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
9170
9172
  const isOrb = language === "orb";
@@ -9335,7 +9337,37 @@ var CodeBlock = React90__default.memo(
9335
9337
  ]
9336
9338
  }
9337
9339
  ),
9338
- /* @__PURE__ */ jsx(
9340
+ editable ? (
9341
+ /* GAP-51: editable mode — composes the Textarea atom. Plain text editing,
9342
+ no Prism highlighting overlay (follow-up). The textarea is uncontrolled
9343
+ on the value side: we pass `code` as the initial value and forward
9344
+ every keystroke via onChange — the consumer is responsible for
9345
+ debouncing and re-deriving `code` only after the user stops typing
9346
+ so the cursor doesn't fight a re-render. */
9347
+ /* @__PURE__ */ jsx(
9348
+ Textarea,
9349
+ {
9350
+ defaultValue: code,
9351
+ onChange: (e) => onChange?.(e.target.value),
9352
+ spellCheck: false,
9353
+ style: {
9354
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
9355
+ fontSize: "13px",
9356
+ lineHeight: "1.5",
9357
+ backgroundColor: "#1e1e1e",
9358
+ color: "#e6e6e6",
9359
+ borderRadius: hasHeader ? "0 0 0.5rem 0.5rem" : "0.5rem",
9360
+ border: "none",
9361
+ padding: "1rem",
9362
+ resize: "none",
9363
+ minHeight: "160px",
9364
+ maxHeight,
9365
+ width: "100%",
9366
+ outline: "none"
9367
+ }
9368
+ }
9369
+ )
9370
+ ) : /* @__PURE__ */ jsx(
9339
9371
  "div",
9340
9372
  {
9341
9373
  ref: scrollRef,
@@ -9355,7 +9387,7 @@ var CodeBlock = React90__default.memo(
9355
9387
  )
9356
9388
  ] });
9357
9389
  },
9358
- (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable
9390
+ (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange
9359
9391
  );
9360
9392
  CodeBlock.displayName = "CodeBlock";
9361
9393
  init_Typography();
@@ -34869,7 +34901,7 @@ var Timeline = ({
34869
34901
  title && /* @__PURE__ */ jsx(Typography, { variant: "h5", weight: "semibold", children: title }),
34870
34902
  /* @__PURE__ */ jsx(VStack, { gap: "none", className: "relative", children: items.map((item, idx) => {
34871
34903
  const status = item.status || "pending";
34872
- const style = STATUS_STYLES3[status];
34904
+ const style = STATUS_STYLES3[status] || STATUS_STYLES3.pending;
34873
34905
  const ItemIcon = item.icon || style.icon;
34874
34906
  const isLast = idx === items.length - 1;
34875
34907
  return /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "start", className: "relative", children: [
@@ -23,5 +23,17 @@ export interface CodeBlockProps {
23
23
  foldable?: boolean;
24
24
  /** Additional CSS classes */
25
25
  className?: string;
26
+ /**
27
+ * GAP-51: when true, render an editable surface (composes the `Textarea` atom)
28
+ * instead of the syntax-highlighted read-only display. Folding + Prism
29
+ * highlighting are skipped in editable mode for the first cut. Default: false
30
+ * (existing read-only behavior unchanged).
31
+ */
32
+ editable?: boolean;
33
+ /**
34
+ * GAP-51: called with the new code on every keystroke when `editable === true`.
35
+ * Consumers should debounce + parse downstream — `CodeBlock` does not.
36
+ */
37
+ onChange?: (code: string) => void;
26
38
  }
27
39
  export declare const CodeBlock: React.NamedExoticComponent<CodeBlockProps>;
@@ -27,5 +27,12 @@ export interface AvlOrbitalsCosmicZoomProps {
27
27
  width?: number | string;
28
28
  /** Container height */
29
29
  height?: number | string;
30
+ /**
31
+ * GAP-52: name of the orbital to highlight with a persistent ring/glow.
32
+ * Independent from user-driven selection (click). Used by the builder workspace
33
+ * when entering cosmic mode from a focused orbital — the focused orbital is
34
+ * highlighted while the user can still click any other orbital to select it.
35
+ */
36
+ highlightedOrbital?: string;
30
37
  }
31
38
  export declare const AvlOrbitalsCosmicZoom: React.FC<AvlOrbitalsCosmicZoomProps>;
@@ -28,6 +28,16 @@ export interface FlowCanvasProps {
28
28
  transition?: string;
29
29
  }) => void;
30
30
  onLevelChange?: (level: ViewLevel, orbital?: string) => void;
31
+ /**
32
+ * GAP-52: fired when the user double-clicks an orbital while ALREADY at
33
+ * `level === 'expanded'`. Consumers (e.g. the builder workspace) use this as
34
+ * the trigger to enter cosmic mode (`AvlOrbitalsCosmicZoom`) for the focused
35
+ * orbital. This does NOT replace the existing overview→expanded drill —
36
+ * that path still fires `onLevelChange('expanded', ...)` as before.
37
+ * The callback runs unconditionally; persona / permission gating is the
38
+ * consumer's responsibility.
39
+ */
40
+ onOrbitalDoubleClick?: (orbital: string) => void;
31
41
  initialOrbital?: string;
32
42
  /** Start at Level 2 (expanded) when initialOrbital is set. Default: 'overview'. */
33
43
  initialLevel?: ViewLevel;
@@ -4094,7 +4094,9 @@ var CodeBlock = React114__namespace.default.memo(
4094
4094
  showLanguageBadge = true,
4095
4095
  maxHeight = "60vh",
4096
4096
  foldable: foldableProp,
4097
- className
4097
+ className,
4098
+ editable = false,
4099
+ onChange
4098
4100
  }) => {
4099
4101
  const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
4100
4102
  const isOrb = language === "orb";
@@ -4265,7 +4267,37 @@ var CodeBlock = React114__namespace.default.memo(
4265
4267
  ]
4266
4268
  }
4267
4269
  ),
4268
- /* @__PURE__ */ jsxRuntime.jsx(
4270
+ editable ? (
4271
+ /* GAP-51: editable mode — composes the Textarea atom. Plain text editing,
4272
+ no Prism highlighting overlay (follow-up). The textarea is uncontrolled
4273
+ on the value side: we pass `code` as the initial value and forward
4274
+ every keystroke via onChange — the consumer is responsible for
4275
+ debouncing and re-deriving `code` only after the user stops typing
4276
+ so the cursor doesn't fight a re-render. */
4277
+ /* @__PURE__ */ jsxRuntime.jsx(
4278
+ Textarea,
4279
+ {
4280
+ defaultValue: code,
4281
+ onChange: (e) => onChange?.(e.target.value),
4282
+ spellCheck: false,
4283
+ style: {
4284
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
4285
+ fontSize: "13px",
4286
+ lineHeight: "1.5",
4287
+ backgroundColor: "#1e1e1e",
4288
+ color: "#e6e6e6",
4289
+ borderRadius: hasHeader ? "0 0 0.5rem 0.5rem" : "0.5rem",
4290
+ border: "none",
4291
+ padding: "1rem",
4292
+ resize: "none",
4293
+ minHeight: "160px",
4294
+ maxHeight,
4295
+ width: "100%",
4296
+ outline: "none"
4297
+ }
4298
+ }
4299
+ )
4300
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
4269
4301
  "div",
4270
4302
  {
4271
4303
  ref: scrollRef,
@@ -4285,7 +4317,7 @@ var CodeBlock = React114__namespace.default.memo(
4285
4317
  )
4286
4318
  ] });
4287
4319
  },
4288
- (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable
4320
+ (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange
4289
4321
  );
4290
4322
  CodeBlock.displayName = "CodeBlock";
4291
4323
 
@@ -4049,7 +4049,9 @@ var CodeBlock = React114__default.memo(
4049
4049
  showLanguageBadge = true,
4050
4050
  maxHeight = "60vh",
4051
4051
  foldable: foldableProp,
4052
- className
4052
+ className,
4053
+ editable = false,
4054
+ onChange
4053
4055
  }) => {
4054
4056
  const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
4055
4057
  const isOrb = language === "orb";
@@ -4220,7 +4222,37 @@ var CodeBlock = React114__default.memo(
4220
4222
  ]
4221
4223
  }
4222
4224
  ),
4223
- /* @__PURE__ */ jsx(
4225
+ editable ? (
4226
+ /* GAP-51: editable mode — composes the Textarea atom. Plain text editing,
4227
+ no Prism highlighting overlay (follow-up). The textarea is uncontrolled
4228
+ on the value side: we pass `code` as the initial value and forward
4229
+ every keystroke via onChange — the consumer is responsible for
4230
+ debouncing and re-deriving `code` only after the user stops typing
4231
+ so the cursor doesn't fight a re-render. */
4232
+ /* @__PURE__ */ jsx(
4233
+ Textarea,
4234
+ {
4235
+ defaultValue: code,
4236
+ onChange: (e) => onChange?.(e.target.value),
4237
+ spellCheck: false,
4238
+ style: {
4239
+ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
4240
+ fontSize: "13px",
4241
+ lineHeight: "1.5",
4242
+ backgroundColor: "#1e1e1e",
4243
+ color: "#e6e6e6",
4244
+ borderRadius: hasHeader ? "0 0 0.5rem 0.5rem" : "0.5rem",
4245
+ border: "none",
4246
+ padding: "1rem",
4247
+ resize: "none",
4248
+ minHeight: "160px",
4249
+ maxHeight,
4250
+ width: "100%",
4251
+ outline: "none"
4252
+ }
4253
+ }
4254
+ )
4255
+ ) : /* @__PURE__ */ jsx(
4224
4256
  "div",
4225
4257
  {
4226
4258
  ref: scrollRef,
@@ -4240,7 +4272,7 @@ var CodeBlock = React114__default.memo(
4240
4272
  )
4241
4273
  ] });
4242
4274
  },
4243
- (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable
4275
+ (prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange
4244
4276
  );
4245
4277
  CodeBlock.displayName = "CodeBlock";
4246
4278