@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.
- package/dist/jsenv_navi.js +22954 -0
- package/index.js +66 -16
- package/package.json +22 -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/{input → field}/input_textual.jsx +247 -173
- 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/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
|
@@ -194,155 +194,98 @@
|
|
|
194
194
|
<script type="module" jsenv-type="module/jsx">
|
|
195
195
|
import { render } from "preact";
|
|
196
196
|
import { useState } from "preact/hooks";
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
Input,
|
|
200
|
-
// eslint-disable-next-line no-unused-vars
|
|
201
|
-
Field,
|
|
202
|
-
} from "@jsenv/navi";
|
|
197
|
+
// eslint-disable-next-line no-unused-vars
|
|
198
|
+
import { Input } from "@jsenv/navi";
|
|
203
199
|
|
|
204
200
|
// eslint-disable-next-line no-unused-vars
|
|
205
201
|
const App = () => {
|
|
202
|
+
return (
|
|
203
|
+
<div className="demo-grid">
|
|
204
|
+
<LoadingDemo />
|
|
205
|
+
<ReadOnlyDemo />
|
|
206
|
+
<DisabledDemo />
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// eslint-disable-next-line no-unused-vars
|
|
212
|
+
const LoadingDemo = () => {
|
|
213
|
+
const [value, setValue] = useState();
|
|
206
214
|
const [loading, setLoading] = useState(false);
|
|
207
|
-
const [loadingB, setLoadingB] = useState(false);
|
|
208
|
-
const [loadingC, setLoadingC] = useState(false);
|
|
209
|
-
const [loadingD, setLoadingD] = useState(false);
|
|
210
215
|
|
|
211
216
|
return (
|
|
212
|
-
<div className="demo-
|
|
213
|
-
<
|
|
214
|
-
|
|
215
|
-
<
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
</div>
|
|
223
|
-
<div className="native-comparison">
|
|
224
|
-
<div className="native-demo">
|
|
225
|
-
<h4>@jsenv/navi Input</h4>
|
|
226
|
-
<Input loading={loading} placeholder="Enter some text..." />
|
|
227
|
-
</div>
|
|
228
|
-
<div className="native-demo">
|
|
229
|
-
<h4>Native HTML Input</h4>
|
|
230
|
-
<input placeholder="Native comparison" />
|
|
231
|
-
</div>
|
|
232
|
-
</div>
|
|
233
|
-
<div className="button-group">
|
|
234
|
-
<button onClick={() => setLoading(!loading)}>
|
|
235
|
-
{loading ? "Stop Loading" : "Start Loading"}
|
|
236
|
-
</button>
|
|
237
|
-
</div>
|
|
217
|
+
<div className="demo-card">
|
|
218
|
+
<h3 className="demo-title">💫 Loading State</h3>
|
|
219
|
+
<div className="control-group">
|
|
220
|
+
<h4>@jsenv/navi Input</h4>
|
|
221
|
+
<Input
|
|
222
|
+
loading={loading}
|
|
223
|
+
value={value}
|
|
224
|
+
onUIStateChange={setValue}
|
|
225
|
+
placeholder="Enter some text..."
|
|
226
|
+
/>
|
|
238
227
|
</div>
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
<
|
|
242
|
-
<div className="control-group">
|
|
243
|
-
<Field
|
|
244
|
-
input={
|
|
245
|
-
<Input
|
|
246
|
-
name="action-input"
|
|
247
|
-
action={() => {}}
|
|
248
|
-
loading={loadingB}
|
|
249
|
-
placeholder="Input with action..."
|
|
250
|
-
/>
|
|
251
|
-
}
|
|
252
|
-
label="Action Input"
|
|
253
|
-
/>
|
|
254
|
-
</div>
|
|
255
|
-
<div className="native-comparison">
|
|
256
|
-
<div className="native-demo">
|
|
257
|
-
<h4>@jsenv/navi Input with Action</h4>
|
|
258
|
-
<Input
|
|
259
|
-
name="action-input"
|
|
260
|
-
action={() => {}}
|
|
261
|
-
loading={loadingB}
|
|
262
|
-
placeholder="Input with action..."
|
|
263
|
-
/>
|
|
264
|
-
</div>
|
|
265
|
-
<div className="native-demo">
|
|
266
|
-
<h4>Native HTML Input</h4>
|
|
267
|
-
<input placeholder="Native has no built-in action" />
|
|
268
|
-
</div>
|
|
269
|
-
</div>
|
|
270
|
-
<div className="button-group">
|
|
271
|
-
<button onClick={() => setLoadingB(!loadingB)}>
|
|
272
|
-
{loadingB ? "Stop Loading" : "Start Loading"}
|
|
273
|
-
</button>
|
|
274
|
-
</div>
|
|
228
|
+
<div className="control-group">
|
|
229
|
+
<h4>Native HTML Input</h4>
|
|
230
|
+
<input placeholder="Enter some text..." />
|
|
275
231
|
</div>
|
|
232
|
+
<div className="button-group">
|
|
233
|
+
<button onClick={() => setLoading(!loading)}>
|
|
234
|
+
{loading ? "Stop Loading" : "Start Loading"}
|
|
235
|
+
</button>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
);
|
|
239
|
+
};
|
|
276
240
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
<div className="native-comparison">
|
|
293
|
-
<div className="native-demo">
|
|
294
|
-
<h4>@jsenv/navi Read-only</h4>
|
|
295
|
-
<Input
|
|
296
|
-
value="This is read-only content"
|
|
297
|
-
readonly
|
|
298
|
-
loading={loadingC}
|
|
299
|
-
/>
|
|
300
|
-
</div>
|
|
301
|
-
<div className="native-demo">
|
|
302
|
-
<h4>Native Read-only</h4>
|
|
303
|
-
<input readonly value="Native read-only" />
|
|
304
|
-
</div>
|
|
305
|
-
</div>
|
|
306
|
-
<div className="button-group">
|
|
307
|
-
<button onClick={() => setLoadingC(!loadingC)}>
|
|
308
|
-
{loadingC ? "Stop Loading" : "Start Loading"}
|
|
309
|
-
</button>
|
|
310
|
-
</div>
|
|
241
|
+
// eslint-disable-next-line no-unused-vars
|
|
242
|
+
const ReadOnlyDemo = () => {
|
|
243
|
+
// not giving onValueChange param makes it read-only
|
|
244
|
+
const [loading, setLoading] = useState(false);
|
|
245
|
+
|
|
246
|
+
return (
|
|
247
|
+
<div className="demo-card">
|
|
248
|
+
<h3 className="demo-title">🔒 Read-only State</h3>
|
|
249
|
+
<div className="control-group">
|
|
250
|
+
<h4>@jsenv/navi Read-only</h4>
|
|
251
|
+
<Input value="This is read-only content" loading={loading} />
|
|
252
|
+
</div>
|
|
253
|
+
<div className="control-group">
|
|
254
|
+
<h4>Native Read-only</h4>
|
|
255
|
+
<input readOnly value="This is read-only content" />
|
|
311
256
|
</div>
|
|
257
|
+
<div className="button-group">
|
|
258
|
+
<button onClick={() => setLoading(!loading)}>
|
|
259
|
+
{loading ? "Stop Loading" : "Start Loading"}
|
|
260
|
+
</button>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
// eslint-disable-next-line no-unused-vars
|
|
267
|
+
const DisabledDemo = () => {
|
|
268
|
+
const [loading, setLoading] = useState(false);
|
|
312
269
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
loading={loadingD}
|
|
333
|
-
placeholder="Disabled input..."
|
|
334
|
-
/>
|
|
335
|
-
</div>
|
|
336
|
-
<div className="native-demo">
|
|
337
|
-
<h4>Native Disabled</h4>
|
|
338
|
-
<input disabled placeholder="Native disabled" />
|
|
339
|
-
</div>
|
|
340
|
-
</div>
|
|
341
|
-
<div className="button-group">
|
|
342
|
-
<button onClick={() => setLoadingD(!loadingD)}>
|
|
343
|
-
{loadingD ? "Stop Loading" : "Start Loading"}
|
|
344
|
-
</button>
|
|
345
|
-
</div>
|
|
270
|
+
return (
|
|
271
|
+
<div className="demo-card">
|
|
272
|
+
<h3 className="demo-title">🚫 Disabled State</h3>
|
|
273
|
+
<div className="control-group">
|
|
274
|
+
<h4>@jsenv/navi Disabled</h4>
|
|
275
|
+
<Input
|
|
276
|
+
disabled
|
|
277
|
+
loading={loading}
|
|
278
|
+
placeholder="Disabled input..."
|
|
279
|
+
/>
|
|
280
|
+
</div>
|
|
281
|
+
<div className="control-group">
|
|
282
|
+
<h4>Native Disabled</h4>
|
|
283
|
+
<input disabled placeholder="Disabled input..." />
|
|
284
|
+
</div>
|
|
285
|
+
<div className="button-group">
|
|
286
|
+
<button onClick={() => setLoading(!loading)}>
|
|
287
|
+
{loading ? "Stop Loading" : "Start Loading"}
|
|
288
|
+
</button>
|
|
346
289
|
</div>
|
|
347
290
|
</div>
|
|
348
291
|
);
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// eslint-disable-next-line no-unused-vars
|
|
17
17
|
Select,
|
|
18
18
|
// eslint-disable-next-line no-unused-vars
|
|
19
|
-
|
|
19
|
+
Label,
|
|
20
20
|
} from "@jsenv/navi";
|
|
21
21
|
|
|
22
22
|
// eslint-disable-next-line no-unused-vars
|
|
@@ -41,17 +41,15 @@
|
|
|
41
41
|
<strong>Loading</strong>
|
|
42
42
|
</p>
|
|
43
43
|
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
label="Coucou"
|
|
54
|
-
></Field>
|
|
44
|
+
<Label>
|
|
45
|
+
Coucou
|
|
46
|
+
<Select name="loading" loading={loading}>
|
|
47
|
+
{[
|
|
48
|
+
{ label: "a", value: "a" },
|
|
49
|
+
{ label: "b", value: "b" },
|
|
50
|
+
]}
|
|
51
|
+
</Select>
|
|
52
|
+
</Label>
|
|
55
53
|
|
|
56
54
|
<div>
|
|
57
55
|
<label>
|
|
@@ -69,17 +67,15 @@
|
|
|
69
67
|
<strong>Readonly</strong>
|
|
70
68
|
</p>
|
|
71
69
|
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
label="Coucou"
|
|
82
|
-
></Field>
|
|
70
|
+
<Label>
|
|
71
|
+
Coucou
|
|
72
|
+
<Select name="loading" loading={loading} value="b" readOnly>
|
|
73
|
+
{[
|
|
74
|
+
{ label: "a", value: "a" },
|
|
75
|
+
{ label: "b", value: "b" },
|
|
76
|
+
]}
|
|
77
|
+
</Select>
|
|
78
|
+
</Label>
|
|
83
79
|
|
|
84
80
|
<div>
|
|
85
81
|
<label>
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" href="data:," />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>TabList demo</title>
|
|
8
|
+
<style>
|
|
9
|
+
.tab_button {
|
|
10
|
+
background: none;
|
|
11
|
+
border: none;
|
|
12
|
+
color: inherit;
|
|
13
|
+
font: inherit;
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<div id="root" style="position: relative"></div>
|
|
20
|
+
|
|
21
|
+
<script type="module" jsenv-type="module/jsx">
|
|
22
|
+
import { render } from "preact";
|
|
23
|
+
import { useState } from "preact/hooks";
|
|
24
|
+
import {
|
|
25
|
+
// eslint-disable-next-line no-unused-vars
|
|
26
|
+
TabList,
|
|
27
|
+
// eslint-disable-next-line no-unused-vars
|
|
28
|
+
Tab,
|
|
29
|
+
} from "../tablist/tablist.jsx";
|
|
30
|
+
|
|
31
|
+
const tabs = [
|
|
32
|
+
{ id: "overview", label: "Overview" },
|
|
33
|
+
{ id: "code", label: "Code" },
|
|
34
|
+
{ id: "issues", label: "Issues" },
|
|
35
|
+
{ id: "pulls", label: "Pull requests" },
|
|
36
|
+
{ id: "actions", label: "Actions" },
|
|
37
|
+
{ id: "projects", label: "Projects" },
|
|
38
|
+
{ id: "wiki", label: "Wiki" },
|
|
39
|
+
{ id: "security", label: "Security" },
|
|
40
|
+
{ id: "insights", label: "Insights" },
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
// eslint-disable-next-line no-unused-vars
|
|
44
|
+
const App = () => {
|
|
45
|
+
const [selectedTabId, setSelectedTabId] = useState("overview");
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div>
|
|
49
|
+
<p style="max-width: 800px; margin: 20px auto 0;">
|
|
50
|
+
Click the tabs to toggle the active one. The underline marker is
|
|
51
|
+
shown for the active tab.
|
|
52
|
+
</p>
|
|
53
|
+
<TabList aria-label="Demo tabs">
|
|
54
|
+
{tabs.map((tab) => (
|
|
55
|
+
<Tab key={tab.id} selected={selectedTabId === tab.id}>
|
|
56
|
+
<button
|
|
57
|
+
type="button"
|
|
58
|
+
className="tab_button"
|
|
59
|
+
onClick={() => setSelectedTabId(tab.id)}
|
|
60
|
+
>
|
|
61
|
+
{tab.label}
|
|
62
|
+
</button>
|
|
63
|
+
</Tab>
|
|
64
|
+
))}
|
|
65
|
+
</TabList>
|
|
66
|
+
<div style="max-width: 800px; margin: 16px auto; padding: 12px; border: 1px dashed #ccc; border-radius: 8px;">
|
|
67
|
+
<strong>Selected tab:</strong>{" "}
|
|
68
|
+
{tabs.find((t) => t.id === selectedTabId).label}
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
render(<App />, document.querySelector("#root"));
|
|
75
|
+
</script>
|
|
76
|
+
</body>
|
|
77
|
+
</html>
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Table Cell Selection Demo - Preact</title>
|
|
7
|
+
<style>
|
|
8
|
+
body {
|
|
9
|
+
font-family:
|
|
10
|
+
system-ui,
|
|
11
|
+
-apple-system,
|
|
12
|
+
sans-serif;
|
|
13
|
+
margin: 20px;
|
|
14
|
+
background: #f5f5f5;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.demo-container {
|
|
18
|
+
max-width: 800px;
|
|
19
|
+
margin: 0 auto;
|
|
20
|
+
background: white;
|
|
21
|
+
padding: 20px;
|
|
22
|
+
border-radius: 8px;
|
|
23
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Status display */
|
|
27
|
+
.status {
|
|
28
|
+
margin-top: 20px;
|
|
29
|
+
padding: 10px;
|
|
30
|
+
background: #f0f8ff;
|
|
31
|
+
border-radius: 4px;
|
|
32
|
+
font-family: monospace;
|
|
33
|
+
font-size: 14px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.actions {
|
|
37
|
+
margin-top: 15px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
button {
|
|
41
|
+
background: #0078d4;
|
|
42
|
+
color: white;
|
|
43
|
+
border: none;
|
|
44
|
+
padding: 8px 16px;
|
|
45
|
+
border-radius: 4px;
|
|
46
|
+
cursor: pointer;
|
|
47
|
+
margin-right: 8px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
button:hover {
|
|
51
|
+
background: #106ebe;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
button:disabled {
|
|
55
|
+
background: #ccc;
|
|
56
|
+
cursor: not-allowed;
|
|
57
|
+
}
|
|
58
|
+
</style>
|
|
59
|
+
</head>
|
|
60
|
+
<body>
|
|
61
|
+
<div id="root"></div>
|
|
62
|
+
|
|
63
|
+
<script type="module" jsenv-type="module/jsx">
|
|
64
|
+
import { render } from "preact";
|
|
65
|
+
import { useRef, useState } from "preact/hooks";
|
|
66
|
+
import {
|
|
67
|
+
// eslint-disable-next-line no-unused-vars
|
|
68
|
+
Table,
|
|
69
|
+
} from "@jsenv/navi";
|
|
70
|
+
|
|
71
|
+
// Sample data
|
|
72
|
+
const data = [
|
|
73
|
+
{
|
|
74
|
+
id: "1",
|
|
75
|
+
index: 1,
|
|
76
|
+
name: "1A",
|
|
77
|
+
email: "2A",
|
|
78
|
+
status: "3A",
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
id: "2",
|
|
82
|
+
index: 2,
|
|
83
|
+
name: "1B",
|
|
84
|
+
email: "2B",
|
|
85
|
+
status: "3B",
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: "3",
|
|
89
|
+
index: 3,
|
|
90
|
+
name: "1C",
|
|
91
|
+
email: "2C",
|
|
92
|
+
status: "3C",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
id: "4",
|
|
96
|
+
index: 4,
|
|
97
|
+
name: "4A",
|
|
98
|
+
email: "4B",
|
|
99
|
+
status: "4C",
|
|
100
|
+
},
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
// Column definitions
|
|
104
|
+
const columns = [
|
|
105
|
+
{ id: "name", accessorKey: "name", header: "Name" },
|
|
106
|
+
{ id: "email", accessorKey: "email", header: "Email" },
|
|
107
|
+
{ id: "status", accessorKey: "status", header: "Status" },
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
// eslint-disable-next-line no-unused-vars
|
|
111
|
+
const TableDemo = () => {
|
|
112
|
+
const tableRef = useRef(null);
|
|
113
|
+
const [selection, setSelection] = useState([]);
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<div className="demo-container">
|
|
117
|
+
<h1>Table Cell Selection Demo - Preact</h1>
|
|
118
|
+
<p>
|
|
119
|
+
Click cells to select/deselect. Use Cmd/Ctrl+click for
|
|
120
|
+
multi-select. Use Tab and arrow keys to navigate.
|
|
121
|
+
<br />
|
|
122
|
+
<strong>Click the # column to select entire rows.</strong>
|
|
123
|
+
<br />
|
|
124
|
+
<strong>Click column headers to select entire columns.</strong>
|
|
125
|
+
</p>
|
|
126
|
+
|
|
127
|
+
<Table
|
|
128
|
+
ref={tableRef}
|
|
129
|
+
data={data}
|
|
130
|
+
columns={columns}
|
|
131
|
+
selection={selection}
|
|
132
|
+
onSelectionChange={(value) => {
|
|
133
|
+
setSelection(value);
|
|
134
|
+
}}
|
|
135
|
+
/>
|
|
136
|
+
|
|
137
|
+
<div className="status">
|
|
138
|
+
<div>
|
|
139
|
+
Selection: <span>{JSON.stringify(selection)}</span>
|
|
140
|
+
</div>
|
|
141
|
+
<div>
|
|
142
|
+
Total selection count: <span>{selection.length}</span>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
<div className="actions">
|
|
147
|
+
<button
|
|
148
|
+
onClick={() => {
|
|
149
|
+
tableRef.current.clearSelection();
|
|
150
|
+
}}
|
|
151
|
+
>
|
|
152
|
+
Clear Selection
|
|
153
|
+
</button>
|
|
154
|
+
<button
|
|
155
|
+
onClick={() => {
|
|
156
|
+
tableRef.current.selectAll();
|
|
157
|
+
}}
|
|
158
|
+
>
|
|
159
|
+
Select All
|
|
160
|
+
</button>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// Render the app
|
|
167
|
+
render(<TableDemo />, document.getElementById("root"));
|
|
168
|
+
|
|
169
|
+
console.log("Preact Table selection demo loaded. Try:");
|
|
170
|
+
console.log("- Click cells to select/deselect");
|
|
171
|
+
console.log("- Use Cmd/Ctrl+click for multi-select");
|
|
172
|
+
console.log("- Use Tab and arrow keys to navigate");
|
|
173
|
+
console.log("- Press Space or Enter to toggle selection");
|
|
174
|
+
</script>
|
|
175
|
+
</body>
|
|
176
|
+
</html>
|