@datawheel/data-explorer 0.3.7 → 0.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.d.mts CHANGED
@@ -371,6 +371,7 @@ interface QueryItem {
371
371
  key: string;
372
372
  label: string;
373
373
  panel: string | null;
374
+ chart: string | null;
374
375
  params: QueryParams;
375
376
  result: QueryResult;
376
377
  }
@@ -732,6 +733,8 @@ declare const defaultTranslation: {
732
733
  };
733
734
  vizbuilder: {
734
735
  action_close: string;
736
+ action_share: string;
737
+ share_copied: string;
735
738
  action_enlarge: string;
736
739
  action_fileissue: string;
737
740
  action_retry: string;
@@ -1024,6 +1027,7 @@ declare const actions: {
1024
1027
  selectQuery: _reduxjs_toolkit.ActionCreatorWithPayload<string, "explorerQueries/selectQuery">;
1025
1028
  updateQuery: _reduxjs_toolkit.ActionCreatorWithPayload<QueryItem, "explorerQueries/updateQuery">;
1026
1029
  switchPanel: _reduxjs_toolkit.ActionCreatorWithPayload<string | null, "explorerQueries/switchPanel">;
1030
+ updateChart: _reduxjs_toolkit.ActionCreatorWithPayload<string | null, "explorerQueries/updateChart">;
1027
1031
  removeCut: _reduxjs_toolkit.ActionCreatorWithPayload<string, "explorerQueries/removeCut">;
1028
1032
  removeDrilldown: _reduxjs_toolkit.ActionCreatorWithPayload<string, "explorerQueries/removeDrilldown">;
1029
1033
  removeMeasure: _reduxjs_toolkit.ActionCreatorWithPayload<string, "explorerQueries/removeMeasure">;
package/dist/main.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { keyframes, createStyles, Select, rem, Input, Box, Text, Stack, Group, Button, SimpleGrid, Flex, ScrollArea, LoadingOverlay, Table, MultiSelect, Center, NumberInput, Menu, ActionIcon, UnstyledButton, Alert, Loader, Container, Title, useMantineTheme, MantineProvider, Modal, useComponentDefaultProps, Anchor, Paper, CloseButton, Tooltip, Tabs, Switch, ThemeIcon, packSx, Affix, Accordion, Drawer, Divider, Checkbox, Popover } from '@mantine/core';
2
2
  import { useClipboard, useDebouncedState, useClickOutside, useFullscreen, useMediaQuery, useDisclosure } from '@mantine/hooks';
3
- import { IconWorld, IconExternalLink, IconClipboard, IconSettings, IconMathGreater, IconMathLower, IconArrowsLeftRight, IconAlertCircle, IconAlertTriangle, IconCopy, IconDownload, IconDotsVertical, IconArrowRight, IconArrowLeft, IconBrandGithub, IconChevronLeft, IconChevronRight, IconSearch, IconLanguage, IconTrash, IconInfoCircleFilled, IconArrowsMinimize, IconArrowsMaximize, IconCircleOff, IconArrowsSort, IconSortDescendingNumbers, IconSortDescendingLetters, IconSortAscendingNumbers, IconSortAscendingLetters, IconPlus, IconStack3, IconFilterOff, IconFilter, IconAdjustments, IconBox, IconClock, IconHelpCircle, IconPhotoDown, IconVectorTriangle } from '@tabler/icons-react';
3
+ import { IconWorld, IconExternalLink, IconClipboard, IconSettings, IconMathGreater, IconMathLower, IconArrowsLeftRight, IconAlertCircle, IconAlertTriangle, IconCopy, IconDownload, IconDotsVertical, IconArrowRight, IconArrowLeft, IconBrandGithub, IconCheck, IconShare, IconChevronLeft, IconChevronRight, IconSearch, IconLanguage, IconTrash, IconInfoCircleFilled, IconArrowsMinimize, IconArrowsMaximize, IconCircleOff, IconArrowsSort, IconSortDescendingNumbers, IconSortDescendingLetters, IconSortAscendingNumbers, IconSortAscendingLetters, IconPlus, IconStack3, IconFilterOff, IconFilter, IconAdjustments, IconBox, IconClock, IconHelpCircle, IconPhotoDown, IconVectorTriangle } from '@tabler/icons-react';
4
4
  import * as React19 from 'react';
5
5
  import React19__default, { createContext, forwardRef, useMemo, useCallback, useContext, useRef, useEffect, useState, Suspense, Component, useLayoutEffect } from 'react';
6
6
  import { translationFactory } from '@datawheel/use-translation';
@@ -443,6 +443,8 @@ var defaultTranslation = {
443
443
  },
444
444
  vizbuilder: {
445
445
  action_close: "Close",
446
+ action_share: "Share",
447
+ share_copied: "Copied",
446
448
  action_enlarge: "Enlarge",
447
449
  action_fileissue: "Report an issue",
448
450
  action_retry: "Retry",
@@ -639,6 +641,7 @@ function buildQuery(props) {
639
641
  label: props.label || "",
640
642
  isDirty: true,
641
643
  panel: props.panel || null,
644
+ chart: props.chart || null,
642
645
  params: buildQueryParams(props.params || {}),
643
646
  result: {
644
647
  data: [],
@@ -1236,6 +1239,10 @@ var queriesSlice = createSlice({
1236
1239
  const current = state.itemMap[state.current];
1237
1240
  current.panel = action.payload;
1238
1241
  },
1242
+ updateChart(state, action) {
1243
+ const current = state.itemMap[state.current];
1244
+ current.chart = action.payload;
1245
+ },
1239
1246
  /**
1240
1247
  * Remove a single CutItem from the current QueryItem.
1241
1248
  */
@@ -1699,13 +1706,18 @@ function serializePermalink(item) {
1699
1706
  Object.entries(request).filter((entry) => entry[1] != null && entry[1] !== "")
1700
1707
  );
1701
1708
  search.set("panel", item.panel || "table");
1709
+ if (item.chart !== "" && item.chart) {
1710
+ search.set("chart", item.chart);
1711
+ }
1702
1712
  return search.toString();
1703
1713
  }
1704
1714
  function parsePermalink(cube, value) {
1705
1715
  const search = new URLSearchParams(value);
1706
1716
  const params = requestToQueryParams(cube, search);
1717
+ console.log(search.get("chart"));
1707
1718
  return buildQuery({
1708
1719
  panel: search.get("panel") || "table",
1720
+ chart: search.get("chart") || "",
1709
1721
  params
1710
1722
  });
1711
1723
  }
@@ -1732,7 +1744,8 @@ function usePermalink(isEnabled, options) {
1732
1744
  if (currPermalink !== nextPermalink) {
1733
1745
  const nextLocation = `${window.location.pathname}?${nextPermalink}`;
1734
1746
  const oldPanel = new URLSearchParams(window.location.search).get("panel");
1735
- if (oldPanel && oldPanel[1] !== panel) {
1747
+ const oldChart = new URLSearchParams(window.location.search).get("chart");
1748
+ if (oldPanel && oldPanel[1] !== panel || oldChart && oldChart[1] !== queryItem.chart) {
1736
1749
  window.history.replaceState(queryItem, "", nextLocation);
1737
1750
  } else {
1738
1751
  window.history.pushState(queryItem, "", nextLocation);
@@ -1761,6 +1774,7 @@ function useUpdatePermaLink({
1761
1774
  }
1762
1775
  function useKey(params = {}) {
1763
1776
  const queryItem = useSelector(selectCurrentQueryItem);
1777
+ console.log(queryItem);
1764
1778
  if (isValidQuery(queryItem.params)) {
1765
1779
  return serializePermalink({ ...queryItem, params: { ...queryItem.params, ...params } });
1766
1780
  }
@@ -2007,6 +2021,7 @@ function willParseQueryUrl(url) {
2007
2021
  const params = requestToQueryParams(cubeMap[cube], search);
2008
2022
  const queryItem = buildQuery({
2009
2023
  panel: search.get("panel") || "table",
2024
+ chart: search.get("chart") || "",
2010
2025
  // params: {...params, drilldowns: keyBy(dds, "key")}
2011
2026
  params
2012
2027
  });
@@ -2659,6 +2674,13 @@ var Graph = class {
2659
2674
  this.nodes = /* @__PURE__ */ new Set([]);
2660
2675
  this.adjList = {};
2661
2676
  this.items = [];
2677
+ this.topicOrder = {};
2678
+ }
2679
+ addTopicOrder(topic, order) {
2680
+ this.topicOrder[topic] = Number(order);
2681
+ }
2682
+ getTopicOrder(topic) {
2683
+ return this.topicOrder[topic] || 0;
2662
2684
  }
2663
2685
  addNode(node) {
2664
2686
  this.nodes.add(node);
@@ -2920,6 +2942,7 @@ function useBuildGraph(locale) {
2920
2942
  const filteredItems = items.map((item) => {
2921
2943
  const { name: name4 } = item;
2922
2944
  const topic = getAnnotation(item, "topic", locale);
2945
+ const topic_order = getAnnotation(item, "topic_order", locale);
2923
2946
  const subtopic = getAnnotation(item, "subtopic", locale);
2924
2947
  getAnnotation(item, "table", locale);
2925
2948
  const hide = getAnnotation(item, "hide_in_ui", locale);
@@ -2929,6 +2952,9 @@ function useBuildGraph(locale) {
2929
2952
  graph2.addNode(name4);
2930
2953
  graph2.addEdge(topic, subtopic);
2931
2954
  graph2.addEdge(subtopic, name4);
2955
+ if (topic_order) {
2956
+ graph2.addTopicOrder(topic, topic_order);
2957
+ }
2932
2958
  return item;
2933
2959
  }
2934
2960
  return null;
@@ -3401,7 +3427,7 @@ function RootAccordions({ items, graph, locale, selectedItem, onSelectCube }) {
3401
3427
  }
3402
3428
  })
3403
3429
  },
3404
- items.map((item) => {
3430
+ items.sort((a, b) => graph.topicOrder[a] - graph.topicOrder[b]).map((item) => {
3405
3431
  return /* @__PURE__ */ React19__default.createElement(Accordion.Item, { value: `topic-${item}`, key: `topic-${item}` }, /* @__PURE__ */ React19__default.createElement(AccordionControl, null, item), /* @__PURE__ */ React19__default.createElement(Accordion.Panel, null, /* @__PURE__ */ React19__default.createElement(
3406
3432
  SubtopicAccordion,
3407
3433
  {
@@ -8168,7 +8194,6 @@ function _buildTitle(t, chart) {
8168
8194
  const [mainSeries, otherSeries] = series;
8169
8195
  const { measure } = values;
8170
8196
  const timeline = chart.timeline || chart.time;
8171
- console.log({ chart });
8172
8197
  const seriesStr = (series2) => {
8173
8198
  if (!series2) return "";
8174
8199
  const { members } = series2.captions[series2.level.name];
@@ -8290,8 +8315,6 @@ function IssueButton(props) {
8290
8315
  t("vizbuilder.action_fileissue")
8291
8316
  );
8292
8317
  }
8293
-
8294
- // src/vizbuilder/components/ChartCard.tsx
8295
8318
  var iconByFormat = {
8296
8319
  jpg: IconPhotoDown,
8297
8320
  png: IconPhotoDown,
@@ -8307,6 +8330,8 @@ function ChartCard(props) {
8307
8330
  getMeasureConfig: props.measureConfig,
8308
8331
  t: translate
8309
8332
  });
8333
+ const clipboard = useClipboard();
8334
+ const [isShared, setIsShared] = useState(false);
8310
8335
  const downloadButtons = useMemo(() => {
8311
8336
  const filename = (typeof config.title === "function" ? config.title() : config.title || "").replace(/[^\w]/g, "_").replace(/[_]+/g, "_");
8312
8337
  return asArray(downloadFormats).map((format2) => {
@@ -8350,9 +8375,27 @@ function ChartCard(props) {
8350
8375
  isFullMode ? translate("vizbuilder.action_close") : translate("vizbuilder.action_enlarge")
8351
8376
  );
8352
8377
  }, [isFullMode, translate, onFocus]);
8378
+ const shareButton = useMemo(() => {
8379
+ return /* @__PURE__ */ React19__default.createElement(
8380
+ Button,
8381
+ {
8382
+ compact: true,
8383
+ leftIcon: isShared ? /* @__PURE__ */ React19__default.createElement(IconCheck, { size: 16 }) : /* @__PURE__ */ React19__default.createElement(IconShare, { size: 16 }),
8384
+ onClick: () => {
8385
+ clipboard.copy(window.location.href);
8386
+ setIsShared(true);
8387
+ setTimeout(() => setIsShared(false), 1500);
8388
+ },
8389
+ size: "sm",
8390
+ variant: isShared ? "filled" : "light",
8391
+ color: isShared ? "green" : "blue"
8392
+ },
8393
+ isShared ? translate("vizbuilder.share_copied") : translate("vizbuilder.action_share")
8394
+ );
8395
+ }, [clipboard, translate, isShared]);
8353
8396
  const height = isFullMode ? "calc(100vh - 3rem)" : 300;
8354
8397
  if (!ChartComponent) return null;
8355
- return /* @__PURE__ */ React19__default.createElement(Paper, { h: height, w: "100%", style: { overflow: "hidden" } }, /* @__PURE__ */ React19__default.createElement(ErrorBoundary, null, /* @__PURE__ */ React19__default.createElement(Stack, { spacing: 0, h: height, style: { position: "relative" }, w: "100%" }, /* @__PURE__ */ React19__default.createElement(Group, { position: "right", p: "xs", spacing: "xs", align: "center" }, downloadButtons, onFocus && focusButton), /* @__PURE__ */ React19__default.createElement(Box, { style: { flex: "1 1 auto" }, ref: nodeRef, pb: "xs", px: "xs" }, /* @__PURE__ */ React19__default.createElement(ChartComponent, { config })))));
8398
+ return /* @__PURE__ */ React19__default.createElement(Paper, { h: height, w: "100%", style: { overflow: "hidden" } }, /* @__PURE__ */ React19__default.createElement(ErrorBoundary, null, /* @__PURE__ */ React19__default.createElement(Stack, { spacing: 0, h: height, style: { position: "relative" }, w: "100%" }, /* @__PURE__ */ React19__default.createElement(Group, { position: "right", p: "xs", spacing: "xs", align: "center" }, isFullMode && shareButton, downloadButtons, onFocus && focusButton), /* @__PURE__ */ React19__default.createElement(Box, { style: { flex: "1 1 auto" }, ref: nodeRef, pb: "xs", px: "xs" }, /* @__PURE__ */ React19__default.createElement(ChartComponent, { config })))));
8356
8399
  }
8357
8400
  var getBackground = (node) => {
8358
8401
  if (node.nodeType !== Node.ELEMENT_NODE) return "white";
@@ -8374,8 +8417,6 @@ function NonIdealState2(props) {
8374
8417
  }, [status, t]);
8375
8418
  return /* @__PURE__ */ React19__default.createElement(Center, { h: "100%" }, description);
8376
8419
  }
8377
-
8378
- // src/vizbuilder/components/Vizbuilder.tsx
8379
8420
  function Vizbuilder(props) {
8380
8421
  const {
8381
8422
  datasets,
@@ -8389,7 +8430,12 @@ function Vizbuilder(props) {
8389
8430
  topojsonConfig,
8390
8431
  userConfig
8391
8432
  } = props;
8392
- const [currentChart, setCurrentChart] = useState("");
8433
+ const queryItem = useSelector$1(selectCurrentQueryItem);
8434
+ const currentChart = (queryItem == null ? void 0 : queryItem.chart) || "";
8435
+ const { actions: actions2 } = useSettings();
8436
+ const setCurrentChart = useCallback((chart) => {
8437
+ actions2.updateChart(chart);
8438
+ }, [actions2]);
8393
8439
  const getMeasureConfig = useMemo(() => {
8394
8440
  const config = measureConfig || {};
8395
8441
  return typeof config === "function" ? config : (item) => config[item.name];
@@ -8407,7 +8453,6 @@ function Vizbuilder(props) {
8407
8453
  });
8408
8454
  return Object.fromEntries(charts2.map((chart) => [chart.key, chart]));
8409
8455
  }, [chartLimits, chartTypes, datacap, datasets, getTopojsonConfig]);
8410
- console.log("charts", charts);
8411
8456
  const content = useMemo(() => {
8412
8457
  const Notice = nonIdealState || NonIdealState2;
8413
8458
  const isLoading = asArray(datasets).some(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datawheel/data-explorer",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "main": "./dist/main.mjs",
5
5
  "types": "./dist/main.d.mts",
6
6
  "files": [