@yuneta/gobj-ui 5.2.1 → 5.3.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/README.md +165 -0
- package/dist/gobj-ui.cjs.js +386 -41
- package/dist/gobj-ui.es.js +386 -41
- package/package.json +1 -1
- package/src/c_yui_json.css +23 -3
- package/src/c_yui_json.js +17 -3
- package/src/c_yui_nav.js +63 -3
- package/src/c_yui_node.css +77 -0
- package/src/c_yui_node.js +1567 -0
- package/src/c_yui_shell.css +18 -0
- package/src/c_yui_shell.js +206 -4
- package/src/c_yui_window.js +8 -3
- package/src/node_tree_model.js +463 -0
- package/src/node_tree_model.test.js +282 -0
- package/src/route_map_model.js +48 -0
- package/src/route_map_model.test.js +70 -0
- package/src/route_resolver.js +11 -0
- package/src/shell_route_map.css +36 -2
- package/src/shell_route_map.js +205 -45
- package/src/yui_dev.js +8 -3
- package/src/yui_icons.css +13 -0
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -344,6 +344,11 @@ function _is_non_empty_string(v) {
|
|
|
344
344
|
* - root `/` is NEVER an ancestor catch-all (it only matches
|
|
345
345
|
* exactly): otherwise every typo route would silently mount
|
|
346
346
|
* the home view and the unknown-route diagnostic would die.
|
|
347
|
+
* ONE exception, opt-in: an entry whose target declares
|
|
348
|
+
* `owns_subtree` is a view that resolves the tail ITSELF and
|
|
349
|
+
* says so when a segment names nothing — a C_YUI_NODE tree
|
|
350
|
+
* rooted at `/`. The diagnostic is not lost there, it moves
|
|
351
|
+
* one layer down to whoever actually knows the names.
|
|
347
352
|
* - nothing matched → entry as found (may be
|
|
348
353
|
* null or a targetless submenu parent), subpath "".
|
|
349
354
|
************************************************************/
|
|
@@ -371,7 +376,15 @@ function resolve_route(item_index, route) {
|
|
|
371
376
|
while (parts.length > 0 && (!entry || !entry.target)) {
|
|
372
377
|
parts.pop();
|
|
373
378
|
let cand = "/" + parts.join("/");
|
|
374
|
-
if (cand === "/")
|
|
379
|
+
if (cand === "/") {
|
|
380
|
+
let root = item_index["/"];
|
|
381
|
+
if (root && root.target && root.target.owns_subtree) {
|
|
382
|
+
entry = root;
|
|
383
|
+
matched_route = "/";
|
|
384
|
+
subpath = route.replace(/^\/+/, "");
|
|
385
|
+
}
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
375
388
|
let e = item_index[cand];
|
|
376
389
|
if (e && e.target) {
|
|
377
390
|
entry = e;
|
|
@@ -488,6 +501,38 @@ function collect_routes(nodes, into) {
|
|
|
488
501
|
}
|
|
489
502
|
}
|
|
490
503
|
/************************************************************
|
|
504
|
+
* A route can be reached from more than one surface: the primary
|
|
505
|
+
* menu, a drawer, an account dropdown. Each occurrence rendered
|
|
506
|
+
* its whole SUBTREE, so a branch reachable three ways was drawn
|
|
507
|
+
* three times — bearable when a section had four children, noise
|
|
508
|
+
* once a node tree hangs there with fourteen.
|
|
509
|
+
*
|
|
510
|
+
* Exactly one occurrence owns the subtree; the others become
|
|
511
|
+
* references (`ref: true`, no children) — still real, clickable
|
|
512
|
+
* routes, just not repeated structure.
|
|
513
|
+
*
|
|
514
|
+
* Who owns it: the first occurrence in the NAV, then in `other`,
|
|
515
|
+
* then in the toolbar. The nav is where the app's structure
|
|
516
|
+
* lives; a toolbar entry pointing at the same route is a
|
|
517
|
+
* shortcut — a non-structural edge — and hanging the tree off it
|
|
518
|
+
* would bury the whole structure inside the account menu.
|
|
519
|
+
************************************************************/
|
|
520
|
+
function dedupe_subtrees(groups) {
|
|
521
|
+
let owner = {};
|
|
522
|
+
let visit = (node) => {
|
|
523
|
+
if (node.route) {
|
|
524
|
+
if (owner[node.route] === void 0) owner[node.route] = node;
|
|
525
|
+
else if (owner[node.route] !== node) {
|
|
526
|
+
node.ref = true;
|
|
527
|
+
node.children = [];
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
if (Array.isArray(node.children)) node.children.forEach(visit);
|
|
532
|
+
};
|
|
533
|
+
for (let group of groups) group.forEach(visit);
|
|
534
|
+
}
|
|
535
|
+
/************************************************************
|
|
491
536
|
* Mark "you are here": the node whose route best matches
|
|
492
537
|
* current_route — exact hit wins, else the LONGEST declared
|
|
493
538
|
* route that is a path-prefix of it (the base view of a deep
|
|
@@ -497,6 +542,7 @@ function mark_current(groups, current_route) {
|
|
|
497
542
|
if (!current_route) return;
|
|
498
543
|
let best = null;
|
|
499
544
|
let visit = (n) => {
|
|
545
|
+
if (n.ref) return;
|
|
500
546
|
if (n.route) {
|
|
501
547
|
if (n.route === current_route) {
|
|
502
548
|
if (!best || best.node.route !== current_route) best = {
|
|
@@ -614,6 +660,11 @@ function build_nav_map(input) {
|
|
|
614
660
|
});
|
|
615
661
|
}
|
|
616
662
|
other.forEach(enrich);
|
|
663
|
+
dedupe_subtrees([
|
|
664
|
+
nav,
|
|
665
|
+
other,
|
|
666
|
+
toolbar
|
|
667
|
+
]);
|
|
617
668
|
mark_current([
|
|
618
669
|
toolbar,
|
|
619
670
|
nav,
|
|
@@ -775,6 +826,7 @@ var attrs_table$17 = [
|
|
|
775
826
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_JSON, "config", 0, null, "Shell declarative config (zones, menu, stages, toolbar)"),
|
|
776
827
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "default_route", 0, "", "Fallback route if hash is empty"),
|
|
777
828
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "current_route", 0, "", "Current active route"),
|
|
829
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "remember_section_position", 0, false, "A menu click returns to the last position visited inside that section"),
|
|
778
830
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "use_hash", 0, true, "Bind navigation to window.location.hash"),
|
|
779
831
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "mount_element", 0, null, "HTMLElement to mount shell into (default: document.body)"),
|
|
780
832
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "$container", 0, null, "Root HTMLElement of the shell"),
|
|
@@ -786,6 +838,7 @@ var PRIVATE_DATA$17 = {
|
|
|
786
838
|
stages: {},
|
|
787
839
|
navs: [],
|
|
788
840
|
item_index: {},
|
|
841
|
+
section_pos: {},
|
|
789
842
|
sub_routes: {},
|
|
790
843
|
event_handlers: {},
|
|
791
844
|
hash_handler: null,
|
|
@@ -833,6 +886,8 @@ function mt_start$14(gobj) {
|
|
|
833
886
|
]));
|
|
834
887
|
return;
|
|
835
888
|
}
|
|
889
|
+
let shell_cfg = config.shell || {};
|
|
890
|
+
if (typeof shell_cfg.remember_section_position === "boolean") (0, _yuneta_gobj_js.gobj_write_attr)(gobj, "remember_section_position", shell_cfg.remember_section_position);
|
|
836
891
|
build_item_index(gobj, config);
|
|
837
892
|
instantiate_menus(gobj, config);
|
|
838
893
|
build_toolbar(gobj, config);
|
|
@@ -1192,6 +1247,59 @@ function build_item_index(gobj, config) {
|
|
|
1192
1247
|
menu_id: prev && prev.menu_id || ""
|
|
1193
1248
|
};
|
|
1194
1249
|
}
|
|
1250
|
+
index_node_tree(gobj, config);
|
|
1251
|
+
}
|
|
1252
|
+
/************************************************************
|
|
1253
|
+
* config.shell.tree — the navigation is a TREE OF NODES and
|
|
1254
|
+
* its root is where the shell's own root used to be.
|
|
1255
|
+
*
|
|
1256
|
+
* The shell keeps what it is good at, the SPACE: zones, layers,
|
|
1257
|
+
* stages, toolbar, overlays, theme, breakpoints. It stops being
|
|
1258
|
+
* the owner of the menu: the root C_YUI_NODE holds the primary
|
|
1259
|
+
* options as its children and projects them into zones (a left
|
|
1260
|
+
* rail, a bottom bar) exactly as `menu.primary.render` used to
|
|
1261
|
+
* say — a per-zone projection is still a projection.
|
|
1262
|
+
*
|
|
1263
|
+
* All this does is synthesize ONE route entry. `owns_subtree`
|
|
1264
|
+
* lets it match as the ancestor of everything (route_resolver),
|
|
1265
|
+
* so the whole url space below it is the tree's `subpath` and no
|
|
1266
|
+
* route table grows. The unknown-route diagnostic is not lost:
|
|
1267
|
+
* it moves to the node that knows the names of its children.
|
|
1268
|
+
*
|
|
1269
|
+
* `menu` and `tree` are not exclusive — an app may declare both
|
|
1270
|
+
* while it migrates — but a tree at "/" owns every route no
|
|
1271
|
+
* other entry claims, which is the point.
|
|
1272
|
+
************************************************************/
|
|
1273
|
+
function index_node_tree(gobj, config) {
|
|
1274
|
+
let priv = gobj.priv;
|
|
1275
|
+
let tree = config.shell && config.shell.tree || null;
|
|
1276
|
+
if (!tree) return;
|
|
1277
|
+
if (!(0, _yuneta_gobj_js.is_object)(tree)) {
|
|
1278
|
+
(0, _yuneta_gobj_js.log_error)("C_YUI_SHELL: config.shell.tree must be an object");
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1281
|
+
let base_route = normalize_route(tree.base_route || "/");
|
|
1282
|
+
let kw = {};
|
|
1283
|
+
for (let key of Object.keys(tree)) {
|
|
1284
|
+
if (key.charAt(0) === "_" || key === "stage") continue;
|
|
1285
|
+
kw[key] = tree[key];
|
|
1286
|
+
}
|
|
1287
|
+
kw.base_route = base_route;
|
|
1288
|
+
if (!kw.node_id) kw.node_id = "root";
|
|
1289
|
+
let prev = priv.item_index[base_route];
|
|
1290
|
+
priv.item_index[base_route] = {
|
|
1291
|
+
item: prev && prev.item || null,
|
|
1292
|
+
parent_item: prev && prev.parent_item || null,
|
|
1293
|
+
stage: tree.stage || "main",
|
|
1294
|
+
menu_id: prev && prev.menu_id || "",
|
|
1295
|
+
target: {
|
|
1296
|
+
stage: tree.stage || "main",
|
|
1297
|
+
gclass: "C_YUI_NODE",
|
|
1298
|
+
lifecycle: "keep_alive",
|
|
1299
|
+
owns_subtree: true,
|
|
1300
|
+
kw
|
|
1301
|
+
}
|
|
1302
|
+
};
|
|
1195
1303
|
}
|
|
1196
1304
|
/************************************************************
|
|
1197
1305
|
* For each menu declared: for each zone hosting it, create
|
|
@@ -1436,6 +1544,7 @@ function navigate_to(gobj, route, depth, no_drain) {
|
|
|
1436
1544
|
if ($c) $c.classList.remove("is-hidden");
|
|
1437
1545
|
stage.active_route = matched_route;
|
|
1438
1546
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "current_route", route);
|
|
1547
|
+
remember_position(gobj, route);
|
|
1439
1548
|
update_secondary_nav_visibility(gobj, entry);
|
|
1440
1549
|
close_all_drawers(gobj);
|
|
1441
1550
|
close_toolbar_dropdown(gobj);
|
|
@@ -2060,7 +2169,11 @@ function pop_escape(gobj, handler) {
|
|
|
2060
2169
|
* - navigate_to() drains (closes) every registered overlay when the
|
|
2061
2170
|
* RESTING route changes — overlays are transient and do not
|
|
2062
2171
|
* outlive the view they float above. An action route or a
|
|
2063
|
-
* subpath-only move keeps them open.
|
|
2172
|
+
* subpath-only move keeps them open. An overlay registered with
|
|
2173
|
+
* `keep_on_navigate` opts OUT of the drain: it is a NAVIGATION
|
|
2174
|
+
* PANEL, not a thing floating above one view — the site map is
|
|
2175
|
+
* the reference case, where every row click is meant to move the
|
|
2176
|
+
* user with the panel still up.
|
|
2064
2177
|
* - a drained/buried entry is left INERT: overlay_dismissed only
|
|
2065
2178
|
* history.back()s when the marker is the CURRENT history entry
|
|
2066
2179
|
* (adjacent, so the back() is invisible) — never over real route
|
|
@@ -2073,14 +2186,20 @@ function pop_escape(gobj, handler) {
|
|
|
2073
2186
|
function drain_overlays(gobj) {
|
|
2074
2187
|
let priv = gobj.priv;
|
|
2075
2188
|
if (!priv || !priv.overlay_stack) return;
|
|
2189
|
+
let kept = [];
|
|
2076
2190
|
while (priv.overlay_stack.length > 0) {
|
|
2077
2191
|
let entry = priv.overlay_stack.pop();
|
|
2192
|
+
if (entry.keep_on_navigate) {
|
|
2193
|
+
kept.unshift(entry);
|
|
2194
|
+
continue;
|
|
2195
|
+
}
|
|
2078
2196
|
try {
|
|
2079
2197
|
entry.close();
|
|
2080
2198
|
} catch (e) {
|
|
2081
2199
|
(0, _yuneta_gobj_js.log_warning)(`C_YUI_SHELL: overlay close on navigation failed: ${e}`);
|
|
2082
2200
|
}
|
|
2083
2201
|
}
|
|
2202
|
+
for (let entry of kept) priv.overlay_stack.push(entry);
|
|
2084
2203
|
}
|
|
2085
2204
|
function retag_overlay_hash(gobj, st, hash) {
|
|
2086
2205
|
let priv = gobj.priv;
|
|
@@ -2088,7 +2207,7 @@ function retag_overlay_hash(gobj, st, hash) {
|
|
|
2088
2207
|
let entry = priv.overlay_stack.find((e) => e.id === st.__yui_overlay__);
|
|
2089
2208
|
if (entry) entry.hash = hash;
|
|
2090
2209
|
}
|
|
2091
|
-
function push_overlay_history(gobj, close) {
|
|
2210
|
+
function push_overlay_history(gobj, close, opts) {
|
|
2092
2211
|
let priv = gobj.priv;
|
|
2093
2212
|
if (!priv || !priv.overlay_stack || !(0, _yuneta_gobj_js.gobj_read_attr)(gobj, "use_hash")) return null;
|
|
2094
2213
|
let entry = {
|
|
@@ -2219,6 +2338,7 @@ function update_secondary_nav_visibility(gobj, entry) {
|
|
|
2219
2338
|
function ac_nav_clicked(gobj, event, kw, src) {
|
|
2220
2339
|
let route = kw && kw.route || "";
|
|
2221
2340
|
if ((0, _yuneta_gobj_js.empty_string)(route)) return 0;
|
|
2341
|
+
route = remembered_position(gobj, route);
|
|
2222
2342
|
if ((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "use_hash") && !route_restores_url(gobj, route)) {
|
|
2223
2343
|
let target_hash = route_to_hash(route);
|
|
2224
2344
|
if (window.location.hash !== target_hash) window.location.hash = target_hash;
|
|
@@ -2302,6 +2422,48 @@ function register_c_yui_shell() {
|
|
|
2302
2422
|
* bottom of the file to keep the skeleton layout intact.
|
|
2303
2423
|
***************************************************************/
|
|
2304
2424
|
/************************************************************
|
|
2425
|
+
* Last position inside each section — the routes a MENU CLICK
|
|
2426
|
+
* returns to (`remember_section_position`).
|
|
2427
|
+
*
|
|
2428
|
+
* A section is a menu item's route; anything under it is a
|
|
2429
|
+
* position inside it. The memory MIRRORS the url and is never
|
|
2430
|
+
* the authority for it (ROUTING.md §3): it lives for the page,
|
|
2431
|
+
* not on disk, and only a click on the section's own menu item
|
|
2432
|
+
* consults it. Typing the url, a deep link, Back/Forward and
|
|
2433
|
+
* programmatic navigation all land exactly where they say —
|
|
2434
|
+
* which is the property that would be lost if this were stored
|
|
2435
|
+
* and applied everywhere.
|
|
2436
|
+
************************************************************/
|
|
2437
|
+
function remember_position(gobj, route) {
|
|
2438
|
+
let priv = gobj.priv;
|
|
2439
|
+
if (!(0, _yuneta_gobj_js.gobj_read_attr)(gobj, "remember_section_position")) return;
|
|
2440
|
+
for (let section of Object.keys(priv.item_index)) {
|
|
2441
|
+
if (section === "/") continue;
|
|
2442
|
+
if (route === section || route.indexOf(section + "/") === 0) priv.section_pos[section] = route;
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
/************************************************************
|
|
2446
|
+
* Where a click on `route` should actually land: the last
|
|
2447
|
+
* position inside it, when there is one and it still resolves.
|
|
2448
|
+
* A remembered route whose node has since disappeared is
|
|
2449
|
+
* dropped rather than followed — the tree is allowed to change
|
|
2450
|
+
* under a memory.
|
|
2451
|
+
************************************************************/
|
|
2452
|
+
function remembered_position(gobj, route) {
|
|
2453
|
+
let priv = gobj.priv;
|
|
2454
|
+
if (!(0, _yuneta_gobj_js.gobj_read_attr)(gobj, "remember_section_position")) return route;
|
|
2455
|
+
let current = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "current_route") || "";
|
|
2456
|
+
if (current === route || current.indexOf(route + "/") === 0) return route;
|
|
2457
|
+
let last = priv.section_pos[route];
|
|
2458
|
+
if (!last || last === route) return route;
|
|
2459
|
+
let r = resolve_route(priv.item_index, last);
|
|
2460
|
+
if (!r || !r.entry || !r.entry.target) {
|
|
2461
|
+
delete priv.section_pos[route];
|
|
2462
|
+
return route;
|
|
2463
|
+
}
|
|
2464
|
+
return last;
|
|
2465
|
+
}
|
|
2466
|
+
/************************************************************
|
|
2305
2467
|
* Resolve the shell that governs `gobj`: the nearest
|
|
2306
2468
|
* C_YUI_SHELL ancestor, else the last shell created on the
|
|
2307
2469
|
* page (apps have exactly one). Null when no shell exists —
|
|
@@ -2403,8 +2565,8 @@ function yui_shell_push_escape(shell_gobj, layer, handler) {
|
|
|
2403
2565
|
function yui_shell_pop_escape(shell_gobj, handler) {
|
|
2404
2566
|
pop_escape(shell_gobj, handler);
|
|
2405
2567
|
}
|
|
2406
|
-
function yui_shell_register_overlay(shell_gobj, close_fn) {
|
|
2407
|
-
return push_overlay_history(shell_gobj, close_fn);
|
|
2568
|
+
function yui_shell_register_overlay(shell_gobj, close_fn, opts) {
|
|
2569
|
+
return push_overlay_history(shell_gobj, close_fn, opts);
|
|
2408
2570
|
}
|
|
2409
2571
|
function yui_shell_overlay_dismissed(shell_gobj, overlay) {
|
|
2410
2572
|
overlay_dismissed(shell_gobj, overlay);
|
|
@@ -3008,6 +3170,7 @@ var attrs_table$16 = [
|
|
|
3008
3170
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "modal", 0, false, "Enable modal mode"),
|
|
3009
3171
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "keyboard", 0, true, "Close window on ESC if not modal"),
|
|
3010
3172
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "back_dismissable", 0, true, "Browser Back closes this window (floating overlays only; ignored when it has a `manager`)"),
|
|
3173
|
+
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_BOOLEAN, "keep_on_navigate", 0, false, "This window is a navigation PANEL: a route change does not close it"),
|
|
3011
3174
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "back_overlay", 0, null, "Internal: overlay-history entry (Back-button integration)"),
|
|
3012
3175
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_POINTER, "$container", 0, null, "Internal: Window container element"),
|
|
3013
3176
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_STRING, "window_id", 0, "", "Internal: Window ID"),
|
|
@@ -3047,7 +3210,7 @@ function mt_create$16(gobj) {
|
|
|
3047
3210
|
let shell = yui_shell_of(gobj);
|
|
3048
3211
|
if (shell) (0, _yuneta_gobj_js.gobj_write_attr)(gobj, "back_overlay", yui_shell_register_overlay(shell, function() {
|
|
3049
3212
|
close_window(gobj);
|
|
3050
|
-
}));
|
|
3213
|
+
}, { keep_on_navigate: (0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "keep_on_navigate") }));
|
|
3051
3214
|
}
|
|
3052
3215
|
let on_win_resize = function() {
|
|
3053
3216
|
handleResize(gobj);
|
|
@@ -10493,10 +10656,19 @@ function leaf_row(key, value, depth) {
|
|
|
10493
10656
|
];
|
|
10494
10657
|
}
|
|
10495
10658
|
/************************************************************
|
|
10496
|
-
* Depth indentation (inline style keeps it CSS-framework free)
|
|
10659
|
+
* Depth indentation (inline style keeps it CSS-framework free).
|
|
10660
|
+
*
|
|
10661
|
+
* FOUR characters per level, house rule: structure is read as
|
|
10662
|
+
* indentation, and it has to be the same four everywhere — this
|
|
10663
|
+
* viewer, the raw dump behind it, the site map's tree. `ch` is
|
|
10664
|
+
* the character width of the row's own font, so the rows line up
|
|
10665
|
+
* with the monospace text they carry instead of drifting from it
|
|
10666
|
+
* at some zoom level.
|
|
10497
10667
|
************************************************************/
|
|
10668
|
+
var INDENT_CH = 4;
|
|
10669
|
+
var INDENT_PAD = .4;
|
|
10498
10670
|
function row_indent(depth) {
|
|
10499
|
-
return "padding-left:" + (
|
|
10671
|
+
return "padding-left:" + (INDENT_PAD + depth * INDENT_CH) + "ch;background-size:" + depth * INDENT_CH + "ch 100%;";
|
|
10500
10672
|
}
|
|
10501
10673
|
/************************************************************
|
|
10502
10674
|
* String() that never throws on a non-primitive
|
|
@@ -10636,7 +10808,7 @@ function ac_collapse_all$1(gobj, event, kw, src) {
|
|
|
10636
10808
|
function ac_copy_all(gobj, event, kw, src) {
|
|
10637
10809
|
let priv = gobj.priv;
|
|
10638
10810
|
if (priv.root === null || priv.root === void 0) return 0;
|
|
10639
|
-
let text = JSON.stringify(priv.root, null,
|
|
10811
|
+
let text = JSON.stringify(priv.root, null, 4);
|
|
10640
10812
|
if (navigator.clipboard && navigator.clipboard.writeText) navigator.clipboard.writeText(text).catch(function(e) {
|
|
10641
10813
|
(0, _yuneta_gobj_js.log_error)(`${GCLASS_NAME$8}: clipboard write failed: ${e}`);
|
|
10642
10814
|
});
|
|
@@ -12493,6 +12665,13 @@ function cards_grid_descriptor(items, show_label) {
|
|
|
12493
12665
|
* "cards" — grid of tappable cards (section-index landing;
|
|
12494
12666
|
* mounted as a stage view by C_YUI_SHELL when a
|
|
12495
12667
|
* primary item declares submenu.index)
|
|
12668
|
+
* "breadcrumb" — the PATH as one line ("Cards › Energy › South
|
|
12669
|
+
* hall › Meter 3"), each crumb a link to that
|
|
12670
|
+
* level. Unlike every other layout its items
|
|
12671
|
+
* are not a node's children but the trail down
|
|
12672
|
+
* to where the user is: the second way to show
|
|
12673
|
+
* depth, for when stacking one strip per level
|
|
12674
|
+
* costs more vertical room than it is worth.
|
|
12496
12675
|
* "backbar" — single "← <section>" link back to the section
|
|
12497
12676
|
* index; the mobile replacement of the tab strip
|
|
12498
12677
|
* for submenu.index sections (the shell collapses
|
|
@@ -12540,7 +12719,8 @@ var SUPPORTED_LAYOUTS = [
|
|
|
12540
12719
|
"submenu",
|
|
12541
12720
|
"accordion",
|
|
12542
12721
|
"cards",
|
|
12543
|
-
"backbar"
|
|
12722
|
+
"backbar",
|
|
12723
|
+
"breadcrumb"
|
|
12544
12724
|
];
|
|
12545
12725
|
function is_decorative(it) {
|
|
12546
12726
|
return !!(it && (it.type === "header" || it.type === "divider"));
|
|
@@ -12646,6 +12826,9 @@ function build_ui$6(gobj) {
|
|
|
12646
12826
|
case "backbar":
|
|
12647
12827
|
$container = render_backbar(gobj);
|
|
12648
12828
|
break;
|
|
12829
|
+
case "breadcrumb":
|
|
12830
|
+
$container = render_breadcrumb(gobj, items);
|
|
12831
|
+
break;
|
|
12649
12832
|
default: $container = render_vertical(gobj, items);
|
|
12650
12833
|
}
|
|
12651
12834
|
$container.setAttribute("data-nav-zone", zone);
|
|
@@ -12666,6 +12849,7 @@ function build_ui$6(gobj) {
|
|
|
12666
12849
|
}
|
|
12667
12850
|
wire_clicks(gobj, $container);
|
|
12668
12851
|
(0, _yuneta_gobj_js.gobj_write_attr)(gobj, "$container", $container);
|
|
12852
|
+
apply_active_route(gobj);
|
|
12669
12853
|
}
|
|
12670
12854
|
/************************************************************
|
|
12671
12855
|
* Rebuild the nav DOM in place from the current menu_items.
|
|
@@ -12684,7 +12868,6 @@ function rebuild(gobj) {
|
|
|
12684
12868
|
if ($new && was_hidden) $new.classList.add("is-hidden");
|
|
12685
12869
|
if (parent && $new) parent.insertBefore($new, next);
|
|
12686
12870
|
if ($old && $old.parentNode) $old.parentNode.removeChild($old);
|
|
12687
|
-
apply_active_route(gobj);
|
|
12688
12871
|
}
|
|
12689
12872
|
/************************************************************
|
|
12690
12873
|
* Re-apply the active-route highlight after a rebuild (the
|
|
@@ -12838,6 +13021,74 @@ function render_cards(gobj, items) {
|
|
|
12838
13021
|
* collapses the whole secondary zone (tabs and cards never
|
|
12839
13022
|
* coexist), so the bar needs no self-hiding logic.
|
|
12840
13023
|
************************************************************/
|
|
13024
|
+
/************************************************************
|
|
13025
|
+
* breadcrumb: the trail to here, one line.
|
|
13026
|
+
*
|
|
13027
|
+
* Bulma's own markup (nav.breadcrumb > ul > li, separators drawn by
|
|
13028
|
+
* CSS), with the SAME data-route/data-item-id contract as every
|
|
13029
|
+
* other layout — so the delegated click handler and the active
|
|
13030
|
+
* highlight work unchanged, and the last crumb marks itself through
|
|
13031
|
+
* `active_route` like a tab does.
|
|
13032
|
+
************************************************************/
|
|
13033
|
+
function render_breadcrumb(gobj, items) {
|
|
13034
|
+
let show_label = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "show_label");
|
|
13035
|
+
let lis = [];
|
|
13036
|
+
for (let it of items || []) {
|
|
13037
|
+
if (is_decorative(it)) continue;
|
|
13038
|
+
let children = [];
|
|
13039
|
+
if (it.icon) children.push([
|
|
13040
|
+
"span",
|
|
13041
|
+
{ class: "icon is-small" },
|
|
13042
|
+
["i", {
|
|
13043
|
+
class: it.icon,
|
|
13044
|
+
"aria-hidden": "true"
|
|
13045
|
+
}]
|
|
13046
|
+
]);
|
|
13047
|
+
if (show_label !== false) {
|
|
13048
|
+
let label = it.name || it.id || "";
|
|
13049
|
+
children.push([
|
|
13050
|
+
"span",
|
|
13051
|
+
{
|
|
13052
|
+
class: "yui-nav-label",
|
|
13053
|
+
i18n: label
|
|
13054
|
+
},
|
|
13055
|
+
label
|
|
13056
|
+
]);
|
|
13057
|
+
}
|
|
13058
|
+
let a_attrs = {
|
|
13059
|
+
class: "yui-nav-item yui-nav-crumb",
|
|
13060
|
+
href: it.route ? "#" + it.route : "#",
|
|
13061
|
+
"data-item-id": it.id,
|
|
13062
|
+
"data-route": it.route || "",
|
|
13063
|
+
"data-disabled": it.disabled ? "1" : "0"
|
|
13064
|
+
};
|
|
13065
|
+
if (it.name) {
|
|
13066
|
+
a_attrs["aria-label"] = it.name;
|
|
13067
|
+
a_attrs["data-i18n-aria-label"] = it.name;
|
|
13068
|
+
}
|
|
13069
|
+
lis.push([
|
|
13070
|
+
"li",
|
|
13071
|
+
{},
|
|
13072
|
+
[[
|
|
13073
|
+
"a",
|
|
13074
|
+
a_attrs,
|
|
13075
|
+
children
|
|
13076
|
+
]]
|
|
13077
|
+
]);
|
|
13078
|
+
}
|
|
13079
|
+
return (0, _yuneta_gobj_js.createElement2)([
|
|
13080
|
+
"nav",
|
|
13081
|
+
{
|
|
13082
|
+
class: "breadcrumb is-small",
|
|
13083
|
+
"aria-label": "breadcrumbs"
|
|
13084
|
+
},
|
|
13085
|
+
[[
|
|
13086
|
+
"ul",
|
|
13087
|
+
{},
|
|
13088
|
+
lis
|
|
13089
|
+
]]
|
|
13090
|
+
]);
|
|
13091
|
+
}
|
|
12841
13092
|
function render_backbar(gobj) {
|
|
12842
13093
|
let back_route = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "back_route") || "";
|
|
12843
13094
|
let label = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "nav_label") || "";
|
|
@@ -13243,6 +13494,7 @@ function register_c_yui_nav() {
|
|
|
13243
13494
|
//#endregion
|
|
13244
13495
|
//#region src/shell_route_map.js
|
|
13245
13496
|
var WIN_NAME$1 = "shell-route-map-window";
|
|
13497
|
+
var __show_refs__ = true;
|
|
13246
13498
|
var __open_modal__ = null;
|
|
13247
13499
|
function scroll_to_current($body) {
|
|
13248
13500
|
let $cur = $body.querySelector(".ROUTEMAP_CURRENT");
|
|
@@ -13288,6 +13540,16 @@ function render_node(node) {
|
|
|
13288
13540
|
{ class: "ROUTEMAP_EVENT" },
|
|
13289
13541
|
node.event
|
|
13290
13542
|
]);
|
|
13543
|
+
if (node.ref) row.push([
|
|
13544
|
+
"span",
|
|
13545
|
+
{
|
|
13546
|
+
class: "ROUTEMAP_REF",
|
|
13547
|
+
i18n: "shown above",
|
|
13548
|
+
title: "shown above",
|
|
13549
|
+
"data-i18n-title": "shown above"
|
|
13550
|
+
},
|
|
13551
|
+
"shown above"
|
|
13552
|
+
]);
|
|
13291
13553
|
if (node.current) row.push([
|
|
13292
13554
|
"span",
|
|
13293
13555
|
{
|
|
@@ -13296,7 +13558,7 @@ function render_node(node) {
|
|
|
13296
13558
|
},
|
|
13297
13559
|
"you are here"
|
|
13298
13560
|
]);
|
|
13299
|
-
let row_class = node.current ? " ROUTEMAP_CURRENT" : "";
|
|
13561
|
+
let row_class = (node.current ? " ROUTEMAP_CURRENT" : "") + (node.ref ? " ROUTEMAP_IS_REF" : "");
|
|
13300
13562
|
let $row;
|
|
13301
13563
|
if (node.route) $row = (0, _yuneta_gobj_js.createElement2)([
|
|
13302
13564
|
"a",
|
|
@@ -13329,21 +13591,37 @@ function render_node(node) {
|
|
|
13329
13591
|
* descendant matches (keep the ancestor path). Empty `q` shows all.
|
|
13330
13592
|
* Matches against the visible row text (name + route + event), so it
|
|
13331
13593
|
* honours the current translation. Returns whether the <li> is shown.
|
|
13594
|
+
*
|
|
13595
|
+
* `show_refs` off hides the reference rows — the second and third
|
|
13596
|
+
* place a route is reachable from, which carry no structure. They are
|
|
13597
|
+
* hidden by DEFAULT: in an app with a drawer and an account menu they
|
|
13598
|
+
* are a third of the map, and what a reader comes here for is the
|
|
13599
|
+
* structure. A ref stays hidden even inside a matched subtree — an
|
|
13600
|
+
* ancestor match must not smuggle it back in — and a group left with
|
|
13601
|
+
* nothing but refs collapses with them, since a group is only ever
|
|
13602
|
+
* shown by what it contains.
|
|
13332
13603
|
***************************************************************/
|
|
13333
|
-
function filter_li($li, q, ancestor_match) {
|
|
13604
|
+
function filter_li($li, q, ancestor_match, show_refs) {
|
|
13334
13605
|
let $row = $li.querySelector(":scope > .ROUTEMAP_ROW");
|
|
13335
13606
|
let text = $row ? ($row.textContent || "").toLowerCase() : "";
|
|
13607
|
+
let hidden_ref = !show_refs && !!($row && $row.classList.contains("ROUTEMAP_IS_REF"));
|
|
13336
13608
|
let self_match = q === "" || text.indexOf(q) >= 0;
|
|
13337
|
-
let show_all = ancestor_match || self_match;
|
|
13609
|
+
let show_all = (ancestor_match || self_match) && !hidden_ref;
|
|
13338
13610
|
let any_child = false;
|
|
13339
13611
|
let $ul = $li.querySelector(":scope > ul");
|
|
13340
13612
|
if ($ul) {
|
|
13341
13613
|
let kids = $ul.children;
|
|
13342
|
-
for (let i = 0; i < kids.length; i++) if (filter_li(kids[i], q, show_all)) any_child = true;
|
|
13614
|
+
for (let i = 0; i < kids.length; i++) if (filter_li(kids[i], q, show_all, show_refs)) any_child = true;
|
|
13615
|
+
}
|
|
13616
|
+
let is_group = !!($row && $row.classList.contains("ROUTEMAP_STRUCT"));
|
|
13617
|
+
let had_children = !!($ul && $ul.children.length);
|
|
13618
|
+
if (is_group && had_children && !any_child && !show_refs) {
|
|
13619
|
+
let kids = $ul.children;
|
|
13620
|
+
for (let i = 0; i < kids.length; i++) if (filter_li(kids[i], q, show_all, true)) any_child = true;
|
|
13343
13621
|
}
|
|
13344
|
-
let visible = show_all || any_child;
|
|
13622
|
+
let visible = is_group && had_children ? any_child || q !== "" && self_match : (show_all || any_child) && !hidden_ref;
|
|
13345
13623
|
$li.style.display = visible ? "" : "none";
|
|
13346
|
-
if ($row) $row.classList.toggle("ROUTEMAP_MATCH", q !== "" && self_match);
|
|
13624
|
+
if ($row) $row.classList.toggle("ROUTEMAP_MATCH", q !== "" && self_match && visible);
|
|
13347
13625
|
return visible;
|
|
13348
13626
|
}
|
|
13349
13627
|
/***************************************************************
|
|
@@ -13353,16 +13631,17 @@ function filter_li($li, q, ancestor_match) {
|
|
|
13353
13631
|
* on a resting-route change. `on_jump()` closes the host for the
|
|
13354
13632
|
* one click that navigates nowhere (the current route).
|
|
13355
13633
|
***************************************************************/
|
|
13356
|
-
function build_body(shell, t
|
|
13634
|
+
function build_body(shell, t) {
|
|
13357
13635
|
let map = yui_shell_nav_map(shell);
|
|
13358
|
-
let children = [
|
|
13636
|
+
let children = [].concat(map.nav);
|
|
13637
|
+
if (Array.isArray(map.toolbar) && map.toolbar.length) children.push({
|
|
13359
13638
|
label: "toolbar",
|
|
13360
13639
|
icon: "",
|
|
13361
13640
|
route: "",
|
|
13362
13641
|
event: "",
|
|
13363
13642
|
kind: "group",
|
|
13364
13643
|
children: map.toolbar
|
|
13365
|
-
}
|
|
13644
|
+
});
|
|
13366
13645
|
if (Array.isArray(map.other) && map.other.length) children.push({
|
|
13367
13646
|
label: "other routes",
|
|
13368
13647
|
icon: "",
|
|
@@ -13415,21 +13694,53 @@ function build_body(shell, t, on_jump) {
|
|
|
13415
13694
|
"matches"
|
|
13416
13695
|
]]
|
|
13417
13696
|
]);
|
|
13697
|
+
let $refs_input = (0, _yuneta_gobj_js.createElement2)(["input", {
|
|
13698
|
+
class: "ROUTEMAP_REFS_INPUT",
|
|
13699
|
+
type: "checkbox"
|
|
13700
|
+
}]);
|
|
13701
|
+
if (__show_refs__) $refs_input.checked = true;
|
|
13702
|
+
let $refs_toggle = (0, _yuneta_gobj_js.createElement2)([
|
|
13703
|
+
"label",
|
|
13704
|
+
{
|
|
13705
|
+
class: "checkbox is-size-7 ROUTEMAP_REFS_TOGGLE",
|
|
13706
|
+
title: "show references",
|
|
13707
|
+
"data-i18n-title": "show references"
|
|
13708
|
+
},
|
|
13709
|
+
[$refs_input, [
|
|
13710
|
+
"span",
|
|
13711
|
+
{
|
|
13712
|
+
class: "ml-1",
|
|
13713
|
+
i18n: "show references"
|
|
13714
|
+
},
|
|
13715
|
+
"show references"
|
|
13716
|
+
]]
|
|
13717
|
+
]);
|
|
13418
13718
|
let $search_row = (0, _yuneta_gobj_js.createElement2)([
|
|
13419
13719
|
"div",
|
|
13420
13720
|
{ class: "ROUTEMAP_SEARCH_ROW mb-2" },
|
|
13421
|
-
[
|
|
13721
|
+
[
|
|
13722
|
+
$search_ctrl,
|
|
13723
|
+
$count,
|
|
13724
|
+
$refs_toggle
|
|
13725
|
+
]
|
|
13422
13726
|
]);
|
|
13423
|
-
|
|
13727
|
+
let apply_filter = function() {
|
|
13424
13728
|
let q = ($search.value || "").trim().toLowerCase();
|
|
13425
13729
|
let $root_li = $tree.querySelector(".ROUTEMAP_ROOT > li");
|
|
13426
|
-
if ($root_li) filter_li($root_li, q, false);
|
|
13730
|
+
if ($root_li) filter_li($root_li, q, false, __show_refs__);
|
|
13427
13731
|
if (q === "") $count.classList.add("is-hidden");
|
|
13428
13732
|
else {
|
|
13429
13733
|
$count_n.textContent = $tree.querySelectorAll(".ROUTEMAP_MATCH").length;
|
|
13430
13734
|
$count.classList.remove("is-hidden");
|
|
13431
13735
|
}
|
|
13736
|
+
};
|
|
13737
|
+
$search.addEventListener("input", apply_filter);
|
|
13738
|
+
$refs_input.addEventListener("change", function() {
|
|
13739
|
+
__show_refs__ = !!$refs_input.checked;
|
|
13740
|
+
apply_filter();
|
|
13432
13741
|
});
|
|
13742
|
+
if ($tree.querySelectorAll(".ROUTEMAP_IS_REF").length === 0) $refs_toggle.classList.add("is-hidden");
|
|
13743
|
+
apply_filter();
|
|
13433
13744
|
let $body = (0, _yuneta_gobj_js.createElement2)([
|
|
13434
13745
|
"div",
|
|
13435
13746
|
{ class: "C_YUI_SHELL_ROUTEMAP ROUTEMAP_BODY" },
|
|
@@ -13472,19 +13783,55 @@ function build_body(shell, t, on_jump) {
|
|
|
13472
13783
|
if ($area.parentNode) $area.parentNode.removeChild($area);
|
|
13473
13784
|
}
|
|
13474
13785
|
});
|
|
13475
|
-
|
|
13476
|
-
|
|
13477
|
-
|
|
13478
|
-
|
|
13479
|
-
if (href && typeof window !== "undefined" && window.location.hash === href && typeof on_jump === "function") {
|
|
13480
|
-
ev.preventDefault();
|
|
13481
|
-
on_jump();
|
|
13786
|
+
let on_hash = function() {
|
|
13787
|
+
if (typeof document === "undefined" || !$body.isConnected) {
|
|
13788
|
+
if (typeof window !== "undefined") window.removeEventListener("hashchange", on_hash);
|
|
13789
|
+
return;
|
|
13482
13790
|
}
|
|
13483
|
-
|
|
13791
|
+
mark_current_row($body, window.location.hash, t);
|
|
13792
|
+
};
|
|
13793
|
+
if (typeof window !== "undefined") window.addEventListener("hashchange", on_hash);
|
|
13484
13794
|
(0, _yuneta_gobj_js.refresh_language)($body, t);
|
|
13485
13795
|
return $body;
|
|
13486
13796
|
}
|
|
13487
13797
|
/***************************************************************
|
|
13798
|
+
* Move the "you are here" mark to the row that best matches
|
|
13799
|
+
* `hash`: an exact route wins, else the LONGEST declared route
|
|
13800
|
+
* that is a path-prefix of it (the base view of a deep subpath
|
|
13801
|
+
* position). Same rule as the model's mark_current(), applied
|
|
13802
|
+
* to the rendered rows so the open panel stays truthful.
|
|
13803
|
+
***************************************************************/
|
|
13804
|
+
function mark_current_row($body, hash, t) {
|
|
13805
|
+
let route = String(hash || "").replace(/^#/, "");
|
|
13806
|
+
let $best = null;
|
|
13807
|
+
let best_len = -1;
|
|
13808
|
+
for (let $a of $body.querySelectorAll(".ROUTEMAP_LINK")) {
|
|
13809
|
+
let r = String($a.getAttribute("href") || "").replace(/^#/, "");
|
|
13810
|
+
if (!r) continue;
|
|
13811
|
+
if (r === route) {
|
|
13812
|
+
$best = $a;
|
|
13813
|
+
break;
|
|
13814
|
+
}
|
|
13815
|
+
if (route.indexOf(r + "/") === 0 && r.length > best_len) {
|
|
13816
|
+
$best = $a;
|
|
13817
|
+
best_len = r.length;
|
|
13818
|
+
}
|
|
13819
|
+
}
|
|
13820
|
+
for (let $marked of $body.querySelectorAll(".ROUTEMAP_CURRENT")) $marked.classList.remove("ROUTEMAP_CURRENT");
|
|
13821
|
+
if (!$best) return;
|
|
13822
|
+
$best.classList.add("ROUTEMAP_CURRENT");
|
|
13823
|
+
let $badge = $body.querySelector(".ROUTEMAP_HERE");
|
|
13824
|
+
if (!$badge) $badge = (0, _yuneta_gobj_js.createElement2)([
|
|
13825
|
+
"span",
|
|
13826
|
+
{
|
|
13827
|
+
class: "ROUTEMAP_HERE",
|
|
13828
|
+
i18n: "you are here"
|
|
13829
|
+
},
|
|
13830
|
+
t ? t("you are here") : "you are here"
|
|
13831
|
+
]);
|
|
13832
|
+
$best.appendChild($badge);
|
|
13833
|
+
}
|
|
13834
|
+
/***************************************************************
|
|
13488
13835
|
* Show the site map. Toggles: a second call closes the open one.
|
|
13489
13836
|
***************************************************************/
|
|
13490
13837
|
function yui_shell_show_route_map(shell, opts) {
|
|
@@ -13502,9 +13849,7 @@ function yui_shell_show_route_map(shell, opts) {
|
|
|
13502
13849
|
}
|
|
13503
13850
|
if ((0, _yuneta_gobj_js.gclass_find_by_name)("C_YUI_WINDOW") !== null) {
|
|
13504
13851
|
let win_ref = { gobj: null };
|
|
13505
|
-
let $body = build_body(shell, t
|
|
13506
|
-
if (win_ref.gobj && (0, _yuneta_gobj_js.is_gobj)(win_ref.gobj)) (0, _yuneta_gobj_js.gobj_send_event)(win_ref.gobj, "EV_CLOSE_WINDOW", {}, shell);
|
|
13507
|
-
});
|
|
13852
|
+
let $body = build_body(shell, t);
|
|
13508
13853
|
let $parent = yui_shell_popup_layer(shell) || typeof document !== "undefined" && document.getElementById("top-layer") || null;
|
|
13509
13854
|
let win = (0, _yuneta_gobj_js.gobj_create_service)(WIN_NAME$1, "C_YUI_WINDOW", {
|
|
13510
13855
|
$parent,
|
|
@@ -13521,7 +13866,8 @@ function yui_shell_show_route_map(shell, opts) {
|
|
|
13521
13866
|
title: "site map",
|
|
13522
13867
|
icon: "yi-bars",
|
|
13523
13868
|
body: $body,
|
|
13524
|
-
manager: null
|
|
13869
|
+
manager: (0, _yuneta_gobj_js.gobj_find_service)("__window_manager__", false) || null,
|
|
13870
|
+
keep_on_navigate: true
|
|
13525
13871
|
}, shell);
|
|
13526
13872
|
if (!win) {
|
|
13527
13873
|
(0, _yuneta_gobj_js.log_error)("C_YUI_SHELL: cannot create the site-map window");
|
|
@@ -13533,9 +13879,7 @@ function yui_shell_show_route_map(shell, opts) {
|
|
|
13533
13879
|
return win;
|
|
13534
13880
|
}
|
|
13535
13881
|
let modal_ref = { modal: null };
|
|
13536
|
-
let $body = build_body(shell, t
|
|
13537
|
-
if (modal_ref.modal && typeof modal_ref.modal.close === "function") modal_ref.modal.close();
|
|
13538
|
-
});
|
|
13882
|
+
let $body = build_body(shell, t);
|
|
13539
13883
|
modal_ref.modal = yui_shell_show_modal(shell, $body, {
|
|
13540
13884
|
dialog: true,
|
|
13541
13885
|
logical_class: "ROUTEMAP_SHEET",
|
|
@@ -52011,7 +52355,7 @@ function render_full(e) {
|
|
|
52011
52355
|
let payload = full_sections(e.kw ? e.kw : e.jn);
|
|
52012
52356
|
let text;
|
|
52013
52357
|
try {
|
|
52014
|
-
text = JSON.stringify(payload, null,
|
|
52358
|
+
text = JSON.stringify(payload, null, 4);
|
|
52015
52359
|
} catch (err) {
|
|
52016
52360
|
text = String(payload);
|
|
52017
52361
|
}
|
|
@@ -52274,7 +52618,7 @@ function info_log(level, msg, hora) {
|
|
|
52274
52618
|
let text;
|
|
52275
52619
|
if (lvl === "json") {
|
|
52276
52620
|
try {
|
|
52277
|
-
text = JSON.stringify(msg, null,
|
|
52621
|
+
text = JSON.stringify(msg, null, 4);
|
|
52278
52622
|
} catch (e) {
|
|
52279
52623
|
text = String(msg);
|
|
52280
52624
|
}
|
|
@@ -52448,7 +52792,7 @@ function traffic_to_text() {
|
|
|
52448
52792
|
out.push(head);
|
|
52449
52793
|
let payload = e.kw ? e.kw : e.jn;
|
|
52450
52794
|
try {
|
|
52451
|
-
out.push(JSON.stringify(payload, null,
|
|
52795
|
+
out.push(JSON.stringify(payload, null, 4));
|
|
52452
52796
|
} catch (err) {
|
|
52453
52797
|
out.push(String(payload));
|
|
52454
52798
|
}
|
|
@@ -52820,6 +53164,7 @@ function setup_dev(self, show) {
|
|
|
52820
53164
|
title: "Developer",
|
|
52821
53165
|
icon: "yi-terminal",
|
|
52822
53166
|
manager: (0, _yuneta_gobj_js.gobj_find_service)("__window_manager__", false) || null,
|
|
53167
|
+
keep_on_navigate: true,
|
|
52823
53168
|
on_close: function() {
|
|
52824
53169
|
(0, _yuneta_gobj_js.kw_set_local_storage_value)("open_developer_window", 0);
|
|
52825
53170
|
}
|