@jsenv/navi 0.0.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.
- package/index.js +51 -0
- package/package.json +38 -0
- package/src/action_private_properties.js +11 -0
- package/src/action_proxy_test.html +353 -0
- package/src/action_run_states.js +5 -0
- package/src/actions.js +1377 -0
- package/src/browser_integration/browser_integration.js +191 -0
- package/src/browser_integration/document_back_and_forward.js +17 -0
- package/src/browser_integration/document_loading_signal.js +100 -0
- package/src/browser_integration/document_state_signal.js +9 -0
- package/src/browser_integration/document_url_signal.js +9 -0
- package/src/browser_integration/use_is_visited.js +19 -0
- package/src/browser_integration/via_history.js +199 -0
- package/src/browser_integration/via_navigation.js +168 -0
- package/src/components/action_execution/form_context.js +8 -0
- package/src/components/action_execution/render_actionable_component.jsx +27 -0
- package/src/components/action_execution/use_action.js +330 -0
- package/src/components/action_execution/use_execute_action.js +161 -0
- package/src/components/action_renderer.jsx +136 -0
- package/src/components/collect_form_element_values.js +79 -0
- package/src/components/demos/0_button_demo.html +155 -0
- package/src/components/demos/1_checkbox_demo.html +257 -0
- package/src/components/demos/2_input_textual_demo.html +354 -0
- package/src/components/demos/3_radio_demo.html +222 -0
- package/src/components/demos/4_select_demo.html +104 -0
- package/src/components/demos/5_list_scrollable_demo.html +153 -0
- package/src/components/demos/action/0_button_demo.html +204 -0
- package/src/components/demos/action/10_shortcuts_demo.html +189 -0
- package/src/components/demos/action/11_nested_shortcuts_demo.html +401 -0
- package/src/components/demos/action/1_input_text_demo.html +461 -0
- package/src/components/demos/action/2_form_multiple.html +303 -0
- package/src/components/demos/action/3_details_demo.html +172 -0
- package/src/components/demos/action/4_input_checkbox_demo.html +611 -0
- package/src/components/demos/action/6_checkbox_list_demo.html +109 -0
- package/src/components/demos/action/7_radio_list_demo.html +217 -0
- package/src/components/demos/action/8_editable_text_demo.html +442 -0
- package/src/components/demos/action/9_link_demo.html +172 -0
- package/src/components/demos/demo.md +0 -0
- package/src/components/demos/route/basic/basic.html +14 -0
- package/src/components/demos/route/basic/basic_route_demo.jsx +224 -0
- package/src/components/demos/route/multi/multi.html +14 -0
- package/src/components/demos/route/multi/multi_route_demo.jsx +277 -0
- package/src/components/details/details.jsx +248 -0
- package/src/components/details/summary_marker.jsx +141 -0
- package/src/components/editable_text/editable_text.jsx +96 -0
- package/src/components/error_boundary_context.js +9 -0
- package/src/components/form.jsx +144 -0
- package/src/components/input/button.jsx +333 -0
- package/src/components/input/checkbox_list.jsx +294 -0
- package/src/components/input/field.jsx +61 -0
- package/src/components/input/field_css.js +118 -0
- package/src/components/input/input.jsx +15 -0
- package/src/components/input/input_checkbox.jsx +370 -0
- package/src/components/input/input_radio.jsx +299 -0
- package/src/components/input/input_textual.jsx +338 -0
- package/src/components/input/radio_list.jsx +283 -0
- package/src/components/input/select.jsx +273 -0
- package/src/components/input/use_form_event.js +20 -0
- package/src/components/input/use_on_change.js +12 -0
- package/src/components/link/link.jsx +291 -0
- package/src/components/loader/loader_background.jsx +324 -0
- package/src/components/loader/loading_spinner.jsx +68 -0
- package/src/components/loader/network_speed.js +83 -0
- package/src/components/loader/rectangle_loading.jsx +225 -0
- package/src/components/route.jsx +15 -0
- package/src/components/selection/selection.js +5 -0
- package/src/components/selection/selection_context.jsx +262 -0
- package/src/components/shortcut/os.js +9 -0
- package/src/components/shortcut/shortcut_context.jsx +390 -0
- package/src/components/use_action_events.js +37 -0
- package/src/components/use_auto_focus.js +43 -0
- package/src/components/use_debounce_true.js +31 -0
- package/src/components/use_focus_group.js +19 -0
- package/src/components/use_initial_value.js +104 -0
- package/src/components/use_is_visited.js +19 -0
- package/src/components/use_ref_array.js +38 -0
- package/src/components/use_signal_sync.js +50 -0
- package/src/components/use_state_array.js +40 -0
- package/src/docs/actions.md +228 -0
- package/src/docs/demos/resource/action_status.jsx +42 -0
- package/src/docs/demos/resource/demo.md +1 -0
- package/src/docs/demos/resource/resource_demo_0.html +84 -0
- package/src/docs/demos/resource/resource_demo_10_post_gc.html +364 -0
- package/src/docs/demos/resource/resource_demo_11_describe_many.html +362 -0
- package/src/docs/demos/resource/resource_demo_2.html +173 -0
- package/src/docs/demos/resource/resource_demo_3_filtered_users.html +415 -0
- package/src/docs/demos/resource/resource_demo_4_details.html +284 -0
- package/src/docs/demos/resource/resource_demo_5_renderer_lazy.html +115 -0
- package/src/docs/demos/resource/resource_demo_6_gc.html +217 -0
- package/src/docs/demos/resource/resource_demo_7_child_gc.html +240 -0
- package/src/docs/demos/resource/resource_demo_8_proxy_gc.html +319 -0
- package/src/docs/demos/resource/resource_demo_9_describe_one.html +472 -0
- package/src/docs/demos/resource/tata.jsx +3 -0
- package/src/docs/demos/resource/toto.jsx +3 -0
- package/src/docs/demos/user_nav/user_nav.html +12 -0
- package/src/docs/demos/user_nav/user_nav.jsx +330 -0
- package/src/docs/resource_dependencies.md +103 -0
- package/src/docs/resource_with_params.md +80 -0
- package/src/notes.md +13 -0
- package/src/route/route.js +518 -0
- package/src/route/route.test.html +228 -0
- package/src/store/array_signal_store.js +537 -0
- package/src/store/local_storage_signal.js +17 -0
- package/src/store/resource_graph.js +1303 -0
- package/src/store/tests/resource_graph_autoreload_demo.html +12 -0
- package/src/store/tests/resource_graph_autoreload_demo.jsx +964 -0
- package/src/store/tests/resource_graph_dependencies.test.js +95 -0
- package/src/store/value_in_local_storage.js +187 -0
- package/src/symbol_object_signal.js +1 -0
- package/src/use_action_data.js +10 -0
- package/src/use_action_status.js +47 -0
- package/src/utils/add_many_event_listeners.js +15 -0
- package/src/utils/array_add_remove.js +61 -0
- package/src/utils/array_signal.js +15 -0
- package/src/utils/compare_two_js_values.js +172 -0
- package/src/utils/execute_with_cleanup.js +21 -0
- package/src/utils/get_caller_info.js +85 -0
- package/src/utils/iterable_weak_set.js +62 -0
- package/src/utils/js_value_weak_map.js +162 -0
- package/src/utils/js_value_weak_map_demo.html +690 -0
- package/src/utils/merge_two_js_values.js +53 -0
- package/src/utils/stringify_for_display.js +150 -0
- package/src/utils/weak_effect.js +48 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Route test</title>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
<link rel="icon" href="data:," />
|
|
7
|
+
</head>
|
|
8
|
+
|
|
9
|
+
<body>
|
|
10
|
+
<script type="module">
|
|
11
|
+
import { assert } from "@jsenv/assert";
|
|
12
|
+
import { createRoute } from "./route.js";
|
|
13
|
+
import { updateDocumentUrl } from "../browser_integration/document_url_signal.js";
|
|
14
|
+
|
|
15
|
+
assert.colors = false;
|
|
16
|
+
|
|
17
|
+
const test = (description, callback) => {
|
|
18
|
+
console.log(`Running test: ${description}`);
|
|
19
|
+
callback();
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
test("buildUrl with named parameters", () => {
|
|
23
|
+
const route = createRoute("/user/:id/profile/:section");
|
|
24
|
+
const url = route.buildUrl({ id: "123", section: "settings" });
|
|
25
|
+
const expect = `${window.location.origin}/user/123/profile/settings`;
|
|
26
|
+
|
|
27
|
+
assert({
|
|
28
|
+
actual: url,
|
|
29
|
+
expect,
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("buildUrl with curly brace parameters", () => {
|
|
34
|
+
const route = createRoute("/api/{version}/user/{id}");
|
|
35
|
+
const url = route.buildUrl({ version: "v1", id: "456" });
|
|
36
|
+
const expected = `${window.location.origin}/api/v1/user/456`;
|
|
37
|
+
|
|
38
|
+
assert({
|
|
39
|
+
actual: url,
|
|
40
|
+
expect: expected,
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("buildUrl with wildcards and numbered parameters", () => {
|
|
45
|
+
const route = createRoute("/*/user/:name/*");
|
|
46
|
+
const url = route.buildUrl({ 0: "admin", name: "dam", 1: "profile" });
|
|
47
|
+
const expected = `${window.location.origin}/admin/user/dam/profile`;
|
|
48
|
+
|
|
49
|
+
assert({
|
|
50
|
+
actual: url,
|
|
51
|
+
expect: expected,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("buildUrl with only wildcards", () => {
|
|
56
|
+
const route = createRoute("/*/*/data");
|
|
57
|
+
const url = route.buildUrl({ 0: "api", 1: "v2" });
|
|
58
|
+
const expected = `${window.location.origin}/api/v2/data`;
|
|
59
|
+
|
|
60
|
+
assert({
|
|
61
|
+
actual: url,
|
|
62
|
+
expect: expected,
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("buildUrl with missing parameters leaves wildcards", () => {
|
|
67
|
+
const route = createRoute("/*/user/:name/*");
|
|
68
|
+
const url = route.buildUrl({ name: "dam" });
|
|
69
|
+
const expected = `${window.location.origin}/*/user/dam/*`;
|
|
70
|
+
|
|
71
|
+
assert({
|
|
72
|
+
actual: url,
|
|
73
|
+
expect: expected,
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("buildUrl with URLPattern object", () => {
|
|
78
|
+
const route = createRoute("/blog/:slug/comments");
|
|
79
|
+
const url = route.buildUrl({ slug: "hello-world" });
|
|
80
|
+
const expected = `${window.location.origin}/blog/hello-world/comments`;
|
|
81
|
+
|
|
82
|
+
assert({
|
|
83
|
+
actual: url,
|
|
84
|
+
expect: expected,
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("buildUrl with special characters in parameters", () => {
|
|
89
|
+
const route = createRoute("/search/:query");
|
|
90
|
+
const url = route.buildUrl({ query: "hello world & more" });
|
|
91
|
+
const expected = `${window.location.origin}/search/hello%20world%20%26%20more`;
|
|
92
|
+
|
|
93
|
+
assert({
|
|
94
|
+
actual: url,
|
|
95
|
+
expect: expected,
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("buildUrl with no parameters", () => {
|
|
100
|
+
const route = createRoute("/static/page");
|
|
101
|
+
const url = route.buildUrl();
|
|
102
|
+
const expected = `${window.location.origin}/static/page`;
|
|
103
|
+
|
|
104
|
+
assert({
|
|
105
|
+
actual: url,
|
|
106
|
+
expect: expected,
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("buildUrl with empty parameters object", () => {
|
|
111
|
+
const route = createRoute("/home");
|
|
112
|
+
const url = route.buildUrl({});
|
|
113
|
+
const expected = `${window.location.origin}/home`;
|
|
114
|
+
|
|
115
|
+
assert({
|
|
116
|
+
actual: url,
|
|
117
|
+
expect: expected,
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("buildUrl with mixed parameter types", () => {
|
|
122
|
+
const route = createRoute("/*/api/:version/user/{id}/*");
|
|
123
|
+
const url = route.buildUrl({
|
|
124
|
+
0: "public",
|
|
125
|
+
version: "v1",
|
|
126
|
+
id: "123",
|
|
127
|
+
1: "settings",
|
|
128
|
+
});
|
|
129
|
+
const expected = `${window.location.origin}/public/api/v1/user/123/settings`;
|
|
130
|
+
|
|
131
|
+
assert({
|
|
132
|
+
actual: url,
|
|
133
|
+
expect: expected,
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("buildUrl with param in search", () => {
|
|
138
|
+
const route = createRoute("/before/:id/after?name=:name");
|
|
139
|
+
const url = route.buildUrl({
|
|
140
|
+
id: "123",
|
|
141
|
+
name: "dam",
|
|
142
|
+
});
|
|
143
|
+
const expected = `${window.location.origin}/before/123/after?name=dam`;
|
|
144
|
+
|
|
145
|
+
assert({
|
|
146
|
+
actual: url,
|
|
147
|
+
expect: expected,
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
// Wildcard parameter extraction tests
|
|
152
|
+
test("paramsSignal extracts single wildcard parameter", () => {
|
|
153
|
+
const route = createRoute("/*/data");
|
|
154
|
+
updateDocumentUrl(new URL("/users/data", window.location.origin));
|
|
155
|
+
const params = route.paramsSignal.value;
|
|
156
|
+
|
|
157
|
+
assert({
|
|
158
|
+
actual: params,
|
|
159
|
+
expect: { 0: "users" },
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test("paramsSignal extracts multiple wildcard parameters", () => {
|
|
164
|
+
const route = createRoute("/*/*/data");
|
|
165
|
+
updateDocumentUrl(new URL("/api/v1/data", window.location.origin));
|
|
166
|
+
const params = route.paramsSignal.value;
|
|
167
|
+
|
|
168
|
+
assert({
|
|
169
|
+
actual: params,
|
|
170
|
+
expect: { 0: "api", 1: "v1" },
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("paramsSignal mixes wildcards and named parameters", () => {
|
|
175
|
+
const route = createRoute("/*/user/:id/*");
|
|
176
|
+
updateDocumentUrl(
|
|
177
|
+
new URL("/admin/user/123/edit", window.location.origin),
|
|
178
|
+
);
|
|
179
|
+
const params = route.paramsSignal.value;
|
|
180
|
+
|
|
181
|
+
assert({
|
|
182
|
+
actual: params,
|
|
183
|
+
expect: { 0: "admin", id: "123", 1: "edit" },
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test("paramsSignal handles wildcards in search params", () => {
|
|
188
|
+
const route = createRoute("/data?type=*&format=*");
|
|
189
|
+
updateDocumentUrl(
|
|
190
|
+
new URL("/data?type=json&format=csv", window.location.origin),
|
|
191
|
+
);
|
|
192
|
+
const params = route.paramsSignal.value;
|
|
193
|
+
|
|
194
|
+
assert({
|
|
195
|
+
actual: params,
|
|
196
|
+
expect: { 0: "json", 1: "csv" },
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("paramsSignal ignores empty wildcard values", () => {
|
|
201
|
+
const route = createRoute("/*/data/*");
|
|
202
|
+
updateDocumentUrl(new URL("//data/", window.location.origin));
|
|
203
|
+
const params = route.paramsSignal.value;
|
|
204
|
+
|
|
205
|
+
// Should only return non-empty values
|
|
206
|
+
assert({
|
|
207
|
+
actual: params,
|
|
208
|
+
expect: {},
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test("paramsSignal handles URL-encoded wildcard values", () => {
|
|
213
|
+
const route = createRoute("/search/*");
|
|
214
|
+
updateDocumentUrl(
|
|
215
|
+
new URL("/search/hello%20world", window.location.origin),
|
|
216
|
+
);
|
|
217
|
+
const params = route.paramsSignal.value;
|
|
218
|
+
|
|
219
|
+
assert({
|
|
220
|
+
actual: params,
|
|
221
|
+
expect: { 0: "hello world" },
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
console.log("All tests completed successfully.");
|
|
226
|
+
</script>
|
|
227
|
+
</body>
|
|
228
|
+
</html>
|