@datawheel/bespoke 0.1.25 → 0.1.27

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.
Files changed (3) hide show
  1. package/dist/index.js +603 -137
  2. package/dist/server.js +112 -48
  3. package/package.json +3 -1
package/dist/index.js CHANGED
@@ -16,14 +16,14 @@ 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, Title, Select, SegmentedControl, MultiSelect, Box, List, Menu, Anchor, MantineProvider, Divider, Burger, Navbar, ScrollArea, Avatar, AppShell, UnstyledButton, ThemeIcon, LoadingOverlay, Skeleton, Container, TextInput, Loader, Alert, Autocomplete, Card, Space, Code, Textarea, rem, Overlay, Grid, Input, Popover, Checkbox, Radio, Switch, Drawer, Tabs, Header, px, SimpleGrid, Image, Paper, FileInput, Accordion, HoverCard, CopyButton, NumberInput, Col } from '@mantine/core';
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';
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, IconAlignLeft, IconAlignCenter, IconAlignRight, IconBoxMargin, IconTable, IconMathFunction, IconUsers, IconLogout, IconSearch, IconTrash, IconUserCircle, IconEdit, IconDatabase, IconServer, IconPencil, IconAlertCircle, IconCircleCheck, IconPlayerPlay, IconAlarmFilled, IconBox, IconLink, IconCirclePlus, IconCircleX, IconFlag, IconFileAnalytics, IconPlus, IconCamera, IconShare, IconCircleDashed, IconListSearch, IconExternalLink, IconSettings, IconFileOff, IconFilesOff, IconMenu, IconRefresh, IconPolaroid, IconCircleMinus, IconEyeOff, 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 { useDisclosure, useDebouncedValue, useSetState, useMediaQuery, useHotkeys, useFullscreen, getHotkeyHandler } from '@mantine/hooks';
25
- import Link from 'next/link';
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';
26
25
  import dynamic from 'next/dynamic';
26
+ import Link from 'next/link';
27
27
  import parse2, { Element, domToReact, Text as Text$1 } from 'html-react-parser';
28
28
  import { UserProvider, withPageAuthRequired, useUser } from '@auth0/nextjs-auth0/client';
29
29
  import { Prism } from '@mantine/prism';
@@ -37,6 +37,8 @@ import slugifyFn from 'slugify';
37
37
  import { FacebookShareButton, FacebookIcon, TwitterShareButton, TwitterIcon, TelegramShareButton, TelegramIcon, WhatsappShareButton, WhatsappIcon, LinkedinShareButton, LinkedinIcon, RedditShareButton, RedditIcon, EmailShareButton, EmailIcon } from 'react-share';
38
38
  import Head from 'next/head';
39
39
  import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd';
40
+ import * as d3 from 'd3';
41
+ import * as d3Dag from 'd3-dag';
40
42
  import Editor, { useMonaco } from '@monaco-editor/react';
41
43
  import { format } from 'pretty-format';
42
44
  import { Editor as Editor$1 } from '@tinymce/tinymce-react';
@@ -194,7 +196,6 @@ var init_http = __esm({
194
196
  init_imageSearch();
195
197
  init_lib();
196
198
  transformDeletePayload = (id) => {
197
- console.log("transformDeletePayload", id);
198
199
  return { id };
199
200
  };
200
201
  transformReadMembers = (params) => {
@@ -274,7 +275,7 @@ var init_block = __esm({
274
275
  });
275
276
 
276
277
  // types/cms.ts
277
- var ENTITY_TYPES, ENTITY_PRETTY_NAMES, REPORT_TYPES, SELECTOR_TYPES, REPORT_FIELDS, ALLOWED, ACCESS, BLOCK_CONTENT_TYPES, BLOCK_LOGIC_TYPES, BLOCK_LOGIC_LOCALE, BLOCK_TYPES, BLOCK_FIELDS, BLOCK_MAP, BLOCK_SETTINGS, FORMATTER_TYPES, FORMATTER_TYPES_NAMES, FORMATTER_INPUT_TYPES, FORMATTER_INPUT_TYPES_NAMES;
278
+ var ENTITY_TYPES, ENTITY_PRETTY_NAMES, REPORT_TYPES, SELECTOR_TYPES, SELECTOR_COMPONENTS, REPORT_FIELDS, ALLOWED, ACCESS, BLOCK_CONTENT_TYPES, BLOCK_LOGIC_TYPES, BLOCK_LOGIC_LOCALE, BLOCK_TYPES, BLOCK_FIELDS, BLOCK_MAP, BLOCK_SETTINGS, FORMATTER_TYPES, FORMATTER_TYPES_NAMES, FORMATTER_INPUT_TYPES, FORMATTER_INPUT_TYPES_NAMES;
278
279
  var init_cms = __esm({
279
280
  "types/cms.ts"() {
280
281
  init_esm_shims();
@@ -314,6 +315,10 @@ var init_cms = __esm({
314
315
  SINGLE: "single",
315
316
  MULTI: "multi"
316
317
  };
318
+ SELECTOR_COMPONENTS = {
319
+ SEGMENTED_CONTROL: "segmented control",
320
+ SELECTOR: "selector"
321
+ };
317
322
  REPORT_FIELDS = {
318
323
  TITLE: "title",
319
324
  SUBTITLE: "subtitle",
@@ -882,6 +887,7 @@ var init_runSelector = __esm({
882
887
  const evalResult = mortarEval_default("variables", variables, transpiledLogic, formatterFunctions, void 0, blockContext);
883
888
  const { vars, log, error } = evalResult;
884
889
  const type = vars.type || SELECTOR_TYPES.SINGLE;
890
+ const component = vars.component || "Selector";
885
891
  const name = vars.name || "Unlabeled Selector";
886
892
  const options = scaffoldDynamic_default(vars.options || []);
887
893
  const maybeFixForMulti2 = (defaultValue2) => type === SELECTOR_TYPES.MULTI && !Array.isArray(defaultValue2) ? [defaultValue2] : defaultValue2;
@@ -900,7 +906,8 @@ var init_runSelector = __esm({
900
906
  name,
901
907
  type,
902
908
  options,
903
- defaultValue
909
+ defaultValue,
910
+ component
904
911
  };
905
912
  return { config, log, error };
906
913
  };
@@ -1078,6 +1085,7 @@ async function apiFetch(url, settings, readMemberFn, locale = "en") {
1078
1085
  }
1079
1086
  async function runSingleBlock(block, formatterFunctions, blockContext, readMemberFn) {
1080
1087
  const { locale, variables, query } = parseBlockContext(blockContext);
1088
+ const allowed = isBlockAllowed(block, blockContext, variables, formatterFunctions);
1081
1089
  let resp = null;
1082
1090
  const unswappedAPI = block.contentByLocale?.logic?.content?.api;
1083
1091
  let apiResponse;
@@ -1115,7 +1123,8 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
1115
1123
  duration: null,
1116
1124
  resp: null,
1117
1125
  log: log2,
1118
- error: error2
1126
+ error: error2,
1127
+ allowed
1119
1128
  }
1120
1129
  };
1121
1130
  }
@@ -1129,7 +1138,8 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
1129
1138
  duration: null,
1130
1139
  resp: null,
1131
1140
  log: [],
1132
- error: null
1141
+ error: null,
1142
+ allowed
1133
1143
  }
1134
1144
  };
1135
1145
  }
@@ -1146,7 +1156,8 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
1146
1156
  log,
1147
1157
  duration,
1148
1158
  resp,
1149
- api
1159
+ api,
1160
+ allowed
1150
1161
  }
1151
1162
  };
1152
1163
  }
@@ -1159,11 +1170,12 @@ async function runSingleBlock(block, formatterFunctions, blockContext, readMembe
1159
1170
  error,
1160
1171
  duration,
1161
1172
  resp,
1162
- api
1173
+ api,
1174
+ allowed
1163
1175
  }
1164
1176
  };
1165
1177
  }
1166
- var verbose2, ORIGIN, swapAPI, urlProxy, getDependencies, runConsumersV2, getDurationColor, getSizeColor;
1178
+ var verbose2, ORIGIN, swapAPI, urlProxy, getDependencies, isBlockAllowed, runConsumersV2, getDurationColor, getSizeColor;
1167
1179
  var init_runConsumers = __esm({
1168
1180
  "libs/blocks/runConsumers.ts"() {
1169
1181
  init_esm_shims();
@@ -1195,27 +1207,51 @@ var init_runConsumers = __esm({
1195
1207
  return url;
1196
1208
  };
1197
1209
  ({ urlProxy } = apiFactory("/api/cms"));
1198
- getDependencies = (bid, blocks, acc = [], crawlUp = true, crawlDown = true) => {
1210
+ getDependencies = (bid, blocks, acc = [], crawlUp = true, crawlDown = true, withinSection = true, visited = []) => {
1211
+ if (visited.includes(bid))
1212
+ return [];
1213
+ visited.push(bid);
1199
1214
  const rootBlock = blocks[bid];
1200
1215
  if (rootBlock.inputs.length && crawlUp) {
1201
1216
  rootBlock.inputs.forEach((iid) => {
1202
1217
  const rel = `${iid}-${bid}`;
1203
1218
  if (!acc.includes(rel))
1204
1219
  acc.push(rel);
1205
- rootBlock.inputs.forEach((iid2) => getDependencies(iid2, blocks, acc, crawlUp, false));
1220
+ rootBlock.inputs.forEach((iid2) => getDependencies(iid2, blocks, acc, crawlUp, false, withinSection, visited));
1206
1221
  });
1207
1222
  }
1208
1223
  if (rootBlock.consumers.length && crawlDown) {
1209
1224
  rootBlock.consumers.forEach((cid) => {
1210
1225
  const rel = `${bid}-${cid}`;
1211
- if (!acc.includes(rel) && blocks[cid].section_id === blocks[bid].section_id)
1226
+ if (!acc.includes(rel) && (blocks[cid].section_id === blocks[bid].section_id || !withinSection))
1212
1227
  acc.push(rel);
1213
- rootBlock.consumers.filter((cid2) => blocks[cid2].section_id === blocks[bid].section_id).forEach((cid2) => getDependencies(cid2, blocks, acc, crawlUp, crawlDown));
1228
+ rootBlock.consumers.filter((cid2) => blocks[cid2].section_id === blocks[bid].section_id || !withinSection).forEach((cid2) => getDependencies(cid2, blocks, acc, crawlUp, crawlDown, withinSection, visited));
1214
1229
  });
1215
1230
  }
1216
1231
  return acc;
1217
1232
  };
1218
- runConsumersV2 = async (blocks, sections, bid, formatterFunctions, blockContext, initialVariables = {}, readMemberFn) => {
1233
+ isBlockAllowed = (block, blockContext, variables, formatterFunctions) => {
1234
+ let allowed = true;
1235
+ if (block && "allowed" in block.settings && block.settings.allowed !== "always") {
1236
+ if (block.settings.allowed === "never") {
1237
+ allowed = false;
1238
+ } else {
1239
+ const parsedBlockContext = parseBlockContext(blockContext);
1240
+ const { vars, error, output } = mortarEval_default(
1241
+ "variables",
1242
+ variables,
1243
+ block.settings.allowedLogic || "return false;",
1244
+ formatterFunctions,
1245
+ void 0,
1246
+ parsedBlockContext
1247
+ );
1248
+ if (!error)
1249
+ allowed = Boolean(output);
1250
+ }
1251
+ }
1252
+ return allowed;
1253
+ };
1254
+ runConsumersV2 = async (blocks, sections, bid, formatterFunctions, blockContext, initialVariables = {}, readMemberFn, mode = "section") => {
1219
1255
  if (!bid && !sections)
1220
1256
  return { variables: { ...initialVariables } };
1221
1257
  const variablesById = { ...initialVariables };
@@ -1223,11 +1259,15 @@ var init_runConsumers = __esm({
1223
1259
  const parsedBlockContext = parseBlockContext(blockContext);
1224
1260
  const attributes = parsedBlockContext.variables;
1225
1261
  const rootBlocks = bid ? { [bid]: blocks[bid] } : sections.reduce((rootBlocks2, { id }) => ({ ...rootBlocks2, ...getRootBlocksForSection_default(id, blocks) }), {});
1262
+ const withinSection = mode === "section";
1226
1263
  const blockDeps = Object.keys(rootBlocks).reduce((deps, id) => {
1227
- const dependencies = getDependencies(Number(id), blocks, [], !bid).map((rel) => rel.split("-"));
1264
+ const dependencies = getDependencies(Number(id), blocks, [], !bid, true, withinSection).map((rel) => rel.split("-"));
1228
1265
  return [...deps, ...dependencies];
1229
1266
  }, []);
1230
- const orderedDAG = toposort(blockDeps);
1267
+ const orderedDAG = Object.keys(rootBlocks).reduce(
1268
+ (orderedDAG2, bid2) => orderedDAG2.includes(bid2) ? [...orderedDAG2] : [bid2, ...orderedDAG2],
1269
+ toposort(blockDeps)
1270
+ );
1231
1271
  async function runTasksInParallel(executionOrder, blocks2) {
1232
1272
  const runningBlocks = /* @__PURE__ */ new Map();
1233
1273
  for (const bid2 of executionOrder) {
@@ -2398,15 +2438,16 @@ var init_actions = __esm({
2398
2438
  }
2399
2439
  });
2400
2440
  function ResourceProvider(props) {
2401
- const { pathSegment } = props;
2441
+ const { pathSegment, profilePrefix } = props;
2402
2442
  const formatters = useFormatterList();
2403
2443
  const value = useMemo(() => ({
2444
+ profilePrefix,
2404
2445
  pathSegment,
2405
2446
  formatterFunctions: locales3.reduce((acc, locale) => ({
2406
2447
  ...acc,
2407
2448
  [locale]: formatters.data ? funcifyFormattersByLocale(formatters.data, locale) : {}
2408
2449
  }), {})
2409
- }), [formatters, pathSegment]);
2450
+ }), [formatters, pathSegment, profilePrefix]);
2410
2451
  return /* @__PURE__ */ jsx(ResourceContext.Provider, { value, children: props.children });
2411
2452
  }
2412
2453
  function useBespoke() {
@@ -2426,7 +2467,8 @@ var init_ResourceProvider = __esm({
2426
2467
  ({ locales: locales3 } = getLocales_default());
2427
2468
  initialContext = {
2428
2469
  pathSegment: "path",
2429
- formatterFunctions: locales3.reduce((acc, d) => ({ ...acc, [d]: {} }), {})
2470
+ formatterFunctions: locales3.reduce((acc, d) => ({ ...acc, [d]: {} }), {}),
2471
+ profilePrefix: "path"
2430
2472
  };
2431
2473
  ResourceContext = createContext(initialContext);
2432
2474
  }
@@ -2514,7 +2556,7 @@ function processResult(data, req) {
2514
2556
  }
2515
2557
  return { ...result, data };
2516
2558
  }
2517
- var localeDefault5, useAppDispatch, useAppSelector, useReportList, useVariantList, useSectionList, useFormatterList, useReportRef, useSectionRef, useBlockRef, useDimensionRef, useVariantRef, useFormatterRef, useInputVariablesFlat, useInputVariablesHash, useBlockStatus, useFormatterFunctionsForLocale, useBlockContext, getFormatterUsageCount, useFormatterUsageCount, useFormatterUsageCountList;
2559
+ var localeDefault5, useAppDispatch, useAppSelector, useReportList, useVariantList, useSectionList, useBlockList, useFormatterList, useReportRef, useSectionRef, useBlockRef, useDimensionRef, useVariantRef, useFormatterRef, useInputVariablesFlat, useInputVariablesHash, useBlockStatus, useFormatterFunctionsForLocale, useProfilePrefix, useBlockContext, getFormatterUsageCount, useFormatterUsageCount, useFormatterUsageCountList;
2518
2560
  var init_hooks = __esm({
2519
2561
  "store/hooks.ts"() {
2520
2562
  init_esm_shims();
@@ -2529,6 +2571,7 @@ var init_hooks = __esm({
2529
2571
  useReportList = entityListHookFactory("report");
2530
2572
  useVariantList = entityListHookFactory("variant");
2531
2573
  useSectionList = entityListHookFactory("section");
2574
+ useBlockList = entityListHookFactory("block");
2532
2575
  useFormatterList = entityListHookFactory("formatter");
2533
2576
  useReportRef = entityRefHookFactory("report");
2534
2577
  useSectionRef = entityRefHookFactory("section");
@@ -2570,6 +2613,10 @@ var init_hooks = __esm({
2570
2613
  const resource = useContext(ResourceContext);
2571
2614
  return resource.formatterFunctions[locale];
2572
2615
  };
2616
+ useProfilePrefix = () => {
2617
+ const resource = useContext(ResourceContext);
2618
+ return resource.profilePrefix;
2619
+ };
2573
2620
  useBlockContext = (id = void 0, locale = void 0) => {
2574
2621
  useAppSelector((state2) => state2);
2575
2622
  const localeDefault9 = useAppSelector((state2) => state2.status.localeDefault);
@@ -2623,6 +2670,7 @@ var init_store = __esm({
2623
2670
  return getDefaultMiddleware({
2624
2671
  thunk: {
2625
2672
  extraArgument: apiFactory("/api/cms/")
2673
+ // serializableCheck: false,
2626
2674
  }
2627
2675
  });
2628
2676
  }
@@ -2630,7 +2678,7 @@ var init_store = __esm({
2630
2678
  storeWrapper = createWrapper(storeFactory);
2631
2679
  }
2632
2680
  });
2633
- function withFetcher(Component, useRef6) {
2681
+ function withFetcher(Component, useRef7) {
2634
2682
  const ComponentWithFetcher = (props) => {
2635
2683
  const {
2636
2684
  id,
@@ -2638,7 +2686,7 @@ function withFetcher(Component, useRef6) {
2638
2686
  skelWidth,
2639
2687
  ...otherProps
2640
2688
  } = props;
2641
- const ref = useRef6(id);
2689
+ const ref = useRef7(id);
2642
2690
  if (ref.isUninitialized || ref.isFetching) {
2643
2691
  return /* @__PURE__ */ jsx(Skeleton, { width: skelWidth, height: skelHeight });
2644
2692
  }
@@ -3282,8 +3330,13 @@ init_esm_shims();
3282
3330
 
3283
3331
  // frontend/components/explore/ExploreTile.tsx
3284
3332
  init_esm_shims();
3285
- function ExploreTile({ profile, profilePrefix }) {
3286
- const url = `${profilePrefix}${profile.path}`;
3333
+ init_store2();
3334
+ function ExploreTile({ profile, profilePrefix, onSelect }) {
3335
+ const currentLocale = useAppSelector((state) => state.status.currentLocale);
3336
+ const localeDefault9 = useAppSelector((state) => state.status.localeDefault);
3337
+ const localePrefix = currentLocale === localeDefault9 ? "" : `/${currentLocale}`;
3338
+ const url = `${localePrefix}${profilePrefix}${profile.path}`;
3339
+ const router = useRouter();
3287
3340
  const images = profile.members.map((m) => /* @__PURE__ */ jsx(
3288
3341
  Image,
3289
3342
  {
@@ -3298,21 +3351,37 @@ function ExploreTile({ profile, profilePrefix }) {
3298
3351
  /* @__PURE__ */ jsx(Text, { weight: 500, children: m.name }),
3299
3352
  /* @__PURE__ */ jsx(Badge, { color: "green", variant: "light", children: m.metadata.variant.name })
3300
3353
  ] }, m.id));
3354
+ const onItemSubmit = (innerUrl) => {
3355
+ router.push(`${innerUrl}`);
3356
+ if (onSelect)
3357
+ onSelect();
3358
+ };
3301
3359
  return /* @__PURE__ */ jsx(Grid.Col, { xs: 12, sm: 6, md: 4, lg: 4, xl: 3, children: /* @__PURE__ */ jsxs(Card, { shadow: "sm", p: "lg", radius: "md", withBorder: true, children: [
3302
3360
  /* @__PURE__ */ jsx(Card.Section, { children: /* @__PURE__ */ jsx(Group, { grow: true, spacing: 0, children: images }) }),
3303
3361
  /* @__PURE__ */ jsx(Group, { position: "apart", mt: "md", mb: "xs", children: names }),
3304
- /* @__PURE__ */ jsx(Link, { href: url, passHref: true, prefetch: false, children: /* @__PURE__ */ jsx(Button, { variant: "light", color: "blue", fullWidth: true, mt: "md", radius: "md", children: `See ${profile.report.name} Report` }) })
3362
+ /* @__PURE__ */ jsx(
3363
+ "a",
3364
+ {
3365
+ href: url,
3366
+ onClick: (evt) => {
3367
+ evt.preventDefault();
3368
+ onItemSubmit(url);
3369
+ },
3370
+ children: /* @__PURE__ */ jsx(Button, { variant: "light", color: "blue", fullWidth: true, mt: "md", radius: "md", children: `See ${profile.report.name} Report` })
3371
+ }
3372
+ )
3305
3373
  ] }) }, profile.id);
3306
3374
  }
3307
3375
  var ExploreTile_default = ExploreTile;
3308
- function ExploreResults({ results = [], profilePrefix }) {
3376
+ function ExploreResults({ results = [], profilePrefix, onSelect = () => {
3377
+ } }) {
3309
3378
  const [scrollSize, setScrollSize] = useState(500);
3310
3379
  useEffect(() => {
3311
3380
  const { innerHeight } = window;
3312
3381
  setScrollSize(innerHeight - 200);
3313
3382
  }, []);
3314
3383
  return /* @__PURE__ */ jsx(ScrollArea, { offsetScrollbars: true, type: "always", style: { height: scrollSize }, children: /* @__PURE__ */ jsx(Grid, { align: "stretch", children: results.map(
3315
- (item) => /* @__PURE__ */ jsx(ExploreTile_default, { profile: item, profilePrefix }, item.id)
3384
+ (item) => /* @__PURE__ */ jsx(ExploreTile_default, { profile: item, profilePrefix, onSelect }, item.id)
3316
3385
  ) }) });
3317
3386
  }
3318
3387
  var ExploreResults_default = ExploreResults;
@@ -3323,10 +3392,12 @@ function BespokeExplore({
3323
3392
  locale,
3324
3393
  profilePrefix,
3325
3394
  initialReportId,
3326
- initialVariantId
3395
+ initialVariantId,
3396
+ onSelect
3327
3397
  }) {
3328
3398
  const dispatch = useAppDispatch();
3329
3399
  const defaultFilters = {
3400
+ // initial reportIds should go here to avoid multiple unnecesary requests
3330
3401
  profile: void 0,
3331
3402
  variant: void 0
3332
3403
  };
@@ -3345,6 +3416,7 @@ function BespokeExplore({
3345
3416
  });
3346
3417
  }, []);
3347
3418
  useEffect(() => {
3419
+ let cancelled = false;
3348
3420
  if (metadata) {
3349
3421
  setLoading(true);
3350
3422
  const filterProfile = filters.profile && !Number.isNaN(filters.profile) ? filters.profile : [];
@@ -3363,7 +3435,7 @@ function BespokeExplore({
3363
3435
  all: false
3364
3436
  };
3365
3437
  dispatch(actions_exports.reportSearch(params)).then((resp) => {
3366
- if (resp && resp.results) {
3438
+ if (resp && resp.results && !cancelled) {
3367
3439
  setResults(resp.results);
3368
3440
  }
3369
3441
  setLoading(false);
@@ -3373,6 +3445,9 @@ function BespokeExplore({
3373
3445
  setLoading(false);
3374
3446
  });
3375
3447
  }
3448
+ return () => {
3449
+ cancelled = false;
3450
+ };
3376
3451
  }, [debouncedQuery, filters, metadata]);
3377
3452
  const onFilterChange = (newFilters) => {
3378
3453
  setFilters(newFilters);
@@ -3415,7 +3490,7 @@ function BespokeExplore({
3415
3490
  ),
3416
3491
  /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading }),
3417
3492
  !loading && results.length === 0 && /* @__PURE__ */ jsx(Alert, { title: "No results", color: "blue", children: "Try another search or filter." }),
3418
- !loading && /* @__PURE__ */ jsx(ExploreResults_default, { results, profilePrefix })
3493
+ !loading && /* @__PURE__ */ jsx(ExploreResults_default, { results, profilePrefix, onSelect })
3419
3494
  ] });
3420
3495
  }
3421
3496
  var Explore_default = BespokeExplore;
@@ -3426,13 +3501,14 @@ init_getLocales();
3426
3501
  var { localeDefault: localeDefault6 } = getLocales_default();
3427
3502
  function BespokeExploreModal({
3428
3503
  exploreProps = { profilePrefix: "/", locale: localeDefault6 },
3429
- icon = /* @__PURE__ */ jsx(IconSearch, {}),
3504
+ icon = /* @__PURE__ */ jsx(IconSearch, { size: 20 }),
3430
3505
  actionIconProps = {},
3431
- modalProps = {}
3506
+ modalProps = {},
3507
+ children
3432
3508
  }) {
3433
3509
  const [opened, setOpened] = useState(false);
3434
3510
  const btnConfig = {
3435
- variant: "subtle",
3511
+ variant: "light",
3436
3512
  size: "md",
3437
3513
  radius: "md",
3438
3514
  ...actionIconProps
@@ -3441,10 +3517,22 @@ function BespokeExploreModal({
3441
3517
  fullScreen: true,
3442
3518
  opened,
3443
3519
  onClose: () => setOpened(false)
3520
+ //...modalProps,
3444
3521
  };
3522
+ const actionIcon = /* @__PURE__ */ jsx(ActionIcon, { ...btnConfig, onClick: () => setOpened(true), children: icon });
3445
3523
  return /* @__PURE__ */ jsxs(Fragment, { children: [
3446
- /* @__PURE__ */ jsx(Modal, { ...modalProps, ...mdlConfig, children: /* @__PURE__ */ jsx(Explore_default, { ...exploreProps }) }),
3447
- /* @__PURE__ */ jsx(ActionIcon, { ...btnConfig, onClick: () => setOpened(true), children: icon })
3524
+ /* @__PURE__ */ jsx(Modal, { ...modalProps, ...mdlConfig, children: /* @__PURE__ */ jsx(Explore_default, { ...exploreProps, onSelect: () => setOpened(false) }) }),
3525
+ /* @__PURE__ */ jsx("div", { onClick: () => setOpened(true), children: children ? /* @__PURE__ */ jsx(Tooltip, { label: "Click to search", children: /* @__PURE__ */ jsxs(
3526
+ Group,
3527
+ {
3528
+ spacing: "sm",
3529
+ style: { cursor: "pointer" },
3530
+ children: [
3531
+ children,
3532
+ actionIcon
3533
+ ]
3534
+ }
3535
+ ) }) : /* @__PURE__ */ jsx(Fragment, { children: actionIcon }) })
3448
3536
  ] });
3449
3537
  }
3450
3538
  var ExploreModal_default = BespokeExploreModal;
@@ -3469,8 +3557,10 @@ var SearchItem = forwardRef(
3469
3557
  }
3470
3558
  );
3471
3559
  var SearchItem_default = SearchItem;
3472
- function BespokeSearch({ locale, profilePrefix, autocompleteProps = {} }) {
3560
+ function BespokeSearch({ locale, profilePrefix, autocompleteProps = {}, children }) {
3473
3561
  const dispatch = useAppDispatch();
3562
+ const currentLocale = useAppSelector((state) => state.status.currentLocale);
3563
+ const localeDefault9 = useAppSelector((state) => state.status.localeDefault);
3474
3564
  const router = useRouter();
3475
3565
  const [query, setQuery] = useState("");
3476
3566
  const [debouncedQuery, cancel] = useDebouncedValue(query, 500);
@@ -3478,6 +3568,7 @@ function BespokeSearch({ locale, profilePrefix, autocompleteProps = {} }) {
3478
3568
  const [loading, setLoading] = useState(false);
3479
3569
  const [redirecting, setRedirecting] = useState(false);
3480
3570
  const [initialized, setInitialized] = useState(false);
3571
+ const [visible, setVisible] = useState(children ? false : true);
3481
3572
  const inputRef = useRef();
3482
3573
  const doSearch = () => {
3483
3574
  setLoading(true);
@@ -3497,7 +3588,7 @@ function BespokeSearch({ locale, profilePrefix, autocompleteProps = {} }) {
3497
3588
  dispatch(actions_exports.reportSearch(params)).then((value) => {
3498
3589
  if (value && value.results) {
3499
3590
  setResults(value.results.map((r) => {
3500
- r.value = `VALUE: ${r.name}...`;
3591
+ r.value = `VALUE: ${r.id}`;
3501
3592
  return r;
3502
3593
  }));
3503
3594
  }
@@ -3515,10 +3606,16 @@ function BespokeSearch({ locale, profilePrefix, autocompleteProps = {} }) {
3515
3606
  }, [debouncedQuery]);
3516
3607
  useEffect(() => {
3517
3608
  cancel();
3518
- if (inputRef.current) {
3609
+ if (inputRef.current && visible) {
3519
3610
  setInitialized(true);
3520
3611
  }
3521
3612
  }, []);
3613
+ useEffect(() => {
3614
+ cancel();
3615
+ if (inputRef.current && visible) {
3616
+ setInitialized(true);
3617
+ }
3618
+ }, [visible]);
3522
3619
  const acConfig = {
3523
3620
  placeholder: "Search",
3524
3621
  size: "md",
@@ -3528,14 +3625,24 @@ function BespokeSearch({ locale, profilePrefix, autocompleteProps = {} }) {
3528
3625
  };
3529
3626
  const onItemSubmit = (item) => {
3530
3627
  setRedirecting(true);
3531
- router.push(`${profilePrefix}${item.path}`);
3628
+ setVisible(false);
3629
+ const localePrefix = currentLocale === localeDefault9 ? "" : `/${currentLocale}`;
3630
+ const url = `${localePrefix}${profilePrefix}${item.path}`;
3631
+ router.push(url);
3532
3632
  };
3533
3633
  const onChange = (searchTerm) => {
3534
3634
  if (!searchTerm.includes("VALUE:")) {
3535
3635
  setQuery(searchTerm);
3536
3636
  }
3537
3637
  };
3538
- return /* @__PURE__ */ jsx(
3638
+ const doClose = () => {
3639
+ setVisible(false);
3640
+ };
3641
+ const doOpen = () => {
3642
+ setVisible(true);
3643
+ doSearch();
3644
+ };
3645
+ const autocompleteElement = /* @__PURE__ */ jsx(
3539
3646
  Autocomplete,
3540
3647
  {
3541
3648
  value: query,
@@ -3546,11 +3653,26 @@ function BespokeSearch({ locale, profilePrefix, autocompleteProps = {} }) {
3546
3653
  disabled: (loading || redirecting) && !initialized,
3547
3654
  limit: 10,
3548
3655
  maxDropdownHeight: 250,
3549
- rightSection: loading ? /* @__PURE__ */ jsx(Loader, { size: 20 }) : "",
3656
+ rightSection: /* @__PURE__ */ jsx(Group, { spacing: 0, position: "right", children: loading ? /* @__PURE__ */ jsx(Loader, { size: 20 }) : /* @__PURE__ */ jsx(Fragment, {}) }),
3657
+ rightSectionWidth: 50,
3550
3658
  ref: inputRef,
3551
3659
  ...acConfig
3552
3660
  }
3553
3661
  );
3662
+ const finalElement = children ? /* @__PURE__ */ jsx(Tooltip, { label: "Click to search", disabled: visible, children: /* @__PURE__ */ jsxs(
3663
+ Group,
3664
+ {
3665
+ spacing: "sm",
3666
+ align: "center",
3667
+ style: { cursor: "pointer" },
3668
+ children: [
3669
+ !visible && /* @__PURE__ */ jsx("div", { onClick: () => setVisible(true), children }),
3670
+ visible && /* @__PURE__ */ jsx(Fragment, { children: autocompleteElement }),
3671
+ visible ? /* @__PURE__ */ jsx(ActionIcon, { variant: "light", onClick: doClose, children: /* @__PURE__ */ jsx(IconX, { size: 20 }) }) : /* @__PURE__ */ jsx(ActionIcon, { variant: "light", onClick: doOpen, children: /* @__PURE__ */ jsx(IconSearch, { size: 20 }) })
3672
+ ]
3673
+ }
3674
+ ) }) : autocompleteElement;
3675
+ return finalElement;
3554
3676
  }
3555
3677
  var Search_default = BespokeSearch;
3556
3678
 
@@ -3623,7 +3745,7 @@ function ParagraphView({ paragraph, tooltip, size = "md" }) {
3623
3745
  // frontend/components/report/blocks/Stat.tsx
3624
3746
  init_esm_shims();
3625
3747
  init_sanitizeBlockContent();
3626
- function Stat({ subtitle, title, value, tooltip = "stat tooltip" }) {
3748
+ function Stat({ subtitle, title, value, tooltip }) {
3627
3749
  const titleHTML = sanitizeBlockContent_default(title);
3628
3750
  const valueHTML = sanitizeBlockContent_default(value);
3629
3751
  const subtitleHTML = sanitizeBlockContent_default(subtitle);
@@ -3655,21 +3777,62 @@ function SubtitleView({ subtitle, tooltip }) {
3655
3777
  // frontend/components/report/blocks/Title.tsx
3656
3778
  init_esm_shims();
3657
3779
  init_sanitizeBlockContent();
3780
+ init_hooks();
3658
3781
  function TitleView({ title, tooltip, slug, settings }) {
3659
3782
  const titleHTML = sanitizeBlockContent_default(title) || "<span class='cr-block-placeholder'>Title</span>";
3660
3783
  const tooltipHTML = sanitizeBlockContent_default(tooltip);
3661
3784
  const intOrder = settings && settings.order ? parseInt(settings.order, 10) : 1;
3662
3785
  const order = intOrder <= 6 ? intOrder : 1;
3663
- return /* @__PURE__ */ jsxs(Group, { spacing: "xs", children: [
3664
- tooltip && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Tooltip, { label: tooltipHTML, withArrow: true, withinPortal: true, children: /* @__PURE__ */ jsx(ActionIcon, { children: /* @__PURE__ */ jsx(IconInfoCircle, {}) }) }) }, "tooltip"),
3665
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
3666
- Title,
3667
- {
3668
- order,
3669
- dangerouslySetInnerHTML: { __html: titleHTML }
3670
- }
3671
- ) })
3672
- ] });
3786
+ const searchOnClick = settings && settings.search ? settings.search : "off";
3787
+ const currentLocale = useAppSelector((state) => state.status.currentLocale);
3788
+ const profilePrefix = useProfilePrefix();
3789
+ const initialIds = useAppSelector(
3790
+ (state) => ({
3791
+ reportId: state.variables.attributes.report_id,
3792
+ variantId: state.variables.attributes.variant_id1
3793
+ })
3794
+ );
3795
+ const titleElement = /* @__PURE__ */ jsx(
3796
+ Title,
3797
+ {
3798
+ order,
3799
+ dangerouslySetInnerHTML: { __html: titleHTML }
3800
+ }
3801
+ );
3802
+ const locale = currentLocale;
3803
+ const finalElement = useMemo(() => {
3804
+ let component = /* @__PURE__ */ jsx(Fragment, {});
3805
+ if (searchOnClick === "modal") {
3806
+ component = /* @__PURE__ */ jsx(ExploreModal_default, { exploreProps: {
3807
+ locale,
3808
+ profilePrefix,
3809
+ initialReportId: initialIds.reportId,
3810
+ initialVariantId: initialIds.variantId
3811
+ }, children: titleElement });
3812
+ } else if (searchOnClick === "inline") {
3813
+ component = /* @__PURE__ */ jsx(
3814
+ Search_default,
3815
+ {
3816
+ locale,
3817
+ profilePrefix,
3818
+ children: titleElement
3819
+ }
3820
+ );
3821
+ } else {
3822
+ component = titleElement;
3823
+ }
3824
+ return component;
3825
+ }, [searchOnClick, titleElement]);
3826
+ return /* @__PURE__ */ jsxs(
3827
+ Group,
3828
+ {
3829
+ spacing: "sm",
3830
+ children: [
3831
+ tooltip && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Tooltip, { label: tooltipHTML, withArrow: true, withinPortal: true, children: /* @__PURE__ */ jsx(ActionIcon, { children: /* @__PURE__ */ jsx(IconInfoCircle, {}) }) }) }, "tooltip"),
3832
+ /* @__PURE__ */ jsx("div", { children: finalElement })
3833
+ ]
3834
+ }
3835
+ );
3673
3836
  }
3674
3837
 
3675
3838
  // frontend/components/report/blocks/Selector.tsx
@@ -3723,12 +3886,13 @@ function useOnChangeSelector(blockId, section, selectorIdentifier) {
3723
3886
  formatters,
3724
3887
  blockContext,
3725
3888
  initialVariables,
3726
- readMemberFn
3889
+ readMemberFn,
3890
+ "report"
3727
3891
  ).then((data) => {
3728
3892
  dispatch(variablesActions.setVariableChange({
3729
3893
  attributes,
3730
3894
  variables: data.variables,
3731
- status: {}
3895
+ status: data.status
3732
3896
  }));
3733
3897
  });
3734
3898
  },
@@ -3754,7 +3918,7 @@ var parseMultiValue = (selectorValue, defaultValue) => {
3754
3918
  return defaultValue;
3755
3919
  };
3756
3920
  function Selector(config) {
3757
- const { name, options, id, defaultValue, section } = config;
3921
+ const { name, options, id, defaultValue, section, component } = config;
3758
3922
  const selectorIdentifier = getSelectorIdentifier(id);
3759
3923
  const router = useRouter();
3760
3924
  const callback = useOnChangeSelector(id, section, selectorIdentifier);
@@ -3765,22 +3929,22 @@ function Selector(config) {
3765
3929
  (d) => ({ value: d.id, label: d.label })
3766
3930
  ), [optDependency]);
3767
3931
  return {
3768
- [SELECTOR_TYPES.SINGLE]: data.length > 3 ? /* @__PURE__ */ jsx(
3769
- Select,
3932
+ [SELECTOR_TYPES.SINGLE]: component === SELECTOR_COMPONENTS.SEGMENTED_CONTROL ? /* @__PURE__ */ jsx(
3933
+ SegmentedControl,
3770
3934
  {
3771
- label: name,
3772
3935
  data,
3773
3936
  value,
3774
- onChange: (value2) => callback(value2)
3937
+ onChange: (value2) => callback(value2),
3938
+ name,
3939
+ fullWidth: true
3775
3940
  }
3776
3941
  ) : /* @__PURE__ */ jsx(
3777
- SegmentedControl,
3942
+ Select,
3778
3943
  {
3944
+ label: name,
3779
3945
  data,
3780
3946
  value,
3781
- onChange: (value2) => callback(value2),
3782
- name,
3783
- fullWidth: true
3947
+ onChange: (value2) => callback(value2)
3784
3948
  }
3785
3949
  ),
3786
3950
  [SELECTOR_TYPES.MULTI]: /* @__PURE__ */ jsx(
@@ -3884,7 +4048,8 @@ function useInitialState(pathSegmentsKey) {
3884
4048
  formatters,
3885
4049
  blockContext,
3886
4050
  variables,
3887
- readMemberFn
4051
+ readMemberFn,
4052
+ "report"
3888
4053
  ).then((data) => {
3889
4054
  return dispatch(variablesActions.setVariableChange({ ...data, attributes }));
3890
4055
  });
@@ -3921,7 +4086,7 @@ function createOutline(elements, variables) {
3921
4086
  const node = {
3922
4087
  id,
3923
4088
  order,
3924
- label: variables[id] ? variables[id][`title${id}title`] : "-Not calculated yet-",
4089
+ label: variables[id] ? variables[id][`title${id}title`] : `Title ${id}`,
3925
4090
  children: []
3926
4091
  };
3927
4092
  nodes[id] = node;
@@ -3983,12 +4148,12 @@ function useContentOutline(min = 1, max = 6, headings = []) {
3983
4148
  return useMemo(() => {
3984
4149
  if (titlesSorted && titlesSorted?.length > 0) {
3985
4150
  return createOutline(titlesSorted, titleVariables);
4151
+ } else {
4152
+ return [];
3986
4153
  }
3987
4154
  }, [titlesSorted, titleVariables]);
3988
4155
  }
3989
- function NavView({ headings, settings }) {
3990
- const { type, min, max } = settings;
3991
- const contentOutline = useContentOutline(parseInt(min, 10), parseInt(max, 10), headings);
4156
+ var DesktopNav = ({ contentOutline }) => {
3992
4157
  const renderMenu = (nodes) => {
3993
4158
  if (!nodes || !nodes?.length) {
3994
4159
  return null;
@@ -4021,6 +4186,80 @@ function NavView({ headings, settings }) {
4021
4186
  )
4022
4187
  }
4023
4188
  ) });
4189
+ };
4190
+ var MobileAccordion = ({ contentOutline, closeNav }) => {
4191
+ const [value, setValue] = useState(null);
4192
+ return /* @__PURE__ */ jsx(Stack, { children: contentOutline.map(
4193
+ (node) => node.children.length ? /* @__PURE__ */ jsxs(Fragment, { children: [
4194
+ /* @__PURE__ */ jsxs(Group, { spacing: 0, noWrap: true, children: [
4195
+ /* @__PURE__ */ jsx(
4196
+ UnstyledButton,
4197
+ {
4198
+ w: "100%",
4199
+ component: "a",
4200
+ onClick: closeNav,
4201
+ href: `#bespoke-title-${node.id}`,
4202
+ children: /* @__PURE__ */ jsx(Text, { pl: "sm", dangerouslySetInnerHTML: { __html: node.label } })
4203
+ },
4204
+ node.id
4205
+ ),
4206
+ /* @__PURE__ */ jsx(
4207
+ ActionIcon,
4208
+ {
4209
+ component: "a",
4210
+ size: "lg",
4211
+ onClick: () => setValue((value2) => value2 === node.id ? null : node.id),
4212
+ children: /* @__PURE__ */ jsx(
4213
+ IconChevronDown,
4214
+ {
4215
+ style: {
4216
+ transition: "transform 0.2s",
4217
+ transform: value === node.id ? "rotate(-180deg)" : "none"
4218
+ },
4219
+ stroke: 1
4220
+ }
4221
+ )
4222
+ }
4223
+ )
4224
+ ] }, node.id),
4225
+ /* @__PURE__ */ jsx(
4226
+ Collapse,
4227
+ {
4228
+ in: value === node.id,
4229
+ pl: "sm",
4230
+ transitionTimingFunction: "linear",
4231
+ transitionDuration: 200,
4232
+ children: /* @__PURE__ */ jsx(MobileAccordion, { contentOutline: node.children, closeNav })
4233
+ }
4234
+ )
4235
+ ] }) : /* @__PURE__ */ jsx(Group, { noWrap: true, children: /* @__PURE__ */ jsx(
4236
+ UnstyledButton,
4237
+ {
4238
+ display: "flex",
4239
+ w: "100%",
4240
+ component: "a",
4241
+ href: `#bespoke-title-${node.id}`,
4242
+ children: /* @__PURE__ */ jsx(Text, { pl: "sm", dangerouslySetInnerHTML: { __html: node.label } })
4243
+ },
4244
+ node.id
4245
+ ) }, node.id)
4246
+ ) });
4247
+ };
4248
+ var MobileNav = ({ contentOutline }) => {
4249
+ const [opened, { toggle }] = useDisclosure(false);
4250
+ const label = opened ? "Close content outline" : "Open content outline";
4251
+ return /* @__PURE__ */ jsxs(Box, { component: "nav", children: [
4252
+ /* @__PURE__ */ jsx(Group, { children: /* @__PURE__ */ jsx(Burger, { opened, onClick: toggle, "aria-label": label, size: "md" }) }),
4253
+ /* @__PURE__ */ jsx(Collapse, { in: opened, mt: "md", children: /* @__PURE__ */ jsx(MobileAccordion, { contentOutline, closeNav: toggle }) })
4254
+ ] });
4255
+ };
4256
+ function NavView({ headings, settings }) {
4257
+ const { type, min, max } = settings;
4258
+ const contentOutline = useContentOutline(parseInt(min, 10), parseInt(max, 10), headings);
4259
+ const theme = useMantineTheme();
4260
+ const mq = `(max-width: ${theme.breakpoints.md})`;
4261
+ const smallerThanMd = useMediaQuery(mq);
4262
+ return smallerThanMd ? /* @__PURE__ */ jsx(MobileNav, { contentOutline }) : /* @__PURE__ */ jsx(DesktopNav, { contentOutline });
4024
4263
  }
4025
4264
 
4026
4265
  // frontend/components/report/blocks/index.tsx
@@ -4059,8 +4298,9 @@ var validateOptionsArray = (options) => {
4059
4298
  return options.map((d) => typeof d === "string" ? { id: d, label: d } : d);
4060
4299
  };
4061
4300
  var maybeFixForMulti = (defaultValue, type) => type === SELECTOR_TYPES.MULTI && !Array.isArray(defaultValue) ? [defaultValue] : defaultValue;
4062
- var Selector_default = (vars, id) => {
4301
+ var selectorAdapter = (vars, id) => {
4063
4302
  const type = vars.type || SELECTOR_TYPES.SINGLE;
4303
+ const component = vars.component || "Selector";
4064
4304
  const name = vars.name || "Unlabeled Selector";
4065
4305
  const options = validateOptionsArray(vars.options || []);
4066
4306
  let defaultValue;
@@ -4078,9 +4318,11 @@ var Selector_default = (vars, id) => {
4078
4318
  name,
4079
4319
  type,
4080
4320
  options,
4321
+ component,
4081
4322
  defaultValue
4082
4323
  };
4083
4324
  };
4325
+ var Selector_default = selectorAdapter;
4084
4326
 
4085
4327
  // components/blocks/types/adapters/index.js
4086
4328
  var adapters_default = {
@@ -4123,6 +4365,10 @@ var SELECTOR_TYPE = {
4123
4365
  SINGLE: "single",
4124
4366
  MULTI: "multi"
4125
4367
  };
4368
+ var SELECTOR_COMPONENT = {
4369
+ SEGMENTED_CONTROL: "segmented control",
4370
+ SELECTOR: "selector"
4371
+ };
4126
4372
  var OPTION_TYPE = {
4127
4373
  STATIC: "static",
4128
4374
  DYNAMIC: "dynamic"
@@ -4344,14 +4590,16 @@ function SelectorUI(props) {
4344
4590
  } = props;
4345
4591
  const [selectorIdentifier, setSelectorIdentifier] = useState("");
4346
4592
  const [selectorType, setSelectorType] = useState(SELECTOR_TYPE.SINGLE);
4593
+ const [selectorComponent, setSelectorComponent] = useState(SELECTOR_COMPONENT.SELECTOR);
4347
4594
  const [options, setOptions] = useState({ static: [], dynamic: {} });
4348
4595
  const [optionsType, setOptionsType] = useState(OPTION_TYPE.STATIC);
4349
- const stateFields = [selectorIdentifier, selectorType, options, optionsType];
4596
+ const stateFields = [selectorIdentifier, selectorType, selectorComponent, options, optionsType];
4350
4597
  useEffect(() => {
4351
4598
  if (!simpleState)
4352
4599
  return;
4353
4600
  setSelectorIdentifier(simpleState.name || "");
4354
4601
  setSelectorType(simpleState.type);
4602
+ setSelectorComponent(simpleState.component);
4355
4603
  if (simpleState.options?.hasOwnProperty("dynamic") && simpleState.options?.hasOwnProperty("static")) {
4356
4604
  setOptions(simpleState.options);
4357
4605
  }
@@ -4361,6 +4609,7 @@ function SelectorUI(props) {
4361
4609
  () => {
4362
4610
  const logicObj = {
4363
4611
  name: selectorIdentifier,
4612
+ component: selectorComponent,
4364
4613
  type: selectorType
4365
4614
  };
4366
4615
  let defaultValue;
@@ -4387,6 +4636,7 @@ function SelectorUI(props) {
4387
4636
  const simpleState2 = {
4388
4637
  name: selectorIdentifier,
4389
4638
  type: selectorType,
4639
+ component: selectorComponent,
4390
4640
  optionsType,
4391
4641
  options
4392
4642
  };
@@ -4415,6 +4665,15 @@ function SelectorUI(props) {
4415
4665
  data: Object.values(SELECTOR_TYPE)
4416
4666
  }
4417
4667
  ),
4668
+ selectorType === SELECTOR_TYPE.SINGLE && /* @__PURE__ */ jsx(
4669
+ Select,
4670
+ {
4671
+ label: "Selector Component",
4672
+ value: selectorComponent,
4673
+ onChange: setSelectorComponent,
4674
+ data: Object.values(SELECTOR_COMPONENT)
4675
+ }
4676
+ ),
4418
4677
  /* @__PURE__ */ jsx(
4419
4678
  Select,
4420
4679
  {
@@ -4515,7 +4774,9 @@ function TitlePreview({ title, tooltip, slug, settings }) {
4515
4774
  const tooltipHTML = sanitizeBlockContent_default(tooltip);
4516
4775
  const intOrder = settings && settings.order ? parseInt(settings.order, 10) : 1;
4517
4776
  const order = intOrder <= 6 ? intOrder : 1;
4518
- return /* @__PURE__ */ jsxs("div", { children: [
4777
+ const searchOnClick = settings && settings.search && settings.search !== "off" ? true : false;
4778
+ const searchType = settings && settings.search ? settings.search : "";
4779
+ return /* @__PURE__ */ jsxs(Group, { spacing: "sm", children: [
4519
4780
  tooltip && /* @__PURE__ */ jsx("div", { style: { position: "absolute", right: "50px" }, children: /* @__PURE__ */ jsx(Tooltip, { label: tooltipHTML, withArrow: true, withinPortal: true, children: /* @__PURE__ */ jsx(ActionIcon, { children: /* @__PURE__ */ jsx(IconInfoCircle, {}) }) }) }, "tooltip"),
4520
4781
  /* @__PURE__ */ jsx(
4521
4782
  Title,
@@ -4523,7 +4784,8 @@ function TitlePreview({ title, tooltip, slug, settings }) {
4523
4784
  order,
4524
4785
  dangerouslySetInnerHTML: { __html: titleHTML }
4525
4786
  }
4526
- )
4787
+ ),
4788
+ searchOnClick && /* @__PURE__ */ jsx(Tooltip, { label: `Click will open '${searchType}' report search`, children: /* @__PURE__ */ jsx(ActionIcon, { variant: "light", children: /* @__PURE__ */ jsx(IconSearch, { size: 20 }) }) })
4527
4789
  ] });
4528
4790
  }
4529
4791
 
@@ -4576,7 +4838,18 @@ function SelectorPreview(config) {
4576
4838
  };
4577
4839
  const { name } = config;
4578
4840
  return {
4579
- [SELECTOR_TYPES.SINGLE]: /* @__PURE__ */ jsx(
4841
+ [SELECTOR_TYPES.SINGLE]: config.component === SELECTOR_COMPONENTS.SEGMENTED_CONTROL ? /* @__PURE__ */ jsxs("div", { children: [
4842
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: name }),
4843
+ /* @__PURE__ */ jsx(
4844
+ SegmentedControl,
4845
+ {
4846
+ data,
4847
+ value,
4848
+ onChange: onChangeSingle,
4849
+ fullWidth: true
4850
+ }
4851
+ )
4852
+ ] }) : /* @__PURE__ */ jsx(
4580
4853
  Select,
4581
4854
  {
4582
4855
  label: name,
@@ -4968,7 +5241,6 @@ init_varSwap();
4968
5241
  init_mortarEval();
4969
5242
  init_envvars();
4970
5243
  init_runSelector();
4971
- init_block();
4972
5244
  function Block({ blockId, active = true }) {
4973
5245
  const { query, locale = localeDefault4 } = useRouter();
4974
5246
  const block = useBlockRef(blockId).data;
@@ -4981,8 +5253,9 @@ function Block({ blockId, active = true }) {
4981
5253
  locale
4982
5254
  };
4983
5255
  const generatorVariables = useAppSelector((state) => state.variables.variables[block.id] || {});
5256
+ const blockStatus = useAppSelector((state) => state.variables.status[block.id] || {});
4984
5257
  const [content, setContent] = useState(() => {
4985
- if (![BLOCK_TYPES.GENERATOR, BLOCK_TYPES.VIZ, BLOCK_TYPES.NAV].includes(block?.type)) {
5258
+ if (![BLOCK_TYPES.GENERATOR, BLOCK_TYPES.VIZ, BLOCK_TYPES.NAV].includes(block.type)) {
4986
5259
  if (block?.type === BLOCK_TYPES.SELECTOR) {
4987
5260
  const blockContent2 = getBlockContent(block, locale);
4988
5261
  const { config: renderVariables } = runSelector_default(blockContent2?.logic, formatterFunctions, blockContext);
@@ -5002,24 +5275,6 @@ function Block({ blockId, active = true }) {
5002
5275
  }
5003
5276
  return null;
5004
5277
  });
5005
- let allowed = true;
5006
- if (block && "allowed" in block.settings && block.settings.allowed !== "always") {
5007
- if (block.settings.allowed === "never") {
5008
- allowed = false;
5009
- } else {
5010
- const parsedBlockContext = parseBlockContext(blockContext);
5011
- const { vars, error, output } = mortarEval_default(
5012
- "variables",
5013
- variables,
5014
- block.settings.allowedLogic || "return false;",
5015
- formatterFunctions,
5016
- void 0,
5017
- parsedBlockContext
5018
- );
5019
- if (!error)
5020
- allowed = Boolean(output);
5021
- }
5022
- }
5023
5278
  useEffect(() => {
5024
5279
  const fetch = async () => {
5025
5280
  if (!block || block.type === BLOCK_TYPES.GENERATOR)
@@ -5074,7 +5329,7 @@ function Block({ blockId, active = true }) {
5074
5329
  };
5075
5330
  fetch();
5076
5331
  }, [blockContent, variables]);
5077
- if (!block || !content || !allowed)
5332
+ if (!block || !content || !blockStatus.allowed)
5078
5333
  return null;
5079
5334
  const Renderer = blocks_default[block.type];
5080
5335
  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 }) });
@@ -5903,7 +6158,8 @@ function DesignSectionMenu({ sectionId }) {
5903
6158
  return null;
5904
6159
  const {
5905
6160
  memberImageBg,
5906
- optionsMenu
6161
+ optionsMenu,
6162
+ hidden
5907
6163
  } = section.settings;
5908
6164
  return /* @__PURE__ */ jsxs(
5909
6165
  Popover,
@@ -5939,6 +6195,15 @@ function DesignSectionMenu({ sectionId }) {
5939
6195
  onChange: (e) => handleChange("optionsMenu", e.currentTarget.checked)
5940
6196
  }
5941
6197
  ),
6198
+ /* @__PURE__ */ jsx(
6199
+ Checkbox,
6200
+ {
6201
+ size: "xs",
6202
+ label: "Hide section",
6203
+ checked: hidden,
6204
+ onChange: (e) => handleChange("hidden", e.currentTarget.checked)
6205
+ }
6206
+ ),
5942
6207
  Object.entries(sectionSettings).map(([key, { label, defaultValue, options }]) => /* @__PURE__ */ jsxs(Group, { spacing: "xs", position: "apart", noWrap: true, style: { width: "100%" }, children: [
5943
6208
  label && /* @__PURE__ */ jsx(Text, { fz: "sm", children: label }),
5944
6209
  /* @__PURE__ */ jsx(
@@ -5978,6 +6243,9 @@ function SectionMenu({ sectionId }) {
5978
6243
  ] });
5979
6244
  }
5980
6245
  var SectionMenu_default = SectionMenu;
6246
+
6247
+ // frontend/components/report/Section.tsx
6248
+ init_cms();
5981
6249
  var getStyles = (styles, settings) => (theme) => styles ? styles(theme, settings) : {};
5982
6250
  var PositionWrapper = ({ settings, styles, children, ...props }) => {
5983
6251
  const { position } = settings;
@@ -6042,11 +6310,20 @@ function Section({ section }) {
6042
6310
  ...settings
6043
6311
  };
6044
6312
  const state = useAppSelector((state2) => state2);
6313
+ const status = useAppSelector((state2) => state2.variables.status);
6045
6314
  const sectionStyles = useBespokeStyles()["Section"];
6046
6315
  const blockRecords = selectBlockRecords(state);
6047
6316
  const theme = useMantineTheme();
6048
6317
  const smallScreen = useMediaQuery(`(max-width: ${theme.breakpoints.sm}px)`);
6049
- const columns = Object.values(blockRecords || {}).filter((d) => d.section_id === id).reduce((acc, d) => {
6318
+ const sectionBlocks = Object.values(blockRecords || {}).filter((d) => d.section_id === id);
6319
+ const allowedSection = sectionBlocks.some((b) => {
6320
+ try {
6321
+ return status[b.id].allowed && b.type !== BLOCK_TYPES.GENERATOR;
6322
+ } catch (e) {
6323
+ return b.settings.allowed === "always";
6324
+ }
6325
+ });
6326
+ const columns = sectionBlocks.reduce((acc, d) => {
6050
6327
  if (!acc[d.blockcol]) {
6051
6328
  acc[d.blockcol] = { [d.blockrow]: d };
6052
6329
  } else {
@@ -6054,6 +6331,9 @@ function Section({ section }) {
6054
6331
  }
6055
6332
  return acc;
6056
6333
  }, {});
6334
+ const displaySection = Object.keys(blockRecords).length > 0 && !settings.hidden && allowedSection;
6335
+ if (!displaySection)
6336
+ return null;
6057
6337
  return /* @__PURE__ */ jsxs(
6058
6338
  PositionWrapper,
6059
6339
  {
@@ -6292,8 +6572,14 @@ init_esm_shims();
6292
6572
 
6293
6573
  // components/builder/JumpTo.tsx
6294
6574
  init_esm_shims();
6575
+ init_store2();
6295
6576
  function JumpTo() {
6296
- const contentOutline = useContentOutline();
6577
+ const blocks = useBlockList();
6578
+ const titleBlocks = useMemo(
6579
+ () => blocks.data ? blocks.data.filter((d) => d.type === "title").map((d) => d.id) : [],
6580
+ [blocks.data]
6581
+ );
6582
+ const contentOutline = useContentOutline(1, 6, titleBlocks);
6297
6583
  const handleClick = (blockId) => {
6298
6584
  const section = document.getElementById(`title-${blockId}`);
6299
6585
  if (section) {
@@ -6305,7 +6591,7 @@ function JumpTo() {
6305
6591
  if (!nodes) {
6306
6592
  return null;
6307
6593
  }
6308
- return /* @__PURE__ */ jsx(Fragment, { children: nodes.map((node) => /* @__PURE__ */ jsxs(Fragment, { children: [
6594
+ return /* @__PURE__ */ jsx(Fragment, { children: nodes.map((node) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
6309
6595
  /* @__PURE__ */ jsx(
6310
6596
  Menu.Item,
6311
6597
  {
@@ -6313,11 +6599,10 @@ function JumpTo() {
6313
6599
  onClick: () => handleClick(node.id),
6314
6600
  pl: 10 * node.order,
6315
6601
  children: node.label
6316
- },
6317
- `jump-key-${node.id}`
6602
+ }
6318
6603
  ),
6319
6604
  renderOutline(node.children)
6320
- ] })) });
6605
+ ] }, `jump-key-${node.id}`)) });
6321
6606
  };
6322
6607
  return /* @__PURE__ */ jsx("div", { style: { position: "fixed", bottom: 10, right: 10, zIndex: 10 }, children: /* @__PURE__ */ jsxs(Menu, { shadow: "md", position: "top-end", offset: 0, children: [
6323
6608
  /* @__PURE__ */ jsx(Menu.Target, { children: /* @__PURE__ */ jsx(ActionIcon, { variant: "filled", color: "blue", children: /* @__PURE__ */ jsx(IconListSearch, {}) }) }),
@@ -7138,12 +7423,13 @@ function VariantEditor({ for: variant, onClose: closeHandler }) {
7138
7423
  ),
7139
7424
  variantConfig.config[selectedLocale] && /* @__PURE__ */ jsxs(Fragment, { children: [
7140
7425
  /* @__PURE__ */ jsx(Space, { h: "lg" }),
7141
- /* @__PURE__ */ jsxs(Group, { grow: true, children: [
7426
+ /* @__PURE__ */ jsxs(Group, { grow: true, align: "flex-end", children: [
7142
7427
  /* @__PURE__ */ jsx(
7143
7428
  TextInput,
7144
7429
  {
7145
7430
  onChange: (e) => onChangeConfig("path", e.target.value),
7146
- placeholder: "Enter a source API",
7431
+ title: "Api endpoint",
7432
+ description: "Enter the url to retrieve a member list to ingest. (JSON) and click Fetch.",
7147
7433
  value: variantConfig.config[selectedLocale].path
7148
7434
  }
7149
7435
  ),
@@ -7164,19 +7450,24 @@ function VariantEditor({ for: variant, onClose: closeHandler }) {
7164
7450
  Select,
7165
7451
  {
7166
7452
  value: variantConfig.config[selectedLocale].accessor,
7167
- label: "Accessor property (array)",
7453
+ label: "Elements",
7454
+ description: "Choose the key that returns the array of elements that \n are going to be ingested as members.",
7168
7455
  data: accessorSelectData,
7456
+ disabled: accessorSelectData.length === 0,
7457
+ placeholder: accessorSelectData.length === 0 ? "Root is an array" : "",
7169
7458
  onChange: (e) => onChangeAccessor(e)
7170
7459
  }
7171
7460
  ),
7172
7461
  /* @__PURE__ */ jsx(Divider, { label: "First element preview", labelPosition: "center" }),
7173
- payload[variantConfig.config[selectedLocale].accessor] && /* @__PURE__ */ jsx(InputMenuItem_default, { variables: payload[variantConfig.config[selectedLocale].accessor][0] }),
7462
+ payload[variantConfig.config[selectedLocale].accessor] && !Array.isArray(payload) && /* @__PURE__ */ jsx(InputMenuItem_default, { variables: payload[variantConfig.config[selectedLocale].accessor][0] }),
7463
+ Array.isArray(payload) && payload[0] && /* @__PURE__ */ jsx(InputMenuItem_default, { variables: payload[0] }),
7174
7464
  /* @__PURE__ */ jsx(Space, { h: "md" }),
7175
7465
  /* @__PURE__ */ jsx(
7176
7466
  Select,
7177
7467
  {
7178
7468
  value: variantConfig.config[selectedLocale].idKey,
7179
- label: "Key property",
7469
+ label: "Unique identificator",
7470
+ description: "Choose the field that is a unique identification for a single member.",
7180
7471
  data: keys,
7181
7472
  onChange: (e) => onChangeConfig("idKey", e)
7182
7473
  }
@@ -7186,13 +7477,29 @@ function VariantEditor({ for: variant, onClose: closeHandler }) {
7186
7477
  Select,
7187
7478
  {
7188
7479
  value: variantConfig.config[selectedLocale].labelKey,
7189
- label: "Label property",
7480
+ label: "Members' name",
7481
+ description: "Choose the field that contains the members name.",
7190
7482
  data: keys,
7191
7483
  onChange: (e) => onChangeConfig("labelKey", e)
7192
7484
  }
7193
7485
  ),
7194
7486
  /* @__PURE__ */ jsx(Space, { h: "md" }),
7487
+ /* @__PURE__ */ jsx(
7488
+ Select,
7489
+ {
7490
+ value: variantConfig.config[selectedLocale].zValueKey || "",
7491
+ label: "Member's relevance (optional)",
7492
+ description: "Choose a field that will be converted to a number and \n normalized from 0 to 1 to determine the member's relevance.",
7493
+ data: [
7494
+ { value: "null", label: "None" },
7495
+ ...keys
7496
+ ],
7497
+ onChange: (e) => onChangeConfig("zValueKey", e)
7498
+ }
7499
+ ),
7500
+ /* @__PURE__ */ jsx(Space, { h: "md" }),
7195
7501
  /* @__PURE__ */ jsx(Title, { order: 3, size: "h5", children: "Attributes" }),
7502
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: "Attributes are properties to be ingested as metadata with the member element. Could be constants (same value for every member) or dynamic (based on a property of the data)" }),
7196
7503
  /* @__PURE__ */ jsx(Space, { h: "xs" }),
7197
7504
  variantConfig.config[selectedLocale].attributes && variantConfig.config[selectedLocale].attributes.map((attr, ix) => /* @__PURE__ */ jsxs(Group, { align: "end", grow: true, children: [
7198
7505
  /* @__PURE__ */ jsx(
@@ -7289,7 +7596,7 @@ function VariantEditor({ for: variant, onClose: closeHandler }) {
7289
7596
  }
7290
7597
  )
7291
7598
  ] }),
7292
- size: 145
7599
+ size: 165
7293
7600
  }
7294
7601
  );
7295
7602
  }
@@ -7368,7 +7675,7 @@ function DimensionEditor({ id, onClose: closeHandler }) {
7368
7675
  /* @__PURE__ */ jsx(Button, { variant: "outline", disabled: loading, loading, onClick: closeHandler, children: "Cancel" }),
7369
7676
  /* @__PURE__ */ jsx(Button, { disabled: loading, loading, onClick: submitHandler, children: "Save Dimension" })
7370
7677
  ] }),
7371
- size: 145
7678
+ size: 165
7372
7679
  }
7373
7680
  );
7374
7681
  }
@@ -7439,7 +7746,7 @@ function ReportEditor({ id, onClose: closeHandler }) {
7439
7746
  /* @__PURE__ */ jsx(Button, { variant: "outline", disabled: loading, loading, onClick: closeHandler, children: "Cancel" }),
7440
7747
  /* @__PURE__ */ jsx(Button, { disabled: loading, loading, onClick: submitHandler, children: "Save Report" })
7441
7748
  ] }),
7442
- size: 145
7749
+ size: 165
7443
7750
  }
7444
7751
  );
7445
7752
  }
@@ -7460,17 +7767,155 @@ function HeaderLayout(props) {
7460
7767
 
7461
7768
  // components/builder/CMSHeader.tsx
7462
7769
  init_statusSlice();
7770
+ init_hooks();
7771
+
7772
+ // components/builder/BlockGraph.tsx
7773
+ init_esm_shims();
7774
+ init_store2();
7775
+ function BlockGraph() {
7776
+ const [screenWidth, setScreenWidth] = useState(window.innerWidth - 40);
7777
+ const [screenHeight, setScreenHeight] = useState(window.innerHeight - 150);
7778
+ useEffect(() => {
7779
+ const handleResize = () => {
7780
+ setScreenWidth(window.innerWidth - 40);
7781
+ setScreenHeight(window.innerHeight - 120);
7782
+ };
7783
+ window.addEventListener("resize", handleResize);
7784
+ return () => {
7785
+ window.removeEventListener("resize", handleResize);
7786
+ };
7787
+ }, []);
7788
+ const blocks = useBlockList();
7789
+ const sections = useSectionList();
7790
+ const [sectionSelected, setSectionSelected] = useState(null);
7791
+ const sectionList = useMemo(() => {
7792
+ if (sections.isSuccess) {
7793
+ const sectionsOptions = sections.data.map((n) => ({
7794
+ value: `${n.id}`,
7795
+ label: `Section ${n.id}`
7796
+ }));
7797
+ setSectionSelected(sectionsOptions[0].value);
7798
+ return sectionsOptions;
7799
+ } else {
7800
+ return [];
7801
+ }
7802
+ }, [sections.isLoading]);
7803
+ const data = useMemo(() => {
7804
+ if (blocks.isSuccess && sectionSelected) {
7805
+ const rootNode = { id: "root", label: "section", size: 40, parentIds: [] };
7806
+ const globalNode = { id: "wide", label: "report", size: 40, parentIds: [] };
7807
+ const sectionBlocks = blocks.data.filter((n) => `${n.section_id}` === `${sectionSelected}`);
7808
+ const sectionBlocksIds = sectionBlocks.map((n) => n.id);
7809
+ return [
7810
+ rootNode,
7811
+ globalNode,
7812
+ ...sectionBlocks.map((n) => {
7813
+ const projectedSize = n.consumers.length > 0 ? n.consumers.length * 20 : 40;
7814
+ const parentIds = n.inputs.length > 0 ? n.inputs.map((i) => sectionBlocksIds.includes(i) ? `${i}` : `${globalNode.id}`) : [`${rootNode.id}`];
7815
+ return {
7816
+ id: `${n.id}`,
7817
+ label: `${n.type}`,
7818
+ size: projectedSize > 50 ? 50 : projectedSize,
7819
+ parentIds: [...Array.from(new Set(parentIds))]
7820
+ };
7821
+ })
7822
+ ];
7823
+ } else {
7824
+ return [];
7825
+ }
7826
+ }, [blocks.isLoading, sectionSelected]);
7827
+ const svgRef = useRef(null);
7828
+ useEffect(() => {
7829
+ const dag = d3Dag.dagStratify()(data);
7830
+ const nodeRadius = 40;
7831
+ const layout = d3Dag.sugiyama().nodeSize((node) => {
7832
+ const data2 = node ? node.data : null;
7833
+ const internalRadius = data2 ? data2.size : nodeRadius;
7834
+ return [(node ? 3.6 : 0.25) * internalRadius, 3 * internalRadius];
7835
+ });
7836
+ const { width, height } = layout(dag);
7837
+ const svgSelection = d3.select(svgRef.current);
7838
+ svgSelection.selectAll("*").remove();
7839
+ svgSelection.attr("viewBox", [0, 0, width, height].join(" "));
7840
+ const defs = svgSelection.append("defs");
7841
+ const steps = dag.size();
7842
+ const interp = d3.interpolateRainbow;
7843
+ const colorMap = /* @__PURE__ */ new Map();
7844
+ data.forEach((node, i) => {
7845
+ colorMap.set(node.id, interp(i / steps));
7846
+ });
7847
+ const line2 = d3.line().curve(d3.curveCatmullRom).x((d) => d.x).y((d) => d.y);
7848
+ const paths = svgSelection.append("g").selectAll("g").data(dag.links()).enter().append("g");
7849
+ paths.append("path").attr("class", "curve").attr("d", ({ points }) => line2(points)).attr("fill", "none").attr("stroke-width", 3).attr("stroke", ({ source, target }) => {
7850
+ const gradId = encodeURIComponent(`${source.data.id}--${target.data.id}`);
7851
+ const grad = defs.append("linearGradient").attr("id", gradId).attr("gradientUnits", "userSpaceOnUse").attr("x1", source.x).attr("x2", target.x).attr("y1", source.y).attr("y2", target.y);
7852
+ grad.append("stop").attr("offset", "0%").attr("stop-color", colorMap.get(source.data.id));
7853
+ grad.append("stop").attr("offset", "100%").attr("stop-color", colorMap.get(target.data.id));
7854
+ return `url(#${gradId})`;
7855
+ });
7856
+ const nodes = svgSelection.append("g").selectAll("g").data(dag.descendants()).enter().append("g").attr("transform", ({ x, y }) => `translate(${x}, ${y})`);
7857
+ nodes.append("circle").attr("r", (n) => n.data.size).attr("fill", (n) => colorMap.get(n.data.id));
7858
+ const arrows = svgSelection.append("g").selectAll("g").data(dag.links()).enter().append("g");
7859
+ const arrow = d3.symbol().type(d3.symbolTriangle).size(nodeRadius * 1.5);
7860
+ arrows.append("path").attr("class", "arrow").attr("d", arrow).attr("transform", (link) => {
7861
+ const { points, target } = link;
7862
+ const [end, start] = points.reverse();
7863
+ const dx = start.x - end.x;
7864
+ const dy = start.y - end.y;
7865
+ const scale = target.data.size * 1 / Math.sqrt(dx * dx + dy * dy);
7866
+ const angle = Math.atan2(-dy, -dx) * 180 / Math.PI + 90;
7867
+ return `translate(${end.x + dx * scale}, ${end.y + dy * scale}) rotate(${angle})`;
7868
+ }).attr("fill", ({ target }) => colorMap.get(target.data.id)).attr("stroke", "white");
7869
+ const texts = svgSelection.append("g").selectAll("g").data(dag.descendants()).enter().append("g").attr("transform", ({ x, y }) => `translate(${x}, ${y})`);
7870
+ texts.append("text").text((d) => d.data.id).attr("font-weight", "bold").attr("font-family", "sans-serif").attr("text-anchor", "middle").attr("font-size", "10px").style("transform", "translate(0px,10px)").attr("alignment-baseline", "middle").attr("fill", "black");
7871
+ texts.append("text").text((d) => d.data.label).attr("font-weight", "bold").attr("font-family", "sans-serif").attr("font-size", "15px").style("transform", "translate(0px,-5px)").attr("text-anchor", "middle").attr("alignment-baseline", "middle").attr("fill", "black");
7872
+ }, [data]);
7873
+ const handlePrev = () => {
7874
+ const currentIndex = sectionList.findIndex((item) => item.value === sectionSelected);
7875
+ if (currentIndex > 0) {
7876
+ setSectionSelected(sectionList[currentIndex - 1].value);
7877
+ }
7878
+ };
7879
+ const handleNext = () => {
7880
+ const currentIndex = sectionList.findIndex((item) => item.value === sectionSelected);
7881
+ if (currentIndex < sectionList.length - 1) {
7882
+ setSectionSelected(sectionList[currentIndex + 1].value);
7883
+ }
7884
+ };
7885
+ return /* @__PURE__ */ jsxs(Stack, { spacing: 0, children: [
7886
+ /* @__PURE__ */ jsxs(Group, { align: "flex-end", w: "100%", position: "apart", children: [
7887
+ /* @__PURE__ */ jsx(
7888
+ Select,
7889
+ {
7890
+ label: "Chooose a section",
7891
+ placeholder: "Pick one",
7892
+ value: sectionSelected,
7893
+ onChange: setSectionSelected,
7894
+ data: sectionList,
7895
+ width: "80%"
7896
+ }
7897
+ ),
7898
+ /* @__PURE__ */ jsxs(Group, { grow: true, maw: 100, children: [
7899
+ /* @__PURE__ */ jsx(ActionIcon, { onClick: handlePrev, variant: "outline", children: /* @__PURE__ */ jsx(IconChevronLeft, { size: "1.125rem" }) }),
7900
+ /* @__PURE__ */ jsx(ActionIcon, { onClick: handleNext, variant: "outline", children: /* @__PURE__ */ jsx(IconChevronRight, { size: "1.125rem" }) })
7901
+ ] })
7902
+ ] }),
7903
+ /* @__PURE__ */ jsx("svg", { ref: svgRef, width: screenWidth, height: screenHeight })
7904
+ ] });
7905
+ }
7463
7906
  function CMSHeader(props) {
7464
- const { report: currentReport, profilePrefix } = props;
7907
+ const { report: currentReport } = props;
7465
7908
  const { id } = currentReport;
7466
7909
  const { newConfirmation } = useDialog();
7467
7910
  const dispatch = useAppDispatch();
7468
7911
  const resource = useContext(ResourceContext);
7912
+ const profilePrefix = useProfilePrefix();
7469
7913
  const currentLocale = useAppSelector((state) => state.status.currentLocale);
7470
7914
  const localeDefault9 = useAppSelector((state) => state.status.localeDefault);
7471
7915
  const localeOptions = useAppSelector(selectLocaleOptions);
7472
7916
  const previewsFromState = useAppSelector((state) => state.status.previews);
7473
7917
  const [opened, handlers] = useDisclosure(false);
7918
+ const [openedGraph, handlersGraph] = useDisclosure(false);
7474
7919
  const { user } = useUser();
7475
7920
  const castedUser = user;
7476
7921
  const dimensions = useMemo(() => {
@@ -7648,9 +8093,11 @@ function CMSHeader(props) {
7648
8093
  /* @__PURE__ */ jsx(Text, { fw: 700, children: currentReport.name })
7649
8094
  ] }) }),
7650
8095
  /* @__PURE__ */ jsx(Menu.Label, { children: "Settings" }),
7651
- /* @__PURE__ */ jsx(Menu.Item, { onClick: handlers.open, icon: /* @__PURE__ */ jsx(IconSettings, { size: 20 }), children: "Report settings" })
8096
+ /* @__PURE__ */ jsx(Menu.Item, { onClick: handlers.open, icon: /* @__PURE__ */ jsx(IconSettings, { size: 20 }), children: "Report settings" }),
8097
+ /* @__PURE__ */ jsx(Menu.Item, { onClick: handlersGraph.open, icon: /* @__PURE__ */ jsx(IconHierarchy3, { size: 20 }), children: "Block Graph" })
7652
8098
  ] })
7653
8099
  ] }),
8100
+ /* @__PURE__ */ jsx(Modal, { opened: openedGraph, onClose: handlersGraph.close, title: "Block Graph", fullScreen: true, children: /* @__PURE__ */ jsx(BlockGraph, {}) }),
7654
8101
  /* @__PURE__ */ jsx(
7655
8102
  Drawer,
7656
8103
  {
@@ -7744,6 +8191,15 @@ var customSettings = {
7744
8191
  { label: "6", value: "6" }
7745
8192
  ]
7746
8193
  },
8194
+ search: {
8195
+ label: "Search on Click",
8196
+ defaultValue: "off",
8197
+ options: [
8198
+ { label: "Off", value: "off" },
8199
+ { label: "Inline", value: "inline" },
8200
+ { label: "Modal", value: "modal" }
8201
+ ]
8202
+ },
7747
8203
  ...defaultSettings2
7748
8204
  },
7749
8205
  [BLOCK_TYPES.GENERATOR]: {
@@ -7757,8 +8213,8 @@ var customSettings = {
7757
8213
  }
7758
8214
  },
7759
8215
  [BLOCK_TYPES.NAV]: {
7760
- type: {
7761
- label: "Nav type",
8216
+ variant: {
8217
+ label: "Nav variant",
7762
8218
  defaultValue: "inline",
7763
8219
  options: [
7764
8220
  { label: "Inline", value: "inline" },
@@ -8036,7 +8492,8 @@ var emptyStatus = {
8036
8492
  duration: null,
8037
8493
  error: null,
8038
8494
  log: [],
8039
- resp: null
8495
+ resp: null,
8496
+ allowed: true
8040
8497
  };
8041
8498
  function BlockPreview(props) {
8042
8499
  const {
@@ -9321,13 +9778,15 @@ function SectionHeader({
9321
9778
  active,
9322
9779
  isDragging,
9323
9780
  id,
9324
- dragHandleProps
9781
+ dragHandleProps,
9782
+ hidden
9325
9783
  }) {
9326
9784
  return /* @__PURE__ */ jsxs(
9327
9785
  Group,
9328
9786
  {
9329
9787
  className: `cms-section-header${active || isDragging ? " active" : ""}`,
9330
9788
  position: "apart",
9789
+ bg: hidden ? "red.1" : "none",
9331
9790
  children: [
9332
9791
  /* @__PURE__ */ jsxs(Group, { className: "cms-section-header-editor", spacing: 0, children: [
9333
9792
  /* @__PURE__ */ jsxs(Code, { style: { backgroundColor: "transparent" }, children: [
@@ -9336,6 +9795,7 @@ function SectionHeader({
9336
9795
  ] }, "s1"),
9337
9796
  /* @__PURE__ */ jsx(ActionIcon, { ...dragHandleProps, children: /* @__PURE__ */ jsx(IconMenu, { size: 16 }) }, "b1")
9338
9797
  ] }),
9798
+ hidden && /* @__PURE__ */ jsx(Text, { size: "xs", fw: 600, color: "dark.3", children: "Section will be hidden on the frontend" }),
9339
9799
  /* @__PURE__ */ jsx(SectionMenu_default, { sectionId: id })
9340
9800
  ]
9341
9801
  }
@@ -9357,7 +9817,7 @@ function SectionEditor({
9357
9817
  const [sectionState, setSectionState2] = useSetState({});
9358
9818
  const blocks = useAppSelector((state) => state.records.entities.block);
9359
9819
  const blockSettings = getBlockSettings();
9360
- const { memberImageBg, optionsMenu } = section.settings;
9820
+ const { memberImageBg, optionsMenu, hidden } = section.settings;
9361
9821
  const [hoverBlock, setHoverBlock] = useState();
9362
9822
  const { inputs, consumers } = useMemo(() => {
9363
9823
  if (hoverBlock) {
@@ -9470,6 +9930,7 @@ function SectionEditor({
9470
9930
  active: isActive,
9471
9931
  id: section.id,
9472
9932
  isDragging,
9933
+ hidden,
9473
9934
  dragHandleProps
9474
9935
  }
9475
9936
  ),
@@ -9642,7 +10103,7 @@ init_ordering();
9642
10103
  init_store2();
9643
10104
  init_actions();
9644
10105
  function BuilderEditor(props) {
9645
- const { profilePrefix, id } = props;
10106
+ const { id } = props;
9646
10107
  const reportRef = useReportRef(id);
9647
10108
  return useMemo(() => {
9648
10109
  if (reportRef.isError) {
@@ -9656,14 +10117,13 @@ function BuilderEditor(props) {
9656
10117
  {
9657
10118
  report: reportRef.data,
9658
10119
  locale: props.locale,
9659
- isLoading: reportRef.isFetching,
9660
- profilePrefix
10120
+ isLoading: reportRef.isFetching
9661
10121
  }
9662
10122
  );
9663
10123
  }, [reportRef.status, reportRef.data?.sections]);
9664
10124
  }
9665
10125
  function InteractiveReport(props) {
9666
- const { report, isLoading, profilePrefix } = props;
10126
+ const { report, isLoading } = props;
9667
10127
  const theme = useMantineTheme();
9668
10128
  const dispatch = useAppDispatch();
9669
10129
  const resource = useContext(ResourceContext);
@@ -9741,7 +10201,7 @@ function InteractiveReport(props) {
9741
10201
  }
9742
10202
  ), [sectionOrder, activeSection, maybeActivate]);
9743
10203
  return /* @__PURE__ */ jsxs(Stack, { styles: { backgroundColor: theme.colors.gray[2] }, spacing: 0, children: [
9744
- /* @__PURE__ */ jsx(CMSHeader, { report, profilePrefix }),
10204
+ /* @__PURE__ */ jsx(CMSHeader, { report }),
9745
10205
  /* @__PURE__ */ jsxs(Alert, { icon: /* @__PURE__ */ jsx(IconFlag, {}), children: [
9746
10206
  "You are editing the ",
9747
10207
  /* @__PURE__ */ jsx(Code, { children: currentLocale.toUpperCase() }),
@@ -10109,7 +10569,7 @@ function FormatterForm({ formatterId, onEditEnd }) {
10109
10569
  }
10110
10570
  )
10111
10571
  ] }),
10112
- size: 145
10572
+ size: 165
10113
10573
  }
10114
10574
  )
10115
10575
  }
@@ -11051,7 +11511,7 @@ function MemberForm({ memberId, onEditEnd }) {
11051
11511
  }
11052
11512
  )
11053
11513
  ] }),
11054
- size: 145
11514
+ size: 165
11055
11515
  }
11056
11516
  )
11057
11517
  }
@@ -11103,6 +11563,11 @@ function MembersTable({ members, onClickEdit, onSort }) {
11103
11563
  title: "Variant",
11104
11564
  accessor: "variant.name"
11105
11565
  },
11566
+ {
11567
+ title: "Relevance",
11568
+ sortable: true,
11569
+ accessor: "zvalue"
11570
+ },
11106
11571
  {
11107
11572
  title: "Slug",
11108
11573
  accessor: "slug",
@@ -11214,8 +11679,8 @@ function MetadataEditor() {
11214
11679
  ...getParams,
11215
11680
  locale: "all",
11216
11681
  includes: true,
11217
- sort: internalSort ? internalSort.columnAccessor : "id",
11218
- direction: internalSort ? internalSort.direction : "asc"
11682
+ sort: internalSort ? internalSort.columnAccessor : "zvalue",
11683
+ direction: internalSort ? internalSort.direction : "desc"
11219
11684
  }
11220
11685
  }
11221
11686
  ).then((response) => response.data && response.data.data && response.data.data.results ? response.data.data.results : []);
@@ -11804,7 +12269,7 @@ function UserForm({ userId, onEditEnd, roles }) {
11804
12269
  }
11805
12270
  )
11806
12271
  ] }),
11807
- size: 145
12272
+ size: 165
11808
12273
  }
11809
12274
  )
11810
12275
  }
@@ -11994,7 +12459,7 @@ function BespokeManager(options) {
11994
12459
  title = "Bespoke CMS",
11995
12460
  pathSegment = "bespoke",
11996
12461
  locale = localeDefault4,
11997
- profilePrefix
12462
+ profilePrefix = "/profilePathManager"
11998
12463
  } = options;
11999
12464
  const notifications3 = {
12000
12465
  position: "bottom-center",
@@ -12006,17 +12471,17 @@ function BespokeManager(options) {
12006
12471
  FailureComponent: UnauthorizeView
12007
12472
  });
12008
12473
  function BespokeManagerPage() {
12009
- return /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment, children: [
12474
+ return /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment, profilePrefix, children: [
12010
12475
  /* @__PURE__ */ jsx(Head, { children: /* @__PURE__ */ jsx("title", { children: title }) }),
12011
12476
  /* @__PURE__ */ jsxs(MantineProvider, { inherit: false, children: [
12012
12477
  /* @__PURE__ */ jsx(Notifications, { ...notifications3 }),
12013
- /* @__PURE__ */ jsx(DialogProvider, { children: /* @__PURE__ */ jsx(BespokeManagerShell, { locale, profilePrefix }) })
12478
+ /* @__PURE__ */ jsx(DialogProvider, { children: /* @__PURE__ */ jsx(BespokeManagerShell, { locale }) })
12014
12479
  ] })
12015
12480
  ] });
12016
12481
  }
12017
12482
  }
12018
12483
  function BespokeManagerShell(props) {
12019
- const { locale, profilePrefix } = props;
12484
+ const { locale } = props;
12020
12485
  const [opened, { toggle: toggleOpened }] = useDisclosure(true);
12021
12486
  const { user, error, isLoading } = useUser();
12022
12487
  const location = useManagerLocation();
@@ -12142,7 +12607,7 @@ function BespokeManagerShell(props) {
12142
12607
  if (location.page === "reports") {
12143
12608
  if (location.params.length > 0) {
12144
12609
  const reportId = Number.parseInt(location.params[0]);
12145
- return /* @__PURE__ */ jsx(BuilderEditor, { id: reportId, locale, profilePrefix });
12610
+ return /* @__PURE__ */ jsx(BuilderEditor, { id: reportId, locale });
12146
12611
  }
12147
12612
  return /* @__PURE__ */ jsx(ReportPicker, {});
12148
12613
  }
@@ -12193,12 +12658,13 @@ init_ResourceProvider();
12193
12658
  function BespokeRenderer({
12194
12659
  pathSegmentsKey = "bespoke",
12195
12660
  bespokeStyles,
12196
- buildTime
12661
+ buildTime,
12662
+ profilePrefix = "/defaultPath"
12197
12663
  }) {
12198
12664
  const loading = useInitialState(pathSegmentsKey);
12199
12665
  if (loading)
12200
12666
  return /* @__PURE__ */ jsx(LoadingOverlay, { visible: true });
12201
- return /* @__PURE__ */ jsx(MantineProvider, { theme: { other: { bespokeStyles } }, inherit: true, children: /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment: "bespoke", children: [
12667
+ return /* @__PURE__ */ jsx(MantineProvider, { theme: { other: { bespokeStyles } }, inherit: true, children: /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment: "bespoke", profilePrefix, children: [
12202
12668
  /* @__PURE__ */ jsx(Report_default, {}),
12203
12669
  /* @__PURE__ */ jsx("small", { children: buildTime })
12204
12670
  ] }) });