@datawheel/bespoke 0.6.0-rc.8 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/index.js +839 -610
  2. package/dist/server.js +417 -420
  3. package/package.json +14 -16
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Group, Stack, Text, useMantineTheme, List, Modal, Button, Input, MantineProvider, Box, Navbar, ScrollArea, Avatar, AppShell, UnstyledButton, ThemeIcon, LoadingOverlay, Skeleton, Flex, packSx, Menu, Card, Center, Space, Badge, Title, Tabs, TextInput, Code, Loader, Divider, SegmentedControl, Select, ActionIcon, Textarea, Paper, Alert, Container, Grid, Tooltip, createStyles, MultiSelect, Anchor, Checkbox, MediaQuery, Affix, rem, Popover, Radio, Switch, Drawer, Overlay, NumberInput, Autocomplete, Notification, Image, Accordion, Header, px, FileInput, SimpleGrid, Burger, Collapse, CopyButton, HoverCard, Breadcrumbs, Col } from '@mantine/core';
1
+ import { Group, Stack, Text, useMantineTheme, List, Modal, Button, Input, MantineProvider, Box, Navbar, ScrollArea, Avatar, AppShell, UnstyledButton, ThemeIcon, LoadingOverlay, Skeleton, Flex, packSx, Menu, Card, Center, Space, Badge, Title, Tabs, TextInput, Code, NumberInput, Loader, Divider, SegmentedControl, Select, ActionIcon, Textarea, Paper, Alert, Container, Grid, Pagination, Tooltip, createStyles, MultiSelect, Anchor, Checkbox, MediaQuery, Affix, rem, Popover, Radio, Switch, Drawer, Overlay, Autocomplete, Notification, Image, Accordion, Header, px, FileInput, SimpleGrid, Burger, Collapse, CopyButton, HoverCard, Breadcrumbs, Col } from '@mantine/core';
2
2
  import React, { forwardRef, useState, useCallback, useRef, useEffect, createContext, useContext, useMemo, Fragment as Fragment$1, createElement, memo, useImperativeHandle } from 'react';
3
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
4
  import axios from 'axios';
@@ -20,8 +20,8 @@ import { createSlice, configureStore } from '@reduxjs/toolkit';
20
20
  import { HYDRATE, createWrapper } from 'next-redux-wrapper';
21
21
  import { Notifications, notifications } from '@mantine/notifications';
22
22
  import { useDispatch, useSelector } from 'react-redux';
23
+ import { useDebouncedValue, useClickOutside, useDisclosure, useSetState, useUncontrolled, useHotkeys, useListState, randomId, getHotkeyHandler, useMediaQuery, useMergedRef, useFullscreen } from '@mantine/hooks';
23
24
  import Router, { useRouter } from 'next/router';
24
- import { useClickOutside, useDisclosure, useDebouncedValue, useSetState, useUncontrolled, useHotkeys, useListState, randomId, getHotkeyHandler, useMediaQuery, useMergedRef, useFullscreen } from '@mantine/hooks';
25
25
  import { IconDice, IconBoxMultiple, IconEyeOff, IconChevronDown, IconBallpen, IconDatabase, IconMathFunction, IconUsers, IconLogout, IconHeading, IconApi, IconPercentage, IconChartBar, IconAlignLeft, IconSelector, IconPhoto, IconTable, IconUserCircle, IconEdit, IconServer, IconPencil, IconAlertCircle, IconCircleCheck, IconPlayerPlay, IconTrash, IconCircleX, IconPlus, IconFileAnalytics, IconHome, IconSearch, IconX, IconRefresh, IconDownload, IconCircleDashed, IconLanguage, IconSettingsFilled, IconEye, IconWorldUpload, IconBraces, IconClockHour2, IconAugmentedReality, IconGitMerge, IconGripHorizontal, IconChevronLeft, IconChevronRight, IconListCheck, IconPolaroid, IconCircleMinus, IconInfoCircle, IconGripVertical, IconCamera, IconShare, IconQuestionMark, IconCirclePlus, IconLogin, IconWorld, IconLock, IconCopy, IconBinaryTree, IconVariable, IconArrowRightCircle, IconPhotoFilled, IconFileUpload, IconIndentIncrease, IconCodeDots, IconUpload, IconCheck, IconCodePlus, IconLink, IconSparkles, IconClipboardCheck, IconClipboardCopy, IconExternalLink, IconFileTypeCsv, IconFileTypeJs, IconFileTypeXls, IconTemplate, IconCode, IconPalette, IconBold, IconItalic, IconUnderline, IconAlignCenter, IconAlignRight, IconAlignJustified, IconArrowBackUp, IconArrowForwardUp, IconLanguageOff, IconTriangleInvertedFilled, IconDeviceFloppy, IconSettings, IconMinimize, IconMaximize, IconGlobe, IconLinkOff } from '@tabler/icons-react';
26
26
  import Link from 'next/link';
27
27
  import parse2, { Element as Element$1, domToReact, Text as Text$1 } from 'html-react-parser';
@@ -37,7 +37,7 @@ import { Fragment as Fragment$2, Slice, DOMParser } from '@tiptap/pm/model';
37
37
  import { liftTarget, joinPoint, canSplit, ReplaceStep, ReplaceAroundStep, canJoin } from '@tiptap/pm/transform';
38
38
  import { createParagraphNear as createParagraphNear$1, deleteSelection as deleteSelection$1, exitCode as exitCode$1, joinUp as joinUp$1, joinDown as joinDown$1, joinBackward as joinBackward$1, joinForward as joinForward$1, joinTextblockBackward as joinTextblockBackward$1, joinTextblockForward as joinTextblockForward$1, lift as lift$1, liftEmptyBlock as liftEmptyBlock$1, newlineInCode as newlineInCode$1, selectNodeBackward as selectNodeBackward$1, selectNodeForward as selectNodeForward$1, selectParentNode as selectParentNode$1, selectTextblockEnd as selectTextblockEnd$1, selectTextblockStart as selectTextblockStart$1, setBlockType, wrapIn as wrapIn$1 } from '@tiptap/pm/commands';
39
39
  import { liftListItem as liftListItem$1, sinkListItem as sinkListItem$1, wrapInList as wrapInList$1 } from '@tiptap/pm/schema-list';
40
- import { EditorProvider, BubbleMenu, useCurrentEditor, ReactRenderer } from '@tiptap/react';
40
+ import { EditorProvider, useCurrentEditor, BubbleMenu, ReactRenderer } from '@tiptap/react';
41
41
  import Underline from '@tiptap/extension-underline';
42
42
  import StarterKit from '@tiptap/starter-kit';
43
43
  import Mention from '@tiptap/extension-mention';
@@ -51,6 +51,7 @@ import slugifyFn from 'slugify';
51
51
  import JSZip from 'jszip';
52
52
  import { saveAs } from 'file-saver';
53
53
  import { select } from 'd3-selection';
54
+ import { saveElement } from 'd3plus-export';
54
55
  import { FacebookShareButton, FacebookIcon, TwitterShareButton, TwitterIcon, TelegramShareButton, TelegramIcon, WhatsappShareButton, WhatsappIcon, LinkedinShareButton, LinkedinIcon, RedditShareButton, RedditIcon, EmailShareButton, EmailIcon } from 'react-share';
55
56
  import Head from 'next/head';
56
57
  import Editor, { useMonaco } from '@monaco-editor/react';
@@ -160,111 +161,10 @@ var init_Dialog = __esm({
160
161
  DialogContext = React.createContext(void 0);
161
162
  }
162
163
  });
163
- function ExploreFilters({ metadata, onFilter, initialReportId, initialVariantId, translations }) {
164
- const [showSelectors, setShowSelectors] = useState(false);
165
- const [selectors, setSelectors] = useState([]);
166
- const [filters, setFilters] = useState({ profile: void 0, variant: void 0 });
167
- const [selectedProfile, setSelectedProfile] = useState();
168
- const [selectedVariant, setSelectedVariant] = useState();
169
- const allMember = { id: void 0, name: translations["filters_all"] };
170
- const getVariantsCombinatory = (variantsArrays) => {
171
- const combinatory = variantsArrays.reduce((a2, b2) => a2.reduce((r2, v2) => r2.concat(b2.map((w2) => [].concat(v2, w2))), [])).map((combination) => {
172
- if (!Array.isArray(combination))
173
- return combination;
174
- return {
175
- id: combination.map((c2) => c2.id).join(","),
176
- name: combination.map((c2) => c2.name).join(" / ")
177
- };
178
- });
179
- return [allMember, ...combinatory];
180
- };
181
- const onClickProfile = (profile) => {
182
- if (profile !== selectedProfile) {
183
- setSelectedProfile(profile);
184
- setSelectedVariant(allMember);
185
- }
186
- };
187
- const onClickVariant = (variant) => {
188
- if (variant !== selectedVariant) {
189
- setSelectedVariant(variant);
190
- }
191
- };
192
- useEffect(() => {
193
- const newFilters = {};
194
- if (selectedProfile) {
195
- newFilters.profile = selectedProfile.id;
196
- }
197
- if (selectedVariant) {
198
- newFilters.variant = selectedVariant.id;
199
- }
200
- setFilters({ ...filters, ...newFilters });
201
- }, [selectedProfile, selectedVariant]);
202
- useEffect(() => {
203
- onFilter(filters);
204
- }, [filters]);
205
- useEffect(() => {
206
- if (metadata) {
207
- let worthShowSelectors = false;
208
- const selectorStructure = metadata.filter((profile) => profile.dimensions.length > 0).map((profile) => {
209
- const combinatory = getVariantsCombinatory(profile.dimensions.map((d2) => d2.variants));
210
- if (!worthShowSelectors && combinatory && combinatory.length > 2) {
211
- worthShowSelectors = true;
212
- }
213
- return {
214
- id: profile.id,
215
- name: profile.dimensions.map((d2) => d2.name).join(" / "),
216
- variants: combinatory
217
- };
218
- });
219
- setSelectors([allMember, ...selectorStructure]);
220
- setShowSelectors(worthShowSelectors ? true : selectorStructure.length > 1);
221
- if (initialReportId || initialVariantId) {
222
- if (initialReportId) {
223
- const initialReport = selectorStructure.find((ss) => ss.id === initialReportId);
224
- setSelectedProfile(initialReport);
225
- if (initialVariantId && initialReport) {
226
- setSelectedVariant(initialReport.variants.find((v2) => v2.id === initialVariantId));
227
- }
228
- }
229
- }
230
- }
231
- }, [metadata, initialReportId, initialVariantId]);
232
- return /* @__PURE__ */ jsxs(Fragment, { children: [
233
- showSelectors && /* @__PURE__ */ jsx(Group, { position: "center", className: "bespoke-explore-reports-selector", mb: "md", children: selectors.map((s2) => /* @__PURE__ */ jsx(
234
- Button,
235
- {
236
- "data-selected": s2.id === selectedProfile?.id ? "true" : "false",
237
- "data-report-name": s2.name,
238
- variant: s2.id === selectedProfile?.id ? "outline" : "subtle",
239
- onClick: () => onClickProfile(s2),
240
- children: translations?.dimension[s2.name] ?? s2.name
241
- },
242
- `p-${s2.id}`
243
- )) }),
244
- selectedProfile && selectedProfile.variants && selectedProfile.variants.length > 2 && /* @__PURE__ */ jsx(Group, { position: "center", style: { minHeight: "36px" }, className: "bespoke-explore-variant-selector", mb: "md", children: selectedProfile.variants.map((v2) => /* @__PURE__ */ jsx(
245
- Button,
246
- {
247
- "data-selected": v2.id === selectedVariant?.id ? "true" : "false",
248
- "data-variant-name": v2.name,
249
- variant: v2.id === selectedVariant?.id ? "outline" : "subtle",
250
- onClick: () => onClickVariant(v2),
251
- children: translations?.dimension[v2.name] ?? v2.name
252
- },
253
- `v-${v2.id}`
254
- )) })
255
- ] });
256
- }
257
- var ExploreFilters_default;
258
- var init_ExploreFilters = __esm({
259
- "frontend/components/explore/ExploreFilters.tsx"() {
260
- init_esm_shims();
261
- ExploreFilters_default = ExploreFilters;
262
- }
263
- });
264
164
 
265
165
  // api/http/lib.ts
266
- function http(axios11, config) {
267
- return axios11.request(config).then((response) => {
166
+ function http(axios10, config) {
167
+ return axios10.request(config).then((response) => {
268
168
  const { status, data } = response;
269
169
  return "error" in data ? { ok: false, status, error: data.error } : { ok: true, status, data: data.data };
270
170
  }, (err) => {
@@ -275,26 +175,26 @@ function http(axios11, config) {
275
175
  return { ok: false, status: 500, error: err.message };
276
176
  });
277
177
  }
278
- function httpGET(axios11, request, transformParams) {
178
+ function httpGET(axios10, request, transformParams) {
279
179
  const config = typeof request === "string" ? { url: request } : request;
280
- return (params) => http(axios11, {
180
+ return (params) => http(axios10, {
281
181
  ...config,
282
182
  method: "GET",
283
183
  params: transformParams ? transformParams(params) : params
284
184
  });
285
185
  }
286
- function httpPOST(axios11, request, transformPayload) {
186
+ function httpPOST(axios10, request, transformPayload) {
287
187
  const config = typeof request === "string" ? { url: request } : request;
288
- return (payload) => http(axios11, {
188
+ return (payload) => http(axios10, {
289
189
  ...config,
290
190
  method: "POST",
291
191
  data: transformPayload ? transformPayload(payload) : payload
292
192
  });
293
193
  }
294
- function httpDELETE(axios11, request, transformPayload) {
194
+ function httpDELETE(axios10, request, transformPayload) {
295
195
  const config = typeof request === "string" ? { url: request } : request;
296
196
  return (payload) => {
297
- return http(axios11, {
197
+ return http(axios10, {
298
198
  ...config,
299
199
  method: "DELETE",
300
200
  params: transformPayload ? transformPayload(payload) : payload
@@ -308,8 +208,8 @@ var init_lib = __esm({
308
208
  });
309
209
 
310
210
  // api/http/image/imageSave.ts
311
- function httpImageSaveFactory(axios11, provider) {
312
- return (params) => http(axios11, {
211
+ function httpImageSaveFactory(axios10, provider) {
212
+ return (params) => http(axios10, {
313
213
  method: "POST",
314
214
  url: `images/save/${provider}`,
315
215
  params: { prompt: params.prompt, provider }
@@ -323,8 +223,8 @@ var init_imageSave = __esm({
323
223
  });
324
224
 
325
225
  // api/http/image/imageSearch.ts
326
- function httpImageSearchFactory(axios11, provider) {
327
- return (params) => http(axios11, {
226
+ function httpImageSearchFactory(axios10, provider) {
227
+ return (params) => http(axios10, {
328
228
  method: "GET",
329
229
  url: `images/search/${provider}`,
330
230
  params: { prompt: params.prompt, page: params.page, provider }
@@ -338,8 +238,8 @@ var init_imageSearch = __esm({
338
238
  });
339
239
 
340
240
  // api/http/icon/listIcons.ts
341
- function httpListIconsFactory(axios11, provider) {
342
- return () => http(axios11, {
241
+ function httpListIconsFactory(axios10, provider) {
242
+ return () => http(axios10, {
343
243
  method: "GET",
344
244
  url: `list/icons/${provider}`,
345
245
  params: { provider }
@@ -353,8 +253,8 @@ var init_listIcons = __esm({
353
253
  });
354
254
 
355
255
  // api/http/icon/readIcon.ts
356
- function httpReadIconFactory(axios11, provider) {
357
- return (params) => http(axios11, {
256
+ function httpReadIconFactory(axios10, provider) {
257
+ return (params) => http(axios10, {
358
258
  method: "GET",
359
259
  url: `read/icons/${provider}/icon.svg`,
360
260
  params: { name: params.name }
@@ -367,65 +267,65 @@ var init_readIcon = __esm({
367
267
  }
368
268
  });
369
269
  function apiFactory(baseURL) {
370
- const axios11 = axios.create({ baseURL });
270
+ const axios10 = axios.create({ baseURL });
371
271
  return {
372
- createBulkBlock: httpPOST(axios11, "create/bulk/block"),
373
- createBlock: httpPOST(axios11, "create/block"),
374
- createDimension: httpPOST(axios11, "create/dimension"),
375
- createFormatter: httpPOST(axios11, "create/formatter"),
376
- createReport: httpPOST(axios11, "create/report"),
377
- createSection: httpPOST(axios11, "create/section"),
378
- createVariant: httpPOST(axios11, "create/variant"),
379
- deleteBlock: httpDELETE(axios11, "delete/block", transformDeletePayload),
380
- deleteDimension: httpDELETE(axios11, "delete/dimension", transformDeletePayload),
381
- deleteFormatter: httpDELETE(axios11, "delete/formatter", transformDeletePayload),
382
- deleteReport: httpDELETE(axios11, "delete/report", transformDeletePayload),
383
- deleteSection: httpDELETE(axios11, "delete/section", transformDeletePayload),
384
- deleteVariant: httpDELETE(axios11, "delete/variant", transformDeletePayload),
385
- readBlock: httpGET(axios11, "read/block"),
386
- readDimension: httpGET(axios11, "read/dimension"),
387
- readFormatter: httpGET(axios11, "read/formatter"),
388
- readReport: httpGET(axios11, "read/report"),
389
- readSection: httpGET(axios11, "read/section"),
390
- readVariant: httpGET(axios11, "read/variant"),
391
- updateBulkBlock: httpPOST(axios11, "update/bulk/block"),
392
- updateBlock: httpPOST(axios11, "update/block"),
393
- updateDimension: httpPOST(axios11, "update/dimension"),
394
- updateFormatter: httpPOST(axios11, "update/formatter"),
395
- updateReport: httpPOST(axios11, "update/report"),
396
- updateSection: httpPOST(axios11, "update/section"),
397
- updateVariant: httpPOST(axios11, "update/variant"),
398
- searchReport: httpGET(axios11, "search/reports"),
399
- validateVariantSlug: httpGET(axios11, "validate/variant"),
400
- readMember: httpGET(axios11, "read/members", transformReadMembers),
401
- readMemberImage: httpGET(axios11, {
272
+ createBulkBlock: httpPOST(axios10, "create/bulk/block"),
273
+ createBlock: httpPOST(axios10, "create/block"),
274
+ createDimension: httpPOST(axios10, "create/dimension"),
275
+ createFormatter: httpPOST(axios10, "create/formatter"),
276
+ createReport: httpPOST(axios10, "create/report"),
277
+ createSection: httpPOST(axios10, "create/section"),
278
+ createVariant: httpPOST(axios10, "create/variant"),
279
+ deleteBlock: httpDELETE(axios10, "delete/block", transformDeletePayload),
280
+ deleteDimension: httpDELETE(axios10, "delete/dimension", transformDeletePayload),
281
+ deleteFormatter: httpDELETE(axios10, "delete/formatter", transformDeletePayload),
282
+ deleteReport: httpDELETE(axios10, "delete/report", transformDeletePayload),
283
+ deleteSection: httpDELETE(axios10, "delete/section", transformDeletePayload),
284
+ deleteVariant: httpDELETE(axios10, "delete/variant", transformDeletePayload),
285
+ readBlock: httpGET(axios10, "read/block"),
286
+ readDimension: httpGET(axios10, "read/dimension"),
287
+ readFormatter: httpGET(axios10, "read/formatter"),
288
+ readReport: httpGET(axios10, "read/report"),
289
+ readSection: httpGET(axios10, "read/section"),
290
+ readVariant: httpGET(axios10, "read/variant"),
291
+ updateBulkBlock: httpPOST(axios10, "update/bulk/block"),
292
+ updateBlock: httpPOST(axios10, "update/block"),
293
+ updateDimension: httpPOST(axios10, "update/dimension"),
294
+ updateFormatter: httpPOST(axios10, "update/formatter"),
295
+ updateReport: httpPOST(axios10, "update/report"),
296
+ updateSection: httpPOST(axios10, "update/section"),
297
+ updateVariant: httpPOST(axios10, "update/variant"),
298
+ searchReport: httpGET(axios10, "search/reports"),
299
+ validateVariantSlug: httpGET(axios10, "validate/variant"),
300
+ readMember: httpGET(axios10, "read/members", transformReadMembers),
301
+ readMemberImage: httpGET(axios10, {
402
302
  url: "member/image",
403
303
  responseType: "blob"
404
304
  }),
405
- searchMember: httpGET(axios11, "search/members"),
406
- updateMember: httpGET(axios11, "update/members"),
407
- imageLocalSearch: httpImageSearchFactory(axios11, "local"),
408
- imageLocalSave: httpImageSaveFactory(axios11, "local"),
409
- imageFlickrSearch: httpImageSearchFactory(axios11, "flickr"),
410
- imageFlickrSave: httpImageSaveFactory(axios11, "flickr"),
411
- imageUnsplashSearch: httpImageSearchFactory(axios11, "unsplash"),
412
- imageUnsplashSave: httpImageSaveFactory(axios11, "unsplash"),
413
- imageUploadSave: httpImageSaveFactory(axios11, "upload"),
414
- imageAdobeSearch: httpImageSearchFactory(axios11, "adobe"),
415
- imageAdobeSave: httpImageSaveFactory(axios11, "adobe"),
416
- readMetadata: httpGET(axios11, "read/metadata"),
417
- regenerateSearch: httpPOST(axios11, "search/regenerate"),
418
- urlProxy: httpGET(axios11, "url/proxy"),
419
- searchRole: httpGET(axios11, "auth/search/roles"),
420
- searchUser: httpGET(axios11, "auth/search/users"),
421
- readUser: httpGET(axios11, "auth/read/user"),
422
- updateUser: httpPOST(axios11, "auth/update/user"),
423
- updateMyData: httpPOST(axios11, "auth/update/me"),
424
- revalidateReport: httpGET(axios11, "revalidate/report"),
425
- revalidateUrl: httpGET(axios11, "revalidate/url"),
426
- readPrivateBlocks: httpPOST(axios11, "read/blocks/private"),
427
- listTablerIcons: httpListIconsFactory(axios11, "tabler"),
428
- readTablerIcon: httpReadIconFactory(axios11, "tabler")
305
+ searchMember: httpGET(axios10, "search/members"),
306
+ updateMember: httpGET(axios10, "update/members"),
307
+ imageLocalSearch: httpImageSearchFactory(axios10, "local"),
308
+ imageLocalSave: httpImageSaveFactory(axios10, "local"),
309
+ imageFlickrSearch: httpImageSearchFactory(axios10, "flickr"),
310
+ imageFlickrSave: httpImageSaveFactory(axios10, "flickr"),
311
+ imageUnsplashSearch: httpImageSearchFactory(axios10, "unsplash"),
312
+ imageUnsplashSave: httpImageSaveFactory(axios10, "unsplash"),
313
+ imageUploadSave: httpImageSaveFactory(axios10, "upload"),
314
+ imageAdobeSearch: httpImageSearchFactory(axios10, "adobe"),
315
+ imageAdobeSave: httpImageSaveFactory(axios10, "adobe"),
316
+ readMetadata: httpGET(axios10, "read/metadata"),
317
+ regenerateSearch: httpPOST(axios10, "search/regenerate"),
318
+ urlProxy: httpGET(axios10, "url/proxy"),
319
+ searchRole: httpGET(axios10, "auth/search/roles"),
320
+ searchUser: httpGET(axios10, "auth/search/users"),
321
+ readUser: httpGET(axios10, "auth/read/user"),
322
+ updateUser: httpPOST(axios10, "auth/update/user"),
323
+ updateMyData: httpPOST(axios10, "auth/update/me"),
324
+ revalidateReport: httpGET(axios10, "revalidate/report"),
325
+ revalidateUrl: httpGET(axios10, "revalidate/url"),
326
+ readPrivateBlocks: httpPOST(axios10, "read/blocks/private"),
327
+ listTablerIcons: httpListIconsFactory(axios10, "tabler"),
328
+ readTablerIcon: httpReadIconFactory(axios10, "tabler")
429
329
  };
430
330
  }
431
331
  var transformDeletePayload, transformReadMembers;
@@ -2569,26 +2469,6 @@ var init_recordsSlice = __esm({
2569
2469
  }
2570
2470
  }
2571
2471
  };
2572
- },
2573
- normalizeSection: (state, action) => {
2574
- const sectionId = action.payload.section;
2575
- const section = state.entities.section[sectionId];
2576
- return {
2577
- ...state,
2578
- entities: {
2579
- ...state.entities,
2580
- section: {
2581
- // ...state.entities.section,
2582
- [sectionId]: {
2583
- ...section,
2584
- settings: {
2585
- ...section.settings,
2586
- width: "full"
2587
- }
2588
- }
2589
- }
2590
- }
2591
- };
2592
2472
  }
2593
2473
  },
2594
2474
  extraReducers: {
@@ -3520,7 +3400,6 @@ __export(actions_exports, {
3520
3400
  createEntity: () => createEntity,
3521
3401
  deleteEntity: () => deleteEntity,
3522
3402
  deleteQueryParam: () => deleteQueryParam,
3523
- normalizeSectionLayout: () => normalizeSectionLayout,
3524
3403
  readEntity: () => readEntity,
3525
3404
  readMember: () => readMember,
3526
3405
  readMetadata: () => readMetadata,
@@ -3717,12 +3596,6 @@ function removeBlocksFromState(privateBlockIds) {
3717
3596
  await dispatch(removeBlocks(privateBlockIds));
3718
3597
  };
3719
3598
  }
3720
- function normalizeSectionLayout(sectionId) {
3721
- const { normalizeSection } = recordsSlice.actions;
3722
- return async (dispatch) => {
3723
- await dispatch(normalizeSection(sectionId));
3724
- };
3725
- }
3726
3599
  function addBlockToState(newBlocks) {
3727
3600
  const { addBlocks } = recordsSlice.actions;
3728
3601
  return async (dispatch) => {
@@ -4129,6 +4002,321 @@ var init_store2 = __esm({
4129
4002
  init_withFetcher();
4130
4003
  }
4131
4004
  });
4005
+ function ExploreProvider({ children, explorePageSize }) {
4006
+ const pageSize = explorePageSize || 10;
4007
+ const defaultFilters = {
4008
+ // initial reportIds should go here to avoid multiple unnecesary requests
4009
+ profile: void 0,
4010
+ variant: void 0
4011
+ };
4012
+ const [metadata, setMetadata] = useState([]);
4013
+ const [loadingItems, setLoadingItems] = useState(false);
4014
+ const [loadingMetadata, setLoadingMetadata] = useState(false);
4015
+ const [resultCount, setResultCount] = useState({});
4016
+ const [totalCount, setTotalCount] = useState({});
4017
+ const [activePage, setActivePage] = useState(1);
4018
+ const [filters, setFilters] = useState(defaultFilters);
4019
+ const [query, setQuery] = useState("");
4020
+ const [debouncedQuery] = useDebouncedValue(query, 500);
4021
+ const [results, setResults] = useState([]);
4022
+ const [translations, setTranslations] = useState(DEFAULT_TRANSLATIONS);
4023
+ const [initialized, setInitialized] = useState(false);
4024
+ const dispatch = useAppDispatch();
4025
+ const { locale } = useRouter();
4026
+ const fetchMetadata = async () => {
4027
+ try {
4028
+ setLoadingMetadata(true);
4029
+ dispatch(actions_exports.readMetadata({})).then((resp) => {
4030
+ const metadataCount = resp.data.reduce((acc, report) => {
4031
+ if (report.dimensions) {
4032
+ report.dimensions.forEach((dimension) => {
4033
+ if (dimension.variants) {
4034
+ dimension.variants.forEach((variant) => {
4035
+ acc[variant.id] = variant.members_count || 0;
4036
+ });
4037
+ }
4038
+ });
4039
+ }
4040
+ return acc;
4041
+ }, {});
4042
+ setMetadata(resp.data);
4043
+ setLoadingMetadata(false);
4044
+ setResultCount(metadataCount);
4045
+ setTotalCount(metadataCount);
4046
+ setInitialized(true);
4047
+ }, (err) => {
4048
+ console.error(err);
4049
+ });
4050
+ } catch (error) {
4051
+ console.error("Error fetching metadata:", error);
4052
+ setMetadata([]);
4053
+ setLoadingMetadata(false);
4054
+ setResultCount({});
4055
+ setTotalCount({});
4056
+ }
4057
+ };
4058
+ const setResultCountInternal = (totalPerVariant) => {
4059
+ if (totalPerVariant) {
4060
+ setResultCount(totalPerVariant);
4061
+ } else {
4062
+ setResultCount(totalCount);
4063
+ }
4064
+ };
4065
+ const initExplore = async (initialReportId, initialVariantId) => {
4066
+ if (!initialized && metadata.length === 0) {
4067
+ await fetchMetadata();
4068
+ }
4069
+ setFilters({
4070
+ profile: initialReportId,
4071
+ variant: initialVariantId
4072
+ });
4073
+ };
4074
+ useEffect(() => {
4075
+ let cancelled = false;
4076
+ if (initialized) {
4077
+ setLoadingItems(true);
4078
+ setActivePage(1);
4079
+ doQuery(cancelled, 0);
4080
+ }
4081
+ return () => {
4082
+ cancelled = false;
4083
+ };
4084
+ }, [debouncedQuery, filters, initialized]);
4085
+ useEffect(() => {
4086
+ if (initialized) {
4087
+ setLoadingItems(true);
4088
+ const newOffset = (activePage - 1) * pageSize;
4089
+ doQuery(false, newOffset);
4090
+ }
4091
+ }, [activePage]);
4092
+ const doQuery = async (cancelled, newOffset) => {
4093
+ const filterProfile = filters.profile && !Number.isNaN(filters.profile) ? [filters.profile] : [];
4094
+ const filterVariant = filters.variant && !Number.isNaN(filters.variant) ? [filters.variant] : [];
4095
+ const params = {
4096
+ query: debouncedQuery,
4097
+ format: "profiles",
4098
+ locale,
4099
+ limit: pageSize,
4100
+ offset: newOffset,
4101
+ visible: true,
4102
+ includes: true,
4103
+ noImage: false,
4104
+ variant: filterVariant,
4105
+ dimension: [],
4106
+ report: filterProfile,
4107
+ all: false
4108
+ };
4109
+ dispatch(actions_exports.reportSearch(params)).then((resp) => {
4110
+ if (resp && resp.results && !cancelled) {
4111
+ const mergedResults = resp.results;
4112
+ setResults(mergedResults);
4113
+ setResultCount(query === "" ? false : resp.meta.variantCount);
4114
+ }
4115
+ setLoadingItems(false);
4116
+ }).catch((e) => {
4117
+ console.error(e);
4118
+ setLoadingItems(false);
4119
+ });
4120
+ };
4121
+ const counts = resultCount || totalCount;
4122
+ const allMember = { id: void 0, name: translations["filters_all"] || "ALL" };
4123
+ const getVariantsCombinatory = (variantsArrays) => {
4124
+ const combinatory = variantsArrays.reduce((a2, b2) => a2.reduce((r2, v2) => r2.concat(b2.map((w2) => [].concat(v2, w2))), [])).map((combination) => {
4125
+ let final;
4126
+ if (!Array.isArray(combination)) {
4127
+ combination.members_count = counts[combination.id] || 0;
4128
+ final = {
4129
+ ...combination,
4130
+ members_count: counts[combination.id] || 0
4131
+ };
4132
+ } else {
4133
+ final = {
4134
+ id: combination.map((c2) => c2.id).join(","),
4135
+ name: combination.map((c2) => c2.name).join(" / "),
4136
+ members_count: combination.reduce((t2, q2) => t2 * (counts[q2.id] || 1), 0)
4137
+ };
4138
+ }
4139
+ return final;
4140
+ });
4141
+ const allTotal = combinatory.reduce((t2, q2) => t2 + (q2.members_count || 0), 0);
4142
+ return [
4143
+ { ...allMember, members_count: allTotal },
4144
+ ...combinatory
4145
+ ];
4146
+ };
4147
+ const showSelectors = metadata.length > 1;
4148
+ const selectorsObj = useMemo(() => {
4149
+ let temp = [];
4150
+ if (!loadingMetadata && metadata.length > 0 && counts) {
4151
+ const selectors = metadata.filter((profile) => profile.dimensions.length > 0).map((profile) => {
4152
+ let worthShowSelectors = false;
4153
+ const combinatory = getVariantsCombinatory(profile.dimensions.map((d2) => d2.variants));
4154
+ if (combinatory && combinatory.length > 2) {
4155
+ worthShowSelectors = true;
4156
+ }
4157
+ return {
4158
+ id: profile.id,
4159
+ name: profile.dimensions.map((d2) => d2.name).join(" / "),
4160
+ variants: combinatory,
4161
+ members_count: combinatory.filter((v2) => v2.id).reduce((t2, q2) => t2 + (q2.members_count || 0), 0),
4162
+ show: worthShowSelectors
4163
+ };
4164
+ });
4165
+ temp = [
4166
+ { ...allMember, members_count: selectors.reduce((t2, q2) => t2 + (q2.members_count || 0), 0) },
4167
+ ...selectors
4168
+ ];
4169
+ }
4170
+ return temp;
4171
+ }, [loadingMetadata, counts, metadata, allMember]);
4172
+ const currentPageTotal = useMemo(() => {
4173
+ let selector;
4174
+ if (selectorsObj) {
4175
+ if (!filters.profile) {
4176
+ selector = selectorsObj.find((p2) => !p2.id);
4177
+ } else if (filters.profile) {
4178
+ selector = selectorsObj.find((p2) => p2.id === filters.profile);
4179
+ if (selector && filters.variant && selector.variants) {
4180
+ selector = selector.variants.find((p2) => p2.id === filters.variant);
4181
+ }
4182
+ }
4183
+ }
4184
+ return selector ? selector.members_count : pageSize;
4185
+ }, [filters, selectorsObj]);
4186
+ const state = {
4187
+ metadata,
4188
+ loadingMetadata,
4189
+ setLoadingMetadata,
4190
+ loadingItems,
4191
+ setLoadingItems,
4192
+ resultCount,
4193
+ totalCount,
4194
+ setResultCount: setResultCountInternal,
4195
+ activePage,
4196
+ setActivePage,
4197
+ pageSize,
4198
+ filters,
4199
+ setFilters,
4200
+ doQuery,
4201
+ query,
4202
+ setQuery,
4203
+ debouncedQuery,
4204
+ results,
4205
+ currentPageTotal,
4206
+ selectorStructure: selectorsObj,
4207
+ translations,
4208
+ setTranslations: (t2) => {
4209
+ setTranslations({ ...DEFAULT_TRANSLATIONS, ...t2 });
4210
+ },
4211
+ showSelectors,
4212
+ initExplore
4213
+ };
4214
+ return /* @__PURE__ */ jsx(ExploreContext.Provider, { value: state, children });
4215
+ }
4216
+ var DEFAULT_TRANSLATIONS, ExploreContext, useExplore;
4217
+ var init_ExploreProvider = __esm({
4218
+ "frontend/components/explore/ExploreProvider.tsx"() {
4219
+ init_esm_shims();
4220
+ init_store2();
4221
+ DEFAULT_TRANSLATIONS = {
4222
+ "try_another": "Try another search or filter.",
4223
+ "search": "Search",
4224
+ "filters_all": "All",
4225
+ "no_results": "No Results",
4226
+ "load_more": "Load more",
4227
+ report: {},
4228
+ dimension: {},
4229
+ variant: {}
4230
+ };
4231
+ ExploreContext = createContext({
4232
+ metadata: [],
4233
+ loadingItems: false,
4234
+ setLoadingItems: () => null,
4235
+ loadingMetadata: false,
4236
+ setLoadingMetadata: () => null,
4237
+ resultCount: {},
4238
+ totalCount: {},
4239
+ setResultCount: () => null,
4240
+ activePage: 1,
4241
+ setActivePage: () => null,
4242
+ pageSize: 10,
4243
+ results: [],
4244
+ filters: {},
4245
+ doQuery: () => null,
4246
+ setFilters: () => null,
4247
+ query: "",
4248
+ setQuery: () => null,
4249
+ debouncedQuery: "",
4250
+ currentPageTotal: 10,
4251
+ selectorStructure: [],
4252
+ translations: DEFAULT_TRANSLATIONS,
4253
+ setTranslations: () => null,
4254
+ showSelectors: true,
4255
+ initExplore: (p2, v2) => null
4256
+ });
4257
+ useExplore = () => useContext(ExploreContext);
4258
+ }
4259
+ });
4260
+ function ExploreFilters({ translations }) {
4261
+ const { loadingItems, setFilters, selectorStructure, filters, showSelectors } = useExplore();
4262
+ const onClickProfile = (profileId) => {
4263
+ if (profileId !== filters.profile) {
4264
+ setFilters({
4265
+ profile: profileId,
4266
+ variant: void 0
4267
+ });
4268
+ }
4269
+ };
4270
+ const onClickVariant = (variantId) => {
4271
+ if (variantId !== filters.variant) {
4272
+ setFilters({
4273
+ ...filters,
4274
+ variant: variantId
4275
+ });
4276
+ }
4277
+ };
4278
+ const selectedProfile = selectorStructure.length === 2 ? selectorStructure[1].id : filters.profile;
4279
+ const selectedProfileObj = selectedProfile ? selectorStructure.find((p2) => p2.id === selectedProfile) : void 0;
4280
+ const selectedVariantObj = selectedProfileObj && selectedProfileObj.variants && filters.variant ? selectedProfileObj.variants.find((p2) => p2.id === filters.variant) : void 0;
4281
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
4282
+ showSelectors && /* @__PURE__ */ jsx(Group, { position: "center", className: "bespoke-explore-reports-selector", mb: "md", children: selectorStructure.map((s2) => /* @__PURE__ */ jsxs(
4283
+ Button,
4284
+ {
4285
+ "data-selected": s2.id === selectedProfileObj?.id ? "true" : "false",
4286
+ "data-report-name": s2.name,
4287
+ variant: s2.id === selectedProfileObj?.id ? "outline" : "subtle",
4288
+ onClick: () => onClickProfile(s2.id),
4289
+ children: [
4290
+ translations?.dimension[s2.name] ?? s2.name,
4291
+ !loadingItems && /* @__PURE__ */ jsx(Text, { span: true, size: "xs", ml: "0.2rem", children: `(${s2.members_count})` })
4292
+ ]
4293
+ },
4294
+ `p-${s2.id}`
4295
+ )) }),
4296
+ selectedProfileObj && selectedProfileObj.variants && selectedProfileObj.variants.length > 2 && /* @__PURE__ */ jsx(Group, { position: "center", style: { minHeight: "36px" }, className: "bespoke-explore-variant-selector", mb: "md", children: selectedProfileObj.variants.map((v2) => /* @__PURE__ */ jsxs(
4297
+ Button,
4298
+ {
4299
+ "data-selected": v2.id === selectedVariantObj?.id ? "true" : "false",
4300
+ "data-variant-name": v2.name,
4301
+ variant: v2.id === selectedVariantObj?.id ? "outline" : "subtle",
4302
+ onClick: () => onClickVariant(v2.id),
4303
+ children: [
4304
+ translations?.dimension[v2.name] ?? v2.name,
4305
+ !loadingItems && /* @__PURE__ */ jsx(Text, { span: true, size: "xs", ml: "0.2rem", children: `(${v2.members_count})` })
4306
+ ]
4307
+ },
4308
+ `v-${v2.id}`
4309
+ )) })
4310
+ ] });
4311
+ }
4312
+ var ExploreFilters_default;
4313
+ var init_ExploreFilters = __esm({
4314
+ "frontend/components/explore/ExploreFilters.tsx"() {
4315
+ init_esm_shims();
4316
+ init_ExploreProvider();
4317
+ ExploreFilters_default = ExploreFilters;
4318
+ }
4319
+ });
4132
4320
  function useBespokeStyles() {
4133
4321
  const theme = useMantineTheme();
4134
4322
  return theme.other.bespokeStyles ?? {};
@@ -4215,11 +4403,16 @@ var init_ExploreTile = __esm({
4215
4403
  ExploreTile_default = ExploreTile;
4216
4404
  }
4217
4405
  });
4218
- function ExploreResults({ results = [], profilePrefix, onSelect = () => void 0, reportTile }) {
4406
+ function ExploreResults({
4407
+ profilePrefix,
4408
+ onSelect = () => void 0,
4409
+ reportTile
4410
+ }) {
4219
4411
  const [scrollSize, setScrollSize] = useState(500);
4220
4412
  const scrollAreaRef = useRef(null);
4413
+ const { results } = useExplore();
4221
4414
  const offset2 = scrollAreaRef.current?.offsetTop || 0;
4222
- const gap = 30;
4415
+ const gap = 50;
4223
4416
  useEffect(() => {
4224
4417
  const { innerHeight } = window;
4225
4418
  setScrollSize(innerHeight - offset2 - gap);
@@ -4242,80 +4435,74 @@ var init_ExploreResults = __esm({
4242
4435
  "frontend/components/explore/ExploreResults.tsx"() {
4243
4436
  init_esm_shims();
4244
4437
  init_ExploreTile();
4438
+ init_ExploreProvider();
4245
4439
  ExploreResults_default = ExploreResults;
4246
4440
  }
4247
4441
  });
4442
+ function ExplorePagination() {
4443
+ const {
4444
+ activePage,
4445
+ setActivePage,
4446
+ pageSize,
4447
+ currentPageTotal
4448
+ } = useExplore();
4449
+ const onChangePage = (page) => {
4450
+ setActivePage(page);
4451
+ };
4452
+ return /* @__PURE__ */ jsx(Group, { position: "center", children: /* @__PURE__ */ jsx(
4453
+ Pagination,
4454
+ {
4455
+ value: activePage,
4456
+ onChange: onChangePage,
4457
+ total: Math.ceil(currentPageTotal / pageSize),
4458
+ size: "sm",
4459
+ py: "xs"
4460
+ }
4461
+ ) });
4462
+ }
4463
+ var ExplorePagination_default;
4464
+ var init_ExplorePagination = __esm({
4465
+ "frontend/components/explore/ExplorePagination.tsx"() {
4466
+ init_esm_shims();
4467
+ init_ExploreProvider();
4468
+ ExplorePagination_default = ExplorePagination;
4469
+ }
4470
+ });
4248
4471
  function BespokeExplore({
4249
- locale,
4250
4472
  profilePrefix,
4251
4473
  initialReportId,
4252
4474
  initialVariantId,
4253
- translations = DEFAULT_TRANSLATIONS,
4475
+ translations,
4254
4476
  onSelect,
4255
4477
  reportTile
4256
4478
  }) {
4257
- const dispatch = useAppDispatch();
4258
- const defaultFilters = {
4259
- // initial reportIds should go here to avoid multiple unnecesary requests
4260
- profile: void 0,
4261
- variant: void 0
4262
- };
4263
- const [query, setQuery] = useState("");
4264
- const [debouncedQuery] = useDebouncedValue(query, 500);
4265
- const [results, setResults] = useState([]);
4266
- const [loading, setLoading] = useState(false);
4267
- const [filters, setFilters] = useState(defaultFilters);
4268
- const [metadata, setMetadata] = useState();
4269
4479
  const inputRef = useRef();
4480
+ const {
4481
+ query,
4482
+ setQuery,
4483
+ results,
4484
+ loadingItems,
4485
+ loadingMetadata,
4486
+ translations: exploreTranslations,
4487
+ setTranslations,
4488
+ initExplore
4489
+ } = useExplore();
4270
4490
  useEffect(() => {
4271
- setLoading(true);
4272
- dispatch(actions_exports.readMetadata({})).then((resp) => {
4273
- setMetadata(resp.data);
4274
- }, (err) => {
4275
- console.error(err);
4276
- });
4491
+ initExplore(initialReportId, initialVariantId);
4277
4492
  }, []);
4278
4493
  useEffect(() => {
4279
- let cancelled = false;
4280
- if (metadata) {
4281
- setLoading(true);
4282
- const filterProfile = filters.profile && !Number.isNaN(filters.profile) ? filters.profile : [];
4283
- const filterVariant = filters.variant && !Number.isNaN(filters.variant) ? filters.variant : [];
4284
- const params = {
4285
- query: debouncedQuery,
4286
- format: "profiles",
4287
- locale,
4288
- limit: 25,
4289
- visible: true,
4290
- includes: true,
4291
- noImage: false,
4292
- variant: filterVariant,
4293
- dimension: [],
4294
- report: filterProfile,
4295
- all: false
4296
- };
4297
- dispatch(actions_exports.reportSearch(params)).then((resp) => {
4298
- if (resp && resp.results && !cancelled) {
4299
- setResults(resp.results);
4300
- }
4301
- setLoading(false);
4302
- inputRef.current?.focus();
4303
- }).catch((e) => {
4304
- console.error(e);
4305
- setLoading(false);
4306
- });
4494
+ if (!loadingItems) {
4495
+ inputRef.current?.focus();
4307
4496
  }
4308
- return () => {
4309
- cancelled = false;
4310
- };
4311
- }, [debouncedQuery, filters, metadata]);
4312
- const onFilterChange = (newFilters) => {
4313
- setFilters(newFilters);
4314
- };
4497
+ }, [loadingItems]);
4498
+ useEffect(() => {
4499
+ if (translations) {
4500
+ setTranslations(translations);
4501
+ }
4502
+ }, [translations]);
4315
4503
  const onClearInput = () => {
4316
4504
  setQuery("");
4317
4505
  };
4318
- const exploreTranslations = { ...DEFAULT_TRANSLATIONS, ...translations };
4319
4506
  return /* @__PURE__ */ jsxs(Container, { fluid: true, pt: "1em", children: [
4320
4507
  /* @__PURE__ */ jsx(
4321
4508
  TextInput,
@@ -4324,7 +4511,7 @@ function BespokeExplore({
4324
4511
  mb: "md",
4325
4512
  size: "xl",
4326
4513
  onChange: (e) => setQuery(e.target.value),
4327
- readOnly: loading,
4514
+ readOnly: loadingMetadata || loadingItems,
4328
4515
  icon: /* @__PURE__ */ jsx(IconSearch, { size: 24 }),
4329
4516
  value: query,
4330
4517
  rightSectionWidth: 100,
@@ -4335,7 +4522,7 @@ function BespokeExplore({
4335
4522
  }
4336
4523
  },
4337
4524
  rightSection: /* @__PURE__ */ jsxs(Group, { align: "center", children: [
4338
- loading && /* @__PURE__ */ jsx(Loader, { size: 28 }),
4525
+ (loadingMetadata || loadingItems) && /* @__PURE__ */ jsx(Loader, { size: 28 }),
4339
4526
  query !== "" && /* @__PURE__ */ jsx(ActionIcon, { onClick: onClearInput, children: /* @__PURE__ */ jsx(IconTrash, { size: 24 }) })
4340
4527
  ] }),
4341
4528
  ref: inputRef
@@ -4344,34 +4531,30 @@ function BespokeExplore({
4344
4531
  /* @__PURE__ */ jsx(
4345
4532
  ExploreFilters_default,
4346
4533
  {
4347
- metadata,
4348
- onFilter: onFilterChange,
4349
- initialReportId,
4350
- initialVariantId,
4351
4534
  translations: exploreTranslations
4352
4535
  }
4353
4536
  ),
4354
- /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading }),
4355
- !loading && results.length === 0 && /* @__PURE__ */ jsx(Alert, { title: exploreTranslations["no_results"], color: "blue", children: exploreTranslations["try_another"] }),
4356
- !loading && /* @__PURE__ */ jsx(ExploreResults_default, { results, profilePrefix, onSelect, reportTile })
4537
+ /* @__PURE__ */ jsx(LoadingOverlay, { visible: loadingMetadata || loadingItems }),
4538
+ !loadingItems && results.length === 0 && /* @__PURE__ */ jsx(Alert, { title: exploreTranslations["no_results"], color: "blue", children: exploreTranslations["try_another"] }),
4539
+ /* @__PURE__ */ jsx(
4540
+ ExploreResults_default,
4541
+ {
4542
+ profilePrefix,
4543
+ onSelect,
4544
+ reportTile
4545
+ }
4546
+ ),
4547
+ /* @__PURE__ */ jsx(ExplorePagination_default, {})
4357
4548
  ] });
4358
4549
  }
4359
- var DEFAULT_TRANSLATIONS, Explore_default;
4550
+ var Explore_default;
4360
4551
  var init_Explore = __esm({
4361
4552
  "frontend/components/explore/Explore.tsx"() {
4362
4553
  init_esm_shims();
4363
4554
  init_ExploreFilters();
4364
4555
  init_ExploreResults();
4365
- init_store2();
4366
- DEFAULT_TRANSLATIONS = {
4367
- "try_another": "Try another search or filter.",
4368
- "search": "Search",
4369
- "filters_all": "All",
4370
- "no_results": "No Results",
4371
- report: {},
4372
- dimension: {},
4373
- variant: {}
4374
- };
4556
+ init_ExplorePagination();
4557
+ init_ExploreProvider();
4375
4558
  Explore_default = BespokeExplore;
4376
4559
  }
4377
4560
  });
@@ -4415,7 +4598,7 @@ function BespokeExploreModal({
4415
4598
  target = /* @__PURE__ */ jsx(Tooltip, { label: tooltipText, ...tooltipProps, children: target });
4416
4599
  }
4417
4600
  return /* @__PURE__ */ jsxs(Fragment, { children: [
4418
- /* @__PURE__ */ jsx(Modal, { ...mdlConfig, ...modalProps, children: /* @__PURE__ */ jsx(Explore_default, { ...exploreProps, onSelect: () => setOpened(false) }) }),
4601
+ /* @__PURE__ */ jsx(Modal, { ...mdlConfig, ...modalProps, children: opened && /* @__PURE__ */ jsx(Explore_default, { ...exploreProps, onSelect: () => setOpened(false) }) }),
4419
4602
  /* @__PURE__ */ jsx("div", { onClick: () => setOpened(true), children: children ? target : /* @__PURE__ */ jsx(Fragment, { children: actionIcon }) })
4420
4603
  ] });
4421
4604
  }
@@ -4762,10 +4945,10 @@ var init_RichText = __esm({
4762
4945
  });
4763
4946
  function InnerTooltip(props) {
4764
4947
  const { content, style = {} } = props;
4765
- const { isPrint } = useMode();
4948
+ const print = usePrint();
4766
4949
  const contentObj = /* @__PURE__ */ jsx(RichText, { component: "span", html: content, isPreview: true });
4767
4950
  const element = useMemo(() => {
4768
- return isPrint ? /* @__PURE__ */ jsx("div", { className: "bespoke-inner-tooltip-notification", children: /* @__PURE__ */ jsx(
4951
+ return print ? /* @__PURE__ */ jsx("div", { className: "bespoke-inner-tooltip-notification", children: /* @__PURE__ */ jsx(
4769
4952
  Notification,
4770
4953
  {
4771
4954
  icon: /* @__PURE__ */ jsx(IconInfoCircle, { size: "1.1rem" }),
@@ -5307,7 +5490,7 @@ function TitleView({
5307
5490
  _iconPadding,
5308
5491
  asComparison = false
5309
5492
  }) {
5310
- const { isPrint } = useMode();
5493
+ const print = usePrint();
5311
5494
  const titleHTML = sanitizeBlockContent_default(title) || "<span class='cr-block-placeholder'>Title</span>";
5312
5495
  const intOrder = settings && settings.order ? parseInt(settings.order, 10) : 1;
5313
5496
  const order2 = intOrder <= 6 ? intOrder : 1;
@@ -5350,7 +5533,7 @@ function TitleView({
5350
5533
  position: getAlignForGroup(align),
5351
5534
  children: [
5352
5535
  /* @__PURE__ */ jsxs("div", { children: [
5353
- isPrint ? titleElement : finalElement,
5536
+ print ? titleElement : finalElement,
5354
5537
  displayName && /* @__PURE__ */ jsx(Text, { className: "bespoke-comparison-title", children: memberName })
5355
5538
  ] }),
5356
5539
  tooltip && /* @__PURE__ */ jsx(InnerTooltip, { content: tooltip })
@@ -5471,7 +5654,7 @@ var init_useOnChangeSelector = __esm({
5471
5654
  });
5472
5655
  function Selector(config) {
5473
5656
  const { name, settings, options, id, defaultValue, section, component, asComparison, hideLabel } = config;
5474
- const { isPrint } = useMode();
5657
+ const print = usePrint();
5475
5658
  const selectorIdentifier = getSelectorIdentifier(id);
5476
5659
  const callback = useOnChangeSelector(id, section, selectorIdentifier, asComparison);
5477
5660
  const selectorIdentifierParam = asComparison ? `${selectorIdentifier}Compare` : selectorIdentifier;
@@ -5482,9 +5665,9 @@ function Selector(config) {
5482
5665
  (d2) => ({ value: d2.id, label: d2.label })
5483
5666
  ), [optDependency]);
5484
5667
  const printValue = useMemo(() => {
5485
- const optionsString = isPrint ? options.filter((o2) => multiValue.includes(o2.id)).map((o2) => o2.label).join(", ") : "";
5668
+ const optionsString = print ? options.filter((o2) => multiValue.includes(o2.id)).map((o2) => o2.label).join(", ") : "";
5486
5669
  return optionsString;
5487
- }, [isPrint]);
5670
+ }, [print]);
5488
5671
  const label = config.hideLabel === "true" ? /* @__PURE__ */ jsx(Fragment, {}) : /* @__PURE__ */ jsx(RichText, { component: "div", html: name, size: "sm", style: settings });
5489
5672
  useEffect(() => {
5490
5673
  const searchParams = new URLSearchParams(window.location.search);
@@ -5539,7 +5722,7 @@ function Selector(config) {
5539
5722
  }
5540
5723
  )
5541
5724
  }[config.type] }) }),
5542
- isPrint && /* @__PURE__ */ jsxs(Text, { children: [
5725
+ print && /* @__PURE__ */ jsxs(Text, { children: [
5543
5726
  label,
5544
5727
  ": ",
5545
5728
  printValue
@@ -5595,7 +5778,7 @@ var init_Image = __esm({
5595
5778
  init_block2();
5596
5779
  }
5597
5780
  });
5598
- function useInitialState(pathSegmentsKey, mode) {
5781
+ function useInitialState(pathSegmentsKey) {
5599
5782
  const { asPath, locale, defaultLocale } = useRouter();
5600
5783
  const [loading, setLoading] = useState(true);
5601
5784
  const { user, isLoading } = useUser();
@@ -5638,41 +5821,39 @@ function useInitialState(pathSegmentsKey, mode) {
5638
5821
  }
5639
5822
  }, [user, isLoading]);
5640
5823
  useEffect(() => {
5641
- if (mode !== "embed") {
5642
- const hasParams = Object.keys(query).some((key) => key !== pathSegmentsKey);
5643
- if ((hasParams || privateBlocks.blocks.length > 0) && privateBlocks.resolved) {
5644
- const selectorIds = Object.keys(query).map((d2) => Number(d2.match(/\d+/)));
5645
- const revalidateBlocks = selectorIds.filter((id) => id !== 0).concat(privateBlocks.blocks);
5646
- Promise.all(
5647
- revalidateBlocks.map((bid) => {
5648
- const block = blockRecords[bid];
5649
- const inputVariablesFlat = block.consumers.reduce((inputVars, cid) => ({ ...inputVars, ...variables[cid] }), {});
5650
- const blockContext = {
5651
- locale: localeDefault4,
5652
- query,
5653
- variables: {
5654
- ...inputVariablesFlat,
5655
- ...attributes
5656
- }
5657
- };
5658
- return runConsumersV2(
5659
- blockRecords,
5660
- void 0,
5661
- bid,
5662
- formatters2,
5663
- blockContext,
5664
- { variables, status },
5665
- readMemberFn,
5666
- "report"
5667
- );
5668
- })
5669
- ).then((d2) => {
5670
- setLoading(false);
5671
- d2.map((data) => dispatch(variablesActions.setVariableChange({ ...data, attributes })));
5672
- });
5673
- }
5824
+ const hasParams = Object.keys(query).some((key) => key !== pathSegmentsKey);
5825
+ if ((hasParams || privateBlocks.blocks.length > 0) && privateBlocks.resolved) {
5826
+ const selectorIds = Object.keys(query).map((d2) => Number(d2.match(/\d+/)));
5827
+ const revalidateBlocks = selectorIds.filter((id) => id !== 0).concat(privateBlocks.blocks);
5828
+ Promise.all(
5829
+ revalidateBlocks.map((bid) => {
5830
+ const block = blockRecords[bid];
5831
+ const inputVariablesFlat = block.consumers.reduce((inputVars, cid) => ({ ...inputVars, ...variables[cid] }), {});
5832
+ const blockContext = {
5833
+ locale: localeDefault4,
5834
+ query,
5835
+ variables: {
5836
+ ...inputVariablesFlat,
5837
+ ...attributes
5838
+ }
5839
+ };
5840
+ return runConsumersV2(
5841
+ blockRecords,
5842
+ void 0,
5843
+ bid,
5844
+ formatters2,
5845
+ blockContext,
5846
+ { variables, status },
5847
+ readMemberFn,
5848
+ "report"
5849
+ );
5850
+ })
5851
+ ).then((d2) => {
5852
+ setLoading(false);
5853
+ d2.map((data) => dispatch(variablesActions.setVariableChange({ ...data, attributes })));
5854
+ });
5674
5855
  }
5675
- }, [privateBlocks.resolved, mode]);
5856
+ }, [privateBlocks.resolved]);
5676
5857
  return loading || !privateBlocks.resolved;
5677
5858
  }
5678
5859
  var init_useInitialState = __esm({
@@ -6265,7 +6446,7 @@ __export(Viz_exports, {
6265
6446
  default: () => Viz
6266
6447
  });
6267
6448
  function Viz(config) {
6268
- const { isPrint, isEmbed } = useMode();
6449
+ const print = usePrint();
6269
6450
  const { block, active, locale, variables, configOverride = {} } = config;
6270
6451
  const content = getBlockContent(block);
6271
6452
  const formatterFunctions = useFormatterFunctionsForLocale(locale);
@@ -6294,8 +6475,8 @@ function Viz(config) {
6294
6475
  const Visualization = vizTypes[fallbackType];
6295
6476
  const vizPropsConfig = useMemo(() => {
6296
6477
  const { _data, ...vizPropsInnerConfig } = vizProps.config;
6297
- return printOverrides(vizPropsInnerConfig, isPrint || isEmbed);
6298
- }, [vizProps, isPrint, isEmbed]);
6478
+ return printOverrides(vizPropsInnerConfig, print);
6479
+ }, [vizProps, print]);
6299
6480
  const vizConfig = { locale, variables, ...vizPropsConfig, ...configOverride };
6300
6481
  return /* @__PURE__ */ jsx("div", { className: "bespoke-Viz", children: /* @__PURE__ */ jsx(
6301
6482
  "div",
@@ -12351,7 +12532,8 @@ var init_BespokeTextEditor = __esm({
12351
12532
  ] });
12352
12533
  };
12353
12534
  TextOptions = () => {
12354
- return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(BubbleMenu, { tippyOptions: { placement: "bottom" }, children: /* @__PURE__ */ jsx(FormatControls, {}) }) });
12535
+ const { editor } = useCurrentEditor();
12536
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(BubbleMenu, { tippyOptions: { placement: "bottom" }, editor, children: /* @__PURE__ */ jsx(FormatControls, {}) }) });
12355
12537
  };
12356
12538
  AlignControls = () => {
12357
12539
  const { editor } = useCurrentEditor();
@@ -15941,112 +16123,161 @@ var init_DataTab = __esm({
15941
16123
  };
15942
16124
  }
15943
16125
  });
15944
- function useLocalePrefix() {
15945
- const { locales: locales4 } = useRouter();
15946
- const locale = location && location.pathname.split("/").filter((segment) => segment.length > 0)[0];
15947
- return locales4?.includes(locale);
15948
- }
15949
- var init_useLocalePrefix = __esm({
15950
- "frontend/hooks/useLocalePrefix.ts"() {
15951
- init_esm_shims();
15952
- }
15953
- });
15954
16126
  function ImageTab(props) {
15955
16127
  const { section } = props;
15956
16128
  const blocksIds = section.blocks || [];
15957
- const { asPath, query, locale } = useRouter();
15958
- const prefixLocale = useLocalePrefix();
15959
- const { pathSegment } = useBespoke();
15960
16129
  const vizAvailable = useAppSelector((state) => blocksIds.map((blockId) => state.records.entities.block[blockId]).filter((block) => block.type === "visualization" && state.variables.status[block.id].allowed));
15961
16130
  const [imageContext, setImageContext] = useState(contextOptions.section);
15962
16131
  const [imageFormat, setImageFormat] = useState(formatOptions2.png);
15963
16132
  const [imageProcessing, setImageProcessing] = useState(false);
16133
+ const [svgAvailable, setSvgAvailable] = useState(false);
15964
16134
  const [vizPreviews, setVizPreviews] = useState([]);
15965
16135
  const [vizSelected, setVizSelected] = useState(vizAvailable.length > 0 ? vizAvailable[0].id : null);
15966
- const [transparentBackground, setTransparentBackground] = useState(false);
16136
+ const [transparentBackground, setTransparentBackground] = useState(true);
15967
16137
  const [loadingPreviews, setLoadingPreviews] = useState(false);
15968
16138
  const optionsTranslations = useBespokeTranslations("options");
15969
16139
  const translations = { ...DEFAULT_TRANSLATIONS3, ...optionsTranslations["image_tab"] };
15970
- const sectionId = slugify_default(section?.settings?.name) || `section-${section.id}`;
15971
- const onSaveClickSection = async () => {
15972
- const search = Object.fromEntries(new URLSearchParams(location.search));
15973
- const selectors = Object.fromEntries(
15974
- Object.entries(search).filter(([key]) => key.match(/selector\d+id/))
15975
- );
15976
- const body = {
15977
- path: asPath,
15978
- slugs: JSON.stringify(query[pathSegment]),
15979
- section: section.id,
15980
- query: selectors,
15981
- locale,
15982
- prefixLocale,
15983
- transparent: transparentBackground
15984
- };
15985
- setImageProcessing(true);
15986
- axios.post("/api/cms/img", body, { responseType: "blob" }).then((res) => {
15987
- const url = window.URL.createObjectURL(new Blob([res.data]));
16140
+ const { siteProps } = useBespoke();
16141
+ const includeLogo = siteProps?.logoSrc && typeof siteProps.logoSrc === "string";
16142
+ const sectionId = section?.settings?.name || `section-${section.id}`;
16143
+ const sectionHash = `#${sectionId}`;
16144
+ const theme = useMantineTheme();
16145
+ const vizSelectedHasSVG = () => {
16146
+ const vizNode = getVizNode(vizSelected);
16147
+ const svgCount = select(vizNode).select("svg").size();
16148
+ return svgCount === 1;
16149
+ };
16150
+ const getFileName = () => `${slugify_default(sectionId)}`;
16151
+ const getSectionNode = () => {
16152
+ const sectionNode = document.getElementById(sectionId);
16153
+ return select(sectionNode).select(".bespoke-section-content").node();
16154
+ };
16155
+ const getVizNode = (vizId) => {
16156
+ const sectionNode = getSectionNode();
16157
+ return select(sectionNode).select(`#bespoke-visualization-${vizId}.bespoke-block-area`).node();
16158
+ };
16159
+ const getSelectedNode = () => new Promise((resolve) => {
16160
+ let node;
16161
+ if (imageContext === contextOptions.section) {
16162
+ node = getSectionNode();
16163
+ } else if (imageContext === contextOptions.viz) {
16164
+ node = getVizNode(vizSelected);
16165
+ }
16166
+ const sourceContainer = document.createElement("div");
16167
+ sourceContainer.style.display = "flex";
16168
+ sourceContainer.style.justifyContent = "space-between";
16169
+ sourceContainer.classList.add("bespoke-Viz-source");
16170
+ sourceContainer.style.padding = theme.spacing.xs;
16171
+ sourceContainer.style.width = "100%";
16172
+ const sourceNode = document.createElement("div");
16173
+ sourceNode.innerText = translations["source"].replace("{src}", `${window.location}${sectionHash}`);
16174
+ sourceNode.style.fontSize = theme.fontSizes.xs;
16175
+ sourceContainer.appendChild(sourceNode);
16176
+ if (includeLogo) {
16177
+ const sourceImage = document.createElement("img");
16178
+ sourceImage.src = siteProps.logoSrc;
16179
+ sourceImage.style.height = "30px";
16180
+ sourceImage.onload = () => resolve(node);
16181
+ sourceImage.onerror = () => {
16182
+ sourceImage.remove();
16183
+ resolve(node);
16184
+ };
16185
+ sourceContainer.appendChild(sourceImage);
16186
+ node.appendChild(sourceContainer);
16187
+ } else {
16188
+ node.appendChild(sourceContainer);
16189
+ resolve(node);
16190
+ }
16191
+ });
16192
+ const getBackground = (elem) => {
16193
+ if (transparentBackground)
16194
+ return "transparent";
16195
+ const color = select(elem).style("background-color");
16196
+ if (color !== "rgba(0, 0, 0, 0)" && color !== "transparent")
16197
+ return color;
16198
+ if (elem === document.body)
16199
+ return "white";
16200
+ return getBackground(elem.parentNode);
16201
+ };
16202
+ const exportPng = async (node, config) => {
16203
+ const { toPng } = await import('html-to-image');
16204
+ toPng(
16205
+ node,
16206
+ {
16207
+ backgroundColor: config.background,
16208
+ cacheBust: true,
16209
+ filter: (innerNode) => {
16210
+ if (innerNode && innerNode.classList) {
16211
+ return !config.exclusionClasses.some((classname) => innerNode.classList.contains(classname));
16212
+ }
16213
+ return true;
16214
+ }
16215
+ }
16216
+ ).then((dataUrl) => {
15988
16217
  const link = document.createElement("a");
15989
- link.href = url;
15990
- link.setAttribute("download", "image.png");
15991
- document.body.appendChild(link);
16218
+ link.download = `${config.filename}.png`;
16219
+ link.href = dataUrl;
15992
16220
  link.click();
15993
- document.body.removeChild(link);
16221
+ cleanDOM();
15994
16222
  setImageProcessing(false);
16223
+ }).catch((err) => {
16224
+ console.log(err);
15995
16225
  });
15996
16226
  };
15997
- const onSaveClickViz = async () => {
15998
- const search = Object.fromEntries(new URLSearchParams(location.search));
15999
- const selectors = Object.fromEntries(
16000
- Object.entries(search).filter(([key]) => key.match(/selector\d+id/))
16227
+ const exportSvg = (node, config) => {
16228
+ saveElement(
16229
+ node,
16230
+ { filename: config.filename, type: "svg", callback: () => setImageProcessing(false) },
16231
+ { background: config.background }
16001
16232
  );
16002
- const body = {
16003
- path: asPath,
16004
- slugs: JSON.stringify(query[pathSegment]),
16005
- section: section.id,
16006
- viz: vizSelected,
16007
- query: selectors,
16008
- locale,
16009
- prefixLocale,
16010
- transparent: transparentBackground,
16011
- svg: imageFormat === formatOptions2.svg
16012
- };
16233
+ };
16234
+ const onSaveClick = async () => {
16013
16235
  setImageProcessing(true);
16014
- axios.post("/api/cms/img", body, { responseType: "blob" }).then((res) => {
16015
- const url = window.URL.createObjectURL(new Blob([res.data]));
16016
- const link = document.createElement("a");
16017
- link.href = url;
16018
- link.setAttribute("download", `image.${imageFormat.toLowerCase()}`);
16019
- document.body.appendChild(link);
16020
- link.click();
16021
- document.body.removeChild(link);
16236
+ const node = await getSelectedNode();
16237
+ const exportConfig = {
16238
+ background: getBackground(node),
16239
+ exclusionClasses: ["export-hidden"],
16240
+ filename: getFileName()
16241
+ };
16242
+ const exportFunction = imageFormat === formatOptions2.png ? exportPng : exportSvg;
16243
+ try {
16244
+ if (node) {
16245
+ exportFunction(node, exportConfig);
16246
+ } else {
16247
+ throw new Error(translations["wrong_node"]);
16248
+ }
16249
+ } catch (error) {
16022
16250
  setImageProcessing(false);
16023
- });
16251
+ }
16024
16252
  };
16025
16253
  const generatePreviews = async () => {
16026
16254
  const { toCanvas } = await import('html-to-image');
16027
16255
  Promise.all(
16028
- vizAvailable.map((viz) => toCanvas(getVizNode(viz.id, sectionId)))
16256
+ vizAvailable.map((viz) => toCanvas(getVizNode(viz.id)))
16029
16257
  ).then((canvases) => {
16030
16258
  setVizPreviews(canvases.map((canvas) => canvas.toDataURL()));
16031
16259
  setLoadingPreviews(false);
16032
16260
  });
16033
16261
  };
16034
- const handleContextChange = (newValue) => {
16035
- setImageContext(newValue);
16036
- if (newValue === contextOptions.section) {
16037
- setImageFormat(formatOptions2.png);
16038
- }
16039
- if (newValue === contextOptions.viz && vizAvailable.length > 0) {
16262
+ useEffect(() => {
16263
+ if (imageContext === contextOptions.viz && vizAvailable.length > 0) {
16040
16264
  setVizSelected(vizAvailable[0].id);
16041
16265
  setLoadingPreviews(true);
16042
16266
  generatePreviews();
16043
- } else if (newValue === contextOptions.section) {
16267
+ } else if (imageContext === contextOptions.section) {
16044
16268
  setVizPreviews([]);
16045
16269
  }
16046
- };
16047
- const onSelectViz = (vizId) => () => {
16048
- setVizSelected(vizId);
16049
- };
16270
+ }, [imageContext]);
16271
+ useEffect(() => {
16272
+ if (vizSelected) {
16273
+ if (vizSelectedHasSVG()) {
16274
+ setSvgAvailable(true);
16275
+ } else {
16276
+ setSvgAvailable(false);
16277
+ setImageFormat(formatOptions2.png);
16278
+ }
16279
+ }
16280
+ }, [vizSelected]);
16050
16281
  return /* @__PURE__ */ jsxs(Stack, { className: "cms-section-options-image", children: [
16051
16282
  /* @__PURE__ */ jsx(Space, { h: "xs" }),
16052
16283
  vizAvailable.length > 0 ? /* @__PURE__ */ jsx(Input.Wrapper, { label: `${translations["choose_area"]}:`, children: /* @__PURE__ */ jsx(
@@ -16070,7 +16301,12 @@ function ImageTab(props) {
16070
16301
  ] })
16071
16302
  }
16072
16303
  ],
16073
- onChange: handleContextChange
16304
+ onChange: (newValue) => {
16305
+ setImageContext(newValue);
16306
+ if (newValue === contextOptions.section) {
16307
+ setImageFormat(formatOptions2.png);
16308
+ }
16309
+ }
16074
16310
  }
16075
16311
  ) }) : /* @__PURE__ */ jsx(Text, { fw: "700", color: "gray.7", children: `${translations["entire_section"]}:` }),
16076
16312
  imageContext === contextOptions.viz && vizAvailable.length > 0 && /* @__PURE__ */ jsxs(
@@ -16080,20 +16316,27 @@ function ImageTab(props) {
16080
16316
  style: { minHeight: "161px", position: "relative" },
16081
16317
  children: [
16082
16318
  !loadingPreviews && vizPreviews.length > 0 && /* @__PURE__ */ jsx(ScrollArea, { style: { height: 250 }, children: /* @__PURE__ */ jsx(SimpleGrid, { cols: 3, children: vizAvailable.map((vizOption, ix) => /* @__PURE__ */ jsx(
16083
- VizPreview2,
16319
+ Image,
16084
16320
  {
16085
- vizId: vizOption.id,
16086
- isSelected: vizOption.id === vizSelected,
16087
- onClick: () => onSelectViz(vizAvailable[ix].id),
16088
- src: vizPreviews[ix]
16321
+ alt: `Viz ${vizOption.id}`,
16322
+ onClick: () => {
16323
+ setVizSelected(vizOption.id);
16324
+ },
16325
+ style: {
16326
+ cursor: "pointer",
16327
+ border: vizSelected === vizOption.id ? "4px solid #228be6" : "4px solid #eee"
16328
+ },
16329
+ radius: 0,
16330
+ src: vizPreviews[ix],
16331
+ withPlaceholder: true
16089
16332
  },
16090
- vizOption.id
16333
+ `viz-option-${vizOption.id}`
16091
16334
  )) }) }),
16092
16335
  /* @__PURE__ */ jsx(LoadingOverlay, { visible: loadingPreviews })
16093
16336
  ]
16094
16337
  }
16095
16338
  ),
16096
- imageContext !== contextOptions.section && /* @__PURE__ */ jsx(Input.Wrapper, { label: `${translations["choose_format"]}:`, children: /* @__PURE__ */ jsxs(Button.Group, { children: [
16339
+ svgAvailable && imageContext !== contextOptions.section && /* @__PURE__ */ jsx(Input.Wrapper, { label: `${translations["choose_format"]}:`, children: /* @__PURE__ */ jsxs(Button.Group, { children: [
16097
16340
  /* @__PURE__ */ jsx(
16098
16341
  Button,
16099
16342
  {
@@ -16115,7 +16358,7 @@ function ImageTab(props) {
16115
16358
  }
16116
16359
  )
16117
16360
  ] }) }),
16118
- imageFormat !== formatOptions2.svg && /* @__PURE__ */ jsx(
16361
+ /* @__PURE__ */ jsx(
16119
16362
  Checkbox,
16120
16363
  {
16121
16364
  checked: transparentBackground,
@@ -16129,14 +16372,14 @@ function ImageTab(props) {
16129
16372
  {
16130
16373
  leftIcon: /* @__PURE__ */ jsx(IconDownload, { size: 16 }),
16131
16374
  loading: imageProcessing,
16132
- onClick: imageContext === contextOptions.section ? onSaveClickSection : onSaveClickViz,
16375
+ onClick: onSaveClick,
16133
16376
  fullWidth: true,
16134
16377
  children: /* @__PURE__ */ jsx("span", { children: imageProcessing ? translations["processing"] : translations["download"].replace("{imageFormat}", imageFormat) })
16135
16378
  }
16136
16379
  )
16137
16380
  ] });
16138
16381
  }
16139
- var contextOptions, formatOptions2, VizPreview2, DEFAULT_TRANSLATIONS3, getSectionNode, getVizNode;
16382
+ var contextOptions, formatOptions2, cleanDOM, DEFAULT_TRANSLATIONS3;
16140
16383
  var init_ImageTab = __esm({
16141
16384
  "components/options/tabs/ImageTab.tsx"() {
16142
16385
  init_esm_shims();
@@ -16144,11 +16387,6 @@ var init_ImageTab = __esm({
16144
16387
  init_store2();
16145
16388
  init_TranslationsProvider();
16146
16389
  init_ResourceProvider();
16147
- init_useLocalePrefix();
16148
- init_d3plusPropify();
16149
- init_varSwapRecursive();
16150
- init_getBlockContent();
16151
- init_hooks();
16152
16390
  contextOptions = {
16153
16391
  viz: "viz",
16154
16392
  section: "section"
@@ -16157,50 +16395,9 @@ var init_ImageTab = __esm({
16157
16395
  png: "PNG",
16158
16396
  svg: "SVG"
16159
16397
  };
16160
- VizPreview2 = ({ vizId, isSelected = false, onClick = () => void 0, src = void 0 }) => {
16161
- const router = useRouter();
16162
- const { locale } = router;
16163
- const variables = useInputVariablesFlat(vizId);
16164
- const block = useBlockRef(vizId).data;
16165
- const content = getBlockContent(block);
16166
- const formatterFunctions = useFormatterFunctionsForLocale(locale);
16167
- const blockContext = { variables };
16168
- const transpiledLogic = varSwapRecursive_default({ logic: content.logic }, formatterFunctions, blockContext).logic;
16169
- const globals = {
16170
- router
16171
- };
16172
- const props = d3plusPropify_default(transpiledLogic, formatterFunctions, variables, locale, vizId, {}, globals);
16173
- const { title } = props.config;
16174
- return /* @__PURE__ */ jsxs(Stack, { align: "center", spacing: "xs", children: [
16175
- /* @__PURE__ */ jsx(
16176
- Image,
16177
- {
16178
- alt: `Viz ${vizId}`,
16179
- onClick,
16180
- style: {
16181
- cursor: "pointer",
16182
- border: isSelected ? "4px solid #228be6" : "4px solid #eee"
16183
- },
16184
- radius: 0,
16185
- src,
16186
- withPlaceholder: true
16187
- },
16188
- `viz-option-${vizId}`
16189
- ),
16190
- title && /* @__PURE__ */ jsx(
16191
- Text,
16192
- {
16193
- fz: "0.8rem",
16194
- fw: 700,
16195
- bg: isSelected ? "rgba(0, 0, 0, 0.2)" : "transparent",
16196
- w: "fit-content",
16197
- px: "xs",
16198
- sx: { borderRadius: "0.3rem" },
16199
- ta: "center",
16200
- children: title
16201
- }
16202
- )
16203
- ] });
16398
+ cleanDOM = () => {
16399
+ const sourceNodes = document.getElementsByClassName("bespoke-Viz-source");
16400
+ Array.from(sourceNodes).forEach((node) => node.remove());
16204
16401
  };
16205
16402
  DEFAULT_TRANSLATIONS3 = {
16206
16403
  "wrong_node": "Wrong node in export",
@@ -16214,15 +16411,6 @@ var init_ImageTab = __esm({
16214
16411
  "viz_only": "Visualization only",
16215
16412
  "source": "Source: {src}"
16216
16413
  };
16217
- getSectionNode = (sectionId) => {
16218
- console.log({ sectionId });
16219
- const sectionNode = document.getElementById(sectionId);
16220
- return select(sectionNode).select(".bespoke-section-content").node();
16221
- };
16222
- getVizNode = (vizId, sectionId) => {
16223
- const sectionNode = getSectionNode(sectionId);
16224
- return select(sectionNode).select(`#bespoke-visualization-${vizId}.bespoke-block-area`).node();
16225
- };
16226
16414
  }
16227
16415
  });
16228
16416
  function CopyInput(props) {
@@ -16244,31 +16432,12 @@ var init_CopyInput = __esm({
16244
16432
  init_esm_shims();
16245
16433
  }
16246
16434
  });
16247
- function useEmbedPath(sectionId) {
16248
- const { query, locale } = useRouter();
16249
- const prefixLocale = useLocalePrefix();
16250
- const { pathSegment } = useBespoke();
16251
- const slugs = query[pathSegment];
16252
- if (slugs && Array.isArray(slugs)) {
16253
- const search = new URLSearchParams({ section: sectionId });
16254
- const embed = `/embed/${slugs.join("/")}`;
16255
- const url = new URL(
16256
- prefixLocale ? `/${locale}${embed}` : `${embed}`,
16257
- location.href
16258
- );
16259
- url.search = search.toString();
16260
- return url.href;
16261
- }
16262
- return void 0;
16263
- }
16264
16435
  function ShareTab(props) {
16265
16436
  const { section } = props;
16266
16437
  const [shareUrl, setShareUrl] = useState("");
16267
16438
  const [title, setTitle] = useState("");
16268
16439
  const [includeSection, setIncludeSection] = useState(true);
16269
16440
  const optionsTranslations = useBespokeTranslations("options");
16270
- const embedPath = useEmbedPath(section.id);
16271
- const iframeStr = `<iframe width="100%" height="500px" frameborder="0" src="${embedPath}"></iframe>`;
16272
16441
  const translations = { ...DEFAULT_TRANSLATIONS4, ...optionsTranslations["share_tab"] };
16273
16442
  useEffect(() => {
16274
16443
  setTitle(document.title);
@@ -16289,7 +16458,6 @@ function ShareTab(props) {
16289
16458
  radius: "xl"
16290
16459
  }
16291
16460
  ),
16292
- /* @__PURE__ */ jsx(CopyInput, { title: translations["embed"], url: iframeStr }),
16293
16461
  /* @__PURE__ */ jsxs(Group, { position: "center", children: [
16294
16462
  /* @__PURE__ */ jsx(
16295
16463
  FacebookShareButton,
@@ -16352,12 +16520,9 @@ var init_ShareTab = __esm({
16352
16520
  init_esm_shims();
16353
16521
  init_CopyInput();
16354
16522
  init_TranslationsProvider();
16355
- init_useLocalePrefix();
16356
- init_ResourceProvider();
16357
16523
  DEFAULT_TRANSLATIONS4 = {
16358
16524
  "title": "Title",
16359
- "include_section": "Include Section",
16360
- "embed": "Embed"
16525
+ "include_section": "Include Section"
16361
16526
  };
16362
16527
  }
16363
16528
  });
@@ -17157,7 +17322,7 @@ var init_site = __esm({
17157
17322
  }
17158
17323
  });
17159
17324
  function ImageCredits({ previews, translations }) {
17160
- const { isPrint } = useMode();
17325
+ const print = usePrint();
17161
17326
  const credits = useMemo(() => previews.map(
17162
17327
  ({ image, name }, idx) => (image?.author || image?.url) && /* @__PURE__ */ jsxs(Stack, { spacing: 0, children: [
17163
17328
  image.author && /* @__PURE__ */ jsxs(Text, { size: "xs", children: [
@@ -17182,7 +17347,7 @@ function ImageCredits({ previews, translations }) {
17182
17347
  idx + 1 < previews.length && /* @__PURE__ */ jsx(Divider, {})
17183
17348
  ] }, image.id)
17184
17349
  ), [previews]);
17185
- return /* @__PURE__ */ jsx(Fragment, { children: isPrint ? /* @__PURE__ */ jsx(Fragment, { children: credits }) : /* @__PURE__ */ jsxs(Popover, { position: "right", children: [
17350
+ return /* @__PURE__ */ jsx(Fragment, { children: print ? /* @__PURE__ */ jsx(Fragment, { children: credits }) : /* @__PURE__ */ jsxs(Popover, { position: "right", children: [
17186
17351
  /* @__PURE__ */ jsx(Popover.Target, { children: /* @__PURE__ */ jsx(ActionIcon, { variant: "light", radius: "xl", children: /* @__PURE__ */ jsx(IconPhoto, { size: 20 }) }) }),
17187
17352
  /* @__PURE__ */ jsx(Popover.Dropdown, { children: credits })
17188
17353
  ] }) });
@@ -17202,7 +17367,7 @@ function SectionWrapper({
17202
17367
  previews,
17203
17368
  translations
17204
17369
  }) {
17205
- const { isPrint, isEmbed } = useMode();
17370
+ const print = usePrint();
17206
17371
  const showCredits = sectionSettings2.memberImageBg && previews.some(({ image }) => image && (image.url || image.author));
17207
17372
  return /* @__PURE__ */ jsxs(
17208
17373
  PositionWrapper,
@@ -17218,12 +17383,12 @@ function SectionWrapper({
17218
17383
  className: `bespoke-Section-${id} bespoke-Section-container `,
17219
17384
  settings: sectionSettings2,
17220
17385
  styles: sectionStyles?.container,
17221
- id: slugify_default(name) || `section-${id}`,
17386
+ id: name || `section-${id}`,
17222
17387
  pos: "relative",
17223
17388
  children: [
17224
- !isPrint && /* @__PURE__ */ jsxs(Group, { position: "right", mb: "xs", children: [
17389
+ !print && /* @__PURE__ */ jsxs(Group, { position: "right", mb: "xs", children: [
17225
17390
  /* @__PURE__ */ jsx(SectionResetButton, { id }),
17226
- sectionSettings2.optionsMenu && !isEmbed && /* @__PURE__ */ jsx(Options, { sectionId: id, disabled: false })
17391
+ sectionSettings2.optionsMenu && /* @__PURE__ */ jsx(Options, { sectionId: id, disabled: false })
17227
17392
  ] }),
17228
17393
  /* @__PURE__ */ jsxs(
17229
17394
  StyleWrapper,
@@ -17250,21 +17415,14 @@ function Section({ section }) {
17250
17415
  ...defaultSectionSettings,
17251
17416
  ...settings
17252
17417
  };
17253
- const { query } = useRouter();
17254
17418
  const comparison = useComparison();
17255
- const { isEmbed } = useMode();
17256
17419
  const state = useAppSelector((state2) => state2);
17257
17420
  const status = useAppSelector((state2) => state2.variables.status);
17258
17421
  const previews = useAppSelector((state2) => state2.status.previews);
17259
17422
  const comparisonPreviews = comparison.active && comparison.status ? previews.concat(comparison.status?.previews || []) : previews;
17260
17423
  const sectionStyles = useBespokeStyles()["Section"];
17261
17424
  const blockRecords = selectBlockRecords(state);
17262
- let sectionBlocks = [];
17263
- if (isEmbed && query.viz) {
17264
- sectionBlocks = Object.values(blockRecords || {}).filter((d2) => d2.section_id === id && d2.id === Number(query.viz));
17265
- } else {
17266
- sectionBlocks = Object.values(blockRecords || {}).filter((d2) => d2.section_id === id);
17267
- }
17425
+ const sectionBlocks = Object.values(blockRecords || {}).filter((d2) => d2.section_id === id);
17268
17426
  const sectionTranslations = useBespokeTranslations("sections");
17269
17427
  const translations = { ...DEFAULT_TRANSLATIONS6, ...sectionTranslations };
17270
17428
  const allowedSection = sectionBlocks.some((b2) => {
@@ -17372,7 +17530,7 @@ function Section({ section }) {
17372
17530
  );
17373
17531
  });
17374
17532
  }
17375
- return /* @__PURE__ */ jsxs(
17533
+ return /* @__PURE__ */ jsx(
17376
17534
  SectionWrapper,
17377
17535
  {
17378
17536
  id,
@@ -17381,24 +17539,21 @@ function Section({ section }) {
17381
17539
  sectionSettings: sectionSettings2,
17382
17540
  sectionStyles,
17383
17541
  translations,
17384
- children: [
17385
- /* @__PURE__ */ jsx(
17386
- ColumnsWrapper,
17387
- {
17388
- containerProps: {
17389
- gap: sectionSettings2.columnGutter || "md",
17390
- wrap: comparison.active ? "nowrap" : "wrap",
17391
- sx: { zIndex: 20 }
17392
- },
17393
- children: sectionColumns
17394
- }
17395
- ),
17396
- isEmbed && /* @__PURE__ */ jsx(EmbedSectionSrc, {})
17397
- ]
17542
+ children: /* @__PURE__ */ jsx(
17543
+ ColumnsWrapper,
17544
+ {
17545
+ containerProps: {
17546
+ gap: sectionSettings2.columnGutter || "md",
17547
+ wrap: comparison.active ? "nowrap" : "wrap",
17548
+ sx: { zIndex: 20 }
17549
+ },
17550
+ children: sectionColumns
17551
+ }
17552
+ )
17398
17553
  }
17399
17554
  );
17400
17555
  }
17401
- var DEFAULT_TRANSLATIONS6, getStyles, PositionWrapper, WidthWrapper, StyleWrapper, EmbedSectionSrc, Section_default;
17556
+ var DEFAULT_TRANSLATIONS6, getStyles, PositionWrapper, WidthWrapper, StyleWrapper, Section_default;
17402
17557
  var init_Section = __esm({
17403
17558
  "frontend/components/report/Section.tsx"() {
17404
17559
  init_esm_shims();
@@ -17419,9 +17574,6 @@ var init_Section = __esm({
17419
17574
  init_TranslationsProvider();
17420
17575
  init_ImageCredits();
17421
17576
  init_ComparisonProvider();
17422
- init_ResourceProvider();
17423
- init_useLocalePrefix();
17424
- init_slugify();
17425
17577
  DEFAULT_TRANSLATIONS6 = {
17426
17578
  "image_by": "image by"
17427
17579
  };
@@ -17482,56 +17634,18 @@ var init_Section = __esm({
17482
17634
  const sx = [defaultStyles[variant], getStyles(styles, settings)];
17483
17635
  return /* @__PURE__ */ jsx(Paper, { sx, ...defaultProps2[variant], ...props, children });
17484
17636
  };
17485
- EmbedSectionSrc = () => {
17486
- const router = useRouter();
17487
- const { query, locale } = router;
17488
- const { siteProps, profilePrefix, pathSegment } = useBespoke();
17489
- const querySlugs = query[pathSegment];
17490
- const slugs = Array.isArray(querySlugs) ? querySlugs?.join("/") : [];
17491
- const prefixLocale = useLocalePrefix();
17492
- let path = prefixLocale ? `/${locale}` : "";
17493
- path += `/${profilePrefix}/${slugs}/`;
17494
- const link = new URL(path, window?.location.href).href;
17495
- return /* @__PURE__ */ jsxs(Group, { position: "apart", noWrap: true, sx: { flexGrow: 1 }, children: [
17496
- /* @__PURE__ */ jsx(Anchor, { href: link, target: "_blank", children: link }),
17497
- /* @__PURE__ */ jsx(
17498
- "img",
17499
- {
17500
- src: siteProps.logoSrc,
17501
- width: "auto",
17502
- height: 40,
17503
- alt: "Site Logo"
17504
- }
17505
- )
17506
- ] });
17507
- };
17508
17637
  Section_default = Section;
17509
17638
  }
17510
17639
  });
17511
- function useMode() {
17512
- const mode = useContext(ModeContext);
17513
- return {
17514
- mode,
17515
- isPrint: mode === MODES.print,
17516
- isEmbed: mode === MODES.embed,
17517
- isReport: mode === MODES.report
17518
- };
17640
+ function usePrint() {
17641
+ return useContext(PrintContext);
17519
17642
  }
17520
- function Report({ pathSegmentsKey = "bespoke", mode = "report" }) {
17521
- const router = useRouter();
17522
- const { asPath, query } = router;
17643
+ function Report({ pathSegmentsKey = "bespoke" }) {
17644
+ const { asPath, query } = useRouter();
17523
17645
  const sectionList = useSectionList();
17524
17646
  const comparison = useComparison();
17525
- const [reportMode, setReportMode] = useState(mode);
17526
- useEffect(() => {
17527
- if (router.isReady) {
17528
- const { mode: mode2 } = router.query;
17529
- if (mode2 && typeof mode2 === "string" && Object.values(MODES).includes(mode2)) {
17530
- setReportMode(mode2);
17531
- }
17532
- }
17533
- }, [router.isReady, router.query]);
17534
- const printBtn = yn4(router.query.printBtn) ?? false;
17647
+ const print = yn4(query.print) ?? false;
17648
+ const printBtn = yn4(query.printBtn) ?? false;
17535
17649
  const [downloadLoading, setDownloadLoading] = useState(false);
17536
17650
  const printReport = () => {
17537
17651
  setDownloadLoading(true);
@@ -17546,8 +17660,8 @@ function Report({ pathSegmentsKey = "bespoke", mode = "report" }) {
17546
17660
  });
17547
17661
  };
17548
17662
  useScrollToAnchor();
17549
- return /* @__PURE__ */ jsxs(ModeContext.Provider, { value: reportMode, children: [
17550
- mode === MODES.print && /* @__PURE__ */ jsx(MediaQuery, { query: "print", styles: { display: "block" }, children: /* @__PURE__ */ jsx(Title, { display: "none", children: "This is the report header" }) }),
17663
+ return /* @__PURE__ */ jsxs(PrintContext.Provider, { value: print, children: [
17664
+ print && /* @__PURE__ */ jsx(MediaQuery, { query: "print", styles: { display: "block" }, children: /* @__PURE__ */ jsx(Title, { display: "none", children: "This is the report header" }) }),
17551
17665
  /* @__PURE__ */ jsxs(Container, { id: "bespoke-report", className: comparison.comparisonLoaded ? "compare" : "", p: 0, pos: "relative", fluid: true, children: [
17552
17666
  sectionList.isSuccess && sectionList.data.sort(orderSort).map((section) => /* @__PURE__ */ jsx(Section_default, { section }, section.id)),
17553
17667
  /*pdf.active*/
@@ -17555,7 +17669,7 @@ function Report({ pathSegmentsKey = "bespoke", mode = "report" }) {
17555
17669
  ] })
17556
17670
  ] });
17557
17671
  }
17558
- var MODES, ModeContext, Report_default;
17672
+ var PrintContext, Report_default;
17559
17673
  var init_Report = __esm({
17560
17674
  "frontend/components/report/Report.tsx"() {
17561
17675
  init_esm_shims();
@@ -17564,12 +17678,7 @@ var init_Report = __esm({
17564
17678
  init_Section();
17565
17679
  init_ComparisonProvider();
17566
17680
  init_useScrollToAnchor();
17567
- MODES = {
17568
- report: "report",
17569
- print: "print",
17570
- embed: "embed"
17571
- };
17572
- ModeContext = createContext("report");
17681
+ PrintContext = createContext(false);
17573
17682
  Report_default = Report;
17574
17683
  }
17575
17684
  });
@@ -17694,6 +17803,9 @@ var LoginButton_default = BespokeLoginBtn;
17694
17803
  init_esm_shims();
17695
17804
  var UserProvider_default = UserProvider;
17696
17805
 
17806
+ // frontend/index.ts
17807
+ init_ExploreProvider();
17808
+
17697
17809
  // frontend/components/auth/withPageRoleAuthRequired.tsx
17698
17810
  init_esm_shims();
17699
17811
  function withPageRoleAuthRequired(params) {
@@ -17717,6 +17829,13 @@ var useUser_default = useUser;
17717
17829
  // frontend/index.ts
17718
17830
  init_hooks2();
17719
17831
 
17832
+ // frontend/components/BespokeProvider.tsx
17833
+ init_esm_shims();
17834
+ init_ExploreProvider();
17835
+ function BespokeProvider(props) {
17836
+ return /* @__PURE__ */ jsx(UserProvider_default, { children: /* @__PURE__ */ jsx(ExploreProvider, { explorePageSize: props.explorePageSize, children: props.children }) });
17837
+ }
17838
+
17720
17839
  // index.ts
17721
17840
  init_store2();
17722
17841
 
@@ -18019,7 +18138,8 @@ function parseSearchMemberParams(query) {
18019
18138
  report,
18020
18139
  all: localeIsAll,
18021
18140
  sort: normalizeList(query.sort)[0],
18022
- direction: normalizeList(query.direction)[0]
18141
+ direction: normalizeList(query.direction)[0],
18142
+ offset: Number(query.offset || 0)
18023
18143
  };
18024
18144
  }
18025
18145
 
@@ -18198,7 +18318,7 @@ function MembersAutocomplete(props) {
18198
18318
  variant: [variantId],
18199
18319
  dimension: [dimensionId],
18200
18320
  limit: 5,
18201
- visible: true,
18321
+ visible: false,
18202
18322
  includes: true,
18203
18323
  noImage: false,
18204
18324
  format: "plain",
@@ -18280,7 +18400,7 @@ function VariantSelector(props) {
18280
18400
  const showAsLabel = variantsData.length === 1 || !active;
18281
18401
  const [_variant, setVariant] = useUncontrolled({
18282
18402
  value: value ? String(value) : void 0,
18283
- defaultValue: variantsData[0].value,
18403
+ defaultValue: variantsData[0] ? variantsData[0].value : "",
18284
18404
  finalValue: void 0,
18285
18405
  onChange: onChange ? (v2) => onChange(Number(v2)) : void 0
18286
18406
  });
@@ -18291,7 +18411,7 @@ function VariantSelector(props) {
18291
18411
  {
18292
18412
  onClick: () => setActive(true),
18293
18413
  clickable: variantsData.length > 1,
18294
- children: displayValue.label
18414
+ children: displayValue ? displayValue.label : "No Variant"
18295
18415
  }
18296
18416
  ) : /* @__PURE__ */ jsx(
18297
18417
  Select,
@@ -18319,7 +18439,7 @@ function DimensionAutocomplete(props) {
18319
18439
  const [_variant, setVariant] = useUncontrolled({
18320
18440
  value: void 0,
18321
18441
  defaultValue: value?.variantId,
18322
- finalValue: Number(variantsData[0].value),
18442
+ finalValue: variantsData[0] ? Number(variantsData[0].value) : 0,
18323
18443
  onChange: () => {
18324
18444
  setMember({});
18325
18445
  }
@@ -18696,6 +18816,18 @@ init_esm_shims();
18696
18816
  init_EntityDeleteButton();
18697
18817
  init_Dialog();
18698
18818
  init_store2();
18819
+
18820
+ // libs/settings/variant.tsx
18821
+ init_esm_shims();
18822
+ var getVariantSettingsDefaults = (settings) => ({
18823
+ overrideNames: settings && typeof settings.overrideNames !== "undefined" ? settings.overrideNames : false,
18824
+ overrideRelevance: settings && typeof settings.overrideRelevance !== "undefined" ? settings.overrideRelevance : false,
18825
+ regenerateSlugs: settings && typeof settings.regenerateSlugs !== "undefined" ? settings.regenerateSlugs : false,
18826
+ keepOldMembers: settings && typeof settings.keepOldMembers !== "undefined" ? settings.keepOldMembers : true,
18827
+ doIngest: settings && typeof settings.doIngest !== "undefined" ? settings.doIngest : false,
18828
+ overrideAttributes: settings && typeof settings.overrideAttributes !== "undefined" ? settings.overrideAttributes : false,
18829
+ order: settings && typeof settings.order !== "undefined" ? settings.order : 0
18830
+ });
18699
18831
  function VariantCard({ for: variant, onEdit }) {
18700
18832
  const theme = useMantineTheme();
18701
18833
  const { newConfirmation } = useDialog();
@@ -18712,13 +18844,18 @@ function VariantCard({ for: variant, onEdit }) {
18712
18844
  console.debug("Variant edition aborted.");
18713
18845
  }
18714
18846
  }, [onEdit]);
18715
- const { slug, name } = variant;
18847
+ const { slug, name, settings } = variant;
18848
+ const variantSettings = getVariantSettingsDefaults(settings);
18716
18849
  return /* @__PURE__ */ jsxs(Card, { shadow: "xs", withBorder: true, style: { margin: theme.spacing.sm }, children: [
18717
18850
  /* @__PURE__ */ jsxs(Group, { position: "apart", children: [
18718
18851
  /* @__PURE__ */ jsxs(Center, { children: [
18719
18852
  /* @__PURE__ */ jsx(IconServer, { size: 22 }),
18720
18853
  /* @__PURE__ */ jsx(Space, { w: "xs" }),
18721
- /* @__PURE__ */ jsx(Text, { weight: "bold", children: name })
18854
+ /* @__PURE__ */ jsx(Text, { weight: "bold", children: name }),
18855
+ /* @__PURE__ */ jsxs(Text, { size: "xs", ml: "xs", children: [
18856
+ "Order: ",
18857
+ variantSettings.order
18858
+ ] })
18722
18859
  ] }),
18723
18860
  /* @__PURE__ */ jsxs(Badge, { variant: "light", children: [
18724
18861
  "/",
@@ -18979,17 +19116,6 @@ function MembersTable({ members, onClickEdit, onSort, colsToRender = [], dataTab
18979
19116
  );
18980
19117
  }
18981
19118
 
18982
- // libs/settings/variant.tsx
18983
- init_esm_shims();
18984
- var getVariantSettingsDefaults = (settings) => ({
18985
- overrideNames: settings && typeof settings.overrideNames !== "undefined" ? settings.overrideNames : false,
18986
- overrideRelevance: settings && typeof settings.overrideRelevance !== "undefined" ? settings.overrideRelevance : false,
18987
- regenerateSlugs: settings && typeof settings.regenerateSlugs !== "undefined" ? settings.regenerateSlugs : false,
18988
- keepOldMembers: settings && typeof settings.keepOldMembers !== "undefined" ? settings.keepOldMembers : true,
18989
- doIngest: settings && typeof settings.doIngest !== "undefined" ? settings.doIngest : false,
18990
- overrideAttributes: settings && typeof settings.overrideAttributes !== "undefined" ? settings.overrideAttributes : false
18991
- });
18992
-
18993
19119
  // components/builder/components/SwitchWithTooltip.tsx
18994
19120
  init_esm_shims();
18995
19121
  function SwitchWithTooltip({ switchProps, yesText, noText }) {
@@ -19377,6 +19503,19 @@ function VariantEditor({ for: variant, onClose: closeHandler }) {
19377
19503
  ] }) : false,
19378
19504
  onChange: (e) => onChange("slug", e.target.value)
19379
19505
  }
19506
+ ),
19507
+ /* @__PURE__ */ jsx(Space, { h: "xs" }),
19508
+ /* @__PURE__ */ jsx(
19509
+ NumberInput,
19510
+ {
19511
+ value: variantSettings.order || 0,
19512
+ description: "It affects on explore options order",
19513
+ placeholder: "Order",
19514
+ label: "Order",
19515
+ onChange: (v2) => {
19516
+ onChangeSettings("order", v2);
19517
+ }
19518
+ }
19380
19519
  )
19381
19520
  ] }),
19382
19521
  /* @__PURE__ */ jsxs(Tabs.Panel, { value: "members", py: "md", children: [
@@ -19732,11 +19871,24 @@ function ReportEditor({ id, onClose: closeHandler }) {
19732
19871
  const onChange = useCallback((field, value) => {
19733
19872
  setConfig({ ...config, [field]: value });
19734
19873
  }, []);
19874
+ const onChangeSettings = (field, value) => {
19875
+ setConfig({
19876
+ ...config,
19877
+ //config: configUpdate,
19878
+ settings: {
19879
+ ...config.settings,
19880
+ [field]: value
19881
+ }
19882
+ });
19883
+ };
19735
19884
  if (isEditing) {
19736
19885
  return /* @__PURE__ */ jsx(DimensionEditor, { id: isEditing, onClose: () => setEditing(null) });
19737
19886
  }
19738
19887
  const loading = ref.isFetching;
19739
19888
  const dimensions = ref.isSuccess ? ref.data.dimensions : [];
19889
+ const settings = config.settings;
19890
+ const order2 = settings && typeof settings.order === "number" ? settings.order : 0;
19891
+ const hide2 = settings && typeof settings.hide === "boolean" ? settings.hide : false;
19740
19892
  return /* @__PURE__ */ jsx(
19741
19893
  DrawerContentWithScroll,
19742
19894
  {
@@ -19751,7 +19903,36 @@ function ReportEditor({ id, onClose: closeHandler }) {
19751
19903
  onChange: (e) => onChange("name", e.target.value)
19752
19904
  }
19753
19905
  ),
19754
- /* @__PURE__ */ jsx(Divider, { my: "xl" }),
19906
+ /* @__PURE__ */ jsx(Space, { h: "xs" }),
19907
+ /* @__PURE__ */ jsxs(Group, { grow: true, children: [
19908
+ /* @__PURE__ */ jsx(
19909
+ SwitchWithTooltip_default,
19910
+ {
19911
+ switchProps: {
19912
+ label: "Show in Explore & Search",
19913
+ checked: !hide2,
19914
+ onChange: (event) => onChangeSettings("hide", !event.currentTarget.checked)
19915
+ },
19916
+ yesText: "Profile appears in Explore search and members are listed in search results",
19917
+ noText: "Profile is hidden in Explore search and members are not included in search results"
19918
+ }
19919
+ ),
19920
+ /* @__PURE__ */ jsx(
19921
+ NumberInput,
19922
+ {
19923
+ defaultValue: 0,
19924
+ value: order2,
19925
+ description: "It affects the Explore search options order",
19926
+ placeholder: "Order in Explore",
19927
+ label: "Order",
19928
+ disabled: hide2,
19929
+ onChange: (v2) => {
19930
+ onChangeSettings("order", v2);
19931
+ }
19932
+ }
19933
+ )
19934
+ ] }),
19935
+ /* @__PURE__ */ jsx(Divider, { my: "sm" }),
19755
19936
  /* @__PURE__ */ jsx(IconTitle, { icon: /* @__PURE__ */ jsx(IconDatabase, { size: 22 }), children: /* @__PURE__ */ jsx(Title, { order: 2, size: "h4", children: "Dimensions" }) }),
19756
19937
  /* @__PURE__ */ jsx(Grid, { children: dimensions.map((d2) => /* @__PURE__ */ jsx(Grid.Col, { span: 6, children: /* @__PURE__ */ jsx(DimensionCardWithFetcher, { id: d2, onEdit: setEditing }) }, d2)) }),
19757
19938
  /* @__PURE__ */ jsx(
@@ -23750,7 +23931,8 @@ function FilterSidebar2({ onChange, loading }) {
23750
23931
  variant: allOption2.value,
23751
23932
  visible: false,
23752
23933
  noImage: false,
23753
- limit: "10"
23934
+ limit: "10",
23935
+ paginationVariants: []
23754
23936
  };
23755
23937
  const [filters, setFilters] = useState(initialFilterState);
23756
23938
  const options = useMemo(() => ({
@@ -23762,7 +23944,7 @@ function FilterSidebar2({ onChange, loading }) {
23762
23944
  });
23763
23945
  return acc;
23764
23946
  }, [])),
23765
- limit: [10, 25, 50].map((i2) => ({ value: String(i2), label: String(i2) }))
23947
+ limit: [10, 25, 50, 100].map((i2) => ({ value: String(i2), label: String(i2) }))
23766
23948
  }), [reportsNested, filters]);
23767
23949
  const onChangeFilter = useCallback((key, value) => {
23768
23950
  const newFilters = {
@@ -23772,6 +23954,7 @@ function FilterSidebar2({ onChange, loading }) {
23772
23954
  switch (key) {
23773
23955
  case "report":
23774
23956
  newFilters.dimension = allOption2.value;
23957
+ newFilters.variant = allOption2.value;
23775
23958
  break;
23776
23959
  case "dimension":
23777
23960
  newFilters.variant = allOption2.value;
@@ -23791,7 +23974,28 @@ function FilterSidebar2({ onChange, loading }) {
23791
23974
  });
23792
23975
  };
23793
23976
  useEffect(() => {
23794
- onChange({ ...filters, query: debouncedQuery });
23977
+ let variants = [];
23978
+ if (filters.variant !== allOption2.value) {
23979
+ variants = [`${filters.variant}`];
23980
+ } else if (filters.dimension !== allOption2.value) {
23981
+ reportsNested.forEach((r2) => {
23982
+ const dim = r2.dimensions.find((d2) => `${d2.id}` === filters.dimension);
23983
+ if (dim) {
23984
+ variants = dim.variants.map((v2) => `${v2.id}`);
23985
+ }
23986
+ });
23987
+ } else if (filters.report !== allOption2.value) {
23988
+ const rep = reportsNested.find((r2) => `${r2.id}` === filters.report);
23989
+ if (rep) {
23990
+ rep.dimensions.forEach((d2) => {
23991
+ variants = [
23992
+ ...variants,
23993
+ ...d2.variants.map((v2) => `${v2.id}`)
23994
+ ];
23995
+ });
23996
+ }
23997
+ }
23998
+ onChange({ ...filters, paginationVariants: variants, query: debouncedQuery });
23795
23999
  }, [
23796
24000
  filters.report,
23797
24001
  filters.dimension,
@@ -24618,6 +24822,8 @@ function MetadataEditor() {
24618
24822
  const [loading, setLoading] = useState(true);
24619
24823
  const [internalFilters, setInternalFilters] = useState(true);
24620
24824
  const [internalSort, setInternalSort] = useState();
24825
+ const [activePage, setActivePage] = useState(1);
24826
+ const [currentPageTotal, setCurrentPageTotal] = useState(0);
24621
24827
  const onChangeFilters = (filters) => {
24622
24828
  setInternalFilters(filters);
24623
24829
  };
@@ -24645,19 +24851,33 @@ function MetadataEditor() {
24645
24851
  {
24646
24852
  params: {
24647
24853
  ...getParams,
24854
+ offset: (activePage - 1) * parseInt(getParams.limit || "10", 10),
24648
24855
  locale: "all",
24649
24856
  includes: true,
24650
24857
  sort: internalSort ? internalSort.id : "zvalue",
24651
24858
  direction: internalSort ? internalSort.desc ? "desc" : "asc" : "desc"
24652
24859
  }
24653
24860
  }
24654
- ).then((response) => response.data && response.data.data && response.data.data.results ? response.data.data.results : []);
24861
+ ).then((response) => {
24862
+ const total = response.data && response.data.data && response.data.data.meta ? Object.keys(response.data.data.meta.variantCount).reduce((acc, ix) => {
24863
+ let add = response.data.data.meta.variantCount[ix];
24864
+ if (internalFilters.paginationVariants && internalFilters.paginationVariants.length > 0) {
24865
+ if (!internalFilters.paginationVariants.includes(ix)) {
24866
+ add = 0;
24867
+ }
24868
+ }
24869
+ return acc + add;
24870
+ }, 0) : 0;
24871
+ setCurrentPageTotal(total);
24872
+ return response.data && response.data.data && response.data.data.results ? response.data.data.results : [];
24873
+ });
24655
24874
  setResults(entityRecords);
24656
24875
  setLoading(false);
24657
24876
  };
24658
24877
  useEffect(() => {
24659
24878
  doSearch();
24660
- }, [internalFilters, internalSort]);
24879
+ }, [internalFilters, internalSort, activePage]);
24880
+ console.log(internalFilters);
24661
24881
  return /* @__PURE__ */ jsxs(Container, { fluid: true, children: [
24662
24882
  /* @__PURE__ */ jsxs(Grid, { children: [
24663
24883
  /* @__PURE__ */ jsxs(Grid.Col, { span: 2, children: [
@@ -24667,7 +24887,17 @@ function MetadataEditor() {
24667
24887
  /* @__PURE__ */ jsxs(Grid.Col, { span: 10, style: { height: "100vh", position: "relative" }, children: [
24668
24888
  /* @__PURE__ */ jsx(LoadingOverlay, { visible: loading, overlayBlur: 2, overlayOpacity: 0.5 }),
24669
24889
  /* @__PURE__ */ jsx(Space, { h: "xs" }),
24670
- /* @__PURE__ */ jsx(MembersTable, { members: results, onClickEdit: setEditMember, onSort: onChangeSort })
24890
+ /* @__PURE__ */ jsx(MembersTable, { members: results, onClickEdit: setEditMember, onSort: onChangeSort }),
24891
+ /* @__PURE__ */ jsx(Group, { position: "center", children: /* @__PURE__ */ jsx(
24892
+ Pagination,
24893
+ {
24894
+ value: activePage,
24895
+ onChange: setActivePage,
24896
+ total: Math.ceil(currentPageTotal / internalFilters.limit),
24897
+ size: "sm",
24898
+ py: "xs"
24899
+ }
24900
+ ) })
24671
24901
  ] })
24672
24902
  ] }),
24673
24903
  editingId && /* @__PURE__ */ jsx(MemberForm, { memberId: editingId, onEditEnd: onEditClose })
@@ -25806,16 +26036,15 @@ function BespokeRenderer({
25806
26036
  siteProps,
25807
26037
  profilePrefix = "/defaultPath",
25808
26038
  loader = /* @__PURE__ */ jsx(LoadingOverlay, { visible: true }),
25809
- mode = "report",
25810
26039
  mantineProviderProps = {}
25811
26040
  }) {
25812
- const loading = useInitialState(pathSegmentsKey, mode);
26041
+ const loading = useInitialState(pathSegmentsKey);
25813
26042
  if (loading)
25814
26043
  return /* @__PURE__ */ jsx(Fragment, { children: loader });
25815
- return /* @__PURE__ */ jsx(MantineProvider, { ...mantineProviderProps, theme: { other: { bespokeStyles } }, inherit: true, children: /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment: pathSegmentsKey, profilePrefix, siteProps, children: [
25816
- /* @__PURE__ */ jsx(TranslationsProvider, { translations, children: /* @__PURE__ */ jsx(ComparisonProvider, { children: /* @__PURE__ */ jsx(PdfProvider, { children: /* @__PURE__ */ jsx(Report_default, { pathSegmentsKey, mode }) }) }) }),
25817
- /* @__PURE__ */ jsx("small", { className: "bespoke-timestamp", hidden: true, children: buildTime })
26044
+ return /* @__PURE__ */ jsx(MantineProvider, { ...mantineProviderProps, theme: { other: { bespokeStyles } }, inherit: true, children: /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment: "bespoke", profilePrefix, siteProps, children: [
26045
+ /* @__PURE__ */ jsx(TranslationsProvider, { translations, children: /* @__PURE__ */ jsx(ComparisonProvider, { children: /* @__PURE__ */ jsx(PdfProvider, { children: /* @__PURE__ */ jsx(Report_default, {}) }) }) }),
26046
+ /* @__PURE__ */ jsx("small", { className: "bespoke-timestamp", children: buildTime })
25818
26047
  ] }) });
25819
26048
  }
25820
26049
 
25821
- export { Explore_default as BespokeExplore, ExploreModal_default as BespokeExploreModal, LoginButton_default as BespokeLoginBtn, BespokeManager, BespokeRenderer, Report_default as BespokeReport, Search_default as BespokeSearch, UserProvider_default as BespokeUserProvider, withPageRoleAuthRequired as BespokeWithPageRoleAuthRequired, CMS_ROLES, DialogProvider, actions_exports as actions, storeWrapper, useAppDispatch as useBespokeDispatch, useAppSelector as useBespokeSelector, useUser_default as useBespokeUser, useDialog };
26050
+ export { Explore_default as BespokeExplore, ExploreModal_default as BespokeExploreModal, ExploreProvider as BespokeExploreProvider, LoginButton_default as BespokeLoginBtn, BespokeManager, BespokeProvider, BespokeRenderer, Report_default as BespokeReport, Search_default as BespokeSearch, UserProvider_default as BespokeUserProvider, withPageRoleAuthRequired as BespokeWithPageRoleAuthRequired, CMS_ROLES, DialogProvider, actions_exports as actions, storeWrapper, useAppDispatch as useBespokeDispatch, useExplore as useBespokeExplore, useAppSelector as useBespokeSelector, useUser_default as useBespokeUser, useDialog };