#
tokens: 46848/50000 6/1630 files (page 49/143)
lines: off (toggle) GitHub
raw markdown copy
This is page 49 of 143. Use http://codebase.md/xmlui-org/xmlui/xmlui/mockApiDef.js?lines=false&page={x} to view the full context.

# Directory Structure

```
├── .changeset
│   ├── config.json
│   └── cyan-tools-design.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
│   │           ├── FancyButton.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
    │   │   ├── 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/src/components/Text/Text.md:
--------------------------------------------------------------------------------

```markdown
%-DESC-START

You can learn more about this component in the [Working with Text](/working-with-text) article.

Also note that variants of the `Text` component are also mapped to HtmlTag components.
See the [variant](#variant) section to check which variant maps to which HtmlTag.

## Custom Variants

In addition to the predefined variants, the `Text` component supports **custom variant names** that can be styled using theme variables. This allows you to create application-specific text styles without modifying the component itself.

When you use a custom variant name (one not in the predefined list), the component automatically applies theme variables following the naming pattern: `{cssProperty}-Text-{variantName}`.

```xmlui-pg display name="Example: custom variants"
<App>
  <Theme 
    textColor-Text-brandTitle="rgb(41, 128, 185)"
    fontSize-Text-brandTitle="28px"
    fontWeight-Text-brandTitle="bold"
    letterSpacing-Text-brandTitle="2px"
  >
    <Text variant="brandTitle">
      Welcome to Our Application
    </Text>
  </Theme>
</App>
```

In this example, the custom variant `brandTitle` is styled using theme variables. Any CSS text property can be configured, including `textColor`, `fontSize`, `fontWeight`, `fontFamily`, `textDecoration*`, `lineHeight`, `backgroundColor`, `textTransform`, `letterSpacing`, `wordSpacing`, `textShadow`, and more.

%-DESC-END

%-PROP-START maxLines

```xmlui-pg copy display name="Example: maxLines"
<App>
  <Text
    maxWidth="120px"
    backgroundColor="cyan"
    color="black"
    value="A long text that will likely overflow"
    maxLines="2" />
</App>
```

%-PROP-END

%-PROP-START ellipses

```xmlui-pg copy display name="Example: ellipses"
<App>
  <VStack width="120px">
    <Text
      backgroundColor="cyan"
      color="black"
      maxLines="1"
      ellipses="false">
      Though this long text does is about to crop!
    </Text>
    <Text
      backgroundColor="cyan"
      color="black"
      maxLines="1">
      Though this long text does is about to crop!
    </Text>
  </VStack>
</App>
```

%-PROP-END

%-PROP-START preserveLinebreaks

```xmlui-pg copy {7} display name="Example: preserveLinebreaks"
<App>
  <HStack>
    <Text
      width="250px"
      backgroundColor="cyan"
      color="black"
      preserveLinebreaks="true"
      value="(preserve) This long text

      with several line breaks


              does not fit into a viewport with a 200-pixel width." />
    <Text
      width="250px"
      backgroundColor="cyan"
      color="black"
      preserveLinebreaks="false"
      value="(don't preserve) This long text


      with several line breaks

      
              does not fit into a viewport with a 200-pixel width." />
  </HStack>
</App>
```

> **Note**: Remember to use the `value` property of the `Text`.
> Linebreaks are converted to spaces when nesting the text inside the `Text` component.

%-PROP-END

%-PROP-START value

```xmlui-pg copy display name="Example: value"
<App>
  <Text value="An example text" />
  <Text>An example text</Text>
</App>
```

%-PROP-END

%-PROP-START variant

```xmlui-pg name="Example: variant"
<App>
  <HStack>
    <Text width="150px">default:</Text>
    <Text>This is an example text</Text>
  </HStack>
  <HStack>
    <Text width="150px">paragraph:</Text>
    <Text variant="paragraph">This is an example paragraph</Text>
  </HStack>
  <HStack>
    <Text width="150px">abbr:</Text>
    <Text variant="abbr">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">cite:</Text>
    <Text variant="cite">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">code:</Text>
    <Text variant="code">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">deleted:</Text>
    <Text variant="deleted">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">inserted:</Text>
    <Text variant="inserted">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">keyboard:</Text>
    <Text variant="keyboard">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">marked:</Text>
    <Text variant="marked">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">sample:</Text>
    <Text variant="sample">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">sup:</Text>
    <Text>
      This is an example text
      <Text variant="sup">(with some additional text)</Text>
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">sub:</Text>
    <Text>
      This is an example text
      <Text variant="sub">(with some additional text)</Text>
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">var:</Text>
    <Text variant="var">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">mono:</Text>
    <Text variant="mono">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">strong:</Text>
    <Text variant="strong">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">em:</Text>
    <Text variant="em">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">title:</Text>
    <Text variant="title">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">subtitle:</Text>
    <Text variant="subtitle">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">small:</Text>
    <Text variant="small">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">caption:</Text>
    <Text variant="caption">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">placeholder:</Text>
    <Text variant="placeholder">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">subheading:</Text>
    <Text variant="subheading">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">tableheading:</Text>
    <Text variant="tableheading">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">secondary:</Text>
    <Text variant="secondary">
      This is an example text
    </Text>
  </HStack>
</App>
```

**HtmlTag Mappings**

The table below indicates which Text `variant` maps to which HtmlTag component.

| Variant     | Component |
| ----------- | --------- |
| `abbr`      | abbr      |
| `cite`      | cite      |
| `code`      | code      |
| `deleted`   | del       |
| `inserted`  | ins       |
| `keyboard`  | kbd       |
| `marked`    | mark      |
| `sample`    | samp      |
| `sub`       | sub       |
| `sup`       | sup       |
| `var`       | var       |
| `strong`    | strong    |
| `em`        | em        |
| `paragraph` | p         |

%-PROP-END

%-PROP-START overflowMode

```xmlui-pg copy display name="Example: overflowMode"
<App>
  <VStack gap="16px">
    <VStack gap="8px">
      <Text variant="strong">overflowMode="none"</Text>
      <Text
        width="200px"
        backgroundColor="lightcoral"
        padding="8px"
        overflowMode="none"
        maxLines="2">
        This is a very long text that will be clipped cleanly without 
        any overflow indicator when it exceeds the specified lines.
      </Text>
    </VStack>

    <VStack gap="8px">
      <Text variant="strong">overflowMode="ellipsis" (default)</Text>
      <Text
        width="200px"
        backgroundColor="lightblue"
        padding="8px"
        overflowMode="ellipsis"
        maxLines="1">
        This is a very long text that will show ellipsis when it 
        overflows the container width.
      </Text>
    </VStack>
    
    <VStack gap="8px">
      <Text variant="strong">overflowMode="scroll"</Text>
      <Text
        width="200px"
        backgroundColor="lightgreen"
        padding="8px"
        overflowMode="scroll">
        This is a very long text that will enable horizontal scrolling 
        when it overflows the container width.
      </Text>
    </VStack>
    
    <VStack gap="8px">
      <Text variant="strong">overflowMode="flow"</Text>
      <Text
        width="200px"
        height="100px"
        backgroundColor="lightyellow"
        padding="8px"
        overflowMode="flow">
        This is a very long text that will wrap to multiple lines and show 
        a vertical scrollbar when the content exceeds the container height. 
        This mode ignores maxLines and allows unlimited text wrapping with 
        vertical scrolling when needed.
      </Text>
    </VStack>
    
    <VStack gap="8px">
      <Text variant="strong">overflowMode="flow" (no height constraint)</Text>
      <Text
        width="200px"
        backgroundColor="lightpink"
        padding="8px"
        overflowMode="flow">
        This is a very long text that demonstrates flow mode without a 
        height constraint. The text will wrap to multiple lines naturally 
        and the container will grow to accommodate all the content. No 
        scrollbar will appear since there's no height limitation - the text 
        flows freely across as many lines as needed.
      </Text>
    </VStack>
  </VStack>
</App>
```

%-PROP-END

%-PROP-START breakMode

```xmlui-pg copy display name="Example: breakMode"
<App>
  <VStack gap="16px">
    <VStack gap="8px">
      <Text variant="strong">breakMode="normal" (default)</Text>
      <Text
        width="150px"
        backgroundColor="lightblue"
        padding="8px"
        breakMode="normal">
        This text uses standardwordbreaking at natural boundaries 
        like spaces and hyphens.
      </Text>
    </VStack>
    
    <VStack gap="8px">
      <Text variant="strong">breakMode="word"</Text>
      <Text
        width="150px"
        backgroundColor="lightgreen"
        padding="8px"
        breakMode="word">
        This text will breakverylongwordswhenneeded to prevent 
        overflow while preserving readability.
      </Text>
    </VStack>
    
    <VStack gap="8px">
      <Text variant="strong">breakMode="anywhere"</Text>
      <Text
        width="150px"
        backgroundColor="lightyellow"
        padding="8px"
        breakMode="anywhere">
        Thistext willbreakanywhereif neededtofit thecontainer 
        eveninthe middleofwords.
      </Text>
    </VStack>
    
    <VStack gap="8px">
      <Text variant="strong">breakMode="keep"</Text>
      <Text
        width="150px"
        backgroundColor="lightcoral"
        padding="8px"
        breakMode="keep">
        This text will keep verylongwords intact and prevent 
        breaking within words entirely.
      </Text>
    </VStack>
    
    <VStack gap="8px">
      <Text variant="strong">breakMode="hyphenate"</Text>
      <Text
        width="150px"
        backgroundColor="lavender"
        padding="8px"
        breakMode="hyphenate"
        lang="en">
        This text uses automatic hyphenation for 
        supercalifragilisticexpialidocious words.
      </Text>
    </VStack>
  </VStack>
</App>
```

%-PROP-END

%-STYLE-START

### Custom Variant Theme Variables

When using custom variants, you can style them using theme variables with the naming pattern `{propertyName}-Text-{variantName}`. The following CSS properties are supported:

| Theme Variable Name | Description | Example Value |
|---------------------|-------------|---------------|
| `textColor-Text-{variant}` | Text color | `rgb(255, 0, 0)`, `#ff0000`, `red` |
| `fontFamily-Text-{variant}` | Font family | `"Arial, sans-serif"`, `monospace` |
| `fontSize-Text-{variant}` | Font size | `16px`, `1.5rem`, `large` |
| `fontStyle-Text-{variant}` | Font style | `normal`, `italic`, `oblique` |
| `fontWeight-Text-{variant}` | Font weight | `normal`, `bold`, `700` |
| `fontStretch-Text-{variant}` | Font stretch | `normal`, `expanded`, `condensed` |
| `textDecorationLine-Text-{variant}` | Decoration line type | `none`, `underline`, `overline`, `line-through` |
| `textDecorationColor-Text-{variant}` | Decoration color | `rgb(255, 0, 0)`, `currentColor` |
| `textDecorationStyle-Text-{variant}` | Decoration style | `solid`, `dashed`, `dotted`, `wavy` |
| `textDecorationThickness-Text-{variant}` | Decoration thickness | `2px`, `from-font`, `auto` |
| `textUnderlineOffset-Text-{variant}` | Underline offset | `5px`, `0.2em`, `auto` |
| `lineHeight-Text-{variant}` | Line height | `1.5`, `24px`, `normal` |
| `backgroundColor-Text-{variant}` | Background color | `rgb(255, 255, 0)`, `transparent` |
| `textTransform-Text-{variant}` | Text transformation | `none`, `uppercase`, `lowercase`, `capitalize` |
| `letterSpacing-Text-{variant}` | Space between letters | `1px`, `0.1em`, `normal` |
| `wordSpacing-Text-{variant}` | Space between words | `5px`, `0.2em`, `normal` |
| `textShadow-Text-{variant}` | Text shadow | `2px 2px 4px rgba(0,0,0,0.5)` |
| `textIndent-Text-{variant}` | First line indentation | `20px`, `2em`, `0` |
| `textAlign-Text-{variant}` | Horizontal alignment | `left`, `center`, `right`, `justify` |
| `textAlignLast-Text-{variant}` | Last line alignment | `left`, `center`, `right`, `justify` |
| `wordBreak-Text-{variant}` | Word breaking behavior | `normal`, `break-all`, `keep-all` |
| `wordWrap-Text-{variant}` | Word wrapping | `normal`, `break-word` |
| `direction-Text-{variant}` | Text direction | `ltr`, `rtl` |
| `writingMode-Text-{variant}` | Writing mode | `horizontal-tb`, `vertical-rl`, `vertical-lr` |
| `lineBreak-Text-{variant}` | Line breaking rules | `auto`, `normal`, `strict`, `loose` |

```xmlui-pg  display name="Example: custom variant styles" /highlight/
<App>
  <Theme 
    textColor-Text-highlight="rgb(255, 193, 7)"
    fontWeight-Text-highlight="bold"
    backgroundColor-Text-highlight="rgba(0, 0, 0, 0.8)"
    padding-Text-highlight="4px 8px"
    textShadow-Text-highlight="0 2px 4px rgba(0,0,0,0.5)"
  >
    <Text variant="highlight">Important Notice</Text>
    <Text variant="highlight">This is Important Too</Text>
  </Theme>
</App>
```

%-STYLE-END
```

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

```typescript
import { test, expect } from "../../testing/fixtures";

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

test("component renders with basic props", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone>Upload Area</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toBeVisible();
  await expect(driver.component).toContainText("Upload Area");
});

test("component displays children content", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`
    <FileUploadDropZone>
      <Text>Drag files here</Text>
      <Button>Or click to browse</Button>
    </FileUploadDropZone>
  `);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toContainText("Drag files here");
  await expect(driver.component).toContainText("Or click to browse");
});

test("component handles disabled state", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  // TODO: Disabled state handling needs investigation
  await initTestBed(`<FileUploadDropZone enabled="false">Upload Area</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  // Check that the component is visible but the input reflects disabled state
  await expect(driver.component).toBeVisible();
  await expect(driver.component).toHaveAttribute('data-drop-enabled', 'false');
});

test("component supports custom drop text", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone text="Custom drop message">Upload Area</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toBeVisible();
});

test("component supports allowPaste property", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone allowPaste="false">Upload Area</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toBeVisible();
});

test("component has hidden file input", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone>Upload Area</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.getHiddenInput()).toBeAttached();
  await expect(driver.getHiddenInput()).toHaveAttribute('type', 'file');
});

test("component initially hides drop placeholder", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone>Upload Area</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  expect(await driver.isDropPlaceholderVisible()).toBe(false);
});

// =============================================================================
// ACCESSIBILITY TESTS (REQUIRED)
// =============================================================================

test("component has correct accessibility structure", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone>Upload files here</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.getHiddenInput()).toHaveAttribute('type', 'file');
  await expect(driver.component).toBeVisible();
});

test("component supports keyboard interaction through children", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`
    <FileUploadDropZone>
      <Button testId="customButton">Browse Files</Button>
    </FileUploadDropZone>
  `);
  const driver = await createFileUploadDropZoneDriver();
  const button = driver.component.getByTestId('customButton');
  await expect(button).toBeVisible();
  await button.focus();
  await expect(button).toBeFocused();
});

test("component maintains semantic structure", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`
    <FileUploadDropZone>
      <H3>Upload Documents</H3>
      <Text>Supported formats: PDF, DOC, JPG</Text>
    </FileUploadDropZone>
  `);
  const driver = await createFileUploadDropZoneDriver();
  // Check that content is visible within the drop zone
  await expect(driver.component).toContainText("Upload Documents");
  await expect(driver.component).toContainText("Supported formats");
});

test("component supports screen reader announcements", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`
    <FileUploadDropZone>
      <Text role="status" aria-live="polite">Ready for file upload</Text>
    </FileUploadDropZone>
  `);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toContainText("Ready for file upload");
});

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

test("component applies theme variables correctly", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone>Upload Area</FileUploadDropZone>`, {
    testThemeVars: {
      "backgroundColor-FileUploadDropZone": "rgb(255, 0, 0)",
    },
  });
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toHaveCSS("background-color", "rgb(255, 0, 0)");
});

test("component applies text color theme variables", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone>Upload Area</FileUploadDropZone>`, {
    testThemeVars: {
      "textColor-FileUploadDropZone": "rgb(0, 255, 0)",
    },
  });
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toHaveCSS("color", "rgb(0, 255, 0)");
});

test("component shows drop placeholder during drag operations", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone text="Drop files here">Upload Area</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  
  // Initially hidden
  expect(await driver.isDropPlaceholderVisible()).toBe(false);
  
  // Would be visible during drag (tested functionally)
  await expect(driver.component).toBeVisible();
});

test("component maintains layout with custom styles", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`
    <FileUploadDropZone style="min-height: 200px; border: 2px dashed #ccc;">
      Upload Area
    </FileUploadDropZone>
  `);
  const driver = await createFileUploadDropZoneDriver();
  // Check that the component is visible and contains content
  await expect(driver.component).toBeVisible();
  await expect(driver.component).toContainText("Upload Area");
});

// =============================================================================
// EDGE CASE TESTS (CRITICAL)
// =============================================================================

test("component handles null and undefined props gracefully", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone>Upload Area</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toBeVisible();
  await expect(driver.getHiddenInput()).toBeAttached();
});

test("component handles empty children", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone> </FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  // Component should be attached even with minimal content
  await expect(driver.component).toBeAttached();
  await expect(driver.getHiddenInput()).toBeAttached();
});

test("component handles special characters in text prop", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone text="Drop files here 📁 & upload 🚀">Upload</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toBeVisible();
});

test("component handles boolean string props correctly", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone enabled="true" allowPaste="false">Upload</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toBeVisible();
  expect(await driver.isEnabled()).toBe(true);
});

test("component handles complex nested children", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`
    <FileUploadDropZone>
      <VStack>
        <Icon name="upload"/>
        <Heading>Upload Files</Heading>
        <Text>Drag and drop or click to browse</Text>
        <HStack>
          <Button>Browse</Button>
          <Button variant="outline">Cancel</Button>
        </HStack>
      </VStack>
    </FileUploadDropZone>
  `);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toBeVisible();
  expect(await driver.hasChildren()).toBe(true);
});

// =============================================================================
// PERFORMANCE TESTS
// =============================================================================

test("component handles multiple rapid drag events efficiently", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone>Upload Area</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  
  // Multiple rapid drag events should not cause issues
  await driver.triggerDragEnter();
  await driver.triggerDragLeave();
  await driver.triggerDragEnter();
  await driver.triggerDragLeave();
  
  await expect(driver.component).toBeVisible();
});

test("component maintains performance with large child content", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  const largeContent = Array.from({ length: 10 }, (_, i) => `<Text>Content item ${i + 1}</Text>`).join('');
  await initTestBed(`
    <FileUploadDropZone>
      ${largeContent}
    </FileUploadDropZone>
  `);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toBeVisible();
});

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

test("component works correctly in different layout contexts", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`
    <VStack>
      <FileUploadDropZone>
        <Text>Layout Test</Text>
      </FileUploadDropZone>
    </VStack>
  `);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toBeVisible();
});

test("component works in form context", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`
    <Form>
      <FileUploadDropZone>
        <FormItem label="Document Upload">
          <Button>Choose Files</Button>
        </FormItem>
      </FileUploadDropZone>
    </Form>
  `);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toBeVisible();
});

test("component upload event handlers work correctly", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  const { testStateDriver } = await initTestBed(`
    <FileUploadDropZone onUpload="files => testState = files.length">
      Upload Area
    </FileUploadDropZone>
  `);
  const driver = await createFileUploadDropZoneDriver();
  
  await driver.triggerDrop(['file1.txt', 'file2.txt']);
  await expect.poll(testStateDriver.testState).toEqual(2);
});

test("component supports programmatic file dialog opening", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`
    <VStack>
      <FileUploadDropZone id="dropzone">Upload Area</FileUploadDropZone>
      <Button onClick="dropzone.open()">Open Dialog</Button>
    </VStack>
  `);
  const driver = await createFileUploadDropZoneDriver();
  await expect(driver.component).toBeVisible();
});

test("component maintains state with dynamic content", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`
    <FileUploadDropZone text="Dynamic drop text">
      <Text>Dynamic content area</Text>
    </FileUploadDropZone>
  `);
  const driver = await createFileUploadDropZoneDriver();
  
  await expect(driver.component).toBeVisible();
  await expect(driver.component).toContainText("Dynamic content area");
});

test("component works with nested interactive elements", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`
    <FileUploadDropZone>
      <VStack>
        <Button testId="button">Upload from Computer</Button>
        <Text>Upload Help</Text>
        <TextBox testId="textbox" placeholder="File description"/>
      </VStack>
    </FileUploadDropZone>
  `);
  const driver = await createFileUploadDropZoneDriver();
  
  await expect(driver.component.getByTestId('button')).toBeVisible();
  await expect(driver.component).toContainText("Upload Help");
  await expect(driver.component.getByTestId('textbox')).toBeVisible();
});

test("component handles paste operations when enabled", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone allowPaste="true">Upload Area</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  
  // Component should be ready for paste operations
  await expect(driver.component).toBeVisible();
  await expect(driver.getHiddenInput()).toBeAttached();
});

test("component ignores paste operations when disabled", async ({ initTestBed, createFileUploadDropZoneDriver }) => {
  await initTestBed(`<FileUploadDropZone allowPaste="false">Upload Area</FileUploadDropZone>`);
  const driver = await createFileUploadDropZoneDriver();
  
  // Component should be visible but paste functionality controlled by prop
  await expect(driver.component).toBeVisible();
});

```

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

```typescript
import { expect, test } from "../../testing/fixtures";

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

test("renders with basic props", async ({ initTestBed, createDropdownMenuDriver }) => {
  await initTestBed(`<DropdownMenu label="Menu" />`);
  const driver = await createDropdownMenuDriver();

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

test("renders with menu items", async ({ initTestBed, createDropdownMenuDriver, page }) => {
  await initTestBed(`
    <DropdownMenu label="Menu">
      <MenuItem>Item 1</MenuItem>
      <MenuItem>Item 2</MenuItem>
    </DropdownMenu>
  `);
  const driver = await createDropdownMenuDriver();

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

  await expect(page.getByRole("menuitem", { name: "Item 1" })).toBeVisible();
  await expect(page.getByRole("menuitem", { name: "Item 2" })).toBeVisible();
});

test("opens and closes menu correctly", async ({ initTestBed, createDropdownMenuDriver, page }) => {
  await initTestBed(`
    <DropdownMenu label="Menu">
      <MenuItem>Item 1</MenuItem>
    </DropdownMenu>
  `);
  const driver = await createDropdownMenuDriver();

  await expect(page.getByRole("menuitem")).not.toBeVisible();

  await driver.open();
  await expect(page.getByRole("menuitem")).toBeVisible();

  await driver.close();
  await expect(page.getByRole("menuitem")).not.toBeVisible();
});

test("handles menu item clicks", async ({ initTestBed, createDropdownMenuDriver, page }) => {
  const { testStateDriver } = await initTestBed(`
    <DropdownMenu label="Menu">
      <MenuItem onClick="testState = 'item1-clicked'">Item 1</MenuItem>
      <MenuItem onClick="testState = 'item2-clicked'">Item 2</MenuItem>
    </DropdownMenu>
  `);
  const driver = await createDropdownMenuDriver();

  await driver.open();
  await driver.clickMenuItem("Item 1");
  await expect.poll(testStateDriver.testState).toEqual("item1-clicked");

  // Menu should close after click
  await expect(page.getByRole("menuitem", { name: "Item 1" })).not.toBeVisible();
  await expect(page.getByRole("menuitem", { name: "Item 2" })).not.toBeVisible();
});

test("alignment='start' aligns popup menu left", async ({
  initTestBed,
  createDropdownMenuDriver,
  page,
}) => {
  await initTestBed(`
    <HStack width="50%">
      <DropdownMenu alignment="start" label="Menu">
        <MenuItem >Item 1</MenuItem>
        <MenuItem >Item 2</MenuItem>
      </DropdownMenu>
    </HStack>
  `);
  const driver = await createDropdownMenuDriver();

  await driver.open();
  const { x: triggerX } = await driver.component.boundingBox();
  const { x: menuX } = await page.getByRole("menu").boundingBox();
  expect(menuX).toBeCloseTo(triggerX);
});

test("alignment='end' aligns popup menu right", async ({
  initTestBed,
  createDropdownMenuDriver,
  page,
}) => {
  await initTestBed(`
    <HStack width="50%" reverse="true">
      <DropdownMenu alignment="end" label="Menu">
        <MenuItem >Item 1</MenuItem>
        <MenuItem >Item 2</MenuItem>
      </DropdownMenu>
    </HStack>
  `);
  const driver = await createDropdownMenuDriver();

  await driver.open();
  const { width: triggerWidth, x: triggerX } = await driver.component.boundingBox();
  const { width: menuWidth, x: menuX } = await page.getByRole("menu").boundingBox();
  const menuEndX = menuX + menuWidth;
  const triggerEndX = triggerX + triggerWidth;
  expect(menuEndX).toBeCloseTo(triggerEndX);
});

test("supports submenu functionality", async ({ initTestBed, createDropdownMenuDriver, page }) => {
  await initTestBed(`
    <DropdownMenu label="Menu">
      <MenuItem>Regular Item</MenuItem>
      <SubMenuItem label="Submenu">
        <MenuItem>Submenu Item 1</MenuItem>
        <MenuItem>Submenu Item 2</MenuItem>
      </SubMenuItem>
    </DropdownMenu>
  `);
  const driver = await createDropdownMenuDriver();

  // Open main menu
  await driver.open();
  await expect(page.getByText("Regular Item")).toBeVisible();
  await expect(page.getByText("Submenu")).toBeVisible();

  // Open submenu using driver method
  await driver.openSubMenu("Submenu");
  await expect(page.getByRole("menuitem", { name: "Submenu Item 1" })).toBeVisible();
  await expect(page.getByRole("menuitem", { name: "Submenu Item 2" })).toBeVisible();
});

test("supports menu separators", async ({ initTestBed, createDropdownMenuDriver, page }) => {
  await initTestBed(`
    <DropdownMenu label="Menu">
      <MenuItem>Item 1</MenuItem>
      <MenuSeparator />
      <MenuItem>Item 2</MenuItem>
    </DropdownMenu>
  `);
  const driver = await createDropdownMenuDriver();

  await driver.open();
  await expect(page.getByRole("menuitem", { name: "Item 1" })).toBeVisible();
  await expect(page.getByRole("menuitem", { name: "Item 2" })).toBeVisible();

  // Check that separator is rendered using driver method
  const separators = driver.getMenuSeparators();
  await expect(separators).toHaveCount(1);
});

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

test("has correct accessibility attributes", async ({
  initTestBed,
  createDropdownMenuDriver,
  page,
}) => {
  await initTestBed(`
    <DropdownMenu label="Accessible Menu">
      <MenuItem>Item 1</MenuItem>
    </DropdownMenu>
  `);
  const driver = await createDropdownMenuDriver();

  let btn = page.getByRole("button", { name: "Accessible Menu" });
  await expect(btn).toHaveAttribute("aria-haspopup", "menu");
  await expect(btn).toHaveAttribute("aria-expanded", "false");

  await driver.open();
  await page.getByRole("button", { includeHidden: true, expanded: true }).waitFor();
  await page.getByRole("menu").waitFor();
});

test("is keyboard accessible", async ({ initTestBed, createDropdownMenuDriver, page }) => {
  const { testStateDriver } = await initTestBed(`
    <DropdownMenu label="Keyboard Menu">
      <MenuItem onClick="testState = 'keyboard-activated'">Item 1</MenuItem>
    </DropdownMenu>
  `);

  const btn = page.getByRole("button");
  await page.keyboard.press("Tab");
  await expect(btn).toBeFocused();

  // Open with Enter
  await page.keyboard.press("Enter");
  await expect(page.getByRole("menuitem", { name: "Item 1" })).toBeVisible();

  // Navigate and select with keyboard
  await page.keyboard.press("ArrowDown");
  await page.keyboard.press("Enter");
  await expect.poll(testStateDriver.testState).toEqual("keyboard-activated");
});

test("disabled DropdownMenu can't be focused", async ({ initTestBed, page }) => {
  await initTestBed(`<DropdownMenu label="Disabled Menu" enabled="false" />`);
  const btn = page.getByRole("button");

  await expect(btn).toBeDisabled();

  // Should not be focusable when disabled
  await btn.focus();
  await expect(btn).not.toBeFocused();
});

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

test("applies theme variables correctly", async ({ initTestBed, createDropdownMenuDriver }) => {
  await initTestBed(
    `<DropdownMenu label="Themed Menu">
      <MenuItem>Item 1</MenuItem>
    </DropdownMenu>`,
    {
      testThemeVars: {
        "backgroundColor-DropdownMenu": "rgb(255, 0, 0)",
        "minWidth-DropdownMenu": "200px",
      },
    },
  );
  const driver = await createDropdownMenuDriver();

  // Open menu to see styled content
  await driver.open();

  // Check theme variables are applied to menu content
  const menuContent = driver.getMenuContent();
  await expect(menuContent).toBeVisible();
  await expect(menuContent).toHaveCSS("background-color", "rgb(255, 0, 0)");
  await expect(menuContent).toHaveCSS("min-width", "200px");
});

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

test("handles null label gracefully", async ({ initTestBed, page }) => {
  await initTestBed(`<DropdownMenu label="{null}" />`);
  await expect(page.getByRole("button")).toBeVisible();
});

test("handles special characters in labels", async ({
  initTestBed,
  createDropdownMenuDriver,
  page,
}) => {
  await initTestBed(`
    <DropdownMenu label="Menu with émojis 🚀">
      <MenuItem>Item with ñ and ü</MenuItem>
      <MenuItem>Item with &amp; &lt; &gt; quotes</MenuItem>
    </DropdownMenu>
  `);
  const driver = await createDropdownMenuDriver();

  await expect(driver.component).toBeVisible();
  await expect(driver.component).toContainText("Menu with émojis 🚀");

  await driver.open();
  await expect(page.getByText("Item with ñ and ü")).toBeVisible();
  await expect(page.getByText("Item with & < > quotes")).toBeVisible();
});

test("doesn't show empty menu with no MenuItem", async ({
  initTestBed,
  createDropdownMenuDriver,
  page,
}) => {
  await initTestBed(`<DropdownMenu label="Empty Menu" />`);
  const driver = await createDropdownMenuDriver();
  await driver.open();

  await expect(page.getByRole("menu")).not.toBeVisible();
});

test("handles disabled menu items", async ({ initTestBed, createDropdownMenuDriver, page }) => {
  const { testStateDriver } = await initTestBed(`
    <DropdownMenu label="Menu">
      <MenuItem enabled="true" onClick="testState = 'enabled-clicked'">Enabled Item</MenuItem>
      <MenuItem enabled="false" onClick="testState = 'disabled-clicked'">Disabled Item</MenuItem>
    </DropdownMenu>
  `);
  const driver = await createDropdownMenuDriver();

  await driver.open();

  // Enabled item should work
  await driver.clickMenuItem("Enabled Item");
  await expect.poll(testStateDriver.testState).toEqual("enabled-clicked");

  // Reopen menu
  await driver.open();

  await page.getByText("Disabled Item").click();
  await expect.poll(testStateDriver.testState).not.toEqual("disabled-clicked");
});

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

test("supports custom trigger template", async ({ initTestBed, page }) => {
  await initTestBed(`
    <DropdownMenu>
      <property name="triggerTemplate">
        <Button variant="solid" themeColor="secondary">Custom Trigger</Button>
      </property>
      <MenuItem>Item 1</MenuItem>
      <MenuItem>Item 2</MenuItem>
    </DropdownMenu>
  `);
  const btn = page.getByRole("button", { name: "Custom Trigger" });
  await expect(btn).toBeVisible();

  await btn.click();
  await expect(page.getByRole("menuitem", { name: "Item 1" })).toBeVisible();
  await expect(page.getByRole("menuitem", { name: "Item 2" })).toBeVisible();
});

test("handles onWillOpen event correctly", async ({
  initTestBed,
  createDropdownMenuDriver,
  page,
}) => {
  const { testStateDriver } = await initTestBed(`
    <DropdownMenu label="Event Menu" onWillOpen="testState = 'willOpen-fired'">
      <MenuItem>Item 1</MenuItem>
    </DropdownMenu>
  `);
  const driver = await createDropdownMenuDriver();

  // Click to trigger onWillOpen event
  await driver.open();

  // Event should have fired
  await expect.poll(testStateDriver.testState).toEqual("willOpen-fired");

  // Menu should be open
  await expect(page.getByRole("menuitem", { name: "Item 1" })).toBeVisible();
});

test("prevents opening when onWillOpen returns false", async ({
  initTestBed,
  createDropdownMenuDriver,
  page,
}) => {
  await initTestBed(`
    <DropdownMenu label="Prevented Menu" onWillOpen="return false">
      <MenuItem>Item 1</MenuItem>
    </DropdownMenu>
  `);
  const driver = await createDropdownMenuDriver();

  // Click should not open menu due to onWillOpen returning false
  await driver.open();
  await expect(page.getByText("Item 1")).not.toBeVisible();
});

test("API methods work correctly", async ({ initTestBed, createDropdownMenuDriver, page }) => {
  await initTestBed(`
    <HStack>
      <DropdownMenu id="apiMenu" label="API Menu">
        <MenuItem>Item 1</MenuItem>
        <MenuItem><Button testId="closeBtn" onGotFocus="apiMenu.close()" label="Close Menu" /></MenuItem>
      </DropdownMenu>
      <Button testId="openBtn" onClick="apiMenu.open()">Open Menu</Button>
    </HStack>
  `);
  const menuItem = page.getByRole("menuitem", { name: "Item 1" });
  await expect(menuItem).not.toBeVisible();

  await page.getByTestId("openBtn").click();
  await expect(menuItem).toBeVisible();

  await page.getByTestId("closeBtn").focus();
  await expect(menuItem).not.toBeVisible();
});

test("works with nested menu structures", async ({
  initTestBed,
  createDropdownMenuDriver,
  page,
}) => {
  await initTestBed(`
    <DropdownMenu label="Main Menu">
      <MenuItem>Top Level Item</MenuItem>
      <SubMenuItem label="Category 1">
        <MenuItem>Category 1 Item 1</MenuItem>
        <SubMenuItem label="Subcategory">
          <MenuItem>Deep Item 1</MenuItem>
          <MenuItem>Deep Item 2</MenuItem>
        </SubMenuItem>
      </SubMenuItem>
      <MenuSeparator />
      <SubMenuItem label="Category 2">
        <MenuItem>Category 2 Item 1</MenuItem>
        <MenuItem>Category 2 Item 2</MenuItem>
      </SubMenuItem>
    </DropdownMenu>
  `);
  const driver = await createDropdownMenuDriver();

  // Open main menu
  await driver.open();
  await expect(page.getByText("Top Level Item")).toBeVisible();
  await expect(page.getByText("Category 1")).toBeVisible();

  // Navigate to submenu using driver method
  await expect(page.getByText("Category 1 Item 1")).not.toBeVisible();
  await driver.openSubMenu("Category 1");
  await expect(page.getByText("Category 1 Item 1")).toBeVisible();
  await expect(page.getByText("Subcategory")).toBeVisible();

  // Navigate to nested submenu
  await expect(page.getByText("Deep Item 1")).not.toBeVisible();
  await driver.openSubMenu("Subcategory");
  await expect(page.getByText("Deep Item 1")).toBeVisible();
  await expect(page.getByText("Deep Item 2")).toBeVisible();
});

```

--------------------------------------------------------------------------------
/docs/public/pages/forms.md:
--------------------------------------------------------------------------------

```markdown
# Forms

XMLUI enables to create forms without the hassle of managing, editing, validating, and saving the information you provide in the UI.

This example demonstrates the core elements: [Form](/components/Form) and [FormItem](/components/FormItem).

```xmlui-pg display
<App>
  <Form data="{{ name: 'Joe', age: 43 }}">
    <FlowLayout>
      <H3>Customer information</H3>
      <FormItem bindTo="name" label="Customer name" />
      <FormItem bindTo="age" label="Age" type="integer" zeroOrPositive="true" />
    </FlowLayout>
  </Form>
</App>
```

- `Form` encapsulates the management of form UI elements and data handling
- The `data` property holds the form's data
- `FormItem` manages a piece of the data
  - `bindTo` specifies the property name within the `data` to bind the corresponding field
  - `type` determines the kind of input field needed for a given piece of data (number field, text area field, radio buttons, etc.)
  - other properties support styling or validation

## Form Layouts

You can use any of XMLUI's layout mechanisms with a `Form`. Here is a single-column format using `FlowLayout`.

```xmlui-pg display
<App>
  <Form data="{
    {
      firstname: 'Jake',
      lastname: 'Hard',
      jobTitle: 'janitor',
      experience: 'broom'
     }
  }">
    <FlowLayout>
      <FormItem label="Firstname" bindTo="firstname" />
      <FormItem label="Lastname" bindTo="lastname" />
      <FormItem label="Job Title" bindTo="jobTitle" />
      <FormItem label="Experience" bindTo="experience" />
    </FlowLayout>
  </Form>
</App>
```

Set each item's width to `50%` to create a two-column layout.

 ```xmlui-pg display
<App>
  <Form
    data="{{
      firstname: 'Jake',
      lastname: 'Hard',
      jobTitle: 'janitor',
      experience: 'broom'
    }}">
    <FlowLayout>
      <FormItem label="Firstname" bindTo="firstname" width="50%" />
      <FormItem label="Lastname" bindTo="lastname" width="50%" />
      <FormItem label="Job Title" bindTo="jobTitle" width="50%" />
      <FormItem label="Experience" bindTo="experience" width="50%" />
    </FlowLayout>
  </Form>
</App>
```

Use star sizing to allocate widths flexibly. Here `Firstname` and `Lastname` equally share the space remaining after the 100-px-wide `Title`.

```xmlui-pg display
<App>
  <Form
    data="{{
      title: 'Mr.',
      firstname: 'Jake',
      lastname: 'Hard',
      jobTitle: 'janitor',
      experience: 'broom'
    }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FlowLayout>
      <HStack>
        <FormItem label="Title" bindTo="title" width="100px" />
        <FormItem label="Firstname" bindTo="firstname" width="*" />
        <FormItem label="Lastname" bindTo="lastname" width="*" />
      </HStack>
      <FormItem label="Job Title" bindTo="jobTitle" width="50%" />
      <FormItem label="Experience" bindTo="experience" width="50%" />
    </FlowLayout>
  </Form>
</App>
```

## FormItem

`FormItem` is an intermediary layer between `Form` and an input component; it manages the data represented by that component. The [`type`](/components/FormItem#type-default-text) property of a `FormItem` specifies what input component to render.

### Checkbox

```xmlui-pg display
<App>
  <Form data="{{ option1: true, option2: false, option3: true }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem type="checkbox" bindTo="option1" label="Option #1" labelPosition="end" />
    <FormItem type="checkbox" bindTo="option2" label="Option #2" labelPosition="end" />
    <FormItem type="checkbox" bindTo="option3" label="Option #3" labelPosition="end" />
  </Form>
</App>
```

[Checkbox component doc](/components/Checkbox)

### DatePicker

```xmlui-pg display
<App>
  <Form
    data="{{ birthDate: '2021-04-08' }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem type="datePicker" bindTo="birthDate" label="Birthdate" />
  </Form>
</App>
```

[DatePicker component doc](/components/DatePicker)

### File

Use `file` to select one or multiple files.

```xmlui-pg display
<App>
  <Form
    data="{{ articles: null }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem type="file" bindTo="articles" label="Articles file" />
  </Form>
</App>
```

[File component doc](/components/FileInput)

### Integer

```xmlui-pg display
<App>
  <Form
    data="{{ age: 30 }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem type="integer" bindTo="age" label="Age" />
  </Form>
</App>
```

[NumberBox component doc](/components/NumberBox)

### Number

```xmlui-pg display
<App>
  <Form
    data="{{ distance: 192.5 }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem type="number" bindTo="distance" label="Distance in miles" />
  </Form>
</App>
```

[NumberBox component doc](/components/NumberBox)

### RadioGroup

```xmlui-pg display
<App>
  <Form
    data="{{ title: 'Mr.' }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem type="radioGroup" bindTo="title" label="Title">
      <Option label="Mr." value="Mr." />
      <Option label="Mrs." value="Mrs." />
      <Option label="Ms." value="Ms." />
      <Option label="Dr." value="Dr." />
    </FormItem>
  </Form>
</App>
```

[RadioGroup component doc](/components/RadioGroup)


### Select

```xmlui-pg display
<App>
  <Form
    data="{{ size: 'xs' }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem type="select" bindTo="size" label="Box size">
      <Option label="Extra small" value="xs" />
      <Option label="Small" value="sm" />
      <Option label="Medium" value="md" />
      <Option label="Large" value="lg" />
    </FormItem>
  </Form>
</App>
```

[Select component doc](/components/Select)

### Switch

```xmlui-pg display
<App>
  <Form
    data="{{ showBorder: true, showText: false, hideShadow: true }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem type="switch" bindTo="showBorder" label="Show border" labelPosition="right" />
    <FormItem type="switch" bindTo="showText" label="Show text" labelPosition="right" />
    <FormItem type="switch" bindTo="hideShadow" label="Hide shadow" labelPosition="right" />
  </Form>
</App>
```

[Switch component doc](/components/Switch)


### TextBox

```xmlui-pg display
<App>
  <Form
    data="{{ name: 'Joe' }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem type="text" bindTo="name" label="Name" />
  </Form>
</App>
```

[TextBox component doc](/components/TextBox)

### TextArea

```xmlui-pg display
<App>
  <Form
    data="{{ description: 'This is a description' }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem type="textarea" bindTo="description" label="Description" />
  </Form>
</App>
```

[TextArea component doc](/components/TextArea)

### Custom

You can create a custom input component that uses the XMLUI forms infrastructure.

```xmlui-pg display
<App>
  <Form
    data="{{ userAvailable: false }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem bindTo="userAvailable">
      <HStack>
        <Button
          label="Toggle"
          backgroundColor="{$value === false ? 'red' : 'green'}"
          onClick="$setValue(!$value)"
        />
      </HStack>
    </FormItem>
  </Form>
</App>
```

`$value` represents the current value of the component. `$setValue` changes the value.

## Provide data

You can define a `Form`s data structure and initial values directly.

```xmlui copy
<Form data="{{ name: 'Joe', age: 43 }}" />
```

Or via an API endpoint.

```xmlui
<Form data="/path/to/resource" />
```

Use the `bindTo` property to access fields in the structure.

```xmlui
<Form data="{{ name: 'Joe' }}">
  <FormItem bindTo="name" />
</Form>
```

## Refer to data

The `$data` variable holds all the form's data. You can use values in `$data` to control `FormItem` properties. Here the `Switch`s value sets the `enabled` property of a `FormItem`.

```xmlui-pg display
<App>
  <Form data="{{ isEnabled: true, name: 'Joe' }}">
    <FormItem label="Enable name" bindTo="isEnabled" type="switch" />
    <FormItem enabled="{$data.isEnabled}" label="Name" bindTo="name" />
  </Form>
</App>
```

Other components in the form can reference the form's data too. Here the `Text` updates reactively when input values change.

```xmlui-pg display
<App>
  <Form data="{{ firstname: 'John', lastname: 'Doe' }}">
    <FormItem label="Firstname" bindTo="firstname" />
    <FormItem label="Lastname" bindTo="lastname" />
    <Text>Full name: {$data.firstname} {$data.lastname}</Text>
  </Form>
</App>
```

You can drill into `$data` to reference nested fields.

```xmlui-pg display {9}
<App>
  <Form
    data="{{
      name: 'John smith',
      address: { street: '96th Ave N', city: 'Seattle', zip: '98005' }
    }}"
    onSubmit="(toSave) => toast.success(JSON.stringify(toSave))">
    <FormItem bindTo="name" label="Name" />
    <FormItem bindTo="address.street" label="Street" />
  </Form>
</App>
```

## Validate data

The `Form` handles client-side validation, reporting issues interactively. Server-side validation happens when the form data is sent to the server. The `Form` handles the server's response and displays it in a summary or below input fields.

These are the `FormItem` validation properties.

### `minLength`

```xmlui-pg display
<App>
  <Form data="{{ name: 'Billy Bob' }}">
    <FormItem bindTo="name" minLength="10" label="minLength" />
  </Form>
</App>
```

Try submitting with fewer than 10 characters.

### `maxLength`

```xmlui-pg display
<App>
  <Form data="{{ name: 'Billy Bob' }}">
    <FormItem bindTo="name" maxLength="11" label="maxLength" />
  </Form>
</App>
```

Try entering more than 11 characters.

### `minValue`

```xmlui-pg display
<App>
  <Form data="{{ age: 30 }}">
    <FormItem bindTo="age" type="number" minValue="32" label="minValue" />
  </Form>
</App>
```

Try entering a number smaller than 32.


### `maxValue`

```xmlui-pg display
<App>
  <Form data="{{ age: 30 }}" >
    <FormItem bindTo="age" type="number" maxValue="29" label="maxValue" />
  </Form>
</App>
```

Try entering a number larger than 32.

### `pattern`

Evaluate predefined regex patterns: "email", "url", or "phone".

```xmlui-pg
<App>
  <Form data="{{
      mobile: '+13456123456',
      website: 'http://www.blogsite.com',
      email: '[email protected]'
    }}">
    <FormItem bindTo="mobile" pattern="phone" label="mobilePattern" />
    <FormItem bindTo="website" pattern="url" label="websitePattern" />
    <FormItem bindTo="email" pattern="email" label="emailPattern" />
  </Form>
</App>
```


See the [pattern property](/components/FormItem#pattern) of `FormItem`.

### `regex`

Evaluate a custom regex pattern.

```xmlui-pg display
<App>
  <Form data="{{ password: 'hello' }}">
    <!-- Only all uppercase letters are accepted -->
    <FormItem bindTo="password" regex="/^[A-Z]+$/" label="regex" />
  </Form>
</App>
```

### Compound validation

You can use multiple validations.

```xmlui-pg display
<App>
  <Form data="{{ site: 'http://www.example.com' }}">
    <FormItem bindTo="site" minLength="10" maxLength="30"
      pattern="url" label="Multiple Validations" />
  </Form>
</App>
```

### Validation-specific severity

By default, all validations have a severity level of **"error"**. You can set whether a validation should have a level of **"warning"** or **"error"**.

```xmlui-pg display
<App>
  <Form data="{{ mobile: '+13456123456', website: 'http://www.blogsite.com' }}" >
    <FormItem
      bindTo="mobile"
      pattern="phone"
      patternInvalidSeverity="warning"
      label="mobilePattern" />
    <FormItem
      bindTo="website"
      pattern="url"
      patternInvalidSeverity="error"
      label="websitePattern" />
  </Form>
</App>
```

### Validation-specific messages

Predefined validations have built-in messages that you can change.

```xmlui-pg display
<App>
  <Form data="{{ age: 20 }}" >
    <FormItem
      bindTo="age"
      type="number"
      minValue="21"
      rangeInvalidMessage="The given age is too low!"
      label="Invalid Message" />
  </Form>
</App>
```


## Server-side validation

The `Form` component can receive and display a server-side validation response. Field related issues are shown just like client-side validation errors, removed when a field is edited. Non-field related issues are displayed in a validation summary view.

<br/>
<Image alt="Server-side Validation" src="/resources/images/create-apps/using-forms.png" />



## Submit data

By default the `Form` component provides a submit button to save the modified data.

```xmlui-pg display
<App>
  <Form onSubmit="toast('Saved!')" />
</App>
```

The `onSubmit` accepts either a block of code or function. When you use a function it receives data in a parameter; in this example it's called `toSave` but you can use any name. The function can be defined inline, in a code-behind file, or in `index.html` attached to the global `window` variable. See the [Code](/code) chapter for details.

```xmlui-pg display
<App>
  <Form
    data="{{ name: 'Joe', age: 43 }}"
    onSubmit="(d) => toast(JSON.stringify(d))"
  >
    <FormItem label="name" bindTo="name" />
    <FormItem label="age" bindTo="age" />
  </Form>
</App>
```

To submit via an `APICall`, use the `event` helper tag to bridge between the form and the API. The `Form`s `data` attribute maps to the `APICall`'s `$param` [context variable](/context-variables). A `Toast` popup reports success or error.

```xmlui
<App>
  <Form data="{{ name: 'Joe', age: 43 }}">
    <event name="submit">
      <APICall
        url="/api/contacts"
        method="POST"
        body="{$param}" />
    </event>
    <FormItem bindTo="name" label="name" />
    <FormItem bindTo="age" label="age" />
  </Form>
</App>
```

## Form in ModalDialog

[ModalDialog](/components/ModalDialog) supports `Form` as a first-class citizen component. When a `Form` nests directly in a `ModalDialog`, the dialog's button row is replaced with the form's own button row. When form submission is successful, the dialog closes.


```

--------------------------------------------------------------------------------
/xmlui/conventions/xmlui-in-a-nutshell.md:
--------------------------------------------------------------------------------

```markdown
# XMLUI in a Nutshell

A comprehensive guide to understanding the XMLUI framework, its architecture, core concepts, and key features.

## Overview

**XMLUI** is a declarative UI framework for building web applications using XML markup with minimal JavaScript. It emphasizes simplicity, allowing developers to create modern web applications with little to no knowledge of React or CSS while leveraging the power of reactive data binding.

### Core Philosophy
- **Declarative approach**: Build UIs by describing what you want, not how to achieve it
- **Minimal scripting**: Most functionality achieved through markup and expressions
- **Reactive by default**: Automatic data binding and UI updates
- **Theme-driven**: Comprehensive theming system for consistent, professional appearance
- **Component-based**: Modular architecture with reusable custom components

## Project Structure

### Typical XMLUI Application Structure
```
app-root/
├── index.html              # Entry point HTML file
├── Main.xmlui              # Main application component
├── config.json             # Application configuration
├── components/             # Custom components directory
│   ├── ClientDetails.xmlui
│   ├── CustomForm.xmlui
│   └── ...
├── resources/             # Static assets
│   ├── favicon.ico
│   ├── images/
│   └── ...
├── themes/               # Custom themes
│   └── custom.json
├── xmlui/               # XMLUI framework files
│   ├── 0.9.23.js        # Core framework (versioned)
│   └── charts-0.1.21.js # Extensions
└── start.sh/bat         # Development server scripts
```

### Key Files
- **`index.html`**: Contains the HTML scaffold and loads the XMLUI engine
- **`Main.xmlui`**: The application's root component defining navigation and pages
- **`config.json`**: Application configuration including routing settings and global variables
- **`components/`**: Directory containing custom reusable components
- **`themes/`**: Custom theme definitions for styling

## Core Concepts

### 1. Components and Markup

XMLUI uses XML markup where tags represent components and attributes set properties:

```xml
<Text value="Hello World" />
<Text value="Dynamic: {6 * 7}" />
<Button label="Click me" onClick="handleClick()" />
```

#### Built-in Component Categories
- **Data**: `AppState`, `DataSource`, `APICall`
- **Display**: `Avatar`, `Card`, `Heading`, `Image`, `Icon`, `Markdown`, `Text`, `Table`
- **Input**: `Checkbox`, `DatePicker`, `Form`, `FormItem`, `NumberBox`, `Select`, `TextBox`
- **Layout**: `FlowLayout`, `HStack`, `VStack`, `Stack`
- **Navigation**: `DropdownMenu`, `MenuItem`, `NavLink`, `NavPanel`, `Tabs`

### 2. Reactive Data Binding

XMLUI implements automatic reactive data binding similar to spreadsheets or React:

```xml
<Select id="lines" initialValue="bakerloo">
  <Items data="https://api.tfl.gov.uk/line/mode/tube/status">
    <Option value="{$item.id}" label="{$item.name}" />
  </Items>
</Select>

<DataSource
  id="tubeStations"
  when="{lines.value}"
  url="https://api.tfl.gov.uk/Line/{lines.value}/StopPoints"
/>

<Table data="{tubeStations}">
  <Column bindTo="name" />
  <Column bindTo="zone" />
</Table>
```

When `lines.value` changes, the DataSource automatically refetches, and the Table updates.

### 3. Context Variables

XMLUI provides several context variables for different scopes:

| Variable | Scope | Description |
|----------|-------|-------------|
| `myComponentId` | General | Reference to component instance |
| `var.myVar` | General | Scoped variables |
| `$item` | Iterators | Current item in loops |
| `$itemIndex` | Iterators | Current index in loops |
| `$param` | Event handlers | Event payload data |
| `$data` | Forms | Complete form data object |
| `$value` | FormItem | Current field value |
| `$pathname` | Page | Current route path |
| `$routeParams` | Page | Route parameter values |
| `$queryParams` | Page | Query string parameters |

### 4. Variables and Expressions

Variables can be declared using `var.` prefix or `<variable>` tags:

```xml
<App var.count="{0}">
  <Button onClick="count++" label="Increment" />
  <Text>Count: {count}</Text>
</App>

<!-- Alternative syntax -->
<App>
  <variable name="stations" value="{['Central', 'Bakerloo']}" />
  <Items data="{stations}">
    <Text>{$item}</Text>
  </Items>
</App>
```

Expressions use JavaScript syntax within curly braces:
- Simple expressions: `{6 * 7}`
- Object literals: `{{name: 'John', age: 30}}`
- Function calls: `{myFunction(param)}`
- Arrow functions: `{() => console.log('clicked')}`

## Data Management

### DataSource Component
Central to XMLUI's data handling, supports:
- REST API calls with automatic reactive updates
- Data transformation via `transformResult`
- Conditional loading with `when` attribute
- Result selection with `resultSelector`

```xml
<DataSource
  id="users"
  url="/api/users"
  transformResult="{window.processUsers}"
  when="{shouldLoadUsers}"
  resultSelector="data"
/>
```

### API Integration
XMLUI provides comprehensive API integration:
- `APICall` component for imperative calls
- `Actions.callApi()` for programmatic API calls
- Built-in loading states and error handling
- Optimistic updates and caching

### Form Handling
Sophisticated form management without manual state handling:

```xml
<Form data="{{name: '', email: ''}}" onSubmit="handleSubmit">
  <FormItem bindTo="name" label="Name" />
  <FormItem bindTo="email" label="Email" type="email" />
</Form>
```

#### FormItem Types
- `text` (default), `email`, `password`, `number`, `integer`
- `checkbox`, `radio`, `select`, `multiselect`
- `textarea`, `date`, `time`, `datetime`
- `file`, `color`, `range`

## Layout System

### Layout Components
- **`HStack`**: Horizontal layout (flex-row)
- **`VStack`**: Vertical layout (flex-column) 
- **`FlowLayout`**: Responsive wrapping layout
- **`Stack`**: Basic container

### Sizing System
- **Pixel values**: `width="200px"`
- **Percentages**: `width="50%"`
- **Star sizing**: `width="*"` (flexible proportional)
- **Combined**: `width="2*"` (takes 2 parts of available space)

### Layout Properties
- **Alignment**: `horizontalAlignment`, `verticalAlignment`
- **Spacing**: `gap`, `padding`, `margin`
- **Direction**: `direction="rtl"` for right-to-left layouts
- **Overflow**: Automatic scrollbars when content exceeds viewport

## Routing and Navigation

### Route Configuration
XMLUI supports both hash-based (default) and standard routing:

```xml
<App>
  <NavPanel>
    <NavLink label="Home" to="/home" />
    <NavLink label="Users" to="/users" />
  </NavPanel>
  
  <Pages>
    <Page url="/home">
      <Home />
    </Page>
    <Page url="/users/:id?">
      <UserDetail />
    </Page>
  </Pages>
</App>
```

### Navigation Context
- `$pathname`: Current route path
- `$routeParams`: URL parameters (e.g., `:id`)
- `$queryParams`: Query string parameters
- `$linkInfo`: Navigation context with previous/next

### Route Configuration Options
```json
{
  "appGlobals": {
    "useHashBasedRouting": false
  }
}
```

## Custom Components

### Component Definition
Custom components live in the `components/` directory:

```xml
<!-- components/TubeStops.xmlui -->
<Component name="TubeStops">
  <DataSource
    id="stops"
    when="{$props.line}"
    url="https://api.tfl.gov.uk/Line/{$props.line}/StopPoints"
  />
  
  <Text variant="strong">{$props.line}</Text>
  <Table data="{stops}">
    <Column bindTo="name" />
    <Column bindTo="zone" />
  </Table>
</Component>
```

### Component Usage
```xml
<TubeStops line="bakerloo" />
<TubeStops line="central" />
```

### Component Benefits
- **Property handling**: Receive data via `$props`
- **Data transformation**: Clean up complex API responses
- **Encapsulation**: Self-contained functionality
- **Reusability**: Use across multiple pages/contexts

## Theming and Styling

### Theme System
XMLUI uses comprehensive JSON-based theming:

```json
{
  "name": "Custom Theme",
  "colors": {
    "primary": "#007acc",
    "secondary": "#6c757d",
    "success": "#28a745"
  },
  "typography": {
    "fontFamily": "Segoe UI, sans-serif",
    "fontSize": "14px"
  },
  "spacing": {
    "small": "8px",
    "medium": "16px",
    "large": "24px"
  }
}
```

### Style Properties
Components support styling through attributes:
- `backgroundColor`, `color`, `border`
- `padding`, `margin`, `gap`
- `fontSize`, `fontWeight`, `textAlign`
- `width`, `height`, `minWidth`, `maxHeight`

### Variants
Many components support semantic variants:
```xml
<Text variant="strong">Bold text</Text>
<Button variant="primary">Primary action</Button>
<Card variant="outlined">Bordered card</Card>
```

## Advanced Features

### Modal Dialogs
Support both declarative and imperative usage:

```xml
<!-- Declarative -->
<ModalDialog when="{showDialog}" onClose="showDialog = false">
  Content here
</ModalDialog>

<!-- Imperative -->
<ModalDialog id="dialog">
  Content here
</ModalDialog>
<Button onClick="dialog.open()" label="Open" />
```

### Global Functions and Actions
XMLUI provides global utilities:

```javascript
// API calls
Actions.callApi({method: 'post', url: '/api/users', body: userData});

// File operations  
Actions.download({url: '/api/report', fileName: 'report.pdf'});
Actions.upload({file: selectedFile, url: '/api/upload'});

// Navigation
navigate('/users/123');
goBack();

// Notifications
toast.success('Operation completed');
toast.error('Something went wrong');
```

### Validation
Built-in form validation with customizable messages:

```xml
<FormItem
  bindTo="email"
  type="email"
  required="true"
  requiredMessage="Email is required"
  invalidMessage="Please enter a valid email"
/>
```

### Conditional Rendering
Multiple approaches for conditional display:

```xml
<!-- Fragment with when attribute -->
<Fragment when="{user.isAdmin}">
  <Button label="Admin Panel" />
</Fragment>

<!-- Component-level when -->
<Text when="{items.length > 0}" value="Found {items.length} items" />

<!-- Ternary in expressions -->
<Text value="{user.isOnline ? 'Online' : 'Offline'}" />
```

## Scripting and JavaScript Integration

### Expression Types
- **Inline expressions**: `{count + 1}`
- **Event handlers**: `onClick="handleClick()"`
- **Object literals**: `data="{{name: 'John'}}"`
- **Function definitions**: Arrow functions in attributes

### Script Blocks
For complex logic, use script blocks in components:

```xml
<Component name="MyComponent">
  <script>
    function processData(items) {
      return items.filter(item => item.active)
        .map(item => ({...item, displayName: item.firstName + ' ' + item.lastName}));
    }
  </script>
  
  <!-- Use the function in markup -->
  <DataSource url="/api/users" transformResult="{processData}" />
</Component>
```

### Global Integration
Access global browser APIs and XMLUI utilities:
- `window` object for browser APIs
- `console` for debugging
- `fetch` for custom HTTP calls
- XMLUI globals like `Actions`, `toast`, `navigate`

## Development and Debugging

### Development Server
XMLUI includes a test server for development:
```bash
# Start development server
./start.sh    # Mac/Linux
start.bat     # Windows
```

### Debugging Techniques
```xml
<!-- Display data structures -->
<Text preserveLinebreaks="true">
  {JSON.stringify(userData, null, 2)}
</Text>

<!-- Console logging in handlers -->
<Button onClick="console.log('Debug:', userData)" />

<!-- Script-based debugging -->
<script>
  function debug(msg, data) {
    console.log(msg, data);
  }
</script>
```

### Error Handling
- Built-in validation display in forms
- API error handling via `onError` callbacks
- Loading states automatically managed
- Network failure graceful degradation

## Deployment

### Static Deployment
XMLUI applications deploy as static files:
1. Copy all files to web server
2. Configure server to serve `index.html` for all routes (SPA)
3. Set appropriate cache headers for static assets

### Server Configuration Example (nginx)
```nginx
location / {
  try_files $uri $uri/ /index.html;
}
```

### Production Considerations
- Use versioned XMLUI files (e.g., `0.9.23.js`)
- Configure CDN for static assets
- Enable compression for `.js` and `.json` files
- Set appropriate cache headers

## Extension Packages

XMLUI supports extension packages for additional functionality:
- **xmlui-charts**: Charting components (LineChart, BarChart, PieChart)
- **xmlui-pdf**: PDF generation and display
- **xmlui-spreadsheet**: Spreadsheet components
- **xmlui-animations**: Animation utilities
- **xmlui-search**: Advanced search components

### Using Extensions
```html
<script src="xmlui/0.9.23.js"></script>
<script src="xmlui/charts-0.1.21.js"></script>
```

```xml
<LineChart data="{salesData}" xField="month" yField="revenue" />
```

## Best Practices

### Component Design
1. **Single responsibility**: Each component should have one clear purpose
2. **Property-driven**: Accept configuration via props rather than hardcoding
3. **Data transformation**: Handle complex API responses in components
4. **Reusable**: Design for use across different contexts

### Data Management
1. **Centralize data sources**: Use DataSource components for shared data
2. **Transform at source**: Clean up data in `transformResult` functions
3. **Leverage reactivity**: Let XMLUI handle data flow automatically
4. **Cache appropriately**: Use DataSource caching for expensive operations

### Performance
1. **Conditional loading**: Use `when` attributes to avoid unnecessary requests
2. **Efficient expressions**: Keep expressions simple and fast
3. **Minimize re-renders**: Structure data to minimize cascading updates
4. **Optimize images**: Use appropriate formats and sizes in resources

### Code Organization
1. **Consistent naming**: Use clear, descriptive names for components and variables
2. **Logical structure**: Organize components by feature or domain
3. **Documentation**: Comment complex expressions and transformations
4. **Version management**: Use versioned XMLUI files for stability

This comprehensive guide covers the essential aspects of XMLUI framework architecture, core concepts, and practical usage patterns that developers need to understand when working with XMLUI applications.
```

--------------------------------------------------------------------------------
/xmlui/src/components/Queue/QueueNative.tsx:
--------------------------------------------------------------------------------

```typescript
import type React from "react";
import { useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef } from "react";
import toast from "react-hot-toast";
import produce from "immer";
import { isEqual } from "lodash-es";

import type { ComponentDef } from "../../abstractions/ComponentDefs";
import type {
  LookupEventHandlerFn,
  RegisterComponentApiFn,
  RenderChildFn,
  ValueExtractor,
} from "../../abstractions/RendererDefs";
import type { AsyncFunction } from "../../abstractions/FunctionDefs";
import { usePrevious } from "../../components-core/utils/hooks";
import { generatedId, useEvent } from "../../components-core/utils/misc";
import { useAppContext } from "../../components-core/AppContext";
import { MemoizedItem } from "../container-helpers";
import type { QueueMd } from "./Queue";
import type { QueueAction } from "../Queue/queueActions";
import {
  actionItemCompleted,
  actionItemError,
  actionItemProgress,
  actionItemStarted,
  actionQueueInitialized,
  clearCompletedActionItems,
  QueueActionKind,
  removeActionItem,
} from "../Queue/queueActions";

// =====================================================================================================================
// React Queue component implementation

export const defaultProps = {
  clearAfterFinish: false,
};

type Props = {
  registerComponentApi: RegisterComponentApiFn;
  willProcessItem?: AsyncFunction;
  processItem?: AsyncFunction;
  didProcessItem?: AsyncFunction;
  processItemError?: AsyncFunction;
  onComplete?: AsyncFunction;
  //progressFeedback?: React.ReactNode;
  renderProgressFeedback?: (completedItems: any, queuedItems: any) => React.ReactNode;
  renderResultFeedback?: (completedItems: any, queuedItems: any) => React.ReactNode;
  clearAfterFinish?: boolean;
  // Optional external state management
  queueState?: QueueState;
  dispatch?: React.Dispatch<QueueAction>;
};

const queueReducer = produce((state: QueueState, action: QueueAction) => {
  switch (action.type) {
    case QueueActionKind.ACTION_QUEUE_INITIALIZED: {
      const queueState: Record<string, QueueItem> = {};

      const itemsById: Record<string, any> = {};
      action.payload.queue.forEach((item: any, index: number) => {
        itemsById[action.payload.actionItemIds[index]] = item;
      });

      const queue = Object.keys(itemsById);
      Object.entries(itemsById).forEach(([actionItemId, item]) => {
        queueState[actionItemId] = {
          batchId: action.payload.batchId,
          actionItemId,
          status: "pending",
          item,
        };
      });
      return {
        queue: [...(state.queue || []), ...queue],
        queueState: { ...state.queueState, ...queueState },
      };
    }
    case QueueActionKind.ACTION_ITEM_STARTED: {
      if (state.queueState[action.payload.actionItemId]) {
        state.queueState[action.payload.actionItemId].status = "started";
      }
      break;
    }
    case QueueActionKind.ACTION_ITEM_PROGRESS: {
      if (state.queueState[action.payload.actionItemId]) {
        state.queueState[action.payload.actionItemId].status = "in-progress";
        state.queueState[action.payload.actionItemId].progress = action.payload.progressEvent;
      }
      break;
    }
    case QueueActionKind.ACTION_ITEM_COMPLETED: {
      state.queue = state.queue.filter((aiId: string) => aiId !== action.payload.actionItemId);
      if (state.queueState[action.payload.actionItemId]) {
        state.queueState[action.payload.actionItemId].status = "completed";
        state.queueState[action.payload.actionItemId].result = action.payload.result;
      }
      break;
    }
    case QueueActionKind.ACTION_ITEM_REMOVED: {
      state.queue = state.queue.filter((aiId: string) => aiId !== action.payload.actionItemId);
      delete state.queueState[action.payload.actionItemId];
      break;
    }
    case QueueActionKind.ACTION_ITEM_ERROR: {
      state.queue = state.queue.filter((aiId: string) => aiId !== action.payload.actionItemId);
      if (state.queueState[action.payload.actionItemId]) {
        state.queueState[action.payload.actionItemId].status = "error";
        state.queueState[action.payload.actionItemId].error = action.payload.error;
      }
      break;
    }
    case QueueActionKind.CLEAR_COMPLETED_ACTION_ITEMS: {
      if (state.queueState) {
        Object.entries(state.queueState).forEach(([key, value]) => {
          if ((value as any).status === "completed" || (value as any).status === "error") {
            delete state.queueState[key];
          }
        });
      }
      break;
    }
    default:
      throw new Error();
  }
  // console.log("queue action arrived", action);
  // console.log("queue state", cloneDeep(state));
});

const INITIAL_STATE: QueueState = {
  queue: [],
  queueState: {},
};

export function Queue({
  registerComponentApi,
  willProcessItem,
  processItem,
  didProcessItem,
  processItemError,
  onComplete,
  //progressFeedback,
  renderProgressFeedback,
  renderResultFeedback,
  clearAfterFinish = defaultProps.clearAfterFinish,
  queueState: externalQueueState,
  dispatch: externalDispatch,
}: Props) {
  const runningActionItemRef = useRef<Set<string>>(new Set());
  const [internalQueueState, internalDispatch] = useReducer(queueReducer, INITIAL_STATE);
  
  // Use external state if provided, otherwise use internal state
  const queueState = externalQueueState ?? internalQueueState;
  const dispatch = externalDispatch ?? internalDispatch;

  let appContext = useAppContext();

  // --- This Queue API adds a single item to the queue
  const enqueueItem = useEvent((item: any) => {
    const itemId = generatedId();
    dispatch(actionQueueInitialized([item], generatedId(), [itemId]));
    return itemId;
  });

  // --- This Queue API adds a list of items to the queue
  const enqueueItems = useEvent((items: any[]) => {
    const itemIds = items.map(() => generatedId());
    dispatch(actionQueueInitialized(items, generatedId(), itemIds));
    return itemIds;
  });

  const clearCompleted = useCallback(() => {
    dispatch(clearCompletedActionItems());
  }, []);

  const remove = useCallback((actionItemId: string) => {
    if (actionItemId) {
      dispatch(removeActionItem(actionItemId));
    }
  }, []);

  const getQueueLength = useCallback(() => {
    return queueState.queue.length;
  }, [queueState.queue.length]);

  const getQueuedItems = useCallback(() => {
    // console.log("GET QUEUED ITEMS", Object.values(queueState.queueState));
    return Object.values(queueState.queueState);
  }, [queueState.queueState]);

  useEffect(() => {
    registerComponentApi({
      enqueueItem,
      enqueueItems,
      clearCompleted,
      remove,
      getQueueLength,
      getQueuedItems,
    });
  }, [
    registerComponentApi,
    enqueueItem,
    enqueueItems,
    clearCompleted,
    remove,
    getQueueLength,
    getQueuedItems,
  ]);

  const doSingle = useCallback(
    async (actionItemId: string) => {
      const queueItem = queueState.queueState[actionItemId];
      if (queueItem?.status !== "pending") {
        return;
      }
      if (runningActionItemRef.current.has(actionItemId)) {
        return;
      }
      runningActionItemRef.current.add(actionItemId);
      const item = queueItem.item;
      let processItemContext = {};
      try {
        const willProcessResult = await willProcessItem?.({
          item,
          actionItemId,
          processItemContext,
        });
        processItemContext = { ...processItemContext, willProcessResult: willProcessResult };

        if (willProcessResult === false) {
          dispatch(removeActionItem(actionItemId));
          return;
        }
        dispatch(actionItemStarted(actionItemId));

        const result = await processItem?.({
          item: item,
          actionItemId,
          processItemContext,
          onProgress: (progressEvent: any) => {
            dispatch(actionItemProgress(actionItemId, progressEvent));
          },
        });

        processItemContext = { ...processItemContext, processResult: result };

        await didProcessItem?.({
          item,
          actionItemId,
          processItemContext,
        });

        dispatch(actionItemCompleted(actionItemId, result));
      } catch (error) {
        let result = await processItemError?.(error, {
          item,
          actionItemId,
          processItemContext,
        });
        dispatch(actionItemError(actionItemId, error));
        if (result !== false) {
          appContext.signError(error as Error);
        }
      } finally {
        runningActionItemRef.current.delete(actionItemId);
      }
    },
    [
      appContext,
      didProcessItem,
      dispatch,
      processItem,
      processItemError,
      queueState.queueState,
      willProcessItem,
    ],
  );

  const toastId = useRef<string | undefined>();
  const queue = queueState.queue;
  const prevQueue = usePrevious(queue);

  const doComplete = useCallback(() => {
    onComplete?.();
    const queuedItems = getQueuedItems();
    const completedItems = getQueuedItems().filter((item) => item.status === "completed");
    const resultFeedback = renderResultFeedback?.(completedItems, queuedItems);
    if (resultFeedback && completedItems.length) {
      let currentToast = toastId.current;
      toast.success(<>{resultFeedback}</>, {
        id: currentToast,
      });
    } else {
      if (toastId.current) {
        let currentToast = toastId.current;
        toast.dismiss(currentToast);
      }
    }
    // toastId.current = undefined;
    if (clearAfterFinish) {
      clearCompleted();
    }
  }, [clearAfterFinish, clearCompleted, getQueuedItems, onComplete, renderResultFeedback]);

  //with useEffect, it's showing the previous state for some reason, review!
  useLayoutEffect(() => {
    if (!queue.length) {
      return;
    }
    if (renderProgressFeedback) {
      const queuedItems = getQueuedItems();
      const completedItems = getQueuedItems().filter((item) => item.status === "completed");
      const progressFeedback = renderProgressFeedback?.(completedItems, queuedItems);
      if (progressFeedback && toastId.current) {
        toast.loading(<>{progressFeedback}</>, {
          id: toastId.current,
        });
      } else {
        toastId.current = toast.loading(<>{progressFeedback}</>);
      }
    }
  }, [renderProgressFeedback, queue?.length]);

  useEffect(() => {
    if (!queue) {
      return;
    }
    if (prevQueue === queue) {
      return;
    }
    if (isEqual(prevQueue, queue)) {
      return;
    }
    if (prevQueue?.length && !queue.length) {
      doComplete();
      return;
    }
    let queueItem = queue[0];
    void (async () => {
      await doSingle(queueItem);
    })();
  }, [doComplete, doSingle, prevQueue, queue]);

  return null;
}

type QueueItemState = "pending" | "started" | "in-progress" | "completed" | "error";

export type QueueItem = {
  actionItemId: string;
  batchId?: string;
  status: QueueItemState;
  item: any;
  progress?: any;
  result?: any;
  error?: any;
};

type QueueState = {
  queue: string[];
  queueState: Record<string, QueueItem>;
};

// =====================================================================================================================
// QueueWithContextVar component - wrapper that provides context variables to event handlers

type QueueComponentDef = ComponentDef<typeof QueueMd>;

export function QueueWithContextVar({
  node,
  renderChild,
  extractValue,
  lookupEventHandler,
  registerComponentApi,
}: {
  node: QueueComponentDef;
  renderChild: RenderChildFn;
  extractValue: ValueExtractor;
  lookupEventHandler: LookupEventHandlerFn<typeof QueueMd>;
  registerComponentApi: RegisterComponentApiFn;
}) {
  const [queueState, dispatch] = useReducer(queueReducer, INITIAL_STATE);

  // Compute context variables from queue state
  const completedItems = useMemo(() => {
    return Object.values(queueState.queueState).filter((item) => item.status === "completed");
  }, [queueState.queueState]);

  const queuedItems = useMemo(() => {
    return Object.values(queueState.queueState);
  }, [queueState.queueState]);

  const $completedItems = completedItems;
  const $queuedItems = queuedItems;

  return (
    <Queue
      queueState={queueState}
      dispatch={dispatch}
      registerComponentApi={registerComponentApi}
      renderResultFeedback={
        node.props.resultFeedback
          ? (completedItems, queuedItems) => {
              return (
                <MemoizedItem
                  node={node.props.resultFeedback! as any}
                  contextVars={{
                    $completedItems: completedItems,
                    $queuedItems: queuedItems,
                  }}
                  renderChild={renderChild}
                />
              );
            }
          : undefined
      }
      renderProgressFeedback={
        node.props.progressFeedback
          ? (completedItems, queuedItems) => {
              return (
                <MemoizedItem
                  node={node.props.progressFeedback! as any}
                  contextVars={{
                    $completedItems: completedItems,
                    $queuedItems: queuedItems,
                  }}
                  renderChild={renderChild}
                />
              );
            }
          : undefined
      }
      willProcessItem={lookupEventHandler("willProcess", {
        context: {
          $completedItems,
          $queuedItems,
        },
      })}
      processItem={lookupEventHandler("process", {
        signError: false,
        context: {
          $completedItems,
          $queuedItems,
        },
      })}
      didProcessItem={lookupEventHandler("didProcess", {
        context: {
          $completedItems,
          $queuedItems,
        },
      })}
      processItemError={lookupEventHandler("processError", {
        context: {
          $completedItems,
          $queuedItems,
        },
      })}
      onComplete={lookupEventHandler("complete", {
        context: {
          $completedItems,
          $queuedItems,
        },
      })}
      clearAfterFinish={extractValue.asOptionalBoolean(node.props.clearAfterFinish)}
    />
  );
}


```
Page 49/143FirstPrevNextLast