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

# Directory Structure

```
├── .changeset
│   ├── config.json
│   └── cool-queens-look.md
├── .eslintrc.cjs
├── .github
│   ├── build-checklist.png
│   ├── ISSUE_TEMPLATE
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows
│       ├── deploy-blog.yml
│       ├── deploy-docs-optimized.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
│   │   │   │   ├── blog-page-component.png
│   │   │   │   ├── blog-scrabble.png
│   │   │   │   ├── integrated-blog-search.png
│   │   │   │   └── lorem-ipsum.png
│   │   │   ├── lorem-ipsum.md
│   │   │   ├── newest-post.md
│   │   │   ├── older-post.md
│   │   │   └── welcome-to-the-xmlui-blog.md
│   │   ├── mockServiceWorker.js
│   │   ├── netlify.toml
│   │   ├── resources
│   │   │   ├── favicon.ico
│   │   │   ├── files
│   │   │   │   └── for-download
│   │   │   │       └── xmlui
│   │   │   │           └── xmlui-standalone.umd.js
│   │   │   ├── github.svg
│   │   │   ├── 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
│   │   │   ├── Debug.xmlui
│   │   │   └── PageNotFound.xmlui
│   │   ├── config.ts
│   │   ├── Main.xmlui
│   │   ├── Main.xmlui.xs
│   │   └── themes
│   │       ├── docs-theme.ts
│   │       ├── earthtone.ts
│   │       ├── xmlui-gray-on-default.ts
│   │       ├── xmlui-green-on-default.ts
│   │       └── xmlui-orange-on-default.ts
│   └── tsconfig.json
├── CONTRIBUTING.md
├── docs
│   ├── .gitignore
│   ├── CHANGELOG.md
│   ├── ComponentRefLinks.txt
│   ├── content
│   │   ├── _meta.json
│   │   ├── components
│   │   │   ├── _meta.json
│   │   │   ├── _overview.md
│   │   │   ├── APICall.md
│   │   │   ├── App.md
│   │   │   ├── AppHeader.md
│   │   │   ├── AppState.md
│   │   │   ├── AutoComplete.md
│   │   │   ├── Avatar.md
│   │   │   ├── Backdrop.md
│   │   │   ├── Badge.md
│   │   │   ├── BarChart.md
│   │   │   ├── Bookmark.md
│   │   │   ├── Breakout.md
│   │   │   ├── Button.md
│   │   │   ├── Card.md
│   │   │   ├── Carousel.md
│   │   │   ├── ChangeListener.md
│   │   │   ├── Checkbox.md
│   │   │   ├── CHStack.md
│   │   │   ├── ColorPicker.md
│   │   │   ├── Column.md
│   │   │   ├── ContentSeparator.md
│   │   │   ├── CVStack.md
│   │   │   ├── DataSource.md
│   │   │   ├── DateInput.md
│   │   │   ├── DatePicker.md
│   │   │   ├── DonutChart.md
│   │   │   ├── DropdownMenu.md
│   │   │   ├── EmojiSelector.md
│   │   │   ├── ExpandableItem.md
│   │   │   ├── FileInput.md
│   │   │   ├── FileUploadDropZone.md
│   │   │   ├── FlowLayout.md
│   │   │   ├── Footer.md
│   │   │   ├── Form.md
│   │   │   ├── FormItem.md
│   │   │   ├── FormSection.md
│   │   │   ├── Fragment.md
│   │   │   ├── H1.md
│   │   │   ├── H2.md
│   │   │   ├── H3.md
│   │   │   ├── H4.md
│   │   │   ├── H5.md
│   │   │   ├── H6.md
│   │   │   ├── Heading.md
│   │   │   ├── HSplitter.md
│   │   │   ├── HStack.md
│   │   │   ├── Icon.md
│   │   │   ├── IFrame.md
│   │   │   ├── Image.md
│   │   │   ├── Items.md
│   │   │   ├── LabelList.md
│   │   │   ├── Legend.md
│   │   │   ├── LineChart.md
│   │   │   ├── Link.md
│   │   │   ├── List.md
│   │   │   ├── Logo.md
│   │   │   ├── Markdown.md
│   │   │   ├── MenuItem.md
│   │   │   ├── MenuSeparator.md
│   │   │   ├── ModalDialog.md
│   │   │   ├── NavGroup.md
│   │   │   ├── NavLink.md
│   │   │   ├── NavPanel.md
│   │   │   ├── NoResult.md
│   │   │   ├── NumberBox.md
│   │   │   ├── Option.md
│   │   │   ├── Page.md
│   │   │   ├── PageMetaTitle.md
│   │   │   ├── Pages.md
│   │   │   ├── Pagination.md
│   │   │   ├── PasswordInput.md
│   │   │   ├── PieChart.md
│   │   │   ├── ProgressBar.md
│   │   │   ├── Queue.md
│   │   │   ├── RadioGroup.md
│   │   │   ├── RealTimeAdapter.md
│   │   │   ├── Redirect.md
│   │   │   ├── Select.md
│   │   │   ├── Slider.md
│   │   │   ├── Slot.md
│   │   │   ├── SpaceFiller.md
│   │   │   ├── Spinner.md
│   │   │   ├── Splitter.md
│   │   │   ├── Stack.md
│   │   │   ├── StickyBox.md
│   │   │   ├── SubMenuItem.md
│   │   │   ├── Switch.md
│   │   │   ├── TabItem.md
│   │   │   ├── Table.md
│   │   │   ├── TableOfContents.md
│   │   │   ├── Tabs.md
│   │   │   ├── Text.md
│   │   │   ├── TextArea.md
│   │   │   ├── TextBox.md
│   │   │   ├── Theme.md
│   │   │   ├── TimeInput.md
│   │   │   ├── Timer.md
│   │   │   ├── ToneChangerButton.md
│   │   │   ├── ToneSwitch.md
│   │   │   ├── Tooltip.md
│   │   │   ├── Tree.md
│   │   │   ├── VSplitter.md
│   │   │   ├── VStack.md
│   │   │   ├── xmlui-animations
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   ├── Animation.md
│   │   │   │   ├── FadeAnimation.md
│   │   │   │   ├── FadeInAnimation.md
│   │   │   │   ├── FadeOutAnimation.md
│   │   │   │   ├── ScaleAnimation.md
│   │   │   │   └── SlideInAnimation.md
│   │   │   ├── xmlui-pdf
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   └── Pdf.md
│   │   │   ├── xmlui-spreadsheet
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   └── Spreadsheet.md
│   │   │   └── xmlui-website-blocks
│   │   │       ├── _meta.json
│   │   │       ├── _overview.md
│   │   │       ├── Carousel.md
│   │   │       ├── HelloMd.md
│   │   │       ├── HeroSection.md
│   │   │       └── ScrollToTop.md
│   │   └── extensions
│   │       ├── _meta.json
│   │       ├── xmlui-animations
│   │       │   ├── _meta.json
│   │       │   ├── _overview.md
│   │       │   ├── Animation.md
│   │       │   ├── FadeAnimation.md
│   │       │   ├── FadeInAnimation.md
│   │       │   ├── FadeOutAnimation.md
│   │       │   ├── ScaleAnimation.md
│   │       │   └── SlideInAnimation.md
│   │       └── xmlui-website-blocks
│   │           ├── _meta.json
│   │           ├── _overview.md
│   │           ├── Carousel.md
│   │           ├── HelloMd.md
│   │           ├── HeroSection.md
│   │           └── ScrollToTop.md
│   ├── extensions.ts
│   ├── index.html
│   ├── index.ts
│   ├── package.json
│   ├── public
│   │   ├── feed.rss
│   │   ├── mockServiceWorker.js
│   │   ├── pages
│   │   │   ├── _meta.json
│   │   │   ├── app-structure.md
│   │   │   ├── build-editor-component.md
│   │   │   ├── build-hello-world-component.md
│   │   │   ├── components-intro.md
│   │   │   ├── context-variables.md
│   │   │   ├── forms.md
│   │   │   ├── globals.md
│   │   │   ├── glossary.md
│   │   │   ├── helper-tags.md
│   │   │   ├── hosted-deployment.md
│   │   │   ├── howto
│   │   │   │   ├── assign-a-complex-json-literal-to-a-component-variable.md
│   │   │   │   ├── chain-a-refetch.md
│   │   │   │   ├── 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
│   │   │   │   ├── 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
│   ├── 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
│   │   └── tsconfig.json
│   ├── 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
│   │   ├── tsconfig.json
│   │   └── 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
│   │   └── tsconfig.json
│   ├── 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
│   │   └── tsconfig.json
│   ├── 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
│   │   └── tsconfig.json
│   ├── 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
│   │   └── tsconfig.json
│   ├── 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
│   │   └── tsconfig.json
│   ├── xmlui-spreadsheet
│   │   ├── .gitignore
│   │   ├── demo
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   ├── src
│   │   │   ├── index.tsx
│   │   │   ├── Spreadsheet.tsx
│   │   │   └── SpreadsheetNative.tsx
│   │   └── tsconfig.json
│   └── 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.tsx
│       │   │   └── HeroSectionNative.tsx
│       │   ├── index.tsx
│       │   ├── ScrollToTop
│       │   │   ├── ScrollToTop.module.scss
│       │   │   ├── ScrollToTop.tsx
│       │   │   └── ScrollToTopNative.tsx
│       │   └── vite-env.d.ts
│       └── tsconfig.json
├── 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.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
    │   ├── containers.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
    │   ├── state-management.md
    │   └── xmlui-repo.md
    ├── package.json
    ├── playwright.config.ts
    ├── scripts
    │   ├── coverage-only.js
    │   ├── e2e-test-summary.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
    │   ├── get-langserver-metadata.mjs
    │   ├── 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.spec.ts
    │   │   │   │   ├── LabelList.tsx
    │   │   │   │   ├── LabelListNative.module.scss
    │   │   │   │   └── 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
    │   │   │   ├── MultiSelectOption.tsx
    │   │   │   ├── OptionContext.ts
    │   │   │   ├── Select.md
    │   │   │   ├── Select.module.scss
    │   │   │   ├── Select.spec.ts
    │   │   │   ├── Select.tsx
    │   │   │   ├── SelectContext.tsx
    │   │   │   ├── SelectNative.tsx
    │   │   │   ├── SelectOption.tsx
    │   │   │   └── SimpleSelect.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
    │   │   │   ├── 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.mjs
    │   ├── 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
    │   │   │   ├── ModalDialogDriver.ts
    │   │   │   ├── NumberBoxDriver.ts
    │   │   │   ├── TextBoxDriver.ts
    │   │   │   ├── TimeInputDriver.ts
    │   │   │   ├── TimerDriver.ts
    │   │   │   └── TreeDriver.ts
    │   │   ├── fixtures.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.bin.json
    ├── tsconfig.json
    ├── tsconfig.node.json
    ├── vite.config.ts
    └── vitest.config.ts
```

# Files

--------------------------------------------------------------------------------
/xmlui/src/components-core/devtools/InspectorDialog.module.scss:
--------------------------------------------------------------------------------

```scss
  1 | @use "xmlui/themes.scss" as t;
  2 | 
  3 | // --- This code snippet is required to collect the theme variables used in this module
  4 | $component: "ModalDialog";
  5 | $themeVars: ();
  6 | @function createThemeVar($componentVariable) {
  7 |   $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global;
  8 |   @return t.getThemeVar($themeVars, $componentVariable);
  9 | }
 10 | 
 11 | // --- Theme vars for paddings
 12 | $themeVars: t.composePaddingVars($themeVars, $component);
 13 | $themeVars: t.composePaddingVars($themeVars, "overlay-#{$component}");
 14 | $padding-ModalDialog: createThemeVar("padding-#{$component}");
 15 | $backgroundColor-ModalDialog: createThemeVar("Dialog:backgroundColor-#{$component}");
 16 | $backgroundColor-overlay-ModalDialog: createThemeVar("Dialog:backgroundColor-overlay-#{$component}");
 17 | $borderRadius-ModalDialog: createThemeVar("Dialog:borderRadius-#{$component}");
 18 | $fontFamily-ModalDialog: createThemeVar("Dialog:fontFamily-#{$component}");
 19 | $textColor-ModalDialog: createThemeVar("Dialog:textColor-#{$component}");
 20 | $minWidth-ModalDialog: createThemeVar("Dialog:minWidth-#{$component}");
 21 | $maxWidth-ModalDialog: createThemeVar("Dialog:maxWidth-#{$component}");
 22 | $marginBottom-title-ModalDialog: createThemeVar("Dialog:marginBottom-title-#{$component}");
 23 | 
 24 | 
 25 | .overlay {
 26 |   position: fixed;
 27 |   overflow-y: auto;
 28 |   display: flex;
 29 |   align-items: center;
 30 |   justify-content: center;
 31 |   inset: 0;
 32 |   background-color: $backgroundColor-overlay-ModalDialog;
 33 |   padding: t.$space-4;
 34 | }
 35 | 
 36 | .overlayBg {
 37 |   background-color: $backgroundColor-overlay-ModalDialog;
 38 |   position: fixed;
 39 |   inset: 0;
 40 | }
 41 | 
 42 | .contentWrapper {
 43 |   display: flex;
 44 |   justify-content: center;
 45 |   align-items: center;
 46 |   width: 100%;
 47 |   height: 100%;
 48 | }
 49 | 
 50 | .content {
 51 |   border-radius: $borderRadius-ModalDialog;
 52 |   font-family: $fontFamily-ModalDialog;
 53 |   color: $textColor-ModalDialog;
 54 |   width: 90vw;
 55 |   max-width: 960px;
 56 |   min-width: 240px;
 57 |   isolation: isolate;
 58 |   position: relative;
 59 |   display: flex;
 60 |   flex-direction: column;
 61 |   max-height: 80vh;
 62 |   overflow-y: auto;
 63 | }
 64 | 
 65 | .content:focus {
 66 |   outline: none;
 67 | }
 68 | 
 69 | .dialogTitle {
 70 |   flex: 1;
 71 |   margin-bottom: $marginBottom-title-ModalDialog;
 72 |   font-size: t.$fontSize-2xl;
 73 | }
 74 | 
 75 | .innerContent {
 76 |   display: flex;
 77 |   flex-direction: column;
 78 |   min-height: 0;
 79 |   gap: var(--stack-gap-default);
 80 |   flex: 1;
 81 | }
 82 | 
 83 | .closeButton {
 84 |   position: absolute;
 85 |   right: 0.5rem;
 86 |   top: 0.4rem;
 87 | }
 88 | 
 89 | .actions {
 90 |   display: inline-flex;
 91 |   align-items: center;
 92 |   justify-content: flex-end;
 93 | }
 94 | 
 95 | .header {
 96 |   padding: t.$space-2;
 97 |   justify-content: space-between;
 98 |   display: flex;
 99 |   flex-direction: row;
100 |   border-bottom: 1px solid t.$borderColor;
101 | }
102 | 
103 | @media (max-width: 70em) {
104 |   .dialog, .content {
105 |     max-width: 90%;
106 |   }
107 | }
108 | 
109 | @media (max-width: 50em) {
110 |   .dialog, .content {
111 |     width: 100%;
112 |     max-width: calc(100% - #{t.$space-6});
113 |     min-width: 0 !important;
114 |   }
115 | }
116 | 
117 | // --- We export the theme variables to add them to the component renderer
118 | :export {
119 |   themeVars: t.json-stringify($themeVars);
120 | }
121 | 
```

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

```typescript
 1 | import type { ComponentDef } from "../../abstractions/ComponentDefs";
 2 | import type { ActionExecutionContext } from "../../abstractions/ActionDefs";
 3 | import type { ApiActionOptions, DownloadOperationDef } from "../RestApiProxy";
 4 | import RestApiProxy from "../RestApiProxy";
 5 | 
 6 | import { createAction } from "./actions";
 7 | 
 8 | export interface DownloadActionComponent extends ComponentDef {
 9 |   props: DownloadOperationDef;
10 | }
11 | 
12 | async function download(
13 |   { state, appContext }: ActionExecutionContext,
14 |   {
15 |     params,
16 |     url,
17 |     queryParams,
18 |     method,
19 |     rawBody,
20 |     body,
21 |     fileName,
22 |     headers,
23 |   }: {
24 |     params: any;
25 |   } & DownloadOperationDef,
26 |   { resolveBindingExpressions }: ApiActionOptions = {}
27 | ) {
28 |   const context = { ...params, ...state };
29 |   const operation: DownloadOperationDef = {
30 |     url,
31 |     queryParams,
32 |     method,
33 |     rawBody,
34 |     body,
35 |     fileName,
36 |     headers,
37 |   };
38 | 
39 |   const api = new RestApiProxy(appContext);
40 |   const _url = api.resolveUrl({ operation, params: context, resolveBindingExpressions });
41 | 
42 |   if (
43 |     (operation.method && (operation.method as string).toLowerCase() !== "get") ||
44 |     Object.keys(appContext.appGlobals?.headers || {}).length !== 0 || //if we have any headers for the api, we can't use the iframe trick
45 |     appContext.apiInterceptorContext.isMocked(_url) //if we mock this url, the mock can't work in an iframe, so we must fall back to download it with the restApiProxy
46 |   ) {
47 |     const file: File = await api.execute({
48 |       operation,
49 |       params: context,
50 |       parseOptions: {
51 |         asFile: true,
52 |       },
53 |       resolveBindingExpressions,
54 |     });
55 |     downloadWithAnchor(file);
56 |   } else {
57 |     downloadInIframe(_url);
58 |   }
59 | }
60 | 
61 | //we use a hidden iframe trick here,
62 | // we set the iframe source as the download url, this way the browser will ask to download the file, and show a progress bar
63 | // (we could use an anchor tag with a download attribute, but in this case we can't show progress )
64 | // we can use it if we don't have to add extra headers to the request in order to download a file (pre-signed urls, or public urls)
65 | function downloadInIframe(fileUrl: string) {
66 |   const iframe = document.createElement("iframe");
67 |   iframe.style.display = "none";
68 |   iframe.hidden = true;
69 |   iframe.name = fileUrl;
70 |   iframe.id = `download-iframe_${fileUrl}`;
71 |   iframe.src = fileUrl;
72 |   document.body.appendChild(iframe);
73 |   setTimeout(() => {
74 |     iframe.remove();
75 |   }, 20000);
76 | }
77 | 
78 | // we can use it if we do have to add extra headers to the request in order to download a file (urls require authentication)
79 | function downloadWithAnchor(file: File) {
80 |   const url = window.URL.createObjectURL(file);
81 |   const a = document.createElement("a");
82 |   a.style.display = "none";
83 |   a.href = url;
84 |   // the filename you want
85 |   a.download = file.name;
86 |   document.body.appendChild(a);
87 |   a.click();
88 |   window.URL.revokeObjectURL(url);
89 | }
90 | 
91 | export const downloadAction = createAction("download", download);
92 | 
```

--------------------------------------------------------------------------------
/xmlui/scripts/inline-links.mjs:
--------------------------------------------------------------------------------

```
 1 | import * as fs from "fs";
 2 | import * as path from "path";
 3 | 
 4 | const includedFileExtensions = [".mdx", ".md"];
 5 | 
 6 | // Read the file contents
 7 | const fileContent = fs.readFileSync("../docs/meta/pages.js", "utf-8");
 8 | 
 9 | // Match lines like: export const NAME = "value";
10 | const regex = /export const (\w+)\s*=\s*["'`](.*?)["'`];/g;
11 | 
12 | const constants = {};
13 | let match;
14 | while ((match = regex.exec(fileContent)) !== null) {
15 |   const [, key, value] = match;
16 |   constants[key] = value;
17 | }
18 | 
19 | inlineLinks("../docs/pages");
20 | 
21 | function inlineLinks(pagesFolder) {
22 |   traverseDirectory({ name: "", path: pagesFolder }, (item, _) => {
23 |     /**
24 |      * name: the folder's/file's name (eg. "hello-app-engine")
25 |      * path: the path to the root of the given folder from the project root (eg. "src/apps/1_basic/samples/hello-app-engine")
26 |      * parent: parent node
27 |      * children: children file/folder names
28 |      */
29 |     if (fs.statSync(item.path).isDirectory()) {
30 |       // Node is a folder
31 |     } else {
32 |       // Node is a file
33 |       if (includedFileExtensions.includes(path.extname(item.name))) {
34 |         console.log(item.name);
35 |         const mdxContent = fs.readFileSync(item.path, "utf-8");
36 |         
37 |         const regex = /<SmartLink\s+href=\{([^}]+)\}>/g;
38 |         const newMdxContent = mdxContent.replace(regex, (_, hrefExpr) => {
39 |           return `<SmartLink href="${constants[hrefExpr] || ''}">`;
40 |         });
41 | 
42 |         fs.writeFileSync(item.path, newMdxContent);
43 |       }
44 |     }
45 |   });
46 | }
47 | 
48 | /**
49 |  * Recursive function that traverses a given folder and applies an optional function on
50 |  * each of the folders/files found inside.
51 |  */
52 | export function traverseDirectory(node, visitor, level = 0) {
53 |   level++;
54 |   const dirContents = fs.readdirSync(node.path);
55 |   if (!node.children) node.children = dirContents;
56 |   for (const itemName of dirContents) {
57 |     const itemPath = [winPathToPosix(node.path), itemName].join(path.posix.sep);
58 |     const itemIsDir = fs.statSync(itemPath).isDirectory();
59 |     const childNode = {
60 |       name: itemName,
61 |       path: itemPath,
62 |       parent: node,
63 |     };
64 |     visitor && visitor(childNode, level);
65 |     if (itemIsDir) {
66 |       traverseDirectory(childNode, visitor, level);
67 |     }
68 |   }
69 | }
70 | 
71 | /**
72 |  * Multi-liner (commented and compatible with really old javascript versions)
73 |  * Source: https://stackoverflow.com/a/62732509
74 |  */
75 | export function winPathToPosix(windowsPath) {
76 |   // handle the edge-case of Window's long file names
77 |   // See: https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#short-vs-long-names
78 |   windowsPath = windowsPath.replace(/^\\\\\?\\/, "");
79 | 
80 |   // convert the separators, valid since both \ and / can't be in a windows filename
81 |   windowsPath = windowsPath.replace(/\\/g, "/");
82 | 
83 |   // compress any // or /// to be just /, which is a safe oper under POSIX
84 |   // and prevents accidental errors caused by manually doing path1+path2
85 |   windowsPath = windowsPath.replace(/\/\/+/g, "/");
86 | 
87 |   return windowsPath;
88 | }
89 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components/Stack/VStack.spec.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { test, expect } from "../../testing/fixtures";
 2 | 
 3 | // =============================================================================
 4 | // BASIC FUNCTIONALITY TESTS
 5 | // =============================================================================
 6 | 
 7 | test.describe("Basic Functionality", () => {
 8 |   test("renders items vertically", async ({ initTestBed, page }) => {
 9 |     await initTestBed(`
10 |       <VStack testId="vstack">
11 |         <Stack testId="item1" height="32px" width="32px" backgroundColor="red" />
12 |         <Stack testId="item2" height="32px" width="32px" backgroundColor="blue" />
13 |         <Stack testId="item3" height="32px" width="32px" backgroundColor="green" />
14 |       </VStack>
15 |     `);
16 | 
17 |     const vstack = page.getByTestId("vstack");
18 |     const item1 = page.getByTestId("item1");
19 |     const item2 = page.getByTestId("item2");
20 |     const item3 = page.getByTestId("item3");
21 | 
22 |     await expect(vstack).toBeVisible();
23 |     await expect(item1).toBeVisible();
24 |     await expect(item2).toBeVisible();
25 |     await expect(item3).toBeVisible();
26 | 
27 |     // Get bounding boxes to verify vertical layout
28 |     const item1Box = await item1.boundingBox();
29 |     const item2Box = await item2.boundingBox();
30 |     const item3Box = await item3.boundingBox();
31 | 
32 |     // Verify items are stacked vertically (item2 should be below item1, item3 below item2)
33 |     expect(item2Box!.y).toBeGreaterThan(item1Box!.y + item1Box!.height - 1); // -1 for floating point tolerance
34 |     expect(item3Box!.y).toBeGreaterThan(item2Box!.y + item2Box!.height - 1); // -1 for floating point tolerance
35 | 
36 |     // Verify items are horizontally aligned (should start at roughly the same x position)
37 |     expect(Math.abs(item1Box!.x - item2Box!.x)).toBeLessThan(1);
38 |     expect(Math.abs(item2Box!.x - item3Box!.x)).toBeLessThan(1);
39 |   });
40 | 
41 |   test("renders empty VStack", async ({ initTestBed, page }) => {
42 |     await initTestBed(`<VStack testId="vstack"></VStack>`);
43 |     
44 |     const vstack = page.getByTestId("vstack");
45 |     await expect(vstack).toBeAttached();
46 |     await expect(vstack).toBeEmpty();
47 |   });
48 | 
49 |   test("ignores orientation property", async ({ initTestBed, page }) => {
50 |     await initTestBed(`
51 |       <VStack testId="vstack" orientation="horizontal">
52 |         <Stack testId="item1" height="32px" width="32px" backgroundColor="red" />
53 |         <Stack testId="item2" height="32px" width="32px" backgroundColor="blue" />
54 |       </VStack>
55 |     `);
56 | 
57 |     const item1 = page.getByTestId("item1");
58 |     const item2 = page.getByTestId("item2");
59 | 
60 |     await expect(item1).toBeVisible();
61 |     await expect(item2).toBeVisible();
62 | 
63 |     // Get bounding boxes to verify still renders vertically despite orientation="horizontal"
64 |     const item1Box = await item1.boundingBox();
65 |     const item2Box = await item2.boundingBox();
66 | 
67 |     // Verify items are still stacked vertically (orientation prop should be ignored)
68 |     expect(item2Box!.y).toBeGreaterThan(item1Box!.y + item1Box!.height - 1);
69 |   });
70 | });
71 | 
```

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

```typescript
 1 | import { createComponentRenderer } from "../../components-core/renderers";
 2 | import { MemoizedItem } from "../container-helpers";
 3 | import { createMetadata, d } from "../metadata-helpers";
 4 | import { OptionNative, defaultProps } from "./OptionNative";
 5 | 
 6 | const COMP = "Option";
 7 | 
 8 | export const OptionMd = createMetadata({
 9 |   status: "stable",
10 |   description:
11 |     "`Option` defines selectable items for choice-based components, providing both " +
12 |     "the underlying value and display text for selection interfaces. It serves as " +
13 |     "a non-visual data structure that describes individual choices within " +
14 |     "[Select](/components/Select), [AutoComplete](/components/AutoComplete), " +
15 |     "and other selection components.",
16 |   props: {
17 |     label: d(
18 |       `This property defines the text to display for the option. If \`label\` is not defined, ` +
19 |       `\`Option\` will use the \`value\` as the label.`,
20 |     ),
21 |     value: d(
22 |       "This property defines the value of the option. If `value` is not defined, " +
23 |       "`Option` will use the `label` as the value. If neither is defined, " +
24 |       "the option is not displayed.",
25 |     ),
26 |     enabled: {
27 |       description: "This boolean property indicates whether the option is enabled or disabled.",
28 |       valueType: "boolean",
29 |       defaultValue: defaultProps.enabled,
30 |     },
31 |     keywords: d(
32 |       "An array of keywords that can be used for searching and filtering the option. " +
33 |       "These keywords are not displayed but help users find the option through search.",
34 |     ),
35 |   },
36 | });
37 | 
38 | export const optionComponentRenderer = createComponentRenderer(
39 |   COMP,
40 |   OptionMd,
41 |   ({ node, extractValue, className, renderChild, layoutContext }) => {
42 |     const label = extractValue.asOptionalString(node.props.label);
43 |     let value = extractValue(node.props.value);
44 |     if (label === undefined && value === undefined) {
45 |       return null;
46 |     }
47 | 
48 |     const hasTextNodeChild = node.children?.length === 1 && (node.children[0].type === "TextNode" || node.children[0].type === "TextNodeCData");
49 |     const textNodeChild = hasTextNodeChild ? renderChild(node.children) as string : undefined;
50 | 
51 |     return (
52 |       <OptionNative
53 |         label={label || textNodeChild}
54 |         value={value !== undefined && value !== "" ? value : label}
55 |         enabled={extractValue.asOptionalBoolean(node.props.enabled)}
56 |         keywords={extractValue.asOptionalStringArray(node.props.keywords)}
57 |         className={className}
58 |         optionRenderer={
59 |           node.children?.length > 0
60 |             ? !hasTextNodeChild ? (contextVars) => (
61 |               <MemoizedItem
62 |                 node={node.children}
63 |                 renderChild={renderChild}
64 |                 contextVars={contextVars}
65 |                 layoutContext={layoutContext}
66 |               />
67 |             ) : undefined
68 |             : undefined
69 |         }
70 |       >
71 |         {!hasTextNodeChild && renderChild(node.children)}
72 |       </OptionNative>
73 |     );
74 |   },
75 | );
76 | 
```

--------------------------------------------------------------------------------
/docs/public/pages/howto/paginate-a-list.md:
--------------------------------------------------------------------------------

```markdown
 1 | # Paginate a List
 2 | 
 3 | XMLUI provides a `Pagination` component that can be used to display visual controls for the pagination feature, no matter whether it is handled inside or outside of a layout component requiring that feature.
 4 | 
 5 | The [`Table`](./table) component provides out-of-the-box support for pagination,
 6 | so you can access pagination options via the following properties: `isPaginated`, `pageSize`, `pageSizeOptions`, `paginationControlsLocation`.
 7 | 
 8 | ```xmlui noHeader copy
 9 | <Table
10 |   data="/api/endpoint"
11 |   isPaginated
12 |   pageSize="10"
13 |   pageSizeOptions="{[5, 10, 20, 30]}"
14 |   paginationControlsLocation="both"
15 | >
16 |     ...
17 | </Table>
18 | ```
19 | 
20 | Other components, such as the `List`, can be hooked up with pagination using a `DataSource` combined with the `Pagination` component. This pattern works as a more generic solution where either the component does not have pagination implemented in the component itself, or you wish to use custom pagination logic.
21 | 
22 | In this case the `DataSource` component does the heavy lifting by querying the page index, the previous and next page IDs. This can be done using variables and query parameters.
23 | 
24 | ```xmlui-pg
25 | ---app display
26 | <App var.pageSize="{5}" var.currentPage="{0}" var.before="{0}" var.after="{pageSize-1}">
27 |   <DataSource id="pagination_ds" url="/api/pagination_items" queryParams="{{ from: before, to: after }}" />
28 |   <Pagination
29 |     itemCount="20"
30 |     pageSize="{pageSize}"
31 |     pageIndex="{currentPage}"
32 |     onPageDidChange="(page, size, total) => {
33 |       currentPage = page;
34 |       before = page * size;
35 |       after = before + size - 1;
36 |     }"
37 |   />
38 |   <List data="{pagination_ds}" />
39 | </App>
40 | ---api
41 | {
42 |   "apiUrl": "/api",
43 |   "initialize": "$state.pagination_items = [{ id: 1, name: 'Laptop Pro', price: 1299 },{ id: 2, name: 'Wireless Mouse', price: 29 },{ id: 3, name: 'Mechanical Keyboard', price: 149 },{ id: 4, name: '4K Monitor', price: 399 },{ id: 5, name: 'USB-C Hub', price: 79 },{ id: 6, name: 'Bluetooth Headphones', price: 199 },{ id: 7, name: 'Webcam HD', price: 89 },{ id: 8, name: 'Standing Desk', price: 299 },{ id: 9, name: 'Ergonomic Chair', price: 249 },{ id: 10, name: 'Desk Lamp', price: 45 },{ id: 11, name: 'Cable Organizer', price: 15 },{ id: 12, name: 'Mouse Pad', price: 12 },{ id: 13, name: 'Laptop Stand', price: 35 },{ id: 14, name: 'External SSD', price: 129 },{ id: 15, name: 'Wireless Charger', price: 59 },{ id: 16, name: 'Smart Speaker', price: 99 },{ id: 17, name: 'Fitness Tracker', price: 199 },{ id: 18, name: 'Tablet Pro', price: 799 },{ id: 19, name: 'Gaming Mouse', price: 89 },{ id: 20, name: 'Noise Cancelling Headphones', price: 349 }]",
44 |   "operations": {
45 |     "get-pagination-items": {
46 |       "url": "/pagination_items",
47 |       "method": "get",
48 |       "queryParams": {
49 |         "from": "integer",
50 |         "to": "integer"
51 |       },
52 |       "handler": "$state.pagination_items.slice(Number($queryParams.from), Number($queryParams.to) + 1);"
53 |     }
54 |   }
55 | }
56 | ```
57 | 
```

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

```markdown
  1 | # FormSection [#formsection]
  2 | 
  3 | `FormSection` groups elements within a `Form`. Child components are placed in a [FlowLayout](/components/FlowLayout).
  4 | 
  5 | ## Properties [#properties]
  6 | 
  7 | ### `columnGap` (default: "3rem") [#columngap-default-3rem]
  8 | 
  9 | The gap between columns of items within the section.
 10 | 
 11 | ```xmlui-pg copy display name="Example: columnGap"
 12 | <Form padding="1rem">
 13 |   <FormSection columnGap="1rem">
 14 |     <FormItem width="50%" label="Name" bindTo="" />
 15 |     <FormItem width="50%" label="Occupation" bindTo="" />
 16 |   </FormSection>
 17 | </Form>
 18 | ```
 19 | 
 20 | ### `heading` [#heading]
 21 | 
 22 | The heading text to be displayed at the top of the form section.
 23 | 
 24 | ```xmlui-pg copy display name="Example: heading"
 25 | <Form padding="1rem">
 26 |   <FormSection heading="Basic Heading">
 27 |     <FormItem label="Input Field" bindTo="" />
 28 |   </FormSection>
 29 | </Form>
 30 | ```
 31 | 
 32 | ### `headingLevel` (default: "h3") [#headinglevel-default-h3]
 33 | 
 34 | The semantic and visual level of the heading.
 35 | 
 36 | Available values: `h1`, `h2`, `h3` **(default)**, `h4`, `h5`, `h6`
 37 | 
 38 | ```xmlui-pg copy display name="Example: headingLevel"
 39 | <Form padding="1rem">
 40 |   <FormSection heading="Basic Heading" headingLevel="h1">
 41 |     <FormItem label="Input Field" bindTo="" />
 42 |   </FormSection>
 43 | </Form>
 44 | ```
 45 | 
 46 | ### `headingWeight` (default: "bold") [#headingweight-default-bold]
 47 | 
 48 | The font weight of the heading.
 49 | 
 50 | The default weight is `bold`.
 51 | 
 52 | ```xmlui-pg copy display name="Example: headingWeight"
 53 | <Form padding="1rem">
 54 |   <FormSection heading="Basic Heading" headingWeight="normal">
 55 |     <FormItem label="Input Field" bindTo="" />
 56 |   </FormSection>
 57 | </Form>
 58 | ```
 59 | 
 60 | ### `info` [#info]
 61 | 
 62 | Informational text displayed below the heading.
 63 | 
 64 | ```xmlui-pg copy display name="Example: info"
 65 | <Form padding="1rem">
 66 |   <FormSection info="This is some information about a particular section.">
 67 |     <FormItem label="Input Field" bindTo="" />
 68 |   </FormSection>
 69 | </Form>
 70 | ```
 71 | 
 72 | ### `infoFontSize` (default: "0.8rem") [#infofontsize-default-0-8rem]
 73 | 
 74 | The font size of the informational text.
 75 | 
 76 | ```xmlui-pg copy {4} display name="Example: infoFontSize"
 77 | <Form padding="1rem">
 78 |   <FormSection
 79 |     info="This is some information about a particular section."
 80 |     infoFontSize="18px"
 81 |   >
 82 |     <FormItem label="Input Field" bindTo="" />
 83 |   </FormSection>
 84 | </Form>
 85 | ```
 86 | 
 87 | ### `paddingTop` (default: "$space-normal") [#paddingtop-default-space-normal]
 88 | 
 89 | The top padding of the FlowLayout where the section's children are placed.
 90 | 
 91 | ### `rowGap` (default: "$space-normal") [#rowgap-default-space-normal]
 92 | 
 93 | The gap between rows of items within the section.
 94 | 
 95 | ```xmlui-pg copy display name="Example: rowGap"
 96 | <Form padding="1rem">
 97 |   <FormSection rowGap="2rem">
 98 |     <FormItem label="Name" bindTo="" />
 99 |     <FormItem label="Occupation" bindTo="" />
100 |   </FormSection>
101 | </Form>
102 | ```
103 | 
104 | ## Events [#events]
105 | 
106 | This component does not have any events.
107 | 
108 | ## Exposed Methods [#exposed-methods]
109 | 
110 | This component does not expose any methods.
111 | 
112 | ## Styling [#styling]
113 | 
114 | This component does not have any styles.
115 | 
```

--------------------------------------------------------------------------------
/packages/xmlui-devtools/src/devtools/ModalDialog.module.scss:
--------------------------------------------------------------------------------

```scss
  1 | @use "xmlui/themes.scss" as t;
  2 | 
  3 | // --- This code snippet is required to collect the theme variables used in this module
  4 | $component: "ModalDialog";
  5 | $themeVars: ();
  6 | @function createThemeVar($componentVariable) {
  7 |   $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global;
  8 |   @return t.getThemeVar($themeVars, $componentVariable);
  9 | }
 10 | 
 11 | // --- Theme vars for paddings
 12 | $themeVars: t.composePaddingVars($themeVars, $component);
 13 | $themeVars: t.composePaddingVars($themeVars, "overlay-#{$component}");
 14 | $padding-ModalDialog: createThemeVar("padding-#{$component}");
 15 | $backgroundColor-ModalDialog: createThemeVar("Dialog:backgroundColor-#{$component}");
 16 | $backgroundColor-overlay-ModalDialog: createThemeVar("Dialog:backgroundColor-overlay-#{$component}");
 17 | $borderRadius-ModalDialog: createThemeVar("Dialog:borderRadius-#{$component}");
 18 | $fontFamily-ModalDialog: createThemeVar("Dialog:fontFamily-#{$component}");
 19 | $textColor-ModalDialog: createThemeVar("Dialog:textColor-#{$component}");
 20 | $minWidth-ModalDialog: createThemeVar("Dialog:minWidth-#{$component}");
 21 | $maxWidth-ModalDialog: createThemeVar("Dialog:maxWidth-#{$component}");
 22 | $marginBottom-title-ModalDialog: createThemeVar("Dialog:marginBottom-title-#{$component}");
 23 | 
 24 | 
 25 | .overlay {
 26 |   position: fixed;
 27 |   overflow-y: auto;
 28 |   display: flex;
 29 |   align-items: center;
 30 |   justify-content: center;
 31 |   inset: 0;
 32 |   padding: t.$space-4;
 33 | }
 34 | 
 35 | .overlayBg {
 36 |   background-color: $backgroundColor-overlay-ModalDialog;
 37 |   position: fixed;
 38 |   inset: 0;
 39 | }
 40 | 
 41 | .contentWrapper {
 42 |   display: flex;
 43 |   justify-content: center;
 44 |   align-items: center;
 45 |   width: 100%;
 46 |   height: 100%;
 47 | }
 48 | 
 49 | .content {
 50 |   background-color: $backgroundColor-ModalDialog;
 51 |   border-radius: $borderRadius-ModalDialog;
 52 |   font-family: $fontFamily-ModalDialog;
 53 |   color: $textColor-ModalDialog;
 54 |   box-shadow: t.$boxShadow-spread;
 55 |   width: 90vw;
 56 |   max-width: 960px;
 57 |   min-width: 240px;
 58 |   isolation: isolate;
 59 |   position: relative;
 60 |   display: flex;
 61 |   flex-direction: column;
 62 |   max-height: 80vh;
 63 |   overflow-y: auto;
 64 | }
 65 | 
 66 | .content:focus {
 67 |   outline: none;
 68 | }
 69 | 
 70 | .dialogTitle {
 71 |   flex: 1;
 72 |   margin-bottom: $marginBottom-title-ModalDialog;
 73 |   font-size: t.$fontSize-2xl;
 74 | }
 75 | 
 76 | .innerContent {
 77 |   display: flex;
 78 |   flex-direction: column;
 79 |   min-height: 0;
 80 |   gap: var(--stack-gap-default);
 81 |   flex: 1;
 82 | }
 83 | 
 84 | .closeButton {
 85 |   position: absolute;
 86 |   right: 0.5rem;
 87 |   top: 0.4rem;
 88 | }
 89 | 
 90 | .actions {
 91 |   display: inline-flex;
 92 |   align-items: center;
 93 |   justify-content: flex-end;
 94 | }
 95 | 
 96 | .header {
 97 |   padding: t.$space-2;
 98 |   justify-content: space-between;
 99 |   display: flex;
100 |   flex-direction: row;
101 |   border-bottom: 1px solid t.$borderColor;
102 | }
103 | 
104 | @media (max-width: 70em) {
105 |   .dialog, .content {
106 |     max-width: 90%;
107 |   }
108 | }
109 | 
110 | @media (max-width: 50em) {
111 |   .dialog, .content {
112 |     width: 100%;
113 |     max-width: calc(100% - #{t.$space-6});
114 |     min-width: 0 !important;
115 |   }
116 | }
117 | 
118 | // --- We export the theme variables to add them to the component renderer
119 | :export {
120 |   themeVars: t.json-stringify($themeVars);
121 | }
122 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components/Stack/HStack.spec.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { test, expect } from "../../testing/fixtures";
 2 | 
 3 | // =============================================================================
 4 | // BASIC FUNCTIONALITY TESTS
 5 | // =============================================================================
 6 | 
 7 | test.describe("Basic Functionality", () => {
 8 |   test("renders items horizontally", async ({ initTestBed, page }) => {
 9 |     await initTestBed(`
10 |       <HStack testId="hstack">
11 |         <Stack testId="item1" height="32px" width="32px" backgroundColor="red" />
12 |         <Stack testId="item2" height="32px" width="32px" backgroundColor="blue" />
13 |         <Stack testId="item3" height="32px" width="32px" backgroundColor="green" />
14 |       </HStack>
15 |     `);
16 | 
17 |     const hstack = page.getByTestId("hstack");
18 |     const item1 = page.getByTestId("item1");
19 |     const item2 = page.getByTestId("item2");
20 |     const item3 = page.getByTestId("item3");
21 | 
22 |     await expect(hstack).toBeVisible();
23 |     await expect(item1).toBeVisible();
24 |     await expect(item2).toBeVisible();
25 |     await expect(item3).toBeVisible();
26 | 
27 |     // Get bounding boxes to verify horizontal layout
28 |     const item1Box = await item1.boundingBox();
29 |     const item2Box = await item2.boundingBox();
30 |     const item3Box = await item3.boundingBox();
31 | 
32 |     // Verify items are stacked horizontally (item2 should be to the right of item1, item3 to the right of item2)
33 |     expect(item2Box!.x).toBeGreaterThan(item1Box!.x + item1Box!.width - 1); // -1 for floating point tolerance
34 |     expect(item3Box!.x).toBeGreaterThan(item2Box!.x + item2Box!.width - 1); // -1 for floating point tolerance
35 | 
36 |     // Verify items are vertically aligned (should start at roughly the same y position)
37 |     expect(Math.abs(item1Box!.y - item2Box!.y)).toBeLessThan(1);
38 |     expect(Math.abs(item2Box!.y - item3Box!.y)).toBeLessThan(1);
39 |   });
40 | 
41 |   test("renders empty HStack", async ({ initTestBed, page }) => {
42 |     await initTestBed(`<HStack testId="hstack"></HStack>`);
43 |     
44 |     const hstack = page.getByTestId("hstack");
45 |     await expect(hstack).toBeAttached();
46 |     await expect(hstack).toBeEmpty();
47 |   });
48 | 
49 |   test("ignores orientation property", async ({ initTestBed, page }) => {
50 |     await initTestBed(`
51 |       <HStack testId="hstack" orientation="vertical">
52 |         <Stack testId="item1" height="32px" width="32px" backgroundColor="red" />
53 |         <Stack testId="item2" height="32px" width="32px" backgroundColor="blue" />
54 |       </HStack>
55 |     `);
56 | 
57 |     const item1 = page.getByTestId("item1");
58 |     const item2 = page.getByTestId("item2");
59 | 
60 |     await expect(item1).toBeVisible();
61 |     await expect(item2).toBeVisible();
62 | 
63 |     // Get bounding boxes to verify still renders horizontally despite orientation="vertical"
64 |     const item1Box = await item1.boundingBox();
65 |     const item2Box = await item2.boundingBox();
66 | 
67 |     // Verify items are still stacked horizontally (orientation prop should be ignored)
68 |     expect(item2Box!.x).toBeGreaterThan(item1Box!.x + item1Box!.width - 1);
69 |   });
70 | });
71 | 
```

--------------------------------------------------------------------------------
/xmlui/bin/vite-xmlui-plugin.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { dataToEsm } from "@rollup/pluginutils";
 2 | import type { Plugin } from "vite";
 3 | import {
 4 |   collectCodeBehindFromSource,
 5 |   removeCodeBehindTokensFromTree,
 6 | } from "../src/parsers/scripting/code-behind-collect";
 7 | import {
 8 |   codeBehindFileExtension,
 9 |   componentFileExtension,
10 |   moduleFileExtension,
11 | } from "../src/parsers/xmlui-parser/fileExtensions";
12 | import { Parser } from "../src/parsers/scripting/Parser";
13 | import * as fs from "fs";
14 | import * as path from "path";
15 | import { errReportComponent, xmlUiMarkupToComponent } from "../src/components-core/xmlui-parser";
16 | 
17 | export type PluginOptions = {
18 |   // --- Add plugin options here.
19 | };
20 | 
21 | const xmluiExtension = new RegExp(`.${componentFileExtension}$`);
22 | const xmluiScriptExtension = new RegExp(`.${codeBehindFileExtension}$`);
23 | const moduleScriptExtension = new RegExp(`.${moduleFileExtension}$`);
24 | 
25 | /**
26 |  * Transform XMLUI files to JS objects.
27 |  */
28 | export default function viteXmluiPlugin(pluginOptions: PluginOptions = {}): Plugin {
29 |   let itemIndex = 0;
30 |   return {
31 |     name: "vite:transform-xmlui",
32 | 
33 |     async transform(code: string, id: string, options) {
34 |       const moduleNameResolver = (moduleName: string) => {
35 |         return path.resolve(path.dirname(id), moduleName);
36 |       };
37 | 
38 |       if (xmluiExtension.test(id)) {
39 |         const fileId = "" + itemIndex++;
40 |         let { component, errors, erroneousCompoundComponentName } = xmlUiMarkupToComponent(
41 |           code,
42 |           fileId,
43 |         );
44 |         if (errors.length > 0) {
45 |           component = errReportComponent(errors, id, erroneousCompoundComponentName);
46 |         }
47 |         const file = {
48 |           component,
49 |           src: code,
50 |           file: fileId,
51 |         };
52 | 
53 |         return {
54 |           code: dataToEsm(file),
55 |           map: { mappings: "" },
56 |         };
57 |       }
58 | 
59 |       const hasXmluiScriptExtension = xmluiScriptExtension.test(id);
60 |       const hasModuleScriptExtension = moduleScriptExtension.test(id);
61 |       if (hasXmluiScriptExtension || hasModuleScriptExtension) {
62 |         // --- We parse the module file to catch parsing errors
63 | 
64 |         const parser = new Parser(code);
65 |         parser.parseStatements();
66 |         const moduleName = hasXmluiScriptExtension
67 |           ? id.substring(0, id.length - (codeBehindFileExtension.length + 1))
68 |           : id.substring(0, id.length - (moduleFileExtension.length + 1));
69 | 
70 |         const codeBehind = collectCodeBehindFromSource(moduleNameResolver(moduleName), code);
71 |         removeCodeBehindTokensFromTree(codeBehind);
72 | 
73 |         // TODO: Add error handling.
74 |         // Check, if codeBehind.moduleErrors is not empty (Record<string, ModuleErrors[]>); each module
75 |         // should be checked for errors and warnings. If there are errors, throw an error.
76 | 
77 |         return {
78 |           code: dataToEsm({...codeBehind, src: code}),
79 |           map: { mappings: "" },
80 |         };
81 |       }
82 |       return null;
83 |     },
84 |     // async generateBundle(opts, bundle, isWrite){
85 |     //   console.log('generate bundle', opts);
86 |     // }
87 |   };
88 | }
89 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components-core/loader/ApiLoader.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import { useCallback } from "react";
  2 | 
  3 | import type {
  4 |   LoaderErrorFn,
  5 |   LoaderInProgressChangedFn,
  6 |   LoaderLoadedFn,
  7 | } from "../abstractions/LoaderRenderer";
  8 | import type { ComponentDef } from "../../abstractions/ComponentDefs";
  9 | import type { ContainerState } from "../rendering/ContainerWrapper";
 10 | import { removeNullProperties } from "../utils/misc";
 11 | import { extractParam } from "../utils/extractParam";
 12 | import { createLoaderRenderer } from "../renderers";
 13 | import { useAppContext } from "../AppContext";
 14 | import { Loader } from "./Loader";
 15 | import { createMetadata, d } from "../../components/metadata-helpers";
 16 | 
 17 | /**
 18 |  * Properties of the API loader component
 19 |  */
 20 | type ApiLoaderProps = {
 21 |   loader: ApiLoaderDef;
 22 |   loaderInProgressChanged: LoaderInProgressChangedFn;
 23 |   loaderIsRefetchingChanged: LoaderInProgressChangedFn;
 24 |   loaderLoaded: LoaderLoadedFn;
 25 |   loaderError: LoaderErrorFn;
 26 |   state: ContainerState;
 27 |   doNotRemoveNulls?: boolean;
 28 |   structuralSharing?: boolean;
 29 | };
 30 | 
 31 | /**
 32 |  * Represents a non-displayed React component, which handles the specified API loader
 33 |  */
 34 | function ApiLoader({
 35 |   loader,
 36 |   loaderInProgressChanged,
 37 |   loaderIsRefetchingChanged,
 38 |   loaderLoaded,
 39 |   loaderError,
 40 |   state,
 41 |   doNotRemoveNulls,
 42 |   structuralSharing = true,
 43 | }: ApiLoaderProps) {
 44 |   const appContext = useAppContext();
 45 | 
 46 |   const url = extractParam(state, loader.props.url, appContext);
 47 |   const loadable = !!url;
 48 | 
 49 |   const doLoad = useCallback(async () => {
 50 |     if (!loadable) {
 51 |       return;
 52 |     }
 53 |     const response = await fetch(url);
 54 |     if (loader.props.raw) {
 55 |       return await response.text();
 56 |     }
 57 |     const responseObj = await response.json();
 58 |     if (!doNotRemoveNulls) {
 59 |       removeNullProperties(responseObj);
 60 |     }
 61 |     return responseObj;
 62 |   }, [doNotRemoveNulls, loadable, loader.props.raw, url]);
 63 | 
 64 |   return (
 65 |     <Loader
 66 |       state={state}
 67 |       loader={loader}
 68 |       loaderInProgressChanged={loaderInProgressChanged}
 69 |       loaderIsRefetchingChanged={loaderIsRefetchingChanged}
 70 |       loaderLoaded={loaderLoaded}
 71 |       loaderError={loaderError}
 72 |       loaderFn={doLoad}
 73 |       structuralSharing={structuralSharing}
 74 |     />
 75 |   );
 76 | }
 77 | 
 78 | const ApiLoaderMd = createMetadata({
 79 |   status: "stable",
 80 |   description: `Represents a loader that calls an API through an HTTP/HTTPS GET request`,
 81 |   props: {
 82 |     url: d("URL segment to use in the GET request"),
 83 |     raw: d("If true, the loader returns the raw text response instead of parsing it as JSON"),
 84 |   },
 85 | });
 86 | 
 87 | type ApiLoaderDef = ComponentDef<typeof ApiLoaderMd>;
 88 | 
 89 | export const apiLoaderRenderer = createLoaderRenderer(
 90 |   "ApiLoader",
 91 |   ({ loader, state, loaderInProgressChanged, loaderIsRefetchingChanged, loaderLoaded, loaderError }) => {
 92 |     return (
 93 |       <ApiLoader
 94 |         loader={loader}
 95 |         state={state}
 96 |         loaderInProgressChanged={loaderInProgressChanged}
 97 |         loaderIsRefetchingChanged={loaderIsRefetchingChanged}
 98 |         loaderLoaded={loaderLoaded}
 99 |         loaderError={loaderError}
100 |       />
101 |     );
102 |   },
103 |   ApiLoaderMd,
104 | );
105 | 
```

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

```typescript
 1 | import { useThemes } from "../../components-core/theming/ThemeContext";
 2 | import { createComponentRenderer } from "../../components-core/renderers";
 3 | import { Button } from "../Button/ButtonNative";
 4 | import { Icon } from "../Icon/IconNative";
 5 | import { createMetadata, dClick } from "../metadata-helpers";
 6 | import { noop } from "lodash-es";
 7 | 
 8 | const COMP = "ToneChangerButton";
 9 | const LIGHT_TO_DARK_ICON = "lightToDark:ToneChangerButton";
10 | const DARK_TO_LIGHT_ICON = "darkToLight:ToneChangerButton";
11 | 
12 | export const defaultProps = {
13 |   lightToDarkIcon: LIGHT_TO_DARK_ICON,
14 |   darkToLightIcon: DARK_TO_LIGHT_ICON,
15 |   onClick: noop,
16 | };
17 | 
18 | export const ToneChangerButtonMd = createMetadata({
19 |   status: "stable",
20 |   description: "`ToneChangerButton` enables the user to switch between light and dark modes.",
21 |   props: {
22 |     lightToDarkIcon: {
23 |       description:
24 |         `The icon displayed when the theme is in light mode and will switch to dark. You can change ` +
25 |         `the default icon for all ${COMP} instances with the "icon.lightToDark:ToneChangerButton" ` +
26 |         `declaration in the app configuration file.`,
27 |       defaultValue: defaultProps.lightToDarkIcon,
28 |     },
29 |     darkToLightIcon: {
30 |       description:
31 |         `The icon displayed when the theme is in dark mode and will switch to light. You can change ` +
32 |         `the default icon for all ${COMP} instances with the "icon.darkToLight:ToneChangerButton" ` +
33 |         `declaration in the app configuration file.`,
34 |       defaultValue: defaultProps.darkToLightIcon,
35 |     },
36 |   },
37 |   events: {
38 |     click: dClick(COMP),
39 |   },
40 | });
41 | 
42 | export function ToneChangerButton({
43 |   lightToDarkIcon = defaultProps.lightToDarkIcon,
44 |   darkToLightIcon = defaultProps.darkToLightIcon,
45 |   onClick = defaultProps.onClick,
46 | }) {
47 |   const { activeThemeTone, setActiveThemeTone } = useThemes();
48 | 
49 |   // Use the direct icon name as both the main icon and the fallback
50 |   // This ensures we always have a working icon
51 |   const iconName = activeThemeTone === "light" ? lightToDarkIcon : darkToLightIcon;
52 |   const fallbackIcon = activeThemeTone === "light" ? "lightToDark" : "darkToLight";
53 | 
54 |   return (
55 |     <Button
56 |       variant="ghost"
57 |       style={{ flexShrink: 0 }}
58 |       icon={<Icon name={iconName} fallback={fallbackIcon} />}
59 |       onClick={() => {
60 |         if (activeThemeTone === "light") {
61 |           setActiveThemeTone("dark");
62 |           onClick?.("dark");
63 |         } else {
64 |           setActiveThemeTone("light");
65 |           onClick?.("light");
66 |         }
67 |       }}
68 |     />
69 |   );
70 | }
71 | 
72 | /**
73 |  * Define the renderer for the ToneChangerButton component
74 |  */
75 | export const toneChangerButtonComponentRenderer = createComponentRenderer(
76 |   COMP,
77 |   ToneChangerButtonMd,
78 |   ({ node, extractValue, lookupEventHandler }) => {
79 |     return (
80 |       <ToneChangerButton
81 |         onClick={lookupEventHandler("click")}
82 |         lightToDarkIcon={extractValue.asOptionalString(node.props.lightToDarkIcon)}
83 |         darkToLightIcon={extractValue.asOptionalString(node.props.darkToLightIcon)}
84 |       />
85 |     );
86 |   },
87 | );
88 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components/Pages/PagesNative.tsx:
--------------------------------------------------------------------------------

```typescript
  1 | import type { CSSProperties, ReactNode } from "react";
  2 | import { useMemo } from "react";
  3 | import { Navigate, Route, Routes, useParams } from "@remix-run/react";
  4 | import classnames from "classnames";
  5 | 
  6 | import type { ComponentDef } from "../../abstractions/ComponentDefs";
  7 | import type { LayoutContext, RenderChildFn, ValueExtractor } from "../../abstractions/RendererDefs";
  8 | import { EMPTY_ARRAY, EMPTY_OBJECT } from "../../components-core/constants";
  9 | import type { PageMd } from "./Pages";
 10 | import styles from "./Pages.module.scss";
 11 | 
 12 | // Default props for Pages component
 13 | export const defaultProps = {
 14 |   fallbackPath: "/",
 15 | };
 16 | 
 17 | // --- We need this component to make sure all the child routes are wrapped in a
 18 | // --- container and  this way they can access the routeParams
 19 | type RouteWrapperProps = {
 20 |   childRoute?: ComponentDef | Array<ComponentDef>;
 21 |   renderChild: RenderChildFn;
 22 |   layoutContext?: LayoutContext;
 23 |   style?: CSSProperties;
 24 |   className?: string;
 25 |   uid?: string;
 26 | };
 27 | 
 28 | export function RouteWrapper({
 29 |   childRoute = EMPTY_ARRAY,
 30 |   renderChild,
 31 |   layoutContext,
 32 |   style,
 33 |   className,
 34 |   uid,
 35 | }: RouteWrapperProps) {
 36 |   const params = useParams();
 37 | 
 38 |   //we need to wrap the child route in a container to make sure the route params are available.
 39 |   // we do this wrapping by providing an empty object to vars.
 40 |   // this way it becomes an 'implicit' container (vars/state inside this container is propagated to the parent)
 41 |   const wrappedWithContainer = useMemo(() => {
 42 |     if (Array.isArray(childRoute)) {
 43 |       return {
 44 |         type: "Fragment",
 45 |         uid,
 46 |         vars: EMPTY_OBJECT,
 47 |         children: childRoute,
 48 |       };
 49 |     }
 50 |     return {
 51 |       type: "Fragment",
 52 |       uid,
 53 |       vars: EMPTY_OBJECT,
 54 |       children: [childRoute],
 55 |     };
 56 |   }, [childRoute, uid]);
 57 | 
 58 |   return (
 59 |     <div
 60 |       key={JSON.stringify(params)}
 61 |       className={classnames(className, styles.wrapper, "xmlui-page-root")}
 62 |       style={style}
 63 |     >
 64 |       {renderChild(wrappedWithContainer, layoutContext)}
 65 |     </div>
 66 |   );
 67 | }
 68 | 
 69 | type PageComponentDef = ComponentDef<typeof PageMd>;
 70 | 
 71 | type PagesProps = {
 72 |   fallbackPath?: string;
 73 |   node?: ComponentDef;
 74 |   renderChild: RenderChildFn;
 75 |   extractValue: ValueExtractor;
 76 |   children?: ReactNode;
 77 |   className?: ReactNode;
 78 | };
 79 | 
 80 | export function Pages({
 81 |   node,
 82 |   renderChild,
 83 |   extractValue,
 84 |   fallbackPath = defaultProps.fallbackPath,
 85 | }: PagesProps) {
 86 |   const routes: Array<PageComponentDef> = [];
 87 |   const restChildren: Array<ComponentDef> = [];
 88 |   node.children?.forEach((child) => {
 89 |     if (child.type === "Page") {
 90 |       routes.push(child as PageComponentDef);
 91 |     } else {
 92 |       restChildren.push(child);
 93 |     }
 94 |   });
 95 |   return (
 96 |     <>
 97 |       <Routes>
 98 |         {routes.map((child, i) => {
 99 |           return (
100 |             <Route path={extractValue(child.props.url)} key={i} element={renderChild(child)} />
101 |           );
102 |         })}
103 |         {fallbackPath && <Route path="*" element={<Navigate to={fallbackPath} replace  />} />}
104 |       </Routes>
105 |       {renderChild(restChildren)}
106 |     </>
107 |   );
108 | }
109 | 
```

--------------------------------------------------------------------------------
/docs/public/pages/app-structure.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Structure of an XMLUI app
  2 | 
  3 | The [XMLUI Invoice demo app](https://github.com/xmlui-org/xmlui-invoice/releases) exhibits the typical structure of an XMLUI app.
  4 | 
  5 | ```xmlui-tree
  6 | <root>
  7 |   index.html
  8 |   Main.xmlui
  9 |   config.json
 10 |   components
 11 |     ClientDetails.xmlui
 12 |     Clients.xmlui
 13 |     ...
 14 |     MonthlyRevenue.xmlui
 15 |     WeeklyRevenue.xmlui
 16 |   resources
 17 |     favicon.ico
 18 |     xmlui-logo-inverted.svg
 19 |     xmlui-logo.svg
 20 |   themes
 21 |     invoice.json
 22 |   xmlui
 23 |     0.9.23.js
 24 |     charts-0.1.21.js
 25 |   start.bat
 26 |   start.sh
 27 |   api.json
 28 |   data.db
 29 |   xmlui-test-server
 30 | ```
 31 | 
 32 | > [!INFO] The `xmlui` folder contains the xmlui engine with a version number, specifically `0.9.23.js`. We recommend this practice in order to know when/whether to upgrade.
 33 | 
 34 | 
 35 | | file| description |
 36 | |---|---|
 37 | | **`index.html`** | The default webpage to display |
 38 | | **`Main.xmlui`** | The XMLUI app's entry point |
 39 | | **`config.json`** | The XMLUI app's configuration file |
 40 | | **`components`** | The folder with your custom components |
 41 | | **`resources`** | The folder with static app resources |
 42 | | **`themes`** | The folder with your custom themes |
 43 | | **`xmlui`** | The folder with the XMLUI core framework and extensions  |
 44 | | **`start.bat`** | The batch file to start the test server on Windows |
 45 | | **`start.sh`** | The bash script file to start the test server on Mac, Linux, or WSL |
 46 | | **`api.json`** | *Optional*: API description file for use with xmlui-test-server |
 47 | | **`data.db`** | *Optional*: SQLite database for use with xmlui-test-server|
 48 | | **`xmlui-test-server`** | *Optional*: server, you can use any static web server|
 49 | 
 50 | 
 51 | You can deploy this tree structure (minus the optional `api.json`, `data.db`, and `xmlui-test-server`) to any static webserver that's configured to serve `index.html`. Consider this minimal app.
 52 | 
 53 | ```xmlui-tree
 54 | xmlui-minimal
 55 |   index.html
 56 |   Main.xmlui
 57 |   components
 58 |     Home.xmlui
 59 |   resources
 60 |     favicon.ico
 61 |     xmlui-logo-inverted.svg
 62 |     xmlui-logo.svg
 63 |   xmlui
 64 |     0.9.23.js
 65 | ```
 66 | 
 67 | ## index.html
 68 | 
 69 | ```html
 70 | <!DOCTYPE html>
 71 | <html lang="en">
 72 | 
 73 | <head>
 74 |     <meta charset="UTF-8" />
 75 |     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
 76 |     <script src="xmlui/0.9.23.js"></script>
 77 | </head>
 78 | 
 79 | <body>
 80 | </body>
 81 | 
 82 | </html>
 83 | ```
 84 | 
 85 | ## Main.xmlui
 86 | 
 87 | ```xmlui
 88 | <App name="XMLUI Minimal">
 89 | 
 90 |   <NavPanel>
 91 |     <NavLink label="Home" to="/Home" />
 92 |   </NavPanel>
 93 | 
 94 |   <Pages>
 95 |     <Page url="/Home">
 96 |       <Home />
 97 |     </Page>
 98 |   </Pages>
 99 | 
100 | </App>
101 | ```
102 | 
103 | ## Home.xmlui
104 | 
105 | ```xmlui
106 | <Component name="Home" >
107 | 
108 | A minimal XMLUI app
109 | 
110 | </Component>
111 | ```
112 | 
113 | ## Local deployment
114 | 
115 | If you are working locally, in a folder at the root of this tree, here are some ways you can serve the app.
116 | 
117 | If you have node.js and npm:
118 | 
119 | ```
120 | npx -y http-server
121 | 
122 | $ npx -y http-server
123 | Starting up http-server, serving ./
124 | 
125 | Available on:
126 |   http://127.0.0.1:8080
127 | ```
128 | 
129 | If you have python:
130 | 
131 | ```
132 | $ python -m http.server 8080
133 | Serving HTTP on :: port 8080 (http://[::]:8080/) ...
134 | ```
135 | 
136 | In either case, visit http://localhost:8080 to view the app.
137 | 
138 | See also [Hosted deployment](/hosted-deployment).
139 | 
140 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components/Charts/DonutChart/DonutChart.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { createComponentRenderer } from "../../../components-core/renderers";
 2 | import styles from "../PieChart/PieChartNative.module.scss";
 3 | import { defaultProps, PieChart } from "../PieChart/PieChartNative";
 4 | import { parseScssVar } from "../../../components-core/theming/themeVars";
 5 | import { createMetadata } from "../../metadata-helpers";
 6 | 
 7 | const COMP = "DonutChart";
 8 | 
 9 | const defaultPropsDonut = {
10 |   ...defaultProps,
11 |   innerRadius: 60,
12 | };
13 | 
14 | export const DonutChartMd = createMetadata({
15 |   status: "experimental",
16 |   description: "A derivative of [PieChart](/components/PieChart) with a hollow center. " +
17 |     "Note that the height of the component or its parent needs to be set explicitly.",
18 |   props: {
19 |     data: {
20 |       description: "The data to be displayed in the chart. Needs to be an array of objects.",
21 |     },
22 |     nameKey: {
23 |       description:
24 |         "Specifies the key in the data objects that will be used to label the different data series.",
25 |       valueType: "string",
26 |     },
27 |     dataKey: {
28 |       description:
29 |         "This property specifies the key in the data objects that will be used to render the chart.",
30 |       valueType: "string",
31 |     },
32 |     showLabel: {
33 |       description: "Toggles whether to show labels (\`true\`) or not (\`false\`).",
34 |       valueType: "boolean",
35 |       defaultValue: defaultPropsDonut.showLabel,
36 |     },
37 |     innerRadius: {
38 |       description: "Sets the inner radius of the donut chart.",
39 |       valueType: "number",
40 |       defaultValue: defaultPropsDonut.innerRadius,
41 |     },
42 |     showLabelList: {
43 |       description: "Whether to show labels in a list (\`true\`) or not (\`false\`).",
44 |       valueType: "boolean",
45 |       defaultValue: defaultPropsDonut.showLabelList,
46 |     },
47 |     showLegend: {
48 |       description: "Whether to show a legend (\`true\`) or not (\`false\`).",
49 |       valueType: "boolean",
50 |       defaultValue: defaultPropsDonut.showLegend,
51 |     },
52 |   },
53 |   themeVars: parseScssVar(styles.themeVars),
54 |   defaultThemeVars: {
55 |     "textColor-labelList-PieChart": "$textColor-primary",
56 |   },
57 | });
58 | 
59 | export const donutChartComponentRenderer = createComponentRenderer(
60 |   COMP,
61 |   DonutChartMd,
62 |   ({ extractValue, node, className, renderChild }) => {
63 |     return (
64 |       <PieChart
65 |         showLabelList={extractValue.asOptionalBoolean(
66 |           node.props?.showLabelList,
67 |           defaultPropsDonut.showLabelList,
68 |         )}
69 |         innerRadius={extractValue.asOptionalNumber(
70 |           node.props?.innerRadius,
71 |           defaultPropsDonut.innerRadius,
72 |         )}
73 |         data={extractValue(node.props?.data)}
74 |         className={className}
75 |         showLabel={extractValue.asOptionalBoolean(
76 |           node.props?.showLabel,
77 |           defaultPropsDonut.showLabel,
78 |         )}
79 |         dataKey={extractValue(node.props?.dataKey)}
80 |         nameKey={extractValue(node.props?.nameKey)}
81 |         showLegend={extractValue.asOptionalBoolean(
82 |           node.props?.showLegend,
83 |           defaultPropsDonut.showLegend,
84 |         )}
85 |       >
86 |         {renderChild(node.children)}
87 |       </PieChart>
88 |     );
89 |   },
90 | );
91 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components/List/List.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 | @layer components {
 11 |   .outerWrapper {
 12 |     overflow: auto;
 13 |     //max-height: 100%;
 14 |     overflow-anchor: none;
 15 | 
 16 |     &.hasOutsideScroll {
 17 |       overflow: initial;
 18 |     }
 19 |   }
 20 | 
 21 |   .innerWrapper {
 22 |     visibility: hidden;
 23 |     display: flex;
 24 |     flex-direction: column;
 25 |     min-height: 100%;
 26 | 
 27 |     &.reverse {
 28 |       justify-content: flex-end;
 29 |     }
 30 |   }
 31 | 
 32 |   .infoWrapper {
 33 |     width: 100%;
 34 |     margin: 0 auto;
 35 |   }
 36 | 
 37 |   .loadingWrapper {
 38 |     display: flex;
 39 |     flex-direction: row;
 40 |     justify-content: center;
 41 |     padding-top: t.$space-2;
 42 |     padding-bottom: t.$space-2;
 43 |   }
 44 | 
 45 |   .noRows {
 46 |     width: 100%;
 47 |     text-align: center;
 48 |     margin-top: t.$space-4;
 49 |   }
 50 | 
 51 |   // --- We export the theme variables to add them to the component renderer
 52 |   :export {
 53 |     themeVars: t.json-stringify($themeVars);
 54 |   }
 55 | 
 56 |   .borderCollapse {
 57 |     &:not(.sectioned) {
 58 |       .row {
 59 |         //first row in the list (but not the last)
 60 |         &:first-child:not(:last-child) {
 61 |           & > * {
 62 |             border-bottom-left-radius: 0;
 63 |             border-bottom-right-radius: 0;
 64 |             border-bottom: 0;
 65 |           }
 66 |         }
 67 | 
 68 |         //last row in the list (but not the first)
 69 |         &:last-child:not(:first-child) {
 70 |           & > * {
 71 |             border-top-left-radius: 0;
 72 |             border-top-right-radius: 0;
 73 |           }
 74 |         }
 75 | 
 76 |         //rows in the middle of the list
 77 |         &:not(:first-child):not(:last-child) {
 78 |           & > * {
 79 |             border-bottom-left-radius: 0;
 80 |             border-bottom-right-radius: 0;
 81 |             border-top-left-radius: 0;
 82 |             border-top-right-radius: 0;
 83 |             border-bottom: 0;
 84 |           }
 85 |         }
 86 |       }
 87 |     }
 88 | 
 89 |     &.sectioned {
 90 |       //.row after the section header (first row in a section)
 91 |       .section + .row:not(:has(+ .sectionFooter)) {
 92 |         & > * {
 93 |           border-bottom-left-radius: 0;
 94 |           border-bottom-right-radius: 0;
 95 |           border-bottom: 0;
 96 |         }
 97 |       }
 98 | 
 99 |       //.row before the sectionFooter (last row in a section)
100 |       .row:has(+ .sectionFooter):not(.section + .row) {
101 |         & > * {
102 |           border-top-left-radius: 0;
103 |           border-top-right-radius: 0;
104 |         }
105 |       }
106 | 
107 |       //we select the rows that has .row as direct sibling, but not the first row of a section (rows in the middle of the section)
108 |       .row:has(+ .row):not(.section + .row) {
109 |         & > * {
110 |           border-bottom-left-radius: 0;
111 |           border-bottom-right-radius: 0;
112 |           border-top-left-radius: 0;
113 |           border-top-right-radius: 0;
114 |           border-bottom: 0;
115 |         }
116 |       }
117 |     }
118 |   }
119 | }
120 | 
121 | // --- We export the theme variables to add them to the component renderer
122 | :export {
123 |   themeVars: t.json-stringify($themeVars);
124 | }
125 | 
```

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

```typescript
 1 | import { expect, test } from "../../testing/fixtures";
 2 | 
 3 | // =============================================================================
 4 | // BASIC FUNCTIONALITY TESTS
 5 | // =============================================================================
 6 | 
 7 | test.describe("Basic Functionality", () => {
 8 |   test("renders in light mode by default", async ({ initTestBed, page }) => {
 9 |     await initTestBed(`
10 |       <App>
11 |         <ToneSwitch />
12 |         <Text>{activeThemeTone}</Text>
13 |       </App>
14 |     `);
15 |     const toggle = page.getByRole("switch");
16 |     await expect(toggle).toBeVisible();
17 |     await expect(page.getByText("light")).toBeVisible();
18 |   });
19 | 
20 |   test("toggles to dark mode when clicked", async ({ initTestBed, page }) => {
21 |     await initTestBed(`
22 |       <App>
23 |         <ToneSwitch />
24 |         <Text>{activeThemeTone}</Text>
25 |       </App>
26 |     `);
27 |     const toggle = page.getByRole("switch");
28 |     await expect(toggle).toBeVisible();
29 |     await toggle.click({ force: true });
30 |     await expect(page.getByText("dark")).toBeVisible();
31 |     await expect(toggle).toBeChecked();
32 |   });
33 | 
34 |   test("toggles back to light mode when clicked again", async ({ initTestBed, page }) => {
35 |     await initTestBed(`
36 |       <App>
37 |         <ToneSwitch />
38 |         <Text>{activeThemeTone}</Text>
39 |       </App>
40 |     `);
41 |     const toggle = page.getByRole("switch");
42 |     await expect(toggle).toBeVisible();
43 |     await toggle.click({ force: true });
44 |     await expect(page.getByText("dark")).toBeVisible();
45 |     await expect(toggle).toBeChecked();
46 |     await toggle.click({ force: true });
47 |     await expect(page.getByText("light")).toBeVisible();
48 |     await expect(toggle).not.toBeChecked();
49 |   });
50 | });
51 | 
52 | // =============================================================================
53 | // ACCESSIBILITY TESTS
54 | // =============================================================================
55 | 
56 | test.describe("Accessibility", () => {
57 |   test("has switch role", async ({ initTestBed, page }) => {
58 |     await initTestBed(`<ToneSwitch />`);
59 |     const toggle = page.getByRole("switch");
60 |     await expect(toggle).toBeVisible();
61 |   });
62 | 
63 |   test("is keyboard accessible with Space key", async ({ initTestBed, page }) => {
64 |     await initTestBed(`<ToneSwitch />`);
65 |     const toggle = page.getByRole("switch");
66 |     
67 |     await toggle.focus();
68 |     await expect(toggle).toBeFocused();
69 |     
70 |     await page.keyboard.press("Space");
71 |     await expect(toggle).toBeChecked();
72 |   });
73 | 
74 |   test("maintains focus during interactions", async ({ initTestBed, page }) => {
75 |     await initTestBed(`<ToneSwitch />`);
76 |     const toggle = page.getByRole("switch");
77 |     
78 |     await toggle.focus();
79 |     await toggle.click({ force: true });
80 |     await expect(toggle).toBeFocused();
81 |   });
82 | 
83 |   test("has appropriate aria-checked state", async ({ initTestBed, page }) => {
84 |     await initTestBed(`<ToneSwitch />`);
85 |     const toggle = page.getByRole("switch");
86 |     
87 |     await expect(toggle).toHaveAttribute("aria-checked", "false");
88 |     
89 |     await toggle.click({ force: true });
90 |     await expect(toggle).toHaveAttribute("aria-checked", "true");
91 |   });
92 | });
93 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components/Charts/PieChart/PieChart.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { defaultProps, PieChart } from "./PieChartNative";
 2 | import styles from "./PieChartNative.module.scss";
 3 | import { LabelPositionValues } from "../utils/abstractions";
 4 | import { parseScssVar } from "../../../components-core/theming/themeVars";
 5 | import { createComponentRenderer } from "../../../components-core/renderers";
 6 | import type { LabelPosition } from "recharts/types/component/Label";
 7 | import { createMetadata, d } from "../../metadata-helpers";
 8 | 
 9 | const COMP = "PieChart";
10 | 
11 | export const PieChartMd = createMetadata({
12 |   status: "experimental",
13 |   description:
14 |     "`PieChart` visualizes proportional data as circular segments; each slice " +
15 |     "represents a percentage of the whole. Note that the height of the component or " +
16 |     "its parent needs to be set explicitly.",
17 |   docFolder: "Charts/PieChart",
18 |   props: {
19 |     data: {
20 |       description: "The data to be displayed in the chart. Needs to be an array of objects.",
21 |     },
22 |     nameKey: {
23 |       description:
24 |         "Specifies the key in the data objects that will be used to label the different data series.",
25 |       valueType: "string",
26 |     },
27 |     dataKey: {
28 |       description:
29 |         "This property specifies the key in the data objects that will be used to render the chart.",
30 |       valueType: "string",
31 |     },
32 |     showLabel: {
33 |       description: "Toggles whether to show labels (\`true\`) or not (\`false\`).",
34 |       valueType: "boolean",
35 |       defaultValue: defaultProps.showLabel,
36 |     },
37 |     showLabelList: {
38 |       description: "Whether to show labels in a list (\`true\`) or not (\`false\`).",
39 |       valueType: "boolean",
40 |       defaultValue: defaultProps.showLabelList,
41 |     },
42 |     labelListPosition: {
43 |       description: "The position of the label list.",
44 |       valueType: "string",
45 |       defaultValue: defaultProps.labelListPosition,
46 |       availableValues: LabelPositionValues,
47 |     },
48 |     outerRadius: d(
49 |       "The outer radius of the pie chart, can be a number or a string (e.g., '100%').",
50 |     ),
51 |     showLegend: {
52 |       description: "Toggles whether to show legend (\`true\`) or not (\`false\`).",
53 |       valueType: "boolean",
54 |       defaultValue: defaultProps.showLegend,
55 |     }
56 |   },
57 |   themeVars: parseScssVar(styles.themeVars),
58 |   defaultThemeVars: {
59 |     "textColor-labelList-PieChart": "$textColor-primary",
60 |   },
61 | });
62 | 
63 | export const pieChartComponentRenderer = createComponentRenderer(
64 |   COMP,
65 |   PieChartMd,
66 |   ({ extractValue, node, className, renderChild }) => {
67 |     return (
68 |       <PieChart
69 |         showLabelList={extractValue.asOptionalBoolean(node.props?.showLabelList)}
70 |         labelListPosition={extractValue.asOptionalString(node.props?.labelListPosition) as LabelPosition}
71 |         data={extractValue(node.props?.data)}
72 |         className={className}
73 |         showLabel={extractValue.asOptionalBoolean(node.props?.showLabel)}
74 |         showLegend={extractValue.asOptionalBoolean(node.props?.showLegend)}
75 |         dataKey={extractValue(node.props?.dataKey)}
76 |         nameKey={extractValue(node.props?.nameKey)}
77 |       >
78 |         {renderChild(node.children)}
79 |       </PieChart>
80 |     );
81 |   },
82 | );
83 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components/Tooltip/Tooltip.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 | $component: "Tooltip";
 11 | $themeVars: t.composePaddingVars($themeVars, $component);
 12 | $themeVars: t.composeBorderVars($themeVars, $component);
 13 | 
 14 | 
 15 | // --- Theme variables for Tooltip component
 16 | $backgroundColor-Tooltip: createThemeVar("backgroundColor-#{$component}");
 17 | $textColor-Tooltip: createThemeVar("textColor-#{$component}");
 18 | $fontSize-Tooltip: createThemeVar("fontSize-#{$component}");
 19 | $lineHeight-Tooltip: createThemeVar("lineHeight-#{$component}");
 20 | $boxShadow-Tooltip: createThemeVar("boxShadow-#{$component}");
 21 | $fill-arrow-Tooltip: createThemeVar("fill-arrow-#{$component}");
 22 | $stroke-arrow-Tooltip: createThemeVar("stroke-arrow-#{$component}");
 23 | $strokeWidth-arrow-Tooltip: createThemeVar("strokeWidth-arrow-#{$component}");  
 24 | $animationDuration-Tooltip: createThemeVar("animationDuration-#{$component}");
 25 | $animation-Tooltip: createThemeVar("animation-#{$component}");
 26 | 
 27 | /* Tooltip styles */
 28 | 
 29 | .hiddenTrigger {
 30 |   position: fixed;
 31 |   left: 0;
 32 |   top: 0;
 33 |   width: 1px;
 34 |   height: 1px;
 35 |   pointer-events: none;
 36 |   z-index: -1;
 37 |   opacity: 0;
 38 | }
 39 | 
 40 | .content {
 41 |   @include t.paddingVars($themeVars, $component);
 42 |   @include t.borderVars($themeVars, $component);
 43 |   font-size: $fontSize-Tooltip;
 44 |   line-height: $lineHeight-Tooltip;
 45 |   color: $textColor-Tooltip;
 46 |   background-color: $backgroundColor-Tooltip;
 47 |   box-shadow: $boxShadow-Tooltip;
 48 |   user-select: none;
 49 |   animation-duration: $animationDuration-Tooltip;
 50 |   animation-timing-function: $animation-Tooltip;
 51 |   will-change: transform, opacity;
 52 |   z-index: 9999;
 53 | }
 54 | 
 55 | .content[data-state='delayed-open'][data-side='top'] {
 56 |   animation-name: slideDownAndFade;
 57 | }
 58 | 
 59 | .content[data-state='delayed-open'][data-side='right'] {
 60 |   animation-name: slideLeftAndFade;
 61 | }
 62 | 
 63 | .content[data-state='delayed-open'][data-side='bottom'] {
 64 |   animation-name: slideUpAndFade;
 65 | }
 66 | 
 67 | .content[data-state='delayed-open'][data-side='left'] {
 68 |   animation-name: slideRightAndFade;
 69 | }
 70 | 
 71 | .arrow {
 72 |   fill: $fill-arrow-Tooltip;
 73 |   stroke: $stroke-arrow-Tooltip;
 74 |   stroke-width: $strokeWidth-arrow-Tooltip;
 75 | }
 76 | 
 77 | @keyframes slideUpAndFade {
 78 |   from {
 79 |     opacity: 0;
 80 |     transform: translateY(2px);
 81 |   }
 82 |   to {
 83 |     opacity: 1;
 84 |     transform: translateY(0);
 85 |   }
 86 | }
 87 | 
 88 | @keyframes slideRightAndFade {
 89 |   from {
 90 |     opacity: 0;
 91 |     transform: translateX(-2px);
 92 |   }
 93 |   to {
 94 |     opacity: 1;
 95 |     transform: translateX(0);
 96 |   }
 97 | }
 98 | 
 99 | @keyframes slideDownAndFade {
100 |   from {
101 |     opacity: 0;
102 |     transform: translateY(-2px);
103 |   }
104 |   to {
105 |     opacity: 1;
106 |     transform: translateY(0);
107 |   }
108 | }
109 | 
110 | @keyframes slideLeftAndFade {
111 |   from {
112 |     opacity: 0;
113 |     transform: translateX(2px);
114 |   }
115 |   to {
116 |     opacity: 1;
117 |     transform: translateX(0);
118 |   }
119 | }
120 | 
121 | // --- We export the theme variables to add them to the component renderer
122 | :export {
123 |   themeVars: t.json-stringify($themeVars);
124 | }
125 | 
```

--------------------------------------------------------------------------------
/xmlui/tests/parsers/scripting/eval-tree-arrow.test.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { describe, expect, it } from "vitest";
  2 | 
  3 | import { evalBindingExpression } from "../../../src/components-core/script-runner/eval-tree-sync";
  4 | import { createEvalContext } from "./test-helpers";
  5 | 
  6 | describe("Evaluate arrow expressions", () => {
  7 |   it("Arrow #1", () => {
  8 |     // --- Arrange
  9 |     const source = "(x => 2 * x)(4)";
 10 |     const context = createEvalContext({});
 11 | 
 12 |     // --- Act
 13 |     const value = evalBindingExpression(source, context);
 14 | 
 15 |     // --- Arrange
 16 |     expect(value).equal(8);
 17 |   });
 18 | 
 19 |   it("Arrow #2", () => {
 20 |     // --- Arrange
 21 |     const source = "((x, y) => x + y)(1, 2)";
 22 |     const context = createEvalContext({});
 23 | 
 24 |     // --- Act
 25 |     const value = evalBindingExpression(source, context);
 26 | 
 27 |     // --- Arrange
 28 |     expect(value).equal(3);
 29 |   });
 30 | 
 31 |   it("Arrow #3", () => {
 32 |     // --- Arrange
 33 |     const source = "((x, y) => { return x + y })(1, 2)";
 34 |     const context = createEvalContext({});
 35 | 
 36 |     // --- Act
 37 |     const value = evalBindingExpression(source, context);
 38 | 
 39 |     // --- Arrange
 40 |     expect(value).equal(3);
 41 |   });
 42 | 
 43 |   it("Arrow #4", () => {
 44 |     // --- Arrange
 45 |     const source = "(x => (++x.h))(count)";
 46 |     const context = createEvalContext({
 47 |       localContext: {
 48 |         count: { h: 3 },
 49 |       },
 50 |     });
 51 | 
 52 |     // --- Act
 53 |     const value = evalBindingExpression(source, context);
 54 | 
 55 |     // --- Arrange
 56 |     expect(value).equal(4);
 57 |   });
 58 | 
 59 |   it("Arrow #5", () => {
 60 |     // --- Arrange
 61 |     const source = "(x => x += 2)(count)";
 62 |     const context = createEvalContext({
 63 |       localContext: {
 64 |         count: 3,
 65 |       },
 66 |     });
 67 | 
 68 |     // --- Act
 69 |     const value = evalBindingExpression(source, context);
 70 | 
 71 |     // --- Arrange
 72 |     expect(value).equal(5);
 73 |   });
 74 | 
 75 |   it("Arrow #6", () => {
 76 |     // --- Arrange
 77 |     const source = "(x => x += 2)(count + 4)";
 78 |     const context = createEvalContext({
 79 |       localContext: {
 80 |         count: 3,
 81 |       },
 82 |     });
 83 | 
 84 |     // --- Act
 85 |     const value = evalBindingExpression(source, context);
 86 | 
 87 |     // --- Arrange
 88 |     expect(value).equal(9);
 89 |   });
 90 | 
 91 |   it("Arrow #7", () => {
 92 |     // --- Arrange
 93 |     const source = "[1,2,3,4,5].filter(x => x % 2 === 0)[1]";
 94 |     const context = createEvalContext({
 95 |       localContext: {
 96 |         count: 3,
 97 |       },
 98 |     });
 99 | 
100 |     // --- Act
101 |     const value = evalBindingExpression(source, context);
102 | 
103 |     // --- Arrange
104 |     expect(value).equal(4);
105 |   });
106 | 
107 |   it("Arrow #8", () => {
108 |     // --- Arrange
109 |     const source = "containsArray.array.filter(item => item % 2 === 0)[1]";
110 |     const context = createEvalContext({
111 |       localContext: {
112 |         containsArray: {
113 |           array: [5, 4, 3, 2, 1],
114 |         },
115 |       },
116 |     });
117 | 
118 |     // --- Act
119 |     const value = evalBindingExpression(source, context);
120 | 
121 |     // --- Arrange
122 |     expect(value).equal(2);
123 |   });
124 | 
125 |   it("Arrow #9", () => {
126 |     // --- Arrange
127 |     const source = "array.reduce((acc, item) => acc + item, 0)";
128 |     const context = createEvalContext({
129 |       localContext: {
130 |         array: [5, 4, 3, 2, 1],
131 |       },
132 |     });
133 | 
134 |     // --- Act
135 |     const value = evalBindingExpression(source, context);
136 | 
137 |     // --- Arrange
138 |     expect(value).equal(15);
139 |   });
140 | });
141 | 
```

--------------------------------------------------------------------------------
/xmlui/src/components-core/script-runner/asyncProxy.ts:
--------------------------------------------------------------------------------

```typescript
 1 | /**
 2 |  * Gets a proxy function for one that does not support async operations
 3 |  * @param fn Function to replace with a proxy
 4 |  * @param origArgs Original function arguments
 5 |  * @param context Function context ("this" of the function invocation)
 6 |  * @return The proxy, if found; otherwise the original function
 7 |  */
 8 | export function getAsyncProxy(fn: Function, origArgs: any[], context: any): Function {
 9 |     const proxyFn = asyncProxies.get(fn);
10 |     if (!proxyFn) return fn;
11 | 
12 |     origArgs.unshift(context);
13 |     return proxyFn;
14 | }
15 | 
16 | // Async implementations for JavaScript functions that do not support async arguments
17 | const asyncProxies = new Map<Function, Function>();
18 | asyncProxies.set(Array.prototype.filter, asyncFilter);
19 | asyncProxies.set(Array.prototype.forEach, asyncForEach);
20 | asyncProxies.set(Array.prototype.map, asyncMap);
21 | asyncProxies.set(Array.prototype.every, asyncEvery);
22 | asyncProxies.set(Array.prototype.findIndex, asyncFindIndex);
23 | asyncProxies.set(Array.prototype.find, asyncFind);
24 | asyncProxies.set(Array.prototype.flatMap, asyncFlatMap);
25 | asyncProxies.set(Array.prototype.some, asyncSome);
26 | 
27 | // The async implementation of Array.prototype.some
28 | async function asyncSome(arr: any[], predicate: (...args: any[]) => boolean) {
29 |   const results = await Promise.all(arr.map(predicate));
30 |   return arr.some((_v, index) => results[index]);
31 | }
32 | 
33 | // The async implementation of Array.prototype.filter
34 | async function asyncFilter(arr: any[], predicate: (...args: any[]) => boolean) {
35 |   const results = await Promise.all(arr.map(predicate));
36 |   return arr.filter((_v, index) => results[index]);
37 | }
38 | 
39 | // The async implementation of Array.prototype.forEach
40 | async function asyncForEach(arr: any[], predicate: (...args: any[]) => void) {
41 |   for (let i = 0; i < arr.length; i++) {
42 |     await predicate(arr[i], i, arr);
43 |   }
44 | }
45 | 
46 | // The async implementation of Array.prototype.map
47 | async function asyncMap(arr: any[], predicate: (...args: any[]) => Promise<any[]>) {
48 |   const result = [];
49 |   for (let i = 0; i < arr.length; i++) {
50 |     result.push(await predicate(arr[i], i, arr));
51 |   }
52 |   return result;
53 | }
54 | 
55 | // The async implementation of Array.prototype.asyncEvery
56 | async function asyncEvery(arr: any[], callback: (...args: any[]) => any) {
57 |   const results = await Promise.all(arr.map(callback));
58 |   return results.every((_v, index) => results[index]);
59 | }
60 | 
61 | // The async implementation of Array.prototype.asyncFind
62 | async function asyncFind(arr: any[], predicate: (...args: any[]) => boolean) {
63 |   const results = await Promise.all(arr.map(predicate));
64 |   return arr.find((_v, index) => results[index]);
65 | }
66 | 
67 | // The async implementation of Array.prototype.asyncFindIndex
68 | async function asyncFindIndex(arr: any[], predicate: (...args: any[]) => boolean) {
69 |   const results = await Promise.all(arr.map(predicate));
70 |   return arr.findIndex((_v, index) => results[index]);
71 | }
72 | 
73 | // The async implementation of Array.prototype.asyncFlatMap
74 | async function asyncFlatMap(arr: any[], predicate: (...args: any[]) => boolean) {
75 |   const results = await Promise.all(arr.map(predicate));
76 |   return arr.flatMap((_v, index) => results[index]);
77 | }
78 | 
```

--------------------------------------------------------------------------------
/docs/public/pages/user-defined-components.md:
--------------------------------------------------------------------------------

```markdown
 1 | # User-defined components
 2 | 
 3 | You can define your own components, pass properties to them, and use them interchangeably with core components. When you find yourself writing a component with more than a few dozen lines of XMLUI markup, consider refactoring in order to name and package the key blocks of code. This strategy not only enables reuse but, just as importantly, ensures that the refactored component will be easy to read and maintain.
 4 | 
 5 | Such refactoring requires you to create and name new `.xmlui` files, identify inline elements that need to be passed as properties from a refactored component, and use those properties in newly-created subcomponents. Historically that kind of overhead has been a disincentive to refactoring in any programming environment. Now you can often outsource that gruntwork to AI assistants. It works particularly well with XMLUI, we use this strategy extensively, and we highly recommend it.
 6 | 
 7 | Here's a simple component to package a name/value pair.
 8 | 
 9 | ```xmlui-pg display noHeader
10 | ---app display
11 | <App>
12 |   <NameValue name="Mary" value="123" />
13 | </App>
14 | ---comp display
15 | <Component name="NameValue">
16 |   <Card width="20%">
17 |     <Text>Name: { $props.name} </Text>
18 |     <Text>Value: { $props.value} </Text>
19 |   </Card>
20 | </Component>
21 | ```
22 | 
23 | The component's name must start with an uppercase letter followed by letters, digits, the underscore (`_`), or the dollar sign (`$`) character. Components must be placed into separate files in the `components` folder within the app's root folder. The component's name must match its filename.
24 | 
25 | Here's how you can define default values for properties.
26 | 
27 | ```xmlui
28 | <Component name="NameValue">
29 |   <Card width="20%">
30 |     <Text>Name: { $props.name ?? '[no name]' } </Text>
31 |     <Text>Value: { $props.value ?? '[no value]' } </Text>
32 |   </Card>
33 | </Component>
34 | ```
35 | 
36 | ## Events
37 | 
38 | The `<IncButton>` component increments its value for every click, and notifies its environment by firing an event. The event's handler receives the current counter as an event parameter.
39 | 
40 | ```xmlui-pg noHeader
41 | ---app display
42 | <App>
43 |   <Card width="30%">
44 |     <variable name="text" value=""/>
45 |     <IncButton onIncremented="(clickCount) => text += ' ' + clickCount" />
46 |     <Text value="{text}" />
47 |   </Card>
48 | </App>
49 | ---comp display
50 | <Component name="IncButton">
51 |   <variable name="count" value="{0}" />
52 |   <Button
53 |     label="Click to increment: {count}"
54 |     onClick="count++; emitEvent('incremented', count)"
55 |   />
56 | </Component>
57 | ```
58 | 
59 | ## Methods
60 | 
61 | The `<UsingInternalModal>` component exports the `open` method of the `ModalDialog` that it defines.
62 | 
63 | ```xmlui-pg noHeader
64 | ---app display
65 | <App height="300px" >
66 |   <UsingInternalModal id="component"/>
67 |   <Button label="Open the internal dialog" onClick="component.openDialog()" />
68 | </App>
69 | ---comp display
70 | <Component name="UsingInternalModal">
71 |   <ModalDialog id="dialog" title="Example Dialog">
72 |     <Button label="Close Dialog" onClick="dialog.close()" />
73 |   </ModalDialog>
74 | 
75 |   <H1>Using an Internal Modal Dialog</H1>
76 | 
77 |   <method name="openDialog">
78 |     console.log('internal method called')
79 |     dialog.open();
80 |   </method>
81 | </Component>
82 | ```
83 | 
```
Page 16/181FirstPrevNextLast