@almadar/ui 5.146.2 → 5.147.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
@@ -29887,7 +29887,12 @@ function daysAgo(n) {
29887
29887
  d.setDate(d.getDate() - n);
29888
29888
  return d;
29889
29889
  }
29890
- var DEFAULT_PRESETS, DateRangePicker;
29890
+ function resolvePresetRange(preset) {
29891
+ if (typeof preset.range === "function") return preset.range();
29892
+ if (preset.range) return preset.range;
29893
+ return TOKEN_RANGES[preset.value]?.() ?? null;
29894
+ }
29895
+ var TOKEN_RANGES, DEFAULT_PRESETS, DateRangePicker;
29891
29896
  var init_DateRangePicker = __esm({
29892
29897
  "components/core/molecules/DateRangePicker.tsx"() {
29893
29898
  "use client";
@@ -29897,32 +29902,19 @@ var init_DateRangePicker = __esm({
29897
29902
  init_Stack();
29898
29903
  init_Typography();
29899
29904
  init_useEventBus();
29905
+ TOKEN_RANGES = {
29906
+ "7d": () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) }),
29907
+ "30d": () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) }),
29908
+ month: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) }),
29909
+ quarter: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) }),
29910
+ ytd: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
29911
+ };
29900
29912
  DEFAULT_PRESETS = [
29901
- {
29902
- label: "Last 7 days",
29903
- value: "7d",
29904
- range: () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) })
29905
- },
29906
- {
29907
- label: "Last 30 days",
29908
- value: "30d",
29909
- range: () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) })
29910
- },
29911
- {
29912
- label: "This Month",
29913
- value: "month",
29914
- range: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
29915
- },
29916
- {
29917
- label: "This Quarter",
29918
- value: "quarter",
29919
- range: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
29920
- },
29921
- {
29922
- label: "YTD",
29923
- value: "ytd",
29924
- range: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
29925
- }
29913
+ { label: "Last 7 days", value: "7d" },
29914
+ { label: "Last 30 days", value: "30d" },
29915
+ { label: "This Month", value: "month" },
29916
+ { label: "This Quarter", value: "quarter" },
29917
+ { label: "YTD", value: "ytd" }
29926
29918
  ];
29927
29919
  DateRangePicker = ({
29928
29920
  from: fromProp,
@@ -29963,7 +29955,8 @@ var init_DateRangePicker = __esm({
29963
29955
  );
29964
29956
  const handlePreset = useCallback(
29965
29957
  (preset) => {
29966
- const range = preset.range();
29958
+ const range = resolvePresetRange(preset);
29959
+ if (range === null) return;
29967
29960
  setFrom(range.from);
29968
29961
  setTo(range.to);
29969
29962
  setActivePreset(preset.value);
@@ -29971,8 +29964,12 @@ var init_DateRangePicker = __esm({
29971
29964
  },
29972
29965
  [emit]
29973
29966
  );
29967
+ const renderablePresets = useMemo(
29968
+ () => presets.filter((p) => p.range !== void 0 || TOKEN_RANGES[p.value] !== void 0),
29969
+ [presets]
29970
+ );
29974
29971
  const presetButtons = useMemo(
29975
- () => presets.map((preset) => /* @__PURE__ */ jsx(
29972
+ () => renderablePresets.map((preset) => /* @__PURE__ */ jsx(
29976
29973
  Button,
29977
29974
  {
29978
29975
  variant: activePreset === preset.value ? "primary" : "ghost",
@@ -29982,7 +29979,7 @@ var init_DateRangePicker = __esm({
29982
29979
  },
29983
29980
  preset.value
29984
29981
  )),
29985
- [presets, activePreset, handlePreset]
29982
+ [renderablePresets, activePreset, handlePreset]
29986
29983
  );
29987
29984
  return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn(className), children: [
29988
29985
  /* @__PURE__ */ jsxs(HStack, { gap: "md", align: "end", children: [
@@ -30009,7 +30006,7 @@ var init_DateRangePicker = __esm({
30009
30006
  )
30010
30007
  ] })
30011
30008
  ] }),
30012
- presets.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
30009
+ renderablePresets.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
30013
30010
  ] });
30014
30011
  };
30015
30012
  DateRangePicker.displayName = "DateRangePicker";
@@ -30451,6 +30448,208 @@ var init_PhysicsCanvas = __esm({
30451
30448
  };
30452
30449
  }
30453
30450
  });
30451
+
30452
+ // lib/graphViewLayouts.ts
30453
+ function buildAdjacency(nodeIds, edges) {
30454
+ const known = new Set(nodeIds);
30455
+ const out = /* @__PURE__ */ new Map();
30456
+ const inMap = /* @__PURE__ */ new Map();
30457
+ for (const id of nodeIds) {
30458
+ out.set(id, []);
30459
+ inMap.set(id, []);
30460
+ }
30461
+ for (const edge of edges) {
30462
+ if (!known.has(edge.source) || !known.has(edge.target)) continue;
30463
+ out.get(edge.source)?.push(edge.target);
30464
+ inMap.get(edge.target)?.push(edge.source);
30465
+ }
30466
+ return { out, in: inMap };
30467
+ }
30468
+ function findRoots(nodeIds, adjacency) {
30469
+ return nodeIds.filter((id) => (adjacency.in.get(id)?.length ?? 0) === 0);
30470
+ }
30471
+ function assignLayers(nodeIds, adjacency, roots) {
30472
+ const layer = new Map(nodeIds.map((id) => [id, 0]));
30473
+ const onStack = /* @__PURE__ */ new Set();
30474
+ const visit = (id) => {
30475
+ onStack.add(id);
30476
+ const currentLayer = layer.get(id) ?? 0;
30477
+ for (const next of adjacency.out.get(id) ?? []) {
30478
+ if (onStack.has(next)) continue;
30479
+ const candidate = currentLayer + 1;
30480
+ if (candidate > (layer.get(next) ?? 0)) {
30481
+ layer.set(next, candidate);
30482
+ }
30483
+ visit(next);
30484
+ }
30485
+ onStack.delete(id);
30486
+ };
30487
+ for (const root of roots) visit(root);
30488
+ return layer;
30489
+ }
30490
+ function computeVisitOrder(nodeIds, adjacency, roots) {
30491
+ const order = /* @__PURE__ */ new Map();
30492
+ const visited = /* @__PURE__ */ new Set();
30493
+ let counter = 0;
30494
+ const visit = (id) => {
30495
+ if (visited.has(id)) return;
30496
+ visited.add(id);
30497
+ order.set(id, counter++);
30498
+ for (const next of adjacency.out.get(id) ?? []) visit(next);
30499
+ };
30500
+ for (const root of roots) visit(root);
30501
+ for (const id of nodeIds) {
30502
+ if (!visited.has(id)) order.set(id, counter++);
30503
+ }
30504
+ return order;
30505
+ }
30506
+ function bfsDepthAndOrder(nodeIds, adjacency, roots) {
30507
+ const depth = new Map(nodeIds.map((id) => [id, 0]));
30508
+ const visitOrder = /* @__PURE__ */ new Map();
30509
+ const visited = /* @__PURE__ */ new Set();
30510
+ const queue = [];
30511
+ let counter = 0;
30512
+ for (const root of roots) {
30513
+ if (visited.has(root)) continue;
30514
+ visited.add(root);
30515
+ depth.set(root, 0);
30516
+ visitOrder.set(root, counter++);
30517
+ queue.push(root);
30518
+ }
30519
+ let head = 0;
30520
+ while (head < queue.length) {
30521
+ const id = queue[head++];
30522
+ const d = depth.get(id) ?? 0;
30523
+ for (const next of adjacency.out.get(id) ?? []) {
30524
+ if (visited.has(next)) continue;
30525
+ visited.add(next);
30526
+ depth.set(next, d + 1);
30527
+ visitOrder.set(next, counter++);
30528
+ queue.push(next);
30529
+ }
30530
+ }
30531
+ for (const id of nodeIds) {
30532
+ if (!visited.has(id)) visitOrder.set(id, counter++);
30533
+ }
30534
+ return { depth, visitOrder };
30535
+ }
30536
+ function edgeWalkOrder(nodeIds, adjacency) {
30537
+ const visited = /* @__PURE__ */ new Set();
30538
+ const result = [];
30539
+ for (const start of nodeIds) {
30540
+ if (visited.has(start)) continue;
30541
+ let current = start;
30542
+ while (current !== void 0 && !visited.has(current)) {
30543
+ visited.add(current);
30544
+ result.push(current);
30545
+ const outs = adjacency.out.get(current) ?? [];
30546
+ current = outs.find((next) => !visited.has(next));
30547
+ }
30548
+ }
30549
+ return result;
30550
+ }
30551
+ function groupByTier(nodeIds, tierOf, maxTier) {
30552
+ const groups = Array.from({ length: maxTier + 1 }, () => []);
30553
+ for (const id of nodeIds) {
30554
+ groups[tierOf.get(id) ?? 0].push(id);
30555
+ }
30556
+ return groups;
30557
+ }
30558
+ function distributeAxis(count, start, end) {
30559
+ if (count <= 0) return [];
30560
+ const slot = (end - start) / count;
30561
+ return Array.from({ length: count }, (_, i) => start + slot * (i + 0.5));
30562
+ }
30563
+ function orderByParentPositionThenInput(group, adjacency, positioned, inputIndex) {
30564
+ const withKey = group.map((id) => {
30565
+ const parentValues = (adjacency.in.get(id) ?? []).map((p) => positioned.get(p)).filter((v) => v !== void 0);
30566
+ const avg = parentValues.length > 0 ? parentValues.reduce((a, b) => a + b, 0) / parentValues.length : Number.POSITIVE_INFINITY;
30567
+ return { id, avg, idx: inputIndex.get(id) ?? 0 };
30568
+ });
30569
+ withKey.sort((a, b) => a.avg !== b.avg ? a.avg - b.avg : a.idx - b.idx);
30570
+ return withKey.map((k) => k.id);
30571
+ }
30572
+ function layoutFlow(nodeIds, adjacency, roots, width, height, margin) {
30573
+ const inputIndex = new Map(nodeIds.map((id, i) => [id, i]));
30574
+ const layers = assignLayers(nodeIds, adjacency, roots);
30575
+ const maxLayer = Math.max(...Array.from(layers.values()));
30576
+ const layerGroups = groupByTier(nodeIds, layers, maxLayer);
30577
+ const positions = /* @__PURE__ */ new Map();
30578
+ const yById = /* @__PURE__ */ new Map();
30579
+ for (let l = 0; l <= maxLayer; l++) {
30580
+ const x = margin + l * (width - 2 * margin) / Math.max(1, maxLayer);
30581
+ const ordered2 = orderByParentPositionThenInput(layerGroups[l], adjacency, yById, inputIndex);
30582
+ const ys = distributeAxis(ordered2.length, margin, height - margin);
30583
+ ordered2.forEach((id, i) => {
30584
+ positions.set(id, { id, x, y: ys[i] });
30585
+ yById.set(id, ys[i]);
30586
+ });
30587
+ }
30588
+ return nodeIds.map((id) => positions.get(id));
30589
+ }
30590
+ function layoutTree2(nodeIds, adjacency, roots, width, height, margin) {
30591
+ const effectiveRoots = roots.length > 0 ? roots : [nodeIds[0]];
30592
+ const layers = assignLayers(nodeIds, adjacency, effectiveRoots);
30593
+ const maxLayer = Math.max(...Array.from(layers.values()));
30594
+ const visitOrder = computeVisitOrder(nodeIds, adjacency, effectiveRoots);
30595
+ const layerGroups = groupByTier(nodeIds, layers, maxLayer);
30596
+ const positions = /* @__PURE__ */ new Map();
30597
+ for (let l = 0; l <= maxLayer; l++) {
30598
+ const ordered2 = [...layerGroups[l]].sort(
30599
+ (a, b) => (visitOrder.get(a) ?? 0) - (visitOrder.get(b) ?? 0)
30600
+ );
30601
+ const y = margin + l * (height - 2 * margin) / Math.max(1, maxLayer);
30602
+ const xs = distributeAxis(ordered2.length, margin, width - margin);
30603
+ ordered2.forEach((id, i) => positions.set(id, { id, x: xs[i], y }));
30604
+ }
30605
+ return nodeIds.map((id) => positions.get(id));
30606
+ }
30607
+ function layoutRadial(nodeIds, adjacency, roots, width, height, margin) {
30608
+ const cx = width / 2;
30609
+ const cy = height / 2;
30610
+ const maxRadius = Math.min(width, height) / 2 - margin;
30611
+ if (roots.length === 0) {
30612
+ const order = edgeWalkOrder(nodeIds, adjacency);
30613
+ const k = order.length;
30614
+ const positions2 = /* @__PURE__ */ new Map();
30615
+ order.forEach((id, i) => {
30616
+ const angle = i / k * 2 * Math.PI;
30617
+ positions2.set(id, { id, x: cx + maxRadius * Math.cos(angle), y: cy + maxRadius * Math.sin(angle) });
30618
+ });
30619
+ return nodeIds.map((id) => positions2.get(id));
30620
+ }
30621
+ const { depth, visitOrder } = bfsDepthAndOrder(nodeIds, adjacency, roots);
30622
+ const maxDepth = Math.max(...Array.from(depth.values()));
30623
+ const ringGroups = groupByTier(nodeIds, depth, maxDepth);
30624
+ const positions = /* @__PURE__ */ new Map();
30625
+ for (let d = 0; d <= maxDepth; d++) {
30626
+ const ordered2 = [...ringGroups[d]].sort(
30627
+ (a, b) => (visitOrder.get(a) ?? 0) - (visitOrder.get(b) ?? 0)
30628
+ );
30629
+ const radius = d * maxRadius / Math.max(1, maxDepth);
30630
+ const k = ordered2.length;
30631
+ ordered2.forEach((id, i) => {
30632
+ const angle = i / k * 2 * Math.PI;
30633
+ positions.set(id, { id, x: cx + radius * Math.cos(angle), y: cy + radius * Math.sin(angle) });
30634
+ });
30635
+ }
30636
+ return nodeIds.map((id) => positions.get(id));
30637
+ }
30638
+ function computeStaticLayout(mode, input) {
30639
+ const { nodeIds, edges, width, height } = input;
30640
+ const margin = input.margin ?? 40;
30641
+ if (nodeIds.length === 0) return [];
30642
+ if (nodeIds.length === 1) return [{ id: nodeIds[0], x: width / 2, y: height / 2 }];
30643
+ const adjacency = buildAdjacency(nodeIds, edges);
30644
+ const roots = findRoots(nodeIds, adjacency);
30645
+ if (mode === "flow") return layoutFlow(nodeIds, adjacency, roots, width, height, margin);
30646
+ if (mode === "tree") return layoutTree2(nodeIds, adjacency, roots, width, height, margin);
30647
+ return layoutRadial(nodeIds, adjacency, roots, width, height, margin);
30648
+ }
30649
+ var init_graphViewLayouts = __esm({
30650
+ "lib/graphViewLayouts.ts"() {
30651
+ }
30652
+ });
30454
30653
  function resolveNodeColor(node, groups) {
30455
30654
  if (node.color) return node.color;
30456
30655
  if (node.group) {
@@ -30465,6 +30664,7 @@ var init_GraphView = __esm({
30465
30664
  "use client";
30466
30665
  init_cn();
30467
30666
  init_atoms();
30667
+ init_graphViewLayouts();
30468
30668
  GROUP_COLORS = [
30469
30669
  "#3b82f6",
30470
30670
  // blue-500
@@ -30495,11 +30695,13 @@ var init_GraphView = __esm({
30495
30695
  height: propHeight,
30496
30696
  className,
30497
30697
  showLabels = true,
30498
- zoomToFit = true
30698
+ zoomToFit = true,
30699
+ layout = "force"
30499
30700
  }) => {
30500
30701
  const { t } = useTranslate();
30501
30702
  const containerRef = useRef(null);
30502
30703
  const animRef = useRef(0);
30704
+ const arrowMarkerId = useId();
30503
30705
  const [simNodes, setSimNodes] = useState([]);
30504
30706
  const [settled, setSettled] = useState(false);
30505
30707
  const [hoveredId, setHoveredId] = useState(null);
@@ -30556,6 +30758,22 @@ var init_GraphView = __esm({
30556
30758
  fy: 0
30557
30759
  };
30558
30760
  });
30761
+ if (layout !== "force") {
30762
+ const points = computeStaticLayout(layout, {
30763
+ nodeIds: nodes.map((n) => n.id),
30764
+ edges,
30765
+ width: w,
30766
+ height: h
30767
+ });
30768
+ const pointById = new Map(points.map((p) => [p.id, p]));
30769
+ const laidOut = initialNodes.map((node) => {
30770
+ const point = pointById.get(node.id);
30771
+ return point ? { ...node, x: point.x, y: point.y } : node;
30772
+ });
30773
+ setSimNodes(laidOut);
30774
+ setSettled(true);
30775
+ return;
30776
+ }
30559
30777
  let iterations = 0;
30560
30778
  const maxIterations = 120;
30561
30779
  let currentNodes = initialNodes;
@@ -30624,7 +30842,7 @@ var init_GraphView = __esm({
30624
30842
  return () => {
30625
30843
  cancelAnimationFrame(animRef.current);
30626
30844
  };
30627
- }, [nodes, edges, w, h, groups]);
30845
+ }, [nodes, edges, w, h, groups, layout]);
30628
30846
  const viewBox = useMemo(() => {
30629
30847
  if (!zoomToFit || !settled || simNodes.length === 0) {
30630
30848
  return `0 0 ${w} ${h}`;
@@ -30699,6 +30917,19 @@ var init_GraphView = __esm({
30699
30917
  viewBox,
30700
30918
  preserveAspectRatio: "xMidYMid meet",
30701
30919
  children: [
30920
+ layout !== "force" && /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx(
30921
+ "marker",
30922
+ {
30923
+ id: arrowMarkerId,
30924
+ viewBox: "0 0 10 10",
30925
+ refX: "9",
30926
+ refY: "5",
30927
+ markerWidth: "6",
30928
+ markerHeight: "6",
30929
+ orient: "auto-start-reverse",
30930
+ children: /* @__PURE__ */ jsx("path", { d: "M0,0 L10,5 L0,10 z", fill: "currentColor" })
30931
+ }
30932
+ ) }),
30702
30933
  edges.map((edge, idx) => {
30703
30934
  const source = nodeMap.get(edge.source);
30704
30935
  const target = nodeMap.get(edge.target);
@@ -30713,8 +30944,10 @@ var init_GraphView = __esm({
30713
30944
  x2: target.x,
30714
30945
  y2: target.y,
30715
30946
  stroke: edge.color ?? DEFAULT_EDGE_COLOR,
30947
+ color: edge.color ?? DEFAULT_EDGE_COLOR,
30716
30948
  strokeWidth: 1.5,
30717
- opacity: isHighlighted ? 0.8 : 0.15
30949
+ opacity: isHighlighted ? 0.8 : 0.15,
30950
+ markerEnd: layout !== "force" ? `url(#${arrowMarkerId})` : void 0
30718
30951
  }
30719
30952
  ),
30720
30953
  showLabels && edge.label && /* @__PURE__ */ jsx(
@@ -55787,7 +56020,9 @@ function FlowCanvasInner({
55787
56020
  behaviorEntries,
55788
56021
  behaviorWires,
55789
56022
  userType = "builder",
55790
- themeManifest
56023
+ themeManifest,
56024
+ nodePositions,
56025
+ onPositionsChange
55791
56026
  }) {
55792
56027
  const { t } = useTranslate();
55793
56028
  const NODE_TYPES2 = useMemo(() => ({
@@ -55874,9 +56109,15 @@ function FlowCanvasInner({
55874
56109
  const [nodes, setNodes, onNodesChange] = useNodesState(activeNodes);
55875
56110
  const [edges, setEdges, onEdgesChange] = useEdgesState(activeEdges);
55876
56111
  const reactFlow = useReactFlow();
56112
+ const savedPositionsRef = React94__default.useRef(nodePositions);
56113
+ savedPositionsRef.current = nodePositions;
56114
+ const nodesRef = React94__default.useRef(nodes);
56115
+ nodesRef.current = nodes;
55877
56116
  useEffect(() => {
55878
56117
  setEdges([]);
55879
- setNodes(activeNodes);
56118
+ const saved = savedPositionsRef.current;
56119
+ const merged = saved ? activeNodes.map((n) => saved[n.id] ? { ...n, position: saved[n.id] } : n) : activeNodes;
56120
+ setNodes(merged);
55880
56121
  setEdges(activeEdges);
55881
56122
  requestAnimationFrame(() => {
55882
56123
  reactFlow.fitView({ duration: 300, padding: 0.25 });
@@ -56026,6 +56267,14 @@ function FlowCanvasInner({
56026
56267
  targetTraitName: tgtData.traitName
56027
56268
  });
56028
56269
  }, [nodes, onEventWire, eventBus]);
56270
+ const handleNodeDragStop = useCallback(() => {
56271
+ if (!onPositionsChange) return;
56272
+ const positions = {};
56273
+ for (const n of nodesRef.current) {
56274
+ positions[n.id] = { x: n.position.x, y: n.position.y };
56275
+ }
56276
+ onPositionsChange(positions);
56277
+ }, [onPositionsChange]);
56029
56278
  const screenSizeKeys = ["mobile", "tablet", "laptop", "wide"];
56030
56279
  const traitCardSelectionValue = useMemo(() => ({
56031
56280
  selectTransition: (sel) => {
@@ -56057,6 +56306,7 @@ function FlowCanvasInner({
56057
56306
  onNodeDoubleClick: handleNodeDoubleClick,
56058
56307
  onNodeClick: handleNodeClick,
56059
56308
  onConnect: handleConnect,
56309
+ onNodeDragStop: handleNodeDragStop,
56060
56310
  minZoom: 0.1,
56061
56311
  maxZoom: 2,
56062
56312
  fitView: true,
@@ -1,4 +1,5 @@
1
1
  import { OrbitalSchema, SExpr, Effect, OrbitalVerificationAPI, TraitStateSnapshot, EventPayload, BusEvent, VerificationCheck, BridgeHealth, VerificationSnapshot, VerificationSummary, TransitionTrace, ServerResponseTrace, CheckStatus, AssetLoadStatus } from '@almadar/core';
2
+ import React__default from 'react';
2
3
  import { D as DrawableNode } from './paintDispatch-Cb_hQj4Y.cjs';
3
4
  import { ClassValue } from 'clsx';
4
5
 
@@ -34,7 +35,7 @@ type ContentSegment = {
34
35
  * Splits markdown into segments of plain markdown and fenced code blocks.
35
36
  * JSON/orb code blocks containing orbital schemas are tagged as 'orbital'.
36
37
  */
37
- declare function parseMarkdownWithCodeBlocks(content: string | undefined | null): ContentSegment[];
38
+ declare function parseMarkdownWithCodeBlocks$1(content: string | undefined | null): ContentSegment[];
38
39
  /**
39
40
  * Parse content to extract all segments including quiz tags and code blocks.
40
41
  *
@@ -45,6 +46,95 @@ declare function parseMarkdownWithCodeBlocks(content: string | undefined | null)
45
46
  */
46
47
  declare function parseContentSegments(content: string | undefined | null): ContentSegment[];
47
48
 
49
+ /**
50
+ * BloomQuizBlock Molecule Component
51
+ *
52
+ * Practice Q&A with Bloom's Taxonomy level badge. Emits `UI:ANSWER_BLOOM { index, level }`.
53
+ *
54
+ * Event Contract:
55
+ * - Emits: UI:ANSWER_BLOOM { index, level }
56
+ * - entityAware: false
57
+ */
58
+
59
+ type BloomLevel = 'remember' | 'understand' | 'apply' | 'analyze' | 'evaluate' | 'create';
60
+ interface BloomQuizBlockProps {
61
+ level: BloomLevel;
62
+ question: string;
63
+ answer: string;
64
+ /** Zero-based index (used in the emitted event payload) */
65
+ index?: number;
66
+ /** Whether the learner has already answered */
67
+ isAnswered?: boolean;
68
+ /** Event name emitted on first reveal (as `UI:<answerEvent>`). Defaults to 'ANSWER_BLOOM'. */
69
+ answerEvent?: string;
70
+ /** Additional CSS classes */
71
+ className?: string;
72
+ }
73
+ declare const BloomQuizBlock: React__default.FC<BloomQuizBlockProps>;
74
+
75
+ /**
76
+ * Utility for lesson-segment parsing: splits a markdown string into alternating
77
+ * markdown and fenced-code-block segments. Exported so SegmentRenderer and
78
+ * BloomQuizBlock can reuse without circular imports.
79
+ */
80
+ type MarkdownSegment = {
81
+ type: 'markdown';
82
+ content: string;
83
+ };
84
+ type CodeSegment = {
85
+ type: 'code';
86
+ language: string;
87
+ content: string;
88
+ runnable?: boolean;
89
+ };
90
+ type MixedSegment = MarkdownSegment | CodeSegment;
91
+ /** Splits markdown content into markdown and fenced-code-block segments. */
92
+ declare function parseMarkdownWithCodeBlocks(content: string): MixedSegment[];
93
+
94
+ /**
95
+ * parseLessonSegments — parses lesson markdown with embedded learning-science
96
+ * XML-style tags into a typed Segment array.
97
+ *
98
+ * Supported tags: <activate>, <connect>, <reflect>, <bloom level="...">,
99
+ * <question>/<answer>, <visualize type="..." description="..." />.
100
+ *
101
+ * Tags may be open (unclosed) — the parser falls back to consuming content
102
+ * until the next recognised tag, a section heading (`\n\n#`), or end-of-input.
103
+ */
104
+
105
+ type InteractiveOrbitalType = 'algorithms' | 'math' | 'physics' | 'biology' | 'chemistry' | 'probability';
106
+ type LessonSegment = MixedSegment | {
107
+ type: 'quiz';
108
+ question: string;
109
+ answer: string;
110
+ } | {
111
+ type: 'activate';
112
+ question: string;
113
+ } | {
114
+ type: 'connect';
115
+ content: string;
116
+ } | {
117
+ type: 'reflect';
118
+ prompt: string;
119
+ } | {
120
+ type: 'bloom';
121
+ level: BloomLevel;
122
+ question: string;
123
+ answer: string;
124
+ } | {
125
+ type: 'visualization';
126
+ visualizationType: InteractiveOrbitalType;
127
+ description: string;
128
+ };
129
+ /** User progress state passed into SegmentRenderer. */
130
+ interface LessonUserProgress {
131
+ activationResponse?: string;
132
+ reflectionNotes?: string[];
133
+ bloomAnswered?: Record<number, boolean>;
134
+ }
135
+ /** Parse a lesson string into typed segments. Returns `[]` when input is empty. */
136
+ declare function parseLessonSegments(lesson: string | undefined): LessonSegment[];
137
+
48
138
  /**
49
139
  * Orbital State Machine Visualizer
50
140
  *
@@ -292,4 +382,4 @@ declare function clearVerification(): void;
292
382
  */
293
383
  declare function cn(...inputs: ClassValue[]): string;
294
384
 
295
- export { parseMarkdownWithCodeBlocks as A, recordServerResponse as B, type ContentSegment as C, DEFAULT_CONFIG as D, type EntityDefinition as E, recordTransition as F, registerCheck as G, registerTraitSnapshot as H, renderStateMachineToDomData as I, renderStateMachineToSvg as J, subscribeToVerification as K, updateAssetStatus as L, updateBridgeHealth as M, updateCheck as N, waitForTransition as O, type RenderOptions as R, type StateDefinition as S, type TraitSnapshotGetter as T, type VisualizerConfig as V, type DomEntityBox as a, type DomLayoutData as b, type DomOutputsBox as c, type DomStateNode as d, type DomTransitionLabel as e, type DomTransitionPath as f, type StateMachineDefinition as g, type TransitionDefinition as h, bindCanvasCapture as i, bindEventBus as j, bindLastDrawables as k, bindTraitStateGetter as l, clearVerification as m, cn as n, extractOutputsFromTransitions as o, extractStateMachine as p, formatGuard as q, getAllChecks as r, getBridgeHealth as s, getEffectSummary as t, getSnapshot as u, getSummary as v, getTraitSnapshots as w, getTransitions as x, getTransitionsForTrait as y, parseContentSegments as z };
385
+ export { parseMarkdownWithCodeBlocks as $, parseLessonSegments as A, parseMarkdownWithCodeBlocks$1 as B, type ContentSegment as C, DEFAULT_CONFIG as D, type EntityDefinition as E, recordServerResponse as F, recordTransition as G, registerCheck as H, registerTraitSnapshot as I, renderStateMachineToDomData as J, renderStateMachineToSvg as K, type LessonSegment as L, subscribeToVerification as M, updateAssetStatus as N, updateBridgeHealth as O, updateCheck as P, waitForTransition as Q, type RenderOptions as R, type StateDefinition as S, type TraitSnapshotGetter as T, type LessonUserProgress as U, type VisualizerConfig as V, type InteractiveOrbitalType as W, type BloomLevel as X, BloomQuizBlock as Y, type BloomQuizBlockProps as Z, type MixedSegment as _, type DomEntityBox as a, type DomLayoutData as b, type DomOutputsBox as c, type DomStateNode as d, type DomTransitionLabel as e, type DomTransitionPath as f, type StateMachineDefinition as g, type TransitionDefinition as h, bindCanvasCapture as i, bindEventBus as j, bindLastDrawables as k, bindTraitStateGetter as l, clearVerification as m, cn as n, extractOutputsFromTransitions as o, extractStateMachine as p, formatGuard as q, getAllChecks as r, getBridgeHealth as s, getEffectSummary as t, getSnapshot as u, getSummary as v, getTraitSnapshots as w, getTransitions as x, getTransitionsForTrait as y, parseContentSegments as z };
@@ -1,4 +1,5 @@
1
1
  import { OrbitalSchema, SExpr, Effect, OrbitalVerificationAPI, TraitStateSnapshot, EventPayload, BusEvent, VerificationCheck, BridgeHealth, VerificationSnapshot, VerificationSummary, TransitionTrace, ServerResponseTrace, CheckStatus, AssetLoadStatus } from '@almadar/core';
2
+ import React__default from 'react';
2
3
  import { D as DrawableNode } from './paintDispatch-Cb_hQj4Y.js';
3
4
  import { ClassValue } from 'clsx';
4
5
 
@@ -34,7 +35,7 @@ type ContentSegment = {
34
35
  * Splits markdown into segments of plain markdown and fenced code blocks.
35
36
  * JSON/orb code blocks containing orbital schemas are tagged as 'orbital'.
36
37
  */
37
- declare function parseMarkdownWithCodeBlocks(content: string | undefined | null): ContentSegment[];
38
+ declare function parseMarkdownWithCodeBlocks$1(content: string | undefined | null): ContentSegment[];
38
39
  /**
39
40
  * Parse content to extract all segments including quiz tags and code blocks.
40
41
  *
@@ -45,6 +46,95 @@ declare function parseMarkdownWithCodeBlocks(content: string | undefined | null)
45
46
  */
46
47
  declare function parseContentSegments(content: string | undefined | null): ContentSegment[];
47
48
 
49
+ /**
50
+ * BloomQuizBlock Molecule Component
51
+ *
52
+ * Practice Q&A with Bloom's Taxonomy level badge. Emits `UI:ANSWER_BLOOM { index, level }`.
53
+ *
54
+ * Event Contract:
55
+ * - Emits: UI:ANSWER_BLOOM { index, level }
56
+ * - entityAware: false
57
+ */
58
+
59
+ type BloomLevel = 'remember' | 'understand' | 'apply' | 'analyze' | 'evaluate' | 'create';
60
+ interface BloomQuizBlockProps {
61
+ level: BloomLevel;
62
+ question: string;
63
+ answer: string;
64
+ /** Zero-based index (used in the emitted event payload) */
65
+ index?: number;
66
+ /** Whether the learner has already answered */
67
+ isAnswered?: boolean;
68
+ /** Event name emitted on first reveal (as `UI:<answerEvent>`). Defaults to 'ANSWER_BLOOM'. */
69
+ answerEvent?: string;
70
+ /** Additional CSS classes */
71
+ className?: string;
72
+ }
73
+ declare const BloomQuizBlock: React__default.FC<BloomQuizBlockProps>;
74
+
75
+ /**
76
+ * Utility for lesson-segment parsing: splits a markdown string into alternating
77
+ * markdown and fenced-code-block segments. Exported so SegmentRenderer and
78
+ * BloomQuizBlock can reuse without circular imports.
79
+ */
80
+ type MarkdownSegment = {
81
+ type: 'markdown';
82
+ content: string;
83
+ };
84
+ type CodeSegment = {
85
+ type: 'code';
86
+ language: string;
87
+ content: string;
88
+ runnable?: boolean;
89
+ };
90
+ type MixedSegment = MarkdownSegment | CodeSegment;
91
+ /** Splits markdown content into markdown and fenced-code-block segments. */
92
+ declare function parseMarkdownWithCodeBlocks(content: string): MixedSegment[];
93
+
94
+ /**
95
+ * parseLessonSegments — parses lesson markdown with embedded learning-science
96
+ * XML-style tags into a typed Segment array.
97
+ *
98
+ * Supported tags: <activate>, <connect>, <reflect>, <bloom level="...">,
99
+ * <question>/<answer>, <visualize type="..." description="..." />.
100
+ *
101
+ * Tags may be open (unclosed) — the parser falls back to consuming content
102
+ * until the next recognised tag, a section heading (`\n\n#`), or end-of-input.
103
+ */
104
+
105
+ type InteractiveOrbitalType = 'algorithms' | 'math' | 'physics' | 'biology' | 'chemistry' | 'probability';
106
+ type LessonSegment = MixedSegment | {
107
+ type: 'quiz';
108
+ question: string;
109
+ answer: string;
110
+ } | {
111
+ type: 'activate';
112
+ question: string;
113
+ } | {
114
+ type: 'connect';
115
+ content: string;
116
+ } | {
117
+ type: 'reflect';
118
+ prompt: string;
119
+ } | {
120
+ type: 'bloom';
121
+ level: BloomLevel;
122
+ question: string;
123
+ answer: string;
124
+ } | {
125
+ type: 'visualization';
126
+ visualizationType: InteractiveOrbitalType;
127
+ description: string;
128
+ };
129
+ /** User progress state passed into SegmentRenderer. */
130
+ interface LessonUserProgress {
131
+ activationResponse?: string;
132
+ reflectionNotes?: string[];
133
+ bloomAnswered?: Record<number, boolean>;
134
+ }
135
+ /** Parse a lesson string into typed segments. Returns `[]` when input is empty. */
136
+ declare function parseLessonSegments(lesson: string | undefined): LessonSegment[];
137
+
48
138
  /**
49
139
  * Orbital State Machine Visualizer
50
140
  *
@@ -292,4 +382,4 @@ declare function clearVerification(): void;
292
382
  */
293
383
  declare function cn(...inputs: ClassValue[]): string;
294
384
 
295
- export { parseMarkdownWithCodeBlocks as A, recordServerResponse as B, type ContentSegment as C, DEFAULT_CONFIG as D, type EntityDefinition as E, recordTransition as F, registerCheck as G, registerTraitSnapshot as H, renderStateMachineToDomData as I, renderStateMachineToSvg as J, subscribeToVerification as K, updateAssetStatus as L, updateBridgeHealth as M, updateCheck as N, waitForTransition as O, type RenderOptions as R, type StateDefinition as S, type TraitSnapshotGetter as T, type VisualizerConfig as V, type DomEntityBox as a, type DomLayoutData as b, type DomOutputsBox as c, type DomStateNode as d, type DomTransitionLabel as e, type DomTransitionPath as f, type StateMachineDefinition as g, type TransitionDefinition as h, bindCanvasCapture as i, bindEventBus as j, bindLastDrawables as k, bindTraitStateGetter as l, clearVerification as m, cn as n, extractOutputsFromTransitions as o, extractStateMachine as p, formatGuard as q, getAllChecks as r, getBridgeHealth as s, getEffectSummary as t, getSnapshot as u, getSummary as v, getTraitSnapshots as w, getTransitions as x, getTransitionsForTrait as y, parseContentSegments as z };
385
+ export { parseMarkdownWithCodeBlocks as $, parseLessonSegments as A, parseMarkdownWithCodeBlocks$1 as B, type ContentSegment as C, DEFAULT_CONFIG as D, type EntityDefinition as E, recordServerResponse as F, recordTransition as G, registerCheck as H, registerTraitSnapshot as I, renderStateMachineToDomData as J, renderStateMachineToSvg as K, type LessonSegment as L, subscribeToVerification as M, updateAssetStatus as N, updateBridgeHealth as O, updateCheck as P, waitForTransition as Q, type RenderOptions as R, type StateDefinition as S, type TraitSnapshotGetter as T, type LessonUserProgress as U, type VisualizerConfig as V, type InteractiveOrbitalType as W, type BloomLevel as X, BloomQuizBlock as Y, type BloomQuizBlockProps as Z, type MixedSegment as _, type DomEntityBox as a, type DomLayoutData as b, type DomOutputsBox as c, type DomStateNode as d, type DomTransitionLabel as e, type DomTransitionPath as f, type StateMachineDefinition as g, type TransitionDefinition as h, bindCanvasCapture as i, bindEventBus as j, bindLastDrawables as k, bindTraitStateGetter as l, clearVerification as m, cn as n, extractOutputsFromTransitions as o, extractStateMachine as p, formatGuard as q, getAllChecks as r, getBridgeHealth as s, getEffectSummary as t, getSnapshot as u, getSummary as v, getTraitSnapshots as w, getTransitions as x, getTransitionsForTrait as y, parseContentSegments as z };