@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.
- package/dist/jsenv_navi.js +22959 -0
- package/index.js +66 -16
- package/package.json +23 -11
- package/src/actions.js +50 -26
- package/src/browser_integration/browser_integration.js +31 -6
- package/src/browser_integration/via_history.js +42 -9
- package/src/components/action_execution/render_actionable_component.jsx +6 -4
- package/src/components/action_execution/use_action.js +51 -282
- package/src/components/action_execution/use_execute_action.js +106 -92
- package/src/components/action_execution/use_run_on_mount.js +9 -0
- package/src/components/action_renderer.jsx +21 -32
- package/src/components/demos/0_button_demo.html +574 -103
- package/src/components/demos/10_column_reordering_debug.html +277 -0
- package/src/components/demos/11_table_selection_debug.html +432 -0
- package/src/components/demos/1_checkbox_demo.html +579 -202
- package/src/components/demos/2_input_textual_demo.html +81 -138
- package/src/components/demos/3_radio_demo.html +0 -2
- package/src/components/demos/4_select_demo.html +19 -23
- package/src/components/demos/6_tablist_demo.html +77 -0
- package/src/components/demos/7_table_selection_demo.html +176 -0
- package/src/components/demos/8_table_fixed_headers_demo.html +584 -0
- package/src/components/demos/9_table_column_drag_demo.html +325 -0
- package/src/components/demos/action/0_button_demo.html +2 -4
- package/src/components/demos/action/1_input_text_demo.html +643 -222
- package/src/components/demos/action/3_details_demo.html +146 -115
- package/src/components/demos/action/4_input_checkbox_demo.html +442 -322
- package/src/components/demos/action/5_input_checkbox_state_demo.html +270 -0
- package/src/components/demos/action/6_checkbox_list_demo.html +304 -72
- package/src/components/demos/action/7_radio_list_demo.html +310 -170
- package/src/components/demos/action/{8_editable_text_demo.html → 8_editable_demo.html} +65 -76
- package/src/components/demos/action/9_link_demo.html +84 -62
- package/src/components/demos/ui_transition/0_action_renderer_ui_transition_demo.html +695 -0
- package/src/components/demos/ui_transition/1_nested_ui_transition_demo.html +429 -0
- package/src/components/demos/ui_transition/2_height_transition_test.html +295 -0
- package/src/components/details/details.jsx +62 -64
- package/src/components/edition/editable.jsx +186 -0
- package/src/components/field/README.md +247 -0
- package/src/components/{input → field}/button.jsx +151 -130
- package/src/components/field/checkbox_list.jsx +184 -0
- package/src/components/{collect_form_element_values.js → field/collect_form_element_values.js} +7 -4
- package/src/components/{input → field}/field_css.js +4 -1
- package/src/components/field/form.jsx +211 -0
- package/src/components/{input → field}/input.jsx +1 -0
- package/src/components/{input → field}/input_checkbox.jsx +132 -155
- package/src/components/{input → field}/input_radio.jsx +135 -46
- package/src/components/field/input_textual.jsx +418 -0
- package/src/components/field/label.jsx +32 -0
- package/src/components/field/radio_list.jsx +182 -0
- package/src/components/{input → field}/select.jsx +17 -32
- package/src/components/field/use_action_events.js +132 -0
- package/src/components/field/use_form_events.js +55 -0
- package/src/components/field/use_ui_state_controller.js +506 -0
- package/src/components/item_tracker/README.md +461 -0
- package/src/components/item_tracker/use_isolated_item_tracker.jsx +209 -0
- package/src/components/item_tracker/use_isolated_item_tracker_demo.html +148 -0
- package/src/components/item_tracker/use_isolated_item_tracker_demo.jsx +460 -0
- package/src/components/item_tracker/use_item_tracker.jsx +143 -0
- package/src/components/item_tracker/use_item_tracker_demo.html +207 -0
- package/src/components/item_tracker/use_item_tracker_demo.jsx +216 -0
- package/src/components/keyboard_shortcuts/active_keyboard_shortcuts.jsx +87 -0
- package/src/components/keyboard_shortcuts/aria_key_shortcuts.js +61 -0
- package/src/components/keyboard_shortcuts/keyboard_key_meta.js +17 -0
- package/src/components/keyboard_shortcuts/keyboard_shortcuts.js +371 -0
- package/src/components/link/link.jsx +65 -102
- package/src/components/link/link_with_icon.jsx +52 -0
- package/src/components/loader/loader_background.jsx +85 -64
- package/src/components/loader/rectangle_loading.jsx +38 -19
- package/src/components/route.jsx +8 -4
- package/src/components/selection/selection.jsx +1583 -0
- package/src/components/svg/font_sized_svg.jsx +45 -0
- package/src/components/svg/icon_and_text.jsx +21 -0
- package/src/components/svg/svg_mask_overlay.jsx +105 -0
- package/src/components/table/drag/table_drag.jsx +506 -0
- package/src/components/table/resize/table_resize.jsx +650 -0
- package/src/components/table/resize/table_size.js +43 -0
- package/src/components/table/selection/table_selection.js +106 -0
- package/src/components/table/selection/table_selection.jsx +203 -0
- package/src/components/table/sticky/sticky_group.js +354 -0
- package/src/components/table/sticky/table_sticky.js +25 -0
- package/src/components/table/sticky/table_sticky.jsx +501 -0
- package/src/components/table/table.jsx +721 -0
- package/src/components/table/table_css.js +211 -0
- package/src/components/table/table_ui.jsx +49 -0
- package/src/components/table/use_cells_and_columns.js +90 -0
- package/src/components/table/use_object_array_to_cells.js +46 -0
- package/src/components/table/z_indexes.js +23 -0
- package/src/components/tablist/tablist.jsx +99 -0
- package/src/components/text/overflow.jsx +15 -0
- package/src/components/text/text_and_count.jsx +28 -0
- package/src/components/ui_transition.jsx +128 -0
- package/src/components/use_auto_focus.js +58 -7
- package/src/components/use_batch_during_render.js +33 -0
- package/src/components/use_debounce_true.js +7 -7
- package/src/components/use_dependencies_diff.js +35 -0
- package/src/components/use_focus_group.js +4 -3
- package/src/components/use_initial_value.js +8 -34
- package/src/components/use_signal_sync.js +1 -1
- package/src/components/use_stable_callback.js +68 -0
- package/src/components/use_state_array.js +16 -9
- package/src/docs/actions.md +22 -0
- package/src/notes.md +33 -12
- package/src/route/route.js +97 -47
- package/src/store/resource_graph.js +2 -1
- package/src/store/tests/{resource_graph_dependencies.test.js → resource_graph_dependencies.test_manual.js} +13 -13
- package/src/utils/is_signal.js +20 -0
- package/src/utils/stringify_for_display.js +4 -23
- package/src/validation/constraints/confirm_constraint.js +14 -0
- package/src/validation/constraints/create_unique_value_constraint.js +27 -0
- package/src/validation/constraints/native_constraints.js +313 -0
- package/src/validation/constraints/readonly_constraint.js +36 -0
- package/src/validation/constraints/single_space_constraint.js +13 -0
- package/src/validation/custom_constraint_validation.js +599 -0
- package/src/validation/custom_message.js +18 -0
- package/src/validation/demos/browser_style.png +0 -0
- package/src/validation/demos/form_validation_demo.html +142 -0
- package/src/validation/demos/form_validation_demo_preact.html +87 -0
- package/src/validation/demos/form_validation_native_popover_demo.html +168 -0
- package/src/validation/demos/form_validation_vs_native_demo.html +172 -0
- package/src/validation/demos/validation_message_demo.html +203 -0
- package/src/validation/hooks/use_constraints.js +23 -0
- package/src/validation/hooks/use_custom_validation_ref.js +73 -0
- package/src/validation/hooks/use_validation_message.js +19 -0
- package/src/validation/validation_message.js +741 -0
- package/src/components/editable_text/editable_text.jsx +0 -96
- package/src/components/form.jsx +0 -144
- package/src/components/input/checkbox_list.jsx +0 -294
- package/src/components/input/field.jsx +0 -61
- package/src/components/input/input_textual.jsx +0 -338
- package/src/components/input/radio_list.jsx +0 -283
- package/src/components/input/use_form_event.js +0 -20
- package/src/components/input/use_on_change.js +0 -12
- package/src/components/selection/selection.js +0 -5
- package/src/components/selection/selection_context.jsx +0 -262
- package/src/components/shortcut/shortcut_context.jsx +0 -390
- package/src/components/use_action_events.js +0 -37
- package/src/utils/iterable_weak_set.js +0 -62
- /package/src/components/demos/action/{11_nested_shortcuts_demo.html → 11_nested_shortcuts_demo.xhtml} +0 -0
- /package/src/components/{shortcut → keyboard_shortcuts}/os.js +0 -0
- /package/src/route/{route.test.html → route.xtest.html} +0 -0
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import { requestAction } from "@jsenv/validation";
|
|
2
1
|
import { forwardRef } from "preact/compat";
|
|
3
2
|
import { useEffect, useImperativeHandle, useRef, useState } from "preact/hooks";
|
|
3
|
+
|
|
4
4
|
import { useNavState } from "../../browser_integration/browser_integration.js";
|
|
5
5
|
import { useActionStatus } from "../../use_action_status.js";
|
|
6
|
+
import { requestAction } from "../../validation/custom_constraint_validation.js";
|
|
6
7
|
import { renderActionableComponent } from "../action_execution/render_actionable_component.jsx";
|
|
7
|
-
import {
|
|
8
|
-
useActionBoundToOneParam,
|
|
9
|
-
useOneFormParam,
|
|
10
|
-
} from "../action_execution/use_action.js";
|
|
8
|
+
import { useActionBoundToOneParam } from "../action_execution/use_action.js";
|
|
11
9
|
import { useExecuteAction } from "../action_execution/use_execute_action.js";
|
|
12
10
|
import { LoaderBackground } from "../loader/loader_background.jsx";
|
|
13
|
-
import { useActionEvents } from "../use_action_events.js";
|
|
14
11
|
import { useRefArray } from "../use_ref_array.js";
|
|
15
|
-
import {
|
|
12
|
+
import { useActionEvents } from "./use_action_events.js";
|
|
13
|
+
import { useFormEvents } from "./use_form_events.js";
|
|
16
14
|
|
|
17
15
|
import.meta.css = /* css */ `
|
|
18
16
|
.navi_select[data-readonly] {
|
|
@@ -21,11 +19,12 @@ import.meta.css = /* css */ `
|
|
|
21
19
|
`;
|
|
22
20
|
|
|
23
21
|
export const Select = forwardRef((props, ref) => {
|
|
24
|
-
|
|
22
|
+
const select = renderActionableComponent(props, ref, {
|
|
25
23
|
Basic: SelectBasic,
|
|
26
24
|
WithAction: SelectWithAction,
|
|
27
25
|
InsideForm: SelectInsideForm,
|
|
28
26
|
});
|
|
27
|
+
return select;
|
|
29
28
|
});
|
|
30
29
|
|
|
31
30
|
const SelectControlled = forwardRef((props, ref) => {
|
|
@@ -137,7 +136,7 @@ const SelectWithAction = forwardRef((props, ref) => {
|
|
|
137
136
|
useImperativeHandle(ref, () => innerRef.current);
|
|
138
137
|
|
|
139
138
|
const [navState, setNavState, resetNavState] = useNavState(id);
|
|
140
|
-
const [boundAction, value, setValue,
|
|
139
|
+
const [boundAction, value, setValue, initialValue] = useActionBoundToOneParam(
|
|
141
140
|
action,
|
|
142
141
|
name,
|
|
143
142
|
valueSignal ? valueSignal : externalValue,
|
|
@@ -155,7 +154,7 @@ const SelectWithAction = forwardRef((props, ref) => {
|
|
|
155
154
|
useActionEvents(innerRef, {
|
|
156
155
|
onCancel: (e, reason) => {
|
|
157
156
|
resetNavState();
|
|
158
|
-
|
|
157
|
+
setValue(initialValue);
|
|
159
158
|
onCancel?.(e, reason);
|
|
160
159
|
},
|
|
161
160
|
onPrevented: onActionPrevented,
|
|
@@ -165,11 +164,11 @@ const SelectWithAction = forwardRef((props, ref) => {
|
|
|
165
164
|
},
|
|
166
165
|
onStart: onActionStart,
|
|
167
166
|
onAbort: (e) => {
|
|
168
|
-
|
|
167
|
+
setValue(initialValue);
|
|
169
168
|
onActionAbort?.(e);
|
|
170
169
|
},
|
|
171
170
|
onError: (error) => {
|
|
172
|
-
|
|
171
|
+
setValue(initialValue);
|
|
173
172
|
onActionError?.(error);
|
|
174
173
|
},
|
|
175
174
|
onEnd: () => {
|
|
@@ -194,10 +193,10 @@ const SelectWithAction = forwardRef((props, ref) => {
|
|
|
194
193
|
const optionSelected = select.querySelector(
|
|
195
194
|
`option[value="${selectedValue}"]`,
|
|
196
195
|
);
|
|
197
|
-
requestAction(boundAction, {
|
|
196
|
+
requestAction(radioListContainer, boundAction, {
|
|
198
197
|
event,
|
|
199
|
-
target: radioListContainer,
|
|
200
198
|
requester: optionSelected,
|
|
199
|
+
actionOrigin: "action_prop",
|
|
201
200
|
});
|
|
202
201
|
}}
|
|
203
202
|
{...rest}
|
|
@@ -218,26 +217,13 @@ const SelectWithAction = forwardRef((props, ref) => {
|
|
|
218
217
|
});
|
|
219
218
|
|
|
220
219
|
const SelectInsideForm = forwardRef((props, ref) => {
|
|
221
|
-
const {
|
|
222
|
-
formContext,
|
|
223
|
-
id,
|
|
224
|
-
name,
|
|
225
|
-
readOnly,
|
|
226
|
-
value: externalValue,
|
|
227
|
-
children,
|
|
228
|
-
...rest
|
|
229
|
-
} = props;
|
|
230
|
-
const { formIsReadOnly } = formContext;
|
|
220
|
+
const { id, name, value: externalValue, children, ...rest } = props;
|
|
231
221
|
|
|
232
222
|
const innerRef = useRef();
|
|
233
223
|
useImperativeHandle(ref, () => innerRef.current);
|
|
234
224
|
|
|
235
225
|
const [navState, setNavState] = useNavState(id);
|
|
236
|
-
const [value, setValue,
|
|
237
|
-
name,
|
|
238
|
-
externalValue,
|
|
239
|
-
navState,
|
|
240
|
-
);
|
|
226
|
+
const [value, setValue, initialValue] = [name, externalValue, navState];
|
|
241
227
|
useEffect(() => {
|
|
242
228
|
setNavState(value);
|
|
243
229
|
}, [value]);
|
|
@@ -247,10 +233,10 @@ const SelectInsideForm = forwardRef((props, ref) => {
|
|
|
247
233
|
setValue(undefined);
|
|
248
234
|
},
|
|
249
235
|
onFormActionAbort: () => {
|
|
250
|
-
|
|
236
|
+
setValue(initialValue);
|
|
251
237
|
},
|
|
252
238
|
onFormActionError: () => {
|
|
253
|
-
|
|
239
|
+
setValue(initialValue);
|
|
254
240
|
},
|
|
255
241
|
});
|
|
256
242
|
|
|
@@ -259,7 +245,6 @@ const SelectInsideForm = forwardRef((props, ref) => {
|
|
|
259
245
|
ref={innerRef}
|
|
260
246
|
name={name}
|
|
261
247
|
value={value}
|
|
262
|
-
readOnly={readOnly || formIsReadOnly}
|
|
263
248
|
onChange={(event) => {
|
|
264
249
|
const select = event.target;
|
|
265
250
|
const selectedValue = select.checked;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { useLayoutEffect, useState } from "preact/hooks";
|
|
2
|
+
|
|
3
|
+
import { addManyEventListeners } from "../../utils/add_many_event_listeners.js";
|
|
4
|
+
import { useStableCallback } from "../use_stable_callback.js";
|
|
5
|
+
|
|
6
|
+
export const useActionEvents = (
|
|
7
|
+
elementRef,
|
|
8
|
+
{
|
|
9
|
+
actionOrigin = "action_prop",
|
|
10
|
+
/**
|
|
11
|
+
* @param {Event} e - L'événement original
|
|
12
|
+
* @param {"form_reset" | "blur_invalid" | "escape_key"} reason - Raison du cancel
|
|
13
|
+
*/
|
|
14
|
+
onCancel,
|
|
15
|
+
onRequested,
|
|
16
|
+
onPrevented,
|
|
17
|
+
onAction,
|
|
18
|
+
onStart,
|
|
19
|
+
onAbort,
|
|
20
|
+
onError,
|
|
21
|
+
onEnd,
|
|
22
|
+
},
|
|
23
|
+
) => {
|
|
24
|
+
onCancel = useStableCallback(onCancel);
|
|
25
|
+
onRequested = useStableCallback(onRequested);
|
|
26
|
+
onPrevented = useStableCallback(onPrevented);
|
|
27
|
+
onAction = useStableCallback(onAction);
|
|
28
|
+
onStart = useStableCallback(onStart);
|
|
29
|
+
onAbort = useStableCallback(onAbort);
|
|
30
|
+
onError = useStableCallback(onError);
|
|
31
|
+
onEnd = useStableCallback(onEnd);
|
|
32
|
+
|
|
33
|
+
useLayoutEffect(() => {
|
|
34
|
+
const element = elementRef.current;
|
|
35
|
+
if (!element) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return addManyEventListeners(element, {
|
|
40
|
+
cancel: (e) => {
|
|
41
|
+
// cancel don't need to check for actionOrigin because
|
|
42
|
+
// it's actually unrelated to a specific actions
|
|
43
|
+
// in that sense it should likely be moved elsewhere as it's related to
|
|
44
|
+
// interaction and constraint validation, not to a specific action
|
|
45
|
+
onCancel?.(e, e.detail.reason);
|
|
46
|
+
},
|
|
47
|
+
actionrequested: (e) => {
|
|
48
|
+
if (e.detail.actionOrigin !== actionOrigin) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
onRequested?.(e);
|
|
52
|
+
},
|
|
53
|
+
actionprevented: (e) => {
|
|
54
|
+
if (e.detail.actionOrigin !== actionOrigin) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
onPrevented?.(e);
|
|
58
|
+
},
|
|
59
|
+
action: (e) => {
|
|
60
|
+
if (e.detail.actionOrigin !== actionOrigin) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
onAction?.(e);
|
|
64
|
+
},
|
|
65
|
+
actionstart: (e) => {
|
|
66
|
+
if (e.detail.actionOrigin !== actionOrigin) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
onStart?.(e);
|
|
70
|
+
},
|
|
71
|
+
actionabort: (e) => {
|
|
72
|
+
if (e.detail.actionOrigin !== actionOrigin) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
onAbort?.(e);
|
|
76
|
+
},
|
|
77
|
+
actionerror: (e) => {
|
|
78
|
+
if (e.detail.actionOrigin !== actionOrigin) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
onError?.(e.detail.error, e);
|
|
82
|
+
},
|
|
83
|
+
actionend: onEnd,
|
|
84
|
+
});
|
|
85
|
+
}, [
|
|
86
|
+
actionOrigin,
|
|
87
|
+
onCancel,
|
|
88
|
+
onRequested,
|
|
89
|
+
onPrevented,
|
|
90
|
+
onAction,
|
|
91
|
+
onStart,
|
|
92
|
+
onAbort,
|
|
93
|
+
onError,
|
|
94
|
+
onEnd,
|
|
95
|
+
]);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const useRequestedActionStatus = (elementRef) => {
|
|
99
|
+
const [actionRequester, setActionRequester] = useState(null);
|
|
100
|
+
const [actionPending, setActionPending] = useState(false);
|
|
101
|
+
const [actionAborted, setActionAborted] = useState(false);
|
|
102
|
+
const [actionError, setActionError] = useState(null);
|
|
103
|
+
|
|
104
|
+
useActionEvents(elementRef, {
|
|
105
|
+
onAction: (actionEvent) => {
|
|
106
|
+
setActionRequester(actionEvent.detail.requester);
|
|
107
|
+
},
|
|
108
|
+
onStart: () => {
|
|
109
|
+
setActionPending(true);
|
|
110
|
+
setActionAborted(false);
|
|
111
|
+
setActionError(null);
|
|
112
|
+
},
|
|
113
|
+
onAbort: () => {
|
|
114
|
+
setActionPending(false);
|
|
115
|
+
setActionAborted(true);
|
|
116
|
+
},
|
|
117
|
+
onError: (error) => {
|
|
118
|
+
setActionPending(false);
|
|
119
|
+
setActionError(error);
|
|
120
|
+
},
|
|
121
|
+
onEnd: () => {
|
|
122
|
+
setActionPending(false);
|
|
123
|
+
},
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
actionRequester,
|
|
128
|
+
actionPending,
|
|
129
|
+
actionAborted,
|
|
130
|
+
actionError,
|
|
131
|
+
};
|
|
132
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useLayoutEffect } from "preact/hooks";
|
|
2
|
+
|
|
3
|
+
import { addManyEventListeners } from "../../utils/add_many_event_listeners.js";
|
|
4
|
+
import { useStableCallback } from "../use_stable_callback.js";
|
|
5
|
+
|
|
6
|
+
export const useFormEvents = (
|
|
7
|
+
elementRef,
|
|
8
|
+
{
|
|
9
|
+
onFormReset,
|
|
10
|
+
onFormActionPrevented,
|
|
11
|
+
onFormActionStart,
|
|
12
|
+
onFormActionAbort,
|
|
13
|
+
onFormActionError,
|
|
14
|
+
onFormActionEnd,
|
|
15
|
+
},
|
|
16
|
+
) => {
|
|
17
|
+
onFormReset = useStableCallback(onFormReset);
|
|
18
|
+
onFormActionPrevented = useStableCallback(onFormActionPrevented);
|
|
19
|
+
onFormActionStart = useStableCallback(onFormActionStart);
|
|
20
|
+
onFormActionAbort = useStableCallback(onFormActionAbort);
|
|
21
|
+
onFormActionError = useStableCallback(onFormActionError);
|
|
22
|
+
onFormActionEnd = useStableCallback(onFormActionEnd);
|
|
23
|
+
|
|
24
|
+
useLayoutEffect(() => {
|
|
25
|
+
const element = elementRef.current;
|
|
26
|
+
if (!element) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let form = element.form;
|
|
31
|
+
if (!form) {
|
|
32
|
+
// some non input elements may want to listen form events (<RadioList> is a <div>)
|
|
33
|
+
form = element.closest("form");
|
|
34
|
+
if (!form) {
|
|
35
|
+
console.warn("No form found for element", element);
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return addManyEventListeners(form, {
|
|
40
|
+
reset: onFormReset,
|
|
41
|
+
actionprevented: onFormActionPrevented,
|
|
42
|
+
actionstart: onFormActionStart,
|
|
43
|
+
actionabort: onFormActionAbort,
|
|
44
|
+
actionerror: onFormActionError,
|
|
45
|
+
actionend: onFormActionEnd,
|
|
46
|
+
});
|
|
47
|
+
}, [
|
|
48
|
+
onFormReset,
|
|
49
|
+
onFormActionPrevented,
|
|
50
|
+
onFormActionStart,
|
|
51
|
+
onFormActionAbort,
|
|
52
|
+
onFormActionError,
|
|
53
|
+
onFormActionEnd,
|
|
54
|
+
]);
|
|
55
|
+
};
|