@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,312 @@
1
+ "use strict";
2
+ /**
3
+ * Proof of Concept: React Flow Implementation with Custom Choice Edges
4
+ *
5
+ * This demonstrates how we can use React Flow's custom edges feature
6
+ * to implement our choice-based edge system.
7
+ *
8
+ * Key concepts:
9
+ * 1. Dynamic handles on PlayerNode (one handle per choice)
10
+ * 2. Custom ChoiceEdge component that colors based on choice index
11
+ * 3. Edge data stores choiceIndex and choiceId
12
+ *
13
+ * To use this, install: npm install reactflow
14
+ */
15
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28
+ }) : function(o, v) {
29
+ o["default"] = v;
30
+ });
31
+ var __importStar = (this && this.__importStar) || (function () {
32
+ var ownKeys = function(o) {
33
+ ownKeys = Object.getOwnPropertyNames || function (o) {
34
+ var ar = [];
35
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
+ return ar;
37
+ };
38
+ return ownKeys(o);
39
+ };
40
+ return function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
+ __setModuleDefault(result, mod);
45
+ return result;
46
+ };
47
+ })();
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.convertDialogueTreeToReactFlow = convertDialogueTreeToReactFlow;
50
+ exports.ReactFlowPOC = ReactFlowPOC;
51
+ const react_1 = __importStar(require("react"));
52
+ const constants_1 = require("../types/constants");
53
+ // Color scheme for choice edges (same as current implementation)
54
+ const CHOICE_COLORS = ['#e94560', '#8b5cf6', '#06b6d4', '#22c55e', '#f59e0b'];
55
+ /**
56
+ * Custom Edge Component for Player Choice Connections
57
+ *
58
+ * This edge:
59
+ * - Colors based on choice index (from edge data)
60
+ * - Uses bezier path for smooth curves
61
+ * - Matches our current visual style
62
+ */
63
+ // function ChoiceEdge({ id, sourceX, sourceY, targetX, targetY, data }: EdgeProps) {
64
+ // const [edgePath] = getBezierPath({
65
+ // sourceX,
66
+ // sourceY,
67
+ // targetX,
68
+ // targetY,
69
+ // });
70
+ //
71
+ // const choiceIndex = data?.choiceIndex ?? 0;
72
+ // const color = CHOICE_COLORS[choiceIndex % CHOICE_COLORS.length];
73
+ //
74
+ // return (
75
+ // <>
76
+ // <BaseEdge
77
+ // id={id}
78
+ // path={edgePath}
79
+ // style={{ stroke: color, strokeWidth: 2, opacity: 0.7 }}
80
+ // markerEnd={{
81
+ // type: 'arrowclosed',
82
+ // color: color,
83
+ // }}
84
+ // />
85
+ // </>
86
+ // );
87
+ // }
88
+ /**
89
+ * NPC Node Component
90
+ *
91
+ * Features:
92
+ * - Single output handle at bottom
93
+ * - Speaker + content display
94
+ * - Matches current styling
95
+ */
96
+ // function NPCNode({ data, selected }: NodeProps) {
97
+ // const node = data.node as DialogueNode;
98
+ //
99
+ // return (
100
+ // <div className={`rounded-lg border-2 transition-all ${
101
+ // selected ? 'border-[#e94560] shadow-lg shadow-[#e94560]/20' : 'border-[#2a2a3e]'
102
+ // } bg-[#1a1a2e] min-w-[200px]`}>
103
+ // {/* Input handle at top */}
104
+ // <Handle type="target" position={Position.Top} className="!bg-[#2a2a3e] !border-[#4a4a6a]" />
105
+ //
106
+ // {/* Header */}
107
+ // <div className="px-3 py-1.5 border-b border-[#2a2a3e] bg-[#12121a] flex items-center gap-2 rounded-t-lg">
108
+ // <span className="text-[10px] font-mono text-gray-500 truncate flex-1">{node.id}</span>
109
+ // <span className="text-[10px] text-gray-600">NPC</span>
110
+ // </div>
111
+ //
112
+ // {/* Content */}
113
+ // <div className="px-3 py-2 min-h-[50px]">
114
+ // {node.speaker && (
115
+ // <div className="text-[10px] text-[#e94560] font-medium">{node.speaker}</div>
116
+ // )}
117
+ // <div className="text-xs text-gray-400 line-clamp-2">
118
+ // {node.content.slice(0, 60) + (node.content.length > 60 ? '...' : '')}
119
+ // </div>
120
+ // </div>
121
+ //
122
+ // {/* Output handle at bottom (for nextNodeId connection) */}
123
+ // {node.nextNodeId && (
124
+ // <Handle
125
+ // type="source"
126
+ // position={Position.Bottom}
127
+ // className="!bg-[#2a2a3e] !border-[#4a4a6a] !w-4 !h-4"
128
+ // id="next"
129
+ // />
130
+ // )}
131
+ // </div>
132
+ // );
133
+ // }
134
+ /**
135
+ * Player Node Component
136
+ *
137
+ * Features:
138
+ * - Dynamic handles: one per choice (positioned on right side)
139
+ * - Each handle positioned at choice's Y offset
140
+ * - Matches current styling
141
+ */
142
+ // function PlayerNode({ data, selected }: NodeProps) {
143
+ // const node = data.node as DialogueNode;
144
+ // const choices = node.choices || [];
145
+ //
146
+ // return (
147
+ // <div className={`rounded-lg border-2 transition-all ${
148
+ // selected ? 'border-[#e94560] shadow-lg shadow-[#e94560]/20' : 'border-[#2a2a3e]'
149
+ // } bg-[#1e1e3a] min-w-[200px]`}>
150
+ // {/* Input handle at top */}
151
+ // <Handle type="target" position={Position.Top} className="!bg-[#2a2a3e] !border-[#4a4a6a]" />
152
+ //
153
+ // {/* Header */}
154
+ // <div className="px-3 py-1.5 border-b border-[#2a2a3e] bg-[#16162a] flex items-center gap-2 rounded-t-lg">
155
+ // <span className="text-[10px] font-mono text-gray-500 truncate flex-1">{node.id}</span>
156
+ // <span className="text-[10px] text-gray-600">PLAYER</span>
157
+ // </div>
158
+ //
159
+ // {/* Choices */}
160
+ // <div className="border-t border-[#2a2a3e]">
161
+ // {choices.map((choice, idx) => {
162
+ // const color = CHOICE_COLORS[idx % CHOICE_COLORS.length];
163
+ // // Calculate Y position: base offset + choice index * height
164
+ // const handleY = 20 + idx * 24; // Matches current: fromY + 10 + idx * 24
165
+ //
166
+ // return (
167
+ // <div
168
+ // key={choice.id}
169
+ // className="px-3 py-1 text-[10px] text-gray-400 flex items-center gap-2 border-b border-[#2a2a3e] last:border-0 relative"
170
+ // style={{ minHeight: 24 }}
171
+ // >
172
+ // <div className="flex-1 min-w-0">
173
+ // <span className="truncate block">{choice.text.slice(0, 25)}...</span>
174
+ // </div>
175
+ //
176
+ // {/* Dynamic handle for this choice */}
177
+ // <Handle
178
+ // type="source"
179
+ // position={Position.Right}
180
+ // id={`choice-${idx}`}
181
+ // style={{
182
+ // top: `${handleY}px`,
183
+ // right: '-6px',
184
+ // background: color,
185
+ // borderColor: color,
186
+ // width: '12px',
187
+ // height: '12px',
188
+ // }}
189
+ // className="!bg-[#2a2a3e] !border-2 hover:!border-[#e94560] hover:!bg-[#e94560]/20"
190
+ // />
191
+ // </div>
192
+ // );
193
+ // })}
194
+ // </div>
195
+ // </div>
196
+ // );
197
+ // }
198
+ /**
199
+ * Convert DialogueTree to React Flow format
200
+ */
201
+ function convertDialogueTreeToReactFlow(dialogue) {
202
+ const nodes = [];
203
+ const edges = [];
204
+ // Define node types
205
+ const nodeTypes = {
206
+ // 'npc': NPCNode,
207
+ // 'player': PlayerNode,
208
+ };
209
+ // Define edge types
210
+ const edgeTypes = {
211
+ // 'choice': ChoiceEdge,
212
+ };
213
+ // Convert nodes
214
+ Object.values(dialogue.nodes).forEach(node => {
215
+ nodes.push({
216
+ id: node.id,
217
+ type: node.type, // 'npc' or 'player'
218
+ position: { x: node.x, y: node.y },
219
+ data: { node },
220
+ selected: false,
221
+ });
222
+ });
223
+ // Convert edges
224
+ Object.values(dialogue.nodes).forEach(node => {
225
+ if (node.type === constants_1.NODE_TYPE.NPC && node.nextNodeId) {
226
+ // NPC -> next node (single connection)
227
+ edges.push({
228
+ id: `${node.id}-next`,
229
+ source: node.id,
230
+ target: node.nextNodeId,
231
+ sourceHandle: 'next',
232
+ type: 'default', // Use default edge for NPC connections
233
+ style: { stroke: '#4a4a6a', strokeWidth: 2 },
234
+ });
235
+ }
236
+ if (node.type === constants_1.NODE_TYPE.PLAYER && node.choices) {
237
+ // Player -> multiple choices (one edge per choice)
238
+ node.choices.forEach((choice, idx) => {
239
+ if (choice.nextNodeId) {
240
+ edges.push({
241
+ id: `${node.id}-choice-${idx}`,
242
+ source: node.id,
243
+ target: choice.nextNodeId,
244
+ sourceHandle: `choice-${idx}`, // Connect to specific choice handle
245
+ type: 'choice', // Use custom ChoiceEdge
246
+ data: {
247
+ choiceIndex: idx,
248
+ choiceId: choice.id,
249
+ },
250
+ });
251
+ }
252
+ });
253
+ }
254
+ });
255
+ return { nodes, edges, nodeTypes, edgeTypes };
256
+ }
257
+ /**
258
+ * Main React Flow Component (POC)
259
+ *
260
+ * Usage:
261
+ * ```tsx
262
+ * <ReactFlowProvider>
263
+ * <ReactFlowPOC dialogue={dialogueTree} />
264
+ * </ReactFlowProvider>
265
+ * ```
266
+ */
267
+ function ReactFlowPOC({ dialogue }) {
268
+ // Convert dialogue to React Flow format
269
+ const { nodes, edges, nodeTypes, edgeTypes } = (0, react_1.useMemo)(() => convertDialogueTreeToReactFlow(dialogue), [dialogue]);
270
+ // Handle node changes (drag, etc.)
271
+ const onNodesChange = (0, react_1.useCallback)((changes) => {
272
+ // Update dialogue tree positions
273
+ // This would sync back to our DialogueTree structure
274
+ console.log('Nodes changed:', changes);
275
+ }, []);
276
+ // Handle edge connections
277
+ const onConnect = (0, react_1.useCallback)((connection) => {
278
+ // Handle new edge connections
279
+ // This would update our DialogueTree structure
280
+ console.log('Connected:', connection);
281
+ }, []);
282
+ // Handle edge changes (delete, etc.)
283
+ const onEdgesChange = (0, react_1.useCallback)((changes) => {
284
+ console.log('Edges changed:', changes);
285
+ }, []);
286
+ return (react_1.default.createElement("div", { className: "w-full h-full" },
287
+ react_1.default.createElement("div", { className: "p-8 text-gray-400" },
288
+ react_1.default.createElement("h2", { className: "text-xl font-bold mb-4 text-white" }, "React Flow POC"),
289
+ react_1.default.createElement("p", { className: "mb-4" }, "This is a proof of concept for migrating to React Flow."),
290
+ react_1.default.createElement("p", { className: "mb-4" }, "To use this:"),
291
+ react_1.default.createElement("ol", { className: "list-decimal list-inside space-y-2 mb-4" },
292
+ react_1.default.createElement("li", null,
293
+ "Install React Flow: ",
294
+ react_1.default.createElement("code", { className: "bg-[#1a1a2e] px-2 py-1 rounded" }, "npm install reactflow")),
295
+ react_1.default.createElement("li", null, "Uncomment the React Flow imports and components"),
296
+ react_1.default.createElement("li", null, "Test with your dialogue tree")),
297
+ react_1.default.createElement("div", { className: "mt-8 p-4 bg-[#1a1a2e] rounded" },
298
+ react_1.default.createElement("h3", { className: "font-semibold mb-2" }, "Key Features:"),
299
+ react_1.default.createElement("ul", { className: "list-disc list-inside space-y-1 text-sm" },
300
+ react_1.default.createElement("li", null, "\u2705 Custom ChoiceEdge component with color-coded edges"),
301
+ react_1.default.createElement("li", null, "\u2705 Dynamic handles on PlayerNode (one per choice)"),
302
+ react_1.default.createElement("li", null, "\u2705 NPCNode with single output handle"),
303
+ react_1.default.createElement("li", null, "\u2705 Conversion functions (DialogueTree \u2194 React Flow)"),
304
+ react_1.default.createElement("li", null, "\u2705 Matches current visual style"))),
305
+ react_1.default.createElement("div", { className: "mt-4 p-4 bg-[#1a1a2e] rounded" },
306
+ react_1.default.createElement("h3", { className: "font-semibold mb-2" }, "Current Stats:"),
307
+ react_1.default.createElement("p", { className: "text-sm" },
308
+ "Nodes: ",
309
+ nodes.length,
310
+ ", Edges: ",
311
+ edges.length)))));
312
+ }
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import { DialogueTree, DialogueNode, Choice } from '../types';
3
+ import { FlagState, DialogueResult } from '../types/game-state';
4
+ import { type FlattenConfig } from '../utils/game-state-flattener';
5
+ export interface ScenePlayerProps {
6
+ dialogue: DialogueTree;
7
+ gameState: Record<string, any>;
8
+ startNodeId?: string;
9
+ onComplete: (result: DialogueResult) => void;
10
+ onFlagUpdate?: (flags: FlagState) => void;
11
+ flattenConfig?: FlattenConfig;
12
+ onNodeEnter?: (nodeId: string, node: DialogueNode) => void;
13
+ onNodeExit?: (nodeId: string, node: DialogueNode) => void;
14
+ onChoiceSelect?: (nodeId: string, choice: Choice) => void;
15
+ onDialogueStart?: () => void;
16
+ onDialogueEnd?: () => void;
17
+ }
18
+ export declare function ScenePlayer({ dialogue, gameState, startNodeId, onComplete, onFlagUpdate, flattenConfig, onNodeEnter, onNodeExit, onChoiceSelect, onDialogueStart, onDialogueEnd, }: ScenePlayerProps): React.JSX.Element;
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ScenePlayer = ScenePlayer;
37
+ const react_1 = __importStar(require("react"));
38
+ const flag_manager_1 = require("../lib/flag-manager");
39
+ const game_state_flattener_1 = require("../utils/game-state-flattener");
40
+ function ScenePlayer({ dialogue, gameState, startNodeId, onComplete, onFlagUpdate, flattenConfig, onNodeEnter, onNodeExit, onChoiceSelect, onDialogueStart, onDialogueEnd, }) {
41
+ // Validate and extract flags from gameState
42
+ const initialFlags = (0, react_1.useMemo)(() => {
43
+ try {
44
+ (0, game_state_flattener_1.validateGameState)(gameState);
45
+ return (0, game_state_flattener_1.extractFlagsFromGameState)(gameState, flattenConfig);
46
+ }
47
+ catch (error) {
48
+ console.error('ScenePlayer: Invalid gameState', error);
49
+ throw error;
50
+ }
51
+ }, [gameState, flattenConfig]);
52
+ const [currentNodeId, setCurrentNodeId] = (0, react_1.useState)(startNodeId || dialogue.startNodeId);
53
+ const [flags, setFlags] = (0, react_1.useState)(initialFlags);
54
+ const [history, setHistory] = (0, react_1.useState)([]);
55
+ const [isTyping, setIsTyping] = (0, react_1.useState)(false);
56
+ const [visitedNodes, setVisitedNodes] = (0, react_1.useState)(new Set());
57
+ const chatEndRef = (0, react_1.useRef)(null);
58
+ // Re-extract flags when gameState changes
59
+ (0, react_1.useEffect)(() => {
60
+ try {
61
+ (0, game_state_flattener_1.validateGameState)(gameState);
62
+ const newFlags = (0, game_state_flattener_1.extractFlagsFromGameState)(gameState, flattenConfig);
63
+ setFlags(newFlags);
64
+ }
65
+ catch (error) {
66
+ console.error('ScenePlayer: Failed to update flags from gameState', error);
67
+ }
68
+ }, [gameState, flattenConfig]);
69
+ // Initialize dialogue
70
+ (0, react_1.useEffect)(() => {
71
+ if (currentNodeId === dialogue.startNodeId) {
72
+ onDialogueStart?.();
73
+ }
74
+ }, []); // Only on mount
75
+ // Process current node
76
+ (0, react_1.useEffect)(() => {
77
+ const node = dialogue.nodes[currentNodeId];
78
+ if (!node)
79
+ return;
80
+ // Call onNodeEnter hook
81
+ onNodeEnter?.(currentNodeId, node);
82
+ if (node.type === 'npc') {
83
+ setIsTyping(true);
84
+ const timer = setTimeout(() => {
85
+ // Mark as visited
86
+ setVisitedNodes(prev => new Set([...prev, node.id]));
87
+ // Update flags
88
+ if (node.setFlags && node.setFlags.length > 0) {
89
+ const updated = (0, flag_manager_1.mergeFlagUpdates)(flags, node.setFlags);
90
+ setFlags(updated);
91
+ onFlagUpdate?.(updated);
92
+ }
93
+ // Add to history
94
+ setHistory(prev => [...prev, {
95
+ nodeId: node.id,
96
+ type: 'npc',
97
+ speaker: node.speaker,
98
+ content: node.content
99
+ }]);
100
+ setIsTyping(false);
101
+ // Call onNodeExit before moving to next
102
+ onNodeExit?.(currentNodeId, node);
103
+ // Auto-advance if there's a next node
104
+ if (node.nextNodeId) {
105
+ setTimeout(() => setCurrentNodeId(node.nextNodeId), 300);
106
+ }
107
+ else {
108
+ // Dialogue complete
109
+ onDialogueEnd?.();
110
+ onComplete({
111
+ updatedFlags: flags,
112
+ dialogueTree: dialogue,
113
+ completedNodeIds: Array.from(visitedNodes)
114
+ });
115
+ }
116
+ }, 500);
117
+ return () => clearTimeout(timer);
118
+ }
119
+ }, [currentNodeId, dialogue, flags, onNodeEnter, onNodeExit, onDialogueEnd, onComplete, onFlagUpdate]);
120
+ (0, react_1.useEffect)(() => {
121
+ chatEndRef.current?.scrollIntoView({ behavior: 'smooth' });
122
+ }, [history, isTyping]);
123
+ const currentNode = dialogue.nodes[currentNodeId];
124
+ // Filter choices based on conditions and flags
125
+ const availableChoices = currentNode?.choices?.filter(choice => {
126
+ if (!choice.conditions)
127
+ return true;
128
+ return choice.conditions.every(cond => {
129
+ const flagValue = flags[cond.flag];
130
+ const hasFlag = flagValue !== undefined && flagValue !== false && flagValue !== 0 && flagValue !== '';
131
+ return cond.operator === 'is_set' ? hasFlag : !hasFlag;
132
+ });
133
+ }) || [];
134
+ const handleChoice = (choice) => {
135
+ const currentNode = dialogue.nodes[currentNodeId];
136
+ // Call onChoiceSelect hook
137
+ onChoiceSelect?.(currentNodeId, choice);
138
+ // Call onNodeExit for current player node
139
+ if (currentNode) {
140
+ onNodeExit?.(currentNodeId, currentNode);
141
+ }
142
+ // Add to history
143
+ setHistory(prev => [...prev, {
144
+ nodeId: choice.id,
145
+ type: 'player',
146
+ content: choice.text
147
+ }]);
148
+ // Update flags
149
+ if (choice.setFlags && choice.setFlags.length > 0) {
150
+ const updated = (0, flag_manager_1.mergeFlagUpdates)(flags, choice.setFlags);
151
+ setFlags(updated);
152
+ onFlagUpdate?.(updated);
153
+ }
154
+ // Move to next node
155
+ if (choice.nextNodeId) {
156
+ setCurrentNodeId(choice.nextNodeId);
157
+ }
158
+ else {
159
+ // Choice leads nowhere - dialogue complete
160
+ onComplete({
161
+ updatedFlags: flags,
162
+ dialogueTree: dialogue,
163
+ completedNodeIds: Array.from(visitedNodes)
164
+ });
165
+ }
166
+ };
167
+ return (react_1.default.createElement("div", { className: "flex-1 flex flex-col" },
168
+ react_1.default.createElement("div", { className: "flex-1 overflow-y-auto p-4" },
169
+ react_1.default.createElement("div", { className: "max-w-2xl mx-auto space-y-4" },
170
+ history.map((entry, idx) => (react_1.default.createElement("div", { key: idx, className: `flex ${entry.type === 'player' ? 'justify-end' : 'justify-start'}` },
171
+ react_1.default.createElement("div", { className: `max-w-[80%] rounded-2xl px-4 py-3 ${entry.type === 'player'
172
+ ? 'bg-[#e94560] text-white rounded-br-md'
173
+ : 'bg-[#1a1a2e] text-gray-100 rounded-bl-md'}` },
174
+ entry.type === 'npc' && entry.speaker && (react_1.default.createElement("div", { className: "text-xs text-[#e94560] font-medium mb-1" }, entry.speaker)),
175
+ react_1.default.createElement("div", { className: "whitespace-pre-wrap" }, entry.content))))),
176
+ isTyping && (react_1.default.createElement("div", { className: "flex justify-start" },
177
+ react_1.default.createElement("div", { className: "bg-[#1a1a2e] rounded-2xl rounded-bl-md px-4 py-3" },
178
+ react_1.default.createElement("div", { className: "flex gap-1" },
179
+ react_1.default.createElement("span", { className: "w-2 h-2 bg-[#e94560] rounded-full animate-bounce", style: { animationDelay: '0ms' } }),
180
+ react_1.default.createElement("span", { className: "w-2 h-2 bg-[#e94560] rounded-full animate-bounce", style: { animationDelay: '150ms' } }),
181
+ react_1.default.createElement("span", { className: "w-2 h-2 bg-[#e94560] rounded-full animate-bounce", style: { animationDelay: '300ms' } }))))),
182
+ react_1.default.createElement("div", { ref: chatEndRef }))),
183
+ currentNode?.type === 'player' && !isTyping && availableChoices.length > 0 && (react_1.default.createElement("div", { className: "border-t border-[#1a1a2e] bg-[#0d0d14]/80 backdrop-blur-sm p-4" },
184
+ react_1.default.createElement("div", { className: "max-w-2xl mx-auto space-y-2" }, availableChoices.map((choice) => (react_1.default.createElement("button", { key: choice.id, onClick: () => handleChoice(choice), className: "w-full text-left px-4 py-3 rounded-lg border border-[#2a2a3e] hover:border-[#e94560] bg-[#12121a] hover:bg-[#1a1a2e] text-gray-200 transition-all group flex items-center justify-between" },
185
+ react_1.default.createElement("span", null, choice.text),
186
+ react_1.default.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", className: "text-gray-600 group-hover:text-[#e94560] transition-colors" },
187
+ react_1.default.createElement("polyline", { points: "9 18 15 12 9 6" })))))))),
188
+ currentNode?.type === 'npc' && !currentNode.nextNodeId && !isTyping && (react_1.default.createElement("div", { className: "border-t border-[#1a1a2e] bg-[#0d0d14]/80 backdrop-blur-sm p-4" },
189
+ react_1.default.createElement("div", { className: "max-w-2xl mx-auto text-center" },
190
+ react_1.default.createElement("p", { className: "text-gray-500 mb-3" }, "Dialogue complete"),
191
+ react_1.default.createElement("button", { onClick: () => onComplete({
192
+ updatedFlags: flags,
193
+ dialogueTree: dialogue,
194
+ completedNodeIds: Array.from(visitedNodes)
195
+ }), className: "px-4 py-2 bg-[#e94560] hover:bg-[#d63850] text-white rounded-lg transition-colors" }, "Close"))))));
196
+ }
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import { DialogueTree } from '../types';
3
+ interface YarnViewProps {
4
+ dialogue: DialogueTree;
5
+ onExport: () => void;
6
+ onImport?: (yarn: string) => void;
7
+ }
8
+ export declare function YarnView({ dialogue, onExport, onImport }: YarnViewProps): React.JSX.Element;
9
+ export {};
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.YarnView = YarnView;
7
+ const react_1 = __importDefault(require("react"));
8
+ const yarn_converter_1 = require("../lib/yarn-converter");
9
+ function YarnView({ dialogue, onExport, onImport }) {
10
+ const fileInputRef = react_1.default.useRef(null);
11
+ const handleImport = (e) => {
12
+ const file = e.target.files?.[0];
13
+ if (!file)
14
+ return;
15
+ const reader = new FileReader();
16
+ reader.onload = (ev) => {
17
+ const content = ev.target?.result;
18
+ if (onImport) {
19
+ onImport(content);
20
+ }
21
+ };
22
+ reader.readAsText(file);
23
+ e.target.value = '';
24
+ };
25
+ return (react_1.default.createElement("main", { className: "flex-1 flex flex-col bg-[#0d0d14] overflow-hidden" },
26
+ react_1.default.createElement("div", { className: "border-b border-[#1a1a2e] px-4 py-2 flex items-center justify-between flex-shrink-0" },
27
+ react_1.default.createElement("span", { className: "text-sm text-gray-400" }, "Yarn Spinner Output"),
28
+ react_1.default.createElement("div", { className: "flex items-center gap-2" },
29
+ onImport && (react_1.default.createElement(react_1.default.Fragment, null,
30
+ react_1.default.createElement("button", { onClick: () => fileInputRef.current?.click(), className: "px-3 py-1.5 bg-[#2a2a3e] hover:bg-[#3a3a4e] text-gray-300 text-sm rounded flex items-center gap-2" },
31
+ react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
32
+ react_1.default.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
33
+ react_1.default.createElement("polyline", { points: "17 8 12 3 7 8" }),
34
+ react_1.default.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })),
35
+ "Import .yarn"),
36
+ react_1.default.createElement("input", { ref: fileInputRef, type: "file", accept: ".yarn", onChange: handleImport, className: "hidden" }))),
37
+ react_1.default.createElement("button", { onClick: onExport, className: "px-3 py-1.5 bg-[#e94560] hover:bg-[#d63850] text-white text-sm rounded flex items-center gap-2" },
38
+ react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
39
+ react_1.default.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
40
+ react_1.default.createElement("polyline", { points: "7 10 12 15 17 10" }),
41
+ react_1.default.createElement("line", { x1: "12", y1: "15", x2: "12", y2: "3" })),
42
+ "Download .yarn"))),
43
+ react_1.default.createElement("div", { className: "flex-1 overflow-y-auto p-4 min-h-0" },
44
+ react_1.default.createElement("pre", { className: "font-mono text-sm text-gray-300 whitespace-pre-wrap bg-[#08080c] rounded-lg p-4 border border-[#1a1a2e]" }, (0, yarn_converter_1.exportToYarn)(dialogue)))));
45
+ }
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ interface ZoomControlsProps {
3
+ scale: number;
4
+ onZoomIn: () => void;
5
+ onZoomOut: () => void;
6
+ onZoomFit: () => void;
7
+ onZoomToSelection?: () => void;
8
+ className?: string;
9
+ }
10
+ export declare function ZoomControls({ scale, onZoomIn, onZoomOut, onZoomFit, onZoomToSelection, className }: ZoomControlsProps): React.JSX.Element;
11
+ export {};
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ZoomControls = ZoomControls;
7
+ const react_1 = __importDefault(require("react"));
8
+ function ZoomControls({ scale, onZoomIn, onZoomOut, onZoomFit, onZoomToSelection, className }) {
9
+ const zoomPercent = Math.round(scale * 100);
10
+ return (react_1.default.createElement("div", { className: `flex flex-col gap-1 ${className}` },
11
+ react_1.default.createElement("div", { className: "bg-[#0d0d14] border border-[#2a2a3e] rounded px-2 py-1 text-xs text-gray-400 text-center mb-1" },
12
+ zoomPercent,
13
+ "%"),
14
+ react_1.default.createElement("div", { className: "flex flex-col gap-1 bg-[#0d0d14] border border-[#2a2a3e] rounded-lg p-1" },
15
+ react_1.default.createElement("button", { onClick: onZoomIn, className: "p-1.5 hover:bg-[#1a1a2e] rounded text-gray-400 hover:text-white transition-colors", title: "Zoom In (Ctrl +)" },
16
+ react_1.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
17
+ react_1.default.createElement("circle", { cx: "11", cy: "11", r: "8" }),
18
+ react_1.default.createElement("line", { x1: "11", y1: "8", x2: "11", y2: "14" }),
19
+ react_1.default.createElement("line", { x1: "8", y1: "11", x2: "14", y2: "11" }))),
20
+ react_1.default.createElement("button", { onClick: onZoomOut, className: "p-1.5 hover:bg-[#1a1a2e] rounded text-gray-400 hover:text-white transition-colors", title: "Zoom Out (Ctrl -)" },
21
+ react_1.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
22
+ react_1.default.createElement("circle", { cx: "11", cy: "11", r: "8" }),
23
+ react_1.default.createElement("line", { x1: "8", y1: "11", x2: "14", y2: "11" }))),
24
+ react_1.default.createElement("div", { className: "h-px bg-[#2a2a3e] my-1" }),
25
+ react_1.default.createElement("button", { onClick: onZoomFit, className: "p-1.5 hover:bg-[#1a1a2e] rounded text-gray-400 hover:text-white transition-colors", title: "Zoom to Fit (Ctrl 0)" },
26
+ react_1.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
27
+ react_1.default.createElement("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
28
+ react_1.default.createElement("path", { d: "M8 8h8v8" }))),
29
+ onZoomToSelection && (react_1.default.createElement("button", { onClick: onZoomToSelection, className: "p-1.5 hover:bg-[#1a1a2e] rounded text-gray-400 hover:text-white transition-colors", title: "Zoom to Selection" },
30
+ react_1.default.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
31
+ react_1.default.createElement("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
32
+ react_1.default.createElement("path", { d: "M8 8h8v8" }),
33
+ react_1.default.createElement("circle", { cx: "12", cy: "12", r: "2" })))))));
34
+ }
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import { EdgeProps } from 'reactflow';
3
+ export declare function ChoiceEdgeV2({ id, sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, data, selected, }: EdgeProps): React.JSX.Element;