@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
|
@@ -65,33 +65,6 @@
|
|
|
65
65
|
gap: 10px;
|
|
66
66
|
margin-top: 10px;
|
|
67
67
|
}
|
|
68
|
-
button {
|
|
69
|
-
padding: 8px 16px;
|
|
70
|
-
border: 1px solid #ccc;
|
|
71
|
-
border-radius: 4px;
|
|
72
|
-
background: white;
|
|
73
|
-
cursor: pointer;
|
|
74
|
-
font-size: 14px;
|
|
75
|
-
}
|
|
76
|
-
button:hover {
|
|
77
|
-
background: #f8f9fa;
|
|
78
|
-
}
|
|
79
|
-
button[type="submit"] {
|
|
80
|
-
background: #007bff;
|
|
81
|
-
color: white;
|
|
82
|
-
border-color: #007bff;
|
|
83
|
-
}
|
|
84
|
-
button[type="submit"]:hover {
|
|
85
|
-
background: #0056b3;
|
|
86
|
-
}
|
|
87
|
-
button[type="reset"] {
|
|
88
|
-
background: #6c757d;
|
|
89
|
-
color: white;
|
|
90
|
-
border-color: #6c757d;
|
|
91
|
-
}
|
|
92
|
-
button[type="reset"]:hover {
|
|
93
|
-
background: #545b62;
|
|
94
|
-
}
|
|
95
68
|
.control-group {
|
|
96
69
|
margin-bottom: 15px;
|
|
97
70
|
}
|
|
@@ -140,6 +113,24 @@
|
|
|
140
113
|
opacity: 0.5;
|
|
141
114
|
}
|
|
142
115
|
}
|
|
116
|
+
nav a {
|
|
117
|
+
color: #007bff;
|
|
118
|
+
text-decoration: none;
|
|
119
|
+
}
|
|
120
|
+
nav a:hover {
|
|
121
|
+
text-decoration: underline;
|
|
122
|
+
}
|
|
123
|
+
h2 {
|
|
124
|
+
margin-top: 40px;
|
|
125
|
+
margin-bottom: 20px;
|
|
126
|
+
padding-top: 20px;
|
|
127
|
+
border-top: 2px solid #e0e0e0;
|
|
128
|
+
}
|
|
129
|
+
h2:first-of-type {
|
|
130
|
+
margin-top: 0;
|
|
131
|
+
border-top: none;
|
|
132
|
+
padding-top: 0;
|
|
133
|
+
}
|
|
143
134
|
</style>
|
|
144
135
|
</head>
|
|
145
136
|
<body>
|
|
@@ -148,13 +139,10 @@
|
|
|
148
139
|
|
|
149
140
|
<script type="module" jsenv-type="module/jsx">
|
|
150
141
|
import { render } from "preact";
|
|
151
|
-
import { useState } from "preact/hooks";
|
|
152
|
-
import { signal } from "@preact/signals";
|
|
142
|
+
import { useState, useRef } from "preact/hooks";
|
|
153
143
|
import {
|
|
154
144
|
createAction,
|
|
155
145
|
// eslint-disable-next-line no-unused-vars
|
|
156
|
-
Field,
|
|
157
|
-
// eslint-disable-next-line no-unused-vars
|
|
158
146
|
Form,
|
|
159
147
|
// eslint-disable-next-line no-unused-vars
|
|
160
148
|
Input,
|
|
@@ -166,53 +154,148 @@
|
|
|
166
154
|
|
|
167
155
|
// eslint-disable-next-line no-unused-vars
|
|
168
156
|
const App = () => {
|
|
157
|
+
const [checkboxBackgroundColor, setCheckboxBackgroundColor] =
|
|
158
|
+
useState(undefined);
|
|
159
|
+
|
|
169
160
|
return (
|
|
170
161
|
<>
|
|
162
|
+
<div className="demo-card" style={{ marginBottom: "30px" }}>
|
|
163
|
+
<h2>Checkbox Demo - Overview</h2>
|
|
164
|
+
<p>
|
|
165
|
+
This demo showcases different ways to use the Input component
|
|
166
|
+
with checkboxes.
|
|
167
|
+
</p>
|
|
168
|
+
|
|
169
|
+
<div
|
|
170
|
+
className="control-group"
|
|
171
|
+
style={{
|
|
172
|
+
marginBottom: "20px",
|
|
173
|
+
padding: "15px",
|
|
174
|
+
backgroundColor: "#f8f9fa",
|
|
175
|
+
borderRadius: "8px",
|
|
176
|
+
}}
|
|
177
|
+
>
|
|
178
|
+
<label>
|
|
179
|
+
<strong>Global Checkbox Background Color:</strong>
|
|
180
|
+
<select
|
|
181
|
+
value={checkboxBackgroundColor || ""}
|
|
182
|
+
onChange={(e) =>
|
|
183
|
+
setCheckboxBackgroundColor(e.target.value || undefined)
|
|
184
|
+
}
|
|
185
|
+
style={{
|
|
186
|
+
marginLeft: "10px",
|
|
187
|
+
padding: "5px 10px",
|
|
188
|
+
borderRadius: "4px",
|
|
189
|
+
border: "1px solid #ccc",
|
|
190
|
+
}}
|
|
191
|
+
>
|
|
192
|
+
<option value="">Default</option>
|
|
193
|
+
<option value="#ff6b6b">Red</option>
|
|
194
|
+
<option value="#51cf66">Green</option>
|
|
195
|
+
</select>
|
|
196
|
+
</label>
|
|
197
|
+
<p
|
|
198
|
+
style={{
|
|
199
|
+
fontSize: "14px",
|
|
200
|
+
color: "#666",
|
|
201
|
+
margin: "8px 0 0 0",
|
|
202
|
+
}}
|
|
203
|
+
>
|
|
204
|
+
This affects all checkboxes below and demonstrates that
|
|
205
|
+
background color changes don't affect checked state.
|
|
206
|
+
</p>
|
|
207
|
+
</div>
|
|
208
|
+
|
|
209
|
+
<nav>
|
|
210
|
+
<h3>Sections:</h3>
|
|
211
|
+
<ul style={{ marginLeft: "20px" }}>
|
|
212
|
+
<li>
|
|
213
|
+
<a href="#basic-checkboxes">
|
|
214
|
+
1. Basic Checkbox (no action/no form)
|
|
215
|
+
</a>{" "}
|
|
216
|
+
- Simple checkboxes with value handling
|
|
217
|
+
</li>
|
|
218
|
+
<li>
|
|
219
|
+
<a href="#checkbox-actions">2. Checkbox with Actions</a> -
|
|
220
|
+
Checkboxes that trigger actions on change, including error
|
|
221
|
+
handling
|
|
222
|
+
</li>
|
|
223
|
+
<li>
|
|
224
|
+
<a href="#checkbox-forms">3. Checkbox inside Form</a> - Form
|
|
225
|
+
integration patterns
|
|
226
|
+
</li>
|
|
227
|
+
</ul>
|
|
228
|
+
</nav>
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<h2 id="basic-checkboxes">1. Basic Checkbox (no action/no form)</h2>
|
|
232
|
+
<div className="demo-grid">
|
|
233
|
+
<CheckboxDemo backgroundColor={checkboxBackgroundColor} />
|
|
234
|
+
<CheckboxDefaultCheckedDemo
|
|
235
|
+
backgroundColor={checkboxBackgroundColor}
|
|
236
|
+
/>
|
|
237
|
+
</div>
|
|
238
|
+
|
|
239
|
+
<h2 id="checkbox-actions">2. Checkbox with Actions</h2>
|
|
240
|
+
<div className="demo-grid">
|
|
241
|
+
<CheckboxActionDemo backgroundColor={checkboxBackgroundColor} />
|
|
242
|
+
<CheckboxActionDefaultCheckedDemo
|
|
243
|
+
backgroundColor={checkboxBackgroundColor}
|
|
244
|
+
/>
|
|
245
|
+
<CheckboxActionErrorDemo
|
|
246
|
+
backgroundColor={checkboxBackgroundColor}
|
|
247
|
+
/>
|
|
248
|
+
<CheckboxActionErrorDefaultCheckedDemo
|
|
249
|
+
backgroundColor={checkboxBackgroundColor}
|
|
250
|
+
/>
|
|
251
|
+
<CheckboxActionErrorOnUncheckedDemo
|
|
252
|
+
backgroundColor={checkboxBackgroundColor}
|
|
253
|
+
/>
|
|
254
|
+
<CheckboxActionObjectDemo
|
|
255
|
+
backgroundColor={checkboxBackgroundColor}
|
|
256
|
+
/>
|
|
257
|
+
</div>
|
|
258
|
+
|
|
259
|
+
<h2 id="checkbox-forms">3. Checkbox inside Form</h2>
|
|
171
260
|
<div className="demo-grid">
|
|
172
|
-
<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
<CheckboxWithSignalControlDemo />
|
|
176
|
-
<CheckboxErrorDemo />
|
|
177
|
-
<FormCheckboxDemo />
|
|
178
|
-
<SharedActionDemo />
|
|
261
|
+
<CheckboxFormControlledErrorDemo
|
|
262
|
+
backgroundColor={checkboxBackgroundColor}
|
|
263
|
+
/>
|
|
179
264
|
</div>
|
|
180
265
|
</>
|
|
181
266
|
);
|
|
182
267
|
};
|
|
183
268
|
|
|
184
269
|
// eslint-disable-next-line no-unused-vars
|
|
185
|
-
const
|
|
270
|
+
const CheckboxDemo = ({ backgroundColor }) => {
|
|
186
271
|
const [result, setResult] = useState("");
|
|
187
|
-
const [status
|
|
272
|
+
const [status] = useState("idle");
|
|
273
|
+
const ref = useRef();
|
|
188
274
|
|
|
189
275
|
return (
|
|
190
276
|
<div className="demo-card">
|
|
191
|
-
<h3 className="demo-title">
|
|
277
|
+
<h3 className="demo-title">
|
|
278
|
+
Basic Checkbox
|
|
279
|
+
<button
|
|
280
|
+
onClick={() => {
|
|
281
|
+
ref.current.dispatchEvent(new CustomEvent("resetuistate"));
|
|
282
|
+
}}
|
|
283
|
+
>
|
|
284
|
+
Reset
|
|
285
|
+
</button>
|
|
286
|
+
</h3>
|
|
192
287
|
<div className="control-group">
|
|
193
288
|
<div className="checkbox-group">
|
|
194
|
-
<
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
setResult(response);
|
|
205
|
-
setStatus("success");
|
|
206
|
-
return response;
|
|
207
|
-
} catch (error) {
|
|
208
|
-
setResult(`❌ Error: ${error.message}`);
|
|
209
|
-
setStatus("error");
|
|
210
|
-
throw error;
|
|
211
|
-
}
|
|
212
|
-
}}
|
|
213
|
-
/>
|
|
214
|
-
<label htmlFor="basic-checkbox">
|
|
215
|
-
<span className={`status-indicator status-${status}`}></span>
|
|
289
|
+
<label>
|
|
290
|
+
<Input
|
|
291
|
+
ref={ref}
|
|
292
|
+
type="checkbox"
|
|
293
|
+
name="enabled"
|
|
294
|
+
accentColor={backgroundColor}
|
|
295
|
+
onUIStateChange={(checked) => {
|
|
296
|
+
setResult(checked ? "checked" : "unchecked");
|
|
297
|
+
}}
|
|
298
|
+
/>
|
|
216
299
|
Enable feature
|
|
217
300
|
</label>
|
|
218
301
|
</div>
|
|
@@ -225,223 +308,198 @@
|
|
|
225
308
|
</div>
|
|
226
309
|
);
|
|
227
310
|
};
|
|
228
|
-
|
|
229
311
|
// eslint-disable-next-line no-unused-vars
|
|
230
|
-
const
|
|
312
|
+
const CheckboxDefaultCheckedDemo = ({ backgroundColor }) => {
|
|
231
313
|
const [result, setResult] = useState("");
|
|
314
|
+
const [status] = useState("idle");
|
|
315
|
+
const ref = useRef();
|
|
232
316
|
|
|
233
317
|
return (
|
|
234
318
|
<div className="demo-card">
|
|
235
|
-
<h3 className="demo-title">
|
|
319
|
+
<h3 className="demo-title">
|
|
320
|
+
Basic Checkbox (Default Checked)
|
|
321
|
+
<button
|
|
322
|
+
onClick={() => {
|
|
323
|
+
ref.current.dispatchEvent(new CustomEvent("resetuistate"));
|
|
324
|
+
}}
|
|
325
|
+
>
|
|
326
|
+
Reset
|
|
327
|
+
</button>
|
|
328
|
+
</h3>
|
|
236
329
|
<div className="control-group">
|
|
237
330
|
<div className="checkbox-group">
|
|
238
|
-
<
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
/>
|
|
251
|
-
<label htmlFor="initial-checkbox">
|
|
252
|
-
I agree to the terms and conditions
|
|
331
|
+
<label>
|
|
332
|
+
<Input
|
|
333
|
+
ref={ref}
|
|
334
|
+
type="checkbox"
|
|
335
|
+
name="enabled"
|
|
336
|
+
defaultChecked
|
|
337
|
+
accentColor={backgroundColor}
|
|
338
|
+
onUIStateChange={(checked) => {
|
|
339
|
+
setResult(checked ? "checked" : "unchecked");
|
|
340
|
+
}}
|
|
341
|
+
/>
|
|
342
|
+
Enable feature
|
|
253
343
|
</label>
|
|
254
344
|
</div>
|
|
255
345
|
</div>
|
|
256
346
|
<div
|
|
257
|
-
className={`result-display ${
|
|
347
|
+
className={`result-display ${status === "loading" ? "result-loading" : status === "success" ? "result-success" : status === "error" ? "result-error" : ""}`}
|
|
258
348
|
>
|
|
259
|
-
{result || "
|
|
349
|
+
{result || "Check or uncheck to see action..."}
|
|
260
350
|
</div>
|
|
261
351
|
</div>
|
|
262
352
|
);
|
|
263
353
|
};
|
|
264
|
-
|
|
265
354
|
// eslint-disable-next-line no-unused-vars
|
|
266
|
-
const
|
|
267
|
-
const [isChecked, setIsChecked] = useState(undefined);
|
|
355
|
+
const CheckboxActionDemo = ({ backgroundColor }) => {
|
|
268
356
|
const [result, setResult] = useState("");
|
|
357
|
+
const [status, setStatus] = useState("idle");
|
|
269
358
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
359
|
+
return (
|
|
360
|
+
<div className="demo-card">
|
|
361
|
+
<h3 className="demo-title">Checkbox with Action</h3>
|
|
362
|
+
<div className="control-group">
|
|
363
|
+
<div className="checkbox-group">
|
|
364
|
+
<label>
|
|
365
|
+
<Input
|
|
366
|
+
type="checkbox"
|
|
367
|
+
name="enabled"
|
|
368
|
+
accentColor={backgroundColor}
|
|
369
|
+
action={async (enabled) => {
|
|
370
|
+
setStatus("loading");
|
|
371
|
+
setResult("Processing...");
|
|
372
|
+
try {
|
|
373
|
+
await delay(1000);
|
|
374
|
+
const response = `${enabled ? "✅" : "☐"} Checkbox ${enabled ? "checked" : "unchecked"}`;
|
|
375
|
+
setResult(response);
|
|
376
|
+
setStatus("success");
|
|
377
|
+
return response;
|
|
378
|
+
} catch (error) {
|
|
379
|
+
setResult(`❌ Error: ${error.message}`);
|
|
380
|
+
setStatus("error");
|
|
381
|
+
throw error;
|
|
382
|
+
}
|
|
383
|
+
}}
|
|
384
|
+
/>
|
|
385
|
+
<span className={`status-indicator status-${status}`}></span>
|
|
386
|
+
Enable feature
|
|
387
|
+
</label>
|
|
388
|
+
</div>
|
|
389
|
+
</div>
|
|
390
|
+
<div
|
|
391
|
+
className={`result-display ${status === "loading" ? "result-loading" : status === "success" ? "result-success" : status === "error" ? "result-error" : ""}`}
|
|
392
|
+
>
|
|
393
|
+
{result || "Check or uncheck to see action..."}
|
|
394
|
+
</div>
|
|
395
|
+
</div>
|
|
274
396
|
);
|
|
397
|
+
};
|
|
398
|
+
// eslint-disable-next-line no-unused-vars
|
|
399
|
+
const CheckboxActionDefaultCheckedDemo = ({ backgroundColor }) => {
|
|
400
|
+
const [result, setResult] = useState("");
|
|
275
401
|
|
|
276
402
|
return (
|
|
277
403
|
<div className="demo-card">
|
|
278
|
-
<h3 className="demo-title">
|
|
404
|
+
<h3 className="demo-title">
|
|
405
|
+
Checkbox with Action (Default Checked)
|
|
406
|
+
</h3>
|
|
279
407
|
<div className="control-group">
|
|
280
408
|
<div className="checkbox-group">
|
|
281
|
-
<
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
409
|
+
<label>
|
|
410
|
+
<Input
|
|
411
|
+
type="checkbox"
|
|
412
|
+
name="agreed"
|
|
413
|
+
defaultChecked
|
|
414
|
+
accentColor={backgroundColor}
|
|
415
|
+
action={async (agreed) => {
|
|
416
|
+
setResult("Processing...");
|
|
417
|
+
await delay(800);
|
|
418
|
+
const response = `${agreed ? "✅" : "☐"} Agreement: ${agreed ? "accepted" : "declined"}`;
|
|
419
|
+
setResult(response);
|
|
420
|
+
return response;
|
|
421
|
+
}}
|
|
422
|
+
/>
|
|
423
|
+
I agree to the terms and conditions
|
|
296
424
|
</label>
|
|
297
425
|
</div>
|
|
298
426
|
</div>
|
|
299
|
-
<div className="button-group">
|
|
300
|
-
<button
|
|
301
|
-
onClick={() => {
|
|
302
|
-
console.log("Setting checkbox to checked");
|
|
303
|
-
setIsChecked(true);
|
|
304
|
-
}}
|
|
305
|
-
>
|
|
306
|
-
Enable
|
|
307
|
-
</button>
|
|
308
|
-
<button
|
|
309
|
-
onClick={() => {
|
|
310
|
-
console.log("Setting checkbox to unchecked");
|
|
311
|
-
setIsChecked(false);
|
|
312
|
-
}}
|
|
313
|
-
>
|
|
314
|
-
Disable
|
|
315
|
-
</button>
|
|
316
|
-
<button
|
|
317
|
-
onClick={() => {
|
|
318
|
-
console.log(
|
|
319
|
-
"Resetting checkbox, current isChecked:",
|
|
320
|
-
isChecked,
|
|
321
|
-
);
|
|
322
|
-
setIsChecked(undefined);
|
|
323
|
-
}}
|
|
324
|
-
>
|
|
325
|
-
Reset
|
|
326
|
-
</button>
|
|
327
|
-
</div>
|
|
328
427
|
<div
|
|
329
428
|
className={`result-display ${result.startsWith("✅") || result.startsWith("☐") ? "result-success" : ""}`}
|
|
330
429
|
>
|
|
331
|
-
|
|
332
|
-
{isChecked === undefined
|
|
333
|
-
? "undefined"
|
|
334
|
-
: isChecked
|
|
335
|
-
? "checked"
|
|
336
|
-
: "unchecked"}
|
|
337
|
-
<br />
|
|
338
|
-
{result ||
|
|
339
|
-
"Use buttons to control checkbox, then it will trigger action..."}
|
|
430
|
+
{result || "Change checkbox to see action..."}
|
|
340
431
|
</div>
|
|
341
432
|
</div>
|
|
342
433
|
);
|
|
343
434
|
};
|
|
344
|
-
|
|
345
|
-
// Create an action that's bound to the signal
|
|
346
|
-
const toggleAction = createAction(async ({ notifications }) => {
|
|
347
|
-
await delay(600);
|
|
348
|
-
return `${notifications ? "✅" : "☐"} Notifications ${notifications ? "enabled" : "disabled"}`;
|
|
349
|
-
});
|
|
350
|
-
// Create a signal to control the checkbox state
|
|
351
|
-
const valueSignal = signal(undefined);
|
|
352
|
-
const toggleActionBound = toggleAction.bindParams({
|
|
353
|
-
notifications: valueSignal,
|
|
354
|
-
});
|
|
355
|
-
|
|
356
435
|
// eslint-disable-next-line no-unused-vars
|
|
357
|
-
const
|
|
436
|
+
const CheckboxActionErrorDemo = ({ backgroundColor }) => {
|
|
358
437
|
const [result, setResult] = useState("");
|
|
438
|
+
const [status, setStatus] = useState("idle");
|
|
359
439
|
|
|
360
440
|
return (
|
|
361
441
|
<div className="demo-card">
|
|
362
|
-
<h3 className="demo-title">Checkbox with
|
|
442
|
+
<h3 className="demo-title">Checkbox with Action (Always Fails)</h3>
|
|
363
443
|
<div className="control-group">
|
|
364
444
|
<div className="checkbox-group">
|
|
365
|
-
<
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
445
|
+
<label>
|
|
446
|
+
<Input
|
|
447
|
+
type="checkbox"
|
|
448
|
+
name="dangerous"
|
|
449
|
+
accentColor={backgroundColor}
|
|
450
|
+
action={async (dangerous) => {
|
|
451
|
+
setStatus("loading");
|
|
452
|
+
setResult("Processing...");
|
|
453
|
+
try {
|
|
454
|
+
await delay(1500);
|
|
455
|
+
throw new Error(
|
|
456
|
+
`Action failed for ${dangerous ? "checked" : "unchecked"} state`,
|
|
457
|
+
);
|
|
458
|
+
} catch (error) {
|
|
459
|
+
setResult(`❌ ${error.message}`);
|
|
460
|
+
setStatus("error");
|
|
461
|
+
throw error;
|
|
462
|
+
}
|
|
463
|
+
}}
|
|
464
|
+
/>
|
|
465
|
+
<span className={`status-indicator status-${status}`}></span>
|
|
466
|
+
Dangerous operation (always fails)
|
|
380
467
|
</label>
|
|
381
468
|
</div>
|
|
382
469
|
</div>
|
|
383
|
-
<div className="button-group">
|
|
384
|
-
<button
|
|
385
|
-
onClick={() => {
|
|
386
|
-
console.log("Setting signal to true");
|
|
387
|
-
valueSignal.value = "on";
|
|
388
|
-
}}
|
|
389
|
-
>
|
|
390
|
-
Enable via Signal
|
|
391
|
-
</button>
|
|
392
|
-
<button
|
|
393
|
-
onClick={() => {
|
|
394
|
-
console.log("Setting signal to false");
|
|
395
|
-
valueSignal.value = false;
|
|
396
|
-
}}
|
|
397
|
-
>
|
|
398
|
-
Disable via Signal
|
|
399
|
-
</button>
|
|
400
|
-
<button
|
|
401
|
-
onClick={() => {
|
|
402
|
-
console.log(
|
|
403
|
-
"Toggling signal, current value:",
|
|
404
|
-
valueSignal.value,
|
|
405
|
-
);
|
|
406
|
-
valueSignal.value = valueSignal.value === "on" ? false : "on";
|
|
407
|
-
}}
|
|
408
|
-
>
|
|
409
|
-
Toggle Signal
|
|
410
|
-
</button>
|
|
411
|
-
</div>
|
|
412
470
|
<div
|
|
413
|
-
className={`result-display ${
|
|
471
|
+
className={`result-display ${status === "loading" ? "result-loading" : status === "error" ? "result-error" : ""}`}
|
|
414
472
|
>
|
|
415
|
-
|
|
416
|
-
<br />
|
|
417
|
-
{result ||
|
|
418
|
-
"Use buttons to control checkbox via signal, action will trigger automatically..."}
|
|
473
|
+
{result || "This checkbox will always trigger an error..."}
|
|
419
474
|
</div>
|
|
420
475
|
</div>
|
|
421
476
|
);
|
|
422
477
|
};
|
|
423
|
-
|
|
424
478
|
// eslint-disable-next-line no-unused-vars
|
|
425
|
-
const
|
|
479
|
+
const CheckboxActionErrorDefaultCheckedDemo = ({ backgroundColor }) => {
|
|
426
480
|
const [result, setResult] = useState("");
|
|
427
481
|
const [status, setStatus] = useState("idle");
|
|
428
482
|
|
|
429
483
|
return (
|
|
430
484
|
<div className="demo-card">
|
|
431
|
-
<h3 className="demo-title">
|
|
485
|
+
<h3 className="demo-title">
|
|
486
|
+
Checkbox with Action (Default Checked, Always Fails)
|
|
487
|
+
</h3>
|
|
432
488
|
<div className="control-group">
|
|
433
489
|
<div className="checkbox-group">
|
|
434
490
|
<Input
|
|
435
|
-
id="error-checkbox"
|
|
491
|
+
id="error-initial-checkbox"
|
|
436
492
|
type="checkbox"
|
|
437
|
-
name="
|
|
438
|
-
|
|
493
|
+
name="risky"
|
|
494
|
+
defaultChecked
|
|
495
|
+
accentColor={backgroundColor}
|
|
496
|
+
action={async (risky) => {
|
|
439
497
|
setStatus("loading");
|
|
440
498
|
setResult("Processing...");
|
|
441
499
|
try {
|
|
442
|
-
await delay(
|
|
500
|
+
await delay(1200);
|
|
443
501
|
throw new Error(
|
|
444
|
-
`
|
|
502
|
+
`Operation failed for ${risky ? "enabled" : "disabled"} risky feature`,
|
|
445
503
|
);
|
|
446
504
|
} catch (error) {
|
|
447
505
|
setResult(`❌ ${error.message}`);
|
|
@@ -450,160 +508,222 @@
|
|
|
450
508
|
}
|
|
451
509
|
}}
|
|
452
510
|
/>
|
|
453
|
-
<label htmlFor="error-checkbox">
|
|
511
|
+
<label htmlFor="error-initial-checkbox">
|
|
454
512
|
<span className={`status-indicator status-${status}`}></span>
|
|
455
|
-
|
|
513
|
+
Enable risky feature (starts checked, always fails)
|
|
456
514
|
</label>
|
|
457
515
|
</div>
|
|
458
516
|
</div>
|
|
459
517
|
<div
|
|
460
518
|
className={`result-display ${status === "loading" ? "result-loading" : status === "error" ? "result-error" : ""}`}
|
|
461
519
|
>
|
|
462
|
-
{result ||
|
|
520
|
+
{result ||
|
|
521
|
+
"This checkbox starts checked and will always trigger an error..."}
|
|
463
522
|
</div>
|
|
464
523
|
</div>
|
|
465
524
|
);
|
|
466
525
|
};
|
|
467
526
|
|
|
468
527
|
// eslint-disable-next-line no-unused-vars
|
|
469
|
-
const
|
|
528
|
+
const CheckboxActionErrorOnUncheckedDemo = ({ backgroundColor }) => {
|
|
529
|
+
// for this example the checkbox is going to be controlled because that's how you would
|
|
530
|
+
// implement it in a real world scenario:
|
|
531
|
+
// the fact checkbox is checked comes from a backend so when the operation succeeds
|
|
532
|
+
// the component is re-rendered as checked
|
|
533
|
+
|
|
470
534
|
const [result, setResult] = useState("");
|
|
471
|
-
const [
|
|
535
|
+
const [status, setStatus] = useState("idle");
|
|
536
|
+
const [checked, setChecked] = useState(false);
|
|
472
537
|
|
|
473
538
|
return (
|
|
474
539
|
<div className="demo-card">
|
|
475
|
-
<h3 className="demo-title">
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
await delay(1200);
|
|
482
|
-
const prefs = [];
|
|
483
|
-
if (newsletter) prefs.push("newsletter");
|
|
484
|
-
if (updates) prefs.push("updates");
|
|
485
|
-
if (marketing) prefs.push("marketing");
|
|
486
|
-
const response = `✅ User: ${username}\nSubscriptions: ${prefs.length > 0 ? prefs.join(", ") : "none"}`;
|
|
487
|
-
setResult(response);
|
|
488
|
-
return response;
|
|
489
|
-
} catch (error) {
|
|
490
|
-
setResult(`❌ Form error: ${error.message}`);
|
|
491
|
-
throw error;
|
|
492
|
-
} finally {
|
|
493
|
-
setIsLoading(false);
|
|
494
|
-
}
|
|
495
|
-
}}
|
|
496
|
-
>
|
|
497
|
-
<input type="hidden" name="username" value="john_doe" />
|
|
498
|
-
<div className="control-group">
|
|
499
|
-
<div className="checkbox-group">
|
|
540
|
+
<h3 className="demo-title">
|
|
541
|
+
Checkbox with Action (Fails When Unchecked)
|
|
542
|
+
</h3>
|
|
543
|
+
<div className="control-group">
|
|
544
|
+
<div className="checkbox-group">
|
|
545
|
+
<label>
|
|
500
546
|
<Input
|
|
501
|
-
id="form-newsletter"
|
|
502
547
|
type="checkbox"
|
|
503
|
-
name="
|
|
504
|
-
checked={
|
|
548
|
+
name="protection"
|
|
549
|
+
checked={checked}
|
|
550
|
+
accentColor={backgroundColor}
|
|
551
|
+
action={async (protection) => {
|
|
552
|
+
setStatus("loading");
|
|
553
|
+
setResult("Processing...");
|
|
554
|
+
await delay(1000);
|
|
555
|
+
try {
|
|
556
|
+
if (!protection) {
|
|
557
|
+
throw new Error(
|
|
558
|
+
"Protection must be enabled for security",
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
const response = `✅ Protection ${protection ? "enabled" : "disabled"}`;
|
|
562
|
+
setResult(response);
|
|
563
|
+
setStatus("success");
|
|
564
|
+
setChecked(true);
|
|
565
|
+
return response;
|
|
566
|
+
} catch (error) {
|
|
567
|
+
setResult(`❌ ${error.message}`);
|
|
568
|
+
setStatus("error");
|
|
569
|
+
throw error;
|
|
570
|
+
}
|
|
571
|
+
}}
|
|
505
572
|
/>
|
|
506
|
-
<
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
</div>
|
|
510
|
-
<div className="checkbox-group">
|
|
511
|
-
<Input id="form-updates" type="checkbox" name="updates" />
|
|
512
|
-
<label htmlFor="form-updates">Product updates</label>
|
|
513
|
-
</div>
|
|
514
|
-
<div className="checkbox-group">
|
|
515
|
-
<Input id="form-marketing" type="checkbox" name="marketing" />
|
|
516
|
-
<label htmlFor="form-marketing">Marketing emails</label>
|
|
517
|
-
</div>
|
|
518
|
-
</div>
|
|
519
|
-
<div className="button-group">
|
|
520
|
-
<Button type="submit">Save Preferences</Button>
|
|
521
|
-
<Button type="reset">Reset</Button>
|
|
573
|
+
<span className={`status-indicator status-${status}`}></span>
|
|
574
|
+
Enable security protection (fails when unchecked)
|
|
575
|
+
</label>
|
|
522
576
|
</div>
|
|
523
|
-
</
|
|
577
|
+
</div>
|
|
524
578
|
<div
|
|
525
|
-
className={`result-display ${
|
|
579
|
+
className={`result-display ${status === "loading" ? "result-loading" : status === "success" ? "result-success" : status === "error" ? "result-error" : ""}`}
|
|
526
580
|
>
|
|
527
|
-
{result ||
|
|
581
|
+
{result ||
|
|
582
|
+
"Toggle checkbox - succeeds when checked, fails when unchecked..."}
|
|
528
583
|
</div>
|
|
529
584
|
</div>
|
|
530
585
|
);
|
|
531
586
|
};
|
|
532
587
|
|
|
588
|
+
const toggleAction = createAction(async ({ notifications }) => {
|
|
589
|
+
await delay(600);
|
|
590
|
+
return `${notifications ? "✅" : "☐"} Notifications ${notifications ? "enabled" : "disabled"}`;
|
|
591
|
+
});
|
|
533
592
|
// eslint-disable-next-line no-unused-vars
|
|
534
|
-
const
|
|
593
|
+
const CheckboxActionObjectDemo = ({ backgroundColor }) => {
|
|
535
594
|
const [result, setResult] = useState("");
|
|
536
595
|
|
|
537
596
|
return (
|
|
538
597
|
<div className="demo-card">
|
|
539
|
-
<h3 className="demo-title">
|
|
540
|
-
<p
|
|
541
|
-
style={{
|
|
542
|
-
margin: "0 0 15px 0",
|
|
543
|
-
fontSize: "14px",
|
|
544
|
-
color: "#666",
|
|
545
|
-
lineHeight: "1.4",
|
|
546
|
-
}}
|
|
547
|
-
>
|
|
548
|
-
<strong>Note:</strong> The checkbox states are not synced here,
|
|
549
|
-
which is normal. In a real application, both checkboxes would
|
|
550
|
-
typically be controlled by the same external state to keep them
|
|
551
|
-
synchronized.
|
|
552
|
-
</p>
|
|
598
|
+
<h3 className="demo-title">Checkbox with Action Object</h3>
|
|
553
599
|
<div className="control-group">
|
|
554
600
|
<div className="checkbox-group">
|
|
555
|
-
<
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
<div className="checkbox-group">
|
|
572
|
-
<Input
|
|
573
|
-
id="shared-checkbox-2"
|
|
574
|
-
type="checkbox"
|
|
575
|
-
name="feature2"
|
|
576
|
-
action={sharedToggleAction}
|
|
577
|
-
onActionStart={() => {
|
|
578
|
-
setResult("Processing...");
|
|
579
|
-
}}
|
|
580
|
-
onActionEnd={(e) => {
|
|
581
|
-
setResult(e.detail.data);
|
|
582
|
-
}}
|
|
583
|
-
/>
|
|
584
|
-
<label htmlFor="shared-checkbox-2">
|
|
585
|
-
Feature 2 (same shared action)
|
|
601
|
+
<label>
|
|
602
|
+
<Input
|
|
603
|
+
type="checkbox"
|
|
604
|
+
name="notifications"
|
|
605
|
+
accentColor={backgroundColor}
|
|
606
|
+
action={(notifications) => {
|
|
607
|
+
return toggleAction({ notifications });
|
|
608
|
+
}}
|
|
609
|
+
onActionStart={() => {
|
|
610
|
+
setResult("Processing...");
|
|
611
|
+
}}
|
|
612
|
+
onActionEnd={(e) => {
|
|
613
|
+
setResult(e.detail.data);
|
|
614
|
+
}}
|
|
615
|
+
/>
|
|
616
|
+
Enable notifications (with action object)
|
|
586
617
|
</label>
|
|
587
618
|
</div>
|
|
588
619
|
</div>
|
|
589
620
|
<div
|
|
590
621
|
className={`result-display ${result.startsWith("✅") || result.startsWith("☐") ? "result-success" : ""}`}
|
|
591
622
|
>
|
|
592
|
-
{result || "Toggle
|
|
623
|
+
{result || "Toggle checkbox to trigger action object..."}
|
|
593
624
|
</div>
|
|
594
625
|
</div>
|
|
595
626
|
);
|
|
596
627
|
};
|
|
597
628
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
const
|
|
601
|
-
|
|
629
|
+
// eslint-disable-next-line no-unused-vars
|
|
630
|
+
const CheckboxFormControlledErrorDemo = ({ backgroundColor }) => {
|
|
631
|
+
const [checked, setChecked] = useState(true);
|
|
632
|
+
const [result, setResult] = useState("");
|
|
633
|
+
const [status, setStatus] = useState("idle");
|
|
634
|
+
const ref = useRef();
|
|
635
|
+
|
|
636
|
+
return (
|
|
637
|
+
<div className="demo-card">
|
|
638
|
+
<h3 className="demo-title">
|
|
639
|
+
Form with Controlled Checkbox (Fails When Submit Without Check)
|
|
640
|
+
</h3>
|
|
641
|
+
<p
|
|
642
|
+
style={{ fontSize: "14px", color: "#666", marginBottom: "15px" }}
|
|
643
|
+
>
|
|
644
|
+
This demonstrates backend validation when frontend forgets to add
|
|
645
|
+
"required" - the server throws an error during form submission if
|
|
646
|
+
terms aren't agreed.
|
|
647
|
+
</p>
|
|
648
|
+
<Form
|
|
649
|
+
action={async ({ terms }) => {
|
|
650
|
+
setStatus("loading");
|
|
651
|
+
setResult("Processing form...");
|
|
652
|
+
try {
|
|
653
|
+
await delay(1000);
|
|
654
|
+
if (!terms) {
|
|
655
|
+
throw new Error(
|
|
656
|
+
"You must agree to the terms and conditions to proceed",
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
setChecked(Boolean(terms));
|
|
660
|
+
const response = "✅ Form submitted successfully!";
|
|
661
|
+
setResult(response);
|
|
662
|
+
setStatus("success");
|
|
663
|
+
return response;
|
|
664
|
+
} catch (error) {
|
|
665
|
+
setResult(`❌ ${error.message}`);
|
|
666
|
+
setStatus("error");
|
|
667
|
+
throw error;
|
|
668
|
+
}
|
|
669
|
+
}}
|
|
670
|
+
>
|
|
671
|
+
<div className="control-group">
|
|
672
|
+
<div className="checkbox-group">
|
|
673
|
+
<label>
|
|
674
|
+
<Input
|
|
675
|
+
ref={ref}
|
|
676
|
+
type="checkbox"
|
|
677
|
+
name="terms"
|
|
678
|
+
checked={checked}
|
|
679
|
+
accentColor={backgroundColor}
|
|
680
|
+
/>
|
|
681
|
+
<span
|
|
682
|
+
className={`status-indicator status-${status}`}
|
|
683
|
+
></span>
|
|
684
|
+
I agree to the terms and conditions
|
|
685
|
+
</label>
|
|
686
|
+
</div>
|
|
687
|
+
</div>
|
|
688
|
+
<div className="button-group">
|
|
689
|
+
<Button type="submit">Submit Form</Button>
|
|
690
|
+
<button
|
|
691
|
+
type="button"
|
|
692
|
+
onClick={() => {
|
|
693
|
+
ref.current.dispatchEvent(
|
|
694
|
+
new CustomEvent("setuistate", {
|
|
695
|
+
detail: { value: true },
|
|
696
|
+
}),
|
|
697
|
+
);
|
|
698
|
+
}}
|
|
699
|
+
>
|
|
700
|
+
Accept Terms
|
|
701
|
+
</button>
|
|
702
|
+
<button
|
|
703
|
+
type="button"
|
|
704
|
+
onClick={() => {
|
|
705
|
+
ref.current.dispatchEvent(
|
|
706
|
+
new CustomEvent("setuistate", {
|
|
707
|
+
detail: { value: false },
|
|
708
|
+
}),
|
|
709
|
+
);
|
|
710
|
+
}}
|
|
711
|
+
>
|
|
712
|
+
Decline Terms
|
|
713
|
+
</button>
|
|
714
|
+
</div>
|
|
715
|
+
</Form>
|
|
716
|
+
<div
|
|
717
|
+
className={`result-display ${status === "loading" ? "result-loading" : status === "success" ? "result-success" : status === "error" ? "result-error" : ""}`}
|
|
718
|
+
>
|
|
719
|
+
Terms agreed: {checked ? "Yes" : "No"}
|
|
720
|
+
<br />
|
|
721
|
+
{result ||
|
|
722
|
+
"Fill out the form - frontend will simulate backend submission rejected when terms not agreed..."}
|
|
723
|
+
</div>
|
|
724
|
+
</div>
|
|
602
725
|
);
|
|
603
|
-
|
|
604
|
-
const response = `${isEnabled ? "✅" : "☐"} ${featureName} ${isEnabled ? "enabled" : "disabled"} (from shared action)`;
|
|
605
|
-
return response;
|
|
606
|
-
});
|
|
726
|
+
};
|
|
607
727
|
|
|
608
728
|
render(<App />, document.querySelector("#root"));
|
|
609
729
|
</script>
|