@jsenv/navi 0.0.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/index.js +51 -0
- package/package.json +38 -0
- package/src/action_private_properties.js +11 -0
- package/src/action_proxy_test.html +353 -0
- package/src/action_run_states.js +5 -0
- package/src/actions.js +1377 -0
- package/src/browser_integration/browser_integration.js +191 -0
- package/src/browser_integration/document_back_and_forward.js +17 -0
- package/src/browser_integration/document_loading_signal.js +100 -0
- package/src/browser_integration/document_state_signal.js +9 -0
- package/src/browser_integration/document_url_signal.js +9 -0
- package/src/browser_integration/use_is_visited.js +19 -0
- package/src/browser_integration/via_history.js +199 -0
- package/src/browser_integration/via_navigation.js +168 -0
- package/src/components/action_execution/form_context.js +8 -0
- package/src/components/action_execution/render_actionable_component.jsx +27 -0
- package/src/components/action_execution/use_action.js +330 -0
- package/src/components/action_execution/use_execute_action.js +161 -0
- package/src/components/action_renderer.jsx +136 -0
- package/src/components/collect_form_element_values.js +79 -0
- package/src/components/demos/0_button_demo.html +155 -0
- package/src/components/demos/1_checkbox_demo.html +257 -0
- package/src/components/demos/2_input_textual_demo.html +354 -0
- package/src/components/demos/3_radio_demo.html +222 -0
- package/src/components/demos/4_select_demo.html +104 -0
- package/src/components/demos/5_list_scrollable_demo.html +153 -0
- package/src/components/demos/action/0_button_demo.html +204 -0
- package/src/components/demos/action/10_shortcuts_demo.html +189 -0
- package/src/components/demos/action/11_nested_shortcuts_demo.html +401 -0
- package/src/components/demos/action/1_input_text_demo.html +461 -0
- package/src/components/demos/action/2_form_multiple.html +303 -0
- package/src/components/demos/action/3_details_demo.html +172 -0
- package/src/components/demos/action/4_input_checkbox_demo.html +611 -0
- package/src/components/demos/action/6_checkbox_list_demo.html +109 -0
- package/src/components/demos/action/7_radio_list_demo.html +217 -0
- package/src/components/demos/action/8_editable_text_demo.html +442 -0
- package/src/components/demos/action/9_link_demo.html +172 -0
- package/src/components/demos/demo.md +0 -0
- package/src/components/demos/route/basic/basic.html +14 -0
- package/src/components/demos/route/basic/basic_route_demo.jsx +224 -0
- package/src/components/demos/route/multi/multi.html +14 -0
- package/src/components/demos/route/multi/multi_route_demo.jsx +277 -0
- package/src/components/details/details.jsx +248 -0
- package/src/components/details/summary_marker.jsx +141 -0
- package/src/components/editable_text/editable_text.jsx +96 -0
- package/src/components/error_boundary_context.js +9 -0
- package/src/components/form.jsx +144 -0
- package/src/components/input/button.jsx +333 -0
- package/src/components/input/checkbox_list.jsx +294 -0
- package/src/components/input/field.jsx +61 -0
- package/src/components/input/field_css.js +118 -0
- package/src/components/input/input.jsx +15 -0
- package/src/components/input/input_checkbox.jsx +370 -0
- package/src/components/input/input_radio.jsx +299 -0
- package/src/components/input/input_textual.jsx +338 -0
- package/src/components/input/radio_list.jsx +283 -0
- package/src/components/input/select.jsx +273 -0
- package/src/components/input/use_form_event.js +20 -0
- package/src/components/input/use_on_change.js +12 -0
- package/src/components/link/link.jsx +291 -0
- package/src/components/loader/loader_background.jsx +324 -0
- package/src/components/loader/loading_spinner.jsx +68 -0
- package/src/components/loader/network_speed.js +83 -0
- package/src/components/loader/rectangle_loading.jsx +225 -0
- package/src/components/route.jsx +15 -0
- package/src/components/selection/selection.js +5 -0
- package/src/components/selection/selection_context.jsx +262 -0
- package/src/components/shortcut/os.js +9 -0
- package/src/components/shortcut/shortcut_context.jsx +390 -0
- package/src/components/use_action_events.js +37 -0
- package/src/components/use_auto_focus.js +43 -0
- package/src/components/use_debounce_true.js +31 -0
- package/src/components/use_focus_group.js +19 -0
- package/src/components/use_initial_value.js +104 -0
- package/src/components/use_is_visited.js +19 -0
- package/src/components/use_ref_array.js +38 -0
- package/src/components/use_signal_sync.js +50 -0
- package/src/components/use_state_array.js +40 -0
- package/src/docs/actions.md +228 -0
- package/src/docs/demos/resource/action_status.jsx +42 -0
- package/src/docs/demos/resource/demo.md +1 -0
- package/src/docs/demos/resource/resource_demo_0.html +84 -0
- package/src/docs/demos/resource/resource_demo_10_post_gc.html +364 -0
- package/src/docs/demos/resource/resource_demo_11_describe_many.html +362 -0
- package/src/docs/demos/resource/resource_demo_2.html +173 -0
- package/src/docs/demos/resource/resource_demo_3_filtered_users.html +415 -0
- package/src/docs/demos/resource/resource_demo_4_details.html +284 -0
- package/src/docs/demos/resource/resource_demo_5_renderer_lazy.html +115 -0
- package/src/docs/demos/resource/resource_demo_6_gc.html +217 -0
- package/src/docs/demos/resource/resource_demo_7_child_gc.html +240 -0
- package/src/docs/demos/resource/resource_demo_8_proxy_gc.html +319 -0
- package/src/docs/demos/resource/resource_demo_9_describe_one.html +472 -0
- package/src/docs/demos/resource/tata.jsx +3 -0
- package/src/docs/demos/resource/toto.jsx +3 -0
- package/src/docs/demos/user_nav/user_nav.html +12 -0
- package/src/docs/demos/user_nav/user_nav.jsx +330 -0
- package/src/docs/resource_dependencies.md +103 -0
- package/src/docs/resource_with_params.md +80 -0
- package/src/notes.md +13 -0
- package/src/route/route.js +518 -0
- package/src/route/route.test.html +228 -0
- package/src/store/array_signal_store.js +537 -0
- package/src/store/local_storage_signal.js +17 -0
- package/src/store/resource_graph.js +1303 -0
- package/src/store/tests/resource_graph_autoreload_demo.html +12 -0
- package/src/store/tests/resource_graph_autoreload_demo.jsx +964 -0
- package/src/store/tests/resource_graph_dependencies.test.js +95 -0
- package/src/store/value_in_local_storage.js +187 -0
- package/src/symbol_object_signal.js +1 -0
- package/src/use_action_data.js +10 -0
- package/src/use_action_status.js +47 -0
- package/src/utils/add_many_event_listeners.js +15 -0
- package/src/utils/array_add_remove.js +61 -0
- package/src/utils/array_signal.js +15 -0
- package/src/utils/compare_two_js_values.js +172 -0
- package/src/utils/execute_with_cleanup.js +21 -0
- package/src/utils/get_caller_info.js +85 -0
- package/src/utils/iterable_weak_set.js +62 -0
- package/src/utils/js_value_weak_map.js +162 -0
- package/src/utils/js_value_weak_map_demo.html +690 -0
- package/src/utils/merge_two_js_values.js +53 -0
- package/src/utils/stringify_for_display.js +150 -0
- package/src/utils/weak_effect.js +48 -0
|
@@ -0,0 +1,401 @@
|
|
|
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>Nested Keyboard Shortcuts Demo</title>
|
|
8
|
+
<style>
|
|
9
|
+
body {
|
|
10
|
+
font-family:
|
|
11
|
+
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
12
|
+
max-width: 900px;
|
|
13
|
+
margin: 0 auto;
|
|
14
|
+
padding: 40px 20px;
|
|
15
|
+
line-height: 1.6;
|
|
16
|
+
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
|
17
|
+
min-height: 100vh;
|
|
18
|
+
color: #333;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.demo-container {
|
|
22
|
+
background: white;
|
|
23
|
+
border-radius: 12px;
|
|
24
|
+
padding: 40px;
|
|
25
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.demo-title {
|
|
29
|
+
font-size: 2rem;
|
|
30
|
+
font-weight: 700;
|
|
31
|
+
margin: 0 0 30px 0;
|
|
32
|
+
color: #2d3748;
|
|
33
|
+
text-align: center;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.demo-description {
|
|
37
|
+
background: #e6fffa;
|
|
38
|
+
border-left: 4px solid #38b2ac;
|
|
39
|
+
padding: 20px;
|
|
40
|
+
margin: 0 0 30px 0;
|
|
41
|
+
border-radius: 0 8px 8px 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.demo-description h3 {
|
|
45
|
+
margin: 0 0 15px 0;
|
|
46
|
+
color: #2d3748;
|
|
47
|
+
font-size: 1.2rem;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.shortcut-section {
|
|
51
|
+
margin: 20px 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.shortcut-section h4 {
|
|
55
|
+
margin: 0 0 10px 0;
|
|
56
|
+
color: #2c7a7b;
|
|
57
|
+
font-size: 1rem;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.shortcut-list {
|
|
61
|
+
list-style: none;
|
|
62
|
+
padding: 0;
|
|
63
|
+
margin: 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.shortcut-item {
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
margin: 8px 0;
|
|
70
|
+
padding: 6px 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.shortcut-key {
|
|
74
|
+
background: #2d3748;
|
|
75
|
+
color: white;
|
|
76
|
+
padding: 3px 10px;
|
|
77
|
+
border-radius: 5px;
|
|
78
|
+
font-family: "Monaco", "Menlo", monospace;
|
|
79
|
+
font-size: 0.8rem;
|
|
80
|
+
font-weight: 600;
|
|
81
|
+
margin-right: 12px;
|
|
82
|
+
min-width: 50px;
|
|
83
|
+
text-align: center;
|
|
84
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.shortcut-description {
|
|
88
|
+
color: #4a5568;
|
|
89
|
+
flex: 1;
|
|
90
|
+
font-size: 0.9rem;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.file-explorer {
|
|
94
|
+
background: #f8f9fa;
|
|
95
|
+
border: 2px solid #e9ecef;
|
|
96
|
+
border-radius: 12px;
|
|
97
|
+
padding: 20px;
|
|
98
|
+
margin: 30px 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.explorer-title {
|
|
102
|
+
margin: 0 0 20px 0;
|
|
103
|
+
color: #2d3748;
|
|
104
|
+
font-size: 1.3rem;
|
|
105
|
+
text-align: center;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.file-list {
|
|
109
|
+
list-style: none;
|
|
110
|
+
padding: 0;
|
|
111
|
+
margin: 0;
|
|
112
|
+
border: 1px solid #d1d5db;
|
|
113
|
+
border-radius: 6px;
|
|
114
|
+
background: white;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.file-item {
|
|
118
|
+
border-bottom: 1px solid #e5e7eb;
|
|
119
|
+
padding: 0;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.file-item:last-child {
|
|
123
|
+
border-bottom: none;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.file-link {
|
|
127
|
+
display: block;
|
|
128
|
+
padding: 12px 16px;
|
|
129
|
+
text-decoration: none;
|
|
130
|
+
color: #374151;
|
|
131
|
+
transition: background-color 0.2s ease;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.file-link:hover {
|
|
135
|
+
background-color: #f3f4f6;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.file-link:focus {
|
|
139
|
+
outline: 2px solid #3b82f6;
|
|
140
|
+
outline-offset: -2px;
|
|
141
|
+
background-color: #dbeafe;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.file-icon {
|
|
145
|
+
margin-right: 10px;
|
|
146
|
+
font-size: 1.1rem;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.instructions {
|
|
150
|
+
background: #fef7ff;
|
|
151
|
+
border: 1px solid #e879f9;
|
|
152
|
+
border-radius: 8px;
|
|
153
|
+
padding: 20px;
|
|
154
|
+
margin-top: 30px;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.instructions h4 {
|
|
158
|
+
color: #a21caf;
|
|
159
|
+
margin: 0 0 10px 0;
|
|
160
|
+
font-size: 1rem;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.instructions p {
|
|
164
|
+
margin: 5px 0;
|
|
165
|
+
color: #744210;
|
|
166
|
+
font-size: 0.9rem;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.status-display {
|
|
170
|
+
background: #1f2937;
|
|
171
|
+
color: #f9fafb;
|
|
172
|
+
padding: 15px;
|
|
173
|
+
border-radius: 8px;
|
|
174
|
+
margin: 20px 0;
|
|
175
|
+
font-family: "Monaco", "Menlo", monospace;
|
|
176
|
+
font-size: 0.9rem;
|
|
177
|
+
min-height: 60px;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.status-title {
|
|
181
|
+
color: #9ca3af;
|
|
182
|
+
margin-bottom: 8px;
|
|
183
|
+
font-size: 0.8rem;
|
|
184
|
+
text-transform: uppercase;
|
|
185
|
+
letter-spacing: 0.5px;
|
|
186
|
+
}
|
|
187
|
+
</style>
|
|
188
|
+
</head>
|
|
189
|
+
<body>
|
|
190
|
+
<div id="root"></div>
|
|
191
|
+
|
|
192
|
+
<script type="module" jsenv-type="module/jsx">
|
|
193
|
+
import { render } from "preact";
|
|
194
|
+
import { useState, useRef } from "preact/hooks";
|
|
195
|
+
import {
|
|
196
|
+
// eslint-disable-next-line no-unused-vars
|
|
197
|
+
Link,
|
|
198
|
+
// eslint-disable-next-line no-unused-vars
|
|
199
|
+
ShortcutProvider,
|
|
200
|
+
// eslint-disable-next-line no-unused-vars
|
|
201
|
+
SelectionProvider,
|
|
202
|
+
} from "@jsenv/navi";
|
|
203
|
+
|
|
204
|
+
// eslint-disable-next-line no-unused-vars
|
|
205
|
+
const App = () => {
|
|
206
|
+
const [status, setStatus] = useState("Ready - Try the shortcuts!");
|
|
207
|
+
const [selection, setSelection] = useState([]);
|
|
208
|
+
const [deletedFiles, setDeletedFiles] = useState([]);
|
|
209
|
+
|
|
210
|
+
const containerShortcuts = [
|
|
211
|
+
{
|
|
212
|
+
key: "a",
|
|
213
|
+
description: "Select all files",
|
|
214
|
+
action: () => {
|
|
215
|
+
setStatus("đ Selected all files (container shortcut)");
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
key: "delete",
|
|
220
|
+
description: "Delete selected files",
|
|
221
|
+
action: async () => {
|
|
222
|
+
setStatus("đī¸ Start deleting files (container shortcut)");
|
|
223
|
+
await new Promise((resolve) => setTimeout(resolve, 2_000));
|
|
224
|
+
setStatus(
|
|
225
|
+
"đī¸ Selected files deletion done! (container shortcut)",
|
|
226
|
+
);
|
|
227
|
+
},
|
|
228
|
+
confirmMessage: "Are you sure you want to delete selected files?",
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
key: "r",
|
|
232
|
+
description: "Refresh file list",
|
|
233
|
+
action: () => {
|
|
234
|
+
setStatus("đ Refreshed file list (container shortcut)");
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
];
|
|
238
|
+
|
|
239
|
+
const files = [
|
|
240
|
+
{ name: "document.pdf", icon: "đ", type: "PDF Document" },
|
|
241
|
+
{ name: "image.jpg", icon: "đŧī¸", type: "JPEG Image" },
|
|
242
|
+
{ name: "video.mp4", icon: "đĨ", type: "MP4 Video" },
|
|
243
|
+
{ name: "archive.zip", icon: "đĻ", type: "ZIP Archive" },
|
|
244
|
+
];
|
|
245
|
+
|
|
246
|
+
const elementRef = useRef();
|
|
247
|
+
|
|
248
|
+
return (
|
|
249
|
+
<div className="demo-container">
|
|
250
|
+
<h1 className="demo-title">đ Nested Shortcuts Demo</h1>
|
|
251
|
+
|
|
252
|
+
<div className="demo-description">
|
|
253
|
+
<h3>Container vs Link Shortcuts:</h3>
|
|
254
|
+
|
|
255
|
+
<div className="shortcut-section">
|
|
256
|
+
<h4>
|
|
257
|
+
đ Container Shortcuts (work anywhere in file explorer):
|
|
258
|
+
</h4>
|
|
259
|
+
<ul className="shortcut-list">
|
|
260
|
+
<li className="shortcut-item">
|
|
261
|
+
<span className="shortcut-key">a</span>
|
|
262
|
+
<span className="shortcut-description">
|
|
263
|
+
Select all files
|
|
264
|
+
</span>
|
|
265
|
+
</li>
|
|
266
|
+
<li className="shortcut-item">
|
|
267
|
+
<span className="shortcut-key">Delete</span>
|
|
268
|
+
<span className="shortcut-description">
|
|
269
|
+
Delete selected files
|
|
270
|
+
</span>
|
|
271
|
+
</li>
|
|
272
|
+
<li className="shortcut-item">
|
|
273
|
+
<span className="shortcut-key">r</span>
|
|
274
|
+
<span className="shortcut-description">
|
|
275
|
+
Refresh file list
|
|
276
|
+
</span>
|
|
277
|
+
</li>
|
|
278
|
+
</ul>
|
|
279
|
+
</div>
|
|
280
|
+
|
|
281
|
+
<div className="shortcut-section">
|
|
282
|
+
<h4>đ Link Shortcuts (work only when link is focused):</h4>
|
|
283
|
+
<ul className="shortcut-list">
|
|
284
|
+
<li className="shortcut-item">
|
|
285
|
+
<span className="shortcut-key">Enter</span>
|
|
286
|
+
<span className="shortcut-description">
|
|
287
|
+
Open/download file
|
|
288
|
+
</span>
|
|
289
|
+
</li>
|
|
290
|
+
<li className="shortcut-item">
|
|
291
|
+
<span className="shortcut-key">Space</span>
|
|
292
|
+
<span className="shortcut-description">Preview file</span>
|
|
293
|
+
</li>
|
|
294
|
+
<li className="shortcut-item">
|
|
295
|
+
<span className="shortcut-key">i</span>
|
|
296
|
+
<span className="shortcut-description">Show file info</span>
|
|
297
|
+
</li>
|
|
298
|
+
</ul>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
<div className="status-display">
|
|
303
|
+
<div className="status-title">Action Status:</div>
|
|
304
|
+
<div>{status}</div>
|
|
305
|
+
</div>
|
|
306
|
+
|
|
307
|
+
<div className="file-explorer">
|
|
308
|
+
<h2 className="explorer-title">đ File Explorer</h2>
|
|
309
|
+
|
|
310
|
+
<SelectionProvider
|
|
311
|
+
value={selection}
|
|
312
|
+
onChange={(value) => {
|
|
313
|
+
setSelection(value);
|
|
314
|
+
}}
|
|
315
|
+
>
|
|
316
|
+
<ShortcutProvider
|
|
317
|
+
elementRef={elementRef}
|
|
318
|
+
shortcuts={containerShortcuts}
|
|
319
|
+
onActionStart={() => {
|
|
320
|
+
setDeletedFiles(selection);
|
|
321
|
+
}}
|
|
322
|
+
onActionEnd={() => {
|
|
323
|
+
setDeletedFiles([]);
|
|
324
|
+
}}
|
|
325
|
+
>
|
|
326
|
+
<ul className="file-list" ref={elementRef}>
|
|
327
|
+
{files.map((file) => (
|
|
328
|
+
<li key={file.name} className="file-item">
|
|
329
|
+
<Link
|
|
330
|
+
className="file-link"
|
|
331
|
+
href="#"
|
|
332
|
+
value={file.name}
|
|
333
|
+
readOnly={deletedFiles.includes(file.name)}
|
|
334
|
+
loading={deletedFiles.includes(file.name)}
|
|
335
|
+
shortcuts={[
|
|
336
|
+
{
|
|
337
|
+
key: "enter",
|
|
338
|
+
description: `Open ${file.name}`,
|
|
339
|
+
action: () => {
|
|
340
|
+
setStatus(
|
|
341
|
+
`đ Opening ${file.name} (link shortcut)`,
|
|
342
|
+
);
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
key: "space",
|
|
347
|
+
description: `Preview ${file.name}`,
|
|
348
|
+
action: () => {
|
|
349
|
+
setStatus(
|
|
350
|
+
`đī¸ Previewing ${file.name} (link shortcut)`,
|
|
351
|
+
);
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
key: "i",
|
|
356
|
+
description: `Info for ${file.name}`,
|
|
357
|
+
action: () => {
|
|
358
|
+
setStatus(
|
|
359
|
+
`âšī¸ Info: ${file.name} - ${file.type} (link shortcut)`,
|
|
360
|
+
);
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
]}
|
|
364
|
+
>
|
|
365
|
+
<span className="file-icon">{file.icon}</span>
|
|
366
|
+
{file.name}
|
|
367
|
+
</Link>
|
|
368
|
+
</li>
|
|
369
|
+
))}
|
|
370
|
+
</ul>
|
|
371
|
+
</ShortcutProvider>
|
|
372
|
+
</SelectionProvider>
|
|
373
|
+
</div>
|
|
374
|
+
|
|
375
|
+
<div className="instructions">
|
|
376
|
+
<h4>đ¯ How to Test:</h4>
|
|
377
|
+
<p>
|
|
378
|
+
<strong>Container shortcuts:</strong> Click anywhere in the file
|
|
379
|
+
explorer area, then press 'a', 'Delete', or 'r'
|
|
380
|
+
</p>
|
|
381
|
+
<p>
|
|
382
|
+
<strong>Link shortcuts:</strong> Tab to focus a specific file,
|
|
383
|
+
then press 'Enter', 'Space', or 'i'
|
|
384
|
+
</p>
|
|
385
|
+
<p>
|
|
386
|
+
<strong>Precedence:</strong> When a link is focused, link
|
|
387
|
+
shortcuts take priority over container shortcuts
|
|
388
|
+
</p>
|
|
389
|
+
<p>
|
|
390
|
+
<strong>Status display:</strong> Watch the black box above to
|
|
391
|
+
see which shortcuts are triggered
|
|
392
|
+
</p>
|
|
393
|
+
</div>
|
|
394
|
+
</div>
|
|
395
|
+
);
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
render(<App />, document.getElementById("root"));
|
|
399
|
+
</script>
|
|
400
|
+
</body>
|
|
401
|
+
</html>
|