@teachinglab/omd 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 (144) hide show
  1. package/README.md +138 -0
  2. package/canvas/core/canvasConfig.js +203 -0
  3. package/canvas/core/omdCanvas.js +475 -0
  4. package/canvas/drawing/segment.js +168 -0
  5. package/canvas/drawing/stroke.js +386 -0
  6. package/canvas/events/eventManager.js +435 -0
  7. package/canvas/events/pointerEventHandler.js +263 -0
  8. package/canvas/features/focusFrameManager.js +287 -0
  9. package/canvas/index.js +49 -0
  10. package/canvas/tools/eraserTool.js +322 -0
  11. package/canvas/tools/pencilTool.js +319 -0
  12. package/canvas/tools/selectTool.js +457 -0
  13. package/canvas/tools/tool.js +223 -0
  14. package/canvas/tools/toolManager.js +394 -0
  15. package/canvas/ui/cursor.js +438 -0
  16. package/canvas/ui/toolbar.js +304 -0
  17. package/canvas/utils/boundingBox.js +378 -0
  18. package/canvas/utils/mathUtils.js +259 -0
  19. package/docs/api/configuration-options.md +104 -0
  20. package/docs/api/eventManager.md +68 -0
  21. package/docs/api/focusFrameManager.md +150 -0
  22. package/docs/api/index.md +91 -0
  23. package/docs/api/main.md +58 -0
  24. package/docs/api/omdBinaryExpressionNode.md +227 -0
  25. package/docs/api/omdCanvas.md +142 -0
  26. package/docs/api/omdConfigManager.md +192 -0
  27. package/docs/api/omdConstantNode.md +117 -0
  28. package/docs/api/omdDisplay.md +121 -0
  29. package/docs/api/omdEquationNode.md +161 -0
  30. package/docs/api/omdEquationSequenceNode.md +301 -0
  31. package/docs/api/omdEquationStack.md +139 -0
  32. package/docs/api/omdFunctionNode.md +141 -0
  33. package/docs/api/omdGroupNode.md +182 -0
  34. package/docs/api/omdHelpers.md +96 -0
  35. package/docs/api/omdLeafNode.md +163 -0
  36. package/docs/api/omdNode.md +101 -0
  37. package/docs/api/omdOperationDisplayNode.md +139 -0
  38. package/docs/api/omdOperatorNode.md +127 -0
  39. package/docs/api/omdParenthesisNode.md +122 -0
  40. package/docs/api/omdPopup.md +117 -0
  41. package/docs/api/omdPowerNode.md +127 -0
  42. package/docs/api/omdRationalNode.md +128 -0
  43. package/docs/api/omdSequenceNode.md +128 -0
  44. package/docs/api/omdSimplification.md +110 -0
  45. package/docs/api/omdSqrtNode.md +79 -0
  46. package/docs/api/omdStepVisualizer.md +115 -0
  47. package/docs/api/omdStepVisualizerHighlighting.md +61 -0
  48. package/docs/api/omdStepVisualizerInteractiveSteps.md +129 -0
  49. package/docs/api/omdStepVisualizerLayout.md +60 -0
  50. package/docs/api/omdStepVisualizerNodeUtils.md +140 -0
  51. package/docs/api/omdStepVisualizerTextBoxes.md +68 -0
  52. package/docs/api/omdToolbar.md +102 -0
  53. package/docs/api/omdTranscriptionService.md +76 -0
  54. package/docs/api/omdTreeDiff.md +134 -0
  55. package/docs/api/omdUnaryExpressionNode.md +174 -0
  56. package/docs/api/omdUtilities.md +70 -0
  57. package/docs/api/omdVariableNode.md +148 -0
  58. package/docs/api/selectTool.md +74 -0
  59. package/docs/api/simplificationEngine.md +98 -0
  60. package/docs/api/simplificationRules.md +77 -0
  61. package/docs/api/simplificationUtils.md +64 -0
  62. package/docs/api/transcribe.md +43 -0
  63. package/docs/api-reference.md +85 -0
  64. package/docs/index.html +454 -0
  65. package/docs/user-guide.md +9 -0
  66. package/index.js +67 -0
  67. package/omd/config/omdConfigManager.js +267 -0
  68. package/omd/core/index.js +150 -0
  69. package/omd/core/omdEquationStack.js +347 -0
  70. package/omd/core/omdUtilities.js +115 -0
  71. package/omd/display/omdDisplay.js +443 -0
  72. package/omd/display/omdToolbar.js +502 -0
  73. package/omd/nodes/omdBinaryExpressionNode.js +460 -0
  74. package/omd/nodes/omdConstantNode.js +142 -0
  75. package/omd/nodes/omdEquationNode.js +1223 -0
  76. package/omd/nodes/omdEquationSequenceNode.js +1273 -0
  77. package/omd/nodes/omdFunctionNode.js +352 -0
  78. package/omd/nodes/omdGroupNode.js +68 -0
  79. package/omd/nodes/omdLeafNode.js +77 -0
  80. package/omd/nodes/omdNode.js +557 -0
  81. package/omd/nodes/omdOperationDisplayNode.js +322 -0
  82. package/omd/nodes/omdOperatorNode.js +109 -0
  83. package/omd/nodes/omdParenthesisNode.js +293 -0
  84. package/omd/nodes/omdPowerNode.js +236 -0
  85. package/omd/nodes/omdRationalNode.js +295 -0
  86. package/omd/nodes/omdSqrtNode.js +308 -0
  87. package/omd/nodes/omdUnaryExpressionNode.js +178 -0
  88. package/omd/nodes/omdVariableNode.js +123 -0
  89. package/omd/simplification/omdSimplification.js +171 -0
  90. package/omd/simplification/omdSimplificationEngine.js +886 -0
  91. package/omd/simplification/package.json +6 -0
  92. package/omd/simplification/rules/binaryRules.js +1037 -0
  93. package/omd/simplification/rules/functionRules.js +111 -0
  94. package/omd/simplification/rules/index.js +48 -0
  95. package/omd/simplification/rules/parenthesisRules.js +19 -0
  96. package/omd/simplification/rules/powerRules.js +143 -0
  97. package/omd/simplification/rules/rationalRules.js +475 -0
  98. package/omd/simplification/rules/sqrtRules.js +48 -0
  99. package/omd/simplification/rules/unaryRules.js +37 -0
  100. package/omd/simplification/simplificationRules.js +32 -0
  101. package/omd/simplification/simplificationUtils.js +1056 -0
  102. package/omd/step-visualizer/omdStepVisualizer.js +597 -0
  103. package/omd/step-visualizer/omdStepVisualizerHighlighting.js +206 -0
  104. package/omd/step-visualizer/omdStepVisualizerLayout.js +245 -0
  105. package/omd/step-visualizer/omdStepVisualizerTextBoxes.js +163 -0
  106. package/omd/utils/omdNodeOverlay.js +638 -0
  107. package/omd/utils/omdPopup.js +1084 -0
  108. package/omd/utils/omdStepVisualizerInteractiveSteps.js +491 -0
  109. package/omd/utils/omdStepVisualizerNodeUtils.js +268 -0
  110. package/omd/utils/omdTranscriptionService.js +125 -0
  111. package/omd/utils/omdTreeDiff.js +734 -0
  112. package/package.json +46 -0
  113. package/src/index.js +62 -0
  114. package/src/json-schemas.md +109 -0
  115. package/src/omd-json-samples.js +115 -0
  116. package/src/omd.js +109 -0
  117. package/src/omdApp.js +391 -0
  118. package/src/omdAppCanvas.js +336 -0
  119. package/src/omdBalanceHanger.js +172 -0
  120. package/src/omdColor.js +13 -0
  121. package/src/omdCoordinatePlane.js +467 -0
  122. package/src/omdEquation.js +125 -0
  123. package/src/omdExpression.js +104 -0
  124. package/src/omdFunction.js +113 -0
  125. package/src/omdMetaExpression.js +287 -0
  126. package/src/omdNaturalExpression.js +564 -0
  127. package/src/omdNode.js +384 -0
  128. package/src/omdNumber.js +53 -0
  129. package/src/omdNumberLine.js +107 -0
  130. package/src/omdNumberTile.js +119 -0
  131. package/src/omdOperator.js +73 -0
  132. package/src/omdPowerExpression.js +92 -0
  133. package/src/omdProblem.js +55 -0
  134. package/src/omdRatioChart.js +232 -0
  135. package/src/omdRationalExpression.js +115 -0
  136. package/src/omdSampleData.js +215 -0
  137. package/src/omdShapes.js +476 -0
  138. package/src/omdSpinner.js +148 -0
  139. package/src/omdString.js +39 -0
  140. package/src/omdTable.js +369 -0
  141. package/src/omdTapeDiagram.js +245 -0
  142. package/src/omdTerm.js +92 -0
  143. package/src/omdTileEquation.js +349 -0
  144. package/src/omdVariable.js +51 -0
@@ -0,0 +1,267 @@
1
+ /**
2
+ * OMD Configuration Manager
3
+ * Dynamically loads and manages configuration from JSON file
4
+ */
5
+
6
+ // Configuration data - will be loaded from JSON or provided by user
7
+ let configData = null;
8
+ let configLoadPromise = null;
9
+
10
+ // Default configuration (fallback when no config file is available)
11
+ const defaultConfig = {
12
+ multiplication: {
13
+ symbol: "·",
14
+ forceImplicit: false,
15
+ implicitCombinations: {
16
+ constantVariable: true,
17
+ variableConstant: false,
18
+ parenthesisAfterVariable: true,
19
+ parenthesisAfterConstant: true,
20
+ variableParenthesis: true,
21
+ parenthesisParenthesis: true,
22
+ parenthesisVariable: true,
23
+ parenthesisConstant: true,
24
+ variableVariable: true
25
+ }
26
+ },
27
+ stepVisualizer: {
28
+ dotSizes: {
29
+ level0: 8,
30
+ level1: 6,
31
+ level2: 4
32
+ },
33
+ fontWeights: {
34
+ level0: 400,
35
+ level1: 400,
36
+ level2: 400
37
+ }
38
+ }
39
+ };
40
+
41
+ /**
42
+ * Loads configuration from JSON file or uses default
43
+ * @param {string|Object} configSource - Optional path to config file or config object
44
+ * @returns {Promise<Object>} Promise that resolves to the configuration object
45
+ */
46
+ async function loadConfig(configSource = null) {
47
+ if (configLoadPromise && !configSource) {
48
+ return configLoadPromise;
49
+ }
50
+
51
+ // If a config object is provided directly, use it
52
+ if (configSource && typeof configSource === 'object') {
53
+ configData = { ...defaultConfig, ...configSource };
54
+ return configData;
55
+ }
56
+
57
+ configLoadPromise = (async () => {
58
+ try {
59
+ // Detect environment and use appropriate loading method
60
+ if (typeof window !== 'undefined') {
61
+ // Browser environment - use fetch
62
+ const configPath = configSource || './omd/config/omdConfig.json';
63
+ const response = await fetch(configPath);
64
+ if (!response.ok) {
65
+ console.warn(`Config file not found at ${configPath}, using default configuration`);
66
+ configData = defaultConfig;
67
+ return configData;
68
+ }
69
+
70
+ const configText = await response.text();
71
+ const loadedConfig = JSON.parse(configText);
72
+ configData = { ...defaultConfig, ...loadedConfig };
73
+ return configData;
74
+
75
+ } else {
76
+ // Node.js environment - use fs
77
+ const fs = await import('fs');
78
+ const path = await import('path');
79
+ const { fileURLToPath } = await import('url');
80
+
81
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
82
+ const configPath = configSource || path.join(__dirname, 'omdConfig.json');
83
+
84
+ try {
85
+ const fileContent = await fs.promises.readFile(configPath, 'utf-8');
86
+ const loadedConfig = JSON.parse(fileContent);
87
+ configData = { ...defaultConfig, ...loadedConfig };
88
+ } catch (err) {
89
+ console.warn(`Config file not found at ${configPath}, using default configuration`);
90
+ configData = defaultConfig;
91
+ }
92
+ return configData;
93
+ }
94
+ } catch (error) {
95
+ console.warn('Error loading config, using default configuration:', error);
96
+ configData = defaultConfig;
97
+ return configData;
98
+ }
99
+ })();
100
+
101
+ return configLoadPromise;
102
+ }
103
+
104
+ /**
105
+ * Gets the configuration object, loading it if necessary
106
+ * @returns {Promise<Object>} Promise that resolves to the configuration object
107
+ */
108
+ async function getConfig() {
109
+ if (!configData) {
110
+ await loadConfig();
111
+ }
112
+ return configData;
113
+ }
114
+
115
+ /**
116
+ * Gets the configuration object synchronously (for backwards compatibility)
117
+ * If config hasn't been loaded yet, returns default config
118
+ * @returns {Object} The configuration object
119
+ */
120
+ function getConfigSync() {
121
+ if (!configData) {
122
+ // Auto-initialize with defaults if not loaded
123
+ configData = defaultConfig;
124
+ }
125
+ return configData;
126
+ }
127
+
128
+ /**
129
+ * Initialize configuration loading (call this early in app lifecycle)
130
+ * @param {string|Object} configSource - Optional path to config file or config object
131
+ * @returns {Promise<void>}
132
+ */
133
+ export async function initializeConfig(configSource = null) {
134
+ await loadConfig(configSource);
135
+ }
136
+
137
+ /**
138
+ * Set configuration directly without loading from file
139
+ * @param {Object} config - Configuration object
140
+ */
141
+ export function setConfig(config) {
142
+ configData = { ...defaultConfig, ...config };
143
+ }
144
+
145
+ /**
146
+ * Get the default configuration
147
+ * @returns {Object} The default configuration object
148
+ */
149
+ export function getDefaultConfig() {
150
+ return { ...defaultConfig };
151
+ }
152
+
153
+ /**
154
+ * Utility function to check if a specific feature is enabled
155
+ * @param {string} category - The configuration category (e.g., 'multiplication', 'simplification')
156
+ * @param {string} setting - The specific setting to check
157
+ * @returns {boolean} Whether the setting is enabled
158
+ */
159
+ export function isEnabled(category, setting) {
160
+ const config = getConfigSync();
161
+ return config[category]?.[setting] ?? false;
162
+ }
163
+
164
+ /**
165
+ * Check if implicit multiplication should be used for a specific combination
166
+ * @param {string} combination - The type of combination (e.g., 'constantVariable')
167
+ * @returns {boolean} Whether implicit multiplication should be used
168
+ */
169
+ export function useImplicitMultiplication(combination = null) {
170
+ const config = getConfigSync();
171
+ if (combination) {
172
+ return config.multiplication.implicitCombinations[combination] ?? false;
173
+ }
174
+ return config.multiplication.forceImplicit;
175
+ }
176
+
177
+ /**
178
+ * Get the configured multiplication symbol
179
+ * @returns {string} The multiplication symbol to use for display
180
+ */
181
+ export function getMultiplicationSymbol() {
182
+ const config = getConfigSync();
183
+ return config.multiplication.symbol;
184
+ }
185
+
186
+ /**
187
+ * Update configuration settings at runtime
188
+ * @param {string} category - The configuration category
189
+ * @param {string} setting - The setting to update
190
+ * @param {any} value - The new value
191
+ */
192
+ export function updateConfig(category, setting, value) {
193
+ const config = getConfigSync();
194
+ if (config[category] && config[category].hasOwnProperty(setting)) {
195
+ config[category][setting] = value;
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Get a configuration value by path
201
+ * @param {string} path - Dot-separated path to the config value (e.g., 'multiplication.symbol')
202
+ * @returns {any} The configuration value
203
+ */
204
+ export function getConfigValue(path) {
205
+ const config = getConfigSync();
206
+ return path.split('.').reduce((obj, key) => obj?.[key], config);
207
+ }
208
+
209
+ /**
210
+ * Set a configuration value by path
211
+ * @param {string} path - Dot-separated path to the config value
212
+ * @param {any} value - The new value
213
+ */
214
+ export function setConfigValue(path, value) {
215
+ const config = getConfigSync();
216
+ const keys = path.split('.');
217
+ const lastKey = keys.pop();
218
+ const target = keys.reduce((obj, key) => obj[key] = obj[key] || {}, config);
219
+ target[lastKey] = value;
220
+ }
221
+
222
+ /**
223
+ * Reset configuration to defaults
224
+ */
225
+ export function resetConfig() {
226
+ throw new Error('resetConfig not available - edit omdConfig.json file directly');
227
+ }
228
+
229
+ /**
230
+ * Reload configuration from JSON file
231
+ * @returns {Promise<Object>} Promise that resolves to the reloaded configuration
232
+ */
233
+ export async function reloadConfig() {
234
+ configData = null;
235
+ configLoadPromise = null;
236
+ return await loadConfig();
237
+ }
238
+
239
+ /**
240
+ * Get the raw configuration object (async)
241
+ * @returns {Promise<Object>} Promise that resolves to the configuration object
242
+ */
243
+ export async function getConfigAsync() {
244
+ return await getConfig();
245
+ }
246
+
247
+ /**
248
+ * Get dot radius for a given step level (0,1,2)
249
+ * @param {number} level
250
+ * @returns {number}
251
+ */
252
+ export function getDotRadius(level=0){
253
+ const cfg=getConfigSync();
254
+ const key=`level${level}`;
255
+ return cfg.stepVisualizer?.dotSizes?.[key]??6;
256
+ }
257
+
258
+ /**
259
+ * Get font weight for a given step level (0,1,2)
260
+ * @param {number} level
261
+ * @returns {number}
262
+ */
263
+ export function getFontWeight(level=0){
264
+ const cfg=getConfigSync();
265
+ const key=`level${level}`;
266
+ return cfg.stepVisualizer?.fontWeights?.[key]??400;
267
+ }
@@ -0,0 +1,150 @@
1
+ // Core node classes
2
+ import { omdNode } from '../nodes/omdNode.js';
3
+ import { omdBinaryExpressionNode } from '../nodes/omdBinaryExpressionNode.js';
4
+ import { omdConstantNode } from '../nodes/omdConstantNode.js';
5
+ import { omdEquationNode } from '../nodes/omdEquationNode.js';
6
+ import { omdFunctionNode } from '../nodes/omdFunctionNode.js';
7
+ import { omdGroupNode } from '../nodes/omdGroupNode.js';
8
+ import { omdLeafNode } from '../nodes/omdLeafNode.js';
9
+ import { omdOperationDisplayNode } from '../nodes/omdOperationDisplayNode.js';
10
+ import { omdOperatorNode } from '../nodes/omdOperatorNode.js';
11
+ import { omdParenthesisNode } from '../nodes/omdParenthesisNode.js';
12
+ import { omdPowerNode } from '../nodes/omdPowerNode.js';
13
+ import { omdRationalNode } from '../nodes/omdRationalNode.js';
14
+ import { omdEquationSequenceNode } from '../nodes/omdEquationSequenceNode.js';
15
+ import { omdSqrtNode } from '../nodes/omdSqrtNode.js';
16
+ import { omdUnaryExpressionNode } from '../nodes/omdUnaryExpressionNode.js';
17
+ import { omdVariableNode } from '../nodes/omdVariableNode.js';
18
+ import { omdEquationStack } from './omdEquationStack.js';
19
+
20
+ // Visualization components
21
+ import { omdStepVisualizer } from '../step-visualizer/omdStepVisualizer.js';
22
+ import { omdDisplay } from '../display/omdDisplay.js';
23
+ import { omdToolbar } from '../display/omdToolbar.js';
24
+
25
+ // Utilities
26
+ import { getNodeForAST } from './omdUtilities.js';
27
+ import { simplifyStep } from '../simplification/omdSimplification.js';
28
+ import {
29
+ initializeConfig,
30
+ setConfig,
31
+ getDefaultConfig
32
+ } from '../config/omdConfigManager.js';
33
+
34
+ // Expression handling
35
+ import { omdExpression } from '../../src/omdExpression.js';
36
+ import { omdColor } from '../../src/omdColor.js';
37
+
38
+ // Re-export all imports
39
+ export {
40
+ // Core node classes
41
+ omdNode,
42
+ omdBinaryExpressionNode,
43
+ omdConstantNode,
44
+ omdEquationNode,
45
+ omdFunctionNode,
46
+ omdGroupNode,
47
+ omdLeafNode,
48
+ omdOperationDisplayNode,
49
+ omdOperatorNode,
50
+ omdParenthesisNode,
51
+ omdPowerNode,
52
+ omdRationalNode,
53
+ omdEquationSequenceNode,
54
+ omdSqrtNode,
55
+ omdUnaryExpressionNode,
56
+ omdVariableNode,
57
+ omdEquationStack,
58
+
59
+ // Visualization
60
+ omdStepVisualizer,
61
+ omdDisplay,
62
+ omdToolbar,
63
+
64
+ // Utilities
65
+ getNodeForAST,
66
+ simplifyStep,
67
+ initializeConfig,
68
+ setConfig,
69
+ getDefaultConfig,
70
+ omdExpression,
71
+ omdColor
72
+ };
73
+
74
+ // Helper utilities for common operations
75
+ export const omdHelpers = {
76
+ /**
77
+ * Creates a node from a text expression
78
+ * @param {string} expression - The expression string
79
+ * @param {object} mathjs - The math.js instance
80
+ * @returns {omdNode} The created node
81
+ */
82
+ createNodeFromExpression(expression, mathjs) {
83
+ const parsedAST = mathjs.parse(expression);
84
+ const NodeClass = getNodeForAST(parsedAST);
85
+ return new NodeClass(parsedAST);
86
+ },
87
+
88
+ /**
89
+ * Creates an equation node from a string
90
+ * @param {string} equationString - The equation string (e.g., "x+2=5")
91
+ * @returns {omdEquationNode} The equation node
92
+ */
93
+ createEquation(equationString) {
94
+ return omdEquationNode.fromString(equationString);
95
+ },
96
+
97
+ /**
98
+ * Creates a step visualizer from multiple equation strings
99
+ * @param {string[]} equationStrings - Array of equation strings
100
+ * @returns {omdStepVisualizer} The step visualizer
101
+ */
102
+ createStepVisualizer(equationStrings) {
103
+ const steps = equationStrings.map(str => omdEquationNode.fromString(str));
104
+ return new omdStepVisualizer(steps);
105
+ }
106
+ };
107
+
108
+ // Default export for convenience
109
+ export default {
110
+ // All node classes
111
+ nodes: {
112
+ omdNode,
113
+ omdBinaryExpressionNode,
114
+ omdConstantNode,
115
+ omdEquationNode,
116
+ omdFunctionNode,
117
+ omdGroupNode,
118
+ omdLeafNode,
119
+ omdOperationDisplayNode,
120
+ omdOperatorNode,
121
+ omdParenthesisNode,
122
+ omdPowerNode,
123
+ omdRationalNode,
124
+ omdEquationSequenceNode,
125
+ omdSqrtNode,
126
+ omdUnaryExpressionNode,
127
+ omdVariableNode
128
+ },
129
+
130
+ // Visualization
131
+ omdStepVisualizer,
132
+ omdDisplay,
133
+ omdToolbar,
134
+
135
+ // Utilities
136
+ getNodeForAST,
137
+ simplifyStep,
138
+ initializeConfig,
139
+ setConfig,
140
+ getDefaultConfig,
141
+ omdExpression,
142
+ omdColor,
143
+
144
+ // Helper functions
145
+ helpers: omdHelpers
146
+ };
147
+
148
+ export * from '../step-visualizer/omdStepVisualizer.js';
149
+ export * from './omdUtilities.js';
150
+ export * from '../display/omdToolbar.js';