wyreframe 0.1.0 → 0.1.1

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 (59) hide show
  1. package/LICENSE +692 -0
  2. package/README.md +65 -5
  3. package/package.json +8 -7
  4. package/src/index.ts +425 -0
  5. package/src/renderer/Renderer.gen.tsx +49 -0
  6. package/src/renderer/Renderer.mjs +41 -1
  7. package/src/renderer/Renderer.res +78 -0
  8. package/src/test/Expect.mjs +9 -0
  9. package/src/parser/Core/__tests__/Bounds_test.mjs +0 -326
  10. package/src/parser/Core/__tests__/Bounds_test.res +0 -412
  11. package/src/parser/Core/__tests__/Grid_test.mjs +0 -322
  12. package/src/parser/Core/__tests__/Grid_test.res +0 -319
  13. package/src/parser/Core/__tests__/Types_test.mjs +0 -614
  14. package/src/parser/Core/__tests__/Types_test.res +0 -650
  15. package/src/parser/Detector/__tests__/BoxTracer_test.mjs +0 -70
  16. package/src/parser/Detector/__tests__/BoxTracer_test.res +0 -92
  17. package/src/parser/Detector/__tests__/HierarchyBuilder_test.mjs +0 -489
  18. package/src/parser/Detector/__tests__/HierarchyBuilder_test.res +0 -849
  19. package/src/parser/Detector/__tests__/ShapeDetector_test.mjs +0 -377
  20. package/src/parser/Detector/__tests__/ShapeDetector_test.res +0 -563
  21. package/src/parser/Interactions/__tests__/InteractionMerger_test.mjs +0 -576
  22. package/src/parser/Interactions/__tests__/InteractionMerger_test.res +0 -646
  23. package/src/parser/Scanner/__tests__/Grid_manual.mjs +0 -214
  24. package/src/parser/Scanner/__tests__/Grid_manual.res +0 -141
  25. package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.mjs +0 -189
  26. package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.res +0 -257
  27. package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.mjs +0 -202
  28. package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.res +0 -250
  29. package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.mjs +0 -293
  30. package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.res +0 -134
  31. package/src/parser/Semantic/Elements/__tests__/InputParser_test.mjs +0 -253
  32. package/src/parser/Semantic/Elements/__tests__/InputParser_test.res +0 -304
  33. package/src/parser/Semantic/Elements/__tests__/LinkParser_test.mjs +0 -289
  34. package/src/parser/Semantic/Elements/__tests__/LinkParser_test.res +0 -402
  35. package/src/parser/Semantic/Elements/__tests__/TextParser_test.mjs +0 -149
  36. package/src/parser/Semantic/Elements/__tests__/TextParser_test.res +0 -167
  37. package/src/parser/Semantic/__tests__/ASTBuilder_test.mjs +0 -187
  38. package/src/parser/Semantic/__tests__/ASTBuilder_test.res +0 -192
  39. package/src/parser/Semantic/__tests__/ParserRegistry_test.mjs +0 -154
  40. package/src/parser/Semantic/__tests__/ParserRegistry_test.res +0 -191
  41. package/src/parser/Semantic/__tests__/SemanticParser_integration_test.mjs +0 -768
  42. package/src/parser/Semantic/__tests__/SemanticParser_integration_test.res +0 -1069
  43. package/src/parser/Semantic/__tests__/SemanticParser_manual.mjs +0 -1329
  44. package/src/parser/Semantic/__tests__/SemanticParser_manual.res +0 -544
  45. package/src/parser/__tests__/GridScanner_integration.test.mjs +0 -632
  46. package/src/parser/__tests__/GridScanner_integration.test.res +0 -816
  47. package/src/parser/__tests__/Performance.test.mjs +0 -244
  48. package/src/parser/__tests__/Performance.test.res +0 -371
  49. package/src/parser/__tests__/PerformanceFixtures.mjs +0 -200
  50. package/src/parser/__tests__/PerformanceFixtures.res +0 -284
  51. package/src/parser/__tests__/WyreframeParser_integration.test.mjs +0 -770
  52. package/src/parser/__tests__/WyreframeParser_integration.test.res +0 -1008
  53. package/src/parser/__tests__/fixtures/alignment-test.txt +0 -9
  54. package/src/parser/__tests__/fixtures/all-elements.txt +0 -16
  55. package/src/parser/__tests__/fixtures/login-scene.txt +0 -17
  56. package/src/parser/__tests__/fixtures/multi-scene.txt +0 -25
  57. package/src/parser/__tests__/fixtures/nested-boxes.txt +0 -15
  58. package/src/parser/__tests__/fixtures/simple-box.txt +0 -5
  59. package/src/parser/__tests__/fixtures/with-dividers.txt +0 -14
@@ -556,3 +556,81 @@ let toHTMLString = (_ast: ast, _options: option<renderOptions>): string => {
556
556
  "<!-- Static HTML generation not yet implemented -->"
557
557
  }
558
558
 
559
+ // ============================================================================
560
+ // createUI - Convenience Functions
561
+ // ============================================================================
562
+
563
+ /**
564
+ * Result type for createUI function.
565
+ * Contains either success with rendered elements or error with parse errors.
566
+ */
567
+ type createUISuccessResult = {
568
+ root: DomBindings.element,
569
+ sceneManager: sceneManager,
570
+ ast: Types.ast,
571
+ }
572
+
573
+ type createUIResult = result<createUISuccessResult, array<ErrorTypes.t>>
574
+
575
+ /**
576
+ * Parse and render wireframe in one step.
577
+ * Combines Parser.parse() and Renderer.render() for convenience.
578
+ *
579
+ * @param text Text containing ASCII wireframe and/or interaction DSL
580
+ * @param options Optional render options
581
+ * @returns Result containing root element, scene manager, and AST, or errors
582
+ *
583
+ * @example
584
+ * ```rescript
585
+ * let result = Renderer.createUI(wireframeText, None)
586
+ * switch result {
587
+ * | Ok({root, sceneManager, ast}) => {
588
+ * // Append root to DOM
589
+ * sceneManager.goto("login")
590
+ * }
591
+ * | Error(errors) => Console.error(errors)
592
+ * }
593
+ * ```
594
+ */
595
+ @genType
596
+ let createUI = (text: string, options: option<renderOptions>): createUIResult => {
597
+ switch Parser.parse(text) {
598
+ | Ok(ast) => {
599
+ let {root, sceneManager} = render(ast, options)
600
+ Ok({root, sceneManager, ast})
601
+ }
602
+ | Error(errors) => Error(errors)
603
+ }
604
+ }
605
+
606
+ /**
607
+ * Parse and render wireframe, throwing on error.
608
+ * Use this for simpler code when parsing is expected to succeed.
609
+ *
610
+ * @param text Text containing ASCII wireframe and/or interaction DSL
611
+ * @param options Optional render options
612
+ * @returns Rendered root element, scene manager, and AST
613
+ * @raises Js.Exn.Error if parsing fails
614
+ *
615
+ * @example
616
+ * ```rescript
617
+ * let {root, sceneManager, ast} = Renderer.createUIOrThrow(wireframeText, None)
618
+ * // Use root directly - errors will throw exception
619
+ * ```
620
+ */
621
+ @genType
622
+ let createUIOrThrow = (text: string, options: option<renderOptions>): createUISuccessResult => {
623
+ switch Parser.parse(text) {
624
+ | Ok(ast) => {
625
+ let {root, sceneManager} = render(ast, options)
626
+ {root, sceneManager, ast}
627
+ }
628
+ | Error(errors) => {
629
+ let messages = errors
630
+ ->Array.map(err => ErrorMessages.getTitle(err.code))
631
+ ->Array.join("\n")
632
+ JsError.throwWithMessage("Parse failed:\n" ++ messages)
633
+ }
634
+ }
635
+ }
636
+
@@ -0,0 +1,9 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ let pass;
5
+
6
+ export {
7
+ pass,
8
+ }
9
+ /* No side effect */
@@ -1,326 +0,0 @@
1
- // Generated by ReScript, PLEASE EDIT WITH CARE
2
-
3
- import * as Bounds from "../Bounds.mjs";
4
- import * as Vitest from "rescript-vitest/src/Vitest.mjs";
5
- import * as Core__Option from "@rescript/core/src/Core__Option.mjs";
6
-
7
- Vitest.describe("Bounds.make", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
8
- Vitest.test("creates valid bounds when top < bottom and left < right", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
9
- let result = Bounds.make(0, 0, 10, 10);
10
- if (result !== undefined) {
11
- t.expect(result.top).toBe(0);
12
- t.expect(result.left).toBe(0);
13
- t.expect(result.bottom).toBe(10);
14
- return t.expect(result.right).toBe(10);
15
- } else {
16
- return t.expect(true).toBe(false);
17
- }
18
- });
19
- Vitest.test("returns None when top >= bottom", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
20
- let result = Bounds.make(10, 0, 10, 10);
21
- t.expect(result).toBe(undefined);
22
- });
23
- Vitest.test("returns None when top > bottom", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
24
- let result = Bounds.make(15, 0, 10, 10);
25
- t.expect(result).toBe(undefined);
26
- });
27
- Vitest.test("returns None when left >= right", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
28
- let result = Bounds.make(0, 10, 10, 10);
29
- t.expect(result).toBe(undefined);
30
- });
31
- Vitest.test("returns None when left > right", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
32
- let result = Bounds.make(0, 15, 10, 10);
33
- t.expect(result).toBe(undefined);
34
- });
35
- Vitest.test("handles negative coordinates", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
36
- let result = Bounds.make(-10, -10, 0, 0);
37
- if (result !== undefined) {
38
- t.expect(result.top).toBe(-10);
39
- t.expect(result.left).toBe(-10);
40
- t.expect(result.bottom).toBe(0);
41
- return t.expect(result.right).toBe(0);
42
- } else {
43
- return t.expect(true).toBe(false);
44
- }
45
- });
46
- Vitest.test("creates minimal 1x1 bounds", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
47
- let result = Bounds.make(0, 0, 1, 1);
48
- if (result !== undefined) {
49
- t.expect(Bounds.width(result)).toBe(1);
50
- return t.expect(Bounds.height(result)).toBe(1);
51
- } else {
52
- return t.expect(true).toBe(false);
53
- }
54
- });
55
- });
56
-
57
- Vitest.describe("Bounds.width", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
58
- Vitest.test("calculates width correctly", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
59
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 10, 20), undefined);
60
- t.expect(Bounds.width(bounds)).toBe(20);
61
- });
62
- Vitest.test("calculates width for single column", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
63
- let bounds = Core__Option.getExn(Bounds.make(0, 5, 10, 6), undefined);
64
- t.expect(Bounds.width(bounds)).toBe(1);
65
- });
66
- Vitest.test("handles negative coordinates", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
67
- let bounds = Core__Option.getExn(Bounds.make(0, -5, 10, 5), undefined);
68
- t.expect(Bounds.width(bounds)).toBe(10);
69
- });
70
- Vitest.test("calculates width for large bounds", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
71
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 10, 1000), undefined);
72
- t.expect(Bounds.width(bounds)).toBe(1000);
73
- });
74
- });
75
-
76
- Vitest.describe("Bounds.height", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
77
- Vitest.test("calculates height correctly", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
78
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 15, 10), undefined);
79
- t.expect(Bounds.height(bounds)).toBe(15);
80
- });
81
- Vitest.test("calculates height for single row", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
82
- let bounds = Core__Option.getExn(Bounds.make(5, 0, 6, 10), undefined);
83
- t.expect(Bounds.height(bounds)).toBe(1);
84
- });
85
- Vitest.test("handles negative coordinates", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
86
- let bounds = Core__Option.getExn(Bounds.make(-5, 0, 5, 10), undefined);
87
- t.expect(Bounds.height(bounds)).toBe(10);
88
- });
89
- Vitest.test("calculates height for tall bounds", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
90
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 1000, 10), undefined);
91
- t.expect(Bounds.height(bounds)).toBe(1000);
92
- });
93
- });
94
-
95
- Vitest.describe("Bounds.area", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
96
- Vitest.test("calculates area correctly", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
97
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 10, 20), undefined);
98
- t.expect(Bounds.area(bounds)).toBe(200);
99
- });
100
- Vitest.test("calculates area for 1x1 box", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
101
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 1, 1), undefined);
102
- t.expect(Bounds.area(bounds)).toBe(1);
103
- });
104
- Vitest.test("calculates area for narrow box", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
105
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 100, 1), undefined);
106
- t.expect(Bounds.area(bounds)).toBe(100);
107
- });
108
- Vitest.test("calculates area for wide box", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
109
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 1, 100), undefined);
110
- t.expect(Bounds.area(bounds)).toBe(100);
111
- });
112
- Vitest.test("calculates area with negative coordinates", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
113
- let bounds = Core__Option.getExn(Bounds.make(-10, -20, 10, 20), undefined);
114
- t.expect(Bounds.area(bounds)).toBe(800);
115
- });
116
- Vitest.test("calculates area for very large bounds", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
117
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 1000, 1000), undefined);
118
- t.expect(Bounds.area(bounds)).toBe(1000000);
119
- });
120
- });
121
-
122
- Vitest.describe("Bounds.contains", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
123
- Vitest.test("returns true when outer completely contains inner", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
124
- let outer = Core__Option.getExn(Bounds.make(0, 0, 20, 20), undefined);
125
- let inner = Core__Option.getExn(Bounds.make(5, 5, 15, 15), undefined);
126
- t.expect(Bounds.contains(outer, inner)).toBe(true);
127
- });
128
- Vitest.test("returns false when boxes are equal", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
129
- let a = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
130
- let b = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
131
- t.expect(Bounds.contains(a, b)).toBe(false);
132
- });
133
- Vitest.test("returns false when inner top edge touches outer top edge", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
134
- let outer = Core__Option.getExn(Bounds.make(0, 0, 20, 20), undefined);
135
- let inner = Core__Option.getExn(Bounds.make(0, 5, 15, 15), undefined);
136
- t.expect(Bounds.contains(outer, inner)).toBe(false);
137
- });
138
- Vitest.test("returns false when inner left edge touches outer left edge", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
139
- let outer = Core__Option.getExn(Bounds.make(0, 0, 20, 20), undefined);
140
- let inner = Core__Option.getExn(Bounds.make(5, 0, 15, 15), undefined);
141
- t.expect(Bounds.contains(outer, inner)).toBe(false);
142
- });
143
- Vitest.test("returns false when inner bottom edge touches outer bottom edge", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
144
- let outer = Core__Option.getExn(Bounds.make(0, 0, 20, 20), undefined);
145
- let inner = Core__Option.getExn(Bounds.make(5, 5, 20, 15), undefined);
146
- t.expect(Bounds.contains(outer, inner)).toBe(false);
147
- });
148
- Vitest.test("returns false when inner right edge touches outer right edge", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
149
- let outer = Core__Option.getExn(Bounds.make(0, 0, 20, 20), undefined);
150
- let inner = Core__Option.getExn(Bounds.make(5, 5, 15, 20), undefined);
151
- t.expect(Bounds.contains(outer, inner)).toBe(false);
152
- });
153
- Vitest.test("returns false when boxes are disjoint", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
154
- let a = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
155
- let b = Core__Option.getExn(Bounds.make(20, 20, 30, 30), undefined);
156
- t.expect(Bounds.contains(a, b)).toBe(false);
157
- });
158
- Vitest.test("returns false when inner is larger than outer", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
159
- let outer = Core__Option.getExn(Bounds.make(5, 5, 15, 15), undefined);
160
- let inner = Core__Option.getExn(Bounds.make(0, 0, 20, 20), undefined);
161
- t.expect(Bounds.contains(outer, inner)).toBe(false);
162
- });
163
- Vitest.test("returns false when boxes partially overlap", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
164
- let a = Core__Option.getExn(Bounds.make(0, 0, 15, 15), undefined);
165
- let b = Core__Option.getExn(Bounds.make(10, 10, 20, 20), undefined);
166
- t.expect(Bounds.contains(a, b)).toBe(false);
167
- });
168
- Vitest.test("handles negative coordinates correctly", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
169
- let outer = Core__Option.getExn(Bounds.make(-20, -20, 20, 20), undefined);
170
- let inner = Core__Option.getExn(Bounds.make(-5, -5, 5, 5), undefined);
171
- t.expect(Bounds.contains(outer, inner)).toBe(true);
172
- });
173
- Vitest.test("returns true when inner is minimal 1-pixel margin inside outer", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
174
- let outer = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
175
- let inner = Core__Option.getExn(Bounds.make(1, 1, 9, 9), undefined);
176
- t.expect(Bounds.contains(outer, inner)).toBe(true);
177
- });
178
- });
179
-
180
- Vitest.describe("Bounds.overlaps", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
181
- Vitest.test("returns true when boxes partially overlap", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
182
- let a = Core__Option.getExn(Bounds.make(0, 0, 15, 15), undefined);
183
- let b = Core__Option.getExn(Bounds.make(10, 10, 20, 20), undefined);
184
- t.expect(Bounds.overlaps(a, b)).toBe(true);
185
- });
186
- Vitest.test("returns true when one box completely contains another", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
187
- let outer = Core__Option.getExn(Bounds.make(0, 0, 20, 20), undefined);
188
- let inner = Core__Option.getExn(Bounds.make(5, 5, 15, 15), undefined);
189
- t.expect(Bounds.overlaps(outer, inner)).toBe(true);
190
- t.expect(Bounds.overlaps(inner, outer)).toBe(true);
191
- });
192
- Vitest.test("returns true when boxes are equal", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
193
- let a = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
194
- let b = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
195
- t.expect(Bounds.overlaps(a, b)).toBe(true);
196
- });
197
- Vitest.test("returns false when boxes are disjoint horizontally", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
198
- let a = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
199
- let b = Core__Option.getExn(Bounds.make(0, 20, 10, 30), undefined);
200
- t.expect(Bounds.overlaps(a, b)).toBe(false);
201
- });
202
- Vitest.test("returns false when boxes are disjoint vertically", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
203
- let a = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
204
- let b = Core__Option.getExn(Bounds.make(20, 0, 30, 10), undefined);
205
- t.expect(Bounds.overlaps(a, b)).toBe(false);
206
- });
207
- Vitest.test("returns false when boxes touch at edges horizontally", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
208
- let a = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
209
- let b = Core__Option.getExn(Bounds.make(0, 10, 10, 20), undefined);
210
- t.expect(Bounds.overlaps(a, b)).toBe(false);
211
- });
212
- Vitest.test("returns false when boxes touch at edges vertically", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
213
- let a = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
214
- let b = Core__Option.getExn(Bounds.make(10, 0, 20, 10), undefined);
215
- t.expect(Bounds.overlaps(a, b)).toBe(false);
216
- });
217
- Vitest.test("returns false when boxes are completely separated", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
218
- let a = Core__Option.getExn(Bounds.make(0, 0, 5, 5), undefined);
219
- let b = Core__Option.getExn(Bounds.make(10, 10, 15, 15), undefined);
220
- t.expect(Bounds.overlaps(a, b)).toBe(false);
221
- });
222
- Vitest.test("returns true when boxes overlap at corner", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
223
- let a = Core__Option.getExn(Bounds.make(0, 0, 11, 11), undefined);
224
- let b = Core__Option.getExn(Bounds.make(10, 10, 20, 20), undefined);
225
- t.expect(Bounds.overlaps(a, b)).toBe(true);
226
- });
227
- Vitest.test("returns true for L-shaped overlap", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
228
- let a = Core__Option.getExn(Bounds.make(0, 0, 15, 10), undefined);
229
- let b = Core__Option.getExn(Bounds.make(5, 5, 10, 20), undefined);
230
- t.expect(Bounds.overlaps(a, b)).toBe(true);
231
- });
232
- Vitest.test("returns true for T-shaped overlap", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
233
- let a = Core__Option.getExn(Bounds.make(0, 5, 10, 15), undefined);
234
- let b = Core__Option.getExn(Bounds.make(5, 0, 15, 20), undefined);
235
- t.expect(Bounds.overlaps(a, b)).toBe(true);
236
- });
237
- Vitest.test("handles negative coordinates correctly", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
238
- let a = Core__Option.getExn(Bounds.make(-10, -10, 0, 0), undefined);
239
- let b = Core__Option.getExn(Bounds.make(-5, -5, 5, 5), undefined);
240
- t.expect(Bounds.overlaps(a, b)).toBe(true);
241
- });
242
- Vitest.test("returns false for disjoint bounds with negative coordinates", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
243
- let a = Core__Option.getExn(Bounds.make(-20, -20, -10, -10), undefined);
244
- let b = Core__Option.getExn(Bounds.make(10, 10, 20, 20), undefined);
245
- t.expect(Bounds.overlaps(a, b)).toBe(false);
246
- });
247
- Vitest.test("is symmetric (order doesn't matter)", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
248
- let a = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
249
- let b = Core__Option.getExn(Bounds.make(5, 5, 15, 15), undefined);
250
- t.expect(Bounds.overlaps(a, b)).toBe(Bounds.overlaps(b, a));
251
- });
252
- });
253
-
254
- Vitest.describe("Bounds.toString", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
255
- Vitest.test("formats bounds as string correctly", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
256
- let bounds = Core__Option.getExn(Bounds.make(1, 2, 10, 20), undefined);
257
- let str = Bounds.toString(bounds);
258
- t.expect(str).toBe("Bounds{top: 1, left: 2, bottom: 10, right: 20}");
259
- });
260
- Vitest.test("handles negative coordinates in string", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
261
- let bounds = Core__Option.getExn(Bounds.make(-5, -10, 5, 10), undefined);
262
- let str = Bounds.toString(bounds);
263
- t.expect(str).toBe("Bounds{top: -5, left: -10, bottom: 5, right: 10}");
264
- });
265
- });
266
-
267
- Vitest.describe("Bounds.equals", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
268
- Vitest.test("returns true for equal bounds", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
269
- let a = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
270
- let b = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
271
- t.expect(Bounds.equals(a, b)).toBe(true);
272
- });
273
- Vitest.test("returns false for different bounds", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
274
- let a = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
275
- let b = Core__Option.getExn(Bounds.make(0, 0, 10, 11), undefined);
276
- t.expect(Bounds.equals(a, b)).toBe(false);
277
- });
278
- Vitest.test("returns false when only one field differs", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
279
- let base = Core__Option.getExn(Bounds.make(0, 0, 10, 10), undefined);
280
- let diffTop = Core__Option.getExn(Bounds.make(1, 0, 10, 10), undefined);
281
- t.expect(Bounds.equals(base, diffTop)).toBe(false);
282
- let diffLeft = Core__Option.getExn(Bounds.make(0, 1, 10, 10), undefined);
283
- t.expect(Bounds.equals(base, diffLeft)).toBe(false);
284
- let diffBottom = Core__Option.getExn(Bounds.make(0, 0, 11, 10), undefined);
285
- t.expect(Bounds.equals(base, diffBottom)).toBe(false);
286
- let diffRight = Core__Option.getExn(Bounds.make(0, 0, 10, 11), undefined);
287
- t.expect(Bounds.equals(base, diffRight)).toBe(false);
288
- });
289
- });
290
-
291
- Vitest.describe("Bounds edge cases", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
292
- Vitest.test("handles zero-width bounds validation", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
293
- let result = Bounds.make(0, 5, 10, 5);
294
- t.expect(result).toBe(undefined);
295
- });
296
- Vitest.test("handles zero-height bounds validation", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
297
- let result = Bounds.make(5, 0, 5, 10);
298
- t.expect(result).toBe(undefined);
299
- });
300
- Vitest.test("handles inverted bounds", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
301
- let result = Bounds.make(10, 0, 5, 10);
302
- t.expect(result).toBe(undefined);
303
- });
304
- Vitest.test("handles very large coordinate values", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
305
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 1000000, 1000000), undefined);
306
- t.expect(Bounds.area(bounds)).toBe(-727379968);
307
- });
308
- Vitest.test("handles single pixel bounds", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
309
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 1, 1), undefined);
310
- t.expect(Bounds.width(bounds)).toBe(1);
311
- t.expect(Bounds.height(bounds)).toBe(1);
312
- t.expect(Bounds.area(bounds)).toBe(1);
313
- });
314
- Vitest.test("handles thin horizontal line", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
315
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 1, 100), undefined);
316
- t.expect(Bounds.height(bounds)).toBe(1);
317
- t.expect(Bounds.area(bounds)).toBe(100);
318
- });
319
- Vitest.test("handles thin vertical line", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
320
- let bounds = Core__Option.getExn(Bounds.make(0, 0, 100, 1), undefined);
321
- t.expect(Bounds.width(bounds)).toBe(1);
322
- t.expect(Bounds.area(bounds)).toBe(100);
323
- });
324
- });
325
-
326
- /* Not a pure module */