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

# Directory Structure

```
├── .changeset
│   ├── config.json
│   └── itchy-cases-deny.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.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.module.scss
│   │       │   ├── Preview.tsx
│   │       │   ├── Select.module.scss
│   │       │   ├── StandalonePlayground.tsx
│   │       │   ├── StandalonePlaygroundNative.module.scss
│   │       │   ├── StandalonePlaygroundNative.tsx
│   │       │   ├── ThemeSwitcher.module.scss
│   │       │   ├── ThemeSwitcher.tsx
│   │       │   ├── ToneSwitcher.tsx
│   │       │   ├── Tooltip.module.scss
│   │       │   ├── Tooltip.tsx
│   │       │   └── utils.ts
│   │       ├── providers
│   │       │   ├── Toast.module.scss
│   │       │   └── ToastProvider.tsx
│   │       ├── state
│   │       │   └── store.ts
│   │       ├── themes
│   │       │   └── theme.ts
│   │       └── utils
│   │           └── helpers.ts
│   ├── xmlui-search
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── demo
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   └── src
│   │       ├── index.tsx
│   │       ├── Search.module.scss
│   │       └── Search.tsx
│   ├── xmlui-spreadsheet
│   │   ├── .gitignore
│   │   ├── demo
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   └── src
│   │       ├── index.tsx
│   │       ├── Spreadsheet.tsx
│   │       └── SpreadsheetNative.tsx
│   └── xmlui-website-blocks
│       ├── .gitignore
│       ├── CHANGELOG.md
│       ├── demo
│       │   ├── components
│       │   │   ├── HeroBackgroundBreakoutPage.xmlui
│       │   │   ├── HeroBackgroundsPage.xmlui
│       │   │   ├── HeroContentsPage.xmlui
│       │   │   ├── HeroTextAlignPage.xmlui
│       │   │   ├── HeroTextPage.xmlui
│       │   │   └── HeroTonesPage.xmlui
│       │   ├── Main.xmlui
│       │   └── themes
│       │       └── default.ts
│       ├── index.html
│       ├── index.ts
│       ├── meta
│       │   └── componentsMetadata.ts
│       ├── package.json
│       ├── public
│       │   └── resources
│       │       ├── building.jpg
│       │       └── xmlui-logo.svg
│       └── src
│           ├── Carousel
│           │   ├── Carousel.module.scss
│           │   ├── Carousel.tsx
│           │   ├── CarouselContext.tsx
│           │   └── CarouselNative.tsx
│           ├── FancyButton
│           │   ├── FancyButton.module.scss
│           │   ├── FancyButton.tsx
│           │   └── FancyButton.xmlui
│           ├── Hello
│           │   ├── Hello.tsx
│           │   ├── Hello.xmlui
│           │   └── Hello.xmlui.xs
│           ├── HeroSection
│           │   ├── HeroSection.module.scss
│           │   ├── HeroSection.spec.ts
│           │   ├── HeroSection.tsx
│           │   └── HeroSectionNative.tsx
│           ├── index.tsx
│           ├── ScrollToTop
│           │   ├── ScrollToTop.module.scss
│           │   ├── ScrollToTop.tsx
│           │   └── ScrollToTopNative.tsx
│           └── vite-env.d.ts
├── playwright.config.ts
├── README.md
├── tools
│   ├── codefence
│   │   └── xmlui-code-fence-docs.md
│   ├── create-app
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── create-app.ts
│   │   ├── helpers
│   │   │   ├── copy.ts
│   │   │   ├── get-pkg-manager.ts
│   │   │   ├── git.ts
│   │   │   ├── install.ts
│   │   │   ├── is-folder-empty.ts
│   │   │   ├── is-writeable.ts
│   │   │   ├── make-dir.ts
│   │   │   └── validate-pkg.ts
│   │   ├── index.ts
│   │   ├── package.json
│   │   ├── templates
│   │   │   ├── default
│   │   │   │   └── ts
│   │   │   │       ├── gitignore
│   │   │   │       ├── index.html
│   │   │   │       ├── index.ts
│   │   │   │       ├── public
│   │   │   │       │   ├── mockServiceWorker.js
│   │   │   │       │   ├── resources
│   │   │   │       │   │   ├── favicon.ico
│   │   │   │       │   │   └── xmlui-logo.svg
│   │   │   │       │   └── serve.json
│   │   │   │       └── src
│   │   │   │           ├── components
│   │   │   │           │   ├── ApiAware.xmlui
│   │   │   │           │   ├── Home.xmlui
│   │   │   │           │   ├── IncButton.xmlui
│   │   │   │           │   └── PagePanel.xmlui
│   │   │   │           ├── config.ts
│   │   │   │           └── Main.xmlui
│   │   │   ├── index.ts
│   │   │   └── types.ts
│   │   └── tsconfig.json
│   ├── create-xmlui-hello-world
│   │   ├── index.js
│   │   └── package.json
│   └── vscode
│       ├── .gitignore
│       ├── .vscode
│       │   ├── launch.json
│       │   └── tasks.json
│       ├── .vscodeignore
│       ├── build.sh
│       ├── CHANGELOG.md
│       ├── esbuild.js
│       ├── eslint.config.mjs
│       ├── formatter-docs.md
│       ├── generate-test-sample.sh
│       ├── LICENSE.md
│       ├── package-lock.json
│       ├── package.json
│       ├── README.md
│       ├── resources
│       │   ├── xmlui-logo.png
│       │   └── xmlui-markup-syntax-highlighting.png
│       ├── src
│       │   ├── extension.ts
│       │   └── server.ts
│       ├── syntaxes
│       │   └── xmlui.tmLanguage.json
│       ├── test-samples
│       │   └── sample.xmlui
│       ├── tsconfig.json
│       └── tsconfig.tsbuildinfo
├── turbo.json
└── xmlui
    ├── .gitignore
    ├── bin
    │   ├── bootstrap.cjs
    │   ├── bootstrap.js
    │   ├── build-lib.ts
    │   ├── build.ts
    │   ├── index.ts
    │   ├── preview.ts
    │   ├── start.ts
    │   ├── vite-xmlui-plugin.ts
    │   └── viteConfig.ts
    ├── CHANGELOG.md
    ├── conventions
    │   ├── component-qa-checklist.md
    │   ├── copilot-conventions.md
    │   ├── create-xmlui-components.md
    │   ├── mermaid.md
    │   ├── testing-conventions.md
    │   └── xmlui-in-a-nutshell.md
    ├── dev-docs
    │   ├── accessibility.md
    │   ├── build-system.md
    │   ├── build-xmlui.md
    │   ├── component-behaviors.md
    │   ├── component-metadata.md
    │   ├── components-with-options.md
    │   ├── containers.md
    │   ├── data-operations.md
    │   ├── glossary.md
    │   ├── index.md
    │   ├── next
    │   │   ├── component-dev-guide.md
    │   │   ├── configuration-management-enhancement-summary.md
    │   │   ├── documentation-scripts-refactoring-complete-summary.md
    │   │   ├── documentation-scripts-refactoring-plan.md
    │   │   ├── duplicate-pattern-extraction-summary.md
    │   │   ├── error-handling-standardization-summary.md
    │   │   ├── generating-component-reference.md
    │   │   ├── index.md
    │   │   ├── logging-consistency-implementation-summary.md
    │   │   ├── project-build.md
    │   │   ├── project-structure.md
    │   │   ├── theme-context.md
    │   │   ├── tiptap-design-considerations.md
    │   │   ├── working-with-code.md
    │   │   ├── xmlui-runtime-architecture
    │   │   └── xmlui-wcag-accessibility-report.md
    │   ├── react-fundamentals.md
    │   ├── release-method.md
    │   ├── standalone-app.md
    │   ├── theme-variables-refactoring.md
    │   ├── ud-components.md
    │   └── xmlui-repo.md
    ├── package.json
    ├── scripts
    │   ├── coverage-only.js
    │   ├── e2e-test-summary.js
    │   ├── extract-component-metadata.js
    │   ├── generate-docs
    │   │   ├── build-downloads-map.mjs
    │   │   ├── build-pages-map.mjs
    │   │   ├── components-config.json
    │   │   ├── configuration-management.mjs
    │   │   ├── constants.mjs
    │   │   ├── create-theme-files.mjs
    │   │   ├── DocsGenerator.mjs
    │   │   ├── error-handling.mjs
    │   │   ├── extensions-config.json
    │   │   ├── folders.mjs
    │   │   ├── generate-summary-files.mjs
    │   │   ├── get-docs.mjs
    │   │   ├── input-handler.mjs
    │   │   ├── logger.mjs
    │   │   ├── logging-standards.mjs
    │   │   ├── MetadataProcessor.mjs
    │   │   ├── pattern-utilities.mjs
    │   │   └── utils.mjs
    │   ├── generate-metadata-markdown.js
    │   ├── get-langserver-metadata.js
    │   ├── inline-links.mjs
    │   └── README-e2e-summary.md
    ├── src
    │   ├── abstractions
    │   │   ├── _conventions.md
    │   │   ├── ActionDefs.ts
    │   │   ├── AppContextDefs.ts
    │   │   ├── ComponentDefs.ts
    │   │   ├── ContainerDefs.ts
    │   │   ├── ExtensionDefs.ts
    │   │   ├── FunctionDefs.ts
    │   │   ├── RendererDefs.ts
    │   │   ├── scripting
    │   │   │   ├── BlockScope.ts
    │   │   │   ├── Compilation.ts
    │   │   │   ├── LogicalThread.ts
    │   │   │   ├── LoopScope.ts
    │   │   │   ├── modules.ts
    │   │   │   ├── ScriptParserError.ts
    │   │   │   ├── Token.ts
    │   │   │   ├── TryScope.ts
    │   │   │   └── TryScopeExp.ts
    │   │   └── ThemingDefs.ts
    │   ├── components
    │   │   ├── _conventions.md
    │   │   ├── abstractions.ts
    │   │   ├── Accordion
    │   │   │   ├── Accordion.md
    │   │   │   ├── Accordion.module.scss
    │   │   │   ├── Accordion.spec.ts
    │   │   │   ├── Accordion.tsx
    │   │   │   ├── AccordionContext.tsx
    │   │   │   ├── AccordionItem.tsx
    │   │   │   ├── AccordionItemNative.tsx
    │   │   │   └── AccordionNative.tsx
    │   │   ├── Animation
    │   │   │   └── AnimationNative.tsx
    │   │   ├── APICall
    │   │   │   ├── APICall.md
    │   │   │   ├── APICall.spec.ts
    │   │   │   ├── APICall.tsx
    │   │   │   └── APICallNative.tsx
    │   │   ├── App
    │   │   │   ├── App.md
    │   │   │   ├── App.module.scss
    │   │   │   ├── App.spec.ts
    │   │   │   ├── App.tsx
    │   │   │   ├── AppLayoutContext.ts
    │   │   │   ├── AppNative.tsx
    │   │   │   ├── AppStateContext.ts
    │   │   │   ├── doc-resources
    │   │   │   │   ├── condensed-sticky.xmlui
    │   │   │   │   ├── condensed.xmlui
    │   │   │   │   ├── horizontal-sticky.xmlui
    │   │   │   │   ├── horizontal.xmlui
    │   │   │   │   ├── vertical-full-header.xmlui
    │   │   │   │   ├── vertical-sticky.xmlui
    │   │   │   │   └── vertical.xmlui
    │   │   │   ├── IndexerContext.ts
    │   │   │   ├── LinkInfoContext.ts
    │   │   │   ├── SearchContext.tsx
    │   │   │   ├── Sheet.module.scss
    │   │   │   └── Sheet.tsx
    │   │   ├── AppHeader
    │   │   │   ├── AppHeader.md
    │   │   │   ├── AppHeader.module.scss
    │   │   │   ├── AppHeader.spec.ts
    │   │   │   ├── AppHeader.tsx
    │   │   │   └── AppHeaderNative.tsx
    │   │   ├── AppState
    │   │   │   ├── AppState.md
    │   │   │   ├── AppState.spec.ts
    │   │   │   ├── AppState.tsx
    │   │   │   └── AppStateNative.tsx
    │   │   ├── AutoComplete
    │   │   │   ├── AutoComplete.md
    │   │   │   ├── AutoComplete.module.scss
    │   │   │   ├── AutoComplete.spec.ts
    │   │   │   ├── AutoComplete.tsx
    │   │   │   ├── AutoCompleteContext.tsx
    │   │   │   └── AutoCompleteNative.tsx
    │   │   ├── Avatar
    │   │   │   ├── Avatar.md
    │   │   │   ├── Avatar.module.scss
    │   │   │   ├── Avatar.spec.ts
    │   │   │   ├── Avatar.tsx
    │   │   │   └── AvatarNative.tsx
    │   │   ├── Backdrop
    │   │   │   ├── Backdrop.md
    │   │   │   ├── Backdrop.module.scss
    │   │   │   ├── Backdrop.spec.ts
    │   │   │   ├── Backdrop.tsx
    │   │   │   └── BackdropNative.tsx
    │   │   ├── Badge
    │   │   │   ├── Badge.md
    │   │   │   ├── Badge.module.scss
    │   │   │   ├── Badge.spec.ts
    │   │   │   ├── Badge.tsx
    │   │   │   └── BadgeNative.tsx
    │   │   ├── Bookmark
    │   │   │   ├── Bookmark.md
    │   │   │   ├── Bookmark.module.scss
    │   │   │   ├── Bookmark.spec.ts
    │   │   │   ├── Bookmark.tsx
    │   │   │   └── BookmarkNative.tsx
    │   │   ├── Breakout
    │   │   │   ├── Breakout.module.scss
    │   │   │   ├── Breakout.spec.ts
    │   │   │   ├── Breakout.tsx
    │   │   │   └── BreakoutNative.tsx
    │   │   ├── Button
    │   │   │   ├── Button-style.spec.ts
    │   │   │   ├── Button.md
    │   │   │   ├── Button.module.scss
    │   │   │   ├── Button.spec.ts
    │   │   │   ├── Button.tsx
    │   │   │   └── ButtonNative.tsx
    │   │   ├── Card
    │   │   │   ├── Card.md
    │   │   │   ├── Card.module.scss
    │   │   │   ├── Card.spec.ts
    │   │   │   ├── Card.tsx
    │   │   │   └── CardNative.tsx
    │   │   ├── Carousel
    │   │   │   ├── Carousel.md
    │   │   │   ├── Carousel.module.scss
    │   │   │   ├── Carousel.spec.ts
    │   │   │   ├── Carousel.tsx
    │   │   │   ├── CarouselContext.tsx
    │   │   │   ├── CarouselItem.tsx
    │   │   │   ├── CarouselItemNative.tsx
    │   │   │   └── CarouselNative.tsx
    │   │   ├── ChangeListener
    │   │   │   ├── ChangeListener.md
    │   │   │   ├── ChangeListener.spec.ts
    │   │   │   ├── ChangeListener.tsx
    │   │   │   └── ChangeListenerNative.tsx
    │   │   ├── chart-color-schemes.ts
    │   │   ├── Charts
    │   │   │   ├── AreaChart
    │   │   │   │   ├── AreaChart.md
    │   │   │   │   ├── AreaChart.spec.ts
    │   │   │   │   ├── AreaChart.tsx
    │   │   │   │   └── AreaChartNative.tsx
    │   │   │   ├── BarChart
    │   │   │   │   ├── BarChart.md
    │   │   │   │   ├── BarChart.module.scss
    │   │   │   │   ├── BarChart.spec.ts
    │   │   │   │   ├── BarChart.tsx
    │   │   │   │   └── BarChartNative.tsx
    │   │   │   ├── DonutChart
    │   │   │   │   ├── DonutChart.spec.ts
    │   │   │   │   └── DonutChart.tsx
    │   │   │   ├── LabelList
    │   │   │   │   ├── LabelList.module.scss
    │   │   │   │   ├── LabelList.spec.ts
    │   │   │   │   ├── LabelList.tsx
    │   │   │   │   └── LabelListNative.tsx
    │   │   │   ├── Legend
    │   │   │   │   ├── Legend.spec.ts
    │   │   │   │   ├── Legend.tsx
    │   │   │   │   └── LegendNative.tsx
    │   │   │   ├── LineChart
    │   │   │   │   ├── LineChart.md
    │   │   │   │   ├── LineChart.module.scss
    │   │   │   │   ├── LineChart.spec.ts
    │   │   │   │   ├── LineChart.tsx
    │   │   │   │   └── LineChartNative.tsx
    │   │   │   ├── PieChart
    │   │   │   │   ├── PieChart.md
    │   │   │   │   ├── PieChart.spec.ts
    │   │   │   │   ├── PieChart.tsx
    │   │   │   │   ├── PieChartNative.module.scss
    │   │   │   │   └── PieChartNative.tsx
    │   │   │   ├── RadarChart
    │   │   │   │   ├── RadarChart.md
    │   │   │   │   ├── RadarChart.spec.ts
    │   │   │   │   ├── RadarChart.tsx
    │   │   │   │   └── RadarChartNative.tsx
    │   │   │   ├── Tooltip
    │   │   │   │   ├── TooltipContent.module.scss
    │   │   │   │   ├── TooltipContent.spec.ts
    │   │   │   │   └── TooltipContent.tsx
    │   │   │   └── utils
    │   │   │       ├── abstractions.ts
    │   │   │       └── ChartProvider.tsx
    │   │   ├── Checkbox
    │   │   │   ├── Checkbox.md
    │   │   │   ├── Checkbox.spec.ts
    │   │   │   └── Checkbox.tsx
    │   │   ├── CodeBlock
    │   │   │   ├── CodeBlock.module.scss
    │   │   │   ├── CodeBlock.spec.ts
    │   │   │   ├── CodeBlock.tsx
    │   │   │   ├── CodeBlockNative.tsx
    │   │   │   └── highlight-code.ts
    │   │   ├── collectedComponentMetadata.ts
    │   │   ├── ColorPicker
    │   │   │   ├── ColorPicker.md
    │   │   │   ├── ColorPicker.module.scss
    │   │   │   ├── ColorPicker.spec.ts
    │   │   │   ├── ColorPicker.tsx
    │   │   │   └── ColorPickerNative.tsx
    │   │   ├── Column
    │   │   │   ├── Column.md
    │   │   │   ├── Column.tsx
    │   │   │   ├── ColumnNative.tsx
    │   │   │   ├── doc-resources
    │   │   │   │   └── list-component-data.js
    │   │   │   └── TableContext.tsx
    │   │   ├── component-utils.ts
    │   │   ├── ComponentProvider.tsx
    │   │   ├── ComponentRegistryContext.tsx
    │   │   ├── container-helpers.tsx
    │   │   ├── ContentSeparator
    │   │   │   ├── ContentSeparator.md
    │   │   │   ├── ContentSeparator.module.scss
    │   │   │   ├── ContentSeparator.spec.ts
    │   │   │   ├── ContentSeparator.tsx
    │   │   │   └── ContentSeparatorNative.tsx
    │   │   ├── DataSource
    │   │   │   ├── DataSource.md
    │   │   │   └── DataSource.tsx
    │   │   ├── DateInput
    │   │   │   ├── DateInput.md
    │   │   │   ├── DateInput.module.scss
    │   │   │   ├── DateInput.spec.ts
    │   │   │   ├── DateInput.tsx
    │   │   │   └── DateInputNative.tsx
    │   │   ├── DatePicker
    │   │   │   ├── DatePicker.md
    │   │   │   ├── DatePicker.module.scss
    │   │   │   ├── DatePicker.spec.ts
    │   │   │   ├── DatePicker.tsx
    │   │   │   └── DatePickerNative.tsx
    │   │   ├── DropdownMenu
    │   │   │   ├── DropdownMenu.md
    │   │   │   ├── DropdownMenu.module.scss
    │   │   │   ├── DropdownMenu.spec.ts
    │   │   │   ├── DropdownMenu.tsx
    │   │   │   ├── DropdownMenuNative.tsx
    │   │   │   ├── MenuItem.md
    │   │   │   └── SubMenuItem.md
    │   │   ├── EmojiSelector
    │   │   │   ├── EmojiSelector.md
    │   │   │   ├── EmojiSelector.spec.ts
    │   │   │   ├── EmojiSelector.tsx
    │   │   │   └── EmojiSelectorNative.tsx
    │   │   ├── ExpandableItem
    │   │   │   ├── ExpandableItem.module.scss
    │   │   │   ├── ExpandableItem.spec.ts
    │   │   │   ├── ExpandableItem.tsx
    │   │   │   └── ExpandableItemNative.tsx
    │   │   ├── FileInput
    │   │   │   ├── FileInput.md
    │   │   │   ├── FileInput.module.scss
    │   │   │   ├── FileInput.spec.ts
    │   │   │   ├── FileInput.tsx
    │   │   │   └── FileInputNative.tsx
    │   │   ├── FileUploadDropZone
    │   │   │   ├── FileUploadDropZone.md
    │   │   │   ├── FileUploadDropZone.module.scss
    │   │   │   ├── FileUploadDropZone.spec.ts
    │   │   │   ├── FileUploadDropZone.tsx
    │   │   │   └── FileUploadDropZoneNative.tsx
    │   │   ├── FlowLayout
    │   │   │   ├── FlowLayout.md
    │   │   │   ├── FlowLayout.module.scss
    │   │   │   ├── FlowLayout.spec.ts
    │   │   │   ├── FlowLayout.spec.ts-snapshots
    │   │   │   │   └── Edge-cases-boxShadow-is-not-clipped-1-non-smoke-darwin.png
    │   │   │   ├── FlowLayout.tsx
    │   │   │   └── FlowLayoutNative.tsx
    │   │   ├── Footer
    │   │   │   ├── Footer.md
    │   │   │   ├── Footer.module.scss
    │   │   │   ├── Footer.spec.ts
    │   │   │   ├── Footer.tsx
    │   │   │   └── FooterNative.tsx
    │   │   ├── Form
    │   │   │   ├── Form.md
    │   │   │   ├── Form.module.scss
    │   │   │   ├── Form.spec.ts
    │   │   │   ├── Form.tsx
    │   │   │   ├── formActions.ts
    │   │   │   ├── FormContext.ts
    │   │   │   └── FormNative.tsx
    │   │   ├── FormItem
    │   │   │   ├── FormItem.md
    │   │   │   ├── FormItem.module.scss
    │   │   │   ├── FormItem.spec.ts
    │   │   │   ├── FormItem.tsx
    │   │   │   ├── FormItemNative.tsx
    │   │   │   ├── HelperText.module.scss
    │   │   │   ├── HelperText.tsx
    │   │   │   ├── ItemWithLabel.tsx
    │   │   │   └── Validations.ts
    │   │   ├── FormSection
    │   │   │   ├── FormSection.md
    │   │   │   ├── FormSection.ts
    │   │   │   └── FormSection.xmlui
    │   │   ├── Fragment
    │   │   │   ├── Fragment.spec.ts
    │   │   │   └── Fragment.tsx
    │   │   ├── Heading
    │   │   │   ├── abstractions.ts
    │   │   │   ├── H1.md
    │   │   │   ├── H1.spec.ts
    │   │   │   ├── H2.md
    │   │   │   ├── H2.spec.ts
    │   │   │   ├── H3.md
    │   │   │   ├── H3.spec.ts
    │   │   │   ├── H4.md
    │   │   │   ├── H4.spec.ts
    │   │   │   ├── H5.md
    │   │   │   ├── H5.spec.ts
    │   │   │   ├── H6.md
    │   │   │   ├── H6.spec.ts
    │   │   │   ├── Heading.md
    │   │   │   ├── Heading.module.scss
    │   │   │   ├── Heading.spec.ts
    │   │   │   ├── Heading.tsx
    │   │   │   └── HeadingNative.tsx
    │   │   ├── HoverCard
    │   │   │   ├── HoverCard.tsx
    │   │   │   └── HovercardNative.tsx
    │   │   ├── HtmlTags
    │   │   │   ├── HtmlTags.module.scss
    │   │   │   ├── HtmlTags.spec.ts
    │   │   │   └── HtmlTags.tsx
    │   │   ├── Icon
    │   │   │   ├── AdmonitionDanger.tsx
    │   │   │   ├── AdmonitionInfo.tsx
    │   │   │   ├── AdmonitionNote.tsx
    │   │   │   ├── AdmonitionTip.tsx
    │   │   │   ├── AdmonitionWarning.tsx
    │   │   │   ├── ApiIcon.tsx
    │   │   │   ├── ArrowDropDown.module.scss
    │   │   │   ├── ArrowDropDown.tsx
    │   │   │   ├── ArrowDropUp.module.scss
    │   │   │   ├── ArrowDropUp.tsx
    │   │   │   ├── ArrowLeft.module.scss
    │   │   │   ├── ArrowLeft.tsx
    │   │   │   ├── ArrowRight.module.scss
    │   │   │   ├── ArrowRight.tsx
    │   │   │   ├── Attach.tsx
    │   │   │   ├── Binding.module.scss
    │   │   │   ├── Binding.tsx
    │   │   │   ├── BoardIcon.tsx
    │   │   │   ├── BoxIcon.tsx
    │   │   │   ├── CheckIcon.tsx
    │   │   │   ├── ChevronDownIcon.tsx
    │   │   │   ├── ChevronLeft.tsx
    │   │   │   ├── ChevronRight.tsx
    │   │   │   ├── ChevronUpIcon.tsx
    │   │   │   ├── CodeFileIcon.tsx
    │   │   │   ├── CodeSandbox.tsx
    │   │   │   ├── CompactListIcon.tsx
    │   │   │   ├── ContentCopyIcon.tsx
    │   │   │   ├── DarkToLightIcon.tsx
    │   │   │   ├── DatabaseIcon.module.scss
    │   │   │   ├── DatabaseIcon.tsx
    │   │   │   ├── DocFileIcon.tsx
    │   │   │   ├── DocIcon.tsx
    │   │   │   ├── DotMenuHorizontalIcon.tsx
    │   │   │   ├── DotMenuIcon.tsx
    │   │   │   ├── EmailIcon.tsx
    │   │   │   ├── EmptyFolderIcon.tsx
    │   │   │   ├── ErrorIcon.tsx
    │   │   │   ├── ExpressionIcon.tsx
    │   │   │   ├── FillPlusCricleIcon.tsx
    │   │   │   ├── FilterIcon.tsx
    │   │   │   ├── FolderIcon.tsx
    │   │   │   ├── GlobeIcon.tsx
    │   │   │   ├── HomeIcon.tsx
    │   │   │   ├── HyperLinkIcon.tsx
    │   │   │   ├── Icon.md
    │   │   │   ├── Icon.module.scss
    │   │   │   ├── Icon.spec.ts
    │   │   │   ├── Icon.tsx
    │   │   │   ├── IconNative.tsx
    │   │   │   ├── ImageFileIcon.tsx
    │   │   │   ├── Inspect.tsx
    │   │   │   ├── LightToDark.tsx
    │   │   │   ├── LinkIcon.tsx
    │   │   │   ├── ListIcon.tsx
    │   │   │   ├── LooseListIcon.tsx
    │   │   │   ├── MoonIcon.tsx
    │   │   │   ├── MoreOptionsIcon.tsx
    │   │   │   ├── NoSortIcon.tsx
    │   │   │   ├── PDFIcon.tsx
    │   │   │   ├── PenIcon.tsx
    │   │   │   ├── PhoneIcon.tsx
    │   │   │   ├── PhotoIcon.tsx
    │   │   │   ├── PlusIcon.tsx
    │   │   │   ├── SearchIcon.tsx
    │   │   │   ├── ShareIcon.tsx
    │   │   │   ├── SortAscendingIcon.tsx
    │   │   │   ├── SortDescendingIcon.tsx
    │   │   │   ├── StarsIcon.tsx
    │   │   │   ├── SunIcon.tsx
    │   │   │   ├── svg
    │   │   │   │   ├── admonition_danger.svg
    │   │   │   │   ├── admonition_info.svg
    │   │   │   │   ├── admonition_note.svg
    │   │   │   │   ├── admonition_tip.svg
    │   │   │   │   ├── admonition_warning.svg
    │   │   │   │   ├── api.svg
    │   │   │   │   ├── arrow-dropdown.svg
    │   │   │   │   ├── arrow-left.svg
    │   │   │   │   ├── arrow-right.svg
    │   │   │   │   ├── arrow-up.svg
    │   │   │   │   ├── attach.svg
    │   │   │   │   ├── binding.svg
    │   │   │   │   ├── box.svg
    │   │   │   │   ├── bulb.svg
    │   │   │   │   ├── code-file.svg
    │   │   │   │   ├── code-sandbox.svg
    │   │   │   │   ├── dark_to_light.svg
    │   │   │   │   ├── database.svg
    │   │   │   │   ├── doc.svg
    │   │   │   │   ├── empty-folder.svg
    │   │   │   │   ├── expression.svg
    │   │   │   │   ├── eye-closed.svg
    │   │   │   │   ├── eye-dark.svg
    │   │   │   │   ├── eye.svg
    │   │   │   │   ├── file-text.svg
    │   │   │   │   ├── filter.svg
    │   │   │   │   ├── folder.svg
    │   │   │   │   ├── img.svg
    │   │   │   │   ├── inspect.svg
    │   │   │   │   ├── light_to_dark.svg
    │   │   │   │   ├── moon.svg
    │   │   │   │   ├── pdf.svg
    │   │   │   │   ├── photo.svg
    │   │   │   │   ├── share.svg
    │   │   │   │   ├── stars.svg
    │   │   │   │   ├── sun.svg
    │   │   │   │   ├── trending-down.svg
    │   │   │   │   ├── trending-level.svg
    │   │   │   │   ├── trending-up.svg
    │   │   │   │   ├── txt.svg
    │   │   │   │   ├── unknown-file.svg
    │   │   │   │   ├── unlink.svg
    │   │   │   │   └── xls.svg
    │   │   │   ├── TableDeleteColumnIcon.tsx
    │   │   │   ├── TableDeleteRowIcon.tsx
    │   │   │   ├── TableInsertColumnIcon.tsx
    │   │   │   ├── TableInsertRowIcon.tsx
    │   │   │   ├── TrashIcon.tsx
    │   │   │   ├── TrendingDownIcon.tsx
    │   │   │   ├── TrendingLevelIcon.tsx
    │   │   │   ├── TrendingUpIcon.tsx
    │   │   │   ├── TxtIcon.tsx
    │   │   │   ├── UnknownFileIcon.tsx
    │   │   │   ├── UnlinkIcon.tsx
    │   │   │   ├── UserIcon.tsx
    │   │   │   ├── WarningIcon.tsx
    │   │   │   └── XlsIcon.tsx
    │   │   ├── IconProvider.tsx
    │   │   ├── IconRegistryContext.tsx
    │   │   ├── IFrame
    │   │   │   ├── IFrame.md
    │   │   │   ├── IFrame.module.scss
    │   │   │   ├── IFrame.spec.ts
    │   │   │   ├── IFrame.tsx
    │   │   │   └── IFrameNative.tsx
    │   │   ├── Image
    │   │   │   ├── Image.md
    │   │   │   ├── Image.module.scss
    │   │   │   ├── Image.spec.ts
    │   │   │   ├── Image.tsx
    │   │   │   └── ImageNative.tsx
    │   │   ├── Input
    │   │   │   ├── index.ts
    │   │   │   ├── InputAdornment.module.scss
    │   │   │   ├── InputAdornment.tsx
    │   │   │   ├── InputDivider.module.scss
    │   │   │   ├── InputDivider.tsx
    │   │   │   ├── InputLabel.module.scss
    │   │   │   ├── InputLabel.tsx
    │   │   │   ├── PartialInput.module.scss
    │   │   │   └── PartialInput.tsx
    │   │   ├── InspectButton
    │   │   │   ├── InspectButton.module.scss
    │   │   │   └── InspectButton.tsx
    │   │   ├── Items
    │   │   │   ├── Items.md
    │   │   │   ├── Items.spec.ts
    │   │   │   ├── Items.tsx
    │   │   │   └── ItemsNative.tsx
    │   │   ├── Link
    │   │   │   ├── Link.md
    │   │   │   ├── Link.module.scss
    │   │   │   ├── Link.spec.ts
    │   │   │   ├── Link.tsx
    │   │   │   └── LinkNative.tsx
    │   │   ├── List
    │   │   │   ├── doc-resources
    │   │   │   │   └── list-component-data.js
    │   │   │   ├── List.md
    │   │   │   ├── List.module.scss
    │   │   │   ├── List.spec.ts
    │   │   │   ├── List.tsx
    │   │   │   └── ListNative.tsx
    │   │   ├── Logo
    │   │   │   ├── doc-resources
    │   │   │   │   └── xmlui-logo.svg
    │   │   │   ├── Logo.md
    │   │   │   ├── Logo.tsx
    │   │   │   └── LogoNative.tsx
    │   │   ├── Markdown
    │   │   │   ├── CodeText.module.scss
    │   │   │   ├── CodeText.tsx
    │   │   │   ├── Markdown.md
    │   │   │   ├── Markdown.module.scss
    │   │   │   ├── Markdown.spec.ts
    │   │   │   ├── Markdown.tsx
    │   │   │   ├── MarkdownNative.tsx
    │   │   │   ├── parse-binding-expr.ts
    │   │   │   └── utils.ts
    │   │   ├── metadata-helpers.ts
    │   │   ├── ModalDialog
    │   │   │   ├── ConfirmationModalContextProvider.tsx
    │   │   │   ├── Dialog.module.scss
    │   │   │   ├── Dialog.tsx
    │   │   │   ├── ModalDialog.md
    │   │   │   ├── ModalDialog.module.scss
    │   │   │   ├── ModalDialog.spec.ts
    │   │   │   ├── ModalDialog.tsx
    │   │   │   ├── ModalDialogNative.tsx
    │   │   │   └── ModalVisibilityContext.tsx
    │   │   ├── NavGroup
    │   │   │   ├── NavGroup.md
    │   │   │   ├── NavGroup.module.scss
    │   │   │   ├── NavGroup.spec.ts
    │   │   │   ├── NavGroup.tsx
    │   │   │   ├── NavGroupContext.ts
    │   │   │   └── NavGroupNative.tsx
    │   │   ├── NavLink
    │   │   │   ├── NavLink.md
    │   │   │   ├── NavLink.module.scss
    │   │   │   ├── NavLink.spec.ts
    │   │   │   ├── NavLink.tsx
    │   │   │   └── NavLinkNative.tsx
    │   │   ├── NavPanel
    │   │   │   ├── NavPanel.md
    │   │   │   ├── NavPanel.module.scss
    │   │   │   ├── NavPanel.spec.ts
    │   │   │   ├── NavPanel.tsx
    │   │   │   └── NavPanelNative.tsx
    │   │   ├── NestedApp
    │   │   │   ├── AppWithCodeView.module.scss
    │   │   │   ├── AppWithCodeView.tsx
    │   │   │   ├── AppWithCodeViewNative.tsx
    │   │   │   ├── defaultProps.tsx
    │   │   │   ├── logo.svg
    │   │   │   ├── NestedApp.module.scss
    │   │   │   ├── NestedApp.tsx
    │   │   │   ├── NestedAppNative.tsx
    │   │   │   ├── Tooltip.module.scss
    │   │   │   ├── Tooltip.tsx
    │   │   │   └── utils.ts
    │   │   ├── NoResult
    │   │   │   ├── NoResult.md
    │   │   │   ├── NoResult.module.scss
    │   │   │   ├── NoResult.spec.ts
    │   │   │   ├── NoResult.tsx
    │   │   │   └── NoResultNative.tsx
    │   │   ├── NumberBox
    │   │   │   ├── numberbox-abstractions.ts
    │   │   │   ├── NumberBox.md
    │   │   │   ├── NumberBox.module.scss
    │   │   │   ├── NumberBox.spec.ts
    │   │   │   ├── NumberBox.tsx
    │   │   │   └── NumberBoxNative.tsx
    │   │   ├── Option
    │   │   │   ├── Option.md
    │   │   │   ├── Option.spec.ts
    │   │   │   ├── Option.tsx
    │   │   │   ├── OptionNative.tsx
    │   │   │   └── OptionTypeProvider.tsx
    │   │   ├── PageMetaTitle
    │   │   │   ├── PageMetaTilteNative.tsx
    │   │   │   ├── PageMetaTitle.md
    │   │   │   ├── PageMetaTitle.spec.ts
    │   │   │   └── PageMetaTitle.tsx
    │   │   ├── Pages
    │   │   │   ├── Page.md
    │   │   │   ├── Pages.md
    │   │   │   ├── Pages.module.scss
    │   │   │   ├── Pages.tsx
    │   │   │   └── PagesNative.tsx
    │   │   ├── Pagination
    │   │   │   ├── Pagination.md
    │   │   │   ├── Pagination.module.scss
    │   │   │   ├── Pagination.spec.ts
    │   │   │   ├── Pagination.tsx
    │   │   │   └── PaginationNative.tsx
    │   │   ├── PositionedContainer
    │   │   │   ├── PositionedContainer.module.scss
    │   │   │   ├── PositionedContainer.tsx
    │   │   │   └── PositionedContainerNative.tsx
    │   │   ├── ProfileMenu
    │   │   │   ├── ProfileMenu.module.scss
    │   │   │   └── ProfileMenu.tsx
    │   │   ├── ProgressBar
    │   │   │   ├── ProgressBar.md
    │   │   │   ├── ProgressBar.module.scss
    │   │   │   ├── ProgressBar.spec.ts
    │   │   │   ├── ProgressBar.tsx
    │   │   │   └── ProgressBarNative.tsx
    │   │   ├── Queue
    │   │   │   ├── Queue.md
    │   │   │   ├── Queue.spec.ts
    │   │   │   ├── Queue.tsx
    │   │   │   ├── queueActions.ts
    │   │   │   └── QueueNative.tsx
    │   │   ├── RadioGroup
    │   │   │   ├── RadioGroup.md
    │   │   │   ├── RadioGroup.module.scss
    │   │   │   ├── RadioGroup.spec.ts
    │   │   │   ├── RadioGroup.tsx
    │   │   │   ├── RadioGroupNative.tsx
    │   │   │   ├── RadioItem.tsx
    │   │   │   └── RadioItemNative.tsx
    │   │   ├── RealTimeAdapter
    │   │   │   ├── RealTimeAdapter.tsx
    │   │   │   └── RealTimeAdapterNative.tsx
    │   │   ├── Redirect
    │   │   │   ├── Redirect.md
    │   │   │   ├── Redirect.spec.ts
    │   │   │   └── Redirect.tsx
    │   │   ├── ResponsiveBar
    │   │   │   ├── README.md
    │   │   │   ├── ResponsiveBar.md
    │   │   │   ├── ResponsiveBar.module.scss
    │   │   │   ├── ResponsiveBar.spec.ts
    │   │   │   ├── ResponsiveBar.tsx
    │   │   │   └── ResponsiveBarNative.tsx
    │   │   ├── Select
    │   │   │   ├── HiddenOption.tsx
    │   │   │   ├── OptionContext.ts
    │   │   │   ├── Select.md
    │   │   │   ├── Select.module.scss
    │   │   │   ├── Select.spec.ts
    │   │   │   ├── Select.tsx
    │   │   │   ├── SelectContext.tsx
    │   │   │   └── SelectNative.tsx
    │   │   ├── SelectionStore
    │   │   │   ├── SelectionStore.md
    │   │   │   ├── SelectionStore.tsx
    │   │   │   └── SelectionStoreNative.tsx
    │   │   ├── Slider
    │   │   │   ├── Slider.md
    │   │   │   ├── Slider.module.scss
    │   │   │   ├── Slider.spec.ts
    │   │   │   ├── Slider.tsx
    │   │   │   └── SliderNative.tsx
    │   │   ├── Slot
    │   │   │   ├── Slot.md
    │   │   │   ├── Slot.spec.ts
    │   │   │   └── Slot.ts
    │   │   ├── SlotItem.tsx
    │   │   ├── SpaceFiller
    │   │   │   ├── SpaceFiller.md
    │   │   │   ├── SpaceFiller.module.scss
    │   │   │   ├── SpaceFiller.spec.ts
    │   │   │   ├── SpaceFiller.tsx
    │   │   │   └── SpaceFillerNative.tsx
    │   │   ├── Spinner
    │   │   │   ├── Spinner.md
    │   │   │   ├── Spinner.module.scss
    │   │   │   ├── Spinner.spec.ts
    │   │   │   ├── Spinner.tsx
    │   │   │   └── SpinnerNative.tsx
    │   │   ├── Splitter
    │   │   │   ├── HSplitter.md
    │   │   │   ├── HSplitter.spec.ts
    │   │   │   ├── Splitter.md
    │   │   │   ├── Splitter.module.scss
    │   │   │   ├── Splitter.spec.ts
    │   │   │   ├── Splitter.tsx
    │   │   │   ├── SplitterNative.tsx
    │   │   │   ├── utils.ts
    │   │   │   ├── VSplitter.md
    │   │   │   └── VSplitter.spec.ts
    │   │   ├── Stack
    │   │   │   ├── CHStack.md
    │   │   │   ├── CHStack.spec.ts
    │   │   │   ├── CVStack.md
    │   │   │   ├── CVStack.spec.ts
    │   │   │   ├── HStack.md
    │   │   │   ├── HStack.spec.ts
    │   │   │   ├── Stack.md
    │   │   │   ├── Stack.module.scss
    │   │   │   ├── Stack.spec.ts
    │   │   │   ├── Stack.tsx
    │   │   │   ├── StackNative.tsx
    │   │   │   ├── VStack.md
    │   │   │   └── VStack.spec.ts
    │   │   ├── StickyBox
    │   │   │   ├── StickyBox.md
    │   │   │   ├── StickyBox.module.scss
    │   │   │   ├── StickyBox.tsx
    │   │   │   └── StickyBoxNative.tsx
    │   │   ├── Switch
    │   │   │   ├── Switch.md
    │   │   │   ├── Switch.spec.ts
    │   │   │   └── Switch.tsx
    │   │   ├── Table
    │   │   │   ├── doc-resources
    │   │   │   │   └── list-component-data.js
    │   │   │   ├── react-table-config.d.ts
    │   │   │   ├── Table.md
    │   │   │   ├── Table.module.scss
    │   │   │   ├── Table.spec.ts
    │   │   │   ├── Table.tsx
    │   │   │   ├── TableNative.tsx
    │   │   │   └── useRowSelection.tsx
    │   │   ├── TableOfContents
    │   │   │   ├── TableOfContents.module.scss
    │   │   │   ├── TableOfContents.spec.ts
    │   │   │   ├── TableOfContents.tsx
    │   │   │   └── TableOfContentsNative.tsx
    │   │   ├── Tabs
    │   │   │   ├── TabContext.tsx
    │   │   │   ├── TabItem.md
    │   │   │   ├── TabItem.tsx
    │   │   │   ├── TabItemNative.tsx
    │   │   │   ├── Tabs.md
    │   │   │   ├── Tabs.module.scss
    │   │   │   ├── Tabs.spec.ts
    │   │   │   ├── Tabs.tsx
    │   │   │   └── TabsNative.tsx
    │   │   ├── Text
    │   │   │   ├── Text.md
    │   │   │   ├── Text.module.scss
    │   │   │   ├── Text.spec.ts
    │   │   │   ├── Text.tsx
    │   │   │   └── TextNative.tsx
    │   │   ├── TextArea
    │   │   │   ├── TextArea.md
    │   │   │   ├── TextArea.module.scss
    │   │   │   ├── TextArea.spec.ts
    │   │   │   ├── TextArea.tsx
    │   │   │   ├── TextAreaNative.tsx
    │   │   │   ├── TextAreaResizable.tsx
    │   │   │   └── useComposedRef.ts
    │   │   ├── TextBox
    │   │   │   ├── TextBox.md
    │   │   │   ├── TextBox.module.scss
    │   │   │   ├── TextBox.spec.ts
    │   │   │   ├── TextBox.tsx
    │   │   │   └── TextBoxNative.tsx
    │   │   ├── Theme
    │   │   │   ├── NotificationToast.tsx
    │   │   │   ├── Theme.md
    │   │   │   ├── Theme.module.scss
    │   │   │   ├── Theme.spec.ts
    │   │   │   ├── Theme.tsx
    │   │   │   └── ThemeNative.tsx
    │   │   ├── TimeInput
    │   │   │   ├── TimeInput.md
    │   │   │   ├── TimeInput.module.scss
    │   │   │   ├── TimeInput.spec.ts
    │   │   │   ├── TimeInput.tsx
    │   │   │   ├── TimeInputNative.tsx
    │   │   │   └── utils.ts
    │   │   ├── Timer
    │   │   │   ├── Timer.md
    │   │   │   ├── Timer.spec.ts
    │   │   │   ├── Timer.tsx
    │   │   │   └── TimerNative.tsx
    │   │   ├── Toggle
    │   │   │   ├── Toggle.module.scss
    │   │   │   └── Toggle.tsx
    │   │   ├── ToneChangerButton
    │   │   │   ├── ToneChangerButton.md
    │   │   │   ├── ToneChangerButton.spec.ts
    │   │   │   └── ToneChangerButton.tsx
    │   │   ├── ToneSwitch
    │   │   │   ├── ToneSwitch.md
    │   │   │   ├── ToneSwitch.module.scss
    │   │   │   ├── ToneSwitch.spec.ts
    │   │   │   ├── ToneSwitch.tsx
    │   │   │   └── ToneSwitchNative.tsx
    │   │   ├── Tooltip
    │   │   │   ├── Tooltip.md
    │   │   │   ├── Tooltip.module.scss
    │   │   │   ├── Tooltip.spec.ts
    │   │   │   ├── Tooltip.tsx
    │   │   │   └── TooltipNative.tsx
    │   │   ├── Tree
    │   │   │   ├── testData.ts
    │   │   │   ├── Tree-dynamic.spec.ts
    │   │   │   ├── Tree-icons.spec.ts
    │   │   │   ├── Tree.md
    │   │   │   ├── Tree.spec.ts
    │   │   │   ├── TreeComponent.module.scss
    │   │   │   ├── TreeComponent.tsx
    │   │   │   └── TreeNative.tsx
    │   │   ├── TreeDisplay
    │   │   │   ├── TreeDisplay.md
    │   │   │   ├── TreeDisplay.module.scss
    │   │   │   ├── TreeDisplay.tsx
    │   │   │   └── TreeDisplayNative.tsx
    │   │   ├── ValidationSummary
    │   │   │   ├── ValidationSummary.module.scss
    │   │   │   └── ValidationSummary.tsx
    │   │   └── VisuallyHidden.tsx
    │   ├── components-core
    │   │   ├── abstractions
    │   │   │   ├── ComponentRenderer.ts
    │   │   │   ├── LoaderRenderer.ts
    │   │   │   ├── standalone.ts
    │   │   │   └── treeAbstractions.ts
    │   │   ├── action
    │   │   │   ├── actions.ts
    │   │   │   ├── APICall.tsx
    │   │   │   ├── FileDownloadAction.tsx
    │   │   │   ├── FileUploadAction.tsx
    │   │   │   ├── NavigateAction.tsx
    │   │   │   └── TimedAction.tsx
    │   │   ├── ApiBoundComponent.tsx
    │   │   ├── appContext
    │   │   │   ├── date-functions.ts
    │   │   │   ├── math-function.ts
    │   │   │   └── misc-utils.ts
    │   │   ├── AppContext.tsx
    │   │   ├── behaviors
    │   │   │   ├── Behavior.tsx
    │   │   │   └── CoreBehaviors.tsx
    │   │   ├── component-hooks.ts
    │   │   ├── ComponentDecorator.tsx
    │   │   ├── ComponentViewer.tsx
    │   │   ├── CompoundComponent.tsx
    │   │   ├── constants.ts
    │   │   ├── DebugViewProvider.tsx
    │   │   ├── descriptorHelper.ts
    │   │   ├── devtools
    │   │   │   ├── InspectorDialog.module.scss
    │   │   │   ├── InspectorDialog.tsx
    │   │   │   └── InspectorDialogVisibilityContext.tsx
    │   │   ├── EngineError.ts
    │   │   ├── event-handlers.ts
    │   │   ├── InspectorButton.module.scss
    │   │   ├── InspectorContext.tsx
    │   │   ├── interception
    │   │   │   ├── abstractions.ts
    │   │   │   ├── ApiInterceptor.ts
    │   │   │   ├── ApiInterceptorProvider.tsx
    │   │   │   ├── apiInterceptorWorker.ts
    │   │   │   ├── Backend.ts
    │   │   │   ├── Errors.ts
    │   │   │   ├── IndexedDb.ts
    │   │   │   ├── initMock.ts
    │   │   │   ├── InMemoryDb.ts
    │   │   │   ├── ReadonlyCollection.ts
    │   │   │   └── useApiInterceptorContext.tsx
    │   │   ├── loader
    │   │   │   ├── ApiLoader.tsx
    │   │   │   ├── DataLoader.tsx
    │   │   │   ├── ExternalDataLoader.tsx
    │   │   │   ├── Loader.tsx
    │   │   │   ├── MockLoaderRenderer.tsx
    │   │   │   └── PageableLoader.tsx
    │   │   ├── LoaderComponent.tsx
    │   │   ├── markup-check.ts
    │   │   ├── parts.ts
    │   │   ├── renderers.ts
    │   │   ├── rendering
    │   │   │   ├── AppContent.tsx
    │   │   │   ├── AppRoot.tsx
    │   │   │   ├── AppWrapper.tsx
    │   │   │   ├── buildProxy.ts
    │   │   │   ├── collectFnVarDeps.ts
    │   │   │   ├── ComponentAdapter.tsx
    │   │   │   ├── ComponentWrapper.tsx
    │   │   │   ├── Container.tsx
    │   │   │   ├── containers.ts
    │   │   │   ├── ContainerWrapper.tsx
    │   │   │   ├── ErrorBoundary.module.scss
    │   │   │   ├── ErrorBoundary.tsx
    │   │   │   ├── InvalidComponent.module.scss
    │   │   │   ├── InvalidComponent.tsx
    │   │   │   ├── nodeUtils.ts
    │   │   │   ├── reducer.ts
    │   │   │   ├── renderChild.tsx
    │   │   │   ├── StandaloneComponent.tsx
    │   │   │   ├── StateContainer.tsx
    │   │   │   ├── UnknownComponent.module.scss
    │   │   │   ├── UnknownComponent.tsx
    │   │   │   └── valueExtractor.ts
    │   │   ├── reportEngineError.ts
    │   │   ├── RestApiProxy.ts
    │   │   ├── script-runner
    │   │   │   ├── asyncProxy.ts
    │   │   │   ├── AttributeValueParser.ts
    │   │   │   ├── bannedFunctions.ts
    │   │   │   ├── BindingTreeEvaluationContext.ts
    │   │   │   ├── eval-tree-async.ts
    │   │   │   ├── eval-tree-common.ts
    │   │   │   ├── eval-tree-sync.ts
    │   │   │   ├── ParameterParser.ts
    │   │   │   ├── process-statement-async.ts
    │   │   │   ├── process-statement-common.ts
    │   │   │   ├── process-statement-sync.ts
    │   │   │   ├── ScriptingSourceTree.ts
    │   │   │   ├── simplify-expression.ts
    │   │   │   ├── statement-queue.ts
    │   │   │   └── visitors.ts
    │   │   ├── StandaloneApp.tsx
    │   │   ├── StandaloneExtensionManager.ts
    │   │   ├── TableOfContentsContext.tsx
    │   │   ├── theming
    │   │   │   ├── _themes.scss
    │   │   │   ├── component-layout-resolver.ts
    │   │   │   ├── extendThemeUtils.ts
    │   │   │   ├── hvar.ts
    │   │   │   ├── layout-resolver.ts
    │   │   │   ├── parse-layout-props.ts
    │   │   │   ├── StyleContext.tsx
    │   │   │   ├── StyleRegistry.ts
    │   │   │   ├── ThemeContext.tsx
    │   │   │   ├── ThemeProvider.tsx
    │   │   │   ├── themes
    │   │   │   │   ├── base-utils.ts
    │   │   │   │   ├── palette.ts
    │   │   │   │   ├── root.ts
    │   │   │   │   ├── solid.ts
    │   │   │   │   ├── theme-colors.ts
    │   │   │   │   └── xmlui.ts
    │   │   │   ├── themeVars.module.scss
    │   │   │   ├── themeVars.ts
    │   │   │   ├── transformThemeVars.ts
    │   │   │   └── utils.ts
    │   │   ├── utils
    │   │   │   ├── actionUtils.ts
    │   │   │   ├── audio-utils.ts
    │   │   │   ├── base64-utils.ts
    │   │   │   ├── compound-utils.ts
    │   │   │   ├── css-utils.ts
    │   │   │   ├── DataLoaderQueryKeyGenerator.ts
    │   │   │   ├── date-utils.ts
    │   │   │   ├── extractParam.ts
    │   │   │   ├── hooks.tsx
    │   │   │   ├── LruCache.ts
    │   │   │   ├── mergeProps.ts
    │   │   │   ├── misc.ts
    │   │   │   ├── request-params.ts
    │   │   │   ├── statementUtils.ts
    │   │   │   └── treeUtils.ts
    │   │   └── xmlui-parser.ts
    │   ├── index-standalone.ts
    │   ├── index.scss
    │   ├── index.ts
    │   ├── language-server
    │   │   ├── server-common.ts
    │   │   ├── server-web-worker.ts
    │   │   ├── server.ts
    │   │   ├── services
    │   │   │   ├── common
    │   │   │   │   ├── docs-generation.ts
    │   │   │   │   ├── lsp-utils.ts
    │   │   │   │   ├── metadata-utils.ts
    │   │   │   │   └── syntax-node-utilities.ts
    │   │   │   ├── completion.ts
    │   │   │   ├── diagnostic.ts
    │   │   │   ├── format.ts
    │   │   │   └── hover.ts
    │   │   └── xmlui-metadata-generated.js
    │   ├── logging
    │   │   ├── LoggerContext.tsx
    │   │   ├── LoggerInitializer.tsx
    │   │   ├── LoggerService.ts
    │   │   └── xmlui.ts
    │   ├── logo.svg
    │   ├── parsers
    │   │   ├── common
    │   │   │   ├── GenericToken.ts
    │   │   │   ├── InputStream.ts
    │   │   │   └── utils.ts
    │   │   ├── scripting
    │   │   │   ├── code-behind-collect.ts
    │   │   │   ├── Lexer.ts
    │   │   │   ├── modules.ts
    │   │   │   ├── Parser.ts
    │   │   │   ├── ParserError.ts
    │   │   │   ├── ScriptingNodeTypes.ts
    │   │   │   ├── TokenTrait.ts
    │   │   │   ├── TokenType.ts
    │   │   │   └── tree-visitor.ts
    │   │   ├── style-parser
    │   │   │   ├── errors.ts
    │   │   │   ├── source-tree.ts
    │   │   │   ├── StyleInputStream.ts
    │   │   │   ├── StyleLexer.ts
    │   │   │   ├── StyleParser.ts
    │   │   │   └── tokens.ts
    │   │   └── xmlui-parser
    │   │       ├── CharacterCodes.ts
    │   │       ├── diagnostics.ts
    │   │       ├── fileExtensions.ts
    │   │       ├── index.ts
    │   │       ├── lint.ts
    │   │       ├── parser.ts
    │   │       ├── ParserError.ts
    │   │       ├── scanner.ts
    │   │       ├── syntax-kind.ts
    │   │       ├── syntax-node.ts
    │   │       ├── transform.ts
    │   │       ├── utils.ts
    │   │       ├── xmlui-serializer.ts
    │   │       └── xmlui-tree.ts
    │   ├── react-app-env.d.ts
    │   ├── syntax
    │   │   ├── monaco
    │   │   │   ├── grammar.monacoLanguage.ts
    │   │   │   ├── index.ts
    │   │   │   ├── xmlui-dark.ts
    │   │   │   ├── xmlui-light.ts
    │   │   │   └── xmluiscript.monacoLanguage.ts
    │   │   └── textMate
    │   │       ├── index.ts
    │   │       ├── xmlui-dark.json
    │   │       ├── xmlui-light.json
    │   │       ├── xmlui.json
    │   │       └── xmlui.tmLanguage.json
    │   ├── testing
    │   │   ├── assertions.ts
    │   │   ├── component-test-helpers.ts
    │   │   ├── ComponentDrivers.ts
    │   │   ├── drivers
    │   │   │   ├── DateInputDriver.ts
    │   │   │   ├── index.ts
    │   │   │   ├── ModalDialogDriver.ts
    │   │   │   ├── NumberBoxDriver.ts
    │   │   │   ├── TextBoxDriver.ts
    │   │   │   ├── TimeInputDriver.ts
    │   │   │   ├── TimerDriver.ts
    │   │   │   └── TreeDriver.ts
    │   │   ├── fixtures.ts
    │   │   ├── index.ts
    │   │   ├── infrastructure
    │   │   │   ├── index.html
    │   │   │   ├── main.tsx
    │   │   │   ├── public
    │   │   │   │   ├── mockServiceWorker.js
    │   │   │   │   ├── resources
    │   │   │   │   │   ├── bell.svg
    │   │   │   │   │   ├── box.svg
    │   │   │   │   │   ├── doc.svg
    │   │   │   │   │   ├── eye.svg
    │   │   │   │   │   ├── flower-640x480.jpg
    │   │   │   │   │   ├── sun.svg
    │   │   │   │   │   ├── test-image-100x100.jpg
    │   │   │   │   │   └── txt.svg
    │   │   │   │   └── serve.json
    │   │   │   └── TestBed.tsx
    │   │   └── themed-app-test-helpers.ts
    │   └── vite-env.d.ts
    ├── tests
    │   ├── components
    │   │   ├── CodeBlock
    │   │   │   └── hightlight-code.test.ts
    │   │   ├── playground-pattern.test.ts
    │   │   └── Tree
    │   │       └── Tree-states.test.ts
    │   ├── components-core
    │   │   ├── abstractions
    │   │   │   └── treeAbstractions.test.ts
    │   │   ├── container
    │   │   │   └── buildProxy.test.ts
    │   │   ├── interception
    │   │   │   ├── orderBy.test.ts
    │   │   │   ├── ReadOnlyCollection.test.ts
    │   │   │   └── request-param-converter.test.ts
    │   │   ├── scripts-runner
    │   │   │   ├── AttributeValueParser.test.ts
    │   │   │   ├── eval-tree-arrow-async.test.ts
    │   │   │   ├── eval-tree-arrow.test.ts
    │   │   │   ├── eval-tree-func-decl-async.test.ts
    │   │   │   ├── eval-tree-func-decl.test.ts
    │   │   │   ├── eval-tree-pre-post.test.ts
    │   │   │   ├── eval-tree-regression.test.ts
    │   │   │   ├── eval-tree.test.ts
    │   │   │   ├── function-proxy.test.ts
    │   │   │   ├── parser-regression.test.ts
    │   │   │   ├── process-event.test.ts
    │   │   │   ├── process-function.test.ts
    │   │   │   ├── process-implicit-context.test.ts
    │   │   │   ├── process-statement-asgn.test.ts
    │   │   │   ├── process-statement-destruct.test.ts
    │   │   │   ├── process-statement-regs.test.ts
    │   │   │   ├── process-statement-sync.test.ts
    │   │   │   ├── process-statement.test.ts
    │   │   │   ├── process-switch-sync.test.ts
    │   │   │   ├── process-switch.test.ts
    │   │   │   ├── process-try-sync.test.ts
    │   │   │   ├── process-try.test.ts
    │   │   │   └── test-helpers.ts
    │   │   ├── test-metadata-handler.ts
    │   │   ├── theming
    │   │   │   ├── border-segments.test.ts
    │   │   │   ├── component-layout.resolver.test.ts
    │   │   │   ├── layout-property-parser.test.ts
    │   │   │   ├── layout-resolver.test.ts
    │   │   │   ├── layout-resolver2.test.ts
    │   │   │   ├── layout-vp-override.test.ts
    │   │   │   └── padding-segments.test.ts
    │   │   └── utils
    │   │       ├── date-utils.test.ts
    │   │       ├── format-human-elapsed-time.test.ts
    │   │       └── LruCache.test.ts
    │   ├── language-server
    │   │   ├── completion.test.ts
    │   │   ├── format.test.ts
    │   │   ├── hover.test.ts
    │   │   └── mockData.ts
    │   └── parsers
    │       ├── common
    │       │   └── input-stream.test.ts
    │       ├── markdown
    │       │   └── parse-binding-expression.test.ts
    │       ├── parameter-parser.test.ts
    │       ├── paremeter-parser.test.ts
    │       ├── scripting
    │       │   ├── eval-tree-arrow.test.ts
    │       │   ├── eval-tree-pre-post.test.ts
    │       │   ├── eval-tree.test.ts
    │       │   ├── function-proxy.test.ts
    │       │   ├── lexer-literals.test.ts
    │       │   ├── lexer-misc.test.ts
    │       │   ├── module-parse.test.ts
    │       │   ├── parser-arrow.test.ts
    │       │   ├── parser-assignments.test.ts
    │       │   ├── parser-binary.test.ts
    │       │   ├── parser-destructuring.test.ts
    │       │   ├── parser-errors.test.ts
    │       │   ├── parser-expressions.test.ts
    │       │   ├── parser-function.test.ts
    │       │   ├── parser-literals.test.ts
    │       │   ├── parser-primary.test.ts
    │       │   ├── parser-regex.test.ts
    │       │   ├── parser-statements.test.ts
    │       │   ├── parser-unary.test.ts
    │       │   ├── process-event.test.ts
    │       │   ├── process-implicit-context.test.ts
    │       │   ├── process-statement-asgn.test.ts
    │       │   ├── process-statement-destruct.test.ts
    │       │   ├── process-statement-regs.test.ts
    │       │   ├── process-statement-sync.test.ts
    │       │   ├── process-statement.test.ts
    │       │   ├── process-switch-sync.test.ts
    │       │   ├── process-switch.test.ts
    │       │   ├── process-try-sync.test.ts
    │       │   ├── process-try.test.ts
    │       │   ├── simplify-expression.test.ts
    │       │   ├── statement-hooks.test.ts
    │       │   └── test-helpers.ts
    │       ├── style-parser
    │       │   ├── generateHvarChain.test.ts
    │       │   ├── parseHVar.test.ts
    │       │   ├── parser.test.ts
    │       │   └── tokens.test.ts
    │       └── xmlui
    │           ├── lint.test.ts
    │           ├── parser.test.ts
    │           ├── scanner.test.ts
    │           ├── transform.attr.test.ts
    │           ├── transform.circular.test.ts
    │           ├── transform.element.test.ts
    │           ├── transform.errors.test.ts
    │           ├── transform.escape.test.ts
    │           ├── transform.regression.test.ts
    │           ├── transform.script.test.ts
    │           ├── transform.test.ts
    │           └── xmlui.ts
    ├── tests-e2e
    │   ├── api-bound-component-regression.spec.ts
    │   ├── api-call-as-extracted-component.spec.ts
    │   ├── assign-to-object-or-array-regression.spec.ts
    │   ├── binding-regression.spec.ts
    │   ├── children-as-template-context-vars.spec.ts
    │   ├── compound-component.spec.ts
    │   ├── context-vars-regression.spec.ts
    │   ├── data-bindings.spec.ts
    │   ├── datasource-and-api-usage-in-var.spec.ts
    │   ├── datasource-direct-binding.spec.ts
    │   ├── datasource-onLoaded-regression.spec.ts
    │   ├── modify-array-item-regression.spec.ts
    │   ├── namespaces.spec.ts
    │   ├── push-to-array-regression.spec.ts
    │   ├── screen-breakpoints.spec.ts
    │   ├── scripting.spec.ts
    │   ├── state-scope-in-pages.spec.ts
    │   └── state-var-scopes.spec.ts
    ├── tsconfig.json
    ├── tsdown.config.ts
    ├── vite.config.ts
    └── vitest.config.ts
```

# Files

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

```markdown
  1 | # Invoice Details
  2 | 
  3 | We've seen that the `Invoices` [Table](/components/Table) includes a `Details` [Column](/components/Column) with an icon. Clicking the icon opens a [ModalDialog](/components/ModalDialog) and sends it the current row of the table as `$item`.
  4 | 
  5 | ```xmlui /detailsDialog/
  6 | <Table data="{invoices}">
  7 |     <Column  bindTo="invoice_number" />
  8 |     <Column  bindTo="client" />
  9 |     <Column  bindTo="issue_date" />
 10 |     <Column  bindTo="due_date" />
 11 |     <Column  bindTo="paid_date" />
 12 |     <Column  header="total">
 13 |         ${$item.total}
 14 |     </Column>
 15 |     <Column  header="Status">
 16 |         <StatusBadge status="{$item.status}" />
 17 |     </Column>
 18 |     <Column canSort="{false}" header="Details">
 19 |         <Icon name="doc-outline" onClick="detailsDialog.open($item)" />
 20 |     </Column>
 21 | </Table>
 22 | ```
 23 | 
 24 | ```xmlui /detailsDialog/
 25 | <ModalDialog id="detailsDialog">
 26 |   <InvoiceDetails details="{$params[0]}" />
 27 | </ModalDialog>
 28 | ```
 29 | 
 30 | The `ModalDialog` wraps an `InvoiceDetails` component which displays an invoice and enables editing. Click the `Details` icon to open the viewer/editor.
 31 | 
 32 | ```xmlui-pg noHeader height="500px"
 33 | ---app
 34 | <App>
 35 |   <Table gap="0" data="{[window.sampleInvoice]}">
 36 |     <Column canSort="{false}" bindTo="invoice_number" />
 37 |     <Column canSort="{false}" bindTo="client" />
 38 |     <Column canSort="{false}" bindTo="issue_date" />
 39 |     <Column canSort="{false}" bindTo="due_date" />
 40 |     <Column canSort="{false}" bindTo="paid_date" />
 41 |     <Column canSort="{false}" header="total">
 42 |       ${$item.total}
 43 |     </Column>
 44 |     <Column canSort="{false}" header="Status">
 45 |       <StatusBadge status="{$item.status}" />
 46 |     </Column>
 47 |     <Column canSort="{false}" header="Details">
 48 |       <Icon name="doc-outline" onClick="detailsDialog.open($item)" />
 49 |     </Column>
 50 |   </Table>
 51 | 
 52 |   <Theme
 53 |     maxWidth-ModalDialog="50%"
 54 |     backgroundColor-overlay-ModalDialog="rgba(0,0,0,0.5)">
 55 |     <ModalDialog id="detailsDialog">
 56 |       <InvoiceDetails details="{$params[0]}" />
 57 |     </ModalDialog>
 58 |   </Theme>
 59 | </App>
 60 | ---comp
 61 | <Component
 62 |     name="StatusBadge"
 63 |     var.statusColors="{{
 64 |         draft: { background: '#f59e0b', label: 'white' },
 65 |         sent: { background: '#3b82f6', label: 'white' },
 66 |         paid: { background: '#10b981', label: 'white' }
 67 |     }}"
 68 | >
 69 |     <Badge
 70 |         value="{$props.status}"
 71 |         colorMap="{statusColors}"
 72 |         variant="pill"
 73 |     />
 74 | </Component>
 75 | ---comp
 76 | <Component name="InvoiceDetails">
 77 | 
 78 |     <variable name="details" value="{$props.details}" />
 79 | 
 80 |     <Form>
 81 | 
 82 |         <Table width="100%" data="{[details]}">
 83 |             <Column canSort="{false}" bindTo="invoice_number" />
 84 |             <Column canSort="{false}" bindTo="client" />
 85 |             <Column canSort="{false}" bindTo="issue_date" />
 86 |             <Column canSort="{false}" bindTo="due_date" />
 87 |             <Column canSort="{false}" header="Status">
 88 |                 <StatusBadge status="{$item.status}" />
 89 |             </Column>
 90 |         </Table>
 91 | 
 92 | 
 93 |         <VStack gap="0">
 94 |             <Text>Notes:</Text>
 95 |             <FormItem bindTo="notes" initialValue="{window.coalesce(details.notes)}" />
 96 |         </VStack>
 97 | 
 98 |         <VStack gap="0">
 99 |             <Text>Status:</Text>
100 |             <FormItem type="select" bindTo="status" initialValue="{details.status}" enabled="{details.status !== 'paid'}">
101 |                 <Option label="sent"  value="sent" />
102 |                 <Option label="paid"  value="paid" />
103 |                 <Option label="draft" value="draft" />
104 |                 <Option value="{$item.name}" label="{$item.name}" />
105 |             </FormItem>
106 |         </VStack>
107 | 
108 | 
109 |         <Table width="100%" data="{JSON.parse(details.items)}">
110 |             <Column bindTo="name" />
111 |             <Column bindTo="quantity" />
112 |             <Column bindTo="total">
113 |                 ${$item.total}
114 |             </Column>
115 |             <Column header="price">
116 |                 ${$item.price}
117 |             </Column>
118 |         </Table>
119 | 
120 |         <event name="submit">
121 |             <APICall
122 |                 url="https://httpbin.org/post"
123 |                 method="POST"
124 |                 inProgressNotificationMessage="Updating invoice..."
125 |                 completedNotificationMessage="Invoice updated successfully"
126 |                 body="{
127 |                     {
128 |                     number: details.invoice_number,
129 |                     status: $param.status,
130 |                     notes: $param.notes
131 |                     }
132 |                   }"
133 |                   onSuccess="Actions.navigate('/invoices')"
134 |             />
135 |         </event>
136 | 
137 |     </Form>
138 | 
139 | </Component>
140 | ```
141 | 
142 | Here's the `InvoiceDetails` component.
143 | 
144 | ```xmlui
145 | <Component name="InvoiceDetails">
146 |     <Table width="100%" data="{[$props.details]}">
147 |         <Column canSort="{false}" bindTo="invoice_number" />
148 |         <Column canSort="{false}" bindTo="client" />
149 |         <Column canSort="{false}" bindTo="issue_date" />
150 |         <Column canSort="{false}" bindTo="due_date" />
151 |         <Column canSort="{false}" header="Status">
152 |             <StatusBadge status="{$item.status}" />
153 |         </Column>
154 |     </Table>
155 |     <Form submitUrl="/api/invoices/{$props.details.invoice_number}"
156 |           submitMethod="PUT"
157 |     >
158 |         <FormItem
159 |            label="Notes"
160 |            bindTo="notes"
161 |            initialValue="{window.coalesce($props.details.notes)}" />
162 |         <FormItem label="Status" bindTo="status"
163 |           initialValue="{$props.details.status}"
164 |           type="select"
165 |           enabled="{$props.details.status !== 'paid'}"
166 |         >
167 |             <Option label="sent"  value="sent" />
168 |             <Option label="paid"  value="paid" />
169 |             <Option label="draft" value="draft" />
170 |         </FormItem>
171 |         <Table data="{JSON.parse($props.details.items)}">
172 |             <Column bindTo="name" />
173 |             <Column bindTo="quantity" />
174 |             <Column bindTo="total">
175 |                 ${$item.total}
176 |             </Column>
177 |             <Column header="price">
178 |                 ${$item.price}
179 |             </Column>
180 |         </Table>
181 |     </Form>
182 | </Component>
183 | ```
184 | 
185 | There are two `Table`s. The first has only one row to report the top-level details. Since `$props.details` is an object, not an array, we wrap it in square brackets (`[ ]`) to provide the array that `Table` expects.
186 | 
187 | The second `Table` reports one row per lineitem. The Invoices app chooses not to make lineitems editable. The editable fields are `notes` and `status`.
188 | 
189 | The `status` field uses `FormItem type="select"`. It's disabled for statuses other than `paid`, so the operator can mark a `sent` invoice as `paid` but not vice versa.
190 | 
191 | The [APICall](/component/APICall) is triggered by the submit event. Its `onSuccess` handler uses [Actions.navigate](/globals#navigate) to return to the `Invoices` page.
192 | 
193 | In other contexts you use `ModalDialog`'s `close()` method, but when a `Form` is wrapped in a `ModalDialog`, the form's submit and cancel buttons both close the dialog.
194 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components/DropdownMenu/DropdownMenuNative.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import { type CSSProperties, forwardRef, type ReactNode } from "react";
  2 | import { useEffect, useState, useRef } from "react";
  3 | import * as ReactDropdownMenu from "@radix-ui/react-dropdown-menu";
  4 | import classnames from "classnames";
  5 | 
  6 | import styles from "./DropdownMenu.module.scss";
  7 | 
  8 | import type { RegisterComponentApiFn } from "../../abstractions/RendererDefs";
  9 | import { useTheme } from "../../components-core/theming/ThemeContext";
 10 | import { noop } from "../../components-core/constants";
 11 | import type {
 12 |   IconPosition,
 13 |   ButtonVariant,
 14 |   ButtonThemeColor,
 15 |   AlignmentOptions,
 16 | } from "../abstractions";
 17 | import { Button } from "../Button/ButtonNative";
 18 | import { Icon } from "../Icon/IconNative";
 19 | 
 20 | type DropdownMenuProps = {
 21 |   triggerTemplate?: ReactNode;
 22 |   children?: ReactNode;
 23 |   label?: string;
 24 |   registerComponentApi?: RegisterComponentApiFn;
 25 |   style?: CSSProperties;
 26 |   className?: string;
 27 |   alignment?: AlignmentOptions;
 28 |   onWillOpen?: () => Promise<boolean | undefined>;
 29 |   disabled?: boolean;
 30 |   triggerButtonVariant?: string;
 31 |   triggerButtonThemeColor?: string;
 32 |   triggerButtonIcon?: string;
 33 |   triggerButtonIconPosition?: IconPosition;
 34 | };
 35 | 
 36 | export const defaultDropdownMenuProps: Pick<
 37 |   DropdownMenuProps,
 38 |   | "alignment"
 39 |   | "triggerButtonVariant"
 40 |   | "triggerButtonThemeColor"
 41 |   | "triggerButtonIcon"
 42 |   | "triggerButtonIconPosition"
 43 | > = {
 44 |   alignment: "start",
 45 |   triggerButtonVariant: "ghost",
 46 |   triggerButtonThemeColor: "primary",
 47 |   triggerButtonIcon: "triggerButton:DropdownMenu", // Use component-specific icon resource pattern
 48 |   triggerButtonIconPosition: "end",
 49 | };
 50 | 
 51 | export const DropdownMenu = forwardRef(function DropdownMenu(
 52 |   {
 53 |     triggerTemplate,
 54 |     children,
 55 |     label,
 56 |     registerComponentApi,
 57 |     style,
 58 |     className,
 59 |     onWillOpen,
 60 |     alignment = defaultDropdownMenuProps.alignment,
 61 |     disabled = false,
 62 |     triggerButtonVariant = defaultDropdownMenuProps.triggerButtonVariant,
 63 |     triggerButtonThemeColor = defaultDropdownMenuProps.triggerButtonThemeColor,
 64 |     triggerButtonIcon = defaultDropdownMenuProps.triggerButtonIcon,
 65 |     triggerButtonIconPosition = defaultDropdownMenuProps.triggerButtonIconPosition,
 66 |     ...rest
 67 |   }: DropdownMenuProps,
 68 |   ref,
 69 | ) {
 70 |   const { root } = useTheme();
 71 |   const [open, setOpen] = useState(false);
 72 |   const closeTimeoutRef = useRef<NodeJS.Timeout>();
 73 | 
 74 |   useEffect(() => {
 75 |     registerComponentApi?.({
 76 |       open: () => setOpen(true),
 77 |       close: () => setOpen(false),
 78 |     });
 79 |   }, [registerComponentApi]);
 80 | 
 81 |   // Cleanup timeout on unmount
 82 |   useEffect(() => {
 83 |     return () => {
 84 |       if (closeTimeoutRef.current) {
 85 |         clearTimeout(closeTimeoutRef.current);
 86 |       }
 87 |     };
 88 |   }, []);
 89 | 
 90 |   return (
 91 |     <ReactDropdownMenu.Root
 92 |       open={open}
 93 |       onOpenChange={async (isOpen) => {
 94 |         if (isOpen) {
 95 |           // Clear any pending close timeout when opening
 96 |           if (closeTimeoutRef.current) {
 97 |             clearTimeout(closeTimeoutRef.current);
 98 |             closeTimeoutRef.current = undefined;
 99 |           }
100 |           
101 |           const willOpenResult = await onWillOpen?.();
102 |           if (willOpenResult === false) {
103 |             return;
104 |           }
105 |           setOpen(isOpen);
106 |         } else {
107 |           // When closing, add a small delay to allow child components (like Select)
108 |           // to handle their click-outside events first before the DropdownMenu closes
109 |           closeTimeoutRef.current = setTimeout(() => {
110 |             setOpen(false);
111 |             closeTimeoutRef.current = undefined;
112 |           }, 0);
113 |         }
114 |       }}
115 |     >
116 |       <ReactDropdownMenu.Trigger {...rest} asChild disabled={disabled} ref={ref as any}>
117 |         {triggerTemplate ? (
118 |           triggerTemplate
119 |         ) : (
120 |           <Button
121 |             icon={<Icon name={triggerButtonIcon} fallback="chevrondown" />}
122 |             iconPosition={triggerButtonIconPosition}
123 |             type="button"
124 |             variant={triggerButtonVariant as ButtonVariant}
125 |             themeColor={triggerButtonThemeColor as ButtonThemeColor}
126 |             disabled={disabled}
127 |           >
128 |             {label}
129 |           </Button>
130 |         )}
131 |       </ReactDropdownMenu.Trigger>
132 |       <ReactDropdownMenu.Portal container={root}>
133 |         <ReactDropdownMenu.Content
134 |           align={alignment}
135 |           style={style}
136 |           className={classnames(styles.DropdownMenuContent, className)}
137 |         >
138 |           {children}
139 |         </ReactDropdownMenu.Content>
140 |       </ReactDropdownMenu.Portal>
141 |     </ReactDropdownMenu.Root>
142 |   );
143 | });
144 | 
145 | type MenuItemProps = {
146 |   icon?: ReactNode;
147 |   iconPosition?: IconPosition;
148 |   onClick?: (event: any) => void;
149 |   children?: ReactNode;
150 |   label?: string;
151 |   style?: CSSProperties;
152 |   className?: string;
153 |   to?: string;
154 |   active?: boolean;
155 |   enabled?: boolean;
156 | };
157 | 
158 | export const defaultMenuItemProps: Pick<MenuItemProps, "iconPosition" | "active"> = {
159 |   iconPosition: "start",
160 |   active: false,
161 | };
162 | 
163 | export const MenuItem = forwardRef(function MenuItem(
164 |   {
165 |     children,
166 |     onClick = noop,
167 |     label,
168 |     style,
169 |     className,
170 |     icon,
171 |     iconPosition = defaultMenuItemProps.iconPosition,
172 |     active = defaultMenuItemProps.active,
173 |     enabled = true,
174 |   }: MenuItemProps,
175 |   ref,
176 | ) {
177 |   const iconToStart = iconPosition === "start";
178 | 
179 |   return (
180 |     <ReactDropdownMenu.Item
181 |       style={style}
182 |       className={classnames(className, styles.DropdownMenuItem, {
183 |         [styles.active]: active,
184 |         [styles.disabled]: !enabled,
185 |       })}
186 |       onClick={(event) => {
187 |         if (!enabled) {
188 |           event.preventDefault();
189 |           event.stopPropagation();
190 |           return;
191 |         }
192 |         event.stopPropagation();
193 |         if (enabled) {
194 |           onClick(event);
195 |         }
196 |       }}
197 |       ref={ref as any}
198 |     >
199 |       {iconToStart && icon}
200 |       <div className={styles.wrapper}>{label ?? children}</div>
201 |       {!iconToStart && icon}
202 |     </ReactDropdownMenu.Item>
203 |   );
204 | });
205 | 
206 | type SubMenuItemProps = {
207 |   label?: string;
208 |   children?: ReactNode;
209 |   triggerTemplate?: ReactNode;
210 | };
211 | 
212 | export const SubMenuItem = forwardRef<HTMLDivElement, SubMenuItemProps>(
213 |   function SubMenuItem({ children, label, triggerTemplate }, ref) {
214 |     const { root } = useTheme();
215 | 
216 |     return (
217 |       <ReactDropdownMenu.Sub>
218 |         <ReactDropdownMenu.SubTrigger className={styles.DropdownMenuSubTrigger} asChild ref={ref}>
219 |           {triggerTemplate ? triggerTemplate : <div>{label}</div>}
220 |         </ReactDropdownMenu.SubTrigger>
221 |         <ReactDropdownMenu.Portal container={root}>
222 |           <ReactDropdownMenu.SubContent className={styles.DropdownMenuSubContent}>
223 |             {children}
224 |           </ReactDropdownMenu.SubContent>
225 |         </ReactDropdownMenu.Portal>
226 |       </ReactDropdownMenu.Sub>
227 |     );
228 |   },
229 | );
230 | 
231 | export const MenuSeparator = forwardRef<HTMLDivElement>(function MenuSeparator(props, ref) {
232 |   return <ReactDropdownMenu.Separator ref={ref} className={styles.DropdownMenuSeparator} {...props} />;
233 | });
234 | 
```

--------------------------------------------------------------------------------
/xmlui/scripts/generate-docs/utils.mjs:
--------------------------------------------------------------------------------

```
  1 | import { existsSync, readdirSync, statSync, unlinkSync } from "fs";
  2 | import { posix } from "path";
  3 | import { TABLE_CONFIG } from "./constants.mjs";
  4 | 
  5 | /**
  6 |  * Creates a markdown table.
  7 |  * The number of headers can be more or less than the number of rows.
  8 |  * @param {Record<string, string[] | boolean>} data
  9 |  * @param {string[]} data.headers A list of headers for the table 
 10 |  * @param {string[][]} data.rows A list of rows of the table content,
 11 |  *  each row is an array of strings
 12 |  * @param {boolean} data.rowNums Toggle to generate row numbers or not
 13 |  * @returns {string} Generated markdown table
 14 |  */
 15 | export function createTable({ headers = [], rows = [], rowNums = false }) {
 16 |   let table = "";
 17 | 
 18 |   if (headers.length === 0 && rows.length === 0) {
 19 |     return table;
 20 |   }
 21 | 
 22 |   if (rowNums) {
 23 |     headers.unshift(TABLE_CONFIG.DEFAULT_ROW_NUM_HEADER);
 24 |   }
 25 | 
 26 |   table +=
 27 |     "| " +
 28 |     headers
 29 |       .map((h) => {
 30 |         if (typeof h === "string") return h;
 31 |         if (typeof h === "object") return h.value;
 32 |       })
 33 |       .join(" | ") +
 34 |     " |\n";
 35 | 
 36 |   table +=
 37 |     "| " +
 38 |     headers
 39 |       .map((h) => {
 40 |         if (typeof h === "object" && h.style === TABLE_CONFIG.STYLES.LEFT) return TABLE_CONFIG.MARKDOWN_ALIGNMENTS.LEFT;
 41 |         if (typeof h === "object" && h.style === TABLE_CONFIG.STYLES.CENTER) return TABLE_CONFIG.MARKDOWN_ALIGNMENTS.CENTER;
 42 |         if (typeof h === "object" && h.style === TABLE_CONFIG.STYLES.RIGHT) return TABLE_CONFIG.MARKDOWN_ALIGNMENTS.RIGHT;
 43 |         return TABLE_CONFIG.MARKDOWN_ALIGNMENTS.DEFAULT;
 44 |       })
 45 |       .join(" | ") +
 46 |     " |\n";
 47 | 
 48 |   rows.forEach((row) => {
 49 |     table += "| " + (rowNums ? rows.indexOf(row) + 1 + " | " : "") + row.join(" | ") + " |\n";
 50 |   });
 51 | 
 52 |   return table;
 53 | }
 54 | 
 55 | /**
 56 |  * Multi-liner (commented and compatible with really old javascript versions)
 57 |  * Source: https://stackoverflow.com/a/62732509
 58 |  */
 59 | export function winPathToPosix(windowsPath) {
 60 |   // handle the edge-case of Window's long file names
 61 |   // See: https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#short-vs-long-names
 62 |   windowsPath = windowsPath.replace(/^\\\\\?\\/, "");
 63 | 
 64 |   // convert the separators, valid since both \ and / can't be in a windows filename
 65 |   windowsPath = windowsPath.replace(/\\/g, "/");
 66 | 
 67 |   // compress any // or /// to be just /, which is a safe operation under POSIX
 68 |   // and prevents accidental errors caused by manually doing path1+path2
 69 |   windowsPath = windowsPath.replace(/\/\/+/g, "/");
 70 | 
 71 |   return windowsPath;
 72 | }
 73 | 
 74 | /**
 75 |  * Simple but slow
 76 |  * @param {string} buffer
 77 |  */
 78 | export function strBufferToLines(buffer) {
 79 |   if (typeof buffer !== "string") {
 80 |     throw new Error("Only string buffers are supported.");
 81 |   }
 82 |   return buffer.split(/\r?\n/);
 83 | }
 84 | 
 85 | /**
 86 |  * Recursive function that traverses a given folder and applies an optional function on
 87 |  * each of the folders/files found inside.
 88 |  */
 89 | export function traverseDirectory(node, visitor, level = 0) {
 90 |   level++;
 91 |   const dirContents = readdirSync(node.path);
 92 |   if (!node.children) node.children = dirContents;
 93 |   for (const itemName of dirContents) {
 94 |     const itemPath = [winPathToPosix(node.path), itemName].join(posix.sep);
 95 |     const itemIsDir = statSync(itemPath).isDirectory();
 96 |     const childNode = {
 97 |       name: itemName,
 98 |       path: itemPath,
 99 |       parent: node,
100 |     };
101 |     visitor && visitor(childNode, level);
102 |     if (itemIsDir) {
103 |       traverseDirectory(childNode, visitor, level);
104 |     }
105 |   }
106 | }
107 | 
108 | /**
109 |  * Removes duplicate entries from the input array.
110 |  */
111 | export function gatherAndRemoveDuplicates(container, byAttribute = "id") {
112 |   const idSet = new Set();
113 |   const duplicates = [];
114 |   container.forEach((item) => {
115 |     if (idSet.has(item[byAttribute])) {
116 |       duplicates.push(item);
117 |     }
118 |     idSet.add(item[byAttribute]);
119 |   });
120 | 
121 |   return {
122 |     filtered: container.filter((item) => !duplicates.includes(item)),
123 |     duplicates,
124 |   };
125 | }
126 | 
127 | export function toNormalizedUpperCase(rawStr) {
128 |   return rawStr
129 |     .trim()
130 |     .toLocaleUpperCase()
131 |     .replaceAll(/[^A-Za-z0-9_]/g, "_")
132 |     .replaceAll(/__+/g, "_"); // <- remove duplicate underscores
133 | }
134 | 
135 | export function toHeadingPath(rawStr) {
136 |   return rawStr
137 |     .trim()
138 |     .toLocaleLowerCase()
139 |     .replaceAll(/[^A-Za-z0-9-]/g, "-")
140 |     .replaceAll(/--+/g, "-")
141 |     .replace(/^-|-$/, "");
142 | }
143 | 
144 | /**
145 |  * Converts string from kebab case to space separated string with uppercase starting character
146 |  * @param {string} rawStr input in kebab case (e.g. "hello-there-friend")
147 |  * @returns {string} camel cased string (e.g. "Hello There Friend")
148 |  */
149 | export function fromKebabtoReadable(rawStr) {
150 |   return rawStr
151 |     .trim()
152 |     .split("-")
153 |     .map((n) => n[0].toUpperCase() + n.slice(1))
154 |     .join(" ");
155 | }
156 | 
157 | /**
158 |  * Deletes a file if it exists
159 |  * @param {string} filePath the full path of the file to delete
160 |  */
161 | export function deleteFileIfExists(filePath) {
162 |   if (existsSync(filePath)) {
163 |     unlinkSync(filePath);
164 |   }
165 | }
166 | 
167 | /**
168 |  * Removes duplicate new line characters adjecent to one another in a list of strings
169 |  * @param {string[]} buffer the list of strings
170 |  * @returns {string[]} the list of strings without duplicate new line characters
171 |  */
172 | export function removeAdjacentNewlines(buffer) {
173 |   const result = [];  
174 |   let prevWasNewline = false;
175 | 
176 |   for (const item of buffer) {
177 |     // Check if the current item is only newline characters
178 |     const isNewline = /^\s*$/.test(item);
179 | 
180 |     if (!isNewline || !prevWasNewline) {
181 |       result.push(item);
182 |     }
183 |     prevWasNewline = isNewline;
184 |   }
185 |   return result;
186 | }
187 | 
188 | /**
189 |  * The summary file may contain further sections other than the summary table.
190 |  * Thus, we only (re)generate the section that contains the summary table.
191 |  * This is done by finding the heading for the start of the summary table section
192 |  * and either the end of file or the next section heading.
193 |  * @param {string} buffer the string containing the file contents
194 |  * @param {string} sectionHeading The section to look for, has to have heading level as well
195 |  */
196 | export function getSectionBeforeAndAfter(buffer, sectionHeading) {
197 |   if (!sectionHeading) {
198 |     return { beforeSection: buffer, afterSection: "" };
199 |   }
200 | 
201 |   const lines = strBufferToLines(buffer);
202 |   const sectionStartIdx = lines.findIndex((line) => line.includes(sectionHeading));
203 | 
204 |   // If sectionHeading isn't found, return the buffer unchanged
205 |   if (sectionStartIdx === -1) {
206 |     return { beforeSection: buffer, afterSection: "" };
207 |   }
208 | 
209 |   // Find the next heading after the section heading
210 |   let nextHeadingIdx = -1;
211 |   for (let i = sectionStartIdx + 1; i < lines.length; i++) {
212 |     if (/^#+\s/.test(lines[i])) {
213 |       nextHeadingIdx = i;
214 |       break;
215 |     }
216 |   }
217 | 
218 |   // Remove lines after the section heading and before the next heading (or end of file)
219 |   const beforeSection = lines.slice(0, sectionStartIdx).join("\n");
220 |   const afterSection = (nextHeadingIdx !== -1 ? lines.slice(nextHeadingIdx) : []).join("\n");
221 | 
222 |   return { beforeSection, afterSection };
223 | }
224 | 
```

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

```markdown
  1 | %-DESC-START
  2 | 
  3 | **Key features:**
  4 | - **Flexible modes**: Single date selection (default) or date range selection
  5 | - **Format customization**: Support for various date formats (MM/dd/yyyy, yyyy-MM-dd, etc.)
  6 | - **Date restrictions**: Set minimum/maximum dates and disable specific dates
  7 | - **Localization options**: Configure first day of week and show week numbers
  8 | 
  9 | %-DESC-END
 10 | 
 11 | %-API-START setValue
 12 | 
 13 | ```xmlui-pg copy {3, 9, 12} display name="Example: setValue" height="500px"
 14 | <App>
 15 |   <HStack>
 16 |     <Button
 17 |       label="Set Date to 05/25/2024"
 18 |       onClick="picker.setValue('05/25/2024')" />
 19 |     <Button
 20 |       label="Remove Date"
 21 |       onClick="picker.setValue('')" />
 22 |   </HStack>
 23 |   <DatePicker inline id="picker" />
 24 | </App>
 25 | ```
 26 | 
 27 | %-API-END
 28 | 
 29 | %-PROP-START initialValue
 30 | 
 31 | ```xmlui-pg copy display name="Example: initialValue" height="440px"
 32 | <App>
 33 |   <DatePicker inline initialValue="05/25/2024" />
 34 | </App>  
 35 | ```
 36 | 
 37 | %-PROP-END
 38 | 
 39 | %-PROP-START placeholder
 40 | 
 41 | ```xmlui-pg copy display name="Example: placeholder" height="500px"
 42 | <App>
 43 |   <DatePicker placeholder="This is a placeholder" />
 44 | </App>  
 45 | ```
 46 | 
 47 | %-PROP-END
 48 | 
 49 | %-PROP-START enabled
 50 | 
 51 | ```xmlui-pg copy display name="Example: enabled" height="120px"
 52 | <App>
 53 |   <DatePicker enabled="false" />
 54 | </App>  
 55 | ```
 56 | 
 57 | %-PROP-END
 58 | 
 59 | %-PROP-START validationStatus
 60 | 
 61 | | Value     | Description                                           |
 62 | | :-------- | :---------------------------------------------------- |
 63 | | `valid`   | Visual indicator for an input that is accepted        |
 64 | | `warning` | Visual indicator for an input that produced a warning |
 65 | | `error`   | Visual indicator for an input that produced an error  |
 66 | 
 67 | ```xmlui-pg copy display name="Example: validationStatus" height="500px"
 68 | <App>
 69 |   <DatePicker />
 70 |   <DatePicker validationStatus="valid" />
 71 |   <DatePicker validationStatus="warning" />
 72 |   <DatePicker validationStatus="error" />
 73 | </App>
 74 | ```
 75 | 
 76 | %-PROP-END
 77 | 
 78 | %-PROP-START mode
 79 | 
 80 | ```xmlui-pg copy {2-3} display name="Example: mode" height="560px"
 81 | <App>
 82 |   <DatePicker mode="single" />
 83 |   <DatePicker mode="range" />
 84 | </App>
 85 | ```
 86 | 
 87 | %-PROP-END
 88 | 
 89 | %-PROP-START dateFormat
 90 | 
 91 | Formats handle years (`y`), months (`m` or `M`), days of the month (`d`).
 92 | Providing multiple placeholder letters changes the display of the date.
 93 | 
 94 | The table below shows the available date formats:
 95 | 
 96 | | Format     | Example    |
 97 | | :--------- | :--------- |
 98 | | MM/dd/yyyy | 05/25/2024 |
 99 | | MM-dd-yyyy | 05-25-2024 |
100 | | yyyy/MM/dd | 2024/05/25 |
101 | | yyyy-MM-dd | 2024-05-25 |
102 | | dd/MM/yyyy | 25/05/2024 |
103 | | dd-MM-yyyy | 25-05-2024 |
104 | | yyyyMMdd   | 20240525   |
105 | | MMddyyyy   | 05252024   |
106 | 
107 | ```xmlui-pg copy display name="Example: dateFormat" height="440px"
108 | <App>
109 |   <DatePicker 
110 |     inline 
111 |     dateFormat="dd-MM-yyyy" 
112 |     initialValue="05/25/2024" />
113 | </App>
114 | ```
115 | 
116 | %-PROP-END
117 | 
118 | %-PROP-START showWeekNumber
119 | 
120 | ```xmlui-pg copy display name="Example: showWeekNumber" height="500px"
121 | <App>
122 |   <DatePicker showWeekNumber="true" />
123 | </App>
124 | ```
125 | 
126 | %-PROP-END
127 | 
128 | %-PROP-START weekStartsOn
129 | 
130 | | Day       | Number |
131 | | :-------- | :----- |
132 | | Sunday    | 0      |
133 | | Monday    | 1      |
134 | | Tuesday   | 2      |
135 | | Wednesday | 3      |
136 | | Thursday  | 4      |
137 | | Friday    | 5      |
138 | | Saturday  | 6      |
139 | 
140 | ```xmlui-pg copy display name="Example: weekStartsOn" height="440px"
141 | <App>
142 |   <DatePicker inline weekStartsOn="1" />
143 | </App>
144 | ```
145 | 
146 | %-PROP-END
147 | 
148 | %-PROP-START minValue
149 | 
150 | ```xmlui-pg copy display name="Example: minValue" height="440px"
151 | <App>
152 |   <DatePicker inline minValue="05/24/2024" />
153 | </App>
154 | ```
155 | 
156 | %-PROP-END
157 | 
158 | %-PROP-START maxValue
159 | 
160 | ```xmlui-pg copy display name="Example: maxValue" height="440px"
161 | <App>
162 |   <DatePicker inline maxValue="05/26/2024" />
163 | </App>
164 | ```
165 | 
166 | %-PROP-END
167 | 
168 | %-PROP-START disabledDates
169 | 
170 | The `disabledDates` prop supports multiple patterns for disabling specific dates in the calendar. You can use Date objects, strings (parsed using the `dateFormat`), or complex matcher objects.
171 | 
172 | **Basic patterns:**
173 | 
174 | | Pattern | Description | Example |
175 | | :------ | :---------- | :------ |
176 | | Single string | Disable one specific date | `"05/25/2024"` |
177 | | Array of strings | Disable multiple specific dates | `["05/25/2024", "05/26/2024"]` |
178 | | Boolean | Disable all dates | `true` |
179 | 
180 | > [!INFO] You can use the [getDate()](/globals#getdate) function to query the current date.
181 | 
182 | ```xmlui-pg copy display name="Example: Disable specific dates" height="440px"
183 | <App>
184 |   <DatePicker 
185 |     inline 
186 |     disabledDates="{['05/26/2024', '05/27/2024']}" 
187 |     initialValue="05/25/2024" />
188 | </App>  
189 | ```
190 | 
191 | **Advanced patterns:**
192 | 
193 | | Pattern | Description | Example |
194 | | :------ | :---------- | :------ |
195 | | Date range | Disable a range of dates | `{from: "05/20/2024", to: "05/25/2024"}` |
196 | | Day of week | Disable specific weekdays (0=Sunday, 6=Saturday) | `{dayOfWeek: [0, 6]}` |
197 | | Before date | Disable all dates before a specific date | `{before: "05/25/2024"}` |
198 | | After date | Disable all dates after a specific date | `{after: "05/25/2024"}` |
199 | | Date interval | Disable dates between two dates (exclusive) | `{before: "05/30/2024", after: "05/20/2024"}` |
200 | 
201 | 
202 | ```xmlui-pg copy display name="Example: Disable weekends" height="440px"
203 | <App>
204 |   <DatePicker inline disabledDates="{{dayOfWeek: [0, 6]}}" />
205 | </App>  
206 | ```
207 | 
208 | ```xmlui-pg copy display name="Example: Disable date range" height="440px"
209 | <App>
210 |   <DatePicker 
211 |     inline 
212 |     disabledDates="{{from: '05/20/2024', to: '05/25/2024'}}" 
213 |     initialValue="05/18/2024" />
214 | </App>  
215 | ```
216 | 
217 | ```xmlui-pg copy display name="Example: Disable dates before today" height="440px"
218 | <App>
219 |   <DatePicker
220 |     inline 
221 |     disabledDates="{{before: getDate()}}"
222 |     intialValue="{getDate()}"/>
223 | </App>  
224 | ```
225 | 
226 | ```xmlui-pg copy display name="Example: Disable dates today and after" height="440px"
227 | <App>
228 |   <DatePicker
229 |     inline 
230 |     disabledDates="{[getDate(), {after: getDate()}]}"
231 |     intialValue="{getDate()}"/>
232 | </App>  
233 | ```
234 | 
235 | 
236 | ```xmlui-pg copy display name="Example: Complex combination" height="440px"
237 | <App>
238 |   <DatePicker 
239 |     inline
240 |     disabledDates="{[
241 |     {dayOfWeek: [0, 6]}, 
242 |     {from: '12/24/2024', to: '12/26/2024'}, 
243 |     '01/01/2025']}" 
244 |     initialValue="12/20/2024"
245 | />
246 | </App>  
247 | ```
248 | 
249 | %-PROP-END
250 | 
251 | %-EVENT-START didChange
252 | 
253 | Write in the input field and see how the `Text` underneath it is updated in parallel.
254 | 
255 | ```xmlui-pg copy {2} display name="Example: didChange" height="520px"
256 | <App var.field="(none)">
257 |   <Text value="{field}" />
258 |   <DatePicker 
259 |     inline
260 |     initialValue="{field}" 
261 |     onDidChange="(val) => field = val" />
262 | </App>
263 | ```
264 | 
265 | %-EVENT-END
266 | 
267 | %-EVENT-START gotFocus
268 | 
269 | Clicking on the `DatePicker` in the example demo changes the label text.
270 | Note how clicking elsewhere resets the text to the original.
271 | 
272 | ```xmlui-pg copy {4-5} display name="Example: gotFocus/lostFocus" height="540px"
273 | <App var.isFocused="false">
274 |   <Text value="{isFocused === true 
275 |     ? 'DatePicker focused' : 'DatePicker lost focus'}" 
276 |   />
277 |   <DatePicker
278 |     onGotFocus="isFocused = true"
279 |     onLostFocus="isFocused = false"
280 |   />
281 | </App>
282 | ```
283 | 
284 | %-EVENT-END
285 | 
286 | 
```

--------------------------------------------------------------------------------
/packages/xmlui-playground/src/playground/StandalonePlaygroundNative.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import { useEffect, useId, useMemo, useReducer, useRef, useState } from "react";
  2 | import {
  3 |   appDescriptionInitialized,
  4 |   contentChanged,
  5 |   optionsInitialized,
  6 |   PlaygroundContext,
  7 |   playgroundReducer,
  8 | } from "../state/store";
  9 | import { decompressData, INITIAL_PLAYGROUND_STATE } from "../utils/helpers";
 10 | import { ToastProvider } from "../providers/ToastProvider";
 11 | import styles from "./StandalonePlaygroundNative.module.scss";
 12 | import { useToast } from "../hooks/useToast";
 13 | import { ErrorBoundary, useThemes } from "xmlui";
 14 | import { Header } from "./Header";
 15 | import { PlaygroundContent } from "./PlaygroundContent";
 16 | import { Theme } from "../themes/theme";
 17 | 
 18 | export const StandalonePlayground = () => {
 19 |   const { showToast } = useToast();
 20 |   const id = useId();
 21 |   const [loading, setLoading] = useState(true);
 22 |   const { setActiveThemeTone } = useThemes();
 23 |   const [playgroundState, dispatch] = useReducer(playgroundReducer, INITIAL_PLAYGROUND_STATE);
 24 |   const initialized = useRef(false);
 25 | 
 26 |   const queryParams = useMemo(() => {
 27 |     if (typeof window !== "undefined") {
 28 |       return Object.fromEntries(new URLSearchParams("?app=" + window.location.hash.split("#")[2]));
 29 |     }
 30 |     return {};
 31 |   }, []);
 32 | 
 33 |   useEffect(() => {
 34 |     const getApp = async () => {
 35 |       try {
 36 |         const data = JSON.parse(await decompressData(queryParams.app as string));
 37 |         dispatch(appDescriptionInitialized(data.standalone));
 38 |         dispatch(
 39 |           optionsInitialized({
 40 |             ...playgroundState.options,
 41 |             ...data.options,
 42 |             content: "app",
 43 |             orientation: "horizontal",
 44 |           }),
 45 |         );
 46 |         setActiveThemeTone(data.options.activeTone || "light");
 47 |         dispatch(contentChanged(data.options.content));
 48 |       } catch (e) {
 49 |         showToast({
 50 |           type: "error",
 51 |           title: "Error",
 52 |           description: "The app could not be loaded",
 53 |         });
 54 |       }
 55 |       setLoading(false);
 56 |       initialized.current = true;
 57 |     };
 58 | 
 59 |     if (initialized.current) {
 60 |       return;
 61 |     } else {
 62 |       if (queryParams.app && queryParams.app !== "undefined") {
 63 |         getApp();
 64 |       } else {
 65 |         dispatch(
 66 |           appDescriptionInitialized({
 67 |             config: {
 68 |               name: "Hello World",
 69 |               description: "",
 70 |               appGlobals: {},
 71 |               resources: {},
 72 |               themes: [Theme],
 73 |             },
 74 |             components: [],
 75 |             app: "<App>Hello World!</App>",
 76 |           }),
 77 |         );
 78 |         dispatch(
 79 |           optionsInitialized({
 80 |             activeTheme: "theme",
 81 |             activeTone: "light",
 82 |             content: "app",
 83 |             orientation: "horizontal",
 84 |             id: 0,
 85 |             allowStandalone: true,
 86 |             language: "xmlui",
 87 |             emulatedApi: undefined,
 88 |             fixedTheme: false,
 89 |           }),
 90 |         );
 91 |         setLoading(false);
 92 |         initialized.current = true;
 93 |       }
 94 |     }
 95 |   }, [queryParams.app, showToast, setActiveThemeTone, playgroundState.options]);
 96 | 
 97 |   const playgroundContextValue = useMemo(() => {
 98 |     return {
 99 |       editorStatus: playgroundState.editorStatus,
100 |       status: playgroundState.status,
101 |       options: playgroundState.options,
102 |       text: playgroundState.text,
103 |       originalAppDescription: playgroundState.originalAppDescription,
104 |       appDescription: playgroundState.appDescription,
105 |       dispatch,
106 |       playgroundId: id,
107 |       error: playgroundState.error,
108 |     };
109 |   }, [
110 |     playgroundState.editorStatus,
111 |     playgroundState.status,
112 |     playgroundState.options,
113 |     playgroundState.text,
114 |     playgroundState.originalAppDescription,
115 |     playgroundState.appDescription,
116 |     id,
117 |     playgroundState.error,
118 |   ]);
119 | 
120 |   return (
121 |     <ToastProvider>
122 |       <PlaygroundContext.Provider value={playgroundContextValue}>
123 |         <ErrorBoundary>
124 |           {loading && <AnimatedLogo />}
125 |           {!loading && (
126 |             <div className={styles.standalonePlayground}>
127 |               {!playgroundState.options.previewMode && <Header standalone={true} />}
128 |               <div style={{ flexGrow: 1, overflow: "auto" }}>
129 |                 <PlaygroundContent standalone={true} />
130 |               </div>
131 |             </div>
132 |           )}
133 |         </ErrorBoundary>
134 |       </PlaygroundContext.Provider>
135 |     </ToastProvider>
136 |   );
137 | };
138 | 
139 | function AnimatedLogo() {
140 |   return (
141 |     <div className={styles.loadingContainer}>
142 |       <div className={styles.loadingText}>Loading XMLUI App...</div>
143 |       <div className={styles.logoWrapper}>
144 |         <svg viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg">
145 |           {/* Unchanged inner paths */}
146 |           <path
147 |             d="M9.04674 19.3954C8.2739 19.3954 7.60226 19.2265 7.03199 18.8887C6.47443 18.5384 6.0435 18.0505 5.73938 17.425C5.43526 16.7869 5.2832 16.0362 5.2832 15.173V9.89961C5.2832 9.7745 5.32771 9.66815 5.41637 9.58059C5.50502 9.493 5.61275 9.44922 5.73938 9.44922H7.41222C7.55157 9.44922 7.6593 9.493 7.73524 9.58059C7.8239 9.66815 7.86841 9.7745 7.86841 9.89961V15.0604C7.86841 16.6117 8.55895 17.3874 9.94021 17.3874C10.5991 17.3874 11.1187 17.181 11.4988 16.7681C11.8917 16.3553 12.0881 15.786 12.0881 15.0604V9.89961C12.0881 9.7745 12.1325 9.66815 12.2211 9.58059C12.3098 9.493 12.4175 9.44922 12.5443 9.44922H14.217C14.3436 9.44922 14.4513 9.493 14.54 9.58059C14.6288 9.66815 14.6732 9.7745 14.6732 9.89961V18.7574C14.6732 18.8825 14.6288 18.9888 14.54 19.0764C14.4513 19.164 14.3436 19.2078 14.217 19.2078H12.6773C12.538 19.2078 12.4239 19.164 12.3352 19.0764C12.2591 18.9888 12.2211 18.8825 12.2211 18.7574V17.988C11.879 18.4258 11.4545 18.7699 10.9476 19.0201C10.4407 19.2703 9.80704 19.3954 9.04674 19.3954Z"
148 |             fill="#3367CC"
149 |           />
150 |           <path
151 |             d="M17.6397 19.2104C17.5129 19.2104 17.4052 19.1666 17.3165 19.079C17.2279 18.9914 17.1835 18.8851 17.1835 18.76V9.90221C17.1835 9.7771 17.2279 9.67075 17.3165 9.58319C17.4052 9.4956 17.5129 9.45182 17.6397 9.45182H19.2174C19.3567 9.45182 19.4644 9.4956 19.5404 9.58319C19.6292 9.67075 19.6736 9.7771 19.6736 9.90221V18.76C19.6736 18.8851 19.6292 18.9914 19.5404 19.079C19.4644 19.1666 19.3567 19.2104 19.2174 19.2104H17.6397ZM17.5636 7.8379C17.4243 7.8379 17.3102 7.80038 17.2215 7.72531C17.1454 7.63773 17.1074 7.52514 17.1074 7.38751V6.03633C17.1074 5.91122 17.1454 5.80487 17.2215 5.71731C17.3102 5.62972 17.4243 5.58594 17.5636 5.58594H19.2933C19.4327 5.58594 19.5467 5.62972 19.6354 5.71731C19.7242 5.80487 19.7686 5.91122 19.7686 6.03633V7.38751C19.7686 7.52514 19.7242 7.63773 19.6354 7.72531C19.5467 7.80038 19.4327 7.8379 19.2933 7.8379H17.5636Z"
152 |             fill="#3367CC"
153 |           />
154 | 
155 |           {/* ✨ MODIFIED outer path for animation */}
156 |           <path
157 |             className={styles.animatedLogoPath}
158 |             d="M23.0215 2.81748H2.53486V23.044H23.0215V2.81748Z"
159 |             fill="none"
160 |             stroke="#3367CC"
161 |             strokeWidth="0.75"
162 |           />
163 |         </svg>
164 |       </div>
165 |     </div>
166 |   );
167 | }
168 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components/App/App.module.scss:
--------------------------------------------------------------------------------

```scss
  1 | @use "../../components-core/theming/themes" as t;
  2 | 
  3 | // --- This code snippet is required to collect the theme variables used in this module
  4 | $themeVars: ();
  5 | @function createThemeVar($componentVariable) {
  6 |   $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global;
  7 |   @return t.getThemeVar($themeVars, $componentVariable);
  8 | }
  9 | 
 10 | $width-navPanel-App: createThemeVar("width-navPanel-App");
 11 | $backgroundColor-navPanel-App: createThemeVar("backgroundColor-navPanel-App");
 12 | $boxShadow-header-App: createThemeVar("boxShadow-header-App");
 13 | $boxShadow-navPanel-App: createThemeVar("boxShadow-navPanel-App");
 14 | $backgroundColor-content-App: createThemeVar("backgroundColor-content-App");
 15 | $borderLeft-content-App: createThemeVar("borderLeft-content-App");
 16 | $maxWidth-content-App: createThemeVar("maxWidth-content-App");
 17 | $maxWidth-App: createThemeVar("maxWidth-App");
 18 | $backgroundColor-AppHeader: createThemeVar("backgroundColor-AppHeader");
 19 | $borderBottom-NavPanel: createThemeVar("borderBottom-AppHeader");
 20 | $scrollPaddingBlockPage: createThemeVar("scroll-padding-block-Pages");
 21 | 
 22 | // Variables for @layer section
 23 | $maxWidth-App: createThemeVar("maxWidth-App");
 24 | 
 25 | @layer components {
 26 |   @include t.withMaxScreenSize(0) {
 27 |     .wrapper.verticalFullHeader{
 28 |       .navPanelWrapper{
 29 |         display: none;
 30 |       }
 31 |     }
 32 |   }
 33 | 
 34 | 
 35 | 
 36 |   .wrapper {
 37 |     --footer-height: 0px;
 38 |     --header-height: 0px;
 39 |     width: 100%;
 40 |     height: 100%;
 41 |     position: relative; //leave it here, otherwise there could be double scrollbars because of the absolute positionings (typically radix's visuallyHidden)
 42 |     display: flex;
 43 |     flex-direction: column;
 44 |     isolation: isolate;
 45 | 
 46 |     &.vertical {
 47 |       flex-direction: row;
 48 |       overflow: initial;
 49 | 
 50 |       .contentWrapper {
 51 |         overflow: auto;
 52 |         scroll-padding-block: $scrollPaddingBlockPage;
 53 |         position: relative;
 54 |         scrollbar-gutter: stable both-edges;
 55 |       }
 56 |       &.noScrollbarGutters{
 57 |         .contentWrapper {
 58 |           scrollbar-gutter: auto;
 59 |         }
 60 |       }
 61 |       .navPanelWrapper {
 62 |         width: $width-navPanel-App;
 63 |         flex-shrink: 0;
 64 |       }
 65 | 
 66 |       .PagesWrapper {
 67 |         min-height: initial;
 68 |         flex: 1;
 69 |       }
 70 | 
 71 |       .footerWrapper {
 72 |         position: static;
 73 |       }
 74 |       &.sticky {
 75 |         .footerWrapper {
 76 |           position: sticky;
 77 |           bottom: 0;
 78 |         }
 79 |       }
 80 |     }
 81 | 
 82 |     &.horizontal {
 83 |       overflow: auto;
 84 |       scroll-padding-block: $scrollPaddingBlockPage;
 85 |       .PagesWrapper {
 86 |         min-height: initial;
 87 |       }
 88 |       .footerWrapper {
 89 |         position: static;
 90 |       }
 91 |       &.sticky {
 92 |         min-height: 100%;
 93 |         .footerWrapper {
 94 |           position: sticky;
 95 |           bottom: 0;
 96 |         }
 97 |       }
 98 |       .navPanelWrapper {
 99 |         border-bottom: $borderBottom-NavPanel;
100 |         justify-content: end;
101 |         background-color: $backgroundColor-navPanel-App;
102 |       }
103 |     }
104 | 
105 |     &.verticalFullHeader {
106 |       min-height: 100%;
107 |       height: 100%;
108 |       overflow: auto;
109 |       scroll-padding-block: $scrollPaddingBlockPage;
110 |       .navPanelWrapper {
111 |         width: $width-navPanel-App;
112 |         position: sticky;
113 |         height: calc(var(--containerHeight, 100vh) - var(--footer-height) - var(--header-height));
114 |         top: var(--header-height);
115 | 
116 |         &::before {
117 |           content: "";
118 |           position: absolute;
119 |           top: 0;
120 |           right: 0;
121 |           bottom: 0;
122 |           width: 50vw;
123 |           z-index: -1;
124 |           background-color: $backgroundColor-navPanel-App;
125 |         }
126 |       }
127 |       .PagesWrapper {
128 |         overflow: initial;
129 |         min-height: calc(var(--containerHeight, 100vh) - var(--header-height) - var(--footer-height));
130 |         height: 100%;
131 |       }
132 | 
133 |       .PagesWrapperInner {
134 |         height: 100%;
135 |         & > :global(.xmlui-page-root) {
136 |           height: 100%;
137 |         }
138 |       }
139 | 
140 |       .footerWrapper {
141 |         position: sticky;
142 |         left: 0;
143 |         right: 0;
144 |         bottom: 0;
145 |       }
146 |     }
147 | 
148 |     &.scrollWholePage {
149 |       scrollbar-gutter: stable both-edges;
150 | 
151 |       .headerWrapper {
152 |         & > div {
153 |           padding-inline: var(--scrollbar-width);
154 |         }
155 |         margin-inline: calc(-1 * var(--scrollbar-width));
156 |       }
157 | 
158 |       .footerWrapper {
159 |         margin-inline: calc(-1 * var(--scrollbar-width));
160 |         & > div {
161 |           padding-inline: var(--scrollbar-width);
162 |         }
163 |       }
164 | 
165 |       &.verticalFullHeader {
166 |         .content {
167 |           margin-inline: calc(-1 * var(--scrollbar-width));
168 |           width: calc(100% + (2 * var(--scrollbar-width)));
169 |         }
170 |         .contentWrapper {
171 |           padding-inline: var(--scrollbar-width);
172 |         }
173 |       }
174 |     }
175 | 
176 |     &:not(.scrollWholePage) {
177 |       overflow: hidden;
178 |       .content {
179 |         min-height: 0;
180 |         height: 100%;
181 |       }
182 |       .contentWrapper {
183 |         overflow: initial;
184 |       }
185 |       .PagesWrapper {
186 |         overflow: auto;
187 |         scroll-padding-block: $scrollPaddingBlockPage;
188 |         min-height: 0;
189 |         height: 100%;
190 |         scrollbar-gutter: stable both-edges;
191 |       }
192 |       .PagesWrapperInner {
193 |         min-height: 100%;
194 |         height: 0;
195 |       }
196 |     }
197 | 
198 |     &.noScrollbarGutters {
199 |       scrollbar-gutter: auto;
200 |       .PagesWrapper{
201 |         scrollbar-gutter: auto;
202 |       }
203 |     }
204 |   }
205 | 
206 |   .headerWrapper {
207 |     z-index: 1;
208 |     //position: relative;
209 |     min-height: 0;
210 |     flex-shrink: 0;
211 |     overflow-x: clip;
212 |     top: 0;
213 |     box-shadow: $boxShadow-header-App;
214 |     background-color: $backgroundColor-AppHeader;
215 |     &.sticky {
216 |       position: sticky;
217 |     }
218 |   }
219 | 
220 |   .content {
221 |     display: flex;
222 |     flex-direction: row;
223 |     isolation: isolate;
224 |     align-self: center;
225 |     width: 100%;
226 |     max-width: $maxWidth-App;
227 |   }
228 | 
229 |   .contentWrapper {
230 |     position: relative;
231 |     min-width: 0;
232 |     flex: 1;
233 |     display: flex;
234 |     flex-direction: column;
235 |     box-shadow: $boxShadow-navPanel-App;
236 |     background-color: $backgroundColor-content-App;
237 |     border-left: $borderLeft-content-App;
238 |   }
239 | 
240 |   .navPanelWrapper {
241 |     display: flex;
242 |     position: sticky;
243 |     top: 0;
244 | 
245 |     &:empty {
246 |       display: none;
247 |     }
248 |   }
249 | 
250 |   .PagesWrapper {
251 |     flex: 1;
252 |     //display: flex;
253 |     //flex-direction: column;
254 |     //flex: 1;
255 |     //min-height: 0;
256 |     //width: 100%;
257 |     isolation: isolate;
258 |     //height: 100%;
259 |     //overflow: auto;
260 |   }
261 | 
262 |   .PagesWrapperInner {
263 |     max-width: $maxWidth-content-App;
264 |     width: 100%;
265 |     margin: 0 auto;
266 |     //flex: 1;
267 |     min-height: 100%;
268 |     display: flex;
269 |     flex-direction: column;
270 |     &.withDefaultContentPadding{
271 |       padding-left: t.$space-4;
272 |       padding-right: t.$space-4;
273 |       padding-top: t.$space-5;
274 |       padding-bottom: t.$space-5;
275 |       gap: t.$space-5;
276 |     }
277 |   }
278 | 
279 |   .footerWrapper {
280 |     flex-shrink: 0;
281 |     //position: sticky;
282 |     //bottom:  calc(-1 * var(--footer-height));
283 |     //margin-bottom: calc(-1 * var(--footer-height));
284 |   }
285 | }
286 | 
287 | 
288 | // --- We export the theme variables to add them to the component renderer
289 | :export {
290 |   themeVars: t.json-stringify($themeVars);
291 | }
```

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

```markdown
  1 | # NavPanel [#navpanel]
  2 | 
  3 | `NavPanel` defines the navigation structure within an App, serving as a container for NavLink and NavGroup components that create your application's primary navigation menu. Its appearance and behavior automatically adapt based on the App's layout configuration.
  4 | 
  5 | **Key features:**
  6 | 
  7 | - **Layout adaptation**: Automatically positions navigation horizontally or vertically based on App layout
  8 | - **Navigation organization**: Contains NavLink and NavGroup components to build structured menus
  9 | - **Logo integration**: Supports custom logo templates in vertical layouts via logoTemplate property
 10 | - **Drawer mode**: Can optionally display navigation in a collapsible drawer interface
 11 | - **Theme integration**: Inherits styling from the app's theme system for consistent appearance
 12 | 
 13 | ## Properties [#properties]
 14 | 
 15 | ### `inDrawer` (default: false) [#indrawer-default-false]
 16 | 
 17 | This property determines if the navigation panel is displayed in a drawer.
 18 | 
 19 | ### `logoTemplate` [#logotemplate]
 20 | 
 21 | This property defines the logo template to display in the navigation panel with the `vertical` and `vertical-sticky` layout.
 22 | 
 23 | ```xmlui-pg copy {3-8} display name="Example: logoTemplate" height={250}
 24 | <App layout="vertical">
 25 |   <NavPanel>
 26 |     <property name="logoTemplate">
 27 |        <H3>
 28 |          <Icon name="drive" />
 29 |          DriveDiag (Nav)
 30 |        </H3>
 31 |     </property>
 32 |     <NavLink label="Home" to="/" icon="home"/>
 33 |     <NavLink label="Page 1" to="/page1"/>
 34 |   </NavPanel>
 35 |   <Pages fallbackPath="/">
 36 |     <Page url="/">
 37 |       <Text value="Home" />
 38 |     </Page>
 39 |     <Page url="/page1">
 40 |       <Text value="Page 1" />
 41 |     </Page>
 42 |   </Pages>
 43 | </App>
 44 | ```
 45 | 
 46 | ## Events [#events]
 47 | 
 48 | This component does not have any events.
 49 | 
 50 | ## Exposed Methods [#exposed-methods]
 51 | 
 52 | This component does not expose any methods.
 53 | 
 54 | ## Styling [#styling]
 55 | 
 56 | ### Theme Variables [#theme-variables]
 57 | 
 58 | | Variable | Default Value (Light) | Default Value (Dark) |
 59 | | --- | --- | --- |
 60 | | [backgroundColor](../styles-and-themes/common-units/#color)-NavPanel | $backgroundColor | $backgroundColor |
 61 | | [backgroundColor](../styles-and-themes/common-units/#color)-NavPanel-horizontal | $backgroundColor-AppHeader | $backgroundColor-AppHeader |
 62 | | [border](../styles-and-themes/common-units/#border)-NavPanel | 0px solid $borderColor | 0px solid $borderColor |
 63 | | [borderBottom](../styles-and-themes/common-units/#border)-NavPanel | *none* | *none* |
 64 | | [borderBottomColor](../styles-and-themes/common-units/#color)-NavPanel | *none* | *none* |
 65 | | [borderBottomStyle](../styles-and-themes/common-units/#border-style)-NavPanel | *none* | *none* |
 66 | | [borderBottomWidth](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
 67 | | [borderColor](../styles-and-themes/common-units/#color)-NavPanel | *none* | *none* |
 68 | | [borderEndEndRadius](../styles-and-themes/common-units/#border-rounding)-NavPanel | *none* | *none* |
 69 | | [borderEndStartRadius](../styles-and-themes/common-units/#border-rounding)-NavPanel | *none* | *none* |
 70 | | [borderHorizontal](../styles-and-themes/common-units/#border)-NavPanel | *none* | *none* |
 71 | | [borderHorizontalColor](../styles-and-themes/common-units/#color)-NavPanel | *none* | *none* |
 72 | | [borderHorizontalStyle](../styles-and-themes/common-units/#border-style)-NavPanel | *none* | *none* |
 73 | | [borderHorizontalWidth](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
 74 | | [borderLeft](../styles-and-themes/common-units/#border)-NavPanel | *none* | *none* |
 75 | | [color](../styles-and-themes/common-units/#color)-NavPanel | *none* | *none* |
 76 | | [borderLeftStyle](../styles-and-themes/common-units/#border-style)-NavPanel | *none* | *none* |
 77 | | [borderLeftWidth](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
 78 | | [borderRight](../styles-and-themes/common-units/#border)-NavPanel | *none* | *none* |
 79 | | [color](../styles-and-themes/common-units/#color)-NavPanel | *none* | *none* |
 80 | | [borderRightStyle](../styles-and-themes/common-units/#border-style)-NavPanel | *none* | *none* |
 81 | | [borderRightWidth](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
 82 | | [borderStartEndRadius](../styles-and-themes/common-units/#border-rounding)-NavPanel | *none* | *none* |
 83 | | [borderStartStartRadius](../styles-and-themes/common-units/#border-rounding)-NavPanel | *none* | *none* |
 84 | | [borderStyle](../styles-and-themes/common-units/#border-style)-NavPanel | *none* | *none* |
 85 | | [borderTop](../styles-and-themes/common-units/#border)-NavPanel | *none* | *none* |
 86 | | [borderTopColor](../styles-and-themes/common-units/#color)-NavPanel | *none* | *none* |
 87 | | [borderTopStyle](../styles-and-themes/common-units/#border-style)-NavPanel | *none* | *none* |
 88 | | [borderTopWidth](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
 89 | | [borderHorizontal](../styles-and-themes/common-units/#border)-NavPanel | *none* | *none* |
 90 | | [borderVerticalColor](../styles-and-themes/common-units/#color)-NavPanel | *none* | *none* |
 91 | | [borderVerticalStyle](../styles-and-themes/common-units/#border-style)-NavPanel | *none* | *none* |
 92 | | [borderVerticalWidth](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
 93 | | [borderWidth](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
 94 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NavPanel | *none* | *none* |
 95 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NavPanel-vertical | 4px 0 4px 0 rgb(0 0 0 / 10%) | 4px 0 4px 0 rgb(0 0 0 / 10%) |
 96 | | [horizontalAlignment](../styles-and-themes/common-units/#alignment)-logo-NavPanel | center | center |
 97 | | [marginBottom](../styles-and-themes/common-units/#size)-logo-NavPanel | $space-4 | $space-4 |
 98 | | [padding](../styles-and-themes/common-units/#size)-logo-NavPanel | *none* | *none* |
 99 | | [padding](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
100 | | [paddingBottom](../styles-and-themes/common-units/#size)-logo-NavPanel | *none* | *none* |
101 | | [paddingBottom](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
102 | | [paddingHorizontal](../styles-and-themes/common-units/#size)-logo-NavPanel | $space-4 | $space-4 |
103 | | [paddingHorizontal](../styles-and-themes/common-units/#size)-NavPanel | 0 | 0 |
104 | | [paddingLeft](../styles-and-themes/common-units/#size)-logo-NavPanel | *none* | *none* |
105 | | [paddingLeft](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
106 | | [paddingRight](../styles-and-themes/common-units/#size)-logo-NavPanel | *none* | *none* |
107 | | [paddingRight](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
108 | | [paddingTop](../styles-and-themes/common-units/#size)-logo-NavPanel | *none* | *none* |
109 | | [paddingTop](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
110 | | [paddingVertical](../styles-and-themes/common-units/#size)-logo-NavPanel | $space-4 | $space-4 |
111 | | [paddingVertical](../styles-and-themes/common-units/#size)-NavPanel | *none* | *none* |
112 | 
```

--------------------------------------------------------------------------------
/xmlui/scripts/extract-component-metadata.js:
--------------------------------------------------------------------------------

```javascript
  1 | const fs = require('fs');
  2 | const path = require('path');
  3 | 
  4 | const componentsDir = path.join(__dirname, '..', 'src', 'components');
  5 | 
  6 | // Component directories to scan
  7 | const componentDirs = [
  8 |   'Accordion', 'APICall', 'App', 'AppHeader', 'AppState', 'AutoComplete', 'Avatar',
  9 |   'Backdrop', 'Badge', 'Bookmark', 'Breakout', 'Button', 'Card', 'Carousel', 
 10 |   'ChangeListener', 'Checkbox', 'CodeBlock', 'ColorPicker', 'Column', 'ContentSeparator',
 11 |   'DataSource', 'DateInput', 'DatePicker', 'DropdownMenu', 'EmojiSelector', 'ExpandableItem',
 12 |   'FileInput', 'FileUploadDropZone', 'FlowLayout', 'Footer', 'Form', 'FormItem', 'Fragment',
 13 |   'Heading', 'HoverCard', 'IFrame', 'Image', 'InspectButton', 'Items', 'Link', 'List',
 14 |   'Logo', 'Markdown', 'ModalDialog', 'NavGroup', 'NavLink', 'NavPanel', 'NestedApp',
 15 |   'NoResult', 'NumberBox', 'Option', 'PageMetaTitle', 'Pages', 'Pagination',
 16 |   'PositionedContainer', 'ProfileMenu', 'ProgressBar', 'Queue', 'RadioGroup',
 17 |   'RealTimeAdapter', 'Redirect', 'ResponsiveBar', 'Select', 'SelectionStore', 'Slider',
 18 |   'Slot', 'SpaceFiller', 'Spinner', 'Splitter', 'Stack', 'StickyBox', 'Switch', 'Table',
 19 |   'TableOfContents', 'Tabs', 'Text', 'TextArea', 'TextBox', 'Theme', 'TimeInput', 'Timer',
 20 |   'Toggle', 'ToneChangerButton', 'ToneSwitch', 'Tooltip', 'Tree', 'TreeDisplay',
 21 |   'ValidationSummary', 'Charts/AreaChart', 'Charts/BarChart', 'Charts/DonutChart',
 22 |   'Charts/LabelList', 'Charts/Legend', 'Charts/LineChart', 'Charts/PieChart', 'Charts/RadarChart'
 23 | ];
 24 | 
 25 | const results = [];
 26 | 
 27 | // Function to check if SCSS file has unexposed theme variables
 28 | function hasUnexposedThemeVars(componentDir) {
 29 |   try {
 30 |     const files = fs.readdirSync(componentDir);
 31 |     const scssFiles = files.filter(f => f.endsWith('.scss') || f.endsWith('.module.scss'));
 32 |     
 33 |     for (const scssFile of scssFiles) {
 34 |       const scssPath = path.join(componentDir, scssFile);
 35 |       const content = fs.readFileSync(scssPath, 'utf8');
 36 |       
 37 |       // Find all @layer blocks and check if createThemeVar is called inside them
 38 |       if (hasCreateThemeVarInBlock(content, '@layer')) {
 39 |         return true;
 40 |       }
 41 |       
 42 |       // Find all @mixin blocks and check if createThemeVar is called inside them
 43 |       if (hasCreateThemeVarInBlock(content, '@mixin')) {
 44 |         return true;
 45 |       }
 46 |     }
 47 |   } catch (error) {
 48 |     // Ignore errors for directories that don't exist or can't be read
 49 |   }
 50 |   return false;
 51 | }
 52 | 
 53 | // Helper function to check if createThemeVar is called inside a specific block type
 54 | function hasCreateThemeVarInBlock(content, blockType) {
 55 |   const lines = content.split('\n');
 56 |   let insideBlock = false;
 57 |   let braceCount = 0;
 58 |   
 59 |   for (let i = 0; i < lines.length; i++) {
 60 |     const line = lines[i];
 61 |     
 62 |     // Check if we're entering a block
 63 |     if (new RegExp(`${blockType}\\s`).test(line)) {
 64 |       insideBlock = true;
 65 |     }
 66 |     
 67 |     if (insideBlock) {
 68 |       // Count braces
 69 |       const openBraces = (line.match(/\{/g) || []).length;
 70 |       const closeBraces = (line.match(/\}/g) || []).length;
 71 |       braceCount += openBraces - closeBraces;
 72 |       
 73 |       // Check if createThemeVar is called in this line
 74 |       if (/createThemeVar\s*\(/i.test(line)) {
 75 |         return true;
 76 |       }
 77 |       
 78 |       // If we've closed all braces, we're out of the block
 79 |       if (braceCount === 0 && openBraces > 0) {
 80 |         insideBlock = false;
 81 |       }
 82 |     }
 83 |   }
 84 |   
 85 |   return false;
 86 | }
 87 | 
 88 | // Function to extract metadata from a file
 89 | function extractMetadata(filePath, componentName) {
 90 |   try {
 91 |     const content = fs.readFileSync(filePath, 'utf8');
 92 |     
 93 |     // Find all createMetadata calls
 94 |     const metadataRegex = /export const (\w+Md) = createMetadata\(\{([\s\S]*?)\n\}\);/g;
 95 |     let match;
 96 |     
 97 |     while ((match = metadataRegex.exec(content)) !== null) {
 98 |       const mdName = match[1];
 99 |       const mdContent = match[2];
100 |       
101 |       // Extract component name from metadata name (e.g., ButtonMd -> Button)
102 |       const name = mdName.replace(/Md$/, '');
103 |       
104 |       // Check if it has validationStatus in props
105 |       const hasValidationStatus = mdContent.includes('validationStatus:');
106 |       
107 |       // Extract parts - improved to handle nested braces
108 |       let parts = [];
109 |       let defaultPart = null;
110 |       
111 |       const partsStartIdx = mdContent.indexOf('parts: {');
112 |       if (partsStartIdx !== -1) {
113 |         let braceCount = 0;
114 |         let partsEndIdx = -1;
115 |         let startIdx = partsStartIdx + 'parts: {'.length - 1; // start at the opening brace
116 |         
117 |         for (let i = startIdx; i < mdContent.length; i++) {
118 |           if (mdContent[i] === '{') braceCount++;
119 |           else if (mdContent[i] === '}') {
120 |             braceCount--;
121 |             if (braceCount === 0) {
122 |               partsEndIdx = i;
123 |               break;
124 |             }
125 |           }
126 |         }
127 |         
128 |         if (partsEndIdx !== -1) {
129 |           const partsContent = mdContent.substring(startIdx + 1, partsEndIdx);
130 |           // Match part names - look for word followed by : and then { (part definition)
131 |           // This ensures we only get part names, not properties within parts like "description"
132 |           const partMatches = partsContent.match(/^\s*(\w+)\s*:\s*\{/gm);
133 |           if (partMatches) {
134 |             parts = partMatches.map(p => p.trim().replace(/:\s*\{$/, '').trim());
135 |           }
136 |         }
137 |       }
138 |       
139 |       // Extract defaultPart
140 |       const defaultPartMatch = mdContent.match(/defaultPart:\s*["'](\w+)["']/);
141 |       if (defaultPartMatch) {
142 |         defaultPart = defaultPartMatch[1];
143 |       }
144 |       
145 |       // Get the directory of the component file to check for SCSS
146 |       const componentDir = path.dirname(filePath);
147 |       const hasUnexposedVars = hasUnexposedThemeVars(componentDir);
148 |       
149 |       results.push({
150 |         name,
151 |         hasValidationStatus,
152 |         parts: parts.length > 0 ? parts : null,
153 |         hasUnexposedThemeVars: hasUnexposedVars
154 |       });
155 |     }
156 |   } catch (error) {
157 |     // Ignore errors for files that don't exist
158 |   }
159 | }
160 | 
161 | // Scan all component directories
162 | componentDirs.forEach(dir => {
163 |   const fullPath = path.join(componentsDir, dir);
164 |   
165 |   // Try to find the main component file
166 |   const baseName = dir.split('/').pop();
167 |   const possibleFiles = [
168 |     path.join(fullPath, `${baseName}.tsx`),
169 |     path.join(fullPath, `${baseName}Component.tsx`),
170 |   ];
171 |   
172 |   possibleFiles.forEach(filePath => {
173 |     if (fs.existsSync(filePath)) {
174 |       extractMetadata(filePath, baseName);
175 |     }
176 |   });
177 | });
178 | 
179 | // Also check for special files
180 | const specialFiles = [
181 |   'DropdownMenu/DropdownMenu.tsx', // has multiple components
182 |   'Carousel/CarouselItem.tsx',
183 |   'RadioGroup/RadioItem.tsx',
184 |   'Tabs/TabItem.tsx',
185 |   'FormSection/FormSection.tsx',
186 | ];
187 | 
188 | specialFiles.forEach(file => {
189 |   const filePath = path.join(componentsDir, file);
190 |   const baseName = path.basename(file, '.tsx');
191 |   extractMetadata(filePath, baseName);
192 | });
193 | 
194 | // Sort by component name
195 | results.sort((a, b) => a.name.localeCompare(b.name));
196 | 
197 | // Output as JSON
198 | console.log(JSON.stringify(results, null, 2));
199 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components/FileInput/FileInputNative.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import type React from "react";
  2 | import { type CSSProperties, useCallback, useEffect, useId, useRef, useState } from "react";
  3 | import type { DropzoneRootProps } from "react-dropzone";
  4 | import * as dropzone from "react-dropzone";
  5 | import * as VisuallyHidden from "@radix-ui/react-visually-hidden";
  6 | import classnames from "classnames";
  7 | 
  8 | import styles from "./FileInput.module.scss";
  9 | 
 10 | import type { RegisterComponentApiFn, UpdateStateFn } from "../../abstractions/RendererDefs";
 11 | import { noop } from "../../components-core/constants";
 12 | import { useEvent } from "../../components-core/utils/misc";
 13 | import type { ValidationStatus } from "../abstractions";
 14 | import type { ButtonThemeColor, ButtonVariant, SizeType, IconPosition } from "../abstractions";
 15 | import { Button } from "../Button/ButtonNative";
 16 | import { TextBox } from "../TextBox/TextBoxNative";
 17 | 
 18 | // https://github.com/react-dropzone/react-dropzone/issues/1259
 19 | const { useDropzone } = dropzone;
 20 | 
 21 | // ============================================================================
 22 | // React FileInput component implementation
 23 | 
 24 | type Props = {
 25 |   // General
 26 |   id?: string;
 27 |   enabled?: boolean;
 28 |   style?: CSSProperties;
 29 |   className?: string;
 30 |   // Button styles
 31 |   buttonLabel?: string;
 32 |   variant?: ButtonVariant;
 33 |   buttonThemeColor?: ButtonThemeColor;
 34 |   buttonSize?: SizeType;
 35 |   buttonIcon?: React.ReactNode;
 36 |   buttonIconPosition?: IconPosition;
 37 |   // Input props
 38 |   updateState?: UpdateStateFn;
 39 |   onDidChange?: (newValue: File[]) => void;
 40 |   onFocus?: () => void;
 41 |   onBlur?: () => void;
 42 |   registerComponentApi?: RegisterComponentApiFn;
 43 |   validationStatus?: ValidationStatus;
 44 |   autoFocus?: boolean;
 45 |   // Component-specific props
 46 |   value?: any;
 47 |   initialValue?: any;
 48 |   acceptsFileType?: string | string[];
 49 |   multiple?: boolean;
 50 |   directory?: boolean;
 51 |   required?: boolean;
 52 |   placeholder?: string;
 53 |   buttonPosition?: "start" | "end";
 54 | };
 55 | 
 56 | export const defaultProps: Pick<
 57 |   Props,
 58 |   | "enabled"
 59 |   | "buttonPosition"
 60 |   | "buttonLabel"
 61 |   | "multiple"
 62 |   | "directory"
 63 |   | "updateState"
 64 |   | "onDidChange"
 65 |   | "onFocus"
 66 |   | "onBlur"
 67 |   | "buttonThemeColor"
 68 | > = {
 69 |   enabled: true,
 70 |   buttonPosition: "end",
 71 |   buttonLabel: "Browse",
 72 |   multiple: false,
 73 |   directory: false,
 74 |   buttonThemeColor: "primary",
 75 |   updateState: noop,
 76 |   onDidChange: noop,
 77 |   onFocus: noop,
 78 |   onBlur: noop,
 79 | };
 80 | 
 81 | export const FileInput = ({
 82 |   id,
 83 |   enabled = defaultProps.enabled,
 84 |   style,
 85 |   className,
 86 |   placeholder,
 87 |   buttonPosition = defaultProps.buttonPosition,
 88 |   buttonLabel = defaultProps.buttonLabel,
 89 |   buttonIcon,
 90 |   buttonIconPosition,
 91 |   variant,
 92 |   buttonThemeColor,
 93 |   buttonSize,
 94 | 
 95 |   autoFocus,
 96 |   validationStatus,
 97 |   updateState = defaultProps.updateState,
 98 |   onDidChange = defaultProps.onDidChange,
 99 |   onFocus = defaultProps.onFocus,
100 |   onBlur = defaultProps.onBlur,
101 |   registerComponentApi,
102 |   value,
103 |   initialValue,
104 |   acceptsFileType,
105 |   multiple = defaultProps.multiple,
106 |   directory = defaultProps.directory,
107 |   required,
108 |   ...rest
109 | }: Props) => {
110 |   const _id = useId();
111 |   id = id || _id;
112 |   // Don't accept any (initial) value if it is not a File array explicitly
113 |   const _initialValue: File[] | undefined = isFileArray(initialValue) ? initialValue : undefined;
114 |   const _value: File[] | undefined = isFileArray(value) ? value : undefined;
115 | 
116 |   const buttonRef = useRef<HTMLButtonElement>(null);
117 |   const _acceptsFileType =
118 |     typeof acceptsFileType === "string" ? acceptsFileType : acceptsFileType?.join(",");
119 | 
120 |   useEffect(() => {
121 |     if (autoFocus) {
122 |       setTimeout(() => {
123 |         buttonRef.current?.focus();
124 |       }, 0);
125 |     }
126 |   }, [autoFocus]);
127 | 
128 |   // --- Initialize the related field with the input's initial value
129 |   useEffect(() => {
130 |     updateState({ value: _initialValue }, { initial: true });
131 |   }, [_initialValue, updateState]);
132 | 
133 |   // --- Manage obtaining and losing the focus
134 |   const handleOnFocus = useCallback((e: React.FocusEvent) => {
135 |     // Only fire onFocus if focus is coming from outside the component
136 |     if (!e.currentTarget.contains(e.relatedTarget as Node)) {
137 |       onFocus?.();
138 |     }
139 |   }, [onFocus]);
140 | 
141 |   const handleOnBlur = useCallback((e: React.FocusEvent) => {
142 |     // Only fire onBlur if focus is leaving the component entirely
143 |     if (!e.currentTarget.contains(e.relatedTarget as Node)) {
144 |       onBlur?.();
145 |     }
146 |   }, [onBlur]);
147 | 
148 |   const focus = useCallback(() => {
149 |     buttonRef.current?.focus();
150 |   }, []);
151 | 
152 |   // --- Handle the value change events for this input
153 |   const onDrop = useCallback(
154 |     (acceptedFiles: File[]) => {
155 |       if (!acceptedFiles.length) return;
156 |       updateState({ value: acceptedFiles });
157 |       onDidChange(acceptedFiles);
158 |     },
159 |     [updateState, onDidChange],
160 |   );
161 | 
162 |   const { getRootProps, getInputProps, open } = useDropzone({
163 |     disabled: !enabled,
164 |     multiple: multiple || directory,
165 |     onDrop,
166 |     noClick: true,
167 |     noKeyboard: true,
168 |     noDragEventsBubbling: true,
169 |     useFsAccessApi: directory === false,
170 |   });
171 | 
172 |   const doOpen = useEvent(() => {
173 |     open();
174 |   });
175 | 
176 |   useEffect(() => {
177 |     registerComponentApi?.({
178 |       focus,
179 |       open: doOpen,
180 |     });
181 |   }, [focus, doOpen, registerComponentApi]);
182 | 
183 |   // Solution source: https://stackoverflow.com/questions/1084925/input-type-file-show-only-button
184 |   return (
185 |       <div
186 |         className={classnames(styles.container, className, {
187 |           [styles.buttonStart]: buttonPosition === "start",
188 |           [styles.buttonEnd]: buttonPosition === "end",
189 |         })}
190 |         style={style}
191 |         onFocus={handleOnFocus}
192 |         onBlur={handleOnBlur}
193 |         tabIndex={-1}
194 |         {...rest}
195 |       >
196 |         <button
197 |           id={id}
198 |           {...getRootProps({
199 |             tabIndex: 0,
200 |             disabled: !enabled,
201 |             className: styles.textBoxWrapper,
202 |             onClick: open,
203 |             ref: buttonRef,
204 |             type: "button",
205 |           })}
206 |         >
207 |           <VisuallyHidden.Root>
208 |             <input
209 |               {...getInputProps({
210 |                 webkitdirectory: directory ? "true" : undefined,
211 |               } as DropzoneRootProps)}
212 |               accept={_acceptsFileType}
213 |             />
214 |           </VisuallyHidden.Root>
215 | 
216 |           <TextBox
217 |             placeholder={placeholder}
218 |             enabled={enabled}
219 |             value={_value?.map((v) => v.name).join(", ") || ""}
220 |             validationStatus={validationStatus}
221 |             readOnly
222 |             tabIndex={-1}
223 |           />
224 |         </button>
225 |         <Button
226 |           disabled={!enabled}
227 |           type="button"
228 |           onClick={open}
229 |           icon={buttonIcon}
230 |           iconPosition={buttonIconPosition}
231 |           variant={variant}
232 |           themeColor={buttonThemeColor}
233 |           size={buttonSize}
234 |           className={styles.button}
235 |           autoFocus={autoFocus}
236 |         >
237 |           {buttonLabel}
238 |         </Button>
239 |       </div>
240 |   );
241 | };
242 | 
243 | export function isFile(value: any): value is File {
244 |   return value instanceof File;
245 | }
246 | 
247 | export function isFileArray(value: any): value is File[] {
248 |   return Array.isArray(value) && value.every(isFile);
249 | }
250 | 
```

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

```typescript
  1 | import styles from "./DatePicker.module.scss";
  2 | 
  3 | import { createComponentRenderer } from "../../components-core/renderers";
  4 | import { parseScssVar } from "../../components-core/theming/themeVars";
  5 | import {
  6 |   createMetadata,
  7 |   dAutoFocus,
  8 |   dDidChange,
  9 |   dEnabled,
 10 |   dEndIcon,
 11 |   dEndText,
 12 |   dGotFocus,
 13 |   dInitialValue,
 14 |   dLostFocus,
 15 |   dPlaceholder,
 16 |   dReadonly,
 17 |   dStartIcon,
 18 |   dStartText,
 19 |   dValidationStatus,
 20 | } from "../metadata-helpers";
 21 | import {
 22 |   dateFormats,
 23 |   DatePicker,
 24 |   DatePickerModeValues,
 25 |   defaultProps,
 26 |   WeekDays,
 27 | } from "./DatePickerNative";
 28 | 
 29 | const COMP = "DatePicker";
 30 | 
 31 | export const DatePickerMd = createMetadata({
 32 |   status: "experimental",
 33 |   description:
 34 |     "`DatePicker` provides an interactive calendar interface for selecting single dates " +
 35 |     "or date ranges, with customizable formatting and validation options. It displays " +
 36 |     "a text input that opens a calendar popup when clicked, offering both keyboard and " +
 37 |     "mouse interaction.",
 38 |   props: {
 39 |     placeholder: dPlaceholder(),
 40 |     initialValue: dInitialValue(),
 41 |     autoFocus: dAutoFocus(),
 42 |     readOnly: dReadonly(),
 43 |     enabled: dEnabled(defaultProps.enabled),
 44 |     validationStatus: dValidationStatus(defaultProps.validationStatus),
 45 |     mode: {
 46 |       description: "The mode of the datepicker (single or range)",
 47 |       valueType: "string",
 48 |       availableValues: DatePickerModeValues,
 49 |       defaultValue: defaultProps.mode,
 50 |     },
 51 |     dateFormat: {
 52 |       description: "The format of the date displayed in the input field",
 53 |       valueType: "string",
 54 |       defaultValue: defaultProps.dateFormat,
 55 |       availableValues: dateFormats,
 56 |     },
 57 |     showWeekNumber: {
 58 |       description: "Whether to show the week number in the calendar",
 59 |       valueType: "boolean",
 60 |       defaultValue: defaultProps.showWeekNumber,
 61 |     },
 62 |     weekStartsOn: {
 63 |       description: "The first day of the week. 0 is Sunday, 1 is Monday, etc.",
 64 |       valueType: "number",
 65 |       defaultValue: defaultProps.weekStartsOn,
 66 |       availableValues: [
 67 |         {
 68 |           value: WeekDays.Sunday,
 69 |           description: "Sunday",
 70 |         },
 71 |         {
 72 |           value: WeekDays.Monday,
 73 |           description: "Monday",
 74 |         },
 75 |         {
 76 |           value: WeekDays.Tuesday,
 77 |           description: "Tuesday",
 78 |         },
 79 |         {
 80 |           value: WeekDays.Wednesday,
 81 |           description: "Wednesday",
 82 |         },
 83 |         {
 84 |           value: WeekDays.Thursday,
 85 |           description: "Thursday",
 86 |         },
 87 |         {
 88 |           value: WeekDays.Friday,
 89 |           description: "Friday",
 90 |         },
 91 |         {
 92 |           value: WeekDays.Saturday,
 93 |           description: "Saturday",
 94 |         },
 95 |       ],
 96 |     },
 97 |     startDate: {
 98 |       description:
 99 |         "The earliest month to start the month navigation from (inclusive). " +
100 |         "If not defined, the component allows any dates in the past. " +
101 |         "Accepts the same date format as the `initialValue`." +
102 |         "Example: '2023-01-01' ensures the first month to select a date from is January 2023.",
103 |       valueType: "string",
104 |     },
105 |     endDate: {
106 |       description:
107 |         "The latest month to start the month navigation from (inclusive). " +
108 |         "If not defined, the component allows any future dates. " +
109 |         "Accepts the same date format as the `initialValue`." +
110 |         "Example: '2023-12-31' ensures the last month to select a date from is December 2023.",
111 |       valueType: "string",
112 |     },
113 |     disabledDates: {
114 |       description: "An optional array of dates that are to be disabled.",
115 |       valueType: "any",
116 |     },
117 |     inline: {
118 |       description:
119 |         "If set to true, the calendar is always visible and its panel is rendered as part of the layout." +
120 |         " If false, the calendar is shown in a popup when the input is focused or clicked.",
121 |       valueType: "boolean",
122 |       defaultValue: defaultProps.inline,
123 |     },
124 |     startText: dStartText(),
125 |     startIcon: dStartIcon(),
126 |     endText: dEndText(),
127 |     endIcon: dEndIcon(),
128 |   },
129 |   events: {
130 |     didChange: dDidChange(COMP),
131 |     gotFocus: dGotFocus(COMP),
132 |     lostFocus: dLostFocus(COMP),
133 |   },
134 |   apis: {
135 |     focus: {
136 |       description: `Focus the ${COMP} component.`,
137 |       signature: "focus(): void",
138 |     },
139 |     value: {
140 |       description: `You can query the component's value. If no value is set, it will retrieve \`undefined\`.`,
141 |       signature: "get value(): any",
142 |     },
143 |     setValue: {
144 |       description: `This method sets the current value of the ${COMP}.`,
145 |       signature: "set value(value: any): void",
146 |       parameters: {
147 |         value: "The new value to set for the date picker.",
148 |       },
149 |     },
150 |   },
151 |   themeVars: parseScssVar(styles.themeVars),
152 |   defaultThemeVars: {
153 |     [`boxShadow-menu-${COMP}`]: "$boxShadow-md",
154 |     [`borderRadius-menu-${COMP}`]: "$borderRadius",
155 |     [`textColor-value-${COMP}`]: "$textColor-primary",
156 |     [`borderColor-selectedItem-${COMP}`]: "$color-primary-200",
157 |     [`backgroundColor-menu-${COMP}`]: "$color-surface-50",
158 |     [`backgroundColor-item-${COMP}--hover`]: "$color-surface-100",
159 |     [`backgroundColor-item-${COMP}--active`]: "$color-surface-200",
160 |     [`paddingVertical-${COMP}`]: "$space-2",
161 |     [`paddingHorizontal-${COMP}`]: "$space-2",
162 |   },
163 | });
164 | 
165 | export const datePickerComponentRenderer = createComponentRenderer(
166 |   COMP,
167 |   DatePickerMd,
168 |   ({
169 |     node,
170 |     state,
171 |     updateState,
172 |     extractValue,
173 |     className,
174 |     lookupEventHandler,
175 |     registerComponentApi,
176 |   }) => {
177 |     return (
178 |       <DatePicker
179 |         className={className}
180 |         mode={extractValue(node.props?.mode)}
181 |         value={state?.value}
182 |         initialValue={extractValue(node.props.initialValue)}
183 |         enabled={extractValue.asOptionalBoolean(node.props.enabled)}
184 |         placeholder={extractValue.asOptionalString(node.props.placeholder)}
185 |         validationStatus={extractValue(node.props.validationStatus)}
186 |         updateState={updateState}
187 |         onDidChange={lookupEventHandler("didChange")}
188 |         onFocus={lookupEventHandler("gotFocus")}
189 |         onBlur={lookupEventHandler("lostFocus")}
190 |         registerComponentApi={registerComponentApi}
191 |         dateFormat={extractValue(node.props.dateFormat)}
192 |         showWeekNumber={extractValue.asOptionalBoolean(node.props.showWeekNumber)}
193 |         weekStartsOn={extractValue(node.props.weekStartsOn)}
194 |         startDate={extractValue(node.props.startDate)}
195 |         endDate={extractValue(node.props.endDate)}
196 |         disabledDates={extractValue(node.props.disabledDates)}
197 |         inline={extractValue.asOptionalBoolean(node.props.inline)}
198 |         startText={extractValue.asOptionalString(node.props.startText)}
199 |         startIcon={extractValue.asOptionalString(node.props.startIcon)}
200 |         endText={extractValue.asOptionalString(node.props.endText)}
201 |         endIcon={extractValue.asOptionalString(node.props.endIcon)}
202 |         readOnly={extractValue.asOptionalBoolean(node.props.readOnly)}
203 |         autoFocus={extractValue.asOptionalBoolean(node.props.autoFocus)}
204 |       />
205 |     );
206 |   },
207 | );
208 | 
```
Page 38/187FirstPrevNextLast