@geotab/zenith 3.6.0-ssr.beta.1 → 3.6.0

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.
@@ -76,7 +76,7 @@ const useDriveClassName_1 = require("../utils/theme/useDriveClassName");
76
76
  const useLanguage_1 = require("../utils/localization/useLanguage");
77
77
  const useUniqueId_1 = require("../commonHelpers/useUniqueId");
78
78
  const useFadeComponent_1 = require("../utils/useFadeComponent");
79
- // ...existing code...
79
+ const useClientReady_1 = require("../commonHelpers/hooks/useClientReady");
80
80
  const zen_1 = require("../utils/zen");
81
81
  // eslint-disable-next-line @typescript-eslint/naming-convention
82
82
  const MobileSheet = ({
@@ -140,12 +140,15 @@ const MobileSheet = ({
140
140
  return;
141
141
  }
142
142
  }, [onHidePanel, dataShieldId]);
143
- // ...existing code...
143
+ const isClientReady = (0, useClientReady_1.useClientReady)();
144
144
  (0, react_1.useEffect)(() => {
145
145
  setIsOpen(isOpen);
146
146
  }, [isOpen, setIsOpen]);
147
147
  (0, react_1.useEffect)(() => {
148
148
  var _a, _b, _c, _d;
149
+ if (!isClientReady) {
150
+ return;
151
+ }
149
152
  if (useTrapFocusWithTrigger) {
150
153
  return;
151
154
  }
@@ -153,7 +156,7 @@ const MobileSheet = ({
153
156
  return;
154
157
  }
155
158
  showContent && !preventFirstFocus && ((_d = (_c = ref.current) === null || _c === void 0 ? void 0 : _c.querySelector(focusableSelector_1.FOCUSABLE_SELECTOR)) === null || _d === void 0 ? void 0 : _d.focus());
156
- }, [content, showContent, readyForFocus, useTrapFocusWithTrigger, preventFirstFocus]);
159
+ }, [content, showContent, readyForFocus, useTrapFocusWithTrigger, preventFirstFocus, isClientReady]);
157
160
  (0, react_1.useEffect)(() => {
158
161
  var _a;
159
162
  if (triggerRef && !renderComponent && !readyForFocus && ((_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.getAttribute("aria-expanded")) === "true") {
@@ -161,6 +164,9 @@ const MobileSheet = ({
161
164
  triggerRef.current.focus();
162
165
  }
163
166
  }, [triggerRef, renderComponent, readyForFocus]);
167
+ if (!isClientReady) {
168
+ return null;
169
+ }
164
170
  if (!renderComponent && !isOpen) {
165
171
  return null;
166
172
  }
@@ -84,6 +84,7 @@ const dialogHelpers_1 = require("../dialog/dialogHelpers");
84
84
  const themeContext_1 = require("../utils/theme/themeContext");
85
85
  const modalHelpers_1 = require("./modalHelpers");
86
86
  const textIconButton_1 = require("../textIconButton/textIconButton");
87
+ const useClientReady_1 = require("../commonHelpers/hooks/useClientReady");
87
88
  const zen_1 = require("../utils/zen");
88
89
  const react_dom_1 = require("react-dom");
89
90
  const Modal = ({
@@ -100,26 +101,34 @@ const Modal = ({
100
101
  }) => {
101
102
  var _a, _b, _c;
102
103
  const lastActiveOutsideElement = (0, react_1.useRef)((_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.activeElement);
103
- // eslint-disable-next-line
104
- const modalRoot = ((_b = zen_1.zen === null || zen_1.zen === void 0 ? void 0 : zen_1.zen.document) === null || _b === void 0 ? void 0 : _b.fullscreenElement) || ((_c = zen_1.zen === null || zen_1.zen === void 0 ? void 0 : zen_1.zen.document) === null || _c === void 0 ? void 0 : _c.body);
105
104
  const [top, setTop] = (0, react_1.useState)(`${zen_1.zen.pageYOffset || 0}px`);
106
105
  const {
107
106
  dark
108
107
  } = (0, react_1.useContext)(themeContext_1.themeContext);
108
+ const isClientReady = (0, useClientReady_1.useClientReady)();
109
109
  const onOutSideClick = (0, react_1.useCallback)(() => {
110
+ if (!isClientReady) {
111
+ return;
112
+ }
110
113
  if (!isOpen || !closeOnClickOutside || !onClose) {
111
114
  return;
112
115
  }
113
116
  onClose();
114
- }, [isOpen, closeOnClickOutside, onClose]);
117
+ }, [isClientReady, isOpen, closeOnClickOutside, onClose]);
115
118
  (0, react_1.useEffect)(() => {
119
+ if (!isClientReady) {
120
+ return undefined;
121
+ }
116
122
  const copyActive = lastActiveOutsideElement.current;
117
123
  return () => {
118
124
  (0, dialogHelpers_1.isFocusable)(copyActive) && copyActive.focus();
119
125
  };
120
- }, []);
126
+ }, [isClientReady]);
121
127
  (0, react_1.useEffect)(() => {
122
128
  var _a, _b;
129
+ if (!isClientReady) {
130
+ return undefined;
131
+ }
123
132
  (_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.body.classList.remove("zen-modal-content--hidden-overflow");
124
133
  if (isOpen) {
125
134
  (_b = zen_1.zen.document) === null || _b === void 0 ? void 0 : _b.body.classList.add("zen-modal-content--hidden-overflow");
@@ -128,9 +137,12 @@ const Modal = ({
128
137
  var _a;
129
138
  (_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.body.classList.remove("zen-modal-content--hidden-overflow");
130
139
  };
131
- }, [isOpen]);
140
+ }, [isClientReady, isOpen]);
132
141
  (0, react_1.useEffect)(() => {
133
142
  var _a, _b;
143
+ if (!isClientReady) {
144
+ return undefined;
145
+ }
134
146
  const changeTopSpace = () => {
135
147
  setTop(`${zen_1.zen.pageYOffset || 0}px`);
136
148
  };
@@ -141,7 +153,7 @@ const Modal = ({
141
153
  (_a = zen_1.zen.removeEventListener) === null || _a === void 0 ? void 0 : _a.call(zen_1.zen, "resize", changeTopSpace);
142
154
  (_b = zen_1.zen.removeEventListener) === null || _b === void 0 ? void 0 : _b.call(zen_1.zen, "scroll", changeTopSpace);
143
155
  };
144
- }, []);
156
+ }, [isClientReady]);
145
157
  const labeledId = (0, react_1.useId)();
146
158
  const darkClass = dark ? "zen-dark" : "";
147
159
  const modalContent = (0, react_1.useMemo)(() => {
@@ -176,10 +188,11 @@ const Modal = ({
176
188
  onClick: onOutSideClick
177
189
  })]
178
190
  }), [darkClass, modalContainerClassName, labeledId, top, onClose, maxWidth, title, className, type, focus, modalContent, onOutSideClick]);
179
- if (!isOpen) {
191
+ if (!isOpen || !isClientReady) {
180
192
  return null;
181
193
  }
182
- return (0, react_dom_1.createPortal)(dialogHTML(labeledId), modalRoot, "ModalPortal" + labeledId);
194
+ const modalRoot = ((_b = zen_1.zen.document) === null || _b === void 0 ? void 0 : _b.fullscreenElement) || ((_c = zen_1.zen.document) === null || _c === void 0 ? void 0 : _c.body);
195
+ return (0, react_dom_1.createPortal)(dialogHTML(labeledId), modalRoot);
183
196
  };
184
197
  exports.Modal = Modal;
185
198
  const dummyOnClose = () => {};
@@ -202,10 +215,10 @@ const DialogContentNew = ({
202
215
  const lastActiveOutsideElement = (0, react_1.useRef)((_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.activeElement);
203
216
  const iconDriveClassName = (0, useDriveClassName_1.useDriveClassName)("icon");
204
217
  const iconsByType = (0, react_1.useMemo)(() => ({
205
- "error": iconException_1.IconException,
206
- "success": iconCheckRadio_1.IconCheckRadio,
207
- "warning": iconWarning_1.IconWarning,
208
- "info": iconInfoCircle_1.IconInfoCircle
218
+ error: iconException_1.IconException,
219
+ success: iconCheckRadio_1.IconCheckRadio,
220
+ warning: iconWarning_1.IconWarning,
221
+ info: iconInfoCircle_1.IconInfoCircle
209
222
  }), []);
210
223
  const subscriptionCondition = (0, react_1.useCallback)(trigger => trigger.current !== null, []);
211
224
  (0, useTrapFocus_1.useTrapFocus)(contentRef, undefined, contentRef, subscriptionCondition);
@@ -14,10 +14,8 @@ const collapsedItemsControl_1 = require("../header/components/collapsedItemsCont
14
14
  const pageHeaderButton_1 = require("./pageHeaderButton");
15
15
  const pageHeaderMenu_1 = require("./pageHeaderMenu");
16
16
  const pageHeaderHelpers_1 = require("./pageHeaderHelpers");
17
- const react_dom_1 = require("react-dom");
18
- const zen_1 = require("../utils/zen");
17
+ const usePortal_1 = require("../commonHelpers/hooks/usePortal");
19
18
  const PageHeaderActions = ({ className = "", children }) => {
20
- var _a;
21
19
  const isMobile = (0, useMobile_1.useMobile)();
22
20
  const childrenArray = (0, react_1.useMemo)(() => (0, pageHeaderHelpers_1.getItemsFromFragments)(
23
21
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
@@ -34,9 +32,10 @@ const PageHeaderActions = ({ className = "", children }) => {
34
32
  }), [childrenArray]);
35
33
  const moreButton = (0, react_1.useMemo)(() => ((0, jsx_runtime_1.jsx)(collapsedItemsControl_1.PageToolbarCollapsedItemsControl, { className: "zen-page-header-component__actions-more", children: nonFittingElements }, "page-header-more-actions-key")), [nonFittingElements]);
36
34
  const actionsContent = childrenArray.length ? ((0, jsx_runtime_1.jsxs)("div", { className: (0, classNames_1.classNames)(["zen-page-header-component__actions", isMobile ? "zen-page-header-component__actions--mobile-portal" : "", className]), children: [nonFittingElements.length > 0 ? moreButton : null, fittingElements] })) : null;
35
+ const portal = (0, usePortal_1.usePortal)(actionsContent);
37
36
  // For mobile, render actions in a portal at the bottom center of viewport
38
37
  if (isMobile && actionsContent) {
39
- return (0, react_dom_1.createPortal)(actionsContent, (_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.body);
38
+ return portal;
40
39
  }
41
40
  return actionsContent;
42
41
  };
@@ -11,13 +11,14 @@ const useTrapFocus_1 = require("../commonHelpers/hooks/useTrapFocus");
11
11
  const isChildOf_1 = require("../utils/isChildOf");
12
12
  const getParentByClass_1 = require("../utils/getParentByClass");
13
13
  const sidePanelCell_1 = require("./sidePanelCell/sidePanelCell");
14
- const react_dom_1 = require("react-dom");
15
14
  const useDriveClassName_1 = require("../utils/theme/useDriveClassName");
16
15
  const themeContext_1 = require("../utils/theme/themeContext");
17
16
  const useFadeComponent_1 = require("../utils/useFadeComponent");
18
17
  const useMobile_1 = require("../commonHelpers/hooks/useMobile");
19
18
  const isAlertTarget_1 = require("../alert/utils/isAlertTarget");
20
19
  const isToastTarget_1 = require("../toast/utils/isToastTarget");
20
+ const usePortal_1 = require("../commonHelpers/hooks/usePortal");
21
+ const useClientReady_1 = require("../commonHelpers/hooks/useClientReady");
21
22
  const zen_1 = require("../utils/zen");
22
23
  /* eslint-enable @typescript-eslint/naming-convention */
23
24
  const isChildPopup = (target, stopElement) => {
@@ -65,15 +66,16 @@ const SidePanel = ({ label, className, id, isOpen, onHidePanel, children, trigge
65
66
  const autoId = (0, react_1.useId)();
66
67
  const popupId = id || autoId;
67
68
  const prevReadyForFocus = (0, react_1.useRef)(false);
69
+ const isClientReady = (0, useClientReady_1.useClientReady)();
68
70
  (0, react_1.useEffect)(() => {
69
- if (triggerRef && triggerRef.current) {
71
+ if (triggerRef && triggerRef.current && isClientReady) {
70
72
  const triggerRole = triggerRef.current.dataset.role;
71
73
  triggerRef.current.setAttribute("aria-haspopup", triggerRole ? triggerRole : "true");
72
74
  triggerRef.current.setAttribute("aria-expanded", renderComponent ? "true" : "false");
73
75
  triggerRef.current.setAttribute("aria-controls", popupId);
74
76
  triggerRef.current.setAttribute("data-popup-id", popupId);
75
77
  }
76
- }, [triggerRef, renderComponent, popupId]);
78
+ }, [triggerRef, renderComponent, popupId, isClientReady]);
77
79
  function handleEscape() {
78
80
  onHidePanel(SidePanelCloseReason.Escape);
79
81
  if (!triggerRef || !triggerRef.current) {
@@ -86,10 +88,13 @@ const SidePanel = ({ label, className, id, isOpen, onHidePanel, children, trigge
86
88
  const focusable = Array.from(triggerRef.current.querySelectorAll(focusableSelector_1.FOCUSABLE_SELECTOR));
87
89
  (focusable[0] || triggerRef.current).focus();
88
90
  }
89
- (0, useTrapFocus_1.useTrapFocus)(sidePanelRef, useTrapFocusWithTrigger ? triggerRef : undefined, showContent);
90
- (0, useEscape_1.useEscape)(sidePanelRef, handleEscape, renderComponent);
91
+ (0, useTrapFocus_1.useTrapFocus)(sidePanelRef, useTrapFocusWithTrigger ? triggerRef : undefined, showContent && isClientReady);
92
+ (0, useEscape_1.useEscape)(sidePanelRef, handleEscape, renderComponent && isClientReady);
91
93
  (0, react_1.useEffect)(() => {
92
94
  var _a, _b, _c;
95
+ if (!isClientReady) {
96
+ return undefined;
97
+ }
93
98
  // eslint-disable-next-line complexity
94
99
  const closeOnClickOutside = (e) => {
95
100
  var _a, _b, _c, _d, _e, _f;
@@ -117,7 +122,7 @@ const SidePanel = ({ label, className, id, isOpen, onHidePanel, children, trigge
117
122
  || isOpenPeriodPicker && (0, isChildOf_1.isChildOf)(e.target, isOpenPeriodPicker)
118
123
  || isOpenPeriodPicker && isOpenTimePicker && (0, isChildOf_1.isChildOf)(e.target, isOpenTimePicker)
119
124
  || isOpenPeriodPicker && isOpenYearPicker && (0, isChildOf_1.isChildOf)(e.target, isOpenYearPicker)
120
- || openedCustomComponents.length && Array.from(openedCustomComponents).some(el => (0, isChildOf_1.isChildOf)(e.target, el));
125
+ || (openedCustomComponents === null || openedCustomComponents === void 0 ? void 0 : openedCustomComponents.length) && Array.from(openedCustomComponents).some(el => (0, isChildOf_1.isChildOf)(e.target, el));
121
126
  const isClickInPopup = !isClickInChildPopup
122
127
  ? false
123
128
  : isClickInChildPopup;
@@ -147,7 +152,7 @@ const SidePanel = ({ label, className, id, isOpen, onHidePanel, children, trigge
147
152
  prevReadyForFocus.current = false;
148
153
  }
149
154
  return () => { var _a; return (_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.body.removeEventListener("click", closeOnClickOutside, true); };
150
- }, [renderComponent, readyForFocus, onHidePanel, triggerRef, useTrapFocusWithTrigger, preventFirstFocus]);
155
+ }, [renderComponent, readyForFocus, onHidePanel, triggerRef, useTrapFocusWithTrigger, preventFirstFocus, isClientReady]);
151
156
  (0, react_1.useEffect)(() => {
152
157
  setIsOpen(isOpen);
153
158
  }, [isOpen, setIsOpen]);
@@ -161,17 +166,22 @@ const SidePanel = ({ label, className, id, isOpen, onHidePanel, children, trigge
161
166
  }
162
167
  return {};
163
168
  }, [width, isMobile, panelPosition]);
164
- if (!renderComponent && !isOpen) {
165
- return null;
166
- }
167
- return (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: sidePanelRef, id: popupId }, memoizedStyles, { role: "dialog", "aria-label": label, onTransitionEnd: handleTransitionEnd, className: (0, classNames_1.classNames)([
169
+ const portalContainer = ((_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.fullscreenElement) || ((_b = zen_1.zen.document) === null || _b === void 0 ? void 0 : _b.body);
170
+ const portal = (0, usePortal_1.usePortal)((0, jsx_runtime_1.jsx)("div", Object.assign({ ref: sidePanelRef, id: popupId }, memoizedStyles, { role: "dialog", "aria-label": label, onTransitionEnd: handleTransitionEnd, className: (0, classNames_1.classNames)([
168
171
  "zen-side-panel",
169
172
  driveClassName || "",
170
173
  dark ? "zen-dark" : "",
171
174
  showContent ? "zen-side-panel--shown" : "",
172
175
  positioningClass,
173
176
  className !== null && className !== void 0 ? className : ""
174
- ]), children: memoizedChildForRender })), ((_a = zen_1.zen.document) === null || _a === void 0 ? void 0 : _a.fullscreenElement) || ((_b = zen_1.zen.document) === null || _b === void 0 ? void 0 : _b.body));
177
+ ]), children: memoizedChildForRender })), portalContainer);
178
+ if (!renderComponent && !isOpen) {
179
+ return null;
180
+ }
181
+ if (!isClientReady) {
182
+ return undefined;
183
+ }
184
+ return portal;
175
185
  };
176
186
  exports.SidePanel = SidePanel;
177
187
  exports.SidePanel.Cell = sidePanelCell_1.SidePanelCell;
@@ -24,4 +24,4 @@ export interface IAbsolute extends IZenComponentProps {
24
24
  recalculateOnScroll?: boolean;
25
25
  recalculateTrigger?: boolean;
26
26
  }
27
- export declare const Absolute: ({ isOpen, id, paddingX, paddingY, className, children, triggerRef, alignment, inline, onOpenChange, useTrapFocusWithTrigger, shouldHoldScroll, stateFullChilds, role, ariaLabel, ariaLabelledby, alignmentsFn, recalculateOnScroll, recalculateTrigger }: IAbsolute) => import("react/jsx-runtime").JSX.Element | "";
27
+ export declare const Absolute: ({ isOpen, id, paddingX, paddingY, className, children, triggerRef, alignment, inline, onOpenChange, useTrapFocusWithTrigger, shouldHoldScroll, stateFullChilds, role, ariaLabel, ariaLabelledby, alignmentsFn, recalculateOnScroll, recalculateTrigger }: IAbsolute) => import("react/jsx-runtime").JSX.Element | "" | null;
@@ -14,13 +14,13 @@ import { useArrowKey } from "../commonHelpers/hooks/useArrowKey";
14
14
  import { themeContext } from "../utils/theme/themeContext";
15
15
  import { useScroll } from "../commonHelpers/hooks/useScroll";
16
16
  import { getScrollableParent } from "../utils/getScrollableParent";
17
- // ...existing code...
17
+ import { useClientReady } from "../commonHelpers/hooks/useClientReady";
18
18
  import { zen } from "../utils/zen";
19
19
  export const Absolute = ({ isOpen, id, paddingX, paddingY, className, children, triggerRef, alignment, inline, onOpenChange, useTrapFocusWithTrigger = "off", shouldHoldScroll, stateFullChilds, role, ariaLabel, ariaLabelledby, alignmentsFn, recalculateOnScroll, recalculateTrigger = true }) => {
20
20
  const popupRef = useRef(null);
21
21
  const prevScroll = useRef(0);
22
22
  const { dark } = useContext(themeContext);
23
- // ...existing code...
23
+ const isClientReady = useClientReady();
24
24
  const onScrollHandler = e => {
25
25
  var _a;
26
26
  prevScroll.current = (_a = e.target) === null || _a === void 0 ? void 0 : _a.scrollTop;
@@ -113,7 +113,7 @@ export const Absolute = ({ isOpen, id, paddingX, paddingY, className, children,
113
113
  calculatePosition();
114
114
  }
115
115
  return () => { };
116
- }, [calculatePosition, children, isOpen]);
116
+ }, [calculatePosition, children, isOpen, isClientReady]);
117
117
  useEffect(() => {
118
118
  if (isOpen) {
119
119
  if (popupRef.current && prevScroll.current && shouldHoldScroll) {
@@ -124,5 +124,8 @@ export const Absolute = ({ isOpen, id, paddingX, paddingY, className, children,
124
124
  prevScroll.current = 0;
125
125
  }
126
126
  }, [children, isOpen, shouldHoldScroll]);
127
+ if (!isClientReady) {
128
+ return null;
129
+ }
127
130
  return renderPopup();
128
131
  };
@@ -2,11 +2,13 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useEffect, useId } from "react";
3
3
  import { Absolute } from "../absolute/absolute";
4
4
  import { classNames } from "../commonHelpers/classNames/classNames";
5
+ import { useClientReady } from "../commonHelpers/hooks/useClientReady";
5
6
  export const ControlledPopup = ({ isOpen, id, paddingX, paddingY, triggerRef, className, children, alignment, inline, onOpenChange, useTrapFocusWithTrigger, shouldHoldScroll, ariaLabel, ariaLabelledby, recalculateOnScroll, preventAttributesAutoSet }) => {
6
7
  const autoId = useId();
7
8
  const popupId = id || autoId;
9
+ const isClientReady = useClientReady();
8
10
  useEffect(() => {
9
- if (!triggerRef.current) {
11
+ if (!triggerRef.current || !isClientReady) {
10
12
  return;
11
13
  }
12
14
  triggerRef.current.setAttribute("data-popup-id", popupId);
@@ -18,6 +20,6 @@ export const ControlledPopup = ({ isOpen, id, paddingX, paddingY, triggerRef, cl
18
20
  triggerRef.current.setAttribute("aria-haspopup", triggerRole ? triggerRole : refTriggerRole === "menuitem" ? "menu" : "true");
19
21
  triggerRef.current.setAttribute("aria-expanded", isOpen ? "true" : "false");
20
22
  triggerRef.current.setAttribute("aria-controls", popupId);
21
- }, [triggerRef, isOpen, popupId, preventAttributesAutoSet]);
23
+ }, [triggerRef, isOpen, popupId, preventAttributesAutoSet, isClientReady]);
22
24
  return (_jsx(Absolute, { triggerRef: triggerRef, alignment: alignment, id: popupId, isOpen: isOpen, className: classNames(["zen-popup", className ? className : ""]), paddingX: paddingX, paddingY: paddingY, inline: inline, onOpenChange: onOpenChange, useTrapFocusWithTrigger: useTrapFocusWithTrigger, shouldHoldScroll: shouldHoldScroll, role: "dialog", ariaLabel: ariaLabel, ariaLabelledby: ariaLabelledby, recalculateOnScroll: recalculateOnScroll, children: children }));
23
25
  };
@@ -9,4 +9,4 @@ export interface IDialog {
9
9
  /**
10
10
  * @deprecated - use Modal instead
11
11
  */
12
- export declare const Dialog: ({ isOpen, children, isElementVisible }: IDialog) => import("react").ReactPortal;
12
+ export declare const Dialog: ({ isOpen, children, isElementVisible }: IDialog) => import("react").ReactPortal | null;
@@ -5,8 +5,9 @@ import { isFocusable } from "./dialogHelpers";
5
5
  import { themeContext } from "../utils/theme/themeContext";
6
6
  import { classNames } from "../commonHelpers/classNames/classNames";
7
7
  import { useBodyScroll } from "../utils/useBodyScroll";
8
+ import { usePortal } from "../commonHelpers/hooks/usePortal";
9
+ import { useClientReady } from "../commonHelpers/hooks/useClientReady";
8
10
  import { zen } from "../utils/zen";
9
- import { createPortal } from "react-dom";
10
11
  /**
11
12
  * @deprecated - use Modal instead
12
13
  */
@@ -16,14 +17,21 @@ export const Dialog = ({ isOpen, children, isElementVisible }) => {
16
17
  const modalRoot = ((_b = zen.document) === null || _b === void 0 ? void 0 : _b.fullscreenElement) || ((_c = zen.document) === null || _c === void 0 ? void 0 : _c.body);
17
18
  const { dark } = useContext(themeContext);
18
19
  const { resetScroll } = useBodyScroll();
20
+ const isClientReady = useClientReady();
19
21
  useEffect(() => {
22
+ if (!isClientReady) {
23
+ return () => { };
24
+ }
20
25
  const copyActive = lastActiveOutsideElement.current;
21
26
  return () => {
22
27
  isFocusable(copyActive) && copyActive.focus();
23
28
  };
24
- }, []);
29
+ }, [isClientReady]);
25
30
  useEffect(() => {
26
31
  var _a;
32
+ if (!isClientReady) {
33
+ return;
34
+ }
27
35
  if (isOpen) {
28
36
  return;
29
37
  }
@@ -31,9 +39,13 @@ export const Dialog = ({ isOpen, children, isElementVisible }) => {
31
39
  if (!(modalCont === null || modalCont === void 0 ? void 0 : modalCont.length)) {
32
40
  resetScroll();
33
41
  }
34
- }, [isOpen, resetScroll]);
42
+ }, [isClientReady, isOpen, resetScroll]);
35
43
  const labeledId = useId();
36
44
  const darkClass = dark ? "zen-dark" : "";
37
45
  const createDialog = (id) => _jsxs("div", { className: classNames(["zen-dialog", darkClass]), "aria-modal": "true", role: "dialog", "aria-labelledby": labeledId, style: { top: `${zen.pageYOffset || 0}px` }, children: [_jsx(DialogContent, Object.assign({}, children.props, { labeledId: id, isElementVisible: isElementVisible })), _jsx("div", { className: "zen-dialog__shield" })] });
38
- return createPortal(isOpen && isValidElement(children) ? createDialog(labeledId) : null, modalRoot, "ModalPortal");
46
+ const portal = usePortal(isOpen && isValidElement(children) ? createDialog(labeledId) : null, modalRoot, "ModalPortal");
47
+ if (!isClientReady) {
48
+ return null;
49
+ }
50
+ return portal;
39
51
  };
@@ -2,18 +2,21 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
2
2
  import React, { useMemo } from "react";
3
3
  import { FeedbackContext } from "./feedbackContext";
4
4
  import { AlertRaw } from "../alertRaw/alertRaw";
5
- import { createPortal } from "react-dom";
6
5
  import { useMobile } from "../commonHelpers/hooks/useMobile";
7
6
  import { ToastRaw } from "../toastRaw/toastRaw";
8
7
  import { classNames } from "../commonHelpers/classNames/classNames";
9
8
  import { getAlertAnimation } from "./utils/getAlertAnimation";
10
9
  import { getToastAnimation } from "./utils/getToastAnimation";
10
+ import { usePortal } from "../commonHelpers/hooks/usePortal";
11
+ import { useClientReady } from "../commonHelpers/hooks/useClientReady";
11
12
  import { zen } from "../utils/zen";
12
13
  export const FeedbackContainer = () => {
14
+ var _a, _b;
13
15
  const { alerts, removeAlert, toasts, removeToast, activeFeedback, removedAlertId, removedToastId, mode } = React.useContext(FeedbackContext);
14
16
  const prevAlertsLength = React.useRef(alerts.length);
15
17
  const prevToastsLength = React.useRef(toasts.length);
16
18
  const isAPIMode = mode === "api";
19
+ const isClientReady = useClientReady();
17
20
  const isMobile = useMobile();
18
21
  const isAlertAdded = alerts.length > prevAlertsLength.current;
19
22
  const isToastAdded = toasts.length > prevToastsLength.current;
@@ -34,18 +37,15 @@ export const FeedbackContainer = () => {
34
37
  }, type: alert.type, animation: alert.animation || (sameAlertsLength ? null : getAlertAnimation(isAlertAdded, indx, removedAlertId.current, isMobile, activeFeedback)), buttons: alert.buttons, className: alert.className }, alert.id)), [alerts, isMobile, isAlertAdded, removeAlert, activeFeedback, sameAlertsLength, removedAlertId]);
35
38
  const alertClasses = useMemo(() => classNames(["zen-alerts", isMobile ? "zen-alerts--mobile" : ""]), [isMobile]);
36
39
  const toastClasses = useMemo(() => classNames(["zen-toasts", isMobile ? "zen-toasts--mobile" : ""]), [isMobile]);
37
- const alertsPortal = useMemo(() => {
38
- var _a;
39
- return createPortal(_jsx("div", { className: alertClasses, children: alertsToRender }), (_a = zen.document) === null || _a === void 0 ? void 0 : _a.body);
40
- }, [alertsToRender, alertClasses]);
41
40
  const toastsToRender = useMemo(() => toasts.map((toast, indx, arr) => _jsx(ToastRaw, { id: toast.id, animation: toast.animation || (sameToastsLength ? null : getToastAnimation(isToastAdded, indx, removedToastId.current, arr.length, isMobile, activeFeedback)), header: toast.header, showSeconds: toast.showSeconds, className: toast.className, isOpen: true, onClose: () => {
42
41
  removeToast(toast.id);
43
42
  removedToastId.current = indx;
44
43
  toast.onClose();
45
44
  }, type: toast.type, hasIcon: toast.hasIcon, action: toast.action }, toast.id)), [toasts, sameToastsLength, isToastAdded, removedToastId, isMobile, activeFeedback, removeToast]);
46
- const toastsPortal = useMemo(() => {
47
- var _a;
48
- return createPortal(_jsx("div", { className: toastClasses, children: toastsToRender }), (_a = zen.document) === null || _a === void 0 ? void 0 : _a.body);
49
- }, [toastsToRender, toastClasses]);
45
+ const alertsPortal = usePortal(_jsx("div", { className: alertClasses, children: alertsToRender }), (_a = zen.document) === null || _a === void 0 ? void 0 : _a.body);
46
+ const toastsPortal = usePortal(_jsx("div", { className: toastClasses, children: toastsToRender }), (_b = zen.document) === null || _b === void 0 ? void 0 : _b.body);
47
+ if (!isClientReady) {
48
+ return null;
49
+ }
50
50
  return _jsxs(_Fragment, { children: [!isAPIMode && alertsPortal, !isAPIMode && toastsPortal] });
51
51
  };
@@ -21,6 +21,7 @@ import { useSearchComponent } from "./filtersBarProviderSearch";
21
21
  import { useMobileTrigger } from "./filtersBarProviderTrigger";
22
22
  import { FOCUSABLE_SELECTOR } from "../utils/focusableSelector";
23
23
  import { FiltersBarDateInput } from "./components/filtersBarDateInput/filtersBarDateInput";
24
+ import { useClientReady } from "../commonHelpers/hooks/useClientReady";
24
25
  /* eslint-enable @typescript-eslint/naming-convention */
25
26
  export const FiltersBarDisplayName = "FiltersBar";
26
27
  const getChildren = (children) => (!children
@@ -83,7 +84,7 @@ export const FiltersBar = ({ className, children, isAllFiltersVisible, hideAllFi
83
84
  const stateFromChildren = useMemo(() => getCurrentFiltersState(filterBarChildren), [filterBarChildren]);
84
85
  const [filtersBarState, dispatchFiltersBarState] = useReducer(filtersBarReducer, getInitialFiltersBarState(stateFromChildren, getDefaultFiltersState, onApplyAllFilters === undefined));
85
86
  const [sidePanelState, dispatchSidePanelState] = useReducer(sidePanelReducer, stateFromChildren);
86
- // ...existing code...
87
+ const isClientReady = useClientReady();
87
88
  useEffect(() => {
88
89
  // need for dynamic items loading
89
90
  if (Object.keys(stateFromChildren).length > Object.keys(sidePanelState).length) {
@@ -195,6 +196,9 @@ export const FiltersBar = ({ className, children, isAllFiltersVisible, hideAllFi
195
196
  pillName, pillIcon, pillType, sidePanelState, filterBarChildren]);
196
197
  const noActions = useMemo(() => isAllFiltersButtonHidden && (selectedQuantity === undefined && filtersBarState.currentNumberOfChangedFilters === 0 || selectedQuantity === 0)
197
198
  && (!isApplyButtonShown || onApplyAllFilters === undefined), [isAllFiltersButtonHidden, selectedQuantity, filtersBarState.currentNumberOfChangedFilters, isApplyButtonShown, onApplyAllFilters]);
199
+ if (!isClientReady) {
200
+ return null;
201
+ }
198
202
  return _jsxs(_Fragment, { children: [!isMobile && _jsxs("div", { ref: toolbarRef, className: classNames(["zen-filters-toolbar", noActions ? "zen-filters-toolbar--no-actions" : "", className !== null && className !== void 0 ? className : ""]), children: [_jsx(FiltersContainer, { children: filterBarChildren }), _jsx(FiltersBarActions, { allFiltersRef: allFiltersRef, onShowAllFilters: () => toggleAllFiltersCallback(true), onClearFilters: handleClearClick, selectedQuantity: selectedQuantity !== undefined ? selectedQuantity : filtersBarState.currentNumberOfChangedFilters, selectedQuantityToDisplay: selectedQuantity !== undefined ? selectedQuantity : filtersBarState.numberOfChangedFilters, hideAllFiltersButton: isAllFiltersButtonHidden, onApplyButtonClick: onApplyAllFilters ? handleApplyAllFilters(false) : undefined, isApplyButtonShown: isApplyButtonShown })] }), !isAllFiltersButtonHidden ? sidePanel : null] });
199
203
  };
200
204
  FiltersBar.Search = FiltersBarSearch;
@@ -295,8 +295,13 @@ export const GroupsFilterRaw = props => {
295
295
  const prevSearchField = useRef("");
296
296
  const groupsFilterId = useId();
297
297
  const popupId = useId();
298
- const isDataLoadedRef = useRef(false);
299
298
  const blocksMap = useMemo(() => [["builtInGroups", "userGroups"], ["advancedGroups", "builtInGroups", "userGroups"], ["builtInGroups", "userGroups"]], []);
299
+ const onOptionsToggle = useCallback(() => {
300
+ dispatchUiState({
301
+ type: UiStateActionType.ToggleOpen,
302
+ payload: undefined
303
+ });
304
+ }, []);
300
305
  const handleSetStep = useCallback(newStep => {
301
306
  var _a;
302
307
  uiState.step !== FilterMenuStep.CurrentlySelected && dispatchUiState({
@@ -545,8 +550,7 @@ export const GroupsFilterRaw = props => {
545
550
  errorHandler(e);
546
551
  return [];
547
552
  }), [dataLoader, errorHandler]);
548
- const loadData = useCallback(() => {
549
- isDataLoadedRef.current = true;
553
+ useEffect(() => {
550
554
  dispatchUiState({
551
555
  type: UiStateActionType.SetLoadWithError,
552
556
  payload: {
@@ -575,32 +579,9 @@ export const GroupsFilterRaw = props => {
575
579
  isLoading: false
576
580
  }
577
581
  });
578
- isDataLoadedRef.current = false;
579
582
  errorHandler(e);
580
583
  });
581
584
  }, [dataLoader, errorHandler]);
582
- useEffect(() => {
583
- if (isDataLoadedRef.current) {
584
- return;
585
- }
586
- loadData();
587
- }, [loadData]);
588
- const onOptionsToggle = useCallback(() => {
589
- const willBeOpen = !uiState.isOpen;
590
- dispatchUiState({
591
- type: UiStateActionType.ToggleOpen,
592
- payload: undefined
593
- });
594
- if (willBeOpen && !isDataLoadedRef.current && !uiState.isLoading) {
595
- loadData();
596
- }
597
- }, [uiState.isOpen, uiState.isLoading, loadData]);
598
- const isEmptyMap = dataItems.length === 0;
599
- useEffect(() => {
600
- if (isEmptyMap && uiState.isOpen && !uiState.isLoading && !uiState.hasError) {
601
- loadData();
602
- }
603
- }, [uiState.isOpen, isEmptyMap, uiState.isLoading, uiState.hasError, loadData]);
604
585
  useEffect(() => {
605
586
  const step = uiState.step;
606
587
  if (step !== FilterMenuStep.CurrentlySelected) {
@@ -841,6 +822,41 @@ export const GroupsFilterRaw = props => {
841
822
  children: translate("Clear")
842
823
  })]
843
824
  }), [handleApply, handleCancel, handleReset, isApplyDisabled, translate]);
825
+ const isEmptyMap = dataItems.length === 0;
826
+ useEffect(() => {
827
+ if (isEmptyMap && uiState.isOpen && !uiState.isLoading && !uiState.hasError) {
828
+ dispatchUiState({
829
+ type: UiStateActionType.SetLoadWithError,
830
+ payload: {
831
+ hasError: false,
832
+ isLoading: true
833
+ }
834
+ });
835
+ dataLoader().then(groups => {
836
+ dispatchState({
837
+ type: StateActionType.CreateGroupsMap,
838
+ payload: groups
839
+ });
840
+ dispatchUiState({
841
+ type: UiStateActionType.SetLoadWithError,
842
+ payload: {
843
+ hasError: false,
844
+ isLoading: false
845
+ }
846
+ });
847
+ setDataItems(groups);
848
+ }).catch(e => {
849
+ dispatchUiState({
850
+ type: UiStateActionType.SetLoadWithError,
851
+ payload: {
852
+ hasError: true,
853
+ isLoading: false
854
+ }
855
+ });
856
+ errorHandler(e);
857
+ });
858
+ }
859
+ }, [uiState.isOpen, isEmptyMap, uiState.isLoading, uiState.hasError, dataLoader, errorHandler]);
844
860
  const memoizedMobileView = useMemo(() => _jsxs(MobileSheet, {
845
861
  label: translate("Organization groups filter"),
846
862
  triggerRef: triggerRef,
@@ -23,7 +23,7 @@ import { SearchContextProvider } from "../filtersBar/filtersBarProviderSearch";
23
23
  import { useDriveClassName } from "../utils/theme/useDriveClassName";
24
24
  import { TriggerContextProvider } from "../filtersBar/filtersBarProviderTrigger";
25
25
  import { useHeaderButtons } from "../utils/headerButtons/headerButtonsProvider";
26
- // ...existing code...
26
+ import { useClientReady } from "../commonHelpers/hooks/useClientReady";
27
27
  import { zen } from "../utils/zen";
28
28
  export var HeaderType;
29
29
  (function (HeaderType) {
@@ -35,7 +35,7 @@ export const Header = ({ children, className, onFiltersBarOpen
35
35
  // eslint-disable-next-line complexity
36
36
  }) => {
37
37
  var _a, _b;
38
- // ...existing code...
38
+ const isClientReady = useClientReady();
39
39
  const toolbarRef = useRef(null);
40
40
  const leftElementsRef = useRef(null);
41
41
  const rightElementsRef = useRef(null);
@@ -168,7 +168,7 @@ export const Header = ({ children, className, onFiltersBarOpen
168
168
  }, [result === null || result === void 0 ? void 0 : result.contentRect.width, calculateMiddleWidth]);
169
169
  useEffect(() => {
170
170
  calculateMiddleWidth();
171
- }, [calculateMiddleWidth]);
171
+ }, [calculateMiddleWidth, isClientReady]);
172
172
  const moreButton = useMemo(() => _jsx(PageToolbarCollapsedItemsControl, { children: nonFittingElements }, "pageCollapsedToolbar"), [nonFittingElements]);
173
173
  const mobileSearch = useMemo(() => searchComponent && memoizedFiltersBar ? (_jsx(MobileSearchControl, { state: searchExpandedState, searchInput: searchComponent, onClick: (state) => setSearchExpandedState(state) })) : null, [memoizedFiltersBar, searchComponent, searchExpandedState]);
174
174
  const mobileFilterButton = useMemo(() => (isMobile && memoizedFiltersBar ? _jsx(MobileFilterControl, { count: numberOfChangedFilters, onClick: filtersBarToggler, ref: mobileFilterControlRef }) : null), [filtersBarToggler, isMobile, memoizedFiltersBar, numberOfChangedFilters]);
@@ -253,6 +253,9 @@ export const Header = ({ children, className, onFiltersBarOpen
253
253
  return;
254
254
  }
255
255
  }, [mobileFilterControlRef, mobileFilterNewLineControlRef, isMobileFilterButtonExists, mobileFilterTrigger, isFilterInNewLine]);
256
+ if (!isClientReady) {
257
+ return null;
258
+ }
256
259
  return (_jsx(HeaderMenuProvider, { alignment: "left-top", children: _jsx(HeaderCustomContent.Provider, { value: { content, setContent }, children: _jsx(FiltersBarContextProvider, { value: { setFiltersBarToggleAllFiltersFn, onUpdateNumberOfChangedFiltersFn: setNumberOfChangedFilters }, children: _jsx(SearchContextProvider, { value: { setSearchComponent: handleSearchChange }, children: _jsx(TriggerContextProvider, { value: { triggerComponent: mobileFilterTrigger }, children: _jsxs("div", { className: fullClassName, ref: headerRef, children: [mainLineContainer, newLineContainer, tabs ? (_jsxs("div", { className: classNames(["zen-main-header__tabs", "zen-main-header--border", isMobile ? "zen-main-header__tabs--mobile" : "", driveClassnameTab || ""]), children: [" ", tabs, " "] })) : null, memoizedFiltersBar ? _jsx("div", { className: "zen-main-header__filtersBar", children: memoizedFiltersBar }) : null, _jsx("div", { className: "zen-main-header__section zen-main-header__section--hidden", ref: hiddenContainerRef, children: hiddenItemForRender }), _jsx("div", { className: "zen-main-header__section zen-main-header__section--hidden", children: _jsx("div", { className: "zen-main-header__section--inline", ref: moreButtonRef, children: moreButton }) })] }) }) }) }) }) }));
257
260
  };
258
261
  export const HeaderDisplayName = "Header";
package/esm/index.d.ts CHANGED
@@ -50,7 +50,6 @@ export { type IEntityWithId } from "./commonHelpers/entity";
50
50
  export { generateId } from "./commonHelpers/generateId";
51
51
  export { DeviceContext, DeviceProvider } from "./commonHelpers/hooks/deviceProvider";
52
52
  export { DeviceType } from "./commonHelpers/hooks/deviceType";
53
- export { useClientReady } from "./commonHelpers/hooks/useClientReady";
54
53
  export { useDebounce } from "./commonHelpers/hooks/useDebounce";
55
54
  export { useDebouncedMemo } from "./commonHelpers/hooks/useDebouncedMemo";
56
55
  export { useDeviceType } from "./commonHelpers/hooks/useDeviceType";
package/esm/index.js CHANGED
@@ -50,7 +50,6 @@ export { hexToRGBA } from "./commonHelpers/colorUtils";
50
50
  export { generateId } from "./commonHelpers/generateId";
51
51
  export { DeviceContext, DeviceProvider } from "./commonHelpers/hooks/deviceProvider";
52
52
  export { DeviceType } from "./commonHelpers/hooks/deviceType";
53
- export { useClientReady } from "./commonHelpers/hooks/useClientReady";
54
53
  export { useDebounce } from "./commonHelpers/hooks/useDebounce";
55
54
  export { useDebouncedMemo } from "./commonHelpers/hooks/useDebouncedMemo";
56
55
  export { useDeviceType } from "./commonHelpers/hooks/useDeviceType";
@@ -22,5 +22,5 @@ interface ILayoutComponents {
22
22
  FullScreenButton: React.FC<IFullScreenButton>;
23
23
  }
24
24
  export declare const getContentPaddings: (isMobile: boolean, startWithToolbar: boolean) => number;
25
- export declare const Layout: (({ id, className, pageScrolling, children }: ILayout) => import("react/jsx-runtime").JSX.Element) & ILayoutComponents;
25
+ export declare const Layout: (({ id, className, pageScrolling, children }: ILayout) => import("react/jsx-runtime").JSX.Element | null) & ILayoutComponents;
26
26
  export {};