@openzeppelin/ui-components 1.7.0 → 2.0.1
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/README.md +20 -2
- package/dist/index.cjs +55 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -15
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +21 -21
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +55 -55
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -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 = "
|
|
29
|
+
const VERSION = "2.0.1";
|
|
30
30
|
|
|
31
31
|
//#endregion
|
|
32
32
|
//#region src/components/ui/accordion.tsx
|
|
@@ -114,7 +114,7 @@ const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
|
114
114
|
const TooltipContent = React$1.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx(TooltipPrimitive.Content, {
|
|
115
115
|
ref,
|
|
116
116
|
sideOffset,
|
|
117
|
-
className: cn("bg-
|
|
117
|
+
className: cn("bg-foreground text-background 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),
|
|
118
118
|
...props
|
|
119
119
|
}) }));
|
|
120
120
|
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
@@ -561,15 +561,15 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }) {
|
|
|
561
561
|
weekdays: "flex",
|
|
562
562
|
weekday: "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
|
|
563
563
|
week: "flex w-full mt-2",
|
|
564
|
-
day: cn("relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-
|
|
564
|
+
day: cn("relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-selected/15 [&:has([aria-selected].day-outside)]:bg-selected/10 [&:has([aria-selected].day-range-end)]:rounded-r-md", props.mode === "range" ? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md" : "[&:has([aria-selected])]:rounded-md"),
|
|
565
565
|
day_button: cn(buttonVariants({ variant: "ghost" }), "h-9 w-9 p-0 font-normal aria-selected:opacity-100 rounded-none hover:rounded-none"),
|
|
566
566
|
range_start: "day-range-start rounded-l-md",
|
|
567
567
|
range_end: "day-range-end rounded-r-md",
|
|
568
|
-
selected: "bg-
|
|
568
|
+
selected: "bg-selected text-selected-foreground hover:bg-selected hover:text-selected-foreground focus:bg-selected focus:text-selected-foreground",
|
|
569
569
|
today: "bg-accent text-accent-foreground",
|
|
570
|
-
outside: "day-outside text-muted-foreground opacity-50 aria-selected:bg-
|
|
570
|
+
outside: "day-outside text-muted-foreground opacity-50 aria-selected:bg-selected/10 aria-selected:text-muted-foreground aria-selected:opacity-30",
|
|
571
571
|
disabled: "text-muted-foreground opacity-50",
|
|
572
|
-
range_middle: "aria-selected:bg-
|
|
572
|
+
range_middle: "aria-selected:bg-selected/15 aria-selected:text-foreground",
|
|
573
573
|
hidden: "invisible",
|
|
574
574
|
...classNames
|
|
575
575
|
},
|
|
@@ -638,7 +638,7 @@ function CardFooter({ className, ...props }) {
|
|
|
638
638
|
function Checkbox({ className, ...props }) {
|
|
639
639
|
return /* @__PURE__ */ jsx(CheckboxPrimitive.Root, {
|
|
640
640
|
"data-slot": "checkbox",
|
|
641
|
-
className: cn("border-input data-[state=checked]:bg-
|
|
641
|
+
className: cn("border-input data-[state=checked]:bg-selected data-[state=checked]:text-selected-foreground data-[state=checked]:border-selected focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50", className),
|
|
642
642
|
...props,
|
|
643
643
|
children: /* @__PURE__ */ jsx(CheckboxPrimitive.Indicator, {
|
|
644
644
|
"data-slot": "checkbox-indicator",
|
|
@@ -1232,7 +1232,7 @@ const Header = ({ title, onOpenSidebar, rightContent }) => {
|
|
|
1232
1232
|
type: "button",
|
|
1233
1233
|
"aria-label": "Open menu",
|
|
1234
1234
|
onClick: onOpenSidebar,
|
|
1235
|
-
className: "mr-2 sm:mr-3 inline-flex items-center justify-center rounded-md p-2 text-
|
|
1235
|
+
className: "mr-2 sm:mr-3 inline-flex items-center justify-center rounded-md p-2 text-foreground hover:bg-muted focus:outline-none focus:ring-2 focus:ring-primary xl:hidden",
|
|
1236
1236
|
children: /* @__PURE__ */ jsx(Menu, { className: "size-5" })
|
|
1237
1237
|
}),
|
|
1238
1238
|
title && /* @__PURE__ */ jsx("div", {
|
|
@@ -1479,7 +1479,7 @@ function NetworkSelector({ networks, getNetworkLabel, getNetworkIcon, getNetwork
|
|
|
1479
1479
|
className: "gap-2",
|
|
1480
1480
|
children: [
|
|
1481
1481
|
isMultiple ? /* @__PURE__ */ jsx("div", {
|
|
1482
|
-
className: "flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border border-
|
|
1482
|
+
className: cn("flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border transition-colors", isSelected(network) ? "border-selected bg-selected text-selected-foreground" : "border-input bg-background"),
|
|
1483
1483
|
children: isSelected(network) && /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" })
|
|
1484
1484
|
}) : null,
|
|
1485
1485
|
getNetworkIcon?.(network),
|
|
@@ -1493,7 +1493,7 @@ function NetworkSelector({ networks, getNetworkLabel, getNetworkIcon, getNetwork
|
|
|
1493
1493
|
children: getNetworkType(network)
|
|
1494
1494
|
})]
|
|
1495
1495
|
}),
|
|
1496
|
-
!isMultiple && isSelected(network) && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 opacity-100" })
|
|
1496
|
+
!isMultiple && isSelected(network) && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-selected opacity-100" })
|
|
1497
1497
|
]
|
|
1498
1498
|
}, getNetworkId(network))) }),
|
|
1499
1499
|
index < Object.keys(groupedNetworks).length - 1 && /* @__PURE__ */ jsx(DropdownMenuSeparator, {})
|
|
@@ -1583,7 +1583,7 @@ RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
|
|
|
1583
1583
|
const RadioGroupItem = React$1.forwardRef(({ className, ...props }, ref) => {
|
|
1584
1584
|
return /* @__PURE__ */ jsx(RadioGroupPrimitive.Item, {
|
|
1585
1585
|
ref,
|
|
1586
|
-
className: cn("border-input bg-background text-
|
|
1586
|
+
className: cn("border-input bg-background text-selected h-4 w-4 rounded-full border shadow-sm focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", className),
|
|
1587
1587
|
...props,
|
|
1588
1588
|
children: /* @__PURE__ */ jsx(RadioGroupPrimitive.Indicator, {
|
|
1589
1589
|
className: "flex items-center justify-center",
|
|
@@ -1675,7 +1675,7 @@ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
|
1675
1675
|
* Can render as a button or anchor element depending on whether href is provided.
|
|
1676
1676
|
*/
|
|
1677
1677
|
function SidebarButton({ icon, children, onClick, size = "default", badge, disabled = false, isSelected = false, href, target, rel, className }) {
|
|
1678
|
-
const commonClass = cn("group relative flex flex-wrap items-center gap-x-2 gap-y-0.5 px-3 py-2 rounded-lg font-semibold text-sm transition-colors", badge ? "justify-between" : "justify-start", disabled ? "text-
|
|
1678
|
+
const commonClass = cn("group relative flex flex-wrap items-center gap-x-2 gap-y-0.5 px-3 py-2 rounded-lg font-semibold text-sm transition-colors", badge ? "justify-between" : "justify-start", disabled ? "text-muted-foreground/60 cursor-not-allowed" : isSelected ? "text-selected bg-selected/10" : "text-muted-foreground hover:text-foreground cursor-pointer hover:before:content-[\"\"] hover:before:absolute hover:before:inset-x-0 hover:before:top-1 hover:before:bottom-1 hover:before:bg-muted/80 hover:before:rounded-lg hover:before:-z-10", size === "small" ? "min-h-10" : "min-h-11", className);
|
|
1679
1679
|
const content = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
1680
1680
|
className: "flex items-center gap-2",
|
|
1681
1681
|
children: [icon, children]
|
|
@@ -1853,7 +1853,7 @@ function TabsList({ className, ...props }) {
|
|
|
1853
1853
|
function TabsTrigger({ className, ...props }) {
|
|
1854
1854
|
return /* @__PURE__ */ jsx(TabsPrimitive.Trigger, {
|
|
1855
1855
|
"data-slot": "tabs-trigger",
|
|
1856
|
-
className: cn("data-[state=active]:bg-background data-[state=active]:text-
|
|
1856
|
+
className: cn("data-[state=active]:bg-background data-[state=active]:text-selected focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring inline-flex flex-1 items-center justify-center gap-1.5 rounded-md px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
|
|
1857
1857
|
...props
|
|
1858
1858
|
});
|
|
1859
1859
|
}
|
|
@@ -1928,7 +1928,7 @@ function canClick(state, freeNavigation = false) {
|
|
|
1928
1928
|
}
|
|
1929
1929
|
function StepCircle({ state, index }) {
|
|
1930
1930
|
return /* @__PURE__ */ jsx("span", {
|
|
1931
|
-
className: cn("flex size-6 shrink-0 items-center justify-center rounded-full text-xs font-semibold transition-all", state === "completed" && "bg-
|
|
1931
|
+
className: cn("flex size-6 shrink-0 items-center justify-center rounded-full text-xs font-semibold transition-all", state === "completed" && "bg-selected text-selected-foreground", state === "current" && "bg-selected text-selected-foreground ring-2 ring-selected/30", state === "visited" && "bg-selected/10 text-selected ring-1 ring-selected/40", state === "invalid" && "bg-destructive/10 text-destructive ring-1 ring-destructive/40", state === "upcoming" && "bg-muted text-muted-foreground"),
|
|
1932
1932
|
children: state === "completed" ? /* @__PURE__ */ jsx(Check, { className: "size-3.5" }) : state === "visited" ? /* @__PURE__ */ jsx(Pencil, { className: "size-3" }) : state === "invalid" ? /* @__PURE__ */ jsx(AlertCircle, { className: "size-3.5" }) : index + 1
|
|
1933
1933
|
});
|
|
1934
1934
|
}
|
|
@@ -1936,10 +1936,10 @@ function StepLabel({ title, state, isSkipped }) {
|
|
|
1936
1936
|
return /* @__PURE__ */ jsxs("div", {
|
|
1937
1937
|
className: "min-w-0 flex-1",
|
|
1938
1938
|
children: [/* @__PURE__ */ jsx("span", {
|
|
1939
|
-
className: cn("text-sm font-medium transition-colors", state === "current" && "text-
|
|
1939
|
+
className: cn("text-sm font-medium transition-colors", state === "current" && "text-selected", state === "completed" && "text-foreground", state === "visited" && "text-selected", state === "invalid" && "text-destructive", state === "upcoming" && "text-muted-foreground"),
|
|
1940
1940
|
children: title
|
|
1941
1941
|
}), isSkipped && /* @__PURE__ */ jsx("span", {
|
|
1942
|
-
className: "mt-0.5 block text-[11px] text-
|
|
1942
|
+
className: "mt-0.5 block text-[11px] text-muted-foreground",
|
|
1943
1943
|
children: "Skipped"
|
|
1944
1944
|
})]
|
|
1945
1945
|
});
|
|
@@ -1947,7 +1947,7 @@ function StepLabel({ title, state, isSkipped }) {
|
|
|
1947
1947
|
function VerticalStepper({ steps, currentStepIndex, furthestStepIndex = currentStepIndex, onStepClick, freeNavigation, className }) {
|
|
1948
1948
|
return /* @__PURE__ */ jsx("nav", {
|
|
1949
1949
|
"aria-label": "Wizard steps",
|
|
1950
|
-
className: cn("rounded-2xl border border-
|
|
1950
|
+
className: cn("rounded-2xl border border-border bg-card p-6", className),
|
|
1951
1951
|
children: /* @__PURE__ */ jsx("div", {
|
|
1952
1952
|
className: "flex flex-col gap-1",
|
|
1953
1953
|
children: steps.map((step, index) => {
|
|
@@ -1957,7 +1957,7 @@ function VerticalStepper({ steps, currentStepIndex, furthestStepIndex = currentS
|
|
|
1957
1957
|
type: "button",
|
|
1958
1958
|
onClick: () => clickable && onStepClick?.(index),
|
|
1959
1959
|
disabled: !clickable,
|
|
1960
|
-
className: cn("flex items-center gap-3 rounded-xl border border-transparent px-3 py-3 text-left transition-all duration-150", clickable ? "cursor-pointer" : "cursor-not-allowed opacity-50", state === "current" && "border-
|
|
1960
|
+
className: cn("flex items-center gap-3 rounded-xl border border-transparent px-3 py-3 text-left transition-all duration-150", clickable ? "cursor-pointer" : "cursor-not-allowed opacity-50", state === "current" && "border-selected/40 bg-selected/5", state === "completed" && "bg-card hover:bg-muted/40", state === "visited" && "bg-card hover:bg-selected/5", state === "invalid" && "border-destructive/40 bg-destructive/5 hover:bg-destructive/10", state === "upcoming" && "bg-card"),
|
|
1961
1961
|
"aria-current": state === "current" ? "step" : void 0,
|
|
1962
1962
|
children: [/* @__PURE__ */ jsx(StepCircle, {
|
|
1963
1963
|
state,
|
|
@@ -1975,7 +1975,7 @@ function VerticalStepper({ steps, currentStepIndex, furthestStepIndex = currentS
|
|
|
1975
1975
|
function HorizontalStepper({ steps, currentStepIndex, furthestStepIndex = currentStepIndex, onStepClick, freeNavigation, className }) {
|
|
1976
1976
|
return /* @__PURE__ */ jsx("nav", {
|
|
1977
1977
|
"aria-label": "Wizard steps",
|
|
1978
|
-
className: cn("rounded-2xl border border-
|
|
1978
|
+
className: cn("rounded-2xl border border-border bg-card p-6", className),
|
|
1979
1979
|
children: /* @__PURE__ */ jsx("div", {
|
|
1980
1980
|
className: "flex w-full items-center",
|
|
1981
1981
|
children: steps.map((step, index) => {
|
|
@@ -1986,7 +1986,7 @@ function HorizontalStepper({ steps, currentStepIndex, furthestStepIndex = curren
|
|
|
1986
1986
|
type: "button",
|
|
1987
1987
|
onClick: () => clickable && onStepClick?.(index),
|
|
1988
1988
|
disabled: !clickable,
|
|
1989
|
-
className: cn("flex items-center gap-2 rounded-xl border border-transparent px-3 py-2 text-left transition-all duration-150", clickable ? "cursor-pointer" : "cursor-not-allowed opacity-50", state === "current" && "border-
|
|
1989
|
+
className: cn("flex items-center gap-2 rounded-xl border border-transparent px-3 py-2 text-left transition-all duration-150", clickable ? "cursor-pointer" : "cursor-not-allowed opacity-50", state === "current" && "border-selected/40 bg-selected/5", state === "completed" && "bg-card hover:bg-muted/40", state === "visited" && "bg-card hover:bg-selected/5", state === "invalid" && "border-destructive/40 bg-destructive/5 hover:bg-destructive/10", state === "upcoming" && "bg-card"),
|
|
1990
1990
|
"aria-current": state === "current" ? "step" : void 0,
|
|
1991
1991
|
"aria-label": `Step ${index + 1}: ${step.title}`,
|
|
1992
1992
|
children: [/* @__PURE__ */ jsx(StepCircle, {
|
|
@@ -2000,7 +2000,7 @@ function HorizontalStepper({ steps, currentStepIndex, furthestStepIndex = curren
|
|
|
2000
2000
|
isSkipped: step.status === "skipped"
|
|
2001
2001
|
})
|
|
2002
2002
|
})]
|
|
2003
|
-
}), !isLast && /* @__PURE__ */ jsx("div", { className: cn("mx-1 h-px flex-1 transition-colors sm:mx-2", index < currentStepIndex ? "bg-
|
|
2003
|
+
}), !isLast && /* @__PURE__ */ jsx("div", { className: cn("mx-1 h-px flex-1 transition-colors sm:mx-2", index < currentStepIndex ? "bg-selected" : "bg-border") })] }, step.id);
|
|
2004
2004
|
})
|
|
2005
2005
|
})
|
|
2006
2006
|
});
|
|
@@ -2662,13 +2662,13 @@ const MAX_SUGGESTIONS = 5;
|
|
|
2662
2662
|
* 2. TransactionForm renders the overall form structure with React Hook Form
|
|
2663
2663
|
* 3. DynamicFormField selects the appropriate field component (like AddressField) based on field type
|
|
2664
2664
|
* 4. BaseField provides consistent layout and hook form integration
|
|
2665
|
-
* 5. This component handles blockchain address-specific rendering and validation using the passed
|
|
2665
|
+
* 5. This component handles blockchain address-specific rendering and validation using the passed addressing capability
|
|
2666
2666
|
*
|
|
2667
2667
|
* The component includes:
|
|
2668
2668
|
* - Integration with React Hook Form
|
|
2669
|
-
* - Blockchain address validation through
|
|
2669
|
+
* - Blockchain address validation through the provided addressing capability
|
|
2670
2670
|
* - Automatic error handling and reporting
|
|
2671
|
-
* - Chain-agnostic design (validation handled by
|
|
2671
|
+
* - Chain-agnostic design (validation handled by capabilities)
|
|
2672
2672
|
* - Full accessibility support with ARIA attributes
|
|
2673
2673
|
* - Keyboard navigation
|
|
2674
2674
|
*
|
|
@@ -2683,7 +2683,7 @@ const MAX_SUGGESTIONS = 5;
|
|
|
2683
2683
|
* The suggestion dropdown includes built-in debouncing, keyboard navigation (Arrow keys,
|
|
2684
2684
|
* Enter, Escape), click-outside dismissal, and ARIA listbox semantics.
|
|
2685
2685
|
*/
|
|
2686
|
-
function AddressField({ id, label, placeholder, helperText, control, name, width = "full", validation,
|
|
2686
|
+
function AddressField({ id, label, placeholder, helperText, control, name, width = "full", validation, addressing, readOnly, suggestions: suggestionsProp, onSuggestionSelect }) {
|
|
2687
2687
|
const isRequired = !!validation?.required;
|
|
2688
2688
|
const errorId = `${id}-error`;
|
|
2689
2689
|
const descriptionId = `${id}-description`;
|
|
@@ -2766,8 +2766,8 @@ function AddressField({ id, label, placeholder, helperText, control, name, width
|
|
|
2766
2766
|
if (value === void 0 || value === null || value === "") return validation?.required ? "This field is required" : true;
|
|
2767
2767
|
const standardValidationResult = validateField(value, validation);
|
|
2768
2768
|
if (standardValidationResult !== true) return standardValidationResult;
|
|
2769
|
-
if (
|
|
2770
|
-
if (!
|
|
2769
|
+
if (addressing && typeof value === "string") {
|
|
2770
|
+
if (!addressing.isValidAddress(value)) return "Invalid address format for the selected chain";
|
|
2771
2771
|
}
|
|
2772
2772
|
return true;
|
|
2773
2773
|
} },
|
|
@@ -2843,7 +2843,7 @@ function AddressField({ id, label, placeholder, helperText, control, name, width
|
|
|
2843
2843
|
type: "button",
|
|
2844
2844
|
role: "option",
|
|
2845
2845
|
"aria-selected": i === highlightedIndex,
|
|
2846
|
-
className: cn("flex w-full flex-col px-3 py-2 text-left text-sm", "hover:bg-
|
|
2846
|
+
className: cn("flex w-full flex-col px-3 py-2 text-left text-sm", "hover:bg-selected/10", i === highlightedIndex && "bg-selected/10"),
|
|
2847
2847
|
onMouseDown: (e) => {
|
|
2848
2848
|
e.preventDefault();
|
|
2849
2849
|
applySuggestion(s);
|
|
@@ -3323,7 +3323,7 @@ ArrayField.displayName = "ArrayField";
|
|
|
3323
3323
|
* The component combines the functionality of ArrayField and ObjectField to handle
|
|
3324
3324
|
* complex nested data structures commonly found in blockchain contracts.
|
|
3325
3325
|
*/
|
|
3326
|
-
function ArrayObjectField({ id, label, helperText, control, name, width = "full", validation, components = [], minItems = 0, maxItems, renderProperty, collapsible = true, defaultCollapsed = false, readOnly,
|
|
3326
|
+
function ArrayObjectField({ id, label, helperText, control, name, width = "full", validation, components = [], minItems = 0, maxItems, renderProperty, collapsible = true, defaultCollapsed = false, readOnly, typeMapping, contractSchema }) {
|
|
3327
3327
|
const isRequired = !!validation?.required;
|
|
3328
3328
|
const errorId = `${id}-error`;
|
|
3329
3329
|
const descriptionId = `${id}-description`;
|
|
@@ -3440,8 +3440,8 @@ function ArrayObjectField({ id, label, helperText, control, name, width = "full"
|
|
|
3440
3440
|
}), !isCollapsed && /* @__PURE__ */ jsx("div", {
|
|
3441
3441
|
className: "space-y-4 mt-4",
|
|
3442
3442
|
children: components.map((component) => {
|
|
3443
|
-
if (!
|
|
3444
|
-
const generatedField =
|
|
3443
|
+
if (!typeMapping) throw new Error(`ArrayObjectField: No typeMapping capability provided for field generation. Cannot generate field for "${component.name}"`);
|
|
3444
|
+
const generatedField = typeMapping.generateDefaultField(component, contractSchema);
|
|
3445
3445
|
const propertyField = {
|
|
3446
3446
|
...generatedField,
|
|
3447
3447
|
id: `${id}-${index}-${component.name}`,
|
|
@@ -4537,15 +4537,15 @@ function FileUploadField({ id, label, placeholder = "Drop your file here or clic
|
|
|
4537
4537
|
},
|
|
4538
4538
|
className: `
|
|
4539
4539
|
relative rounded-lg border-2 border-dashed transition-all duration-200
|
|
4540
|
-
${isDragOver ? "border-
|
|
4540
|
+
${isDragOver ? "border-selected bg-selected/5" : hasError ? "border-destructive bg-destructive/5" : fileName ? "border-border bg-muted/30" : "border-border bg-background hover:border-selected/50 hover:bg-muted/50"}
|
|
4541
4541
|
${readOnly || isProcessing ? "cursor-not-allowed opacity-60" : fileName ? "cursor-default" : "cursor-pointer"}
|
|
4542
4542
|
p-6
|
|
4543
4543
|
`,
|
|
4544
4544
|
children: !fileName ? /* @__PURE__ */ jsxs("div", {
|
|
4545
4545
|
className: "flex flex-col items-center justify-center gap-3 text-center",
|
|
4546
4546
|
children: [/* @__PURE__ */ jsx("div", {
|
|
4547
|
-
className: `rounded-full p-3 transition-colors ${isDragOver ? "bg-
|
|
4548
|
-
children: /* @__PURE__ */ jsx(Upload, { className: `h-8 w-8 transition-colors ${isDragOver ? "text-
|
|
4547
|
+
className: `rounded-full p-3 transition-colors ${isDragOver ? "bg-selected/10" : "bg-muted"}`,
|
|
4548
|
+
children: /* @__PURE__ */ jsx(Upload, { className: `h-8 w-8 transition-colors ${isDragOver ? "text-selected" : "text-muted-foreground"}` })
|
|
4549
4549
|
}), /* @__PURE__ */ jsxs("div", {
|
|
4550
4550
|
className: "space-y-1",
|
|
4551
4551
|
children: [/* @__PURE__ */ jsx("p", {
|
|
@@ -5154,7 +5154,7 @@ NumberField.displayName = "NumberField";
|
|
|
5154
5154
|
* The component reuses existing field components for individual properties,
|
|
5155
5155
|
* maintaining consistency across the form system while supporting complex nested structures.
|
|
5156
5156
|
*/
|
|
5157
|
-
function ObjectField({ id, label, helperText, control, name, width = "full", validation, components = [], renderProperty, showCard = true, readOnly,
|
|
5157
|
+
function ObjectField({ id, label, helperText, control, name, width = "full", validation, components = [], renderProperty, showCard = true, readOnly, typeMapping, contractSchema }) {
|
|
5158
5158
|
const isRequired = !!validation?.required;
|
|
5159
5159
|
const errorId = `${id}-error`;
|
|
5160
5160
|
const descriptionId = `${id}-description`;
|
|
@@ -5181,8 +5181,8 @@ function ObjectField({ id, label, helperText, control, name, width = "full", val
|
|
|
5181
5181
|
className: "text-muted-foreground text-sm",
|
|
5182
5182
|
children: "No properties defined for this object"
|
|
5183
5183
|
}) : components.map((component) => {
|
|
5184
|
-
if (!
|
|
5185
|
-
const generatedField =
|
|
5184
|
+
if (!typeMapping) throw new Error(`ObjectField: No typeMapping capability provided for field generation. Cannot generate field for "${component.name}"`);
|
|
5185
|
+
const generatedField = typeMapping.generateDefaultField(component, contractSchema);
|
|
5186
5186
|
const propertyField = {
|
|
5187
5187
|
...generatedField,
|
|
5188
5188
|
id: `${id}-${component.name}`,
|
|
@@ -5430,7 +5430,7 @@ function RadioField({ id, label, helperText, control, name, width = "full", vali
|
|
|
5430
5430
|
const isDisabled = option.disabled;
|
|
5431
5431
|
return /* @__PURE__ */ jsxs("label", {
|
|
5432
5432
|
htmlFor: optionId,
|
|
5433
|
-
className: `group relative flex cursor-pointer items-center gap-2 rounded-lg px-3 py-2 transition-all duration-150 ${isDisabled ? "cursor-not-allowed opacity-50" : "hover:bg-muted/50"} ${isSelected && !hasError ? "bg-
|
|
5433
|
+
className: `group relative flex cursor-pointer items-center gap-2 rounded-lg px-3 py-2 transition-all duration-150 ${isDisabled ? "cursor-not-allowed opacity-50" : "hover:bg-muted/50"} ${isSelected && !hasError ? "bg-selected/5" : ""}`,
|
|
5434
5434
|
children: [
|
|
5435
5435
|
/* @__PURE__ */ jsx("input", {
|
|
5436
5436
|
type: "radio",
|
|
@@ -5444,13 +5444,13 @@ function RadioField({ id, label, helperText, control, name, width = "full", vali
|
|
|
5444
5444
|
}),
|
|
5445
5445
|
/* @__PURE__ */ jsxs("div", {
|
|
5446
5446
|
className: "relative flex size-4 items-center justify-center",
|
|
5447
|
-
children: [/* @__PURE__ */ jsx("div", { className: `absolute size-4 rounded-full border-2 transition-all duration-150 ${isSelected ? hasError ? "border-destructive bg-destructive/10" : "border-
|
|
5447
|
+
children: [/* @__PURE__ */ jsx("div", { className: `absolute size-4 rounded-full border-2 transition-all duration-150 ${isSelected ? hasError ? "border-destructive bg-destructive/10" : "border-selected bg-selected/10" : hasError ? "border-destructive/50" : "border-muted-foreground/40 group-hover:border-muted-foreground/60"} ${!isDisabled && "group-hover:scale-105"}` }), /* @__PURE__ */ jsx("div", { className: `absolute size-1.5 rounded-full transition-all duration-150 ${isSelected ? hasError ? "bg-destructive scale-100 opacity-100" : "bg-selected scale-100 opacity-100" : "scale-0 opacity-0"}` })]
|
|
5448
5448
|
}),
|
|
5449
5449
|
/* @__PURE__ */ jsx("span", {
|
|
5450
5450
|
className: `text-sm transition-colors duration-150 ${isDisabled ? "text-muted-foreground" : isSelected ? hasError ? "text-destructive font-medium" : "text-foreground font-medium" : "text-foreground"}`,
|
|
5451
5451
|
children: option.label
|
|
5452
5452
|
}),
|
|
5453
|
-
/* @__PURE__ */ jsx("div", { className: `absolute -inset-1 rounded-lg ring-2 ring-
|
|
5453
|
+
/* @__PURE__ */ jsx("div", { className: `absolute -inset-1 rounded-lg ring-2 ring-selected ring-offset-2 ring-offset-background transition-opacity duration-150 ${isSelected && !isDisabled ? "opacity-0 focus-within:opacity-100" : "opacity-0"}` })
|
|
5454
5454
|
]
|
|
5455
5455
|
}, option.value);
|
|
5456
5456
|
})
|
|
@@ -6204,19 +6204,19 @@ function useNetworkErrors() {
|
|
|
6204
6204
|
return context;
|
|
6205
6205
|
}
|
|
6206
6206
|
/**
|
|
6207
|
-
* Hook for reporting network errors for a specific
|
|
6207
|
+
* Hook for reporting network errors for a specific runtime-bound capability
|
|
6208
6208
|
*/
|
|
6209
|
-
function useNetworkErrorReporter(
|
|
6209
|
+
function useNetworkErrorReporter(capability) {
|
|
6210
6210
|
const { reportNetworkError } = useNetworkErrors();
|
|
6211
6211
|
return {
|
|
6212
6212
|
reportRpcError: useCallback((message) => {
|
|
6213
|
-
if (!
|
|
6214
|
-
reportNetworkError("rpc",
|
|
6215
|
-
}, [
|
|
6213
|
+
if (!capability) return;
|
|
6214
|
+
reportNetworkError("rpc", capability.networkConfig.id, capability.networkConfig.name, message);
|
|
6215
|
+
}, [capability, reportNetworkError]),
|
|
6216
6216
|
reportExplorerError: useCallback((message) => {
|
|
6217
|
-
if (!
|
|
6218
|
-
reportNetworkError("explorer",
|
|
6219
|
-
}, [
|
|
6217
|
+
if (!capability) return;
|
|
6218
|
+
reportNetworkError("explorer", capability.networkConfig.id, capability.networkConfig.name, message);
|
|
6219
|
+
}, [capability, reportNetworkError])
|
|
6220
6220
|
};
|
|
6221
6221
|
}
|
|
6222
6222
|
|
|
@@ -6225,15 +6225,15 @@ function useNetworkErrorReporter(adapter) {
|
|
|
6225
6225
|
/**
|
|
6226
6226
|
* Creates an adapter proxy that intercepts and reports network errors
|
|
6227
6227
|
*/
|
|
6228
|
-
function useNetworkErrorAwareAdapter(
|
|
6228
|
+
function useNetworkErrorAwareAdapter(capability) {
|
|
6229
6229
|
const { reportNetworkError } = useNetworkErrors();
|
|
6230
|
-
const
|
|
6230
|
+
const wrappedCapabilityRef = useRef(null);
|
|
6231
6231
|
useEffect(() => {
|
|
6232
|
-
if (!
|
|
6233
|
-
|
|
6232
|
+
if (!capability) {
|
|
6233
|
+
wrappedCapabilityRef.current = null;
|
|
6234
6234
|
return;
|
|
6235
6235
|
}
|
|
6236
|
-
|
|
6236
|
+
wrappedCapabilityRef.current = new Proxy(capability, { get(target, prop, receiver) {
|
|
6237
6237
|
const value = Reflect.get(target, prop, receiver);
|
|
6238
6238
|
if (typeof value === "function" && (prop === "queryViewFunction" || prop === "loadContract")) return async (...args) => {
|
|
6239
6239
|
try {
|
|
@@ -6247,8 +6247,8 @@ function useNetworkErrorAwareAdapter(adapter) {
|
|
|
6247
6247
|
};
|
|
6248
6248
|
return value;
|
|
6249
6249
|
} });
|
|
6250
|
-
}, [
|
|
6251
|
-
return
|
|
6250
|
+
}, [capability, reportNetworkError]);
|
|
6251
|
+
return wrappedCapabilityRef.current;
|
|
6252
6252
|
}
|
|
6253
6253
|
|
|
6254
6254
|
//#endregion
|