#
tokens: 48677/50000 7/1630 files (page 51/186)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 51 of 186. Use http://codebase.md/xmlui-org/xmlui/xmlui/mockApiDef.js?lines=true&page={x} to view the full context.

# Directory Structure

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

# Files

--------------------------------------------------------------------------------
/xmlui/src/components/NavPanel/NavPanelNative.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import React, { forwardRef, type ReactNode, useEffect } from "react";
  2 | import classnames from "classnames";
  3 | 
  4 | import styles from "./NavPanel.module.scss";
  5 | 
  6 | import type { RenderChildFn } from "../../abstractions/RendererDefs";
  7 | import { Logo } from "../Logo/LogoNative";
  8 | import { useAppLayoutContext } from "../App/AppLayoutContext";
  9 | import { getAppLayoutOrientation } from "../App/AppNative";
 10 | import { useLinkInfoContext } from "../App/LinkInfoContext";
 11 | 
 12 | // Define navigation hierarchy node structure
 13 | export interface NavHierarchyNode {
 14 |   /** The type of navigation node - either a clickable link or a grouping container */
 15 |   type: "NavLink" | "NavGroup";
 16 | 
 17 |   /** The display label/text for this navigation item */
 18 |   label: string;
 19 | 
 20 |   /** The URL/route path for navigation (only present for NavLink types) */
 21 |   to?: string;
 22 | 
 23 |   /** Child navigation nodes nested under this node (only present for NavGroup types) */
 24 |   children?: NavHierarchyNode[];
 25 | 
 26 |   /** Reference to the immediate parent node in the hierarchy (undefined for root-level nodes) */
 27 |   parent?: NavHierarchyNode;
 28 | 
 29 |   /** Array of ancestor nodes from root to this node, excluding this node itself (empty for root-level nodes) */
 30 |   pathSegments?: NavHierarchyNode[];
 31 | 
 32 |   /** Reference to the previous NavLink in the flattened navigation order */
 33 |   prevLink?: NavHierarchyNode;
 34 | 
 35 |   /** Reference to the next NavLink in the flattened navigation order */
 36 |   nextLink?: NavHierarchyNode;
 37 | 
 38 |   /** True if this is the first NavLink within its immediate parent container */
 39 |   firstLink?: boolean;
 40 | 
 41 |   /** True if this is the last NavLink within its immediate parent container */
 42 |   lastLink?: boolean;
 43 | }
 44 | 
 45 | // Function to build navigation hierarchy from component children
 46 | export function buildNavHierarchy(
 47 |   children: any[] | undefined,
 48 |   extractValue: any,
 49 |   parent?: NavHierarchyNode,
 50 |   pathSegments: NavHierarchyNode[] = [],
 51 | ): NavHierarchyNode[] {
 52 |   if (!children) return [];
 53 | 
 54 |   const hierarchy: NavHierarchyNode[] = [];
 55 | 
 56 |   // Skip non-object children
 57 |   children
 58 |     .filter((child) => child && typeof child === "object")
 59 |     .forEach((child) => {
 60 |       if (child.type === "NavLink") {
 61 |         const label =
 62 |           extractValue.asOptionalString?.(child.props?.label) || extractValue(child.props?.label);
 63 |         const to =
 64 |           extractValue.asOptionalString?.(child.props?.to) || extractValue(child.props?.to);
 65 | 
 66 |         // Handle case where label might not be in props but in children as text
 67 |         let finalLabel = label;
 68 |         if (!finalLabel && child.children?.length === 1 && child.children[0].type === "TextNode") {
 69 |           finalLabel = extractValue(child.children[0].props?.value);
 70 |         }
 71 | 
 72 |         // Only include NavLinks that have both label and to values
 73 |         if (finalLabel && to) {
 74 |           const node: NavHierarchyNode = {
 75 |             type: "NavLink",
 76 |             label: finalLabel,
 77 |             to: to,
 78 |             parent: parent,
 79 |             pathSegments: [...pathSegments],
 80 |           };
 81 |           hierarchy.push(node);
 82 |         }
 83 |       } else if (child.type === "NavGroup") {
 84 |         const label =
 85 |           extractValue.asOptionalString?.(child.props?.label) || extractValue(child.props?.label);
 86 | 
 87 |         // NavGroups only need a label, no "to" value required
 88 |         if (label) {
 89 |           const groupNode: NavHierarchyNode = {
 90 |             type: "NavGroup",
 91 |             label: label,
 92 |             parent: parent,
 93 |             pathSegments: [...pathSegments],
 94 |             children: [],
 95 |           };
 96 | 
 97 |           // Build children with this groupNode as parent and updated path
 98 |           const newPathSegments = [...pathSegments, groupNode];
 99 |           groupNode.children = buildNavHierarchy(
100 |             child.children,
101 |             extractValue,
102 |             groupNode,
103 |             newPathSegments,
104 |           );
105 |           hierarchy.push(groupNode);
106 |         } else if (child.children && child.children.length > 0) {
107 |           // If no label but has children, process them at the current level with same parent and path
108 |           hierarchy.push(...buildNavHierarchy(child.children, extractValue, parent, pathSegments));
109 |         }
110 |       } else if (child.children && child.children.length > 0) {
111 |         //console.log("CN", child.children);
112 |         // Process any children that might contain NavGroup and NavLink components recursively
113 |         const nestedNodes = buildNavHierarchy(child.children, extractValue, parent, pathSegments);
114 |         if (nestedNodes.length > 0) {
115 |           hierarchy.push(...nestedNodes);
116 |         }
117 |       }
118 |     });
119 | 
120 |   // Set navigation properties after building the hierarchy
121 |   setNavigationProperties(hierarchy);
122 |   return hierarchy;
123 | }
124 | 
125 | // Helper function to set navigation properties (prevLink, nextLink, firstLink, lastLink)
126 | function setNavigationProperties(hierarchy: NavHierarchyNode[]) {
127 |   // Collect all NavLinks in traversal order
128 |   const allNavLinks: NavHierarchyNode[] = [];
129 | 
130 |   function collectNavLinks(nodes: NavHierarchyNode[]) {
131 |     nodes.forEach((node) => {
132 |       if (node.type === "NavLink") {
133 |         allNavLinks.push(node);
134 |       }
135 |       if (node.children) {
136 |         collectNavLinks(node.children);
137 |       }
138 |     });
139 |   }
140 | 
141 |   collectNavLinks(hierarchy);
142 | 
143 |   // Set prevLink and nextLink for all NavLinks
144 |   allNavLinks.forEach((link, index) => {
145 |     if (index > 0) {
146 |       link.prevLink = allNavLinks[index - 1];
147 |     }
148 |     if (index < allNavLinks.length - 1) {
149 |       link.nextLink = allNavLinks[index + 1];
150 |     }
151 |   });
152 | 
153 |   // Set firstLink and lastLink properties
154 |   function setFirstLastProperties(nodes: NavHierarchyNode[]) {
155 |     const navLinks = nodes.filter((node) => node.type === "NavLink");
156 | 
157 |     if (navLinks.length > 0) {
158 |       navLinks[0].firstLink = true;
159 |       navLinks[navLinks.length - 1].lastLink = true;
160 |     }
161 | 
162 |     // Recursively process children
163 |     nodes.forEach((node) => {
164 |       if (node.children) {
165 |         setFirstLastProperties(node.children);
166 |       }
167 |     });
168 |   }
169 | 
170 |   setFirstLastProperties(hierarchy);
171 | }
172 | 
173 | // Function to build a map of NavLinks by their "to" property
174 | export function buildLinkMap(
175 |   navLinks: NavHierarchyNode[] | undefined,
176 | ): Map<string, NavHierarchyNode> {
177 |   const linkMap = new Map<string, NavHierarchyNode>();
178 | 
179 |   if (!navLinks) return linkMap;
180 | 
181 |   function processNodes(nodes: NavHierarchyNode[]) {
182 |     nodes.forEach((node) => {
183 |       if (node.type === "NavLink" && node.to) {
184 |         // If multiple items use the same "to" value, the last wins
185 |         linkMap.set(node.to, node);
186 |       }
187 |       if (node.children) {
188 |         processNodes(node.children);
189 |       }
190 |     });
191 |   }
192 | 
193 |   processNodes(navLinks);
194 |   return linkMap;
195 | }
196 | 
197 | // Default props for NavPanel component
198 | export const defaultProps = {
199 |   inDrawer: false,
200 | };
201 | 
202 | interface INavPanelContext {
203 |   inDrawer: boolean;
204 | }
205 | 
206 | export const NavPanelContext = React.createContext<INavPanelContext | null>(null);
207 | 
208 | const contextValue = {
209 |   inDrawer: true,
210 | };
211 | 
212 | function DrawerNavPanel({
213 |   logoContent,
214 |   children,
215 |   className,
216 |   style,
217 |   ...rest
218 | }: {
219 |   children: ReactNode;
220 |   className?: string;
221 |   style?: React.CSSProperties;
222 |   logoContent?: ReactNode;
223 | }) {
224 |   return (
225 |     <NavPanelContext.Provider value={contextValue}>
226 |       <div {...rest} className={classnames(styles.wrapper, className)} style={style}>
227 |         <div className={classnames(styles.logoWrapper, styles.inDrawer)}>
228 |           {logoContent || <Logo />}
229 |         </div>
230 |         <div className={styles.wrapperInner} style={style}>
231 |           {children}
232 |         </div>
233 |       </div>
234 |     </NavPanelContext.Provider>
235 |   );
236 | }
237 | 
238 | type Props = {
239 |   children: ReactNode;
240 |   className?: string;
241 |   style?: React.CSSProperties;
242 |   logoContent?: ReactNode;
243 |   inDrawer?: boolean;
244 |   renderChild: RenderChildFn;
245 |   navLinks?: NavHierarchyNode[];
246 | };
247 | 
248 | export const NavPanel = forwardRef(function NavPanel(
249 |   {
250 |     children,
251 |     style,
252 |     logoContent,
253 |     className,
254 |     inDrawer = defaultProps.inDrawer,
255 |     renderChild,
256 |     navLinks,
257 |     ...rest
258 |   }: Props,
259 |   forwardedRef: React.ForwardedRef<any>,
260 | ) {
261 |   const appLayoutContext = useAppLayoutContext();
262 |   const linkInfoContext = useLinkInfoContext();
263 |   const horizontal = getAppLayoutOrientation(appLayoutContext?.layout) === "horizontal";
264 |   const showLogo =
265 |     appLayoutContext?.layout === "vertical" || appLayoutContext?.layout === "vertical-sticky";
266 |   const isCondensed = appLayoutContext?.layout?.startsWith("condensed");
267 |   const vertical = appLayoutContext?.layout?.startsWith("vertical");
268 |   const safeLogoContent = logoContent || renderChild(appLayoutContext?.logoContentDef);
269 | 
270 |   // Register the linkMap when navLinks change
271 |   const registerLinkMap = linkInfoContext?.registerLinkMap;
272 |   useEffect(() => {
273 |     if (registerLinkMap && navLinks) {
274 |       const linkMap = buildLinkMap(navLinks);
275 |       registerLinkMap(linkMap);
276 |     }
277 |   }, [navLinks, registerLinkMap]);
278 | 
279 |   if (inDrawer) {
280 |     return (
281 |       <DrawerNavPanel {...rest} style={style} logoContent={safeLogoContent} className={className}>
282 |         {children}
283 |       </DrawerNavPanel>
284 |     );
285 |   }
286 | 
287 |   return (
288 |     <div
289 |       {...rest}
290 |       ref={forwardedRef}
291 |       className={classnames(styles.wrapper, className, {
292 |         [styles.horizontal]: horizontal,
293 |         [styles.vertical]: vertical,
294 |         [styles.condensed]: isCondensed,
295 |       })}
296 |       style={style}
297 |     >
298 |       {showLogo && (
299 |         <div className={classnames(styles.logoWrapper)}>{safeLogoContent || <Logo />}</div>
300 |       )}
301 |       <div className={styles.wrapperInner} style={style}>
302 |         {children}
303 |       </div>
304 |     </div>
305 |   );
306 | });
307 | 
```

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

```typescript
  1 | import styles from "./Text.module.scss";
  2 | 
  3 | import { createComponentRenderer } from "../../components-core/renderers";
  4 | import { parseScssVar } from "../../components-core/theming/themeVars";
  5 | import {
  6 |   variantOptionsMd,
  7 |   type VariantProps,
  8 |   VariantPropsKeys,
  9 |   type OverflowMode,
 10 |   type BreakMode,
 11 | } from "../abstractions";
 12 | import { Text, defaultProps } from "./TextNative";
 13 | import { createMetadata, d } from "../metadata-helpers";
 14 | 
 15 | const COMP = "Text";
 16 | 
 17 | export const TextMd = createMetadata({
 18 |   status: "stable",
 19 |   description:
 20 |     `The \`${COMP}\` component displays textual information in a number of optional ` +
 21 |     `styles and variants.`,
 22 |   props: {
 23 |     value: d(
 24 |       `The text to be displayed. This value can also be set via nesting the text into ` +
 25 |         `the \`${COMP}\` component.`,
 26 |     ),
 27 |     variant: {
 28 |       description:
 29 |         "An optional string value that provides named presets for text variants with a " +
 30 |         "unique combination of font style, weight, size, color, and other parameters. " +
 31 |         "If not defined, the text uses the current style of its context. " +
 32 |         "In addition to predefined variants, you can specify custom variant names and style them " +
 33 |         "using theme variables with the pattern `{cssProperty}-Text-{variantName}` " +
 34 |         "(e.g., `textColor-Text-brandTitle`, `fontSize-Text-highlight`). " +
 35 |         "See the documentation for a complete list of supported CSS properties.",
 36 |       availableValues: variantOptionsMd,
 37 |     },
 38 |     maxLines: d(
 39 |       "This property determines the maximum number of lines the component can wrap to. " +
 40 |         "If there is no space to display all the contents, the component displays up to as " +
 41 |         "many lines as specified in this property. When the value is not defined, there is " +
 42 |         "no limit on the displayed lines.",
 43 |     ),
 44 |     preserveLinebreaks: {
 45 |       description: `This property indicates if linebreaks should be preserved when displaying text.`,
 46 |       valueType: "boolean",
 47 |       defaultValue: defaultProps.preserveLinebreaks,
 48 |     },
 49 |     ellipses: {
 50 |       description:
 51 |         "This property indicates whether ellipses should be displayed when the text is " +
 52 |         "cropped (\`true\`) or not (\`false\`).",
 53 |       valueType: "boolean",
 54 |       defaultValue: defaultProps.ellipses,
 55 |     },
 56 |     breakMode: {
 57 |       description:
 58 |         "This property controls how text breaks into multiple lines. " +
 59 |         "`normal` uses standard word boundaries, `word` breaks long words to prevent overflow, " +
 60 |         "`anywhere` breaks at any character, `keep` prevents word breaking, " +
 61 |         "and `hyphenate` uses automatic hyphenation. When not specified, uses the default browser behavior or theme variables.",
 62 |       valueType: "string",
 63 |       defaultValue: "normal",
 64 |       availableValues: [
 65 |         { value: "normal", description: "Uses standard word boundaries for breaking" },
 66 |         { value: "word", description: "Breaks long words when necessary to prevent overflow" },
 67 |         { value: "anywhere", description: "Breaks at any character if needed to fit content" },
 68 |         { value: "keep", description: "Prevents breaking within words entirely" },
 69 |         { value: "hyphenate", description: "Uses automatic hyphenation when breaking words" },
 70 |       ],
 71 |     },
 72 |     overflowMode: {
 73 |       description:
 74 |         "This property controls how text overflow is handled. " +
 75 |         "`none` prevents wrapping and shows no overflow indicator, " +
 76 |         "`ellipsis` shows ellipses when text is truncated, `scroll` forces single line with horizontal scrolling, " +
 77 |         "and `flow` allows multi-line wrapping with vertical scrolling when needed (ignores maxLines). " +
 78 |         "When not specified, uses the default text behavior.",
 79 |       valueType: "string",
 80 |       defaultValue: "not specified",
 81 |       availableValues: [
 82 |         {
 83 |           value: "none",
 84 |           description: "No wrapping, text stays on a single line with no overflow indicator",
 85 |         },
 86 |         { value: "ellipsis", description: "Truncates with an ellipsis (default)" },
 87 |         {
 88 |           value: "scroll",
 89 |           description: "Forces single line with horizontal scrolling when content overflows",
 90 |         },
 91 |         {
 92 |           value: "flow",
 93 |           description:
 94 |             "Allows text to wrap into multiple lines with vertical scrolling when container height is constrained (ignores maxLines)",
 95 |         },
 96 |       ],
 97 |     },
 98 |   },
 99 |   apis: {
100 |     hasOverflow: {
101 |       description: "Returns true when the displayed text overflows its container boundaries.",
102 |       signature: "hasOverflow(): boolean",
103 |     },
104 |   },
105 |   themeVars: parseScssVar(styles.themeVars),
106 |   defaultThemeVars: {
107 |     [`borderRadius-${COMP}`]: "$borderRadius",
108 |     [`borderStyle-${COMP}`]: "solid",
109 |     [`fontSize-${COMP}`]: "$fontSize-sm",
110 |     [`borderWidth-${COMP}`]: "$space-0",
111 |     [`textColor-${COMP}`]: "$textColor-primary",
112 |     [`fontFamily-${COMP}`]: "$fontFamily",
113 |     [`fontWeight-${COMP}`]: "$fontWeight-normal",
114 | 
115 |     [`fontSize-${COMP}-secondary`]: "$fontSize-sm",
116 |     [`textColor-${COMP}-secondary`]: "$textColor-secondary",
117 | 
118 |     [`fontWeight-${COMP}-abbr`]: "$fontWeight-bold",
119 |     [`textTransform-${COMP}-abbr`]: "uppercase",
120 |     [`fontStyle-${COMP}-cite`]: "italic",
121 | 
122 |     [`fontSize-${COMP}-codefence`]: "$fontSize-code",
123 |     [`fontFamily-${COMP}-codefence`]: "$fontFamily-monospace",
124 |     [`paddingHorizontal-${COMP}-codefence`]: "$space-4",
125 |     [`paddingVertical-${COMP}-codefence`]: "$space-3",
126 |     [`textColor-${COMP}-codefence`]: "$color-surface-900",
127 |     [`lineHeight-${COMP}-codefence`]: "1.5",
128 |     
129 |     [`fontFamily-${COMP}-code`]: "$fontFamily-monospace",
130 |     [`fontSize-${COMP}-code`]: "$fontSize-sm",
131 |     [`borderWidth-${COMP}-code`]: "1px",
132 |     [`borderStyle-${COMP}-code`]: "solid",
133 |     [`borderRadius-${COMP}-code`]: "4px",
134 |     [`paddingHorizontal-${COMP}-code`]: "$space-0_5",
135 |     [`paddingBottom-${COMP}-code`]: "2px",
136 |     [`backgroundColor-${COMP}-code`]: "rgb(from $color-surface-100 r g b / 0.4)",
137 |     [`borderColor-${COMP}-code`]: "$color-surface-100",
138 | 
139 |     [`textDecorationLine-${COMP}-deleted`]: "line-through",
140 | 
141 |     [`textDecorationLine-${COMP}-inserted`]: "underline",
142 | 
143 |     [`fontFamily-${COMP}-keyboard`]: "$fontFamily-monospace",
144 |     [`fontSize-${COMP}-keyboard`]: "$fontSize-sm",
145 |     [`fontWeight-${COMP}-keyboard`]: "$fontWeight-bold",
146 |     [`borderWidth-${COMP}-keyboard`]: "1px",
147 |     [`paddingHorizontal-${COMP}-keyboard`]: "$space-1",
148 |     [`backgroundColor-${COMP}-keyboard`]: "rgb(from $color-surface-100 r g b / 0.4)",
149 |     [`borderColor-${COMP}-keyboard`]: "$color-surface-300",
150 | 
151 |     [`fontFamily-${COMP}-sample`]: "$fontFamily-monospace",
152 |     [`fontSize-${COMP}-sample`]: "$fontSize-sm",
153 | 
154 |     [`fontSize-${COMP}-sup`]: "$fontSize-xs",
155 |     [`verticalAlignment-${COMP}-sup`]: "super",
156 | 
157 |     [`fontSize-${COMP}-sub`]: "$fontSize-xs",
158 |     [`verticalAlignment-${COMP}-sub`]: "sub",
159 | 
160 |     [`fontStyle-${COMP}-var`]: "italic",
161 | 
162 |     [`fontStyle-${COMP}-em`]: "italic",
163 | 
164 |     [`fontFamily-${COMP}-mono`]: "$fontFamily-monospace",
165 | 
166 |     [`fontSize-${COMP}-title`]: "$fontSize-2xl",
167 | 
168 |     [`fontSize-${COMP}-subtitle`]: "$fontSize-xl",
169 | 
170 |     [`fontSize-${COMP}-small`]: "$fontSize-sm",
171 | 
172 |     [`letterSpacing-${COMP}-caption`]: "0.05rem",
173 | 
174 |     [`fontSize-${COMP}-placeholder`]: "$fontSize-xs",
175 |     [`textColor-${COMP}-placeholder`]: "$color-surface-500",
176 | 
177 |     [`paddingVertical-${COMP}-paragraph`]: "$space-1",
178 | 
179 |     [`fontSize-${COMP}-subheading`]: "$fontSize-H6",
180 |     [`fontWeight-${COMP}-subheading`]: "$fontWeight-bold",
181 |     [`letterSpacing-${COMP}-subheading`]: "0.04em",
182 |     [`textTransform-${COMP}-subheading`]: "uppercase",
183 |     [`textColor-${COMP}-subheading`]: "$textColor-secondary",
184 | 
185 |     [`marginTop-${COMP}-tableheading`]: "$space-1",
186 |     [`marginBottom-${COMP}-tableheading`]: "$space-4",
187 |     [`paddingHorizontal-${COMP}-tableheading`]: "$space-1",
188 |     [`fontSize-${COMP}-tableheading`]: "$fontSize-H6",
189 |     [`fontWeight-${COMP}-tableheading`]: "$fontWeight-bold",
190 | 
191 |     [`fontWeight-${COMP}-strong`]: "$fontWeight-bold",
192 | 
193 |     [`backgroundColor-${COMP}-marked`]: "rgb(from $color-primary-200 r g b / 0.4)",
194 | 
195 |     dark: {
196 |       [`backgroundColor-${COMP}-marked`]: "rgb(from $color-primary-400 r g b / 0.4)",
197 |     },
198 |   },
199 | });
200 | 
201 | export const textComponentRenderer = createComponentRenderer(
202 |   COMP,
203 |   TextMd,
204 |   ({ node, extractValue, className, renderChild, registerComponentApi }) => {
205 |     const {
206 |       variant,
207 |       maxLines,
208 |       preserveLinebreaks,
209 |       ellipses,
210 |       overflowMode,
211 |       breakMode,
212 |       value,
213 |       ...variantSpecific
214 |     } = node.props;
215 | 
216 |     const variantSpecificProps: VariantProps = Object.fromEntries(
217 |       Object.entries(variantSpecific)
218 |         .filter(([key, _]) => VariantPropsKeys.includes(key as any))
219 |         .map(([key, value]) => [key, extractValue(value)]),
220 |     );
221 | 
222 |     return (
223 |       <Text
224 |         variant={extractValue(variant)}
225 |         maxLines={extractValue.asOptionalNumber(maxLines)}
226 |         className={className}
227 |         preserveLinebreaks={extractValue.asOptionalBoolean(
228 |           preserveLinebreaks,
229 |           defaultProps.preserveLinebreaks,
230 |         )}
231 |         ellipses={extractValue.asOptionalBoolean(ellipses, defaultProps.ellipses)}
232 |         overflowMode={extractValue(overflowMode) as OverflowMode | undefined}
233 |         breakMode={extractValue(breakMode) as BreakMode | undefined}
234 |         registerComponentApi={registerComponentApi}
235 |         {...variantSpecificProps}
236 |       >
237 |         {extractValue.asDisplayText(value) || renderChild(node.children)}
238 |       </Text>
239 |     );
240 |   },
241 | );
242 | 
```

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

```markdown
  1 | # Switch [#switch]
  2 | 
  3 | `Switch` enables users to toggle between two states: on and off.
  4 | 
  5 | ## Switch Values [#switch-values]
  6 | 
  7 | The `initialValue` and `value` properties of the switch are transformed to a Boolean value to display the on (`true`) or off (`false`) state with this logic:
  8 | - `null` and `undefined` go to `false`.
  9 | - If the property is Boolean, the property value is used as is.
 10 | - If it is a number, `NaN` and `0` result in `false`; other values represent `true`.
 11 | - If the property is a string, the empty string and the literal "false" string result in `false`; others result in `true`.
 12 | - The empty array value goes to `false`; other array values result in `true`.
 13 | - Object values with no properties result in `false`; other values represent `true`.
 14 | 
 15 | ## Properties [#properties]
 16 | 
 17 | ### `autoFocus` (default: false) [#autofocus-default-false]
 18 | 
 19 | If this property is set to `true`, the component gets the focus automatically when displayed.
 20 | 
 21 | ### `enabled` (default: true) [#enabled-default-true]
 22 | 
 23 | This boolean property value indicates whether the component responds to user events (`true`) or not (`false`).
 24 | 
 25 | This boolean property indicates whether the checkbox responds to user events (i.e. clicks);
 26 | it is `true` by default.
 27 | 
 28 | ```xmlui-pg copy {4-5, 9-10} display name="Example: enabled"
 29 | <App>
 30 |   Enabled switches:
 31 |   <HStack>
 32 |     <Switch initialValue="true" enabled="true" />
 33 |     <Switch initialValue="false" enabled="true" />
 34 |   </HStack>
 35 |   Disabled switches:
 36 |   <HStack>
 37 |     <Switch initialValue="true" enabled="false" />
 38 |     <Switch initilaValue="false" enabled="false" />
 39 |   </HStack>
 40 | </App>
 41 | ```
 42 | 
 43 | ### `initialValue` (default: false) [#initialvalue-default-false]
 44 | 
 45 | This property sets the component's initial value.
 46 | 
 47 | ### `readOnly` (default: false) [#readonly-default-false]
 48 | 
 49 | Set this property to `true` to disallow changing the component value.
 50 | 
 51 | If true, the value of the component cannot be modified.
 52 | 
 53 | ```xmlui-pg copy display name="Example: readOnly"
 54 | <App>
 55 |   <Switch readOnly="true" label="Checked" initialValue="true" />
 56 |   <Switch readOnly="true" label="Unchecked" intialValue="false" />
 57 | </App>
 58 | ```
 59 | 
 60 | ### `required` (default: false) [#required-default-false]
 61 | 
 62 | Set this property to `true` to indicate it must have a value before submitting the containing form.
 63 | 
 64 | ### `validationStatus` (default: "none") [#validationstatus-default-none]
 65 | 
 66 | This property allows you to set the validation status of the input component.
 67 | 
 68 | Available values:
 69 | 
 70 | | Value | Description |
 71 | | --- | --- |
 72 | | `valid` | Visual indicator for an input that is accepted |
 73 | | `warning` | Visual indicator for an input that produced a warning |
 74 | | `error` | Visual indicator for an input that produced an error |
 75 | 
 76 | ## Events [#events]
 77 | 
 78 | ### `click` [#click]
 79 | 
 80 | This event is triggered when the Switch is clicked.
 81 | 
 82 | ### `didChange` [#didchange]
 83 | 
 84 | This event is triggered when value of Switch has changed.
 85 | 
 86 | This event is triggered when the `Switch` is toggled due to user interaction.
 87 | A read-only switch never fires this event, and it won't fire if the switch's value is set programmatically.
 88 | 
 89 | ```xmlui-pg copy display name="Example: didChange"
 90 | <App verticalAlignment="center" var.changes="">
 91 |   <Switch label="Changeable" onDidChange="changes += '+'" />
 92 |   <Switch label="Readonly" readOnly="true" onDidChange="changes += '-'" />
 93 |   <Text value="Changes: {changes}" />
 94 | </App>
 95 | ```
 96 | 
 97 | ### `gotFocus` [#gotfocus]
 98 | 
 99 | This event is triggered when the Switch has received the focus.
100 | 
101 | This event is triggered when the `Switch` receives focus.
102 | 
103 | Click the `Switch` in the example demo to change the label text. Note how clicking elsewhere resets the text to the original.
104 | 
105 | ```xmlui-pg copy {4,5} display name="Example: gotFocus"
106 | <App var.focused="{false}" verticalAlignment="center">
107 |   <Switch
108 |     value="true"
109 |     onGotFocus="focused = true"
110 |     onLostFocus="focused = false"
111 |   />
112 |   <Text value="{focused === true ? 'I am focused!' : 'I have lost the focus!'}" />
113 | </App>
114 | ```
115 | 
116 | ### `lostFocus` [#lostfocus]
117 | 
118 | This event is triggered when the Switch has lost the focus.
119 | 
120 | ## Exposed Methods [#exposed-methods]
121 | 
122 | ### `setValue` [#setvalue]
123 | 
124 | This API sets the value of the `Switch`. You can use it to programmatically change the value.
125 | 
126 | **Signature**: `setValue(value: boolean): void`
127 | 
128 | - `value`: The new value to set. Can be either true (on) or false (off).
129 | 
130 | ```xmlui-pg copy {10,13,15} display name="Example: value and setValue"
131 | <App var.changes="">
132 |   <Switch
133 |     id="mySwitch"
134 |     readOnly="true"
135 |     label="This switch can be set only programmatically"
136 |     onDidChange="changes += '+'" />
137 |   <HStack>
138 |     <Button
139 |       label="Check"
140 |       onClick="mySwitch.setValue(true)" />
141 |     <Button
142 |       label="Uncheck"
143 |       onClick="mySwitch.setValue(false)" />
144 |   </HStack>
145 |   <Text>The switch is {checkbox.value ? "checked" : "unchecked"}</Text>
146 |   <Text value="Changes: {changes}" />
147 | </App>
148 | ```
149 | 
150 | ### `value` [#value]
151 | 
152 | This property holds the current value of the Switch, which can be either "true" (on) or "false" (off).
153 | 
154 | **Signature**: `get value():boolean`
155 | 
156 | ## Parts [#parts]
157 | 
158 | The component has some parts that can be styled through layout properties and theme variables separately:
159 | 
160 | - **`input`**: The switch input area.
161 | - **`label`**: The label displayed for the switch.
162 | 
163 | ## Styling [#styling]
164 | 
165 | ### Theme Variables [#theme-variables]
166 | 
167 | | Variable | Default Value (Light) | Default Value (Dark) |
168 | | --- | --- | --- |
169 | | [backgroundColor](../styles-and-themes/common-units/#color)-checked-Switch | $color-primary-500 | $color-primary-500 |
170 | | [backgroundColor](../styles-and-themes/common-units/#color)-checked-Switch | $color-primary-500 | $color-primary-500 |
171 | | [backgroundColor](../styles-and-themes/common-units/#color)-checked-Switch--error | $borderColor-Switch--error | $borderColor-Switch--error |
172 | | [backgroundColor](../styles-and-themes/common-units/#color)-checked-Switch--error | $borderColor-Switch--error | $borderColor-Switch--error |
173 | | [backgroundColor](../styles-and-themes/common-units/#color)-checked-Switch--success | $borderColor-Switch--success | $borderColor-Switch--success |
174 | | [backgroundColor](../styles-and-themes/common-units/#color)-checked-Switch--success | $borderColor-Switch--success | $borderColor-Switch--success |
175 | | [backgroundColor](../styles-and-themes/common-units/#color)-checked-Switch--warning | $borderColor-Switch--warning | $borderColor-Switch--warning |
176 | | [backgroundColor](../styles-and-themes/common-units/#color)-checked-Switch--warning | $borderColor-Switch--warning | $borderColor-Switch--warning |
177 | | [backgroundColor](../styles-and-themes/common-units/#color)-indicator-checked-Switch | $backgroundColor-primary | $backgroundColor-primary |
178 | | [backgroundColor](../styles-and-themes/common-units/#color)-indicator-Switch | $color-surface-400 | $color-surface-500 |
179 | | [backgroundColor](../styles-and-themes/common-units/#color)-Switch | $color-surface-0 | $color-surface-0 |
180 | | [backgroundColor](../styles-and-themes/common-units/#color)-Switch | $color-surface-0 | $color-surface-0 |
181 | | [backgroundColor](../styles-and-themes/common-units/#color)-Switch--disabled | $color-surface-200 | $color-surface-200 |
182 | | [backgroundColor](../styles-and-themes/common-units/#color)-Switch--disabled | $color-surface-200 | $color-surface-200 |
183 | | [backgroundColor](../styles-and-themes/common-units/#color)-Switch-indicator--disabled | $backgroundColor-primary | $backgroundColor-primary |
184 | | [borderColor](../styles-and-themes/common-units/#color)-checked-Switch | $color-primary-500 | $color-primary-500 |
185 | | [borderColor](../styles-and-themes/common-units/#color)-checked-Switch | $color-primary-500 | $color-primary-500 |
186 | | [borderColor](../styles-and-themes/common-units/#color)-checked-Switch--error | $borderColor-Switch--error | $borderColor-Switch--error |
187 | | [borderColor](../styles-and-themes/common-units/#color)-checked-Switch--error | $borderColor-Switch--error | $borderColor-Switch--error |
188 | | [borderColor](../styles-and-themes/common-units/#color)-checked-Switch--success | $borderColor-Switch--success | $borderColor-Switch--success |
189 | | [borderColor](../styles-and-themes/common-units/#color)-checked-Switch--success | $borderColor-Switch--success | $borderColor-Switch--success |
190 | | [borderColor](../styles-and-themes/common-units/#color)-checked-Switch--warning | $borderColor-Switch--warning | $borderColor-Switch--warning |
191 | | [borderColor](../styles-and-themes/common-units/#color)-checked-Switch--warning | $borderColor-Switch--warning | $borderColor-Switch--warning |
192 | | [borderColor](../styles-and-themes/common-units/#color)-Switch | $color-surface-200 | $color-surface-200 |
193 | | [borderColor](../styles-and-themes/common-units/#color)-Switch | $color-surface-200 | $color-surface-200 |
194 | | [borderColor](../styles-and-themes/common-units/#color)-Switch--default--hover | *none* | *none* |
195 | | [borderColor](../styles-and-themes/common-units/#color)-Switch--disabled | *none* | *none* |
196 | | [borderColor](../styles-and-themes/common-units/#color)-Switch--error | *none* | *none* |
197 | | [borderColor](../styles-and-themes/common-units/#color)-Switch--success | *none* | *none* |
198 | | [borderColor](../styles-and-themes/common-units/#color)-Switch--warning | *none* | *none* |
199 | | [borderWidth](../styles-and-themes/common-units/#size)-Switch | 1px | 1px |
200 | | [outlineColor](../styles-and-themes/common-units/#color)-Switch--focus | *none* | *none* |
201 | | [outlineOffset](../styles-and-themes/common-units/#size)-Switch--focus | *none* | *none* |
202 | | [outlineStyle](../styles-and-themes/common-units/#border)-Switch--focus | *none* | *none* |
203 | | [outlineWidth](../styles-and-themes/common-units/#size)-Switch--focus | *none* | *none* |
204 | 
```

--------------------------------------------------------------------------------
/docs/public/pages/tutorial-08.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Create Invoice
  2 | 
  3 | Here's the `Create Invoice` form, using cached data for clients and products. The `Save` button is wired to a dummy API endpoint, try it as you explore the form to see how validation works when no client is selected, and/or when no line items are added.
  4 | 
  5 | ```xmlui-pg display name="Try saving in various stages of completion"
  6 | ---app
  7 | <App>
  8 |   <CreateInvoice />
  9 | </App>
 10 | ---comp
 11 | <Component name="CreateInvoice">
 12 |   <DataSource id="clients" url="/resources/files/clients.json" method="GET" />
 13 | 
 14 |   <DataSource id="products" url="/resources/files/products.json" method="GET" />
 15 | 
 16 |   <Form
 17 |     id="invoiceForm"
 18 |     onCancel="invoiceForm.reset()">
 19 |     <Card>
 20 |       <H1>Create New Invoice</H1>
 21 | 
 22 |         <FlowLayout>
 23 | 
 24 |         <Card border="none" width="50%" padding="0">
 25 |           <FormItem
 26 |             type="select"
 27 |             placeholder="select client"
 28 |             bindTo="client"
 29 |             label="Client"
 30 |             required="true"
 31 |           >
 32 |             <Items data="{clients}">
 33 |               <Option value="{$item.name}" label="{$item.name}" />
 34 |             </Items>
 35 |           </FormItem>
 36 |         </Card>
 37 | 
 38 |         <Card border="none" width="25%" padding="0">
 39 |           <FormItem type="datePicker" dateFormat="yyyy-MM-dd" initialValue="{ formatToday() }"
 40 |             bindTo="issueDate" label="Issue date" />
 41 |         </Card>
 42 | 
 43 |         <Card border="none" width="25%" padding="0">
 44 |           <FormItem type="datePicker" dateFormat="yyyy-MM-dd" initialValue="{ formatToday(30) }"
 45 |             bindTo="dueDate" label="Due date" />
 46 |         </Card>
 47 | 
 48 |       </FlowLayout>
 49 | 
 50 |       <H2>Line Items</H2>
 51 |       <FlowLayout fontWeight="bold" backgroundColor="$color-surface-100" padding="$space-2">
 52 |         <Text width="25%">Product/Service</Text>
 53 |         <Text width="25%">Description</Text>
 54 |         <Text width="12%">Quantity</Text>
 55 |         <Text width="12%">Price</Text>
 56 |         <Text width="12%">Amount</Text>
 57 |       </FlowLayout>
 58 | 
 59 |       <FormItem
 60 |         bindTo="lineItems"
 61 |         type="items"
 62 |         id="lineItemsForm"
 63 |         required="true"
 64 |         onValidate="(value) => Array.isArray(value) && value.length > 0 && value.every(item => item.product)"
 65 |         requiredInvalidMessage="At least one line item is required."
 66 |       >
 67 |         <FlowLayout
 68 |            width="100%"
 69 |           verticalAlignment="center"
 70 |           gap="$space-2"
 71 |         >
 72 |           <DataSource
 73 |             id="productDetails"
 74 |             url="/resources/files/products.json"
 75 |             when="{$item.product != null}"
 76 |             method="GET"
 77 |             transformResult="{(data) => data.filter(product => product.name === $item.product)}"
 78 |           />
 79 |           <FormItem
 80 |             bindTo="product"
 81 |             type="select"
 82 |             placeholder="select product"
 83 |             width="25%"
 84 |           >
 85 |             <Items data="{products}">
 86 |               <Option value="{$item.name}" label="{$item.name}" />
 87 |             </Items>
 88 |           </FormItem>
 89 | 
 90 |           <Text width="25%">{ productDetails.value[0].description }</Text>
 91 |           <FormItem width="12%" bindTo="quantity"               type="number"   initialValue="1" minValue="1" />
 92 |           <FormItem width="12%" bindTo="price"  startText="$"                   initialValue="{ productDetails.value[0].price }" />
 93 |           <FormItem width="12%" bindTo="amount" startText="$"   enabled="false" initialValue="{ $item.price ? $item.quantity * $item.price : '' } " />
 94 |           <Button width="2rem" onClick="lineItemsForm.removeItem($itemIndex)">X</Button>
 95 | 
 96 |         </FlowLayout>
 97 |       </FormItem>
 98 |       <HStack>
 99 |         <Button onClick="lineItemsForm.addItem()">
100 |           Add Item
101 |         </Button>
102 |         <SpaceFiller />
103 |         <Text>
104 |          Total: ${ window.lineItemTotal($data.lineItems) }
105 |         </Text>
106 |       </HStack>
107 |     </Card>
108 |     <event name="submit">
109 |       <APICall
110 |         url="https://httpbin.org/post"
111 |         method="POST"
112 |         inProgressNotificationMessage="Saving invoice..."
113 |         completedNotificationMessage="Invoice saved successfully"
114 |         body="{
115 |           {
116 |           client: $param.client,
117 |           issueDate: $param.issueDate,
118 |           dueDate: $param.dueDate,
119 |           total: window.lineItemTotal($param.lineItems),
120 |           items: JSON.stringify($param.lineItems || [])
121 |           }
122 |         }"
123 |         onSuccess="Actions.navigate('/invoices')"
124 |       />
125 |     </event>
126 | 
127 |   </Form>
128 | </Component>
129 | ```
130 | 
131 | The `CreateInvoice` component encapsulates all the form logic. Let's review the key points.
132 | 
133 | ## The Form tag
134 | 
135 | This [Form](/components/Form) contains a dropdown menu of products, two date pickers, and an expandable set of lineitems. These parts separately feed into the form's `$data` [context variable](/context-variables) which accumulates the JSON payload sent to the server on submit with successful validation.
136 | 
137 | ```xmlui
138 | <Form
139 |     id="invoiceForm"
140 |     onCancel="invoiceForm.reset()">
141 | ```
142 | 
143 | ## The payload
144 | 
145 | A valid payload looks like this.
146 | 
147 | ```json
148 | {
149 |   "issueDate": "2025-06-10",
150 |   "dueDate": "2025-07-10",
151 |   "client": "Abstergo Industries",
152 |   "lineItems": [
153 |     {
154 |       "quantity": "1",
155 |       "amount": 105,
156 |       "product": "API Integration",
157 |       "price": 105
158 |     },
159 |     {
160 |       "quantity": "1",
161 |       "amount": 115,
162 |       "product": "Brand Strategy Consulting",
163 |       "price": 115
164 |     }
165 |   ]
166 | }
167 | ```
168 | 
169 | The form's `Cancel` button resets all of its components and empties this data structure.
170 | 
171 | ## Nested FormItems
172 | 
173 | There is a top-level `FormItem` for `client`, `issue_date`, `due_date`, and `lineItems`. Their `bindTo` attributes name and populate corresponding fields in `$data`.
174 | 
175 | Nested within `lineItems` there is a `FormItem` for `product`, `quantity`, `price`, and `amount`. Their `bindTo` attributes name and define slots in an array of `lineItems` that's dynamically built on each click of the `Add Item` button.
176 | 
177 | ```xmlui /<FormItem/
178 | <Card title="Create New Invoice">
179 |   <FlowLayout>
180 |     <FormItem
181 |       width="50%"
182 |       type="select"
183 |       placeholder="select client"
184 |       bindTo="client"
185 |       label="Client"
186 |       required="true"
187 |     >
188 |       <Items data="/api/clients">
189 |         <Option value="{$item.name}" label="{$item.name}"/>
190 |       </Items>
191 |     </FormItem>
192 | 
193 |     <FormItem
194 |       type="datePicker"
195 |       dateFormat="yyyy-MM-dd"
196 |       initialValue="{ formatToday() }"
197 |       bindTo="issueDate"
198 |       label="Issue date" width="25%"
199 |     />
200 | 
201 |     <FormItem
202 |       type="datePicker"
203 |       dateFormat="yyyy-MM-dd"
204 |       initialValue="{ formatToday(30) }"
205 |       bindTo="dueDate"
206 |       label="Due date"
207 |       width="25%" />
208 |   </FlowLayout>
209 | 
210 |   <H2>Line Items</H2>
211 |   <FlowLayout
212 |     fontWeight="bold"
213 |     backgroundColor="$color-surface-100"
214 |     padding="$space-2"
215 |   >
216 |     <Text width="20%">Product/Service</Text>
217 |     <Text width="20%">Description</Text>
218 |     <Text width="20%">Quantity</Text>
219 |     <Text width="20%">Price</Text>
220 |     <Text width="20%">Amount</Text>
221 |   </FlowLayout>
222 | 
223 |   <FormItem
224 |     bindTo="lineItems"
225 |     type="items"
226 |     id="lineItemsForm"
227 |     required="true"
228 |     requiredInvalidMessage="At least one line item is required."
229 |   >
230 |     <FlowLayout width="100%">
231 |       <DataSource
232 |         id="productDetails"
233 |         url="/api/products/byname/{$item.product}"
234 |         when="{$item.product != null}"
235 |         method="GET"
236 |       />
237 |       <FormItem
238 |         bindTo="product"
239 |         type="select"
240 |         placeholder="select product"
241 |         width="20%"
242 |         required="true"
243 |       >
244 |         <Items data="/api/products">
245 |           <Option value="{$item.name}" label="{$item.name}"/>
246 |         </Items>
247 |       </FormItem>
248 |       <Text width="20%">{ productDetails.value[0].description }</Text>
249 |       <FormItem
250 |         width="20%"
251 |         bindTo="quantity"
252 |         type="number"
253 |         initialValue="1"
254 |         minValue="1"
255 |       />
256 |       <FormItem
257 |         width="20%"
258 |         bindTo="price"
259 |         startText="$"
260 |         initialValue="{ productDetails.value[0].price }"
261 |       />
262 |       <FormItem
263 |         width="13%"
264 |         bindTo="amount"
265 |         startText="$"
266 |         enabled="false"
267 |         initialValue="{ $item.price ? $item.quantity * $item.price : '' } "
268 |       />
269 |       <Button
270 |         width="2rem"
271 |         onClick="lineItemsForm.removeItem($itemIndex)">
272 |         X
273 |       </Button>
274 |     </FlowLayout>
275 |   </FormItem>
276 |   <HStack>
277 |     <Button onClick="lineItemsForm.addItem()">
278 |       Add Item
279 |     </Button>
280 |     <SpaceFiller/>
281 |     <Text>
282 |       Total: ${ window.lineItemTotal($data.lineItems) }
283 |     </Text>
284 |   </HStack>
285 | </Card>
286 | ```
287 | 
288 | ## Total for lineItems
289 | 
290 | The `Add Item` button invokes the `addItem` method of [FormItem](/components/FormItem) to add a new empty row to the array. (Above we see the corresponding `removeItem` used when clicking the button at the end of a row.)
291 | 
292 | The app defines a function, `lineItemTotal`, to receive the `lineItems` array and add up the amounts.
293 | 
294 | ```xmlui /lineItemTotal/
295 | <HStack>
296 |   <Button onClick="lineItemsForm.addItem()">
297 |     Add Item
298 |   </Button>
299 |   <SpaceFiller />
300 |   <Text>
301 |     Total: ${ window.lineItemTotal($data.lineItems) }
302 |   </Text>
303 | </HStack>
304 | ```
305 | 
306 | The same function runs when the [APICall](/components/APICall) runs on form submission.
307 | 
308 | ```xmlui /lineItemTotal/
309 | <Form>
310 |   <!-- ... -->
311 |   <event name="submit">
312 |     <APICall
313 |       url="https://httpbin.org/post"
314 |       method="POST"
315 |       inProgressNotificationMessage="Saving invoice..."
316 |       completedNotificationMessage="Invoice saved successfully"
317 |       body="{
318 |         {
319 |           client: $param.client,
320 |           issueDate: $param.issueDate,
321 |           dueDate: $param.dueDate,
322 |           total: window.lineItemTotal($data.lineItems),
323 |           items: JSON.stringify($param.lineItems || [])
324 |         }
325 |       }"
326 |       onSuccess="Actions.navigate('/invoices')"
327 |     />
328 |   </event>
329 |   <!-- ... -->
330 | </Form>
331 | ```
332 | 
```

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

```typescript
  1 | import { SKIP_REASON } from "../../testing/component-test-helpers";
  2 | import { expect, test } from "../../testing/fixtures";
  3 | 
  4 | test.describe("Basic Functionality", () => {
  5 |   test("renders", async ({ page, initTestBed }) => {
  6 |     await initTestBed(`<Image testId="img" />`);
  7 |     await expect(page.getByTestId("img")).toBeVisible();
  8 |   });
  9 | 
 10 |   test("displays image with valid src", async ({ page, initTestBed }) => {
 11 |     await initTestBed(`<Image testId="img" src="/resources/test-image-100x100.jpg" />`);
 12 |     await expect(page.getByTestId("img")).toHaveAttribute(
 13 |       "src",
 14 |       "/resources/test-image-100x100.jpg",
 15 |     );
 16 |   });
 17 | 
 18 |   test("displays image with valid data property", async ({ page, initTestBed }) => {
 19 |     await initTestBed(`<Image testId="img" data="/resources/test-image-100x100.jpg" />`);
 20 |     await expect(page.getByTestId("img")).toBeVisible();
 21 |     
 22 |     // Check that the src attribute contains a blob URL when using data property
 23 |     // The Image component fetches the binary data and passes it as a Blob to ImageNative,
 24 |     // which creates a blob URL and sets it as the src attribute
 25 |     const img = page.getByTestId("img");
 26 |     await expect(img).toHaveAttribute("src", /blob:/);
 27 |   });
 28 | 
 29 |   test("handles invalid src gracefully", async ({ page, initTestBed }) => {
 30 |     await initTestBed(`<Image testId="img" src="/non/existent/bad/url.jpg" />`);
 31 |     await expect(page.getByTestId("img")).toBeVisible();
 32 |     await expect(page.getByTestId("img")).toHaveAttribute("src", "/non/existent/bad/url.jpg");
 33 |   });
 34 | 
 35 |   test("alt text", async ({ page, initTestBed }) => {
 36 |     await initTestBed(`<Image alt="test text for alt" src="/non/existent/bad/url.jpg" />`);
 37 |     await expect(page.getByAltText("test text for alt")).toBeVisible();
 38 |   });
 39 | 
 40 |   test("handles undefined alt", async ({ page, initTestBed }) => {
 41 |     await initTestBed(`<Image testId="img" src="/resources/test-image-100x100.jpg" />`);
 42 |     await expect(page.getByTestId("img")).not.toHaveAttribute("alt");
 43 |   });
 44 | 
 45 |   test("handles long unicode alt text", async ({ page, initTestBed }) => {
 46 |     await initTestBed(`
 47 |       <Image
 48 |         testId="img" alt="👨‍👩‍👧‍👦 Family photo with unicode characters 中文测试"
 49 |         src="/resources/test-image-100x100.jpg"
 50 |       />
 51 |     `);
 52 |     await expect(page.getByTestId("img")).toHaveAttribute(
 53 |       "alt",
 54 |       "👨‍👩‍👧‍👦 Family photo with unicode characters 中文测试",
 55 |     );
 56 |   });
 57 | 
 58 |   test(`fit="contain"`, async ({ page, initTestBed }) => {
 59 |     await initTestBed(`
 60 |         <HStack width="300px" height="200px" >
 61 |           <Image testId="img" src="/resources/test-image-100x100.jpg" fit="contain" />
 62 |         </HStack>
 63 |       `);
 64 |     await expect(page.getByTestId("img")).toHaveCSS("object-fit", "contain");
 65 |   });
 66 | 
 67 |   test(`fit="cover"`, async ({ page, initTestBed }) => {
 68 |     await initTestBed(`
 69 |         <HStack width="300px" height="200px" >
 70 |           <Image testId="img" src="/resources/test-image-100x100.jpg" fit="cover" />
 71 |         </HStack>
 72 |       `);
 73 |     await expect(page.getByTestId("img")).toHaveCSS("object-fit", "cover");
 74 |   });
 75 | 
 76 |   test("handles invalid fit value", async ({ page, initTestBed }) => {
 77 |     await initTestBed(
 78 |       `<Image testId="img" src="/resources/test-image-100x100.jpg" fit="invalid" />`,
 79 |     );
 80 |     await expect(page.getByTestId("img")).toHaveCSS("object-fit", "contain");
 81 |   });
 82 | 
 83 |   test("lazy loading enabled", async ({ page, initTestBed }) => {
 84 |     await initTestBed(
 85 |       `<Image testId="img" src="/resources/test-image-100x100.jpg" lazyLoad="true" />`,
 86 |     );
 87 |     await expect(page.getByTestId("img")).toHaveAttribute("loading", "lazy");
 88 |   });
 89 | 
 90 |   test("lazy loading disabled (default)", async ({ page, initTestBed }) => {
 91 |     await initTestBed(`<Image testId="img" src="/resources/test-image-100x100.jpg" />`);
 92 |     await expect(page.getByTestId("img")).toHaveAttribute("loading", "eager");
 93 |   });
 94 | 
 95 |   test("lazy loading explicitly disabled", async ({ page, initTestBed }) => {
 96 |     await initTestBed(
 97 |       `<Image testId="img" src="/resources/test-image-100x100.jpg" lazyLoad="false" />`,
 98 |     );
 99 |     await expect(page.getByTestId("img")).toHaveAttribute("loading", "eager");
100 |   });
101 | 
102 |   test("applies aspect ratio as number", async ({ page, initTestBed }) => {
103 |     await initTestBed(
104 |       `<Image testId="img" src="/resources/test-image-100x100.jpg" aspectRatio="1.5" />`,
105 |     );
106 |     await expect(page.getByTestId("img")).toHaveCSS("aspect-ratio", "1.5 / 1");
107 |   });
108 | 
109 |   test("applies aspect ratio as string fraction", async ({ page, initTestBed }) => {
110 |     await initTestBed(
111 |       `<Image testId="img" src="/resources/test-image-100x100.jpg" aspectRatio="16/9" />`,
112 |     );
113 |     await expect(page.getByTestId("img")).toHaveCSS("aspect-ratio", "16 / 9");
114 |   });
115 | 
116 |   test("inline display when true", async ({ page, initTestBed }) => {
117 |     await initTestBed(
118 |       `<Image testId="img" src="/resources/test-image-100x100.jpg" inline="true" />`,
119 |     );
120 |     await expect(page.getByTestId("img")).toHaveCSS("display", "inline");
121 |   });
122 | 
123 |   test("block display when false (default)", async ({ page, initTestBed }) => {
124 |     await initTestBed(
125 |       `<Image testId="img" src="/resources/test-image-100x100.jpg" inline="false" />`,
126 |     );
127 |     await expect(page.getByTestId("img")).not.toHaveCSS("display", "inline");
128 |   });
129 | });
130 | 
131 | test.describe("Accessibility", () => {
132 |   test("has correct role when clickable", async ({ page, initTestBed }) => {
133 |     await initTestBed(`
134 |         <Image testId="img" src="/resources/test-image-100x100.jpg" onClick="console.log('clicked')" alt="Clickable image" />
135 |       `);
136 |     const img = page.getByTestId("img");
137 |     await expect(img).toHaveAttribute("alt", "Clickable image");
138 |   });
139 | });
140 | 
141 | test.describe("Events", () => {
142 |   test(`onClick event`, async ({ page, initTestBed }) => {
143 |     await initTestBed(`
144 |         <HStack width="100px" gap="1rem" verticalAlignment="center">   
145 |           <variable name="showTestText" value="{false}" />
146 |           <Image onClick="showTestText = true" testId="img" src="/resources/test-image-100x100.jpg" />
147 |           <Text when="{showTestText}">this is a test text</Text>
148 |         </HStack>
149 |       `);
150 |     await page.getByTestId("img").click();
151 |     await expect(page.getByText("this is a test text")).toBeVisible();
152 |   });
153 | });
154 | 
155 | test.describe("Theme Variables", () => {
156 |   test(`custom themeVar borderRadius`, async ({ page, initTestBed }) => {
157 |     await initTestBed(`<Image testId="img" src="/resources/test-image-100x100.jpg" />`, {
158 |       testThemeVars: {
159 |         "borderRadius-Image": "25px",
160 |       },
161 |     });
162 |     await expect(page.getByTestId("img")).toHaveCSS("border-radius", "25px");
163 |   });
164 | 
165 |   test(`custom themeVar borderColor`, async ({ page, initTestBed }) => {
166 |     await initTestBed(`<Image testId="img" src="/resources/test-image-100x100.jpg" />`, {
167 |       testThemeVars: {
168 |         "borderColor-Image": "rgb(255, 0, 0)",
169 |       },
170 |     });
171 |     await expect(page.getByTestId("img")).toHaveCSS("border-color", "rgb(255, 0, 0)");
172 |   });
173 | });
174 | 
175 | test.describe("Other Edge Cases", () => {
176 |   [
177 |     { label: "null", value: null },
178 |     { label: "undefined", value: undefined },
179 |     { label: "number", value: 123 },
180 |     { label: "boolean", value: true },
181 |     { label: "empty object", value: "{}" },
182 |     { label: "empty array", value: "[]" },
183 |     { label: "array", value: "['/resources/test-image-100x100.jpg']" },
184 |     { label: "function", value: "() => '/resources/test-image-100x100.jpg'" },
185 |     { label: "object", value: "{ a: '/resources/test-image-100x100.jpg' }" },
186 |   ].forEach(({ label, value }) => {
187 |     test(`src prop handles ${label} by rendering broken image`, async ({ page, initTestBed }) => {
188 |       await initTestBed(`<Image testId="img" src="{${value}}" />`);
189 |       const img = page.getByTestId("img");
190 | 
191 |       await expect(img).toBeVisible();
192 | 
193 |       const naturalWidth = await img.evaluate((el: HTMLImageElement) => el.naturalWidth);
194 |       const naturalHeight = await img.evaluate((el: HTMLImageElement) => el.naturalHeight);
195 | 
196 |       expect(naturalWidth).toBe(0);
197 |       expect(naturalHeight).toBe(0);
198 |     });
199 |   });
200 | 
201 |   [
202 |     { label: "empty string", prop: "alt=\"\"", expected: undefined },
203 |     { label: "string", prop: 'alt="some text"', expected: "some text" },
204 |     { label: "number", prop: 'alt="{123}"', expected: "123" },
205 |     { label: "boolean", prop: 'alt="{true}"', expected: "true" },
206 |   ].forEach(({ label, prop, expected }) => {
207 |     test(`alt attribute appears if value is ${label}`, async ({ page, initTestBed }) => {
208 |       await initTestBed(`<Image testId="img" ${prop} />`);
209 |       const img = page.getByTestId("img");
210 | 
211 |       await expect(img).toBeVisible();
212 |       await expect(img).toHaveAttribute("alt", expected);
213 |     });
214 |   });
215 | 
216 |   [
217 |     { label: "null", prop: 'alt="{null}"' },
218 |     { label: "undefined", prop: 'alt="{undefined}"' },
219 |     { label: "empty object", prop: 'alt="{{}}"' },
220 |     { label: "empty array", prop: 'alt="{[]}"' },
221 |     { label: "array", prop: 'alt="{[\'/resources/test-image-100x100.jpg\']}"' },
222 |     { label: "function", prop: 'alt="{() => \'/resources/test-image-100x100.jpg\'}"' },
223 |     { label: "object", prop: 'alt="{{ a: \'/resources/test-image-100x100.jpg\' }}"' },
224 |   ].forEach(({ label, prop }) => {
225 |     test(`alt attr not shown if value is ${label}`, async ({ page, initTestBed }) => {
226 |       await initTestBed(`<Image testId="img" ${prop} />`);
227 |       const img = page.getByTestId("img");
228 | 
229 |       await expect(img).toBeVisible();
230 |       await expect(img).not.toHaveAttribute("alt");
231 |     });
232 |   });
233 | 
234 |   test("handles very long src URL", async ({ page, initTestBed }) => {
235 |     const longUrl = "/very/long/path/".repeat(20) + "image.jpg";
236 |     await initTestBed(`<Image testId="img" src="${longUrl}" />`);
237 |     await expect(page.getByTestId("img")).toHaveAttribute("src", longUrl);
238 |   });
239 | });
240 | 
```

--------------------------------------------------------------------------------
/blog/public/blog/xmlui-powered-blog.md:
--------------------------------------------------------------------------------

```markdown
  1 | In this post we'll explore the development of the blog engine we're using on this site. Our tagline is *Practical User Interfaces Built Simply*  and creating this blog couldn't have been simpler. It's an XMLUI app built with a handful of core components (including [NavPanel](https://docs.xmlui.org/components/NavPanel), [NavLink](https://docs.xmlui.org/components/NavLink), [Pages](https://docs.xmlui.org/components/Pages), [Page](https://docs.xmlui.org/components/Page), and [Markdown](https://docs.xmlui.org/components/Markdown)) and a couple of [user-defined components](https://docs.xmlui.org/user-defined-components).
  2 | 
  3 | ## The simplest possible thing
  4 | 
  5 | We started with the simplest possible approach: post metadata and data as literal strings.
  6 | 
  7 | ```xmlui-pg name="XMLUI blog v1" height="200px"
  8 | ---app
  9 | <App layout="vertical">
 10 |   <NavPanel>
 11 |     <NavGroup label="Blog">
 12 |       <NavLink label="Newest post" to="/newest-post" />
 13 |       <NavLink label="Older píost" to="/older-post" />
 14 |     </NavGroup>
 15 |   </NavPanel>
 16 |     <Pages>
 17 |       <Page url="/newest-post">
 18 |         <BlogPage
 19 |           content="This is the latest post"
 20 |           title="Newest post"
 21 |           author="Jon Udell"
 22 |           date="2025-09-01" />
 23 |       </Page>
 24 |       <Page url="/older-post">
 25 |         <BlogPage
 26 |           content="This is an older post"
 27 |           title="Older post"
 28 |           author="Istvan Novak"
 29 |           date="2025-08-30" />
 30 |       </Page>
 31 |     </Pages>
 32 | </App>
 33 | ---comp copy
 34 | <Component name="BlogPage">
 35 |   <VStack width="{$props.width ? $props.width : '85%'}">
 36 |     <VStack>
 37 |       <H1>{$props.title}</H1>
 38 |       <HStack gap="$space-2">
 39 |         <Text>{$props.date}</Text>
 40 |         <Text>-</Text>
 41 |         <Text>{$props.author}</Text>
 42 |       </HStack>
 43 |     </VStack>
 44 |     <Markdown content="{$props.content}" />
 45 |   </VStack>
 46 | </Component>
 47 | ```
 48 | 
 49 | You can use it right here or you can click the ![](/resources/pg-popout.svg) icon to open a playground where you can make live changes.
 50 | 
 51 | This is a pretty good start! We can write posts, arrange them in reverse chronological order, and hey, it's the essence of a blog. The live playground is a nice bonus that any XMLUI app might put to good use. When you build user interfaces with XMLUI you'll want to document them, it's useful to do that with working examples as well as images, text, and video.
 52 | 
 53 | Let's unpack how this works, there isn't much to it. The `App` declared in `Main.xmlui` sets up navigation.
 54 | 
 55 | ```xmlui copy
 56 | <App>
 57 |   <NavPanel>
 58 |     <NavGroup label="Blog">
 59 |       <NavLink label="Newest post" to="/newest-post" />
 60 |       <NavLink label="Older post" to="/older-post" />
 61 |     </NavGroup>
 62 |   </NavPanel>
 63 |   <!-- Pages section... -->
 64 | </App>
 65 | ```
 66 | 
 67 | Each Page contains a user-defined component called `BlogPage` that receives the properties `content`, `title`, `author`, and `date`.
 68 | 
 69 | ```xmlui
 70 | <Pages>
 71 |   <Page url="/newest-post">
 72 |     <BlogPage
 73 |       content="This is the latest post"
 74 |       title="Newest post"
 75 |       author="Jon Udell"
 76 |       date="2025-09-01" />
 77 |   </Page>
 78 | </Pages>
 79 | ```
 80 | 
 81 | Here's how `BlogPage` assembles data and metadata to create a post.
 82 | 
 83 | ```xmlui /$props/
 84 | <Component name="BlogPage">
 85 |     <VStack gap="0">
 86 |       <H1>{$props.post.title}</H1>
 87 |       <Text>{$props.post.date} • {$props.post.author}</Text>
 88 |     </VStack>
 89 |     <Image src="/blog/images/{$props.post.image}" />
 90 |     <Markdown marginTop="$space-4" data="/blog/{$props.post.slug}.md" />
 91 | </Component>
 92 | ```
 93 | 
 94 | ## Use Markdown files
 95 | 
 96 | So far the post content exists only as the `content` property passed to the `BlogPage` component. For the real blog we'll want to manage it as a set of Markdown files. This version enables that.
 97 | 
 98 | ```xmlui-pg name="XMLUI blog v2"  height="200px"
 99 | ---app
100 | <App
101 |   layout="vertical"
102 |   var.posts = `{[
103 |     {
104 |       title: "Welcome to the XMLUI blog!",
105 |       slug: "xmlui-powered-blog",
106 |       author: "Jon Udell",
107 |       date: "2025-09-01",
108 |       image: "blog-scrabble.png"
109 |     },
110 |     {
111 |       title: "Lorem Ipsum!",
112 |       slug: "lorem-ipsum",
113 |       author: "H. Rackham",
114 |       date: "1914-06-03",
115 |       image: "lorem-ipsum.png"
116 |     }
117 |   ]}`
118 | >
119 |   <NavPanel>
120 |     <NavGroup label="Blog">
121 |       <NavLink label="Newest post" to="/blog/{posts[0].slug}" />
122 |       <NavLink label="Older post" to="/blog/{posts[1].slug}" />
123 |     </NavGroup>
124 |   </NavPanel>
125 |     <Pages>
126 |       <Page url="/blog/{posts[0].slug}">
127 |         <BlogPage post="{posts[0]}" />
128 |       </Page>
129 |       <Page url="/blog/{posts[1].slug}">
130 |         <BlogPage post="{posts[1]}" />
131 |       </Page>
132 |     </Pages>
133 | </App>
134 | ---comp
135 | <Component name="BlogPage">
136 |   <VStack width="{$props.width ? $props.width : '85%'}">
137 |     <VStack gap="0">
138 |       <H1>{$props.post.title}</H1>
139 |       <Text>{$props.post.date} - {$props.post.author}</Text>
140 |     </VStack>
141 |     <Image src="/blog/images/{$props.post.image}" />
142 |     <Markdown marginTop="$space-4" data="/blog/{$props.post.slug}.md" />
143 |   </VStack>
144 | </Component>
145 | ```
146 | 
147 | Now we write post metadata as an App-level variable, and create Markdown files corresponding to the slugs. In this case the files are `xmlui-powered-blog.md` (this post) and `lorem-ipsum.md` (a dummy older post). We also add a hero image for each post.
148 | 
149 | ```xmlui copy
150 | <App
151 |   layout="vertical"
152 |   var.posts = `{[
153 |     {
154 |       title: "Welcome to the XMLUI blog!",
155 |       slug: "xmlui-powered-blog",
156 |       author: "Jon Udell",
157 |       date: "2025-09-01",
158 |       image: "blog-scrabble.png"
159 |     },
160 |     {
161 |       title: "Lorem Ipsum!",
162 |       slug: "lorem-ipsum",
163 |       author: "H. Rackham",
164 |       date: "1914-06-03",
165 |       image: "lorem-ipsum.png"
166 |     }
167 |   ]}`
168 | >
169 | ```
170 | 
171 | The blog's `NavGroup` now looks like this. We'll maintain reverse chronology by just writing the `NavLink`s in that order.
172 | 
173 | ```xmlui copy
174 | <NavGroup label="Blog">
175 |   <NavLink label="{posts[0].title}" to="/blog/{posts[0].slug}" />
176 |   <NavLink label="{posts[1].title}" to="/blog/{posts[1].slug}" />
177 | </NavGroup>
178 | ```
179 | 
180 | The `NavLink` uses the post's slug to bind to its corresponding `Page`.
181 | 
182 | ```xmlui copy
183 | <Page url="/blog/{posts[0].slug}">
184 |   <BlogPage post="{posts[0]}" />
185 | </Page>
186 | ```
187 | 
188 | And the `Page` passes the complete post object to `BlogPage`. In v1 we used the `content` property of the `Markdown` component to pass a string. In v2 we use the `data` property to pass a URL constructed from the post slug.
189 | 
190 | ```xmlui copy {11}
191 | <Component name="BlogPage">
192 |   <VStack width="{$props.width ? $props.width : '85%'}">
193 |     <VStack>
194 |       <H1>{$props.post.title}</H1>
195 |       <HStack gap="$space-2">
196 |         <Text>{$props.post.date}</Text>
197 |         <Text> - </Text>
198 |         <Text>{$props.post.author}</Text>
199 |       </HStack>
200 |     </VStack>
201 |     <Markdown data="/blog/{$props.post.slug}.md" />
202 |   </VStack>
203 | </Component>
204 | ```
205 | 
206 | ## Create the overview page
207 | 
208 | Although we have a `NavGroup` to list the posts, a blog should really have an overview page. Let's add another user-defined component for that.
209 | 
210 | ```xmlui copy
211 | <Component name="BlogOverview">
212 |   <CVStack>
213 |     <VStack width="100%">
214 |       <H1>XMLUI Blog</H1>
215 |       <Text>Latest updates, tutorials, and insights for building with XMLUI</Text>
216 |       <List data="{
217 |         $props.posts.sort(function(a, b) {
218 |           return new Date(b.date) - new Date(a.date);
219 |         })
220 |       }">
221 |         <VStack gap="$space-2">
222 |           <Link to="/blog/{$item.slug}">
223 |             <Text fontSize="larger">
224 |               {$item.title}
225 |             </Text>
226 |           </Link>
227 |           <Text>
228 |             {$item.date} • {$item.author}
229 |           </Text>
230 |           <Link to="/blog/{$item.slug}">
231 |             <Image src="/blog/images/{$item.image}" />
232 |           </Link>
233 |           <Stack height="$space-8" />
234 |         </VStack>
235 |       </List>
236 |     </VStack>
237 |   </CVStack>
238 | </Component>
239 | ```
240 | 
241 | The `NavGroup` now just becomes a `NavLink`.
242 | 
243 | ```xmlui copy
244 | <NavLink label="Blog" to="/blog" />
245 | ```
246 | 
247 | We refer to the overview in `Pages` along with the same `Page` used for the intro post.
248 | 
249 | ```xmlui copy
250 | <Page url="/blog">
251 |     <BlogOverview posts="{posts}" />
252 | </Page>
253 | <Page url="/blog/{posts[0].slug}">
254 |     <BlogPage post="{posts[0]}" />
255 | </Page>
256 | ```
257 | 
258 | ## Create an RSS feed
259 | 
260 | We can't call it a blog unless it provides an RSS feed. For that we've added a simple feed generator that reads the metadata and writes `/feed.rss` which is then served statically by the webserver that hosts the site. So we've added a RSS icon to the template and feed autodiscovery to the site's `index.html`.
261 | 
262 | ## Deploy standalone
263 | 
264 | Our blog lives in the XMLUI monorepo where it coordinates with the landing page and docs.
265 | But it can exist standalone, you only need a folder with a handful of files.
266 | 
267 | 
268 | ```
269 | 
270 | ├── Main.xmlui
271 | ├── blog
272 | │   ├── images
273 | │   │   ├── blog-scrabble.png
274 | │   │   └── lorem-ipsum.png
275 | │   ├── lorem-ipsum.md
276 | │   └── xmlui-powered-blog.md
277 | ├── components
278 | │   ├── BlogOverview.xmlui
279 | │   ├── BlogPage.xmlui
280 | ├── index.html
281 | └── xmlui
282 |     └── 0.10.24.js
283 | ```
284 | 
285 | Here's the `index.html`.
286 | 
287 | ```xmlui copy
288 | <!DOCTYPE html>
289 | <html lang="en">
290 | <head>
291 |   <meta charset="UTF-8" />
292 |   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
293 |   <title>XMLUI blog test</title>
294 |   <script src="xmlui/0.10.24.js"></script>
295 | </head>
296 | <body>
297 | </body>
298 | </html>
299 | ```
300 | 
301 | I dragged the folder containing the standalone app onto Netlify's drop target. Check it out!
302 | 
303 | [https://test-xmlui-blog.netlify.app/](https://test-xmlui-blog.netlify.app/)
304 | 
305 | ## XMLUI for publishing
306 | 
307 | We get it, blog engines are a dime a dozen. We made this one because XMLUI was already a strong publishing system that we use for the [docs](https://docs.xmlui.org), [demo](https://demo.xmlui.org), and [landing page](https://xmlui.org). The `Markdown` component, with its support for playgrounds, works really well and it made sense to leverage that for our blog. We're not saying that you *should* build a blog engine with XMLUI but it's clearly something you *could* do. We think it's pretty easy to create a competent engine that makes life easy for authors and readers.
308 | 
309 | 
```

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

```markdown
  1 | %-DESC-START
  2 | 
  3 | **Essential features:**
  4 | 
  5 | - **Layout templates**: Choose from 7 predefined layouts (horizontal, vertical, condensed, etc.) with sticky navigation options
  6 | - **Routing**: Built-in page routing via the [Pages](/components/Pages) component
  7 | 
  8 | %-DESC-END
  9 | 
 10 | %-PROP-START layout
 11 | 
 12 | Here are a few samples demonstrating the usage of the `layout` property. All samples use this markup, except the value of `App`'s layout and a few marked code snippets:
 13 | 
 14 | ```xmlui
 15 | <App layout="(specific layout value)">
 16 |   <!-- AppHeader omitted for "vertical" and "vertical-sticky" -->
 17 |   <AppHeader>
 18 |     <property name="logoTemplate">
 19 |       <Heading level="h3" value="Example App"/>
 20 |     </property>
 21 |   </AppHeader>
 22 |   <NavPanel>
 23 |     <NavLink label="Home" to="/" icon="home"/>
 24 |     <NavLink label="Page 1" to="/page1"/>
 25 |     <NavLink label="Page 2" to="/page2"/>
 26 |   </NavPanel>
 27 |   <Pages fallbackPath="/">
 28 |     <Page url="/">
 29 |       <List data="https://api.spacexdata.com/v3/history">
 30 |         <property name="itemTemplate">
 31 |           <Card title="{$item.title}" subtitle="{$item.details}"/>
 32 |         </property>
 33 |       </List>
 34 |     </Page>
 35 |     <Page url="/page1">
 36 |       <Text value="Page 1" />
 37 |     </Page>
 38 |     <Page url="/page2">
 39 |       <Text value="Page 2" />
 40 |     </Page>
 41 |   </Pages>
 42 |   <Footer>Powered by XMLUI</Footer>
 43 | </App>
 44 | ```
 45 | 
 46 | #### `horizontal`
 47 | 
 48 | ```xmlui-pg copy name="Example: 'horizontal' layout" height="350px"
 49 | <App layout="horizontal">
 50 |   <AppHeader>
 51 |     <property name="logoTemplate">
 52 |       <Heading level="h3" value="Example App"/>
 53 |     </property>
 54 |   </AppHeader>
 55 |   <NavPanel>
 56 |       <NavLink label="Home" to="/" icon="home"/>
 57 |       <NavLink label="Page 1" to="/page1"/>
 58 |       <NavLink label="Page 2" to="/page2"/>
 59 |   </NavPanel>
 60 |   <Pages fallbackPath="/">
 61 |       <Page url="/">
 62 |         <List data="https://api.spacexdata.com/v3/history">
 63 |           <property name="itemTemplate">
 64 |             <Card title="{$item.title}" subtitle="{$item.details}"/>
 65 |           </property>
 66 |         </List>
 67 |       </Page>
 68 |       <Page url="/page1">
 69 |         <Text value="Page 1" />
 70 |       </Page>
 71 |       <Page url="/page2">
 72 |         <Text value="Page 2" />
 73 |       </Page>
 74 |   </Pages>
 75 |   <Footer>Powered by XMLUI</Footer>
 76 | </App>
 77 | ```
 78 | 
 79 | #### `horizontal-sticky`
 80 | 
 81 | ```xmlui-pg copy name="Example: 'horizontal-sticky' layout" height="350px"
 82 | <App layout="horizontal-sticky">
 83 |   <AppHeader>
 84 |     <property name="logoTemplate">
 85 |       <Heading level="h3" value="Example App"/>
 86 |     </property>
 87 |   </AppHeader>
 88 |   <NavPanel>
 89 |       <NavLink label="Home" to="/" icon="home"/>
 90 |       <NavLink label="Page 1" to="/page1"/>
 91 |       <NavLink label="Page 2" to="/page2"/>
 92 |   </NavPanel>
 93 |   <Pages fallbackPath="/">
 94 |       <Page url="/">
 95 |         <List data="https://api.spacexdata.com/v3/history">
 96 |           <property name="itemTemplate">
 97 |             <Card title="{$item.title}" subtitle="{$item.details}"/>
 98 |           </property>
 99 |         </List>
100 |       </Page>
101 |       <Page url="/page1">
102 |         <Text value="Page 1" />
103 |       </Page>
104 |       <Page url="/page2">
105 |         <Text value="Page 2" />
106 |       </Page>
107 |   </Pages>
108 |   <Footer>Powered by XMLUI</Footer>
109 | </App>
110 | ```
111 | 
112 | #### `condensed`
113 | 
114 | ```xmlui-pg copy name="Example: 'condensed' layout" height="350px"
115 | <App layout="condensed">
116 |   <property name="logoTemplate">
117 |     <Heading level="h3" value="Example App"/>
118 |   </property>
119 |   <NavPanel>
120 |       <NavLink label="Home" to="/" icon="home"/>
121 |       <NavLink label="Page 1" to="/page1"/>
122 |       <NavLink label="Page 2" to="/page2"/>
123 |   </NavPanel>
124 |   <Pages fallbackPath="/">
125 |       <Page url="/">
126 |         <List data="https://api.spacexdata.com/v3/history">
127 |           <property name="itemTemplate">
128 |             <Card title="{$item.title}" subtitle="{$item.details}"/>
129 |           </property>
130 |         </List>
131 |       </Page>
132 |       <Page url="/page1">
133 |         <Text value="Page 1" />
134 |       </Page>
135 |       <Page url="/page2">
136 |         <Text value="Page 2" />
137 |       </Page>
138 |   </Pages>
139 |   <Footer>Powered by XMLUI</Footer>
140 | </App>
141 | ```
142 | 
143 | #### `condensed-sticky`
144 | 
145 | ```xmlui-pg copy name="Example: 'condensed-sticky' layout" height="350px"
146 | <App layout="condensed-sticky">
147 |   <property name="logoTemplate">
148 |       <Heading level="h3" value="Example App"/>
149 |   </property>
150 |   <NavPanel>
151 |       <NavLink label="Home" to="/" icon="home"/>
152 |       <NavLink label="Page 1" to="/page1"/>
153 |       <NavLink label="Page 2" to="/page2"/>
154 |   </NavPanel>
155 |   <Pages fallbackPath="/">
156 |       <Page url="/">
157 |         <List data="https://api.spacexdata.com/v3/history">
158 |           <property name="itemTemplate">
159 |             <Card title="{$item.title}" subtitle="{$item.details}"/>
160 |           </property>
161 |         </List>
162 |       </Page>
163 |       <Page url="/page1">
164 |         <Text value="Page 1" />
165 |       </Page>
166 |       <Page url="/page2">
167 |         <Text value="Page 2" />
168 |       </Page>
169 |   </Pages>
170 |   <Footer>Powered by XMLUI</Footer>
171 | </App>
172 | ```
173 | 
174 | #### `vertical`
175 | 
176 | ```xmlui-pg copy name="Example: 'vertical' layout" height="300px"
177 | <App layout="vertical">
178 |   <property name="logoTemplate">
179 |     <Heading level="h3" value="Example App"/>
180 |   </property>
181 |   <NavPanel>
182 |     <NavLink label="Home" to="/" icon="home"/>
183 |     <NavLink label="Page 1" to="/page1"/>
184 |     <NavLink label="Page 2" to="/page2"/>
185 |   </NavPanel>
186 |   <Pages fallbackPath="/">
187 |       <Page url="/">
188 |         <List data="https://api.spacexdata.com/v3/history">
189 |           <property name="itemTemplate">
190 |             <Card title="{$item.title}" subtitle="{$item.details}"/>
191 |           </property>
192 |         </List>
193 |       </Page>
194 |       <Page url="/page1">
195 |         <Text value="Page 1" />
196 |       </Page>
197 |       <Page url="/page2">
198 |         <Text value="Page 2" />
199 |       </Page>
200 |   </Pages>
201 |   <Footer>Powered by XMLUI</Footer>
202 | </App>
203 | ```
204 | 
205 | #### `vertical-sticky`
206 | 
207 | ```xmlui-pg copy name="Example: 'vertical-sticky' layout" height="300px"
208 | <App layout="vertical-sticky">
209 |   <property name="logoTemplate">
210 |     <Heading level="h3" value="Example App"/>
211 |   </property>
212 |   <NavPanel>
213 |       <NavLink label="Home" to="/" icon="home"/>
214 |       <NavLink label="Page 1" to="/page1"/>
215 |       <NavLink label="Page 2" to="/page2"/>
216 |   </NavPanel>
217 |   <Pages fallbackPath="/">
218 |       <Page url="/">
219 |         <List data="https://api.spacexdata.com/v3/history">
220 |           <property name="itemTemplate">
221 |             <Card title="{$item.title}" subtitle="{$item.details}"/>
222 |           </property>
223 |         </List>
224 |       </Page>
225 |       <Page url="/page1">
226 |         <Text value="Page 1" />
227 |       </Page>
228 |       <Page url="/page2">
229 |         <Text value="Page 2" />
230 |       </Page>
231 |   </Pages>
232 |   <Footer>Powered by XMLUI</Footer>
233 | </App>
234 | ```
235 | 
236 | #### `vertical-full-header`
237 | 
238 | ```xmlui-pg copy name="Example: 'vertical-full-header' layout" height="300px"
239 | <App layout="vertical-full-header">
240 |   <AppHeader>
241 |     <property name="logoTemplate">
242 |         <Heading level="h3" value="Example App"/>
243 |     </property>
244 |   </AppHeader>
245 |   <NavPanel>
246 |       <NavLink label="Home" to="/" icon="home"/>
247 |       <NavLink label="Page 1" to="/page1"/>
248 |       <NavLink label="Page 2" to="/page2"/>
249 |   </NavPanel>
250 |   <Pages fallbackPath="/">
251 |       <Page url="/">
252 |         <List data="https://api.spacexdata.com/v3/history">
253 |           <property name="itemTemplate">
254 |             <Card title="{$item.title}" subtitle="{$item.details}"/>
255 |           </property>
256 |         </List>
257 |       </Page>
258 |       <Page url="/page1">
259 |         <Text value="Page 1" />
260 |       </Page>
261 |       <Page url="/page2">
262 |         <Text value="Page 2" />
263 |       </Page>
264 |   </Pages>
265 |   <Footer>Powered by XMLUI</Footer>
266 | </App>
267 | ```
268 | 
269 | %-PROP-END
270 | 
271 | %-PROP-START scrollWholePage
272 | 
273 | This boolean property specifies whether the whole page should scroll (true) or just the content area (false).
274 | The default value is `true`.
275 | 
276 | ```xmlui-pg copy display name="Example: scrollWholePage" height="150px"
277 | <App scrollWholePage="false">
278 |   <NavPanel>
279 |     <NavLink label="Home" to="/" icon="home"/>
280 |   </NavPanel>
281 |   <Pages fallbackPath="/">
282 |     <Page url="/">
283 |       <Text>
284 |         Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
285 |         Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
286 |         Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
287 |         Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
288 |       </Text>
289 |     </Page>
290 |   </Pages>
291 | </App>
292 | ```
293 | 
294 | %-PROP-END
295 | 
296 | %-PROP-START loggedInUser
297 | 
298 | Stores information about the currently logged in user.
299 | Currently, there is no restriction on what the user data must look like.
300 | 
301 | ```xmlui-pg copy display name="Example: loggedInUser" height="180px"
302 | <App loggedInUser="{{ name: 'Joe', token: '1234' }}">
303 |   <NavPanel>
304 |     <NavLink label="Home" to="/" icon="home"/>
305 |   </NavPanel>
306 |   <Pages fallbackPath="/">
307 |     <Page url="/">
308 |       <Text value="User name: {loggedInUser.name}" />
309 |       <Text value="User token: {loggedInUser.token}" />
310 |     </Page>
311 |   </Pages>
312 | </App>
313 | ```
314 | 
315 | %-PROP-END
316 | 
317 | %-EVENT-START ready
318 | 
319 | This event fires when the `App` component finishes rendering on the page.
320 | Use it as `onReady` when inlining it on the component.
321 | 
322 | ```xmlui-pg copy display name="Example: ready"
323 | <App onReady="isAppReady = true">
324 |   <variable name="isAppReady" value="{false}"/>
325 |   <Text value="{isAppReady ? 'App is ready' : 'Sadly, App is not ready'}" />
326 | </App>
327 | ```
328 | 
329 | %-EVENT-END
330 | 
331 | %-EVENT-START messageReceived
332 | 
333 | The event handler method has two parameters. The first is the message sent; the second is the entire native event object.
334 | 
335 | ```xmlui-pg copy display name="Example: messageReceived" /onMessageReceived/ /window.postMessage/
336 | <App 
337 |   var.message = "<none>" 
338 |   onMessageReceived="(msg, ev) => {
339 |     message = JSON.stringify(msg);
340 |     console.log('Message event received:', ev);
341 |   }">
342 |   <Button label="Send a message"
343 |     onClick="window.postMessage({type: 'message', messages:'Here you are!'})" />
344 |   <Text>Message received: {message}</Text>
345 | </App>
346 | ```
347 | 
348 | %-EVENT-END
```
Page 51/186FirstPrevNextLast