@teachinglab/omd 0.5.6 → 0.5.8
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.
- package/canvas/ui/toolbar.js +6 -9
- package/index.js +3 -0
- package/npm-docs/DOCUMENTATION_SUMMARY.md +220 -0
- package/npm-docs/README.md +251 -0
- package/npm-docs/api/api-reference.md +85 -0
- package/npm-docs/api/configuration-options.md +198 -0
- package/npm-docs/api/eventManager.md +83 -0
- package/npm-docs/api/expression-nodes.md +561 -0
- package/npm-docs/api/focusFrameManager.md +145 -0
- package/npm-docs/api/index.md +106 -0
- package/npm-docs/api/main.md +63 -0
- package/npm-docs/api/omdBinaryExpressionNode.md +86 -0
- package/npm-docs/api/omdCanvas.md +84 -0
- package/npm-docs/api/omdConfigManager.md +113 -0
- package/npm-docs/api/omdConstantNode.md +53 -0
- package/npm-docs/api/omdDisplay.md +87 -0
- package/npm-docs/api/omdEquationNode.md +174 -0
- package/npm-docs/api/omdEquationSequenceNode.md +259 -0
- package/npm-docs/api/omdEquationStack.md +193 -0
- package/npm-docs/api/omdFunctionNode.md +83 -0
- package/npm-docs/api/omdGroupNode.md +79 -0
- package/npm-docs/api/omdHelpers.md +88 -0
- package/npm-docs/api/omdLeafNode.md +86 -0
- package/npm-docs/api/omdNode.md +202 -0
- package/npm-docs/api/omdOperationDisplayNode.md +118 -0
- package/npm-docs/api/omdOperatorNode.md +92 -0
- package/npm-docs/api/omdParenthesisNode.md +134 -0
- package/npm-docs/api/omdPopup.md +192 -0
- package/npm-docs/api/omdPowerNode.md +132 -0
- package/npm-docs/api/omdRationalNode.md +145 -0
- package/npm-docs/api/omdSequenceNode.md +128 -0
- package/npm-docs/api/omdSimplification.md +79 -0
- package/npm-docs/api/omdSqrtNode.md +144 -0
- package/npm-docs/api/omdStepVisualizer.md +147 -0
- package/npm-docs/api/omdStepVisualizerHighlighting.md +66 -0
- package/npm-docs/api/omdStepVisualizerInteractiveSteps.md +109 -0
- package/npm-docs/api/omdStepVisualizerLayout.md +71 -0
- package/npm-docs/api/omdStepVisualizerNodeUtils.md +140 -0
- package/npm-docs/api/omdStepVisualizerTextBoxes.md +77 -0
- package/npm-docs/api/omdToolbar.md +131 -0
- package/npm-docs/api/omdTranscriptionService.md +96 -0
- package/npm-docs/api/omdTreeDiff.md +170 -0
- package/npm-docs/api/omdUnaryExpressionNode.md +137 -0
- package/npm-docs/api/omdUtilities.md +83 -0
- package/npm-docs/api/omdVariableNode.md +123 -0
- package/npm-docs/api/selectTool.md +74 -0
- package/npm-docs/api/simplificationEngine.md +98 -0
- package/npm-docs/api/simplificationRules.md +77 -0
- package/npm-docs/api/simplificationUtils.md +64 -0
- package/npm-docs/api/transcribe.md +43 -0
- package/npm-docs/guides/equations.md +854 -0
- package/npm-docs/guides/factory-functions.md +354 -0
- package/npm-docs/guides/getting-started.md +318 -0
- package/npm-docs/guides/quick-examples.md +525 -0
- package/npm-docs/guides/visualizations.md +682 -0
- package/npm-docs/json-schemas.md +826 -0
- package/omd/utils/omdTranscriptionService.js +1 -1
- package/package.json +2 -1
- package/src/index.js +2 -0
- package/src/omdFactory.js +150 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# omdOperatorNode
|
|
2
|
+
|
|
3
|
+
Represents an operator symbol (e.g., `+`, `-`, `*`, `÷`) as a leaf node in the expression tree. This node handles the visual representation of operators, including mapping common operation names to their appropriate symbols and applying styling.
|
|
4
|
+
|
|
5
|
+
## Class Definition
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
export class omdOperatorNode extends omdLeafNode
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Constructor
|
|
12
|
+
|
|
13
|
+
### `new omdOperatorNode(nodeData)`
|
|
14
|
+
|
|
15
|
+
Creates a new `omdOperatorNode` instance.
|
|
16
|
+
|
|
17
|
+
- **`nodeData`** (`object` | `string`): The AST node data (from math.js) or the operator symbol as a string (e.g., `"+"`, `"*"`). The constructor maps common operation names (like `"multiply"`) to their display symbols (like `"×"`), respecting the configured multiplication symbol.
|
|
18
|
+
|
|
19
|
+
## Public Properties
|
|
20
|
+
|
|
21
|
+
- **`opName`** (`string`): The internal name of the operator (e.g., `"*"`, `"+"`). This might differ from the displayed symbol for multiplication.
|
|
22
|
+
- **`type`** (`string`): Always `"omdOperatorNode"`.
|
|
23
|
+
- **`textElement`** (`jsvgTextLine`): The internal `jsvgTextLine` instance that displays the operator symbol.
|
|
24
|
+
|
|
25
|
+
## Public Methods
|
|
26
|
+
|
|
27
|
+
### `computeDimensions()`
|
|
28
|
+
|
|
29
|
+
Calculates the dimensions of the node based on its text content, adding a small amount of padding around the operator symbol to improve visual spacing.
|
|
30
|
+
|
|
31
|
+
- **Overrides**: `omdLeafNode.computeDimensions()`.
|
|
32
|
+
|
|
33
|
+
### `updateLayout()`
|
|
34
|
+
|
|
35
|
+
Updates the layout of the node. This method primarily calls the superclass's `updateLayout`.
|
|
36
|
+
|
|
37
|
+
- **Overrides**: `omdLeafNode.updateLayout()`.
|
|
38
|
+
|
|
39
|
+
### `toMathJSNode()`
|
|
40
|
+
|
|
41
|
+
Converts the `omdOperatorNode` to a math.js-compatible AST format. It creates a minimal `OperatorNode` AST object.
|
|
42
|
+
|
|
43
|
+
- **Returns**: `object` - A math.js-compatible AST node with `type: "OperatorNode"`, `op` (operator symbol), `fn` (function name, typically same as `op`), and an empty `args` array. The returned object also includes a `clone` method for compatibility.
|
|
44
|
+
|
|
45
|
+
### `toString()`
|
|
46
|
+
|
|
47
|
+
Converts the operator node to its string representation, which is simply its `opName`.
|
|
48
|
+
|
|
49
|
+
- **Returns**: `string` - The operator symbol (e.g., `"+"`, `"*"`).
|
|
50
|
+
|
|
51
|
+
### `highlight(color)`
|
|
52
|
+
|
|
53
|
+
Applies a highlight to the node's background and sets the operator's text color to white for better contrast. This method respects the `isExplainHighlighted` lock.
|
|
54
|
+
|
|
55
|
+
- **`color`** (`string`): The color of the highlight.
|
|
56
|
+
|
|
57
|
+
### `clearProvenanceHighlights()`
|
|
58
|
+
|
|
59
|
+
Clears any provenance-related highlights from the node and resets the operator's text color to its default (black).
|
|
60
|
+
|
|
61
|
+
## Internal Methods
|
|
62
|
+
|
|
63
|
+
- **`parseOpName(nodeData)`**: Extracts the operator's internal name from the constructor's `nodeData`. It handles mapping from math.js function names (e.g., `"multiply"`) to display symbols (e.g., `"×"`), using the configured multiplication symbol.
|
|
64
|
+
- **`parseType()`**: Sets the node's type. Always returns `"operator"`.
|
|
65
|
+
|
|
66
|
+
## Example
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
import { omdOperatorNode } from '@teachinglab/omd';
|
|
70
|
+
|
|
71
|
+
// Create operator nodes from strings
|
|
72
|
+
const plus = new omdOperatorNode('+');
|
|
73
|
+
const times = new omdOperatorNode('*'); // Displays as × (configurable via omdConfigManager)
|
|
74
|
+
|
|
75
|
+
// Create operator node from AST data (e.g., from math.js parse result)
|
|
76
|
+
const minus = new omdOperatorNode({
|
|
77
|
+
type: 'OperatorNode',
|
|
78
|
+
op: '-',
|
|
79
|
+
fn: 'subtract'
|
|
80
|
+
}); // Displays as −
|
|
81
|
+
|
|
82
|
+
// To render, typically add to a parent node or an omdDisplay
|
|
83
|
+
// node.setFontSize(24);
|
|
84
|
+
// node.initialize(); // Computes dimensions and layout
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## See Also
|
|
88
|
+
|
|
89
|
+
- [`omdLeafNode`](./omdLeafNode.md) - The parent class for all leaf nodes.
|
|
90
|
+
- [`omdNode`](./omdNode.md) - The base class for all OMD nodes.
|
|
91
|
+
- [`omdBinaryExpressionNode`](./omdBinaryExpressionNode.md) - A common consumer of operator nodes.
|
|
92
|
+
- [`omdUnaryExpressionNode`](./omdUnaryExpressionNode.md) - Another consumer of operator nodes (e.g., for unary minus).
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# omdParenthesisNode
|
|
2
|
+
|
|
3
|
+
Represents a parenthetical grouping in a mathematical expression, such as `(x + 2)`. This node is crucial for enforcing the correct order of operations and visually grouping parts of an expression.
|
|
4
|
+
|
|
5
|
+
## Class Definition
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
export class omdParenthesisNode extends omdNode
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Constructor
|
|
12
|
+
|
|
13
|
+
### `new omdParenthesisNode(astNodeData)`
|
|
14
|
+
|
|
15
|
+
Creates a new `omdParenthesisNode` instance.
|
|
16
|
+
|
|
17
|
+
- **`astNodeData`** (`object`): The math.js AST node for the parenthesized expression. It must contain a `content` property (or `args[0]`) which is the AST for the inner expression.
|
|
18
|
+
|
|
19
|
+
During construction, it creates `omdGroupNode` instances for the opening and closing parentheses and an `omdNode` for the inner expression.
|
|
20
|
+
|
|
21
|
+
## Static Methods
|
|
22
|
+
|
|
23
|
+
### `fromString(expressionString)`
|
|
24
|
+
|
|
25
|
+
Creates an `omdParenthesisNode` from a string representation of a parenthesized expression. The input string must start and end with parentheses.
|
|
26
|
+
|
|
27
|
+
- **`expressionString`** (`string`): The expression, which must be enclosed in parentheses (e.g., `"(2 * x)"`).
|
|
28
|
+
- **Returns**: `omdParenthesisNode` - A new instance.
|
|
29
|
+
- **Throws**: `Error` if `math.js` is not available, if the string is not properly enclosed in parentheses, or if it's not a valid parenthesized expression.
|
|
30
|
+
|
|
31
|
+
## Public Properties
|
|
32
|
+
|
|
33
|
+
- **`expression`** (`omdNode`): The node representing the mathematical expression inside the parentheses.
|
|
34
|
+
- **`open`** (`omdGroupNode`): The `omdGroupNode` for the opening parenthesis `(`.
|
|
35
|
+
- **`closed`** (`omdGroupNode`): The `omdGroupNode` for the closing parenthesis `)`.
|
|
36
|
+
|
|
37
|
+
## Public Methods
|
|
38
|
+
|
|
39
|
+
### `computeDimensions()`
|
|
40
|
+
|
|
41
|
+
Calculates the dimensions of the parenthesis node. It sums the widths of the opening parenthesis, the inner expression, and the closing parenthesis. The height is determined by the maximum height of these components plus a small amount of padding that scales with font size.
|
|
42
|
+
|
|
43
|
+
- **Overrides**: `omdNode.computeDimensions()`.
|
|
44
|
+
|
|
45
|
+
### `updateLayout()`
|
|
46
|
+
|
|
47
|
+
Updates the layout of the parenthesis node and its children. It positions the inner `expression` and then centers the `open` and `closed` parentheses vertically around the mathematical baseline of the inner expression. This ensures proper visual alignment, especially for expressions containing superscripts or subscripts.
|
|
48
|
+
|
|
49
|
+
- **Overrides**: `omdNode.updateLayout()`.
|
|
50
|
+
|
|
51
|
+
### `getAlignmentBaseline()`
|
|
52
|
+
|
|
53
|
+
Returns the vertical y-coordinate for alignment. For a parenthesis node, this is the baseline of its inner expression.
|
|
54
|
+
|
|
55
|
+
- **Overrides**: `omdNode.getAlignmentBaseline()`.
|
|
56
|
+
|
|
57
|
+
### `clone()`
|
|
58
|
+
|
|
59
|
+
Creates a deep, structural clone of the parenthesis node, including its inner `expression` and `omdGroupNode` children. The cloned node's `provenance` array is updated to include the original node's ID.
|
|
60
|
+
|
|
61
|
+
- **Returns**: `omdParenthesisNode` - A new, identical instance of the parenthesis node.
|
|
62
|
+
|
|
63
|
+
### `isConstant()`
|
|
64
|
+
|
|
65
|
+
Checks if the inner expression is a constant value.
|
|
66
|
+
|
|
67
|
+
- **Returns**: `boolean` - `true` if `this.expression.isConstant()` is `true`, `false` otherwise.
|
|
68
|
+
|
|
69
|
+
### `getValue()`
|
|
70
|
+
|
|
71
|
+
Returns the numerical value of the inner expression, if it is constant.
|
|
72
|
+
|
|
73
|
+
- **Returns**: `number`.
|
|
74
|
+
- **Throws**: `Error` if the inner expression is not constant or cannot be evaluated.
|
|
75
|
+
|
|
76
|
+
### `toMathJSNode()`
|
|
77
|
+
|
|
78
|
+
Converts the `omdParenthesisNode` back into its math.js AST representation. It creates a `ParenthesisNode` AST object with the converted inner expression.
|
|
79
|
+
|
|
80
|
+
- **Returns**: `object` - A math.js `ParenthesisNode` AST object. The returned object also includes a `clone` method for compatibility.
|
|
81
|
+
|
|
82
|
+
### `toString()`
|
|
83
|
+
|
|
84
|
+
Converts the node to its string representation, including the parentheses.
|
|
85
|
+
|
|
86
|
+
- **Returns**: `string` - e.g., `"(x + 2)"`.
|
|
87
|
+
|
|
88
|
+
### `evaluate(variables)`
|
|
89
|
+
|
|
90
|
+
Evaluates the inner expression of the parenthesis node.
|
|
91
|
+
|
|
92
|
+
- **`variables`** (`object`): A map of variable names to their numeric values.
|
|
93
|
+
- **Returns**: `number` - The result of the inner expression's evaluation.
|
|
94
|
+
- **Throws**: `Error` if the inner expression cannot be evaluated.
|
|
95
|
+
|
|
96
|
+
### `isNecessary()`
|
|
97
|
+
|
|
98
|
+
Checks if the parentheses are mathematically necessary to maintain the correct order of operations, based on the parent node's context and the type of the inner expression. For example, parentheses around a simple constant or variable are generally not necessary, but they are often required around complex expressions within a power or binary operation.
|
|
99
|
+
|
|
100
|
+
- **Returns**: `boolean` - `true` if the parentheses are required, `false` otherwise.
|
|
101
|
+
|
|
102
|
+
## Internal Methods
|
|
103
|
+
|
|
104
|
+
- **`createParenthesis(symbol)`**: Creates an `omdGroupNode` for an opening or closing parenthesis.
|
|
105
|
+
- **`createExpression(ast)`**: Creates an `omdNode` instance for the inner expression from its AST.
|
|
106
|
+
|
|
107
|
+
## Example
|
|
108
|
+
|
|
109
|
+
```javascript
|
|
110
|
+
import { omdParenthesisNode } from '@teachinglab/omd';
|
|
111
|
+
import * as math from 'mathjs';
|
|
112
|
+
|
|
113
|
+
// Create a node representing (x + 2)
|
|
114
|
+
const innerExpressionAst = math.parse('x + 2');
|
|
115
|
+
const parenNode = new omdParenthesisNode({ content: innerExpressionAst });
|
|
116
|
+
|
|
117
|
+
// Set font size and render
|
|
118
|
+
parenNode.setFontSize(28);
|
|
119
|
+
parenNode.initialize();
|
|
120
|
+
|
|
121
|
+
// The simplification engine might remove these parentheses if they are not necessary
|
|
122
|
+
// const simplified = parenNode.simplify();
|
|
123
|
+
|
|
124
|
+
// Add to an SVG container to display
|
|
125
|
+
// const svgContainer = new jsvgContainer();
|
|
126
|
+
// svgContainer.addChild(parenNode);
|
|
127
|
+
// document.body.appendChild(svgContainer.svgObject);
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## See Also
|
|
131
|
+
|
|
132
|
+
- [`omdNode`](./omdNode.md) - The base class for all OMD nodes.
|
|
133
|
+
- [`omdGroupNode`](./omdGroupNode.md) - The class used to render the individual `(` and `)` symbols.
|
|
134
|
+
- [`omdBinaryExpressionNode`](./omdBinaryExpressionNode.md) - A common type for the inner expression within parentheses.
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# omdPopup
|
|
2
|
+
|
|
3
|
+
The `omdPopup` class handles the creation and management of interactive popups for node overlays. These popups can be used for text input or for drawing with a pen tool, often integrated with a transcription service for converting handwriting to text.
|
|
4
|
+
|
|
5
|
+
## Class Definition
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
export class omdPopup
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Constructor
|
|
12
|
+
|
|
13
|
+
### `new omdPopup(targetNode, parentElement, [options])`
|
|
14
|
+
|
|
15
|
+
Creates a new `omdPopup` instance.
|
|
16
|
+
|
|
17
|
+
- **`targetNode`** (`omdNode`): The OMD node to which the popup is logically attached. Its dimensions can influence the popup's size.
|
|
18
|
+
- **`parentElement`** (`jsvgElement`): The parent `jsvgElement` (or `jsvgGroup`) to which the popup's SVG elements will be added.
|
|
19
|
+
- **`options`** (`object`, optional): Configuration options for the popup:
|
|
20
|
+
- `editable` (`boolean`): Whether the popup's input area is editable. Default: `true`.
|
|
21
|
+
- `animationDuration` (`number`): The duration of the show/hide animation in milliseconds. Default: `200`.
|
|
22
|
+
|
|
23
|
+
## Public Properties
|
|
24
|
+
|
|
25
|
+
- **`popup`** (`jsvgLayoutGroup`): The main SVG group element that contains all popup components.
|
|
26
|
+
- **`popupBackground`** (`jsvgRect`): The background rectangle of the popup.
|
|
27
|
+
- **`popupTextInput`** (`jsvgTextInput`): The text input field element (active in `'text'` mode).
|
|
28
|
+
- **`penCanvas`** (`omdCanvas`): The drawing canvas instance (active in `'pen'` mode).
|
|
29
|
+
- **`penCanvasCleanup`** (`function`): A cleanup function for the `penCanvas`.
|
|
30
|
+
- **`currentMode`** (`string`): The current mode of the popup (`'text'` or `'pen'`).
|
|
31
|
+
- **`popupAnimationId`** (`number`): The ID of the current animation frame request.
|
|
32
|
+
- **`penButton`** (`jsvgButton`): The button to switch to `'pen'` mode.
|
|
33
|
+
- **`textButton`** (`jsvgButton`): The button to switch to `'text'` mode.
|
|
34
|
+
- **`clearButton`** (`jsvgButton`): The button to clear the current input.
|
|
35
|
+
- **`submitButton`** (`jsvgButton`): The button to submit the input.
|
|
36
|
+
- **`onValidateCallback`** (`function`): The callback function to execute when the user submits input.
|
|
37
|
+
- **`onClearCallback`** (`function`): The callback function to execute when the user clears input.
|
|
38
|
+
- **`popupWidth`** (`number`): The fixed width of the popup.
|
|
39
|
+
- **`buttonSize`** (`number`): The size (width and height) of the control buttons.
|
|
40
|
+
- **`margin`** (`number`): General margin/padding value used for layout.
|
|
41
|
+
- **`buttonSpacing`** (`number`): Spacing between buttons.
|
|
42
|
+
- **`canvasMinWidth`** (`number`): Minimum width for the pen canvas.
|
|
43
|
+
- **`canvasMinHeight`** (`number`): Minimum height for the pen canvas.
|
|
44
|
+
- **`popupHeightMultiplier`** (`number`): Multiplier for the target node's height to determine popup height.
|
|
45
|
+
- **`targetNodeDefaultHeight`** (`number`): Default height for the target node if not available.
|
|
46
|
+
- **`canvasTopOffset`** (`number`): Vertical offset for the pen canvas within the popup.
|
|
47
|
+
- **`canvasLeftOffset`** (`number`): Horizontal offset for the pen canvas within the popup.
|
|
48
|
+
- **`transcribedText`** (`string` | `null`): Stores the text result from pen-to-text transcription.
|
|
49
|
+
|
|
50
|
+
## Public Methods
|
|
51
|
+
|
|
52
|
+
### `show(x, y)`
|
|
53
|
+
|
|
54
|
+
Creates and displays the popup at the specified coordinates with an animation.
|
|
55
|
+
|
|
56
|
+
- **`x`** (`number`): The x-coordinate for the popup's top-left corner.
|
|
57
|
+
- **`y`** (`number`): The y-coordinate for the popup's top-left corner.
|
|
58
|
+
- **Returns**: `Promise` - A promise that resolves when the show animation is complete.
|
|
59
|
+
|
|
60
|
+
### `hide()`
|
|
61
|
+
|
|
62
|
+
Hides the popup with an animation and performs cleanup.
|
|
63
|
+
|
|
64
|
+
- **Returns**: `Promise` - A promise that resolves when the hide animation is complete.
|
|
65
|
+
|
|
66
|
+
### `toggle(x, y)`
|
|
67
|
+
|
|
68
|
+
Toggles the visibility of the popup. If visible, it hides; otherwise, it shows.
|
|
69
|
+
|
|
70
|
+
- **`x`** (`number`): The x-coordinate for showing the popup.
|
|
71
|
+
- **`y`** (`number`): The y-coordinate for showing the popup.
|
|
72
|
+
- **Returns**: `Promise` - A promise that resolves when the animation is complete.
|
|
73
|
+
|
|
74
|
+
### `setValidationCallback(callback)`
|
|
75
|
+
|
|
76
|
+
Sets the callback function to be invoked when the user submits their input (e.g., by clicking the submit button).
|
|
77
|
+
|
|
78
|
+
- **`callback`** (`Function`): The function to call for validation.
|
|
79
|
+
|
|
80
|
+
### `setClearCallback(callback)`
|
|
81
|
+
|
|
82
|
+
Sets the callback function to be invoked when the user clears the input (e.g., by clicking the clear button).
|
|
83
|
+
|
|
84
|
+
- **`callback`** (`Function`): The function to call when clearing.
|
|
85
|
+
|
|
86
|
+
### `getValue()`
|
|
87
|
+
|
|
88
|
+
Retrieves the current input value from the popup. If in pen mode, it returns the last transcribed text and then clears it.
|
|
89
|
+
|
|
90
|
+
- **Returns**: `string` - The current input value.
|
|
91
|
+
|
|
92
|
+
### `setValue(value)`
|
|
93
|
+
|
|
94
|
+
Sets the input value of the popup's text field.
|
|
95
|
+
|
|
96
|
+
- **`value`** (`string`): The value to set.
|
|
97
|
+
|
|
98
|
+
### `switchToMode(mode)`
|
|
99
|
+
|
|
100
|
+
Switches the popup between `'text'` and `'pen'` input modes. This updates the visible input area and button states.
|
|
101
|
+
|
|
102
|
+
- **`mode`** (`string`): The mode to switch to. Can be `'text'` or `'pen'`.
|
|
103
|
+
|
|
104
|
+
### `flashValidation(isValid)`
|
|
105
|
+
|
|
106
|
+
Flashes the popup background (and associated elements) to visually indicate whether the user's input was valid or invalid.
|
|
107
|
+
|
|
108
|
+
- **`isValid`** (`boolean`): `true` for a success flash (greenish), `false` for an error flash (reddish).
|
|
109
|
+
|
|
110
|
+
### `areExpressionsEquivalent(expr1, expr2)`
|
|
111
|
+
|
|
112
|
+
Compares two mathematical expressions for equivalence. It uses `math.js` to simplify and evaluate expressions with random variable assignments to robustly check for mathematical equality.
|
|
113
|
+
|
|
114
|
+
- **`expr1`** (`string`): The first expression string.
|
|
115
|
+
- **`expr2`** (`string`): The second expression string.
|
|
116
|
+
- **Returns**: `boolean` - `true` if the expressions are mathematically equivalent, `false` otherwise.
|
|
117
|
+
|
|
118
|
+
### `destroy()`
|
|
119
|
+
|
|
120
|
+
Completely destroys the popup, removing all associated DOM elements, event listeners, and internal references. This method calls `hide()` internally to ensure a clean animated exit.
|
|
121
|
+
|
|
122
|
+
### `repositionCanvasRelativeToPopup()`
|
|
123
|
+
|
|
124
|
+
Manually triggers an update to the pen canvas's position to ensure it remains correctly aligned with the popup, especially after layout changes.
|
|
125
|
+
|
|
126
|
+
## Internal Methods
|
|
127
|
+
|
|
128
|
+
- **`_createPopup()`**: Creates the main `jsvgLayoutGroup` for the popup, its background, and initializes buttons and input areas.
|
|
129
|
+
- **`_createButtons(popupWidth, popupHeight, buttonSize, margin, buttonSpacing)`**: Creates and positions the clear, submit, pen, and text mode switch buttons.
|
|
130
|
+
- **`_createTextInput(popupWidth, popupHeight, margin)`**: Creates and styles the `jsvgTextInput` element for text input mode.
|
|
131
|
+
- **`_createPenCanvas()`**: Initializes the `omdCanvas` instance for drawing in pen mode. It handles embedding the HTML canvas within an SVG `foreignObject` if necessary.
|
|
132
|
+
- **`_showPenMode()`**: Activates the pen drawing mode, hiding the text input and showing/creating the pen canvas.
|
|
133
|
+
- **`_showTextMode()`**: Activates the text input mode, hiding the pen canvas and showing the text input.
|
|
134
|
+
- **`_addCanvasToParent(element)`**: Adds the pen canvas's DOM element (or its `foreignObject` wrapper) to the appropriate parent, handling positioning.
|
|
135
|
+
- **`_updateButtonStates()`**: Updates the visual appearance of the mode switch buttons to reflect the `currentMode`.
|
|
136
|
+
- **`_positionPopup(x, y)`**: Sets the absolute position of the main popup SVG group.
|
|
137
|
+
- **`_animateOpacity(fromOpacity, toOpacity, duration)`**: Handles the smooth opacity animation for showing and hiding the popup.
|
|
138
|
+
- **`_flashAllElements(flashColor)`**: Applies a temporary background color flash to all relevant popup elements (background, canvas) to indicate validation feedback.
|
|
139
|
+
- **`_downloadCanvasAsBitmap()`**: Converts the content of the pen canvas to a PNG bitmap and initiates the transcription process.
|
|
140
|
+
- **`_transcribeCanvas(imageBlob)`**: Sends the pen canvas image data to the `omdTranscriptionService` for handwriting recognition.
|
|
141
|
+
- **`_setSubmitButtonLoading(isLoading)`**: Controls the loading state of the submit button, including a blinking animation.
|
|
142
|
+
- **`_startBlinkingAnimation()`**: Initiates the blinking animation for the submit button.
|
|
143
|
+
- **`_stopBlinkingAnimation()`**: Stops the blinking animation for the submit button.
|
|
144
|
+
- **`_setupResizeObserver()`**: Sets up a `ResizeObserver` to monitor changes in the popup's dimensions and reposition the pen canvas accordingly.
|
|
145
|
+
- **`_updateCanvasPosition()`**: Recalculates and applies the correct position and size for the pen canvas within the popup's content area.
|
|
146
|
+
- **`_cleanup()`**: Performs comprehensive cleanup of all popup-related DOM elements, event listeners, and internal references.
|
|
147
|
+
|
|
148
|
+
## Modes
|
|
149
|
+
|
|
150
|
+
The `omdPopup` has two primary interaction modes:
|
|
151
|
+
|
|
152
|
+
- **Text Mode**: This is the default mode, providing a standard text input field (`jsvgTextInput`).
|
|
153
|
+
- **Pen Mode**: This mode allows the user to draw directly inside the popup using an embedded `omdCanvas`. The drawing can then be transcribed to text using an external OCR service (via `omdTranscriptionService`).
|
|
154
|
+
|
|
155
|
+
Users can switch between modes using the `'T'` (Text) and `'P'` (Pen) buttons on the popup.
|
|
156
|
+
|
|
157
|
+
## Example Usage
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
import { omdPopup } from '@teachinglab/omd';
|
|
161
|
+
import { omdNode } from '@teachinglab/omd'; // Assuming you have an omdNode instance
|
|
162
|
+
import { jsvgGroup } from '@teachinglab/jsvg'; // Assuming a parent jsvgElement
|
|
163
|
+
|
|
164
|
+
// Create a dummy node and parent element for demonstration
|
|
165
|
+
const targetNode = new omdNode({});
|
|
166
|
+
const parentElement = new jsvgGroup();
|
|
167
|
+
|
|
168
|
+
// Create a popup for a node
|
|
169
|
+
const popup = new omdPopup(targetNode, parentElement);
|
|
170
|
+
|
|
171
|
+
// Set a validation callback
|
|
172
|
+
popup.setValidationCallback(() => {
|
|
173
|
+
const value = popup.getValue();
|
|
174
|
+
if (popup.areExpressionsEquivalent(value, 'correct')) {
|
|
175
|
+
popup.flashValidation(true);
|
|
176
|
+
popup.hide();
|
|
177
|
+
} else {
|
|
178
|
+
popup.flashValidation(false);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
// Set a clear callback
|
|
183
|
+
popup.setClearCallback(() => {
|
|
184
|
+
console.log('Popup input cleared!');
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Show the popup at a specific position
|
|
188
|
+
// popup.show(100, 100);
|
|
189
|
+
|
|
190
|
+
// To add the parentElement to the DOM for actual display:
|
|
191
|
+
// document.body.appendChild(parentElement.svgObject);
|
|
192
|
+
```
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# omdPowerNode
|
|
2
|
+
|
|
3
|
+
Represents an exponentiation in a mathematical expression, such as `x^2` or `(a+b)^c`. This node handles the specific layout requirements of a base and a superscripted exponent, ensuring correct visual hierarchy and alignment.
|
|
4
|
+
|
|
5
|
+
## Class Definition
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
export class omdPowerNode extends omdNode
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Constructor
|
|
12
|
+
|
|
13
|
+
### `new omdPowerNode(ast)`
|
|
14
|
+
|
|
15
|
+
Creates a new `omdPowerNode` instance.
|
|
16
|
+
|
|
17
|
+
- **`ast`** (`object`): The math.js AST for the power operation. It must be an `OperatorNode` with `op: '^'` and an `args` array containing exactly two elements: the base and the exponent. Throws an error if the AST is invalid.
|
|
18
|
+
|
|
19
|
+
## Static Methods
|
|
20
|
+
|
|
21
|
+
### `fromString(expressionString)`
|
|
22
|
+
|
|
23
|
+
Creates an `omdPowerNode` from a string representation of a power expression. Requires `window.math` (math.js) to be available globally for parsing.
|
|
24
|
+
|
|
25
|
+
- **`expressionString`** (`string`): The power expression as a string (e.g., `"x^2"`, `"(a+b)^c"`).
|
|
26
|
+
- **Returns**: `omdPowerNode` - A new instance.
|
|
27
|
+
- **Throws**: `Error` if `math.js` is not available, if the string cannot be parsed, or if it does not represent a valid power expression.
|
|
28
|
+
|
|
29
|
+
## Public Properties
|
|
30
|
+
|
|
31
|
+
- **`base`** (`omdNode`): The node representing the base of the power operation.
|
|
32
|
+
- **`exponent`** (`omdNode`): The node representing the exponent.
|
|
33
|
+
- **`value`** (`string`): The operator symbol for power, which is `"^"`.
|
|
34
|
+
|
|
35
|
+
## Public Methods
|
|
36
|
+
|
|
37
|
+
### `computeDimensions()`
|
|
38
|
+
|
|
39
|
+
Calculates the dimensions of the power node. It computes the dimensions of the base and exponent (scaling the exponent's font size down). The total width is the sum of their widths, and the total height accounts for the base's height plus the vertical offset needed for the superscripted exponent.
|
|
40
|
+
|
|
41
|
+
- **Overrides**: `omdNode.computeDimensions()`.
|
|
42
|
+
|
|
43
|
+
### `updateLayout()`
|
|
44
|
+
|
|
45
|
+
Updates the layout of the power node. It positions the `base` at the bottom of the node's bounding box to ensure space for the exponent above it. The `exponent` is then positioned to the right of the base and shifted upwards by a calculated superscript offset.
|
|
46
|
+
|
|
47
|
+
- **Overrides**: `omdNode.updateLayout()`.
|
|
48
|
+
|
|
49
|
+
### `getSuperscriptOffset()`
|
|
50
|
+
|
|
51
|
+
Calculates the vertical offset (in pixels) by which the exponent should be raised above the base. This offset is a proportion of the current font size to ensure consistent scaling.
|
|
52
|
+
|
|
53
|
+
- **Returns**: `number` - The vertical offset.
|
|
54
|
+
|
|
55
|
+
### `getAlignmentBaseline()`
|
|
56
|
+
|
|
57
|
+
Calculates the vertical alignment point for the node. For a power node, the baseline is determined by the baseline of its `base` expression, ensuring proper alignment with other mathematical elements.
|
|
58
|
+
|
|
59
|
+
- **Overrides**: `omdNode.getAlignmentBaseline()`.
|
|
60
|
+
|
|
61
|
+
### `clone()`
|
|
62
|
+
|
|
63
|
+
Creates a deep, structural clone of the power node, including its `base` and `exponent` nodes. The cloned node's `provenance` array is updated to include the original node's ID.
|
|
64
|
+
|
|
65
|
+
- **Returns**: `omdPowerNode` - A new, identical instance of the power node.
|
|
66
|
+
|
|
67
|
+
### `toMathJSNode()`
|
|
68
|
+
|
|
69
|
+
Converts the `omdPowerNode` back into its math.js AST representation. It creates an `OperatorNode` with `op: '^'` and `fn: 'pow'`, containing the converted base and exponent ASTs.
|
|
70
|
+
|
|
71
|
+
- **Returns**: `object` - A math.js `OperatorNode` for the power operation. The returned object also includes a `clone` method for compatibility.
|
|
72
|
+
|
|
73
|
+
### `toString()`
|
|
74
|
+
|
|
75
|
+
Converts the node to its string representation, adding parentheses where necessary to preserve the correct order of operations for both the base and the exponent.
|
|
76
|
+
|
|
77
|
+
- **Returns**: `string` - e.g., `"(x+1)^2"`.
|
|
78
|
+
|
|
79
|
+
### `evaluate(variables)`
|
|
80
|
+
|
|
81
|
+
Evaluates the power expression by raising the evaluated base to the power of the evaluated exponent. It handles cases where base or exponent might not be numerical.
|
|
82
|
+
|
|
83
|
+
- **`variables`** (`object`): A map of variable names to their numeric values.
|
|
84
|
+
- **Returns**: `number` - The result of the exponentiation, or `NaN` if base or exponent cannot be evaluated to a number.
|
|
85
|
+
|
|
86
|
+
### `isSquare()`
|
|
87
|
+
|
|
88
|
+
Checks if the exponent of the power node is the constant value `2`.
|
|
89
|
+
|
|
90
|
+
- **Returns**: `boolean`.
|
|
91
|
+
|
|
92
|
+
### `isCube()`
|
|
93
|
+
|
|
94
|
+
Checks if the exponent of the power node is the constant value `3`.
|
|
95
|
+
|
|
96
|
+
- **Returns**: `boolean`.
|
|
97
|
+
|
|
98
|
+
## Internal Methods
|
|
99
|
+
|
|
100
|
+
- **`parseValue()`**: Sets the `value` property to `"^"`.
|
|
101
|
+
- **`createOperand(ast)`**: Creates an `omdNode` instance for the base or exponent from its AST.
|
|
102
|
+
|
|
103
|
+
## Example
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
import { omdPowerNode } from '@teachinglab/omd';
|
|
107
|
+
import * as math from 'mathjs';
|
|
108
|
+
|
|
109
|
+
// Create a node representing x^2
|
|
110
|
+
const ast = math.parse('x^2');
|
|
111
|
+
const powerNode = new omdPowerNode(ast);
|
|
112
|
+
|
|
113
|
+
// Set font size and render
|
|
114
|
+
powerNode.setFontSize(32);
|
|
115
|
+
powerNode.initialize();
|
|
116
|
+
|
|
117
|
+
// Check properties
|
|
118
|
+
console.log(powerNode.isSquare()); // true
|
|
119
|
+
|
|
120
|
+
// Evaluate
|
|
121
|
+
console.log(powerNode.evaluate({ x: 5 })); // 25
|
|
122
|
+
|
|
123
|
+
// Add to an SVG container to display
|
|
124
|
+
// const svgContainer = new jsvgContainer();
|
|
125
|
+
// svgContainer.addChild(powerNode);
|
|
126
|
+
// document.body.appendChild(svgContainer.svgObject);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## See Also
|
|
130
|
+
|
|
131
|
+
- [`omdNode`](./omdNode.md) - The base class for all OMD nodes.
|
|
132
|
+
- [`omdBinaryExpressionNode`](./omdBinaryExpressionNode.md) - Can be used for complex bases or exponents.
|