@heymantle/litho 0.0.12 → 0.0.14

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 (33) hide show
  1. package/dist/cjs/components/DropZone.js +4 -0
  2. package/dist/cjs/components/Navigation.js +4 -3
  3. package/dist/cjs/components/Popover.js +33 -5
  4. package/dist/cjs/components/Select.js +4 -0
  5. package/dist/cjs/components/TabNavigation.js +65 -11
  6. package/dist/cjs/components/TextField.js +4 -2
  7. package/dist/cjs/components/ToastNotification.js +368 -0
  8. package/dist/cjs/components/ToastProvider.js +342 -0
  9. package/dist/cjs/index.js +11 -0
  10. package/dist/esm/components/DropZone.js +5 -1
  11. package/dist/esm/components/Navigation.js +4 -3
  12. package/dist/esm/components/Popover.js +33 -5
  13. package/dist/esm/components/Select.js +5 -1
  14. package/dist/esm/components/TabNavigation.js +65 -11
  15. package/dist/esm/components/TextField.js +4 -2
  16. package/dist/esm/components/ToastNotification.js +353 -0
  17. package/dist/esm/components/ToastProvider.js +336 -0
  18. package/dist/esm/index.js +2 -0
  19. package/dist/types/components/DropZone.d.ts.map +1 -1
  20. package/dist/types/components/Navigation.d.ts +1 -0
  21. package/dist/types/components/Navigation.d.ts.map +1 -1
  22. package/dist/types/components/Popover.d.ts.map +1 -1
  23. package/dist/types/components/Select.d.ts.map +1 -1
  24. package/dist/types/components/TabNavigation.d.ts.map +1 -1
  25. package/dist/types/components/TextField.d.ts +2 -0
  26. package/dist/types/components/TextField.d.ts.map +1 -1
  27. package/dist/types/components/ToastNotification.d.ts +36 -0
  28. package/dist/types/components/ToastNotification.d.ts.map +1 -0
  29. package/dist/types/components/ToastProvider.d.ts +21 -0
  30. package/dist/types/components/ToastProvider.d.ts.map +1 -0
  31. package/dist/types/index.d.ts +2 -0
  32. package/index.css +3 -0
  33. package/package.json +2 -2
@@ -0,0 +1,342 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ function _export(target, all) {
7
+ for(var name in all)Object.defineProperty(target, name, {
8
+ enumerable: true,
9
+ get: Object.getOwnPropertyDescriptor(all, name).get
10
+ });
11
+ }
12
+ _export(exports, {
13
+ get default () {
14
+ return _default;
15
+ },
16
+ get useToast () {
17
+ return useToast;
18
+ }
19
+ });
20
+ var _jsxruntime = require("react/jsx-runtime");
21
+ var _react = require("react");
22
+ var _reactdom = require("react-dom");
23
+ var _ToastNotification = /*#__PURE__*/ _interop_require_default(require("./ToastNotification"));
24
+ var _Frame = require("./Frame");
25
+ var _Stack = /*#__PURE__*/ _interop_require_default(require("./Stack"));
26
+ function _array_like_to_array(arr, len) {
27
+ if (len == null || len > arr.length) len = arr.length;
28
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
29
+ return arr2;
30
+ }
31
+ function _array_with_holes(arr) {
32
+ if (Array.isArray(arr)) return arr;
33
+ }
34
+ function _array_without_holes(arr) {
35
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
36
+ }
37
+ function _interop_require_default(obj) {
38
+ return obj && obj.__esModule ? obj : {
39
+ default: obj
40
+ };
41
+ }
42
+ function _iterable_to_array(iter) {
43
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
44
+ }
45
+ function _iterable_to_array_limit(arr, i) {
46
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
47
+ if (_i == null) return;
48
+ var _arr = [];
49
+ var _n = true;
50
+ var _d = false;
51
+ var _s, _e;
52
+ try {
53
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
54
+ _arr.push(_s.value);
55
+ if (i && _arr.length === i) break;
56
+ }
57
+ } catch (err) {
58
+ _d = true;
59
+ _e = err;
60
+ } finally{
61
+ try {
62
+ if (!_n && _i["return"] != null) _i["return"]();
63
+ } finally{
64
+ if (_d) throw _e;
65
+ }
66
+ }
67
+ return _arr;
68
+ }
69
+ function _non_iterable_rest() {
70
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
71
+ }
72
+ function _non_iterable_spread() {
73
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
74
+ }
75
+ function _sliced_to_array(arr, i) {
76
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
77
+ }
78
+ function _to_consumable_array(arr) {
79
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
80
+ }
81
+ function _unsupported_iterable_to_array(o, minLen) {
82
+ if (!o) return;
83
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
84
+ var n = Object.prototype.toString.call(o).slice(8, -1);
85
+ if (n === "Object" && o.constructor) n = o.constructor.name;
86
+ if (n === "Map" || n === "Set") return Array.from(n);
87
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
88
+ }
89
+ var ToastContext = /*#__PURE__*/ (0, _react.createContext)(null);
90
+ var useToast = function() {
91
+ var context = (0, _react.useContext)(ToastContext);
92
+ if (!context) {
93
+ // Return a no-op function if used outside provider
94
+ return {
95
+ show: function() {
96
+ console.warn("useToast must be used within a ToastProvider");
97
+ },
98
+ dismiss: function() {},
99
+ dismissAll: function() {}
100
+ };
101
+ }
102
+ return context;
103
+ };
104
+ /**
105
+ * ToastProvider component that manages multiple toast notifications.
106
+ * Handles stacking and positioning of multiple toasts.
107
+ *
108
+ * @component
109
+ * @param {Object} props - The component props.
110
+ * @param {React.ReactNode} props.children - Child components that can use the toast system.
111
+ * @param {'topRight' | 'topLeft' | 'topCenter' | 'bottomRight' | 'bottomLeft' | 'bottomCenter'} [props.defaultPosition='topRight'] - Default position for toasts.
112
+ * @param {number} [props.maxToasts=5] - Maximum number of toasts to display at once.
113
+ * @param {number} [props.stackGap=2] - Gap in pixels between stacked toasts.
114
+ * @returns {JSX.Element} The provider component.
115
+ */ function ToastProvider(param) {
116
+ var children = param.children, _param_defaultPosition = param.defaultPosition, defaultPosition = _param_defaultPosition === void 0 ? "topRight" : _param_defaultPosition, _param_maxToasts = param.maxToasts, maxToasts = _param_maxToasts === void 0 ? 5 : _param_maxToasts, _param_stackGap = param.stackGap, stackGap = _param_stackGap === void 0 ? 2 : _param_stackGap;
117
+ var _useState = _sliced_to_array((0, _react.useState)([]), 2), toasts = _useState[0], setToasts = _useState[1];
118
+ var _useState1 = _sliced_to_array((0, _react.useState)([]), 2), dismissingToasts = _useState1[0], setDismissingToasts = _useState1[1];
119
+ var _useState2 = _sliced_to_array((0, _react.useState)(null), 2), container = _useState2[0], setContainer = _useState2[1];
120
+ var paneIsOpen = (0, _Frame.useFrame)().paneIsOpen;
121
+ // Create portal container on mount
122
+ (0, _react.useEffect)(function() {
123
+ if (typeof window !== "undefined") {
124
+ var div = document.createElement("div");
125
+ div.className = "Litho-ToastProvider";
126
+ div.setAttribute("data-toast-container", "true");
127
+ document.body.appendChild(div);
128
+ setContainer(div);
129
+ return function() {
130
+ if (document.body.contains(div)) {
131
+ document.body.removeChild(div);
132
+ }
133
+ };
134
+ }
135
+ }, []);
136
+ var show = (0, _react.useCallback)(function() {
137
+ var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
138
+ var prefix = options.prefix, icon = options.icon, title = options.title, subtitle = options.subtitle, _options_duration = options.duration, duration = _options_duration === void 0 ? 2000 : _options_duration, _options_position = options.position, position = _options_position === void 0 ? defaultPosition : _options_position, _options_dismissible = options.dismissible, dismissible = _options_dismissible === void 0 ? true : _options_dismissible, onDismiss = options.onDismiss, onClick = options.onClick, id = options.id;
139
+ if (!title) {
140
+ console.warn("Toast requires a title");
141
+ return null;
142
+ }
143
+ var toastId = id || "toast-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
144
+ setToasts(function(prev) {
145
+ // Limit number of toasts
146
+ var newToasts = _to_consumable_array(prev).concat([
147
+ {
148
+ id: toastId,
149
+ prefix: prefix,
150
+ icon: icon,
151
+ title: title,
152
+ subtitle: subtitle,
153
+ duration: duration,
154
+ position: position,
155
+ dismissible: dismissible,
156
+ onDismiss: onDismiss,
157
+ onClick: onClick
158
+ }
159
+ ]);
160
+ return newToasts.slice(-maxToasts);
161
+ });
162
+ return toastId;
163
+ }, [
164
+ defaultPosition,
165
+ maxToasts
166
+ ]);
167
+ var dismiss = (0, _react.useCallback)(function(id) {
168
+ // Move toast to dismissing state for exit animation, remove from active toasts immediately
169
+ (0, _reactdom.flushSync)(function() {
170
+ setToasts(function(prev) {
171
+ var toast = prev.find(function(t) {
172
+ return t.id === id;
173
+ });
174
+ if (toast) {
175
+ // Add to dismissing toasts for exit animation
176
+ setDismissingToasts(function(prevDismissing) {
177
+ // Avoid duplicates
178
+ if (prevDismissing.find(function(t) {
179
+ return t.id === id;
180
+ })) {
181
+ return prevDismissing;
182
+ }
183
+ return _to_consumable_array(prevDismissing).concat([
184
+ toast
185
+ ]);
186
+ });
187
+ // Remove from active toasts immediately so others slide up
188
+ return prev.filter(function(t) {
189
+ return t.id !== id;
190
+ });
191
+ }
192
+ return prev;
193
+ });
194
+ });
195
+ // Clean up dismissing toast after animation completes
196
+ setTimeout(function() {
197
+ setDismissingToasts(function(prev) {
198
+ return prev.filter(function(t) {
199
+ return t.id !== id;
200
+ });
201
+ });
202
+ }, 300); // Match transition duration
203
+ }, []);
204
+ var dismissAll = (0, _react.useCallback)(function() {
205
+ setToasts([]);
206
+ }, []);
207
+ var handleToastDismiss = (0, _react.useCallback)(function(id, onDismiss) {
208
+ // Remove from state immediately so other toasts can slide up
209
+ dismiss(id);
210
+ // Call onDismiss callback after a brief delay to allow exit animation to start
211
+ if (onDismiss) {
212
+ setTimeout(function() {
213
+ onDismiss();
214
+ }, 0);
215
+ }
216
+ }, [
217
+ dismiss
218
+ ]);
219
+ // Group toasts by position
220
+ var toastsByPosition = toasts.reduce(function(acc, toast) {
221
+ var position = toast.position || defaultPosition;
222
+ if (!acc[position]) {
223
+ acc[position] = [];
224
+ }
225
+ acc[position].push(toast);
226
+ return acc;
227
+ }, {});
228
+ if (!container) {
229
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_jsxruntime.Fragment, {
230
+ children: children
231
+ });
232
+ }
233
+ return /*#__PURE__*/ (0, _jsxruntime.jsxs)(ToastContext.Provider, {
234
+ value: {
235
+ show: show,
236
+ dismiss: dismiss,
237
+ dismissAll: dismissAll
238
+ },
239
+ children: [
240
+ children,
241
+ /*#__PURE__*/ (0, _reactdom.createPortal)(/*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
242
+ children: [
243
+ dismissingToasts.map(function(toast) {
244
+ var position = toast.position || defaultPosition;
245
+ var isTop = position.startsWith("top");
246
+ var isBottom = position.startsWith("bottom");
247
+ var dismissingStyle = {
248
+ position: "fixed",
249
+ zIndex: 9998
250
+ };
251
+ if (isTop) {
252
+ dismissingStyle.top = "calc(12px + var(--litho-header-height))";
253
+ } else if (isBottom) {
254
+ dismissingStyle.bottom = "12px";
255
+ }
256
+ if (position.includes("Right")) {
257
+ if (paneIsOpen) {
258
+ dismissingStyle.right = "calc(12px + var(--litho-pane-width))";
259
+ } else {
260
+ dismissingStyle.right = "12px";
261
+ }
262
+ } else if (position.includes("Left")) {
263
+ dismissingStyle.left = "12px";
264
+ } else if (position.includes("Center")) {
265
+ dismissingStyle.left = "50%";
266
+ dismissingStyle.transform = "translateX(-50%)";
267
+ }
268
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)("div", {
269
+ style: dismissingStyle,
270
+ className: "Litho-ToastProvider__DismissingToast",
271
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ToastNotification.default, {
272
+ prefix: toast.prefix,
273
+ icon: toast.icon,
274
+ title: toast.title,
275
+ subtitle: toast.subtitle,
276
+ duration: 0,
277
+ position: toast.position || defaultPosition,
278
+ dismissible: false,
279
+ fixed: false,
280
+ isDismissing: true,
281
+ onClick: toast.onClick,
282
+ onDismiss: function() {}
283
+ })
284
+ }, "dismissing-".concat(toast.id));
285
+ }),
286
+ Object.entries(toastsByPosition).map(function(param) {
287
+ var _param = _sliced_to_array(param, 2), position = _param[0], positionToasts = _param[1];
288
+ var isTop = position.startsWith("top");
289
+ var isBottom = position.startsWith("bottom");
290
+ var isCenter = position.includes("Center");
291
+ var containerStyle = {
292
+ position: "fixed",
293
+ zIndex: 9999
294
+ };
295
+ if (isTop) {
296
+ containerStyle.top = "calc(12px + var(--litho-header-height))"; // top-4
297
+ } else if (isBottom) {
298
+ containerStyle.bottom = "12px"; // bottom-4
299
+ }
300
+ if (position.includes("Right")) {
301
+ // Adjust right position when pane is open to avoid covering the pane
302
+ if (paneIsOpen) {
303
+ containerStyle.right = "calc(12px + var(--litho-pane-width))";
304
+ } else {
305
+ containerStyle.right = "12px";
306
+ }
307
+ } else if (position.includes("Left")) {
308
+ containerStyle.left = "12px";
309
+ } else if (position.includes("Center")) {
310
+ containerStyle.left = "50%";
311
+ containerStyle.transform = "translateX(-50%)";
312
+ }
313
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)("div", {
314
+ style: containerStyle,
315
+ className: "Litho-ToastProvider__Container",
316
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_Stack.default, {
317
+ gap: stackGap,
318
+ children: positionToasts.map(function(toast, index) {
319
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_ToastNotification.default, {
320
+ prefix: toast.prefix,
321
+ icon: toast.icon,
322
+ title: toast.title,
323
+ subtitle: toast.subtitle,
324
+ duration: toast.duration,
325
+ position: toast.position || defaultPosition,
326
+ dismissible: toast.dismissible,
327
+ fixed: false,
328
+ onClick: toast.onClick,
329
+ onDismiss: function() {
330
+ return handleToastDismiss(toast.id, toast.onDismiss);
331
+ }
332
+ }, toast.id);
333
+ })
334
+ })
335
+ }, position);
336
+ })
337
+ ]
338
+ }), container)
339
+ ]
340
+ });
341
+ }
342
+ var _default = ToastProvider;
package/dist/cjs/index.js CHANGED
@@ -192,6 +192,12 @@ _export(exports, {
192
192
  get Tip () {
193
193
  return _Tip.default;
194
194
  },
195
+ get ToastNotification () {
196
+ return _ToastNotification.default;
197
+ },
198
+ get ToastProvider () {
199
+ return _ToastProvider.default;
200
+ },
195
201
  get Tooltip () {
196
202
  return _Tooltip.default;
197
203
  },
@@ -206,6 +212,9 @@ _export(exports, {
206
212
  },
207
213
  get useIndexResourceState () {
208
214
  return _useIndexResourceState.useIndexResourceState;
215
+ },
216
+ get useToast () {
217
+ return _ToastProvider.useToast;
209
218
  }
210
219
  });
211
220
  var _ActionList = /*#__PURE__*/ _interop_require_default(require("./components/ActionList"));
@@ -268,6 +277,8 @@ var _TextField = /*#__PURE__*/ _interop_require_default(require("./components/Te
268
277
  var _Thumbnail = /*#__PURE__*/ _interop_require_default(require("./components/Thumbnail"));
269
278
  var _TimePicker = /*#__PURE__*/ _interop_require_default(require("./components/TimePicker"));
270
279
  var _Tip = /*#__PURE__*/ _interop_require_default(require("./components/Tip"));
280
+ var _ToastNotification = /*#__PURE__*/ _interop_require_default(require("./components/ToastNotification"));
281
+ var _ToastProvider = /*#__PURE__*/ _interop_require_wildcard(require("./components/ToastProvider"));
271
282
  var _Tooltip = /*#__PURE__*/ _interop_require_default(require("./components/Tooltip"));
272
283
  var _TopBar = /*#__PURE__*/ _interop_require_default(require("./components/TopBar"));
273
284
  var _VerticalStack = /*#__PURE__*/ _interop_require_default(require("./components/VerticalStack"));
@@ -68,7 +68,7 @@ import Link from "./Link.js";
68
68
  import SkeletonText from "./SkeletonText.js";
69
69
  import Spinner from "./Spinner.js";
70
70
  import Text from "./Text.js";
71
- import { CancelMajor, CircleAlertMajor, FileMinor, ImageMajor, ImagesMajor } from "@shopify/polaris-icons";
71
+ import { CancelMajor, CircleAlertMajor, FileMinor, ImageMajor, ImagesMajor, MagicMajor } from "@shopify/polaris-icons";
72
72
  var dropZoneStyles = tv({
73
73
  base: "Litho-DropZone w-full flex items-center justify-center p-4 border border-form-border border-dashed rounded-md focus:outline-hidden",
74
74
  variants: {
@@ -276,6 +276,10 @@ var dropZoneStyles = tv({
276
276
  }),
277
277
  labelAction && /*#__PURE__*/ _jsx(Link, {
278
278
  onClick: labelAction.onAction,
279
+ insight: labelAction.insight,
280
+ icon: labelAction.insight ? MagicMajor : undefined,
281
+ color: labelAction.insight ? "insight" : undefined,
282
+ disabled: labelAction.disabled,
279
283
  removeUnderline: true,
280
284
  children: labelAction.content
281
285
  })
@@ -27,6 +27,7 @@ function _object_spread(target) {
27
27
  return target;
28
28
  }
29
29
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
30
+ import React from "react";
30
31
  import { tv } from "tailwind-variants";
31
32
  import Badge from "./Badge.js";
32
33
  import Icon from "./Icon.js";
@@ -225,7 +226,7 @@ var linkStyles = tv({
225
226
  })
226
227
  ]
227
228
  }),
228
- badge ? /*#__PURE__*/ _jsx(Badge, {
229
+ badge ? /*#__PURE__*/ React.isValidElement(badge) ? badge : /*#__PURE__*/ _jsx(Badge, {
229
230
  status: badge.status,
230
231
  children: badge.label
231
232
  }) : external ? /*#__PURE__*/ _jsx(Icon, {
@@ -314,10 +315,10 @@ var subLinkStyles = tv({
314
315
  })
315
316
  ]
316
317
  }),
317
- badge && /*#__PURE__*/ _jsx(Badge, {
318
+ badge && /*#__PURE__*/ (React.isValidElement(badge) ? badge : /*#__PURE__*/ _jsx(Badge, {
318
319
  status: badge.status,
319
320
  children: badge.label
320
- }),
321
+ })),
321
322
  accessory
322
323
  ]
323
324
  });
@@ -138,7 +138,7 @@ var styles = tv({
138
138
  * @returns {JSX.Element} The rendered popover component.
139
139
  */ function Popover() {
140
140
  var props = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
141
- var activatorWrapper = props.activatorWrapper, _props_activatorDisplayType = props.activatorDisplayType, activatorDisplayType = _props_activatorDisplayType === void 0 ? "inline-block" : _props_activatorDisplayType, activator = props.activator, children = props.children, onClose = props.onClose, active = props.active, fixed = props.fixed, zIndexOverride = props.zIndexOverride, _props_sectioned = props.sectioned, sectioned = _props_sectioned === void 0 ? false : _props_sectioned, _props_preferredAlignment = props.preferredAlignment, preferredAlignment = _props_preferredAlignment === void 0 ? "center" : _props_preferredAlignment, _props_preferredPosition = props.preferredPosition, preferredPosition = _props_preferredPosition === void 0 ? "below" : _props_preferredPosition, _props_matchActivatorWidth = props.matchActivatorWidth, matchActivatorWidth = _props_matchActivatorWidth === void 0 ? false : _props_matchActivatorWidth, _props_maxWidth = props.maxWidth, maxWidth = _props_maxWidth === void 0 ? "default" : _props_maxWidth, className = props.className, containerClassName = props.containerClassName;
141
+ var activatorWrapper = props.activatorWrapper, _props_activatorDisplayType = props.activatorDisplayType, activatorDisplayType = _props_activatorDisplayType === void 0 ? "inline-block" : _props_activatorDisplayType, activator = props.activator, children = props.children, onClose = props.onClose, active = props.active, fixed = props.fixed, zIndexOverride = props.zIndexOverride, _props_sectioned = props.sectioned, sectioned = _props_sectioned === void 0 ? false : _props_sectioned, _props_preferredAlignment = props.preferredAlignment, preferredAlignment = _props_preferredAlignment === void 0 ? "center" : _props_preferredAlignment, _props_preferredPosition = props.preferredPosition, preferredPosition = _props_preferredPosition === void 0 ? "below" : _props_preferredPosition, _props_matchActivatorWidth = props.matchActivatorWidth, matchActivatorWidth = _props_matchActivatorWidth === void 0 ? false : _props_matchActivatorWidth, _props_maxWidth = props.maxWidth, maxWidth = _props_maxWidth === void 0 ? "default" : _props_maxWidth, className = props.className, containerClassName = props.containerClassName, _props_closeOnResize = props.closeOnResize, closeOnResize = _props_closeOnResize === void 0 ? true : _props_closeOnResize, _props_debounceResizeObserver = props.debounceResizeObserver, debounceResizeObserver = _props_debounceResizeObserver === void 0 ? false : _props_debounceResizeObserver, _props_usePortal = props.usePortal, usePortal = _props_usePortal === void 0 ? true : _props_usePortal;
142
142
  var ActivatorWrapper = activatorWrapper || "div";
143
143
  var idValue = useId();
144
144
  var idRef = useRef(idValue);
@@ -154,6 +154,25 @@ var styles = tv({
154
154
  }, zIndexOverride ? {
155
155
  zIndex: zIndexOverride
156
156
  } : {})), 2), popoverStyle = _useState[0], setPopoverStyle = _useState[1];
157
+ // Reset popover style to hidden when it becomes active - this prevents flash
158
+ // of stale position from previous open. useLayoutEffect ensures this happens
159
+ // synchronously before paint.
160
+ useLayoutEffect(function() {
161
+ if (active) {
162
+ setPopoverStyle(_object_spread({
163
+ visibility: "hidden",
164
+ opacity: 0,
165
+ position: "absolute",
166
+ top: 0,
167
+ left: 0
168
+ }, zIndexOverride ? {
169
+ zIndex: zIndexOverride
170
+ } : {}));
171
+ }
172
+ }, [
173
+ active,
174
+ zIndexOverride
175
+ ]);
157
176
  useEffect(function() {
158
177
  if (active) {
159
178
  PopoverManager.open(idRef.current);
@@ -283,7 +302,8 @@ var styles = tv({
283
302
  observer.disconnect();
284
303
  };
285
304
  }, [
286
- active
305
+ active,
306
+ debounceResizeObserver
287
307
  ]);
288
308
  useLayoutEffect(function() {
289
309
  if (!active || !popoverRef.current) return;
@@ -328,7 +348,7 @@ var styles = tv({
328
348
  }
329
349
  };
330
350
  var handleResize = function handleResize() {
331
- if (onClose) {
351
+ if (onClose && closeOnResize) {
332
352
  onClose();
333
353
  }
334
354
  };
@@ -371,7 +391,15 @@ var styles = tv({
371
391
  className: "Litho-PopoverActivator ".concat(activatorDisplayType),
372
392
  children: memoizedActivator
373
393
  }),
374
- active && typeof children !== "undefined" && /*#__PURE__*/ createPortal(/*#__PURE__*/ _jsx("div", {
394
+ active && typeof children !== "undefined" && (usePortal ? /*#__PURE__*/ createPortal(/*#__PURE__*/ _jsx("div", {
395
+ className: "@container",
396
+ children: /*#__PURE__*/ _jsx("div", {
397
+ ref: popoverRef,
398
+ style: popoverStyle,
399
+ className: "".concat(classes).concat(className ? " ".concat(className) : ""),
400
+ children: children
401
+ })
402
+ }), document.body) : /*#__PURE__*/ _jsx("div", {
375
403
  className: "@container",
376
404
  children: /*#__PURE__*/ _jsx("div", {
377
405
  ref: popoverRef,
@@ -379,7 +407,7 @@ var styles = tv({
379
407
  className: "".concat(classes).concat(className ? " ".concat(className) : ""),
380
408
  children: children
381
409
  })
382
- }), document.body)
410
+ }))
383
411
  ]
384
412
  });
385
413
  }
@@ -52,7 +52,7 @@ import Icon from "./Icon.js";
52
52
  import Label from "./Label.js";
53
53
  import Link from "./Link.js";
54
54
  import Text from "./Text.js";
55
- import { CaretDownMinor, CircleAlertMajor } from "@shopify/polaris-icons";
55
+ import { CaretDownMinor, CircleAlertMajor, MagicMajor } from "@shopify/polaris-icons";
56
56
  var styles = tv({
57
57
  base: "Litho-Select relative border border-form-border rounded-md",
58
58
  variants: {
@@ -188,6 +188,10 @@ var contentStyles = tv({
188
188
  }),
189
189
  labelAction && /*#__PURE__*/ _jsx(Link, {
190
190
  onClick: labelAction.onAction,
191
+ insight: labelAction.insight,
192
+ icon: labelAction.insight ? MagicMajor : undefined,
193
+ color: labelAction.insight ? "insight" : undefined,
194
+ disabled: labelAction.disabled,
191
195
  removeUnderline: true,
192
196
  children: labelAction.content
193
197
  })
@@ -84,9 +84,57 @@ var gradientOverlayStyles = tv({
84
84
  }
85
85
  }
86
86
  });
87
+ var containerStyles = tv({
88
+ base: "w-2 h-2 rounded-full relative overflow-hidden bg-tint-2 flex-shrink-0",
89
+ variants: {
90
+ readStatus: {
91
+ full: ""
92
+ }
93
+ },
94
+ defaultVariants: {
95
+ readStatus: "read"
96
+ }
97
+ });
98
+ var readStatusStyles = tv({
99
+ base: "absolute w-full h-full",
100
+ variants: {
101
+ readStatus: {
102
+ read: "",
103
+ partiallyRead: "bg-brand-saturated",
104
+ unread: "bg-brand-saturated"
105
+ }
106
+ },
107
+ defaultVariants: {
108
+ readStatus: "read"
109
+ }
110
+ });
111
+ // Small read status indicator for tabs
112
+ function TabReadStatusIndicator(param) {
113
+ var readStatus = param.readStatus;
114
+ if (!readStatus || !readStatus.status) {
115
+ return null;
116
+ }
117
+ var status = readStatus.status;
118
+ // Don't show indicator for read threads
119
+ if (status === "read") {
120
+ return null;
121
+ }
122
+ var containerClasses = containerStyles({
123
+ readStatus: status
124
+ });
125
+ var readStatusClasses = readStatusStyles({
126
+ readStatus: status
127
+ });
128
+ return /*#__PURE__*/ _jsx("div", {
129
+ className: containerClasses,
130
+ children: /*#__PURE__*/ _jsx("div", {
131
+ className: readStatusClasses
132
+ })
133
+ });
134
+ }
87
135
  // Component to handle truncation detection and tooltip
88
136
  function TabTitle(param) {
89
- var title = param.title, isActive = param.isActive, tabContainerRef = param.tabContainerRef;
137
+ var title = param.title, isActive = param.isActive, tabContainerRef = param.tabContainerRef, readStatus = param.readStatus;
90
138
  var _useState = _sliced_to_array(useState(false), 2), shouldShowTooltip = _useState[0], setShouldShowTooltip = _useState[1];
91
139
  useLayoutEffect(function() {
92
140
  if (!title || !(tabContainerRef === null || tabContainerRef === void 0 ? void 0 : tabContainerRef.current)) {
@@ -123,16 +171,21 @@ function TabTitle(param) {
123
171
  title,
124
172
  tabContainerRef
125
173
  ]);
126
- var textElement = /*#__PURE__*/ _jsx("div", {
127
- className: "overflow-hidden",
128
- children: /*#__PURE__*/ _jsx(Text, {
129
- variant: "bodyXs",
130
- className: textStyles({
131
- isActive: isActive
174
+ var textElement = /*#__PURE__*/ _jsxs("div", {
175
+ className: "overflow-hidden flex items-center gap-1.5 min-w-0",
176
+ children: [
177
+ /*#__PURE__*/ _jsx(Text, {
178
+ variant: "bodyXs",
179
+ className: "".concat(textStyles({
180
+ isActive: isActive
181
+ }), " min-w-0 flex-1"),
182
+ clampLines: 1,
183
+ children: title
132
184
  }),
133
- clampLines: 1,
134
- children: title
135
- })
185
+ readStatus && /*#__PURE__*/ _jsx(TabReadStatusIndicator, {
186
+ readStatus: readStatus
187
+ })
188
+ ]
136
189
  });
137
190
  // Only show tooltip if text is likely truncated based on character count vs tab width
138
191
  if (shouldShowTooltip) {
@@ -251,7 +304,8 @@ function TabNavigation() {
251
304
  }) : /*#__PURE__*/ _jsx(TabTitle, {
252
305
  title: tab.title,
253
306
  isActive: isActive,
254
- tabContainerRef: tabRef
307
+ tabContainerRef: tabRef,
308
+ readStatus: tab.readStatus
255
309
  }),
256
310
  /*#__PURE__*/ _jsx("div", {
257
311
  className: "".concat(gradientOverlayStyles({
@@ -226,10 +226,11 @@ var clearButtonStyles = tv({
226
226
  * @param {Function} [props.onKeyDown] - Handler for key down.
227
227
  * @param {ReactNode} [props.tooltip] - Tooltip content for the label.
228
228
  * @param {string} [props.className] - Additional CSS classes.
229
+ * @param {boolean} [props.disableFocusStyles=false] - Whether to disable focused styles when the input is focused.
229
230
  * @returns {JSX.Element} The rendered TextField component.
230
231
  */ function TextField() {
231
232
  var props = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
232
- var prefix = props.prefix, _suffix = props.suffix, placeholder = props.placeholder, _props_value = props.value, value = _props_value === void 0 ? "" : _props_value, helpText = props.helpText, label = props.label, _props_labelVariant = props.labelVariant, labelVariant = _props_labelVariant === void 0 ? "bodyMd" : _props_labelVariant, labelAction = props.labelAction, labelHidden = props.labelHidden, _props_disabled = props.disabled, disabled = _props_disabled === void 0 ? false : _props_disabled, clearButton = props.clearButton, readOnly = props.readOnly, autoFocus = props.autoFocus, _focused = props.focused, _props_multiline = props.multiline, multiline = _props_multiline === void 0 ? 1 : _props_multiline, _props_autoGrow = props.autoGrow, autoGrow = _props_autoGrow === void 0 ? false : _props_autoGrow, maxHeight = props.maxHeight, error = props.error, connectedRight = props.connectedRight, connectedLeft = props.connectedLeft, _props_type = props.type, type = _props_type === void 0 ? "text" : _props_type, _props_subdued = props.subdued, subdued = _props_subdued === void 0 ? false : _props_subdued, name = props.name, _id = props.id, role = props.role, step = props.step, _props_largeStep = props.largeStep, largeStep = _props_largeStep === void 0 ? 10 : _props_largeStep, autoComplete = props.autoComplete, max = props.max, maxLength = props.maxLength, min = props.min, minLength = props.minLength, _props_showCharacterCount = props.showCharacterCount, showCharacterCount = _props_showCharacterCount === void 0 ? false : _props_showCharacterCount, pattern = props.pattern, spellCheck = props.spellCheck, ariaOwns = props.ariaOwns, ariaControls = props.ariaControls, ariaExpanded = props.ariaExpanded, ariaActiveDescendant = props.ariaActiveDescendant, ariaAutocomplete = props.ariaAutocomplete, _props_align = props.align, align = _props_align === void 0 ? "left" : _props_align, requiredIndicator = props.requiredIndicator, selectTextOnFocus = props.selectTextOnFocus, onClearButtonClick = props.onClearButtonClick, onChange = props.onChange, onFocus = props.onFocus, onBlur = props.onBlur, tooltip = props.tooltip, className = props.className, _inputRef = props.inputRef, icon = props.icon, _props_transparent = props.transparent, transparent = _props_transparent === void 0 ? false : _props_transparent, _props_showNumberSteppers = props.showNumberSteppers, showNumberSteppers = _props_showNumberSteppers === void 0 ? true : _props_showNumberSteppers, onKeyDown = props.onKeyDown;
233
+ var prefix = props.prefix, _suffix = props.suffix, placeholder = props.placeholder, _props_value = props.value, value = _props_value === void 0 ? "" : _props_value, helpText = props.helpText, label = props.label, _props_labelVariant = props.labelVariant, labelVariant = _props_labelVariant === void 0 ? "bodyMd" : _props_labelVariant, labelAction = props.labelAction, labelHidden = props.labelHidden, _props_disabled = props.disabled, disabled = _props_disabled === void 0 ? false : _props_disabled, clearButton = props.clearButton, readOnly = props.readOnly, autoFocus = props.autoFocus, _focused = props.focused, _props_multiline = props.multiline, multiline = _props_multiline === void 0 ? 1 : _props_multiline, _props_autoGrow = props.autoGrow, autoGrow = _props_autoGrow === void 0 ? false : _props_autoGrow, maxHeight = props.maxHeight, error = props.error, connectedRight = props.connectedRight, connectedLeft = props.connectedLeft, _props_type = props.type, type = _props_type === void 0 ? "text" : _props_type, _props_subdued = props.subdued, subdued = _props_subdued === void 0 ? false : _props_subdued, name = props.name, _id = props.id, role = props.role, step = props.step, _props_largeStep = props.largeStep, largeStep = _props_largeStep === void 0 ? 10 : _props_largeStep, autoComplete = props.autoComplete, max = props.max, maxLength = props.maxLength, min = props.min, minLength = props.minLength, _props_showCharacterCount = props.showCharacterCount, showCharacterCount = _props_showCharacterCount === void 0 ? false : _props_showCharacterCount, pattern = props.pattern, spellCheck = props.spellCheck, ariaOwns = props.ariaOwns, ariaControls = props.ariaControls, ariaExpanded = props.ariaExpanded, ariaActiveDescendant = props.ariaActiveDescendant, ariaAutocomplete = props.ariaAutocomplete, _props_align = props.align, align = _props_align === void 0 ? "left" : _props_align, requiredIndicator = props.requiredIndicator, selectTextOnFocus = props.selectTextOnFocus, onClearButtonClick = props.onClearButtonClick, onChange = props.onChange, onFocus = props.onFocus, onBlur = props.onBlur, tooltip = props.tooltip, className = props.className, _inputRef = props.inputRef, icon = props.icon, _props_transparent = props.transparent, transparent = _props_transparent === void 0 ? false : _props_transparent, _props_showNumberSteppers = props.showNumberSteppers, showNumberSteppers = _props_showNumberSteppers === void 0 ? true : _props_showNumberSteppers, onKeyDown = props.onKeyDown, _props_disableFocusStyles = props.disableFocusStyles, disableFocusStyles = _props_disableFocusStyles === void 0 ? false : _props_disableFocusStyles;
233
234
  var suffix = maxLength && showCharacterCount ? "".concat(value.length, " / ").concat(maxLength) : _suffix;
234
235
  var _internalRef = useRef(null);
235
236
  var inputRef = _inputRef || _internalRef;
@@ -288,7 +289,7 @@ var clearButtonStyles = tv({
288
289
  var classes = styles({
289
290
  disabled: Boolean(disabled || readOnly),
290
291
  hasError: hasError,
291
- focused: Boolean(focused && !readOnly),
292
+ focused: Boolean(focused && !readOnly && !disableFocusStyles),
292
293
  subdued: subdued,
293
294
  transparent: transparent
294
295
  });
@@ -511,6 +512,7 @@ var clearButtonStyles = tv({
511
512
  insight: labelAction.insight,
512
513
  icon: labelAction.insight ? MagicMajor : undefined,
513
514
  color: labelAction.insight ? "insight" : undefined,
515
+ disabled: labelAction.disabled,
514
516
  removeUnderline: true,
515
517
  children: labelAction.content
516
518
  })