#
tokens: 46190/50000 2/1634 files (page 120/182)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 120 of 182. Use http://codebase.md/xmlui-org/xmlui/tools/vscode/resources/%7Bsrc%7D?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .changeset
│   ├── config.json
│   ├── cool-queens-look.md
│   ├── hot-berries-argue.md
│   ├── twelve-guests-care.md
│   └── wise-towns-dance.md
├── .eslintrc.cjs
├── .github
│   ├── build-checklist.png
│   ├── ISSUE_TEMPLATE
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows
│       ├── deploy-blog.yml
│       ├── deploy-docs-optimized.yml
│       ├── deploy-docs.yml
│       ├── prepare-versions.yml
│       ├── release-packages.yml
│       ├── run-all-tests.yml
│       └── run-smoke-tests.yml
├── .gitignore
├── .prettierrc.js
├── .vscode
│   ├── launch.json
│   └── settings.json
├── blog
│   ├── .gitignore
│   ├── .gitkeep
│   ├── CHANGELOG.md
│   ├── extensions.ts
│   ├── index.html
│   ├── index.ts
│   ├── package.json
│   ├── public
│   │   ├── blog
│   │   │   ├── images
│   │   │   │   ├── blog-page-component.png
│   │   │   │   ├── blog-scrabble.png
│   │   │   │   ├── integrated-blog-search.png
│   │   │   │   └── lorem-ipsum.png
│   │   │   ├── lorem-ipsum.md
│   │   │   ├── newest-post.md
│   │   │   ├── older-post.md
│   │   │   └── welcome-to-the-xmlui-blog.md
│   │   ├── mockServiceWorker.js
│   │   ├── netlify.toml
│   │   ├── resources
│   │   │   ├── favicon.ico
│   │   │   ├── files
│   │   │   │   └── for-download
│   │   │   │       └── xmlui
│   │   │   │           └── xmlui-standalone.umd.js
│   │   │   ├── github.svg
│   │   │   ├── llms.txt
│   │   │   ├── logo-dark.svg
│   │   │   ├── logo.svg
│   │   │   ├── pg-popout.svg
│   │   │   └── xmlui-logo.svg
│   │   ├── serve.json
│   │   └── web.config
│   ├── scripts
│   │   ├── download-latest-xmlui.js
│   │   ├── generate-rss.js
│   │   ├── get-releases.js
│   │   └── utils.js
│   ├── src
│   │   ├── components
│   │   │   ├── BlogOverview.xmlui
│   │   │   ├── BlogPage.xmlui
│   │   │   ├── Debug.xmlui
│   │   │   └── PageNotFound.xmlui
│   │   ├── config.ts
│   │   ├── Main.xmlui
│   │   ├── Main.xmlui.xs
│   │   └── themes
│   │       ├── docs-theme.ts
│   │       ├── earthtone.ts
│   │       ├── xmlui-gray-on-default.ts
│   │       ├── xmlui-green-on-default.ts
│   │       └── xmlui-orange-on-default.ts
│   └── tsconfig.json
├── CONTRIBUTING.md
├── docs
│   ├── .gitignore
│   ├── CHANGELOG.md
│   ├── ComponentRefLinks.txt
│   ├── content
│   │   ├── _meta.json
│   │   ├── components
│   │   │   ├── _meta.json
│   │   │   ├── _overview.md
│   │   │   ├── APICall.md
│   │   │   ├── App.md
│   │   │   ├── AppHeader.md
│   │   │   ├── AppState.md
│   │   │   ├── AutoComplete.md
│   │   │   ├── Avatar.md
│   │   │   ├── Backdrop.md
│   │   │   ├── Badge.md
│   │   │   ├── BarChart.md
│   │   │   ├── Bookmark.md
│   │   │   ├── Breakout.md
│   │   │   ├── Button.md
│   │   │   ├── Card.md
│   │   │   ├── Carousel.md
│   │   │   ├── ChangeListener.md
│   │   │   ├── Checkbox.md
│   │   │   ├── CHStack.md
│   │   │   ├── ColorPicker.md
│   │   │   ├── Column.md
│   │   │   ├── ContentSeparator.md
│   │   │   ├── CVStack.md
│   │   │   ├── DataSource.md
│   │   │   ├── DateInput.md
│   │   │   ├── DatePicker.md
│   │   │   ├── DonutChart.md
│   │   │   ├── DropdownMenu.md
│   │   │   ├── EmojiSelector.md
│   │   │   ├── ExpandableItem.md
│   │   │   ├── FileInput.md
│   │   │   ├── FileUploadDropZone.md
│   │   │   ├── FlowLayout.md
│   │   │   ├── Footer.md
│   │   │   ├── Form.md
│   │   │   ├── FormItem.md
│   │   │   ├── FormSection.md
│   │   │   ├── Fragment.md
│   │   │   ├── H1.md
│   │   │   ├── H2.md
│   │   │   ├── H3.md
│   │   │   ├── H4.md
│   │   │   ├── H5.md
│   │   │   ├── H6.md
│   │   │   ├── Heading.md
│   │   │   ├── HSplitter.md
│   │   │   ├── HStack.md
│   │   │   ├── Icon.md
│   │   │   ├── IFrame.md
│   │   │   ├── Image.md
│   │   │   ├── Items.md
│   │   │   ├── LabelList.md
│   │   │   ├── Legend.md
│   │   │   ├── LineChart.md
│   │   │   ├── Link.md
│   │   │   ├── List.md
│   │   │   ├── Logo.md
│   │   │   ├── Markdown.md
│   │   │   ├── MenuItem.md
│   │   │   ├── MenuSeparator.md
│   │   │   ├── ModalDialog.md
│   │   │   ├── NavGroup.md
│   │   │   ├── NavLink.md
│   │   │   ├── NavPanel.md
│   │   │   ├── NoResult.md
│   │   │   ├── NumberBox.md
│   │   │   ├── Option.md
│   │   │   ├── Page.md
│   │   │   ├── PageMetaTitle.md
│   │   │   ├── Pages.md
│   │   │   ├── Pagination.md
│   │   │   ├── PasswordInput.md
│   │   │   ├── PieChart.md
│   │   │   ├── ProgressBar.md
│   │   │   ├── Queue.md
│   │   │   ├── RadioGroup.md
│   │   │   ├── RealTimeAdapter.md
│   │   │   ├── Redirect.md
│   │   │   ├── Select.md
│   │   │   ├── Slider.md
│   │   │   ├── Slot.md
│   │   │   ├── SpaceFiller.md
│   │   │   ├── Spinner.md
│   │   │   ├── Splitter.md
│   │   │   ├── Stack.md
│   │   │   ├── StickyBox.md
│   │   │   ├── SubMenuItem.md
│   │   │   ├── Switch.md
│   │   │   ├── TabItem.md
│   │   │   ├── Table.md
│   │   │   ├── TableOfContents.md
│   │   │   ├── Tabs.md
│   │   │   ├── Text.md
│   │   │   ├── TextArea.md
│   │   │   ├── TextBox.md
│   │   │   ├── Theme.md
│   │   │   ├── TimeInput.md
│   │   │   ├── Timer.md
│   │   │   ├── ToneChangerButton.md
│   │   │   ├── ToneSwitch.md
│   │   │   ├── Tooltip.md
│   │   │   ├── Tree.md
│   │   │   ├── VSplitter.md
│   │   │   ├── VStack.md
│   │   │   ├── xmlui-animations
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   ├── Animation.md
│   │   │   │   ├── FadeAnimation.md
│   │   │   │   ├── FadeInAnimation.md
│   │   │   │   ├── FadeOutAnimation.md
│   │   │   │   ├── ScaleAnimation.md
│   │   │   │   └── SlideInAnimation.md
│   │   │   ├── xmlui-pdf
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   └── Pdf.md
│   │   │   ├── xmlui-spreadsheet
│   │   │   │   ├── _meta.json
│   │   │   │   ├── _overview.md
│   │   │   │   └── Spreadsheet.md
│   │   │   └── xmlui-website-blocks
│   │   │       ├── _meta.json
│   │   │       ├── _overview.md
│   │   │       ├── Carousel.md
│   │   │       ├── HelloMd.md
│   │   │       ├── HeroSection.md
│   │   │       └── ScrollToTop.md
│   │   └── extensions
│   │       ├── _meta.json
│   │       ├── xmlui-animations
│   │       │   ├── _meta.json
│   │       │   ├── _overview.md
│   │       │   ├── Animation.md
│   │       │   ├── FadeAnimation.md
│   │       │   ├── FadeInAnimation.md
│   │       │   ├── FadeOutAnimation.md
│   │       │   ├── ScaleAnimation.md
│   │       │   └── SlideInAnimation.md
│   │       └── xmlui-website-blocks
│   │           ├── _meta.json
│   │           ├── _overview.md
│   │           ├── Carousel.md
│   │           ├── HelloMd.md
│   │           ├── HeroSection.md
│   │           └── ScrollToTop.md
│   ├── extensions.ts
│   ├── index.html
│   ├── index.ts
│   ├── package.json
│   ├── public
│   │   ├── feed.rss
│   │   ├── mockServiceWorker.js
│   │   ├── pages
│   │   │   ├── _meta.json
│   │   │   ├── app-structure.md
│   │   │   ├── build-editor-component.md
│   │   │   ├── build-hello-world-component.md
│   │   │   ├── components-intro.md
│   │   │   ├── context-variables.md
│   │   │   ├── forms.md
│   │   │   ├── globals.md
│   │   │   ├── glossary.md
│   │   │   ├── helper-tags.md
│   │   │   ├── hosted-deployment.md
│   │   │   ├── howto
│   │   │   │   ├── assign-a-complex-json-literal-to-a-component-variable.md
│   │   │   │   ├── chain-a-refetch.md
│   │   │   │   ├── debug-a-component.md
│   │   │   │   ├── delay-a-datasource-until-another-datasource-is-ready.md
│   │   │   │   ├── delegate-a-method.md
│   │   │   │   ├── do-custom-form-validation.md
│   │   │   │   ├── expose-a-method-from-a-component.md
│   │   │   │   ├── filter-and-transform-data-from-an-api.md
│   │   │   │   ├── group-items-in-list-by-a-property.md
│   │   │   │   ├── handle-background-operations.md
│   │   │   │   ├── hide-an-element-until-its-datasource-is-ready.md
│   │   │   │   ├── make-a-set-of-equal-width-cards.md
│   │   │   │   ├── make-a-table-responsive.md
│   │   │   │   ├── 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
    │   ├── containers.md
    │   ├── glossary.md
    │   ├── index.md
    │   ├── next
    │   │   ├── component-dev-guide.md
    │   │   ├── configuration-management-enhancement-summary.md
    │   │   ├── documentation-scripts-refactoring-complete-summary.md
    │   │   ├── documentation-scripts-refactoring-plan.md
    │   │   ├── duplicate-pattern-extraction-summary.md
    │   │   ├── error-handling-standardization-summary.md
    │   │   ├── generating-component-reference.md
    │   │   ├── index.md
    │   │   ├── logging-consistency-implementation-summary.md
    │   │   ├── project-build.md
    │   │   ├── project-structure.md
    │   │   ├── theme-context.md
    │   │   ├── tiptap-design-considerations.md
    │   │   ├── working-with-code.md
    │   │   ├── xmlui-runtime-architecture
    │   │   └── xmlui-wcag-accessibility-report.md
    │   ├── react-fundamentals.md
    │   ├── release-method.md
    │   ├── standalone-app.md
    │   ├── state-management.md
    │   ├── 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
    │   │   │   ├── MultiSelectOption.tsx
    │   │   │   ├── OptionContext.ts
    │   │   │   ├── Select.md
    │   │   │   ├── Select.module.scss
    │   │   │   ├── Select.spec.ts
    │   │   │   ├── Select.tsx
    │   │   │   ├── SelectContext.tsx
    │   │   │   ├── SelectNative.tsx
    │   │   │   ├── SelectOption.tsx
    │   │   │   └── SimpleSelect.tsx
    │   │   ├── SelectionStore
    │   │   │   ├── SelectionStore.md
    │   │   │   ├── SelectionStore.tsx
    │   │   │   └── SelectionStoreNative.tsx
    │   │   ├── Slider
    │   │   │   ├── Slider.md
    │   │   │   ├── Slider.module.scss
    │   │   │   ├── Slider.spec.ts
    │   │   │   ├── Slider.tsx
    │   │   │   └── SliderNative.tsx
    │   │   ├── Slot
    │   │   │   ├── Slot.md
    │   │   │   ├── Slot.spec.ts
    │   │   │   └── Slot.ts
    │   │   ├── SlotItem.tsx
    │   │   ├── SpaceFiller
    │   │   │   ├── SpaceFiller.md
    │   │   │   ├── SpaceFiller.module.scss
    │   │   │   ├── SpaceFiller.spec.ts
    │   │   │   ├── SpaceFiller.tsx
    │   │   │   └── SpaceFillerNative.tsx
    │   │   ├── Spinner
    │   │   │   ├── Spinner.md
    │   │   │   ├── Spinner.module.scss
    │   │   │   ├── Spinner.spec.ts
    │   │   │   ├── Spinner.tsx
    │   │   │   └── SpinnerNative.tsx
    │   │   ├── Splitter
    │   │   │   ├── HSplitter.md
    │   │   │   ├── HSplitter.spec.ts
    │   │   │   ├── Splitter.md
    │   │   │   ├── Splitter.module.scss
    │   │   │   ├── Splitter.spec.ts
    │   │   │   ├── Splitter.tsx
    │   │   │   ├── SplitterNative.tsx
    │   │   │   ├── utils.ts
    │   │   │   ├── VSplitter.md
    │   │   │   └── VSplitter.spec.ts
    │   │   ├── Stack
    │   │   │   ├── CHStack.md
    │   │   │   ├── CHStack.spec.ts
    │   │   │   ├── CVStack.md
    │   │   │   ├── CVStack.spec.ts
    │   │   │   ├── HStack.md
    │   │   │   ├── HStack.spec.ts
    │   │   │   ├── Stack.md
    │   │   │   ├── Stack.module.scss
    │   │   │   ├── Stack.spec.ts
    │   │   │   ├── Stack.tsx
    │   │   │   ├── StackNative.tsx
    │   │   │   ├── VStack.md
    │   │   │   └── VStack.spec.ts
    │   │   ├── StickyBox
    │   │   │   ├── StickyBox.md
    │   │   │   ├── StickyBox.module.scss
    │   │   │   ├── StickyBox.tsx
    │   │   │   └── StickyBoxNative.tsx
    │   │   ├── Switch
    │   │   │   ├── Switch.md
    │   │   │   ├── Switch.spec.ts
    │   │   │   └── Switch.tsx
    │   │   ├── Table
    │   │   │   ├── doc-resources
    │   │   │   │   └── list-component-data.js
    │   │   │   ├── react-table-config.d.ts
    │   │   │   ├── Table.md
    │   │   │   ├── Table.module.scss
    │   │   │   ├── Table.spec.ts
    │   │   │   ├── Table.tsx
    │   │   │   ├── TableNative.tsx
    │   │   │   └── useRowSelection.tsx
    │   │   ├── TableOfContents
    │   │   │   ├── TableOfContents.module.scss
    │   │   │   ├── TableOfContents.spec.ts
    │   │   │   ├── TableOfContents.tsx
    │   │   │   └── TableOfContentsNative.tsx
    │   │   ├── Tabs
    │   │   │   ├── TabContext.tsx
    │   │   │   ├── TabItem.md
    │   │   │   ├── TabItem.tsx
    │   │   │   ├── TabItemNative.tsx
    │   │   │   ├── Tabs.md
    │   │   │   ├── Tabs.module.scss
    │   │   │   ├── Tabs.spec.ts
    │   │   │   ├── Tabs.tsx
    │   │   │   └── TabsNative.tsx
    │   │   ├── Text
    │   │   │   ├── Text.md
    │   │   │   ├── Text.module.scss
    │   │   │   ├── Text.spec.ts
    │   │   │   ├── Text.tsx
    │   │   │   └── TextNative.tsx
    │   │   ├── TextArea
    │   │   │   ├── TextArea.md
    │   │   │   ├── TextArea.module.scss
    │   │   │   ├── TextArea.spec.ts
    │   │   │   ├── TextArea.tsx
    │   │   │   ├── TextAreaNative.tsx
    │   │   │   ├── TextAreaResizable.tsx
    │   │   │   └── useComposedRef.ts
    │   │   ├── TextBox
    │   │   │   ├── TextBox.md
    │   │   │   ├── TextBox.module.scss
    │   │   │   ├── TextBox.spec.ts
    │   │   │   ├── TextBox.tsx
    │   │   │   └── TextBoxNative.tsx
    │   │   ├── Theme
    │   │   │   ├── NotificationToast.tsx
    │   │   │   ├── Theme.md
    │   │   │   ├── Theme.module.scss
    │   │   │   ├── Theme.spec.ts
    │   │   │   ├── Theme.tsx
    │   │   │   └── ThemeNative.tsx
    │   │   ├── TimeInput
    │   │   │   ├── TimeInput.md
    │   │   │   ├── TimeInput.module.scss
    │   │   │   ├── TimeInput.spec.ts
    │   │   │   ├── TimeInput.tsx
    │   │   │   ├── TimeInputNative.tsx
    │   │   │   └── utils.ts
    │   │   ├── Timer
    │   │   │   ├── Timer.md
    │   │   │   ├── Timer.spec.ts
    │   │   │   ├── Timer.tsx
    │   │   │   └── TimerNative.tsx
    │   │   ├── Toggle
    │   │   │   ├── Toggle.module.scss
    │   │   │   └── Toggle.tsx
    │   │   ├── ToneChangerButton
    │   │   │   ├── ToneChangerButton.md
    │   │   │   ├── ToneChangerButton.spec.ts
    │   │   │   └── ToneChangerButton.tsx
    │   │   ├── ToneSwitch
    │   │   │   ├── ToneSwitch.md
    │   │   │   ├── ToneSwitch.module.scss
    │   │   │   ├── ToneSwitch.spec.ts
    │   │   │   ├── ToneSwitch.tsx
    │   │   │   └── ToneSwitchNative.tsx
    │   │   ├── Tooltip
    │   │   │   ├── Tooltip.md
    │   │   │   ├── Tooltip.module.scss
    │   │   │   ├── Tooltip.spec.ts
    │   │   │   ├── Tooltip.tsx
    │   │   │   └── TooltipNative.tsx
    │   │   ├── Tree
    │   │   │   ├── testData.ts
    │   │   │   ├── Tree-dynamic.spec.ts
    │   │   │   ├── Tree-icons.spec.ts
    │   │   │   ├── Tree.md
    │   │   │   ├── Tree.spec.ts
    │   │   │   ├── TreeComponent.module.scss
    │   │   │   ├── TreeComponent.tsx
    │   │   │   └── TreeNative.tsx
    │   │   ├── TreeDisplay
    │   │   │   ├── TreeDisplay.md
    │   │   │   ├── TreeDisplay.module.scss
    │   │   │   ├── TreeDisplay.tsx
    │   │   │   └── TreeDisplayNative.tsx
    │   │   ├── ValidationSummary
    │   │   │   ├── ValidationSummary.module.scss
    │   │   │   └── ValidationSummary.tsx
    │   │   └── VisuallyHidden.tsx
    │   ├── components-core
    │   │   ├── abstractions
    │   │   │   ├── ComponentRenderer.ts
    │   │   │   ├── LoaderRenderer.ts
    │   │   │   ├── standalone.ts
    │   │   │   └── treeAbstractions.ts
    │   │   ├── action
    │   │   │   ├── actions.ts
    │   │   │   ├── APICall.tsx
    │   │   │   ├── FileDownloadAction.tsx
    │   │   │   ├── FileUploadAction.tsx
    │   │   │   ├── NavigateAction.tsx
    │   │   │   └── TimedAction.tsx
    │   │   ├── ApiBoundComponent.tsx
    │   │   ├── appContext
    │   │   │   ├── date-functions.ts
    │   │   │   ├── math-function.ts
    │   │   │   └── misc-utils.ts
    │   │   ├── AppContext.tsx
    │   │   ├── behaviors
    │   │   │   ├── Behavior.tsx
    │   │   │   └── CoreBehaviors.tsx
    │   │   ├── component-hooks.ts
    │   │   ├── ComponentDecorator.tsx
    │   │   ├── ComponentViewer.tsx
    │   │   ├── CompoundComponent.tsx
    │   │   ├── constants.ts
    │   │   ├── DebugViewProvider.tsx
    │   │   ├── descriptorHelper.ts
    │   │   ├── devtools
    │   │   │   ├── InspectorDialog.module.scss
    │   │   │   ├── InspectorDialog.tsx
    │   │   │   └── InspectorDialogVisibilityContext.tsx
    │   │   ├── EngineError.ts
    │   │   ├── event-handlers.ts
    │   │   ├── InspectorButton.module.scss
    │   │   ├── InspectorContext.tsx
    │   │   ├── interception
    │   │   │   ├── abstractions.ts
    │   │   │   ├── ApiInterceptor.ts
    │   │   │   ├── ApiInterceptorProvider.tsx
    │   │   │   ├── apiInterceptorWorker.ts
    │   │   │   ├── Backend.ts
    │   │   │   ├── Errors.ts
    │   │   │   ├── IndexedDb.ts
    │   │   │   ├── initMock.ts
    │   │   │   ├── InMemoryDb.ts
    │   │   │   ├── ReadonlyCollection.ts
    │   │   │   └── useApiInterceptorContext.tsx
    │   │   ├── loader
    │   │   │   ├── ApiLoader.tsx
    │   │   │   ├── DataLoader.tsx
    │   │   │   ├── ExternalDataLoader.tsx
    │   │   │   ├── Loader.tsx
    │   │   │   ├── MockLoaderRenderer.tsx
    │   │   │   └── PageableLoader.tsx
    │   │   ├── LoaderComponent.tsx
    │   │   ├── markup-check.ts
    │   │   ├── parts.ts
    │   │   ├── renderers.ts
    │   │   ├── rendering
    │   │   │   ├── AppContent.tsx
    │   │   │   ├── AppRoot.tsx
    │   │   │   ├── AppWrapper.tsx
    │   │   │   ├── buildProxy.ts
    │   │   │   ├── collectFnVarDeps.ts
    │   │   │   ├── ComponentAdapter.tsx
    │   │   │   ├── ComponentWrapper.tsx
    │   │   │   ├── Container.tsx
    │   │   │   ├── containers.ts
    │   │   │   ├── ContainerWrapper.tsx
    │   │   │   ├── ErrorBoundary.module.scss
    │   │   │   ├── ErrorBoundary.tsx
    │   │   │   ├── InvalidComponent.module.scss
    │   │   │   ├── InvalidComponent.tsx
    │   │   │   ├── nodeUtils.ts
    │   │   │   ├── reducer.ts
    │   │   │   ├── renderChild.tsx
    │   │   │   ├── StandaloneComponent.tsx
    │   │   │   ├── StateContainer.tsx
    │   │   │   ├── UnknownComponent.module.scss
    │   │   │   ├── UnknownComponent.tsx
    │   │   │   └── valueExtractor.ts
    │   │   ├── reportEngineError.ts
    │   │   ├── RestApiProxy.ts
    │   │   ├── script-runner
    │   │   │   ├── asyncProxy.ts
    │   │   │   ├── AttributeValueParser.ts
    │   │   │   ├── bannedFunctions.ts
    │   │   │   ├── BindingTreeEvaluationContext.ts
    │   │   │   ├── eval-tree-async.ts
    │   │   │   ├── eval-tree-common.ts
    │   │   │   ├── eval-tree-sync.ts
    │   │   │   ├── ParameterParser.ts
    │   │   │   ├── process-statement-async.ts
    │   │   │   ├── process-statement-common.ts
    │   │   │   ├── process-statement-sync.ts
    │   │   │   ├── ScriptingSourceTree.ts
    │   │   │   ├── simplify-expression.ts
    │   │   │   ├── statement-queue.ts
    │   │   │   └── visitors.ts
    │   │   ├── StandaloneApp.tsx
    │   │   ├── StandaloneExtensionManager.ts
    │   │   ├── TableOfContentsContext.tsx
    │   │   ├── theming
    │   │   │   ├── _themes.scss
    │   │   │   ├── component-layout-resolver.ts
    │   │   │   ├── extendThemeUtils.ts
    │   │   │   ├── hvar.ts
    │   │   │   ├── layout-resolver.ts
    │   │   │   ├── parse-layout-props.ts
    │   │   │   ├── StyleContext.tsx
    │   │   │   ├── StyleRegistry.ts
    │   │   │   ├── ThemeContext.tsx
    │   │   │   ├── ThemeProvider.tsx
    │   │   │   ├── themes
    │   │   │   │   ├── base-utils.ts
    │   │   │   │   ├── palette.ts
    │   │   │   │   ├── root.ts
    │   │   │   │   ├── solid.ts
    │   │   │   │   ├── theme-colors.ts
    │   │   │   │   └── xmlui.ts
    │   │   │   ├── themeVars.module.scss
    │   │   │   ├── themeVars.ts
    │   │   │   ├── transformThemeVars.ts
    │   │   │   └── utils.ts
    │   │   ├── utils
    │   │   │   ├── actionUtils.ts
    │   │   │   ├── audio-utils.ts
    │   │   │   ├── compound-utils.ts
    │   │   │   ├── css-utils.ts
    │   │   │   ├── DataLoaderQueryKeyGenerator.ts
    │   │   │   ├── date-utils.ts
    │   │   │   ├── extractParam.ts
    │   │   │   ├── hooks.tsx
    │   │   │   ├── LruCache.ts
    │   │   │   ├── mergeProps.ts
    │   │   │   ├── misc.ts
    │   │   │   ├── request-params.ts
    │   │   │   ├── statementUtils.ts
    │   │   │   └── treeUtils.ts
    │   │   └── xmlui-parser.ts
    │   ├── index-standalone.ts
    │   ├── index.scss
    │   ├── index.ts
    │   ├── language-server
    │   │   ├── server-common.ts
    │   │   ├── server-web-worker.ts
    │   │   ├── server.ts
    │   │   ├── services
    │   │   │   ├── common
    │   │   │   │   ├── docs-generation.ts
    │   │   │   │   ├── lsp-utils.ts
    │   │   │   │   ├── metadata-utils.ts
    │   │   │   │   └── syntax-node-utilities.ts
    │   │   │   ├── completion.ts
    │   │   │   ├── diagnostic.ts
    │   │   │   ├── format.ts
    │   │   │   └── hover.ts
    │   │   └── xmlui-metadata-generated.mjs
    │   ├── logging
    │   │   ├── LoggerContext.tsx
    │   │   ├── LoggerInitializer.tsx
    │   │   ├── LoggerService.ts
    │   │   └── xmlui.ts
    │   ├── logo.svg
    │   ├── parsers
    │   │   ├── common
    │   │   │   ├── GenericToken.ts
    │   │   │   ├── InputStream.ts
    │   │   │   └── utils.ts
    │   │   ├── scripting
    │   │   │   ├── code-behind-collect.ts
    │   │   │   ├── Lexer.ts
    │   │   │   ├── modules.ts
    │   │   │   ├── Parser.ts
    │   │   │   ├── ParserError.ts
    │   │   │   ├── ScriptingNodeTypes.ts
    │   │   │   ├── TokenTrait.ts
    │   │   │   ├── TokenType.ts
    │   │   │   └── tree-visitor.ts
    │   │   ├── style-parser
    │   │   │   ├── errors.ts
    │   │   │   ├── source-tree.ts
    │   │   │   ├── StyleInputStream.ts
    │   │   │   ├── StyleLexer.ts
    │   │   │   ├── StyleParser.ts
    │   │   │   └── tokens.ts
    │   │   └── xmlui-parser
    │   │       ├── CharacterCodes.ts
    │   │       ├── diagnostics.ts
    │   │       ├── fileExtensions.ts
    │   │       ├── index.ts
    │   │       ├── lint.ts
    │   │       ├── parser.ts
    │   │       ├── ParserError.ts
    │   │       ├── scanner.ts
    │   │       ├── syntax-kind.ts
    │   │       ├── syntax-node.ts
    │   │       ├── transform.ts
    │   │       ├── utils.ts
    │   │       ├── xmlui-serializer.ts
    │   │       └── xmlui-tree.ts
    │   ├── react-app-env.d.ts
    │   ├── syntax
    │   │   ├── monaco
    │   │   │   ├── grammar.monacoLanguage.ts
    │   │   │   ├── index.ts
    │   │   │   ├── xmlui-dark.ts
    │   │   │   ├── xmlui-light.ts
    │   │   │   └── xmluiscript.monacoLanguage.ts
    │   │   └── textMate
    │   │       ├── index.ts
    │   │       ├── xmlui-dark.json
    │   │       ├── xmlui-light.json
    │   │       ├── xmlui.json
    │   │       └── xmlui.tmLanguage.json
    │   ├── testing
    │   │   ├── assertions.ts
    │   │   ├── component-test-helpers.ts
    │   │   ├── ComponentDrivers.ts
    │   │   ├── drivers
    │   │   │   ├── DateInputDriver.ts
    │   │   │   ├── ModalDialogDriver.ts
    │   │   │   ├── NumberBoxDriver.ts
    │   │   │   ├── TextBoxDriver.ts
    │   │   │   ├── TimeInputDriver.ts
    │   │   │   ├── TimerDriver.ts
    │   │   │   └── TreeDriver.ts
    │   │   ├── fixtures.ts
    │   │   ├── infrastructure
    │   │   │   ├── index.html
    │   │   │   ├── main.tsx
    │   │   │   ├── public
    │   │   │   │   ├── mockServiceWorker.js
    │   │   │   │   ├── resources
    │   │   │   │   │   ├── bell.svg
    │   │   │   │   │   ├── box.svg
    │   │   │   │   │   ├── doc.svg
    │   │   │   │   │   ├── eye.svg
    │   │   │   │   │   ├── flower-640x480.jpg
    │   │   │   │   │   ├── sun.svg
    │   │   │   │   │   ├── test-image-100x100.jpg
    │   │   │   │   │   └── txt.svg
    │   │   │   │   └── serve.json
    │   │   │   └── TestBed.tsx
    │   │   └── themed-app-test-helpers.ts
    │   └── vite-env.d.ts
    ├── tests
    │   ├── components
    │   │   ├── CodeBlock
    │   │   │   └── hightlight-code.test.ts
    │   │   ├── playground-pattern.test.ts
    │   │   └── Tree
    │   │       └── Tree-states.test.ts
    │   ├── components-core
    │   │   ├── abstractions
    │   │   │   └── treeAbstractions.test.ts
    │   │   ├── container
    │   │   │   └── buildProxy.test.ts
    │   │   ├── interception
    │   │   │   ├── orderBy.test.ts
    │   │   │   ├── ReadOnlyCollection.test.ts
    │   │   │   └── request-param-converter.test.ts
    │   │   ├── scripts-runner
    │   │   │   ├── AttributeValueParser.test.ts
    │   │   │   ├── eval-tree-arrow-async.test.ts
    │   │   │   ├── eval-tree-arrow.test.ts
    │   │   │   ├── eval-tree-func-decl-async.test.ts
    │   │   │   ├── eval-tree-func-decl.test.ts
    │   │   │   ├── eval-tree-pre-post.test.ts
    │   │   │   ├── eval-tree-regression.test.ts
    │   │   │   ├── eval-tree.test.ts
    │   │   │   ├── function-proxy.test.ts
    │   │   │   ├── parser-regression.test.ts
    │   │   │   ├── process-event.test.ts
    │   │   │   ├── process-function.test.ts
    │   │   │   ├── process-implicit-context.test.ts
    │   │   │   ├── process-statement-asgn.test.ts
    │   │   │   ├── process-statement-destruct.test.ts
    │   │   │   ├── process-statement-regs.test.ts
    │   │   │   ├── process-statement-sync.test.ts
    │   │   │   ├── process-statement.test.ts
    │   │   │   ├── process-switch-sync.test.ts
    │   │   │   ├── process-switch.test.ts
    │   │   │   ├── process-try-sync.test.ts
    │   │   │   ├── process-try.test.ts
    │   │   │   └── test-helpers.ts
    │   │   ├── test-metadata-handler.ts
    │   │   ├── theming
    │   │   │   ├── border-segments.test.ts
    │   │   │   ├── component-layout.resolver.test.ts
    │   │   │   ├── layout-property-parser.test.ts
    │   │   │   ├── layout-resolver.test.ts
    │   │   │   ├── layout-resolver2.test.ts
    │   │   │   ├── layout-vp-override.test.ts
    │   │   │   └── padding-segments.test.ts
    │   │   └── utils
    │   │       ├── date-utils.test.ts
    │   │       ├── format-human-elapsed-time.test.ts
    │   │       └── LruCache.test.ts
    │   ├── language-server
    │   │   ├── completion.test.ts
    │   │   ├── format.test.ts
    │   │   ├── hover.test.ts
    │   │   └── mockData.ts
    │   └── parsers
    │       ├── common
    │       │   └── input-stream.test.ts
    │       ├── markdown
    │       │   └── parse-binding-expression.test.ts
    │       ├── parameter-parser.test.ts
    │       ├── paremeter-parser.test.ts
    │       ├── scripting
    │       │   ├── eval-tree-arrow.test.ts
    │       │   ├── eval-tree-pre-post.test.ts
    │       │   ├── eval-tree.test.ts
    │       │   ├── function-proxy.test.ts
    │       │   ├── lexer-literals.test.ts
    │       │   ├── lexer-misc.test.ts
    │       │   ├── module-parse.test.ts
    │       │   ├── parser-arrow.test.ts
    │       │   ├── parser-assignments.test.ts
    │       │   ├── parser-binary.test.ts
    │       │   ├── parser-destructuring.test.ts
    │       │   ├── parser-errors.test.ts
    │       │   ├── parser-expressions.test.ts
    │       │   ├── parser-function.test.ts
    │       │   ├── parser-literals.test.ts
    │       │   ├── parser-primary.test.ts
    │       │   ├── parser-regex.test.ts
    │       │   ├── parser-statements.test.ts
    │       │   ├── parser-unary.test.ts
    │       │   ├── process-event.test.ts
    │       │   ├── process-implicit-context.test.ts
    │       │   ├── process-statement-asgn.test.ts
    │       │   ├── process-statement-destruct.test.ts
    │       │   ├── process-statement-regs.test.ts
    │       │   ├── process-statement-sync.test.ts
    │       │   ├── process-statement.test.ts
    │       │   ├── process-switch-sync.test.ts
    │       │   ├── process-switch.test.ts
    │       │   ├── process-try-sync.test.ts
    │       │   ├── process-try.test.ts
    │       │   ├── simplify-expression.test.ts
    │       │   ├── statement-hooks.test.ts
    │       │   └── test-helpers.ts
    │       ├── style-parser
    │       │   ├── generateHvarChain.test.ts
    │       │   ├── parseHVar.test.ts
    │       │   ├── parser.test.ts
    │       │   └── tokens.test.ts
    │       └── xmlui
    │           ├── lint.test.ts
    │           ├── parser.test.ts
    │           ├── scanner.test.ts
    │           ├── transform.attr.test.ts
    │           ├── transform.circular.test.ts
    │           ├── transform.element.test.ts
    │           ├── transform.errors.test.ts
    │           ├── transform.escape.test.ts
    │           ├── transform.regression.test.ts
    │           ├── transform.script.test.ts
    │           ├── transform.test.ts
    │           └── xmlui.ts
    ├── tests-e2e
    │   ├── api-bound-component-regression.spec.ts
    │   ├── api-call-as-extracted-component.spec.ts
    │   ├── assign-to-object-or-array-regression.spec.ts
    │   ├── binding-regression.spec.ts
    │   ├── children-as-template-context-vars.spec.ts
    │   ├── compound-component.spec.ts
    │   ├── context-vars-regression.spec.ts
    │   ├── data-bindings.spec.ts
    │   ├── datasource-and-api-usage-in-var.spec.ts
    │   ├── datasource-direct-binding.spec.ts
    │   ├── datasource-onLoaded-regression.spec.ts
    │   ├── modify-array-item-regression.spec.ts
    │   ├── namespaces.spec.ts
    │   ├── push-to-array-regression.spec.ts
    │   ├── screen-breakpoints.spec.ts
    │   ├── scripting.spec.ts
    │   ├── state-scope-in-pages.spec.ts
    │   └── state-var-scopes.spec.ts
    ├── tsconfig.bin.json
    ├── tsconfig.json
    ├── tsconfig.node.json
    ├── vite.config.ts
    └── vitest.config.ts
```

# Files

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

```
  1 | import {
  2 |   existsSync,
  3 |   mkdirSync,
  4 |   copyFileSync,
  5 |   constants,
  6 |   readFileSync,
  7 |   accessSync,
  8 |   lstatSync,
  9 | } from "fs";
 10 | import { parse, join, basename, extname, sep, posix, relative } from "path";
 11 | import { writeFileSync, readdirSync } from "fs";
 12 | import { logger, LOGGER_LEVELS, processError, ErrorWithSeverity } from "./logger.mjs";
 13 | import { createTable, strBufferToLines, removeAdjacentNewlines } from "./utils.mjs";
 14 | import { iterateObjectEntries, processComponentSection } from "./pattern-utilities.mjs";
 15 | import {
 16 |   METADATA_SECTIONS,
 17 |   DIRECTIVE_CONFIG,
 18 |   SECTION_DISPLAY_NAMES,
 19 |   SECTION_REFERENCE_KEYS,
 20 |   COMMON_TABLE_HEADERS,
 21 |   FILE_EXTENSIONS,
 22 | } from "./constants.mjs";
 23 | 
 24 | // Note: string concatenation is the fastest using `+=` in Node.js
 25 | 
 26 | // These constants denote which attribute contains the inline component description
 27 | // and which contains the reference to the source markdown file
 28 | const SECTION_DESCRIPTION = SECTION_REFERENCE_KEYS.DESCRIPTION;
 29 | const SECTION_DESCRIPTION_REF = SECTION_REFERENCE_KEYS.DESCRIPTION_REF;
 30 | 
 31 | export class MetadataProcessor {
 32 |   constructor(metadata, importsToInject, { sourceFolder, outFolder, examplesFolder }) {
 33 |     this.metadata = metadata;
 34 |     this.importsToInject = importsToInject;
 35 |     this.sourceFolder = sourceFolder;
 36 |     this.outFolder = outFolder;
 37 |     this.examplesFolder = examplesFolder;
 38 |   }
 39 | 
 40 |   /**
 41 |    * @returns object containing the component name and the associated filenames
 42 |    */
 43 |   processDocfiles() {
 44 |     // Check for docs already in the output folder
 45 |     const docFiles = existsSync(this.outFolder)
 46 |       ? readdirSync(this.outFolder).filter((file) => extname(file) === FILE_EXTENSIONS.MARKDOWN[0])
 47 |       : [];
 48 |     let componentNames = docFiles.map((file) => basename(file, extname(file)));
 49 | 
 50 |     this.metadata.forEach((component) => {
 51 |       componentNames = this._processMdx(component, componentNames);
 52 |     });
 53 | 
 54 |     const metaFileContents = Object.fromEntries(componentNames.sort().map((name) => [name, name]));
 55 |     return metaFileContents;
 56 |   }
 57 | 
 58 |   _processMdx(component, componentNames) {
 59 |     let result = "";
 60 |     let fileData = "";
 61 | 
 62 |     // descriptionRef is explicitly set to empty, which means there is no external doc file for this component
 63 |     if (!!component.descriptionRef) {
 64 |       try {
 65 |         // File sizes don't exceed 1 MB (most are 20-23 KB), so reading the contents of the files into memory is okay
 66 |         fileData = readFileContents(join(this.sourceFolder, component.descriptionRef));
 67 |       } catch (error) {
 68 |         processError(error);
 69 |       }
 70 |     }
 71 | 
 72 |     logger.info(`Processing ${component.displayName}...`);
 73 | 
 74 |     const parent = findParent(this.metadata, component);
 75 | 
 76 |     // TODO: add check to throw warning if parent is not found
 77 |     // TODO: add check to throw error if component display name is the same as its specializedFrom attribute value
 78 | 
 79 |     if (!!parent) {
 80 |       result += this.importsToInject;
 81 | 
 82 |       result += `# ${component.displayName}`;
 83 |       result += appendArticleId(component.displayName);
 84 |       result += "\n\n";
 85 | 
 86 |       result += addComponentStatusDisclaimer(component.status);
 87 |       result += addNonVisualDisclaimer(component.nonVisual);
 88 | 
 89 |       result += addParentLinkLine(parent.displayName, basename(this.outFolder));
 90 | 
 91 |       const siblings = findSiblings(this.metadata, component);
 92 |       result += addSiblingLinkLine(siblings, basename(this.outFolder));
 93 | 
 94 |       result += fileData || "There is no description for this component as of yet.";
 95 |       result += `\n\n`;
 96 |     } else {
 97 |       logger.info("Processing imports section");
 98 | 
 99 |       result += this.importsToInject;
100 | 
101 |       const { buffer, copyFilePaths } = addImportsSection(
102 |         fileData,
103 |         component,
104 |         this.sourceFolder,
105 |         this.outFolder,
106 |         this.examplesFolder,
107 |       );
108 |       if (buffer) {
109 |         result += `${buffer}\n`;
110 |         copyImports(copyFilePaths);
111 |       }
112 | 
113 |       result += `# ${component.displayName}`;
114 |       result += appendArticleId(component.displayName);
115 |       result += "\n\n";
116 | 
117 |       result += addComponentStatusDisclaimer(component.status);
118 |       result += addNonVisualDisclaimer(component.nonVisual);
119 | 
120 |       result += combineDescriptionAndDescriptionRef(
121 |         fileData,
122 |         component,
123 |         METADATA_SECTIONS.DESCRIPTION,
124 |       );
125 | 
126 |       // Add context variables if they exist
127 |       if (component.contextVars && Object.keys(component.contextVars ?? {}).length > 0) {
128 |         result += "\n\n**Context variables available during execution:**";
129 |         result += "\n\n";
130 | 
131 |         // Use pattern utility for processing context variables
132 |         processComponentSection(
133 |           component.contextVars,
134 |           (contextVarName, contextVar) => {
135 |             if (contextVar.description) {
136 |               result += `- \`${contextVarName}\`: ${contextVar.description}\n`;
137 |             }
138 |           },
139 |           {
140 |             filter: (name, contextVar) => !contextVar.isInternal && contextVar.description,
141 |           },
142 |         );
143 |       }
144 | 
145 |       result += "\n\n";
146 | 
147 |       result += addChildrenTemplateSection(component);
148 |       result += "\n\n";
149 | 
150 |       result += addPropsSection(fileData, component);
151 |       result += "\n\n";
152 | 
153 |       result += addEventsSection(fileData, component);
154 |       result += "\n\n";
155 | 
156 |       result += addApisSection(fileData, component);
157 |       result += "\n\n";
158 | 
159 |       const partsSection = addPartsSection(fileData, component);
160 |       if (partsSection) {
161 |         result += partsSection;
162 |         result += "\n\n";
163 |       }
164 | 
165 |       result += addStylesSection(fileData, component);
166 |       result += "\n";
167 | 
168 |       result = removeAdjacentNewlines(strBufferToLines(result)).join("\n");
169 |     }
170 | 
171 |     try {
172 |       writeFileSync(join(this.outFolder, `${component.displayName}.md`), result);
173 |       componentNames.push(component.displayName);
174 |     } catch (error) {
175 |       logger.error("Could not write markdown file: ", error?.message || "unknown error");
176 |     }
177 |     return componentNames;
178 |   }
179 | }
180 | 
181 | // --- File & String Processing
182 | 
183 | function addImportsSection(data, component, sourceFolder, outFolder, examplesFolder) {
184 |   // This array is used in the transformer function
185 |   const copyFilePaths = [];
186 |   const buffer = getSection(
187 |     data,
188 |     component[SECTION_DESCRIPTION_REF],
189 |     METADATA_SECTIONS.IMPORTS,
190 |     importPathTransformer,
191 |   );
192 |   return { buffer, copyFilePaths };
193 | 
194 |   // ---
195 | 
196 |   function importPathTransformer(contents) {
197 |     if (!contents) {
198 |       return "";
199 |     }
200 | 
201 |     // 1. Get the import paths from the import statements, e.g. "./resources/icon.svg"
202 |     const normalized = contents
203 |       .replaceAll(/'|`/g, '"')
204 |       .split(/;|\n|;\n/g)
205 |       .filter(Boolean);
206 |     const splitNormalized = [
207 |       ...normalized.flatMap((line) =>
208 |         line
209 |           .trim()
210 |           .split('"')
211 |           .filter((part) => !!part.trim()),
212 |       ),
213 |     ];
214 |     // We assume that removing the ;-s and/or the \n-s will leave an even number of parts: an import statement & an import path
215 |     if (splitNormalized.length % 2 !== 0) {
216 |       throw new ErrorWithSeverity(
217 |         "Malformed import statement found in: ",
218 |         component.displayName,
219 |         "Skipping imports",
220 |         LOGGER_LEVELS.warning,
221 |       );
222 |     }
223 |     const importStatements = [];
224 |     const importPaths = [];
225 |     for (let i = 0; i < splitNormalized.length - 1; i += 2) {
226 |       importStatements.push(splitNormalized[i]);
227 |       importPaths.push(splitNormalized[i + 1]);
228 |     }
229 | 
230 |     // 2. Transform import paths and add them to the string buffer
231 |     let transformedStatements = "";
232 |     for (let i = 0; i < importPaths.length; i++) {
233 |       // NOTE: this is pretty restrictive, but works for now
234 |       if (!importPaths[i].startsWith("./doc-resources")) {
235 |         logger.error("Invalid import path:", importPaths[i], " in ", component.displayName);
236 |         continue;
237 |       }
238 |       const importFile = parse(importPaths[i]);
239 |       const transformedPath = join(
240 |         examplesFolder,
241 |         component.displayName,
242 |         importFile.base,
243 |       ).replaceAll(posix.sep, sep);
244 | 
245 |       // NOTE: need to use POSIX separators here regardless of platform
246 |       transformedStatements += `${
247 |         importStatements[i]
248 |       } "${relative(outFolder, transformedPath).replaceAll(sep, posix.sep)}";\n`;
249 | 
250 |       // 3. Add the original and new import paths to an array to copy them later
251 |       copyFilePaths.push({
252 |         oldPath: join(sourceFolder, component.displayName, importFile.dir, importFile.base),
253 |         newPath: relative(outFolder, transformedPath),
254 |       });
255 |     }
256 | 
257 |     return transformedStatements;
258 |   }
259 | }
260 | 
261 | function addPropsSection(data, component) {
262 |   logger.info(`Processing ${component.displayName} props`);
263 |   let buffer = `## ${SECTION_DISPLAY_NAMES.props}\n\n`;
264 | 
265 |   if (!component.props || Object.keys(component.props ?? {}).length === 0) {
266 |     return buffer + "This component does not have any properties.";
267 |   }
268 | 
269 |   // Use pattern utility for processing props
270 |   processComponentSection(component.props, (propName, prop) => {
271 |     const isRequired = prop.isRequired === true ? "(required)" : "";
272 |     const defaultValue =
273 |       prop.defaultValue !== undefined
274 |         ? `(default: ${typeof prop.defaultValue === "string" ? `"${prop.defaultValue}"` : prop.defaultValue})`
275 |         : "";
276 |     const propModifier = isRequired || defaultValue ? ` ${isRequired || defaultValue}` : "";
277 |     buffer += `### \`${propName}\`${propModifier}\n\n`;
278 | 
279 |     buffer += combineDescriptionAndDescriptionRef(data, prop, METADATA_SECTIONS.PROPS);
280 |     buffer += "\n\n";
281 |   });
282 | 
283 |   // Remove last newline
284 |   buffer = buffer.slice(0, -2);
285 |   return buffer;
286 | }
287 | 
288 | function addApisSection(data, component) {
289 |   logger.info(`Processing ${component.displayName} APIs`);
290 |   let buffer = `## ${SECTION_DISPLAY_NAMES.apis}\n\n`;
291 | 
292 |   if (!component.apis || Object.keys(component.apis ?? {}).length === 0) {
293 |     return buffer + "This component does not expose any methods.";
294 |   }
295 | 
296 |   // Use pattern utility for processing APIs
297 |   processComponentSection(component.apis, (apiName, api) => {
298 |     buffer += `### \`${apiName}\`\n\n`;
299 |     buffer += getComponentDescription(api);
300 |     buffer += "\n\n";
301 |     if (api.signature) {
302 |       buffer += `**Signature**: \`${api.signature}\`\n\n`;
303 |       if (api.parameters && Object.keys(api.parameters).length > 0) {
304 |         Object.entries(api.parameters).forEach(([name, param]) => {
305 |           buffer += `- \`${name}\`: ${param}\n`;
306 |         });
307 |         buffer += `\n`;
308 |       }
309 |     }
310 |     buffer += getComponentDescriptionRef(data, api, METADATA_SECTIONS.API);
311 |     buffer += "\n\n";
312 |   });
313 | 
314 |   // Remove last newline
315 |   buffer = buffer.slice(0, -2);
316 |   return buffer;
317 | }
318 | 
319 | function addEventsSection(data, component) {
320 |   logger.info(`Processing ${component.displayName} events`);
321 |   let buffer = `## ${SECTION_DISPLAY_NAMES.events}\n\n`;
322 | 
323 |   if (!component.events || Object.keys(component.events ?? {}).length === 0) {
324 |     return buffer + "This component does not have any events.";
325 |   }
326 | 
327 |   // Use pattern utility for processing events
328 |   processComponentSection(component.events, (eventName, event) => {
329 |     buffer += `### \`${eventName}\`\n\n`;
330 |     buffer += combineDescriptionAndDescriptionRef(data, event, METADATA_SECTIONS.EVENTS);
331 |     buffer += "\n\n";
332 |   });
333 | 
334 |   // Remove last newline
335 |   buffer = buffer.slice(0, -2);
336 |   return buffer;
337 | }
338 | 
339 | function addPartsSection(data, component) {
340 |   logger.info(`Processing ${component.displayName} parts`);
341 |   
342 |   if (!component.parts || Object.keys(component.parts ?? {}).length === 0) {
343 |     return "";
344 |   }
345 | 
346 |   let buffer = `## ${SECTION_DISPLAY_NAMES.parts}\n\n`;
347 | 
348 |   // Add lead text for components with parts
349 |   buffer += "The component has some parts that can be styled through layout properties and theme variables separately:\n\n";
350 | 
351 |   // Use pattern utility for processing parts
352 |   processComponentSection(component.parts, (partName, part) => {
353 |     buffer += `- **\`${partName}\`**: ${part.description}\n`;
354 |   });
355 | 
356 |   // Add default part information if available
357 |   if (component.defaultPart) {
358 |     buffer += `\n**Default part**: \`${component.defaultPart}\`\n`;
359 |   }
360 | 
361 |   return buffer;
362 | }
363 | 
364 | function addStylesSection(data, component) {
365 |   logger.info(`Processing ${component.displayName} styles`);
366 | 
367 |   let buffer = `## ${SECTION_DISPLAY_NAMES.styles}\n\n`;
368 |   const fileBuffer = getSection(data, component[SECTION_DESCRIPTION_REF], METADATA_SECTIONS.STYLES);
369 |   const varsTable = listThemeVars(component);
370 | 
371 |   let hasStylesSection = false;
372 |   if (fileBuffer) {
373 |     buffer += fileBuffer;
374 |     hasStylesSection = true;
375 |   }
376 |   if (varsTable) {
377 |     buffer += "\n\n### Theme Variables\n\n" + varsTable;
378 |     buffer += addThemeVarDescriptions(component);
379 |     hasStylesSection = true;
380 |   }
381 |   if (!hasStylesSection) {
382 |     buffer += "This component does not have any styles.";
383 |   }
384 | 
385 |   return buffer;
386 | }
387 | 
388 | function getComponentDescription(component) {
389 |   let descriptionBuffer = "";
390 | 
391 |   if (component[SECTION_DESCRIPTION]) {
392 |     descriptionBuffer = component[SECTION_DESCRIPTION];
393 |   }
394 | 
395 |   return descriptionBuffer;
396 | }
397 | 
398 | function getComponentDescriptionRef(data, component, sectionId) {
399 |   let fileBuffer = "";
400 |   if (component.hasOwnProperty(SECTION_DESCRIPTION_REF) && component[SECTION_DESCRIPTION_REF]) {
401 |     fileBuffer = getSection(data, component[SECTION_DESCRIPTION_REF], sectionId);
402 |   }
403 | 
404 |   return fileBuffer;
405 | }
406 | 
407 | function combineDescriptionAndDescriptionRef(
408 |   data,
409 |   component,
410 |   sectionId,
411 |   emptyDescriptionMessage = "No description provided.",
412 | ) {
413 |   let descriptionBuffer = "";
414 |   let fileBuffer = "";
415 | 
416 |   if (component[SECTION_DESCRIPTION]) {
417 |     descriptionBuffer = component[SECTION_DESCRIPTION];
418 |   }
419 | 
420 |   if (sectionId === METADATA_SECTIONS.PROPS) {
421 |     const availableValuesBuffer = addAvailableValues(component);
422 |     if (availableValuesBuffer) {
423 |       descriptionBuffer += "\n\n" + availableValuesBuffer;
424 |     }
425 |   }
426 | 
427 |   if (component.hasOwnProperty(SECTION_DESCRIPTION_REF) && component[SECTION_DESCRIPTION_REF]) {
428 |     fileBuffer = getSection(data, component[SECTION_DESCRIPTION_REF], sectionId);
429 |   }
430 | 
431 |   if (!descriptionBuffer && !fileBuffer) {
432 |     return emptyDescriptionMessage;
433 |   }
434 |   if (descriptionBuffer && fileBuffer) {
435 |     return descriptionBuffer + "\n\n" + fileBuffer;
436 |   }
437 |   return descriptionBuffer || fileBuffer;
438 | }
439 | 
440 | function addChildrenTemplateSection(component) {
441 |   if (!component.childrenAsTemplate) return "";
442 |   if (!component.props.hasOwnProperty(component.childrenAsTemplate)) {
443 |     return "";
444 |   }
445 |   const compName = component.displayName;
446 |   const childrenAsTemplate = component.childrenAsTemplate;
447 |   let buffer = "";
448 |   buffer += "## Use children as Content Template\n\n";
449 |   buffer +=
450 |     `The [${childrenAsTemplate}](#${childrenAsTemplate.toLowerCase()}) property can be replaced by ` +
451 |     `setting the item template component directly as the ${compName}'s child.\n`;
452 |   buffer += `In the following example, the two ${compName} are functionally the same:\n\n`;
453 |   buffer += "```xmlui copy\n";
454 |   buffer += "<App>\n";
455 |   buffer += `  <!-- This is the same -->\n`;
456 |   buffer += `  <${compName}>\n`;
457 |   buffer += `    <property name="${childrenAsTemplate}">\n`;
458 |   buffer += `      <Text>Template</Text>\n`;
459 |   buffer += `    </property>\n`;
460 |   buffer += `  </${compName}>\n`;
461 |   buffer += `  <!-- As this -->\n`;
462 |   buffer += `  <${compName}>\n`;
463 |   buffer += `    <Text>Template</Text>\n`;
464 |   buffer += `  </${compName}>\n`;
465 |   buffer += "</App>\n";
466 |   buffer += "```\n\n";
467 |   return buffer;
468 | }
469 | 
470 | function getSection(data, sectionRef, sectionId, transformer = (contents) => contents) {
471 |   const separator = "?";
472 |   const descRefParts = sectionRef.split(separator);
473 |   const sectionName = descRefParts.length > 1 ? descRefParts[1] : "";
474 | 
475 |   try {
476 |     if (!acceptSection(sectionId, sectionName)) {
477 |       throw new ErrorWithSeverity(
478 |         `Invalid section name and ID: ${sectionName} and ${sectionId}`,
479 |         LOGGER_LEVELS.warning,
480 |       );
481 |     }
482 |     const sectionHeader = DIRECTIVE_CONFIG.SECTION_MAP[sectionId];
483 |     if (!sectionHeader) {
484 |       throw new ErrorWithSeverity(`Unknown section ID: ${sectionId}`, LOGGER_LEVELS.warning);
485 |     }
486 | 
487 |     const startDirective = `${DIRECTIVE_CONFIG.INDICATOR}${sectionHeader}-START${
488 |       sectionName ? ` ${sectionName}` : ""
489 |     }`;
490 |     const endDirective = `${DIRECTIVE_CONFIG.INDICATOR}${sectionHeader}-END`;
491 |     const contents = resolveSection(data, startDirective, endDirective);
492 | 
493 |     return transformer(contents);
494 |   } catch (error) {
495 |     logger.error(error);
496 |   }
497 | }
498 | 
499 | function acceptSection(sectionId, sectionName) {
500 |   if (sectionId === METADATA_SECTIONS.PROPS && !sectionName) return false;
501 |   if (sectionId === METADATA_SECTIONS.EVENTS && !sectionName) return false;
502 |   return true;
503 | }
504 | 
505 | function resolveSection(data, startDirective, endDirective) {
506 |   startDirective = startDirective.replaceAll("$", "\\$");
507 |   endDirective = endDirective.replaceAll("$", "\\$");
508 |   const match = data.match(new RegExp(`${startDirective}([\\s\\S]*?)${endDirective}`, "i"));
509 |   if (!match || match?.length === 0) {
510 |     return "";
511 |   }
512 | 
513 |   let section = match[1];
514 |   let sectionLines = strBufferToLines(section);
515 | 
516 |   // Replace this with a function that handles META directives
517 |   sectionLines = stripMetaDirectives(sectionLines);
518 |   sectionLines = trimSection(sectionLines);
519 |   return sectionLines.join("\n");
520 | }
521 | 
522 | function trimSection(sectionLines) {
523 |   const firstNonEmptyIdx = sectionLines.findIndex((line) => line.trim() !== "");
524 |   const lastNonEmptyIdx = sectionLines.findLastIndex((line) => line.trim() !== "");
525 |   return sectionLines.slice(firstNonEmptyIdx, lastNonEmptyIdx + 1);
526 | }
527 | 
528 | function stripMetaDirectives(sectionLines) {
529 |   let buffer = sectionLines;
530 |   const metaStart = `${DIRECTIVE_CONFIG.INDICATOR}META`;
531 | 
532 |   buffer.forEach((line) => {
533 |     if (line.startsWith(metaStart)) {
534 |       buffer[buffer.indexOf(line)] = "";
535 |     }
536 |   });
537 | 
538 |   return buffer;
539 | }
540 | 
541 | function findParent(metadata, component) {
542 |   return component.specializedFrom
543 |     ? metadata.find((otherComponent) => otherComponent.displayName === component.specializedFrom)
544 |     : null;
545 | }
546 | 
547 | function addParentLinkLine(parentName, componentDocsFolder) {
548 |   // TODO: Insert component link
549 |   const result = parentName
550 |     ? `This component is inherited from [${parentName}](/${componentDocsFolder}/${parentName})`
551 |     : "";
552 |   return result ? `${result}\n\n` : "";
553 | }
554 | 
555 | function findSiblings(metadata, component) {
556 |   return metadata.filter(
557 |     (otherComponent) =>
558 |       otherComponent.specializedFrom === component.specializedFrom &&
559 |       otherComponent.displayName !== component.displayName,
560 |   );
561 | }
562 | 
563 | function addSiblingLinkLine(siblings = [], componentDocsFolder) {
564 |   const result =
565 |     siblings?.length > 0
566 |       ? `See also: ${siblings
567 |           .map((sibling) => {
568 |             return `[${sibling.displayName}](/${componentDocsFolder}/${sibling.displayName})`;
569 |           })
570 |           .join(", ")}`
571 |       : "";
572 |   return result ? `${result}\n\n` : "";
573 | }
574 | 
575 | function copyImports(imports) {
576 |   try {
577 |     imports.forEach((importPath) => {
578 |       const pathToNewFile = parse(importPath.newPath).dir;
579 |       if (!!pathToNewFile && !existsSync(pathToNewFile)) {
580 |         mkdirSync(pathToNewFile, { recursive: true });
581 |       }
582 |       copyFileSync(importPath.oldPath, importPath.newPath, constants.COPYFILE_FICLONE);
583 |     });
584 |   } catch (e) {
585 |     logger.error("Could not copy file: ", e?.message || "unknown error");
586 |   }
587 | }
588 | 
589 | function readFileContents(filePath) {
590 |   if (!fileExists(filePath)) {
591 |     throw new ErrorWithSeverity(`File ${filePath} does not exist.`, LOGGER_LEVELS.warning);
592 |   }
593 |   if (isDirectory(filePath)) {
594 |     throw new ErrorWithSeverity(
595 |       `File ${filePath} is a directory, cannot be processed.`,
596 |       LOGGER_LEVELS.warning,
597 |     );
598 |   }
599 | 
600 |   return readFileSync(filePath, "utf8");
601 | }
602 | 
603 | function fileExists(filePath) {
604 |   try {
605 |     accessSync(filePath, constants.F_OK);
606 |   } catch (error) {
607 |     return false;
608 |   }
609 |   return true;
610 | }
611 | 
612 | function isDirectory(filePath) {
613 |   try {
614 |     return lstatSync(filePath).isDirectory();
615 |   } catch (error) {
616 |     return false;
617 |   }
618 | }
619 | 
620 | // --- Section helpers (string manipulation)
621 | 
622 | function addComponentStatusDisclaimer(status) {
623 |   let disclaimer = "";
624 |   switch (status) {
625 |     case "stable":
626 |       disclaimer = "";
627 |       break;
628 |     // --- Tempoparily removed
629 |     // case "experimental":
630 |     //   disclaimer =
631 |     //     "This component is in an **experimental** state; you can use it in your app. " +
632 |     //     "However, we may modify it, and it may even have breaking changes in the future.";
633 |     //   break;
634 |     case "deprecated":
635 |       disclaimer =
636 |         "This component has been **deprecated**. We may remove it in a future XMLUI version.";
637 |       break;
638 |     case "in progress":
639 |       disclaimer =
640 |         "This component's implementation is **in progress**. This documentation shows the component's planned interface.";
641 |       break;
642 |     default:
643 |       disclaimer = "";
644 |   }
645 | 
646 |   return disclaimer !== "" ? `>[!WARNING]\n> ${disclaimer}` : "";
647 | }
648 | 
649 | function appendArticleId(articleId) {
650 |   if (!articleId) return "";
651 |   return ` [#${articleId.toLocaleLowerCase().replace(" ", "-")}]`;
652 | }
653 | 
654 | function addNonVisualDisclaimer(isNonVisual) {
655 |   return ""; // Temporarily disabled
656 |   // return isNonVisual
657 |   //   ? ">[!WARNING]\n> This component does not show up on the UI; " +
658 |   //       "it merely helps implement UI logic.\n\n"
659 |   //   : "";
660 | }
661 | 
662 | function addDefaultValue(component) {
663 |   const defaultValue = component.defaultValue;
664 |   if (defaultValue === undefined) {
665 |     return "";
666 |   }
667 |   if (typeof defaultValue === "string") {
668 |     return `Default value: \`"${defaultValue}"\`.`;
669 |   }
670 |   return `Default value: \`${JSON.stringify(defaultValue, null, 2)}\`.`;
671 | }
672 | 
673 | function addAvailableValues(component) {
674 |   if (
675 |     !(
676 |       component.availableValues &&
677 |       Array.isArray(component.availableValues) &&
678 |       component.availableValues.length > 0
679 |     )
680 |   ) {
681 |     return "";
682 |   }
683 | 
684 |   let availableValuesBuffer = "";
685 |   const valuesType = typeof component.availableValues[0];
686 |   const valuesTypeIsPrimitive = valuesType === "string" || valuesType === "number";
687 | 
688 |   if (valuesType === "string" || valuesType === "number") {
689 |     availableValuesBuffer = component.availableValues
690 |       .map((v) => `\`${v}\`${appendDefaultIndicator(v)}`)
691 |       .join(", ");
692 |   } else if (valuesType === "object") {
693 |     availableValuesBuffer = createTable({
694 |       headers: COMMON_TABLE_HEADERS.VALUE_DESCRIPTION,
695 |       rows: component.availableValues.map((v) => [
696 |         `\`${v.value}\``,
697 |         `${v.description}${appendDefaultIndicator(v.value)}`,
698 |       ]),
699 |     });
700 |   }
701 | 
702 |   if (availableValuesBuffer) {
703 |     return `Available values:${valuesTypeIsPrimitive ? " " : "\n\n"}${availableValuesBuffer}`;
704 |   }
705 |   return "";
706 | 
707 |   function appendDefaultIndicator(value) {
708 |     return component.defaultValue === value ? " **(default)**" : "";
709 |   }
710 | }
711 | 
712 | function listThemeVars(component) {
713 |   if (!component.themeVars) {
714 |     return "";
715 |   }
716 | 
717 |   const defaultThemeVars = component.defaultThemeVars
718 |     ? flattenDefaultThemeVarKeys(component.defaultThemeVars)
719 |     : [];
720 | 
721 |   const allThemeVars = Array.from(
722 |     new Set([...defaultThemeVars, ...Object.keys(component.themeVars)]),
723 |   );
724 | 
725 |   const varsWithDefaults = allThemeVars
726 |     .sort((a, b) => {
727 |       // --- Sort by removing the optional base component prefix
728 |       const partsA = a.split(":");
729 |       const partsB = b.split(":");
730 |       const partAValue = partsA.length > 1 ? partsA[1] : partsA[0];
731 |       const partBValue = partsB.length > 1 ? partsB[1] : partsB[0];
732 |       return partAValue.localeCompare(partBValue);
733 |     })
734 |     // --- Only list theme vars that contain the component name
735 |     .filter(
736 |       (themeVar) =>
737 |         !component.limitThemeVarsToComponent || themeVar.indexOf(component.displayName) !== -1,
738 |     )
739 |     .map((themeVar) => {
740 |       const parts = themeVar.split(":");
741 |       if (parts.length > 1) {
742 |         themeVar = parts[1];
743 |       }
744 | 
745 |       const defaultLightVar =
746 |         component.defaultThemeVars?.["light"]?.[themeVar] ||
747 |         component.defaultThemeVars?.[themeVar] ||
748 |         "*none*";
749 |       const defaultDarkVar =
750 |         component.defaultThemeVars?.["dark"]?.[themeVar] ||
751 |         component.defaultThemeVars?.[themeVar] ||
752 |         "*none*";
753 | 
754 |       return [provideLinkForThemeVar(themeVar), defaultLightVar, defaultDarkVar];
755 |     });
756 | 
757 |   return varsWithDefaults.length === 0
758 |     ? ""
759 |     : createTable({
760 |         headers: ["Variable", "Default Value (Light)", "Default Value (Dark)"],
761 |         rows: varsWithDefaults,
762 |       });
763 | 
764 |   function flattenDefaultThemeVarKeys(defaultThemeVars) {
765 |     const lightDefaults = defaultThemeVars?.["light"] || [];
766 |     if (lightDefaults.length > 0) {
767 |       defaultThemeVars["light"] = undefined;
768 |       delete defaultThemeVars["light"];
769 |     }
770 | 
771 |     const darkDefaults = defaultThemeVars?.["dark"] || [];
772 |     if (darkDefaults.length > 0) {
773 |       defaultThemeVars["dark"] = undefined;
774 |       delete defaultThemeVars["dark"];
775 |     }
776 | 
777 |     return Array.from(
778 |       new Set([
779 |         ...Object.keys(defaultThemeVars).filter((key) => key !== "light" && key !== "dark"),
780 |         ...Object.keys?.(lightDefaults),
781 |         ...Object.keys?.(darkDefaults),
782 |       ]),
783 |     );
784 |   }
785 | 
786 |   function provideLinkForThemeVar(themeVar) {
787 |     if (!themeVar) {
788 |       return "";
789 |     }
790 | 
791 |     const themeKeywords = Object.keys(themeKeywordLinks);
792 |     const matches = themeKeywords.filter((item) => themeVar.includes(item));
793 |     if (matches.length === 0) {
794 |       return themeVar;
795 |     }
796 | 
797 |     const result = matches.reduce((longest, current) =>
798 |       current.length > longest.length ? current : longest,
799 |     );
800 | 
801 |     const parts = themeVar.split(result);
802 |     return parts[0] + themeKeywordLinks[result] + parts[1];
803 |   }
804 | }
805 | 
806 | /**
807 |  * Creates a buffer that contains the section with the theme variable descriptions
808 |  * @param {Record<string, any>} component Record containing component metadata
809 |  * @returns Buffer with a table of theme variable keys and their descriptions
810 |  */
811 | function addThemeVarDescriptions(component) {
812 |   if (!component.themeVarDescriptions || Object.keys(component.themeVarDescriptions).length === 0) {
813 |     return "";
814 |   }
815 |   let buffer = "\n\n### Variable Explanations\n\n";
816 | 
817 |   buffer += createTable({
818 |     headers: COMMON_TABLE_HEADERS.THEME_VARIABLE_DESCRIPTION,
819 |     rows: Object.entries(component.themeVarDescriptions).map(([themeVar, description]) => [
820 |       `**\`${themeVar}\`**`,
821 |       description,
822 |     ]),
823 |   });
824 | 
825 |   return buffer + "\n\n";
826 | }
827 | 
828 | // Use this object/map to replace the occurrences of the keys and have them be replaced by links
829 | const themeKeywordLinks = {
830 |   animation: "[animation](../styles-and-themes/layout-props/#animation)",
831 |   animationDuration: "[animationDuration](../styles-and-themes/layout-props/#animationDuration)",
832 |   color: "[color](../styles-and-themes/common-units/#color)",
833 |   borderColor: "[borderColor](../styles-and-themes/common-units/#color)",
834 |   borderBottomColor: "[borderBottomColor](../styles-and-themes/common-units/#color)",
835 |   borderTopColor: "[borderTopColor](../styles-and-themes/common-units/#color)",
836 |   borderHorizontalColor: "[borderHorizontalColor](../styles-and-themes/common-units/#color)",
837 |   borderVerticalColor: "[borderVerticalColor](../styles-and-themes/common-units/#color)",
838 |   borderRightColor: "[color](../styles-and-themes/common-units/#color)",
839 |   borderLeftColor: "[color](../styles-and-themes/common-units/#color)",
840 |   backgroundColor: "[backgroundColor](../styles-and-themes/common-units/#color)",
841 |   textDecorationColor: "[textDecorationColor](../styles-and-themes/common-units/#color)",
842 |   textColor: "[textColor](../styles-and-themes/common-units/#color)",
843 |   fill: "[fill](../styles-and-themes/common-units/#color)",
844 |   stroke: "[stroke](../styles-and-themes/common-units/#color)",
845 |   fontWeight: "[fontWeight](../styles-and-themes/common-units/#fontWeight)",
846 |   rounding: "[rounding](../styles-and-themes/common-units/#border-rounding)",
847 |   borderStyle: "[borderStyle](../styles-and-themes/common-units/#border-style)",
848 |   borderBottomStyle: "[borderBottomStyle](../styles-and-themes/common-units/#border-style)",
849 |   borderTopStyle: "[borderTopStyle](../styles-and-themes/common-units/#border-style)",
850 |   borderHorizontalStyle: "[borderHorizontalStyle](../styles-and-themes/common-units/#border-style)",
851 |   borderVerticalStyle: "[borderVerticalStyle](../styles-and-themes/common-units/#border-style)",
852 |   borderRightStyle: "[borderRightStyle](../styles-and-themes/common-units/#border-style)",
853 |   borderLeftStyle: "[borderLeftStyle](../styles-and-themes/common-units/#border-style)",
854 |   size: "[size](../styles-and-themes/common-units/#size)",
855 |   fontSize: "[fontSize](../styles-and-themes/common-units/#size)",
856 |   height: "[height](../styles-and-themes/common-units/#size)",
857 |   minHeight: "[minHeight](../styles-and-themes/common-units/#size)",
858 |   maxHeight: "[maxHeight](../styles-and-themes/common-units/#size)",
859 |   width: "[width](../styles-and-themes/common-units/#size)",
860 |   minWidth: "[minWidth](../styles-and-themes/common-units/#size)",
861 |   maxWidth: "[maxWidth](../styles-and-themes/common-units/#size)",
862 |   distance: "[distance](../styles-and-themes/common-units/#size)",
863 |   thickness: "[thickness](../styles-and-themes/common-units/#size)",
864 |   borderWidth: "[borderWidth](../styles-and-themes/common-units/#size)",
865 |   borderBottomWidth: "[borderBottomWidth](../styles-and-themes/common-units/#size)",
866 |   borderTopWidth: "[borderTopWidth](../styles-and-themes/common-units/#size)",
867 |   borderHorizontalWidth: "[borderHorizontalWidth](../styles-and-themes/common-units/#size)",
868 |   borderVerticalWidth: "[borderVerticalWidth](../styles-and-themes/common-units/#size)",
869 |   borderRightWidth: "[borderRightWidth](../styles-and-themes/common-units/#size)",
870 |   borderLeftWidth: "[borderLeftWidth](../styles-and-themes/common-units/#size)",
871 |   textDecorationThickness: "[textDecorationThickness](../styles-and-themes/common-units/#size)",
872 |   strokeWidth: "[strokeWidth](../styles-and-themes/common-units/#size)",
873 |   offset: "[offset](../styles-and-themes/common-units/#size)",
874 |   padding: "[padding](../styles-and-themes/common-units/#size)",
875 |   paddingTop: "[paddingTop](../styles-and-themes/common-units/#size)",
876 |   paddingRight: "[paddingRight](../styles-and-themes/common-units/#size)",
877 |   paddingBottom: "[paddingBottom](../styles-and-themes/common-units/#size)",
878 |   paddingLeft: "[paddingLeft](../styles-and-themes/common-units/#size)",
879 |   paddingHorizontal: "[paddingHorizontal](../styles-and-themes/common-units/#size)",
880 |   paddingVertical: "[paddingVertical](../styles-and-themes/common-units/#size)",
881 |   margin: "[margin](../styles-and-themes/common-units/#size)",
882 |   marginTop: "[marginTop](../styles-and-themes/common-units/#size)",
883 |   marginBottom: "[marginBottom](../styles-and-themes/common-units/#size)",
884 |   marginLeft: "[marginLeft](../styles-and-themes/common-units/#size)",
885 |   marginRight: "[marginRight](../styles-and-themes/common-units/#size)",
886 |   textDecorationLine: "[textDecorationLine](../styles-and-themes/common-units/#textDecoration)",
887 |   lineHeight: "[lineHeight](../styles-and-themes/common-units/#size)",
888 |   borderEndEndRadius: "[borderEndEndRadius](../styles-and-themes/common-units/#border-rounding)",
889 |   borderEndStartRadius:
890 |     "[borderEndStartRadius](../styles-and-themes/common-units/#border-rounding)",
891 |   borderStartEndRadius:
892 |     "[borderStartEndRadius](../styles-and-themes/common-units/#border-rounding)",
893 |   borderStartStartRadius:
894 |     "[borderStartStartRadius](../styles-and-themes/common-units/#border-rounding)",
895 |   borderRadius: "[borderRadius](../styles-and-themes/common-units/#border-rounding)",
896 |   borderHorizontal: "[borderHorizontal](../styles-and-themes/common-units/#border)",
897 |   borderVertical: "[borderHorizontal](../styles-and-themes/common-units/#border)",
898 |   border: "[border](../styles-and-themes/common-units/#border)",
899 |   borderLeft: "[borderLeft](../styles-and-themes/common-units/#border)",
900 |   borderRight: "[borderRight](../styles-and-themes/common-units/#border)",
901 |   borderTop: "[borderTop](../styles-and-themes/common-units/#border)",
902 |   borderBottom: "[borderBottom](../styles-and-themes/common-units/#border)",
903 |   boxShadow: "[boxShadow](../styles-and-themes/common-units/#boxShadow)",
904 |   direction: "[direction](../styles-and-themes/layout-props#direction)",
905 |   gap: "[gap](../styles-and-themes/common-units/#size)",
906 |   horizontalAlignment: "[horizontalAlignment](../styles-and-themes/common-units/#alignment)",
907 |   verticalAlignment: "[verticalAlignment](../styles-and-themes/common-units/#alignment)",
908 |   alignment: "[alignment](../styles-and-themes/common-units/#alignment)",
909 |   fontFamily: "[fontFamily](../styles-and-themes/common-units/#fontFamily)",
910 |   fontStretch: "[fontStretch](../styles-and-themes/common-units/#fontStretch)",
911 |   fontStyle: "[fontStyle](../styles-and-themes/common-units/#fontStyle)",
912 |   letterSpacing: "[letterSpacing](../styles-and-themes/common-units/#size)",
913 |   textDecorationStyle: "[textDecorationStyle](../styles-and-themes/common-units/#textDecoration)",
914 |   textDecorationThickness:
915 |     "[textDecorationThickness](../styles-and-themes/common-units/#textDecoration)",
916 |   textTransform: "[textTransform](../styles-and-themes/common-units/#textTransform)",
917 |   "maxWidth-content": "[maxWidth-content](../styles-and-themes/common-units/#size)",
918 |   outlineStyle: "[outlineStyle](../styles-and-themes/common-units/#border)",
919 |   outlineWidth: "[outlineWidth](../styles-and-themes/common-units/#size)",
920 |   outlineColor: "[outlineColor](../styles-and-themes/common-units/#color)",
921 |   outlineOffset: "[outlineOffset](../styles-and-themes/common-units/#size)",
922 |   textUnderlineOffset: "[textUnderlineOffset](../styles-and-themes/common-units/#size)",
923 |   opacity: "[opacity](../styles-and-themes/common-units/#opacity)",
924 |   cursor: "[cursor](../styles-and-themes/common-units/#cursor)",
925 |   fontVariant: "[fontVariant](../styles-and-themes/common-units/#font-variant)",
926 |   lineBreak: "[lineBreak](../styles-and-themes/common-units/#line-break)",
927 |   textAlign: "[textAlign](../styles-and-themes/common-units/#text-align)",
928 |   textAlignLast: "[textAlignLast](../styles-and-themes/common-units/#text-align)",
929 |   textIndent: "[textIndent](../styles-and-themes/common-units/#text-indent)",
930 |   textShadow: "[textShadow](../styles-and-themes/common-units/#text-shadow)",
931 |   wordBreak: "[wordBreak](../styles-and-themes/common-units/#word-break)",
932 |   wordSpacing: "[wordSpacing](../styles-and-themes/common-units/#word-spacing)",
933 |   wordWrap: "[wordWrap](../styles-and-themes/common-units/#word-wrap)",
934 |   writingMode: "[writingMode](../styles-and-themes/common-units/#writing-mode)",
935 |   transition: "[transition](../styles-and-themes/common-units/#transition)",
936 | };
937 | 
```

--------------------------------------------------------------------------------
/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 combinedState = useCombinedState(stateFromOutside, node.contextVars, mergedWithVars, routingParams);
400 | ```
401 | 
402 | ### Variable Resolution and Memoization
403 | 
404 | Variables are resolved through a sophisticated memoization system:
405 | 
406 | ```typescript
407 | // From StateContainer.tsx - useVars function
408 | type MemoedVars = Map<any, {
409 |   getDependencies: (value: string | CodeDeclaration, referenceTrackedApi: Record<string, ComponentApi>) => Array<string>;
410 |   obtainValue: (expression: any, state: ContainerState, appContext: AppContextObject | undefined, strict: boolean | undefined, stateDeps: Record<string, any>, appContextDeps: Record<string, any>) => any;
411 | }>;
412 | ```
413 | 
414 | #### Variable Dependency Tracking
415 | 
416 | 1. **Function Dependencies**: Arrow expressions and their variable dependencies are collected first
417 | 2. **Variable Dependencies**: Dependencies between variables are resolved in multiple passes
418 | 3. **Memoization**: Results are memoized based on dependency changes to avoid unnecessary recalculation
419 | 
420 | ## Reducer-Based State Updates
421 | 
422 | ### Container Actions
423 | 
424 | State changes are managed through Redux-style actions via the `ContainerActionKind` enum:
425 | 
426 | ```typescript
427 | // From /xmlui/src/components-core/rendering/containers.ts
428 | export const enum ContainerActionKind {
429 |   LOADER_LOADED = "ContainerActionKind:LOADER_LOADED",
430 |   LOADER_IN_PROGRESS_CHANGED = "ContainerActionKind:LOADER_IN_PROGRESS_CHANGED", 
431 |   LOADER_IS_REFETCHING_CHANGED = "ContainerActionKind:LOADER_IS_REFETCHING_CHANGED",
432 |   LOADER_ERROR = "ContainerActionKind:LOADER_ERROR",
433 |   EVENT_HANDLER_STARTED = "ContainerActionKind:EVENT_HANDLER_STARTED",
434 |   EVENT_HANDLER_COMPLETED = "ContainerActionKind:EVENT_HANDLER_COMPLETED",
435 |   EVENT_HANDLER_ERROR = "ContainerActionKind:EVENT_HANDLER_ERROR", 
436 |   COMPONENT_STATE_CHANGED = "ContainerActionKind:COMPONENT_STATE_CHANGED",
437 |   STATE_PART_CHANGED = "ContainerActionKind:STATE_PART_CHANGED",
438 | }
439 | ```
440 | 
441 | ### Partial State Changes
442 | 
443 | The most sophisticated action is `STATE_PART_CHANGED`, which handles deep object/array mutations:
444 | 
445 | ```typescript
446 | // Example: Updating nested property some.count++
447 | {
448 |   "type": "ContainerActionKind:STATE_PART_CHANGED",
449 |   "payload": {
450 |     "actionType": "set",
451 |     "path": ["some", "count"],
452 |     "target": { "count": 0 },
453 |     "value": 1,
454 |     "localVars": resolvedLocalVars
455 |   }
456 | }
457 | ```
458 | 
459 | The reducer uses Lodash's `setWith` to update nested paths while preserving object vs array types based on target structure.
460 | 
461 | ## Proxy-Based Change Detection
462 | 
463 | ### BuildProxy Function
464 | 
465 | State changes are detected using JavaScript Proxies that intercept get/set operations:
466 | 
467 | ```typescript
468 | // From /xmlui/src/components-core/rendering/buildProxy.ts
469 | export function buildProxy(
470 |   proxyTarget: any,
471 |   callback: (changeInfo: ProxyCallbackArgs) => void,
472 |   tree: Array<string | symbol> = [],
473 | ): any {
474 |   return new Proxy(proxyTarget, {
475 |     get: function (target, prop, receiver) {
476 |       const value = Reflect.get(target, prop, receiver);
477 |       // Create nested proxies for objects and arrays
478 |       if (value && typeof value === "object" && ["Array", "Object"].includes(value.constructor.name)) {
479 |         if (!proxiedValues.has(value)) {
480 |           proxiedValues.set(value, buildProxy(value, callback, tree.concat(prop)));
481 |         }
482 |         return proxiedValues.get(value);
483 |       }
484 |       return value;
485 |     },
486 |     set: function (target, prop, value, receiver) {
487 |       // Notify of state changes
488 |       callback({
489 |         action: "set", 
490 |         path: getPath(prop),
491 |         pathArray: tree.concat(prop),
492 |         target,
493 |         newValue: value,
494 |         previousValue: Reflect.get(target, prop, receiver),
495 |       });
496 |       return Reflect.set(target, prop, value, receiver);
497 |     }
498 |   });
499 | }
500 | ```
501 | 
502 | ### Change Propagation
503 | 
504 | When a proxied state change occurs:
505 | 
506 | 1. **Detection**: Proxy intercepts the change and calls the callback
507 | 2. **Path Analysis**: Determines if the change belongs to current container or parent
508 | 3. **Dispatch**: Sends `STATE_PART_CHANGED` action to appropriate container
509 | 4. **Reduction**: Immer-based reducer applies the change immutably
510 | 5. **Re-render**: React re-renders affected components
511 | 
512 | ## Component Identification and APIs
513 | 
514 | ### Symbol-Based Component IDs
515 | 
516 | Components within containers are identified using JavaScript Symbols:
517 | 
518 | ```typescript
519 | // Component ID resolution
520 | const componentUid = componentId ?? Symbol(id);
521 | if (id) {
522 |   componentUid.description = id; // For debugging and API access
523 | }
524 | ```
525 | 
526 | ### Component ID Storage vs Accessibility
527 | 
528 | 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.
529 | 
530 | **Component ID Creation and Storage Flow**
531 | 
532 | 1. **Universal ID Assignment**: ALL components receive a unique Symbol-based ID, regardless of whether they create containers:
533 | 
534 | ```tsx
535 | // From ComponentAdapter.tsx - every component gets a UID
536 | const uid = useMemo(() => Symbol(safeNode.uid), [safeNode.uid]);
537 | ```
538 | 
539 | 2. **Container vs Non-Container Components**:
540 |    - **Components that create containers**: Store their child component IDs in their own `componentApis` state
541 |    - **Components that DON'T create containers**: Their IDs are stored in the nearest parent container
542 | 
543 | 3. **Registration Mechanism**: Components register their APIs (including their ID) with the nearest container:
544 | 
545 | ```tsx
546 | // From ComponentAdapter.tsx - all components register with nearest container
547 | const memoedRegisterComponentApi: RegisterComponentApiFn = useCallback(
548 |   (api) => {
549 |     registerComponentApi(uid, api);  // Registers with nearest parent container
550 |   },
551 |   [registerComponentApi, uid],
552 | );
553 | ```
554 | 
555 | 4. **Storage in Parent Container**: The `StateContainer` maintains a `componentApis` map:
556 | 
557 | ```tsx
558 | // From StateContainer.tsx - parent container stores all child component IDs
559 | const registerComponentApi: RegisterComponentApiFnInner = useCallback((uid, api) => {
560 |   setComponentApis(produce((draft) => {
561 |     if (!draft[uid]) {
562 |       draft[uid] = {};
563 |     }
564 |     Object.entries(api).forEach(([key, value]) => {
565 |       draft[uid][key] = value;
566 |     });
567 |   }));
568 | }, []);
569 | ```
570 | 
571 | **Global Access Through State Composition**
572 | Even though component IDs are stored hierarchically, they become accessible file-wide through state inheritance:
573 | 
574 | ```tsx
575 | // From StateContainer.tsx - state flows down through hierarchy
576 | const combinedState = useCombinedState(
577 |   stateFromOutside,      // Parent state (contains parent component IDs)
578 |   node.contextVars,      // Framework context variables
579 |   mergedWithVars,        // Local variables and component state  
580 |   routingParams,         // Routing parameters
581 | );
582 | ```
583 | 
584 | **Example Scenarios**:
585 | 
586 | 1. **Component with ID but no container**:
587 | ```xml
588 | <Stack var.count="{0}">           <!-- Creates container A -->
589 |   <Button id="myBtn" />           <!-- ID stored in container A -->
590 |   <Text id="myText" />            <!-- ID also stored in container A -->
591 | </Stack>
592 | ```
593 | 
594 | 2. **Nested containers with inheritance**:
595 | ```xml
596 | <Stack var.count="{0}">           <!-- Creates container A -->
597 |   <Button id="myBtn" />           <!-- ID stored in container A -->
598 |   <Stack var.data="{null}">       <!-- Creates container B -->
599 |     <Text>{myBtn.visible}</Text>  <!-- Can access myBtn via state inheritance -->
600 |     <Button id="innerBtn" />      <!-- ID stored in container B -->
601 |   </Stack>
602 | </Stack>
603 | ```
604 | 
605 | **Storage and Access Pattern**:
606 | - `myBtn` and `myText` IDs are stored in container A's `componentApis` (they don't create their own containers)
607 | - `innerBtn` ID is stored in container B's `componentApis`
608 | - Container B inherits parent state through `stateFromOutside`, making `myBtn` accessible
609 | - All components can reference each other within the same .xmlui file through the state inheritance chain
610 | 
611 | **Root Component Storage**: 
612 | 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.
613 | 
614 | This design ensures that:
615 | - **Performance**: Each container only manages its direct responsibility
616 | - **Usability**: All components within a .xmlui file can reference each other
617 | - **Consistency**: Component IDs flow predictably through the container hierarchy
618 | - **Reliability**: There's always a root container to store component IDs, even for simple root components
619 | 
620 | ### Component API Registration
621 | 
622 | Components can expose APIs that other components can invoke:
623 | 
624 | ```typescript
625 | // From StateContainer.tsx
626 | const registerComponentApi: RegisterComponentApiFnInner = useCallback((uid, api) => {
627 |   setComponentApis(produce((draft) => {
628 |     if (!draft[uid]) {
629 |       draft[uid] = {};
630 |     }
631 |     Object.entries(api).forEach(([key, value]) => {
632 |       if (draft[uid][key] !== value) {
633 |         draft[uid][key] = value;
634 |       }
635 |     });
636 |   }));
637 | }, []);
638 | ```
639 | 
640 | APIs are merged into the component state so they're accessible via the component's ID:
641 | 
642 | ```typescript
643 | // API access pattern
644 | componentStateWithApis[componentId] = { ...componentState, ...exposedApi };
645 | ```
646 | 
647 | ## Asynchronous Event Handler Execution
648 | 
649 | ### UI Responsiveness Strategy
650 | 
651 | The Container component maintains UI responsiveness during long-running operations through:
652 | 
653 | 1. **Async Instruction Execution**: Each instruction in an event handler runs asynchronously
654 | 2. **State Synchronization Points**: Execution pauses after each instruction for state updates
655 | 3. **Promise-Based Coordination**: Uses promises to coordinate when state changes are committed
656 | 4. **Transition-Based Updates**: Uses React's `startTransition` for non-urgent updates
657 | 
658 | ### Execution Flow
659 | 
660 | ```typescript
661 | // Simplified execution pattern from Container.tsx
662 | const executeHandler = async (statements: Statement[], options: ExecutionOptions) => {
663 |   for (const statement of statements) {
664 |     // Execute statement
665 |     await processStatement(statement, evalContext);
666 |     
667 |     // Collect state changes
668 |     if (changes.length > 0) {
669 |       // Dispatch state changes
670 |       changes.forEach(change => {
671 |         statePartChanged(change.pathArray, change.newValue, change.target, change.action);
672 |       });
673 |       
674 |       // Create promise for this statement
675 |       const statementPromise = new Promise(resolve => {
676 |         statementPromiseResolvers.current.set(statementId, resolve);
677 |       });
678 |       
679 |       // Increment version to trigger re-render
680 |       startTransition(() => {
681 |         setVersion(prev => prev + 1);
682 |       });
683 |       
684 |       // Wait for state to be committed
685 |       await statementPromise;
686 |     }
687 |   }
688 | };
689 | ```
690 | 
691 | ### Version-Based Synchronization
692 | 
693 | The Container uses a version counter to coordinate state updates:
694 | 
695 | ```typescript
696 | // When version changes, resolve pending promises
697 | useEffect(() => {
698 |   // Resolve all pending statement promises
699 |   statementPromiseResolvers.current.forEach(resolve => resolve());
700 |   statementPromiseResolvers.current.clear();
701 | }, [version]);
702 | ```
703 | 
704 | ## State Scoping and Inheritance
705 | 
706 | ### Parent State Extraction
707 | 
708 | Child containers can limit which parent state they receive:
709 | 
710 | ```typescript
711 | // From StateContainer.tsx
712 | function extractScopedState(parentState: ContainerState, uses?: string[]): ContainerState | undefined {
713 |   if (!uses) {
714 |     return parentState; // Inherit all parent state
715 |   }
716 |   if (uses.length === 0) {
717 |     return EMPTY_OBJECT; // Inherit no parent state  
718 |   }
719 |   return pick(parentState, uses); // Inherit only specified keys
720 | }
721 | ```
722 | 
723 | ### Context Variables
724 | 
725 | Containers can provide context variables to their children:
726 | 
727 | ```typescript
728 | // contextVars flow down to child containers automatically
729 | const localVarsStateContext = useCombinedState(
730 |   stateFromOutside,
731 |   componentStateWithApis, 
732 |   node.contextVars // These become available to children
733 | );
734 | ```
735 | 
736 | ### State Merging Strategies
737 | 
738 | Different merging strategies are used for different state layers:
739 | 
740 | 1. **Override**: Higher-priority state overrides lower-priority (`useCombinedState`)
741 | 2. **Merge**: Object and array values are deep-merged (`useMergedState`)
742 | 3. **Replace**: Simple values replace entirely
743 | 
744 | ## Routing Integration
745 | 
746 | ### Routing Parameters as State
747 | 
748 | Routing information is automatically injected into container state:
749 | 
750 | ```typescript
751 | // From StateContainer.tsx - useRoutingParams
752 | const routingParams = useMemo(() => {
753 |   return {
754 |     $pathname: location.pathname,
755 |     $routeParams: routeParams,      // URL parameters like :id
756 |     $queryParams: queryParamsMap,   // Query string parameters
757 |     $linkInfo: linkInfo,            // Navigation context
758 |   };
759 | }, [linkInfo, location.pathname, queryParamsMap, routeParams]);
760 | ```
761 | 
762 | These are automatically available in all containers as context variables.
763 | 
764 | ## Error Boundaries and Resilience
765 | 
766 | ### Layered Error Protection
767 | 
768 | The container system has multiple error boundaries:
769 | 
770 | 1. **Container-Level**: Protects StateContainer from Container errors
771 | 2. **StateContainer-Level**: Protects parent containers from child container errors  
772 | 3. **Component-Level**: Individual component errors don't crash containers
773 | 
774 | ### State Preservation
775 | 
776 | If a Container crashes during event handler execution, the StateContainer preserves its state, allowing recovery or graceful degradation.
777 | 
778 | ## Performance Optimizations
779 | 
780 | ### Memoization Strategies
781 | 
782 | 1. **Component Memoization**: Container components are memoized to prevent unnecessary re-renders
783 | 2. **Variable Memoization**: Variable resolution results are cached based on dependencies
784 | 3. **Shallow Comparison**: State objects use shallow comparison for change detection
785 | 4. **Reference Tracking**: Proxy objects maintain stable references for nested access
786 | 
787 | ### Change Detection Optimizations
788 | 
789 | 1. **Path-Based Updates**: Only affected parts of state tree are updated
790 | 2. **Dependency Tracking**: Variables are only re-evaluated when their dependencies change
791 | 3. **Batch Updates**: Multiple changes in single instruction are batched together
792 | 4. **Transition Updates**: Non-urgent updates use React transitions for better performance
793 | 
794 | ## Debugging Support
795 | 
796 | ### State Transition Logging
797 | 
798 | The container reducer can log state transitions for debugging:
799 | 
800 | ```typescript
801 | // From reducer.ts
802 | export function createContainerReducer(debugView: IDebugViewContext) {
803 |   const allowLogging = debugView.collectStateTransitions;
804 |   // ... logging implementation
805 | }
806 | ```
807 | 
808 | ### Component Keys and Resolution
809 | 
810 | Components receive resolved keys for debugging and tracking:
811 | 
812 | ```typescript
813 | // From renderChild.tsx  
814 | const key = extractParam(state, node.uid, appContext, true);
815 | return (
816 |   <ComponentWrapper
817 |     key={key}
818 |     resolvedKey={key} // For debugging container parent chains
819 |     // ...
820 |   />
821 | );
822 | ```
823 | 
824 | ## Integration Points
825 | 
826 | ### DataSource Integration
827 | 
828 | DataSource components integrate with the container system through loader actions:
829 | 
830 | ```typescript
831 | // Loader state management
832 | dispatch({
833 |   type: ContainerActionKind.LOADER_LOADED,
834 |   payload: {
835 |     uid: dataSourceUid,
836 |     data: fetchedData,
837 |     pageInfo: paginationInfo
838 |   }
839 | });
840 | ```
841 | 
842 | ### Form Integration
843 | 
844 | Form components manage their state through the container system while maintaining their own internal state for performance.
845 | 
846 | ### API Integration
847 | 
848 | Component APIs are registered with containers and become part of the state, making them accessible to other components via component IDs.
849 | 
850 | ## Key Design Principles
851 | 
852 | 1. **Hierarchical Encapsulation**: State is scoped to container boundaries while allowing controlled inheritance
853 | 2. **Reactive Consistency**: All state changes automatically propagate to dependent UI elements
854 | 3. **Async Coordination**: Long-running operations don't block the UI thread
855 | 4. **Immutable Updates**: All state changes produce new immutable state objects
856 | 5. **Proxy Transparency**: State mutations are detected transparently without special syntax
857 | 6. **Error Isolation**: Component errors are contained and don't propagate to affect other parts of the application
858 | 
859 | 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 120/182FirstPrevNextLast