#
tokens: 46779/50000 2/1633 files (page 123/186)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 123 of 186. Use http://codebase.md/xmlui-org/xmlui/tools/vscode/resources/%7BextractResourceUrl(node.props.src)%7D?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .changeset
│   └── config.json
├── .eslintrc.cjs
├── .github
│   ├── build-checklist.png
│   ├── ISSUE_TEMPLATE
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows
│       ├── deploy-blog-optimized.yml
│       ├── deploy-blog-swa.yml
│       ├── deploy-blog.yml
│       ├── deploy-docs-optimized.yml
│       ├── deploy-docs.yml
│       ├── prepare-versions.yml
│       ├── release-packages.yml
│       ├── run-all-tests.yml
│       └── run-smoke-tests.yml
├── .gitignore
├── .prettierrc.js
├── .vscode
│   ├── launch.json
│   └── settings.json
├── blog
│   ├── .gitignore
│   ├── .gitkeep
│   ├── CHANGELOG.md
│   ├── extensions.ts
│   ├── index.html
│   ├── index.ts
│   ├── package.json
│   ├── public
│   │   ├── blog
│   │   │   ├── images
│   │   │   │   ├── an-advanced-codefence.gif
│   │   │   │   ├── an-advanced-codefence.mp4
│   │   │   │   ├── blog-page-component.png
│   │   │   │   ├── blog-scrabble.png
│   │   │   │   ├── codefence-runner.png
│   │   │   │   ├── integrated-blog-search.png
│   │   │   │   ├── lorem-ipsum.png
│   │   │   │   ├── playground-checkbox-source.png
│   │   │   │   ├── playground.png
│   │   │   │   ├── use-xmlui-mcp-to-find-a-howto.png
│   │   │   │   └── xmlui-demo-gallery.png
│   │   │   ├── introducing-xmlui.md
│   │   │   ├── lorem-ipsum.md
│   │   │   ├── newest-post.md
│   │   │   ├── older-post.md
│   │   │   ├── xmlui-playground.md
│   │   │   └── xmlui-powered-blog.md
│   │   ├── mockServiceWorker.js
│   │   ├── resources
│   │   │   ├── favicon.ico
│   │   │   ├── files
│   │   │   │   └── for-download
│   │   │   │       └── xmlui
│   │   │   │           └── xmlui-standalone.umd.js
│   │   │   ├── github.svg
│   │   │   ├── llms.txt
│   │   │   ├── logo-dark.svg
│   │   │   ├── logo.svg
│   │   │   ├── pg-popout.svg
│   │   │   ├── rss.svg
│   │   │   └── xmlui-logo.svg
│   │   ├── serve.json
│   │   ├── 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.tsx
│   │       │   ├── ConfirmationDialog.module.scss
│   │       │   ├── ConfirmationDialog.tsx
│   │       │   ├── Editor.tsx
│   │       │   ├── Header.module.scss
│   │       │   ├── Header.tsx
│   │       │   ├── Playground.tsx
│   │       │   ├── PlaygroundContent.module.scss
│   │       │   ├── PlaygroundContent.tsx
│   │       │   ├── PlaygroundNative.module.scss
│   │       │   ├── PlaygroundNative.tsx
│   │       │   ├── Preview.module.scss
│   │       │   ├── Preview.tsx
│   │       │   ├── Select.module.scss
│   │       │   ├── StandalonePlayground.tsx
│   │       │   ├── StandalonePlaygroundNative.module.scss
│   │       │   ├── StandalonePlaygroundNative.tsx
│   │       │   ├── ThemeSwitcher.module.scss
│   │       │   ├── ThemeSwitcher.tsx
│   │       │   ├── ToneSwitcher.tsx
│   │       │   ├── Tooltip.module.scss
│   │       │   ├── Tooltip.tsx
│   │       │   └── utils.ts
│   │       ├── providers
│   │       │   ├── Toast.module.scss
│   │       │   └── ToastProvider.tsx
│   │       ├── state
│   │       │   └── store.ts
│   │       ├── themes
│   │       │   └── theme.ts
│   │       └── utils
│   │           └── helpers.ts
│   ├── xmlui-search
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── demo
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   └── src
│   │       ├── index.tsx
│   │       ├── Search.module.scss
│   │       └── Search.tsx
│   ├── xmlui-spreadsheet
│   │   ├── .gitignore
│   │   ├── demo
│   │   │   └── Main.xmlui
│   │   ├── index.html
│   │   ├── index.ts
│   │   ├── meta
│   │   │   └── componentsMetadata.ts
│   │   ├── package.json
│   │   └── src
│   │       ├── index.tsx
│   │       ├── Spreadsheet.tsx
│   │       └── SpreadsheetNative.tsx
│   └── xmlui-website-blocks
│       ├── .gitignore
│       ├── CHANGELOG.md
│       ├── demo
│       │   ├── components
│       │   │   ├── HeroBackgroundBreakoutPage.xmlui
│       │   │   ├── HeroBackgroundsPage.xmlui
│       │   │   ├── HeroContentsPage.xmlui
│       │   │   ├── HeroTextAlignPage.xmlui
│       │   │   ├── HeroTextPage.xmlui
│       │   │   └── HeroTonesPage.xmlui
│       │   ├── Main.xmlui
│       │   └── themes
│       │       └── default.ts
│       ├── index.html
│       ├── index.ts
│       ├── meta
│       │   └── componentsMetadata.ts
│       ├── package.json
│       ├── public
│       │   └── resources
│       │       ├── building.jpg
│       │       └── xmlui-logo.svg
│       └── src
│           ├── Carousel
│           │   ├── Carousel.module.scss
│           │   ├── Carousel.tsx
│           │   ├── CarouselContext.tsx
│           │   └── CarouselNative.tsx
│           ├── FancyButton
│           │   ├── FancyButton.module.scss
│           │   ├── FancyButton.tsx
│           │   └── FancyButton.xmlui
│           ├── Hello
│           │   ├── Hello.tsx
│           │   ├── Hello.xmlui
│           │   └── Hello.xmlui.xs
│           ├── HeroSection
│           │   ├── HeroSection.module.scss
│           │   ├── HeroSection.spec.ts
│           │   ├── HeroSection.tsx
│           │   └── HeroSectionNative.tsx
│           ├── index.tsx
│           ├── ScrollToTop
│           │   ├── ScrollToTop.module.scss
│           │   ├── ScrollToTop.tsx
│           │   └── ScrollToTopNative.tsx
│           └── vite-env.d.ts
├── playwright.config.ts
├── README.md
├── tools
│   ├── codefence
│   │   └── xmlui-code-fence-docs.md
│   ├── create-app
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── create-app.ts
│   │   ├── helpers
│   │   │   ├── copy.ts
│   │   │   ├── get-pkg-manager.ts
│   │   │   ├── git.ts
│   │   │   ├── install.ts
│   │   │   ├── is-folder-empty.ts
│   │   │   ├── is-writeable.ts
│   │   │   ├── make-dir.ts
│   │   │   └── validate-pkg.ts
│   │   ├── index.ts
│   │   ├── package.json
│   │   ├── templates
│   │   │   ├── default
│   │   │   │   └── ts
│   │   │   │       ├── gitignore
│   │   │   │       ├── index.html
│   │   │   │       ├── index.ts
│   │   │   │       ├── public
│   │   │   │       │   ├── mockServiceWorker.js
│   │   │   │       │   ├── resources
│   │   │   │       │   │   ├── favicon.ico
│   │   │   │       │   │   └── xmlui-logo.svg
│   │   │   │       │   └── serve.json
│   │   │   │       └── src
│   │   │   │           ├── components
│   │   │   │           │   ├── ApiAware.xmlui
│   │   │   │           │   ├── Home.xmlui
│   │   │   │           │   ├── IncButton.xmlui
│   │   │   │           │   └── PagePanel.xmlui
│   │   │   │           ├── config.ts
│   │   │   │           └── Main.xmlui
│   │   │   ├── index.ts
│   │   │   └── types.ts
│   │   └── tsconfig.json
│   ├── create-xmlui-hello-world
│   │   ├── index.js
│   │   └── package.json
│   └── vscode
│       ├── .gitignore
│       ├── .vscode
│       │   ├── launch.json
│       │   └── tasks.json
│       ├── .vscodeignore
│       ├── build.sh
│       ├── CHANGELOG.md
│       ├── esbuild.js
│       ├── eslint.config.mjs
│       ├── formatter-docs.md
│       ├── generate-test-sample.sh
│       ├── LICENSE.md
│       ├── package-lock.json
│       ├── package.json
│       ├── README.md
│       ├── resources
│       │   ├── xmlui-logo.png
│       │   └── xmlui-markup-syntax-highlighting.png
│       ├── src
│       │   ├── extension.ts
│       │   └── server.ts
│       ├── syntaxes
│       │   └── xmlui.tmLanguage.json
│       ├── test-samples
│       │   └── sample.xmlui
│       ├── tsconfig.json
│       └── tsconfig.tsbuildinfo
├── turbo.json
└── xmlui
    ├── .gitignore
    ├── bin
    │   ├── bootstrap.cjs
    │   ├── bootstrap.js
    │   ├── build-lib.ts
    │   ├── build.ts
    │   ├── index.ts
    │   ├── preview.ts
    │   ├── start.ts
    │   ├── vite-xmlui-plugin.ts
    │   └── viteConfig.ts
    ├── CHANGELOG.md
    ├── conventions
    │   ├── component-qa-checklist.md
    │   ├── copilot-conventions.md
    │   ├── create-xmlui-components.md
    │   ├── mermaid.md
    │   ├── testing-conventions.md
    │   └── xmlui-in-a-nutshell.md
    ├── dev-docs
    │   ├── accessibility.md
    │   ├── build-system.md
    │   ├── build-xmlui.md
    │   ├── component-behaviors.md
    │   ├── 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.bin.json
    ├── tsconfig.json
    ├── tsconfig.node.json
    ├── vite.config.ts
    └── vitest.config.ts
```

# Files

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

```typescript
  1 | import { expect, test } from "../../testing/fixtures";
  2 | 
  3 | // =============================================================================
  4 | // BASIC FUNCTIONALITY TESTS
  5 | // =============================================================================
  6 | 
  7 | test.describe("Basic Functionality", () => {
  8 |   // --- Component rendering
  9 | 
 10 |   test("dynamic options displayed with Items component", async ({
 11 |     initTestBed,
 12 |     createSelectDriver,
 13 |     page,
 14 |   }) => {
 15 |     await initTestBed(`
 16 |       <Select>
 17 |         <Items data="{['One', 'Two', 'Three']}" >
 18 |           <Option value="{$itemIndex}" label="{$item}" />
 19 |         </Items>
 20 |       </Select>`);
 21 |     const driver = await createSelectDriver();
 22 | 
 23 |     await driver.click();
 24 |     await expect(page.getByRole("option", { name: "One" })).toBeVisible();
 25 |     await expect(page.getByRole("option", { name: "Two" })).toBeVisible();
 26 |     await expect(page.getByRole("option", { name: "Three" })).toBeVisible();
 27 |   });
 28 | 
 29 |   test("changing selected option in form", async ({ initTestBed, createSelectDriver }) => {
 30 |     await initTestBed(`
 31 |     <Form data="{{sel: 'opt1'}}">
 32 |       <FormItem testId="mySelect" type="select" bindTo="sel">
 33 |         <Option value="opt1" label="first"/>
 34 |         <Option value="opt2" label="second"/>
 35 |         <Option value="opt3" label="third"/>
 36 |       </FormItem>
 37 |     </Form>`);
 38 |     const driver = await createSelectDriver("mySelect");
 39 | 
 40 |     await expect(driver.component).toHaveText("first");
 41 |     await driver.toggleOptionsVisibility();
 42 |     await driver.selectLabel("second");
 43 |     await expect(driver.component).toHaveText("second");
 44 |   });
 45 | 
 46 |   // --- initialValue prop
 47 | 
 48 |   test("initialValue set to first valid value", async ({ page, initTestBed }) => {
 49 |     await initTestBed(`
 50 |     <Fragment>
 51 |       <Select id="mySelect" initialValue="{0}">
 52 |         <Option value="{0}" label="Zero"/>
 53 |         <Option value="{1}" label="One"/>
 54 |         <Option value="{2}" label="Two"/>
 55 |       </Select>
 56 |       <Text testId="text">Selected value: {mySelect.value}</Text>
 57 |     </Fragment>
 58 |   `);
 59 |     await expect(page.getByTestId("text")).toHaveText("Selected value: 0");
 60 |     await expect(page.getByText("Zero", { exact: true })).toBeVisible();
 61 |     await expect(page.getByText("One", { exact: true })).not.toBeVisible();
 62 |   });
 63 | 
 64 |   test("initialValue set to non-existant option", async ({ page, initTestBed }) => {
 65 |     await initTestBed(`
 66 |     <Fragment>
 67 |       <Select id="mySelect" initialValue="{42}">
 68 |         <Option value="{0}" label="Zero"/>
 69 |         <Option value="{1}" label="One"/>
 70 |         <Option value="{2}" label="Two"/>
 71 |       </Select>
 72 |       <Text testId="text">Selected value: {mySelect.value}</Text>
 73 |     </Fragment>
 74 |   `);
 75 |     await expect(page.getByTestId("text")).toHaveText("Selected value: 42");
 76 |   });
 77 | 
 78 |   test("reset works with initialValue", async ({
 79 |     page,
 80 |     initTestBed,
 81 |     createSelectDriver,
 82 |     createButtonDriver,
 83 |   }) => {
 84 |     await initTestBed(`
 85 |     <Fragment>
 86 |       <Select id="mySelect" initialValue="{0}">
 87 |         <Option value="{0}" label="Zero"/>
 88 |         <Option value="{1}" label="One"/>
 89 |         <Option value="{2}" label="Two"/>
 90 |       </Select>
 91 |       <Button id="resetBtn" label="reset" onClick="mySelect.reset()"/>
 92 |       <Text testId="text">Selected value: {mySelect.value}</Text>
 93 |     </Fragment>
 94 |     `);
 95 |     const selectDrv = await createSelectDriver("mySelect");
 96 |     await selectDrv.toggleOptionsVisibility();
 97 |     await selectDrv.selectLabel("One");
 98 |     await expect(page.getByTestId("text")).toHaveText("Selected value: 1");
 99 |     const btnDriver = await createButtonDriver("resetBtn");
100 |     await btnDriver.click();
101 | 
102 |     await expect(page.getByTestId("text")).toHaveText("Selected value: 0");
103 |   });
104 | 
105 |   test("reset works with no intialValue", async ({
106 |     page,
107 |     initTestBed,
108 |     createSelectDriver,
109 |     createButtonDriver,
110 |   }) => {
111 |     await initTestBed(`
112 |     <Fragment>
113 |       <Select id="mySelect">
114 |         <Option value="{0}" label="Zero"/>
115 |         <Option value="{1}" label="One"/>
116 |         <Option value="{2}" label="Two"/>
117 |       </Select>
118 |       <Button id="resetBtn" label="reset" onClick="mySelect.reset()"/>
119 |       <Text testId="text">Selected value: {mySelect.value}</Text>
120 |     </Fragment>
121 |     `);
122 |     const selectDrv = await createSelectDriver("mySelect");
123 |     await selectDrv.toggleOptionsVisibility();
124 |     await selectDrv.selectLabel("One");
125 |     await expect(page.getByTestId("text")).toHaveText("Selected value: 1");
126 |     const btnDriver = await createButtonDriver("resetBtn");
127 |     await btnDriver.click();
128 | 
129 |     await expect(page.getByTestId("text")).not.toContainText("1");
130 |   });
131 | 
132 |   // --- enabled prop
133 | 
134 |   test("disabled Select cannot be opened", async ({ page, createSelectDriver, initTestBed }) => {
135 |     await initTestBed(`
136 |     <Select enabled="{false}">
137 |       <Option value="1" label="One"/>
138 |       <Option value="2" label="Two"/>
139 |     </Select>
140 |     `);
141 |     const driver = await createSelectDriver();
142 |     await driver.click({ force: true });
143 |     await expect(page.getByText("One")).not.toBeVisible();
144 |   });
145 | 
146 |   // --- readOnly prop
147 | 
148 |   test("readOnly Select shows options, but value cannot be changed", async ({
149 |     page,
150 |     initTestBed,
151 |     createSelectDriver,
152 |   }) => {
153 |     await initTestBed(`
154 |     <Select readOnly initialValue="1">
155 |       <Option value="1" label="One"/>
156 |       <Option value="2" label="Two"/>
157 |     </Select>
158 |     `);
159 |     const driver = await createSelectDriver();
160 |     await expect(driver.component).toHaveText("One");
161 |     await driver.toggleOptionsVisibility();
162 |     await driver.selectLabel("Two");
163 |     await expect(driver.component).toHaveText("One");
164 | 
165 |     // verify dropdown is not visible but value is shown
166 |   });
167 | 
168 |   test("readOnly multi-Select shows options, but value cannot be changed", async ({
169 |     page,
170 |     initTestBed,
171 |     createSelectDriver,
172 |   }) => {
173 |     await initTestBed(`
174 |     <Select readOnly initialValue="{[1, 2]}" multiSelect>
175 |       <Option value="1" label="One"/>
176 |       <Option value="2" label="Two"/>
177 |       <Option value="3" label="Three"/>
178 |     </Select>
179 |     `);
180 |     const driver = await createSelectDriver();
181 |     await expect(page.getByText("Three")).not.toBeVisible();
182 |     await expect(page.getByText("One")).toBeVisible();
183 |     await expect(page.getByText("Two")).toBeVisible();
184 | 
185 |     await driver.toggleOptionsVisibility();
186 |     await driver.selectLabel("Three");
187 | 
188 |     await expect(page.getByText("Three")).not.toBeVisible();
189 |     await expect(page.getByText("One")).toBeVisible();
190 |     await expect(page.getByText("Two")).toBeVisible();
191 |   });
192 | 
193 |   test("disabled Option cannot be selected", async ({ initTestBed, createSelectDriver, page }) => {
194 |     await initTestBed(`
195 |     <Select>
196 |       <Option value="1" label="One"/>
197 |       <Option value="2" label="Two" enabled="{false}"/>
198 |     </Select>
199 |     `);
200 |     await expect(page.getByRole("option", { name: "One" })).not.toBeVisible();
201 |     await expect(page.getByRole("option", { name: "Two" })).not.toBeVisible();
202 |     const driver = await createSelectDriver();
203 |     await driver.toggleOptionsVisibility();
204 |     await driver.selectLabel("Two");
205 |     await expect(page.getByRole("option", { name: "One" })).toBeVisible();
206 |     await expect(page.getByRole("option", { name: "Two" })).toBeVisible();
207 |   });
208 | 
209 |   test(
210 |     "clicking label brings up the options",
211 |     { tag: "@smoke" },
212 |     async ({ initTestBed, page, createSelectDriver }) => {
213 |       await initTestBed(`
214 |     <Select label="Choose an option">
215 |       <Option value="1" label="One"/>
216 |       <Option value="2" label="Two"/>
217 |     </Select>
218 |   `);
219 |       await page.getByLabel("Choose an option").click();
220 |       await expect(page.getByRole("option", { name: "One" })).toBeVisible();
221 |       await expect(page.getByRole("option", { name: "Two" })).toBeVisible();
222 |     },
223 |   );
224 | 
225 |   test("label displayed for selected numeric value", async ({ page, initTestBed }) => {
226 |     await initTestBed(`
227 |     <Fragment>
228 |       <Select initialValue="{0}" >
229 |         <Option value="{0}" label="Zero"/>
230 |         <Option value="{1}" label="One"/>
231 |         <Option value="{2}" label="Two"/>
232 |       </Select>
233 |     </Fragment>
234 |   `);
235 |     await expect(page.getByText("Zero")).toBeVisible();
236 |   });
237 | 
238 |   // --- autoFocus prop
239 | 
240 |   test("autoFocus brings the focus to component", async ({
241 |     initTestBed,
242 |     page,
243 |     createSelectDriver,
244 |   }) => {
245 |     await initTestBed(`
246 |     <Select>
247 |       <Option value="1" label="One"/>
248 |       <Option value="2" label="Two"/>
249 |     </Select>
250 |     <Select testId="focused-select" autoFocus>
251 |       <Option value="1" label="One"/>
252 |       <Option value="2" label="Two"/>
253 |     </Select>
254 |     `);
255 |     const driver = await createSelectDriver("focused-select");
256 | 
257 |     await expect(driver.component).toBeFocused();
258 |   });
259 | 
260 |   // --- Templates
261 | 
262 |   test("emptyListTemplate shown when wrapped inside an App component", async ({
263 |     initTestBed,
264 |     page,
265 |     createSelectDriver,
266 |   }) => {
267 |     await initTestBed(`
268 |     <App>
269 |       <Select testId="mySelect">
270 |         <property name="emptyListTemplate">
271 |           <Text value="Nothing to see here!" />
272 |         </property>
273 |       </Select>
274 |     </App>
275 |     `);
276 |     const driver = await createSelectDriver("mySelect");
277 |     await driver.click();
278 | 
279 |     await expect(page.getByText("Nothing to see here!", { exact: true })).toBeVisible();
280 |   });
281 | 
282 |   test("optionTemplate is shown", async ({ initTestBed, page, createSelectDriver }) => {
283 |     await initTestBed(`
284 |     <Select>
285 |       <Items items="{[
286 |         { value: 'opt1', label: 'first' },
287 |         { value: 'opt2', label: 'second' },
288 |         { value: 'opt3', label: 'third' },
289 |       ]}">
290 |         <Option value="{$item.value}" label="{$item.label}">
291 |           <Text>Template for value {$item.value}</Text>
292 |         </Option>
293 |       </Items>
294 |     </Select>
295 |     `);
296 |     const driver = await createSelectDriver();
297 |     await driver.click();
298 |     await expect(page.getByText("Template for value opt1")).toBeVisible();
299 |     await expect(page.getByText("Template for value opt2")).toBeVisible();
300 |     await expect(page.getByText("Template for value opt3")).toBeVisible();
301 |   });
302 | 
303 |   // --- placeholder prop
304 | 
305 |   test("placeholder is shown", async ({ initTestBed, page, createSelectDriver }) => {
306 |     await initTestBed(`
307 |       <Select placeholder="Please select an item">
308 |         <Option value="opt1" label="first"/>
309 |         <Option value="opt2" label="second"/>
310 |         <Option value="opt3" label="third"/>
311 |       </Select>
312 |     `);
313 |     await expect(page.getByText("Please select an item")).toBeVisible();
314 |   });
315 | 
316 |   test(
317 |     "Option without label and value is not rendered",
318 |     { tag: "@smoke" },
319 |     async ({ initTestBed, page, createSelectDriver }) => {
320 |       await initTestBed(`
321 |       <Select placeholder="Please select an item">
322 |         <Option />
323 |         <Option />
324 |         <Option />
325 |       </Select>
326 |     `);
327 |       const driver = await createSelectDriver();
328 |       await driver.click();
329 |       await expect(page.getByRole("option")).not.toBeVisible();
330 |     },
331 |   );
332 | 
333 |   test(
334 |     "Option value defaults to label",
335 |     { tag: "@smoke" },
336 |     async ({ initTestBed, page, createSelectDriver }) => {
337 |       await initTestBed(`
338 |       <Fragment>
339 |         <Select id="mySelect">
340 |           <Option label="Zero"/>
341 |           <Option label="One"/>
342 |           <Option label="Two"/>
343 |         </Select>
344 |         <Text testId="text">Selected value: {mySelect.value}</Text>
345 |       </Fragment>
346 |     `);
347 |       const driver = await createSelectDriver("mySelect");
348 |       await driver.toggleOptionsVisibility();
349 |       await driver.selectLabel("Zero");
350 |       await expect(page.getByTestId("text")).toHaveText("Selected value: Zero");
351 |     },
352 |   );
353 | });
354 | 
355 | // =============================================================================
356 | // LABEL POSITIONING TESTS
357 | // =============================================================================
358 | 
359 | test.describe("Label", () => {
360 |   test("labelBreak prop defaults to false", async ({ initTestBed, page, createSelectDriver }) => {
361 |     await page.setViewportSize({ width: 300, height: 720 });
362 | 
363 |     await initTestBed(`
364 |     <Select
365 |       label="Dignissimos esse quasi esse cupiditate qui qui. Ut provident ad voluptatem tenetur sit consequuntur. Aliquam nisi fugit ut temporibus itaque ducimus rerum. Dolorem reprehenderit qui adipisci. Ullam harum atque ipsa."
366 |       >
367 |       <Option value="1" label="One"/>
368 |       <Option value="2" label="Two"/>
369 |     </Select>
370 |     `);
371 |     const labelWidth = (await page.getByText("Dignissimos esse quasi").boundingBox()).width;
372 |     const select = page.getByRole("button").or(page.getByRole("combobox")).first();
373 |     const { width: selectWidth } = await select.boundingBox();
374 |     expect(labelWidth).toBe(selectWidth);
375 |   });
376 | 
377 |   test('labelWidth applies with labelPosition="start"', async ({ initTestBed, page }) => {
378 |     await page.setViewportSize({ width: 300, height: 720 });
379 | 
380 |     await initTestBed(`
381 |       <Select label="Dignissimos esse quasi" labelWidth="200px" labelPosition="start" >
382 |         <Option value="opt1" label="first"/>
383 |         <Option value="opt2" label="second"/>
384 |         <Option value="opt3" label="third"/>
385 |         <Option value="opt4" label="fourth"/>
386 |         <Option value="opt5" label="fifth"/>
387 |       </Select>
388 |     `);
389 |     const labelWidth = (await page.getByText("Dignissimos esse quasi").boundingBox()).width;
390 |     expect(labelWidth).toBeGreaterThanOrEqual(200);
391 |   });
392 | });
393 | 
394 | // =============================================================================
395 | // SEARCHABLE SELECT TESTS
396 | // =============================================================================
397 | 
398 | test.describe("searchable select", () => {
399 |   test("placeholder is shown", async ({ initTestBed, page, createSelectDriver }) => {
400 |     await initTestBed(`
401 |       <Select searchable placeholder="Please select an item">
402 |         <Option value="opt1" label="first"/>
403 |         <Option value="opt2" label="second"/>
404 |         <Option value="opt3" label="third"/>
405 |       </Select>
406 |     `);
407 |     await expect(page.getByText("Please select an item")).toBeVisible();
408 |   });
409 | 
410 |   test("inProgressNotificationMessage shown when inProgress is true", async ({
411 |     initTestBed,
412 |     page,
413 |     createSelectDriver,
414 |   }) => {
415 |     await initTestBed(`
416 |       <Select searchable inProgress inProgressNotificationMessage="in-progress-msg">
417 |         <Option value="opt1" label="first"/>
418 |         <Option value="opt2" label="second"/>
419 |         <Option value="opt3" label="third"/>
420 |       </Select>
421 |     `);
422 |     const driver = await createSelectDriver();
423 |     await driver.click();
424 |     await expect(page.getByText("in-progress-msg")).toBeVisible();
425 |   });
426 | 
427 |   test("inProgressNotificationMessage not shown when inProgress is false", async ({
428 |     initTestBed,
429 |     page,
430 |     createSelectDriver,
431 |   }) => {
432 |     await initTestBed(`
433 |       <Select searchable inProgress="false" inProgressNotificationMessage="in-progress-msg">
434 |         <Option value="opt1" label="first"/>
435 |         <Option value="opt2" label="second"/>
436 |         <Option value="opt3" label="third"/>
437 |       </Select>
438 |     `);
439 |     const driver = await createSelectDriver();
440 |     await driver.click();
441 |     await expect(page.getByText("in-progress-msg")).not.toBeVisible();
442 |   });
443 | 
444 |   test(
445 |     "search filters option labels",
446 |     { tag: "@smoke" },
447 |     async ({ initTestBed, page, createSelectDriver }) => {
448 |       await initTestBed(`
449 |       <Select searchable>
450 |         <Option value="opt1" label="first"/>
451 |         <Option value="opt2" label="second"/>
452 |         <Option value="opt3" label="third"/>
453 |       </Select>
454 |     `);
455 |       const driver = await createSelectDriver();
456 |       await driver.toggleOptionsVisibility();
457 |       await driver.searchFor("econd");
458 |       const options = await page.getByRole("option").all();
459 |       expect(options).toHaveLength(1);
460 |       await expect(options[0]).toHaveText("second");
461 |     },
462 |   );
463 | });
464 | 
465 | // =============================================================================
466 | // MULTISELECT TESTS
467 | // =============================================================================
468 | 
469 | test.describe("multiSelect", () => {
470 |   test("initialValue='{[0]}' works", async ({ page, initTestBed }) => {
471 |     await initTestBed(`
472 |       <Fragment>
473 |         <Select id="mySelect" initialValue="{[0]}" multiSelect>
474 |           <Option value="{0}" label="Zero"/>
475 |           <Option value="{1}" label="One"/>
476 |           <Option value="{2}" label="Two"/>
477 |         </Select>
478 |         <Text testId="text">Selected value: {mySelect.value}</Text>
479 |       </Fragment>
480 |     `);
481 | 
482 |     await expect(page.getByTestId("text")).toHaveText("Selected value: 0");
483 |   });
484 | 
485 |   test("initialValue='{[0,1]}' works", { tag: "@smoke" }, async ({ page, initTestBed }) => {
486 |     await initTestBed(`
487 |       <Fragment>
488 |         <Select id="mySelect" initialValue="{[0,1]}" multiSelect>
489 |           <Option value="{0}" label="Zero"/>
490 |           <Option value="{1}" label="One"/>
491 |           <Option value="{2}" label="Two"/>
492 |         </Select>
493 |         <Text testId="text">Selected value: {mySelect.value}</Text>
494 |       </Fragment>
495 |     `);
496 | 
497 |     await expect(page.getByTestId("text")).toHaveText("Selected value: 0,1");
498 |   });
499 | 
500 |   test("select multiple items without closing listbox", async ({
501 |     page,
502 |     initTestBed,
503 |     createSelectDriver,
504 |   }) => {
505 |     const { testStateDriver } = await initTestBed(`
506 |       <Fragment>
507 |         <Select id="mySelect" multiSelect>
508 |           <Option value="{0}" label="Zero"/>
509 |           <Option value="{1}" label="One"/>
510 |           <Option value="{2}" label="Two"/>
511 |         </Select>
512 |         <Text testId="text">Selected value: {mySelect.value}</Text>
513 |       </Fragment>
514 |     `);
515 |     const selectDrv = await createSelectDriver("mySelect");
516 |     await selectDrv.toggleOptionsVisibility();
517 |     await selectDrv.selectMultipleLabels(["Zero", "One"]);
518 | 
519 |     /* problem is that the listbox closes after the 1st selection is made */
520 |     await expect(page.getByTestId("text")).toHaveText("Selected value: 0,1");
521 |   });
522 | 
523 |   test(
524 |     "clicking label brings up the options",
525 |     { tag: "@smoke" },
526 |     async ({ initTestBed, page, createSelectDriver }) => {
527 |       await initTestBed(`
528 |       <Select label="Choose an option" multiSelect>
529 |         <Option value="1" label="One"/>
530 |         <Option value="2" label="Two"/>
531 |       </Select>
532 |     `);
533 |       await page.getByLabel("Choose an option").click();
534 |       await expect(page.getByRole("option", { name: "One" })).toBeVisible();
535 |       await expect(page.getByRole("option", { name: "Two" })).toBeVisible();
536 |     },
537 |   );
538 | 
539 |   test("labelBreak prop defaults to false", async ({ initTestBed, page, createSelectDriver }) => {
540 |     await page.setViewportSize({ width: 300, height: 720 });
541 | 
542 |     await initTestBed(`
543 |       <Select
544 |         label="Dignissimos esse quasi esse cupiditate qui qui. Ut provident ad voluptatem tenetur sit consequuntur. Aliquam nisi fugit ut temporibus itaque ducimus rerum. Dolorem reprehenderit qui adipisci. Ullam harum atque ipsa."
545 |         multiSelect>
546 |         <Option value="1" label="One"/>
547 |         <Option value="2" label="Two"/>
548 |       </Select>
549 |     `);
550 |     const labelWidth = (await page.getByText("Dignissimos esse quasi").boundingBox()).width;
551 |     const select = page.getByRole("button").or(page.getByRole("combobox")).first();
552 |     const { width: selectWidth } = await select.boundingBox();
553 |     expect(labelWidth).toBe(selectWidth);
554 |   });
555 | 
556 |   test('labelPosition="start" is left in ltr language', async ({ initTestBed, page }) => {
557 |     await initTestBed(`
558 |       <Select multiSelect label="hi there" labelPosition="start" labelBreak="false">
559 |         <Option value="1" label="One"/>
560 |         <Option value="2" label="Two"/>
561 |       </Select>
562 |       `);
563 |     const { x: labelX } = await page.getByText("hi there").boundingBox();
564 |     const select = page.getByRole("button").or(page.getByRole("combobox")).first();
565 |     const { x: selectX } = await select.boundingBox();
566 |     expect(labelX).toBeLessThan(selectX);
567 |   });
568 | 
569 |   test('labelPosition="start" is right in rtl language', async ({ initTestBed, page }) => {
570 |     await initTestBed(`
571 |       <VStack direction="rtl">
572 |         <Select multiSelect label="hi there" labelPosition="start" labelBreak="false">
573 |           <Option value="1" label="One" />
574 |           <Option value="2" label="Two" />
575 |         </Select>
576 |       </VStack>
577 |     `);
578 |     const { x: labelX } = await page.getByText("hi there").boundingBox();
579 |     const select = page.getByRole("button").or(page.getByRole("combobox")).first();
580 |     const { x: selectX } = await select.boundingBox();
581 |     expect(labelX).toBeGreaterThan(selectX);
582 |   });
583 | 
584 |   test("multiSelect autoFocus brings the focus to component", async ({
585 |     initTestBed,
586 |     page,
587 |     createSelectDriver,
588 |   }) => {
589 |     await initTestBed(`
590 |       <Select multiSelect>
591 |         <Option value="1" label="One"/>
592 |         <Option value="2" label="Two"/>
593 |       </Select>
594 |       <Select testId="focused-select" multmultiSelect autoFocus>
595 |         <Option value="1" label="One"/>
596 |         <Option value="2" label="Two"/>
597 |       </Select>
598 |     `);
599 |     const driver = await createSelectDriver("focused-select");
600 | 
601 |     await expect(driver.component).toBeFocused();
602 |   });
603 | 
604 |   test("autoFocus brings the focus to component", async ({
605 |     initTestBed,
606 |     page,
607 |     createSelectDriver,
608 |   }) => {
609 |     await initTestBed(`
610 |       <Select initialValue="opt1" placeholder="Select..." multiSelect>
611 |           <property name="valueTemplate">
612 |               <HStack>
613 |               <Text>{$item.value}={$item.label}</Text>
614 |               <Button
615 |                   variant="ghost"
616 |                   icon="close"
617 |                   size="xs"
618 |                   testId="remove-item-btn"
619 |                   onClick="$itemContext.removeItem()"/>
620 |               </HStack>
621 |           </property>
622 |           <Option value="opt1" label="first"/>
623 |           <Option value="opt2" label="second"/>
624 |           <Option value="opt3" label="third"/>
625 |       </Select>
626 |     `);
627 |     const driver = await createSelectDriver();
628 |     await driver.toggleOptionsVisibility();
629 |     await driver.selectLabel("first");
630 | 
631 |     await expect(page.getByText("opt1=first", { exact: true })).toBeVisible();
632 |     await page.getByTestId("remove-item-btn").click();
633 |     await expect(page.getByText("opt1=first", { exact: true })).not.toBeVisible();
634 |   });
635 | });
636 | 
637 | // =============================================================================
638 | // SEARCHABLE MULTISELECT TESTS
639 | // =============================================================================
640 | 
641 | test.describe("searchable multiselect", { tag: "@smoke" }, () => {
642 |   test("searching for and selecting 2 items works", async ({
643 |     page,
644 |     initTestBed,
645 |     createSelectDriver,
646 |   }) => {
647 |     await initTestBed(`
648 |       <Fragment>
649 |         <Select id="mySelect" testId="mySelect" multiSelect searchable>
650 |           <Option value="{0}" label="Zero"/>
651 |           <Option value="{1}" label="One"/>
652 |           <Option value="{2}" label="Two"/>
653 |         </Select>
654 |         <Text testId="text">Selected value: {mySelect.value}</Text>
655 |       </Fragment>
656 |     `);
657 |     const driver = await createSelectDriver("mySelect");
658 |     await driver.toggleOptionsVisibility();
659 |     await driver.selectFirstLabelPostSearh("One");
660 |     await driver.selectFirstLabelPostSearh("Two");
661 | 
662 |     await expect(page.getByTestId("text")).toHaveText("Selected value: 1,2");
663 |   });
664 | });
665 | 
666 | // =============================================================================
667 | // EVENT HANDLING TESTS
668 | // =============================================================================
669 | 
670 | test.describe("Event Handling", () => {
671 |   test("gotFocus event fires on focus", async ({ initTestBed, page }) => {
672 |     const { testStateDriver } = await initTestBed(`
673 |       <Select onGotFocus="testState = 'focused'">
674 |         <Option value="1" label="One"/>
675 |         <Option value="2" label="Two"/>
676 |       </Select>
677 |     `);
678 |     const selectButton = page.getByRole("combobox");
679 |     await selectButton.focus();
680 |     await expect.poll(testStateDriver.testState).toBe("focused");
681 |   });
682 | 
683 |   test("gotFocus event fires on label click", async ({ initTestBed, page }) => {
684 |     const { testStateDriver } = await initTestBed(`
685 |       <Select label="Choose" onGotFocus="testState = 'focused'">
686 |         <Option value="1" label="One"/>
687 |         <Option value="2" label="Two"/>
688 |       </Select>
689 |     `);
690 |     await page.getByText("Choose").click();
691 |     await expect.poll(testStateDriver.testState).toBe("focused");
692 |   });
693 | 
694 |   test("lostFocus event fires on blur", async ({ initTestBed, page }) => {
695 |     const { testStateDriver } = await initTestBed(`
696 |       <Select onLostFocus="testState = 'blurred'">
697 |         <Option value="1" label="One"/>
698 |         <Option value="2" label="Two"/>
699 |       </Select>
700 |     `);
701 |     const selectButton = page.getByRole("combobox");
702 |     await selectButton.focus();
703 |     await selectButton.blur();
704 |     await expect.poll(testStateDriver.testState).toBe("blurred");
705 |   });
706 | });
707 | 
708 | // =============================================================================
709 | // FORM INTEGRATION TESTS
710 | // =============================================================================
711 | 
712 | //this is an upstream issue: https://github.com/radix-ui/primitives/issues/3135
713 | test("initialValue honored when used within Form", async ({ initTestBed, page }) => {
714 |   await initTestBed(`
715 |     <Form>
716 |       <Select id="mySelect" initialValue="opt3">
717 |         <Option value="opt1" label="first"/>
718 |         <Option value="opt2" label="second"/>
719 |         <Option value="opt3" label="third"/>
720 |       </Select>
721 |       <Text testId="text">Selected value: {mySelect.value}</Text>
722 |     </Form>`);
723 | 
724 |   await expect(page.getByTestId("text")).toHaveText("Selected value: opt3");
725 | });
726 | 
727 | // =============================================================================
728 | // VISUAL STATE TESTS
729 | // =============================================================================
730 | 
731 | test.describe("Visual State", () => {
732 |   test("input has correct width in px", async ({ page, initTestBed }) => {
733 |     await initTestBed(`<Select width="200px" testId="test"/>`, {});
734 | 
735 |     const input = page.getByTestId("test");
736 |     const { width } = await input.boundingBox();
737 |     expect(width).toBe(200);
738 |   });
739 | 
740 |   test("input with label has correct width in px", async ({ page, initTestBed }) => {
741 |     await initTestBed(`<Select width="200px" label="test" testId="test"/>`, {});
742 | 
743 |     const input = page.getByTestId("test");
744 |     const { width } = await input.boundingBox();
745 |     expect(width).toBe(200);
746 |   });
747 | 
748 |   test("input has correct width in %", async ({ page, initTestBed }) => {
749 |     await page.setViewportSize({ width: 400, height: 300 });
750 |     await initTestBed(`<Select width="50%" testId="test"/>`, {});
751 | 
752 |     const input = page.getByTestId("test");
753 |     const { width } = await input.boundingBox();
754 |     expect(width).toBe(200);
755 |   });
756 | 
757 |   test("input with label has correct width in %", async ({ page, initTestBed }) => {
758 |     await page.setViewportSize({ width: 400, height: 300 });
759 |     await initTestBed(`<Select width="50%" label="test" testId="test"/>`, {});
760 | 
761 |     const input = page.getByTestId("test");
762 |     const { width } = await input.boundingBox();
763 |     expect(width).toBe(200);
764 |   });
765 | });
766 | 
767 | // =============================================================================
768 | // Z-INDEX AND MODAL LAYERING TESTS
769 | // =============================================================================
770 | 
771 | test.describe("Z-Index and Modal Layering", () => {
772 |   test("Select dropdown in modal is visible and not covered by modal overlay", async ({
773 |     initTestBed,
774 |     page,
775 |     createSelectDriver,
776 |   }) => {
777 |     await initTestBed(`
778 |       <Fragment>
779 |         <Select testId="select">
780 |           <Option value="stuff1">option 1</Option>
781 |           <Option value="stuff2">option 2</Option>
782 |           <Button onClick="modal.open()">BLOW UP</Button>
783 |         </Select>
784 |         <ModalDialog id="modal" title="Example Dialog">
785 |           <Form data="{{ firstName: 'Billy', lastName: 'Bob' }}">
786 |             <FormItem bindTo="firstName" required="true" />
787 |             <FormItem bindTo="lastName" required="true" />
788 |             <FormItem
789 |               label="Field to Update"
790 |               type="select"
791 |               width="200px"
792 |               bindTo="fieldToUpdate"
793 |               required
794 |               initialValue="rate"
795 |               testId="modal-select"
796 |             >
797 |               <Option value="rate">Price</Option>
798 |               <Option value="description">Item Description</Option>
799 |               <Option value="account_id">Account</Option>
800 |             </FormItem>
801 |           </Form>
802 |         </ModalDialog>
803 |       </Fragment>
804 |     `);
805 | 
806 |     const selectDriver = await createSelectDriver("select");
807 |     await selectDriver.click();
808 | 
809 |     // Click button to open modal
810 |     const blowUpButton = page.getByText("BLOW UP");
811 |     await blowUpButton.click();
812 | 
813 |     // Wait for modal to be visible
814 |     await expect(page.getByRole("dialog", { name: "Example Dialog" })).toBeVisible();
815 | 
816 |     // Open the select in the modal
817 |     const modalSelectDriver = await createSelectDriver("modal-select");
818 |     await modalSelectDriver.click();
819 | 
820 |     // Check that all options are visible
821 |     await expect(page.getByRole("option", { name: "Price" })).toBeVisible();
822 |     await expect(page.getByRole("option", { name: "Item Description" })).toBeVisible();
823 |     await expect(page.getByRole("option", { name: "Account" })).toBeVisible();
824 |   });
825 | });
826 | 
827 | // =============================================================================
828 | // THEME VARIABLE TESTS
829 | // =============================================================================
830 | 
831 | test.describe("Theme Variables", () => {
832 |   [
833 |     { value: "--default", prop: "" },
834 |     { value: "--warning", prop: 'validationStatus="warning"' },
835 |     { value: "--error", prop: 'validationStatus="error"' },
836 |     { value: "--success", prop: 'validationStatus="valid"' },
837 |   ].forEach((variant) => {
838 |     test(`applies correct borderRadius ${variant.value}`, async ({ initTestBed, page }) => {
839 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
840 |         testThemeVars: { [`borderRadius-Select${variant.value}`]: "12px" },
841 |       });
842 |       await expect(page.getByTestId("test")).toHaveCSS("border-radius", "12px");
843 |     });
844 | 
845 |     test(`applies correct borderColor ${variant.value}`, async ({ initTestBed, page }) => {
846 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
847 |         testThemeVars: { [`borderColor-Select${variant.value}`]: "rgb(255, 0, 0)" },
848 |       });
849 |       await expect(page.getByTestId("test")).toHaveCSS("border-color", "rgb(255, 0, 0)");
850 |     });
851 | 
852 |     test(`applies correct borderWidth ${variant.value}`, async ({ initTestBed, page }) => {
853 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
854 |         testThemeVars: { [`borderWidth-Select${variant.value}`]: "1px" },
855 |       });
856 |       await expect(page.getByTestId("test")).toHaveCSS("border-width", "1px");
857 |     });
858 | 
859 |     test(`applies correct borderStyle ${variant.value}`, async ({ initTestBed, page }) => {
860 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
861 |         testThemeVars: { [`borderStyle-Select${variant.value}`]: "dashed" },
862 |       });
863 |       await expect(page.getByTestId("test")).toHaveCSS("border-style", "dashed");
864 |     });
865 | 
866 |     test(`applies correct fontSize ${variant.value}`, async ({ initTestBed, page }) => {
867 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
868 |         testThemeVars: { [`fontSize-Select${variant.value}`]: "14px" },
869 |       });
870 |       await expect(page.getByTestId("test")).toHaveCSS("font-size", "14px");
871 |     });
872 | 
873 |     test(`applies correct backgroundColor ${variant.value}`, async ({ initTestBed, page }) => {
874 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
875 |         testThemeVars: { [`backgroundColor-Select${variant.value}`]: "rgb(240, 240, 240)" },
876 |       });
877 |       await expect(page.getByTestId("test")).toHaveCSS("background-color", "rgb(240, 240, 240)");
878 |     });
879 | 
880 |     test(`applies correct boxShadow ${variant.value}`, async ({ initTestBed, page }) => {
881 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
882 |         testThemeVars: {
883 |           [`boxShadow-Select${variant.value}`]: "0 2px 8px rgba(0, 0, 0, 0.1)",
884 |         },
885 |       });
886 |       await expect(page.getByTestId("test")).toHaveCSS(
887 |         "box-shadow",
888 |         "rgba(0, 0, 0, 0.1) 0px 2px 8px 0px",
889 |       );
890 |     });
891 | 
892 |     test(`applies correct textColor ${variant.value}`, async ({ initTestBed, page }) => {
893 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
894 |         testThemeVars: { [`textColor-Select${variant.value}`]: "rgb(0, 0, 0)" },
895 |       });
896 |       await expect(page.getByTestId("test")).toHaveCSS("color", "rgb(0, 0, 0)");
897 |     });
898 | 
899 |     test(`applies correct borderColor on hover ${variant.value}`, async ({ initTestBed, page }) => {
900 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
901 |         testThemeVars: { [`borderColor-Select${variant.value}--hover`]: "rgb(0, 0, 0)" },
902 |       });
903 |       await page.getByTestId("test").hover();
904 |       await expect(page.getByTestId("test")).toHaveCSS("border-color", "rgb(0, 0, 0)");
905 |     });
906 | 
907 |     test(`applies correct backgroundColor on hover ${variant.value}`, async ({
908 |       initTestBed,
909 |       page,
910 |     }) => {
911 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
912 |         testThemeVars: { [`backgroundColor-Select${variant.value}--hover`]: "rgb(0, 0, 0)" },
913 |       });
914 |       await page.getByTestId("test").hover();
915 |       await expect(page.getByTestId("test")).toHaveCSS("background-color", "rgb(0, 0, 0)");
916 |     });
917 | 
918 |     test(`applies correct boxShadow on hover ${variant.value}`, async ({ initTestBed, page }) => {
919 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
920 |         testThemeVars: {
921 |           [`boxShadow-Select${variant.value}--hover`]: "0 2px 8px rgba(0, 0, 0, 0.1)",
922 |         },
923 |       });
924 |       await page.getByTestId("test").hover();
925 |       await expect(page.getByTestId("test")).toHaveCSS(
926 |         "box-shadow",
927 |         "rgba(0, 0, 0, 0.1) 0px 2px 8px 0px",
928 |       );
929 |     });
930 | 
931 |     test(`applies correct textColor on hover ${variant.value}`, async ({ initTestBed, page }) => {
932 |       await initTestBed(`<Select testId="test" ${variant.prop} />`, {
933 |         testThemeVars: { [`textColor-Select${variant.value}--hover`]: "rgb(0, 0, 0)" },
934 |       });
935 |       await page.getByTestId("test").hover();
936 |       await expect(page.getByTestId("test")).toHaveCSS("color", "rgb(0, 0, 0)");
937 |     });
938 |   });
939 | });
940 | 
```

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

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