#
tokens: 49448/50000 14/1626 files (page 28/141)
lines: off (toggle) GitHub
raw markdown copy
This is page 28 of 141. Use http://codebase.md/xmlui-org/xmlui/%7Bnode.props.src?lines=false&page={x} to view the full context.

# Directory Structure

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

# Files

--------------------------------------------------------------------------------
/docs/public/pages/scripting.md:
--------------------------------------------------------------------------------

```markdown
# XMLUI Scripting

With XMLUI you can go a long way without coding anything more than small JavaScript snippets like those we've seen in the [Markup](/markup) chapter.

An expression:

```xmlui !/{ 6 * 7 }/
<Text value="Life, the universe, and everything: { 6 * 7 }" />
```

A statement:

```xmlui !/{ count++ }/
<Button label="Click to increment the count">
  <event name="click">
    { count++ }
  </event>
</Button>
```

An object literal:

```xmlui !/{ station: "Brixton", wifi: true, toilets: false }/
<Form
  data='{{ station: "Brixton", wifi: true, toilets: false }}'
  onSubmit="() => { preview.setValue(JSON.stringify($data)) }"
>
```

A function call:

```xmlui !/() => { preview.setValue(JSON.stringify($data)) }/
<Form
  data='{{ station: "Brixton", wifi: true, toilets: false }}'
  onSubmit="() => { preview.setValue(JSON.stringify($data)) }"
>
```

The last example uses a JavaScript [arrow function expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), a concise way to define and use a function in an XMLUI attribute. The function receives the value of a selected theme in the `newTheme` argument (a name of your choosing) and calls the [global](/globals) `setTheme` function with that value.

## Writing longer functions

The most elaborate function we've seen so far was this one, used in [Components](/components-intro) chapter to extract data from a complex API response.

```js copy
window.transformStops = function(stops) {
  return stops.map(function(stop) {
  // Helper to extract a value from additionalProperties by key
    function getProp(key) {
      if (!stop.additionalProperties) return '';
      var propObj = stop.additionalProperties.find(function(p) {
        return p.key === key;
      });
      return propObj ? propObj.value : '';
    }
    return {
      name: stop.commonName,
      zone: getProp('Zone'),
      wifi: getProp('WiFi'),
      toilets: getProp('Toilets'),
      // A comma-separated list of line names that serve this stop
      lines: stop.lines
        ? stop.lines.map(function(line) { return line.name; }).join(', ')
        : ''
    };
  });
}
```

Here's how it works.

- `transformStops` receives a `stops` argument which is an array of JavaScript objects created by a `DataSource`. Each is a complex object representing a London tube stop.
- `map` is a method on an array object like `stops`. It takes an anonymous function as an argument, runs it for each item in the array, and returns a new array with each item transformed by a call to the function.
- `function(stop) { ... }` is the anonymous function passed to `map`. It defines a nested helper function, `getProp`, to extract property values.
- `getProp` calls `find`, another method on an array object. In this case the array is `stop.additionalProperties`. Like `map` it receives an anonymous function (`function(p)`) that receives an `additionalProperties` object. It  returns true if the name passed to `getProp` matches the value of `p.key`.

It helps to see the structure of a single object in the `stops` array.

```json
{
  "commonName": "Baker Street Underground Station",
  "placeType": "StopPoint",
  "additionalProperties": [
    {
      "$type": "Tfl.Api.Presentation.Entities.AdditionalProperties, Tfl.Api.Presentation.Entities",
      "category": "ServiceInfo",
      "key": "WiFi",
      "sourceSystemKey": "StaticObjects",
      "value": "yes"
    },
    {
      "$type": "Tfl.Api.Presentation.Entities.AdditionalProperties, Tfl.Api.Presentation.Entities",
      "category": "Facility",
      "key": "Car park",
      "sourceSystemKey": "StaticObjects",
      "value": "no"
    },
  ]
}
```

Here's an example of the transformed output.

```json
{
  "value": [
    {
      "name": "Bank Underground Station",
      "zone": "1",
      "wifi": "yes",
      "toilets": "yes",
      "lines": "Central, Northern, Waterloo & City"
    },
    {
      "name": "Waterloo Underground Station",
      "zone": "1",
      "wifi": "yes",
      "toilets": "no",
      "lines": "Bakerloo, Jubilee, Northern, Waterloo & City"
    }
  ]
}
```

## Deploying the transform function

We defined the function in XMLUI's `index.html` like so:

```html
<script>
  window.transformStops = function(stops) {
    ...
  }
</script>
```

When you define functions in `index.html` you can keep everything in one place for easy reference, and debug your functions in the browser's devtools environment.

You can alternatively put functions into XMLUI *code-behind* files. In this case, for the `TubeStops` component which lives in the file `TubeStops.xmlui`, you would create a parallel file called `TubeStops.xmlui.xs`. In that context, arrow functions are required, so the function would look like this.

```js
function transformStops(stops) {
  return stops.map(stop => {
    // Helper to extract a value from additionalProperties by key
    const getProp = (key) => {
      const prop = stop.additionalProperties &&
        stop.additionalProperties.find(p => p.key === key);
      return prop ? prop.value : '';
    };
    return {
      name: stop.commonName,
      zone: getProp('Zone'),
      wifi: getProp('WiFi'),
      toilets: getProp('Toilets'),
      // A comma-separated list of line names that serve this stop
      lines: stop.lines ? stop.lines.map(line => line.name).join(', ') : ''
    };
  });
}
```

## index.html vs code-behind

You can use either or both of these strategies in an XMLUI app. Use `index.html` if:

- Your function will be reused across components
- You like keeping all your functions in one place for convenient review
- You need to debug your function
- Your function interacts with JavaScript libraries you load via `index.html`
- You are unfamiliar with "modern" JavaScript features like arrow functions

Use code-behind if:

- You prefer to organize functions by component
- Your function works with variables scoped to a component
- Your function works with XMLUI [globals](/globals)

## Inline code

When you write JavaScript expressions in XMLUI attributes you typically write single expressions, not multiline code blocks. But you can write multiline code blocks in some event handlers, for example click handlers.

```xmlui copy
<Button label="onClick" onClick="{
  console.log('clicked');
  count++;
  toast('count now' + count)
}" />
```

```xmlui copy
<Button label="event tag">
  <event name="click">
  {
    console.log('clicked');
    count++;
    toast('count now' + count)
  }
  </event>
</Button>
```

```

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

```typescript
import { type ComponentDef } from "../../abstractions/ComponentDefs";
import { createComponentRenderer } from "../../components-core/renderers";
import type { ApiOperationDef } from "../../components-core/RestApiProxy";
import { createMetadata, dInternal } from "../../components/metadata-helpers";
import { httpMethodNames } from "../abstractions";
import { APICallNative, defaultProps } from "./APICallNative";

const COMP = "APICall";

export interface ApiActionComponent extends ComponentDef {
  props?: ApiOperationDef & {
    invalidates?: string | string[];
    updates?: string | string[];
    confirmTitle?: string;
    confirmMessage?: string;
    confirmButtonLabel?: string;
    optimisticValue: any;
    getOptimisticValue: string;
    inProgressNotificationMessage?: string;
    errorNotificationMessage?: string;
    completedNotificationMessage?: string;
  };
  events?: {
    success: string;
    progress: string;
    error: string;
    beforeRequest: string;
  };
}

export const APICallMd = createMetadata({
  status: "stable",
  description:
    "`APICall` creates, updates or deletes data on the backend, versus [`DataSource`]" +
    "(/components/DataSource) which fetches data. Unlike DataSource, APICall doesn't " +
    "automatically execute - you must trigger it manually with the `execute()` method, " +
    "typically from form submissions or button clicks.",
  props: {
    method: {
      description: "The method of data manipulation can be done via setting this property.",
      valueType: "string",
      availableValues: httpMethodNames,
      defaultValue: defaultProps.method,
    },
    url: {
      description:
        "Use this property to set the URL to which data will be sent. If not provided, an empty URL is used.",
      isRequired: true,
      valueType: "string",
    },
    rawBody: {
      description:
        "This optional property sets the request body to the value provided here without any conversion. " +
        "Use the * \`body\` property if you want the object sent in JSON. When you define " +
        "\`body\` and \`rawBody\`, the latest one prevails.",
      valueType: "string",
    },
    body: {
      description:
        "This optional property sets the request body. Use to pass an object that will be " +
        "serialized as a JSON string. If you have an object that is already serialized as " +
        "a JSON string, use `rawBody` instead.",
      valueType: "string",
    },
    queryParams: {
      description:
        "This optional property sets the query parameters for the request. The object you pass here will " +
        "be serialized to a query string and appended to the request URL. You can specify key " +
        "and value pairs where the key is the name of a particular query parameter and the value " +
        "is that parameter's value.",
    },
    headers: {
      description:
        "You can optionally define request header values as key-value pairs, where the key is the ID " +
        "of the particular header and the value is that header's corresponding value.",
    },
    confirmTitle: {
      description:
        "This optional string sets the title in the confirmation dialog that is displayed before " +
        `the \`${COMP}\` is executed.`,
      valueType: "string",
    },
    confirmMessage: {
      description:
        "This optional string sets the message in the confirmation dialog that is displayed before " +
        `the \`${COMP}\` is executed.`,
      valueType: "string",
    },
    confirmButtonLabel: {
      description:
        "This optional string property enables the customization of the submit button in the " +
        `confirmation dialog that is displayed before the \`${COMP}\` is executed.`,
      valueType: "string",
    },
    inProgressNotificationMessage: {
      description:
        "This property customizes the message that is displayed in a toast while the API " +
        "operation is in progress. If not defined, no progress message is displayed.",
      valueType: "string",
    },
    errorNotificationMessage: {
      description:
        "This property defines the message to display automatically when the operation " +
        "results in an error. You can use the `$error` context value in an expression to " +
        "refer to the original error message.",
      valueType: "string",
    },
    completedNotificationMessage: {
      description:
        "This property defines the message to display automatically when the operation has " +
        "been completed. When this property is not defined, the completion does not display any message.",
      valueType: "string",
    },
    payloadType: dInternal(),
    invalidates: dInternal(),
    updates: dInternal(),
    optimisticValue: dInternal(),
    getOptimisticValue: dInternal(),
  },
  events: {
    beforeRequest: {
      description:
        "This event fires before the request is sent. Returning an explicit boolean" +
        "\`false\` value will prevent the request from being sent.",
    },
    success: {
      description: "This event fires when a request results in a success.",
    },
    // This event fires when a request results in an error.
    error: {
      description: "This event fires when a request results in an error.",
    },
    progress: dInternal(),
  },
  contextVars: {
    $param: {
      description: "The first parameter passed to `execute()` method",
    },
    $params: {
      description:
        "Array of all parameters passed to `execute()` method (access with " +
        "`$params[0]`, `$params[1]`, etc.)",
    },
    $result: {
      description:
        "Response data (available in `completedNotificationMessage`)",
    },
    $error: {
      description: "Error details (available in `errorNotificationMessage`)",
    },
  },
  apis: {
    execute: {
      description:
        "This method triggers the invocation of the API. You can pass an arbitrary " +
        "number of parameters to the method. In the \`APICall\` instance, you can " +
        "access those with the \`$param\` and \`$params\` context values.",
      signature: "execute(...params: any[])",
      parameters: {
        params: "An arbitrary number of parameters that can be used in the API call.",
      },
    },
  },
});

export const apiCallRenderer = createComponentRenderer(
  COMP,
  APICallMd,
  ({ node, registerComponentApi, uid }) => {
    return (
      <APICallNative registerComponentApi={registerComponentApi} node={node as any} uid={uid} />
    );
  },
);

```

--------------------------------------------------------------------------------
/docs/public/pages/working-with-text.md:
--------------------------------------------------------------------------------

```markdown
# Working with Text

Text elements appear in UI components such as menu items, titles, headings, labels, and descriptions. There is also a [Markdown](/components/Markdown) component for complete text documents (like this page). We'll cover `Text` here and `Markdown` in the [next chapter](/working-with-markdown).

You can nest text in any component that renders its children.


```xmlui-pg display name="Example: displaying text"
<App>
  This is text!
  <Button label="This is text too." />
  This is more text!
</App>
```

To gain more control we can use the  `Text` component.

```xmlui-pg display name="Example: Using the Text component"
<App>
  <Text fontSize="1.5rem" color="purple">This is a text!</Text>
  <Button label="I'm just a button" />
  <Text backgroundColor="lightgreen">This is another text!</Text>
</App>
```

Components that render text support theme variables. You can use them, for example, to control the styling of the heading family of components ([Heading](/components/Heading), [H1](/components/H1), [H2](/components/H2), etc).

```xmlui-pg display name="Example: Text can be styled"
<App>
  <Theme
    textColor-H1 = "red"
    textColor-H2 = "green">
    <H1>My Main Title</H1>
    This document contains several sections.
    <H2>Section Title</H2>
  </Theme>
</App>
```

## Specifying text content

Components like `Text`, `H1` and `Badge` can display text in two ways:

- **Nesting text**
- **Setting the `value` property**

We've seen nesting, here's an example that uses the `value` property.

```xmlui-pg display name="Example: Text and the value property"
<App>
  <H2 value="Text Content with Properties" />
  <Text value="This text is set in the 'value' property of 'Text'." />
</App>
```

>[!INFO]
> With nested text, multiple consecutive spaces or newlines collapse to a single space. That doesn't happen when you set text using the `value`.

Whitespace collapsing enables you to maintain source text that's broken into multiple lines for easier editing.

The collapsed view renders neatly.

```xmlui-pg display name="Example: whitespace collapsing"
<App>
  This is a long text broken into multiple lines.

  The source markup would be challenging to read if

  the entire text were specified in a single line.
</App>
```


## Binding expressions

Binding expressions are placeholders for computed values.


```xmlui-pg display name="Try the reset button!"
<App>
   Seconds of the current minute: { getDate().getSeconds() }
</App>
```

Results of binding expressions are displayed with collapsed whitespace.


## Inline and block rendering

When you render text, it accommodates the current layout context. If that context uses inline rendering, the text is rendered inline; otherwise, it renders as a block.

In an `HStack`, text segments render inline.

```xmlui-pg copy display name="Example: inline rendering"
<App>
  <HStack>
    Show me a trash
    <Icon name="trash"/>
    icon!
  </HStack>
</App>
```



In a `VStack` they render as blocks.

```xmlui-pg copy display name="Example: block rendering"
<App>
  <VStack>
    Show me a trash
    <Icon name="trash"/>
    icon!
  </VStack>
</App>
```

## Non-breaking spaces

Use `&nbsp;` to preserve spaces in a context where they would otherwise collapse.

```xmlui-pg copy display name="Example: non-breaking spaces"
<App>
  A series of non-breaking segments: [1&nbsp;2&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;4]
</App>
```


## Long text

With long text you may need to control how that text is broken into new lines (if at all) and how to handle overflows. By default a long text breaks into multiple lines.

```xmlui-pg copy display name="Example: text breaks into multiple lines"
<App>
  <Text width="200px">
    This long text does not fit into a width constraint of 200 pixels.
  </Text>
</App>
```

If necessary, breaks occur within a word.

```xmlui-pg copy display name="Example: break within a word"
<App>
  <Text width="200px">
    ThisLongTextDoesNotFitInTheGivenConstraint of 200 pixels wide.
   </Text>
</App>
```

## Preserving line breaks

Sometimes you want to preserve line breaks, as when inspecting a JSON object.

```xmlui-pg copy display name="Example: preserving line breaks" /preserveLinebreaks="true"/
<App
  var.data = "{
    {
      apples: 3,
      oranges: 4
    }
  }"
>
  <Text preserveLinebreaks="false">
    { JSON.stringify(data, null, 2) }
  </Text>
  <Text preserveLinebreaks="true">
    { JSON.stringify(data, null, 2) }
  </Text>
</App>
```

## Variants of the Text component

In addition to the theme variables that govern the `Text` component, you can use the [`variant`](/components/Text#variant) property to control styles directly.

```xmlui-pg
<App>
  <HStack>
    <Text width="150px">default:</Text>
    <Text>This is an example text</Text>
  </HStack>
  <HStack>
    <Text width="150px">paragraph:</Text>
    <Text variant="paragraph">This is an example paragraph</Text>
  </HStack>
  <HStack>
    <Text width="150px">placeholder:</Text>
    <Text variant="placeholder">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">secondary:</Text>
    <Text variant="secondary">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">code:</Text>
    <Text variant="code">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">codefence + code:</Text>
    <Text variant="codefence">
      <Text variant="code">
        This is an example text
      </Text>
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">keyboard:</Text>
    <Text variant="keyboard">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">sup:</Text>
    <Text>
      This is an example text
      <Text variant="sup">(with some additional text)</Text>
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">sub:</Text>
    <Text>
      This is an example text
      <Text variant="sub">(with some additional text)</Text>
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">mono:</Text>
    <Text variant="mono">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">strong:</Text>
    <Text variant="strong">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">small:</Text>
    <Text variant="small">
      This is an example text
    </Text>
  </HStack>
  <HStack>
    <Text width="150px">caption:</Text>
    <Text variant="caption">
      This is an example text
    </Text>
  </HStack>
</App>
```


```

--------------------------------------------------------------------------------
/xmlui/dev-docs/next/project-build.md:
--------------------------------------------------------------------------------

```markdown
# XMLUI Project Build System

This document explains how the XMLUI monorepo is built using Turborepo, covering the build pipeline, task orchestration, and development workflows.

## Build System Overview

XMLUI uses **Turborepo** to orchestrate builds across the entire monorepo containing 12+ buildable packages. Turborepo provides:

- **Parallel execution** of build tasks across workspaces
- **Intelligent caching** to avoid rebuilding unchanged packages
- **Task dependency management** ensuring correct build order
- **Incremental builds** for faster development cycles

## Turborepo Configuration

### Core Configuration (`turbo.json`)

The build pipeline is defined in the root `turbo.json` file:

```json
{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", "build/**"]
    },
    "build:xmlui": {
      "dependsOn": ["^build:xmlui"],
      "outputs": ["dist/**"]
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": []
    },
    "lint": {
      "outputs": []
    }
  }
}
```

### Key Pipeline Tasks

- **`build`**: Generic build task for all packages
- **`build:xmlui`**: Specific build for XMLUI framework and extensions
- **`test`**: Run tests (depends on build completion)
- **`lint`**: Code quality checks

## Workspace Build Scripts

### Root Package Scripts

The root `package.json` defines orchestration scripts:

```json
{
  "scripts": {
    "build-xmlui": "turbo run build:xmlui-all",
    "build-vscode-extension": "turbo run xmlui-vscode#build:vsix",
    "test-xmlui": "turbo run build:xmlui-all test:xmlui-all",
    "test-xmlui-smoke": "turbo run build:xmlui-all test:xmlui-smoke",
    "build-extensions": "turbo run build:extension",
    "build-docs": "turbo run build:xmlui-all build:docs",
    "publish-packages": "turbo run build:xmlui-all test:xmlui-all && npm run changeset:publish"
  }
}
```

## Build Targets by Workspace

### 1. Core Framework (`xmlui/`)

**Build Scripts:**
```json
{
  "scripts": {
    "build:xmlui": "vite build --mode lib",
    "build:xmlui-standalone": "vite build --mode standalone", 
    "build:xmlui-metadata": "vite build --mode metadata",
    "build:bin": "tsc -p tsconfig.bin.json"
  }
}
```

**Build Outputs:**
- `dist/` - Library bundle for npm distribution
- `bin/` - CLI executables
- Metadata files for tooling support

### 2. Extension Packages (`packages/*/`)

**Common Build Scripts:**
```json
{
  "scripts": {
    "build:extension": "xmlui build-lib",
    "build:demo": "xmlui build",
    "build:meta": "xmlui build-lib --mode=metadata",
    "build-watch": "xmlui build-lib --watch"
  }
}
```

**Build Outputs:**
- `dist/` - Extension library bundle
- Demo applications (when applicable)
- Component metadata

### 3. Documentation Website (`docs/`)

**Build Scripts:**
```json
{
  "scripts": {
    "build:docs": "xmlui build --buildMode=INLINE_ALL --withMock && xmlui zip-dist --target=dist/ui.zip"
  }
}
```

**Build Outputs:**
- Static website with inlined dependencies
- Zipped distribution package
- Mock service worker integration

### 4. Development Tools (`tools/`)

**CLI Tool (`tools/create-app/`):**
```json
{
  "scripts": {
    "build": "ncc build ./index.ts -o dist/ --minify"
  }
}
```

**VS Code Extension (`tools/vscode/`):**
```json
{
  "scripts": {
    "build:vsix": "vsce package"
  }
}
```

## Build Execution Flows

### Development Build

```bash
# Build everything for development
npm run build-xmlui

# This executes:
# 1. Core framework build
# 2. All extension packages (in parallel)
# 3. CLI tools compilation
```

### Production Build

```bash
# Full production build with tests
npm run publish-packages

# This executes:
# 1. Build all packages
# 2. Run complete test suite
# 3. Publish to npm (if tests pass)
```

### Incremental Development

```bash
# Watch mode for specific package
cd packages/xmlui-animations
npm run build-watch

# Or build only changed packages
turbo run build --filter=...@main
```

## Build Dependencies

### Inter-Package Dependencies

```mermaid
graph TD
    Core[xmlui] --> Ext1[xmlui-animations]
    Core --> Ext2[xmlui-devtools]
    Core --> Ext3[xmlui-playground]
    Core --> Docs[xmlui-docs]
    Ext3 --> Docs
    Core --> Tests[xmlui-e2e]
    Core --> CLI[create-xmlui-app]
```

### Build Order

1. **Core Framework** (`xmlui`) - Must build first
2. **Extension Packages** - Can build in parallel after core
3. **Applications** - Documentation and test bed
4. **Tools** - CLI and VS Code extension

## Caching Strategy

### Turborepo Cache

Turborepo automatically caches build outputs based on:
- **Input files** - Source code, configuration files
- **Dependencies** - package.json, lock files  
- **Environment** - Node version, environment variables

### Cache Locations

- **Local cache**: `.turbo/cache/`
- **Remote cache**: Configured via `TURBO_TOKEN` (optional)

### Cache Invalidation

Cache is invalidated when:
- Source files change
- Dependencies are updated
- Build configuration changes
- Environment variables change

## Development Workflows

### First-Time Setup

```bash
# 1. Install dependencies
npm install

# 2. Build documentation (includes framework)
npm run build-docs

# 3. Build complete framework
npm run build-xmlui

# 4. Run tests
npm run test-xmlui-smoke
```

### Daily Development

```bash
# Build only changed packages
turbo run build --filter=...@HEAD~1

# Start development server
cd docs && npm start

# Build specific package
turbo run build --filter=xmlui-animations
```

### Pre-Release

```bash
# Complete build and test
npm run test-xmlui

# Build documentation
npm run build-docs

# Package VS Code extension
npm run build-vscode-extension
```

## Performance Optimization

### Parallel Execution

Turborepo runs tasks in parallel when dependencies allow:

```bash
# These run in parallel:
- xmlui-animations build
- xmlui-devtools build  
- xmlui-pdf build
# (after xmlui core completes)
```

### Build Filtering

Target specific packages or changes:

```bash
# Build only animation package and its dependencies
turbo run build --filter=xmlui-animations

# Build packages changed since main branch
turbo run build --filter=...@main

# Build specific scope
turbo run build --filter=./packages/*
```

### Watch Mode

For active development:

```bash
# Watch core framework
cd xmlui && npm run build:xmlui-watch

# Watch specific extension
cd packages/xmlui-playground && npm run build-watch
```

This build system ensures efficient, reliable builds across the entire XMLUI ecosystem while supporting both development and production workflows.

```

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

```markdown
# NavGroup [#navgroup]

`NavGroup` creates collapsible containers for organizing related navigation items into hierarchical menu structures. It groups `NavLink` components and other `NavGroup` components, providing expandable submenus with customizable icons and states.

**Key features:**

- **Hierarchical organization**: Creates nested menu structures by containing NavLinks and other NavGroups
- **Expand/collapse behavior**: Users can toggle visibility of grouped navigation items
- **Customizable icons**: Different icons for expanded/collapsed states and layout orientations
- **Flexible placement**: Works within NavPanel for app navigation or standalone for custom menus
- **Initial state control**: Configure whether groups start expanded or collapsed

## Using `NavGroup` [#using-navgroup]

The primary use of a `NavGroup` is to create an application menu with submenus, as the following example shows:

```xmlui-pg copy display name="Example: NavGroup in App" height="280px"
---app
<App layout="condensed">
  <NavPanel>
    <NavLink label="Home" to="/" icon="home"/>
    <NavGroup label="Pages">
      <NavLink label="Page 1" to="/page/1"/>
      <NavGroup label="Page 2-4">
        <NavLink label="Page 2" to="/page/2"/>
        <NavLink label="Page 3" to="/page/3"/>
        <NavLink label="Page 4" to="/page/4"/>
      </NavGroup>
      <NavLink label="Page 5" to="/page/5"/>
      <NavLink label="Page Other" to="/page/Other"/>
    </NavGroup>
  </NavPanel>
  <Pages fallbackPath="/">
    <Page url="/">
      Home
    </Page>
    <Page url="/page/:id">
      <Text value="Page {$routeParams.id}" />
    </Page>
  </Pages>
</App>
---desc
Here, the highlighted `NavGroup` element nests other `NavLink` and `NavGroup` elements to create a hierarchical menu:
```

You do not have to use `NavGroup` within `NavPanel`; you can nest it into other components to represent a menu, like in the following example:

```xmlui-pg copy display name="Example: NavGroup in a Stack" height="280px"
<App>
  <HStack verticalAlignment="center">
    <Text>Use this menu:</Text>
    <NavGroup label="Pages">
      <NavLink label="Page 1" />
      <NavGroup label="Page 2-4">
        <NavLink label="Page 2" />
        <NavLink label="Page 3" />
        <NavLink label="Page 4" />
      </NavGroup>
      <NavLink label="Page 5" />
      <NavLink label="Page Other" />
    </NavGroup>
  </HStack>
</App>
```

### Custom Icons [#custom-icons]

You can also provide custom icons for a specific NavGroup component via it's respective property:

- [iconHorizontalCollapsed](#iconHorizontalCollapsed)
- [iconHorizontalExpanded](#iconHorizontalExpanded)
- [iconVerticalCollapsed](#iconVerticalCollapsed)
- [iconVerticalExpanded](#iconVerticalExpanded)

See the following for an example of all variants:

```xmlui-pg copy display name="Example: custom icons in horizontal layout" height="250px"
<App layout="horizontal">
  <NavGroup icon="email" label="Send To"
    iconVerticalExpanded="arrowup" iconVerticalCollapsed="arrowbottom">
    <NavLink icon="arrowup" label="Boss" />
    <NavGroup icon="users" label="Team"
      iconHorizontalExpanded="arrowleft" iconHorizontalCollapsed="arrowright">
      <NavLink label="Jane" />
      <NavLink label="Will" />
    </NavGroup>
    <NavLink icon="cube" label="Support" />
  </NavGroup>
</App>
```

## Properties [#properties]

### `enabled` (default: true) [#enabled-default-true]

This boolean property value indicates whether the component responds to user events (`true`) or not (`false`).

### `icon` [#icon]

This property defines an optional icon to display along with the `NavGroup` label.

Look at this example:

```xmlui-pg copy {3, 5} display name="Example: label and icon" height="280px"
<App>
  <HStack verticalAlignment="center">
    <NavGroup icon="email" label="Send To" >
      <NavLink icon="arrowup" label="Boss" />
      <NavGroup icon="users" label="Team">
        <NavLink label="Jane" />
        <NavLink label="Will" />
        <NavLink label="Sandra" />
      </NavGroup>
      <NavLink icon="cube" label="Support" />
    </NavGroup>
  </HStack>
</App>
```

### `iconHorizontalCollapsed` (default: "chevronright") [#iconhorizontalcollapsed-default-chevronright]

Set a custom icon to display when the navigation menu is collapsed, is in a **horizontal** app layout, and is in a navigation submenu.

For an example, see the [Custom Icons section](#custom-icons).

### `iconHorizontalExpanded` (default: "chevronright") [#iconhorizontalexpanded-default-chevronright]

Set a custom icon to display when the navigation menu is expanded, is in a **horizontal** app layout, and is in a navigation submenu.

For an example, see the [Custom Icons section](#custom-icons).

### `iconVerticalCollapsed` (default: "chevronright") [#iconverticalcollapsed-default-chevronright]

Set a custom icon to display when the navigation menu is collapsed, is in a **vertical** app layout, or is in a **horizontal** layout and is the top-level navigation item in the menu.

For an example, see the [Custom Icons section](#custom-icons).

### `iconVerticalExpanded` (default: "chevrondown") [#iconverticalexpanded-default-chevrondown]

Set a custom icon to display when the navigation menu is expanded, is in a **vertical** app layout, or is in a **horizontal** layout and is the top-level navigation item in the menu.

For an example, see the [Custom Icons section](#custom-icons).

### `initiallyExpanded` [#initiallyexpanded]

This property defines whether the group is initially expanded or collapsed. If not defined, the group is collapsed by default.

### `label` [#label]

This property sets the label of the component.  If not set, the component will not display a label.

This property sets the text displayed as the name of the `NavGroup`.

For an example, see the [section on the icon property](#icon).

### `to` [#to]

This property defines an optional navigation link.

## Events [#events]

This component does not have any events.

## Exposed Methods [#exposed-methods]

This component does not expose any methods.

## Styling [#styling]

### Theme Variables [#theme-variables]

| Variable | Default Value (Light) | Default Value (Dark) |
| --- | --- | --- |
| [backgroundColor](../styles-and-themes/common-units/#color)-dropdown-NavGroup | $backgroundColor-primary | $backgroundColor-primary |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-dropdown-NavGroup | $borderRadius | $borderRadius |
| [boxShadow](../styles-and-themes/common-units/#boxShadow)-dropdown-NavGroup | $boxShadow-spread | $boxShadow-spread |

```

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

```typescript
import { Slider } from "./SliderNative";
import styles from "./Slider.module.scss";
import { createComponentRenderer } from "../../components-core/renderers";
import { parseScssVar } from "../../components-core/theming/themeVars";
import {
  createMetadata,
  d,
  dAutoFocus,
  dDidChange,
  dEnabled,
  dGotFocus,
  dInitialValue,
  dLostFocus,
  dReadonly,
  dRequired,
  dValidationStatus,
} from "../metadata-helpers";

const COMP = "Slider";

export const SliderMd = createMetadata({
  status: "stable",
  description:
    "`Slider` provides an interactive control for selecting numeric values within " +
    "a defined range, supporting both single value selection and range selection with " +
    "multiple thumbs. It offers precise control through customizable steps and visual " +
    "feedback with formatted value display." +
    "\n\n" +
    "Hover over the component to see the tooltip with the current value. On mobile, tap the thumb to see the tooltip.",
  props: {
    initialValue: dInitialValue(),
    minValue: {
      description: `This property specifies the minimum value of the allowed input range.`,
      valueType: "number",
      defaultValue: 0,
    },
    maxValue: {
      description: `This property specifies the maximum value of the allowed input range.`,
      valueType: "number",
      defaultValue: 10,
    },
    step: {
      description: `This property defines the increment value for the slider, determining the allowed intervals between selectable values.`,
      defaultValue: 1,
    },
    minStepsBetweenThumbs: d(
      `This property sets the minimum number of steps required between multiple thumbs on the slider, ensuring they maintain a specified distance.`,
      undefined,
      "number",
      1,
    ),
    enabled: dEnabled(),
    autoFocus: dAutoFocus(),
    required: dRequired(),
    readOnly: dReadonly(),
    validationStatus: {
      ...dValidationStatus(),
      defaultValue: "none",
    },
    rangeStyle: d(
      `This optional property allows you to apply custom styles to the range element of the slider.`,
    ),
    thumbStyle: d(
      `This optional property allows you to apply custom styles to the thumb elements of the slider.`,
    ),
    showValues: {
      description: `This property controls whether the slider shows the current values of the thumbs.`,
      valueType: "boolean",
      defaultValue: true,
    },
    valueFormat: {
      description: `This property allows you to customize how the values are displayed.`,
      valueType: "any",
      defaultValue: "(value) => value.toString()",
    },
  },
  events: {
    didChange: dDidChange(COMP),
    gotFocus: dGotFocus(COMP),
    lostFocus: dLostFocus(COMP),
  },
  apis: {
    focus: {
      description: `This method sets the focus on the slider component.`,
      signature: "focus(): void",
    },
    value: {
      description: `This API retrieves the current value of the \`${COMP}\`. You can use it to get the value programmatically.`,
      signature: "get value(): number | [number, number] | undefined",
    },
    setValue: {
      description: `This API sets the value of the \`${COMP}\`. You can use it to programmatically change the value.`,
      signature: "setValue(value: number | [number, number] | undefined): void",
      parameters: {
        value: "The new value to set. Can be a single value or an array of values for range sliders.",
      },
    },
  },
  themeVars: parseScssVar(styles.themeVars),
  defaultThemeVars: {
    [`backgroundColor-track-${COMP}`]: "$color-surface-200",
    [`backgroundColor-range-${COMP}`]: "$color-primary",
    [`borderWidth-thumb-${COMP}`]: "2px",
    [`borderStyle-thumb-${COMP}`]: "solid",
    [`borderColor-thumb-${COMP}`]: "$color-surface-50",
    [`backgroundColor-thumb-${COMP}`]: "$color-primary",
    [`backgroundColor-thumb-${COMP}--focus`]: "$color-primary",
    [`boxShadow-thumb-${COMP}--focus`]: "0 0 0 6px rgb(from $color-primary r g b / 0.4)",
    [`backgroundColor-thumb-${COMP}--hover`]: "$color-primary",
    [`boxShadow-thumb-${COMP}--hover`]: "0 0 0 6px rgb(from $color-primary r g b / 0.4)",
    [`backgroundColor-thumb-${COMP}--active`]: "$color-primary-400",
    [`boxShadow-thumb-${COMP}--active`]: "0 0 0 6px rgb(from $color-primary r g b / 0.4)",
    [`borderRadius-${COMP}-default`]: "$borderRadius",
    [`borderColor-${COMP}-default`]: "transparent",
    [`borderWidth-${COMP}-default`]: "0",
    [`borderStyle-${COMP}-default`]: "solid",
    [`boxShadow-${COMP}-default`]: "none",

    light: {
      [`backgroundColor-track-${COMP}--disabled`]: "$color-surface-300",
      [`backgroundColor-range-${COMP}--disabled`]: "$color-surface-400",
      [`backgroundColor-thumb-${COMP}`]: "$color-primary-500",
      [`borderColor-thumb-${COMP}`]: "$color-surface-50",
    },
    dark: {
      [`backgroundColor-track-${COMP}--disabled`]: "$color-surface-600",
      [`backgroundColor-range-${COMP}--disabled`]: "$color-surface-800",
      [`backgroundColor-thumb-${COMP}`]: "$color-primary-400",
      [`borderColor-thumb-${COMP}`]: "$color-surface-950",
    },
  },
});

export const sliderComponentRenderer = createComponentRenderer(
  COMP,
  SliderMd,
  ({
    node,
    extractValue,
    lookupEventHandler,
    lookupSyncCallback,
    className,
    updateState,
    state,
    registerComponentApi,
  }) => {
    return (
      <Slider
        validationStatus={extractValue(node.props.validationStatus)}
        minStepsBetweenThumbs={extractValue(node.props?.minStepsBetweenThumbs)}
        value={state.value}
        initialValue={extractValue(node.props.initialValue)}
        updateState={updateState}
        onDidChange={lookupEventHandler("didChange")}
        onFocus={lookupEventHandler("gotFocus")}
        onBlur={lookupEventHandler("lostFocus")}
        registerComponentApi={registerComponentApi}
        className={className}
        step={extractValue(node.props?.step)}
        min={extractValue(node.props?.minValue)}
        max={extractValue(node.props?.maxValue)}
        enabled={extractValue.asOptionalBoolean(node.props?.enabled)}
        autoFocus={extractValue.asOptionalBoolean(node.props.autoFocus)}
        readOnly={extractValue.asOptionalBoolean(node.props.readOnly)}
        required={extractValue.asOptionalBoolean(node.props.required)}
        rangeStyle={extractValue(node.props?.rangeStyle)}
        thumbStyle={extractValue(node.props?.thumbStyle)}
        showValues={extractValue.asOptionalBoolean(node.props?.showValues)}
        valueFormat={lookupSyncCallback(node.props?.valueFormat)}
      />
    );
  },
);

```

--------------------------------------------------------------------------------
/xmlui/src/components-core/theming/component-layout-resolver.ts:
--------------------------------------------------------------------------------

```typescript
import type { CSSProperties } from "react";
import type { LayoutContext } from "../../abstractions/RendererDefs";
import { EMPTY_OBJECT } from "../constants";
import { parseLayoutProperty } from "./parse-layout-props";

export type ResolvedComponentLayout = Record<string, ResolvedPartLayout>;

export type ResolvedPartLayout = {
  baseStyles?: CssPropsWithStates;
  responsiveStyles?: Record<string, CssPropsWithStates>;
};

export type CssPropsWithStates = CSSProperties & {
  states?: Record<string, CSSProperties>;
};

export const THEME_VAR_PREFIX = "xmlui";
export const BASE_COMPONENT_PART = "_base_";
const themeVarCapturesRegex = /(\$[a-zA-Z][a-zA-Z0-9-_]*)/g;
const starSizeRegex = /^\d*\*$/;

export function resolveComponentLayoutProps(
  layoutProps: Record<string, any> = EMPTY_OBJECT,
  layoutContext?: LayoutContext,
): ResolvedComponentLayout {
  const result: ResolvedComponentLayout = {};

  for (const [key, value] of Object.entries(layoutProps)) {
    const parsed = parseLayoutProperty(key, false);

    if (typeof parsed === "string") {
      // --- Ignore failed properties
      continue;
    }

    // --- Process the properties, resolve theme variables to CSS variables
    const cssPropName = parsed.property;
    const appliedValue = value
      ?.toString()
      ?.replace(themeVarCapturesRegex, (match: string) => toCssVar(match.trim()));

    // --- Some properties may need transformation
    const cssProps: CSSProperties =
      cssPropName in specialResolvers
        ? specialResolvers[cssPropName](appliedValue, layoutContext)
        : { [cssPropName]: appliedValue };

    // --- Check if the property belongs to one or more states
    const stateName = parsed.states && parsed.states.length > 0 ? parsed.states.join("&") : null;

    // --- Prepare the place to store the styles. It belongs to the specified part.
    const partName = parsed.part ? parsed.part : BASE_COMPONENT_PART;
    let propertyTarget: any = (result[partName] ??= {});
    if (parsed.screenSizes && parsed.screenSizes.length > 0) {
      const screenSizeKey = parsed.screenSizes.join("&");
      propertyTarget.responsiveStyles ??= {};
      propertyTarget.responsiveStyles[screenSizeKey] ??= {};
      if (stateName) {
        propertyTarget.responsiveStyles[screenSizeKey].states ??= {};
        propertyTarget.responsiveStyles[screenSizeKey].states = {
          ...propertyTarget.responsiveStyles[screenSizeKey].states,
          [stateName]: {
            ...propertyTarget.responsiveStyles[screenSizeKey].states[stateName],
            ...cssProps,
          },
        };
      } else {
        propertyTarget.responsiveStyles[screenSizeKey] = {
          ...propertyTarget.responsiveStyles[screenSizeKey],
          ...cssProps,
        };
      }
    } else {
      // --- No screen sizes specified, the property belongs to the base styles
      propertyTarget.baseStyles ??= {};
      if (stateName) {
        propertyTarget.baseStyles.states ??= {};
        propertyTarget.baseStyles.states = {
          ...propertyTarget.baseStyles.states,
          [stateName]: { ...propertyTarget.baseStyles.states[stateName], ...cssProps },
        };
      } else {
        propertyTarget.baseStyles = { ...propertyTarget.baseStyles, ...cssProps };
      }
    }
  }

  // --- Done
  return result;
}

// --- Checks if the specified size is a star size and the orientation is horizontal
function getHorizontalStarSize(
  size: string | number,
  layoutContext?: LayoutContext,
): number | null {
  if (!size) return null;
  const orientation = getOrientation(layoutContext);
  return orientation === "horizontal" && starSizeRegex.test(size.toString())
    ? getStarSizeNumber(size.toString())
    : null;
}

// --- Checks if the specified size is a star size and the orientation is vertical
function getVerticalStarSize(size: string | number, layoutContext?: LayoutContext): number | null {
  if (!size) return null;
  const orientation = getOrientation(layoutContext);
  return orientation === "vertical" && starSizeRegex.test(size.toString())
    ? getStarSizeNumber(size.toString())
    : null;
}

// ---  Obtains the integer number from a string that matches the starSizeRegex.
function getStarSizeNumber(input: string): number | null {
  if (starSizeRegex.test(input)) {
    const numberPart = input.slice(0, -1); // Remove the trailing '*'
    return numberPart === "" ? 1 : parseInt(numberPart, 10); // Default to 1 if no number is present
  }
  return null;
}

// --- Gets the current orientation from the layout context
function getOrientation(layoutContext?: LayoutContext): string | undefined {
  if (!layoutContext) return;
  let orientation = layoutContext?.type === "Stack" && layoutContext?.orientation;
  return orientation?.toString();
}

function toCssVar(c: string): string {
  return `var(--${THEME_VAR_PREFIX}-${c.substring(1)})`;
}

type SpecialResolver = (propValue: any, layoutContext?: LayoutContext) => CSSProperties;

export const specialResolvers: Record<string, SpecialResolver> = {
  paddingHorizontal: (propValue) => ({
    paddingLeft: propValue,
    paddingRight: propValue,
  }),
  paddingVertical: (propValue) => ({
    paddingTop: propValue,
    paddingBottom: propValue,
  }),
  marginHorizontal: (propValue) => ({
    marginLeft: propValue,
    marginRight: propValue,
  }),
  marginVertical: (propValue) => ({
    marginTop: propValue,
    marginBottom: propValue,
  }),
  borderHorizontal: (propValue) => ({
    borderLeft: propValue,
    borderRight: propValue,
  }),
  borderVertical: (propValue) => ({
    borderTop: propValue,
    borderBottom: propValue,
  }),
  wrapContent: (propValue) => ({
    flexWrap: propValue === "true" ? "wrap" : "nowrap",
  }),
  canShrink: (propValue) => ({
    flexShrink: propValue === "true" ? 1 : 0,
  }),
  width: (propValue, layoutContext) => {
    const horizontalStarSize = getHorizontalStarSize(propValue, layoutContext);
    const result: CSSProperties = {};
    if (horizontalStarSize !== null) {
      // --- We use "flex" when width is in start-size and allow shrinking
      result.flex = horizontalStarSize;
      result.flexShrink = 1;
    } else {
      result.width = propValue;
    }
    return result;
  },
  height: (propValue, layoutContext) => {
    const verticalStarSize = getVerticalStarSize(propValue, layoutContext);
    const result: CSSProperties = {};
    if (verticalStarSize !== null) {
      // --- We use "flex" when height is in start-size and allow shrinking
      result.flex = verticalStarSize;
      result.flexShrink = 1;
    } else {
      result.height = propValue;
    }
    return result;
  },
};

```

--------------------------------------------------------------------------------
/docs/content/components/xmlui-website-blocks/Carousel.md:
--------------------------------------------------------------------------------

```markdown
# Carousel [#carousel]

This component displays a slideshow by cycling through elements (images, text, or custom slides) like a carousel.

## Properties

### `autoplay` (default: false)

Start scrolling the carousel automatically (`true`) or not (`false`).

### `autoplayInterval` (default: 5000)

Specifies the interval between autoplay transitions.

### `controls` (default: true)

Display the previous/next controls (`true`) or not (`false`).

### `indicators` (default: true)

Display the individual slides as buttons (`true`) or not (`false`).

### `loop` (default: false)

Sets whether the carousel should loop back to the start/end when it reaches the last/first slide.

### `nextIcon`

The icon to display for the next control.

### `orientation` (default: "horizontal")

This property indicates the orientation of the carousel. The `horizontal` value indicates that the carousel moves horizontally, and the `vertical` value indicates that the carousel moves vertically.

Available values: `horizontal` **(default)**, `vertical`

### `prevIcon`

The icon to display for the previous control.

### `startIndex` (default: 0)

The index of the first slide to display.

### `stopAutoplayOnInteraction` (default: true)

This property indicates whether autoplay stops on user interaction.

### `transitionDuration` (default: 25)

The duration of the transition between slides.

## Events

### `displayDidChange`

This event is fired when the displayed content of the CarouselNew changes.

## Exposed Methods

### `canScrollNext`

This method returns `true` if the carousel can scroll to the next slide.

**Signature**: `canScrollNext(): boolean`

### `canScrollPrev`

This method returns `true` if the carousel can scroll to the previous slide.

**Signature**: `canScrollPrev(): boolean`

### `scrollNext`

This method scrolls the carousel to the next slide.

**Signature**: `scrollNext(): void`

### `scrollPrev`

This method scrolls the carousel to the previous slide.

**Signature**: `scrollPrev(): void`

### `scrollTo`

This method scrolls the carousel to the specified slide index.

**Signature**: `scrollTo(index: number): void`

- `index`: The index of the slide to scroll to.

## Styling

### Theme Variables

| Variable | Default Value (Light) | Default Value (Dark) |
| --- | --- | --- |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-active-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-active-CarouselNew | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-CarouselNew | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-disabled-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-disabled-CarouselNew | $color-surface-200 | $color-surface-200 |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-hover-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-hover-CarouselNew | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-active-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-active-CarouselNew | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-CarouselNew | $color-surface-200 | $color-surface-200 |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-hover-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-hover-CarouselNew | $color-surface-200 | $color-surface-200 |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-control-Carousel | *none* | *none* |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-control-CarouselNew | 50% | 50% |
| [height](../styles-and-themes/common-units/#size)-Carousel | *none* | *none* |
| [height](../styles-and-themes/common-units/#size)-CarouselNew | 100% | 100% |
| [height](../styles-and-themes/common-units/#size)-control-Carousel | *none* | *none* |
| [height](../styles-and-themes/common-units/#size)-control-CarouselNew | 36px | 36px |
| [height](../styles-and-themes/common-units/#size)-indicator-Carousel | *none* | *none* |
| [height](../styles-and-themes/common-units/#size)-indicator-CarouselNew | 6px | 6px |
| [textColor](../styles-and-themes/common-units/#color)-control-active-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-control-active-CarouselNew | $color-primary | $color-primary |
| [textColor](../styles-and-themes/common-units/#color)-control-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-control-CarouselNew | $textColor | $textColor |
| [textColor](../styles-and-themes/common-units/#color)-control-disabled-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-control-disabled-CarouselNew | $textColor-disabled | $textColor-disabled |
| [textColor](../styles-and-themes/common-units/#color)-control-hover-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-control-hover-CarouselNew | $textColor | $textColor |
| [textColor](../styles-and-themes/common-units/#color)-indicator-active-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-indicator-active-CarouselNew | $color-primary | $color-primary |
| [textColor](../styles-and-themes/common-units/#color)-indicator-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-indicator-CarouselNew | $color-primary | $color-primary |
| [textColor](../styles-and-themes/common-units/#color)-indicator-hover-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-indicator-hover-CarouselNew | $color-primary | $color-primary |
| [width](../styles-and-themes/common-units/#size)-Carousel | *none* | *none* |
| [width](../styles-and-themes/common-units/#size)-CarouselNew | 100% | 100% |
| [width](../styles-and-themes/common-units/#size)-control-Carousel | *none* | *none* |
| [width](../styles-and-themes/common-units/#size)-control-CarouselNew | 36px | 36px |
| [width](../styles-and-themes/common-units/#size)-indicator-Carousel | *none* | *none* |
| [width](../styles-and-themes/common-units/#size)-indicator-CarouselNew | 25px | 25px |

```

--------------------------------------------------------------------------------
/docs/content/extensions/xmlui-website-blocks/Carousel.md:
--------------------------------------------------------------------------------

```markdown
# Carousel [#carousel]

This component displays a slideshow by cycling through elements (images, text, or custom slides) like a carousel.

## Properties

### `autoplay` (default: false)

Start scrolling the carousel automatically (`true`) or not (`false`).

### `autoplayInterval` (default: 5000)

Specifies the interval between autoplay transitions.

### `controls` (default: true)

Display the previous/next controls (`true`) or not (`false`).

### `indicators` (default: true)

Display the individual slides as buttons (`true`) or not (`false`).

### `loop` (default: false)

Sets whether the carousel should loop back to the start/end when it reaches the last/first slide.

### `nextIcon`

The icon to display for the next control.

### `orientation` (default: "horizontal")

This property indicates the orientation of the carousel. The `horizontal` value indicates that the carousel moves horizontally, and the `vertical` value indicates that the carousel moves vertically.

Available values: `horizontal` **(default)**, `vertical`

### `prevIcon`

The icon to display for the previous control.

### `startIndex` (default: 0)

The index of the first slide to display.

### `stopAutoplayOnInteraction` (default: true)

This property indicates whether autoplay stops on user interaction.

### `transitionDuration` (default: 25)

The duration of the transition between slides.

## Events

### `displayDidChange`

This event is fired when the displayed content of the CarouselNew changes.

## Exposed Methods

### `canScrollNext`

This method returns `true` if the carousel can scroll to the next slide.

**Signature**: `canScrollNext(): boolean`

### `canScrollPrev`

This method returns `true` if the carousel can scroll to the previous slide.

**Signature**: `canScrollPrev(): boolean`

### `scrollNext`

This method scrolls the carousel to the next slide.

**Signature**: `scrollNext(): void`

### `scrollPrev`

This method scrolls the carousel to the previous slide.

**Signature**: `scrollPrev(): void`

### `scrollTo`

This method scrolls the carousel to the specified slide index.

**Signature**: `scrollTo(index: number): void`

- `index`: The index of the slide to scroll to.

## Styling

### Theme Variables

| Variable | Default Value (Light) | Default Value (Dark) |
| --- | --- | --- |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-active-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-active-CarouselNew | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-CarouselNew | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-disabled-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-disabled-CarouselNew | $color-surface-200 | $color-surface-200 |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-hover-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-control-hover-CarouselNew | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-active-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-active-CarouselNew | $color-primary | $color-primary |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-CarouselNew | $color-surface-200 | $color-surface-200 |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-hover-Carousel | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-indicator-hover-CarouselNew | $color-surface-200 | $color-surface-200 |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-control-Carousel | *none* | *none* |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-control-CarouselNew | 50% | 50% |
| [height](../styles-and-themes/common-units/#size)-Carousel | *none* | *none* |
| [height](../styles-and-themes/common-units/#size)-CarouselNew | 100% | 100% |
| [height](../styles-and-themes/common-units/#size)-control-Carousel | *none* | *none* |
| [height](../styles-and-themes/common-units/#size)-control-CarouselNew | 36px | 36px |
| [height](../styles-and-themes/common-units/#size)-indicator-Carousel | *none* | *none* |
| [height](../styles-and-themes/common-units/#size)-indicator-CarouselNew | 6px | 6px |
| [textColor](../styles-and-themes/common-units/#color)-control-active-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-control-active-CarouselNew | $color-primary | $color-primary |
| [textColor](../styles-and-themes/common-units/#color)-control-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-control-CarouselNew | $textColor | $textColor |
| [textColor](../styles-and-themes/common-units/#color)-control-disabled-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-control-disabled-CarouselNew | $textColor-disabled | $textColor-disabled |
| [textColor](../styles-and-themes/common-units/#color)-control-hover-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-control-hover-CarouselNew | $textColor | $textColor |
| [textColor](../styles-and-themes/common-units/#color)-indicator-active-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-indicator-active-CarouselNew | $color-primary | $color-primary |
| [textColor](../styles-and-themes/common-units/#color)-indicator-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-indicator-CarouselNew | $color-primary | $color-primary |
| [textColor](../styles-and-themes/common-units/#color)-indicator-hover-Carousel | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-indicator-hover-CarouselNew | $color-primary | $color-primary |
| [width](../styles-and-themes/common-units/#size)-Carousel | *none* | *none* |
| [width](../styles-and-themes/common-units/#size)-CarouselNew | 100% | 100% |
| [width](../styles-and-themes/common-units/#size)-control-Carousel | *none* | *none* |
| [width](../styles-and-themes/common-units/#size)-control-CarouselNew | 36px | 36px |
| [width](../styles-and-themes/common-units/#size)-indicator-Carousel | *none* | *none* |
| [width](../styles-and-themes/common-units/#size)-indicator-CarouselNew | 25px | 25px |

```

--------------------------------------------------------------------------------
/xmlui/src/components/Timer/TimerNative.tsx:
--------------------------------------------------------------------------------

```typescript
import type { CSSProperties, ForwardedRef } from "react";
import { forwardRef, useEffect, useRef, useState, useCallback, useMemo } from "react";
import type { RegisterComponentApiFn } from "../../abstractions/RendererDefs";

export interface TimerApi {
  pause(): void;
  resume(): void;
  isPaused(): boolean;
  isRunning(): boolean;
}

export const defaultProps = {
  enabled: true,
  interval: 1000,
  once: false,
  initialDelay: 0,
};

type TimerProps = {
  enabled?: boolean;
  interval?: number;
  once?: boolean;
  initialDelay?: number;
  onTick?: () => void | Promise<void>;
  registerComponentApi?: RegisterComponentApiFn;
  style?: CSSProperties;
  className?: string;
} & React.HTMLAttributes<HTMLDivElement>;

export const Timer = forwardRef(function Timer(
  {
    enabled = defaultProps.enabled,
    interval = defaultProps.interval,
    once = defaultProps.once,
    initialDelay = defaultProps.initialDelay,
    onTick,
    registerComponentApi,
    style,
    className,
    ...rest
  }: TimerProps,
  forwardedRef: ForwardedRef<HTMLDivElement>,
) {
  const [isPaused, setIsPaused] = useState(false);
  const [hasExecutedOnce, setHasExecutedOnce] = useState(false);
  const [hasEverStarted, setHasEverStarted] = useState(false);
  const intervalRef = useRef<NodeJS.Timeout | null>(null);
  const initialDelayRef = useRef<NodeJS.Timeout | null>(null);
  const handlerRunningRef = useRef(false);

  // Refs for current values to ensure handleTick has stable dependencies
  const enabledRef = useRef(enabled);
  const isPausedRef = useRef(isPaused);
  const intervalRef2 = useRef(interval);
  const onTickRef = useRef(onTick);
  const onceRef = useRef(once);
  const hasExecutedOnceRef = useRef(hasExecutedOnce);
  const hasEverStartedRef = useRef(hasEverStarted);

  // Update refs when values change
  enabledRef.current = enabled;
  isPausedRef.current = isPaused;
  intervalRef2.current = interval;
  onTickRef.current = onTick;
  onceRef.current = once;
  hasExecutedOnceRef.current = hasExecutedOnce;
  hasEverStartedRef.current = hasEverStarted;

  // Derived state
  const isRunning = enabled && !isPaused && (intervalRef.current !== null || initialDelayRef.current !== null);
  const isInInitialDelay = initialDelayRef.current !== null;

  // Timer API methods
  const pause = useCallback(() => {
    // Pause if timer is enabled and currently running (not already paused)
    if (enabled && !isPaused) {
      setIsPaused(true);
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
        intervalRef.current = null;
      }
      if (initialDelayRef.current) {
        clearTimeout(initialDelayRef.current);
        initialDelayRef.current = null;
      }
    }
  }, [enabled, isPaused]);

  const resume = useCallback(() => {
    // Resume if timer is enabled and currently paused
    if (enabled && isPaused) {
      setIsPaused(false);
      // The useEffect will handle restarting the timer
    }
  }, [enabled, isPaused]);

  // Create API object once
  const timerApi = useMemo(() => ({
    pause,
    resume,
    isPaused: () => isPaused,
    isRunning: () => isRunning && !isPaused,
  }), [pause, resume, isPaused, isRunning]);

  // Register both APIs together
  useEffect(() => {
    if (registerComponentApi) {
      registerComponentApi(timerApi);
    }
  }, [registerComponentApi, timerApi]);

  const handleTick = useCallback(async () => {
    // Check if timer should still be running (enabled, not paused, valid interval)
    if (!enabledRef.current || isPausedRef.current || intervalRef2.current <= 0) {
      return;
    }

    // Prevent re-firing if the previous event hasn't completed yet
    if (handlerRunningRef.current) {
      return;
    }

    if (onTickRef.current) {
      handlerRunningRef.current = true;
      try {
        await onTickRef.current();
        
        // Mark that the timer has actually started executing (for initial delay logic)
        if (!hasEverStartedRef.current) {
          setHasEverStarted(true);
        }
        
        // If this is a "once" timer and it's the very first execution, mark it as executed
        // After the first execution, the timer becomes a regular timer that can be paused/resumed
        if (onceRef.current && !hasExecutedOnceRef.current) {
          setHasExecutedOnce(true);
        }
      } finally {
        handlerRunningRef.current = false;
      }
    }
  }, []);

  useEffect(() => {
    // Clear any existing timers first
    if (intervalRef.current) {
      clearInterval(intervalRef.current);
      intervalRef.current = null;
    }
    if (initialDelayRef.current) {
      clearTimeout(initialDelayRef.current);
      initialDelayRef.current = null;
    }

    // If "once" is true and the timer has already executed, don't start the timer
    if (once && hasExecutedOnce) {
      return;
    }

    if (enabled && !isPaused && interval > 0) {
      // Helper to start the actual timer
      const startTicking = () => {
        intervalRef.current = (once && !hasExecutedOnce) 
          ? setTimeout(handleTick, interval) as any
          : setInterval(handleTick, interval);
      };

      // Only apply initial delay if timer has never been started before
      if (initialDelay > 0 && !hasEverStarted) {
        initialDelayRef.current = setTimeout(() => {
          initialDelayRef.current = null;
          startTicking();
        }, initialDelay);
      } else {
        startTicking();
      }
    }

    return () => {
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
        intervalRef.current = null;
      }
      if (initialDelayRef.current) {
        clearTimeout(initialDelayRef.current);
        initialDelayRef.current = null;
      }
    };
  }, [enabled, interval, once, hasExecutedOnce, isPaused, initialDelay, hasEverStarted]);

  // Reset state when enabled changes
  useEffect(() => {
    if (enabled && once) {
      // Reset hasExecutedOnce when enabled changes from false to true for "once" timers
      setHasExecutedOnce(false);
    }
    if (!enabled) {
      // Reset pause state when timer is disabled
      setIsPaused(false);
    }
  }, [enabled, once]);

  // Timer is a non-visual component
  return (
    <div
      ref={forwardedRef}
      style={{ display: "none", ...style }}
      className={className}
      data-timer-enabled={enabled}
      data-timer-interval={interval}
      data-timer-initial-delay={initialDelay}
      data-timer-once={once}
      data-timer-running={isRunning}
      data-timer-paused={isPaused}
      data-timer-in-initial-delay={isInInitialDelay}
      data-timer-has-executed={hasExecutedOnce}
      {...rest}
    />
  );
});

```

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

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

$themeVars: ();
@function createThemeVar($componentVariable) {
  $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global;
  @return t.getThemeVar($themeVars, $componentVariable);
}

$component: "TableOfContents";
$backgroundColor-TableOfContents: createThemeVar("backgroundColor-#{$component}");
$width-TableOfContents: createThemeVar("width-#{$component}");
$height-TableOfContents: createThemeVar("height-#{$component}");
$themeVars: t.composeBorderVars($themeVars, $component);
$themeVars: t.composePaddingVars($themeVars, $component);

$componentItem: "TableOfContentsItem";
$themeVars: t.composeTextVars($themeVars, $componentItem);
$themeVars: t.composeBorderVars($themeVars, $componentItem);
$themeVars: t.composeBorderVars($themeVars, "#{$componentItem}--hover");
$themeVars: t.composeBorderVars($themeVars, "#{$componentItem}--active");
$themeVars: t.composePaddingVars($themeVars, $componentItem);
$themeVars: t.composePaddingVars($themeVars, "#{$componentItem}-level-1");
$themeVars: t.composeTextVars($themeVars, "#{$componentItem}-level-1");
$themeVars: t.composePaddingVars($themeVars, "#{$componentItem}-level-2");
$themeVars: t.composeTextVars($themeVars, "#{$componentItem}-level-2");
$themeVars: t.composePaddingVars($themeVars, "#{$componentItem}-level-3");
$themeVars: t.composeTextVars($themeVars, "#{$componentItem}-level-3");
$themeVars: t.composePaddingVars($themeVars, "#{$componentItem}-level-4");
$themeVars: t.composeTextVars($themeVars, "#{$componentItem}-level-4");
$themeVars: t.composePaddingVars($themeVars, "#{$componentItem}-level-5");
$themeVars: t.composeTextVars($themeVars, "#{$componentItem}-level-5");
$themeVars: t.composePaddingVars($themeVars, "#{$componentItem}-level-6");
$themeVars: t.composeTextVars($themeVars, "#{$componentItem}-level-6");

@layer components {
  .nav {
    border-width: createThemeVar("borderWidth-#{$component}");
    border-color: createThemeVar("borderColor-#{$component}");
    border-style: createThemeVar("borderStyle-#{$component}");
    @include t.borderVars($themeVars, $component);
    @include t.paddingVars($themeVars, $component);
    background-color: $backgroundColor-TableOfContents;
    min-width: 250px;
    align-self: flex-start;
    width: $width-TableOfContents;
    height: $height-TableOfContents;
    max-height: calc(100vh - var(--header-abs-height) - var(--footer-abs-height));
    overflow-y: auto;
    overflow-x: hidden;
    z-index: 99;
    top: var(--header-height);
    position: sticky;
    scrollbar-width: thin;
    // --- Do not collapse these padding properties; they are intentionally expanded
    margin-top: createThemeVar("marginTop-#{$component}");
    margin-bottom: createThemeVar("marginBottom-#{$component}");

    .list {
      margin: 0;
      padding: 0;
      list-style: none;

      .listItem {
        list-style-type: none;
        @include t.borderVars($themeVars, $componentItem);

        .link {
          display: block;
          overflow-wrap: break-word;
          color: createThemeVar("textColor-#{$componentItem}");
          @include t.paddingVars($themeVars, $componentItem);
          @include t.textVars($themeVars, $componentItem);

          &.head_1 {
            @include t.paddingVars($themeVars, "#{$componentItem}-level-1");
            @include t.textVars($themeVars, "#{$componentItem}-level-1");
          }

          &.head_2 {
            @include t.paddingVars($themeVars, "#{$componentItem}-level-2");
            @include t.textVars($themeVars, "#{$componentItem}-level-2");
          }

          &.head_3 {
            @include t.paddingVars($themeVars, "#{$componentItem}-level-3");
            @include t.textVars($themeVars, "#{$componentItem}-level-3");
          }

          &.head_4 {
            @include t.paddingVars($themeVars, "#{$componentItem}-level-4");
            @include t.textVars($themeVars, "#{$componentItem}-level-4");
          }

          &.head_5 {
            @include t.paddingVars($themeVars, "#{$componentItem}-level-5");
            @include t.textVars($themeVars, "#{$componentItem}-level-5");
          }

          &.head_6 {
            @include t.paddingVars($themeVars, "#{$componentItem}-level-6");
            @include t.textVars($themeVars, "#{$componentItem}-level-6");
          }
        }

        &:hover {
          @include t.borderVars($themeVars, "#{$componentItem}--hover");
          background-color: createThemeVar("backgroundColor-#{$componentItem}--hover");

          .link {
            font-weight: createThemeVar("fontWeight-#{$componentItem}--hover");
            color: createThemeVar("textColor-#{$componentItem}--hover");

            &.head_1 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-1--hover");
            }
            &.head_2 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-2--hover");
            }
            &.head_3 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-3--hover");
            }
            &.head_4 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-4--hover");
            }
            &.head_5 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-5--hover");
            }
            &.head_6 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-6--hover");
            }
          }
        }

        &.active {
          @include t.borderVars($themeVars, "#{$componentItem}--active");
          background-color: createThemeVar("backgroundColor-#{$componentItem}--active");

          .link {
            color: createThemeVar("textColor-#{$componentItem}--active");
            font-weight: createThemeVar("fontWeight-#{$componentItem}--active");

            &.head_1 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-1--active");
            }
            &.head_2 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-2--active");
            }
            &.head_3 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-3--active");
            }
            &.head_4 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-4--active");
            }
            &.head_5 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-5--active");
            }
            &.head_6 {
              font-weight: createThemeVar("fontWeight-#{$componentItem}-level-6--active");
            }
          }
        }
      }
    }
  }
}

:export {
  themeVars: t.json-stringify($themeVars);
}

```

--------------------------------------------------------------------------------
/xmlui/src/components-core/theming/StyleRegistry.ts:
--------------------------------------------------------------------------------

```typescript
// app/utils/styleUtils.ts

import type { CSSProperties } from 'react';

// --- Type Definitions ---

// This type definition is now more powerful. It allows a value to be another
// style object, enabling true nesting.
export type StyleObjectType =
  CSSProperties & {
  [selectorOrAtRule: string]: StyleObjectType | CSSProperties[keyof CSSProperties];
};

interface StyleCacheEntry {
  className: string;
  styleHash: string;
  css: string;
}

// --- Helper Functions ---

function hashString(str: string): string {
  let hash = 5381;
  let i = str.length;
  while (i) {
    hash = (hash * 33) ^ str.charCodeAt(--i);
  }
  let s = (hash >>> 0).toString(36);
  // console.log("hashString", str, "->", s);
  return s;
}

/**
 * Converts a camelCase string to kebab-case, but ignores CSS Custom Properties.
 * @param {string} str The string to convert.
 * @returns {string} The formatted string.
 */
function toKebabCase(str: string): string {
  // NEW: If the string is a CSS Custom Property (starts with '--'),
  // return it as-is without any changes.
  if (str.startsWith('--')) {
    return str;
  }
  // Otherwise, convert from camelCase to kebab-case as before.
  return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
}


/**
 * Creates a stable, canonical JSON string from an object by sorting keys recursively.
 * This ensures that objects with the same content produce the same string regardless of key order.
 * @param obj The object to stringify.
 * @returns A stable string representation.
 */
function stableJSONStringify(obj: any): string {
  return JSON.stringify(obj);
  // if (obj === null || typeof obj !== 'object') {
  //   return JSON.stringify(obj);
  // }
  //
  // if (Array.isArray(obj)) {
  //   const arrayStr = obj.map(item => stableJSONStringify(item)).join(',');
  //   return `[${arrayStr}]`;
  // }
  //
  // const keys = Object.keys(obj).sort();
  // const props = keys.map(key => {
  //   const value = stableJSONStringify(obj[key]);
  //   return `"${key}":${value}`;
  // });
  //
  // return `{${props.join(',')}}`;
}

// --- The StyleRegistry Class (with updated logic) ---

export class StyleRegistry {
  public cache: Map<string, StyleCacheEntry> = new Map();
  public rootClasses: Set<string> = new Set();
  public injected: Set<string> = new Set();

  // NEW: A map to track how many components are using a style.
  public refCounts: Map<string, number> = new Map();

  // NEW: A set to specifically track hashes injected by SSR.
  public ssrHashes: Set<string> = new Set();

  public register(styles: StyleObjectType): StyleCacheEntry {
    const key = stableJSONStringify(styles);
    const styleHash = hashString(key);

    const cachedEntry = this.cache.get(styleHash);
    if (cachedEntry) {
      return cachedEntry;
    }

    // The entry point for our new recursive generator.
    const className = `css-${styleHash}`;
    const css = this._generateCss(`.${className}`, styles);

    const entry: StyleCacheEntry = { className, styleHash, css };
    this.cache.set(styleHash, entry);
    return entry;
  }

  /**
   * [PRIVATE] Recursively generates CSS rules from a style object.
   * This is the new, more powerful engine.
   * @param selector - The CSS selector for the current context (e.g., '.css-123' or '&:hover').
   * @param styles - The style object to process.
   * @returns A string of CSS rules.
   */
  private _generateCss(selector: string, styles: StyleObjectType): string {
    const directProps: string[] = [];
    const nestedRules: string[] = [];

    // 1. Separate direct CSS properties from nested rules.
    for (const key in styles) {
      const value = styles[key];
      if (typeof value === 'object' && value !== null) {
        // It's a nested rule (e.g., '&:hover', '@media').
        nestedRules.push(this._processNestedRule(selector, key, value as StyleObjectType));
      } else {
        // It's a direct CSS property (e.g., 'backgroundColor').
        directProps.push(`${toKebabCase(key)}:${value};`);
      }
    }

    let finalCss = '';

    // 2. Generate the CSS for the direct properties at the current selector level.
    if (directProps.length > 0) {
      finalCss += `${selector} {${directProps.join('')}}`;
    }

    // 3. Append the CSS from all the processed nested rules.
    finalCss += nestedRules.join('');

    return finalCss;
  }

  private _processNestedRule(parentSelector: string, nestedKey: string, nestedStyles: StyleObjectType): string {
    // If the key is an at-rule (@media, @container, @keyframes), wrap the recursive call.
    if (nestedKey.startsWith('@')) {
      // The inner content is generated relative to the original parent selector.
      return `${nestedKey}{${this._generateCss(parentSelector, nestedStyles)}}`;
    }

    // If the key is a nested selector, resolve the '&' placeholder.
    // e.g., parent='.css-123', nestedKey='&:hover' -> '.css-123:hover'
    const newSelector = nestedKey.replace(/&/g, parentSelector);
    return this._generateCss(newSelector, nestedStyles);
  }

  public getSsrStyles(): string {
    const allCss = Array.from(this.cache.values()).map(entry => entry.css).join('');
    // Wrap the entire output in our top-most layer.
    return `@layer dynamic {${allCss}}`;
  }

  /**
   * Adds a class name to be applied to the <html> tag.
   */
  public addRootClasses(classNames: Array<string>): void {
    classNames.forEach((className)=>{
      this.rootClasses.add(className);
    });
  }

  /**
   * Returns a space-separated string of all collected html classes.
   */
  public getRootClasses(): string {
    return Array.from(this.rootClasses).join(' ');
  }



  // NEW: A helper to safely get the current reference count.
  public getRefCount(styleHash: string): number {
    return this.refCounts.get(styleHash) || 0;
  }


  /**
   * Increments the reference count for a given style hash.
   */
  public incrementRef(styleHash: string): void {
    const newCount = (this.refCounts.get(styleHash) || 0) + 1;
    this.refCounts.set(styleHash, newCount);
    // console.log("incrementing ref count for styleHash:", styleHash, "to", newCount);
  }

  /**
   * Decrements the reference count for a given style hash.
   * @returns {number} The new reference count.
   */
  public decrementRef(styleHash: string): number {
    const currentCount = this.refCounts.get(styleHash) || 0;
    const newCount = Math.max(0, currentCount - 1);
    // console.log("decrementing ref count for styleHash:", styleHash, "from", currentCount, "to", newCount);

    if (newCount > 0) {
      this.refCounts.set(styleHash, newCount);
    } else {
      // If the count is zero, remove it from the map.
      this.refCounts.delete(styleHash);
    }

    return newCount;
  }
}
```

--------------------------------------------------------------------------------
/packages/xmlui-playground/src/utils/helpers.ts:
--------------------------------------------------------------------------------

```typescript
import type { PlaygroundState } from "../state/store";
import JSZip from "jszip";
import { saveAs } from "file-saver";
import {
  type ComponentDef,
  type CompoundComponentDef,
  type ThemeDefinition,
  XmlUiHelper,
  type XmlUiNode,
} from "xmlui";
import { decompress } from "../playground/utils";
import { base64ToUint8Array } from "../../../../xmlui/src/components-core/utils/base64-utils";

export function normalizePath(url?: string): string | undefined {
  if (!url) {
    return undefined;
  }
  if (url.startsWith("http://") || url.startsWith("https://")) {
    return url;
  }
  if (typeof window === "undefined") {
    return url;
  }
  // @ts-ignore
  const prefix = window.__PUBLIC_PATH || "";
  if (!prefix) {
    return url;
  }
  const prefixWithoutTrailingSlash = prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
  const urlWithoutLeadingSlash = url.startsWith("/") ? url.slice(1) : url;

  return `${prefixWithoutTrailingSlash}/${urlWithoutLeadingSlash}`;
}

async function fetchWithoutCache(url: string) {
  return fetch(normalizePath(url) as any, {
    headers: {
      "Cache-Control": "no-cache, no-store",
    },
  });
}

export function serialize(component: ComponentDef | CompoundComponentDef): string {
  if (component) {
    const xh = new XmlUiHelper();
    try {
      const node = xh.transformComponentDefinition(component) as XmlUiNode;
      return xh.serialize(node, { prettify: true });
    } catch (e) {
      console.log(e);
      return "";
    }
  }
  return "";
}

export async function decompressData(source: string) {
  const base64 = decodeURIComponent(source);
  const compressed = base64ToUint8Array(base64);
  return await decompress(compressed);
}

export const INITIAL_PLAYGROUND_STATE: PlaygroundState = {
  editorStatus: "idle",
  status: "idle",
  options: {
    orientation: "horizontal",
    swapped: false,
    content: "app",
    previewMode: false,
    id: 0,
    language: "xmlui",
  },
  text: "",
  appDescription: {
    config: {
      name: "",
      appGlobals: {},
      resources: {},
      themes: [],
    },
    components: [],
    app: "",
  },
  originalAppDescription: {
    config: {
      name: "",
      appGlobals: {},
      resources: {},
      themes: [],
    },
    components: [],
    app: "",
  },
  error: null,
};

function removeWhitespace(obj: any) {
  if (typeof obj === "string") {
    return obj.replace(/\s+/g, " ").trim(); // Remove extra whitespaces and newlines
  } else if (obj !== null && typeof obj === "object") {
    const newObj: any = Array.isArray(obj) ? [] : {};
    for (const key in obj) {
      newObj[key] = removeWhitespace(obj[key]);
    }
    return newObj;
  }
  return obj; // Return the value as is if not a string or object
}

export const handleDownloadZip = async (appDescription: any) => {
  const operatingSystem = getOperatingSystem();

  const zip = new JSZip();

  const xmluiFolder = zip.folder("xmlui");
  const xmluiStandalone = await fetchWithoutCache(
    "/resources/files/for-download/xmlui/xmlui-standalone.umd.js",
  ).then((res) => res.blob());
  xmluiFolder?.file("xmlui-standalone.umd.js", xmluiStandalone);

  zip.file("Main.xmlui", appDescription.app);
  zip.file("config.json", JSON.stringify(appDescription.config, null, 2));

  if (appDescription.components.length > 0) {
    const components = zip.folder("components");
    appDescription.components.forEach((component: { name: string; component: string }) => {
      components?.file(`${component.name}.xmlui`, component.component);
    });
  }
  if (appDescription.config.themes.length > 0) {
    const themes = zip.folder("themes");
    appDescription.config.themes.forEach((theme: ThemeDefinition) => {
      themes?.file(`${theme.id}.json`, JSON.stringify(theme, null, 2));
    });
  }

  const emulatedApi = appDescription.api;
  if (emulatedApi) {
    const indexWithApiHtml = await fetchWithoutCache(
      "/resources/files/for-download/index-with-api.html",
    ).then((res) => res.blob());
    zip.file("index.html", indexWithApiHtml);
    xmluiFolder?.file(
      "mockApiDef.js",
      `window.XMLUI_MOCK_API = ${JSON.stringify(removeWhitespace(emulatedApi), null, 2)};`,
    );

    const emulatedApiWorker = await fetchWithoutCache(
      "/resources/files/for-download/mockApi.js",
    ).then((res) => res.blob());
    zip.file("mockApi.js", emulatedApiWorker);
  } else {
    const indexHtml = await fetchWithoutCache("/resources/files/for-download/index.html").then(
      (res) => res.blob(),
    );
    zip.file("index.html", indexHtml);
  }

  const startBat = await fetchWithoutCache("/resources/files/for-download/start.bat").then((res) =>
    res.blob(),
  );

  if (operatingSystem === "Windows") {
    zip.file("start.bat", startBat);
  } else {
    let fileName = operatingSystem === "Linux" ? "start-linux.sh" : "start-darwin.sh";
    const startSh = await fetchWithoutCache(`/resources/files/for-download/${fileName}`).then(
      (res) => res.blob(),
    );
    zip.file("start.sh", startSh, {
      unixPermissions: "777",
    });
  }

  try {
    const content = await zip.generateAsync({
      type: "blob",
      platform: operatingSystem === "Windows" ? "DOS" : "UNIX",
    });
    saveAs(content, `${(appDescription.config.name || "xmlui-playground-app").trim()}.zip`);
  } catch (error) {
    console.error("An error occurred while generating the ZIP:", error);
  }
};

export function preprocessCode(code: string): string {
  // Split code by newlines
  const lines = code.split("\n");

  // Remove whitespace-only lines from the beginning and end
  let start = 0;
  while (start < lines.length && lines[start].trim() === "") {
    start++;
  }

  let end = lines.length - 1;
  while (end >= 0 && lines[end].trim() === "") {
    end--;
  }

  const trimmedLines = lines.slice(start, end + 1);

  // Calculate the minimum indentation
  const minIndent = Math.min(
    ...trimmedLines
      .filter((line) => line.trim() !== "") // Ignore empty lines for indentation
      .map((line) => line.match(/^\s*/)?.[0].length || 0), // Count leading spaces
  );

  // Remove minIndent spaces from the beginning of each line
  const result = trimmedLines.map((line) =>
    line.startsWith(" ".repeat(minIndent)) ? line.slice(minIndent) : line,
  );

  // Join lines back into a single string
  return result.join("\n");
}

function getOperatingSystem() {
  const userAgent = window.navigator.userAgent;
  const platform = window.navigator.platform;

  if (/Win/.test(platform)) {
    return "Windows";
  }
  if (/Mac/.test(platform)) {
    return "MacOS";
  }
  if (/Linux/.test(platform)) {
    return "Linux";
  }
  if (/Android/.test(userAgent)) {
    return "Android";
  }
  if (/iPhone|iPad|iPod/.test(userAgent)) {
    return "iOS";
  }
  return "Unknown OS";
}

```

--------------------------------------------------------------------------------
/xmlui/scripts/generate-docs/logging-standards.mjs:
--------------------------------------------------------------------------------

```
import { logger } from "./logger.mjs";

/**
 * Standardized logging utilities for documentation generation scripts
 * Provides consistent logging patterns and message formatting
 */

/**
 * Log levels in order of severity (lowest to highest)
 */
export const LOG_LEVELS = {
  INFO: "info",
  WARN: "warn", 
  ERROR: "error"
};

/**
 * Standard logging patterns for common operations
 */
export const LOGGING_PATTERNS = {
  // Operation start/completion
  OPERATION_START: (operation) => `Starting ${operation}...`,
  OPERATION_COMPLETE: (operation) => `Completed ${operation}`,
  OPERATION_FAILED: (operation, error) => `Failed ${operation}: ${error}`,
  
  // File operations
  FILE_PROCESSING: (filePath) => `Processing file: ${filePath}`,
  FILE_WRITTEN: (filePath) => `Written file: ${filePath}`,
  FILE_DELETED: (filePath) => `Deleted file: ${filePath}`,
  FILE_NOT_FOUND: (filePath) => `File not found: ${filePath}`,
  
  // Directory operations  
  DIRECTORY_CREATED: (dirPath) => `Created directory: ${dirPath}`,
  DIRECTORY_CLEANED: (dirPath) => `Cleaned directory: ${dirPath}`,
  
  // Component processing
  COMPONENT_PROCESSING: (componentName) => `Processing component: ${componentName}`,
  COMPONENT_SKIPPED: (componentName, reason) => `Skipped component ${componentName}: ${reason}`,
  
  // Package/Extension operations
  PACKAGE_LOADING: (packageName) => `Loading package: ${packageName}`,
  PACKAGE_LOADED: (packageName) => `Loaded package: ${packageName}`,
  PACKAGE_SKIPPED: (packageName, reason) => `Skipped package ${packageName}: ${reason}`,
  
  // Configuration
  CONFIG_LOADING: (configPath) => `Loading configuration from: ${configPath}`,
  CONFIG_LOADED: (configPath) => `Configuration loaded from: ${configPath}`,
  
  // Progress indicators
  PROGRESS: (current, total, operation) => `Progress: ${current}/${total} ${operation}`,
  
  // Validation
  VALIDATION_PASSED: (item) => `Validation passed: ${item}`,
  VALIDATION_FAILED: (item, reason) => `Validation failed for ${item}: ${reason}`,
  
  // Generic warnings and errors
  DEPRECATION_WARNING: (feature) => `DEPRECATED: ${feature} is deprecated and will be removed in a future version`,
  FEATURE_NOT_SUPPORTED: (feature) => `Feature not supported: ${feature}`,
  UNEXPECTED_CONDITION: (condition) => `Unexpected condition encountered: ${condition}`
};

/**
 * Standardized logging functions with consistent formatting
 */
export const standardLogger = {
  /**
   * Log an informational message
   */
  info: (message, ...additionalArgs) => {
    if (additionalArgs.length > 0) {
      logger.info(message, ...additionalArgs);
    } else {
      logger.info(message);
    }
  },

  /**
   * Log a warning message
   */
  warn: (message, ...additionalArgs) => {
    if (additionalArgs.length > 0) {
      logger.warn(message, ...additionalArgs);
    } else {
      logger.warn(message);
    }
  },

  /**
   * Log an error message
   */
  error: (message, ...additionalArgs) => {
    if (additionalArgs.length > 0) {
      logger.error(message, ...additionalArgs);
    } else {
      logger.error(message);
    }
  },

  /**
   * Log the start of an operation
   */
  operationStart: (operation) => {
    logger.info(LOGGING_PATTERNS.OPERATION_START(operation));
  },

  /**
   * Log the completion of an operation
   */
  operationComplete: (operation) => {
    logger.info(LOGGING_PATTERNS.OPERATION_COMPLETE(operation));
  },

  /**
   * Log a failed operation
   */
  operationFailed: (operation, error) => {
    logger.error(LOGGING_PATTERNS.OPERATION_FAILED(operation, error));
  },

  /**
   * Log file processing
   */
  fileProcessing: (filePath) => {
    logger.info(LOGGING_PATTERNS.FILE_PROCESSING(filePath));
  },

  /**
   * Log successful file write
   */
  fileWritten: (filePath) => {
    logger.info(LOGGING_PATTERNS.FILE_WRITTEN(filePath));
  },

  /**
   * Log component processing
   */
  componentProcessing: (componentName) => {
    logger.info(LOGGING_PATTERNS.COMPONENT_PROCESSING(componentName));
  },

  /**
   * Log skipped component
   */
  componentSkipped: (componentName, reason) => {
    logger.warn(LOGGING_PATTERNS.COMPONENT_SKIPPED(componentName, reason));
  },

  /**
   * Log package loading
   */
  packageLoading: (packageName) => {
    logger.info(LOGGING_PATTERNS.PACKAGE_LOADING(packageName));
  },

  /**
   * Log package loaded
   */
  packageLoaded: (packageName) => {
    logger.info(LOGGING_PATTERNS.PACKAGE_LOADED(packageName));
  },

  /**
   * Log skipped package
   */
  packageSkipped: (packageName, reason) => {
    logger.warn(LOGGING_PATTERNS.PACKAGE_SKIPPED(packageName, reason));
  },

  /**
   * Log configuration loading
   */
  configLoading: (configPath) => {
    logger.info(LOGGING_PATTERNS.CONFIG_LOADING(configPath));
  },

  /**
   * Log progress
   */
  progress: (current, total, operation) => {
    logger.info(LOGGING_PATTERNS.PROGRESS(current, total, operation));
  },

  /**
   * Log deprecation warning
   */
  deprecationWarning: (feature) => {
    logger.warn(LOGGING_PATTERNS.DEPRECATION_WARNING(feature));
  }
};

/**
 * Creates a scoped logger for a specific module/operation
 */
export function createScopedLogger(scope) {
  return {
    info: (message, ...args) => standardLogger.info(`[${scope}] ${message}`, ...args),
    warn: (message, ...args) => standardLogger.warn(`[${scope}] ${message}`, ...args),
    error: (message, ...args) => standardLogger.error(`[${scope}] ${message}`, ...args),
    operationStart: (operation) => standardLogger.operationStart(`${scope}: ${operation}`),
    operationComplete: (operation) => standardLogger.operationComplete(`${scope}: ${operation}`),
    operationFailed: (operation, error) => standardLogger.operationFailed(`${scope}: ${operation}`, error),
    
    // File operations
    fileProcessing: (filePath) => standardLogger.fileProcessing(filePath),
    fileWritten: (filePath) => standardLogger.fileWritten(filePath),
    
    // Component operations
    componentProcessing: (componentName) => standardLogger.componentProcessing(componentName),
    componentSkipped: (componentName, reason) => standardLogger.componentSkipped(componentName, reason),
    
    // Package operations
    packageLoading: (packageName) => standardLogger.packageLoading(packageName),
    packageLoaded: (packageName) => standardLogger.packageLoaded(packageName),
    packageSkipped: (packageName, reason) => standardLogger.packageSkipped(packageName, reason),
    
    // Configuration
    configLoading: (configPath) => standardLogger.configLoading(configPath),
    
    // Progress
    progress: (current, total, operation) => standardLogger.progress(current, total, operation),
    
    // Warnings
    deprecationWarning: (feature) => standardLogger.deprecationWarning(feature)
  };
}

```
Page 28/141FirstPrevNextLast