datastake-daf 0.6.423 → 0.6.424

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.
@@ -13305,12 +13305,41 @@ DAFFooter.propTypes = {
13305
13305
  const PAGE_HEIGHT = 1587;
13306
13306
  const FOOTER_HEIGHT = 70;
13307
13307
  const HEADER_HEIGHT = 100;
13308
- const PAGE_MARGIN_TOP = 20;
13309
- const PAGE_MARGIN_BOTTOM = 20;
13310
- const CONTENT_HEIGHT = 1200; // 1397px
13311
- const SECTION_GAP = 24;
13312
- const isHTMLElement = node => node instanceof HTMLElement;
13313
- function PdfView(_ref) {
13308
+ const CONTENT_HEIGHT_PER_PAGE = 1200; // Maximum content height per page
13309
+ const PAGE_TOP_MARGIN = 30; // Margin at the top of content on new pages
13310
+
13311
+ const Row = _ref => {
13312
+ let {
13313
+ widgets,
13314
+ i,
13315
+ onChangeHeight = () => {}
13316
+ } = _ref;
13317
+ const ref = React.useRef();
13318
+ const [height, setHeight] = React.useState(0);
13319
+ React.useEffect(() => {
13320
+ const observer = new ResizeObserver(entries => {
13321
+ for (const entry of entries) {
13322
+ setHeight(entry.contentRect.height);
13323
+ }
13324
+ });
13325
+ observer.observe(ref.current);
13326
+ return () => observer.disconnect();
13327
+ }, []);
13328
+ React.useEffect(() => {
13329
+ if (height) {
13330
+ onChangeHeight(i, {
13331
+ height,
13332
+ ref
13333
+ });
13334
+ }
13335
+ }, [height]);
13336
+ return /*#__PURE__*/jsxRuntime.jsx("section", {
13337
+ ref: ref,
13338
+ style: widgets.style,
13339
+ children: typeof widgets.render === 'function' ? widgets.render() : null
13340
+ });
13341
+ };
13342
+ function PdfView(_ref2) {
13314
13343
  let {
13315
13344
  config = [],
13316
13345
  customClassName,
@@ -13320,224 +13349,125 @@ function PdfView(_ref) {
13320
13349
  accountId = 'IDD-0000000',
13321
13350
  documentId = 'IDD-0000000',
13322
13351
  downloadId = 'DWL-00000123'
13323
- } = _ref;
13352
+ } = _ref2;
13353
+ const [sectionsConfig, setSectionsConfig] = React.useState({});
13324
13354
  const [pages, setPages] = React.useState([1]);
13325
- const contentRef = React.useRef(null);
13326
- const sectionsRef = React.useRef([]);
13327
- const resizeTimeoutRef = React.useRef(null);
13328
- const isCalculatingRef = React.useRef(false);
13329
- const resetPaginationStyles = React.useCallback(sections => {
13330
- sections.forEach(section => {
13331
- if (!section) return;
13332
- section.style.marginTop = '';
13333
- section.style.marginBottom = '';
13334
- section.style.pageBreakBefore = '';
13335
- section.style.breakBefore = '';
13336
- section.removeAttribute('data-pdf-page');
13337
-
13338
- // Reset all children
13339
- const allElements = section.querySelectorAll('*');
13340
- allElements.forEach(el => {
13341
- if (!isHTMLElement(el)) return;
13342
- el.style.marginTop = '';
13343
- el.style.marginBottom = '';
13344
- el.style.pageBreakBefore = '';
13345
- el.style.breakBefore = '';
13346
- el.removeAttribute('data-pdf-page');
13347
- });
13348
- });
13349
- }, []);
13350
- const getAllBreakableElements = React.useCallback(section => {
13351
- const elements = [];
13352
- const shouldInclude = el => {
13353
- if (!isHTMLElement(el)) return false;
13354
- const style = window.getComputedStyle(el);
13355
- if (style.display === 'inline' || style.display === 'contents') return false;
13356
- if (style.position === 'absolute' || style.position === 'fixed') return false;
13357
- if (el.offsetHeight === 0) return false;
13358
- return true;
13359
- };
13360
- const traverse = parent => {
13361
- Array.from(parent.children).forEach(child => {
13362
- if (shouldInclude(child)) {
13363
- elements.push(child);
13364
- traverse(child);
13365
- }
13355
+ const doSizing = React.useCallback(() => {
13356
+ const keys = Object.keys(sectionsConfig);
13357
+ let _pages = [1];
13358
+ let _page = 1;
13359
+ if (keys.length === config.length) {
13360
+ // Reset all margins and padding first
13361
+ keys.forEach(k => {
13362
+ const {
13363
+ ref
13364
+ } = sectionsConfig[k];
13365
+ ref.current.style.marginTop = '0px';
13366
+ ref.current.style.marginBottom = '0px';
13367
+ ref.current.style.paddingBottom = '0px';
13366
13368
  });
13367
- };
13368
- traverse(section);
13369
- return elements;
13370
- }, []);
13371
- const paginateContent = React.useCallback(() => {
13372
- // Prevent recursive calls
13373
- if (isCalculatingRef.current) return;
13374
- const sections = sectionsRef.current.filter(Boolean);
13375
- if (sections.length === 0) return;
13376
- isCalculatingRef.current = true;
13377
- resetPaginationStyles(sections);
13378
-
13379
- // Force layout recalc
13380
- sections.forEach(s => s.offsetHeight);
13381
- let currentPage = 1;
13382
- let currentPageHeight = 0;
13383
- sections.forEach((section, sectionIndex) => {
13384
- // Measure height after reset
13385
- const sectionHeight = section.offsetHeight;
13386
- const isFirstOnPage = currentPageHeight === 0;
13387
- const gapBefore = isFirstOnPage ? 0 : SECTION_GAP;
13388
- if (currentPageHeight + gapBefore + sectionHeight <= CONTENT_HEIGHT) {
13389
- // Fits in current page
13390
- section.setAttribute('data-pdf-page', currentPage.toString());
13391
- if (isFirstOnPage) {
13392
- // First item on page
13393
- if (currentPage === 1) {
13394
- // Very first section on first page - needs to be below header
13395
- section.style.marginTop = '0px'; // Container padding handles this
13396
- } else {
13397
- // First section on subsequent pages - no margin (container padding handles it)
13398
- section.style.marginTop = '0px';
13369
+ let currentPageHeight = 0; // Track height accumulated on current page
13370
+ const sectionGap = 24; // Gap between sections
13371
+
13372
+ keys.forEach((k, i) => {
13373
+ const {
13374
+ height,
13375
+ ref
13376
+ } = sectionsConfig[k];
13377
+ const isFirstSection = i === 0;
13378
+ const isLastSection = i === keys.length - 1;
13379
+
13380
+ // First section on first page needs header space
13381
+ if (isFirstSection) {
13382
+ ref.current.style.marginTop = "".concat(HEADER_HEIGHT, "px");
13383
+ currentPageHeight = 0; // Content height tracking starts fresh
13384
+ }
13385
+
13386
+ // Check if this section would exceed the page content limit
13387
+ const willExceedPageLimit = currentPageHeight + height > CONTENT_HEIGHT_PER_PAGE;
13388
+ if (willExceedPageLimit && !isFirstSection) {
13389
+ // Need to break to a new page
13390
+ _page += 1;
13391
+ _pages.push(_page);
13392
+
13393
+ // Calculate remaining space on current page
13394
+ const remainingSpace = PAGE_HEIGHT - currentPageHeight - HEADER_HEIGHT - FOOTER_HEIGHT;
13395
+
13396
+ // Add margin to previous section to push current section to next page
13397
+ if (sectionsConfig[keys[i - 1]]) {
13398
+ const {
13399
+ ref: prevRef
13400
+ } = sectionsConfig[keys[i - 1]];
13401
+ prevRef.current.style.marginBottom = "".concat(remainingSpace, "px");
13399
13402
  }
13403
+
13404
+ // Position this section at the top of the new page
13405
+ ref.current.style.marginTop = "".concat(HEADER_HEIGHT + PAGE_TOP_MARGIN, "px");
13406
+
13407
+ // Reset page height counter for new page
13408
+ currentPageHeight = height + sectionGap;
13400
13409
  } else {
13401
- // Not first item on page - add gap
13402
- section.style.marginTop = "".concat(SECTION_GAP, "px");
13410
+ // Section fits on current page
13411
+ currentPageHeight += height + sectionGap;
13403
13412
  }
13404
- currentPageHeight += gapBefore + sectionHeight;
13405
- } else {
13406
- // Doesn't fit - need to move to next page
13407
- const remainingSpace = CONTENT_HEIGHT - currentPageHeight;
13408
-
13409
- // Calculate margin needed to push this section to the next page
13410
- // remainingSpace = space left on current page
13411
- // Then we need to skip: footer margin + footer + header margin + header
13412
- const pushMargin = remainingSpace + PAGE_MARGIN_BOTTOM + FOOTER_HEIGHT + PAGE_MARGIN_TOP + HEADER_HEIGHT;
13413
-
13414
- // Move entire section to next page
13415
- currentPage += 1;
13416
- section.setAttribute('data-pdf-page', currentPage.toString());
13417
- section.style.pageBreakBefore = 'always';
13418
- section.style.breakBefore = 'page';
13419
- section.style.marginTop = "".concat(pushMargin, "px");
13420
-
13421
- // Start fresh height counter for new page
13422
- currentPageHeight = sectionHeight;
13423
-
13424
- // Check if section is too tall and needs internal breaks
13425
- if (sectionHeight > CONTENT_HEIGHT) {
13426
- // Try to break within section
13427
- const innerElements = getAllBreakableElements(section);
13428
- let pageHeightInSection = 0;
13429
- let sectionPage = currentPage;
13430
- for (const el of innerElements) {
13431
- const rect = el.getBoundingClientRect();
13432
- const sectionRect = section.getBoundingClientRect();
13433
- const relativeTop = rect.top - sectionRect.top;
13434
- const elHeight = rect.height;
13435
-
13436
- // Check if this element would exceed the page
13437
- if (pageHeightInSection + elHeight > CONTENT_HEIGHT && relativeTop > 50) {
13438
- // Calculate remaining space on this page within the section
13439
- const remainingInSection = CONTENT_HEIGHT - pageHeightInSection;
13440
- const pushMarginInner = remainingInSection + PAGE_MARGIN_BOTTOM + FOOTER_HEIGHT + PAGE_MARGIN_TOP + HEADER_HEIGHT;
13441
- sectionPage += 1;
13442
- el.setAttribute('data-pdf-page', sectionPage.toString());
13443
- el.style.pageBreakBefore = 'always';
13444
- el.style.breakBefore = 'page';
13445
- el.style.marginTop = "".concat(pushMarginInner, "px");
13446
-
13447
- // Reset page height for new page within section
13448
- pageHeightInSection = elHeight;
13449
- } else {
13450
- pageHeightInSection += elHeight;
13451
- }
13452
- }
13453
13413
 
13454
- // Update current page if we created additional pages
13455
- if (sectionPage > currentPage) {
13456
- currentPage = sectionPage;
13457
- currentPageHeight = pageHeightInSection;
13458
- }
13414
+ // Add padding to last section
13415
+ if (isLastSection) {
13416
+ ref.current.style.paddingBottom = "".concat(PAGE_TOP_MARGIN, "px");
13459
13417
  }
13460
- }
13461
- });
13462
- setPages(Array.from({
13463
- length: currentPage
13464
- }, (_, idx) => idx + 1));
13465
-
13466
- // Reset flag after a brief delay to allow next calculation
13467
- setTimeout(() => {
13468
- isCalculatingRef.current = false;
13469
- }, 100);
13470
- }, [getAllBreakableElements, resetPaginationStyles]);
13471
- React.useLayoutEffect(() => {
13472
- // Use requestAnimationFrame to ensure DOM is painted
13473
- const rafId = requestAnimationFrame(() => {
13474
- paginateContent();
13475
- });
13476
- return () => cancelAnimationFrame(rafId);
13477
- }, [paginateContent, config]);
13418
+ });
13419
+ setPages(_pages);
13420
+ }
13421
+ }, [sectionsConfig, config.length]);
13478
13422
  React.useEffect(() => {
13479
- const sections = sectionsRef.current.filter(Boolean);
13480
- if (sections.length === 0) return undefined;
13481
- const observer = new ResizeObserver(() => {
13482
- // Debounce the pagination calculation
13483
- if (resizeTimeoutRef.current) {
13484
- clearTimeout(resizeTimeoutRef.current);
13485
- }
13486
- resizeTimeoutRef.current = setTimeout(() => {
13487
- // Use requestAnimationFrame to avoid ResizeObserver loop warning
13488
- requestAnimationFrame(() => {
13489
- paginateContent();
13490
- });
13491
- }, 150);
13492
- });
13493
- sections.forEach(section => observer.observe(section));
13494
- return () => {
13495
- observer.disconnect();
13496
- if (resizeTimeoutRef.current) {
13497
- clearTimeout(resizeTimeoutRef.current);
13498
- }
13499
- };
13500
- }, [paginateContent, config.length]);
13423
+ doSizing();
13424
+ }, [doSizing]);
13425
+ const onChangeHeight = React.useCallback((index, conf) => {
13426
+ setSectionsConfig(prev => _objectSpread2(_objectSpread2({}, prev), {}, {
13427
+ [index]: conf
13428
+ }));
13429
+ }, []);
13501
13430
  const contClassName = formatClassname(['daf-analysis daf-pdf-view', customClassName]);
13502
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
13503
- className: contClassName,
13504
- style: {
13505
- position: 'relative',
13506
- minHeight: "".concat(PAGE_HEIGHT, "px")
13507
- },
13508
- children: [/*#__PURE__*/jsxRuntime.jsx("div", {
13431
+ const renderDashboard = React.useCallback(() => {
13432
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
13509
13433
  className: "view-content",
13510
13434
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
13511
13435
  className: "daf-analysis-layout",
13512
13436
  children: /*#__PURE__*/jsxRuntime.jsx("div", {
13513
13437
  className: "sections-cont",
13514
- ref: contentRef,
13515
- "data-pdf-content-root": "true",
13516
- style: {
13517
- marginTop: "".concat(HEADER_HEIGHT + PAGE_MARGIN_TOP, "px"),
13518
- // paddingBottom: `${FOOTER_HEIGHT + PAGE_MARGIN_BOTTOM}px !important`,
13519
- position: 'relative'
13520
- },
13521
- children: config.map((widgets, index) => /*#__PURE__*/jsxRuntime.jsx("section", {
13522
- ref: el => {
13523
- sectionsRef.current[index] = el;
13524
- },
13525
- style: widgets.style,
13526
- "data-pdf-section": "true",
13527
- children: typeof widgets.render === 'function' ? widgets.render() : null
13528
- }, "dashboard-section-".concat(index + 1)))
13438
+ children: config.map((widgets, i) => /*#__PURE__*/jsxRuntime.jsx(Row, {
13439
+ widgets: widgets,
13440
+ i: i,
13441
+ onChangeHeight: onChangeHeight
13442
+ }, "dashboard-sections=".concat(i + 1)))
13529
13443
  })
13530
13444
  })
13531
- }), pages.map(page => /*#__PURE__*/jsxRuntime.jsxs(React.Fragment, {
13445
+ });
13446
+ }, [config, onChangeHeight]);
13447
+
13448
+ // <div className="daf-analysis">
13449
+ // <Header title={t('Dashboard Title')} />
13450
+
13451
+ // <div className="content">
13452
+ // <div className="view-content">
13453
+ // <div className="daf-analysis-layout">
13454
+ // <div className='sections-cont w-pt'>
13455
+ // <section>
13456
+
13457
+ return /*#__PURE__*/jsxRuntime.jsxs("div", {
13458
+ className: contClassName,
13459
+ style: {
13460
+ position: 'relative'
13461
+ },
13462
+ children: [renderDashboard(), pages.map(page => /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
13532
13463
  children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
13533
13464
  style: {
13534
- top: (page - 1) * PAGE_HEIGHT + PAGE_MARGIN_TOP,
13465
+ top: (page - 1) * PAGE_HEIGHT,
13535
13466
  width: '100%',
13536
- height: HEADER_HEIGHT,
13467
+ height: HEADER_HEIGHT - 24,
13537
13468
  position: 'absolute',
13538
13469
  left: 0,
13539
- zIndex: 1000000,
13540
- pointerEvents: 'none'
13470
+ zIndex: 1000000
13541
13471
  },
13542
13472
  className: "flex-row dashboard-header",
13543
13473
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
@@ -13552,15 +13482,14 @@ function PdfView(_ref) {
13552
13482
  alt: "logo"
13553
13483
  })
13554
13484
  })]
13555
- }), /*#__PURE__*/jsxRuntime.jsxs("div", {
13485
+ }, "headers-".concat(page)), /*#__PURE__*/jsxRuntime.jsxs("div", {
13556
13486
  style: {
13557
- top: page * PAGE_HEIGHT - FOOTER_HEIGHT - PAGE_MARGIN_BOTTOM,
13487
+ top: page * PAGE_HEIGHT - FOOTER_HEIGHT,
13558
13488
  width: '100%',
13559
13489
  height: FOOTER_HEIGHT,
13560
13490
  position: 'absolute',
13561
13491
  left: 0,
13562
- zIndex: 1000000,
13563
- pointerEvents: 'none'
13492
+ zIndex: 1000000
13564
13493
  },
13565
13494
  className: "dashboard-footer flex-row",
13566
13495
  children: [/*#__PURE__*/jsxRuntime.jsx("div", {
@@ -13596,8 +13525,8 @@ function PdfView(_ref) {
13596
13525
  children: page
13597
13526
  })
13598
13527
  })]
13599
- })]
13600
- }, "pdf-decor-".concat(page)))]
13528
+ }, "footers-".concat(page))]
13529
+ }))]
13601
13530
  });
13602
13531
  }
13603
13532
  PdfView.propTypes = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "datastake-daf",
3
- "version": "0.6.423",
3
+ "version": "0.6.424",
4
4
  "dependencies": {
5
5
  "@ant-design/icons": "^5.2.5",
6
6
  "@antv/g2": "^5.1.1",
@@ -1,17 +1,42 @@
1
1
  import moment from "moment";
2
2
  import PropTypes from 'prop-types';
3
- import { Fragment, useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
4
  import { formatClassname } from "../../../../../helpers/ClassesHelper";
5
5
 
6
6
  const PAGE_HEIGHT = 1587;
7
7
  const FOOTER_HEIGHT = 70;
8
8
  const HEADER_HEIGHT = 100;
9
- const PAGE_MARGIN_TOP = 20;
10
- const PAGE_MARGIN_BOTTOM = 20;
11
- const CONTENT_HEIGHT = 1200; // 1397px
12
- const SECTION_GAP = 24;
9
+ const CONTENT_HEIGHT_PER_PAGE = 1200; // Maximum content height per page
10
+ const PAGE_TOP_MARGIN = 30; // Margin at the top of content on new pages
13
11
 
14
- const isHTMLElement = (node) => node instanceof HTMLElement;
12
+ const Row = ({ widgets, i, onChangeHeight = () => { } }) => {
13
+ const ref = useRef();
14
+ const [height, setHeight] = useState(0);
15
+
16
+ useEffect(() => {
17
+ const observer = new ResizeObserver((entries) => {
18
+ for (const entry of entries) {
19
+ setHeight(entry.contentRect.height);
20
+ }
21
+ });
22
+
23
+ observer.observe(ref.current);
24
+
25
+ return () => observer.disconnect();
26
+ }, []);
27
+
28
+ useEffect(() => {
29
+ if (height) {
30
+ onChangeHeight(i, { height, ref });
31
+ }
32
+ }, [height])
33
+
34
+ return (
35
+ <section ref={ref} style={widgets.style}>
36
+ {typeof widgets.render === 'function' ? widgets.render() : null}
37
+ </section>
38
+ )
39
+ };
15
40
 
16
41
  export default function PdfView({
17
42
  config = [],
@@ -23,251 +48,120 @@ export default function PdfView({
23
48
  documentId = 'IDD-0000000',
24
49
  downloadId = 'DWL-00000123',
25
50
  }) {
51
+ const [sectionsConfig, setSectionsConfig] = useState({});
26
52
  const [pages, setPages] = useState([1]);
27
- const contentRef = useRef(null);
28
- const sectionsRef = useRef([]);
29
- const resizeTimeoutRef = useRef(null);
30
- const isCalculatingRef = useRef(false);
31
53
 
32
- const resetPaginationStyles = useCallback((sections) => {
33
- sections.forEach((section) => {
34
- if (!section) return;
35
- section.style.marginTop = '';
36
- section.style.marginBottom = '';
37
- section.style.pageBreakBefore = '';
38
- section.style.breakBefore = '';
39
- section.removeAttribute('data-pdf-page');
40
-
41
- // Reset all children
42
- const allElements = section.querySelectorAll('*');
43
- allElements.forEach((el) => {
44
- if (!isHTMLElement(el)) return;
45
- el.style.marginTop = '';
46
- el.style.marginBottom = '';
47
- el.style.pageBreakBefore = '';
48
- el.style.breakBefore = '';
49
- el.removeAttribute('data-pdf-page');
54
+ const doSizing = useCallback(() => {
55
+ const keys = Object.keys(sectionsConfig);
56
+ let _pages = [1];
57
+ let _page = 1;
58
+
59
+ if (keys.length === config.length) {
60
+ // Reset all margins and padding first
61
+ keys.forEach(k => {
62
+ const { ref } = sectionsConfig[k];
63
+ ref.current.style.marginTop = '0px';
64
+ ref.current.style.marginBottom = '0px';
65
+ ref.current.style.paddingBottom = '0px';
50
66
  });
51
- });
52
- }, []);
53
-
54
- const getAllBreakableElements = useCallback((section) => {
55
- const elements = [];
56
-
57
- const shouldInclude = (el) => {
58
- if (!isHTMLElement(el)) return false;
59
- const style = window.getComputedStyle(el);
60
- if (style.display === 'inline' || style.display === 'contents') return false;
61
- if (style.position === 'absolute' || style.position === 'fixed') return false;
62
- if (el.offsetHeight === 0) return false;
63
- return true;
64
- };
65
67
 
66
- const traverse = (parent) => {
67
- Array.from(parent.children).forEach((child) => {
68
- if (shouldInclude(child)) {
69
- elements.push(child);
70
- traverse(child);
71
- }
72
- });
73
- };
68
+ let currentPageHeight = 0; // Track height accumulated on current page
69
+ const sectionGap = 24; // Gap between sections
74
70
 
75
- traverse(section);
76
- return elements;
77
- }, []);
71
+ keys.forEach((k, i) => {
72
+ const { height, ref } = sectionsConfig[k];
73
+ const isFirstSection = i === 0;
74
+ const isLastSection = i === keys.length - 1;
78
75
 
79
- const paginateContent = useCallback(() => {
80
- // Prevent recursive calls
81
- if (isCalculatingRef.current) return;
82
-
83
- const sections = sectionsRef.current.filter(Boolean);
84
- if (sections.length === 0) return;
85
-
86
- isCalculatingRef.current = true;
87
-
88
- resetPaginationStyles(sections);
76
+ // First section on first page needs header space
77
+ if (isFirstSection) {
78
+ ref.current.style.marginTop = `${HEADER_HEIGHT}px`;
79
+ currentPageHeight = 0; // Content height tracking starts fresh
80
+ }
89
81
 
90
- // Force layout recalc
91
- sections.forEach(s => s.offsetHeight);
82
+ // Check if this section would exceed the page content limit
83
+ const willExceedPageLimit = currentPageHeight + height > CONTENT_HEIGHT_PER_PAGE;
92
84
 
93
- let currentPage = 1;
94
- let currentPageHeight = 0;
95
- const breaks = [];
85
+ if (willExceedPageLimit && !isFirstSection) {
86
+ // Need to break to a new page
87
+ _page += 1;
88
+ _pages.push(_page);
96
89
 
97
- sections.forEach((section, sectionIndex) => {
98
- // Measure height after reset
99
- const sectionHeight = section.offsetHeight;
100
- const isFirstOnPage = currentPageHeight === 0;
101
- const gapBefore = isFirstOnPage ? 0 : SECTION_GAP;
102
-
103
- if (currentPageHeight + gapBefore + sectionHeight <= CONTENT_HEIGHT) {
104
- // Fits in current page
105
- section.setAttribute('data-pdf-page', currentPage.toString());
106
-
107
- if (isFirstOnPage) {
108
- // First item on page
109
- if (currentPage === 1) {
110
- // Very first section on first page - needs to be below header
111
- section.style.marginTop = '0px'; // Container padding handles this
112
- } else {
113
- // First section on subsequent pages - no margin (container padding handles it)
114
- section.style.marginTop = '0px';
115
- }
116
- } else {
117
- // Not first item on page - add gap
118
- section.style.marginTop = `${SECTION_GAP}px`;
119
- }
120
- currentPageHeight += gapBefore + sectionHeight;
121
- } else {
122
- // Doesn't fit - need to move to next page
123
- const remainingSpace = CONTENT_HEIGHT - currentPageHeight;
124
-
125
- // Calculate margin needed to push this section to the next page
126
- // remainingSpace = space left on current page
127
- // Then we need to skip: footer margin + footer + header margin + header
128
- const pushMargin = remainingSpace + PAGE_MARGIN_BOTTOM + FOOTER_HEIGHT + PAGE_MARGIN_TOP + HEADER_HEIGHT;
129
-
130
- // Move entire section to next page
131
- currentPage += 1;
132
- breaks.push({ section, type: 'section', page: currentPage });
133
- section.setAttribute('data-pdf-page', currentPage.toString());
134
- section.style.pageBreakBefore = 'always';
135
- section.style.breakBefore = 'page';
136
- section.style.marginTop = `${pushMargin}px`;
137
-
138
- // Start fresh height counter for new page
139
- currentPageHeight = sectionHeight;
140
-
141
- // Check if section is too tall and needs internal breaks
142
- if (sectionHeight > CONTENT_HEIGHT) {
143
- // Try to break within section
144
- const innerElements = getAllBreakableElements(section);
145
- let pageHeightInSection = 0;
146
- let sectionPage = currentPage;
90
+ // Calculate remaining space on current page
91
+ const remainingSpace = PAGE_HEIGHT - currentPageHeight - HEADER_HEIGHT - FOOTER_HEIGHT;
147
92
 
148
- for (const el of innerElements) {
149
- const rect = el.getBoundingClientRect();
150
- const sectionRect = section.getBoundingClientRect();
151
- const relativeTop = rect.top - sectionRect.top;
152
- const elHeight = rect.height;
153
-
154
- // Check if this element would exceed the page
155
- if (pageHeightInSection + elHeight > CONTENT_HEIGHT && relativeTop > 50) {
156
- // Calculate remaining space on this page within the section
157
- const remainingInSection = CONTENT_HEIGHT - pageHeightInSection;
158
- const pushMarginInner = remainingInSection + PAGE_MARGIN_BOTTOM + FOOTER_HEIGHT + PAGE_MARGIN_TOP + HEADER_HEIGHT;
159
-
160
- sectionPage += 1;
161
- breaks.push({ element: el, type: 'inner', page: sectionPage });
162
- el.setAttribute('data-pdf-page', sectionPage.toString());
163
- el.style.pageBreakBefore = 'always';
164
- el.style.breakBefore = 'page';
165
- el.style.marginTop = `${pushMarginInner}px`;
166
-
167
- // Reset page height for new page within section
168
- pageHeightInSection = elHeight;
169
- } else {
170
- pageHeightInSection += elHeight;
171
- }
93
+ // Add margin to previous section to push current section to next page
94
+ if (sectionsConfig[keys[i - 1]]) {
95
+ const { ref: prevRef } = sectionsConfig[keys[i - 1]];
96
+ prevRef.current.style.marginBottom = `${remainingSpace}px`;
172
97
  }
98
+
99
+ // Position this section at the top of the new page
100
+ ref.current.style.marginTop = `${HEADER_HEIGHT + PAGE_TOP_MARGIN}px`;
173
101
 
174
- // Update current page if we created additional pages
175
- if (sectionPage > currentPage) {
176
- currentPage = sectionPage;
177
- currentPageHeight = pageHeightInSection;
178
- }
102
+ // Reset page height counter for new page
103
+ currentPageHeight = height + sectionGap;
104
+ } else {
105
+ // Section fits on current page
106
+ currentPageHeight += height + sectionGap;
179
107
  }
180
- }
181
- });
182
108
 
183
- setPages(Array.from({ length: currentPage }, (_, idx) => idx + 1));
184
-
185
- // Reset flag after a brief delay to allow next calculation
186
- setTimeout(() => {
187
- isCalculatingRef.current = false;
188
- }, 100);
189
- }, [getAllBreakableElements, resetPaginationStyles]);
109
+ // Add padding to last section
110
+ if (isLastSection) {
111
+ ref.current.style.paddingBottom = `${PAGE_TOP_MARGIN}px`;
112
+ }
113
+ });
190
114
 
191
- useLayoutEffect(() => {
192
- // Use requestAnimationFrame to ensure DOM is painted
193
- const rafId = requestAnimationFrame(() => {
194
- paginateContent();
195
- });
196
-
197
- return () => cancelAnimationFrame(rafId);
198
- }, [paginateContent, config]);
115
+ setPages(_pages);
116
+ }
117
+ }, [sectionsConfig, config.length]);
199
118
 
200
119
  useEffect(() => {
201
- const sections = sectionsRef.current.filter(Boolean);
202
- if (sections.length === 0) return undefined;
203
-
204
- const observer = new ResizeObserver(() => {
205
- // Debounce the pagination calculation
206
- if (resizeTimeoutRef.current) {
207
- clearTimeout(resizeTimeoutRef.current);
208
- }
209
-
210
- resizeTimeoutRef.current = setTimeout(() => {
211
- // Use requestAnimationFrame to avoid ResizeObserver loop warning
212
- requestAnimationFrame(() => {
213
- paginateContent();
214
- });
215
- }, 150);
216
- });
217
-
218
- sections.forEach(section => observer.observe(section));
120
+ doSizing();
121
+ }, [doSizing]);
219
122
 
220
- return () => {
221
- observer.disconnect();
222
- if (resizeTimeoutRef.current) {
223
- clearTimeout(resizeTimeoutRef.current);
224
- }
225
- };
226
- }, [paginateContent, config.length]);
123
+ const onChangeHeight = useCallback((index, conf) => {
124
+ setSectionsConfig((prev) => ({ ...prev, [index]: conf }))
125
+ }, []);
227
126
 
228
127
  const contClassName = formatClassname(['daf-analysis daf-pdf-view', customClassName]);
229
128
 
230
- return (
231
- <div className={contClassName} style={{ position: 'relative', minHeight: `${PAGE_HEIGHT}px` }}>
129
+ const renderDashboard = useCallback(() => {
130
+ return (
232
131
  <div className="view-content">
233
132
  <div className="daf-analysis-layout">
234
- <div
235
- className='sections-cont'
236
- ref={contentRef}
237
- data-pdf-content-root="true"
238
- style={{
239
- marginTop: `${HEADER_HEIGHT + PAGE_MARGIN_TOP}px`,
240
- // paddingBottom: `${FOOTER_HEIGHT + PAGE_MARGIN_BOTTOM}px !important`,
241
- position: 'relative',
242
- }}
243
- >
244
- {config.map((widgets, index) => (
245
- <section
246
- key={`dashboard-section-${index + 1}`}
247
- ref={(el) => {
248
- sectionsRef.current[index] = el;
249
- }}
250
- style={widgets.style}
251
- data-pdf-section="true"
252
- >
253
- {typeof widgets.render === 'function' ? widgets.render() : null}
254
- </section>
133
+ <div className='sections-cont'>
134
+ {config.map((widgets, i) => (
135
+ <Row
136
+ widgets={widgets}
137
+ key={`dashboard-sections=${i + 1}`}
138
+ i={i}
139
+ onChangeHeight={onChangeHeight}
140
+ />
255
141
  ))}
256
142
  </div>
257
143
  </div>
258
144
  </div>
145
+ );
146
+ }, [config, onChangeHeight]);
147
+
148
+ // <div className="daf-analysis">
149
+ // <Header title={t('Dashboard Title')} />
150
+
151
+ // <div className="content">
152
+ // <div className="view-content">
153
+ // <div className="daf-analysis-layout">
154
+ // <div className='sections-cont w-pt'>
155
+ // <section>
156
+
157
+ return (
158
+ <div className={contClassName} style={{ position: 'relative' }}>
159
+ {renderDashboard()}
259
160
  {pages.map((page) => (
260
- <Fragment key={`pdf-decor-${page}`}>
161
+ <>
261
162
  <div
262
- style={{
263
- top: ((page - 1) * PAGE_HEIGHT) + PAGE_MARGIN_TOP,
264
- width: '100%',
265
- height: HEADER_HEIGHT,
266
- position: 'absolute',
267
- left: 0,
268
- zIndex: 1000000,
269
- pointerEvents: 'none'
270
- }}
163
+ style={{ top: ((page - 1) * PAGE_HEIGHT), width: '100%', height: HEADER_HEIGHT - 24, position: 'absolute', left: 0, zIndex: 1000000 }}
164
+ key={`headers-${page}`}
271
165
  className="flex-row dashboard-header"
272
166
  >
273
167
  <div className="flex flex-column justify-center flex-1">
@@ -278,15 +172,8 @@ export default function PdfView({
278
172
  </div>
279
173
  </div>
280
174
  <div
281
- style={{
282
- top: (page * PAGE_HEIGHT) - FOOTER_HEIGHT - PAGE_MARGIN_BOTTOM,
283
- width: '100%',
284
- height: FOOTER_HEIGHT,
285
- position: 'absolute',
286
- left: 0,
287
- zIndex: 1000000,
288
- pointerEvents: 'none'
289
- }}
175
+ style={{ top: (page * PAGE_HEIGHT) - FOOTER_HEIGHT, width: '100%', height: FOOTER_HEIGHT, position: 'absolute', left: 0, zIndex: 1000000 }}
176
+ key={`footers-${page}`}
290
177
  className="dashboard-footer flex-row"
291
178
  >
292
179
  <div className="flex flex-column justify-center">
@@ -320,7 +207,7 @@ export default function PdfView({
320
207
  <h5>{page}</h5>
321
208
  </div>
322
209
  </div>
323
- </Fragment>
210
+ </>
324
211
  ))}
325
212
  </div>
326
213
  );