@blerp/design 1.4.1 → 1.4.3
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/cjs/neo-components/Autocomplete.js +5 -0
- package/dist/cjs/neo-components/Dialog.js +5 -0
- package/dist/cjs/neo-components/Input.js +3 -1
- package/dist/cjs/neo-components/Layout.js +1 -0
- package/dist/cjs/neo-components/Misc.js +24 -14
- package/dist/cjs/neo-components/Navigation.js +69 -31
- package/dist/cjs/neo-components/withSx.js +10 -3
- package/dist/esm/neo-components/Autocomplete.js +5 -0
- package/dist/esm/neo-components/Dialog.js +5 -0
- package/dist/esm/neo-components/Input.js +3 -1
- package/dist/esm/neo-components/Layout.js +1 -0
- package/dist/esm/neo-components/Misc.js +25 -15
- package/dist/esm/neo-components/Navigation.js +70 -32
- package/dist/esm/neo-components/withSx.js +10 -3
- package/package.json +1 -1
|
@@ -22,10 +22,13 @@ const _excluded = ["options", "value", "defaultValue", "onChange", "onInputChang
|
|
|
22
22
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
|
|
23
23
|
|
|
24
24
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
25
|
+
|
|
26
|
+
const canUseDOM = () => typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
25
27
|
/**
|
|
26
28
|
* Autocomplete - combo box with filtering
|
|
27
29
|
*/
|
|
28
30
|
|
|
31
|
+
|
|
29
32
|
const AutocompleteBase = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref) => {
|
|
30
33
|
let {
|
|
31
34
|
options = [],
|
|
@@ -174,6 +177,8 @@ const AutocompleteBase = /*#__PURE__*/React__default["default"].forwardRef((_ref
|
|
|
174
177
|
|
|
175
178
|
|
|
176
179
|
React.useEffect(() => {
|
|
180
|
+
if (!canUseDOM()) return;
|
|
181
|
+
|
|
177
182
|
const handleClickOutside = event => {
|
|
178
183
|
if (inputRef.current && !inputRef.current.contains(event.target) && listboxRef.current && !listboxRef.current.contains(event.target)) {
|
|
179
184
|
handleClose();
|
|
@@ -244,6 +244,11 @@ const BaseModal = /*#__PURE__*/React__default["default"].forwardRef((_ref2, ref)
|
|
|
244
244
|
|
|
245
245
|
if (disablePortal) {
|
|
246
246
|
return modalContent;
|
|
247
|
+
} // SSR check - don't use createPortal on the server
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
if (typeof window === 'undefined') {
|
|
251
|
+
return null;
|
|
247
252
|
}
|
|
248
253
|
|
|
249
254
|
return /*#__PURE__*/ReactDOM.createPortal(modalContent, container || document.body);
|
|
@@ -50,6 +50,8 @@ const resolveStyles = (styleObj, colors) => {
|
|
|
50
50
|
|
|
51
51
|
return resolved;
|
|
52
52
|
};
|
|
53
|
+
|
|
54
|
+
const canUseDOM = () => typeof window !== "undefined" && typeof document !== "undefined";
|
|
53
55
|
/**
|
|
54
56
|
* Input/TextField - Form input component (replaces MUI TextField)
|
|
55
57
|
* Supports variants: outlined, filled, standard
|
|
@@ -340,7 +342,7 @@ const BaseInput = /*#__PURE__*/React__default["default"].forwardRef((_ref, ref)
|
|
|
340
342
|
const handleClick = e => {
|
|
341
343
|
onClick === null || onClick === void 0 ? void 0 : onClick(e);
|
|
342
344
|
|
|
343
|
-
if (!disabled) {
|
|
345
|
+
if (!disabled && canUseDOM()) {
|
|
344
346
|
const input = document.getElementById(id);
|
|
345
347
|
input === null || input === void 0 ? void 0 : input.focus();
|
|
346
348
|
}
|
|
@@ -29,6 +29,11 @@ const _excluded = ["orientation", "variant", "flexItem", "light", "textAlign", "
|
|
|
29
29
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
|
|
30
30
|
|
|
31
31
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
32
|
+
|
|
33
|
+
const canUseDOM = () => typeof window !== 'undefined' && typeof document !== 'undefined'; // Use useLayoutEffect only on client, useEffect on server
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
const useIsomorphicLayoutEffect = canUseDOM() ? React.useLayoutEffect : React.useEffect;
|
|
32
37
|
/**
|
|
33
38
|
* Divider - Visual separator (replaces MUI Divider)
|
|
34
39
|
*/
|
|
@@ -471,13 +476,18 @@ const BaseTooltip = /*#__PURE__*/React__default["default"].forwardRef((_ref5, re
|
|
|
471
476
|
top: 0,
|
|
472
477
|
left: 0
|
|
473
478
|
});
|
|
479
|
+
const [mounted, setMounted] = React.useState(false);
|
|
474
480
|
const timeoutRef = React.useRef(null);
|
|
475
481
|
const childRef = React.useRef(null);
|
|
476
482
|
const tooltipRef = React.useRef(null);
|
|
477
|
-
const open = controlledOpen !== undefined ? controlledOpen : isOpen; //
|
|
483
|
+
const open = controlledOpen !== undefined ? controlledOpen : isOpen; // SSR safety - only mount portal after hydration
|
|
484
|
+
|
|
485
|
+
React.useEffect(() => {
|
|
486
|
+
setMounted(true);
|
|
487
|
+
}, []); // Calculate position based on child element and placement
|
|
478
488
|
|
|
479
489
|
const updatePosition = React.useCallback(() => {
|
|
480
|
-
if (!childRef.current) return;
|
|
490
|
+
if (!canUseDOM() || !childRef.current) return;
|
|
481
491
|
const childRect = childRef.current.getBoundingClientRect();
|
|
482
492
|
const tooltipEl = tooltipRef.current;
|
|
483
493
|
const tooltipRect = tooltipEl ? tooltipEl.getBoundingClientRect() : {
|
|
@@ -577,17 +587,16 @@ const BaseTooltip = /*#__PURE__*/React__default["default"].forwardRef((_ref5, re
|
|
|
577
587
|
});
|
|
578
588
|
}, [placement]); // Update position when open changes or on scroll/resize
|
|
579
589
|
|
|
580
|
-
|
|
581
|
-
if (open)
|
|
582
|
-
|
|
590
|
+
useIsomorphicLayoutEffect(() => {
|
|
591
|
+
if (!canUseDOM() || !open) return;
|
|
592
|
+
updatePosition(); // Update position on scroll and resize
|
|
583
593
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
}
|
|
594
|
+
window.addEventListener('scroll', updatePosition, true);
|
|
595
|
+
window.addEventListener('resize', updatePosition);
|
|
596
|
+
return () => {
|
|
597
|
+
window.removeEventListener('scroll', updatePosition, true);
|
|
598
|
+
window.removeEventListener('resize', updatePosition);
|
|
599
|
+
};
|
|
591
600
|
}, [open, updatePosition]); // Re-calculate after tooltip renders (to get accurate dimensions)
|
|
592
601
|
|
|
593
602
|
React.useEffect(() => {
|
|
@@ -688,9 +697,10 @@ const BaseTooltip = /*#__PURE__*/React__default["default"].forwardRef((_ref5, re
|
|
|
688
697
|
}, (_componentsProps$tool3 = componentsProps.tooltip) === null || _componentsProps$tool3 === void 0 ? void 0 : _componentsProps$tool3.sx), PopperProps.sx), {}, {
|
|
689
698
|
// Force background at the end to ensure it's never transparent
|
|
690
699
|
backgroundColor
|
|
691
|
-
});
|
|
700
|
+
}); // Don't render portal during SSR or before mount
|
|
701
|
+
|
|
692
702
|
|
|
693
|
-
const tooltipContent = open && title ? /*#__PURE__*/React__default["default"].createElement("span", {
|
|
703
|
+
const tooltipContent = open && title && mounted && canUseDOM() ? /*#__PURE__*/React__default["default"].createElement("span", {
|
|
694
704
|
ref: tooltipRef,
|
|
695
705
|
role: "tooltip",
|
|
696
706
|
style: tooltipStyle
|
|
@@ -32,6 +32,11 @@ const _excluded = ["open", "onClose", "anchorEl", "anchorOrigin", "transformOrig
|
|
|
32
32
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
|
|
33
33
|
|
|
34
34
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
35
|
+
|
|
36
|
+
const canUseDOM = () => typeof window !== 'undefined' && typeof document !== 'undefined'; // Use useLayoutEffect only on client, useEffect on server
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
const useIsomorphicLayoutEffect = canUseDOM() ? React.useLayoutEffect : React.useEffect;
|
|
35
40
|
/**
|
|
36
41
|
* Context to detect if we're inside a Popover
|
|
37
42
|
*/
|
|
@@ -106,6 +111,7 @@ function resolveStyleColors(style, colors) {
|
|
|
106
111
|
|
|
107
112
|
|
|
108
113
|
function isClickInsideAnyOverlay(target, excludeElement) {
|
|
114
|
+
if (!canUseDOM()) return false;
|
|
109
115
|
let element = target;
|
|
110
116
|
|
|
111
117
|
while (element && element !== document.body) {
|
|
@@ -180,10 +186,15 @@ const BaseMenu = /*#__PURE__*/React__default["default"].forwardRef((_ref2, ref)
|
|
|
180
186
|
top: 0,
|
|
181
187
|
left: 0
|
|
182
188
|
});
|
|
189
|
+
const [mounted, setMounted] = React.useState(false);
|
|
183
190
|
const {
|
|
184
191
|
registerOverlay,
|
|
185
192
|
isClickInsideOverlay
|
|
186
|
-
} = useOverlayStack(); //
|
|
193
|
+
} = useOverlayStack(); // SSR safety
|
|
194
|
+
|
|
195
|
+
React.useEffect(() => {
|
|
196
|
+
setMounted(true);
|
|
197
|
+
}, []); // Combine refs
|
|
187
198
|
|
|
188
199
|
const combinedRef = React.useCallback(node => {
|
|
189
200
|
menuRef.current = node;
|
|
@@ -206,8 +217,8 @@ const BaseMenu = /*#__PURE__*/React__default["default"].forwardRef((_ref2, ref)
|
|
|
206
217
|
return _objectSpread(_objectSpread({}, sxStyles), PaperProps.style);
|
|
207
218
|
}, [PaperProps.sx, PaperProps.style, colors]); // Calculate position (only when standalone)
|
|
208
219
|
|
|
209
|
-
|
|
210
|
-
if (isInsidePopover || !open || !anchorEl) return; // Safety check - make sure anchorEl is a valid DOM element
|
|
220
|
+
useIsomorphicLayoutEffect(() => {
|
|
221
|
+
if (!canUseDOM() || isInsidePopover || !open || !anchorEl) return; // Safety check - make sure anchorEl is a valid DOM element
|
|
211
222
|
|
|
212
223
|
if (!(anchorEl instanceof Element)) return;
|
|
213
224
|
const rect = anchorEl.getBoundingClientRect();
|
|
@@ -255,7 +266,7 @@ const BaseMenu = /*#__PURE__*/React__default["default"].forwardRef((_ref2, ref)
|
|
|
255
266
|
}, [open, anchorEl, anchorOrigin, transformOrigin, isInsidePopover]); // Click outside and escape handling (only when standalone)
|
|
256
267
|
|
|
257
268
|
React.useEffect(() => {
|
|
258
|
-
if (isInsidePopover || !open) return;
|
|
269
|
+
if (!canUseDOM() || isInsidePopover || !open) return;
|
|
259
270
|
|
|
260
271
|
const handleClickOutside = e => {
|
|
261
272
|
// Don't close if clicking inside the menu itself
|
|
@@ -301,10 +312,9 @@ const BaseMenu = /*#__PURE__*/React__default["default"].forwardRef((_ref2, ref)
|
|
|
301
312
|
}, [open, onClose, anchorEl, isInsidePopover, isClickInsideOverlay]); // Focus first item on open
|
|
302
313
|
|
|
303
314
|
React.useEffect(() => {
|
|
304
|
-
if (open
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
315
|
+
if (!canUseDOM() || !open || !autoFocus || !menuRef.current) return;
|
|
316
|
+
const firstItem = menuRef.current.querySelector('[role="menuitem"]:not([aria-disabled="true"])');
|
|
317
|
+
if (firstItem) firstItem.focus();
|
|
308
318
|
}, [open, autoFocus]);
|
|
309
319
|
if (!open && !keepMounted) return null;
|
|
310
320
|
|
|
@@ -353,7 +363,9 @@ const BaseMenu = /*#__PURE__*/React__default["default"].forwardRef((_ref2, ref)
|
|
|
353
363
|
}, props), /*#__PURE__*/React__default["default"].createElement("ul", _extends__default["default"]({
|
|
354
364
|
style: listStyle
|
|
355
365
|
}, MenuListProps), children));
|
|
356
|
-
if (disablePortal) return content;
|
|
366
|
+
if (disablePortal) return content; // SSR safety - don't render portal until mounted
|
|
367
|
+
|
|
368
|
+
if (!mounted) return null;
|
|
357
369
|
return /*#__PURE__*/ReactDOM.createPortal(content, document.body);
|
|
358
370
|
});
|
|
359
371
|
BaseMenu.displayName = "BaseMenu";
|
|
@@ -449,8 +461,8 @@ const BaseTabs = /*#__PURE__*/React__default["default"].forwardRef((_ref4, ref)
|
|
|
449
461
|
const colorValue = (colors === null || colors === void 0 ? void 0 : colors[indicatorColor]) || (colors === null || colors === void 0 ? void 0 : colors.ibisRed);
|
|
450
462
|
typeof colorValue === "object" ? colorValue.main : colorValue || "ibisRed.main"; // Update indicator position
|
|
451
463
|
|
|
452
|
-
|
|
453
|
-
if (!tabsRef.current) return;
|
|
464
|
+
useIsomorphicLayoutEffect(() => {
|
|
465
|
+
if (!canUseDOM() || !tabsRef.current) return;
|
|
454
466
|
const tabs = tabsRef.current.querySelectorAll('[role="tab"]');
|
|
455
467
|
const selectedTab = Array.from(tabs).find((tab, index) => {
|
|
456
468
|
const tabValue = tab.dataset.value !== undefined ? tab.dataset.value : index;
|
|
@@ -774,6 +786,11 @@ const BaseSnackbar = /*#__PURE__*/React__default["default"].forwardRef((_ref8, r
|
|
|
774
786
|
const {
|
|
775
787
|
colors
|
|
776
788
|
} = ThemeProvider.useTheme();
|
|
789
|
+
const [mounted, setMounted] = React.useState(false); // SSR safety
|
|
790
|
+
|
|
791
|
+
React.useEffect(() => {
|
|
792
|
+
setMounted(true);
|
|
793
|
+
}, []);
|
|
777
794
|
const startTimer = React.useCallback(() => {
|
|
778
795
|
if (autoHideDuration != null) {
|
|
779
796
|
timerRef.current = setTimeout(() => {
|
|
@@ -796,7 +813,7 @@ const BaseSnackbar = /*#__PURE__*/React__default["default"].forwardRef((_ref8, r
|
|
|
796
813
|
}, [open, startTimer, stopTimer]); // Pause timer on window blur
|
|
797
814
|
|
|
798
815
|
React.useEffect(() => {
|
|
799
|
-
if (disableWindowBlurListener || !open) return;
|
|
816
|
+
if (!canUseDOM() || disableWindowBlurListener || !open) return;
|
|
800
817
|
|
|
801
818
|
const handleBlur = () => stopTimer();
|
|
802
819
|
|
|
@@ -812,7 +829,9 @@ const BaseSnackbar = /*#__PURE__*/React__default["default"].forwardRef((_ref8, r
|
|
|
812
829
|
window.removeEventListener("focus", handleFocus);
|
|
813
830
|
};
|
|
814
831
|
}, [open, disableWindowBlurListener, startTimer, stopTimer]);
|
|
815
|
-
if (!open) return null;
|
|
832
|
+
if (!open) return null; // SSR safety - don't render portal until mounted
|
|
833
|
+
|
|
834
|
+
if (!mounted || !canUseDOM()) return null;
|
|
816
835
|
|
|
817
836
|
const positionStyles = _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
|
|
818
837
|
position: "fixed",
|
|
@@ -908,10 +927,15 @@ const BasePopover = /*#__PURE__*/React__default["default"].forwardRef((_ref9, re
|
|
|
908
927
|
top: 0,
|
|
909
928
|
left: 0
|
|
910
929
|
});
|
|
930
|
+
const [mounted, setMounted] = React.useState(false);
|
|
911
931
|
const {
|
|
912
932
|
registerOverlay,
|
|
913
933
|
isClickInsideOverlay
|
|
914
|
-
} = useOverlayStack();
|
|
934
|
+
} = useOverlayStack(); // SSR safety
|
|
935
|
+
|
|
936
|
+
React.useEffect(() => {
|
|
937
|
+
setMounted(true);
|
|
938
|
+
}, []);
|
|
915
939
|
const combinedRef = React.useCallback(node => {
|
|
916
940
|
popoverRef.current = node;
|
|
917
941
|
|
|
@@ -933,8 +957,8 @@ const BasePopover = /*#__PURE__*/React__default["default"].forwardRef((_ref9, re
|
|
|
933
957
|
return _objectSpread(_objectSpread({}, sxStyles), PaperProps.style);
|
|
934
958
|
}, [PaperProps.sx, PaperProps.style, colors]); // Calculate position
|
|
935
959
|
|
|
936
|
-
|
|
937
|
-
if (!open) return;
|
|
960
|
+
useIsomorphicLayoutEffect(() => {
|
|
961
|
+
if (!canUseDOM() || !open) return;
|
|
938
962
|
let top = 0;
|
|
939
963
|
let left = 0;
|
|
940
964
|
|
|
@@ -983,7 +1007,7 @@ const BasePopover = /*#__PURE__*/React__default["default"].forwardRef((_ref9, re
|
|
|
983
1007
|
}, [open, anchorEl, anchorOrigin, transformOrigin, anchorPosition, anchorReference, marginThreshold]); // Click outside handling
|
|
984
1008
|
|
|
985
1009
|
React.useEffect(() => {
|
|
986
|
-
if (!open) return;
|
|
1010
|
+
if (!canUseDOM() || !open) return;
|
|
987
1011
|
|
|
988
1012
|
const handleClickOutside = e => {
|
|
989
1013
|
// Use a small delay to ensure ref is populated after portal render
|
|
@@ -1056,7 +1080,9 @@ const BasePopover = /*#__PURE__*/React__default["default"].forwardRef((_ref9, re
|
|
|
1056
1080
|
style: popoverStyle,
|
|
1057
1081
|
onClick: onClick
|
|
1058
1082
|
}, props), children));
|
|
1059
|
-
if (disablePortal) return content;
|
|
1083
|
+
if (disablePortal) return content; // SSR safety - don't render portal until mounted
|
|
1084
|
+
|
|
1085
|
+
if (!mounted) return null;
|
|
1060
1086
|
return /*#__PURE__*/ReactDOM.createPortal(content, document.body);
|
|
1061
1087
|
});
|
|
1062
1088
|
BasePopover.displayName = "BasePopover";
|
|
@@ -1088,10 +1114,15 @@ const BaseDrawer = /*#__PURE__*/React__default["default"].forwardRef((_ref10, re
|
|
|
1088
1114
|
colors
|
|
1089
1115
|
} = ThemeProvider.useTheme();
|
|
1090
1116
|
const [isVisible, setIsVisible] = React.useState(open);
|
|
1117
|
+
const [mounted, setMounted] = React.useState(false);
|
|
1091
1118
|
const {
|
|
1092
1119
|
registerOverlay
|
|
1093
1120
|
} = useOverlayStack();
|
|
1094
|
-
const drawerRef = React.useRef(null); //
|
|
1121
|
+
const drawerRef = React.useRef(null); // SSR safety
|
|
1122
|
+
|
|
1123
|
+
React.useEffect(() => {
|
|
1124
|
+
setMounted(true);
|
|
1125
|
+
}, []); // Resolve PaperProps.sx colors
|
|
1095
1126
|
|
|
1096
1127
|
const resolvedPaperStyle = React.useMemo(() => {
|
|
1097
1128
|
const sxStyles = PaperProps.sx ? resolveStyleColors(PaperProps.sx, colors) : {};
|
|
@@ -1114,13 +1145,12 @@ const BaseDrawer = /*#__PURE__*/React__default["default"].forwardRef((_ref10, re
|
|
|
1114
1145
|
}, [open, transitionDuration]); // Lock body scroll for temporary drawers
|
|
1115
1146
|
|
|
1116
1147
|
React.useEffect(() => {
|
|
1117
|
-
if (open
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
}
|
|
1148
|
+
if (!canUseDOM() || !open || variant !== "temporary") return;
|
|
1149
|
+
const originalOverflow = document.body.style.overflow;
|
|
1150
|
+
document.body.style.overflow = "hidden";
|
|
1151
|
+
return () => {
|
|
1152
|
+
document.body.style.overflow = originalOverflow;
|
|
1153
|
+
};
|
|
1124
1154
|
}, [open, variant]);
|
|
1125
1155
|
const drawerWidth = (resolvedPaperStyle === null || resolvedPaperStyle === void 0 ? void 0 : resolvedPaperStyle.width) || ((_PaperProps$style = PaperProps.style) === null || _PaperProps$style === void 0 ? void 0 : _PaperProps$style.width) || "240px";
|
|
1126
1156
|
const drawerHeight = (resolvedPaperStyle === null || resolvedPaperStyle === void 0 ? void 0 : resolvedPaperStyle.height) || ((_PaperProps$style2 = PaperProps.style) === null || _PaperProps$style2 === void 0 ? void 0 : _PaperProps$style2.height) || "auto";
|
|
@@ -1205,7 +1235,9 @@ const BaseDrawer = /*#__PURE__*/React__default["default"].forwardRef((_ref10, re
|
|
|
1205
1235
|
} // Temporary drawer - with backdrop
|
|
1206
1236
|
|
|
1207
1237
|
|
|
1208
|
-
if (!isVisible && !open) return null;
|
|
1238
|
+
if (!isVisible && !open) return null; // SSR safety - don't render portal until mounted
|
|
1239
|
+
|
|
1240
|
+
if (!mounted || !canUseDOM()) return null;
|
|
1209
1241
|
|
|
1210
1242
|
const backdropStyle = _objectSpread({
|
|
1211
1243
|
position: "fixed",
|
|
@@ -1269,11 +1301,16 @@ const BaseTooltip = /*#__PURE__*/React__default["default"].forwardRef((_ref11, r
|
|
|
1269
1301
|
top: 0,
|
|
1270
1302
|
left: 0
|
|
1271
1303
|
});
|
|
1304
|
+
const [mounted, setMounted] = React.useState(false);
|
|
1272
1305
|
const anchorRef = React.useRef(null);
|
|
1273
1306
|
const tooltipRef = React.useRef(null);
|
|
1274
1307
|
const enterTimeoutRef = React.useRef(null);
|
|
1275
1308
|
const leaveTimeoutRef = React.useRef(null);
|
|
1276
|
-
const open = controlledOpen !== undefined ? controlledOpen : isOpen; //
|
|
1309
|
+
const open = controlledOpen !== undefined ? controlledOpen : isOpen; // SSR safety
|
|
1310
|
+
|
|
1311
|
+
React.useEffect(() => {
|
|
1312
|
+
setMounted(true);
|
|
1313
|
+
}, []); // Merge slotProps and componentsProps
|
|
1277
1314
|
|
|
1278
1315
|
const mergedSlotProps = _objectSpread(_objectSpread({}, componentsProps), slotProps); // Resolve tooltip styles
|
|
1279
1316
|
|
|
@@ -1309,7 +1346,7 @@ const BaseTooltip = /*#__PURE__*/React__default["default"].forwardRef((_ref11, r
|
|
|
1309
1346
|
return _objectSpread(_objectSpread(_objectSpread({}, resolvedSx), popperSlotProps.style), popperPropsSx);
|
|
1310
1347
|
}, [mergedSlotProps, PopperProps, colors]);
|
|
1311
1348
|
const updatePosition = React.useCallback(() => {
|
|
1312
|
-
if (!anchorRef.current || !tooltipRef.current) return;
|
|
1349
|
+
if (!canUseDOM() || !anchorRef.current || !tooltipRef.current) return;
|
|
1313
1350
|
const anchorRect = anchorRef.current.getBoundingClientRect();
|
|
1314
1351
|
const tooltipRect = tooltipRef.current.getBoundingClientRect();
|
|
1315
1352
|
const offset = 8;
|
|
@@ -1455,8 +1492,9 @@ const BaseTooltip = /*#__PURE__*/React__default["default"].forwardRef((_ref11, r
|
|
|
1455
1492
|
}
|
|
1456
1493
|
|
|
1457
1494
|
const clonedChild = /*#__PURE__*/React__default["default"].cloneElement(childElement, childProps);
|
|
1458
|
-
if (!title) return clonedChild;
|
|
1459
|
-
|
|
1495
|
+
if (!title) return clonedChild; // SSR safety - don't render portal until mounted
|
|
1496
|
+
|
|
1497
|
+
const tooltipContent = open && mounted && canUseDOM() ? /*#__PURE__*/ReactDOM.createPortal( /*#__PURE__*/React__default["default"].createElement("div", {
|
|
1460
1498
|
ref: tooltipRef,
|
|
1461
1499
|
role: "tooltip",
|
|
1462
1500
|
style: _objectSpread(_objectSpread({}, tooltipStyle), popperStyle)
|
|
@@ -21,10 +21,14 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
21
21
|
|
|
22
22
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty__default["default"](target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
23
23
|
|
|
24
|
+
const canUseDOM = () => typeof window !== 'undefined' && typeof document !== 'undefined'; // Global style cache to avoid re-injecting same styles
|
|
25
|
+
|
|
26
|
+
|
|
24
27
|
const styleCache = new Map();
|
|
25
28
|
let styleSheet = null;
|
|
26
29
|
|
|
27
30
|
function getStyleSheet() {
|
|
31
|
+
if (!canUseDOM()) return null;
|
|
28
32
|
if (styleSheet) return styleSheet; // Check for existing stylesheet
|
|
29
33
|
|
|
30
34
|
const existing = document.querySelector("style[data-blerp-sx]");
|
|
@@ -43,6 +47,8 @@ function getStyleSheet() {
|
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
function injectStyles(className, pseudoStyles, nestedStyles, mediaQueries, themeColors) {
|
|
50
|
+
if (!canUseDOM()) return;
|
|
51
|
+
|
|
46
52
|
if (!className) {
|
|
47
53
|
return;
|
|
48
54
|
}
|
|
@@ -65,7 +71,8 @@ function injectStyles(className, pseudoStyles, nestedStyles, mediaQueries, theme
|
|
|
65
71
|
|
|
66
72
|
if (css) {
|
|
67
73
|
try {
|
|
68
|
-
const sheet = getStyleSheet();
|
|
74
|
+
const sheet = getStyleSheet();
|
|
75
|
+
if (!sheet) return; // Split by newlines and insert each rule
|
|
69
76
|
|
|
70
77
|
css.split("\n").filter(Boolean).forEach(rule => {
|
|
71
78
|
try {
|
|
@@ -137,12 +144,12 @@ function withSx(Component) {
|
|
|
137
144
|
}, [sx, style, colors]); // Inject special styles (pseudo, nested, media queries)
|
|
138
145
|
|
|
139
146
|
React.useEffect(() => {
|
|
140
|
-
if (
|
|
147
|
+
if (canUseDOM() && pseudoClassName) {
|
|
141
148
|
injectStyles(pseudoClassName, pseudoStyles, nestedStyles, mediaQueries, colors);
|
|
142
149
|
}
|
|
143
150
|
}, [pseudoClassName, pseudoStyles, nestedStyles, mediaQueries, colors]); // Also inject synchronously for SSR/initial render
|
|
144
151
|
|
|
145
|
-
if (
|
|
152
|
+
if (canUseDOM() && pseudoClassName) {
|
|
146
153
|
injectStyles(pseudoClassName, pseudoStyles, nestedStyles, mediaQueries, colors);
|
|
147
154
|
} // Combine classNames
|
|
148
155
|
|
|
@@ -11,10 +11,13 @@ const _excluded = ["options", "value", "defaultValue", "onChange", "onInputChang
|
|
|
11
11
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
|
|
12
12
|
|
|
13
13
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
14
|
+
|
|
15
|
+
const canUseDOM = () => typeof window !== 'undefined' && typeof document !== 'undefined';
|
|
14
16
|
/**
|
|
15
17
|
* Autocomplete - combo box with filtering
|
|
16
18
|
*/
|
|
17
19
|
|
|
20
|
+
|
|
18
21
|
const AutocompleteBase = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
19
22
|
let {
|
|
20
23
|
options = [],
|
|
@@ -163,6 +166,8 @@ const AutocompleteBase = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
163
166
|
|
|
164
167
|
|
|
165
168
|
useEffect(() => {
|
|
169
|
+
if (!canUseDOM()) return;
|
|
170
|
+
|
|
166
171
|
const handleClickOutside = event => {
|
|
167
172
|
if (inputRef.current && !inputRef.current.contains(event.target) && listboxRef.current && !listboxRef.current.contains(event.target)) {
|
|
168
173
|
handleClose();
|
|
@@ -233,6 +233,11 @@ const BaseModal = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
233
233
|
|
|
234
234
|
if (disablePortal) {
|
|
235
235
|
return modalContent;
|
|
236
|
+
} // SSR check - don't use createPortal on the server
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
if (typeof window === 'undefined') {
|
|
240
|
+
return null;
|
|
236
241
|
}
|
|
237
242
|
|
|
238
243
|
return /*#__PURE__*/createPortal(modalContent, container || document.body);
|
|
@@ -39,6 +39,8 @@ const resolveStyles = (styleObj, colors) => {
|
|
|
39
39
|
|
|
40
40
|
return resolved;
|
|
41
41
|
};
|
|
42
|
+
|
|
43
|
+
const canUseDOM = () => typeof window !== "undefined" && typeof document !== "undefined";
|
|
42
44
|
/**
|
|
43
45
|
* Input/TextField - Form input component (replaces MUI TextField)
|
|
44
46
|
* Supports variants: outlined, filled, standard
|
|
@@ -329,7 +331,7 @@ const BaseInput = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
329
331
|
const handleClick = e => {
|
|
330
332
|
onClick === null || onClick === void 0 ? void 0 : onClick(e);
|
|
331
333
|
|
|
332
|
-
if (!disabled) {
|
|
334
|
+
if (!disabled && canUseDOM()) {
|
|
333
335
|
const input = document.getElementById(id);
|
|
334
336
|
input === null || input === void 0 ? void 0 : input.focus();
|
|
335
337
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _extends from '@babel/runtime/helpers/extends';
|
|
2
2
|
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
3
3
|
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
|
|
4
|
-
import React, { useState, useRef, useCallback, useLayoutEffect
|
|
4
|
+
import React, { useState, useRef, useEffect, useCallback, useLayoutEffect } from 'react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
import { withSx } from './withSx.js';
|
|
7
7
|
import { useTheme } from './ThemeProvider.js';
|
|
@@ -18,6 +18,11 @@ const _excluded = ["orientation", "variant", "flexItem", "light", "textAlign", "
|
|
|
18
18
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
|
|
19
19
|
|
|
20
20
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
21
|
+
|
|
22
|
+
const canUseDOM = () => typeof window !== 'undefined' && typeof document !== 'undefined'; // Use useLayoutEffect only on client, useEffect on server
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
const useIsomorphicLayoutEffect = canUseDOM() ? useLayoutEffect : useEffect;
|
|
21
26
|
/**
|
|
22
27
|
* Divider - Visual separator (replaces MUI Divider)
|
|
23
28
|
*/
|
|
@@ -460,13 +465,18 @@ const BaseTooltip = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
|
|
|
460
465
|
top: 0,
|
|
461
466
|
left: 0
|
|
462
467
|
});
|
|
468
|
+
const [mounted, setMounted] = useState(false);
|
|
463
469
|
const timeoutRef = useRef(null);
|
|
464
470
|
const childRef = useRef(null);
|
|
465
471
|
const tooltipRef = useRef(null);
|
|
466
|
-
const open = controlledOpen !== undefined ? controlledOpen : isOpen; //
|
|
472
|
+
const open = controlledOpen !== undefined ? controlledOpen : isOpen; // SSR safety - only mount portal after hydration
|
|
473
|
+
|
|
474
|
+
useEffect(() => {
|
|
475
|
+
setMounted(true);
|
|
476
|
+
}, []); // Calculate position based on child element and placement
|
|
467
477
|
|
|
468
478
|
const updatePosition = useCallback(() => {
|
|
469
|
-
if (!childRef.current) return;
|
|
479
|
+
if (!canUseDOM() || !childRef.current) return;
|
|
470
480
|
const childRect = childRef.current.getBoundingClientRect();
|
|
471
481
|
const tooltipEl = tooltipRef.current;
|
|
472
482
|
const tooltipRect = tooltipEl ? tooltipEl.getBoundingClientRect() : {
|
|
@@ -566,17 +576,16 @@ const BaseTooltip = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
|
|
|
566
576
|
});
|
|
567
577
|
}, [placement]); // Update position when open changes or on scroll/resize
|
|
568
578
|
|
|
569
|
-
|
|
570
|
-
if (open)
|
|
571
|
-
|
|
579
|
+
useIsomorphicLayoutEffect(() => {
|
|
580
|
+
if (!canUseDOM() || !open) return;
|
|
581
|
+
updatePosition(); // Update position on scroll and resize
|
|
572
582
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
}
|
|
583
|
+
window.addEventListener('scroll', updatePosition, true);
|
|
584
|
+
window.addEventListener('resize', updatePosition);
|
|
585
|
+
return () => {
|
|
586
|
+
window.removeEventListener('scroll', updatePosition, true);
|
|
587
|
+
window.removeEventListener('resize', updatePosition);
|
|
588
|
+
};
|
|
580
589
|
}, [open, updatePosition]); // Re-calculate after tooltip renders (to get accurate dimensions)
|
|
581
590
|
|
|
582
591
|
useEffect(() => {
|
|
@@ -677,9 +686,10 @@ const BaseTooltip = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
|
|
|
677
686
|
}, (_componentsProps$tool3 = componentsProps.tooltip) === null || _componentsProps$tool3 === void 0 ? void 0 : _componentsProps$tool3.sx), PopperProps.sx), {}, {
|
|
678
687
|
// Force background at the end to ensure it's never transparent
|
|
679
688
|
backgroundColor
|
|
680
|
-
});
|
|
689
|
+
}); // Don't render portal during SSR or before mount
|
|
690
|
+
|
|
681
691
|
|
|
682
|
-
const tooltipContent = open && title ? /*#__PURE__*/React.createElement("span", {
|
|
692
|
+
const tooltipContent = open && title && mounted && canUseDOM() ? /*#__PURE__*/React.createElement("span", {
|
|
683
693
|
ref: tooltipRef,
|
|
684
694
|
role: "tooltip",
|
|
685
695
|
style: tooltipStyle
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _extends from '@babel/runtime/helpers/extends';
|
|
2
2
|
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
3
3
|
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
|
|
4
|
-
import React, { useContext, useRef, useState,
|
|
4
|
+
import React, { useContext, useRef, useState, useEffect, useCallback, useMemo, useLayoutEffect, createContext } from 'react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
import { withSx } from './withSx.js';
|
|
7
7
|
import { useTheme } from './ThemeProvider.js';
|
|
@@ -21,6 +21,11 @@ const _excluded = ["open", "onClose", "anchorEl", "anchorOrigin", "transformOrig
|
|
|
21
21
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
|
|
22
22
|
|
|
23
23
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
24
|
+
|
|
25
|
+
const canUseDOM = () => typeof window !== 'undefined' && typeof document !== 'undefined'; // Use useLayoutEffect only on client, useEffect on server
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
const useIsomorphicLayoutEffect = canUseDOM() ? useLayoutEffect : useEffect;
|
|
24
29
|
/**
|
|
25
30
|
* Context to detect if we're inside a Popover
|
|
26
31
|
*/
|
|
@@ -95,6 +100,7 @@ function resolveStyleColors(style, colors) {
|
|
|
95
100
|
|
|
96
101
|
|
|
97
102
|
function isClickInsideAnyOverlay(target, excludeElement) {
|
|
103
|
+
if (!canUseDOM()) return false;
|
|
98
104
|
let element = target;
|
|
99
105
|
|
|
100
106
|
while (element && element !== document.body) {
|
|
@@ -169,10 +175,15 @@ const BaseMenu = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
169
175
|
top: 0,
|
|
170
176
|
left: 0
|
|
171
177
|
});
|
|
178
|
+
const [mounted, setMounted] = useState(false);
|
|
172
179
|
const {
|
|
173
180
|
registerOverlay,
|
|
174
181
|
isClickInsideOverlay
|
|
175
|
-
} = useOverlayStack(); //
|
|
182
|
+
} = useOverlayStack(); // SSR safety
|
|
183
|
+
|
|
184
|
+
useEffect(() => {
|
|
185
|
+
setMounted(true);
|
|
186
|
+
}, []); // Combine refs
|
|
176
187
|
|
|
177
188
|
const combinedRef = useCallback(node => {
|
|
178
189
|
menuRef.current = node;
|
|
@@ -195,8 +206,8 @@ const BaseMenu = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
195
206
|
return _objectSpread(_objectSpread({}, sxStyles), PaperProps.style);
|
|
196
207
|
}, [PaperProps.sx, PaperProps.style, colors]); // Calculate position (only when standalone)
|
|
197
208
|
|
|
198
|
-
|
|
199
|
-
if (isInsidePopover || !open || !anchorEl) return; // Safety check - make sure anchorEl is a valid DOM element
|
|
209
|
+
useIsomorphicLayoutEffect(() => {
|
|
210
|
+
if (!canUseDOM() || isInsidePopover || !open || !anchorEl) return; // Safety check - make sure anchorEl is a valid DOM element
|
|
200
211
|
|
|
201
212
|
if (!(anchorEl instanceof Element)) return;
|
|
202
213
|
const rect = anchorEl.getBoundingClientRect();
|
|
@@ -244,7 +255,7 @@ const BaseMenu = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
244
255
|
}, [open, anchorEl, anchorOrigin, transformOrigin, isInsidePopover]); // Click outside and escape handling (only when standalone)
|
|
245
256
|
|
|
246
257
|
useEffect(() => {
|
|
247
|
-
if (isInsidePopover || !open) return;
|
|
258
|
+
if (!canUseDOM() || isInsidePopover || !open) return;
|
|
248
259
|
|
|
249
260
|
const handleClickOutside = e => {
|
|
250
261
|
// Don't close if clicking inside the menu itself
|
|
@@ -290,10 +301,9 @@ const BaseMenu = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
290
301
|
}, [open, onClose, anchorEl, isInsidePopover, isClickInsideOverlay]); // Focus first item on open
|
|
291
302
|
|
|
292
303
|
useEffect(() => {
|
|
293
|
-
if (open
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
304
|
+
if (!canUseDOM() || !open || !autoFocus || !menuRef.current) return;
|
|
305
|
+
const firstItem = menuRef.current.querySelector('[role="menuitem"]:not([aria-disabled="true"])');
|
|
306
|
+
if (firstItem) firstItem.focus();
|
|
297
307
|
}, [open, autoFocus]);
|
|
298
308
|
if (!open && !keepMounted) return null;
|
|
299
309
|
|
|
@@ -342,7 +352,9 @@ const BaseMenu = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
342
352
|
}, props), /*#__PURE__*/React.createElement("ul", _extends({
|
|
343
353
|
style: listStyle
|
|
344
354
|
}, MenuListProps), children));
|
|
345
|
-
if (disablePortal) return content;
|
|
355
|
+
if (disablePortal) return content; // SSR safety - don't render portal until mounted
|
|
356
|
+
|
|
357
|
+
if (!mounted) return null;
|
|
346
358
|
return /*#__PURE__*/createPortal(content, document.body);
|
|
347
359
|
});
|
|
348
360
|
BaseMenu.displayName = "BaseMenu";
|
|
@@ -438,8 +450,8 @@ const BaseTabs = /*#__PURE__*/React.forwardRef((_ref4, ref) => {
|
|
|
438
450
|
const colorValue = (colors === null || colors === void 0 ? void 0 : colors[indicatorColor]) || (colors === null || colors === void 0 ? void 0 : colors.ibisRed);
|
|
439
451
|
typeof colorValue === "object" ? colorValue.main : colorValue || "ibisRed.main"; // Update indicator position
|
|
440
452
|
|
|
441
|
-
|
|
442
|
-
if (!tabsRef.current) return;
|
|
453
|
+
useIsomorphicLayoutEffect(() => {
|
|
454
|
+
if (!canUseDOM() || !tabsRef.current) return;
|
|
443
455
|
const tabs = tabsRef.current.querySelectorAll('[role="tab"]');
|
|
444
456
|
const selectedTab = Array.from(tabs).find((tab, index) => {
|
|
445
457
|
const tabValue = tab.dataset.value !== undefined ? tab.dataset.value : index;
|
|
@@ -763,6 +775,11 @@ const BaseSnackbar = /*#__PURE__*/React.forwardRef((_ref8, ref) => {
|
|
|
763
775
|
const {
|
|
764
776
|
colors
|
|
765
777
|
} = useTheme();
|
|
778
|
+
const [mounted, setMounted] = useState(false); // SSR safety
|
|
779
|
+
|
|
780
|
+
useEffect(() => {
|
|
781
|
+
setMounted(true);
|
|
782
|
+
}, []);
|
|
766
783
|
const startTimer = useCallback(() => {
|
|
767
784
|
if (autoHideDuration != null) {
|
|
768
785
|
timerRef.current = setTimeout(() => {
|
|
@@ -785,7 +802,7 @@ const BaseSnackbar = /*#__PURE__*/React.forwardRef((_ref8, ref) => {
|
|
|
785
802
|
}, [open, startTimer, stopTimer]); // Pause timer on window blur
|
|
786
803
|
|
|
787
804
|
useEffect(() => {
|
|
788
|
-
if (disableWindowBlurListener || !open) return;
|
|
805
|
+
if (!canUseDOM() || disableWindowBlurListener || !open) return;
|
|
789
806
|
|
|
790
807
|
const handleBlur = () => stopTimer();
|
|
791
808
|
|
|
@@ -801,7 +818,9 @@ const BaseSnackbar = /*#__PURE__*/React.forwardRef((_ref8, ref) => {
|
|
|
801
818
|
window.removeEventListener("focus", handleFocus);
|
|
802
819
|
};
|
|
803
820
|
}, [open, disableWindowBlurListener, startTimer, stopTimer]);
|
|
804
|
-
if (!open) return null;
|
|
821
|
+
if (!open) return null; // SSR safety - don't render portal until mounted
|
|
822
|
+
|
|
823
|
+
if (!mounted || !canUseDOM()) return null;
|
|
805
824
|
|
|
806
825
|
const positionStyles = _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
|
|
807
826
|
position: "fixed",
|
|
@@ -897,10 +916,15 @@ const BasePopover = /*#__PURE__*/React.forwardRef((_ref9, ref) => {
|
|
|
897
916
|
top: 0,
|
|
898
917
|
left: 0
|
|
899
918
|
});
|
|
919
|
+
const [mounted, setMounted] = useState(false);
|
|
900
920
|
const {
|
|
901
921
|
registerOverlay,
|
|
902
922
|
isClickInsideOverlay
|
|
903
|
-
} = useOverlayStack();
|
|
923
|
+
} = useOverlayStack(); // SSR safety
|
|
924
|
+
|
|
925
|
+
useEffect(() => {
|
|
926
|
+
setMounted(true);
|
|
927
|
+
}, []);
|
|
904
928
|
const combinedRef = useCallback(node => {
|
|
905
929
|
popoverRef.current = node;
|
|
906
930
|
|
|
@@ -922,8 +946,8 @@ const BasePopover = /*#__PURE__*/React.forwardRef((_ref9, ref) => {
|
|
|
922
946
|
return _objectSpread(_objectSpread({}, sxStyles), PaperProps.style);
|
|
923
947
|
}, [PaperProps.sx, PaperProps.style, colors]); // Calculate position
|
|
924
948
|
|
|
925
|
-
|
|
926
|
-
if (!open) return;
|
|
949
|
+
useIsomorphicLayoutEffect(() => {
|
|
950
|
+
if (!canUseDOM() || !open) return;
|
|
927
951
|
let top = 0;
|
|
928
952
|
let left = 0;
|
|
929
953
|
|
|
@@ -972,7 +996,7 @@ const BasePopover = /*#__PURE__*/React.forwardRef((_ref9, ref) => {
|
|
|
972
996
|
}, [open, anchorEl, anchorOrigin, transformOrigin, anchorPosition, anchorReference, marginThreshold]); // Click outside handling
|
|
973
997
|
|
|
974
998
|
useEffect(() => {
|
|
975
|
-
if (!open) return;
|
|
999
|
+
if (!canUseDOM() || !open) return;
|
|
976
1000
|
|
|
977
1001
|
const handleClickOutside = e => {
|
|
978
1002
|
// Use a small delay to ensure ref is populated after portal render
|
|
@@ -1045,7 +1069,9 @@ const BasePopover = /*#__PURE__*/React.forwardRef((_ref9, ref) => {
|
|
|
1045
1069
|
style: popoverStyle,
|
|
1046
1070
|
onClick: onClick
|
|
1047
1071
|
}, props), children));
|
|
1048
|
-
if (disablePortal) return content;
|
|
1072
|
+
if (disablePortal) return content; // SSR safety - don't render portal until mounted
|
|
1073
|
+
|
|
1074
|
+
if (!mounted) return null;
|
|
1049
1075
|
return /*#__PURE__*/createPortal(content, document.body);
|
|
1050
1076
|
});
|
|
1051
1077
|
BasePopover.displayName = "BasePopover";
|
|
@@ -1077,10 +1103,15 @@ const BaseDrawer = /*#__PURE__*/React.forwardRef((_ref10, ref) => {
|
|
|
1077
1103
|
colors
|
|
1078
1104
|
} = useTheme();
|
|
1079
1105
|
const [isVisible, setIsVisible] = useState(open);
|
|
1106
|
+
const [mounted, setMounted] = useState(false);
|
|
1080
1107
|
const {
|
|
1081
1108
|
registerOverlay
|
|
1082
1109
|
} = useOverlayStack();
|
|
1083
|
-
const drawerRef = useRef(null); //
|
|
1110
|
+
const drawerRef = useRef(null); // SSR safety
|
|
1111
|
+
|
|
1112
|
+
useEffect(() => {
|
|
1113
|
+
setMounted(true);
|
|
1114
|
+
}, []); // Resolve PaperProps.sx colors
|
|
1084
1115
|
|
|
1085
1116
|
const resolvedPaperStyle = useMemo(() => {
|
|
1086
1117
|
const sxStyles = PaperProps.sx ? resolveStyleColors(PaperProps.sx, colors) : {};
|
|
@@ -1103,13 +1134,12 @@ const BaseDrawer = /*#__PURE__*/React.forwardRef((_ref10, ref) => {
|
|
|
1103
1134
|
}, [open, transitionDuration]); // Lock body scroll for temporary drawers
|
|
1104
1135
|
|
|
1105
1136
|
useEffect(() => {
|
|
1106
|
-
if (open
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
}
|
|
1137
|
+
if (!canUseDOM() || !open || variant !== "temporary") return;
|
|
1138
|
+
const originalOverflow = document.body.style.overflow;
|
|
1139
|
+
document.body.style.overflow = "hidden";
|
|
1140
|
+
return () => {
|
|
1141
|
+
document.body.style.overflow = originalOverflow;
|
|
1142
|
+
};
|
|
1113
1143
|
}, [open, variant]);
|
|
1114
1144
|
const drawerWidth = (resolvedPaperStyle === null || resolvedPaperStyle === void 0 ? void 0 : resolvedPaperStyle.width) || ((_PaperProps$style = PaperProps.style) === null || _PaperProps$style === void 0 ? void 0 : _PaperProps$style.width) || "240px";
|
|
1115
1145
|
const drawerHeight = (resolvedPaperStyle === null || resolvedPaperStyle === void 0 ? void 0 : resolvedPaperStyle.height) || ((_PaperProps$style2 = PaperProps.style) === null || _PaperProps$style2 === void 0 ? void 0 : _PaperProps$style2.height) || "auto";
|
|
@@ -1194,7 +1224,9 @@ const BaseDrawer = /*#__PURE__*/React.forwardRef((_ref10, ref) => {
|
|
|
1194
1224
|
} // Temporary drawer - with backdrop
|
|
1195
1225
|
|
|
1196
1226
|
|
|
1197
|
-
if (!isVisible && !open) return null;
|
|
1227
|
+
if (!isVisible && !open) return null; // SSR safety - don't render portal until mounted
|
|
1228
|
+
|
|
1229
|
+
if (!mounted || !canUseDOM()) return null;
|
|
1198
1230
|
|
|
1199
1231
|
const backdropStyle = _objectSpread({
|
|
1200
1232
|
position: "fixed",
|
|
@@ -1258,11 +1290,16 @@ const BaseTooltip = /*#__PURE__*/React.forwardRef((_ref11, ref) => {
|
|
|
1258
1290
|
top: 0,
|
|
1259
1291
|
left: 0
|
|
1260
1292
|
});
|
|
1293
|
+
const [mounted, setMounted] = useState(false);
|
|
1261
1294
|
const anchorRef = useRef(null);
|
|
1262
1295
|
const tooltipRef = useRef(null);
|
|
1263
1296
|
const enterTimeoutRef = useRef(null);
|
|
1264
1297
|
const leaveTimeoutRef = useRef(null);
|
|
1265
|
-
const open = controlledOpen !== undefined ? controlledOpen : isOpen; //
|
|
1298
|
+
const open = controlledOpen !== undefined ? controlledOpen : isOpen; // SSR safety
|
|
1299
|
+
|
|
1300
|
+
useEffect(() => {
|
|
1301
|
+
setMounted(true);
|
|
1302
|
+
}, []); // Merge slotProps and componentsProps
|
|
1266
1303
|
|
|
1267
1304
|
const mergedSlotProps = _objectSpread(_objectSpread({}, componentsProps), slotProps); // Resolve tooltip styles
|
|
1268
1305
|
|
|
@@ -1298,7 +1335,7 @@ const BaseTooltip = /*#__PURE__*/React.forwardRef((_ref11, ref) => {
|
|
|
1298
1335
|
return _objectSpread(_objectSpread(_objectSpread({}, resolvedSx), popperSlotProps.style), popperPropsSx);
|
|
1299
1336
|
}, [mergedSlotProps, PopperProps, colors]);
|
|
1300
1337
|
const updatePosition = useCallback(() => {
|
|
1301
|
-
if (!anchorRef.current || !tooltipRef.current) return;
|
|
1338
|
+
if (!canUseDOM() || !anchorRef.current || !tooltipRef.current) return;
|
|
1302
1339
|
const anchorRect = anchorRef.current.getBoundingClientRect();
|
|
1303
1340
|
const tooltipRect = tooltipRef.current.getBoundingClientRect();
|
|
1304
1341
|
const offset = 8;
|
|
@@ -1444,8 +1481,9 @@ const BaseTooltip = /*#__PURE__*/React.forwardRef((_ref11, ref) => {
|
|
|
1444
1481
|
}
|
|
1445
1482
|
|
|
1446
1483
|
const clonedChild = /*#__PURE__*/React.cloneElement(childElement, childProps);
|
|
1447
|
-
if (!title) return clonedChild;
|
|
1448
|
-
|
|
1484
|
+
if (!title) return clonedChild; // SSR safety - don't render portal until mounted
|
|
1485
|
+
|
|
1486
|
+
const tooltipContent = open && mounted && canUseDOM() ? /*#__PURE__*/createPortal( /*#__PURE__*/React.createElement("div", {
|
|
1449
1487
|
ref: tooltipRef,
|
|
1450
1488
|
role: "tooltip",
|
|
1451
1489
|
style: _objectSpread(_objectSpread({}, tooltipStyle), popperStyle)
|
|
@@ -11,10 +11,14 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
11
11
|
|
|
12
12
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
13
13
|
|
|
14
|
+
const canUseDOM = () => typeof window !== 'undefined' && typeof document !== 'undefined'; // Global style cache to avoid re-injecting same styles
|
|
15
|
+
|
|
16
|
+
|
|
14
17
|
const styleCache = new Map();
|
|
15
18
|
let styleSheet = null;
|
|
16
19
|
|
|
17
20
|
function getStyleSheet() {
|
|
21
|
+
if (!canUseDOM()) return null;
|
|
18
22
|
if (styleSheet) return styleSheet; // Check for existing stylesheet
|
|
19
23
|
|
|
20
24
|
const existing = document.querySelector("style[data-blerp-sx]");
|
|
@@ -33,6 +37,8 @@ function getStyleSheet() {
|
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
function injectStyles(className, pseudoStyles, nestedStyles, mediaQueries, themeColors) {
|
|
40
|
+
if (!canUseDOM()) return;
|
|
41
|
+
|
|
36
42
|
if (!className) {
|
|
37
43
|
return;
|
|
38
44
|
}
|
|
@@ -55,7 +61,8 @@ function injectStyles(className, pseudoStyles, nestedStyles, mediaQueries, theme
|
|
|
55
61
|
|
|
56
62
|
if (css) {
|
|
57
63
|
try {
|
|
58
|
-
const sheet = getStyleSheet();
|
|
64
|
+
const sheet = getStyleSheet();
|
|
65
|
+
if (!sheet) return; // Split by newlines and insert each rule
|
|
59
66
|
|
|
60
67
|
css.split("\n").filter(Boolean).forEach(rule => {
|
|
61
68
|
try {
|
|
@@ -127,12 +134,12 @@ function withSx(Component) {
|
|
|
127
134
|
}, [sx, style, colors]); // Inject special styles (pseudo, nested, media queries)
|
|
128
135
|
|
|
129
136
|
useEffect(() => {
|
|
130
|
-
if (
|
|
137
|
+
if (canUseDOM() && pseudoClassName) {
|
|
131
138
|
injectStyles(pseudoClassName, pseudoStyles, nestedStyles, mediaQueries, colors);
|
|
132
139
|
}
|
|
133
140
|
}, [pseudoClassName, pseudoStyles, nestedStyles, mediaQueries, colors]); // Also inject synchronously for SSR/initial render
|
|
134
141
|
|
|
135
|
-
if (
|
|
142
|
+
if (canUseDOM() && pseudoClassName) {
|
|
136
143
|
injectStyles(pseudoClassName, pseudoStyles, nestedStyles, mediaQueries, colors);
|
|
137
144
|
} // Combine classNames
|
|
138
145
|
|