@openzeppelin/ui-components 3.4.0 → 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.
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import { a as getValidationStateClasses, c as isDuplicateMapKey, d as INTEGER_HTML_PATTERN, f as INTEGER_INPUT_PATTERN, i as getErrorMessage, l as validateField, n as createValidationResult, o as handleValidationError, p as INTEGER_PATTERN, r as formatValidationError, s as hasFieldError, t as ErrorMessage, u as validateMapEntries } from "./ErrorMessage-BqOEJm84.mjs";
2
2
  import * as AccordionPrimitive from "@radix-ui/react-accordion";
3
3
  import { cva } from "class-variance-authority";
4
- import { AlertCircle, Calendar as Calendar$1, Check, CheckCircle, CheckCircle2, CheckIcon, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Circle, ClipboardPaste, CloudOff, Copy, DollarSign, ExternalLink as ExternalLink$1, ExternalLinkIcon, Eye, EyeOff, File, FileText, GripVertical, Hash, Info, Loader2, Menu, MoreHorizontal, Network, Pencil, PencilLine, Plus, Search, Settings, Timer, Upload, X } from "lucide-react";
4
+ import { AlertCircle, Calendar as Calendar$1, Check, CheckCircle, CheckCircle2, CheckIcon, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Circle, ClipboardPaste, CloudOff, Copy, DollarSign, ExternalLink as ExternalLink$1, ExternalLinkIcon, Eye, EyeOff, File, FileText, GripVertical, Hash, Info, Loader2, Menu, MoreHorizontal, Network, Pencil, PencilLine, Plus, Search, Settings, Timer, TriangleAlert, Upload, X } from "lucide-react";
5
5
  import * as React$1 from "react";
6
6
  import React, { createContext, useCallback, useContext, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
7
- import { classifyAddressCandidates, classifyAddressInput, cn, getDefaultValueForType, getHostedNetworkAvailabilityNoticeCopy, getInvalidUrlMessage, getServiceDisplayName, isChainScopeMismatch, isNetworkAvailabilityPolicyActive, isValidUrl, logger, nameResolutionChainScopeMismatchMessage, nameResolutionMessageForCode, parseDelimitedAddressInput, truncateMiddle, validateBytesSimple } from "@openzeppelin/ui-utils";
7
+ import { classifyAddressCandidates, classifyAddressInput, cn, crossNetworkFallbackMessageNames, getDefaultValueForType, getFallbackNetworks, getHostedNetworkAvailabilityNoticeCopy, getInvalidUrlMessage, getServiceDisplayName, isChainScopeMismatch, isCrossNetworkFallback, isNetworkAvailabilityPolicyActive, isValidUrl, logger, nameResolutionChainScopeMismatchMessage, nameResolutionCrossNetworkFallbackMessage, nameResolutionMessageForCode, parseDelimitedAddressInput, truncateMiddle, validateBytesSimple } from "@openzeppelin/ui-utils";
8
8
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
9
9
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
10
10
  import { Slot, Slottable } from "@radix-ui/react-slot";
@@ -26,7 +26,7 @@ import { Toaster as Toaster$1, toast } from "sonner";
26
26
  import { useTheme } from "next-themes";
27
27
 
28
28
  //#region src/version.ts
29
- const VERSION = "3.4.0";
29
+ const VERSION = "3.6.0";
30
30
 
31
31
  //#endregion
32
32
  //#region src/components/ui/accordion.tsx
@@ -264,7 +264,7 @@ function sanitizeVerifiedNameForDisplay(name) {
264
264
  * <AddressDisplay address="G..." truncateWhenLabeled />
265
265
  * ```
266
266
  */
267
- function AddressDisplay({ address, truncate: truncateProp, truncateWhenLabeled = false, untruncateOnHover = false, startChars = 6, endChars = 4, showCopyButton = false, showCopyButtonOnHover = false, explorerUrl, label: labelProp, onLabelEdit: onLabelEditProp, networkId, disableLabel = false, showTooltip = false, variant = "chip", avatar, avatarVariant = "fill", resolvedName, className, onPointerEnter, onPointerLeave, onMouseEnter, onMouseLeave, onClick, ...props }) {
267
+ function AddressDisplay({ address, truncate: truncateProp, truncateWhenLabeled = false, untruncateOnHover = false, startChars = 6, endChars = 4, showCopyButton = false, showCopyButtonOnHover = false, explorerUrl, label: labelProp, onLabelEdit: onLabelEditProp, networkId, disableLabel = false, showTooltip = false, variant = "chip", avatar, avatarVariant = "fill", resolvedName, showCrossNetworkFallbackDisclaimer = true, className, onPointerEnter, onPointerLeave, onMouseEnter, onMouseLeave, onClick, ...props }) {
268
268
  const [copied, setCopied] = React$1.useState(false);
269
269
  const [isHovered, setIsHovered] = React$1.useState(false);
270
270
  const copyTimeoutRef = React$1.useRef(null);
@@ -275,6 +275,13 @@ function AddressDisplay({ address, truncate: truncateProp, truncateWhenLabeled =
275
275
  const record = disableLabel ? void 0 : resolvedName ?? nameResolver?.resolveAddressName(address, networkId);
276
276
  const ensName = record?.forwardVerified === true ? sanitizeVerifiedNameForDisplay(record.name) : void 0;
277
277
  const effectiveLabel = resolvedLabel ?? ensName;
278
+ const showFallbackNote = showCrossNetworkFallbackDisclaimer && ensName !== void 0 && effectiveLabel === ensName && record !== void 0 && isCrossNetworkFallback(record.provenance);
279
+ const fallbackNote = (() => {
280
+ if (!showFallbackNote) return void 0;
281
+ const networks = getFallbackNetworks(record.provenance);
282
+ if (networks === void 0) return void 0;
283
+ return nameResolutionCrossNetworkFallbackMessage(networks, crossNetworkFallbackMessageNames(networks, nameResolver?.resolveNetworkLabel));
284
+ })();
278
285
  const effectiveTruncate = truncateProp !== void 0 ? truncateProp : truncateWhenLabeled ? Boolean(effectiveLabel) : true;
279
286
  const contextEditHandler = React$1.useCallback(() => {
280
287
  resolver?.onEditLabel?.(address, networkId);
@@ -375,9 +382,29 @@ function AddressDisplay({ address, truncate: truncateProp, truncateWhenLabeled =
375
382
  });
376
383
  };
377
384
  if (effectiveLabel) {
378
- const labelColumn = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
379
- className: "truncate font-sans font-medium text-slate-900 leading-snug",
380
- children: effectiveLabel
385
+ const labelColumn = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("span", {
386
+ className: "inline-flex min-w-0 max-w-full items-center gap-1",
387
+ children: [/* @__PURE__ */ jsx("span", {
388
+ className: "truncate font-sans font-medium text-slate-900 leading-snug",
389
+ children: effectiveLabel
390
+ }), fallbackNote && showCrossNetworkFallbackDisclaimer ? /* @__PURE__ */ jsx(TooltipProvider, {
391
+ delayDuration: 300,
392
+ children: /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
393
+ asChild: true,
394
+ children: /* @__PURE__ */ jsx("button", {
395
+ type: "button",
396
+ className: "inline-flex shrink-0 rounded-sm text-amber-500 outline-none focus-visible:ring-2 focus-visible:ring-amber-500/50",
397
+ "aria-label": fallbackNote,
398
+ children: /* @__PURE__ */ jsx(TriangleAlert, {
399
+ className: "h-3 w-3",
400
+ "aria-hidden": true
401
+ })
402
+ })
403
+ }), /* @__PURE__ */ jsx(TooltipContent, {
404
+ className: "max-w-xs font-sans text-xs font-normal normal-case",
405
+ children: fallbackNote
406
+ })] })
407
+ }) : null]
381
408
  }), /* @__PURE__ */ jsxs("div", {
382
409
  className: "flex min-w-0 items-center font-mono text-[10px] text-slate-400 leading-snug",
383
410
  children: [/* @__PURE__ */ jsx("span", {
@@ -541,8 +568,11 @@ function useAddressLabel(address, networkId) {
541
568
  *
542
569
  * @param props - Resolver function and children
543
570
  */
544
- function AddressNameProvider({ children, resolveAddressName }) {
545
- const value = React$1.useMemo(() => ({ resolveAddressName }), [resolveAddressName]);
571
+ function AddressNameProvider({ children, resolveAddressName, resolveNetworkLabel }) {
572
+ const value = React$1.useMemo(() => ({
573
+ resolveAddressName,
574
+ resolveNetworkLabel
575
+ }), [resolveAddressName, resolveNetworkLabel]);
546
576
  return /* @__PURE__ */ jsx(AddressNameContext.Provider, {
547
577
  value,
548
578
  children
@@ -3385,7 +3415,7 @@ function normalizeResolvedName(value) {
3385
3415
  * The component stays capability-free: it never reads a runtime or wallet
3386
3416
  * state; everything arrives through the injected context (INV-118).
3387
3417
  */
3388
- function AddressField({ id, label, placeholder, helperText, control, name, width = "full", validation, addressing, readOnly, suggestions: suggestionsProp, onSuggestionSelect, onResolvedNameChange }) {
3418
+ function AddressField({ id, label, placeholder, helperText, control, name, width = "full", validation, addressing, readOnly, suggestions: suggestionsProp, onSuggestionSelect, onResolvedNameChange, showCrossNetworkFallbackDisclaimer = true, showForwardResolutionSuccessAnnouncer = true }) {
3389
3419
  const isRequired = !!validation?.required;
3390
3420
  const errorId = `${id}-error`;
3391
3421
  const descriptionId = `${id}-description`;
@@ -3395,6 +3425,7 @@ function AddressField({ id, label, placeholder, helperText, control, name, width
3395
3425
  const isValidName = resolver?.isValidName;
3396
3426
  const activeNetworkId = resolver?.activeNetworkId;
3397
3427
  const activeNetworkName = resolver?.activeNetworkName;
3428
+ const resolveNetworkLabel = resolver?.resolveNetworkLabel;
3398
3429
  const lastSetValueRef = useRef("");
3399
3430
  const [inputValue, setInputValue] = useState("");
3400
3431
  const watchedFieldValue = useWatch({
@@ -3585,12 +3616,19 @@ function AddressField({ id, label, placeholder, helperText, control, name, width
3585
3616
  className: "text-destructive text-sm",
3586
3617
  children: nameResolutionChainScopeMismatchMessage({ activeNetworkName })
3587
3618
  });
3619
+ const fallbackNetworks = showCrossNetworkFallbackDisclaimer && isCrossNetworkFallback(resolution.data.provenance) ? getFallbackNetworks(resolution.data.provenance) : void 0;
3620
+ const fallbackMessage = fallbackNetworks && nameResolutionCrossNetworkFallbackMessage(fallbackNetworks, crossNetworkFallbackMessageNames(fallbackNetworks, resolveNetworkLabel));
3621
+ if (!showForwardResolutionSuccessAnnouncer) return null;
3588
3622
  return /* @__PURE__ */ jsxs("span", {
3589
3623
  className: "text-sm",
3590
- children: ["Resolved to ", /* @__PURE__ */ jsx("code", {
3624
+ children: [/* @__PURE__ */ jsxs("span", { children: ["Resolved to ", /* @__PURE__ */ jsx("code", {
3591
3625
  className: "font-mono",
3592
3626
  children: resolution.data.address
3593
- })]
3627
+ })] }), fallbackMessage ? /* @__PURE__ */ jsx("span", {
3628
+ className: "mt-1 block text-muted-foreground text-xs",
3629
+ role: "note",
3630
+ children: fallbackMessage
3631
+ }) : null]
3594
3632
  });
3595
3633
  case "error": {
3596
3634
  const networkName = resolution.error.code === "UNSUPPORTED_NETWORK" ? resolution.error.networkId || void 0 : void 0;
@@ -4270,17 +4308,19 @@ function useAddressSuggestions(query, networkId) {
4270
4308
  *
4271
4309
  * @param props - Injected resolver functions and children
4272
4310
  */
4273
- function NameResolverProvider({ children, isValidName, resolveName, activeNetworkId, activeNetworkName }) {
4311
+ function NameResolverProvider({ children, isValidName, resolveName, activeNetworkId, activeNetworkName, resolveNetworkLabel }) {
4274
4312
  const value = React$1.useMemo(() => ({
4275
4313
  isValidName,
4276
4314
  resolveName,
4277
4315
  activeNetworkId,
4278
- activeNetworkName
4316
+ activeNetworkName,
4317
+ resolveNetworkLabel
4279
4318
  }), [
4280
4319
  isValidName,
4281
4320
  resolveName,
4282
4321
  activeNetworkId,
4283
- activeNetworkName
4322
+ activeNetworkName,
4323
+ resolveNetworkLabel
4284
4324
  ]);
4285
4325
  return /* @__PURE__ */ jsx(NameResolverContext.Provider, {
4286
4326
  value,