@java-memory-playground/java-memory-playground 0.2.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.
- package/LICENSE +21 -0
- package/README.md +345 -0
- package/dist/ArrayCreationDialog.d.ts +8 -0
- package/dist/ClassSource.d.ts +15 -0
- package/dist/ConfigView.d.ts +1 -0
- package/dist/ConfirmDialog.d.ts +16 -0
- package/dist/InlineString.d.ts +14 -0
- package/dist/KeyboardShortcuts.d.ts +7 -0
- package/dist/MemoryPlayground.d.ts +74 -0
- package/dist/MemoryView.d.ts +9 -0
- package/dist/MethodCallNode.d.ts +8 -0
- package/dist/ObjectNode.d.ts +7 -0
- package/dist/ReferenceEdge.d.ts +3 -0
- package/dist/Sidebar.d.ts +11 -0
- package/dist/SimpleInputDialog.d.ts +10 -0
- package/dist/StepBar.d.ts +10 -0
- package/dist/VariableNode.d.ts +5 -0
- package/dist/ariaLabels.d.ts +11 -0
- package/dist/canonical.d.ts +19 -0
- package/dist/exportSteps.d.ts +30 -0
- package/dist/fitPadding.d.ts +13 -0
- package/dist/getEdgesAndNodes.d.ts +10 -0
- package/dist/helper.d.ts +19 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +13208 -0
- package/dist/javaSource.d.ts +17 -0
- package/dist/klassImpact.d.ts +28 -0
- package/dist/memory.d.ts +152 -0
- package/dist/palette.d.ts +29 -0
- package/dist/presets.d.ts +10 -0
- package/dist/serde.d.ts +4 -0
- package/dist/stepDiff.d.ts +18 -0
- package/dist/store.d.ts +230 -0
- package/dist/storeContext.d.ts +24 -0
- package/dist/translations.d.ts +119 -0
- package/dist/types.d.ts +23 -0
- package/dist/useDnD.d.ts +23 -0
- package/dist/useUndoRedo.d.ts +13 -0
- package/dist/utils.d.ts +8 -0
- package/package.json +72 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Klasses } from "./memory";
|
|
2
|
+
/**
|
|
3
|
+
* Reads the class structure out of Java source.
|
|
4
|
+
*
|
|
5
|
+
* Only declarations are read — class names, and the name and type of each
|
|
6
|
+
* field. Method bodies are skipped wholesale and nothing is executed or
|
|
7
|
+
* interpreted: the source is a convenient way to write down the shape of the
|
|
8
|
+
* objects a diagram will contain, not a program the playground runs.
|
|
9
|
+
*/
|
|
10
|
+
export type ParsedClasses = {
|
|
11
|
+
klasses: Klasses;
|
|
12
|
+
/** Things the teacher probably wants to know about, in reading order. */
|
|
13
|
+
problems: string[];
|
|
14
|
+
};
|
|
15
|
+
export declare const parseJavaClasses: (source: string) => ParsedClasses;
|
|
16
|
+
/** Writes the current classes back out as Java, for editing as source. */
|
|
17
|
+
export declare const toJavaSource: (klasses: Klasses) => string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Klasses } from "./memory";
|
|
2
|
+
import { CustomEdgeType, CustomNodeType } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* What applying a set of classes would cost the objects already drawn.
|
|
5
|
+
*
|
|
6
|
+
* Classes belong to the whole diagram, so changing them reaches every step. A
|
|
7
|
+
* teacher pasting a new file over the old one should be told what that takes
|
|
8
|
+
* with it before it happens — but only when it takes something, because a
|
|
9
|
+
* warning that always appears is one nobody reads.
|
|
10
|
+
*/
|
|
11
|
+
export type KlassImpact = {
|
|
12
|
+
/** Objects of a class that is gone. They stay; no new ones can be made. */
|
|
13
|
+
orphaned: Array<{
|
|
14
|
+
klass: string;
|
|
15
|
+
count: number;
|
|
16
|
+
}>;
|
|
17
|
+
/** Values and references a removed field takes with it. */
|
|
18
|
+
dropped: Array<{
|
|
19
|
+
klass: string;
|
|
20
|
+
field: string;
|
|
21
|
+
count: number;
|
|
22
|
+
}>;
|
|
23
|
+
};
|
|
24
|
+
export declare const klassImpact: (steps: Array<{
|
|
25
|
+
nodes: CustomNodeType[];
|
|
26
|
+
edges: CustomEdgeType[];
|
|
27
|
+
}>, klasses: Klasses) => KlassImpact;
|
|
28
|
+
export declare const hasImpact: ({ orphaned, dropped }: KlassImpact) => boolean;
|
package/dist/memory.d.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
export declare const numericDataTypes: string[];
|
|
2
|
+
/**
|
|
3
|
+
* The eight-ish types whose value really is stored in the variable itself.
|
|
4
|
+
*
|
|
5
|
+
* `String` is deliberately NOT here: in Java it is a reference type, and a
|
|
6
|
+
* String value lives on the heap like any other object. Drawing every String as
|
|
7
|
+
* its own box clutters a diagram whose lesson is elsewhere, so the playground
|
|
8
|
+
* collapses them by default — but that is a display choice (`options.
|
|
9
|
+
* inlineStrings`), not a claim about how memory works.
|
|
10
|
+
*/
|
|
11
|
+
export declare const primitveDataTypes: string[];
|
|
12
|
+
/** The class name of the heap objects that hold String values. */
|
|
13
|
+
export declare const STRING_KLASS = "String";
|
|
14
|
+
/** Types always offered in a type picker, before the user's own classes. */
|
|
15
|
+
export declare const builtInDataTypes: string[];
|
|
16
|
+
/**
|
|
17
|
+
* What a field of this type holds before anyone has put anything in it.
|
|
18
|
+
*
|
|
19
|
+
* A reference starts out null, which the diagram draws as an empty handle
|
|
20
|
+
* rather than a value, so it has none.
|
|
21
|
+
*/
|
|
22
|
+
export declare const defaultValueFor: (dataType: string) => Attribute["value"];
|
|
23
|
+
export type DataType = "int" | "long" | "short" | "byte" | "float" | "char" | "double" | "boolean" | "String" | "Array" | string;
|
|
24
|
+
export interface KlassAttributes {
|
|
25
|
+
[key: string]: DataType;
|
|
26
|
+
}
|
|
27
|
+
export type Klass = {
|
|
28
|
+
attributes: KlassAttributes;
|
|
29
|
+
};
|
|
30
|
+
export type Attribute = {
|
|
31
|
+
dataType: DataType;
|
|
32
|
+
value?: string | number | boolean;
|
|
33
|
+
};
|
|
34
|
+
export interface ObjAttributes {
|
|
35
|
+
[key: string]: Attribute;
|
|
36
|
+
}
|
|
37
|
+
export type Obj = {
|
|
38
|
+
klass: string;
|
|
39
|
+
attributes: ObjAttributes;
|
|
40
|
+
position: {
|
|
41
|
+
x: number;
|
|
42
|
+
y: number;
|
|
43
|
+
};
|
|
44
|
+
arrayElementType?: DataType;
|
|
45
|
+
/**
|
|
46
|
+
* The characters held by a String object (`klass === STRING_KLASS`), without
|
|
47
|
+
* surrounding quotes — those are added when rendering.
|
|
48
|
+
*/
|
|
49
|
+
literal?: string;
|
|
50
|
+
};
|
|
51
|
+
export type Variable = {
|
|
52
|
+
name: string;
|
|
53
|
+
dataType: DataType;
|
|
54
|
+
value: string | null;
|
|
55
|
+
position: {
|
|
56
|
+
x: number;
|
|
57
|
+
y: number;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
export interface localVariables {
|
|
61
|
+
[key: string]: Attribute;
|
|
62
|
+
}
|
|
63
|
+
export type MethodCall = {
|
|
64
|
+
name: string;
|
|
65
|
+
index: number;
|
|
66
|
+
localVariables: localVariables;
|
|
67
|
+
position: {
|
|
68
|
+
x: number;
|
|
69
|
+
y: number;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
export interface Klasses {
|
|
73
|
+
[key: string]: Klass;
|
|
74
|
+
}
|
|
75
|
+
export interface Objs {
|
|
76
|
+
[key: string]: Obj;
|
|
77
|
+
}
|
|
78
|
+
export interface Variables {
|
|
79
|
+
[key: string]: Variable;
|
|
80
|
+
}
|
|
81
|
+
export interface MethodCalls {
|
|
82
|
+
[key: number]: MethodCall;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* One state of the diagram: the heap, the roots and the call stack at a single
|
|
86
|
+
* moment. A diagram is a sequence of these, so that a stack can be shown doing
|
|
87
|
+
* the thing that makes it a stack — growing and shrinking over time.
|
|
88
|
+
*/
|
|
89
|
+
export type Step = {
|
|
90
|
+
/** Shown in the step bar, e.g. "3: head = head.next". */
|
|
91
|
+
label?: string;
|
|
92
|
+
/** The teacher's note about what this step did. */
|
|
93
|
+
note?: string;
|
|
94
|
+
/**
|
|
95
|
+
* The student produces this step themselves. Its contents are the solution:
|
|
96
|
+
* a student's playground starts them from the previous step and checks what
|
|
97
|
+
* they build against it.
|
|
98
|
+
*/
|
|
99
|
+
exercise?: boolean;
|
|
100
|
+
objects: Objs;
|
|
101
|
+
variables: Variables;
|
|
102
|
+
methodCalls: MethodCalls;
|
|
103
|
+
};
|
|
104
|
+
export type Memory = {
|
|
105
|
+
viewport: {
|
|
106
|
+
x: number;
|
|
107
|
+
y: number;
|
|
108
|
+
zoom: number;
|
|
109
|
+
};
|
|
110
|
+
options: {
|
|
111
|
+
disableGarbageCollector?: boolean;
|
|
112
|
+
hideSidebar?: boolean;
|
|
113
|
+
hideCallMethod?: boolean;
|
|
114
|
+
hideDeclareGlobalVariable?: boolean;
|
|
115
|
+
hideNewArray?: boolean;
|
|
116
|
+
createNewOnEdgeDrop?: boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Draw String values inside the object that references them instead of as
|
|
119
|
+
* their own heap box. On by default: a diagram about a linked list should
|
|
120
|
+
* not sprout a box per name. Turn it off to teach that a String is an
|
|
121
|
+
* object like any other — `==` versus `.equals()`, the string pool.
|
|
122
|
+
*/
|
|
123
|
+
inlineStrings?: boolean;
|
|
124
|
+
/** Hide the step bar, for lessons that are about one picture. */
|
|
125
|
+
hideSteps?: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Stop marking what a step changed compared with the one before it. The
|
|
128
|
+
* marking is usually the point of a trace, so it is on by default.
|
|
129
|
+
*/
|
|
130
|
+
hideStepChanges?: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Ask which objects are unreachable before collecting them, instead of
|
|
133
|
+
* simply sweeping. Committing to an answer is where the learning is.
|
|
134
|
+
*/
|
|
135
|
+
gcPrediction?: boolean;
|
|
136
|
+
};
|
|
137
|
+
klasses: Klasses;
|
|
138
|
+
/**
|
|
139
|
+
* The steps of the diagram. `parseMemory` always fills this in, from the
|
|
140
|
+
* single-state fields below when a diagram predates stepping.
|
|
141
|
+
*/
|
|
142
|
+
steps?: Step[];
|
|
143
|
+
/**
|
|
144
|
+
* The state of a one-step diagram. Still written for those, so that a link to
|
|
145
|
+
* a single picture stays readable by older versions, and still read from
|
|
146
|
+
* every diagram saved before steps existed.
|
|
147
|
+
*/
|
|
148
|
+
objects?: Objs;
|
|
149
|
+
variables?: Variables;
|
|
150
|
+
methodCalls?: MethodCalls;
|
|
151
|
+
};
|
|
152
|
+
export declare const initialMemory: Memory;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The handful of palette entries that have to exist in JavaScript as well as in
|
|
3
|
+
* CSS, named after the tokens in `index.css` they duplicate.
|
|
4
|
+
*
|
|
5
|
+
* Anything drawn into an `<svg>` or onto a canvas has to be a literal colour;
|
|
6
|
+
* `var(--jmp-…)` does not survive being photographed. html-to-image copies
|
|
7
|
+
* computed styles onto its clone but stops at an `<svg>`, taking that subtree
|
|
8
|
+
* wholesale, and then renders the clone outside `.java-memory-playground`,
|
|
9
|
+
* where the custom properties are not defined. An unresolvable `var()` is
|
|
10
|
+
* invalid at computed-value time, so `stroke` falls back to its initial `none`
|
|
11
|
+
* and a reference disappears from the picture — while its arrowhead, whose
|
|
12
|
+
* `fill` falls back to black, stays behind pointing at nothing. A canvas has no
|
|
13
|
+
* stylesheet to read at all.
|
|
14
|
+
*
|
|
15
|
+
* `palette.test.ts` keeps these in step with `index.css`, so a colour still
|
|
16
|
+
* only has to be changed in one place.
|
|
17
|
+
*/
|
|
18
|
+
/** `--jmp-black`. What print mode draws its references in. */
|
|
19
|
+
export declare const BLACK = "#000000";
|
|
20
|
+
/** `--jmp-text` — Coal. */
|
|
21
|
+
export declare const TEXT = "#242428";
|
|
22
|
+
/** `--jmp-text-muted` — Charcoal. */
|
|
23
|
+
export declare const TEXT_MUTED = "#3c3c3c";
|
|
24
|
+
/** `--jmp-surface` — White. */
|
|
25
|
+
export declare const SURFACE = "#ffffff";
|
|
26
|
+
/** `--jmp-surface-sunken` — Whitesmoke. */
|
|
27
|
+
export declare const SURFACE_SUNKEN = "#f5f5f5";
|
|
28
|
+
/** `--jmp-warning`. */
|
|
29
|
+
export declare const WARNING = "#b7791f";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Memory } from "./memory";
|
|
2
|
+
export type PresetName = "references" | "stack" | "everything";
|
|
3
|
+
/**
|
|
4
|
+
* Option sets for the stages a course goes through.
|
|
5
|
+
*
|
|
6
|
+
* The options already describe a teaching sequence — references before the
|
|
7
|
+
* stack, arrays and the collector after — but only as flags a teacher has to
|
|
8
|
+
* remember the combination of. These name the combinations.
|
|
9
|
+
*/
|
|
10
|
+
export declare const optionPresets: Record<PresetName, Memory["options"]>;
|
package/dist/serde.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { StoreStep } from "./store";
|
|
2
|
+
export type StepDiff = {
|
|
3
|
+
/** Nodes that did not exist in the previous step. */
|
|
4
|
+
added: Set<string>;
|
|
5
|
+
/** Nodes whose contents differ from the previous step. */
|
|
6
|
+
changed: Set<string>;
|
|
7
|
+
/** Edges that are new, or that now point somewhere else. */
|
|
8
|
+
edges: Set<string>;
|
|
9
|
+
};
|
|
10
|
+
export declare const emptyDiff: () => StepDiff;
|
|
11
|
+
/**
|
|
12
|
+
* What the current step changed, compared with the one before it.
|
|
13
|
+
*
|
|
14
|
+
* This is what turns a sequence of pictures into a story: the interesting part
|
|
15
|
+
* of a step is rarely the whole diagram, it is the one reference that moved or
|
|
16
|
+
* the one frame that appeared.
|
|
17
|
+
*/
|
|
18
|
+
export declare const diffSteps: (previous: StoreStep | undefined, current: StoreStep) => StepDiff;
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import type { EdgeChange, NodeChange, Viewport } from "@xyflow/react";
|
|
2
|
+
import { ExerciseResult } from "./canonical";
|
|
3
|
+
import { Memory } from "./memory";
|
|
4
|
+
import { Translations } from "./translations";
|
|
5
|
+
import { CustomEdgeType, CustomNodeType } from "./types";
|
|
6
|
+
export type Route = "view" | "config";
|
|
7
|
+
/**
|
|
8
|
+
* Who the playground is for.
|
|
9
|
+
*
|
|
10
|
+
* `view` is the student's playground: the whole diagram, every edit, steps to
|
|
11
|
+
* walk through. `edit` adds the teacher's tools on top — configuring classes
|
|
12
|
+
* and options, and authoring the steps of a trace.
|
|
13
|
+
*/
|
|
14
|
+
export type PlaygroundMode = "view" | "edit";
|
|
15
|
+
/** One step, in the shape React Flow wants. */
|
|
16
|
+
export type StoreStep = {
|
|
17
|
+
label?: string;
|
|
18
|
+
note?: string;
|
|
19
|
+
exercise?: boolean;
|
|
20
|
+
nodes: CustomNodeType[];
|
|
21
|
+
edges: CustomEdgeType[];
|
|
22
|
+
};
|
|
23
|
+
export type GcPredictionResult = {
|
|
24
|
+
/** Unreachable objects the prediction found. */
|
|
25
|
+
found: number;
|
|
26
|
+
/** Unreachable objects it missed. */
|
|
27
|
+
missed: number;
|
|
28
|
+
/** Objects it marked that are still reachable. */
|
|
29
|
+
wrong: number;
|
|
30
|
+
};
|
|
31
|
+
type Updater<T> = T[] | ((current: T[]) => T[]);
|
|
32
|
+
export type RFState = {
|
|
33
|
+
route: Route;
|
|
34
|
+
mode: PlaygroundMode;
|
|
35
|
+
selectedNodeId: string;
|
|
36
|
+
/** Whether this store mirrors its memory into `location.hash`. */
|
|
37
|
+
persistence: boolean;
|
|
38
|
+
steps: StoreStep[];
|
|
39
|
+
currentStep: number;
|
|
40
|
+
klasses: Memory["klasses"];
|
|
41
|
+
options: Memory["options"];
|
|
42
|
+
viewport: Viewport;
|
|
43
|
+
/**
|
|
44
|
+
* The authored contents of the exercise steps, kept aside in a student's
|
|
45
|
+
* playground so that their attempt can be compared with it.
|
|
46
|
+
*/
|
|
47
|
+
solutions: Record<number, StoreStep>;
|
|
48
|
+
exerciseResult: ExerciseResult | null;
|
|
49
|
+
/** Ids of the objects a prediction has marked as unreachable, while running. */
|
|
50
|
+
gcPrediction: string[] | null;
|
|
51
|
+
gcResult: GcPredictionResult | null;
|
|
52
|
+
defaultLanguage?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Bumped every time the user presses Save. The diagram itself is kept in the
|
|
55
|
+
* store continuously; this is what tells a host "the user committed".
|
|
56
|
+
*/
|
|
57
|
+
saveCount: number;
|
|
58
|
+
save: () => void;
|
|
59
|
+
goToStep: (index: number) => void;
|
|
60
|
+
addStep: () => void;
|
|
61
|
+
deleteStep: (index: number) => void;
|
|
62
|
+
setStepLabel: (index: number, label: string) => void;
|
|
63
|
+
/** The nodes and edges of the step on screen. */
|
|
64
|
+
getNodes: () => CustomNodeType[];
|
|
65
|
+
getEdges: () => CustomEdgeType[];
|
|
66
|
+
/** Reconciles every step's objects with a new set of class definitions. */
|
|
67
|
+
applyKlasses: (klasses: Memory["klasses"], options: Memory["options"]) => void;
|
|
68
|
+
setRoute: (route: Route) => void;
|
|
69
|
+
selectNodeId: (nodeId: string) => void;
|
|
70
|
+
setDefaultLanguage: (language: string) => void;
|
|
71
|
+
onNodesChange: (changes: NodeChange<CustomNodeType>[]) => void;
|
|
72
|
+
onEdgesChange: (changes: EdgeChange<CustomEdgeType>[]) => void;
|
|
73
|
+
setNodes: (nodes: Updater<CustomNodeType>) => void;
|
|
74
|
+
setEdges: (edges: Updater<CustomEdgeType>) => void;
|
|
75
|
+
setKlasses: (klasses: Memory["klasses"]) => void;
|
|
76
|
+
setOptions: (options: Memory["options"]) => void;
|
|
77
|
+
setViewport: (viewport: Viewport) => void;
|
|
78
|
+
setStepExercise: (index: number, exercise: boolean) => void;
|
|
79
|
+
checkExercise: () => void;
|
|
80
|
+
revealSolution: () => void;
|
|
81
|
+
clearExerciseResult: () => void;
|
|
82
|
+
startGcPrediction: () => void;
|
|
83
|
+
toggleGcPrediction: (id: string) => void;
|
|
84
|
+
cancelGcPrediction: () => void;
|
|
85
|
+
/** Checks a prediction if one is running, then collects. */
|
|
86
|
+
collectGarbage: () => void;
|
|
87
|
+
loadMemory: (memory: Memory) => void;
|
|
88
|
+
getMemory: () => Memory;
|
|
89
|
+
getLanguage: () => string;
|
|
90
|
+
getTranslations: () => Translations;
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Set whether playgrounds created from now on mirror their state into
|
|
94
|
+
* `location.hash`. Off by default; the standalone web app turns it on during
|
|
95
|
+
* bootstrap. Embedded usages (React hosts, the web component) leave it off and
|
|
96
|
+
* drive state through the `memory` prop and the `change` event instead.
|
|
97
|
+
*/
|
|
98
|
+
export declare function setPersistence(enabled: boolean): void;
|
|
99
|
+
/** The persistence setting new playgrounds are created with. */
|
|
100
|
+
export declare function isPersistenceEnabled(): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Creates an independent playground store.
|
|
103
|
+
*
|
|
104
|
+
* One store per `MemoryPlayground` instance, so that a page can host several
|
|
105
|
+
* playgrounds without them overwriting each other's diagrams.
|
|
106
|
+
*/
|
|
107
|
+
export declare const createMemoryStore: (persistence?: boolean, mode?: PlaygroundMode) => Omit<Omit<import("zustand").StoreApi<RFState>, "persist" | "setState"> & {
|
|
108
|
+
setState(partial: Partial<RFState> | RFState | ((state: RFState) => Partial<RFState> | RFState), replace?: false | undefined): unknown;
|
|
109
|
+
setState(state: RFState | ((state: RFState) => RFState), replace: true): unknown;
|
|
110
|
+
persist: {
|
|
111
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<RFState, any, unknown>>) => void;
|
|
112
|
+
clearStorage: () => void;
|
|
113
|
+
rehydrate: () => Promise<void> | void;
|
|
114
|
+
hasHydrated: () => boolean;
|
|
115
|
+
onHydrate: (fn: (state: RFState) => void) => () => void;
|
|
116
|
+
onFinishHydration: (fn: (state: RFState) => void) => () => void;
|
|
117
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<RFState, any, unknown>>;
|
|
118
|
+
};
|
|
119
|
+
}, "temporal"> & {
|
|
120
|
+
temporal: import("zustand").StoreApi<import("zundo").TemporalState<{
|
|
121
|
+
steps: {
|
|
122
|
+
label: string | undefined;
|
|
123
|
+
note: string | undefined;
|
|
124
|
+
nodes: ({
|
|
125
|
+
[x: string]: unknown;
|
|
126
|
+
id: string;
|
|
127
|
+
position: import("@xyflow/react").XYPosition;
|
|
128
|
+
data: import("./memory").MethodCall;
|
|
129
|
+
sourcePosition?: import("@xyflow/react").Position;
|
|
130
|
+
targetPosition?: import("@xyflow/react").Position;
|
|
131
|
+
hidden?: boolean;
|
|
132
|
+
draggable?: boolean;
|
|
133
|
+
selectable?: boolean;
|
|
134
|
+
connectable?: boolean;
|
|
135
|
+
deletable?: boolean;
|
|
136
|
+
dragHandle?: string;
|
|
137
|
+
initialWidth?: number;
|
|
138
|
+
initialHeight?: number;
|
|
139
|
+
parentId?: string;
|
|
140
|
+
zIndex?: number;
|
|
141
|
+
extent?: 'parent' | import("@xyflow/react").CoordinateExtent | null;
|
|
142
|
+
expandParent?: boolean;
|
|
143
|
+
ariaLabel?: string;
|
|
144
|
+
origin?: import("@xyflow/react").NodeOrigin;
|
|
145
|
+
handles?: import("@xyflow/react").NodeHandle[];
|
|
146
|
+
type: "method-call";
|
|
147
|
+
style?: import("react").CSSProperties;
|
|
148
|
+
className?: string;
|
|
149
|
+
resizing?: boolean;
|
|
150
|
+
focusable?: boolean;
|
|
151
|
+
ariaRole?: import("react").AriaRole;
|
|
152
|
+
domAttributes?: Omit<import("react").HTMLAttributes<HTMLDivElement>, 'id' | 'style' | 'className' | 'draggable' | 'role' | 'aria-label' | 'defaultValue' | 'dangerouslySetInnerHTML' | keyof import("react").DOMAttributes<HTMLDivElement>>;
|
|
153
|
+
} | {
|
|
154
|
+
[x: string]: unknown;
|
|
155
|
+
id: string;
|
|
156
|
+
position: import("@xyflow/react").XYPosition;
|
|
157
|
+
data: import("./memory").Obj;
|
|
158
|
+
sourcePosition?: import("@xyflow/react").Position;
|
|
159
|
+
targetPosition?: import("@xyflow/react").Position;
|
|
160
|
+
hidden?: boolean;
|
|
161
|
+
draggable?: boolean;
|
|
162
|
+
selectable?: boolean;
|
|
163
|
+
connectable?: boolean;
|
|
164
|
+
deletable?: boolean;
|
|
165
|
+
dragHandle?: string;
|
|
166
|
+
initialWidth?: number;
|
|
167
|
+
initialHeight?: number;
|
|
168
|
+
parentId?: string;
|
|
169
|
+
zIndex?: number;
|
|
170
|
+
extent?: 'parent' | import("@xyflow/react").CoordinateExtent | null;
|
|
171
|
+
expandParent?: boolean;
|
|
172
|
+
ariaLabel?: string;
|
|
173
|
+
origin?: import("@xyflow/react").NodeOrigin;
|
|
174
|
+
handles?: import("@xyflow/react").NodeHandle[];
|
|
175
|
+
type: "object";
|
|
176
|
+
style?: import("react").CSSProperties;
|
|
177
|
+
className?: string;
|
|
178
|
+
resizing?: boolean;
|
|
179
|
+
focusable?: boolean;
|
|
180
|
+
ariaRole?: import("react").AriaRole;
|
|
181
|
+
domAttributes?: Omit<import("react").HTMLAttributes<HTMLDivElement>, 'id' | 'style' | 'className' | 'draggable' | 'role' | 'aria-label' | 'defaultValue' | 'dangerouslySetInnerHTML' | keyof import("react").DOMAttributes<HTMLDivElement>>;
|
|
182
|
+
} | {
|
|
183
|
+
[x: string]: unknown;
|
|
184
|
+
id: string;
|
|
185
|
+
position: import("@xyflow/react").XYPosition;
|
|
186
|
+
data: import("./memory").Variable;
|
|
187
|
+
sourcePosition?: import("@xyflow/react").Position;
|
|
188
|
+
targetPosition?: import("@xyflow/react").Position;
|
|
189
|
+
hidden?: boolean;
|
|
190
|
+
draggable?: boolean;
|
|
191
|
+
selectable?: boolean;
|
|
192
|
+
connectable?: boolean;
|
|
193
|
+
deletable?: boolean;
|
|
194
|
+
dragHandle?: string;
|
|
195
|
+
initialWidth?: number;
|
|
196
|
+
initialHeight?: number;
|
|
197
|
+
parentId?: string;
|
|
198
|
+
zIndex?: number;
|
|
199
|
+
extent?: 'parent' | import("@xyflow/react").CoordinateExtent | null;
|
|
200
|
+
expandParent?: boolean;
|
|
201
|
+
ariaLabel?: string;
|
|
202
|
+
origin?: import("@xyflow/react").NodeOrigin;
|
|
203
|
+
handles?: import("@xyflow/react").NodeHandle[];
|
|
204
|
+
type: "variable";
|
|
205
|
+
style?: import("react").CSSProperties;
|
|
206
|
+
className?: string;
|
|
207
|
+
resizing?: boolean;
|
|
208
|
+
focusable?: boolean;
|
|
209
|
+
ariaRole?: import("react").AriaRole;
|
|
210
|
+
domAttributes?: Omit<import("react").HTMLAttributes<HTMLDivElement>, 'id' | 'style' | 'className' | 'draggable' | 'role' | 'aria-label' | 'defaultValue' | 'dangerouslySetInnerHTML' | keyof import("react").DOMAttributes<HTMLDivElement>>;
|
|
211
|
+
})[];
|
|
212
|
+
edges: CustomEdgeType[];
|
|
213
|
+
}[];
|
|
214
|
+
klasses: import("./memory").Klasses;
|
|
215
|
+
options: {
|
|
216
|
+
disableGarbageCollector?: boolean;
|
|
217
|
+
hideSidebar?: boolean;
|
|
218
|
+
hideCallMethod?: boolean;
|
|
219
|
+
hideDeclareGlobalVariable?: boolean;
|
|
220
|
+
hideNewArray?: boolean;
|
|
221
|
+
createNewOnEdgeDrop?: boolean;
|
|
222
|
+
inlineStrings?: boolean;
|
|
223
|
+
hideSteps?: boolean;
|
|
224
|
+
hideStepChanges?: boolean;
|
|
225
|
+
gcPrediction?: boolean;
|
|
226
|
+
};
|
|
227
|
+
}>>;
|
|
228
|
+
};
|
|
229
|
+
export type MemoryStore = ReturnType<typeof createMemoryStore>;
|
|
230
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import type { TemporalState } from "zundo";
|
|
3
|
+
import { MemoryStore, PlaygroundMode, RFState } from "./store";
|
|
4
|
+
export declare const StoreProvider: ({ persistence, mode, children, }: {
|
|
5
|
+
persistence?: boolean;
|
|
6
|
+
mode?: PlaygroundMode;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}) => import("react").JSX.Element;
|
|
9
|
+
/**
|
|
10
|
+
* Reads from the store of the surrounding `MemoryPlayground`.
|
|
11
|
+
*
|
|
12
|
+
* For a selector that builds an object, wrap it in zustand's `useShallow` so
|
|
13
|
+
* the component only re-renders when one of the picked values actually changes.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useStore<U>(selector: (state: RFState) => U): U;
|
|
16
|
+
/** The raw store instance, for reading or subscribing outside of React. */
|
|
17
|
+
export declare function useMemoryStore(): MemoryStore;
|
|
18
|
+
/**
|
|
19
|
+
* Reads the undo/redo history of the surrounding `MemoryPlayground`.
|
|
20
|
+
*
|
|
21
|
+
* `undo`, `redo`, `pastStates` and `futureStates` come from zundo.
|
|
22
|
+
*/
|
|
23
|
+
export declare function useTemporalStore<U>(selector: (state: TemporalState<Partial<RFState>>) => U): U;
|
|
24
|
+
export default useStore;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
export interface Translations {
|
|
2
|
+
save: string;
|
|
3
|
+
saveUrl: string;
|
|
4
|
+
downloadPng: string;
|
|
5
|
+
downloadAllPng: string;
|
|
6
|
+
downloadAllPngHint: string;
|
|
7
|
+
printMode: string;
|
|
8
|
+
printModeHint: string;
|
|
9
|
+
config: string;
|
|
10
|
+
runGarbageCollector: string;
|
|
11
|
+
predictGarbage: string;
|
|
12
|
+
predictGarbageHint: (marked: number) => string;
|
|
13
|
+
checkAndCollect: string;
|
|
14
|
+
gcScore: (found: number, missed: number, wrong: number) => string;
|
|
15
|
+
undo: string;
|
|
16
|
+
redo: string;
|
|
17
|
+
help: string;
|
|
18
|
+
newInstanceOf: (klass: string) => string;
|
|
19
|
+
newArray: string;
|
|
20
|
+
callMethod: string;
|
|
21
|
+
declareGlobalVariable: string;
|
|
22
|
+
previousStep: string;
|
|
23
|
+
nextStep: string;
|
|
24
|
+
addStep: string;
|
|
25
|
+
addStepHint: string;
|
|
26
|
+
deleteStep: string;
|
|
27
|
+
stepLabel: string;
|
|
28
|
+
stepLabelPlaceholder: string;
|
|
29
|
+
exerciseStep: string;
|
|
30
|
+
exerciseStepHint: string;
|
|
31
|
+
yourTurn: string;
|
|
32
|
+
checkAnswer: string;
|
|
33
|
+
showSolution: string;
|
|
34
|
+
exerciseCorrect: string;
|
|
35
|
+
exerciseWrong: (wrong: string[]) => string;
|
|
36
|
+
exerciseExtra: (extra: string[]) => string;
|
|
37
|
+
declareLocalVariable: string;
|
|
38
|
+
returnMethod: string;
|
|
39
|
+
returnOnlyTopOfStack: string;
|
|
40
|
+
ok: string;
|
|
41
|
+
cancel: string;
|
|
42
|
+
createMethodCall: string;
|
|
43
|
+
methodName: string;
|
|
44
|
+
methodNamePlaceholder: string;
|
|
45
|
+
createGlobalVariable: string;
|
|
46
|
+
variableName: string;
|
|
47
|
+
variableNamePlaceholder: string;
|
|
48
|
+
createObject: (type: string) => string;
|
|
49
|
+
objectName: string;
|
|
50
|
+
createArray: string;
|
|
51
|
+
arrayLength: string;
|
|
52
|
+
arrayElementType: string;
|
|
53
|
+
declareLocalVariableTitle: string;
|
|
54
|
+
configuration: string;
|
|
55
|
+
classes: string;
|
|
56
|
+
addClass: string;
|
|
57
|
+
className: string;
|
|
58
|
+
classNamePlaceholder: string;
|
|
59
|
+
attributes: string;
|
|
60
|
+
addAttribute: string;
|
|
61
|
+
attributeName: string;
|
|
62
|
+
dataType: string;
|
|
63
|
+
classSource: string;
|
|
64
|
+
classList: string;
|
|
65
|
+
classSourceHint: string;
|
|
66
|
+
classSourcePlaceholder: string;
|
|
67
|
+
options: string;
|
|
68
|
+
presets: string;
|
|
69
|
+
presetReferences: string;
|
|
70
|
+
presetStack: string;
|
|
71
|
+
presetEverything: string;
|
|
72
|
+
backToDiagram: string;
|
|
73
|
+
saved: string;
|
|
74
|
+
unsavedChangesLeave: string;
|
|
75
|
+
confirmDeleteClass: (name: string) => string;
|
|
76
|
+
applyClassesTitle: string;
|
|
77
|
+
applyClassesIntro: string;
|
|
78
|
+
applyClassesDropped: (klass: string, field: string, count: number) => string;
|
|
79
|
+
applyClassesOrphaned: (klass: string, count: number) => string;
|
|
80
|
+
applyClassesMore: (count: number) => string;
|
|
81
|
+
applyClassesConfirm: string;
|
|
82
|
+
/**
|
|
83
|
+
* React Flow's own accessible descriptions, which it ships in English only.
|
|
84
|
+
* A German playground was reading them out in English next to its own
|
|
85
|
+
* translated labels; they are handed back through `ariaLabelConfig`.
|
|
86
|
+
*/
|
|
87
|
+
a11y: {
|
|
88
|
+
node: string;
|
|
89
|
+
nodeKeyboard: string;
|
|
90
|
+
nodeMoved: (direction: string, x: number, y: number) => string;
|
|
91
|
+
edge: string;
|
|
92
|
+
controls: string;
|
|
93
|
+
zoomIn: string;
|
|
94
|
+
zoomOut: string;
|
|
95
|
+
fitView: string;
|
|
96
|
+
toggleInteractivity: string;
|
|
97
|
+
handle: string;
|
|
98
|
+
};
|
|
99
|
+
optionLabels: {
|
|
100
|
+
hideSidebar: string;
|
|
101
|
+
hideCallMethod: string;
|
|
102
|
+
hideDeclareGlobalVariable: string;
|
|
103
|
+
hideNewArray: string;
|
|
104
|
+
disableGarbageCollector: string;
|
|
105
|
+
createNewOnEdgeDrop: string;
|
|
106
|
+
inlineStrings: string;
|
|
107
|
+
hideSteps: string;
|
|
108
|
+
hideStepChanges: string;
|
|
109
|
+
gcPrediction: string;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
export declare const translations: Record<string, Translations>;
|
|
113
|
+
/**
|
|
114
|
+
* Detects the user's browser language and returns a supported language code.
|
|
115
|
+
* Falls back to 'en' if the browser language is not supported.
|
|
116
|
+
*/
|
|
117
|
+
export declare function detectBrowserLanguage(): string;
|
|
118
|
+
export declare function getLanguage(explicitLanguage?: string): string;
|
|
119
|
+
export declare function getTranslations(language?: string): Translations;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { BuiltInEdge } from "@xyflow/react";
|
|
2
|
+
import { ObjectNodeType } from "./ObjectNode";
|
|
3
|
+
import { VariableNode } from "./VariableNode";
|
|
4
|
+
import { MethodCallNodeType } from "./MethodCallNode";
|
|
5
|
+
import { ReferenceEdge } from "./ReferenceEdge";
|
|
6
|
+
export type CustomNodeType = ObjectNodeType | VariableNode | MethodCallNodeType;
|
|
7
|
+
export type CustomEdgeType = BuiltInEdge | ReferenceEdge;
|
|
8
|
+
export interface KeyBinding {
|
|
9
|
+
key: string;
|
|
10
|
+
ctrl?: boolean;
|
|
11
|
+
shift?: boolean;
|
|
12
|
+
alt?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface KeyBindings {
|
|
15
|
+
save: KeyBinding;
|
|
16
|
+
undo: KeyBinding;
|
|
17
|
+
redo: KeyBinding;
|
|
18
|
+
toggleConfig: KeyBinding;
|
|
19
|
+
zoomIn: KeyBinding;
|
|
20
|
+
zoomOut: KeyBinding;
|
|
21
|
+
resetZoom: KeyBinding;
|
|
22
|
+
fitView: KeyBinding;
|
|
23
|
+
}
|