@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,122 @@
1
+ /***********************************************************************
2
+ * wizard_helpers.test.mjs
3
+ *
4
+ * Unit tests for the pure step logic of C_YUI_WIZARD.
5
+ * Run with: node --test tests/
6
+ ***********************************************************************/
7
+ import { test, expect } from "vitest";
8
+ import {
9
+ wizard_clamp_index,
10
+ wizard_next_index,
11
+ wizard_prev_index,
12
+ wizard_step_model,
13
+ wizard_accumulate,
14
+ wizard_should_validate,
15
+ } from "./wizard_helpers.js";
16
+
17
+
18
+ /*============================================================
19
+ * clamp / next / prev
20
+ *============================================================*/
21
+ test("clamp: negative -> 0, overflow -> count-1, empty -> 0", () => {
22
+ expect(wizard_clamp_index(-3, 4)).toBe(0);
23
+ expect(wizard_clamp_index(9, 4)).toBe(3);
24
+ expect(wizard_clamp_index(2, 4)).toBe(2);
25
+ expect(wizard_clamp_index(0, 0)).toBe(0);
26
+ });
27
+
28
+ test("next/prev never wrap", () => {
29
+ expect(wizard_next_index(0, 3)).toBe(1);
30
+ expect(wizard_next_index(2, 3)).toBe(2); // already last
31
+ expect(wizard_prev_index(0, 3)).toBe(0); // already first
32
+ expect(wizard_prev_index(2, 3)).toBe(1);
33
+ });
34
+
35
+
36
+ /*============================================================
37
+ * wizard_step_model
38
+ *============================================================*/
39
+ const STEPS = [
40
+ { id: "a", title: "Step A" },
41
+ { id: "b", title: "Step B" },
42
+ { id: "c", title: "Step C" },
43
+ ];
44
+
45
+ test("first step: is_first, back hidden, primary='next'", () => {
46
+ const m = wizard_step_model(STEPS, 0, {
47
+ allow_back: true, confirm_label: "confirm", next_label: "next",
48
+ });
49
+ expect(m.idx).toBe(0);
50
+ expect(m.count).toBe(3);
51
+ expect(m.id).toBe("a");
52
+ expect(m.is_first).toBe(true);
53
+ expect(m.is_last).toBe(false);
54
+ expect(m.show_back).toBe(false); // first step, even if allow_back
55
+ expect(m.primary_label).toBe("next");
56
+ });
57
+
58
+ test("middle step: back shown when allow_back", () => {
59
+ expect(wizard_step_model(STEPS, 1, { allow_back: true }).show_back).toBe(true);
60
+ expect(wizard_step_model(STEPS, 1, { allow_back: false }).show_back).toBe(false);
61
+ });
62
+
63
+ test("last step: is_last, primary='confirm'", () => {
64
+ const m = wizard_step_model(STEPS, 2, {
65
+ allow_back: true, confirm_label: "confirm", next_label: "next",
66
+ });
67
+ expect(m.is_last).toBe(true);
68
+ expect(m.primary_label).toBe("confirm");
69
+ expect(m.title).toBe("Step C");
70
+ });
71
+
72
+ test("out-of-range idx is clamped by the model", () => {
73
+ const m = wizard_step_model(STEPS, 99, {});
74
+ expect(m.idx).toBe(2);
75
+ expect(m.is_last).toBe(true);
76
+ });
77
+
78
+ test("default labels when opts omitted", () => {
79
+ const m = wizard_step_model(STEPS, 0, {});
80
+ expect(m.primary_label).toBe("next");
81
+ const last = wizard_step_model(STEPS, 2, {});
82
+ expect(last.primary_label).toBe("confirm");
83
+ });
84
+
85
+
86
+ /*============================================================
87
+ * wizard_accumulate (pure, immutable)
88
+ *============================================================*/
89
+ test("accumulate merges flat and keeps per-step, no mutation", () => {
90
+ const a1 = wizard_accumulate(null, "a", { x: 1 });
91
+ const a2 = wizard_accumulate(a1, "b", { y: 2 });
92
+ expect(a2.merged).toEqual({ x: 1, y: 2 });
93
+ expect(a2.by_step).toEqual({ a: { x: 1 }, b: { y: 2 } });
94
+ // a1 untouched
95
+ expect(a1.merged).toEqual({ x: 1 });
96
+ expect(a1.by_step).toEqual({ a: { x: 1 } });
97
+ });
98
+
99
+ test("accumulate: later step overrides merged key but keeps by_step", () => {
100
+ const a1 = wizard_accumulate(null, "a", { v: "first" });
101
+ const a2 = wizard_accumulate(a1, "b", { v: "second" });
102
+ expect(a2.merged.v).toBe("second");
103
+ expect(a2.by_step.a.v).toBe("first");
104
+ expect(a2.by_step.b.v).toBe("second");
105
+ });
106
+
107
+ test("accumulate tolerates missing kw", () => {
108
+ const a = wizard_accumulate(null, "a");
109
+ expect(a.merged).toEqual({});
110
+ expect(a.by_step).toEqual({ a: {} });
111
+ });
112
+
113
+
114
+ /*============================================================
115
+ * wizard_should_validate
116
+ *============================================================*/
117
+ test("validate only when linear AND step has a gobj", () => {
118
+ expect(wizard_should_validate(true, true)).toBe(true);
119
+ expect(wizard_should_validate(true, false)).toBe(false);
120
+ expect(wizard_should_validate(false, true)).toBe(false);
121
+ expect(wizard_should_validate(false, false)).toBe(false);
122
+ });