@openzeppelin/ui-components 1.6.0 → 2.0.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/README.md +20 -2
- package/dist/index.cjs +32 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -22
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +19 -16
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +32 -28
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -137,11 +137,29 @@ components/
|
|
|
137
137
|
|
|
138
138
|
Components are styled using Tailwind CSS. The necessary Tailwind configuration is expected to be present in the consuming application. The UI package itself does not bundle CSS but provides the class names and structure.
|
|
139
139
|
|
|
140
|
-
|
|
140
|
+
Important: a bare Tailwind import is not enough for OpenZeppelin packages. Tailwind v4 must be told to scan the relevant `@openzeppelin/*` sources, or some component classes will be omitted from the final CSS.
|
|
141
|
+
|
|
142
|
+
For consumer apps that use `@openzeppelin/ui-dev-cli`, the recommended workflow is:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
pnpm exec oz-ui-dev tailwind doctor --project "$PWD"
|
|
146
|
+
pnpm exec oz-ui-dev tailwind fix --project "$PWD"
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
That creates a managed `oz-tailwind.generated.css` file and keeps the `@source` wiring in sync with your installed dependencies.
|
|
150
|
+
|
|
151
|
+
If you need to configure Tailwind manually, import the shared styles and register the OpenZeppelin package sources explicitly:
|
|
141
152
|
|
|
142
153
|
```css
|
|
154
|
+
@layer base, components, utilities;
|
|
155
|
+
|
|
156
|
+
@import 'tailwindcss' source(none);
|
|
157
|
+
@source "../node_modules/@openzeppelin/ui-components";
|
|
158
|
+
@source "../node_modules/@openzeppelin/ui-react";
|
|
159
|
+
@source "../node_modules/@openzeppelin/ui-renderer";
|
|
160
|
+
@source "../node_modules/@openzeppelin/ui-styles";
|
|
161
|
+
@source "../node_modules/@openzeppelin/ui-utils";
|
|
143
162
|
@import '@openzeppelin/ui-styles/global.css';
|
|
144
|
-
@import 'tailwindcss';
|
|
145
163
|
```
|
|
146
164
|
|
|
147
165
|
## Development
|
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,10 @@ 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 = "2.0.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: {
|
|
@@ -2670,13 +2674,13 @@ const MAX_SUGGESTIONS = 5;
|
|
|
2670
2674
|
* 2. TransactionForm renders the overall form structure with React Hook Form
|
|
2671
2675
|
* 3. DynamicFormField selects the appropriate field component (like AddressField) based on field type
|
|
2672
2676
|
* 4. BaseField provides consistent layout and hook form integration
|
|
2673
|
-
* 5. This component handles blockchain address-specific rendering and validation using the passed
|
|
2677
|
+
* 5. This component handles blockchain address-specific rendering and validation using the passed addressing capability
|
|
2674
2678
|
*
|
|
2675
2679
|
* The component includes:
|
|
2676
2680
|
* - Integration with React Hook Form
|
|
2677
|
-
* - Blockchain address validation through
|
|
2681
|
+
* - Blockchain address validation through the provided addressing capability
|
|
2678
2682
|
* - Automatic error handling and reporting
|
|
2679
|
-
* - Chain-agnostic design (validation handled by
|
|
2683
|
+
* - Chain-agnostic design (validation handled by capabilities)
|
|
2680
2684
|
* - Full accessibility support with ARIA attributes
|
|
2681
2685
|
* - Keyboard navigation
|
|
2682
2686
|
*
|
|
@@ -2691,7 +2695,7 @@ const MAX_SUGGESTIONS = 5;
|
|
|
2691
2695
|
* The suggestion dropdown includes built-in debouncing, keyboard navigation (Arrow keys,
|
|
2692
2696
|
* Enter, Escape), click-outside dismissal, and ARIA listbox semantics.
|
|
2693
2697
|
*/
|
|
2694
|
-
function AddressField({ id, label, placeholder, helperText, control, name, width = "full", validation,
|
|
2698
|
+
function AddressField({ id, label, placeholder, helperText, control, name, width = "full", validation, addressing, readOnly, suggestions: suggestionsProp, onSuggestionSelect }) {
|
|
2695
2699
|
const isRequired = !!validation?.required;
|
|
2696
2700
|
const errorId = `${id}-error`;
|
|
2697
2701
|
const descriptionId = `${id}-description`;
|
|
@@ -2774,8 +2778,8 @@ function AddressField({ id, label, placeholder, helperText, control, name, width
|
|
|
2774
2778
|
if (value === void 0 || value === null || value === "") return validation?.required ? "This field is required" : true;
|
|
2775
2779
|
const standardValidationResult = require_ErrorMessage.validateField(value, validation);
|
|
2776
2780
|
if (standardValidationResult !== true) return standardValidationResult;
|
|
2777
|
-
if (
|
|
2778
|
-
if (!
|
|
2781
|
+
if (addressing && typeof value === "string") {
|
|
2782
|
+
if (!addressing.isValidAddress(value)) return "Invalid address format for the selected chain";
|
|
2779
2783
|
}
|
|
2780
2784
|
return true;
|
|
2781
2785
|
} },
|
|
@@ -3331,7 +3335,7 @@ ArrayField.displayName = "ArrayField";
|
|
|
3331
3335
|
* The component combines the functionality of ArrayField and ObjectField to handle
|
|
3332
3336
|
* complex nested data structures commonly found in blockchain contracts.
|
|
3333
3337
|
*/
|
|
3334
|
-
function ArrayObjectField({ id, label, helperText, control, name, width = "full", validation, components = [], minItems = 0, maxItems, renderProperty, collapsible = true, defaultCollapsed = false, readOnly,
|
|
3338
|
+
function ArrayObjectField({ id, label, helperText, control, name, width = "full", validation, components = [], minItems = 0, maxItems, renderProperty, collapsible = true, defaultCollapsed = false, readOnly, typeMapping, contractSchema }) {
|
|
3335
3339
|
const isRequired = !!validation?.required;
|
|
3336
3340
|
const errorId = `${id}-error`;
|
|
3337
3341
|
const descriptionId = `${id}-description`;
|
|
@@ -3448,8 +3452,8 @@ function ArrayObjectField({ id, label, helperText, control, name, width = "full"
|
|
|
3448
3452
|
}), !isCollapsed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3449
3453
|
className: "space-y-4 mt-4",
|
|
3450
3454
|
children: components.map((component) => {
|
|
3451
|
-
if (!
|
|
3452
|
-
const generatedField =
|
|
3455
|
+
if (!typeMapping) throw new Error(`ArrayObjectField: No typeMapping capability provided for field generation. Cannot generate field for "${component.name}"`);
|
|
3456
|
+
const generatedField = typeMapping.generateDefaultField(component, contractSchema);
|
|
3453
3457
|
const propertyField = {
|
|
3454
3458
|
...generatedField,
|
|
3455
3459
|
id: `${id}-${index}-${component.name}`,
|
|
@@ -5162,7 +5166,7 @@ NumberField.displayName = "NumberField";
|
|
|
5162
5166
|
* The component reuses existing field components for individual properties,
|
|
5163
5167
|
* maintaining consistency across the form system while supporting complex nested structures.
|
|
5164
5168
|
*/
|
|
5165
|
-
function ObjectField({ id, label, helperText, control, name, width = "full", validation, components = [], renderProperty, showCard = true, readOnly,
|
|
5169
|
+
function ObjectField({ id, label, helperText, control, name, width = "full", validation, components = [], renderProperty, showCard = true, readOnly, typeMapping, contractSchema }) {
|
|
5166
5170
|
const isRequired = !!validation?.required;
|
|
5167
5171
|
const errorId = `${id}-error`;
|
|
5168
5172
|
const descriptionId = `${id}-description`;
|
|
@@ -5189,8 +5193,8 @@ function ObjectField({ id, label, helperText, control, name, width = "full", val
|
|
|
5189
5193
|
className: "text-muted-foreground text-sm",
|
|
5190
5194
|
children: "No properties defined for this object"
|
|
5191
5195
|
}) : components.map((component) => {
|
|
5192
|
-
if (!
|
|
5193
|
-
const generatedField =
|
|
5196
|
+
if (!typeMapping) throw new Error(`ObjectField: No typeMapping capability provided for field generation. Cannot generate field for "${component.name}"`);
|
|
5197
|
+
const generatedField = typeMapping.generateDefaultField(component, contractSchema);
|
|
5194
5198
|
const propertyField = {
|
|
5195
5199
|
...generatedField,
|
|
5196
5200
|
id: `${id}-${component.name}`,
|
|
@@ -6212,19 +6216,19 @@ function useNetworkErrors() {
|
|
|
6212
6216
|
return context;
|
|
6213
6217
|
}
|
|
6214
6218
|
/**
|
|
6215
|
-
* Hook for reporting network errors for a specific
|
|
6219
|
+
* Hook for reporting network errors for a specific runtime-bound capability
|
|
6216
6220
|
*/
|
|
6217
|
-
function useNetworkErrorReporter(
|
|
6221
|
+
function useNetworkErrorReporter(capability) {
|
|
6218
6222
|
const { reportNetworkError } = useNetworkErrors();
|
|
6219
6223
|
return {
|
|
6220
6224
|
reportRpcError: (0, react.useCallback)((message) => {
|
|
6221
|
-
if (!
|
|
6222
|
-
reportNetworkError("rpc",
|
|
6223
|
-
}, [
|
|
6225
|
+
if (!capability) return;
|
|
6226
|
+
reportNetworkError("rpc", capability.networkConfig.id, capability.networkConfig.name, message);
|
|
6227
|
+
}, [capability, reportNetworkError]),
|
|
6224
6228
|
reportExplorerError: (0, react.useCallback)((message) => {
|
|
6225
|
-
if (!
|
|
6226
|
-
reportNetworkError("explorer",
|
|
6227
|
-
}, [
|
|
6229
|
+
if (!capability) return;
|
|
6230
|
+
reportNetworkError("explorer", capability.networkConfig.id, capability.networkConfig.name, message);
|
|
6231
|
+
}, [capability, reportNetworkError])
|
|
6228
6232
|
};
|
|
6229
6233
|
}
|
|
6230
6234
|
|
|
@@ -6233,15 +6237,15 @@ function useNetworkErrorReporter(adapter) {
|
|
|
6233
6237
|
/**
|
|
6234
6238
|
* Creates an adapter proxy that intercepts and reports network errors
|
|
6235
6239
|
*/
|
|
6236
|
-
function useNetworkErrorAwareAdapter(
|
|
6240
|
+
function useNetworkErrorAwareAdapter(capability) {
|
|
6237
6241
|
const { reportNetworkError } = useNetworkErrors();
|
|
6238
|
-
const
|
|
6242
|
+
const wrappedCapabilityRef = (0, react.useRef)(null);
|
|
6239
6243
|
(0, react.useEffect)(() => {
|
|
6240
|
-
if (!
|
|
6241
|
-
|
|
6244
|
+
if (!capability) {
|
|
6245
|
+
wrappedCapabilityRef.current = null;
|
|
6242
6246
|
return;
|
|
6243
6247
|
}
|
|
6244
|
-
|
|
6248
|
+
wrappedCapabilityRef.current = new Proxy(capability, { get(target, prop, receiver) {
|
|
6245
6249
|
const value = Reflect.get(target, prop, receiver);
|
|
6246
6250
|
if (typeof value === "function" && (prop === "queryViewFunction" || prop === "loadContract")) return async (...args) => {
|
|
6247
6251
|
try {
|
|
@@ -6255,8 +6259,8 @@ function useNetworkErrorAwareAdapter(adapter) {
|
|
|
6255
6259
|
};
|
|
6256
6260
|
return value;
|
|
6257
6261
|
} });
|
|
6258
|
-
}, [
|
|
6259
|
-
return
|
|
6262
|
+
}, [capability, reportNetworkError]);
|
|
6263
|
+
return wrappedCapabilityRef.current;
|
|
6260
6264
|
}
|
|
6261
6265
|
|
|
6262
6266
|
//#endregion
|
|
@@ -6464,6 +6468,7 @@ exports.TooltipContent = TooltipContent;
|
|
|
6464
6468
|
exports.TooltipProvider = TooltipProvider;
|
|
6465
6469
|
exports.TooltipTrigger = TooltipTrigger;
|
|
6466
6470
|
exports.UrlField = UrlField;
|
|
6471
|
+
exports.VERSION = VERSION;
|
|
6467
6472
|
exports.ViewContractStateButton = ViewContractStateButton;
|
|
6468
6473
|
exports.WizardLayout = WizardLayout;
|
|
6469
6474
|
exports.WizardNavigation = WizardNavigation;
|