control text
diff --git a/.changeset/13449-retire-html-renderer.md b/.changeset/13449-retire-html-renderer.md new file mode 100644 index 0000000000..d5cf2f6b1b --- /dev/null +++ b/.changeset/13449-retire-html-renderer.md @@ -0,0 +1,19 @@ +--- +'@object-ui/components': minor +'@object-ui/types': minor +'@object-ui/core': minor +'@object-ui/cli': minor +--- + +The raw-HTML `html` node type is retired (objectui#13449). Its renderer wrote the authored `html` string into the page through `dangerouslySetInnerHTML` with no sanitiser, so anyone who could write metadata could put script-bearing markup in front of every viewer — a `kind: 'html'` page included, which compiled an `html` tag carrying an `html` attribute with no diagnostic. `@objectstack/spec` declares no `html` component, so it is removed rather than sanitised, at once, with no deprecation alias. This is breaking for a page that still names it; it is marked `minor` under this repository's version policy. + +- **SDUI node `html`**, also registered as `ui:html`. FROM: `@object-ui/components` registered both keys. TO: neither is registered. A JSON node that still names it draws the unknown-component panel, a `kind: 'html'` page that writes the tag fails to compile with `forbidden-tag` and `unknown-component`, and `objectui check` no longer counts either key among the known component types. +- **Public block `html`** in `PUBLIC_BLOCKS` (`@object-ui/core`). FROM: listed as the curated tier's escape hatch, so `getPublicConfigs()` and the published `sdui.manifest.json` carried it. TO: not listed, so neither names it. +- **Schema `HtmlSchema`** in `@object-ui/types`: the TypeScript interface from the package entry, with its `DataDisplaySchema` member and its `SchemaRegistry` row (so `ComponentType` no longer offers `'html'`), and the zod arm from `@object-ui/types/zod`. FROM: exported, and a `type: "html"` node validated against the arm. TO: there is no such export, so importing it fails to compile. `DataDisplaySchema` keeps a refusal arm for the literal, which is not exported, so `objectui validate` refuses a `type: "html"` node BY NAME at `type`, and the message names the remedy. + +The `html` FIELD type (`HtmlFieldMetadata`, drawn by `field:html`) is a different layer and stays: its value displays through the sanitised fields path. + +Fix for a page that still names it: in place of `{ "type": "html", "html": "…" }`, declare rich text a user edits as an `html` or `richtext` field on the object, whose value renders sanitised, and write authored page copy as a `kind: 'html'` page. + +Clause-②: no (narrowing) +Metadata-protocol: narrowed diff --git a/apps/console/src/__tests__/html-node-retired-13449.test.tsx b/apps/console/src/__tests__/html-node-retired-13449.test.tsx new file mode 100644 index 0000000000..1da604b79a --- /dev/null +++ b/apps/console/src/__tests__/html-node-retired-13449.test.tsx @@ -0,0 +1,140 @@ +/** + * ObjectUI + * Copyright (c) 2024-present ObjectStack Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * objectui#13449 — the raw-HTML `html` node type is retired, and neither + * authoring surface can put unsanitised markup into the page any more. + * + * ## The defect + * + * `@object-ui/components` registered `html` (`ui:html` plus the bare key), + * whose renderer wrote the authored `html` string into a `div` through + * `dangerouslySetInnerHTML` with no sanitiser. `@objectstack/spec` declares no + * `html` component. Two doors reached it: + * + * 1. a JSON node `{ "type": "html", "html": "…" }`; + * 2. a `kind:'html'` page — the tier documented as parsed, never executed, + * and safe for untrusted authors. Its compile whitelists every registered + * type, so `
` compiled with NO diagnostic and the + * renderer injected the string. Measured on the base before the fix: an + * `img` carrying an `onerror` attribute reached the DOM through both doors. + * + * ## What each suite holds + * + * 1. the `kind:'html'` page refuses the tag at compile time and renders no + * authored markup (red on the base: zero diagnostics, the `img` with its + * `onerror` attribute in the DOM); + * 2. the JSON node draws the unknown-component panel and no authored markup + * (red on the base: the markup was injected); + * 3. CONTROL — the same page without the retired tag renders its authored + * content, so suite 1's absence is not a page that renders nothing. + * + * It lives in `apps/console` because the claim is about the whole registration + * graph: `@object-ui/fields` registers a `field:html` editor that must not take + * over the bare key once the display renderer is gone. + */ +import { describe, it, expect } from 'vitest'; +import { render, waitFor } from '@testing-library/react'; +import { SchemaRenderer, SchemaRendererProvider } from '@object-ui/react'; +import { ComponentRegistry } from '@object-ui/core'; +import { compile, manifestFromConfigs } from '@object-ui/sdui-parser'; + +// The full registration graph — the pair `dev/manifest-dump.tsx` builds the +// published artifacts from, and the pair every live-path suite here reads. +import '@object-ui/components'; +import '../register-plugins'; + +const dataSource = { + find: async () => ({ data: [], total: 0, hasMore: false }), + findOne: async () => null, + create: async () => ({}), + update: async () => ({}), + delete: async () => ({}), + count: async () => 0, + getObjectSchema: async (name: string) => ({ name, label: name, fields: {} }), + getObjects: async () => [], + onMutation: () => () => {}, +} as any; + +/** + * The manifest an html-kind page validates against, built the way the renderer + * builds it — `ComponentRegistry.getKnownTypes()` + each type's declared + * `inputs`, mirroring `page.tsx`'s `getJsxManifest()`. + */ +const livePageManifest = () => + manifestFromConfigs( + ComponentRegistry.getKnownTypes().map((t) => { + const meta = ComponentRegistry.getMeta(t); + return { type: t, namespace: meta?.namespace, isContainer: meta?.isContainer, inputs: meta?.inputs }; + }) as unknown as Parameterscontrol text
This is HTML content
" -} diff --git a/packages/app-shell/src/__tests__/widget-dom-leak-sweep.test.tsx b/packages/app-shell/src/__tests__/widget-dom-leak-sweep.test.tsx index b1756dec9e..76d136d625 100644 --- a/packages/app-shell/src/__tests__/widget-dom-leak-sweep.test.tsx +++ b/packages/app-shell/src/__tests__/widget-dom-leak-sweep.test.tsx @@ -37,9 +37,9 @@ * | plugin-calendar | 3 | 0 | 0 | * | plugin-chatbot | 3 | 0 | 0 | * | plugin-dashboard | 7 | 0 | 0 | - * | components | 150 | 82 | 12 .. 15 | + * | components | 149 | 81 | 12 .. 15 | * - * **82 of 168 targets leak.** All of them are the `components` row, which is + * **81 of 167 targets leak.** All of them are the `components` row, which is * objectui#5574 and is covered in its own section below. The four packages * objectui#4425 named now read zero. Three migration steps have closed their * rows since the phase-1 measurement: @@ -128,7 +128,7 @@ * have failed. These two differ in exactly one thing: which namespace the extra * widget went into. * - * ### The reading — 119 of 158 ON ARRIVAL, in seven shapes; 82 today + * ### The reading — 119 of 158 ON ARRIVAL, in seven shapes; 81 today * * The card named four candidates (`flex`, `stack`, `container`, `text`) and was * careful to call them candidates. All four leaked. So did 115 others, and the @@ -145,9 +145,10 @@ * so their rows had to go for the gate to pass — the two-way expiry below, * working exactly once it had something to expire. Later slices took more, * and objectui#5632's `ui:sidebar-trigger` took the last shape that named a - * single renderer: **82 rows in FOUR shapes** remain, on a target set of 150 - * today (it grew past 158, and objectui#10859 batch 8 phase 2d took the ten - * retired `ui:sidebar-*` part keys out of it). What the arrival reading measured is preserved here in prose and in + * single renderer: **81 rows in FOUR shapes** remain, on a target set of 149 + * today (it grew past 158, objectui#10859 batch 8 phase 2d took the ten + * retired `ui:sidebar-*` part keys out of it, and objectui#13449 took the + * retired raw-HTML `ui:html`). What the arrival reading measured is preserved here in prose and in * the burn-down note on {@link COMPONENTS_LEAK_GROUPS}; what the gate asserts * is always current truth, which is the whole point of not writing dates into * a ledger. @@ -615,7 +616,7 @@ const CALENDAR_OBJECT_EXTRAS = { * an ordinary authored prop while doing it. * * Measured on the tree this landed on: 152 of 158 targets matched it. - * Today 147 of 150 targets match it; the other three are in + * Today 146 of 149 targets match it; the other three are in * {@link READY_OVERRIDE_REASONS}, each with the reason it cannot — * a recorded limitation with its own two-way assertion below, never a quiet * exemption (the `omitCanaries` discipline, applied to readiness). @@ -772,7 +773,7 @@ const COMPONENTS_PLAIN_TYPES: readonly string[] = [ 'ui:date-picker', 'ui:dd', 'ui:del', 'ui:div', 'ui:dl', 'ui:dt', 'ui:em', 'ui:email', 'ui:empty', 'ui:figcaption', 'ui:figure', 'ui:file-upload', 'ui:filter-builder', 'ui:flex', 'ui:footer', 'ui:form', 'ui:grid', 'ui:h1', 'ui:h2', 'ui:h3', 'ui:h4', 'ui:h5', 'ui:h6', - 'ui:header', 'ui:home', 'ui:hr', 'ui:html', 'ui:i', 'ui:icon', 'ui:image', 'ui:img', + 'ui:header', 'ui:home', 'ui:hr', 'ui:i', 'ui:icon', 'ui:image', 'ui:img', 'ui:input', 'ui:input-otp', 'ui:ins', 'ui:kbd', 'ui:label', 'ui:li', 'ui:list', 'ui:loading', 'ui:main', 'ui:mark', 'ui:menubar', 'ui:nav', 'ui:navigation-menu', 'ui:ol', 'ui:p', @@ -908,8 +909,8 @@ const TARGETS: Readonlyx
' }); + expect(result.success).toBe(false); + const named = (result.success ? [] : result.error.issues).filter( + (issue) => issue.code === 'custom' && issue.path.length === 1 && issue.path[0] === 'type', + ); + expect(named).toHaveLength(1); + expect(named[0]?.message).toContain('`html` is a RETIRED node type'); + expect(refusedAtType('html')).toBe(false); + // Control: an unknown bare literal still takes the generic path. + expect(refusedAtType('no-such-node-13449')).toBe(true); + }); + it('counts `cloud:workspace-timezone-notice` armed — it registered WITH its arm (objectui#11930)', () => { // One registry key (`skipFallback: true`, so no bare `workspace-timezone-notice`), // armed in `@object-ui/types/zod` in the same change, so the pin above did not move. diff --git a/packages/cli/src/utils/known-schema-types.ts b/packages/cli/src/utils/known-schema-types.ts index 285dbf9e58..1fbf40cbe0 100644 --- a/packages/cli/src/utils/known-schema-types.ts +++ b/packages/cli/src/utils/known-schema-types.ts @@ -198,7 +198,6 @@ export const KNOWN_SCHEMA_TYPES: readonly string[] = [ 'home', 'hover-card', 'hr', - 'html', 'i', 'icon', 'image', @@ -500,7 +499,6 @@ export const KNOWN_SCHEMA_TYPES: readonly string[] = [ 'ui:home', 'ui:hover-card', 'ui:hr', - 'ui:html', 'ui:i', 'ui:icon', 'ui:image', diff --git a/packages/components/src/__tests__/basic-renderers.test.tsx b/packages/components/src/__tests__/basic-renderers.test.tsx index 9893221fdc..0ba35ba16f 100644 --- a/packages/components/src/__tests__/basic-renderers.test.tsx +++ b/packages/components/src/__tests__/basic-renderers.test.tsx @@ -19,7 +19,6 @@ import { import '../renderers'; import type { DivSchema, - HtmlSchema, IconSchema, ImageSchema, SeparatorSchema, @@ -40,7 +39,6 @@ const spanNode = (schema: TextSpanSchema): TextSpanSchema => schema; const imageNode = (schema: ImageSchema): ImageSchema => schema; const iconNode = (schema: IconSchema): IconSchema => schema; const separatorNode = (schema: SeparatorSchema): SeparatorSchema => schema; -const htmlNode = (schema: HtmlSchema): HtmlSchema => schema; /** * Comprehensive tests for basic renderer components @@ -275,21 +273,21 @@ describe('Basic Renderers - Display Issue Detection', () => { }); }); - describe('HTML Renderer', () => { - it('should be properly registered', () => { - const validation = validateComponentRegistration('html'); - expect(validation.isRegistered).toBe(true); + describe('the retired `html` node type (objectui#13449)', () => { + // The raw-HTML renderer injected `schema.html` through + // `dangerouslySetInnerHTML` with no sanitiser, and `@objectstack/spec` + // declares no `html` component. It is retired, not sanitised: neither + // registry key survives. + it('registers neither the bare key nor `ui:html`', () => { + expect(validateComponentRegistration('html').isRegistered).toBe(false); + expect(validateComponentRegistration('ui:html').isRegistered).toBe(false); }); - it('should render HTML content safely', () => { - const { container } = renderComponent(htmlNode({ - type: 'html', - html: 'HTML Content
', - })); - - // HTML renderer uses dangerouslySetInnerHTML - const hasContent = container.querySelector('p') || container.textContent?.includes('HTML Content'); - expect(hasContent).toBeTruthy(); + it('control: a sibling basic renderer from the same module set is still registered', () => { + // Without this, the two `false` readings above would also pass under a + // `../renderers` import that registered nothing at all. + expect(validateComponentRegistration('text').isRegistered).toBe(true); + expect(validateComponentRegistration('ui:text').isRegistered).toBe(true); }); }); }); diff --git a/packages/components/src/renderers/basic/html.tsx b/packages/components/src/renderers/basic/html.tsx deleted file mode 100644 index b2a9adc072..0000000000 --- a/packages/components/src/renderers/basic/html.tsx +++ /dev/null @@ -1,43 +0,0 @@ -/** - * ObjectUI - * Copyright (c) 2024-present ObjectStack Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -import React from 'react'; -import { ComponentRegistry } from '@object-ui/core'; -import type { HtmlSchema } from '@object-ui/types'; -import { cn } from '../../lib/utils'; - -ComponentRegistry.register('html', - ({ schema, className, ...props }: { schema: HtmlSchema; className?: string; [key: string]: any }) => { - // Extract designer-related props - const { - 'data-obj-id': dataObjId, - 'data-obj-type': dataObjType, - style, - ...htmlProps - } = props; - - return ( - - ); - }, - { - namespace: 'ui', - label: 'HTML Content', - inputs: [ - { name: 'html', type: 'string', description: 'Raw HTML content' } - ] - } -); diff --git a/packages/components/src/renderers/basic/index.ts b/packages/components/src/renderers/basic/index.ts index 8cdfc9e41a..30a08b4d2a 100644 --- a/packages/components/src/renderers/basic/index.ts +++ b/packages/components/src/renderers/basic/index.ts @@ -12,7 +12,10 @@ import './span'; import './separator'; import './image'; import './icon'; -import './html'; +// `./html` (the raw-HTML `html` node type) is retired (objectui#13449): it +// injected `schema.html` unsanitised and `@objectstack/spec` declares no such +// component. Rich HTML is a field value (`html` / `richtext`, sanitised) or a +// `kind: 'html'` page. import './html-elements'; import './button-group'; import './pagination'; diff --git a/packages/core/src/registry/public-blocks.ts b/packages/core/src/registry/public-blocks.ts index 1b382afaeb..a1aee46583 100644 --- a/packages/core/src/registry/public-blocks.ts +++ b/packages/core/src/registry/public-blocks.ts @@ -16,7 +16,7 @@ * contract (`getPublicConfigs`). * * Shaped like Salesforce App Builder standard components — small, object-centric - * — plus a thin layout/content layer and one escape hatch. A component not yet + * — plus a thin layout/content layer. A component not yet * registered is simply skipped (the list is aspirational-safe). Registrations * may also opt in individually via `tier: 'public'`. * @@ -169,8 +169,13 @@ export const PUBLIC_BLOCKS: readonly string[] = [ 'badge', 'alert', 'button', - // ── Tier C — escape hatch (flagged, second-class) ───────────────────────── - 'html', + // ⛔ The raw-HTML `html` block that sat here as a "Tier C escape hatch" is + // RETIRED (objectui#13449): it injected `schema.html` unsanitised, so any + // metadata author — a `kind:'html'` page included, which could write it as an + // `` tag — could put script-bearing markup in front of every + // viewer, and `@objectstack/spec` declares no `html` component. Rich HTML is + // a sanitised field value (`html` / `richtext`) or a `kind:'html'` page; + // there is no raw-HTML block. ]; /** Fast membership set built from {@link PUBLIC_BLOCKS}. */ diff --git a/packages/fields/src/__tests__/registry-collision.test.ts b/packages/fields/src/__tests__/registry-collision.test.ts index 6eaba7cbb6..c9cd96861a 100644 --- a/packages/fields/src/__tests__/registry-collision.test.ts +++ b/packages/fields/src/__tests__/registry-collision.test.ts @@ -10,7 +10,7 @@ * Registry collision guard. * * `@object-ui/components` registers display widgets (`text`, `image`, - * `avatar`, `html`, `grid`) under their bare names, and the html tier's + * `avatar`, `grid`) under their bare names, and the html tier's * inline `code` element passthrough (objectui#10756). `@object-ui/fields` * registers form-input widgets that — by name — collide with those. * @@ -37,7 +37,7 @@ import { ComponentRegistry } from '@object-ui/core'; import '@object-ui/components'; import { registerAllFields } from '../index'; -const COLLIDING_TYPES = ['text', 'html', 'image', 'avatar', 'grid', 'code'] as const; +const COLLIDING_TYPES = ['text', 'image', 'avatar', 'grid', 'code'] as const; describe('registry collision (fields ↔ components)', () => { beforeAll(() => { @@ -102,4 +102,15 @@ describe('registry collision (fields ↔ components)', () => { expect(ComponentRegistry.get(type)).not.toBe(ComponentRegistry.get(`field:${type}`)); } }); + + it('bare `html` resolves to NOTHING once the raw-HTML node type retired (objectui#13449)', () => { + // `html` left COLLIDING_TYPES: `@object-ui/components` no longer registers + // the raw-HTML `ui:html` node that owned the bare key. The field widget + // still stands down from it, so a stale `{ type: 'html' }` node draws the + // unknown-component panel instead of a rich-text editor, and a form still + // reaches the widget under its namespace. + expect(ComponentRegistry.get('field:html'), 'field:html must be registered').toBeTruthy(); + expect(ComponentRegistry.get('html'), 'bare "html" must not be registered').toBeFalsy(); + expect(ComponentRegistry.get('ui:html'), '"ui:html" must not be registered').toBeFalsy(); + }); }); diff --git a/packages/fields/src/index.tsx b/packages/fields/src/index.tsx index d9c55a62e5..71bd5286f8 100644 --- a/packages/fields/src/index.tsx +++ b/packages/fields/src/index.tsx @@ -4780,10 +4780,9 @@ const FIELD_TYPES_SKIP_FALLBACK = new Set([ // expect (e.g. `{ type: 'markdown', content }` → the markdown renderer, not // the RichText editor). Without skipFallback each of these logged a // "bare-name fallback is being overwritten" warning at boot. - // Display widgets (text/html/image/avatar/grid live in @object-ui/components + // Display widgets (text/image/avatar/grid live in @object-ui/components // or @object-ui/layout as the bare-name owners). 'text', - 'html', 'image', 'avatar', 'grid', @@ -4848,6 +4847,14 @@ const FIELD_TYPES_SKIP_FALLBACK = new Set([ 'url', 'user', 'vector', + // ── Retired bare node key (objectui#13449) ──────────────────────────────── + // `html` sat in the display-widget group above while `@object-ui/components` + // registered its raw-HTML `ui:html` node, which owned the bare key. That node + // type is retired, so no package owns bare `html` any more. It stays in this + // set so the bare key resolves to NOTHING: a stale `{ type: 'html' }` node + // must draw the unknown-component panel, never this rich-text editor, and a + // form keeps reaching the widget as `field:html`. + 'html', ]); /** diff --git a/packages/types/examples/data-display-examples.json b/packages/types/examples/data-display-examples.json index 8a3f01b4b3..d14ddaac4e 100644 --- a/packages/types/examples/data-display-examples.json +++ b/packages/types/examples/data-display-examples.json @@ -228,11 +228,6 @@ "type": "markdown", "id": "readme", "content": "# Welcome\n\nThis is a **markdown** component.\n\n- Feature 1\n- Feature 2\n- Feature 3" - }, - "html": { - "type": "html", - "id": "custom-html", - "html": "This is raw HTML content.
This is HTML content
' } as const; + +describe('suite 1 — a `type: "html"` node is REFUSED, by name (objectui#13449)', () => { + it('refuses the document with one `custom` issue at `type`', () => { + const found = refusals(RETIRED_NODE); + expect(found.filter((f) => f.code === 'custom' && f.path === 'type')).toHaveLength(1); + }); + + it('the refusal names the retired type and the two replacements', () => { + // ⭐ The whole reason the arm survives as a refusal instead of being + // deleted. Suite 3 is its control. + const [issue] = refusals(RETIRED_NODE).filter((f) => f.code === 'custom' && f.path === 'type'); + expect(issue?.message).toContain('`html` is a RETIRED node type'); + expect(issue?.message).toContain('`richtext`'); + expect(issue?.message).toContain("`kind: 'html'`"); + }); + + it('refuses a bare node too, whatever else it carries', () => { + expect(refusals({ type: 'html' }).filter((f) => f.code === 'custom' && f.path === 'type')).toHaveLength(1); + }); +}); + +describe('suite 2 — the refusal is not a validator that turned strict', () => { + it('a surviving data-display node on the same call is still accepted', () => { + // Firing control: without it every assertion in suite 1 would also pass + // under a `safeValidateSchema` that had started refusing everything. + expect(refusals({ type: 'kbd', keys: ['Ctrl', 'K'] })).toEqual([]); + }); +}); + +describe('suite 3 — control: an unknown literal takes the GENERIC path', () => { + it('a name no arm claims is refused without the retirement text', () => { + // ⭐ The separator. If this document ALSO carried the guidance, suite 1 + // would be measuring the union's boilerplate rather than this arm. + const found = refusals({ type: 'no-such-node-13449', html: 'x
' }); + const text = found.map((r) => r.message).join('\n'); + expect(text).not.toEqual(''); + expect(found.some((f) => f.code === 'custom')).toBe(false); + expect(text).not.toContain('RETIRED'); + }); +}); + +describe('suite 4 — the `html` FIELD type is a different layer and is untouched', () => { + it('a form declaring an `html` field still validates', () => { + // The catalog's own `fields-rich-text/html-editor` document, spelled + // unchanged: the remedy suite 1 names has to keep working. + const form = { + type: 'form', + showSubmit: false, + showCancel: false, + fields: [{ name: 'description', label: 'Description', type: 'html', placeholder: 'Enter HTML content...', rows: 8 }], + }; + expect(refusals(form)).toEqual([]); + }); +}); diff --git a/packages/types/src/__tests__/zod-mirror-parity.test.ts b/packages/types/src/__tests__/zod-mirror-parity.test.ts index e153c08a28..0549a8674c 100644 --- a/packages/types/src/__tests__/zod-mirror-parity.test.ts +++ b/packages/types/src/__tests__/zod-mirror-parity.test.ts @@ -959,7 +959,7 @@ import { RecordApprovalDecisionBlockSchema } from '../zod/record-approval-decisi import { RecordApprovalsBlockSchema, RecordAttachmentsBlockSchema } from '../zod/record-panels.zod.js'; import { CalendarEventSchema, CalendarViewSchema, CarouselItemSchema, CarouselSchema, ChatbotSchema, ChatbotEnhancedSchema, ChatbotFloatingSchema, ChatMessageSchema, ChatMessageSourceSchema, ChatToolInvocationSchema, DashboardComponentSchema, DashboardConfigSchema, DashboardWidgetConfigSchema, DashboardWidgetLayoutSchema, DashboardWidgetSchema, FilterBuilderSchema, FilterFieldSchema, KanbanCardSchema, KanbanColumnSchema, CardTemplateSchema, FilterGroupSchema } from '../zod/complex.zod.js'; import { ActionSchema, CRUDDialogSchema, DetailSchema } from '../zod/crud.zod.js'; -import { AlertSchema, AvatarSchema, BadgeSchema, BarChartSchema, ChartDataSeriesSchema, ChartSchema, DataTableSchema, DrillDownConfigSchema, HtmlSchema, KbdSchema, ListItemSchema, ListSchema, MarkdownSchema, PivotTableSchema, StaticTableColumnSchema, StatisticSchema, TableColumnSchema, TableSchema, TimelineEventSchema, TimelineFeedItemSchema, TimelineGanttItemBarSchema, TimelineGanttItemSchema, TimelineSchema, TreeNodeSchema, TreeViewSchema } from '../zod/data-display.zod.js'; +import { AlertSchema, AvatarSchema, BadgeSchema, BarChartSchema, ChartDataSeriesSchema, ChartSchema, DataTableSchema, DrillDownConfigSchema, KbdSchema, ListItemSchema, ListSchema, MarkdownSchema, PivotTableSchema, StaticTableColumnSchema, StatisticSchema, TableColumnSchema, TableSchema, TimelineEventSchema, TimelineFeedItemSchema, TimelineGanttItemBarSchema, TimelineGanttItemSchema, TimelineSchema, TreeNodeSchema, TreeViewSchema } from '../zod/data-display.zod.js'; import { BPMNEdgeSchema, BPMNLaneSchema, BPMNNodeSchema, DataModelDesignerSchema, DataModelEntitySchema, DataModelFieldSchema, DataModelRelationshipSchema, DesignerCanvasConfigSchema, DesignerComponentSchema, DesignerFieldDefinitionSchema, DesignerFieldOptionSchema, DesignerPaletteCategorySchema, DesignerPaletteItemSchema, DesignerPositionSchema, FieldDesignerSchema, ObjectDefinitionSchema, ObjectManagerSchema, PageDesignerSchema, ProcessDesignerSchema, ReportDesignerElementSchema, ReportDesignerSchema, ReportDesignerSectionSchema } from '../zod/designer.zod.js'; import { AccordionItemSchema, AccordionSchema, CollapsibleSchema, ToggleGroupItemSchema, ToggleGroupSchema } from '../zod/disclosure.zod.js'; import { EmptySchema, LoadingSchema, ProgressSchema, SkeletonSchema, SonnerSchema, SpinnerSchema, ToasterSchema, ToastSchema } from '../zod/feedback.zod.js'; @@ -981,7 +981,7 @@ import type { RecordApprovalsBlockSchema as Ts_RecordApprovalsBlockSchema, Recor import type { CalendarEvent as Ts_CalendarEvent, CalendarViewSchema as Ts_CalendarViewSchema, CarouselItem as Ts_CarouselItem, CarouselSchema as Ts_CarouselSchema, ChatbotSchema as Ts_ChatbotSchema, ChatbotEnhancedSchema as Ts_ChatbotEnhancedSchema, ChatbotFloatingSchema as Ts_ChatbotFloatingSchema, ChatMessage as Ts_ChatMessage, ChatMessageSource as Ts_ChatMessageSource, ChatToolInvocation as Ts_ChatToolInvocation, DashboardComponentSchema as Ts_DashboardComponentSchema, DashboardWidgetLayout as Ts_DashboardWidgetLayout, DashboardWidgetSchema as Ts_DashboardWidgetSchema, FilterBuilderSchema as Ts_FilterBuilderSchema, FilterField as Ts_FilterField, KanbanCard as Ts_KanbanCard, KanbanColumn as Ts_KanbanColumn, CardTemplate as Ts_CardTemplate } from '../complex'; import type { BPMNEdge as Ts_BPMNEdge, BPMNLane as Ts_BPMNLane, BPMNNode as Ts_BPMNNode, DashboardConfig as Ts_DashboardConfig, DashboardWidgetConfig as Ts_DashboardWidgetConfig, DataModelDesignerSchema as Ts_DataModelDesignerSchema, DataModelEntity as Ts_DataModelEntity, DataModelField as Ts_DataModelField, DataModelRelationship as Ts_DataModelRelationship, DesignerCanvasConfig as Ts_DesignerCanvasConfig, DesignerFieldDefinition as Ts_DesignerFieldDefinition, DesignerFieldOption as Ts_DesignerFieldOption, DesignerPaletteCategory as Ts_DesignerPaletteCategory, DesignerPaletteItem as Ts_DesignerPaletteItem, DesignerPosition as Ts_DesignerPosition, FieldDesignerSchema as Ts_FieldDesignerSchema, ObjectDefinition as Ts_ObjectDefinition, ObjectManagerSchema as Ts_ObjectManagerSchema, PageDesignerSchema as Ts_PageDesignerSchema, ProcessDesignerSchema as Ts_ProcessDesignerSchema, ReportDesignerElement as Ts_ReportDesignerElement, ReportDesignerSchema as Ts_ReportDesignerSchema, ReportDesignerSection as Ts_ReportDesignerSection } from '../designer'; import type { CRUDDialogSchema as Ts_CRUDDialogSchema, DetailSchema as Ts_DetailSchema } from '../crud'; -import type { AlertSchema as Ts_AlertSchema, AvatarSchema as Ts_AvatarSchema, BadgeSchema as Ts_BadgeSchema, BarChartSchema as Ts_BarChartSchema, ChartDataSeries as Ts_ChartDataSeries, ChartSchema as Ts_ChartSchema, DataTableSchema as Ts_DataTableSchema, DrillDownConfig as Ts_DrillDownConfig, HtmlSchema as Ts_HtmlSchema, KbdSchema as Ts_KbdSchema, ListItem as Ts_ListItem, ListSchema as Ts_ListSchema, MarkdownSchema as Ts_MarkdownSchema, PivotTableSchema as Ts_PivotTableSchema, StaticTableColumn as Ts_StaticTableColumn, StatisticSchema as Ts_StatisticSchema, TableColumn as Ts_TableColumn, TableSchema as Ts_TableSchema, TimelineEvent as Ts_TimelineEvent, TimelineFeedItem as Ts_TimelineFeedItem, TimelineGanttItem as Ts_TimelineGanttItem, TimelineGanttItemBar as Ts_TimelineGanttItemBar, TimelineSchema as Ts_TimelineSchema, TreeViewSchema as Ts_TreeViewSchema, BreadcrumbItem as Ts_BreadcrumbItem, BreadcrumbSchema as Ts_BreadcrumbSchema } from '../data-display'; +import type { AlertSchema as Ts_AlertSchema, AvatarSchema as Ts_AvatarSchema, BadgeSchema as Ts_BadgeSchema, BarChartSchema as Ts_BarChartSchema, ChartDataSeries as Ts_ChartDataSeries, ChartSchema as Ts_ChartSchema, DataTableSchema as Ts_DataTableSchema, DrillDownConfig as Ts_DrillDownConfig, KbdSchema as Ts_KbdSchema, ListItem as Ts_ListItem, ListSchema as Ts_ListSchema, MarkdownSchema as Ts_MarkdownSchema, PivotTableSchema as Ts_PivotTableSchema, StaticTableColumn as Ts_StaticTableColumn, StatisticSchema as Ts_StatisticSchema, TableColumn as Ts_TableColumn, TableSchema as Ts_TableSchema, TimelineEvent as Ts_TimelineEvent, TimelineFeedItem as Ts_TimelineFeedItem, TimelineGanttItem as Ts_TimelineGanttItem, TimelineGanttItemBar as Ts_TimelineGanttItemBar, TimelineSchema as Ts_TimelineSchema, TreeViewSchema as Ts_TreeViewSchema, BreadcrumbItem as Ts_BreadcrumbItem, BreadcrumbSchema as Ts_BreadcrumbSchema } from '../data-display'; import type { AccordionItem as Ts_AccordionItem, AccordionSchema as Ts_AccordionSchema, CollapsibleSchema as Ts_CollapsibleSchema, ToggleGroupItem as Ts_ToggleGroupItem, ToggleGroupSchema as Ts_ToggleGroupSchema } from '../disclosure'; import type { EmptySchema as Ts_EmptySchema, LoadingSchema as Ts_LoadingSchema, ProgressSchema as Ts_ProgressSchema, SkeletonSchema as Ts_SkeletonSchema, SonnerSchema as Ts_SonnerSchema, SpinnerSchema as Ts_SpinnerSchema, ToasterSchema as Ts_ToasterSchema, ToastSchema as Ts_ToastSchema } from '../feedback'; import type { ButtonSchema as Ts_ButtonSchema, CalendarSchema as Ts_CalendarSchema, CheckboxSchema as Ts_CheckboxSchema, CodeEditorSchema as Ts_CodeEditorSchema, ComboboxOption as Ts_ComboboxOption, ComboboxSchema as Ts_ComboboxSchema, CommandGroup as Ts_CommandGroup, CommandItem as Ts_CommandItem, CommandSchema as Ts_CommandSchema, DatePickerSchema as Ts_DatePickerSchema, FieldCondition as Ts_FieldCondition, FieldValidationRules as Ts_FieldValidationRules, FileUploadSchema as Ts_FileUploadSchema, FormField as Ts_FormField, FormSchema as Ts_FormSchema, InputOTPSchema as Ts_InputOTPSchema, InputSchema as Ts_InputSchema, InputShorthandSchema as Ts_InputShorthandSchema, UiCalendarSchema as Ts_UiCalendarSchema, LabelSchema as Ts_LabelSchema, RadioGroupSchema as Ts_RadioGroupSchema, RadioOption as Ts_RadioOption, SelectOption as Ts_SelectOption, SelectSchema as Ts_SelectSchema, SliderSchema as Ts_SliderSchema, SwitchSchema as Ts_SwitchSchema, TextareaSchema as Ts_TextareaSchema, ToggleSchema as Ts_ToggleSchema } from '../form'; @@ -1853,7 +1853,6 @@ const MIRRORS = { 'data-display.zod.ts#ChartSchema': ChartSchema, 'data-display.zod.ts#DataTableSchema': DataTableSchema, 'data-display.zod.ts#DrillDownConfigSchema': DrillDownConfigSchema, - 'data-display.zod.ts#HtmlSchema': HtmlSchema, 'data-display.zod.ts#KbdSchema': KbdSchema, 'data-display.zod.ts#BarChartSchema': BarChartSchema, 'data-display.zod.ts#ListItemSchema': ListItemSchema, @@ -2066,7 +2065,6 @@ interface Declared { 'data-display.zod.ts#ChartSchema': Ts_ChartSchema; 'data-display.zod.ts#DataTableSchema': Ts_DataTableSchema; 'data-display.zod.ts#DrillDownConfigSchema': Ts_DrillDownConfig; - 'data-display.zod.ts#HtmlSchema': Ts_HtmlSchema; 'data-display.zod.ts#KbdSchema': Ts_KbdSchema; 'data-display.zod.ts#BarChartSchema': Ts_BarChartSchema; 'data-display.zod.ts#ListItemSchema': Ts_ListItem; @@ -4839,6 +4837,11 @@ const EXCLUSIONS: Readonly