zuzu-js 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/LICENSE +5 -0
  2. package/README.md +113 -0
  3. package/bin/zuzu +17 -0
  4. package/bin/zuzu-build-browser-bundle +57 -0
  5. package/bin/zuzu-generate-browser-stdlib +584 -0
  6. package/bin/zuzu-js +23 -0
  7. package/bin/zuzu-js-compile +152 -0
  8. package/bin/zuzu-js-electron +19 -0
  9. package/dist/zuzu-browser-worker.js +45574 -0
  10. package/dist/zuzu-browser.js +45362 -0
  11. package/lib/browser-bundle-entry.js +160 -0
  12. package/lib/browser-gui-renderer.js +387 -0
  13. package/lib/browser-runtime.js +167 -0
  14. package/lib/browser-worker-entry.js +413 -0
  15. package/lib/browser-ztests/runner.html +103 -0
  16. package/lib/browser-ztests/runner.js +369 -0
  17. package/lib/cli.js +350 -0
  18. package/lib/collections.js +367 -0
  19. package/lib/compiler.js +303 -0
  20. package/lib/electron/launcher.js +70 -0
  21. package/lib/electron/main.js +956 -0
  22. package/lib/electron/preload.js +80 -0
  23. package/lib/electron/renderer.html +122 -0
  24. package/lib/electron/renderer.js +24 -0
  25. package/lib/execution-metadata.js +18 -0
  26. package/lib/gui/dom-renderer.js +778 -0
  27. package/lib/host/browser-host.js +278 -0
  28. package/lib/host/capabilities.js +47 -0
  29. package/lib/host/electron-host.js +15 -0
  30. package/lib/host/node-host.js +74 -0
  31. package/lib/paths.js +150 -0
  32. package/lib/runtime-entrypoints.js +60 -0
  33. package/lib/runtime-helpers.js +886 -0
  34. package/lib/runtime.js +3529 -0
  35. package/lib/tap.js +37 -0
  36. package/lib/transpiler-new/ast.js +23 -0
  37. package/lib/transpiler-new/codegen.js +2455 -0
  38. package/lib/transpiler-new/errors.js +28 -0
  39. package/lib/transpiler-new/index.js +26 -0
  40. package/lib/transpiler-new/lexer.js +834 -0
  41. package/lib/transpiler-new/parser.js +2332 -0
  42. package/lib/transpiler-new/validate-bindings.js +326 -0
  43. package/lib/transpiler-utils.js +95 -0
  44. package/lib/transpiler.js +33 -0
  45. package/lib/zuzu.js +53 -0
  46. package/modules/javascript.js +193 -0
  47. package/modules/std/archive.js +603 -0
  48. package/modules/std/clib.js +338 -0
  49. package/modules/std/data/csv.js +1331 -0
  50. package/modules/std/data/json.js +531 -0
  51. package/modules/std/data/xml.js +441 -0
  52. package/modules/std/data/yaml.js +256 -0
  53. package/modules/std/db-worker.js +250 -0
  54. package/modules/std/db.js +664 -0
  55. package/modules/std/digest/_hash.js +443 -0
  56. package/modules/std/digest/md5.js +26 -0
  57. package/modules/std/digest/sha.js +72 -0
  58. package/modules/std/eval.js +10 -0
  59. package/modules/std/gui/objects.js +1519 -0
  60. package/modules/std/internals.js +571 -0
  61. package/modules/std/io/socks-worker.js +318 -0
  62. package/modules/std/io/socks.js +186 -0
  63. package/modules/std/io.js +475 -0
  64. package/modules/std/marshal/cbor.js +463 -0
  65. package/modules/std/marshal/graph.js +1624 -0
  66. package/modules/std/marshal.js +87 -0
  67. package/modules/std/math/bignum.js +91 -0
  68. package/modules/std/math.js +79 -0
  69. package/modules/std/net/dns.js +306 -0
  70. package/modules/std/net/http.js +820 -0
  71. package/modules/std/net/smtp.js +943 -0
  72. package/modules/std/net/url.js +109 -0
  73. package/modules/std/proc.js +602 -0
  74. package/modules/std/secure.js +3724 -0
  75. package/modules/std/string/base64.js +138 -0
  76. package/modules/std/string.js +299 -0
  77. package/modules/std/task.js +914 -0
  78. package/modules/std/time.js +579 -0
  79. package/modules/std/tui.js +188 -0
  80. package/modules/std/worker-thread.js +246 -0
  81. package/modules/std/worker.js +790 -0
  82. package/package.json +67 -0
  83. package/stdlib/modules/javascript.zzm +99 -0
  84. package/stdlib/modules/perl.zzm +105 -0
  85. package/stdlib/modules/std/archive.zzm +132 -0
  86. package/stdlib/modules/std/cache/lru.zzm +174 -0
  87. package/stdlib/modules/std/clib.zzm +112 -0
  88. package/stdlib/modules/std/colour.zzm +220 -0
  89. package/stdlib/modules/std/config.zzm +818 -0
  90. package/stdlib/modules/std/data/cbor.zzm +497 -0
  91. package/stdlib/modules/std/data/csv.zzm +285 -0
  92. package/stdlib/modules/std/data/ini.zzm +472 -0
  93. package/stdlib/modules/std/data/json/schema/core.zzm +573 -0
  94. package/stdlib/modules/std/data/json/schema/format.zzm +581 -0
  95. package/stdlib/modules/std/data/json/schema/model.zzm +255 -0
  96. package/stdlib/modules/std/data/json/schema/output.zzm +272 -0
  97. package/stdlib/modules/std/data/json/schema/relative_pointer.zzm +299 -0
  98. package/stdlib/modules/std/data/json/schema/validation.zzm +1503 -0
  99. package/stdlib/modules/std/data/json/schema.zzm +306 -0
  100. package/stdlib/modules/std/data/json.zzm +102 -0
  101. package/stdlib/modules/std/data/kdl/json.zzm +460 -0
  102. package/stdlib/modules/std/data/kdl/xml.zzm +387 -0
  103. package/stdlib/modules/std/data/kdl.zzm +1631 -0
  104. package/stdlib/modules/std/data/toml.zzm +756 -0
  105. package/stdlib/modules/std/data/toon.zzm +1017 -0
  106. package/stdlib/modules/std/data/xml/escape.zzm +156 -0
  107. package/stdlib/modules/std/data/xml.zzm +276 -0
  108. package/stdlib/modules/std/data/yaml.zzm +94 -0
  109. package/stdlib/modules/std/db.zzm +173 -0
  110. package/stdlib/modules/std/defer.zzm +75 -0
  111. package/stdlib/modules/std/digest/crc32.zzm +196 -0
  112. package/stdlib/modules/std/digest/md5.zzm +54 -0
  113. package/stdlib/modules/std/digest/sha.zzm +83 -0
  114. package/stdlib/modules/std/dump.zzm +317 -0
  115. package/stdlib/modules/std/eval.zzm +63 -0
  116. package/stdlib/modules/std/getopt.zzm +432 -0
  117. package/stdlib/modules/std/gui/dialogue.zzm +592 -0
  118. package/stdlib/modules/std/gui/objects.zzm +123 -0
  119. package/stdlib/modules/std/gui.zzm +1914 -0
  120. package/stdlib/modules/std/internals.zzm +139 -0
  121. package/stdlib/modules/std/io/socks.zzm +139 -0
  122. package/stdlib/modules/std/io.zzm +157 -0
  123. package/stdlib/modules/std/lingua/en.zzm +347 -0
  124. package/stdlib/modules/std/log.zzm +169 -0
  125. package/stdlib/modules/std/mail.zzm +2726 -0
  126. package/stdlib/modules/std/marshal.zzm +138 -0
  127. package/stdlib/modules/std/math/bignum.zzm +98 -0
  128. package/stdlib/modules/std/math/range.zzm +116 -0
  129. package/stdlib/modules/std/math/roman.zzm +156 -0
  130. package/stdlib/modules/std/math.zzm +141 -0
  131. package/stdlib/modules/std/net/dns.zzm +93 -0
  132. package/stdlib/modules/std/net/http.zzm +278 -0
  133. package/stdlib/modules/std/net/smtp.zzm +257 -0
  134. package/stdlib/modules/std/net/url.zzm +69 -0
  135. package/stdlib/modules/std/path/jsonpointer.zzm +526 -0
  136. package/stdlib/modules/std/path/kdl.zzm +1003 -0
  137. package/stdlib/modules/std/path/simple.zzm +520 -0
  138. package/stdlib/modules/std/path/z/context.zzm +147 -0
  139. package/stdlib/modules/std/path/z/evaluate.zzm +549 -0
  140. package/stdlib/modules/std/path/z/functions.zzm +874 -0
  141. package/stdlib/modules/std/path/z/lexer.zzm +490 -0
  142. package/stdlib/modules/std/path/z/node.zzm +1455 -0
  143. package/stdlib/modules/std/path/z/operators.zzm +445 -0
  144. package/stdlib/modules/std/path/z/parser.zzm +359 -0
  145. package/stdlib/modules/std/path/z.zzm +403 -0
  146. package/stdlib/modules/std/path/zz/functions.zzm +828 -0
  147. package/stdlib/modules/std/path/zz/operators.zzm +1036 -0
  148. package/stdlib/modules/std/path/zz.zzm +100 -0
  149. package/stdlib/modules/std/proc.zzm +155 -0
  150. package/stdlib/modules/std/result.zzm +149 -0
  151. package/stdlib/modules/std/secure.zzm +606 -0
  152. package/stdlib/modules/std/string/base64.zzm +66 -0
  153. package/stdlib/modules/std/string/quoted_printable.zzm +485 -0
  154. package/stdlib/modules/std/string.zzm +179 -0
  155. package/stdlib/modules/std/task.zzm +221 -0
  156. package/stdlib/modules/std/template/z.zzm +531 -0
  157. package/stdlib/modules/std/template/zz.zzm +62 -0
  158. package/stdlib/modules/std/time.zzm +188 -0
  159. package/stdlib/modules/std/tui.zzm +89 -0
  160. package/stdlib/modules/std/uuid.zzm +223 -0
  161. package/stdlib/modules/std/web/session.zzm +388 -0
  162. package/stdlib/modules/std/web/static.zzm +329 -0
  163. package/stdlib/modules/std/web.zzm +1942 -0
  164. package/stdlib/modules/std/worker.zzm +202 -0
  165. package/stdlib/modules/std/zuzuzoo.zzm +3960 -0
  166. package/stdlib/modules/test/more.zzm +528 -0
  167. package/stdlib/modules/test/parser.zzm +209 -0
@@ -0,0 +1,592 @@
1
+ =encoding utf8
2
+
3
+ =head1 NAME
4
+
5
+ std/gui/dialogue - Dialogue helpers.
6
+
7
+ =head1 SYNOPSIS
8
+
9
+ from std/gui/dialogue import *;
10
+
11
+ alert("Saved");
12
+ let ok := confirm("Continue?");
13
+ let name := prompt("Name:", value: "Ada");
14
+
15
+ =head1 IMPLEMENTATION SUPPORT
16
+
17
+ This module is supported by zuzu.pl, zuzu-rust, and zuzu-js on Electron
18
+ and Browser. It is not supported by zuzu-js on Node.
19
+
20
+ =head1 DESCRIPTION
21
+
22
+ This module provides convenience dialogue helpers layered on top of the
23
+ regular C<std/gui> widgets.
24
+
25
+ =head1 EXPORTS
26
+
27
+ =head2 Functions
28
+
29
+ =over
30
+
31
+ =item C<< alert(String message, ... PairList p) >>, C<< alert_window(String message, ... PairList p) >>
32
+
33
+ Parameters: C<message> is display text and C<p> contains options.
34
+ Returns: C<null> for C<alert> or C<Window> for C<alert_window>. Shows or
35
+ builds an alert dialogue.
36
+
37
+ =item C<< confirm(String message, ... PairList p) >>, C<< confirm_window(String message, ... PairList p) >>
38
+
39
+ Parameters: C<message> is display text and C<p> contains options.
40
+ Returns: C<Boolean> for C<confirm> or C<Window> for
41
+ C<confirm_window>. Shows or builds a confirmation dialogue.
42
+
43
+ =item C<< prompt(String message, ... PairList p) >>, C<< prompt_window(String message, ... PairList p) >>
44
+
45
+ Parameters: C<message> is prompt text and C<p> contains options such as
46
+ C<value>. Returns: C<String> or C<null> for C<prompt>, or C<Window> for
47
+ C<prompt_window>. Shows or builds a text prompt.
48
+
49
+ =item C<< file_open(... PairList p) >>, C<< file_save(... PairList p) >>
50
+
51
+ Parameters: C<p> contains dialogue options. Returns: path value or
52
+ C<null>. Opens a file selection dialogue.
53
+
54
+ =item C<< directory_open(... PairList p) >>, C<< directory_save(... PairList p) >>
55
+
56
+ Parameters: C<p> contains dialogue options. Returns: path value or
57
+ C<null>. Opens a directory selection dialogue.
58
+
59
+ =item C<< colour_picker(... PairList p) >>
60
+
61
+ Parameters: C<p> contains dialogue options. Returns: C<String> or
62
+ C<null>. Opens a colour picker and returns a normalized colour string.
63
+
64
+ =item C<< file_open_window(... PairList p) >>, C<< file_save_window(... PairList p) >>, C<< directory_open_window(... PairList p) >>, C<< directory_save_window(... PairList p) >>, C<< colour_picker_window(... PairList p) >>
65
+
66
+ Parameters: C<p> contains dialogue options. Returns: C<Window>. Builds
67
+ the corresponding GUI dialogue window.
68
+
69
+ =back
70
+
71
+ =head1 COPYRIGHT AND LICENCE
72
+
73
+ B<< std/gui/dialogue >> is copyright Toby Inkster.
74
+
75
+ It is free software; you may redistribute it and/or modify it under
76
+ the terms of either the Artistic License 1.0 or the GNU General Public
77
+ License version 2.
78
+
79
+ =cut
80
+
81
+ from std/gui try import
82
+ EM,
83
+ Window,
84
+ VBox,
85
+ HBox,
86
+ Label,
87
+ Text,
88
+ Input,
89
+ Button,
90
+ Widget,
91
+ native_file_open,
92
+ native_file_save,
93
+ native_directory_open,
94
+ native_directory_save,
95
+ native_colour_picker;
96
+ from std/gui/objects try import
97
+ meta as _objects_meta,
98
+ native_alert,
99
+ native_confirm,
100
+ native_prompt;
101
+ from std/colour import parse_colour;
102
+ from std/string import split;
103
+ from std/tui import
104
+ colour_text,
105
+ directory_completions,
106
+ filename_completions,
107
+ readline;
108
+
109
+ function _tui_string ( value ) {
110
+ return value ≡ null ? "" : "" _ value;
111
+ }
112
+
113
+ function _gui_backend () {
114
+ if ( _objects_meta ≢ null ) {
115
+ return _objects_meta{backend};
116
+ }
117
+ return "";
118
+ }
119
+
120
+ function _path_dialogue_unsupported () {
121
+ if ( __system__{deny_fs} ) {
122
+ die "GUI_DIALOGUE_FS_DENIED: file and directory dialogues require filesystem capability";
123
+ }
124
+ if ( _gui_backend() eq "browser-dom" ) {
125
+ die "GUI_DIALOGUE_UNSUPPORTED: file and directory dialogues are unsupported in JS/Browser";
126
+ }
127
+ }
128
+
129
+ function _tui_prompt ( String message, PairList p, String default_value ) {
130
+ return readline(
131
+ colour_text( message _ " ", "cyan" ),
132
+ default_value,
133
+ null,
134
+ );
135
+ }
136
+
137
+ function _tui_path_dialog (
138
+ String label,
139
+ String default_value,
140
+ completion,
141
+ PairList p
142
+ ) {
143
+ let answer := readline(
144
+ colour_text( p.get( "label", label ) _ " ", "cyan" ),
145
+ _tui_string( p.get( "value", default_value ) ),
146
+ completion,
147
+ );
148
+ if ( p.get( "multiple", false ) ) {
149
+ return split( answer, p.get( "separator", "\n" ) );
150
+ }
151
+ return answer;
152
+ }
153
+
154
+ function _parse_colour_or_null ( value ) {
155
+ return try {
156
+ parse_colour( _tui_string(value) );
157
+ }
158
+ catch {
159
+ null;
160
+ };
161
+ }
162
+
163
+ function _colour_initial_value ( PairList p ) {
164
+ let raw := _tui_string( p.get( "value", "#000000" ) );
165
+ let parsed := _parse_colour_or_null(raw);
166
+ return parsed ≢ null ? parsed : raw;
167
+ }
168
+
169
+ function _colour_default_value ( PairList p ) {
170
+ return _parse_colour_or_null( p.get( "value", "#000000" ) ) ?: "#000000";
171
+ }
172
+
173
+ function _tui_colour_dialog ( PairList p ) {
174
+ let default_value := _colour_default_value(p);
175
+ while ( true ) {
176
+ let answer := readline(
177
+ colour_text( p.get( "label", "Colour:" ) _ " ", "cyan" ),
178
+ default_value,
179
+ null,
180
+ );
181
+ let parsed := _parse_colour_or_null(answer);
182
+ if ( parsed ≢ null ) {
183
+ return parsed;
184
+ }
185
+ say( colour_text( "Invalid colour; try #336699 or red.", "yellow" ) );
186
+ }
187
+ }
188
+
189
+ function _dialogue_window (
190
+ String kind,
191
+ String title,
192
+ Widget body,
193
+ Array buttons,
194
+ PairList p
195
+ ) {
196
+ let button_row := HBox(
197
+ id: "buttons",
198
+ align: "right",
199
+ gap: 6,
200
+ height: p.get( "button_row_height", 2.125 × EM ),
201
+ maxheight: p.get( "button_row_height", 2.125 × EM ),
202
+ );
203
+ for ( let button in buttons ) {
204
+ button_row.add_child(button);
205
+ }
206
+ let w := Window(
207
+ title: title,
208
+ width: p.get( "width", 360 ),
209
+ height: p.get( "height", 180 ),
210
+ resizable: p.get( "resizable", false ),
211
+ modal: true,
212
+ VBox(
213
+ id: p.get( "id", null ),
214
+ gap: p.get( "gap", 8 ),
215
+ padding: p.get( "padding", 12 ),
216
+ body,
217
+ button_row,
218
+ ),
219
+ );
220
+ w.meta( "dialogue.kind", kind );
221
+ return w;
222
+ }
223
+
224
+ function _message_body ( String message, PairList p ) {
225
+ return Text(
226
+ id: p.get( "message_id", "message" ),
227
+ value: message,
228
+ readonly: true,
229
+ wrap: true,
230
+ );
231
+ }
232
+
233
+ function _primary_button ( PairList p, String fallback ) {
234
+ return Button(
235
+ id: p.get( "ok_id", "ok" ),
236
+ text: p.get( "ok_text", fallback ),
237
+ variant: "primary",
238
+ width: p.get( "button_width", 5.5 × EM ),
239
+ height: p.get( "button_height", 1.75 × EM ),
240
+ maxheight: p.get( "button_height", 1.75 × EM ),
241
+ );
242
+ }
243
+
244
+ function _cancel_button ( PairList p ) {
245
+ return Button(
246
+ id: p.get( "cancel_id", "cancel" ),
247
+ text: p.get( "cancel_text", "Cancel" ),
248
+ width: p.get( "button_width", 5.5 × EM ),
249
+ height: p.get( "button_height", 1.75 × EM ),
250
+ maxheight: p.get( "button_height", 1.75 × EM ),
251
+ );
252
+ }
253
+
254
+ function _alert_window ( String message, PairList p ) {
255
+ let ok := _primary_button( p, "OK" );
256
+ let w := _dialogue_window(
257
+ "alert",
258
+ p.get( "title", "Alert" ),
259
+ _message_body( message, p ),
260
+ [ ok ],
261
+ p,
262
+ );
263
+ ok.click( function () {
264
+ w.close(null);
265
+ } );
266
+ return w;
267
+ }
268
+
269
+ function alert_window ( String message, ... PairList p ) {
270
+ return _alert_window( message, p );
271
+ }
272
+
273
+ function alert ( String message, ... PairList p ) {
274
+ if ( p.has("auto_result") ) {
275
+ return null;
276
+ }
277
+ if ( __system__{deny_gui} ) {
278
+ say( colour_text( message, "yellow" ) );
279
+ return null;
280
+ }
281
+ if ( native_alert ≢ null ) {
282
+ let native_result := native_alert( message, p );
283
+ if ( native_result ) {
284
+ return null;
285
+ }
286
+ }
287
+ return _alert_window( message, p ).call();
288
+ }
289
+
290
+ function _confirm_window ( String message, PairList p ) {
291
+ let ok := _primary_button( p, p.get( "ok_text", "OK" ) );
292
+ let cancel := _cancel_button(p);
293
+ let w := _dialogue_window(
294
+ "confirm",
295
+ p.get( "title", "Confirm" ),
296
+ _message_body( message, p ),
297
+ [ cancel, ok ],
298
+ p,
299
+ );
300
+ ok.click( function () {
301
+ w.close(true);
302
+ } );
303
+ cancel.click( function () {
304
+ w.close(false);
305
+ } );
306
+ return w;
307
+ }
308
+
309
+ function confirm_window ( String message, ... PairList p ) {
310
+ return _confirm_window( message, p );
311
+ }
312
+
313
+ function confirm ( String message, ... PairList p ) {
314
+ if ( p.has("auto_result") ) {
315
+ return p.get("auto_result") ? true : false;
316
+ }
317
+ if ( __system__{deny_gui} ) {
318
+ let yes_default := p.get( "value", p.get( "default", false ) );
319
+ let suffix := yes_default ? " [Y/n] " : " [y/N] ";
320
+ let answer := readline(
321
+ colour_text( message _ suffix, "cyan" ),
322
+ yes_default ? "y" : "n",
323
+ null,
324
+ );
325
+ return ( answer ~ /^(?:y|yes|1|true)$/i ) ? true : false;
326
+ }
327
+ if ( native_confirm ≢ null ) {
328
+ let native_result := native_confirm( message, p );
329
+ if ( native_result ≢ null ) {
330
+ return native_result ? true : false;
331
+ }
332
+ }
333
+ return _confirm_window( message, p ).call() ? true : false;
334
+ }
335
+
336
+ function _prompt_window ( String message, PairList p ) {
337
+ let input := Input(
338
+ id: p.get( "input_id", "value" ),
339
+ value: p.get( "value", "" ),
340
+ placeholder: p.get( "placeholder", "" ),
341
+ );
342
+ let ok := _primary_button( p, p.get( "ok_text", "OK" ) );
343
+ let cancel := _cancel_button(p);
344
+ let w := _dialogue_window(
345
+ "prompt",
346
+ p.get( "title", "Prompt" ),
347
+ VBox(
348
+ gap: 6,
349
+ _message_body( message, p ),
350
+ input,
351
+ ),
352
+ [ cancel, ok ],
353
+ p,
354
+ );
355
+ ok.click( function () {
356
+ w.close( input.value() );
357
+ } );
358
+ cancel.click( function () {
359
+ w.close(null);
360
+ } );
361
+ return w;
362
+ }
363
+
364
+ function prompt_window ( String message, ... PairList p ) {
365
+ return _prompt_window( message, p );
366
+ }
367
+
368
+ function prompt ( String message, ... PairList p ) {
369
+ if ( p.has("auto_result") ) {
370
+ return p.get("auto_result");
371
+ }
372
+ if ( __system__{deny_gui} ) {
373
+ return _tui_prompt(
374
+ message,
375
+ p,
376
+ _tui_string( p.get( "value", "" ) ),
377
+ );
378
+ }
379
+ if ( native_prompt ≢ null ) {
380
+ let native_result := native_prompt( message, p );
381
+ if ( _gui_backend() eq "browser-dom" ) {
382
+ return native_result;
383
+ }
384
+ if ( native_result ≢ null ) {
385
+ return native_result;
386
+ }
387
+ }
388
+ return _prompt_window( message, p ).call();
389
+ }
390
+
391
+ function _path_dialog_window (
392
+ String kind,
393
+ String title,
394
+ String label,
395
+ String default_value,
396
+ PairList p
397
+ ) {
398
+ let input := Input(
399
+ id: p.get( "input_id", "path" ),
400
+ value: p.get( "value", default_value ),
401
+ placeholder: p.get( "placeholder", "" ),
402
+ multiline: p.get( "multiple", false ),
403
+ );
404
+ let ok := _primary_button( p, p.get( "ok_text", "OK" ) );
405
+ let cancel := _cancel_button(p);
406
+ let w := _dialogue_window(
407
+ kind,
408
+ p.get( "title", title ),
409
+ VBox(
410
+ gap: 6,
411
+ Label( text: p.get( "label", label ), ("for"): input.id() ),
412
+ input,
413
+ ),
414
+ [ cancel, ok ],
415
+ p,
416
+ );
417
+ ok.click( function () {
418
+ if ( p.get( "multiple", false ) ) {
419
+ w.close( split( input.value(), p.get( "separator", "\n" ) ) );
420
+ }
421
+ else {
422
+ w.close( input.value() );
423
+ }
424
+ } );
425
+ cancel.click( function () {
426
+ w.close(null);
427
+ } );
428
+ return w;
429
+ }
430
+
431
+ function file_open_window ( ... PairList p ) {
432
+ return _path_dialog_window( "file_open", "Open File", "File:", "", p );
433
+ }
434
+
435
+ function file_save_window ( ... PairList p ) {
436
+ return _path_dialog_window( "file_save", "Save File", "File:", "", p );
437
+ }
438
+
439
+ function directory_open_window ( ... PairList p ) {
440
+ return _path_dialog_window(
441
+ "directory_open",
442
+ "Open Directory",
443
+ "Directory:",
444
+ "",
445
+ p,
446
+ );
447
+ }
448
+
449
+ function directory_save_window ( ... PairList p ) {
450
+ return _path_dialog_window(
451
+ "directory_save",
452
+ "Save Directory",
453
+ "Directory:",
454
+ "",
455
+ p,
456
+ );
457
+ }
458
+
459
+ function _colour_picker_window ( PairList p ) {
460
+ let input := Input(
461
+ id: p.get( "input_id", "path" ),
462
+ value: _colour_initial_value(p),
463
+ placeholder: p.get( "placeholder", "#336699" ),
464
+ );
465
+ let ok := _primary_button( p, p.get( "ok_text", "OK" ) );
466
+ let cancel := _cancel_button(p);
467
+ let default_value := _colour_default_value(p);
468
+ let sync_ok := function () {
469
+ ok.set_enabled( _parse_colour_or_null( input.value() ) ≢ null );
470
+ };
471
+ let w := _dialogue_window(
472
+ "colour_picker",
473
+ p.get( "title", "Choose Colour" ),
474
+ VBox(
475
+ gap: 6,
476
+ Label(
477
+ text: p.get( "label", "Colour:" ),
478
+ ("for"): input.id(),
479
+ ),
480
+ input,
481
+ ),
482
+ [ cancel, ok ],
483
+ p,
484
+ );
485
+ sync_ok();
486
+ input.on( "change", sync_ok );
487
+ ok.click( function () {
488
+ let parsed := _parse_colour_or_null( input.value() );
489
+ if ( parsed ≢ null ) {
490
+ w.close(parsed);
491
+ }
492
+ } );
493
+ cancel.click( function () {
494
+ w.close(default_value);
495
+ } );
496
+ return w;
497
+ }
498
+
499
+ function colour_picker_window ( ... PairList p ) {
500
+ return _colour_picker_window(p);
501
+ }
502
+
503
+ function file_open ( ... PairList p ) {
504
+ _path_dialogue_unsupported();
505
+ if ( p.has("auto_result") ) {
506
+ return p.get("auto_result");
507
+ }
508
+ if ( __system__{deny_gui} ) {
509
+ return _tui_path_dialog( "File:", "", filename_completions, p );
510
+ }
511
+ return native_file_open(p);
512
+ }
513
+
514
+ function file_save ( ... PairList p ) {
515
+ _path_dialogue_unsupported();
516
+ if ( p.has("auto_result") ) {
517
+ return p.get("auto_result");
518
+ }
519
+ if ( __system__{deny_gui} ) {
520
+ return _tui_path_dialog( "File:", "", filename_completions, p );
521
+ }
522
+ return native_file_save(p);
523
+ }
524
+
525
+ function directory_open ( ... PairList p ) {
526
+ _path_dialogue_unsupported();
527
+ if ( p.has("auto_result") ) {
528
+ return p.get("auto_result");
529
+ }
530
+ if ( __system__{deny_gui} ) {
531
+ return _tui_path_dialog(
532
+ "Directory:",
533
+ "",
534
+ directory_completions,
535
+ p,
536
+ );
537
+ }
538
+ return native_directory_open(p);
539
+ }
540
+
541
+ function directory_save ( ... PairList p ) {
542
+ _path_dialogue_unsupported();
543
+ if ( p.has("auto_result") ) {
544
+ return p.get("auto_result");
545
+ }
546
+ if ( __system__{deny_gui} ) {
547
+ return _tui_path_dialog(
548
+ "Directory:",
549
+ "",
550
+ directory_completions,
551
+ p,
552
+ );
553
+ }
554
+ if ( native_directory_save ≢ null ) {
555
+ let native_result := native_directory_save(p);
556
+ if ( native_result ≢ null ) {
557
+ return native_result;
558
+ }
559
+ if ( _gui_backend() eq "electron-dom" ) {
560
+ return null;
561
+ }
562
+ }
563
+ return _path_dialog_window(
564
+ "directory_save",
565
+ "Save Directory",
566
+ "Directory:",
567
+ "",
568
+ p,
569
+ ).call();
570
+ }
571
+
572
+ function colour_picker ( ... PairList p ) {
573
+ if ( p.has("auto_result") ) {
574
+ return parse_colour( _tui_string( p.get("auto_result") ) );
575
+ }
576
+ if ( __system__{deny_gui} ) {
577
+ return _tui_colour_dialog(p);
578
+ }
579
+ if ( native_colour_picker ≢ null ) {
580
+ let native_result := native_colour_picker(p);
581
+ if ( native_result ≢ null ) {
582
+ return parse_colour(native_result);
583
+ }
584
+ if ( _gui_backend() eq "browser-dom" ) {
585
+ return null;
586
+ }
587
+ }
588
+ if ( _gui_backend() eq "electron-dom" ) {
589
+ return _colour_picker_window(p).call();
590
+ }
591
+ return parse_colour( _colour_picker_window(p).call() );
592
+ }
@@ -0,0 +1,123 @@
1
+ =encoding utf8
2
+
3
+ =head1 NAME
4
+
5
+ std/gui/objects - Runtime-supported GUI object classes.
6
+
7
+ =head1 SYNOPSIS
8
+
9
+ from std/gui/objects import Window, VBox, Button;
10
+
11
+ let w := new Window( title: "Demo" );
12
+ let b := new Button( text: "OK", id: "submit" );
13
+ w.set_content( new VBox( children: [ b ] ) );
14
+
15
+ =head1 IMPLEMENTATION SUPPORT
16
+
17
+ This module is supported by zuzu.pl, zuzu-rust, and zuzu-js on Electron.
18
+ It is not supported by zuzu-js on Node or Browser.
19
+
20
+ =head1 DESCRIPTION
21
+
22
+ This runtime-supported module provides the C<std/gui> object model.
23
+ Host runtimes provide visible windows and baseline controls where GUI
24
+ support is available, while retaining the same object tree and event API
25
+ for tests and future backends.
26
+
27
+ =head1 EXPORTS
28
+
29
+ =head2 Variables
30
+
31
+ =over
32
+
33
+ =item C<meta>
34
+
35
+ Type: C<Dict>. Runtime/backend metadata. Current keys include
36
+ C<backend>, C<font_size_pixels>, C<font_name>, and C<font_point_size>.
37
+
38
+ =back
39
+
40
+ =head2 Classes
41
+
42
+ =over
43
+
44
+ =item C<Widget>
45
+
46
+ Base class for GUI objects. Supports C<id>, C<parent>, C<children>,
47
+ C<add_child>, C<remove_child>, C<enabled>, C<set_enabled>,
48
+ C<visible>, C<set_visible>, C<width>, C<height>, C<minwidth>,
49
+ C<minheight>, C<maxwidth>, C<maxheight>, C<classes>, C<add_class>,
50
+ C<remove_class>, C<style>, C<meta>, C<find_by_id>, C<on>, C<once>,
51
+ C<off>, C<emit>, and event shortcuts such as C<click>.
52
+
53
+ Common widget methods take or return widget state values. Getters return
54
+ the current value; setters return the widget so calls can be chained.
55
+
56
+ =item C<Window>
57
+
58
+ Top-level container with C<show>, C<call>, C<close>, C<content>, and
59
+ C<set_content>. In Phase 1, C<show> is non-rendering and C<call>
60
+ returns the current close result.
61
+
62
+ =item C<VBox>, C<HBox>, C<Frame>
63
+
64
+ Layout containers.
65
+
66
+ =item C<Menu>, C<MenuItem>
67
+
68
+ Window menu bar widgets. C<Menu> widgets are direct C<Window> children;
69
+ C<MenuItem> widgets are direct C<Menu> children.
70
+
71
+ =item C<Label>, C<Text>, C<RichText>, C<Image>
72
+
73
+ Content widgets.
74
+
75
+ =item C<Input>, C<DatePicker>, C<Checkbox>, C<Radio>, C<RadioGroup>,
76
+ C<Select>, C<Button>
77
+
78
+ Baseline input widgets.
79
+
80
+ =item C<Separator>, C<Slider>, C<Progress>
81
+
82
+ Extended baseline controls.
83
+
84
+ =item C<Tabs>, C<Tab>
85
+
86
+ Tab container and tab pages. C<Tabs.selected> selects the active C<Tab>.
87
+
88
+ =item C<ListView>, C<TreeView>
89
+
90
+ Collection controls with selection and activation events.
91
+
92
+ =item C<Event>
93
+
94
+ Event object passed to handlers which accept an argument. Provides
95
+ C<name>, C<target>, C<current_target>, C<window>, C<phase>,
96
+ C<timestamp>, C<data>, C<cancelled>, C<default_prevented>,
97
+ C<stop_propagation>, and C<prevent_default>.
98
+
99
+ =item C<ListenerToken>
100
+
101
+ Opaque token returned by C<on> and C<once>, accepted by C<off>.
102
+
103
+ =item C<native_file_open>, C<native_file_save>, C<native_directory_open>,
104
+ C<native_directory_save>, C<native_alert>, C<native_confirm>,
105
+ C<native_prompt>, C<native_colour_picker>
106
+
107
+ Backend-native modal file and directory dialogue hooks used by
108
+ C<std/gui/dialogue>. These return selected paths or C<null> when cancelled.
109
+ C<native_alert>, C<native_confirm>, C<native_prompt>, and
110
+ C<native_colour_picker> return C<null> when unsupported so
111
+ C<std/gui/dialogue> can use its shared fallback.
112
+
113
+ =back
114
+
115
+ =head1 COPYRIGHT AND LICENCE
116
+
117
+ B<< std/gui/objects >> is copyright Toby Inkster.
118
+
119
+ It is free software; you may redistribute it and/or modify it under
120
+ the terms of either the Artistic License 1.0 or the GNU General Public
121
+ License version 2.
122
+
123
+ =cut