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

# Files

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

```typescript
  1 | import { test, expect } from "../../testing/fixtures";
  2 | import { overflows, getBounds } from "../../testing/component-test-helpers";
  3 | 
  4 | const PAGE_WIDTH = 1280;
  5 | const PAGE_HEIGHT = 720;
  6 | test.use({ viewport: { width: PAGE_WIDTH, height: PAGE_HEIGHT } });
  7 | 
  8 | // =============================================================================
  9 | // BASIC FUNCTIONALITY TESTS
 10 | // =============================================================================
 11 | 
 12 | test.describe("Basic Functionality", () => {
 13 |   test("can render empty", async ({ page, initTestBed }) => {
 14 |     await initTestBed(`<Stack testId="stack"></Stack>`);
 15 |     await expect(page.getByTestId("stack")).toBeAttached();
 16 |     await expect(page.getByTestId("stack")).toBeEmpty();
 17 |   });
 18 | });
 19 | 
 20 | // =============================================================================
 21 | // LAYOUT TESTS
 22 | // =============================================================================
 23 | 
 24 | test.describe("Layout", () => {
 25 |   // "(horizontal) children with unspecified dimensions" -> width is content size, height is content size
 26 |   test("(horizontal) children with unspecified dimensions", async ({ page, initTestBed }) => {
 27 |     await initTestBed(`
 28 |       <Stack testId="stack" orientation="horizontal" backgroundColor="lightgray" gap="0">
 29 |         <Text testId="item_0" backgroundColor="cyan">Text #1</Text>
 30 |         <Text testId="item_1" backgroundColor="yellow">Text #2</Text>
 31 |         <Text testId="item_2" backgroundColor="lightgreen">Text #3</Text>
 32 |       </Stack>
 33 |     `);
 34 | 
 35 |     const { width: stackWidth, height: stackHeight } = await getBounds(page.getByTestId("stack"));
 36 |     const { width: itemWidth0, height: itemHeight0 } = await getBounds(page.getByTestId("item_0"));
 37 |     const { width: itemWidth1 } = await getBounds(page.getByTestId("item_1"));
 38 |     const { width: itemWidth2, right: itemRight2 } = await getBounds(page.getByTestId("item_2"));
 39 |     const itemWidthSum = itemWidth0 + itemWidth1 + itemWidth2;
 40 | 
 41 |     // ensure the elements are not overflowing and that the stack is not as wide as the width-sum of the elements
 42 |     // this can be stated, since we set the viewport size at the start,
 43 |     // which is bigger than the width-sum of the elements
 44 |     expect(itemWidthSum).toBeLessThan(stackWidth);
 45 | 
 46 |     //no gaps between elements
 47 |     // with tolerance, since we are comparing floating point number. The pixel values could be non-whole numbers
 48 |     // in which case adding up fractions could have a very small difference that would make the test fail
 49 |     expect(itemWidthSum).toEqualWithTolerance(itemRight2);
 50 | 
 51 |     // enusre that the stack is as tall as the tallest element (they all have the same height in this case)
 52 |     expect(stackHeight).toEqual(itemHeight0);
 53 |   });
 54 | 
 55 |   // "(vertical) children with unspecified dimensions" -> width fills available space, height is content size
 56 |   test("(vertical) children with unspecified dimensions, orientation is implicit", async ({
 57 |     page,
 58 |     initTestBed,
 59 |   }) => {
 60 |     await initTestBed(`
 61 |       <Stack testId="stack" backgroundColor="lightgray" gap="0">
 62 |         <Text testId="item_0" backgroundColor="cyan">Text #1</Text>
 63 |         <Text testId="item_1" backgroundColor="yellow">Text #2</Text>
 64 |         <Text testId="item_2" backgroundColor="lightgreen">Text #3</Text>
 65 |       </Stack>
 66 |     `);
 67 | 
 68 |     const { height: stackHeight, width: stackWidth } = await getBounds(page.getByTestId("stack"));
 69 |     const itemDims0 = await getBounds(page.getByTestId("item_0"));
 70 |     const itemDims1 = await getBounds(page.getByTestId("item_1"));
 71 |     const itemDims2 = await getBounds(page.getByTestId("item_2"));
 72 | 
 73 |     const itemHeightSum = itemDims0.height + itemDims1.height + itemDims2.height;
 74 | 
 75 |     expect(itemHeightSum).toEqualWithTolerance(stackHeight);
 76 |     expect(itemDims0.width).toEqual(stackWidth);
 77 |     expect(itemDims1.width).toEqual(stackWidth);
 78 |     expect(itemDims2.width).toEqual(stackWidth);
 79 |   });
 80 | 
 81 |   // "(horizontal) block children with unspecified dimensions" -> width is content size,
 82 |   // height is content size, block children are treated as inline elements
 83 |   test("(horizontal) block children with unspecified dimensions", async ({ page, initTestBed }) => {
 84 |     await initTestBed(`
 85 |       <Fragment>
 86 |         <Stack testId="stack" orientation="horizontal" backgroundColor="lightgray" gap="0">
 87 |           <Text testId="item_0" backgroundColor="cyan">Heading 1</Text>
 88 |           <Text testId="item_1" backgroundColor="yellow">Heading 2</Text>
 89 |           <Text testId="item_2" backgroundColor="lightgreen">Heading 3</Text>
 90 |         </Stack>
 91 |         <Stack testId="stack2" orientation="horizontal" backgroundColor="lightgray">
 92 |           <Text testId="item_3" backgroundColor="coral">Heading 1Heading 2Heading 3</Text>
 93 |         </Stack>
 94 |       </Fragment>
 95 |     `);
 96 | 
 97 |     const { width: stackWidth, height: stackHeight } = await getBounds(page.getByTestId("stack"));
 98 |     const { width: itemWidth0, height: itemHeight0 } = await getBounds(page.getByTestId("item_0"));
 99 |     const { width: itemWidth1, height: itemHeight1 } = await getBounds(page.getByTestId("item_1"));
100 |     const { width: itemWidth2, height: itemHeight2 } = await getBounds(page.getByTestId("item_2"));
101 |     const { width: itemWidth3 } = await getBounds(page.getByTestId("item_3"));
102 | 
103 |     const itemWidthSum = itemWidth0 + itemWidth1 + itemWidth2;
104 |     const tallestItemHeight = Math.max(itemHeight0, itemHeight1, itemHeight2);
105 | 
106 |     expect(itemWidthSum).toBeLessThan(stackWidth);
107 |     expect(itemWidthSum).toEqualWithTolerance(itemWidth3);
108 |     expect(stackHeight).toEqual(tallestItemHeight);
109 |   });
110 | 
111 |   // "(horizontal) children with fixed dimensions" -> Stack does not alter dimensions
112 |   test("(horizontal) children with fixed dimensions", async ({ page, initTestBed }) => {
113 |     await initTestBed(`
114 |       <Stack testId="stack" orientation="horizontal" gap="0">
115 |         <Text testId="item_0" backgroundColor="cyan" width="72px" height="36px">72 x 36</Text>
116 |         <Text testId="item_1" backgroundColor="yellow" width="144px" height="72px">144 x 72</Text>
117 |         <Text testId="item_2" backgroundColor="lightgreen" width="64px" height="48px">64 x 48</Text>
118 |       </Stack>
119 |     `);
120 | 
121 |     const { height: stackHeight } = await getBounds(page.getByTestId("stack"));
122 |     const itemDims0 = await getBounds(page.getByTestId("item_0"));
123 |     const itemDims1 = await getBounds(page.getByTestId("item_1"));
124 |     const itemDims2 = await getBounds(page.getByTestId("item_2"));
125 | 
126 |     const tallestItemHeight = 72;
127 |     const itemWidthSum = 72 + 144 + 64;
128 | 
129 |     //no gaps between items
130 |     expect(itemWidthSum).toEqualWithTolerance(itemDims2.right);
131 |     expect(stackHeight).toEqual(tallestItemHeight);
132 |     expect(itemDims0).toMatchObject({ width: 72, height: 36 });
133 |     expect(itemDims1).toMatchObject({ width: 144, height: 72 });
134 |     expect(itemDims2).toMatchObject({ width: 64, height: 48 });
135 |   });
136 | 
137 |   // "(vertical) children with fixed dimensions" -> Stack does not alter dimensions
138 |   test("(vertical) children with fixed dimensions", async ({ page, initTestBed }) => {
139 |     await initTestBed(`
140 |       <Stack testId="stack" orientation="vertical" gap="0">
141 |         <Text testId="item_0" backgroundColor="cyan" width="72px" height="36px">72 x 36</Text>
142 |         <Text testId="item_1" backgroundColor="yellow" width="144px" height="72px">144 x 72</Text>
143 |         <Text testId="item_2" backgroundColor="lightgreen" width="64px" height="48px">64 x 48</Text>
144 |       </Stack>
145 |     `);
146 | 
147 |     const { width: stackWidth, height: stackHeight } = await getBounds(page.getByTestId("stack"));
148 |     const itemDims0 = await getBounds(page.getByTestId("item_0"));
149 |     const itemDims1 = await getBounds(page.getByTestId("item_1"));
150 |     const itemDims2 = await getBounds(page.getByTestId("item_2"));
151 | 
152 |     const widestItemWidth = 144;
153 |     const itemHeightSum = 36 + 72 + 48;
154 | 
155 |     expect(widestItemWidth).toBeLessThan(stackWidth);
156 |     expect(itemHeightSum).toEqualWithTolerance(itemDims2.bottom);
157 |     expect(itemHeightSum).toEqualWithTolerance(stackHeight);
158 |     expect(itemDims0).toMatchObject({ width: 72, height: 36 });
159 |     expect(itemDims1).toMatchObject({ width: 144, height: 72 });
160 |     expect(itemDims2).toMatchObject({ width: 64, height: 48 });
161 |   });
162 | 
163 |   // (horizontal) children with fixed width and unspecified height -> item height is the same as stack height
164 |   test("(horizontal) children with fixed width and unspecified height", async ({
165 |     page,
166 |     initTestBed,
167 |   }) => {
168 |     await initTestBed(`
169 |       <Stack testId="stack" orientation="horizontal" gap="0">
170 |         <Text testId="item_0" backgroundColor="cyan" width="72px">W: 72</Text>
171 |         <Text testId="item_1" backgroundColor="yellow" width="144px">W: 144</Text>
172 |         <Text testId="item_2" backgroundColor="lightgreen" width="48px">W: 48 + long, long, long text</Text>
173 |       </Stack>
174 |     `);
175 | 
176 |     const { height: stackHeight, width: stackWidth } = await getBounds(page.getByTestId("stack"));
177 |     const itemDims0 = await getBounds(page.getByTestId("item_0"));
178 |     const itemDims1 = await getBounds(page.getByTestId("item_1"));
179 |     const itemDims2 = await getBounds(page.getByTestId("item_2"));
180 | 
181 |     const itemWidthSum = itemDims0.width + itemDims1.width + itemDims2.width;
182 | 
183 |     expect(itemWidthSum).toEqualWithTolerance(itemDims2.right);
184 |     expect(itemWidthSum).toBeLessThan(stackWidth);
185 | 
186 |     expect(itemDims0.height).toEqual(stackHeight);
187 |     expect(itemDims1.height).toEqual(stackHeight);
188 |     expect(itemDims2.height).toEqual(stackHeight);
189 | 
190 |     expect(itemDims0.width).toEqual(72);
191 |     expect(itemDims1.width).toEqual(144);
192 |     expect(itemDims2.width).toEqual(48);
193 |   });
194 | 
195 |   // (vertical) children with fixed height and unspecified width -> width fills available space
196 |   test("(vertical) children with fixed height and unspecified width ", async ({
197 |     page,
198 |     initTestBed,
199 |   }) => {
200 |     await initTestBed(`
201 |       <Stack testId="stack" orientation="vertical" gap="0">
202 |         <Text testId="item_0" backgroundColor="cyan" height="36px">H: 36</Text>
203 |         <Text testId="item_1" backgroundColor="yellow" height="72px">H: 72</Text>
204 |         <Text testId="item_2" backgroundColor="lightgreen" height="48px">H: 48 + long, long, long text</Text>
205 |       </Stack>
206 |     `);
207 | 
208 |     const { height: stackHeight, width: stackWidth } = await getBounds(page.getByTestId("stack"));
209 |     const itemDims0 = await getBounds(page.getByTestId("item_0"));
210 |     const itemDims1 = await getBounds(page.getByTestId("item_1"));
211 |     const itemDims2 = await getBounds(page.getByTestId("item_2"));
212 | 
213 |     const itemHeightSum = 36 + 72 + 48;
214 | 
215 |     expect(itemHeightSum).toEqualWithTolerance(itemDims2.bottom);
216 |     expect(itemHeightSum).toEqualWithTolerance(stackHeight);
217 | 
218 |     expect(itemDims0.width).toEqual(stackWidth);
219 |     expect(itemDims1.width).toEqual(stackWidth);
220 |     expect(itemDims2.width).toEqual(stackWidth);
221 | 
222 |     expect(itemDims0.height).toEqual(36);
223 |     expect(itemDims1.height).toEqual(72);
224 |     expect(itemDims2.height).toEqual(48);
225 |   });
226 | 
227 |   // (horizontal) children with fixed height and unspecified width -> item widths are conent size, item heights are not altered
228 |   test("(horizontal) children with fixed height and unspecified width", async ({
229 |     page,
230 |     initTestBed,
231 |   }) => {
232 |     await initTestBed(`
233 |       <Stack testId="stack" orientation="horizontal" gap="0">
234 |         <Text testId="item_0" backgroundColor="cyan" height="36px">H: 36</Text>
235 |         <Text testId="item_1" backgroundColor="yellow" height="72px">H: 72</Text>
236 |         <Text testId="item_2" backgroundColor="lightgreen" height="48px">H: 48</Text>
237 |       </Stack>
238 |     `);
239 | 
240 |     const { height: stackHeight, width: stackWidth } = await getBounds(page.getByTestId("stack"));
241 |     const itemDims0 = await getBounds(page.getByTestId("item_0"));
242 |     const itemDims1 = await getBounds(page.getByTestId("item_1"));
243 |     const itemDims2 = await getBounds(page.getByTestId("item_2"));
244 | 
245 |     const itemWidthSum = itemDims0.width + itemDims1.width + itemDims2.width;
246 |     const tallestItemHeight = 72;
247 | 
248 |     expect(itemWidthSum).toBeLessThan(stackWidth);
249 |     expect(stackHeight).toEqual(tallestItemHeight);
250 | 
251 |     expect(itemDims0.height).toEqual(36);
252 |     expect(itemDims1.height).toEqual(72);
253 |     expect(itemDims2.height).toEqual(48);
254 |   });
255 | 
256 |   // (vertical) children with fixed width and unspecified height -> item heights are content size, widths are not altered
257 |   test("(vertical) children with fixed width and unspecified height", async ({
258 |     page,
259 |     initTestBed,
260 |   }) => {
261 |     await initTestBed(`
262 |       <Stack testId="stack" orientation="vertical" gap="0">
263 |         <Text testId="item_0" backgroundColor="cyan" width="72px">W: 72</Text>
264 |         <Text testId="item_1" backgroundColor="yellow" width="144px">W: 144</Text>
265 |         <Text testId="item_2" backgroundColor="lightgreen" width="48px">W: 48 + long, long, long text</Text>
266 |       </Stack>
267 |     `);
268 | 
269 |     const { height: stackHeight } = await getBounds(page.getByTestId("stack"));
270 |     const itemDims0 = await getBounds(page.getByTestId("item_0"));
271 |     const itemDims1 = await getBounds(page.getByTestId("item_1"));
272 |     const itemDims2 = await getBounds(page.getByTestId("item_2"));
273 | 
274 |     const itemHeightSum = itemDims0.height + itemDims1.height + itemDims2.height;
275 | 
276 |     expect(itemHeightSum).toEqualWithTolerance(itemDims2.bottom);
277 |     expect(itemHeightSum).toEqualWithTolerance(stackHeight);
278 | 
279 |     expect(itemDims0.width).toEqual(72);
280 |     expect(itemDims1.width).toEqual(144);
281 |     expect(itemDims2.width).toEqual(48);
282 |   });
283 | 
284 |   test("(horizontal) percentage sizing", async ({ page, initTestBed }) => {
285 |     await initTestBed(`
286 |       <Stack testId="stack" orientation="horizontal" backgroundColor="lightgray" gap="0">
287 |         <Text testId="item_0" backgroundColor="cyan" width="20%">W: 20%</Text>
288 |         <H2 testId="item_1" backgroundColor="yellow" width="50%">W: 50%</H2>
289 |         <H5 testId="item_2" backgroundColor="lightgreen" width="20%">W: 20% + long, long, long text</H5>
290 |       </Stack>
291 |     `);
292 | 
293 |     const { width: stackWidth } = await getBounds(page.getByTestId("stack"));
294 |     const { width: itemWidth0 } = await getBounds(page.getByTestId("item_0"));
295 |     const { width: itemWidth1 } = await getBounds(page.getByTestId("item_1"));
296 |     const { width: itemWidth2, right: lastItemRight } = await getBounds(page.getByTestId("item_2"));
297 |     const itemWidthSum = itemWidth0 + itemWidth1 + itemWidth2;
298 | 
299 |     expect(stackWidth).toEqual(PAGE_WIDTH);
300 |     expect(itemWidthSum).toEqualWithTolerance(lastItemRight);
301 |     expect(itemWidth0).toEqualWithTolerance(0.2 * stackWidth);
302 |     expect(itemWidth1).toEqualWithTolerance(0.5 * stackWidth);
303 |     expect(itemWidth2).toEqualWithTolerance(0.2 * stackWidth);
304 |   });
305 | 
306 |   test("(vertical) percentage sizing", async ({ page, initTestBed }) => {
307 |     await initTestBed(`
308 |       <Stack testId="stack" height="180px" orientation="vertical" backgroundColor="lightgray" gap="0">
309 |         <Text testId="item_0" backgroundColor="cyan" height="20%">W: 20%</Text>
310 |         <Text testId="item_1" backgroundColor="yellow" height="50%">W: 50%</Text>
311 |         <Text testId="item_2" backgroundColor="lightgreen" height="20%">W: 20% + long, long, long text</Text>
312 |       </Stack>
313 |     `);
314 | 
315 |     const { height: stackHeight, width: stackWidth } = await getBounds(page.getByTestId("stack"));
316 |     const { height: itemHeight0, width: itemWidth0 } = await getBounds(page.getByTestId("item_0"));
317 |     const { height: itemHeight1 } = await getBounds(page.getByTestId("item_1"));
318 |     const { height: itemHeight2, bottom: lastItemBottom } = await getBounds(
319 |       page.getByTestId("item_2"),
320 |     );
321 |     const itemHeightSum = itemHeight0 + itemHeight1 + itemHeight2;
322 | 
323 |     expect(itemWidth0).toEqual(stackWidth);
324 |     expect(itemHeightSum).toEqualWithTolerance(lastItemBottom);
325 |     expect(itemHeight0).toEqualWithTolerance(0.2 * stackHeight);
326 |     expect(itemHeight1).toEqualWithTolerance(0.5 * stackHeight);
327 |     expect(itemHeight2).toEqualWithTolerance(0.2 * stackHeight);
328 |   });
329 | 
330 |   test("(horizontal) percentage sizing fully filled", async ({ page, initTestBed }) => {
331 |     await initTestBed(`
332 |       <Stack testId="stack" orientation="horizontal" backgroundColor="lightgray" gap="0">
333 |         <Text testId="item_0" backgroundColor="cyan" width="20%">W: 20%</Text>
334 |         <H2 testId="item_1" backgroundColor="yellow" width="50%">W: 50%</H2>
335 |         <H5 testId="item_2" backgroundColor="lightgreen" width="30%">W: 30% + long, long, long text</H5>
336 |       </Stack>
337 |     `);
338 |     const { width: stackWidth } = await getBounds(page.getByTestId("stack"));
339 |     const { right: lastItemRight } = await getBounds(page.getByTestId("item_2"));
340 |     expect(stackWidth).toEqualWithTolerance(lastItemRight);
341 |   });
342 | 
343 |   test("(vertical) percentage sizing fully filled", async ({ page, initTestBed }) => {
344 |     await initTestBed(`
345 |       <Stack testId="stack" height="180px" orientation="vertical" backgroundColor="lightgray" gap="0">
346 |         <Text testId="item_0" backgroundColor="cyan" height="20%">W: 20%</Text>
347 |         <Text testId="item_1" backgroundColor="yellow" height="50%">W: 50%</Text>
348 |         <Text testId="item_2" backgroundColor="lightgreen" height="30%">W: 30% + long, long, long text</Text>
349 |       </Stack>
350 |     `);
351 |     const { height: stackHeight } = await getBounds(page.getByTestId("stack"));
352 |     const { bottom: lastItemBottom } = await getBounds(page.getByTestId("item_2"));
353 |     expect(stackHeight).toEqualWithTolerance(lastItemBottom);
354 |   });
355 | 
356 |   // (horizontal) percentage overflow X
357 |   test("(horizontal) percentage overflow X", async ({ page, initTestBed }) => {
358 |     await initTestBed(`
359 |       <Stack testId="stack" orientation="horizontal" backgroundColor="lightgray" gap="0">
360 |         <Text testId="item_0" backgroundColor="cyan" width="30%">W: 30%</Text>
361 |         <H2 testId="item_1" backgroundColor="yellow" width="50%">W: 50%</H2>
362 |         <H5 testId="item_2" backgroundColor="lightgreen" width="40%">W: 40% + long, long, long text</H5>
363 |       </Stack>
364 |     `);
365 |     const isOverflown = await overflows(page.getByTestId("stack"), "x");
366 |     expect(isOverflown).toEqual(true);
367 |   });
368 | 
369 |   // (vertical) percentage overflow Y
370 |   test("(vertical) percentage overflow Y", async ({ page, initTestBed }) => {
371 |     await initTestBed(`
372 |       <Stack testId="stack" orientation="vertical" height="180px" backgroundColor="lightgray" gap="0">
373 |         <Text testId="item_0" backgroundColor="cyan" height="30%">H: 30%</Text>
374 |         <H2 testId="item_1" backgroundColor="yellow" height="60%">H: 60%</H2>
375 |         <H5 testId="item_2" backgroundColor="lightgreen" height="20%">H: 20% + long, long, long text</H5>
376 |       </Stack>
377 |     `);
378 |     const isOverflown = await overflows(page.getByTestId("stack"), "y");
379 |     expect(isOverflown).toEqual(true);
380 |   });
381 | 
382 |   test("(horizontal) star sizing", async ({ page, initTestBed }) => {
383 |     await initTestBed(`
384 |       <Stack testId="stack" width="100%" orientation="horizontal" backgroundColor="lightgray" gap="0">
385 |         <Text testId="item_0" backgroundColor="cyan" width="100px">W: 100</Text>
386 |         <Text testId="item_1" backgroundColor="yellow" width="3*">W: 3*</Text>
387 |         <Text testId="item_2" backgroundColor="lightgreen" width="*">W: *</Text>
388 |       </Stack>
389 |     `);
390 |     const { width: stackWidth } = await getBounds(page.getByTestId("stack"));
391 |     const { width: itemWidth0 } = await getBounds(page.getByTestId("item_0"));
392 |     const { width: itemWidth1 } = await getBounds(page.getByTestId("item_1"));
393 |     const { width: itemWidth2, right: lastItemRight } = await getBounds(page.getByTestId("item_2"));
394 |     const itemWidthSum = itemWidth0 + itemWidth1 + itemWidth2;
395 | 
396 |     const expectedItemWidth0 = 100;
397 |     const expectedItemWidth1 = (stackWidth - 100) * (3 / 4);
398 |     const expectedItemWidth2 = (stackWidth - 100) * (1 / 4);
399 | 
400 |     expect(itemWidthSum).toEqualWithTolerance(lastItemRight);
401 |     expect(itemWidth0).toEqual(expectedItemWidth0);
402 |     expect(itemWidth1).toEqualWithTolerance(expectedItemWidth1);
403 |     expect(itemWidth2).toEqualWithTolerance(expectedItemWidth2);
404 |   });
405 | 
406 |   // (horizontal) star sizing comparison -> Larger Stack have larger star sized children, px sizes are same
407 |   test("(horizontal) star sizing comparison", async ({ page, initTestBed }) => {
408 |     await initTestBed(`
409 |       <Fragment>
410 |         <Stack testId="stack_0" orientation="horizontal" width="600px" gap="0">
411 |           <Text testId="ref_item_0" backgroundColor="cyan" width="100px">W: 100</Text>
412 |           <Text testId="ref_item_1" backgroundColor="yellow" width="3*">W: 3*</Text>
413 |           <Text testId="ref_item_2" backgroundColor="lightgreen" width="*">W: *</Text>
414 |         </Stack>
415 |         <Stack testId="stack_1" orientation="horizontal" width="300px" gap="0">
416 |           <Text testId="item_0" backgroundColor="cyan" width="100px">W: 100</Text>
417 |           <Text testId="item_1" backgroundColor="yellow" width="3*">W: 3*</Text>
418 |           <Text testId="item_2" backgroundColor="lightgreen" width="*">W: *</Text>
419 |         </Stack>
420 |       </Fragment>
421 |     `);
422 |     const { width: refItemWidth0 } = await getBounds(page.getByTestId("ref_item_0"));
423 |     const { width: refItemWidth1 } = await getBounds(page.getByTestId("ref_item_1"));
424 |     const { width: refItemWidth2 } = await getBounds(page.getByTestId("ref_item_2"));
425 |     const { width: itemWidth0 } = await getBounds(page.getByTestId("item_0"));
426 |     const { width: itemWidth1 } = await getBounds(page.getByTestId("item_1"));
427 |     const { width: itemWidth2 } = await getBounds(page.getByTestId("item_2"));
428 | 
429 |     expect(refItemWidth0).toEqual(itemWidth0);
430 |     expect(refItemWidth1).toBeGreaterThan(itemWidth1);
431 |     expect(refItemWidth2).toBeGreaterThan(itemWidth2);
432 |   });
433 | 
434 |   // (vertical) star sizing comparison -> Larger Stack have larger star sized children, px sizes are same
435 |   test("(vertical) star sizing comparison", async ({ page, initTestBed }) => {
436 |     await initTestBed(`
437 |       <Fragment>
438 |         <Stack testId="stack_0" orientation="vertical" height="600px" gap="0">
439 |           <Text testId="ref_item_0" backgroundColor="cyan" height="100px">W: 100</Text>
440 |           <Text testId="ref_item_1" backgroundColor="yellow" height="3*">W: 3*</Text>
441 |           <Text testId="ref_item_2" backgroundColor="lightgreen" height="*">W: *</Text>
442 |         </Stack>
443 |         <Stack testId="stack_1" orientation="vertical" height="300px" gap="0">
444 |           <Text testId="item_0" backgroundColor="cyan" height="100px">W: 100</Text>
445 |           <Text testId="item_1" backgroundColor="yellow" height="3*">W: 3*</Text>
446 |           <Text testId="item_2" backgroundColor="lightgreen" height="*">W: *</Text>
447 |         </Stack>
448 |       </Fragment>
449 |     `);
450 |     const { height: refItemHeight0 } = await getBounds(page.getByTestId("ref_item_0"));
451 |     const { height: refItemHeight1 } = await getBounds(page.getByTestId("ref_item_1"));
452 |     const { height: refItemHeight2 } = await getBounds(page.getByTestId("ref_item_2"));
453 |     const { height: itemHeight0 } = await getBounds(page.getByTestId("item_0"));
454 |     const { height: itemHeight1 } = await getBounds(page.getByTestId("item_1"));
455 |     const { height: itemHeight2 } = await getBounds(page.getByTestId("item_2"));
456 | 
457 |     expect(refItemHeight0).toEqual(itemHeight0);
458 |     expect(refItemHeight1).toBeGreaterThan(itemHeight1);
459 |     expect(refItemHeight2).toBeGreaterThan(itemHeight2);
460 |   });
461 | 
462 |   // (horizontal) gaps + percentage -> children use available space
463 |   test("(horizontal) paddings + percentage", async ({ page, initTestBed }) => {
464 |     await initTestBed(`
465 |       <Stack testId="stack" orientation="horizontal" backgroundColor="lightgray" gap="0"
466 |         paddingHorizontal="50px" paddingVertical="50px">
467 |         <Text testId="item_0" backgroundColor="cyan" width="25%">W: 25%</Text>
468 |         <Text testId="item_1" backgroundColor="yellow" width="50%">W: 50%</Text>
469 |         <Text testId="item_2" backgroundColor="lightgreen" width="25%">W: 25%</Text>
470 |       </Stack>
471 |     `);
472 |     const { width: stackWidth } = await getBounds(page.getByTestId("stack"));
473 |     const { width: itemWidth0, left: firstItemLeft } = await getBounds(page.getByTestId("item_0"));
474 |     const { width: itemWidth1 } = await getBounds(page.getByTestId("item_1"));
475 |     const { width: itemWidth2, right: lastItemRight } = await getBounds(page.getByTestId("item_2"));
476 | 
477 |     const itemWidthSum = itemWidth0 + itemWidth1 + itemWidth2;
478 |     expect(firstItemLeft).toEqual(50);
479 |     expect(lastItemRight).toEqual(stackWidth - 50);
480 |     expect(itemWidthSum).toEqualWithTolerance(stackWidth - 2 * 50);
481 |   });
482 | 
483 |   // (vertical) gaps + percentage -> children use available space
484 |   test("(vertical) paddings + percentage", async ({ page, initTestBed }) => {
485 |     await initTestBed(`
486 |       <Stack testId="stack" orientation="vertical" backgroundColor="lightgray" gap="0"
487 |         height="240px" paddingHorizontal="50px" paddingVertical="50px">
488 |         <Text testId="item_0" backgroundColor="cyan" height="25%">H: 25%</Text>
489 |         <Text testId="item_1" backgroundColor="yellow" height="50%">H: 50%</Text>
490 |         <Text testId="item_2" backgroundColor="lightgreen" height="25%">H: 25%</Text>
491 |       </Stack>
492 |     `);
493 |     const { height: stackHeight } = await getBounds(page.getByTestId("stack"));
494 |     const { top: firstItemTop } = await getBounds(page.getByTestId("item_0"));
495 |     const { bottom: lastItemBottom } = await getBounds(page.getByTestId("item_2"));
496 | 
497 |     expect(firstItemTop).toEqual(50);
498 |     expect(lastItemBottom).toEqual(stackHeight - 50);
499 |   });
500 | 
501 |   test("(horizontal) gaps", async ({ page, initTestBed }) => {
502 |     await initTestBed(`
503 |       <Stack orientation="horizontal" backgroundColor="lightgray" gap="50px">
504 |         <Stack testId="item_0" backgroundColor="red" height="36px" width="36px" />
505 |         <Stack testId="item_1" backgroundColor="green" height="36px" width="36px" />
506 |         <Stack testId="item_2" backgroundColor="blue" height="36px" width="36px" />
507 |       </Stack>
508 |     `);
509 | 
510 |     const itemDims0 = await getBounds(page.getByTestId("item_0"));
511 |     const itemDims1 = await getBounds(page.getByTestId("item_1"));
512 |     const itemDims2 = await getBounds(page.getByTestId("item_2"));
513 | 
514 |     expect(itemDims0.left).toEqual(0);
515 |     expect(itemDims1.left).toEqual(itemDims0.right + 50);
516 |     expect(itemDims2.left).toEqual(2 * (itemDims0.right + 50));
517 |   });
518 | 
519 |   test("(vertical) gaps", async ({ page, initTestBed }) => {
520 |     await initTestBed(`
521 |       <Stack orientation="vertical" backgroundColor="lightgray" gap="50px">
522 |         <Stack testId="item_0" backgroundColor="red" height="36px" width="36px" />
523 |         <Stack testId="item_1" backgroundColor="green" height="36px" width="36px" />
524 |         <Stack testId="item_2" backgroundColor="blue" height="36px" width="36px" />
525 |       </Stack>
526 |     `);
527 | 
528 |     const itemDims0 = await getBounds(page.getByTestId("item_0"));
529 |     const itemDims1 = await getBounds(page.getByTestId("item_1"));
530 |     const itemDims2 = await getBounds(page.getByTestId("item_2"));
531 | 
532 |     expect(itemDims0.top).toEqual(0);
533 |     expect(itemDims1.top).toEqual(itemDims0.bottom + 50);
534 |     expect(itemDims2.top).toEqual(2 * (itemDims0.bottom + 50));
535 |   });
536 | 
537 |   // (horizontal) gaps + percentage -> gaps push the content out of the container
538 |   test("(horizontal) gaps + percentage", async ({ page, initTestBed }) => {
539 |     await initTestBed(`
540 |       <Stack testId="stack" orientation="horizontal" backgroundColor="lightgray" padding="1rem" gap="2rem">
541 |         <Stack backgroundColor="red" height="36px" width="25%" />
542 |         <Stack backgroundColor="green" height="36px" width="50%" />
543 |         <Stack backgroundColor="blue" height="36px" width="25%" />
544 |       </Stack>
545 |     `);
546 |     const isOverflown = await overflows(page.getByTestId("stack"), "x");
547 |     expect(isOverflown).toEqual(true);
548 |   });
549 | 
550 |   // (horizontal) gaps + star sizing -> gaps don't push the content out of the container
551 |   test("(horizontal) gaps + star sizing", async ({ page, initTestBed }) => {
552 |     await initTestBed(`
553 |       <Stack testId="stack" orientation="horizontal" backgroundColor="lightgray" padding="1rem" gap="2rem">
554 |         <Stack backgroundColor="red" height="36px" width="*" />
555 |         <Stack backgroundColor="green" height="36px" width="*" />
556 |         <Stack backgroundColor="blue" height="36px" width="*" />
557 |         <Stack backgroundColor="purple" height="36px" width="*" />
558 |       </Stack>
559 |     `);
560 |     const isOverflown = await overflows(page.getByTestId("stack"), "x");
561 |     expect(isOverflown).toEqual(false);
562 |   });
563 | 
564 |   test("(horizontal) rtl rendering direction", async ({ page, initTestBed }) => {
565 |     await initTestBed(`
566 |       <Stack testId="stack" orientation="horizontal" gap="1rem" direction="rtl">
567 |         <Stack testId="item_0" backgroundColor="red" height="36px" width="36px" />
568 |         <Stack testId="item_1" backgroundColor="green" height="36px" width="36px" />
569 |         <Stack testId="item_2" backgroundColor="blue" height="36px" width="36px" />
570 |       </Stack>
571 |     `);
572 | 
573 |     const { right: stackRight } = await getBounds(page.getByTestId("stack"));
574 |     const { right: itemRight0, left: itemLeft0 } = await getBounds(page.getByTestId("item_0"));
575 |     const { left: itemLeft1 } = await getBounds(page.getByTestId("item_1"));
576 |     const { left: itemLeft2 } = await getBounds(page.getByTestId("item_2"));
577 | 
578 |     expect(itemLeft2).toBeLessThan(itemLeft1);
579 |     expect(itemLeft1).toBeLessThan(itemLeft0);
580 |     expect(itemRight0).toEqual(stackRight);
581 |   });
582 | 
583 |   test("(horizontal) reverse rendering direction", async ({ page, initTestBed }) => {
584 |     await initTestBed(`
585 |       <Stack testId="stack" orientation="horizontal" gap="1rem" reverse="true">
586 |         <Stack testId="item_0" backgroundColor="red" height="36px" width="36px" />
587 |         <Stack testId="item_1" backgroundColor="green" height="36px" width="36px" />
588 |         <Stack testId="item_2" backgroundColor="blue" height="36px" width="36px" />
589 |       </Stack>
590 |     `);
591 |     const { right: stackRight } = await getBounds(page.getByTestId("stack"));
592 |     const { right: itemRight0, left: itemLeft0 } = await getBounds(page.getByTestId("item_0"));
593 |     const { left: itemLeft1 } = await getBounds(page.getByTestId("item_1"));
594 |     const { left: itemLeft2 } = await getBounds(page.getByTestId("item_2"));
595 | 
596 |     expect(itemLeft2).toBeLessThan(itemLeft1);
597 |     expect(itemLeft1).toBeLessThan(itemLeft0);
598 |     expect(itemRight0).toEqual(stackRight);
599 |   });
600 | 
601 |   test("(vertical) reverse rendering direction", async ({ page, initTestBed }) => {
602 |     await initTestBed(`
603 |       <Stack testId="stack" orientation="vertical" gap="1rem" reverse="true">
604 |         <Stack testId="item_0" backgroundColor="red" height="36px" width="36px" />
605 |         <Stack testId="item_1" backgroundColor="green" height="36px" width="36px" />
606 |         <Stack testId="item_2" backgroundColor="blue" height="36px" width="36px" />
607 |       </Stack>
608 |     `);
609 |     const { bottom: stackBottom } = await getBounds(page.getByTestId("stack"));
610 |     const { bottom: itemBottom0, top: itemTop0 } = await getBounds(page.getByTestId("item_0"));
611 |     const { top: itemTop1 } = await getBounds(page.getByTestId("item_1"));
612 |     const { top: itemTop2 } = await getBounds(page.getByTestId("item_2"));
613 | 
614 |     expect(itemTop2).toBeLessThan(itemTop1);
615 |     expect(itemTop1).toBeLessThan(itemTop0);
616 |     expect(itemBottom0).toEqual(stackBottom);
617 |   });
618 | 
619 |   test("(horizontal) content wrapping", async ({ page, initTestBed }) => {
620 |     await initTestBed(`
621 |       <Stack testId="stack" orientation="horizontal" gap="1rem" wrapContent="true">
622 |         <Stack testId="item_0" backgroundColor="red" height="36px" width="25%" />
623 |         <Stack testId="item_1" backgroundColor="green" height="36px" width="40%" />
624 |         <Stack testId="item_2" backgroundColor="blue" height="36px" width="20%" />
625 |         <Stack testId="item_3" backgroundColor="purple" height="36px" width="30%" />
626 |       </Stack>
627 |     `);
628 |     const { right: stackRight, bottom: stackBottom } = await getBounds(page.getByTestId("stack"));
629 |     const { left: itemLeft0, bottom: itemBottom0 } = await getBounds(page.getByTestId("item_0"));
630 |     const { left: itemLeft1 } = await getBounds(page.getByTestId("item_1"));
631 |     const { left: itemLeft2, right: itemRight2 } = await getBounds(page.getByTestId("item_2"));
632 |     const {
633 |       left: itemLeft3,
634 |       bottom: itemBottom3,
635 |       top: itemTop3,
636 |     } = await getBounds(page.getByTestId("item_3"));
637 | 
638 |     expect(itemLeft0).toBeLessThan(itemLeft1);
639 |     expect(itemLeft1).toBeLessThan(itemLeft2);
640 |     expect(itemRight2).toBeLessThan(stackRight);
641 | 
642 |     expect(itemBottom0).toBeLessThan(itemTop3);
643 |     expect(itemLeft3).toEqual(itemLeft0);
644 |     expect(itemBottom3).toEqual(stackBottom);
645 |   });
646 | 
647 |   test("(horizontal) horizontalAlignment center", async ({ page, initTestBed }) => {
648 |     await initTestBed(`
649 |       <Stack testId="stack" orientation="horizontal" horizontalAlignment="center" gap="0">
650 |         <Stack testId="item_0" backgroundColor="red" height="36px" width="36px" />
651 |         <Stack testId="item_1" backgroundColor="green" height="36px" width="36px" />
652 |         <Stack testId="item_2" backgroundColor="blue" height="36px" width="36px" />
653 |       </Stack>
654 |     `);
655 |     const { right: stackRight } = await getBounds(page.getByTestId("stack"));
656 |     const { left: itemLeft0 } = await getBounds(page.getByTestId("item_0"));
657 |     const { right: itemRight2 } = await getBounds(page.getByTestId("item_2"));
658 |     const itemWidthSum = 3 * 36;
659 | 
660 |     expect(itemLeft0).toEqual(stackRight / 2 - itemWidthSum / 2);
661 |     expect(itemRight2).toEqual(stackRight / 2 + itemWidthSum / 2);
662 |   });
663 | 
664 |   test("(vertical) horizontal alignment end", async ({ page, initTestBed }) => {
665 |     await initTestBed(`
666 |       <Stack testId="stack" orientation="vertical" horizontalAlignment="end" gap="0">
667 |         <Stack testId="item_0" backgroundColor="red" height="36px" width="36px" />
668 |         <Stack testId="item_1" backgroundColor="green" height="36px" width="36px" />
669 |         <Stack testId="item_2" backgroundColor="blue" height="36px" width="36px" />
670 |       </Stack>
671 |     `);
672 |     const { right: stackRight } = await getBounds(page.getByTestId("stack"));
673 |     const { right: itemRight0 } = await getBounds(page.getByTestId("item_0"));
674 |     const { right: itemRight1 } = await getBounds(page.getByTestId("item_1"));
675 |     const { right: itemRight2 } = await getBounds(page.getByTestId("item_2"));
676 | 
677 |     expect(itemRight0).toEqual(stackRight);
678 |     expect(itemRight1).toEqual(stackRight);
679 |     expect(itemRight2).toEqual(stackRight);
680 |   });
681 | 
682 |   test("(horizontal) verticalAlignment center", async ({ page, initTestBed }) => {
683 |     await initTestBed(`
684 |       <Stack testId="stack" orientation="horizontal" gap="1rem" verticalAlignment="center">
685 |         <Stack testId="item_0" backgroundColor="red" height="36px" width="36px" />
686 |         <Stack testId="item_1" backgroundColor="green" height="72px" width="36px" />
687 |         <Stack testId="item_2" backgroundColor="blue" height="48px" width="36px" />
688 |       </Stack>
689 |     `);
690 |     const stackDims = await getBounds(page.getByTestId("stack"));
691 |     const itemDims0 = await getBounds(page.getByTestId("item_0"));
692 |     const itemDims1 = await getBounds(page.getByTestId("item_1"));
693 |     const itemDims2 = await getBounds(page.getByTestId("item_2"));
694 | 
695 |     expect(itemDims0.top).toEqual(stackDims.height / 2 - itemDims0.height / 2);
696 |     expect(itemDims0.bottom).toEqual(stackDims.height / 2 + itemDims0.height / 2);
697 | 
698 |     expect(itemDims1.top).toEqual(stackDims.top);
699 |     expect(itemDims1.bottom).toEqual(stackDims.bottom);
700 | 
701 |     expect(itemDims2.top).toEqual(stackDims.height / 2 - itemDims2.height / 2);
702 |     expect(itemDims2.bottom).toEqual(stackDims.height / 2 + itemDims2.height / 2);
703 |   });
704 | 
705 |   test(`overflowY="scroll"`, async ({ page, initTestBed }) => {
706 |     await initTestBed(`
707 |       <VStack testId="stack" width="100px" height="60px" backgroundColor="cyan"
708 |         overflowY="scroll">
709 |         <Text testId="item0">
710 |           As its container width and height are fixed, this long text does not
711 |           fit into it; it will overflow.
712 |         </Text>
713 |       </VStack>
714 |     `);
715 |     const { scrollHeight, clientHeight } = await page
716 |       .getByTestId("stack")
717 |       .evaluate((elem) => ({ scrollHeight: elem.scrollHeight, clientHeight: elem.clientHeight }));
718 | 
719 |     expect(scrollHeight).toBeGreaterThan(clientHeight);
720 |   });
721 | 
722 |   test(`overflowX="scroll"`, async ({ page, initTestBed }) => {
723 |     await initTestBed(`
724 |       <HStack testId="stack" width="100px" height="60px" backgroundColor="cyan"
725 |         overflowX="scroll">
726 |         <Text testId="item0">
727 |           As its container width and height are fixed, this long text does not
728 |           fit into it; it will overflow.
729 |         </Text>
730 |       </HStack>
731 |     `);
732 |     const { scrollWidth, clientWidth } = await page
733 |       .getByTestId("stack")
734 |       .evaluate((elem) => ({ scrollWidth: elem.scrollWidth, clientWidth: elem.clientWidth }));
735 | 
736 |     expect(scrollWidth).toBeGreaterThan(clientWidth);
737 |   });
738 | 
739 |   // When you set overflowX to scroll, it will automatically set overflowY to scroll if the text exceeds the viewport vertically
740 |   test(`overflowX sets overflowY`, async ({ page, initTestBed }) => {
741 |     await initTestBed(`
742 |       <VStack testId="stack" height="50px" width="300px" backgroundColor="cyan"
743 |         overflowX="scroll">
744 |         <Text width="400px" backgroundColor="silver" opacity="0.8">
745 |           This text sets its size explicitly bigger than its container.
746 |           As it does not fit into the container's viewport, it overflows.
747 |           However, its container supports horizontal scrolling so you can
748 |           see its content.
749 |         </Text>
750 |       </VStack>
751 |     `);
752 |     const { scrollHeight, clientHeight, scrollWidth, clientWidth } = await page
753 |       .getByTestId("stack")
754 |       .evaluate((elem) => ({
755 |         scrollHeight: elem.scrollHeight,
756 |         clientHeight: elem.clientHeight,
757 |         scrollWidth: elem.scrollWidth,
758 |         clientWidth: elem.clientWidth,
759 |       }));
760 | 
761 |     expect(scrollWidth).toBeGreaterThan(clientWidth);
762 |     expect(scrollHeight).toBeGreaterThan(clientHeight);
763 |   });
764 | });
765 | 
```

--------------------------------------------------------------------------------
/xmlui/dev-docs/containers.md:
--------------------------------------------------------------------------------

```markdown
  1 | # XMLUI Container-Based State Management
  2 | 
  3 | A deep dive into XMLUI's hierarchical container system for managing component state, variables, and reactive data binding.
  4 | 
  5 | ## Fundamentals of XMLUI Reactivity
  6 | 
  7 | XMLUI implements **automatic reactivity** - a programming model where UI updates happen automatically when underlying data changes, without requiring manual DOM manipulation or explicit update calls.
  8 | 
  9 | ### The Reactive Loop
 10 | 
 11 | XMLUI follows a simple reactive cycle:
 12 | 1. **Initial Render**: Framework renders the complete UI from declarative markup
 13 | 2. **Event Occurrence**: User interactions or system events trigger changes
 14 | 3. **Automatic State Detection**: Framework detects state mutations transparently
 15 | 4. **Selective UI Refresh**: Only components affected by the state change re-render
 16 | 5. **Loop Continuation**: Process repeats for subsequent events
 17 | 
 18 | From a developer perspective, reactivity means:
 19 | - **Write declarative expressions**: Use `{count}` to display values, `count++` to modify them
 20 | - **No manual updates**: Framework automatically handles UI synchronization
 21 | - **Transparent mutations**: Change variables directly without special APIs
 22 | - **Predictable behavior**: UI always reflects current state consistently
 23 | 
 24 | ### The Role of Containers in Reactivity Implementation
 25 | 
 26 | Containers are the **core mechanism** that enables XMLUI's automatic reactivity. They provide the infrastructure necessary to detect state changes, coordinate updates, and maintain UI consistency.
 27 | 
 28 | Reactivity requires several technical capabilities:
 29 | - **State Storage**: A place to hold component variables and data
 30 | - **Change Detection**: Mechanism to detect when state mutations occur  
 31 | - **Update Coordination**: System to propagate changes to affected UI components
 32 | - **Scope Management**: Control over which components can access which state
 33 | - **Performance Optimization**: Efficient updates that don't block the UI
 34 | 
 35 | Containers provide all these capabilities through a hierarchical architecture that mirrors the component structure.
 36 | 
 37 | ## Automatic Container Wrapping
 38 | 
 39 | XMLUI **automatically wraps components with containers** when they need reactive capabilities. You declare variables or data sources, and the framework creates the container infrastructure.
 40 | 
 41 | The framework creates containers for these cases:
 42 | - **App Root Container** - Wraps the entire application entry point
 43 | - **User-Defined Component Containers** - Each component instance gets isolated state
 44 | - **Variables** - Reactive state holders that trigger UI updates
 45 | - **Loaders** - Handle asynchronous data operations
 46 | - **Uses Declarations** - Control state inheritance from parents
 47 | - **Context Variables** - Framework-injected variables (routing, forms)
 48 | - **Scripts** - JavaScript blocks with variables and functions
 49 | - **Code-Behind Files** - External script files for application root or component roots
 50 | 
 51 | Every component receives an identifier (user-defined or framework-assigned). **User-defined IDs enable programmatic component interaction** - accessing methods, properties, and APIs. Framework IDs handle internal state. Component IDs scope to their declaring file (.xmlui). These IDs are stored in the App Root and User-Defined Component Containers.
 52 | 
 53 | ### App Root Container
 54 | For every XMLUI application, a root container is automatically created to wrap the entire application entry point (typically Main.xmlui). This ensures there's always a top-level container to manage application-wide state.
 55 | 
 56 | **Example - Main.xmlui:**
 57 | ```xml
 58 | <!-- File: Main.xmlui -->
 59 | <App>
 60 |   <VStack>
 61 |     <Text id="title">Welcome to My App</Text>
 62 |     <Button id="actionBtn" label="Click Me" />
 63 |     <Button label="Cancel" />
 64 |   </VStack>
 65 | </App>
 66 | ```
 67 | 
 68 | ```mermaid
 69 | %%{init: {"block": {"padding": 8}}}%%
 70 | block-beta
 71 |     columns 1
 72 |     
 73 |     AR["<div style='text-align: left; width: 100%; padding: 0 15px;'>🏠 App Root Container<br/>💡 Container State:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─ title → Text reference<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─ actionBtn → Button reference<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└─ [[cancel]] → Button reference<br/>🌳 Component Tree:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VStack:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─ Text (id: title)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─ Button (id: actionBtn)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└─ Button (id: [[cancel]])</div>"]
 74 |     
 75 |     classDef rootContainer fill:#f0f0f0,stroke:#888,stroke-width:2px,color:#333,padding-left:15px,padding-right:15px
 76 |     class AR rootContainer
 77 | ```
 78 | 
 79 | > **Note**: `[[cancel]]` is an framework-assigned ID for the Cancel button since it doesn't have an explicit `id` attribute.
 80 | 
 81 | In this example, XMLUI automatically creates a root container that stores the IDs for `title`, `actionBtn`, and `[[cancel]]`, making them accessible throughout the application.
 82 | 
 83 | ### User-Defined Component Instance Containers  
 84 | Each time you use a user-defined component (created with `<Component name="...">`) in your markup, XMLUI automatically creates a container for that specific instance. This ensures **Instance Isolation** - each component usage gets its own state container with isolated internal state.
 85 | 
 86 | **Example Files:**
 87 | 
 88 | **File: Main.xmlui**
 89 | ```xml
 90 | <!-- File: Main.xmlui -->
 91 | <App>
 92 |   <VStack>
 93 |     <!-- Each MyButton usage creates its own container -->
 94 |     <MyButton label="Save" />     <!-- Creates Container A -->
 95 |     <MyButton label="Cancel" />   <!-- Creates Container B -->  
 96 |     <MyButton label="Delete" />   <!-- Creates Container C -->
 97 |   </VStack>
 98 | </App>
 99 | ```
100 | 
101 | **File: components/MyButton.xmlui**
102 | ```xml
103 | <!-- File: components/MyButton.xmlui -->
104 | <Component name="MyButton" var.count="{0}">
105 |   <Button 
106 |     label="{$props.label} ({count})"
107 |     onClick="count++"
108 |   />
109 | </Component>
110 | ```
111 | 
112 | ```mermaid
113 | %%{init: {"block": {"padding": 8}}}%%
114 | block-beta
115 |     columns 3
116 |     
117 |     block:AppRoot:3
118 |         AR["<div style='text-align: left; width: 100%'>🏠 App Root Container<br/>💡 Container State: MyButton instances<br/>🌳 Component Tree:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VStack:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─ MyButton (Container A)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─ MyButton (Container B)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└─ MyButton (Container C)</div>"]
119 |     end
120 |     
121 |     CA["<div style='text-align: left; width: 100%'>🏠 Container A<br/>💡 State:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─ count: 0<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└─ $props.label: 'Save'<br/>🌳 Component: Button (Save 0)</div>"]
122 |     
123 |     CB["<div style='text-align: left; width: 100%'>🏠 Container B<br/>💡 State:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─ count: 0<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└─ $props.label: 'Cancel'<br/>🌳 Component: Button (Cancel 0)</div>"]
124 |     
125 |     CC["<div style='text-align: left; width: 100%'>🏠 Container C<br/>💡 State:<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─ count: 0<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└─ $props.label: 'Delete'<br/>🌳 Component: Button (Delete 0)</div>"]
126 |     
127 |     classDef rootContainer fill:#f0f0f0,stroke:#888,stroke-width:2px,color:#333
128 |     classDef innerContainer fill:#f8f8f8,stroke:#aaa,stroke-width:1px,color:#333
129 |     
130 |     class AR,CC,CB,CA rootContainer
131 |     class ARS,ART,CHC,CHB,CHA,CSC,CSB,CSA innerContainer
132 | ```
133 | 
134 | Each `MyButton` instance gets its own container with isolated `count` variable - clicking one button doesn't affect the others.
135 | 
136 | ### Variables
137 | Variables in XMLUI are reactive state holders that automatically trigger UI updates when changed. They can contain any JavaScript value, including functions. Variables can declare functions, and those functions can be invoked.
138 | 
139 | **Simple Variable Example:**
140 | ```xml
141 | <Stack var.count="{0}">
142 |   <Button onClick="count++" label="Count: {count}" />
143 | </Stack>
144 | ```
145 | 
146 | **Function Variable Example:**
147 | ```xml
148 | <Stack var.count="{0}" var.increment="{() => count++}">
149 |   <Button onClick="increment()" label="Count: {count}" />
150 | </Stack>
151 | ```
152 | 
153 | Variables and functions can also be defined in `<script>` tags:
154 | 
155 | ```xml
156 | <Stack>
157 |   <script>
158 |     let count = 0;
159 |     const increment = () => count++;
160 |     function reset() { count = 0; }
161 |   </script>
162 |   <Button onClick="increment()" label="Count: {count}" />
163 |   <Button onClick="reset()" label="Reset" />
164 | </Stack>
165 | ```
166 | 
167 | **Role in Reactivity**: Variables provide the state storage layer for reactive data binding. When a variable changes, the container detects this through proxy-based change detection and triggers selective UI updates. Functions participate in dependency tracking - when they reference other variables, the system tracks these dependencies and re-evaluates when dependencies change.
168 | 
169 | ### Loaders (`loaders`)
170 | Loaders are XMLUI's mechanism for handling asynchronous data operations. The framework automatically creates loaders when it recognizes that components contain data-handling requirements. This happens through the **ApiBoundComponent** system.
171 | 
172 | **Automatic Loader Creation Cases:**
173 | 
174 | 1. **Properties with DataSource/DataSourceRef types**: When a component property contains a `DataSource` or `DataSourceRef` object
175 | 2. **Events with API action types**: When a component event contains `APICall`, `FileDownload`, or `FileUpload` objects
176 | 3. **Components with data properties**: Any component with URL-based `data` properties
177 | 
178 | ```xml
179 | <!-- Property-based loader creation -->
180 | <Table data="{users}" />
181 | <!-- Framework creates internal DataLoader when 'users' references a DataSource -->
182 | 
183 | <!-- Direct URL pattern (frequently used) -->
184 | <Table data="/api/users" />
185 | <!-- Framework automatically creates DataLoader for URL-based data properties -->
186 | 
187 | <!-- Event-based loader creation -->  
188 | <Button>
189 |   Save
190 |   <event name="click">
191 |     <APICall url="/api/save" method="POST" />
192 |   </event>
193 | </Button>
194 | <!-- Framework creates APICall handler -->
195 | 
196 | <!-- Explicit DataSource (also creates loaders) -->
197 | <DataSource id="users" url="/api/users" />
198 | <Table data="{users}" />
199 | <!-- Creates DataLoader managing: loading states, error states, caching, polling -->
200 | ```
201 | 
202 | **Framework Detection Process**: The `ComponentAdapter` scans component properties and events for specific object types that require API operations. It looks for:
203 | - **Properties**: Objects with `type: "DataSource"` or `type: "DataSourceRef"`  
204 | - **Events**: Objects with `type: "APICall"`, `type: "FileDownload"`, or `type: "FileUpload"`
205 | 
206 | When any of these object types are found, the framework wraps the component in an `ApiBoundComponent`, which automatically generates the necessary loaders and wires them into the container system.
207 | 
208 | **Role in Reactivity**: Loaders manage asynchronous state transitions (loading → loaded/error) and integrate with the container's reducer system via actions like `LOADER_LOADED`, `LOADER_IN_PROGRESS_CHANGED`, etc. They provide reactive properties like `users.value`, `users.inProgress`, `users.loaded`.
209 | 
210 | ### Uses Declarations (`uses`)
211 | The `uses` property provides explicit control over state inheritance from parent containers:
212 | 
213 | ```xml
214 | <!-- Inherit all parent state (default) -->
215 | <Stack>
216 |   <!-- children -->
217 | </Stack>
218 | 
219 | <!-- Inherit no parent state -->
220 | <Stack uses="[]">
221 |   <!-- children -->
222 | </Stack>
223 | 
224 | <!-- Inherit only specific parent state -->
225 | <Stack uses="['userInfo', 'theme']">
226 |   <!-- children -->
227 | </Stack>
228 | ```
229 | 
230 | **Note**: XMLUI is moving toward automating the use of `uses` declarations, with plans to eliminate this property in favor of automatic dependency detection.
231 | 
232 | **Role in Reactivity**: Controls the scope of reactive data flow between parent and child containers. This prevents unnecessary re-renders when unrelated parent state changes and provides explicit data dependencies.
233 | 
234 | ### Context Variables
235 | Context variables are automatically injected by the framework and component implementations to provide contextual information to child components. These cannot be declared through attributes but are provided by the React implementation of XMLUI components.
236 | 
237 | **Naming Convention**: Context variables start with `$` by convention to distinguish them from user-defined variables.
238 | 
239 | **Examples of Context Variables** (not exhaustive):
240 | - **Routing**: `$pathname`, `$routeParams`, `$queryParams`, `$linkInfo`
241 | - **Iterators**: `$item`, `$itemIndex` (in Lists, Tables, etc.)
242 | - **Forms**: `$data`, `$validationResult`, `$value`, `$setValue` (in FormItems)
243 | - **Events**: `$param` (in event handlers)
244 | 
245 | Different components may inject additional context variables specific to their functionality.
246 | 
247 | ```xml
248 | <!-- Context variables are automatically available -->
249 | <Table data="/api/users">
250 |   <Column bindTo="name">
251 |     <Text>{$item.name}</Text>  <!-- $item provided by Table -->
252 |   </Column>
253 | </Table>
254 | 
255 | <Page url="/users/:id">
256 |   <Text>User ID: {$routeParams.id}</Text>  <!-- $routeParams provided by Page -->
257 | </Page>
258 | ```
259 | 
260 | **Role in Reactivity**: Context variables are automatically injected into the container state, making them available for reactive data binding. When these variables change (e.g., route changes, current item changes), all dependent UI elements automatically update.
261 | 
262 | ### Scripts
263 | JavaScript code blocks that declare variables and functions:
264 | 
265 | ```xml
266 | <Stack>
267 |   <script>
268 |     var counter = 0;
269 |     function increment() { counter++; }
270 |     var multiplier = (x) => x * 2;
271 |   </script>
272 |   <Button onClick="increment()" label="Count: {counter}" />
273 | </Stack>
274 | ```
275 | 
276 | **Role in Reactivity**: Scripts are parsed and their declarations (variables, functions) become part of the container's reactive state. The scripting system integrates with the dependency tracking and memoization systems to ensure efficient updates.
277 | 
278 | ### Code-Behind Files
279 | Code-behind files provide a way to define scripts in separate files rather than inline within components. The framework automatically treats these external script files as if they were `<script>` declarations within the application root or user-defined component root.
280 | 
281 | **File Naming Convention:**
282 | - **Application Root**: `Main.xmlui.xs` (for `Main.xmlui`)
283 | - **User-Defined Component**: `ComponentName.xmlui.xs` (for `ComponentName.xmlui`)
284 | 
285 | **Role in Reactivity**: Code-behind files are processed identically to inline `<script>` blocks. Their variable and function declarations become part of the container's reactive state, with the same dependency tracking and memoization behavior. The framework automatically imports and executes code-behind files during component initialization, making their exports available in the component's reactive scope.
286 | 
287 | ### Examples
288 | 
289 | **Important**: Simply having an `id` attribute does NOT automatically create a container. Component IDs are handled differently and are stored in the nearest parent container.
290 | 
291 | Components are wrapped in containers when they have any of these characteristics (determined by the `isContainerLike` function):
292 | 
293 | ```tsx
294 | // From ContainerWrapper.tsx - Container creation logic
295 | export function isContainerLike(node: ComponentDef) {
296 |   if (node.type === "Container") {
297 |     return true;
298 |   }
299 | 
300 |   // If any of the following properties have a value, we need a container
301 |   return !!(
302 |     node.loaders ||      // Data loading operations
303 |     node.vars ||         // Variable declarations  
304 |     node.uses ||         // Parent state scoping
305 |     node.contextVars ||  // Context variable provision
306 |     node.functions ||    // Function declarations
307 |     node.scriptCollected // Script blocks
308 |   );
309 | }
310 | ```
311 | 
312 | **Container Creation Examples:**
313 | ```xml
314 | <!-- Creates container - has variable -->
315 | <Stack var.count="{0}" />
316 | 
317 | <!-- Creates container - has script -->
318 | <Stack>
319 |   <script>let x = 1;</script>
320 | </Stack>
321 | 
322 | <!-- Creates container - has data loading -->
323 | <Table data="/api/users" />
324 | 
325 | <!-- Does NOT create container - only has ID -->
326 | <Stack id="myStack" />
327 | 
328 | <!-- Does NOT create container - only layout properties -->
329 | <Stack direction="horizontal" />
330 | ```
331 | 
332 | ## Container Structure, Hierarchy, and Features
333 | 
334 | This section explores the architectural design of containers, their hierarchical organization, and how they support XMLUI's special concepts like loaders, user-defined components, and reactive variables.
335 | 
336 | ### Container Hierarchy
337 | 
338 | The container system consists of three main React components working together:
339 | 
340 | ```
341 | ContainerWrapper
342 | └── ErrorBoundary
343 |     └── StateContainer  
344 |         └── ErrorBoundary
345 |             └── Container
346 | ```
347 | 
348 | ### Core Container Components
349 | 
350 | #### ContainerWrapper
351 | - **Purpose**: Outer wrapper that converts components into containerized form
352 | - **Location**: `/xmlui/src/components-core/rendering/ContainerWrapper.tsx`
353 | - **Key Responsibility**: Determines if a component needs containerization and wraps it accordingly
354 | 
355 | Components are wrapped in containers if they have any of these characteristics:
356 | - Loaders (data management operations)
357 | - Variables declared (`vars`)  
358 | - Context variables (`contextVars`)
359 | - Scripts (`script` or `scriptCollected`)
360 | - Explicit state usage declarations (`uses` property)
361 | 
362 | #### StateContainer
363 | - **Purpose**: Manages the actual state storage and state composition
364 | - **Location**: `/xmlui/src/components-core/rendering/StateContainer.tsx`
365 | - **Key Responsibility**: Assembles state from multiple sources and manages state lifecycle
366 | 
367 | #### Container
368 | - **Purpose**: Executes event handlers and manages state changes while maintaining UI responsiveness
369 | - **Location**: `/xmlui/src/components-core/rendering/Container.tsx`
370 | - **Key Responsibility**: Asynchronous event handler execution and state synchronization
371 | 
372 | ## State Composition and Management
373 | 
374 | ### ContainerState Type
375 | 
376 | ```typescript
377 | // From /xmlui/src/abstractions/ContainerDefs.ts
378 | export type ContainerState = Record<string | symbol, any>;
379 | ```
380 | 
381 | ### State Assembly Process
382 | 
383 | The `StateContainer` assembles the complete state from multiple layers:
384 | 
385 | 1. **State from Parent**: Inherited state from parent containers (with optional scoping via `uses`)
386 | 2. **Component APIs**: Exposed component methods and properties  
387 | 3. **Local Variables**: Variables declared in the current component
388 | 4. **Context Variables**: Variables provided to child components
389 | 5. **Routing Parameters**: URL parameters, query strings, and navigation context
390 | 
391 | ### State Flow Implementation
392 | 
393 | ```typescript
394 | // Simplified flow from StateContainer.tsx
395 | const stateFromOutside = extractScopedState(parentState, node.uses);
396 | const componentStateWithApis = mergeComponentApis(componentState, componentApis);
397 | const localVarsStateContext = useCombinedState(stateFromOutside, componentStateWithApis, node.contextVars);
398 | const resolvedLocalVars = useVars(varDefinitions, functionDeps, localVarsStateContext, memoedVars);
399 | const mergedWithVars = useMergedState(resolvedLocalVars, componentStateWithApis);
400 | 
401 | // State priority order (later overrides earlier):
402 | // 1. stateFromOutside (parent state - lowest priority)
403 | // 2. node.contextVars (context variables like $item)
404 | // 3. mergedWithVars (local vars + component APIs - highest priority)
405 | const combinedState = useCombinedState(
406 |   stateFromOutside,      // Parent state (lowest priority) - allows shadowing
407 |   node.contextVars,      // Context vars
408 |   mergedWithVars,        // Local vars and component APIs (highest priority) - enables shadowing
409 |   routingParams          // Routing parameters
410 | );
411 | ```
412 | 
413 | **State Shadowing**: The priority order allows local variables to shadow (override) parent state variables with the same name. This enables child containers to define their own versions of variables without being forced to use the parent's state, supporting better component encapsulation.
414 | 
415 | ### Variable Resolution and Memoization
416 | 
417 | Variables are resolved through a sophisticated memoization system:
418 | 
419 | ```typescript
420 | // From StateContainer.tsx - useVars function
421 | type MemoedVars = Map<any, {
422 |   getDependencies: (value: string | CodeDeclaration, referenceTrackedApi: Record<string, ComponentApi>) => Array<string>;
423 |   obtainValue: (expression: any, state: ContainerState, appContext: AppContextObject | undefined, strict: boolean | undefined, stateDeps: Record<string, any>, appContextDeps: Record<string, any>) => any;
424 | }>;
425 | ```
426 | 
427 | #### Variable Dependency Tracking
428 | 
429 | 1. **Function Dependencies**: Arrow expressions and their variable dependencies are collected first
430 | 2. **Variable Dependencies**: Dependencies between variables are resolved in multiple passes
431 | 3. **Memoization**: Results are memoized based on dependency changes to avoid unnecessary recalculation
432 | 
433 | ## Reducer-Based State Updates
434 | 
435 | ### Container Actions
436 | 
437 | State changes are managed through Redux-style actions via the `ContainerActionKind` enum:
438 | 
439 | ```typescript
440 | // From /xmlui/src/components-core/rendering/containers.ts
441 | export const enum ContainerActionKind {
442 |   LOADER_LOADED = "ContainerActionKind:LOADER_LOADED",
443 |   LOADER_IN_PROGRESS_CHANGED = "ContainerActionKind:LOADER_IN_PROGRESS_CHANGED", 
444 |   LOADER_IS_REFETCHING_CHANGED = "ContainerActionKind:LOADER_IS_REFETCHING_CHANGED",
445 |   LOADER_ERROR = "ContainerActionKind:LOADER_ERROR",
446 |   EVENT_HANDLER_STARTED = "ContainerActionKind:EVENT_HANDLER_STARTED",
447 |   EVENT_HANDLER_COMPLETED = "ContainerActionKind:EVENT_HANDLER_COMPLETED",
448 |   EVENT_HANDLER_ERROR = "ContainerActionKind:EVENT_HANDLER_ERROR", 
449 |   COMPONENT_STATE_CHANGED = "ContainerActionKind:COMPONENT_STATE_CHANGED",
450 |   STATE_PART_CHANGED = "ContainerActionKind:STATE_PART_CHANGED",
451 | }
452 | ```
453 | 
454 | #### Event Handler State Preservation
455 | 
456 | The event handler lifecycle actions (`EVENT_HANDLER_STARTED`, `EVENT_HANDLER_COMPLETED`, `EVENT_HANDLER_ERROR`) implement a critical state preservation pattern. When setting lifecycle flags like `inProgress` or `error`, the reducer checks if state already exists for the component's `uid`:
457 | 
458 | ```typescript
459 | // From reducer.ts - state preservation pattern
460 | case ContainerActionKind.EVENT_HANDLER_STARTED:
461 |   state[uid] = state[uid] 
462 |     ? { ...state[uid], [inProgressFlagName]: true }
463 |     : { [inProgressFlagName]: true };
464 |   break;
465 | ```
466 | 
467 | **Why This Matters**: Components with reducer state (like `DataSource` or `APICall`) maintain their `data`, `error`, and other properties throughout the event handler lifecycle. Without this preservation, setting the `inProgress` flag would replace the entire state object, losing critical data like loaded results or previous errors. This fix resolved issues where APIs would become non-functional after their first error because the state was being wiped out instead of updated.
468 | 
469 | ### Partial State Changes
470 | 
471 | The most sophisticated action is `STATE_PART_CHANGED`, which handles deep object/array mutations:
472 | 
473 | ```typescript
474 | // Example: Updating nested property some.count++
475 | {
476 |   "type": "ContainerActionKind:STATE_PART_CHANGED",
477 |   "payload": {
478 |     "actionType": "set",
479 |     "path": ["some", "count"],
480 |     "target": { "count": 0 },
481 |     "value": 1,
482 |     "localVars": resolvedLocalVars
483 |   }
484 | }
485 | ```
486 | 
487 | The reducer uses Lodash's `setWith` to update nested paths while preserving object vs array types based on target structure.
488 | 
489 | ## Proxy-Based Change Detection
490 | 
491 | ### BuildProxy Function
492 | 
493 | State changes are detected using JavaScript Proxies that intercept get/set operations:
494 | 
495 | ```typescript
496 | // From /xmlui/src/components-core/rendering/buildProxy.ts
497 | export function buildProxy(
498 |   proxyTarget: any,
499 |   callback: (changeInfo: ProxyCallbackArgs) => void,
500 |   tree: Array<string | symbol> = [],
501 | ): any {
502 |   return new Proxy(proxyTarget, {
503 |     get: function (target, prop, receiver) {
504 |       const value = Reflect.get(target, prop, receiver);
505 |       // Create nested proxies for objects and arrays
506 |       if (value && typeof value === "object" && ["Array", "Object"].includes(value.constructor.name)) {
507 |         if (!proxiedValues.has(value)) {
508 |           proxiedValues.set(value, buildProxy(value, callback, tree.concat(prop)));
509 |         }
510 |         return proxiedValues.get(value);
511 |       }
512 |       return value;
513 |     },
514 |     set: function (target, prop, value, receiver) {
515 |       // Notify of state changes
516 |       callback({
517 |         action: "set", 
518 |         path: getPath(prop),
519 |         pathArray: tree.concat(prop),
520 |         target,
521 |         newValue: value,
522 |         previousValue: Reflect.get(target, prop, receiver),
523 |       });
524 |       return Reflect.set(target, prop, value, receiver);
525 |     }
526 |   });
527 | }
528 | ```
529 | 
530 | ### Change Propagation
531 | 
532 | When a proxied state change occurs:
533 | 
534 | 1. **Detection**: Proxy intercepts the change and calls the callback
535 | 2. **Path Analysis**: Determines if the change belongs to current container or parent
536 | 3. **Dispatch**: Sends `STATE_PART_CHANGED` action to appropriate container
537 | 4. **Reduction**: Immer-based reducer applies the change immutably
538 | 5. **Re-render**: React re-renders affected components
539 | 
540 | ## Component Identification and APIs
541 | 
542 | ### Symbol-Based Component IDs
543 | 
544 | Components within containers are identified using JavaScript Symbols:
545 | 
546 | ```typescript
547 | // Component ID resolution
548 | const componentUid = componentId ?? Symbol(id);
549 | if (id) {
550 |   componentUid.description = id; // For debugging and API access
551 | }
552 | ```
553 | 
554 | ### Component ID Storage vs Accessibility
555 | 
556 | A key insight about XMLUI's component management is understanding where component IDs are stored, how they flow through the container hierarchy, and what happens when a component has an ID but doesn't create its own container.
557 | 
558 | **Component ID Creation and Storage Flow**
559 | 
560 | 1. **Universal ID Assignment**: ALL components receive a unique Symbol-based ID, regardless of whether they create containers:
561 | 
562 | ```tsx
563 | // From ComponentAdapter.tsx - every component gets a UID
564 | const uid = useMemo(() => Symbol(safeNode.uid), [safeNode.uid]);
565 | ```
566 | 
567 | 2. **Container vs Non-Container Components**:
568 |    - **Components that create containers**: Store their child component IDs in their own `componentApis` state
569 |    - **Components that DON'T create containers**: Their IDs are stored in the nearest parent container
570 | 
571 | 3. **Registration Mechanism**: Components register their APIs (including their ID) with the nearest container:
572 | 
573 | ```tsx
574 | // From ComponentAdapter.tsx - all components register with nearest container
575 | const memoedRegisterComponentApi: RegisterComponentApiFn = useCallback(
576 |   (api) => {
577 |     registerComponentApi(uid, api);  // Registers with nearest parent container
578 |   },
579 |   [registerComponentApi, uid],
580 | );
581 | ```
582 | 
583 | 4. **Storage in Parent Container**: The `StateContainer` maintains a `componentApis` map:
584 | 
585 | ```tsx
586 | // From StateContainer.tsx - parent container stores all child component IDs
587 | const registerComponentApi: RegisterComponentApiFnInner = useCallback((uid, api) => {
588 |   setComponentApis(produce((draft) => {
589 |     if (!draft[uid]) {
590 |       draft[uid] = {};
591 |     }
592 |     Object.entries(api).forEach(([key, value]) => {
593 |       draft[uid][key] = value;
594 |     });
595 |   }));
596 | }, []);
597 | ```
598 | 
599 | **Global Access Through State Composition**
600 | Even though component IDs are stored hierarchically, they become accessible file-wide through state inheritance:
601 | 
602 | ```tsx
603 | // From StateContainer.tsx - state flows down through hierarchy
604 | const combinedState = useCombinedState(
605 |   stateFromOutside,      // Parent state (contains parent component IDs)
606 |   node.contextVars,      // Framework context variables
607 |   mergedWithVars,        // Local variables and component state  
608 |   routingParams,         // Routing parameters
609 | );
610 | ```
611 | 
612 | **Example Scenarios**:
613 | 
614 | 1. **Component with ID but no container**:
615 | ```xml
616 | <Stack var.count="{0}">           <!-- Creates container A -->
617 |   <Button id="myBtn" />           <!-- ID stored in container A -->
618 |   <Text id="myText" />            <!-- ID also stored in container A -->
619 | </Stack>
620 | ```
621 | 
622 | 2. **Nested containers with inheritance**:
623 | ```xml
624 | <Stack var.count="{0}">           <!-- Creates container A -->
625 |   <Button id="myBtn" />           <!-- ID stored in container A -->
626 |   <Stack var.data="{null}">       <!-- Creates container B -->
627 |     <Text>{myBtn.visible}</Text>  <!-- Can access myBtn via state inheritance -->
628 |     <Button id="innerBtn" />      <!-- ID stored in container B -->
629 |   </Stack>
630 | </Stack>
631 | ```
632 | 
633 | **Storage and Access Pattern**:
634 | - `myBtn` and `myText` IDs are stored in container A's `componentApis` (they don't create their own containers)
635 | - `innerBtn` ID is stored in container B's `componentApis`
636 | - Container B inherits parent state through `stateFromOutside`, making `myBtn` accessible
637 | - All components can reference each other within the same .xmlui file through the state inheritance chain
638 | 
639 | **Root Component Storage**: 
640 | If `<Stack id="myStack" />` is a root component that doesn't create its own container, its ID is stored in the automatically-created root container. XMLUI ensures there's always at least one container in the hierarchy to store component IDs.
641 | 
642 | This design ensures that:
643 | - **Performance**: Each container only manages its direct responsibility
644 | - **Usability**: All components within a .xmlui file can reference each other
645 | - **Consistency**: Component IDs flow predictably through the container hierarchy
646 | - **Reliability**: There's always a root container to store component IDs, even for simple root components
647 | 
648 | ### Component API Registration
649 | 
650 | Components can expose APIs that other components can invoke:
651 | 
652 | ```typescript
653 | // From StateContainer.tsx
654 | const registerComponentApi: RegisterComponentApiFnInner = useCallback((uid, api) => {
655 |   setComponentApis(produce((draft) => {
656 |     if (!draft[uid]) {
657 |       draft[uid] = {};
658 |     }
659 |     Object.entries(api).forEach(([key, value]) => {
660 |       if (draft[uid][key] !== value) {
661 |         draft[uid][key] = value;
662 |       }
663 |     });
664 |   }));
665 | }, []);
666 | ```
667 | 
668 | APIs are merged into the component state so they're accessible via the component's ID:
669 | 
670 | ```typescript
671 | // API access pattern
672 | componentStateWithApis[componentId] = { ...componentState, ...exposedApi };
673 | ```
674 | 
675 | #### API State Scoping
676 | 
677 | Component API state (particularly reducer state from loaders like `DataSource` or `APICall`) is carefully scoped to prevent state leakage between containers. When component APIs are exposed as string keys in the container state (using the component's `id` as the key), the StateContainer only includes reducer state for APIs that are actually registered within that specific container.
678 | 
679 | **Implementation**: The StateContainer maintains a Set of registered API keys and filters which reducer state properties are copied to string keys:
680 | 
681 | ```typescript
682 | // From StateContainer.tsx - API state scoping
683 | const registeredApiKeys = new Set<string>();
684 | for (const sym of Object.getOwnPropertySymbols(componentApis)) {
685 |   if (sym.description) {
686 |     registeredApiKeys.add(sym.description);
687 |   }
688 | }
689 | 
690 | // Only copy reducer state if the API is registered in this container
691 | for (const key of Object.keys(componentState)) {
692 |   if (registeredApiKeys.has(key)) {
693 |     ret[key] = { ...(ret[key] || {}), ...componentState[key] };
694 |   }
695 | }
696 | ```
697 | 
698 | **Benefit**: This prevents child containers from inheriting parent API reducer state. For example, if a parent has a `DataSource` with `id="users"`, child containers won't see `users.inProgress`, `users.error`, or other reducer properties unless they register their own API with that ID. This ensures clean separation and prevents confusing state interactions.
699 | 
700 | ## Asynchronous Event Handler Execution
701 | 
702 | ### UI Responsiveness Strategy
703 | 
704 | The Container component maintains UI responsiveness during long-running operations through:
705 | 
706 | 1. **Async Instruction Execution**: Each instruction in an event handler runs asynchronously
707 | 2. **State Synchronization Points**: Execution pauses after each instruction for state updates
708 | 3. **Promise-Based Coordination**: Uses promises to coordinate when state changes are committed
709 | 4. **Transition-Based Updates**: Uses React's `startTransition` for non-urgent updates
710 | 
711 | ### Execution Flow
712 | 
713 | ```typescript
714 | // Simplified execution pattern from Container.tsx
715 | const executeHandler = async (statements: Statement[], options: ExecutionOptions) => {
716 |   for (const statement of statements) {
717 |     // Execute statement
718 |     await processStatement(statement, evalContext);
719 |     
720 |     // Collect state changes
721 |     if (changes.length > 0) {
722 |       // Dispatch state changes
723 |       changes.forEach(change => {
724 |         statePartChanged(change.pathArray, change.newValue, change.target, change.action);
725 |       });
726 |       
727 |       // Create promise for this statement
728 |       const statementPromise = new Promise(resolve => {
729 |         statementPromiseResolvers.current.set(statementId, resolve);
730 |       });
731 |       
732 |       // Increment version to trigger re-render
733 |       startTransition(() => {
734 |         setVersion(prev => prev + 1);
735 |       });
736 |       
737 |       // Wait for state to be committed
738 |       await statementPromise;
739 |     }
740 |   }
741 | };
742 | ```
743 | 
744 | ### Version-Based Synchronization
745 | 
746 | The Container uses a version counter to coordinate state updates:
747 | 
748 | ```typescript
749 | // When version changes, resolve pending promises
750 | useEffect(() => {
751 |   // Resolve all pending statement promises
752 |   statementPromiseResolvers.current.forEach(resolve => resolve());
753 |   statementPromiseResolvers.current.clear();
754 | }, [version]);
755 | ```
756 | 
757 | ## State Scoping and Inheritance
758 | 
759 | ### Parent State Extraction
760 | 
761 | Child containers can limit which parent state they receive:
762 | 
763 | ```typescript
764 | // From StateContainer.tsx
765 | function extractScopedState(parentState: ContainerState, uses?: string[]): ContainerState | undefined {
766 |   if (!uses) {
767 |     return parentState; // Inherit all parent state
768 |   }
769 |   if (uses.length === 0) {
770 |     return EMPTY_OBJECT; // Inherit no parent state  
771 |   }
772 |   return pick(parentState, uses); // Inherit only specified keys
773 | }
774 | ```
775 | 
776 | ### Context Variables
777 | 
778 | Containers can provide context variables to their children:
779 | 
780 | ```typescript
781 | // contextVars flow down to child containers automatically
782 | const localVarsStateContext = useCombinedState(
783 |   stateFromOutside,
784 |   componentStateWithApis, 
785 |   node.contextVars // These become available to children
786 | );
787 | ```
788 | 
789 | ### State Merging Strategies
790 | 
791 | Different merging strategies are used for different state layers:
792 | 
793 | 1. **Override**: Higher-priority state overrides lower-priority (`useCombinedState`)
794 | 2. **Merge**: Object and array values are deep-merged (`useMergedState`)
795 | 3. **Replace**: Simple values replace entirely
796 | 
797 | ## Routing Integration
798 | 
799 | ### Routing Parameters as State
800 | 
801 | Routing information is automatically injected into container state:
802 | 
803 | ```typescript
804 | // From StateContainer.tsx - useRoutingParams
805 | const routingParams = useMemo(() => {
806 |   return {
807 |     $pathname: location.pathname,
808 |     $routeParams: routeParams,      // URL parameters like :id
809 |     $queryParams: queryParamsMap,   // Query string parameters
810 |     $linkInfo: linkInfo,            // Navigation context
811 |   };
812 | }, [linkInfo, location.pathname, queryParamsMap, routeParams]);
813 | ```
814 | 
815 | These are automatically available in all containers as context variables.
816 | 
817 | ## Error Boundaries and Resilience
818 | 
819 | ### Layered Error Protection
820 | 
821 | The container system has multiple error boundaries:
822 | 
823 | 1. **Container-Level**: Protects StateContainer from Container errors
824 | 2. **StateContainer-Level**: Protects parent containers from child container errors  
825 | 3. **Component-Level**: Individual component errors don't crash containers
826 | 
827 | ### State Preservation
828 | 
829 | If a Container crashes during event handler execution, the StateContainer preserves its state, allowing recovery or graceful degradation.
830 | 
831 | ## Performance Optimizations
832 | 
833 | ### Memoization Strategies
834 | 
835 | 1. **Component Memoization**: Container components are memoized to prevent unnecessary re-renders
836 | 2. **Variable Memoization**: Variable resolution results are cached based on dependencies
837 | 3. **Shallow Comparison**: State objects use shallow comparison for change detection
838 | 4. **Reference Tracking**: Proxy objects maintain stable references for nested access
839 | 
840 | ### Change Detection Optimizations
841 | 
842 | 1. **Path-Based Updates**: Only affected parts of state tree are updated
843 | 2. **Dependency Tracking**: Variables are only re-evaluated when their dependencies change
844 | 3. **Batch Updates**: Multiple changes in single instruction are batched together
845 | 4. **Transition Updates**: Non-urgent updates use React transitions for better performance
846 | 
847 | ## Debugging Support
848 | 
849 | ### State Transition Logging
850 | 
851 | The container reducer can log state transitions for debugging:
852 | 
853 | ```typescript
854 | // From reducer.ts
855 | export function createContainerReducer(debugView: IDebugViewContext) {
856 |   const allowLogging = debugView.collectStateTransitions;
857 |   // ... logging implementation
858 | }
859 | ```
860 | 
861 | ### Component Keys and Resolution
862 | 
863 | Components receive resolved keys for debugging and tracking:
864 | 
865 | ```typescript
866 | // From renderChild.tsx  
867 | const key = extractParam(state, node.uid, appContext, true);
868 | return (
869 |   <ComponentWrapper
870 |     key={key}
871 |     resolvedKey={key} // For debugging container parent chains
872 |     // ...
873 |   />
874 | );
875 | ```
876 | 
877 | ## Integration Points
878 | 
879 | ### DataSource Integration
880 | 
881 | DataSource components integrate with the container system through loader actions:
882 | 
883 | ```typescript
884 | // Loader state management
885 | dispatch({
886 |   type: ContainerActionKind.LOADER_LOADED,
887 |   payload: {
888 |     uid: dataSourceUid,
889 |     data: fetchedData,
890 |     pageInfo: paginationInfo
891 |   }
892 | });
893 | ```
894 | 
895 | ### Form Integration
896 | 
897 | Form components manage their state through the container system while maintaining their own internal state for performance.
898 | 
899 | ### API Integration
900 | 
901 | Component APIs are registered with containers and become part of the state, making them accessible to other components via component IDs.
902 | 
903 | ## Key Design Principles
904 | 
905 | 1. **Hierarchical Encapsulation**: State is scoped to container boundaries while allowing controlled inheritance
906 | 2. **Reactive Consistency**: All state changes automatically propagate to dependent UI elements
907 | 3. **Async Coordination**: Long-running operations don't block the UI thread
908 | 4. **Immutable Updates**: All state changes produce new immutable state objects
909 | 5. **Proxy Transparency**: State mutations are detected transparently without special syntax
910 | 6. **Error Isolation**: Component errors are contained and don't propagate to affect other parts of the application
911 | 
912 | This container-based architecture provides XMLUI with a robust, scalable state management solution that maintains the declarative programming model while handling complex state interactions and ensuring optimal performance characteristics.
```
Page 127/181FirstPrevNextLast