datastake-daf 0.6.421 → 0.6.423
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/components/index.js
CHANGED
|
@@ -13303,41 +13303,14 @@ DAFFooter.propTypes = {
|
|
|
13303
13303
|
};
|
|
13304
13304
|
|
|
13305
13305
|
const PAGE_HEIGHT = 1587;
|
|
13306
|
-
// margin-top: 20, bottom: 20;
|
|
13307
13306
|
const FOOTER_HEIGHT = 70;
|
|
13308
13307
|
const HEADER_HEIGHT = 100;
|
|
13309
|
-
const
|
|
13310
|
-
|
|
13311
|
-
|
|
13312
|
-
|
|
13313
|
-
|
|
13314
|
-
|
|
13315
|
-
const ref = React.useRef();
|
|
13316
|
-
const [height, setHeight] = React.useState(0);
|
|
13317
|
-
React.useEffect(() => {
|
|
13318
|
-
const observer = new ResizeObserver(entries => {
|
|
13319
|
-
for (const entry of entries) {
|
|
13320
|
-
setHeight(entry.contentRect.height);
|
|
13321
|
-
}
|
|
13322
|
-
});
|
|
13323
|
-
observer.observe(ref.current);
|
|
13324
|
-
return () => observer.disconnect();
|
|
13325
|
-
}, []);
|
|
13326
|
-
React.useEffect(() => {
|
|
13327
|
-
if (height) {
|
|
13328
|
-
onChangeHeight(i, {
|
|
13329
|
-
height,
|
|
13330
|
-
ref
|
|
13331
|
-
});
|
|
13332
|
-
}
|
|
13333
|
-
}, [height]);
|
|
13334
|
-
return /*#__PURE__*/jsxRuntime.jsx("section", {
|
|
13335
|
-
ref: ref,
|
|
13336
|
-
style: widgets.style,
|
|
13337
|
-
children: typeof widgets.render === 'function' ? widgets.render() : null
|
|
13338
|
-
});
|
|
13339
|
-
};
|
|
13340
|
-
function PdfView(_ref2) {
|
|
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) {
|
|
13341
13314
|
let {
|
|
13342
13315
|
config = [],
|
|
13343
13316
|
customClassName,
|
|
@@ -13347,105 +13320,224 @@ function PdfView(_ref2) {
|
|
|
13347
13320
|
accountId = 'IDD-0000000',
|
|
13348
13321
|
documentId = 'IDD-0000000',
|
|
13349
13322
|
downloadId = 'DWL-00000123'
|
|
13350
|
-
} =
|
|
13351
|
-
const [sectionsConfig, setSectionsConfig] = React.useState({});
|
|
13323
|
+
} = _ref;
|
|
13352
13324
|
const [pages, setPages] = React.useState([1]);
|
|
13353
|
-
const
|
|
13354
|
-
|
|
13355
|
-
|
|
13356
|
-
|
|
13357
|
-
|
|
13358
|
-
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
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');
|
|
13365
13347
|
});
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
|
|
13370
|
-
|
|
13371
|
-
|
|
13372
|
-
|
|
13373
|
-
|
|
13374
|
-
|
|
13375
|
-
|
|
13376
|
-
|
|
13377
|
-
|
|
13378
|
-
|
|
13379
|
-
|
|
13380
|
-
|
|
13381
|
-
|
|
13382
|
-
|
|
13383
|
-
|
|
13384
|
-
|
|
13385
|
-
|
|
13386
|
-
|
|
13387
|
-
|
|
13388
|
-
|
|
13389
|
-
|
|
13390
|
-
|
|
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
|
+
}
|
|
13366
|
+
});
|
|
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';
|
|
13391
13399
|
}
|
|
13392
13400
|
} else {
|
|
13393
|
-
|
|
13401
|
+
// Not first item on page - add gap
|
|
13402
|
+
section.style.marginTop = "".concat(SECTION_GAP, "px");
|
|
13394
13403
|
}
|
|
13395
|
-
|
|
13396
|
-
}
|
|
13397
|
-
|
|
13398
|
-
|
|
13399
|
-
|
|
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
|
+
|
|
13454
|
+
// Update current page if we created additional pages
|
|
13455
|
+
if (sectionPage > currentPage) {
|
|
13456
|
+
currentPage = sectionPage;
|
|
13457
|
+
currentPageHeight = pageHeightInSection;
|
|
13458
|
+
}
|
|
13459
|
+
}
|
|
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]);
|
|
13400
13478
|
React.useEffect(() => {
|
|
13401
|
-
|
|
13402
|
-
|
|
13403
|
-
|
|
13404
|
-
|
|
13405
|
-
|
|
13406
|
-
|
|
13407
|
-
|
|
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]);
|
|
13408
13501
|
const contClassName = formatClassname(['daf-analysis daf-pdf-view', customClassName]);
|
|
13409
|
-
|
|
13410
|
-
|
|
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", {
|
|
13411
13509
|
className: "view-content",
|
|
13412
13510
|
children: /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
13413
13511
|
className: "daf-analysis-layout",
|
|
13414
13512
|
children: /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
13415
13513
|
className: "sections-cont",
|
|
13416
|
-
|
|
13417
|
-
|
|
13418
|
-
|
|
13419
|
-
|
|
13420
|
-
|
|
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)))
|
|
13421
13529
|
})
|
|
13422
13530
|
})
|
|
13423
|
-
})
|
|
13424
|
-
}, [config, onChangeHeight]);
|
|
13425
|
-
|
|
13426
|
-
// <div className="daf-analysis">
|
|
13427
|
-
// <Header title={t('Dashboard Title')} />
|
|
13428
|
-
|
|
13429
|
-
// <div className="content">
|
|
13430
|
-
// <div className="view-content">
|
|
13431
|
-
// <div className="daf-analysis-layout">
|
|
13432
|
-
// <div className='sections-cont w-pt'>
|
|
13433
|
-
// <section>
|
|
13434
|
-
|
|
13435
|
-
return /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
13436
|
-
className: contClassName,
|
|
13437
|
-
style: {
|
|
13438
|
-
position: 'relative'
|
|
13439
|
-
},
|
|
13440
|
-
children: [renderDashboard(), pages.map(page => /*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
13531
|
+
}), pages.map(page => /*#__PURE__*/jsxRuntime.jsxs(React.Fragment, {
|
|
13441
13532
|
children: [/*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
13442
13533
|
style: {
|
|
13443
|
-
top: (page - 1) * PAGE_HEIGHT,
|
|
13534
|
+
top: (page - 1) * PAGE_HEIGHT + PAGE_MARGIN_TOP,
|
|
13444
13535
|
width: '100%',
|
|
13445
|
-
height: HEADER_HEIGHT
|
|
13536
|
+
height: HEADER_HEIGHT,
|
|
13446
13537
|
position: 'absolute',
|
|
13447
13538
|
left: 0,
|
|
13448
|
-
zIndex: 1000000
|
|
13539
|
+
zIndex: 1000000,
|
|
13540
|
+
pointerEvents: 'none'
|
|
13449
13541
|
},
|
|
13450
13542
|
className: "flex-row dashboard-header",
|
|
13451
13543
|
children: [/*#__PURE__*/jsxRuntime.jsx("div", {
|
|
@@ -13460,14 +13552,15 @@ function PdfView(_ref2) {
|
|
|
13460
13552
|
alt: "logo"
|
|
13461
13553
|
})
|
|
13462
13554
|
})]
|
|
13463
|
-
}
|
|
13555
|
+
}), /*#__PURE__*/jsxRuntime.jsxs("div", {
|
|
13464
13556
|
style: {
|
|
13465
|
-
top: page * PAGE_HEIGHT - FOOTER_HEIGHT,
|
|
13557
|
+
top: page * PAGE_HEIGHT - FOOTER_HEIGHT - PAGE_MARGIN_BOTTOM,
|
|
13466
13558
|
width: '100%',
|
|
13467
13559
|
height: FOOTER_HEIGHT,
|
|
13468
13560
|
position: 'absolute',
|
|
13469
13561
|
left: 0,
|
|
13470
|
-
zIndex: 1000000
|
|
13562
|
+
zIndex: 1000000,
|
|
13563
|
+
pointerEvents: 'none'
|
|
13471
13564
|
},
|
|
13472
13565
|
className: "dashboard-footer flex-row",
|
|
13473
13566
|
children: [/*#__PURE__*/jsxRuntime.jsx("div", {
|
|
@@ -13503,8 +13596,8 @@ function PdfView(_ref2) {
|
|
|
13503
13596
|
children: page
|
|
13504
13597
|
})
|
|
13505
13598
|
})]
|
|
13506
|
-
}
|
|
13507
|
-
}))]
|
|
13599
|
+
})]
|
|
13600
|
+
}, "pdf-decor-".concat(page)))]
|
|
13508
13601
|
});
|
|
13509
13602
|
}
|
|
13510
13603
|
PdfView.propTypes = {
|
package/package.json
CHANGED
|
@@ -189,5 +189,15 @@ export const Primary = {
|
|
|
189
189
|
},
|
|
190
190
|
],
|
|
191
191
|
},
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
render: (args) => (
|
|
193
|
+
<div style={{
|
|
194
|
+
height: '100vh',
|
|
195
|
+
overflowY: 'auto',
|
|
196
|
+
background: "#f8f8f8",
|
|
197
|
+
padding: "20px",
|
|
198
|
+
}}
|
|
199
|
+
>
|
|
200
|
+
<PdfView {...args} />
|
|
201
|
+
</div>
|
|
202
|
+
),
|
|
203
|
+
};
|
|
@@ -1,41 +1,17 @@
|
|
|
1
1
|
import moment from "moment";
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
import { Fragment, useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
4
4
|
import { formatClassname } from "../../../../../helpers/ClassesHelper";
|
|
5
5
|
|
|
6
6
|
const PAGE_HEIGHT = 1587;
|
|
7
|
-
// margin-top: 20, bottom: 20;
|
|
8
7
|
const FOOTER_HEIGHT = 70;
|
|
9
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;
|
|
10
13
|
|
|
11
|
-
const
|
|
12
|
-
const ref = useRef();
|
|
13
|
-
const [height, setHeight] = useState(0);
|
|
14
|
-
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
const observer = new ResizeObserver((entries) => {
|
|
17
|
-
for (const entry of entries) {
|
|
18
|
-
setHeight(entry.contentRect.height);
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
observer.observe(ref.current);
|
|
23
|
-
|
|
24
|
-
return () => observer.disconnect();
|
|
25
|
-
}, []);
|
|
26
|
-
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (height) {
|
|
29
|
-
onChangeHeight(i, { height, ref });
|
|
30
|
-
}
|
|
31
|
-
}, [height])
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<section ref={ref} style={widgets.style}>
|
|
35
|
-
{typeof widgets.render === 'function' ? widgets.render() : null}
|
|
36
|
-
</section>
|
|
37
|
-
)
|
|
38
|
-
};
|
|
14
|
+
const isHTMLElement = (node) => node instanceof HTMLElement;
|
|
39
15
|
|
|
40
16
|
export default function PdfView({
|
|
41
17
|
config = [],
|
|
@@ -47,104 +23,251 @@ export default function PdfView({
|
|
|
47
23
|
documentId = 'IDD-0000000',
|
|
48
24
|
downloadId = 'DWL-00000123',
|
|
49
25
|
}) {
|
|
50
|
-
const [sectionsConfig, setSectionsConfig] = useState({});
|
|
51
26
|
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
|
+
|
|
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');
|
|
50
|
+
});
|
|
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
|
+
};
|
|
52
65
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
+
};
|
|
57
74
|
|
|
58
|
-
|
|
59
|
-
|
|
75
|
+
traverse(section);
|
|
76
|
+
return elements;
|
|
77
|
+
}, []);
|
|
60
78
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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;
|
|
66
85
|
|
|
67
|
-
|
|
68
|
-
const { height, ref } = sectionsConfig[k];
|
|
86
|
+
isCalculatingRef.current = true;
|
|
69
87
|
|
|
70
|
-
|
|
71
|
-
ref.current.style.marginTop = `${HEADER_HEIGHT}px`;
|
|
72
|
-
incrHeight += HEADER_HEIGHT;
|
|
73
|
-
}
|
|
88
|
+
resetPaginationStyles(sections);
|
|
74
89
|
|
|
75
|
-
|
|
90
|
+
// Force layout recalc
|
|
91
|
+
sections.forEach(s => s.offsetHeight);
|
|
76
92
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
let currentPage = 1;
|
|
94
|
+
let currentPageHeight = 0;
|
|
95
|
+
const breaks = [];
|
|
80
96
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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';
|
|
92
115
|
}
|
|
93
116
|
} else {
|
|
94
|
-
|
|
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;
|
|
147
|
+
|
|
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
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Update current page if we created additional pages
|
|
175
|
+
if (sectionPage > currentPage) {
|
|
176
|
+
currentPage = sectionPage;
|
|
177
|
+
currentPageHeight = pageHeightInSection;
|
|
178
|
+
}
|
|
95
179
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
100
|
-
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
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]);
|
|
190
|
+
|
|
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]);
|
|
101
199
|
|
|
102
200
|
useEffect(() => {
|
|
103
|
-
|
|
104
|
-
|
|
201
|
+
const sections = sectionsRef.current.filter(Boolean);
|
|
202
|
+
if (sections.length === 0) return undefined;
|
|
105
203
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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));
|
|
219
|
+
|
|
220
|
+
return () => {
|
|
221
|
+
observer.disconnect();
|
|
222
|
+
if (resizeTimeoutRef.current) {
|
|
223
|
+
clearTimeout(resizeTimeoutRef.current);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}, [paginateContent, config.length]);
|
|
109
227
|
|
|
110
228
|
const contClassName = formatClassname(['daf-analysis daf-pdf-view', customClassName]);
|
|
111
229
|
|
|
112
|
-
|
|
113
|
-
|
|
230
|
+
return (
|
|
231
|
+
<div className={contClassName} style={{ position: 'relative', minHeight: `${PAGE_HEIGHT}px` }}>
|
|
114
232
|
<div className="view-content">
|
|
115
233
|
<div className="daf-analysis-layout">
|
|
116
|
-
<div
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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>
|
|
124
255
|
))}
|
|
125
256
|
</div>
|
|
126
257
|
</div>
|
|
127
258
|
</div>
|
|
128
|
-
);
|
|
129
|
-
}, [config, onChangeHeight]);
|
|
130
|
-
|
|
131
|
-
// <div className="daf-analysis">
|
|
132
|
-
// <Header title={t('Dashboard Title')} />
|
|
133
|
-
|
|
134
|
-
// <div className="content">
|
|
135
|
-
// <div className="view-content">
|
|
136
|
-
// <div className="daf-analysis-layout">
|
|
137
|
-
// <div className='sections-cont w-pt'>
|
|
138
|
-
// <section>
|
|
139
|
-
|
|
140
|
-
return (
|
|
141
|
-
<div className={contClassName} style={{ position: 'relative' }}>
|
|
142
|
-
{renderDashboard()}
|
|
143
259
|
{pages.map((page) => (
|
|
144
|
-
|
|
260
|
+
<Fragment key={`pdf-decor-${page}`}>
|
|
145
261
|
<div
|
|
146
|
-
style={{
|
|
147
|
-
|
|
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
|
+
}}
|
|
148
271
|
className="flex-row dashboard-header"
|
|
149
272
|
>
|
|
150
273
|
<div className="flex flex-column justify-center flex-1">
|
|
@@ -155,8 +278,15 @@ export default function PdfView({
|
|
|
155
278
|
</div>
|
|
156
279
|
</div>
|
|
157
280
|
<div
|
|
158
|
-
style={{
|
|
159
|
-
|
|
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
|
+
}}
|
|
160
290
|
className="dashboard-footer flex-row"
|
|
161
291
|
>
|
|
162
292
|
<div className="flex flex-column justify-center">
|
|
@@ -190,7 +320,7 @@ export default function PdfView({
|
|
|
190
320
|
<h5>{page}</h5>
|
|
191
321
|
</div>
|
|
192
322
|
</div>
|
|
193
|
-
|
|
323
|
+
</Fragment>
|
|
194
324
|
))}
|
|
195
325
|
</div>
|
|
196
326
|
);
|
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
/* Isolated Mapbox GL CSS - Scoped to prevent Leaflet conflicts */
|
|
2
|
-
|
|
3
|
-
/* Mapbox GL Core Styles - Scoped with .mapbox-gl-scope */
|
|
4
|
-
.mapbox-gl-scope .mapboxgl-map {
|
|
5
|
-
font: 12px/20px Helvetica Neue, Arial, Helvetica, sans-serif;
|
|
6
|
-
overflow: hidden;
|
|
7
|
-
position: relative;
|
|
8
|
-
-webkit-tap-highlight-color: rgb(0 0 0/0);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.mapbox-gl-scope .mapboxgl-canvas {
|
|
12
|
-
left: 0;
|
|
13
|
-
position: absolute;
|
|
14
|
-
top: 0;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
.mapbox-gl-scope .mapboxgl-map:-webkit-full-screen {
|
|
18
|
-
height: 100%;
|
|
19
|
-
width: 100%;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.mapbox-gl-scope .mapboxgl-canary {
|
|
23
|
-
background-color: salmon;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-interactive,
|
|
27
|
-
.mapbox-gl-scope .mapboxgl-ctrl-group button.mapboxgl-ctrl-compass {
|
|
28
|
-
cursor: grab;
|
|
29
|
-
-webkit-user-select: none;
|
|
30
|
-
user-select: none;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-interactive.mapboxgl-track-pointer {
|
|
34
|
-
cursor: pointer;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-interactive:active,
|
|
38
|
-
.mapbox-gl-scope .mapboxgl-ctrl-group button.mapboxgl-ctrl-compass:active {
|
|
39
|
-
cursor: grabbing;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate,
|
|
43
|
-
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate .mapboxgl-canvas {
|
|
44
|
-
touch-action: pan-x pan-y;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-drag-pan,
|
|
48
|
-
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-drag-pan .mapboxgl-canvas {
|
|
49
|
-
touch-action: pinch-zoom;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate.mapboxgl-touch-drag-pan,
|
|
53
|
-
.mapbox-gl-scope .mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate.mapboxgl-touch-drag-pan .mapboxgl-canvas {
|
|
54
|
-
touch-action: none;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/* Control positioning */
|
|
58
|
-
.mapbox-gl-scope .mapboxgl-ctrl-bottom,
|
|
59
|
-
.mapbox-gl-scope .mapboxgl-ctrl-bottom-left,
|
|
60
|
-
.mapbox-gl-scope .mapboxgl-ctrl-bottom-right,
|
|
61
|
-
.mapbox-gl-scope .mapboxgl-ctrl-left,
|
|
62
|
-
.mapbox-gl-scope .mapboxgl-ctrl-right,
|
|
63
|
-
.mapbox-gl-scope .mapboxgl-ctrl-top,
|
|
64
|
-
.mapbox-gl-scope .mapboxgl-ctrl-top-left,
|
|
65
|
-
.mapbox-gl-scope .mapboxgl-ctrl-top-right {
|
|
66
|
-
pointer-events: none;
|
|
67
|
-
position: absolute;
|
|
68
|
-
z-index: 2;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.mapbox-gl-scope .mapboxgl-ctrl-top-left {
|
|
72
|
-
left: 0;
|
|
73
|
-
top: 0;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
.mapbox-gl-scope .mapboxgl-ctrl-top {
|
|
77
|
-
left: 50%;
|
|
78
|
-
top: 0;
|
|
79
|
-
transform: translateX(-50%);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.mapbox-gl-scope .mapboxgl-ctrl-top-right {
|
|
83
|
-
right: 0;
|
|
84
|
-
top: 0;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
.mapbox-gl-scope .mapboxgl-ctrl-right {
|
|
88
|
-
right: 0;
|
|
89
|
-
top: 50%;
|
|
90
|
-
transform: translateY(-50%);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.mapbox-gl-scope .mapboxgl-ctrl-bottom-right {
|
|
94
|
-
bottom: 0;
|
|
95
|
-
right: 0;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.mapbox-gl-scope .mapboxgl-ctrl-bottom {
|
|
99
|
-
bottom: 0;
|
|
100
|
-
left: 50%;
|
|
101
|
-
transform: translateX(-50%);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.mapbox-gl-scope .mapboxgl-ctrl-bottom-left {
|
|
105
|
-
bottom: 0;
|
|
106
|
-
left: 0;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.mapbox-gl-scope .mapboxgl-ctrl-left {
|
|
110
|
-
left: 0;
|
|
111
|
-
top: 50%;
|
|
112
|
-
transform: translateY(-50%);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
.mapbox-gl-scope .mapboxgl-ctrl {
|
|
116
|
-
clear: both;
|
|
117
|
-
pointer-events: auto;
|
|
118
|
-
transform: translate(0);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.mapbox-gl-scope .mapboxgl-ctrl-top-left .mapboxgl-ctrl {
|
|
122
|
-
float: left;
|
|
123
|
-
margin: 10px 0 0 10px;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.mapbox-gl-scope .mapboxgl-ctrl-top .mapboxgl-ctrl {
|
|
127
|
-
float: left;
|
|
128
|
-
margin: 10px 0;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.mapbox-gl-scope .mapboxgl-ctrl-top-right .mapboxgl-ctrl {
|
|
132
|
-
float: right;
|
|
133
|
-
margin: 10px 10px 0 0;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.mapbox-gl-scope .mapboxgl-ctrl-bottom-right .mapboxgl-ctrl,
|
|
137
|
-
.mapbox-gl-scope .mapboxgl-ctrl-right .mapboxgl-ctrl {
|
|
138
|
-
float: right;
|
|
139
|
-
margin: 0 10px 10px 0;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.mapbox-gl-scope .mapboxgl-ctrl-bottom .mapboxgl-ctrl {
|
|
143
|
-
float: left;
|
|
144
|
-
margin: 10px 0;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
.mapbox-gl-scope .mapboxgl-ctrl-bottom-left .mapboxgl-ctrl,
|
|
148
|
-
.mapbox-gl-scope .mapboxgl-ctrl-left .mapboxgl-ctrl {
|
|
149
|
-
float: left;
|
|
150
|
-
margin: 0 0 10px 10px;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/* Control group styling */
|
|
154
|
-
.mapbox-gl-scope .mapboxgl-ctrl-group {
|
|
155
|
-
background: #fff;
|
|
156
|
-
border-radius: 4px;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
.mapbox-gl-scope .mapboxgl-ctrl-group:not(:empty) {
|
|
160
|
-
box-shadow: 0 0 0 2px #0000001a;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
.mapbox-gl-scope .mapboxgl-ctrl-group button {
|
|
164
|
-
background-color: initial;
|
|
165
|
-
border: 0;
|
|
166
|
-
box-sizing: border-box;
|
|
167
|
-
cursor: pointer;
|
|
168
|
-
display: block;
|
|
169
|
-
height: 29px;
|
|
170
|
-
outline: none;
|
|
171
|
-
overflow: hidden;
|
|
172
|
-
padding: 0;
|
|
173
|
-
width: 29px;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
.mapbox-gl-scope .mapboxgl-ctrl-group button+button {
|
|
177
|
-
border-top: 1px solid #ddd;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.mapbox-gl-scope .mapboxgl-ctrl button .mapboxgl-ctrl-icon {
|
|
181
|
-
background-position: 50%;
|
|
182
|
-
background-repeat: no-repeat;
|
|
183
|
-
display: block;
|
|
184
|
-
height: 100%;
|
|
185
|
-
width: 100%;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
.mapbox-gl-scope .mapboxgl-ctrl-attrib-button:focus,
|
|
189
|
-
.mapbox-gl-scope .mapboxgl-ctrl-group button:focus {
|
|
190
|
-
box-shadow: 0 0 2px 2px #0096ff;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
.mapbox-gl-scope .mapboxgl-ctrl button:disabled {
|
|
194
|
-
cursor: not-allowed;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
.mapbox-gl-scope .mapboxgl-ctrl button:disabled .mapboxgl-ctrl-icon {
|
|
198
|
-
opacity: .25;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
.mapbox-gl-scope .mapboxgl-ctrl-group button:first-child {
|
|
202
|
-
border-radius: 4px 4px 0 0;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
.mapbox-gl-scope .mapboxgl-ctrl-group button:last-child {
|
|
206
|
-
border-radius: 0 0 4px 4px;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
.mapbox-gl-scope .mapboxgl-ctrl-group button:only-child {
|
|
210
|
-
border-radius: inherit;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
.mapbox-gl-scope .mapboxgl-ctrl button:not(:disabled):hover {
|
|
214
|
-
background-color: #0000000d;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/* Marker styles */
|
|
218
|
-
.mapbox-gl-scope .mapboxgl-marker {
|
|
219
|
-
position: absolute;
|
|
220
|
-
z-index: 1;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
.mapbox-gl-scope .mapboxgl-marker svg {
|
|
224
|
-
display: block;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/* Popup styles */
|
|
228
|
-
.mapbox-gl-scope .mapboxgl-popup {
|
|
229
|
-
position: absolute;
|
|
230
|
-
text-align: center;
|
|
231
|
-
margin-bottom: 20px;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
.mapbox-gl-scope .mapboxgl-popup-content-wrapper {
|
|
235
|
-
padding: 1px;
|
|
236
|
-
text-align: left;
|
|
237
|
-
border-radius: 12px;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
.mapbox-gl-scope .mapboxgl-popup-content {
|
|
241
|
-
margin: 13px 24px 13px 20px;
|
|
242
|
-
line-height: 1.3;
|
|
243
|
-
font-size: 13px;
|
|
244
|
-
min-height: 1px;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
.mapbox-gl-scope .mapboxgl-popup-content p {
|
|
248
|
-
margin: 17px 0;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
.mapbox-gl-scope .mapboxgl-popup-tip-container {
|
|
252
|
-
width: 40px;
|
|
253
|
-
height: 20px;
|
|
254
|
-
position: absolute;
|
|
255
|
-
left: 50%;
|
|
256
|
-
margin-top: -1px;
|
|
257
|
-
margin-left: -20px;
|
|
258
|
-
overflow: hidden;
|
|
259
|
-
pointer-events: none;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
.mapbox-gl-scope .mapboxgl-popup-tip {
|
|
263
|
-
width: 17px;
|
|
264
|
-
height: 17px;
|
|
265
|
-
padding: 1px;
|
|
266
|
-
margin: -10px auto 0;
|
|
267
|
-
pointer-events: auto;
|
|
268
|
-
-webkit-transform: rotate(45deg);
|
|
269
|
-
-moz-transform: rotate(45deg);
|
|
270
|
-
-ms-transform: rotate(45deg);
|
|
271
|
-
transform: rotate(45deg);
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
.mapbox-gl-scope .mapboxgl-popup-content-wrapper,
|
|
275
|
-
.mapbox-gl-scope .mapboxgl-popup-tip {
|
|
276
|
-
background: white;
|
|
277
|
-
color: #333;
|
|
278
|
-
box-shadow: 0 3px 14px rgba(0, 0, 0, 0.4);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
.mapbox-gl-scope .mapboxgl-popup-close-button {
|
|
282
|
-
position: absolute;
|
|
283
|
-
top: 0;
|
|
284
|
-
right: 0;
|
|
285
|
-
border: none;
|
|
286
|
-
text-align: center;
|
|
287
|
-
width: 24px;
|
|
288
|
-
height: 24px;
|
|
289
|
-
font: 16px/24px Tahoma, Verdana, sans-serif;
|
|
290
|
-
color: #757575;
|
|
291
|
-
text-decoration: none;
|
|
292
|
-
background: transparent;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
.mapbox-gl-scope .mapboxgl-popup-close-button:hover,
|
|
296
|
-
.mapbox-gl-scope .mapboxgl-popup-close-button:focus {
|
|
297
|
-
color: #585858;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
/* Attribution */
|
|
301
|
-
.mapbox-gl-scope .mapboxgl-ctrl-attribution {
|
|
302
|
-
background: #fff;
|
|
303
|
-
background: rgba(255, 255, 255, 0.8);
|
|
304
|
-
margin: 0;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
.mapbox-gl-scope .mapboxgl-ctrl-attribution,
|
|
308
|
-
.mapbox-gl-scope .mapboxgl-ctrl-scale-line {
|
|
309
|
-
padding: 0 5px;
|
|
310
|
-
color: #333;
|
|
311
|
-
line-height: 1.4;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
.mapbox-gl-scope .mapboxgl-ctrl-attribution a {
|
|
315
|
-
text-decoration: none;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
.mapbox-gl-scope .mapboxgl-ctrl-attribution a:hover,
|
|
319
|
-
.mapbox-gl-scope .mapboxgl-ctrl-attribution a:focus {
|
|
320
|
-
text-decoration: underline;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/* Hide attribution by default */
|
|
324
|
-
.mapbox-gl-scope .mapboxgl-ctrl-attribution {
|
|
325
|
-
display: none !important;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
.mapbox-gl-scope .mapboxgl-ctrl-logo {
|
|
329
|
-
display: none !important;
|
|
330
|
-
}
|