@matdata/yasgui-chart-plugin 1.0.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.
@@ -24962,9 +24962,9 @@ var ECharts = (
24962
24962
  var chartView = ecIns._chartsMap[seriesModel.__viewId];
24963
24963
  if (chartView.__alive) {
24964
24964
  chartView.eachRendered(function(el) {
24965
- var emphasis = el.states.emphasis;
24966
- if (emphasis && emphasis.hoverLayer !== HOVER_LAYER_FOR_INCREMENTAL) {
24967
- emphasis.hoverLayer = shouldUseHoverLayer2 ? HOVER_LAYER_FROM_THRESHOLD : HOVER_LAYER_NO;
24965
+ var emphasis2 = el.states.emphasis;
24966
+ if (emphasis2 && emphasis2.hoverLayer !== HOVER_LAYER_FOR_INCREMENTAL) {
24967
+ emphasis2.hoverLayer = shouldUseHoverLayer2 ? HOVER_LAYER_FROM_THRESHOLD : HOVER_LAYER_NO;
24968
24968
  }
24969
24969
  });
24970
24970
  }
@@ -42358,16 +42358,16 @@ function getLegendStyle(iconType, legendItemModel, lineVisualStyle, itemVisualSt
42358
42358
  }
42359
42359
  function getDefaultLegendIcon(opt) {
42360
42360
  var symboType = opt.icon || "roundRect";
42361
- var icon = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect);
42362
- icon.setStyle(opt.itemStyle);
42363
- icon.rotation = (opt.iconRotate || 0) * Math.PI / 180;
42364
- icon.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]);
42361
+ var icon2 = createSymbol(symboType, 0, 0, opt.itemWidth, opt.itemHeight, opt.itemStyle.fill, opt.symbolKeepAspect);
42362
+ icon2.setStyle(opt.itemStyle);
42363
+ icon2.rotation = (opt.iconRotate || 0) * Math.PI / 180;
42364
+ icon2.setOrigin([opt.itemWidth / 2, opt.itemHeight / 2]);
42365
42365
  if (symboType.indexOf("empty") > -1) {
42366
- icon.style.stroke = icon.style.fill;
42367
- icon.style.fill = tokens_default.color.neutral00;
42368
- icon.style.lineWidth = 2;
42366
+ icon2.style.stroke = icon2.style.fill;
42367
+ icon2.style.fill = tokens_default.color.neutral00;
42368
+ icon2.style.lineWidth = 2;
42369
42369
  }
42370
- return icon;
42370
+ return icon2;
42371
42371
  }
42372
42372
  function dispatchSelectAction(seriesName, dataName, api, excludeSeriesId) {
42373
42373
  dispatchDownplayAction(seriesName, dataName, api, excludeSeriesId);
@@ -42590,7 +42590,7 @@ var ScrollableLegendView = (
42590
42590
  createPageButton("pageNext", 1);
42591
42591
  function createPageButton(name, iconIdx) {
42592
42592
  var pageDataIndexName = name + "DataIndex";
42593
- var icon = createIcon(legendModel.get("pageIcons", true)[legendModel.getOrient().name][iconIdx], {
42593
+ var icon2 = createIcon(legendModel.get("pageIcons", true)[legendModel.getOrient().name][iconIdx], {
42594
42594
  // Buttons will be created in each render, so we do not need
42595
42595
  // to worry about avoiding using legendModel kept in scope.
42596
42596
  onclick: bind(self2._pageGo, self2, pageDataIndexName, legendModel, api)
@@ -42600,8 +42600,8 @@ var ScrollableLegendView = (
42600
42600
  width: pageIconSizeArr[0],
42601
42601
  height: pageIconSizeArr[1]
42602
42602
  });
42603
- icon.name = name;
42604
- controllerGroup.add(icon);
42603
+ icon2.name = name;
42604
+ controllerGroup.add(icon2);
42605
42605
  }
42606
42606
  };
42607
42607
  ScrollableLegendView2.prototype.layoutInner = function(legendModel, itemAlign, maxSize, isFirstRender, selector, selectorPosition) {
@@ -42728,10 +42728,10 @@ var ScrollableLegendView = (
42728
42728
  each(["pagePrev", "pageNext"], function(name) {
42729
42729
  var key = name + "DataIndex";
42730
42730
  var canJump = pageInfo[key] != null;
42731
- var icon = controllerGroup.childOfName(name);
42732
- if (icon) {
42733
- icon.setStyle("fill", canJump ? legendModel.get("pageIconColor", true) : legendModel.get("pageIconInactiveColor", true));
42734
- icon.cursor = canJump ? "pointer" : "default";
42731
+ var icon2 = controllerGroup.childOfName(name);
42732
+ if (icon2) {
42733
+ icon2.setStyle("fill", canJump ? legendModel.get("pageIconColor", true) : legendModel.get("pageIconInactiveColor", true));
42734
+ icon2.cursor = canJump ? "pointer" : "default";
42735
42735
  }
42736
42736
  });
42737
42737
  var pageText = controllerGroup.childOfName("pageText");
@@ -46966,6 +46966,11 @@ function baseOption(colors, pointCount) {
46966
46966
  }
46967
46967
  };
46968
46968
  }
46969
+ function emphasis(colors, focusSeries) {
46970
+ const result = focusSeries ? { focus: "series" } : {};
46971
+ if (colors.highlight) result.itemStyle = { color: colors.highlight };
46972
+ return result;
46973
+ }
46969
46974
  function axisStyle(colors) {
46970
46975
  return {
46971
46976
  axisLine: { lineStyle: { color: colors.border } },
@@ -47007,6 +47012,7 @@ function categoryOption(data, settings, colors) {
47007
47012
  center: ["50%", "55%"],
47008
47013
  avoidLabelOverlap: true,
47009
47014
  itemStyle: { borderColor: colors.background, borderWidth: 1 },
47015
+ emphasis: emphasis(colors, false),
47010
47016
  label: { color: colors.text, formatter: "{b}: {d}%" },
47011
47017
  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)
47012
47018
  }
@@ -47081,7 +47087,7 @@ function categoryOption(data, settings, colors) {
47081
47087
  areaStyle: settings.chartType === "area" ? { opacity: 0.25 } : void 0,
47082
47088
  connectNulls: isLine,
47083
47089
  showSymbol: isLine && labels.length <= 100,
47084
- emphasis: { focus: "series" },
47090
+ emphasis: isLine ? { focus: "series" } : emphasis(colors, true),
47085
47091
  large: !isLine && labels.length > 1e3
47086
47092
  }));
47087
47093
  return option;
@@ -47124,7 +47130,7 @@ function xyOption(data, settings, colors) {
47124
47130
  symbolSize: scatter ? 8 : 4,
47125
47131
  showSymbol: !scatter && s.points.length <= 100,
47126
47132
  areaStyle: settings.chartType === "area" ? { opacity: 0.25 } : void 0,
47127
- emphasis: { focus: "series" },
47133
+ emphasis: scatter ? emphasis(colors, true) : { focus: "series" },
47128
47134
  large: scatter && s.points.length > 2e3
47129
47135
  }));
47130
47136
  return option;
@@ -47156,7 +47162,13 @@ function histogramOption(data, colors) {
47156
47162
  return `${escapeHtml(data.column)}: ${escapeHtml(labels[p.dataIndex])}<br/>Count: <strong>${formatNumber(p.value)}</strong>`;
47157
47163
  };
47158
47164
  option.series = [
47159
- { type: "bar", name: "Count", data: data.bins.map((b) => b.count), barCategoryGap: "4%" }
47165
+ {
47166
+ type: "bar",
47167
+ name: "Count",
47168
+ data: data.bins.map((b) => b.count),
47169
+ barCategoryGap: "4%",
47170
+ emphasis: emphasis(colors, false)
47171
+ }
47160
47172
  ];
47161
47173
  return option;
47162
47174
  }
@@ -47181,6 +47193,27 @@ function iriForClick(data, params) {
47181
47193
  return void 0;
47182
47194
  }
47183
47195
 
47196
+ // src/icons.ts
47197
+ var ICON_PATHS = {
47198
+ "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"/>',
47199
+ "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"/>',
47200
+ "chevron-down": '<path d="m6 9 6 6 6-6"/>',
47201
+ "chevron-left": '<path d="m15 18-6-6 6-6"/>',
47202
+ "chevron-right": '<path d="m9 18 6-6-6-6"/>',
47203
+ "chevrons-left": '<path d="m11 17-5-5 5-5"/><path d="m18 17-5-5 5-5"/>',
47204
+ x: '<path d="M18 6 6 18"/><path d="m6 6 12 12"/>',
47205
+ 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"/>',
47206
+ "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"/>'
47207
+ };
47208
+ function iconSvg(name, size = 16, strokeWidth = 1.75) {
47209
+ 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>`;
47210
+ }
47211
+ function icon(name, size, strokeWidth) {
47212
+ const template = document.createElement("template");
47213
+ template.innerHTML = iconSvg(name, size, strokeWidth);
47214
+ return template.content.firstElementChild;
47215
+ }
47216
+
47184
47217
  // src/settings.ts
47185
47218
  var CHART_TYPES = [
47186
47219
  { value: "bar", label: "Bar" },
@@ -47283,9 +47316,10 @@ var KIND_LABEL = {
47283
47316
  iri: "IRI",
47284
47317
  text: "text"
47285
47318
  };
47286
- function field(labelText, control) {
47287
- const wrapper = document.createElement("label");
47288
- wrapper.className = "chart-toolbar-field";
47319
+ var menuCounter = 0;
47320
+ function field(layout2, labelText, control, tag = "label") {
47321
+ const wrapper = document.createElement(tag);
47322
+ wrapper.className = layout2 === "host" ? "yasr_toolbarSelect chart-toolbar-field" : "chart-toolbar-field";
47289
47323
  const label = document.createElement("span");
47290
47324
  label.className = "chart-toolbar-label";
47291
47325
  label.textContent = labelText;
@@ -47293,9 +47327,9 @@ function field(labelText, control) {
47293
47327
  wrapper.appendChild(control);
47294
47328
  return wrapper;
47295
47329
  }
47296
- function select(className, options, value, onChange) {
47330
+ function select(layout2, className, options, value, onChange) {
47297
47331
  const el = document.createElement("select");
47298
- el.className = `chart-toolbar-select ${className}`;
47332
+ el.className = layout2 === "host" ? className : `chart-toolbar-select ${className}`;
47299
47333
  for (const o of options) {
47300
47334
  const option = document.createElement("option");
47301
47335
  option.value = o.value;
@@ -47319,11 +47353,10 @@ function button(className, text, title, onClick) {
47319
47353
  function columnLabel(c) {
47320
47354
  return `${c.name} (${KIND_LABEL[c.kind]})`;
47321
47355
  }
47322
- function renderToolbar(state, callbacks) {
47356
+ function renderPickers(layout2, state, callbacks) {
47323
47357
  var _a2, _b2;
47324
47358
  const { columns, resolved } = state;
47325
- const toolbar = document.createElement("div");
47326
- toolbar.className = "chart-toolbar";
47359
+ const fields = [];
47327
47360
  const current = () => {
47328
47361
  var _a3, _b3;
47329
47362
  return {
@@ -47335,10 +47368,12 @@ function renderToolbar(state, callbacks) {
47335
47368
  };
47336
47369
  const isHistogram = resolved.chartType === "histogram";
47337
47370
  const isPie = resolved.chartType === "pie" || resolved.chartType === "donut";
47338
- toolbar.appendChild(
47371
+ fields.push(
47339
47372
  field(
47340
- "Chart",
47373
+ layout2,
47374
+ layout2 === "host" ? "Type" : "Chart",
47341
47375
  select(
47376
+ layout2,
47342
47377
  "chart-type-select",
47343
47378
  CHART_TYPES,
47344
47379
  resolved.chartType,
@@ -47348,6 +47383,7 @@ function renderToolbar(state, callbacks) {
47348
47383
  );
47349
47384
  const candidates = categoryCandidates(columns);
47350
47385
  const categorySelect = select(
47386
+ layout2,
47351
47387
  "chart-category-select",
47352
47388
  candidates.map((c) => ({ value: c.name, label: columnLabel(c) })),
47353
47389
  (_a2 = resolved.category) != null ? _a2 : "",
@@ -47361,8 +47397,9 @@ function renderToolbar(state, callbacks) {
47361
47397
  }
47362
47398
  );
47363
47399
  categorySelect.disabled = isHistogram || candidates.length === 0;
47364
- toolbar.appendChild(
47400
+ fields.push(
47365
47401
  field(
47402
+ layout2,
47366
47403
  isPie ? "Slices" : resolved.chartType === "horizontal-bar" ? "Y axis" : "X axis",
47367
47404
  categorySelect
47368
47405
  )
@@ -47371,8 +47408,12 @@ function renderToolbar(state, callbacks) {
47371
47408
  const valuesPicker = document.createElement("details");
47372
47409
  valuesPicker.className = "chart-values-picker";
47373
47410
  const summary = document.createElement("summary");
47374
- summary.className = "chart-toolbar-select";
47375
- summary.textContent = resolved.values.length > 0 ? resolved.values.join(", ") : "None";
47411
+ summary.className = layout2 === "host" ? "chart-values-summary" : "chart-toolbar-select chart-values-summary";
47412
+ const summaryText = document.createElement("span");
47413
+ summaryText.className = "chart-values-summary-text";
47414
+ summaryText.textContent = resolved.values.length > 0 ? resolved.values.join(", ") : "None";
47415
+ summary.appendChild(summaryText);
47416
+ summary.appendChild(icon("chevron-down", 14));
47376
47417
  valuesPicker.appendChild(summary);
47377
47418
  const list = document.createElement("div");
47378
47419
  list.className = "chart-values-list";
@@ -47403,18 +47444,32 @@ function renderToolbar(state, callbacks) {
47403
47444
  list.appendChild(item);
47404
47445
  }
47405
47446
  valuesPicker.appendChild(list);
47406
- toolbar.appendChild(field(isHistogram ? "Value" : isPie ? "Size" : "Values", valuesPicker));
47447
+ fields.push(
47448
+ field(
47449
+ layout2,
47450
+ isHistogram ? "Value" : isPie ? "Size" : "Values",
47451
+ valuesPicker,
47452
+ layout2 === "host" ? "div" : "label"
47453
+ )
47454
+ );
47407
47455
  const seriesOptions = [{ value: "", label: "None" }].concat(
47408
47456
  candidates.filter((c) => c.name !== resolved.category && !resolved.values.includes(c.name)).map((c) => ({ value: c.name, label: columnLabel(c) }))
47409
47457
  );
47410
47458
  const seriesSelect = select(
47459
+ layout2,
47411
47460
  "chart-series-select",
47412
47461
  seriesOptions,
47413
47462
  (_b2 = resolved.series) != null ? _b2 : "",
47414
47463
  (value) => callbacks.onChange({ ...current(), series: value })
47415
47464
  );
47416
47465
  seriesSelect.disabled = isHistogram || isPie || seriesOptions.length <= 1;
47417
- toolbar.appendChild(field("Series", seriesSelect));
47466
+ fields.push(field(layout2, "Series", seriesSelect));
47467
+ return fields;
47468
+ }
47469
+ function renderToolbar(state, callbacks) {
47470
+ const toolbar = document.createElement("div");
47471
+ toolbar.className = "chart-toolbar";
47472
+ for (const el of renderPickers("own", state, callbacks)) toolbar.appendChild(el);
47418
47473
  if (state.customised) {
47419
47474
  toolbar.appendChild(
47420
47475
  button(
@@ -47446,6 +47501,130 @@ function renderToolbar(state, callbacks) {
47446
47501
  );
47447
47502
  return toolbar;
47448
47503
  }
47504
+ function menuItem(className, iconName, text, title, onClick) {
47505
+ const el = document.createElement("button");
47506
+ el.type = "button";
47507
+ el.className = `chart-view-settings-item ${className}`;
47508
+ el.title = title;
47509
+ el.appendChild(icon(iconName));
47510
+ const label = document.createElement("span");
47511
+ label.textContent = text;
47512
+ el.appendChild(label);
47513
+ el.addEventListener("click", onClick);
47514
+ return el;
47515
+ }
47516
+ function renderViewSettings(state, callbacks) {
47517
+ const wrapper = document.createElement("div");
47518
+ wrapper.className = "chart-view-settings";
47519
+ const menuId = `chart-view-settings-menu-${++menuCounter}`;
47520
+ const toggle = document.createElement("button");
47521
+ toggle.type = "button";
47522
+ toggle.className = "yasr_toolbarButton chart-view-settings-button";
47523
+ toggle.setAttribute("aria-haspopup", "true");
47524
+ toggle.setAttribute("aria-expanded", "false");
47525
+ toggle.setAttribute("aria-controls", menuId);
47526
+ toggle.appendChild(icon("sliders-horizontal"));
47527
+ const text = document.createElement("span");
47528
+ text.textContent = "View settings";
47529
+ toggle.appendChild(text);
47530
+ const menu = document.createElement("div");
47531
+ menu.className = "chart-view-settings-menu";
47532
+ menu.id = menuId;
47533
+ menu.setAttribute("role", "group");
47534
+ menu.setAttribute("aria-label", "View settings");
47535
+ menu.hidden = true;
47536
+ const setOpen = (open) => {
47537
+ menu.hidden = !open;
47538
+ toggle.setAttribute("aria-expanded", String(open));
47539
+ toggle.classList.toggle("is-active", open);
47540
+ };
47541
+ const run = (action) => () => {
47542
+ setOpen(false);
47543
+ action();
47544
+ };
47545
+ const reset = menuItem(
47546
+ "chart-reset-button",
47547
+ "rotate-ccw",
47548
+ "Automatic chart",
47549
+ "Go back to the automatic chart for these results",
47550
+ run(callbacks.onReset)
47551
+ );
47552
+ reset.disabled = !state.customised;
47553
+ menu.appendChild(reset);
47554
+ const separator = document.createElement("div");
47555
+ separator.className = "chart-view-settings-separator";
47556
+ separator.setAttribute("role", "separator");
47557
+ menu.appendChild(separator);
47558
+ menu.appendChild(
47559
+ menuItem(
47560
+ "chart-export-png",
47561
+ "download",
47562
+ "Download PNG",
47563
+ "Download the chart as a PNG image",
47564
+ run(() => callbacks.onExport("png"))
47565
+ )
47566
+ );
47567
+ menu.appendChild(
47568
+ menuItem(
47569
+ "chart-export-svg",
47570
+ "download",
47571
+ "Download SVG",
47572
+ "Download the chart as an SVG image",
47573
+ run(() => callbacks.onExport("svg"))
47574
+ )
47575
+ );
47576
+ toggle.addEventListener("click", () => setOpen(menu.hidden));
47577
+ wrapper.addEventListener("keydown", (e2) => {
47578
+ if (e2.key === "Escape" && !menu.hidden) {
47579
+ e2.stopPropagation();
47580
+ setOpen(false);
47581
+ toggle.focus();
47582
+ }
47583
+ });
47584
+ wrapper.appendChild(toggle);
47585
+ wrapper.appendChild(menu);
47586
+ return wrapper;
47587
+ }
47588
+ function renderHostToolbar(slot, state, callbacks) {
47589
+ const group = document.createElement("div");
47590
+ group.className = "yasr_toolbarGroup chart-toolbar-pickers";
47591
+ for (const el of renderPickers("host", state, callbacks)) group.appendChild(el);
47592
+ const spacer = document.createElement("div");
47593
+ spacer.className = "yasr_toolbarSpacer";
47594
+ const nodes = [group, spacer, renderViewSettings(state, callbacks)];
47595
+ for (const node of nodes) slot.appendChild(node);
47596
+ return nodes;
47597
+ }
47598
+ function closeToolbarPopups(root, target) {
47599
+ root.querySelectorAll(".chart-values-picker[open]").forEach((picker) => {
47600
+ if (!target || !picker.contains(target)) picker.removeAttribute("open");
47601
+ });
47602
+ root.querySelectorAll(".chart-view-settings").forEach((wrapper) => {
47603
+ const menu = wrapper.querySelector(".chart-view-settings-menu");
47604
+ if (!menu || menu.hidden || target && wrapper.contains(target)) return;
47605
+ menu.hidden = true;
47606
+ const toggle = wrapper.querySelector(".chart-view-settings-button");
47607
+ toggle == null ? void 0 : toggle.setAttribute("aria-expanded", "false");
47608
+ toggle == null ? void 0 : toggle.classList.remove("is-active");
47609
+ });
47610
+ }
47611
+
47612
+ // src/host.ts
47613
+ function hasHostDescribe(yasr) {
47614
+ var _a2;
47615
+ return !!((_a2 = yasr == null ? void 0 : yasr.hostApi) == null ? void 0 : _a2.describe) && typeof yasr.describe === "function";
47616
+ }
47617
+ function getHostToolbar(yasr) {
47618
+ var _a2;
47619
+ if (!((_a2 = yasr == null ? void 0 : yasr.hostApi) == null ? void 0 : _a2.toolbar) || typeof yasr.getPluginToolbar !== "function") return null;
47620
+ try {
47621
+ const slot = yasr.getPluginToolbar();
47622
+ return slot instanceof HTMLElement ? slot : null;
47623
+ } catch (error2) {
47624
+ console.warn("yasgui-chart-plugin: could not get the plugin toolbar", error2);
47625
+ return null;
47626
+ }
47627
+ }
47449
47628
 
47450
47629
  // src/theme.ts
47451
47630
  var LIGHT_PALETTE = [
@@ -47472,6 +47651,10 @@ var DARK_PALETTE = [
47472
47651
  "#ef8cc8",
47473
47652
  "#9aa8bb"
47474
47653
  ];
47654
+ var BRAND_LIGHT = "#0563bb";
47655
+ var BRAND_DARK = "#5aa8f2";
47656
+ var HIGHLIGHT_LIGHT = "#f2b300";
47657
+ var HIGHLIGHT_DARK = "#f5c242";
47475
47658
  function getCurrentTheme() {
47476
47659
  if (typeof document === "undefined") return "light";
47477
47660
  return document.documentElement.getAttribute("data-theme") === "dark" ? "dark" : "light";
@@ -47487,7 +47670,11 @@ function getThemeColors() {
47487
47670
  border: read("--yasgui-border-color", dark ? "#444444" : "#d0d0d0"),
47488
47671
  background: read("--yasgui-bg-primary", dark ? "#1e1e1e" : "#ffffff"),
47489
47672
  tooltipBackground: read("--yasgui-bg-secondary", dark ? "#2a2a2a" : "#ffffff"),
47490
- palette: dark ? DARK_PALETTE : LIGHT_PALETTE
47673
+ palette: [
47674
+ read("--yasgui-brand", dark ? BRAND_DARK : BRAND_LIGHT),
47675
+ ...(dark ? DARK_PALETTE : LIGHT_PALETTE).slice(1)
47676
+ ],
47677
+ highlight: read("--yasgui-highlight", dark ? HIGHLIGHT_DARK : HIGHLIGHT_LIGHT)
47491
47678
  };
47492
47679
  }
47493
47680
  function watchThemeChanges(callback) {
@@ -50367,7 +50554,8 @@ var DescribeModal = class {
50367
50554
  title.title = uri;
50368
50555
  const closeButton = document.createElement("button");
50369
50556
  closeButton.className = "chart-modal-close";
50370
- closeButton.innerHTML = "&times;";
50557
+ closeButton.type = "button";
50558
+ closeButton.appendChild(icon("x", 20));
50371
50559
  closeButton.setAttribute("aria-label", "Close modal");
50372
50560
  closeButton.addEventListener("click", () => this.close());
50373
50561
  header.appendChild(this.createNavigation());
@@ -50389,7 +50577,7 @@ var DescribeModal = class {
50389
50577
  hint.textContent = "Ctrl+click a URI to describe it, Ctrl+Shift+click for the triples where it is the object.";
50390
50578
  const copyButton = document.createElement("button");
50391
50579
  copyButton.className = "chart-modal-button";
50392
- copyButton.textContent = "Copy Raw";
50580
+ copyButton.textContent = "Copy raw";
50393
50581
  copyButton.addEventListener("click", () => {
50394
50582
  const rawText = payload.state === "results" ? payload.result.raw : payload.state === "error" ? payload.raw : "";
50395
50583
  this.copyToClipboard(rawText);
@@ -50428,11 +50616,11 @@ var DescribeModal = class {
50428
50616
  createNavigation() {
50429
50617
  const nav = document.createElement("div");
50430
50618
  nav.className = "chart-describe-modal-nav";
50431
- const button2 = (className, text, label, enabled, onClick) => {
50619
+ const button2 = (className, iconName, label, enabled, onClick) => {
50432
50620
  const btn = document.createElement("button");
50433
50621
  btn.type = "button";
50434
50622
  btn.className = `chart-describe-modal-nav-button ${className}`;
50435
- btn.textContent = text;
50623
+ btn.appendChild(icon(iconName));
50436
50624
  btn.title = label;
50437
50625
  btn.setAttribute("aria-label", label);
50438
50626
  btn.disabled = !enabled;
@@ -50442,19 +50630,25 @@ var DescribeModal = class {
50442
50630
  nav.appendChild(
50443
50631
  button2(
50444
50632
  "chart-describe-modal-start",
50445
- "\u23EE",
50633
+ "chevrons-left",
50446
50634
  "Back to start",
50447
50635
  this.canGoBack(),
50448
50636
  () => this.backToStart()
50449
50637
  )
50450
50638
  );
50451
50639
  nav.appendChild(
50452
- button2("chart-describe-modal-back", "\u25C0", "Back (Alt+\u2190)", this.canGoBack(), () => this.back())
50640
+ button2(
50641
+ "chart-describe-modal-back",
50642
+ "chevron-left",
50643
+ "Back (Alt+\u2190)",
50644
+ this.canGoBack(),
50645
+ () => this.back()
50646
+ )
50453
50647
  );
50454
50648
  nav.appendChild(
50455
50649
  button2(
50456
50650
  "chart-describe-modal-forward",
50457
- "\u25B6",
50651
+ "chevron-right",
50458
50652
  "Forward (Alt+\u2192)",
50459
50653
  this.canGoForward(),
50460
50654
  () => this.forward()
@@ -50677,7 +50871,7 @@ use([
50677
50871
  ]);
50678
50872
  var DEFAULT_MAX_ROWS = 5e3;
50679
50873
  var MIN_CHART_HEIGHT = 320;
50680
- 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>';
50874
+ var ICON_SVG = iconSvg("chart-column");
50681
50875
  var ChartPlugin = class {
50682
50876
  constructor(yasr, options = {}) {
50683
50877
  /** Below the table (10), so SELECT results still open in the table */
@@ -50697,6 +50891,9 @@ var ChartPlugin = class {
50697
50891
  this.outsideClickHandler = null;
50698
50892
  this.windowResizeHandler = null;
50699
50893
  this.fullscreenObserver = null;
50894
+ /** Elements this plugin put in the host's toolbar slot */
50895
+ this.hostToolbarNodes = [];
50896
+ /** @deprecated Own describe modal, used only when the host has no shared describe panel */
50700
50897
  this.describeModal = null;
50701
50898
  this.describeAbortController = null;
50702
50899
  var _a2, _b2, _c2;
@@ -50711,11 +50908,11 @@ var ChartPlugin = class {
50711
50908
  return 5;
50712
50909
  }
50713
50910
  getIcon() {
50714
- const icon = document.createElement("div");
50715
- icon.innerHTML = ICON_SVG;
50716
- icon.setAttribute("role", "img");
50717
- icon.setAttribute("aria-label", "Chart view");
50718
- return icon;
50911
+ const icon2 = document.createElement("div");
50912
+ icon2.innerHTML = ICON_SVG;
50913
+ icon2.setAttribute("role", "img");
50914
+ icon2.setAttribute("aria-label", "Chart view");
50915
+ return icon2;
50719
50916
  }
50720
50917
  /** Offered for SELECT results with at least one numeric column */
50721
50918
  canHandleResults() {
@@ -50792,20 +50989,23 @@ var ChartPlugin = class {
50792
50989
  this.data = buildChartData(rows, this.columns, this.resolved, this.getPrefixes());
50793
50990
  const wrapper = document.createElement("div");
50794
50991
  wrapper.className = "yasgui-chart-plugin";
50795
- wrapper.appendChild(
50796
- renderToolbar(
50797
- {
50798
- columns: this.columns,
50799
- resolved: this.resolved,
50800
- customised: Object.keys(this.saved).length > 0
50801
- },
50802
- {
50803
- onChange: (settings) => this.updateSettings(settings),
50804
- onReset: () => this.updateSettings({}),
50805
- onExport: (format2) => this.exportImage(format2)
50806
- }
50807
- )
50808
- );
50992
+ const toolbarState = {
50993
+ columns: this.columns,
50994
+ resolved: this.resolved,
50995
+ customised: Object.keys(this.saved).length > 0
50996
+ };
50997
+ const toolbarCallbacks = {
50998
+ onChange: (settings) => this.updateSettings(settings),
50999
+ onReset: () => this.updateSettings({}),
51000
+ onExport: (format2) => this.exportImage(format2)
51001
+ };
51002
+ const slot = getHostToolbar(this.yasr);
51003
+ if (slot) {
51004
+ this.hostToolbarNodes = renderHostToolbar(slot, toolbarState, toolbarCallbacks);
51005
+ } else {
51006
+ wrapper.classList.add("chart-own-toolbar");
51007
+ wrapper.appendChild(renderToolbar(toolbarState, toolbarCallbacks));
51008
+ }
50809
51009
  const notes = [];
50810
51010
  if (allRows.length > maxRows) {
50811
51011
  notes.push(
@@ -50856,11 +51056,9 @@ var ChartPlugin = class {
50856
51056
  this.fullscreenObserver.observe(yasrRoot, { attributes: true, attributeFilter: ["class"] });
50857
51057
  }
50858
51058
  this.themeObserver = watchThemeChanges(() => this.applyOption());
51059
+ const popupRoot = slot || wrapper;
50859
51060
  this.outsideClickHandler = (e2) => {
50860
- const picker = wrapper.querySelector(".chart-values-picker");
50861
- if (picker && picker.hasAttribute("open") && !picker.contains(e2.target)) {
50862
- picker.removeAttribute("open");
50863
- }
51061
+ closeToolbarPopups(popupRoot, e2.target);
50864
51062
  };
50865
51063
  document.addEventListener("mousedown", this.outsideClickHandler);
50866
51064
  }
@@ -50902,15 +51100,37 @@ var ChartPlugin = class {
50902
51100
  if (!iri) return;
50903
51101
  this.runResourceQuery(iri, event.shiftKey ? "object" : "subject");
50904
51102
  }
51103
+ /**
51104
+ * Show the triples of `uri`: in the host's shared describe panel when YASR
51105
+ * offers one, otherwise in the plugin's own describe modal.
51106
+ */
51107
+ runResourceQuery(uri, direction) {
51108
+ if (hasHostDescribe(this.yasr)) {
51109
+ const hostDirection = direction === "object" ? "incoming" : "outgoing";
51110
+ const fail = (error2) => console.error("yasgui-chart-plugin: describe failed", uri, error2);
51111
+ try {
51112
+ Promise.resolve(
51113
+ this.yasr.describe(uri, { direction: hostDirection, source: "Chart" })
51114
+ ).catch(fail);
51115
+ } catch (error2) {
51116
+ fail(error2);
51117
+ }
51118
+ return;
51119
+ }
51120
+ void this.runOwnResourceQuery(uri, direction);
51121
+ }
50905
51122
  /**
50906
51123
  * Run a background query for the triples where `iri` is the subject (or
50907
- * object) and show them in the describe modal, as the table and geo plugins do.
51124
+ * object) and show them in the plugin's own describe modal.
51125
+ *
51126
+ * @deprecated Fallback for YASR versions without `yasr.describe()`; it will be
51127
+ * removed in the next major version.
50908
51128
  */
50909
- async runResourceQuery(uri, direction, newHistory = true) {
51129
+ async runOwnResourceQuery(uri, direction, newHistory = true) {
50910
51130
  var _a2, _b2, _c2, _d2;
50911
51131
  if (!this.describeModal) {
50912
51132
  this.describeModal = new DescribeModal({
50913
- onDescribe: (u, d) => this.runResourceQuery(u, d, false)
51133
+ onDescribe: (u, d) => this.runOwnResourceQuery(u, d, false)
50914
51134
  });
50915
51135
  }
50916
51136
  if (typeof this.yasr.executeQuery !== "function") {
@@ -51029,6 +51249,8 @@ var ChartPlugin = class {
51029
51249
  this.chart.dispose();
51030
51250
  this.chart = null;
51031
51251
  }
51252
+ for (const node of this.hostToolbarNodes) node.remove();
51253
+ this.hostToolbarNodes = [];
51032
51254
  this.chartEl = null;
51033
51255
  this.option = null;
51034
51256
  }