@datawheel/bespoke 0.1.28 → 0.1.30

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/index.js CHANGED
@@ -16,12 +16,12 @@ import { Notifications, notifications } from '@mantine/notifications';
16
16
  import React, { forwardRef, useMemo, useState, useCallback, useContext, useEffect, createContext, useRef, Fragment as Fragment$1, createElement } from 'react';
17
17
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
18
18
  import { useDispatch, useSelector } from 'react-redux';
19
- import { Stack, Text, Badge, Group, Tooltip, ActionIcon, Center, useMantineTheme, Modal, Button, Flex, SegmentedControl, Select, MultiSelect, Title, Box, List, Menu, Anchor, MantineProvider, Divider, Burger, Navbar, ScrollArea, Avatar, AppShell, UnstyledButton, ThemeIcon, LoadingOverlay, Skeleton, Container, TextInput, Loader, Alert, Collapse, Card, Space, Code, Textarea, rem, Overlay, Grid, Input, Popover, Checkbox, Radio, Switch, Drawer, Autocomplete, Tabs, Header, px, SimpleGrid, Image, Paper, FileInput, Accordion, HoverCard, CopyButton, NumberInput, Col } from '@mantine/core';
19
+ import { Stack, Text, Badge, Group, useMantineTheme, Flex, packSx, Tooltip, ActionIcon, Center, Modal, Button, SegmentedControl, Select, MultiSelect, Title, Box, List, Menu, Anchor, MantineProvider, Divider, Burger, Navbar, ScrollArea, Avatar, AppShell, UnstyledButton, ThemeIcon, LoadingOverlay, Skeleton, Container, TextInput, Loader, Alert, Collapse, Card, Space, Code, Textarea, rem, Paper, Grid, Input, Popover, Checkbox, Radio, Switch, Drawer, Overlay, SimpleGrid, Autocomplete, Tabs, Header, px, Image, FileInput, Accordion, HoverCard, CopyButton, NumberInput, Col } from '@mantine/core';
20
20
  import { dataConcat } from 'd3plus-viz';
21
21
  import * as d3plus from 'd3plus-react';
22
22
  import Router, { useRouter } from 'next/router';
23
- import { IconInfoCircle, IconSearch, IconAlignLeft, IconAlignCenter, IconAlignRight, IconBoxMargin, IconTable, IconMathFunction, IconUsers, IconLogout, IconTrash, IconUserCircle, IconEdit, IconDatabase, IconServer, IconPencil, IconAlertCircle, IconCircleCheck, IconPlayerPlay, IconAlarmFilled, IconBox, IconLink, IconCirclePlus, IconCircleX, IconFlag, IconFileAnalytics, IconPlus, IconX, IconChevronDown, IconCamera, IconShare, IconCircleDashed, IconListSearch, IconExternalLink, IconSettings, IconFileOff, IconFilesOff, IconHierarchy3, IconMenu, IconRefresh, IconPolaroid, IconCircleMinus, IconEyeOff, IconChevronLeft, IconChevronRight, IconLogin, IconWorld, IconLock, IconVariable, IconArrowRightCircle, IconDownload, IconTemplate, IconChartBar, IconCode, IconUpload, IconCodePlus, IconClipboardCheck, IconClipboardCopy, IconPalette, IconEye, IconMinimize, IconMaximize, IconRss, IconGlobe } from '@tabler/icons-react';
24
- import { useMediaQuery, useDisclosure, useDebouncedValue, useSetState, useHotkeys, useFullscreen, getHotkeyHandler } from '@mantine/hooks';
23
+ import { IconInfoCircle, IconSearch, IconAlignLeft, IconAlignCenter, IconAlignRight, IconBoxMargin, IconTable, IconMathFunction, IconUsers, IconLogout, IconTrash, IconUserCircle, IconEdit, IconDatabase, IconServer, IconPencil, IconAlertCircle, IconCircleCheck, IconPlayerPlay, IconAlarmFilled, IconBox, IconLink, IconCircleX, IconFlag, IconCirclePlus, IconFileAnalytics, IconPlus, IconX, IconChevronDown, IconCamera, IconShare, IconCircleDashed, IconListSearch, IconExternalLink, IconSettings, IconFileOff, IconFilesOff, IconHierarchy3, IconMenu, IconRefresh, IconPolaroid, IconCircleMinus, IconEyeOff, IconChevronLeft, IconChevronRight, IconLogin, IconWorld, IconLock, IconVariable, IconArrowRightCircle, IconDownload, IconTemplate, IconChartBar, IconCode, IconUpload, IconCodePlus, IconClipboardCheck, IconClipboardCopy, IconPalette, IconEye, IconMinimize, IconMaximize, IconRss, IconGlobe } from '@tabler/icons-react';
24
+ import { useMediaQuery, useDisclosure, useDebouncedValue, useHotkeys, useFullscreen, getHotkeyHandler } from '@mantine/hooks';
25
25
  import dynamic from 'next/dynamic';
26
26
  import Link from 'next/link';
27
27
  import parse2, { Element, domToReact, Text as Text$1 } from 'html-react-parser';
@@ -1224,21 +1224,26 @@ var init_runConsumers = __esm({
1224
1224
  getDependencies = (bid, blocks, acc = [], crawlUp = true, crawlDown = true, withinSection = true, visited = []) => {
1225
1225
  if (visited.includes(bid))
1226
1226
  return [];
1227
- visited.push(bid);
1227
+ if (crawlDown)
1228
+ visited.push(bid);
1229
+ if (verbose2)
1230
+ console.log("%cpassing through block", "color:green", bid);
1228
1231
  const rootBlock = blocks[bid];
1229
1232
  if (rootBlock.inputs.length && crawlUp) {
1230
1233
  rootBlock.inputs.forEach((iid) => {
1231
1234
  const rel = `${iid}-${bid}`;
1232
- if (!acc.includes(rel))
1235
+ if (!acc.includes(rel)) {
1233
1236
  acc.push(rel);
1237
+ }
1234
1238
  rootBlock.inputs.forEach((iid2) => getDependencies(iid2, blocks, acc, crawlUp, false, withinSection, visited));
1235
1239
  });
1236
1240
  }
1237
1241
  if (rootBlock.consumers.length && crawlDown) {
1238
1242
  rootBlock.consumers.forEach((cid) => {
1239
1243
  const rel = `${bid}-${cid}`;
1240
- if (!acc.includes(rel) && (blocks[cid].section_id === blocks[bid].section_id || !withinSection))
1244
+ if (!acc.includes(rel) && (blocks[cid].section_id === blocks[bid].section_id || !withinSection)) {
1241
1245
  acc.push(rel);
1246
+ }
1242
1247
  rootBlock.consumers.filter((cid2) => blocks[cid2].section_id === blocks[bid].section_id || !withinSection).forEach((cid2) => getDependencies(cid2, blocks, acc, crawlUp, crawlDown, withinSection, visited));
1243
1248
  });
1244
1249
  }
@@ -1265,16 +1270,20 @@ var init_runConsumers = __esm({
1265
1270
  }
1266
1271
  return allowed;
1267
1272
  };
1268
- runConsumersV2 = async (blocks, sections, bid, formatterFunctions, blockContext, initialVariables = {}, readMemberFn, mode = "section") => {
1273
+ runConsumersV2 = async (blocks, sections, bid, formatterFunctions, blockContext, initialState4 = {}, readMemberFn, mode = "section") => {
1269
1274
  if (!bid && !sections)
1270
- return { variables: { ...initialVariables } };
1271
- const variablesById = { ...initialVariables };
1272
- const statusById = {};
1275
+ return { ...initialState4 };
1276
+ const variablesById = { ...initialState4.variables ?? {} };
1277
+ const statusById = { ...initialState4.status ?? {} };
1273
1278
  const parsedBlockContext = parseBlockContext(blockContext);
1274
1279
  const attributes = parsedBlockContext.variables;
1275
1280
  const rootBlocks = bid ? { [bid]: blocks[bid] } : sections.reduce((rootBlocks2, { id }) => ({ ...rootBlocks2, ...getRootBlocksForSection_default(id, blocks) }), {});
1281
+ if (verbose2)
1282
+ console.log("%crunConsumers: running root blocks", "color:blue", Object.keys(rootBlocks));
1276
1283
  const withinSection = mode === "section";
1277
1284
  const blockDeps = Object.keys(rootBlocks).reduce((deps, id) => {
1285
+ if (verbose2)
1286
+ console.log("%cresolving dependencies for", "color:red", id);
1278
1287
  const dependencies = getDependencies(Number(id), blocks, [], !bid, true, withinSection).map((rel) => rel.split("-"));
1279
1288
  return [...deps, ...dependencies];
1280
1289
  }, []);
@@ -1282,6 +1291,8 @@ var init_runConsumers = __esm({
1282
1291
  (orderedDAG2, bid2) => orderedDAG2.includes(bid2) ? [...orderedDAG2] : [bid2, ...orderedDAG2],
1283
1292
  toposort(blockDeps)
1284
1293
  );
1294
+ if (verbose2)
1295
+ console.log("resolved DAG: ", orderedDAG);
1285
1296
  async function runTasksInParallel(executionOrder, blocks2) {
1286
1297
  const runningBlocks = /* @__PURE__ */ new Map();
1287
1298
  for (const bid2 of executionOrder) {
@@ -1322,7 +1333,10 @@ var init_runConsumers = __esm({
1322
1333
  await Promise.all(Array.from(runningBlocks.values()));
1323
1334
  }
1324
1335
  await runTasksInParallel(orderedDAG, blocks);
1325
- return { variables: { ...initialVariables, ...variablesById }, status: statusById };
1336
+ return {
1337
+ variables: { ...initialState4.variables ?? {}, ...variablesById },
1338
+ status: { ...initialState4.status ?? {}, ...statusById }
1339
+ };
1326
1340
  };
1327
1341
  getDurationColor = (duration) => {
1328
1342
  if (duration < 250)
@@ -1497,11 +1511,11 @@ var init_FUNC = __esm({
1497
1511
  "libs/FUNC.js"() {
1498
1512
  init_esm_shims();
1499
1513
  init_libs();
1500
- parse = (config, formatters = {}, locale = "en", actions = {}, extraGlobals = {}) => {
1514
+ parse = (config, formatters2 = {}, locale = "en", actions = {}, extraGlobals = {}) => {
1501
1515
  const globals = {
1502
1516
  setVariables: actions.onSetVariables ? actions.onSetVariables : (d) => d,
1503
1517
  openModal: actions.onOpenModal ? actions.onOpenModal : (d) => d,
1504
- formatters,
1518
+ formatters: formatters2,
1505
1519
  libs: libraries,
1506
1520
  locale,
1507
1521
  ...extraGlobals
@@ -1635,7 +1649,7 @@ var init_lib2 = __esm({
1635
1649
  statusPayload
1636
1650
  };
1637
1651
  };
1638
- funcifyFormattersByLocale = (formatters = [], locale = localeDefault3) => formatters.reduce((acc, f) => {
1652
+ funcifyFormattersByLocale = (formatters2 = [], locale = localeDefault3) => formatters2.reduce((acc, f) => {
1639
1653
  const formatterFn = parse({ vars: ["n"], logic: f.content.logic }, {}, locale, {});
1640
1654
  acc[f.name] = formatterFn;
1641
1655
  return acc;
@@ -2466,15 +2480,15 @@ var init_actions = __esm({
2466
2480
  });
2467
2481
  function ResourceProvider(props) {
2468
2482
  const { pathSegment, profilePrefix } = props;
2469
- const formatters = useFormatterList();
2483
+ const formatters2 = useFormatterList();
2470
2484
  const value = useMemo(() => ({
2471
2485
  profilePrefix,
2472
2486
  pathSegment,
2473
2487
  formatterFunctions: locales3.reduce((acc, locale) => ({
2474
2488
  ...acc,
2475
- [locale]: formatters.data ? funcifyFormattersByLocale(formatters.data, locale) : {}
2489
+ [locale]: formatters2.data ? funcifyFormattersByLocale(formatters2.data, locale) : {}
2476
2490
  }), {})
2477
- }), [formatters, pathSegment, profilePrefix]);
2491
+ }), [formatters2, pathSegment, profilePrefix]);
2478
2492
  return /* @__PURE__ */ jsx(ResourceContext.Provider, { value, children: props.children });
2479
2493
  }
2480
2494
  function useBespoke() {
@@ -2705,7 +2719,7 @@ var init_store = __esm({
2705
2719
  storeWrapper = createWrapper(storeFactory);
2706
2720
  }
2707
2721
  });
2708
- function withFetcher(Component, useRef7) {
2722
+ function withFetcher(Component, useRef8) {
2709
2723
  const ComponentWithFetcher = (props) => {
2710
2724
  const {
2711
2725
  id,
@@ -2713,7 +2727,7 @@ function withFetcher(Component, useRef7) {
2713
2727
  skelWidth,
2714
2728
  ...otherProps
2715
2729
  } = props;
2716
- const ref = useRef7(id);
2730
+ const ref = useRef8(id);
2717
2731
  if (ref.isUninitialized || ref.isFetching) {
2718
2732
  return /* @__PURE__ */ jsx(Skeleton, { width: skelWidth, height: skelHeight });
2719
2733
  }
@@ -2769,10 +2783,10 @@ var init_d3plusPropify = __esm({
2769
2783
  <strong>${frontEndMessage}</strong>
2770
2784
  </p>`
2771
2785
  };
2772
- propify = (logic, formatters, variables = {}, locale = localeDefault7, id = null, actions = {}, globals = {}) => {
2786
+ propify = (logic, formatters2, variables = {}, locale = localeDefault7, id = null, actions = {}, globals = {}) => {
2773
2787
  let config;
2774
2788
  try {
2775
- config = parse({ vars: ["variables"], logic }, formatters, locale, actions, globals)(variables);
2789
+ config = parse({ vars: ["variables"], logic }, formatters2, locale, actions, globals)(variables);
2776
2790
  } catch (e) {
2777
2791
  console.error(`Parsing Error in propify (ID: ${id})`);
2778
2792
  console.error(`Error message: ${e.message}`);
@@ -2842,6 +2856,37 @@ var init_defaultConfig = __esm({
2842
2856
  };
2843
2857
  }
2844
2858
  });
2859
+ var ErrorBoundary;
2860
+ var init_ErrorBoundary = __esm({
2861
+ "views/ErrorBoundary.tsx"() {
2862
+ init_esm_shims();
2863
+ ErrorBoundary = class extends React.Component {
2864
+ constructor(props) {
2865
+ super(props);
2866
+ this.state = { hasError: false };
2867
+ }
2868
+ static getDerivedStateFromError(error) {
2869
+ return { hasError: true };
2870
+ }
2871
+ componentDidCatch(error, info) {
2872
+ console.log("Error information:", info.componentStack);
2873
+ notifications.show({
2874
+ autoClose: false,
2875
+ color: "red",
2876
+ id: "revalidate-error",
2877
+ message: "Check the console for more details",
2878
+ title: error.message
2879
+ });
2880
+ }
2881
+ render() {
2882
+ if (this.state.hasError) {
2883
+ return this.props.fallback;
2884
+ }
2885
+ return this.props.children;
2886
+ }
2887
+ };
2888
+ }
2889
+ });
2845
2890
 
2846
2891
  // frontend/components/report/blocks/Viz.tsx
2847
2892
  var Viz_exports = {};
@@ -2874,17 +2919,17 @@ function Viz(config) {
2874
2919
  if (!vizTypes[type])
2875
2920
  vizProps.config = { error: `"${type}" is not a valid Visualization Type` };
2876
2921
  const Visualization = vizTypes[fallbackType];
2877
- vizProps.config = { ...vizProps.config, ...configOverride };
2878
- const vizConfig = { locale, variables, ...vizProps.config };
2922
+ const { _data, ...vizPropsConfig } = vizProps.config;
2923
+ const vizConfig = { locale, variables, ...vizPropsConfig, ...configOverride };
2879
2924
  return /* @__PURE__ */ jsx(
2880
2925
  "div",
2881
2926
  {
2882
2927
  style: {
2883
2928
  display: "flex",
2884
2929
  flex: "1 1 100%",
2885
- minHeight: 500
2930
+ minHeight: 400
2886
2931
  },
2887
- children: /* @__PURE__ */ jsx(
2932
+ children: /* @__PURE__ */ jsx(ErrorBoundary, { fallback: /* @__PURE__ */ jsx("p", { children: "Error in d3plus viz config." }), children: /* @__PURE__ */ jsx(
2888
2933
  Visualization,
2889
2934
  {
2890
2935
  style: { flex: 1 },
@@ -2905,7 +2950,7 @@ function Viz(config) {
2905
2950
  config: { ...defaultConfig_default, ...vizConfig }
2906
2951
  },
2907
2952
  "viz-key"
2908
- )
2953
+ ) })
2909
2954
  }
2910
2955
  );
2911
2956
  }
@@ -2919,6 +2964,7 @@ var init_Viz = __esm({
2919
2964
  init_hooks();
2920
2965
  init_defaultConfig();
2921
2966
  init_hooks();
2967
+ init_ErrorBoundary();
2922
2968
  vizTypes = {
2923
2969
  ...d3plus
2924
2970
  };
@@ -3110,8 +3156,8 @@ function Viz2({
3110
3156
  if (debugMessage) {
3111
3157
  return /* @__PURE__ */ jsx(Center, { style: { height: "100%" }, children: /* @__PURE__ */ jsx(Badge, { color: "gray", variant: "outline", children: debugMessage }, "type") });
3112
3158
  }
3113
- vizProps.config = { ...vizProps.config, ...configOverride };
3114
- const vizConfig = { locale, variables, ...vizProps.config };
3159
+ const { _data, ...vizPropsConfig } = vizProps.config;
3160
+ const vizConfig = { locale, variables, ...vizPropsConfig, ...configOverride };
3115
3161
  if (context.print)
3116
3162
  vizConfig.detectVisible = false;
3117
3163
  !context.print && type !== "Graphic" && type !== "HTML";
@@ -3122,7 +3168,7 @@ function Viz2({
3122
3168
  display: "flex",
3123
3169
  flex: "1 1 100%"
3124
3170
  },
3125
- children: /* @__PURE__ */ jsx(
3171
+ children: /* @__PURE__ */ jsx(ErrorBoundary, { fallback: /* @__PURE__ */ jsx("p", { children: "Error in d3plus viz config." }), children: /* @__PURE__ */ jsx(
3126
3172
  Visualization,
3127
3173
  {
3128
3174
  style: { flex: 1 },
@@ -3143,7 +3189,7 @@ function Viz2({
3143
3189
  config: { ...defaultConfig_default, ...vizConfig }
3144
3190
  },
3145
3191
  "viz-key"
3146
- )
3192
+ ) })
3147
3193
  }
3148
3194
  );
3149
3195
  }
@@ -3160,6 +3206,7 @@ var init_Viz2 = __esm({
3160
3206
  init_d3plusPropify();
3161
3207
  init_getBlockContent();
3162
3208
  init_hooks();
3209
+ init_ErrorBoundary();
3163
3210
  useAppContext = () => ({});
3164
3211
  CustomVizzes = {};
3165
3212
  vizTypes2 = {
@@ -3894,9 +3941,10 @@ function useOnChangeSelector(blockId, section, selectorIdentifier) {
3894
3941
  const attributes = useAppSelector((state2) => state2.variables.attributes);
3895
3942
  const blockRecords = selectBlockRecords(state);
3896
3943
  const formatterList = selectFormatterList(state);
3897
- const formatters = funcifyFormattersByLocale(formatterList, localeDefault4);
3944
+ const formatters2 = funcifyFormattersByLocale(formatterList, localeDefault4);
3898
3945
  const variables = useInputVariablesFlat(blockId);
3899
3946
  const initialVariables = useAppSelector((state2) => state2.variables.variables);
3947
+ const initialStatus = useAppSelector((state2) => state2.variables.status);
3900
3948
  const readMemberFn = useReadMemberFn();
3901
3949
  const callback = useCallback(
3902
3950
  (value) => {
@@ -3910,9 +3958,12 @@ function useOnChangeSelector(blockId, section, selectorIdentifier) {
3910
3958
  blockRecords,
3911
3959
  void 0,
3912
3960
  blockId,
3913
- formatters,
3961
+ formatters2,
3914
3962
  blockContext,
3915
- initialVariables,
3963
+ {
3964
+ variables: initialVariables,
3965
+ status: initialStatus
3966
+ },
3916
3967
  readMemberFn,
3917
3968
  "report"
3918
3969
  ).then((data) => {
@@ -3930,7 +3981,7 @@ function useOnChangeSelector(blockId, section, selectorIdentifier) {
3930
3981
  query,
3931
3982
  blockRecords,
3932
3983
  dispatch,
3933
- formatters,
3984
+ formatters2,
3934
3985
  router,
3935
3986
  variables.attributes
3936
3987
  ]
@@ -4029,8 +4080,9 @@ function useInitialState(pathSegmentsKey) {
4029
4080
  const attributes = useAppSelector((state2) => state2.variables.attributes);
4030
4081
  const blockRecords = selectBlockRecords(state);
4031
4082
  const formatterList = selectFormatterList(state);
4032
- const formatters = funcifyFormattersByLocale(formatterList, localeDefault4);
4083
+ const formatters2 = funcifyFormattersByLocale(formatterList, localeDefault4);
4033
4084
  const variables = useAppSelector((state2) => state2.variables.variables);
4085
+ const status = useAppSelector((state2) => state2.variables.status);
4034
4086
  const readMemberFn = useReadMemberFn();
4035
4087
  useEffect(() => {
4036
4088
  if (!isLoading && user && report_id) {
@@ -4072,9 +4124,9 @@ function useInitialState(pathSegmentsKey) {
4072
4124
  blockRecords,
4073
4125
  void 0,
4074
4126
  bid,
4075
- formatters,
4127
+ formatters2,
4076
4128
  blockContext,
4077
- variables,
4129
+ { variables, status },
4078
4130
  readMemberFn,
4079
4131
  "report"
4080
4132
  ).then((data) => {
@@ -4145,12 +4197,14 @@ function createOutline(elements, variables) {
4145
4197
  function useContentOutline(min = 1, max = 6, headings = []) {
4146
4198
  const state = useAppSelector((state2) => state2);
4147
4199
  const variables = useAppSelector((state2) => state2.variables.variables);
4200
+ const status = useAppSelector((state2) => state2.variables.status);
4148
4201
  const sectionList = useSectionList();
4149
4202
  const titleList = selectBlockList(state).filter((block) => {
4150
4203
  return block.type === BLOCK_TYPES.TITLE && headings.includes(block.id);
4151
4204
  });
4152
4205
  const titleBlocks = Object.fromEntries(titleList.map((block) => [block.id, block]));
4153
4206
  const titleVariables = Object.fromEntries(titleList.map((block) => [block.id, variables[block.id]]));
4207
+ const titleStatus = Object.fromEntries(titleList.map((block) => [block.id, status[block.id]]));
4154
4208
  const titlesSorted = useMemo(() => {
4155
4209
  if (sectionList.isSuccess && titleBlocks) {
4156
4210
  let titleBlocksNormalized = [];
@@ -4168,10 +4222,10 @@ function useContentOutline(min = 1, max = 6, headings = []) {
4168
4222
  });
4169
4223
  return titleBlocksNormalized.filter((title) => {
4170
4224
  const currentOrder = parseInt(title.settings.order || "1", 10);
4171
- return currentOrder >= min && currentOrder <= max;
4225
+ return currentOrder >= min && currentOrder <= max && titleStatus[title.id] ? titleStatus[title.id].allowed : true;
4172
4226
  });
4173
4227
  }
4174
- }, [headings, sectionList, titleBlocks]);
4228
+ }, [headings, sectionList, titleBlocks, titleStatus]);
4175
4229
  return useMemo(() => {
4176
4230
  if (titlesSorted && titlesSorted?.length > 0) {
4177
4231
  return createOutline(titlesSorted, titleVariables);
@@ -5356,10 +5410,18 @@ function Block({ blockId, active = true }) {
5356
5410
  };
5357
5411
  fetch();
5358
5412
  }, [blockContent, variables]);
5359
- if (!block || !content || !blockStatus.allowed)
5413
+ const allowed = blockStatus.allowed || block?.type === BLOCK_TYPES.NAV;
5414
+ if (!block || !content || !allowed)
5360
5415
  return null;
5361
5416
  const Renderer = blocks_default[block.type];
5362
- return /* @__PURE__ */ jsx("div", { id: `bespoke-${block.type}-${block.id}`, className: `cms-block-wrapper cms-block-${blockId}`, children: /* @__PURE__ */ jsx(Renderer, { ...content, settings: block.settings }) });
5417
+ return /* @__PURE__ */ jsx(
5418
+ "div",
5419
+ {
5420
+ id: `bespoke-${block.type}-${block.id}`,
5421
+ className: `cms-block-wrapper bespoke-block-area cms-block-${blockId}`,
5422
+ children: /* @__PURE__ */ jsx(Renderer, { ...content, settings: block.settings })
5423
+ }
5424
+ );
5363
5425
  }
5364
5426
 
5365
5427
  // libs/settings/section.tsx
@@ -5472,19 +5534,33 @@ function CopyInput(props) {
5472
5534
  init_esm_shims();
5473
5535
  var defaultIdAccessor = "_key";
5474
5536
  function SortableTable({ data, customIdAccessor = "id" }) {
5475
- const [records, setRecords] = useState(data);
5537
+ const [records, setRecords] = useState();
5476
5538
  const [sortStatus, setSortStatus] = useState();
5477
- const keys = data && data[0] ? Object.keys(data[0]) : [];
5539
+ const keys = data && Array.isArray(data) && data[0] ? Object.keys(data[0]) : [];
5478
5540
  const idAccessor = keys.includes(customIdAccessor) ? customIdAccessor : defaultIdAccessor;
5479
5541
  const fields = keys.filter((k) => !k.startsWith("_"));
5480
5542
  const columns = fields.map((field) => ({ accessor: field, sortable: true }));
5481
5543
  const getSortedData = (sortField) => {
5482
5544
  let dataTemp = [...data];
5483
- if (idAccessor === defaultIdAccessor) {
5484
- dataTemp = dataTemp.map((item, ix) => ({ ...item, _key: `i-${ix}` }));
5485
- }
5545
+ dataTemp = dataTemp.map((item, ix) => {
5546
+ fields.forEach((f) => {
5547
+ if (typeof item[f] === "object") {
5548
+ item[f] = JSON.stringify(item[f]);
5549
+ }
5550
+ });
5551
+ if (idAccessor === defaultIdAccessor) {
5552
+ item._key = `i-${ix}`;
5553
+ }
5554
+ return item;
5555
+ });
5486
5556
  if (sortField) {
5487
- dataTemp = dataTemp.sort((a, b) => a[sortField.columnAccessor].localeCompare(b[sortField.columnAccessor]));
5557
+ dataTemp = dataTemp.sort((a, b) => {
5558
+ if (isNaN(a[sortField.columnAccessor])) {
5559
+ return a[sortField.columnAccessor].localeCompare(b[sortField.columnAccessor]);
5560
+ } else {
5561
+ return a[sortField.columnAccessor] > b[sortField.columnAccessor] ? 1 : -1;
5562
+ }
5563
+ });
5488
5564
  }
5489
5565
  return sortField && sortField.direction === "desc" ? dataTemp.reverse() : dataTemp;
5490
5566
  };
@@ -5511,6 +5587,14 @@ function SortableTable({ data, customIdAccessor = "id" }) {
5511
5587
  }
5512
5588
  );
5513
5589
  }
5590
+
5591
+ // components/options/tabs/DataTab.tsx
5592
+ init_cms();
5593
+ init_d3plusPropify();
5594
+ init_getBlockContent();
5595
+ init_hooks();
5596
+ init_varSwapRecursive();
5597
+ init_runConsumers();
5514
5598
  var formatOptions = {
5515
5599
  csv: "CSV",
5516
5600
  json: "JSON",
@@ -5518,54 +5602,149 @@ var formatOptions = {
5518
5602
  };
5519
5603
  function DataTab(props) {
5520
5604
  const { section } = props;
5605
+ const readMemberFn = useReadMemberFn();
5521
5606
  const blocksIds = section.blocks || [];
5522
- const apiBlocks = useAppSelector((state) => blocksIds.map((blockId) => state.records.entities.block[blockId]).filter((block) => block.type === "generator" && block.contentByLocale.logic.content.api).map((generator) => {
5523
- const api = state.variables.status[generator.id]?.api || "";
5524
- const data = state.variables.variables[generator.id]._data || [];
5525
- return {
5526
- ...generator,
5527
- api,
5528
- data
5529
- };
5530
- }));
5531
- const sourcesOptions = apiBlocks.map((block, ix) => ({
5532
- id: block.id,
5533
- title: `Data Source ${ix + 1}`,
5534
- path: block.api,
5535
- data: block.data
5536
- }));
5607
+ const locale = useAppSelector((state) => state.status.currentLocale);
5608
+ const PREVIEW_SIZE = 50;
5609
+ const formatterFunctions = useFormatterFunctionsForLocale(locale);
5610
+ const router = useRouter();
5611
+ const sourcesOptions = useAppSelector((state) => {
5612
+ const dataInformation = [];
5613
+ console.log("calculate api blocks");
5614
+ blocksIds.map((blockId) => state.records.entities.block[blockId]).filter((block) => [BLOCK_TYPES.GENERATOR, BLOCK_TYPES.VIZ].includes(block.type)).map((block) => {
5615
+ if (block.type === BLOCK_TYPES.GENERATOR) {
5616
+ const api = state.variables.variables[block.id]._api || state.variables.status[block.id].api;
5617
+ if (api) {
5618
+ const ix = dataInformation.length;
5619
+ dataInformation.push(
5620
+ {
5621
+ ix,
5622
+ id: block.id,
5623
+ title: `Data Source ${ix + 1}`,
5624
+ path: api
5625
+ }
5626
+ );
5627
+ }
5628
+ } else if (block.type === BLOCK_TYPES.VIZ) {
5629
+ const content = getBlockContent(block);
5630
+ const variables = useInputVariablesFlat(block.id);
5631
+ const blockContext = { variables };
5632
+ const { sectionVariables, setSectionVariables, resetSectionVariables } = useSectionVariables(block.section_id);
5633
+ const transpiledLogic = varSwapRecursive_default({ logic: content.logic }, formatterFunctions, blockContext).logic;
5634
+ const globals = {
5635
+ router,
5636
+ section: {
5637
+ variables: sectionVariables,
5638
+ setVariables: setSectionVariables,
5639
+ resetVariables: resetSectionVariables
5640
+ }
5641
+ };
5642
+ const d3Props = d3plusPropify_default(transpiledLogic, formatterFunctions, variables, locale, block.id, {}, globals);
5643
+ if (d3Props.config._api) {
5644
+ const ix = dataInformation.length;
5645
+ dataInformation.push(
5646
+ {
5647
+ ix,
5648
+ id: block.id,
5649
+ title: `Viz Data Source ${ix + 1}`,
5650
+ path: d3Props.config._api
5651
+ }
5652
+ );
5653
+ } else if (typeof d3Props.config.data === "string") {
5654
+ const ix = dataInformation.length;
5655
+ dataInformation.push(
5656
+ {
5657
+ ix,
5658
+ id: block.id,
5659
+ title: `Viz Data Source ${ix + 1}`,
5660
+ path: d3Props.config.data
5661
+ }
5662
+ );
5663
+ } else if (Array.isArray(d3Props.config.data)) {
5664
+ d3Props.config.data.forEach((dataItem) => {
5665
+ if (typeof dataItem === "string") {
5666
+ const ix = dataInformation.length;
5667
+ dataInformation.push(
5668
+ {
5669
+ ix,
5670
+ id: block.id,
5671
+ title: `Viz Data Source ${ix + 1}`,
5672
+ path: dataItem
5673
+ }
5674
+ );
5675
+ }
5676
+ });
5677
+ }
5678
+ }
5679
+ });
5680
+ return dataInformation;
5681
+ });
5537
5682
  const [selectedSource, setSelectedSource] = useState();
5538
5683
  const [fileProcessing, setFileProcessing] = useState(false);
5539
5684
  const [fileFormat, setFileFormat] = useState(formatOptions.csv);
5685
+ const [previewsSource, setPreviewsSource] = useState({});
5686
+ const [loadingPreview, setLoadingPreview] = useState(false);
5540
5687
  useEffect(() => {
5541
5688
  if (sourcesOptions[0]) {
5542
5689
  setSelectedSource(sourcesOptions[0]);
5543
5690
  }
5544
5691
  }, []);
5545
- const getFileName = (format2) => {
5546
- const sectionId = section.id;
5547
- const sourceId = selectedSource.id;
5548
- return `data_section_${sectionId}_block_${sourceId}.${format2.toLowerCase()}`;
5692
+ useEffect(() => {
5693
+ if (selectedSource && !previewsSource[selectedSource.ix]) {
5694
+ setLoadingPreview(true);
5695
+ apiFetch(selectedSource.path, {}, readMemberFn, locale).then((response) => {
5696
+ let dataToShare = [];
5697
+ if (response && response.data) {
5698
+ if (response.data && Array.isArray(response.data)) {
5699
+ dataToShare = response.data;
5700
+ } else if (response.data && response.data.data && Array.isArray(response.data.data)) {
5701
+ dataToShare = response.data.data;
5702
+ } else if (response.data && response.data.data && response.data.data.results && Array.isArray(response.data.data.results)) {
5703
+ dataToShare = response.data.data.results;
5704
+ } else if (response.data && response.data.results && Array.isArray(response.data.results)) {
5705
+ dataToShare = response.data.results;
5706
+ }
5707
+ }
5708
+ setPreviewsSource({
5709
+ ...previewsSource,
5710
+ [selectedSource.ix]: dataToShare
5711
+ });
5712
+ }).catch((e) => {
5713
+ console.error(e);
5714
+ }).finally(() => {
5715
+ setLoadingPreview(false);
5716
+ });
5717
+ }
5718
+ }, [selectedSource]);
5719
+ const getFileName = (nameformat, fileFormat2) => {
5720
+ const finalNameFormat = nameformat === fileFormat2 ? "" : `_${nameformat}`.toLowerCase();
5721
+ if (selectedSource) {
5722
+ return `data_section_${section.id}_block_${selectedSource.id}_${selectedSource.ix}${finalNameFormat}.${fileFormat2.toLowerCase()}`;
5723
+ }
5724
+ return `data_file${finalNameFormat}.${fileFormat2}`;
5725
+ };
5726
+ const getCurrentPreview = () => {
5727
+ return selectedSource && previewsSource[selectedSource.ix] ? previewsSource[selectedSource.ix] : [];
5549
5728
  };
5550
5729
  const onSaveClick = async () => {
5551
5730
  if (selectedSource) {
5552
5731
  setFileProcessing(true);
5553
5732
  const zipFile = new JSZip();
5554
- const filename = getFileName(fileFormat);
5733
+ const filename = getFileName(fileFormat, fileFormat);
5555
5734
  try {
5556
5735
  switch (fileFormat) {
5557
5736
  case formatOptions.json:
5558
- zipFile.file(filename, JSON.stringify(selectedSource.data));
5737
+ zipFile.file(filename, JSON.stringify(currentPreview));
5559
5738
  break;
5560
5739
  case formatOptions.csv:
5561
- zipFile.file(filename, csvFormat(selectedSource.data));
5740
+ zipFile.file(filename, csvFormat(currentPreview));
5562
5741
  break;
5563
5742
  case formatOptions.xlsx:
5564
5743
  const { utils, write } = await import('xlsx');
5565
5744
  const wb = utils.book_new();
5566
5745
  utils.book_append_sheet(
5567
5746
  wb,
5568
- utils.json_to_sheet(selectedSource.data),
5747
+ utils.json_to_sheet(currentPreview),
5569
5748
  filename.substring(0, 30)
5570
5749
  // Sheet name max length
5571
5750
  );
@@ -5581,7 +5760,7 @@ function DataTab(props) {
5581
5760
  compressionOptions: { level: 9 }
5582
5761
  }).then((content) => {
5583
5762
  setFileProcessing(false);
5584
- saveAs(content, getFileName("zip"));
5763
+ saveAs(content, getFileName(fileFormat, "zip"));
5585
5764
  });
5586
5765
  } catch (error) {
5587
5766
  console.error("Error generating file", error);
@@ -5589,22 +5768,24 @@ function DataTab(props) {
5589
5768
  }
5590
5769
  }
5591
5770
  };
5771
+ const currentPreview = getCurrentPreview();
5592
5772
  return /* @__PURE__ */ jsxs(Stack, { className: "cms-section-options-data", children: [
5593
5773
  /* @__PURE__ */ jsx(Space, { h: "xs" }),
5594
5774
  sourcesOptions.length === 0 && /* @__PURE__ */ jsx("p", { children: "No data sources defined." }),
5595
- sourcesOptions.length > 0 && /* @__PURE__ */ jsx(Input.Wrapper, { label: "Choose Data Source:", children: /* @__PURE__ */ jsx(Button.Group, { children: sourcesOptions.map((source, ix) => /* @__PURE__ */ jsx(
5775
+ sourcesOptions.length > 1 && /* @__PURE__ */ jsx(Input.Wrapper, { label: "Choose Data Source:", children: /* @__PURE__ */ jsx(Group, { spacing: "xs", children: sourcesOptions.map((source, ix) => /* @__PURE__ */ jsx(
5596
5776
  Button,
5597
5777
  {
5598
5778
  leftIcon: /* @__PURE__ */ jsx(IconDatabase, { size: 16 }),
5599
5779
  onClick: () => setSelectedSource(source),
5600
- variant: selectedSource?.id === source.id ? "filled" : "default",
5601
- fullWidth: true,
5780
+ variant: selectedSource?.ix === ix ? "filled" : "default",
5602
5781
  children: source.title
5603
5782
  },
5604
- `source-${source.id}`
5783
+ `source-${source.id}-${ix}`
5605
5784
  )) }) }),
5606
5785
  selectedSource && /* @__PURE__ */ jsx(CopyInput, { title: `Original ${selectedSource.title}:`, url: selectedSource.path }),
5607
- selectedSource && (!selectedSource.data || selectedSource.data.length === 0) && /* @__PURE__ */ jsx("a", { href: selectedSource.path, target: "_blank", rel: "noreferrer", children: /* @__PURE__ */ jsx(
5786
+ selectedSource && loadingPreview && /* @__PURE__ */ jsx(Fragment, { children: "Loading..." }),
5787
+ selectedSource && !loadingPreview && currentPreview.length === 0 && /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: "1rem" }), title: "Oops!", children: "Sorry. We couldn't generate the data preview. Try to open the source and check the data directly." }),
5788
+ selectedSource && !loadingPreview && currentPreview.length === 0 && /* @__PURE__ */ jsx("a", { href: selectedSource.path, target: "_blank", rel: "noreferrer", children: /* @__PURE__ */ jsx(
5608
5789
  Button,
5609
5790
  {
5610
5791
  leftIcon: /* @__PURE__ */ jsx(IconExternalLink, { size: 16 }),
@@ -5612,8 +5793,16 @@ function DataTab(props) {
5612
5793
  children: `Open ${selectedSource.title} response in a new window`
5613
5794
  }
5614
5795
  ) }),
5615
- selectedSource && selectedSource.data && selectedSource.data.length > 0 && /* @__PURE__ */ jsxs(Stack, { children: [
5616
- /* @__PURE__ */ jsx(Input.Wrapper, { label: `Formatted ${selectedSource.title}:`, style: { height: "300px" }, children: /* @__PURE__ */ jsx(SortableTable, { data: selectedSource.data }) }),
5796
+ selectedSource && !loadingPreview && currentPreview.length > 0 && /* @__PURE__ */ jsxs(Stack, { children: [
5797
+ /* @__PURE__ */ jsx(
5798
+ Input.Wrapper,
5799
+ {
5800
+ label: `Formatted ${selectedSource.title}
5801
+ ${currentPreview.length > PREVIEW_SIZE ? `(First ${PREVIEW_SIZE} rows as preview)` : ""}:`,
5802
+ style: { height: "300px" },
5803
+ children: /* @__PURE__ */ jsx(SortableTable, { data: currentPreview.slice(0, PREVIEW_SIZE) })
5804
+ }
5805
+ ),
5617
5806
  /* @__PURE__ */ jsx(Space, { h: "xs" }),
5618
5807
  /* @__PURE__ */ jsx(Input.Wrapper, { label: "Choose format:", children: /* @__PURE__ */ jsx(Button.Group, { children: Object.keys(formatOptions).map((format2) => /* @__PURE__ */ jsx(
5619
5808
  Button,
@@ -5633,7 +5822,7 @@ function DataTab(props) {
5633
5822
  loading: fileProcessing,
5634
5823
  onClick: onSaveClick,
5635
5824
  fullWidth: true,
5636
- children: /* @__PURE__ */ jsx("span", { children: fileProcessing ? "Processing file..." : `Download ${fileFormat}` })
5825
+ children: /* @__PURE__ */ jsx("span", { children: fileProcessing ? "Processing file..." : `Download full dataset in ${fileFormat} format` })
5637
5826
  }
5638
5827
  )
5639
5828
  ] })
@@ -5724,12 +5913,12 @@ function ImageTab(props) {
5724
5913
  };
5725
5914
  const getFileName = () => `${slugify_default("export-name")}`;
5726
5915
  const getSectionNode = (sectionId) => {
5727
- const sectionNode = document.getElementById(`cms-section-${sectionId}`);
5728
- return select(sectionNode).select(".cms-section-content").node();
5916
+ const sectionNode = document.getElementById(`section-${sectionId}`);
5917
+ return select(sectionNode).select(".bespoke-section-content").node();
5729
5918
  };
5730
5919
  const getVizNode = (sectionId, vizId) => {
5731
- const sectionNode = document.getElementById(`cms-section-${sectionId}`);
5732
- return select(sectionNode).select(`#cms-block-${vizId} .cms-block-preview`).node();
5920
+ const sectionNode = getSectionNode(sectionId);
5921
+ return select(sectionNode).select(`#bespoke-visualization-${vizId}.bespoke-block-area`).node();
5733
5922
  };
5734
5923
  const getSelectedNode = () => {
5735
5924
  let node;
@@ -5939,7 +6128,7 @@ function ShareTab(props) {
5939
6128
  setTitle(document.title);
5940
6129
  const { origin, pathname } = window.location;
5941
6130
  const url = `${origin}${pathname}`;
5942
- const sectionAnchor = includeSection ? `#cms-section-${section.id}` : "";
6131
+ const sectionAnchor = includeSection ? `#section-${section.id}` : "";
5943
6132
  setShareUrl(`${url}${sectionAnchor}`);
5944
6133
  }, [includeSection]);
5945
6134
  return /* @__PURE__ */ jsxs(Stack, { className: "cms-section-options-share", children: [
@@ -6039,9 +6228,9 @@ function OptionsModal(props) {
6039
6228
  keepMounted: false,
6040
6229
  children: [
6041
6230
  /* @__PURE__ */ jsxs(Tabs.List, { children: [
6042
- /* @__PURE__ */ jsx(Tabs.Tab, { value: "data", children: "Data" }),
6231
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "data", children: "Download data" }),
6043
6232
  /* @__PURE__ */ jsx(Tabs.Tab, { value: "image", children: "Save image" }),
6044
- /* @__PURE__ */ jsx(Tabs.Tab, { value: "share", children: "Share" })
6233
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "share", children: "Share link" })
6045
6234
  ] }),
6046
6235
  /* @__PURE__ */ jsx(Tabs.Panel, { value: "data", children: /* @__PURE__ */ jsx(DataTab, { section }) }),
6047
6236
  /* @__PURE__ */ jsx(Tabs.Panel, { value: "image", children: /* @__PURE__ */ jsx(ImageTab, { section }) }),
@@ -6080,7 +6269,7 @@ function Options(props) {
6080
6269
  initialMode: mode,
6081
6270
  open: opened,
6082
6271
  onEnds: onModalEnds,
6083
- title: "Section title"
6272
+ title: "Section information"
6084
6273
  }
6085
6274
  )
6086
6275
  ] });
@@ -6273,183 +6462,576 @@ var SectionMenu_default = SectionMenu;
6273
6462
 
6274
6463
  // frontend/components/report/Section.tsx
6275
6464
  init_cms();
6276
- var getStyles = (styles, settings) => (theme) => styles ? styles(theme, settings) : {};
6277
- var PositionWrapper = ({ settings, styles, children, ...props }) => {
6278
- const { position } = settings;
6279
- const defaultStyles = {
6280
- "normal": {
6281
- position: "relative",
6282
- backgroundColor: "transparent",
6283
- borderRadius: 0
6284
- },
6285
- "sticky": {
6286
- position: "sticky",
6287
- zIndex: 3,
6288
- top: 0,
6289
- borderRadius: 0,
6290
- borderTop: "none",
6291
- borderLeft: "none",
6292
- borderRight: "none"
6293
- }
6294
- };
6295
- const defaultProps = {
6296
- "normal": {
6297
- radius: 0
6298
- },
6299
- "sticky": {
6300
- radius: 0,
6301
- withBorder: true
6302
- }
6303
- };
6304
- const sx = [defaultStyles[position], getStyles(styles, settings)];
6305
- return /* @__PURE__ */ jsx(Paper, { component: "section", sx, ...defaultProps[position], ...props, children });
6306
- };
6307
- var WidthWrapper = ({ settings, styles, children, ...props }) => {
6308
- const { width: container } = settings;
6309
- const defaultStyles = {
6310
- "center": {},
6311
- "full": {}
6312
- };
6313
- const defaultProps = {
6314
- "center": { size: "md", p: "sm", fluid: false },
6315
- "full": { fluid: true, p: "md" }
6316
- };
6317
- const sx = [defaultStyles[container], getStyles(styles, settings)];
6318
- return /* @__PURE__ */ jsx(Container, { sx, ...defaultProps[container], ...props, children });
6319
- };
6320
- var StyleWrapper = ({ settings, styles, children, ...props }) => {
6321
- const { style: variant } = settings;
6322
- const defaultStyles = {
6323
- "none": {},
6324
- "card": {}
6325
- };
6326
- const defaultProps = {
6327
- "none": { bg: "transparent" },
6328
- "card": { shadow: "lg", p: "md", radius: "md" }
6329
- };
6330
- const sx = [defaultStyles[variant], getStyles(styles, settings)];
6331
- return /* @__PURE__ */ jsx(Paper, { sx, ...defaultProps[variant], ...props, children });
6465
+
6466
+ // components/sections/SectionColumns.tsx
6467
+ init_esm_shims();
6468
+
6469
+ // libs/settings/site.ts
6470
+ init_esm_shims();
6471
+ var site_default = {
6472
+ backgroundColor: "#fafafa",
6473
+ block: {
6474
+ padding: 10
6475
+ },
6476
+ column: {
6477
+ padding: 12
6478
+ },
6479
+ section: {
6480
+ backgroundColor: "white",
6481
+ borderRadius: 10,
6482
+ boxShadow: "0px 6px 10px rgba(12, 32, 50, 0.14), 0px 1px 15px rgba(12, 32, 50, 0.12), 0px 3px 5px rgba(12, 32, 50, 0.15)",
6483
+ margin: 8,
6484
+ padding: 32
6485
+ }
6332
6486
  };
6333
- function Section({ section }) {
6334
- const { id, settings } = section;
6335
- const sectionSettings2 = {
6336
- ...defaultSectionSettings,
6337
- ...settings
6338
- };
6339
- const state = useAppSelector((state2) => state2);
6340
- const status = useAppSelector((state2) => state2.variables.status);
6341
- const sectionStyles = useBespokeStyles()["Section"];
6342
- const blockRecords = selectBlockRecords(state);
6487
+
6488
+ // components/sections/SectionColumns.tsx
6489
+ init_store2();
6490
+ function SectionColumnsWrapper({
6491
+ children,
6492
+ containerProps
6493
+ }, ref) {
6343
6494
  const theme = useMantineTheme();
6344
- const smallScreen = useMediaQuery(`(max-width: ${theme.breakpoints.sm}px)`);
6345
- const sectionBlocks = Object.values(blockRecords || {}).filter((d) => d.section_id === id);
6346
- const allowedSection = sectionBlocks.some((b) => {
6347
- try {
6348
- return status[b.id].allowed && b.type !== BLOCK_TYPES.GENERATOR;
6349
- } catch (e) {
6350
- return b.settings.allowed === "always";
6351
- }
6352
- });
6353
- const columns = sectionBlocks.reduce((acc, d) => {
6354
- if (!acc[d.blockcol]) {
6355
- acc[d.blockcol] = { [d.blockrow]: d };
6356
- } else {
6357
- acc[d.blockcol][d.blockrow] = d;
6358
- }
6359
- return acc;
6360
- }, {});
6361
- const displaySection = Object.keys(blockRecords).length > 0 && !settings.hidden && allowedSection;
6362
- if (!displaySection)
6363
- return null;
6364
- return /* @__PURE__ */ jsxs(
6365
- PositionWrapper,
6495
+ const mediumScreen = useMediaQuery(`(max-width: ${theme.breakpoints.md})`);
6496
+ return /* @__PURE__ */ jsx(
6497
+ Flex,
6366
6498
  {
6367
- settings: sectionSettings2,
6368
- styles: sectionStyles?.root || void 0,
6369
- children: [
6370
- sectionSettings2.memberImageBg && /* @__PURE__ */ jsx(SectionBackground, {}),
6371
- /* @__PURE__ */ jsx(
6372
- WidthWrapper,
6373
- {
6374
- settings: sectionSettings2,
6375
- styles: sectionStyles?.container,
6376
- className: `cms-section-${id}`,
6377
- pos: "relative",
6378
- children: /* @__PURE__ */ jsx(StyleWrapper, { settings: sectionSettings2, styles: sectionStyles?.content, children: /* @__PURE__ */ jsxs(
6379
- Flex,
6380
- {
6381
- className: "cms-section-content",
6382
- align: "stretch",
6383
- direction: smallScreen ? "column" : "row",
6384
- pos: "relative",
6385
- gap: "md",
6386
- children: [
6387
- /* @__PURE__ */ jsxs("div", { style: {
6388
- position: "absolute",
6389
- right: 10,
6390
- top: 10,
6391
- zIndex: 100
6392
- }, children: [
6393
- sectionSettings2.optionsMenu && /* @__PURE__ */ jsx(Options, { sectionId: section.id }),
6394
- /* @__PURE__ */ jsx(SectionResetButton, { id: section.id })
6395
- ] }),
6396
- Object.keys(columns).sort((a, b) => orderSort(a, b, "blockcol")).map((columnIndex) => {
6397
- const column = columns[columnIndex];
6398
- const staticWidths = Object.values(column).map(({ id: id2 }) => parseFloat(blockRecords[id2]?.settings?.width || "none")).filter((d) => !Number.isNaN(d));
6399
- return /* @__PURE__ */ jsx(
6400
- Stack,
6401
- {
6402
- className: "cms-section-col",
6403
- sx: {
6404
- flex: "1 1 100%",
6405
- maxWidth: staticWidths.length ? Math.max(...staticWidths) : "none"
6406
- },
6407
- children: Object.values(column).sort((a, b) => orderSort(a, b, "blockrow")).map((item) => {
6408
- if (item.id)
6409
- return /* @__PURE__ */ jsx(Block, { blockId: item.id }, item.id);
6410
- })
6411
- },
6412
- columnIndex
6413
- );
6414
- })
6415
- ]
6416
- }
6417
- ) })
6418
- }
6419
- )
6420
- ]
6499
+ ref,
6500
+ className: "bespoke-section-content",
6501
+ pos: "relative",
6502
+ align: "stretch",
6503
+ direction: mediumScreen ? "column" : "row",
6504
+ wrap: "wrap",
6505
+ ...containerProps,
6506
+ children
6421
6507
  }
6422
6508
  );
6423
6509
  }
6424
- var Section_default = Section;
6425
- function Report() {
6426
- const sectionList = useSectionList();
6427
- return /* @__PURE__ */ jsx(Container, { p: 0, pos: "relative", fluid: true, children: sectionList.isSuccess && sectionList.data.sort(orderSort).map((section) => /* @__PURE__ */ jsx(Section_default, { section }, section.id)) });
6428
- }
6429
- var Report_default = Report;
6430
-
6431
- // frontend/components/auth/LoginButton.tsx
6432
- init_esm_shims();
6433
-
6434
- // types/auth.ts
6435
- init_esm_shims();
6436
- var CMS_ROLES = {
6437
- ADMIN: "Admin",
6438
- EDITOR: "Editor",
6439
- WRITER: "Writer"
6440
- };
6441
- function BespokeLoginBtn({
6442
- buttonProps = {},
6443
- editorMenuItemProps = {},
6444
- editorMenuItemRoute = "/cms",
6445
- logoutButtonProps = {},
6446
- menuProps = {},
6447
- options = "",
6448
- optionsPosition = "bottom",
6449
- translations = {},
6450
- withEditorMenuItem = true,
6451
- withSession = true
6452
- }) {
6510
+ var SectionColumn = React.forwardRef(
6511
+ function SectionColumn2({ children, column, columnSettings, sx = {}, ...rest }, ref) {
6512
+ const hasInline = Object.values(column).some((item) => item.settings?.display === "inline");
6513
+ const width = columnSettings?.width;
6514
+ const theme = useMantineTheme();
6515
+ const mediumScreen = useMediaQuery(`(max-width: ${theme.breakpoints.md})`);
6516
+ return /* @__PURE__ */ jsx(
6517
+ Flex,
6518
+ {
6519
+ ref,
6520
+ className: "bespoke-section-col",
6521
+ align: "flex-start",
6522
+ direction: hasInline ? "row" : "column",
6523
+ wrap: hasInline ? "wrap" : "nowrap",
6524
+ maw: width && !mediumScreen ? `${width}px` : "none",
6525
+ miw: mediumScreen ? 300 : 400,
6526
+ p: site_default.column.padding,
6527
+ pos: "relative",
6528
+ sx: [{ flexGrow: 1, flexShrink: 1 }, ...packSx(sx)],
6529
+ ...rest,
6530
+ children
6531
+ }
6532
+ );
6533
+ }
6534
+ );
6535
+ var ResizeColumnInput = ({ sectionId, columnIndex }) => {
6536
+ const dispatch = useAppDispatch();
6537
+ const section = useSectionRef(sectionId).data;
6538
+ if (!section)
6539
+ return null;
6540
+ const { columnSettings = {} } = section.settings;
6541
+ const { width = void 0 } = columnSettings[columnIndex] ? columnSettings[columnIndex] : {};
6542
+ const handleChange = (e) => {
6543
+ if (section) {
6544
+ dispatch(actions_exports.updateEntity("section", {
6545
+ id: sectionId,
6546
+ settings: {
6547
+ ...section.settings,
6548
+ columnSettings: {
6549
+ ...columnSettings,
6550
+ [columnIndex]: {
6551
+ width: parseInt(e.target.value, 10)
6552
+ }
6553
+ }
6554
+ }
6555
+ }));
6556
+ }
6557
+ };
6558
+ const handleReset = () => {
6559
+ if (section) {
6560
+ dispatch(actions_exports.updateEntity("section", {
6561
+ id: sectionId,
6562
+ settings: {
6563
+ ...section.settings,
6564
+ columnSettings: {
6565
+ ...columnSettings,
6566
+ [columnIndex]: {
6567
+ width: void 0
6568
+ }
6569
+ }
6570
+ }
6571
+ }));
6572
+ }
6573
+ };
6574
+ return /* @__PURE__ */ jsx(
6575
+ Box,
6576
+ {
6577
+ className: "bespoke-resize-col",
6578
+ pos: "absolute",
6579
+ top: 0,
6580
+ left: "50%",
6581
+ sx: {
6582
+ transform: "translate(-50%, -50%)",
6583
+ zIndex: 2
6584
+ },
6585
+ p: "sm",
6586
+ maw: 110,
6587
+ children: /* @__PURE__ */ jsx(
6588
+ Input,
6589
+ {
6590
+ placeholder: "auto",
6591
+ w: "fit-content",
6592
+ miw: "none",
6593
+ variant: "filled",
6594
+ type: "number",
6595
+ value: width || "auto",
6596
+ onChange: handleChange,
6597
+ size: "xs",
6598
+ p: 0,
6599
+ rightSection: /* @__PURE__ */ jsx(IconX, { onClick: handleReset, size: 8 })
6600
+ }
6601
+ )
6602
+ }
6603
+ );
6604
+ };
6605
+ var ColumnsWrapper = React.forwardRef(SectionColumnsWrapper);
6606
+
6607
+ // libs/settings/block.tsx
6608
+ init_esm_shims();
6609
+ init_cms();
6610
+ var defaultSettings2 = {
6611
+ display: {
6612
+ label: "Size",
6613
+ defaultValue: "block",
6614
+ options: [
6615
+ { label: "Full Width", value: "block" },
6616
+ { label: "Inline", value: "inline" }
6617
+ ]
6618
+ },
6619
+ align: {
6620
+ label: "Alignment",
6621
+ defaultValue: "left",
6622
+ options: [
6623
+ { label: /* @__PURE__ */ jsx(IconAlignLeft, { size: 20 }), value: "left" },
6624
+ { label: /* @__PURE__ */ jsx(IconAlignCenter, { size: 20 }), value: "center" },
6625
+ { label: /* @__PURE__ */ jsx(IconAlignRight, { size: 20 }), value: "right" }
6626
+ ]
6627
+ }
6628
+ };
6629
+ var customSettings = {
6630
+ [BLOCK_TYPES.IMAGE]: { ...defaultSettings2 },
6631
+ [BLOCK_TYPES.PARAGRAPH]: { ...defaultSettings2 },
6632
+ [BLOCK_TYPES.SUBTITLE]: { ...defaultSettings2 },
6633
+ [BLOCK_TYPES.SELECTOR]: { ...defaultSettings2 },
6634
+ [BLOCK_TYPES.STAT]: { ...defaultSettings2 },
6635
+ [BLOCK_TYPES.VIZ]: { ...defaultSettings2 },
6636
+ [BLOCK_TYPES.TITLE]: {
6637
+ order: {
6638
+ label: "Importance",
6639
+ defaultValue: "1",
6640
+ options: [
6641
+ { label: "1", value: "1" },
6642
+ { label: "2", value: "2" },
6643
+ { label: "3", value: "3" },
6644
+ { label: "4", value: "4" },
6645
+ { label: "5", value: "5" },
6646
+ { label: "6", value: "6" }
6647
+ ]
6648
+ },
6649
+ search: {
6650
+ label: "Search on Click",
6651
+ defaultValue: "off",
6652
+ options: [
6653
+ { label: "Off", value: "off" },
6654
+ { label: "Inline", value: "inline" },
6655
+ { label: "Modal", value: "modal" }
6656
+ ]
6657
+ },
6658
+ ...defaultSettings2
6659
+ },
6660
+ [BLOCK_TYPES.GENERATOR]: {
6661
+ useProxy: {
6662
+ label: "Use proxy (avoid CORS)",
6663
+ defaultValue: "false",
6664
+ options: [
6665
+ { label: "No", value: "false" },
6666
+ { label: "Yes", value: "true" }
6667
+ ]
6668
+ }
6669
+ },
6670
+ [BLOCK_TYPES.NAV]: {
6671
+ variant: {
6672
+ label: "Nav variant",
6673
+ defaultValue: "inline",
6674
+ options: [
6675
+ { label: "Inline", value: "inline" },
6676
+ { label: "Fixed", value: "fixed" },
6677
+ { label: "Jump", value: "jump" }
6678
+ ]
6679
+ },
6680
+ min: {
6681
+ label: "Min Title level",
6682
+ defaultValue: "1",
6683
+ options: [
6684
+ { label: "1", value: "1" },
6685
+ { label: "2", value: "2" },
6686
+ { label: "3", value: "3" },
6687
+ { label: "4", value: "4" },
6688
+ { label: "5", value: "5" },
6689
+ { label: "6", value: "6" }
6690
+ ]
6691
+ },
6692
+ max: {
6693
+ label: "Max Title level",
6694
+ defaultValue: "6",
6695
+ options: [
6696
+ { label: "1", value: "1" },
6697
+ { label: "2", value: "2" },
6698
+ { label: "3", value: "3" },
6699
+ { label: "4", value: "4" },
6700
+ { label: "5", value: "5" },
6701
+ { label: "6", value: "6" }
6702
+ ]
6703
+ }
6704
+ }
6705
+ };
6706
+ var getBlockSettings = (blockType) => {
6707
+ const extraSettings = blockType && customSettings[blockType] ? customSettings[blockType] : defaultSettings2;
6708
+ return extraSettings;
6709
+ };
6710
+
6711
+ // cms/components/components/DesignMenu.tsx
6712
+ init_esm_shims();
6713
+ init_store2();
6714
+ var ALLOWED_UNITS = ["px", "%"];
6715
+ var formatters = {
6716
+ px: (value) => !Number.isNaN(parseFloat(value)) ? `${value}px`.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",") : "px",
6717
+ ["%"]: (value) => !Number.isNaN(parseFloat(value)) ? `${value}%`.replace(/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g, ",") : "%"
6718
+ };
6719
+ var WidthInputProps = {
6720
+ "px": {
6721
+ defaultValue: 400,
6722
+ min: 25,
6723
+ step: 5,
6724
+ formatter: formatters["px"]
6725
+ },
6726
+ "%": {
6727
+ defaultValue: 50,
6728
+ min: 20,
6729
+ max: 100,
6730
+ step: 5,
6731
+ formatter: formatters["%"]
6732
+ }
6733
+ };
6734
+ var defaultWidthSettings = { stretch: false, unit: "px", value: "400" };
6735
+ var UnitSelector = ({ currUnit, changeUnit }) => {
6736
+ return /* @__PURE__ */ jsxs(Group, { position: "apart", children: [
6737
+ /* @__PURE__ */ jsx(Text, { size: "xs", fw: "bold", children: "Unit" }),
6738
+ /* @__PURE__ */ jsx(Group, { spacing: 3, children: ALLOWED_UNITS.map(
6739
+ (unit) => /* @__PURE__ */ jsx(
6740
+ Anchor,
6741
+ {
6742
+ component: "button",
6743
+ size: "xs",
6744
+ td: currUnit === unit ? "underline" : "none",
6745
+ onClick: () => changeUnit(unit),
6746
+ children: unit
6747
+ },
6748
+ unit
6749
+ )
6750
+ ) })
6751
+ ] });
6752
+ };
6753
+ var getWidthSettings = (block) => {
6754
+ const widthSettings = block?.settings?.width || {};
6755
+ if (widthSettings && ["stretch", "value", "unit"].every((prop) => Object.prototype.hasOwnProperty.call(widthSettings, prop)))
6756
+ return widthSettings;
6757
+ return defaultWidthSettings;
6758
+ };
6759
+ function DesignMenu({ id, display = "button", handleChange }) {
6760
+ const dispatch = useAppDispatch();
6761
+ const block = useBlockRef(id).data;
6762
+ const [opened, setOpened] = useState(false);
6763
+ const width = getWidthSettings(block);
6764
+ const handleChangeWidth = (value) => {
6765
+ if (typeof value === "boolean") {
6766
+ const result = value ? { stretch: true } : defaultWidthSettings;
6767
+ handleChangeInternal("width", { ...width, ...result });
6768
+ } else {
6769
+ handleChangeInternal("width", { ...width, value });
6770
+ }
6771
+ };
6772
+ const handleChangeInternal = (field, value) => {
6773
+ if (block) {
6774
+ if (handleChange) {
6775
+ handleChange(field, value);
6776
+ } else {
6777
+ dispatch(actions_exports.updateEntity("block", {
6778
+ id,
6779
+ settings: { ...block.settings, [field]: value }
6780
+ }));
6781
+ }
6782
+ }
6783
+ };
6784
+ if (!block)
6785
+ return null;
6786
+ const defaultSettings3 = getBlockSettings(block.type);
6787
+ const widthInputProps = WidthInputProps[width.unit];
6788
+ const changeUnit = (newUnit) => {
6789
+ const { defaultValue } = WidthInputProps[newUnit];
6790
+ handleChangeInternal("width", {
6791
+ ...width,
6792
+ value: defaultValue,
6793
+ unit: newUnit
6794
+ });
6795
+ };
6796
+ const menu = /* @__PURE__ */ jsxs(Stack, { spacing: "xs", children: [
6797
+ Object.entries(defaultSettings3).map(([key, { label, defaultValue, options }]) => /* @__PURE__ */ jsxs(Group, { spacing: "xs", position: "apart", noWrap: true, style: { width: "100%" }, children: [
6798
+ label && /* @__PURE__ */ jsx(Text, { fz: "sm", children: label }),
6799
+ /* @__PURE__ */ jsx(
6800
+ SegmentedControl,
6801
+ {
6802
+ defaultValue: String(block.settings[key] || defaultValue),
6803
+ onChange: (e) => handleChangeInternal(key, e),
6804
+ data: options,
6805
+ size: "xs"
6806
+ }
6807
+ )
6808
+ ] }, key)),
6809
+ block.type !== "generator" && /* @__PURE__ */ jsxs(Group, { spacing: "xs", children: [
6810
+ /* @__PURE__ */ jsx(Text, { fz: "sm", children: "Width" }),
6811
+ /* @__PURE__ */ jsxs(Group, { spacing: "xs", children: [
6812
+ !width.stretch && /* @__PURE__ */ jsxs("div", { children: [
6813
+ /* @__PURE__ */ jsx(UnitSelector, { currUnit: width.unit, changeUnit }),
6814
+ /* @__PURE__ */ jsx(
6815
+ NumberInput,
6816
+ {
6817
+ defaultValue: parseInt(widthInputProps.defaultValue, 10),
6818
+ disabled: width.stretch,
6819
+ onChange: (value) => handleChangeWidth(value),
6820
+ size: "xs",
6821
+ value: !Number.isNaN(width.value) ? parseInt(width.value, 10) : void 0,
6822
+ ...widthInputProps
6823
+ }
6824
+ )
6825
+ ] }),
6826
+ /* @__PURE__ */ jsx(
6827
+ Checkbox,
6828
+ {
6829
+ size: "xs",
6830
+ label: "Stretch",
6831
+ checked: width.stretch,
6832
+ onChange: (e) => handleChangeWidth(e.currentTarget.checked)
6833
+ }
6834
+ )
6835
+ ] })
6836
+ ] }, "width")
6837
+ ] });
6838
+ return display === "button" ? /* @__PURE__ */ jsxs(
6839
+ Popover,
6840
+ {
6841
+ opened,
6842
+ onClose: () => setOpened(false),
6843
+ position: "bottom-end",
6844
+ withinPortal: true,
6845
+ children: [
6846
+ /* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx(
6847
+ ActionIcon,
6848
+ {
6849
+ onClick: () => setOpened((o) => !o),
6850
+ children: /* @__PURE__ */ jsx(IconPalette, { size: 20 })
6851
+ }
6852
+ ) }),
6853
+ /* @__PURE__ */ jsx(Popover.Dropdown, { children: menu })
6854
+ ]
6855
+ }
6856
+ ) : /* @__PURE__ */ jsx(Paper, { p: "md", withBorder: true, children: menu });
6857
+ }
6858
+ var DesignMenu_default = DesignMenu;
6859
+ var getStyles = (styles, settings) => (theme) => styles ? styles(theme, settings) : {};
6860
+ var PositionWrapper = ({ settings, styles, children, ...props }) => {
6861
+ const { position } = settings;
6862
+ const defaultStyles = {
6863
+ "normal": {
6864
+ position: "relative",
6865
+ backgroundColor: "transparent",
6866
+ borderRadius: 0
6867
+ },
6868
+ "sticky": {
6869
+ position: "sticky",
6870
+ zIndex: 3,
6871
+ top: 0,
6872
+ borderRadius: 0,
6873
+ borderTop: "none",
6874
+ borderLeft: "none",
6875
+ borderRight: "none"
6876
+ }
6877
+ };
6878
+ const defaultProps = {
6879
+ "normal": {
6880
+ radius: 0
6881
+ },
6882
+ "sticky": {
6883
+ radius: 0,
6884
+ withBorder: true
6885
+ }
6886
+ };
6887
+ const sx = [defaultStyles[position], getStyles(styles, settings)];
6888
+ return /* @__PURE__ */ jsx(Paper, { component: "section", sx, ...defaultProps[position], ...props, children });
6889
+ };
6890
+ var WidthWrapper = ({ settings, styles, children, ...props }) => {
6891
+ const { width: container } = settings;
6892
+ const defaultStyles = {
6893
+ "center": {},
6894
+ "full": {}
6895
+ };
6896
+ const defaultProps = {
6897
+ "center": { size: "lg", p: "sm", fluid: false },
6898
+ "full": { fluid: true, p: "md" }
6899
+ };
6900
+ const sx = [defaultStyles[container], getStyles(styles, settings)];
6901
+ return /* @__PURE__ */ jsx(Container, { sx, ...defaultProps[container], ...props, children });
6902
+ };
6903
+ var StyleWrapper = ({ settings, styles, children, ...props }) => {
6904
+ const { style: variant } = settings;
6905
+ const defaultStyles = {
6906
+ "none": {},
6907
+ "card": {}
6908
+ };
6909
+ const defaultProps = {
6910
+ "none": { bg: "transparent" },
6911
+ "card": { shadow: "lg", p: "md", radius: "md" }
6912
+ };
6913
+ const sx = [defaultStyles[variant], getStyles(styles, settings)];
6914
+ return /* @__PURE__ */ jsx(Paper, { sx, ...defaultProps[variant], ...props, children });
6915
+ };
6916
+ function Section({ section }) {
6917
+ const { id, settings } = section;
6918
+ const sectionSettings2 = {
6919
+ ...defaultSectionSettings,
6920
+ ...settings
6921
+ };
6922
+ const state = useAppSelector((state2) => state2);
6923
+ const status = useAppSelector((state2) => state2.variables.status);
6924
+ const sectionStyles = useBespokeStyles()["Section"];
6925
+ const blockRecords = selectBlockRecords(state);
6926
+ const sectionBlocks = Object.values(blockRecords || {}).filter((d) => d.section_id === id);
6927
+ const allowedSection = sectionBlocks.some((b) => {
6928
+ try {
6929
+ return status[b.id].allowed && b.type !== BLOCK_TYPES.GENERATOR || b.type === BLOCK_TYPES.NAV;
6930
+ } catch (e) {
6931
+ return b.settings.allowed === "always";
6932
+ }
6933
+ });
6934
+ const columns = sectionBlocks.reduce((acc, d) => {
6935
+ if (!acc[d.blockcol]) {
6936
+ acc[d.blockcol] = { [d.blockrow]: d };
6937
+ } else {
6938
+ acc[d.blockcol][d.blockrow] = d;
6939
+ }
6940
+ return acc;
6941
+ }, {});
6942
+ const blockSettings = getBlockSettings();
6943
+ const displaySection = Object.keys(blockRecords).length > 0 && !settings.hidden && allowedSection;
6944
+ const colsQty = Object.keys(columns).length;
6945
+ if (!displaySection)
6946
+ return null;
6947
+ return /* @__PURE__ */ jsxs(
6948
+ PositionWrapper,
6949
+ {
6950
+ settings: sectionSettings2,
6951
+ styles: sectionStyles?.root || void 0,
6952
+ children: [
6953
+ sectionSettings2.memberImageBg && /* @__PURE__ */ jsx(SectionBackground, {}),
6954
+ /* @__PURE__ */ jsxs(
6955
+ WidthWrapper,
6956
+ {
6957
+ settings: sectionSettings2,
6958
+ styles: sectionStyles?.container,
6959
+ id: `section-${id}`,
6960
+ pos: "relative",
6961
+ children: [
6962
+ /* @__PURE__ */ jsxs("div", { style: {
6963
+ position: "absolute",
6964
+ right: 10,
6965
+ top: 10,
6966
+ zIndex: 3
6967
+ }, children: [
6968
+ sectionSettings2.optionsMenu && /* @__PURE__ */ jsx(Options, { sectionId: section.id }),
6969
+ /* @__PURE__ */ jsx(SectionResetButton, { id: section.id })
6970
+ ] }),
6971
+ /* @__PURE__ */ jsx(StyleWrapper, { className: "bespoke-section-content", settings: sectionSettings2, styles: sectionStyles?.content, children: /* @__PURE__ */ jsx(ColumnsWrapper, { children: Object.keys(columns).sort((a, b) => orderSort(a, b, "blockcol")).map((columnIndex) => {
6972
+ const column = columns[columnIndex];
6973
+ const columnSettings = settings.columnSettings ? settings.columnSettings[columnIndex] : {};
6974
+ return /* @__PURE__ */ jsx(
6975
+ SectionColumn,
6976
+ {
6977
+ column,
6978
+ columnSettings,
6979
+ sx: { flexBasis: `${100 / colsQty}%` },
6980
+ children: Object.values(column).sort((a, b) => orderSort(a, b, "blockrow")).map((item) => {
6981
+ if (!item.id)
6982
+ return null;
6983
+ const { settings: settings2, type } = blockRecords[item.id];
6984
+ const blockWidth = settings2.width && !settings2.width.stretch && settings2.width.unit ? formatters[settings2.width.unit](settings2.width.value) : settings2.display === "inline" ? "auto" : "100%";
6985
+ const blockStyles = {
6986
+ alignSelf: type === "visualization" ? "stretch" : "flex-start",
6987
+ flexGrow: 0,
6988
+ margin: "0",
6989
+ textAlign: settings2.align || blockSettings.align.defaultValue,
6990
+ width: blockWidth,
6991
+ minWidth: 300
6992
+ };
6993
+ return /* @__PURE__ */ jsx(Box, { sx: blockStyles, py: site_default.block.padding, children: /* @__PURE__ */ jsx(Block, { blockId: item.id }, item.id) }, item.id);
6994
+ })
6995
+ },
6996
+ columnIndex
6997
+ );
6998
+ }) }) })
6999
+ ]
7000
+ }
7001
+ )
7002
+ ]
7003
+ }
7004
+ );
7005
+ }
7006
+ var Section_default = Section;
7007
+ function Report() {
7008
+ const sectionList = useSectionList();
7009
+ return /* @__PURE__ */ jsx(Container, { p: 0, pos: "relative", fluid: true, children: sectionList.isSuccess && sectionList.data.sort(orderSort).map((section) => /* @__PURE__ */ jsx(Section_default, { section }, section.id)) });
7010
+ }
7011
+ var Report_default = Report;
7012
+
7013
+ // frontend/components/auth/LoginButton.tsx
7014
+ init_esm_shims();
7015
+
7016
+ // types/auth.ts
7017
+ init_esm_shims();
7018
+ var CMS_ROLES = {
7019
+ ADMIN: "Admin",
7020
+ EDITOR: "Editor",
7021
+ WRITER: "Writer"
7022
+ };
7023
+ function BespokeLoginBtn({
7024
+ buttonProps = {},
7025
+ editorMenuItemProps = {},
7026
+ editorMenuItemRoute = "/cms",
7027
+ logoutButtonProps = {},
7028
+ menuProps = {},
7029
+ options = "",
7030
+ optionsPosition = "bottom",
7031
+ translations = {},
7032
+ withEditorMenuItem = true,
7033
+ withSession = true
7034
+ }) {
6453
7035
  const { user, error, isLoading } = useUser();
6454
7036
  const userRoles = useMemo(() => user?.bespoke_roles || [], [user]);
6455
7037
  const isCMSUser = useMemo(() => CMS_ROLES && Object.keys(CMS_ROLES).length > 0 && Object.keys(CMS_ROLES).some((role) => userRoles.includes(CMS_ROLES[role])), [userRoles]);
@@ -8102,278 +8684,76 @@ function CMSHeader(props) {
8102
8684
  variant: "outline",
8103
8685
  onClick: handlers.open,
8104
8686
  children: "Import Data"
8105
- }
8106
- )
8107
- ] })
8108
- ] }),
8109
- right: /* @__PURE__ */ jsxs(Group, { spacing: "xs", children: [
8110
- /* @__PURE__ */ jsxs(Menu, { shadow: "md", children: [
8111
- /* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(ActionIcon, { color: "blue", variant: "filled", children: /* @__PURE__ */ jsx(IconSettings, { size: 20 }) }) }),
8112
- /* @__PURE__ */ jsxs(Menu.Dropdown, { children: [
8113
- /* @__PURE__ */ jsx(Menu.Label, { children: "Revalidate" }),
8114
- /* @__PURE__ */ jsx(Menu.Item, { onClick: maybeRevalidateUrl, icon: /* @__PURE__ */ jsx(IconFileOff, { size: 20 }), children: /* @__PURE__ */ jsxs(Text, { children: [
8115
- "Revalidate ",
8116
- /* @__PURE__ */ jsx(Text, { fw: 700, children: previewName })
8117
- ] }) }),
8118
- /* @__PURE__ */ jsx(Menu.Item, { onClick: maybeRevalidateReport, icon: /* @__PURE__ */ jsx(IconFilesOff, { size: 20 }), children: /* @__PURE__ */ jsxs(Text, { children: [
8119
- "Revalidate ALL ",
8120
- /* @__PURE__ */ jsx(Text, { fw: 700, children: currentReport.name })
8121
- ] }) }),
8122
- /* @__PURE__ */ jsx(Menu.Label, { children: "Settings" }),
8123
- /* @__PURE__ */ jsx(Menu.Item, { onClick: handlers.open, icon: /* @__PURE__ */ jsx(IconSettings, { size: 20 }), children: "Report settings" }),
8124
- /* @__PURE__ */ jsx(Menu.Item, { onClick: handlersGraph.open, icon: /* @__PURE__ */ jsx(IconHierarchy3, { size: 20 }), children: "Block Graph" })
8125
- ] })
8126
- ] }),
8127
- /* @__PURE__ */ jsx(Modal, { opened: openedGraph, onClose: handlersGraph.close, title: "Block Graph", fullScreen: true, children: /* @__PURE__ */ jsx(BlockGraph, {}) }),
8128
- /* @__PURE__ */ jsx(
8129
- Drawer,
8130
- {
8131
- opened,
8132
- onClose: handlers.close,
8133
- title: /* @__PURE__ */ jsx(IconTitle, { icon: /* @__PURE__ */ jsx(IconFileAnalytics, { size: 24 }), children: `Editing Report: ${currentReport ? currentReport.name : ""}` }),
8134
- size: "50%",
8135
- padding: "xl",
8136
- position: "right",
8137
- children: /* @__PURE__ */ jsx(ReportEditor, { id, onClose: handlers.close })
8138
- }
8139
- )
8140
- ] })
8141
- }
8142
- );
8143
- }
8144
- var selectLocaleOptions = (state) => state.status.locales.map((d) => ({ value: d, label: d.toUpperCase() }));
8145
-
8146
- // components/sections/Section.tsx
8147
- init_esm_shims();
8148
-
8149
- // components/blocks/BlockElement.tsx
8150
- init_esm_shims();
8151
-
8152
- // cms/components/components/DeleteButton.tsx
8153
- init_esm_shims();
8154
- init_store2();
8155
- init_cms();
8156
- function DeleteButton({ type, id, warning = "" }) {
8157
- const PRETTY_NAME = ENTITY_PRETTY_NAMES[type] || "Entity";
8158
- const message = warning || `Delete this ${PRETTY_NAME} and all its contents? This action cannot be undone.`;
8159
- const dispatch = useDispatch();
8160
- const { newConfirmation } = useDialog();
8161
- const maybeDelete = async () => {
8162
- try {
8163
- await newConfirmation({
8164
- title: "Are you sure?",
8165
- message,
8166
- confirmText: "Yes, Delete it."
8167
- });
8168
- dispatch(actions_exports.deleteEntity(type, id));
8169
- } catch {
8170
- }
8171
- };
8172
- return /* @__PURE__ */ jsx(ActionIcon, { color: "red", onClick: maybeDelete, children: /* @__PURE__ */ jsx(IconTrash, { size: 20 }) });
8173
- }
8174
- var DeleteButton_default = DeleteButton;
8175
-
8176
- // cms/components/components/DesignMenu.tsx
8177
- init_esm_shims();
8178
-
8179
- // libs/settings/block.tsx
8180
- init_esm_shims();
8181
- init_cms();
8182
- var defaultSettings2 = {
8183
- display: {
8184
- label: "Size",
8185
- defaultValue: "block",
8186
- options: [
8187
- { label: "Full Width", value: "block" },
8188
- { label: "Inline", value: "inline" }
8189
- ]
8190
- },
8191
- align: {
8192
- label: "Alignment",
8193
- defaultValue: "left",
8194
- options: [
8195
- { label: /* @__PURE__ */ jsx(IconAlignLeft, { size: 20 }), value: "left" },
8196
- { label: /* @__PURE__ */ jsx(IconAlignCenter, { size: 20 }), value: "center" },
8197
- { label: /* @__PURE__ */ jsx(IconAlignRight, { size: 20 }), value: "right" }
8198
- ]
8199
- }
8200
- };
8201
- var customSettings = {
8202
- [BLOCK_TYPES.IMAGE]: { ...defaultSettings2 },
8203
- [BLOCK_TYPES.PARAGRAPH]: { ...defaultSettings2 },
8204
- [BLOCK_TYPES.SUBTITLE]: { ...defaultSettings2 },
8205
- [BLOCK_TYPES.SELECTOR]: { ...defaultSettings2 },
8206
- [BLOCK_TYPES.STAT]: { ...defaultSettings2 },
8207
- [BLOCK_TYPES.VIZ]: { ...defaultSettings2 },
8208
- [BLOCK_TYPES.TITLE]: {
8209
- order: {
8210
- label: "Importance",
8211
- defaultValue: "1",
8212
- options: [
8213
- { label: "1", value: "1" },
8214
- { label: "2", value: "2" },
8215
- { label: "3", value: "3" },
8216
- { label: "4", value: "4" },
8217
- { label: "5", value: "5" },
8218
- { label: "6", value: "6" }
8219
- ]
8220
- },
8221
- search: {
8222
- label: "Search on Click",
8223
- defaultValue: "off",
8224
- options: [
8225
- { label: "Off", value: "off" },
8226
- { label: "Inline", value: "inline" },
8227
- { label: "Modal", value: "modal" }
8228
- ]
8229
- },
8230
- ...defaultSettings2
8231
- },
8232
- [BLOCK_TYPES.GENERATOR]: {
8233
- useProxy: {
8234
- label: "Use proxy (avoid CORS)",
8235
- defaultValue: "false",
8236
- options: [
8237
- { label: "No", value: "false" },
8238
- { label: "Yes", value: "true" }
8239
- ]
8240
- }
8241
- },
8242
- [BLOCK_TYPES.NAV]: {
8243
- variant: {
8244
- label: "Nav variant",
8245
- defaultValue: "inline",
8246
- options: [
8247
- { label: "Inline", value: "inline" },
8248
- { label: "Fixed", value: "fixed" },
8249
- { label: "Jump", value: "jump" }
8250
- ]
8251
- },
8252
- min: {
8253
- label: "Min Title level",
8254
- defaultValue: "1",
8255
- options: [
8256
- { label: "1", value: "1" },
8257
- { label: "2", value: "2" },
8258
- { label: "3", value: "3" },
8259
- { label: "4", value: "4" },
8260
- { label: "5", value: "5" },
8261
- { label: "6", value: "6" }
8262
- ]
8263
- },
8264
- max: {
8265
- label: "Max Title level",
8266
- defaultValue: "6",
8267
- options: [
8268
- { label: "1", value: "1" },
8269
- { label: "2", value: "2" },
8270
- { label: "3", value: "3" },
8271
- { label: "4", value: "4" },
8272
- { label: "5", value: "5" },
8273
- { label: "6", value: "6" }
8274
- ]
8275
- }
8276
- }
8277
- };
8278
- var getBlockSettings = (blockType) => {
8279
- const extraSettings = blockType && customSettings[blockType] ? customSettings[blockType] : defaultSettings2;
8280
- return extraSettings;
8281
- };
8282
-
8283
- // cms/components/components/DesignMenu.tsx
8284
- init_store2();
8285
- function DesignMenu({ id, display = "button", handleChange }) {
8286
- const dispatch = useAppDispatch();
8287
- const block = useBlockRef(id).data;
8288
- const [opened, setOpened] = useState(false);
8289
- const defaultWidth = "400";
8290
- const handleChangeWidth = (value) => {
8291
- let result;
8292
- if (typeof value === "boolean") {
8293
- result = value ? "stretch" : String(defaultWidth);
8294
- } else {
8295
- result = value;
8296
- }
8297
- handleChangeInternal("width", result);
8298
- };
8299
- const handleChangeInternal = (field, value) => {
8300
- if (block) {
8301
- if (handleChange) {
8302
- handleChange(field, value);
8303
- } else {
8304
- dispatch(actions_exports.updateEntity("block", {
8305
- id,
8306
- settings: { ...block.settings, [field]: value }
8307
- }));
8308
- }
8309
- }
8310
- };
8311
- if (!block)
8312
- return null;
8313
- const defaultSettings3 = getBlockSettings(block.type);
8314
- const width = block.settings?.width ?? "stretch";
8315
- const menu = /* @__PURE__ */ jsxs(Stack, { spacing: "xs", children: [
8316
- Object.entries(defaultSettings3).map(([key, { label, defaultValue, options }]) => /* @__PURE__ */ jsxs(Group, { spacing: "xs", position: "apart", noWrap: true, style: { width: "100%" }, children: [
8317
- label && /* @__PURE__ */ jsx(Text, { fz: "sm", children: label }),
8318
- /* @__PURE__ */ jsx(
8319
- SegmentedControl,
8320
- {
8321
- defaultValue: String(block.settings[key] || defaultValue),
8322
- onChange: (e) => handleChangeInternal(key, e),
8323
- data: options,
8324
- size: "xs"
8325
- }
8326
- )
8327
- ] }, key)),
8328
- block.type !== "generator" && /* @__PURE__ */ jsxs(Group, { spacing: "xs", children: [
8329
- /* @__PURE__ */ jsx(Text, { fz: "sm", children: "Width" }),
8330
- /* @__PURE__ */ jsxs(Group, { spacing: "xs", children: [
8331
- width !== "stretch" && /* @__PURE__ */ jsx(
8332
- NumberInput,
8333
- {
8334
- defaultValue: parseInt(defaultWidth, 10),
8335
- disabled: width === "stretch",
8336
- min: 25,
8337
- onChange: (value) => handleChangeWidth(value),
8338
- placeholder: width === "stretch" ? defaultWidth : width,
8339
- step: 5,
8340
- style: { width: 80 },
8341
- value: !Number.isNaN(width) ? parseInt(width, 10) : void 0
8342
- }
8343
- ),
8687
+ }
8688
+ )
8689
+ ] })
8690
+ ] }),
8691
+ right: /* @__PURE__ */ jsxs(Group, { spacing: "xs", children: [
8692
+ /* @__PURE__ */ jsxs(Menu, { shadow: "md", children: [
8693
+ /* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(ActionIcon, { color: "blue", variant: "filled", children: /* @__PURE__ */ jsx(IconSettings, { size: 20 }) }) }),
8694
+ /* @__PURE__ */ jsxs(Menu.Dropdown, { children: [
8695
+ /* @__PURE__ */ jsx(Menu.Label, { children: "Revalidate" }),
8696
+ /* @__PURE__ */ jsx(Menu.Item, { onClick: maybeRevalidateUrl, icon: /* @__PURE__ */ jsx(IconFileOff, { size: 20 }), children: /* @__PURE__ */ jsxs(Text, { children: [
8697
+ "Revalidate ",
8698
+ /* @__PURE__ */ jsx(Text, { fw: 700, children: previewName })
8699
+ ] }) }),
8700
+ /* @__PURE__ */ jsx(Menu.Item, { onClick: maybeRevalidateReport, icon: /* @__PURE__ */ jsx(IconFilesOff, { size: 20 }), children: /* @__PURE__ */ jsxs(Text, { children: [
8701
+ "Revalidate ALL ",
8702
+ /* @__PURE__ */ jsx(Text, { fw: 700, children: currentReport.name })
8703
+ ] }) }),
8704
+ /* @__PURE__ */ jsx(Menu.Label, { children: "Settings" }),
8705
+ /* @__PURE__ */ jsx(Menu.Item, { onClick: handlers.open, icon: /* @__PURE__ */ jsx(IconSettings, { size: 20 }), children: "Report settings" }),
8706
+ /* @__PURE__ */ jsx(Menu.Item, { onClick: handlersGraph.open, icon: /* @__PURE__ */ jsx(IconHierarchy3, { size: 20 }), children: "Block Graph" })
8707
+ ] })
8708
+ ] }),
8709
+ /* @__PURE__ */ jsx(Modal, { opened: openedGraph, onClose: handlersGraph.close, title: "Block Graph", fullScreen: true, children: /* @__PURE__ */ jsx(BlockGraph, {}) }),
8344
8710
  /* @__PURE__ */ jsx(
8345
- Checkbox,
8711
+ Drawer,
8346
8712
  {
8347
- size: "xs",
8348
- label: "Stretch",
8349
- checked: width === "stretch",
8350
- onChange: (e) => handleChangeWidth(e.currentTarget.checked)
8713
+ opened,
8714
+ onClose: handlers.close,
8715
+ title: /* @__PURE__ */ jsx(IconTitle, { icon: /* @__PURE__ */ jsx(IconFileAnalytics, { size: 24 }), children: `Editing Report: ${currentReport ? currentReport.name : ""}` }),
8716
+ size: "50%",
8717
+ padding: "xl",
8718
+ position: "right",
8719
+ children: /* @__PURE__ */ jsx(ReportEditor, { id, onClose: handlers.close })
8351
8720
  }
8352
8721
  )
8353
8722
  ] })
8354
- ] }, "width")
8355
- ] });
8356
- return display === "button" ? /* @__PURE__ */ jsxs(
8357
- Popover,
8358
- {
8359
- opened,
8360
- onClose: () => setOpened(false),
8361
- position: "bottom-end",
8362
- withinPortal: true,
8363
- children: [
8364
- /* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx(
8365
- ActionIcon,
8366
- {
8367
- onClick: () => setOpened((o) => !o),
8368
- children: /* @__PURE__ */ jsx(IconPalette, { size: 20 })
8369
- }
8370
- ) }),
8371
- /* @__PURE__ */ jsx(Popover.Dropdown, { children: menu })
8372
- ]
8373
8723
  }
8374
- ) : /* @__PURE__ */ jsx(Paper, { p: "md", withBorder: true, children: menu });
8724
+ );
8375
8725
  }
8376
- var DesignMenu_default = DesignMenu;
8726
+ var selectLocaleOptions = (state) => state.status.locales.map((d) => ({ value: d, label: d.toUpperCase() }));
8727
+
8728
+ // components/sections/Section.tsx
8729
+ init_esm_shims();
8730
+
8731
+ // components/blocks/BlockElement.tsx
8732
+ init_esm_shims();
8733
+
8734
+ // cms/components/components/DeleteButton.tsx
8735
+ init_esm_shims();
8736
+ init_store2();
8737
+ init_cms();
8738
+ function DeleteButton({ type, id, warning = "" }) {
8739
+ const PRETTY_NAME = ENTITY_PRETTY_NAMES[type] || "Entity";
8740
+ const message = warning || `Delete this ${PRETTY_NAME} and all its contents? This action cannot be undone.`;
8741
+ const dispatch = useDispatch();
8742
+ const { newConfirmation } = useDialog();
8743
+ const maybeDelete = async () => {
8744
+ try {
8745
+ await newConfirmation({
8746
+ title: "Are you sure?",
8747
+ message,
8748
+ confirmText: "Yes, Delete it."
8749
+ });
8750
+ dispatch(actions_exports.deleteEntity(type, id));
8751
+ } catch {
8752
+ }
8753
+ };
8754
+ return /* @__PURE__ */ jsx(ActionIcon, { color: "red", onClick: maybeDelete, children: /* @__PURE__ */ jsx(IconTrash, { size: 20 }) });
8755
+ }
8756
+ var DeleteButton_default = DeleteButton;
8377
8757
 
8378
8758
  // components/blocks/Block.tsx
8379
8759
  init_esm_shims();
@@ -8630,9 +9010,9 @@ function BlockPreview(props) {
8630
9010
  return /* @__PURE__ */ jsxs(
8631
9011
  "div",
8632
9012
  {
8633
- id: `${block.type}-${block.id}`,
8634
- className: "cms-block-preview",
8635
- style: { width: "100%", minHeight: block.type === BLOCK_TYPES.VIZ ? 300 : "auto" },
9013
+ id: `bespoke-${block.type}-${block.id}`,
9014
+ className: "cms-block-preview bespoke-block-area",
9015
+ style: { width: "100%", minHeight: block.type === BLOCK_TYPES.VIZ ? 400 : "auto" },
8636
9016
  children: [
8637
9017
  !allowed && allowedOverlay,
8638
9018
  Renderer ? /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsx(Renderer, { id: block.id, debug, ...content, settings: block.settings }) }, "renderer") : /* @__PURE__ */ jsx(Center, { style: { minHeight: 100 }, children: /* @__PURE__ */ jsx(Badge, { color: "gray", variant: "outline", children: block.type }, "type") }),
@@ -9266,6 +9646,7 @@ function BlockEditor({
9266
9646
  executeButton
9267
9647
  }
9268
9648
  );
9649
+ const isVizOrGenerator = [BLOCK_TYPES.GENERATOR, BLOCK_TYPES.VIZ].includes(blockType);
9269
9650
  return /* @__PURE__ */ jsxs(Grid, { children: [
9270
9651
  /* @__PURE__ */ jsxs(
9271
9652
  Col,
@@ -9317,7 +9698,7 @@ function BlockEditor({
9317
9698
  height: "100%"
9318
9699
  },
9319
9700
  children: [
9320
- ![BLOCK_TYPES.GENERATOR, BLOCK_TYPES.VIZ].includes(blockType) && /* @__PURE__ */ jsxs(Alert, { icon: /* @__PURE__ */ jsx(IconFlag, {}), children: [
9701
+ isVizOrGenerator && /* @__PURE__ */ jsxs(Alert, { icon: /* @__PURE__ */ jsx(IconFlag, {}), children: [
9321
9702
  "You are editing the ",
9322
9703
  /* @__PURE__ */ jsx(Code, { children: locale.toUpperCase() }),
9323
9704
  " version of the block."
@@ -9366,7 +9747,12 @@ function BlockEditor({
9366
9747
  ] }),
9367
9748
  "and ",
9368
9749
  /* @__PURE__ */ jsx(Code, { children: "router" }),
9369
- " in the scope of this generator."
9750
+ " in the scope of this generator.",
9751
+ isVizOrGenerator && /* @__PURE__ */ jsxs(Fragment, { children: [
9752
+ " Return a property called",
9753
+ /* @__PURE__ */ jsx(Code, { children: "_api" }),
9754
+ " as string, to let the user download that data and override api value."
9755
+ ] })
9370
9756
  ] }),
9371
9757
  codeEditor,
9372
9758
  /* @__PURE__ */ jsx(Divider, { my: "sm", color: "gray.8" }),
@@ -9642,27 +10028,6 @@ var Block_default = Block2;
9642
10028
 
9643
10029
  // components/blocks/BlockElement.tsx
9644
10030
  init_store2();
9645
-
9646
- // libs/settings/site.ts
9647
- init_esm_shims();
9648
- var site_default = {
9649
- backgroundColor: "#fafafa",
9650
- block: {
9651
- padding: 10
9652
- },
9653
- column: {
9654
- padding: 12
9655
- },
9656
- section: {
9657
- backgroundColor: "white",
9658
- borderRadius: 10,
9659
- boxShadow: "0px 6px 10px rgba(12, 32, 50, 0.14), 0px 1px 15px rgba(12, 32, 50, 0.12), 0px 3px 5px rgba(12, 32, 50, 0.15)",
9660
- margin: 16,
9661
- padding: 32
9662
- }
9663
- };
9664
-
9665
- // components/blocks/BlockElement.tsx
9666
10031
  init_cms();
9667
10032
  init_hooks();
9668
10033
  function BlockElement({
@@ -9670,12 +10035,12 @@ function BlockElement({
9670
10035
  setHoverBlock,
9671
10036
  isInput,
9672
10037
  isConsumer,
9673
- active,
9674
- sectionState
10038
+ active
9675
10039
  }) {
9676
10040
  const currentLocale = useAppSelector((state) => state.status.currentLocale);
9677
10041
  const block = useBlockRef(id).data;
9678
10042
  const blockStatus = useBlockStatus(id);
10043
+ const [showOptions, setShowOptions] = useState(false);
9679
10044
  const { newConfirmation } = useDialog();
9680
10045
  const [opened, setOpened] = useState(false);
9681
10046
  const [modified, setModified] = useState(false);
@@ -9733,12 +10098,29 @@ function BlockElement({
9733
10098
  Group,
9734
10099
  {
9735
10100
  id: `cms-block-${id}`,
10101
+ onMouseOver: () => setShowOptions(true),
10102
+ onMouseOut: () => setShowOptions(false),
9736
10103
  className: "cr-section-block",
10104
+ pos: "relative",
10105
+ py: site_default.block.padding,
9737
10106
  ...hoverActions,
9738
- style: {
9739
- padding: site_default.block.padding,
9740
- position: "relative"
9741
- },
10107
+ sx: (theme2) => ({
10108
+ border: "1px solid transparent",
10109
+ resize: "horizontal",
10110
+ "&:hover": {
10111
+ border: `1px solid ${theme2.colors.blue[2]}`
10112
+ },
10113
+ "&:hover::before": {
10114
+ position: "absolute",
10115
+ top: 0,
10116
+ left: 0,
10117
+ fontSize: 8,
10118
+ color: theme2.colors.blue[5],
10119
+ transform: "translateY(-100%)",
10120
+ content: `"Block ${id}"`,
10121
+ width: "fit-content"
10122
+ }
10123
+ }),
9742
10124
  children: [
9743
10125
  /* @__PURE__ */ jsx(
9744
10126
  BlockPreview_default,
@@ -9752,7 +10134,7 @@ function BlockElement({
9752
10134
  },
9753
10135
  "bp"
9754
10136
  ),
9755
- /* @__PURE__ */ jsxs(
10137
+ (showOptions || isInput || isConsumer) && /* @__PURE__ */ jsxs(
9756
10138
  Group,
9757
10139
  {
9758
10140
  spacing: 0,
@@ -9806,7 +10188,8 @@ function SectionHeader({
9806
10188
  isDragging,
9807
10189
  id,
9808
10190
  dragHandleProps,
9809
- hidden
10191
+ hidden,
10192
+ generators
9810
10193
  }) {
9811
10194
  return /* @__PURE__ */ jsxs(
9812
10195
  Group,
@@ -9820,7 +10203,17 @@ function SectionHeader({
9820
10203
  "#",
9821
10204
  id || "hello"
9822
10205
  ] }, "s1"),
9823
- /* @__PURE__ */ jsx(ActionIcon, { ...dragHandleProps, children: /* @__PURE__ */ jsx(IconMenu, { size: 16 }) }, "b1")
10206
+ /* @__PURE__ */ jsx(ActionIcon, { ...dragHandleProps, children: /* @__PURE__ */ jsx(IconMenu, { size: 16 }) }, "b1"),
10207
+ /* @__PURE__ */ jsx(
10208
+ Switch,
10209
+ {
10210
+ size: "xs",
10211
+ label: "Show generators",
10212
+ color: "green",
10213
+ checked: generators.showGenerators,
10214
+ onChange: (e) => generators.setShowGenerators(e.currentTarget.checked)
10215
+ }
10216
+ )
9824
10217
  ] }),
9825
10218
  hidden && /* @__PURE__ */ jsx(Text, { size: "xs", fw: 600, color: "dark.3", children: "Section will be hidden on the frontend" }),
9826
10219
  /* @__PURE__ */ jsx(SectionMenu_default, { sectionId: id })
@@ -9832,28 +10225,8 @@ function SectionHeader({
9832
10225
  // components/sections/Section.tsx
9833
10226
  init_cms();
9834
10227
  var blockTypes = Object.values(BLOCK_TYPES);
9835
- function SectionEditor({
9836
- for: section,
9837
- isDragging,
9838
- isActive,
9839
- onActivate,
9840
- dragHandleProps
9841
- }) {
10228
+ var CreateBlockButton = ({ columns, columnIndex, section }) => {
9842
10229
  const dispatch = useAppDispatch();
9843
- const [columns, setColumns] = useState({});
9844
- const [sectionState, setSectionState2] = useSetState({});
9845
- const blocks = useAppSelector((state) => state.records.entities.block);
9846
- const blockSettings = getBlockSettings();
9847
- const { memberImageBg, optionsMenu, hidden } = section.settings;
9848
- const [hoverBlock, setHoverBlock] = useState();
9849
- const { inputs, consumers } = useMemo(() => {
9850
- if (hoverBlock) {
9851
- const block = blocks[hoverBlock];
9852
- const { inputs: inputs2, consumers: consumers2 } = block;
9853
- return { inputs: inputs2, consumers: consumers2 };
9854
- }
9855
- return { inputs: [], consumers: [] };
9856
- }, [hoverBlock]);
9857
10230
  const addBlock = (type, targetColumn = false) => {
9858
10231
  let blockrow = FIRST_POSITION;
9859
10232
  let blockcol = FIRST_POSITION;
@@ -9872,29 +10245,130 @@ function SectionEditor({
9872
10245
  locales: locales4
9873
10246
  }));
9874
10247
  };
9875
- useEffect(() => {
9876
- const columns2 = Object.values(blocks || {}).filter((d) => d.section_id === section.id).reduce((acc, d) => {
9877
- if (!acc[d.blockcol]) {
9878
- acc[d.blockcol] = { [d.blockrow]: d };
9879
- } else {
9880
- acc[d.blockcol][d.blockrow] = d;
10248
+ return /* @__PURE__ */ jsx(Center, { w: "100%", py: "sm", children: /* @__PURE__ */ jsx(
10249
+ EntityCreateButton,
10250
+ {
10251
+ fields: [{
10252
+ type: "select",
10253
+ name: "type",
10254
+ label: "Block Type",
10255
+ options: blockTypes.map((d) => ({ label: d, value: d }))
10256
+ }],
10257
+ onSubmit: (value) => addBlock(value.type, columnIndex),
10258
+ target: /* @__PURE__ */ jsx(ActionIcon, { size: "md", radius: "lg", children: /* @__PURE__ */ jsx(IconCirclePlus, { size: 20 }) })
10259
+ }
10260
+ ) });
10261
+ };
10262
+ var FirstBlockButton = ({ columns, section, show = false }) => {
10263
+ if (!show)
10264
+ return null;
10265
+ return /* @__PURE__ */ jsx(Center, { w: "100%", children: /* @__PURE__ */ jsxs("div", { children: [
10266
+ /* @__PURE__ */ jsx(Text, { ta: "center", fw: 700, size: "sm", color: "gray.8", children: "Add your first block!" }),
10267
+ /* @__PURE__ */ jsx(CreateBlockButton, { columnIndex: false, columns, section })
10268
+ ] }) });
10269
+ };
10270
+ var CreateColumnArea = ({ active = false }) => {
10271
+ return /* @__PURE__ */ jsx(Droppable, { droppableId: "newColumn", children: (provided) => /* @__PURE__ */ jsx(
10272
+ Center,
10273
+ {
10274
+ ref: provided.innerRef,
10275
+ pos: "absolute",
10276
+ top: 16,
10277
+ right: 0,
10278
+ bottom: 16,
10279
+ w: active ? 140 : 0,
10280
+ sx: (theme) => ({
10281
+ boxSizing: "border-box",
10282
+ background: theme.colors.gray[0],
10283
+ transition: "width 0.4s",
10284
+ overflow: "hidden",
10285
+ "&:hover": {
10286
+ background: theme.colors.blue[0]
10287
+ }
10288
+ }),
10289
+ children: /* @__PURE__ */ jsxs(Stack, { p: "md", align: "center", children: [
10290
+ /* @__PURE__ */ jsx(Text, { size: "xs", ta: "center", children: "Drop here to add new column" }),
10291
+ /* @__PURE__ */ jsx(IconPlus, {})
10292
+ ] })
10293
+ }
10294
+ ) });
10295
+ };
10296
+ var ClickToEditOverlay = ({ onActivate, section, show = false }) => {
10297
+ if (!show)
10298
+ return null;
10299
+ return /* @__PURE__ */ jsx(
10300
+ Overlay,
10301
+ {
10302
+ className: "cms-section-overlay",
10303
+ onClick: () => onActivate(section.id),
10304
+ opacity: 0.4,
10305
+ style: { cursor: "pointer", zIndex: 3 },
10306
+ center: true,
10307
+ children: /* @__PURE__ */ jsx(Badge, { size: "xl", color: "blue", children: "Click to Edit" })
10308
+ }
10309
+ );
10310
+ };
10311
+ var GeneratorsPanel = ({ generators, show = false }) => {
10312
+ return /* @__PURE__ */ jsxs(Collapse, { in: show, p: "sm", children: [
10313
+ /* @__PURE__ */ jsx(Title, { order: 5, align: "center", children: "Generators" }),
10314
+ /* @__PURE__ */ jsx(
10315
+ SimpleGrid,
10316
+ {
10317
+ cols: generators.length > 3 ? 3 : generators.length,
10318
+ breakpoints: [
10319
+ { maxWidth: "md", cols: 3, spacing: "md" },
10320
+ { maxWidth: "sm", cols: 2, spacing: "sm" },
10321
+ { maxWidth: "xs", cols: 1, spacing: "sm" }
10322
+ ],
10323
+ children: generators
9881
10324
  }
9882
- return acc;
9883
- }, {});
9884
- setColumns(columns2);
9885
- }, [blocks]);
10325
+ )
10326
+ ] });
10327
+ };
10328
+ function SectionEditor({
10329
+ for: section,
10330
+ isDragging,
10331
+ isActive,
10332
+ onActivate,
10333
+ dragHandleProps
10334
+ }) {
10335
+ const dispatch = useAppDispatch();
10336
+ const [showGenerators, setShowGenerators] = useState(false);
10337
+ const [draggingBlock, setDraggingBlock] = useState(false);
10338
+ const [hoverBlock, setHoverBlock] = useState();
10339
+ const columnContainer = useRef(null);
10340
+ const blocks = useAppSelector((state) => state.records.entities.block);
10341
+ const blockSettings = getBlockSettings();
10342
+ const { memberImageBg, optionsMenu, hidden, columnSettings = {} } = section.settings;
10343
+ const { inputs, consumers } = useMemo(() => {
10344
+ if (hoverBlock) {
10345
+ const block = blocks[hoverBlock];
10346
+ const { inputs: inputs2, consumers: consumers2 } = block;
10347
+ return { inputs: inputs2, consumers: consumers2 };
10348
+ }
10349
+ return { inputs: [], consumers: [] };
10350
+ }, [hoverBlock]);
10351
+ const columns = Object.values(blocks || {}).filter((d) => d.section_id === section.id && d.type !== BLOCK_TYPES.GENERATOR).reduce((acc, d) => {
10352
+ if (!acc[d.blockcol]) {
10353
+ acc[d.blockcol] = { [d.blockrow]: d };
10354
+ } else {
10355
+ acc[d.blockcol][d.blockrow] = d;
10356
+ }
10357
+ return acc;
10358
+ }, {});
9886
10359
  const theme = useMantineTheme();
9887
- const smallScreen = useMediaQuery(`(max-width: ${theme.breakpoints.sm}px)`);
10360
+ const onDragStart = () => setDraggingBlock(true);
9888
10361
  const onDragEnd = (result) => {
10362
+ setDraggingBlock(false);
9889
10363
  if (!result.destination)
9890
10364
  return;
9891
10365
  const { source, destination } = result;
9892
10366
  if (source.droppableId === destination.droppableId && source.index === destination.index)
9893
10367
  return;
10368
+ const newColumn = destination.droppableId === "newColumn";
9894
10369
  const blockId = Number(result.draggableId);
9895
10370
  const sourceColumnIndex = source.droppableId;
9896
- const destinationColumnIndex = destination.droppableId;
9897
- const sourceRowIndex = blocks[blockId].blockrow;
10371
+ const destinationColumnIndex = newColumn ? findMaxOrdering(Object.keys(columns), true) : destination.droppableId;
9898
10372
  const payload = {
9899
10373
  id: blockId,
9900
10374
  blockrow: FIRST_POSITION,
@@ -9902,7 +10376,7 @@ function SectionEditor({
9902
10376
  };
9903
10377
  const changedColumn = sourceColumnIndex !== destinationColumnIndex;
9904
10378
  payload.blockcol = changedColumn ? destinationColumnIndex : sourceColumnIndex;
9905
- const rowItems = Object.values(columns[payload.blockcol]);
10379
+ const rowItems = Object.values(columns[payload.blockcol] || {});
9906
10380
  const entities = rowItems.reduce((acc, d) => ({ ...acc, [d.id]: d }), {});
9907
10381
  const entityIds = rowItems.sort((a, b) => orderSort(a, b, "blockrow")).map((d) => d.id);
9908
10382
  const descending = destination.index > source.index;
@@ -9914,42 +10388,24 @@ function SectionEditor({
9914
10388
  descending,
9915
10389
  "blockrow"
9916
10390
  );
9917
- const { [sourceRowIndex]: draggingBlock, ...sourceColumnPruned } = columns[sourceColumnIndex];
9918
- if (changedColumn) {
9919
- setColumns({
9920
- ...columns,
9921
- [sourceColumnIndex]: sourceColumnPruned,
9922
- [destinationColumnIndex]: {
9923
- ...columns[destinationColumnIndex],
9924
- [payload.blockrow]: { ...draggingBlock, blockrow: payload.blockrow }
9925
- }
9926
- });
9927
- } else {
9928
- setColumns({
9929
- ...columns,
9930
- [sourceColumnIndex]: {
9931
- ...sourceColumnPruned,
9932
- [payload.blockrow]: { ...draggingBlock, blockrow: payload.blockrow }
9933
- }
9934
- });
9935
- }
9936
10391
  dispatch(actions_exports.updateEntity("block", payload));
9937
10392
  };
10393
+ const generators = Object.values(blocks || {}).filter((d) => d.section_id === section.id && d.type == BLOCK_TYPES.GENERATOR);
10394
+ const orderedCols = Object.keys(columns).sort((a, b) => orderSort(a, b, "blockcol"));
9938
10395
  const columnsQty = Object.keys(columns).length;
9939
10396
  return /* @__PURE__ */ jsxs(
9940
- "div",
10397
+ Paper,
9941
10398
  {
9942
- id: `cms-section-${section.id}`,
10399
+ id: `section-${section.id}`,
9943
10400
  className: `cms-section${isDragging || isActive ? " active" : ""}`,
9944
- style: {
9945
- backgroundColor: site_default.section.backgroundColor,
9946
- borderRadius: site_default.section.borderRadius,
9947
- boxShadow: site_default.section.boxShadow,
9948
- margin: `${site_default.section.margin}px ${site_default.section.margin}px 0`,
9949
- overflow: "hidden",
9950
- width: `calc(100% - ${site_default.section.margin * 2}px)`,
9951
- position: "relative"
9952
- },
10401
+ bg: site_default.section.backgroundColor,
10402
+ m: `${site_default.section.margin}px ${site_default.section.margin}px 0`,
10403
+ w: `calc(100% - ${site_default.section.margin * 2}px)`,
10404
+ mih: 100,
10405
+ pos: "relative",
10406
+ shadow: site_default.section.boxShadow,
10407
+ radius: site_default.section.borderRadius,
10408
+ sx: { overflow: "hidden" },
9953
10409
  children: [
9954
10410
  /* @__PURE__ */ jsx(
9955
10411
  SectionHeader,
@@ -9958,166 +10414,134 @@ function SectionEditor({
9958
10414
  id: section.id,
9959
10415
  isDragging,
9960
10416
  hidden,
9961
- dragHandleProps
10417
+ dragHandleProps,
10418
+ generators: {
10419
+ showGenerators,
10420
+ setShowGenerators
10421
+ }
9962
10422
  }
9963
10423
  ),
9964
10424
  memberImageBg && /* @__PURE__ */ jsx(SectionBackground, {}),
10425
+ optionsMenu && /* @__PURE__ */ jsx(Flex, { justify: "flex-end", mx: 16, children: /* @__PURE__ */ jsx(Options, { sectionId: section.id }) }),
10426
+ /* @__PURE__ */ jsx(
10427
+ GeneratorsPanel,
10428
+ {
10429
+ show: showGenerators,
10430
+ generators: generators.map((item) => /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
10431
+ BlockElement_default,
10432
+ {
10433
+ id: Number(item.id),
10434
+ active: isActive,
10435
+ isInput: inputs.includes(Number(item.id)),
10436
+ isConsumer: consumers.includes(Number(item.id)),
10437
+ setHoverBlock
10438
+ }
10439
+ ) }, `block-${item.id}`))
10440
+ }
10441
+ ),
9965
10442
  /* @__PURE__ */ jsxs(
9966
- "div",
10443
+ ColumnsWrapper,
9967
10444
  {
9968
- className: "cms-section-content",
9969
- style: {
9970
- alignItems: "stretch",
9971
- display: "flex",
9972
- flexDirection: smallScreen ? "column" : "row",
9973
- padding: "32px 32px 32px 32px",
9974
- position: "relative",
9975
- zIndex: 0
10445
+ ref: columnContainer,
10446
+ containerProps: {
10447
+ mih: !isActive || !columnsQty ? 120 : "none",
10448
+ p: "md"
9976
10449
  },
9977
10450
  children: [
9978
- optionsMenu && /* @__PURE__ */ jsx("div", { style: {
9979
- position: "absolute",
9980
- right: 10,
9981
- top: 10,
9982
- zIndex: 100
9983
- }, children: /* @__PURE__ */ jsx(Options, { sectionId: section.id }) }),
9984
- /* @__PURE__ */ jsx(DragDropContext, { onDragEnd, children: Object.keys(columns).sort((a, b) => orderSort(a, b, "blockcol")).map((columnIndex) => {
9985
- const column = columns[columnIndex];
9986
- const staticWidths = Object.values(column).map(({ id }) => parseFloat(blocks[id]?.settings?.width)).filter((d) => !Number.isNaN(d));
9987
- return /* @__PURE__ */ jsx(
9988
- "div",
9989
- {
9990
- className: "cms-section-column",
9991
- style: {
9992
- flex: "1 1 100%",
9993
- maxWidth: staticWidths.length ? Math.max(...staticWidths) : `${100 / columnsQty}%`,
9994
- padding: site_default.column.padding
9995
- },
9996
- children: /* @__PURE__ */ jsx(Droppable, { droppableId: columnIndex, children: (provided, snapshot) => /* @__PURE__ */ jsxs(
9997
- "div",
9998
- {
9999
- ...provided.droppableProps,
10000
- ref: provided.innerRef,
10001
- style: {
10002
- alignContent: "flex-start",
10003
- background: snapshot.isDraggingOver ? theme.colors[theme.primaryColor][0] : "inherit",
10004
- display: "flex",
10005
- flexDirection: Object.values(column).find(
10006
- (item) => blocks[item.id]?.settings?.display === "inline"
10007
- ) ? "row" : "column",
10008
- flexWrap: Object.values(column).find(
10009
- (item) => blocks[item.id]?.settings?.display === "inline"
10010
- ) ? "wrap" : "nowrap",
10011
- height: "100%",
10012
- maxWidth: "100%"
10451
+ /* @__PURE__ */ jsxs(DragDropContext, { onDragEnd, onDragStart, children: [
10452
+ orderedCols.map((columnIndex) => {
10453
+ const orderedBlocks = Object.values(columns[columnIndex]).sort((a, b) => orderSort(a, b, "blockrow"));
10454
+ return /* @__PURE__ */ jsx(Droppable, { droppableId: columnIndex, children: (provided, snapshot) => /* @__PURE__ */ jsxs(
10455
+ SectionColumn,
10456
+ {
10457
+ column: columns[columnIndex],
10458
+ columnSettings: columnSettings[columnIndex],
10459
+ ref: provided.innerRef,
10460
+ sx: {
10461
+ // extra styles for columns on editor
10462
+ flexBasis: `${100 / columnsQty}%`,
10463
+ background: snapshot.isDraggingOver ? theme.colors[theme.primaryColor][0] : "inherit",
10464
+ border: "1px solid transparent",
10465
+ "& .bespoke-resize-col": {
10466
+ visibility: "hidden"
10013
10467
  },
10014
- children: [
10015
- Object.values(column).sort((a, b) => orderSort(a, b, "blockrow")).map((item, rowIndex) => {
10016
- if (!blocks[item.id])
10017
- return null;
10018
- const { settings, type } = blocks[item.id];
10019
- return /* @__PURE__ */ jsx(
10020
- Draggable,
10021
- {
10022
- draggableId: String(item.id),
10023
- index: rowIndex,
10024
- children: (provided2, snapshot2) => /* @__PURE__ */ jsx(
10025
- "div",
10026
- {
10027
- ref: provided2.innerRef,
10028
- ...provided2.draggableProps,
10029
- ...provided2.dragHandleProps,
10030
- style: {
10031
- ...provided2.draggableProps.style,
10032
- alignSelf: type === "visualization" ? "stretch" : "flex-start",
10468
+ "&:hover .bespoke-resize-col": {
10469
+ visibility: "visible"
10470
+ },
10471
+ "&:hover": {
10472
+ border: `1px solid ${theme.colors.teal[1]}`
10473
+ }
10474
+ },
10475
+ ...provided.droppableProps,
10476
+ children: [
10477
+ /* @__PURE__ */ jsx(
10478
+ ResizeColumnInput,
10479
+ {
10480
+ sectionId: section.id,
10481
+ columnIndex
10482
+ }
10483
+ ),
10484
+ orderedBlocks.map((item, rowIndex) => {
10485
+ if (!blocks[item.id])
10486
+ return null;
10487
+ const { settings, type } = blocks[item.id];
10488
+ const blockWidth = settings.width && !settings.width.stretch && settings.width.unit ? formatters[settings.width.unit](settings.width.value) : settings.display === "inline" ? "auto" : "100%";
10489
+ const blockStyles = {
10490
+ alignSelf: type === "visualization" ? "stretch" : "flex-start",
10491
+ flexGrow: 0,
10492
+ margin: "0",
10493
+ textAlign: settings.align || blockSettings.align.defaultValue,
10494
+ width: blockWidth,
10495
+ minWidth: 120
10496
+ };
10497
+ return /* @__PURE__ */ jsx(
10498
+ Draggable,
10499
+ {
10500
+ draggableId: String(item.id),
10501
+ index: rowIndex,
10502
+ children: (provided2, snapshot2) => /* @__PURE__ */ jsx(
10503
+ Box,
10504
+ {
10505
+ ref: provided2.innerRef,
10506
+ ...provided2.draggableProps,
10507
+ ...provided2.dragHandleProps,
10508
+ sx: [
10509
+ blockStyles,
10510
+ {
10033
10511
  boxShadow: snapshot2.isDragging ? theme.shadows.lg : "none",
10034
- flex: type === "visualization" ? smallScreen ? "1 1 300px" : "1 1 100%" : settings.display === "inline" ? "1 1 auto" : "0 0 auto",
10035
- margin: "0",
10036
- textAlign: settings.align || blockSettings.align.defaultValue,
10037
- width: settings.width && settings.width !== "stretch" ? parseFloat(settings.width) : settings.display === "inline" ? "auto" : "100%"
10512
+ ...provided2.draggableProps.style
10513
+ }
10514
+ ],
10515
+ children: /* @__PURE__ */ jsx(
10516
+ BlockElement_default,
10517
+ {
10518
+ id: Number(item.id),
10519
+ active: isActive,
10520
+ isInput: inputs.includes(Number(item.id)),
10521
+ isConsumer: consumers.includes(Number(item.id)),
10522
+ setHoverBlock
10038
10523
  },
10039
- children: /* @__PURE__ */ jsx(
10040
- BlockElement_default,
10041
- {
10042
- id: Number(item.id),
10043
- active: isActive,
10044
- isInput: inputs.includes(Number(item.id)),
10045
- isConsumer: consumers.includes(Number(item.id)),
10046
- sectionState: {
10047
- state: sectionState,
10048
- set: setSectionState2
10049
- },
10050
- setHoverBlock
10051
- },
10052
- `block-${item.id}`
10053
- )
10054
- }
10055
- )
10056
- },
10057
- item.id
10058
- );
10059
- }),
10060
- isActive && /* @__PURE__ */ jsx(
10061
- EntityCreateButton,
10062
- {
10063
- fields: [{
10064
- type: "select",
10065
- name: "type",
10066
- label: "Block Type",
10067
- options: blockTypes.map((d) => ({ label: d, value: d }))
10068
- }],
10069
- onSubmit: (value) => addBlock(value.type, columnIndex),
10070
- target: /* @__PURE__ */ jsx(ActionIcon, { size: "md", radius: "lg", children: /* @__PURE__ */ jsx(IconCirclePlus, { size: 20 }) })
10071
- }
10072
- ),
10073
- provided.placeholder
10074
- ]
10075
- }
10076
- ) }, columnIndex)
10077
- },
10078
- columnIndex
10079
- );
10080
- }) }),
10081
- isActive && /* @__PURE__ */ jsx(
10082
- EntityCreateButton,
10083
- {
10084
- fields: [{
10085
- type: "select",
10086
- name: "type",
10087
- label: "Block Type",
10088
- options: blockTypes.map((d) => ({ label: d, value: d }))
10089
- }],
10090
- onSubmit: (value) => addBlock(value.type),
10091
- target: /* @__PURE__ */ jsx(ActionIcon, { size: "md", radius: "lg", children: /* @__PURE__ */ jsx(IconCirclePlus, { size: 20 }) })
10092
- }
10093
- ),
10094
- !isActive && /* @__PURE__ */ jsx(
10095
- Center,
10096
- {
10097
- className: "cms-section-click-to-edit",
10098
- style: {
10099
- bottom: "0",
10100
- position: "absolute",
10101
- width: "100%",
10102
- left: "0",
10103
- top: "0"
10104
- },
10105
- children: /* @__PURE__ */ jsx(Badge, { size: "xl", variant: "outline", color: "gray", children: "Click to Edit" })
10106
- }
10107
- ),
10108
- !isActive && /* @__PURE__ */ jsx(
10109
- Overlay,
10110
- {
10111
- className: "cms-section-overlay",
10112
- onClick: () => onActivate(section.id),
10113
- color: theme.black,
10114
- opacity: 0.5,
10115
- style: { cursor: "pointer" }
10116
- }
10117
- )
10524
+ `block-${item.id}`
10525
+ )
10526
+ }
10527
+ )
10528
+ },
10529
+ item.id
10530
+ );
10531
+ }),
10532
+ isActive && /* @__PURE__ */ jsx(CreateBlockButton, { section, columnIndex, columns }),
10533
+ provided.placeholder
10534
+ ]
10535
+ }
10536
+ ) }, columnIndex);
10537
+ }),
10538
+ /* @__PURE__ */ jsx(CreateColumnArea, { active: draggingBlock && isActive })
10539
+ ] }),
10540
+ /* @__PURE__ */ jsx(FirstBlockButton, { columns, section, show: isActive && !columnsQty })
10118
10541
  ]
10119
10542
  }
10120
- )
10543
+ ),
10544
+ /* @__PURE__ */ jsx(ClickToEditOverlay, { onActivate, section, show: !isActive })
10121
10545
  ]
10122
10546
  }
10123
10547
  );
@@ -10415,9 +10839,9 @@ function FormatterForm({ formatterId, onEditEnd }) {
10415
10839
  useEffect(() => {
10416
10840
  if (!ref.isLoading && !formattersList.isLoading) {
10417
10841
  const formatterItem = !ref.isSuccess ? void 0 : ref.data;
10418
- const formatters = !formattersList.isSuccess ? [] : formattersList.data;
10842
+ const formatters2 = !formattersList.isSuccess ? [] : formattersList.data;
10419
10843
  if (formatterItem) {
10420
- const formatterNamesList = formatters.filter((f) => f.id !== formatterItem.id).map((f) => f.name);
10844
+ const formatterNamesList = formatters2.filter((f) => f.id !== formatterItem.id).map((f) => f.name);
10421
10845
  setFormatterNames(formatterNamesList);
10422
10846
  }
10423
10847
  onTest();
@@ -10620,10 +11044,10 @@ function FormattersTable({ filters, onClickEdit }) {
10620
11044
  const [sortStatus, setSortStatus] = useState();
10621
11045
  const [records, setRecords] = useState([]);
10622
11046
  const formattersList = useFormatterList();
10623
- const formatters = !formattersList.isSuccess ? [] : formattersList.data;
11047
+ const formatters2 = !formattersList.isSuccess ? [] : formattersList.data;
10624
11048
  const formatterFunctions = useFormatterFunctionsForLocale();
10625
11049
  const formattersUsageCount = useFormatterUsageCountList();
10626
- const formattersFull = useMemo(() => formatters.map((f) => {
11050
+ const formattersFull = useMemo(() => formatters2.map((f) => {
10627
11051
  const usageCount = formattersUsageCount[f.name] ? formattersUsageCount[f.name] : 0;
10628
11052
  let result = "";
10629
11053
  try {
@@ -10639,7 +11063,7 @@ function FormattersTable({ filters, onClickEdit }) {
10639
11063
  result,
10640
11064
  usageCount
10641
11065
  };
10642
- }), [formatters]);
11066
+ }), [formatters2]);
10643
11067
  const doSearch = () => {
10644
11068
  let filteredResults = formattersFull.filter(
10645
11069
  (formatter) => {
@@ -12480,6 +12904,9 @@ function UsersEditor() {
12480
12904
  editingId && /* @__PURE__ */ jsx(UserForm, { userId: editingId, onEditEnd: onEditClose, roles })
12481
12905
  ] });
12482
12906
  }
12907
+
12908
+ // views/BespokeManager.tsx
12909
+ init_ErrorBoundary();
12483
12910
  init_envvars();
12484
12911
  function BespokeManager(options) {
12485
12912
  const {
@@ -12488,7 +12915,7 @@ function BespokeManager(options) {
12488
12915
  locale = localeDefault4,
12489
12916
  profilePrefix = "/profilePathManager"
12490
12917
  } = options;
12491
- const notifications3 = {
12918
+ const notifications4 = {
12492
12919
  position: "bottom-center",
12493
12920
  ...options.notifications
12494
12921
  };
@@ -12501,8 +12928,8 @@ function BespokeManager(options) {
12501
12928
  return /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment, profilePrefix, children: [
12502
12929
  /* @__PURE__ */ jsx(Head, { children: /* @__PURE__ */ jsx("title", { children: title }) }),
12503
12930
  /* @__PURE__ */ jsxs(MantineProvider, { inherit: false, children: [
12504
- /* @__PURE__ */ jsx(Notifications, { ...notifications3 }),
12505
- /* @__PURE__ */ jsx(DialogProvider, { children: /* @__PURE__ */ jsx(BespokeManagerShell, { locale }) })
12931
+ /* @__PURE__ */ jsx(Notifications, { ...notifications4 }),
12932
+ /* @__PURE__ */ jsx(DialogProvider, { children: /* @__PURE__ */ jsx(ErrorBoundary, { fallback: /* @__PURE__ */ jsx("p", { children: "Client side error in Bespoke. Check the console for details." }), children: /* @__PURE__ */ jsx(BespokeManagerShell, { locale }) }) })
12506
12933
  ] })
12507
12934
  ] });
12508
12935
  }