@yuneta/gobj-ui 7.23.179 → 7.23.181

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 CHANGED
@@ -572,7 +572,7 @@ Two layout facts the browser taught this component, both worth keeping:
572
572
 
573
573
  - Attributes: `subscriber`, `title` (i18n key, optional — hidden on mobile,
574
574
  where the toolbar cannot hold it as well as the buttons), `json_data`
575
- (initial JSON, optional), `view_mode` (`"tree"` default | `"text"` |
575
+ (initial JSON, optional — given, the viewer starts in `ST_READY`), `view_mode` (`"tree"` default | `"text"` |
576
576
  `"graph"`), `$container` (mounted by the parent).
577
577
  - Input events: `EV_SET_JSON {json}` (replace the whole document; `ST_EMPTY` →
578
578
  `ST_READY`), `EV_SUBTREE_LOADED {path, json}` (splice a fetched subtree),
@@ -14023,6 +14023,7 @@ function mt_create$13(gobj) {
14023
14023
  * Framework Method: Start
14024
14024
  ***************************************************************/
14025
14025
  function mt_start$13(gobj) {
14026
+ if (gobj.priv.root !== null) (0, _yuneta_gobj_js.gobj_change_state)(gobj, "ST_READY");
14026
14027
  render_view$1(gobj);
14027
14028
  }
14028
14029
  /***************************************************************
@@ -76430,6 +76431,41 @@ function ensure_dev_style() {
76430
76431
  .YDEV_TITLE { display: flex; align-items: baseline; gap: 8px; }
76431
76432
  .YDEV_TITLE_MAIN { font-weight: 700; }
76432
76433
  .YDEV_TITLE_SUB { opacity: 0.7; font-size: 12px; }
76434
+ /* The ink of the log.
76435
+ *
76436
+ * It used to be one grey dimmed with opacity per role -- 0.85 for a key,
76437
+ * 0.5 for a preview, 0.45 for the source -- which is what washed the window
76438
+ * out: opacity blends text TOWARDS the background, so the more a line
76439
+ * mattered the less of it was left. Measured on the dark scheme the preview
76440
+ * came out at 4.39:1 and the source at 3.78:1, both under the 4.5 floor,
76441
+ * and everything that was legible was the same grey as everything else.
76442
+ *
76443
+ * Explicit colours now, one per ROLE and measured against the entry's own
76444
+ * background (#1b1e24 dark, #fafafa light): a key, a string, a number and a
76445
+ * boolean read apart from each other the way they do in a browser console,
76446
+ * which is the point of colouring a payload at all.
76447
+ * Ratios: dark 11.20 / 6.32 / 9.83 / 6.00 / 6.77 / 6.49 / 4.82,
76448
+ * light 7.38 / 7.52 / 5.16 / 8.35 / 5.59 / 7.21 / 4.35. */
76449
+ :root {
76450
+ --ydev-ink: #1f2937;
76451
+ --ydev-key: #0451a5;
76452
+ --ydev-str: #a31515;
76453
+ --ydev-num: #067a4e;
76454
+ --ydev-bool: #6b21a8;
76455
+ --ydev-dim: #5b6675;
76456
+ --ydev-src: #4a5568;
76457
+ --ydev-bullet: #6b7789;
76458
+ }
76459
+ :root[data-theme="dark"] {
76460
+ --ydev-ink: #e5e7eb;
76461
+ --ydev-key: #9cdcfe;
76462
+ --ydev-str: #ce9178;
76463
+ --ydev-num: #b5cea8;
76464
+ --ydev-bool: #c586c0;
76465
+ --ydev-dim: #9aa6b8;
76466
+ --ydev-src: #8fa3bf;
76467
+ --ydev-bullet: #7b8ba3;
76468
+ }
76433
76469
  /* -------- entries (shared) -------- */
76434
76470
  .TRAFFIC_ENTRY {
76435
76471
  border-left: 3px solid #94a3b8; border-radius: 3px;
@@ -76443,15 +76479,15 @@ function ensure_dev_style() {
76443
76479
  .TRAFFIC_HEADER { display: flex; align-items: baseline; gap: 8px; }
76444
76480
  .TRAFFIC_ARROW { font-weight: 700; }
76445
76481
  .TRAFFIC_EVENT { font-weight: 700; }
76446
- .TRAFFIC_CMD { opacity: 0.75; font-weight: 600; }
76482
+ .TRAFFIC_CMD { color: var(--ydev-dim); font-weight: 600; }
76447
76483
  /* Where the message went through. min-width 0 and flex 0 1 auto so it is the
76448
76484
  part that gives way when the row runs out of width -- the event name and
76449
76485
  the size/time must not be the ones to go. */
76450
- .TRAFFIC_SRC { opacity: 0.45; font-size: 11px; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
76486
+ .TRAFFIC_SRC { color: var(--ydev-src); font-size: 11px; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
76451
76487
  .dir-out .TRAFFIC_ARROW, .dir-out .TRAFFIC_EVENT { color: #2563eb; }
76452
76488
  .dir-in .TRAFFIC_ARROW, .dir-in .TRAFFIC_EVENT { color: #059669; }
76453
76489
  .dir-err .TRAFFIC_ARROW, .dir-err .TRAFFIC_EVENT { color: #dc2626; }
76454
- .TRAFFIC_META { margin-left: auto; opacity: 0.6; font-size: 11px; white-space: nowrap; }
76490
+ .TRAFFIC_META { margin-left: auto; color: var(--ydev-dim); font-size: 11px; white-space: nowrap; }
76455
76491
  /* The indent of a nested block is NOT a hover effect: it used to be given
76456
76492
  only on .TRAFFIC_ENTRY:hover, so moving the cursor across the log made
76457
76493
  every payload under it jump 16px sideways and reflow. A payload being
@@ -76460,29 +76496,40 @@ function ensure_dev_style() {
76460
76496
  .TRAFFIC_KW { margin: 2px 0 0 16px; }
76461
76497
  .TRAFFIC_FULL { margin: 4px 0 0 16px; padding: 6px 8px; font-family: monospace; font-size: 11px; line-height: 1.4; white-space: pre-wrap; word-break: break-word; background: rgba(0,0,0,0.04); border-radius: 4px; overflow-x: auto; }
76462
76498
  .TRAFFIC_ROW { display: flex; gap: 6px; align-items: baseline; }
76463
- .TRAFFIC_BULLET { opacity: 0.45; flex: 0 0 auto; }
76464
- .TRAFFIC_KEY { opacity: 0.85; flex: 0 0 auto; }
76465
- .TRAFFIC_VAL { word-break: break-word; }
76466
- .TRAFFIC_VAL.t-num { color: #0891b2; }
76467
- .TRAFFIC_VAL.t-bool { color: #9333ea; }
76468
- .TRAFFIC_VAL.t-null { color: #9333ea; font-style: italic; }
76469
- .TRAFFIC_VAL.t-empty { opacity: 0.5; }
76470
- .TRAFFIC_TS { opacity: 0.6; margin-left: 8px; }
76499
+ .TRAFFIC_BULLET { color: var(--ydev-bullet); flex: 0 0 auto; }
76500
+ .TRAFFIC_KEY { color: var(--ydev-key); flex: 0 0 auto; }
76501
+ .TRAFFIC_VAL { color: var(--ydev-ink); word-break: break-word; }
76502
+ .TRAFFIC_VAL.t-str { color: var(--ydev-str); }
76503
+ .TRAFFIC_VAL.t-num { color: var(--ydev-num); }
76504
+ .TRAFFIC_VAL.t-bool { color: var(--ydev-bool); }
76505
+ .TRAFFIC_VAL.t-null { color: var(--ydev-bool); font-style: italic; }
76506
+ .TRAFFIC_VAL.t-empty { color: var(--ydev-dim); }
76507
+ .TRAFFIC_TS { color: var(--ydev-dim); margin-left: 8px; }
76471
76508
  details.TRAFFIC_NEST > summary { cursor: pointer; list-style: none; display: flex; gap: 6px; align-items: baseline; }
76472
76509
  details.TRAFFIC_NEST > summary::-webkit-details-marker { display: none; }
76473
- .TRAFFIC_NEST_KEY { opacity: 0.85; }
76474
- .TRAFFIC_NEST_HINT { opacity: 0.5; margin-left: 4px; }
76475
- .YDEV_EMPTY { opacity: 0.5; font-size: 12px; padding: 18px 10px; text-align: center; }
76510
+ .TRAFFIC_NEST_KEY { color: var(--ydev-key); }
76511
+ .TRAFFIC_NEST_HINT { color: var(--ydev-dim); margin-left: 4px; }
76512
+ /* The folded preview, painted with the same ink as the expanded rows: a key
76513
+ is a key and a string is a string wherever it is read. */
76514
+ .TRAFFIC_NEST_HINT_WRAP { margin-left: 4px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
76515
+ .TRAFFIC_PREV.p-punct { color: var(--ydev-dim); }
76516
+ .TRAFFIC_PREV.p-key { color: var(--ydev-key); }
76517
+ .TRAFFIC_PREV.t-str { color: var(--ydev-str); }
76518
+ .TRAFFIC_PREV.t-num { color: var(--ydev-num); }
76519
+ .TRAFFIC_PREV.t-bool { color: var(--ydev-bool); }
76520
+ .TRAFFIC_PREV.t-null { color: var(--ydev-bool); font-style: italic; }
76521
+ .TRAFFIC_PREV.t-empty { color: var(--ydev-dim); }
76522
+ .YDEV_EMPTY { color: var(--ydev-dim); font-size: 12px; padding: 18px 10px; text-align: center; }
76476
76523
  /* -------- mirrored console logs (error/warning/info/debug/msg; the automata trace shows as debug) -------- */
76477
76524
  .YDEV_LOGROW { display: flex; align-items: baseline; gap: 8px; margin: 1px 0; padding: 2px 8px; border-left: 3px solid #94a3b8; border-radius: 3px; font-family: "DejaVu Sans Mono", monospace, consolas, monaco; font-size: 12px; background: rgba(0,0,0,0.015); }
76478
- .YDEV_LOG_LVL { flex: 0 0 auto; text-transform: uppercase; font-size: 9px; font-weight: 700; letter-spacing: 0.04em; opacity: 0.8; min-width: 48px; }
76479
- .YDEV_LOG_TXT { flex: 1 1 auto; min-width: 0; white-space: pre-wrap; word-break: break-word; opacity: 0.9; }
76525
+ .YDEV_LOG_LVL { flex: 0 0 auto; text-transform: uppercase; font-size: 9px; font-weight: 700; letter-spacing: 0.04em; color: var(--ydev-dim); min-width: 48px; }
76526
+ .YDEV_LOG_TXT { flex: 1 1 auto; min-width: 0; white-space: pre-wrap; word-break: break-word; color: var(--ydev-ink); }
76480
76527
  .YDEV_LOG_error { border-left-color: #dc2626; } .YDEV_LOG_error .YDEV_LOG_LVL { color: #dc2626; }
76481
76528
  .YDEV_LOG_warning { border-left-color: #d97706; } .YDEV_LOG_warning .YDEV_LOG_LVL { color: #d97706; }
76482
76529
  .YDEV_LOG_info { border-left-color: #2563eb; } .YDEV_LOG_info .YDEV_LOG_LVL { color: #2563eb; }
76483
76530
  .YDEV_LOG_msg { border-left-color: #0891b2; } .YDEV_LOG_msg .YDEV_LOG_LVL { color: #0891b2; }
76484
- .YDEV_LOG_debug { border-left-color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_LVL { color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_TXT { opacity: 0.72; }
76485
- .YDEV_LOG_json { border-left-color: #9333ea; align-items: flex-start; } .YDEV_LOG_json .YDEV_LOG_LVL { color: #9333ea; } .YDEV_LOG_json .YDEV_LOG_TXT { font-size: 11px; line-height: 1.35; opacity: 0.8; }
76531
+ .YDEV_LOG_debug { border-left-color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_LVL { color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_TXT { color: var(--ydev-dim); }
76532
+ .YDEV_LOG_json { border-left-color: #9333ea; align-items: flex-start; } .YDEV_LOG_json .YDEV_LOG_LVL { color: #9333ea; } .YDEV_LOG_json .YDEV_LOG_TXT { font-size: 11px; line-height: 1.35; color: var(--ydev-dim); }
76486
76533
  /* -------- dark theme -------- */
76487
76534
  :root[data-theme="dark"] .TRAFFIC_FULL { background: rgba(255,255,255,0.05); }
76488
76535
  :root[data-theme="dark"] .YDEV_BAR, :root[data-theme="dark"] .YDEV_STATS { background: rgba(255,255,255,0.04); }
@@ -76497,7 +76544,7 @@ details.TRAFFIC_NEST > summary::-webkit-details-marker { display: none; }
76497
76544
  :root[data-theme="dark"] .dir-err .TRAFFIC_ARROW, :root[data-theme="dark"] .dir-err .TRAFFIC_EVENT { color: #f87171; }
76498
76545
  :root[data-theme="dark"] .YDEV_STAT.s-out { color: #60a5fa; } :root[data-theme="dark"] .YDEV_STAT.s-in { color: #34d399; } :root[data-theme="dark"] .YDEV_STAT.s-err { color: #f87171; }
76499
76546
  :root[data-theme="dark"] .YDEV_STAT.s-warn { color: #fbbf24; }
76500
- :root[data-theme="dark"] .TRAFFIC_VAL.t-num { color: #22d3ee; }
76547
+
76501
76548
  :root[data-theme="dark"] .TRAFFIC_VAL.t-bool, :root[data-theme="dark"] .TRAFFIC_VAL.t-null { color: #c084fc; }
76502
76549
  :root[data-theme="dark"] .YDEV_CHIP.is-active { background: rgba(96,165,250,0.2); border-color: #60a5fa; color: #93c5fd; }
76503
76550
  :root[data-theme="dark"] .YDEV_SEG_BTN.is-active { background: #2563eb; color: #fff; }
@@ -76571,24 +76618,65 @@ var PREVIEW_MAX_KEYS = 4;
76571
76618
  var PREVIEW_MAX_CHARS = 90;
76572
76619
  var PREVIEW_MAX_VALUE = 28;
76573
76620
  function preview_scalar(v) {
76574
- if (v === null) return "null";
76575
- if (typeof v === "string") return "\"" + (v.length > PREVIEW_MAX_VALUE ? v.slice(0, PREVIEW_MAX_VALUE) + "…" : v) + "\"";
76576
- if (typeof v === "object") return Array.isArray(v) ? "[…]" : "{…}";
76577
- return String(v);
76621
+ if (v === null) return {
76622
+ text: "null",
76623
+ cls: "t-null"
76624
+ };
76625
+ if (typeof v === "string") return {
76626
+ text: "\"" + (v.length > PREVIEW_MAX_VALUE ? v.slice(0, PREVIEW_MAX_VALUE) + "…" : v) + "\"",
76627
+ cls: "t-str"
76628
+ };
76629
+ if (typeof v === "object") return {
76630
+ text: Array.isArray(v) ? "[…]" : "{…}",
76631
+ cls: "t-empty"
76632
+ };
76633
+ if (typeof v === "boolean") return {
76634
+ text: String(v),
76635
+ cls: "t-bool"
76636
+ };
76637
+ return {
76638
+ text: String(v),
76639
+ cls: "t-num"
76640
+ };
76578
76641
  }
76579
- function object_preview(obj, count) {
76642
+ function object_preview_parts(obj, count) {
76580
76643
  let keys = Object.keys(obj);
76581
- let parts = [];
76644
+ let out = [{
76645
+ text: "{",
76646
+ cls: "p-punct"
76647
+ }];
76648
+ let fields = 0;
76582
76649
  let used = 0;
76583
76650
  for (let k of keys) {
76584
- if (parts.length >= PREVIEW_MAX_KEYS) break;
76585
- let part = k + ": " + preview_scalar(obj[k]);
76586
- if (parts.length > 0 && used + part.length > PREVIEW_MAX_CHARS) break;
76587
- parts.push(part);
76588
- used += part.length + 2;
76651
+ if (fields >= PREVIEW_MAX_KEYS) break;
76652
+ let val = preview_scalar(obj[k]);
76653
+ let width = k.length + 2 + val.text.length;
76654
+ if (fields > 0 && used + width > PREVIEW_MAX_CHARS) break;
76655
+ if (fields > 0) out.push({
76656
+ text: ", ",
76657
+ cls: "p-punct"
76658
+ });
76659
+ out.push({
76660
+ text: k,
76661
+ cls: "p-key"
76662
+ });
76663
+ out.push({
76664
+ text: ": ",
76665
+ cls: "p-punct"
76666
+ });
76667
+ out.push(val);
76668
+ fields++;
76669
+ used += width + 2;
76589
76670
  }
76590
- if (parts.length < count) parts.push("…");
76591
- return "{" + parts.join(", ") + "}";
76671
+ if (fields < count) out.push({
76672
+ text: fields > 0 ? ", …" : "…",
76673
+ cls: "p-punct"
76674
+ });
76675
+ out.push({
76676
+ text: "}",
76677
+ cls: "p-punct"
76678
+ });
76679
+ return out;
76592
76680
  }
76593
76681
  /************************************************************
76594
76682
  * One field of any type. Scalars → a bullet row; objects and
@@ -76620,7 +76708,15 @@ function traffic_value_node(key, value) {
76620
76708
  ]
76621
76709
  ]
76622
76710
  ];
76623
- let hint = is_arr ? `[${count}]` : object_preview(value, count);
76711
+ let hint = is_arr ? [[
76712
+ "span",
76713
+ { class: "TRAFFIC_NEST_HINT" },
76714
+ `[${count}]`
76715
+ ]] : object_preview_parts(value, count).map((t) => [
76716
+ "span",
76717
+ { class: "TRAFFIC_PREV " + t.cls },
76718
+ t.text
76719
+ ]);
76624
76720
  return [
76625
76721
  "details",
76626
76722
  { class: "TRAFFIC_NEST" },
@@ -76640,7 +76736,7 @@ function traffic_value_node(key, value) {
76640
76736
  ],
76641
76737
  [
76642
76738
  "span",
76643
- { class: "TRAFFIC_NEST_HINT" },
76739
+ { class: "TRAFFIC_NEST_HINT_WRAP" },
76644
76740
  hint
76645
76741
  ]
76646
76742
  ]
@@ -14018,6 +14018,7 @@ function mt_create$13(gobj) {
14018
14018
  * Framework Method: Start
14019
14019
  ***************************************************************/
14020
14020
  function mt_start$13(gobj) {
14021
+ if (gobj.priv.root !== null) gobj_change_state(gobj, "ST_READY");
14021
14022
  render_view$1(gobj);
14022
14023
  }
14023
14024
  /***************************************************************
@@ -76425,6 +76426,41 @@ function ensure_dev_style() {
76425
76426
  .YDEV_TITLE { display: flex; align-items: baseline; gap: 8px; }
76426
76427
  .YDEV_TITLE_MAIN { font-weight: 700; }
76427
76428
  .YDEV_TITLE_SUB { opacity: 0.7; font-size: 12px; }
76429
+ /* The ink of the log.
76430
+ *
76431
+ * It used to be one grey dimmed with opacity per role -- 0.85 for a key,
76432
+ * 0.5 for a preview, 0.45 for the source -- which is what washed the window
76433
+ * out: opacity blends text TOWARDS the background, so the more a line
76434
+ * mattered the less of it was left. Measured on the dark scheme the preview
76435
+ * came out at 4.39:1 and the source at 3.78:1, both under the 4.5 floor,
76436
+ * and everything that was legible was the same grey as everything else.
76437
+ *
76438
+ * Explicit colours now, one per ROLE and measured against the entry's own
76439
+ * background (#1b1e24 dark, #fafafa light): a key, a string, a number and a
76440
+ * boolean read apart from each other the way they do in a browser console,
76441
+ * which is the point of colouring a payload at all.
76442
+ * Ratios: dark 11.20 / 6.32 / 9.83 / 6.00 / 6.77 / 6.49 / 4.82,
76443
+ * light 7.38 / 7.52 / 5.16 / 8.35 / 5.59 / 7.21 / 4.35. */
76444
+ :root {
76445
+ --ydev-ink: #1f2937;
76446
+ --ydev-key: #0451a5;
76447
+ --ydev-str: #a31515;
76448
+ --ydev-num: #067a4e;
76449
+ --ydev-bool: #6b21a8;
76450
+ --ydev-dim: #5b6675;
76451
+ --ydev-src: #4a5568;
76452
+ --ydev-bullet: #6b7789;
76453
+ }
76454
+ :root[data-theme="dark"] {
76455
+ --ydev-ink: #e5e7eb;
76456
+ --ydev-key: #9cdcfe;
76457
+ --ydev-str: #ce9178;
76458
+ --ydev-num: #b5cea8;
76459
+ --ydev-bool: #c586c0;
76460
+ --ydev-dim: #9aa6b8;
76461
+ --ydev-src: #8fa3bf;
76462
+ --ydev-bullet: #7b8ba3;
76463
+ }
76428
76464
  /* -------- entries (shared) -------- */
76429
76465
  .TRAFFIC_ENTRY {
76430
76466
  border-left: 3px solid #94a3b8; border-radius: 3px;
@@ -76438,15 +76474,15 @@ function ensure_dev_style() {
76438
76474
  .TRAFFIC_HEADER { display: flex; align-items: baseline; gap: 8px; }
76439
76475
  .TRAFFIC_ARROW { font-weight: 700; }
76440
76476
  .TRAFFIC_EVENT { font-weight: 700; }
76441
- .TRAFFIC_CMD { opacity: 0.75; font-weight: 600; }
76477
+ .TRAFFIC_CMD { color: var(--ydev-dim); font-weight: 600; }
76442
76478
  /* Where the message went through. min-width 0 and flex 0 1 auto so it is the
76443
76479
  part that gives way when the row runs out of width -- the event name and
76444
76480
  the size/time must not be the ones to go. */
76445
- .TRAFFIC_SRC { opacity: 0.45; font-size: 11px; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
76481
+ .TRAFFIC_SRC { color: var(--ydev-src); font-size: 11px; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
76446
76482
  .dir-out .TRAFFIC_ARROW, .dir-out .TRAFFIC_EVENT { color: #2563eb; }
76447
76483
  .dir-in .TRAFFIC_ARROW, .dir-in .TRAFFIC_EVENT { color: #059669; }
76448
76484
  .dir-err .TRAFFIC_ARROW, .dir-err .TRAFFIC_EVENT { color: #dc2626; }
76449
- .TRAFFIC_META { margin-left: auto; opacity: 0.6; font-size: 11px; white-space: nowrap; }
76485
+ .TRAFFIC_META { margin-left: auto; color: var(--ydev-dim); font-size: 11px; white-space: nowrap; }
76450
76486
  /* The indent of a nested block is NOT a hover effect: it used to be given
76451
76487
  only on .TRAFFIC_ENTRY:hover, so moving the cursor across the log made
76452
76488
  every payload under it jump 16px sideways and reflow. A payload being
@@ -76455,29 +76491,40 @@ function ensure_dev_style() {
76455
76491
  .TRAFFIC_KW { margin: 2px 0 0 16px; }
76456
76492
  .TRAFFIC_FULL { margin: 4px 0 0 16px; padding: 6px 8px; font-family: monospace; font-size: 11px; line-height: 1.4; white-space: pre-wrap; word-break: break-word; background: rgba(0,0,0,0.04); border-radius: 4px; overflow-x: auto; }
76457
76493
  .TRAFFIC_ROW { display: flex; gap: 6px; align-items: baseline; }
76458
- .TRAFFIC_BULLET { opacity: 0.45; flex: 0 0 auto; }
76459
- .TRAFFIC_KEY { opacity: 0.85; flex: 0 0 auto; }
76460
- .TRAFFIC_VAL { word-break: break-word; }
76461
- .TRAFFIC_VAL.t-num { color: #0891b2; }
76462
- .TRAFFIC_VAL.t-bool { color: #9333ea; }
76463
- .TRAFFIC_VAL.t-null { color: #9333ea; font-style: italic; }
76464
- .TRAFFIC_VAL.t-empty { opacity: 0.5; }
76465
- .TRAFFIC_TS { opacity: 0.6; margin-left: 8px; }
76494
+ .TRAFFIC_BULLET { color: var(--ydev-bullet); flex: 0 0 auto; }
76495
+ .TRAFFIC_KEY { color: var(--ydev-key); flex: 0 0 auto; }
76496
+ .TRAFFIC_VAL { color: var(--ydev-ink); word-break: break-word; }
76497
+ .TRAFFIC_VAL.t-str { color: var(--ydev-str); }
76498
+ .TRAFFIC_VAL.t-num { color: var(--ydev-num); }
76499
+ .TRAFFIC_VAL.t-bool { color: var(--ydev-bool); }
76500
+ .TRAFFIC_VAL.t-null { color: var(--ydev-bool); font-style: italic; }
76501
+ .TRAFFIC_VAL.t-empty { color: var(--ydev-dim); }
76502
+ .TRAFFIC_TS { color: var(--ydev-dim); margin-left: 8px; }
76466
76503
  details.TRAFFIC_NEST > summary { cursor: pointer; list-style: none; display: flex; gap: 6px; align-items: baseline; }
76467
76504
  details.TRAFFIC_NEST > summary::-webkit-details-marker { display: none; }
76468
- .TRAFFIC_NEST_KEY { opacity: 0.85; }
76469
- .TRAFFIC_NEST_HINT { opacity: 0.5; margin-left: 4px; }
76470
- .YDEV_EMPTY { opacity: 0.5; font-size: 12px; padding: 18px 10px; text-align: center; }
76505
+ .TRAFFIC_NEST_KEY { color: var(--ydev-key); }
76506
+ .TRAFFIC_NEST_HINT { color: var(--ydev-dim); margin-left: 4px; }
76507
+ /* The folded preview, painted with the same ink as the expanded rows: a key
76508
+ is a key and a string is a string wherever it is read. */
76509
+ .TRAFFIC_NEST_HINT_WRAP { margin-left: 4px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
76510
+ .TRAFFIC_PREV.p-punct { color: var(--ydev-dim); }
76511
+ .TRAFFIC_PREV.p-key { color: var(--ydev-key); }
76512
+ .TRAFFIC_PREV.t-str { color: var(--ydev-str); }
76513
+ .TRAFFIC_PREV.t-num { color: var(--ydev-num); }
76514
+ .TRAFFIC_PREV.t-bool { color: var(--ydev-bool); }
76515
+ .TRAFFIC_PREV.t-null { color: var(--ydev-bool); font-style: italic; }
76516
+ .TRAFFIC_PREV.t-empty { color: var(--ydev-dim); }
76517
+ .YDEV_EMPTY { color: var(--ydev-dim); font-size: 12px; padding: 18px 10px; text-align: center; }
76471
76518
  /* -------- mirrored console logs (error/warning/info/debug/msg; the automata trace shows as debug) -------- */
76472
76519
  .YDEV_LOGROW { display: flex; align-items: baseline; gap: 8px; margin: 1px 0; padding: 2px 8px; border-left: 3px solid #94a3b8; border-radius: 3px; font-family: "DejaVu Sans Mono", monospace, consolas, monaco; font-size: 12px; background: rgba(0,0,0,0.015); }
76473
- .YDEV_LOG_LVL { flex: 0 0 auto; text-transform: uppercase; font-size: 9px; font-weight: 700; letter-spacing: 0.04em; opacity: 0.8; min-width: 48px; }
76474
- .YDEV_LOG_TXT { flex: 1 1 auto; min-width: 0; white-space: pre-wrap; word-break: break-word; opacity: 0.9; }
76520
+ .YDEV_LOG_LVL { flex: 0 0 auto; text-transform: uppercase; font-size: 9px; font-weight: 700; letter-spacing: 0.04em; color: var(--ydev-dim); min-width: 48px; }
76521
+ .YDEV_LOG_TXT { flex: 1 1 auto; min-width: 0; white-space: pre-wrap; word-break: break-word; color: var(--ydev-ink); }
76475
76522
  .YDEV_LOG_error { border-left-color: #dc2626; } .YDEV_LOG_error .YDEV_LOG_LVL { color: #dc2626; }
76476
76523
  .YDEV_LOG_warning { border-left-color: #d97706; } .YDEV_LOG_warning .YDEV_LOG_LVL { color: #d97706; }
76477
76524
  .YDEV_LOG_info { border-left-color: #2563eb; } .YDEV_LOG_info .YDEV_LOG_LVL { color: #2563eb; }
76478
76525
  .YDEV_LOG_msg { border-left-color: #0891b2; } .YDEV_LOG_msg .YDEV_LOG_LVL { color: #0891b2; }
76479
- .YDEV_LOG_debug { border-left-color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_LVL { color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_TXT { opacity: 0.72; }
76480
- .YDEV_LOG_json { border-left-color: #9333ea; align-items: flex-start; } .YDEV_LOG_json .YDEV_LOG_LVL { color: #9333ea; } .YDEV_LOG_json .YDEV_LOG_TXT { font-size: 11px; line-height: 1.35; opacity: 0.8; }
76526
+ .YDEV_LOG_debug { border-left-color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_LVL { color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_TXT { color: var(--ydev-dim); }
76527
+ .YDEV_LOG_json { border-left-color: #9333ea; align-items: flex-start; } .YDEV_LOG_json .YDEV_LOG_LVL { color: #9333ea; } .YDEV_LOG_json .YDEV_LOG_TXT { font-size: 11px; line-height: 1.35; color: var(--ydev-dim); }
76481
76528
  /* -------- dark theme -------- */
76482
76529
  :root[data-theme="dark"] .TRAFFIC_FULL { background: rgba(255,255,255,0.05); }
76483
76530
  :root[data-theme="dark"] .YDEV_BAR, :root[data-theme="dark"] .YDEV_STATS { background: rgba(255,255,255,0.04); }
@@ -76492,7 +76539,7 @@ details.TRAFFIC_NEST > summary::-webkit-details-marker { display: none; }
76492
76539
  :root[data-theme="dark"] .dir-err .TRAFFIC_ARROW, :root[data-theme="dark"] .dir-err .TRAFFIC_EVENT { color: #f87171; }
76493
76540
  :root[data-theme="dark"] .YDEV_STAT.s-out { color: #60a5fa; } :root[data-theme="dark"] .YDEV_STAT.s-in { color: #34d399; } :root[data-theme="dark"] .YDEV_STAT.s-err { color: #f87171; }
76494
76541
  :root[data-theme="dark"] .YDEV_STAT.s-warn { color: #fbbf24; }
76495
- :root[data-theme="dark"] .TRAFFIC_VAL.t-num { color: #22d3ee; }
76542
+
76496
76543
  :root[data-theme="dark"] .TRAFFIC_VAL.t-bool, :root[data-theme="dark"] .TRAFFIC_VAL.t-null { color: #c084fc; }
76497
76544
  :root[data-theme="dark"] .YDEV_CHIP.is-active { background: rgba(96,165,250,0.2); border-color: #60a5fa; color: #93c5fd; }
76498
76545
  :root[data-theme="dark"] .YDEV_SEG_BTN.is-active { background: #2563eb; color: #fff; }
@@ -76566,24 +76613,65 @@ var PREVIEW_MAX_KEYS = 4;
76566
76613
  var PREVIEW_MAX_CHARS = 90;
76567
76614
  var PREVIEW_MAX_VALUE = 28;
76568
76615
  function preview_scalar(v) {
76569
- if (v === null) return "null";
76570
- if (typeof v === "string") return "\"" + (v.length > PREVIEW_MAX_VALUE ? v.slice(0, PREVIEW_MAX_VALUE) + "…" : v) + "\"";
76571
- if (typeof v === "object") return Array.isArray(v) ? "[…]" : "{…}";
76572
- return String(v);
76616
+ if (v === null) return {
76617
+ text: "null",
76618
+ cls: "t-null"
76619
+ };
76620
+ if (typeof v === "string") return {
76621
+ text: "\"" + (v.length > PREVIEW_MAX_VALUE ? v.slice(0, PREVIEW_MAX_VALUE) + "…" : v) + "\"",
76622
+ cls: "t-str"
76623
+ };
76624
+ if (typeof v === "object") return {
76625
+ text: Array.isArray(v) ? "[…]" : "{…}",
76626
+ cls: "t-empty"
76627
+ };
76628
+ if (typeof v === "boolean") return {
76629
+ text: String(v),
76630
+ cls: "t-bool"
76631
+ };
76632
+ return {
76633
+ text: String(v),
76634
+ cls: "t-num"
76635
+ };
76573
76636
  }
76574
- function object_preview(obj, count) {
76637
+ function object_preview_parts(obj, count) {
76575
76638
  let keys = Object.keys(obj);
76576
- let parts = [];
76639
+ let out = [{
76640
+ text: "{",
76641
+ cls: "p-punct"
76642
+ }];
76643
+ let fields = 0;
76577
76644
  let used = 0;
76578
76645
  for (let k of keys) {
76579
- if (parts.length >= PREVIEW_MAX_KEYS) break;
76580
- let part = k + ": " + preview_scalar(obj[k]);
76581
- if (parts.length > 0 && used + part.length > PREVIEW_MAX_CHARS) break;
76582
- parts.push(part);
76583
- used += part.length + 2;
76646
+ if (fields >= PREVIEW_MAX_KEYS) break;
76647
+ let val = preview_scalar(obj[k]);
76648
+ let width = k.length + 2 + val.text.length;
76649
+ if (fields > 0 && used + width > PREVIEW_MAX_CHARS) break;
76650
+ if (fields > 0) out.push({
76651
+ text: ", ",
76652
+ cls: "p-punct"
76653
+ });
76654
+ out.push({
76655
+ text: k,
76656
+ cls: "p-key"
76657
+ });
76658
+ out.push({
76659
+ text: ": ",
76660
+ cls: "p-punct"
76661
+ });
76662
+ out.push(val);
76663
+ fields++;
76664
+ used += width + 2;
76584
76665
  }
76585
- if (parts.length < count) parts.push("…");
76586
- return "{" + parts.join(", ") + "}";
76666
+ if (fields < count) out.push({
76667
+ text: fields > 0 ? ", …" : "…",
76668
+ cls: "p-punct"
76669
+ });
76670
+ out.push({
76671
+ text: "}",
76672
+ cls: "p-punct"
76673
+ });
76674
+ return out;
76587
76675
  }
76588
76676
  /************************************************************
76589
76677
  * One field of any type. Scalars → a bullet row; objects and
@@ -76615,7 +76703,15 @@ function traffic_value_node(key, value) {
76615
76703
  ]
76616
76704
  ]
76617
76705
  ];
76618
- let hint = is_arr ? `[${count}]` : object_preview(value, count);
76706
+ let hint = is_arr ? [[
76707
+ "span",
76708
+ { class: "TRAFFIC_NEST_HINT" },
76709
+ `[${count}]`
76710
+ ]] : object_preview_parts(value, count).map((t) => [
76711
+ "span",
76712
+ { class: "TRAFFIC_PREV " + t.cls },
76713
+ t.text
76714
+ ]);
76619
76715
  return [
76620
76716
  "details",
76621
76717
  { class: "TRAFFIC_NEST" },
@@ -76635,7 +76731,7 @@ function traffic_value_node(key, value) {
76635
76731
  ],
76636
76732
  [
76637
76733
  "span",
76638
- { class: "TRAFFIC_NEST_HINT" },
76734
+ { class: "TRAFFIC_NEST_HINT_WRAP" },
76639
76735
  hint
76640
76736
  ]
76641
76737
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.23.179",
3
+ "version": "7.23.181",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
package/src/c_yui_json.js CHANGED
@@ -86,6 +86,7 @@ import {
86
86
  refresh_language,
87
87
  kw_get_local_storage_value,
88
88
  kw_set_local_storage_value,
89
+ gobj_change_state,
89
90
  } from "@yuneta/gobj-js";
90
91
 
91
92
  import {
@@ -244,6 +245,14 @@ function mt_create(gobj)
244
245
  ***************************************************************/
245
246
  function mt_start(gobj)
246
247
  {
248
+ let priv = gobj.priv;
249
+
250
+ /* The FSM starts in ST_EMPTY, and a viewer handed `json_data` at
251
+ * create is not empty: left there it rendered the tree and then
252
+ * answered every expand/collapse with "Event NOT DEFINED in state". */
253
+ if(priv.root !== null) {
254
+ gobj_change_state(gobj, "ST_READY");
255
+ }
247
256
  render_view(gobj);
248
257
  }
249
258
 
@@ -2567,9 +2567,6 @@ function open_schema_dialog(gobj)
2567
2567
  priv.schema_modal = presented.modal;
2568
2568
  priv.schema_win = presented.win;
2569
2569
 
2570
- /* EV_SET_JSON and not the `json_data` attr: the attr renders the
2571
- * tree but leaves the viewer in ST_IDLE, where a click to expand a
2572
- * node is an event nobody handles. */
2573
2570
  gobj_send_event(json_view, "EV_SET_JSON", {json: desc}, gobj);
2574
2571
  }
2575
2572
 
@@ -2697,9 +2694,6 @@ function open_cell_json_dialog(gobj, row_id, col_id)
2697
2694
  priv.cell_json_modal = presented.modal;
2698
2695
  priv.cell_json_win = presented.win;
2699
2696
 
2700
- /* EV_SET_JSON and not the `json_data` attr: the attr renders the
2701
- * tree but leaves the viewer in ST_IDLE, where a click to expand a
2702
- * node is an event nobody handles. */
2703
2697
  gobj_send_event(json_view, "EV_SET_JSON", {json: value}, gobj);
2704
2698
  }
2705
2699
 
package/src/yui_dev.js CHANGED
@@ -450,6 +450,41 @@ function ensure_dev_style()
450
450
  .YDEV_TITLE { display: flex; align-items: baseline; gap: 8px; }
451
451
  .YDEV_TITLE_MAIN { font-weight: 700; }
452
452
  .YDEV_TITLE_SUB { opacity: 0.7; font-size: 12px; }
453
+ /* The ink of the log.
454
+ *
455
+ * It used to be one grey dimmed with opacity per role -- 0.85 for a key,
456
+ * 0.5 for a preview, 0.45 for the source -- which is what washed the window
457
+ * out: opacity blends text TOWARDS the background, so the more a line
458
+ * mattered the less of it was left. Measured on the dark scheme the preview
459
+ * came out at 4.39:1 and the source at 3.78:1, both under the 4.5 floor,
460
+ * and everything that was legible was the same grey as everything else.
461
+ *
462
+ * Explicit colours now, one per ROLE and measured against the entry's own
463
+ * background (#1b1e24 dark, #fafafa light): a key, a string, a number and a
464
+ * boolean read apart from each other the way they do in a browser console,
465
+ * which is the point of colouring a payload at all.
466
+ * Ratios: dark 11.20 / 6.32 / 9.83 / 6.00 / 6.77 / 6.49 / 4.82,
467
+ * light 7.38 / 7.52 / 5.16 / 8.35 / 5.59 / 7.21 / 4.35. */
468
+ :root {
469
+ --ydev-ink: #1f2937;
470
+ --ydev-key: #0451a5;
471
+ --ydev-str: #a31515;
472
+ --ydev-num: #067a4e;
473
+ --ydev-bool: #6b21a8;
474
+ --ydev-dim: #5b6675;
475
+ --ydev-src: #4a5568;
476
+ --ydev-bullet: #6b7789;
477
+ }
478
+ :root[data-theme="dark"] {
479
+ --ydev-ink: #e5e7eb;
480
+ --ydev-key: #9cdcfe;
481
+ --ydev-str: #ce9178;
482
+ --ydev-num: #b5cea8;
483
+ --ydev-bool: #c586c0;
484
+ --ydev-dim: #9aa6b8;
485
+ --ydev-src: #8fa3bf;
486
+ --ydev-bullet: #7b8ba3;
487
+ }
453
488
  /* -------- entries (shared) -------- */
454
489
  .TRAFFIC_ENTRY {
455
490
  border-left: 3px solid #94a3b8; border-radius: 3px;
@@ -463,15 +498,15 @@ function ensure_dev_style()
463
498
  .TRAFFIC_HEADER { display: flex; align-items: baseline; gap: 8px; }
464
499
  .TRAFFIC_ARROW { font-weight: 700; }
465
500
  .TRAFFIC_EVENT { font-weight: 700; }
466
- .TRAFFIC_CMD { opacity: 0.75; font-weight: 600; }
501
+ .TRAFFIC_CMD { color: var(--ydev-dim); font-weight: 600; }
467
502
  /* Where the message went through. min-width 0 and flex 0 1 auto so it is the
468
503
  part that gives way when the row runs out of width -- the event name and
469
504
  the size/time must not be the ones to go. */
470
- .TRAFFIC_SRC { opacity: 0.45; font-size: 11px; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
505
+ .TRAFFIC_SRC { color: var(--ydev-src); font-size: 11px; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
471
506
  .dir-out .TRAFFIC_ARROW, .dir-out .TRAFFIC_EVENT { color: #2563eb; }
472
507
  .dir-in .TRAFFIC_ARROW, .dir-in .TRAFFIC_EVENT { color: #059669; }
473
508
  .dir-err .TRAFFIC_ARROW, .dir-err .TRAFFIC_EVENT { color: #dc2626; }
474
- .TRAFFIC_META { margin-left: auto; opacity: 0.6; font-size: 11px; white-space: nowrap; }
509
+ .TRAFFIC_META { margin-left: auto; color: var(--ydev-dim); font-size: 11px; white-space: nowrap; }
475
510
  /* The indent of a nested block is NOT a hover effect: it used to be given
476
511
  only on .TRAFFIC_ENTRY:hover, so moving the cursor across the log made
477
512
  every payload under it jump 16px sideways and reflow. A payload being
@@ -480,29 +515,40 @@ function ensure_dev_style()
480
515
  .TRAFFIC_KW { margin: 2px 0 0 16px; }
481
516
  .TRAFFIC_FULL { margin: 4px 0 0 16px; padding: 6px 8px; font-family: monospace; font-size: 11px; line-height: 1.4; white-space: pre-wrap; word-break: break-word; background: rgba(0,0,0,0.04); border-radius: 4px; overflow-x: auto; }
482
517
  .TRAFFIC_ROW { display: flex; gap: 6px; align-items: baseline; }
483
- .TRAFFIC_BULLET { opacity: 0.45; flex: 0 0 auto; }
484
- .TRAFFIC_KEY { opacity: 0.85; flex: 0 0 auto; }
485
- .TRAFFIC_VAL { word-break: break-word; }
486
- .TRAFFIC_VAL.t-num { color: #0891b2; }
487
- .TRAFFIC_VAL.t-bool { color: #9333ea; }
488
- .TRAFFIC_VAL.t-null { color: #9333ea; font-style: italic; }
489
- .TRAFFIC_VAL.t-empty { opacity: 0.5; }
490
- .TRAFFIC_TS { opacity: 0.6; margin-left: 8px; }
518
+ .TRAFFIC_BULLET { color: var(--ydev-bullet); flex: 0 0 auto; }
519
+ .TRAFFIC_KEY { color: var(--ydev-key); flex: 0 0 auto; }
520
+ .TRAFFIC_VAL { color: var(--ydev-ink); word-break: break-word; }
521
+ .TRAFFIC_VAL.t-str { color: var(--ydev-str); }
522
+ .TRAFFIC_VAL.t-num { color: var(--ydev-num); }
523
+ .TRAFFIC_VAL.t-bool { color: var(--ydev-bool); }
524
+ .TRAFFIC_VAL.t-null { color: var(--ydev-bool); font-style: italic; }
525
+ .TRAFFIC_VAL.t-empty { color: var(--ydev-dim); }
526
+ .TRAFFIC_TS { color: var(--ydev-dim); margin-left: 8px; }
491
527
  details.TRAFFIC_NEST > summary { cursor: pointer; list-style: none; display: flex; gap: 6px; align-items: baseline; }
492
528
  details.TRAFFIC_NEST > summary::-webkit-details-marker { display: none; }
493
- .TRAFFIC_NEST_KEY { opacity: 0.85; }
494
- .TRAFFIC_NEST_HINT { opacity: 0.5; margin-left: 4px; }
495
- .YDEV_EMPTY { opacity: 0.5; font-size: 12px; padding: 18px 10px; text-align: center; }
529
+ .TRAFFIC_NEST_KEY { color: var(--ydev-key); }
530
+ .TRAFFIC_NEST_HINT { color: var(--ydev-dim); margin-left: 4px; }
531
+ /* The folded preview, painted with the same ink as the expanded rows: a key
532
+ is a key and a string is a string wherever it is read. */
533
+ .TRAFFIC_NEST_HINT_WRAP { margin-left: 4px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
534
+ .TRAFFIC_PREV.p-punct { color: var(--ydev-dim); }
535
+ .TRAFFIC_PREV.p-key { color: var(--ydev-key); }
536
+ .TRAFFIC_PREV.t-str { color: var(--ydev-str); }
537
+ .TRAFFIC_PREV.t-num { color: var(--ydev-num); }
538
+ .TRAFFIC_PREV.t-bool { color: var(--ydev-bool); }
539
+ .TRAFFIC_PREV.t-null { color: var(--ydev-bool); font-style: italic; }
540
+ .TRAFFIC_PREV.t-empty { color: var(--ydev-dim); }
541
+ .YDEV_EMPTY { color: var(--ydev-dim); font-size: 12px; padding: 18px 10px; text-align: center; }
496
542
  /* -------- mirrored console logs (error/warning/info/debug/msg; the automata trace shows as debug) -------- */
497
543
  .YDEV_LOGROW { display: flex; align-items: baseline; gap: 8px; margin: 1px 0; padding: 2px 8px; border-left: 3px solid #94a3b8; border-radius: 3px; font-family: "DejaVu Sans Mono", monospace, consolas, monaco; font-size: 12px; background: rgba(0,0,0,0.015); }
498
- .YDEV_LOG_LVL { flex: 0 0 auto; text-transform: uppercase; font-size: 9px; font-weight: 700; letter-spacing: 0.04em; opacity: 0.8; min-width: 48px; }
499
- .YDEV_LOG_TXT { flex: 1 1 auto; min-width: 0; white-space: pre-wrap; word-break: break-word; opacity: 0.9; }
544
+ .YDEV_LOG_LVL { flex: 0 0 auto; text-transform: uppercase; font-size: 9px; font-weight: 700; letter-spacing: 0.04em; color: var(--ydev-dim); min-width: 48px; }
545
+ .YDEV_LOG_TXT { flex: 1 1 auto; min-width: 0; white-space: pre-wrap; word-break: break-word; color: var(--ydev-ink); }
500
546
  .YDEV_LOG_error { border-left-color: #dc2626; } .YDEV_LOG_error .YDEV_LOG_LVL { color: #dc2626; }
501
547
  .YDEV_LOG_warning { border-left-color: #d97706; } .YDEV_LOG_warning .YDEV_LOG_LVL { color: #d97706; }
502
548
  .YDEV_LOG_info { border-left-color: #2563eb; } .YDEV_LOG_info .YDEV_LOG_LVL { color: #2563eb; }
503
549
  .YDEV_LOG_msg { border-left-color: #0891b2; } .YDEV_LOG_msg .YDEV_LOG_LVL { color: #0891b2; }
504
- .YDEV_LOG_debug { border-left-color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_LVL { color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_TXT { opacity: 0.72; }
505
- .YDEV_LOG_json { border-left-color: #9333ea; align-items: flex-start; } .YDEV_LOG_json .YDEV_LOG_LVL { color: #9333ea; } .YDEV_LOG_json .YDEV_LOG_TXT { font-size: 11px; line-height: 1.35; opacity: 0.8; }
550
+ .YDEV_LOG_debug { border-left-color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_LVL { color: #94a3b8; } .YDEV_LOG_debug .YDEV_LOG_TXT { color: var(--ydev-dim); }
551
+ .YDEV_LOG_json { border-left-color: #9333ea; align-items: flex-start; } .YDEV_LOG_json .YDEV_LOG_LVL { color: #9333ea; } .YDEV_LOG_json .YDEV_LOG_TXT { font-size: 11px; line-height: 1.35; color: var(--ydev-dim); }
506
552
  /* -------- dark theme -------- */
507
553
  :root[data-theme="dark"] .TRAFFIC_FULL { background: rgba(255,255,255,0.05); }
508
554
  :root[data-theme="dark"] .YDEV_BAR, :root[data-theme="dark"] .YDEV_STATS { background: rgba(255,255,255,0.04); }
@@ -517,7 +563,7 @@ details.TRAFFIC_NEST > summary::-webkit-details-marker { display: none; }
517
563
  :root[data-theme="dark"] .dir-err .TRAFFIC_ARROW, :root[data-theme="dark"] .dir-err .TRAFFIC_EVENT { color: #f87171; }
518
564
  :root[data-theme="dark"] .YDEV_STAT.s-out { color: #60a5fa; } :root[data-theme="dark"] .YDEV_STAT.s-in { color: #34d399; } :root[data-theme="dark"] .YDEV_STAT.s-err { color: #f87171; }
519
565
  :root[data-theme="dark"] .YDEV_STAT.s-warn { color: #fbbf24; }
520
- :root[data-theme="dark"] .TRAFFIC_VAL.t-num { color: #22d3ee; }
566
+
521
567
  :root[data-theme="dark"] .TRAFFIC_VAL.t-bool, :root[data-theme="dark"] .TRAFFIC_VAL.t-null { color: #c084fc; }
522
568
  :root[data-theme="dark"] .YDEV_CHIP.is-active { background: rgba(96,165,250,0.2); border-color: #60a5fa; color: #93c5fd; }
523
569
  :root[data-theme="dark"] .YDEV_SEG_BTN.is-active { background: #2563eb; color: #fff; }
@@ -603,44 +649,66 @@ const PREVIEW_MAX_VALUE = 28;
603
649
  function preview_scalar(v)
604
650
  {
605
651
  if(v === null) {
606
- return "null";
652
+ return {text: "null", cls: "t-null"};
607
653
  }
608
654
  if(typeof v === "string") {
609
655
  let text = (v.length > PREVIEW_MAX_VALUE) ?
610
656
  v.slice(0, PREVIEW_MAX_VALUE) + "…" : v;
611
- return '"' + text + '"';
657
+ return {text: '"' + text + '"', cls: "t-str"};
612
658
  }
613
659
  if(typeof v === "object") {
614
- return Array.isArray(v) ? "[…]" : "{…}";
660
+ return {text: Array.isArray(v) ? "[…]" : "{…}", cls: "t-empty"};
615
661
  }
616
- return String(v);
662
+ if(typeof v === "boolean") {
663
+ return {text: String(v), cls: "t-bool"};
664
+ }
665
+ return {text: String(v), cls: "t-num"};
617
666
  }
618
667
 
619
- function object_preview(obj, count)
668
+ /* The preview as TOKENS, so the renderer can paint a key, a string and a
669
+ number the way the expanded rows paint them. A preview in one flat grey
670
+ is the thing this window was asked to stop doing. */
671
+ function object_preview_parts(obj, count)
620
672
  {
621
673
  let keys = Object.keys(obj);
622
- let parts = [];
674
+ let out = [{text: "{", cls: "p-punct"}];
675
+ let fields = 0;
623
676
  let used = 0;
624
677
 
625
678
  for(let k of keys) {
626
- if(parts.length >= PREVIEW_MAX_KEYS) {
679
+ if(fields >= PREVIEW_MAX_KEYS) {
627
680
  break;
628
681
  }
629
- let part = k + ": " + preview_scalar(obj[k]);
682
+ let val = preview_scalar(obj[k]);
683
+ let width = k.length + 2 + val.text.length;
630
684
  /* Stop at the width, but never with an empty preview: one field
631
685
  too wide still says more than a number. */
632
- if(parts.length > 0 && used + part.length > PREVIEW_MAX_CHARS) {
686
+ if(fields > 0 && used + width > PREVIEW_MAX_CHARS) {
633
687
  break;
634
688
  }
635
- parts.push(part);
636
- used += part.length + 2;
689
+ if(fields > 0) {
690
+ out.push({text: ", ", cls: "p-punct"});
691
+ }
692
+ out.push({text: k, cls: "p-key"});
693
+ out.push({text: ": ", cls: "p-punct"});
694
+ out.push(val);
695
+ fields++;
696
+ used += width + 2;
637
697
  }
638
698
 
639
- if(parts.length < count) {
640
- parts.push("…");
699
+ if(fields < count) {
700
+ out.push({text: fields > 0 ? ", …" : "…", cls: "p-punct"});
641
701
  }
702
+ out.push({text: "}", cls: "p-punct"});
642
703
 
643
- return "{" + parts.join(", ") + "}";
704
+ return out;
705
+ }
706
+
707
+ /* The same preview as one string. What the tests assert on, and what any
708
+ caller wanting a plain line would use. */
709
+ function object_preview(obj, count)
710
+ {
711
+ return object_preview_parts(obj, count).map((t) => t.text).join("");
644
712
  }
645
713
 
646
714
  /************************************************************
@@ -664,12 +732,16 @@ function traffic_value_node(key, value)
664
732
  ]];
665
733
  }
666
734
 
667
- let hint = is_arr ? `[${count}]` : object_preview(value, count);
735
+ let hint = is_arr ?
736
+ [['span', {class: 'TRAFFIC_NEST_HINT'}, `[${count}]`]] :
737
+ object_preview_parts(value, count).map(
738
+ (t) => ['span', {class: 'TRAFFIC_PREV ' + t.cls}, t.text]
739
+ );
668
740
  return ['details', {class: 'TRAFFIC_NEST'}, [
669
741
  ['summary', {}, [
670
742
  ['span', {class: 'TRAFFIC_BULLET'}, '▸'],
671
743
  ['span', {class: 'TRAFFIC_NEST_KEY'}, key],
672
- ['span', {class: 'TRAFFIC_NEST_HINT'}, hint],
744
+ ['span', {class: 'TRAFFIC_NEST_HINT_WRAP'}, hint],
673
745
  ]],
674
746
  ['div', {class: 'TRAFFIC_KW'}, traffic_bullets(value)],
675
747
  ]];
@@ -1787,5 +1859,5 @@ export {
1787
1859
  guards this file from a syntax error nothing else would catch --
1788
1860
  the stylesheet below is a template literal, so one backtick in a CSS
1789
1861
  comment stops the whole module from parsing. */
1790
- object_preview,
1862
+ object_preview, object_preview_parts,
1791
1863
  };
@@ -13,7 +13,7 @@
13
13
  * All Rights Reserved.
14
14
  ***********************************************************************/
15
15
  import {describe, it, expect} from "vitest";
16
- import {object_preview} from "./yui_dev.js";
16
+ import {object_preview, object_preview_parts} from "./yui_dev.js";
17
17
 
18
18
  describe("object_preview", () => {
19
19
  it("names the first fields instead of counting them", () => {
@@ -56,3 +56,23 @@ describe("object_preview", () => {
56
56
  expect(object_preview({a: null, b: true}, 2)).toBe("{a: null, b: true}");
57
57
  });
58
58
  });
59
+
60
+ describe("object_preview_parts", () => {
61
+ it("gives every token the class its ink is chosen by", () => {
62
+ const parts = object_preview_parts({a: "s", b: 1, c: true, d: null}, 4);
63
+ const seen = parts.filter((t) => t.cls !== "p-punct")
64
+ .map((t) => [t.text, t.cls]);
65
+ expect(seen).toEqual([
66
+ ["a", "p-key"], ['"s"', "t-str"],
67
+ ["b", "p-key"], ["1", "t-num"],
68
+ ["c", "p-key"], ["true", "t-bool"],
69
+ ["d", "p-key"], ["null", "t-null"],
70
+ ]);
71
+ });
72
+
73
+ it("joins back into exactly what object_preview says", () => {
74
+ const o = {header: "id", fillspace: 18, flag: ["x"], hidden: false, more: 1};
75
+ const joined = object_preview_parts(o, 5).map((t) => t.text).join("");
76
+ expect(joined).toBe(object_preview(o, 5));
77
+ });
78
+ });