@openzeppelin/ui-components 1.5.0 → 1.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.
package/dist/index.cjs CHANGED
@@ -7,6 +7,8 @@ let react = require("react");
7
7
  react = require_ErrorMessage.__toESM(react);
8
8
  let _openzeppelin_ui_utils = require("@openzeppelin/ui-utils");
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
+ let _radix_ui_react_tooltip = require("@radix-ui/react-tooltip");
11
+ _radix_ui_react_tooltip = require_ErrorMessage.__toESM(_radix_ui_react_tooltip);
10
12
  let _radix_ui_react_slot = require("@radix-ui/react-slot");
11
13
  let react_day_picker = require("react-day-picker");
12
14
  let _radix_ui_react_checkbox = require("@radix-ui/react-checkbox");
@@ -31,12 +33,14 @@ let _radix_ui_react_collapsible = require("@radix-ui/react-collapsible");
31
33
  _radix_ui_react_collapsible = require_ErrorMessage.__toESM(_radix_ui_react_collapsible);
32
34
  let _radix_ui_react_tabs = require("@radix-ui/react-tabs");
33
35
  _radix_ui_react_tabs = require_ErrorMessage.__toESM(_radix_ui_react_tabs);
34
- let _radix_ui_react_tooltip = require("@radix-ui/react-tooltip");
35
- _radix_ui_react_tooltip = require_ErrorMessage.__toESM(_radix_ui_react_tooltip);
36
36
  let _openzeppelin_ui_types = require("@openzeppelin/ui-types");
37
37
  let sonner = require("sonner");
38
38
  let next_themes = require("next-themes");
39
39
 
40
+ //#region src/version.ts
41
+ const VERSION = "1.7.0";
42
+
43
+ //#endregion
40
44
  //#region src/components/ui/accordion.tsx
41
45
  const accordionItemVariants = (0, class_variance_authority.cva)("", {
42
46
  variants: { variant: {
@@ -114,6 +118,19 @@ const AccordionContent = react.forwardRef(({ className, children, variant: varia
114
118
  });
115
119
  AccordionContent.displayName = "AccordionContent";
116
120
 
121
+ //#endregion
122
+ //#region src/components/ui/tooltip.tsx
123
+ const TooltipProvider = _radix_ui_react_tooltip.Provider;
124
+ const Tooltip = _radix_ui_react_tooltip.Root;
125
+ const TooltipTrigger = _radix_ui_react_tooltip.Trigger;
126
+ const TooltipContent = react.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.Portal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.Content, {
127
+ ref,
128
+ sideOffset,
129
+ className: (0, _openzeppelin_ui_utils.cn)("bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden rounded-md px-3 py-1.5 text-xs", className),
130
+ ...props
131
+ }) }));
132
+ TooltipContent.displayName = _radix_ui_react_tooltip.Content.displayName;
133
+
117
134
  //#endregion
118
135
  //#region src/components/ui/address-display/context.ts
119
136
  /**
@@ -126,8 +143,20 @@ const AddressLabelContext = (0, react.createContext)(null);
126
143
  //#endregion
127
144
  //#region src/components/ui/address-display/address-display.tsx
128
145
  /**
146
+ * True when the primary input can hover (e.g. desktop with mouse).
147
+ * Touch-first phones typically report false. SSR assumes hover-capable.
148
+ */
149
+ function usePrefersHover() {
150
+ return react.useSyncExternalStore(react.useCallback((onStoreChange) => {
151
+ if (typeof window === "undefined" || typeof window.matchMedia === "undefined") return () => {};
152
+ const mq = window.matchMedia("(hover: hover)");
153
+ mq.addEventListener("change", onStoreChange);
154
+ return () => mq.removeEventListener("change", onStoreChange);
155
+ }, []), () => typeof window !== "undefined" && typeof window.matchMedia !== "undefined" ? window.matchMedia("(hover: hover)").matches : true, () => true);
156
+ }
157
+ /**
129
158
  * Displays a blockchain address with optional truncation, copy button,
130
- * explorer link, and human-readable label.
159
+ * explorer link, tooltip, and human-readable label.
131
160
  *
132
161
  * Labels are resolved in priority order:
133
162
  * 1. Explicit `label` prop
@@ -152,11 +181,22 @@ const AddressLabelContext = (0, react.createContext)(null);
152
181
  *
153
182
  * // Suppress label resolution for a specific instance
154
183
  * <AddressDisplay address="0x742d35Cc..." disableLabel />
184
+ *
185
+ * // Reveal full address on hover (still truncated when idle)
186
+ * <AddressDisplay address="0x742d35Cc..." untruncateOnHover />
187
+ *
188
+ * // Tooltip with full address on hover + copy icon on hover
189
+ * <AddressDisplay address="0x742d35Cc..." showTooltip showCopyButton showCopyButtonOnHover />
190
+ *
191
+ * // Inline variant (no chip background) — useful inside wallet bars
192
+ * <AddressDisplay address="0x742d35Cc..." variant="inline" showTooltip showCopyButton />
155
193
  * ```
156
194
  */
157
- function AddressDisplay({ address, truncate = true, startChars = 6, endChars = 4, showCopyButton = false, showCopyButtonOnHover = false, explorerUrl, label: labelProp, onLabelEdit: onLabelEditProp, networkId, disableLabel = false, className, ...props }) {
195
+ function AddressDisplay({ address, truncate = true, untruncateOnHover = false, startChars = 6, endChars = 4, showCopyButton = false, showCopyButtonOnHover = false, explorerUrl, label: labelProp, onLabelEdit: onLabelEditProp, networkId, disableLabel = false, showTooltip = false, variant = "chip", className, onPointerEnter, onPointerLeave, onMouseEnter, onMouseLeave, onClick, ...props }) {
158
196
  const [copied, setCopied] = react.useState(false);
197
+ const [isHovered, setIsHovered] = react.useState(false);
159
198
  const copyTimeoutRef = react.useRef(null);
199
+ const prefersHover = usePrefersHover();
160
200
  const resolver = react.useContext(AddressLabelContext);
161
201
  const resolvedLabel = disableLabel ? void 0 : labelProp ?? resolver?.resolveLabel(address, networkId);
162
202
  const contextEditHandler = react.useCallback(() => {
@@ -167,7 +207,25 @@ function AddressDisplay({ address, truncate = true, startChars = 6, endChars = 4
167
207
  networkId
168
208
  ]);
169
209
  const editHandler = disableLabel ? void 0 : onLabelEditProp ?? (resolver?.onEditLabel ? contextEditHandler : void 0);
170
- const displayAddress = truncate ? (0, _openzeppelin_ui_utils.truncateMiddle)(address, startChars, endChars) : address;
210
+ const canUntruncate = untruncateOnHover && truncate && !showTooltip;
211
+ const showFullAddress = !truncate || canUntruncate && isHovered;
212
+ const displayAddress = showFullAddress ? address : (0, _openzeppelin_ui_utils.truncateMiddle)(address, startChars, endChars);
213
+ const addressTextClassName = (0, _openzeppelin_ui_utils.cn)(!showFullAddress && "truncate", (showFullAddress || !truncate) && "break-all");
214
+ const expandInteractionClassName = canUntruncate && !prefersHover ? "cursor-pointer" : void 0;
215
+ const handlePointerEnter = (e) => {
216
+ if (canUntruncate && prefersHover) setIsHovered(true);
217
+ onPointerEnter?.(e);
218
+ onMouseEnter?.(e);
219
+ };
220
+ const handlePointerLeave = (e) => {
221
+ if (canUntruncate && prefersHover) setIsHovered(false);
222
+ onPointerLeave?.(e);
223
+ onMouseLeave?.(e);
224
+ };
225
+ const handleUntruncateClick = (e) => {
226
+ if (canUntruncate && !prefersHover) setIsHovered((open) => !open);
227
+ onClick?.(e);
228
+ };
171
229
  const handleCopy = (e) => {
172
230
  e.stopPropagation();
173
231
  navigator.clipboard.writeText(address);
@@ -183,6 +241,7 @@ function AddressDisplay({ address, truncate = true, startChars = 6, endChars = 4
183
241
  if (copyTimeoutRef.current) window.clearTimeout(copyTimeoutRef.current);
184
242
  };
185
243
  }, []);
244
+ const isChip = variant === "chip";
186
245
  const actionButtons = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
187
246
  showCopyButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
188
247
  type: "button",
@@ -195,6 +254,9 @@ function AddressDisplay({ address, truncate = true, startChars = 6, endChars = 4
195
254
  href: explorerUrl,
196
255
  target: "_blank",
197
256
  rel: "noopener noreferrer",
257
+ onClick: (e) => {
258
+ e.stopPropagation();
259
+ },
198
260
  className: "ml-1.5 shrink-0 text-slate-500 transition-colors hover:text-slate-700",
199
261
  "aria-label": "View in explorer",
200
262
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ExternalLink, { className: "h-3.5 w-3.5" })
@@ -210,28 +272,48 @@ function AddressDisplay({ address, truncate = true, startChars = 6, endChars = 4
210
272
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Pencil, { className: "h-3.5 w-3.5" })
211
273
  })
212
274
  ] });
213
- if (resolvedLabel) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
214
- className: (0, _openzeppelin_ui_utils.cn)("group inline-flex max-w-full flex-col rounded-md bg-slate-100 px-2 py-1", "text-xs text-slate-700", className),
275
+ const shouldShowTooltip = showTooltip && truncate;
276
+ const wrapWithTooltip = (content) => {
277
+ if (!shouldShowTooltip) return content;
278
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipProvider, {
279
+ delayDuration: 300,
280
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Tooltip, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipTrigger, {
281
+ asChild: true,
282
+ children: content
283
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipContent, {
284
+ className: "font-mono text-xs",
285
+ children: address
286
+ })] })
287
+ });
288
+ };
289
+ if (resolvedLabel) return wrapWithTooltip(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
290
+ className: (0, _openzeppelin_ui_utils.cn)("group inline-flex max-w-full min-w-0 flex-col", isChip && "rounded-md bg-slate-100 px-2 py-1", "text-xs text-slate-700", expandInteractionClassName, className),
291
+ onPointerEnter: handlePointerEnter,
292
+ onPointerLeave: handlePointerLeave,
293
+ onClick: handleUntruncateClick,
215
294
  ...props,
216
295
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
217
296
  className: "truncate font-sans font-medium text-slate-900 leading-snug",
218
297
  children: resolvedLabel
219
298
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
220
- className: "flex items-center font-mono text-[10px] text-slate-400 leading-snug",
299
+ className: "flex min-w-0 items-center font-mono text-[10px] text-slate-400 leading-snug",
221
300
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
222
- className: (0, _openzeppelin_ui_utils.cn)("truncate", truncate ? "" : "break-all"),
301
+ className: addressTextClassName,
223
302
  children: displayAddress
224
303
  }), actionButtons]
225
304
  })]
226
- });
227
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
228
- className: (0, _openzeppelin_ui_utils.cn)("group inline-flex max-w-full items-center rounded-md bg-slate-100 px-2 py-1", "text-xs font-mono text-slate-700", className),
305
+ }));
306
+ return wrapWithTooltip(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
307
+ className: (0, _openzeppelin_ui_utils.cn)("group inline-flex max-w-full min-w-0 items-center", isChip && "rounded-md bg-slate-100 px-2 py-1", "text-xs font-mono text-slate-700", expandInteractionClassName, className),
308
+ onPointerEnter: handlePointerEnter,
309
+ onPointerLeave: handlePointerLeave,
310
+ onClick: handleUntruncateClick,
229
311
  ...props,
230
312
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
231
- className: (0, _openzeppelin_ui_utils.cn)("truncate", truncate ? "" : "break-all"),
313
+ className: addressTextClassName,
232
314
  children: displayAddress
233
315
  }), actionButtons]
234
- });
316
+ }));
235
317
  }
236
318
 
237
319
  //#endregion
@@ -1808,19 +1890,6 @@ const Textarea = react.forwardRef(({ className, ...props }, ref) => {
1808
1890
  });
1809
1891
  Textarea.displayName = "Textarea";
1810
1892
 
1811
- //#endregion
1812
- //#region src/components/ui/tooltip.tsx
1813
- const TooltipProvider = _radix_ui_react_tooltip.Provider;
1814
- const Tooltip = _radix_ui_react_tooltip.Root;
1815
- const TooltipTrigger = _radix_ui_react_tooltip.Trigger;
1816
- const TooltipContent = react.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.Content, {
1817
- ref,
1818
- sideOffset,
1819
- className: (0, _openzeppelin_ui_utils.cn)("bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 overflow-hidden rounded-md px-3 py-1.5 text-xs", className),
1820
- ...props
1821
- }));
1822
- TooltipContent.displayName = _radix_ui_react_tooltip.Content.displayName;
1823
-
1824
1893
  //#endregion
1825
1894
  //#region src/components/ui/view-contract-state-button.tsx
1826
1895
  /**
@@ -6399,6 +6468,7 @@ exports.TooltipContent = TooltipContent;
6399
6468
  exports.TooltipProvider = TooltipProvider;
6400
6469
  exports.TooltipTrigger = TooltipTrigger;
6401
6470
  exports.UrlField = UrlField;
6471
+ exports.VERSION = VERSION;
6402
6472
  exports.ViewContractStateButton = ViewContractStateButton;
6403
6473
  exports.WizardLayout = WizardLayout;
6404
6474
  exports.WizardNavigation = WizardNavigation;