wyreframe 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.
- package/README.md +123 -0
- package/dist/index.d.ts +267 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +195 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
- package/src/parser/Core/Bounds.mjs +61 -0
- package/src/parser/Core/Bounds.res +65 -0
- package/src/parser/Core/Grid.mjs +268 -0
- package/src/parser/Core/Grid.res +265 -0
- package/src/parser/Core/Position.mjs +83 -0
- package/src/parser/Core/Position.res +54 -0
- package/src/parser/Core/Types.mjs +435 -0
- package/src/parser/Core/Types.res +331 -0
- package/src/parser/Core/__tests__/Bounds_test.mjs +326 -0
- package/src/parser/Core/__tests__/Bounds_test.res +412 -0
- package/src/parser/Core/__tests__/Grid_test.mjs +322 -0
- package/src/parser/Core/__tests__/Grid_test.res +319 -0
- package/src/parser/Core/__tests__/Types_test.mjs +614 -0
- package/src/parser/Core/__tests__/Types_test.res +650 -0
- package/src/parser/Detector/BoxTracer.mjs +302 -0
- package/src/parser/Detector/BoxTracer.res +374 -0
- package/src/parser/Detector/HierarchyBuilder.mjs +158 -0
- package/src/parser/Detector/HierarchyBuilder.res +315 -0
- package/src/parser/Detector/ShapeDetector.mjs +134 -0
- package/src/parser/Detector/ShapeDetector.res +236 -0
- package/src/parser/Detector/__tests__/BoxTracer_test.mjs +70 -0
- package/src/parser/Detector/__tests__/BoxTracer_test.res +92 -0
- package/src/parser/Detector/__tests__/HierarchyBuilder_test.mjs +489 -0
- package/src/parser/Detector/__tests__/HierarchyBuilder_test.res +849 -0
- package/src/parser/Detector/__tests__/ShapeDetector_test.mjs +377 -0
- package/src/parser/Detector/__tests__/ShapeDetector_test.res +563 -0
- package/src/parser/Errors/ErrorContext.mjs +106 -0
- package/src/parser/Errors/ErrorContext.res +191 -0
- package/src/parser/Errors/ErrorMessages.mjs +289 -0
- package/src/parser/Errors/ErrorMessages.res +303 -0
- package/src/parser/Errors/ErrorTypes.mjs +105 -0
- package/src/parser/Errors/ErrorTypes.res +169 -0
- package/src/parser/Interactions/InteractionMerger.mjs +266 -0
- package/src/parser/Interactions/InteractionMerger.res +450 -0
- package/src/parser/Interactions/InteractionParser.mjs +88 -0
- package/src/parser/Interactions/InteractionParser.res +127 -0
- package/src/parser/Interactions/SimpleInteractionParser.mjs +278 -0
- package/src/parser/Interactions/SimpleInteractionParser.res +262 -0
- package/src/parser/Interactions/__tests__/InteractionMerger_test.mjs +576 -0
- package/src/parser/Interactions/__tests__/InteractionMerger_test.res +646 -0
- package/src/parser/Parser.gen.tsx +96 -0
- package/src/parser/Parser.mjs +212 -0
- package/src/parser/Parser.res +481 -0
- package/src/parser/Scanner/__tests__/Grid_manual.mjs +214 -0
- package/src/parser/Scanner/__tests__/Grid_manual.res +141 -0
- package/src/parser/Semantic/ASTBuilder.mjs +197 -0
- package/src/parser/Semantic/ASTBuilder.res +288 -0
- package/src/parser/Semantic/AlignmentCalc.mjs +41 -0
- package/src/parser/Semantic/AlignmentCalc.res +104 -0
- package/src/parser/Semantic/Elements/ButtonParser.mjs +58 -0
- package/src/parser/Semantic/Elements/ButtonParser.res +131 -0
- package/src/parser/Semantic/Elements/CheckboxParser.mjs +58 -0
- package/src/parser/Semantic/Elements/CheckboxParser.res +79 -0
- package/src/parser/Semantic/Elements/CodeTextParser.mjs +50 -0
- package/src/parser/Semantic/Elements/CodeTextParser.res +111 -0
- package/src/parser/Semantic/Elements/ElementParser.mjs +15 -0
- package/src/parser/Semantic/Elements/ElementParser.res +83 -0
- package/src/parser/Semantic/Elements/EmphasisParser.mjs +46 -0
- package/src/parser/Semantic/Elements/EmphasisParser.res +67 -0
- package/src/parser/Semantic/Elements/InputParser.mjs +41 -0
- package/src/parser/Semantic/Elements/InputParser.res +97 -0
- package/src/parser/Semantic/Elements/LinkParser.mjs +60 -0
- package/src/parser/Semantic/Elements/LinkParser.res +156 -0
- package/src/parser/Semantic/Elements/TextParser.mjs +19 -0
- package/src/parser/Semantic/Elements/TextParser.res +42 -0
- package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.mjs +189 -0
- package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.res +257 -0
- package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.mjs +202 -0
- package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.res +250 -0
- package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.mjs +293 -0
- package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.res +134 -0
- package/src/parser/Semantic/Elements/__tests__/InputParser_test.mjs +253 -0
- package/src/parser/Semantic/Elements/__tests__/InputParser_test.res +304 -0
- package/src/parser/Semantic/Elements/__tests__/LinkParser_test.mjs +289 -0
- package/src/parser/Semantic/Elements/__tests__/LinkParser_test.res +402 -0
- package/src/parser/Semantic/Elements/__tests__/TextParser_test.mjs +149 -0
- package/src/parser/Semantic/Elements/__tests__/TextParser_test.res +167 -0
- package/src/parser/Semantic/ParserRegistry.mjs +82 -0
- package/src/parser/Semantic/ParserRegistry.res +145 -0
- package/src/parser/Semantic/SemanticParser.mjs +850 -0
- package/src/parser/Semantic/SemanticParser.res +1368 -0
- package/src/parser/Semantic/__tests__/ASTBuilder_test.mjs +187 -0
- package/src/parser/Semantic/__tests__/ASTBuilder_test.res +192 -0
- package/src/parser/Semantic/__tests__/ParserRegistry_test.mjs +154 -0
- package/src/parser/Semantic/__tests__/ParserRegistry_test.res +191 -0
- package/src/parser/Semantic/__tests__/SemanticParser_integration_test.mjs +768 -0
- package/src/parser/Semantic/__tests__/SemanticParser_integration_test.res +1069 -0
- package/src/parser/Semantic/__tests__/SemanticParser_manual.mjs +1329 -0
- package/src/parser/Semantic/__tests__/SemanticParser_manual.res +544 -0
- package/src/parser/TestMain.mjs +21 -0
- package/src/parser/TestMain.res +14 -0
- package/src/parser/TextExtractor.mjs +179 -0
- package/src/parser/TextExtractor.res +264 -0
- package/src/parser/__tests__/GridScanner_integration.test.mjs +632 -0
- package/src/parser/__tests__/GridScanner_integration.test.res +816 -0
- package/src/parser/__tests__/Performance.test.mjs +244 -0
- package/src/parser/__tests__/Performance.test.res +371 -0
- package/src/parser/__tests__/PerformanceFixtures.mjs +200 -0
- package/src/parser/__tests__/PerformanceFixtures.res +284 -0
- package/src/parser/__tests__/WyreframeParser_integration.test.mjs +770 -0
- package/src/parser/__tests__/WyreframeParser_integration.test.res +1008 -0
- package/src/parser/__tests__/fixtures/alignment-test.txt +9 -0
- package/src/parser/__tests__/fixtures/all-elements.txt +16 -0
- package/src/parser/__tests__/fixtures/login-scene.txt +17 -0
- package/src/parser/__tests__/fixtures/multi-scene.txt +25 -0
- package/src/parser/__tests__/fixtures/nested-boxes.txt +15 -0
- package/src/parser/__tests__/fixtures/simple-box.txt +5 -0
- package/src/parser/__tests__/fixtures/with-dividers.txt +14 -0
- package/src/renderer/Renderer.gen.tsx +32 -0
- package/src/renderer/Renderer.mjs +391 -0
- package/src/renderer/Renderer.res +558 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
+--Elements---------------+
|
|
2
|
+
| |
|
|
3
|
+
| * Emphasis Text |
|
|
4
|
+
| |
|
|
5
|
+
| [ Button ] |
|
|
6
|
+
| |
|
|
7
|
+
| #input-field |
|
|
8
|
+
| |
|
|
9
|
+
| "Link Text" |
|
|
10
|
+
| |
|
|
11
|
+
| [x] Checked Item |
|
|
12
|
+
| [ ] Unchecked Item |
|
|
13
|
+
| |
|
|
14
|
+
| Regular text |
|
|
15
|
+
| |
|
|
16
|
+
+-------------------------+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
@scene: login
|
|
2
|
+
@title: Login Page
|
|
3
|
+
|
|
4
|
+
+--Login------------------+
|
|
5
|
+
| |
|
|
6
|
+
| Welcome Back! |
|
|
7
|
+
| |
|
|
8
|
+
| Email: |
|
|
9
|
+
| #email |
|
|
10
|
+
| |
|
|
11
|
+
| Password: |
|
|
12
|
+
| #password |
|
|
13
|
+
| |
|
|
14
|
+
| [ Sign In ] |
|
|
15
|
+
| |
|
|
16
|
+
| "Forgot Password?" |
|
|
17
|
+
+-------------------------+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
@scene: home
|
|
2
|
+
@title: Home
|
|
3
|
+
|
|
4
|
+
+--Home-------------------+
|
|
5
|
+
| |
|
|
6
|
+
| Welcome! |
|
|
7
|
+
| |
|
|
8
|
+
| [ Get Started ] |
|
|
9
|
+
| |
|
|
10
|
+
+-------------------------+
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
@scene: profile
|
|
15
|
+
@title: Profile
|
|
16
|
+
|
|
17
|
+
+--Profile----------------+
|
|
18
|
+
| |
|
|
19
|
+
| User Profile |
|
|
20
|
+
| |
|
|
21
|
+
| #username |
|
|
22
|
+
| |
|
|
23
|
+
| [ Save ] |
|
|
24
|
+
| |
|
|
25
|
+
+-------------------------+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
+--Container--------------+
|
|
2
|
+
| |
|
|
3
|
+
| +--Header-----------+ |
|
|
4
|
+
| | | |
|
|
5
|
+
| | * Dashboard | |
|
|
6
|
+
| | | |
|
|
7
|
+
| +------------------+ |
|
|
8
|
+
| |
|
|
9
|
+
| +--Content----------+ |
|
|
10
|
+
| | | |
|
|
11
|
+
| | Main Content | |
|
|
12
|
+
| | | |
|
|
13
|
+
| +------------------+ |
|
|
14
|
+
| |
|
|
15
|
+
+-------------------------+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/* TypeScript file generated from Renderer.res by genType. */
|
|
2
|
+
|
|
3
|
+
/* eslint-disable */
|
|
4
|
+
/* tslint:disable */
|
|
5
|
+
|
|
6
|
+
import * as RendererJS from './Renderer.mjs';
|
|
7
|
+
|
|
8
|
+
import type {ast as Types_ast} from '../../src/parser/Core/Types.gen';
|
|
9
|
+
|
|
10
|
+
export abstract class DomBindings_element { protected opaque!: any }; /* simulate opaque types */
|
|
11
|
+
|
|
12
|
+
/** * Configuration for the rendering process. */
|
|
13
|
+
export type renderOptions = {
|
|
14
|
+
readonly theme: (undefined | string);
|
|
15
|
+
readonly interactive: boolean;
|
|
16
|
+
readonly injectStyles: boolean;
|
|
17
|
+
readonly containerClass: (undefined | string)
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/** * Scene management interface returned by render function. */
|
|
21
|
+
export type sceneManager = {
|
|
22
|
+
readonly goto: (_1:string) => void;
|
|
23
|
+
readonly getCurrentScene: () => (undefined | string);
|
|
24
|
+
readonly getSceneIds: () => string[]
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** * Render result containing the root element and scene manager. */
|
|
28
|
+
export type renderResult = { readonly root: DomBindings_element; readonly sceneManager: sceneManager };
|
|
29
|
+
|
|
30
|
+
export const render: (ast:Types_ast, options:(undefined | renderOptions)) => renderResult = RendererJS.render as any;
|
|
31
|
+
|
|
32
|
+
export const toHTMLString: (_ast:Types_ast, _options:(undefined | renderOptions)) => string = RendererJS.toHTMLString as any;
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Core__Option from "@rescript/core/src/Core__Option.mjs";
|
|
4
|
+
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
5
|
+
|
|
6
|
+
let DomBindings = {};
|
|
7
|
+
|
|
8
|
+
let defaultOptions = {
|
|
9
|
+
theme: undefined,
|
|
10
|
+
interactive: true,
|
|
11
|
+
injectStyles: true,
|
|
12
|
+
containerClass: undefined
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
let defaultStyles = `
|
|
16
|
+
.wf-app { font-family: monospace; position: relative; overflow: hidden; background: #fff; color: #333; font-size: 14px; margin: 0 auto; }
|
|
17
|
+
.wf-app.wf-device-desktop { width: 1440px; height: 900px; max-width: 100%; aspect-ratio: 16/10; }
|
|
18
|
+
.wf-app.wf-device-laptop { width: 1280px; height: 800px; max-width: 100%; aspect-ratio: 16/10; }
|
|
19
|
+
.wf-app.wf-device-tablet { width: 768px; height: 1024px; max-width: 100%; aspect-ratio: 3/4; }
|
|
20
|
+
.wf-app.wf-device-tablet-landscape { width: 1024px; height: 768px; max-width: 100%; aspect-ratio: 4/3; }
|
|
21
|
+
.wf-app.wf-device-mobile { width: 375px; height: 812px; max-width: 100%; aspect-ratio: 375/812; }
|
|
22
|
+
.wf-app.wf-device-mobile-landscape { width: 812px; height: 375px; max-width: 100%; aspect-ratio: 812/375; }
|
|
23
|
+
.wf-scene { position: absolute; top:0; left:0; width:100%; height:100%; padding:16px; box-sizing:border-box; opacity:0; pointer-events:none; transition: opacity 0.3s ease, transform 0.3s ease; overflow-y: auto; }
|
|
24
|
+
.wf-scene.active { opacity:1; pointer-events:auto; }
|
|
25
|
+
.wf-box { border:1px solid #333; padding:12px; margin:8px 0; background:#fff; }
|
|
26
|
+
.wf-box-named { position: relative; margin-top: 16px; }
|
|
27
|
+
.wf-box-named::before { content: attr(data-name); position: absolute; top: -10px; left: 8px; background: #fff; padding: 0 4px; font-size: 12px; color: #666; }
|
|
28
|
+
.wf-row { display:flex; gap:12px; align-items:center; margin:4px 0; }
|
|
29
|
+
.wf-column { flex:1; display:flex; flex-direction:column; gap:4px; }
|
|
30
|
+
.wf-button { display:block; width:fit-content; padding:8px 16px; background:#fff; color:#333; border:1px solid #333; font: inherit; cursor:pointer; margin:4px 0; }
|
|
31
|
+
.wf-button.secondary { background:#eee; }
|
|
32
|
+
.wf-button.ghost { background:transparent; border:1px dashed #999; color:#666; }
|
|
33
|
+
.wf-input { width:100%; padding:8px; border:1px solid #333; font: inherit; box-sizing:border-box; margin:4px 0; }
|
|
34
|
+
.wf-link { display:block; color:#333; text-decoration:underline; cursor:pointer; margin:4px 0; }
|
|
35
|
+
.wf-row .wf-button { display:inline-block; margin:0; }
|
|
36
|
+
.wf-row .wf-link { display:inline; margin:0 8px; }
|
|
37
|
+
.wf-text { margin:4px 0; line-height:1.4; }
|
|
38
|
+
.wf-text.emphasis { font-weight:bold; }
|
|
39
|
+
.wf-divider { border:none; border-top:1px solid #333; margin:12px 0; }
|
|
40
|
+
.wf-section { border:1px solid #333; margin:8px 0; }
|
|
41
|
+
.wf-section-header { background:#fff; padding:4px 8px; font-size:12px; color:#666; border-bottom:1px solid #333; }
|
|
42
|
+
.wf-section-content { padding:8px; }
|
|
43
|
+
.wf-checkbox { display:flex; align-items:center; gap:8px; margin:4px 0; cursor:pointer; }
|
|
44
|
+
.align-center { text-align:center; }
|
|
45
|
+
.align-right { text-align:right; }
|
|
46
|
+
.wf-row.align-center { justify-content:center; }
|
|
47
|
+
.wf-row.align-right { justify-content:flex-end; }
|
|
48
|
+
.wf-button.align-center, .wf-link.align-center { margin-left:auto; margin-right:auto; }
|
|
49
|
+
.wf-button.align-right, .wf-link.align-right { margin-left:auto; margin-right:0; }
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
function isNoiseText(content) {
|
|
53
|
+
let trimmed = content.trim();
|
|
54
|
+
if (trimmed === "") {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
let borderPattern = /^[+|=\-\s]+$/;
|
|
58
|
+
let hasPipeOrPlus = /[+|]/;
|
|
59
|
+
if (borderPattern.test(trimmed)) {
|
|
60
|
+
return true;
|
|
61
|
+
} else {
|
|
62
|
+
return hasPipeOrPlus.test(trimmed);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function isInputOnlyBox(elem) {
|
|
67
|
+
if (elem.TAG !== "Box") {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
if (elem.name !== undefined) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
let children = elem.children;
|
|
74
|
+
if (children.length > 0) {
|
|
75
|
+
return children.every(child => child.TAG === "Input");
|
|
76
|
+
} else {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function getInputsFromBox(elem) {
|
|
82
|
+
if (elem.TAG === "Box") {
|
|
83
|
+
if (elem.name !== undefined) {
|
|
84
|
+
return [];
|
|
85
|
+
} else {
|
|
86
|
+
return elem.children;
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function alignmentToClass(align) {
|
|
94
|
+
switch (align) {
|
|
95
|
+
case "Left" :
|
|
96
|
+
return;
|
|
97
|
+
case "Center" :
|
|
98
|
+
return "align-center";
|
|
99
|
+
case "Right" :
|
|
100
|
+
return "align-right";
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function applyAlignment(el, align) {
|
|
105
|
+
let cls = alignmentToClass(align);
|
|
106
|
+
if (cls !== undefined) {
|
|
107
|
+
el.classList.add(cls);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function deviceTypeToClass(device) {
|
|
113
|
+
if (typeof device === "object") {
|
|
114
|
+
return "wf-device-custom-" + device._0.toString() + "x" + device._1.toString();
|
|
115
|
+
}
|
|
116
|
+
switch (device) {
|
|
117
|
+
case "Desktop" :
|
|
118
|
+
return "wf-device-desktop";
|
|
119
|
+
case "Laptop" :
|
|
120
|
+
return "wf-device-laptop";
|
|
121
|
+
case "Tablet" :
|
|
122
|
+
return "wf-device-tablet";
|
|
123
|
+
case "TabletLandscape" :
|
|
124
|
+
return "wf-device-tablet-landscape";
|
|
125
|
+
case "Mobile" :
|
|
126
|
+
return "wf-device-mobile";
|
|
127
|
+
case "MobileLandscape" :
|
|
128
|
+
return "wf-device-mobile-landscape";
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function renderElement(_elem, onAction) {
|
|
133
|
+
while (true) {
|
|
134
|
+
let elem = _elem;
|
|
135
|
+
if (isInputOnlyBox(elem)) {
|
|
136
|
+
let inputs = getInputsFromBox(elem);
|
|
137
|
+
let input = inputs[0];
|
|
138
|
+
if (input === undefined) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
_elem = input;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
switch (elem.TAG) {
|
|
145
|
+
case "Box" :
|
|
146
|
+
let name = elem.name;
|
|
147
|
+
let div = document.createElement("div");
|
|
148
|
+
div.className = "wf-box";
|
|
149
|
+
if (name !== undefined) {
|
|
150
|
+
div.classList.add("wf-box-named");
|
|
151
|
+
div.dataset["name"] = name;
|
|
152
|
+
}
|
|
153
|
+
elem.children.forEach(child => {
|
|
154
|
+
let el = renderElement(child, onAction);
|
|
155
|
+
if (el !== undefined) {
|
|
156
|
+
div.appendChild(Primitive_option.valFromOption(el));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
return Primitive_option.some(div);
|
|
161
|
+
case "Button" :
|
|
162
|
+
let actions = elem.actions;
|
|
163
|
+
let btn = document.createElement("button");
|
|
164
|
+
btn.className = "wf-button";
|
|
165
|
+
btn.id = elem.id;
|
|
166
|
+
btn.textContent = elem.text;
|
|
167
|
+
applyAlignment(btn, elem.align);
|
|
168
|
+
if (actions.length > 0 && onAction !== undefined) {
|
|
169
|
+
btn.addEventListener("click", _event => {
|
|
170
|
+
let action = actions[0];
|
|
171
|
+
if (action !== undefined) {
|
|
172
|
+
return onAction(action);
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
return Primitive_option.some(btn);
|
|
177
|
+
case "Input" :
|
|
178
|
+
let placeholder = elem.placeholder;
|
|
179
|
+
let input$1 = document.createElement("input");
|
|
180
|
+
input$1.className = "wf-input";
|
|
181
|
+
input$1.id = elem.id;
|
|
182
|
+
if (placeholder !== undefined) {
|
|
183
|
+
input$1.placeholder = placeholder;
|
|
184
|
+
}
|
|
185
|
+
return Primitive_option.some(input$1);
|
|
186
|
+
case "Link" :
|
|
187
|
+
let actions$1 = elem.actions;
|
|
188
|
+
let link = document.createElement("a");
|
|
189
|
+
link.className = "wf-link";
|
|
190
|
+
link.id = elem.id;
|
|
191
|
+
link.href = "#";
|
|
192
|
+
link.textContent = elem.text;
|
|
193
|
+
applyAlignment(link, elem.align);
|
|
194
|
+
if (actions$1.length > 0 && onAction !== undefined) {
|
|
195
|
+
link.addEventListener("click", event => {
|
|
196
|
+
event.preventDefault();
|
|
197
|
+
let action = actions$1[0];
|
|
198
|
+
if (action !== undefined) {
|
|
199
|
+
return onAction(action);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
return Primitive_option.some(link);
|
|
204
|
+
case "Checkbox" :
|
|
205
|
+
let labelEl = document.createElement("label");
|
|
206
|
+
labelEl.className = "wf-checkbox";
|
|
207
|
+
let input$2 = document.createElement("input");
|
|
208
|
+
input$2.type = "checkbox";
|
|
209
|
+
input$2.checked = elem.checked;
|
|
210
|
+
let span = document.createElement("span");
|
|
211
|
+
span.textContent = elem.label;
|
|
212
|
+
labelEl.appendChild(input$2);
|
|
213
|
+
labelEl.appendChild(span);
|
|
214
|
+
return Primitive_option.some(labelEl);
|
|
215
|
+
case "Text" :
|
|
216
|
+
let content = elem.content;
|
|
217
|
+
if (isNoiseText(content)) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
let p = document.createElement("p");
|
|
221
|
+
p.className = "wf-text";
|
|
222
|
+
if (elem.emphasis) {
|
|
223
|
+
p.classList.add("emphasis");
|
|
224
|
+
}
|
|
225
|
+
applyAlignment(p, elem.align);
|
|
226
|
+
p.textContent = content;
|
|
227
|
+
return Primitive_option.some(p);
|
|
228
|
+
case "Divider" :
|
|
229
|
+
let hr = document.createElement("hr");
|
|
230
|
+
hr.className = "wf-divider";
|
|
231
|
+
return Primitive_option.some(hr);
|
|
232
|
+
case "Row" :
|
|
233
|
+
let row = document.createElement("div");
|
|
234
|
+
row.className = "wf-row";
|
|
235
|
+
applyAlignment(row, elem.align);
|
|
236
|
+
elem.children.forEach(child => {
|
|
237
|
+
let el = renderElement(child, onAction);
|
|
238
|
+
if (el !== undefined) {
|
|
239
|
+
row.appendChild(Primitive_option.valFromOption(el));
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
return Primitive_option.some(row);
|
|
244
|
+
case "Section" :
|
|
245
|
+
let section = document.createElement("div");
|
|
246
|
+
section.className = "wf-section";
|
|
247
|
+
let header = document.createElement("div");
|
|
248
|
+
header.className = "wf-section-header";
|
|
249
|
+
header.textContent = elem.name;
|
|
250
|
+
let contentEl = document.createElement("div");
|
|
251
|
+
contentEl.className = "wf-section-content";
|
|
252
|
+
elem.children.forEach(child => {
|
|
253
|
+
let el = renderElement(child, onAction);
|
|
254
|
+
if (el !== undefined) {
|
|
255
|
+
contentEl.appendChild(Primitive_option.valFromOption(el));
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
section.appendChild(header);
|
|
260
|
+
section.appendChild(contentEl);
|
|
261
|
+
return Primitive_option.some(section);
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function renderScene(scene, onAction) {
|
|
267
|
+
let sceneEl = document.createElement("div");
|
|
268
|
+
sceneEl.className = "wf-scene";
|
|
269
|
+
sceneEl.dataset["scene"] = scene.id;
|
|
270
|
+
scene.elements.forEach(elem => {
|
|
271
|
+
let el = renderElement(elem, onAction);
|
|
272
|
+
if (el !== undefined) {
|
|
273
|
+
sceneEl.appendChild(Primitive_option.valFromOption(el));
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
return sceneEl;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function createSceneManager(scenes) {
|
|
281
|
+
let currentScene = {
|
|
282
|
+
contents: undefined
|
|
283
|
+
};
|
|
284
|
+
let goto = id => {
|
|
285
|
+
let currentId = currentScene.contents;
|
|
286
|
+
if (currentId !== undefined) {
|
|
287
|
+
let el = scenes.get(currentId);
|
|
288
|
+
if (el !== undefined) {
|
|
289
|
+
Primitive_option.valFromOption(el).classList.remove("active");
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
let el$1 = scenes.get(id);
|
|
293
|
+
if (el$1 !== undefined) {
|
|
294
|
+
Primitive_option.valFromOption(el$1).classList.add("active");
|
|
295
|
+
currentScene.contents = id;
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
let getCurrentScene = () => currentScene.contents;
|
|
300
|
+
let getSceneIds = () => Array.from(scenes.keys());
|
|
301
|
+
return {
|
|
302
|
+
goto: goto,
|
|
303
|
+
getCurrentScene: getCurrentScene,
|
|
304
|
+
getSceneIds: getSceneIds
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function injectStyles() {
|
|
309
|
+
let match = document.getElementById("wf-styles");
|
|
310
|
+
if (!(match == null)) {
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
let style = document.createElement("style");
|
|
314
|
+
style.id = "wf-styles";
|
|
315
|
+
style.textContent = defaultStyles;
|
|
316
|
+
document.head.appendChild(style);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function render(ast, options) {
|
|
320
|
+
let opts = Core__Option.getOr(options, defaultOptions);
|
|
321
|
+
if (opts.injectStyles) {
|
|
322
|
+
injectStyles();
|
|
323
|
+
}
|
|
324
|
+
let app = document.createElement("div");
|
|
325
|
+
app.className = "wf-app";
|
|
326
|
+
let cls = opts.containerClass;
|
|
327
|
+
if (cls !== undefined) {
|
|
328
|
+
app.classList.add(cls);
|
|
329
|
+
}
|
|
330
|
+
let firstScene = ast.scenes[0];
|
|
331
|
+
if (firstScene !== undefined) {
|
|
332
|
+
let deviceClass = deviceTypeToClass(firstScene.device);
|
|
333
|
+
app.classList.add(deviceClass);
|
|
334
|
+
}
|
|
335
|
+
let gotoRef = {
|
|
336
|
+
contents: undefined
|
|
337
|
+
};
|
|
338
|
+
let handleAction = action => {
|
|
339
|
+
if (typeof action !== "object") {
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
if (action.TAG !== "Goto") {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
let goto = gotoRef.contents;
|
|
346
|
+
if (goto !== undefined) {
|
|
347
|
+
return goto(action.target);
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
let sceneMap = new Map();
|
|
351
|
+
ast.scenes.forEach(scene => {
|
|
352
|
+
let sceneEl = renderScene(scene, handleAction);
|
|
353
|
+
app.appendChild(sceneEl);
|
|
354
|
+
sceneMap.set(scene.id, sceneEl);
|
|
355
|
+
});
|
|
356
|
+
let manager = createSceneManager(sceneMap);
|
|
357
|
+
gotoRef.contents = manager.goto;
|
|
358
|
+
if (ast.scenes.length > 0) {
|
|
359
|
+
let firstScene$1 = ast.scenes[0];
|
|
360
|
+
if (firstScene$1 !== undefined) {
|
|
361
|
+
manager.goto(firstScene$1.id);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return {
|
|
365
|
+
root: app,
|
|
366
|
+
sceneManager: manager
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
function toHTMLString(_ast, _options) {
|
|
371
|
+
return "<!-- Static HTML generation not yet implemented -->";
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export {
|
|
375
|
+
DomBindings,
|
|
376
|
+
defaultOptions,
|
|
377
|
+
defaultStyles,
|
|
378
|
+
isNoiseText,
|
|
379
|
+
isInputOnlyBox,
|
|
380
|
+
getInputsFromBox,
|
|
381
|
+
alignmentToClass,
|
|
382
|
+
applyAlignment,
|
|
383
|
+
deviceTypeToClass,
|
|
384
|
+
renderElement,
|
|
385
|
+
renderScene,
|
|
386
|
+
createSceneManager,
|
|
387
|
+
injectStyles,
|
|
388
|
+
render,
|
|
389
|
+
toHTMLString,
|
|
390
|
+
}
|
|
391
|
+
/* No side effect */
|