@jsenv/navi 0.10.2 → 0.11.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/dist/jsenv_navi.js +13838 -23291
- package/dist/jsenv_navi.js.map +1281 -0
- package/package.json +6 -8
- package/index.js +0 -122
- package/src/action_private_properties.js +0 -11
- package/src/action_proxy_test.html +0 -353
- package/src/action_run_states.js +0 -5
- package/src/actions.js +0 -1401
- package/src/browser_integration/browser_integration.js +0 -216
- package/src/browser_integration/document_back_and_forward.js +0 -17
- package/src/browser_integration/document_loading_signal.js +0 -100
- package/src/browser_integration/document_state_signal.js +0 -9
- package/src/browser_integration/document_url_signal.js +0 -9
- package/src/browser_integration/use_is_visited.js +0 -19
- package/src/browser_integration/via_history.js +0 -232
- package/src/browser_integration/via_navigation.js +0 -168
- package/src/components/action_execution/form_context.js +0 -5
- package/src/components/action_execution/render_actionable_component.jsx +0 -29
- package/src/components/action_execution/use_action.js +0 -99
- package/src/components/action_execution/use_execute_action.js +0 -193
- package/src/components/action_execution/use_run_on_mount.js +0 -9
- package/src/components/action_renderer.jsx +0 -125
- package/src/components/callout/callout.js +0 -990
- package/src/components/callout/callout_demo.html +0 -201
- package/src/components/callout/test_dynamic_positioning.html +0 -161
- package/src/components/callout/test_html_document_iframe.html +0 -182
- package/src/components/demos/0_button_demo.html +0 -707
- package/src/components/demos/10_column_reordering_debug.html +0 -277
- package/src/components/demos/11_table_selection_debug.html +0 -432
- package/src/components/demos/1_checkbox_demo.html +0 -754
- package/src/components/demos/2_input_textual_demo.html +0 -286
- package/src/components/demos/3_radio_demo.html +0 -874
- package/src/components/demos/4_select_demo.html +0 -100
- package/src/components/demos/5_list_scrollable_demo.html +0 -153
- package/src/components/demos/6_tablist_demo.html +0 -77
- package/src/components/demos/7_table_selection_demo.html +0 -176
- package/src/components/demos/8_table_fixed_headers_demo.html +0 -584
- package/src/components/demos/9_table_column_drag_demo.html +0 -325
- package/src/components/demos/action/0_button_demo.html +0 -204
- package/src/components/demos/action/10_shortcuts_demo.html +0 -189
- package/src/components/demos/action/11_nested_shortcuts_demo.xhtml +0 -401
- package/src/components/demos/action/1_input_text_demo.html +0 -876
- package/src/components/demos/action/2_form_multiple.html +0 -303
- package/src/components/demos/action/3_details_demo.html +0 -203
- package/src/components/demos/action/4_input_checkbox_demo.html +0 -731
- package/src/components/demos/action/5_input_checkbox_state_demo.html +0 -270
- package/src/components/demos/action/6_checkbox_list_demo.html +0 -341
- package/src/components/demos/action/7_radio_list_demo.html +0 -357
- package/src/components/demos/action/8_editable_demo.html +0 -431
- package/src/components/demos/action/9_link_demo.html +0 -194
- package/src/components/demos/demo.md +0 -0
- package/src/components/demos/route/basic/basic.html +0 -14
- package/src/components/demos/route/basic/basic_route_demo.jsx +0 -224
- package/src/components/demos/route/multi/multi.html +0 -14
- package/src/components/demos/route/multi/multi_route_demo.jsx +0 -277
- package/src/components/demos/ui_transition/0_action_renderer_ui_transition_demo.html +0 -695
- package/src/components/demos/ui_transition/1_nested_ui_transition_demo.html +0 -429
- package/src/components/demos/ui_transition/2_height_transition_test.html +0 -295
- package/src/components/details/details.jsx +0 -245
- package/src/components/details/summary_marker.jsx +0 -141
- package/src/components/edition/editable.jsx +0 -186
- package/src/components/error_boundary_context.js +0 -9
- package/src/components/field/README.md +0 -247
- package/src/components/field/button.jsx +0 -429
- package/src/components/field/checkbox_list.jsx +0 -185
- package/src/components/field/collect_form_element_values.js +0 -82
- package/src/components/field/custom_field.js +0 -106
- package/src/components/field/form.jsx +0 -209
- package/src/components/field/input.jsx +0 -16
- package/src/components/field/input_checkbox.jsx +0 -434
- package/src/components/field/input_radio.jsx +0 -432
- package/src/components/field/input_textual.jsx +0 -389
- package/src/components/field/label.jsx +0 -46
- package/src/components/field/radio_list.jsx +0 -183
- package/src/components/field/select.jsx +0 -256
- package/src/components/field/use_action_events.js +0 -132
- package/src/components/field/use_form_events.js +0 -59
- package/src/components/field/use_ui_state_controller.js +0 -506
- package/src/components/item_tracker/README.md +0 -461
- package/src/components/item_tracker/use_isolated_item_tracker.jsx +0 -209
- package/src/components/item_tracker/use_isolated_item_tracker_demo.html +0 -148
- package/src/components/item_tracker/use_isolated_item_tracker_demo.jsx +0 -460
- package/src/components/item_tracker/use_item_tracker.jsx +0 -143
- package/src/components/item_tracker/use_item_tracker_demo.html +0 -207
- package/src/components/item_tracker/use_item_tracker_demo.jsx +0 -216
- package/src/components/keyboard_shortcuts/active_keyboard_shortcuts.jsx +0 -87
- package/src/components/keyboard_shortcuts/aria_key_shortcuts.js +0 -61
- package/src/components/keyboard_shortcuts/keyboard_key_meta.js +0 -17
- package/src/components/keyboard_shortcuts/keyboard_shortcuts.js +0 -371
- package/src/components/keyboard_shortcuts/os.js +0 -9
- package/src/components/layout/demos/demo_flex.html +0 -638
- package/src/components/layout/demos/demo_layout_style_buttons.html +0 -351
- package/src/components/layout/demos/demo_layout_style_input.html +0 -226
- package/src/components/layout/demos/demo_layout_style_text.html +0 -514
- package/src/components/layout/flex.jsx +0 -109
- package/src/components/layout/layout_context.jsx +0 -3
- package/src/components/layout/spacing.jsx +0 -20
- package/src/components/layout/use_layout_style.js +0 -249
- package/src/components/link/link.jsx +0 -267
- package/src/components/link/link_with_icon.jsx +0 -52
- package/src/components/loader/loader_background.jsx +0 -372
- package/src/components/loader/loading_spinner.jsx +0 -68
- package/src/components/loader/network_speed.js +0 -83
- package/src/components/loader/rectangle_loading.jsx +0 -244
- package/src/components/props_composition/demos/demo_with_props_style.html +0 -81
- package/src/components/props_composition/with_props_class_name.js +0 -37
- package/src/components/props_composition/with_props_style.js +0 -26
- package/src/components/route.jsx +0 -19
- package/src/components/selection/selection.jsx +0 -1583
- package/src/components/svg/font_sized_svg.jsx +0 -59
- package/src/components/svg/icon_and_text.jsx +0 -21
- package/src/components/svg/svg_mask_overlay.jsx +0 -105
- package/src/components/table/drag/table_drag.jsx +0 -506
- package/src/components/table/resize/table_resize.jsx +0 -650
- package/src/components/table/resize/table_size.js +0 -43
- package/src/components/table/selection/table_selection.js +0 -106
- package/src/components/table/selection/table_selection.jsx +0 -203
- package/src/components/table/sticky/sticky_group.js +0 -354
- package/src/components/table/sticky/table_sticky.js +0 -25
- package/src/components/table/sticky/table_sticky.jsx +0 -501
- package/src/components/table/table.jsx +0 -721
- package/src/components/table/table_css.js +0 -211
- package/src/components/table/table_ui.jsx +0 -49
- package/src/components/table/use_cells_and_columns.js +0 -90
- package/src/components/table/use_object_array_to_cells.js +0 -46
- package/src/components/table/z_indexes.js +0 -23
- package/src/components/tablist/tablist.jsx +0 -99
- package/src/components/text/demos/demo_text_and_icon.html +0 -421
- package/src/components/text/overflow.jsx +0 -15
- package/src/components/text/text.jsx +0 -83
- package/src/components/text/text_and_count.jsx +0 -28
- package/src/components/ui_transition.jsx +0 -128
- package/src/components/use_auto_focus.js +0 -94
- package/src/components/use_batch_during_render.js +0 -33
- package/src/components/use_debounce_true.js +0 -31
- package/src/components/use_dependencies_diff.js +0 -35
- package/src/components/use_focus_group.js +0 -20
- package/src/components/use_initial_value.js +0 -78
- package/src/components/use_is_visited.js +0 -19
- package/src/components/use_ref_array.js +0 -38
- package/src/components/use_signal_sync.js +0 -50
- package/src/components/use_stable_callback.js +0 -68
- package/src/components/use_state_array.js +0 -47
- package/src/docs/actions.md +0 -250
- package/src/docs/demos/resource/action_status.jsx +0 -42
- package/src/docs/demos/resource/demo.md +0 -1
- package/src/docs/demos/resource/resource_demo_0.html +0 -84
- package/src/docs/demos/resource/resource_demo_10_post_gc.html +0 -364
- package/src/docs/demos/resource/resource_demo_11_describe_many.html +0 -362
- package/src/docs/demos/resource/resource_demo_2.html +0 -173
- package/src/docs/demos/resource/resource_demo_3_filtered_users.html +0 -415
- package/src/docs/demos/resource/resource_demo_4_details.html +0 -284
- package/src/docs/demos/resource/resource_demo_5_renderer_lazy.html +0 -115
- package/src/docs/demos/resource/resource_demo_6_gc.html +0 -217
- package/src/docs/demos/resource/resource_demo_7_child_gc.html +0 -240
- package/src/docs/demos/resource/resource_demo_8_proxy_gc.html +0 -319
- package/src/docs/demos/resource/resource_demo_9_describe_one.html +0 -472
- package/src/docs/demos/resource/tata.jsx +0 -3
- package/src/docs/demos/resource/toto.jsx +0 -3
- package/src/docs/demos/user_nav/user_nav.html +0 -12
- package/src/docs/demos/user_nav/user_nav.jsx +0 -330
- package/src/docs/resource_dependencies.md +0 -103
- package/src/docs/resource_with_params.md +0 -80
- package/src/navi_css_vars.js +0 -14
- package/src/notes.md +0 -34
- package/src/route/route.js +0 -596
- package/src/route/route.xtest.html +0 -228
- package/src/store/array_signal_store.js +0 -537
- package/src/store/local_storage_signal.js +0 -17
- package/src/store/resource_graph.js +0 -1304
- package/src/store/tests/resource_graph_autoreload_demo.html +0 -12
- package/src/store/tests/resource_graph_autoreload_demo.jsx +0 -964
- package/src/store/tests/resource_graph_dependencies.test_manual.js +0 -95
- package/src/store/value_in_local_storage.js +0 -187
- package/src/symbol_object_signal.js +0 -1
- package/src/use_action_data.js +0 -10
- package/src/use_action_status.js +0 -47
- package/src/utils/add_many_event_listeners.js +0 -15
- package/src/utils/array_add_remove.js +0 -61
- package/src/utils/array_signal.js +0 -15
- package/src/utils/compare_two_js_values.js +0 -172
- package/src/utils/execute_with_cleanup.js +0 -21
- package/src/utils/get_caller_info.js +0 -85
- package/src/utils/is_signal.js +0 -20
- package/src/utils/js_value_weak_map.js +0 -162
- package/src/utils/js_value_weak_map_demo.html +0 -690
- package/src/utils/merge_two_js_values.js +0 -53
- package/src/utils/stringify_for_display.js +0 -131
- package/src/utils/weak_effect.js +0 -48
- package/src/validation/constraints/confirm_constraint.js +0 -14
- package/src/validation/constraints/create_unique_value_constraint.js +0 -27
- package/src/validation/constraints/native_constraints.js +0 -338
- package/src/validation/constraints/readonly_constraint.js +0 -41
- package/src/validation/constraints/same_as_constraint.js +0 -42
- package/src/validation/constraints/single_space_constraint.js +0 -13
- package/src/validation/custom_constraint_validation.js +0 -793
- package/src/validation/custom_message.js +0 -18
- package/src/validation/demos/browser_style.png +0 -0
- package/src/validation/demos/demo_same_as_constraint.html +0 -259
- package/src/validation/demos/form_validation_demo.html +0 -142
- package/src/validation/demos/form_validation_demo_preact.html +0 -87
- package/src/validation/demos/form_validation_native_popover_demo.html +0 -168
- package/src/validation/demos/form_validation_vs_native_demo.html +0 -172
- package/src/validation/hooks/use_constraints.js +0 -23
- package/src/validation/hooks/use_custom_validation_ref.js +0 -73
- package/src/validation/hooks/use_validation_message.js +0 -19
- package/src/validation/input_change_effect.js +0 -106
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
// Example test demonstrating the dependency system
|
|
2
|
-
import { resource } from "../resource_graph.js";
|
|
3
|
-
|
|
4
|
-
// Create test resources
|
|
5
|
-
const role = resource("role", {
|
|
6
|
-
GET_MANY: () =>
|
|
7
|
-
Promise.resolve([
|
|
8
|
-
{ id: 1, name: "admin" },
|
|
9
|
-
{ id: 2, name: "user" },
|
|
10
|
-
]),
|
|
11
|
-
POST: (data) => Promise.resolve({ id: Date.now(), ...data }),
|
|
12
|
-
DELETE: (id) => Promise.resolve(id),
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
const database = resource("database", {
|
|
16
|
-
GET_MANY: () =>
|
|
17
|
-
Promise.resolve([
|
|
18
|
-
{ id: 1, name: "main_db" },
|
|
19
|
-
{ id: 2, name: "test_db" },
|
|
20
|
-
]),
|
|
21
|
-
POST: (data) => Promise.resolve({ id: Date.now(), ...data }),
|
|
22
|
-
DELETE: (id) => Promise.resolve(id),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
const tables = resource("tables", {
|
|
26
|
-
GET_MANY: () =>
|
|
27
|
-
Promise.resolve([
|
|
28
|
-
{ id: 1, name: "users", database_id: 1 },
|
|
29
|
-
{ id: 2, name: "roles", database_id: 1 },
|
|
30
|
-
]),
|
|
31
|
-
POST: (data) => Promise.resolve({ id: Date.now(), ...data }),
|
|
32
|
-
DELETE: (id) => Promise.resolve(id),
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// Create parameterized resource with dependencies
|
|
36
|
-
// This will autoreload when any of the dependency resources are modified
|
|
37
|
-
const ROLE_WITH_OWNERSHIP = role.withParams(
|
|
38
|
-
{ owners: true },
|
|
39
|
-
{
|
|
40
|
-
dependencies: [role, database, tables],
|
|
41
|
-
},
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
// Demonstrate the functionality
|
|
45
|
-
console.log("🚀 Dependency system demo");
|
|
46
|
-
console.log(
|
|
47
|
-
`✅ Created ROLE_WITH_OWNERSHIP with ${ROLE_WITH_OWNERSHIP.dependencies.length} dependencies`,
|
|
48
|
-
);
|
|
49
|
-
console.log(
|
|
50
|
-
`📋 Dependencies: ${ROLE_WITH_OWNERSHIP.dependencies.map((d) => d.name).join(", ")}`,
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
// Test the autoreload mechanism
|
|
54
|
-
async function testAutorerun() {
|
|
55
|
-
console.log("\n🧪 Testing autorerun mechanism...");
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
// Load the parameterized resource
|
|
59
|
-
const ownershipData = await ROLE_WITH_OWNERSHIP.GET_MANY.run();
|
|
60
|
-
console.log(
|
|
61
|
-
"✅ ROLE_WITH_OWNERSHIP.GET_MANY.run() executed:",
|
|
62
|
-
ownershipData.length,
|
|
63
|
-
"items",
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
// Trigger dependency changes that should cause autorerun
|
|
67
|
-
console.log("\n📝 Triggering dependency changes...");
|
|
68
|
-
|
|
69
|
-
await tables.POST.run({ name: "new_table", database_id: 1 });
|
|
70
|
-
console.log(
|
|
71
|
-
"✅ tables.POST.run() - should trigger ROLE_WITH_OWNERSHIP autorerun",
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
await database.POST.run({ name: "new_database" });
|
|
75
|
-
console.log(
|
|
76
|
-
"✅ database.POST.run() - should trigger ROLE_WITH_OWNERSHIP autorerun",
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
await role.POST.run({ name: "new_role" });
|
|
80
|
-
console.log(
|
|
81
|
-
"✅ role.POST.run() - should trigger ROLE_WITH_OWNERSHIP autorerun",
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
console.log("\n✅ Dependency system test completed successfully!");
|
|
85
|
-
console.log(
|
|
86
|
-
"💡 In a real application, these would automatically rerun ROLE_WITH_OWNERSHIP.GET_MANY",
|
|
87
|
-
);
|
|
88
|
-
} catch (error) {
|
|
89
|
-
console.error("❌ Test failed:", error);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
testAutorerun();
|
|
94
|
-
|
|
95
|
-
export { database, role, ROLE_WITH_OWNERSHIP, tables };
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
export const valueInLocalStorage = (key, options = {}) => {
|
|
2
|
-
const { type = "string" } = options;
|
|
3
|
-
const converter = typeConverters[type];
|
|
4
|
-
if (converter === undefined) {
|
|
5
|
-
console.warn(
|
|
6
|
-
`Invalid type "${type}" for "${key}" in local storage, expected one of ${Object.keys(
|
|
7
|
-
typeConverters,
|
|
8
|
-
).join(", ")}`,
|
|
9
|
-
);
|
|
10
|
-
}
|
|
11
|
-
const getValidityMessage = (
|
|
12
|
-
valueToCheck,
|
|
13
|
-
valueInLocalStorage = valueToCheck,
|
|
14
|
-
) => {
|
|
15
|
-
if (!converter) {
|
|
16
|
-
return "";
|
|
17
|
-
}
|
|
18
|
-
if (!converter.checkValidity) {
|
|
19
|
-
return "";
|
|
20
|
-
}
|
|
21
|
-
const checkValidityResult = converter.checkValidity(valueToCheck);
|
|
22
|
-
if (checkValidityResult === false) {
|
|
23
|
-
return `${valueInLocalStorage}`;
|
|
24
|
-
}
|
|
25
|
-
if (!checkValidityResult) {
|
|
26
|
-
return "";
|
|
27
|
-
}
|
|
28
|
-
return `${checkValidityResult}, got "${valueInLocalStorage}"`;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const get = () => {
|
|
32
|
-
let valueInLocalStorage = window.localStorage.getItem(key);
|
|
33
|
-
if (valueInLocalStorage === null) {
|
|
34
|
-
return Object.hasOwn(options, "default") ? options.default : undefined;
|
|
35
|
-
}
|
|
36
|
-
if (converter && converter.decode) {
|
|
37
|
-
const valueDecoded = converter.decode(valueInLocalStorage);
|
|
38
|
-
const validityMessage = getValidityMessage(
|
|
39
|
-
valueDecoded,
|
|
40
|
-
valueInLocalStorage,
|
|
41
|
-
);
|
|
42
|
-
if (validityMessage) {
|
|
43
|
-
console.warn(
|
|
44
|
-
`The value found in localStorage "${key}" is invalid: ${validityMessage}`,
|
|
45
|
-
);
|
|
46
|
-
return undefined;
|
|
47
|
-
}
|
|
48
|
-
return valueDecoded;
|
|
49
|
-
}
|
|
50
|
-
const validityMessage = getValidityMessage(valueInLocalStorage);
|
|
51
|
-
if (validityMessage) {
|
|
52
|
-
console.warn(
|
|
53
|
-
`The value found in localStorage "${key}" is invalid: ${validityMessage}`,
|
|
54
|
-
);
|
|
55
|
-
return undefined;
|
|
56
|
-
}
|
|
57
|
-
return valueInLocalStorage;
|
|
58
|
-
};
|
|
59
|
-
const set = (value) => {
|
|
60
|
-
if (value === undefined) {
|
|
61
|
-
window.localStorage.removeItem(key);
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const validityMessage = getValidityMessage(value);
|
|
65
|
-
if (validityMessage) {
|
|
66
|
-
console.warn(
|
|
67
|
-
`The value to set in localStorage "${key}" is invalid: ${validityMessage}`,
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
if (converter && converter.encode) {
|
|
71
|
-
const valueEncoded = converter.encode(value);
|
|
72
|
-
window.localStorage.setItem(key, valueEncoded);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
window.localStorage.setItem(key, value);
|
|
76
|
-
};
|
|
77
|
-
const remove = () => {
|
|
78
|
-
window.localStorage.removeItem(key);
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
return [get, set, remove];
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const typeConverters = {
|
|
85
|
-
boolean: {
|
|
86
|
-
checkValidity: (value) => {
|
|
87
|
-
if (typeof value !== "boolean") {
|
|
88
|
-
return `must be a boolean`;
|
|
89
|
-
}
|
|
90
|
-
return "";
|
|
91
|
-
},
|
|
92
|
-
decode: (value) => {
|
|
93
|
-
return value === "true";
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
string: {
|
|
97
|
-
checkValidity: (value) => {
|
|
98
|
-
if (typeof value !== "string") {
|
|
99
|
-
return `must be a string`;
|
|
100
|
-
}
|
|
101
|
-
return "";
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
number: {
|
|
105
|
-
decode: (value) => {
|
|
106
|
-
const valueParsed = parseFloat(value);
|
|
107
|
-
return valueParsed;
|
|
108
|
-
},
|
|
109
|
-
checkValidity: (value) => {
|
|
110
|
-
if (typeof value !== "number") {
|
|
111
|
-
return `must be a number`;
|
|
112
|
-
}
|
|
113
|
-
if (!Number.isFinite(value)) {
|
|
114
|
-
return `must be finite`;
|
|
115
|
-
}
|
|
116
|
-
return "";
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
positive_number: {
|
|
120
|
-
decode: (value) => {
|
|
121
|
-
const valueParsed = parseFloat(value);
|
|
122
|
-
return valueParsed;
|
|
123
|
-
},
|
|
124
|
-
checkValidity: (value) => {
|
|
125
|
-
if (typeof value !== "number") {
|
|
126
|
-
return `must be a number`;
|
|
127
|
-
}
|
|
128
|
-
if (value < 0) {
|
|
129
|
-
return `must be positive`;
|
|
130
|
-
}
|
|
131
|
-
return "";
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
positive_integer: {
|
|
135
|
-
decode: (value) => {
|
|
136
|
-
const valueParsed = parseInt(value, 10);
|
|
137
|
-
return valueParsed;
|
|
138
|
-
},
|
|
139
|
-
checkValidity: (value) => {
|
|
140
|
-
if (typeof value !== "number") {
|
|
141
|
-
return `must be a number`;
|
|
142
|
-
}
|
|
143
|
-
if (!Number.isInteger(value)) {
|
|
144
|
-
return `must be an integer`;
|
|
145
|
-
}
|
|
146
|
-
if (value < 0) {
|
|
147
|
-
return `must be positive`;
|
|
148
|
-
}
|
|
149
|
-
return "";
|
|
150
|
-
},
|
|
151
|
-
},
|
|
152
|
-
percentage: {
|
|
153
|
-
checkValidity: (value) => {
|
|
154
|
-
if (typeof value !== "string") {
|
|
155
|
-
return `must be a percentage`;
|
|
156
|
-
}
|
|
157
|
-
if (!value.endsWith("%")) {
|
|
158
|
-
return `must end with %`;
|
|
159
|
-
}
|
|
160
|
-
const percentageString = value.slice(0, -1);
|
|
161
|
-
const percentageFloat = parseFloat(percentageString);
|
|
162
|
-
if (typeof percentageFloat !== "number") {
|
|
163
|
-
return `must be a percentage`;
|
|
164
|
-
}
|
|
165
|
-
if (percentageFloat < 0 || percentageFloat > 100) {
|
|
166
|
-
return `must be between 0 and 100`;
|
|
167
|
-
}
|
|
168
|
-
return "";
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
object: {
|
|
172
|
-
decode: (value) => {
|
|
173
|
-
const valueParsed = JSON.parse(value);
|
|
174
|
-
return valueParsed;
|
|
175
|
-
},
|
|
176
|
-
encode: (value) => {
|
|
177
|
-
const valueStringified = JSON.stringify(value);
|
|
178
|
-
return valueStringified;
|
|
179
|
-
},
|
|
180
|
-
checkValidity: (value) => {
|
|
181
|
-
if (value === null || typeof value !== "object") {
|
|
182
|
-
return `must be an object`;
|
|
183
|
-
}
|
|
184
|
-
return "";
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const SYMBOL_OBJECT_SIGNAL = Symbol.for("navi_object_signal");
|
package/src/use_action_data.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { getActionPrivateProperties } from "./action_private_properties.js";
|
|
2
|
-
|
|
3
|
-
export const useActionData = (action) => {
|
|
4
|
-
if (!action) {
|
|
5
|
-
return undefined;
|
|
6
|
-
}
|
|
7
|
-
const { computedDataSignal } = getActionPrivateProperties(action);
|
|
8
|
-
const data = computedDataSignal.value;
|
|
9
|
-
return data;
|
|
10
|
-
};
|
package/src/use_action_status.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { getActionPrivateProperties } from "./action_private_properties.js";
|
|
2
|
-
import { ABORTED, COMPLETED, IDLE, RUNNING } from "./action_run_states.js";
|
|
3
|
-
|
|
4
|
-
export const useActionStatus = (action) => {
|
|
5
|
-
if (!action) {
|
|
6
|
-
return {
|
|
7
|
-
params: undefined,
|
|
8
|
-
runningState: IDLE,
|
|
9
|
-
isPrerun: false,
|
|
10
|
-
idle: true,
|
|
11
|
-
loading: false,
|
|
12
|
-
aborted: false,
|
|
13
|
-
error: null,
|
|
14
|
-
completed: false,
|
|
15
|
-
data: undefined,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
const {
|
|
19
|
-
paramsSignal,
|
|
20
|
-
runningStateSignal,
|
|
21
|
-
isPrerunSignal,
|
|
22
|
-
errorSignal,
|
|
23
|
-
computedDataSignal,
|
|
24
|
-
} = getActionPrivateProperties(action);
|
|
25
|
-
|
|
26
|
-
const params = paramsSignal.value;
|
|
27
|
-
const isPrerun = isPrerunSignal.value;
|
|
28
|
-
const runningState = runningStateSignal.value;
|
|
29
|
-
const idle = runningState === IDLE;
|
|
30
|
-
const aborted = runningState === ABORTED;
|
|
31
|
-
const error = errorSignal.value;
|
|
32
|
-
const loading = runningState === RUNNING;
|
|
33
|
-
const completed = runningState === COMPLETED;
|
|
34
|
-
const data = computedDataSignal.value;
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
params,
|
|
38
|
-
runningState,
|
|
39
|
-
isPrerun,
|
|
40
|
-
idle,
|
|
41
|
-
loading,
|
|
42
|
-
aborted,
|
|
43
|
-
error,
|
|
44
|
-
completed,
|
|
45
|
-
data,
|
|
46
|
-
};
|
|
47
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export const addManyEventListeners = (element, events) => {
|
|
2
|
-
const cleanupCallbackSet = new Set();
|
|
3
|
-
for (const event of Object.keys(events)) {
|
|
4
|
-
const callback = events[event];
|
|
5
|
-
element.addEventListener(event, callback);
|
|
6
|
-
cleanupCallbackSet.add(() => {
|
|
7
|
-
element.removeEventListener(event, callback);
|
|
8
|
-
});
|
|
9
|
-
}
|
|
10
|
-
return () => {
|
|
11
|
-
for (const cleanupCallback of cleanupCallbackSet) {
|
|
12
|
-
cleanupCallback();
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
};
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
export const addIntoArray = (array, ...valuesToAdd) => {
|
|
2
|
-
if (valuesToAdd.length === 1) {
|
|
3
|
-
const [valueToAdd] = valuesToAdd;
|
|
4
|
-
const arrayWithThisValue = [];
|
|
5
|
-
for (const value of array) {
|
|
6
|
-
if (value === valueToAdd) {
|
|
7
|
-
return array;
|
|
8
|
-
}
|
|
9
|
-
arrayWithThisValue.push(value);
|
|
10
|
-
}
|
|
11
|
-
arrayWithThisValue.push(valueToAdd);
|
|
12
|
-
return arrayWithThisValue;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const existingValueSet = new Set();
|
|
16
|
-
const arrayWithTheseValues = [];
|
|
17
|
-
for (const existingValue of array) {
|
|
18
|
-
arrayWithTheseValues.push(existingValue);
|
|
19
|
-
existingValueSet.add(existingValue);
|
|
20
|
-
}
|
|
21
|
-
let hasNewValues = false;
|
|
22
|
-
for (const valueToAdd of valuesToAdd) {
|
|
23
|
-
if (existingValueSet.has(valueToAdd)) {
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
arrayWithTheseValues.push(valueToAdd);
|
|
27
|
-
hasNewValues = true;
|
|
28
|
-
}
|
|
29
|
-
return hasNewValues ? arrayWithTheseValues : array;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export const removeFromArray = (array, ...valuesToRemove) => {
|
|
33
|
-
if (valuesToRemove.length === 1) {
|
|
34
|
-
const [valueToRemove] = valuesToRemove;
|
|
35
|
-
const arrayWithoutThisValue = [];
|
|
36
|
-
let found = false;
|
|
37
|
-
for (const value of array) {
|
|
38
|
-
if (value === valueToRemove) {
|
|
39
|
-
found = true;
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
arrayWithoutThisValue.push(value);
|
|
43
|
-
}
|
|
44
|
-
if (!found) {
|
|
45
|
-
return array;
|
|
46
|
-
}
|
|
47
|
-
return arrayWithoutThisValue;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const valuesToRemoveSet = new Set(valuesToRemove);
|
|
51
|
-
const arrayWithoutTheseValues = [];
|
|
52
|
-
let hasRemovedValues = false;
|
|
53
|
-
for (const value of array) {
|
|
54
|
-
if (valuesToRemoveSet.has(value)) {
|
|
55
|
-
hasRemovedValues = true;
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
arrayWithoutTheseValues.push(value);
|
|
59
|
-
}
|
|
60
|
-
return hasRemovedValues ? arrayWithoutTheseValues : array;
|
|
61
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { signal } from "@preact/signals";
|
|
2
|
-
import { addIntoArray, removeFromArray } from "./array_add_remove.js";
|
|
3
|
-
|
|
4
|
-
export const arraySignal = (initialValue = []) => {
|
|
5
|
-
const theSignal = signal(initialValue);
|
|
6
|
-
|
|
7
|
-
const add = (...args) => {
|
|
8
|
-
theSignal.value = addIntoArray(theSignal.peek(), ...args);
|
|
9
|
-
};
|
|
10
|
-
const remove = (...args) => {
|
|
11
|
-
theSignal.value = removeFromArray(theSignal.peek(), ...args);
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
return [theSignal, add, remove];
|
|
15
|
-
};
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Deep equality comparison for JavaScript values with cycle detection and identity optimization.
|
|
3
|
-
*
|
|
4
|
-
* This function performs a comprehensive deep comparison between two JavaScript values,
|
|
5
|
-
* handling all primitive types, objects, arrays, and edge cases that standard equality
|
|
6
|
-
* operators miss.
|
|
7
|
-
*
|
|
8
|
-
* Key features:
|
|
9
|
-
* - **Deep comparison**: Recursively compares nested objects and arrays
|
|
10
|
-
* - **Cycle detection**: Prevents infinite loops with circular references
|
|
11
|
-
* - **Identity optimization**: Uses SYMBOL_IDENTITY for fast comparison of objects with same identity
|
|
12
|
-
* - **Edge case handling**: Properly handles NaN, null, undefined, 0, false comparisons
|
|
13
|
-
* - **Type safety**: Ensures both values have same type before deep comparison
|
|
14
|
-
*
|
|
15
|
-
* Performance optimizations:
|
|
16
|
-
* - Early exit for reference equality (a === b)
|
|
17
|
-
* - Identity symbol check for objects (avoids deep comparison when possible)
|
|
18
|
-
* - Efficient array length check before element-by-element comparison
|
|
19
|
-
*
|
|
20
|
-
* **SYMBOL_IDENTITY explained**:
|
|
21
|
-
* This symbol allows recognizing objects as "conceptually the same" even when they are
|
|
22
|
-
* different object instances. When two objects share the same SYMBOL_IDENTITY value,
|
|
23
|
-
* they are considered equal without performing deep comparison.
|
|
24
|
-
*
|
|
25
|
-
* This is particularly useful for:
|
|
26
|
-
* - Copied objects that should be treated as the same entity
|
|
27
|
-
* - Objects reconstructed from serialization that represent the same data
|
|
28
|
-
* - Parameters passed through spread operator: `{ ...originalParams, newProp: value }`
|
|
29
|
-
* - Memoization scenarios where object content identity matters more than reference identity
|
|
30
|
-
*
|
|
31
|
-
* Use cases:
|
|
32
|
-
* - Memoization cache key comparison ({ id: 1 } should equal { id: 1 })
|
|
33
|
-
* - React/Preact dependency comparison for effects and memos
|
|
34
|
-
* - State change detection in signals and stores
|
|
35
|
-
* - Action parameter comparison for avoiding duplicate requests
|
|
36
|
-
* - Object recognition across serialization/deserialization boundaries
|
|
37
|
-
*
|
|
38
|
-
* Examples:
|
|
39
|
-
* ```js
|
|
40
|
-
* // Standard deep comparison
|
|
41
|
-
* compareTwoJsValues({ id: 1 }, { id: 1 }) // true (slow - deep comparison)
|
|
42
|
-
*
|
|
43
|
-
* // NaN edge case handling
|
|
44
|
-
* compareTwoJsValues(NaN, NaN) // true (unlike === which gives false)
|
|
45
|
-
*
|
|
46
|
-
* // Identity optimization - objects are different instances but same identity
|
|
47
|
-
* const originalParams = { userId: 123, filters: ['active'] };
|
|
48
|
-
* const copiedParams = { ...originalParams, newFlag: true };
|
|
49
|
-
*
|
|
50
|
-
* // Without SYMBOL_IDENTITY: slow deep comparison every time
|
|
51
|
-
* compareTwoJsValues(originalParams, copiedParams) // false (different content)
|
|
52
|
-
*
|
|
53
|
-
* // With SYMBOL_IDENTITY: fast path recognition
|
|
54
|
-
* const sharedIdentity = Symbol('params-identity');
|
|
55
|
-
* originalParams[SYMBOL_IDENTITY] = sharedIdentity;
|
|
56
|
-
* copiedParams[SYMBOL_IDENTITY] = sharedIdentity;
|
|
57
|
-
*
|
|
58
|
-
* compareTwoJsValues(originalParams, copiedParams) // true (fast - identity match)
|
|
59
|
-
* // ↑ This returns true immediately without comparing all properties
|
|
60
|
-
*
|
|
61
|
-
* // Real-world scenario: action memoization
|
|
62
|
-
* const params1 = { userId: 123 };
|
|
63
|
-
* const action1 = createAction(params1);
|
|
64
|
-
*
|
|
65
|
-
* const params2 = { ...params1, extra: 'data' }; // Different object reference
|
|
66
|
-
* params2[SYMBOL_IDENTITY] = params1[SYMBOL_IDENTITY]; // Same conceptual identity
|
|
67
|
-
*
|
|
68
|
-
* const action2 = createAction(params2);
|
|
69
|
-
* // action1 === action2 because params are recognized as conceptually identical
|
|
70
|
-
* ```
|
|
71
|
-
*
|
|
72
|
-
* @param {any} a - First value to compare
|
|
73
|
-
* @param {any} b - Second value to compare
|
|
74
|
-
* @param {Set} seenSet - Internal cycle detection set (automatically managed)
|
|
75
|
-
* @returns {boolean} true if values are deeply equal, false otherwise
|
|
76
|
-
*/
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Symbol used to mark objects with a conceptual identity that transcends reference equality.
|
|
80
|
-
*
|
|
81
|
-
* When two different object instances share the same SYMBOL_IDENTITY value, they are
|
|
82
|
-
* considered equal by compareTwoJsValues without performing expensive deep comparison.
|
|
83
|
-
*
|
|
84
|
-
* This enables recognition of "the same logical object" even when:
|
|
85
|
-
* - The object has been copied via spread operator: `{ ...obj, newProp }`
|
|
86
|
-
* - The object has been reconstructed from serialization
|
|
87
|
-
* - The object is a different instance but represents the same conceptual entity
|
|
88
|
-
*
|
|
89
|
-
* Use Symbol.for() to ensure the same symbol across different modules/contexts.
|
|
90
|
-
*/
|
|
91
|
-
export const SYMBOL_IDENTITY = Symbol.for("navi_object_identity");
|
|
92
|
-
|
|
93
|
-
export const compareTwoJsValues = (a, b, seenSet = new Set()) => {
|
|
94
|
-
if (a === b) {
|
|
95
|
-
return true;
|
|
96
|
-
}
|
|
97
|
-
const aIsIsTruthy = Boolean(a);
|
|
98
|
-
const bIsTruthy = Boolean(b);
|
|
99
|
-
if (aIsIsTruthy && !bIsTruthy) {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
if (!aIsIsTruthy && !bIsTruthy) {
|
|
103
|
-
// null, undefined, 0, false, NaN
|
|
104
|
-
if (isNaN(a) && isNaN(b)) {
|
|
105
|
-
return true;
|
|
106
|
-
}
|
|
107
|
-
return a === b;
|
|
108
|
-
}
|
|
109
|
-
const aType = typeof a;
|
|
110
|
-
const bType = typeof b;
|
|
111
|
-
if (aType !== bType) {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
const aIsPrimitive =
|
|
115
|
-
a === null || (aType !== "object" && aType !== "function");
|
|
116
|
-
const bIsPrimitive =
|
|
117
|
-
b === null || (bType !== "object" && bType !== "function");
|
|
118
|
-
if (aIsPrimitive !== bIsPrimitive) {
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
if (aIsPrimitive && bIsPrimitive) {
|
|
122
|
-
return a === b;
|
|
123
|
-
}
|
|
124
|
-
if (seenSet.has(a)) {
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
|
-
if (seenSet.has(b)) {
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
seenSet.add(a);
|
|
131
|
-
seenSet.add(b);
|
|
132
|
-
const aIsArray = Array.isArray(a);
|
|
133
|
-
const bIsArray = Array.isArray(b);
|
|
134
|
-
if (aIsArray !== bIsArray) {
|
|
135
|
-
return false;
|
|
136
|
-
}
|
|
137
|
-
if (aIsArray) {
|
|
138
|
-
// compare arrays
|
|
139
|
-
if (a.length !== b.length) {
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
let i = 0;
|
|
143
|
-
while (i < a.length) {
|
|
144
|
-
const aValue = a[i];
|
|
145
|
-
const bValue = b[i];
|
|
146
|
-
if (!compareTwoJsValues(aValue, bValue, seenSet)) {
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
i++;
|
|
150
|
-
}
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
// compare objects
|
|
154
|
-
const aIdentity = a[SYMBOL_IDENTITY];
|
|
155
|
-
const bIdentity = b[SYMBOL_IDENTITY];
|
|
156
|
-
if (aIdentity === bIdentity && SYMBOL_IDENTITY in a && SYMBOL_IDENTITY in b) {
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
const aKeys = Object.keys(a);
|
|
160
|
-
const bKeys = Object.keys(b);
|
|
161
|
-
if (aKeys.length !== bKeys.length) {
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
for (const key of aKeys) {
|
|
165
|
-
const aValue = a[key];
|
|
166
|
-
const bValue = b[key];
|
|
167
|
-
if (!compareTwoJsValues(aValue, bValue, seenSet)) {
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
return true;
|
|
172
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export const executeWithCleanup = (fn, cleanup) => {
|
|
2
|
-
let isThenable;
|
|
3
|
-
try {
|
|
4
|
-
const result = fn();
|
|
5
|
-
isThenable = result && typeof result.then === "function";
|
|
6
|
-
if (isThenable) {
|
|
7
|
-
return (async () => {
|
|
8
|
-
try {
|
|
9
|
-
return await result;
|
|
10
|
-
} finally {
|
|
11
|
-
cleanup();
|
|
12
|
-
}
|
|
13
|
-
})();
|
|
14
|
-
}
|
|
15
|
-
return result;
|
|
16
|
-
} finally {
|
|
17
|
-
if (!isThenable) {
|
|
18
|
-
cleanup();
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
};
|