@yuneta/gobj-ui 7.23.186 → 7.23.187

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.
@@ -23714,7 +23714,7 @@ function build_ui$6(gobj) {
23714
23714
  [[
23715
23715
  "span",
23716
23716
  { class: "icon" },
23717
- [yui_toolbar_icon("yi-hexagon-nodes")]
23717
+ [yui_toolbar_icon("yi-compass-drafting")]
23718
23718
  ], [
23719
23719
  "span",
23720
23720
  { i18n: "schema" },
@@ -23725,6 +23725,29 @@ function build_ui$6(gobj) {
23725
23725
  (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_TOGGLE_LANDING_VIEW", {}, gobj);
23726
23726
  } }
23727
23727
  ],
23728
+ [
23729
+ "button",
23730
+ {
23731
+ class: "button TREEDB_SCHEMA_JSON_BTN is-hidden",
23732
+ title: (0, i18next.t)("schema json"),
23733
+ "aria-label": (0, i18next.t)("schema json"),
23734
+ "data-i18n-title": "schema json",
23735
+ "data-i18n-aria-label": "schema json"
23736
+ },
23737
+ [[
23738
+ "span",
23739
+ { class: "icon" },
23740
+ [yui_toolbar_icon("yi-code")]
23741
+ ], [
23742
+ "span",
23743
+ { i18n: "schema json" },
23744
+ "schema json"
23745
+ ]],
23746
+ { click: (evt) => {
23747
+ evt.stopPropagation();
23748
+ (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_OPEN_SCHEMA_JSON", {}, gobj);
23749
+ } }
23750
+ ],
23728
23751
  [
23729
23752
  "div",
23730
23753
  {
@@ -24168,6 +24191,7 @@ function show_topics_landing(gobj) {
24168
24191
  let $info = $container.querySelector(".TREEDB_TOPIC_INFO");
24169
24192
  let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
24170
24193
  let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
24194
+ let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
24171
24195
  if ($tabs) $tabs.classList.add("is-hidden");
24172
24196
  if ($sub) $sub.classList.add("is-hidden");
24173
24197
  if ($info) $info.classList.add("is-hidden");
@@ -24177,6 +24201,7 @@ function show_topics_landing(gobj) {
24177
24201
  $toggle.classList.remove("is-hidden");
24178
24202
  $toggle.classList.toggle("is-primary", schema_mode);
24179
24203
  }
24204
+ if ($schema_json) $schema_json.classList.toggle("is-hidden", !schema_mode);
24180
24205
  if (schema_mode) {
24181
24206
  if ($landing) $landing.classList.add("is-hidden");
24182
24207
  if ($schema) $schema.classList.remove("is-hidden");
@@ -24246,9 +24271,11 @@ function show_topic_detail(gobj) {
24246
24271
  let $info = $container.querySelector(".TREEDB_TOPIC_INFO");
24247
24272
  let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
24248
24273
  let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
24274
+ let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
24249
24275
  if ($landing) $landing.classList.add("is-hidden");
24250
24276
  if ($schema) $schema.classList.add("is-hidden");
24251
24277
  if ($info) $info.classList.add("is-hidden");
24278
+ if ($schema_json) $schema_json.classList.add("is-hidden");
24252
24279
  if ($toggle) $toggle.classList.add("is-hidden");
24253
24280
  if ($tabs) $tabs.classList.remove("is-hidden");
24254
24281
  if ($sub) $sub.classList.remove("is-hidden");
@@ -24289,8 +24316,10 @@ function show_topic_info(gobj, topic) {
24289
24316
  let $schema = $container.querySelector(".TREEDB_TOPICS_SCHEMA");
24290
24317
  let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
24291
24318
  let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
24319
+ let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
24292
24320
  if ($landing) $landing.classList.add("is-hidden");
24293
24321
  if ($schema) $schema.classList.add("is-hidden");
24322
+ if ($schema_json) $schema_json.classList.add("is-hidden");
24294
24323
  if ($toggle) $toggle.classList.add("is-hidden");
24295
24324
  if ($tabs) $tabs.classList.add("is-hidden");
24296
24325
  if ($sub) $sub.classList.add("is-hidden");
@@ -24565,7 +24594,7 @@ function register_sub_routes$1(gobj) {
24565
24594
  if ((0, _yuneta_gobj_js.is_object)((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "landing_routes"))) nodes.push({
24566
24595
  route: base + "/schema",
24567
24596
  label: "schema",
24568
- icon: "yi-hexagon-nodes",
24597
+ icon: "yi-compass-drafting",
24569
24598
  gclass: "C_YUI_TREEDB_SCHEMA"
24570
24599
  });
24571
24600
  if ((0, _yuneta_gobj_js.is_object)(descs)) for (let topic of Object.keys(descs)) {
@@ -24708,10 +24737,11 @@ function is_mobile$2() {
24708
24737
  * whole service (lazy drill). CHILD model: the viewer publishes
24709
24738
  * EV_EXPAND_PATH to us.
24710
24739
  ************************************************************/
24711
- function open_json_viewer$1(gobj) {
24740
+ function open_json_viewer$1(gobj, opts) {
24712
24741
  let priv = gobj.priv;
24742
+ let schema = !!(opts && opts.schema);
24713
24743
  if (priv.json_win || priv.json_modal) {
24714
- request_print_tranger$1(gobj, "");
24744
+ if (!schema) request_print_tranger$1(gobj, "");
24715
24745
  return;
24716
24746
  }
24717
24747
  if (!(0, _yuneta_gobj_js.gclass_find_by_name)("C_YUI_JSON")) {
@@ -24721,7 +24751,10 @@ function open_json_viewer$1(gobj) {
24721
24751
  }
24722
24752
  let mobile = is_mobile$2();
24723
24753
  let shell = yui_shell_of(gobj);
24724
- let jv = (0, _yuneta_gobj_js.gobj_create_service)(`treedb-topics-json-${(0, _yuneta_gobj_js.clean_name)((0, _yuneta_gobj_js.gobj_name)(gobj))}`, "C_YUI_JSON", { subscriber: gobj }, gobj);
24754
+ let jv = (0, _yuneta_gobj_js.gobj_create_service)(`treedb-topics-json-${(0, _yuneta_gobj_js.clean_name)((0, _yuneta_gobj_js.gobj_name)(gobj))}`, "C_YUI_JSON", {
24755
+ subscriber: gobj,
24756
+ json_data: schema ? (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "descs") : null
24757
+ }, gobj);
24725
24758
  if (!jv) {
24726
24759
  (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot create the JSON viewer`);
24727
24760
  return;
@@ -24739,7 +24772,7 @@ function open_json_viewer$1(gobj) {
24739
24772
  dialog: true,
24740
24773
  logical_class: "TREEDB_JSON_SHEET",
24741
24774
  title_prefix: priv.treedb_name,
24742
- title: "raw json",
24775
+ title: schema ? "schema json" : "raw json",
24743
24776
  t: i18next.t,
24744
24777
  on_close: () => {
24745
24778
  if ((0, _yuneta_gobj_js.gobj_is_destroying)(gobj)) return;
@@ -24761,8 +24794,8 @@ function open_json_viewer$1(gobj) {
24761
24794
  height: 620,
24762
24795
  logical_class: "TREEDB_JSON_WINDOW",
24763
24796
  title_prefix: priv.treedb_name,
24764
- title: "raw json",
24765
- icon: "yi-eye",
24797
+ title: schema ? "schema json" : "raw json",
24798
+ icon: schema ? "yi-code" : "yi-eye",
24766
24799
  body: $box,
24767
24800
  manager: null,
24768
24801
  on_close: () => {
@@ -24777,7 +24810,7 @@ function open_json_viewer$1(gobj) {
24777
24810
  }
24778
24811
  (0, _yuneta_gobj_js.gobj_start)(priv.json_win);
24779
24812
  }
24780
- request_print_tranger$1(gobj, "");
24813
+ if (!schema) request_print_tranger$1(gobj, "");
24781
24814
  }
24782
24815
  /************************************************************
24783
24816
  * Close the JSON viewer (user dismiss / teardown).
@@ -25371,6 +25404,19 @@ function ac_open_json$1(gobj, event, kw, src) {
25371
25404
  return 0;
25372
25405
  }
25373
25406
  /********************************************
25407
+ * The schema, as the json it is: the `descs` the schema graph is
25408
+ * drawing. Same viewer and same host as the tranger's raw json --
25409
+ * one at a time, so it closes whatever was open first.
25410
+ ********************************************/
25411
+ function ac_open_schema_json(gobj, event, kw, src) {
25412
+ if (!(0, _yuneta_gobj_js.is_object)((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "descs"))) {
25413
+ (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: schema json with no descs`);
25414
+ return -1;
25415
+ }
25416
+ open_json_viewer$1(gobj, { schema: true });
25417
+ return 0;
25418
+ }
25419
+ /********************************************
25374
25420
  * Open the graph where the reader left it: its last visited
25375
25421
  * route under the graph's base -- `<graph>/<topic>` when a topic
25376
25422
  * was focused there -- or the bare base when the graph was never
@@ -25504,6 +25550,11 @@ function create_gclass$6(gclass_name) {
25504
25550
  ac_open_json$1,
25505
25551
  null
25506
25552
  ],
25553
+ [
25554
+ "EV_OPEN_SCHEMA_JSON",
25555
+ ac_open_schema_json,
25556
+ null
25557
+ ],
25507
25558
  [
25508
25559
  "EV_OPEN_GRAPH",
25509
25560
  ac_open_graph,
@@ -25576,6 +25627,7 @@ function create_gclass$6(gclass_name) {
25576
25627
  ["EV_RECORD_WRITTEN", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT | _yuneta_gobj_js.event_flag_t.EVF_NO_WARN_SUBS],
25577
25628
  ["EV_REFRESH_TOPIC", 0],
25578
25629
  ["EV_OPEN_JSON", 0],
25630
+ ["EV_OPEN_SCHEMA_JSON", 0],
25579
25631
  ["EV_OPEN_GRAPH", 0],
25580
25632
  ["EV_EXPAND_PATH", 0],
25581
25633
  ["EV_JSON_CLOSED", 0],
@@ -58820,7 +58872,7 @@ function build_graph$1(gobj) {
58820
58872
  container: priv.$container,
58821
58873
  animation: false,
58822
58874
  autoResize: false,
58823
- zoomRange: [.2, 4],
58875
+ zoomRange: [.02, 4],
58824
58876
  node: {
58825
58877
  palette: {
58826
58878
  type: "group",
@@ -60076,6 +60128,7 @@ function draw_link(gobj, child_topic, child_id, source_col, fkey, verbose) {
60076
60128
  parent_topic,
60077
60129
  parent_id,
60078
60130
  hook_name,
60131
+ child_topic,
60079
60132
  child_id,
60080
60133
  is_tree
60081
60134
  });
@@ -60582,7 +60635,7 @@ async function graph_fit_selection(gobj, ids) {
60582
60635
  let bw = Math.max(1, maxx - minx);
60583
60636
  let bh = Math.max(1, maxy - miny);
60584
60637
  let zoom = Math.min(vw / bw, vh / bh);
60585
- let range = graph.getZoomRange() || [.2, 4];
60638
+ let range = graph.getZoomRange() || [.02, 4];
60586
60639
  zoom = Math.max(range[0], Math.min(range[1], zoom));
60587
60640
  await graph.zoomTo(zoom);
60588
60641
  await graph.focusElement(ids);
@@ -63319,16 +63372,14 @@ function refresh_html_nodes_theme(gobj, theme) {
63319
63372
  function refresh_default_edges_theme(gobj, theme) {
63320
63373
  let graph = gobj.priv.graph;
63321
63374
  if (!graph) return;
63322
- let dark = theme === "dark";
63323
63375
  let edges = graph.getData().edges || [];
63324
63376
  let updates = [];
63325
63377
  for (let i = 0; i < edges.length; i++) {
63326
63378
  let d = edges[i].data || {};
63327
63379
  if (!d.themed_default) continue;
63328
- let stroke = d.is_tree ? dark ? "#22a7c2" : "#0e7490" : dark ? "#8b94a3" : "#6b7280";
63329
63380
  updates.push({
63330
63381
  id: edges[i].id,
63331
- style: { stroke }
63382
+ style: { stroke: default_edge_stroke(gobj, d, theme) }
63332
63383
  });
63333
63384
  }
63334
63385
  if (updates.length > 0) graph.updateEdgeData(updates);
@@ -63900,21 +63951,54 @@ function apply_edge_properties(gobj, edge_id, lineWidth, stroke, scope) {
63900
63951
  deselect_edge(gobj);
63901
63952
  }
63902
63953
  /************************************************************
63954
+ * The colour a link is DRAWN in: the colour of the two knobs it
63955
+ * joins.
63956
+ *
63957
+ * Both ends of a link wear the CHILD topic's colour -- the
63958
+ * parent's hook port is painted with the colour of whatever may
63959
+ * hang there, and the child's fkey port with its own (see
63960
+ * build_ports) -- so the line between them has one obvious
63961
+ * colour, and a reader follows a link by its hue instead of
63962
+ * tracing a grey thread across the canvas.
63963
+ *
63964
+ * It goes through port_rim(): the FILL of a port says which
63965
+ * topic, and a line on the canvas is a graphical object that
63966
+ * needs 3:1 against it, which that mix clears in both themes
63967
+ * (9.11 dark, 3.80 light) while keeping the hue. So a link is
63968
+ * drawn in exactly the colour of the rim of the two knobs it
63969
+ * ends on.
63970
+ *
63971
+ * The containment/tree relation (parent and child of the same
63972
+ * topic) is no longer marked by a teal of its own -- it is that
63973
+ * topic's colour like any other link, and what still tells it
63974
+ * apart is its WIDTH.
63975
+ *
63976
+ * A topic with no colour, or an edge of a graph with no schema
63977
+ * yet, keeps the neutral grey this used to give everything.
63978
+ ************************************************************/
63979
+ function default_edge_stroke(gobj, d, theme) {
63980
+ let priv = gobj.priv;
63981
+ let desc = (0, _yuneta_gobj_js.is_object)(priv.descs) ? priv.descs[d.child_topic] : null;
63982
+ if (desc && desc.color) return port_rim(desc.color, theme);
63983
+ let dark = theme === "dark";
63984
+ return d.is_tree ? dark ? "#22a7c2" : "#0e7490" : dark ? "#8b94a3" : "#6b7280";
63985
+ }
63986
+ /************************************************************
63903
63987
  * The style an edge INHERITS, before anything saved for the
63904
63988
  * edge itself: its hook's default in the parent topic, else the
63905
63989
  * parent topic's default for every edge, else the library's.
63906
63990
  *
63907
- * The library's: neutral grey, teal for the containment/tree
63908
- * relation (parent and child of the same topic, a
63909
- * self-hierarchy). `themed_default` says the colour is still the
63910
- * library's, so a theme toggle re-themes it and leaves a chosen
63911
- * one alone.
63991
+ * The library's: the colour of the ports it joins (see
63992
+ * default_edge_stroke), and a wider line for the
63993
+ * containment/tree relation. `themed_default` says the colour is
63994
+ * still the library's, so a theme toggle re-themes it and leaves
63995
+ * a chosen one alone.
63912
63996
  ************************************************************/
63913
63997
  function edge_inherited_style_of(gobj, d) {
63914
- let dark = gobj.priv.theme === "dark";
63998
+ let priv = gobj.priv;
63915
63999
  let style = {
63916
64000
  lineWidth: d.is_tree ? 2 : 1.6,
63917
- stroke: d.is_tree ? dark ? "#22a7c2" : "#0e7490" : dark ? "#8b94a3" : "#6b7280",
64001
+ stroke: default_edge_stroke(gobj, d, priv.theme),
63918
64002
  themed_default: true
63919
64003
  };
63920
64004
  let defs = topic_defaults_of(gobj, d.parent_topic);
@@ -71735,7 +71819,7 @@ function render_toolbar(gobj) {
71735
71819
  ]);
71736
71820
  let $right = [];
71737
71821
  if (priv.treedb_id && has_model) {
71738
- $right.push(toolbar_button("SCHEMA_DIAGRAM_BTN", "yi-hexagon-nodes", priv.diagram ? "topics" : "diagram", "EV_TOGGLE_DIAGRAM", false));
71822
+ $right.push(toolbar_button("SCHEMA_DIAGRAM_BTN", "yi-compass-drafting", priv.diagram ? "topics" : "diagram", "EV_TOGGLE_DIAGRAM", false));
71739
71823
  $right.push(toolbar_button("SCHEMA_VALIDATE_BTN", "yi-square-check", "check", "EV_VALIDATE", false));
71740
71824
  $right.push(toolbar_button("SCHEMA_EXPORT_BTN", "yi-download", "export", "EV_EXPORT", false));
71741
71825
  if (!readonly) $right.push(toolbar_button("SCHEMA_IMPORT_BTN", "yi-upload", "import", "EV_IMPORT", false));
@@ -23709,7 +23709,7 @@ function build_ui$6(gobj) {
23709
23709
  [[
23710
23710
  "span",
23711
23711
  { class: "icon" },
23712
- [yui_toolbar_icon("yi-hexagon-nodes")]
23712
+ [yui_toolbar_icon("yi-compass-drafting")]
23713
23713
  ], [
23714
23714
  "span",
23715
23715
  { i18n: "schema" },
@@ -23720,6 +23720,29 @@ function build_ui$6(gobj) {
23720
23720
  gobj_send_event(gobj, "EV_TOGGLE_LANDING_VIEW", {}, gobj);
23721
23721
  } }
23722
23722
  ],
23723
+ [
23724
+ "button",
23725
+ {
23726
+ class: "button TREEDB_SCHEMA_JSON_BTN is-hidden",
23727
+ title: t("schema json"),
23728
+ "aria-label": t("schema json"),
23729
+ "data-i18n-title": "schema json",
23730
+ "data-i18n-aria-label": "schema json"
23731
+ },
23732
+ [[
23733
+ "span",
23734
+ { class: "icon" },
23735
+ [yui_toolbar_icon("yi-code")]
23736
+ ], [
23737
+ "span",
23738
+ { i18n: "schema json" },
23739
+ "schema json"
23740
+ ]],
23741
+ { click: (evt) => {
23742
+ evt.stopPropagation();
23743
+ gobj_send_event(gobj, "EV_OPEN_SCHEMA_JSON", {}, gobj);
23744
+ } }
23745
+ ],
23723
23746
  [
23724
23747
  "div",
23725
23748
  {
@@ -24163,6 +24186,7 @@ function show_topics_landing(gobj) {
24163
24186
  let $info = $container.querySelector(".TREEDB_TOPIC_INFO");
24164
24187
  let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
24165
24188
  let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
24189
+ let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
24166
24190
  if ($tabs) $tabs.classList.add("is-hidden");
24167
24191
  if ($sub) $sub.classList.add("is-hidden");
24168
24192
  if ($info) $info.classList.add("is-hidden");
@@ -24172,6 +24196,7 @@ function show_topics_landing(gobj) {
24172
24196
  $toggle.classList.remove("is-hidden");
24173
24197
  $toggle.classList.toggle("is-primary", schema_mode);
24174
24198
  }
24199
+ if ($schema_json) $schema_json.classList.toggle("is-hidden", !schema_mode);
24175
24200
  if (schema_mode) {
24176
24201
  if ($landing) $landing.classList.add("is-hidden");
24177
24202
  if ($schema) $schema.classList.remove("is-hidden");
@@ -24241,9 +24266,11 @@ function show_topic_detail(gobj) {
24241
24266
  let $info = $container.querySelector(".TREEDB_TOPIC_INFO");
24242
24267
  let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
24243
24268
  let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
24269
+ let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
24244
24270
  if ($landing) $landing.classList.add("is-hidden");
24245
24271
  if ($schema) $schema.classList.add("is-hidden");
24246
24272
  if ($info) $info.classList.add("is-hidden");
24273
+ if ($schema_json) $schema_json.classList.add("is-hidden");
24247
24274
  if ($toggle) $toggle.classList.add("is-hidden");
24248
24275
  if ($tabs) $tabs.classList.remove("is-hidden");
24249
24276
  if ($sub) $sub.classList.remove("is-hidden");
@@ -24284,8 +24311,10 @@ function show_topic_info(gobj, topic) {
24284
24311
  let $schema = $container.querySelector(".TREEDB_TOPICS_SCHEMA");
24285
24312
  let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
24286
24313
  let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
24314
+ let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
24287
24315
  if ($landing) $landing.classList.add("is-hidden");
24288
24316
  if ($schema) $schema.classList.add("is-hidden");
24317
+ if ($schema_json) $schema_json.classList.add("is-hidden");
24289
24318
  if ($toggle) $toggle.classList.add("is-hidden");
24290
24319
  if ($tabs) $tabs.classList.add("is-hidden");
24291
24320
  if ($sub) $sub.classList.add("is-hidden");
@@ -24560,7 +24589,7 @@ function register_sub_routes$1(gobj) {
24560
24589
  if (is_object(gobj_read_attr(gobj, "landing_routes"))) nodes.push({
24561
24590
  route: base + "/schema",
24562
24591
  label: "schema",
24563
- icon: "yi-hexagon-nodes",
24592
+ icon: "yi-compass-drafting",
24564
24593
  gclass: "C_YUI_TREEDB_SCHEMA"
24565
24594
  });
24566
24595
  if (is_object(descs)) for (let topic of Object.keys(descs)) {
@@ -24703,10 +24732,11 @@ function is_mobile$2() {
24703
24732
  * whole service (lazy drill). CHILD model: the viewer publishes
24704
24733
  * EV_EXPAND_PATH to us.
24705
24734
  ************************************************************/
24706
- function open_json_viewer$1(gobj) {
24735
+ function open_json_viewer$1(gobj, opts) {
24707
24736
  let priv = gobj.priv;
24737
+ let schema = !!(opts && opts.schema);
24708
24738
  if (priv.json_win || priv.json_modal) {
24709
- request_print_tranger$1(gobj, "");
24739
+ if (!schema) request_print_tranger$1(gobj, "");
24710
24740
  return;
24711
24741
  }
24712
24742
  if (!gclass_find_by_name("C_YUI_JSON")) {
@@ -24716,7 +24746,10 @@ function open_json_viewer$1(gobj) {
24716
24746
  }
24717
24747
  let mobile = is_mobile$2();
24718
24748
  let shell = yui_shell_of(gobj);
24719
- let jv = gobj_create_service(`treedb-topics-json-${clean_name(gobj_name(gobj))}`, "C_YUI_JSON", { subscriber: gobj }, gobj);
24749
+ let jv = gobj_create_service(`treedb-topics-json-${clean_name(gobj_name(gobj))}`, "C_YUI_JSON", {
24750
+ subscriber: gobj,
24751
+ json_data: schema ? gobj_read_attr(gobj, "descs") : null
24752
+ }, gobj);
24720
24753
  if (!jv) {
24721
24754
  log_error(`${gobj_short_name(gobj)}: cannot create the JSON viewer`);
24722
24755
  return;
@@ -24734,7 +24767,7 @@ function open_json_viewer$1(gobj) {
24734
24767
  dialog: true,
24735
24768
  logical_class: "TREEDB_JSON_SHEET",
24736
24769
  title_prefix: priv.treedb_name,
24737
- title: "raw json",
24770
+ title: schema ? "schema json" : "raw json",
24738
24771
  t,
24739
24772
  on_close: () => {
24740
24773
  if (gobj_is_destroying(gobj)) return;
@@ -24756,8 +24789,8 @@ function open_json_viewer$1(gobj) {
24756
24789
  height: 620,
24757
24790
  logical_class: "TREEDB_JSON_WINDOW",
24758
24791
  title_prefix: priv.treedb_name,
24759
- title: "raw json",
24760
- icon: "yi-eye",
24792
+ title: schema ? "schema json" : "raw json",
24793
+ icon: schema ? "yi-code" : "yi-eye",
24761
24794
  body: $box,
24762
24795
  manager: null,
24763
24796
  on_close: () => {
@@ -24772,7 +24805,7 @@ function open_json_viewer$1(gobj) {
24772
24805
  }
24773
24806
  gobj_start(priv.json_win);
24774
24807
  }
24775
- request_print_tranger$1(gobj, "");
24808
+ if (!schema) request_print_tranger$1(gobj, "");
24776
24809
  }
24777
24810
  /************************************************************
24778
24811
  * Close the JSON viewer (user dismiss / teardown).
@@ -25366,6 +25399,19 @@ function ac_open_json$1(gobj, event, kw, src) {
25366
25399
  return 0;
25367
25400
  }
25368
25401
  /********************************************
25402
+ * The schema, as the json it is: the `descs` the schema graph is
25403
+ * drawing. Same viewer and same host as the tranger's raw json --
25404
+ * one at a time, so it closes whatever was open first.
25405
+ ********************************************/
25406
+ function ac_open_schema_json(gobj, event, kw, src) {
25407
+ if (!is_object(gobj_read_attr(gobj, "descs"))) {
25408
+ log_error(`${gobj_short_name(gobj)}: schema json with no descs`);
25409
+ return -1;
25410
+ }
25411
+ open_json_viewer$1(gobj, { schema: true });
25412
+ return 0;
25413
+ }
25414
+ /********************************************
25369
25415
  * Open the graph where the reader left it: its last visited
25370
25416
  * route under the graph's base -- `<graph>/<topic>` when a topic
25371
25417
  * was focused there -- or the bare base when the graph was never
@@ -25499,6 +25545,11 @@ function create_gclass$6(gclass_name) {
25499
25545
  ac_open_json$1,
25500
25546
  null
25501
25547
  ],
25548
+ [
25549
+ "EV_OPEN_SCHEMA_JSON",
25550
+ ac_open_schema_json,
25551
+ null
25552
+ ],
25502
25553
  [
25503
25554
  "EV_OPEN_GRAPH",
25504
25555
  ac_open_graph,
@@ -25571,6 +25622,7 @@ function create_gclass$6(gclass_name) {
25571
25622
  ["EV_RECORD_WRITTEN", event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
25572
25623
  ["EV_REFRESH_TOPIC", 0],
25573
25624
  ["EV_OPEN_JSON", 0],
25625
+ ["EV_OPEN_SCHEMA_JSON", 0],
25574
25626
  ["EV_OPEN_GRAPH", 0],
25575
25627
  ["EV_EXPAND_PATH", 0],
25576
25628
  ["EV_JSON_CLOSED", 0],
@@ -58815,7 +58867,7 @@ function build_graph$1(gobj) {
58815
58867
  container: priv.$container,
58816
58868
  animation: false,
58817
58869
  autoResize: false,
58818
- zoomRange: [.2, 4],
58870
+ zoomRange: [.02, 4],
58819
58871
  node: {
58820
58872
  palette: {
58821
58873
  type: "group",
@@ -60071,6 +60123,7 @@ function draw_link(gobj, child_topic, child_id, source_col, fkey, verbose) {
60071
60123
  parent_topic,
60072
60124
  parent_id,
60073
60125
  hook_name,
60126
+ child_topic,
60074
60127
  child_id,
60075
60128
  is_tree
60076
60129
  });
@@ -60577,7 +60630,7 @@ async function graph_fit_selection(gobj, ids) {
60577
60630
  let bw = Math.max(1, maxx - minx);
60578
60631
  let bh = Math.max(1, maxy - miny);
60579
60632
  let zoom = Math.min(vw / bw, vh / bh);
60580
- let range = graph.getZoomRange() || [.2, 4];
60633
+ let range = graph.getZoomRange() || [.02, 4];
60581
60634
  zoom = Math.max(range[0], Math.min(range[1], zoom));
60582
60635
  await graph.zoomTo(zoom);
60583
60636
  await graph.focusElement(ids);
@@ -63314,16 +63367,14 @@ function refresh_html_nodes_theme(gobj, theme) {
63314
63367
  function refresh_default_edges_theme(gobj, theme) {
63315
63368
  let graph = gobj.priv.graph;
63316
63369
  if (!graph) return;
63317
- let dark = theme === "dark";
63318
63370
  let edges = graph.getData().edges || [];
63319
63371
  let updates = [];
63320
63372
  for (let i = 0; i < edges.length; i++) {
63321
63373
  let d = edges[i].data || {};
63322
63374
  if (!d.themed_default) continue;
63323
- let stroke = d.is_tree ? dark ? "#22a7c2" : "#0e7490" : dark ? "#8b94a3" : "#6b7280";
63324
63375
  updates.push({
63325
63376
  id: edges[i].id,
63326
- style: { stroke }
63377
+ style: { stroke: default_edge_stroke(gobj, d, theme) }
63327
63378
  });
63328
63379
  }
63329
63380
  if (updates.length > 0) graph.updateEdgeData(updates);
@@ -63895,21 +63946,54 @@ function apply_edge_properties(gobj, edge_id, lineWidth, stroke, scope) {
63895
63946
  deselect_edge(gobj);
63896
63947
  }
63897
63948
  /************************************************************
63949
+ * The colour a link is DRAWN in: the colour of the two knobs it
63950
+ * joins.
63951
+ *
63952
+ * Both ends of a link wear the CHILD topic's colour -- the
63953
+ * parent's hook port is painted with the colour of whatever may
63954
+ * hang there, and the child's fkey port with its own (see
63955
+ * build_ports) -- so the line between them has one obvious
63956
+ * colour, and a reader follows a link by its hue instead of
63957
+ * tracing a grey thread across the canvas.
63958
+ *
63959
+ * It goes through port_rim(): the FILL of a port says which
63960
+ * topic, and a line on the canvas is a graphical object that
63961
+ * needs 3:1 against it, which that mix clears in both themes
63962
+ * (9.11 dark, 3.80 light) while keeping the hue. So a link is
63963
+ * drawn in exactly the colour of the rim of the two knobs it
63964
+ * ends on.
63965
+ *
63966
+ * The containment/tree relation (parent and child of the same
63967
+ * topic) is no longer marked by a teal of its own -- it is that
63968
+ * topic's colour like any other link, and what still tells it
63969
+ * apart is its WIDTH.
63970
+ *
63971
+ * A topic with no colour, or an edge of a graph with no schema
63972
+ * yet, keeps the neutral grey this used to give everything.
63973
+ ************************************************************/
63974
+ function default_edge_stroke(gobj, d, theme) {
63975
+ let priv = gobj.priv;
63976
+ let desc = is_object(priv.descs) ? priv.descs[d.child_topic] : null;
63977
+ if (desc && desc.color) return port_rim(desc.color, theme);
63978
+ let dark = theme === "dark";
63979
+ return d.is_tree ? dark ? "#22a7c2" : "#0e7490" : dark ? "#8b94a3" : "#6b7280";
63980
+ }
63981
+ /************************************************************
63898
63982
  * The style an edge INHERITS, before anything saved for the
63899
63983
  * edge itself: its hook's default in the parent topic, else the
63900
63984
  * parent topic's default for every edge, else the library's.
63901
63985
  *
63902
- * The library's: neutral grey, teal for the containment/tree
63903
- * relation (parent and child of the same topic, a
63904
- * self-hierarchy). `themed_default` says the colour is still the
63905
- * library's, so a theme toggle re-themes it and leaves a chosen
63906
- * one alone.
63986
+ * The library's: the colour of the ports it joins (see
63987
+ * default_edge_stroke), and a wider line for the
63988
+ * containment/tree relation. `themed_default` says the colour is
63989
+ * still the library's, so a theme toggle re-themes it and leaves
63990
+ * a chosen one alone.
63907
63991
  ************************************************************/
63908
63992
  function edge_inherited_style_of(gobj, d) {
63909
- let dark = gobj.priv.theme === "dark";
63993
+ let priv = gobj.priv;
63910
63994
  let style = {
63911
63995
  lineWidth: d.is_tree ? 2 : 1.6,
63912
- stroke: d.is_tree ? dark ? "#22a7c2" : "#0e7490" : dark ? "#8b94a3" : "#6b7280",
63996
+ stroke: default_edge_stroke(gobj, d, priv.theme),
63913
63997
  themed_default: true
63914
63998
  };
63915
63999
  let defs = topic_defaults_of(gobj, d.parent_topic);
@@ -71730,7 +71814,7 @@ function render_toolbar(gobj) {
71730
71814
  ]);
71731
71815
  let $right = [];
71732
71816
  if (priv.treedb_id && has_model) {
71733
- $right.push(toolbar_button("SCHEMA_DIAGRAM_BTN", "yi-hexagon-nodes", priv.diagram ? "topics" : "diagram", "EV_TOGGLE_DIAGRAM", false));
71817
+ $right.push(toolbar_button("SCHEMA_DIAGRAM_BTN", "yi-compass-drafting", priv.diagram ? "topics" : "diagram", "EV_TOGGLE_DIAGRAM", false));
71734
71818
  $right.push(toolbar_button("SCHEMA_VALIDATE_BTN", "yi-square-check", "check", "EV_VALIDATE", false));
71735
71819
  $right.push(toolbar_button("SCHEMA_EXPORT_BTN", "yi-download", "export", "EV_EXPORT", false));
71736
71820
  if (!readonly) $right.push(toolbar_button("SCHEMA_IMPORT_BTN", "yi-upload", "import", "EV_IMPORT", false));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.23.186",
3
+ "version": "7.23.187",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
@@ -967,7 +967,12 @@ function build_graph(gobj)
967
967
  container: priv.$container,
968
968
  animation: false,
969
969
  autoResize: false,
970
- zoomRange: [0.2, 4],
970
+ /* The floor was 0.2, and a treedb of a few hundred records does
971
+ * not fit in a screen at 20%: the reader could see the shape of
972
+ * the whole thing in the minimap and never on the canvas. Fit
973
+ * still stops at a legible zoom on purpose (graph_fit_readable);
974
+ * zooming out by hand is the reader's business. */
975
+ zoomRange: [0.02, 4],
971
976
  node: { // WARNING this affect to all nodes with prevalence over individual defines!
972
977
  palette: {
973
978
  type: 'group',
@@ -2938,6 +2943,7 @@ function draw_link(
2938
2943
  parent_topic: parent_topic,
2939
2944
  parent_id: parent_id,
2940
2945
  hook_name: hook_name,
2946
+ child_topic: child_topic,
2941
2947
  child_id: child_id,
2942
2948
  is_tree: is_tree,
2943
2949
  });
@@ -3718,7 +3724,7 @@ async function graph_fit_selection(gobj, ids)
3718
3724
  let bh = Math.max(1, maxy - miny);
3719
3725
 
3720
3726
  let zoom = Math.min(vw / bw, vh / bh);
3721
- let range = graph.getZoomRange() || [0.2, 4];
3727
+ let range = graph.getZoomRange() || [0.02, 4];
3722
3728
  zoom = Math.max(range[0], Math.min(range[1], zoom));
3723
3729
 
3724
3730
  await graph.zoomTo(zoom);
@@ -7795,7 +7801,6 @@ function refresh_default_edges_theme(gobj, theme)
7795
7801
  if(!graph) {
7796
7802
  return;
7797
7803
  }
7798
- let dark = (theme === "dark");
7799
7804
  let edges = graph.getData().edges || [];
7800
7805
  let updates = [];
7801
7806
  for(let i = 0; i < edges.length; i++) {
@@ -7803,10 +7808,7 @@ function refresh_default_edges_theme(gobj, theme)
7803
7808
  if(!d.themed_default) {
7804
7809
  continue;
7805
7810
  }
7806
- let stroke = d.is_tree
7807
- ? (dark ? '#22a7c2' : '#0e7490')
7808
- : (dark ? '#8b94a3' : '#6b7280');
7809
- updates.push({ id: edges[i].id, style: { stroke: stroke } });
7811
+ updates.push({id: edges[i].id, style: {stroke: default_edge_stroke(gobj, d, theme)}});
7810
7812
  }
7811
7813
  if(updates.length > 0) {
7812
7814
  graph.updateEdgeData(updates);
@@ -8688,26 +8690,60 @@ function apply_edge_properties(gobj, edge_id, lineWidth, stroke, scope)
8688
8690
  deselect_edge(gobj);
8689
8691
  }
8690
8692
 
8693
+ /************************************************************
8694
+ * The colour a link is DRAWN in: the colour of the two knobs it
8695
+ * joins.
8696
+ *
8697
+ * Both ends of a link wear the CHILD topic's colour -- the
8698
+ * parent's hook port is painted with the colour of whatever may
8699
+ * hang there, and the child's fkey port with its own (see
8700
+ * build_ports) -- so the line between them has one obvious
8701
+ * colour, and a reader follows a link by its hue instead of
8702
+ * tracing a grey thread across the canvas.
8703
+ *
8704
+ * It goes through port_rim(): the FILL of a port says which
8705
+ * topic, and a line on the canvas is a graphical object that
8706
+ * needs 3:1 against it, which that mix clears in both themes
8707
+ * (9.11 dark, 3.80 light) while keeping the hue. So a link is
8708
+ * drawn in exactly the colour of the rim of the two knobs it
8709
+ * ends on.
8710
+ *
8711
+ * The containment/tree relation (parent and child of the same
8712
+ * topic) is no longer marked by a teal of its own -- it is that
8713
+ * topic's colour like any other link, and what still tells it
8714
+ * apart is its WIDTH.
8715
+ *
8716
+ * A topic with no colour, or an edge of a graph with no schema
8717
+ * yet, keeps the neutral grey this used to give everything.
8718
+ ************************************************************/
8719
+ function default_edge_stroke(gobj, d, theme)
8720
+ {
8721
+ let priv = gobj.priv;
8722
+ let desc = is_object(priv.descs)? priv.descs[d.child_topic] : null;
8723
+ if(desc && desc.color) {
8724
+ return port_rim(desc.color, theme);
8725
+ }
8726
+ let dark = (theme === "dark");
8727
+ return d.is_tree? (dark? '#22a7c2' : '#0e7490') : (dark? '#8b94a3' : '#6b7280');
8728
+ }
8729
+
8691
8730
  /************************************************************
8692
8731
  * The style an edge INHERITS, before anything saved for the
8693
8732
  * edge itself: its hook's default in the parent topic, else the
8694
8733
  * parent topic's default for every edge, else the library's.
8695
8734
  *
8696
- * The library's: neutral grey, teal for the containment/tree
8697
- * relation (parent and child of the same topic, a
8698
- * self-hierarchy). `themed_default` says the colour is still the
8699
- * library's, so a theme toggle re-themes it and leaves a chosen
8700
- * one alone.
8735
+ * The library's: the colour of the ports it joins (see
8736
+ * default_edge_stroke), and a wider line for the
8737
+ * containment/tree relation. `themed_default` says the colour is
8738
+ * still the library's, so a theme toggle re-themes it and leaves
8739
+ * a chosen one alone.
8701
8740
  ************************************************************/
8702
8741
  function edge_inherited_style_of(gobj, d)
8703
8742
  {
8704
8743
  let priv = gobj.priv;
8705
- let dark = (priv.theme === "dark");
8706
8744
  let style = {
8707
8745
  lineWidth: d.is_tree ? 2 : 1.6,
8708
- stroke: d.is_tree
8709
- ? (dark ? '#22a7c2' : '#0e7490')
8710
- : (dark ? '#8b94a3' : '#6b7280'),
8746
+ stroke: default_edge_stroke(gobj, d, priv.theme),
8711
8747
  themed_default: true,
8712
8748
  };
8713
8749
 
@@ -810,7 +810,9 @@ function render_toolbar(gobj)
810
810
  *----------------------------------------------*/
811
811
  let $right = [];
812
812
  if(priv.treedb_id && has_model) {
813
- $right.push(toolbar_button("SCHEMA_DIAGRAM_BTN", "yi-hexagon-nodes",
813
+ /* The compass, like every other door to a SCHEMA: the
814
+ * `hexagon-nodes` it wore is the graph of the DATA. */
815
+ $right.push(toolbar_button("SCHEMA_DIAGRAM_BTN", "yi-compass-drafting",
814
816
  priv.diagram ? "topics" : "diagram", "EV_TOGGLE_DIAGRAM", false));
815
817
  $right.push(toolbar_button("SCHEMA_VALIDATE_BTN", "yi-square-check",
816
818
  "check", "EV_VALIDATE", false));
@@ -335,12 +335,19 @@ function build_ui(gobj)
335
335
  }
336
336
  }],
337
337
  /* Landing view toggle: cards grid <-> schema graph
338
- * (topics as nodes). Shown only on the landing. */
338
+ * (topics as nodes). Shown only on the landing.
339
+ *
340
+ * The glyph is the draughtsman's compass, not the
341
+ * `hexagon-nodes` of the graph: the button one place
342
+ * to its left opens the graph of the DATA, and the
343
+ * two wore the same shape with only their labels
344
+ * telling them apart -- which on a narrow toolbar is
345
+ * nothing. A schema is the PLAN of the treedb. */
339
346
  ['button', {class: 'button TREEDB_LANDING_TOGGLE is-hidden',
340
347
  title: t('schema graph'), 'aria-label': t('schema graph'),
341
348
  'data-i18n-title': 'schema graph',
342
349
  'data-i18n-aria-label': 'schema graph'}, [
343
- ['span', {class: 'icon'}, [yui_toolbar_icon('yi-hexagon-nodes')]],
350
+ ['span', {class: 'icon'}, [yui_toolbar_icon('yi-compass-drafting')]],
344
351
  ['span', {i18n: 'schema'}, 'schema']
345
352
  ], {
346
353
  click: (evt) => {
@@ -348,6 +355,24 @@ function build_ui(gobj)
348
355
  gobj_send_event(gobj, "EV_TOGGLE_LANDING_VIEW", {}, gobj);
349
356
  }
350
357
  }],
358
+ /* The schema as JSON -- the `descs` the view is drawing,
359
+ * which is what a person writing a schema literal, or
360
+ * chasing a flag that did not take, actually needs to
361
+ * read. Landing-only, like the toggle it stands next
362
+ * to; the `raw json` button further right is another
363
+ * thing entirely (the tranger's content). */
364
+ ['button', {class: 'button TREEDB_SCHEMA_JSON_BTN is-hidden',
365
+ title: t('schema json'), 'aria-label': t('schema json'),
366
+ 'data-i18n-title': 'schema json',
367
+ 'data-i18n-aria-label': 'schema json'}, [
368
+ ['span', {class: 'icon'}, [yui_toolbar_icon('yi-code')]],
369
+ ['span', {i18n: 'schema json'}, 'schema json']
370
+ ], {
371
+ click: (evt) => {
372
+ evt.stopPropagation();
373
+ gobj_send_event(gobj, "EV_OPEN_SCHEMA_JSON", {}, gobj);
374
+ }
375
+ }],
351
376
  /* The backend this view browses. The tab that hosts this
352
377
  * view is labelled with the TREEDB name, and the same
353
378
  * treedb name lives on more than one node — two tabs
@@ -817,6 +842,7 @@ function show_topics_landing(gobj)
817
842
  let $info = $container.querySelector(".TREEDB_TOPIC_INFO");
818
843
  let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
819
844
  let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
845
+ let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
820
846
  if($tabs) {
821
847
  $tabs.classList.add("is-hidden");
822
848
  }
@@ -835,6 +861,11 @@ function show_topics_landing(gobj)
835
861
  $toggle.classList.remove("is-hidden"); /* the toggle lives on the landing */
836
862
  $toggle.classList.toggle("is-primary", schema_mode);
837
863
  }
864
+ if($schema_json) {
865
+ /* The schema's json is worth reading when the schema is what is
866
+ * on screen; on the cards grid it is one more button in the way. */
867
+ $schema_json.classList.toggle("is-hidden", !schema_mode);
868
+ }
838
869
  if(schema_mode) {
839
870
  if($landing) {
840
871
  $landing.classList.add("is-hidden");
@@ -946,6 +977,7 @@ function show_topic_detail(gobj)
946
977
  let $info = $container.querySelector(".TREEDB_TOPIC_INFO");
947
978
  let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
948
979
  let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
980
+ let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
949
981
  if($landing) {
950
982
  $landing.classList.add("is-hidden");
951
983
  }
@@ -955,6 +987,9 @@ function show_topic_detail(gobj)
955
987
  if($info) {
956
988
  $info.classList.add("is-hidden");
957
989
  }
990
+ if($schema_json) {
991
+ $schema_json.classList.add("is-hidden");
992
+ }
958
993
  if($toggle) {
959
994
  $toggle.classList.add("is-hidden"); /* landing-only */
960
995
  }
@@ -1010,12 +1045,16 @@ function show_topic_info(gobj, topic)
1010
1045
  let $schema = $container.querySelector(".TREEDB_TOPICS_SCHEMA");
1011
1046
  let $back = $container.querySelector(".TREEDB_TOPICS_BACK");
1012
1047
  let $toggle = $container.querySelector(".TREEDB_LANDING_TOGGLE");
1048
+ let $schema_json = $container.querySelector(".TREEDB_SCHEMA_JSON_BTN");
1013
1049
  if($landing) {
1014
1050
  $landing.classList.add("is-hidden");
1015
1051
  }
1016
1052
  if($schema) {
1017
1053
  $schema.classList.add("is-hidden");
1018
1054
  }
1055
+ if($schema_json) {
1056
+ $schema_json.classList.add("is-hidden");
1057
+ }
1019
1058
  if($toggle) {
1020
1059
  $toggle.classList.add("is-hidden");
1021
1060
  }
@@ -1307,7 +1346,7 @@ function register_sub_routes(gobj)
1307
1346
  let nodes = [];
1308
1347
  if(is_object(gobj_read_attr(gobj, "landing_routes"))) {
1309
1348
  nodes.push({route: base + "/schema", label: "schema",
1310
- icon: "yi-hexagon-nodes", gclass: "C_YUI_TREEDB_SCHEMA"});
1349
+ icon: "yi-compass-drafting", gclass: "C_YUI_TREEDB_SCHEMA"});
1311
1350
  }
1312
1351
  if(is_object(descs)) {
1313
1352
  for(let topic of Object.keys(descs)) {
@@ -1655,13 +1694,18 @@ function is_mobile()
1655
1694
  * whole service (lazy drill). CHILD model: the viewer publishes
1656
1695
  * EV_EXPAND_PATH to us.
1657
1696
  ************************************************************/
1658
- function open_json_viewer(gobj)
1697
+ function open_json_viewer(gobj, opts)
1659
1698
  {
1660
1699
  let priv = gobj.priv;
1700
+ let schema = !!(opts && opts.schema);
1661
1701
 
1662
- /* Already open: just re-fetch. */
1702
+ /* Already open: just re-fetch. The schema needs no fetch -- it is
1703
+ * the `descs` this view already holds -- so a second click on a
1704
+ * viewer that is already showing it does nothing. */
1663
1705
  if(priv.json_win || priv.json_modal) {
1664
- request_print_tranger(gobj, "");
1706
+ if(!schema) {
1707
+ request_print_tranger(gobj, "");
1708
+ }
1665
1709
  return;
1666
1710
  }
1667
1711
 
@@ -1681,7 +1725,11 @@ function open_json_viewer(gobj)
1681
1725
  /* No `title`: the host titles it — the window's title bar on
1682
1726
  * desktop, the dialog's header on mobile. The viewer's own
1683
1727
  * title would land INSIDE that host, doubling it. */
1684
- subscriber: gobj /* publishes EV_EXPAND_PATH to us */
1728
+ subscriber: gobj, /* publishes EV_EXPAND_PATH to us */
1729
+ /* The schema is here already and it is small: it goes in
1730
+ * whole, and no drill-down happens because nothing is
1731
+ * collapsed. */
1732
+ json_data: schema? gobj_read_attr(gobj, "descs") : null
1685
1733
  },
1686
1734
  gobj
1687
1735
  );
@@ -1703,7 +1751,7 @@ function open_json_viewer(gobj)
1703
1751
  dialog: true,
1704
1752
  logical_class: "TREEDB_JSON_SHEET",
1705
1753
  title_prefix: priv.treedb_name,
1706
- title: "raw json",
1754
+ title: schema? "schema json" : "raw json",
1707
1755
  t: t,
1708
1756
  on_close: () => {
1709
1757
  if(gobj_is_destroying(gobj)) {
@@ -1733,8 +1781,8 @@ function open_json_viewer(gobj)
1733
1781
  height: 620,
1734
1782
  logical_class: "TREEDB_JSON_WINDOW",
1735
1783
  title_prefix: priv.treedb_name,
1736
- title: "raw json",
1737
- icon: "yi-eye",
1784
+ title: schema? "schema json" : "raw json",
1785
+ icon: schema? "yi-code" : "yi-eye",
1738
1786
  body: $box,
1739
1787
  manager: null,
1740
1788
  on_close: () => {
@@ -1754,7 +1802,9 @@ function open_json_viewer(gobj)
1754
1802
  gobj_start(priv.json_win);
1755
1803
  }
1756
1804
 
1757
- request_print_tranger(gobj, "");
1805
+ if(!schema) {
1806
+ request_print_tranger(gobj, "");
1807
+ }
1758
1808
  }
1759
1809
 
1760
1810
  /************************************************************
@@ -2718,6 +2768,24 @@ function ac_open_json(gobj, event, kw, src)
2718
2768
  return 0;
2719
2769
  }
2720
2770
 
2771
+ /********************************************
2772
+ * The schema, as the json it is: the `descs` the schema graph is
2773
+ * drawing. Same viewer and same host as the tranger's raw json --
2774
+ * one at a time, so it closes whatever was open first.
2775
+ ********************************************/
2776
+ function ac_open_schema_json(gobj, event, kw, src)
2777
+ {
2778
+ if(!is_object(gobj_read_attr(gobj, "descs"))) {
2779
+ /* Not reachable by hand -- the button only exists while the
2780
+ * schema is on screen, which needs the descs -- so this is a
2781
+ * broken caller, not something to tell the reader about. */
2782
+ log_error(`${gobj_short_name(gobj)}: schema json with no descs`);
2783
+ return -1;
2784
+ }
2785
+ open_json_viewer(gobj, {schema: true});
2786
+ return 0;
2787
+ }
2788
+
2721
2789
  /********************************************
2722
2790
  * Open the graph where the reader left it: its last visited
2723
2791
  * route under the graph's base -- `<graph>/<topic>` when a topic
@@ -2823,6 +2891,7 @@ function create_gclass(gclass_name)
2823
2891
  ["EV_DELETE_RECORD", ac_delete_record, null],
2824
2892
  ["EV_REFRESH_TOPIC", ac_refresh_topic, null],
2825
2893
  ["EV_OPEN_JSON", ac_open_json, null],
2894
+ ["EV_OPEN_SCHEMA_JSON", ac_open_schema_json, null],
2826
2895
  ["EV_OPEN_GRAPH", ac_open_graph, null],
2827
2896
  ["EV_EXPAND_PATH", ac_json_expand_path, null],
2828
2897
  ["EV_JSON_CLOSED", ac_json_closed, null],
@@ -2857,6 +2926,7 @@ function create_gclass(gclass_name)
2857
2926
  event_flag_t.EVF_NO_WARN_SUBS],
2858
2927
  ["EV_REFRESH_TOPIC", 0],
2859
2928
  ["EV_OPEN_JSON", 0],
2929
+ ["EV_OPEN_SCHEMA_JSON", 0],
2860
2930
  ["EV_OPEN_GRAPH", 0],
2861
2931
  ["EV_EXPAND_PATH", 0],
2862
2932
  ["EV_JSON_CLOSED", 0],
package/src/yui_icons.css CHANGED
@@ -176,6 +176,15 @@
176
176
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 576 512'%3E%3Cpath d='M41-24.9c-9.4-9.4-24.6-9.4-33.9 0S-2.3-.3 7 9.1l528 528c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-96.4-96.4c2.7-2.4 5.4-4.8 8-7.2 46.8-43.5 78.1-95.4 93-131.1 3.3-7.9 3.3-16.7 0-24.6-14.9-35.7-46.2-87.7-93-131.1-47.1-43.7-111.8-80.6-192.6-80.6-56.8 0-105.6 18.2-146 44.2L41-24.9zM204.5 138.7c23.5-16.8 52.4-26.7 83.5-26.7 79.5 0 144 64.5 144 144 0 31.1-9.9 59.9-26.7 83.5l-34.7-34.7c12.7-21.4 17-47.7 10.1-73.7-13.7-51.2-66.4-81.6-117.6-67.9-8.6 2.3-16.7 5.7-24 10l-34.7-34.7zM325.3 395.1c-11.9 3.2-24.4 4.9-37.3 4.9-79.5 0-144-64.5-144-144 0-12.9 1.7-25.4 4.9-37.3L69.4 139.2c-32.6 36.8-55 75.8-66.9 104.5-3.3 7.9-3.3 16.7 0 24.6 14.9 35.7 46.2 87.7 93 131.1 47.1 43.7 111.8 80.6 192.6 80.6 37.3 0 71.2-7.9 101.5-20.6l-64.2-64.2z'/%3E%3C/svg%3E");
177
177
  }
178
178
 
179
+ /* The SCHEMA of a treedb -- its plan, as against the `hexagon-nodes`
180
+ * of the DATA graph. The two sat on the same glyph in the same
181
+ * toolbar, one button apart, and nothing but the label told them
182
+ * apart. */
183
+ .yi-compass-drafting::before {
184
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M99.3 256.1l69.4-119.9c-5.6-12.2-8.8-25.8-8.8-40.2 0-53 43-96 96-96s96 43 96 96c0 14.3-3.1 27.9-8.8 40.2l44.4 76.7c-23.1 26-53.7 45.1-88.4 53.8L256 191.9 187.9 309.5c21.5 6.8 44.3 10.5 68.1 10.5 70.7 0 133.8-32.7 174.9-84 11.1-13.8 31.2-16 45-5s16 31.2 5 45c-52.7 65.8-133.9 108-224.8 108-35.4 0-69.4-6.4-100.7-18.1L98.7 463.7C94 471.8 87 478.4 78.6 482.6L23.2 510.3c-5 2.5-10.9 2.2-15.6-.7S0 501.5 0 496l0-55.4c0-8.4 2.2-16.7 6.5-24.1l60-103.7c-12.8-11.2-24.6-23.5-35.3-36.8-11.1-13.8-8.8-33.9 5-45s33.9-8.8 45 5c5.7 7.1 11.8 13.8 18.2 20.1zM381.1 407.9c32.5-13 62.4-31 88.9-52.9l35.6 61.5c4.2 7.3 6.5 15.6 6.5 24.1l0 55.4c0 5.5-2.9 10.7-7.6 13.6s-10.6 3.2-15.6 .7l-55.4-27.7c-8.4-4.2-15.4-10.8-20.1-18.9l-32.3-55.8zM256 128a32 32 0 1 0 0-64 32 32 0 1 0 0 64z'/%3E%3C/svg%3E");
185
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M99.3 256.1l69.4-119.9c-5.6-12.2-8.8-25.8-8.8-40.2 0-53 43-96 96-96s96 43 96 96c0 14.3-3.1 27.9-8.8 40.2l44.4 76.7c-23.1 26-53.7 45.1-88.4 53.8L256 191.9 187.9 309.5c21.5 6.8 44.3 10.5 68.1 10.5 70.7 0 133.8-32.7 174.9-84 11.1-13.8 31.2-16 45-5s16 31.2 5 45c-52.7 65.8-133.9 108-224.8 108-35.4 0-69.4-6.4-100.7-18.1L98.7 463.7C94 471.8 87 478.4 78.6 482.6L23.2 510.3c-5 2.5-10.9 2.2-15.6-.7S0 501.5 0 496l0-55.4c0-8.4 2.2-16.7 6.5-24.1l60-103.7c-12.8-11.2-24.6-23.5-35.3-36.8-11.1-13.8-8.8-33.9 5-45s33.9-8.8 45 5c5.7 7.1 11.8 13.8 18.2 20.1zM381.1 407.9c32.5-13 62.4-31 88.9-52.9l35.6 61.5c4.2 7.3 6.5 15.6 6.5 24.1l0 55.4c0 5.5-2.9 10.7-7.6 13.6s-10.6 3.2-15.6 .7l-55.4-27.7c-8.4-4.2-15.4-10.8-20.1-18.9l-32.3-55.8zM256 128a32 32 0 1 0 0-64 32 32 0 1 0 0 64z'/%3E%3C/svg%3E");
186
+ }
187
+
179
188
  .yi-hexagon-nodes::before {
180
189
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M248 106.6c18.9-9 32-28.3 32-50.6c0-30.9-25.1-56-56-56s-56 25.1-56 56c0 22.3 13.1 41.6 32 50.6l0 98.8c-2.8 1.3-5.5 2.9-8 4.7l-80.1-45.8c1.6-20.8-8.6-41.6-27.9-52.8C57.2 96 23 105.2 7.5 132S1.2 193 28 208.5c1.3 .8 2.6 1.5 4 2.1l0 90.8c-1.3 .6-2.7 1.3-4 2.1C1.2 319-8 353.2 7.5 380S57.2 416 84 400.5c19.3-11.1 29.4-32 27.8-52.8l50.5-28.9c-11.5-11.2-19.9-25.6-23.8-41.7L88 306.1c-2.6-1.8-5.2-3.3-8-4.7l0-90.8c2.8-1.3 5.5-2.9 8-4.7l80.1 45.8c-.1 1.4-.2 2.8-.2 4.3c0 22.3 13.1 41.6 32 50.6l0 98.8c-18.9 9-32 28.3-32 50.6c0 30.9 25.1 56 56 56s56-25.1 56-56c0-22.3-13.1-41.6-32-50.6l0-98.8c2.8-1.3 5.5-2.9 8-4.7l80.1 45.8c-1.6 20.8 8.6 41.6 27.8 52.8c26.8 15.5 61 6.3 76.5-20.5s6.3-61-20.5-76.5c-1.3-.8-2.7-1.5-4-2.1l0-90.8c1.4-.6 2.7-1.3 4-2.1c26.8-15.5 36-49.7 20.5-76.5S390.8 96 364 111.5c-19.3 11.1-29.4 32-27.8 52.8l-50.6 28.9c11.5 11.2 19.9 25.6 23.8 41.7L360 205.9c2.6 1.8 5.2 3.3 8 4.7l0 90.8c-2.8 1.3-5.5 2.9-8 4.6l-80.1-45.8c.1-1.4 .2-2.8 .2-4.3c0-22.3-13.1-41.6-32-50.6l0-98.8z'/%3E%3C/svg%3E");
181
190
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 448 512'%3E%3Cpath d='M248 106.6c18.9-9 32-28.3 32-50.6c0-30.9-25.1-56-56-56s-56 25.1-56 56c0 22.3 13.1 41.6 32 50.6l0 98.8c-2.8 1.3-5.5 2.9-8 4.7l-80.1-45.8c1.6-20.8-8.6-41.6-27.9-52.8C57.2 96 23 105.2 7.5 132S1.2 193 28 208.5c1.3 .8 2.6 1.5 4 2.1l0 90.8c-1.3 .6-2.7 1.3-4 2.1C1.2 319-8 353.2 7.5 380S57.2 416 84 400.5c19.3-11.1 29.4-32 27.8-52.8l50.5-28.9c-11.5-11.2-19.9-25.6-23.8-41.7L88 306.1c-2.6-1.8-5.2-3.3-8-4.7l0-90.8c2.8-1.3 5.5-2.9 8-4.7l80.1 45.8c-.1 1.4-.2 2.8-.2 4.3c0 22.3 13.1 41.6 32 50.6l0 98.8c-18.9 9-32 28.3-32 50.6c0 30.9 25.1 56 56 56s56-25.1 56-56c0-22.3-13.1-41.6-32-50.6l0-98.8c2.8-1.3 5.5-2.9 8-4.7l80.1 45.8c-1.6 20.8 8.6 41.6 27.8 52.8c26.8 15.5 61 6.3 76.5-20.5s6.3-61-20.5-76.5c-1.3-.8-2.7-1.5-4-2.1l0-90.8c1.4-.6 2.7-1.3 4-2.1c26.8-15.5 36-49.7 20.5-76.5S390.8 96 364 111.5c-19.3 11.1-29.4 32-27.8 52.8l-50.6 28.9c11.5 11.2 19.9 25.6 23.8 41.7L360 205.9c2.6 1.8 5.2 3.3 8 4.7l0 90.8c-2.8 1.3-5.5 2.9-8 4.6l-80.1-45.8c.1-1.4 .2-2.8 .2-4.3c0-22.3-13.1-41.6-32-50.6l0-98.8z'/%3E%3C/svg%3E");