datastake-daf 0.6.440 → 0.6.441

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.
@@ -14538,9 +14538,8 @@ DAFFooter.propTypes = {
14538
14538
  const PAGE_HEIGHT = 1587;
14539
14539
  const HEADER_HEIGHT = 100;
14540
14540
  const FOOTER_HEIGHT = 70;
14541
- const GAP_BETWEEN_BLOCKS = 24; // vertical spacing inside page
14542
- const FILL_RATIO = 0.80; // your "80% of page" rule
14543
-
14541
+ const GAP_BETWEEN_BLOCKS = 24;
14542
+ const FILL_RATIO = 0.80;
14544
14543
  const CONTENT_HEIGHT = PAGE_HEIGHT - HEADER_HEIGHT - FOOTER_HEIGHT;
14545
14544
  const Row = _ref => {
14546
14545
  let {
@@ -14579,10 +14578,19 @@ function PdfView(_ref2) {
14579
14578
  documentId = "IDD-0000000",
14580
14579
  downloadId = "DWL-00000123"
14581
14580
  } = _ref2;
14581
+ // Config actually used for rendering (may expand if we split big blocks)
14582
+ const [expandedConfig, setExpandedConfig] = React.useState(config);
14582
14583
  // index -> {height, ref}
14583
14584
  const [sections, setSections] = React.useState({});
14584
- // pageMap is an array of arrays of indices, e.g. [[0,1,2],[3,4],...]
14585
+ // [[indices for page 1], [indices for page 2], ...]
14585
14586
  const [pageMap, setPageMap] = React.useState([]);
14587
+
14588
+ // Reset expansion when the external config changes
14589
+ React.useEffect(() => {
14590
+ setExpandedConfig(config);
14591
+ setSections({});
14592
+ setPageMap([]);
14593
+ }, [config]);
14586
14594
  const onChangeHeight = React.useCallback((index, conf) => {
14587
14595
  setSections(prev => {
14588
14596
  var _prev$index;
@@ -14592,48 +14600,133 @@ function PdfView(_ref2) {
14592
14600
  });
14593
14601
  }, []);
14594
14602
 
14595
- // Core paginator: greedy packing with 80% threshold
14603
+ // --- Step 1: After measurement, split any oversized splittable blocks (one per pass) ---
14604
+ React.useEffect(() => {
14605
+ const keys = Object.keys(sections).map(k => Number(k)).sort((a, b) => a - b);
14606
+ if (keys.length !== expandedConfig.length) return; // not all measured yet
14607
+
14608
+ for (const idx of keys) {
14609
+ var _sections$idx$height, _sections$idx;
14610
+ const h = (_sections$idx$height = (_sections$idx = sections[idx]) === null || _sections$idx === void 0 ? void 0 : _sections$idx.height) !== null && _sections$idx$height !== void 0 ? _sections$idx$height : 0;
14611
+ const item = expandedConfig[idx];
14612
+ const canSplit = (item === null || item === void 0 ? void 0 : item.splittable) && typeof (item === null || item === void 0 ? void 0 : item.splitInto) === "function";
14613
+ if (canSplit && h > CONTENT_HEIGHT) {
14614
+ // Split it and re-measure
14615
+ const chunks = item.splitInto(CONTENT_HEIGHT);
14616
+ const next = [...expandedConfig.slice(0, idx), ...chunks, ...expandedConfig.slice(idx + 1)];
14617
+ setExpandedConfig(next);
14618
+ setSections({}); // force re-measure since indices changed
14619
+ setPageMap([]);
14620
+ return; // do one split per layout pass to avoid loops
14621
+ }
14622
+ }
14623
+ }, [sections, expandedConfig]);
14624
+
14625
+ // --- Step 2: Paginate with per-block hints (priority + keepWithNext) ---
14596
14626
  const paginate = React.useCallback(() => {
14597
14627
  const keys = Object.keys(sections).map(k => Number(k)).sort((a, b) => a - b);
14598
- if (keys.length !== config.length) return; // wait until all measured
14628
+ if (keys.length !== expandedConfig.length) return;
14599
14629
 
14630
+ // Build meta (read hints from config)
14631
+ const meta = keys.map(i => {
14632
+ var _expandedConfig$i$pri, _expandedConfig$i, _expandedConfig$i2;
14633
+ return {
14634
+ i,
14635
+ h: sections[i].height,
14636
+ priority: (_expandedConfig$i$pri = (_expandedConfig$i = expandedConfig[i]) === null || _expandedConfig$i === void 0 ? void 0 : _expandedConfig$i.priority) !== null && _expandedConfig$i$pri !== void 0 ? _expandedConfig$i$pri : 2,
14637
+ // 1 > 2 > 3 (1 is most important)
14638
+ keepWithNext: !!((_expandedConfig$i2 = expandedConfig[i]) !== null && _expandedConfig$i2 !== void 0 && _expandedConfig$i2.keepWithNext)
14639
+ };
14640
+ });
14600
14641
  const threshold = Math.floor(CONTENT_HEIGHT * FILL_RATIO);
14601
14642
  const pages = [];
14602
14643
  let current = [];
14603
14644
  let used = 0;
14604
- for (let idx of keys) {
14605
- const h = sections[idx].height;
14606
- const hWithGap = (current.length === 0 ? 0 : GAP_BETWEEN_BLOCKS) + h;
14607
-
14608
- // Oversized single block: start a new page but still place it alone
14609
- if (h > threshold && current.length === 0) {
14610
- current.push(idx);
14611
- pages.push(current);
14645
+ let carryKeep = false;
14646
+ for (let k = 0; k < meta.length; k++) {
14647
+ const curr = meta[k];
14648
+ const hWithGap = (current.length === 0 ? 0 : GAP_BETWEEN_BLOCKS) + curr.h;
14649
+
14650
+ // Honor keep-with-next from the previous block
14651
+ if (carryKeep) {
14652
+ // start current on a fresh page
14653
+ if (current.length) pages.push(current);
14654
+ current = [curr.i];
14655
+ used = curr.h;
14656
+ carryKeep = false;
14657
+ if (curr.keepWithNext) carryKeep = true;
14658
+ continue;
14659
+ }
14660
+
14661
+ // Oversized singleton: own page
14662
+ if (curr.h > threshold && current.length === 0) {
14663
+ pages.push([curr.i]);
14612
14664
  current = [];
14613
14665
  used = 0;
14666
+ carryKeep = false;
14614
14667
  continue;
14615
14668
  }
14669
+
14670
+ // Fits on current page?
14616
14671
  if (current.length === 0 || used + hWithGap <= threshold) {
14617
- current.push(idx);
14672
+ current.push(curr.i);
14618
14673
  used += hWithGap;
14619
14674
  } else {
14620
- pages.push(current);
14621
- current = [idx];
14622
- used = h; // first item on a fresh page, no top gap
14675
+ // Rebalance: try pushing a lower-priority block from current to next page to make room
14676
+ let moved = false;
14677
+ for (let j = current.length - 1; j >= 0; j--) {
14678
+ const prevIdx = current[j];
14679
+ const prev = meta.find(m => m.i === prevIdx);
14680
+ if (prev.priority > curr.priority) {
14681
+ // lower priority number = higher importance
14682
+ const tentativeUsed = used - (j === 0 ? prev.h : prev.h + GAP_BETWEEN_BLOCKS);
14683
+ if (tentativeUsed + hWithGap <= threshold) {
14684
+ // move prev off this page
14685
+ current.splice(j, 1);
14686
+ used = tentativeUsed;
14687
+ moved = true;
14688
+ break;
14689
+ }
14690
+ }
14691
+ }
14692
+ if (!moved) {
14693
+ pages.push(current);
14694
+ current = [curr.i];
14695
+ used = curr.h; // first element on new page (no top gap)
14696
+ } else {
14697
+ // we made space; place current here
14698
+ current.push(curr.i);
14699
+ used += hWithGap;
14700
+ }
14623
14701
  }
14702
+ if (curr.keepWithNext) carryKeep = true;
14624
14703
  }
14625
14704
  if (current.length) pages.push(current);
14626
- setPageMap(pages);
14627
- }, [sections, config.length]);
14628
-
14629
- // Re-run pagination when sizes change
14705
+ setPageMap(pages); // <-- unlimited pages; grows as needed
14706
+ }, [expandedConfig, sections]);
14630
14707
  React.useEffect(() => {
14631
14708
  paginate();
14632
14709
  }, [paginate]);
14633
14710
  const contClassName = formatClassname(["daf-analysis daf-pdf-view", customClassName]);
14634
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
14711
+
14712
+ // Measurement layer (only shown until we have a pageMap)
14713
+ const MeasurementLayer = React.useMemo(() => /*#__PURE__*/jsxRuntime.jsx("div", {
14714
+ className: "view-content",
14715
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
14716
+ className: "daf-analysis-layout",
14717
+ children: /*#__PURE__*/jsxRuntime.jsx("div", {
14718
+ className: "sections-cont",
14719
+ children: expandedConfig.map((widgets, i) => /*#__PURE__*/jsxRuntime.jsx(Row, {
14720
+ widgets: widgets,
14721
+ i: i,
14722
+ onChangeHeight: onChangeHeight
14723
+ }, "measure-".concat(i)))
14724
+ })
14725
+ })
14726
+ }), [expandedConfig, onChangeHeight]);
14727
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
14635
14728
  className: contClassName,
14636
- children: [pageMap.map((indices, pageIdx) => /*#__PURE__*/jsxRuntime.jsxs("div", {
14729
+ children: pageMap.length > 0 ? pageMap.map((indices, pageIdx) => /*#__PURE__*/jsxRuntime.jsxs("div", {
14637
14730
  className: "pdf-page",
14638
14731
  style: {
14639
14732
  height: PAGE_HEIGHT,
@@ -14660,9 +14753,7 @@ function PdfView(_ref2) {
14660
14753
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
14661
14754
  className: "pdf-body",
14662
14755
  style: {
14663
- minHeight: CONTENT_HEIGHT,
14664
- paddingTop: 0,
14665
- paddingBottom: 0
14756
+ minHeight: CONTENT_HEIGHT
14666
14757
  },
14667
14758
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
14668
14759
  style: {
@@ -14671,7 +14762,7 @@ function PdfView(_ref2) {
14671
14762
  gap: GAP_BETWEEN_BLOCKS
14672
14763
  },
14673
14764
  children: indices.map(i => /*#__PURE__*/jsxRuntime.jsx(Row, {
14674
- widgets: config[i],
14765
+ widgets: expandedConfig[i],
14675
14766
  i: i,
14676
14767
  onChangeHeight: onChangeHeight
14677
14768
  }, "row-".concat(i)))
@@ -14715,24 +14806,18 @@ function PdfView(_ref2) {
14715
14806
  })
14716
14807
  })]
14717
14808
  })]
14718
- }, "page-".concat(pageIdx))), pageMap.length === 0 && /*#__PURE__*/jsxRuntime.jsx("div", {
14719
- className: "view-content",
14720
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
14721
- className: "daf-analysis-layout",
14722
- children: /*#__PURE__*/jsxRuntime.jsx("div", {
14723
- className: "sections-cont",
14724
- children: config.map((widgets, i) => /*#__PURE__*/jsxRuntime.jsx(Row, {
14725
- widgets: widgets,
14726
- i: i,
14727
- onChangeHeight: onChangeHeight
14728
- }, "measure-".concat(i)))
14729
- })
14730
- })
14731
- })]
14809
+ }, "page-".concat(pageIdx))) : MeasurementLayer
14732
14810
  });
14733
14811
  }
14734
14812
  PdfView.propTypes = {
14735
- config: PropTypes__default["default"].array,
14813
+ config: PropTypes__default["default"].arrayOf(PropTypes__default["default"].shape({
14814
+ render: PropTypes__default["default"].func.isRequired,
14815
+ style: PropTypes__default["default"].object,
14816
+ priority: PropTypes__default["default"].oneOf([1, 2, 3]),
14817
+ keepWithNext: PropTypes__default["default"].bool,
14818
+ splittable: PropTypes__default["default"].bool,
14819
+ splitInto: PropTypes__default["default"].func // (maxHeightPx) => WidgetConfig[]
14820
+ })),
14736
14821
  customClassName: PropTypes__default["default"].any,
14737
14822
  title: PropTypes__default["default"].string,
14738
14823
  imgSrc: PropTypes__default["default"].string,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datastake-daf",
3
- "version": "0.6.440",
3
+ "version": "0.6.441",
4
4
  "dependencies": {
5
5
  "@ant-design/icons": "^5.2.5",
6
6
  "@antv/g2": "^5.1.1",
@@ -1,13 +1,13 @@
1
1
  import moment from "moment";
2
2
  import PropTypes from "prop-types";
3
- import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
3
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
4
4
  import { formatClassname } from "../../../../../helpers/ClassesHelper";
5
5
 
6
6
  const PAGE_HEIGHT = 1587;
7
7
  const HEADER_HEIGHT = 100;
8
8
  const FOOTER_HEIGHT = 70;
9
- const GAP_BETWEEN_BLOCKS = 24; // vertical spacing inside page
10
- const FILL_RATIO = 0.80; // your "80% of page" rule
9
+ const GAP_BETWEEN_BLOCKS = 24;
10
+ const FILL_RATIO = 0.80;
11
11
 
12
12
  const CONTENT_HEIGHT = PAGE_HEIGHT - HEADER_HEIGHT - FOOTER_HEIGHT;
13
13
 
@@ -41,145 +41,222 @@ export default function PdfView({
41
41
  documentId = "IDD-0000000",
42
42
  downloadId = "DWL-00000123",
43
43
  }) {
44
+ // Config actually used for rendering (may expand if we split big blocks)
45
+ const [expandedConfig, setExpandedConfig] = useState(config);
44
46
  // index -> {height, ref}
45
47
  const [sections, setSections] = useState({});
46
- // pageMap is an array of arrays of indices, e.g. [[0,1,2],[3,4],...]
48
+ // [[indices for page 1], [indices for page 2], ...]
47
49
  const [pageMap, setPageMap] = useState([]);
48
50
 
51
+ // Reset expansion when the external config changes
52
+ useEffect(() => {
53
+ setExpandedConfig(config);
54
+ setSections({});
55
+ setPageMap([]);
56
+ }, [config]);
57
+
49
58
  const onChangeHeight = useCallback((index, conf) => {
50
59
  setSections((prev) => (prev[index]?.height === conf.height ? prev : { ...prev, [index]: conf }));
51
60
  }, []);
52
61
 
53
- // Core paginator: greedy packing with 80% threshold
62
+ // --- Step 1: After measurement, split any oversized splittable blocks (one per pass) ---
63
+ useEffect(() => {
64
+ const keys = Object.keys(sections)
65
+ .map((k) => Number(k))
66
+ .sort((a, b) => a - b);
67
+
68
+ if (keys.length !== expandedConfig.length) return; // not all measured yet
69
+
70
+ for (const idx of keys) {
71
+ const h = sections[idx]?.height ?? 0;
72
+ const item = expandedConfig[idx];
73
+ const canSplit = item?.splittable && typeof item?.splitInto === "function";
74
+ if (canSplit && h > CONTENT_HEIGHT) {
75
+ // Split it and re-measure
76
+ const chunks = item.splitInto(CONTENT_HEIGHT);
77
+ const next = [
78
+ ...expandedConfig.slice(0, idx),
79
+ ...chunks,
80
+ ...expandedConfig.slice(idx + 1),
81
+ ];
82
+ setExpandedConfig(next);
83
+ setSections({}); // force re-measure since indices changed
84
+ setPageMap([]);
85
+ return; // do one split per layout pass to avoid loops
86
+ }
87
+ }
88
+ }, [sections, expandedConfig]);
89
+
90
+ // --- Step 2: Paginate with per-block hints (priority + keepWithNext) ---
54
91
  const paginate = useCallback(() => {
55
92
  const keys = Object.keys(sections)
56
93
  .map((k) => Number(k))
57
94
  .sort((a, b) => a - b);
95
+ if (keys.length !== expandedConfig.length) return;
58
96
 
59
- if (keys.length !== config.length) return; // wait until all measured
97
+ // Build meta (read hints from config)
98
+ const meta = keys.map((i) => ({
99
+ i,
100
+ h: sections[i].height,
101
+ priority: expandedConfig[i]?.priority ?? 2, // 1 > 2 > 3 (1 is most important)
102
+ keepWithNext: !!expandedConfig[i]?.keepWithNext,
103
+ }));
60
104
 
61
105
  const threshold = Math.floor(CONTENT_HEIGHT * FILL_RATIO);
62
106
  const pages = [];
63
107
  let current = [];
64
108
  let used = 0;
109
+ let carryKeep = false;
65
110
 
66
- for (let idx of keys) {
67
- const h = sections[idx].height;
68
- const hWithGap = (current.length === 0 ? 0 : GAP_BETWEEN_BLOCKS) + h;
111
+ for (let k = 0; k < meta.length; k++) {
112
+ const curr = meta[k];
113
+ const hWithGap = (current.length === 0 ? 0 : GAP_BETWEEN_BLOCKS) + curr.h;
114
+
115
+ // Honor keep-with-next from the previous block
116
+ if (carryKeep) {
117
+ // start current on a fresh page
118
+ if (current.length) pages.push(current);
119
+ current = [curr.i];
120
+ used = curr.h;
121
+ carryKeep = false;
122
+ if (curr.keepWithNext) carryKeep = true;
123
+ continue;
124
+ }
69
125
 
70
- // Oversized single block: start a new page but still place it alone
71
- if (h > threshold && current.length === 0) {
72
- current.push(idx);
73
- pages.push(current);
126
+ // Oversized singleton: own page
127
+ if (curr.h > threshold && current.length === 0) {
128
+ pages.push([curr.i]);
74
129
  current = [];
75
130
  used = 0;
131
+ carryKeep = false;
76
132
  continue;
77
133
  }
78
134
 
135
+ // Fits on current page?
79
136
  if (current.length === 0 || used + hWithGap <= threshold) {
80
- current.push(idx);
137
+ current.push(curr.i);
81
138
  used += hWithGap;
82
139
  } else {
83
- pages.push(current);
84
- current = [idx];
85
- used = h; // first item on a fresh page, no top gap
140
+ // Rebalance: try pushing a lower-priority block from current to next page to make room
141
+ let moved = false;
142
+ for (let j = current.length - 1; j >= 0; j--) {
143
+ const prevIdx = current[j];
144
+ const prev = meta.find((m) => m.i === prevIdx);
145
+ if (prev.priority > curr.priority) { // lower priority number = higher importance
146
+ const tentativeUsed = used - (j === 0 ? prev.h : (prev.h + GAP_BETWEEN_BLOCKS));
147
+ if (tentativeUsed + hWithGap <= threshold) {
148
+ // move prev off this page
149
+ current.splice(j, 1);
150
+ used = tentativeUsed;
151
+ moved = true;
152
+ break;
153
+ }
154
+ }
155
+ }
156
+ if (!moved) {
157
+ pages.push(current);
158
+ current = [curr.i];
159
+ used = curr.h; // first element on new page (no top gap)
160
+ } else {
161
+ // we made space; place current here
162
+ current.push(curr.i);
163
+ used += hWithGap;
164
+ }
86
165
  }
166
+
167
+ if (curr.keepWithNext) carryKeep = true;
87
168
  }
88
169
 
89
170
  if (current.length) pages.push(current);
90
- setPageMap(pages);
91
- }, [sections, config.length]);
171
+ setPageMap(pages); // <-- unlimited pages; grows as needed
172
+ }, [expandedConfig, sections]);
92
173
 
93
- // Re-run pagination when sizes change
94
174
  useEffect(() => {
95
175
  paginate();
96
176
  }, [paginate]);
97
177
 
98
178
  const contClassName = formatClassname(["daf-analysis daf-pdf-view", customClassName]);
99
179
 
180
+ // Measurement layer (only shown until we have a pageMap)
181
+ const MeasurementLayer = useMemo(
182
+ () => (
183
+ <div className="view-content">
184
+ <div className="daf-analysis-layout">
185
+ <div className="sections-cont">
186
+ {expandedConfig.map((widgets, i) => (
187
+ <Row key={`measure-${i}`} widgets={widgets} i={i} onChangeHeight={onChangeHeight} />
188
+ ))}
189
+ </div>
190
+ </div>
191
+ </div>
192
+ ),
193
+ [expandedConfig, onChangeHeight]
194
+ );
195
+
100
196
  return (
101
197
  <div className={contClassName}>
102
- {/* Render final paginated pages */}
103
- {pageMap.map((indices, pageIdx) => (
104
- <div
105
- key={`page-${pageIdx}`}
106
- className="pdf-page"
107
- style={{ height: PAGE_HEIGHT, position: "relative", overflow: "hidden" }}
108
- >
109
- {/* Header */}
110
- <div style={{ height: HEADER_HEIGHT }} className="flex-row dashboard-header">
111
- <div className="flex flex-column justify-center flex-1">
112
- <h2>{title}</h2>
113
- </div>
114
- <div className="flex flex-column justify-center">
115
- <img src={imgSrc} alt="logo" />
116
- </div>
117
- </div>
198
+ {/* Render paginated pages (unlimited) */}
199
+ {pageMap.length > 0
200
+ ? pageMap.map((indices, pageIdx) => (
201
+ <div
202
+ key={`page-${pageIdx}`}
203
+ className="pdf-page"
204
+ style={{ height: PAGE_HEIGHT, position: "relative", overflow: "hidden" }}
205
+ >
206
+ {/* Header */}
207
+ <div style={{ height: HEADER_HEIGHT }} className="flex-row dashboard-header">
208
+ <div className="flex flex-column justify-center flex-1">
209
+ <h2>{title}</h2>
210
+ </div>
211
+ <div className="flex flex-column justify-center">
212
+ <img src={imgSrc} alt="logo" />
213
+ </div>
214
+ </div>
118
215
 
119
- {/* Body */}
120
- <div
121
- className="pdf-body"
122
- style={{
123
- minHeight: CONTENT_HEIGHT,
124
- paddingTop: 0,
125
- paddingBottom: 0,
126
- }}
127
- >
128
- <div style={{ display: "flex", flexDirection: "column", gap: GAP_BETWEEN_BLOCKS }}>
129
- {indices.map((i) => (
130
- <Row key={`row-${i}`} widgets={config[i]} i={i} onChangeHeight={onChangeHeight} />
131
- ))}
132
- </div>
133
- </div>
216
+ {/* Body */}
217
+ <div className="pdf-body" style={{ minHeight: CONTENT_HEIGHT }}>
218
+ <div style={{ display: "flex", flexDirection: "column", gap: GAP_BETWEEN_BLOCKS }}>
219
+ {indices.map((i) => (
220
+ <Row key={`row-${i}`} widgets={expandedConfig[i]} i={i} onChangeHeight={onChangeHeight} />
221
+ ))}
222
+ </div>
223
+ </div>
134
224
 
135
- {/* Footer */}
136
- <div style={{ height: FOOTER_HEIGHT }} className="dashboard-footer flex-row">
137
- <div className="flex flex-column justify-center">
138
- <h5>{moment().format("DD MMM YYYY")}</h5>
139
- </div>
140
- <div className="flex flex-column justify-center">
141
- <div className="flex gap-2">
142
- <h5>
143
- User ID: <strong>{userId}</strong>
144
- </h5>
145
- <h5>
146
- Account ID: <strong>{accountId}</strong>
147
- </h5>
148
- <h5>
149
- Document ID: <strong>{documentId}</strong>
150
- </h5>
151
- <h5>
152
- Download ID: <strong>{downloadId}</strong>
153
- </h5>
225
+ {/* Footer */}
226
+ <div style={{ height: FOOTER_HEIGHT }} className="dashboard-footer flex-row">
227
+ <div className="flex flex-column justify-center">
228
+ <h5>{moment().format("DD MMM YYYY")}</h5>
229
+ </div>
230
+ <div className="flex flex-column justify-center">
231
+ <div className="flex gap-2">
232
+ <h5>User ID: <strong>{userId}</strong></h5>
233
+ <h5>Account ID: <strong>{accountId}</strong></h5>
234
+ <h5>Document ID: <strong>{documentId}</strong></h5>
235
+ <h5>Download ID: <strong>{downloadId}</strong></h5>
236
+ </div>
237
+ </div>
238
+ <div className="flex flex-column justify-center">
239
+ <h5>{pageIdx + 1}</h5>
240
+ </div>
154
241
  </div>
155
242
  </div>
156
- <div className="flex flex-column justify-center">
157
- <h5>{pageIdx + 1}</h5>
158
- </div>
159
- </div>
160
- </div>
161
- ))}
162
-
163
- {/* Optional: first pass "measurement layer" for instant sizes (kept visible).
164
- If you want to avoid double-render cost, keep as-is; if you want to hide it after pagination,
165
- you can track a 'measured' flag and conditionally render. */}
166
- {pageMap.length === 0 && (
167
- <div className="view-content">
168
- <div className="daf-analysis-layout">
169
- <div className="sections-cont">
170
- {config.map((widgets, i) => (
171
- <Row key={`measure-${i}`} widgets={widgets} i={i} onChangeHeight={onChangeHeight} />
172
- ))}
173
- </div>
174
- </div>
175
- </div>
176
- )}
243
+ ))
244
+ : MeasurementLayer}
177
245
  </div>
178
246
  );
179
247
  }
180
248
 
181
249
  PdfView.propTypes = {
182
- config: PropTypes.array,
250
+ config: PropTypes.arrayOf(
251
+ PropTypes.shape({
252
+ render: PropTypes.func.isRequired,
253
+ style: PropTypes.object,
254
+ priority: PropTypes.oneOf([1, 2, 3]),
255
+ keepWithNext: PropTypes.bool,
256
+ splittable: PropTypes.bool,
257
+ splitInto: PropTypes.func, // (maxHeightPx) => WidgetConfig[]
258
+ })
259
+ ),
183
260
  customClassName: PropTypes.any,
184
261
  title: PropTypes.string,
185
262
  imgSrc: PropTypes.string,