@jsenv/navi 0.0.1 → 0.1.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 (138) hide show
  1. package/dist/jsenv_navi.js +22954 -0
  2. package/index.js +66 -16
  3. package/package.json +22 -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/{input → field}/input_textual.jsx +247 -173
  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/radio_list.jsx +0 -283
  129. package/src/components/input/use_form_event.js +0 -20
  130. package/src/components/input/use_on_change.js +0 -12
  131. package/src/components/selection/selection.js +0 -5
  132. package/src/components/selection/selection_context.jsx +0 -262
  133. package/src/components/shortcut/shortcut_context.jsx +0 -390
  134. package/src/components/use_action_events.js +0 -37
  135. package/src/utils/iterable_weak_set.js +0 -62
  136. /package/src/components/demos/action/{11_nested_shortcuts_demo.html → 11_nested_shortcuts_demo.xhtml} +0 -0
  137. /package/src/components/{shortcut → keyboard_shortcuts}/os.js +0 -0
  138. /package/src/route/{route.test.html → route.xtest.html} +0 -0
@@ -0,0 +1,184 @@
1
+ // TOFIX: select in data then reset, it reset to red/blue instead of red/blue/green
2
+
3
+ import { forwardRef } from "preact/compat";
4
+ import {
5
+ useContext,
6
+ useImperativeHandle,
7
+ useRef,
8
+ useState,
9
+ } from "preact/hooks";
10
+
11
+ import { useActionStatus } from "../../use_action_status.js";
12
+ import { requestAction } from "../../validation/custom_constraint_validation.js";
13
+ import { renderActionableComponent } from "../action_execution/render_actionable_component.jsx";
14
+ import { useActionBoundToOneArrayParam } from "../action_execution/use_action.js";
15
+ import { useExecuteAction } from "../action_execution/use_execute_action.js";
16
+ import { InputCheckbox } from "./input_checkbox.jsx";
17
+ import { useActionEvents } from "./use_action_events.js";
18
+ import {
19
+ DisabledContext,
20
+ FieldNameContext,
21
+ LoadingContext,
22
+ LoadingElementContext,
23
+ ParentUIStateControllerContext,
24
+ ReadOnlyContext,
25
+ RequiredContext,
26
+ UIStateContext,
27
+ UIStateControllerContext,
28
+ useUIGroupStateController,
29
+ useUIState,
30
+ } from "./use_ui_state_controller.js";
31
+
32
+ import.meta.css = /* css */ `
33
+ .navi_checkbox_list {
34
+ display: flex;
35
+ flex-direction: column;
36
+ }
37
+ `;
38
+
39
+ export const CheckboxList = forwardRef((props, ref) => {
40
+ const uiStateController = useUIGroupStateController(props, "checkbox_list", {
41
+ childComponentType: "checkbox",
42
+ aggregateChildStates: (childUIStateControllers) => {
43
+ const values = [];
44
+ for (const childUIStateController of childUIStateControllers) {
45
+ if (childUIStateController.uiState) {
46
+ values.push(childUIStateController.uiState);
47
+ }
48
+ }
49
+ return values.length === 0 ? undefined : values;
50
+ },
51
+ });
52
+ const uiState = useUIState(uiStateController);
53
+
54
+ const checkboxList = renderActionableComponent(props, ref, {
55
+ Basic: CheckboxListBasic,
56
+ WithAction: CheckboxListWithAction,
57
+ InsideForm: CheckboxListInsideForm,
58
+ });
59
+ return (
60
+ <UIStateControllerContext.Provider value={uiStateController}>
61
+ <UIStateContext.Provider value={uiState}>
62
+ {checkboxList}
63
+ </UIStateContext.Provider>
64
+ </UIStateControllerContext.Provider>
65
+ );
66
+ });
67
+ export const Checkbox = InputCheckbox;
68
+
69
+ const CheckboxListBasic = forwardRef((props, ref) => {
70
+ const contextReadOnly = useContext(ReadOnlyContext);
71
+ const contextDisabled = useContext(DisabledContext);
72
+ const contextLoading = useContext(LoadingContext);
73
+ const uiStateController = useContext(UIStateControllerContext);
74
+ const { name, readOnly, disabled, required, loading, children, ...rest } =
75
+ props;
76
+ const innerRef = useRef();
77
+ useImperativeHandle(ref, () => innerRef.current);
78
+
79
+ const innerLoading = loading || contextLoading;
80
+ const innerReadOnly =
81
+ readOnly || contextReadOnly || innerLoading || uiStateController.readOnly;
82
+ const innerDisabled = disabled || contextDisabled;
83
+
84
+ return (
85
+ <div
86
+ {...rest}
87
+ ref={innerRef}
88
+ name={name}
89
+ className="navi_checkbox_list"
90
+ data-checkbox-list
91
+ // eslint-disable-next-line react/no-unknown-property
92
+ onresetuistate={(e) => {
93
+ uiStateController.resetUIState(e);
94
+ }}
95
+ >
96
+ <ParentUIStateControllerContext.Provider value={uiStateController}>
97
+ <FieldNameContext.Provider value={name}>
98
+ <ReadOnlyContext.Provider value={innerReadOnly}>
99
+ <DisabledContext.Provider value={innerDisabled}>
100
+ <RequiredContext.Provider value={required}>
101
+ <LoadingContext.Provider value={innerLoading}>
102
+ {children}
103
+ </LoadingContext.Provider>
104
+ </RequiredContext.Provider>
105
+ </DisabledContext.Provider>
106
+ </ReadOnlyContext.Provider>
107
+ </FieldNameContext.Provider>
108
+ </ParentUIStateControllerContext.Provider>
109
+ </div>
110
+ );
111
+ });
112
+
113
+ const CheckboxListWithAction = forwardRef((props, ref) => {
114
+ const uiStateController = useContext(UIStateControllerContext);
115
+ const uiState = useContext(UIStateContext);
116
+ const {
117
+ action,
118
+ actionErrorEffect,
119
+ onCancel,
120
+ onActionPrevented,
121
+ onActionStart,
122
+ onActionAbort,
123
+ onActionError,
124
+ onActionEnd,
125
+ loading,
126
+ children,
127
+ ...rest
128
+ } = props;
129
+ const innerRef = useRef();
130
+ useImperativeHandle(ref, () => innerRef.current);
131
+ const [boundAction] = useActionBoundToOneArrayParam(action, uiState);
132
+ const { loading: actionLoading } = useActionStatus(boundAction);
133
+ const executeAction = useExecuteAction(innerRef, {
134
+ errorEffect: actionErrorEffect,
135
+ });
136
+ const [actionRequester, setActionRequester] = useState(null);
137
+
138
+ useActionEvents(innerRef, {
139
+ onCancel: (e, reason) => {
140
+ uiStateController.resetUIState(e);
141
+ onCancel?.(e, reason);
142
+ },
143
+ onPrevented: onActionPrevented,
144
+ onAction: (actionEvent) => {
145
+ setActionRequester(actionEvent.detail.requester);
146
+ executeAction(actionEvent);
147
+ },
148
+ onStart: onActionStart,
149
+ onAbort: (e) => {
150
+ uiStateController.resetUIState(e);
151
+ onActionAbort?.(e);
152
+ },
153
+ onError: (e) => {
154
+ uiStateController.resetUIState(e);
155
+ onActionError?.(e);
156
+ },
157
+ onEnd: (e) => {
158
+ onActionEnd?.(e);
159
+ },
160
+ });
161
+
162
+ return (
163
+ <CheckboxListBasic
164
+ data-action={boundAction.name}
165
+ {...rest}
166
+ ref={innerRef}
167
+ onChange={(event) => {
168
+ const checkboxList = innerRef.current;
169
+ const checkbox = event.target;
170
+ requestAction(checkboxList, boundAction, {
171
+ event,
172
+ requester: checkbox,
173
+ actionOrigin: "action_prop",
174
+ });
175
+ }}
176
+ loading={loading || actionLoading}
177
+ >
178
+ <LoadingElementContext.Provider value={actionRequester}>
179
+ {children}
180
+ </LoadingElementContext.Provider>
181
+ </CheckboxListBasic>
182
+ );
183
+ });
184
+ const CheckboxListInsideForm = CheckboxListBasic;
@@ -72,8 +72,11 @@ const getFormElementValue = (formElement) => {
72
72
  };
73
73
 
74
74
  const getValue = (formElement) => {
75
- const hasDataFormValueAttribute = formElement.hasAttribute("data-form-value");
76
- return hasDataFormValueAttribute
77
- ? formElement.getAttribute("data-form-value")
78
- : formElement.value;
75
+ const hasDataValueAttribute = formElement.hasAttribute("data-value");
76
+ if (hasDataValueAttribute) {
77
+ // happens for "datetime-local" inputs to keep the timezone
78
+ // consistent when sending to the server
79
+ return formElement.getAttribute("data-value");
80
+ }
81
+ return formElement.value;
79
82
  };
@@ -112,7 +112,10 @@ import.meta.css = /* css */ `
112
112
  [data-field-with-hover]:disabled:hover,
113
113
  [data-field-with-hover][data-disabled]:hover {
114
114
  outline-color: var(--field-disabled-border-color);
115
- background-color: var(--field-disabled-background-color);
116
115
  color: var(--field-disabled-text-color);
117
116
  }
117
+ [data-field-with-background]:disabled,
118
+ [data-field-with-background][disabled] {
119
+ background-color: var(--field-disabled-background-color);
120
+ }
118
121
  `;
@@ -0,0 +1,211 @@
1
+ /**
2
+ *
3
+ * Here we want the same behaviour as web standards:
4
+ *
5
+ * 1. When submitting the form URL does not change
6
+ * 2. When form submission id done user is redirected (by default the current one)
7
+ * (we can configure this using target)
8
+ * So for example user might be reidrect to a page with the resource he just created
9
+ * I could create an example where we would put a link on the page to let user see what he created
10
+ * but by default user stays on the form allowing to create multiple resources at once
11
+ * And an other where he is redirected to the resource he created
12
+ * 3. If form submission fails ideally we should display this somewhere on the UI
13
+ * right now it's just logged to the console I need to see how we can achieve this
14
+ */
15
+
16
+ import { forwardRef } from "preact/compat";
17
+ import { useContext, useImperativeHandle, useMemo, useRef } from "preact/hooks";
18
+
19
+ import { requestAction } from "../../validation/custom_constraint_validation.js";
20
+ import { useConstraints } from "../../validation/hooks/use_constraints.js";
21
+ import { FormContext } from "../action_execution/form_context.js";
22
+ import { renderActionableComponent } from "../action_execution/render_actionable_component.jsx";
23
+ import { useActionBoundToOneParam } from "../action_execution/use_action.js";
24
+ import { useExecuteAction } from "../action_execution/use_execute_action.js";
25
+ import { collectFormElementValues } from "./collect_form_element_values.js";
26
+ import {
27
+ useActionEvents,
28
+ useRequestedActionStatus,
29
+ } from "./use_action_events.js";
30
+ import {
31
+ LoadingContext,
32
+ LoadingElementContext,
33
+ ParentUIStateControllerContext,
34
+ ReadOnlyContext,
35
+ UIStateContext,
36
+ UIStateControllerContext,
37
+ useUIGroupStateController,
38
+ useUIState,
39
+ } from "./use_ui_state_controller.js";
40
+
41
+ export const Form = forwardRef((props, ref) => {
42
+ const uiStateController = useUIGroupStateController(props, "form", {
43
+ childComponentType: "*",
44
+ aggregateChildStates: (childUIStateControllers) => {
45
+ const formValues = {};
46
+ for (const childUIStateController of childUIStateControllers) {
47
+ const { name, uiState } = childUIStateController;
48
+ if (!name) {
49
+ console.warn(
50
+ "A form child component is missing a name property, its state won't be included in the form state",
51
+ childUIStateController,
52
+ );
53
+ continue;
54
+ }
55
+ formValues[name] = uiState;
56
+ }
57
+ return formValues;
58
+ },
59
+ });
60
+ const uiState = useUIState(uiStateController);
61
+
62
+ const form = renderActionableComponent(props, ref, {
63
+ Basic: FormBasic,
64
+ WithAction: FormWithAction,
65
+ });
66
+ return (
67
+ <UIStateControllerContext.Provider value={uiStateController}>
68
+ <UIStateContext.Provider value={uiState}>{form}</UIStateContext.Provider>
69
+ </UIStateControllerContext.Provider>
70
+ );
71
+ });
72
+
73
+ const FormBasic = forwardRef((props, ref) => {
74
+ const uiStateController = useContext(UIStateControllerContext);
75
+ const { readOnly, loading, children, ...rest } = props;
76
+ const innerRef = useRef();
77
+ useImperativeHandle(ref, () => innerRef.current);
78
+
79
+ // instantiation validation to:
80
+ // - receive "requestsubmit" custom event ensure submit is prevented
81
+ // (and also execute action without validation if form.submit() is ever called)
82
+ useConstraints(innerRef, []);
83
+
84
+ const innerReadOnly = readOnly || loading;
85
+
86
+ const formContextValue = useMemo(() => {
87
+ return { loading };
88
+ }, [loading]);
89
+
90
+ return (
91
+ <form
92
+ {...rest}
93
+ ref={innerRef}
94
+ onReset={(e) => {
95
+ // browser would empty all fields to their default values (likely empty/unchecked)
96
+ // we want to reset to the last known external state instead
97
+ e.preventDefault();
98
+ uiStateController.resetUIState(e);
99
+ }}
100
+ >
101
+ <ParentUIStateControllerContext.Provider value={uiStateController}>
102
+ <ReadOnlyContext.Provider value={innerReadOnly}>
103
+ <LoadingContext.Provider value={loading}>
104
+ <FormContext.Provider value={formContextValue}>
105
+ {children}
106
+ </FormContext.Provider>
107
+ </LoadingContext.Provider>
108
+ </ReadOnlyContext.Provider>
109
+ </ParentUIStateControllerContext.Provider>
110
+ </form>
111
+ );
112
+ });
113
+
114
+ const FormWithAction = forwardRef((props, ref) => {
115
+ const uiStateController = useContext(UIStateControllerContext);
116
+ const uiState = useContext(UIStateContext);
117
+ const {
118
+ action,
119
+ method,
120
+ actionErrorEffect = "show_validation_message", // "show_validation_message" or "throw"
121
+ onActionPrevented,
122
+ onActionStart,
123
+ onActionAbort,
124
+ onActionError,
125
+ onActionEnd,
126
+ loading,
127
+ children,
128
+ ...rest
129
+ } = props;
130
+ const innerRef = useRef();
131
+ useImperativeHandle(ref, () => innerRef.current);
132
+ const [actionBoundToUIState] = useActionBoundToOneParam(action, uiState);
133
+ const executeAction = useExecuteAction(innerRef, {
134
+ errorEffect: actionErrorEffect,
135
+ });
136
+ const { actionPending, actionRequester: formActionRequester } =
137
+ useRequestedActionStatus(innerRef);
138
+
139
+ useActionEvents(innerRef, {
140
+ onPrevented: onActionPrevented,
141
+ onRequested: (e) => {
142
+ const form = innerRef.current;
143
+ requestAction(form, actionBoundToUIState, {
144
+ requester: e.detail?.requester,
145
+ event: e.detail?.event || e,
146
+ meta: e.detail?.meta,
147
+ actionOrigin: e.detail?.actionOrigin,
148
+ });
149
+ },
150
+ onAction: (e) => {
151
+ const form = innerRef.current;
152
+ const formElementValues = collectFormElementValues(form);
153
+ uiStateController.setUIState(formElementValues, e);
154
+ executeAction(e);
155
+ },
156
+ onStart: onActionStart,
157
+ onAbort: (e) => {
158
+ // user might want to re-submit as is
159
+ // or change the ui state before re-submitting
160
+ // we can't decide for him
161
+ onActionAbort?.(e);
162
+ },
163
+ onError: (e) => {
164
+ // user might want to re-submit as is
165
+ // or change the ui state before re-submitting
166
+ // we can't decide for him
167
+ onActionError?.(e);
168
+ },
169
+ onEnd: (e) => {
170
+ // form side effect is a success
171
+ // we can get rid of the nav state
172
+ // that was keeping the ui state in case user navigates away without submission
173
+ uiStateController.actionEnd(e);
174
+ onActionEnd?.(e);
175
+ },
176
+ });
177
+ const innerLoading = loading || actionPending;
178
+
179
+ return (
180
+ <FormBasic
181
+ data-action={actionBoundToUIState.name}
182
+ data-method={action.meta?.httpVerb || method || "GET"}
183
+ {...rest}
184
+ ref={innerRef}
185
+ loading={innerLoading}
186
+ onrequestsubmit={(e) => {
187
+ // prevent "submit" event that would be dispatched by the browser after form.requestSubmit()
188
+ // (not super important because our <form> listen the "action" and do does preventDefault on "submit")
189
+ e.preventDefault();
190
+ requestAction(e.target, actionBoundToUIState, {
191
+ event: e,
192
+ actionOrigin: "action_prop",
193
+ });
194
+ }}
195
+ >
196
+ <LoadingElementContext.Provider value={formActionRequester}>
197
+ {children}
198
+ </LoadingElementContext.Provider>
199
+ </FormBasic>
200
+ );
201
+ });
202
+
203
+ // const dispatchCustomEventOnFormAndFormElements = (type, options) => {
204
+ // const form = innerRef.current;
205
+ // const customEvent = new CustomEvent(type, options);
206
+ // // https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/elements
207
+ // for (const element of form.elements) {
208
+ // element.dispatchEvent(customEvent);
209
+ // }
210
+ // form.dispatchEvent(customEvent);
211
+ // };
@@ -1,4 +1,5 @@
1
1
  import { forwardRef } from "preact/compat";
2
+
2
3
  import { InputCheckbox } from "./input_checkbox.jsx";
3
4
  import { InputRadio } from "./input_radio.jsx";
4
5
  import { InputTextual } from "./input_textual.jsx";