#
tokens: 43241/50000 3/1634 files (page 80/144)
lines: off (toggle) GitHub
raw markdown copy
This is page 80 of 144. Use http://codebase.md/xmlui-org/xmlui/xmlui/tools/vscode/resources/xmlui-markup-syntax-highlighting.png?lines=false&page={x} to view the full context.

# Directory Structure

```
├── .changeset
│   ├── config.json
│   ├── cyan-tools-design.md
│   ├── every-moments-teach.md
│   ├── fancy-laws-drop.md
│   ├── full-symbols-accept.md
│   └── tricky-zoos-crash.md
├── .eslintrc.cjs
├── .github
│   ├── build-checklist.png
│   ├── ISSUE_TEMPLATE
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows
│       ├── deploy-blog-optimized.yml
│       ├── deploy-blog-swa.yml
│       ├── deploy-blog.yml
│       ├── deploy-docs-optimized.yml
│       ├── deploy-docs-swa.yml
│       ├── deploy-docs.yml
│       ├── prepare-versions.yml
│       ├── release-packages.yml
│       ├── run-all-tests.yml
│       └── run-smoke-tests.yml
├── .gitignore
├── .prettierrc.js
├── .vscode
│   ├── launch.json
│   └── settings.json
├── blog
│   ├── .gitignore
│   ├── .gitkeep
│   ├── CHANGELOG.md
│   ├── extensions.ts
│   ├── index.html
│   ├── index.ts
│   ├── package.json
│   ├── public
│   │   ├── blog
│   │   │   ├── images
│   │   │   │   ├── an-advanced-codefence.gif
│   │   │   │   ├── an-advanced-codefence.mp4
│   │   │   │   ├── blog-page-component.png
│   │   │   │   ├── blog-scrabble.png
│   │   │   │   ├── codefence-runner.png
│   │   │   │   ├── integrated-blog-search.png
│   │   │   │   ├── lorem-ipsum.png
│   │   │   │   ├── playground-checkbox-source.png
│   │   │   │   ├── playground.png
│   │   │   │   ├── use-xmlui-mcp-to-find-a-howto.png
│   │   │   │   └── xmlui-demo-gallery.png
│   │   │   ├── introducing-xmlui.md
│   │   │   ├── lorem-ipsum.md
│   │   │   ├── newest-post.md
│   │   │   ├── older-post.md
│   │   │   ├── xmlui-playground.md
│   │   │   └── xmlui-powered-blog.md
│   │   ├── mockServiceWorker.js
│   │   ├── resources
│   │   │   ├── favicon.ico
│   │   │   ├── files
│   │   │   │   └── for-download
│   │   │   │       └── xmlui
│   │   │   │           └── xmlui-standalone.umd.js
│   │   │   ├── github.svg
│   │   │   ├── llms.txt
│   │   │   ├── logo-dark.svg
│   │   │   ├── logo.svg
│   │   │   ├── pg-popout.svg
│   │   │   ├── rss.svg
│   │   │   └── xmlui-logo.svg
│   │   ├── serve.json
│   │   ├── staticwebapp.config.json
│   │   └── web.config
│   ├── scripts
│   │   ├── download-latest-xmlui.js
│   │   ├── generate-rss.js
│   │   ├── get-releases.js
│   │   └── utils.js
│   ├── src
│   │   ├── components
│   │   │   ├── BlogOverview.xmlui
│   │   │   ├── BlogPage.xmlui
│   │   │   └── PageNotFound.xmlui
│   │   ├── config.ts
│   │   ├── Main.xmlui
│   │   └── themes
│   │       └── blog-theme.ts
│   └── tsconfig.json
├── CONTRIBUTING.md
├── docs
│   ├── .gitignore
│   ├── CHANGELOG.md
│   ├── ComponentRefLinks.txt
│   ├── content
│   │   ├── _meta.json
│   │   ├── components
│   │   │   ├── _meta.json
│   │   │   ├── _overview.md
│   │   │   ├── APICall.md
│   │   │   ├── App.md
│   │   │   ├── AppHeader.md
│   │   │   ├── AppState.md
│   │   │   ├── AutoComplete.md
│   │   │   ├── Avatar.md
│   │   │   ├── Backdrop.md
│   │   │   ├── Badge.md
│   │   │   ├── BarChart.md
│   │   │   ├── Bookmark.md
│   │   │   ├── Breakout.md
│   │   │   ├── Button.md
│   │   │   ├── Card.md
│   │   │   ├── Carousel.md
│   │   │   ├── ChangeListener.md
│   │   │   ├── Checkbox.md
│   │   │   ├── CHStack.md
│   │   │   ├── ColorPicker.md
│   │   │   ├── Column.md
│   │   │   ├── ContentSeparator.md
│   │   │   ├── CVStack.md
│   │   │   ├── DataSource.md
│   │   │   ├── DateInput.md
│   │   │   ├── DatePicker.md
│   │   │   ├── DonutChart.md
│   │   │   ├── DropdownMenu.md
│   │   │   ├── EmojiSelector.md
│   │   │   ├── ExpandableItem.md
│   │   │   ├── FileInput.md
│   │   │   ├── FileUploadDropZone.md
│   │   │   ├── FlowLayout.md
│   │   │   ├── Footer.md
│   │   │   ├── Form.md
│   │   │   ├── FormItem.md
│   │   │   ├── FormSection.md
│   │   │   ├── Fragment.md
│   │   │   ├── H1.md
│   │   │   ├── H2.md
│   │   │   ├── H3.md
│   │   │   ├── H4.md
│   │   │   ├── H5.md
│   │   │   ├── H6.md
│   │   │   ├── Heading.md
│   │   │   ├── HSplitter.md
│   │   │   ├── HStack.md
│   │   │   ├── Icon.md
│   │   │   ├── IFrame.md
│   │   │   ├── Image.md
│   │   │   ├── Items.md
│   │   │   ├── LabelList.md
│   │   │   ├── Legend.md
│   │   │   ├── LineChart.md
│   │   │   ├── Link.md
│   │   │   ├── List.md
│   │   │   ├── Logo.md
│   │   │   ├── Markdown.md
│   │   │   ├── MenuItem.md
│   │   │   ├── MenuSeparator.md
│   │   │   ├── ModalDialog.md
│   │   │   ├── NavGroup.md
│   │   │   ├── NavLink.md
│   │   │   ├── NavPanel.md
│   │   │   ├── NoResult.md
│   │   │   ├── NumberBox.md
│   │   │   ├── Option.md
│   │   │   ├── Page.md
│   │   │   ├── PageMetaTitle.md
│   │   │   ├── Pages.md
│   │   │   ├── Pagination.md
│   │   │   ├── PasswordInput.md
│   │   │   ├── PieChart.md
│   │   │   ├── ProgressBar.md
│   │   │   ├── Queue.md
│   │   │   ├── RadioGroup.md
│   │   │   ├── RealTimeAdapter.md
│   │   │   ├── Redirect.md
│   │   │   ├── Select.md
│   │   │   ├── Slider.md
│   │   │   ├── Slot.md
│   │   │   ├── SpaceFiller.md
│   │   │   ├── Spinner.md
│   │   │   ├── Splitter.md
│   │   │   ├── Stack.md
│   │   │   ├── StickyBox.md
│   │   │   ├── SubMenuItem.md
│   │   │   ├── Switch.md
│   │   │   ├── TabItem.md
│   │   │   ├── Table.md
│   │   │   ├── TableOfContents.md
│   │   │   ├── Tabs.md
│   │   │   ├── Text.md
│   │   │   ├── TextArea.md
│   │   │   ├── TextBox.md
│   │   │   ├── Theme.md
│   │   │   ├── TimeInput.md
│   │   │   ├── Timer.md
│   │   │   ├── ToneChangerButton.md
│   │   │   ├── ToneSwitch.md
│   │   │   ├── Tooltip.md
│   │   │   ├── Tree.md
│   │   │   ├── VSplitter.md
│   │   │   ├── VStack.md
│   │   │   ├── xmlui-animations
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   ├── Animation.md
│   │   │   │   ├── FadeAnimation.md
│   │   │   │   ├── FadeInAnimation.md
│   │   │   │   ├── FadeOutAnimation.md
│   │   │   │   ├── ScaleAnimation.md
│   │   │   │   └── SlideInAnimation.md
│   │   │   ├── xmlui-pdf
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   └── Pdf.md
│   │   │   ├── xmlui-spreadsheet
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   └── Spreadsheet.md
│   │   │   └── xmlui-website-blocks
│   │   │       ├── _meta.json
│   │   │       ├── _overview.md
│   │   │       ├── Carousel.md
│   │   │       ├── HelloMd.md
│   │   │       ├── HeroSection.md
│   │   │       └── ScrollToTop.md
│   │   └── extensions
│   │       ├── _meta.json
│   │       ├── xmlui-animations
│   │       │   ├── _meta.json
│   │       │   ├── _overview.md
│   │       │   ├── Animation.md
│   │       │   ├── FadeAnimation.md
│   │       │   ├── FadeInAnimation.md
│   │       │   ├── FadeOutAnimation.md
│   │       │   ├── ScaleAnimation.md
│   │       │   └── SlideInAnimation.md
│   │       └── xmlui-website-blocks
│   │           ├── _meta.json
│   │           ├── _overview.md
│   │           ├── Carousel.md
│   │           ├── HelloMd.md
│   │           ├── HeroSection.md
│   │           └── ScrollToTop.md
│   ├── extensions.ts
│   ├── index.html
│   ├── index.ts
│   ├── package.json
│   ├── public
│   │   ├── feed.rss
│   │   ├── mockServiceWorker.js
│   │   ├── pages
│   │   │   ├── _meta.json
│   │   │   ├── app-structure.md
│   │   │   ├── build-editor-component.md
│   │   │   ├── build-hello-world-component.md
│   │   │   ├── components-intro.md
│   │   │   ├── context-variables.md
│   │   │   ├── forms.md
│   │   │   ├── globals.md
│   │   │   ├── glossary.md
│   │   │   ├── helper-tags.md
│   │   │   ├── hosted-deployment.md
│   │   │   ├── howto
│   │   │   │   ├── assign-a-complex-json-literal-to-a-component-variable.md
│   │   │   │   ├── chain-a-refetch.md
│   │   │   │   ├── control-cache-invalidation.md
│   │   │   │   ├── debounce-user-input-for-api-calls.md
│   │   │   │   ├── debounce-with-changelistener.md
│   │   │   │   ├── debug-a-component.md
│   │   │   │   ├── delay-a-datasource-until-another-datasource-is-ready.md
│   │   │   │   ├── delegate-a-method.md
│   │   │   │   ├── do-custom-form-validation.md
│   │   │   │   ├── expose-a-method-from-a-component.md
│   │   │   │   ├── filter-and-transform-data-from-an-api.md
│   │   │   │   ├── group-items-in-list-by-a-property.md
│   │   │   │   ├── handle-background-operations.md
│   │   │   │   ├── hide-an-element-until-its-datasource-is-ready.md
│   │   │   │   ├── make-a-set-of-equal-width-cards.md
│   │   │   │   ├── make-a-table-responsive.md
│   │   │   │   ├── make-navpanel-width-responsive.md
│   │   │   │   ├── modify-a-value-reported-in-a-column.md
│   │   │   │   ├── paginate-a-list.md
│   │   │   │   ├── pass-data-to-a-modal-dialog.md
│   │   │   │   ├── react-to-button-click-not-keystrokes.md
│   │   │   │   ├── set-the-initial-value-of-a-select-from-fetched-data.md
│   │   │   │   ├── share-a-modaldialog-across-components.md
│   │   │   │   ├── sync-selections-between-table-and-list-views.md
│   │   │   │   ├── update-ui-optimistically.md
│   │   │   │   ├── use-built-in-form-validation.md
│   │   │   │   └── use-the-same-modaldialog-to-add-or-edit.md
│   │   │   ├── howto.md
│   │   │   ├── intro.md
│   │   │   ├── layout.md
│   │   │   ├── markup.md
│   │   │   ├── mcp.md
│   │   │   ├── modal-dialogs.md
│   │   │   ├── news-and-reviews.md
│   │   │   ├── reactive-intro.md
│   │   │   ├── refactoring.md
│   │   │   ├── routing-and-links.md
│   │   │   ├── samples
│   │   │   │   ├── color-palette.xmlui
│   │   │   │   ├── color-values.xmlui
│   │   │   │   ├── shadow-sizes.xmlui
│   │   │   │   ├── spacing-sizes.xmlui
│   │   │   │   ├── swatch.xmlui
│   │   │   │   ├── theme-gallery-brief.xmlui
│   │   │   │   └── theme-gallery.xmlui
│   │   │   ├── scoping.md
│   │   │   ├── scripting.md
│   │   │   ├── styles-and-themes
│   │   │   │   ├── common-units.md
│   │   │   │   ├── layout-props.md
│   │   │   │   ├── theme-variable-defaults.md
│   │   │   │   ├── theme-variables.md
│   │   │   │   └── themes.md
│   │   │   ├── template-properties.md
│   │   │   ├── test.md
│   │   │   ├── tutorial-01.md
│   │   │   ├── tutorial-02.md
│   │   │   ├── tutorial-03.md
│   │   │   ├── tutorial-04.md
│   │   │   ├── tutorial-05.md
│   │   │   ├── tutorial-06.md
│   │   │   ├── tutorial-07.md
│   │   │   ├── tutorial-08.md
│   │   │   ├── tutorial-09.md
│   │   │   ├── tutorial-10.md
│   │   │   ├── tutorial-11.md
│   │   │   ├── tutorial-12.md
│   │   │   ├── universal-properties.md
│   │   │   ├── user-defined-components.md
│   │   │   ├── vscode.md
│   │   │   ├── working-with-markdown.md
│   │   │   ├── working-with-text.md
│   │   │   ├── xmlui-animations
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   ├── Animation.md
│   │   │   │   ├── FadeAnimation.md
│   │   │   │   ├── FadeInAnimation.md
│   │   │   │   ├── FadeOutAnimation.md
│   │   │   │   ├── ScaleAnimation.md
│   │   │   │   └── SlideInAnimation.md
│   │   │   ├── xmlui-charts
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   ├── BarChart.md
│   │   │   │   ├── DonutChart.md
│   │   │   │   ├── LabelList.md
│   │   │   │   ├── Legend.md
│   │   │   │   ├── LineChart.md
│   │   │   │   └── PieChart.md
│   │   │   ├── xmlui-pdf
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   └── Pdf.md
│   │   │   └── xmlui-spreadsheet
│   │   │       ├── _meta.json
│   │   │       ├── _overview.md
│   │   │       └── Spreadsheet.md
│   │   ├── resources
│   │   │   ├── devdocs
│   │   │   │   ├── debug-proxy-object-2.png
│   │   │   │   ├── debug-proxy-object.png
│   │   │   │   ├── table_editor_01.png
│   │   │   │   ├── table_editor_02.png
│   │   │   │   ├── table_editor_03.png
│   │   │   │   ├── table_editor_04.png
│   │   │   │   ├── table_editor_05.png
│   │   │   │   ├── table_editor_06.png
│   │   │   │   ├── table_editor_07.png
│   │   │   │   ├── table_editor_08.png
│   │   │   │   ├── table_editor_09.png
│   │   │   │   ├── table_editor_10.png
│   │   │   │   ├── table_editor_11.png
│   │   │   │   ├── table-editor-01.png
│   │   │   │   ├── table-editor-02.png
│   │   │   │   ├── table-editor-03.png
│   │   │   │   ├── table-editor-04.png
│   │   │   │   ├── table-editor-06.png
│   │   │   │   ├── table-editor-07.png
│   │   │   │   ├── table-editor-08.png
│   │   │   │   ├── table-editor-09.png
│   │   │   │   └── xmlui-rendering-of-tiptap-markdown.png
│   │   │   ├── favicon.ico
│   │   │   ├── files
│   │   │   │   ├── clients.json
│   │   │   │   ├── daily-revenue.json
│   │   │   │   ├── dashboard-stats.json
│   │   │   │   ├── demo.xmlui
│   │   │   │   ├── demo.xmlui.xs
│   │   │   │   ├── downloads
│   │   │   │   │   └── downloads.json
│   │   │   │   ├── for-download
│   │   │   │   │   ├── index-with-api.html
│   │   │   │   │   ├── index.html
│   │   │   │   │   ├── mockApi.js
│   │   │   │   │   ├── start-darwin.sh
│   │   │   │   │   ├── start-linux.sh
│   │   │   │   │   ├── start.bat
│   │   │   │   │   └── xmlui
│   │   │   │   │       └── xmlui-standalone.umd.js
│   │   │   │   ├── getting-started
│   │   │   │   │   ├── cl-tutorial-final.zip
│   │   │   │   │   ├── cl-tutorial.zip
│   │   │   │   │   ├── cl-tutorial2.zip
│   │   │   │   │   ├── cl-tutorial3.zip
│   │   │   │   │   ├── cl-tutorial4.zip
│   │   │   │   │   ├── cl-tutorial5.zip
│   │   │   │   │   ├── cl-tutorial6.zip
│   │   │   │   │   ├── getting-started.zip
│   │   │   │   │   ├── hello-xmlui.zip
│   │   │   │   │   ├── xmlui-empty.zip
│   │   │   │   │   └── xmlui-starter.zip
│   │   │   │   ├── howto
│   │   │   │   │   └── component-icons
│   │   │   │   │       └── up-arrow.svg
│   │   │   │   ├── invoices.json
│   │   │   │   ├── monthly-status.json
│   │   │   │   ├── news-and-reviews.json
│   │   │   │   ├── products.json
│   │   │   │   ├── releases.json
│   │   │   │   ├── tutorials
│   │   │   │   │   ├── datasource
│   │   │   │   │   │   └── api.ts
│   │   │   │   │   └── p2do
│   │   │   │   │       ├── api.ts
│   │   │   │   │       └── todo-logo.svg
│   │   │   │   └── xmlui.json
│   │   │   ├── github.svg
│   │   │   ├── images
│   │   │   │   ├── apiaction-tutorial
│   │   │   │   │   ├── add-success.png
│   │   │   │   │   ├── apiaction-param.png
│   │   │   │   │   ├── change-completed.png
│   │   │   │   │   ├── change-in-progress.png
│   │   │   │   │   ├── confirm-delete.png
│   │   │   │   │   ├── data-error.png
│   │   │   │   │   ├── data-progress.png
│   │   │   │   │   ├── data-success.png
│   │   │   │   │   ├── display-1.png
│   │   │   │   │   ├── item-deleted.png
│   │   │   │   │   ├── item-updated.png
│   │   │   │   │   ├── missing-api-key.png
│   │   │   │   │   ├── new-item-added.png
│   │   │   │   │   └── test-message.png
│   │   │   │   ├── chat-api
│   │   │   │   │   └── domain-model.svg
│   │   │   │   ├── components
│   │   │   │   │   ├── image
│   │   │   │   │   │   └── breakfast.jpg
│   │   │   │   │   ├── markdown
│   │   │   │   │   │   └── colors.png
│   │   │   │   │   └── modal
│   │   │   │   │       ├── deep_link_dialog_1.jpg
│   │   │   │   │       └── deep_link_dialog_2.jpg
│   │   │   │   ├── create-apps
│   │   │   │   │   ├── collapsed-vertical.png
│   │   │   │   │   ├── using-forms-warning-dialog.png
│   │   │   │   │   └── using-forms.png
│   │   │   │   ├── datasource-tutorial
│   │   │   │   │   ├── data-with-header.png
│   │   │   │   │   ├── filtered-data.png
│   │   │   │   │   ├── filtered-items.png
│   │   │   │   │   ├── initial-page-items.png
│   │   │   │   │   ├── list-items.png
│   │   │   │   │   ├── next-page-items.png
│   │   │   │   │   ├── no-data.png
│   │   │   │   │   ├── pagination-1.jpg
│   │   │   │   │   ├── pagination-1.png
│   │   │   │   │   ├── polling-1.png
│   │   │   │   │   ├── refetch-data.png
│   │   │   │   │   ├── slow-loading.png
│   │   │   │   │   ├── test-message.png
│   │   │   │   │   ├── Thumbs.db
│   │   │   │   │   ├── unconventional-data.png
│   │   │   │   │   └── unfiltered-items.png
│   │   │   │   ├── flower.jpg
│   │   │   │   ├── get-started
│   │   │   │   │   ├── add-new-contact.png
│   │   │   │   │   ├── app-modified.png
│   │   │   │   │   ├── app-start.png
│   │   │   │   │   ├── app-with-boxes.png
│   │   │   │   │   ├── app-with-toast.png
│   │   │   │   │   ├── boilerplate-structure.png
│   │   │   │   │   ├── cl-initial.png
│   │   │   │   │   ├── cl-start.png
│   │   │   │   │   ├── contact-counts.png
│   │   │   │   │   ├── contact-dialog-title.png
│   │   │   │   │   ├── contact-dialog.png
│   │   │   │   │   ├── contact-menus.png
│   │   │   │   │   ├── contact-predicates.png
│   │   │   │   │   ├── context-menu.png
│   │   │   │   │   ├── dashboard-numbers.png
│   │   │   │   │   ├── default-contact-list.png
│   │   │   │   │   ├── delete-contact.png
│   │   │   │   │   ├── delete-task.png
│   │   │   │   │   ├── detailed-template.png
│   │   │   │   │   ├── edit-contact-details.png
│   │   │   │   │   ├── edited-contact-saved.png
│   │   │   │   │   ├── empty-sections.png
│   │   │   │   │   ├── filter-completed.png
│   │   │   │   │   ├── fullwidth-desktop.png
│   │   │   │   │   ├── fullwidth-mobile.png
│   │   │   │   │   ├── initial-table.png
│   │   │   │   │   ├── items-and-badges.png
│   │   │   │   │   ├── loading-message.png
│   │   │   │   │   ├── new-contact-button.png
│   │   │   │   │   ├── new-contact-saved.png
│   │   │   │   │   ├── no-empty-sections.png
│   │   │   │   │   ├── personal-todo-initial.png
│   │   │   │   │   ├── piechart.png
│   │   │   │   │   ├── review-today.png
│   │   │   │   │   ├── rudimentary-dashboard.png
│   │   │   │   │   ├── section-collapsed.png
│   │   │   │   │   ├── sectioned-items.png
│   │   │   │   │   ├── sections-ordered.png
│   │   │   │   │   ├── spacex-list-with-links.png
│   │   │   │   │   ├── spacex-list.png
│   │   │   │   │   ├── start-personal-todo-1.png
│   │   │   │   │   ├── submit-new-contact.png
│   │   │   │   │   ├── submit-new-task.png
│   │   │   │   │   ├── syntax-highlighting.png
│   │   │   │   │   ├── table-with-badge.png
│   │   │   │   │   ├── template-with-card.png
│   │   │   │   │   ├── test-emulated-api.png
│   │   │   │   │   ├── Thumbs.db
│   │   │   │   │   ├── todo-logo.png
│   │   │   │   │   └── xmlui-tools.png
│   │   │   │   ├── HelloApp.png
│   │   │   │   ├── HelloApp2.png
│   │   │   │   ├── logos
│   │   │   │   │   ├── xmlui1.svg
│   │   │   │   │   ├── xmlui2.svg
│   │   │   │   │   ├── xmlui3.svg
│   │   │   │   │   ├── xmlui4.svg
│   │   │   │   │   ├── xmlui5.svg
│   │   │   │   │   ├── xmlui6.svg
│   │   │   │   │   └── xmlui7.svg
│   │   │   │   ├── pdf
│   │   │   │   │   └── dummy-pdf.jpg
│   │   │   │   ├── rendering-engine
│   │   │   │   │   ├── AppEngine-flow.svg
│   │   │   │   │   ├── Component.svg
│   │   │   │   │   ├── CompoundComponent.svg
│   │   │   │   │   ├── RootComponent.svg
│   │   │   │   │   └── tree-with-containers.svg
│   │   │   │   ├── reviewers-guide
│   │   │   │   │   ├── AppEngine-flow.svg
│   │   │   │   │   └── incbutton-in-action.png
│   │   │   │   ├── tools
│   │   │   │   │   └── boilerplate-structure.png
│   │   │   │   ├── try.svg
│   │   │   │   ├── tutorial
│   │   │   │   │   ├── app-chat-history.png
│   │   │   │   │   ├── app-content-placeholder.png
│   │   │   │   │   ├── app-header-and-content.png
│   │   │   │   │   ├── app-links-channel-selected.png
│   │   │   │   │   ├── app-links-click.png
│   │   │   │   │   ├── app-navigation.png
│   │   │   │   │   ├── finished-ex01.png
│   │   │   │   │   ├── finished-ex02.png
│   │   │   │   │   ├── hello.png
│   │   │   │   │   ├── splash-screen-advanced.png
│   │   │   │   │   ├── splash-screen-after-click.png
│   │   │   │   │   ├── splash-screen-centered.png
│   │   │   │   │   ├── splash-screen-events.png
│   │   │   │   │   ├── splash-screen-expression.png
│   │   │   │   │   ├── splash-screen-reuse-after.png
│   │   │   │   │   ├── splash-screen-reuse-before.png
│   │   │   │   │   └── splash-screen.png
│   │   │   │   └── tutorial-01.png
│   │   │   ├── llms.txt
│   │   │   ├── logo-dark.svg
│   │   │   ├── logo.svg
│   │   │   ├── pg-popout.svg
│   │   │   └── xmlui-logo.svg
│   │   ├── serve.json
│   │   └── web.config
│   ├── scripts
│   │   ├── download-latest-xmlui.js
│   │   ├── generate-rss.js
│   │   ├── get-releases.js
│   │   └── utils.js
│   ├── src
│   │   ├── components
│   │   │   ├── BlogOverview.xmlui
│   │   │   ├── BlogPage.xmlui
│   │   │   ├── Boxes.xmlui
│   │   │   ├── Breadcrumb.xmlui
│   │   │   ├── ChangeLog.xmlui
│   │   │   ├── ColorPalette.xmlui
│   │   │   ├── DocumentLinks.xmlui
│   │   │   ├── DocumentPage.xmlui
│   │   │   ├── DocumentPageNoTOC.xmlui
│   │   │   ├── Icons.xmlui
│   │   │   ├── IncButton.xmlui
│   │   │   ├── IncButton2.xmlui
│   │   │   ├── NameValue.xmlui
│   │   │   ├── PageNotFound.xmlui
│   │   │   ├── PaletteItem.xmlui
│   │   │   ├── Palettes.xmlui
│   │   │   ├── SectionHeader.xmlui
│   │   │   ├── TBD.xmlui
│   │   │   ├── Test.xmlui
│   │   │   ├── ThemesIntro.xmlui
│   │   │   ├── ThousandThemes.xmlui
│   │   │   ├── TubeStops.xmlui
│   │   │   ├── TubeStops.xmlui.xs
│   │   │   └── TwoColumnCode.xmlui
│   │   ├── config.ts
│   │   ├── Main.xmlui
│   │   └── themes
│   │       ├── docs-theme.ts
│   │       ├── earthtone.ts
│   │       ├── xmlui-gray-on-default.ts
│   │       ├── xmlui-green-on-default.ts
│   │       └── xmlui-orange-on-default.ts
│   └── tsconfig.json
├── LICENSE
├── package-lock.json
├── package.json
├── packages
│   ├── tsconfig.json
│   ├── xmlui-animations
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── demo
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   └── src
│   │       ├── Animation.tsx
│   │       ├── AnimationNative.tsx
│   │       ├── FadeAnimation.tsx
│   │       ├── FadeInAnimation.tsx
│   │       ├── FadeOutAnimation.tsx
│   │       ├── index.tsx
│   │       ├── ScaleAnimation.tsx
│   │       └── SlideInAnimation.tsx
│   ├── xmlui-devtools
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── demo
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   ├── src
│   │   │   ├── devtools
│   │   │   │   ├── DevTools.tsx
│   │   │   │   ├── DevToolsNative.module.scss
│   │   │   │   ├── DevToolsNative.tsx
│   │   │   │   ├── ModalDialog.module.scss
│   │   │   │   ├── ModalDialog.tsx
│   │   │   │   ├── ModalVisibilityContext.tsx
│   │   │   │   ├── Tooltip.module.scss
│   │   │   │   ├── Tooltip.tsx
│   │   │   │   └── utils.ts
│   │   │   ├── editor
│   │   │   │   └── Editor.tsx
│   │   │   └── index.tsx
│   │   └── vite.config-overrides.ts
│   ├── xmlui-hello-world
│   │   ├── .gitignore
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   └── src
│   │       ├── HelloWorld.module.scss
│   │       ├── HelloWorld.tsx
│   │       ├── HelloWorldNative.tsx
│   │       └── index.tsx
│   ├── xmlui-os-frames
│   │   ├── .gitignore
│   │   ├── demo
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   └── src
│   │       ├── index.tsx
│   │       ├── IPhoneFrame.module.scss
│   │       ├── IPhoneFrame.tsx
│   │       ├── MacOSAppFrame.module.scss
│   │       ├── MacOSAppFrame.tsx
│   │       ├── WindowsAppFrame.module.scss
│   │       └── WindowsAppFrame.tsx
│   ├── xmlui-pdf
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── demo
│   │   │   ├── components
│   │   │   │   └── Pdf.xmlui
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   └── src
│   │       ├── index.tsx
│   │       ├── LazyPdfNative.tsx
│   │       ├── Pdf.module.scss
│   │       └── Pdf.tsx
│   ├── xmlui-playground
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── demo
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   └── src
│   │       ├── hooks
│   │       │   ├── usePlayground.ts
│   │       │   └── useToast.ts
│   │       ├── index.tsx
│   │       ├── playground
│   │       │   ├── Box.module.scss
│   │       │   ├── Box.tsx
│   │       │   ├── CodeSelector.module.scss
│   │       │   ├── CodeSelector.tsx
│   │       │   ├── ConfirmationDialog.module.scss
│   │       │   ├── ConfirmationDialog.tsx
│   │       │   ├── Editor.tsx
│   │       │   ├── Header.module.scss
│   │       │   ├── Header.tsx
│   │       │   ├── Playground.tsx
│   │       │   ├── PlaygroundContent.module.scss
│   │       │   ├── PlaygroundContent.tsx
│   │       │   ├── PlaygroundNative.module.scss
│   │       │   ├── PlaygroundNative.tsx
│   │       │   ├── Preview.tsx
│   │       │   ├── StandalonePlayground.tsx
│   │       │   ├── StandalonePlaygroundNative.module.scss
│   │       │   ├── StandalonePlaygroundNative.tsx
│   │       │   ├── ThemeSwitcher.module.scss
│   │       │   ├── ThemeSwitcher.tsx
│   │       │   └── utils.ts
│   │       ├── providers
│   │       │   ├── Toast.module.scss
│   │       │   └── ToastProvider.tsx
│   │       ├── state
│   │       │   └── store.ts
│   │       ├── themes
│   │       │   └── theme.ts
│   │       └── utils
│   │           └── helpers.ts
│   ├── xmlui-search
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── demo
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   └── src
│   │       ├── index.tsx
│   │       ├── Search.module.scss
│   │       └── Search.tsx
│   ├── xmlui-spreadsheet
│   │   ├── .gitignore
│   │   ├── demo
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   └── src
│   │       ├── index.tsx
│   │       ├── Spreadsheet.tsx
│   │       └── SpreadsheetNative.tsx
│   └── xmlui-website-blocks
│       ├── .gitignore
│       ├── CHANGELOG.md
│       ├── demo
│       │   ├── components
│       │   │   ├── HeroBackgroundBreakoutPage.xmlui
│       │   │   ├── HeroBackgroundsPage.xmlui
│       │   │   ├── HeroContentsPage.xmlui
│       │   │   ├── HeroTextAlignPage.xmlui
│       │   │   ├── HeroTextPage.xmlui
│       │   │   └── HeroTonesPage.xmlui
│       │   ├── Main.xmlui
│       │   └── themes
│       │       └── default.ts
│       ├── index.html
│       ├── index.ts
│       ├── meta
│       │   └── componentsMetadata.ts
│       ├── package.json
│       ├── public
│       │   └── resources
│       │       ├── building.jpg
│       │       └── xmlui-logo.svg
│       └── src
│           ├── Carousel
│           │   ├── Carousel.module.scss
│           │   ├── Carousel.tsx
│           │   ├── CarouselContext.tsx
│           │   └── CarouselNative.tsx
│           ├── FancyButton
│           │   ├── FancyButton.module.scss
│           │   ├── FancyButton.tsx
│           │   └── FancyButton.xmlui
│           ├── Hello
│           │   ├── Hello.tsx
│           │   ├── Hello.xmlui
│           │   └── Hello.xmlui.xs
│           ├── HeroSection
│           │   ├── HeroSection.module.scss
│           │   ├── HeroSection.spec.ts
│           │   ├── HeroSection.tsx
│           │   └── HeroSectionNative.tsx
│           ├── index.tsx
│           ├── ScrollToTop
│           │   ├── ScrollToTop.module.scss
│           │   ├── ScrollToTop.tsx
│           │   └── ScrollToTopNative.tsx
│           └── vite-env.d.ts
├── playwright.config.ts
├── README.md
├── tools
│   ├── codefence
│   │   └── xmlui-code-fence-docs.md
│   ├── create-app
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── create-app.ts
│   │   ├── helpers
│   │   │   ├── copy.ts
│   │   │   ├── get-pkg-manager.ts
│   │   │   ├── git.ts
│   │   │   ├── install.ts
│   │   │   ├── is-folder-empty.ts
│   │   │   ├── is-writeable.ts
│   │   │   ├── make-dir.ts
│   │   │   └── validate-pkg.ts
│   │   ├── index.ts
│   │   ├── package.json
│   │   ├── templates
│   │   │   ├── default
│   │   │   │   └── ts
│   │   │   │       ├── gitignore
│   │   │   │       ├── index.html
│   │   │   │       ├── index.ts
│   │   │   │       ├── public
│   │   │   │       │   ├── mockServiceWorker.js
│   │   │   │       │   ├── resources
│   │   │   │       │   │   ├── favicon.ico
│   │   │   │       │   │   └── xmlui-logo.svg
│   │   │   │       │   └── serve.json
│   │   │   │       └── src
│   │   │   │           ├── components
│   │   │   │           │   ├── ApiAware.xmlui
│   │   │   │           │   ├── Home.xmlui
│   │   │   │           │   ├── IncButton.xmlui
│   │   │   │           │   └── PagePanel.xmlui
│   │   │   │           ├── config.ts
│   │   │   │           └── Main.xmlui
│   │   │   ├── index.ts
│   │   │   └── types.ts
│   │   └── tsconfig.json
│   ├── create-xmlui-hello-world
│   │   ├── index.js
│   │   └── package.json
│   └── vscode
│       ├── .gitignore
│       ├── .vscode
│       │   ├── launch.json
│       │   └── tasks.json
│       ├── .vscodeignore
│       ├── build.sh
│       ├── CHANGELOG.md
│       ├── esbuild.js
│       ├── eslint.config.mjs
│       ├── formatter-docs.md
│       ├── generate-test-sample.sh
│       ├── LICENSE.md
│       ├── package-lock.json
│       ├── package.json
│       ├── README.md
│       ├── resources
│       │   ├── xmlui-logo.png
│       │   └── xmlui-markup-syntax-highlighting.png
│       ├── src
│       │   ├── extension.ts
│       │   └── server.ts
│       ├── syntaxes
│       │   └── xmlui.tmLanguage.json
│       ├── test-samples
│       │   └── sample.xmlui
│       ├── tsconfig.json
│       └── tsconfig.tsbuildinfo
├── turbo.json
└── xmlui
    ├── .gitignore
    ├── bin
    │   ├── bootstrap.cjs
    │   ├── bootstrap.js
    │   ├── build-lib.ts
    │   ├── build.ts
    │   ├── index.ts
    │   ├── preview.ts
    │   ├── start.ts
    │   ├── vite-xmlui-plugin.ts
    │   └── viteConfig.ts
    ├── CHANGELOG.md
    ├── conventions
    │   ├── component-qa-checklist.md
    │   ├── copilot-conventions.md
    │   ├── create-xmlui-components.md
    │   ├── mermaid.md
    │   ├── testing-conventions.md
    │   └── xmlui-in-a-nutshell.md
    ├── dev-docs
    │   ├── accessibility.md
    │   ├── build-system.md
    │   ├── build-xmlui.md
    │   ├── component-behaviors.md
    │   ├── component-metadata.md
    │   ├── components-with-options.md
    │   ├── containers.md
    │   ├── data-operations.md
    │   ├── glossary.md
    │   ├── index.md
    │   ├── next
    │   │   ├── component-dev-guide.md
    │   │   ├── configuration-management-enhancement-summary.md
    │   │   ├── documentation-scripts-refactoring-complete-summary.md
    │   │   ├── documentation-scripts-refactoring-plan.md
    │   │   ├── duplicate-pattern-extraction-summary.md
    │   │   ├── error-handling-standardization-summary.md
    │   │   ├── generating-component-reference.md
    │   │   ├── index.md
    │   │   ├── logging-consistency-implementation-summary.md
    │   │   ├── project-build.md
    │   │   ├── project-structure.md
    │   │   ├── theme-context.md
    │   │   ├── tiptap-design-considerations.md
    │   │   ├── working-with-code.md
    │   │   ├── xmlui-runtime-architecture
    │   │   └── xmlui-wcag-accessibility-report.md
    │   ├── react-fundamentals.md
    │   ├── release-method.md
    │   ├── standalone-app.md
    │   ├── theme-variables-refactoring.md
    │   ├── ud-components.md
    │   └── xmlui-repo.md
    ├── package.json
    ├── scripts
    │   ├── coverage-only.js
    │   ├── e2e-test-summary.js
    │   ├── extract-component-metadata.js
    │   ├── generate-docs
    │   │   ├── build-downloads-map.mjs
    │   │   ├── build-pages-map.mjs
    │   │   ├── components-config.json
    │   │   ├── configuration-management.mjs
    │   │   ├── constants.mjs
    │   │   ├── create-theme-files.mjs
    │   │   ├── DocsGenerator.mjs
    │   │   ├── error-handling.mjs
    │   │   ├── extensions-config.json
    │   │   ├── folders.mjs
    │   │   ├── generate-summary-files.mjs
    │   │   ├── get-docs.mjs
    │   │   ├── input-handler.mjs
    │   │   ├── logger.mjs
    │   │   ├── logging-standards.mjs
    │   │   ├── MetadataProcessor.mjs
    │   │   ├── pattern-utilities.mjs
    │   │   └── utils.mjs
    │   ├── generate-metadata-markdown.js
    │   ├── get-langserver-metadata.js
    │   ├── inline-links.mjs
    │   └── README-e2e-summary.md
    ├── src
    │   ├── abstractions
    │   │   ├── _conventions.md
    │   │   ├── ActionDefs.ts
    │   │   ├── AppContextDefs.ts
    │   │   ├── ComponentDefs.ts
    │   │   ├── ContainerDefs.ts
    │   │   ├── ExtensionDefs.ts
    │   │   ├── FunctionDefs.ts
    │   │   ├── RendererDefs.ts
    │   │   ├── scripting
    │   │   │   ├── BlockScope.ts
    │   │   │   ├── Compilation.ts
    │   │   │   ├── LogicalThread.ts
    │   │   │   ├── LoopScope.ts
    │   │   │   ├── modules.ts
    │   │   │   ├── ScriptParserError.ts
    │   │   │   ├── Token.ts
    │   │   │   ├── TryScope.ts
    │   │   │   └── TryScopeExp.ts
    │   │   └── ThemingDefs.ts
    │   ├── components
    │   │   ├── _conventions.md
    │   │   ├── abstractions.ts
    │   │   ├── Accordion
    │   │   │   ├── Accordion.md
    │   │   │   ├── Accordion.module.scss
    │   │   │   ├── Accordion.spec.ts
    │   │   │   ├── Accordion.tsx
    │   │   │   ├── AccordionContext.tsx
    │   │   │   ├── AccordionItem.tsx
    │   │   │   ├── AccordionItemNative.tsx
    │   │   │   └── AccordionNative.tsx
    │   │   ├── Animation
    │   │   │   └── AnimationNative.tsx
    │   │   ├── APICall
    │   │   │   ├── APICall.md
    │   │   │   ├── APICall.spec.ts
    │   │   │   ├── APICall.tsx
    │   │   │   └── APICallNative.tsx
    │   │   ├── App
    │   │   │   ├── App.md
    │   │   │   ├── App.module.scss
    │   │   │   ├── App.spec.ts
    │   │   │   ├── App.tsx
    │   │   │   ├── AppLayoutContext.ts
    │   │   │   ├── AppNative.tsx
    │   │   │   ├── AppStateContext.ts
    │   │   │   ├── doc-resources
    │   │   │   │   ├── condensed-sticky.xmlui
    │   │   │   │   ├── condensed.xmlui
    │   │   │   │   ├── horizontal-sticky.xmlui
    │   │   │   │   ├── horizontal.xmlui
    │   │   │   │   ├── vertical-full-header.xmlui
    │   │   │   │   ├── vertical-sticky.xmlui
    │   │   │   │   └── vertical.xmlui
    │   │   │   ├── IndexerContext.ts
    │   │   │   ├── LinkInfoContext.ts
    │   │   │   ├── SearchContext.tsx
    │   │   │   ├── Sheet.module.scss
    │   │   │   └── Sheet.tsx
    │   │   ├── AppHeader
    │   │   │   ├── AppHeader.md
    │   │   │   ├── AppHeader.module.scss
    │   │   │   ├── AppHeader.spec.ts
    │   │   │   ├── AppHeader.tsx
    │   │   │   └── AppHeaderNative.tsx
    │   │   ├── AppState
    │   │   │   ├── AppState.md
    │   │   │   ├── AppState.spec.ts
    │   │   │   ├── AppState.tsx
    │   │   │   └── AppStateNative.tsx
    │   │   ├── AutoComplete
    │   │   │   ├── AutoComplete.md
    │   │   │   ├── AutoComplete.module.scss
    │   │   │   ├── AutoComplete.spec.ts
    │   │   │   ├── AutoComplete.tsx
    │   │   │   ├── AutoCompleteContext.tsx
    │   │   │   └── AutoCompleteNative.tsx
    │   │   ├── Avatar
    │   │   │   ├── Avatar.md
    │   │   │   ├── Avatar.module.scss
    │   │   │   ├── Avatar.spec.ts
    │   │   │   ├── Avatar.tsx
    │   │   │   └── AvatarNative.tsx
    │   │   ├── Backdrop
    │   │   │   ├── Backdrop.md
    │   │   │   ├── Backdrop.module.scss
    │   │   │   ├── Backdrop.spec.ts
    │   │   │   ├── Backdrop.tsx
    │   │   │   └── BackdropNative.tsx
    │   │   ├── Badge
    │   │   │   ├── Badge.md
    │   │   │   ├── Badge.module.scss
    │   │   │   ├── Badge.spec.ts
    │   │   │   ├── Badge.tsx
    │   │   │   └── BadgeNative.tsx
    │   │   ├── Bookmark
    │   │   │   ├── Bookmark.md
    │   │   │   ├── Bookmark.module.scss
    │   │   │   ├── Bookmark.spec.ts
    │   │   │   ├── Bookmark.tsx
    │   │   │   └── BookmarkNative.tsx
    │   │   ├── Breakout
    │   │   │   ├── Breakout.module.scss
    │   │   │   ├── Breakout.spec.ts
    │   │   │   ├── Breakout.tsx
    │   │   │   └── BreakoutNative.tsx
    │   │   ├── Button
    │   │   │   ├── Button-style.spec.ts
    │   │   │   ├── Button.md
    │   │   │   ├── Button.module.scss
    │   │   │   ├── Button.spec.ts
    │   │   │   ├── Button.tsx
    │   │   │   └── ButtonNative.tsx
    │   │   ├── Card
    │   │   │   ├── Card.md
    │   │   │   ├── Card.module.scss
    │   │   │   ├── Card.spec.ts
    │   │   │   ├── Card.tsx
    │   │   │   └── CardNative.tsx
    │   │   ├── Carousel
    │   │   │   ├── Carousel.md
    │   │   │   ├── Carousel.module.scss
    │   │   │   ├── Carousel.spec.ts
    │   │   │   ├── Carousel.tsx
    │   │   │   ├── CarouselContext.tsx
    │   │   │   ├── CarouselItem.tsx
    │   │   │   ├── CarouselItemNative.tsx
    │   │   │   └── CarouselNative.tsx
    │   │   ├── ChangeListener
    │   │   │   ├── ChangeListener.md
    │   │   │   ├── ChangeListener.spec.ts
    │   │   │   ├── ChangeListener.tsx
    │   │   │   └── ChangeListenerNative.tsx
    │   │   ├── chart-color-schemes.ts
    │   │   ├── Charts
    │   │   │   ├── AreaChart
    │   │   │   │   ├── AreaChart.md
    │   │   │   │   ├── AreaChart.spec.ts
    │   │   │   │   ├── AreaChart.tsx
    │   │   │   │   └── AreaChartNative.tsx
    │   │   │   ├── BarChart
    │   │   │   │   ├── BarChart.md
    │   │   │   │   ├── BarChart.module.scss
    │   │   │   │   ├── BarChart.spec.ts
    │   │   │   │   ├── BarChart.tsx
    │   │   │   │   └── BarChartNative.tsx
    │   │   │   ├── DonutChart
    │   │   │   │   ├── DonutChart.spec.ts
    │   │   │   │   └── DonutChart.tsx
    │   │   │   ├── LabelList
    │   │   │   │   ├── LabelList.module.scss
    │   │   │   │   ├── LabelList.spec.ts
    │   │   │   │   ├── LabelList.tsx
    │   │   │   │   └── LabelListNative.tsx
    │   │   │   ├── Legend
    │   │   │   │   ├── Legend.spec.ts
    │   │   │   │   ├── Legend.tsx
    │   │   │   │   └── LegendNative.tsx
    │   │   │   ├── LineChart
    │   │   │   │   ├── LineChart.md
    │   │   │   │   ├── LineChart.module.scss
    │   │   │   │   ├── LineChart.spec.ts
    │   │   │   │   ├── LineChart.tsx
    │   │   │   │   └── LineChartNative.tsx
    │   │   │   ├── PieChart
    │   │   │   │   ├── PieChart.md
    │   │   │   │   ├── PieChart.spec.ts
    │   │   │   │   ├── PieChart.tsx
    │   │   │   │   ├── PieChartNative.module.scss
    │   │   │   │   └── PieChartNative.tsx
    │   │   │   ├── RadarChart
    │   │   │   │   ├── RadarChart.md
    │   │   │   │   ├── RadarChart.spec.ts
    │   │   │   │   ├── RadarChart.tsx
    │   │   │   │   └── RadarChartNative.tsx
    │   │   │   ├── Tooltip
    │   │   │   │   ├── TooltipContent.module.scss
    │   │   │   │   ├── TooltipContent.spec.ts
    │   │   │   │   └── TooltipContent.tsx
    │   │   │   └── utils
    │   │   │       ├── abstractions.ts
    │   │   │       └── ChartProvider.tsx
    │   │   ├── Checkbox
    │   │   │   ├── Checkbox.md
    │   │   │   ├── Checkbox.spec.ts
    │   │   │   └── Checkbox.tsx
    │   │   ├── CodeBlock
    │   │   │   ├── CodeBlock.module.scss
    │   │   │   ├── CodeBlock.spec.ts
    │   │   │   ├── CodeBlock.tsx
    │   │   │   ├── CodeBlockNative.tsx
    │   │   │   └── highlight-code.ts
    │   │   ├── collectedComponentMetadata.ts
    │   │   ├── ColorPicker
    │   │   │   ├── ColorPicker.md
    │   │   │   ├── ColorPicker.module.scss
    │   │   │   ├── ColorPicker.spec.ts
    │   │   │   ├── ColorPicker.tsx
    │   │   │   └── ColorPickerNative.tsx
    │   │   ├── Column
    │   │   │   ├── Column.md
    │   │   │   ├── Column.tsx
    │   │   │   ├── ColumnNative.tsx
    │   │   │   ├── doc-resources
    │   │   │   │   └── list-component-data.js
    │   │   │   └── TableContext.tsx
    │   │   ├── component-utils.ts
    │   │   ├── ComponentProvider.tsx
    │   │   ├── ComponentRegistryContext.tsx
    │   │   ├── container-helpers.tsx
    │   │   ├── ContentSeparator
    │   │   │   ├── ContentSeparator.md
    │   │   │   ├── ContentSeparator.module.scss
    │   │   │   ├── ContentSeparator.spec.ts
    │   │   │   ├── ContentSeparator.tsx
    │   │   │   ├── ContentSeparatorNative.tsx
    │   │   │   └── test-padding.xmlui
    │   │   ├── DataSource
    │   │   │   ├── DataSource.md
    │   │   │   └── DataSource.tsx
    │   │   ├── DateInput
    │   │   │   ├── DateInput.md
    │   │   │   ├── DateInput.module.scss
    │   │   │   ├── DateInput.spec.ts
    │   │   │   ├── DateInput.tsx
    │   │   │   └── DateInputNative.tsx
    │   │   ├── DatePicker
    │   │   │   ├── DatePicker.md
    │   │   │   ├── DatePicker.module.scss
    │   │   │   ├── DatePicker.spec.ts
    │   │   │   ├── DatePicker.tsx
    │   │   │   └── DatePickerNative.tsx
    │   │   ├── DropdownMenu
    │   │   │   ├── DropdownMenu.md
    │   │   │   ├── DropdownMenu.module.scss
    │   │   │   ├── DropdownMenu.spec.ts
    │   │   │   ├── DropdownMenu.tsx
    │   │   │   ├── DropdownMenuNative.tsx
    │   │   │   ├── MenuItem.md
    │   │   │   └── SubMenuItem.md
    │   │   ├── EmojiSelector
    │   │   │   ├── EmojiSelector.md
    │   │   │   ├── EmojiSelector.spec.ts
    │   │   │   ├── EmojiSelector.tsx
    │   │   │   └── EmojiSelectorNative.tsx
    │   │   ├── ExpandableItem
    │   │   │   ├── ExpandableItem.module.scss
    │   │   │   ├── ExpandableItem.spec.ts
    │   │   │   ├── ExpandableItem.tsx
    │   │   │   └── ExpandableItemNative.tsx
    │   │   ├── FileInput
    │   │   │   ├── FileInput.md
    │   │   │   ├── FileInput.module.scss
    │   │   │   ├── FileInput.spec.ts
    │   │   │   ├── FileInput.tsx
    │   │   │   └── FileInputNative.tsx
    │   │   ├── FileUploadDropZone
    │   │   │   ├── FileUploadDropZone.md
    │   │   │   ├── FileUploadDropZone.module.scss
    │   │   │   ├── FileUploadDropZone.spec.ts
    │   │   │   ├── FileUploadDropZone.tsx
    │   │   │   └── FileUploadDropZoneNative.tsx
    │   │   ├── FlowLayout
    │   │   │   ├── FlowLayout.md
    │   │   │   ├── FlowLayout.module.scss
    │   │   │   ├── FlowLayout.spec.ts
    │   │   │   ├── FlowLayout.spec.ts-snapshots
    │   │   │   │   └── Edge-cases-boxShadow-is-not-clipped-1-non-smoke-darwin.png
    │   │   │   ├── FlowLayout.tsx
    │   │   │   └── FlowLayoutNative.tsx
    │   │   ├── Footer
    │   │   │   ├── Footer.md
    │   │   │   ├── Footer.module.scss
    │   │   │   ├── Footer.spec.ts
    │   │   │   ├── Footer.tsx
    │   │   │   └── FooterNative.tsx
    │   │   ├── Form
    │   │   │   ├── Form.md
    │   │   │   ├── Form.module.scss
    │   │   │   ├── Form.spec.ts
    │   │   │   ├── Form.tsx
    │   │   │   ├── formActions.ts
    │   │   │   ├── FormContext.ts
    │   │   │   └── FormNative.tsx
    │   │   ├── FormItem
    │   │   │   ├── FormItem.md
    │   │   │   ├── FormItem.module.scss
    │   │   │   ├── FormItem.spec.ts
    │   │   │   ├── FormItem.tsx
    │   │   │   ├── FormItemNative.tsx
    │   │   │   ├── HelperText.module.scss
    │   │   │   ├── HelperText.tsx
    │   │   │   ├── ItemWithLabel.tsx
    │   │   │   └── Validations.ts
    │   │   ├── FormSection
    │   │   │   ├── FormSection.md
    │   │   │   ├── FormSection.ts
    │   │   │   └── FormSection.xmlui
    │   │   ├── Fragment
    │   │   │   ├── Fragment.spec.ts
    │   │   │   └── Fragment.tsx
    │   │   ├── Heading
    │   │   │   ├── abstractions.ts
    │   │   │   ├── H1.md
    │   │   │   ├── H1.spec.ts
    │   │   │   ├── H2.md
    │   │   │   ├── H2.spec.ts
    │   │   │   ├── H3.md
    │   │   │   ├── H3.spec.ts
    │   │   │   ├── H4.md
    │   │   │   ├── H4.spec.ts
    │   │   │   ├── H5.md
    │   │   │   ├── H5.spec.ts
    │   │   │   ├── H6.md
    │   │   │   ├── H6.spec.ts
    │   │   │   ├── Heading.md
    │   │   │   ├── Heading.module.scss
    │   │   │   ├── Heading.spec.ts
    │   │   │   ├── Heading.tsx
    │   │   │   └── HeadingNative.tsx
    │   │   ├── HoverCard
    │   │   │   ├── HoverCard.tsx
    │   │   │   └── HovercardNative.tsx
    │   │   ├── HtmlTags
    │   │   │   ├── HtmlTags.module.scss
    │   │   │   ├── HtmlTags.spec.ts
    │   │   │   └── HtmlTags.tsx
    │   │   ├── Icon
    │   │   │   ├── AdmonitionDanger.tsx
    │   │   │   ├── AdmonitionInfo.tsx
    │   │   │   ├── AdmonitionNote.tsx
    │   │   │   ├── AdmonitionTip.tsx
    │   │   │   ├── AdmonitionWarning.tsx
    │   │   │   ├── ApiIcon.tsx
    │   │   │   ├── ArrowDropDown.module.scss
    │   │   │   ├── ArrowDropDown.tsx
    │   │   │   ├── ArrowDropUp.module.scss
    │   │   │   ├── ArrowDropUp.tsx
    │   │   │   ├── ArrowLeft.module.scss
    │   │   │   ├── ArrowLeft.tsx
    │   │   │   ├── ArrowRight.module.scss
    │   │   │   ├── ArrowRight.tsx
    │   │   │   ├── Attach.tsx
    │   │   │   ├── Binding.module.scss
    │   │   │   ├── Binding.tsx
    │   │   │   ├── BoardIcon.tsx
    │   │   │   ├── BoxIcon.tsx
    │   │   │   ├── CheckIcon.tsx
    │   │   │   ├── ChevronDownIcon.tsx
    │   │   │   ├── ChevronLeft.tsx
    │   │   │   ├── ChevronRight.tsx
    │   │   │   ├── ChevronUpIcon.tsx
    │   │   │   ├── CodeFileIcon.tsx
    │   │   │   ├── CodeSandbox.tsx
    │   │   │   ├── CompactListIcon.tsx
    │   │   │   ├── ContentCopyIcon.tsx
    │   │   │   ├── DarkToLightIcon.tsx
    │   │   │   ├── DatabaseIcon.module.scss
    │   │   │   ├── DatabaseIcon.tsx
    │   │   │   ├── DocFileIcon.tsx
    │   │   │   ├── DocIcon.tsx
    │   │   │   ├── DotMenuHorizontalIcon.tsx
    │   │   │   ├── DotMenuIcon.tsx
    │   │   │   ├── EmailIcon.tsx
    │   │   │   ├── EmptyFolderIcon.tsx
    │   │   │   ├── ErrorIcon.tsx
    │   │   │   ├── ExpressionIcon.tsx
    │   │   │   ├── FillPlusCricleIcon.tsx
    │   │   │   ├── FilterIcon.tsx
    │   │   │   ├── FolderIcon.tsx
    │   │   │   ├── GlobeIcon.tsx
    │   │   │   ├── HomeIcon.tsx
    │   │   │   ├── HyperLinkIcon.tsx
    │   │   │   ├── Icon.md
    │   │   │   ├── Icon.module.scss
    │   │   │   ├── Icon.spec.ts
    │   │   │   ├── Icon.tsx
    │   │   │   ├── IconNative.tsx
    │   │   │   ├── ImageFileIcon.tsx
    │   │   │   ├── Inspect.tsx
    │   │   │   ├── LightToDark.tsx
    │   │   │   ├── LinkIcon.tsx
    │   │   │   ├── ListIcon.tsx
    │   │   │   ├── LooseListIcon.tsx
    │   │   │   ├── MoonIcon.tsx
    │   │   │   ├── MoreOptionsIcon.tsx
    │   │   │   ├── NoSortIcon.tsx
    │   │   │   ├── PDFIcon.tsx
    │   │   │   ├── PenIcon.tsx
    │   │   │   ├── PhoneIcon.tsx
    │   │   │   ├── PhotoIcon.tsx
    │   │   │   ├── PlusIcon.tsx
    │   │   │   ├── SearchIcon.tsx
    │   │   │   ├── ShareIcon.tsx
    │   │   │   ├── SortAscendingIcon.tsx
    │   │   │   ├── SortDescendingIcon.tsx
    │   │   │   ├── StarsIcon.tsx
    │   │   │   ├── SunIcon.tsx
    │   │   │   ├── svg
    │   │   │   │   ├── admonition_danger.svg
    │   │   │   │   ├── admonition_info.svg
    │   │   │   │   ├── admonition_note.svg
    │   │   │   │   ├── admonition_tip.svg
    │   │   │   │   ├── admonition_warning.svg
    │   │   │   │   ├── api.svg
    │   │   │   │   ├── arrow-dropdown.svg
    │   │   │   │   ├── arrow-left.svg
    │   │   │   │   ├── arrow-right.svg
    │   │   │   │   ├── arrow-up.svg
    │   │   │   │   ├── attach.svg
    │   │   │   │   ├── binding.svg
    │   │   │   │   ├── box.svg
    │   │   │   │   ├── bulb.svg
    │   │   │   │   ├── code-file.svg
    │   │   │   │   ├── code-sandbox.svg
    │   │   │   │   ├── dark_to_light.svg
    │   │   │   │   ├── database.svg
    │   │   │   │   ├── doc.svg
    │   │   │   │   ├── empty-folder.svg
    │   │   │   │   ├── expression.svg
    │   │   │   │   ├── eye-closed.svg
    │   │   │   │   ├── eye-dark.svg
    │   │   │   │   ├── eye.svg
    │   │   │   │   ├── file-text.svg
    │   │   │   │   ├── filter.svg
    │   │   │   │   ├── folder.svg
    │   │   │   │   ├── img.svg
    │   │   │   │   ├── inspect.svg
    │   │   │   │   ├── light_to_dark.svg
    │   │   │   │   ├── moon.svg
    │   │   │   │   ├── pdf.svg
    │   │   │   │   ├── photo.svg
    │   │   │   │   ├── share.svg
    │   │   │   │   ├── stars.svg
    │   │   │   │   ├── sun.svg
    │   │   │   │   ├── trending-down.svg
    │   │   │   │   ├── trending-level.svg
    │   │   │   │   ├── trending-up.svg
    │   │   │   │   ├── txt.svg
    │   │   │   │   ├── unknown-file.svg
    │   │   │   │   ├── unlink.svg
    │   │   │   │   └── xls.svg
    │   │   │   ├── TableDeleteColumnIcon.tsx
    │   │   │   ├── TableDeleteRowIcon.tsx
    │   │   │   ├── TableInsertColumnIcon.tsx
    │   │   │   ├── TableInsertRowIcon.tsx
    │   │   │   ├── TrashIcon.tsx
    │   │   │   ├── TrendingDownIcon.tsx
    │   │   │   ├── TrendingLevelIcon.tsx
    │   │   │   ├── TrendingUpIcon.tsx
    │   │   │   ├── TxtIcon.tsx
    │   │   │   ├── UnknownFileIcon.tsx
    │   │   │   ├── UnlinkIcon.tsx
    │   │   │   ├── UserIcon.tsx
    │   │   │   ├── WarningIcon.tsx
    │   │   │   └── XlsIcon.tsx
    │   │   ├── IconProvider.tsx
    │   │   ├── IconRegistryContext.tsx
    │   │   ├── IFrame
    │   │   │   ├── IFrame.md
    │   │   │   ├── IFrame.module.scss
    │   │   │   ├── IFrame.spec.ts
    │   │   │   ├── IFrame.tsx
    │   │   │   └── IFrameNative.tsx
    │   │   ├── Image
    │   │   │   ├── Image.md
    │   │   │   ├── Image.module.scss
    │   │   │   ├── Image.spec.ts
    │   │   │   ├── Image.tsx
    │   │   │   └── ImageNative.tsx
    │   │   ├── Input
    │   │   │   ├── index.ts
    │   │   │   ├── InputAdornment.module.scss
    │   │   │   ├── InputAdornment.tsx
    │   │   │   ├── InputDivider.module.scss
    │   │   │   ├── InputDivider.tsx
    │   │   │   ├── InputLabel.module.scss
    │   │   │   ├── InputLabel.tsx
    │   │   │   ├── PartialInput.module.scss
    │   │   │   └── PartialInput.tsx
    │   │   ├── InspectButton
    │   │   │   ├── InspectButton.module.scss
    │   │   │   └── InspectButton.tsx
    │   │   ├── Items
    │   │   │   ├── Items.md
    │   │   │   ├── Items.spec.ts
    │   │   │   ├── Items.tsx
    │   │   │   └── ItemsNative.tsx
    │   │   ├── Link
    │   │   │   ├── Link.md
    │   │   │   ├── Link.module.scss
    │   │   │   ├── Link.spec.ts
    │   │   │   ├── Link.tsx
    │   │   │   └── LinkNative.tsx
    │   │   ├── List
    │   │   │   ├── doc-resources
    │   │   │   │   └── list-component-data.js
    │   │   │   ├── List.md
    │   │   │   ├── List.module.scss
    │   │   │   ├── List.spec.ts
    │   │   │   ├── List.tsx
    │   │   │   └── ListNative.tsx
    │   │   ├── Logo
    │   │   │   ├── doc-resources
    │   │   │   │   └── xmlui-logo.svg
    │   │   │   ├── Logo.md
    │   │   │   ├── Logo.tsx
    │   │   │   └── LogoNative.tsx
    │   │   ├── Markdown
    │   │   │   ├── CodeText.module.scss
    │   │   │   ├── CodeText.tsx
    │   │   │   ├── Markdown.md
    │   │   │   ├── Markdown.module.scss
    │   │   │   ├── Markdown.spec.ts
    │   │   │   ├── Markdown.tsx
    │   │   │   ├── MarkdownNative.tsx
    │   │   │   ├── parse-binding-expr.ts
    │   │   │   └── utils.ts
    │   │   ├── metadata-helpers.ts
    │   │   ├── ModalDialog
    │   │   │   ├── ConfirmationModalContextProvider.tsx
    │   │   │   ├── Dialog.module.scss
    │   │   │   ├── Dialog.tsx
    │   │   │   ├── ModalDialog.md
    │   │   │   ├── ModalDialog.module.scss
    │   │   │   ├── ModalDialog.spec.ts
    │   │   │   ├── ModalDialog.tsx
    │   │   │   ├── ModalDialogNative.tsx
    │   │   │   └── ModalVisibilityContext.tsx
    │   │   ├── NavGroup
    │   │   │   ├── NavGroup.md
    │   │   │   ├── NavGroup.module.scss
    │   │   │   ├── NavGroup.spec.ts
    │   │   │   ├── NavGroup.tsx
    │   │   │   ├── NavGroupContext.ts
    │   │   │   └── NavGroupNative.tsx
    │   │   ├── NavLink
    │   │   │   ├── NavLink.md
    │   │   │   ├── NavLink.module.scss
    │   │   │   ├── NavLink.spec.ts
    │   │   │   ├── NavLink.tsx
    │   │   │   └── NavLinkNative.tsx
    │   │   ├── NavPanel
    │   │   │   ├── NavPanel.md
    │   │   │   ├── NavPanel.module.scss
    │   │   │   ├── NavPanel.spec.ts
    │   │   │   ├── NavPanel.tsx
    │   │   │   └── NavPanelNative.tsx
    │   │   ├── NestedApp
    │   │   │   ├── AppWithCodeView.module.scss
    │   │   │   ├── AppWithCodeView.tsx
    │   │   │   ├── AppWithCodeViewNative.tsx
    │   │   │   ├── defaultProps.tsx
    │   │   │   ├── logo.svg
    │   │   │   ├── NestedApp.module.scss
    │   │   │   ├── NestedApp.tsx
    │   │   │   ├── NestedAppNative.tsx
    │   │   │   ├── Tooltip.module.scss
    │   │   │   ├── Tooltip.tsx
    │   │   │   └── utils.ts
    │   │   ├── NoResult
    │   │   │   ├── NoResult.md
    │   │   │   ├── NoResult.module.scss
    │   │   │   ├── NoResult.spec.ts
    │   │   │   ├── NoResult.tsx
    │   │   │   └── NoResultNative.tsx
    │   │   ├── NumberBox
    │   │   │   ├── numberbox-abstractions.ts
    │   │   │   ├── NumberBox.md
    │   │   │   ├── NumberBox.module.scss
    │   │   │   ├── NumberBox.spec.ts
    │   │   │   ├── NumberBox.tsx
    │   │   │   └── NumberBoxNative.tsx
    │   │   ├── Option
    │   │   │   ├── Option.md
    │   │   │   ├── Option.spec.ts
    │   │   │   ├── Option.tsx
    │   │   │   ├── OptionNative.tsx
    │   │   │   └── OptionTypeProvider.tsx
    │   │   ├── PageMetaTitle
    │   │   │   ├── PageMetaTilteNative.tsx
    │   │   │   ├── PageMetaTitle.md
    │   │   │   ├── PageMetaTitle.spec.ts
    │   │   │   └── PageMetaTitle.tsx
    │   │   ├── Pages
    │   │   │   ├── Page.md
    │   │   │   ├── Pages.md
    │   │   │   ├── Pages.module.scss
    │   │   │   ├── Pages.tsx
    │   │   │   └── PagesNative.tsx
    │   │   ├── Pagination
    │   │   │   ├── Pagination.md
    │   │   │   ├── Pagination.module.scss
    │   │   │   ├── Pagination.spec.ts
    │   │   │   ├── Pagination.tsx
    │   │   │   └── PaginationNative.tsx
    │   │   ├── PositionedContainer
    │   │   │   ├── PositionedContainer.module.scss
    │   │   │   ├── PositionedContainer.tsx
    │   │   │   └── PositionedContainerNative.tsx
    │   │   ├── ProfileMenu
    │   │   │   ├── ProfileMenu.module.scss
    │   │   │   └── ProfileMenu.tsx
    │   │   ├── ProgressBar
    │   │   │   ├── ProgressBar.md
    │   │   │   ├── ProgressBar.module.scss
    │   │   │   ├── ProgressBar.spec.ts
    │   │   │   ├── ProgressBar.tsx
    │   │   │   └── ProgressBarNative.tsx
    │   │   ├── Queue
    │   │   │   ├── Queue.md
    │   │   │   ├── Queue.spec.ts
    │   │   │   ├── Queue.tsx
    │   │   │   ├── queueActions.ts
    │   │   │   └── QueueNative.tsx
    │   │   ├── RadioGroup
    │   │   │   ├── RadioGroup.md
    │   │   │   ├── RadioGroup.module.scss
    │   │   │   ├── RadioGroup.spec.ts
    │   │   │   ├── RadioGroup.tsx
    │   │   │   ├── RadioGroupNative.tsx
    │   │   │   ├── RadioItem.tsx
    │   │   │   └── RadioItemNative.tsx
    │   │   ├── RealTimeAdapter
    │   │   │   ├── RealTimeAdapter.tsx
    │   │   │   └── RealTimeAdapterNative.tsx
    │   │   ├── Redirect
    │   │   │   ├── Redirect.md
    │   │   │   ├── Redirect.spec.ts
    │   │   │   └── Redirect.tsx
    │   │   ├── ResponsiveBar
    │   │   │   ├── README.md
    │   │   │   ├── ResponsiveBar.md
    │   │   │   ├── ResponsiveBar.module.scss
    │   │   │   ├── ResponsiveBar.spec.ts
    │   │   │   ├── ResponsiveBar.tsx
    │   │   │   └── ResponsiveBarNative.tsx
    │   │   ├── Select
    │   │   │   ├── HiddenOption.tsx
    │   │   │   ├── OptionContext.ts
    │   │   │   ├── Select.md
    │   │   │   ├── Select.module.scss
    │   │   │   ├── Select.spec.ts
    │   │   │   ├── Select.tsx
    │   │   │   ├── SelectContext.tsx
    │   │   │   └── SelectNative.tsx
    │   │   ├── SelectionStore
    │   │   │   ├── SelectionStore.md
    │   │   │   ├── SelectionStore.tsx
    │   │   │   └── SelectionStoreNative.tsx
    │   │   ├── Slider
    │   │   │   ├── Slider.md
    │   │   │   ├── Slider.module.scss
    │   │   │   ├── Slider.spec.ts
    │   │   │   ├── Slider.tsx
    │   │   │   └── SliderNative.tsx
    │   │   ├── Slot
    │   │   │   ├── Slot.md
    │   │   │   ├── Slot.spec.ts
    │   │   │   └── Slot.ts
    │   │   ├── SlotItem.tsx
    │   │   ├── SpaceFiller
    │   │   │   ├── SpaceFiller.md
    │   │   │   ├── SpaceFiller.module.scss
    │   │   │   ├── SpaceFiller.spec.ts
    │   │   │   ├── SpaceFiller.tsx
    │   │   │   └── SpaceFillerNative.tsx
    │   │   ├── Spinner
    │   │   │   ├── Spinner.md
    │   │   │   ├── Spinner.module.scss
    │   │   │   ├── Spinner.spec.ts
    │   │   │   ├── Spinner.tsx
    │   │   │   └── SpinnerNative.tsx
    │   │   ├── Splitter
    │   │   │   ├── HSplitter.md
    │   │   │   ├── HSplitter.spec.ts
    │   │   │   ├── Splitter.md
    │   │   │   ├── Splitter.module.scss
    │   │   │   ├── Splitter.spec.ts
    │   │   │   ├── Splitter.tsx
    │   │   │   ├── SplitterNative.tsx
    │   │   │   ├── utils.ts
    │   │   │   ├── VSplitter.md
    │   │   │   └── VSplitter.spec.ts
    │   │   ├── Stack
    │   │   │   ├── CHStack.md
    │   │   │   ├── CHStack.spec.ts
    │   │   │   ├── CVStack.md
    │   │   │   ├── CVStack.spec.ts
    │   │   │   ├── HStack.md
    │   │   │   ├── HStack.spec.ts
    │   │   │   ├── Stack.md
    │   │   │   ├── Stack.module.scss
    │   │   │   ├── Stack.spec.ts
    │   │   │   ├── Stack.tsx
    │   │   │   ├── StackNative.tsx
    │   │   │   ├── VStack.md
    │   │   │   └── VStack.spec.ts
    │   │   ├── StickyBox
    │   │   │   ├── StickyBox.md
    │   │   │   ├── StickyBox.module.scss
    │   │   │   ├── StickyBox.tsx
    │   │   │   └── StickyBoxNative.tsx
    │   │   ├── Switch
    │   │   │   ├── Switch.md
    │   │   │   ├── Switch.spec.ts
    │   │   │   └── Switch.tsx
    │   │   ├── Table
    │   │   │   ├── doc-resources
    │   │   │   │   └── list-component-data.js
    │   │   │   ├── react-table-config.d.ts
    │   │   │   ├── Table.md
    │   │   │   ├── Table.module.scss
    │   │   │   ├── Table.spec.ts
    │   │   │   ├── Table.tsx
    │   │   │   ├── TableNative.tsx
    │   │   │   └── useRowSelection.tsx
    │   │   ├── TableOfContents
    │   │   │   ├── TableOfContents.module.scss
    │   │   │   ├── TableOfContents.spec.ts
    │   │   │   ├── TableOfContents.tsx
    │   │   │   └── TableOfContentsNative.tsx
    │   │   ├── Tabs
    │   │   │   ├── TabContext.tsx
    │   │   │   ├── TabItem.md
    │   │   │   ├── TabItem.tsx
    │   │   │   ├── TabItemNative.tsx
    │   │   │   ├── Tabs.md
    │   │   │   ├── Tabs.module.scss
    │   │   │   ├── Tabs.spec.ts
    │   │   │   ├── Tabs.tsx
    │   │   │   └── TabsNative.tsx
    │   │   ├── Text
    │   │   │   ├── Text.md
    │   │   │   ├── Text.module.scss
    │   │   │   ├── Text.spec.ts
    │   │   │   ├── Text.tsx
    │   │   │   └── TextNative.tsx
    │   │   ├── TextArea
    │   │   │   ├── TextArea.md
    │   │   │   ├── TextArea.module.scss
    │   │   │   ├── TextArea.spec.ts
    │   │   │   ├── TextArea.tsx
    │   │   │   ├── TextAreaNative.tsx
    │   │   │   ├── TextAreaResizable.tsx
    │   │   │   └── useComposedRef.ts
    │   │   ├── TextBox
    │   │   │   ├── TextBox.md
    │   │   │   ├── TextBox.module.scss
    │   │   │   ├── TextBox.spec.ts
    │   │   │   ├── TextBox.tsx
    │   │   │   └── TextBoxNative.tsx
    │   │   ├── Theme
    │   │   │   ├── NotificationToast.tsx
    │   │   │   ├── Theme.md
    │   │   │   ├── Theme.module.scss
    │   │   │   ├── Theme.spec.ts
    │   │   │   ├── Theme.tsx
    │   │   │   └── ThemeNative.tsx
    │   │   ├── TimeInput
    │   │   │   ├── TimeInput.md
    │   │   │   ├── TimeInput.module.scss
    │   │   │   ├── TimeInput.spec.ts
    │   │   │   ├── TimeInput.tsx
    │   │   │   ├── TimeInputNative.tsx
    │   │   │   └── utils.ts
    │   │   ├── Timer
    │   │   │   ├── Timer.md
    │   │   │   ├── Timer.spec.ts
    │   │   │   ├── Timer.tsx
    │   │   │   └── TimerNative.tsx
    │   │   ├── Toggle
    │   │   │   ├── Toggle.module.scss
    │   │   │   └── Toggle.tsx
    │   │   ├── ToneChangerButton
    │   │   │   ├── ToneChangerButton.md
    │   │   │   ├── ToneChangerButton.spec.ts
    │   │   │   └── ToneChangerButton.tsx
    │   │   ├── ToneSwitch
    │   │   │   ├── ToneSwitch.md
    │   │   │   ├── ToneSwitch.module.scss
    │   │   │   ├── ToneSwitch.spec.ts
    │   │   │   ├── ToneSwitch.tsx
    │   │   │   └── ToneSwitchNative.tsx
    │   │   ├── Tooltip
    │   │   │   ├── Tooltip.md
    │   │   │   ├── Tooltip.module.scss
    │   │   │   ├── Tooltip.spec.ts
    │   │   │   ├── Tooltip.tsx
    │   │   │   └── TooltipNative.tsx
    │   │   ├── Tree
    │   │   │   ├── testData.ts
    │   │   │   ├── Tree-dynamic.spec.ts
    │   │   │   ├── Tree-icons.spec.ts
    │   │   │   ├── Tree.md
    │   │   │   ├── Tree.spec.ts
    │   │   │   ├── TreeComponent.module.scss
    │   │   │   ├── TreeComponent.tsx
    │   │   │   └── TreeNative.tsx
    │   │   ├── TreeDisplay
    │   │   │   ├── TreeDisplay.md
    │   │   │   ├── TreeDisplay.module.scss
    │   │   │   ├── TreeDisplay.tsx
    │   │   │   └── TreeDisplayNative.tsx
    │   │   ├── ValidationSummary
    │   │   │   ├── ValidationSummary.module.scss
    │   │   │   └── ValidationSummary.tsx
    │   │   └── VisuallyHidden.tsx
    │   ├── components-core
    │   │   ├── abstractions
    │   │   │   ├── ComponentRenderer.ts
    │   │   │   ├── LoaderRenderer.ts
    │   │   │   ├── standalone.ts
    │   │   │   └── treeAbstractions.ts
    │   │   ├── action
    │   │   │   ├── actions.ts
    │   │   │   ├── APICall.tsx
    │   │   │   ├── FileDownloadAction.tsx
    │   │   │   ├── FileUploadAction.tsx
    │   │   │   ├── NavigateAction.tsx
    │   │   │   └── TimedAction.tsx
    │   │   ├── ApiBoundComponent.tsx
    │   │   ├── appContext
    │   │   │   ├── date-functions.ts
    │   │   │   ├── math-function.ts
    │   │   │   └── misc-utils.ts
    │   │   ├── AppContext.tsx
    │   │   ├── behaviors
    │   │   │   ├── Behavior.tsx
    │   │   │   └── CoreBehaviors.tsx
    │   │   ├── component-hooks.ts
    │   │   ├── ComponentDecorator.tsx
    │   │   ├── ComponentViewer.tsx
    │   │   ├── CompoundComponent.tsx
    │   │   ├── constants.ts
    │   │   ├── DebugViewProvider.tsx
    │   │   ├── descriptorHelper.ts
    │   │   ├── devtools
    │   │   │   ├── InspectorDialog.module.scss
    │   │   │   ├── InspectorDialog.tsx
    │   │   │   └── InspectorDialogVisibilityContext.tsx
    │   │   ├── EngineError.ts
    │   │   ├── event-handlers.ts
    │   │   ├── InspectorButton.module.scss
    │   │   ├── InspectorContext.tsx
    │   │   ├── interception
    │   │   │   ├── abstractions.ts
    │   │   │   ├── ApiInterceptor.ts
    │   │   │   ├── ApiInterceptorProvider.tsx
    │   │   │   ├── apiInterceptorWorker.ts
    │   │   │   ├── Backend.ts
    │   │   │   ├── Errors.ts
    │   │   │   ├── IndexedDb.ts
    │   │   │   ├── initMock.ts
    │   │   │   ├── InMemoryDb.ts
    │   │   │   ├── ReadonlyCollection.ts
    │   │   │   └── useApiInterceptorContext.tsx
    │   │   ├── loader
    │   │   │   ├── ApiLoader.tsx
    │   │   │   ├── DataLoader.tsx
    │   │   │   ├── ExternalDataLoader.tsx
    │   │   │   ├── Loader.tsx
    │   │   │   ├── MockLoaderRenderer.tsx
    │   │   │   └── PageableLoader.tsx
    │   │   ├── LoaderComponent.tsx
    │   │   ├── markup-check.ts
    │   │   ├── parts.ts
    │   │   ├── renderers.ts
    │   │   ├── rendering
    │   │   │   ├── AppContent.tsx
    │   │   │   ├── AppRoot.tsx
    │   │   │   ├── AppWrapper.tsx
    │   │   │   ├── buildProxy.ts
    │   │   │   ├── collectFnVarDeps.ts
    │   │   │   ├── ComponentAdapter.tsx
    │   │   │   ├── ComponentWrapper.tsx
    │   │   │   ├── Container.tsx
    │   │   │   ├── containers.ts
    │   │   │   ├── ContainerWrapper.tsx
    │   │   │   ├── ErrorBoundary.module.scss
    │   │   │   ├── ErrorBoundary.tsx
    │   │   │   ├── InvalidComponent.module.scss
    │   │   │   ├── InvalidComponent.tsx
    │   │   │   ├── nodeUtils.ts
    │   │   │   ├── reducer.ts
    │   │   │   ├── renderChild.tsx
    │   │   │   ├── StandaloneComponent.tsx
    │   │   │   ├── StateContainer.tsx
    │   │   │   ├── UnknownComponent.module.scss
    │   │   │   ├── UnknownComponent.tsx
    │   │   │   └── valueExtractor.ts
    │   │   ├── reportEngineError.ts
    │   │   ├── RestApiProxy.ts
    │   │   ├── script-runner
    │   │   │   ├── asyncProxy.ts
    │   │   │   ├── AttributeValueParser.ts
    │   │   │   ├── bannedFunctions.ts
    │   │   │   ├── BindingTreeEvaluationContext.ts
    │   │   │   ├── eval-tree-async.ts
    │   │   │   ├── eval-tree-common.ts
    │   │   │   ├── eval-tree-sync.ts
    │   │   │   ├── ParameterParser.ts
    │   │   │   ├── process-statement-async.ts
    │   │   │   ├── process-statement-common.ts
    │   │   │   ├── process-statement-sync.ts
    │   │   │   ├── ScriptingSourceTree.ts
    │   │   │   ├── simplify-expression.ts
    │   │   │   ├── statement-queue.ts
    │   │   │   └── visitors.ts
    │   │   ├── StandaloneApp.tsx
    │   │   ├── StandaloneExtensionManager.ts
    │   │   ├── TableOfContentsContext.tsx
    │   │   ├── theming
    │   │   │   ├── _themes.scss
    │   │   │   ├── component-layout-resolver.ts
    │   │   │   ├── extendThemeUtils.ts
    │   │   │   ├── hvar.ts
    │   │   │   ├── layout-resolver.ts
    │   │   │   ├── parse-layout-props.ts
    │   │   │   ├── StyleContext.tsx
    │   │   │   ├── StyleRegistry.ts
    │   │   │   ├── ThemeContext.tsx
    │   │   │   ├── ThemeProvider.tsx
    │   │   │   ├── themes
    │   │   │   │   ├── base-utils.ts
    │   │   │   │   ├── palette.ts
    │   │   │   │   ├── root.ts
    │   │   │   │   ├── solid.ts
    │   │   │   │   ├── theme-colors.ts
    │   │   │   │   └── xmlui.ts
    │   │   │   ├── themeVars.module.scss
    │   │   │   ├── themeVars.ts
    │   │   │   ├── transformThemeVars.ts
    │   │   │   └── utils.ts
    │   │   ├── utils
    │   │   │   ├── actionUtils.ts
    │   │   │   ├── audio-utils.ts
    │   │   │   ├── base64-utils.ts
    │   │   │   ├── compound-utils.ts
    │   │   │   ├── css-utils.ts
    │   │   │   ├── DataLoaderQueryKeyGenerator.ts
    │   │   │   ├── date-utils.ts
    │   │   │   ├── extractParam.ts
    │   │   │   ├── hooks.tsx
    │   │   │   ├── LruCache.ts
    │   │   │   ├── mergeProps.ts
    │   │   │   ├── misc.ts
    │   │   │   ├── request-params.ts
    │   │   │   ├── statementUtils.ts
    │   │   │   └── treeUtils.ts
    │   │   └── xmlui-parser.ts
    │   ├── index-standalone.ts
    │   ├── index.scss
    │   ├── index.ts
    │   ├── language-server
    │   │   ├── server-common.ts
    │   │   ├── server-web-worker.ts
    │   │   ├── server.ts
    │   │   ├── services
    │   │   │   ├── common
    │   │   │   │   ├── docs-generation.ts
    │   │   │   │   ├── lsp-utils.ts
    │   │   │   │   ├── metadata-utils.ts
    │   │   │   │   └── syntax-node-utilities.ts
    │   │   │   ├── completion.ts
    │   │   │   ├── diagnostic.ts
    │   │   │   ├── format.ts
    │   │   │   └── hover.ts
    │   │   └── xmlui-metadata-generated.js
    │   ├── logging
    │   │   ├── LoggerContext.tsx
    │   │   ├── LoggerInitializer.tsx
    │   │   ├── LoggerService.ts
    │   │   └── xmlui.ts
    │   ├── logo.svg
    │   ├── parsers
    │   │   ├── common
    │   │   │   ├── GenericToken.ts
    │   │   │   ├── InputStream.ts
    │   │   │   └── utils.ts
    │   │   ├── scripting
    │   │   │   ├── code-behind-collect.ts
    │   │   │   ├── Lexer.ts
    │   │   │   ├── modules.ts
    │   │   │   ├── Parser.ts
    │   │   │   ├── ParserError.ts
    │   │   │   ├── ScriptingNodeTypes.ts
    │   │   │   ├── TokenTrait.ts
    │   │   │   ├── TokenType.ts
    │   │   │   └── tree-visitor.ts
    │   │   ├── style-parser
    │   │   │   ├── errors.ts
    │   │   │   ├── source-tree.ts
    │   │   │   ├── StyleInputStream.ts
    │   │   │   ├── StyleLexer.ts
    │   │   │   ├── StyleParser.ts
    │   │   │   └── tokens.ts
    │   │   └── xmlui-parser
    │   │       ├── CharacterCodes.ts
    │   │       ├── diagnostics.ts
    │   │       ├── fileExtensions.ts
    │   │       ├── index.ts
    │   │       ├── lint.ts
    │   │       ├── parser.ts
    │   │       ├── ParserError.ts
    │   │       ├── scanner.ts
    │   │       ├── syntax-kind.ts
    │   │       ├── syntax-node.ts
    │   │       ├── transform.ts
    │   │       ├── utils.ts
    │   │       ├── xmlui-serializer.ts
    │   │       └── xmlui-tree.ts
    │   ├── react-app-env.d.ts
    │   ├── syntax
    │   │   ├── monaco
    │   │   │   ├── grammar.monacoLanguage.ts
    │   │   │   ├── index.ts
    │   │   │   ├── xmlui-dark.ts
    │   │   │   ├── xmlui-light.ts
    │   │   │   └── xmluiscript.monacoLanguage.ts
    │   │   └── textMate
    │   │       ├── index.ts
    │   │       ├── xmlui-dark.json
    │   │       ├── xmlui-light.json
    │   │       ├── xmlui.json
    │   │       └── xmlui.tmLanguage.json
    │   ├── testing
    │   │   ├── assertions.ts
    │   │   ├── component-test-helpers.ts
    │   │   ├── ComponentDrivers.ts
    │   │   ├── drivers
    │   │   │   ├── DateInputDriver.ts
    │   │   │   ├── index.ts
    │   │   │   ├── ModalDialogDriver.ts
    │   │   │   ├── NumberBoxDriver.ts
    │   │   │   ├── TextBoxDriver.ts
    │   │   │   ├── TimeInputDriver.ts
    │   │   │   ├── TimerDriver.ts
    │   │   │   └── TreeDriver.ts
    │   │   ├── fixtures.ts
    │   │   ├── index.ts
    │   │   ├── infrastructure
    │   │   │   ├── index.html
    │   │   │   ├── main.tsx
    │   │   │   ├── public
    │   │   │   │   ├── mockServiceWorker.js
    │   │   │   │   ├── resources
    │   │   │   │   │   ├── bell.svg
    │   │   │   │   │   ├── box.svg
    │   │   │   │   │   ├── doc.svg
    │   │   │   │   │   ├── eye.svg
    │   │   │   │   │   ├── flower-640x480.jpg
    │   │   │   │   │   ├── sun.svg
    │   │   │   │   │   ├── test-image-100x100.jpg
    │   │   │   │   │   └── txt.svg
    │   │   │   │   └── serve.json
    │   │   │   └── TestBed.tsx
    │   │   └── themed-app-test-helpers.ts
    │   └── vite-env.d.ts
    ├── tests
    │   ├── components
    │   │   ├── CodeBlock
    │   │   │   └── hightlight-code.test.ts
    │   │   ├── playground-pattern.test.ts
    │   │   └── Tree
    │   │       └── Tree-states.test.ts
    │   ├── components-core
    │   │   ├── abstractions
    │   │   │   └── treeAbstractions.test.ts
    │   │   ├── container
    │   │   │   └── buildProxy.test.ts
    │   │   ├── interception
    │   │   │   ├── orderBy.test.ts
    │   │   │   ├── ReadOnlyCollection.test.ts
    │   │   │   └── request-param-converter.test.ts
    │   │   ├── scripts-runner
    │   │   │   ├── AttributeValueParser.test.ts
    │   │   │   ├── eval-tree-arrow-async.test.ts
    │   │   │   ├── eval-tree-arrow.test.ts
    │   │   │   ├── eval-tree-func-decl-async.test.ts
    │   │   │   ├── eval-tree-func-decl.test.ts
    │   │   │   ├── eval-tree-pre-post.test.ts
    │   │   │   ├── eval-tree-regression.test.ts
    │   │   │   ├── eval-tree.test.ts
    │   │   │   ├── function-proxy.test.ts
    │   │   │   ├── parser-regression.test.ts
    │   │   │   ├── process-event.test.ts
    │   │   │   ├── process-function.test.ts
    │   │   │   ├── process-implicit-context.test.ts
    │   │   │   ├── process-statement-asgn.test.ts
    │   │   │   ├── process-statement-destruct.test.ts
    │   │   │   ├── process-statement-regs.test.ts
    │   │   │   ├── process-statement-sync.test.ts
    │   │   │   ├── process-statement.test.ts
    │   │   │   ├── process-switch-sync.test.ts
    │   │   │   ├── process-switch.test.ts
    │   │   │   ├── process-try-sync.test.ts
    │   │   │   ├── process-try.test.ts
    │   │   │   └── test-helpers.ts
    │   │   ├── test-metadata-handler.ts
    │   │   ├── theming
    │   │   │   ├── border-segments.test.ts
    │   │   │   ├── component-layout.resolver.test.ts
    │   │   │   ├── layout-property-parser.test.ts
    │   │   │   ├── layout-resolver.test.ts
    │   │   │   ├── layout-resolver2.test.ts
    │   │   │   ├── layout-vp-override.test.ts
    │   │   │   └── padding-segments.test.ts
    │   │   └── utils
    │   │       ├── date-utils.test.ts
    │   │       ├── format-human-elapsed-time.test.ts
    │   │       └── LruCache.test.ts
    │   ├── language-server
    │   │   ├── completion.test.ts
    │   │   ├── format.test.ts
    │   │   ├── hover.test.ts
    │   │   └── mockData.ts
    │   └── parsers
    │       ├── common
    │       │   └── input-stream.test.ts
    │       ├── markdown
    │       │   └── parse-binding-expression.test.ts
    │       ├── parameter-parser.test.ts
    │       ├── paremeter-parser.test.ts
    │       ├── scripting
    │       │   ├── eval-tree-arrow.test.ts
    │       │   ├── eval-tree-pre-post.test.ts
    │       │   ├── eval-tree.test.ts
    │       │   ├── function-proxy.test.ts
    │       │   ├── lexer-literals.test.ts
    │       │   ├── lexer-misc.test.ts
    │       │   ├── module-parse.test.ts
    │       │   ├── parser-arrow.test.ts
    │       │   ├── parser-assignments.test.ts
    │       │   ├── parser-binary.test.ts
    │       │   ├── parser-destructuring.test.ts
    │       │   ├── parser-errors.test.ts
    │       │   ├── parser-expressions.test.ts
    │       │   ├── parser-function.test.ts
    │       │   ├── parser-literals.test.ts
    │       │   ├── parser-primary.test.ts
    │       │   ├── parser-regex.test.ts
    │       │   ├── parser-statements.test.ts
    │       │   ├── parser-unary.test.ts
    │       │   ├── process-event.test.ts
    │       │   ├── process-implicit-context.test.ts
    │       │   ├── process-statement-asgn.test.ts
    │       │   ├── process-statement-destruct.test.ts
    │       │   ├── process-statement-regs.test.ts
    │       │   ├── process-statement-sync.test.ts
    │       │   ├── process-statement.test.ts
    │       │   ├── process-switch-sync.test.ts
    │       │   ├── process-switch.test.ts
    │       │   ├── process-try-sync.test.ts
    │       │   ├── process-try.test.ts
    │       │   ├── simplify-expression.test.ts
    │       │   ├── statement-hooks.test.ts
    │       │   └── test-helpers.ts
    │       ├── style-parser
    │       │   ├── generateHvarChain.test.ts
    │       │   ├── parseHVar.test.ts
    │       │   ├── parser.test.ts
    │       │   └── tokens.test.ts
    │       └── xmlui
    │           ├── lint.test.ts
    │           ├── parser.test.ts
    │           ├── scanner.test.ts
    │           ├── transform.attr.test.ts
    │           ├── transform.circular.test.ts
    │           ├── transform.element.test.ts
    │           ├── transform.errors.test.ts
    │           ├── transform.escape.test.ts
    │           ├── transform.regression.test.ts
    │           ├── transform.script.test.ts
    │           ├── transform.test.ts
    │           └── xmlui.ts
    ├── tests-e2e
    │   ├── api-bound-component-regression.spec.ts
    │   ├── api-call-as-extracted-component.spec.ts
    │   ├── assign-to-object-or-array-regression.spec.ts
    │   ├── binding-regression.spec.ts
    │   ├── children-as-template-context-vars.spec.ts
    │   ├── compound-component.spec.ts
    │   ├── context-vars-regression.spec.ts
    │   ├── data-bindings.spec.ts
    │   ├── datasource-and-api-usage-in-var.spec.ts
    │   ├── datasource-direct-binding.spec.ts
    │   ├── datasource-onLoaded-regression.spec.ts
    │   ├── modify-array-item-regression.spec.ts
    │   ├── namespaces.spec.ts
    │   ├── push-to-array-regression.spec.ts
    │   ├── screen-breakpoints.spec.ts
    │   ├── scripting.spec.ts
    │   ├── state-scope-in-pages.spec.ts
    │   └── state-var-scopes.spec.ts
    ├── tsconfig.json
    ├── tsdown.config.ts
    ├── vite.config.ts
    └── vitest.config.ts
```

# Files

--------------------------------------------------------------------------------
/xmlui/dev-docs/component-behaviors.md:
--------------------------------------------------------------------------------

```markdown
# Component Behaviors

This document explains XMLUI's component behavior system - a cross-cutting concern mechanism that enables attaching reusable functionality to components declaratively. It covers the behavior architecture, the three core behaviors (tooltip, animation, label), the attachment mechanism, and implementation details for framework developers working on the XMLUI core.

## What Are Component Behaviors?

**Component behaviors** are decorator-like objects that wrap rendered React components with additional functionality based on component properties. They implement cross-cutting concerns that apply to multiple components without requiring changes to component implementations.

A behavior examines a component's definition and metadata to determine eligibility, then wraps the rendered React node with enhanced functionality. This approach enables features like tooltips, animations, and form labels to work consistently across all visual components without coupling the feature implementation to specific component renderers.

**Key Characteristics:**

- **Declarative Attachment** - Behaviors attach automatically when specific properties are present
- **Zero Component Coupling** - Components need no knowledge of behaviors; they simply render
- **Composable** - Multiple behaviors can wrap the same component in sequence
- **Renderer Context Access** - Behaviors access the full renderer context for value extraction and state management
- **Metadata-Aware** - Behaviors inspect component metadata to determine applicability

## Architectural Overview

### The Behavior Interface

All behaviors implement a simple contract with three members:

```typescript
export interface Behavior {
  name: string;
  canAttach: (node: ComponentDef, metadata: ComponentMetadata) => boolean;
  // The attach method now receives an optional metadata argument so
  // behaviors can make use of component descriptor information when
  // transforming the rendered node.
  attach: (
    context: RendererContext<any>,
    node: ReactNode,
    metadata?: ComponentMetadata
  ) => ReactNode;
}
```

- **name** - Unique identifier for the behavior (e.g., "tooltip", "animation", "label")
- **canAttach** - Predicate determining if the behavior applies to a specific component instance based on its definition and metadata
- **attach** - Transformation function that wraps the rendered React node with enhanced functionality

**Important Note on Transformation Flexibility:**

The `attach` function can transform the rendered component in any valid way - wrapping it in other React components is just one approach. Behaviors can also clone the rendered node using `React.cloneElement()` to add or modify properties (such as CSS classes, event handlers, or attributes), compose multiple transformations, or apply any other valid React node manipulation. The only requirement is that `attach` must return a valid React node.

### Application in ComponentAdapter

Behaviors apply in `ComponentAdapter` immediately after the component renderer produces the initial React node:

```typescript
// 1. Component renderer executes
renderedNode = renderer(rendererContext);

// 2. Retrieve registered behaviors from component registry
const behaviors = componentRegistry.getBehaviors();

// 3. Apply behaviors sequentially (skip compound components)
if (!isCompoundComponent) {
    for (const behavior of behaviors) {
      if (behavior.canAttach(rendererContext.node, descriptor)) {
        // Pass the component metadata into attach so behaviors that need
        // descriptor-level information (for example, to avoid wrapping
        // components marked `opaque` or `nonVisual`) can use it.
        renderedNode = behavior.attach(rendererContext, renderedNode, descriptor);
      }
    }
}

// 4. Continue with decoration, API binding, layout wrapping...
```

**Application Logic:**

1. **Renderer Execution** - Component's renderer function produces the initial React node from the component definition
2. **Behavior Retrieval** - `componentRegistry.getBehaviors()` returns all registered behaviors from the central registry (framework behaviors plus any contributed by external packages)
3. **Compound Check** - If the component is a compound (XMLUI-defined) component, skip all behaviors to avoid wrapping internal structure
4. **Sequential Evaluation** - For each behavior in order:
  - Call `canAttach(node, metadata)` with the component definition and its metadata descriptor
  - If true, call `attach(context, renderedNode, metadata)` to wrap the node; the metadata is passed so behaviors can consult descriptor-level information during attachment
  - The wrapped node becomes the input for the next behavior
5. **Result** - Multiple behaviors create nested wrappers in application order (tooltip innermost, label outermost)

This placement ensures behaviors wrap the core component but remain inside decorations (test IDs), API bindings, and layout wrappers.

### Behavior Registration Architecture

Behaviors are registered centrally in the `ComponentRegistry` class within `ComponentProvider`, following the same pattern used for components, actions, and loaders. This centralized registry enables both framework behaviors and external package behaviors to coexist.

**Registration in ComponentRegistry:**

```typescript
class ComponentRegistry {
  private behaviors: Behavior[] = [];

  constructor(contributes: ContributesDefinition = {}, ...) {
    // ... component and action registration ...

    // Register framework-implemented behaviors
    this.registerBehavior(tooltipBehavior);
    this.registerBehavior(animationBehavior);
    this.registerBehavior(labelBehavior);

    // Register external behaviors from contributes
    contributes.behaviors?.forEach((behavior) => {
      this.registerBehavior(behavior);
    });
  }

  private registerBehavior(
    behavior: Behavior,
    location: "before" | "after" = "after",
    position?: string
  ) {
    if (position) {
      const targetIndex = this.behaviors.findIndex(b => b.name === position);
      if (targetIndex !== -1) {
        const insertIndex = location === "before" ? targetIndex : targetIndex + 1;
        this.behaviors.splice(insertIndex, 0, behavior);
        return;
      }
    }
    this.behaviors.push(behavior);
  }

  getBehaviors(): Behavior[] {
    return this.behaviors;
  }
}
```

**ComponentAdapter Retrieval:**

The `ComponentAdapter` retrieves registered behaviors from the component registry:

```typescript
// In ComponentAdapter.tsx
const componentRegistry = useComponentRegistry();
const behaviors = componentRegistry.getBehaviors();

// Apply behaviors to rendered node
for (const behavior of behaviors) {
  if (behavior.canAttach(rendererContext.node, descriptor)) {
    renderedNode = behavior.attach(rendererContext, renderedNode);
  }
}
```

**External Package Registration:**

External component packages can contribute custom behaviors through the `ContributesDefinition`:

```typescript
// In an external package (e.g., packages/my-package/src/index.tsx)
import { myCustomBehavior } from "./behaviors/MyCustomBehavior";

export default {
  namespace: "MyPackage",
  components: [myComponentRenderer],
  behaviors: [myCustomBehavior],  // Custom behaviors register here
};
```

**Positioned Registration:**

The `registerBehavior` method supports precise control over behavior execution order through optional `location` and `position` parameters:

- **location**: `"before" | "after"` - Specifies placement relative to the target behavior
- **position**: `string` - The name of the target behavior for positioning

This allows external packages to insert behaviors at specific points in the execution sequence:

```typescript
// Insert a custom behavior before the animation behavior
registerBehavior(myBehavior, "before", "animation");

// Insert a custom behavior after the tooltip behavior
registerBehavior(myBehavior, "after", "tooltip");
```

**Benefits of Registry Architecture:**

- **Extensibility** - Third-party packages can register custom behaviors without modifying framework code
- **Consistency** - Follows the same pattern as components, actions, and loaders
- **Order Control** - Positioned registration enables fine-grained control over behavior application sequence
- **Centralized Management** - All behaviors accessible through single `getBehaviors()` method
- **Type Safety** - Full TypeScript type checking for behavior implementations

## Framework-Implemented Behaviors

XMLUI currently implements three behaviors that handle common cross-cutting concerns. These serve as examples of the behavior pattern and provide essential functionality across all visual components:

### Tooltip Behavior

Displays informational text or markdown content when hovering over visual components. The tooltip behavior activates when a component has either the `tooltip` or `tooltipMarkdown` property defined.

**Attachment Criteria:**
```typescript
canAttach: (node) => {
  const tooltipText = node.props?.tooltip;
  const tooltipMarkdown = node.props?.tooltipMarkdown;
  return !!tooltipText || !!tooltipMarkdown;
}
```

**Usage Example:**
```xmlui
<Button 
  label="Click me" 
  tooltip="This button saves your changes"
  tooltipOptions="right; delayDuration: 800" />
```

**Wrapping Process:**
1. Extracts `tooltip`, `tooltipMarkdown`, and `tooltipOptions` properties using the renderer context's value extractor
2. Parses tooltip options (side, alignment, delay, etc.) via `parseTooltipOptions()`
3. Wraps the rendered component in a `<Tooltip>` component with extracted configuration
4. The wrapped component becomes the tooltip trigger; the Tooltip component handles display logic

### Animation Behavior

Applies entry/exit animations to components using CSS animations or transitions. The animation behavior activates when a component has the `animation` property defined.

**Attachment Criteria:**
```typescript
canAttach: (node) => {
  return !!node.props?.animation;
}
```

**Usage Example:**
```xmlui
<Card 
  title="Welcome" 
  animation="fadeIn"
  animationOptions="duration: 500; delay: 200" />
```

**Wrapping Process:**
1. Extracts `animation` and `animationOptions` properties from the component definition
2. Parses animation configuration via `parseAnimation()` and `parseAnimationOptions()`
3. Wraps the component in an `<Animation>` component that manages the animation lifecycle
4. Special handling for ModalDialog components - passes `externalAnimation={true}` to prevent animation conflicts

**ModalDialog Special Case:**
```typescript
return (
  <Animation animation={parseAnimation(animation)} {...parsedOptions}>
    {context.node.type === "ModalDialog"
      ? cloneElement(node as ReactElement, {
          externalAnimation: true,
        })
      : node}
  </Animation>
);
```

ModalDialog components have internal animation support. When wrapped by the animation behavior, the `externalAnimation` prop signals the dialog to defer to external animation control.

### Label Behavior

Wraps form input components with labels, positioning, and visual indicators (required asterisk, validation states). The label behavior activates when a component has the `label` property and does not explicitly handle its own labeling.

**Attachment Criteria:**
```typescript
canAttach: (node, metadata) => {
  // Don't attach if component declares its own label prop handling
  if (metadata?.props?.label) {
    return false;
  }
  // Only attach if component has a label prop
  if (!node.props?.label) {
    return false;
  }
  return true;
}
```

**Usage Example:**
```xmlui
<TextBox 
  label="Email Address" 
  labelPosition="top"
  required={true}
  placeholder="[email protected]" />
```

**Wrapping Process:**
1. Extracts label-related properties: `label`, `labelPosition`, `labelWidth`, `labelBreak`, `required`, `enabled`, `style`, `readOnly`, `shrinkToLabel`
2. Uses the renderer context's `className` to maintain styling consistency
3. Wraps the component in `<ItemWithLabel>` which handles label rendering, positioning, and required indicators
4. Special handling for `inputTemplate` - the `isInputTemplateUsed` flag adjusts label layout when custom input templates are present

**Metadata Check Explanation:**

The label behavior checks `metadata?.props?.label` to determine if a component has explicit label property metadata defined. Components like Checkbox or Radio that include label rendering as part of their core functionality define `label` in their metadata. For these components, the label behavior does not attach - they handle their own labels.

Components like TextBox or Select do not define `label` in their metadata because they expect the label behavior to handle labeling. The presence of a `label` prop in the component instance (but absence in metadata) signals that the behavior should attach.

### Behavior Execution Order

Behaviors are registered in the `ComponentRegistry` during construction. The framework registers its three core behaviors first, followed by any behaviors contributed by external packages:

```typescript
// Framework behaviors registered in ComponentRegistry constructor
this.registerBehavior(tooltipBehavior);
this.registerBehavior(animationBehavior);
this.registerBehavior(labelBehavior);

// External behaviors registered after
contributes.behaviors?.forEach((behavior) => {
  this.registerBehavior(behavior);
});
```

**Order Significance:**

The registration order matters because behaviors wrap sequentially. The current order (tooltip, animation, label) produces this nesting:

```
<ItemWithLabel>          ← Label behavior (outermost)
  <Animation>            ← Animation behavior (middle)
    <Tooltip>            ← Tooltip behavior (innermost)
      <Button />         ← Original component
    </Tooltip>
  </Animation>
</ItemWithLabel>
```

This order ensures:
- Tooltips appear on the actual interactive component
- Animations affect the component and its tooltip together
- Labels encompass the entire animated, tooltip-enabled component

Changing the order would alter this nesting and could break visual consistency or interaction behavior.

## Renderer Context in Behaviors

Behaviors receive the full `RendererContext` when attaching, providing access to all rendering capabilities:

```typescript
export interface RendererContext<TMd extends ComponentMetadata = ComponentMetadata>
  extends ComponentRendererContextBase<TMd> {
  node: ComponentDef<TMd>;
  state: any;
  updateState: (state: any) => void;
  appContext: AppContextType;
  extractValue: ValueExtractor;
  lookupEventHandler: LookupEventHandlerFn<TMd>;
  lookupAction: LookupAsyncFn;
  lookupSyncCallback: LookupSyncFn;
  extractResourceUrl: (url?: unknown) => string | undefined;
  renderChild: RenderChildFn;
  registerComponentApi: RegisterComponentApiFn;
  className: string | undefined;
  layoutContext: LayoutContext | undefined;
  uid: symbol;
}
```

**Key Context Properties Used by Behaviors:**

- **extractValue** - Extracts property values from expressions, handles data binding, evaluates context variables
- **node** - The component definition containing props, events, children, and type information
- **className** - Computed CSS classes from layout properties, passed to wrapped components for style consistency
- **renderChild** - Function to render child components, used when behaviors need to render templates (e.g., tooltip templates)
- **appContext** - Global application context with navigation, state buckets, media queries, and theme information

**Example - Tooltip Behavior Using Context:**

```typescript
attach: (context, node, metadata) => {
  const { extractValue } = context;
  const tooltipText = extractValue(context.node.props?.tooltip, true);
  const tooltipMarkdown = extractValue(context.node.props?.tooltipMarkdown, true);
  const tooltipOptions = extractValue(context.node.props?.tooltipOptions, true);
  const parsedOptions = parseTooltipOptions(tooltipOptions);

  // metadata may be used to alter behavior for components marked nonVisual
  // or opaque; it's passed in for richer decision-making.
  return (
    <Tooltip text={tooltipText} markdown={tooltipMarkdown} {...parsedOptions}>
      {node}
    </Tooltip>
  );
}
```

The `extractValue` function handles:
- Static string values: `tooltip="Click me"` → `"Click me"`
- Expression evaluation: `tooltip={message}` → evaluates `message` variable
- Context variable resolution: `tooltip={$user.name}` → retrieves from app context
- Data binding: `tooltip={item.description}` → extracts from current data context

## Implementation Details

### ComponentAdapter Integration Point

The behavior application occurs in `ComponentAdapter` after the renderer produces the initial node but before decoration and event handler attachment:

```typescript
// From ComponentAdapter.tsx (simplified flow)
let renderedNode: ReactNode = null;

try {
  if (safeNode.type === "Slot") {
    renderedNode = slotRenderer(rendererContext, parentRenderContext);
  } else {
    if (!renderer) {
      return <UnknownComponent message={`${safeNode.type}`} />;
    }
    renderedNode = renderer(rendererContext);
  }

  /**
   * Apply behaviors to the component.
   */
  const behaviors = componentRegistry.getBehaviors();
  if (!isCompoundComponent) {
    for (const behavior of behaviors) {
      if (behavior.canAttach(rendererContext.node, descriptor)) {
        renderedNode = behavior.attach(rendererContext, renderedNode, descriptor);
      }
    }
  }

  // --- Components may have a `testId` property for E2E testing purposes
  if ((appContext?.decorateComponentsWithTestId && ...) || inspectId !== undefined) {
    renderedNode = (
      <ComponentDecorator attr={{ "data-testid": resolvedUid, ... }}>
        {cloneElement(renderedNode as ReactElement, { ... })}
      </ComponentDecorator>
    );
  }

  // --- API-bound components provide helpful behavior
  if (isApiBound) {
    return <ApiBoundComponent ... />;
  }

  // --- Layout context wrapping
  if (layoutContextRef.current?.wrapChild) {
    renderedNode = layoutContextRef.current.wrapChild(...);
  }
} catch (e) {
  renderingError = (e as Error)?.message || "Internal error";
}
```

**Pipeline Position:**

1. **Renderer Execution** - Component-specific rendering logic produces initial node
2. **Behavior Application** ← **Behaviors apply here**
3. **Test Decoration** - Test IDs and inspection attributes added via ComponentDecorator
4. **API Binding** - API-bound components wrapped in ApiBoundComponent
5. **Layout Wrapping** - Layout context applies layout-specific wrappers

This position ensures behaviors wrap the core component but remain inside decorations and API bindings. The layering ensures:
- Behaviors affect only the visual component, not decoration infrastructure
- Test IDs and inspection attributes apply to behavior-wrapped components
- API binding affects the entire behavior-enhanced component
- Layout wrapping encompasses all previous layers

### Behavior Transformation Examples

The following examples demonstrate how the framework-implemented behaviors transform components. These behaviors all use the wrapping approach, where the rendered component is wrapped in additional React components to provide enhanced functionality.

**Single Behavior (Tooltip):**

```xmlui
<Button label="Save" tooltip="Save your changes" />
```

Produces:
```jsx
<Tooltip text="Save your changes">
  <button className="xmlui-button">Save</button>
</Tooltip>
```

**Multiple Behaviors (Tooltip + Animation):**

```xmlui
<Card 
  title="Welcome" 
  tooltip="Dashboard card"
  animation="fadeIn" />
```

Produces:
```jsx
<Animation animation={fadeInAnimation}>
  <Tooltip text="Dashboard card">
    <div className="xmlui-card">
      <div className="card-title">Welcome</div>
    </div>
  </Tooltip>
</Animation>
```

**All Three Behaviors:**

```xmlui
<TextBox 
  label="Email"
  tooltip="Enter your email address"
  animation="slideIn" />
```

Produces:
```jsx
<ItemWithLabel label="Email">
  <Animation animation={slideInAnimation}>
    <Tooltip text="Enter your email address">
      <input type="text" className="xmlui-textbox" />
    </Tooltip>
  </Animation>
</ItemWithLabel>
```

### Metadata-Driven Attachment

Behaviors inspect component metadata passed to `canAttach()` to make attachment decisions. The metadata contains component descriptor information from the component registry:

```typescript
export type ComponentMetadata<
  TProps extends Record<string, ComponentPropertyMetadata> = Record<string, any>,
  TEvents extends Record<string, ComponentPropertyMetadata> = Record<string, any>,
  TContextValues extends Record<string, ComponentPropertyMetadata> = Record<string, any>,
  TApis extends Record<string, ComponentApiMetadata> = Record<string, any>,
> = {
  status?: "stable" | "experimental" | "deprecated" | "in progress" | "internal";
  description?: string;
  props?: TProps;
  events?: TEvents;
  contextVars?: TContextValues;
  apis?: TApis;
  nonVisual?: boolean;
  childrenAsTemplate?: string;
  opaque?: boolean;
  // ... theme-related fields
};
```

**Label Behavior Metadata Check:**

```typescript
canAttach: (node, metadata) => {
  // Check if component defines its own label handling
  if (metadata?.props?.label) {
    return false;  // Component handles labels itself
  }
  // Check if instance has label prop
  if (!node.props?.label) {
    return false;  // No label to attach
  }
  return true;  // Attach label behavior
}
```

**Metadata Usage Patterns:**

- **nonVisual** - Behaviors can check this flag to avoid attaching to non-visual components like DataSource or Container
- **props** - Behaviors check for property metadata to determine if a component explicitly handles a feature
- **opaque** - Indicates internal component structure should not be affected by behaviors

## Behavior Execution Flow

### Complete Rendering Flow with Behaviors

```mermaid
graph TD
    A[ComponentWrapper receives component definition] --> B[ComponentWrapper routes to ComponentAdapter]
    B --> C[ComponentAdapter prepares renderer context]
    C --> D[ComponentAdapter calls component renderer]
    D --> E[Initial React node created]
    E --> F[ComponentAdapter retrieves behaviors from registry via componentRegistry.getBehaviors]
    F --> G[FOR EACH behavior: Evaluate canAttach]
    G --> H{canAttach returns true?}
    H -->|Yes| I[behavior.attach wraps node]
    H -->|No| J[Skip this behavior]
    I --> K[Node transformed with behavior functionality]
    J --> K
    K --> L{More behaviors?}
    L -->|Yes| G
    L -->|No| M[ComponentAdapter applies test decoration]
    M --> N[ComponentAdapter checks for API-bound properties]
    N --> O{Is API-bound?}
    O -->|Yes| P[Wrap in ApiBoundComponent]
    O -->|No| Q[ComponentAdapter applies layout context wrapping]
    P --> Q
    Q --> R[ComponentAdapter returns final transformed node]
```

### Behavior Attachment Decision Tree

```mermaid
flowchart TD
    A[Component rendered] --> B{Is compound component?}
    B -->|Yes| Z[Skip all behaviors]
    B -->|No| C[Tooltip Behavior Check]
    C --> D{Has tooltip or tooltipMarkdown prop?}
    D -->|Yes| E[Wrap in Tooltip component]
    D -->|No| F[Animation Behavior Check]
    E --> F
    F --> G{Has animation prop?}
    G -->|Yes| H[Wrap in Animation component]
    G -->|No| I[Label Behavior Check]
    H --> I
    I --> J{Metadata has label prop?}
    J -->|Yes| K[Skip - component handles own label]
    J -->|No| L{Instance has label prop?}
    K --> M[Return transformed node]
    L -->|Yes| N[Wrap in ItemWithLabel component]
    L -->|No| M
    N --> M
    Z --> M
```

## Summary

Component behaviors provide a powerful mechanism for applying cross-cutting concerns to XMLUI components declaratively. Behaviors integrate seamlessly into the rendering pipeline, transforming components after initial rendering but before decoration. They leverage the full renderer context for value extraction, event handling, and state management.

The behavior system reduces code duplication, ensures consistency, and enables framework-level enhancements without component-level changes. Behaviors are registered in the central `ComponentRegistry` and retrieved via `componentRegistry.getBehaviors()`, then applied sequentially in `ComponentAdapter`.

The registry-based architecture enables extensibility - both framework behaviors and external package behaviors coexist through the `ContributesDefinition` mechanism. External packages can register custom behaviors that execute alongside framework behaviors, with optional positioning control for precise execution order.

For framework developers working on XMLUI core, behaviors represent a critical architectural pattern for implementing features that span multiple components uniformly and maintainably.

```

--------------------------------------------------------------------------------
/xmlui/src/components/AutoComplete/AutoComplete.spec.ts:
--------------------------------------------------------------------------------

```typescript
import { SKIP_REASON } from "../../testing/component-test-helpers";
import { expect, test } from "../../testing/fixtures";

// =============================================================================
// BASIC FUNCTIONALITY TESTS
// =============================================================================

test("renders with default props", async ({ initTestBed, createAutoCompleteDriver }) => {
  await initTestBed(`
    <AutoComplete />
  `);

  const driver = await createAutoCompleteDriver();

  await expect(driver.component).toBeVisible();
});

test("displays placeholder text", async ({ initTestBed, page }) => {
  const placeholder = "Search for an option";
  await initTestBed(`<AutoComplete placeholder="${placeholder}" />`);
  await expect(page.getByPlaceholder(placeholder)).toBeVisible();
});

test("initialValue sets the selected option", async ({ initTestBed, page }) => {
  await initTestBed(`
    <Fragment>
      <AutoComplete id="autoComplete" initialValue="1" label="Select a superhero">
        <Option value="1" label="Bruce Wayne" />
        <Option value="2" label="Clark Kent" />
        <Option value="3" label="Diana Prince" />
      </AutoComplete>
      <Text testId="text">Selected value: {autoComplete.value}</Text>
    </Fragment>
  `);

  await expect(page.getByTestId("text")).toHaveText("Selected value: 1");
  await expect(page.getByRole("combobox")).toHaveValue("Bruce Wayne");
});

test("opens dropdown when clicked", async ({ initTestBed, page, createAutoCompleteDriver }) => {
  await initTestBed(`
    <AutoComplete>
      <Option value="1" label="Bruce Wayne" />
      <Option value="2" label="Clark Kent" />
      <Option value="3" label="Diana Prince" />
    </AutoComplete>
  `);

  const driver = await createAutoCompleteDriver();
  await driver.click();

  await expect(page.getByRole("listbox")).toBeVisible();
});

test("selects an option when clicked", async ({ initTestBed, page, createAutoCompleteDriver }) => {
  await initTestBed(`
    <Fragment>
      <AutoComplete id="autoComplete">
        <Option value="1" label="Bruce Wayne" />
        <Option value="2" label="Clark Kent" />
        <Option value="3" label="Diana Prince" />
      </AutoComplete>
      <Text testId="text">Selected value: {autoComplete.value}</Text>
    </Fragment>
  `);

  const driver = await createAutoCompleteDriver("autoComplete");

  // Open the dropdown
  await driver.click();

  // Wait for options to be visible before selecting
  await page.getByRole("option", { name: "Diana Prince" }).waitFor({ state: "visible" });

  // Select the option
  await driver.selectLabel("Diana Prince");

  // Verify the results
  await expect(page.getByTestId("text")).toHaveText("Selected value: 3");
  await expect(page.getByRole("combobox")).toHaveValue("Diana Prince");
});

// =============================================================================
// EDGE CASE TESTS
// =============================================================================

test("disabled option cannot be selected", async ({
  initTestBed,
  page,
  createAutoCompleteDriver,
}) => {
  await initTestBed(`
    <Fragment>
      <AutoComplete id="autoComplete">
        <Option value="1" label="Bruce Wayne" />
        <Option value="2" label="Clark Kent" enabled="false" />
        <Option value="3" label="Diana Prince" />
      </AutoComplete>
      <Text testId="text">Selected value: {autoComplete.value}</Text>
    </Fragment>
  `);

  const driver = await createAutoCompleteDriver("autoComplete");
  await driver.click();

  await driver.selectLabel("Clark Kent");

  // Value should not change to the disabled option
  await expect(page.getByRole("combobox")).not.toHaveValue("Bruce Wayne");
  await expect(page.getByTestId("text")).not.toHaveText("Selected value: 2");
});

// =============================================================================
// INTEGRATION TESTS
// =============================================================================

test("multi mode allows selecting multiple options", async ({
  initTestBed,
  page,
  createAutoCompleteDriver,
}) => {
  await initTestBed(`
    <Fragment>
      <AutoComplete id="autoComplete" multi="true">
        <Option value="1" label="Bruce Wayne" />
        <Option value="2" label="Clark Kent" />
        <Option value="3" label="Diana Prince" />
      </AutoComplete>
      <Text testId="text">Selected values: {autoComplete.value}</Text>
    </Fragment>
  `);

  const driver = await createAutoCompleteDriver("autoComplete");
  await driver.click();

  // Click the first option
  await driver.selectLabel("Bruce Wayne");

  // First option should be selected
  await expect(page.getByTestId("text")).toHaveText("Selected values: 1");

  // Click another option
  await driver.selectLabel("Diana Prince");

  // Both options should be selected
  await expect(page.getByTestId("text")).toHaveText("Selected values: 1,3");

  await driver.click();

  // Both selected options should be visible as badges
  await expect(page.getByText("Bruce Wayne")).toBeVisible();
  await expect(page.getByText("Diana Prince")).toBeVisible();
});

test("searching filters options", async ({ initTestBed, page, createAutoCompleteDriver }) => {
  await initTestBed(`
    <AutoComplete>
      <Option value="1" label="Bruce Wayne" />
      <Option value="2" label="Clark Kent" />
      <Option value="3" label="Diana Prince" />
      <Option value="4" label="Barry Allen" />
      <Option value="5" label="Hal Jordan" />
    </AutoComplete>
  `);

  const driver = await createAutoCompleteDriver();
  await driver.click();

  // Type in the search field
  await page.keyboard.type("Bruce");

  // Only Bruce Wayne should be visible
  await expect(page.getByText("Bruce Wayne")).toBeVisible();
  await expect(page.getByText("Clark Kent")).not.toBeVisible();
  await expect(page.getByText("Diana Prince")).not.toBeVisible();
});

test("emptyListTemplate is shown when no options match", async ({
  initTestBed,
  page,
  createAutoCompleteDriver,
}) => {
  await initTestBed(`
    <AutoComplete>
      <property name="emptyListTemplate">
        <Text>No options found</Text>
      </property>
      <Option value="1" label="Bruce Wayne" />
      <Option value="2" label="Clark Kent" />
      <Option value="3" label="Diana Prince" />
    </AutoComplete>
  `);

  const driver = await createAutoCompleteDriver();
  await driver.click();

  // Type something that doesn't match any option
  await page.keyboard.type("Joker");

  // Empty list template should be shown
  await expect(page.getByText("No options found")).toBeVisible();
});

test("optionTemplate customizes option appearance", async ({
  initTestBed,
  page,
  createAutoCompleteDriver,
}) => {
  await initTestBed(`
    <AutoComplete>
      <property name="optionTemplate">
        <Text textAlign="center" color="purple">{$item.label}</Text>
      </property>
      <Option value="1" label="Bruce Wayne" />
      <Option value="2" label="Clark Kent" />
      <Option value="3" label="Diana Prince" />
    </AutoComplete>
  `);

  const driver = await createAutoCompleteDriver();
  await driver.click();

  // Options should be visible with custom styling
  await expect(page.getByText("Bruce Wayne")).toBeVisible();
  await expect(page.getByText("Clark Kent")).toBeVisible();
  await expect(page.getByText("Diana Prince")).toBeVisible();
});

// =============================================================================
// VISUAL STATE TESTS
// =============================================================================

test("readOnly prevents changing selection", async ({
  initTestBed,
  page,
  createAutoCompleteDriver,
}) => {
  await initTestBed(`
    <AutoComplete readOnly="true" initialValue="1">
      <Option value="1" label="Bruce Wayne" />
      <Option value="2" label="Clark Kent" />
      <Option value="3" label="Diana Prince" />
    </AutoComplete>
  `);

  // Initial value should be displayed
  await expect(page.getByRole("combobox")).toHaveValue("Bruce Wayne");

  // Try to click to open dropdown
  const driver = await createAutoCompleteDriver();
  await driver.click();

  // Selection should not change
  await expect(page.getByRole("listbox")).not.toBeVisible();
});

test("disabled state prevents interaction", async ({
  initTestBed,
  page,
  createAutoCompleteDriver,
}) => {
  await initTestBed(`
    <AutoComplete enabled="false">
      <Option value="1" label="Bruce Wayne" />
      <Option value="2" label="Clark Kent" />
      <Option value="3" label="Diana Prince" />
    </AutoComplete>
  `);

  const driver = await createAutoCompleteDriver();

  // Try to click to open dropdown
  await driver.click({ force: true });

  // Try to type in the input
  await page.keyboard.type("Joker");

  // Dropdown should not open
  await expect(page.getByRole("listbox")).not.toBeVisible();

  // Input should not change
  await expect(page.getByRole("combobox")).toHaveValue("");
});

// =============================================================================
// API AND EVENT TESTS
// =============================================================================

test("didChange event fires when option is selected", async ({
  initTestBed,
  page,
  createAutoCompleteDriver,
}) => {
  await initTestBed(`
    <App var.selectedValue="">
      <AutoComplete id="autoComplete" onDidChange="(val) => selectedValue = val">
        <Option value="1" label="Bruce Wayne" />
        <Option value="2" label="Clark Kent" />
        <Option value="3" label="Diana Prince" />
      </AutoComplete>
      <Text testId="text">{selectedValue}</Text>
    </App>
  `);

  const driver = await createAutoCompleteDriver("autoComplete");
  await driver.click();
  await driver.selectLabel("Diana Prince");

  await expect(page.getByTestId("text")).toHaveText("3");
});

test("gotFocus and lostFocus events work correctly", async ({
  initTestBed,
  page,
  createAutoCompleteDriver,
}) => {
  await initTestBed(`
    <App var.isFocused="false">
      <Text testId="focusText">{isFocused === true ? 'AutoComplete focused' : 'AutoComplete lost focus'}</Text>
      <AutoComplete
        id="autoComplete"
        onGotFocus="isFocused = true"
        onLostFocus="isFocused = false"
      >
        <Option value="1" label="Bruce Wayne" />
      </AutoComplete>
    </App>
  `);

  // Initial state
  await expect(page.getByTestId("focusText")).toHaveText("AutoComplete lost focus");

  // Focus the autocomplete
  const driver = await createAutoCompleteDriver("autoComplete");
  await driver.click();

  await expect(page.getByTestId("focusText")).toHaveText("AutoComplete focused");

  // Blur the autocomplete
  await page.keyboard.press("Tab");
  await expect(page.getByTestId("focusText")).toHaveText("AutoComplete lost focus");
});

test("gotFocus and lostFocus events by clicking on label work correctly", async ({
  initTestBed,
  page,
}) => {
  await initTestBed(`
    <App var.isFocused="false">
      <Text testId="focusText">{isFocused === true ? 'AutoComplete focused' : 'AutoComplete lost focus'}</Text>
      <AutoComplete
        id="autoComplete"
        label="Select a hero"
        onGotFocus="isFocused = true"
        onLostFocus="isFocused = false"
      >
        <Option value="1" label="Bruce Wayne" />
      </AutoComplete>
    </App>
  `);

  // Initial state
  await expect(page.getByTestId("focusText")).toHaveText("AutoComplete lost focus");

  // Focus the autocomplete
  await page.getByText("Select a hero").click();

  await expect(page.getByTestId("focusText")).toHaveText("AutoComplete focused");

  // Blur the autocomplete
  await page.keyboard.press("Tab");
  await expect(page.getByTestId("focusText")).toHaveText("AutoComplete lost focus");
});

test("setValue API works correctly", async ({ initTestBed, page }) => {
  await initTestBed(`
    <App>
      <AutoComplete id="autoComplete">
        <Option value="1" label="Bruce Wayne" />
        <Option value="2" label="Clark Kent" />
        <Option value="3" label="Diana Prince" />
      </AutoComplete>
      <Button
        testId="setButton"
        label="Set Value"
        onClick="autoComplete.setValue('2')" />
      <Text testId="text">Selected value: {autoComplete.value}</Text>
    </App>
  `);

  // Initially no selection
  await expect(page.getByTestId("text")).toHaveText("Selected value: ");

  // Set the value using the API
  await page.getByTestId("setButton").click();
  await expect(page.getByTestId("text")).toHaveText("Selected value: 2");
  await expect(page.getByRole("combobox")).toHaveValue("Clark Kent");
});

test("focus API brings focus to the component", async ({ initTestBed, page }) => {
  await initTestBed(`
    <App var.isFocused="false">
      <Text testId="focusText">{isFocused === true ? 'AutoComplete focused' : 'AutoComplete lost focus'}</Text>
 
      <AutoComplete id="autoComplete">
        <Option value="1" label="Bruce Wayne" />
      </AutoComplete>
      <Button
        testId="focusButton"
        label="Focus AutoComplete"
        onClick="autoComplete.focus()" />
    </App>
  `);

  // Initial state
  await expect(page.getByTestId("focusText")).toHaveText("AutoComplete lost focus");

  // Focus the autocomplete using the API
  await page.getByTestId("focusButton").click();

  // Check if the autocomplete is focused
  await expect(page.getByTestId("focusText")).toHaveText("AutoComplete lost focus");

  const isFocused = await page
    .getByRole("combobox")
    .evaluate((el) => document.activeElement === el);
  expect(isFocused).toBeTruthy();
});

test("autoFocus brings focus to the component on load", async ({ initTestBed, page }) => {
  await initTestBed(`
    <App var.isFocused="false">
      <Text testId="focusText">{isFocused === true ? 'AutoComplete focused' : 'AutoComplete lost focus'}</Text>
      <AutoComplete autoFocus="true" onGotFocus="isFocused = true">
        <Option value="1" label="Bruce Wayne" />
      </AutoComplete>
    </App>
  `);

  await expect(page.getByTestId("focusText")).toHaveText("AutoComplete focused");
});

test("creates new option when typing non-existing value", async ({
  initTestBed,
  page,
  createAutoCompleteDriver,
}) => {
  const { testStateDriver } = await initTestBed(`
    <Fragment>
      <AutoComplete id="autoComplete" creatable="true" onItemCreated="item => testState = item">
        <Option value="1" label="Bruce Wayne" />
        <Option value="2" label="Clark Kent" />
      </AutoComplete>
    </Fragment>
  `);

  const driver = await createAutoCompleteDriver("autoComplete");
  await driver.click();

  // Type a new option
  await page.keyboard.type("Peter Parker");
  await page.keyboard.press("Enter");

  expect(await testStateDriver.testState()).toBe("Peter Parker");
});

// =============================================================================
// ACCESSIBILITY TESTS
// =============================================================================

test("has appropriate ARIA attributes", async ({ initTestBed, page }) => {
  // ), //   "There's a weird issue where the aria-expanded attribute is not set correctly on the input but it is on the wrapping div.", // SKIP_REASON.XMLUI_BUG(
  // TODO: review these Copilot-created tests
  await initTestBed(`
    <AutoComplete label="Select a hero" placeholder="Search heroes">
      <Option value="1" label="Bruce Wayne" />
      <Option value="2" label="Clark Kent" />
      <Option value="3" label="Diana Prince" />
    </AutoComplete>
  `);

  // Get the combobox element
  const listWrapper = page.locator('[data-part-id="listWrapper"]').first();
  const combobox = page.getByRole("combobox");

  // Check initial ARIA attributes
  await expect(combobox).toHaveAttribute("aria-autocomplete", "list");
  await expect(listWrapper).toHaveAttribute("aria-expanded", "false");

  // Open the dropdown
  await combobox.focus();
  await page.keyboard.press("Enter");

  // Check expanded state
  await expect(listWrapper).toHaveAttribute("aria-expanded", "true");
});

test("supports keyboard navigation with arrow keys", async ({ initTestBed, page }) => {
  await initTestBed(`
    <AutoComplete id="autoComplete">
      <Option value="1" label="Bruce Wayne" />
      <Option value="2" label="Clark Kent" />
      <Option value="3" label="Diana Prince" />
    </AutoComplete>
  `);

  // Focus the autocomplete
  await page.getByRole("combobox").focus();

  // Open dropdown with arrow down
  await page.keyboard.press("ArrowDown", { delay: 100 });
  await expect(page.getByRole("listbox")).toBeVisible();

  // Navigate through options
  await page.keyboard.press("ArrowDown", { delay: 100 }); // First option
  await page.keyboard.press("ArrowDown", { delay: 100 }); // Second option
  await page.keyboard.press("ArrowDown", { delay: 100 }); // Third option
  await page.keyboard.press("ArrowUp", { delay: 100 }); // Back to second option

  // Select with Enter
  await page.keyboard.press("Enter", { delay: 100 });

  // Verify selection
  await expect(page.getByRole("combobox")).toHaveValue("Clark Kent");
});

// =============================================================================
// VISUAL STATE TESTS
// =============================================================================

test("input has correct width in px", async ({ page, initTestBed }) => {
  await initTestBed(`<AutoComplete width="200px" testId="test"/>`, {});

  const input = page.getByTestId("test");
  const { width } = await input.boundingBox();
  expect(width).toBe(200);
});

test("input with label has correct width in px", async ({ page, initTestBed }) => {
  await initTestBed(`<AutoComplete width="200px" label="test" testId="test"/>`, {});

  const input = page.getByTestId("test");
  const { width } = await input.boundingBox();
  expect(width).toBe(200);
});

test("input has correct width in %", async ({ page, initTestBed }) => {
  await page.setViewportSize({ width: 400, height: 300 });
  await initTestBed(`<AutoComplete width="50%" testId="test"/>`, {});

  const input = page.getByTestId("test");
  const { width } = await input.boundingBox();
  expect(width).toBe(200);
});

test("input with label has correct width in %", async ({ page, initTestBed }) => {
  await page.setViewportSize({ width: 400, height: 300 });
  await initTestBed(`<AutoComplete width="50%" label="test" testId="test"/>`, {});

  const input = page.getByTestId("test");
  const { width } = await input.boundingBox();
  expect(width).toBe(200);
});

// =============================================================================
// THEME VARIABLE TESTS
// =============================================================================

test.describe("Theme Variables", () => {
  [
    { value: "--default", prop: "" },
    { value: "--warning", prop: 'validationStatus="warning"' },
    { value: "--error", prop: 'validationStatus="error"' },
    { value: "--success", prop: 'validationStatus="valid"' },
  ].forEach((variant) => {
    test(`applies correct borderRadius ${variant.value}`, async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: { [`borderRadius-AutoComplete${variant.value}`]: "12px" },
      });
      await expect(page.getByTestId("test")).toHaveCSS("border-radius", "12px");
    });

    test(`applies correct borderColor ${variant.value}`, async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: { [`borderColor-AutoComplete${variant.value}`]: "rgb(255, 0, 0)" },
      });
      await expect(page.getByTestId("test")).toHaveCSS("border-color", "rgb(255, 0, 0)");
    });

    test(`applies correct borderWidth ${variant.value}`, async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: { [`borderWidth-AutoComplete${variant.value}`]: "1px" },
      });
      await expect(page.getByTestId("test")).toHaveCSS("border-width", "1px");
    });

    test(`applies correct borderStyle ${variant.value}`, async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: { [`borderStyle-AutoComplete${variant.value}`]: "dashed" },
      });
      await expect(page.getByTestId("test")).toHaveCSS("border-style", "dashed");
    });

    test(`applies correct fontSize ${variant.value}`, async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: { [`fontSize-AutoComplete${variant.value}`]: "14px" },
      });
      await expect(page.getByTestId("test")).toHaveCSS("font-size", "14px");
    });

    test(`applies correct backgroundColor ${variant.value}`, async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: { [`backgroundColor-AutoComplete${variant.value}`]: "rgb(240, 240, 240)" },
      });
      await expect(page.getByTestId("test")).toHaveCSS("background-color", "rgb(240, 240, 240)");
    });

    test(`applies correct boxShadow ${variant.value}`, async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: {
          [`boxShadow-AutoComplete${variant.value}`]: "0 2px 8px rgba(0, 0, 0, 0.1)",
        },
      });
      await expect(page.getByTestId("test")).toHaveCSS(
        "box-shadow",
        "rgba(0, 0, 0, 0.1) 0px 2px 8px 0px",
      );
    });

    test(`applies correct textColor ${variant.value}`, async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: { [`textColor-AutoComplete${variant.value}`]: "rgb(0, 0, 0)" },
      });
      await expect(page.getByTestId("test")).toHaveCSS("color", "rgb(0, 0, 0)");
    });

    test(`applies correct borderColor on hover ${variant.value}`, async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: { [`borderColor-AutoComplete${variant.value}--hover`]: "rgb(0, 0, 0)" },
      });
      await page.getByTestId("test").hover();
      await expect(page.getByTestId("test")).toHaveCSS("border-color", "rgb(0, 0, 0)");
    });

    test(`applies correct backgroundColor on hover ${variant.value}`, async ({
      initTestBed,
      page,
    }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: { [`backgroundColor-AutoComplete${variant.value}--hover`]: "rgb(0, 0, 0)" },
      });
      await page.getByTestId("test").hover();
      await expect(page.getByTestId("test")).toHaveCSS("background-color", "rgb(0, 0, 0)");
    });

    test(`applies correct boxShadow on hover ${variant.value}`, async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: {
          [`boxShadow-AutoComplete${variant.value}--hover`]: "0 2px 8px rgba(0, 0, 0, 0.1)",
        },
      });
      await page.getByTestId("test").hover();
      await expect(page.getByTestId("test")).toHaveCSS(
        "box-shadow",
        "rgba(0, 0, 0, 0.1) 0px 2px 8px 0px",
      );
    });

    test(`applies correct textColor on hover ${variant.value}`, async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" ${variant.prop} />`, {
        testThemeVars: { [`textColor-AutoComplete${variant.value}--hover`]: "rgb(0, 0, 0)" },
      });
      await page.getByTestId("test").hover();
      await expect(page.getByTestId("test")).toHaveCSS("color", "rgb(0, 0, 0)");
    });
  });

  test("applies correct textColor to placeholder", async ({ initTestBed, page }) => {
    await initTestBed(`<AutoComplete testId="test" placeholder="Search..." />`, {
      testThemeVars: { "textColor-placeholder-AutoComplete": "rgb(0, 0, 0)" },
    });
    const placeholderColor = await page.evaluate(() => {
      const input = document.querySelector("input");
      return window.getComputedStyle(input, "::placeholder").color;
    });
    expect(placeholderColor).toBe("rgb(0, 0, 0)");
  });

  test.fixme(
    "applies correct fontSize to placeholder",
    SKIP_REASON.UNSURE("Does AutoComplete applies the correct css for the placeholder?"),
    async ({ initTestBed, page }) => {
      await initTestBed(`<AutoComplete testId="test" placeholder="Search..." />`, {
        testThemeVars: { "fontSize-placeholder-AutoComplete--default": "20px" },
      });
      const placeholderFontSize = await page.evaluate(() => {
        const input = document.querySelector("input");
        return window.getComputedStyle(input, "::placeholder").fontSize;
      });
      expect(placeholderFontSize).toBe("20px");
    },
  );
});

```

--------------------------------------------------------------------------------
/xmlui/src/components/App/App.tsx:
--------------------------------------------------------------------------------

```typescript
import styles from "./App.module.scss";
import drawerStyles from "./Sheet.module.scss";

import { type ComponentDef } from "../../abstractions/ComponentDefs";
import { createComponentRenderer } from "../../components-core/renderers";
import { parseScssVar } from "../../components-core/theming/themeVars";

import { createMetadata, dComponent } from "../../components/metadata-helpers";
import { appLayoutMd } from "./AppLayoutContext";
import { App, defaultProps } from "./AppNative";
import type { CSSProperties } from "react";
import { useCallback, useEffect, useMemo, useRef, useState, useTransition } from "react";
import type { PageMd } from "../Pages/Pages";
import type { RenderChildFn } from "../../abstractions/RendererDefs";
import { IndexerContext } from "./IndexerContext";
import { createPortal } from "react-dom";
import { useAppContext } from "../../components-core/AppContext";
import { useSearchContextSetIndexing, useSearchContextUpdater } from "./SearchContext";

// --- Define a structure to represent navigation hierarchy
interface NavHierarchyNode {
  type: string;
  label: string;
  path?: string;
  children?: NavHierarchyNode[];
}

const COMP = "App";

export const AppMd = createMetadata({
  status: "stable",
  description:
    "The `App` component is the root container that defines your application's overall " +
    "structure and layout. It provides a complete UI framework with built-in navigation, " +
    "header, footer, and content areas that work together seamlessly.",
  props: {
    layout: {
      description:
        `This property sets the layout template of the app. This setting determines the position ` +
        `and size of the app parts (such as header, navigation bar, footer, etc.) and the app's ` +
        `scroll behavior.`,
      availableValues: appLayoutMd,
    },
    loggedInUser: {
      description:
        "Stores information about the currently logged-in user. By not defining this property, " +
        "you can indicate that no user is logged in.",
      valueType: "string",
    },
    logoTemplate: dComponent("Optional template of the app logo"),
    logo: {
      description: "Optional logo path",
      valueType: "string",
    },
    "logo-dark": {
      description: "Optional logo path in dark tone",
      valueType: "string",
    },
    "logo-light": {
      description: "Optional logo path in light tone",
      valueType: "string",
    },
    name: {
      description:
        "Optional application name (visible in the browser tab). When you do not define " +
        "this property, the tab name falls back to the one defined in the app\'s configuration. " +
        'If the name is not configured, "XMLUI App" is displayed in the tab.',
      valueType: "string",
    },
    scrollWholePage: {
      description:
        `This boolean property specifies whether the whole page should scroll (\`true\`) or just ` +
        `the content area (\`false\`). The default value is \`true\`.`,
      valueType: "boolean",
      defaultValue: defaultProps.scrollWholePage,
    },
    noScrollbarGutters: {
      description:
        "This boolean property specifies whether the scrollbar gutters should be hidden.",
      valueType: "boolean",
      defaultValue: defaultProps.noScrollbarGutters,
    },
    defaultTone: {
      description: 'This property sets the app\'s default tone ("light" or "dark").',
      valueType: "string",
      defaultValue: defaultProps.defaultTone,
      availableValues: ["light", "dark"],
    },
    defaultTheme: {
      description: "This property sets the app's default theme.",
      valueType: "string",
      defaultValue: defaultProps.defaultTheme,
    },
    autoDetectTone: {
      description: 
        'This boolean property enables automatic detection of the system theme preference. ' +
        'When set to true and no defaultTone is specified, the app will automatically use ' +
        '"light" or "dark" tone based on the user\'s system theme setting. The app will ' +
        'also respond to changes in the system theme preference.',
      valueType: "boolean",
      defaultValue: defaultProps.autoDetectTone,
    },
  },
  events: {
    ready: {
      description: `This event fires when the \`${COMP}\` component finishes rendering on the page.`,
    },
    messageReceived: {
      description: `This event fires when the \`${COMP}\` component receives a message from another window or iframe via the window.postMessage API.`,
    },
  },
  themeVars: { ...parseScssVar(styles.themeVars), ...parseScssVar(drawerStyles.themeVars) },
  limitThemeVarsToComponent: true,
  themeVarDescriptions: {
    "maxWidth-content-App":
      "This theme variable defines the maximum width of the main content. If the main " +
      "content is broader, the engine adds margins to keep the expected maximum size.",
    "boxShadow‑header‑App": "This theme variable sets the shadow of the app's header section.",
    "boxShadow‑navPanel‑App":
      "This theme variable sets the shadow of the app's navigation panel section " +
      "(visible only in vertical layouts).",
    "width‑navPanel‑App":
      "This theme variable sets the width of the navigation panel when the app is displayed " +
      "with one of the vertical layouts.",
  },
  defaultThemeVars: {
    "maxWidth-Drawer": "100%",
    [`width-navPanel-${COMP}`]: "$space-64",
    [`backgroundColor-navPanel-${COMP}`]: "$backgroundColor",
    [`maxWidth-content-${COMP}`]: "$maxWidth-content",
    [`boxShadow-header-${COMP}`]: "none",
    [`boxShadow-navPanel-${COMP}`]: "$boxShadow-spread",
    [`scroll-padding-block-Pages`]: "$space-4",
    [`backgroundColor-content-App`]: "$backgroundColor",
    light: {
      // --- No light-specific theme vars
    },
    dark: {
      // --- No dark-specific theme vars
    },
  },
});


function AppNode({ node, extractValue, renderChild, className, lookupEventHandler, registerComponentApi }) {
  // --- Use ref to track if we've already processed the navigation to avoid duplicates in strict mode
  const processedNavRef = useRef(false);

  // --- Memoize the layout type to avoid unnecessary re-extraction
  const layoutType = useMemo(
    () => extractValue(node.props.layout),
    [node.props.layout, extractValue],
  );

  // --- Memoize helper functions that are used in multiple places

  // --- Parse a string into hierarchy labels, handling escaped pipe characters
  const parseHierarchyLabels = useMemo(() => {
    // Cache to hold previously computed results
    const cache = new Map<string, string[]>();

    return (labelText: string): string[] => {
      // Return cached result if we've seen this input before
      if (cache.has(labelText)) {
        return cache.get(labelText)!;
      }

      const result: string[] = [];
      let currentLabel = "";
      let escaped = false;

      for (let i = 0; i < labelText.length; i++) {
        const char = labelText[i];

        if (escaped) {
          // --- If this character was escaped, just add it literally
          currentLabel += char;
          escaped = false;
        } else if (char === "\\") {
          // --- Start of an escape sequence
          escaped = true;
        } else if (char === "|") {
          // --- Unescaped pipe indicates hierarchy separator
          result.push(currentLabel.trim());
          currentLabel = "";
        } else {
          // --- Regular character
          currentLabel += char;
        }
      }

      // --- Don't forget to add the last segment
      if (currentLabel.length > 0) {
        result.push(currentLabel.trim());
      }

      // Cache the result
      cache.set(labelText, result);

      return result;
    };
  }, []);

  // --- Helper function to check if a label exists in the navigation hierarchy
  const labelExistsInHierarchy = useMemo(() => {
    // Cache for previously checked labels within a hierarchy
    const cache = new Map<string, boolean>();

    return (searchLabel: string, hierarchy: any[]): boolean => {
      // Create a cache key (could be improved with a better serialization of hierarchy)
      const cacheKey = searchLabel + "_" + hierarchy.length;

      if (cache.has(cacheKey)) {
        return cache.get(cacheKey)!;
      }

      const result = hierarchy.some((node) => {
        if (node.label === searchLabel) {
          return true;
        }

        if (node.children && node.children.length > 0) {
          return labelExistsInHierarchy(searchLabel, node.children);
        }

        return false;
      });

      cache.set(cacheKey, result);
      return result;
    };
  }, []);

  // --- Helper function to find or create NavGroups in the hierarchy
  const findOrCreateNavGroup = useMemo(() => {
    return (navItems: any[], groupLabel: string): any => {
      // --- Check if a NavGroup with this label already exists
      const existingGroup = navItems.find(
        (item) => item.type === "NavGroup" && item.props?.label === groupLabel,
      );

      if (existingGroup) {
        return existingGroup;
      }

      // --- Create a new NavGroup and add it to the array
      const newGroup = {
        type: "NavGroup",
        props: {
          label: groupLabel,
        },
        children: [],
      };

      navItems.push(newGroup);
      return newGroup;
    };
  }, []);

  const { AppHeader, Footer, NavPanel, Pages, restChildren } = useMemo(() => {
    let AppHeader: ComponentDef;
    let Footer: ComponentDef;
    let NavPanel: ComponentDef;
    let Pages: ComponentDef;
    const restChildren: any[] = [];
    node.children?.forEach((rootChild) => {
      let transformedChild = { ...rootChild };
      if (rootChild.type === "Theme") {
        transformedChild.children = rootChild.children?.filter((child) => {
          if (child.type === "AppHeader") {
            AppHeader = {
              ...rootChild,
              children: [child],
            };
            return false;
          } else if (child.type === "Footer") {
            Footer = {
              ...rootChild,
              children: [child],
            };
            return false;
          } else if (child.type === "NavPanel") {
            NavPanel = {
              ...rootChild,
              children: [child],
            };
            return false;
          }
          return true;
        });
        if (!transformedChild.children.length) {
          transformedChild = null;
        }
      }
      if (rootChild.type === "AppHeader") {
        AppHeader = rootChild;
      } else if (rootChild.type === "Footer") {
        Footer = rootChild;
      } else if (rootChild.type === "NavPanel") {
        NavPanel = rootChild;
      } else if (rootChild.type === "Pages") {
        Pages = rootChild;
        restChildren.push(transformedChild);
      } else if (transformedChild !== null) {
        restChildren.push(transformedChild);
      }
    });

    // --- Check if there is any extra NavPanel in Pages
    const extraNavs = extractNavPanelFromPages(
      Pages,
      NavPanel,
      processedNavRef,
      extractValue,
      parseHierarchyLabels,
      labelExistsInHierarchy,
      findOrCreateNavGroup,
    );

    // --- If we found extra navigation items
    if (extraNavs?.length) {
      if (NavPanel) {
        // --- Create a new NavPanel with combined children instead of mutating the existing one
        NavPanel = {
          ...NavPanel,
          children: NavPanel.children ? [...NavPanel.children, ...extraNavs] : extraNavs,
        };
      } else {
        // --- Create a new NavPanel component definition if none exists
        NavPanel = {
          type: "NavPanel",
          props: {},
          children: extraNavs,
        };
      }
    }

    return {
      AppHeader,
      Footer,
      NavPanel,
      Pages,
      restChildren,
    };
  }, [
    node.children,
    extractValue,
    parseHierarchyLabels,
    labelExistsInHierarchy,
    findOrCreateNavGroup,
  ]);

  const applyDefaultContentPadding= !Pages;

  // --- Memoize all app props to prevent unnecessary re-renders
  const appProps = useMemo(
    () => ({
      scrollWholePage: extractValue.asOptionalBoolean(node.props.scrollWholePage, true),
      noScrollbarGutters: extractValue.asOptionalBoolean(node.props.noScrollbarGutters, false),
      className,
      layout: layoutType,
      loggedInUser: extractValue(node.props.loggedInUser),
      onReady: lookupEventHandler("ready"),
      onMessageReceived: lookupEventHandler("messageReceived"),
      name: extractValue(node.props.name),
      logo: extractValue(node.props.logo),
      logoDark: extractValue(node.props["logo-dark"]),
      logoLight: extractValue(node.props["logo-light"]),
      defaultTone: extractValue(node.props.defaultTone),
      defaultTheme: extractValue(node.props.defaultTheme),
      autoDetectTone: extractValue.asOptionalBoolean(node.props.autoDetectTone, false),
      applyDefaultContentPadding
    }),
    [
      extractValue,
      layoutType,
      lookupEventHandler,
      node.props.loggedInUser,
      node.props.noScrollbarGutters,
      node.props.scrollWholePage,
      node.props.name,
      node.props.logo,
      node.props["logo-dark"],
      node.props["logo-light"],
      node.props.defaultTone,
      node.props.defaultTheme,
      node.props.autoDetectTone,
      className,
      applyDefaultContentPadding
    ],
  );

  // Memoize the rendered children to prevent unnecessary re-renders
  const renderedHeader = useMemo(() => renderChild(AppHeader), [AppHeader, renderChild]);
  const renderedFooter = useMemo(() => renderChild(Footer), [Footer, renderChild]);
  const renderedNavPanel = useMemo(() => renderChild(NavPanel), [NavPanel, renderChild]);
  const renderedContent = useMemo(() => renderChild(restChildren), [restChildren, renderChild]);

  return (
    <App
      {...appProps}
      header={renderedHeader}
      footer={renderedFooter}
      navPanel={renderedNavPanel}
      navPanelDef={NavPanel}
      logoContentDef={node.props.logoTemplate}
      renderChild={renderChild}
      registerComponentApi={registerComponentApi}
    >
      {renderedContent}
      <SearchIndexCollector Pages={Pages} renderChild={renderChild} />
    </App>
  );
}

const HIDDEN_STYLE: CSSProperties = {
  position: "absolute",
  top: "-9999px",
  display: "none",
};

const indexerContextValue = {
  indexing: true,
};

function SearchIndexCollector({ Pages, renderChild }) {
  const appContext = useAppContext();
  const setIndexing = useSearchContextSetIndexing();

  const [isClient, setIsClient] = useState(false);
  useEffect(() => {
    setIsClient(true); // Ensure document.body is available

    return () => {
      setIndexing(false);
    };
  }, [setIndexing]);

  // 1. Memoize the list of pages to be indexed
  const pagesToIndex = useMemo(() => {
    return (
      Pages?.children?.filter(
        (child) =>
          child.type === "Page" && // Ensure 'Page' matches your actual component type name
          child.props?.url && // Ensure URL exists
          !child.props.url.includes("*") &&
          !child.props.url.includes(":"),
      ) || []
    );
  }, [Pages?.children]);

  const [currentIndex, setCurrentIndex] = useState(0);
  const [isDoneIndexing, setIsDoneIndexing] = useState(false);
  const [, startTransitionParent] = useTransition(); // Transition for parent updates

  const handlePageIndexed = useCallback(() => {
    startTransitionParent(() => {
      // Transition the update to the next page
      setCurrentIndex((prevIndex) => {
        const nextIndex = prevIndex + 1;
        if (nextIndex >= pagesToIndex.length) {
          // console.log("All pages indexed.");
          setIsDoneIndexing(true); // All pages processed
        }
        return nextIndex;
      });
    });
  }, [pagesToIndex.length]); // Recreate if the total number of pages changes

  if (!appContext.appGlobals?.searchIndexEnabled || isDoneIndexing || !isClient) {
    return null;
  }

  const currentPageToProcess = pagesToIndex[currentIndex];

  if (!currentPageToProcess) {
    // This can happen if pagesToIndex is empty or currentIndex went out of bounds unexpectedly.
    // Setting isDoneIndexing if pagesToIndex is empty initially.
    if (pagesToIndex.length === 0 && currentIndex === 0 && !isDoneIndexing) {
      setIsDoneIndexing(true);
    }
    return null;
  }

  return (
    <IndexerContext.Provider value={indexerContextValue}>
      {createPortal(
        <div style={HIDDEN_STYLE} aria-hidden="true">
          {/* Render only one PageIndexer at a time */}
          <PageIndexer
            Page={currentPageToProcess}
            renderChild={renderChild}
            onIndexed={handlePageIndexed}
            key={currentPageToProcess.props?.url || currentIndex} // Key ensures re-mount
          />
        </div>,
        document.body,
      )}
    </IndexerContext.Provider>
  );
}

function PageIndexer({
  Page,
  renderChild,
  onIndexed,
}: {
  Page: ComponentDef<typeof PageMd>; // Use the defined PageMdProps
  renderChild: RenderChildFn;
  onIndexed: () => void;
}) {
  const contentRef = useRef<HTMLDivElement>(null);
  const pageUrl = Page.props?.url || "";
  const navLabel = Page.props?.navLabel || "";
  const searchContextUpdater = useSearchContextUpdater();

  const [isContentRendered, setIsContentRendered] = useState(false);
  const [isCollected, setIsCollected] = useState(false);
  const [isProcessing, startTransition] = useTransition();

  // Effect 1: Schedule the rendering of the Page's children (low priority)
  useEffect(() => {
    // console.log(`PageIndexer (${pageUrl}): Scheduling content render.`);
    startTransition(() => {
      setIsContentRendered(true); // This will trigger rendering of Page.children
    });
  }, [pageUrl]); // Re-run if the Page prop itself changes identity (due to key in parent)

  // Effect 2: Extract content once Page.children is rendered and ref is available (low priority)
  useEffect(() => {
    if (isContentRendered && contentRef.current && !isCollected && !isProcessing) {
      // console.log(`PageIndexer (${pageUrl}): Content rendered, scheduling extraction.`);
      startTransition(() => {
        // console.log(`PageIndexer (${pageUrl}): Starting extraction...`);
        const currentContent = contentRef.current; // Capture ref value
        if (!currentContent) return;

        const clone = currentContent.cloneNode(true) as HTMLDivElement;
        const elementsToRemove = clone.querySelectorAll("style, script");
        elementsToRemove.forEach((el) => el.remove());
        const titleElement = clone.querySelector("h1");
        const title = titleElement
          ? titleElement.innerText
          : navLabel || pageUrl.split("/").pop() || pageUrl;
        titleElement?.remove(); // Remove title element from clone to avoid duplication
        const textContent = (clone.textContent || "").trim().replace(/\s+/g, " ");

        const entry = {
          title: title,
          content: textContent,
          path: pageUrl,
        };

        searchContextUpdater(entry);
        // console.log(`PageIndexer (${pageUrl}): Extraction complete, signaling parent.`);
        onIndexed(); // Signal completion to parent
        setIsCollected(true); // Mark as collected
      });
    }
  }, [
    isContentRendered,
    pageUrl,
    searchContextUpdater,
    onIndexed,
    isCollected,
    isProcessing,
    navLabel,
  ]); // Ensure all dependencies are listed

  // If this PageIndexer instance's work is done, or content not yet rendered, render nothing.
  // The parent (SearchIndexCollector) will unmount this and mount the next one.
  if (isCollected || !isContentRendered) {
    // console.log(`PageIndexer (${pageUrl}): Null render (isCollected: ${isCollected}, isContentRendered: ${isContentRendered})`);
    return null;
  }

  // This part renders when isContentRendered is true and isCollected is false.
  // The content needs to be in the DOM for contentRef.current to be populated.
  // console.log(`PageIndexer (${pageUrl}): Rendering content for ref population.`);
  return <div ref={contentRef}>{renderChild(Page.children)}</div>;
}

export const appRenderer = createComponentRenderer(
  COMP,
  AppMd,
  ({ node, extractValue, renderChild, className, lookupEventHandler, registerComponentApi }) => {
    return (
      <AppNode
        node={node}
        renderChild={renderChild}
        extractValue={extractValue}
        className={className}
        lookupEventHandler={lookupEventHandler}
        registerComponentApi={registerComponentApi}
      />
    );
  },
);

// --- Process the entire navigation tree recursively and build hierarchy
function processNavItems(
  items: ComponentDef[],
  parentHierarchy: NavHierarchyNode[],
  extractValue: (value: any) => any,
) {
  items.forEach((navItem) => {
    // --- Process NavLink items
    if (navItem.type === "NavLink") {
      let itemLabel = navItem.props?.label;
      let itemPath = navItem.props?.to;

      if (!itemLabel) {
        if (navItem.children?.length === 1 && navItem.children[0].type === "TextNode") {
          itemLabel = navItem.children[0].props.value;
        }
      }

      if (itemLabel) {
        const labelValue = extractValue(itemLabel);

        // --- Add to hierarchy
        parentHierarchy.push({
          type: "NavLink",
          label: labelValue,
          path: itemPath ? extractValue(itemPath) : undefined,
        });
      }
    }
    // --- Process NavGroup items (which may contain nested NavLink or NavGroup items)
    else if (navItem.type === "NavGroup") {
      let groupLabel = navItem.props?.label;

      if (groupLabel) {
        const labelValue = extractValue(groupLabel);

        // --- Create group node
        const groupNode: NavHierarchyNode = {
          type: "NavGroup",
          label: labelValue,
          children: [],
        };

        // --- Add to parent hierarchy
        parentHierarchy.push(groupNode);

        // --- Recursively process children of the NavGroup
        if (navItem.children && navItem.children.length > 0) {
          processNavItems(navItem.children, groupNode.children, extractValue);
        }
      } else if (navItem.children && navItem.children.length > 0) {
        // --- If no label but has children, still process them under parent
        processNavItems(navItem.children, parentHierarchy, extractValue);
      }
    }
  });
}

// --- Extract navigation panel items from Pages component
function extractNavPanelFromPages(
  Pages: ComponentDef,
  NavPanel: ComponentDef | undefined,
  processedNavRef: React.MutableRefObject<boolean>,
  extractValue: (value: any) => any,
  parseHierarchyLabels: (labelText: string) => string[],
  labelExistsInHierarchy: (searchLabel: string, hierarchy: NavHierarchyNode[]) => boolean,
  findOrCreateNavGroup: (navItems: ComponentDef[], groupLabel: string) => ComponentDef,
): ComponentDef[] | null {
  // --- Skip extraction if we've already processed this navigation structure
  // --- This prevents duplicate items when React renders twice in strict mode
  if (!Pages || processedNavRef.current) return null;

  // --- Mark as processed
  processedNavRef.current = true;

  const extraNavs: ComponentDef[] = [];

  // --- Root of navigation hierarchy
  const navigationHierarchy: NavHierarchyNode[] = [];

  // --- Start processing the navigation tree if NavPanel exists
  if (NavPanel?.children) {
    processNavItems(NavPanel.children, navigationHierarchy, extractValue);
  }

  // --- Process Pages to create hierarchical navigation structure
  Pages.children?.forEach((page) => {
    if (page.type === "Page" && page.props.navLabel) {
      const label = extractValue(page.props.navLabel);
      const url = extractValue(page.props.url);

      // --- Parse hierarchy labels separated by unescaped pipe characters
      const hierarchyLabels = parseHierarchyLabels(label);

      // --- Skip if we have no labels
      if (hierarchyLabels.length === 0) {
        return;
      }

      // --- For a single level, just add a NavLink directly
      if (hierarchyLabels.length === 1) {
        // --- Check if this exact NavLink already exists in the navigation hierarchy
        if (!labelExistsInHierarchy(hierarchyLabels[0], navigationHierarchy)) {
          extraNavs.push({
            type: "NavLink",
            props: {
              label: hierarchyLabels[0],
              to: url,
            },
          });
        }
        return;
      }

      // --- For multi-level hierarchies, create NavGroups and a final NavLink
      let currentLevel = extraNavs;

      // --- Create NavGroups for all levels except the last one
      for (let i = 0; i < hierarchyLabels.length - 1; i++) {
        const groupLabel = hierarchyLabels[i];
        const navGroup = findOrCreateNavGroup(currentLevel, groupLabel);

        // --- Initialize children array if it doesn't exist
        if (!navGroup.children) {
          navGroup.children = [];
        }

        // --- Move to the next level
        currentLevel = navGroup.children;
      }

      // --- Add the leaf NavLink to the deepest NavGroup
      const leafLabel = hierarchyLabels[hierarchyLabels.length - 1];

      // --- Check if this NavLink already exists at this level
      const existingNavLink = currentLevel.find(
        (item) => item.type === "NavLink" && item.props?.label === leafLabel,
      );

      if (!existingNavLink) {
        currentLevel.push({
          type: "NavLink",
          props: {
            label: leafLabel,
            to: url,
          },
        });
      }
    }
  });

  return extraNavs;
}

```
Page 80/144FirstPrevNextLast