@geotab/zenith 3.6.3 → 3.7.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.
Files changed (149) hide show
  1. package/README.md +15 -0
  2. package/dist/absolute/absolute.d.ts +3 -1
  3. package/dist/absolute/absolute.js +4 -4
  4. package/dist/checkbox/checkbox.d.ts +3 -1
  5. package/dist/checkbox/checkbox.js +5 -8
  6. package/dist/checkboxListWithAction/checkboxListWithAction.d.ts +3 -1
  7. package/dist/checkboxListWithAction/checkboxListWithAction.js +185 -3
  8. package/dist/controlledPopup/controlledPopup.d.ts +3 -1
  9. package/dist/controlledPopup/controlledPopup.js +2 -2
  10. package/dist/dropdown/dropdownPopup.d.ts +1 -1
  11. package/dist/dropdown/dropdownTrigger.d.ts +1 -1
  12. package/dist/dropdownRaw/dropdownList.d.ts +2 -1
  13. package/dist/dropdownRaw/dropdownList.js +15 -4
  14. package/dist/dropdownRaw/dropdownPopup.d.ts +3 -1
  15. package/dist/dropdownRaw/dropdownPopup.js +35 -5
  16. package/dist/dropdownRaw/dropdownRaw.js +82 -7
  17. package/dist/dropdownRaw/dropdownSearchableTrigger.d.ts +2 -1
  18. package/dist/dropdownRaw/dropdownSearchableTrigger.js +7 -2
  19. package/dist/dropdownRaw/dropdownTrigger.d.ts +2 -1
  20. package/dist/dropdownRaw/dropdownTrigger.js +3 -5
  21. package/dist/footerButtons/footerButtons.d.ts +6 -4
  22. package/dist/footerButtons/footerButtons.js +3 -8
  23. package/dist/groupsFilterRaw/groupsFilterCurrentlySelectedState.js +8 -2
  24. package/dist/groupsFilterRaw/groupsFilterInitialState.js +16 -0
  25. package/dist/groupsFilterRaw/groupsFilterRaw.js +43 -9
  26. package/dist/groupsFilterRaw/groupsFilterTrigger.d.ts +2 -1
  27. package/dist/groupsFilterRaw/groupsFilterTrigger.js +13 -2
  28. package/dist/index.css +222 -18
  29. package/dist/index.d.ts +1 -1
  30. package/dist/list/hooks/useDragAndDrop.d.ts +3 -1
  31. package/dist/list/hooks/useDragAndDrop.js +11 -4
  32. package/dist/menu/components/menuItem.js +12 -2
  33. package/dist/menu/contexts/pathContext.d.ts +3 -1
  34. package/dist/menu/contexts/pathProvider.d.ts +1 -1
  35. package/dist/menu/contexts/pathProvider.js +1 -1
  36. package/dist/menu/controlledMenu.js +97 -29
  37. package/dist/nav/nav.d.ts +2 -1
  38. package/dist/nav/nav.js +3 -2
  39. package/dist/nav/navEditList/navEditList.js +2 -1
  40. package/dist/nav/navItem/navItem.d.ts +1 -0
  41. package/dist/nav/navItem/navItem.js +4 -1
  42. package/dist/pillExpandable/pillContent.d.ts +2 -1
  43. package/dist/pillExpandable/pillContent.js +8 -3
  44. package/dist/pillExpandable/pillExpandable.d.ts +27 -4
  45. package/dist/pillExpandable/pillExpandable.js +426 -196
  46. package/dist/pillExpandable/pillExpandablePopoverContent.d.ts +19 -0
  47. package/dist/pillExpandable/pillExpandablePopoverContent.js +7 -0
  48. package/dist/pillExpandable/pillExpandableSimple.d.ts +5 -3
  49. package/dist/pillExpandable/pillExpandableSimple.js +12 -5
  50. package/dist/summary/summary.js +29 -1
  51. package/dist/summaryTile/summaryTile.d.ts +2 -1
  52. package/dist/summaryTile/summaryTile.js +175 -65
  53. package/dist/summaryTile/summaryTileTrigger.d.ts +1 -1
  54. package/dist/summaryTile/summaryTileTrigger.js +1 -1
  55. package/dist/toggleButtonRaw/toggleButtonRaw.js +2 -1
  56. package/dist/utils/localization/getSupportedLanguage.d.ts +2 -2
  57. package/dist/utils/localization/getSupportedLanguage.js +28 -8
  58. package/dist/utils/localization/languageContext.d.ts +1 -1
  59. package/dist/utils/localization/translations/cs.json +2 -1
  60. package/dist/utils/localization/translations/de.json +2 -1
  61. package/dist/utils/localization/translations/en.json +2 -1
  62. package/dist/utils/localization/translations/es.json +2 -1
  63. package/dist/utils/localization/translations/fr-FR.json +2 -1
  64. package/dist/utils/localization/translations/fr.json +2 -1
  65. package/dist/utils/localization/translations/id.json +2 -1
  66. package/dist/utils/localization/translations/it.json +2 -1
  67. package/dist/utils/localization/translations/ja.json +2 -1
  68. package/dist/utils/localization/translations/ms.json +2 -1
  69. package/dist/utils/localization/translations/nl.json +2 -1
  70. package/dist/utils/localization/translations/pl.json +2 -1
  71. package/dist/utils/localization/translations/pt-BR.json +2 -1
  72. package/dist/utils/localization/translations/sv.json +2 -1
  73. package/dist/utils/localization/translations/th.json +2 -1
  74. package/dist/utils/localization/translations/tr.json +2 -1
  75. package/dist/utils/localization/translations/zh-Hans.json +2 -1
  76. package/esm/absolute/absolute.d.ts +3 -1
  77. package/esm/absolute/absolute.js +4 -4
  78. package/esm/checkbox/checkbox.d.ts +3 -1
  79. package/esm/checkbox/checkbox.js +5 -8
  80. package/esm/checkboxListWithAction/checkboxListWithAction.d.ts +3 -1
  81. package/esm/checkboxListWithAction/checkboxListWithAction.js +186 -4
  82. package/esm/controlledPopup/controlledPopup.d.ts +3 -1
  83. package/esm/controlledPopup/controlledPopup.js +2 -2
  84. package/esm/dropdown/dropdownPopup.d.ts +1 -1
  85. package/esm/dropdown/dropdownTrigger.d.ts +1 -1
  86. package/esm/dropdownRaw/dropdownList.d.ts +2 -1
  87. package/esm/dropdownRaw/dropdownList.js +16 -5
  88. package/esm/dropdownRaw/dropdownPopup.d.ts +3 -1
  89. package/esm/dropdownRaw/dropdownPopup.js +37 -7
  90. package/esm/dropdownRaw/dropdownRaw.js +82 -7
  91. package/esm/dropdownRaw/dropdownSearchableTrigger.d.ts +2 -1
  92. package/esm/dropdownRaw/dropdownSearchableTrigger.js +7 -2
  93. package/esm/dropdownRaw/dropdownTrigger.d.ts +2 -1
  94. package/esm/dropdownRaw/dropdownTrigger.js +3 -5
  95. package/esm/footerButtons/footerButtons.d.ts +6 -4
  96. package/esm/footerButtons/footerButtons.js +3 -8
  97. package/esm/groupsFilterRaw/groupsFilterCurrentlySelectedState.js +9 -3
  98. package/esm/groupsFilterRaw/groupsFilterInitialState.js +16 -0
  99. package/esm/groupsFilterRaw/groupsFilterRaw.js +43 -9
  100. package/esm/groupsFilterRaw/groupsFilterTrigger.d.ts +2 -1
  101. package/esm/groupsFilterRaw/groupsFilterTrigger.js +13 -2
  102. package/esm/index.d.ts +1 -1
  103. package/esm/list/hooks/useDragAndDrop.d.ts +3 -1
  104. package/esm/list/hooks/useDragAndDrop.js +11 -4
  105. package/esm/menu/components/menuItem.js +12 -2
  106. package/esm/menu/contexts/pathContext.d.ts +3 -1
  107. package/esm/menu/contexts/pathProvider.d.ts +1 -1
  108. package/esm/menu/contexts/pathProvider.js +1 -1
  109. package/esm/menu/controlledMenu.js +98 -30
  110. package/esm/nav/nav.d.ts +2 -1
  111. package/esm/nav/nav.js +3 -2
  112. package/esm/nav/navEditList/navEditList.js +2 -1
  113. package/esm/nav/navItem/navItem.d.ts +1 -0
  114. package/esm/nav/navItem/navItem.js +5 -2
  115. package/esm/pillExpandable/pillContent.d.ts +2 -1
  116. package/esm/pillExpandable/pillContent.js +8 -3
  117. package/esm/pillExpandable/pillExpandable.d.ts +27 -4
  118. package/esm/pillExpandable/pillExpandable.js +427 -197
  119. package/esm/pillExpandable/pillExpandablePopoverContent.d.ts +19 -0
  120. package/esm/pillExpandable/pillExpandablePopoverContent.js +3 -0
  121. package/esm/pillExpandable/pillExpandableSimple.d.ts +5 -3
  122. package/esm/pillExpandable/pillExpandableSimple.js +12 -5
  123. package/esm/summary/summary.js +29 -1
  124. package/esm/summaryTile/summaryTile.d.ts +2 -1
  125. package/esm/summaryTile/summaryTile.js +140 -43
  126. package/esm/summaryTile/summaryTileTrigger.d.ts +1 -1
  127. package/esm/summaryTile/summaryTileTrigger.js +1 -1
  128. package/esm/toggleButtonRaw/toggleButtonRaw.js +2 -1
  129. package/esm/utils/localization/getSupportedLanguage.d.ts +2 -2
  130. package/esm/utils/localization/getSupportedLanguage.js +28 -8
  131. package/esm/utils/localization/languageContext.d.ts +1 -1
  132. package/esm/utils/localization/translations/cs.json +2 -1
  133. package/esm/utils/localization/translations/de.json +2 -1
  134. package/esm/utils/localization/translations/en.json +2 -1
  135. package/esm/utils/localization/translations/es.json +2 -1
  136. package/esm/utils/localization/translations/fr-FR.json +2 -1
  137. package/esm/utils/localization/translations/fr.json +2 -1
  138. package/esm/utils/localization/translations/id.json +2 -1
  139. package/esm/utils/localization/translations/it.json +2 -1
  140. package/esm/utils/localization/translations/ja.json +2 -1
  141. package/esm/utils/localization/translations/ms.json +2 -1
  142. package/esm/utils/localization/translations/nl.json +2 -1
  143. package/esm/utils/localization/translations/pl.json +2 -1
  144. package/esm/utils/localization/translations/pt-BR.json +2 -1
  145. package/esm/utils/localization/translations/sv.json +2 -1
  146. package/esm/utils/localization/translations/th.json +2 -1
  147. package/esm/utils/localization/translations/tr.json +2 -1
  148. package/esm/utils/localization/translations/zh-Hans.json +2 -1
  149. package/package.json +4 -7
@@ -1,43 +1,24 @@
1
1
  import { injectString } from "../utils/localization/translationsDictionary";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { Children, createContext, memo, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
4
4
  import { Absolute } from "../absolute/absolute";
5
+ import { FOCUSABLE_SELECTOR } from "../utils/focusableSelector";
5
6
  import { Button } from "../button/button";
7
+ import { Divider } from "../divider/divider";
6
8
  import { PillContent } from "./pillContent";
7
9
  import { PillExpandableSimple } from "./pillExpandableSimple";
10
+ import { PillExpandablePopoverContent } from "./pillExpandablePopoverContent";
8
11
  import { alignments } from "./pillExpandableAlignments";
9
12
  import { useLanguage } from "../utils/localization/useLanguage";
10
13
  import { classNames } from "../commonHelpers/classNames/classNames";
11
14
  import { getButtonMoreProps } from "./getProps";
15
+ import { IconUnlocked } from "../icons/iconUnlocked";
12
16
  import { Skeleton } from "../skeleton/skeleton";
13
17
  import { isFunction } from "../commonHelpers/reactHelpers/reactHelpers";
14
- import { Divider } from "../divider/divider";
15
- injectString("cs", "Expand", "Rozbalit");
16
- injectString("da-DK", "Expand", "Udvid");
17
- injectString("de", "Expand", "Erweitern");
18
- injectString("en", "Expand", "Expand");
19
- injectString("es", "Expand", "Expandir");
20
- injectString("fi-FI", "Expand", "Laajenna");
21
- injectString("fr", "Expand", "D\xE9velopper");
22
- injectString("fr-FR", "Expand", "D\xE9velopper");
23
- injectString("hu-HU", "Expand", "B\u0151v\xEDtsd ki");
24
- injectString("id", "Expand", "Perluas");
25
- injectString("it", "Expand", "Espandere");
26
- injectString("ja", "Expand", "\u5C55\u958B");
27
- injectString("ko-KR", "Expand", "\uD655\uC7A5");
28
- injectString("ms", "Expand", "Kembangkan");
29
- injectString("nb-NO", "Expand", "Utvide");
30
- injectString("nl", "Expand", "Uitvouwen");
31
- injectString("pl", "Expand", "Rozwi\u0144");
32
- injectString("pt-BR", "Expand", "Expandir");
33
- injectString("pt-PT", "Expand", "Expandir");
34
- injectString("sk-SK", "Expand", "Roz\u0161\xEDr.");
35
- injectString("sv", "Expand", "Expandera");
36
- injectString("th", "Expand", "\u0E02\u0E22\u0E32\u0E22");
37
- injectString("tr", "Expand", "Geni\u015Flet");
38
- injectString("zh-Hans", "Expand", "\u5C55\u5F00");
39
- injectString("zh-TW", "Expand", "\u5C55\u958B");
40
- injectString("ro-RO", "Expand", "Extinde\u021Bi");
18
+ import { MobileSheet } from "../mobileSheet/mobileSheet";
19
+ import { useDrive } from "../utils/theme/useDrive";
20
+ import { DeviceType } from "../commonHelpers/hooks/deviceType";
21
+ import { useDeviceType } from "../commonHelpers/hooks/useDeviceType";
41
22
  injectString("cs", "View all", "Zobrazit v\u0161e");
42
23
  injectString("da-DK", "View all", "Se alle");
43
24
  injectString("de", "View all", "Alle anzeigen");
@@ -64,6 +45,32 @@ injectString("tr", "View all", "T\xFCm\xFCn\xFC g\xF6r\xFCnt\xFCle");
64
45
  injectString("zh-Hans", "View all", "\u67E5\u770B\u5168\u90E8");
65
46
  injectString("zh-TW", "View all", "\u6AA2\u8996\u5168\u90E8");
66
47
  injectString("ro-RO", "View all", "Afi\u0219a\u021Bi tot");
48
+ injectString("cs", "Expand", "Rozbalit");
49
+ injectString("da-DK", "Expand", "Udvid");
50
+ injectString("de", "Expand", "Erweitern");
51
+ injectString("en", "Expand", "Expand");
52
+ injectString("es", "Expand", "Expandir");
53
+ injectString("fi-FI", "Expand", "Laajenna");
54
+ injectString("fr", "Expand", "D\xE9velopper");
55
+ injectString("fr-FR", "Expand", "D\xE9velopper");
56
+ injectString("hu-HU", "Expand", "B\u0151v\xEDtsd ki");
57
+ injectString("id", "Expand", "Perluas");
58
+ injectString("it", "Expand", "Espandere");
59
+ injectString("ja", "Expand", "\u5C55\u958B");
60
+ injectString("ko-KR", "Expand", "\uD655\uC7A5");
61
+ injectString("ms", "Expand", "Kembangkan");
62
+ injectString("nb-NO", "Expand", "Utvide");
63
+ injectString("nl", "Expand", "Uitvouwen");
64
+ injectString("pl", "Expand", "Rozwi\u0144");
65
+ injectString("pt-BR", "Expand", "Expandir");
66
+ injectString("pt-PT", "Expand", "Expandir");
67
+ injectString("sk-SK", "Expand", "Roz\u0161\xEDr.");
68
+ injectString("sv", "Expand", "Expandera");
69
+ injectString("th", "Expand", "\u0E02\u0E22\u0E32\u0E22");
70
+ injectString("tr", "Expand", "Geni\u015Flet");
71
+ injectString("zh-Hans", "Expand", "\u5C55\u5F00");
72
+ injectString("zh-TW", "Expand", "\u5C55\u958B");
73
+ injectString("ro-RO", "Expand", "Extinde\u021Bi");
67
74
  const MAX_PILLS_TO_DISPLAY_IN_POPUP = 2;
68
75
  const PillContext = createContext({
69
76
  level: 0,
@@ -72,13 +79,197 @@ const PillContext = createContext({
72
79
  expandedChildPillIds: new Set(),
73
80
  autoExpand: false
74
81
  });
75
- const paddingX = 26;
76
- const paddingY = 52;
82
+ const PillExpandablePopover = ({
83
+ useMobileSheet,
84
+ isOpen,
85
+ popupId,
86
+ popupClassName,
87
+ text,
88
+ triggerRef,
89
+ onClose,
90
+ onToggle,
91
+ onChange,
92
+ isPopupContentReady,
93
+ setContainerNode,
94
+ popoverSize,
95
+ popoverContentProps,
96
+ showFooter,
97
+ moreCounter,
98
+ buttonMoreProps,
99
+ title
100
+ }) => {
101
+ const {
102
+ translate
103
+ } = useLanguage();
104
+ const popoverRef = useRef(null);
105
+ const handlePopoverRef = useCallback(node => {
106
+ popoverRef.current = node;
107
+ setContainerNode(node);
108
+ }, [setContainerNode]);
109
+ // Focus first focusable element in desktop popover when content is ready.
110
+ // Mobile MobileSheet handles its own first-focus (close button).
111
+ useEffect(() => {
112
+ if (!useMobileSheet && isPopupContentReady && popoverRef.current) {
113
+ const firstFocusable = popoverRef.current.querySelector(FOCUSABLE_SELECTOR);
114
+ firstFocusable === null || firstFocusable === void 0 ? void 0 : firstFocusable.focus();
115
+ }
116
+ }, [useMobileSheet, isPopupContentReady]);
117
+ const titleItem = title && _jsx("div", {
118
+ className: "zen-status-pill-popup__title-item",
119
+ children: _jsx("span", {
120
+ className: "zen-status-pill-popup__title-item-text",
121
+ children: title
122
+ })
123
+ });
124
+ const footer = showFooter && _jsxs("div", {
125
+ className: "zen-status-pill-popup__footer",
126
+ children: [_jsx(Divider, {
127
+ className: "zen-status-pill-popup__divider"
128
+ }), _jsxs(Button, Object.assign({}, buttonMoreProps, {
129
+ type: "tertiary",
130
+ className: "zen-status-pill-popup__view-more-button",
131
+ children: [_jsx("span", {
132
+ children: translate("View all")
133
+ }), _jsx("span", {
134
+ className: "zen-status-pill-popup__view-more-badge",
135
+ children: moreCounter
136
+ })]
137
+ }))]
138
+ });
139
+ if (useMobileSheet) {
140
+ return _jsxs(MobileSheet, {
141
+ className: classNames(["zen-status-pill-popup--mobile", popupClassName || ""]),
142
+ label: text,
143
+ triggerRef: triggerRef,
144
+ isOpen: isOpen,
145
+ onHidePanel: onClose,
146
+ onCloseClick: onClose,
147
+ id: popupId,
148
+ children: [_jsx(MobileSheet.Title, {
149
+ className: "zen-status-pill-popup__mobile-title",
150
+ children: title || text
151
+ }), _jsx(MobileSheet.Content, {
152
+ children: _jsxs("div", {
153
+ className: "zen-status-pill-popup__mobile-content",
154
+ children: [_jsx(PillExpandablePopoverContent, Object.assign({}, popoverContentProps, {
155
+ onActionClick: onClose
156
+ })), footer]
157
+ })
158
+ })]
159
+ });
160
+ }
161
+ return _jsx(Absolute, {
162
+ recalculateTrigger: isPopupContentReady,
163
+ recalculateOnScroll: true,
164
+ useTrapFocusWithTrigger: "on",
165
+ className: popupClassName,
166
+ id: popupId,
167
+ onOpenChange: onChange,
168
+ isOpen: isOpen,
169
+ triggerRef: triggerRef,
170
+ alignmentsFn: alignments,
171
+ children: _jsxs("div", {
172
+ ref: handlePopoverRef,
173
+ className: "zen-status-pill-popup",
174
+ tabIndex: -1,
175
+ children: [titleItem, _jsx("div", {
176
+ className: classNames(["zen-status-pill-popup__container", `zen-status-pill-popup__container--${popoverSize}`]),
177
+ children: _jsx(PillExpandablePopoverContent, Object.assign({}, popoverContentProps, {
178
+ onActionClick: onToggle
179
+ }))
180
+ }), footer]
181
+ })
182
+ });
183
+ };
184
+ const PillExpandableChild = ({
185
+ icon,
186
+ text,
187
+ type,
188
+ errorHandler,
189
+ content,
190
+ autoExpandChildren
191
+ }) => {
192
+ const pillId = useId();
193
+ const descriptionId = useId();
194
+ const {
195
+ translate
196
+ } = useLanguage();
197
+ const {
198
+ level,
199
+ expandedChildPillIds,
200
+ onChildPillExpand,
201
+ onChildPillCollapse,
202
+ autoExpand
203
+ } = useContext(PillContext);
204
+ const [currentExpandedPills, setCurrentExpandedPills] = useState(new Set());
205
+ const isExpanded = expandedChildPillIds.has(pillId);
206
+ useEffect(() => {
207
+ if (autoExpand) {
208
+ onChildPillExpand(pillId);
209
+ }
210
+ }, [autoExpand, onChildPillExpand, pillId]);
211
+ const handleChildToggle = useCallback(e => {
212
+ e === null || e === void 0 ? void 0 : e.stopPropagation();
213
+ if (isExpanded) {
214
+ onChildPillCollapse(pillId);
215
+ } else {
216
+ if (!autoExpand) {
217
+ expandedChildPillIds.forEach(pill => onChildPillCollapse(pill));
218
+ }
219
+ onChildPillExpand(pillId);
220
+ }
221
+ }, [isExpanded, expandedChildPillIds, pillId, autoExpand, onChildPillCollapse, onChildPillExpand]);
222
+ const addExpandedChild = useCallback(id => {
223
+ setCurrentExpandedPills(prev => {
224
+ const next = new Set(prev);
225
+ next.add(id);
226
+ return next;
227
+ });
228
+ }, []);
229
+ const removeExpandedChild = useCallback(id => {
230
+ setCurrentExpandedPills(prev => {
231
+ const next = new Set(prev);
232
+ next.delete(id);
233
+ return next;
234
+ });
235
+ }, []);
236
+ return _jsxs(PillContext.Provider, {
237
+ value: {
238
+ level: level + 1,
239
+ onChildPillExpand: addExpandedChild,
240
+ onChildPillCollapse: removeExpandedChild,
241
+ expandedChildPillIds: currentExpandedPills,
242
+ autoExpand: autoExpandChildren || false
243
+ },
244
+ children: [_jsx(PillExpandableSimple, {
245
+ icon: icon,
246
+ text: text,
247
+ expanded: isExpanded,
248
+ onExpand: handleChildToggle,
249
+ expandAriaText: translate("Expand"),
250
+ type: type,
251
+ errorHandler: errorHandler,
252
+ descriptionId: descriptionId
253
+ }), _jsx(PillContent, {
254
+ onActionClick: handleChildToggle,
255
+ descriptionText: content.description,
256
+ date: content.date,
257
+ count: content.count,
258
+ mainAction: content.mainAction,
259
+ secondaryAction: content.secondaryAction,
260
+ tertiaryAction: content.tertiaryAction,
261
+ isVisible: isExpanded,
262
+ errorHandler: errorHandler,
263
+ descriptionId: descriptionId
264
+ })]
265
+ });
266
+ };
77
267
  const getDefaultContent = ({
78
268
  description,
79
269
  date,
80
270
  count,
81
271
  secondaryAction,
272
+ tertiaryAction,
82
273
  mainAction,
83
274
  getData
84
275
  }) => {
@@ -102,6 +293,12 @@ const getDefaultContent = ({
102
293
  text: ""
103
294
  }
104
295
  },
296
+ tertiaryAction: {
297
+ isLoading: true,
298
+ data: {
299
+ text: ""
300
+ }
301
+ },
105
302
  mainAction: {
106
303
  isLoading: true,
107
304
  data: {
@@ -116,6 +313,7 @@ const getDefaultContent = ({
116
313
  date,
117
314
  count,
118
315
  secondaryAction,
316
+ tertiaryAction,
119
317
  mainAction,
120
318
  getData: undefined
121
319
  };
@@ -131,47 +329,56 @@ const getValue = (parameter, setContent, paramName, errorHandler) => {
131
329
  });
132
330
  }
133
331
  };
134
- const PillExpandableBase = ({
135
- children,
136
- errorHandler,
137
- getData,
138
- text,
332
+ const usePillContentState = ({
139
333
  description,
140
334
  date,
141
335
  count,
142
336
  mainAction,
143
337
  secondaryAction,
144
- viewMoreAction,
145
- uniquePills,
146
- type,
147
- className,
148
- popupClassName,
149
- isLoading,
150
- isFlat,
151
- icon,
152
- secondaryIcon,
153
- isBeta,
154
- loadingWidth = 200,
155
- hideCounterNumber,
156
- autoExpandChildren
338
+ tertiaryAction,
339
+ getData,
340
+ isPopupOpen,
341
+ errorHandler
157
342
  }) => {
158
- const popupId = useId();
159
- const pillId = useId();
160
- const descriptionId = useId();
161
- const {
162
- translate
163
- } = useLanguage();
164
343
  const [content, setContent] = useState(getDefaultContent({
165
344
  description,
166
345
  date,
167
346
  count,
168
347
  secondaryAction,
348
+ tertiaryAction,
169
349
  mainAction,
170
350
  getData
171
351
  }));
172
- const [isPopupOpen, setIsPopupOpen] = useState(false);
352
+ useEffect(() => {
353
+ if (!isPopupOpen || !isFunction(getData)) {
354
+ return;
355
+ }
356
+ void getData().then(result => {
357
+ setContent(result);
358
+ }).catch(e => {
359
+ if (errorHandler) {
360
+ void errorHandler(e);
361
+ }
362
+ });
363
+ }, [getData, isPopupOpen, errorHandler]);
364
+ useEffect(() => {
365
+ if (!isPopupOpen) {
366
+ return;
367
+ }
368
+ getValue(description, setContent, "description", errorHandler);
369
+ getValue(date, setContent, "date", errorHandler);
370
+ getValue(count, setContent, "count", errorHandler);
371
+ getValue(secondaryAction, setContent, "secondaryAction", errorHandler);
372
+ getValue(tertiaryAction, setContent, "tertiaryAction", errorHandler);
373
+ getValue(mainAction, setContent, "mainAction", errorHandler);
374
+ }, [content, isPopupOpen, description, date, count, secondaryAction, tertiaryAction, mainAction, errorHandler]);
375
+ return content;
376
+ };
377
+ const usePopupContentReady = ({
378
+ isPopupOpen,
379
+ containerNode
380
+ }) => {
173
381
  const [isPopupContentReady, setIsPopupContentReady] = useState(false);
174
- const [containerNode, setContainerNode] = useState(null);
175
382
  useEffect(() => {
176
383
  if (!isPopupOpen) {
177
384
  setIsPopupContentReady(false);
@@ -191,67 +398,76 @@ const PillExpandableBase = ({
191
398
  observer.unobserve(containerNode);
192
399
  };
193
400
  }, [isPopupOpen, containerNode]);
194
- useEffect(() => {
195
- const fetchData = function () {
196
- if (!isPopupOpen) {
197
- return;
198
- }
199
- if (isFunction(getData)) {
200
- void getData().then(result => {
201
- setContent(result);
202
- }).catch(e => {
203
- if (errorHandler) {
204
- void errorHandler(e);
205
- }
206
- });
207
- }
208
- };
209
- fetchData();
210
- }, [getData, isPopupOpen, errorHandler]);
211
- useEffect(() => {
212
- if (!isPopupOpen) {
213
- return;
214
- }
215
- getValue(description, setContent, "description", errorHandler);
216
- getValue(date, setContent, "date", errorHandler);
217
- getValue(count, setContent, "count", errorHandler);
218
- getValue(secondaryAction, setContent, "secondaryAction", errorHandler);
219
- getValue(mainAction, setContent, "mainAction", errorHandler);
220
- }, [content, isPopupOpen, description, date, count, secondaryAction, mainAction, errorHandler]);
401
+ return isPopupContentReady;
402
+ };
403
+ const PillExpandableBase = ({
404
+ children,
405
+ errorHandler,
406
+ getData,
407
+ text,
408
+ description,
409
+ date,
410
+ count,
411
+ mainAction,
412
+ secondaryAction,
413
+ tertiaryAction,
414
+ viewMoreAction,
415
+ uniquePills,
416
+ type,
417
+ className,
418
+ popupClassName,
419
+ isLoading,
420
+ isFlat,
421
+ icon,
422
+ secondaryIcon,
423
+ isBeta,
424
+ loadingWidth = 200,
425
+ hideCounterNumber,
426
+ autoExpandChildren,
427
+ popoverSize = "medium",
428
+ title
429
+ }) => {
430
+ const popupId = useId();
431
+ const descriptionId = useId();
221
432
  const {
222
- level,
223
- expandedChildPillIds,
224
- onChildPillExpand,
225
- onChildPillCollapse,
226
- autoExpand
433
+ translate
434
+ } = useLanguage();
435
+ const isDrive = useDrive();
436
+ const [isMobile, setIsMobile] = useState(false);
437
+ const handleDeviceTypeChange = useCallback(deviceType => {
438
+ setIsMobile(deviceType === DeviceType.Mobile);
439
+ }, []);
440
+ useDeviceType(handleDeviceTypeChange);
441
+ const useMobileSheet = isMobile || isDrive;
442
+ const [isPopupOpen, setIsPopupOpen] = useState(false);
443
+ const [containerNode, setContainerNode] = useState(null);
444
+ const content = usePillContentState({
445
+ description,
446
+ date,
447
+ count,
448
+ mainAction,
449
+ secondaryAction,
450
+ tertiaryAction,
451
+ getData,
452
+ isPopupOpen,
453
+ errorHandler
454
+ });
455
+ const isPopupContentReady = usePopupContentReady({
456
+ isPopupOpen,
457
+ containerNode
458
+ });
459
+ const {
460
+ level
227
461
  } = useContext(PillContext);
228
462
  const triggerRef = useRef(null);
229
463
  const isChild = level !== 0;
230
464
  const [currentExpandedPills, setCurrentExpandedPills] = useState(new Set());
231
- useEffect(() => {
232
- if (isChild && autoExpand) {
233
- onChildPillExpand(pillId);
234
- }
235
- }, [autoExpand, isChild, onChildPillExpand, pillId]);
236
465
  const handlePopupToggle = useCallback(e => {
237
466
  var _a;
238
467
  e === null || e === void 0 ? void 0 : e.stopPropagation();
239
468
  setIsPopupOpen(!isPopupOpen);
240
469
  isPopupOpen && ((_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.focus());
241
470
  }, [isPopupOpen]);
242
- const handleChildToggle = useCallback(e => {
243
- e === null || e === void 0 ? void 0 : e.stopPropagation();
244
- const isExpanded = expandedChildPillIds.has(pillId);
245
- if (isExpanded) {
246
- onChildPillCollapse(pillId);
247
- } else {
248
- if (!autoExpand) {
249
- // Prevent multiple child pills being expanded at the same time
250
- expandedChildPillIds.forEach(pill => onChildPillCollapse(pill));
251
- }
252
- onChildPillExpand(pillId);
253
- }
254
- }, [expandedChildPillIds, pillId, autoExpand, onChildPillCollapse, onChildPillExpand]);
255
471
  const addExpandedChild = useCallback(id => {
256
472
  setCurrentExpandedPills(prev => {
257
473
  const next = new Set(prev);
@@ -269,16 +485,80 @@ const PillExpandableBase = ({
269
485
  const onChange = useCallback(() => {
270
486
  setIsPopupOpen(!isPopupOpen);
271
487
  }, [isPopupOpen]);
272
- const buttonMoreProps = useMemo(() => getButtonMoreProps(viewMoreAction), [viewMoreAction]);
273
- const validChildren = useMemo(() => Children.toArray(children).filter(child => {
488
+ const handlePopupClose = useCallback(() => {
274
489
  var _a;
275
- return ((_a = child === null || child === void 0 ? void 0 : child.type) === null || _a === void 0 ? void 0 : _a.displayName) === "PillExpandable";
276
- }), [children]);
490
+ setIsPopupOpen(false);
491
+ (_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.focus();
492
+ }, []);
493
+ const buttonMoreProps = useMemo(() => getButtonMoreProps(viewMoreAction), [viewMoreAction]);
494
+ // For upsell type, force IconUnlocked icon
495
+ const effectiveIcon = type === "upsell" ? IconUnlocked : icon;
496
+ // Analyze children to determine variant and extract config
497
+ const childrenAnalysis = useMemo(() => {
498
+ const childArray = Children.toArray(children);
499
+ const pillChildren = childArray.filter(child => {
500
+ var _a;
501
+ const displayName = (_a = child === null || child === void 0 ? void 0 : child.type) === null || _a === void 0 ? void 0 : _a.displayName;
502
+ return displayName === "PillExpandable";
503
+ });
504
+ // Custom content = children that are not PillExpandable or PillExpandable.List
505
+ const customChildren = childArray.filter(child => {
506
+ var _a;
507
+ const displayName = (_a = child === null || child === void 0 ? void 0 : child.type) === null || _a === void 0 ? void 0 : _a.displayName;
508
+ return displayName !== "PillExpandable" && displayName !== "PillExpandable.List";
509
+ });
510
+ return {
511
+ hasPillChildren: pillChildren.length > 0,
512
+ hasCustomChildren: customChildren.length > 0,
513
+ customChildren
514
+ };
515
+ }, [children]);
516
+ // Auto-detect variant based on children
517
+ // Priority: placeholder (custom children) > default
518
+ const effectiveVariant = childrenAnalysis.hasCustomChildren ? "placeholder" : "default";
519
+ // For upsell type, silently ignore nested children
520
+ const validChildren = useMemo(() => {
521
+ if (type === "upsell") {
522
+ return [];
523
+ }
524
+ return Children.toArray(children).filter(child => {
525
+ var _a;
526
+ const displayName = (_a = child === null || child === void 0 ? void 0 : child.type) === null || _a === void 0 ? void 0 : _a.displayName;
527
+ // Filter out PillExpandable.List config component and keep only PillExpandable children
528
+ return displayName === "PillExpandable";
529
+ });
530
+ }, [children, type]);
277
531
  const childToDisplay = useMemo(() => validChildren.slice(0, MAX_PILLS_TO_DISPLAY_IN_POPUP), [validChildren]);
278
- const childCount = useMemo(() => validChildren.length, [validChildren]);
279
- const flatVsChildCounter = isFlat ? `${childCount + 1}` : `${childCount}`;
280
- const moreCounter = uniquePills ? `${uniquePills}` : flatVsChildCounter;
281
- const uniqueChildren = uniquePills ? `${uniquePills}` : `${childCount || ""}`;
532
+ const childCount = validChildren.length;
533
+ const {
534
+ moreCounter,
535
+ uniqueChildren,
536
+ counterText
537
+ } = useMemo(() => {
538
+ const flatVsChildCounter = isFlat ? `${childCount + 1}` : `${childCount}`;
539
+ const more = uniquePills ? `${uniquePills}` : flatVsChildCounter;
540
+ const unique = uniquePills ? `${uniquePills}` : childCount ? `${childCount}` : "";
541
+ const counter = unique ? isFlat ? `+${unique}` : unique : "";
542
+ return {
543
+ moreCounter: more,
544
+ uniqueChildren: unique,
545
+ counterText: counter
546
+ };
547
+ }, [isFlat, uniquePills, childCount]);
548
+ const popoverContentProps = useMemo(() => ({
549
+ variant: effectiveVariant,
550
+ customContent: childrenAnalysis.hasCustomChildren ? childrenAnalysis.customChildren : undefined,
551
+ descriptionText: content.description,
552
+ date: content.date,
553
+ count: content.count,
554
+ mainAction: content.mainAction,
555
+ secondaryAction: content.secondaryAction,
556
+ tertiaryAction: content.tertiaryAction,
557
+ errorHandler: errorHandler,
558
+ descriptionId,
559
+ childToDisplay
560
+ }), [effectiveVariant, childrenAnalysis, content, errorHandler, descriptionId, childToDisplay]);
561
+ const showFooter = Boolean(moreCounter && viewMoreAction && childCount > MAX_PILLS_TO_DISPLAY_IN_POPUP);
282
562
  if (isLoading) {
283
563
  return _jsx(Skeleton, {
284
564
  type: "pill",
@@ -286,35 +566,13 @@ const PillExpandableBase = ({
286
566
  });
287
567
  }
288
568
  if (isChild) {
289
- const isExpanded = expandedChildPillIds.has(pillId);
290
- return _jsxs(PillContext.Provider, {
291
- value: {
292
- level: level + 1,
293
- onChildPillExpand: addExpandedChild,
294
- onChildPillCollapse: removeExpandedChild,
295
- expandedChildPillIds: currentExpandedPills,
296
- autoExpand: autoExpandChildren || false
297
- },
298
- children: [_jsx(PillExpandableSimple, {
299
- icon: icon,
300
- text: text,
301
- expanded: isExpanded,
302
- onExpand: handleChildToggle,
303
- expandAriaText: translate("Expand"),
304
- type: type,
305
- errorHandler: errorHandler,
306
- descriptionId: descriptionId
307
- }), _jsx(PillContent, {
308
- onActionClick: handleChildToggle,
309
- descriptionText: content.description,
310
- date: content.date,
311
- count: content.count,
312
- mainAction: content.mainAction,
313
- secondaryAction: content.secondaryAction,
314
- isVisible: isExpanded,
315
- errorHandler: errorHandler,
316
- descriptionId: descriptionId
317
- })]
569
+ return _jsx(PillExpandableChild, {
570
+ icon: icon,
571
+ text: text,
572
+ type: type,
573
+ errorHandler: errorHandler,
574
+ content: content,
575
+ autoExpandChildren: autoExpandChildren
318
576
  });
319
577
  }
320
578
  return _jsx(PillContext.Provider, {
@@ -332,75 +590,47 @@ const PillExpandableBase = ({
332
590
  className: "zen-status-pill__pill-container",
333
591
  onClick: handlePopupToggle,
334
592
  children: [_jsx(PillExpandableSimple, {
335
- icon: icon,
593
+ icon: effectiveIcon,
336
594
  text: text,
337
595
  expanded: isPopupOpen,
338
596
  expandAriaText: translate("Expand"),
339
597
  ref: triggerRef,
340
598
  type: type,
341
599
  errorHandler: errorHandler,
342
- isBeta: isBeta
600
+ isBeta: isBeta,
601
+ isMobile: isMobile
343
602
  }), uniqueChildren && _jsx(PillExpandableSimple, {
344
- icon: secondaryIcon || icon,
345
- text: hideCounterNumber ? "" : `${isFlat ? "+" : ""}${uniqueChildren}`,
603
+ icon: secondaryIcon || effectiveIcon,
604
+ text: hideCounterNumber ? "" : counterText,
346
605
  includeExpandIcon: false,
347
606
  type: type,
348
607
  errorHandler: errorHandler,
349
- className: "zen-status-pill__counter"
608
+ className: "zen-status-pill__counter",
609
+ isMobile: isMobile
350
610
  })]
351
- }), _jsx(Absolute, {
352
- recalculateTrigger: isPopupContentReady,
353
- recalculateOnScroll: true,
354
- useTrapFocusWithTrigger: "on",
355
- className: popupClassName,
356
- id: popupId,
357
- onOpenChange: onChange,
358
- paddingX: paddingX,
359
- paddingY: paddingY,
611
+ }), _jsx(PillExpandablePopover, {
612
+ useMobileSheet: useMobileSheet,
360
613
  isOpen: isPopupOpen,
614
+ popupId: popupId,
615
+ popupClassName: popupClassName,
616
+ text: text,
361
617
  triggerRef: triggerRef,
362
- alignmentsFn: alignments,
363
- children: _jsx("div", {
364
- ref: node => setContainerNode(node),
365
- className: "zen-status-pill-popup",
366
- children: _jsxs("div", {
367
- className: "zen-status-pill-popup__container",
368
- children: [_jsx("div", {
369
- className: "zen-status-pill-popup__main-pill",
370
- children: _jsx(PillExpandableSimple, {
371
- icon: icon,
372
- text: text,
373
- expanded: true,
374
- onExpand: handlePopupToggle,
375
- expandAriaText: translate("Expand"),
376
- type: type,
377
- errorHandler: errorHandler,
378
- isBeta: isBeta,
379
- descriptionId: descriptionId
380
- })
381
- }), _jsx(PillContent, {
382
- onActionClick: handlePopupToggle,
383
- descriptionText: content.description,
384
- date: content.date,
385
- count: content.count,
386
- mainAction: content.mainAction,
387
- secondaryAction: content.secondaryAction,
388
- errorHandler: errorHandler,
389
- descriptionId: descriptionId
390
- }), childToDisplay, moreCounter && viewMoreAction && childCount > MAX_PILLS_TO_DISPLAY_IN_POPUP && _jsxs(_Fragment, {
391
- children: [_jsx(Divider, {
392
- className: "zen-status-pill-popup__divider"
393
- }), _jsxs(Button, Object.assign({}, buttonMoreProps, {
394
- type: "tertiary",
395
- children: [translate("View all"), " (", moreCounter, ")"]
396
- }))]
397
- })]
398
- })
399
- })
618
+ onClose: handlePopupClose,
619
+ onToggle: handlePopupToggle,
620
+ onChange: onChange,
621
+ isPopupContentReady: isPopupContentReady,
622
+ setContainerNode: setContainerNode,
623
+ popoverSize: popoverSize,
624
+ popoverContentProps: popoverContentProps,
625
+ showFooter: showFooter,
626
+ moreCounter: moreCounter,
627
+ buttonMoreProps: buttonMoreProps,
628
+ title: title
400
629
  })]
401
630
  })
402
631
  });
403
632
  };
404
- export const PillExpandable = memo(PillExpandableBase);
405
- PillExpandable.displayName = "PillExpandable";
633
+ const PillExpandableMemo = memo(PillExpandableBase);
634
+ PillExpandableMemo.displayName = "PillExpandable";
635
+ export const PillExpandable = PillExpandableMemo;
406
636
  export const TRANSLATIONS = ["Expand", "View all"];