@jsenv/navi 0.0.1 → 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 (139) hide show
  1. package/dist/jsenv_navi.js +22959 -0
  2. package/index.js +66 -16
  3. package/package.json +23 -11
  4. package/src/actions.js +50 -26
  5. package/src/browser_integration/browser_integration.js +31 -6
  6. package/src/browser_integration/via_history.js +42 -9
  7. package/src/components/action_execution/render_actionable_component.jsx +6 -4
  8. package/src/components/action_execution/use_action.js +51 -282
  9. package/src/components/action_execution/use_execute_action.js +106 -92
  10. package/src/components/action_execution/use_run_on_mount.js +9 -0
  11. package/src/components/action_renderer.jsx +21 -32
  12. package/src/components/demos/0_button_demo.html +574 -103
  13. package/src/components/demos/10_column_reordering_debug.html +277 -0
  14. package/src/components/demos/11_table_selection_debug.html +432 -0
  15. package/src/components/demos/1_checkbox_demo.html +579 -202
  16. package/src/components/demos/2_input_textual_demo.html +81 -138
  17. package/src/components/demos/3_radio_demo.html +0 -2
  18. package/src/components/demos/4_select_demo.html +19 -23
  19. package/src/components/demos/6_tablist_demo.html +77 -0
  20. package/src/components/demos/7_table_selection_demo.html +176 -0
  21. package/src/components/demos/8_table_fixed_headers_demo.html +584 -0
  22. package/src/components/demos/9_table_column_drag_demo.html +325 -0
  23. package/src/components/demos/action/0_button_demo.html +2 -4
  24. package/src/components/demos/action/1_input_text_demo.html +643 -222
  25. package/src/components/demos/action/3_details_demo.html +146 -115
  26. package/src/components/demos/action/4_input_checkbox_demo.html +442 -322
  27. package/src/components/demos/action/5_input_checkbox_state_demo.html +270 -0
  28. package/src/components/demos/action/6_checkbox_list_demo.html +304 -72
  29. package/src/components/demos/action/7_radio_list_demo.html +310 -170
  30. package/src/components/demos/action/{8_editable_text_demo.html → 8_editable_demo.html} +65 -76
  31. package/src/components/demos/action/9_link_demo.html +84 -62
  32. package/src/components/demos/ui_transition/0_action_renderer_ui_transition_demo.html +695 -0
  33. package/src/components/demos/ui_transition/1_nested_ui_transition_demo.html +429 -0
  34. package/src/components/demos/ui_transition/2_height_transition_test.html +295 -0
  35. package/src/components/details/details.jsx +62 -64
  36. package/src/components/edition/editable.jsx +186 -0
  37. package/src/components/field/README.md +247 -0
  38. package/src/components/{input → field}/button.jsx +151 -130
  39. package/src/components/field/checkbox_list.jsx +184 -0
  40. package/src/components/{collect_form_element_values.js → field/collect_form_element_values.js} +7 -4
  41. package/src/components/{input → field}/field_css.js +4 -1
  42. package/src/components/field/form.jsx +211 -0
  43. package/src/components/{input → field}/input.jsx +1 -0
  44. package/src/components/{input → field}/input_checkbox.jsx +132 -155
  45. package/src/components/{input → field}/input_radio.jsx +135 -46
  46. package/src/components/field/input_textual.jsx +418 -0
  47. package/src/components/field/label.jsx +32 -0
  48. package/src/components/field/radio_list.jsx +182 -0
  49. package/src/components/{input → field}/select.jsx +17 -32
  50. package/src/components/field/use_action_events.js +132 -0
  51. package/src/components/field/use_form_events.js +55 -0
  52. package/src/components/field/use_ui_state_controller.js +506 -0
  53. package/src/components/item_tracker/README.md +461 -0
  54. package/src/components/item_tracker/use_isolated_item_tracker.jsx +209 -0
  55. package/src/components/item_tracker/use_isolated_item_tracker_demo.html +148 -0
  56. package/src/components/item_tracker/use_isolated_item_tracker_demo.jsx +460 -0
  57. package/src/components/item_tracker/use_item_tracker.jsx +143 -0
  58. package/src/components/item_tracker/use_item_tracker_demo.html +207 -0
  59. package/src/components/item_tracker/use_item_tracker_demo.jsx +216 -0
  60. package/src/components/keyboard_shortcuts/active_keyboard_shortcuts.jsx +87 -0
  61. package/src/components/keyboard_shortcuts/aria_key_shortcuts.js +61 -0
  62. package/src/components/keyboard_shortcuts/keyboard_key_meta.js +17 -0
  63. package/src/components/keyboard_shortcuts/keyboard_shortcuts.js +371 -0
  64. package/src/components/link/link.jsx +65 -102
  65. package/src/components/link/link_with_icon.jsx +52 -0
  66. package/src/components/loader/loader_background.jsx +85 -64
  67. package/src/components/loader/rectangle_loading.jsx +38 -19
  68. package/src/components/route.jsx +8 -4
  69. package/src/components/selection/selection.jsx +1583 -0
  70. package/src/components/svg/font_sized_svg.jsx +45 -0
  71. package/src/components/svg/icon_and_text.jsx +21 -0
  72. package/src/components/svg/svg_mask_overlay.jsx +105 -0
  73. package/src/components/table/drag/table_drag.jsx +506 -0
  74. package/src/components/table/resize/table_resize.jsx +650 -0
  75. package/src/components/table/resize/table_size.js +43 -0
  76. package/src/components/table/selection/table_selection.js +106 -0
  77. package/src/components/table/selection/table_selection.jsx +203 -0
  78. package/src/components/table/sticky/sticky_group.js +354 -0
  79. package/src/components/table/sticky/table_sticky.js +25 -0
  80. package/src/components/table/sticky/table_sticky.jsx +501 -0
  81. package/src/components/table/table.jsx +721 -0
  82. package/src/components/table/table_css.js +211 -0
  83. package/src/components/table/table_ui.jsx +49 -0
  84. package/src/components/table/use_cells_and_columns.js +90 -0
  85. package/src/components/table/use_object_array_to_cells.js +46 -0
  86. package/src/components/table/z_indexes.js +23 -0
  87. package/src/components/tablist/tablist.jsx +99 -0
  88. package/src/components/text/overflow.jsx +15 -0
  89. package/src/components/text/text_and_count.jsx +28 -0
  90. package/src/components/ui_transition.jsx +128 -0
  91. package/src/components/use_auto_focus.js +58 -7
  92. package/src/components/use_batch_during_render.js +33 -0
  93. package/src/components/use_debounce_true.js +7 -7
  94. package/src/components/use_dependencies_diff.js +35 -0
  95. package/src/components/use_focus_group.js +4 -3
  96. package/src/components/use_initial_value.js +8 -34
  97. package/src/components/use_signal_sync.js +1 -1
  98. package/src/components/use_stable_callback.js +68 -0
  99. package/src/components/use_state_array.js +16 -9
  100. package/src/docs/actions.md +22 -0
  101. package/src/notes.md +33 -12
  102. package/src/route/route.js +97 -47
  103. package/src/store/resource_graph.js +2 -1
  104. package/src/store/tests/{resource_graph_dependencies.test.js → resource_graph_dependencies.test_manual.js} +13 -13
  105. package/src/utils/is_signal.js +20 -0
  106. package/src/utils/stringify_for_display.js +4 -23
  107. package/src/validation/constraints/confirm_constraint.js +14 -0
  108. package/src/validation/constraints/create_unique_value_constraint.js +27 -0
  109. package/src/validation/constraints/native_constraints.js +313 -0
  110. package/src/validation/constraints/readonly_constraint.js +36 -0
  111. package/src/validation/constraints/single_space_constraint.js +13 -0
  112. package/src/validation/custom_constraint_validation.js +599 -0
  113. package/src/validation/custom_message.js +18 -0
  114. package/src/validation/demos/browser_style.png +0 -0
  115. package/src/validation/demos/form_validation_demo.html +142 -0
  116. package/src/validation/demos/form_validation_demo_preact.html +87 -0
  117. package/src/validation/demos/form_validation_native_popover_demo.html +168 -0
  118. package/src/validation/demos/form_validation_vs_native_demo.html +172 -0
  119. package/src/validation/demos/validation_message_demo.html +203 -0
  120. package/src/validation/hooks/use_constraints.js +23 -0
  121. package/src/validation/hooks/use_custom_validation_ref.js +73 -0
  122. package/src/validation/hooks/use_validation_message.js +19 -0
  123. package/src/validation/validation_message.js +741 -0
  124. package/src/components/editable_text/editable_text.jsx +0 -96
  125. package/src/components/form.jsx +0 -144
  126. package/src/components/input/checkbox_list.jsx +0 -294
  127. package/src/components/input/field.jsx +0 -61
  128. package/src/components/input/input_textual.jsx +0 -338
  129. package/src/components/input/radio_list.jsx +0 -283
  130. package/src/components/input/use_form_event.js +0 -20
  131. package/src/components/input/use_on_change.js +0 -12
  132. package/src/components/selection/selection.js +0 -5
  133. package/src/components/selection/selection_context.jsx +0 -262
  134. package/src/components/shortcut/shortcut_context.jsx +0 -390
  135. package/src/components/use_action_events.js +0 -37
  136. package/src/utils/iterable_weak_set.js +0 -62
  137. /package/src/components/demos/action/{11_nested_shortcuts_demo.html → 11_nested_shortcuts_demo.xhtml} +0 -0
  138. /package/src/components/{shortcut → keyboard_shortcuts}/os.js +0 -0
  139. /package/src/route/{route.test.html → route.xtest.html} +0 -0
@@ -0,0 +1,203 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>Simple Validation Message Demo</title>
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <meta charset="utf-8" />
7
+ <link rel="icon" href="data:," />
8
+ <style>
9
+ body {
10
+ margin: 0;
11
+ padding: 20px;
12
+ font-family: Arial, sans-serif;
13
+ background: linear-gradient(45deg, #f0f8ff, #e6f3ff);
14
+ min-height: 300vh; /* Make page scrollable */
15
+ }
16
+
17
+ .container {
18
+ max-width: 800px;
19
+ margin: 0 auto;
20
+ }
21
+
22
+ .section {
23
+ margin: 40px 0;
24
+ padding: 20px;
25
+ background: white;
26
+ border-radius: 8px;
27
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
28
+ }
29
+
30
+ .target-element {
31
+ display: inline-block;
32
+ padding: 12px 20px;
33
+ background: #4caf50;
34
+ color: white;
35
+ border: none;
36
+ border-radius: 4px;
37
+ cursor: pointer;
38
+ margin: 10px;
39
+ font-size: 16px;
40
+ }
41
+
42
+ .target-element:hover {
43
+ background: #45a049;
44
+ }
45
+
46
+ .spacer {
47
+ height: 200px;
48
+ background: repeating-linear-gradient(
49
+ 45deg,
50
+ transparent,
51
+ transparent 20px,
52
+ rgba(0, 0, 0, 0.1) 20px,
53
+ rgba(0, 0, 0, 0.1) 40px
54
+ );
55
+ margin: 40px 0;
56
+ display: flex;
57
+ align-items: center;
58
+ justify-content: center;
59
+ color: #666;
60
+ font-weight: bold;
61
+ font-size: 18px;
62
+ }
63
+
64
+ .scroll-instruction {
65
+ position: fixed;
66
+ top: 10px;
67
+ right: 10px;
68
+ background: #333;
69
+ color: white;
70
+ padding: 10px;
71
+ border-radius: 4px;
72
+ font-size: 14px;
73
+ z-index: 1000;
74
+ }
75
+
76
+ .scrollable-container {
77
+ height: 300px;
78
+ width: 100%;
79
+ overflow: auto;
80
+ border: 2px solid #ddd;
81
+ border-radius: 8px;
82
+ background: #f9f9f9;
83
+ padding: 20px;
84
+ }
85
+
86
+ .scrollable-content {
87
+ height: 600px;
88
+ width: 800px;
89
+ display: flex;
90
+ flex-direction: column;
91
+ justify-content: space-around;
92
+ align-items: center;
93
+ background: repeating-linear-gradient(
94
+ 45deg,
95
+ transparent,
96
+ transparent 30px,
97
+ rgba(0, 0, 255, 0.1) 30px,
98
+ rgba(0, 0, 255, 0.1) 60px
99
+ );
100
+ }
101
+ </style>
102
+ </head>
103
+ <body>
104
+ <div class="scroll-instruction">
105
+ Scroll to test validation message positioning
106
+ </div>
107
+
108
+ <div class="container">
109
+ <h1>Simple Validation Message Demo</h1>
110
+ <p>
111
+ This demo shows how the validation message follows its target element
112
+ during scrolling.
113
+ </p>
114
+
115
+ <div class="section">
116
+ <h2>Auto-opened Validation Message</h2>
117
+ <p>This validation message opens automatically when the page loads:</p>
118
+ <p>
119
+ <strong
120
+ >Scroll inside the container below to test positioning within a
121
+ scrollable parent:</strong
122
+ >
123
+ </p>
124
+ <div class="scrollable-container">
125
+ <div class="scrollable-content">
126
+ <div>Top of scrollable area</div>
127
+ <button id="auto-target" class="target-element">
128
+ Target Element (Auto-opened message)
129
+ </button>
130
+ <div>Bottom of scrollable area</div>
131
+ </div>
132
+ </div>
133
+ </div>
134
+
135
+ <div class="spacer">
136
+ Scroll Area 1 - Keep scrolling to test positioning
137
+ </div>
138
+
139
+ <div class="section">
140
+ <h2>Middle Section</h2>
141
+ <p>
142
+ The validation message should follow the target element as you scroll
143
+ past this section.
144
+ </p>
145
+ </div>
146
+
147
+ <div class="spacer">Scroll Area 2 - More scrolling space</div>
148
+
149
+ <div class="section">
150
+ <h2>Another Section</h2>
151
+ <p>
152
+ Continue scrolling to test the message positioning at different scroll
153
+ positions.
154
+ </p>
155
+ </div>
156
+
157
+ <div class="spacer">Scroll Area 3 - Bottom section</div>
158
+
159
+ <div class="section">
160
+ <h2>Final Section</h2>
161
+ <p>Scroll back up to see how the validation message behaves.</p>
162
+ </div>
163
+
164
+ <div
165
+ style="
166
+ height: 50vh;
167
+ background: #f0f0f0;
168
+ display: flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+ margin-top: 40px;
172
+ "
173
+ >
174
+ <p>Bottom spacer - scroll back up to see validation messages</p>
175
+ </div>
176
+ </div>
177
+
178
+ <script type="module">
179
+ import { openValidationMessage } from "../validation_message.js";
180
+
181
+ // Auto-open validation message on page load
182
+ window.addEventListener("load", () => {
183
+ const autoTarget = document.getElementById("auto-target");
184
+ openValidationMessage(
185
+ autoTarget,
186
+ `This is a very long validation message that was opened automatically when the page loaded. <strong>Try scrolling both horizontally and vertically</strong> within the container to see how the validation message follows the target element! This message is intentionally made very long to test how the positioning system handles messages that exceed the visible area of their container. The message should properly position itself even when parts of it would normally be clipped by the container boundaries. You can scroll in any direction - up, down, left, right - to test the robustness of the positioning algorithm. This lengthy content helps verify that the validation message system can handle edge cases where the message content is larger than the available viewport space within scrollable containers.`,
187
+ {
188
+ level: "warning",
189
+ debug: true,
190
+ canClickThrough: true,
191
+ onClose: () => {
192
+ console.log("Validation message was closed");
193
+ },
194
+ },
195
+ );
196
+ });
197
+
198
+ console.log(
199
+ "Simple validation message demo loaded. Check console for debug output.",
200
+ );
201
+ </script>
202
+ </body>
203
+ </html>
@@ -0,0 +1,23 @@
1
+ import { useLayoutEffect } from "preact/hooks";
2
+
3
+ import { useCustomValidationRef } from "./use_custom_validation_ref.js";
4
+
5
+ export const useConstraints = (elementRef, constraints, targetSelector) => {
6
+ const customValidationRef = useCustomValidationRef(
7
+ elementRef,
8
+ targetSelector,
9
+ );
10
+ useLayoutEffect(() => {
11
+ const customValidation = customValidationRef.current;
12
+ const cleanupCallbackSet = new Set();
13
+ for (const constraint of constraints) {
14
+ const unregister = customValidation.registerConstraint(constraint);
15
+ cleanupCallbackSet.add(unregister);
16
+ }
17
+ return () => {
18
+ for (const cleanupCallback of cleanupCallbackSet) {
19
+ cleanupCallback();
20
+ }
21
+ };
22
+ }, constraints);
23
+ };
@@ -0,0 +1,73 @@
1
+ import { useLayoutEffect, useRef } from "preact/hooks";
2
+
3
+ import { installCustomConstraintValidation } from "../custom_constraint_validation.js";
4
+
5
+ export const useCustomValidationRef = (elementRef, targetSelector) => {
6
+ const customValidationRef = useRef();
7
+
8
+ useLayoutEffect(() => {
9
+ const element = elementRef.current;
10
+ if (!element) {
11
+ console.warn(
12
+ "useCustomValidationRef: elementRef.current is null, make sure to pass a ref to an element",
13
+ );
14
+ /* can happen if the component does this for instance:
15
+ const Component = () => {
16
+ const ref = useRef(null)
17
+
18
+ if (something) {
19
+ return <input ref={ref} />
20
+ }
21
+ return <span></span>
22
+ }
23
+
24
+ usually it's better to split the component in two but hey
25
+ */
26
+ return null;
27
+ }
28
+ let target;
29
+ if (targetSelector) {
30
+ target = element.querySelector(targetSelector);
31
+ if (!target) {
32
+ console.warn(
33
+ `useCustomValidationRef: targetSelector "${targetSelector}" did not match in element`,
34
+ );
35
+ return null;
36
+ }
37
+ } else {
38
+ target = element;
39
+ }
40
+ const unsubscribe = subscribe(element, target);
41
+ const validationInterface = element.__validationInterface__;
42
+ customValidationRef.current = validationInterface;
43
+ return () => {
44
+ unsubscribe();
45
+ };
46
+ }, [targetSelector]);
47
+
48
+ return customValidationRef;
49
+ };
50
+
51
+ const subscribeCountWeakMap = new WeakMap();
52
+ const subscribe = (element, target) => {
53
+ if (element.__validationInterface__) {
54
+ let subscribeCount = subscribeCountWeakMap.get(element);
55
+ subscribeCountWeakMap.set(element, subscribeCount + 1);
56
+ } else {
57
+ installCustomConstraintValidation(element, target);
58
+ subscribeCountWeakMap.set(element, 1);
59
+ }
60
+ return () => {
61
+ unsubscribe(element);
62
+ };
63
+ };
64
+
65
+ const unsubscribe = (element) => {
66
+ const subscribeCount = subscribeCountWeakMap.get(element);
67
+ if (subscribeCount === 1) {
68
+ element.__validationInterface__.uninstall();
69
+ subscribeCountWeakMap.delete(element);
70
+ } else {
71
+ subscribeCountWeakMap.set(element, subscribeCount - 1);
72
+ }
73
+ };
@@ -0,0 +1,19 @@
1
+ import { useCallback } from "preact/hooks";
2
+
3
+ import { useCustomValidationRef } from "./use_custom_validation_ref.js";
4
+
5
+ export const useValidationMessage = (inputRef, key, target, options = {}) => {
6
+ const customValidationRef = useCustomValidationRef(inputRef, target);
7
+
8
+ const addCustomMessage = useCallback(
9
+ (message) => {
10
+ customValidationRef.current.addCustomMessage(key, message, options);
11
+ },
12
+ [customValidationRef, key],
13
+ );
14
+ const removeCustomMessage = useCallback(() => {
15
+ customValidationRef.current.removeCustomMessage(key);
16
+ }, [customValidationRef, key]);
17
+
18
+ return [addCustomMessage, removeCustomMessage];
19
+ };