@datawheel/data-explorer 1.1.16 → 1.2.0-rc.1

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
@@ -782,6 +782,12 @@ declare const defaultTranslation: {
782
782
  time_range: string;
783
783
  total: string;
784
784
  };
785
+ transient: {
786
+ title_one_row: string;
787
+ title_loading: string;
788
+ title_empty: string;
789
+ description_empty: string;
790
+ };
785
791
  }>;
786
792
  action_copy: string;
787
793
  action_copy_done: string;
package/dist/main.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import { createStyles, keyframes, Select, Center, Text, rem, Input, Box, Stack, Group, Button, SimpleGrid, Flex, ScrollArea, LoadingOverlay as LoadingOverlay$1, Table, MultiSelect, NumberInput, Menu, ActionIcon, UnstyledButton, Loader, Container, Title, useMantineTheme, TextInput, CopyButton, MantineProvider, Space, Modal, Alert, Paper, Tooltip, useComponentDefaultProps, Skeleton, Anchor, packSx, CloseButton, Tabs, ThemeIcon, Drawer, Switch, Divider, Accordion, Popover, Checkbox } from '@mantine/core';
2
2
  import { useClipboard, useDebouncedState, useMediaQuery, useFullscreen, useDisclosure } from '@mantine/hooks';
3
- import { IconWorld, IconExternalLink, IconClipboard, IconSettings, IconMathGreater, IconMathLower, IconArrowsLeftRight, IconWorldWww, IconClipboardCheck, IconCircleOff, IconAlertCircle, IconAlertTriangle, IconVectorTriangle, IconPhotoDown, IconDownload, IconArrowsMinimize, IconArrowsMaximize, IconCheck, IconShare, IconLanguage, IconCopy, IconBrandGithub, IconArrowLeft, IconArrowRight, IconX, IconChevronLeft, IconChevronRight, IconSearch, IconBox, IconDotsVertical, IconTrash, IconPlus, IconStack3, IconInfoCircleFilled, IconArrowsSort, IconSortDescendingNumbers, IconSortDescendingLetters, IconSortAscendingNumbers, IconSortAscendingLetters, IconHelpCircle, IconFilterOff, IconFilter, IconClock, IconAdjustments } from '@tabler/icons-react';
3
+ import { IconWorld, IconExternalLink, IconClipboard, IconSettings, IconMathGreater, IconMathLower, IconArrowsLeftRight, IconWorldWww, IconClipboardCheck, IconCircleOff, IconAlertCircle, IconAlertTriangle, IconBrandGithub, IconVectorTriangle, IconPhotoDown, IconDownload, IconArrowsMinimize, IconArrowsMaximize, IconCheck, IconShare, IconLanguage, IconCopy, IconArrowLeft, IconArrowRight, IconX, IconChevronLeft, IconChevronRight, IconSearch, IconBox, IconDotsVertical, IconTrash, IconPlus, IconStack3, IconInfoCircleFilled, IconArrowsSort, IconSortDescendingNumbers, IconSortDescendingLetters, IconSortAscendingNumbers, IconSortAscendingLetters, IconHelpCircle, IconFilterOff, IconFilter, IconClock, IconAdjustments } from '@tabler/icons-react';
4
4
  import * as React21 from 'react';
5
- import React21__default, { createContext, forwardRef, useMemo, useCallback, useContext, useRef, useEffect, useState, Component, Suspense, useLayoutEffect } from 'react';
5
+ import React21__default, { createContext, forwardRef, useMemo, useCallback, useContext, useRef, useEffect, useState, Suspense, useLayoutEffect } from 'react';
6
6
  import { translationFactory } from '@datawheel/use-translation';
7
- import { VizbuilderProvider, useVizbuilderContext, d3plusConfigBuilder } from '@datawheel/vizbuilder/react';
7
+ import { VizbuilderProvider, useVizbuilderContext, ErrorBoundary, d3plusConfigBuilder } from '@datawheel/vizbuilder/react';
8
8
  import { createSlice, createSelector, combineReducers, configureStore, bindActionCreators } from '@reduxjs/toolkit';
9
9
  import { assign } from 'd3plus-common';
10
10
  import identity2 from 'lodash-es/identity';
@@ -1990,11 +1990,11 @@ function QueryProvider({ children, defaultCube }) {
1990
1990
  if (currentDrilldown && currentDrilldown.members && currentDrilldown.members.length > 0 && !localeChanged && cube === queryItem.params.cube) {
1991
1991
  return Promise.resolve({
1992
1992
  drilldown: currentDrilldown,
1993
- cut: buildCut({ ...currentDrilldown, active: false })
1993
+ cut: buildCut({ ...currentDrilldown, active: false, members: [] })
1994
1994
  });
1995
1995
  } else {
1996
1996
  return fetchMembers(dd.level, newQuery == null ? void 0 : newQuery.params.locale, cube).then((levelMeta) => {
1997
- const cut = buildCut({ ...dd, active: false });
1997
+ const cut = buildCut({ ...dd, active: false, members: [] });
1998
1998
  return {
1999
1999
  drilldown: {
2000
2000
  ...dd,
@@ -2234,7 +2234,7 @@ function ChartCard(props) {
2234
2234
  const { chart, isFullMode, onFocus, height } = props;
2235
2235
  const { dataset } = chart.datagroup;
2236
2236
  const { translate } = useVizbuilderTranslation();
2237
- const { downloadFormats, ErrorBoundary: ErrorBoundary2, showConfidenceInt } = useVizbuilderContext();
2237
+ const { downloadFormats, showConfidenceInt, CardErrorComponent } = useVizbuilderContext();
2238
2238
  const nodeRef = useRef(null);
2239
2239
  const { ref: inViewRef, inView } = useInView({ triggerOnce: false, threshold: 0 });
2240
2240
  const [hasBeenInView, setHasBeenInView] = useState(false);
@@ -2253,6 +2253,7 @@ function ChartCard(props) {
2253
2253
  t: translate
2254
2254
  });
2255
2255
  const downloadButtons = useMemo(() => {
2256
+ if (!config) return null;
2256
2257
  const filename = (typeof config.title === "function" ? config.title(dataset) : config.title || "").replace(/[^\w]/g, "_").replace(/[_]+/g, "_");
2257
2258
  return downloadFormats.map((format2) => {
2258
2259
  const formatLower = format2.toLowerCase();
@@ -2309,24 +2310,16 @@ function ChartCard(props) {
2309
2310
  ));
2310
2311
  }, [translate]);
2311
2312
  const resolvedHeight = height ? height : isFullMode ? "calc(100vh - 3rem)" : 400;
2312
- if (!ChartComponent) return null;
2313
- return /* @__PURE__ */ React21__default.createElement(
2313
+ if (!ChartComponent || !config) return null;
2314
+ return /* @__PURE__ */ React21__default.createElement(ErrorBoundary, { ErrorContent: CardErrorComponent }, /* @__PURE__ */ React21__default.createElement(
2314
2315
  Paper,
2315
2316
  {
2316
2317
  className: props.className,
2317
2318
  w: "100%",
2318
2319
  style: { overflow: "hidden", height: resolvedHeight, ...props.style }
2319
2320
  },
2320
- /* @__PURE__ */ React21__default.createElement(ErrorBoundary2, null, /* @__PURE__ */ React21__default.createElement(Stack, { spacing: "xs", p: "xs", style: { position: "relative" }, h: "100%", w: "100%" }, /* @__PURE__ */ React21__default.createElement(Group, { position: "center", spacing: "xs", align: "center" }, isFullMode && shareButton, downloadButtons, onFocus && focusButton), /* @__PURE__ */ React21__default.createElement(
2321
- Box,
2322
- {
2323
- style: { flex: "1 1 auto" },
2324
- ref: setRefs,
2325
- sx: { "& > .viz": { height: "100%" } }
2326
- },
2327
- ChartComponent && (inView || hasBeenInView) ? /* @__PURE__ */ React21__default.createElement(ChartComponent, { config }) : /* @__PURE__ */ React21__default.createElement("div", { style: { height: "100%", width: "100%" } })
2328
- )))
2329
- );
2321
+ /* @__PURE__ */ React21__default.createElement(Stack, { spacing: "xs", p: "xs", style: { position: "relative" }, h: "100%", w: "100%" }, /* @__PURE__ */ React21__default.createElement(Group, { position: "center", spacing: "xs", align: "center" }, isFullMode && shareButton, downloadButtons, onFocus && focusButton), /* @__PURE__ */ React21__default.createElement(Box, { style: { flex: "1 1 auto" }, ref: setRefs, sx: { "& > .viz": { height: "100%" } } }, ChartComponent && (inView || hasBeenInView) ? /* @__PURE__ */ React21__default.createElement(ChartComponent, { config }) : /* @__PURE__ */ React21__default.createElement("div", { style: { height: "100%", width: "100%" } })))
2322
+ ));
2330
2323
  }
2331
2324
  var getBackground = (node) => {
2332
2325
  if (node.nodeType !== Node.ELEMENT_NODE) return "white";
@@ -2377,14 +2370,7 @@ var useStyles = createStyles((theme) => ({
2377
2370
  function Vizbuilder(props) {
2378
2371
  const datasets = useMemo(() => asArray(props.datasets), [props.datasets]);
2379
2372
  const { t } = useVizbuilderTranslation();
2380
- const {
2381
- chartLimits,
2382
- chartTypes,
2383
- datacap,
2384
- getTopojsonConfig,
2385
- ErrorBoundary: ErrorBoundary2,
2386
- NonIdealState: NonIdealState3
2387
- } = useVizbuilderContext();
2373
+ const { chartLimits, chartTypes, datacap, getTopojsonConfig, NonIdealState: NonIdealState3 } = useVizbuilderContext();
2388
2374
  const { actions: actions2 } = useSettings();
2389
2375
  const queryItem = useSelector$1(selectCurrentQueryItem);
2390
2376
  const { classes, cx } = useStyles();
@@ -2412,14 +2398,10 @@ function Vizbuilder(props) {
2412
2398
  return /* @__PURE__ */ React21__default.createElement(Flex, { justify: "center", align: "center", direction: "column", w: "50%" }, /* @__PURE__ */ React21__default.createElement(IconCircleOff, { size: 92 }), /* @__PURE__ */ React21__default.createElement(Title, { mt: "md", mb: "md", order: 4 }, t("vizbuilder.transient.title_empty")), /* @__PURE__ */ React21__default.createElement(Text, null, t("transient.description_empty")));
2413
2399
  }
2414
2400
  const isSingleChart = chartList.length === 1;
2415
- return /* @__PURE__ */ React21__default.createElement(ErrorBoundary2, null, /* @__PURE__ */ React21__default.createElement("div", { className: cx(classes.grid, { [classes.fill]: isSingleChart }) }, chartList.map((chart2, idx) => {
2401
+ return /* @__PURE__ */ React21__default.createElement("div", { className: cx(classes.grid, { [classes.fill]: isSingleChart }) }, chartList.map((chart2, idx) => {
2416
2402
  let className = classes.fill;
2417
2403
  if (!isSingleChart) {
2418
- const names = [
2419
- classes.itemLarge,
2420
- classes.itemSmallTop,
2421
- classes.itemSmallBottom
2422
- ];
2404
+ const names = [classes.itemLarge, classes.itemSmallTop, classes.itemSmallBottom];
2423
2405
  className = names[idx % 3];
2424
2406
  }
2425
2407
  return /* @__PURE__ */ React21__default.createElement(
@@ -2432,8 +2414,8 @@ function Vizbuilder(props) {
2432
2414
  className
2433
2415
  }
2434
2416
  );
2435
- })));
2436
- }, [charts, classes, datasets, t, cx, ErrorBoundary2]);
2417
+ }));
2418
+ }, [charts, classes, datasets, t, cx]);
2437
2419
  const currentChart = (queryItem == null ? void 0 : queryItem.chart) || "";
2438
2420
  const chart = charts[currentChart];
2439
2421
  return /* @__PURE__ */ React21__default.createElement("div", { className: cls("vb-wrapper", classes.wrapper, props.className) }, props.customHeader, content, props.customFooter, /* @__PURE__ */ React21__default.createElement(
@@ -2505,72 +2487,6 @@ function VizbuilderView(props) {
2505
2487
  };
2506
2488
  return /* @__PURE__ */ React21__default.createElement(Vizbuilder, { datasets: dataset });
2507
2489
  }
2508
- var ErrorBoundary = class extends Component {
2509
- constructor() {
2510
- super(...arguments);
2511
- this.state = {
2512
- message: "",
2513
- name: ""
2514
- };
2515
- this.clearError = () => this.setState({ message: "", name: "" });
2516
- }
2517
- static getDerivedStateFromError(error) {
2518
- return { message: error.message, name: error.name };
2519
- }
2520
- render() {
2521
- const { message, name: name4 } = this.state;
2522
- if (!message) {
2523
- return this.props.children;
2524
- }
2525
- return /* @__PURE__ */ React21__default.createElement(TranslationConsumer, null, ({ translate: t }) => {
2526
- const detailText = t("vizbuilder.error.detail");
2527
- return /* @__PURE__ */ React21__default.createElement(
2528
- Flex,
2529
- {
2530
- p: "xl",
2531
- align: "center",
2532
- justify: "center",
2533
- direction: "column",
2534
- className: "chart-card error"
2535
- },
2536
- /* @__PURE__ */ React21__default.createElement(Title, { order: 3 }, t("vizbuilder.error.title")),
2537
- detailText.length ? /* @__PURE__ */ React21__default.createElement(Text, null, detailText) : null,
2538
- /* @__PURE__ */ React21__default.createElement(Text, null, t("vizbuilder.error.message", { message })),
2539
- /* @__PURE__ */ React21__default.createElement(Group, { spacing: "xs", my: "sm" }, /* @__PURE__ */ React21__default.createElement(Button, { onClick: this.clearError, size: "xs", variant: "light" }, t("vizbuilder.action_retry")), /* @__PURE__ */ React21__default.createElement(IssueButton, { error: name4, message }))
2540
- );
2541
- });
2542
- }
2543
- };
2544
- function IssueButton(props) {
2545
- const { error, message } = props;
2546
- const { t } = useVizbuilderTranslation();
2547
- const location2 = typeof window === "object" ? window.location : { href: "<SSR>" };
2548
- const issueParams = new URLSearchParams({
2549
- title: `[report/vizbuilder] ${error}`,
2550
- body: [
2551
- `**URL**: ${location2.href}`,
2552
- `**Error**: ${error}`,
2553
- message ? `**Error details:** ${message}
2554
- ` : "",
2555
- "**Detail of the issue:**\n"
2556
- ].join("\n")
2557
- });
2558
- return /* @__PURE__ */ React21__default.createElement(
2559
- Button,
2560
- {
2561
- component: "a",
2562
- href: `https://github.com/Datawheel/vizbuilder/issues/new?${issueParams}`,
2563
- leftIcon: /* @__PURE__ */ React21__default.createElement(IconBrandGithub, { size: "1rem" }),
2564
- rel: "noopener noreferrer",
2565
- role: "button",
2566
- size: "xs",
2567
- tabIndex: 0,
2568
- target: "_blank",
2569
- variant: "subtle"
2570
- },
2571
- t("action_fileissue")
2572
- );
2573
- }
2574
2490
  function NonIdealState(props) {
2575
2491
  const { status } = props;
2576
2492
  const { translate: t } = useTranslation();
@@ -3388,53 +3304,38 @@ function FullScreenSVG() {
3388
3304
  function isColumnSorted(column, key) {
3389
3305
  return column == key;
3390
3306
  }
3391
- var propertiesUpdateHandler = (actions2, item, activeProps) => {
3392
- const properties = item.properties.map(
3393
- (prop) => buildProperty({
3394
- ...prop,
3395
- active: activeProps.includes(prop.key)
3396
- })
3397
- );
3398
- actions2.updateDrilldown({ ...item, properties });
3399
- };
3400
- var removeColumn = (actions2, entity, measures, drilldowns, type, queryItem, updateURL) => {
3307
+ var removeColumn = (queryItem, entity) => {
3401
3308
  const newQuery = buildQuery(cloneDeep(queryItem));
3309
+ const params = newQuery.params;
3402
3310
  if ("aggregator" in entity) {
3403
- const measure = measures.find((d) => d.name === entity.name);
3311
+ const measure = params.measures[entity.name];
3404
3312
  if (measure) {
3405
- const newMeasure = { ...measure, active: false };
3406
- actions2.updateMeasure(newMeasure);
3407
- newQuery.params.measures[newMeasure.name] = newMeasure;
3408
- updateURL({
3409
- ...newQuery,
3410
- params: {
3411
- ...newQuery.params
3412
- }
3413
- });
3313
+ params.measures[entity.name] = { ...measure, active: false };
3314
+ return newQuery;
3414
3315
  }
3415
- }
3416
- if ("depth" in entity) {
3417
- const drilldown = drilldowns.find((d) => d.level === entity.name);
3316
+ } else if ("depth" in entity) {
3317
+ const cut = params.cuts[entity.name];
3318
+ if (cut) {
3319
+ params.cuts[cut.key] = { ...cut, active: false };
3320
+ }
3321
+ const drilldown = params.drilldowns[entity.name];
3418
3322
  if (drilldown) {
3419
- const newDrilldown = { ...drilldown, active: false };
3420
- actions2.updateDrilldown(newDrilldown);
3421
- newQuery.params.drilldowns[newDrilldown.key] = newDrilldown;
3422
- updateURL({
3423
- ...newQuery,
3424
- params: {
3425
- ...newQuery.params
3426
- }
3427
- });
3323
+ params.drilldowns[drilldown.key] = { ...drilldown, active: false };
3324
+ return newQuery;
3428
3325
  }
3429
- }
3430
- if (isProperty(type)) {
3431
- const activeDrilldowns = drilldowns.filter((d) => d.active);
3432
- const drilldown = activeDrilldowns.find(
3433
- (dd) => dd.properties.some((property) => property.name === entity.name)
3326
+ } else if ("level" in entity) {
3327
+ const mapPropertyToDrilldown = Object.fromEntries(
3328
+ Object.values(params.drilldowns).filter((drilldown2) => drilldown2.active).flatMap((drilldown2) => drilldown2.properties.map((prop) => [prop.name, drilldown2]))
3434
3329
  );
3435
- const activeProperties = drilldown == null ? void 0 : drilldown.properties.filter((p) => p.active).filter((p) => p.name !== entity.name).filter((p) => p.active).map((p) => p.name);
3436
- if (drilldown && activeProperties) {
3437
- propertiesUpdateHandler(actions2, drilldown, activeProperties);
3330
+ const drilldown = mapPropertyToDrilldown[entity.name];
3331
+ if (drilldown) {
3332
+ params.drilldowns[drilldown.key] = {
3333
+ ...drilldown,
3334
+ properties: drilldown.properties.map(
3335
+ (prop) => prop.name === entity.name ? { ...prop, active: false } : prop
3336
+ )
3337
+ };
3338
+ return newQuery;
3438
3339
  }
3439
3340
  }
3440
3341
  };
@@ -3738,15 +3639,11 @@ function useTable({
3738
3639
  key: `remove-${column2.columnDef.header}`,
3739
3640
  disabled: !showTrashIcon(finalKeys, entityType) || isLoading || isFetching,
3740
3641
  onClick: () => {
3741
- removeColumn(
3742
- actions2,
3743
- entity,
3744
- measures,
3745
- drilldowns,
3746
- entityType,
3747
- queryItem,
3748
- updateURL
3749
- );
3642
+ const nextQueryItem = removeColumn(queryItem, entity);
3643
+ if (nextQueryItem) {
3644
+ actions2.resetAllParams(nextQueryItem.params);
3645
+ updateURL(nextQueryItem);
3646
+ }
3750
3647
  },
3751
3648
  showTooltip: !showTrashIcon(finalKeys, entityType),
3752
3649
  size: 25,
@@ -4296,12 +4193,11 @@ function LevelItem({
4296
4193
  activeItems,
4297
4194
  depth = 0
4298
4195
  }) {
4299
- const [activeFilter, setActiveFilter] = useState(false);
4300
4196
  const [activePropertiesFilter, setActiveProperties] = useState(false);
4301
4197
  const { translate: t } = useTranslation();
4302
4198
  const actions2 = useActions();
4303
4199
  const cutItems = useSelector$1(selectCutItems);
4304
- let drilldowns = useSelector$1(selectDrilldownMap);
4200
+ const drilldowns = useSelector$1(selectDrilldownMap);
4305
4201
  useSelector$1(selectDrilldownItems);
4306
4202
  const { idFormatters } = useidFormatters();
4307
4203
  const label = useMemo(() => {
@@ -4324,12 +4220,7 @@ function LevelItem({
4324
4220
  const isOtherHierarchySelected = activeItems.some(
4325
4221
  (activeItem) => activeItem.dimension === dimension.name && activeItem.hierarchy !== hierarchy.name
4326
4222
  );
4327
- const cut = cutItems.find((cut2) => {
4328
- return cut2.level === (currentDrilldown == null ? void 0 : currentDrilldown.level);
4329
- });
4330
- const updatecutHandler = (item, members) => {
4331
- actions2.updateCut({ ...item, members });
4332
- };
4223
+ const cut = cutItems.find((cut2) => cut2.level === level.name);
4333
4224
  const checked = activeItems.map((i) => i.level).includes(level.name);
4334
4225
  const disableUncheck = activeItems.length === 1 && checked;
4335
4226
  const isDisabled = isOtherHierarchySelected && !checked;
@@ -4345,6 +4236,8 @@ function LevelItem({
4345
4236
  ...currentDrilldown,
4346
4237
  active: !currentDrilldown.active
4347
4238
  });
4239
+ if (cut && cut.members.length > 0)
4240
+ actions2.updateCut({ ...cut, active: !cut.active });
4348
4241
  },
4349
4242
  checked,
4350
4243
  label,
@@ -4356,22 +4249,28 @@ function LevelItem({
4356
4249
  {
4357
4250
  className: "dex-level-filter",
4358
4251
  size: "sm",
4359
- onClick: () => setActiveFilter((value) => !value),
4252
+ onClick: () => {
4253
+ const nextCut = buildCut(cut || level);
4254
+ if (cut == null ? void 0 : cut.active) {
4255
+ nextCut.active = false;
4256
+ actions2.updateCut(nextCut);
4257
+ } else {
4258
+ actions2.updateDrilldown({ ...currentDrilldown, active: true });
4259
+ nextCut.active = true;
4260
+ actions2.updateCut(nextCut);
4261
+ }
4262
+ },
4360
4263
  disabled: isDisabled
4361
4264
  },
4362
- activeFilter ? /* @__PURE__ */ React21__default.createElement(IconFilterOff, null) : /* @__PURE__ */ React21__default.createElement(IconFilter, null)
4363
- ), properties && /* @__PURE__ */ React21__default.createElement(Tooltip, { label: t("params.add_metadata") }, /* @__PURE__ */ React21__default.createElement(ActionIcon, { onClick: () => setActiveProperties((value) => !value) }, /* @__PURE__ */ React21__default.createElement(IconAdjustments, null))), /* @__PURE__ */ React21__default.createElement(ThemeIcon, { size: "xs", color: "gray", variant: "light", bg: "transparent" }, /* @__PURE__ */ React21__default.createElement(StackSVG, null)))), activeFilter && /* @__PURE__ */ React21__default.createElement(Box, { pt: "md" }, /* @__PURE__ */ React21__default.createElement(
4265
+ (cut == null ? void 0 : cut.active) ? /* @__PURE__ */ React21__default.createElement(IconFilterOff, null) : /* @__PURE__ */ React21__default.createElement(IconFilter, null)
4266
+ ), properties && /* @__PURE__ */ React21__default.createElement(Tooltip, { label: t("params.add_metadata") }, /* @__PURE__ */ React21__default.createElement(ActionIcon, { onClick: () => setActiveProperties((value) => !value) }, /* @__PURE__ */ React21__default.createElement(IconAdjustments, null))), /* @__PURE__ */ React21__default.createElement(ThemeIcon, { size: "xs", color: "gray", variant: "light", bg: "transparent" }, /* @__PURE__ */ React21__default.createElement(StackSVG, null)))), (cut == null ? void 0 : cut.active) && /* @__PURE__ */ React21__default.createElement(Box, { pt: "md" }, /* @__PURE__ */ React21__default.createElement(
4364
4267
  MultiSelect,
4365
4268
  {
4366
4269
  sx: { flex: "1 1 100%" },
4367
4270
  searchable: true,
4368
- onChange: (value) => {
4271
+ onChange: (members) => {
4369
4272
  if (cut) {
4370
- if (currentDrilldown.active && !cut.active) {
4371
- updatecutHandler({ ...cut, active: true }, value);
4372
- } else {
4373
- updatecutHandler(cut, value);
4374
- }
4273
+ actions2.updateCut({ ...cut, active: currentDrilldown.active, members });
4375
4274
  }
4376
4275
  },
4377
4276
  placeholder: `Filter by ${label}`,
@@ -4396,7 +4295,7 @@ function PropertiesMultiSelect({ item }) {
4396
4295
  const locale = useSelector$1(selectLocale);
4397
4296
  const actions2 = useActions();
4398
4297
  const { translate: t } = useTranslation();
4399
- const propertiesUpdateHandler2 = useCallback(
4298
+ const propertiesUpdateHandler = useCallback(
4400
4299
  (activeProps) => {
4401
4300
  const properties = item.properties.map(
4402
4301
  (prop) => buildProperty({
@@ -4428,7 +4327,7 @@ function PropertiesMultiSelect({ item }) {
4428
4327
  {
4429
4328
  sx: { flex: "1 1 100%" },
4430
4329
  searchable: true,
4431
- onChange: propertiesUpdateHandler2,
4330
+ onChange: propertiesUpdateHandler,
4432
4331
  value: activeProperties || [],
4433
4332
  placeholder: `Filter by ${label}`,
4434
4333
  data: item.properties.map((property) => ({
@@ -6815,6 +6714,51 @@ function ExplorerTour({ children, tourConfig }) {
6815
6714
  children
6816
6715
  );
6817
6716
  }
6717
+ function ReportIssueCard(props) {
6718
+ const { errorMessage, errorClass, onClear: clearHandler } = props;
6719
+ const location2 = typeof window === "object" ? window.location : { href: "<SSR>" };
6720
+ const issueParams = new URLSearchParams({
6721
+ title: `[report/vizbuilder] ${errorClass}`,
6722
+ body: [
6723
+ `**URL**: ${location2.href}`,
6724
+ `**Error**: ${errorClass}`,
6725
+ errorMessage ? `**Error details:** ${errorMessage}
6726
+ ` : "",
6727
+ "**Detail of the issue:**\n"
6728
+ ].join("\n")
6729
+ });
6730
+ return /* @__PURE__ */ React21__default.createElement(TranslationConsumer, null, ({ translate: t }) => {
6731
+ const detailText = t("vizbuilder.error.detail");
6732
+ return /* @__PURE__ */ React21__default.createElement(Paper, { w: "100%" }, /* @__PURE__ */ React21__default.createElement(
6733
+ Flex,
6734
+ {
6735
+ p: "xl",
6736
+ align: "center",
6737
+ justify: "center",
6738
+ direction: "column",
6739
+ className: "chart-card error"
6740
+ },
6741
+ /* @__PURE__ */ React21__default.createElement(Title, { order: 3 }, t("vizbuilder.error.title")),
6742
+ detailText.length ? /* @__PURE__ */ React21__default.createElement(Text, null, detailText) : null,
6743
+ /* @__PURE__ */ React21__default.createElement(Text, null, t("vizbuilder.error.message", { message: errorMessage })),
6744
+ /* @__PURE__ */ React21__default.createElement(Group, { spacing: "xs", my: "sm" }, /* @__PURE__ */ React21__default.createElement(Button, { onClick: clearHandler, size: "xs", variant: "light" }, t("vizbuilder.action_retry")), /* @__PURE__ */ React21__default.createElement(
6745
+ Button,
6746
+ {
6747
+ component: "a",
6748
+ href: `https://github.com/Datawheel/vizbuilder/issues/new?${issueParams}`,
6749
+ leftIcon: /* @__PURE__ */ React21__default.createElement(IconBrandGithub, { size: "1rem" }),
6750
+ rel: "noopener noreferrer",
6751
+ role: "button",
6752
+ size: "xs",
6753
+ tabIndex: 0,
6754
+ target: "_blank",
6755
+ variant: "subtle"
6756
+ },
6757
+ t("vizbuilder.action_fileissue")
6758
+ ))
6759
+ ));
6760
+ });
6761
+ }
6818
6762
 
6819
6763
  // src/components/Explorer.tsx
6820
6764
  var defaultVizbuilderConfig = {
@@ -6832,7 +6776,7 @@ var defaultVizbuilderConfig = {
6832
6776
  TREE_MAP_SHAPE_MAX: 1e3
6833
6777
  },
6834
6778
  downloadFormats: ["SVG", "PNG"],
6835
- ErrorBoundary,
6779
+ CardErrorComponent: ReportIssueCard,
6836
6780
  NonIdealState
6837
6781
  };
6838
6782
  var defaultTourConfig = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datawheel/data-explorer",
3
- "version": "1.1.16",
3
+ "version": "1.2.0-rc.1",
4
4
  "main": "./dist/main.mjs",
5
5
  "types": "./dist/main.d.mts",
6
6
  "files": [
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "dependencies": {
21
21
  "@datawheel/use-translation": "^0.2.0",
22
- "@datawheel/vizbuilder": "^0.7.0",
22
+ "@datawheel/vizbuilder": "^0.7.4",
23
23
  "@reactour/tour": "^3.7.0",
24
24
  "@reduxjs/toolkit": "^1.9.3",
25
25
  "@tabler/icons-react": "^2.7.0",
@@ -79,4 +79,4 @@
79
79
  "vite": "^6.3.0",
80
80
  "wrangler": "^4.11.0"
81
81
  }
82
- }
82
+ }