@matdata/yasgui-chart-plugin 0.1.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24982,9 +24982,9 @@ var ECharts = (
24982
24982
  var chartView = ecIns._chartsMap[seriesModel.__viewId];
24983
24983
  if (chartView.__alive) {
24984
24984
  chartView.eachRendered(function(el) {
24985
- var emphasis = el.states.emphasis;
24986
- if (emphasis && emphasis.hoverLayer !== HOVER_LAYER_FOR_INCREMENTAL) {
24987
- emphasis.hoverLayer = shouldUseHoverLayer2 ? HOVER_LAYER_FROM_THRESHOLD : HOVER_LAYER_NO;
24985
+ var emphasis2 = el.states.emphasis;
24986
+ if (emphasis2 && emphasis2.hoverLayer !== HOVER_LAYER_FOR_INCREMENTAL) {
24987
+ emphasis2.hoverLayer = shouldUseHoverLayer2 ? HOVER_LAYER_FROM_THRESHOLD : HOVER_LAYER_NO;
24988
24988
  }
24989
24989
  });
24990
24990
  }
@@ -42378,16 +42378,16 @@ function getLegendStyle(iconType, legendItemModel, lineVisualStyle, itemVisualSt
42378
42378
  }
42379
42379
  function getDefaultLegendIcon(opt) {
42380
42380
  var symboType = opt.icon || "roundRect";
42381
- var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect);
42382
- icon.setStyle(opt.itemStyle);
42383
- icon.rotation = (opt.iconRotate || 0) * Math.PI / 180;
42384
- icon.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]);
42381
+ var icon2 = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect);
42382
+ icon2.setStyle(opt.itemStyle);
42383
+ icon2.rotation = (opt.iconRotate || 0) * Math.PI / 180;
42384
+ icon2.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]);
42385
42385
  if (symboType.indexOf("empty") > -1) {
42386
- icon.style.stroke = icon.style.fill;
42387
- icon.style.fill = tokens_default.color.neutral00;
42388
- icon.style.lineWidth = 2;
42386
+ icon2.style.stroke = icon2.style.fill;
42387
+ icon2.style.fill = tokens_default.color.neutral00;
42388
+ icon2.style.lineWidth = 2;
42389
42389
  }
42390
- return icon;
42390
+ return icon2;
42391
42391
  }
42392
42392
  function dispatchSelectAction(seriesName, dataName, api, excludeSeriesId) {
42393
42393
  dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId);
@@ -42610,7 +42610,7 @@ var ScrollableLegendView = (
42610
42610
  createPageButton("pageNext", 1);
42611
42611
  function createPageButton(name, iconIdx) {
42612
42612
  var pageDataIndexName = name + "DataIndex";
42613
- var icon = createIcon(legendModel.get("pageIcons", true)[legendModel.getOrient().name][iconIdx], {
42613
+ var icon2 = createIcon(legendModel.get("pageIcons", true)[legendModel.getOrient().name][iconIdx], {
42614
42614
  // Buttons will be created in each render, so we do not need
42615
42615
  // to worry about avoiding using legendModel kept in scope.
42616
42616
  onclick: bind(self2._pageGo, self2, pageDataIndexName, legendModel, api)
@@ -42620,8 +42620,8 @@ var ScrollableLegendView = (
42620
42620
  width: pageIconSizeArr[0],
42621
42621
  height: pageIconSizeArr[1]
42622
42622
  });
42623
- icon.name = name;
42624
- controllerGroup.add(icon);
42623
+ icon2.name = name;
42624
+ controllerGroup.add(icon2);
42625
42625
  }
42626
42626
  };
42627
42627
  ScrollableLegendView2.prototype.layoutInner = function(legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) {
@@ -42748,10 +42748,10 @@ var ScrollableLegendView = (
42748
42748
  each(["pagePrev", "pageNext"], function(name) {
42749
42749
  var key = name + "DataIndex";
42750
42750
  var canJump = pageInfo[key] != null;
42751
- var icon = controllerGroup.childOfName(name);
42752
- if (icon) {
42753
- icon.setStyle("fill", canJump ? legendModel.get("pageIconColor", true) : legendModel.get("pageIconInactiveColor", true));
42754
- icon.cursor = canJump ? "pointer" : "default";
42751
+ var icon2 = controllerGroup.childOfName(name);
42752
+ if (icon2) {
42753
+ icon2.setStyle("fill", canJump ? legendModel.get("pageIconColor", true) : legendModel.get("pageIconInactiveColor", true));
42754
+ icon2.cursor = canJump ? "pointer" : "default";
42755
42755
  }
42756
42756
  });
42757
42757
  var pageText = controllerGroup.childOfName("pageText");
@@ -46986,6 +46986,11 @@ function baseOption(colors, pointCount) {
46986
46986
  }
46987
46987
  };
46988
46988
  }
46989
+ function emphasis(colors, focusSeries) {
46990
+ const result = focusSeries ? { focus: "series" } : {};
46991
+ if (colors.highlight) result.itemStyle = { color: colors.highlight };
46992
+ return result;
46993
+ }
46989
46994
  function axisStyle(colors) {
46990
46995
  return {
46991
46996
  axisLine: { lineStyle: { color: colors.border } },
@@ -47027,6 +47032,7 @@ function categoryOption(data, settings, colors) {
47027
47032
  center: ["50%", "55%"],
47028
47033
  avoidLabelOverlap: true,
47029
47034
  itemStyle: { borderColor: colors.background, borderWidth: 1 },
47035
+ emphasis: emphasis(colors, false),
47030
47036
  label: { color: colors.text, formatter: "{b}: {d}%" },
47031
47037
  data: data.categories.map((c, i) => ({ name: c.label, value: values[i], categoryIndex: i })).filter((d) => d.value !== null && d.value !== void 0 && d.value > 0)
47032
47038
  }
@@ -47101,7 +47107,7 @@ function categoryOption(data, settings, colors) {
47101
47107
  areaStyle: settings.chartType === "area" ? { opacity: 0.25 } : void 0,
47102
47108
  connectNulls: isLine,
47103
47109
  showSymbol: isLine && labels.length <= 100,
47104
- emphasis: { focus: "series" },
47110
+ emphasis: isLine ? { focus: "series" } : emphasis(colors, true),
47105
47111
  large: !isLine && labels.length > 1e3
47106
47112
  }));
47107
47113
  return option;
@@ -47144,7 +47150,7 @@ function xyOption(data, settings, colors) {
47144
47150
  symbolSize: scatter ? 8 : 4,
47145
47151
  showSymbol: !scatter && s.points.length <= 100,
47146
47152
  areaStyle: settings.chartType === "area" ? { opacity: 0.25 } : void 0,
47147
- emphasis: { focus: "series" },
47153
+ emphasis: scatter ? emphasis(colors, true) : { focus: "series" },
47148
47154
  large: scatter && s.points.length > 2e3
47149
47155
  }));
47150
47156
  return option;
@@ -47176,7 +47182,13 @@ function histogramOption(data, colors) {
47176
47182
  return `${escapeHtml(data.column)}: ${escapeHtml(labels[p.dataIndex])}<br/>Count: <strong>${formatNumber(p.value)}</strong>`;
47177
47183
  };
47178
47184
  option.series = [
47179
- { type: "bar", name: "Count", data: data.bins.map((b) => b.count), barCategoryGap: "4%" }
47185
+ {
47186
+ type: "bar",
47187
+ name: "Count",
47188
+ data: data.bins.map((b) => b.count),
47189
+ barCategoryGap: "4%",
47190
+ emphasis: emphasis(colors, false)
47191
+ }
47180
47192
  ];
47181
47193
  return option;
47182
47194
  }
@@ -47201,6 +47213,27 @@ function iriForClick(data, params) {
47201
47213
  return void 0;
47202
47214
  }
47203
47215
 
47216
+ // src/icons.ts
47217
+ var ICON_PATHS = {
47218
+ "chart-column": '<path d="M3 3v16a2 2 0 0 0 2 2h16"/><path d="M18 17V9"/><path d="M13 17V5"/><path d="M8 17v-3"/>',
47219
+ "sliders-horizontal": '<line x1="21" x2="14" y1="4" y2="4"/><line x1="10" x2="3" y1="4" y2="4"/><line x1="21" x2="12" y1="12" y2="12"/><line x1="8" x2="3" y1="12" y2="12"/><line x1="21" x2="16" y1="20" y2="20"/><line x1="12" x2="3" y1="20" y2="20"/><line x1="14" x2="14" y1="2" y2="6"/><line x1="8" x2="8" y1="10" y2="14"/><line x1="16" x2="16" y1="18" y2="22"/>',
47220
+ "chevron-down": '<path d="m6 9 6 6 6-6"/>',
47221
+ "chevron-left": '<path d="m15 18-6-6 6-6"/>',
47222
+ "chevron-right": '<path d="m9 18 6-6-6-6"/>',
47223
+ "chevrons-left": '<path d="m11 17-5-5 5-5"/><path d="m18 17-5-5 5-5"/>',
47224
+ x: '<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',
47225
+ download: '<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" x2="12" y1="15" y2="3"/>',
47226
+ "rotate-ccw": '<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/>'
47227
+ };
47228
+ function iconSvg(name, size = 16, strokeWidth = 1.75) {
47229
+ return `<svg xmlns="http://www.w3.org/2000/svg" class="chart-icon chart-icon-${name}" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="${strokeWidth}" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${ICON_PATHS[name]}</svg>`;
47230
+ }
47231
+ function icon(name, size, strokeWidth) {
47232
+ const template = document.createElement("template");
47233
+ template.innerHTML = iconSvg(name, size, strokeWidth);
47234
+ return template.content.firstElementChild;
47235
+ }
47236
+
47204
47237
  // src/settings.ts
47205
47238
  var CHART_TYPES = [
47206
47239
  { value: "bar", label: "Bar" },
@@ -47303,9 +47336,10 @@ var KIND_LABEL = {
47303
47336
  iri: "IRI",
47304
47337
  text: "text"
47305
47338
  };
47306
- function field(labelText, control) {
47307
- const wrapper = document.createElement("label");
47308
- wrapper.className = "chart-toolbar-field";
47339
+ var menuCounter = 0;
47340
+ function field(layout2, labelText, control, tag = "label") {
47341
+ const wrapper = document.createElement(tag);
47342
+ wrapper.className = layout2 === "host" ? "yasr_toolbarSelect chart-toolbar-field" : "chart-toolbar-field";
47309
47343
  const label = document.createElement("span");
47310
47344
  label.className = "chart-toolbar-label";
47311
47345
  label.textContent = labelText;
@@ -47313,9 +47347,9 @@ function field(labelText, control) {
47313
47347
  wrapper.appendChild(control);
47314
47348
  return wrapper;
47315
47349
  }
47316
- function select(className, options, value, onChange) {
47350
+ function select(layout2, className, options, value, onChange) {
47317
47351
  const el = document.createElement("select");
47318
- el.className = `chart-toolbar-select ${className}`;
47352
+ el.className = layout2 === "host" ? className : `chart-toolbar-select ${className}`;
47319
47353
  for (const o of options) {
47320
47354
  const option = document.createElement("option");
47321
47355
  option.value = o.value;
@@ -47339,11 +47373,10 @@ function button(className, text, title, onClick) {
47339
47373
  function columnLabel(c) {
47340
47374
  return `${c.name} (${KIND_LABEL[c.kind]})`;
47341
47375
  }
47342
- function renderToolbar(state, callbacks) {
47376
+ function renderPickers(layout2, state, callbacks) {
47343
47377
  var _a2, _b2;
47344
47378
  const { columns, resolved } = state;
47345
- const toolbar = document.createElement("div");
47346
- toolbar.className = "chart-toolbar";
47379
+ const fields = [];
47347
47380
  const current = () => {
47348
47381
  var _a3, _b3;
47349
47382
  return {
@@ -47355,10 +47388,12 @@ function renderToolbar(state, callbacks) {
47355
47388
  };
47356
47389
  const isHistogram = resolved.chartType === "histogram";
47357
47390
  const isPie = resolved.chartType === "pie" || resolved.chartType === "donut";
47358
- toolbar.appendChild(
47391
+ fields.push(
47359
47392
  field(
47360
- "Chart",
47393
+ layout2,
47394
+ layout2 === "host" ? "Type" : "Chart",
47361
47395
  select(
47396
+ layout2,
47362
47397
  "chart-type-select",
47363
47398
  CHART_TYPES,
47364
47399
  resolved.chartType,
@@ -47368,6 +47403,7 @@ function renderToolbar(state, callbacks) {
47368
47403
  );
47369
47404
  const candidates = categoryCandidates(columns);
47370
47405
  const categorySelect = select(
47406
+ layout2,
47371
47407
  "chart-category-select",
47372
47408
  candidates.map((c) => ({ value: c.name, label: columnLabel(c) })),
47373
47409
  (_a2 = resolved.category) != null ? _a2 : "",
@@ -47381,8 +47417,9 @@ function renderToolbar(state, callbacks) {
47381
47417
  }
47382
47418
  );
47383
47419
  categorySelect.disabled = isHistogram || candidates.length === 0;
47384
- toolbar.appendChild(
47420
+ fields.push(
47385
47421
  field(
47422
+ layout2,
47386
47423
  isPie ? "Slices" : resolved.chartType === "horizontal-bar" ? "Y axis" : "X axis",
47387
47424
  categorySelect
47388
47425
  )
@@ -47391,8 +47428,12 @@ function renderToolbar(state, callbacks) {
47391
47428
  const valuesPicker = document.createElement("details");
47392
47429
  valuesPicker.className = "chart-values-picker";
47393
47430
  const summary = document.createElement("summary");
47394
- summary.className = "chart-toolbar-select";
47395
- summary.textContent = resolved.values.length > 0 ? resolved.values.join(", ") : "None";
47431
+ summary.className = layout2 === "host" ? "chart-values-summary" : "chart-toolbar-select chart-values-summary";
47432
+ const summaryText = document.createElement("span");
47433
+ summaryText.className = "chart-values-summary-text";
47434
+ summaryText.textContent = resolved.values.length > 0 ? resolved.values.join(", ") : "None";
47435
+ summary.appendChild(summaryText);
47436
+ summary.appendChild(icon("chevron-down", 14));
47396
47437
  valuesPicker.appendChild(summary);
47397
47438
  const list = document.createElement("div");
47398
47439
  list.className = "chart-values-list";
@@ -47423,18 +47464,32 @@ function renderToolbar(state, callbacks) {
47423
47464
  list.appendChild(item);
47424
47465
  }
47425
47466
  valuesPicker.appendChild(list);
47426
- toolbar.appendChild(field(isHistogram ? "Value" : isPie ? "Size" : "Values", valuesPicker));
47467
+ fields.push(
47468
+ field(
47469
+ layout2,
47470
+ isHistogram ? "Value" : isPie ? "Size" : "Values",
47471
+ valuesPicker,
47472
+ layout2 === "host" ? "div" : "label"
47473
+ )
47474
+ );
47427
47475
  const seriesOptions = [{ value: "", label: "None" }].concat(
47428
47476
  candidates.filter((c) => c.name !== resolved.category && !resolved.values.includes(c.name)).map((c) => ({ value: c.name, label: columnLabel(c) }))
47429
47477
  );
47430
47478
  const seriesSelect = select(
47479
+ layout2,
47431
47480
  "chart-series-select",
47432
47481
  seriesOptions,
47433
47482
  (_b2 = resolved.series) != null ? _b2 : "",
47434
47483
  (value) => callbacks.onChange({ ...current(), series: value })
47435
47484
  );
47436
47485
  seriesSelect.disabled = isHistogram || isPie || seriesOptions.length <= 1;
47437
- toolbar.appendChild(field("Series", seriesSelect));
47486
+ fields.push(field(layout2, "Series", seriesSelect));
47487
+ return fields;
47488
+ }
47489
+ function renderToolbar(state, callbacks) {
47490
+ const toolbar = document.createElement("div");
47491
+ toolbar.className = "chart-toolbar";
47492
+ for (const el of renderPickers("own", state, callbacks)) toolbar.appendChild(el);
47438
47493
  if (state.customised) {
47439
47494
  toolbar.appendChild(
47440
47495
  button(
@@ -47466,6 +47521,130 @@ function renderToolbar(state, callbacks) {
47466
47521
  );
47467
47522
  return toolbar;
47468
47523
  }
47524
+ function menuItem(className, iconName, text, title, onClick) {
47525
+ const el = document.createElement("button");
47526
+ el.type = "button";
47527
+ el.className = `chart-view-settings-item ${className}`;
47528
+ el.title = title;
47529
+ el.appendChild(icon(iconName));
47530
+ const label = document.createElement("span");
47531
+ label.textContent = text;
47532
+ el.appendChild(label);
47533
+ el.addEventListener("click", onClick);
47534
+ return el;
47535
+ }
47536
+ function renderViewSettings(state, callbacks) {
47537
+ const wrapper = document.createElement("div");
47538
+ wrapper.className = "chart-view-settings";
47539
+ const menuId = `chart-view-settings-menu-${++menuCounter}`;
47540
+ const toggle = document.createElement("button");
47541
+ toggle.type = "button";
47542
+ toggle.className = "yasr_toolbarButton chart-view-settings-button";
47543
+ toggle.setAttribute("aria-haspopup", "true");
47544
+ toggle.setAttribute("aria-expanded", "false");
47545
+ toggle.setAttribute("aria-controls", menuId);
47546
+ toggle.appendChild(icon("sliders-horizontal"));
47547
+ const text = document.createElement("span");
47548
+ text.textContent = "View settings";
47549
+ toggle.appendChild(text);
47550
+ const menu = document.createElement("div");
47551
+ menu.className = "chart-view-settings-menu";
47552
+ menu.id = menuId;
47553
+ menu.setAttribute("role", "group");
47554
+ menu.setAttribute("aria-label", "View settings");
47555
+ menu.hidden = true;
47556
+ const setOpen = (open) => {
47557
+ menu.hidden = !open;
47558
+ toggle.setAttribute("aria-expanded", String(open));
47559
+ toggle.classList.toggle("is-active", open);
47560
+ };
47561
+ const run = (action) => () => {
47562
+ setOpen(false);
47563
+ action();
47564
+ };
47565
+ const reset = menuItem(
47566
+ "chart-reset-button",
47567
+ "rotate-ccw",
47568
+ "Automatic chart",
47569
+ "Go back to the automatic chart for these results",
47570
+ run(callbacks.onReset)
47571
+ );
47572
+ reset.disabled = !state.customised;
47573
+ menu.appendChild(reset);
47574
+ const separator = document.createElement("div");
47575
+ separator.className = "chart-view-settings-separator";
47576
+ separator.setAttribute("role", "separator");
47577
+ menu.appendChild(separator);
47578
+ menu.appendChild(
47579
+ menuItem(
47580
+ "chart-export-png",
47581
+ "download",
47582
+ "Download PNG",
47583
+ "Download the chart as a PNG image",
47584
+ run(() => callbacks.onExport("png"))
47585
+ )
47586
+ );
47587
+ menu.appendChild(
47588
+ menuItem(
47589
+ "chart-export-svg",
47590
+ "download",
47591
+ "Download SVG",
47592
+ "Download the chart as an SVG image",
47593
+ run(() => callbacks.onExport("svg"))
47594
+ )
47595
+ );
47596
+ toggle.addEventListener("click", () => setOpen(menu.hidden));
47597
+ wrapper.addEventListener("keydown", (e2) => {
47598
+ if (e2.key === "Escape" && !menu.hidden) {
47599
+ e2.stopPropagation();
47600
+ setOpen(false);
47601
+ toggle.focus();
47602
+ }
47603
+ });
47604
+ wrapper.appendChild(toggle);
47605
+ wrapper.appendChild(menu);
47606
+ return wrapper;
47607
+ }
47608
+ function renderHostToolbar(slot, state, callbacks) {
47609
+ const group = document.createElement("div");
47610
+ group.className = "yasr_toolbarGroup chart-toolbar-pickers";
47611
+ for (const el of renderPickers("host", state, callbacks)) group.appendChild(el);
47612
+ const spacer = document.createElement("div");
47613
+ spacer.className = "yasr_toolbarSpacer";
47614
+ const nodes = [group, spacer, renderViewSettings(state, callbacks)];
47615
+ for (const node of nodes) slot.appendChild(node);
47616
+ return nodes;
47617
+ }
47618
+ function closeToolbarPopups(root, target) {
47619
+ root.querySelectorAll(".chart-values-picker[open]").forEach((picker) => {
47620
+ if (!target || !picker.contains(target)) picker.removeAttribute("open");
47621
+ });
47622
+ root.querySelectorAll(".chart-view-settings").forEach((wrapper) => {
47623
+ const menu = wrapper.querySelector(".chart-view-settings-menu");
47624
+ if (!menu || menu.hidden || target && wrapper.contains(target)) return;
47625
+ menu.hidden = true;
47626
+ const toggle = wrapper.querySelector(".chart-view-settings-button");
47627
+ toggle == null ? void 0 : toggle.setAttribute("aria-expanded", "false");
47628
+ toggle == null ? void 0 : toggle.classList.remove("is-active");
47629
+ });
47630
+ }
47631
+
47632
+ // src/host.ts
47633
+ function hasHostDescribe(yasr) {
47634
+ var _a2;
47635
+ return !!((_a2 = yasr == null ? void 0 : yasr.hostApi) == null ? void 0 : _a2.describe) && typeof yasr.describe === "function";
47636
+ }
47637
+ function getHostToolbar(yasr) {
47638
+ var _a2;
47639
+ if (!((_a2 = yasr == null ? void 0 : yasr.hostApi) == null ? void 0 : _a2.toolbar) || typeof yasr.getPluginToolbar !== "function") return null;
47640
+ try {
47641
+ const slot = yasr.getPluginToolbar();
47642
+ return slot instanceof HTMLElement ? slot : null;
47643
+ } catch (error2) {
47644
+ console.warn("yasgui-chart-plugin: could not get the plugin toolbar", error2);
47645
+ return null;
47646
+ }
47647
+ }
47469
47648
 
47470
47649
  // src/theme.ts
47471
47650
  var LIGHT_PALETTE = [
@@ -47492,6 +47671,10 @@ var DARK_PALETTE = [
47492
47671
  "#ef8cc8",
47493
47672
  "#9aa8bb"
47494
47673
  ];
47674
+ var BRAND_LIGHT = "#0563bb";
47675
+ var BRAND_DARK = "#5aa8f2";
47676
+ var HIGHLIGHT_LIGHT = "#f2b300";
47677
+ var HIGHLIGHT_DARK = "#f5c242";
47495
47678
  function getCurrentTheme() {
47496
47679
  if (typeof document === "undefined") return "light";
47497
47680
  return document.documentElement.getAttribute("data-theme") === "dark" ? "dark" : "light";
@@ -47507,7 +47690,11 @@ function getThemeColors() {
47507
47690
  border: read("--yasgui-border-color", dark ? "#444444" : "#d0d0d0"),
47508
47691
  background: read("--yasgui-bg-primary", dark ? "#1e1e1e" : "#ffffff"),
47509
47692
  tooltipBackground: read("--yasgui-bg-secondary", dark ? "#2a2a2a" : "#ffffff"),
47510
- palette: dark ? DARK_PALETTE : LIGHT_PALETTE
47693
+ palette: [
47694
+ read("--yasgui-brand", dark ? BRAND_DARK : BRAND_LIGHT),
47695
+ ...(dark ? DARK_PALETTE : LIGHT_PALETTE).slice(1)
47696
+ ],
47697
+ highlight: read("--yasgui-highlight", dark ? HIGHLIGHT_DARK : HIGHLIGHT_LIGHT)
47511
47698
  };
47512
47699
  }
47513
47700
  function watchThemeChanges(callback) {
@@ -50387,7 +50574,8 @@ var DescribeModal = class {
50387
50574
  title.title = uri;
50388
50575
  const closeButton = document.createElement("button");
50389
50576
  closeButton.className = "chart-modal-close";
50390
- closeButton.innerHTML = "&times;";
50577
+ closeButton.type = "button";
50578
+ closeButton.appendChild(icon("x", 20));
50391
50579
  closeButton.setAttribute("aria-label", "Close modal");
50392
50580
  closeButton.addEventListener("click", () => this.close());
50393
50581
  header.appendChild(this.createNavigation());
@@ -50409,7 +50597,7 @@ var DescribeModal = class {
50409
50597
  hint.textContent = "Ctrl+click a URI to describe it, Ctrl+Shift+click for the triples where it is the object.";
50410
50598
  const copyButton = document.createElement("button");
50411
50599
  copyButton.className = "chart-modal-button";
50412
- copyButton.textContent = "Copy Raw";
50600
+ copyButton.textContent = "Copy raw";
50413
50601
  copyButton.addEventListener("click", () => {
50414
50602
  const rawText = payload.state === "results" ? payload.result.raw : payload.state === "error" ? payload.raw : "";
50415
50603
  this.copyToClipboard(rawText);
@@ -50448,11 +50636,11 @@ var DescribeModal = class {
50448
50636
  createNavigation() {
50449
50637
  const nav = document.createElement("div");
50450
50638
  nav.className = "chart-describe-modal-nav";
50451
- const button2 = (className, text, label, enabled, onClick) => {
50639
+ const button2 = (className, iconName, label, enabled, onClick) => {
50452
50640
  const btn = document.createElement("button");
50453
50641
  btn.type = "button";
50454
50642
  btn.className = `chart-describe-modal-nav-button ${className}`;
50455
- btn.textContent = text;
50643
+ btn.appendChild(icon(iconName));
50456
50644
  btn.title = label;
50457
50645
  btn.setAttribute("aria-label", label);
50458
50646
  btn.disabled = !enabled;
@@ -50462,19 +50650,25 @@ var DescribeModal = class {
50462
50650
  nav.appendChild(
50463
50651
  button2(
50464
50652
  "chart-describe-modal-start",
50465
- "\u23EE",
50653
+ "chevrons-left",
50466
50654
  "Back to start",
50467
50655
  this.canGoBack(),
50468
50656
  () => this.backToStart()
50469
50657
  )
50470
50658
  );
50471
50659
  nav.appendChild(
50472
- button2("chart-describe-modal-back", "\u25C0", "Back (Alt+\u2190)", this.canGoBack(), () => this.back())
50660
+ button2(
50661
+ "chart-describe-modal-back",
50662
+ "chevron-left",
50663
+ "Back (Alt+\u2190)",
50664
+ this.canGoBack(),
50665
+ () => this.back()
50666
+ )
50473
50667
  );
50474
50668
  nav.appendChild(
50475
50669
  button2(
50476
50670
  "chart-describe-modal-forward",
50477
- "\u25B6",
50671
+ "chevron-right",
50478
50672
  "Forward (Alt+\u2192)",
50479
50673
  this.canGoForward(),
50480
50674
  () => this.forward()
@@ -50697,7 +50891,7 @@ use([
50697
50891
  ]);
50698
50892
  var DEFAULT_MAX_ROWS = 5e3;
50699
50893
  var MIN_CHART_HEIGHT = 320;
50700
- var ICON_SVG = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><path fill="currentColor" d="M3 3h2v16h16v2H3V3zm4 10h3v5H7v-5zm5-6h3v11h-3V7zm5 3h3v8h-3v-8z"/></svg>';
50894
+ var ICON_SVG = iconSvg("chart-column");
50701
50895
  var ChartPlugin = class {
50702
50896
  constructor(yasr, options = {}) {
50703
50897
  /** Below the table (10), so SELECT results still open in the table */
@@ -50717,6 +50911,9 @@ var ChartPlugin = class {
50717
50911
  this.outsideClickHandler = null;
50718
50912
  this.windowResizeHandler = null;
50719
50913
  this.fullscreenObserver = null;
50914
+ /** Elements this plugin put in the host's toolbar slot */
50915
+ this.hostToolbarNodes = [];
50916
+ /** @deprecated Own describe modal, used only when the host has no shared describe panel */
50720
50917
  this.describeModal = null;
50721
50918
  this.describeAbortController = null;
50722
50919
  var _a2, _b2, _c2;
@@ -50731,11 +50928,11 @@ var ChartPlugin = class {
50731
50928
  return 5;
50732
50929
  }
50733
50930
  getIcon() {
50734
- const icon = document.createElement("div");
50735
- icon.innerHTML = ICON_SVG;
50736
- icon.setAttribute("role", "img");
50737
- icon.setAttribute("aria-label", "Chart view");
50738
- return icon;
50931
+ const icon2 = document.createElement("div");
50932
+ icon2.innerHTML = ICON_SVG;
50933
+ icon2.setAttribute("role", "img");
50934
+ icon2.setAttribute("aria-label", "Chart view");
50935
+ return icon2;
50739
50936
  }
50740
50937
  /** Offered for SELECT results with at least one numeric column */
50741
50938
  canHandleResults() {
@@ -50812,20 +51009,23 @@ var ChartPlugin = class {
50812
51009
  this.data = buildChartData(rows, this.columns, this.resolved, this.getPrefixes());
50813
51010
  const wrapper = document.createElement("div");
50814
51011
  wrapper.className = "yasgui-chart-plugin";
50815
- wrapper.appendChild(
50816
- renderToolbar(
50817
- {
50818
- columns: this.columns,
50819
- resolved: this.resolved,
50820
- customised: Object.keys(this.saved).length > 0
50821
- },
50822
- {
50823
- onChange: (settings) => this.updateSettings(settings),
50824
- onReset: () => this.updateSettings({}),
50825
- onExport: (format2) => this.exportImage(format2)
50826
- }
50827
- )
50828
- );
51012
+ const toolbarState = {
51013
+ columns: this.columns,
51014
+ resolved: this.resolved,
51015
+ customised: Object.keys(this.saved).length > 0
51016
+ };
51017
+ const toolbarCallbacks = {
51018
+ onChange: (settings) => this.updateSettings(settings),
51019
+ onReset: () => this.updateSettings({}),
51020
+ onExport: (format2) => this.exportImage(format2)
51021
+ };
51022
+ const slot = getHostToolbar(this.yasr);
51023
+ if (slot) {
51024
+ this.hostToolbarNodes = renderHostToolbar(slot, toolbarState, toolbarCallbacks);
51025
+ } else {
51026
+ wrapper.classList.add("chart-own-toolbar");
51027
+ wrapper.appendChild(renderToolbar(toolbarState, toolbarCallbacks));
51028
+ }
50829
51029
  const notes = [];
50830
51030
  if (allRows.length > maxRows) {
50831
51031
  notes.push(
@@ -50876,11 +51076,9 @@ var ChartPlugin = class {
50876
51076
  this.fullscreenObserver.observe(yasrRoot, { attributes: true, attributeFilter: ["class"] });
50877
51077
  }
50878
51078
  this.themeObserver = watchThemeChanges(() => this.applyOption());
51079
+ const popupRoot = slot || wrapper;
50879
51080
  this.outsideClickHandler = (e2) => {
50880
- const picker = wrapper.querySelector(".chart-values-picker");
50881
- if (picker && picker.hasAttribute("open") && !picker.contains(e2.target)) {
50882
- picker.removeAttribute("open");
50883
- }
51081
+ closeToolbarPopups(popupRoot, e2.target);
50884
51082
  };
50885
51083
  document.addEventListener("mousedown", this.outsideClickHandler);
50886
51084
  }
@@ -50922,15 +51120,37 @@ var ChartPlugin = class {
50922
51120
  if (!iri) return;
50923
51121
  this.runResourceQuery(iri, event.shiftKey ? "object" : "subject");
50924
51122
  }
51123
+ /**
51124
+ * Show the triples of `uri`: in the host's shared describe panel when YASR
51125
+ * offers one, otherwise in the plugin's own describe modal.
51126
+ */
51127
+ runResourceQuery(uri, direction) {
51128
+ if (hasHostDescribe(this.yasr)) {
51129
+ const hostDirection = direction === "object" ? "incoming" : "outgoing";
51130
+ const fail = (error2) => console.error("yasgui-chart-plugin: describe failed", uri, error2);
51131
+ try {
51132
+ Promise.resolve(
51133
+ this.yasr.describe(uri, { direction: hostDirection, source: "Chart" })
51134
+ ).catch(fail);
51135
+ } catch (error2) {
51136
+ fail(error2);
51137
+ }
51138
+ return;
51139
+ }
51140
+ void this.runOwnResourceQuery(uri, direction);
51141
+ }
50925
51142
  /**
50926
51143
  * Run a background query for the triples where `iri` is the subject (or
50927
- * object) and show them in the describe modal, as the table and geo plugins do.
51144
+ * object) and show them in the plugin's own describe modal.
51145
+ *
51146
+ * @deprecated Fallback for YASR versions without `yasr.describe()`; it will be
51147
+ * removed in the next major version.
50928
51148
  */
50929
- async runResourceQuery(uri, direction, newHistory = true) {
51149
+ async runOwnResourceQuery(uri, direction, newHistory = true) {
50930
51150
  var _a2, _b2, _c2, _d2;
50931
51151
  if (!this.describeModal) {
50932
51152
  this.describeModal = new DescribeModal({
50933
- onDescribe: (u, d) => this.runResourceQuery(u, d, false)
51153
+ onDescribe: (u, d) => this.runOwnResourceQuery(u, d, false)
50934
51154
  });
50935
51155
  }
50936
51156
  if (typeof this.yasr.executeQuery !== "function") {
@@ -51049,6 +51269,8 @@ var ChartPlugin = class {
51049
51269
  this.chart.dispose();
51050
51270
  this.chart = null;
51051
51271
  }
51272
+ for (const node of this.hostToolbarNodes) node.remove();
51273
+ this.hostToolbarNodes = [];
51052
51274
  this.chartEl = null;
51053
51275
  this.option = null;
51054
51276
  }