@openzeppelin/ui-components 1.5.0 → 1.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.cjs +92 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -8
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +50 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +91 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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,8 +33,6 @@ 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");
|
|
@@ -114,6 +114,19 @@ const AccordionContent = react.forwardRef(({ className, children, variant: varia
|
|
|
114
114
|
});
|
|
115
115
|
AccordionContent.displayName = "AccordionContent";
|
|
116
116
|
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/components/ui/tooltip.tsx
|
|
119
|
+
const TooltipProvider = _radix_ui_react_tooltip.Provider;
|
|
120
|
+
const Tooltip = _radix_ui_react_tooltip.Root;
|
|
121
|
+
const TooltipTrigger = _radix_ui_react_tooltip.Trigger;
|
|
122
|
+
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, {
|
|
123
|
+
ref,
|
|
124
|
+
sideOffset,
|
|
125
|
+
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),
|
|
126
|
+
...props
|
|
127
|
+
}) }));
|
|
128
|
+
TooltipContent.displayName = _radix_ui_react_tooltip.Content.displayName;
|
|
129
|
+
|
|
117
130
|
//#endregion
|
|
118
131
|
//#region src/components/ui/address-display/context.ts
|
|
119
132
|
/**
|
|
@@ -126,8 +139,20 @@ const AddressLabelContext = (0, react.createContext)(null);
|
|
|
126
139
|
//#endregion
|
|
127
140
|
//#region src/components/ui/address-display/address-display.tsx
|
|
128
141
|
/**
|
|
142
|
+
* True when the primary input can hover (e.g. desktop with mouse).
|
|
143
|
+
* Touch-first phones typically report false. SSR assumes hover-capable.
|
|
144
|
+
*/
|
|
145
|
+
function usePrefersHover() {
|
|
146
|
+
return react.useSyncExternalStore(react.useCallback((onStoreChange) => {
|
|
147
|
+
if (typeof window === "undefined" || typeof window.matchMedia === "undefined") return () => {};
|
|
148
|
+
const mq = window.matchMedia("(hover: hover)");
|
|
149
|
+
mq.addEventListener("change", onStoreChange);
|
|
150
|
+
return () => mq.removeEventListener("change", onStoreChange);
|
|
151
|
+
}, []), () => typeof window !== "undefined" && typeof window.matchMedia !== "undefined" ? window.matchMedia("(hover: hover)").matches : true, () => true);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
129
154
|
* Displays a blockchain address with optional truncation, copy button,
|
|
130
|
-
* explorer link, and human-readable label.
|
|
155
|
+
* explorer link, tooltip, and human-readable label.
|
|
131
156
|
*
|
|
132
157
|
* Labels are resolved in priority order:
|
|
133
158
|
* 1. Explicit `label` prop
|
|
@@ -152,11 +177,22 @@ const AddressLabelContext = (0, react.createContext)(null);
|
|
|
152
177
|
*
|
|
153
178
|
* // Suppress label resolution for a specific instance
|
|
154
179
|
* <AddressDisplay address="0x742d35Cc..." disableLabel />
|
|
180
|
+
*
|
|
181
|
+
* // Reveal full address on hover (still truncated when idle)
|
|
182
|
+
* <AddressDisplay address="0x742d35Cc..." untruncateOnHover />
|
|
183
|
+
*
|
|
184
|
+
* // Tooltip with full address on hover + copy icon on hover
|
|
185
|
+
* <AddressDisplay address="0x742d35Cc..." showTooltip showCopyButton showCopyButtonOnHover />
|
|
186
|
+
*
|
|
187
|
+
* // Inline variant (no chip background) — useful inside wallet bars
|
|
188
|
+
* <AddressDisplay address="0x742d35Cc..." variant="inline" showTooltip showCopyButton />
|
|
155
189
|
* ```
|
|
156
190
|
*/
|
|
157
|
-
function AddressDisplay({ address, truncate = true, startChars = 6, endChars = 4, showCopyButton = false, showCopyButtonOnHover = false, explorerUrl, label: labelProp, onLabelEdit: onLabelEditProp, networkId, disableLabel = false, className, ...props }) {
|
|
191
|
+
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
192
|
const [copied, setCopied] = react.useState(false);
|
|
193
|
+
const [isHovered, setIsHovered] = react.useState(false);
|
|
159
194
|
const copyTimeoutRef = react.useRef(null);
|
|
195
|
+
const prefersHover = usePrefersHover();
|
|
160
196
|
const resolver = react.useContext(AddressLabelContext);
|
|
161
197
|
const resolvedLabel = disableLabel ? void 0 : labelProp ?? resolver?.resolveLabel(address, networkId);
|
|
162
198
|
const contextEditHandler = react.useCallback(() => {
|
|
@@ -167,7 +203,25 @@ function AddressDisplay({ address, truncate = true, startChars = 6, endChars = 4
|
|
|
167
203
|
networkId
|
|
168
204
|
]);
|
|
169
205
|
const editHandler = disableLabel ? void 0 : onLabelEditProp ?? (resolver?.onEditLabel ? contextEditHandler : void 0);
|
|
170
|
-
const
|
|
206
|
+
const canUntruncate = untruncateOnHover && truncate && !showTooltip;
|
|
207
|
+
const showFullAddress = !truncate || canUntruncate && isHovered;
|
|
208
|
+
const displayAddress = showFullAddress ? address : (0, _openzeppelin_ui_utils.truncateMiddle)(address, startChars, endChars);
|
|
209
|
+
const addressTextClassName = (0, _openzeppelin_ui_utils.cn)(!showFullAddress && "truncate", (showFullAddress || !truncate) && "break-all");
|
|
210
|
+
const expandInteractionClassName = canUntruncate && !prefersHover ? "cursor-pointer" : void 0;
|
|
211
|
+
const handlePointerEnter = (e) => {
|
|
212
|
+
if (canUntruncate && prefersHover) setIsHovered(true);
|
|
213
|
+
onPointerEnter?.(e);
|
|
214
|
+
onMouseEnter?.(e);
|
|
215
|
+
};
|
|
216
|
+
const handlePointerLeave = (e) => {
|
|
217
|
+
if (canUntruncate && prefersHover) setIsHovered(false);
|
|
218
|
+
onPointerLeave?.(e);
|
|
219
|
+
onMouseLeave?.(e);
|
|
220
|
+
};
|
|
221
|
+
const handleUntruncateClick = (e) => {
|
|
222
|
+
if (canUntruncate && !prefersHover) setIsHovered((open) => !open);
|
|
223
|
+
onClick?.(e);
|
|
224
|
+
};
|
|
171
225
|
const handleCopy = (e) => {
|
|
172
226
|
e.stopPropagation();
|
|
173
227
|
navigator.clipboard.writeText(address);
|
|
@@ -183,6 +237,7 @@ function AddressDisplay({ address, truncate = true, startChars = 6, endChars = 4
|
|
|
183
237
|
if (copyTimeoutRef.current) window.clearTimeout(copyTimeoutRef.current);
|
|
184
238
|
};
|
|
185
239
|
}, []);
|
|
240
|
+
const isChip = variant === "chip";
|
|
186
241
|
const actionButtons = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
187
242
|
showCopyButton && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
188
243
|
type: "button",
|
|
@@ -195,6 +250,9 @@ function AddressDisplay({ address, truncate = true, startChars = 6, endChars = 4
|
|
|
195
250
|
href: explorerUrl,
|
|
196
251
|
target: "_blank",
|
|
197
252
|
rel: "noopener noreferrer",
|
|
253
|
+
onClick: (e) => {
|
|
254
|
+
e.stopPropagation();
|
|
255
|
+
},
|
|
198
256
|
className: "ml-1.5 shrink-0 text-slate-500 transition-colors hover:text-slate-700",
|
|
199
257
|
"aria-label": "View in explorer",
|
|
200
258
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ExternalLink, { className: "h-3.5 w-3.5" })
|
|
@@ -210,28 +268,48 @@ function AddressDisplay({ address, truncate = true, startChars = 6, endChars = 4
|
|
|
210
268
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Pencil, { className: "h-3.5 w-3.5" })
|
|
211
269
|
})
|
|
212
270
|
] });
|
|
213
|
-
|
|
214
|
-
|
|
271
|
+
const shouldShowTooltip = showTooltip && truncate;
|
|
272
|
+
const wrapWithTooltip = (content) => {
|
|
273
|
+
if (!shouldShowTooltip) return content;
|
|
274
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipProvider, {
|
|
275
|
+
delayDuration: 300,
|
|
276
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Tooltip, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipTrigger, {
|
|
277
|
+
asChild: true,
|
|
278
|
+
children: content
|
|
279
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipContent, {
|
|
280
|
+
className: "font-mono text-xs",
|
|
281
|
+
children: address
|
|
282
|
+
})] })
|
|
283
|
+
});
|
|
284
|
+
};
|
|
285
|
+
if (resolvedLabel) return wrapWithTooltip(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
286
|
+
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),
|
|
287
|
+
onPointerEnter: handlePointerEnter,
|
|
288
|
+
onPointerLeave: handlePointerLeave,
|
|
289
|
+
onClick: handleUntruncateClick,
|
|
215
290
|
...props,
|
|
216
291
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
217
292
|
className: "truncate font-sans font-medium text-slate-900 leading-snug",
|
|
218
293
|
children: resolvedLabel
|
|
219
294
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
220
|
-
className: "flex items-center font-mono text-[10px] text-slate-400 leading-snug",
|
|
295
|
+
className: "flex min-w-0 items-center font-mono text-[10px] text-slate-400 leading-snug",
|
|
221
296
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
222
|
-
className:
|
|
297
|
+
className: addressTextClassName,
|
|
223
298
|
children: displayAddress
|
|
224
299
|
}), actionButtons]
|
|
225
300
|
})]
|
|
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),
|
|
301
|
+
}));
|
|
302
|
+
return wrapWithTooltip(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
303
|
+
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),
|
|
304
|
+
onPointerEnter: handlePointerEnter,
|
|
305
|
+
onPointerLeave: handlePointerLeave,
|
|
306
|
+
onClick: handleUntruncateClick,
|
|
229
307
|
...props,
|
|
230
308
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
231
|
-
className:
|
|
309
|
+
className: addressTextClassName,
|
|
232
310
|
children: displayAddress
|
|
233
311
|
}), actionButtons]
|
|
234
|
-
});
|
|
312
|
+
}));
|
|
235
313
|
}
|
|
236
314
|
|
|
237
315
|
//#endregion
|
|
@@ -1808,19 +1886,6 @@ const Textarea = react.forwardRef(({ className, ...props }, ref) => {
|
|
|
1808
1886
|
});
|
|
1809
1887
|
Textarea.displayName = "Textarea";
|
|
1810
1888
|
|
|
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
1889
|
//#endregion
|
|
1825
1890
|
//#region src/components/ui/view-contract-state-button.tsx
|
|
1826
1891
|
/**
|