@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,35 @@
1
+ /**
2
+ * Inline Yarn file contents for examples
3
+ * This allows examples to be bundled and loaded synchronously
4
+ *
5
+ * To add a new example:
6
+ * 1. Create a .yarn file in the examples directory
7
+ * 2. Copy its content here as a string literal
8
+ * 3. Add it to the yarnExamplesContent object
9
+ */
10
+ import { DialogueTree } from '../types';
11
+ /**
12
+ * Load all examples synchronously
13
+ * This should be called once at initialization
14
+ */
15
+ export declare function loadAllExamples(): Record<string, DialogueTree>;
16
+ /**
17
+ * Get a loaded example dialogue
18
+ */
19
+ export declare function getExampleDialogue(exampleId: string): DialogueTree | null;
20
+ /**
21
+ * Get all loaded examples
22
+ */
23
+ export declare function getAllExampleDialogues(): Record<string, DialogueTree>;
24
+ /**
25
+ * Get flag schema for an example
26
+ */
27
+ export declare function getExampleFlagSchema(exampleId: string): import("..").FlagSchema | null;
28
+ /**
29
+ * Check if an example has Yarn content available
30
+ */
31
+ export declare function hasExampleContent(exampleId: string): boolean;
32
+ /**
33
+ * Get list of example IDs that have content available
34
+ */
35
+ export declare function getAvailableExampleIds(): string[];
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Inline Yarn file contents for examples
3
+ * This allows examples to be bundled and loaded synchronously
4
+ *
5
+ * To add a new example:
6
+ * 1. Create a .yarn file in the examples directory
7
+ * 2. Copy its content here as a string literal
8
+ * 3. Add it to the yarnExamplesContent object
9
+ */
10
+ import { importFromYarn } from '../lib/yarn-converter';
11
+ import { examplesRegistry, exampleFlagSchemas } from './examples-registry';
12
+ /**
13
+ * Map of example ID to Yarn file content
14
+ * All examples are stored as Yarn strings here for easy discovery and maintenance
15
+ */
16
+ const yarnExamplesContent = {
17
+ 'variable-operations': `title: merchant_shop
18
+ ---
19
+ Merchant: Welcome to my shop, {$player_name}!
20
+ Merchant: You currently have {$stat_gold} gold pieces.
21
+ <<if $stat_gold >= 100>>
22
+ Merchant: You can afford the sword! It costs 100 gold.
23
+ -> Buy the sword
24
+ <<set $item_sword = true>>
25
+ <<set $stat_gold -= 100>>
26
+ Merchant: Thank you for your purchase! You now have {$stat_gold} gold.
27
+ <<jump after_purchase>>
28
+ -> Maybe later
29
+ Merchant: Come back anytime!
30
+ <<jump end>>
31
+ <<elseif $stat_gold >= 50>>
32
+ Merchant: You can afford the potion! It costs 50 gold.
33
+ -> Buy the potion
34
+ <<set $item_potion = true>>
35
+ <<set $stat_gold -= 50>>
36
+ Merchant: Thank you! You now have {$stat_gold} gold.
37
+ <<jump after_purchase>>
38
+ -> Save up for the sword
39
+ Merchant: Wise choice! Come back when you have more gold.
40
+ <<jump end>>
41
+ <<else>>
42
+ Merchant: I'm sorry, but you don't have enough gold for anything.
43
+ Merchant: Come back when you have at least 50 gold pieces.
44
+ <<jump end>>
45
+ <<endif>>
46
+ ===
47
+
48
+ title: after_purchase
49
+ ---
50
+ Merchant: Is there anything else you'd like?
51
+ <<set $stat_reputation += 5>>
52
+ Merchant: Your reputation with me has increased! It's now {$stat_reputation}.
53
+ -> Browse more
54
+ <<jump merchant_shop>>
55
+ -> Leave
56
+ Merchant: Thanks for shopping!
57
+ <<jump end>>
58
+ ===
59
+
60
+ title: quest_reward
61
+ ---
62
+ QuestGiver: You've completed the quest! Here's your reward.
63
+ <<set $stat_gold += 500>>
64
+ <<set $stat_experience += 100>>
65
+ <<set $quest_dragon_slayer = "complete">>
66
+ QuestGiver: You received 500 gold and 100 experience!
67
+ QuestGiver: You now have {$stat_gold} gold and {$stat_experience} experience points.
68
+ <<jump end>>
69
+ ===
70
+
71
+ title: stat_multiplier
72
+ ---
73
+ Trainer: I can double your strength for a price.
74
+ <<if $stat_gold >= 200>>
75
+ Trainer: For 200 gold, I'll double your strength stat.
76
+ -> Pay for training
77
+ <<set $stat_strength *= 2>>
78
+ <<set $stat_gold -= 200>>
79
+ Trainer: Your strength is now {$stat_strength}!
80
+ <<jump end>>
81
+ -> Not right now
82
+ Trainer: Come back when you're ready.
83
+ <<jump end>>
84
+ <<else>>
85
+ Trainer: You need 200 gold for this training.
86
+ <<jump end>>
87
+ <<endif>>
88
+ ===
89
+
90
+ title: string_variables
91
+ ---
92
+ NPC: Hello, {$player_name}! Welcome to {$location_name}.
93
+ NPC: Your title is {$player_title}.
94
+ <<set $greeting_count += 1>>
95
+ NPC: I've greeted you {$greeting_count} times now.
96
+ <<if $greeting_count >= 5>>
97
+ NPC: You're a regular here! Let me give you a discount.
98
+ <<set $stat_reputation += 10>>
99
+ <<endif>>
100
+ <<jump end>>
101
+ ===
102
+
103
+ title: end
104
+ ---
105
+ ===
106
+ `,
107
+ // Add more examples here as they're converted to Yarn format
108
+ };
109
+ /**
110
+ * Pre-loaded examples cache
111
+ */
112
+ let examplesCache = {};
113
+ /**
114
+ * Load all examples synchronously
115
+ * This should be called once at initialization
116
+ */
117
+ export function loadAllExamples() {
118
+ if (Object.keys(examplesCache).length > 0) {
119
+ return examplesCache;
120
+ }
121
+ const loaded = {};
122
+ for (const metadata of examplesRegistry) {
123
+ const yarnContent = yarnExamplesContent[metadata.id];
124
+ if (yarnContent) {
125
+ try {
126
+ const dialogue = importFromYarn(yarnContent, metadata.title);
127
+ loaded[metadata.id] = dialogue;
128
+ metadata.nodeCount = Object.keys(dialogue.nodes).length;
129
+ }
130
+ catch (error) {
131
+ console.error(`Error loading example ${metadata.id}:`, error);
132
+ }
133
+ }
134
+ }
135
+ examplesCache = loaded;
136
+ return loaded;
137
+ }
138
+ // Pre-load examples when module is imported
139
+ loadAllExamples();
140
+ /**
141
+ * Get a loaded example dialogue
142
+ */
143
+ export function getExampleDialogue(exampleId) {
144
+ if (Object.keys(examplesCache).length === 0) {
145
+ loadAllExamples();
146
+ }
147
+ return examplesCache[exampleId] || null;
148
+ }
149
+ /**
150
+ * Get all loaded examples
151
+ */
152
+ export function getAllExampleDialogues() {
153
+ if (Object.keys(examplesCache).length === 0) {
154
+ loadAllExamples();
155
+ }
156
+ return examplesCache;
157
+ }
158
+ /**
159
+ * Get flag schema for an example
160
+ */
161
+ export function getExampleFlagSchema(exampleId) {
162
+ const metadata = examplesRegistry.find(ex => ex.id === exampleId);
163
+ if (!metadata) {
164
+ return null;
165
+ }
166
+ return exampleFlagSchemas[metadata.flagSchemaId] || null;
167
+ }
168
+ /**
169
+ * Check if an example has Yarn content available
170
+ */
171
+ export function hasExampleContent(exampleId) {
172
+ return exampleId in yarnExamplesContent;
173
+ }
174
+ /**
175
+ * Get list of example IDs that have content available
176
+ */
177
+ export function getAvailableExampleIds() {
178
+ return examplesRegistry
179
+ .filter(metadata => hasExampleContent(metadata.id))
180
+ .map(metadata => metadata.id);
181
+ }
@@ -0,0 +1,21 @@
1
+ export { DialogueEditorV2 } from './components/DialogueEditorV2';
2
+ export { ScenePlayer } from './components/ScenePlayer';
3
+ export type { ScenePlayerProps } from './components/ScenePlayer';
4
+ export { ScenePlayer as DialogueSimulator } from './components/ScenePlayer';
5
+ export { GuidePanel } from './components/GuidePanel';
6
+ export { FlagSelector } from './components/FlagSelector';
7
+ export { FlagManager } from './components/FlagManager';
8
+ export { ZoomControls } from './components/ZoomControls';
9
+ export { ExampleLoader } from './components/ExampleLoader';
10
+ import './styles/scrollbar.css';
11
+ import './styles/theme.css';
12
+ export { exampleDialogues, demoFlagSchemas, getExampleDialogue, getDemoFlagSchema, listExamples, listDemoFlagSchemas } from './examples';
13
+ export * from './types';
14
+ export * from './types/flags';
15
+ export * from './types/game-state';
16
+ export * from './types/constants';
17
+ export { flattenGameState, validateGameState, extractFlagsFromGameState, type FlattenConfig, type FlattenedState } from './utils/game-state-flattener';
18
+ export { exportToYarn, importFromYarn } from './lib/yarn-converter';
19
+ export { initializeFlags, mergeFlagUpdates, validateFlags, getFlagValue } from './lib/flag-manager';
20
+ export * from './utils/node-helpers';
21
+ export * from './utils/feature-flags';
@@ -0,0 +1,26 @@
1
+ export { DialogueEditorV2 } from './components/DialogueEditorV2';
2
+ export { ScenePlayer } from './components/ScenePlayer';
3
+ // Legacy export for backward compatibility
4
+ export { ScenePlayer as DialogueSimulator } from './components/ScenePlayer';
5
+ export { GuidePanel } from './components/GuidePanel';
6
+ export { FlagSelector } from './components/FlagSelector';
7
+ export { FlagManager } from './components/FlagManager';
8
+ export { ZoomControls } from './components/ZoomControls';
9
+ export { ExampleLoader } from './components/ExampleLoader';
10
+ // Export styles
11
+ import './styles/scrollbar.css';
12
+ import './styles/theme.css';
13
+ // Export examples
14
+ export { exampleDialogues, demoFlagSchemas, getExampleDialogue, getDemoFlagSchema, listExamples, listDemoFlagSchemas } from './examples';
15
+ // Export all types
16
+ export * from './types';
17
+ export * from './types/flags';
18
+ export * from './types/game-state';
19
+ export * from './types/constants';
20
+ // Export game state utilities
21
+ export { flattenGameState, validateGameState, extractFlagsFromGameState } from './utils/game-state-flattener';
22
+ // Export utilities
23
+ export { exportToYarn, importFromYarn } from './lib/yarn-converter';
24
+ export { initializeFlags, mergeFlagUpdates, validateFlags, getFlagValue } from './lib/flag-manager';
25
+ export * from './utils/node-helpers';
26
+ export * from './utils/feature-flags';
@@ -0,0 +1,21 @@
1
+ import { GameFlagState } from '../types/game-state';
2
+ import { FlagSchema } from '../types/flags';
3
+ /**
4
+ * Initialize game flags from schema with default values
5
+ */
6
+ export declare function initializeFlags(schema: FlagSchema): GameFlagState;
7
+ /**
8
+ * Merge current flags with updates from dialogue
9
+ */
10
+ export declare function mergeFlagUpdates(currentFlags: GameFlagState, updates: string[], schema?: FlagSchema): GameFlagState;
11
+ /**
12
+ * Validate flags against schema
13
+ */
14
+ export declare function validateFlags(flags: GameFlagState, schema: FlagSchema): {
15
+ valid: boolean;
16
+ errors: string[];
17
+ };
18
+ /**
19
+ * Get flag value with type safety
20
+ */
21
+ export declare function getFlagValue(flags: GameFlagState, flagId: string, defaultValue?: boolean | number | string): boolean | number | string;
@@ -0,0 +1,93 @@
1
+ import { FLAG_TYPE, FLAG_VALUE_TYPE } from '../types/constants';
2
+ /**
3
+ * Initialize game flags from schema with default values
4
+ */
5
+ export function initializeFlags(schema) {
6
+ const flags = {};
7
+ schema.flags.forEach(flag => {
8
+ if (flag.defaultValue !== undefined) {
9
+ flags[flag.id] = flag.defaultValue;
10
+ }
11
+ else if (flag.valueType === 'number') {
12
+ flags[flag.id] = 0;
13
+ }
14
+ else if (flag.valueType === 'string') {
15
+ flags[flag.id] = '';
16
+ }
17
+ else {
18
+ flags[flag.id] = false;
19
+ }
20
+ });
21
+ return flags;
22
+ }
23
+ /**
24
+ * Merge current flags with updates from dialogue
25
+ */
26
+ export function mergeFlagUpdates(currentFlags, updates, schema) {
27
+ const newFlags = { ...currentFlags };
28
+ updates.forEach(flagId => {
29
+ const flagDef = schema?.flags.find(f => f.id === flagId);
30
+ if (flagDef) {
31
+ // Use default value or increment if number
32
+ if (flagDef.valueType === 'number' && typeof newFlags[flagId] === 'number') {
33
+ newFlags[flagId] = newFlags[flagId] + 1;
34
+ }
35
+ else if (flagDef.valueType === FLAG_VALUE_TYPE.STRING) {
36
+ // For string flags, use smart defaults based on type
37
+ if (flagDef.type === FLAG_TYPE.QUEST) {
38
+ // Quest flags: if not set, mark as "started", otherwise keep current value
39
+ newFlags[flagId] = newFlags[flagId] || 'started';
40
+ }
41
+ else {
42
+ // Other string flags: use default or empty string
43
+ newFlags[flagId] = flagDef.defaultValue !== undefined ? flagDef.defaultValue : '';
44
+ }
45
+ }
46
+ else if (flagDef.defaultValue !== undefined) {
47
+ newFlags[flagId] = flagDef.defaultValue;
48
+ }
49
+ else {
50
+ newFlags[flagId] = true;
51
+ }
52
+ }
53
+ else {
54
+ // Default to true if not in schema
55
+ newFlags[flagId] = true;
56
+ }
57
+ });
58
+ return newFlags;
59
+ }
60
+ /**
61
+ * Validate flags against schema
62
+ */
63
+ export function validateFlags(flags, schema) {
64
+ const errors = [];
65
+ Object.keys(flags).forEach(flagId => {
66
+ const flagDef = schema.flags.find(f => f.id === flagId);
67
+ if (!flagDef) {
68
+ errors.push(`Unknown flag: ${flagId}`);
69
+ }
70
+ else if (flagDef.valueType) {
71
+ const value = flags[flagId];
72
+ if (flagDef.valueType === FLAG_VALUE_TYPE.NUMBER && typeof value !== 'number') {
73
+ errors.push(`Flag ${flagId} should be a number, got ${typeof value}`);
74
+ }
75
+ else if (flagDef.valueType === FLAG_VALUE_TYPE.STRING && typeof value !== 'string') {
76
+ errors.push(`Flag ${flagId} should be a string, got ${typeof value}`);
77
+ }
78
+ else if (flagDef.valueType === FLAG_VALUE_TYPE.BOOLEAN && typeof value !== 'boolean') {
79
+ errors.push(`Flag ${flagId} should be a boolean, got ${typeof value}`);
80
+ }
81
+ }
82
+ });
83
+ return {
84
+ valid: errors.length === 0,
85
+ errors
86
+ };
87
+ }
88
+ /**
89
+ * Get flag value with type safety
90
+ */
91
+ export function getFlagValue(flags, flagId, defaultValue) {
92
+ return flags[flagId] ?? defaultValue ?? false;
93
+ }
@@ -0,0 +1,169 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { importFromYarn, exportToYarn } from '../../yarn-converter';
3
+ /**
4
+ * Test round-trip conversion: Yarn → DialogueTree → Yarn
5
+ * This ensures we can import and export without data loss
6
+ */
7
+ describe('Yarn Round-Trip Conversion', () => {
8
+ const testCases = [
9
+ {
10
+ name: 'Basic dialogue with choices',
11
+ yarn: `title: start
12
+ ---
13
+ NPC: Hello! How can I help you?
14
+ -> Option 1
15
+ <<jump option1>>
16
+ -> Option 2
17
+ <<jump option2>>
18
+ ===
19
+
20
+ title: option1
21
+ ---
22
+ NPC: You chose option 1!
23
+ ===
24
+
25
+ title: option2
26
+ ---
27
+ NPC: You chose option 2!
28
+ ===
29
+ `
30
+ },
31
+ {
32
+ name: 'Dialogue with flags',
33
+ yarn: `title: start
34
+ ---
35
+ NPC: Welcome!
36
+ <<set $flag1 = true>>
37
+ <<set $flag2 = true>>
38
+ -> Continue
39
+ <<set $flag3 = true>>
40
+ <<jump next>>
41
+ ===
42
+
43
+ title: next
44
+ ---
45
+ NPC: Flags have been set!
46
+ ===
47
+ `
48
+ },
49
+ {
50
+ name: 'Conditional blocks',
51
+ yarn: `title: start
52
+ ---
53
+ <<if $has_key>>
54
+ Guard: The door is unlocked.
55
+ <<else>>
56
+ Guard: The door is locked.
57
+ <<endif>>
58
+ ===
59
+ `
60
+ },
61
+ {
62
+ name: 'Variable operations',
63
+ yarn: `title: merchant
64
+ ---
65
+ Merchant: You have {$stat_gold} gold.
66
+ <<set $stat_gold += 100>>
67
+ Merchant: Now you have {$stat_gold} gold!
68
+ -> Buy item
69
+ <<set $stat_gold -= 50>>
70
+ <<set $item_sword = true>>
71
+ Merchant: You bought a sword! You have {$stat_gold} gold left.
72
+ <<jump end>>
73
+ ===
74
+
75
+ title: end
76
+ ---
77
+ ===
78
+ `
79
+ },
80
+ {
81
+ name: 'Complex conditional with multiple blocks',
82
+ yarn: `title: start
83
+ ---
84
+ <<if $stat_gold >= 100>>
85
+ Merchant: You can afford the sword!
86
+ <<elseif $stat_gold >= 50>>
87
+ Merchant: You can afford the potion!
88
+ <<else>>
89
+ Merchant: You don't have enough gold.
90
+ <<endif>>
91
+ ===
92
+ `
93
+ }
94
+ ];
95
+ testCases.forEach(({ name, yarn }) => {
96
+ it(`should round-trip: ${name}`, () => {
97
+ // Import Yarn to DialogueTree
98
+ const dialogue = importFromYarn(yarn, 'Test Dialogue');
99
+ // Export DialogueTree back to Yarn
100
+ const exportedYarn = exportToYarn(dialogue);
101
+ // Import the exported Yarn again
102
+ const reimportedDialogue = importFromYarn(exportedYarn, 'Test Dialogue');
103
+ // Verify structure is preserved
104
+ expect(reimportedDialogue.nodes).toBeDefined();
105
+ expect(Object.keys(reimportedDialogue.nodes).length).toBeGreaterThan(0);
106
+ // Verify all nodes are present
107
+ const originalNodeIds = Object.keys(dialogue.nodes);
108
+ const reimportedNodeIds = Object.keys(reimportedDialogue.nodes);
109
+ expect(reimportedNodeIds.length).toBe(originalNodeIds.length);
110
+ // Verify node types are preserved
111
+ originalNodeIds.forEach(nodeId => {
112
+ const original = dialogue.nodes[nodeId];
113
+ const reimported = reimportedDialogue.nodes[nodeId];
114
+ expect(reimported).toBeDefined();
115
+ expect(reimported.type).toBe(original.type);
116
+ });
117
+ });
118
+ });
119
+ it('should preserve variable operations', () => {
120
+ const yarn = `title: test
121
+ ---
122
+ NPC: Test
123
+ <<set $stat_gold += 100>>
124
+ <<set $stat_gold -= 50>>
125
+ <<set $stat_strength *= 2>>
126
+ ===
127
+ `;
128
+ const dialogue = importFromYarn(yarn, 'Test');
129
+ const exported = exportToYarn(dialogue);
130
+ // Verify operations are in exported Yarn
131
+ expect(exported).toContain('<<set $stat_gold += 100>>');
132
+ expect(exported).toContain('<<set $stat_gold -= 50>>');
133
+ expect(exported).toContain('<<set $stat_strength *= 2>>');
134
+ });
135
+ it('should preserve variable interpolation', () => {
136
+ const yarn = `title: test
137
+ ---
138
+ NPC: Hello {$player_name}! You have {$stat_gold} gold.
139
+ ===
140
+ `;
141
+ const dialogue = importFromYarn(yarn, 'Test');
142
+ const exported = exportToYarn(dialogue);
143
+ // Variable interpolation should be preserved in content
144
+ expect(dialogue.nodes.test.content).toContain('{$player_name}');
145
+ expect(dialogue.nodes.test.content).toContain('{$stat_gold}');
146
+ });
147
+ it('should preserve conditional choices', () => {
148
+ const yarn = `title: start
149
+ ---
150
+ <<if $has_key>>
151
+ -> Use key
152
+ <<jump unlocked>>
153
+ <<endif>>
154
+ -> Try to force
155
+ <<jump forced>>
156
+ ===
157
+ `;
158
+ const dialogue = importFromYarn(yarn, 'Test');
159
+ const exported = exportToYarn(dialogue);
160
+ // Verify conditional choice structure
161
+ const playerNode = dialogue.nodes.start;
162
+ expect(playerNode.type).toBe('player');
163
+ expect(playerNode.choices).toBeDefined();
164
+ expect(playerNode.choices.length).toBeGreaterThan(0);
165
+ // Verify conditions are exported
166
+ expect(exported).toContain('<<if');
167
+ expect(exported).toContain('<<endif>>');
168
+ });
169
+ });
@@ -0,0 +1,17 @@
1
+ import { DialogueTree } from '../types';
2
+ /**
3
+ * Convert DialogueTree to Yarn Spinner format
4
+ *
5
+ * Flags are converted to Yarn variables ($variable).
6
+ * Variables are NOT stored in the .yarn file - they're managed by
7
+ * Yarn Spinner's Variable Storage at runtime.
8
+ *
9
+ * The .yarn file contains commands like:
10
+ * - <<set $flag_name = value>> - Sets variable in Variable Storage
11
+ * - <<if $flag_name>> - Checks variable in Variable Storage
12
+ */
13
+ export declare function exportToYarn(tree: DialogueTree): string;
14
+ /**
15
+ * Parse Yarn Spinner format to DialogueTree
16
+ */
17
+ export declare function importFromYarn(yarnContent: string, title?: string): DialogueTree;