@matdata/yasgui-chart-plugin 1.0.0 → 1.2.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,29 @@ 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
+ square: '<rect width="18" height="18" x="3" y="3" rx="2"/>',
47207
+ "square-check": '<rect width="18" height="18" x="3" y="3" rx="2"/><path d="m9 12 2 2 4-4"/>',
47208
+ "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"/>'
47209
+ };
47210
+ function iconSvg(name, size = 16, strokeWidth = 1.75) {
47211
+ 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>`;
47212
+ }
47213
+ function icon(name, size, strokeWidth) {
47214
+ const template = document.createElement("template");
47215
+ template.innerHTML = iconSvg(name, size, strokeWidth);
47216
+ return template.content.firstElementChild;
47217
+ }
47218
+
47184
47219
  // src/settings.ts
47185
47220
  var CHART_TYPES = [
47186
47221
  { value: "bar", label: "Bar" },
@@ -47209,12 +47244,19 @@ function sanitizeSettings(raw) {
47209
47244
  if (typeof r.series === "string") settings.series = r.series;
47210
47245
  if (Array.isArray(r.columns))
47211
47246
  settings.columns = r.columns.filter((v) => typeof v === "string");
47247
+ if (typeof r.shortenIris === "boolean") settings.shortenIris = r.shortenIris;
47212
47248
  return settings;
47213
47249
  }
47250
+ function isCustomised(saved) {
47251
+ return Object.keys(saved).some((key) => key !== "columns" && key !== "shortenIris");
47252
+ }
47253
+ function displayOptions(saved) {
47254
+ return saved.shortenIris === void 0 ? {} : { shortenIris: saved.shortenIris };
47255
+ }
47214
47256
  function settingsForColumns(saved, vars) {
47215
47257
  if (!saved.columns) return saved;
47216
47258
  const same = saved.columns.length === vars.length && saved.columns.every((v, i) => v === vars[i]);
47217
- return same ? saved : {};
47259
+ return same ? saved : displayOptions(saved);
47218
47260
  }
47219
47261
  function categoryCandidates(columns) {
47220
47262
  return columns.filter((c) => !c.isLabel && c.bound > 0);
@@ -47283,9 +47325,10 @@ var KIND_LABEL = {
47283
47325
  iri: "IRI",
47284
47326
  text: "text"
47285
47327
  };
47286
- function field(labelText, control) {
47287
- const wrapper = document.createElement("label");
47288
- wrapper.className = "chart-toolbar-field";
47328
+ var menuCounter = 0;
47329
+ function field(layout2, labelText, control, tag = "label") {
47330
+ const wrapper = document.createElement(tag);
47331
+ wrapper.className = layout2 === "host" ? "yasr_toolbarSelect chart-toolbar-field" : "chart-toolbar-field";
47289
47332
  const label = document.createElement("span");
47290
47333
  label.className = "chart-toolbar-label";
47291
47334
  label.textContent = labelText;
@@ -47293,9 +47336,9 @@ function field(labelText, control) {
47293
47336
  wrapper.appendChild(control);
47294
47337
  return wrapper;
47295
47338
  }
47296
- function select(className, options, value, onChange) {
47339
+ function select(layout2, className, options, value, onChange) {
47297
47340
  const el = document.createElement("select");
47298
- el.className = `chart-toolbar-select ${className}`;
47341
+ el.className = layout2 === "host" ? className : `chart-toolbar-select ${className}`;
47299
47342
  for (const o of options) {
47300
47343
  const option = document.createElement("option");
47301
47344
  option.value = o.value;
@@ -47319,11 +47362,10 @@ function button(className, text, title, onClick) {
47319
47362
  function columnLabel(c) {
47320
47363
  return `${c.name} (${KIND_LABEL[c.kind]})`;
47321
47364
  }
47322
- function renderToolbar(state, callbacks) {
47365
+ function renderPickers(layout2, state, callbacks) {
47323
47366
  var _a2, _b2;
47324
47367
  const { columns, resolved } = state;
47325
- const toolbar = document.createElement("div");
47326
- toolbar.className = "chart-toolbar";
47368
+ const fields = [];
47327
47369
  const current = () => {
47328
47370
  var _a3, _b3;
47329
47371
  return {
@@ -47335,10 +47377,12 @@ function renderToolbar(state, callbacks) {
47335
47377
  };
47336
47378
  const isHistogram = resolved.chartType === "histogram";
47337
47379
  const isPie = resolved.chartType === "pie" || resolved.chartType === "donut";
47338
- toolbar.appendChild(
47380
+ fields.push(
47339
47381
  field(
47340
- "Chart",
47382
+ layout2,
47383
+ layout2 === "host" ? "Type" : "Chart",
47341
47384
  select(
47385
+ layout2,
47342
47386
  "chart-type-select",
47343
47387
  CHART_TYPES,
47344
47388
  resolved.chartType,
@@ -47348,6 +47392,7 @@ function renderToolbar(state, callbacks) {
47348
47392
  );
47349
47393
  const candidates = categoryCandidates(columns);
47350
47394
  const categorySelect = select(
47395
+ layout2,
47351
47396
  "chart-category-select",
47352
47397
  candidates.map((c) => ({ value: c.name, label: columnLabel(c) })),
47353
47398
  (_a2 = resolved.category) != null ? _a2 : "",
@@ -47361,8 +47406,9 @@ function renderToolbar(state, callbacks) {
47361
47406
  }
47362
47407
  );
47363
47408
  categorySelect.disabled = isHistogram || candidates.length === 0;
47364
- toolbar.appendChild(
47409
+ fields.push(
47365
47410
  field(
47411
+ layout2,
47366
47412
  isPie ? "Slices" : resolved.chartType === "horizontal-bar" ? "Y axis" : "X axis",
47367
47413
  categorySelect
47368
47414
  )
@@ -47371,8 +47417,12 @@ function renderToolbar(state, callbacks) {
47371
47417
  const valuesPicker = document.createElement("details");
47372
47418
  valuesPicker.className = "chart-values-picker";
47373
47419
  const summary = document.createElement("summary");
47374
- summary.className = "chart-toolbar-select";
47375
- summary.textContent = resolved.values.length > 0 ? resolved.values.join(", ") : "None";
47420
+ summary.className = layout2 === "host" ? "chart-values-summary" : "chart-toolbar-select chart-values-summary";
47421
+ const summaryText = document.createElement("span");
47422
+ summaryText.className = "chart-values-summary-text";
47423
+ summaryText.textContent = resolved.values.length > 0 ? resolved.values.join(", ") : "None";
47424
+ summary.appendChild(summaryText);
47425
+ summary.appendChild(icon("chevron-down", 14));
47376
47426
  valuesPicker.appendChild(summary);
47377
47427
  const list = document.createElement("div");
47378
47428
  list.className = "chart-values-list";
@@ -47403,18 +47453,32 @@ function renderToolbar(state, callbacks) {
47403
47453
  list.appendChild(item);
47404
47454
  }
47405
47455
  valuesPicker.appendChild(list);
47406
- toolbar.appendChild(field(isHistogram ? "Value" : isPie ? "Size" : "Values", valuesPicker));
47456
+ fields.push(
47457
+ field(
47458
+ layout2,
47459
+ isHistogram ? "Value" : isPie ? "Size" : "Values",
47460
+ valuesPicker,
47461
+ layout2 === "host" ? "div" : "label"
47462
+ )
47463
+ );
47407
47464
  const seriesOptions = [{ value: "", label: "None" }].concat(
47408
47465
  candidates.filter((c) => c.name !== resolved.category && !resolved.values.includes(c.name)).map((c) => ({ value: c.name, label: columnLabel(c) }))
47409
47466
  );
47410
47467
  const seriesSelect = select(
47468
+ layout2,
47411
47469
  "chart-series-select",
47412
47470
  seriesOptions,
47413
47471
  (_b2 = resolved.series) != null ? _b2 : "",
47414
47472
  (value) => callbacks.onChange({ ...current(), series: value })
47415
47473
  );
47416
47474
  seriesSelect.disabled = isHistogram || isPie || seriesOptions.length <= 1;
47417
- toolbar.appendChild(field("Series", seriesSelect));
47475
+ fields.push(field(layout2, "Series", seriesSelect));
47476
+ return fields;
47477
+ }
47478
+ function renderToolbar(state, callbacks) {
47479
+ const toolbar = document.createElement("div");
47480
+ toolbar.className = "chart-toolbar";
47481
+ for (const el of renderPickers("own", state, callbacks)) toolbar.appendChild(el);
47418
47482
  if (state.customised) {
47419
47483
  toolbar.appendChild(
47420
47484
  button(
@@ -47428,6 +47492,14 @@ function renderToolbar(state, callbacks) {
47428
47492
  const spacer = document.createElement("div");
47429
47493
  spacer.className = "chart-toolbar-spacer";
47430
47494
  toolbar.appendChild(spacer);
47495
+ const shorten = button(
47496
+ "chart-shorten-iris",
47497
+ "Prefixes",
47498
+ "Show IRIs as prefixed names",
47499
+ () => callbacks.onShortenIris(!state.shortenIris)
47500
+ );
47501
+ shorten.setAttribute("aria-pressed", String(state.shortenIris));
47502
+ toolbar.appendChild(shorten);
47431
47503
  toolbar.appendChild(
47432
47504
  button(
47433
47505
  "chart-export-png",
@@ -47446,6 +47518,140 @@ function renderToolbar(state, callbacks) {
47446
47518
  );
47447
47519
  return toolbar;
47448
47520
  }
47521
+ function menuItem(className, iconName, text, title, onClick) {
47522
+ const el = document.createElement("button");
47523
+ el.type = "button";
47524
+ el.className = `chart-view-settings-item ${className}`;
47525
+ el.title = title;
47526
+ el.appendChild(icon(iconName));
47527
+ const label = document.createElement("span");
47528
+ label.textContent = text;
47529
+ el.appendChild(label);
47530
+ el.addEventListener("click", onClick);
47531
+ return el;
47532
+ }
47533
+ function renderViewSettings(state, callbacks) {
47534
+ const wrapper = document.createElement("div");
47535
+ wrapper.className = "chart-view-settings";
47536
+ const menuId = `chart-view-settings-menu-${++menuCounter}`;
47537
+ const toggle = document.createElement("button");
47538
+ toggle.type = "button";
47539
+ toggle.className = "yasr_toolbarButton chart-view-settings-button";
47540
+ toggle.setAttribute("aria-haspopup", "true");
47541
+ toggle.setAttribute("aria-expanded", "false");
47542
+ toggle.setAttribute("aria-controls", menuId);
47543
+ toggle.appendChild(icon("sliders-horizontal"));
47544
+ const text = document.createElement("span");
47545
+ text.textContent = "View settings";
47546
+ toggle.appendChild(text);
47547
+ const menu = document.createElement("div");
47548
+ menu.className = "chart-view-settings-menu";
47549
+ menu.id = menuId;
47550
+ menu.setAttribute("role", "group");
47551
+ menu.setAttribute("aria-label", "View settings");
47552
+ menu.hidden = true;
47553
+ const setOpen = (open) => {
47554
+ menu.hidden = !open;
47555
+ toggle.setAttribute("aria-expanded", String(open));
47556
+ toggle.classList.toggle("is-active", open);
47557
+ };
47558
+ const run = (action) => () => {
47559
+ setOpen(false);
47560
+ action();
47561
+ };
47562
+ const reset = menuItem(
47563
+ "chart-reset-button",
47564
+ "rotate-ccw",
47565
+ "Automatic chart",
47566
+ "Go back to the automatic chart for these results",
47567
+ run(callbacks.onReset)
47568
+ );
47569
+ reset.disabled = !state.customised;
47570
+ menu.appendChild(reset);
47571
+ const shorten = menuItem(
47572
+ "chart-shorten-iris",
47573
+ state.shortenIris ? "square-check" : "square",
47574
+ "Shorten IRIs with prefixes",
47575
+ "Show IRIs as prefixed names, such as ex:Germany",
47576
+ run(() => callbacks.onShortenIris(!state.shortenIris))
47577
+ );
47578
+ shorten.setAttribute("role", "menuitemcheckbox");
47579
+ shorten.setAttribute("aria-checked", String(state.shortenIris));
47580
+ menu.appendChild(shorten);
47581
+ const separator = document.createElement("div");
47582
+ separator.className = "chart-view-settings-separator";
47583
+ separator.setAttribute("role", "separator");
47584
+ menu.appendChild(separator);
47585
+ menu.appendChild(
47586
+ menuItem(
47587
+ "chart-export-png",
47588
+ "download",
47589
+ "Download PNG",
47590
+ "Download the chart as a PNG image",
47591
+ run(() => callbacks.onExport("png"))
47592
+ )
47593
+ );
47594
+ menu.appendChild(
47595
+ menuItem(
47596
+ "chart-export-svg",
47597
+ "download",
47598
+ "Download SVG",
47599
+ "Download the chart as an SVG image",
47600
+ run(() => callbacks.onExport("svg"))
47601
+ )
47602
+ );
47603
+ toggle.addEventListener("click", () => setOpen(menu.hidden));
47604
+ wrapper.addEventListener("keydown", (e2) => {
47605
+ if (e2.key === "Escape" && !menu.hidden) {
47606
+ e2.stopPropagation();
47607
+ setOpen(false);
47608
+ toggle.focus();
47609
+ }
47610
+ });
47611
+ wrapper.appendChild(toggle);
47612
+ wrapper.appendChild(menu);
47613
+ return wrapper;
47614
+ }
47615
+ function renderHostToolbar(slot, state, callbacks) {
47616
+ const group = document.createElement("div");
47617
+ group.className = "yasr_toolbarGroup chart-toolbar-pickers";
47618
+ for (const el of renderPickers("host", state, callbacks)) group.appendChild(el);
47619
+ const spacer = document.createElement("div");
47620
+ spacer.className = "yasr_toolbarSpacer";
47621
+ const nodes = [group, spacer, renderViewSettings(state, callbacks)];
47622
+ for (const node of nodes) slot.appendChild(node);
47623
+ return nodes;
47624
+ }
47625
+ function closeToolbarPopups(root, target) {
47626
+ root.querySelectorAll(".chart-values-picker[open]").forEach((picker) => {
47627
+ if (!target || !picker.contains(target)) picker.removeAttribute("open");
47628
+ });
47629
+ root.querySelectorAll(".chart-view-settings").forEach((wrapper) => {
47630
+ const menu = wrapper.querySelector(".chart-view-settings-menu");
47631
+ if (!menu || menu.hidden || target && wrapper.contains(target)) return;
47632
+ menu.hidden = true;
47633
+ const toggle = wrapper.querySelector(".chart-view-settings-button");
47634
+ toggle == null ? void 0 : toggle.setAttribute("aria-expanded", "false");
47635
+ toggle == null ? void 0 : toggle.classList.remove("is-active");
47636
+ });
47637
+ }
47638
+
47639
+ // src/host.ts
47640
+ function hasHostDescribe(yasr) {
47641
+ var _a2;
47642
+ return !!((_a2 = yasr == null ? void 0 : yasr.hostApi) == null ? void 0 : _a2.describe) && typeof yasr.describe === "function";
47643
+ }
47644
+ function getHostToolbar(yasr) {
47645
+ var _a2;
47646
+ if (!((_a2 = yasr == null ? void 0 : yasr.hostApi) == null ? void 0 : _a2.toolbar) || typeof yasr.getPluginToolbar !== "function") return null;
47647
+ try {
47648
+ const slot = yasr.getPluginToolbar();
47649
+ return slot instanceof HTMLElement ? slot : null;
47650
+ } catch (error2) {
47651
+ console.warn("yasgui-chart-plugin: could not get the plugin toolbar", error2);
47652
+ return null;
47653
+ }
47654
+ }
47449
47655
 
47450
47656
  // src/theme.ts
47451
47657
  var LIGHT_PALETTE = [
@@ -47472,6 +47678,10 @@ var DARK_PALETTE = [
47472
47678
  "#ef8cc8",
47473
47679
  "#9aa8bb"
47474
47680
  ];
47681
+ var BRAND_LIGHT = "#0563bb";
47682
+ var BRAND_DARK = "#5aa8f2";
47683
+ var HIGHLIGHT_LIGHT = "#f2b300";
47684
+ var HIGHLIGHT_DARK = "#f5c242";
47475
47685
  function getCurrentTheme() {
47476
47686
  if (typeof document === "undefined") return "light";
47477
47687
  return document.documentElement.getAttribute("data-theme") === "dark" ? "dark" : "light";
@@ -47487,7 +47697,11 @@ function getThemeColors() {
47487
47697
  border: read("--yasgui-border-color", dark ? "#444444" : "#d0d0d0"),
47488
47698
  background: read("--yasgui-bg-primary", dark ? "#1e1e1e" : "#ffffff"),
47489
47699
  tooltipBackground: read("--yasgui-bg-secondary", dark ? "#2a2a2a" : "#ffffff"),
47490
- palette: dark ? DARK_PALETTE : LIGHT_PALETTE
47700
+ palette: [
47701
+ read("--yasgui-brand", dark ? BRAND_DARK : BRAND_LIGHT),
47702
+ ...(dark ? DARK_PALETTE : LIGHT_PALETTE).slice(1)
47703
+ ],
47704
+ highlight: read("--yasgui-highlight", dark ? HIGHLIGHT_DARK : HIGHLIGHT_LIGHT)
47491
47705
  };
47492
47706
  }
47493
47707
  function watchThemeChanges(callback) {
@@ -50367,7 +50581,8 @@ var DescribeModal = class {
50367
50581
  title.title = uri;
50368
50582
  const closeButton = document.createElement("button");
50369
50583
  closeButton.className = "chart-modal-close";
50370
- closeButton.innerHTML = "&times;";
50584
+ closeButton.type = "button";
50585
+ closeButton.appendChild(icon("x", 20));
50371
50586
  closeButton.setAttribute("aria-label", "Close modal");
50372
50587
  closeButton.addEventListener("click", () => this.close());
50373
50588
  header.appendChild(this.createNavigation());
@@ -50389,7 +50604,7 @@ var DescribeModal = class {
50389
50604
  hint.textContent = "Ctrl+click a URI to describe it, Ctrl+Shift+click for the triples where it is the object.";
50390
50605
  const copyButton = document.createElement("button");
50391
50606
  copyButton.className = "chart-modal-button";
50392
- copyButton.textContent = "Copy Raw";
50607
+ copyButton.textContent = "Copy raw";
50393
50608
  copyButton.addEventListener("click", () => {
50394
50609
  const rawText = payload.state === "results" ? payload.result.raw : payload.state === "error" ? payload.raw : "";
50395
50610
  this.copyToClipboard(rawText);
@@ -50428,11 +50643,11 @@ var DescribeModal = class {
50428
50643
  createNavigation() {
50429
50644
  const nav = document.createElement("div");
50430
50645
  nav.className = "chart-describe-modal-nav";
50431
- const button2 = (className, text, label, enabled, onClick) => {
50646
+ const button2 = (className, iconName, label, enabled, onClick) => {
50432
50647
  const btn = document.createElement("button");
50433
50648
  btn.type = "button";
50434
50649
  btn.className = `chart-describe-modal-nav-button ${className}`;
50435
- btn.textContent = text;
50650
+ btn.appendChild(icon(iconName));
50436
50651
  btn.title = label;
50437
50652
  btn.setAttribute("aria-label", label);
50438
50653
  btn.disabled = !enabled;
@@ -50442,19 +50657,25 @@ var DescribeModal = class {
50442
50657
  nav.appendChild(
50443
50658
  button2(
50444
50659
  "chart-describe-modal-start",
50445
- "\u23EE",
50660
+ "chevrons-left",
50446
50661
  "Back to start",
50447
50662
  this.canGoBack(),
50448
50663
  () => this.backToStart()
50449
50664
  )
50450
50665
  );
50451
50666
  nav.appendChild(
50452
- button2("chart-describe-modal-back", "\u25C0", "Back (Alt+\u2190)", this.canGoBack(), () => this.back())
50667
+ button2(
50668
+ "chart-describe-modal-back",
50669
+ "chevron-left",
50670
+ "Back (Alt+\u2190)",
50671
+ this.canGoBack(),
50672
+ () => this.back()
50673
+ )
50453
50674
  );
50454
50675
  nav.appendChild(
50455
50676
  button2(
50456
50677
  "chart-describe-modal-forward",
50457
- "\u25B6",
50678
+ "chevron-right",
50458
50679
  "Forward (Alt+\u2192)",
50459
50680
  this.canGoForward(),
50460
50681
  () => this.forward()
@@ -50663,6 +50884,18 @@ var DescribeModal = class {
50663
50884
  };
50664
50885
 
50665
50886
  // src/ChartPlugin.ts
50887
+ var COMMON_PREFIXES = {
50888
+ rdf: "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
50889
+ rdfs: "http://www.w3.org/2000/01/rdf-schema#",
50890
+ owl: "http://www.w3.org/2002/07/owl#",
50891
+ xsd: "http://www.w3.org/2001/XMLSchema#",
50892
+ foaf: "http://xmlns.com/foaf/0.1/",
50893
+ dc: "http://purl.org/dc/elements/1.1/",
50894
+ dcterms: "http://purl.org/dc/terms/",
50895
+ skos: "http://www.w3.org/2004/02/skos/core#",
50896
+ schema: "http://schema.org/",
50897
+ wd: "http://www.wikidata.org/entity/"
50898
+ };
50666
50899
  use([
50667
50900
  install2,
50668
50901
  install,
@@ -50677,7 +50910,7 @@ use([
50677
50910
  ]);
50678
50911
  var DEFAULT_MAX_ROWS = 5e3;
50679
50912
  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>';
50913
+ var ICON_SVG = iconSvg("chart-column");
50681
50914
  var ChartPlugin = class {
50682
50915
  constructor(yasr, options = {}) {
50683
50916
  /** Below the table (10), so SELECT results still open in the table */
@@ -50697,6 +50930,9 @@ var ChartPlugin = class {
50697
50930
  this.outsideClickHandler = null;
50698
50931
  this.windowResizeHandler = null;
50699
50932
  this.fullscreenObserver = null;
50933
+ /** Elements this plugin put in the host's toolbar slot */
50934
+ this.hostToolbarNodes = [];
50935
+ /** @deprecated Own describe modal, used only when the host has no shared describe panel */
50700
50936
  this.describeModal = null;
50701
50937
  this.describeAbortController = null;
50702
50938
  var _a2, _b2, _c2;
@@ -50711,11 +50947,11 @@ var ChartPlugin = class {
50711
50947
  return 5;
50712
50948
  }
50713
50949
  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;
50950
+ const icon2 = document.createElement("div");
50951
+ icon2.innerHTML = ICON_SVG;
50952
+ icon2.setAttribute("role", "img");
50953
+ icon2.setAttribute("aria-label", "Chart view");
50954
+ return icon2;
50719
50955
  }
50720
50956
  /** Offered for SELECT results with at least one numeric column */
50721
50957
  canHandleResults() {
@@ -50779,6 +51015,14 @@ var ChartPlugin = class {
50779
51015
  }
50780
51016
  return prefixes;
50781
51017
  }
51018
+ /**
51019
+ * Prefixes used to show IRIs in the chart: well-known ones, then those of
51020
+ * Yasr and the query. None when the user turned shortening off.
51021
+ */
51022
+ getLabelPrefixes() {
51023
+ if (this.saved.shortenIris === false) return {};
51024
+ return { ...COMMON_PREFIXES, ...this.getPrefixes() };
51025
+ }
50782
51026
  /** Build the toolbar and chart for the current results and settings */
50783
51027
  render() {
50784
51028
  var _a2;
@@ -50789,23 +51033,28 @@ var ChartPlugin = class {
50789
51033
  const allRows = this.results.results.bindings;
50790
51034
  const rows = allRows.length > maxRows ? allRows.slice(0, maxRows) : allRows;
50791
51035
  this.resolved = resolveSettings(this.columns, this.saved, rows.length);
50792
- this.data = buildChartData(rows, this.columns, this.resolved, this.getPrefixes());
51036
+ this.data = buildChartData(rows, this.columns, this.resolved, this.getLabelPrefixes());
50793
51037
  const wrapper = document.createElement("div");
50794
51038
  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
- );
51039
+ const toolbarState = {
51040
+ columns: this.columns,
51041
+ resolved: this.resolved,
51042
+ customised: isCustomised(this.saved),
51043
+ shortenIris: this.saved.shortenIris !== false
51044
+ };
51045
+ const toolbarCallbacks = {
51046
+ onChange: (settings) => this.updateSettings({ ...displayOptions(this.saved), ...settings }),
51047
+ onReset: () => this.updateSettings(displayOptions(this.saved)),
51048
+ onShortenIris: (shortenIris) => this.updateSettings({ ...this.saved, shortenIris }),
51049
+ onExport: (format2) => this.exportImage(format2)
51050
+ };
51051
+ const slot = getHostToolbar(this.yasr);
51052
+ if (slot) {
51053
+ this.hostToolbarNodes = renderHostToolbar(slot, toolbarState, toolbarCallbacks);
51054
+ } else {
51055
+ wrapper.classList.add("chart-own-toolbar");
51056
+ wrapper.appendChild(renderToolbar(toolbarState, toolbarCallbacks));
51057
+ }
50809
51058
  const notes = [];
50810
51059
  if (allRows.length > maxRows) {
50811
51060
  notes.push(
@@ -50856,11 +51105,9 @@ var ChartPlugin = class {
50856
51105
  this.fullscreenObserver.observe(yasrRoot, { attributes: true, attributeFilter: ["class"] });
50857
51106
  }
50858
51107
  this.themeObserver = watchThemeChanges(() => this.applyOption());
51108
+ const popupRoot = slot || wrapper;
50859
51109
  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
- }
51110
+ closeToolbarPopups(popupRoot, e2.target);
50864
51111
  };
50865
51112
  document.addEventListener("mousedown", this.outsideClickHandler);
50866
51113
  }
@@ -50883,8 +51130,7 @@ var ChartPlugin = class {
50883
51130
  }
50884
51131
  updateSettings(settings) {
50885
51132
  this.saved = sanitizeSettings(settings);
50886
- if (Object.keys(this.saved).length > 0 && this.results)
50887
- this.saved.columns = [...this.results.head.vars];
51133
+ if (isCustomised(this.saved) && this.results) this.saved.columns = [...this.results.head.vars];
50888
51134
  if (typeof this.yasr.storePluginConfig === "function") {
50889
51135
  try {
50890
51136
  this.yasr.storePluginConfig(this.getPluginName(), this.saved);
@@ -50902,15 +51148,37 @@ var ChartPlugin = class {
50902
51148
  if (!iri) return;
50903
51149
  this.runResourceQuery(iri, event.shiftKey ? "object" : "subject");
50904
51150
  }
51151
+ /**
51152
+ * Show the triples of `uri`: in the host's shared describe panel when YASR
51153
+ * offers one, otherwise in the plugin's own describe modal.
51154
+ */
51155
+ runResourceQuery(uri, direction) {
51156
+ if (hasHostDescribe(this.yasr)) {
51157
+ const hostDirection = direction === "object" ? "incoming" : "outgoing";
51158
+ const fail = (error2) => console.error("yasgui-chart-plugin: describe failed", uri, error2);
51159
+ try {
51160
+ Promise.resolve(
51161
+ this.yasr.describe(uri, { direction: hostDirection, source: "Chart" })
51162
+ ).catch(fail);
51163
+ } catch (error2) {
51164
+ fail(error2);
51165
+ }
51166
+ return;
51167
+ }
51168
+ void this.runOwnResourceQuery(uri, direction);
51169
+ }
50905
51170
  /**
50906
51171
  * 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.
51172
+ * object) and show them in the plugin's own describe modal.
51173
+ *
51174
+ * @deprecated Fallback for YASR versions without `yasr.describe()`; it will be
51175
+ * removed in the next major version.
50908
51176
  */
50909
- async runResourceQuery(uri, direction, newHistory = true) {
51177
+ async runOwnResourceQuery(uri, direction, newHistory = true) {
50910
51178
  var _a2, _b2, _c2, _d2;
50911
51179
  if (!this.describeModal) {
50912
51180
  this.describeModal = new DescribeModal({
50913
- onDescribe: (u, d) => this.runResourceQuery(u, d, false)
51181
+ onDescribe: (u, d) => this.runOwnResourceQuery(u, d, false)
50914
51182
  });
50915
51183
  }
50916
51184
  if (typeof this.yasr.executeQuery !== "function") {
@@ -51029,6 +51297,8 @@ var ChartPlugin = class {
51029
51297
  this.chart.dispose();
51030
51298
  this.chart = null;
51031
51299
  }
51300
+ for (const node of this.hostToolbarNodes) node.remove();
51301
+ this.hostToolbarNodes = [];
51032
51302
  this.chartEl = null;
51033
51303
  this.option = null;
51034
51304
  }