#
tokens: 47278/50000 6/1630 files (page 48/143)
lines: off (toggle) GitHub
raw markdown copy
This is page 48 of 143. Use http://codebase.md/xmlui-org/xmlui/tools/vscode/resources/assets/img/bg-iphone-14-pro.jpg?lines=false&page={x} to view the full context.

# Directory Structure

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

# Files

--------------------------------------------------------------------------------
/xmlui/tests/parsers/style-parser/tokens.test.ts:
--------------------------------------------------------------------------------

```typescript
import { describe, expect, it } from "vitest";
import { StyleTokenType } from "../../../src/parsers/style-parser/tokens";
import { StyleLexer } from "../../../src/parsers/style-parser/StyleLexer";
import { StyleInputStream } from "../../../src/parsers/style-parser/StyleInputStream";

describe("Parser - Binary operations", () => {
  const simpleTokens = [
    { src: " ", token: StyleTokenType.Ws },
    { src: "\t", token: StyleTokenType.Ws },
    { src: "\n", token: StyleTokenType.Ws },
    { src: "\r", token: StyleTokenType.Ws },
    { src: "*", token: StyleTokenType.Star },
    { src: ",", token: StyleTokenType.Comma },
    { src: "(", token: StyleTokenType.LParent },
    { src: ")", token: StyleTokenType.RParent },
    { src: "%", token: StyleTokenType.Percentage },
    { src: "/", token: StyleTokenType.Slash },
    { src: "none", token: StyleTokenType.None },
    { src: "reset", token: StyleTokenType.Reset },
  ];

  simpleTokens.forEach((s) =>
    it(`Token: ${s.src}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s.src));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s.src);
      expect(token.type).equal(s.token);
    })
  );

  const sizeUnitTokens = ["px", "cm", "mm", "in", "pt", "pc", "em", "rem", "vw", "vh", "ex", "ch", "vmin", "vmax"];

  sizeUnitTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.SizeUnit);
    })
  );

  const alignmentTokens = ["start", "center", "end"];

  alignmentTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.Alignment);
    })
  );

  const textAlignTokens = ["left", "right", "justify"];

  textAlignTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.TextAlignment);
    })
  );

  const orientationTokens = ["horizontal", "vertical"];

  orientationTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.Orientation);
    })
  );

  const borderStyleTokens = ["dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"];

  borderStyleTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.BorderStyle);
    })
  );

  const directionTokens = ["ltr", "rtl"];

  directionTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.Direction);
    })
  );

  const fontWeightTokens = ["lighter", "normal", "bold", "bolder", "100", "200"];

  fontWeightTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).to.be.oneOf([StyleTokenType.FontWeight, StyleTokenType.Number]);
    })
  );

  const zIndexTokens = ["-1", "0", "1", "99"];

  zIndexTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.Number);
    })
  );

  const scrollingTokens = ["visible", "hidden", "scroll"];

  scrollingTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.Scrolling);
    })
  );

  const fontFamilyTokens = ["$fontFamily", "serif", "sansSerif", "mono"];

  fontFamilyTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).to.be.oneOf([StyleTokenType.FontFamily, StyleTokenType.Identifier]);
    })
  );

  const angleTokens = ["deg", "rad", "grad", "turn"];

  angleTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.Angle);
    })
  );

  const numberTokens = [
    { src: "0", value: 0 },
    { src: "1", value: 1 },
    { src: "2", value: 2 },
    { src: "3", value: 3 },
    { src: "4", value: 4 },
    { src: "5", value: 5 },
    { src: "6", value: 6 },
    { src: "7", value: 7 },
    { src: "8", value: 8 },
    { src: "9", value: 9 },
    { src: "123", value: 123 },
    { src: ".25", value: 0.25 },
    { src: "1234.125", value: 1234.125 },
    { src: "-9", value: -9 },
    { src: "-123", value: -123 },
    { src: "-.25", value: -0.25 },
    { src: "-1234.125", value: -1234.125 },
  ];

  numberTokens.forEach((s) =>
    it(`Token: ${s.src}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s.src));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s.src);
      expect(token.type).equal(StyleTokenType.Number);
      expect(parseFloat(token.text)).equal(s.value);
    })
  );

  const hexaColorTokens = [
    { src: "#", token: StyleTokenType.Unknown },
    { src: "#1", token: StyleTokenType.Unknown },
    { src: "#f2", token: StyleTokenType.Unknown },
    { src: "#abc", token: StyleTokenType.HexaColor },
    { src: "#abcf", token: StyleTokenType.HexaColor },
    { src: "#1abcf", token: StyleTokenType.Unknown },
    { src: "#12abcf", token: StyleTokenType.HexaColor },
    { src: "#012abcf", token: StyleTokenType.Unknown },
    { src: "#4312abcf", token: StyleTokenType.HexaColor },
    { src: "#14312abcf", token: StyleTokenType.Unknown },
    { src: "#d14312abcf", token: StyleTokenType.Unknown },
  ];

  hexaColorTokens.forEach((s) =>
    it(`Token: ${s.src}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s.src));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s.src);
      expect(token.type).equal(s.token);
    })
  );

  it("Token: none", () => {
    // --- Arrange
    const lexer = new StyleLexer(new StyleInputStream("none"));

    // --- Act
    const token = lexer.get(true);

    // --- Assert
    expect(token.text).equal("none");
    expect(token.type).equal(StyleTokenType.None);
  });

  const colorFunctionTokens = ["rgb", "rgba", "hsl", "hsla"];

  colorFunctionTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.ColorFunc);
    })
  );

  const colorNameTokens = [
    "transparent",
    "black",
    "silver",
    "gray",
    "white",
    "maroon",
    "red",
    "purple",
    "fuchsia",
    "green",
    "lime",
    "olive",
    "yellow",
    "navy",
    "blue",
    "teal",
    "aqua",
    "orange",
    "aliceblue",
    "antiquewhite",
    "aquamarine",
    "azure",
    "beige",
    "bisque",
    "blanchedalmond",
    "blueviolet",
    "brown",
    "burlywood",
    "cadetblue",
    "chartreuse",
    "chocolate",
    "coral",
    "cornflowerblue",
    "cornsilk",
    "crimson",
    "cyan",
    "darkblue",
    "darkcyan",
    "darkgoldenrod",
    "darkgray",
    "darkgreen",
    "darkgrey",
    "darkkhaki",
    "darkmagenta",
    "darkolivegreen",
    "darkorange",
    "darkorchid",
    "darkred",
    "darksalmon",
    "darkseagreen",
    "darkslateblue",
    "darkslategray",
    "darkslategrey",
    "darkturquoise",
    "darkviolet",
    "deeppink",
    "deepskyblue",
    "dimgray",
    "dimgrey",
    "dodgerblue",
    "firebrick",
    "floralwhite",
    "forestgreen",
    "gainsboro",
    "ghostwhite",
    "gold",
    "goldenrod",
    "greenyellow",
    "grey",
    "honeydew",
    "hotpink",
    "indianred",
    "indigo",
    "ivory",
    "khaki",
    "lavender",
    "lavenderblush",
    "lawngreen",
    "lemonchiffon",
    "lightblue",
    "lightcoral",
    "lightcyan",
    "lightgoldenrodyellow",
    "lightgray",
    "lightgreen",
    "lightgrey",
    "lightpink",
    "lightsalmon",
    "lightseagreen",
    "lightskyblue",
    "lightslategray",
    "lightslategrey",
    "lightsteelblue",
    "lightyellow",
    "limegreen",
    "linen",
    "magenta",
    "mediumaquamarine",
    "mediumblue",
    "mediumorchid",
    "mediumpurple",
    "mediumseagreen",
    "mediumslateblue",
    "mediumspringgreen",
    "mediumturquoise",
    "mediumvioletred",
    "midnightblue",
    "mintcream",
    "mistyrose",
    "moccasin",
    "navajowhite",
    "oldlace",
    "olivedrab",
    "orangered",
    "orchid",
    "palegoldenrod",
    "palegreen",
    "paleturquoise",
    "palevioletred",
    "papayawhip",
    "peachpuff",
    "peru",
    "pink",
    "plum",
    "powderblue",
    "rosybrown",
    "royalblue",
    "saddlebrown",
    "salmon",
    "sandybrown",
    "seagreen",
    "seashell",
    "sienna",
    "skyblue",
    "slateblue",
    "slategray",
    "slategrey",
    "snow",
    "springgreen",
    "steelblue",
    "tan",
    "thistle",
    "tomato",
    "turquoise",
    "violet",
    "wheat",
    "whitesmoke",
    "yellowgreen",
    "rebeccapurple",
  ];

  colorNameTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.ColorName);
    })
  );

  const lineDecorationTokens = ["underline", "overline", "line-through"];

  lineDecorationTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.DecorationLine);
    })
  );

  const stringTokens = ["'start'", "'Courier New'", '"end"'];

  stringTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.String);
    })
  );

  const userSelectTokens = ["all", "text", "contain"];

  userSelectTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.UserSelect);
    })
  );

  const textTransformTokens = ["capitalize", "uppercase", "lowercase", "full-width", "full-size-kana"];

  textTransformTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
      expect(token.type).equal(StyleTokenType.TextTransform);
    })
  );

  const cursorTokens = [
    "auto",
    "default",
    "none",
    "context-menu",
    "help",
    "pointer",
    "progress",
    "wait",
    "cell",
    "crosshair",
    "text",
    "vertical-text",
    "alias",
    "copy",
    "move",
    "no-drop",
    "not-allowed",
    "grab",
    "grabbing",
    "all-scroll",
    "col-resize",
    "row-resize",
    "n-resize",
    "e-resize",
    "s-resize",
    "w-resize",
    "ne-resize",
    "nw-resize",
    "se-resize",
    "sw-resize",
    "ew-resize",
    "ns-resize",
    "nesw-resize",
    "nwse-resize",
    "zoom-in",
    "zoom-out",
  ];

  cursorTokens.forEach((s) =>
    it(`Token: ${s}`, () => {
      // --- Arrange
      const lexer = new StyleLexer(new StyleInputStream(s));

      // --- Act
      const token = lexer.get(true);

      // --- Assert
      expect(token.text).equal(s);
    })
  );
});

```

--------------------------------------------------------------------------------
/xmlui/src/components/Markdown/utils.ts:
--------------------------------------------------------------------------------

```typescript
import { encodeToBase64 } from "../../components-core/utils/base64-utils";

export type SegmentProps = {
  display?: boolean;
  copy?: boolean;
  noPopup?: boolean;
  noFrame?: boolean;
  noHeader?: boolean;
  splitView?: boolean;
  initiallyShowCode?: boolean;
  highlights?: (number | [number, number])[];
  filename?: string;
  name?: string;
  height?: string;
  popOutUrl?: string;
  content?: string;
  order?: number;
  patterns?: string[];
  borderedPatterns?: string[];
  withSplashScreen?: boolean;
  immediate?: boolean;
};

export type PlaygroundPattern = {
  default?: SegmentProps;
  app?: SegmentProps;
  components?: SegmentProps[];
  descriptions?: SegmentProps[];
  config?: SegmentProps;
  api?: SegmentProps;
};

export function observePlaygroundPattern(content: string): [number, number, string] | null {
  const startPattern = "```xmlui-pg";
  const endPattern = "```";

  const startIndex = content.indexOf(startPattern);
  if (startIndex === -1) {
    return null; // No match for the start pattern
  }

  // Find the end of the start pattern
  const startContentIndex = content.indexOf("\n", startIndex);
  if (startContentIndex === -1) {
    return null; // Malformed pattern, no newline after start
  }

  // Search for the end pattern after the start content
  let endIndex = startContentIndex;
  while (endIndex !== -1) {
    endIndex = content.indexOf(endPattern, endIndex + 1);
    if (endIndex !== -1) {
      // Check if the end pattern is not part of {pg-content} (escaped with backticks)
      const precedingChar = content[endIndex - 1];
      if (precedingChar !== "\\") {
        return [
          startIndex,
          endIndex + endPattern.length,
          content.substring(startIndex, endIndex + endPattern.length),
        ];
      }
    }
  }

  return null; // No valid end pattern found
}

export function parseSegmentProps(input: string): SegmentProps {
  const segment: SegmentProps = {};

  // --- Match the "display" flag
  if (/\bdisplay\b/.test(input)) {
    segment.display = true;
  }

  // --- Match the "copy" flag
  if (/\bcopy\b/.test(input)) {
    segment.copy = true;
  }

  // --- Match the "noPopup" flag
  if (/\bnoPopup\b/.test(input)) {
    segment.noPopup = true;
  }

  // --- Match the "noFrame" flag
  if (/\bnoFrame\b/.test(input)) {
    segment.noFrame = true;
  }

  // --- Match the "immediate" flag
  if (/\bimmediate\b/.test(input)) {
    segment.immediate = true;
  }

  // --- Match the "withSplashScreen" flag
  if (/\bwithSplashScreen\b/.test(input)) {
    segment.withSplashScreen = true;
  }
  
  // --- Match the "noHeader" flag
  if (/\bnoHeader\b/.test(input)) {
    segment.noHeader = true;
  }

  // --- Match the "splitView" flag
  if (/\bsplitView\b/.test(input)) {
    segment.splitView = true;
  }

  // --- Match the "initiallyShowCode" flag
  if (/\binitiallyShowCode\b/.test(input)) {
    segment.initiallyShowCode = true;
  }

  // Match the "highlights" pattern
  const highlightsMatch = input.match(/\{([^\}]+)\}/);
  if (highlightsMatch) {
    const highlights = highlightsMatch[1].split(",").map((range) => {
      if (range.includes("-")) {
        const [start, end] = range.split("-").map(Number);
        return [start, end]; // Represent ranges as [start, end]
      }
      return Number(range); // Represent single numbers as numbers
    });
    segment.highlights = highlights as (number | [number, number])[];
  }

  // Match the "filename" property
  const filenameMatch = input.match(/\bfilename="([^"]+)"/);
  if (filenameMatch) {
    segment.filename = filenameMatch[1];
  }

  // Match the "name" property
  const nameMatch = input.match(/\bname="([^"]+)"/);
  if (nameMatch) {
    segment.name = nameMatch[1];
  }

  // Match the "height" property
  const heightMatch = input.match(/\bheight="([^"]+)"/);
  if (heightMatch) {
    segment.height = heightMatch[1];
  }

  // Match the "popOutUrl" property
  const popOutUrlMatch = input.match(/\bpopOutUrl="([^"]+)"/);
  if (popOutUrlMatch) {
    segment.popOutUrl = popOutUrlMatch[1];
  }

  // Match patterns enclosed in /pattern/ format
  const patternMatches = input.match(/\/([^\/]+)\//g);
  if (patternMatches) {
    segment.patterns = patternMatches.map((pattern) =>
      // Remove the surrounding slashes
      pattern.substring(1, pattern.length - 1),
    );
  }

  // Match bordered patterns enclosed in !/pattern/ format
  const borderedPatternMatches = input.match(/!\/(.[^\/]+)\//g);
  if (borderedPatternMatches) {
    segment.borderedPatterns = borderedPatternMatches.map((pattern) =>
      // Remove the leading !/ and trailing /
      pattern.substring(2, pattern.length - 1),
    );
  }

  return segment;
}

export function parsePlaygroundPattern(content: string): PlaygroundPattern {
  const pattern: PlaygroundPattern = {};
  const match = observePlaygroundPattern(content);

  if (!match) {
    return pattern;
  }

  // --- Extract the pattern content
  const [_startIndex, _endIndex, patternContent] = match;
  const lines = patternContent.split("\n");
  pattern.default = parseSegmentProps(lines[0].trim());

  let segmentContent = "";
  let currentMode = "";
  let foundSegment = false;
  let order = 0;

  for (let i = 1; i < lines.length - 1; i++) {
    const line = lines[i];
    if (line.startsWith("---app")) {
      const appSegment = parseSegmentProps(line);
      pattern.app = { ...appSegment };
      closeCurrentMode("app");
    } else if (line.startsWith("---comp")) {
      closeCurrentMode("comp");
      const compSegment = parseSegmentProps(line);
      pattern.components ??= [];
      pattern.components.push(compSegment);
    } else if (line.startsWith("---config")) {
      const configSegment = parseSegmentProps(line);
      pattern.config ??= { ...configSegment };
      closeCurrentMode("config");
    } else if (line.startsWith("---api")) {
      const apiSegment = parseSegmentProps(line);
      pattern.api ??= { ...apiSegment };
      closeCurrentMode("api");
    } else if (line.startsWith("---desc")) {
      closeCurrentMode("desc");
      const descSegment = parseSegmentProps(line);
      pattern.descriptions ??= [];
      pattern.descriptions.push(descSegment);
    } else {
      // Append the line to the current segment content
      segmentContent += line + "\n";
    }
  }

  // --- Handle the last segment
  if (foundSegment) {
    closeCurrentMode("");
  } else {
    pattern.app = {
      ...pattern.default,
      content: segmentContent,
      order,
    };
  }

  return pattern;

  function closeCurrentMode(newMode: string) {
    foundSegment = true;
    switch (currentMode) {
      case "app":
        pattern.app.content = segmentContent;
        pattern.app.order = order++;
        break;
      case "comp":
        pattern.components[pattern.components.length - 1].content = segmentContent;
        pattern.components[pattern.components.length - 1].order = order++;
        break;
      case "config":
        pattern.config.content = segmentContent;
        pattern.config.order = order++;
        break;
      case "api":
        pattern.api.content = segmentContent;
        pattern.api.order = order++;
        break;
      case "desc":
        pattern.descriptions[pattern.descriptions.length - 1].content = segmentContent;
        pattern.descriptions[pattern.descriptions.length - 1].order = order++;
        break;
    }
    segmentContent = "";
    currentMode = newMode;
  }
}

export function convertPlaygroundPatternToMarkdown(content: string): string {
  const pattern = parsePlaygroundPattern(content);

  // --- Determine max order for segments
  let maxOrder = 0;
  if (pattern.app?.order > maxOrder) {
    maxOrder = pattern.app.order;
  }
  if (pattern.config?.order > maxOrder) {
    maxOrder = pattern.config.order;
  }
  if (pattern.api?.order > maxOrder) {
    maxOrder = pattern.api.order;
  }
  if (pattern.descriptions) {
    pattern.descriptions.forEach((desc) => {
      if (desc.order > maxOrder) {
        maxOrder = desc.order;
      }
    });
  }
  if (pattern.components) {
    pattern.components.forEach((comp) => {
      if (comp.order > maxOrder) {
        maxOrder = comp.order;
      }
    });
  }

  // --- Assemble the final markdown content
  let markdownContent = "";
  const pgContent: any = {
    noPopup: pattern.default?.noPopup,
    noFrame: pattern.default?.noFrame,
    noHeader: pattern.default?.noHeader,
    splitView: pattern.default?.splitView,
    initiallyShowCode: pattern.default?.initiallyShowCode,
    popOutUrl: pattern.default?.popOutUrl,
    immediate: pattern.default?.immediate,
    withSplashScreen: pattern.default?.withSplashScreen,
  };

  // --- Extract optional playground attributes
  if (pattern.default.height) {
    pgContent.height = pattern.default.height;
  }
  if (pattern.default.name) {
    pgContent.name = pattern.default.name;
  }
  if (pattern.default.popOutUrl) {
    pgContent.popOutUrl = pattern.default.popOutUrl;
  }

  // --- Iterate through segments
  for (let i = 0; i <= maxOrder; i++) {
    let segment: SegmentProps | undefined;
    let type = "";
    if (pattern.app?.order === i) {
      segment = pattern.app;
      type = "app";
    } else if (pattern.config?.order === i) {
      segment = pattern.config;
      type = "config";
    } else if (pattern.api?.order === i) {
      segment = pattern.api;
      type = "api";
    }
    if (!segment && pattern.descriptions) {
      const descSegment = pattern.descriptions.find((desc) => desc.order === i);
      if (descSegment) {
        segment = descSegment;
        type = "desc";
      }
    }
    if (!segment && pattern.components) {
      const compSegment = pattern.components.find((comp) => comp.order === i);
      if (compSegment) {
        segment = compSegment;
        type = "comp";
      }
    }
    if (segment === undefined) {
      continue; // Skip if no segment found
    }

    // --- Assemble the app
    // --- Assemble segment attributes
    let segmentAttrs =
      `${segment.copy ? "copy" : ""} ` +
      `${segment.filename ? `filename="${segment.filename}"` : ""} ` +
      `${segment.name ? `name="${segment.name}"` : ""} ` +
      `${segment.popOutUrl ? `popOutUrl="${segment.popOutUrl}"` : ""}`;
    if (segment.highlights && segment.highlights.length > 0) {
      const highlights = segment.highlights
        .map((highlight) =>
          Array.isArray(highlight) ? `${highlight[0]}-${highlight[1]}` : highlight,
        )
        .join(",");
      segmentAttrs += `{${highlights}}`;
    }
    if (segment.patterns && segment.patterns.length > 0) {
      segmentAttrs += " " + segment.patterns.map((p) => `/${p}/`).join(" ");
    }
    if (segment.borderedPatterns && segment.borderedPatterns.length > 0) {
      segmentAttrs += " " + segment.borderedPatterns.map((p) => `!/` + p + `/`).join(" ");
    }
    segmentAttrs = segmentAttrs.trim().replace(/\s+/g, " ");

    switch (type) {
      case "app":
        if (segment.display) {
          markdownContent += "```xmlui " + segmentAttrs + "\n" + segment.content + "```\n\n";
        }
        pgContent.app = segment.content;
        break;
      case "config":
        if (segment.display) {
          markdownContent += "```json " + segmentAttrs + "\n" + segment.content + "```\n\n";
        }
        pgContent.config = segment.content;
        break;
      case "api":
        // --- Never display API segments
        pgContent.api = segment.content;
        break;
      case "comp":
        if (segment.display) {
          markdownContent += "```xmlui " + segmentAttrs + "\n" + segment.content + "```\n\n";
        }
        pgContent.components ??= [];
        pgContent.components.push(segment.content);
        break;
      case "desc":
        markdownContent += segment.content + "\n";
        break;
    }
  }

  // --- Convert the JSON representation of pgContent to a base64 string
  const jsonString = JSON.stringify(pgContent);
  const base64ContentString = encodeToBase64(jsonString);
  const base64MarkdownString = encodeToBase64(markdownContent);
  return (
    '<samp data-pg-content="' +
    base64ContentString +
    '" data-pg-markdown="' +
    base64MarkdownString +
    '"></samp>\n\n'
  );
}

export function observeTreeDisplay(content: string): [number, number, string] | null {
  const startPattern = "```xmlui-tree";
  const endPattern = "```";

  const startIndex = content.indexOf(startPattern);
  if (startIndex === -1) {
    return null; // No match for the start pattern
  }

  // Find the end of the start pattern
  const startContentIndex = content.indexOf("\n", startIndex);
  if (startContentIndex === -1) {
    return null; // Malformed pattern, no newline after start
  }

  // Search for the end pattern after the start content
  let endIndex = startContentIndex;
  while (endIndex !== -1) {
    endIndex = content.indexOf(endPattern, endIndex + 1);
    if (endIndex !== -1) {
      // Check if the end pattern is not escaped
      const precedingChar = content[endIndex - 1];
      if (precedingChar !== "\\") {
        return [
          startIndex,
          endIndex + endPattern.length,
          content.substring(startIndex, endIndex + endPattern.length),
        ];
      }
    }
  }

  return null; // No valid end pattern found
}

export function convertTreeDisplayToMarkdown(content: string): string {
  if (content.startsWith("```xmlui-tree") && content.endsWith("```")) {
    const treeContent = content
      .slice("```xmlui-tree".length, content.indexOf("```", "```xmlui-tree".length))
      .trim();
    return `<section data-tree-content="${encodeToBase64(treeContent)}"></section>\n\n`;
  }
}

```

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

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

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

test.describe("Basic Functionality", () => {
  test("renders with basic props", async ({ initTestBed, page }) => {
    await initTestBed(`<App name="Test App" testId="app"/>`);
    await expect(page.getByTestId("app")).toBeVisible();
  });

  test("renders with horizontal layout", async ({ initTestBed, page }) => {
    await initTestBed(`<App layout="horizontal">test text</App>`);
    await expect(page.getByText("test text")).toBeVisible();
  });

  test("renders with horizontal-sticky layout", async ({ initTestBed, page }) => {
    await initTestBed(`<App layout="horizontal-sticky">test text</App>`);
    await expect(page.getByText("test text")).toBeVisible();
  });

  test("renders with condensed layout", async ({ initTestBed, page }) => {
    await initTestBed(`<App layout="condensed">test text</App>`);
    await expect(page.getByText("test text")).toBeVisible();
  });

  test("renders with condensed-sticky layout", async ({ initTestBed, page }) => {
    await initTestBed(`<App layout="condensed-sticky">test text</App>`);
    await expect(page.getByText("test text")).toBeVisible();
  });

  test("renders with vertical layout", async ({ initTestBed, page }) => {
    await initTestBed(`<App layout="vertical">test text</App>`);
    await expect(page.getByText("test text")).toBeVisible();
  });

  test("renders with vertical-sticky layout", async ({ initTestBed, page }) => {
    await initTestBed(`<App layout="vertical-sticky">test text</App>`);
    await expect(page.getByText("test text")).toBeVisible();
  });

  test("renders with vertical-full-header layout", async ({ initTestBed, page }) => {
    await initTestBed(`<App layout="vertical-full-header">test text</App>`);
    await expect(page.getByText("test text")).toBeVisible();
  });
  test("handles layout prop changes correctly", async ({
    page,
    initTestBed,
    createButtonDriver,
  }) => {
    await initTestBed(`
      <App var.lo="vertical" layout="{lo}" testId="app">
        <Button testId="toggleLayout" label="Toggle" onClick="lo = 'horizontal'" />
      </App>
    `);

    const buttonDriver = await createButtonDriver("toggleLayout");
    await expect(page.getByTestId("app")).toHaveClass(/vertical/);
    await buttonDriver.click();
    await expect(page.getByTestId("app")).toHaveClass(/horizontal/);
  });

  test("sets document title from name prop", async ({ initTestBed, page }) => {
    const APP_NAME = "My Test Application";
    await initTestBed(`<App name="${APP_NAME}" testId="app"/>`);

    await expect(page.getByTestId("app")).toBeVisible();
    expect(await page.title()).toBe(APP_NAME);
  });

  test("handles different visual states with scrolling options", async ({ initTestBed, page }) => {
    // Test with scrollWholePage=true
    await initTestBed(`<App scrollWholePage="true" testId="app"/>`);

    await expect(page.getByTestId("app")).toHaveClass(/scrollWholePage/);

    // Test with scrollWholePage=false
    await initTestBed(`<App scrollWholePage="false" testId="app"/>`);

    await expect(page.getByTestId("app")).not.toHaveClass(/scrollWholePage/);
  });
});

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

test.describe("Edge Cases", () => {
  test("handles undefined props gracefully", async ({ initTestBed, page }) => {
    await initTestBed(`<App testId="app" />`);

    await expect(page.getByTestId("app")).toBeVisible();

    // App should use a default layout
    await expect(page.getByTestId("app")).toHaveClass(/horizontal/);
  });

  test("works correctly with basic content structure", async ({ initTestBed, page }) => {
    await initTestBed(`
      <App testId="app">
        <Text testId="content">Content</Text>
      </App>`);

    await expect(page.getByTestId("app")).toBeVisible();
    await expect(page.getByTestId("content")).toBeVisible();
    await expect(page.getByText("Content")).toBeVisible();
  });

  test("works correctly with complex content structure", async ({ initTestBed, page }) => {
    await initTestBed(`
      <App testId="app">
        <AppHeader testId="header">Header Content</AppHeader>
        <NavPanel testId="nav">
          <NavLink testId="link1" to="#">Link 1</NavLink>
          <NavGroup testId="group" label="Group">
            <NavLink testId="nestedLink" to="#">Nested Link</NavLink>
          </NavGroup>
        </NavPanel>
        <Pages fallbackPath="/">
          <Page url="/" testId="homePage">
            <Text testId="homeContent">Home Content</Text>
          </Page>
        </Pages>
        <Footer testId="footer">Footer Content</Footer>
      </App>`);

    await expect(page.getByTestId("app")).toBeVisible();

    // Test component structure
    await expect(page.getByTestId("header")).toBeVisible();
    await expect(page.getByTestId("nav")).toBeVisible();
    await expect(page.getByTestId("footer")).toBeVisible();

    // Test content
    await expect(page.getByText("Header Content")).toBeVisible();
    await expect(page.getByText("Link 1")).toBeVisible();
    await expect(page.getByText("Group")).toBeVisible();
    await expect(page.getByText("Home Content")).toBeVisible();
    await expect(page.getByText("Footer Content")).toBeVisible();
  });
});

// =============================================================================
// EVENT HANDLING TESTS
// =============================================================================

test.describe("Event Handling", () => {
  test("ready event is triggered when App component finishes rendering", async ({
    initTestBed,
  }) => {
    const { testStateDriver } = await initTestBed(`
      <App
        onReady="() => testState = 'app-ready'"
        testId="app"
      />
    `);

    // Verify the ready event was fired
    await expect.poll(testStateDriver.testState).toEqual("app-ready");
  });

  test("ready event is triggered for App with complex content", async ({ initTestBed }) => {
    const { testStateDriver } = await initTestBed(`
      <App
        onReady="() => testState = 'complex-app-ready'"
        layout="horizontal"
        testId="app"
      >
        <AppHeader>
          <property name="logoTemplate">
            <Text value="Test App" />
          </property>
        </AppHeader>
        <Pages fallbackPath="/">
          <Page url="/">
            <Text value="Home Page" />
          </Page>
        </Pages>
        <Footer>
          <Text value="Footer Content" />
        </Footer>
      </App>
    `);

    // Verify the ready event was fired even with complex content
    await expect.poll(testStateDriver.testState).toEqual("complex-app-ready");
  });

  test("ready event fires only once during component lifecycle", async ({ initTestBed, page }) => {
    const { testStateDriver } = await initTestBed(`
      <App
        var.counter="{0}"
        onReady="() => { counter = counter + 1; testState = counter; }"
        testId="app"
      >
        <Button
          testId="trigger-rerender"
          label="Re-render"
          onClick="counter = counter"
        />
      </App>
    `);

    // Initial ready event should fire
    await expect.poll(testStateDriver.testState).toEqual(1);

    // Trigger a re-render by clicking the button
    await page.getByTestId("trigger-rerender").click();

    // Counter should still be 1 (ready event doesn't fire again)
    await expect.poll(testStateDriver.testState).toEqual(1);
  });

  test("messageReceived event is triggered when window receives a message", async ({
    initTestBed,
    page,
  }) => {
    const { testStateDriver } = await initTestBed(`
      <App
        onMessageReceived="(msg, ev) => testState = msg"
        testId="app"
      />
    `);

    // Send a message to the window
    await page.evaluate(() => {
      window.postMessage("test-message", "*");
    });

    // Verify the event was received and handled
    await expect.poll(testStateDriver.testState).toEqual("test-message");
  });

  test("messageReceived event receives both message data and event object", async ({
    initTestBed,
    page,
  }) => {
    const { testStateDriver } = await initTestBed(`
      <App
        onMessageReceived="(msg, ev) => testState = { message: msg, eventType: ev.type, origin: ev.origin }"
        testId="app"
      />
    `);

    // Send a message to the window
    await page.evaluate(() => {
      window.postMessage("event-test", "*");
    });

    // Verify both parameters are accessible
    await expect.poll(testStateDriver.testState).toMatchObject({
      message: "event-test",
      eventType: "message",
      origin: expect.any(String),
    });
  });

  test("messageReceived event handles complex data objects", async ({ initTestBed, page }) => {
    const { testStateDriver } = await initTestBed(`
      <App
        onMessageReceived="(msg, ev) => testState = msg"
        testId="app"
      />
    `);

    // Send a complex object as message data
    const testData = { action: "test", payload: { id: 123, name: "test-item" } };
    await page.evaluate((data) => {
      window.postMessage(data, "*");
    }, testData);

    // Verify the complex data is received correctly
    await expect.poll(testStateDriver.testState).toEqual(testData);
  });
});

// =============================================================================
// Drawer HANDLING TESTS
// =============================================================================

test.describe("Drawer Handling", () => {
  test("Drawer displayed if NavPanel has no 'when'", async ({
    initTestBed,
    page,
  }) => {
    // Set small viewport to trigger drawer mode
    await page.setViewportSize({ width: 400, height: 600 });

    await initTestBed(`
      <App layout="condensed">
        <AppHeader testId="appHeader"/>
        <NavPanel>
          <NavGroup label="Pages">
            <NavLink label="Page 1" to="/page1"/>
            <NavLink label="Page 2" to="/page2"/>
          </NavGroup>
        </NavPanel>
      </App>
    `);

    // Open drawer by clicking hamburger button
    const appHeader = page.getByTestId("appHeader");
    const hamburgerButton = appHeader.locator('[data-part-id="hamburger"]').first();
    await expect (hamburgerButton).toBeVisible();
  });

  test("Drawer displayed if NavPanel has when='true'", async ({
    initTestBed,
    page,
  }) => {
    // Set small viewport to trigger drawer mode
    await page.setViewportSize({ width: 400, height: 600 });

    await initTestBed(`
      <App layout="condensed">
        <AppHeader testId="appHeader"/>
        <NavPanel when="true">
          <NavGroup label="Pages">
            <NavLink label="Page 1" to="/page1"/>
            <NavLink label="Page 2" to="/page2"/>
          </NavGroup>
        </NavPanel>
      </App>
    `);

    // Open drawer by clicking hamburger button
    const appHeader = page.getByTestId("appHeader");
    const hamburgerButton = appHeader.locator('[data-part-id="hamburger"]').first();
    await expect (hamburgerButton).toBeVisible();
  });

  test("Drawer displayed if NavPanel has when='{true}'", async ({
    initTestBed,
    page,
  }) => {
    // Set small viewport to trigger drawer mode
    await page.setViewportSize({ width: 400, height: 600 });

    await initTestBed(`
      <App layout="condensed">
        <AppHeader testId="appHeader"/>
        <NavPanel when="{true}">
          <NavGroup label="Pages">
            <NavLink label="Page 1" to="/page1"/>
            <NavLink label="Page 2" to="/page2"/>
          </NavGroup>
        </NavPanel>
      </App>
    `);

    // Open drawer by clicking hamburger button
    const appHeader = page.getByTestId("appHeader");
    const hamburgerButton = appHeader.locator('[data-part-id="hamburger"]').first();
    await expect (hamburgerButton).toBeVisible();
  });

  test("Drawer not displayed if NavPanel has when='false'", async ({
    initTestBed,
    page,
  }) => {
    // Set small viewport to trigger drawer mode
    await page.setViewportSize({ width: 400, height: 600 });

    await initTestBed(`
      <App layout="condensed">
        <AppHeader testId="appHeader"/>
        <NavPanel when="false">
          <NavGroup label="Pages">
            <NavLink label="Page 1" to="/page1"/>
            <NavLink label="Page 2" to="/page2"/>
          </NavGroup>
        </NavPanel>
      </App>
    `);

    // Open drawer by clicking hamburger button
    const appHeader = page.getByTestId("appHeader");
    const hamburgerButton = appHeader.locator('[data-part-id="hamburger"]').first();
    await expect (hamburgerButton).not.toBeVisible();
  });

  test("Drawer not displayed if NavPanel has when='{false}'", async ({
    initTestBed,
    page,
  }) => {
    // Set small viewport to trigger drawer mode
    await page.setViewportSize({ width: 400, height: 600 });

    await initTestBed(`
      <App layout="condensed">
        <AppHeader testId="appHeader"/>
        <NavPanel when="{false}">
          <NavGroup label="Pages">
            <NavLink label="Page 1" to="/page1"/>
            <NavLink label="Page 2" to="/page2"/>
          </NavGroup>
        </NavPanel>
      </App>
    `);

    // Open drawer by clicking hamburger button
    const appHeader = page.getByTestId("appHeader");
    const hamburgerButton = appHeader.locator('[data-part-id="hamburger"]').first();
    await expect (hamburgerButton).not.toBeVisible();
  });
});

```

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

```markdown
# NavLink [#navlink]

`NavLink` creates interactive navigation items that connect users to different destinations within an app or external URLs. It automatically indicates active states, supports custom icons and labels, and can execute custom actions instead of navigation when needed.

**Key features:**
- **Custom actions**: Execute JavaScript code instead of navigation when using onClick handlers
- **Visual customization**: Support for icons, labels, and completely custom nested content
- **Accessibility support**: Proper focus management and keyboard navigation

## Using NavLink [#using-navlink]

### `NavLink` Appearance [#navlink-appearance]

You can use the `label` and `icon` properties of a `NavLink` to set its text and icon to display.
If you want a custom appearance, you can nest define custom visuals for the `NavLink` by nesting:

```xmlui-pg copy {6-14} display name="Example: NavLink appearance" height="250px"
<App layout="horizontal">
  <AppHeader>
    <H1>MyApp</H1>
  </AppHeader>
  <NavPanel>
    <NavLink to="/">
       <Stack width="16px" height="16px" backgroundColor="purple" />
       Home
    </NavLink>
    <NavLink to="/about">
       <Stack width="16px" height="16px" backgroundColor="green" />
       About
    </NavLink>
  </NavPanel>
  <Pages>
    <Page url="/">Home</Page>
    <Page url="/about">About</Page>
  </Pages>
</App>
```

### Actions [#actions]

By default, activating (clicking) a link navigates to the target URL.
However, you can create a link that executes an explicit action responding to the `click` event instead of the default navigation:

```xmlui-pg copy {7} display name="Example: custom NavLink action" height="250px"
<App layout="horizontal">
  <AppHeader>
    <H1>MyApp</H1>
  </AppHeader>
  <NavPanel>
    <NavLink to="/" label="Home" />
    <NavLink label="Danger!" onClick="toast('Be careful with this action!')" />
  </NavPanel>
  <Pages>
    <Page url="/">Home</Page>
  </Pages>
</App>
```

## Properties [#properties]

### `active` (default: false) [#active-default-false]

This property indicates if the particular navigation is an active link. An active link has a particular visual appearance, provided its [`displayActive`](#displayactive) property is set to `true`.

### `displayActive` (default: true) [#displayactive-default-true]

This Boolean property indicates if the active state of a link should have a visual indication. Setting it to `false` removes the visual indication of an active link.

```xmlui-pg copy display name="Example: displayActive" height="250px"
<App layout="horizontal">
  <NavPanel>
    <NavLink to="/" label="Home" displayActive="false" />
  </NavPanel>
  <Pages>
    <Page url="/">Home</Page>
  </Pages>
</App>
```

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

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

In the following app, the "Hotels" link is disabled:

```xmlui-pg copy {8} display name="Example: enabled" height="250px"
<App layout="horizontal">
  <AppHeader>
    <H1>MyTravel App</H1>
  </AppHeader>
  <NavPanel>
    <NavLink label="Home" to="/" />
    <NavLink label="Flights" to="/flights" />
    <NavLink label="Hotels" to="/hotels" enabled="false" />
  </NavPanel>
  <Pages>
    <Page url="/">Home</Page>
    <Page url="/flights">Flights Page</Page>
    <Page url="/hotels">Hotels Page</Page>
  </Pages>
</App>
```

### `icon` [#icon]

This property allows you to add an optional icon (specify the icon's name) to the navigation link.

```xmlui-pg copy {6-7} display name="Example: icon" height="250px"
<App layout="horizontal">
  <AppHeader>
    <H1>MyApp</H1>
  </AppHeader>
  <NavPanel>
    <NavLink label="Home" to="/" icon="home" />
    <NavLink label="Drives" to="/drives" icon="drive" />
  </NavPanel>
  <Pages>
    <Page url="/">Home</Page>
    <Page url="/drives">Drives Page</Page>
  </Pages>
</App>
```

### `label` [#label]

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

```xmlui-pg copy display name="Example: label" height="250px"
<App layout="horizontal">
  <NavPanel>
    <NavLink to="/" label="Home" />
  </NavPanel>
  <Pages>
    <Page url="/">Home</Page>
  </Pages>
</App>
```

### `target` [#target]

This optionally property specifies how to open the clicked link.

Available values:

| Value | Description |
| --- | --- |
| `_self` | The link will open in the same frame as it was clicked. |
| `_blank` | The link will open in a new window or tab. |
| `_parent` | The link will open in the parent frame. If no parent, behaves as _self. |
| `_top` | The topmost browsing context. The link will open in the full body of the window. If no ancestors, behaves as _self. |
| `_unfencedTop` | Allows embedded fenced frames to navigate the top-level frame, i.e. traversing beyond the root of the fenced frame. |

The following example opens the "About XMLUI" link in a new tab:

```xmlui-pg copy {7} display name="Example: target" height="250px"
<App layout="horizontal">
  <AppHeader>
    <H1>MyApp</H1>
  </AppHeader>
  <NavPanel>
    <NavLink label="Home" to="/" />
    <NavLink label="About XMLUI" to="https://docs.xmlui.org/" target="_blank" />
  </NavPanel>
  <Pages>
    <Page url="/">Home</Page>
    <Page url="/drives">Drives Page</Page>
  </Pages>
</App>
```

### `to` [#to]

This property defines the URL of the link.

### `vertical` [#vertical]

This property sets how the active status is displayed on the `NavLink` component. If set to true, the indicator is displayed on the side which lends itself to a vertically aligned navigation menu. By default, it displays a horizontal indicator.

Usually, you do not need to use this property.
However, if you create a custom navigation menu component that runs vertically,
you need to manually set this property for the active state to be displayed properly.

The default value for this property is `false`.

```xmlui-pg copy display name="Example: vertical" height="250px"
<App layout="horizontal">
  <NavPanel>
    <NavLink to="/" label="Home" vertical="true" />
  </NavPanel>
  <Pages>
    <Page url="/">Home</Page>
  </Pages>
</App>
```

## Events [#events]

### `click` [#click]

This event is triggered when the NavLink is clicked.

The following example shows a message and navigates to the "/status" link after closing the message window:

```xmlui-pg copy {7} display name="Example: click" height="250px"
<App layout="horizontal">
  <AppHeader>
    <H1>MyApp</H1>
  </AppHeader>
  <NavPanel>
    <NavLink to="/" label="Home" />
    <NavLink label="Check my status" onClick="
        toast('You will be redirected');
        Actions.navigate('/status');
    " />
  </NavPanel>
  <Pages>
    <Page url="/">Home</Page>
    <Page url="/status">My Status</Page>
  </Pages>
</App>
```

## 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)-NavLink | transparent | transparent |
| [backgroundColor](../styles-and-themes/common-units/#color)-NavLink--active | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-NavLink--hover | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-NavLink--hover--active | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-NavLink--pressed | *none* | *none* |
| [backgroundColor](../styles-and-themes/common-units/#color)-NavLink--pressed--active | *none* | *none* |
| [border](../styles-and-themes/common-units/#border)-NavLink | 0px solid $borderColor | 0px solid $borderColor |
| [borderBottom](../styles-and-themes/common-units/#border)-NavLink | *none* | *none* |
| [borderBottomColor](../styles-and-themes/common-units/#color)-NavLink | *none* | *none* |
| [borderBottomStyle](../styles-and-themes/common-units/#border-style)-NavLink | *none* | *none* |
| [borderBottomWidth](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-NavLink | *none* | *none* |
| [borderEndEndRadius](../styles-and-themes/common-units/#border-rounding)-NavLink | *none* | *none* |
| [borderEndStartRadius](../styles-and-themes/common-units/#border-rounding)-NavLink | *none* | *none* |
| [borderHorizontal](../styles-and-themes/common-units/#border)-NavLink | *none* | *none* |
| [borderHorizontalColor](../styles-and-themes/common-units/#color)-NavLink | *none* | *none* |
| [borderHorizontalStyle](../styles-and-themes/common-units/#border-style)-NavLink | *none* | *none* |
| [borderHorizontalWidth](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [borderLeft](../styles-and-themes/common-units/#border)-NavLink | *none* | *none* |
| [color](../styles-and-themes/common-units/#color)-NavLink | *none* | *none* |
| [borderLeftStyle](../styles-and-themes/common-units/#border-style)-NavLink | *none* | *none* |
| [borderLeftWidth](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-indicator-NavLink | $borderRadius | $borderRadius |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-NavLink | $borderRadius | $borderRadius |
| [borderRight](../styles-and-themes/common-units/#border)-NavLink | *none* | *none* |
| [color](../styles-and-themes/common-units/#color)-NavLink | *none* | *none* |
| [borderRightStyle](../styles-and-themes/common-units/#border-style)-NavLink | *none* | *none* |
| [borderRightWidth](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [borderStartEndRadius](../styles-and-themes/common-units/#border-rounding)-NavLink | *none* | *none* |
| [borderStartStartRadius](../styles-and-themes/common-units/#border-rounding)-NavLink | *none* | *none* |
| [borderStyle](../styles-and-themes/common-units/#border-style)-NavLink | *none* | *none* |
| [borderTop](../styles-and-themes/common-units/#border)-NavLink | *none* | *none* |
| [borderTopColor](../styles-and-themes/common-units/#color)-NavLink | *none* | *none* |
| [borderTopStyle](../styles-and-themes/common-units/#border-style)-NavLink | *none* | *none* |
| [borderTopWidth](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [borderHorizontal](../styles-and-themes/common-units/#border)-NavLink | *none* | *none* |
| [borderVerticalColor](../styles-and-themes/common-units/#color)-NavLink | *none* | *none* |
| [borderVerticalStyle](../styles-and-themes/common-units/#border-style)-NavLink | *none* | *none* |
| [borderVerticalWidth](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [borderWidth](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [color](../styles-and-themes/common-units/#color)-icon-NavLink | $color-surface-500 | $color-surface-500 |
| [color](../styles-and-themes/common-units/#color)-indicator-NavLink | *none* | *none* |
| [color](../styles-and-themes/common-units/#color)-indicator-NavLink--active | $color-primary-500 | $color-primary-500 |
| [color](../styles-and-themes/common-units/#color)-indicator-NavLink--hover | $color-primary-600 | $color-primary-600 |
| [color](../styles-and-themes/common-units/#color)-indicator-NavLink--pressed | $color-primary-500 | $color-primary-500 |
| [fontFamily](../styles-and-themes/common-units/#fontFamily)-NavLink | $fontFamily | $fontFamily |
| [fontSize](../styles-and-themes/common-units/#size)-NavLink | $fontSize-sm | $fontSize-sm |
| [fontWeight](../styles-and-themes/common-units/#fontWeight)-NavLink | $fontWeight-normal | $fontWeight-normal |
| [fontWeight](../styles-and-themes/common-units/#fontWeight)-NavLink--active | *none* | *none* |
| [fontWeight](../styles-and-themes/common-units/#fontWeight)-NavLink--pressed | $fontWeight-normal | $fontWeight-normal |
| [outlineColor](../styles-and-themes/common-units/#color)-NavLink--focus | $outlineColor--focus | $outlineColor--focus |
| [outlineOffset](../styles-and-themes/common-units/#size)-NavLink--focus | -1px | -1px |
| [outlineStyle](../styles-and-themes/common-units/#border)-NavLink--focus | $outlineStyle--focus | $outlineStyle--focus |
| [outlineWidth](../styles-and-themes/common-units/#size)-NavLink--focus | $outlineWidth--focus | $outlineWidth--focus |
| [padding](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [paddingBottom](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [paddingHorizontal](../styles-and-themes/common-units/#size)-NavLink | $space-4 | $space-4 |
| [paddingLeft](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [paddingRight](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [paddingTop](../styles-and-themes/common-units/#size)-NavLink | *none* | *none* |
| [paddingVertical](../styles-and-themes/common-units/#size)-NavLink | $space-2 | $space-2 |
| [textColor](../styles-and-themes/common-units/#color)-NavLink | $textColor-primary | $textColor-primary |
| [textColor](../styles-and-themes/common-units/#color)-NavLink--active | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-NavLink--hover | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-NavLink--hover--active | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-NavLink--pressed | *none* | *none* |
| [textColor](../styles-and-themes/common-units/#color)-NavLink--pressed--active | *none* | *none* |
| [thickness](../styles-and-themes/common-units/#size)-indicator-NavLink | $space-0_5 | $space-0_5 |
| [wordWrap](../styles-and-themes/common-units/#word-wrap)-NavLink | *none* | *none* |

### Variable Explanations [#variable-explanations]

| Theme Variable | Description |
| --- | --- |
| **`color-indicator-NavLink`** | Provides the following states: `--hover`, `--active`, `--pressed` |

```

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

```typescript
import { SKIP_REASON } from "../../testing/component-test-helpers";
import { expect, test } from "../../testing/fixtures";

test.describe("Basic Functionality", () => {
  test("component renders with default props", async ({ page, initTestBed }) => {
    await initTestBed(`<Timer testId="timer" />`);

    const timer = page.getByTestId("timer");
    await expect(timer).toHaveAttribute("data-timer-enabled", "true");
    await expect(timer).toHaveAttribute("data-timer-interval", "1000");
  });

  test("component renders with enabled=false", async ({ page, initTestBed }) => {
    await initTestBed(`<Timer testId="timer" enabled="false" />`);

    const timer = page.getByTestId("timer");
    await expect(timer).toHaveAttribute("data-timer-enabled", "false");
    await expect(timer).toHaveAttribute("data-timer-running", "false");
  });

  test("component renders with custom interval", async ({ page, initTestBed }) => {
    await initTestBed(`<Timer testId="timer" interval="500" />`);

    const timer = page.getByTestId("timer");
    await expect(timer).toHaveAttribute("data-timer-interval", "500");
  });

  test("component renders with once=true", async ({ page, initTestBed }) => {
    await initTestBed(`<Timer testId="timer" once="true" />`);

    const timer = page.getByTestId("timer");
    await expect(timer).toHaveAttribute("data-timer-once", "true");
  });

  test("component renders with initial delay", async ({ page, initTestBed }) => {
    await initTestBed(`<Timer testId="timer" initialDelay="500" />`);

    const timer = page.getByTestId("timer");
    await expect(timer).toHaveAttribute("data-timer-initial-delay", "500");
  });

  test("component is not visible (non-visual component)", async ({ page, initTestBed }) => {
    await initTestBed(`<Timer testId="timer" />`);

    const timer = page.getByTestId("timer");
    await expect(timer).not.toBeVisible();
  });
});

test.describe.fixme("Event Handling", () => {
  test("timer tick event is called", async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickCount="{0}">
        <Timer interval="800" enabled="true" onTick="tickCount++" />
        <Text testId="counter">{tickCount}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    
    // Wait for a few ticks
    await expect(counter).toHaveText("0");
    
    // Wait for the first tick (1000ms + some buffer)
    await page.waitForTimeout(1200);
    await expect(counter).toHaveText("1");
    
    // Wait for the second tick
    await page.waitForTimeout(1000);
    await expect(counter).toHaveText("2");
  });

  test("timer stops when enabled is false", async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickCount="{0}" var.timerEnabled="{true}">
        <Timer interval="800" enabled="{timerEnabled}" onTick="tickCount++" />
        <Button testId="stopButton" onClick="timerEnabled = false">Stop Timer</Button>
        <Text testId="counter">{tickCount}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    const stopButton = page.getByTestId("stopButton");
    
    // Wait for the first tick
    await page.waitForTimeout(1200);
    await expect(counter).toHaveText("1");
    
    // Stop the timer
    await stopButton.click();
    
    // Wait and verify it doesn't increment
    await page.waitForTimeout(1500);
    await expect(counter).toHaveText("1");
  });

  test.fixme("timer prevents overlapping events", async ({ page, initTestBed }) => {
    // This test verifies that a new tick event doesn't fire if the previous one hasn't completed
    await initTestBed(`
      <Fragment var.tickStr="" var.processingTime="{2000}">
        <Timer 
          interval="800" 
          enabled="true" 
          onTick="
            tickStr += '+';
            delay(processingTime);
          " 
        />
        <Text testId="counter">{tickStr}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    
    // First tick should start and take 2000ms to complete
    // but interval is 1000ms, so second tick should not start until first completes
    await page.waitForTimeout(1500); // Wait for first tick to complete
    await expect(counter).toHaveText("+");
    
    // Wait a bit more to see if overlapping was prevented
    await page.waitForTimeout(1500); // Should be enough for second tick to start
    await expect(counter).toContainText("++");
  });
});

test.describe.fixme("Initial Delay Functionality", () => {
  test("timer waits for initial delay before first tick", async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickStr="">
        <Timer interval="800" initialDelay="1600" onTick="tickStr += '+'"/>
        <Text testId="counter">{tickStr}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    
    // Should not tick immediately
    await expect(counter).toHaveText("");
    
    // Should not tick before initial delay
    await page.waitForTimeout(1200);
    await expect(counter).toHaveText("");
    
    // Should tick after initial delay
    await page.waitForTimeout(800); // Total 2500ms, past the 2000ms initial delay + 1000ms interval
    await expect(counter).toHaveText("+");
    
    // Should continue ticking at interval
    await page.waitForTimeout(800);
    await expect(counter).toHaveText("++");
  });

  test("initial delay only applies to first execution, not restarts", async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickStr="" var.timerEnabled="{true}">
        <Timer 
          interval="400" 
          initialDelay="800" 
          enabled="{timerEnabled}" 
          onTick="tickStr += '+'"
        />
        <Button testId="restartButton" onClick="timerEnabled = false; timerEnabled = true">Restart</Button>
        <Text testId="counter">{tickStr}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    const restartButton = page.getByTestId("restartButton");
    
    // Wait for initial delay + first tick
    await page.waitForTimeout(1300);
    await expect(counter).toHaveText("+");
    
    // Restart the timer
    await restartButton.click();
    
    // After restart, should tick immediately without initial delay
    await page.waitForTimeout(500);
    await expect(counter).toContainText("++");
  });

  test("initial delay works with once timer", async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickStr="">
        <Timer interval="800" initialDelay="1600" once="true" onTick="tickStr += '+'"/>
        <Text testId="counter">{tickStr}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    
    // Should not tick before initial delay
    await page.waitForTimeout(1200);
    await expect(counter).toHaveText("");
    
    // Should tick once after initial delay
    await page.waitForTimeout(1000);
    await expect(counter).toHaveText("+");
    
    // Should not tick again
    await page.waitForTimeout(1000);
    await expect(counter).toHaveText("+");
  });
});

test.describe.fixme("Pause and Resume API", () => {
  test("timer can be paused and resumed via API", async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickStr="">
        <Timer 
          id="myTimer"
          interval="800" 
          onTick="tickStr += '+'"
        />
        <Button testId="pauseButton" onClick="myTimer.pause()">Pause</Button>
        <Button testId="resumeButton" onClick="myTimer.resume()">Resume</Button>
        <Text testId="counter">{tickStr}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    const pauseButton = page.getByTestId("pauseButton");
    const resumeButton = page.getByTestId("resumeButton");
    
    // Wait for first tick
    await page.waitForTimeout(1000);
    await expect(counter).toHaveText("+");
    
    // Pause the timer
    await pauseButton.click();
    
    // Should not tick while paused
    await page.waitForTimeout(1000);
    await expect(counter).toHaveText("+");
    
    // Resume the timer
    await resumeButton.click();
    
    // Should continue ticking after resume
    await page.waitForTimeout(1000);
    await expect(counter).toContainText("++");
  });

  test("pause state is reset when timer is disabled", async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickStr="" var.timerEnabled="{true}">
        <Timer 
          id="myTimer"
          interval="1000" 
          enabled="{timerEnabled}"
          onTick="tickStr += '+'"
        />
        <Button testId="pauseButton" onClick="myTimer.pause()">Pause</Button>
        <Button testId="disableButton" onClick="timerEnabled = false">Disable</Button>
        <Button testId="enableButton" onClick="timerEnabled = true">Enable</Button>
        <Text testId="counter">{tickStr}</Text>
        <Text testId="paused">{myTimer.isPaused() ? 'Paused' : 'Running'}</Text>
      </Fragment>
    `);

    const pauseButton = page.getByTestId("pauseButton");
    const disableButton = page.getByTestId("disableButton");
    const enableButton = page.getByTestId("enableButton");
    const pausedStatus = page.getByTestId("paused");
    
    // Pause the timer
    await pauseButton.click();
    await expect(pausedStatus).toHaveText("Paused");
    
    // Disable the timer
    await disableButton.click();
    
    // Re-enable the timer - pause state should be reset
    await enableButton.click();
    await expect(pausedStatus).toHaveText("Running");
  });
});

test.describe("Once Functionality", () => {
  test.fixme("timer with once=true fires only once", 
    SKIP_REASON.TEST_NOT_WORKING("Waiting for timeouts are bad practice because they are flaky."),
    async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickCount="{0}">
        <Timer interval="1000" once="true" onTick="tickCount++" />
        <Text testId="counter">{tickCount}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    
    // Wait for the first tick
    await page.waitForTimeout(1200);
    await expect(counter).toHaveText("1");
    
    // Wait longer to ensure it doesn't tick again
    await page.waitForTimeout(2000);
    await expect(counter).toHaveText("1");
  });

  test.fixme("timer with once=true can be restarted by re-enabling", 
    SKIP_REASON.TEST_NOT_WORKING("Waiting for timeouts are bad practice because they are flaky."),
    async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickCount="{0}" var.timerEnabled="{true}">
        <Timer interval="1000" once="true" enabled="{timerEnabled}" onTick="tickCount++" />
        <Button testId="restartButton" onClick="timerEnabled = false; timerEnabled = true">Restart</Button>
        <Text testId="counter">{tickCount}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    const restartButton = page.getByTestId("restartButton");
    
    // Wait for the first tick
    await page.waitForTimeout(1200);
    await expect(counter).toHaveText("1");
    
    // Restart the timer
    await restartButton.click();
    
    // Wait for another tick
    await page.waitForTimeout(1200);
    await expect(counter).toHaveText("2");
  });

  test.fixme("once timer doesn't interfere with regular timer functionality",
    SKIP_REASON.TEST_NOT_WORKING("Waiting for timeouts are bad practice because they are flaky."),
    async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickStr="">
        <Timer interval="1000" once="false" onTick="tickStr += '+'" />
        <Text testId="counter">{tickStr}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    
    // Wait for multiple ticks
    await page.waitForTimeout(2000);
    await expect(counter).toContainText("+");
  });
});

test.describe.fixme("State Management", () => {
  test("timer can be dynamically enabled and disabled", async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickCount="{0}" var.timerEnabled="{false}">
        <Timer interval="800" enabled="{timerEnabled}" onTick="tickCount++" />
        <Button testId="startButton" onClick="timerEnabled = true">Start Timer</Button>
        <Button testId="stopButton" onClick="timerEnabled = false">Stop Timer</Button>
        <Text testId="counter">{tickCount}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    const startButton = page.getByTestId("startButton");
    const stopButton = page.getByTestId("stopButton");
    
    // Initially disabled - should not increment
    await page.waitForTimeout(1000);
    await expect(counter).toHaveText("0");
    
    // Start the timer
    await startButton.click();
    await page.waitForTimeout(1000);
    await expect(counter).toHaveText("1");
    
    // Stop the timer again
    await stopButton.click();
    const currentCount = await counter.textContent();
    await page.waitForTimeout(1000);
    await expect(counter).toHaveText(currentCount || "1");
  });

  test("timer interval can be changed dynamically", async ({ page, initTestBed }) => {
    await initTestBed(`
      <Fragment var.tickCount="{0}" var.timerInterval="{2000}">
        <Timer interval="{timerInterval}" enabled="true" onTick="tickCount++" />
        <Button testId="fasterButton" onClick="timerInterval = 500">Faster</Button>
        <Text testId="counter">{tickCount}</Text>
      </Fragment>
    `);

    const counter = page.getByTestId("counter");
    const fasterButton = page.getByTestId("fasterButton");
    
    // Start with 2000ms interval
    await page.waitForTimeout(2500);
    await expect(counter).toHaveText("1");
    
    // Change to 500ms interval
    await fasterButton.click();
    await page.waitForTimeout(1500); // Should get multiple ticks quickly
    
    const finalCount = parseInt(await counter.textContent() || "0");
    expect(finalCount).toBeGreaterThan(1);
  });
});

```

--------------------------------------------------------------------------------
/xmlui/src/components-core/script-runner/eval-tree-common.ts:
--------------------------------------------------------------------------------

```typescript
import type { LogicalThread, ValueResult } from "../../abstractions/scripting/LogicalThread";
import {
  T_CALCULATED_MEMBER_ACCESS_EXPRESSION,
  T_IDENTIFIER,
  T_MEMBER_ACCESS_EXPRESSION,
  T_PREFIX_OP_EXPRESSION,
  type ArrowExpression,
  type AssignmentExpression,
  type BinaryExpression,
  type CalculatedMemberAccessExpression,
  type Expression,
  type Identifier,
  type Literal,
  type MemberAccessExpression,
  type PostfixOpExpression,
  type PrefixOpExpression,
  type UnaryExpression,
} from "./ScriptingSourceTree";
import type { BlockScope } from "../../abstractions/scripting/BlockScope";
import type { BindingTreeEvaluationContext } from "./BindingTreeEvaluationContext";

// --- Get the cached expression value
export function getExprValue(expr: Expression, thread: LogicalThread): any {
  return thread?.valueCache?.get(expr)?.value;
}

// --- Set the cached expression value
export function setExprValue(expr: Expression, value: any, thread: LogicalThread): void {
  thread.valueCache ??= new Map();
  thread.valueCache.set(expr, { value });
}

// --- Type guard to check for a Promise
export function isPromise(obj: any): obj is Promise<any> {
  return obj && typeof obj.then === "function";
}

// --- Evaluates a literal value (sync & async context)
export function evalLiteral(thisStack: any[], expr: Literal, thread: LogicalThread): any {
  setExprValue(expr, { value: expr.value }, thread);
  thisStack.push(expr.value);
  return expr.value;
}

type IdentifierScope = "global" | "app" | "localContext" | "block";

// --- Gets the scope of an identifier
export function getIdentifierScope(
  expr: Identifier,
  evalContext: BindingTreeEvaluationContext,
  thread?: LogicalThread,
): { type?: IdentifierScope; scope: any } {
  let type: IdentifierScope | undefined;
  let scope: any;

  // --- Search for primary value scope
  if (expr.isGlobal) {
    // --- Use the global scope only
    scope = globalThis;
    type = "global";
  } else {
    // --- Iterate trough threads from the current to the parent
    let currentThread: LogicalThread | undefined = thread ?? evalContext.mainThread;
    while (currentThread && !scope) {
      if (currentThread.blocks) {
        // --- Search the block-scopes
        for (let idx = currentThread.blocks.length - 1; idx >= 0; idx--) {
          const blockContext = currentThread.blocks[idx]?.vars;
          if (blockContext && expr.name in blockContext) {
            scope = blockContext;
            type = "block";
            break;
          }
        }
      }

      // --- We may have already found the ID
      if (scope) break;

      if (currentThread.closures) {
        // --- Search block-scopes of the closure list
        for (let idx = currentThread.closures.length - 1; idx >= 0; idx--) {
          const blockContext = currentThread.closures[idx]?.vars;
          if (blockContext && expr.name in blockContext) {
            scope = blockContext;
            type = "block";
            break;
          }
        }
      }

      // --- We may have already found the ID
      if (scope) break;

      // --- Check the parent thread
      currentThread = currentThread.parent;
    }
  }

  // --- If no identifier found so far, check the local context, the app context, and finally, the global context
  if (!scope) {
    if (evalContext.localContext && expr.name in evalContext.localContext) {
      // --- Object in localContext
      scope = evalContext.localContext;
      type = "localContext";
    } else if (evalContext.appContext?.[expr.name] !== undefined) {
      // --- Object in appContext
      scope = evalContext.appContext;
      type = "app";
    } else {
      // --- Finally, check the global context
      scope = globalThis;
      type = "global";
    }
  }

  // --- Done
  return { type, scope: scope };
}

// --- Evaluates an identifier (sync & async context)
export function evalIdentifier(
  thisStack: any[],
  expr: Identifier,
  evalContext: BindingTreeEvaluationContext,
  thread: LogicalThread,
): any {
  // --- Check the ID in the cache
  let value: any;
  // --- The cache does not contain the value.
  // --- We need to find the value and store it in the cache.
  const idScope = getIdentifierScope(expr, evalContext, thread);
  const valueScope = idScope.scope;
  let valueIndex: string | number = expr.name;
  value = valueScope[valueIndex];
  const newValue: ValueResult = {
    valueScope,
    valueIndex,
    value,
  };
  setExprValue(expr, newValue, thread);

  // --- Done.
  thisStack.push(value);
  return value;
}

// --- Gets the scope of the root ID
export function getRootIdScope(
  expr: Expression,
  evalContext: BindingTreeEvaluationContext,
  thread?: LogicalThread,
): { type: IdentifierScope | undefined; name: string } | null {
  switch (expr.type) {
    case T_IDENTIFIER:
      const idScope = getIdentifierScope(expr, evalContext, thread);
      return { type: idScope.type, name: expr.name };
    case T_MEMBER_ACCESS_EXPRESSION:
      return getRootIdScope(expr.obj, evalContext, thread);
    case T_CALCULATED_MEMBER_ACCESS_EXPRESSION:
      return getRootIdScope(expr.obj, evalContext, thread);
  }
  return null;
}

// --- Evaluates a member access expression (sync & async context)
export function evalMemberAccessCore(
  thisStack: any[],
  expr: MemberAccessExpression,
  evalContext: BindingTreeEvaluationContext,
  thread: LogicalThread,
): any {
  const parentObj = getExprValue(expr.obj, thread)?.value;
  const value =
    expr.opt || evalContext.options?.defaultToOptionalMemberAccess
      ? parentObj?.[expr.member]
      : parentObj[expr.member];
  setExprValue(
    expr,
    {
      valueScope: parentObj,
      valueIndex: expr.member,
      value,
    },
    thread,
  );
  thisStack.push(value);

  // --- Done.
  return value;
}

// --- Evaluates a calculated member access expression (sync & async context)
export function evalCalculatedMemberAccessCore(
  thisStack: any[],
  expr: CalculatedMemberAccessExpression,
  evalContext: BindingTreeEvaluationContext,
  thread: LogicalThread,
): any {
  const parentObj = getExprValue(expr.obj, thread)?.value;
  const memberObj = getExprValue(expr.member, thread)?.value;
  const value = evalContext.options?.defaultToOptionalMemberAccess
    ? parentObj?.[memberObj]
    : parentObj[memberObj];
  setExprValue(
    expr,
    {
      valueScope: parentObj,
      valueIndex: memberObj,
      value,
    },
    thread,
  );
  thisStack.push(value);

  // --- Done.
  return value;
}

// --- Evaluates a unary expression (sync & async context)
export function evalUnaryCore(
  expr: UnaryExpression,
  thisStack: any[],
  evalContext: BindingTreeEvaluationContext,
  thread: LogicalThread,
): any {
  let value: any;
  const operand = getExprValue(expr.expr, thread);
  const operValue = operand?.value;
  switch (expr.op) {
    case "typeof":
      value = typeof operValue;
      break;
    case "delete":
      if (operand.valueScope && operand.valueIndex) {
        value = delete operand.valueScope[operand.valueIndex];
      } else {
        value = false;
      }
      break;
    case "+":
      value = operValue;
      break;
    case "-":
      value = -operValue;
      break;
    case "!":
      value = !operValue;
      break;
    case "~":
      value = ~operValue;
      break;
    default:
      throw new Error(`Unknown unary operator: ${expr.op}`);
  }
  setExprValue(expr, { value }, thread);

  // --- Done.
  thisStack.push(value);
  return value;
}

// --- Evaluates a binary operation (sync & async context)
export function evalBinaryCore(
  expr: BinaryExpression,
  thisStack: any[],
  evalContext: BindingTreeEvaluationContext,
  thread: LogicalThread,
): any {
  let value: any;
  const l = getExprValue(expr.left, thread)?.value;
  const r = getExprValue(expr.right, thread)?.value;
  switch (expr.op) {
    case "**":
      value = l ** r;
      break;
    case "*":
      value = l * r;
      break;
    case "/":
      value = l / r;
      break;
    case "%":
      value = l % r;
      break;
    case "+":
      value = l + r;
      break;
    case "-":
      value = l - r;
      break;
    case ">>":
      value = l >> r;
      break;
    case ">>>":
      value = l >>> r;
      break;
    case "<<":
      value = l << r;
      break;
    case "<":
      value = l < r;
      break;
    case "<=":
      value = l <= r;
      break;
    case ">":
      value = l > r;
      break;
    case ">=":
      value = l >= r;
      break;
    case "in":
      value = l in r;
      break;
    case "==":
      // eslint-disable-next-line eqeqeq
      value = l == r;
      break;
    case "!=":
      // eslint-disable-next-line eqeqeq
      value = l != r;
      break;
    case "===":
      value = l === r;
      break;
    case "!==":
      value = l !== r;
      break;
    case "&":
      value = l & r;
      break;
    case "^":
      value = l ^ r;
      break;
    case "|":
      value = l | r;
      break;
    case "&&":
      value = l && r;
      break;
    case "||":
      value = l || r;
      break;
    case "??":
      value = l ?? r;
      break;
    default:
      throw new Error(`Unknown binary operator: ${expr.op}`);
  }
  setExprValue(expr, { value }, thread);

  // --- Done.
  thisStack.push(value);
  return value;
}

// --- Evaluates an assignment operation (sync & async context)
export function evalAssignmentCore(
  thisStack: any[],
  expr: AssignmentExpression,
  evalContext: BindingTreeEvaluationContext,
  thread: LogicalThread,
): any {
  const leftValue = getExprValue(expr.leftValue, thread);
  const newValue = getExprValue(expr.expr, thread)?.value;
  if (
    !leftValue.valueScope ||
    leftValue.valueIndex === undefined ||
    leftValue.valueIndex === null
  ) {
    throw new Error(`Evaluation of ${expr.op} requires a left-hand value.`);
  }

  const leftScope = leftValue.valueScope;
  const leftIndex = leftValue.valueIndex;
  if (typeof leftScope !== "object" || leftScope === null) {
    // TODO: Specify the error location in the error message
    throw new Error(`Unknown left-hand value`);
  }

  // --- Check for const value
  if (expr.leftValue.type === T_IDENTIFIER) {
    if (isConstVar(expr.leftValue.name, thread)) {
      throw new Error("A const variable cannot be modified");
    }
  }

  if (leftScope === globalThis && !(leftIndex in leftScope)) {
    throw new Error(`Left value variable (${leftIndex}) not found in the scope.`);
  }

  thisStack.pop();
  switch (expr.op) {
    case "=":
      leftScope[leftIndex] = newValue;
      break;
    case "+=":
      leftScope[leftIndex] += newValue;
      break;
    case "-=":
      leftScope[leftIndex] -= newValue;
      break;
    case "**=":
      leftScope[leftIndex] **= newValue;
      break;
    case "*=":
      leftScope[leftIndex] *= newValue;
      break;
    case "/=":
      leftScope[leftIndex] /= newValue;
      break;
    case "%=":
      leftScope[leftIndex] %= newValue;
      break;
    case "<<=":
      leftScope[leftIndex] <<= newValue;
      break;
    case ">>=":
      leftScope[leftIndex] >>= newValue;
      break;
    case ">>>=":
      leftScope[leftIndex] >>>= newValue;
      break;
    case "&=":
      leftScope[leftIndex] &= newValue;
      break;
    case "^=":
      leftScope[leftIndex] ^= newValue;
      break;
    case "|=":
      leftScope[leftIndex] |= newValue;
      break;
    case "&&=":
      leftScope[leftIndex] &&= newValue;
      break;
    case "||=":
      leftScope[leftIndex] ||= newValue;
      break;
    case "??=":
      leftScope[leftIndex] += newValue;
      break;
  }
  const value = leftScope[leftIndex];
  setExprValue(expr, { value }, thread);
  thisStack.push(value);
  return value;
}

// --- Evaluates a prefix/postfix operator (sync & async context)
export function evalPreOrPostCore(
  thisStack: any[],
  expr: PrefixOpExpression | PostfixOpExpression,
  evalContext: BindingTreeEvaluationContext,
  thread: LogicalThread,
): any {
  const operand = getExprValue(expr.expr, thread);
  if (!operand.valueScope || operand.valueIndex === undefined) {
    throw new Error(`Evaluation of ${expr.op} requires a left-hand value.`);
  }

  // --- Check for const value
  if (expr.expr.type === T_IDENTIFIER) {
    if (isConstVar(expr.expr.name, thread)) {
      // --- We cannot modify a const value
      throw new Error("A const variable cannot be modified");
    }
  }

  const value =
    expr.op === "++"
      ? expr.type === T_PREFIX_OP_EXPRESSION
        ? ++operand.valueScope[operand.valueIndex]
        : operand.valueScope[operand.valueIndex]++
      : expr.type === T_PREFIX_OP_EXPRESSION
        ? --operand.valueScope[operand.valueIndex]
        : operand.valueScope[operand.valueIndex]--;

  setExprValue(expr, { value }, thread);
  thisStack.push(value);
  return value;
}

// --- Evaluates an arrow expression (lazy, sync & async context)
export function evalArrow(
  thisStack: any[],
  expr: ArrowExpression,
  thread: LogicalThread,
): ArrowExpression {
  const lazyArrow = {
    ...expr,
    _ARROW_EXPR_: true,
    closureContext: obtainClosures(thread),
  } as ArrowExpression;
  setExprValue(expr, { value: lazyArrow }, thread);
  thisStack.push(lazyArrow);
  return lazyArrow;
}

export function obtainClosures(thread: LogicalThread): BlockScope[] {
  const closures = thread.blocks?.slice(0) ?? [];
  return thread.parent ? [...obtainClosures(thread.parent), ...closures] : closures;
}

/**
 * Gets the context of the variable
 * @param id Identifier to test
 * @param thread Thread to use for evaluation
 */
function isConstVar(id: string, thread: LogicalThread): boolean {
  // --- Start search the block context
  if (thread.blocks) {
    for (let idx = thread.blocks.length; idx >= 0; idx--) {
      const constContext = thread.blocks[idx]?.constVars;
      if (constContext && constContext.has(id)) return true;
    }
  }

  // --- Not in block context
  return false;
}

export function evalTemplateLiteralCore(segmentValues: any[]): string {
  return segmentValues.map((value) => (typeof value === "string" ? value : `${value}`)).join("");
}

```
Page 48/143FirstPrevNextLast