@yuneta/gobj-ui 1.0.1 → 2.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.
Files changed (46) hide show
  1. package/README.md +40 -363
  2. package/dist/gobj-ui.cjs.js +11154 -5506
  3. package/dist/gobj-ui.es.js +11131 -5508
  4. package/index.js +41 -14
  5. package/package.json +11 -9
  6. package/src/c_g6_nodes_tree.js +6 -1
  7. package/src/c_yui_form.js +1 -1
  8. package/src/c_yui_gobj_tree_js.js +1 -1
  9. package/src/c_yui_json_graph.js +1 -1
  10. package/src/c_yui_main.js +3 -3
  11. package/src/c_yui_map.js +6 -1
  12. package/src/c_yui_nav.js +881 -0
  13. package/src/c_yui_pager.js +545 -0
  14. package/src/c_yui_routing.css +1 -1
  15. package/src/c_yui_routing.js +1 -1
  16. package/src/c_yui_shell.css +571 -0
  17. package/src/c_yui_shell.js +2474 -0
  18. package/src/c_yui_tabs.js +1 -1
  19. package/src/c_yui_treedb_graph.js +35 -9
  20. package/src/c_yui_treedb_topic_with_form.js +1 -1
  21. package/src/c_yui_treedb_topics.js +36 -8
  22. package/src/c_yui_uplot.js +1 -1
  23. package/src/c_yui_window.js +242 -21
  24. package/src/c_yui_window_manager.js +602 -0
  25. package/src/c_yui_wizard.js +612 -0
  26. package/src/pager_helpers.js +138 -0
  27. package/src/pager_helpers.test.js +140 -0
  28. package/src/route_resolver.js +53 -0
  29. package/src/route_resolver.test.js +82 -0
  30. package/src/shell_focus_trap.js +123 -0
  31. package/src/shell_focus_trap.test.js +299 -0
  32. package/src/shell_modals.js +445 -0
  33. package/src/shell_show_on.js +91 -0
  34. package/src/shell_show_on.test.js +86 -0
  35. package/src/shell_toolbar_helpers.js +221 -0
  36. package/src/shell_toolbar_helpers.test.js +207 -0
  37. package/src/tabulator.css +53 -0
  38. package/src/wizard_helpers.js +117 -0
  39. package/src/wizard_helpers.test.js +122 -0
  40. package/src/yui_dev.js +1257 -362
  41. package/src/yui_icons.css +5 -0
  42. package/src/yui_inputs.css +32 -0
  43. package/src/yui_inputs.js +71 -0
  44. package/vite-plugin-yuneta-html.js +2 -2
  45. package/skeleton/config.json +0 -20
  46. package/skeleton/index.html +0 -37
@@ -0,0 +1,612 @@
1
+ /***********************************************************************
2
+ * c_yui_wizard.js
3
+ *
4
+ * Multi-step wizard (Pattern B).
5
+ *
6
+ * Container-agnostic: the gclass owns ONLY the navigation chrome
7
+ * (title + "N / M" + a body that shows one step + a footer with
8
+ * Back / Next, and Confirm on the last step). The parent mounts
9
+ * `gobj_read_attr(wizard, "$container")` wherever it wants and
10
+ * supplies the ordered steps up-front with EV_SET_STEPS.
11
+ *
12
+ * Unlike C_YUI_PAGER, a wizard DOES confirm at the end. In a
13
+ * `linear` wizard each step's content gobj is asked to validate
14
+ * before advancing: the wizard sends EV_STEP_VALIDATE and the
15
+ * step answers EV_STEP_VALID { ...kw } or EV_STEP_INVALID
16
+ * { msg }. Validated kw is accumulated and delivered merged in
17
+ * EV_WIZARD_DONE. Steps that are plain elements (no gobj) and
18
+ * non-linear wizards skip validation.
19
+ *
20
+ * A step `content` may be a gobj exposing a "$container" attr,
21
+ * an HTMLElement, or a createElement2() spec (array).
22
+ *
23
+ * Copyright (c) 2026, ArtGins.
24
+ * All Rights Reserved.
25
+ ***********************************************************************/
26
+ import {
27
+ SDATA,
28
+ SDATA_END,
29
+ data_type_t,
30
+ event_flag_t,
31
+ gclass_create,
32
+ log_error,
33
+ gobj_subscribe_event,
34
+ gobj_read_pointer_attr,
35
+ gobj_parent,
36
+ createElement2,
37
+ gobj_write_attr,
38
+ gobj_read_attr,
39
+ gobj_send_event,
40
+ gobj_publish_event,
41
+ gobj_stop_children,
42
+ } from "@yuneta/gobj-js";
43
+
44
+ import {
45
+ wizard_step_model,
46
+ wizard_next_index,
47
+ wizard_prev_index,
48
+ wizard_clamp_index,
49
+ wizard_accumulate,
50
+ wizard_should_validate,
51
+ } from "./wizard_helpers.js";
52
+
53
+
54
+ /***************************************************************
55
+ * Constants
56
+ ***************************************************************/
57
+ const GCLASS_NAME = "C_YUI_WIZARD";
58
+
59
+ /***************************************************************
60
+ * Data
61
+ ***************************************************************/
62
+ const attrs_table = [
63
+ SDATA(data_type_t.DTP_POINTER, "subscriber", 0, null, "Subscriber of output events"),
64
+
65
+ SDATA(data_type_t.DTP_STRING, "confirm_label",0, "confirm", "i18n key of the last-step primary button"),
66
+ SDATA(data_type_t.DTP_STRING, "next_label", 0, "next", "i18n key of the primary button (not last step)"),
67
+ SDATA(data_type_t.DTP_STRING, "back_label", 0, "back", "i18n key of the back button"),
68
+ SDATA(data_type_t.DTP_BOOLEAN, "allow_back", 0, true, "Allow going back to previous steps"),
69
+ SDATA(data_type_t.DTP_BOOLEAN, "linear", 0, true, "Each step's gobj must validate before advancing"),
70
+
71
+ /*---------------- UI ----------------*/
72
+ SDATA(data_type_t.DTP_POINTER, "$container", 0, null, "HTMLElement root, mounted by the parent"),
73
+ SDATA_END()
74
+ ];
75
+
76
+ let PRIVATE_DATA = {
77
+ steps: null,
78
+ idx: 0,
79
+ acc: null,
80
+ awaiting: false
81
+ };
82
+
83
+ let __gclass__ = null;
84
+
85
+
86
+
87
+
88
+ /******************************
89
+ * Framework Methods
90
+ ******************************/
91
+
92
+
93
+
94
+
95
+ /***************************************************************
96
+ * Framework Method: Create
97
+ ***************************************************************/
98
+ function mt_create(gobj)
99
+ {
100
+ let priv = gobj.priv;
101
+
102
+ priv.steps = [];
103
+ priv.idx = 0;
104
+ priv.acc = null;
105
+ priv.awaiting = false;
106
+
107
+ build_ui(gobj);
108
+
109
+ /*
110
+ * CHILD subscription model
111
+ */
112
+ let subscriber = gobj_read_pointer_attr(gobj, "subscriber");
113
+ if(!subscriber) {
114
+ subscriber = gobj_parent(gobj);
115
+ }
116
+ gobj_subscribe_event(gobj, null, {}, subscriber);
117
+ }
118
+
119
+ /***************************************************************
120
+ * Framework Method: Start
121
+ ***************************************************************/
122
+ function mt_start(gobj)
123
+ {
124
+ }
125
+
126
+ /***************************************************************
127
+ * Framework Method: Stop
128
+ ***************************************************************/
129
+ function mt_stop(gobj)
130
+ {
131
+ gobj_stop_children(gobj);
132
+ }
133
+
134
+ /***************************************************************
135
+ * Framework Method: Destroy
136
+ ***************************************************************/
137
+ function mt_destroy(gobj)
138
+ {
139
+ destroy_ui(gobj);
140
+ }
141
+
142
+
143
+
144
+
145
+ /***************************
146
+ * Local Methods
147
+ ***************************/
148
+
149
+
150
+
151
+
152
+ /************************************************************
153
+ * Build UI
154
+ ************************************************************/
155
+ function build_ui(gobj)
156
+ {
157
+ let $container = createElement2(
158
+ ['div', {class: 'C_YUI_WIZARD', style: 'height:100%; display:flex; flex-direction:column;'}, [
159
+ ['div', {class: 'yui-wizard-header is-flex is-align-items-center is-flex-grow-0',
160
+ style: 'gap:.5rem; padding:.25rem .5rem;'}, [
161
+ ['span', {class: 'yui-wizard-title is-flex-grow-1', style: 'font-weight:600;'}, ''],
162
+ ['span', {class: 'yui-wizard-counter has-text-weight-semibold', style: 'opacity:.7;'}, '']
163
+ ]],
164
+ ['div', {class: 'yui-wizard-body is-flex-grow-1',
165
+ style: 'flex:1 1 auto; min-height:0; position:relative; overflow:auto;'}, []
166
+ ],
167
+ ['div', {class: 'yui-wizard-footer is-flex is-justify-content-space-between is-flex-grow-0',
168
+ style: 'gap:.5rem; padding:.5rem;'}, [
169
+ ['button', {class: 'yui-wizard-back button', 'aria-label': 'back'}, [
170
+ ['span', {class: 'icon'}, ['i', {class: 'yi-arrow-left'}]],
171
+ ['span', {class: 'is-hidden-mobile', i18n: 'back'}, 'back']
172
+ ], {
173
+ click: function(evt) {
174
+ evt.stopPropagation();
175
+ gobj_send_event(gobj, "EV_PREV", {}, gobj);
176
+ }
177
+ }],
178
+ ['button', {class: 'yui-wizard-primary button is-link', 'aria-label': 'next'}, [
179
+ ['span', {class: 'yui-wizard-primary-label', i18n: 'next'}, 'next']
180
+ ], {
181
+ click: function(evt) {
182
+ evt.stopPropagation();
183
+ gobj_send_event(gobj, "EV_NEXT", {}, gobj);
184
+ }
185
+ }]
186
+ ]]
187
+ ]]
188
+ );
189
+ gobj_write_attr(gobj, "$container", $container);
190
+ }
191
+
192
+ /************************************************************
193
+ * Destroy UI
194
+ ************************************************************/
195
+ function destroy_ui(gobj)
196
+ {
197
+ let $container = gobj_read_attr(gobj, "$container");
198
+ if($container) {
199
+ if($container.parentNode) {
200
+ $container.parentNode.removeChild($container);
201
+ }
202
+ gobj_write_attr(gobj, "$container", null);
203
+ }
204
+ }
205
+
206
+ /************************************************************
207
+ * Resolve a step `content` into { $el, gobj }
208
+ ************************************************************/
209
+ function resolve_panel(content)
210
+ {
211
+ if(content instanceof HTMLElement) {
212
+ return { $el: content, gobj: null };
213
+ }
214
+ if(Array.isArray(content)) {
215
+ return { $el: createElement2(content), gobj: null };
216
+ }
217
+ /*
218
+ * Assume a gobj exposing a "$container" attr
219
+ */
220
+ let $el = gobj_read_attr(content, "$container");
221
+ return { $el: $el, gobj: content };
222
+ }
223
+
224
+ /************************************************************
225
+ * Re-render the chrome (title / counter / buttons) and
226
+ * show only the current step.
227
+ ************************************************************/
228
+ function render_chrome(gobj)
229
+ {
230
+ let priv = gobj.priv;
231
+ let proj = priv.steps.map(function(s) {
232
+ return { id: s.id, title: s.title };
233
+ });
234
+ let model = wizard_step_model(proj, priv.idx, {
235
+ allow_back: gobj_read_attr(gobj, "allow_back"),
236
+ confirm_label: gobj_read_attr(gobj, "confirm_label"),
237
+ next_label: gobj_read_attr(gobj, "next_label"),
238
+ });
239
+
240
+ let $container = gobj_read_attr(gobj, "$container");
241
+ let $title = $container.querySelector('.yui-wizard-title');
242
+ let $counter = $container.querySelector('.yui-wizard-counter');
243
+ let $back = $container.querySelector('.yui-wizard-back');
244
+ let $plabel = $container.querySelector('.yui-wizard-primary-label');
245
+
246
+ $title.setAttribute('i18n', model.title);
247
+ $title.textContent = model.title;
248
+
249
+ if(model.count > 0) {
250
+ $counter.textContent = `${model.idx + 1} / ${model.count}`;
251
+ } else {
252
+ $counter.textContent = "";
253
+ }
254
+
255
+ $back.classList.toggle('is-hidden', !model.show_back);
256
+
257
+ $plabel.setAttribute('i18n', model.primary_label);
258
+ $plabel.textContent = model.primary_label;
259
+
260
+ /*
261
+ * Show only the current step
262
+ */
263
+ for(let i = 0; i < priv.steps.length; i++) {
264
+ let s = priv.steps[i];
265
+ if(s.$el) {
266
+ s.$el.classList.toggle('is-hidden', i !== model.idx);
267
+ }
268
+ }
269
+ }
270
+
271
+ /************************************************************
272
+ * Forward an event to the current step (if it is a gobj)
273
+ ************************************************************/
274
+ function forward_current(gobj, event, kw)
275
+ {
276
+ let priv = gobj.priv;
277
+ let s = priv.steps[priv.idx];
278
+ if(s && s.gobj) {
279
+ gobj_send_event(s.gobj, event, kw || {}, gobj);
280
+ }
281
+ }
282
+
283
+ /************************************************************
284
+ * Accumulate the current step's kw, then advance or finish
285
+ ************************************************************/
286
+ function advance(gobj, kw)
287
+ {
288
+ let priv = gobj.priv;
289
+ let cur = priv.steps[priv.idx];
290
+
291
+ priv.acc = wizard_accumulate(priv.acc, cur ? cur.id : "", kw);
292
+
293
+ let proj = priv.steps.map(function(s) {
294
+ return { id: s.id, title: s.title };
295
+ });
296
+ let model = wizard_step_model(proj, priv.idx, {
297
+ allow_back: gobj_read_attr(gobj, "allow_back"),
298
+ confirm_label: gobj_read_attr(gobj, "confirm_label"),
299
+ next_label: gobj_read_attr(gobj, "next_label"),
300
+ });
301
+
302
+ if(model.is_last) {
303
+ gobj_publish_event(gobj, "EV_WIZARD_DONE", {
304
+ kw: priv.acc.merged,
305
+ by_step: priv.acc.by_step,
306
+ });
307
+ return;
308
+ }
309
+
310
+ priv.idx = wizard_next_index(priv.idx, priv.steps.length);
311
+ render_chrome(gobj);
312
+ let now = priv.steps[priv.idx];
313
+ gobj_publish_event(gobj, "EV_STEP_SHOWN", {
314
+ idx: priv.idx,
315
+ id: now ? now.id : "",
316
+ });
317
+ }
318
+
319
+
320
+
321
+
322
+ /***************************
323
+ * Actions
324
+ ***************************/
325
+
326
+
327
+
328
+
329
+ /************************************************************
330
+ * EV_SET_STEPS { steps: [ { id, title, content } ] }
331
+ ************************************************************/
332
+ function ac_set_steps(gobj, event, kw, src)
333
+ {
334
+ let priv = gobj.priv;
335
+
336
+ let steps_in = (kw && kw.steps) || [];
337
+ if(steps_in.length === 0) {
338
+ log_error(`${GCLASS_NAME}: EV_SET_STEPS with no steps`);
339
+ return -1;
340
+ }
341
+
342
+ let $body = gobj_read_attr(gobj, "$container").querySelector('.yui-wizard-body');
343
+ $body.innerHTML = "";
344
+
345
+ let steps = [];
346
+ for(let i = 0; i < steps_in.length; i++) {
347
+ let st = steps_in[i];
348
+ let resolved = resolve_panel(st.content);
349
+ if(!resolved.$el) {
350
+ log_error(`${GCLASS_NAME}: step '${st.id}' has no content`);
351
+ return -1;
352
+ }
353
+ resolved.$el.classList.add('is-hidden');
354
+ $body.appendChild(resolved.$el);
355
+ steps.push({
356
+ id: st.id || "",
357
+ title: st.title || "",
358
+ $el: resolved.$el,
359
+ gobj: resolved.gobj,
360
+ });
361
+ }
362
+
363
+ priv.steps = steps;
364
+ priv.idx = 0;
365
+ priv.acc = null;
366
+ priv.awaiting = false;
367
+
368
+ render_chrome(gobj);
369
+ let now = priv.steps[0];
370
+ gobj_publish_event(gobj, "EV_STEP_SHOWN", {idx: 0, id: now ? now.id : ""});
371
+ return 0;
372
+ }
373
+
374
+ /************************************************************
375
+ * EV_NEXT — validate (if linear) then advance / confirm
376
+ ************************************************************/
377
+ function ac_next(gobj, event, kw, src)
378
+ {
379
+ let priv = gobj.priv;
380
+ if(priv.steps.length === 0) {
381
+ return 0;
382
+ }
383
+
384
+ let cur = priv.steps[priv.idx];
385
+ let linear = gobj_read_attr(gobj, "linear");
386
+
387
+ if(wizard_should_validate(linear, !!(cur && cur.gobj))) {
388
+ if(priv.awaiting) {
389
+ return 0;
390
+ }
391
+ priv.awaiting = true;
392
+ gobj_send_event(cur.gobj, "EV_STEP_VALIDATE", {}, gobj);
393
+ return 0;
394
+ }
395
+
396
+ advance(gobj, {});
397
+ return 0;
398
+ }
399
+
400
+ /************************************************************
401
+ * EV_PREV — go to the previous step
402
+ ************************************************************/
403
+ function ac_prev(gobj, event, kw, src)
404
+ {
405
+ let priv = gobj.priv;
406
+ if(priv.steps.length === 0) {
407
+ return 0;
408
+ }
409
+ priv.awaiting = false;
410
+ priv.idx = wizard_prev_index(priv.idx, priv.steps.length);
411
+ render_chrome(gobj);
412
+ let now = priv.steps[priv.idx];
413
+ gobj_publish_event(gobj, "EV_STEP_SHOWN", {idx: priv.idx, id: now ? now.id : ""});
414
+ return 0;
415
+ }
416
+
417
+ /************************************************************
418
+ * EV_GOTO { idx } — jump to a step (no validation)
419
+ ************************************************************/
420
+ function ac_goto(gobj, event, kw, src)
421
+ {
422
+ let priv = gobj.priv;
423
+ if(priv.steps.length === 0) {
424
+ return 0;
425
+ }
426
+ priv.awaiting = false;
427
+ priv.idx = wizard_clamp_index((kw && kw.idx) || 0, priv.steps.length);
428
+ render_chrome(gobj);
429
+ let now = priv.steps[priv.idx];
430
+ gobj_publish_event(gobj, "EV_STEP_SHOWN", {idx: priv.idx, id: now ? now.id : ""});
431
+ return 0;
432
+ }
433
+
434
+ /************************************************************
435
+ * EV_STEP_VALID { ...kw } — step accepted, accumulate+advance
436
+ ************************************************************/
437
+ function ac_step_valid(gobj, event, kw, src)
438
+ {
439
+ let priv = gobj.priv;
440
+ if(!priv.awaiting) {
441
+ return 0;
442
+ }
443
+ priv.awaiting = false;
444
+ advance(gobj, kw || {});
445
+ return 0;
446
+ }
447
+
448
+ /************************************************************
449
+ * EV_STEP_INVALID { msg } — step rejected, stay put
450
+ * (the step shows its own error)
451
+ ************************************************************/
452
+ function ac_step_invalid(gobj, event, kw, src)
453
+ {
454
+ let priv = gobj.priv;
455
+ priv.awaiting = false;
456
+ return 0;
457
+ }
458
+
459
+ /************************************************************
460
+ * EV_CANCEL — host asked to cancel the wizard
461
+ ************************************************************/
462
+ function ac_cancel(gobj, event, kw, src)
463
+ {
464
+ gobj_publish_event(gobj, "EV_WIZARD_CANCEL", {});
465
+ return 0;
466
+ }
467
+
468
+ /************************************************************
469
+ * EV_SHOW
470
+ ************************************************************/
471
+ function ac_show(gobj, event, kw, src)
472
+ {
473
+ let $container = gobj_read_attr(gobj, "$container");
474
+ if($container) {
475
+ $container.classList.remove('is-hidden');
476
+ }
477
+ forward_current(gobj, "EV_SHOW", kw);
478
+ return 0;
479
+ }
480
+
481
+ /************************************************************
482
+ * EV_HIDE
483
+ ************************************************************/
484
+ function ac_hide(gobj, event, kw, src)
485
+ {
486
+ let $container = gobj_read_attr(gobj, "$container");
487
+ if($container) {
488
+ $container.classList.add('is-hidden');
489
+ }
490
+ forward_current(gobj, "EV_HIDE", {});
491
+ return 0;
492
+ }
493
+
494
+ /************************************************************
495
+ * EV_REFRESH
496
+ ************************************************************/
497
+ function ac_refresh(gobj, event, kw, src)
498
+ {
499
+ render_chrome(gobj);
500
+ forward_current(gobj, "EV_REFRESH", kw);
501
+ return 0;
502
+ }
503
+
504
+ /************************************************************
505
+ * EV_RESIZE
506
+ ************************************************************/
507
+ function ac_resize(gobj, event, kw, src)
508
+ {
509
+ forward_current(gobj, "EV_RESIZE", kw);
510
+ return 0;
511
+ }
512
+
513
+
514
+
515
+
516
+ /***************************
517
+ * FSM
518
+ ***************************/
519
+
520
+
521
+
522
+
523
+ /*---------------------------------------------*
524
+ * Global methods table
525
+ *---------------------------------------------*/
526
+ const gmt = {
527
+ mt_create: mt_create,
528
+ mt_start: mt_start,
529
+ mt_stop: mt_stop,
530
+ mt_destroy: mt_destroy,
531
+ };
532
+
533
+ /***************************************************************
534
+ * Create the GClass
535
+ ***************************************************************/
536
+ function create_gclass(gclass_name)
537
+ {
538
+ if(__gclass__) {
539
+ log_error(`GClass ALREADY created: ${gclass_name}`);
540
+ return -1;
541
+ }
542
+
543
+ /*---------------------------------------------*
544
+ * States
545
+ *---------------------------------------------*/
546
+ const states = [
547
+ ["ST_IDLE", [
548
+ ["EV_SET_STEPS", ac_set_steps, null],
549
+ ["EV_NEXT", ac_next, null],
550
+ ["EV_PREV", ac_prev, null],
551
+ ["EV_GOTO", ac_goto, null],
552
+ ["EV_STEP_VALID", ac_step_valid, null],
553
+ ["EV_STEP_INVALID", ac_step_invalid, null],
554
+ ["EV_CANCEL", ac_cancel, null],
555
+ ["EV_SHOW", ac_show, null],
556
+ ["EV_HIDE", ac_hide, null],
557
+ ["EV_REFRESH", ac_refresh, null],
558
+ ["EV_RESIZE", ac_resize, null]
559
+ ]]
560
+ ];
561
+
562
+ /*---------------------------------------------*
563
+ * Events
564
+ *---------------------------------------------*/
565
+ const event_types = [
566
+ ["EV_SET_STEPS", 0],
567
+ ["EV_NEXT", 0],
568
+ ["EV_PREV", 0],
569
+ ["EV_GOTO", 0],
570
+ ["EV_STEP_VALID", 0],
571
+ ["EV_STEP_INVALID", 0],
572
+ ["EV_CANCEL", 0],
573
+ ["EV_SHOW", 0],
574
+ ["EV_HIDE", 0],
575
+ ["EV_REFRESH", 0],
576
+ ["EV_RESIZE", 0],
577
+ ["EV_STEP_SHOWN", event_flag_t.EVF_OUTPUT_EVENT|event_flag_t.EVF_NO_WARN_SUBS],
578
+ ["EV_WIZARD_DONE", event_flag_t.EVF_OUTPUT_EVENT],
579
+ ["EV_WIZARD_CANCEL", event_flag_t.EVF_OUTPUT_EVENT],
580
+ ["EV_STEP_VALIDATE", event_flag_t.EVF_OUTPUT_EVENT|event_flag_t.EVF_NO_WARN_SUBS]
581
+ ];
582
+
583
+ __gclass__ = gclass_create(
584
+ gclass_name,
585
+ event_types,
586
+ states,
587
+ gmt,
588
+ 0, // lmt,
589
+ attrs_table,
590
+ PRIVATE_DATA,
591
+ 0, // authz_table,
592
+ 0, // command_table,
593
+ 0, // s_user_trace_level
594
+ 0 // gclass_flag
595
+ );
596
+
597
+ if(!__gclass__) {
598
+ return -1;
599
+ }
600
+
601
+ return 0;
602
+ }
603
+
604
+ /***************************************************************
605
+ * Register GClass
606
+ ***************************************************************/
607
+ function register_c_yui_wizard()
608
+ {
609
+ return create_gclass(GCLASS_NAME);
610
+ }
611
+
612
+ export { register_c_yui_wizard };