#
tokens: 49955/50000 8/1630 files (page 44/143)
lines: off (toggle) GitHub
raw markdown copy
This is page 44 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

--------------------------------------------------------------------------------
/docs/content/components/Slider.md:
--------------------------------------------------------------------------------

```markdown
# Slider [#slider]

`Slider` provides an interactive control for selecting numeric values within a defined range, supporting both single value selection and range selection with multiple thumbs. It offers precise control through customizable steps and visual feedback with formatted value display.

Hover over the component to see the tooltip with the current value. On mobile, tap the thumb to see the tooltip.

**Key features:**
- **Range selection**: Single value or dual-thumb range selection with configurable minimum separation
- **Step control**: Precise incremental selection with customizable step values
- **Value formatting**: Custom display formatting for current values and visual feedback

## Properties [#properties]

### `autoFocus` (default: false) [#autofocus-default-false]

If this property is set to `true`, the component gets the focus automatically when displayed.

### `enabled` (default: true) [#enabled-default-true]

This boolean property value indicates whether the component responds to user events (`true`) or not (`false`).

### `initialValue` [#initialvalue]

This property sets the component's initial value.

```xmlui-pg
<Slider initialValue="5" />
```

### `maxValue` (default: 10) [#maxvalue-default-10]

This property specifies the maximum value of the allowed input range.

```xmlui-pg
<Slider maxValue="30" />
```

### `minStepsBetweenThumbs` (default: 1) [#minstepsbetweenthumbs-default-1]

This property sets the minimum number of steps required between multiple thumbs on the slider, ensuring they maintain a specified distance.

### `minValue` (default: 0) [#minvalue-default-0]

This property specifies the minimum value of the allowed input range.

```xmlui-pg
<Slider minValue="10" />
```

### `rangeStyle` [#rangestyle]

This optional property allows you to apply custom styles to the range element of the slider.

### `readOnly` (default: false) [#readonly-default-false]

Set this property to `true` to disallow changing the component value.

### `required` (default: false) [#required-default-false]

Set this property to `true` to indicate it must have a value before submitting the containing form.

### `showValues` (default: true) [#showvalues-default-true]

This property controls whether the slider shows the current values of the thumbs.

### `step` (default: 1) [#step-default-1]

This property defines the increment value for the slider, determining the allowed intervals between selectable values.

### `thumbStyle` [#thumbstyle]

This optional property allows you to apply custom styles to the thumb elements of the slider.

### `validationStatus` (default: "none") [#validationstatus-default-none]

This property allows you to set the validation status of the input component.

Available values:

| Value | Description |
| --- | --- |
| `valid` | Visual indicator for an input that is accepted |
| `warning` | Visual indicator for an input that produced a warning |
| `error` | Visual indicator for an input that produced an error |

### `valueFormat` (default: "(value) => value.toString()") [#valueformat-default-value-value-tostring]

This property allows you to customize how the values are displayed.

## Events [#events]

### `didChange` [#didchange]

This event is triggered when value of Slider has changed.

### `gotFocus` [#gotfocus]

This event is triggered when the Slider has received the focus.

### `lostFocus` [#lostfocus]

This event is triggered when the Slider has lost the focus.

## Exposed Methods [#exposed-methods]

### `focus` [#focus]

This method sets the focus on the slider component.

**Signature**: `focus(): void`

### `setValue` [#setvalue]

This API sets the value of the `Slider`. You can use it to programmatically change the value.

**Signature**: `setValue(value: number | [number, number] | undefined): void`

- `value`: The new value to set. Can be a single value or an array of values for range sliders.

### `value` [#value]

This API retrieves the current value of the `Slider`. You can use it to get the value programmatically.

**Signature**: `get value(): number | [number, number] | undefined`

## Styling [#styling]

### Theme Variables [#theme-variables]

| Variable | Default Value (Light) | Default Value (Dark) |
| --- | --- | --- |
| [backgroundColor](../styles-and-themes/common-units/#color)-range-Slider | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-range-Slider | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-range-Slider--disabled | $color-surface-400 | $color-surface-800 |
| [backgroundColor](../styles-and-themes/common-units/#color)-range-Slider--disabled | $color-surface-400 | $color-surface-800 |
| [backgroundColor](../styles-and-themes/common-units/#color)-thumb-Slider | $color-primary-500 | $color-primary-400 |
| [backgroundColor](../styles-and-themes/common-units/#color)-thumb-Slider | $color-primary-500 | $color-primary-400 |
| [backgroundColor](../styles-and-themes/common-units/#color)-thumb-Slider--active | $color-primary-400 | $color-primary-400 |
| [backgroundColor](../styles-and-themes/common-units/#color)-thumb-Slider--active | $color-primary-400 | $color-primary-400 |
| [backgroundColor](../styles-and-themes/common-units/#color)-thumb-Slider--focus | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-thumb-Slider--focus | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-thumb-Slider--hover | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-thumb-Slider--hover | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-track-Slider | $color-surface-200 | $color-surface-200 |
| [backgroundColor](../styles-and-themes/common-units/#color)-track-Slider | $color-surface-200 | $color-surface-200 |
| [backgroundColor](../styles-and-themes/common-units/#color)-track-Slider--disabled | $color-surface-300 | $color-surface-600 |
| [backgroundColor](../styles-and-themes/common-units/#color)-track-Slider--disabled | $color-surface-300 | $color-surface-600 |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--default | transparent | transparent |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--default | transparent | transparent |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--default--focus | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--default--hover | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--error | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--error--focus | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--error--hover | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--success | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--success--focus | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--success--hover | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--warning | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--warning--focus | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-Slider--warning--hover | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-thumb-Slider | $color-surface-50 | $color-surface-950 |
| [borderColor](../styles-and-themes/common-units/#color)-thumb-Slider | $color-surface-50 | $color-surface-950 |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-Slider--default | $borderRadius | $borderRadius |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-Slider--default | $borderRadius | $borderRadius |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-Slider--error | *none* | *none* |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-Slider--success | *none* | *none* |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-Slider--warning | *none* | *none* |
| [borderStyle](../styles-and-themes/common-units/#border-style)-Slider--default | solid | solid |
| [borderStyle](../styles-and-themes/common-units/#border-style)-Slider--default | solid | solid |
| [borderStyle](../styles-and-themes/common-units/#border-style)-Slider--error | *none* | *none* |
| [borderStyle](../styles-and-themes/common-units/#border-style)-Slider--success | *none* | *none* |
| [borderStyle](../styles-and-themes/common-units/#border-style)-Slider--warning | *none* | *none* |
| [borderStyle](../styles-and-themes/common-units/#border-style)-thumb-Slider | solid | solid |
| [borderStyle](../styles-and-themes/common-units/#border-style)-thumb-Slider | solid | solid |
| [borderWidth](../styles-and-themes/common-units/#size)-Slider--default | 0 | 0 |
| [borderWidth](../styles-and-themes/common-units/#size)-Slider--default | 0 | 0 |
| [borderWidth](../styles-and-themes/common-units/#size)-Slider--error | *none* | *none* |
| [borderWidth](../styles-and-themes/common-units/#size)-Slider--success | *none* | *none* |
| [borderWidth](../styles-and-themes/common-units/#size)-Slider--warning | *none* | *none* |
| [borderWidth](../styles-and-themes/common-units/#size)-thumb-Slider | 2px | 2px |
| [borderWidth](../styles-and-themes/common-units/#size)-thumb-Slider | 2px | 2px |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--default | none | none |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--default | none | none |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--default--focus | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--default--hover | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--error | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--error--focus | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--error--hover | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--success | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--success--focus | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--success--hover | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--warning | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--warning--focus | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-Slider--warning--hover | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-thumb-Slider | *none* | *none* |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-thumb-Slider--active | 0 0 0 6px rgb(from $color-primary r g b / 0.4) | 0 0 0 6px rgb(from $color-primary r g b / 0.4) |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-thumb-Slider--active | 0 0 0 6px rgb(from $color-primary r g b / 0.4) | 0 0 0 6px rgb(from $color-primary r g b / 0.4) |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-thumb-Slider--focus | 0 0 0 6px rgb(from $color-primary r g b / 0.4) | 0 0 0 6px rgb(from $color-primary r g b / 0.4) |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-thumb-Slider--focus | 0 0 0 6px rgb(from $color-primary r g b / 0.4) | 0 0 0 6px rgb(from $color-primary r g b / 0.4) |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-thumb-Slider--hover | 0 0 0 6px rgb(from $color-primary r g b / 0.4) | 0 0 0 6px rgb(from $color-primary r g b / 0.4) |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-thumb-Slider--hover | 0 0 0 6px rgb(from $color-primary r g b / 0.4) | 0 0 0 6px rgb(from $color-primary r g b / 0.4) |

```

--------------------------------------------------------------------------------
/xmlui/bin/build.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node

import { cp, mkdir, rm, writeFile } from "fs/promises";
import * as dotenv from "dotenv";
import { existsSync } from "fs";
import * as glob from "glob";
import type { InlineConfig } from "vite";
import { build as viteBuild } from "vite";
import { getViteConfig } from "./viteConfig";
import * as fs from "node:fs";

type ApiInterceptorDefinition = any;
type CompoundComponentDef = any;
type ThemeDefinition = any;

// --- Set up the configuration
dotenv.config({ path: `${process.cwd()}/.env` });
dotenv.config({ path: `${process.cwd()}/.env.local`, override: true });

type StandaloneJsonConfig = {
  name: string;
  appGlobals?: Record<string, any>;
  entryPoint?: string;
  components?: string[];
  themes?: string[];
  defaultTheme?: string;
  resources?: Record<string, string>;
  apiInterceptor?: ApiInterceptorDefinition;
  resourceMap?: Record<string, string>;
};

async function getExportedJsObjects<T>(path: string): Promise<Array<T>> {
  return await new Promise((resolve, reject) => {
    glob.glob(`${process.cwd()}/${path}`, (err: any, matches = []) => {
      const modules = Promise.all(
        matches.map(async (file: string) => {
          return (await import(file)).default;
        })
      );
      resolve(modules);
    });
  });
}

async function convertResourcesDir(distRoot: string, flatDist: boolean, filePrefix: string) {
  if (!flatDist) {
    return undefined;
  }
  distRoot = distRoot.replaceAll("\\", "/");
  const resourcesDir = `${distRoot}/resources`;
  if (!existsSync(resourcesDir)) {
    return undefined;
  }
  const files = await new Promise<string[]>((resolve, reject) => {
    glob.glob(`${resourcesDir}/**/*`, (err: any, matches = []) => {
      resolve(matches);
    });
  });

  const ret: Record<string, string> = {};
  for (let i = 0; i < files.length; i++) {
    const file = files[i];
    if (fs.statSync(file).isDirectory()) {
      continue;
    }
    const relativePath = file.replace(`${distRoot}/`, "");
    const convertedResource = `${filePrefix}${relativePath.replaceAll("/", "_")}`;

    await cp(file, `${distRoot}/${convertedResource}`);
    ret[relativePath] = convertedResource;
  }
  return ret;
}

export function removeLeadingSlashForPath(path: string): string {
  if (path.startsWith("/")) {
    return path.substring(1);
  }
  return path;
}

type UEBuildOptions = {
  buildMode?: "CONFIG_ONLY" | "INLINE_ALL" | "ALL";
  flatDist?: boolean;
  withMock?: boolean;
  withHostingMetaFiles?: boolean;
  withRelativeRoot?: boolean;
};

export const build = async ({
  buildMode = "CONFIG_ONLY",
  flatDist = false,
  withMock = false,
  withHostingMetaFiles = false,
  withRelativeRoot = false,
}: UEBuildOptions) => {
  const flatDistUiPrefix = "ui_";
  console.log("Building with options:", {
    buildMode,
    flatDist,
    withMock,
    withHostingMetaFiles,
    withRelativeRoot,
  });

  await viteBuild({
    ...(await getViteConfig({
      flatDist,
      withRelativeRoot,
      flatDistUiPrefix,
    })),
    define: {
      "process.env.VITE_BUILD_MODE": JSON.stringify(buildMode),
      "process.env.VITE_DEV_MODE": false,
      "process.env.VITE_MOCK_ENABLED": withMock,
      "process.env.VITE_APP_VERSION": JSON.stringify(process.env.VITE_APP_VERSION),

      "process.env.VITE_USED_COMPONENTS_App": JSON.stringify(process.env.VITE_USED_COMPONENTS_App),
      "process.env.VITE_USED_COMPONENTS_Chart": JSON.stringify(process.env.VITE_USED_COMPONENTS_Chart),
      "process.env.VITE_USED_COMPONENTS_AppHeader": JSON.stringify(process.env.VITE_USED_COMPONENTS_AppHeader),
      "process.env.VITE_USED_COMPONENTS_Stack": JSON.stringify(process.env.VITE_USED_COMPONENTS_Stack),
      "process.env.VITE_USED_COMPONENTS_Link": JSON.stringify(process.env.VITE_USED_COMPONENTS_Link),
      "process.env.VITE_USED_COMPONENTS_Text": JSON.stringify(process.env.VITE_USED_COMPONENTS_Text),
      "process.env.VITE_USED_COMPONENTS_Button": JSON.stringify(process.env.VITE_USED_COMPONENTS_Button),
      "process.env.VITE_USED_COMPONENTS_Card": JSON.stringify(process.env.VITE_USED_COMPONENTS_Card),
      "process.env.VITE_USED_COMPONENTS_Image": JSON.stringify(process.env.VITE_USED_COMPONENTS_Image),
      "process.env.VITE_USED_COMPONENTS_Footer": JSON.stringify(process.env.VITE_USED_COMPONENTS_Footer),
      "process.env.VITE_USED_COMPONENTS_SpaceFiller": JSON.stringify(process.env.VITE_USED_COMPONENTS_SpaceFiller),
      "process.env.VITE_USED_COMPONENTS_Pdf": JSON.stringify(process.env.VITE_USED_COMPONENTS_Pdf),
      "process.env.VITE_USED_COMPONENTS_Textarea": JSON.stringify(process.env.VITE_USED_COMPONENTS_Textarea),
      "process.env.VITE_USED_COMPONENTS_Logo": JSON.stringify(process.env.VITE_USED_COMPONENTS_Logo),
      "process.env.VITE_USED_COMPONENTS_NavLink": JSON.stringify(process.env.VITE_USED_COMPONENTS_NavLink),
      "process.env.VITE_USED_COMPONENTS_NavGroup": JSON.stringify(process.env.VITE_USED_COMPONENTS_NavGroup),
      "process.env.VITE_USED_COMPONENTS_Form": JSON.stringify(process.env.VITE_USED_COMPONENTS_Form),
      "process.env.VITE_USED_COMPONENTS_Tree": JSON.stringify(process.env.VITE_USED_COMPONENTS_Tree),
      "process.env.VITE_USED_COMPONENTS_Checkbox": JSON.stringify(process.env.VITE_USED_COMPONENTS_Checkbox),
      "process.env.VITE_USED_COMPONENTS_Switch": JSON.stringify(process.env.VITE_USED_COMPONENTS_Switch),
      "process.env.VITE_USED_COMPONENTS_DotMenu": JSON.stringify(process.env.VITE_USED_COMPONENTS_DotMenu),
      "process.env.VITE_USED_COMPONENTS_Heading": JSON.stringify(process.env.VITE_USED_COMPONENTS_Heading),
      "process.env.VITE_USED_COMPONENTS_Fragment": JSON.stringify(process.env.VITE_USED_COMPONENTS_Fragment),
      "process.env.VITE_USED_COMPONENTS_Table": JSON.stringify(process.env.VITE_USED_COMPONENTS_Table),
      "process.env.VITE_USED_COMPONENTS_List": JSON.stringify(process.env.VITE_USED_COMPONENTS_List),
      "process.env.VITE_USED_COMPONENTS_XmluiCodeHightlighter": JSON.stringify(process.env.VITE_USED_COMPONENTS_XmluiCodeHightlighter),
      "process.env.VITE_USED_COMPONENTS_Charts": JSON.stringify(process.env.VITE_USED_COMPONENTS_Charts),
      "process.env.VITE_INCLUDE_HTML_COMPONENTS": JSON.stringify(process.env.VITE_INCLUDE_HTML_COMPONENTS),
      "process.env.VITE_USED_COMPONENTS_DatePicker": JSON.stringify(process.env.VITE_USED_COMPONENTS_DatePicker),
      "process.env.VITE_USED_COMPONENTS_NavPanel": JSON.stringify(process.env.VITE_USED_COMPONENTS_NavPanel),
      "process.env.VITE_USED_COMPONENTS_Pages": JSON.stringify(process.env.VITE_USED_COMPONENTS_Pages),
      "process.env.VITE_USED_COMPONENTS_StickyBox": JSON.stringify(process.env.VITE_USED_COMPONENTS_StickyBox),
      "process.env.VITE_USED_COMPONENTS_Badge": JSON.stringify(process.env.VITE_USED_COMPONENTS_Badge),
      "process.env.VITE_USED_COMPONENTS_Avatar": JSON.stringify(process.env.VITE_USED_COMPONENTS_Avatar),
      "process.env.VITE_USED_COMPONENTS_ContentSeparator": JSON.stringify(
        process.env.VITE_USED_COMPONENTS_ContentSeparator
      ),
      "process.env.VITE_USED_COMPONENTS_FlowLayout": JSON.stringify(process.env.VITE_USED_COMPONENTS_FlowLayout),
      "process.env.VITE_USED_COMPONENTS_ModalDialog": JSON.stringify(process.env.VITE_USED_COMPONENTS_ModalDialog),
      "process.env.VITE_USED_COMPONENTS_NoResult": JSON.stringify(process.env.VITE_USED_COMPONENTS_NoResult),
      "process.env.VITE_USED_COMPONENTS_Option": JSON.stringify(process.env.VITE_USED_COMPONENTS_Option),
      "process.env.VITE_USED_COMPONENTS_FileUploadDropZone": JSON.stringify(
        process.env.VITE_USED_COMPONENTS_FileUploadDropZone
      ),
      "process.env.VITE_USED_COMPONENTS_Icon": JSON.stringify(process.env.VITE_USED_COMPONENTS_Icon),
      "process.env.VITE_USED_COMPONENTS_Items": JSON.stringify(process.env.VITE_USED_COMPONENTS_Items),
      "process.env.VITE_USED_COMPONENTS_SelectionStore": JSON.stringify(
        process.env.VITE_USED_COMPONENTS_SelectionStore
      ),
      "process.env.VITE_INCLUDE_REST_COMPONENTS": JSON.stringify(process.env.VITE_INCLUDE_REST_COMPONENTS),
      "process.env.VITE_USED_COMPONENTS_EmojiSelector": JSON.stringify(process.env.VITE_USED_COMPONENTS_EmojiSelector),
    },
  } as InlineConfig);

  if (buildMode === "INLINE_ALL") {
    return;
  }
  const distPath = "/dist";
  const themesFolder = flatDist ? "" : "themes";
  const componentsFolder = flatDist ? "" : "components";
  const themesFolderPath = flatDist ? distPath : `${distPath}/${themesFolder}`;
  const componentsFolderPath = flatDist ? distPath : `${distPath}/${componentsFolder}`;

  function getThemeFileName(theme: ThemeDefinition) {
    return flatDist ? `${flatDistUiPrefix}theme_${theme.id}` : theme.id;
  }

  function getComponentFileName(component: CompoundComponentDef) {
    return flatDist ? `${flatDistUiPrefix}component_${component.name}` : component.name;
  }

  function getEntrypointFileName() {
    return flatDist ? `${flatDistUiPrefix}entrypoint` : `app`;
  }

  if (buildMode === "CONFIG_ONLY") {
    let appDef;
    try {
      appDef = (await import(process.cwd() + "/src/config")).default;
    } catch (e) {
      console.log("couldn't find config");
    }

    const themePaths: string[] = [];
    const themes = await getExportedJsObjects<ThemeDefinition>("/src/themes/**.*");
    const fullDistPath = `${process.cwd()}${distPath}`;
    if (themes) {
      for (const theme of themes) {
        if (!existsSync(process.cwd() + themesFolderPath)) {
          await mkdir(process.cwd() + themesFolderPath, { recursive: true });
        }
        await writeFile(
          `${process.cwd()}${themesFolderPath}/${getThemeFileName(theme)}.json`,
          JSON.stringify(theme, null, 4)
        );
        themePaths.push(removeLeadingSlashForPath(`${themesFolder}/${getThemeFileName(theme)}.json`));
      }
    }

    const configJson: StandaloneJsonConfig = {
      ...appDef,
      resourceMap: await convertResourcesDir(fullDistPath, flatDist, flatDistUiPrefix),
      themes: themePaths,
    };
    delete configJson["components"];
    delete configJson["entryPoint"];
    if (!withMock) {
      delete configJson.apiInterceptor;
    }
    await writeFile(`${process.cwd()}${distPath}/config.json`, JSON.stringify(configJson, null, 4));
  } else if (buildMode === "ALL") {
    // const componentPaths: string[] = [];
    //   const components = await getExportedJsObjects<CompoundComponentDef>("/src/components/**.*");
    //   if (components) {
    //     for (const component of components) {
    //       if (!existsSync(`${process.cwd()}${componentsFolderPath}`)) {
    //         await mkdir(`${process.cwd()}${componentsFolderPath}`, { recursive: true });
    //       }
    //       await writeFile(
    //           `${process.cwd()}${componentsFolderPath}/${getComponentFileName(component)}.json`,
    //           JSON.stringify(component, null, 4)
    //       );
    //       componentPaths.push(removeLeadingSlashForPath(`${componentsFolder}/${getComponentFileName(component)}.json`));
    //     }
    //   }
    //
    // await writeFile(
    //   `${process.cwd()}${distPath}/${getEntrypointFileName()}.json`,
    //   JSON.stringify(appDef.entryPoint, null, 4)
    // );
    //
    // configJson = {
    //   ...configJson,
    //   entryPoint: `${getEntrypointFileName()}.json`,
    //   components: componentPaths,
    // };
  }

  //TODO temp, we should enforce user(who writes the metadata)-added-resources to be put in the resources folder
  if (flatDist) {
    await rm(`${process.cwd()}${distPath}/resources`, { recursive: true, force: true });
  }
  if (!withMock) {
    try {
      await rm(`${process.cwd()}${distPath}/mockServiceWorker.js`);
    } catch (ignored) {}
  }
  if (!withHostingMetaFiles) {
    try {
      await rm(`${process.cwd()}${distPath}/serve.json`);
    } catch (ignored) {}

    try {
      await rm(`${process.cwd()}${distPath}/web.config`);
    } catch (ignored) {}
    try {
      await rm(`${process.cwd()}${distPath}/_redirects`);
    } catch (ignored) {}
  }
};

```

--------------------------------------------------------------------------------
/xmlui/src/components/Text/TextNative.tsx:
--------------------------------------------------------------------------------

```typescript
import type { CSSProperties } from "react";
import type React from "react";
import { forwardRef, useMemo, useRef, useCallback, useEffect, memo } from "react";
import { composeRefs } from "@radix-ui/react-compose-refs";
import classnames from "classnames";

import styles from "./Text.module.scss";

import { getMaxLinesStyle } from "../../components-core/utils/css-utils";
import {
  type BreakMode,
  type OverflowMode,
  type TextVariant,
  TextVariantElement,
} from "../abstractions";
import type { RegisterComponentApiFn } from "../..";
import { useComponentStyle } from "../../components-core/theming/StyleContext";
import { EMPTY_OBJECT } from "../../components-core/constants";
import { toCssVar } from "../../components-core/theming/layout-resolver";

// =============================================================================
// Custom Variant CSS Cache Infrastructure
// =============================================================================

/**
 * Cached CSS information for a custom variant.
 */
interface CustomVariantCacheEntry {
  /** The generated CSS class name for this variant */
  className: string;
  /** The CSS text content that defines the styles for this variant */
  cssText: string;
  /** Timestamp when this entry was created (for debugging/cleanup) */
  createdAt: number;
}

/**
 * Global cache that stores custom variant CSS styles.
 * Key: variant value (string)
 *
 * This cache ensures the same variant value always generates the same CSS.
 */
const customVariantCache = new Map<string, CustomVariantCacheEntry>();

/**
 * Retrieves a cached custom variant entry if it exists.
 */
export function getCustomVariantCache(
  variant: string,
): CustomVariantCacheEntry | undefined {
  return customVariantCache.get(variant);
}

/**
 * Stores a custom variant entry in the cache.
 */
export function setCustomVariantCache(
  variant: string,
  entry: Omit<CustomVariantCacheEntry, "createdAt">,
): void {
  customVariantCache.set(variant, {
    ...entry,
    createdAt: Date.now(),
  });
}

/**
 * Checks if a custom variant is already cached.
 */
export function hasCustomVariantCache(variant: string): boolean {
  return customVariantCache.has(variant);
}

/**
 * Clears the entire custom variant cache.
 * Useful for testing or full app resets.
 */
export function clearCustomVariantCache(): void {
  customVariantCache.clear();
}

/**
 * Gets cache statistics for debugging.
 */
export function getCustomVariantCacheStats() {
  return {
    totalEntries: customVariantCache.size,
    entries: Array.from(customVariantCache.entries()).map(([key, entry]) => ({
      key,
      className: entry.className,
      createdAt: new Date(entry.createdAt).toISOString(),
    })),
  };
}

// =============================================================================
// Component Definition
// =============================================================================

type TextProps = {
  uid?: string;
  children?: React.ReactNode;
  variant?: TextVariant;
  maxLines?: number;
  preserveLinebreaks?: boolean;
  ellipses?: boolean;
  overflowMode?: OverflowMode;
  breakMode?: BreakMode;
  style?: CSSProperties;
  className?: string;
  registerComponentApi?: RegisterComponentApiFn;
  [variantSpecificProps: string]: any;
};

export const defaultProps = {
  maxLines: 0,
  preserveLinebreaks: false,
  ellipses: true,
  overflowMode: undefined as OverflowMode | undefined,
  breakMode: "normal" as BreakMode | undefined,
};

export const Text = forwardRef(function Text(
  {
    uid,
    variant,
    maxLines = defaultProps.maxLines,
    style,
    className,
    children,
    preserveLinebreaks = defaultProps.preserveLinebreaks,
    ellipses = defaultProps.ellipses,
    overflowMode = defaultProps.overflowMode,
    breakMode = defaultProps.breakMode,
    registerComponentApi,
    ...variantSpecificProps
  }: TextProps,
  forwardedRef,
) {
  const innerRef = useRef<HTMLElement>(null);
  const ref = forwardedRef ? composeRefs(innerRef, forwardedRef) : innerRef;

  // Implement hasOverflow function
  const hasOverflow = useCallback((): boolean => {
    const element = innerRef.current;
    if (!element) return false;

    // Check both horizontal and vertical overflow
    const hasHorizontalOverflow = element.scrollWidth > element.clientWidth;
    const hasVerticalOverflow = element.scrollHeight > element.clientHeight;

    return hasHorizontalOverflow || hasVerticalOverflow;
  }, []);

  // Register API with XMLUI if provided
  useEffect(() => {
    if (registerComponentApi) {
      registerComponentApi({ hasOverflow });
    }
  }, [registerComponentApi, hasOverflow]);

  // NOTE: This is to accept syntax highlight classes coming from shiki
  // classes need not to be added to the rendered html element, so we remove them from props
  const { syntaxHighlightClasses, ...restVariantSpecificProps } = variantSpecificProps;

  const Element = useMemo(() => {
    if (!variant || !TextVariantElement[variant]) return "div";
    return TextVariantElement[variant];
  }, [variant]);

  // Custom variant CSS generation
  // Following React hook rules: hooks must be called unconditionally
  // We always call useComponentStyle, passing empty object for known variants
  const isCustomVariant = useMemo(() => {
    return variant && !TextVariantElement[variant];
  }, [variant]);

  // Always call useComponentStyle (React hook rule: no conditional hooks)
  // For now, pass empty object; later this will contain assembled CSS properties
  const variantSpec = useMemo(
    () => {
      if (!isCustomVariant) return EMPTY_OBJECT;
      const subject = `-Text-${variant}`;
      const cssInput = {
        color: toCssVar(`$textColor${subject}`),
        "font-family": toCssVar(`$fontFamily${subject}`),
        "font-size": toCssVar(`$fontSize${subject}`),
        "font-style": toCssVar(`$fontStyle${subject}`),
        "font-weight": toCssVar(`$fontWeight${subject}`),
        "font-stretch": toCssVar(`$fontStretch${subject}`),
        "text-decoration-line": toCssVar(`$textDecorationLine${subject}`),
        "text-decoration-color": toCssVar(`$textDecorationColor${subject}`),
        "text-decoration-style": toCssVar(`$textDecorationStyle${subject}`),
        "text-decoration-thickness": toCssVar(`$textDecorationThickness${subject}`),
        "text-underline-offset": toCssVar(`$textUnderlineOffset${subject}`),
        "line-height": toCssVar(`$lineHeight${subject}`),
        "background-color": toCssVar(`$backgroundColor${subject}`),
        "text-transform": toCssVar(`$textTransform${subject}`),
        "letter-spacing": toCssVar(`$letterSpacing${subject}`),
        "word-spacing": toCssVar(`$wordSpacing${subject}`),
        "text-shadow": toCssVar(`$textShadow${subject}`),
        "text-indent": toCssVar(`$textIndent${subject}`),
        "text-align": toCssVar(`$textAlign${subject}`),
        "text-align-last": toCssVar(`$textAlignLast${subject}`),
        "word-break": toCssVar(`$wordBreak${subject}`),
        "word-wrap": toCssVar(`$wordWrap${subject}`),
        direction: toCssVar(`$direction${subject}`),
        "writing-mode": toCssVar(`$writingMode${subject}`),
        "line-break": toCssVar(`$lineBreak${subject}`),
      };
      return cssInput;
    },
    [isCustomVariant, variant],
  );
  const customVariantClassName = useComponentStyle(variantSpec);

  // Store custom variant in cache if it's a new custom variant
  useEffect(() => {
    if (isCustomVariant && variant && customVariantClassName) {
      // Check if this variant is already cached
      if (!hasCustomVariantCache(variant)) {
        // TODO: When CSS generation is implemented, extract the actual CSS text
        // For now, store placeholder information
        setCustomVariantCache(variant, {
          className: customVariantClassName,
          cssText: "", // Will be populated when CSS generation is implemented
        });
      }
    }
  }, [isCustomVariant, variant, customVariantClassName]);

  // Determine overflow mode classes based on overflowMode and existing props
  const overflowClasses = useMemo(() => {
    const classes: Record<string, boolean> = {};

    // If overflowMode is not explicitly set, use original behavior
    if (!overflowMode) {
      classes[styles.truncateOverflow] = maxLines > 0;
      classes[styles.noEllipsis] = !ellipses;
      return classes;
    }

    switch (overflowMode) {
      case "none":
        // CSS: overflow: hidden + text-overflow: clip + normal wrapping
        // Effect: Text wraps normally but clips cleanly at container boundaries without ellipsis
        classes[styles.overflowNone] = true;
        break;
      case "scroll":
        // CSS: white-space: nowrap + overflow-x: auto + overflow-y: hidden
        // Effect: Forces single line, enables horizontal scrollbar when content overflows
        classes[styles.overflowScroll] = true;
        break;
      case "ellipsis":
        // CSS: Uses -webkit-line-clamp for multi-line or white-space: nowrap + text-overflow: ellipsis for single line
        // Effect: Shows "..." when text is truncated, respects maxLines for multi-line truncation
        classes[styles.truncateOverflow] = true;
        classes[styles.noEllipsis] = !ellipses;
        break;
      case "flow":
        // CSS: white-space: normal + overflow-y: auto + overflow-x: hidden
        // Effect: Text wraps to multiple lines with vertical scrolling when needed, no horizontal scrollbar
        // Note: Flow mode ignores maxLines to allow unlimited text wrapping
        classes[styles.overflowFlow] = true;
        break;
    }

    return classes;
  }, [overflowMode, maxLines, ellipses]);

  // Determine break mode classes
  const breakClasses = useMemo(() => {
    const classes: Record<string, boolean> = {};

    // Only apply break mode classes if explicitly set (preserves theme variable support)
    if (breakMode) {
      switch (breakMode) {
        case "normal":
          // CSS: word-break: normal + overflow-wrap: normal
          // Effect: Standard word breaking at natural boundaries (spaces, hyphens)
          classes[styles.breakNormal] = true;
          break;
        case "word":
          // CSS: overflow-wrap: break-word
          // Effect: Breaks long words only when necessary to prevent overflow, preserves word boundaries when possible
          classes[styles.breakWord] = true;
          break;
        case "anywhere":
          // CSS: word-break: break-all + overflow-wrap: anywhere
          // Effect: Most aggressive breaking - allows breaking between any characters to fit container
          classes[styles.breakAnywhere] = true;
          break;
        case "keep":
          // CSS: word-break: keep-all
          // Effect: Prevents breaking within words entirely (useful for CJK text or technical terms)
          classes[styles.breakKeep] = true;
          break;
        case "hyphenate":
          // CSS: hyphens: auto + overflow-wrap: break-word
          // Effect: Uses browser's hyphenation dictionary to break words with proper hyphens
          classes[styles.breakHyphenate] = true;
          break;
      }
    }

    return classes;
  }, [breakMode]);

  return (
    <Element
      {...restVariantSpecificProps}
      ref={ref as any}
      className={classnames(
        syntaxHighlightClasses,
        styles.text,
        // Use custom variant className if it's a custom variant, otherwise use predefined variant style
        isCustomVariant ? customVariantClassName : styles[variant || "default"],
        {
          [styles.preserveLinebreaks]: preserveLinebreaks,
          ...overflowClasses,
          ...breakClasses,
        },
        className,
      )}
      style={{
        ...style,
        // Apply maxLines style for "ellipsis" mode and default behavior
        // "none", "scroll", and "flow" modes ignore maxLines for predictable, reliable behavior
        ...(overflowMode === "ellipsis" || (!overflowMode && maxLines)
          ? getMaxLinesStyle(maxLines)
          : {}),
      }}
    >
      {children}
    </Element>
  );
});

```

--------------------------------------------------------------------------------
/xmlui/src/testing/component-test-helpers.ts:
--------------------------------------------------------------------------------

```typescript
import type { Locator } from "@playwright/test";

import { type ParserResult, xmlUiMarkupToComponent } from "../components-core/xmlui-parser";
import type { ComponentDef, CompoundComponentDef } from "../abstractions/ComponentDefs";

import chroma, { type Color } from "chroma-js";
import { ComponentDriver } from "./ComponentDrivers";

export type ThemeTestDesc = {
  themeVar: string;
  themeVarAsCSS: string;
  expected: string;
  dependsOnVars?: Record<string, string>;
};

export function mapObject<K extends (val: any) => any, V extends (val: string) => string | number>(
  obj: Record<string, any>,
  valFn: K = ((val) => val) as K,
  keyFn: V = ((val) => val) as V,
) {
  const newObject = {} as Record<ReturnType<V>, ReturnType<K>>;
  Object.entries(obj).forEach(([key, value]) => {
    newObject[keyFn(key)] = valFn(value);
  });
  return newObject;
}

export function getComponentTagName(locator: Locator) {
  return locator.evaluate((el) => el.tagName.toLowerCase());
}

export function parseComponentIfNecessary(
  rawComponent: ComponentDef<any> | CompoundComponentDef | string,
): ParserResult {
  if (typeof rawComponent === "string") {
    return xmlUiMarkupToComponent(rawComponent);
  }
  return {
    component: rawComponent,
    errors: [],
    erroneousCompoundComponentName: undefined,
  };
}

/**
 * Scales a value by a percentage, using NumericCSS for parsing and clarity.
 * @param scalarOf100Percent The value representing 100%.
 * @param percentage A percentage string in the format "NN%", e.g., "40%". Must end with '%'.
 * @returns The scaled value.
 */
export function scaleByPercent(scalarOf100Percent: number, percentage: string) {
  const parsed = parseAsNumericCss(percentage);
  if (parsed.unit !== "%") {
    throw new Error(`Expected percentage unit (%), got: ${parsed.unit}`);
  }
  return (scalarOf100Percent / 100) * parsed.value;
}

export function getBoundingRect(locator: Locator) {
  return locator.evaluate((element) => element.getBoundingClientRect());
}

export function getElementStyle(specifier: Locator, style: string) {
  return specifier.evaluate(
    (element, style) => window.getComputedStyle(element).getPropertyValue(style),
    style,
  );
}

/**
 * Retreives all the provided style properties from the locator
 * @returns an object with the keys being the elements of the styles argument
 */
export function getElementStyles(locator: Locator, styles: string[] = []) {
  return locator.evaluate(
    (element, styles) =>
      Object.fromEntries(
        styles.map((styleName) => [
          styleName,
          window.getComputedStyle(element).getPropertyValue(styleName),
        ]),
      ),
    styles,
  );
}

export function isIndeterminate(specifier: ComponentDriver | Locator) {
  if (specifier instanceof ComponentDriver) specifier = specifier.component;
  return specifier.evaluate((el: HTMLInputElement) => el.indeterminate);
}

export async function overflows(locator: Locator, direction: "x" | "y" | "both" = "both") {
  const [width, height, scrollWidth, scrollHeight] = await locator.evaluate((element) => [
    element.clientWidth,
    element.clientHeight,
    element.scrollWidth,
    element.scrollHeight,
  ]);
  if (direction === "x") return scrollWidth > width;
  if (direction === "y") return scrollHeight > height;
  return scrollWidth > width && scrollHeight > height;
}

// ----------------------------------
// ComponentDriver style helpers
// ----------------------------------

export function getStyles(specifier: ComponentDriver | Locator, style: string | string[]) {
  if (specifier instanceof ComponentDriver) specifier = specifier.component;
  style = Array.isArray(style) ? style : [style];
  return specifier.evaluate(
    (element, styles) =>
      Object.fromEntries(
        styles.map((styleName) => [
          styleName
            .trim()
            .split("-")
            .map((n, idx) => (idx === 0 ? n : n[0].toUpperCase() + n.slice(1)))
            .join(""),
          window.getComputedStyle(element).getPropertyValue(styleName),
        ]),
      ),
    style,
  );
}

export function getPseudoStyles(
  specifier: ComponentDriver | Locator,
  pseudoElement: string,
  style: string | string[],
) {
  if (specifier instanceof ComponentDriver) specifier = specifier.component;
  style = Array.isArray(style) ? style : [style];
  return specifier.evaluate(
    (element, obj) =>
      Object.fromEntries(
        obj.style.map((styleName) => [
          styleName
            .trim()
            .split("-")
            .map((n, idx) => (idx === 0 ? n : n[0].toUpperCase() + n.slice(1)))
            .join(""),
          window.getComputedStyle(element, obj.pseudoElement).getPropertyValue(styleName),
        ]),
      ),
    { style, pseudoElement },
  );
}

export async function getHtmlAttributes(
  specifier: ComponentDriver | Locator,
  attributes: string | string[],
): Promise<{ [k: string]: string }> {
  if (specifier instanceof ComponentDriver) specifier = specifier.component;
  attributes = Array.isArray(attributes) ? attributes : [attributes];

  const mapped = await Promise.all(
    attributes.map(async (attr) => {
      return [attr, await specifier.getAttribute(attr)];
    }),
  );
  return Object.fromEntries(mapped);
}

export async function getPaddings(specifier: ComponentDriver | Locator) {
  const paddings = mapObject(
    await getStyles(specifier, ["padding-left", "padding-right", "padding-top", "padding-bottom"]),
    parseAsNumericCss,
  );
  return {
    left: paddings.paddingLeft,
    right: paddings.paddingRight,
    top: paddings.paddingTop,
    bottom: paddings.paddingBottom,
  };
}

export async function getBorders(specifier: ComponentDriver | Locator) {
  const borders = mapObject(
    await getStyles(specifier, ["border-left", "border-right", "border-top", "border-bottom"]),
    parseAsCssBorder,
  );
  return {
    left: borders.borderLeft,
    right: borders.borderRight,
    top: borders.borderTop,
    bottom: borders.borderBottom,
  };
}

export function getMargins(specifier: ComponentDriver | Locator) {
  return getStyles(specifier, ["margin-left", "margin-right", "margin-top", "margin-bottom"]);
}

/**
 * Retrieves the bounding rectangle of the component including **margins** and **padding**
 * added to the dimensions.
 */
export async function getBounds(specifier: ComponentDriver | Locator) {
  if (specifier instanceof ComponentDriver) specifier = specifier.component;
  const boundingRect = await specifier.evaluate((element) => element.getBoundingClientRect());
  const m = mapObject(await getMargins(specifier), parseFloat);

  const width = boundingRect.width + m.marginLeft + m.marginRight;
  const height = boundingRect.height + m.marginTop + m.marginBottom;
  const left = boundingRect.left - m.marginLeft;
  const right = boundingRect.right + m.marginRight;
  const top = boundingRect.top - m.marginTop;
  const bottom = boundingRect.bottom + m.marginBottom;

  return {
    width,
    height,
    left,
    right,
    top,
    bottom,
  };
}

/**
 * Provides annotations for skipped tests and the ability to specify a reason.
 * Use it via the SKIP_REASON exported variable.
 */
class TestSkipReason {
  private addAnnotation(type: string, description?: string) {
    return {
      annotation: {
        type,
        description: description ?? "",
      },
    };
  }

  NOT_IMPLEMENTED_XMLUI(description?: string) {
    return this.addAnnotation("not implemented in xmlui", description);
  }

  TO_BE_IMPLEMENTED(description?: string) {
    return this.addAnnotation("to be implemented", description);
  }

  XMLUI_BUG(description?: string) {
    return this.addAnnotation("xmlui bug", description);
  }

  TEST_INFRA_BUG(description?: string) {
    return this.addAnnotation("test infra bug", description);
  }

  TEST_NOT_WORKING(description?: string) {
    return this.addAnnotation("test not working", description);
  }

  TEST_INFRA_NOT_IMPLEMENTED(description?: string) {
    return this.addAnnotation("test infra not implemented", description);
  }

  REFACTOR(description?: string) {
    return this.addAnnotation("refactor", description);
  }

  // Need to specify a reason here!
  UNSURE(description: string) {
    return this.addAnnotation("unsure", description);
  }
}

/**
 * Provides annotations for skipped tests and the ability to specify a reason.
 *
 * Usage:
 *
 * ```ts
 * import { SKIP_REASON } from "./tests/component-test-helpers";
 *
 * test.skip(
 *   "test name",
 *   SKIP_REASON.NOT_IMPLEMENTED_XMLUI("This test is not implemented in xmlui")
 *   async ({}) => {},
 * );
 * ```
 */
export const SKIP_REASON = new TestSkipReason();

// --- CSS types and parsers

export function pixelStrToNum(pixelStr: string) {
  return Number(pixelStr.replace("px", ""));
}

export function parseAsCssBorder(str: string) {
  const parts = str.split(/\s+(?=[a-z]+|\()/i);
  if (parts.length > 3) {
    throw new Error(`Provided value ${str} cannot be parsed as a CSS border`);
  }
  const style = parts.filter(isCSSBorderStyle);
  if (style.length > 1) {
    throw new Error(`Too many border styles provided in ${str}`);
  }

  const width = parts.filter(isNumericCSS);
  if (width.length > 1) {
    throw new Error(`Too many border widths provided in ${str}`);
  }

  const color = parts.filter((p) => chroma.valid(p));
  if (color.length > 1) {
    throw new Error(`Too many border colors provided in ${str}`);
  }

  const result: CSSBorder = {
    width: !!width[0] ? parseAsNumericCss(width[0]) : undefined,
    style: style[0],
    color: chroma(color[0]),
  };
  return result;
}

export interface NumericCSS {
  value: number;
  unit: CSSUnit;
}

const numericCSSRegex = /^([+-]?(?:\d+|\d*\.\d+))([a-z]*|%)$/;

export function isNumericCSS(str: any): str is NumericCSS {
  const parts = str.match(numericCSSRegex);

  if (!parts) return false;
  if (parts.length < 3) return false;
  if (isNaN(parseFloat(parts[1]))) return false;
  if (!isCSSUnit(parts[2])) return false;

  return true;
}

export function parseAsNumericCss(str: string) {
  const parts = str.match(numericCSSRegex);
  if (!parts) {
    throw new Error(`Provided value ${str} cannot be parsed as a numeric CSS value`);
  }
  if (parts.length < 3) {
    throw new Error(`${parts[0]} is not a correct numeric CSS value`);
  }
  const value = parseFloat(parts[1]);
  if (isNaN(value)) {
    throw new Error(`${value} is not a valid number in ${str}`);
  }
  const unit = parts[2];
  if (!isCSSUnit(unit)) {
    throw new Error(`${unit} is not have a valid CSS unit in ${str}`);
  }
  const result: NumericCSS = { value, unit };
  return result;
}

export function numericCSSToString(cssValue: NumericCSS) {
  return `${cssValue.value}${cssValue.unit}`;
}

export type CSSColor = chroma.Color;

export function isCSSColor(str: any): str is CSSColor {
  return chroma.valid(str);
}

export function parseAsCSSColor(str: string): CSSColor {
  return chroma(str);
}

const CSSUnitValues = [
  "px",
  "em",
  "rem",
  "vh",
  "vw",
  "%",
  "cm",
  "mm",
  "in",
  "pt",
  "pc",
  "ex",
  "ch",
  "vmin",
  "vmax",
] as const;
type CSSUnit = (typeof CSSUnitValues)[number];

function isCSSUnit(str: string): str is CSSUnit {
  return CSSUnitValues.includes(str as any);
}

export type CSSBorder = {
  width?: NumericCSS;
  style?: CSSBorderStyle;
  color?: Color;
};

const CSSBorderStyleValues = [
  "solid",
  "dotted",
  "dashed",
  "double",
  "none",
  "hidden",
  "groove",
  "ridge",
  "inset",
  "outset",
] as const;
export type CSSBorderStyle = (typeof CSSBorderStyleValues)[number];

export function isCSSBorderStyle(str: string): str is CSSBorderStyle {
  return CSSBorderStyleValues.includes(str as any);
}
export function parseAsCSSBorderStyle(str: string) {
  if (!isCSSBorderStyle(str)) {
    throw new Error(`Provided value ${str} cannot be parsed as a CSS border style`);
  }
  return str;
}

export const BorderSideValues = ["top", "bottom", "left", "right"] as const;
export type BorderSide = (typeof BorderSideValues)[number];

export function isBorderSide(str: string): str is BorderSide {
  return BorderSideValues.includes(str as any);
}

```

--------------------------------------------------------------------------------
/xmlui/src/components/Tree/Tree.md:
--------------------------------------------------------------------------------

```markdown
%-DESC-START

**Key features:**
- **Flat and hierarchical data structures**: You can select the most convenient data format to represent the tree. A set of properties enables you to map your data structure to the visual representation of the tree.
- **Flexible expand/collapse**: You have several properties to represent the expanded and collapsed state of tree nodes. You can also specify several options that determine which tree items are collapsed initially. 
- **Tree API**: Several exposed methods allow you to manage the tree's view state imperatively.

## Specifying Data

With the `dataFormat` property, you can select between "flat" or "hierarchy" formats. The component transforms the data according to the value of this property into a visual representation.

The "flat" and "hierarchy" data structures both use these fields for a particular tree node:
- `id`: Unique ID of tree node
- `name`: The field to be used as the display label
- `icon`: An optional icon identifier. If specified, this icon is displayed with the tree item.
- `iconExpanded`: An optional icon identifier. This icon is displayed when the field is expanded.
- `iconCollapsed`: An optional icon identifier. This icon is displayed when the field is collapsed.
- `selectable`: Indicates if the node can be selected.

The "flat" structure refers to its direct parent node via the `parentId` property, which contains the ID of the node it is referring to.

The "hierarchy" structure uses a `children` property, which is an array of nested child nodes (using the common node property set above).

This example demonstrates the use of the "flat" data mode:

```xmlui-pg display copy height="220px" /"flat"/ /parentId/ name="Example: flat data format"
<App>
  <Tree
    testId="tree"
    dataFormat="flat"
    defaultExpanded="all"
    data='{[
      { id: 1, icon:"folder", name: "Root Item 1", parentId: null },
      { id: 2, icon:"folder", name: "Child Item 1.1", parentId: 1 },
      { id: 3, icon: "code", name: "Child Item 1.2", parentId: 1 },
      { id: 4, icon: "code", name: "Grandchild Item 1.1.1", parentId: 2 },
    ]}'>
  </Tree>
</App>
```

This example demonstrates the use of the "hiearchy" data mode:

```xmlui-pg display copy height="220px" /"flat"/ /children/ name="Example: hierarchical data format"
<App>
  <Tree
    testId="tree"
    dataFormat="hierarchy"
    defaultExpanded="all"
    data='{[
      {
        id: 1, icon: "folder", name: "Root Item 1",
        children: [
          { id: 2, icon: "code", name: "Child Item 1.1" },
          { id: 3, icon: "folder", name: "Child Item 1.2",
            children: [
              { id: 4, icon: "code", name: "Grandchild Item 1.2.1"}
            ],
          }
        ],
      },
    ]}'>
  </Tree>
</App>
```

When you use data (for example, retrieved from a backend), those structures may use different property names. The `Tree` component allows mapping data field names through these properties: 
- `idField` (default: `id`)
- `nameField` (default: `name`)
- `iconField`  (default: `icon`)
- `iconExpandedField` (default: `iconExpanded`)
- `iconCollapsedField` (default: `iconCollapsed`)
- `parentIdField` (default: `parentId`)
- `childrenField` (default: `children`)
- `selectableField` (default: `selectable`)

The following example uses the `idField`, `nameField`, and `parentIdField` mapping properties:

```xmlui-pg display copy height="220px" /idField/ /nameField/ /parentIdField/ /uid/ /label/ /parent/ name="Example: mapping data fields"
<App>
  <Tree
    testId="tree"
    dataFormat="flat"
    defaultExpanded="all"
    idField="uid"
    nameField="label"
    parentIdField="parent"
    data='{[
      { uid: 1, icon:"folder", label: "Root Item 1", parent: null },
      { uid: 2, icon:"folder", label: "Child Item 1.1", parent: 1 },
      { uid: 3, icon: "code", label: "Child Item 1.2", parent: 1 },
      { uid: 4, icon: "code", label: "Grandchild Item 1.1.1", parent: 2 },
    ]}'>
  </Tree>
</App>
```

## Expanding and collapsing tree nodes

By default, when you click a tree node outside of its expand/collapse icon,  the specified item is selected. With the `expandOnItemClick` property (using the `true` value), you can change this behavior to expand or collapse the item when clicking its surface anywhere.

You can use the `defaultExpanded` property to specify what nodes you want to see expanded initially. You can set this property to a list of node IDs or a string. When you specify IDs, the component expands the hierarchy to reveal the specified nodes. When the value is a string, you can use these options:
- `none`: all nodes are collapsed (default)
- `first-level`: all first-level nodes are expanded
- `all`: all nodes are expanded

The following example demonstrates the use of `defaultExpanded` with tree node IDs:

```xmlui-pg display copy height="300px" /doc-root/ /proj-web/ /media-profile-pic/ name="Example: defaultExpanded with node IDs"
<App>
  <Tree
    testId="tree"
    dataFormat="flat"
    defaultExpanded="{['doc-root', 'proj-web', 'media-profile-pic']}"
    data='{[
      // Branch A: Documents
      { id: "doc-root", name: "[Documents]", parentId: null },
      { id: "doc-reports", name: "Reports", parentId: "doc-root" },
      { id: "doc-invoices", name: "Invoices", parentId: "doc-root" },
      { id: "doc-q1-report", name: "Q1 Report.pdf", parentId: "doc-reports" },
      { id: "doc-q2-report", name: "Q2 Report.pdf", parentId: "doc-reports" },
      { id: "doc-inv-001", name: "Invoice-001.pdf", parentId: "doc-invoices" },

      // Branch B: Projects
      { id: "proj-root", name: "Projects", parentId: null },
      { id: "proj-web", name: "[Web Apps]", parentId: "proj-root" },
      { id: "proj-mobile", name: "Mobile Apps", parentId: "proj-root" },
      { id: "proj-ecommerce", name: "E-commerce Site", parentId: "proj-web" },
      { id: "proj-dashboard", name: "Admin Dashboard", parentId: "proj-web" },
      { id: "proj-ios-app", name: "iOS Shopping App", parentId: "proj-mobile" },

      // Branch C: Media
      { id: "media-root", name: "Media", parentId: null },
      { id: "media-images", name: "Images", parentId: "media-root" },
      { id: "media-videos", name: "Videos", parentId: "media-root" },
      { id: "media-profile-pic", name: "[profile.jpg]", parentId: "media-images" },
      { id: "media-banner", name: "banner.png", parentId: "media-images" },
    ]}'>
  </Tree>
</App>
```

You have several options to style the icons representing the expanded or collapsed state:
- The icons used for the expanded and collapsed states can be changed with the `iconExpanded` and `iconCollapsed` properties, respectively.
- You can specify a different size with the `iconSize` property (using only numeric values considered as pixels)
- Using a rotate animation when changing the state with the `animateExpand` flag.
The following option demonstrates the last two options:

```xmlui-pg display copy {4-5} height="220px" name="Example: expand/collapse options"
<App>
  <Tree
    testId="tree"
    iconSize="24"
    animateExpand
    dataFormat="flat"
    defaultExpanded="all"
    data='{[
      { id: 1, name: "Root Item 1", parentId: null },
      { id: 2, name: "Child Item 1.1", parentId: 1 },
      { id: 3, name: "Child Item 1.2", parentId: 1 },
      { id: 4, name: "Grandchild Item 1.1.1", parentId: 2 },
    ]}'>
  </Tree>
</App>
```

## Selection

Each tree node is selectable by default, unless the node item's data does not have a `selectable` property (or the one specified in `selectedField`).
A selectable item can be selected by clicking the mouse or pressing the Enter or Space keys when it has focus.

You can set the `selectedValue` property to define the selected tree item, ot use the `selectNode` exposed method for imperative selection.

## Item templates

You can override the default template used to display a tree item with the `itemTemplate` property. The template definition can use the `$item` context variable to access the item's attributes for display. `$item` provides these properties:
- `id`: The unique node ID
- `name`: The name of the node
- `depth`: The depth level in the tree
- `isExpanded`: Indicates if the tree node is expanded
- `hasChildren`: Indicates if the tree node has children
- `children`: The children of the tree node
- `selectable`: Indicates if the node can be selected
- `parentId`: The ID of the node's parent
- `parentIds`: A list of parent IDs from the root node to the direct parent of the node
- `path`: An array with the node names following the path from the root node to the displayed node.
- `loadingState`: The current state of a dynamic node ("unloaded", "loading", or "loaded")

This example demonstrates these concepts:

```xmlui-pg display copy {20-30} height="400px" /$item.id/ /$item.name/ /$item.hasChildren/ name="Example: itemTemplate"
<App>
  <Tree
    testId="tree"
    id="tree"
    defaultExpanded="all"
    data='{[
        { id: "root", name: "My Files", parentId: null },
        { id: "doc-root", name: "Documents", parentId: "root" },
        { id: "doc-reports", name: "Reports", parentId: "doc-root" },
        { id: "doc-q1-report", name: "Q1 Report.pdf", parentId: "doc-reports" },
        { id: "doc-q2-report", name: "Q2 Report.pdf", parentId: "doc-reports" },
        { id: "proj-root", name: "Projects", parentId: "root" },
        { id: "proj-web", name: "Web Apps", parentId: "proj-root" },
        { id: "proj-ecommerce", name: "E-commerce Site", parentId: "proj-web" },
        { id: "proj-dashboard", name: "Admin Dashboard", parentId: "proj-web" },
        { id: "media-root", name: "Media", parentId: "root" },
        { id: "media-images", name: "Images", parentId: "media-root" },
        { id: "media-videos", name: "Videos", parentId: "media-root" },
      ]}'>
    <property name="itemTemplate">
      <HStack testId="{$item.id}" verticalAlignment="center" gap="$space-1">
        <Icon name="{$item.hasChildren ? 'folder' : 'code'}" />
        <Text>
          ({$item.id}):
        </Text>
        <Text variant="strong">
          {$item.name}
        </Text>
      </HStack>
    </property>
  </Tree>
</App>
```

## Dynamic tree nodes

When initializing the tree with its `data` property, you can set the `dynamic` property of the node to `true` (you can use a field name alias with the `dynamicField` property). When you extend a dynamic node, the tree fires the `loadChildren` event, and the nodes returned by the event handler will be the actual nodes.

By default, nodes are not dynamic.

While the child nodes are being queried, the tree node displays a spinner to indicate the loading state.

You can use the `markNodeUnloaded` exposed method to reset the state of an already loaded dynamic tree node. The next time the user expands the node, its content will be loaded again.

The following sample demonstrates this feature. Click the "Child Item 1.2" node to check how it loads its children. Click the Unload button to reload the items when the node is expanded the next time.

```xmlui-pg display copy {16-19} height="340px" /dynamic: true/ /onLoadChildren/ name="Example: dynamic nodes"
<App var.loadCount="{0}">
  <Tree
    testId="tree"
    defaultExpanded="all"
    id="tree"
    itemClickExpands
    data='{[
      { id: 1, name: "Root Item 1", parentId: null },
      { id: 2, name: "Child Item 1.1", parentId: 1 },
      { id: 3, name: "Child Item 1.2", parentId: 1, dynamic: true },
      { id: 4, name: "Child Item 1.3", parentId: 1 },
    ]}'
    onLoadChildren="(node) => {
      loadCount++;
      delay(1000); 
      return ([
        { id: 5, name: `Dynamic Item 1.2.1 (${loadCount})` },
        { id: 6, name: `Dynamic Item 2.2.2 (${loadCount})` },
      ])
    }"
    >
    <property name="itemTemplate">
      <HStack testId="{$item.id}" verticalAlignment="center" gap="$space-1">
        <Icon name="{$item.hasChildren 
          ? ($item.loadingState === 'loaded' ? 'folder' : 'folder-outline' ) 
          : 'code'}" 
        />
        <Text>{$item.name}</Text>
      </HStack>
    </property>
  </Tree>
  <Button onClick="tree.markNodeUnloaded(3)">Unload</Button>
</App>
```

%-DESC-END
```

--------------------------------------------------------------------------------
/xmlui/tests/parsers/scripting/statement-hooks.test.ts:
--------------------------------------------------------------------------------

```typescript
import { describe, expect, it } from "vitest";

import { processStatementQueueAsync } from "../../../src/components-core/script-runner/process-statement-async";
import { processStatementQueue } from "../../../src/components-core/script-runner/process-statement-sync";
import { createEvalContext, parseStatements } from "./test-helpers";

describe("Statement hooks", () => {
  const stmtCases = [
    { src: "let x = 0;", exp: 1 },
    { src: "let x = 0; x++;", exp: 2 },
    { src: "let x = 0; while (x < 1) { x++ };", exp: 6 },
  ];

  stmtCases.forEach((c) => {
    it(`onStatementStarted (async) works ${c.src}`, async () => {
      // --- Arrange
      let counter = 0;
      const evalContext = createEvalContext({
        localContext: {},
        onStatementStarted: () => {
          counter++;
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      await processStatementQueueAsync(statements, evalContext);

      // --- Assert
      expect(counter).equal(c.exp);
    });
  });

  stmtCases.forEach((c) => {
    it(`onStatementStarted (sync) works ${c.src}`, () => {
      // --- Arrange
      let counter = 0;
      const evalContext = createEvalContext({
        localContext: {},
        onStatementStarted: () => {
          counter++;
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      processStatementQueue(statements, evalContext);

      // --- Assert
      expect(counter).equal(c.exp);
    });
  });

  stmtCases.forEach((c) => {
    it(`onStatementCompleted (async) works ${c.src}`, async () => {
      // --- Arrange
      let counter = 0;
      const evalContext = createEvalContext({
        localContext: {},
        onStatementCompleted: () => {
          counter++;
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      await processStatementQueueAsync(statements, evalContext);

      // --- Assert
      expect(counter).equal(c.exp);
    });
  });

  stmtCases.forEach((c) => {
    it(`onStatementCompleted (sync) works ${c.src}`, () => {
      // --- Arrange
      let counter = 0;
      const evalContext = createEvalContext({
        localContext: {},
        onStatementCompleted: () => {
          counter++;
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      processStatementQueue(statements, evalContext);

      // --- Assert
      expect(counter).equal(c.exp);
    });
  });

  stmtCases.forEach((c) => {
    it(`onStatementStarted&Completed (async) works ${c.src}`, async () => {
      // --- Arrange
      let counter = 0;
      const evalContext = createEvalContext({
        localContext: {},
        onStatementStarted: () => {
          counter++;
        },
        onStatementCompleted: () => {
          counter++;
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      await processStatementQueueAsync(statements, evalContext);

      // --- Assert
      expect(counter).equal(c.exp + c.exp);
    });
  });

  stmtCases.forEach((c) => {
    it(`onStatementStarted&Completed (sync) works ${c.src}`, () => {
      // --- Arrange
      let counter = 0;
      const evalContext = createEvalContext({
        localContext: {},
        onStatementStarted: () => {
          counter++;
        },
        onStatementCompleted: () => {
          counter++;
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      processStatementQueue(statements, evalContext);

      // --- Assert
      expect(counter).equal(c.exp + c.exp);
    });
  });

  const updateAsgnCases = [
    { src: "let x = 0; x = 3", exp: [] },
    { src: "x = 0;", exp: ["x"] },
    { src: "x.a = 0;", exp: ["x"] },
    { src: "x.a = []; x.a[3] = 12", exp: ["x", "x"] },
    { src: "x.a = []; x.a[3] = {}; x.a[3].f = 24", exp: ["x", "x", "x"] },
    { src: "x = 0; y = 0;", exp: ["x", "y"] },
  ];

  updateAsgnCases.forEach((c) => {
    it(`onWillUpdate (async) works ${c.src}`, async () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onWillUpdate: (_scope, index, type) => {
          if (type === "assignment") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      await processStatementQueueAsync(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });

  updateAsgnCases.forEach((c) => {
    it(`onWillUpdate (sync) works ${c.src}`, () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onWillUpdate: (_scope, index, type) => {
          if (type === "assignment") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      processStatementQueue(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });

  updateAsgnCases.forEach((c) => {
    it(`onDidUpdate (async) works ${c.src}`, async () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onDidUpdate: (_scope, index, type) => {
          if (type === "assignment") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      await processStatementQueueAsync(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });

  updateAsgnCases.forEach((c) => {
    it(`onDidUpdate (sync) works ${c.src}`, () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onDidUpdate: (_scope, index, type) => {
          if (type === "assignment") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      processStatementQueue(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });

  const prePostCases = [
    { src: "let x = 0; x++", exp: [] },
    { src: "x = 0; x++", exp: ["x"] },
    { src: "x.a = 0; ++x.a", exp: ["x"] },
    { src: "x.a = []; x.a[3] = 12; --x.a[3]", exp: ["x"] },
    { src: "x.a = []; x.a[3] = {}; x.a[3].f = 24; x.a[3].f--", exp: ["x"] },
    { src: "x = 0; x++; y = 0; --y;", exp: ["x", "y"] },
  ];

  prePostCases.forEach((c) => {
    it(`onWillUpdate (async) works ${c.src}`, async () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onWillUpdate: (_scope, index, type) => {
          if (type === "pre-post") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      await processStatementQueueAsync(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });

  prePostCases.forEach((c) => {
    it(`onWillUpdate (sync) works ${c.src}`, () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onWillUpdate: (_scope, index, type) => {
          if (type === "pre-post") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      processStatementQueue(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });

  prePostCases.forEach((c) => {
    it(`onDidUpdate (async) works ${c.src}`, async () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onDidUpdate: (_scope, index, type) => {
          if (type === "pre-post") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      await processStatementQueueAsync(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });

  prePostCases.forEach((c) => {
    it(`onDidUpdate (sync) works ${c.src}`, () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onDidUpdate: (_scope, index, type) => {
          if (type === "pre-post") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      processStatementQueue(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });

  const funcCallCases = [
    { src: "let x = () => {}; x()", exp: [] },
    { src: "x = () => {}; x()", exp: ["x"] },
    { src: "x.a = () => {}; x.a()", exp: ["x"] },
    { src: "x.a = []; x.a[3] = () => {}; x.a[3]()", exp: ["x"] },
    { src: "x.a = []; x.a[3] = {}; x.a[3].f = () => {}; x.a[3].f()", exp: ["x"] },
    { src: "x = () => {}; x(); y = () => {}; y();", exp: ["x", "y"] },
  ];

  funcCallCases.forEach((c) => {
    it(`onWillUpdate (async) works ${c.src}`, async () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onWillUpdate: (_scope, index, type) => {
          if (type === "function-call") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      await processStatementQueueAsync(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });

  funcCallCases.forEach((c) => {
    it(`onWillUpdate (sync) works ${c.src}`, () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onWillUpdate: (_scope, index, type) => {
          if (type === "function-call") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      processStatementQueue(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });

  funcCallCases.forEach((c) => {
    it(`onDidUpdate (async) works ${c.src}`, async () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onDidUpdate: (_scope, index, type) => {
          if (type === "function-call") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      await processStatementQueueAsync(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });

  funcCallCases.forEach((c) => {
    it(`onDidUpdate (sync) works ${c.src}`, () => {
      // --- Arrange
      let updated: string[] = [];
      const evalContext = createEvalContext({
        localContext: {
          x: {},
          y: {},
        },
        onDidUpdate: (_scope, index, type) => {
          if (type === "function-call") {
            updated.push(index as string);
          }
        },
      });
      const statements = parseStatements(c.src);

      // --- Act
      processStatementQueue(statements, evalContext);

      // --- Assert
      expect(updated).toStrictEqual(c.exp);
    });
  });
});

```

--------------------------------------------------------------------------------
/xmlui/src/components-core/action/APICall.tsx:
--------------------------------------------------------------------------------

```typescript
import toast from "react-hot-toast";
import type { QueryClient, QueryKey } from "@tanstack/react-query";
import { createDraft, finishDraft } from "immer";

import type { AppContextObject } from "../../abstractions/AppContextDefs";
import type { AsyncFunction } from "../../abstractions/FunctionDefs";
import type { ActionExecutionContext, LookupAsyncFnInner } from "../../abstractions/ActionDefs";
import { invalidateQueries } from "../utils/actionUtils";
import { extractParam, shouldKeep } from "../utils/extractParam";
import { randomUUID } from "../utils/misc";
import type { ApiActionOptions, ApiOperationDef } from "../RestApiProxy";
import RestApiProxy from "../RestApiProxy";
import { createAction } from "./actions";

function findQueryKeysToUpdate(updates: string | string[], queryClient: QueryClient) {
  const queryKeysToUpdate: Array<QueryKey> = [];
  if (updates) {
    let updatesArray: Array<string>;
    if (Array.isArray(updates)) {
      updatesArray = updates;
    } else {
      updatesArray = [updates];
    }
    updatesArray.forEach((queryUrl) => {
      queryClient
        .getQueryCache()
        .getAll()
        .forEach((query) => {
          if (query.queryKey[0] === queryUrl) {
            queryKeysToUpdate.push(query.queryKey);
          }
        });
    });
  }
  return queryKeysToUpdate;
}

function prepareOptimisticValue(value: any, clientTxId: string) {
  return {
    ...value,
    id: value.id || clientTxId,
    _optimisticValue: true,
    _initiatorClientTxId: clientTxId,
  };
}

async function prepareOptimisticValuesForQueries(
  queryKeys: Array<QueryKey>,
  queryClient: QueryClient,
  clientTxId: string,
  stateContext: any,
  resolvedOptimisticValue?: any,
  optimisticValueGetter?: AsyncFunction,
) {
  const ret: Map<QueryKey, any> = new Map();

  await Promise.all(
    queryKeys.map(async (queryKey) => {
      if (resolvedOptimisticValue) {
        ret.set(queryKey, prepareOptimisticValue(resolvedOptimisticValue, clientTxId));
        return;
      }
      if (!optimisticValueGetter) {
        return;
      }
      const currentData = queryClient.getQueryData(queryKey) as any;
      const flatData = currentData?.pages
        ? currentData.pages.flatMap((page: any) => page)
        : currentData;
      const optimisticValue = await optimisticValueGetter(flatData, stateContext["$param"]);
      if (optimisticValue) {
        ret.set(queryKey, prepareOptimisticValue(optimisticValue, clientTxId));
      }
    }),
  );

  return ret;
}

async function doOptimisticUpdate(
  optimisticValuesByQueryKeys: Map<QueryKey, any>,
  queryClient: QueryClient,
) {
  if (!optimisticValuesByQueryKeys.size) {
    return;
  }
  for (const entry of optimisticValuesByQueryKeys.entries()) {
    const [key, optimisticValue] = entry;
    await queryClient.cancelQueries({ queryKey: key });
    const oldData = queryClient.getQueryData(key) as any;

    const draft = createDraft(oldData as any);
    if (draft.pages) {
      let updated = false;
      draft.pages.forEach((page: any) => {
        page.forEach((item: any) => {
          if (item.id === optimisticValue.id) {
            Object.assign(item, optimisticValue);
            updated = true;
          }
        });
      });
      if (!updated) {
        draft.pages[draft.pages.length - 1].push(optimisticValue);
      }
    } else {
      let updated = false;
      draft.forEach((item: any) => {
        if (item.id === optimisticValue.id) {
          Object.assign(item, optimisticValue);
          updated = true;
        }
      });
      if (!updated) {
        draft.push(optimisticValue);
      }
    }
    const newData = finishDraft(draft);
    queryClient.setQueryData(key, newData);
    // console.log("optimistic added", { finalOptimisticValue, newData });
  }
}

function updateQueriesWithResult(
  queryKeysToUpdate: Array<QueryKey>,
  optimisticValuesByQueryKeys: Map<QueryKey, any>,
  clientTxId: string,
  queryClient: QueryClient,
  result: any,
) {
  if (!queryKeysToUpdate.length) {
    return;
  }
  queryKeysToUpdate.forEach((key) => {
    const oldData = queryClient.getQueryData(key) as any;
    const draft = createDraft(oldData as any);
    const optimisticValue = optimisticValuesByQueryKeys.get(key);
    if (draft.pages) {
      //pageable loader
      if (optimisticValue) {
        draft.pages[draft.pages.length - 1] = draft.pages[draft.pages.length - 1].map(
          (item: any) =>
            item.id === optimisticValue.id && item._initiatorClientTxId === clientTxId
              ? result || {
              ...item,
              _optimisticValue: undefined,
              _initiatorClientTxId: undefined,
            }
              : item,
        );
      } else {
        let updated = false;
        draft.pages.forEach((page: any) => {
          page?.forEach((item: any) => {
            if (item.id === result?.id) {
              Object.assign(item, result);
              updated = true;
            }
          });
        });
        if (!updated && result) {
          draft.pages[draft.pages.length - 1].push(result);
        }
      }
    } else {
      if (optimisticValue) {
        draft.forEach((item: any, index: number) => {
          if (item.id === optimisticValue.id && item._initiatorClientTxId === clientTxId) {
            draft[index] = result || {
              ...item,
              _optimisticValue: undefined,
              _initiatorClientTxId: undefined,
            };
          }
        });
      } else {
        let updated = false;
        draft.forEach((item: any, index: number) => {
          if (item.id === result.id) {
            draft[index] = result || {
              ...item,
              _optimisticValue: undefined,
              _initiatorClientTxId: undefined,
            };
            updated = true;
          }
        });
        if (!updated && result) {
          draft.push(result);
        }
      }
    }
    const newData = finishDraft(draft);
    queryClient.setQueryData(key, newData);
  });
}

async function updateQueriesWithOptimisticValue({
                                                  stateContext,
                                                  updates,
                                                  appContext,
                                                  queryClient,
                                                  clientTxId,
                                                  optimisticValue,
                                                  lookupAction,
                                                  getOptimisticValue,
                                                  uid,
                                                }: {
  stateContext: any;
  updates: string | string[] | undefined;
  appContext: AppContextObject;
  queryClient: QueryClient;
  clientTxId: string;
  optimisticValue: any;
  lookupAction: LookupAsyncFnInner;
  getOptimisticValue?: string;
  uid: symbol;
}) {
  const queryKeysToUpdate = findQueryKeysToUpdate(
    extractParam(stateContext, updates, appContext),
    queryClient,
  );
  const optimisticValuesByQueryKeys = await prepareOptimisticValuesForQueries(
    queryKeysToUpdate,
    queryClient,
    clientTxId,
    stateContext,
    extractParam(stateContext, optimisticValue, appContext),
    lookupAction(getOptimisticValue, uid),
  );

  await doOptimisticUpdate(optimisticValuesByQueryKeys, queryClient);
  return { queryKeysToUpdate, optimisticValuesByQueryKeys };
}

type APICall = {
  invalidates?: string | string[];
  updates?: string | string[];
  confirmTitle?: string;
  confirmMessage?: string;
  confirmButtonLabel?: string;
  params?: any;
  payloadType?: string;
  optimisticValue?: any;
  getOptimisticValue?: string;
  inProgressNotificationMessage?: string;
  completedNotificationMessage?: string;
  errorNotificationMessage?: string;

  uid?: string | symbol;
  when?: string;

  onBeforeRequest?: string;
  onSuccess?: string;
  onProgress?: string;
  onError?: string;
} & ApiOperationDef;

export async function callApi(
  { state, appContext, lookupAction, getCurrentState, apiInstance }: ActionExecutionContext,
  {
    confirmTitle,
    confirmMessage,
    confirmButtonLabel,
    params = {},
    onBeforeRequest,
    onSuccess,
    onError,
    invalidates,
    updates,
    optimisticValue,
    payloadType,
    when,
    getOptimisticValue,
    inProgressNotificationMessage,
    completedNotificationMessage,
    errorNotificationMessage,
    uid: actionUid,
    onProgress,

    //operation
    headers,
    url,
    queryParams,
    rawBody,
    method,
    body,
  }: APICall,
  { resolveBindingExpressions }: ApiActionOptions = {},
) {
  const uid = typeof actionUid === "symbol" ? actionUid : Symbol(actionUid);
  const stateContext = { ...state, ...params };
  if (!shouldKeep(when, stateContext, appContext)) {
    return;
  }
  if (confirmTitle || confirmMessage || confirmButtonLabel) {
    const title = extractParam(stateContext, confirmTitle, appContext);
    const message = extractParam(stateContext, confirmMessage, appContext);
    const buttonLabel = extractParam(stateContext, confirmButtonLabel, appContext);
    const dialogCheck = await appContext.confirm(
      title ?? "Confirm Operation",
      message ?? "Are you sure you want to perform this operation?",
      buttonLabel ?? "Yes",
    );
    if (!dialogCheck) return;
  }
  const resolvedInvalidates = extractParam(stateContext, invalidates, appContext);

  const clientTxId = randomUUID();
  const beforeRequestFn = lookupAction(onBeforeRequest, uid);
  const beforeRequestResult = await beforeRequestFn?.();
  if (typeof beforeRequestResult === "boolean" && beforeRequestResult === false) {
    return;
  }

  const { queryKeysToUpdate, optimisticValuesByQueryKeys } = await updateQueriesWithOptimisticValue(
    {
      stateContext,
      updates,
      appContext,
      queryClient: appContext.queryClient!,
      clientTxId,
      optimisticValue,
      lookupAction,
      getOptimisticValue,
      uid,
    },
  );

  const inProgressMessage = extractParam(stateContext, inProgressNotificationMessage, appContext);

  let loadingToastId;
  if (inProgressMessage) {
    loadingToastId = toast.loading(inProgressMessage);
  }
  try {
    const operation: ApiOperationDef = {
      headers,
      url,
      queryParams,
      rawBody,
      method,
      body,
      payloadType,
    };
    const _onProgress = lookupAction(onProgress, uid, {
      eventName: "progress",
    });
    const result = await new RestApiProxy(appContext, apiInstance).execute({
      operation,
      params: stateContext,
      transactionId: clientTxId,
      resolveBindingExpressions,
      onProgress: _onProgress,
    });

    const onSuccessFn = lookupAction(onSuccess, uid, {
      eventName: "success",
      context: getCurrentState()
    });
    await onSuccessFn?.(result, stateContext["$param"]);

    updateQueriesWithResult(
      queryKeysToUpdate,
      optimisticValuesByQueryKeys,
      clientTxId,
      appContext.queryClient!,
      result,
    );

    if (resolvedInvalidates || !updates) {
      await invalidateQueries(resolvedInvalidates, appContext, state);
    }
    const completedMessage = extractParam(
      { ...stateContext, $result: result },
      completedNotificationMessage,
      appContext,
    );
    if (completedMessage) {
      toast.success(completedMessage, {
        id: loadingToastId,
      });
    } else if (loadingToastId) {
      toast.dismiss(loadingToastId);
    }
    return result;
  } catch (e) {
    if (optimisticValuesByQueryKeys.size) {
      await appContext.queryClient!.invalidateQueries();
    }
    const onErrorFn = lookupAction(onError, uid, {
      eventName: "error",
    });
    const result = await onErrorFn?.(e, stateContext["$param"]);
    const errorMessage = extractParam(
      { ...stateContext, $error: e },
      errorNotificationMessage,
      appContext,
    );
    if (errorMessage) {
      toast.error(errorMessage, {
        id: loadingToastId,
      });
    } else {
      if (loadingToastId) {
        toast.dismiss(loadingToastId);
      }
      if (result !== false) {
        //stop the error propagation, if the error handler returns false
        throw e;
      }
    }
  }
}

export const apiAction = createAction("callApi", callApi);

```

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

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

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

test.describe("Basic Functionality", () => {
  test("renders children content in default slot", async ({ initTestBed, page }) => {
    await initTestBed(`
      <Custom>
        <Button label="Create" />
        <Button label="Edit" />
        <Button label="Delete" />
      </Custom>
    `, {
      components: [
        `
        <Component name="Custom">
          <Card>
            <H3>Use these actions</H3>
            <HStack>
              <Slot />
            </HStack>
          </Card>
        </Component>
        `
      ]
    });

    // Verify all passed children are rendered in the slot
    await expect(page.getByRole("button", { name: "Create" })).toBeVisible();
    await expect(page.getByRole("button", { name: "Edit" })).toBeVisible();
    await expect(page.getByRole("button", { name: "Delete" })).toBeVisible();
    
    // Verify they are within the card structure from the component
    await expect(page.getByText("Use these actions")).toBeVisible();
  });

  test("renders default content when no children provided", async ({ initTestBed, page }) => {
    await initTestBed(`<ActionBar />`, {
      components: [
        `
        <Component name="ActionBar">
          <Card>
            <H3>Use these actions</H3>
            <HStack>
              <Slot>
                <Button label="Default" />
              </Slot>
            </HStack>
          </Card>
        </Component>
        `
      ]
    });

    // Verify default content is rendered when no children provided
    await expect(page.getByRole("button", { name: "Default" })).toBeVisible();
    await expect(page.getByText("Use these actions")).toBeVisible();
  });

  test("overrides default content with provided children", async ({ initTestBed, page }) => {
    await initTestBed(`
      <ActionBar>
        <Button label="Custom Button" />
      </ActionBar>
    `, {
      components: [
        `
        <Component name="ActionBar">
          <Card>
            <H3>Use these actions</H3>
            <HStack>
              <Slot>
                <Button label="Default" />
              </Slot>
            </HStack>
          </Card>
        </Component>
        `
      ]
    });

    // Verify provided children override default content
    await expect(page.getByRole("button", { name: "Custom Button" })).toBeVisible();
    await expect(page.getByRole("button", { name: "Default" })).not.toBeVisible();
  });

  test("works with named slots using property template syntax", async ({ initTestBed, page }) => {
    await initTestBed(`
      <ActionBar>
        <property name="headerTemplate">
          <H2>Click one of these actions</H2>
        </property>
        <property name="footerTemplate">
          <Text>Footer content goes here</Text>
        </property>
        <Button label="Create" />
        <Button label="Edit" />
        <Button label="Delete" />
      </ActionBar>
    `, {
      components: [
        `
        <Component name="ActionBar">
          <Card>
            <Slot name="headerTemplate">
              <H3>Use these actions</H3>
            </Slot>
            <HStack>
              <Slot>
                <Button label="Default" />
              </Slot>
            </HStack>
            <Slot name="footerTemplate" />
          </Card>
        </Component>
        `
      ]
    });

    // Verify named slots render their provided content
    await expect(page.getByRole("heading", { name: "Click one of these actions" })).toBeVisible();
    await expect(page.getByText("Footer content goes here")).toBeVisible();
    
    // Verify default header is not shown (overridden by headerTemplate)
    await expect(page.getByRole("heading", { name: "Use these actions" })).not.toBeVisible();
    
    // Verify default slot content (buttons)
    await expect(page.getByRole("button", { name: "Create" })).toBeVisible();
    await expect(page.getByRole("button", { name: "Edit" })).toBeVisible();
    await expect(page.getByRole("button", { name: "Delete" })).toBeVisible();
  });

  test("renders default content for named slots when no template provided", async ({ initTestBed, page }) => {
    await initTestBed(`
      <ActionBar>
        <Button label="Main Button" />
      </ActionBar>
    `, {
      components: [
        `
        <Component name="ActionBar">
          <Card>
            <Slot name="headerTemplate">
              <H3>Default header</H3>
            </Slot>
            <HStack>
              <Slot />
            </HStack>
            <Slot name="footerTemplate">
              <Text>Default footer</Text>
            </Slot>
          </Card>
        </Component>
        `
      ]
    });

    // Verify default content for named slots is rendered
    await expect(page.getByRole("heading", { name: "Default header" })).toBeVisible();
    await expect(page.getByText("Default footer")).toBeVisible();
    
    // Verify main slot content
    await expect(page.getByRole("button", { name: "Main Button" })).toBeVisible();
  });

  test("supports template properties with context variables", async ({ initTestBed, page }) => {
    await initTestBed(`
      <ActionBar header="Action Bar Example">
        <property name="headerTemplate">
          <Text variant="title">{$processedHeader}</Text>
        </property>
        <Button label="Create" />
        <Button label="Edit" />
        <Button label="Delete" />
      </ActionBar>
    `, {
      components: [
        `
        <Component name="ActionBar">
          <Card var.transformedHeader="*** {$props.header.toUpperCase()} ***">
            <Slot name="headerTemplate" processedHeader="{transformedHeader}">
              <H3>{transformedHeader}</H3>
            </Slot>
            <HStack>
              <Slot>
                <Button label="Default" />
              </Slot>
            </HStack>
          </Card>
        </Component>
        `
      ]
    });

    // Verify template property is processed and passed to slot template
    await expect(page.getByText("*** ACTION BAR EXAMPLE ***")).toBeVisible();
    
    // Verify main slot content
    await expect(page.getByRole("button", { name: "Create" })).toBeVisible();
    await expect(page.getByRole("button", { name: "Edit" })).toBeVisible();
    await expect(page.getByRole("button", { name: "Delete" })).toBeVisible();
  });

  test("works with multiple context variables in template properties", async ({ initTestBed, page }) => {
    await initTestBed(`
      <DataDisplay>
        <property name="contentTemplate">
          <Text>{$title}: {$value}</Text>
        </property>
      </DataDisplay>
    `, {
      components: [
        `
        <Component name="DataDisplay">
          <Slot name="contentTemplate" title="Score" value="{42}">
            <Text>No data available</Text>
          </Slot>
        </Component>
        `
      ]
    });

    // Verify multiple context variables work
    await expect(page.getByText("Score: 42")).toBeVisible();
    await expect(page.getByText("No data available")).not.toBeVisible();
  });

  test("supports complex nested content in slots", async ({ initTestBed, page }) => {
    await initTestBed(`
      <CustomCard>
        <property name="headerTemplate">
          <HStack>
            <Icon name="star" />
            <Text fontWeight="bold">Custom Header</Text>
          </HStack>
        </property>
        <VStack>
          <Text>Line 1</Text>
          <Text>Line 2</Text>
          <Button label="Action" />
        </VStack>
      </CustomCard>
    `, {
      components: [
        `
        <Component name="CustomCard">
          <Card>
            <Slot name="headerTemplate">
              <H3>Default Header</H3>
            </Slot>
            <ContentSeparator />
            <Slot />
          </Card>
        </Component>
        `
      ]
    });

    // Verify complex nested content renders correctly
    await expect(page.getByText("Custom Header")).toBeVisible();
    await expect(page.getByText("Line 1")).toBeVisible();
    await expect(page.getByText("Line 2")).toBeVisible();
    await expect(page.getByRole("button", { name: "Action" })).toBeVisible();
    
    // Verify default header is not shown
    await expect(page.getByRole("heading", { name: "Default Header" })).not.toBeVisible();
  });

  test("maintains proper rendering order with multiple slots", async ({ initTestBed, page }) => {
    await initTestBed(`
      <MultiSlotComponent>
        <property name="topTemplate">
          <Text testId="top">Top Content</Text>
        </property>
        <property name="bottomTemplate">
          <Text testId="bottom">Bottom Content</Text>
        </property>
        <Text testId="middle">Middle Content</Text>
      </MultiSlotComponent>
    `, {
      components: [
        `
        <Component name="MultiSlotComponent">
          <VStack>
            <Slot name="topTemplate" />
            <Slot />
            <Slot name="bottomTemplate" />
          </VStack>
        </Component>
        `
      ]
    });

    // Verify all content is rendered
    await expect(page.getByTestId("top")).toBeVisible();
    await expect(page.getByTestId("middle")).toBeVisible();
    await expect(page.getByTestId("bottom")).toBeVisible();
    
    // Verify rendering order by checking positions
    const topElement = page.getByTestId("top");
    const middleElement = page.getByTestId("middle");
    const bottomElement = page.getByTestId("bottom");
    
    const topBox = await topElement.boundingBox();
    const middleBox = await middleElement.boundingBox();
    const bottomBox = await bottomElement.boundingBox();
    
    expect(topBox?.y).toBeLessThan(middleBox?.y || 0);
    expect(middleBox?.y).toBeLessThan(bottomBox?.y || 0);
  });

  test("works with dynamic context in template properties", async ({ initTestBed, page }) => {
    await initTestBed(`
      <ContextComponent>
        <property name="messageTemplate">
          <Text>{$message}</Text>
        </property>
      </ContextComponent>
    `, {
      components: [
        `
        <Component name="ContextComponent" var.currentMessage="Initial Message">
          <VStack>
            <Button label="Update Message" onClick="currentMessage = 'Updated Message'" />
            <Slot name="messageTemplate" message="{currentMessage}">
              <Text>No message</Text>
            </Slot>
          </VStack>
        </Component>
        `
      ]
    });

    // Verify initial context value
    await expect(page.getByText("Initial Message")).toBeVisible();
    
    // Update the context and verify template updates
    await page.getByRole("button", { name: "Update Message" }).click();
    await expect(page.getByText("Updated Message")).toBeVisible();
    await expect(page.getByText("Initial Message")).not.toBeVisible();
  });

  test("handles empty slots gracefully", async ({ initTestBed, page }) => {
    await initTestBed(`
      <EmptySlotComponent>
      </EmptySlotComponent>
    `, {
      components: [
        `
        <Component name="EmptySlotComponent">
          <Card>
            <Text>Before slot</Text>
            <Slot />
            <Text>After slot</Text>
          </Card>
        </Component>
        `
      ]
    });

    // Verify component renders without errors when slot is empty
    await expect(page.getByText("Before slot")).toBeVisible();
    await expect(page.getByText("After slot")).toBeVisible();
  });

  test("supports slot with no default content", async ({ initTestBed, page }) => {
    await initTestBed(`
      <MinimalComponent>
        <Text>Provided content</Text>
      </MinimalComponent>
    `, {
      components: [
        `
        <Component name="MinimalComponent">
          <VStack>
            <Text>Component content</Text>
            <Slot name="contentTemplate" />
            <Slot />
          </VStack>
        </Component>
        `
      ]
    });

    // Verify provided content renders in default slot
    await expect(page.getByText("Provided content")).toBeVisible();
    
    // Verify component structure renders without errors
    await expect(page.getByText("Component content")).toBeVisible();
  });
});

```
Page 44/143FirstPrevNextLast