@adia-ai/gen-ui 0.8.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/README.md +77 -0
- package/compose/CHANGELOG.md +1707 -0
- package/compose/README.md +215 -0
- package/compose/core/artifacts.js +262 -0
- package/compose/core/context-store.js +218 -0
- package/compose/core/generator.d.ts +4 -0
- package/compose/core/generator.js +602 -0
- package/compose/core/pipeline/engine.js +289 -0
- package/compose/core/pipeline/types.js +91 -0
- package/compose/core/plan-primitives.js +120 -0
- package/compose/core/plan-turn.js +145 -0
- package/compose/core/reference.js +150 -0
- package/compose/core/state.js +15 -0
- package/compose/evals/harness.d.ts +4 -0
- package/compose/evals/harness.mjs +193 -0
- package/compose/index.d.ts +4 -0
- package/compose/index.js +16 -0
- package/compose/shared/validate-and-repair.js +122 -0
- package/compose/strategies/_shared/chunk-loader.js +282 -0
- package/compose/strategies/cascade.d.ts +67 -0
- package/compose/strategies/cascade.js +165 -0
- package/compose/strategies/escalation.d.ts +13 -0
- package/compose/strategies/escalation.js +132 -0
- package/compose/strategies/free-form-composer/index.js +254 -0
- package/compose/strategies/free-form-composer/system-prompt.js +205 -0
- package/compose/strategies/free-form-composer/transpile.js +279 -0
- package/compose/strategies/monolithic/_shared.js +1619 -0
- package/compose/strategies/monolithic/generate-instant.js +228 -0
- package/compose/strategies/monolithic/generate-pro.js +490 -0
- package/compose/strategies/monolithic/generate-thinking.js +206 -0
- package/compose/strategies/registry.d.ts +20 -0
- package/compose/strategies/registry.js +495 -0
- package/compose/strategies/zettel/_smoke.js +27 -0
- package/compose/strategies/zettel/chunk-composer.js +214 -0
- package/compose/strategies/zettel/chunk-refiner.js +582 -0
- package/compose/strategies/zettel/chunk-synthesizer.js +458 -0
- package/compose/strategies/zettel/composer.js +78 -0
- package/compose/strategies/zettel/composition-library.js +418 -0
- package/compose/strategies/zettel/generate.js +15 -0
- package/compose/strategies/zettel/generator-adapter.d.ts +4 -0
- package/compose/strategies/zettel/generator-adapter.js +242 -0
- package/compose/strategies/zettel/issue-reporter.js +607 -0
- package/compose/strategies/zettel/session-store.js +121 -0
- package/compose/strategies/zettel/state-cache.js +158 -0
- package/compose/transpiler/transpiler-maps.js +675 -0
- package/compose/transpiler/transpiler.d.ts +4 -0
- package/compose/transpiler/transpiler.js +962 -0
- package/corpus/CHANGELOG.md +1957 -0
- package/corpus/README.md +279 -0
- package/corpus/catalog-a2ui_0_9.d.ts +4 -0
- package/corpus/catalog-a2ui_0_9.json +29571 -0
- package/corpus/catalog-a2ui_0_9_rules.txt +1215 -0
- package/corpus/chunk-embeddings.d.ts +4 -0
- package/corpus/chunk-embeddings.json +1 -0
- package/corpus/chunks/_index.json +16658 -0
- package/corpus/chunks/_source-hashes.json +571 -0
- package/corpus/chunks/access-denied-with-request.json +124 -0
- package/corpus/chunks/access-request-form.json +166 -0
- package/corpus/chunks/access-request-pending.json +133 -0
- package/corpus/chunks/accordion-settings.json +176 -0
- package/corpus/chunks/achievement-badges.json +413 -0
- package/corpus/chunks/achievement-unlock.json +104 -0
- package/corpus/chunks/action-list-record-actions.json +84 -0
- package/corpus/chunks/activity-feed.json +390 -0
- package/corpus/chunks/admin-page-header-flush.json +83 -0
- package/corpus/chunks/admin-page-header-title-description.json +80 -0
- package/corpus/chunks/admin-page-header-with-actions.json +107 -0
- package/corpus/chunks/admin-page-header-with-tabs.json +144 -0
- package/corpus/chunks/admin-shell-rounded-borderless.json +287 -0
- package/corpus/chunks/admin-shell-standard.json +310 -0
- package/corpus/chunks/admin-sidebar-brand-signin.json +158 -0
- package/corpus/chunks/admin-sidebar-brand-version.json +130 -0
- package/corpus/chunks/admin-sidebar-flat-nav.json +131 -0
- package/corpus/chunks/admin-sidebar-nav-dividers.json +150 -0
- package/corpus/chunks/admin-sidebar-nav-groups.json +171 -0
- package/corpus/chunks/admin-sidebar-workspace-switcher.json +139 -0
- package/corpus/chunks/admin-topbar-breadcrumb-actions.json +130 -0
- package/corpus/chunks/admin-topbar-breadcrumb-minimal.json +79 -0
- package/corpus/chunks/admin-topbar-deep-breadcrumb.json +129 -0
- package/corpus/chunks/admin-topbar-search.json +104 -0
- package/corpus/chunks/admin-topbar-status-indicator.json +122 -0
- package/corpus/chunks/admin-topbar-trailing-toggle.json +114 -0
- package/corpus/chunks/agent-activity-feed.json +163 -0
- package/corpus/chunks/agent-artifact-stub-card.json +115 -0
- package/corpus/chunks/agent-canvas-shell.json +305 -0
- package/corpus/chunks/agent-citations-source-chips.json +82 -0
- package/corpus/chunks/agent-command-palette-search.json +120 -0
- package/corpus/chunks/agent-cost-detailed.json +260 -0
- package/corpus/chunks/agent-cost-inline.json +78 -0
- package/corpus/chunks/agent-memory-detail.json +181 -0
- package/corpus/chunks/agent-memory-editor.json +173 -0
- package/corpus/chunks/agent-memory-list.json +207 -0
- package/corpus/chunks/agent-pipeline-status-stages.json +61 -0
- package/corpus/chunks/agent-prompt-card.json +179 -0
- package/corpus/chunks/agent-prompt-library-grid.json +341 -0
- package/corpus/chunks/agent-prompt-picker.json +282 -0
- package/corpus/chunks/agent-rate-limit.json +100 -0
- package/corpus/chunks/agent-reasoning-collapsed.json +128 -0
- package/corpus/chunks/agent-tool-call-accordion.json +109 -0
- package/corpus/chunks/agent-tool-call-collapsed.json +98 -0
- package/corpus/chunks/agent-tool-call-error.json +112 -0
- package/corpus/chunks/agent-tool-call-result.json +145 -0
- package/corpus/chunks/agent-tool-call-running.json +85 -0
- package/corpus/chunks/agent-tool-call-success.json +137 -0
- package/corpus/chunks/agent-trace-timeline.json +244 -0
- package/corpus/chunks/ai-streaming-response.json +147 -0
- package/corpus/chunks/alert-banner-stack.json +78 -0
- package/corpus/chunks/alert-banner.json +55 -0
- package/corpus/chunks/alert-dialog-simple.json +72 -0
- package/corpus/chunks/alert-dialog-typed.json +107 -0
- package/corpus/chunks/alert-dialog-unsaved.json +81 -0
- package/corpus/chunks/analytics-chart.json +213 -0
- package/corpus/chunks/analytics-sparklines-dashboard.json +259 -0
- package/corpus/chunks/anchor-bar-selection-bar.json +226 -0
- package/corpus/chunks/api-key-table.json +148 -0
- package/corpus/chunks/api-keys-create.json +140 -0
- package/corpus/chunks/api-keys-list.json +271 -0
- package/corpus/chunks/app-nav-badges-counts.json +77 -0
- package/corpus/chunks/app-nav-badges-group-rollup-badges.json +100 -0
- package/corpus/chunks/app-nav-badges-plan-tiers.json +76 -0
- package/corpus/chunks/app-nav-badges-status-callouts.json +75 -0
- package/corpus/chunks/app-nav-full-example.json +195 -0
- package/corpus/chunks/app-nav-groups.json +103 -0
- package/corpus/chunks/app-nav-items.json +74 -0
- package/corpus/chunks/app-nav-labels-and-dividers.json +92 -0
- package/corpus/chunks/app-nav-spacer.json +77 -0
- package/corpus/chunks/app-product-listing-card.json +214 -0
- package/corpus/chunks/approvals-detail.json +240 -0
- package/corpus/chunks/approvals-queue.json +321 -0
- package/corpus/chunks/audit-log-basic.json +184 -0
- package/corpus/chunks/audit-log.json +174 -0
- package/corpus/chunks/auth-account-deleted-actions.json +51 -0
- package/corpus/chunks/auth-account-deleted.json +202 -0
- package/corpus/chunks/auth-card-content.json +260 -0
- package/corpus/chunks/auth-card-header.json +205 -0
- package/corpus/chunks/auth-email-entry.json +65 -0
- package/corpus/chunks/auth-email-verify-confirm.json +52 -0
- package/corpus/chunks/auth-email-verify.json +196 -0
- package/corpus/chunks/auth-forbidden-actions.json +59 -0
- package/corpus/chunks/auth-forbidden.json +203 -0
- package/corpus/chunks/auth-invite-actions.json +49 -0
- package/corpus/chunks/auth-invite-team-card.json +86 -0
- package/corpus/chunks/auth-link-expired-form.json +65 -0
- package/corpus/chunks/auth-link-expired.json +196 -0
- package/corpus/chunks/auth-locked-account.json +211 -0
- package/corpus/chunks/auth-locked-recovery-options.json +60 -0
- package/corpus/chunks/auth-mfa-enrollment-submit.json +54 -0
- package/corpus/chunks/auth-mfa-enrollment.json +284 -0
- package/corpus/chunks/auth-mfa-fallback-actions.json +52 -0
- package/corpus/chunks/auth-mfa-recovery.json +61 -0
- package/corpus/chunks/auth-new-password-form.json +75 -0
- package/corpus/chunks/auth-new-password.json +217 -0
- package/corpus/chunks/auth-oauth-fallback-actions.json +52 -0
- package/corpus/chunks/auth-oauth-interstitial.json +160 -0
- package/corpus/chunks/auth-password-challenge.json +94 -0
- package/corpus/chunks/auth-password-reset-form.json +64 -0
- package/corpus/chunks/auth-password-reset.json +195 -0
- package/corpus/chunks/auth-profile-form.json +72 -0
- package/corpus/chunks/auth-profile-setup.json +194 -0
- package/corpus/chunks/auth-reset-sent.json +188 -0
- package/corpus/chunks/auth-session-expired-actions.json +52 -0
- package/corpus/chunks/auth-session-expired.json +201 -0
- package/corpus/chunks/auth-signin-card-email.json +245 -0
- package/corpus/chunks/auth-signin-card-magic-link.json +147 -0
- package/corpus/chunks/auth-signin-card-mfa.json +231 -0
- package/corpus/chunks/auth-signin-card-otp.json +205 -0
- package/corpus/chunks/auth-signin-card-password.json +264 -0
- package/corpus/chunks/auth-signin-card-recovery.json +218 -0
- package/corpus/chunks/auth-signout-actions.json +51 -0
- package/corpus/chunks/auth-signout.json +184 -0
- package/corpus/chunks/auth-signup-email-entry.json +66 -0
- package/corpus/chunks/auth-signup-entry.json +281 -0
- package/corpus/chunks/auth-signup-social-auths.json +54 -0
- package/corpus/chunks/auth-signup-verify.json +227 -0
- package/corpus/chunks/auth-social-auths.json +62 -0
- package/corpus/chunks/auth-sso-providers.json +55 -0
- package/corpus/chunks/auth-sso-required.json +213 -0
- package/corpus/chunks/auth-team-invite.json +288 -0
- package/corpus/chunks/avatar-group-overflow.json +137 -0
- package/corpus/chunks/avatar-stack-overflow.json +124 -0
- package/corpus/chunks/banner-announcement-beta.json +99 -0
- package/corpus/chunks/banner-announcement-promo.json +102 -0
- package/corpus/chunks/banner-live-update.json +102 -0
- package/corpus/chunks/banner-system-maintenance.json +101 -0
- package/corpus/chunks/banner-system-offline.json +85 -0
- package/corpus/chunks/banner-system-update.json +102 -0
- package/corpus/chunks/bell-menu-empty.json +107 -0
- package/corpus/chunks/bell-menu-unread.json +395 -0
- package/corpus/chunks/billing-cancel-subscription-danger.json +61 -0
- package/corpus/chunks/billing-invoice-history-table.json +75 -0
- package/corpus/chunks/billing-overview.json +202 -0
- package/corpus/chunks/billing-payment-method-card-on-file.json +157 -0
- package/corpus/chunks/billing-progress-label.json +101 -0
- package/corpus/chunks/blog-post-card.json +212 -0
- package/corpus/chunks/breadcrumb-navigation.json +72 -0
- package/corpus/chunks/bulk-action-toolbar-floating.json +199 -0
- package/corpus/chunks/bulk-action-toolbar-swap.json +158 -0
- package/corpus/chunks/bulk-selection-actions-bar.json +162 -0
- package/corpus/chunks/business-address-form.json +953 -0
- package/corpus/chunks/calendar-month-view.json +74 -0
- package/corpus/chunks/card-grid-images.json +459 -0
- package/corpus/chunks/card-header-with-description.json +47 -0
- package/corpus/chunks/card-with-empty-state.json +96 -0
- package/corpus/chunks/card-with-form.json +143 -0
- package/corpus/chunks/card-with-sparkline.json +90 -0
- package/corpus/chunks/card-with-stat-kpi.json +86 -0
- package/corpus/chunks/changelog-feed-basic.json +470 -0
- package/corpus/chunks/chart-in-card-chart-plus-breakdown.json +188 -0
- package/corpus/chunks/chart-in-card-chart-plus-stat.json +89 -0
- package/corpus/chunks/chart-in-card-chart-with-filter-pills.json +124 -0
- package/corpus/chunks/chart-in-card-full-bleed-legend.json +116 -0
- package/corpus/chunks/chart-in-card-full-chart.json +107 -0
- package/corpus/chunks/chart-in-card-sparkline-tile.json +93 -0
- package/corpus/chunks/chart-in-card-stat-with-sparkline.json +73 -0
- package/corpus/chunks/chart-in-card-trend-footer.json +115 -0
- package/corpus/chunks/chart-with-filter-pills.json +169 -0
- package/corpus/chunks/chat-empty-state-hero.json +102 -0
- package/corpus/chunks/chat-message-assistant-byline.json +85 -0
- package/corpus/chunks/chat-message-user-byline.json +84 -0
- package/corpus/chunks/chat-page-shell.json +379 -0
- package/corpus/chunks/chat-streaming-surface.json +169 -0
- package/corpus/chunks/checkout-order-summary-card.json +140 -0
- package/corpus/chunks/code-snippet.json +107 -0
- package/corpus/chunks/col-form-stack.json +93 -0
- package/corpus/chunks/col-heading-body-action.json +79 -0
- package/corpus/chunks/col-stat-label.json +63 -0
- package/corpus/chunks/color-picker-swatches.json +153 -0
- package/corpus/chunks/command-palette.json +327 -0
- package/corpus/chunks/comments-composer.json +158 -0
- package/corpus/chunks/comments-mention-menu.json +237 -0
- package/corpus/chunks/comments-thread.json +344 -0
- package/corpus/chunks/commerce-pricing-tiers.json +401 -0
- package/corpus/chunks/comparison-table.json +246 -0
- package/corpus/chunks/contact-form-card.json +197 -0
- package/corpus/chunks/contact-form.json +157 -0
- package/corpus/chunks/contact-support-form.json +702 -0
- package/corpus/chunks/conversion-funnel-4-step-funnel.json +139 -0
- package/corpus/chunks/conversion-funnel-6step.json +151 -0
- package/corpus/chunks/conversion-funnel-wide-summary.json +192 -0
- package/corpus/chunks/conversion-funnel-with-segment-compare.json +202 -0
- package/corpus/chunks/cta-banner-centered.json +102 -0
- package/corpus/chunks/dashboard-acquisition-panel.json +212 -0
- package/corpus/chunks/dashboard-admin-page.json +104 -0
- package/corpus/chunks/dashboard-audience-kpis.json +165 -0
- package/corpus/chunks/dashboard-audience-panel.json +756 -0
- package/corpus/chunks/dashboard-behavior-panel.json +114 -0
- package/corpus/chunks/dashboard-chart-recent.json +566 -0
- package/corpus/chunks/dashboard-cohort-retention.json +83 -0
- package/corpus/chunks/dashboard-conversion-panel.json +234 -0
- package/corpus/chunks/dashboard-country-list.json +304 -0
- package/corpus/chunks/dashboard-filter-bar.json +118 -0
- package/corpus/chunks/dashboard-funnel.json +142 -0
- package/corpus/chunks/dashboard-notifications-panel.json +423 -0
- package/corpus/chunks/dashboard-overview-panel.json +1644 -0
- package/corpus/chunks/dashboard-page-header.json +166 -0
- package/corpus/chunks/dashboard-pages-table.json +86 -0
- package/corpus/chunks/dashboard-quick-actions.json +116 -0
- package/corpus/chunks/dashboard-reports-panel.json +166 -0
- package/corpus/chunks/dashboard-reports-table.json +138 -0
- package/corpus/chunks/dashboard-storage-card.json +117 -0
- package/corpus/chunks/dashboard-tabs.json +86 -0
- package/corpus/chunks/dashboard-team-actions-storage.json +605 -0
- package/corpus/chunks/dashboard-team-list.json +334 -0
- package/corpus/chunks/dashboard-traffic-channels.json +184 -0
- package/corpus/chunks/dashboard-transactions-table.json +145 -0
- package/corpus/chunks/data-export-history.json +192 -0
- package/corpus/chunks/data-export-request.json +197 -0
- package/corpus/chunks/data-import-wizard.json +391 -0
- package/corpus/chunks/date-range-picker.json +156 -0
- package/corpus/chunks/date-time-picker-form.json +222 -0
- package/corpus/chunks/departments-checkbox-form.json +390 -0
- package/corpus/chunks/destructive-confirm-modal.json +149 -0
- package/corpus/chunks/diff-inline.json +84 -0
- package/corpus/chunks/diff-side-by-side.json +131 -0
- package/corpus/chunks/diff-structured.json +216 -0
- package/corpus/chunks/digest-email-preview.json +374 -0
- package/corpus/chunks/divider-text-label.json +87 -0
- package/corpus/chunks/doc-editor-shell.json +356 -0
- package/corpus/chunks/drawer-2fa-key.json +273 -0
- package/corpus/chunks/drawer-2fa-sms.json +261 -0
- package/corpus/chunks/drawer-2fa-totp.json +385 -0
- package/corpus/chunks/drawer-cancel-sub.json +636 -0
- package/corpus/chunks/drawer-change-plan.json +561 -0
- package/corpus/chunks/drawer-custom-roles.json +696 -0
- package/corpus/chunks/drawer-data-start.json +171 -0
- package/corpus/chunks/drawer-delete-account.json +341 -0
- package/corpus/chunks/drawer-delete-workspace.json +362 -0
- package/corpus/chunks/drawer-discord.json +434 -0
- package/corpus/chunks/drawer-figma.json +401 -0
- package/corpus/chunks/drawer-first-dashboard.json +220 -0
- package/corpus/chunks/drawer-gcal.json +475 -0
- package/corpus/chunks/drawer-github.json +589 -0
- package/corpus/chunks/drawer-invite.json +397 -0
- package/corpus/chunks/drawer-record-detail.json +44 -0
- package/corpus/chunks/drawer-report.json +528 -0
- package/corpus/chunks/drawer-revoke-session.json +331 -0
- package/corpus/chunks/drawer-role.json +190 -0
- package/corpus/chunks/drawer-slack.json +429 -0
- package/corpus/chunks/drawer-smtp.json +476 -0
- package/corpus/chunks/drawer-source.json +294 -0
- package/corpus/chunks/drawer-transaction.json +493 -0
- package/corpus/chunks/drawer-with-create-form.json +43 -0
- package/corpus/chunks/editor-code-pane.json +204 -0
- package/corpus/chunks/editor-page-shell.json +149 -0
- package/corpus/chunks/editor-preview-pane.json +136 -0
- package/corpus/chunks/editor-statusbar-ready.json +99 -0
- package/corpus/chunks/editor-toolbar-import-export.json +195 -0
- package/corpus/chunks/email-inbox-list.json +678 -0
- package/corpus/chunks/empty-state-danger.json +58 -0
- package/corpus/chunks/empty-state-minimal.json +44 -0
- package/corpus/chunks/empty-state-warning.json +53 -0
- package/corpus/chunks/empty-state.json +65 -0
- package/corpus/chunks/error-404-actions.json +54 -0
- package/corpus/chunks/error-404.json +204 -0
- package/corpus/chunks/error-500-actions.json +61 -0
- package/corpus/chunks/error-500.json +220 -0
- package/corpus/chunks/error-maintenance-actions.json +53 -0
- package/corpus/chunks/error-maintenance.json +203 -0
- package/corpus/chunks/error-page-shell.json +132 -0
- package/corpus/chunks/export-flow-async.json +210 -0
- package/corpus/chunks/export-flow-delivery.json +163 -0
- package/corpus/chunks/export-flow-sync.json +162 -0
- package/corpus/chunks/extended-profile-form.json +512 -0
- package/corpus/chunks/faq-accordion.json +123 -0
- package/corpus/chunks/feature-grid-icons.json +314 -0
- package/corpus/chunks/feature-grid-three-cards.json +187 -0
- package/corpus/chunks/feature-toggle-switch-grid.json +213 -0
- package/corpus/chunks/file-upload-dnd.json +166 -0
- package/corpus/chunks/file-upload-field.json +97 -0
- package/corpus/chunks/file-upload-form.json +251 -0
- package/corpus/chunks/filter-bar-active-filters.json +176 -0
- package/corpus/chunks/filter-bar-filter-bar-with-table.json +113 -0
- package/corpus/chunks/filter-bar-saved-views.json +117 -0
- package/corpus/chunks/filter-popover-form.json +137 -0
- package/corpus/chunks/footer-multi-column.json +270 -0
- package/corpus/chunks/footer-primary-only.json +41 -0
- package/corpus/chunks/form-checkbox-group.json +65 -0
- package/corpus/chunks/form-drawer-edit-form.json +178 -0
- package/corpus/chunks/form-drawer-simple-form.json +151 -0
- package/corpus/chunks/form-drawer-tall-form.json +325 -0
- package/corpus/chunks/form-field-email-hint.json +53 -0
- package/corpus/chunks/form-field-range.json +54 -0
- package/corpus/chunks/form-field-required.json +52 -0
- package/corpus/chunks/form-field-select.json +66 -0
- package/corpus/chunks/form-field-textarea.json +51 -0
- package/corpus/chunks/form-field-with-error.json +151 -0
- package/corpus/chunks/form-fields-two-column.json +69 -0
- package/corpus/chunks/form-page-shell.json +146 -0
- package/corpus/chunks/form-switch-toggle.json +41 -0
- package/corpus/chunks/form-system-live-demo.json +123 -0
- package/corpus/chunks/forms-address-autocomplete.json +277 -0
- package/corpus/chunks/forms-address-fields.json +221 -0
- package/corpus/chunks/forms-conditional-reveal.json +195 -0
- package/corpus/chunks/gallery-page-shell.json +444 -0
- package/corpus/chunks/grid-2col-entry-cards.json +140 -0
- package/corpus/chunks/grid-kpi-4col.json +164 -0
- package/corpus/chunks/grid-responsive-kpi.json +165 -0
- package/corpus/chunks/hero-cta-simple.json +107 -0
- package/corpus/chunks/hero-cta-split.json +183 -0
- package/corpus/chunks/hero-section-split.json +111 -0
- package/corpus/chunks/icon-text-row.json +60 -0
- package/corpus/chunks/image-caption-tile.json +99 -0
- package/corpus/chunks/image-carousel.json +156 -0
- package/corpus/chunks/image-thumbnail-grid.json +77 -0
- package/corpus/chunks/image-upload-preview.json +118 -0
- package/corpus/chunks/import-mapping-flow.json +972 -0
- package/corpus/chunks/inline-dialog-rename.json +128 -0
- package/corpus/chunks/inline-dialog-schedule.json +154 -0
- package/corpus/chunks/inline-dialog-status.json +179 -0
- package/corpus/chunks/integrations-api-keys-card-list.json +475 -0
- package/corpus/chunks/integrations-connect-form.json +550 -0
- package/corpus/chunks/integrations-grid.json +141 -0
- package/corpus/chunks/integrations-webhooks-empty-state.json +66 -0
- package/corpus/chunks/inventory-list-stock.json +137 -0
- package/corpus/chunks/invite-members.json +153 -0
- package/corpus/chunks/invoice-line-items.json +493 -0
- package/corpus/chunks/kanban-board-3col.json +713 -0
- package/corpus/chunks/kanban-page-shell.json +671 -0
- package/corpus/chunks/key-value-detail-list.json +242 -0
- package/corpus/chunks/keyboard-shortcut-display.json +250 -0
- package/corpus/chunks/labeled-textarea.json +45 -0
- package/corpus/chunks/leaderboard-table.json +140 -0
- package/corpus/chunks/library-browser-search-filter.json +109 -0
- package/corpus/chunks/linked-record-row.json +61 -0
- package/corpus/chunks/loading-skeleton-placeholder.json +387 -0
- package/corpus/chunks/login-form-card.json +207 -0
- package/corpus/chunks/logo-cloud-trusted-by.json +235 -0
- package/corpus/chunks/map-with-location-list.json +293 -0
- package/corpus/chunks/marketing-hero-cta.json +102 -0
- package/corpus/chunks/marketing-page-shell.json +352 -0
- package/corpus/chunks/masonry-gallery.json +154 -0
- package/corpus/chunks/member-edit-drawer.json +236 -0
- package/corpus/chunks/members-active-table-search-filter.json +184 -0
- package/corpus/chunks/members-pending-invites-cards.json +251 -0
- package/corpus/chunks/members-roles-permissions-list.json +146 -0
- package/corpus/chunks/menu-context-actions.json +113 -0
- package/corpus/chunks/metadata-description-list.json +178 -0
- package/corpus/chunks/modal-create-project-form.json +133 -0
- package/corpus/chunks/modal-preferences-tabs.json +147 -0
- package/corpus/chunks/multi-field-form-validation.json +394 -0
- package/corpus/chunks/nav-menu-icons.json +74 -0
- package/corpus/chunks/newsletter-subscription.json +190 -0
- package/corpus/chunks/notification-badges-feed.json +411 -0
- package/corpus/chunks/notification-preferences-panel.json +238 -0
- package/corpus/chunks/onb-completion.json +139 -0
- package/corpus/chunks/onb-extension-install.json +172 -0
- package/corpus/chunks/onb-hero-welcome.json +156 -0
- package/corpus/chunks/onb-import-picker.json +86 -0
- package/corpus/chunks/onb-mobile-handoff.json +121 -0
- package/corpus/chunks/onb-notification-prefs.json +83 -0
- package/corpus/chunks/onb-persona-picker.json +82 -0
- package/corpus/chunks/onb-provider-tiles.json +137 -0
- package/corpus/chunks/onb-settings-review.json +257 -0
- package/corpus/chunks/onb-step-footer.json +121 -0
- package/corpus/chunks/onb-step-header.json +121 -0
- package/corpus/chunks/onb-step-progress.json +140 -0
- package/corpus/chunks/onb-step-shell.json +380 -0
- package/corpus/chunks/onb-story-pane.json +121 -0
- package/corpus/chunks/onb-tutorial-steps.json +193 -0
- package/corpus/chunks/order-confirmation-success-card.json +177 -0
- package/corpus/chunks/order-tracking-timeline.json +131 -0
- package/corpus/chunks/pagination-controls.json +82 -0
- package/corpus/chunks/pane-settings-sidebar.json +204 -0
- package/corpus/chunks/patient-visit-shell.json +191 -0
- package/corpus/chunks/payment-checkout-form.json +341 -0
- package/corpus/chunks/payment-method-form.json +328 -0
- package/corpus/chunks/period-comparison.json +236 -0
- package/corpus/chunks/permission-matrix-table.json +438 -0
- package/corpus/chunks/permissions-matrix-grid.json +111 -0
- package/corpus/chunks/permissions-matrix-summary.json +157 -0
- package/corpus/chunks/permissions-role-picker-radio.json +107 -0
- package/corpus/chunks/permissions-role-picker-select.json +101 -0
- package/corpus/chunks/permissions-share-link.json +256 -0
- package/corpus/chunks/permissions-share-people.json +297 -0
- package/corpus/chunks/permissions-sharing-scopes.json +109 -0
- package/corpus/chunks/plan-selection-form.json +529 -0
- package/corpus/chunks/playground-a2ui.json +181 -0
- package/corpus/chunks/playground-agent-admin.json +117 -0
- package/corpus/chunks/playground-agent-chat.json +126 -0
- package/corpus/chunks/playground-app-shell.json +488 -0
- package/corpus/chunks/playground-chat.json +265 -0
- package/corpus/chunks/playground-construct-canvas.json +118 -0
- package/corpus/chunks/playground-css-channel.json +487 -0
- package/corpus/chunks/playground-gen-ui.json +224 -0
- package/corpus/chunks/playground-render-preview.json +369 -0
- package/corpus/chunks/playground-streams-bridge.json +437 -0
- package/corpus/chunks/playground-table-toolbar.json +38 -0
- package/corpus/chunks/popover-with-content.json +118 -0
- package/corpus/chunks/pricing-tiers.json +561 -0
- package/corpus/chunks/product-tour.json +158 -0
- package/corpus/chunks/profile-public.json +297 -0
- package/corpus/chunks/progress-tracker-milestones.json +294 -0
- package/corpus/chunks/radio-button-group.json +83 -0
- package/corpus/chunks/rating-stars-review-summary.json +259 -0
- package/corpus/chunks/reactions-bar.json +75 -0
- package/corpus/chunks/reactions-picker.json +245 -0
- package/corpus/chunks/real-time-metrics-dashboard.json +344 -0
- package/corpus/chunks/record-detail-drawer-simple-detail.json +296 -0
- package/corpus/chunks/record-detail-drawer-tabbed-detail.json +443 -0
- package/corpus/chunks/referral-share-link.json +128 -0
- package/corpus/chunks/referral-status.json +243 -0
- package/corpus/chunks/reg-address-form.json +825 -0
- package/corpus/chunks/reg-billing-card.json +210 -0
- package/corpus/chunks/reg-brand-scrape.json +599 -0
- package/corpus/chunks/reg-departments-toggle.json +259 -0
- package/corpus/chunks/reg-extended-profile.json +356 -0
- package/corpus/chunks/reg-final-done.json +457 -0
- package/corpus/chunks/reg-helpdesk-grid.json +571 -0
- package/corpus/chunks/reg-import-picker.json +112 -0
- package/corpus/chunks/reg-integrations-grid.json +418 -0
- package/corpus/chunks/reg-invite-form.json +245 -0
- package/corpus/chunks/reg-legal-entity.json +260 -0
- package/corpus/chunks/reg-org-chart-review.json +891 -0
- package/corpus/chunks/reg-profile-identity.json +188 -0
- package/corpus/chunks/reg-step-footer.json +201 -0
- package/corpus/chunks/reg-step-header.json +201 -0
- package/corpus/chunks/reg-step-progress.json +236 -0
- package/corpus/chunks/reg-step-shell.json +605 -0
- package/corpus/chunks/reg-story-pane.json +201 -0
- package/corpus/chunks/reg-success-summary.json +257 -0
- package/corpus/chunks/reg-team-size.json +128 -0
- package/corpus/chunks/reg-usecase-picker.json +104 -0
- package/corpus/chunks/reg-workspace-name.json +159 -0
- package/corpus/chunks/responsive-grid-pattern.json +71 -0
- package/corpus/chunks/responsive-kpi-grid.json +166 -0
- package/corpus/chunks/responsive-row-pattern.json +71 -0
- package/corpus/chunks/responsive-shell-sidebar.json +308 -0
- package/corpus/chunks/responsive-wrap-at-pattern.json +124 -0
- package/corpus/chunks/retention-cohort-default-retention.json +80 -0
- package/corpus/chunks/retention-cohort-stat-pair.json +163 -0
- package/corpus/chunks/retention-cohort-with-legend.json +135 -0
- package/corpus/chunks/revenue-heatmap.json +82 -0
- package/corpus/chunks/role-management.json +272 -0
- package/corpus/chunks/row-action-cluster.json +54 -0
- package/corpus/chunks/row-avatar-name-role.json +71 -0
- package/corpus/chunks/row-icon-label.json +52 -0
- package/corpus/chunks/row-spread-label-value.json +54 -0
- package/corpus/chunks/row-wrap-tags.json +72 -0
- package/corpus/chunks/schedule-meeting-form-card.json +229 -0
- package/corpus/chunks/search-recents-menu.json +195 -0
- package/corpus/chunks/search-results-grouped.json +357 -0
- package/corpus/chunks/search-results-list.json +202 -0
- package/corpus/chunks/search-saved-views.json +356 -0
- package/corpus/chunks/search-with-filters.json +311 -0
- package/corpus/chunks/searchable-picker-modal.json +164 -0
- package/corpus/chunks/section-with-stack.json +48 -0
- package/corpus/chunks/security-active-sessions-devices.json +287 -0
- package/corpus/chunks/security-change-password-form.json +102 -0
- package/corpus/chunks/security-delete-account-danger.json +79 -0
- package/corpus/chunks/segmented-control-billing-tabs.json +164 -0
- package/corpus/chunks/select-multiple-preselected.json +70 -0
- package/corpus/chunks/settings-2fa-setup.json +307 -0
- package/corpus/chunks/settings-admin-page.json +1205 -0
- package/corpus/chunks/settings-appearance-primitives.json +145 -0
- package/corpus/chunks/settings-appearance-theme-panel.json +55 -0
- package/corpus/chunks/settings-appearance.json +81 -0
- package/corpus/chunks/settings-danger-zone-delete-workspace.json +93 -0
- package/corpus/chunks/settings-general-form.json +69 -0
- package/corpus/chunks/settings-integrations.json +298 -0
- package/corpus/chunks/settings-members-invite.json +112 -0
- package/corpus/chunks/settings-notification-activity-checkboxes.json +108 -0
- package/corpus/chunks/settings-notification-channels-switches.json +101 -0
- package/corpus/chunks/settings-page-shell.json +190 -0
- package/corpus/chunks/settings-privacy.json +83 -0
- package/corpus/chunks/settings-profile-security.json +122 -0
- package/corpus/chunks/settings-toggle-switches.json +66 -0
- package/corpus/chunks/sidebar-nav.json +120 -0
- package/corpus/chunks/sidebar-navigation-panel.json +165 -0
- package/corpus/chunks/signup-form-card.json +218 -0
- package/corpus/chunks/signup-team-size-form.json +259 -0
- package/corpus/chunks/single-select-card-form.json +231 -0
- package/corpus/chunks/slider-range-controls.json +119 -0
- package/corpus/chunks/social-media-post-card.json +159 -0
- package/corpus/chunks/sortable-list.json +307 -0
- package/corpus/chunks/sortable-search-paginate-table.json +162 -0
- package/corpus/chunks/split-pane-editor.json +146 -0
- package/corpus/chunks/stack-avatar-badge-overlay.json +53 -0
- package/corpus/chunks/stack-image-shimmer.json +51 -0
- package/corpus/chunks/stat-cards-kpi-dashboard.json +178 -0
- package/corpus/chunks/stats-band-big-numbers.json +175 -0
- package/corpus/chunks/status-dashboard.json +282 -0
- package/corpus/chunks/stepper-form-wizard.json +165 -0
- package/corpus/chunks/subscription-status-renewal-card.json +285 -0
- package/corpus/chunks/survey-rating-form.json +165 -0
- package/corpus/chunks/swiper-product-carousel.json +349 -0
- package/corpus/chunks/swiper-testimonial-carousel.json +279 -0
- package/corpus/chunks/table-empty-state.json +116 -0
- package/corpus/chunks/table-inline-edit-row.json +269 -0
- package/corpus/chunks/table-spreadsheet-cells.json +334 -0
- package/corpus/chunks/table-toolbar-no-search.json +42 -0
- package/corpus/chunks/table-toolbar-with-table.json +208 -0
- package/corpus/chunks/table-with-toolbar-card.json +80 -0
- package/corpus/chunks/tabs-with-panels.json +187 -0
- package/corpus/chunks/tag-chips-filter.json +100 -0
- package/corpus/chunks/team-invite-form.json +380 -0
- package/corpus/chunks/team-members-list.json +341 -0
- package/corpus/chunks/testimonial-grid.json +269 -0
- package/corpus/chunks/testimonial-pull-quote.json +137 -0
- package/corpus/chunks/testimonials-avatar-cards.json +286 -0
- package/corpus/chunks/timeline-events.json +89 -0
- package/corpus/chunks/timezone-selector-basic.json +99 -0
- package/corpus/chunks/timezone-selector-preview.json +104 -0
- package/corpus/chunks/toolbar-icons.json +216 -0
- package/corpus/chunks/toolbar-rich-text-editor.json +230 -0
- package/corpus/chunks/toolbar-tooltips.json +191 -0
- package/corpus/chunks/tooltip-hover-button.json +106 -0
- package/corpus/chunks/tree-file-explorer.json +136 -0
- package/corpus/chunks/tree-table-basic.json +171 -0
- package/corpus/chunks/trial-banner.json +158 -0
- package/corpus/chunks/url-import-form.json +728 -0
- package/corpus/chunks/usage-quota-meter-card.json +217 -0
- package/corpus/chunks/user-identity-row.json +81 -0
- package/corpus/chunks/user-onboarding-checklist.json +301 -0
- package/corpus/chunks/user-profile-card.json +192 -0
- package/corpus/chunks/users-table-badge.json +135 -0
- package/corpus/chunks/verification-document-upload.json +179 -0
- package/corpus/chunks/verification-status.json +97 -0
- package/corpus/chunks/verification-stepper.json +111 -0
- package/corpus/chunks/video-player-controls.json +120 -0
- package/corpus/chunks/webhook-config.json +209 -0
- package/corpus/chunks/webhooks-list.json +204 -0
- package/corpus/chunks/wizard-drawer-three-step-wizard.json +443 -0
- package/corpus/manifest.d.ts +4 -0
- package/corpus/manifest.json +6 -0
- package/corpus/scripts/chunk-library.d.ts +4 -0
- package/corpus/scripts/chunk-library.js +335 -0
- package/node-shims.d.ts +48 -0
- package/package.json +215 -0
- package/retrieval/CHANGELOG.md +1073 -0
- package/retrieval/README.md +71 -0
- package/retrieval/anti-patterns.js +189 -0
- package/retrieval/authoring/index.d.ts +4 -0
- package/retrieval/authoring/index.js +9 -0
- package/retrieval/authoring/web-research.js +220 -0
- package/retrieval/catalog.js +250 -0
- package/retrieval/component-catalog.js +168 -0
- package/retrieval/component-entry.js +80 -0
- package/retrieval/context-assembler.js +174 -0
- package/retrieval/domain-router.js +417 -0
- package/retrieval/embedding/chunk-embedding-retriever.js +117 -0
- package/retrieval/embedding/embedding-provider.js +72 -0
- package/retrieval/embedding/index.d.ts +4 -0
- package/retrieval/embedding/index.js +2 -0
- package/retrieval/feedback/dialog-recorder.js +107 -0
- package/retrieval/feedback/feedback-analyzer.js +180 -0
- package/retrieval/feedback/feedback-store.js +194 -0
- package/retrieval/feedback/feedback.js +117 -0
- package/retrieval/feedback/gap-registry.js +80 -0
- package/retrieval/feedback/human-signal.js +113 -0
- package/retrieval/feedback/index.d.ts +4 -0
- package/retrieval/feedback/index.js +24 -0
- package/retrieval/feedback/submit-feedback.js +45 -0
- package/retrieval/index.d.ts +4 -0
- package/retrieval/index.js +53 -0
- package/retrieval/intent/clarity.js +139 -0
- package/retrieval/intent/decomposer.js +124 -0
- package/retrieval/intent/index.d.ts +4 -0
- package/retrieval/intent/index.js +18 -0
- package/retrieval/intent/intent-alignment.js +172 -0
- package/retrieval/intent/intent-categorizer.js +69 -0
- package/retrieval/intent/intent-gate.js +96 -0
- package/retrieval/intent/prompt-analyzer.js +162 -0
- package/retrieval/wiring-catalog.js +168 -0
- package/validate/catalog-validator.d.ts +4 -0
- package/validate/catalog-validator.js +327 -0
- package/validate/semantic/cache.js +54 -0
- package/validate/semantic/classify-intent.js +128 -0
- package/validate/semantic/index.js +163 -0
- package/validate/semantic/intent-specs.js +162 -0
- package/validate/semantic/judge.js +180 -0
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transpiler Maps — Static tag mapping tables and attribute extractors
|
|
3
|
+
* for the HTML → A2UI transpiler.
|
|
4
|
+
*
|
|
5
|
+
* Three mapping layers:
|
|
6
|
+
* 1. Reverse A2UI registry (tag → type, for *-n elements)
|
|
7
|
+
* 2. HTML tag map (native HTML → A2UI type)
|
|
8
|
+
* 3. Input type / ARIA role sub-maps
|
|
9
|
+
*
|
|
10
|
+
* §163 (v0.5.4) — Prop-fidelity fix: extractProps() now runs a
|
|
11
|
+
* catalog-driven generic pass AFTER the legacy per-type blocks. The
|
|
12
|
+
* catalog (`@adia-ai/gen-ui/corpus`'s v0.9 sidecars) is the single source
|
|
13
|
+
* of truth for which attributes are first-class props per component
|
|
14
|
+
* type. Pre-§163, the per-type blocks hardcoded an allowlist that
|
|
15
|
+
* omitted `label`, `icon`, literal `variant=`, and similar — see
|
|
16
|
+
* `.brain/postmortems/2026-05-14-lossy-transpiler-boundary.md`.
|
|
17
|
+
* The catalog-driven pass closes the drift class: when a new prop is
|
|
18
|
+
* added to the catalog (regenerated from `<name>.yaml`), the extractor
|
|
19
|
+
* picks it up automatically without manual sync.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import catalogData from '../../corpus/catalog-a2ui_0_9.json' with { type: 'json' };
|
|
23
|
+
|
|
24
|
+
import { registry } from '@adia-ai/a2ui';
|
|
25
|
+
|
|
26
|
+
// ── §163 Catalog-driven prop schema ──────────────────────────────────────
|
|
27
|
+
//
|
|
28
|
+
// Build CATALOG_PROPS at module-init by reading the v0.9 catalog. Each
|
|
29
|
+
// component's `properties` block declares its first-class props with
|
|
30
|
+
// type hints (string / boolean / number / enum). The transpiler uses
|
|
31
|
+
// this map to extract any prop the catalog declares, closing the
|
|
32
|
+
// pre-§163 drift class where the per-type allowlists (lines ~155-249
|
|
33
|
+
// below) omitted `label`, `icon`, literal `variant=`, etc.
|
|
34
|
+
//
|
|
35
|
+
// Aliasing: the runtime registry maps multiple A2UI type names to the
|
|
36
|
+
// same tag (e.g. CheckBox → check-ui, Toggle → switch-ui, Select →
|
|
37
|
+
// select-ui = ChoicePicker). The catalog is keyed by ONE canonical
|
|
38
|
+
// name per tag (e.g. `Check`, `Switch`, `ChoicePicker`). We build an
|
|
39
|
+
// alias map below so `extractProps(el, 'CheckBox')` resolves to the
|
|
40
|
+
// `Check` catalog entry.
|
|
41
|
+
|
|
42
|
+
// TKT-0010: dynamic props are compiled to a bare `$ref` (DynamicString /
|
|
43
|
+
// DynamicNumber / DynamicBoolean / DynamicStringList / DynamicObjectList),
|
|
44
|
+
// which carries no inline `type` — so `pdef.type || 'string'` below silently
|
|
45
|
+
// treated EVERY dynamic array prop (Chart.data, Table.data) as a string,
|
|
46
|
+
// copying the raw `data='[...]'` attribute text through unparsed instead of
|
|
47
|
+
// JSON-parsing it into a real array. Resolve the ref name to its primitive
|
|
48
|
+
// kind first so extractCatalogProps' array branch actually fires.
|
|
49
|
+
const REF_TYPE_MAP = {
|
|
50
|
+
DynamicString: 'string',
|
|
51
|
+
DynamicNumber: 'number',
|
|
52
|
+
DynamicBoolean: 'boolean',
|
|
53
|
+
DynamicStringList: 'array',
|
|
54
|
+
DynamicObjectList: 'array',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/** @type {Map<string, {props: Map<string, {type: string, enum?: string[]}>, canonical: string}>} */
|
|
58
|
+
const CATALOG_PROPS = (() => {
|
|
59
|
+
const map = new Map();
|
|
60
|
+
const components = catalogData?.components || {};
|
|
61
|
+
for (const [name, def] of Object.entries(components)) {
|
|
62
|
+
const props = def?.properties || {};
|
|
63
|
+
const propMap = new Map();
|
|
64
|
+
for (const [pname, pdef] of Object.entries(props)) {
|
|
65
|
+
// Skip internal/computed props that aren't HTML attributes
|
|
66
|
+
if (pname === 'component' || pname === 'textContent') continue;
|
|
67
|
+
if (typeof pdef !== 'object' || !pdef) continue;
|
|
68
|
+
let type = pdef.type;
|
|
69
|
+
if (!type && typeof pdef.$ref === 'string') {
|
|
70
|
+
const refName = pdef.$ref.split('/').pop();
|
|
71
|
+
type = REF_TYPE_MAP[refName];
|
|
72
|
+
}
|
|
73
|
+
propMap.set(pname, {
|
|
74
|
+
type: type || 'string',
|
|
75
|
+
enum: pdef.enum || null,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
map.set(name, { props: propMap, canonical: name });
|
|
79
|
+
}
|
|
80
|
+
return map;
|
|
81
|
+
})();
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Map an A2UI type name (which may be an alias used by the runtime
|
|
85
|
+
* registry but not the catalog) to the canonical catalog name.
|
|
86
|
+
*
|
|
87
|
+
* Examples (driven by runtime/registry.js mappings):
|
|
88
|
+
* CheckBox → Check (registry: CheckBox→check-ui; catalog: Check)
|
|
89
|
+
* Toggle → Switch (registry: Toggle→switch-ui; catalog: Switch)
|
|
90
|
+
* Select → ChoicePicker (registry: Select→select-ui; catalog: ChoicePicker)
|
|
91
|
+
*
|
|
92
|
+
* Strategy: for every registry alias type, find the catalog entry whose
|
|
93
|
+
* tag (= kebab-cased catalog name + '-ui', or registry forward-lookup)
|
|
94
|
+
* matches the alias's runtime tag. The catalog often uses a name that
|
|
95
|
+
* is NOT in the registry as a forward entry (e.g. `Check` is in the
|
|
96
|
+
* catalog but the registry only has `CheckBox → check-ui`).
|
|
97
|
+
*
|
|
98
|
+
* Cached at module-init.
|
|
99
|
+
*/
|
|
100
|
+
const TYPE_ALIAS = (() => {
|
|
101
|
+
const m = new Map();
|
|
102
|
+
// Pre-pass: every catalog name maps to itself (catalog names ARE valid A2UI types
|
|
103
|
+
// even when the runtime registry doesn't carry them as forward entries — e.g.
|
|
104
|
+
// `Check` is in catalog but registry only has `CheckBox → check-ui`).
|
|
105
|
+
for (const catName of CATALOG_PROPS.keys()) {
|
|
106
|
+
m.set(catName, catName);
|
|
107
|
+
}
|
|
108
|
+
// First pass: direct match (typeName IS the catalog canonical)
|
|
109
|
+
for (const typeName of registry.keys()) {
|
|
110
|
+
if (CATALOG_PROPS.has(typeName)) {
|
|
111
|
+
m.set(typeName, typeName);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Second pass: type's tag matches another registry entry that's in the catalog
|
|
115
|
+
for (const [typeName, tagName] of registry.entries()) {
|
|
116
|
+
if (m.has(typeName)) continue;
|
|
117
|
+
for (const [otherType, otherTag] of registry.entries()) {
|
|
118
|
+
if (otherTag === tagName && CATALOG_PROPS.has(otherType)) {
|
|
119
|
+
m.set(typeName, otherType);
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Third pass: derive canonical from tag — `check-ui` → `Check`,
|
|
125
|
+
// `switch-ui` → `Switch`. The catalog often has the canonical
|
|
126
|
+
// PascalCase that the registry doesn't list as a forward entry.
|
|
127
|
+
// We convert tag kebab → PascalCase and check the catalog.
|
|
128
|
+
for (const [typeName, tagName] of registry.entries()) {
|
|
129
|
+
if (m.has(typeName)) continue;
|
|
130
|
+
// 'check-ui' → 'Check'; 'switch-ui' → 'Switch'; 'list-item-ui' → 'ListItem'
|
|
131
|
+
const stripped = tagName.replace(/-ui$/, '');
|
|
132
|
+
const pascal = stripped.split('-').map(s => s[0]?.toUpperCase() + s.slice(1)).join('');
|
|
133
|
+
if (CATALOG_PROPS.has(pascal)) {
|
|
134
|
+
m.set(typeName, pascal);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return m;
|
|
138
|
+
})();
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* §163 generic extractor: pull every catalog-declared prop from the
|
|
142
|
+
* element's attributes. Type-aware (booleans become true on presence,
|
|
143
|
+
* numbers parse, enums validate optimistically).
|
|
144
|
+
*
|
|
145
|
+
* Runs AFTER the legacy per-type blocks below — so type-specific
|
|
146
|
+
* extraction (e.g. Button.text from textContent, Image.alt) wins on
|
|
147
|
+
* conflict. The generic pass FILLS IN props the legacy blocks miss
|
|
148
|
+
* (the prop-fidelity gap this fix closes).
|
|
149
|
+
*
|
|
150
|
+
* @param {object} el — DOM element or MinimalElement
|
|
151
|
+
* @param {string} a2uiType — Resolved A2UI type name (may be alias)
|
|
152
|
+
* @returns {Record<string, unknown>}
|
|
153
|
+
*/
|
|
154
|
+
function extractCatalogProps(el, a2uiType) {
|
|
155
|
+
const canonical = TYPE_ALIAS.get(a2uiType);
|
|
156
|
+
if (!canonical) return {};
|
|
157
|
+
const schema = CATALOG_PROPS.get(canonical);
|
|
158
|
+
if (!schema) return {};
|
|
159
|
+
const attr = (name) => el.getAttribute?.(name) ?? el.attributes?.get?.(name) ?? null;
|
|
160
|
+
const props = {};
|
|
161
|
+
for (const [pname, pdef] of schema.props.entries()) {
|
|
162
|
+
// gh#853: camelCase catalog prop names (e.g. `channelEnabled`,
|
|
163
|
+
// `hrefPattern`) are authored as kebab-case HTML attributes per the
|
|
164
|
+
// yaml's own `attribute:` override — but that override isn't preserved
|
|
165
|
+
// into the generated catalog (catalog-a2ui_0_9.json keys stay
|
|
166
|
+
// camelCase), and HTML attribute names are always lowercased on parse
|
|
167
|
+
// (`channelenabled` !== `channelEnabled`), so the direct lookup below
|
|
168
|
+
// silently missed every one of them. Fall back to the kebab-cased form.
|
|
169
|
+
const kebab = pname.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
|
|
170
|
+
const raw = attr(pname) ?? (kebab !== pname ? attr(kebab) : null);
|
|
171
|
+
if (raw === null || raw === undefined) continue;
|
|
172
|
+
|
|
173
|
+
if (pdef.type === 'boolean') {
|
|
174
|
+
// HTML boolean attr convention: presence (incl. empty string) = true.
|
|
175
|
+
// <input required> → raw === '' → true
|
|
176
|
+
// <input required=""> → raw === '' → true
|
|
177
|
+
// <input required="required"> → raw === 'required' → true
|
|
178
|
+
// <input required="false"> → raw === 'false' → false (defensive)
|
|
179
|
+
props[pname] = raw !== 'false';
|
|
180
|
+
} else if (pdef.type === 'number' || pdef.type === 'integer') {
|
|
181
|
+
if (raw === '') continue;
|
|
182
|
+
const n = Number(raw);
|
|
183
|
+
props[pname] = Number.isFinite(n) ? n : raw;
|
|
184
|
+
} else if (pdef.type === 'array') {
|
|
185
|
+
// TKT-0010: declarative JSON-array attribute (e.g. chart-ui/table-ui's
|
|
186
|
+
// data='[{...}]'), hydrated once at connect per those components' own
|
|
187
|
+
// yaml docs. Parse it — the raw string never satisfies the catalog's
|
|
188
|
+
// array schema, and per chart.yaml's own contract a non-array value
|
|
189
|
+
// is meant to render empty, so a parse failure/non-array is skipped,
|
|
190
|
+
// not passed through.
|
|
191
|
+
if (raw === '') continue;
|
|
192
|
+
try {
|
|
193
|
+
const parsed = JSON.parse(raw);
|
|
194
|
+
if (Array.isArray(parsed)) props[pname] = parsed;
|
|
195
|
+
} catch { /* not valid JSON — skip */ }
|
|
196
|
+
} else if (pdef.type === 'object') {
|
|
197
|
+
// gh#853 sibling of the array branch above: object-typed props (e.g.
|
|
198
|
+
// InvoiceDetail.invoice, NotificationPreferences.channelEnabled) are
|
|
199
|
+
// JSON-encoded HTML attributes too — same declarative-data convention,
|
|
200
|
+
// just a plain object instead of an array.
|
|
201
|
+
if (raw === '') continue;
|
|
202
|
+
try {
|
|
203
|
+
const parsed = JSON.parse(raw);
|
|
204
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) props[pname] = parsed;
|
|
205
|
+
} catch { /* not valid JSON — skip */ }
|
|
206
|
+
} else {
|
|
207
|
+
// string (incl. enum) — skip empty
|
|
208
|
+
if (raw === '') continue;
|
|
209
|
+
props[pname] = raw;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return props;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// ── Alias types to skip in reverse registry (prefer primary type) ────────
|
|
216
|
+
|
|
217
|
+
const ALIAS_TYPES = new Set([
|
|
218
|
+
'Select', 'LoadingIndicator', 'ErrorContainer', 'Keyboard',
|
|
219
|
+
'DatePicker', 'CommandPalette', 'Segmented', 'OTP', 'SideNav', 'IconSource',
|
|
220
|
+
]);
|
|
221
|
+
|
|
222
|
+
// ── Reverse Registry: tag → primary A2UI type ────────────────────────────
|
|
223
|
+
|
|
224
|
+
/** @type {Map<string, string>} */
|
|
225
|
+
export const reverseRegistry = new Map();
|
|
226
|
+
|
|
227
|
+
for (const [type, tag] of registry) {
|
|
228
|
+
if (ALIAS_TYPES.has(type)) continue;
|
|
229
|
+
// First-write wins — skip if tag already mapped (avoids alias overwrite)
|
|
230
|
+
if (!reverseRegistry.has(tag)) {
|
|
231
|
+
reverseRegistry.set(tag, type);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ── HTML Tag → A2UI Type ─────────────────────────────────────────────────
|
|
236
|
+
|
|
237
|
+
/** @type {Record<string, { type: string, props?: Record<string, unknown> }>} */
|
|
238
|
+
export const HTML_TAG_MAP = {
|
|
239
|
+
// §210 (v0.5.7, FEEDBACK-17 §1): map native heading levels to working
|
|
240
|
+
// text-ui variants. Pre-§210 these mapped to `h1`-`h6` strings that
|
|
241
|
+
// text.css had no `:scope[variant=…]` rule for — silent body-default
|
|
242
|
+
// rendering. The retired variants (`h1`-`h6` + `subheading`) were
|
|
243
|
+
// removed from text.yaml/text.d.ts/text.a2ui.json in §210 because no
|
|
244
|
+
// matching tokens shipped. Replacement mapping prefers role tokens
|
|
245
|
+
// that actually render:
|
|
246
|
+
// <h1> → 'display' (largest type — marketing hero)
|
|
247
|
+
// <h2> → 'title' (page title)
|
|
248
|
+
// <h3> → 'heading' (section division)
|
|
249
|
+
// <h4> → 'subsection' (sub-grouping inside a heading section)
|
|
250
|
+
// <h5>, <h6> → 'subsection' (no smaller subsection token ships;
|
|
251
|
+
// consistent fallback over silent
|
|
252
|
+
// body-default)
|
|
253
|
+
h1: { type: 'Text', props: { variant: 'display' } },
|
|
254
|
+
h2: { type: 'Text', props: { variant: 'title' } },
|
|
255
|
+
h3: { type: 'Text', props: { variant: 'heading' } },
|
|
256
|
+
h4: { type: 'Text', props: { variant: 'subsection' } },
|
|
257
|
+
h5: { type: 'Text', props: { variant: 'subsection' } },
|
|
258
|
+
h6: { type: 'Text', props: { variant: 'subsection' } },
|
|
259
|
+
p: { type: 'Text', props: { variant: 'body' } },
|
|
260
|
+
small: { type: 'Text', props: { variant: 'caption' } },
|
|
261
|
+
strong: { type: 'Text', props: { variant: 'body' } },
|
|
262
|
+
em: { type: 'Text', props: { variant: 'body' } },
|
|
263
|
+
blockquote: { type: 'Text', props: { variant: 'body' } },
|
|
264
|
+
code: { type: 'Code' },
|
|
265
|
+
pre: { type: 'Code' },
|
|
266
|
+
kbd: { type: 'Kbd' },
|
|
267
|
+
button: { type: 'Button' },
|
|
268
|
+
select: { type: 'ChoicePicker' },
|
|
269
|
+
textarea: { type: 'TextArea' },
|
|
270
|
+
form: { type: 'FormContainer' },
|
|
271
|
+
img: { type: 'Image' },
|
|
272
|
+
video: { type: 'Embed' },
|
|
273
|
+
iframe: { type: 'Embed' },
|
|
274
|
+
audio: { type: 'Embed' },
|
|
275
|
+
table: { type: 'Table' },
|
|
276
|
+
ul: { type: 'List' },
|
|
277
|
+
ol: { type: 'List' },
|
|
278
|
+
li: { type: 'Text', props: { variant: 'body' } },
|
|
279
|
+
// gh#848 — description lists. `<dl>` IS description-list-ui (it renders a
|
|
280
|
+
// native dl), and its documented children are native `<dt>`/`<dd>`
|
|
281
|
+
// (description-list.yaml slots: "Consumer passes <dt>/<dd> children
|
|
282
|
+
// inline"). Without these three the pair fell to the Unknown fallback and
|
|
283
|
+
// the term/detail grid collapsed into nested containers.
|
|
284
|
+
dl: { type: 'DescriptionList' },
|
|
285
|
+
dt: { type: 'DescriptionTerm' },
|
|
286
|
+
dd: { type: 'DescriptionDetail' },
|
|
287
|
+
// gh#853 — `<figure>` is a self-contained content unit (image + caption),
|
|
288
|
+
// the same "self-contained block" semantic already given to `<article>`
|
|
289
|
+
// (→ Card). `<figcaption>` is the annotation UNDER that unit — text.yaml's
|
|
290
|
+
// own `caption` variant docstring names this exact use case ("Annotation
|
|
291
|
+
// under a primary line … Use for image captions, footnotes."), so it maps
|
|
292
|
+
// there rather than falling to the generic `body` variant every other
|
|
293
|
+
// untyped inline tag gets.
|
|
294
|
+
figure: { type: 'Card' },
|
|
295
|
+
figcaption: { type: 'Text', props: { variant: 'caption' } },
|
|
296
|
+
// gh#853 — `<s>` (strikethrough) has no dedicated A2UI decoration prop
|
|
297
|
+
// (text.yaml carries no strike/decoration prop today — a platform gap
|
|
298
|
+
// beyond this tag-mapping fix). Until one exists, treat it as the phrasing
|
|
299
|
+
// content it is, same as the `strong`/`em`/`blockquote` mappings above.
|
|
300
|
+
s: { type: 'Text', props: { variant: 'body' } },
|
|
301
|
+
nav: { type: 'Nav' },
|
|
302
|
+
aside: { type: 'Sidebar' },
|
|
303
|
+
main: { type: 'Column' },
|
|
304
|
+
article: { type: 'Card' },
|
|
305
|
+
details: { type: 'Accordion' },
|
|
306
|
+
summary: { type: 'Text', props: { variant: 'subsection' } },
|
|
307
|
+
dialog: { type: 'Modal' },
|
|
308
|
+
hr: { type: 'Divider' },
|
|
309
|
+
a: { type: 'Link' }, // §47 — was: Button + variant=ghost (button.yaml line 60: "for inline navigation use `<link-ui>` instead")
|
|
310
|
+
header: { type: 'Header' },
|
|
311
|
+
footer: { type: 'Footer' },
|
|
312
|
+
section: { type: 'Section' },
|
|
313
|
+
label: { type: 'Text', props: { variant: 'body' } },
|
|
314
|
+
span: { type: 'Text', props: { variant: 'body' } },
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
// ── Input Type Sub-Map ───────────────────────────────────────────────────
|
|
318
|
+
|
|
319
|
+
/** @type {Record<string, { type: string, props?: Record<string, unknown> }>} */
|
|
320
|
+
export const INPUT_TYPE_MAP = {
|
|
321
|
+
text: { type: 'TextField' },
|
|
322
|
+
email: { type: 'TextField', props: { type: 'email' } },
|
|
323
|
+
password: { type: 'TextField', props: { type: 'password' } },
|
|
324
|
+
number: { type: 'TextField', props: { type: 'number' } },
|
|
325
|
+
tel: { type: 'TextField', props: { type: 'tel' } },
|
|
326
|
+
url: { type: 'TextField', props: { type: 'url' } },
|
|
327
|
+
search: { type: 'Search' },
|
|
328
|
+
checkbox: { type: 'CheckBox' },
|
|
329
|
+
radio: { type: 'Radio' },
|
|
330
|
+
range: { type: 'Slider' },
|
|
331
|
+
date: { type: 'DateTimeInput' },
|
|
332
|
+
time: { type: 'DateTimeInput' },
|
|
333
|
+
'datetime-local': { type: 'DateTimeInput' },
|
|
334
|
+
file: { type: 'Upload' },
|
|
335
|
+
color: { type: 'ColorPicker' },
|
|
336
|
+
submit: { type: 'Button', props: { variant: 'primary', type: 'submit' } },
|
|
337
|
+
reset: { type: 'Button', props: { variant: 'outline', type: 'reset' } },
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
// ── ARIA Role Map ────────────────────────────────────────────────────────
|
|
341
|
+
|
|
342
|
+
/** @type {Record<string, string>} */
|
|
343
|
+
export const ARIA_ROLE_MAP = {
|
|
344
|
+
tablist: 'Tabs',
|
|
345
|
+
tab: 'Tab',
|
|
346
|
+
tabpanel: 'Panel',
|
|
347
|
+
alert: 'Alert',
|
|
348
|
+
alertdialog: 'Dialog',
|
|
349
|
+
dialog: 'Modal',
|
|
350
|
+
navigation: 'Nav',
|
|
351
|
+
progressbar: 'Progress',
|
|
352
|
+
slider: 'Slider',
|
|
353
|
+
switch: 'Toggle',
|
|
354
|
+
menu: 'Menu',
|
|
355
|
+
menubar: 'Menu',
|
|
356
|
+
toolbar: 'Toolbar',
|
|
357
|
+
tooltip: 'Tooltip',
|
|
358
|
+
search: 'Search',
|
|
359
|
+
banner: 'Header',
|
|
360
|
+
contentinfo: 'Footer',
|
|
361
|
+
complementary: 'Sidebar',
|
|
362
|
+
};
|
|
363
|
+
|
|
364
|
+
// ── Skip Tags ────────────────────────────────────────────────────────────
|
|
365
|
+
|
|
366
|
+
export const SKIP_TAGS = new Set([
|
|
367
|
+
'script', 'style', 'link', 'meta', 'head', 'br', 'wbr',
|
|
368
|
+
'noscript', 'template', 'slot', 'svg', 'path', 'circle',
|
|
369
|
+
'rect', 'line', 'polyline', 'polygon', 'g', 'defs', 'use',
|
|
370
|
+
]);
|
|
371
|
+
|
|
372
|
+
// ── Attribute Extractors ─────────────────────────────────────────────────
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Extract A2UI props from an HTML element based on the resolved A2UI type.
|
|
376
|
+
*
|
|
377
|
+
* @param {object} el — DOM element or MinimalElement
|
|
378
|
+
* @param {string} a2uiType — Resolved A2UI type name
|
|
379
|
+
* @returns {Record<string, unknown>}
|
|
380
|
+
*/
|
|
381
|
+
export function extractProps(el, a2uiType) {
|
|
382
|
+
const props = {};
|
|
383
|
+
const attr = (name) => el.getAttribute?.(name) ?? el.attributes?.get?.(name) ?? null;
|
|
384
|
+
|
|
385
|
+
// Universal: preserve [slot] for every element. Slot is a layout-bearing
|
|
386
|
+
// HTML attribute that card-ui / drawer-ui / etc. depend on via :has(> [slot])
|
|
387
|
+
// grid activation. Yamls don't declare slot as a prop (it's an HTML standard
|
|
388
|
+
// attribute, not a component prop), so the catalog pass below won't pick it up.
|
|
389
|
+
const slotAttr = attr('slot');
|
|
390
|
+
if (slotAttr) props.slot = slotAttr;
|
|
391
|
+
|
|
392
|
+
// Universal: preserve [span] for every element. Span is a layout-bearing
|
|
393
|
+
// attribute grid-ui's child reads via a pure CSS attribute selector
|
|
394
|
+
// (grid.css: `& > [span="3"] { grid-column: span 3; }`) — it belongs to
|
|
395
|
+
// "whatever this grid child happens to be," never to a specific
|
|
396
|
+
// component's own prop schema, so no .yaml declares it and the
|
|
397
|
+
// catalog-driven pass below silently drops it (TKT-0002: collapsed the
|
|
398
|
+
// admin-dashboard Overview/Recent Sales 3:2 split to two equal, unspanned
|
|
399
|
+
// columns).
|
|
400
|
+
const spanAttr = attr('span');
|
|
401
|
+
if (spanAttr) props.span = spanAttr;
|
|
402
|
+
|
|
403
|
+
// §163 (v0.5.4) — Catalog-driven generic extraction FIRST. Fills in
|
|
404
|
+
// every prop the v0.9 catalog declares for this type (label, icon,
|
|
405
|
+
// variant=, etc.). Legacy per-type blocks below run AFTER and can
|
|
406
|
+
// overwrite specific values (e.g. Button.text inferred from
|
|
407
|
+
// textContent when no `text=` attribute is set).
|
|
408
|
+
Object.assign(props, extractCatalogProps(el, a2uiType));
|
|
409
|
+
|
|
410
|
+
// ── Text content (for leaf elements) ──
|
|
411
|
+
if (['Text', 'Kbd', 'Code'].includes(a2uiType)) {
|
|
412
|
+
const text = (el.textContent || '').trim().replace(/\s+/g, ' ');
|
|
413
|
+
if (text) props.textContent = text;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// ── Button ──
|
|
417
|
+
if (a2uiType === 'Button') {
|
|
418
|
+
if (props.text === undefined) {
|
|
419
|
+
const text = (el.textContent || '').trim().replace(/\s+/g, ' ');
|
|
420
|
+
if (text) props.text = text;
|
|
421
|
+
}
|
|
422
|
+
if (props.type === undefined) {
|
|
423
|
+
const type = attr('type');
|
|
424
|
+
if (type && type !== 'button') props.type = type;
|
|
425
|
+
}
|
|
426
|
+
if (props.disabled === undefined && attr('disabled') !== null) props.disabled = true;
|
|
427
|
+
// Variant inference from class (only if generic pass didn't already extract literal `variant=` attr)
|
|
428
|
+
if (props.variant === undefined) {
|
|
429
|
+
const cls = attr('class') || '';
|
|
430
|
+
if (cls.includes('primary')) props.variant = 'primary';
|
|
431
|
+
else if (cls.includes('danger')) props.variant = 'danger';
|
|
432
|
+
else if (cls.includes('ghost')) props.variant = 'ghost';
|
|
433
|
+
else if (cls.includes('outline')) props.variant = 'outline';
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// ── Tag ── (TKT-0004: tag-ui renders its label via CSS attr(text) —
|
|
438
|
+
// tag.yaml documents textContent as routing to the text attribute. The
|
|
439
|
+
// authored form is light-DOM content (<tag-ui size="sm">label</tag-ui>),
|
|
440
|
+
// so fall back to textContent when no text= attribute is set.)
|
|
441
|
+
if (a2uiType === 'Tag' && props.text === undefined) {
|
|
442
|
+
const text = (el.textContent || '').trim().replace(/\s+/g, ' ');
|
|
443
|
+
if (text) props.text = text;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// ── Link ── (§47 — <a> tags map to Link, not Button; carries href, target, rel)
|
|
447
|
+
if (a2uiType === 'Link') {
|
|
448
|
+
const text = (el.textContent || '').trim().replace(/\s+/g, ' ');
|
|
449
|
+
if (text) props.text = text;
|
|
450
|
+
const href = attr('href');
|
|
451
|
+
if (href) props.href = href;
|
|
452
|
+
const target = attr('target');
|
|
453
|
+
if (target) props.target = target;
|
|
454
|
+
const rel = attr('rel');
|
|
455
|
+
if (rel) props.rel = rel;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// ── TextField / Input ──
|
|
459
|
+
if (['TextField', 'Search'].includes(a2uiType)) {
|
|
460
|
+
for (const name of ['placeholder', 'name', 'value', 'pattern', 'min', 'max', 'minlength', 'maxlength', 'autocomplete']) {
|
|
461
|
+
const v = attr(name);
|
|
462
|
+
if (v !== null && v !== '') props[name] = v;
|
|
463
|
+
}
|
|
464
|
+
if (attr('required') !== null) props.required = true;
|
|
465
|
+
if (attr('disabled') !== null) props.disabled = true;
|
|
466
|
+
if (attr('readonly') !== null) props.readonly = true;
|
|
467
|
+
const type = attr('type');
|
|
468
|
+
if (type && type !== 'text') props.type = type;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// ── CheckBox / Toggle / Radio ──
|
|
472
|
+
if (['CheckBox', 'Toggle', 'Radio'].includes(a2uiType)) {
|
|
473
|
+
const name = attr('name');
|
|
474
|
+
if (name) props.name = name;
|
|
475
|
+
const value = attr('value');
|
|
476
|
+
if (value) props.value = value;
|
|
477
|
+
if (attr('checked') !== null) props.checked = true;
|
|
478
|
+
if (attr('disabled') !== null) props.disabled = true;
|
|
479
|
+
if (attr('required') !== null) props.required = true;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// ── Slider ──
|
|
483
|
+
if (a2uiType === 'Slider') {
|
|
484
|
+
for (const name of ['min', 'max', 'value', 'step', 'name']) {
|
|
485
|
+
if (props[name] !== undefined) continue; // catalog pass already filled this
|
|
486
|
+
const v = attr(name);
|
|
487
|
+
if (v !== null && v !== '') props[name] = name === 'step' ? v : Number(v) || v;
|
|
488
|
+
}
|
|
489
|
+
if (props.disabled === undefined && attr('disabled') !== null) props.disabled = true;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// ── Image ──
|
|
493
|
+
if (a2uiType === 'Image') {
|
|
494
|
+
const src = attr('src');
|
|
495
|
+
if (src) props.src = src;
|
|
496
|
+
const alt = attr('alt');
|
|
497
|
+
if (alt) props.alt = alt;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// ── TextArea ──
|
|
501
|
+
if (a2uiType === 'TextArea') {
|
|
502
|
+
for (const name of ['placeholder', 'name', 'rows', 'cols', 'minlength', 'maxlength']) {
|
|
503
|
+
const v = attr(name);
|
|
504
|
+
if (v !== null && v !== '') props[name] = v;
|
|
505
|
+
}
|
|
506
|
+
if (attr('required') !== null) props.required = true;
|
|
507
|
+
if (attr('disabled') !== null) props.disabled = true;
|
|
508
|
+
const text = (el.textContent || '').trim();
|
|
509
|
+
if (text) props.value = text;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// ── Embed ──
|
|
513
|
+
if (a2uiType === 'Embed') {
|
|
514
|
+
const src = attr('src');
|
|
515
|
+
if (src) props.src = src;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// ── Layout (Column, Row, Grid) ──
|
|
519
|
+
if (['Column', 'Row', 'Grid', 'List'].includes(a2uiType)) {
|
|
520
|
+
const gap = attr('gap');
|
|
521
|
+
if (gap) props.gap = gap;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// ── Label extraction from adjacent <label> or aria-label ──
|
|
525
|
+
if (['TextField', 'CheckBox', 'Toggle', 'Radio', 'Slider', 'Search', 'TextArea', 'ChoicePicker', 'DateTimeInput'].includes(a2uiType)) {
|
|
526
|
+
const ariaLabel = attr('aria-label');
|
|
527
|
+
if (ariaLabel) props.label = ariaLabel;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// ── ChoicePicker / Select, Combobox, Command — build the options[]
|
|
531
|
+
// model from declarative <option> / <optgroup> children (FB-79;
|
|
532
|
+
// extended to Combobox per gh#860, to Command per gh#887).
|
|
533
|
+
// <select-ui>/<combobox-ui>/<command-ui> render natively from
|
|
534
|
+
// `el.options = [{value, label, disabled?}]` (select.yaml /
|
|
535
|
+
// combobox.yaml / command.yaml `options`), so the options must
|
|
536
|
+
// travel as a PROP. Without this, the tree walker emits each
|
|
537
|
+
// <option> as a Text child, which the component rejects (renders
|
|
538
|
+
// empty + "ignoring unrecognized child element" warning).
|
|
539
|
+
// command.yaml's option model additionally carries data-icon/
|
|
540
|
+
// data-shortcut per <option> — extractSelectOptions captures those
|
|
541
|
+
// only for Command (withIcons) so ChoicePicker/Combobox's model
|
|
542
|
+
// stays exactly {value, label, disabled?} (no unused fields).
|
|
543
|
+
if (a2uiType === 'ChoicePicker' || a2uiType === 'Combobox' || a2uiType === 'Command') {
|
|
544
|
+
const options = extractSelectOptions(el, { withIcons: a2uiType === 'Command' });
|
|
545
|
+
if (options.length) {
|
|
546
|
+
props.options = options;
|
|
547
|
+
}
|
|
548
|
+
// Mirror <option selected> into the value when not set via attr,
|
|
549
|
+
// matching select-ui/combobox-ui #parseOptions. Command has no
|
|
550
|
+
// `value` prop (command.yaml declares only open/placeholder) — no
|
|
551
|
+
// value to mirror there.
|
|
552
|
+
if (a2uiType !== 'Command' && (props.value === undefined || props.value === '')) {
|
|
553
|
+
const selected = collectSelectedOptionValues(el);
|
|
554
|
+
if (selected.length) {
|
|
555
|
+
// gh#887 adjacent finding: combobox-ui is single-select —
|
|
556
|
+
// first-selected-wins, matching its own #parseOptions (which
|
|
557
|
+
// only sets `preSelected` from the FIRST `<option selected>` it
|
|
558
|
+
// sees). select-ui's [multiple] mode is the one that legitimately
|
|
559
|
+
// comma-joins several selected values.
|
|
560
|
+
props.value = a2uiType === 'Combobox' ? selected[0] : selected.join(',');
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// ── Data attributes pass-through ──
|
|
566
|
+
if (el.attributes) {
|
|
567
|
+
const attrs = el.attributes instanceof Map ? el.attributes : el.attributes;
|
|
568
|
+
if (typeof attrs[Symbol.iterator] === 'function') {
|
|
569
|
+
for (const a of attrs) {
|
|
570
|
+
const name = a.name || a[0];
|
|
571
|
+
const value = a.value || a[1];
|
|
572
|
+
if (name?.startsWith('data-') && name !== 'data-a2ui-id') {
|
|
573
|
+
props[name] = value;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return props;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// ── Select option model (FB-79) ──────────────────────────────────────────
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Build the <select-ui> / <combobox-ui> / <command-ui> options[] model
|
|
586
|
+
* from an element's declarative <option> / <optgroup> children. Mirrors
|
|
587
|
+
* select-ui #parseOptions:
|
|
588
|
+
* <option value disabled>Label</option> → { value, label, disabled? }
|
|
589
|
+
* <optgroup label>…</optgroup> → { label, options: [...] }
|
|
590
|
+
*
|
|
591
|
+
* @param {object} el — DOM element or MinimalElement
|
|
592
|
+
* @param {{withIcons?: boolean}} [opts] — withIcons: also capture
|
|
593
|
+
* data-icon/data-shortcut per <option> (command.yaml's option model,
|
|
594
|
+
* gh#887) — select/combobox's model has no such fields.
|
|
595
|
+
* @returns {Array<object>}
|
|
596
|
+
*/
|
|
597
|
+
function extractSelectOptions(el, { withIcons = false } = {}) {
|
|
598
|
+
const out = [];
|
|
599
|
+
for (const child of (el.children || [])) {
|
|
600
|
+
const ctag = (child.tagName || '').toLowerCase();
|
|
601
|
+
if (ctag === 'option') {
|
|
602
|
+
out.push(optionToModel(child, { withIcons }));
|
|
603
|
+
} else if (ctag === 'optgroup') {
|
|
604
|
+
const label = optionAttr(child, 'label') || '';
|
|
605
|
+
const groupOptions = [];
|
|
606
|
+
for (const opt of (child.children || [])) {
|
|
607
|
+
if ((opt.tagName || '').toLowerCase() === 'option') groupOptions.push(optionToModel(opt, { withIcons }));
|
|
608
|
+
}
|
|
609
|
+
out.push({ label, options: groupOptions });
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
return out;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* @param {object} opt
|
|
617
|
+
* @param {{withIcons?: boolean}} [modelOpts]
|
|
618
|
+
* @returns {{value: string, label: string, disabled?: boolean, icon?: string, shortcut?: string}}
|
|
619
|
+
*/
|
|
620
|
+
function optionToModel(opt, { withIcons = false } = {}) {
|
|
621
|
+
const value = optionAttr(opt, 'value');
|
|
622
|
+
const label = (opt.textContent || '').trim().replace(/\s+/g, ' ');
|
|
623
|
+
const model = { value: value != null ? value : label, label };
|
|
624
|
+
if (optionAttr(opt, 'disabled') !== null) model.disabled = true;
|
|
625
|
+
if (withIcons) {
|
|
626
|
+
const icon = optionAttr(opt, 'data-icon');
|
|
627
|
+
const shortcut = optionAttr(opt, 'data-shortcut');
|
|
628
|
+
if (icon) model.icon = icon;
|
|
629
|
+
if (shortcut) model.shortcut = shortcut;
|
|
630
|
+
}
|
|
631
|
+
return model;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/** Collect values of <option selected> children (recursing <optgroup>). */
|
|
635
|
+
function collectSelectedOptionValues(el) {
|
|
636
|
+
const values = [];
|
|
637
|
+
const walk = (nodes) => {
|
|
638
|
+
for (const child of (nodes || [])) {
|
|
639
|
+
const ctag = (child.tagName || '').toLowerCase();
|
|
640
|
+
if (ctag === 'option') {
|
|
641
|
+
if (optionAttr(child, 'selected') !== null) {
|
|
642
|
+
const v = optionAttr(child, 'value');
|
|
643
|
+
values.push(v != null ? v : (child.textContent || '').trim().replace(/\s+/g, ' '));
|
|
644
|
+
}
|
|
645
|
+
} else if (ctag === 'optgroup') {
|
|
646
|
+
walk(child.children);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
walk(el.children);
|
|
651
|
+
return values;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/** Read an attribute from either a DOM element or a MinimalElement. */
|
|
655
|
+
function optionAttr(el, name) {
|
|
656
|
+
return el.getAttribute?.(name) ?? el.attributes?.get?.(name) ?? null;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
// ── Gap Inference ────────────────────────────────────────────────────────
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Map a pixel gap value to a token size.
|
|
663
|
+
* @param {string} gapValue — CSS gap value (e.g., "8px", "1rem")
|
|
664
|
+
* @returns {string} — "xs" | "sm" | "md" | "lg" | "xl"
|
|
665
|
+
*/
|
|
666
|
+
export function inferGap(gapValue) {
|
|
667
|
+
if (!gapValue) return 'md';
|
|
668
|
+
const px = parseFloat(gapValue);
|
|
669
|
+
if (isNaN(px)) return 'md';
|
|
670
|
+
if (px <= 4) return 'xs';
|
|
671
|
+
if (px <= 8) return 'sm';
|
|
672
|
+
if (px <= 16) return 'md';
|
|
673
|
+
if (px <= 24) return 'lg';
|
|
674
|
+
return 'xl';
|
|
675
|
+
}
|