From f56eae9f3cbb6507c4bc08b68384438f010ded08 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Tue, 24 Mar 2026 14:38:24 -0700 Subject: [PATCH 01/11] Add a way to infer schema types. --- .../web_core/src/v0_9/catalog/types.test.ts | 42 +++++++++++++++++-- renderers/web_core/src/v0_9/catalog/types.ts | 16 ++++++- 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/renderers/web_core/src/v0_9/catalog/types.test.ts b/renderers/web_core/src/v0_9/catalog/types.test.ts index 0e06fca69..d837960ce 100644 --- a/renderers/web_core/src/v0_9/catalog/types.test.ts +++ b/renderers/web_core/src/v0_9/catalog/types.test.ts @@ -16,16 +16,21 @@ import assert from 'node:assert'; import {describe, it} from 'node:test'; -import {Catalog, ComponentApi, createFunctionImplementation} from './types.js'; +import { + Catalog, + ComponentApi, + InferredComponentApiSchemaType, + createFunctionImplementation, +} from './types.js'; import {A2uiExpressionError} from '../errors.js'; import {z} from 'zod'; describe('Catalog Types', () => { it('creates a catalog with functions', () => { - const mockComponent: ComponentApi = { + const mockComponent = { name: 'MockComp', schema: z.object({}), - }; + } satisfies ComponentApi; const mockFunc = createFunctionImplementation( { @@ -47,6 +52,37 @@ describe('Catalog Types', () => { assert.strictEqual(catalog.functions.get('mockFunc'), mockFunc); }); + it('infers the correct schema type from a ComponentApi', () => { + const mockSchema = z.object({ + field1: z.string(), + field2: z.number().optional(), + }); + + const mockApi: ComponentApi = { + name: 'MockComp', + schema: mockSchema, + }; + + // Type-level assertion: if inferred incorrectly, this would fail compilation + const mockData: InferredComponentApiSchemaType = { + field1: 'test', + field2: 123, + }; + + // Type-level equivalence assertion using z.infer + type ExpectedType = z.infer; + type TypesAreEquivalent = + InferredComponentApiSchemaType extends ExpectedType + ? ExpectedType extends InferredComponentApiSchemaType + ? true + : false + : false; + + // A TypeScript compilation error here means the types do not perfectly align + const typesMatchExact: TypesAreEquivalent = true; + assert.strictEqual(typesMatchExact as boolean, true); + }); + it('throws A2uiExpressionError when function is not found', () => { const catalog = new Catalog('test-cat', []); const ctx = {} as any; diff --git a/renderers/web_core/src/v0_9/catalog/types.ts b/renderers/web_core/src/v0_9/catalog/types.ts index ae24f892d..c4d6a6abf 100644 --- a/renderers/web_core/src/v0_9/catalog/types.ts +++ b/renderers/web_core/src/v0_9/catalog/types.ts @@ -98,8 +98,10 @@ import {FunctionInvoker} from './function_invoker.js'; * A definition of a UI component's API. * This interface defines the contract for a component's capabilities and properties, * independent of any specific rendering implementation. + * + * @template Schema the Zod schema type for the component's properties. */ -export interface ComponentApi { +export interface ComponentApi { /** The name of the component as it appears in the A2UI JSON (e.g., 'Button'). */ name: string; @@ -109,9 +111,19 @@ export interface ComponentApi { * - MUST include catalog-specific common properties (e.g. 'weight', 'accessibility'). * - MUST NOT include 'component' or 'id' as those are handled by the framework/envelope. */ - readonly schema: z.ZodType; + readonly schema: Schema; } +/** + * Infers the schema type from a ComponentApi. + * + * This type uses `z.infer` on the `schema` property of a `ComponentApi` object. + * It is used to access the schema props of a component with type safety. + */ +export type InferredComponentApiSchemaType = z.infer< + Api['schema'] +>; + /** * A collection of available components and functions. */ From 1dc5bd0571c9c498066f90dec34d5d35e58e24e0 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Tue, 24 Mar 2026 15:16:14 -0700 Subject: [PATCH 02/11] Make test detect 'any'. --- .../web_core/src/v0_9/catalog/types.test.ts | 73 +++++++++++-------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/renderers/web_core/src/v0_9/catalog/types.test.ts b/renderers/web_core/src/v0_9/catalog/types.test.ts index d837960ce..aba11fb48 100644 --- a/renderers/web_core/src/v0_9/catalog/types.test.ts +++ b/renderers/web_core/src/v0_9/catalog/types.test.ts @@ -52,37 +52,6 @@ describe('Catalog Types', () => { assert.strictEqual(catalog.functions.get('mockFunc'), mockFunc); }); - it('infers the correct schema type from a ComponentApi', () => { - const mockSchema = z.object({ - field1: z.string(), - field2: z.number().optional(), - }); - - const mockApi: ComponentApi = { - name: 'MockComp', - schema: mockSchema, - }; - - // Type-level assertion: if inferred incorrectly, this would fail compilation - const mockData: InferredComponentApiSchemaType = { - field1: 'test', - field2: 123, - }; - - // Type-level equivalence assertion using z.infer - type ExpectedType = z.infer; - type TypesAreEquivalent = - InferredComponentApiSchemaType extends ExpectedType - ? ExpectedType extends InferredComponentApiSchemaType - ? true - : false - : false; - - // A TypeScript compilation error here means the types do not perfectly align - const typesMatchExact: TypesAreEquivalent = true; - assert.strictEqual(typesMatchExact as boolean, true); - }); - it('throws A2uiExpressionError when function is not found', () => { const catalog = new Catalog('test-cat', []); const ctx = {} as any; @@ -126,3 +95,45 @@ describe('Catalog Types', () => { ); }); }); + +describe('InferredComponentApiSchemaType', () => { + it('infers the correct schema type from a ComponentApi', () => { + const mockSchema = z.object({ + field1: z.string(), + field2: z.number().optional(), + }); + + const mockApi = { + name: 'MockComp', + schema: mockSchema, + } satisfies ComponentApi; + + // Type-level equivalence assertion using z.infer + type ExpectedType = z.infer; + type InferredType = InferredComponentApiSchemaType; + + // Assert `InferredType` is not exactly `any` + type IsAny = 0 extends 1 & T ? true : false; + // inferredIsAny only accepts "true" if `InferredType` is "any". + // This happens when `mockApi: ComponentApi`, but doesn't when + // `mockApi {} satisfies ComponentApi`! + const inferredIsAny: IsAny = false; + assert.strictEqual(inferredIsAny, false); + + // When types are not "any", check that they're the same by checking if they + // extend each other. + type TypesAreEquivalent = + Actual extends Expected + ? Expected extends Actual + ? true + : false + : false; + + // typesMatchExact only accepts "true" if `TypesAreEquivalent` + const typesMatchExact: TypesAreEquivalent = true; + assert.strictEqual(typesMatchExact, true); + + // The asserts in this test should never fail, instead this test should fail + // at compile time if the inference is not correct. + }); +}); From 9a4aeecb322ca004bfb869d65890f4c73438d313 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Tue, 24 Mar 2026 15:25:40 -0700 Subject: [PATCH 03/11] Run npm run fix --- .../web_core/src/v0_9/catalog/types.test.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/renderers/web_core/src/v0_9/catalog/types.test.ts b/renderers/web_core/src/v0_9/catalog/types.test.ts index aba11fb48..f78bd0168 100644 --- a/renderers/web_core/src/v0_9/catalog/types.test.ts +++ b/renderers/web_core/src/v0_9/catalog/types.test.ts @@ -107,6 +107,8 @@ describe('InferredComponentApiSchemaType', () => { name: 'MockComp', schema: mockSchema, } satisfies ComponentApi; + // Appease typescript-eslint/no-unused-vars + assert.strictEqual(mockApi.name, 'MockComp'); // Type-level equivalence assertion using z.infer type ExpectedType = z.infer; @@ -122,15 +124,15 @@ describe('InferredComponentApiSchemaType', () => { // When types are not "any", check that they're the same by checking if they // extend each other. - type TypesAreEquivalent = - Actual extends Expected - ? Expected extends Actual - ? true - : false - : false; + type TypesAreEquivalent = Actual extends Expected + ? Expected extends Actual + ? true + : false + : false; // typesMatchExact only accepts "true" if `TypesAreEquivalent` - const typesMatchExact: TypesAreEquivalent = true; + const typesMatchExact: TypesAreEquivalent = + true; assert.strictEqual(typesMatchExact, true); // The asserts in this test should never fail, instead this test should fail From 59a75a4554f713962a5288c59e45c8a3cb8a161b Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Tue, 24 Mar 2026 15:29:32 -0700 Subject: [PATCH 04/11] Update CHANGELOG and package version. --- renderers/web_core/CHANGELOG.md | 9 +++++++++ renderers/web_core/package.json | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/renderers/web_core/CHANGELOG.md b/renderers/web_core/CHANGELOG.md index 10a6f2cac..e37e86ced 100644 --- a/renderers/web_core/CHANGELOG.md +++ b/renderers/web_core/CHANGELOG.md @@ -1,3 +1,12 @@ +## 0.8.8 + +- Add the ability to access the `schema` of a component in a type-safe way. + - Update `ComponentApi` object to be generic over its `schema` type. + - Modify the basic component definitions to `satisfies ComponentApi` instead + of `: ComponentApi` so their schema type can be inferred later. + - Add an `InferredComponentApiSchemaType` type to extract the schema type + from a `ComponentApi` object. + ## 0.8.7 - Adds `catalogId` to v0.8 schemas (was removed by mistake earlier) diff --git a/renderers/web_core/package.json b/renderers/web_core/package.json index 0a9785aeb..08630c723 100644 --- a/renderers/web_core/package.json +++ b/renderers/web_core/package.json @@ -1,6 +1,6 @@ { "name": "@a2ui/web_core", - "version": "0.8.7", + "version": "0.8.8", "description": "A2UI Core Library", "main": "./dist/src/v0_8/index.js", "types": "./dist/src/v0_8/index.d.ts", From 4e43c823207862c69ff60fe8ce6db2c4135c3e23 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Tue, 24 Mar 2026 15:36:47 -0700 Subject: [PATCH 05/11] Update basic_catalog components to satisfies ComponentApi --- .../components/basic_components.ts | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts b/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts index a2afef8d6..2eae8bfdc 100644 --- a/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts +++ b/renderers/web_core/src/v0_9/basic_catalog/components/basic_components.ts @@ -38,7 +38,7 @@ const CommonProps = { .optional(), }; -export const TextApi: ComponentApi = { +export const TextApi = { name: 'Text', schema: z .object({ @@ -53,9 +53,9 @@ export const TextApi: ComponentApi = { .optional(), }) .strict(), -}; +} satisfies ComponentApi; -export const ImageApi: ComponentApi = { +export const ImageApi = { name: 'Image', schema: z .object({ @@ -82,7 +82,7 @@ export const ImageApi: ComponentApi = { .optional(), }) .strict(), -}; +} satisfies ComponentApi; const ICON_NAMES = [ 'accountCircle', @@ -146,7 +146,7 @@ const ICON_NAMES = [ 'warning', ] as const; -export const IconApi: ComponentApi = { +export const IconApi = { name: 'Icon', schema: z .object({ @@ -163,9 +163,9 @@ export const IconApi: ComponentApi = { .describe('The name of the icon to display.'), }) .strict(), -}; +} satisfies ComponentApi; -export const VideoApi: ComponentApi = { +export const VideoApi = { name: 'Video', schema: z .object({ @@ -173,9 +173,9 @@ export const VideoApi: ComponentApi = { url: DynamicStringSchema.describe('The URL of the video to display.'), }) .strict(), -}; +} satisfies ComponentApi; -export const AudioPlayerApi: ComponentApi = { +export const AudioPlayerApi = { name: 'AudioPlayer', schema: z .object({ @@ -186,9 +186,9 @@ export const AudioPlayerApi: ComponentApi = { ).optional(), }) .strict(), -}; +} satisfies ComponentApi; -export const RowApi: ComponentApi = { +export const RowApi = { name: 'Row', schema: z .object({ @@ -223,9 +223,9 @@ export const RowApi: ComponentApi = { .describe( 'A layout component that arranges its children horizontally. To create a grid layout, nest Columns within this Row.', ), -}; +} satisfies ComponentApi; -export const ColumnApi: ComponentApi = { +export const ColumnApi = { name: 'Column', schema: z .object({ @@ -260,9 +260,9 @@ export const ColumnApi: ComponentApi = { .describe( 'A layout component that arranges its children vertically. To create a grid layout, nest Rows within this Column.', ), -}; +} satisfies ComponentApi; -export const ListApi: ComponentApi = { +export const ListApi = { name: 'List', schema: z .object({ @@ -282,9 +282,9 @@ export const ListApi: ComponentApi = { .optional(), }) .strict(), -}; +} satisfies ComponentApi; -export const CardApi: ComponentApi = { +export const CardApi = { name: 'Card', schema: z .object({ @@ -294,9 +294,9 @@ export const CardApi: ComponentApi = { ), }) .strict(), -}; +} satisfies ComponentApi; -export const TabsApi: ComponentApi = { +export const TabsApi = { name: 'Tabs', schema: z .object({ @@ -318,9 +318,9 @@ export const TabsApi: ComponentApi = { ), }) .strict(), -}; +} satisfies ComponentApi; -export const ModalApi: ComponentApi = { +export const ModalApi = { name: 'Modal', schema: z .object({ @@ -333,9 +333,9 @@ export const ModalApi: ComponentApi = { ), }) .strict(), -}; +} satisfies ComponentApi; -export const DividerApi: ComponentApi = { +export const DividerApi = { name: 'Divider', schema: z .object({ @@ -347,9 +347,9 @@ export const DividerApi: ComponentApi = { .optional(), }) .strict(), -}; +} satisfies ComponentApi; -export const ButtonApi: ComponentApi = { +export const ButtonApi = { name: 'Button', schema: z .object({ @@ -368,9 +368,9 @@ export const ButtonApi: ComponentApi = { checks: CheckableSchema.shape.checks, }) .strict(), -}; +} satisfies ComponentApi; -export const TextFieldApi: ComponentApi = { +export const TextFieldApi = { name: 'TextField', schema: z .object({ @@ -395,9 +395,9 @@ export const TextFieldApi: ComponentApi = { checks: CheckableSchema.shape.checks, }) .strict(), -}; +} satisfies ComponentApi; -export const CheckBoxApi: ComponentApi = { +export const CheckBoxApi = { name: 'CheckBox', schema: z .object({ @@ -411,9 +411,9 @@ export const CheckBoxApi: ComponentApi = { checks: CheckableSchema.shape.checks, }) .strict(), -}; +} satisfies ComponentApi; -export const ChoicePickerApi: ComponentApi = { +export const ChoicePickerApi = { name: 'ChoicePicker', schema: z .object({ @@ -461,9 +461,9 @@ export const ChoicePickerApi: ComponentApi = { .describe( 'A component that allows selecting one or more options from a list.', ), -}; +} satisfies ComponentApi; -export const SliderApi: ComponentApi = { +export const SliderApi = { name: 'Slider', schema: z .object({ @@ -481,9 +481,9 @@ export const SliderApi: ComponentApi = { checks: CheckableSchema.shape.checks, }) .strict(), -}; +} satisfies ComponentApi; -export const DateTimeInputApi: ComponentApi = { +export const DateTimeInputApi = { name: 'DateTimeInput', schema: z .object({ @@ -525,7 +525,7 @@ export const DateTimeInputApi: ComponentApi = { checks: CheckableSchema.shape.checks, }) .strict(), -}; +} satisfies ComponentApi; export const BASIC_COMPONENTS: ComponentApi[] = [ TextApi, From 513ffc00294d3bfe46c4c0940e431b0f55f20047 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Tue, 24 Mar 2026 18:42:14 -0700 Subject: [PATCH 06/11] Use InferredComponentApiSchema in createReactComponent. Adjust Tabs props type. --- renderers/react/package-lock.json | 118 +----------------- renderers/react/src/v0_9/adapter.tsx | 10 +- .../v0_9/catalog/basic/components/Tabs.tsx | 6 +- 3 files changed, 12 insertions(+), 122 deletions(-) diff --git a/renderers/react/package-lock.json b/renderers/react/package-lock.json index fad1480eb..8cb4fa44b 100644 --- a/renderers/react/package-lock.json +++ b/renderers/react/package-lock.json @@ -74,7 +74,7 @@ }, "../web_core": { "name": "@a2ui/web_core", - "version": "0.8.7", + "version": "0.8.8", "license": "Apache-2.0", "dependencies": { "@preact/signals-core": "^1.13.0", @@ -85,6 +85,7 @@ "devDependencies": { "@types/node": "^24.11.0", "c8": "^11.0.0", + "gts": "^7.0.0", "typescript": "^5.8.3", "wireit": "^0.15.0-pre.2" } @@ -139,7 +140,6 @@ }, "node_modules/@babel/code-frame": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", "dev": true, "license": "MIT", @@ -154,7 +154,6 @@ }, "node_modules/@babel/compat-data": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", "dev": true, "license": "MIT", @@ -164,7 +163,6 @@ }, "node_modules/@babel/core": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", @@ -195,7 +193,6 @@ }, "node_modules/@babel/generator": { "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", "dev": true, "license": "MIT", @@ -212,7 +209,6 @@ }, "node_modules/@babel/helper-compilation-targets": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", "dev": true, "license": "MIT", @@ -229,7 +225,6 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "license": "ISC", @@ -239,14 +234,12 @@ }, "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" }, "node_modules/@babel/helper-globals": { "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, "license": "MIT", @@ -256,7 +249,6 @@ }, "node_modules/@babel/helper-module-imports": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", "dev": true, "license": "MIT", @@ -270,7 +262,6 @@ }, "node_modules/@babel/helper-module-transforms": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", "dev": true, "license": "MIT", @@ -288,7 +279,6 @@ }, "node_modules/@babel/helper-plugin-utils": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", "dev": true, "license": "MIT", @@ -298,7 +288,6 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "license": "MIT", @@ -317,7 +306,6 @@ }, "node_modules/@babel/helper-validator-option": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "license": "MIT", @@ -327,7 +315,6 @@ }, "node_modules/@babel/helpers": { "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "dev": true, "license": "MIT", @@ -341,7 +328,6 @@ }, "node_modules/@babel/parser": { "version": "7.29.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "dev": true, "license": "MIT", @@ -357,7 +343,6 @@ }, "node_modules/@babel/plugin-transform-react-jsx-self": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dev": true, "license": "MIT", @@ -373,7 +358,6 @@ }, "node_modules/@babel/plugin-transform-react-jsx-source": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dev": true, "license": "MIT", @@ -398,7 +382,6 @@ }, "node_modules/@babel/template": { "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "dev": true, "license": "MIT", @@ -413,7 +396,6 @@ }, "node_modules/@babel/traverse": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", "dev": true, "license": "MIT", @@ -432,7 +414,6 @@ }, "node_modules/@babel/types": { "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "dev": true, "license": "MIT", @@ -1088,7 +1069,6 @@ }, "node_modules/@eslint/eslintrc/node_modules/globals": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", "dev": true, "license": "MIT", @@ -1210,7 +1190,6 @@ }, "node_modules/@jridgewell/remapping": { "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", @@ -1258,7 +1237,6 @@ }, "node_modules/@puppeteer/browsers": { "version": "2.13.0", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.13.0.tgz", "integrity": "sha512-46BZJYJjc/WwmKjsvDFykHtXrtomsCIrwYQPOP7VfMJoZY2bsDF9oROBABR3paDjDcmkUye1Pb1BqdcdiipaWA==", "dev": true, "license": "Apache-2.0", @@ -1280,7 +1258,6 @@ }, "node_modules/@puppeteer/browsers/node_modules/semver": { "version": "7.7.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", @@ -1293,7 +1270,6 @@ }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-rc.3", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", "dev": true, "license": "MIT" @@ -1703,7 +1679,6 @@ }, "node_modules/@tootallnate/quickjs-emscripten": { "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", "dev": true, "license": "MIT" @@ -1717,7 +1692,6 @@ }, "node_modules/@types/babel__core": { "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "license": "MIT", @@ -1731,7 +1705,6 @@ }, "node_modules/@types/babel__generator": { "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, "license": "MIT", @@ -1741,7 +1714,6 @@ }, "node_modules/@types/babel__template": { "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", "dev": true, "license": "MIT", @@ -1752,7 +1724,6 @@ }, "node_modules/@types/babel__traverse": { "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", "dev": true, "license": "MIT", @@ -1818,7 +1789,6 @@ }, "node_modules/@types/node": { "version": "24.12.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz", "integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==", "dev": true, "license": "MIT", @@ -1859,7 +1829,6 @@ }, "node_modules/@types/yauzl": { "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", "dev": true, "license": "MIT", @@ -2125,7 +2094,6 @@ }, "node_modules/@vitejs/plugin-react": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", "dev": true, "license": "MIT", @@ -2502,7 +2470,6 @@ }, "node_modules/ast-types": { "version": "0.13.4", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", "dev": true, "license": "MIT", @@ -2545,7 +2512,6 @@ }, "node_modules/bare-events": { "version": "2.8.2", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", "dev": true, "license": "Apache-2.0", @@ -2560,7 +2526,6 @@ }, "node_modules/bare-fs": { "version": "4.5.6", - "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.5.6.tgz", "integrity": "sha512-1QovqDrR80Pmt5HPAsMsXTCFcDYr+NSUKW6nd6WO5v0JBmnItc/irNRzm2KOQ5oZ69P37y+AMujNyNtG+1Rggw==", "dev": true, "license": "Apache-2.0", @@ -2585,7 +2550,6 @@ }, "node_modules/bare-os": { "version": "3.8.0", - "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-3.8.0.tgz", "integrity": "sha512-Dc9/SlwfxkXIGYhvMQNUtKaXCaGkZYGcd1vuNUUADVqzu4/vQfvnMkYYOUnt2VwQ2AqKr/8qAVFRtwETljgeFg==", "dev": true, "license": "Apache-2.0", @@ -2595,7 +2559,6 @@ }, "node_modules/bare-path": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-3.0.0.tgz", "integrity": "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==", "dev": true, "license": "Apache-2.0", @@ -2605,7 +2568,6 @@ }, "node_modules/bare-stream": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.10.0.tgz", "integrity": "sha512-DOPZF/DDcDruKDA43cOw6e9Quq5daua7ygcAwJE/pKJsRWhgSSemi7qVNGE5kyDIxIeN1533G/zfbvWX7Wcb9w==", "dev": true, "license": "Apache-2.0", @@ -2628,7 +2590,6 @@ }, "node_modules/bare-url": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.4.0.tgz", "integrity": "sha512-NSTU5WN+fy/L0DDenfE8SXQna4voXuW0FHM7wH8i3/q9khUSchfPbPezO4zSFMnDGIf9YE+mt/RWhZgNRKRIXA==", "dev": true, "license": "Apache-2.0", @@ -2638,7 +2599,6 @@ }, "node_modules/baseline-browser-mapping": { "version": "2.10.9", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.9.tgz", "integrity": "sha512-OZd0e2mU11ClX8+IdXe3r0dbqMEznRiT4TfbhYIbcRPZkqJ7Qwer8ij3GZAmLsRKa+II9V1v5czCkvmHH3XZBg==", "dev": true, "license": "Apache-2.0", @@ -2651,7 +2611,6 @@ }, "node_modules/basic-ftp": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.0.tgz", "integrity": "sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==", "dev": true, "license": "MIT", @@ -2680,7 +2639,6 @@ }, "node_modules/browserslist": { "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ @@ -2714,7 +2672,6 @@ }, "node_modules/buffer-crc32": { "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true, "license": "MIT", @@ -2830,7 +2787,6 @@ }, "node_modules/caniuse-lite": { "version": "1.0.30001780", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001780.tgz", "integrity": "sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==", "dev": true, "funding": [ @@ -2912,7 +2868,6 @@ }, "node_modules/chromium-bidi": { "version": "14.0.0", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-14.0.0.tgz", "integrity": "sha512-9gYlLtS6tStdRWzrtXaTMnqcM4dudNegMXJxkR0I/CXObHalYeYcAMPrL19eroNZHtJ8DQmu1E+ZNOYu/IXMXw==", "dev": true, "license": "Apache-2.0", @@ -2947,7 +2902,6 @@ }, "node_modules/cliui": { "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "license": "ISC", @@ -3018,14 +2972,12 @@ }, "node_modules/convert-source-map": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/cosmiconfig": { "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", "dev": true, "license": "MIT", @@ -3106,7 +3058,6 @@ }, "node_modules/data-uri-to-buffer": { "version": "6.0.2", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", "dev": true, "license": "MIT", @@ -3277,7 +3228,6 @@ }, "node_modules/degenerator": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", "dev": true, "license": "MIT", @@ -3301,7 +3251,6 @@ }, "node_modules/devtools-protocol": { "version": "0.0.1581282", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1581282.tgz", "integrity": "sha512-nv7iKtNZQshSW2hKzYNr46nM/Cfh5SEvE2oV0/SEGgc9XupIY5ggf84Cz8eJIkBce7S3bmTAauFD6aysMpnqsQ==", "dev": true, "license": "BSD-3-Clause" @@ -3341,7 +3290,6 @@ }, "node_modules/electron-to-chromium": { "version": "1.5.321", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.321.tgz", "integrity": "sha512-L2C7Q279W2D/J4PLZLk7sebOILDSWos7bMsMNN06rK482umHUrh/3lM8G7IlHFOYip2oAg5nha1rCMxr/rs6ZQ==", "dev": true, "license": "ISC" @@ -3354,7 +3302,6 @@ }, "node_modules/end-of-stream": { "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "dev": true, "license": "MIT", @@ -3388,7 +3335,6 @@ }, "node_modules/env-paths": { "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "license": "MIT", @@ -3623,7 +3569,6 @@ }, "node_modules/escalade": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", @@ -3645,7 +3590,6 @@ }, "node_modules/escodegen": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", "dev": true, "license": "BSD-2-Clause", @@ -3667,7 +3611,6 @@ }, "node_modules/escodegen/node_modules/source-map": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", @@ -3924,7 +3867,6 @@ }, "node_modules/eslint-plugin-react-refresh": { "version": "0.4.26", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz", "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==", "dev": true, "license": "MIT", @@ -3979,7 +3921,6 @@ }, "node_modules/esprima": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, "license": "BSD-2-Clause", @@ -4044,7 +3985,6 @@ }, "node_modules/events-universal": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", "dev": true, "license": "Apache-2.0", @@ -4100,7 +4040,6 @@ }, "node_modules/extract-zip": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", "dev": true, "license": "BSD-2-Clause", @@ -4121,7 +4060,6 @@ }, "node_modules/extract-zip/node_modules/get-stream": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "license": "MIT", @@ -4149,7 +4087,6 @@ }, "node_modules/fast-fifo": { "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", "dev": true, "license": "MIT" @@ -4168,7 +4105,6 @@ }, "node_modules/fd-slicer": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "license": "MIT", @@ -4353,7 +4289,6 @@ }, "node_modules/gensync": { "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "license": "MIT", @@ -4363,7 +4298,6 @@ }, "node_modules/get-caller-file": { "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "license": "ISC", @@ -4451,7 +4385,6 @@ }, "node_modules/get-uri": { "version": "6.0.5", - "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", "dev": true, "license": "MIT", @@ -4478,7 +4411,6 @@ }, "node_modules/globals": { "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", "dev": true, "license": "MIT", @@ -4819,7 +4751,6 @@ }, "node_modules/inquirer/node_modules/rxjs": { "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", "dev": true, "license": "Apache-2.0", @@ -4832,7 +4763,6 @@ }, "node_modules/inquirer/node_modules/tslib": { "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true, "license": "0BSD" @@ -4853,7 +4783,6 @@ }, "node_modules/ip-address": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz", "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", "dev": true, "license": "MIT", @@ -5358,7 +5287,6 @@ }, "node_modules/jsesc": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", @@ -5691,7 +5619,6 @@ }, "node_modules/mitt": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "dev": true, "license": "MIT" @@ -5766,7 +5693,6 @@ }, "node_modules/netmask": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", "dev": true, "license": "MIT", @@ -5776,7 +5702,6 @@ }, "node_modules/node-releases": { "version": "2.0.36", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", "dev": true, "license": "MIT" @@ -5933,7 +5858,6 @@ }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "license": "ISC", @@ -6040,7 +5964,6 @@ }, "node_modules/pac-proxy-agent": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", "dev": true, "license": "MIT", @@ -6060,7 +5983,6 @@ }, "node_modules/pac-resolver": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", "dev": true, "license": "MIT", @@ -6158,7 +6080,6 @@ }, "node_modules/pend": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true, "license": "MIT" @@ -6333,7 +6254,6 @@ }, "node_modules/progress": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true, "license": "MIT", @@ -6360,7 +6280,6 @@ }, "node_modules/proxy-agent": { "version": "6.5.0", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", "dev": true, "license": "MIT", @@ -6380,7 +6299,6 @@ }, "node_modules/proxy-agent/node_modules/lru-cache": { "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "license": "ISC", @@ -6390,14 +6308,12 @@ }, "node_modules/proxy-from-env": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true, "license": "MIT" }, "node_modules/pump": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", "dev": true, "license": "MIT", @@ -6425,7 +6341,6 @@ }, "node_modules/puppeteer": { "version": "24.40.0", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-24.40.0.tgz", "integrity": "sha512-IxQbDq93XHVVLWHrAkFP7F7iHvb9o0mgfsSIMlhHb+JM+JjM1V4v4MNSQfcRWJopx9dsNOr9adYv0U5fm9BJBQ==", "dev": true, "hasInstallScript": true, @@ -6447,7 +6362,6 @@ }, "node_modules/puppeteer-core": { "version": "24.40.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-24.40.0.tgz", "integrity": "sha512-MWL3XbUCfVgGR0gRsidzT6oKJT2QydPLhMITU6HoVWiiv4gkb6gJi3pcdAa8q4HwjBTbqISOWVP4aJiiyUJvag==", "dev": true, "license": "Apache-2.0", @@ -6507,7 +6421,6 @@ }, "node_modules/react-refresh": { "version": "0.18.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", "dev": true, "license": "MIT", @@ -6734,7 +6647,6 @@ }, "node_modules/require-directory": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "license": "MIT", @@ -6854,7 +6766,6 @@ }, "node_modules/rxjs": { "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", "dependencies": { @@ -7102,7 +7013,6 @@ }, "node_modules/smart-buffer": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, "license": "MIT", @@ -7113,7 +7023,6 @@ }, "node_modules/socks": { "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", "dev": true, "license": "MIT", @@ -7128,7 +7037,6 @@ }, "node_modules/socks-proxy-agent": { "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", "dev": true, "license": "MIT", @@ -7218,7 +7126,6 @@ }, "node_modules/streamx": { "version": "2.25.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz", "integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==", "dev": true, "license": "MIT", @@ -7462,7 +7369,6 @@ }, "node_modules/tar-fs": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.2.tgz", "integrity": "sha512-QGxxTxxyleAdyM3kpFs14ymbYmNFrfY+pHj7Z8FgtbZ7w2//VAgLMac7sT6nRpIHjppXO2AwwEOg0bPFVRcmXw==", "dev": true, "license": "MIT", @@ -7477,7 +7383,6 @@ }, "node_modules/tar-stream": { "version": "3.1.8", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.8.tgz", "integrity": "sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ==", "dev": true, "license": "MIT", @@ -7490,7 +7395,6 @@ }, "node_modules/tar-stream/node_modules/b4a": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz", "integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==", "dev": true, "license": "Apache-2.0", @@ -7505,7 +7409,6 @@ }, "node_modules/teex": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", "dev": true, "license": "MIT", @@ -7515,7 +7418,6 @@ }, "node_modules/text-decoder": { "version": "1.2.7", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", "dev": true, "license": "Apache-2.0", @@ -7525,7 +7427,6 @@ }, "node_modules/text-decoder/node_modules/b4a": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz", "integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==", "dev": true, "license": "Apache-2.0", @@ -7716,7 +7617,6 @@ }, "node_modules/tslib": { "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, @@ -7774,7 +7674,6 @@ }, "node_modules/tsx": { "version": "4.21.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", "dev": true, "license": "MIT", @@ -7892,7 +7791,6 @@ }, "node_modules/typed-query-selector": { "version": "2.12.1", - "resolved": "https://registry.npmjs.org/typed-query-selector/-/typed-query-selector-2.12.1.tgz", "integrity": "sha512-uzR+FzI8qrUEIu96oaeBJmd9E7CFEiQ3goA5qCVgc4s5llSubcfGHq9yUstZx/k4s9dXHVKsE35YWoFyvEqEHA==", "dev": true, "license": "MIT" @@ -7973,14 +7871,12 @@ }, "node_modules/undici-types": { "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", "dev": true, "license": "MIT" }, "node_modules/update-browserslist-db": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ @@ -8202,7 +8098,6 @@ }, "node_modules/webdriver-bidi-protocol": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.1.tgz", "integrity": "sha512-ARrjNjtWRRs2w4Tk7nqrf2gBI0QXWuOmMCx2hU+1jUt6d00MjMxURrhxhGbrsoiZKJrhTSTzbIrc554iKI10qw==", "dev": true, "license": "Apache-2.0" @@ -8366,7 +8261,6 @@ }, "node_modules/wrap-ansi": { "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", @@ -8384,7 +8278,6 @@ }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", @@ -8400,7 +8293,6 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, "license": "ISC" @@ -8432,7 +8324,6 @@ }, "node_modules/ws": { "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "dev": true, "license": "MIT", @@ -8469,7 +8360,6 @@ }, "node_modules/y18n": { "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "license": "ISC", @@ -8485,7 +8375,6 @@ }, "node_modules/yargs": { "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "license": "MIT", @@ -8513,7 +8402,6 @@ }, "node_modules/yargs/node_modules/yargs-parser": { "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "license": "ISC", @@ -8523,7 +8411,6 @@ }, "node_modules/yauzl": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, "license": "MIT", @@ -8546,7 +8433,6 @@ }, "node_modules/zod": { "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", "funding": { diff --git a/renderers/react/src/v0_9/adapter.tsx b/renderers/react/src/v0_9/adapter.tsx index 969235b25..4ec95fde2 100644 --- a/renderers/react/src/v0_9/adapter.tsx +++ b/renderers/react/src/v0_9/adapter.tsx @@ -17,7 +17,7 @@ import React, {useRef, useSyncExternalStore, useCallback, memo, useEffect} from 'react'; import {type z} from 'zod'; import {type ComponentContext, GenericBinder} from '@a2ui/web_core/v0_9'; -import type {ComponentApi, ResolveA2uiProps} from '@a2ui/web_core/v0_9'; +import type {ComponentApi, InferredComponentApiSchemaType, ResolveA2uiProps} from '@a2ui/web_core/v0_9'; export interface ReactComponentImplementation extends ComponentApi { /** The framework-specific rendering wrapper. */ @@ -38,11 +38,11 @@ export type ReactA2uiComponentProps = { /** * Creates a React component implementation using the deep generic binder. */ -export function createReactComponent( - api: {name: string; schema: Schema}, - RenderComponent: React.FC>>> +export function createReactComponent( + api: Api, + RenderComponent: React.FC>>> ): ReactComponentImplementation { - type Props = ResolveA2uiProps>; + type Props = ResolveA2uiProps>; const MemoizedRender = memo(RenderComponent, (prev, next) => { if (prev.props !== next.props) return false; diff --git a/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx b/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx index 47e45f375..2e43df2d6 100644 --- a/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx +++ b/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx @@ -19,6 +19,10 @@ import {createReactComponent} from '../../../adapter'; import {TabsApi} from '@a2ui/web_core/v0_9/basic_catalog'; import {LEAF_MARGIN} from '../utils'; +// It seems that individual tabs don't have their type inferred, so we use a +// helper type here. +type _Tab = {title: string, child: string} + export const Tabs = createReactComponent(TabsApi, ({props, buildChild}) => { const [selectedIndex, setSelectedIndex] = useState(0); @@ -28,7 +32,7 @@ export const Tabs = createReactComponent(TabsApi, ({props, buildChild}) => { return (
- {tabs.map((tab: {title: string; child: string}, i: number) => ( + {tabs.map((tab: _Tab, i: number) => (
{hasError && ( - {props.validationErrors[0]} + {props.validationErrors?.[0]} )}
diff --git a/renderers/react/src/v0_9/catalog/basic/components/ChoicePicker.tsx b/renderers/react/src/v0_9/catalog/basic/components/ChoicePicker.tsx index cde5a4bdf..83d2943b9 100644 --- a/renderers/react/src/v0_9/catalog/basic/components/ChoicePicker.tsx +++ b/renderers/react/src/v0_9/catalog/basic/components/ChoicePicker.tsx @@ -37,8 +37,8 @@ export const ChoicePicker = createReactComponent(ChoicePickerApi, ({props, conte }; const options = (props.options || []).filter( - (opt: {label: string; value: string}) => - !props.filterable || filter === '' || opt.label.toLowerCase().includes(filter.toLowerCase()) + (opt: any) => + !props.filterable || filter === '' || String(opt.label).toLowerCase().includes(filter.toLowerCase()) ); const containerStyle: React.CSSProperties = { @@ -69,7 +69,7 @@ export const ChoicePicker = createReactComponent(ChoicePickerApi, ({props, conte /> )}
- {options.map((opt: {label: string; value: string}, i: number) => { + {options.map((opt: any, i: number) => { const isSelected = values.includes(opt.value); if (props.displayStyle === 'chips') { return ( @@ -88,7 +88,7 @@ export const ChoicePicker = createReactComponent(ChoicePickerApi, ({props, conte fontSize: '12px', }} > - {opt.label} + {opt.label as any} ); } @@ -103,7 +103,7 @@ export const ChoicePicker = createReactComponent(ChoicePickerApi, ({props, conte onChange={() => onToggle(opt.value)} name={isMutuallyExclusive ? `choice-${context.componentModel.id}` : undefined} /> - {opt.label} + {opt.label as any} ); })} diff --git a/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx b/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx index c8046380c..b7bb6463a 100644 --- a/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx +++ b/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx @@ -19,9 +19,7 @@ import {createReactComponent} from '../../../adapter'; import {TabsApi} from '@a2ui/web_core/v0_9/basic_catalog'; import {LEAF_MARGIN} from '../utils'; -// It seems that individual tabs don't have their type inferred, so we use a -// helper type here. -type _Tab = {title: string; child: string}; +// Individual tabs types are dynamic due to core schema, so we type as any in iteration. export const Tabs = createReactComponent(TabsApi, ({props, buildChild}) => { const [selectedIndex, setSelectedIndex] = useState(0); @@ -32,7 +30,7 @@ export const Tabs = createReactComponent(TabsApi, ({props, buildChild}) => { return (
- {tabs.map((tab: _Tab, i: number) => ( + {tabs.map((tab: any, i: number) => ( ))}
From f3acdf2e389f878e05a6f204e913ca061eed19e6 Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Tue, 24 Mar 2026 19:04:28 -0700 Subject: [PATCH 10/11] Address review feedback --- renderers/web_core/src/v0_9/catalog/types.test.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/renderers/web_core/src/v0_9/catalog/types.test.ts b/renderers/web_core/src/v0_9/catalog/types.test.ts index f78bd0168..1b6041f3c 100644 --- a/renderers/web_core/src/v0_9/catalog/types.test.ts +++ b/renderers/web_core/src/v0_9/catalog/types.test.ts @@ -108,7 +108,7 @@ describe('InferredComponentApiSchemaType', () => { schema: mockSchema, } satisfies ComponentApi; // Appease typescript-eslint/no-unused-vars - assert.strictEqual(mockApi.name, 'MockComp'); + type _ = typeof mockApi; // Type-level equivalence assertion using z.infer type ExpectedType = z.infer; @@ -120,7 +120,6 @@ describe('InferredComponentApiSchemaType', () => { // This happens when `mockApi: ComponentApi`, but doesn't when // `mockApi {} satisfies ComponentApi`! const inferredIsAny: IsAny = false; - assert.strictEqual(inferredIsAny, false); // When types are not "any", check that they're the same by checking if they // extend each other. @@ -133,9 +132,5 @@ describe('InferredComponentApiSchemaType', () => { // typesMatchExact only accepts "true" if `TypesAreEquivalent` const typesMatchExact: TypesAreEquivalent = true; - assert.strictEqual(typesMatchExact, true); - - // The asserts in this test should never fail, instead this test should fail - // at compile time if the inference is not correct. }); }); From 09df644465d1f0b53fd7f93789949cc6e1a943eb Mon Sep 17 00:00:00 2001 From: David Iglesias Teixeira Date: Tue, 24 Mar 2026 19:18:51 -0700 Subject: [PATCH 11/11] Fix any lints --- .../catalog/basic/components/ChoicePicker.tsx | 17 ++++++++++++----- .../src/v0_9/catalog/basic/components/Tabs.tsx | 9 ++++++--- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/renderers/react/src/v0_9/catalog/basic/components/ChoicePicker.tsx b/renderers/react/src/v0_9/catalog/basic/components/ChoicePicker.tsx index 83d2943b9..20e77c5dc 100644 --- a/renderers/react/src/v0_9/catalog/basic/components/ChoicePicker.tsx +++ b/renderers/react/src/v0_9/catalog/basic/components/ChoicePicker.tsx @@ -19,6 +19,11 @@ import {createReactComponent} from '../../../adapter'; import {ChoicePickerApi} from '@a2ui/web_core/v0_9/basic_catalog'; import {LEAF_MARGIN, STANDARD_BORDER, STANDARD_RADIUS} from '../utils'; +// The type of an option is deeply nested into the ChoicePickerApi schema, and +// it seems z.infer is not inferring it correctly (?). We use `any` for now. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type _Option = any; + export const ChoicePicker = createReactComponent(ChoicePickerApi, ({props, context}) => { const [filter, setFilter] = useState(''); @@ -37,8 +42,10 @@ export const ChoicePicker = createReactComponent(ChoicePickerApi, ({props, conte }; const options = (props.options || []).filter( - (opt: any) => - !props.filterable || filter === '' || String(opt.label).toLowerCase().includes(filter.toLowerCase()) + (opt: _Option) => + !props.filterable || + filter === '' || + String(opt.label).toLowerCase().includes(filter.toLowerCase()) ); const containerStyle: React.CSSProperties = { @@ -69,7 +76,7 @@ export const ChoicePicker = createReactComponent(ChoicePickerApi, ({props, conte /> )}
- {options.map((opt: any, i: number) => { + {options.map((opt: _Option, i: number) => { const isSelected = values.includes(opt.value); if (props.displayStyle === 'chips') { return ( @@ -88,7 +95,7 @@ export const ChoicePicker = createReactComponent(ChoicePickerApi, ({props, conte fontSize: '12px', }} > - {opt.label as any} + {opt.label} ); } @@ -103,7 +110,7 @@ export const ChoicePicker = createReactComponent(ChoicePickerApi, ({props, conte onChange={() => onToggle(opt.value)} name={isMutuallyExclusive ? `choice-${context.componentModel.id}` : undefined} /> - {opt.label as any} + {opt.label} ); })} diff --git a/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx b/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx index b7bb6463a..6a19dbae4 100644 --- a/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx +++ b/renderers/react/src/v0_9/catalog/basic/components/Tabs.tsx @@ -19,7 +19,10 @@ import {createReactComponent} from '../../../adapter'; import {TabsApi} from '@a2ui/web_core/v0_9/basic_catalog'; import {LEAF_MARGIN} from '../utils'; -// Individual tabs types are dynamic due to core schema, so we type as any in iteration. +// The type of a tab is deeply nested into the TabsApi schema, and +// it seems z.infer is not inferring it correctly (?). We use `any` for now. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type _Tab = any; export const Tabs = createReactComponent(TabsApi, ({props, buildChild}) => { const [selectedIndex, setSelectedIndex] = useState(0); @@ -30,7 +33,7 @@ export const Tabs = createReactComponent(TabsApi, ({props, buildChild}) => { return (
- {tabs.map((tab: any, i: number) => ( + {tabs.map((tab: _Tab, i: number) => ( ))}