@almadar/ui 5.146.3 → 5.148.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.
@@ -1,6 +1,7 @@
1
- export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseMarkdownWithCodeBlocks, B as recordServerResponse, F as recordTransition, G as registerCheck, H as registerTraitSnapshot, I as renderStateMachineToDomData, J as renderStateMachineToSvg, K as subscribeToVerification, L as updateAssetStatus, M as updateBridgeHealth, N as updateCheck, O as waitForTransition } from '../cn-DNkqAWZK.js';
1
+ export { C as ContentSegment, D as DEFAULT_CONFIG, a as DomEntityBox, b as DomLayoutData, c as DomOutputsBox, d as DomStateNode, e as DomTransitionLabel, f as DomTransitionPath, E as EntityDefinition, L as LessonSegment, R as RenderOptions, S as StateDefinition, g as StateMachineDefinition, T as TraitSnapshotGetter, h as TransitionDefinition, V as VisualizerConfig, i as bindCanvasCapture, j as bindEventBus, k as bindLastDrawables, l as bindTraitStateGetter, m as clearVerification, n as cn, o as extractOutputsFromTransitions, p as extractStateMachine, q as formatGuard, r as getAllChecks, s as getBridgeHealth, t as getEffectSummary, u as getSnapshot, v as getSummary, w as getTraitSnapshots, x as getTransitions, y as getTransitionsForTrait, z as parseContentSegments, A as parseLessonSegments, B as parseMarkdownWithCodeBlocks, F as recordServerResponse, G as recordTransition, H as registerCheck, I as registerTraitSnapshot, J as renderStateMachineToDomData, K as renderStateMachineToSvg, M as subscribeToVerification, N as updateAssetStatus, O as updateBridgeHealth, P as updateCheck, Q as waitForTransition } from '../cn-CWxxLkri.js';
2
2
  import { FieldValue, EntityRow, EventPayload } from '@almadar/core';
3
3
  export { AssetLoadStatus, BridgeHealth, CheckStatus, EffectTrace, EventLogEntry, OrbitalVerificationAPI, ServerResponseTrace, TraitStateSnapshot, TransitionTrace, VerificationCheck, VerificationSnapshot, VerificationSummary } from '@almadar/core';
4
+ import 'react';
4
5
  import '../paintDispatch-Cb_hQj4Y.js';
5
6
  import 'clsx';
6
7
 
package/dist/lib/index.js CHANGED
@@ -1636,6 +1636,109 @@ function parseContentSegments(content) {
1636
1636
  return segments;
1637
1637
  }
1638
1638
 
1639
+ // lib/lessonSegmentUtils.ts
1640
+ function parseMarkdownWithCodeBlocks2(content) {
1641
+ const segments = [];
1642
+ const codeBlockRegex = /```([^\n\r]*)\r?\n([\s\S]*?)```/g;
1643
+ let lastIndex = 0;
1644
+ let match;
1645
+ while ((match = codeBlockRegex.exec(content)) !== null) {
1646
+ const before = content.slice(lastIndex, match.index);
1647
+ if (before.trim()) {
1648
+ segments.push({ type: "markdown", content: before });
1649
+ }
1650
+ const tokens = match[1].trim().split(/\s+/).filter(Boolean);
1651
+ let rawLanguage = tokens[0] ?? "text";
1652
+ const suffixRunnable = rawLanguage.endsWith("-runnable");
1653
+ const runnable = suffixRunnable || tokens.includes("run");
1654
+ const baseLanguage = suffixRunnable ? rawLanguage.slice(0, -"-runnable".length) || "text" : rawLanguage;
1655
+ segments.push({ type: "code", language: baseLanguage, content: match[2].trim(), runnable });
1656
+ lastIndex = codeBlockRegex.lastIndex;
1657
+ }
1658
+ const remaining = content.slice(lastIndex);
1659
+ if (remaining.trim()) {
1660
+ segments.push({ type: "markdown", content: remaining });
1661
+ }
1662
+ return segments;
1663
+ }
1664
+
1665
+ // lib/parseLessonSegments.ts
1666
+ function extractTagContent(content, tagName) {
1667
+ const closedTagRegex = new RegExp(`<${tagName}>([\\s\\S]*?)<\\/${tagName}>`, "i");
1668
+ const closedMatch = content.match(closedTagRegex);
1669
+ if (closedMatch) {
1670
+ return { content: closedMatch[1].trim(), fullMatch: closedMatch[0] };
1671
+ }
1672
+ const unclosedTagRegex = new RegExp(
1673
+ `<${tagName}>([\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$)`,
1674
+ "i"
1675
+ );
1676
+ const unclosedMatch = content.match(unclosedTagRegex);
1677
+ if (unclosedMatch) {
1678
+ return { content: unclosedMatch[1].trim(), fullMatch: unclosedMatch[0] };
1679
+ }
1680
+ return null;
1681
+ }
1682
+ function parseLessonSegments(lesson) {
1683
+ if (!lesson) return [];
1684
+ let content = lesson.replace(/<prq>[\s\S]*?<\/prq>/gi, "").trim();
1685
+ const segments = [];
1686
+ const activateResult = extractTagContent(content, "activate");
1687
+ if (activateResult) {
1688
+ segments.push({ type: "activate", question: activateResult.content });
1689
+ content = content.replace(activateResult.fullMatch, "").trim();
1690
+ }
1691
+ const connectResult = extractTagContent(content, "connect");
1692
+ if (connectResult) {
1693
+ segments.push({ type: "connect", content: connectResult.content });
1694
+ content = content.replace(connectResult.fullMatch, "").trim();
1695
+ }
1696
+ const tagRegex = new RegExp(
1697
+ '(?<reflect><reflect>(?<reflectClosed>[\\s\\S]*?)<\\/reflect>)|(?<reflectUnclosed><reflect>(?<reflectOpen>[\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$))|(?<bloom><bloom\\s+level="(?<bloomLevel>remember|understand|apply|analyze|evaluate|create)">(?<bloomClosed>[\\s\\S]*?)<\\/bloom>)|(?<bloomUnclosed><bloom\\s+level="(?<bloomLevelUn>remember|understand|apply|analyze|evaluate|create)">(?<bloomOpen>[\\s\\S]*?)(?=<(?:activate|connect|reflect|bloom|prq|question|answer|visualize)|\\n\\n#|$))|(?<quiz><question>(?<quizQuestion>[\\s\\S]*?)<\\/question>\\s*<answer>(?<quizAnswer>[\\s\\S]*?)<\\/answer>)|(?<visualize><visualize\\s+type="(?<vizType>algorithms|math|physics|biology|chemistry|probability)"\\s+description="(?<vizDesc>[^"]*?)"\\s*\\/?>)',
1698
+ "gi"
1699
+ );
1700
+ let lastIndex = 0;
1701
+ let match;
1702
+ while ((match = tagRegex.exec(content)) !== null) {
1703
+ const before = content.slice(lastIndex, match.index);
1704
+ if (before.trim()) {
1705
+ segments.push(...parseMarkdownWithCodeBlocks2(before));
1706
+ }
1707
+ const g = match.groups ?? {};
1708
+ if (g.reflect || g.reflectUnclosed) {
1709
+ const prompt = (g.reflectClosed ?? g.reflectOpen ?? "").trim();
1710
+ if (prompt) segments.push({ type: "reflect", prompt });
1711
+ } else if (g.bloom || g.bloomUnclosed) {
1712
+ const level = g.bloomLevel ?? g.bloomLevelUn;
1713
+ const bloomContent = g.bloomClosed ?? g.bloomOpen ?? "";
1714
+ if (level && bloomContent) {
1715
+ const qMatch = bloomContent.match(/<question>([\s\S]*?)<\/question>/i);
1716
+ const aMatch = bloomContent.match(/<answer>([\s\S]*?)<\/answer>/i);
1717
+ if (qMatch && aMatch) {
1718
+ segments.push({ type: "bloom", level, question: qMatch[1].trim(), answer: aMatch[1].trim() });
1719
+ } else if (qMatch) {
1720
+ segments.push({ type: "bloom", level, question: qMatch[1].trim(), answer: "(Answer not provided)" });
1721
+ } else {
1722
+ const clean = bloomContent.replace(/^\*\*Question\s*\d*:?\*\*\s*/i, "").replace(/^\*\*Q\d*:?\*\*\s*/i, "").trim();
1723
+ if (clean) segments.push({ type: "bloom", level, question: clean, answer: "(See answers section below)" });
1724
+ }
1725
+ }
1726
+ } else if (g.quiz) {
1727
+ segments.push({ type: "quiz", question: g.quizQuestion.trim(), answer: g.quizAnswer.trim() });
1728
+ } else if (g.visualize) {
1729
+ segments.push({
1730
+ type: "visualization",
1731
+ visualizationType: g.vizType,
1732
+ description: g.vizDesc ?? ""
1733
+ });
1734
+ }
1735
+ lastIndex = tagRegex.lastIndex;
1736
+ }
1737
+ const remaining = content.slice(lastIndex);
1738
+ if (remaining.trim()) segments.push(...parseMarkdownWithCodeBlocks2(remaining));
1739
+ return segments;
1740
+ }
1741
+
1639
1742
  // lib/jazari/layout.ts
1640
1743
  var GEAR_RADIUS = 35;
1641
1744
  var GEAR_SPACING = 130;
@@ -1921,4 +2024,4 @@ var JAZARI_COLORS = {
1921
2024
  darkBg: "#1a1a2e"
1922
2025
  };
1923
2026
 
1924
- export { ApiError, DEFAULT_CONFIG, JAZARI_COLORS, apiClient, arrowheadPath, bindCanvasCapture, bindEventBus, bindLastDrawables, bindTraitStateGetter, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, compareCellValues, computeJazariLayout, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, eightPointedStarPath, extractOutputsFromTransitions, extractStateMachine, formatDate, formatDateTime, formatGuard, formatNestedFieldLabel, formatTime, formatValue, gearTeethPath, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTraitSnapshots, getTransitions, getTransitionsForTrait, humanizeEnumValue, humanizeFieldName, initDebugShortcut, isDebugEnabled, lockIconPath, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseMarkdownWithCodeBlocks, pipeIconPath, recordGuardEvaluation, recordServerResponse, recordTransition, registerCheck, registerTick, registerTrait, registerTraitSnapshot, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, sortRows, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };
2027
+ export { ApiError, DEFAULT_CONFIG, JAZARI_COLORS, apiClient, arrowheadPath, bindCanvasCapture, bindEventBus, bindLastDrawables, bindTraitStateGetter, brainIconPath, clearDebugEvents, clearEntityProvider, clearGuardHistory, clearTicks, clearTraits, clearVerification, cn, compareCellValues, computeJazariLayout, debug, debugCollision, debugError, debugGameState, debugGroup, debugGroupEnd, debugInput, debugPhysics, debugTable, debugTime, debugTimeEnd, debugWarn, eightPointedStarPath, extractOutputsFromTransitions, extractStateMachine, formatDate, formatDateTime, formatGuard, formatNestedFieldLabel, formatTime, formatValue, gearTeethPath, getAllChecks, getAllTicks, getAllTraits, getBridgeHealth, getDebugEvents, getEffectSummary, getEntitiesByType, getEntityById, getEntitySnapshot, getEventsBySource, getEventsByType, getGuardEvaluationsForTrait, getGuardHistory, getNestedValue, getRecentEvents, getRecentGuardEvaluations, getSnapshot, getSummary, getTick, getTrait, getTraitSnapshots, getTransitions, getTransitionsForTrait, humanizeEnumValue, humanizeFieldName, initDebugShortcut, isDebugEnabled, lockIconPath, logDebugEvent, logEffectExecuted, logError, logEventFired, logInfo, logStateChange, logWarning, onDebugToggle, parseContentSegments, parseLessonSegments, parseMarkdownWithCodeBlocks, pipeIconPath, recordGuardEvaluation, recordServerResponse, recordTransition, registerCheck, registerTick, registerTrait, registerTraitSnapshot, renderStateMachineToDomData, renderStateMachineToSvg, setDebugEnabled, setEntityProvider, setTickActive, sortRows, subscribeToDebugEvents, subscribeToGuardChanges, subscribeToTickChanges, subscribeToTraitChanges, subscribeToVerification, toggleDebug, unregisterTick, unregisterTrait, updateAssetStatus, updateBridgeHealth, updateCheck, updateGuardResult, updateTickExecution, updateTraitState, waitForTransition };
@@ -11853,7 +11853,10 @@ var init_LearningCanvas = __esm({
11853
11853
  ctx.fillRect(0, 0, width, height);
11854
11854
  }
11855
11855
  for (const shape of shapes) {
11856
- drawShape(ctx, shape, width, height);
11856
+ if (shape.type !== "text") drawShape(ctx, shape, width, height);
11857
+ }
11858
+ for (const shape of shapes) {
11859
+ if (shape.type === "text") drawShape(ctx, shape, width, height);
11857
11860
  }
11858
11861
  }, [width, height, backgroundColor, shapes]);
11859
11862
  React87.useEffect(() => {
@@ -13799,7 +13802,7 @@ var init_AlgorithmCanvas = __esm({
13799
13802
  DEFAULT_CELL_COLOR = "#e5e7eb";
13800
13803
  DEFAULT_POINTER_COLOR = "#dc2626";
13801
13804
  POINTER_BAND = 34;
13802
- TOP_PAD = 12;
13805
+ TOP_PAD = 26;
13803
13806
  AlgorithmCanvas = ({
13804
13807
  className,
13805
13808
  width = 600,
@@ -25405,6 +25408,7 @@ var init_FilterGroup = __esm({
25405
25408
  init_Badge();
25406
25409
  init_Stack();
25407
25410
  init_Icon();
25411
+ init_RangeSlider();
25408
25412
  init_useEventBus();
25409
25413
  init_useQuerySingleton();
25410
25414
  resolveFilterType = (filter) => filter.filterType ?? filter.type;
@@ -25599,6 +25603,35 @@ var init_FilterGroup = __esm({
25599
25603
  onClear: () => handleFilterSelect(`${filter.field}_to`, null)
25600
25604
  }
25601
25605
  )
25606
+ ] }) : resolveFilterType(filter) === "numberrange" || resolveFilterType(filter) === "number-range" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
25607
+ /* @__PURE__ */ jsxRuntime.jsx(
25608
+ RangeSlider,
25609
+ {
25610
+ min: filter.min ?? 0,
25611
+ max: filter.max ?? 100,
25612
+ step: filter.step ?? 1,
25613
+ value: Number(
25614
+ selectedValues[`${filter.field}_min`] ?? filter.min ?? 0
25615
+ ),
25616
+ onChange: (v) => handleFilterSelect(`${filter.field}_min`, String(v)),
25617
+ showTooltip: true,
25618
+ "aria-label": t("filterGroup.from")
25619
+ }
25620
+ ),
25621
+ /* @__PURE__ */ jsxRuntime.jsx(
25622
+ RangeSlider,
25623
+ {
25624
+ min: filter.min ?? 0,
25625
+ max: filter.max ?? 100,
25626
+ step: filter.step ?? 1,
25627
+ value: Number(
25628
+ selectedValues[`${filter.field}_max`] ?? filter.max ?? 100
25629
+ ),
25630
+ onChange: (v) => handleFilterSelect(`${filter.field}_max`, String(v)),
25631
+ showTooltip: true,
25632
+ "aria-label": t("filterGroup.to")
25633
+ }
25634
+ )
25602
25635
  ] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsxRuntime.jsx(
25603
25636
  Input,
25604
25637
  {
@@ -25681,6 +25714,36 @@ var init_FilterGroup = __esm({
25681
25714
  className: "text-sm min-w-[100px]"
25682
25715
  }
25683
25716
  )
25717
+ ] }) : resolveFilterType(filter) === "numberrange" || resolveFilterType(filter) === "number-range" ? /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
25718
+ /* @__PURE__ */ jsxRuntime.jsx(
25719
+ RangeSlider,
25720
+ {
25721
+ min: filter.min ?? 0,
25722
+ max: filter.max ?? 100,
25723
+ step: filter.step ?? 1,
25724
+ value: Number(
25725
+ selectedValues[`${filter.field}_min`] ?? filter.min ?? 0
25726
+ ),
25727
+ onChange: (v) => handleFilterSelect(`${filter.field}_min`, String(v)),
25728
+ className: "min-w-[100px]",
25729
+ "aria-label": t("filterGroup.from")
25730
+ }
25731
+ ),
25732
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "-" }),
25733
+ /* @__PURE__ */ jsxRuntime.jsx(
25734
+ RangeSlider,
25735
+ {
25736
+ min: filter.min ?? 0,
25737
+ max: filter.max ?? 100,
25738
+ step: filter.step ?? 1,
25739
+ value: Number(
25740
+ selectedValues[`${filter.field}_max`] ?? filter.max ?? 100
25741
+ ),
25742
+ onChange: (v) => handleFilterSelect(`${filter.field}_max`, String(v)),
25743
+ className: "min-w-[100px]",
25744
+ "aria-label": t("filterGroup.to")
25745
+ }
25746
+ )
25684
25747
  ] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsxRuntime.jsx(
25685
25748
  Input,
25686
25749
  {
@@ -25799,6 +25862,38 @@ var init_FilterGroup = __esm({
25799
25862
  className: "min-w-[130px]"
25800
25863
  }
25801
25864
  )
25865
+ ] }) : resolveFilterType(filter) === "numberrange" || resolveFilterType(filter) === "number-range" ? /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
25866
+ /* @__PURE__ */ jsxRuntime.jsx(
25867
+ RangeSlider,
25868
+ {
25869
+ min: filter.min ?? 0,
25870
+ max: filter.max ?? 100,
25871
+ step: filter.step ?? 1,
25872
+ value: Number(
25873
+ selectedValues[`${filter.field}_min`] ?? filter.min ?? 0
25874
+ ),
25875
+ onChange: (v) => handleFilterSelect(`${filter.field}_min`, String(v)),
25876
+ showTooltip: true,
25877
+ className: "min-w-[130px]",
25878
+ "aria-label": t("filterGroup.from")
25879
+ }
25880
+ ),
25881
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "-" }),
25882
+ /* @__PURE__ */ jsxRuntime.jsx(
25883
+ RangeSlider,
25884
+ {
25885
+ min: filter.min ?? 0,
25886
+ max: filter.max ?? 100,
25887
+ step: filter.step ?? 1,
25888
+ value: Number(
25889
+ selectedValues[`${filter.field}_max`] ?? filter.max ?? 100
25890
+ ),
25891
+ onChange: (v) => handleFilterSelect(`${filter.field}_max`, String(v)),
25892
+ showTooltip: true,
25893
+ className: "min-w-[130px]",
25894
+ "aria-label": t("filterGroup.to")
25895
+ }
25896
+ )
25802
25897
  ] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsxRuntime.jsx(
25803
25898
  Input,
25804
25899
  {
@@ -27698,7 +27793,12 @@ function daysAgo(n) {
27698
27793
  d.setDate(d.getDate() - n);
27699
27794
  return d;
27700
27795
  }
27701
- var DEFAULT_PRESETS, DateRangePicker;
27796
+ function resolvePresetRange(preset) {
27797
+ if (typeof preset.range === "function") return preset.range();
27798
+ if (preset.range) return preset.range;
27799
+ return TOKEN_RANGES[preset.value]?.() ?? null;
27800
+ }
27801
+ var TOKEN_RANGES, DEFAULT_PRESETS, DateRangePicker;
27702
27802
  var init_DateRangePicker = __esm({
27703
27803
  "components/core/molecules/DateRangePicker.tsx"() {
27704
27804
  "use client";
@@ -27708,32 +27808,19 @@ var init_DateRangePicker = __esm({
27708
27808
  init_Stack();
27709
27809
  init_Typography();
27710
27810
  init_useEventBus();
27811
+ TOKEN_RANGES = {
27812
+ "7d": () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) }),
27813
+ "30d": () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) }),
27814
+ month: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) }),
27815
+ quarter: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) }),
27816
+ ytd: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
27817
+ };
27711
27818
  DEFAULT_PRESETS = [
27712
- {
27713
- label: "Last 7 days",
27714
- value: "7d",
27715
- range: () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) })
27716
- },
27717
- {
27718
- label: "Last 30 days",
27719
- value: "30d",
27720
- range: () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) })
27721
- },
27722
- {
27723
- label: "This Month",
27724
- value: "month",
27725
- range: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
27726
- },
27727
- {
27728
- label: "This Quarter",
27729
- value: "quarter",
27730
- range: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
27731
- },
27732
- {
27733
- label: "YTD",
27734
- value: "ytd",
27735
- range: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
27736
- }
27819
+ { label: "Last 7 days", value: "7d" },
27820
+ { label: "Last 30 days", value: "30d" },
27821
+ { label: "This Month", value: "month" },
27822
+ { label: "This Quarter", value: "quarter" },
27823
+ { label: "YTD", value: "ytd" }
27737
27824
  ];
27738
27825
  DateRangePicker = ({
27739
27826
  from: fromProp,
@@ -27774,7 +27861,8 @@ var init_DateRangePicker = __esm({
27774
27861
  );
27775
27862
  const handlePreset = React87.useCallback(
27776
27863
  (preset) => {
27777
- const range = preset.range();
27864
+ const range = resolvePresetRange(preset);
27865
+ if (range === null) return;
27778
27866
  setFrom(range.from);
27779
27867
  setTo(range.to);
27780
27868
  setActivePreset(preset.value);
@@ -27782,8 +27870,12 @@ var init_DateRangePicker = __esm({
27782
27870
  },
27783
27871
  [emit]
27784
27872
  );
27873
+ const renderablePresets = React87.useMemo(
27874
+ () => presets.filter((p) => p.range !== void 0 || TOKEN_RANGES[p.value] !== void 0),
27875
+ [presets]
27876
+ );
27785
27877
  const presetButtons = React87.useMemo(
27786
- () => presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
27878
+ () => renderablePresets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
27787
27879
  Button,
27788
27880
  {
27789
27881
  variant: activePreset === preset.value ? "primary" : "ghost",
@@ -27793,7 +27885,7 @@ var init_DateRangePicker = __esm({
27793
27885
  },
27794
27886
  preset.value
27795
27887
  )),
27796
- [presets, activePreset, handlePreset]
27888
+ [renderablePresets, activePreset, handlePreset]
27797
27889
  );
27798
27890
  return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", className: cn(className), children: [
27799
27891
  /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "md", align: "end", children: [
@@ -27820,7 +27912,7 @@ var init_DateRangePicker = __esm({
27820
27912
  )
27821
27913
  ] })
27822
27914
  ] }),
27823
- presets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
27915
+ renderablePresets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
27824
27916
  ] });
27825
27917
  };
27826
27918
  DateRangePicker.displayName = "DateRangePicker";
@@ -28262,6 +28354,208 @@ var init_PhysicsCanvas = __esm({
28262
28354
  };
28263
28355
  }
28264
28356
  });
28357
+
28358
+ // lib/graphViewLayouts.ts
28359
+ function buildAdjacency(nodeIds, edges) {
28360
+ const known = new Set(nodeIds);
28361
+ const out = /* @__PURE__ */ new Map();
28362
+ const inMap = /* @__PURE__ */ new Map();
28363
+ for (const id of nodeIds) {
28364
+ out.set(id, []);
28365
+ inMap.set(id, []);
28366
+ }
28367
+ for (const edge of edges) {
28368
+ if (!known.has(edge.source) || !known.has(edge.target)) continue;
28369
+ out.get(edge.source)?.push(edge.target);
28370
+ inMap.get(edge.target)?.push(edge.source);
28371
+ }
28372
+ return { out, in: inMap };
28373
+ }
28374
+ function findRoots(nodeIds, adjacency) {
28375
+ return nodeIds.filter((id) => (adjacency.in.get(id)?.length ?? 0) === 0);
28376
+ }
28377
+ function assignLayers(nodeIds, adjacency, roots) {
28378
+ const layer = new Map(nodeIds.map((id) => [id, 0]));
28379
+ const onStack = /* @__PURE__ */ new Set();
28380
+ const visit = (id) => {
28381
+ onStack.add(id);
28382
+ const currentLayer = layer.get(id) ?? 0;
28383
+ for (const next of adjacency.out.get(id) ?? []) {
28384
+ if (onStack.has(next)) continue;
28385
+ const candidate = currentLayer + 1;
28386
+ if (candidate > (layer.get(next) ?? 0)) {
28387
+ layer.set(next, candidate);
28388
+ }
28389
+ visit(next);
28390
+ }
28391
+ onStack.delete(id);
28392
+ };
28393
+ for (const root of roots) visit(root);
28394
+ return layer;
28395
+ }
28396
+ function computeVisitOrder(nodeIds, adjacency, roots) {
28397
+ const order = /* @__PURE__ */ new Map();
28398
+ const visited = /* @__PURE__ */ new Set();
28399
+ let counter = 0;
28400
+ const visit = (id) => {
28401
+ if (visited.has(id)) return;
28402
+ visited.add(id);
28403
+ order.set(id, counter++);
28404
+ for (const next of adjacency.out.get(id) ?? []) visit(next);
28405
+ };
28406
+ for (const root of roots) visit(root);
28407
+ for (const id of nodeIds) {
28408
+ if (!visited.has(id)) order.set(id, counter++);
28409
+ }
28410
+ return order;
28411
+ }
28412
+ function bfsDepthAndOrder(nodeIds, adjacency, roots) {
28413
+ const depth = new Map(nodeIds.map((id) => [id, 0]));
28414
+ const visitOrder = /* @__PURE__ */ new Map();
28415
+ const visited = /* @__PURE__ */ new Set();
28416
+ const queue = [];
28417
+ let counter = 0;
28418
+ for (const root of roots) {
28419
+ if (visited.has(root)) continue;
28420
+ visited.add(root);
28421
+ depth.set(root, 0);
28422
+ visitOrder.set(root, counter++);
28423
+ queue.push(root);
28424
+ }
28425
+ let head = 0;
28426
+ while (head < queue.length) {
28427
+ const id = queue[head++];
28428
+ const d = depth.get(id) ?? 0;
28429
+ for (const next of adjacency.out.get(id) ?? []) {
28430
+ if (visited.has(next)) continue;
28431
+ visited.add(next);
28432
+ depth.set(next, d + 1);
28433
+ visitOrder.set(next, counter++);
28434
+ queue.push(next);
28435
+ }
28436
+ }
28437
+ for (const id of nodeIds) {
28438
+ if (!visited.has(id)) visitOrder.set(id, counter++);
28439
+ }
28440
+ return { depth, visitOrder };
28441
+ }
28442
+ function edgeWalkOrder(nodeIds, adjacency) {
28443
+ const visited = /* @__PURE__ */ new Set();
28444
+ const result = [];
28445
+ for (const start of nodeIds) {
28446
+ if (visited.has(start)) continue;
28447
+ let current = start;
28448
+ while (current !== void 0 && !visited.has(current)) {
28449
+ visited.add(current);
28450
+ result.push(current);
28451
+ const outs = adjacency.out.get(current) ?? [];
28452
+ current = outs.find((next) => !visited.has(next));
28453
+ }
28454
+ }
28455
+ return result;
28456
+ }
28457
+ function groupByTier(nodeIds, tierOf, maxTier) {
28458
+ const groups = Array.from({ length: maxTier + 1 }, () => []);
28459
+ for (const id of nodeIds) {
28460
+ groups[tierOf.get(id) ?? 0].push(id);
28461
+ }
28462
+ return groups;
28463
+ }
28464
+ function distributeAxis(count, start, end) {
28465
+ if (count <= 0) return [];
28466
+ const slot = (end - start) / count;
28467
+ return Array.from({ length: count }, (_, i) => start + slot * (i + 0.5));
28468
+ }
28469
+ function orderByParentPositionThenInput(group, adjacency, positioned, inputIndex) {
28470
+ const withKey = group.map((id) => {
28471
+ const parentValues = (adjacency.in.get(id) ?? []).map((p) => positioned.get(p)).filter((v) => v !== void 0);
28472
+ const avg = parentValues.length > 0 ? parentValues.reduce((a, b) => a + b, 0) / parentValues.length : Number.POSITIVE_INFINITY;
28473
+ return { id, avg, idx: inputIndex.get(id) ?? 0 };
28474
+ });
28475
+ withKey.sort((a, b) => a.avg !== b.avg ? a.avg - b.avg : a.idx - b.idx);
28476
+ return withKey.map((k) => k.id);
28477
+ }
28478
+ function layoutFlow(nodeIds, adjacency, roots, width, height, margin) {
28479
+ const inputIndex = new Map(nodeIds.map((id, i) => [id, i]));
28480
+ const layers = assignLayers(nodeIds, adjacency, roots);
28481
+ const maxLayer = Math.max(...Array.from(layers.values()));
28482
+ const layerGroups = groupByTier(nodeIds, layers, maxLayer);
28483
+ const positions = /* @__PURE__ */ new Map();
28484
+ const yById = /* @__PURE__ */ new Map();
28485
+ for (let l = 0; l <= maxLayer; l++) {
28486
+ const x = margin + l * (width - 2 * margin) / Math.max(1, maxLayer);
28487
+ const ordered2 = orderByParentPositionThenInput(layerGroups[l], adjacency, yById, inputIndex);
28488
+ const ys = distributeAxis(ordered2.length, margin, height - margin);
28489
+ ordered2.forEach((id, i) => {
28490
+ positions.set(id, { id, x, y: ys[i] });
28491
+ yById.set(id, ys[i]);
28492
+ });
28493
+ }
28494
+ return nodeIds.map((id) => positions.get(id));
28495
+ }
28496
+ function layoutTree(nodeIds, adjacency, roots, width, height, margin) {
28497
+ const effectiveRoots = roots.length > 0 ? roots : [nodeIds[0]];
28498
+ const layers = assignLayers(nodeIds, adjacency, effectiveRoots);
28499
+ const maxLayer = Math.max(...Array.from(layers.values()));
28500
+ const visitOrder = computeVisitOrder(nodeIds, adjacency, effectiveRoots);
28501
+ const layerGroups = groupByTier(nodeIds, layers, maxLayer);
28502
+ const positions = /* @__PURE__ */ new Map();
28503
+ for (let l = 0; l <= maxLayer; l++) {
28504
+ const ordered2 = [...layerGroups[l]].sort(
28505
+ (a, b) => (visitOrder.get(a) ?? 0) - (visitOrder.get(b) ?? 0)
28506
+ );
28507
+ const y = margin + l * (height - 2 * margin) / Math.max(1, maxLayer);
28508
+ const xs = distributeAxis(ordered2.length, margin, width - margin);
28509
+ ordered2.forEach((id, i) => positions.set(id, { id, x: xs[i], y }));
28510
+ }
28511
+ return nodeIds.map((id) => positions.get(id));
28512
+ }
28513
+ function layoutRadial(nodeIds, adjacency, roots, width, height, margin) {
28514
+ const cx = width / 2;
28515
+ const cy = height / 2;
28516
+ const maxRadius = Math.min(width, height) / 2 - margin;
28517
+ if (roots.length === 0) {
28518
+ const order = edgeWalkOrder(nodeIds, adjacency);
28519
+ const k = order.length;
28520
+ const positions2 = /* @__PURE__ */ new Map();
28521
+ order.forEach((id, i) => {
28522
+ const angle = i / k * 2 * Math.PI;
28523
+ positions2.set(id, { id, x: cx + maxRadius * Math.cos(angle), y: cy + maxRadius * Math.sin(angle) });
28524
+ });
28525
+ return nodeIds.map((id) => positions2.get(id));
28526
+ }
28527
+ const { depth, visitOrder } = bfsDepthAndOrder(nodeIds, adjacency, roots);
28528
+ const maxDepth = Math.max(...Array.from(depth.values()));
28529
+ const ringGroups = groupByTier(nodeIds, depth, maxDepth);
28530
+ const positions = /* @__PURE__ */ new Map();
28531
+ for (let d = 0; d <= maxDepth; d++) {
28532
+ const ordered2 = [...ringGroups[d]].sort(
28533
+ (a, b) => (visitOrder.get(a) ?? 0) - (visitOrder.get(b) ?? 0)
28534
+ );
28535
+ const radius = d * maxRadius / Math.max(1, maxDepth);
28536
+ const k = ordered2.length;
28537
+ ordered2.forEach((id, i) => {
28538
+ const angle = i / k * 2 * Math.PI;
28539
+ positions.set(id, { id, x: cx + radius * Math.cos(angle), y: cy + radius * Math.sin(angle) });
28540
+ });
28541
+ }
28542
+ return nodeIds.map((id) => positions.get(id));
28543
+ }
28544
+ function computeStaticLayout(mode, input) {
28545
+ const { nodeIds, edges, width, height } = input;
28546
+ const margin = input.margin ?? 40;
28547
+ if (nodeIds.length === 0) return [];
28548
+ if (nodeIds.length === 1) return [{ id: nodeIds[0], x: width / 2, y: height / 2 }];
28549
+ const adjacency = buildAdjacency(nodeIds, edges);
28550
+ const roots = findRoots(nodeIds, adjacency);
28551
+ if (mode === "flow") return layoutFlow(nodeIds, adjacency, roots, width, height, margin);
28552
+ if (mode === "tree") return layoutTree(nodeIds, adjacency, roots, width, height, margin);
28553
+ return layoutRadial(nodeIds, adjacency, roots, width, height, margin);
28554
+ }
28555
+ var init_graphViewLayouts = __esm({
28556
+ "lib/graphViewLayouts.ts"() {
28557
+ }
28558
+ });
28265
28559
  function resolveNodeColor(node, groups) {
28266
28560
  if (node.color) return node.color;
28267
28561
  if (node.group) {
@@ -28276,6 +28570,7 @@ var init_GraphView = __esm({
28276
28570
  "use client";
28277
28571
  init_cn();
28278
28572
  init_atoms();
28573
+ init_graphViewLayouts();
28279
28574
  GROUP_COLORS = [
28280
28575
  "#3b82f6",
28281
28576
  // blue-500
@@ -28306,11 +28601,13 @@ var init_GraphView = __esm({
28306
28601
  height: propHeight,
28307
28602
  className,
28308
28603
  showLabels = true,
28309
- zoomToFit = true
28604
+ zoomToFit = true,
28605
+ layout = "force"
28310
28606
  }) => {
28311
28607
  const { t } = hooks.useTranslate();
28312
28608
  const containerRef = React87.useRef(null);
28313
28609
  const animRef = React87.useRef(0);
28610
+ const arrowMarkerId = React87.useId();
28314
28611
  const [simNodes, setSimNodes] = React87.useState([]);
28315
28612
  const [settled, setSettled] = React87.useState(false);
28316
28613
  const [hoveredId, setHoveredId] = React87.useState(null);
@@ -28367,6 +28664,22 @@ var init_GraphView = __esm({
28367
28664
  fy: 0
28368
28665
  };
28369
28666
  });
28667
+ if (layout !== "force") {
28668
+ const points = computeStaticLayout(layout, {
28669
+ nodeIds: nodes.map((n) => n.id),
28670
+ edges,
28671
+ width: w,
28672
+ height: h
28673
+ });
28674
+ const pointById = new Map(points.map((p) => [p.id, p]));
28675
+ const laidOut = initialNodes.map((node) => {
28676
+ const point = pointById.get(node.id);
28677
+ return point ? { ...node, x: point.x, y: point.y } : node;
28678
+ });
28679
+ setSimNodes(laidOut);
28680
+ setSettled(true);
28681
+ return;
28682
+ }
28370
28683
  let iterations = 0;
28371
28684
  const maxIterations = 120;
28372
28685
  let currentNodes = initialNodes;
@@ -28435,7 +28748,7 @@ var init_GraphView = __esm({
28435
28748
  return () => {
28436
28749
  cancelAnimationFrame(animRef.current);
28437
28750
  };
28438
- }, [nodes, edges, w, h, groups]);
28751
+ }, [nodes, edges, w, h, groups, layout]);
28439
28752
  const viewBox = React87.useMemo(() => {
28440
28753
  if (!zoomToFit || !settled || simNodes.length === 0) {
28441
28754
  return `0 0 ${w} ${h}`;
@@ -28510,6 +28823,19 @@ var init_GraphView = __esm({
28510
28823
  viewBox,
28511
28824
  preserveAspectRatio: "xMidYMid meet",
28512
28825
  children: [
28826
+ layout !== "force" && /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx(
28827
+ "marker",
28828
+ {
28829
+ id: arrowMarkerId,
28830
+ viewBox: "0 0 10 10",
28831
+ refX: "9",
28832
+ refY: "5",
28833
+ markerWidth: "6",
28834
+ markerHeight: "6",
28835
+ orient: "auto-start-reverse",
28836
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M0,0 L10,5 L0,10 z", fill: "currentColor" })
28837
+ }
28838
+ ) }),
28513
28839
  edges.map((edge, idx) => {
28514
28840
  const source = nodeMap.get(edge.source);
28515
28841
  const target = nodeMap.get(edge.target);
@@ -28524,8 +28850,10 @@ var init_GraphView = __esm({
28524
28850
  x2: target.x,
28525
28851
  y2: target.y,
28526
28852
  stroke: edge.color ?? DEFAULT_EDGE_COLOR,
28853
+ color: edge.color ?? DEFAULT_EDGE_COLOR,
28527
28854
  strokeWidth: 1.5,
28528
- opacity: isHighlighted ? 0.8 : 0.15
28855
+ opacity: isHighlighted ? 0.8 : 0.15,
28856
+ markerEnd: layout !== "force" ? `url(#${arrowMarkerId})` : void 0
28529
28857
  }
28530
28858
  ),
28531
28859
  showLabels && edge.label && /* @__PURE__ */ jsxRuntime.jsx(