@datawheel/bespoke 0.3.20 → 0.3.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2957,16 +2957,17 @@ var init_actions = __esm({
2957
2957
  }
2958
2958
  });
2959
2959
  function ResourceProvider(props) {
2960
- const { pathSegment, profilePrefix } = props;
2960
+ const { pathSegment, profilePrefix, siteProps } = props;
2961
2961
  const formatters2 = useFormatterList();
2962
2962
  const value = useMemo(() => ({
2963
2963
  profilePrefix,
2964
2964
  pathSegment,
2965
+ siteProps,
2965
2966
  formatterFunctions: locales3.reduce((acc, locale) => ({
2966
2967
  ...acc,
2967
2968
  [locale]: formatters2.data ? funcifyFormattersByLocale(formatters2.data, locale) : {}
2968
2969
  }), {})
2969
- }), [formatters2, pathSegment, profilePrefix]);
2970
+ }), [formatters2, pathSegment, profilePrefix, siteProps]);
2970
2971
  return /* @__PURE__ */ jsx(ResourceContext.Provider, { value, children: props.children });
2971
2972
  }
2972
2973
  function useBespoke() {
@@ -2987,7 +2988,8 @@ var init_ResourceProvider = __esm({
2987
2988
  initialContext = {
2988
2989
  pathSegment: "path",
2989
2990
  formatterFunctions: locales3.reduce((acc, d) => ({ ...acc, [d]: {} }), {}),
2990
- profilePrefix: "path"
2991
+ profilePrefix: "path",
2992
+ siteProps: {}
2991
2993
  };
2992
2994
  ResourceContext = createContext(initialContext);
2993
2995
  }
@@ -8029,24 +8031,27 @@ var init_DataTab = __esm({
8029
8031
  function ImageTab(props) {
8030
8032
  const { section } = props;
8031
8033
  const blocksIds = section.blocks || [];
8032
- const vizBlocks = useAppSelector((state) => blocksIds.map((blockId) => state.records.entities.block[blockId]).filter((block) => block.type === "visualization" && state.variables.status[block.id].allowed));
8034
+ const vizAvailable = useAppSelector((state) => blocksIds.map((blockId) => state.records.entities.block[blockId]).filter((block) => block.type === "visualization" && state.variables.status[block.id].allowed));
8033
8035
  const [imageContext, setImageContext] = useState(contextOptions.section);
8034
8036
  const [imageFormat, setImageFormat] = useState(formatOptions2.png);
8035
8037
  const [imageProcessing, setImageProcessing] = useState(false);
8036
8038
  const [svgAvailable, setSvgAvailable] = useState(false);
8037
- const [vizAvailable, setVizAvailable] = useState(vizBlocks);
8038
8039
  const [vizPreviews, setVizPreviews] = useState([]);
8039
8040
  const [vizSelected, setVizSelected] = useState(vizAvailable.length > 0 ? vizAvailable[0].id : null);
8040
8041
  const [transparentBackground, setTransparentBackground] = useState(true);
8041
8042
  const [loadingPreviews, setLoadingPreviews] = useState(false);
8042
8043
  const optionsTranslations = useBespokeTranslations("options");
8043
8044
  const translations = { ...DEFAULT_TRANSLATIONS3, ...optionsTranslations["image_tab"] };
8045
+ const { siteProps } = useBespoke();
8046
+ const includeLogo = siteProps?.logoSrc && typeof siteProps.logoSrc === "string";
8047
+ const sectionHash = section.settings?.name ? `#${section.settings.name}` : `#section-${section.id}`;
8048
+ const theme = useMantineTheme();
8044
8049
  const vizSelectedHasSVG = () => {
8045
8050
  const vizNode = getVizNode(section.id, vizSelected);
8046
8051
  const svgCount = select(vizNode).select("svg").size();
8047
8052
  return svgCount === 1;
8048
8053
  };
8049
- const getFileName = () => `${slugify_default("export-name")}`;
8054
+ const getFileName = () => `${slugify_default(section?.settings?.name || `section-${section.id}`)}`;
8050
8055
  const getSectionNode = (sectionId) => {
8051
8056
  const sectionNode = document.getElementById(`section-${sectionId}`);
8052
8057
  return select(sectionNode).select(".bespoke-section-content").node();
@@ -8055,15 +8060,39 @@ function ImageTab(props) {
8055
8060
  const sectionNode = getSectionNode(sectionId);
8056
8061
  return select(sectionNode).select(`#bespoke-visualization-${vizId}.bespoke-block-area`).node();
8057
8062
  };
8058
- const getSelectedNode = () => {
8063
+ const getSelectedNode = () => new Promise((resolve) => {
8059
8064
  let node;
8060
8065
  if (imageContext === contextOptions.section) {
8061
8066
  node = getSectionNode(section.id);
8062
8067
  } else if (imageContext === contextOptions.viz) {
8063
8068
  node = getVizNode(section.id, vizSelected);
8064
8069
  }
8065
- return node;
8066
- };
8070
+ const sourceContainer = document.createElement("div");
8071
+ sourceContainer.style.display = "flex";
8072
+ sourceContainer.style.justifyContent = "space-between";
8073
+ sourceContainer.classList.add("bespoke-Viz-source");
8074
+ sourceContainer.style.padding = theme.spacing.xs;
8075
+ sourceContainer.style.width = "100%";
8076
+ const sourceNode = document.createElement("div");
8077
+ sourceNode.innerText = translations["source"].replace("{src}", `${window.location}${sectionHash}`);
8078
+ sourceNode.style.fontSize = theme.fontSizes.xs;
8079
+ sourceContainer.appendChild(sourceNode);
8080
+ if (includeLogo) {
8081
+ const sourceImage = document.createElement("img");
8082
+ sourceImage.src = siteProps.logoSrc;
8083
+ sourceImage.style.height = "30px";
8084
+ sourceImage.onload = () => resolve(node);
8085
+ sourceImage.onerror = () => {
8086
+ sourceImage.remove();
8087
+ resolve(node);
8088
+ };
8089
+ sourceContainer.appendChild(sourceImage);
8090
+ node.appendChild(sourceContainer);
8091
+ } else {
8092
+ node.appendChild(sourceContainer);
8093
+ resolve(node);
8094
+ }
8095
+ });
8067
8096
  const getBackground = (elem) => {
8068
8097
  if (transparentBackground)
8069
8098
  return "transparent";
@@ -8086,9 +8115,6 @@ function ImageTab(props) {
8086
8115
  return !config.exclusionClasses.some((classname) => innerNode.classList.contains(classname));
8087
8116
  }
8088
8117
  return true;
8089
- },
8090
- style: {
8091
- // background: "green",
8092
8118
  }
8093
8119
  }
8094
8120
  ).then((dataUrl) => {
@@ -8096,6 +8122,7 @@ function ImageTab(props) {
8096
8122
  link.download = `${config.filename}.png`;
8097
8123
  link.href = dataUrl;
8098
8124
  link.click();
8125
+ cleanDOM();
8099
8126
  setImageProcessing(false);
8100
8127
  }).catch((err) => {
8101
8128
  console.log(err);
@@ -8108,9 +8135,9 @@ function ImageTab(props) {
8108
8135
  { background: config.background }
8109
8136
  );
8110
8137
  };
8111
- const onSaveClick = () => {
8138
+ const onSaveClick = async () => {
8112
8139
  setImageProcessing(true);
8113
- const node = getSelectedNode();
8140
+ const node = await getSelectedNode();
8114
8141
  const exportConfig = {
8115
8142
  background: getBackground(node),
8116
8143
  exclusionClasses: ["export-hidden"],
@@ -8157,7 +8184,7 @@ function ImageTab(props) {
8157
8184
  }, [vizSelected]);
8158
8185
  return /* @__PURE__ */ jsxs(Stack, { className: "cms-section-options-image", children: [
8159
8186
  /* @__PURE__ */ jsx(Space, { h: "xs" }),
8160
- /* @__PURE__ */ jsx(Input.Wrapper, { label: `${translations["choose_area"]}:`, children: /* @__PURE__ */ jsx(
8187
+ vizAvailable.length > 0 ? /* @__PURE__ */ jsx(Input.Wrapper, { label: `${translations["choose_area"]}:`, children: /* @__PURE__ */ jsx(
8161
8188
  SegmentedControl,
8162
8189
  {
8163
8190
  fullWidth: true,
@@ -8185,7 +8212,7 @@ function ImageTab(props) {
8185
8212
  }
8186
8213
  }
8187
8214
  }
8188
- ) }),
8215
+ ) }) : /* @__PURE__ */ jsx(Text, { fw: "700", color: "gray.7", children: `${translations["entire_section"]}:` }),
8189
8216
  imageContext === contextOptions.viz && vizAvailable.length > 0 && /* @__PURE__ */ jsxs(
8190
8217
  Input.Wrapper,
8191
8218
  {
@@ -8239,7 +8266,7 @@ function ImageTab(props) {
8239
8266
  Checkbox,
8240
8267
  {
8241
8268
  checked: transparentBackground,
8242
- label: `${translations["transparent_bg"]}:`,
8269
+ label: `${translations["transparent_bg"]}`,
8243
8270
  onChange: () => setTransparentBackground(!transparentBackground),
8244
8271
  radius: "xl"
8245
8272
  }
@@ -8256,13 +8283,14 @@ function ImageTab(props) {
8256
8283
  )
8257
8284
  ] });
8258
8285
  }
8259
- var contextOptions, formatOptions2, DEFAULT_TRANSLATIONS3;
8286
+ var contextOptions, formatOptions2, cleanDOM, DEFAULT_TRANSLATIONS3;
8260
8287
  var init_ImageTab = __esm({
8261
8288
  "components/options/tabs/ImageTab.tsx"() {
8262
8289
  init_esm_shims();
8263
8290
  init_slugify();
8264
8291
  init_store2();
8265
8292
  init_TranslationsProvider();
8293
+ init_ResourceProvider();
8266
8294
  contextOptions = {
8267
8295
  viz: "viz",
8268
8296
  section: "section"
@@ -8271,6 +8299,10 @@ var init_ImageTab = __esm({
8271
8299
  png: "PNG",
8272
8300
  svg: "SVG"
8273
8301
  };
8302
+ cleanDOM = () => {
8303
+ const sourceNodes = document.getElementsByClassName("bespoke-Viz-source");
8304
+ Array.from(sourceNodes).forEach((node) => node.remove());
8305
+ };
8274
8306
  DEFAULT_TRANSLATIONS3 = {
8275
8307
  "wrong_node": "Wrong node in export",
8276
8308
  "choose_area": "Choose image area",
@@ -8280,7 +8312,8 @@ var init_ImageTab = __esm({
8280
8312
  "processing": "Processing image...",
8281
8313
  "download": "Download {imageFormat}",
8282
8314
  "entire_section": "Entire section",
8283
- "viz_only": "Visualization only"
8315
+ "viz_only": "Visualization only",
8316
+ "source": "Source: {src}"
8284
8317
  };
8285
8318
  }
8286
8319
  });
@@ -9181,6 +9214,7 @@ var init_ImageCredits = __esm({
9181
9214
  }
9182
9215
  });
9183
9216
  function SectionWrapper({
9217
+ name,
9184
9218
  children,
9185
9219
  id,
9186
9220
  sectionSettings: sectionSettings2,
@@ -9204,7 +9238,7 @@ function SectionWrapper({
9204
9238
  className: `bespoke-Section-${id} bespoke-Section-container `,
9205
9239
  settings: sectionSettings2,
9206
9240
  styles: sectionStyles?.container,
9207
- id: `section-${id}`,
9241
+ id: name || `section-${id}`,
9208
9242
  pos: "relative",
9209
9243
  children: [
9210
9244
  !print && /* @__PURE__ */ jsxs(Group, { position: "right", mb: "xs", children: [
@@ -9356,6 +9390,7 @@ function Section({ section }) {
9356
9390
  SectionWrapper,
9357
9391
  {
9358
9392
  id,
9393
+ name: section?.settings?.name,
9359
9394
  previews: comparisonPreviews,
9360
9395
  sectionSettings: sectionSettings2,
9361
9396
  sectionStyles,
@@ -16677,6 +16712,7 @@ function BespokeRenderer({
16677
16712
  translations,
16678
16713
  bespokeStyles,
16679
16714
  buildTime,
16715
+ siteProps,
16680
16716
  profilePrefix = "/defaultPath",
16681
16717
  loader = /* @__PURE__ */ jsx(LoadingOverlay, { visible: true }),
16682
16718
  mantineProviderProps = {}
@@ -16684,7 +16720,7 @@ function BespokeRenderer({
16684
16720
  const loading = useInitialState(pathSegmentsKey);
16685
16721
  if (loading)
16686
16722
  return /* @__PURE__ */ jsx(Fragment, { children: loader });
16687
- return /* @__PURE__ */ jsx(MantineProvider, { ...mantineProviderProps, theme: { other: { bespokeStyles } }, inherit: true, children: /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment: "bespoke", profilePrefix, children: [
16723
+ return /* @__PURE__ */ jsx(MantineProvider, { ...mantineProviderProps, theme: { other: { bespokeStyles } }, inherit: true, children: /* @__PURE__ */ jsxs(ResourceProvider, { pathSegment: "bespoke", profilePrefix, siteProps, children: [
16688
16724
  /* @__PURE__ */ jsx(TranslationsProvider, { translations, children: /* @__PURE__ */ jsx(ComparisonProvider, { children: /* @__PURE__ */ jsx(PdfProvider, { children: /* @__PURE__ */ jsx(Report_default, {}) }) }) }),
16689
16725
  /* @__PURE__ */ jsx("small", { className: "bespoke-timestamp", children: buildTime })
16690
16726
  ] }) });
package/dist/server.js CHANGED
@@ -5900,7 +5900,8 @@ var { locales: locales8 } = getLocales_default();
5900
5900
  var initialContext = {
5901
5901
  pathSegment: "path",
5902
5902
  formatterFunctions: locales8.reduce((acc, d) => ({ ...acc, [d]: {} }), {}),
5903
- profilePrefix: "path"
5903
+ profilePrefix: "path",
5904
+ siteProps: {}
5904
5905
  };
5905
5906
  createContext(initialContext);
5906
5907
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datawheel/bespoke",
3
- "version": "0.3.20",
3
+ "version": "0.3.21",
4
4
  "description": "Content management system for creating automated data reports",
5
5
  "exports": {
6
6
  ".": {
@@ -130,4 +130,4 @@
130
130
  "peerDependencies": {
131
131
  "next": "^13.4.0"
132
132
  }
133
- }
133
+ }