#
tokens: 49423/50000 9/1632 files (page 41/141)
lines: off (toggle) GitHub
raw markdown copy
This is page 41 of 141. Use http://codebase.md/xmlui-org/xmlui/mockApiDef.js?lines=false&page={x} to view the full context.

# Directory Structure

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

# Files

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

```markdown
# Column [#column]

`Column` defines the structure and behavior of individual table columns within a [`Table`](/components/Table) component. Each Column controls data binding, header display, sorting capabilities, sizing, and can contain any XMLUI components for rich cell content.

**Key features:**
- **Data binding**: Use `bindTo` to automatically display object properties
- **Component embedding**: Place any component inside `Column`: `Button`, `Text`, `Icon`, etc.
- **Interactive behavior**: Enable/disable sorting and column resizing
- **Layout control**: Set width using pixels, star sizing (`*`, `2*`), or proportional values
- **Column pinning**: Pin columns to left or right edges for sticky behavior

**Context variables available during execution:**

- `$cell`: The specific cell value for this column
- `$colIndex`: Zero-based column index
- `$item`: The complete data row object being rendered
- `$itemIndex`: Zero-based row index
- `$row`: The complete data row object being rendered (the same as `$item`).
- `$rowIndex`: Zero-based row index (the same as `$itemIndex`).

## Properties [#properties]

### `bindTo` [#bindto]

Indicates the name of the current row item's property, the value of which to lay out in the column. If this property is not defined, the column is not sortable.

```xmlui copy {3}
<App>
  <Table data='{[...]}'>
    <Column bindTo="name" />
  </Table>
</App>
```

```xmlui-pg name="Example: bindTo"
<App>
  <Table data='{
    [
      {
        id: 0,
        name: "Apples",
        quantity: 5,
        unit: "pieces",
        category: "fruits",
        key: 5,
      },
      {
        id: 1,
        name: "Bananas",
        quantity: 6,
        unit: "pieces",
        category: "fruits",
        key: 4,
      },
      {
        id: 2,
        name: "Carrots",
        quantity: 100,
        unit: "grams",
        category: "vegetables",
        key: 3,
      },
      {
        id: 3,
        name: "Spinach",
        quantity: 1,
        unit: "bunch",
        category: "vegetables",
        key: 2,
      },
      {
        id: 4,
        name: "Milk",
        quantity: 10,
        unit: "liter",
        category: "dairy",
        key: 1,
      },
      {
        id: 5,
        name: "Cheese",
        quantity: 200,
        unit: "grams",
        category: "dairy",
        key: 0,
      },
    ]}'>
    <Column bindTo="name" />
  </Table>
</App>
```

### `canResize` (default: true) [#canresize-default-true]

This property indicates whether the user can resize the column. If set to `true`, the column can be resized by dragging the column border. If set to `false`, the column cannot be resized. Double-clicking the column border resets to the original size.

### `canSort` (default: true) [#cansort-default-true]

This property sets whether the user can sort by a column by clicking on its header (`true`) or not (`false`). If the `bindTo` property is not defined, the column is not sortable.

Click on either the `Name` or the `Quantity` column headers to order the data by that attribute.

```xmlui copy /canSort/
<App>
  <Table data='{[...]}'>
    <Column canSort="true" bindTo="name" />
    <Column canSort="true" bindTo="quantity" />
    <Column canSort="false" bindTo="unit" />
  </Table>
</App>
```

```xmlui-pg name="Example: canSort"
<App>
  <Table data='{
  [
    {
      id: 0,
      name: "Apples",
      quantity: 5,
      unit: "pieces",
      category: "fruits",
      key: 5,
    },
    {
      id: 1,
      name: "Bananas",
      quantity: 6,
      unit: "pieces",
      category: "fruits",
      key: 4,
    },
    {
      id: 2,
      name: "Carrots",
      quantity: 100,
      unit: "grams",
      category: "vegetables",
      key: 3,
    },
    {
      id: 3,
      name: "Spinach",
      quantity: 1,
      unit: "bunch",
      category: "vegetables",
      key: 2,
    },
    {
      id: 4,
      name: "Milk",
      quantity: 10,
      unit: "liter",
      category: "dairy",
      key: 1,
    },
    {
      id: 5,
      name: "Cheese",
      quantity: 200,
      unit: "grams",
      category: "dairy",
      key: 0,
    },
  ]}'>
    <Column canSort="true" bindTo="name" />
    <Column canSort="true" bindTo="quantity" />
    <Column canSort="false" bindTo="unit" />
  </Table>
</App>
```

### `header` [#header]

This property defines a label for a particular column. If not set, the `bindTo` property value is used for the label.

```xmlui copy {3-4}
<App>
  <Table data='{[...]}'>
    <Column header="Food Name" bindTo="name" />
    <Column header="Food Quantity" bindTo="quantity" />
    <Column bindTo="unit" />
  </Table>
</App>
```

```xmlui-pg name="Example: header"
<App>
  <Table data='{
  [
    {
      id: 0,
      name: "Apples",
      quantity: 5,
      unit: "pieces",
      category: "fruits",
      key: 5,
    },
    {
      id: 1,
      name: "Bananas",
      quantity: 6,
      unit: "pieces",
      category: "fruits",
      key: 4,
    },
    {
      id: 2,
      name: "Carrots",
      quantity: 100,
      unit: "grams",
      category: "vegetables",
      key: 3,
    },
    {
      id: 3,
      name: "Spinach",
      quantity: 1,
      unit: "bunch",
      category: "vegetables",
      key: 2,
    },
    {
      id: 4,
      name: "Milk",
      quantity: 10,
      unit: "liter",
      category: "dairy",
      key: 1,
    },
    {
      id: 5,
      name: "Cheese",
      quantity: 200,
      unit: "grams",
      category: "dairy",
      key: 0,
    },
  ]}'>
    <Column header="Food Name" bindTo="name" />
    <Column header="Food Quantity" bindTo="quantity" />
    <Column bindTo="unit" />
  </Table>
</App>
```

### `maxWidth` [#maxwidth]

Indicates the maximum width a particular column can have. Same rules apply as with [width](#width).

### `minWidth` [#minwidth]

Indicates the minimum width a particular column can have. Same rules apply as with [width](#width).

### `pinTo` [#pinto]

This property allows the column to be pinned to the `left` (left-to-right writing style) or `right` (left-to-right writing style) edge of the table. If the writing style is right-to-left, the locations are switched. If this property is not set, the column is not pinned to any edge.

Available values: `left`, `right`

>[!WARNING]
> By default, the background color of table rows is transparent. When using the `pinTo` property, you should set the background to an explicit (non-transparent) color; otherwise, the scrolled cells will be visible under the pinned columns.

```xmlui copy /pinTo="left"/ /pinTo="right"/
<App>
  <Theme backgroundColor-row-Table="$color-surface-0">
    <Table data='{[...]}' height="100%">
      <Column bindTo="id" width="50px" pinTo="left" />
      <Column bindTo="name" width="500px" />
      <Column bindTo="quantity" width="300px" />
      <Column bindTo="unit" width="300px"/>
      <Column bindTo="category" width="100px" pinTo="right"/>
    </Table>
  </Theme>
</App>
```
Scroll the table contents horizontally to see how the pinned columns are displayed.

```xmlui-pg name="Example: pinTo"
<App>
  <Theme backgroundColor-row-Table="$color-surface-0">
  <Table data='{
  [
    {
      id: 0,
      name: "Apples",
      quantity: 5,
      unit: "pieces",
      category: "fruits",
      key: 5,
    },
    {
      id: 1,
      name: "Bananas",
      quantity: 6,
      unit: "pieces",
      category: "fruits",
      key: 4,
    },
    {
      id: 2,
      name: "Carrots",
      quantity: 100,
      unit: "grams",
      category: "vegetables",
      key: 3,
    },
    {
      id: 3,
      name: "Spinach",
      quantity: 1,
      unit: "bunch",
      category: "vegetables",
      key: 2,
    },
    {
      id: 4,
      name: "Milk",
      quantity: 10,
      unit: "liter",
      category: "dairy",
      key: 1,
    },
    {
      id: 5,
      name: "Cheese",
      quantity: 200,
      unit: "grams",
      category: "dairy",
      key: 0,
    },
  ]}'
      height="100%">
    <Column bindTo="id" width="50px" pinTo="left" />
    <Column bindTo="name" width="500px" />
    <Column bindTo="quantity" width="300px" />
    <Column bindTo="unit" width="300px"/>
    <Column bindTo="category" width="100px" pinTo="right"/>
  </Table>
  </Theme>
</App>
```

### `width` [#width]

This property defines the width of the column. You can use a numeric value, a pixel value (such as `100px`), or a star size value (such as `*`, `2*`, etc.). You will get an error if you use any other unit (or value).If not defined, the component will use a width according to the column values and the available space.

The following example sets the second column to an absolute size (size pixels), while the first and third columns have star sizes:

```xmlui copy {4}
<App>
  <Table data='{[...]}'>
    <Column bindTo="name" canResize="true" width="3*" />
    <Column bindTo="quantity" width="100px" minWidth="50px" maxWidth="500px" />
    <Column bindTo="unit" width="*" />
  </Table>
</App>
```

Check what happens when you resize table columns:

```xmlui-pg name="Example: width"
<App>
  <Table data='{
  [
    {
      id: 0,
      name: "Apples",
      quantity: 5,
      unit: "pieces",
      category: "fruits",
      key: 5,
    },
    {
      id: 1,
      name: "Bananas",
      quantity: 6,
      unit: "pieces",
      category: "fruits",
      key: 4,
    },
    {
      id: 2,
      name: "Carrots",
      quantity: 100,
      unit: "grams",
      category: "vegetables",
      key: 3,
    },
    {
      id: 3,
      name: "Spinach",
      quantity: 1,
      unit: "bunch",
      category: "vegetables",
      key: 2,
    },
    {
      id: 4,
      name: "Milk",
      quantity: 10,
      unit: "liter",
      category: "dairy",
      key: 1,
    },
    {
      id: 5,
      name: "Cheese",
      quantity: 200,
      unit: "grams",
      category: "dairy",
      key: 0,
    },
  ]}'>
    <Column bindTo="name" canResize="true" width="3*" />
    <Column bindTo="quantity" width="100px" minWidth="50px" maxWidth="500px" />
    <Column bindTo="unit" width="*" />
  </Table>
</App>
```

## Events [#events]

This component does not have any events.

## Exposed Methods [#exposed-methods]

This component does not expose any methods.

## Styling [#styling]

Styling is done via the [`Table` component](/components/Table).

```

--------------------------------------------------------------------------------
/xmlui/src/components/CodeBlock/highlight-code.ts:
--------------------------------------------------------------------------------

```typescript
import { type ReactNode, isValidElement } from "react";
import { encodeToBase64, decodeFromBase64 } from "../../components-core/utils/base64-utils";

const highlightRowsClass = "codeBlockHighlightRow";
const highlightSubstringsClass = "codeBlockHighlightString";
const highlightSubstringsEmphasisClass = "codeBlockHighlightStringEmphasis";

// Re-export for backward compatibility
export { encodeToBase64, decodeFromBase64 };

/**
 * This function handles two things:
 * 1. The extraction of meta information from code blocks and exposing them as data-meta attributes
 * 2. The highlighting of code blocks providing the highlighter function with meta information
 * @param node The React node containing the code block
 * @param codeHighlighter The highlighter object containing the highlight function and the available languages
 * @returns CSS class names for the codefence and the HTML string with highlighted code tokens
 */
export function parseMetaAndHighlightCode(
  node: ReactNode,
  codeHighlighter: CodeHighlighter,
  themeTone?: string,
): HighlighterResults | null {
  // parse
  const rawCodeStr = getCodeStrFromNode(node);
  const rawMeta = getCodeMetaFromNode(node, CodeHighlighterMetaKeysData);
  // map
  const codeStr = transformCodeLines(rawCodeStr);
  const meta = extractMetaFromChildren(rawMeta, codeStr);

  const { language, ...restMeta } = meta;
  if (language && codeHighlighter.availableLangs.includes(language)) {
    // NOTE: Keep in mind, at this point, we are working with the markdown text
    try{
      const htmlCodeStr = codeHighlighter.highlight(codeStr, language, restMeta, themeTone);
      const match = htmlCodeStr.match(/<pre\b[^>]*\bclass\s*=\s*["']([^"']*)["'][^>]*>/i);
      const classNames = match ? match[1] : null;

      // NOTE: Why remove the <pre>?
      // Shiki appends <pre> tags to the highlighted code,
      // so we would get <pre><pre><code>...</code></pre></pre>
      let cleanedHtmlStr = htmlCodeStr.replace(/<pre\b[^>]*>|<\/pre>/gi, "");

      const numberedRowClass = meta.rowNumbers ? "numbered" : "";
      cleanedHtmlStr = cleanedHtmlStr.replaceAll(
        /<span class="line"/g,
        `<span class="line ${numberedRowClass}"`,
      );

      return { classNames, cleanedHtmlStr, codeStr, meta };
    } catch (e){
      // this could happen in safari after the optimized build (some regexp issues, could be remix/vite/shiki related, TBD)
      return {
        meta,
        codeStr,
        cleanedHtmlStr: codeStr,
        classNames: null
      };
    }

  }
  return null;
}

function getCodeStrFromNode(node: ReactNode) {
  if (typeof node === "string") {
    return node;
  }

  if (isValidElement(node) && node.props && node.props.children) {
    if (Array.isArray(node.props.children)) {
      return node.props.children.map(getCodeStrFromNode).join("");
    }
    return getCodeStrFromNode(node.props.children);
  }
  return "";
}

function getCodeMetaFromNode(node: ReactNode, keys: string[]) {
  if (!node) return {};
  if (typeof node === "string") return {};
  if (typeof node === "number") return {};
  if (typeof node === "boolean") return {};
  if (Array.isArray(node)) return {};

  if (
    isValidElement(node) &&
    node.props &&
    node.props.children &&
    typeof node.props.children === "string"
  ) {
    return Object.entries(node.props)
      .filter(([key, _]) => keys.includes(key))
      .reduce(
        (acc, [key, value]) => {
          acc[key] = value;
          return acc;
        },
        {} as Record<string, any>,
      );
  }
  return {};
}

export function transformCodeLines(node: string) {
  const splitNode = node.split(/\r?\n/);
  for (let i = 0; i < splitNode.length; i++) {
    // Backslash before a codefence indicates an escaped codefence
    // -> don't render the backslash
    if (splitNode[i].startsWith("\\```")) {
      splitNode[i] = splitNode[i].replace("\\```", "```");
    }
  }

  // Remove empty lines from start and end
  let startTrimIdx = 0;
  let endTrimIdx = splitNode.length - 1;
  for (let i = 0; i < splitNode.length; i++) {
    if (splitNode[i].trim() !== "") {
      startTrimIdx = i;
      break;
    }
  }
  for (let i = splitNode.length - 1; i >= 0; i--) {
    if (splitNode[i].trim() !== "") {
      endTrimIdx = i;
      break;
    }
  }

  splitNode.splice(0, startTrimIdx);
  splitNode.splice(endTrimIdx + 1);
  return splitNode.join("\n");
}

export function extractMetaFromChildren(
  meta: Record<string, any>,
  code: string = "",
): CodeHighlighterMeta {
  if (!meta) return {};

  return {
    // NOTE: Row numbers are disabled for now, because applying the highlight class removes the "numbered" class
    /* [CodeHighlighterMetaKeys.rowNumbers.prop]: parseBoolean(
      meta[CodeHighlighterMetaKeys.rowNumbers.data],
    ), */
    [CodeHighlighterMetaKeys.language.prop]: meta[CodeHighlighterMetaKeys.language.data],
    [CodeHighlighterMetaKeys.copy.prop]: parseBoolean(meta[CodeHighlighterMetaKeys.copy.data]),
    [CodeHighlighterMetaKeys.filename.prop]: meta[CodeHighlighterMetaKeys.filename.data],
    [CodeHighlighterMetaKeys.highlightRows.prop]: parseRowHighlights(
      code,
      meta[CodeHighlighterMetaKeys.highlightRows.data],
    ),
    [CodeHighlighterMetaKeys.highlightSubstrings.prop]: parseSubstringHighlights(
      code,
      meta[CodeHighlighterMetaKeys.highlightSubstrings.data],
    ),
    [CodeHighlighterMetaKeys.highlightSubstringsEmphasized.prop]: parseSubstringHighlights(
      code,
      meta[CodeHighlighterMetaKeys.highlightSubstringsEmphasized.data],
      true,
    ),
  };
}

function parseBoolean(str?: string) {
  if (str === "true") return true;
  if (str === "false") return false;
  return false;
}

function parseRowHighlights(code: string, str?: string): DecorationItem[] {
  if (!str) return [];
  if (str === "") return [];
  const codeLines = code.split("\n");
  return str
    .split(",")
    .map((item) => {
      item = item.trim();
      const split = item.split("-");
      let start = -1;
      let end = -1;

      if (split.length === 0) return { start, end, properties: { class: highlightRowsClass } };
      if (split.length > 2) return { start, end, properties: { class: highlightRowsClass } };
      if (split[0] === "") return { start, end, properties: { class: highlightRowsClass } };
      if (split[1] === "") return { start, end, properties: { class: highlightRowsClass } };
      start = 0;
      end = 0;

      // Start Index
      const startIdx = validate(parse(split[0]));
      start = getLineLengthIndex(startIdx);

      // End Index
      const endIdx = split.length === 1 ? startIdx : validate(parse(split[1]));
      let endLineLength = 0;
      if (endIdx >= 0 && codeLines[endIdx] !== undefined) {
        endLineLength = codeLines[endIdx].length;
      }
      end = getLineLengthIndex(endIdx) + endLineLength;

      return { start, end, properties: { class: highlightRowsClass } };
    })
    .filter((item) => {
      if (item.start <= -1 || item.end <= -1) return false;
      if (item.start > code.length || item.end > code.length) return false;
      return true;
    });

  function parse(value: string): number {
    const parsed = parseInt(value, 10);
    if (Number.isNaN(parsed)) return -1;
    return parsed;
  }

  function validate(parsed: number): number {
    // correct for 0-indexed array
    parsed -= 1;
    // check bounds
    if (parsed < 0 || parsed >= codeLines.length) return -1;
    return parsed;
  }

  function getLineLengthIndex(lineNumber: number) {
    if (lineNumber < 0) return -1;
    if (lineNumber === 0) return 0;

    let count = 0;
    let index = 0;
    while (count < lineNumber && index !== -1) {
      index = code.indexOf('\n', index);
      if (index !== -1) {
        index++; // Move past the '\n'
        count++;
      }
    }
    return (index !== -1) ? index : -1;
  }
}

function parseSubstringHighlights(
  code: string,
  str?: string,
  emphasized = false,
): DecorationItem[] {
  if (!str) return [];
  if (!code) return [];
  return str
    .split(" ")
    .map((item) => decodeFromBase64(item))
    .filter((item) => item.trim() !== "")
    .reduce((acc, item) => acc.concat(findAllNonOverlappingSubstrings(code, item)), []);

  function findAllNonOverlappingSubstrings(str: string, code: string) {
    const result: DecorationItem[] = [];
    let startIndex = 0;
    const searchLength = code.length;

    while (startIndex <= str.length - searchLength) {
      const index = str.indexOf(code, startIndex);
      if (index === -1) break;

      result.push({
        start: index,
        end: index + searchLength,
        properties: {
          class: emphasized ? highlightSubstringsEmphasisClass : highlightSubstringsClass,
        },
      });
      startIndex = index + searchLength; // Jump past this match
    }

    return result;
  }
}

export type CodeHighlighter = {
  // Returns html in string!
  highlight: (
    code: string,
    language: string,
    meta?: CodeHighlighterMeta,
    themeTone?: string,
  ) => string;
  availableLangs: string[];
};

export function isCodeHighlighter(obj: any): obj is CodeHighlighter {
  return obj && obj.highlight && typeof obj.highlight === "function" && obj.availableLangs;
}

type HighlighterResults = {
  classNames: string | null;
  cleanedHtmlStr: string;
  codeStr: string;
  meta: CodeHighlighterMeta;
};

export type CodeHighlighterMeta = {
  language?: string;
  copy?: boolean;
  filename?: string;
  rowNumbers?: boolean;
  highlightRows?: DecorationItem[];
  highlightSubstrings?: DecorationItem[];
};

type DecorationItem = {
  start: number;
  end: number;
  properties: { class?: string; style?: string };
};

export const CodeHighlighterMetaKeys = {
  language: { data: "data-language", prop: "language" },
  copy: { data: "data-copy", prop: "copy" },
  filename: { data: "data-filename", prop: "filename" },
  rowNumbers: { data: "data-row-numbers", prop: "rowNumbers" },
  highlightRows: { data: "data-highlight-rows", prop: "highlightRows" },
  highlightSubstrings: { data: "data-highlight-substrings", prop: "highlightSubstrings" },
  highlightSubstringsEmphasized: {
    data: "data-highlight-substrings-emp",
    prop: "highlightSubstringsEmphasized",
  },
};
export const CodeHighlighterMetaKeysData = Object.values(CodeHighlighterMetaKeys).map(
  (item) => item.data,
);

```

--------------------------------------------------------------------------------
/xmlui/src/components-core/ApiBoundComponent.tsx:
--------------------------------------------------------------------------------

```typescript
import type { MutableRefObject } from "react";
import React, { useMemo } from "react";

import type { ComponentDef, ParentRenderContext } from "../abstractions/ComponentDefs";
import type { LayoutContext, RenderChildFn } from "../abstractions/RendererDefs";
import { parseAttributeValue } from "./script-runner/AttributeValueParser";

type ApiBoundComponentProps = {
  uid: symbol;
  node: ComponentDef;
  apiBoundProps: Array<string>;
  apiBoundEvents: Array<string>;
  renderChild: RenderChildFn;
  layoutContextRef?: MutableRefObject<LayoutContext | undefined>;
  parentRendererContext?: ParentRenderContext;
};

export function ApiBoundComponent({
  uid,
  node,
  apiBoundProps,
  apiBoundEvents,
  renderChild,
  layoutContextRef,
  parentRendererContext,
}: ApiBoundComponentProps) {
  const wrappedWithAdapter = useMemo(() => {
    function generateloaderUid(key: string) {
      return `${node.uid}_data_${key}`;
    }

    // Generates a string representation of an event handler function that calls 
    // the appropriate action. This function is used recursively for nested actions.
    function generateEventHandler(actionComponent: any): string {
      const { type } = actionComponent;

      // Prepares an event handler, which can be several types of data
      // (string for inline JS functions, parsed objects, or nested action components)
      const prepareEvent = (eventData: any) => {
        if (!eventData) {
          return "undefined";
        }
        if (typeof eventData === "string") {
          return `"${eventData}"`;
        }
        if (typeof eventData.type === "string") {
          return generateEventHandler(eventData);
        }
        return JSON.stringify(eventData);
      };

      // --- Prepare event handlers
      const { success, error, progress, beforeRequest } = actionComponent.events || {};
      switch (type) {
        case "FileUpload": {
          const {
            invalidates,
            asForm,
            formParams,
            queryParams,
            rawBody,
            body,
            url,
            headers,
            method,
            file,
          } = actionComponent.props;
          return `(eventArgs) => {
            return Actions.upload({
              asForm: ${JSON.stringify(asForm)}, 
              formParams: ${JSON.stringify(formParams)}, 
              queryParams: ${JSON.stringify(queryParams)}, 
              rawBody: ${JSON.stringify(rawBody)}, 
              body: ${JSON.stringify(body)}, 
              url: ${JSON.stringify(url)}, 
              headers: ${JSON.stringify(headers)}, 
              method: ${JSON.stringify(method)}, 
              file: ${JSON.stringify(file)}, 
              params: { '$param': eventArgs }, 
              onError: ${prepareEvent(error)}, 
              onSuccess: ${prepareEvent(success)}, 
              onProgress: eventArgs.onProgress, 
              invalidates: ${
                invalidates === undefined ? undefined : JSON.stringify(invalidates)
              }  }, { resolveBindingExpressions: true });
          }`;
        }
        case "FileDownload": {
          const { url, queryParams, rawBody, body, headers, method, fileName } =
            actionComponent.props;
          return `(eventArgs) => {
            return Actions.download({
              queryParams: ${JSON.stringify(queryParams)}, 
              rawBody: ${JSON.stringify(rawBody)}, 
              body: ${JSON.stringify(body)}, 
              url: ${JSON.stringify(url)}, 
              headers: ${JSON.stringify(headers)}, 
              method: ${JSON.stringify(method)}, 
              fileName: ${JSON.stringify(fileName)}, 
              params: { '$param': eventArgs },
            }, { resolveBindingExpressions: true });
          }`;
        }
        case "APICall": {
          const { when, uid } = actionComponent;

          const {
            confirmTitle,
            confirmMessage,
            confirmButtonLabel,
            inProgressNotificationMessage,
            completedNotificationMessage,
            errorNotificationMessage,
            invalidates,
            updates,
            optimisticValue,
            getOptimisticValue,
            headers,
            payloadType,
            method,
            url,
            queryParams,
            rawBody,
            body,
          } = actionComponent.props;

          return `(eventArgs, options) => {
            return Actions.callApi({
              uid: ${JSON.stringify(uid)},
              headers: ${JSON.stringify(headers)}, 
              method: ${JSON.stringify(method)}, 
              url: ${JSON.stringify(url)}, 
              queryParams: ${JSON.stringify(queryParams)}, 
              rawBody: ${JSON.stringify(rawBody)}, 
              body: ${JSON.stringify(body)} || (options?.passAsDefaultBody ? eventArgs : undefined), 
              confirmTitle: ${JSON.stringify(confirmTitle)}, 
              confirmMessage: ${JSON.stringify(confirmMessage)}, 
              confirmButtonLabel: ${JSON.stringify(confirmButtonLabel)}, 
              inProgressNotificationMessage: ${JSON.stringify(inProgressNotificationMessage)}, 
              completedNotificationMessage: ${JSON.stringify(completedNotificationMessage)}, 
              errorNotificationMessage: ${JSON.stringify(errorNotificationMessage)}, 
              params: { '$param': eventArgs }, 
              onError: ${prepareEvent(error)}, 
              onProgress: ${prepareEvent(progress)}, 
              onBeforeRequest: ${prepareEvent(beforeRequest)}, 
              onSuccess: ${prepareEvent(success)}, 
              updates: ${JSON.stringify(updates)}, 
              optimisticValue: ${JSON.stringify(optimisticValue)}, 
              payloadType: ${JSON.stringify(payloadType)}, 
              getOptimisticValue: ${JSON.stringify(getOptimisticValue)}, 
              invalidates: ${invalidates === undefined ? undefined : JSON.stringify(invalidates)}, 
              when: ${when === undefined ? undefined : JSON.stringify(when)} }, { resolveBindingExpressions: true });
          }`;
        }
        default: {
          throw new Error("Unknown event handler component type: ", type);
        }
      }
    }

    const loaders: Array<ComponentDef> = [...(node.loaders || [])];
    const events = { ...(node.events || {}) } as any;
    const props = { ...(node.props || {}) } as any;
    const vars = { ...(node.vars || {}) };
    const api = { ...(node.api || {}) };

    apiBoundEvents.forEach((key) => {
      const actionComponent = node.events![key];
      events[key] = generateEventHandler(actionComponent);
    });

    apiBoundProps.forEach((key) => {
      const isDatasourceRef = node.props![key]?.type === "DataSourceRef";
      const loaderUid = node.props![key].uid || generateloaderUid(key);
      const operation = node.props![key].props || node.props![key];
      const loaderEvents: Record<string, any> = {};
      Object.entries(node.events || {}).forEach(([eventKey, value]) => {
        if (eventKey.startsWith(key)) {
          const capitalizedEventName = eventKey.substring(key.length);
          const eventName =
            capitalizedEventName.charAt(0).toLowerCase() + capitalizedEventName.slice(1);
          loaderEvents[eventName] = value;
        }
      });
      if (key === "data") {
        props.__DATA_RESOLVED = true;
      }
      if (!isDatasourceRef) {
        loaders.push({
          type: "DataLoader",
          uid: loaderUid,
          props: operation,
          events: loaderEvents,
        });
        api[`fetch_${key}`] = `() => { ${loaderUid}.refetch(); }`;
        api[`update_${key}`] = `(updaterFn) => { ${loaderUid}.update(updaterFn); }`;
        api[`addItem_${key}`] = `(element, index) => {  ${loaderUid}.addItem(element, index); }`;
        api[`getItems_${key}`] = `() => { return ${loaderUid}.getItems(); }`;
        api[`deleteItem_${key}`] = `(element) => { ${loaderUid}.deleteItem(element); }`;
        if (key === "data") {
          props._data_url = operation.url;
        }
      }
      //illesg really experimental
      let prefetchKey = null;
      const { segments } = parseAttributeValue(operation.url?.trim());
      if (segments?.length === 1) {
        if (segments[0].literal) {
          prefetchKey = `"${segments[0].literal}"`;
        } else if (segments[0].expr) {
          // we remove the first and last characters, which are the curly braces
          prefetchKey = operation.url?.trim().substring(1, operation.url.length - 1);
        }
      }
      if (prefetchKey === null) {
        props[key] = `{ ${loaderUid}.value }`;
      } else {
        props[key] =
          `{ ${loaderUid}.value || ( appGlobals.prefetchedContent[${prefetchKey}] || appGlobals.prefetchedContent['/' + ${prefetchKey}] ) }`;
      }
      props.loading = `{ ${loaderUid}.inProgress === undefined ? true : ${loaderUid}.inProgress}`;
      props.pageInfo = `{${loaderUid}.pageInfo}`;
      events.requestFetchPrevPage = `${loaderUid}.fetchPrevPage()`;
      events.requestFetchNextPage = `${loaderUid}.fetchNextPage()`;
      // TODO if the user provides a requestRefetch handler, we should call it
      //  and then call the loader's refetch method if it returns !false;
      //  requestRefetch could receive parameters to select which apibound props to refetch
      events.requestRefetch = `()=> ${loaderUid}.refetch();`;
    });

    const wrapped = {
      ...node,
      containerUid: uid,
      apiBoundContainer: true,
      props,
      events,
    };
    if (loaders.length) {
      //to make sure that we don't wrap the component with a container if we don't have to
      wrapped.loaders = loaders;
    }
    if (Object.keys(vars).length) {
      //to make sure that we don't wrap the component with a container if we don't have to
      wrapped.vars = vars;
    }
    if (Object.keys(api).length) {
      //to make sure that we don't wrap the component with a container if we don't have to
      wrapped.api = api;
    }
    return wrapped;
  }, [apiBoundEvents, apiBoundProps, node, uid]);

  // useEffect(() => {
  //   console.log("wrapped with adapter changed", wrappedWithAdapter);
  // }, [wrappedWithAdapter]);

  const renderedChild = renderChild(
    wrappedWithAdapter,
    layoutContextRef?.current,
    parentRendererContext,
  );
  return React.isValidElement(renderedChild) ? renderedChild : <>{renderedChild}</>;
}

```

--------------------------------------------------------------------------------
/xmlui/src/components-core/loader/PageableLoader.tsx:
--------------------------------------------------------------------------------

```typescript
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef } from "react";
import type { InfiniteData, QueryFunction } from "@tanstack/react-query";
import { useInfiniteQuery } from "@tanstack/react-query";
import produce, { createDraft, finishDraft } from "immer";

import type { RegisterComponentApiFn } from "../../abstractions/RendererDefs";
import type { ComponentDef } from "../../abstractions/ComponentDefs";
import type { ContainerState } from "../rendering/ContainerWrapper";
import type {
  LoaderErrorFn,
  LoaderInProgressChangedFn,
  LoaderLoadedFn,
  TransformResultFn,
} from "../abstractions/LoaderRenderer";
import { extractParam } from "../utils/extractParam";
import { useAppContext } from "../AppContext";
import { usePrevious } from "../utils/hooks";

export type LoaderDirections = "FORWARD" | "BACKWARD" | "BIDIRECTIONAL";

type LoaderProps = {
  state: ContainerState;
  loader: ComponentDef;
  loaderFn: (abortSignal: AbortSignal | undefined, pageParam: string) => Promise<any>;
  queryId?: readonly any[];
  registerComponentApi: RegisterComponentApiFn;
  pollIntervalInSeconds?: number;
  onLoaded?: (...args: any[]) => void;
  loaderInProgressChanged: LoaderInProgressChangedFn;
  loaderIsRefetchingChanged: LoaderInProgressChangedFn;
  loaderLoaded: LoaderLoadedFn;
  loaderError: LoaderErrorFn;
  transformResult?: TransformResultFn;
  structuralSharing?: boolean;
};

export function PageableLoader({
  state,
  loader,
  loaderFn,
  queryId,
  registerComponentApi,
  pollIntervalInSeconds,
  onLoaded,
  loaderInProgressChanged,
  loaderIsRefetchingChanged,
  loaderLoaded,
  loaderError,
  transformResult,
  structuralSharing = true,
}: LoaderProps) {
  const { uid } = loader;
  const appContext = useAppContext();
  const queryKey = useMemo(
    () => (queryId ? queryId : [uid, extractParam(state, loader.props, appContext)]),
    [appContext, loader.props, queryId, state, uid],
  );
  const thizRef = useRef(queryKey);

  const getPreviousPageParam = useCallback(
    (firstPage: any) => {
      let prevPageParam = undefined;
      const prevPageSelector = loader.props.prevPageSelector;
      if (prevPageSelector) {
        prevPageParam = extractParam(
          { $response: firstPage.filter((item) => !item._optimisticValue) },
          prevPageSelector.startsWith("{") ? prevPageSelector : `{$response.${prevPageSelector}}`,
        );
      }
      if (!prevPageParam) {
        return undefined;
      }
      return {
        prevPageParam: prevPageParam,
      };
    },
    [loader.props.prevPageSelector],
  );
  const getNextPageParam = useCallback(
    (lastPage: any) => {
      let nextPageParam = undefined;
      const nextPageSelector = loader.props.nextPageSelector;
      if (nextPageSelector) {
        nextPageParam = extractParam(
          { $response: lastPage },
          nextPageSelector.startsWith("{") ? nextPageSelector : `{$response.${nextPageSelector}}`,
        );
      }
      if (!nextPageParam) {
        return undefined;
      }
      return {
        nextPageParam: nextPageParam,
      };
    },
    [loader.props.nextPageSelector],
  );

  // useEffect(()=>{
  //   console.log("TRANSFORM RESULT CHANGED", transformResult);
  // }, [transformResult]);
  const {
    data,
    status,
    error,
    hasNextPage,
    isFetchingNextPage,
    hasPreviousPage,
    isFetchingPreviousPage,
    isFetching,
    refetch,
    fetchPreviousPage,
    fetchNextPage,
    isRefetching,
  } = useInfiniteQuery({
    queryKey,
    queryFn: useCallback<QueryFunction>(
      async ({ signal, pageParam }) => {
        return await loaderFn(signal, pageParam);
      },
      [loaderFn],
    ),
    structuralSharing,
    select: useCallback(
      (data: any) => {
        let result = [];
        if (data) {
          result = data.pages.flatMap((d) => d);
        }
        const resultSelector = loader.props.resultSelector;
        if (resultSelector) {
          result = extractParam(
            { $response: result },
            resultSelector.startsWith("{") ? resultSelector : `{$response.${resultSelector}}`,
          );
        }
        return transformResult ? transformResult(result) : result;
      },
      [loader.props.resultSelector, transformResult],
    ),
    getPreviousPageParam:
      loader.props.prevPageSelector === undefined ? undefined : getPreviousPageParam,
    getNextPageParam: loader.props.nextPageSelector === undefined ? undefined : getNextPageParam,
  });

  //TODO revisit
  // //we clear all the pages, except the last one (it's suitable for the chat app, but for the other direction we'll have to leave the first page)
  // // otherwise it'll keep it in the cache, and refetch all the pages when you come back
  // //  see more here: https://stackoverflow.com/questions/71286123/reactquery-useinfinitequery-refetching-issue
  // //  and here: https://tanstack.com/query/latest/docs/react/guides/infinite-queries?from=reactQueryV3&original=https%3A%2F%2Ftanstack.com%2Fquery%2Fv3%2Fdocs%2Fguides%2Finfinite-queries#what-happens-when-an-infinite-query-needs-to-be-refetched
  useEffect(() => {
    const queryKey = thizRef.current;
    return () => {
      void appContext.queryClient?.cancelQueries(queryKey);
      appContext.queryClient?.setQueryData(queryKey, (old) => {
        if (!old) {
          return old;
        }
        return produce(old, (draft: any) => {
          draft.pages = draft.pages.length ? [draft.pages[draft.pages.length - 1]] : [];
          // draft.pageParams = draft.pageParams.length ? [draft.pageParams[draft.pageParams.length - 1]] : [];
          draft.pageParams = [];
        });
      });
      loaderLoaded(undefined, undefined);
    };
  }, [appContext.queryClient, loaderLoaded, uid]);

  const prevData = usePrevious(data);
  const prevError = usePrevious(error);

  useLayoutEffect(() => {
    loaderInProgressChanged(isFetching); //TODO isFetchingPrevPage / nextPage
  }, [isFetching, loaderInProgressChanged]);

  useLayoutEffect(() => {
    loaderIsRefetchingChanged(isRefetching); //TODO isFetchingPrevPage / nextPage
  }, [isRefetching, loaderIsRefetchingChanged]);

  const pageInfo = useMemo(() => {
    return {
      hasPrevPage: hasPreviousPage,
      isFetchingPrevPage: isFetchingPreviousPage,
      hasNextPage,
      isFetchingNextPage,
    };
  }, [hasNextPage, hasPreviousPage, isFetchingNextPage, isFetchingPreviousPage]);

  const prevPageInfo = usePrevious(pageInfo);

  useLayoutEffect(() => {
    // console.log("data changed", {
    //   status,
    //   data,
    //   pageInfo,
    // });
    if (status === "success" && (prevData !== data || prevPageInfo !== pageInfo)) {
      loaderLoaded(data, pageInfo);
      //we do this to push the onLoaded callback to the next event loop.
      // It works, because useLayoutEffect will run synchronously after the render, and the onLoaded callback will have
      // access to the latest loader value
      setTimeout(() => {
        onLoaded?.(data, isRefetching);
      }, 0);
    } else if (status === "error" && prevError !== error) {
      loaderError(error);
    }
  }, [
    data,
    error,
    isRefetching,
    loaderError,
    loaderLoaded,
    onLoaded,
    pageInfo,
    prevData,
    prevError,
    prevPageInfo,
    status,
  ]);

  useEffect(() => {
    let intervalId: NodeJS.Timeout;
    if (pollIntervalInSeconds) {
      intervalId = setInterval(() => {
        void refetch();
      }, pollIntervalInSeconds * 1000);
    }
    return () => {
      if (intervalId) {
        clearInterval(intervalId);
      }
    };
  }, [pollIntervalInSeconds, refetch]);

  const fetchPrevPage = useCallback(() => {
    return fetchPreviousPage();
  }, [fetchPreviousPage]);

  const stableFetchNextPage = useCallback(() => {
    return fetchNextPage();
  }, [fetchNextPage]);

  useEffect(() => {
    registerComponentApi({
      fetchPrevPage,
      fetchNextPage: stableFetchNextPage,
      refetch: (options) => {
        void refetch(options);
      },
      update: async (updater) => {
        const oldData = appContext.queryClient?.getQueryData(queryId!) as InfiniteData<any[]>;
        if (!oldData) {
          //loader not loaded yet, we skip the update
          return;
        }
        const originalFlatItems = oldData.pages.flatMap((d) => d);

        const draft = createDraft(oldData);
        const flatItems = [];
        for (let i = 0; i < draft.pages.length; i++) {
          const page = draft.pages[i];
          await updater(page);
          flatItems.push(...page);
        }

        if (flatItems.length !== originalFlatItems.length) {
          throw new Error(
            "Use this method for update only. If you want to add or delete, call the addItem/deleteItem method.",
          );
        }
        const newData = finishDraft(draft);

        // console.log("BEFORE: ", appContext.queryClient?.getQueryData(queryId!));

        appContext.queryClient?.setQueryData(queryId!, newData);

        // console.log("AFTER: ", appContext.queryClient?.getQueryData(queryId!));
      },
      addItem: (element: any, indexToInsert?: number) => {
        const oldData = appContext.queryClient?.getQueryData(queryId!) as InfiniteData<any[]>;
        const draft = createDraft(oldData);

        if (indexToInsert === undefined) {
          draft.pages[draft.pages.length - 1].push(element);
        } else {
          throw new Error("not implemented");
          // TODO is should be something like this
          // //find the pageIndex and itemIndex in that page
          // let pageIndex = -1;
          // let itemIndex = -1;
          // let i = 0;
          // oldData.pages.forEach((page, index)=>{
          //   i += page.result.length;
          //   if(i >= indexToInsert){
          //     pageIndex = index;
          //     itemIndex = i - indexToInsert;
          //     return;
          //   }
          // });
          // draft.pages[pageIndex].result.splice(itemIndex, 0, element);
        }

        const newData = finishDraft(draft);
        appContext.queryClient?.setQueryData(queryId!, newData);
      },
      getItems: () => {
        return data;
      },
      deleteItem: (element: any) => {
        throw new Error("not implemented");
      },
    });
  }, [
    appContext.queryClient,
    fetchPrevPage,
    data,
    loader.uid,
    queryId,
    queryKey,
    refetch,
    registerComponentApi,
    stableFetchNextPage,
  ]);

  return null;
}

```

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

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

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

$component: "Text";
$themeVars: t.composeTextVars($themeVars, $component);

@mixin textVariant($variant) {
  $variantName: if($variant == "", "#{$component}", "#{$component}-#{$variant}");
  $themeVars: t.composePaddingVars($themeVars, $variantName);
  $themeVars: t.composeBorderVars($themeVars, $variantName);
  $themeVars: t.composeTextVars($themeVars, $variantName, $component);
  @include t.paddingVars($themeVars, $variantName);
  @include t.borderVars($themeVars, $variantName);
  @include t.textVars($themeVars, $variantName);
  margin-top: createThemeVar("marginTop-#{$variantName}");
  margin-bottom: createThemeVar("marginBottom-#{$variantName}");
  margin-left: createThemeVar("marginLeft-#{$variantName}");
  margin-right: createThemeVar("marginRight-#{$variantName}");
  vertical-align: createThemeVar("verticalAlignment-#{$variantName}");

  &:hover {
    color: createThemeVar("textColor-#{$variantName}--hover");
  }
}

@layer components {
  .text {
    display: inline;
    overflow: hidden;
    text-overflow: ellipsis;
    margin: 0;
    padding: 0;
    min-height: fit-content;

    &.default {
      @include textVariant("");
    }

    &.inherit {
      @include t.ignoreTextVars();
    }

    &.abbr {
      font-weight: createThemeVar("fontWeight-#{$component}-abbr");
      text-transform: createThemeVar("textTransform-#{$component}-abbr");
    }

    &.cite {
      font-style: createThemeVar("fontStyle-#{$component}-cite");
    }

    &.em {
      font-style: createThemeVar("fontStyle-#{$component}-em");
    }

    &.deleted {
      text-decoration-line: createThemeVar("textDecorationLine-#{$component}-deleted");
      text-decoration-color: createThemeVar("textDecorationColor-#{$component}-deleted");
      text-decoration-style: createThemeVar("textDecorationStyle-#{$component}-deleted");
      text-decoration-thickness: createThemeVar("textDecorationThickness-#{$component}-deleted");

      // Based on accessibility concerns
      // Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del
      &::before,
      &::after {
        clip-path: inset(100%);
        clip: rect(1px, 1px, 1px, 1px);
        height: 1px;
        overflow: hidden;
        position: absolute;
        white-space: nowrap;
        width: 1px;
      }
      &::before {
        content: " [deletion start] ";
      }
      &::after {
        content: " [deletion end] ";
      }
    }

    &.inserted {
      text-decoration-line: createThemeVar("textDecorationLine-#{$component}-inserted") !important;
      text-decoration-color: createThemeVar("textDecorationColor-#{$component}-inserted") !important;
      text-decoration-style: createThemeVar("textDecorationStyle-#{$component}-inserted") !important;
      text-decoration-thickness: createThemeVar("textDecorationThickness-#{$component}-inserted") !important;

      // Based on accessibility concerns
      // Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins
      &::before,
      &::after {
        clip-path: inset(100%);
        clip: rect(1px, 1px, 1px, 1px);
        height: 1px;
        overflow: hidden;
        position: absolute;
        white-space: nowrap;
        width: 1px;
      }
      &::before {
        content: " [insertion start] ";
      }
      &::after {
        content: " [insertion end] ";
      }
    }

    // This is just a style placeholder
    &.keyboard {
      background-color: createThemeVar("backgroundColor-#{$component}-keyboard");
      font-family: createThemeVar("fontFamily-#{$component}-keyboard");
      font-weight: createThemeVar("fontWeight-#{$component}-keyboard");
      font-size: createThemeVar("fontSize-#{$component}-keyboard");
      border-width: createThemeVar("borderWidth-#{$component}-keyboard");
      border-color: createThemeVar("borderColor-#{$component}-keyboard");
      border-style: createThemeVar("borderStyle-#{$component}-keyboard");
      border-radius: createThemeVar("borderRadius-#{$component}-keyboard");
      padding-left: createThemeVar("paddingHorizontal-#{$component}-keyboard");
      padding-right: createThemeVar("paddingHorizontal-#{$component}-keyboard");
    }

    &.marked {
      background-color: createThemeVar("backgroundColor-#{$component}-marked");
      color: createThemeVar("textColor-#{$component}-marked");
      font-weight: createThemeVar("fontWeight-#{$component}-marked");
      font-style: createThemeVar("fontStyle-#{$component}-marked");
      line-height: createThemeVar("lineHeight-#{$component}-marked");

      // Based on accessibility concerns
      // Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark
      &::before,
      &::after {
        clip-path: inset(100%);
        clip: rect(1px, 1px, 1px, 1px);
        height: 1px;
        overflow: hidden;
        position: absolute;
        white-space: nowrap;
        width: 1px;
      }
      &::before {
        content: " [highlight start] ";
      }
      &::after {
        content: " [highlight end] ";
      }
    }

    &.mono {
      font-family: createThemeVar("fontFamily-#{$component}-mono");
    }

    &.sample {
      font-family: createThemeVar("fontFamily-#{$component}-sample");
      font-size: createThemeVar("fontSize-#{$component}-sample");
    }

    &.sup {
      font-size: createThemeVar("fontSize-#{$component}-sup");
      vertical-align: createThemeVar("verticalAlignment-#{$component}-sup");
    }

    &.sub {
      font-size: createThemeVar("fontSize-#{$component}-sub");
      vertical-align: createThemeVar("verticalAlignment-#{$component}-sub");
    }

    &.var {
      font-style: createThemeVar("fontStyle-#{$component}-var");
    }

    &.title {
      font-size: createThemeVar("fontSize-#{$component}-title");
    }

    &.subtitle {
      font-size: createThemeVar("fontSize-#{$component}-subtitle");
    }

    &.small {
      @include textVariant("small");
    }

    &.code {
      @include textVariant("code");
    }

    &.caption {
      letter-spacing: createThemeVar("letterSpacing-#{$component}-caption");
    }

    &.placeholder {
      color: createThemeVar("textColor-#{$component}-placeholder");
      font-style: createThemeVar("fontStyle-#{$component}-placeholder");
      font-weight: createThemeVar("fontWeight-#{$component}-placeholder");
      font-size: createThemeVar("fontSize-#{$component}-placeholder");
    }

    &.paragraph {
      font-size: createThemeVar("fontSize-#{$component}-paragraph");
      padding-top: createThemeVar("paddingVertical-#{$component}-paragraph");
      padding-bottom: createThemeVar("paddingVertical-#{$component}-paragraph");
    }

    &.subheading {
      font-size: createThemeVar("fontSize-#{$component}-subheading");
      font-weight: createThemeVar("fontWeight-#{$component}-subheading");
      font-style: createThemeVar("fontStyle-#{$component}-subheading");
      letter-spacing: createThemeVar("letterSpacing-#{$component}-subheading");
      text-transform: createThemeVar("textTransform-#{$component}-subheading");
      color: createThemeVar("textColor-#{$component}-subheading");
    }

    &.tableheading {
      margin-top: createThemeVar("marginTop-#{$component}-tableheading");
      margin-bottom: createThemeVar("marginBottom-#{$component}-tableheading");
      padding-left: createThemeVar("paddingHorizontal-#{$component}-tableheading");
      padding-right: createThemeVar("paddingHorizontal-#{$component}-tableheading");
      font-size: createThemeVar("fontSize-#{$component}-tableheading");
      font-weight: createThemeVar("fontWeight-#{$component}-tableheading");
    }

    &.secondary {
      font-size: createThemeVar("fontSize-#{$component}-secondary");
      color: createThemeVar("textColor-#{$component}-secondary");
    }

    &.strong{
      font-weight: t.$fontWeight-bold;
    }
  }

  /*
  This is a Chromium based solution that is supported by most modern browsers.
  See this source for details: https://css-tricks.com/line-clampin/
  */
  .truncateOverflow {
    overflow: hidden;
    overflow-wrap: break-word;
    white-space: nowrap;
    max-width: 100%;
  }

  .preserveLinebreaks {
    white-space: pre-wrap;
    display: inline-block;
  }

  .noEllipsis {
    text-overflow: clip;
  }

  // --- Overflow behavior classes
  .overflowNone {
    // Force single line as per metadata: "No wrapping, text stays on a single line"
    white-space: nowrap;
    // Hide overflow content
    overflow: hidden;
    // Use clip instead of ellipsis
    text-overflow: clip;
    // Constrain width
    max-width: 100%;
  }

  .overflowScroll {
    white-space: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    text-overflow: unset;
    max-width: 100%;
    
    // Ensure scrollbar is visible when needed
    &::-webkit-scrollbar {
      height: 6px;
    }
    
    &::-webkit-scrollbar-track {
      background: transparent;
    }
    
    &::-webkit-scrollbar-thumb {
      background-color: rgba(0, 0, 0, 0.3);
      border-radius: 3px;
    }
  }

  .overflowFlow {
    // Allow text to wrap to multiple lines
    white-space: normal;
    // Hide horizontal overflow, show vertical scrollbar when needed
    overflow-x: hidden;
    overflow-y: auto;
    // Disable text-overflow ellipsis since we want wrapping
    text-overflow: unset;
    // Constrain width but allow height to grow
    max-width: 100%;
    // Change display to block to respect width/height constraints
    display: block;
    // Ensure height constraint is respected in flex contexts
    flex-shrink: 0;
    flex-grow: 0;
    // Use min-height instead of height to avoid conflicts
    min-height: 0;
    
    // Style vertical scrollbar
    &::-webkit-scrollbar {
      width: 6px;
    }
    
    &::-webkit-scrollbar-track {
      background: transparent;
    }
    
    &::-webkit-scrollbar-thumb {
      background-color: rgba(0, 0, 0, 0.3);
      border-radius: 3px;
    }
  }
}

// --- Break mode classes
.breakNormal {
  word-break: normal;
  overflow-wrap: normal;
}

.breakWord {
  overflow-wrap: break-word;
}

.breakAnywhere {
  word-break: break-all;
  overflow-wrap: anywhere;
}

.breakKeep {
  word-break: keep-all;
}

.breakHyphenate {
  hyphens: auto;
  overflow-wrap: break-word;
}

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

```

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

```markdown
# IFrame [#iframe]

`IFrame` embeds external content from another HTML document into the current page. It provides security controls through sandbox and allow attributes, and supports features like fullscreen display and referrer policy configuration.

**Key features:**
- **External content embedding**: Load web pages, documents, or media from external URLs
- **Security controls**: Built-in sandbox and permission policies for safe content isolation
- **HTML content support**: Display inline HTML content without external sources
- **Event handling**: Track loading states with load events

## Properties [#properties]

### `allow` [#allow]

Specifies the permissions policy for the iframe. Controls which features (like camera, microphone, geolocation) the embedded content can use.

The `allow` property controls which browser features the embedded content can access. Common values include camera, microphone, geolocation, and fullscreen permissions.

```xmlui-pg copy display name="Example: allow"
<App>
  <IFrame
      src="https://www.youtube.com/embed/dQw4w9WgXcQ"
      allow="camera; microphone; geolocation"
      width="560px"
      height="315px"
      title="Rick Astley - Never Gonna Give You Up (Official Video)"
    />
</App>
```

### `name` [#name]

Specifies a name for the iframe, which can be used as a target for links and forms.

```xmlui-pg copy display name="Example: name" /name="myFrame"/
<App>
  <VStack gap="$space-2">
    <Button 
      label="Open 'Kraftwerk: The Model' in IFrame" 
      onClick="window.open('https://www.youtube.com/embed/-s4zRw16tMA', 'myFrame')" 
    />
    <IFrame 
      src="https://example.com"
      name="myFrame"
      width="100%" 
      height="300px" />
  </VStack>
</App>
```

### `referrerPolicy` [#referrerpolicy]

Controls how much referrer information is sent when fetching the iframe content.

Available values:

| Value | Description |
| --- | --- |
| `no-referrer` | Never send referrer information |
| `no-referrer-when-downgrade` | Send referrer only for same-security destinations |
| `origin` | Send only the origin as referrer |
| `origin-when-cross-origin` | Send full URL for same-origin, origin only for cross-origin |
| `same-origin` | Send referrer only for same-origin requests |
| `strict-origin` | Send origin only for same-security destinations |
| `strict-origin-when-cross-origin` | Full URL for same-origin, origin for cross-origin same-security |
| `unsafe-url` | Always send full URL as referrer |

### `sandbox` [#sandbox]

Applies extra restrictions to the content in the iframe. Value is a space-separated list of sandbox flags (e.g., 'allow-scripts allow-same-origin').

### `src` [#src]

Specifies the URL of the document to embed in the iframe. Either `src` or `srcdoc` should be specified, but not both.

```xmlui-pg copy display name="Example: src"
<App>
  <IFrame 
    src="https://example.com" 
    width="100%" 
    height="300px" />
</App>
```

### `srcdoc` [#srcdoc]

Specifies the HTML content to display in the iframe. Either `src` or `srcdoc` should be specified, but not both.

```xmlui-pg copy display name="Example: srcdoc"
<App>
  <IFrame 
    srcdoc="
      <h1>Hello World</h1>
      <p>This is embedded HTML content with <strong>formatting</strong>.</p>
    "
    width="100%" 
    height="200px" />
</App>
```

## Events [#events]

### `load` [#load]

This event is triggered when the IFrame content has finished loading.

```xmlui-pg copy display name="Example: load"
<App var.loadStatus="Loading...">
  <VStack gap="$space-2">
    <Text value="Status: {loadStatus}" />
    <IFrame 
      src="https://example.com"
      onLoad="loadStatus = 'Content loaded successfully!'"
      width="100%" 
      height="200px" />
  </VStack>
</App>
```

## Exposed Methods [#exposed-methods]

### `getContentDocument` [#getcontentdocument]

This method returns the content document of the iframe element.

**Signature**: `getContentDocument(): Document | null`

Get access to the iframe's content document object. Returns null if the content document is not accessible.

```xmlui-pg copy display name="Example: getContentDocument" /getContentDocument/
<App>
  <VStack var.iFrameTitle="<not queried yet>" >
    <Button 
      label="Get Document Title" 
      onClick="
        const contentDoc = myIframe.getContentDocument();
        iFrameTitle = contentDoc 
          ? contentDoc.title 
          : 'Content document not accessible';
      " />
    <Card title="IFrame title: {iFrameTitle}" />
    <IFrame 
      id="myIframe"
      srcdoc="
        <html>
          <head><title>My Awesome Document</title></head>
          <body><h1>Awesome Content</h1></body>
        </html>"
      width="100%" 
      height="200px" />
  </VStack>
</App>
```

### `getContentWindow` [#getcontentwindow]

This method returns the content window of the iframe element.

**Signature**: `getContentWindow(): Window | null`

Get access to the iframe's content window object. Returns null if the content window is not accessible.

```xmlui-pg copy display name="Example: getContentWindow" /getContentWindow/
<App>
  <VStack var.windowStatus="Not checked yet" gap="$space-2">
    <Button 
      label="Check Content Window" 
      onClick="
        const contentWindow = myIframe.getContentWindow();
        windowStatus = contentWindow 
          ? 'Content window is accessible' 
          : 'Content window is not accessible';
      " />
    <Card title="Status: {windowStatus}" />
    <IFrame 
      id="myIframe"
      src="https://example.com"
      width="100%" 
      height="200px" />
  </VStack>
</App>
```

### `postMessage` [#postmessage]

This method sends a message to the content window of the iframe.

**Signature**: `postMessage(message: any, targetOrigin?: string): void`

- `message`: The message to send to the iframe's content window.
- `targetOrigin`: The origin to which the message should be sent. Defaults to '*'.

```xmlui-pg copy display name="Example: postMessage" /postMessage/
<App>
  <VStack var.messageStatus="Ready to send" gap="$space-2">
    <Button 
      label="Send Message to IFrame" 
      onClick="
        myIframe.postMessage({type: 'greeting', text: 'Hello from parent!'}, '*');
        messageStatus = 'Message sent!';
      " />
    <Card title="Status: {messageStatus}" />
    <IFrame 
      id="myIframe"
      srcdoc="
        <script>
          window.addEventListener('message', (event) => \{
            console.log('Received message:', event.data);
            document.body.innerHTML = 
              '<h1>Message: ' + JSON.stringify(event.data) + '</h1>';
          });
        </script>
        <h1>Waiting for message...</h1>
      "
      width="100%" 
      height="200px" />
  </VStack>
</App>
```

## Styling [#styling]

### Size Control [#size-control]

IFrame supports these theme variables for consistent sizing:
- `width-IFrame`
- `height-IFrame`
- `borderRadius-IFrame`
- `border-IFrame`

```xmlui-pg display copy name="Example: IFrame with custom styling"
<App>
  <Theme 
    width-IFrame="400px" 
    height-IFrame="250px"
    borderRadius-IFrame="8px"
    border-IFrame="2px solid $primaryColor">
    <IFrame src="https://example.com" />
  </Theme>
</App>
```

### Theme Variables [#theme-variables]

| Variable | Default Value (Light) | Default Value (Dark) |
| --- | --- | --- |
| [border](../styles-and-themes/common-units/#border)-IFrame | 1px solid $borderColor | 1px solid $borderColor |
| [borderBottom](../styles-and-themes/common-units/#border)-IFrame | *none* | *none* |
| [borderBottomColor](../styles-and-themes/common-units/#color)-IFrame | *none* | *none* |
| [borderBottomStyle](../styles-and-themes/common-units/#border-style)-IFrame | *none* | *none* |
| [borderBottomWidth](../styles-and-themes/common-units/#size)-IFrame | *none* | *none* |
| [borderColor](../styles-and-themes/common-units/#color)-IFrame | *none* | *none* |
| [borderEndEndRadius](../styles-and-themes/common-units/#border-rounding)-IFrame | *none* | *none* |
| [borderEndStartRadius](../styles-and-themes/common-units/#border-rounding)-IFrame | *none* | *none* |
| [borderHorizontal](../styles-and-themes/common-units/#border)-IFrame | *none* | *none* |
| [borderHorizontalColor](../styles-and-themes/common-units/#color)-IFrame | *none* | *none* |
| [borderHorizontalStyle](../styles-and-themes/common-units/#border-style)-IFrame | *none* | *none* |
| [borderHorizontalWidth](../styles-and-themes/common-units/#size)-IFrame | *none* | *none* |
| [borderLeft](../styles-and-themes/common-units/#border)-IFrame | *none* | *none* |
| [color](../styles-and-themes/common-units/#color)-IFrame | *none* | *none* |
| [borderLeftStyle](../styles-and-themes/common-units/#border-style)-IFrame | *none* | *none* |
| [borderLeftWidth](../styles-and-themes/common-units/#size)-IFrame | *none* | *none* |
| [borderRadius](../styles-and-themes/common-units/#border-rounding)-IFrame | $borderRadius | $borderRadius |
| [borderRight](../styles-and-themes/common-units/#border)-IFrame | *none* | *none* |
| [color](../styles-and-themes/common-units/#color)-IFrame | *none* | *none* |
| [borderRightStyle](../styles-and-themes/common-units/#border-style)-IFrame | *none* | *none* |
| [borderRightWidth](../styles-and-themes/common-units/#size)-IFrame | *none* | *none* |
| [borderStartEndRadius](../styles-and-themes/common-units/#border-rounding)-IFrame | *none* | *none* |
| [borderStartStartRadius](../styles-and-themes/common-units/#border-rounding)-IFrame | *none* | *none* |
| [borderStyle](../styles-and-themes/common-units/#border-style)-IFrame | *none* | *none* |
| [borderTop](../styles-and-themes/common-units/#border)-IFrame | *none* | *none* |
| [borderTopColor](../styles-and-themes/common-units/#color)-IFrame | *none* | *none* |
| [borderTopStyle](../styles-and-themes/common-units/#border-style)-IFrame | *none* | *none* |
| [borderTopWidth](../styles-and-themes/common-units/#size)-IFrame | *none* | *none* |
| [borderHorizontal](../styles-and-themes/common-units/#border)-IFrame | *none* | *none* |
| [borderVerticalColor](../styles-and-themes/common-units/#color)-IFrame | *none* | *none* |
| [borderVerticalStyle](../styles-and-themes/common-units/#border-style)-IFrame | *none* | *none* |
| [borderVerticalWidth](../styles-and-themes/common-units/#size)-IFrame | *none* | *none* |
| [borderWidth](../styles-and-themes/common-units/#size)-IFrame | *none* | *none* |
| [height](../styles-and-themes/common-units/#size)-IFrame | 300px | 300px |
| [width](../styles-and-themes/common-units/#size)-IFrame | 100% | 100% |

```

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

```typescript
import type { CSSProperties, ForwardedRef } from "react";
import React, { useCallback, useEffect, useId, useRef } from "react";
import { forwardRef } from "react";
import { Root, Range, Track, Thumb } from "@radix-ui/react-slider";
import styles from "./Slider.module.scss";
import type { RegisterComponentApiFn, UpdateStateFn } from "../../abstractions/RendererDefs";
import { noop } from "../../components-core/constants";
import { useEvent } from "../../components-core/utils/misc";
import type { ValidationStatus } from "../abstractions";
import classnames from "classnames";
import { Tooltip } from "../Tooltip/TooltipNative";
import { isNaN } from "lodash-es";
import { composeRefs } from "@radix-ui/react-compose-refs";

export type Props = {
  id?: string;
  value?: number | number[];
  initialValue?: number | number[];
  style?: CSSProperties;
  className?: string;
  step?: number;
  max?: number;
  min?: number;
  inverted?: false;
  validationStatus?: ValidationStatus;
  minStepsBetweenThumbs?: number;
  onDidChange?: (newValue: number | number[]) => void;
  onFocus?: (ev: React.FocusEvent<HTMLDivElement>) => void;
  onBlur?: (ev: React.FocusEvent<HTMLDivElement>) => void;
  updateState?: UpdateStateFn;
  registerComponentApi?: RegisterComponentApiFn;
  autoFocus?: boolean;
  readOnly?: boolean;
  tabIndex?: number;
  required?: boolean;
  enabled?: boolean;
  rangeStyle?: CSSProperties;
  thumbStyle?: CSSProperties;
  showValues?: boolean;
  valueFormat?: (value: number) => string;
};

export const defaultProps: Pick<
  Props,
  | "step"
  | "min"
  | "max"
  | "enabled"
  | "validationStatus"
  | "tabIndex"
  | "showValues"
  | "valueFormat"
  | "minStepsBetweenThumbs"
> = {
  step: 1,
  min: 0,
  max: 10,
  enabled: true,
  validationStatus: "none" as ValidationStatus,
  tabIndex: -1,
  showValues: true,
  valueFormat: (value: number) => value.toString(),
  minStepsBetweenThumbs: 1,
};

const parseValue = (val: string | number | undefined, defaultVal: number): number => {
  if (typeof val === "number") {
    return val;
  } else if (typeof val === "string") {
    const parsed = parseFloat(val);
    if (!isNaN(parsed)) {
      return parsed;
    }
  }
  return defaultVal;
};

// Helper function to ensure value is properly formatted
const formatValue = (
  val: number | number[] | undefined,
  defaultVal: number = 0,
  minVal?: number,
  maxVal?: number,
): number[] => {
  const clampValue = (value: number): number => {
    if (minVal !== undefined && value < minVal) return minVal;
    if (maxVal !== undefined && value > maxVal) return maxVal;
    return value;
  };

  if (val === undefined) {
    return [clampValue(defaultVal)];
  }
  if (typeof val === "number") {
    return [clampValue(val)];
  }
  if (Array.isArray(val) && val.length > 0) {
    return val.map(clampValue);
  }
  return [clampValue(defaultVal)];
};

export const Slider = forwardRef(
  (
    {
      id,
      style,
      className,
      step = defaultProps.step,
      min = defaultProps.min,
      max = defaultProps.max,
      inverted,
      updateState,
      onDidChange = noop,
      onFocus = noop,
      onBlur = noop,
      registerComponentApi,
      enabled = defaultProps.enabled,
      value,
      autoFocus,
      readOnly,
      tabIndex = defaultProps.tabIndex,
      required,
      validationStatus = defaultProps.validationStatus,
      initialValue,
      minStepsBetweenThumbs = defaultProps.minStepsBetweenThumbs,
      rangeStyle,
      thumbStyle,
      showValues = defaultProps.showValues,
      valueFormat = defaultProps.valueFormat,
      ...rest
    }: Props,
    forwardedRef: ForwardedRef<HTMLInputElement>,
  ) => {
    const inputRef = useRef(null);
    const ref = forwardedRef ? composeRefs(inputRef, forwardedRef) : inputRef;
    const tooltipRef = useRef<HTMLDivElement>(null);
    const thumbsRef = useRef<(HTMLSpanElement | null)[]>([]);
    min = parseValue(min, defaultProps.min);
    max = parseValue(max, defaultProps.max);

    // Initialize localValue properly
    const [localValue, setLocalValue] = React.useState<number[]>(() =>
      formatValue(value || initialValue, min, min, max),
    );
    const [showTooltip, setShowTooltip] = React.useState(false);
    const onShowTooltip = useCallback(() => setShowTooltip(true), []);
    const onHideTooltip = useCallback(() => setShowTooltip(false), []);

    // Process initialValue on mount
    useEffect(() => {
      let initialVal: number | number[] = min;

      if (typeof initialValue === "string") {
        try {
          // Try to parse as JSON first (for arrays)
          const parsed = JSON.parse(initialValue);
          initialVal = parsed;
        } catch (e) {
          // If not JSON, try to parse as number
          const num = parseFloat(initialValue);
          if (!isNaN(num)) {
            initialVal = num;
          }
        }
      } else if (typeof initialValue === "number") {
        initialVal = initialValue;
      } else if (initialValue !== undefined) {
        initialVal = initialValue;
      }

      // Format the value properly - single call to formatValue with bounds checking
      const formattedValue = formatValue(initialVal, min, min, max);
      setLocalValue(formattedValue);

      // Notify parent component
      if (updateState) {
        updateState(
          {
            value: formattedValue.length === 1 ? formattedValue[0] : formattedValue,
          },
          { initial: true },
        );
      }
    }, [initialValue, min, max, updateState]);

    // Sync with external value changes
    useEffect(() => {
      if (value !== undefined) {
        const formattedValue = formatValue(value, min, min, max);
        setLocalValue(formattedValue);
      }
    }, [value, min, max]);

    const updateValue = useCallback(
      (value: number | number[]) => {
        if (updateState) {
          updateState({ value });
        }
        // Call onDidChange without extra arguments to maintain type compatibility
        onDidChange(value);
      },
      [onDidChange, updateState],
    );

    const onInputChange = useCallback(
      (value: number[]) => {
        if (readOnly) {
          return;
        }
        setLocalValue(value);

        // 👇 Force the DOM element to reflect the latest value synchronously
        if (inputRef.current) {
          inputRef.current.value = value;
        }

        if (value.length > 1) {
          updateValue(value); // calls updateState + onDidChange
        } else if (value.length === 1) {
          updateValue(value[0]);
        }
      },
      [updateValue, readOnly],
    );

    // Component APIs
    const handleOnFocus = useCallback(
      (ev: React.FocusEvent<HTMLInputElement>) => {
        onShowTooltip();
        onFocus?.(ev);
      },
      [onFocus, onShowTooltip],
    );
    const handleOnBlur = useCallback(
      (ev: React.FocusEvent<HTMLInputElement>) => {
        onBlur?.(ev);
      },
      [onBlur],
    );

    const focus = useCallback(() => {
      // Focus the first available thumb
      const firstThumb = thumbsRef.current.find(thumb => thumb !== null);
      if (firstThumb) {
        firstThumb.focus();
      } else {
        inputRef.current?.focus();
      }
    }, []);

    const setValue = useEvent((newValue) => {
      if (readOnly || !enabled) {
        return;
      }
      const formattedValue = formatValue(newValue, min, min, max);
      const valueToUpdate = formattedValue.length === 1 ? formattedValue[0] : formattedValue;
      updateValue(valueToUpdate);
    });

    useEffect(() => {
      registerComponentApi?.({
        focus,
        setValue,
      });
    }, [focus, registerComponentApi, setValue]);

    // Ensure we always have at least one thumb
    const displayValue = localValue.length > 0 ? localValue : formatValue(undefined, min, min, max);

    // Clean up thumbs ref array when number of thumbs changes
    useEffect(() => {
      thumbsRef.current = thumbsRef.current.slice(0, displayValue.length);
    }, [displayValue.length]);

      return (
          <div {...rest} ref={ref} style={style} className={classnames(styles.sliderContainer, className)} data-slider-container>
            <Root
              ref={inputRef}
              minStepsBetweenThumbs={minStepsBetweenThumbs}
              tabIndex={tabIndex}
              aria-readonly={readOnly}
              className={classnames(styles.sliderRoot, {
                [styles.disabled]: !enabled,
                [styles.readOnly]: readOnly,
              })}
              max={max}
              min={min}
              inverted={inverted}
              step={step}
              disabled={!enabled}
              onFocus={handleOnFocus}
              onBlur={handleOnBlur}
              onValueChange={onInputChange}
              onMouseOver={onShowTooltip}
              onMouseLeave={onHideTooltip}
              onPointerDown={onShowTooltip}
              value={displayValue}
            >
            <Track
              data-track
              className={classnames(styles.sliderTrack, {
                [styles.disabled]: !enabled,
                [styles.readOnly]: readOnly,
                [styles.error]: validationStatus === "error",
                [styles.warning]: validationStatus === "warning",
                [styles.valid]: validationStatus === "valid",
              })}
              style={rangeStyle ? { ...rangeStyle } : undefined}
            >
              <Range
                data-range
                className={classnames(styles.sliderRange, {
                  [styles.disabled]: !enabled,
                })}
              />
            </Track>
            {displayValue.map((_, index) => (
              <Tooltip
                key={index}
                ref={tooltipRef}
                text={valueFormat(displayValue[index])}
                delayDuration={100}
                open={showValues && showTooltip}
              >
                <Thumb
                  id={id}
                  aria-required={required}
                  ref={(el) => {
                    thumbsRef.current[index] = el;
                  }}
                  className={classnames(styles.sliderThumb, {
                    [styles.disabled]: !enabled,
                  })}
                  style={thumbStyle ? { ...thumbStyle } : undefined}
                  data-thumb-index={index}
                  autoFocus={autoFocus && index === 0}
                />
              </Tooltip>
            ))}
          </Root>
        </div>
    );
  },
);

Slider.displayName = "Slider";

```

--------------------------------------------------------------------------------
/xmlui/src/components-core/utils/treeUtils.ts:
--------------------------------------------------------------------------------

```typescript
import type {
  FlatTreeNode,
  TreeItem,
  TreeNode,
  UnPackedTreeData,
  TreeFieldConfig,
  NodeLoadingState,
  FlatTreeNodeWithState,
} from "../abstractions/treeAbstractions";

export function flattenNode(
  node: TreeNode,
  depth: number,
  result: FlatTreeNode[],
  openedIds: (string | number)[],
  dynamicField?: string,
  nodeStates?: Map<string | number, NodeLoadingState>,
) {
  const { children, key } = node;
  const isExpanded = openedIds.includes(key);
  // Check if node has actual children OR is a dynamic node that can load children
  const hasActualChildren = !!children && children.length > 0;
  const isDynamic = dynamicField && node[dynamicField];
  const hasChildren = hasActualChildren || isDynamic;
  
  // Get loading state for this node
  const loadingState = nodeStates?.get(key) || (isDynamic ? 'unloaded' : 'loaded');
  
  const flatNode: FlatTreeNodeWithState = {
    ...node,
    hasChildren,
    depth,
    isExpanded,
    loadingState,
    // Ensure key is preserved (in case it was overwritten by ...node spread)
    key: key || node.key || node.id,
  };
  
  result.push(flatNode);

  if (isExpanded && children) {
    for (let child of children) {
      flattenNode(child, depth + 1, result, openedIds, dynamicField, nodeStates);
    }
  }
}

export function toFlatTree(
  treeData: TreeNode[], 
  openedIds: (string | number)[], 
  dynamicField?: string,
  nodeStates?: Map<string | number, NodeLoadingState>
): FlatTreeNodeWithState[] {
  const ret: FlatTreeNodeWithState[] = [];
  treeData.forEach((node) => {
    flattenNode(node, 0, ret, openedIds, dynamicField, nodeStates);
  });

  return ret;
}

export function walkTree(treeData: TreeNode[], visit: (node: TreeNode) => void) {
  treeData.forEach((node) => {
    visit(node);
    walkTree(node.children || [], visit);
  });
}

export function unPackTree(
  items: Array<TreeItem> = [],
  parentIds: Array<string> = [],
  parentPath: Array<number> = [],
): UnPackedTreeData {
  const treeData: Array<TreeNode> = [];
  let treeItemsById: Record<string, TreeNode> = {};

  items.forEach((item, index) => {
    const path = [...parentPath, index];
    const id = item.id || item.cid;
    const childTree = unPackTree(item.children, [...parentIds, id], path);
    const treeItem: TreeNode = {
      ...item,
      id: id,
      key: id,
      parentIds,
      path,
      children: childTree.treeData,
      selectable: item.selectable,
    };
    treeData.push(treeItem);
    treeItemsById[id] = treeItem;
    treeItemsById = {
      ...treeItemsById,
      ...childTree.treeItemsById,
    };
  });

  return {
    treeData,
    treeItemsById,
  };
}

/**
 * Transforms flat array data with parent-child relationships into UnPackedTreeData format
 * @param flatData Array of flat objects with id and parentId relationships
 * @param fieldConfig Configuration for mapping object fields to tree properties
 * @returns UnPackedTreeData structure suitable for Tree component
 */
export function flatToNative(
  flatData: any[],
  fieldConfig: TreeFieldConfig
): UnPackedTreeData {
  if (!flatData || flatData.length === 0) {
    return { treeData: [], treeItemsById: {} };
  }

  // Build parent-to-children map for efficient lookup
  const childrenMap = new Map<string, any[]>();
  const itemsById = new Map<string, any>();
  const rootItems: any[] = [];

  // First pass: organize items and build relationships
  flatData.forEach(item => {
    const id = item[fieldConfig.idField];
    const parentId = item[fieldConfig.parentField || 'parentId'];
    
    // Store item for lookup
    itemsById.set(id, item);
    
    if (parentId && parentId !== '') {
      // Convert parentId to string for consistent type in childrenMap
      const parentKey = String(parentId);
      // Has parent - add to children map
      if (!childrenMap.has(parentKey)) {
        childrenMap.set(parentKey, []);
      }
      childrenMap.get(parentKey)!.push(item);
    } else {
      // Root item
      rootItems.push(item);
    }
  });

  // Generate unique IDs for internal tree structure
  let idCounter = 1;
  const sourceIdToId = new Map<string, string>();
  
  const getOrCreateId = (sourceId: string): string => {
    if (!sourceIdToId.has(sourceId)) {
      sourceIdToId.set(sourceId, `flat_${idCounter++}`);
    }
    return sourceIdToId.get(sourceId)!;
  };

  // Recursive function to build TreeNode structure
  const buildTreeNode = (
    item: any, 
    parentIds: string[] = [], 
    pathSegments: string[] = []
  ): TreeNode => {
    const sourceId = item[fieldConfig.idField];
    const id = getOrCreateId(sourceId);
    const displayName = item[fieldConfig.labelField] || sourceId;
    const currentPath = [...pathSegments, displayName];
    
    // Get children for this item
    const sourceKey = String(sourceId);
    const childItems = childrenMap.get(sourceKey) || [];
    const children: TreeNode[] = childItems.map(childItem => 
      buildTreeNode(childItem, [...parentIds, sourceId], currentPath)
    );

    // Build the TreeNode
    const treeNode: TreeNode = {
      id,
      key: sourceId, // Use source ID as key for expansion state
      path: currentPath,
      displayName,
      parentIds,
      selectable: fieldConfig.selectableField ? (item[fieldConfig.selectableField] ?? true) : true,
      children,
      // Preserve original item properties
      ...item,
      // Add icon properties if configured
      ...(fieldConfig.iconField && item[fieldConfig.iconField] && {
        icon: item[fieldConfig.iconField]
      }),
      ...(fieldConfig.iconExpandedField && item[fieldConfig.iconExpandedField] && {
        iconExpanded: item[fieldConfig.iconExpandedField]
      }),
      ...(fieldConfig.iconCollapsedField && item[fieldConfig.iconCollapsedField] && {
        iconCollapsed: item[fieldConfig.iconCollapsedField]
      })
    };

    return treeNode;
  };

  // Build tree structure from root items
  const treeData: TreeNode[] = rootItems.map(rootItem => 
    buildTreeNode(rootItem)
  );

  // Build lookup map by ID
  const treeItemsById: Record<string, TreeNode> = {};
  const collectNodes = (nodes: TreeNode[]) => {
    nodes.forEach(node => {
      treeItemsById[node.id] = node;
      if (node.children) {
        collectNodes(node.children);
      }
    });
  };
  collectNodes(treeData);

  return {
    treeData,
    treeItemsById,
  };
}

/**
 * Transforms hierarchical nested object data into UnPackedTreeData format
 * @param hierarchyData Single object or array of objects with nested children structure
 * @param fieldConfig Configuration for mapping object fields to tree properties
 * @returns UnPackedTreeData structure suitable for Tree component
 */
export function hierarchyToNative(
  hierarchyData: any,
  fieldConfig: TreeFieldConfig
): UnPackedTreeData {
  if (!hierarchyData) {
    return { treeData: [], treeItemsById: {} };
  }

  // Ensure we're working with an array
  const rootItems = Array.isArray(hierarchyData) ? hierarchyData : [hierarchyData];
  
  if (rootItems.length === 0) {
    return { treeData: [], treeItemsById: {} };
  }

  // Generate unique IDs for internal tree structure
  let idCounter = 1;
  const sourceIdToId = new Map<string, string>();
  
  const getOrCreateId = (sourceId: string): string => {
    if (!sourceIdToId.has(sourceId)) {
      sourceIdToId.set(sourceId, `hierarchy_${idCounter++}`);
    }
    return sourceIdToId.get(sourceId)!;
  };

  // Set to track visited nodes for circular reference detection
  const visitedIds = new Set<string>();

  // Recursive function to build TreeNode structure from hierarchical data
  const buildTreeNode = (
    item: any, 
    parentIds: string[] = [], 
    pathSegments: string[] = []
  ): TreeNode => {
    const sourceId = item[fieldConfig.idField];
    const displayName = item[fieldConfig.labelField] || sourceId;
    
    // Circular reference detection
    if (visitedIds.has(sourceId)) {
      // Return a simple node without children to break the cycle
      const id = getOrCreateId(sourceId);
      return {
        id,
        key: sourceId,
        path: [...pathSegments, displayName],
        displayName,
        parentIds,
        selectable: fieldConfig.selectableField ? (item[fieldConfig.selectableField] ?? true) : true,
        children: [],
        ...item,
        ...(fieldConfig.iconField && item[fieldConfig.iconField] && {
          icon: item[fieldConfig.iconField]
        })
      };
    }

    // Mark as visited
    visitedIds.add(sourceId);

    const id = getOrCreateId(sourceId);
    const currentPath = [...pathSegments, displayName];
    
    // Get children from the specified children field
    const childrenField = fieldConfig.childrenField || 'children';
    const childItems = item[childrenField] || [];
    
    // Recursively build children
    const children: TreeNode[] = childItems.map((childItem: any) => 
      buildTreeNode(childItem, [...parentIds, sourceId], currentPath)
    );

    // Unmark as visited after processing (for depth-first traversal)
    visitedIds.delete(sourceId);

    // Build the TreeNode
    const treeNode: TreeNode = {
      id,
      path: currentPath,
      displayName,
      parentIds,
      selectable: fieldConfig.selectableField ? (item[fieldConfig.selectableField] ?? true) : true,
      // Preserve original item properties (excluding children to avoid overwriting)
      ...item,
      // Add icon properties if configured
      ...(fieldConfig.iconField && item[fieldConfig.iconField] && {
        icon: item[fieldConfig.iconField]
      }),
      ...(fieldConfig.iconExpandedField && item[fieldConfig.iconExpandedField] && {
        iconExpanded: item[fieldConfig.iconExpandedField]
      }),
      ...(fieldConfig.iconCollapsedField && item[fieldConfig.iconCollapsedField] && {
        iconCollapsed: item[fieldConfig.iconCollapsedField]
      }),
      // Set TreeNode-specific properties AFTER spreading item to ensure they're not overwritten
      children, // Use our transformed children, not the original item's children
      key: sourceId, // Use source ID as key for expansion state
    };

    return treeNode;
  };

  // Build tree structure from root items
  const treeData: TreeNode[] = rootItems.map(rootItem => 
    buildTreeNode(rootItem)
  );

  // Build lookup map by ID
  const treeItemsById: Record<string, TreeNode> = {};
  const collectNodes = (nodes: TreeNode[]) => {
    nodes.forEach(node => {
      treeItemsById[node.id] = node;
      if (node.children) {
        collectNodes(node.children);
      }
    });
  };
  collectNodes(treeData);

  return {
    treeData,
    treeItemsById,
  };
}

```

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

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

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

test.describe("Basic Functionality", () => {
  test("renders as standalone bookmark", async ({ initTestBed, page }) => {
    await initTestBed(`<Bookmark id="test-bookmark" />`);
    const bookmark = page.locator("#test-bookmark");
    await expect(bookmark).toHaveCount(1);
  });

  test("renders children", async ({ initTestBed, page }) => {
    await initTestBed(`
      <Bookmark id="test-bookmark">
        <Text>Bookmark content</Text>
      </Bookmark>
    `);
    const bookmark = page.locator("#test-bookmark");
    await expect(bookmark).toBeVisible();
    await expect(bookmark).toContainText("Bookmark content");
  });

  test("renders children without id", async ({ initTestBed, page }) => {
    await initTestBed(`<Bookmark>Content without id</Bookmark>`);
    await expect(page.getByText("Content without id")).toBeVisible();
  });

  // =============================================================================
  // DOCUMENTATION USAGE PATTERNS
  // =============================================================================

  test.describe("Documentation Usage Patterns", () => {
    test("links navigate to standalone bookmarks", async ({ initTestBed, page }) => {
      // Based on documentation example with standalone bookmarks and adjacent content
      await initTestBed(`
        <VStack height="600px" gap="100px">
          <Link to="#red-section">Jump to red</Link>
          <Link to="#green-section">Jump to green</Link>
          <Bookmark id="red-section" />
          <VStack height="700px" backgroundColor="red">Red content</VStack>
          <Bookmark id="green-section" />
          <VStack height="700px" backgroundColor="green">Green content</VStack>
        </VStack>
      `);

      const redLink = page.getByRole("link", { name: "Jump to red" });
      const greenLink = page.getByRole("link", { name: "Jump to green" });

      const redContent = page.getByText("Red content");
      const greenContent = page.getByText("Green content");

      await expect(redContent).toBeInViewport();
      await expect(greenContent).not.toBeInViewport();

      await greenLink.click();
      await page.waitForURL(/#green-section$/);
      await expect(redContent).not.toBeInViewport();
      await expect(greenContent).toBeInViewport();

      await redLink.click();
      await page.waitForURL(/#red-section$/);
      await expect(redContent).toBeInViewport();
      await expect(greenContent).not.toBeInViewport();
    });

    test("links navigate to nested bookmarks", async ({ initTestBed, page }) => {
      // Based on documentation example with standalone bookmarks and adjacent content
      await initTestBed(`
        <VStack height="600px" gap="100px">
          <Link to="#red-section">Jump to red</Link>
          <Link to="#green-section">Jump to green</Link>
          <Bookmark id="red-section" >
            <VStack height="700px" backgroundColor="red">Red content</VStack>
          </Bookmark>
          <Bookmark id="green-section" >
            <VStack height="700px" backgroundColor="green">Green content</VStack>
          </Bookmark>
        </VStack>
      `);

      const redLink = page.getByRole("link", { name: "Jump to red" });
      const greenLink = page.getByRole("link", { name: "Jump to green" });

      const redContent = page.getByText("Red content");
      const greenContent = page.getByText("Green content");

      await expect(redContent).toBeInViewport();
      await expect(greenContent).not.toBeInViewport();

      await greenLink.click();
      await page.waitForURL(/#green-section$/);
      await expect(redContent).not.toBeInViewport();
      await expect(greenContent).toBeInViewport();

      await redLink.click();
      await page.waitForURL(/#red-section$/);
      await expect(redContent).toBeInViewport();
      await expect(greenContent).not.toBeInViewport();
    });
  });

  // =============================================================================
  // ID PROPERTY TESTS
  // =============================================================================

  test.describe("id property", () => {
    test("handles special characters in id", async ({ initTestBed, page }) => {
      await initTestBed(`<Bookmark id="bookmark-with_special.chars" />`);
      const anchor = page.locator('[id="bookmark-with_special.chars"]');
      await expect(anchor).toHaveCount(1);
    });

    test("handles unicode characters in id", async ({ initTestBed, page }) => {
      await initTestBed(`<Bookmark id="书签-émojis🚀" />`);
      const anchor = page.locator('[id="书签-émojis🚀"]');
      await expect(anchor).toHaveCount(1);
    });

    test("handles null id gracefully", async ({ initTestBed, page }) => {
      await initTestBed(`<Bookmark id="{null}">Content</Bookmark>`);
      await expect(page.getByText("Content")).toBeVisible();
    });

    test("handles undefined id gracefully", async ({ initTestBed, page }) => {
      await initTestBed(`<Bookmark id="{undefined}">Content</Bookmark>`);
      await expect(page.getByText("Content")).toBeVisible();
    });

    test("handles object id gracefully", async ({ initTestBed, page }) => {
      await initTestBed(`<Bookmark id="{{a: 1}}">Content</Bookmark>`);
      const anchor = page.locator('[id="[object Object]"]');
      await expect(anchor).toHaveCount(1);
    });
  });

  // =============================================================================
  // SCROLL INTO VIEW API TESTS
  // =============================================================================

  test.describe("scrollIntoView API", () => {
    test("scrollIntoView works in scrollable container", async ({ initTestBed, page }) => {
      await initTestBed(`
        <VStack height="300px">
          <Button onClick="target.scrollIntoView()" >Scroll to Target</Button>
          <VStack height="700px" backgroundColor="lightblue">Top spacer</VStack>
          <Bookmark id="target" ref="bookmarkRef">Target content</Bookmark>
        </VStack>
      `);

      const bookmark = page.locator("#target");
      await expect(bookmark).not.toBeInViewport();

      const button = page.getByRole("button", { name: "Scroll to Target" });
      await button.click();

      await expect(bookmark).toBeInViewport();
    });
  });
});

// =============================================================================
// ACCESSIBILITY TESTS
// =============================================================================

test.describe("Accessibility", () => {
  test("supports keyboard navigation to content", async ({ initTestBed, page }) => {
    await initTestBed(`
      <Bookmark id="keyboard-test">
        <Button>Focusable Content</Button>
      </Bookmark>
    `);

    await page.keyboard.press("Tab");
    const button = page.getByRole("button", { name: "Focusable Content" });
    await expect(button).toBeFocused();
  });
});

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

test.describe("Other Edge Cases", () => {
  test("links navigate to bookmarks with 'null' other props", async ({ initTestBed, page }) => {
    await initTestBed(`
      <VStack height="600px">
        <Link to="#green-section">Jump to green</Link>
        <VStack height="700px" backgroundColor="red">Red content</VStack>
        <Bookmark id="green-section" level="{null}" title="{null}" omitFromToc="{null}" />
        <VStack height="700px" backgroundColor="green">Green content</VStack>
      </VStack>
    `);

    const greenContent = page.getByText("Green content");
    await expect(greenContent).not.toBeInViewport();

    const greenLink = page.getByRole("link", { name: "Jump to green" });
    await greenLink.click();

    await page.waitForURL(/#green-section$/);
    await expect(greenContent).toBeInViewport();
  });

  test("links navigate to bookmarks with valid other props", async ({ initTestBed, page }) => {
    await initTestBed(`
      <VStack height="600px">
        <Link to="#green-section">Jump to green</Link>
        <VStack height="700px" backgroundColor="red">Red content</VStack>
        <Bookmark id="green-section" level="{50}" title="green content section" omitFromToc="{true}" />
        <VStack height="700px" backgroundColor="green">Green content</VStack>
      </VStack>
    `);

    const greenContent = page.getByText("Green content");
    await expect(greenContent).not.toBeInViewport();

    const greenLink = page.getByRole("link", { name: "Jump to green" });
    await greenLink.click();

    await page.waitForURL(/#green-section$/);
    await expect(greenContent).toBeInViewport();
  });

  test("links navigate to bookmarks with empty children", async ({ initTestBed, page }) => {
    await initTestBed(`
      <VStack height="600px">
        <Link to="#green-section">Jump to green</Link>
        <VStack height="700px" backgroundColor="red">Red content</VStack>
        <Bookmark id="green-section" level="{50}" title="green content section" omitFromToc="{true}" ></Bookmark>
        <VStack height="700px" backgroundColor="green">Green content</VStack>
      </VStack>
    `);

    const greenContent = page.getByText("Green content");
    await expect(greenContent).not.toBeInViewport();

    const greenLink = page.getByRole("link", { name: "Jump to green" });
    await greenLink.click();

    await page.waitForURL(/#green-section$/);
    await expect(greenContent).toBeInViewport();
  });

  test("navigates to dynamic 'id' prop", async ({ initTestBed, page }) => {
    await initTestBed(`
      <VStack var.dynId="initial-id" height="600px">
        <Link to="#green-section">Jump to green</Link>
        <Button onClick="dynId = 'green-section'">Set green section id</Button>
        <VStack height="700px" backgroundColor="red">Red content</VStack>
        <Bookmark id="{dynId}" />
        <VStack height="700px" backgroundColor="green">Green content</VStack>
      </VStack>
    `);

    const greenContent = page.getByText("Green content");
    await expect(greenContent).not.toBeInViewport();

    await page.getByRole("button", { name: "Set green section id" }).click();

    const greenLink = page.getByRole("link", { name: "Jump to green" });
    await greenLink.click();

    await page.waitForURL(/#green-section$/);
    await expect(greenContent).toBeInViewport();
  });
});

```
Page 41/141FirstPrevNextLast