@magicborn/dialogue-forge 0.1.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.
Files changed (241) hide show
  1. package/README.md +233 -0
  2. package/bin/dialogue-forge.js +78 -0
  3. package/demo/app/layout.tsx +36 -0
  4. package/demo/app/page.tsx +440 -0
  5. package/demo/components/ThemeSwitcher.tsx +611 -0
  6. package/demo/next.config.mjs +7 -0
  7. package/demo/package.json +29 -0
  8. package/demo/postcss.config.mjs +7 -0
  9. package/demo/public/logo.svg +1 -0
  10. package/demo/styles/globals.css +19 -0
  11. package/demo/tailwind.config.ts +90 -0
  12. package/demo/tsconfig.json +42 -0
  13. package/dist/components/ChoiceEdgeV2.d.ts +3 -0
  14. package/dist/components/ChoiceEdgeV2.js +103 -0
  15. package/dist/components/CodeBlock.d.ts +8 -0
  16. package/dist/components/CodeBlock.js +24 -0
  17. package/dist/components/ConditionAutocomplete.d.ts +14 -0
  18. package/dist/components/ConditionAutocomplete.js +284 -0
  19. package/dist/components/ConditionalNodeV2.d.ts +16 -0
  20. package/dist/components/ConditionalNodeV2.js +147 -0
  21. package/dist/components/DialogueEditorV2.d.ts +22 -0
  22. package/dist/components/DialogueEditorV2.js +1170 -0
  23. package/dist/components/EdgeIcon.d.ts +8 -0
  24. package/dist/components/EdgeIcon.js +13 -0
  25. package/dist/components/ExampleLoader.d.ts +11 -0
  26. package/dist/components/ExampleLoader.js +52 -0
  27. package/dist/components/ExampleLoaderButton.d.ts +15 -0
  28. package/dist/components/ExampleLoaderButton.js +102 -0
  29. package/dist/components/FlagManager.d.ts +11 -0
  30. package/dist/components/FlagManager.js +282 -0
  31. package/dist/components/FlagSelector.d.ts +11 -0
  32. package/dist/components/FlagSelector.js +235 -0
  33. package/dist/components/GuidePanel.d.ts +7 -0
  34. package/dist/components/GuidePanel.js +1176 -0
  35. package/dist/components/Minimap.d.ts +16 -0
  36. package/dist/components/Minimap.js +93 -0
  37. package/dist/components/NPCEdgeV2.d.ts +3 -0
  38. package/dist/components/NPCEdgeV2.js +104 -0
  39. package/dist/components/NPCNodeV2.d.ts +26 -0
  40. package/dist/components/NPCNodeV2.js +86 -0
  41. package/dist/components/NodeEditor.d.ts +18 -0
  42. package/dist/components/NodeEditor.js +1025 -0
  43. package/dist/components/PlayView.d.ts +12 -0
  44. package/dist/components/PlayView.js +307 -0
  45. package/dist/components/PlayerNodeV2.d.ts +16 -0
  46. package/dist/components/PlayerNodeV2.js +139 -0
  47. package/dist/components/ReactFlowPOC.d.ts +61 -0
  48. package/dist/components/ReactFlowPOC.js +312 -0
  49. package/dist/components/ScenePlayer.d.ts +18 -0
  50. package/dist/components/ScenePlayer.js +196 -0
  51. package/dist/components/YarnView.d.ts +9 -0
  52. package/dist/components/YarnView.js +45 -0
  53. package/dist/components/ZoomControls.d.ts +11 -0
  54. package/dist/components/ZoomControls.js +34 -0
  55. package/dist/esm/components/ChoiceEdgeV2.d.ts +3 -0
  56. package/dist/esm/components/ChoiceEdgeV2.js +67 -0
  57. package/dist/esm/components/CodeBlock.d.ts +8 -0
  58. package/dist/esm/components/CodeBlock.js +18 -0
  59. package/dist/esm/components/ConditionAutocomplete.d.ts +14 -0
  60. package/dist/esm/components/ConditionAutocomplete.js +248 -0
  61. package/dist/esm/components/ConditionalNodeV2.d.ts +16 -0
  62. package/dist/esm/components/ConditionalNodeV2.js +111 -0
  63. package/dist/esm/components/DialogueEditorV2.d.ts +22 -0
  64. package/dist/esm/components/DialogueEditorV2.js +1134 -0
  65. package/dist/esm/components/EdgeIcon.d.ts +8 -0
  66. package/dist/esm/components/EdgeIcon.js +7 -0
  67. package/dist/esm/components/ExampleLoader.d.ts +11 -0
  68. package/dist/esm/components/ExampleLoader.js +46 -0
  69. package/dist/esm/components/ExampleLoaderButton.d.ts +15 -0
  70. package/dist/esm/components/ExampleLoaderButton.js +66 -0
  71. package/dist/esm/components/FlagManager.d.ts +11 -0
  72. package/dist/esm/components/FlagManager.js +246 -0
  73. package/dist/esm/components/FlagSelector.d.ts +11 -0
  74. package/dist/esm/components/FlagSelector.js +199 -0
  75. package/dist/esm/components/GuidePanel.d.ts +7 -0
  76. package/dist/esm/components/GuidePanel.js +1140 -0
  77. package/dist/esm/components/Minimap.d.ts +16 -0
  78. package/dist/esm/components/Minimap.js +57 -0
  79. package/dist/esm/components/NPCEdgeV2.d.ts +3 -0
  80. package/dist/esm/components/NPCEdgeV2.js +68 -0
  81. package/dist/esm/components/NPCNodeV2.d.ts +26 -0
  82. package/dist/esm/components/NPCNodeV2.js +80 -0
  83. package/dist/esm/components/NodeEditor.d.ts +18 -0
  84. package/dist/esm/components/NodeEditor.js +989 -0
  85. package/dist/esm/components/PlayView.d.ts +12 -0
  86. package/dist/esm/components/PlayView.js +271 -0
  87. package/dist/esm/components/PlayerNodeV2.d.ts +16 -0
  88. package/dist/esm/components/PlayerNodeV2.js +103 -0
  89. package/dist/esm/components/ReactFlowPOC.d.ts +61 -0
  90. package/dist/esm/components/ReactFlowPOC.js +275 -0
  91. package/dist/esm/components/ScenePlayer.d.ts +18 -0
  92. package/dist/esm/components/ScenePlayer.js +160 -0
  93. package/dist/esm/components/YarnView.d.ts +9 -0
  94. package/dist/esm/components/YarnView.js +39 -0
  95. package/dist/esm/components/ZoomControls.d.ts +11 -0
  96. package/dist/esm/components/ZoomControls.js +28 -0
  97. package/dist/esm/examples/example-loader.d.ts +29 -0
  98. package/dist/esm/examples/example-loader.js +103 -0
  99. package/dist/esm/examples/examples-registry.d.ts +38 -0
  100. package/dist/esm/examples/examples-registry.js +153 -0
  101. package/dist/esm/examples/index.d.ts +26 -0
  102. package/dist/esm/examples/index.js +50 -0
  103. package/dist/esm/examples/legacy-examples.d.ts +9 -0
  104. package/dist/esm/examples/legacy-examples.js +814 -0
  105. package/dist/esm/examples/yarn-examples.d.ts +35 -0
  106. package/dist/esm/examples/yarn-examples.js +181 -0
  107. package/dist/esm/index.d.ts +21 -0
  108. package/dist/esm/index.js +26 -0
  109. package/dist/esm/lib/flag-manager.d.ts +21 -0
  110. package/dist/esm/lib/flag-manager.js +93 -0
  111. package/dist/esm/lib/yarn-converter/__tests__/round-trip.test.d.ts +1 -0
  112. package/dist/esm/lib/yarn-converter/__tests__/round-trip.test.js +169 -0
  113. package/dist/esm/lib/yarn-converter.d.ts +17 -0
  114. package/dist/esm/lib/yarn-converter.js +521 -0
  115. package/dist/esm/lib/yarn-runner/__tests__/condition-evaluator.test.d.ts +1 -0
  116. package/dist/esm/lib/yarn-runner/__tests__/condition-evaluator.test.js +171 -0
  117. package/dist/esm/lib/yarn-runner/__tests__/node-processor.test.d.ts +1 -0
  118. package/dist/esm/lib/yarn-runner/__tests__/node-processor.test.js +237 -0
  119. package/dist/esm/lib/yarn-runner/__tests__/variable-manager.test.d.ts +1 -0
  120. package/dist/esm/lib/yarn-runner/__tests__/variable-manager.test.js +106 -0
  121. package/dist/esm/lib/yarn-runner/condition-evaluator.d.ts +12 -0
  122. package/dist/esm/lib/yarn-runner/condition-evaluator.js +56 -0
  123. package/dist/esm/lib/yarn-runner/index.d.ts +12 -0
  124. package/dist/esm/lib/yarn-runner/index.js +11 -0
  125. package/dist/esm/lib/yarn-runner/node-processor.d.ts +18 -0
  126. package/dist/esm/lib/yarn-runner/node-processor.js +129 -0
  127. package/dist/esm/lib/yarn-runner/variable-manager.d.ts +51 -0
  128. package/dist/esm/lib/yarn-runner/variable-manager.js +120 -0
  129. package/dist/esm/lib/yarn-runner/variable-operations.d.ts +16 -0
  130. package/dist/esm/lib/yarn-runner/variable-operations.js +88 -0
  131. package/dist/esm/types/conditionals.d.ts +29 -0
  132. package/dist/esm/types/conditionals.js +1 -0
  133. package/dist/esm/types/constants.d.ts +59 -0
  134. package/dist/esm/types/constants.js +55 -0
  135. package/dist/esm/types/flags.d.ts +49 -0
  136. package/dist/esm/types/flags.js +49 -0
  137. package/dist/esm/types/game-state.d.ts +62 -0
  138. package/dist/esm/types/game-state.js +6 -0
  139. package/dist/esm/types/index.d.ts +77 -0
  140. package/dist/esm/types/index.js +1 -0
  141. package/dist/esm/utils/constants.d.ts +5 -0
  142. package/dist/esm/utils/constants.js +5 -0
  143. package/dist/esm/utils/feature-flags.d.ts +11 -0
  144. package/dist/esm/utils/feature-flags.js +11 -0
  145. package/dist/esm/utils/game-state-flattener.d.ts +41 -0
  146. package/dist/esm/utils/game-state-flattener.js +135 -0
  147. package/dist/esm/utils/layout/collision.d.ts +27 -0
  148. package/dist/esm/utils/layout/collision.js +74 -0
  149. package/dist/esm/utils/layout/index.d.ts +82 -0
  150. package/dist/esm/utils/layout/index.js +98 -0
  151. package/dist/esm/utils/layout/registry.d.ts +91 -0
  152. package/dist/esm/utils/layout/registry.js +148 -0
  153. package/dist/esm/utils/layout/strategies/dagre.d.ts +19 -0
  154. package/dist/esm/utils/layout/strategies/dagre.js +182 -0
  155. package/dist/esm/utils/layout/strategies/force.d.ts +21 -0
  156. package/dist/esm/utils/layout/strategies/force.js +178 -0
  157. package/dist/esm/utils/layout/strategies/grid.d.ts +17 -0
  158. package/dist/esm/utils/layout/strategies/grid.js +91 -0
  159. package/dist/esm/utils/layout/strategies/index.d.ts +8 -0
  160. package/dist/esm/utils/layout/strategies/index.js +8 -0
  161. package/dist/esm/utils/layout/types.d.ts +100 -0
  162. package/dist/esm/utils/layout/types.js +7 -0
  163. package/dist/esm/utils/layout.d.ts +9 -0
  164. package/dist/esm/utils/layout.js +17 -0
  165. package/dist/esm/utils/node-helpers.d.ts +7 -0
  166. package/dist/esm/utils/node-helpers.js +94 -0
  167. package/dist/esm/utils/reactflow-converter.d.ts +42 -0
  168. package/dist/esm/utils/reactflow-converter.js +217 -0
  169. package/dist/examples/example-loader.d.ts +29 -0
  170. package/dist/examples/example-loader.js +109 -0
  171. package/dist/examples/examples-registry.d.ts +38 -0
  172. package/dist/examples/examples-registry.js +160 -0
  173. package/dist/examples/index.d.ts +26 -0
  174. package/dist/examples/index.js +63 -0
  175. package/dist/examples/legacy-examples.d.ts +9 -0
  176. package/dist/examples/legacy-examples.js +817 -0
  177. package/dist/examples/yarn-examples.d.ts +35 -0
  178. package/dist/examples/yarn-examples.js +189 -0
  179. package/dist/index.d.ts +21 -0
  180. package/dist/index.js +66 -0
  181. package/dist/lib/flag-manager.d.ts +21 -0
  182. package/dist/lib/flag-manager.js +99 -0
  183. package/dist/lib/yarn-converter/__tests__/round-trip.test.d.ts +1 -0
  184. package/dist/lib/yarn-converter/__tests__/round-trip.test.js +171 -0
  185. package/dist/lib/yarn-converter.d.ts +17 -0
  186. package/dist/lib/yarn-converter.js +525 -0
  187. package/dist/lib/yarn-runner/__tests__/condition-evaluator.test.d.ts +1 -0
  188. package/dist/lib/yarn-runner/__tests__/condition-evaluator.test.js +173 -0
  189. package/dist/lib/yarn-runner/__tests__/node-processor.test.d.ts +1 -0
  190. package/dist/lib/yarn-runner/__tests__/node-processor.test.js +239 -0
  191. package/dist/lib/yarn-runner/__tests__/variable-manager.test.d.ts +1 -0
  192. package/dist/lib/yarn-runner/__tests__/variable-manager.test.js +108 -0
  193. package/dist/lib/yarn-runner/condition-evaluator.d.ts +12 -0
  194. package/dist/lib/yarn-runner/condition-evaluator.js +60 -0
  195. package/dist/lib/yarn-runner/index.d.ts +12 -0
  196. package/dist/lib/yarn-runner/index.js +21 -0
  197. package/dist/lib/yarn-runner/node-processor.d.ts +18 -0
  198. package/dist/lib/yarn-runner/node-processor.js +133 -0
  199. package/dist/lib/yarn-runner/variable-manager.d.ts +51 -0
  200. package/dist/lib/yarn-runner/variable-manager.js +124 -0
  201. package/dist/lib/yarn-runner/variable-operations.d.ts +16 -0
  202. package/dist/lib/yarn-runner/variable-operations.js +92 -0
  203. package/dist/types/conditionals.d.ts +29 -0
  204. package/dist/types/conditionals.js +2 -0
  205. package/dist/types/constants.d.ts +59 -0
  206. package/dist/types/constants.js +58 -0
  207. package/dist/types/flags.d.ts +49 -0
  208. package/dist/types/flags.js +52 -0
  209. package/dist/types/game-state.d.ts +62 -0
  210. package/dist/types/game-state.js +7 -0
  211. package/dist/types/index.d.ts +77 -0
  212. package/dist/types/index.js +2 -0
  213. package/dist/utils/constants.d.ts +5 -0
  214. package/dist/utils/constants.js +8 -0
  215. package/dist/utils/feature-flags.d.ts +11 -0
  216. package/dist/utils/feature-flags.js +14 -0
  217. package/dist/utils/game-state-flattener.d.ts +41 -0
  218. package/dist/utils/game-state-flattener.js +140 -0
  219. package/dist/utils/layout/collision.d.ts +27 -0
  220. package/dist/utils/layout/collision.js +77 -0
  221. package/dist/utils/layout/index.d.ts +82 -0
  222. package/dist/utils/layout/index.js +109 -0
  223. package/dist/utils/layout/registry.d.ts +91 -0
  224. package/dist/utils/layout/registry.js +151 -0
  225. package/dist/utils/layout/strategies/dagre.d.ts +19 -0
  226. package/dist/utils/layout/strategies/dagre.js +189 -0
  227. package/dist/utils/layout/strategies/force.d.ts +21 -0
  228. package/dist/utils/layout/strategies/force.js +182 -0
  229. package/dist/utils/layout/strategies/grid.d.ts +17 -0
  230. package/dist/utils/layout/strategies/grid.js +95 -0
  231. package/dist/utils/layout/strategies/index.d.ts +8 -0
  232. package/dist/utils/layout/strategies/index.js +14 -0
  233. package/dist/utils/layout/types.d.ts +100 -0
  234. package/dist/utils/layout/types.js +8 -0
  235. package/dist/utils/layout.d.ts +9 -0
  236. package/dist/utils/layout.js +25 -0
  237. package/dist/utils/node-helpers.d.ts +7 -0
  238. package/dist/utils/node-helpers.js +101 -0
  239. package/dist/utils/reactflow-converter.d.ts +42 -0
  240. package/dist/utils/reactflow-converter.js +223 -0
  241. package/package.json +70 -0
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { DialogueTree } from '../types';
3
+ interface MinimapProps {
4
+ dialogue: DialogueTree;
5
+ viewport: {
6
+ x: number;
7
+ y: number;
8
+ width: number;
9
+ height: number;
10
+ scale: number;
11
+ };
12
+ onNavigate: (x: number, y: number) => void;
13
+ className?: string;
14
+ }
15
+ export declare function Minimap({ dialogue, viewport, onNavigate, className }: MinimapProps): React.JSX.Element;
16
+ export {};
@@ -0,0 +1,57 @@
1
+ import React, { useRef } from 'react';
2
+ import { NODE_TYPE } from '../types/constants';
3
+ const MINIMAP_SIZE = 200;
4
+ const NODE_SIZE = 4;
5
+ export function Minimap({ dialogue, viewport, onNavigate, className }) {
6
+ const minimapRef = useRef(null);
7
+ // Calculate bounds of all nodes
8
+ const bounds = React.useMemo(() => {
9
+ const nodes = Object.values(dialogue.nodes);
10
+ if (nodes.length === 0) {
11
+ return { minX: 0, minY: 0, maxX: 100, maxY: 100 };
12
+ }
13
+ const xs = nodes.map(n => n.x);
14
+ const ys = nodes.map(n => n.y);
15
+ const minX = Math.min(...xs);
16
+ const minY = Math.min(...ys);
17
+ const maxX = Math.max(...xs.map(x => x + 200)); // NODE_WIDTH
18
+ const maxY = Math.max(...ys.map(y => y + 100)); // NODE_HEIGHT
19
+ return { minX, minY, maxX, maxY };
20
+ }, [dialogue.nodes]);
21
+ const width = bounds.maxX - bounds.minX;
22
+ const height = bounds.maxY - bounds.minY;
23
+ const scaleX = MINIMAP_SIZE / Math.max(width, 100);
24
+ const scaleY = MINIMAP_SIZE / Math.max(height, 100);
25
+ const scale = Math.min(scaleX, scaleY);
26
+ const handleClick = (e) => {
27
+ if (!minimapRef.current)
28
+ return;
29
+ const rect = minimapRef.current.getBoundingClientRect();
30
+ const x = (e.clientX - rect.left) / scale - bounds.minX;
31
+ const y = (e.clientY - rect.top) / scale - bounds.minY;
32
+ onNavigate(x, y);
33
+ };
34
+ // Calculate viewport indicator position
35
+ // Account for graph scale and offset
36
+ const viewportX = ((viewport.x - bounds.minX) / viewport.scale) * scale;
37
+ const viewportY = ((viewport.y - bounds.minY) / viewport.scale) * scale;
38
+ const viewportWidth = (viewport.width / viewport.scale) * scale;
39
+ const viewportHeight = (viewport.height / viewport.scale) * scale;
40
+ return (React.createElement("div", { ref: minimapRef, className: `absolute bottom-4 right-4 bg-[#0d0d14] border border-[#2a2a3e] rounded-lg overflow-hidden ${className}`, style: { width: MINIMAP_SIZE, height: MINIMAP_SIZE }, onClick: handleClick },
41
+ React.createElement("svg", { width: MINIMAP_SIZE, height: MINIMAP_SIZE, className: "absolute inset-0" },
42
+ React.createElement("rect", { width: MINIMAP_SIZE, height: MINIMAP_SIZE, fill: "#0d0d14" }),
43
+ React.createElement("defs", null,
44
+ React.createElement("pattern", { id: "minimapGrid", width: "10", height: "10", patternUnits: "userSpaceOnUse" },
45
+ React.createElement("path", { d: "M 10 0 L 0 0 0 10", fill: "none", stroke: "#1a1a2e", strokeWidth: "0.5" }))),
46
+ React.createElement("rect", { width: MINIMAP_SIZE, height: MINIMAP_SIZE, fill: "url(#minimapGrid)" }),
47
+ Object.values(dialogue.nodes).map(node => {
48
+ const x = (node.x - bounds.minX) * scale;
49
+ const y = (node.y - bounds.minY) * scale;
50
+ const color = node.type === NODE_TYPE.NPC ? '#e94560' : '#8b5cf6';
51
+ return (React.createElement("g", { key: node.id },
52
+ React.createElement("rect", { x: x, y: y, width: NODE_SIZE * 2, height: NODE_SIZE * 2, fill: color, opacity: 0.6, stroke: color, strokeWidth: "0.5" }),
53
+ node.id === dialogue.startNodeId && (React.createElement("circle", { cx: x + NODE_SIZE, cy: y + NODE_SIZE, r: NODE_SIZE * 1.5, fill: "none", stroke: "#22c55e", strokeWidth: "1", opacity: 0.8 }))));
54
+ }),
55
+ React.createElement("rect", { x: viewportX, y: viewportY, width: viewportWidth, height: viewportHeight, fill: "none", stroke: "#06b6d4", strokeWidth: "2", opacity: 0.8, strokeDasharray: "4 4" })),
56
+ React.createElement("div", { className: "absolute top-1 left-1 text-[8px] text-gray-500 bg-[#0d0d14]/80 px-1 rounded" }, "Minimap")));
57
+ }
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import { EdgeProps } from 'reactflow';
3
+ export declare function NPCEdgeV2({ id, sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, selected, data, }: EdgeProps): React.JSX.Element;
@@ -0,0 +1,68 @@
1
+ import React, { useState } from 'react';
2
+ import { BaseEdge, getSmoothStepPath, getBezierPath, Position } from 'reactflow';
3
+ // Loop back edge color - now uses CSS variable var(--color-df-edge-loop)
4
+ export function NPCEdgeV2({ id, sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, selected, data, }) {
5
+ const [hovered, setHovered] = useState(false);
6
+ const isBackEdge = data?.isBackEdge ?? false;
7
+ // Use smooth step path for angular look (like the horizontal example)
8
+ // For back edges, use bezier for a more curved appearance
9
+ const [edgePath, labelX, labelY] = isBackEdge
10
+ ? getBezierPath({
11
+ sourceX,
12
+ sourceY,
13
+ sourcePosition,
14
+ targetX,
15
+ targetY,
16
+ targetPosition,
17
+ curvature: 0.5,
18
+ })
19
+ : getSmoothStepPath({
20
+ sourceX,
21
+ sourceY,
22
+ sourcePosition: sourcePosition || Position.Bottom,
23
+ targetX,
24
+ targetY,
25
+ targetPosition: targetPosition || Position.Top,
26
+ borderRadius: 8,
27
+ });
28
+ const isSelected = selected || hovered;
29
+ const isDimmed = data?.isDimmed ?? false;
30
+ // Use CSS variables for colors
31
+ const strokeColor = isDimmed
32
+ ? 'var(--color-df-edge-dimmed)'
33
+ : (isBackEdge ? 'var(--color-df-edge-loop)' : (isSelected ? 'var(--color-df-edge-default-hover)' : 'var(--color-df-edge-default)'));
34
+ const strokeWidth = isSelected ? 4 : 2;
35
+ const opacity = isDimmed ? 0.2 : (isSelected ? 1 : 0.6);
36
+ // Add glow effect when hovered (only if not dimmed)
37
+ const filter = hovered && !isDimmed ? 'drop-shadow(0 0 4px var(--color-df-edge-default-hover))' : undefined;
38
+ // Create a brighter version of the color for the pulse
39
+ const brightenColor = (hex, percent = 40) => {
40
+ const num = parseInt(hex.replace('#', ''), 16);
41
+ const r = Math.min(255, ((num >> 16) & 0xff) + percent);
42
+ const g = Math.min(255, ((num >> 8) & 0xff) + percent);
43
+ const b = Math.min(255, (num & 0xff) + percent);
44
+ return `#${((r << 16) | (g << 8) | b).toString(16).padStart(6, '0')}`;
45
+ };
46
+ const pulseColor = brightenColor(strokeColor, 50);
47
+ const shouldAnimate = data?.isInPathToSelected ?? false;
48
+ return (React.createElement(React.Fragment, null,
49
+ React.createElement("path", { d: edgePath, fill: "none", stroke: "transparent", strokeWidth: 20, style: { cursor: 'pointer', pointerEvents: 'all' }, onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false) }),
50
+ React.createElement(BaseEdge, { id: id, path: edgePath, style: {
51
+ stroke: strokeColor,
52
+ strokeWidth,
53
+ opacity,
54
+ cursor: 'pointer',
55
+ transition: 'all 0.2s ease',
56
+ filter,
57
+ // Dashed line for back edges
58
+ strokeDasharray: isBackEdge ? '8 4' : undefined,
59
+ }, markerEnd: isBackEdge ? `url(#loop-arrow-${id})` : 'url(#react-flow__arrowclosed)' }),
60
+ isBackEdge && (React.createElement("g", { transform: `translate(${labelX - 10}, ${labelY - 10})` },
61
+ React.createElement("circle", { cx: "10", cy: "10", r: "12", fill: "var(--color-df-base)", stroke: strokeColor, strokeWidth: "2" }),
62
+ React.createElement("text", { x: "10", y: "14", textAnchor: "middle", fontSize: "12", fill: strokeColor }, "\u21BA"))),
63
+ shouldAnimate && (React.createElement("circle", { r: "6", fill: pulseColor, opacity: 0.9 },
64
+ React.createElement("animateMotion", { dur: "2s", repeatCount: "indefinite", path: edgePath }))),
65
+ isBackEdge && (React.createElement("defs", null,
66
+ React.createElement("marker", { id: `loop-arrow-${id}`, markerWidth: "12.5", markerHeight: "12.5", viewBox: "-10 -10 20 20", markerUnits: "strokeWidth", orient: "auto", refX: "0", refY: "0" },
67
+ React.createElement("polyline", { stroke: "var(--color-df-edge-loop)", strokeLinecap: "round", strokeLinejoin: "round", fill: "var(--color-df-edge-loop)", points: "-5,-4 0,0 -5,4 -5,-4" }))))));
68
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * NPCNodeV2 - React Flow node component for NPC dialogue
3
+ *
4
+ * Displays:
5
+ * - Node header with ID and type
6
+ * - Speaker name (if present)
7
+ * - Content preview (truncated)
8
+ * - Flag indicators
9
+ * - Start/End badges when applicable
10
+ */
11
+ import React from 'react';
12
+ import { NodeProps } from 'reactflow';
13
+ import { DialogueNode } from '../types';
14
+ import { FlagSchema } from '../types/flags';
15
+ import { LayoutDirection } from '../utils/layout';
16
+ interface NPCNodeData {
17
+ node: DialogueNode;
18
+ flagSchema?: FlagSchema;
19
+ isDimmed?: boolean;
20
+ isInPath?: boolean;
21
+ layoutDirection?: LayoutDirection;
22
+ isStartNode?: boolean;
23
+ isEndNode?: boolean;
24
+ }
25
+ export declare function NPCNodeV2({ data, selected }: NodeProps<NPCNodeData>): React.JSX.Element;
26
+ export {};
@@ -0,0 +1,80 @@
1
+ /**
2
+ * NPCNodeV2 - React Flow node component for NPC dialogue
3
+ *
4
+ * Displays:
5
+ * - Node header with ID and type
6
+ * - Speaker name (if present)
7
+ * - Content preview (truncated)
8
+ * - Flag indicators
9
+ * - Start/End badges when applicable
10
+ */
11
+ import React from 'react';
12
+ import { Handle, Position } from 'reactflow';
13
+ import { MessageSquare, Play, Flag } from 'lucide-react';
14
+ // ============================================================================
15
+ // Styles
16
+ // ============================================================================
17
+ const FLAG_COLORS = {
18
+ dialogue: 'bg-df-flag-dialogue-bg text-df-flag-dialogue border-df-flag-dialogue',
19
+ quest: 'bg-df-flag-quest-bg text-df-flag-quest border-df-flag-quest',
20
+ achievement: 'bg-df-flag-achievement-bg text-df-flag-achievement border-df-flag-achievement',
21
+ item: 'bg-df-flag-item-bg text-df-flag-item border-df-flag-item',
22
+ stat: 'bg-df-flag-stat-bg text-df-flag-stat border-df-flag-stat',
23
+ title: 'bg-df-flag-title-bg text-df-flag-title border-df-flag-title',
24
+ global: 'bg-df-flag-global-bg text-df-flag-global border-df-flag-global',
25
+ };
26
+ function getFlagColorClass(type) {
27
+ return FLAG_COLORS[type] || FLAG_COLORS.dialogue;
28
+ }
29
+ // ============================================================================
30
+ // Component
31
+ // ============================================================================
32
+ export function NPCNodeV2({ data, selected }) {
33
+ const { node, flagSchema, isDimmed, isInPath, layoutDirection = 'TB', isStartNode, isEndNode } = data;
34
+ // Handle positions based on layout direction
35
+ const isHorizontal = layoutDirection === 'LR';
36
+ const targetPosition = isHorizontal ? Position.Left : Position.Top;
37
+ const sourcePosition = isHorizontal ? Position.Right : Position.Bottom;
38
+ // Border color based on state
39
+ const borderClass = selected
40
+ ? 'border-df-npc-selected shadow-lg shadow-df-glow'
41
+ : isStartNode
42
+ ? 'border-df-start shadow-md'
43
+ : isEndNode
44
+ ? 'border-df-end shadow-md'
45
+ : 'border-df-npc-border';
46
+ // Header background based on node type
47
+ const headerBgClass = isStartNode
48
+ ? 'bg-df-start-bg'
49
+ : isEndNode
50
+ ? 'bg-df-end-bg'
51
+ : 'bg-df-npc-header';
52
+ // Content preview (truncated)
53
+ const contentPreview = node.content.length > 60
54
+ ? node.content.slice(0, 60) + '...'
55
+ : node.content;
56
+ return (React.createElement("div", { className: `rounded-lg border-2 transition-all duration-300 ${borderClass} ${isInPath ? 'border-df-node-selected/70' : ''} bg-df-npc-bg min-w-[200px] relative`, style: isDimmed ? { opacity: 0.35, filter: 'saturate(0.3)' } : undefined },
57
+ isStartNode && (React.createElement("div", { className: "absolute -top-2 -left-2 bg-df-start text-df-text-primary text-[8px] font-bold px-1.5 py-0.5 rounded-full flex items-center gap-0.5 shadow-lg z-10" },
58
+ React.createElement(Play, { size: 8, fill: "currentColor" }),
59
+ " START")),
60
+ isEndNode && (React.createElement("div", { className: "absolute -top-2 -right-2 bg-df-end text-df-text-primary text-[8px] font-bold px-1.5 py-0.5 rounded-full flex items-center gap-0.5 shadow-lg z-10" },
61
+ React.createElement(Flag, { size: 8 }),
62
+ " END")),
63
+ React.createElement(Handle, { type: "target", position: targetPosition, className: "!bg-df-control-bg !border-df-control-border !w-4 !h-4 !rounded-full" }),
64
+ React.createElement("div", { className: `px-3 py-1.5 border-b border-df-control-border flex items-center gap-2 rounded-t-lg ${headerBgClass}` },
65
+ React.createElement(MessageSquare, { size: 12, className: "text-df-npc-selected" }),
66
+ React.createElement("span", { className: "text-[10px] font-mono text-df-text-secondary truncate flex-1" }, node.id),
67
+ React.createElement("span", { className: "text-[10px] text-df-text-tertiary" }, "NPC")),
68
+ React.createElement("div", { className: "px-3 py-2 min-h-[50px]" },
69
+ node.speaker && (React.createElement("div", { className: "text-[10px] text-df-npc-selected font-medium mb-1" }, node.speaker)),
70
+ React.createElement("div", { className: "text-xs text-df-text-primary line-clamp-2 bg-df-base border border-df-control-border rounded px-2 py-1" },
71
+ "\"",
72
+ contentPreview,
73
+ "\""),
74
+ node.setFlags && node.setFlags.length > 0 && (React.createElement("div", { className: "mt-1.5 flex flex-wrap gap-1" }, node.setFlags.map((flagId) => {
75
+ const flag = flagSchema?.flags.find((f) => f.id === flagId);
76
+ const flagType = flag?.type || 'dialogue';
77
+ return (React.createElement("span", { key: flagId, className: `text-[8px] px-1 py-0.5 rounded border ${getFlagColorClass(flagType)}`, title: flag?.name || flagId }, flagType === 'dialogue' ? 't' : flagType[0]));
78
+ })))),
79
+ React.createElement(Handle, { type: "source", position: sourcePosition, id: "next", className: "!bg-df-control-bg !border-df-control-border !w-4 !h-4 !rounded-full hover:!border-df-npc-selected hover:!bg-df-npc-selected/20" })));
80
+ }
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { DialogueNode, DialogueTree, Choice } from '../types';
3
+ import { FlagSchema } from '../types/flags';
4
+ interface NodeEditorProps {
5
+ node: DialogueNode;
6
+ dialogue: DialogueTree;
7
+ onUpdate: (updates: Partial<DialogueNode>) => void;
8
+ onDelete: () => void;
9
+ onAddChoice: () => void;
10
+ onUpdateChoice: (idx: number, updates: Partial<Choice>) => void;
11
+ onRemoveChoice: (idx: number) => void;
12
+ onClose: () => void;
13
+ onPlayFromHere?: (nodeId: string) => void;
14
+ onFocusNode?: (nodeId: string) => void;
15
+ flagSchema?: FlagSchema;
16
+ }
17
+ export declare function NodeEditor({ node, dialogue, onUpdate, onDelete, onAddChoice, onUpdateChoice, onRemoveChoice, onClose, onPlayFromHere, onFocusNode, flagSchema }: NodeEditorProps): React.JSX.Element;
18
+ export {};