#
tokens: 48307/50000 7/1630 files (page 46/145)
lines: off (toggle) GitHub
raw markdown copy
This is page 46 of 145. Use http://codebase.md/xmlui-org/xmlui/tools/vscode/resources/%7BimageSrc%7D?lines=false&page={x} to view the full context.

# Directory Structure

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

# Files

--------------------------------------------------------------------------------
/xmlui/src/components-core/utils/hooks.tsx:
--------------------------------------------------------------------------------

```typescript
import type { MutableRefObject } from "react";
import React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
import { isEqual } from "lodash-es";

import type { ComponentApi, ContainerState } from "../rendering/ContainerWrapper";
import type { ColorDef } from "./css-utils";

import { shallowCompare, useEvent } from "../utils/misc";
import { useTheme } from "../theming/ThemeContext";
import { EMPTY_OBJECT } from "../constants";
import Color from "color";

/**
 * This hook invokes a callback when the size of the specified DOM element changes.
 * @param element A DOM element to watch for size changes
 * @param callback The callback function to invoke on size changes
 */
export const useResizeObserver = (
  element: React.MutableRefObject<Element | undefined | null>,
  callback: ResizeObserverCallback,
) => {
  const current = element?.current;
  const observer = useRef<ResizeObserver>();

  useEffect(() => {
    // --- We are already observing old element
    if (observer?.current && current) {
      observer.current.unobserve(current);
    }
    observer.current = new ResizeObserver(callback);
    if (element && element.current && observer.current) {
      observer.current.observe(element.current);
    }
  }, [callback, current, element]);
};

/**
 * This hook gets the previous state of the specified value (props, variable used in a React
 * function).
 *
 * @see {@link https://blog.logrocket.com/accessing-previous-props-state-react-hooks/}
 */
export function usePrevious<T>(value: T): ReturnType<typeof useRef<T>>["current"] {
  const ref = useRef<T>();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
}

/**
 * This hook tests if the component is used within an iframe.
 * @returns True, if the component is used within an iframe; otherwise, false.
 */
export function useIsInIFrame() {
  return useMemo(() => {
    try {
      return window.self !== window.top;
    } catch (e) {
      return true;
    }
  }, []);
}

// --- Tests if the document has the focus
const hasFocus = () => typeof document !== "undefined" && document.hasFocus();

/**
 * This hook tests if the window has the focus.
 * @returns True, if the window has the focus; otherwise, false.
 */
export function useIsWindowFocused() {
  const [focused, setFocused] = useState(hasFocus); // Focus for first render

  useEffect(() => {
    setFocused(hasFocus()); // Focus for additional renders

    const onFocus = () => setFocused(true);
    const onBlur = () => setFocused(false);

    window.addEventListener("focus", onFocus);
    window.addEventListener("blur", onBlur);

    return () => {
      window.removeEventListener("focus", onFocus);
      window.removeEventListener("blur", onBlur);
    };
  }, []);

  return focused;
}

/**
 * This hook allows running media queries.
 * @param query Media query to run
 */
export function useMediaQuery(query: string) {
  const [matches, setMatches] = useState<boolean>(false);
  useEffect(() => {
    if (!window) {
      setMatches(false);
      return;
    }

    const matchMedia = window.matchMedia(query);
    // Triggered at the first client-side load and if query changes
    handleChange();

    matchMedia.addEventListener("change", handleChange);
    return () => {
      matchMedia.removeEventListener("change", handleChange);
    };

    function handleChange() {
      setMatches(matchMedia.matches);
    }
  }, [query]);

  return matches;
}

/**
 * This hook runs a callback function when a key is pressed in the document window.
 * @param onDocumentKeydown Callback function to run
 */
export function useDocumentKeydown(onDocumentKeydown: (event: KeyboardEvent) => void) {
  const onKeyDown = useEvent(onDocumentKeydown);
  useEffect(() => {
    document.addEventListener("keydown", onKeyDown);
    return () => {
      document.removeEventListener("keydown", onKeyDown);
    };
  }, [onKeyDown]);
}

/**
 * This hook runs a function when the corresponding component has been mounted.
 * @param onMount
 */
export function useOnMount(onMount: any) {
  const thizRef = useRef({ mountedFired: false });
  useEffect(() => {
    if (!thizRef.current.mountedFired) {
      thizRef.current.mountedFired = true;
      onMount?.();
    }
  }, [onMount]);
}

/**
 * This hook memoizes the specified value. It uses a shallow comparison with the previously
 * stored value when checking for changes. So, while a shallow comparison shows equality,
 * it returns with the memoized value.
 * @param value Value to memoize
 */
export function useShallowCompareMemoize<T extends Record<any, any> | undefined>(value: T) {
  const ref = React.useRef<T>(value);
  const signalRef = React.useRef<number>(0);

  if (!shallowCompare(value, ref.current)) {
    ref.current = value;
    signalRef.current++;
  }

  // eslint-disable-next-line react-hooks/exhaustive-deps
  return React.useMemo(() => ref.current, [signalRef.current]);
}

/**
 * This hook memoizes the specified value. When checking for changes, it uses a deep comparison
 * with the previously stored value. So, while a deep comparison shows equality, it returns with
 * the memoized value, even if value references differ.
 * @param value Value to memoize
 */
export function useDeepCompareMemoize<T extends Record<any, any> | undefined>(value: T) {
  const ref = React.useRef<T>(value);
  const signalRef = React.useRef<number>(0);

  if (!isEqual(value, ref.current)) {
    ref.current = value;
    signalRef.current += 1;
  }

  // eslint-disable-next-line react-hooks/exhaustive-deps
  return React.useMemo(() => ref.current, [signalRef.current]);
}

export function useColors(...colorNames: (string | ColorDef)[]) {
  const { getThemeVar } = useTheme();
  // const paramsRef = useRef(colorNames);
  // const { themeStyles } = useTheme();
  const colors = useMemo(() => {
    const ret: Record<string, string> = {};
    for (const color of colorNames) {
      if (typeof color === "string") {
        const col = getThemeVar(color);
        ret[color] = Color(col).toString();
      } else {
        const col = getThemeVar(color.name);
        ret[color.name] = Color(col).hex().toString();
      }
    }
    return ret;
  }, [colorNames, getThemeVar]);

  // useEffect(() => {
  //   setColors(getColors(...paramsRef.current));
  // }, [themeStyles]);

  return colors;
}

export function useReferenceTrackedApi(componentState: ContainerState) {
  return useShallowCompareMemoize(
    useMemo(() => {
      const ret: Record<string, ComponentApi> = {};
      if (Reflect.ownKeys(componentState).length === 0) {
        //skip containers with no registered apis
        return EMPTY_OBJECT;
      }
      for (const componentApiKey of Object.getOwnPropertySymbols(componentState)) {
        const value = componentState[componentApiKey];
        if (componentApiKey.description) {
          ret[componentApiKey.description] = value;
        }
      }
      return ret;
    }, [componentState]),
  );
}

/**
 * This hook uses either useLayoutEffect or useEffect based on the environment
 * (client-side or server-side).
 */
export const useIsomorphicLayoutEffect =
  typeof document !== "undefined" ? useLayoutEffect : useEffect;

// https://stackoverflow.com/a/49186677
function getScrollParent(element: HTMLElement) {
  let style = getComputedStyle(element);
  const excludeStaticParent = style.position === "absolute";
  const overflowRegex = /(auto|scroll)/;

  if (style.position === "fixed") {
    return document.body;
  }
  for (let parent = element; ; parent = parent.parentElement) {
    if (!parent) {
      return null;
    }
    style = getComputedStyle(parent);
    if (excludeStaticParent && style.position === "static") {
      continue;
    }
    if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX)) {
      return parent;
    }
  }

  return document.body;
}

export const useScrollParent = (element?: HTMLElement): HTMLElement => {
  const [scrollParent, setScrollParent] = useState<HTMLElement | null>(null);
  useIsomorphicLayoutEffect(() => {
    setScrollParent(element ? getScrollParent(element) : null);
  }, [element]);
  return scrollParent;
};

// because safari doesn't support scrollend event...
export const useScrollEventHandler = (
  element: HTMLElement | null | undefined,
  {
    onScrollStart,
    onScrollEnd,
  }: {
    onScrollStart?: () => void;
    onScrollEnd?: () => void;
  },
) => {
  const thisRef = useRef({ scrolling: false });
  useIsomorphicLayoutEffect(() => {
    let timer;
    let listener = () => {
      if (!thisRef.current.scrolling) {
        onScrollStart?.();
      }
      thisRef.current.scrolling = true;
      clearTimeout(timer);
      timer = setTimeout(() => {
        thisRef.current.scrolling = false;
        onScrollEnd?.();
      }, 50);
    };
    element?.addEventListener("scroll", listener);
    return () => {
      element?.removeEventListener("scroll", listener);
    };
  }, [element, onScrollEnd, onScrollStart]);
};

function realBackgroundColor(elem: HTMLElement) {
  let transparent = "rgba(0, 0, 0, 0)";
  let transparentIE11 = "transparent";
  if (!elem) return transparent;

  let bg = getComputedStyle(elem).backgroundColor;
  if (bg === transparent || bg === transparentIE11) {
    return realBackgroundColor(elem.parentElement);
  } else {
    return bg;
  }
}

export const useRealBackground = (element: HTMLElement) => {
  const { activeThemeTone, activeThemeId } = useTheme();
  const [counter, setCounter] = useState(0);
  useEffect(() => {
    return setCounter((prev) => prev + 1);
  }, [activeThemeTone, activeThemeId]);
  return useMemo(() => (element ? realBackgroundColor(element) : "transparent"), [element]);
};

// export const useIsInViewport = (ref, observerOptions) => {
//   const [entered, setEntered] = useState(false);
//   const observer = useRef(
//     new IntersectionObserver(
//       ([entry]) => setEntered(entry.isIntersecting),
//       observerOptions
//     )
//   );
//
//   useEffect(() => {
//     const element = ref.current;
//     const ob = observer.current;
//
//     // stop observing once the element has entered the viewport for the first time.
//     // if (entered) {
//     //   ob.disconnect();
//     //   return;
//     // }
//
//     if (element) ob.observe(element);
//
//     return () => ob.disconnect();
//   }, [entered, ref]);
//
//   return entered;
// };

export const useStartMargin = (
  hasOutsideScroll: boolean,
  parentRef: MutableRefObject<HTMLElement | null | undefined>,
  scrollRef: MutableRefObject<HTMLElement | null | undefined>,
) => {
  const [startMargin, setStartMargin] = useState<number>(0);

  const calculateStartMargin = useEvent(() => {
    if (!hasOutsideScroll) {
      return 0;
    }
    const precedingElement = parentRef.current;
    const scrollContainer = scrollRef.current;

    if (precedingElement && scrollContainer) {
      const precedingRect = precedingElement.getBoundingClientRect();
      const scrollContainerRect = scrollContainer.getBoundingClientRect();

      // It's important that scrollContainer is indeed the element whose scrollTop is relevant
      const scrollTopOfScrollContainer = scrollContainer.scrollTop;

      const calculatedMargin =
        precedingRect.top - scrollContainerRect.top + scrollTopOfScrollContainer;
      return calculatedMargin;
    }
    return 0;
  });

  useResizeObserver(scrollRef, () => {
    setStartMargin(calculateStartMargin());
  });

  return startMargin;
};

export function useHasExplicitHeight(parentRef: React.MutableRefObject<HTMLDivElement | null>) {
  const [hasHeight, setHasHeight] = useState(false);
  useLayoutEffect(() => {
    if (parentRef.current) {
      const computedStyles = window.getComputedStyle(parentRef.current);
      const hasMaxHeight = computedStyles.maxHeight !== "none";
      // Get the original computed height
      const originalHeight = window.getComputedStyle(parentRef.current).height;

      // Store original inline style to restore it later
      const originalInlineHeight = parentRef.current.style.height || "";

      // Temporarily set height to auto and get the new computed height
      parentRef.current.style.height = "auto";
      const autoHeight = window.getComputedStyle(parentRef.current).height;

      // Restore the original inline style immediately
      parentRef.current.style.height = originalInlineHeight;

      // If the original height is different from what the browser
      // calculates for 'auto', it means a height was explicitly set.
      // We also check if the inline style itself had a value.
      let hasHeight = originalHeight !== autoHeight || !!originalInlineHeight;

      const isFlex = computedStyles.display === "flex";
      setHasHeight(hasMaxHeight || hasHeight || isFlex);
    }
  }, [parentRef]);
  return hasHeight;
}

```

--------------------------------------------------------------------------------
/docs/public/resources/files/tutorials/datasource/api.ts:
--------------------------------------------------------------------------------

```typescript
import { ApiInterceptorDefinition } from "xmlui";

const mock: ApiInterceptorDefinition = {
  type: "db",
  config: {
    database: "xmluiDataManipuliationTutorial",
    version: 1
  },
  apiUrl: "/api",
  helpers: {
    Assertions: {
      getIfPresent: `(itemId) => {
        const found = $db.$shoppingItems.byId(itemId);
        if (!found) {
          throw Errors.NotFound404("Item id:" + itemId + " not found");
        }
        return found;
      }`
    },
  },
  auth: {
    defaultLoggedInUser: {
      id: 1
    }
  },
  schemaDescriptor: {
    tables: [
      {
        name: "shoppingItems",
        fields: {
          id: "bigint",
          name: "varchar(64)",
          quantity: "integer",
          unit: "varchar(64)",
          category: "varchar(64)",
          inPantry: "boolean",
        },
        pk: ["++id"],
      },
      {
        name: "polledItems",
        fields: {
          id: "bigint",
          name: "varchar(64)",
          quantity: "integer",
          unit: "varchar(64)",
          category: "varchar(64)",
          inPantry: "boolean",
        },
        pk: ["++id"],
      },
      {
        name: "recipes",
        fields: {
          id: "bigint",
          name: "varchar(64)",
        },
        pk: ["++id"],
      }
    ],
    dtos: {
      recipe: {
        id: "number",
        name: "string",
        ingredients: "{shoppingItems[]}",
      },
    },
  },
  initialData: {
    shoppingItems: [
      {
        id: 1,
        name: "Carrots",
        quantity: 100,
        unit: "grams",
        category: "vegetables",
        inPantry: true,
      },
      {
        id: 2,
        name: "Bananas",
        quantity: 6,
        unit: "pieces",
        category: "fruits",
        inPantry: false,
      },
      {
        id: 3,
        name: "Apples",
        quantity: 5,
        unit: "pieces",
        category: "fruits",
        inPantry: true,
      },
      {
        id: 4,
        name: "Spinach",
        quantity: 1,
        unit: "bunch",
        category: "vegetables",
        inPantry: true,
      },
      {
        id: 5,
        name: "Milk",
        quantity: 10,
        unit: "liter",
        category: "dairy",
        inPantry: false,
      },
      {
        id: 6,
        name: "Cheese",
        quantity: 200,
        unit: "grams",
        category: "dairy",
        inPantry: false,
      },
      {
        id: 7,
        name: "Tomatoes",
        quantity: 3,
        unit: "pieces",
        category: "vegetables",
        inPantry: false,
      },
      {
        id: 8,
        name: "Oranges",
        quantity: 4,
        unit: "pieces",
        category: "fruits",
        inPantry: true,
      },
      {
        id: 9,
        name: "Broccoli",
        quantity: 2,
        unit: "heads",
        category: "vegetables",
        inPantry: true,
      },
      {
        id: 10,
        name: "Eggs",
        quantity: 12,
        unit: "pieces",
        category: "dairy",
        inPantry: false,
      },
      {
        id: 11,
        name: "Potatoes",
        quantity: 1,
        unit: "kg",
        category: "vegetables",
        inPantry: true,
      },
      {
        id: 12,
        name: "Grapes",
        quantity: 500,
        unit: "grams",
        category: "fruits",
        inPantry: false,
      },
      {
        id: 13,
        name: "Chicken",
        quantity: 2,
        unit: "kg",
        category: "meat",
        inPantry: false,
      },
      {
        id: 14,
        name: "Bread",
        quantity: 1,
        unit: "loaf",
        category: "bakery",
        inPantry: true,
      },
      {
        id: 15,
        name: "Yogurt",
        quantity: 500,
        unit: "grams",
        category: "dairy",
        inPantry: true,
      },
      {
        id: 16,
        name: "Olive Oil",
        quantity: 1,
        unit: "liter",
        category: "cooking oils",
        inPantry: true,
      },
    ],
    polledItems: [],
    recipes: [
      {
        id: 1,
        name: "Salad",
        ingredients: [
          {
            id: 1,
            name: "Carrots",
            quantity: 100,
            unit: "grams",
            category: "vegetables",
            inPantry: true,
          },
          {
            id: 7,
            name: "Tomatoes",
            quantity: 3,
            unit: "pieces",
            category: "vegetables",
            inPantry: false,
          },
          {
            id: 9,
            name: "Broccoli",
            quantity: 2,
            unit: "heads",
            category: "vegetables",
            inPantry: true,
          },
        ]
      },
      {
        id: 2,
        name: "Orange Banana Smoothie",
        ingredients: [
          {
            id: 2,
            name: "Bananas",
            quantity: 6,
            unit: "pieces",
            category: "fruits",
            inPantry: false,
          },
          {
            id: 5,
            name: "Milk",
            quantity: 10,
            unit: "liter",
            category: "dairy",
            inPantry: false,
          },
          {
            id: 8,
            name: "Oranges",
            quantity: 4,
            unit: "pieces",
            category: "fruits",
            inPantry: true,
          },
        ]
      },
      {
        id: 3,
        name: "Carrot Soup",
        ingredients: [
          {
            id: 1,
            name: "Carrots",
            quantity: 100,
            unit: "grams",
            category: "vegetables",
            inPantry: true,
          },
          {
            id: 16,
            name: "Olive Oil",
            quantity: 1,
            unit: "liter",
            category: "cooking oils",
            inPantry: true,
          },
        ]
      },
    ],
  },
  operations: {
    login: {
      url: "/login",
      method: "post",
      queryParamTypes: {
        userId: "integer"
      },
      handler: "$authService.login({id: $queryParams.userId})"
    },

    loadMe: {
      url: "/users/me",
      method: "get",
      handler: "$db.$users.byId($loggedInUser.id)"
    },

    test: {
      url: "/test",
      method: "get",
      handler: "return { message: 'Hello from the Server!' }",
    },

    "shopping-list": {
      url: "/shopping-list",
      method: "get",
      responseShape: "shoppingItem[]",
      handler: `$db.$shoppingItems.toArray()`
    },

    "shopping-list-slow": {
      url: "/shopping-list-slow",
      method: "get",
      responseShape: "shoppingItem[]",
      handler: `
        delay(8000);
        return $db.$shoppingItems.toArray();`
    },

    "shopping-list-create": {
      url: "/shopping-list",
      method: "post",
      queryParamTypes: {
        highlight: "boolean",
      },
      responseShape: "shoppingItem?",
      handler: `{
        if ($queryParams.highlight) {
          $requestBody.name = $requestBody.name.toUpperCase() + "!!!";
        }
        return $db.$shoppingItems.insert($requestBody);
      }`
    },

    "shopping-list-create-query": {
      url: "/shopping-list-query",
      method: "post",
      queryParamTypes: {
        addIfInPantry: "boolean",
      },
      responseShape: "shoppingItem?",
      handler: `return $db.$shoppingItems.insert($requestBody);`
    },

    "shopping-list-delete": {
      url: "/shopping-list/:itemId",
      method: "delete",
      pathParamTypes: {
        itemId: "integer",
      },
      responseShape: "boolean",
      handler: `$db.$shoppingItems.native().where("id").equals($pathParams.itemId).delete();`
    },

    "shopping-list-update": {
      url: "/shopping-list/:itemId",
      method: "put",
      pathParamTypes: {
        itemId: "integer",
      },
      responseShape: "shoppingItem",
      handler: `
        const item = $db.$shoppingItems.byId($pathParams.itemId);
        $db.$shoppingItems.update({...item, ...$requestBody});`
    },

    "shopping-list-update-slow": {
      url: "/shopping-list-slow/:itemId",
      method: "put",
      pathParamTypes: {
        itemId: "integer",
      },
      responseShape: "shoppingItem",
      handler: `{
        delay(5000);
        if ($requestBody.name.toLowerCase() === "error") {
          throw Errors.HttpError(400, { message: "Error!" });
        }
        const item = $db.$shoppingItems.byId($pathParams.itemId);
        $db.$shoppingItems.update({...item, ...$requestBody});
      }`
    },

    "shopping-list-meta": {
      url: "/shopping-list-meta",
      method: "get",
      responseShape: "shoppingItem[]",
      handler: `
        const shoppingList = $db.$shoppingItems.toArray();
        return {
          items: shoppingList,
          meta: {
            totalItems: shoppingList.length,
          },
        };`
    },

    "shopping-list-query": {
      url: "/shopping-list-query",
      method: "get",
      responseShape: "shoppingItem[]",
      handler: `
        let items = $db.$shoppingItems.toArray();
        const { inPantry, limit } = $queryParams;

        items = inPantry !== undefined ? items.filter(item => item.inPantry): items;
        items = limit !== undefined ? items.slice(0, limit) : items;

        return items;`
    },

    "shopping-list-refetch": {
      url: "/shopping-list-refetch",
      method: "get",
      responseShape: "shoppingItem[]",
      handler: `        
        $db.$shoppingItems.insert({
          name: "Carrots",
          quantity: 100,
          unit: "grams",
          category: "vegetables",
          inPantry: true,
        })`
    },

    "shopping-list-headers": {
      url: "/shopping-list-headers",
      method: "get",
      responseShape: "shoppingItem[]",
      handler: `
        const token = $requestHeaders['x-api-key'];
        if (token) {
          console.log("Token #" + token + " accepted!");
          return $db.$shoppingItems.toArray();
        }
        throw Errors.HttpError(400, { message: "No API key provided in header!" });`,
    },

    "shopping-list-headers-post": {
      url: "/shopping-list-headers",
      method: "post",
      responseShape: "shoppingItem[]",
      handler: `
        const token = $requestHeaders['x-api-key'];
        if (token === "1111") {
          console.log("Token #" + token + " accepted!");
          return $db.$shoppingItems.insert($requestBody);
        }
        throw Errors.HttpError(400, { message: "No valid API key provided in header!" });`,
    },

    "shopping-list-polled": {
      url: "/shopping-list-polled",
      method: "get",
      responseShape: "shoppingItem[]",
      handler: `
        if ($db.$polledItems.native().count() >= 5) {
          $db.$polledItems.native().clear();
        }

        const groceriesLength = $db.$shoppingItems.native().count();
        const randomIdx = Math.floor(Math.random() * (groceriesLength + 1));

        const newItem = $db.$shoppingItems.byId(randomIdx);
        if (newItem) {
          newItem.id = undefined;
          $db.$polledItems.insert({
            ...newItem,
          });
        }
        
        return $db.$polledItems.toArray();`
    },

    "shopping-list-pagination": {
      url: "/shopping-list-pagination",
      method: "get",
      responseShape: "shoppingItems[]",
      handler: `
        const items = $db.$shoppingItems.toArray();
        const { size, nextPageParam } = $queryParams;
        const _size = parseInt(size);
        let startIndex = 0;
        let endIndex = items.length < _size ? items.length : _size;
        
        if (nextPageParam !== undefined) {
          const startId = parseInt(nextPageParam);
          const temp = items.findIndex(item => item.id === startId);
          if (temp === -1) {
            throw Errors.HttpError(404, "No such item");
          }

          startIndex = temp + 1;
          endIndex = startIndex + _size < items.length ? startIndex + _size : items.length;
        }

        return items.slice(startIndex, endIndex);`
    },

    "shopping-item-unconventional": {
      url: "/shopping-item-unconventional",
      method: "post",
      responseShape: "shoppingItem",
      handler: "Assertions.getIfPresent($requestBody.id)"
    },

    "shopping-item": {
      url: "/shopping-list/:itemId",
      method: "get",
      pathParamTypes: {
        itemId: "integer"
      },
      responseShape: "shoppingItem",
      handler: "Assertions.getIfPresent($pathParams.itemId)"
    },

    "shopping-item-recipes": {
      url: "/shopping-item-recipes/:itemId",
      method: "get",
      pathParamTypes: {
        itemId: "integer"
      },
      responseShape: "recipe[]",
      handler: `
        const item = Assertions.getIfPresent($pathParams.itemId);
        const recipes = $db.$recipes.toArray().filter(recipe => recipe.ingredients.find(ingredient => ingredient.name === item.name));
        return recipes;`
    }
  }
};

export default mock;

```

--------------------------------------------------------------------------------
/xmlui/src/components-core/markup-check.ts:
--------------------------------------------------------------------------------

```typescript
import type { ComponentDef, CompoundComponentDef } from "../abstractions/ComponentDefs";

import { parseParameterString } from "./script-runner/ParameterParser";
import { Parser } from "../parsers/scripting/Parser";
import { layoutOptionKeys } from "./descriptorHelper";
import { viewportSizeNames } from "../components/abstractions";

type IsValidFunction<T> = (propKey: string, propValue: T) => string | string[] | undefined | null;

// --- This interface reperesent an object that can handle component metadata.
// --- As the metadata format may change in the futue, this interface is used to
// --- abstract the metadata handling.
export interface MetadataHandler {
  componentRegistered: (componentName: string) => boolean;
  getComponentProps: (componentName: string) => PropDescriptorHash;
  getComponentEvents: (componentName: string) => Record<string, any>;
  acceptArbitraryProps: (componentName: string) => boolean;
  getComponentValidator: (componentName: string) => ComponentValidator | void;
}

export type PropDescriptor = {
  type?: string;
  availableValues?: any[];
  defaultValue?: any;
  isValid?: IsValidFunction<any>;
};

export type PropDescriptorHash = Record<string, PropDescriptor>;

export type ComponentValidator = (instance: ComponentDef, devMode?: boolean) => string | string[] | null;

type VisitResult = { cancel?: boolean; abort?: boolean };

/**
 * This function checks the XMLUI markup for potential issues. It retrieves
 * a list of errors and warnings.
 * @param rootDef Root component definition
 * @param components Components referenced in the XMLUI markup
 * @param devMode Indicates if the check is performed in development mode
 * @returns List of errors and warnings
 */
export function checkXmlUiMarkup(
  rootDef: ComponentDef | null,
  components: CompoundComponentDef[],
  metadataHandler: MetadataHandler,
  devMode?: boolean,
): MarkupCheckResult[] {
  const errorsCollected: MarkupCheckResult[] = [];

  // --- Initialize the check
  const continuation: VisitResult = {};
  const componentIdsCollected = new Set<string>();
  const compoundIdsCollected = new Set<string>();

  // --- Visit the root component
  if (rootDef) {
    visitComponent(rootDef, null, componentDefVisitor, continuation, metadataHandler);
  }

  // --- Visit the compound components
  if (!continuation.abort) {
    for (const component of components) {
      // --- Rule: Compound component name must be a valid JavaScript identifier
      if (!isValidIdentifier(component.name)) {
        reportError("M007", "Component", component.name);
      }
      // --- Rule: Compound component name cannot be 'Component'
      if (component.name === "Component") {
        reportError("M008", "Component", component.name);
      }

      // --- Rule: Compound component must not have the name of a registered component
      if (metadataHandler.componentRegistered(component.name)) {
        reportError("M009", "Component", component.name);
      }

      // --- Rule: Compound component name must be unique
      if (compoundIdsCollected.has(component.name)) {
        reportError("M010", "Component", component.name);
      } else {
        compoundIdsCollected.add(component.name);
      }

      // --- Reset component ID scope
      componentIdsCollected.clear();
      // --- Visit the compount component's definition
      visitComponent(component.component, null, componentDefVisitor, continuation, metadataHandler);
    }
  }

  // --- Done.
  return errorsCollected;

  // --- This visitor checks the rules for a particular component
  function componentDefVisitor(
    def: ComponentDef,
    parent: ComponentDef | null | undefined,
    before: boolean,
    continuation: VisitResult,
  ): void {
    // --- This is the visitor function to check a ComponentDef markup
    if (!before) {
      // --- Do not visit the component definition after its children have been visited
      return;
    }

    // --- Rule: Component name must be registered
    if (!metadataHandler.componentRegistered(def.type)) {
      reportError("M001", parent?.type ?? "Root", def.type);
      // continuation.cancel = true;
      return;
    }

    // --- Rule: an ID must be a valid JavaScript identifier
    if (def.uid) {
      if (!isValidIdentifier(def.uid)) {
        reportError("M002", def.type, def.type, def.uid);
      } else if (componentIdsCollected.has(def.uid)) {
        reportError("M003", def.type, def.uid);
      } else {
        componentIdsCollected.add(def.uid);
      }
    }

    // --- Check all props of the component
    const propDescriptors = metadataHandler.getComponentProps(def.type) ?? {};
    const currentProps = def.props ?? {};
    for (const propName of Object.keys(currentProps)) {
      const propDescriptor = propDescriptors[propName];

      // --- Rule: The property must be defined in the component descriptor or be a layout option
      // --- or the component must accept arbitrary properties
      if (propDescriptor) {
        // --- The property has a descriptor, so it is allowed.
        // --- Rule: The property value must be parseable
        const propValue = currentProps[propName];
        if (typeof propValue === "string") {
          try {
            parseParameterString(propValue);
          } catch (error) {
            reportError("M006", def.type, propName, (error as any).message);
          }
        }
      } else {
        // --- The property has no descriptor.
        const propParts = propName.split("-");

        // --- Check for a layout property
        const validProp =
          // --- Layout property
          (propParts.length === 1 && layoutOptionKeys.includes(propName)) ||
          // --- Layout property with viewport size
          (propParts.length === 2 &&
            layoutOptionKeys.includes(propParts[0]) &&
            viewportSizeNames.includes(propParts[1])) ||
          // --- Arbitrary property is allowed
          metadataHandler.acceptArbitraryProps(def.type);

        if (!validProp) {
          // --- The component does not accept arbitrary properties and
          // --- the property is not a layout option
          reportError("M005", def.type, def.type, propName);
        }
      }
    }

    // --- Check all events of the component
    const eventDescriptors = metadataHandler.getComponentEvents(def.type) ?? {};
    const currentEvents = def.events ?? {};
    for (const eventName of Object.keys(currentEvents)) {
      const eventDescriptor = eventDescriptors[eventName];

      // --- Rule: The event must be defined in the component descriptor
      if (eventDescriptor) {
        // --- The event has a descriptor, so it is allowed.
        const eventValue = currentEvents[eventName];
        if (typeof eventValue === "string") {
          // --- Rule: The event value must be parseable
          const parser = new Parser(eventValue);
          try {
            parser.parseStatements();
            if (parser.errors.length > 0) {
              reportError("M012", def.type, eventName, parser.errors[0].text);
            }
          } catch (error) {
            reportError("M012", def.type, eventName, (error as any).message);
          }
        }
      } else {
        reportError("M011", def.type, def.type, eventName);
      }
    }

    // --- Check the component validator
    const componentValidator = metadataHandler.getComponentValidator(def.type);
    if (componentValidator) {
      const validationErrors = componentValidator(def, devMode);
      if (validationErrors) {
        if (Array.isArray(validationErrors)) {
          for (const error of validationErrors) {
            reportError("M013", def.type, error);
          }
        } else {
          reportError("M013", def.type, validationErrors);
        }
      }
    }
  }

  /**
   * Checks if a string is a valid JavaScript identifier.
   * @param identifier The string to check.
   * @returns True if the string is a valid identifier, false otherwise.
   */
  function isValidIdentifier(identifier: string): boolean {
    const identifierRegex = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
    return identifierRegex.test(identifier);
  }

  function reportError(code: ErrorCode, name: string, ...args: any) {
    _reportError(code, name, false, ...args);
  }

  function reportWarning(code: ErrorCode, name: string, ...args: any) {
    _reportError(code, name, true, ...args);
  }

  function _reportError(code: ErrorCode, name: string, isWarning: boolean, ...args: any) {
    let errorText: string = errorMessages[code] ?? "Unkonwn error";
    if (args) {
      args.forEach((a: string, idx: number) => (errorText = replace(errorText, `{${idx}}`, args[idx].toString())));
    }

    errorsCollected.push({ name, code, message: errorText, isWarning, args });

    function replace(input: string, placeholder: string, replacement: string): string {
      do {
        input = input.replace(placeholder, replacement);
      } while (input.includes(placeholder));
      return input;
    }
  }
}
// --- This function visits a component, its nested components and children
export function visitComponent(
    def: ComponentDef,
    parent: ComponentDef | null | undefined,
    visitor: (
        def: ComponentDef,
        parent: ComponentDef | null | undefined,
        before: boolean,
        continuation: VisitResult,
    ) => void,
    continuation: VisitResult = {},
    metadataHandler: MetadataHandler,
): void {
  // --- Visit the component (before)
  visitor(def, parent, true, continuation);
  if (continuation.abort || continuation.cancel) {
    // --- Stop the visit
    return;
  }

  // --- Visit the properties with "ComponentDef" value
  const propDescriptors = metadataHandler.getComponentProps(def.type) ?? {};
  const currentProps = def.props ?? {};
  for (const propName of Object.keys(currentProps)) {
    const propDescriptor = propDescriptors[propName];
    if (!propDescriptor) {
      // --- No descriptor for the property, skip it
      continue;
    }

    const propValue = currentProps[propName];
    if (propDescriptor.type === "ComponentDef" && propValue.type) {
      // --- This property holds a nested component, visit it
      visitComponent(propValue, def, visitor, continuation, metadataHandler);
      if (continuation.abort || continuation.cancel) {
        // --- Stop the visit
        return;
      }
    }
  }


  // --- Visit events with nested components
  const eventDescriptors = metadataHandler.getComponentEvents(def.type) ?? {};
  const currentEvents = def.events ?? {};
  for (const eventName of Object.keys(currentEvents)) {
    const eventDescriptor = eventDescriptors[eventName];
    if (!eventDescriptor) {
      // --- No descriptor for the events, skip it
      continue;
    }

    const eventValue = currentEvents[eventName];
    if (typeof eventValue === "object" && eventValue.type) {
      // --- This event holds a nested component, visit it
      visitComponent(eventValue, def, visitor, continuation, metadataHandler);
      if (continuation.abort) {
        // --- Stop visiting this component
        return;
      }
      if (continuation.cancel) {
        // --- Skip the remaining items
        break;
      }
    }
  }

  // --- Visit the component children
  if (def.children) {
    for (const child of def.children) {
      visitComponent(child, def, visitor, continuation, metadataHandler);
      if (continuation.abort) {
        // --- Stop visiting this component
        return;
      }
      if (continuation.cancel) {
        // --- Skip the remaining items
        break;
      }
    }
  }

  // --- Visit the component (after)
  visitor(def, undefined, false, continuation);
}


export type MarkupCheckResult = {
  name: string;
  code: ErrorCode;
  message: string;
  isWarning?: boolean;
  args?: Array<any>
};

// --- Available error codes
type ErrorCode =
  | "M001"
  | "M002"
  | "M003"
  | "M004"
  | "M005"
  | "M006"
  | "M007"
  | "M008"
  | "M009"
  | "M010"
  | "M011"
  | "M012"
  | "M013";

// --- Error message type description
type ErrorText = Record<string, string>;

// --- The error messages of error codes
const errorMessages: ErrorText = {
  M001: "The component '{0}' is not registered",
  M002: "The '{0}' element has an invalid id: '{1}'",
  M003: "Invalid component identifier: '{0}'",
  M004: "Duplicated component identifier: '{0}'",
  M005: "The '{0}' element has an invalid property: '{1}'",
  M006: "Parsing property value of '{0}' failed: {1}",
  M007: "The name of a reusable component is invalid: '{0}'",
  M008: "The name of a reusable component must not be '{0}', as it is a reserved name",
  M009: "A reusable component cannot have the name of a registered component: '{0}'",
  M010: "Duplicated reusable component name: '{0}'",
  M011: "The '{0}' element has an invalid event: '{1}'",
  M012: "Parsing event value of '{0}' failed: {1}",
  M013: "Component validation failed: '{0}'",
};

```

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

```scss
@use "../../components-core/theming/themes" as t;

// --- This code snippet is required to collect the theme variables used in this module
$themeVars: ();
@function createThemeVar($componentVariable) {
  $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global;
  @return t.getThemeVar($themeVars, $componentVariable);
}

// Variables for Checkbox - default variant
$borderRadius-Checkbox--default: createThemeVar("Input:borderRadius-Checkbox--default");
$borderColor-Checkbox--default: createThemeVar("Input:borderColor-Checkbox--default");
$backgroundColor-Checkbox--default: createThemeVar("Input:backgroundColor-Checkbox--default");
$outlineWidth-Checkbox--default--focus: createThemeVar("Input:outlineWidth-Checkbox--default--focus");
$outlineColor-Checkbox--default--focus: createThemeVar("Input:outlineColor-Checkbox--default--focus");
$outlineStyle-Checkbox--default--focus: createThemeVar("Input:outlineStyle-Checkbox--default--focus");
$outlineOffset-Checkbox--default--focus: createThemeVar("Input:outlineOffset-Checkbox--default--focus");

// Variables for Checkbox - error variant
$borderRadius-Checkbox--error: createThemeVar("Input:borderRadius-Checkbox--error");
$borderColor-Checkbox--error: createThemeVar("Input:borderColor-Checkbox--error");
$backgroundColor-Checkbox--error: createThemeVar("Input:backgroundColor-Checkbox--error");
$outlineWidth-Checkbox--error--focus: createThemeVar("Input:outlineWidth-Checkbox--error--focus");
$outlineColor-Checkbox--error--focus: createThemeVar("Input:outlineColor-Checkbox--error--focus");
$outlineStyle-Checkbox--error--focus: createThemeVar("Input:outlineStyle-Checkbox--error--focus");
$outlineOffset-Checkbox--error--focus: createThemeVar("Input:outlineOffset-Checkbox--error--focus");

// Variables for Checkbox - warning variant
$borderRadius-Checkbox--warning: createThemeVar("Input:borderRadius-Checkbox--warning");
$borderColor-Checkbox--warning: createThemeVar("Input:borderColor-Checkbox--warning");
$backgroundColor-Checkbox--warning: createThemeVar("Input:backgroundColor-Checkbox--warning");
$outlineWidth-Checkbox--warning--focus: createThemeVar("Input:outlineWidth-Checkbox--warning--focus");
$outlineColor-Checkbox--warning--focus: createThemeVar("Input:outlineColor-Checkbox--warning--focus");
$outlineStyle-Checkbox--warning--focus: createThemeVar("Input:outlineStyle-Checkbox--warning--focus");
$outlineOffset-Checkbox--warning--focus: createThemeVar("Input:outlineOffset-Checkbox--warning--focus");

// Variables for Checkbox - success variant
$borderRadius-Checkbox--success: createThemeVar("Input:borderRadius-Checkbox--success");
$borderColor-Checkbox--success: createThemeVar("Input:borderColor-Checkbox--success");
$backgroundColor-Checkbox--success: createThemeVar("Input:backgroundColor-Checkbox--success");
$outlineWidth-Checkbox--success--focus: createThemeVar("Input:outlineWidth-Checkbox--success--focus");
$outlineColor-Checkbox--success--focus: createThemeVar("Input:outlineColor-Checkbox--success--focus");
$outlineStyle-Checkbox--success--focus: createThemeVar("Input:outlineStyle-Checkbox--success--focus");
$outlineOffset-Checkbox--success--focus: createThemeVar("Input:outlineOffset-Checkbox--success--focus");

// Variables for Checkbox - hover and disabled states
$borderColor-Checkbox--default--hover: createThemeVar("Input:borderColor-Checkbox--default--hover");
$backgroundColor-Checkbox--disabled: createThemeVar("Input:backgroundColor-Checkbox--disabled");
$borderColor-Checkbox--disabled: createThemeVar("Input:borderColor-Checkbox--disabled");

// Variables for Checkbox - checked states
$borderColor-checked-Checkbox: createThemeVar("Input:borderColor-checked-Checkbox");
$backgroundColor-checked-Checkbox: createThemeVar("Input:backgroundColor-checked-Checkbox");
$borderColor-checked-Checkbox--error: createThemeVar("Input:borderColor-checked-Checkbox--error");
$backgroundColor-checked-Checkbox--error: createThemeVar("Input:backgroundColor-checked-Checkbox--error");
$borderColor-checked-Checkbox--warning: createThemeVar("Input:borderColor-checked-Checkbox--warning");
$backgroundColor-checked-Checkbox--warning: createThemeVar("Input:backgroundColor-checked-Checkbox--warning");
$borderColor-checked-Checkbox--success: createThemeVar("Input:borderColor-checked-Checkbox--success");
$backgroundColor-checked-Checkbox--success: createThemeVar("Input:backgroundColor-checked-Checkbox--success");

// Variables for Checkbox indicator
$backgroundColor-indicator-Checkbox: createThemeVar("backgroundColor-indicator-Checkbox");

// Variables for Switch - hover and disabled states
$borderColor-Switch--default--hover: createThemeVar("Input:borderColor-Switch--default--hover");
$backgroundColor-Switch--disabled: createThemeVar("Input:backgroundColor-Switch--disabled");
$borderColor-Switch--disabled: createThemeVar("Input:borderColor-Switch--disabled");

// Variables for Switch - checked states
$borderColor-checked-Switch: createThemeVar("Input:borderColor-checked-Switch");
$backgroundColor-checked-Switch: createThemeVar("Input:backgroundColor-checked-Switch");
$borderColor-checked-Switch--error: createThemeVar("Input:borderColor-checked-Switch--error");
$backgroundColor-checked-Switch--error: createThemeVar("Input:backgroundColor-checked-Switch--error");
$borderColor-checked-Switch--warning: createThemeVar("Input:borderColor-checked-Switch--warning");
$backgroundColor-checked-Switch--warning: createThemeVar("Input:backgroundColor-checked-Switch--warning");
$borderColor-checked-Switch--success: createThemeVar("Input:borderColor-checked-Switch--success");
$backgroundColor-checked-Switch--success: createThemeVar("Input:backgroundColor-checked-Switch--success");

// Variables for Switch
$backgroundColor-Switch: createThemeVar("Input:backgroundColor-Switch");
$borderColor-Switch: createThemeVar("Input:borderColor-Switch");
$backgroundColor-indicator-Switch: createThemeVar("backgroundColor-indicator-Switch");
$backgroundColor-checked-Switch: createThemeVar("backgroundColor-checked-Switch");
$backgroundColor-indicator-checked-Switch: createThemeVar("backgroundColor-indicator-checked-Switch");
$backgroundColor-Switch-indicator--disabled: createThemeVar("backgroundColor-Switch-indicator--disabled");
$outlineWidth-Switch--focus: createThemeVar("Input:outlineWidth-Switch--focus");
$outlineColor-Switch--focus: createThemeVar("Input:outlineColor-Switch--focus");
$outlineStyle-Switch--focus: createThemeVar("Input:outlineStyle-Switch--focus");
$outlineOffset-Switch--focus: createThemeVar("Input:outlineOffset-Switch--focus");

// Variables for Switch - validation variants
$borderColor-Switch--error: createThemeVar("Input:borderColor-Switch--error");
$borderColor-Switch--warning: createThemeVar("Input:borderColor-Switch--warning");
$borderColor-Switch--success: createThemeVar("Input:borderColor-Switch--success");

// --- CSS properties of a particular Checkbox variant
@mixin checkboxVariant($variantName) {
  border-radius: createThemeVar("Input:borderRadius-Checkbox--#{$variantName}");
  border-color: createThemeVar("Input:borderColor-Checkbox--#{$variantName}");
  background-color: createThemeVar("Input:backgroundColor-Checkbox--#{$variantName}");

  &:focus-visible {
    outline-width: createThemeVar("Input:outlineWidth-Checkbox--#{$variantName}--focus");
    outline-color: createThemeVar("Input:outlineColor-Checkbox--#{$variantName}--focus");
    outline-style: createThemeVar("Input:outlineStyle-Checkbox--#{$variantName}--focus");
    outline-offset: createThemeVar("Input:outlineOffset-Checkbox--#{$variantName}--focus");
  }
}

@mixin hoverAndDisabledState($componentName) {
  &:not([readonly]):not(:disabled):hover {
    border-color: createThemeVar("Input:borderColor-#{$componentName}--default--hover");
  }

  &:disabled {
    cursor: not-allowed;
    background-color: createThemeVar("Input:backgroundColor-#{$componentName}--disabled");
    border-color: createThemeVar("Input:borderColor-#{$componentName}--disabled");
  }
}

@mixin checkedState($componentName) {
  &:checked {
    border-color: createThemeVar("Input:borderColor-checked-#{$componentName}");
    background-color: createThemeVar("Input:backgroundColor-checked-#{$componentName}");
  }

  &:checked:disabled {
    background-color: createThemeVar("Input:backgroundColor-#{$componentName}--disabled");
    border-color: createThemeVar("Input:borderColor-#{$componentName}--disabled");
  }

  &:checked.error {
    border-color: createThemeVar("Input:borderColor-checked-#{$componentName}--error");
    background-color: createThemeVar("Input:backgroundColor-checked-#{$componentName}--error");
  }

  &:checked.warning {
    border-color: createThemeVar("Input:borderColor-checked-#{$componentName}--warning");
    background-color: createThemeVar("Input:backgroundColor-checked-#{$componentName}--warning");
  }

  &:checked.valid {
    border-color: createThemeVar("Input:borderColor-checked-#{$componentName}--success");
    background-color: createThemeVar("Input:backgroundColor-checked-#{$componentName}--success");
  }
}

@layer components {
  .resetAppearance {
    /* Add if not using autoprefixer */
    -webkit-appearance: none;
    appearance: none;
    /* Not removed via appearance */
    margin: 0;
  }

  .label {
    width: 100%;
  }

  .inputContainer {
    z-index: -1;
    position: relative;
    opacity: 0;
    width: 0;
    height: 0;
  }

  // --------------- Checkbox ---------------

  .checkbox {
    display: grid;
    place-content: center;
    min-width: 1em;
    min-height: 1em;
    width: 1em;
    height: 1em;
    border: 2px solid transparent;

    &:not([readonly]) {
      cursor: pointer;
    }

    @include checkboxVariant("default");
    @include hoverAndDisabledState("Checkbox");

    .forceHover {
      border-color: $borderColor-Checkbox--default--hover;
      // Don't override background-color - let the existing background rules apply
    }

    &.error {
      @include checkboxVariant("error");
    }

    &.warning {
      @include checkboxVariant("warning");
    }

    &.valid {
      @include checkboxVariant("success");
    }

    &::before {
      content: "";
      width: 0.5em;
      height: 0.5em;
      transform: scale(0);
      transition: 0.1s transform ease-out;
      box-shadow: inset 1em 1em $backgroundColor-indicator-Checkbox;
      transform-origin: center;
      clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
    }

    &:checked::before {
      transform: scale(1);
    }

    @include checkedState("Checkbox");

    &:indeterminate {
      background-color: $backgroundColor-checked-Checkbox;
      border-color: $borderColor-checked-Checkbox;

      &[readonly] {
        pointer-events: none;
      }
    }
    &:indeterminate:disabled {
      background-color: $backgroundColor-Checkbox--disabled;
      border-color: $borderColor-Checkbox--disabled;
    }
    &:indeterminate::before {
      clip-path: circle(30% at 50% 50%);
      transform: scale(1);
    }
  }

  // --------------- Switch ---------------

  .switch {
    --thumb-size: 1rem;
    --thumb-position: 0%;
    --track-size: calc(var(--thumb-size) * 3);
    --padding-size: 4px;

    &:not([readonly]) {
      cursor: pointer;
    }
    flex-shrink: 0;
    display: grid;
    align-items: center;
    grid: [track] 1fr / [track] 1fr;
    background-color: $backgroundColor-Switch;

    width: var(--track-size);
    min-height: var(--thumb-size);

    padding: var(--padding-size);
    border: 1px solid $borderColor-Switch;
    border-radius: 1rem;

    &::before {
      content: "";
      grid-area: track;
      height: var(--thumb-size);
      width: var(--thumb-size);
      background: $backgroundColor-indicator-Switch;
      border-radius: 50%;

      transform: translateX(var(--thumb-position));
      transition: 0.3s transform;
    }

    &:checked {
      background: $backgroundColor-checked-Switch;

      &::before {
        background: $backgroundColor-indicator-checked-Switch;
        --thumb-position: calc(
          var(--track-size) - var(--thumb-size) - 2 * var(--padding-size) - 2px
        );
      }
    }

    @include hoverAndDisabledState("Switch");
    @include checkedState("Switch");

    .forceHover {
      border-color: $borderColor-Switch--default--hover;
      // Don't override background-color - let the existing background rules apply
    }

    &:focus-visible {
      outline-width: $outlineWidth-Switch--focus;
      outline-color: $outlineColor-Switch--focus;
      outline-style: $outlineStyle-Switch--focus;
      outline-offset: $outlineOffset-Switch--focus;
    }

    &:disabled {
      &::before {
        background-color: $backgroundColor-Switch-indicator--disabled;
      }
    }

    &.error {
      border-color: $borderColor-Switch--error;
    }

    &.warning {
      border-color: $borderColor-Switch--warning;
    }

    &.valid {
      border-color: $borderColor-Switch--success;
    }
  }
}

// --- We export the theme variables to add them to the component renderer
:export {
  themeVars: t.json-stringify($themeVars);
}

```

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

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

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

test("initializes with default props", async ({ initTestBed, page }) => {
  await initTestBed(`
    <Fragment>
      <AppState id="appState" />
      <Text testId="stateValue">|{JSON.stringify(appState.value)}|</Text>
    </Fragment>
  `);

  // AppState should initialize with default bucket and display the correct value
  await expect(page.getByTestId("stateValue")).toBeVisible();
  await expect(page.getByTestId("stateValue")).toHaveText("||");
});

test("initializes with initial state value", async ({ initTestBed, page }) => {
  await initTestBed(`
    <Fragment>
      <AppState id="appState" initialValue="{{ mode: true }}"/>
      <Text testId="stateValue">|{appState.value.mode}|</Text>
    </Fragment>
  `);

  // AppState should initialize with default bucket and display the correct value
  await expect(page.getByTestId("stateValue")).toBeVisible();
  await expect(page.getByTestId("stateValue")).toHaveText("|true|");
});

test("initializes with multiple initial state value", async ({ initTestBed, page }) => {
  await initTestBed(`
    <Fragment>
      <AppState id="appState" initialValue="{{ mode: true }}"/>
      <AppState id="appState2" initialValue="{{ otherMode: 123 }}"/>
      <Text testId="stateValue">|{appState.value.mode}|{appState2.value.otherMode}|</Text>
    </Fragment>
  `);

  // AppState should initialize with default bucket and display the correct value
  await expect(page.getByTestId("stateValue")).toBeVisible();
  await expect(page.getByTestId("stateValue")).toHaveText("|true|123|");
});

test("initializes with provided bucket name and no initial value", async ({
  initTestBed,
  page,
}) => {
  await initTestBed(`
    <Fragment>
      <AppState id="appState" bucket="settings" />
      <Text testId="stateValue">|{JSON.stringify(appState.value)}|</Text>
    </Fragment>
  `);

  // AppState should initialize with default bucket and display the correct value
  await expect(page.getByTestId("stateValue")).toBeVisible();
  await expect(page.getByTestId("stateValue")).toHaveText("||");
});

test("initializes with bucket name and initial state value", async ({ initTestBed, page }) => {
  await initTestBed(`
    <Fragment>
      <AppState id="appState" bucket="settings" initialValue="{{ mode: true }}"/>
      <Text testId="stateValue">|{appState.value.mode}|</Text>
    </Fragment>
  `);

  // AppState should initialize with default bucket and display the correct value
  await expect(page.getByTestId("stateValue")).toBeVisible();
  await expect(page.getByTestId("stateValue")).toHaveText("|true|");
});

test("initializes with bucket name and multiple initial state value", async ({
  initTestBed,
  page,
}) => {
  await initTestBed(`
    <Fragment>
      <AppState id="appState" bucket="settings" initialValue="{{ mode: true }}"/>
      <AppState id="appState2" bucket="settings" initialValue="{{ otherMode: 123 }}"/>
      <Text testId="stateValue">|{appState.value.mode}|{appState.value.otherMode}|</Text>
    </Fragment>
  `);

  // AppState should initialize with default bucket and display the correct value
  await expect(page.getByTestId("stateValue")).toBeVisible();
  await expect(page.getByTestId("stateValue")).toHaveText("|true|123|");
});

test("updates state using the update API", async ({ initTestBed, page }) => {
  await initTestBed(`
    <Fragment>
      <AppState id="appState" initialValue="{{ counter: 0 }}" />
      <Button testId="updateBtn" onClick="appState.update({ counter: appState.value.counter + 1 })">
        Increment
      </Button>
      <Text testId="stateValue">{JSON.stringify(appState.value)}</Text>
    </Fragment>
  `);

  // Check initial state
  await expect(page.getByTestId("stateValue")).toHaveText('{"counter":0}');

  // Update state by clicking button
  await page.getByTestId("updateBtn").click();

  // Check updated state
  await expect(page.getByTestId("stateValue")).toHaveText('{"counter":1}');
});

test("updates state using the update API (using backet name)", async ({ initTestBed, page }) => {
  await initTestBed(`
    <Fragment>
      <AppState id="appState" bucket="settings" initialValue="{{ counter: 0 }}" />
      <Button testId="updateBtn" onClick="appState.update({ counter: appState.value.counter + 1 })">
        Increment
      </Button>
      <Text testId="stateValue">{JSON.stringify(appState.value)}</Text>
    </Fragment>
  `);

  // Check initial state
  await expect(page.getByTestId("stateValue")).toHaveText('{"counter":0}');

  // Update state by clicking button
  await page.getByTestId("updateBtn").click();

  // Check updated state
  await expect(page.getByTestId("stateValue")).toHaveText('{"counter":1}');
});

// =============================================================================
// STATE SHARING TESTS
// =============================================================================

test("shares state between multiple instances with the default bucket", async ({
  initTestBed,
  page,
}) => {
  await initTestBed(`
    <Fragment>
      <AppState id="appState1" initialValue="{{ counter: 0 }}" />
      <AppState id="appState2" />
      <Button testId="updateBtn" onClick="appState1.update({ counter: appState1.value.counter + 1 })">
        Increment
      </Button>
      <Text testId="stateValue1">{JSON.stringify(appState1.value)}</Text>
      <Text testId="stateValue2">{JSON.stringify(appState2.value)}</Text>
    </Fragment>
  `);

  // Check initial state in both instances
  await expect(page.getByTestId("stateValue1")).toHaveText('{"counter":0}');
  await expect(page.getByTestId("stateValue2")).toHaveText('{"counter":0}');

  // Update state through first instance
  await page.getByTestId("updateBtn").click();

  // Both instances should reflect the change
  await expect(page.getByTestId("stateValue1")).toHaveText('{"counter":1}');
  await expect(page.getByTestId("stateValue2")).toHaveText('{"counter":1}');
});

test("shares state between multiple instances with a specific bucket", async ({
  initTestBed,
  page,
}) => {
  await initTestBed(`
    <Fragment>
      <AppState id="appState1" initialValue="{{ counter: 0 }}" bucket="bucket1" />
      <AppState id="appState2" bucket="bucket1" />
      <Button testId="updateBtn" onClick="appState1.update({ counter: appState1.value.counter + 1 })">
        Increment
      </Button>
      <Text testId="stateValue1">{JSON.stringify(appState1.value)}</Text>
      <Text testId="stateValue2">{JSON.stringify(appState2.value)}</Text>
    </Fragment>
  `);

  // Check initial state in both instances
  await expect(page.getByTestId("stateValue1")).toHaveText('{"counter":0}');
  await expect(page.getByTestId("stateValue2")).toHaveText('{"counter":0}');

  // Update state through first instance
  await page.getByTestId("updateBtn").click();

  // Both instances should reflect the change
  await expect(page.getByTestId("stateValue1")).toHaveText('{"counter":1}');
  await expect(page.getByTestId("stateValue2")).toHaveText('{"counter":1}');
});

test("maintains separate states for different buckets", async ({ initTestBed, page }) => {
  await initTestBed(`
    <Fragment>
      <AppState id="appState1" initialValue="{{ counter: 0 }}" bucket="bucket1" />
      <AppState id="appState2" initialValue="{{ counter: 0 }}" bucket="bucket2" />
      <Button testId="updateBtn" onClick="appState1.update({ counter: appState1.value.counter + 1 })">
        Increment
      </Button>
      <Text testId="stateValue1">{JSON.stringify(appState1.value)}</Text>
      <Text testId="stateValue2">{JSON.stringify(appState2.value)}</Text>
    </Fragment>
  `);

  // Check initial state in both instances
  await expect(page.getByTestId("stateValue1")).toHaveText('{"counter":0}');
  await expect(page.getByTestId("stateValue2")).toHaveText('{"counter":0}');

  // Update state through first instance
  await page.getByTestId("updateBtn").click();

  // Only the first instance should reflect the change
  await expect(page.getByTestId("stateValue1")).toHaveText('{"counter":1}');
  await expect(page.getByTestId("stateValue2")).toHaveText('{"counter":0}');
});

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

test("handles undefined initialValue gracefully", async ({ initTestBed, page }) => {
  await initTestBed(`
    <Fragment>
      <AppState ref="appState" initialValue="{undefined}" />
      <Text testId="stateValue">|{JSON.stringify(appState.value)}|</Text>
    </Fragment>
  `);

  // Should not throw error with undefined initialValue
  await expect(page.getByTestId("stateValue")).toBeVisible();
  await expect(page.getByTestId("stateValue")).toHaveText("||");
});

test("handles complex nested state updates correctly", async ({ initTestBed, page }) => {
  await initTestBed(`
    <Fragment>
      <AppState
        id="appState"
        initialValue="{{ user: { name: 'John', profile: { age: 30, roles: ['admin'] } } }}"
      />
      <Button testId="updateBtn" 
        onClick="appState.update({ 
          user: { ...appState.value.user, 
          profile: { ...appState.value.user.profile, age: 31 } } 
        })">
        Update Age
      </Button>
      <Text testId="stateValue">{JSON.stringify(appState.value)}</Text>
    </Fragment>
  `);

  // Check initial state
  await expect(page.getByTestId("stateValue")).toContainText('"age":30');

  // Update nested property
  await page.getByTestId("updateBtn").click();

  // Check updated nested property
  await expect(page.getByTestId("stateValue")).toContainText('"age":31');
  // Check other properties remain unchanged
  await expect(page.getByTestId("stateValue")).toContainText('"name":"John"');
  await expect(page.getByTestId("stateValue")).toContainText('"roles":["admin"]');
});

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

test("handles multiple rapid state updates efficiently", async ({ initTestBed, page }) => {
  await initTestBed(`
    <Fragment var.clickCount="{0}">
      <AppState id="appState" initialValue="{{ counter: 0 }}" />
      <Button 
        testId="updateBtn" 
        onClick="appState.update({ counter: appState.value.counter + 1 }); clickCount = clickCount + 1;">
        Increment
      </Button>
      <Text testId="stateValue">{JSON.stringify(appState.value)}</Text>
      <Text testId="clickCount">{clickCount}</Text>
    </Fragment>
  `);

  // Perform multiple rapid clicks
  for (let i = 0; i < 5; i++) {
    await page.getByTestId("updateBtn").click();
  }

  // Verify click count
  await expect(page.getByTestId("clickCount")).toHaveText("5");

  // Verify state was updated correctly
  await expect(page.getByTestId("stateValue")).toContainText('{"counter":5}');
});

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

test("integrates with other components that consume app state", async ({ initTestBed, page }) => {
  // TODO: review these Copilot-created tests
  await initTestBed(`
    <Fragment>
      <AppState id="appState" initialValue="{{ theme: 'light', fontSize: 14 }}" />
      <Fragment var.currentTheme="initial">
        <Button testId="themeBtn" onClick="currentTheme = appState.value.theme">
          Get Theme
        </Button>
        <Text testId="themeValue">{currentTheme}</Text>
      </Fragment>
    </Fragment>
  `);

  // Get the theme value by clicking button
  await page.getByTestId("themeBtn").click();

  // Check that the value was correctly retrieved from AppState
  await expect(page.getByTestId("themeValue")).toHaveText("light");
});

test("works correctly when wrapped in conditional rendering", async ({ initTestBed, page }) => {
  // TODO: review these Copilot-created tests
  await initTestBed(`
    <Fragment var.showState="{false}">
      <Fragment when="{showState}">
        <Text>AppState is visible</Text>
        <AppState id="appState" initialValue="{{ visible: true }}" />
      </Fragment>
      <Button testId="toggleBtn" onClick="showState = !showState">Toggle AppState</Button>
      <Text testId="visibilityStatus">{appState.value.visible ? 'Visible' : 'Hidden'}</Text>
    </Fragment>
  `);

  // Initially the AppState component should be rendered
  await expect(page.getByTestId("visibilityStatus")).toHaveText("Hidden");

  // Toggle the component's visibility
  await page.getByTestId("toggleBtn").click();
  await expect(page.getByTestId("visibilityStatus")).toHaveText("Visible");

  // Toggle it back: The AppState component is hidden, but the state is still remain
  // there. It should work this way.
  await page.getByTestId("toggleBtn").click();
  await expect(page.getByTestId("visibilityStatus")).toHaveText("Visible");
});

```

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

```typescript
import type { GenericToken } from "../../parsers/common/GenericToken";
import type { TokenType } from "../../parsers/scripting/TokenType";
import type { ScriptParserErrorMessage } from "../../abstractions/scripting/ScriptParserError";

// --- All binding expression tree node types
type ScriptNode = Statement | Expression;

type ScriptingToken = GenericToken<TokenType>;

// The root type of all source tree nodes
export interface ScripNodeBase {
  // Node type discriminator
  type: ScriptNode["type"];

  // The unique id of the node
  nodeId: number;

  // The start token of the node
  startToken?: ScriptingToken;

  // The end token of the node
  endToken?: ScriptingToken;
}

// Import the actual implementation constants from outside the abstractions folder
import * as NodeTypes from "../../parsers/scripting/ScriptingNodeTypes";

// Re-export the constants so they can be used both as types and values
export const {
  // Statement node type values
  T_BLOCK_STATEMENT,
  T_EMPTY_STATEMENT,
  T_EXPRESSION_STATEMENT,
  T_ARROW_EXPRESSION_STATEMENT,
  T_LET_STATEMENT,
  T_CONST_STATEMENT,
  T_VAR_STATEMENT,
  T_IF_STATEMENT,
  T_RETURN_STATEMENT,
  T_BREAK_STATEMENT,
  T_CONTINUE_STATEMENT,
  T_WHILE_STATEMENT,
  T_DO_WHILE_STATEMENT,
  T_FOR_STATEMENT,
  T_FOR_IN_STATEMENT,
  T_FOR_OF_STATEMENT,
  T_THROW_STATEMENT,
  T_TRY_STATEMENT,
  T_SWITCH_STATEMENT,
  T_FUNCTION_DECLARATION,
  
  // Expression node type values
  T_UNARY_EXPRESSION,
  T_BINARY_EXPRESSION,
  T_SEQUENCE_EXPRESSION,
  T_CONDITIONAL_EXPRESSION,
  T_FUNCTION_INVOCATION_EXPRESSION,
  T_MEMBER_ACCESS_EXPRESSION,
  T_CALCULATED_MEMBER_ACCESS_EXPRESSION,
  T_IDENTIFIER,
  T_TEMPLATE_LITERAL_EXPRESSION,
  T_LITERAL,
  T_ARRAY_LITERAL,
  T_OBJECT_LITERAL,
  T_SPREAD_EXPRESSION,
  T_ASSIGNMENT_EXPRESSION,
  T_NO_ARG_EXPRESSION,
  T_ARROW_EXPRESSION,
  T_PREFIX_OP_EXPRESSION,
  T_POSTFIX_OP_EXPRESSION,
  T_REACTIVE_VAR_DECLARATION,
  
  // Other node type values
  T_VAR_DECLARATION,
  T_DESTRUCTURE,
  T_ARRAY_DESTRUCTURE,
  T_OBJECT_DESTRUCTURE,
  T_SWITCH_CASE
} = NodeTypes;

// --- Statement node types
type BLOCK_STATEMENT = typeof T_BLOCK_STATEMENT;
type EMPTY_STATEMENT = typeof T_EMPTY_STATEMENT;
type EXPRESSION_STATEMENT = typeof T_EXPRESSION_STATEMENT;
type ARROW_EXPRESSION_STATEMENT = typeof T_ARROW_EXPRESSION_STATEMENT;
type LET_STATEMENT = typeof T_LET_STATEMENT;
type CONST_STATEMENT = typeof T_CONST_STATEMENT;
type VAR_STATEMENT = typeof T_VAR_STATEMENT;
type IF_STATEMENT = typeof T_IF_STATEMENT;
type RETURN_STATEMENT = typeof T_RETURN_STATEMENT;
type BREAK_STATEMENT = typeof T_BREAK_STATEMENT;
type CONTINUE_STATEMENT = typeof T_CONTINUE_STATEMENT;
type WHILE_STATEMENT = typeof T_WHILE_STATEMENT;
type DO_WHILE_STATEMENT = typeof T_DO_WHILE_STATEMENT;
type FOR_STATEMENT = typeof T_FOR_STATEMENT;
type FOR_IN_STATEMENT = typeof T_FOR_IN_STATEMENT;
type FOR_OF_STATEMENT = typeof T_FOR_OF_STATEMENT;
type THROW_STATEMENT = typeof T_THROW_STATEMENT;
type TRY_STATEMENT = typeof T_TRY_STATEMENT;
type SWITCH_STATEMENT = typeof T_SWITCH_STATEMENT;
type FUNCTION_DECLARATION = typeof T_FUNCTION_DECLARATION;

// --- Expression node types
type UNARY_EXPRESSION = typeof T_UNARY_EXPRESSION;
type BINARY_EXPRESSION = typeof T_BINARY_EXPRESSION;
type SEQUENCE_EXPRESSION = typeof T_SEQUENCE_EXPRESSION;
type CONDITIONAL_EXPRESSION = typeof T_CONDITIONAL_EXPRESSION;
type FUNCTION_INVOCATION_EXPRESSION = typeof T_FUNCTION_INVOCATION_EXPRESSION;
type MEMBER_ACCESS_EXPRESSION = typeof T_MEMBER_ACCESS_EXPRESSION;
type CALCULATED_MEMBER_ACCESS_EXPRESSION = typeof T_CALCULATED_MEMBER_ACCESS_EXPRESSION;
type IDENTIFIER = typeof T_IDENTIFIER;
type TEMPLATE_LITERAL_EXPRESSION = typeof T_TEMPLATE_LITERAL_EXPRESSION;
type LITERAL = typeof T_LITERAL;
type ARRAY_LITERAL = typeof T_ARRAY_LITERAL;
type OBJECT_LITERAL = typeof T_OBJECT_LITERAL;
type SPREAD_EXPRESSION = typeof T_SPREAD_EXPRESSION;
type ASSIGNMENT_EXPRESSION = typeof T_ASSIGNMENT_EXPRESSION;
type NO_ARG_EXPRESSION = typeof T_NO_ARG_EXPRESSION;
type ARROW_EXPRESSION = typeof T_ARROW_EXPRESSION;
type PREFIX_OP_EXPRESSION = typeof T_PREFIX_OP_EXPRESSION;
type POSTFIX_OP_EXPRESSION = typeof T_POSTFIX_OP_EXPRESSION;
type REACTIVE_VAR_DECLARATION = typeof T_REACTIVE_VAR_DECLARATION;

// --- Other node types
type VAR_DECLARATION = typeof T_VAR_DECLARATION;
type DESTRUCTURE = typeof T_DESTRUCTURE;
type ARRAY_DESTRUCTURE = typeof T_ARRAY_DESTRUCTURE;
type OBJECT_DESTRUCTURE = typeof T_OBJECT_DESTRUCTURE;
type SWITCH_CASE = typeof T_SWITCH_CASE;

// =====================================================================================================================
// Statements

export type Statement =
  | BlockStatement
  | EmptyStatement
  | ExpressionStatement
  | ArrowExpressionStatement
  | LetStatement
  | ConstStatement
  | VarStatement
  | IfStatement
  | ReturnStatement
  | BreakStatement
  | ContinueStatement
  | WhileStatement
  | DoWhileStatement
  | ForStatement
  | ForInStatement
  | ForOfStatement
  | ThrowStatement
  | TryStatement
  | SwitchStatement
  | FunctionDeclaration;

export type LoopStatement = WhileStatement | DoWhileStatement;

export interface EmptyStatement extends ScripNodeBase {
  type: EMPTY_STATEMENT;
}

export interface ExpressionStatement extends ScripNodeBase {
  type: EXPRESSION_STATEMENT;
  expr: Expression;
}

export interface ArrowExpressionStatement extends ScripNodeBase {
  type: ARROW_EXPRESSION_STATEMENT;
  expr: ArrowExpression;
}

export interface VarDeclaration extends ExpressionBase {
  type: VAR_DECLARATION;
  id?: string;
  aDestr?: ArrayDestructure[];
  oDestr?: ObjectDestructure[];
  expr?: Expression;
}

export interface DestructureBase extends ExpressionBase {
  id?: string;
  aDestr?: ArrayDestructure[];
  oDestr?: ObjectDestructure[];
}

export interface Destructure extends DestructureBase {
  type: DESTRUCTURE;
  aDestr?: ArrayDestructure[];
  oDestr?: ObjectDestructure[];
}

export interface ArrayDestructure extends DestructureBase {
  type: ARRAY_DESTRUCTURE;
}

export interface ObjectDestructure extends DestructureBase {
  type: OBJECT_DESTRUCTURE;
  id: string;
  alias?: string;
}

export interface LetStatement extends ScripNodeBase {
  type: LET_STATEMENT;
  decls: VarDeclaration[];
}

export interface ConstStatement extends ScripNodeBase {
  type: CONST_STATEMENT;
  decls: VarDeclaration[];
}

export interface VarStatement extends ScripNodeBase {
  type: VAR_STATEMENT;
  decls: ReactiveVarDeclaration[];
}

export interface ReactiveVarDeclaration extends ExpressionBase {
  type: REACTIVE_VAR_DECLARATION;
  id: Identifier;
  expr: Expression;
}

export interface BlockStatement extends ScripNodeBase {
  type: BLOCK_STATEMENT;
  stmts: Statement[];
}

export interface IfStatement extends ScripNodeBase {
  type: IF_STATEMENT;
  cond: Expression;
  thenB: Statement;
  elseB?: Statement;
}

export interface ReturnStatement extends ScripNodeBase {
  type: RETURN_STATEMENT;
  expr?: Expression;
}

export interface WhileStatement extends ScripNodeBase {
  type: WHILE_STATEMENT;
  cond: Expression;
  body: Statement;
}

export interface DoWhileStatement extends ScripNodeBase {
  type: DO_WHILE_STATEMENT;
  cond: Expression;
  body: Statement;
}

export interface BreakStatement extends ScripNodeBase {
  type: BREAK_STATEMENT;
}

export interface ContinueStatement extends ScripNodeBase {
  type: CONTINUE_STATEMENT;
}

export interface ThrowStatement extends ScripNodeBase {
  type: THROW_STATEMENT;
  expr: Expression;
}

export interface TryStatement extends ScripNodeBase {
  type: TRY_STATEMENT;
  tryB: BlockStatement;
  catchB?: BlockStatement;
  catchV?: Identifier;
  finallyB?: BlockStatement;
}

export interface ForStatement extends ScripNodeBase {
  type: FOR_STATEMENT;
  init?: ExpressionStatement | LetStatement;
  cond?: Expression;
  upd?: Expression;
  body: Statement;
}

export type ForVarBinding = "let" | "const" | "none";
export interface ForInStatement extends ScripNodeBase {
  type: FOR_IN_STATEMENT;
  varB: ForVarBinding;
  id: Identifier;
  expr: Expression;
  body: Statement;
}

export interface ForOfStatement extends ScripNodeBase {
  type: FOR_OF_STATEMENT;
  varB: ForVarBinding;
  id: Identifier;
  expr: Expression;
  body: Statement;
}

export interface SwitchStatement extends ScripNodeBase {
  type: SWITCH_STATEMENT;
  expr: Expression;
  cases: SwitchCase[];
}

export interface SwitchCase extends ExpressionBase {
  type: SWITCH_CASE;
  caseE?: Expression;
  stmts?: Statement[];
}

export interface FunctionDeclaration extends ScripNodeBase {
  type: FUNCTION_DECLARATION;
  id: Identifier;
  args: Expression[];
  stmt: BlockStatement;
}

// =====================================================================================================================
// Expressions

// All syntax nodes that represent an expression
export type Expression =
  | UnaryExpression
  | BinaryExpression
  | SequenceExpression
  | ConditionalExpression
  | FunctionInvocationExpression
  | MemberAccessExpression
  | CalculatedMemberAccessExpression
  | Identifier
  | TemplateLiteralExpression
  | Literal
  | ArrayLiteral
  | ObjectLiteral
  | SpreadExpression
  | AssignmentExpression
  | NoArgExpression
  | ArrowExpression
  | PrefixOpExpression
  | PostfixOpExpression
  | ReactiveVarDeclaration
  | VarDeclaration
  | Destructure
  | ObjectDestructure
  | ArrayDestructure
  | SwitchCase;

// Common base node for all expression syntax nodes
export interface ExpressionBase extends ScripNodeBase {
  // Is this expression parenthesized?
  parenthesized?: number;
}

export type UnaryOpSymbols = "+" | "-" | "~" | "!" | "typeof" | "delete";

export type BinaryOpSymbols =
  | "**"
  | "*"
  | "/"
  | "%"
  | "+"
  | "-"
  | "<<"
  | ">>"
  | ">>>"
  | "<"
  | "<="
  | ">"
  | ">="
  | "=="
  | "==="
  | "!="
  | "!=="
  | "&"
  | "|"
  | "^"
  | "&&"
  | "||"
  | "??"
  | "in";

export type AssignmentSymbols =
  | "="
  | "+="
  | "-="
  | "**="
  | "*="
  | "/="
  | "%="
  | "<<="
  | ">>="
  | ">>>="
  | "&="
  | "^="
  | "|="
  | "&&="
  | "||="
  | "??=";

export type PrefixOpSymbol = "++" | "--";

export interface UnaryExpression extends ExpressionBase {
  type: UNARY_EXPRESSION;
  op: UnaryOpSymbols;
  expr: Expression;
}

export interface BinaryExpression extends ExpressionBase {
  type: BINARY_EXPRESSION;
  op: BinaryOpSymbols;
  left: Expression;
  right: Expression;
}

export interface SequenceExpression extends ExpressionBase {
  type: SEQUENCE_EXPRESSION;
  exprs: Expression[];
  loose?: boolean;
}

export interface ConditionalExpression extends ExpressionBase {
  type: CONDITIONAL_EXPRESSION;
  cond: Expression;
  thenE: Expression;
  elseE: Expression;
}

export interface FunctionInvocationExpression extends ExpressionBase {
  type: FUNCTION_INVOCATION_EXPRESSION;
  obj: Expression;
  arguments: Expression[];
}

export interface MemberAccessExpression extends ExpressionBase {
  type: MEMBER_ACCESS_EXPRESSION;
  obj: Expression;
  member: string;
  opt?: boolean;
}

export interface CalculatedMemberAccessExpression extends ExpressionBase {
  type: CALCULATED_MEMBER_ACCESS_EXPRESSION;
  obj: Expression;
  member: Expression;
}

export interface Identifier extends ExpressionBase {
  type: IDENTIFIER;
  name: string;
  isGlobal?: boolean;
}

export interface Literal extends ExpressionBase {
  type: LITERAL;
  value: any;
}

export interface TemplateLiteralExpression extends ExpressionBase {
  type: TEMPLATE_LITERAL_EXPRESSION;
  segments: (Literal | Expression)[];
}

export interface ArrayLiteral extends ExpressionBase {
  type: ARRAY_LITERAL;
  items: Expression[];
  loose?: boolean;
}

export interface ObjectLiteral extends ExpressionBase {
  type: OBJECT_LITERAL;
  props: (SpreadExpression | [Expression, Expression])[];
}

export interface SpreadExpression extends ExpressionBase {
  type: SPREAD_EXPRESSION;
  expr: Expression;
}

export interface AssignmentExpression extends ExpressionBase {
  type: ASSIGNMENT_EXPRESSION;
  leftValue: Expression;
  op: AssignmentSymbols;
  expr: Expression;
}

export interface NoArgExpression extends ExpressionBase {
  type: NO_ARG_EXPRESSION;
}

export interface ArrowExpression extends ExpressionBase {
  type: ARROW_EXPRESSION;
  name?: string;
  args: Expression[];
  statement: Statement;
}

export interface PrefixOpExpression extends ExpressionBase {
  type: PREFIX_OP_EXPRESSION;
  op: PrefixOpSymbol;
  expr: Expression;
}

export interface PostfixOpExpression extends ExpressionBase {
  type: POSTFIX_OP_EXPRESSION;
  op: PrefixOpSymbol;
  expr: Expression;
}

/**
 * Represents a parsed and resolved module
 */
export type ScriptModule = {
  type: "ScriptModule";
  name: string;
  parent?: ScriptModule | null;
  functions: Record<string, FunctionDeclaration>;
  statements: Statement[];
  sources: Map<Statement, string>;
};

/**
 * Represents a module error
 */
export type ModuleErrors = Record<string, ScriptParserErrorMessage[]>;

export type CollectedDeclarations = {
  vars: Record<string, CodeDeclaration>;
  functions: Record<string, CodeDeclaration>;
  moduleErrors?: ModuleErrors;
};

export type CodeDeclaration = {
  source?: string;
  tree: Expression;
  [x: string]: unknown;
};

```

--------------------------------------------------------------------------------
/xmlui/src/components/NestedApp/NestedAppNative.tsx:
--------------------------------------------------------------------------------

```typescript
import type { CSSProperties, ReactNode } from "react";
import { startTransition, useCallback, useEffect, useMemo, useRef, useState } from "react";
import type { Root } from "react-dom/client";
import ReactDOM from "react-dom/client";

import { AppRoot } from "../../components-core/rendering/AppRoot";
import type { ThemeTone } from "../../abstractions/ThemingDefs";
import { errReportComponent, xmlUiMarkupToComponent } from "../../components-core/xmlui-parser";
import { ApiInterceptorProvider } from "../../components-core/interception/ApiInterceptorProvider";
import { ErrorBoundary } from "../../components-core/rendering/ErrorBoundary";
import type { CompoundComponentDef } from "../../abstractions/ComponentDefs";
import { useTheme } from "../../components-core/theming/ThemeContext";
import { useComponentRegistry } from "../ComponentRegistryContext";
import { useIndexerContext } from "../App/IndexerContext";
import { useApiInterceptorContext } from "../../components-core/interception/useApiInterceptorContext";
import { EMPTY_ARRAY } from "../../components-core/constants";
import { useIsomorphicLayoutEffect } from "../../components-core/utils/hooks";
import styles from "./NestedApp.module.scss";
import classnames from "classnames";
import {
  StyleInjectionTargetContext,
  StyleProvider,
  useStyles,
} from "../../components-core/theming/StyleContext";

type NestedAppProps = {
  api?: any;
  app: string;
  components?: any[];
  config?: any;
  activeTone?: ThemeTone;
  activeTheme?: string;
  height?: string | number;
  style?: CSSProperties;
  refreshVersion?: number;
  withSplashScreen?: boolean;
  className?: string;
};

function AnimatedLogo() {
  return (
    <div className={styles.loadingContainer}>
      <div className={styles.loadingText}>Loading XMLUI App...</div>
      <div className={styles.logoWrapper}>
        <svg viewBox="0 0 26 26" xmlns="http://www.w3.org/2000/svg">
          {/* Unchanged inner paths */}
          <path
            d="M9.04674 19.3954C8.2739 19.3954 7.60226 19.2265 7.03199 18.8887C6.47443 18.5384 6.0435 18.0505 5.73938 17.425C5.43526 16.7869 5.2832 16.0362 5.2832 15.173V9.89961C5.2832 9.7745 5.32771 9.66815 5.41637 9.58059C5.50502 9.493 5.61275 9.44922 5.73938 9.44922H7.41222C7.55157 9.44922 7.6593 9.493 7.73524 9.58059C7.8239 9.66815 7.86841 9.7745 7.86841 9.89961V15.0604C7.86841 16.6117 8.55895 17.3874 9.94021 17.3874C10.5991 17.3874 11.1187 17.181 11.4988 16.7681C11.8917 16.3553 12.0881 15.786 12.0881 15.0604V9.89961C12.0881 9.7745 12.1325 9.66815 12.2211 9.58059C12.3098 9.493 12.4175 9.44922 12.5443 9.44922H14.217C14.3436 9.44922 14.4513 9.493 14.54 9.58059C14.6288 9.66815 14.6732 9.7745 14.6732 9.89961V18.7574C14.6732 18.8825 14.6288 18.9888 14.54 19.0764C14.4513 19.164 14.3436 19.2078 14.217 19.2078H12.6773C12.538 19.2078 12.4239 19.164 12.3352 19.0764C12.2591 18.9888 12.2211 18.8825 12.2211 18.7574V17.988C11.879 18.4258 11.4545 18.7699 10.9476 19.0201C10.4407 19.2703 9.80704 19.3954 9.04674 19.3954Z"
            fill="#3367CC"
          />
          <path
            d="M17.6397 19.2104C17.5129 19.2104 17.4052 19.1666 17.3165 19.079C17.2279 18.9914 17.1835 18.8851 17.1835 18.76V9.90221C17.1835 9.7771 17.2279 9.67075 17.3165 9.58319C17.4052 9.4956 17.5129 9.45182 17.6397 9.45182H19.2174C19.3567 9.45182 19.4644 9.4956 19.5404 9.58319C19.6292 9.67075 19.6736 9.7771 19.6736 9.90221V18.76C19.6736 18.8851 19.6292 18.9914 19.5404 19.079C19.4644 19.1666 19.3567 19.2104 19.2174 19.2104H17.6397ZM17.5636 7.8379C17.4243 7.8379 17.3102 7.80038 17.2215 7.72531C17.1454 7.63773 17.1074 7.52514 17.1074 7.38751V6.03633C17.1074 5.91122 17.1454 5.80487 17.2215 5.71731C17.3102 5.62972 17.4243 5.58594 17.5636 5.58594H19.2933C19.4327 5.58594 19.5467 5.62972 19.6354 5.71731C19.7242 5.80487 19.7686 5.91122 19.7686 6.03633V7.38751C19.7686 7.52514 19.7242 7.63773 19.6354 7.72531C19.5467 7.80038 19.4327 7.8379 19.2933 7.8379H17.5636Z"
            fill="#3367CC"
          />

          {/* ✨ MODIFIED outer path for animation */}
          <path
            className={styles.animatedLogoPath}
            d="M23.0215 2.81748H2.53486V23.044H23.0215V2.81748Z"
            fill="none"
            stroke="#3367CC"
            strokeWidth="0.75"
          />
        </svg>
      </div>
    </div>
  );
}

export function LazyNestedApp({
  immediate,
  ...restProps
}: NestedAppProps & { immediate?: boolean }) {
  const [shouldRender, setShouldRender] = useState(immediate || false);
  useEffect(() => {
    if (!immediate) {
      startTransition(() => {
        setShouldRender(true);
      });
    }
  }, [immediate]);
  if (!shouldRender) {
    return null;
  }
  return <NestedApp {...restProps} />;
}

export function IndexAwareNestedApp(props: NestedAppProps & { immediate?: boolean }) {
  const { indexing } = useIndexerContext();
  if (indexing) {
    return null;
  }

  return <LazyNestedApp {...props} />;
}

export function NestedApp({
  api,
  app,
  components = EMPTY_ARRAY,
  config,
  activeTheme,
  activeTone,
  height,
  style,
  refreshVersion,
  withSplashScreen = false,
  className,
}: NestedAppProps) {
  const rootRef = useRef<HTMLDivElement>(null);
  const shadowRef = useRef(null);
  const contentRootRef = useRef<Root | null>(null);
  const theme = useTheme();
  const toneToApply = activeTone || config?.defaultTone || theme?.activeThemeTone;
  const componentRegistry = useComponentRegistry();
  const parentInterceptorContext = useApiInterceptorContext();
  const [initialized, setInitialized] = useState(!withSplashScreen);
  const [revealAnimationFinished, setRevealAnimationFinished] = useState(false);

  //TODO illesg: we should come up with something to make sure that nestedApps don't overwrite each other's mocked api endpoints
  //   disabled for now, as it messes up the paths of not mocked APIs (e.g. resources/{staticJsonfiles})
  //const safeId = playgroundId || nestedAppId;
  //const apiUrl = api ? `/${safeId.replaceAll(":", "")}` : '';
  const apiUrl = "";

  const mock = useMemo(() => {
    if (!api) {
      return undefined;
    }
    let apiObject = api;
    if (typeof api === "string") {
      try {
        apiObject = JSON.parse(api.replaceAll("\n", " "));
      } catch (e) {
        console.error("Failed to parse API definition", e);
        return undefined;
      }
    }
    return {
      ...apiObject,
      type: "in-memory",
      // apiUrl: apiUrl + (apiObject.apiUrl || ""),
    };
  }, [api]);

  useIsomorphicLayoutEffect(() => {
    if (!shadowRef.current && rootRef.current) {
      // Clone existing style and link tags
      shadowRef.current = rootRef.current.attachShadow({ mode: "open" });
      let style = document.createElement("style");

      // since we are using shadow DOM, we need to define the layers here
      // to ensure that the styles are applied correctly (the adopted styleheets setting is asynchronous, so the layer order might not be respected if we don't do this)
      // MUST BE IN SYNC WITH THE STYLESHEET ORDER IN index.scss
      style.innerHTML = "@layer reset, base, components, dynamic;";
      shadowRef.current.appendChild(style);

      // This should run once to prepare the stylesheets
      const sheetPromises = Array.from(document.styleSheets).map(async (sheet) => {
        // Check if the owner element has the attribute you want to skip
        if (
          sheet.ownerNode &&
          sheet.ownerNode instanceof Element &&
          sheet.ownerNode.hasAttribute("data-style-hash")
        ) {
          return null; // Skip this stylesheet
        }
        // Can't access cross-origin sheets, so skip them
        if (!sheet.href || sheet.href.startsWith(window.location.origin)) {
          try {
            // Create a new CSSStyleSheet object
            const newSheet = new CSSStyleSheet();
            // Get the CSS rules as text
            const cssText = Array.from(sheet.cssRules)
              .map((rule) => rule.cssText)
              .join(" \n");
            // Apply the text to the new sheet object
            await newSheet.replace(cssText);
            return newSheet;
          } catch (e) {
            // console.error('Could not process stylesheet:', sheet.href, e);
            return null;
          }
        }
        return null;
      });

      // When your component mounts and the shadow root is available...
      void Promise.all(sheetPromises).then((sheets) => {
        // Filter out any sheets that failed to load
        const validSheets = sheets.filter(Boolean);

        // Apply the array of constructed stylesheets to the shadow root
        // This is synchronous and does not trigger new network requests
        shadowRef.current.adoptedStyleSheets = validSheets;
      });
    }
    if (!contentRootRef.current && shadowRef.current) {
      contentRootRef.current = ReactDOM.createRoot(shadowRef.current);
    }
  }, []);

  const onInit = useCallback(() => {
    setInitialized(true);
  }, []);

  useEffect(() => {
    let { errors, component, erroneousCompoundComponentName } = xmlUiMarkupToComponent(app);
    if (errors.length > 0) {
      component = errReportComponent(errors, "Main.xmlui", erroneousCompoundComponentName);
    }
    const compoundComponents: CompoundComponentDef[] = (components ?? []).map((src) => {
      const isErrorReportComponent = typeof src !== "string";
      if (isErrorReportComponent) {
        return src;
      }
      let { errors, component, erroneousCompoundComponentName } = xmlUiMarkupToComponent(
        src as string,
      );
      if (errors.length > 0) {
        return errReportComponent(errors, `nested xmlui`, erroneousCompoundComponentName);
      }
      return component;
    });

    let globalProps = {
      name: config?.name,
      ...(config?.appGlobals || {}),
      apiUrl,
    };

    contentRootRef.current?.render(
      <ErrorBoundary node={component}>
        <StyleInjectionTargetContext.Provider value={shadowRef.current}>
          <StyleProvider forceNew={true}>
            <ApiInterceptorProvider
              parentInterceptorContext={parentInterceptorContext}
              key={`app-${refreshVersion}`}
              interceptor={mock}
              waitForApiInterceptor={true}
            >
              <NestedAppRoot themeStylesToReset={theme.themeStyles}>
                <AppRoot
                  onInit={onInit}
                  isNested={true}
                  previewMode={true}
                  standalone={true}
                  trackContainerHeight={height ? "fixed" : "auto"}
                  node={component}
                  globalProps={globalProps}
                  defaultTheme={activeTheme || config?.defaultTheme}
                  defaultTone={toneToApply as ThemeTone}
                  contributes={{
                    compoundComponents,
                    themes: config?.themes,
                  }}
                  resources={config?.resources}
                  extensionManager={componentRegistry.getExtensionManager()}
                />
              </NestedAppRoot>
            </ApiInterceptorProvider>
          </StyleProvider>
        </StyleInjectionTargetContext.Provider>
      </ErrorBoundary>,
    );
  }, [
    onInit,
    activeTheme,
    app,
    componentRegistry,
    components,
    config?.appGlobals,
    config?.defaultTheme,
    config?.name,
    config?.resources,
    config?.themes,
    height,
    mock,
    parentInterceptorContext,
    style,
    theme.themeStyles,
    toneToApply,
    refreshVersion,
  ]);

  const mountedRef = useRef(false);
  useEffect(() => {
    mountedRef.current = true;
    return () => {
      mountedRef.current = false;
      setTimeout(() => {
        // Unmount the content root after a delay (and only if the component is not mounted anymore, could happen in dev mode - double useEffect call)
        if (!mountedRef.current) {
          contentRootRef.current?.unmount();
          contentRootRef.current = null;
        }
      }, 0);
    };
  }, []);

  const animationFinished = useCallback(() => {
    setRevealAnimationFinished(true);
  }, []);

  const shouldAnimate = withSplashScreen && !revealAnimationFinished;
  return (
    <div className={classnames(styles.nestedAppPlaceholder, className)}>
      {shouldAnimate && <AnimatedLogo />}
      <div
        ref={rootRef}
        onTransitionEnd={animationFinished}
        className={classnames(styles.nestedAppRoot, {
          [styles.shouldAnimate]: shouldAnimate,
          [styles.initialized]: initialized,
        })}
      />
    </div>
  );
}

function NestedAppRoot({
  children,
  themeStylesToReset,
}: {
  children: ReactNode;
  themeStylesToReset?: Record<string, string>;
}) {
  // css variables are leaking into to shadow dom, so we reset them here
  const themeVarReset = useMemo(() => {
    const vars = {};
    Object.keys(themeStylesToReset).forEach((key) => {
      vars[key] = "initial";
    });
    return vars;
  }, [themeStylesToReset]);

  const resetClassName = useStyles(themeVarReset, { prepend: true });

  return (
    <div className={classnames(resetClassName, styles.shadowRoot)} id={"nested-app-root"}>
      <div className={styles.content}>{children}</div>
    </div>
  );
}

```
Page 46/145FirstPrevNextLast