This is page 3 of 137. Use http://codebase.md/xmlui-org/xmlui/tools/vscode/resources/xmlui-markup-syntax-highlighting.png?lines=false&page={x} to view the full context. # Directory Structure ``` ├── .changeset │ ├── cold-items-taste.md │ ├── config.json │ ├── empty-spiders-dress.md │ ├── shy-windows-allow.md │ ├── sour-coins-read.md │ ├── tame-zebras-invite.md │ ├── three-ideas-invent.md │ ├── twenty-jeans-watch.md │ ├── warm-spies-melt.md │ └── whole-ways-cry.md ├── .eslintrc.cjs ├── .github │ ├── build-checklist.png │ ├── ISSUE_TEMPLATE │ │ ├── bug_report.md │ │ └── feature_request.md │ └── workflows │ ├── deploy-docs-optimized.yml │ ├── deploy-docs.yml │ ├── prepare-versions.yml │ ├── release-packages.yml │ ├── run-all-tests.yml │ └── run-smoke-tests.yml ├── .gitignore ├── .prettierrc.js ├── .vscode │ ├── launch.json │ └── settings.json ├── blog │ ├── .gitignore │ ├── .gitkeep │ ├── CHANGELOG.md │ ├── extensions.ts │ ├── index.html │ ├── index.ts │ ├── package.json │ ├── public │ │ ├── blog │ │ │ ├── images │ │ │ │ ├── blog-page-component.png │ │ │ │ ├── blog-scrabble.png │ │ │ │ ├── integrated-blog-search.png │ │ │ │ └── lorem-ipsum.png │ │ │ ├── lorem-ipsum.md │ │ │ ├── newest-post.md │ │ │ ├── older-post.md │ │ │ └── welcome-to-the-xmlui-blog.md │ │ ├── mockServiceWorker.js │ │ ├── resources │ │ │ ├── favicon.ico │ │ │ ├── files │ │ │ │ └── for-download │ │ │ │ └── xmlui │ │ │ │ └── xmlui-standalone.umd.js │ │ │ ├── github.svg │ │ │ ├── llms.txt │ │ │ ├── logo-dark.svg │ │ │ ├── logo.svg │ │ │ ├── pg-popout.svg │ │ │ └── xmlui-logo.svg │ │ ├── serve.json │ │ └── web.config │ ├── scripts │ │ ├── download-latest-xmlui.js │ │ ├── generate-rss.js │ │ ├── get-releases.js │ │ └── utils.js │ ├── src │ │ ├── components │ │ │ ├── BlogOverview.xmlui │ │ │ ├── BlogPage.xmlui │ │ │ └── PageNotFound.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 ├── CONTRIBUTING.md ├── docs │ ├── .gitignore │ ├── CHANGELOG.md │ ├── ComponentRefLinks.txt │ ├── content │ │ ├── _meta.json │ │ ├── components │ │ │ ├── _meta.json │ │ │ ├── _overview.md │ │ │ ├── APICall.md │ │ │ ├── App.md │ │ │ ├── AppHeader.md │ │ │ ├── AppState.md │ │ │ ├── AutoComplete.md │ │ │ ├── Avatar.md │ │ │ ├── Backdrop.md │ │ │ ├── Badge.md │ │ │ ├── BarChart.md │ │ │ ├── Bookmark.md │ │ │ ├── Breakout.md │ │ │ ├── Button.md │ │ │ ├── Card.md │ │ │ ├── Carousel.md │ │ │ ├── ChangeListener.md │ │ │ ├── Checkbox.md │ │ │ ├── CHStack.md │ │ │ ├── ColorPicker.md │ │ │ ├── Column.md │ │ │ ├── ContentSeparator.md │ │ │ ├── CVStack.md │ │ │ ├── DataSource.md │ │ │ ├── DateInput.md │ │ │ ├── DatePicker.md │ │ │ ├── DonutChart.md │ │ │ ├── DropdownMenu.md │ │ │ ├── EmojiSelector.md │ │ │ ├── ExpandableItem.md │ │ │ ├── FileInput.md │ │ │ ├── FileUploadDropZone.md │ │ │ ├── FlowLayout.md │ │ │ ├── Footer.md │ │ │ ├── Form.md │ │ │ ├── FormItem.md │ │ │ ├── FormSection.md │ │ │ ├── Fragment.md │ │ │ ├── H1.md │ │ │ ├── H2.md │ │ │ ├── H3.md │ │ │ ├── H4.md │ │ │ ├── H5.md │ │ │ ├── H6.md │ │ │ ├── Heading.md │ │ │ ├── HSplitter.md │ │ │ ├── HStack.md │ │ │ ├── Icon.md │ │ │ ├── IFrame.md │ │ │ ├── Image.md │ │ │ ├── Items.md │ │ │ ├── LabelList.md │ │ │ ├── Legend.md │ │ │ ├── LineChart.md │ │ │ ├── Link.md │ │ │ ├── List.md │ │ │ ├── Logo.md │ │ │ ├── Markdown.md │ │ │ ├── MenuItem.md │ │ │ ├── MenuSeparator.md │ │ │ ├── ModalDialog.md │ │ │ ├── NavGroup.md │ │ │ ├── NavLink.md │ │ │ ├── NavPanel.md │ │ │ ├── NoResult.md │ │ │ ├── NumberBox.md │ │ │ ├── Option.md │ │ │ ├── Page.md │ │ │ ├── PageMetaTitle.md │ │ │ ├── Pages.md │ │ │ ├── Pagination.md │ │ │ ├── PasswordInput.md │ │ │ ├── PieChart.md │ │ │ ├── ProgressBar.md │ │ │ ├── Queue.md │ │ │ ├── RadioGroup.md │ │ │ ├── RealTimeAdapter.md │ │ │ ├── Redirect.md │ │ │ ├── Select.md │ │ │ ├── Slider.md │ │ │ ├── Slot.md │ │ │ ├── SpaceFiller.md │ │ │ ├── Spinner.md │ │ │ ├── Splitter.md │ │ │ ├── Stack.md │ │ │ ├── StickyBox.md │ │ │ ├── SubMenuItem.md │ │ │ ├── Switch.md │ │ │ ├── TabItem.md │ │ │ ├── Table.md │ │ │ ├── TableOfContents.md │ │ │ ├── Tabs.md │ │ │ ├── Text.md │ │ │ ├── TextArea.md │ │ │ ├── TextBox.md │ │ │ ├── Theme.md │ │ │ ├── TimeInput.md │ │ │ ├── Timer.md │ │ │ ├── ToneChangerButton.md │ │ │ ├── ToneSwitch.md │ │ │ ├── Tooltip.md │ │ │ ├── Tree.md │ │ │ ├── VSplitter.md │ │ │ ├── VStack.md │ │ │ ├── xmlui-animations │ │ │ │ ├── _meta.json │ │ │ │ ├── _overview.md │ │ │ │ ├── Animation.md │ │ │ │ ├── FadeAnimation.md │ │ │ │ ├── FadeInAnimation.md │ │ │ │ ├── FadeOutAnimation.md │ │ │ │ ├── ScaleAnimation.md │ │ │ │ └── SlideInAnimation.md │ │ │ ├── xmlui-pdf │ │ │ │ ├── _meta.json │ │ │ │ ├── _overview.md │ │ │ │ └── Pdf.md │ │ │ ├── xmlui-spreadsheet │ │ │ │ ├── _meta.json │ │ │ │ ├── _overview.md │ │ │ │ └── Spreadsheet.md │ │ │ └── xmlui-website-blocks │ │ │ ├── _meta.json │ │ │ ├── _overview.md │ │ │ ├── Carousel.md │ │ │ ├── HelloMd.md │ │ │ ├── HeroSection.md │ │ │ └── ScrollToTop.md │ │ └── extensions │ │ ├── _meta.json │ │ ├── xmlui-animations │ │ │ ├── _meta.json │ │ │ ├── _overview.md │ │ │ ├── Animation.md │ │ │ ├── FadeAnimation.md │ │ │ ├── FadeInAnimation.md │ │ │ ├── FadeOutAnimation.md │ │ │ ├── ScaleAnimation.md │ │ │ └── SlideInAnimation.md │ │ └── xmlui-website-blocks │ │ ├── _meta.json │ │ ├── _overview.md │ │ ├── Carousel.md │ │ ├── HelloMd.md │ │ ├── HeroSection.md │ │ └── ScrollToTop.md │ ├── extensions.ts │ ├── index.html │ ├── index.ts │ ├── package.json │ ├── public │ │ ├── feed.rss │ │ ├── mockServiceWorker.js │ │ ├── pages │ │ │ ├── _meta.json │ │ │ ├── app-structure.md │ │ │ ├── build-editor-component.md │ │ │ ├── build-hello-world-component.md │ │ │ ├── components-intro.md │ │ │ ├── context-variables.md │ │ │ ├── forms.md │ │ │ ├── globals.md │ │ │ ├── glossary.md │ │ │ ├── helper-tags.md │ │ │ ├── hosted-deployment.md │ │ │ ├── howto │ │ │ │ ├── assign-a-complex-json-literal-to-a-component-variable.md │ │ │ │ ├── chain-a-refetch.md │ │ │ │ ├── debug-a-component.md │ │ │ │ ├── delay-a-datasource-until-another-datasource-is-ready.md │ │ │ │ ├── delegate-a-method.md │ │ │ │ ├── do-custom-form-validation.md │ │ │ │ ├── expose-a-method-from-a-component.md │ │ │ │ ├── filter-and-transform-data-from-an-api.md │ │ │ │ ├── group-items-in-list-by-a-property.md │ │ │ │ ├── handle-background-operations.md │ │ │ │ ├── hide-an-element-until-its-datasource-is-ready.md │ │ │ │ ├── make-a-set-of-equal-width-cards.md │ │ │ │ ├── make-a-table-responsive.md │ │ │ │ ├── modify-a-value-reported-in-a-column.md │ │ │ │ ├── paginate-a-list.md │ │ │ │ ├── pass-data-to-a-modal-dialog.md │ │ │ │ ├── react-to-button-click-not-keystrokes.md │ │ │ │ ├── set-the-initial-value-of-a-select-from-fetched-data.md │ │ │ │ ├── share-a-modaldialog-across-components.md │ │ │ │ ├── sync-selections-between-table-and-list-views.md │ │ │ │ ├── update-ui-optimistically.md │ │ │ │ ├── use-built-in-form-validation.md │ │ │ │ └── use-the-same-modaldialog-to-add-or-edit.md │ │ │ ├── howto.md │ │ │ ├── intro.md │ │ │ ├── layout.md │ │ │ ├── markup.md │ │ │ ├── mcp.md │ │ │ ├── modal-dialogs.md │ │ │ ├── news-and-reviews.md │ │ │ ├── reactive-intro.md │ │ │ ├── refactoring.md │ │ │ ├── routing-and-links.md │ │ │ ├── samples │ │ │ │ ├── color-palette.xmlui │ │ │ │ ├── color-values.xmlui │ │ │ │ ├── shadow-sizes.xmlui │ │ │ │ ├── spacing-sizes.xmlui │ │ │ │ ├── swatch.xmlui │ │ │ │ ├── theme-gallery-brief.xmlui │ │ │ │ └── theme-gallery.xmlui │ │ │ ├── scoping.md │ │ │ ├── scripting.md │ │ │ ├── styles-and-themes │ │ │ │ ├── common-units.md │ │ │ │ ├── layout-props.md │ │ │ │ ├── theme-variable-defaults.md │ │ │ │ ├── theme-variables.md │ │ │ │ └── themes.md │ │ │ ├── template-properties.md │ │ │ ├── test.md │ │ │ ├── tutorial-01.md │ │ │ ├── tutorial-02.md │ │ │ ├── tutorial-03.md │ │ │ ├── tutorial-04.md │ │ │ ├── tutorial-05.md │ │ │ ├── tutorial-06.md │ │ │ ├── tutorial-07.md │ │ │ ├── tutorial-08.md │ │ │ ├── tutorial-09.md │ │ │ ├── tutorial-10.md │ │ │ ├── tutorial-11.md │ │ │ ├── tutorial-12.md │ │ │ ├── universal-properties.md │ │ │ ├── user-defined-components.md │ │ │ ├── vscode.md │ │ │ ├── working-with-markdown.md │ │ │ ├── working-with-text.md │ │ │ ├── xmlui-animations │ │ │ │ ├── _meta.json │ │ │ │ ├── _overview.md │ │ │ │ ├── Animation.md │ │ │ │ ├── FadeAnimation.md │ │ │ │ ├── FadeInAnimation.md │ │ │ │ ├── FadeOutAnimation.md │ │ │ │ ├── ScaleAnimation.md │ │ │ │ └── SlideInAnimation.md │ │ │ ├── xmlui-charts │ │ │ │ ├── _meta.json │ │ │ │ ├── _overview.md │ │ │ │ ├── BarChart.md │ │ │ │ ├── DonutChart.md │ │ │ │ ├── LabelList.md │ │ │ │ ├── Legend.md │ │ │ │ ├── LineChart.md │ │ │ │ └── PieChart.md │ │ │ ├── xmlui-pdf │ │ │ │ ├── _meta.json │ │ │ │ ├── _overview.md │ │ │ │ └── Pdf.md │ │ │ └── xmlui-spreadsheet │ │ │ ├── _meta.json │ │ │ ├── _overview.md │ │ │ └── Spreadsheet.md │ │ ├── resources │ │ │ ├── devdocs │ │ │ │ ├── debug-proxy-object-2.png │ │ │ │ ├── debug-proxy-object.png │ │ │ │ ├── table_editor_01.png │ │ │ │ ├── table_editor_02.png │ │ │ │ ├── table_editor_03.png │ │ │ │ ├── table_editor_04.png │ │ │ │ ├── table_editor_05.png │ │ │ │ ├── table_editor_06.png │ │ │ │ ├── table_editor_07.png │ │ │ │ ├── table_editor_08.png │ │ │ │ ├── table_editor_09.png │ │ │ │ ├── table_editor_10.png │ │ │ │ ├── table_editor_11.png │ │ │ │ ├── table-editor-01.png │ │ │ │ ├── table-editor-02.png │ │ │ │ ├── table-editor-03.png │ │ │ │ ├── table-editor-04.png │ │ │ │ ├── table-editor-06.png │ │ │ │ ├── table-editor-07.png │ │ │ │ ├── table-editor-08.png │ │ │ │ ├── table-editor-09.png │ │ │ │ └── xmlui-rendering-of-tiptap-markdown.png │ │ │ ├── favicon.ico │ │ │ ├── files │ │ │ │ ├── clients.json │ │ │ │ ├── daily-revenue.json │ │ │ │ ├── dashboard-stats.json │ │ │ │ ├── demo.xmlui │ │ │ │ ├── demo.xmlui.xs │ │ │ │ ├── downloads │ │ │ │ │ └── downloads.json │ │ │ │ ├── for-download │ │ │ │ │ ├── index-with-api.html │ │ │ │ │ ├── index.html │ │ │ │ │ ├── mockApi.js │ │ │ │ │ ├── start-darwin.sh │ │ │ │ │ ├── start-linux.sh │ │ │ │ │ ├── start.bat │ │ │ │ │ └── xmlui │ │ │ │ │ └── xmlui-standalone.umd.js │ │ │ │ ├── getting-started │ │ │ │ │ ├── cl-tutorial-final.zip │ │ │ │ │ ├── cl-tutorial.zip │ │ │ │ │ ├── cl-tutorial2.zip │ │ │ │ │ ├── cl-tutorial3.zip │ │ │ │ │ ├── cl-tutorial4.zip │ │ │ │ │ ├── cl-tutorial5.zip │ │ │ │ │ ├── cl-tutorial6.zip │ │ │ │ │ ├── getting-started.zip │ │ │ │ │ ├── hello-xmlui.zip │ │ │ │ │ ├── xmlui-empty.zip │ │ │ │ │ └── xmlui-starter.zip │ │ │ │ ├── howto │ │ │ │ │ └── component-icons │ │ │ │ │ └── up-arrow.svg │ │ │ │ ├── invoices.json │ │ │ │ ├── monthly-status.json │ │ │ │ ├── news-and-reviews.json │ │ │ │ ├── products.json │ │ │ │ ├── releases.json │ │ │ │ ├── tutorials │ │ │ │ │ ├── datasource │ │ │ │ │ │ └── api.ts │ │ │ │ │ └── p2do │ │ │ │ │ ├── api.ts │ │ │ │ │ └── todo-logo.svg │ │ │ │ └── xmlui.json │ │ │ ├── github.svg │ │ │ ├── images │ │ │ │ ├── apiaction-tutorial │ │ │ │ │ ├── add-success.png │ │ │ │ │ ├── apiaction-param.png │ │ │ │ │ ├── change-completed.png │ │ │ │ │ ├── change-in-progress.png │ │ │ │ │ ├── confirm-delete.png │ │ │ │ │ ├── data-error.png │ │ │ │ │ ├── data-progress.png │ │ │ │ │ ├── data-success.png │ │ │ │ │ ├── display-1.png │ │ │ │ │ ├── item-deleted.png │ │ │ │ │ ├── item-updated.png │ │ │ │ │ ├── missing-api-key.png │ │ │ │ │ ├── new-item-added.png │ │ │ │ │ └── test-message.png │ │ │ │ ├── chat-api │ │ │ │ │ └── domain-model.svg │ │ │ │ ├── components │ │ │ │ │ ├── image │ │ │ │ │ │ └── breakfast.jpg │ │ │ │ │ ├── markdown │ │ │ │ │ │ └── colors.png │ │ │ │ │ └── modal │ │ │ │ │ ├── deep_link_dialog_1.jpg │ │ │ │ │ └── deep_link_dialog_2.jpg │ │ │ │ ├── create-apps │ │ │ │ │ ├── collapsed-vertical.png │ │ │ │ │ ├── using-forms-warning-dialog.png │ │ │ │ │ └── using-forms.png │ │ │ │ ├── datasource-tutorial │ │ │ │ │ ├── data-with-header.png │ │ │ │ │ ├── filtered-data.png │ │ │ │ │ ├── filtered-items.png │ │ │ │ │ ├── initial-page-items.png │ │ │ │ │ ├── list-items.png │ │ │ │ │ ├── next-page-items.png │ │ │ │ │ ├── no-data.png │ │ │ │ │ ├── pagination-1.jpg │ │ │ │ │ ├── pagination-1.png │ │ │ │ │ ├── polling-1.png │ │ │ │ │ ├── refetch-data.png │ │ │ │ │ ├── slow-loading.png │ │ │ │ │ ├── test-message.png │ │ │ │ │ ├── Thumbs.db │ │ │ │ │ ├── unconventional-data.png │ │ │ │ │ └── unfiltered-items.png │ │ │ │ ├── flower.jpg │ │ │ │ ├── get-started │ │ │ │ │ ├── add-new-contact.png │ │ │ │ │ ├── app-modified.png │ │ │ │ │ ├── app-start.png │ │ │ │ │ ├── app-with-boxes.png │ │ │ │ │ ├── app-with-toast.png │ │ │ │ │ ├── boilerplate-structure.png │ │ │ │ │ ├── cl-initial.png │ │ │ │ │ ├── cl-start.png │ │ │ │ │ ├── contact-counts.png │ │ │ │ │ ├── contact-dialog-title.png │ │ │ │ │ ├── contact-dialog.png │ │ │ │ │ ├── contact-menus.png │ │ │ │ │ ├── contact-predicates.png │ │ │ │ │ ├── context-menu.png │ │ │ │ │ ├── dashboard-numbers.png │ │ │ │ │ ├── default-contact-list.png │ │ │ │ │ ├── delete-contact.png │ │ │ │ │ ├── delete-task.png │ │ │ │ │ ├── detailed-template.png │ │ │ │ │ ├── edit-contact-details.png │ │ │ │ │ ├── edited-contact-saved.png │ │ │ │ │ ├── empty-sections.png │ │ │ │ │ ├── filter-completed.png │ │ │ │ │ ├── fullwidth-desktop.png │ │ │ │ │ ├── fullwidth-mobile.png │ │ │ │ │ ├── initial-table.png │ │ │ │ │ ├── items-and-badges.png │ │ │ │ │ ├── loading-message.png │ │ │ │ │ ├── new-contact-button.png │ │ │ │ │ ├── new-contact-saved.png │ │ │ │ │ ├── no-empty-sections.png │ │ │ │ │ ├── personal-todo-initial.png │ │ │ │ │ ├── piechart.png │ │ │ │ │ ├── review-today.png │ │ │ │ │ ├── rudimentary-dashboard.png │ │ │ │ │ ├── section-collapsed.png │ │ │ │ │ ├── sectioned-items.png │ │ │ │ │ ├── sections-ordered.png │ │ │ │ │ ├── spacex-list-with-links.png │ │ │ │ │ ├── spacex-list.png │ │ │ │ │ ├── start-personal-todo-1.png │ │ │ │ │ ├── submit-new-contact.png │ │ │ │ │ ├── submit-new-task.png │ │ │ │ │ ├── syntax-highlighting.png │ │ │ │ │ ├── table-with-badge.png │ │ │ │ │ ├── template-with-card.png │ │ │ │ │ ├── test-emulated-api.png │ │ │ │ │ ├── Thumbs.db │ │ │ │ │ ├── todo-logo.png │ │ │ │ │ └── xmlui-tools.png │ │ │ │ ├── HelloApp.png │ │ │ │ ├── HelloApp2.png │ │ │ │ ├── logos │ │ │ │ │ ├── xmlui1.svg │ │ │ │ │ ├── xmlui2.svg │ │ │ │ │ ├── xmlui3.svg │ │ │ │ │ ├── xmlui4.svg │ │ │ │ │ ├── xmlui5.svg │ │ │ │ │ ├── xmlui6.svg │ │ │ │ │ └── xmlui7.svg │ │ │ │ ├── pdf │ │ │ │ │ └── dummy-pdf.jpg │ │ │ │ ├── rendering-engine │ │ │ │ │ ├── AppEngine-flow.svg │ │ │ │ │ ├── Component.svg │ │ │ │ │ ├── CompoundComponent.svg │ │ │ │ │ ├── RootComponent.svg │ │ │ │ │ └── tree-with-containers.svg │ │ │ │ ├── reviewers-guide │ │ │ │ │ ├── AppEngine-flow.svg │ │ │ │ │ └── incbutton-in-action.png │ │ │ │ ├── tools │ │ │ │ │ └── boilerplate-structure.png │ │ │ │ ├── try.svg │ │ │ │ ├── tutorial │ │ │ │ │ ├── app-chat-history.png │ │ │ │ │ ├── app-content-placeholder.png │ │ │ │ │ ├── app-header-and-content.png │ │ │ │ │ ├── app-links-channel-selected.png │ │ │ │ │ ├── app-links-click.png │ │ │ │ │ ├── app-navigation.png │ │ │ │ │ ├── finished-ex01.png │ │ │ │ │ ├── finished-ex02.png │ │ │ │ │ ├── hello.png │ │ │ │ │ ├── splash-screen-advanced.png │ │ │ │ │ ├── splash-screen-after-click.png │ │ │ │ │ ├── splash-screen-centered.png │ │ │ │ │ ├── splash-screen-events.png │ │ │ │ │ ├── splash-screen-expression.png │ │ │ │ │ ├── splash-screen-reuse-after.png │ │ │ │ │ ├── splash-screen-reuse-before.png │ │ │ │ │ └── splash-screen.png │ │ │ │ └── tutorial-01.png │ │ │ ├── llms.txt │ │ │ ├── logo-dark.svg │ │ │ ├── logo.svg │ │ │ ├── pg-popout.svg │ │ │ └── xmlui-logo.svg │ │ ├── serve.json │ │ └── web.config │ ├── scripts │ │ ├── download-latest-xmlui.js │ │ ├── generate-rss.js │ │ ├── get-releases.js │ │ └── utils.js │ ├── src │ │ ├── components │ │ │ ├── BlogOverview.xmlui │ │ │ ├── BlogPage.xmlui │ │ │ ├── Boxes.xmlui │ │ │ ├── Breadcrumb.xmlui │ │ │ ├── ChangeLog.xmlui │ │ │ ├── ColorPalette.xmlui │ │ │ ├── DocumentLinks.xmlui │ │ │ ├── DocumentPage.xmlui │ │ │ ├── DocumentPageNoTOC.xmlui │ │ │ ├── Icons.xmlui │ │ │ ├── IncButton.xmlui │ │ │ ├── IncButton2.xmlui │ │ │ ├── NameValue.xmlui │ │ │ ├── PageNotFound.xmlui │ │ │ ├── PaletteItem.xmlui │ │ │ ├── Palettes.xmlui │ │ │ ├── SectionHeader.xmlui │ │ │ ├── TBD.xmlui │ │ │ ├── Test.xmlui │ │ │ ├── ThemesIntro.xmlui │ │ │ ├── ThousandThemes.xmlui │ │ │ ├── TubeStops.xmlui │ │ │ ├── TubeStops.xmlui.xs │ │ │ └── TwoColumnCode.xmlui │ │ ├── config.ts │ │ ├── Main.xmlui │ │ └── themes │ │ ├── docs-theme.ts │ │ ├── earthtone.ts │ │ ├── xmlui-gray-on-default.ts │ │ ├── xmlui-green-on-default.ts │ │ └── xmlui-orange-on-default.ts │ └── tsconfig.json ├── LICENSE ├── package-lock.json ├── package.json ├── packages │ ├── xmlui-animations │ │ ├── .gitignore │ │ ├── CHANGELOG.md │ │ ├── demo │ │ │ └── Main.xmlui │ │ ├── index.html │ │ ├── index.ts │ │ ├── meta │ │ │ └── componentsMetadata.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── Animation.tsx │ │ │ ├── AnimationNative.tsx │ │ │ ├── FadeAnimation.tsx │ │ │ ├── FadeInAnimation.tsx │ │ │ ├── FadeOutAnimation.tsx │ │ │ ├── index.tsx │ │ │ ├── ScaleAnimation.tsx │ │ │ └── SlideInAnimation.tsx │ │ └── tsconfig.json │ ├── xmlui-devtools │ │ ├── .gitignore │ │ ├── CHANGELOG.md │ │ ├── demo │ │ │ └── Main.xmlui │ │ ├── index.html │ │ ├── index.ts │ │ ├── meta │ │ │ └── componentsMetadata.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── devtools │ │ │ │ ├── DevTools.tsx │ │ │ │ ├── DevToolsNative.module.scss │ │ │ │ ├── DevToolsNative.tsx │ │ │ │ ├── ModalDialog.module.scss │ │ │ │ ├── ModalDialog.tsx │ │ │ │ ├── ModalVisibilityContext.tsx │ │ │ │ ├── Tooltip.module.scss │ │ │ │ ├── Tooltip.tsx │ │ │ │ └── utils.ts │ │ │ ├── editor │ │ │ │ └── Editor.tsx │ │ │ └── index.tsx │ │ ├── tsconfig.json │ │ └── vite.config-overrides.ts │ ├── xmlui-hello-world │ │ ├── .gitignore │ │ ├── index.ts │ │ ├── meta │ │ │ └── componentsMetadata.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── HelloWorld.module.scss │ │ │ ├── HelloWorld.tsx │ │ │ ├── HelloWorldNative.tsx │ │ │ └── index.tsx │ │ └── tsconfig.json │ ├── xmlui-os-frames │ │ ├── .gitignore │ │ ├── demo │ │ │ └── Main.xmlui │ │ ├── index.html │ │ ├── index.ts │ │ ├── meta │ │ │ └── componentsMetadata.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── index.tsx │ │ │ ├── IPhoneFrame.module.scss │ │ │ ├── IPhoneFrame.tsx │ │ │ ├── MacOSAppFrame.module.scss │ │ │ ├── MacOSAppFrame.tsx │ │ │ ├── WindowsAppFrame.module.scss │ │ │ └── WindowsAppFrame.tsx │ │ └── tsconfig.json │ ├── xmlui-pdf │ │ ├── .gitignore │ │ ├── CHANGELOG.md │ │ ├── demo │ │ │ ├── components │ │ │ │ └── Pdf.xmlui │ │ │ └── Main.xmlui │ │ ├── index.html │ │ ├── index.ts │ │ ├── meta │ │ │ └── componentsMetadata.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── index.tsx │ │ │ ├── LazyPdfNative.tsx │ │ │ ├── Pdf.module.scss │ │ │ └── Pdf.tsx │ │ └── tsconfig.json │ ├── xmlui-playground │ │ ├── .gitignore │ │ ├── CHANGELOG.md │ │ ├── demo │ │ │ └── Main.xmlui │ │ ├── index.html │ │ ├── index.ts │ │ ├── meta │ │ │ └── componentsMetadata.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── hooks │ │ │ │ ├── usePlayground.ts │ │ │ │ └── useToast.ts │ │ │ ├── index.tsx │ │ │ ├── playground │ │ │ │ ├── Box.module.scss │ │ │ │ ├── Box.tsx │ │ │ │ ├── CodeSelector.tsx │ │ │ │ ├── ConfirmationDialog.module.scss │ │ │ │ ├── ConfirmationDialog.tsx │ │ │ │ ├── Editor.tsx │ │ │ │ ├── Header.module.scss │ │ │ │ ├── Header.tsx │ │ │ │ ├── Playground.tsx │ │ │ │ ├── PlaygroundContent.module.scss │ │ │ │ ├── PlaygroundContent.tsx │ │ │ │ ├── PlaygroundNative.module.scss │ │ │ │ ├── PlaygroundNative.tsx │ │ │ │ ├── Preview.module.scss │ │ │ │ ├── Preview.tsx │ │ │ │ ├── Select.module.scss │ │ │ │ ├── StandalonePlayground.tsx │ │ │ │ ├── StandalonePlaygroundNative.module.scss │ │ │ │ ├── StandalonePlaygroundNative.tsx │ │ │ │ ├── ThemeSwitcher.module.scss │ │ │ │ ├── ThemeSwitcher.tsx │ │ │ │ ├── ToneSwitcher.tsx │ │ │ │ ├── Tooltip.module.scss │ │ │ │ ├── Tooltip.tsx │ │ │ │ └── utils.ts │ │ │ ├── providers │ │ │ │ ├── Toast.module.scss │ │ │ │ └── ToastProvider.tsx │ │ │ ├── state │ │ │ │ └── store.ts │ │ │ ├── themes │ │ │ │ └── theme.ts │ │ │ └── utils │ │ │ └── helpers.ts │ │ └── tsconfig.json │ ├── xmlui-search │ │ ├── .gitignore │ │ ├── CHANGELOG.md │ │ ├── demo │ │ │ └── Main.xmlui │ │ ├── index.html │ │ ├── index.ts │ │ ├── meta │ │ │ └── componentsMetadata.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── index.tsx │ │ │ ├── Search.module.scss │ │ │ └── Search.tsx │ │ └── tsconfig.json │ ├── xmlui-spreadsheet │ │ ├── .gitignore │ │ ├── demo │ │ │ └── Main.xmlui │ │ ├── index.html │ │ ├── index.ts │ │ ├── meta │ │ │ └── componentsMetadata.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── index.tsx │ │ │ ├── Spreadsheet.tsx │ │ │ └── SpreadsheetNative.tsx │ │ └── tsconfig.json │ └── xmlui-website-blocks │ ├── .gitignore │ ├── CHANGELOG.md │ ├── demo │ │ ├── components │ │ │ ├── HeroBackgroundBreakoutPage.xmlui │ │ │ ├── HeroBackgroundsPage.xmlui │ │ │ ├── HeroContentsPage.xmlui │ │ │ ├── HeroTextAlignPage.xmlui │ │ │ ├── HeroTextPage.xmlui │ │ │ └── HeroTonesPage.xmlui │ │ ├── Main.xmlui │ │ └── themes │ │ └── default.ts │ ├── index.html │ ├── index.ts │ ├── meta │ │ └── componentsMetadata.ts │ ├── package.json │ ├── public │ │ └── resources │ │ ├── building.jpg │ │ └── xmlui-logo.svg │ ├── src │ │ ├── Carousel │ │ │ ├── Carousel.module.scss │ │ │ ├── Carousel.tsx │ │ │ ├── CarouselContext.tsx │ │ │ └── CarouselNative.tsx │ │ ├── FancyButton │ │ │ ├── FancyButton.module.scss │ │ │ ├── FancyButton.tsx │ │ │ └── FancyButton.xmlui │ │ ├── Hello │ │ │ ├── Hello.tsx │ │ │ ├── Hello.xmlui │ │ │ └── Hello.xmlui.xs │ │ ├── HeroSection │ │ │ ├── HeroSection.module.scss │ │ │ ├── HeroSection.tsx │ │ │ └── HeroSectionNative.tsx │ │ ├── index.tsx │ │ ├── ScrollToTop │ │ │ ├── ScrollToTop.module.scss │ │ │ ├── ScrollToTop.tsx │ │ │ └── ScrollToTopNative.tsx │ │ └── vite-env.d.ts │ └── tsconfig.json ├── README.md ├── tools │ ├── codefence │ │ └── xmlui-code-fence-docs.md │ ├── create-app │ │ ├── .gitignore │ │ ├── CHANGELOG.md │ │ ├── create-app.ts │ │ ├── helpers │ │ │ ├── copy.ts │ │ │ ├── get-pkg-manager.ts │ │ │ ├── git.ts │ │ │ ├── install.ts │ │ │ ├── is-folder-empty.ts │ │ │ ├── is-writeable.ts │ │ │ ├── make-dir.ts │ │ │ └── validate-pkg.ts │ │ ├── index.ts │ │ ├── package.json │ │ ├── templates │ │ │ ├── default │ │ │ │ └── ts │ │ │ │ ├── gitignore │ │ │ │ ├── index.html │ │ │ │ ├── index.ts │ │ │ │ ├── public │ │ │ │ │ ├── mockServiceWorker.js │ │ │ │ │ ├── resources │ │ │ │ │ │ ├── favicon.ico │ │ │ │ │ │ └── xmlui-logo.svg │ │ │ │ │ └── serve.json │ │ │ │ └── src │ │ │ │ ├── components │ │ │ │ │ ├── ApiAware.xmlui │ │ │ │ │ ├── Home.xmlui │ │ │ │ │ ├── IncButton.xmlui │ │ │ │ │ └── PagePanel.xmlui │ │ │ │ ├── config.ts │ │ │ │ └── Main.xmlui │ │ │ ├── index.ts │ │ │ └── types.ts │ │ └── tsconfig.json │ ├── create-xmlui-hello-world │ │ ├── index.js │ │ └── package.json │ └── vscode │ ├── .gitignore │ ├── .vscode │ │ ├── launch.json │ │ └── tasks.json │ ├── .vscodeignore │ ├── build.sh │ ├── CHANGELOG.md │ ├── esbuild.js │ ├── eslint.config.mjs │ ├── formatter-docs.md │ ├── generate-test-sample.sh │ ├── LICENSE.md │ ├── package-lock.json │ ├── package.json │ ├── README.md │ ├── resources │ │ ├── xmlui-logo.png │ │ └── xmlui-markup-syntax-highlighting.png │ ├── src │ │ ├── extension.ts │ │ └── server.ts │ ├── syntaxes │ │ └── xmlui.tmLanguage.json │ ├── test-samples │ │ └── sample.xmlui │ ├── tsconfig.json │ └── tsconfig.tsbuildinfo ├── turbo.json └── xmlui ├── .gitignore ├── bin │ ├── bootstrap.js │ ├── build-lib.ts │ ├── build.ts │ ├── index.ts │ ├── preview.ts │ ├── start.ts │ ├── vite-xmlui-plugin.ts │ └── viteConfig.ts ├── CHANGELOG.md ├── conventions │ ├── component-qa-checklist.md │ ├── copilot-conventions.md │ ├── create-xmlui-components.md │ ├── mermaid.md │ ├── testing-conventions.md │ └── xmlui-in-a-nutshell.md ├── dev-docs │ ├── accessibility.md │ ├── actions.md │ ├── AppRoot.md │ ├── component-apis.md │ ├── component-rendering.md │ ├── component-review-checklist.md │ ├── containers.md │ ├── data-sources.md │ ├── e2e-summary.md │ ├── expression-evaluation.md │ ├── glossary.md │ ├── helper-components.md │ ├── index.md │ ├── loaders.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 │ ├── rendering-fundamentals.md │ ├── reusable-components.md │ ├── standalone-apps.md │ ├── state-management.md │ └── xmlui-extensibility.xlsx ├── package.json ├── playwright.config.ts ├── scripts │ ├── coverage-only.js │ ├── e2e-test-summary.js │ ├── generate-docs │ │ ├── build-downloads-map.mjs │ │ ├── build-pages-map.mjs │ │ ├── components-config.json │ │ ├── configuration-management.mjs │ │ ├── constants.mjs │ │ ├── create-theme-files.mjs │ │ ├── DocsGenerator.mjs │ │ ├── error-handling.mjs │ │ ├── extensions-config.json │ │ ├── folders.mjs │ │ ├── generate-summary-files.mjs │ │ ├── get-docs.mjs │ │ ├── input-handler.mjs │ │ ├── logger.mjs │ │ ├── logging-standards.mjs │ │ ├── MetadataProcessor.mjs │ │ ├── pattern-utilities.mjs │ │ └── utils.mjs │ ├── get-langserver-metadata.mjs │ ├── inline-links.mjs │ └── README-e2e-summary.md ├── src │ ├── abstractions │ │ ├── _conventions.md │ │ ├── ActionDefs.ts │ │ ├── AppContextDefs.ts │ │ ├── ComponentDefs.ts │ │ ├── ContainerDefs.ts │ │ ├── ExtensionDefs.ts │ │ ├── FunctionDefs.ts │ │ ├── RendererDefs.ts │ │ ├── scripting │ │ │ ├── BlockScope.ts │ │ │ ├── Compilation.ts │ │ │ ├── LogicalThread.ts │ │ │ ├── LoopScope.ts │ │ │ ├── modules.ts │ │ │ ├── ScriptParserError.ts │ │ │ ├── Token.ts │ │ │ ├── TryScope.ts │ │ │ └── TryScopeExp.ts │ │ └── ThemingDefs.ts │ ├── components │ │ ├── _conventions.md │ │ ├── abstractions.ts │ │ ├── Accordion │ │ │ ├── Accordion.md │ │ │ ├── Accordion.module.scss │ │ │ ├── Accordion.spec.ts │ │ │ ├── Accordion.tsx │ │ │ ├── AccordionContext.tsx │ │ │ ├── AccordionItem.tsx │ │ │ ├── AccordionItemNative.tsx │ │ │ └── AccordionNative.tsx │ │ ├── Animation │ │ │ └── AnimationNative.tsx │ │ ├── APICall │ │ │ ├── APICall.md │ │ │ ├── APICall.spec.ts │ │ │ ├── APICall.tsx │ │ │ └── APICallNative.tsx │ │ ├── App │ │ │ ├── App.md │ │ │ ├── App.module.scss │ │ │ ├── App.spec.ts │ │ │ ├── App.tsx │ │ │ ├── AppLayoutContext.ts │ │ │ ├── AppNative.tsx │ │ │ ├── AppStateContext.ts │ │ │ ├── doc-resources │ │ │ │ ├── condensed-sticky.xmlui │ │ │ │ ├── condensed.xmlui │ │ │ │ ├── horizontal-sticky.xmlui │ │ │ │ ├── horizontal.xmlui │ │ │ │ ├── vertical-full-header.xmlui │ │ │ │ ├── vertical-sticky.xmlui │ │ │ │ └── vertical.xmlui │ │ │ ├── IndexerContext.ts │ │ │ ├── LinkInfoContext.ts │ │ │ ├── SearchContext.tsx │ │ │ ├── Sheet.module.scss │ │ │ └── Sheet.tsx │ │ ├── AppHeader │ │ │ ├── AppHeader.md │ │ │ ├── AppHeader.module.scss │ │ │ ├── AppHeader.spec.ts │ │ │ ├── AppHeader.tsx │ │ │ └── AppHeaderNative.tsx │ │ ├── AppState │ │ │ ├── AppState.md │ │ │ ├── AppState.spec.ts │ │ │ ├── AppState.tsx │ │ │ └── AppStateNative.tsx │ │ ├── AutoComplete │ │ │ ├── AutoComplete.md │ │ │ ├── AutoComplete.module.scss │ │ │ ├── AutoComplete.spec.ts │ │ │ ├── AutoComplete.tsx │ │ │ ├── AutoCompleteContext.tsx │ │ │ └── AutoCompleteNative.tsx │ │ ├── Avatar │ │ │ ├── Avatar.md │ │ │ ├── Avatar.module.scss │ │ │ ├── Avatar.spec.ts │ │ │ ├── Avatar.tsx │ │ │ └── AvatarNative.tsx │ │ ├── Backdrop │ │ │ ├── Backdrop.md │ │ │ ├── Backdrop.module.scss │ │ │ ├── Backdrop.spec.ts │ │ │ ├── Backdrop.tsx │ │ │ └── BackdropNative.tsx │ │ ├── Badge │ │ │ ├── Badge.md │ │ │ ├── Badge.module.scss │ │ │ ├── Badge.spec.ts │ │ │ ├── Badge.tsx │ │ │ └── BadgeNative.tsx │ │ ├── Bookmark │ │ │ ├── Bookmark.md │ │ │ ├── Bookmark.module.scss │ │ │ ├── Bookmark.spec.ts │ │ │ ├── Bookmark.tsx │ │ │ └── BookmarkNative.tsx │ │ ├── Breakout │ │ │ ├── Breakout.module.scss │ │ │ ├── Breakout.spec.ts │ │ │ ├── Breakout.tsx │ │ │ └── BreakoutNative.tsx │ │ ├── Button │ │ │ ├── Button-style.spec.ts │ │ │ ├── Button.md │ │ │ ├── Button.module.scss │ │ │ ├── Button.spec.ts │ │ │ ├── Button.tsx │ │ │ └── ButtonNative.tsx │ │ ├── Card │ │ │ ├── Card.md │ │ │ ├── Card.module.scss │ │ │ ├── Card.spec.ts │ │ │ ├── Card.tsx │ │ │ └── CardNative.tsx │ │ ├── Carousel │ │ │ ├── Carousel.md │ │ │ ├── Carousel.module.scss │ │ │ ├── Carousel.spec.ts │ │ │ ├── Carousel.tsx │ │ │ ├── CarouselContext.tsx │ │ │ ├── CarouselItem.tsx │ │ │ ├── CarouselItemNative.tsx │ │ │ └── CarouselNative.tsx │ │ ├── ChangeListener │ │ │ ├── ChangeListener.md │ │ │ ├── ChangeListener.spec.ts │ │ │ ├── ChangeListener.tsx │ │ │ └── ChangeListenerNative.tsx │ │ ├── chart-color-schemes.ts │ │ ├── Charts │ │ │ ├── AreaChart │ │ │ │ ├── AreaChart.md │ │ │ │ ├── AreaChart.spec.ts │ │ │ │ ├── AreaChart.tsx │ │ │ │ └── AreaChartNative.tsx │ │ │ ├── BarChart │ │ │ │ ├── BarChart.md │ │ │ │ ├── BarChart.module.scss │ │ │ │ ├── BarChart.spec.ts │ │ │ │ ├── BarChart.tsx │ │ │ │ └── BarChartNative.tsx │ │ │ ├── DonutChart │ │ │ │ ├── DonutChart.spec.ts │ │ │ │ └── DonutChart.tsx │ │ │ ├── LabelList │ │ │ │ ├── LabelList.spec.ts │ │ │ │ ├── LabelList.tsx │ │ │ │ ├── LabelListNative.module.scss │ │ │ │ └── LabelListNative.tsx │ │ │ ├── Legend │ │ │ │ ├── Legend.spec.ts │ │ │ │ ├── Legend.tsx │ │ │ │ └── LegendNative.tsx │ │ │ ├── LineChart │ │ │ │ ├── LineChart.md │ │ │ │ ├── LineChart.module.scss │ │ │ │ ├── LineChart.spec.ts │ │ │ │ ├── LineChart.tsx │ │ │ │ └── LineChartNative.tsx │ │ │ ├── PieChart │ │ │ │ ├── PieChart.md │ │ │ │ ├── PieChart.spec.ts │ │ │ │ ├── PieChart.tsx │ │ │ │ ├── PieChartNative.module.scss │ │ │ │ └── PieChartNative.tsx │ │ │ ├── RadarChart │ │ │ │ ├── RadarChart.md │ │ │ │ ├── RadarChart.spec.ts │ │ │ │ ├── RadarChart.tsx │ │ │ │ └── RadarChartNative.tsx │ │ │ ├── Tooltip │ │ │ │ ├── TooltipContent.module.scss │ │ │ │ ├── TooltipContent.spec.ts │ │ │ │ └── TooltipContent.tsx │ │ │ └── utils │ │ │ ├── abstractions.ts │ │ │ └── ChartProvider.tsx │ │ ├── Checkbox │ │ │ ├── Checkbox.md │ │ │ ├── Checkbox.spec.ts │ │ │ └── Checkbox.tsx │ │ ├── CodeBlock │ │ │ ├── CodeBlock.module.scss │ │ │ ├── CodeBlock.spec.ts │ │ │ ├── CodeBlock.tsx │ │ │ ├── CodeBlockNative.tsx │ │ │ └── highlight-code.ts │ │ ├── collectedComponentMetadata.ts │ │ ├── ColorPicker │ │ │ ├── ColorPicker.md │ │ │ ├── ColorPicker.module.scss │ │ │ ├── ColorPicker.spec.ts │ │ │ ├── ColorPicker.tsx │ │ │ └── ColorPickerNative.tsx │ │ ├── Column │ │ │ ├── Column.md │ │ │ ├── Column.tsx │ │ │ ├── ColumnNative.tsx │ │ │ ├── doc-resources │ │ │ │ └── list-component-data.js │ │ │ └── TableContext.tsx │ │ ├── component-utils.ts │ │ ├── ComponentProvider.tsx │ │ ├── ComponentRegistryContext.tsx │ │ ├── container-helpers.tsx │ │ ├── ContentSeparator │ │ │ ├── ContentSeparator.md │ │ │ ├── ContentSeparator.module.scss │ │ │ ├── ContentSeparator.spec.ts │ │ │ ├── ContentSeparator.tsx │ │ │ └── ContentSeparatorNative.tsx │ │ ├── DataSource │ │ │ ├── DataSource.md │ │ │ └── DataSource.tsx │ │ ├── DateInput │ │ │ ├── DateInput.md │ │ │ ├── DateInput.module.scss │ │ │ ├── DateInput.spec.ts │ │ │ ├── DateInput.tsx │ │ │ └── DateInputNative.tsx │ │ ├── DatePicker │ │ │ ├── DatePicker.md │ │ │ ├── DatePicker.module.scss │ │ │ ├── DatePicker.spec.ts │ │ │ ├── DatePicker.tsx │ │ │ └── DatePickerNative.tsx │ │ ├── DropdownMenu │ │ │ ├── DropdownMenu.md │ │ │ ├── DropdownMenu.module.scss │ │ │ ├── DropdownMenu.spec.ts │ │ │ ├── DropdownMenu.tsx │ │ │ ├── DropdownMenuNative.tsx │ │ │ ├── MenuItem.md │ │ │ └── SubMenuItem.md │ │ ├── EmojiSelector │ │ │ ├── EmojiSelector.md │ │ │ ├── EmojiSelector.spec.ts │ │ │ ├── EmojiSelector.tsx │ │ │ └── EmojiSelectorNative.tsx │ │ ├── ExpandableItem │ │ │ ├── ExpandableItem.module.scss │ │ │ ├── ExpandableItem.spec.ts │ │ │ ├── ExpandableItem.tsx │ │ │ └── ExpandableItemNative.tsx │ │ ├── FileInput │ │ │ ├── FileInput.md │ │ │ ├── FileInput.module.scss │ │ │ ├── FileInput.spec.ts │ │ │ ├── FileInput.tsx │ │ │ └── FileInputNative.tsx │ │ ├── FileUploadDropZone │ │ │ ├── FileUploadDropZone.md │ │ │ ├── FileUploadDropZone.module.scss │ │ │ ├── FileUploadDropZone.spec.ts │ │ │ ├── FileUploadDropZone.tsx │ │ │ └── FileUploadDropZoneNative.tsx │ │ ├── FlowLayout │ │ │ ├── FlowLayout.md │ │ │ ├── FlowLayout.module.scss │ │ │ ├── FlowLayout.spec.ts │ │ │ ├── FlowLayout.spec.ts-snapshots │ │ │ │ └── Edge-cases-boxShadow-is-not-clipped-1-non-smoke-darwin.png │ │ │ ├── FlowLayout.tsx │ │ │ └── FlowLayoutNative.tsx │ │ ├── Footer │ │ │ ├── Footer.md │ │ │ ├── Footer.module.scss │ │ │ ├── Footer.spec.ts │ │ │ ├── Footer.tsx │ │ │ └── FooterNative.tsx │ │ ├── Form │ │ │ ├── Form.md │ │ │ ├── Form.module.scss │ │ │ ├── Form.spec.ts │ │ │ ├── Form.tsx │ │ │ ├── formActions.ts │ │ │ ├── FormContext.ts │ │ │ └── FormNative.tsx │ │ ├── FormItem │ │ │ ├── FormItem.md │ │ │ ├── FormItem.module.scss │ │ │ ├── FormItem.spec.ts │ │ │ ├── FormItem.tsx │ │ │ ├── FormItemNative.tsx │ │ │ ├── HelperText.module.scss │ │ │ ├── HelperText.tsx │ │ │ ├── ItemWithLabel.tsx │ │ │ └── Validations.ts │ │ ├── FormSection │ │ │ ├── FormSection.md │ │ │ ├── FormSection.ts │ │ │ └── FormSection.xmlui │ │ ├── Fragment │ │ │ ├── Fragment.spec.ts │ │ │ └── Fragment.tsx │ │ ├── Heading │ │ │ ├── abstractions.ts │ │ │ ├── H1.md │ │ │ ├── H1.spec.ts │ │ │ ├── H2.md │ │ │ ├── H2.spec.ts │ │ │ ├── H3.md │ │ │ ├── H3.spec.ts │ │ │ ├── H4.md │ │ │ ├── H4.spec.ts │ │ │ ├── H5.md │ │ │ ├── H5.spec.ts │ │ │ ├── H6.md │ │ │ ├── H6.spec.ts │ │ │ ├── Heading.md │ │ │ ├── Heading.module.scss │ │ │ ├── Heading.spec.ts │ │ │ ├── Heading.tsx │ │ │ └── HeadingNative.tsx │ │ ├── HoverCard │ │ │ ├── HoverCard.tsx │ │ │ └── HovercardNative.tsx │ │ ├── HtmlTags │ │ │ ├── HtmlTags.module.scss │ │ │ ├── HtmlTags.spec.ts │ │ │ └── HtmlTags.tsx │ │ ├── Icon │ │ │ ├── AdmonitionDanger.tsx │ │ │ ├── AdmonitionInfo.tsx │ │ │ ├── AdmonitionNote.tsx │ │ │ ├── AdmonitionTip.tsx │ │ │ ├── AdmonitionWarning.tsx │ │ │ ├── ApiIcon.tsx │ │ │ ├── ArrowDropDown.module.scss │ │ │ ├── ArrowDropDown.tsx │ │ │ ├── ArrowDropUp.module.scss │ │ │ ├── ArrowDropUp.tsx │ │ │ ├── ArrowLeft.module.scss │ │ │ ├── ArrowLeft.tsx │ │ │ ├── ArrowRight.module.scss │ │ │ ├── ArrowRight.tsx │ │ │ ├── Attach.tsx │ │ │ ├── Binding.module.scss │ │ │ ├── Binding.tsx │ │ │ ├── BoardIcon.tsx │ │ │ ├── BoxIcon.tsx │ │ │ ├── CheckIcon.tsx │ │ │ ├── ChevronDownIcon.tsx │ │ │ ├── ChevronLeft.tsx │ │ │ ├── ChevronRight.tsx │ │ │ ├── ChevronUpIcon.tsx │ │ │ ├── CodeFileIcon.tsx │ │ │ ├── CodeSandbox.tsx │ │ │ ├── CompactListIcon.tsx │ │ │ ├── ContentCopyIcon.tsx │ │ │ ├── DarkToLightIcon.tsx │ │ │ ├── DatabaseIcon.module.scss │ │ │ ├── DatabaseIcon.tsx │ │ │ ├── DocFileIcon.tsx │ │ │ ├── DocIcon.tsx │ │ │ ├── DotMenuHorizontalIcon.tsx │ │ │ ├── DotMenuIcon.tsx │ │ │ ├── EmailIcon.tsx │ │ │ ├── EmptyFolderIcon.tsx │ │ │ ├── ErrorIcon.tsx │ │ │ ├── ExpressionIcon.tsx │ │ │ ├── FillPlusCricleIcon.tsx │ │ │ ├── FilterIcon.tsx │ │ │ ├── FolderIcon.tsx │ │ │ ├── GlobeIcon.tsx │ │ │ ├── HomeIcon.tsx │ │ │ ├── HyperLinkIcon.tsx │ │ │ ├── Icon.md │ │ │ ├── Icon.module.scss │ │ │ ├── Icon.spec.ts │ │ │ ├── Icon.tsx │ │ │ ├── IconNative.tsx │ │ │ ├── ImageFileIcon.tsx │ │ │ ├── Inspect.tsx │ │ │ ├── LightToDark.tsx │ │ │ ├── LinkIcon.tsx │ │ │ ├── ListIcon.tsx │ │ │ ├── LooseListIcon.tsx │ │ │ ├── MoonIcon.tsx │ │ │ ├── MoreOptionsIcon.tsx │ │ │ ├── NoSortIcon.tsx │ │ │ ├── PDFIcon.tsx │ │ │ ├── PenIcon.tsx │ │ │ ├── PhoneIcon.tsx │ │ │ ├── PhotoIcon.tsx │ │ │ ├── PlusIcon.tsx │ │ │ ├── SearchIcon.tsx │ │ │ ├── ShareIcon.tsx │ │ │ ├── SortAscendingIcon.tsx │ │ │ ├── SortDescendingIcon.tsx │ │ │ ├── StarsIcon.tsx │ │ │ ├── SunIcon.tsx │ │ │ ├── svg │ │ │ │ ├── admonition_danger.svg │ │ │ │ ├── admonition_info.svg │ │ │ │ ├── admonition_note.svg │ │ │ │ ├── admonition_tip.svg │ │ │ │ ├── admonition_warning.svg │ │ │ │ ├── api.svg │ │ │ │ ├── arrow-dropdown.svg │ │ │ │ ├── arrow-left.svg │ │ │ │ ├── arrow-right.svg │ │ │ │ ├── arrow-up.svg │ │ │ │ ├── attach.svg │ │ │ │ ├── binding.svg │ │ │ │ ├── box.svg │ │ │ │ ├── bulb.svg │ │ │ │ ├── code-file.svg │ │ │ │ ├── code-sandbox.svg │ │ │ │ ├── dark_to_light.svg │ │ │ │ ├── database.svg │ │ │ │ ├── doc.svg │ │ │ │ ├── empty-folder.svg │ │ │ │ ├── expression.svg │ │ │ │ ├── eye-closed.svg │ │ │ │ ├── eye-dark.svg │ │ │ │ ├── eye.svg │ │ │ │ ├── file-text.svg │ │ │ │ ├── filter.svg │ │ │ │ ├── folder.svg │ │ │ │ ├── img.svg │ │ │ │ ├── inspect.svg │ │ │ │ ├── light_to_dark.svg │ │ │ │ ├── moon.svg │ │ │ │ ├── pdf.svg │ │ │ │ ├── photo.svg │ │ │ │ ├── share.svg │ │ │ │ ├── stars.svg │ │ │ │ ├── sun.svg │ │ │ │ ├── trending-down.svg │ │ │ │ ├── trending-level.svg │ │ │ │ ├── trending-up.svg │ │ │ │ ├── txt.svg │ │ │ │ ├── unknown-file.svg │ │ │ │ ├── unlink.svg │ │ │ │ └── xls.svg │ │ │ ├── TableDeleteColumnIcon.tsx │ │ │ ├── TableDeleteRowIcon.tsx │ │ │ ├── TableInsertColumnIcon.tsx │ │ │ ├── TableInsertRowIcon.tsx │ │ │ ├── TrashIcon.tsx │ │ │ ├── TrendingDownIcon.tsx │ │ │ ├── TrendingLevelIcon.tsx │ │ │ ├── TrendingUpIcon.tsx │ │ │ ├── TxtIcon.tsx │ │ │ ├── UnknownFileIcon.tsx │ │ │ ├── UnlinkIcon.tsx │ │ │ ├── UserIcon.tsx │ │ │ ├── WarningIcon.tsx │ │ │ └── XlsIcon.tsx │ │ ├── IconProvider.tsx │ │ ├── IconRegistryContext.tsx │ │ ├── IFrame │ │ │ ├── IFrame.md │ │ │ ├── IFrame.module.scss │ │ │ ├── IFrame.spec.ts │ │ │ ├── IFrame.tsx │ │ │ └── IFrameNative.tsx │ │ ├── Image │ │ │ ├── Image.md │ │ │ ├── Image.module.scss │ │ │ ├── Image.spec.ts │ │ │ ├── Image.tsx │ │ │ └── ImageNative.tsx │ │ ├── Input │ │ │ ├── index.ts │ │ │ ├── InputAdornment.module.scss │ │ │ ├── InputAdornment.tsx │ │ │ ├── InputDivider.module.scss │ │ │ ├── InputDivider.tsx │ │ │ ├── InputLabel.module.scss │ │ │ ├── InputLabel.tsx │ │ │ ├── PartialInput.module.scss │ │ │ └── PartialInput.tsx │ │ ├── InspectButton │ │ │ ├── InspectButton.module.scss │ │ │ └── InspectButton.tsx │ │ ├── Items │ │ │ ├── Items.md │ │ │ ├── Items.spec.ts │ │ │ ├── Items.tsx │ │ │ └── ItemsNative.tsx │ │ ├── Link │ │ │ ├── Link.md │ │ │ ├── Link.module.scss │ │ │ ├── Link.spec.ts │ │ │ ├── Link.tsx │ │ │ └── LinkNative.tsx │ │ ├── List │ │ │ ├── doc-resources │ │ │ │ └── list-component-data.js │ │ │ ├── List.md │ │ │ ├── List.module.scss │ │ │ ├── List.spec.ts │ │ │ ├── List.tsx │ │ │ └── ListNative.tsx │ │ ├── Logo │ │ │ ├── doc-resources │ │ │ │ └── xmlui-logo.svg │ │ │ ├── Logo.md │ │ │ ├── Logo.tsx │ │ │ └── LogoNative.tsx │ │ ├── Markdown │ │ │ ├── CodeText.module.scss │ │ │ ├── CodeText.tsx │ │ │ ├── Markdown.md │ │ │ ├── Markdown.module.scss │ │ │ ├── Markdown.spec.ts │ │ │ ├── Markdown.tsx │ │ │ ├── MarkdownNative.tsx │ │ │ ├── parse-binding-expr.ts │ │ │ └── utils.ts │ │ ├── metadata-helpers.ts │ │ ├── ModalDialog │ │ │ ├── ConfirmationModalContextProvider.tsx │ │ │ ├── Dialog.module.scss │ │ │ ├── Dialog.tsx │ │ │ ├── ModalDialog.md │ │ │ ├── ModalDialog.module.scss │ │ │ ├── ModalDialog.spec.ts │ │ │ ├── ModalDialog.tsx │ │ │ ├── ModalDialogNative.tsx │ │ │ └── ModalVisibilityContext.tsx │ │ ├── NavGroup │ │ │ ├── NavGroup.md │ │ │ ├── NavGroup.module.scss │ │ │ ├── NavGroup.spec.ts │ │ │ ├── NavGroup.tsx │ │ │ ├── NavGroupContext.ts │ │ │ └── NavGroupNative.tsx │ │ ├── NavLink │ │ │ ├── NavLink.md │ │ │ ├── NavLink.module.scss │ │ │ ├── NavLink.spec.ts │ │ │ ├── NavLink.tsx │ │ │ └── NavLinkNative.tsx │ │ ├── NavPanel │ │ │ ├── NavPanel.md │ │ │ ├── NavPanel.module.scss │ │ │ ├── NavPanel.spec.ts │ │ │ ├── NavPanel.tsx │ │ │ └── NavPanelNative.tsx │ │ ├── NestedApp │ │ │ ├── AppWithCodeView.module.scss │ │ │ ├── AppWithCodeView.tsx │ │ │ ├── AppWithCodeViewNative.tsx │ │ │ ├── defaultProps.tsx │ │ │ ├── logo.svg │ │ │ ├── NestedApp.module.scss │ │ │ ├── NestedApp.tsx │ │ │ ├── NestedAppNative.tsx │ │ │ ├── Tooltip.module.scss │ │ │ ├── Tooltip.tsx │ │ │ └── utils.ts │ │ ├── NoResult │ │ │ ├── NoResult.md │ │ │ ├── NoResult.module.scss │ │ │ ├── NoResult.spec.ts │ │ │ ├── NoResult.tsx │ │ │ └── NoResultNative.tsx │ │ ├── NumberBox │ │ │ ├── numberbox-abstractions.ts │ │ │ ├── NumberBox.md │ │ │ ├── NumberBox.module.scss │ │ │ ├── NumberBox.spec.ts │ │ │ ├── NumberBox.tsx │ │ │ └── NumberBoxNative.tsx │ │ ├── Option │ │ │ ├── Option.md │ │ │ ├── Option.spec.ts │ │ │ ├── Option.tsx │ │ │ ├── OptionNative.tsx │ │ │ └── OptionTypeProvider.tsx │ │ ├── PageMetaTitle │ │ │ ├── PageMetaTilteNative.tsx │ │ │ ├── PageMetaTitle.md │ │ │ ├── PageMetaTitle.spec.ts │ │ │ └── PageMetaTitle.tsx │ │ ├── Pages │ │ │ ├── Page.md │ │ │ ├── Pages.md │ │ │ ├── Pages.module.scss │ │ │ ├── Pages.tsx │ │ │ └── PagesNative.tsx │ │ ├── Pagination │ │ │ ├── Pagination.md │ │ │ ├── Pagination.module.scss │ │ │ ├── Pagination.spec.ts │ │ │ ├── Pagination.tsx │ │ │ └── PaginationNative.tsx │ │ ├── PositionedContainer │ │ │ ├── PositionedContainer.module.scss │ │ │ ├── PositionedContainer.tsx │ │ │ └── PositionedContainerNative.tsx │ │ ├── ProfileMenu │ │ │ ├── ProfileMenu.module.scss │ │ │ └── ProfileMenu.tsx │ │ ├── ProgressBar │ │ │ ├── ProgressBar.md │ │ │ ├── ProgressBar.module.scss │ │ │ ├── ProgressBar.spec.ts │ │ │ ├── ProgressBar.tsx │ │ │ └── ProgressBarNative.tsx │ │ ├── Queue │ │ │ ├── Queue.md │ │ │ ├── Queue.spec.ts │ │ │ ├── Queue.tsx │ │ │ ├── queueActions.ts │ │ │ └── QueueNative.tsx │ │ ├── RadioGroup │ │ │ ├── RadioGroup.md │ │ │ ├── RadioGroup.module.scss │ │ │ ├── RadioGroup.spec.ts │ │ │ ├── RadioGroup.tsx │ │ │ ├── RadioGroupNative.tsx │ │ │ ├── RadioItem.tsx │ │ │ └── RadioItemNative.tsx │ │ ├── RealTimeAdapter │ │ │ ├── RealTimeAdapter.tsx │ │ │ └── RealTimeAdapterNative.tsx │ │ ├── Redirect │ │ │ ├── Redirect.md │ │ │ ├── Redirect.spec.ts │ │ │ └── Redirect.tsx │ │ ├── ResponsiveBar │ │ │ ├── README.md │ │ │ ├── ResponsiveBar.md │ │ │ ├── ResponsiveBar.module.scss │ │ │ ├── ResponsiveBar.spec.ts │ │ │ ├── ResponsiveBar.tsx │ │ │ └── ResponsiveBarNative.tsx │ │ ├── Select │ │ │ ├── HiddenOption.tsx │ │ │ ├── MultiSelectOption.tsx │ │ │ ├── OptionContext.ts │ │ │ ├── Select.md │ │ │ ├── Select.module.scss │ │ │ ├── Select.spec.ts │ │ │ ├── Select.tsx │ │ │ ├── SelectContext.tsx │ │ │ ├── SelectNative.tsx │ │ │ ├── SelectOption.tsx │ │ │ └── SimpleSelect.tsx │ │ ├── SelectionStore │ │ │ ├── SelectionStore.md │ │ │ ├── SelectionStore.tsx │ │ │ └── SelectionStoreNative.tsx │ │ ├── Slider │ │ │ ├── Slider.md │ │ │ ├── Slider.module.scss │ │ │ ├── Slider.spec.ts │ │ │ ├── Slider.tsx │ │ │ └── SliderNative.tsx │ │ ├── Slot │ │ │ ├── Slot.md │ │ │ ├── Slot.spec.ts │ │ │ └── Slot.ts │ │ ├── SlotItem.tsx │ │ ├── SpaceFiller │ │ │ ├── SpaceFiller.md │ │ │ ├── SpaceFiller.module.scss │ │ │ ├── SpaceFiller.spec.ts │ │ │ ├── SpaceFiller.tsx │ │ │ └── SpaceFillerNative.tsx │ │ ├── Spinner │ │ │ ├── Spinner.md │ │ │ ├── Spinner.module.scss │ │ │ ├── Spinner.spec.ts │ │ │ ├── Spinner.tsx │ │ │ └── SpinnerNative.tsx │ │ ├── Splitter │ │ │ ├── HSplitter.md │ │ │ ├── HSplitter.spec.ts │ │ │ ├── Splitter.md │ │ │ ├── Splitter.module.scss │ │ │ ├── Splitter.spec.ts │ │ │ ├── Splitter.tsx │ │ │ ├── SplitterNative.tsx │ │ │ ├── utils.ts │ │ │ ├── VSplitter.md │ │ │ └── VSplitter.spec.ts │ │ ├── Stack │ │ │ ├── CHStack.md │ │ │ ├── CHStack.spec.ts │ │ │ ├── CVStack.md │ │ │ ├── CVStack.spec.ts │ │ │ ├── HStack.md │ │ │ ├── HStack.spec.ts │ │ │ ├── Stack.md │ │ │ ├── Stack.module.scss │ │ │ ├── Stack.spec.ts │ │ │ ├── Stack.tsx │ │ │ ├── StackNative.tsx │ │ │ ├── VStack.md │ │ │ └── VStack.spec.ts │ │ ├── StickyBox │ │ │ ├── StickyBox.md │ │ │ ├── StickyBox.module.scss │ │ │ ├── StickyBox.tsx │ │ │ └── StickyBoxNative.tsx │ │ ├── Switch │ │ │ ├── Switch.md │ │ │ ├── Switch.spec.ts │ │ │ └── Switch.tsx │ │ ├── Table │ │ │ ├── doc-resources │ │ │ │ └── list-component-data.js │ │ │ ├── react-table-config.d.ts │ │ │ ├── Table.md │ │ │ ├── Table.module.scss │ │ │ ├── Table.spec.ts │ │ │ ├── Table.tsx │ │ │ ├── TableNative.tsx │ │ │ └── useRowSelection.tsx │ │ ├── TableOfContents │ │ │ ├── TableOfContents.module.scss │ │ │ ├── TableOfContents.spec.ts │ │ │ ├── TableOfContents.tsx │ │ │ └── TableOfContentsNative.tsx │ │ ├── Tabs │ │ │ ├── TabContext.tsx │ │ │ ├── TabItem.md │ │ │ ├── TabItem.tsx │ │ │ ├── TabItemNative.tsx │ │ │ ├── Tabs.md │ │ │ ├── Tabs.module.scss │ │ │ ├── Tabs.spec.ts │ │ │ ├── Tabs.tsx │ │ │ └── TabsNative.tsx │ │ ├── Text │ │ │ ├── Text.md │ │ │ ├── Text.module.scss │ │ │ ├── Text.spec.ts │ │ │ ├── Text.tsx │ │ │ └── TextNative.tsx │ │ ├── TextArea │ │ │ ├── TextArea.md │ │ │ ├── TextArea.module.scss │ │ │ ├── TextArea.spec.ts │ │ │ ├── TextArea.tsx │ │ │ ├── TextAreaNative.tsx │ │ │ ├── TextAreaResizable.tsx │ │ │ └── useComposedRef.ts │ │ ├── TextBox │ │ │ ├── TextBox.md │ │ │ ├── TextBox.module.scss │ │ │ ├── TextBox.spec.ts │ │ │ ├── TextBox.tsx │ │ │ └── TextBoxNative.tsx │ │ ├── Theme │ │ │ ├── NotificationToast.tsx │ │ │ ├── Theme.md │ │ │ ├── Theme.module.scss │ │ │ ├── Theme.spec.ts │ │ │ ├── Theme.tsx │ │ │ └── ThemeNative.tsx │ │ ├── TimeInput │ │ │ ├── TimeInput.md │ │ │ ├── TimeInput.module.scss │ │ │ ├── TimeInput.spec.ts │ │ │ ├── TimeInput.tsx │ │ │ ├── TimeInputNative.tsx │ │ │ └── utils.ts │ │ ├── Timer │ │ │ ├── Timer.md │ │ │ ├── Timer.spec.ts │ │ │ ├── Timer.tsx │ │ │ └── TimerNative.tsx │ │ ├── Toggle │ │ │ ├── Toggle.module.scss │ │ │ └── Toggle.tsx │ │ ├── ToneChangerButton │ │ │ ├── ToneChangerButton.md │ │ │ ├── ToneChangerButton.spec.ts │ │ │ └── ToneChangerButton.tsx │ │ ├── ToneSwitch │ │ │ ├── ToneSwitch.md │ │ │ ├── ToneSwitch.module.scss │ │ │ ├── ToneSwitch.spec.ts │ │ │ ├── ToneSwitch.tsx │ │ │ └── ToneSwitchNative.tsx │ │ ├── Tooltip │ │ │ ├── Tooltip.md │ │ │ ├── Tooltip.module.scss │ │ │ ├── Tooltip.spec.ts │ │ │ ├── Tooltip.tsx │ │ │ └── TooltipNative.tsx │ │ ├── Tree │ │ │ ├── testData.ts │ │ │ ├── Tree-dynamic.spec.ts │ │ │ ├── Tree-icons.spec.ts │ │ │ ├── Tree.md │ │ │ ├── Tree.spec.ts │ │ │ ├── TreeComponent.module.scss │ │ │ ├── TreeComponent.tsx │ │ │ └── TreeNative.tsx │ │ ├── TreeDisplay │ │ │ ├── TreeDisplay.md │ │ │ ├── TreeDisplay.module.scss │ │ │ ├── TreeDisplay.tsx │ │ │ └── TreeDisplayNative.tsx │ │ ├── ValidationSummary │ │ │ ├── ValidationSummary.module.scss │ │ │ └── ValidationSummary.tsx │ │ └── VisuallyHidden.tsx │ ├── components-core │ │ ├── abstractions │ │ │ ├── ComponentRenderer.ts │ │ │ ├── LoaderRenderer.ts │ │ │ ├── standalone.ts │ │ │ └── treeAbstractions.ts │ │ ├── action │ │ │ ├── actions.ts │ │ │ ├── APICall.tsx │ │ │ ├── FileDownloadAction.tsx │ │ │ ├── FileUploadAction.tsx │ │ │ ├── NavigateAction.tsx │ │ │ └── TimedAction.tsx │ │ ├── ApiBoundComponent.tsx │ │ ├── appContext │ │ │ ├── date-functions.ts │ │ │ ├── math-function.ts │ │ │ └── misc-utils.ts │ │ ├── AppContext.tsx │ │ ├── behaviors │ │ │ ├── Behavior.tsx │ │ │ ├── BehaviorContext.tsx │ │ │ └── CoreBehaviors.tsx │ │ ├── component-hooks.ts │ │ ├── ComponentDecorator.tsx │ │ ├── ComponentViewer.tsx │ │ ├── CompoundComponent.tsx │ │ ├── constants.ts │ │ ├── DebugViewProvider.tsx │ │ ├── descriptorHelper.ts │ │ ├── devtools │ │ │ ├── InspectorDialog.module.scss │ │ │ ├── InspectorDialog.tsx │ │ │ └── InspectorDialogVisibilityContext.tsx │ │ ├── EngineError.ts │ │ ├── event-handlers.ts │ │ ├── InspectorButton.module.scss │ │ ├── InspectorContext.tsx │ │ ├── interception │ │ │ ├── abstractions.ts │ │ │ ├── ApiInterceptor.ts │ │ │ ├── ApiInterceptorProvider.tsx │ │ │ ├── apiInterceptorWorker.ts │ │ │ ├── Backend.ts │ │ │ ├── Errors.ts │ │ │ ├── IndexedDb.ts │ │ │ ├── initMock.ts │ │ │ ├── InMemoryDb.ts │ │ │ ├── ReadonlyCollection.ts │ │ │ └── useApiInterceptorContext.tsx │ │ ├── loader │ │ │ ├── ApiLoader.tsx │ │ │ ├── DataLoader.tsx │ │ │ ├── ExternalDataLoader.tsx │ │ │ ├── Loader.tsx │ │ │ ├── MockLoaderRenderer.tsx │ │ │ └── PageableLoader.tsx │ │ ├── LoaderComponent.tsx │ │ ├── markup-check.ts │ │ ├── parts.ts │ │ ├── renderers.ts │ │ ├── rendering │ │ │ ├── AppContent.tsx │ │ │ ├── AppRoot.tsx │ │ │ ├── AppWrapper.tsx │ │ │ ├── buildProxy.ts │ │ │ ├── collectFnVarDeps.ts │ │ │ ├── ComponentAdapter.tsx │ │ │ ├── ComponentWrapper.tsx │ │ │ ├── Container.tsx │ │ │ ├── containers.ts │ │ │ ├── ContainerWrapper.tsx │ │ │ ├── ErrorBoundary.module.scss │ │ │ ├── ErrorBoundary.tsx │ │ │ ├── InvalidComponent.module.scss │ │ │ ├── InvalidComponent.tsx │ │ │ ├── nodeUtils.ts │ │ │ ├── reducer.ts │ │ │ ├── renderChild.tsx │ │ │ ├── StandaloneComponent.tsx │ │ │ ├── StateContainer.tsx │ │ │ ├── UnknownComponent.module.scss │ │ │ ├── UnknownComponent.tsx │ │ │ └── valueExtractor.ts │ │ ├── reportEngineError.ts │ │ ├── RestApiProxy.ts │ │ ├── script-runner │ │ │ ├── asyncProxy.ts │ │ │ ├── AttributeValueParser.ts │ │ │ ├── bannedFunctions.ts │ │ │ ├── BindingTreeEvaluationContext.ts │ │ │ ├── eval-tree-async.ts │ │ │ ├── eval-tree-common.ts │ │ │ ├── eval-tree-sync.ts │ │ │ ├── ParameterParser.ts │ │ │ ├── process-statement-async.ts │ │ │ ├── process-statement-common.ts │ │ │ ├── process-statement-sync.ts │ │ │ ├── ScriptingSourceTree.ts │ │ │ ├── simplify-expression.ts │ │ │ ├── statement-queue.ts │ │ │ └── visitors.ts │ │ ├── StandaloneApp.tsx │ │ ├── StandaloneExtensionManager.ts │ │ ├── TableOfContentsContext.tsx │ │ ├── theming │ │ │ ├── _themes.scss │ │ │ ├── component-layout-resolver.ts │ │ │ ├── extendThemeUtils.ts │ │ │ ├── hvar.ts │ │ │ ├── layout-resolver.ts │ │ │ ├── parse-layout-props.ts │ │ │ ├── StyleContext.tsx │ │ │ ├── StyleRegistry.ts │ │ │ ├── ThemeContext.tsx │ │ │ ├── ThemeProvider.tsx │ │ │ ├── themes │ │ │ │ ├── base-utils.ts │ │ │ │ ├── palette.ts │ │ │ │ ├── root.ts │ │ │ │ ├── solid.ts │ │ │ │ ├── theme-colors.ts │ │ │ │ └── xmlui.ts │ │ │ ├── themeVars.module.scss │ │ │ ├── themeVars.ts │ │ │ ├── transformThemeVars.ts │ │ │ └── utils.ts │ │ ├── utils │ │ │ ├── actionUtils.ts │ │ │ ├── audio-utils.ts │ │ │ ├── compound-utils.ts │ │ │ ├── css-utils.ts │ │ │ ├── DataLoaderQueryKeyGenerator.ts │ │ │ ├── date-utils.ts │ │ │ ├── extractParam.ts │ │ │ ├── hooks.tsx │ │ │ ├── LruCache.ts │ │ │ ├── mergeProps.ts │ │ │ ├── misc.ts │ │ │ ├── request-params.ts │ │ │ ├── statementUtils.ts │ │ │ └── treeUtils.ts │ │ └── xmlui-parser.ts │ ├── index-standalone.ts │ ├── index.scss │ ├── index.ts │ ├── language-server │ │ ├── server-common.ts │ │ ├── server-web-worker.ts │ │ ├── server.ts │ │ ├── services │ │ │ ├── common │ │ │ │ ├── docs-generation.ts │ │ │ │ ├── lsp-utils.ts │ │ │ │ ├── metadata-utils.ts │ │ │ │ └── syntax-node-utilities.ts │ │ │ ├── completion.ts │ │ │ ├── diagnostic.ts │ │ │ ├── format.ts │ │ │ └── hover.ts │ │ └── xmlui-metadata-generated.mjs │ ├── logging │ │ ├── LoggerContext.tsx │ │ ├── LoggerInitializer.tsx │ │ ├── LoggerService.ts │ │ └── xmlui.ts │ ├── logo.svg │ ├── parsers │ │ ├── common │ │ │ ├── GenericToken.ts │ │ │ ├── InputStream.ts │ │ │ └── utils.ts │ │ ├── scripting │ │ │ ├── code-behind-collect.ts │ │ │ ├── Lexer.ts │ │ │ ├── modules.ts │ │ │ ├── Parser.ts │ │ │ ├── ParserError.ts │ │ │ ├── ScriptingNodeTypes.ts │ │ │ ├── TokenTrait.ts │ │ │ ├── TokenType.ts │ │ │ └── tree-visitor.ts │ │ ├── style-parser │ │ │ ├── errors.ts │ │ │ ├── source-tree.ts │ │ │ ├── StyleInputStream.ts │ │ │ ├── StyleLexer.ts │ │ │ ├── StyleParser.ts │ │ │ └── tokens.ts │ │ └── xmlui-parser │ │ ├── CharacterCodes.ts │ │ ├── diagnostics.ts │ │ ├── fileExtensions.ts │ │ ├── index.ts │ │ ├── lint.ts │ │ ├── parser.ts │ │ ├── ParserError.ts │ │ ├── scanner.ts │ │ ├── syntax-kind.ts │ │ ├── syntax-node.ts │ │ ├── transform.ts │ │ ├── utils.ts │ │ ├── xmlui-serializer.ts │ │ └── xmlui-tree.ts │ ├── react-app-env.d.ts │ ├── syntax │ │ ├── monaco │ │ │ ├── grammar.monacoLanguage.ts │ │ │ ├── index.ts │ │ │ ├── xmlui-dark.ts │ │ │ ├── xmlui-light.ts │ │ │ └── xmluiscript.monacoLanguage.ts │ │ └── textMate │ │ ├── index.ts │ │ ├── xmlui-dark.json │ │ ├── xmlui-light.json │ │ ├── xmlui.json │ │ └── xmlui.tmLanguage.json │ ├── testing │ │ ├── assertions.ts │ │ ├── component-test-helpers.ts │ │ ├── ComponentDrivers.ts │ │ ├── drivers │ │ │ ├── DateInputDriver.ts │ │ │ ├── ModalDialogDriver.ts │ │ │ ├── NumberBoxDriver.ts │ │ │ ├── TextBoxDriver.ts │ │ │ ├── TimeInputDriver.ts │ │ │ ├── TimerDriver.ts │ │ │ └── TreeDriver.ts │ │ ├── fixtures.ts │ │ ├── infrastructure │ │ │ ├── index.html │ │ │ ├── main.tsx │ │ │ ├── public │ │ │ │ ├── mockServiceWorker.js │ │ │ │ ├── resources │ │ │ │ │ ├── bell.svg │ │ │ │ │ ├── box.svg │ │ │ │ │ ├── doc.svg │ │ │ │ │ ├── eye.svg │ │ │ │ │ ├── flower-640x480.jpg │ │ │ │ │ ├── sun.svg │ │ │ │ │ ├── test-image-100x100.jpg │ │ │ │ │ └── txt.svg │ │ │ │ └── serve.json │ │ │ └── TestBed.tsx │ │ └── themed-app-test-helpers.ts │ └── vite-env.d.ts ├── tests │ ├── components │ │ ├── CodeBlock │ │ │ └── hightlight-code.test.ts │ │ ├── playground-pattern.test.ts │ │ └── Tree │ │ └── Tree-states.test.ts │ ├── components-core │ │ ├── abstractions │ │ │ └── treeAbstractions.test.ts │ │ ├── container │ │ │ └── buildProxy.test.ts │ │ ├── interception │ │ │ ├── orderBy.test.ts │ │ │ ├── ReadOnlyCollection.test.ts │ │ │ └── request-param-converter.test.ts │ │ ├── scripts-runner │ │ │ ├── AttributeValueParser.test.ts │ │ │ ├── eval-tree-arrow-async.test.ts │ │ │ ├── eval-tree-arrow.test.ts │ │ │ ├── eval-tree-func-decl-async.test.ts │ │ │ ├── eval-tree-func-decl.test.ts │ │ │ ├── eval-tree-pre-post.test.ts │ │ │ ├── eval-tree-regression.test.ts │ │ │ ├── eval-tree.test.ts │ │ │ ├── function-proxy.test.ts │ │ │ ├── parser-regression.test.ts │ │ │ ├── process-event.test.ts │ │ │ ├── process-function.test.ts │ │ │ ├── process-implicit-context.test.ts │ │ │ ├── process-statement-asgn.test.ts │ │ │ ├── process-statement-destruct.test.ts │ │ │ ├── process-statement-regs.test.ts │ │ │ ├── process-statement-sync.test.ts │ │ │ ├── process-statement.test.ts │ │ │ ├── process-switch-sync.test.ts │ │ │ ├── process-switch.test.ts │ │ │ ├── process-try-sync.test.ts │ │ │ ├── process-try.test.ts │ │ │ └── test-helpers.ts │ │ ├── test-metadata-handler.ts │ │ ├── theming │ │ │ ├── border-segments.test.ts │ │ │ ├── component-layout.resolver.test.ts │ │ │ ├── layout-property-parser.test.ts │ │ │ ├── layout-resolver.test.ts │ │ │ ├── layout-resolver2.test.ts │ │ │ ├── layout-vp-override.test.ts │ │ │ └── padding-segments.test.ts │ │ └── utils │ │ ├── date-utils.test.ts │ │ ├── format-human-elapsed-time.test.ts │ │ └── LruCache.test.ts │ ├── language-server │ │ ├── completion.test.ts │ │ ├── format.test.ts │ │ ├── hover.test.ts │ │ └── mockData.ts │ └── parsers │ ├── common │ │ └── input-stream.test.ts │ ├── markdown │ │ └── parse-binding-expression.test.ts │ ├── parameter-parser.test.ts │ ├── paremeter-parser.test.ts │ ├── scripting │ │ ├── eval-tree-arrow.test.ts │ │ ├── eval-tree-pre-post.test.ts │ │ ├── eval-tree.test.ts │ │ ├── function-proxy.test.ts │ │ ├── lexer-literals.test.ts │ │ ├── lexer-misc.test.ts │ │ ├── module-parse.test.ts │ │ ├── parser-arrow.test.ts │ │ ├── parser-assignments.test.ts │ │ ├── parser-binary.test.ts │ │ ├── parser-destructuring.test.ts │ │ ├── parser-errors.test.ts │ │ ├── parser-expressions.test.ts │ │ ├── parser-function.test.ts │ │ ├── parser-literals.test.ts │ │ ├── parser-primary.test.ts │ │ ├── parser-regex.test.ts │ │ ├── parser-statements.test.ts │ │ ├── parser-unary.test.ts │ │ ├── process-event.test.ts │ │ ├── process-implicit-context.test.ts │ │ ├── process-statement-asgn.test.ts │ │ ├── process-statement-destruct.test.ts │ │ ├── process-statement-regs.test.ts │ │ ├── process-statement-sync.test.ts │ │ ├── process-statement.test.ts │ │ ├── process-switch-sync.test.ts │ │ ├── process-switch.test.ts │ │ ├── process-try-sync.test.ts │ │ ├── process-try.test.ts │ │ ├── simplify-expression.test.ts │ │ ├── statement-hooks.test.ts │ │ └── test-helpers.ts │ ├── style-parser │ │ ├── generateHvarChain.test.ts │ │ ├── parseHVar.test.ts │ │ ├── parser.test.ts │ │ └── tokens.test.ts │ └── xmlui │ ├── lint.test.ts │ ├── parser.test.ts │ ├── scanner.test.ts │ ├── transform.attr.test.ts │ ├── transform.circular.test.ts │ ├── transform.element.test.ts │ ├── transform.errors.test.ts │ ├── transform.escape.test.ts │ ├── transform.regression.test.ts │ ├── transform.script.test.ts │ ├── transform.test.ts │ └── xmlui.ts ├── tests-e2e │ ├── api-bound-component-regression.spec.ts │ ├── api-call-as-extracted-component.spec.ts │ ├── assign-to-object-or-array-regression.spec.ts │ ├── binding-regression.spec.ts │ ├── children-as-template-context-vars.spec.ts │ ├── compound-component.spec.ts │ ├── context-vars-regression.spec.ts │ ├── data-bindings.spec.ts │ ├── datasource-and-api-usage-in-var.spec.ts │ ├── datasource-direct-binding.spec.ts │ ├── datasource-onLoaded-regression.spec.ts │ ├── modify-array-item-regression.spec.ts │ ├── namespaces.spec.ts │ ├── push-to-array-regression.spec.ts │ ├── screen-breakpoints.spec.ts │ ├── scripting.spec.ts │ ├── state-scope-in-pages.spec.ts │ └── state-var-scopes.spec.ts ├── tsconfig.bin.json ├── tsconfig.json ├── tsconfig.node.json ├── vite.config.ts └── vitest.config.ts ``` # Files -------------------------------------------------------------------------------- /packages/xmlui-search/tsconfig.json: -------------------------------------------------------------------------------- ```json { "compilerOptions": { "target": "es2015", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "types": ["vite/client", "vite-plugin-svgr/client", "node"], "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx" }, "include": [ "demo", "src", "index.ts" ], "exclude": [ "demo/**/*.xmlui.xs" ] } ``` -------------------------------------------------------------------------------- /packages/xmlui-spreadsheet/tsconfig.json: -------------------------------------------------------------------------------- ```json { "compilerOptions": { "target": "es2015", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "types": ["vite/client", "vite-plugin-svgr/client", "node"], "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx" }, "include": [ "demo", "src", "index.ts" ], "exclude": [ "demo/**/*.xmlui.xs" ] } ``` -------------------------------------------------------------------------------- /packages/xmlui-website-blocks/tsconfig.json: -------------------------------------------------------------------------------- ```json { "compilerOptions": { "target": "es2015", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "types": ["vite/client", "vite-plugin-svgr/client", "node"], "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx" }, "include": [ "demo", "src", "index.ts" ], "exclude": [ "demo/**/*.xmlui.xs" ] } ``` -------------------------------------------------------------------------------- /xmlui/src/components/Charts/PieChart/PieChartNative.module.scss: -------------------------------------------------------------------------------- ```scss @use "xmlui/themes.scss" as t; // --- This code snippet is required to collect the theme variables used in this module $themeVars: (); @function createThemeVar($componentVariable) { $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; @return t.getThemeVar($themeVars, $componentVariable); } $componentName: "PieChart"; @layer components { .wrapper{ width: 100%; height: 100%; flex: 1; min-height: 0; } .chartContainer { margin-left: auto; margin-right: auto; aspect-ratio: 1 / 1; } } // --- We export the theme variables to add them to the component renderer :export { themeVars: t.json-stringify($themeVars); } ``` -------------------------------------------------------------------------------- /xmlui/src/components/FormItem/HelperText.module.scss: -------------------------------------------------------------------------------- ```scss @use "../../components-core/theming/themes" as t; @layer components { .helper { padding-top: t.$space-1; padding-bottom: t.$space-1; display: flex; align-items: center; user-select: none; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; } .helperText { font-size: t.$fontSize-sm; color: t.$textColor-primary; } .valid { .helperText { margin-left: 0.25em; color: t.$color-valid; } } .error { .helperText { margin-left: 0.25em; color: t.$color-error; } } .warning { .helperText { margin-left: 0.25em; color: t.$color-warning; } } } ``` -------------------------------------------------------------------------------- /blog/tsconfig.json: -------------------------------------------------------------------------------- ```json { "compilerOptions": { "target": "es2017", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "types": ["vite/client", "node"], "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", "paths": { "@components/*": ["../ui-engine/src/components/*"], } }, "include": [ "src", "build", "index.ts" ] } ``` -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- ```json { "compilerOptions": { "target": "es2017", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "types": ["vite/client", "node"], "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", "paths": { "@components/*": ["../ui-engine/src/components/*"], } }, "include": [ "src", "build", "index.ts" ] } ``` -------------------------------------------------------------------------------- /xmlui/src/components/Breakout/Breakout.tsx: -------------------------------------------------------------------------------- ```typescript import { createComponentRenderer } from "../../components-core/renderers"; import { createMetadata } from "../metadata-helpers"; import { Breakout } from "./BreakoutNative"; const COMP = "Breakout"; export const BreakoutMd = createMetadata({ status: "stable", description: `The \`${COMP}\` component creates a breakout section. It allows its child to ` + `occupy the entire width of the UI even if the app or the parent container constrains ` + `the maximum content width.`, }); export const breakoutComponentRenderer = createComponentRenderer( COMP, BreakoutMd, ({ node, renderChild }) => { return <Breakout>{renderChild(node.children)}</Breakout>; }, ); ``` -------------------------------------------------------------------------------- /packages/xmlui-spreadsheet/src/Spreadsheet.tsx: -------------------------------------------------------------------------------- ```typescript import { createComponentRenderer, createMetadata, parseScssVar } from "xmlui"; import JSpreadsheet from "./SpreadsheetNative"; const COMP = "Spreadsheet"; export const SpreadsheetMd = createMetadata({ description: "XMLUI Spreadsheet", status: "experimental", props: { worksheets: { description: "This property sets the initial value of the spreadsheet's worksheets.", }, }, themeVars: parseScssVar({}), defaultThemeVars: {}, }); export const spreadsheetComponentRenderer = createComponentRenderer( COMP, SpreadsheetMd, ({ extractValue, node, renderChild }: any) => { return <JSpreadsheet worksheets={extractValue(node.props.worksheets)} />; }, ); ``` -------------------------------------------------------------------------------- /xmlui/src/components/HoverCard/HovercardNative.tsx: -------------------------------------------------------------------------------- ```typescript import type React from "react"; import * as HoverCard from "@radix-ui/react-hover-card"; import { useTheme } from "../../components-core/theming/ThemeContext"; type Props = { triggerTemplate: React.ReactNode; children: React.ReactNode; }; export const HoverCardComponent = ({ triggerTemplate, children }: Props) => { const { root } = useTheme(); return ( <HoverCard.Root openDelay={100} closeDelay={100}> <HoverCard.Trigger>{triggerTemplate}</HoverCard.Trigger> <HoverCard.Portal container={root}> <HoverCard.Content side="bottom" sideOffset={5}> {children} </HoverCard.Content> </HoverCard.Portal> </HoverCard.Root> ); }; ``` -------------------------------------------------------------------------------- /docs/public/pages/xmlui-charts/Legend.md: -------------------------------------------------------------------------------- ```markdown # Legend [#legend] >[!WARNING] > This component is in an **experimental** state; you can use it in your app. However, we may modify it, and it may even have breaking changes in the future.Legend component to be displayed in a chart component. ## Properties ### `align (default: "center")` The alignment of the legend Available values: `left`, `right`, `center` **(default)** ### `verticalAlign (default: "bottom")` The vertical alignment of the legend Available values: `top`, `bottom` **(default)**, `middle` ## Events This component does not have any events. ## Exposed Methods This component does not expose any methods. ## Styling This component does not have any styles. ``` -------------------------------------------------------------------------------- /xmlui/src/components/InspectButton/InspectButton.module.scss: -------------------------------------------------------------------------------- ```scss @use "../../components-core/theming/themes" as t; // --- This code snippet is required to collect the theme variables used in this module $themeVars: (); @function createThemeVar($componentVariable) { $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; @return t.getThemeVar($themeVars, $componentVariable); } @layer components { .icon { font-size: t.$fontSize-base; } .inspectButton { display: flex; gap: t.$space-1; justify-content: center; } .active { background: t.$color-primary-500; } // --- We export the theme variables to add them to the component renderer :export { themeVars: t.json-stringify($themeVars); } } ``` -------------------------------------------------------------------------------- /xmlui/src/components/Icon/svg/api.svg: -------------------------------------------------------------------------------- ``` <svg width="24" height="25" viewBox="0 0 24 25" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M12 8.5C16.9706 8.5 21 7.15685 21 5.5C21 3.84315 16.9706 2.5 12 2.5C7.02944 2.5 3 3.84315 3 5.5C3 7.15685 7.02944 8.5 12 8.5Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M21 12.5C21 14.16 17 15.5 12 15.5C7 15.5 3 14.16 3 12.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> <path d="M3 5.5V19.5C3 21.16 7 22.5 12 22.5C17 22.5 21 21.16 21 19.5V5.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> ``` -------------------------------------------------------------------------------- /xmlui/src/components/Input/InputLabel.tsx: -------------------------------------------------------------------------------- ```typescript import classnames from "classnames"; import styles from "./InputLabel.module.scss"; // ===================================================================================================================== // React component definition type Props = { text: string; forFieldId?: string; required?: boolean; disabled?: boolean; focused?: boolean; }; export const InputLabel = ({ text, required, forFieldId, disabled, ...rest }: Props) => { return ( <label {...rest} className={classnames(styles.inputLabel, { [styles.disabled]: disabled })} htmlFor={forFieldId} > {text} {required && <span className={styles.required}>*</span>} </label> ); }; ``` -------------------------------------------------------------------------------- /packages/xmlui-pdf/src/Pdf.module.scss: -------------------------------------------------------------------------------- ```scss @use "xmlui/themes.scss" as t; // --- This code snippet is required to collect the theme variables used in this module $themeVars: (); @function createThemeVar($componentVariable) { $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; @return t.getThemeVar($themeVars, $componentVariable); } $boxShadow-page-Pdf: createThemeVar("boxShadow-page-Pdf"); $gap-pages-Pdf: createThemeVar("gap-pages-Pdf"); .document{ display: flex; flex-direction: column; gap: $gap-pages-Pdf; width: fit-content; } .page{ box-shadow: $boxShadow-page-Pdf; } // --- We export the theme variables to add them to the component renderer :export{ themeVars: t.json-stringify($themeVars) } ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/theming/ThemeContext.tsx: -------------------------------------------------------------------------------- ```typescript import React, { useContext } from "react"; import type { AppThemes, ThemeScope } from "../../abstractions/ThemingDefs"; export const ThemeContext = React.createContext<ThemeScope | undefined>(undefined); export const ThemesContext = React.createContext<AppThemes | undefined>(undefined); // This React hook makes the current theme information available within any component logic using the hook. export function useTheme(): ThemeScope { return useContext(ThemeContext)!; } export function useThemes(): AppThemes { return useContext(ThemesContext)!; } export function useResourceUrl(resourceString?: string) { const { getResourceUrl } = useTheme(); return getResourceUrl(resourceString); } ``` -------------------------------------------------------------------------------- /xmlui/src/components/Column/TableContext.tsx: -------------------------------------------------------------------------------- ```typescript import type { CSSProperties, ReactNode } from "react"; import { createContext, useContext } from "react"; export type OurColumnMetadata = { style?: CSSProperties; className?: string; header: string; accessorKey?: string; id?: string; size?: number; width?: string; minWidth?: number; maxWidth?: number; canSort?: boolean; pinTo?: string; canResize?: boolean; cellRenderer?: (row: any, rowIndex: number, colIndex: number, value: any) => ReactNode; }; export const TableContext = createContext({ registerColumn: (col: OurColumnMetadata, id: string) => {}, unRegisterColumn: (id: string) => {}, }); export function useTableContext() { return useContext(TableContext); } ``` -------------------------------------------------------------------------------- /xmlui/tsconfig.bin.json: -------------------------------------------------------------------------------- ```json { "compilerOptions": { "target": "es2015", "lib": [ "dom", "dom.iterable", "esnext" ], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "strictNullChecks": false, "noImplicitAny": false, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "CommonJS", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "noEmit": false, "jsx": "react-jsx", "outDir": "dist/scripts", "types": ["vite/client", "vite-plugin-svgr/client", "node"] }, "include": [ "bin", "src" ] } ``` -------------------------------------------------------------------------------- /xmlui/src/parsers/xmlui-parser/xmlui-tree.ts: -------------------------------------------------------------------------------- ```typescript export type XmlUiNode = XmlUiComment | XmlUiAttribute | XmlUiElement; export type XmlUiFragment = XmlUiNode | XmlUiNode[]; export interface XmlUiNodeBase { type: XmlUiNode["type"]; } export interface XmlUiComment extends XmlUiNodeBase { type: "XmlUiComment"; text?: string; } export interface XmlUiAttribute extends XmlUiNodeBase { type: "XmlUiAttribute"; name: string; namespace?: string; value?: string; preserveQuotes?: boolean; preserveSpaces?: boolean; } export interface XmlUiElement extends XmlUiNodeBase { type: "XmlUiElement"; name: string; namespace?: string; attributes?: XmlUiAttribute[]; text?: string; preserveSpaces?: boolean; childNodes?: XmlUiNode[]; } ``` -------------------------------------------------------------------------------- /packages/xmlui-devtools/src/devtools/Tooltip.tsx: -------------------------------------------------------------------------------- ```typescript import { Provider, Root, Portal, Trigger, Content } from "@radix-ui/react-tooltip"; import React, { ReactNode } from "react"; import { useTheme } from "xmlui"; import styles from "./Tooltip.module.scss"; export const Tooltip = React.forwardRef(function ( { children, label, }: { children: ReactNode; label: string; }, ref: React.Ref<HTMLButtonElement>, ) { const { root } = useTheme(); return ( <Provider> <Root> <Trigger ref={ref} asChild>{children}</Trigger> <Portal container={root}> <Content className={styles.TooltipContent} sideOffset={5}> {label} </Content> </Portal> </Root> </Provider> ); }); ``` -------------------------------------------------------------------------------- /docs/content/components/H1.md: -------------------------------------------------------------------------------- ```markdown # H1 [#h1] This component is inherited from [Heading](/components/Heading) See also: [H2](/components/H2), [H3](/components/H3), [H4](/components/H4), [H5](/components/H5), [H6](/components/H6) The `H1` component is a shorthand version of the `Heading` element with its `level` property set to "h1". ```xmlui-pg copy display name="H1 example" <App> <H1 value="This is a H1 text" /> </App> ``` ## Styling [#styling] The `H1` component inherits its visual style from the `Heading` component. Using the `H1` component specifier, you can override the inherited theme variable values. For example, the `textColor-H1` theme variable sets the text color of `H1` while keeping the color of all other headings. ``` -------------------------------------------------------------------------------- /docs/content/components/H2.md: -------------------------------------------------------------------------------- ```markdown # H2 [#h2] This component is inherited from [Heading](/components/Heading) See also: [H1](/components/H1), [H3](/components/H3), [H4](/components/H4), [H5](/components/H5), [H6](/components/H6) The `H2` component is a shorthand version of the `Heading` element with its `level` property set to "h2". ```xmlui-pg copy display name="H2 example" <App> <H2 value="This is a H2 text" /> </App> ``` ## Styling [#styling] The `H2` component inherits its visual style from the `Heading` component. Using the `H2` component specifier, you can override the inherited theme variable values. For example, the `textColor-H2` theme variable sets the text color of `H2` while keeping the color of all other headings. ``` -------------------------------------------------------------------------------- /docs/content/components/H3.md: -------------------------------------------------------------------------------- ```markdown # H3 [#h3] This component is inherited from [Heading](/components/Heading) See also: [H1](/components/H1), [H2](/components/H2), [H4](/components/H4), [H5](/components/H5), [H6](/components/H6) The `H3` component is a shorthand version of the `Heading` element with its `level` property set to "h3". ```xmlui-pg copy display name="H3 example" <App> <H3 value="This is a H3 text" /> </App> ``` ## Styling [#styling] The `H3` component inherits its visual style from the `Heading` component. Using the `H3` component specifier, you can override the inherited theme variable values. For example, the `textColor-H3` theme variable sets the text color of `H3` while keeping the color of all other headings. ``` -------------------------------------------------------------------------------- /docs/content/components/H4.md: -------------------------------------------------------------------------------- ```markdown # H4 [#h4] This component is inherited from [Heading](/components/Heading) See also: [H1](/components/H1), [H2](/components/H2), [H3](/components/H3), [H5](/components/H5), [H6](/components/H6) The `H4` component is a shorthand version of the `Heading` element with its `level` property set to "h4". ```xmlui-pg copy display name="H4 example" <App> <H4 value="This is a H4 text" /> </App> ``` ## Styling [#styling] The `H4` component inherits its visual style from the `Heading` component. Using the `H4` component specifier, you can override the inherited theme variable values. For example, the `textColor-H4` theme variable sets the text color of `H4` while keeping the color of all other headings. ``` -------------------------------------------------------------------------------- /docs/content/components/H5.md: -------------------------------------------------------------------------------- ```markdown # H5 [#h5] This component is inherited from [Heading](/components/Heading) See also: [H1](/components/H1), [H2](/components/H2), [H3](/components/H3), [H4](/components/H4), [H6](/components/H6) The `H5` component is a shorthand version of the `Heading` element with its `level` property set to "h5". ```xmlui-pg copy display name="H5 example" <App> <H5 value="This is a H5 text" /> </App> ``` ## Styling [#styling] The `H5` component inherits its visual style from the `Heading` component. Using the `H5` component specifier, you can override the inherited theme variable values. For example, the `textColor-H5` theme variable sets the text color of `H5` while keeping the color of all other headings. ``` -------------------------------------------------------------------------------- /docs/content/components/H6.md: -------------------------------------------------------------------------------- ```markdown # H6 [#h6] This component is inherited from [Heading](/components/Heading) See also: [H1](/components/H1), [H2](/components/H2), [H3](/components/H3), [H4](/components/H4), [H5](/components/H5) The `H6` component is a shorthand version of the `Heading` element with its `level` property set to "h6". ```xmlui-pg copy display name="H6 example" <App> <H6 value="This is a H6 text" /> </App> ``` ## Styling [#styling] The `H6` component inherits its visual style from the `Heading` component. Using the `H6` component specifier, you can override the inherited theme variable values. For example, the `textColor-H6` theme variable sets the text color of `H6` while keeping the color of all other headings. ``` -------------------------------------------------------------------------------- /xmlui/src/components/Option/OptionNative.tsx: -------------------------------------------------------------------------------- ```typescript import { memo } from "react"; import type { Option } from "../abstractions"; import { useOptionType } from "./OptionTypeProvider"; // Default props for Option component export const defaultProps = { enabled: true, }; export function convertOptionValue(value: any): any { if ( typeof value !== "string" && (typeof value !== "number" || (typeof value === "number" && isNaN(value))) && typeof value !== "boolean" && value !== null ) { return ""; } return value; } export const OptionNative = memo((props: Option) => { const OptionType = useOptionType(); if (!OptionType) { return null; } return <OptionType {...props} />; }); OptionNative.displayName = "OptionNative"; ``` -------------------------------------------------------------------------------- /xmlui/src/language-server/services/diagnostic.ts: -------------------------------------------------------------------------------- ```typescript import type { Diagnostic, Position } from "vscode-languageserver"; import type { Error, ParseResult } from "../../parsers/xmlui-parser"; import { offsetToPosRange } from "./common/lsp-utils"; export type DiagnosticsContext = { offsetToPos: (pos: number) => Position; parseResult: ParseResult; } export function getDiagnostics(ctx: DiagnosticsContext): Diagnostic[] { const { errors } = ctx.parseResult; return errors.map((e) => { return errorToLspDiag(e, ctx.offsetToPos); }); } export function errorToLspDiag(e: Error, offsetToPos: (number) => Position): Diagnostic{ return { severity: e.category, range: offsetToPosRange(offsetToPos, e), message: e.message, code: e.code, } } ``` -------------------------------------------------------------------------------- /xmlui/src/parsers/style-parser/tokens.ts: -------------------------------------------------------------------------------- ```typescript // Token types used in layout parsing export const enum StyleTokenType { Eof = -1, Ws = -2, Unknown = 0, // --- Binding Expression specific tokens Identifier, Star, Percentage, Number, LParent, RParent, Comma, Slash, Reset, None, UserSelect, SizeUnit, FitToContent, Auto, Alignment, TextAlignment, BorderStyle, Scrolling, TextTransform, Direction, Angle, HexaColor, ColorFunc, FontFamily, ColorName, FontWeight, DecorationLine, Orientation, Cursor, Default, Boolean, String } // Represents a generic token export type StyleToken = { readonly text: string; readonly type: StyleTokenType; readonly start: number; readonly end: number; }; ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/appContext/math-function.ts: -------------------------------------------------------------------------------- ```typescript /** * This function calculates the average of the specified values and returns it. * @param values Values to calculate the average * @param decimals Number of decimal places to round the result */ function avg(values: number[], decimals?: number): number { if (values.length === 0) { return 0; } const sumValues = sum(values); const result = sumValues / values.length; return decimals ? Number(result.toFixed(decimals)) : result; } /** * This function calculates the sum of the specified values and returns it. * @param values Values to calculate the sum */ function sum(values: number[]): number { return values.reduce((acc, val) => acc + val, 0); } export const mathFunctions = { avg, sum }; ``` -------------------------------------------------------------------------------- /xmlui/scripts/generate-docs/folders.mjs: -------------------------------------------------------------------------------- ``` import { join, dirname } from "path"; import { fileURLToPath } from "url"; export const FOLDERS = { // import.meta.dirname only works in with ES Modules (Node.js 20.11+) // fallback used for older Node versions (support Node.js 15+) script: import.meta.dirname ?? fileURLToPath(new URL('.', import.meta.url)), xmluiDist: join(dirname(fileURLToPath(import.meta.url)), "../../", "dist"), projectRoot: join(dirname(fileURLToPath(import.meta.url)), "../../../"), docsRoot: join(dirname(fileURLToPath(import.meta.url)), "../../../", "docs"), pages: join(dirname(fileURLToPath(import.meta.url)), "../../../", "docs", "pages"), docsMeta: join(dirname(fileURLToPath(import.meta.url)), "../../../", "docs", "meta"), } ``` -------------------------------------------------------------------------------- /xmlui/src/components/Column/doc-resources/list-component-data.js: -------------------------------------------------------------------------------- ```javascript const 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, }, ]; export default data; ``` -------------------------------------------------------------------------------- /xmlui/src/components/List/doc-resources/list-component-data.js: -------------------------------------------------------------------------------- ```javascript const 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, }, ]; export default data; ``` -------------------------------------------------------------------------------- /xmlui/src/components/Table/doc-resources/list-component-data.js: -------------------------------------------------------------------------------- ```javascript const 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, }, ]; export default data; ``` -------------------------------------------------------------------------------- /xmlui/src/components/Form/Form.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); } @layer components { .wrapper { display: flex; flex-direction: column; gap: createThemeVar("gap-Form"); } .buttonRow { display: flex; flex-direction: row; align-items: center; justify-content: flex-end; gap: createThemeVar("gap-buttonRow-Form"); margin-top: createThemeVar("marginTop-buttonRow-Form"); } } // --- We export the theme variables to add them to the component renderer :export { themeVars: t.json-stringify($themeVars); } ``` -------------------------------------------------------------------------------- /xmlui/src/components/ProgressBar/ProgressBar.md: -------------------------------------------------------------------------------- ```markdown %-DESC-START **Key features:** - **Percentage visualization**: Displays progress as a filled portion of a horizontal bar - **Flexible value handling**: Accepts values from 0 to 1, with automatic bounds handling for out-of-range values - **Extensive theming**: Customizable background color, indicator color, thickness, and border radius - **Responsive design**: Adapts to container width while maintaining consistent height %-DESC-END %-PROP-START value The following example demonstrates using it: ```xmlui-pg copy {2-6} display name="Example: value" height="200px" <App> <ProgressBar /> <ProgressBar value="0.2"/> <ProgressBar value="0.6"/> <ProgressBar value="1"/> <ProgressBar value="1.2"/> </App> ``` %-PROP-END ``` -------------------------------------------------------------------------------- /docs/content/components/HStack.md: -------------------------------------------------------------------------------- ```markdown # HStack [#hstack] This component is inherited from [Stack](/components/Stack) See also: [CHStack](/components/CHStack), [CVStack](/components/CVStack), [VStack](/components/VStack) `HStack` is a specialized, shorthand version for the regular `Stack` component with a horizontal orientation. ```xmlui-pg copy display name="Example: HStack" <App> <HStack> <Stack height="32px" width="32px" backgroundColor="red" /> <Stack height="32px" width="32px" backgroundColor="blue" /> <Stack height="32px" width="32px" backgroundColor="green" /> </HStack> </App> ``` >[!INFO] > You cannot change the orientation of `HStack` from horizontal to vertical by setting the `orientation` prop, as the engine ignores that setting. ``` -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- ```markdown --- name: Bug report about: Create a report to help us improve title: '' labels: '' assignees: '' --- **Description:** [A clear and concise description of what the bug is.] **Steps to Reproduce:** 1. [First Step] 2. [Second Step] 3. [and so on...] **Expected Behavior:** [A clear and concise description of what you expected to happen.] **Actual Behavior:** [A clear and concise description of what actually happened.] **Screenshots/Additional Information:** [If applicable, add screenshots or any additional information that may help explain the issue.] **Environment:** - **xmlui Version:** [e.g., 1.0.0] - **Browser/Environment:** [e.g., Chrome 90.0.4430.212 on macOS 11.3] - **Operating System:** [e.g., macOS, Windows, Linux] ``` -------------------------------------------------------------------------------- /xmlui/src/components/Image/Image.module.scss: -------------------------------------------------------------------------------- ```scss @use "../../components-core/theming/themes" as t; // --- This code snippet is required to collect the theme variables used in this module $themeVars: (); @function createThemeVar($componentVariable) { $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; @return t.getThemeVar($themeVars, $componentVariable); } @layer components { .img { display: block; width: 100%; height: 100%; object-fit: contain; border-radius: createThemeVar("borderRadius-Image"); border-color: createThemeVar("borderColor-Image"); &.clickable { cursor: pointer; } } } // --- We export the theme variables to add them to the component renderer :export{ themeVars: t.json-stringify($themeVars) } ``` -------------------------------------------------------------------------------- /xmlui/src/components/NoResult/NoResult.md: -------------------------------------------------------------------------------- ```markdown %-PROP-START hideIcon ```xmlui-pg copy display name="Example: hideIcon" <App> <FlowLayout> <NoResult hideIcon="true" width="50%" /> <NoResult hideIcon="false" width="50%" /> </FlowLayout> </App> ``` %-PROP-END %-PROP-START icon This property defines the icon to display with the component. For a list of of available icons consult [`Icon` documentation](/components/Icon). ```xmlui-pg copy display name="Example: icon" <App> <NoResult icon="error" height="100%" /> </App> ``` %-PROP-END %-PROP-START label Customize the displayed text using this property. Leave empty to omit it. ```xmlui-pg copy display name="Example: label" <App> <NoResult label="Sorry, found nothing!" height="100%" /> </App> ``` %-PROP-END ``` -------------------------------------------------------------------------------- /xmlui/src/components/PositionedContainer/PositionedContainer.module.scss: -------------------------------------------------------------------------------- ```scss @use "../../components-core/theming/themes" as t; // --- This code snippet is required to collect the theme variables used in this module $themeVars: (); @function createThemeVar($componentVariable) { $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; @return t.getThemeVar($themeVars, $componentVariable); } @layer components { .wrapper { position: absolute; &.visibleOnHover { transition: opacity 0.1s; opacity: 0; } } :has(> .wrapper) { position: relative; &:hover { .wrapper.visibleOnHover { opacity: 1; } } } } // --- We export the theme variables to add them to the component renderer :export { themeVars: t.json-stringify($themeVars); } ``` -------------------------------------------------------------------------------- /docs/content/components/VStack.md: -------------------------------------------------------------------------------- ```markdown # VStack [#vstack] This component is inherited from [Stack](/components/Stack) See also: [CHStack](/components/CHStack), [CVStack](/components/CVStack), [HStack](/components/HStack) `VStack` is a specialized, shorthand version for the regular [Stack](./Stack) component with a vertical orientation. ```xmlui-pg copy display name="Example: VStack" <App> <VStack> <Stack height="32px" width="32px" backgroundColor="red" /> <Stack height="32px" width="32px" backgroundColor="blue" /> <Stack height="32px" width="32px" backgroundColor="green" /> </VStack> </App> ``` >[!INFO] > You cannot change the orientation of `VStack` from vertical to horizontal by setting the `orientation` prop, as the engine ignores that setting. ``` -------------------------------------------------------------------------------- /xmlui/src/components/IFrame/IFrame.module.scss: -------------------------------------------------------------------------------- ```scss @use "../../components-core/theming/themes" as t; // --- This code snippet is required to collect the theme variables used in this module $themeVars: (); @function createThemeVar($componentVariable) { $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; @return t.getThemeVar($themeVars, $componentVariable); } $component: "IFrame"; $themeVars: t.composeBorderVars($themeVars, $component); @layer components { .iframe { @include t.borderVars($themeVars, $component); display: block; width: createThemeVar("width-IFrame"); height: createThemeVar("height-IFrame"); } } // --- We export the theme variables to add them to the component renderer :export{ themeVars: t.json-stringify($themeVars) } ``` -------------------------------------------------------------------------------- /xmlui/src/components/SpaceFiller/SpaceFiller.tsx: -------------------------------------------------------------------------------- ```typescript import styles from "./SpaceFiller.module.scss"; import { createComponentRenderer } from "../../components-core/renderers"; import { parseScssVar } from "../../components-core/theming/themeVars"; import { SpaceFiller } from "./SpaceFillerNative"; import { createMetadata } from "../metadata-helpers"; const COMP = "SpaceFiller"; export const SpaceFillerMd = createMetadata({ status: "stable", description: "`SpaceFiller` works well in layout containers to fill remaining (unused) " + "space. Its behavior depends on the layout container in which it is used.", themeVars: parseScssVar(styles.themeVars), }); export const spaceFillerComponentRenderer = createComponentRenderer(COMP, SpaceFillerMd, () => ( <SpaceFiller /> )); ``` -------------------------------------------------------------------------------- /xmlui/tests/components-core/scripts-runner/parser-regression.test.ts: -------------------------------------------------------------------------------- ```typescript import { describe, expect, it } from "vitest"; import { Parser } from "../../../src/parsers/scripting/Parser"; import { evalBinding } from "../../../src/components-core/script-runner/eval-tree-sync"; import { createEvalContext } from "../../../src/components-core/script-runner/BindingTreeEvaluationContext"; describe("Parser - regression (exp)", () => { it("Function call: 'true.toString()'", () => { // --- Arrange const wParser = new Parser("true.toString()"); const expr = wParser.parseExpr(); expect(expr).not.equal(null); if (!expr) return; // --- Act const context = createEvalContext({ localContext: {} }); const value = evalBinding(expr, context); // --- Assert expect(value).equal("true"); }); }); ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/action/NavigateAction.tsx: -------------------------------------------------------------------------------- ```typescript import type { ActionExecutionContext } from "../../abstractions/ActionDefs"; import { createUrlWithQueryParams } from "../../components/component-utils"; import { createAction } from "./actions"; function navigate( { navigate, location }: ActionExecutionContext, pathname: string | number, queryParams?: Record<string, any>, ) { // https://stackoverflow.com/questions/37385570/how-to-know-if-react-router-can-go-back-to-display-back-button-in-react-app if (pathname === -1 && location.key === "default") { navigate("."); return; } const to = queryParams ? createUrlWithQueryParams({ pathname, queryParams, }) : pathname; navigate(to); } export const navigateAction = createAction("navigate", navigate); ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/appContext/date-functions.ts: -------------------------------------------------------------------------------- ```typescript import { formatDate, formatDateTime, formatDateWithoutYear, formatTime, formatTimeWithoutSeconds, getDate, getDateUntilNow, isDateToday, isDateTomorrow, isDateYesterday, isoDateString, smartFormatDate, smartFormatDateTime, formatHumanElapsedTime } from "../utils/date-utils"; import { differenceInMinutes, isSameDay, isThisYear } from "date-fns"; export const dateFunctions = { isoDateString, formatDate, formatDateTime, formatTime, formatTimeWithoutSeconds, formatDateWithoutYear, getDate, getDateUntilNow, smartFormatDateTime, smartFormatDate, isToday: isDateToday, isYesterday: isDateYesterday, isTomorrow: isDateTomorrow, differenceInMinutes, isSameDay, isThisYear, formatHumanElapsedTime }; ``` -------------------------------------------------------------------------------- /docs/public/pages/howto/hide-an-element-until-its-datasource-is-ready.md: -------------------------------------------------------------------------------- ```markdown # Hide an element until its DataSource is ready ```xmlui-pg noHeader ---app <App> <Test /> </App> ---api { "apiUrl": "/api", "initialize": "$state.fruits = [ { id: 1, name: 'Orange' }, { id: 2, name: 'Apple' }, { id: 3, name: 'Pear' }, ]", "operations": { "get-fruits": { "url": "/fruits", "method": "get", "handler": "delay(3000); return $state.fruits;" } } } ---comp display <Component name="Test" var.nonce="{0}"> <DataSource id="fruits" url="/api/fruits?{nonce}" inProgressNotificationMessage="Loading fruits" when="{nonce > 0}" /> <Button label="Run" onClick="{nonce++}" /> <Fragment when="{fruits.loaded}"> <Text>Fruits: {fruits.value.length} found</Text> </Fragment> </Component> ``` ``` -------------------------------------------------------------------------------- /blog/index.html: -------------------------------------------------------------------------------- ```html <!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/resources/favicon.ico" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="alternate" type="application/rss+xml" title="XMLUI Blog" href="/feed.rss" /> <script>window.__PUBLIC_PATH = '/'</script> <base href="/"> <!-- Google tag (gtag.js) --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-S7NYYDMNPR"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-S7NYYDMNPR'); </script> </head> <body> <div id="root"></div> <script type="module" src="/index.ts"></script> </body> </html> ``` -------------------------------------------------------------------------------- /docs/public/pages/xmlui-pdf/Pdf.md: -------------------------------------------------------------------------------- ```markdown # Pdf [#pdf] >[!WARNING] > This component is in an **experimental** state; you can use it in your app. However, we may modify it, and it may even have breaking changes in the future.The `Pdf` component provides a read-only preview of a pdf document's contents. ## Properties ### `src` This property defines the source URL of the pdf document to display. ## Events This component does not have any events. ## Exposed Methods This component does not expose any methods. ## Styling ### Theme Variables | Variable | Default Value (Light) | Default Value (Dark) | | --- | --- | --- | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-page-Pdf | $boxShadow-md | $boxShadow-md | | [gap](../styles-and-themes/common-units/#size)-pages-Pdf | $space-4 | $space-4 | ``` -------------------------------------------------------------------------------- /xmlui/scripts/coverage-only.js: -------------------------------------------------------------------------------- ```javascript #!/usr/bin/env node const script = require('./e2e-test-summary.js'); // Run without executing tests, just show coverage console.log('XMLUI E2E Test Coverage Report'); console.log('===============================\n'); console.log('1. Extracting XMLUI components from metadata...'); const components = script.getXMLUIComponents(); console.log(` Found ${components.length} XMLUI components`); console.log('2. Scanning for e2e test files...'); const testFiles = script.getE2ETestFiles(); console.log(` Found ${testFiles.length} e2e test files`); console.log('3. Mapping components to test files...'); const componentTestMap = script.mapComponentsToTestFiles(components, testFiles); // Display summary without test results script.displaySummary(components, componentTestMap, null); ``` -------------------------------------------------------------------------------- /docs/content/components/CHStack.md: -------------------------------------------------------------------------------- ```markdown # CHStack [#chstack] This component is inherited from [Stack](/components/Stack) See also: [CVStack](/components/CVStack), [HStack](/components/HStack), [VStack](/components/VStack) `CHStack` is a specialized, shorthand version for the regular `Stack` component that has a horizontal orientation with its contents centered. ```xmlui-pg copy display name="Example: CHStack" <App> <CHStack backgroundColor="cyan"> <Stack height="32px" width="32px" backgroundColor="red" /> <Stack height="32px" width="32px" backgroundColor="blue" /> <Stack height="32px" width="32px" backgroundColor="green" /> </CHStack> </App> ``` >[!INFO] > You cannot change the orientation of `CHStack` from horizontal to vertical by setting the `orientation` prop, as the engine ignores that setting. ``` -------------------------------------------------------------------------------- /docs/content/components/CVStack.md: -------------------------------------------------------------------------------- ```markdown # CVStack [#cvstack] This component is inherited from [Stack](/components/Stack) See also: [CHStack](/components/CHStack), [HStack](/components/HStack), [VStack](/components/VStack) `CVStack` is a specialized, shorthand version for the regular `Stack` component with a vertical orientation centered on its contents. ```xmlui-pg copy display name="Example: CVStack" <App> <CVStack width="33%" backgroundColor="cyan"> <Stack height="32px" width="32px" backgroundColor="red" /> <Stack height="32px" width="32px" backgroundColor="blue" /> <Stack height="32px" width="32px" backgroundColor="green" /> </CVStack> </App> ``` >[!INFO] > You cannot change the orientation of `CVStack` from vertical to horizontal by setting the `orientation` prop, as the engine ignores that setting. ``` -------------------------------------------------------------------------------- /xmlui/bin/preview.ts: -------------------------------------------------------------------------------- ```typescript import { preview as vitePreview } from "vite"; import { getViteConfig } from "./viteConfig"; export const preview = async ({proxy}) => { try { let proxyDef; if (proxy) { const splitProxy = proxy.split("->"); if (splitProxy.length !== 2) { console.error("Invalid proxy definition. Example: /api->http://localhost:3000"); } else { proxyDef = { [splitProxy[0]]: { target: splitProxy[1], changeOrigin: true, }, }; } } const server = await vitePreview({ ...getViteConfig(), server: { proxy: proxyDef, }, }); if (!server.httpServer) { throw new Error("HTTP server not available"); } server.printUrls(); } catch (e) { process.exit(1); } }; ``` -------------------------------------------------------------------------------- /docs/content/components/xmlui-animations/FadeInAnimation.md: -------------------------------------------------------------------------------- ```markdown # FadeInAnimation [#fadeinanimation] The `FadeInAnimation` component represents an animation that fades in the content. ## Properties ### `animateWhenInView` Indicates whether the animation should start when the component is in view ### `delay` (default: 0) The delay before the animation starts in milliseconds ### `duration` The duration of the animation in milliseconds ### `loop` (default: false) Indicates whether the animation should loop ### `reverse` (default: false) Indicates whether the animation should run in reverse ## Events ### `started` Event fired when the animation starts ### `stopped` Event fired when the animation stops ## Exposed Methods ### `start` Starts the animation ### `stop` Stops the animation ## Styling This component does not have any styles. ``` -------------------------------------------------------------------------------- /docs/content/extensions/xmlui-animations/FadeInAnimation.md: -------------------------------------------------------------------------------- ```markdown # FadeInAnimation [#fadeinanimation] The `FadeInAnimation` component represents an animation that fades in the content. ## Properties ### `animateWhenInView` Indicates whether the animation should start when the component is in view ### `delay` (default: 0) The delay before the animation starts in milliseconds ### `duration` The duration of the animation in milliseconds ### `loop` (default: false) Indicates whether the animation should loop ### `reverse` (default: false) Indicates whether the animation should run in reverse ## Events ### `started` Event fired when the animation starts ### `stopped` Event fired when the animation stops ## Exposed Methods ### `start` Starts the animation ### `stop` Stops the animation ## Styling This component does not have any styles. ``` -------------------------------------------------------------------------------- /docs/content/components/xmlui-animations/FadeOutAnimation.md: -------------------------------------------------------------------------------- ```markdown # FadeOutAnimation [#fadeoutanimation] The `FadeOutAnimation` component represents an animation that fades out the content. ## Properties ### `animateWhenInView` Indicates whether the animation should start when the component is in view ### `delay` (default: 0) The delay before the animation starts in milliseconds ### `duration` The duration of the animation in milliseconds ### `loop` (default: false) Indicates whether the animation should loop ### `reverse` (default: false) Indicates whether the animation should run in reverse ## Events ### `started` Event fired when the animation starts ### `stopped` Event fired when the animation stops ## Exposed Methods ### `start` Starts the animation ### `stop` Stops the animation ## Styling This component does not have any styles. ``` -------------------------------------------------------------------------------- /docs/content/extensions/xmlui-animations/FadeOutAnimation.md: -------------------------------------------------------------------------------- ```markdown # FadeOutAnimation [#fadeoutanimation] The `FadeOutAnimation` component represents an animation that fades out the content. ## Properties ### `animateWhenInView` Indicates whether the animation should start when the component is in view ### `delay` (default: 0) The delay before the animation starts in milliseconds ### `duration` The duration of the animation in milliseconds ### `loop` (default: false) Indicates whether the animation should loop ### `reverse` (default: false) Indicates whether the animation should run in reverse ## Events ### `started` Event fired when the animation starts ### `stopped` Event fired when the animation stops ## Exposed Methods ### `start` Starts the animation ### `stop` Stops the animation ## Styling This component does not have any styles. ``` -------------------------------------------------------------------------------- /packages/xmlui-os-frames/package.json: -------------------------------------------------------------------------------- ```json { "name": "xmlui-os-frames", "version": "0.1.0", "sideEffects": false, "type": "module", "private": true, "scripts": { "start": "xmlui start", "preview": "xmlui preview", "build:extension": "xmlui build-lib", "build-watch": "xmlui build-lib --watch", "build:demo": "xmlui build", "build:meta": "xmlui build-lib --mode=metadata" }, "dependencies": {}, "devDependencies": { "xmlui": "*" }, "main": "./dist/xmlui-os-frames.js", "module": "./dist/xmlui-os-frames.mjs", "exports": { ".": { "import": "./dist/xmlui-os-frames.mjs", "require": "./dist/xmlui-os-frames.js" }, "./*.css": { "import": "./dist/*.css", "require": "./dist/*.css" } }, "files": [ "dist" ], "engines": { "node": ">=18.0.0" } } ``` -------------------------------------------------------------------------------- /packages/xmlui-pdf/package.json: -------------------------------------------------------------------------------- ```json { "name": "xmlui-pdf", "version": "0.1.11", "sideEffects": false, "type": "module", "scripts": { "start": "xmlui start", "preview": "xmlui preview", "build:extension": "xmlui build-lib", "build-watch": "xmlui build-lib --watch", "build:demo": "xmlui build", "build:meta": "xmlui build-lib --mode=metadata" }, "dependencies": { "pdfjs-dist": "5.3.93", "react-pdf": "^10.1.0" }, "devDependencies": { "xmlui": "*" }, "main": "./dist/xmlui-pdf.js", "module": "./dist/xmlui-pdf.mjs", "exports": { ".": { "import": "./dist/xmlui-pdf.mjs", "require": "./dist/xmlui-pdf.js" }, "./*.css": { "import": "./dist/*.css", "require": "./dist/*.css" } }, "files": [ "dist" ], "engines": { "node": ">=18.0.0" } } ``` -------------------------------------------------------------------------------- /docs/public/pages/howto/react-to-button-click-not-keystrokes.md: -------------------------------------------------------------------------------- ```markdown # React to button click not keystrokes ```xmlui-pg noHeader ---app <App> <Test /> </App> ---comp display <!-- Use two different variables --> <Component name="Test" var.searchText="" var.triggerSearch="{false}"> <TextBox id="searchInput" placeholder="Type something..." width="300px" /> <Button label="Search" onClick="searchText = searchInput.value; triggerSearch = true" /> <DataSource id="searchResults" url="https://httpbin.org/post" body="{JSON.stringify({query: searchText})}" method="POST" when="{triggerSearch}" onDidLoad="triggerSearch = false" /> <Fragment when="{searchResults.loaded}"> <Text>Search results for: {searchText}</Text> <Text>Response received: {searchResults.value.json ? 'Yes' : 'No'}</Text> </Fragment> </Component> ``` ``` -------------------------------------------------------------------------------- /xmlui/src/components/StickyBox/StickyBox.module.scss: -------------------------------------------------------------------------------- ```scss @use "../../components-core/theming/themes" as t; // --- This code snippet is required to collect the theme variables used in this module $themeVars: (); @function createThemeVar($componentVariable) { $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; @return t.getThemeVar($themeVars, $componentVariable); } @layer components { .wrapper { z-index: 1; } .sentinel ~ *:has([data-anchor="true"]) { [data-anchor="true"] { //my-scroll-margin-top is set by the heading component, we have to take that into account, too scroll-margin-top: calc( var(--my-scroll-margin-top, 0px) + var(--xmlui-scroll-margin-top, 0px) ); } } } // --- We export the theme variables to add them to the component renderer :export { themeVars: t.json-stringify($themeVars); } ``` -------------------------------------------------------------------------------- /blog/CHANGELOG.md: -------------------------------------------------------------------------------- ```markdown # xmlui-blog ## 0.0.9 ### Patch Changes - eb6454f: refactor: change LineChart/BarChart property names - Updated dependencies [f12a042] - Updated dependencies [8731eb8] - Updated dependencies [eb6454f] - Updated dependencies [1210852] - [email protected] ## 0.0.8 ### Patch Changes - 819b563: Update fontSize and lineHeight themes and style (may break existing xmlui code) - Updated dependencies [8c76c8d] - Updated dependencies [d56c3e5] - Updated dependencies [e42d367] - Updated dependencies [f539526] - Updated dependencies [19ce234] - Updated dependencies [455b6c0] - Updated dependencies [e90dc73] - Updated dependencies [819b563] - Updated dependencies [b57dfa2] - Updated dependencies [9dd0f97] - Updated dependencies [19ce234] - Updated dependencies [898346d] - Updated dependencies [705dd04] - [email protected] ``` -------------------------------------------------------------------------------- /tools/vscode/.vscode/tasks.json: -------------------------------------------------------------------------------- ```json { "version": "2.0.0", "tasks": [ { "label": "watch", "dependsOn": ["npm: watch:tsc", "npm: watch:esbuild"], "presentation": { "reveal": "never" }, "group": { "kind": "build", "isDefault": true } }, { "type": "npm", "script": "watch:esbuild", "group": "build", "problemMatcher": "$esbuild-watch", "isBackground": true, "label": "npm: watch:esbuild", "presentation": { "group": "watch", "reveal": "never" } }, { "type": "npm", "script": "watch:tsc", "group": "build", "problemMatcher": "$tsc-watch", "isBackground": true, "label": "npm: watch:tsc", "presentation": { "group": "watch", "reveal": "never" } } ] } ``` -------------------------------------------------------------------------------- /packages/xmlui-animations/package.json: -------------------------------------------------------------------------------- ```json { "name": "xmlui-animations", "version": "0.1.15", "sideEffects": false, "type": "module", "scripts": { "start": "xmlui start", "preview": "xmlui preview", "build:extension": "xmlui build-lib", "build-watch": "xmlui build-lib --watch", "build:demo": "xmlui build", "build:meta": "xmlui build-lib --mode=metadata" }, "dependencies": { "@react-spring/web": "^9.7.5" }, "devDependencies": { "xmlui": "*" }, "main": "./dist/xmlui-animations.js", "module": "./dist/xmlui-animations.mjs", "exports": { ".": { "import": "./dist/xmlui-animations.mjs", "require": "./dist/xmlui-animations.js" }, "./*.css": { "import": "./dist/*.css", "require": "./dist/*.css" } }, "files": [ "dist" ], "engines": { "node": ">=18.0.0" } } ``` -------------------------------------------------------------------------------- /xmlui/src/components/Accordion/Accordion.md: -------------------------------------------------------------------------------- ```markdown # Accordion %-PROP-START positionInGroup The possible values are: | Value | Description | | :------- | :----------------------------------------------------------------------- | | `single` | The accordion stands alone (not in a group) | | `first` | This accordion is the first in a group | | `middle` | This accordion is between the first and last items in an accordion group | | `last` | This accordion is the last in a group | By default, this value is `single`. %-PROP-END %-PROP-START rotateExpanded If this property has a value, only the collapsed icon is used. When the accordion is expanded, the collapsed icon is rotated with this angle. %-PROP-END ``` -------------------------------------------------------------------------------- /xmlui/src/testing/drivers/NumberBoxDriver.ts: -------------------------------------------------------------------------------- ```typescript import { PART_START_ADORNMENT, PART_END_ADORNMENT, PART_INPUT } from "../../components-core/parts"; import { InputComponentDriver } from "../ComponentDrivers"; const PART_SPINNER_UP = "spinnerUp"; const PART_SPINNER_DOWN = "spinnerDown"; export class NumberBoxDriver extends InputComponentDriver { get input() { return this.getByPartName(PART_INPUT); } get startAdornment() { return this.getByPartName(PART_START_ADORNMENT); } get endAdornment() { return this.getByPartName(PART_END_ADORNMENT); } get spinnerUp() { return this.getByPartName(PART_SPINNER_UP); } get spinnerDown() { return this.getByPartName(PART_SPINNER_DOWN); } async increment() { await this.spinnerUp.click({ force: true }); } async decrement() { await this.spinnerDown.click({ force: true }); } } ``` -------------------------------------------------------------------------------- /packages/xmlui-hello-world/package.json: -------------------------------------------------------------------------------- ```json { "name": "xmlui-hello-world", "version": "0.1.0", "sideEffects": false, "type": "module", "scripts": { "start": "xmlui start", "preview": "xmlui preview", "build:extension": "xmlui build-lib", "build-watch": "xmlui build-lib --watch", "build:demo": "xmlui build", "build:meta": "xmlui build-lib --mode=metadata" }, "devDependencies": { "xmlui": "*" }, "main": "./dist/xmlui-hello-world.js", "module": "./dist/xmlui-hello-world.mjs", "exports": { ".": { "import": "./dist/xmlui-hello-world.mjs", "require": "./dist/xmlui-hello-world.js" }, "./*.css": { "import": "./dist/*.css", "require": "./dist/*.css" } }, "files": [ "dist" ], "engines": { "node": ">=18.0.0" }, "author": "", "license": "ISC", "description": "" } ``` -------------------------------------------------------------------------------- /xmlui/tests-e2e/datasource-onLoaded-regression.spec.ts: -------------------------------------------------------------------------------- ```typescript import { expect, test } from "../src/testing/fixtures"; test("onLoaded has access to the loaded datasource state", async ({ page, initTestBed }) => { await initTestBed( ` <Fragment var.dataFromOnLoaded="{[]}"> <DataSource url="/data1" id="data" onLoaded="dataFromOnLoaded = data.value;"/> <List data="{dataFromOnLoaded}" testId="list"> <property name="emptyListTemplate"> <Text testId="emptyLabel">Empty</Text> </property> </List> </Fragment> `, { apiInterceptor: { operations: { "load-api-data1": { url: "/data1", method: "get", handler: `() => { return ['data1', 'data2']; }`, }, }, }, }, ); await expect(page.getByTestId("list")).toHaveText("data1data2"); }); ``` -------------------------------------------------------------------------------- /xmlui/src/components/Timer/Timer.md: -------------------------------------------------------------------------------- ```markdown %-DESC-START ## Using Timer The following sample demonstrates many aspects of the `Timer` component. Use the switches and the buttons to observe how the component works. ```xmlui-pg display copy name="Using Timer" <App var.count="{0}"> <Text> Count: {count} | Timer is {timer.isPaused() ? 'paused' : 'running'} </Text> <Timer id="timer" initialDelay="2000" interval="200" onTick="count++;" enabled="{enable.value}" once="{once.value}" /> <Switch id="enable" label="Enable Timer" initialValue="true" /> <Switch id="once" label="Run Once" initialValue="{false}" /> <HStack> <Button onClick="timer.pause()" enabled="{!timer.isPaused()}"> Pause </Button> <Button onClick="timer.resume()" enabled="{timer.isPaused()}"> Resume </Button> </HStack> </App> ``` %-DESC-END ``` -------------------------------------------------------------------------------- /xmlui/src/components/HoverCard/HoverCard.tsx: -------------------------------------------------------------------------------- ```typescript import { createComponentRenderer } from "../../components-core/renderers"; import { createMetadata, dComponent } from "../metadata-helpers"; import { HoverCardComponent } from "./HovercardNative"; const COMP = "HoverCard"; export const HoverCardMd = createMetadata({ status: "deprecated", description: "(**OBSOLETE**) This component displays some content when its parent component is hovered.", props: { triggerTemplate: dComponent("The component that opens the hover card when hovered."), }, }); export const hoverCardComponentRenderer = createComponentRenderer( COMP, HoverCardMd, ({ node, extractValue, renderChild }) => { return ( <HoverCardComponent triggerTemplate={renderChild(extractValue(node.props.triggerTemplate))}> {renderChild(node.children)} </HoverCardComponent> ); }, ); ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/theming/themes/base-utils.ts: -------------------------------------------------------------------------------- ```typescript type PaddingValue = { left?: string; right?: string; top?: string; bottom?: string; horizontal?: string; vertical?: string; all?: string; }; export function paddingSubject(name: string, valueSpec?: PaddingValue): Record<string, string> { return { [`paddingLeft-${name}`]: valueSpec?.left ?? `$paddingHorizontal-${name}`, [`paddingRight-${name}`]: valueSpec?.right ?? `$paddingHorizontal-${name}`, [`paddingTop-${name}`]: valueSpec?.top ?? `$paddingVertical-${name}`, [`paddingBottom-${name}`]: valueSpec?.bottom ?? `$paddingVertical-${name}`, [`paddingHorizontal-${name}`]: valueSpec?.horizontal ?? "", [`paddingVertical-${name}`]: valueSpec?.vertical ?? "", [`padding-${name}`]: valueSpec?.all ?? `$paddingTop-${name} $paddingRight-${name} $paddingBottom-${name} $paddingLeft-${name}`, }; } ``` -------------------------------------------------------------------------------- /packages/xmlui-website-blocks/package.json: -------------------------------------------------------------------------------- ```json { "name": "xmlui-website-blocks", "version": "0.1.4", "sideEffects": false, "type": "module", "scripts": { "start": "xmlui start", "preview": "xmlui preview", "build:extension": "xmlui build-lib", "build-watch": "xmlui build-lib --watch", "build:demo": "xmlui build", "build:meta": "xmlui build-lib --mode=metadata" }, "dependencies": { "@react-spring/web": "^9.7.5" }, "devDependencies": { "xmlui": "*" }, "main": "./dist/xmlui-website-blocks.js", "module": "./dist/xmlui-website-blocks.mjs", "exports": { ".": { "import": "./dist/xmlui-website-blocks.mjs", "require": "./dist/xmlui-website-blocks.js" }, "./*.css": { "import": "./dist/*.css", "require": "./dist/*.css" } }, "files": [ "dist" ], "engines": { "node": ">=18.0.0" } } ``` -------------------------------------------------------------------------------- /xmlui/src/components/Select/HiddenOption.tsx: -------------------------------------------------------------------------------- ```typescript import type { Option } from "../abstractions"; import { useOption } from "./OptionContext"; import React, { useEffect, useMemo, useState } from "react"; export function HiddenOption(option: Option) { const { label } = option; const { onOptionRemove, onOptionAdd } = useOption(); const [node, setNode] = useState(null); const opt: Option = useMemo(() => { return { ...option, label: label ?? node?.textContent ?? "", keywords: option.keywords || [label ?? node?.textContent ?? ""], // Store the rendered ReactNode for dropdown display }; }, [option, node, label]); useEffect(() => { onOptionAdd(opt); return () => onOptionRemove(opt); }, [opt, onOptionAdd, onOptionRemove]); return ( <div ref={(el) => setNode(el)} style={{ display: "none" }}> {option.children} </div> ); } ``` -------------------------------------------------------------------------------- /docs/content/components/Legend.md: -------------------------------------------------------------------------------- ```markdown # Legend [#legend] `Legend` provides a standalone legend for chart components when you need custom positioning or styling beyond the chart's built-in `showLegend` property. Most charts can display legends automatically, but this component offers precise control over legend placement and alignment. ## Properties [#properties] ### `align` (default: "center") [#align-default-center] The alignment of the legend Available values: `left`, `right`, `center` **(default)** ### `verticalAlign` (default: "bottom") [#verticalalign-default-bottom] The vertical alignment of the legend Available values: `top`, `bottom` **(default)**, `middle` ## Events [#events] This component does not have any events. ## Exposed Methods [#exposed-methods] This component does not expose any methods. ## Styling [#styling] This component does not have any styles. ``` -------------------------------------------------------------------------------- /packages/xmlui-search/package.json: -------------------------------------------------------------------------------- ```json { "name": "xmlui-search", "version": "0.1.4", "sideEffects": false, "type": "module", "scripts": { "start": "xmlui start", "preview": "xmlui preview", "build:extension": "xmlui build-lib", "build-watch": "xmlui build-lib --watch", "build:demo": "xmlui build", "build:meta": "xmlui build-lib --mode=metadata" }, "devDependencies": { "xmlui": "*" }, "main": "./dist/xmlui-search.js", "module": "./dist/xmlui-search.mjs", "exports": { ".": { "import": "./dist/xmlui-search.mjs", "require": "./dist/xmlui-search.js" }, "./*.css": { "import": "./dist/*.css", "require": "./dist/*.css" } }, "files": [ "dist" ], "engines": { "node": ">=18.0.0" }, "author": "", "license": "ISC", "description": "", "dependencies": { "fuse.js": "^7.1.0" } } ``` -------------------------------------------------------------------------------- /xmlui/src/syntax/monaco/xmlui-dark.ts: -------------------------------------------------------------------------------- ```typescript const darkTheme = { base: "vs-dark", inherit: true, rules: [ { token: "comment", foreground: "#9296a9" }, { token: "comment.content", foreground: "#9296a9", fontStyle: "italic" }, { token: "tag-component", foreground: "#FE6BAD" }, { token: "tag-event", foreground: "#80A6F8" }, { token: "tag-helper", foreground: "#80A6F8" }, { token: "attribute", foreground: "#cbd5e1" }, { token: "operators", foreground: "#cbd5e1" }, { token: "delimiter.angle", foreground: "#97A7C5" }, { token: "delimiter.curly", foreground: "#FFD502" }, { token: "string", foreground: "#7dd3fc" }, { token: "tag-cdata", foreground: "#5CC1F9" }, { token: "tag-script", foreground: "#78DBDB" }, { token: "string.escape", foreground: "#BAF80A" }, ], colors: { "editor.background": "#17232b", }, }; export default darkTheme; ``` -------------------------------------------------------------------------------- /xmlui/src/components/ProgressBar/ProgressBarNative.tsx: -------------------------------------------------------------------------------- ```typescript import type { CSSProperties, ForwardedRef} from "react"; import { forwardRef } from "react"; import classnames from "classnames"; import styles from "./ProgressBar.module.scss"; interface Props { value: number; style?: CSSProperties; className?: string; } export const defaultProps = { value: 0, }; export const ProgressBar = forwardRef(function ProgressBar( { value = defaultProps.value, style, className, ...rest }: Props, forwardedRef: ForwardedRef<HTMLDivElement>, ) { return ( <div {...rest} className={classnames(styles.wrapper, className)} style={style} ref={forwardedRef} > <div role="progressbar" aria-valuenow={value * 100} aria-valuemin={0} aria-valuemax={100} style={{ width: `${value * 100}%` }} className={styles.bar} /> </div> ); }); ``` -------------------------------------------------------------------------------- /packages/xmlui-search/CHANGELOG.md: -------------------------------------------------------------------------------- ```markdown # xmlui-search ## 0.1.4 ### Patch Changes - e3f6af0: Fixed an issue where longer search terms in Search did not have results. Now long text search is handled up to around 70 characters. - ccb4bf7: Fixed an extra scrollbar appearing when a navigation group is open in the drawer alongside the Search dropdown. ## 0.1.3 ### Patch Changes - d349036: Tweaked Search dropdown panel styles. Corrected Link component text and decoration hover and active colors ## 0.1.2 ### Patch Changes - 4f1f4b7: Refined search term highlighting to better fit results. ## 0.1.1 ### Patch Changes - c433512: Removed close button from TextBox if type="search". Move the Search package from internal, add arrow key selection in search results and add use it in navigation drawer on small screens. - fb6ba38: Fixed inconsistent styling of keyboard item selection and mouse hover. ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/InspectorButton.module.scss: -------------------------------------------------------------------------------- ```scss @use "./theming/themes" as themes; .wrapper { position: relative; opacity: .6; gap: themes.$space-1; padding: themes.$space-1_5 !important; &:hover { opacity: 1; } button[data-popper-reference-hidden='true'] { opacity: 0; pointer-events: none; display: none; } } .inspectableNode { outline: 1px solid themes.$outlineColor--focus; outline-offset: 4px; position: relative; } .inspectableNode:hover { outline: 2px solid themes.$color-primary-500; } .inspectOverlay { cursor: pointer; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: transparent; z-index: 1000; pointer-events: auto; } .inspectOverlay:hover { background: rgba(32, 107, 196, 0.1); } .inspectedNode { outline: 2px solid themes.$color-primary-500; .inspectOverlay { background: rgba(32, 107, 196, 0.1); } } ``` -------------------------------------------------------------------------------- /xmlui/src/components/ComponentRegistryContext.tsx: -------------------------------------------------------------------------------- ```typescript import React, { useContext } from "react"; import type { ComponentRendererFn } from "../abstractions/RendererDefs"; import type { ComponentMetadata } from "../abstractions/ComponentDefs"; import type { ComponentRegistry } from "./ComponentProvider"; // A single registry entry export type ComponentRegistryEntry = { // The function that renders a component definition into a React component renderer: ComponentRendererFn<any>; // Component descriptor (hints and other metadata) descriptor?: ComponentMetadata; isCompoundComponent?: boolean; }; // Context object that makes the component registry available export const ComponentRegistryContext = React.createContext<ComponentRegistry | null>(null); // Use this hook within a component to access the component registry export function useComponentRegistry() { return useContext(ComponentRegistryContext)!; } ``` -------------------------------------------------------------------------------- /xmlui/src/components/Icon/svg/unknown-file.svg: -------------------------------------------------------------------------------- ``` <svg viewBox="0 0 22 28" fill="none" xmlns="http://www.w3.org/2000/svg"> <g clip-path="url(#clip0_1811_14989)"> <path d="M22.2271 7.38281L16.304 5.74219L14.6117 0H1.91936C0.984697 0 0.227051 0.734508 0.227051 1.64062V26.3594C0.227051 27.2655 0.984697 28 1.91936 28H20.5347C21.4694 28 22.2271 27.2655 22.2271 26.3594V7.38281Z" fill="#C9E3F4"/> <path d="M22.2271 7.38281V26.3594C22.2271 27.2655 21.4695 28 20.5348 28H11.3625V0H14.6117L16.304 5.74219L22.2271 7.38281Z" fill="#C9E3F4"/> <path d="M22.227 7.38281H16.3039C15.3731 7.38281 14.6116 6.64453 14.6116 5.74219V0C14.8316 0 15.0516 0.0820312 15.2038 0.246148L21.9731 6.80865C22.1423 6.95625 22.227 7.16953 22.227 7.38281Z" fill="#AAC4D6"/> </g> <defs> <clipPath id="clip0_1811_14989"> <rect width="22" height="28" fill="white"/> </clipPath> </defs> </svg> ``` -------------------------------------------------------------------------------- /xmlui/src/syntax/monaco/xmlui-light.ts: -------------------------------------------------------------------------------- ```typescript const lightTheme = { base: "vs", inherit: true, rules: [ { token: "comment", foreground: "#606060" }, { token: "comment.content", foreground: "#606060", fontStyle: "italic" }, { token: "tag-component", foreground: "#B33175" }, { token: "tag-event", foreground: "#005AE1" }, { token: "tag-helper", foreground: "#005AE1" }, { token: "attribute", foreground: "#2D2D2D" }, { token: "operators", foreground: "#2D2D2D" }, { token: "delimiter.angle", foreground: "#66748E" }, { token: "delimiter.curly", foreground: "#F07100", fontStyle: "bold" }, { token: "string", foreground: "#0074a9"}, { token: "tag-cdata", foreground: "#079CF1" }, { token: "tag-script", foreground: "#02A1A1" }, { token: "string.escape", foreground: "#708C00" }, ], colors: { "editor.foreground": "#0D458C", }, }; export default lightTheme; ``` -------------------------------------------------------------------------------- /blog/public/resources/pg-popout.svg: -------------------------------------------------------------------------------- ``` <svg stroke="currentColor" fill="none" stroke-width="0" viewBox="0 0 15 15" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 13C12.5523 13 13 12.5523 13 12V3C13 2.44771 12.5523 2 12 2H3C2.44771 2 2 2.44771 2 3V6.5C2 6.77614 2.22386 7 2.5 7C2.77614 7 3 6.77614 3 6.5V3H12V12H8.5C8.22386 12 8 12.2239 8 12.5C8 12.7761 8.22386 13 8.5 13H12ZM9 6.5C9 6.5001 9 6.50021 9 6.50031V6.50035V9.5C9 9.77614 8.77614 10 8.5 10C8.22386 10 8 9.77614 8 9.5V7.70711L2.85355 12.8536C2.65829 13.0488 2.34171 13.0488 2.14645 12.8536C1.95118 12.6583 1.95118 12.3417 2.14645 12.1464L7.29289 7H5.5C5.22386 7 5 6.77614 5 6.5C5 6.22386 5.22386 6 5.5 6H8.5C8.56779 6 8.63244 6.01349 8.69139 6.03794C8.74949 6.06198 8.80398 6.09744 8.85143 6.14433C8.94251 6.23434 8.9992 6.35909 8.99999 6.49708L8.99999 6.49738" fill="currentColor"></path></svg> ``` -------------------------------------------------------------------------------- /docs/public/resources/pg-popout.svg: -------------------------------------------------------------------------------- ``` <svg stroke="currentColor" fill="none" stroke-width="0" viewBox="0 0 15 15" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 13C12.5523 13 13 12.5523 13 12V3C13 2.44771 12.5523 2 12 2H3C2.44771 2 2 2.44771 2 3V6.5C2 6.77614 2.22386 7 2.5 7C2.77614 7 3 6.77614 3 6.5V3H12V12H8.5C8.22386 12 8 12.2239 8 12.5C8 12.7761 8.22386 13 8.5 13H12ZM9 6.5C9 6.5001 9 6.50021 9 6.50031V6.50035V9.5C9 9.77614 8.77614 10 8.5 10C8.22386 10 8 9.77614 8 9.5V7.70711L2.85355 12.8536C2.65829 13.0488 2.34171 13.0488 2.14645 12.8536C1.95118 12.6583 1.95118 12.3417 2.14645 12.1464L7.29289 7H5.5C5.22386 7 5 6.77614 5 6.5C5 6.22386 5.22386 6 5.5 6H8.5C8.56779 6 8.63244 6.01349 8.69139 6.03794C8.74949 6.06198 8.80398 6.09744 8.85143 6.14433C8.94251 6.23434 8.9992 6.35909 8.99999 6.49708L8.99999 6.49738" fill="currentColor"></path></svg> ``` -------------------------------------------------------------------------------- /docs/content/components/xmlui-animations/Animation.md: -------------------------------------------------------------------------------- ```markdown # Animation [#animation] No description provided. ## Properties ### `animateWhenInView` Indicates whether the animation should start when the component is in view ### `animation` The animation object to be applied to the component ### `delay` (default: 0) The delay before the animation starts in milliseconds ### `duration` The duration of the animation in milliseconds ### `loop` (default: false) Indicates whether the animation should loop ### `once` (default: false) Indicates whether the animation should only run once ### `reverse` (default: false) Indicates whether the animation should run in reverse ## Events ### `started` Event fired when the animation starts ### `stopped` Event fired when the animation stops ## Exposed Methods ### `start` Starts the animation ### `stop` Stops the animation ## Styling This component does not have any styles. ``` -------------------------------------------------------------------------------- /docs/content/extensions/xmlui-animations/Animation.md: -------------------------------------------------------------------------------- ```markdown # Animation [#animation] No description provided. ## Properties ### `animateWhenInView` Indicates whether the animation should start when the component is in view ### `animation` The animation object to be applied to the component ### `delay` (default: 0) The delay before the animation starts in milliseconds ### `duration` The duration of the animation in milliseconds ### `loop` (default: false) Indicates whether the animation should loop ### `once` (default: false) Indicates whether the animation should only run once ### `reverse` (default: false) Indicates whether the animation should run in reverse ## Events ### `started` Event fired when the animation starts ### `stopped` Event fired when the animation stops ## Exposed Methods ### `start` Starts the animation ### `stop` Stops the animation ## Styling This component does not have any styles. ``` -------------------------------------------------------------------------------- /docs/content/components/xmlui-animations/SlideInAnimation.md: -------------------------------------------------------------------------------- ```markdown # SlideInAnimation [#slideinanimation] The `SlideInAnimation` component represents an animation that slides in the content from the left. ## Properties ### `animateWhenInView` Indicates whether the animation should start when the component is in view. ### `delay` (default: 0) The delay before the animation starts in milliseconds ### `direction` (default: "left") The direction of the animation. ### `duration` The duration of the animation in milliseconds. ### `loop` (default: false) Indicates whether the animation should loop ### `reverse` (default: false) Indicates whether the animation should run in reverse ## Events ### `started` Event fired when the animation starts ### `stopped` Event fired when the animation stops ## Exposed Methods ### `start` Starts the animation ### `stop` Stops the animation ## Styling This component does not have any styles. ``` -------------------------------------------------------------------------------- /docs/content/extensions/xmlui-animations/SlideInAnimation.md: -------------------------------------------------------------------------------- ```markdown # SlideInAnimation [#slideinanimation] The `SlideInAnimation` component represents an animation that slides in the content from the left. ## Properties ### `animateWhenInView` Indicates whether the animation should start when the component is in view. ### `delay` (default: 0) The delay before the animation starts in milliseconds ### `direction` (default: "left") The direction of the animation. ### `duration` The duration of the animation in milliseconds. ### `loop` (default: false) Indicates whether the animation should loop ### `reverse` (default: false) Indicates whether the animation should run in reverse ## Events ### `started` Event fired when the animation starts ### `stopped` Event fired when the animation stops ## Exposed Methods ### `start` Starts the animation ### `stop` Stops the animation ## Styling This component does not have any styles. ``` -------------------------------------------------------------------------------- /tools/vscode/eslint.config.mjs: -------------------------------------------------------------------------------- ``` /** * ESLint configuration for the project. * * See https://eslint.style and https://typescript-eslint.io for additional linting options. */ // @ts-check import js from '@eslint/js'; import tseslint from 'typescript-eslint'; import stylistic from '@stylistic/eslint-plugin'; export default tseslint.config( { ignores: [ '**/.vscode-test', '**/out', ] }, js.configs.recommended, ...tseslint.configs.recommended, ...tseslint.configs.stylistic, { plugins: { '@stylistic': stylistic }, rules: { 'curly': 'warn', '@stylistic/semi': ['warn', 'always'], '@typescript-eslint/no-empty-function': 'off', '@typescript-eslint/naming-convention': [ 'warn', { 'selector': 'import', 'format': ['camelCase', 'PascalCase'] } ], '@typescript-eslint/no-unused-vars': [ 'error', { 'argsIgnorePattern': '^_' } ] } } ); ``` -------------------------------------------------------------------------------- /xmlui/src/components/EmojiSelector/EmojiSelector.spec.ts: -------------------------------------------------------------------------------- ```typescript import { test, expect } from "../../testing/fixtures"; // ============================================================================= // BASIC FUNCTIONALITY TESTS // ============================================================================= test.describe("Basic Functionality", () => { test("component renders with default properties", async ({ page, initTestBed }) => { await initTestBed(`<EmojiSelector testId="emoji-selector" />`, {}); await expect(page.getByTestId("emoji-selector")).toBeVisible(); }); test("display selected emoji", async ({ page, initTestBed }) => { const EXPECTED_EMOTICON = "😀"; const { testStateDriver } = await initTestBed(` <EmojiSelector onSelect="(emoji) => { testState = emoji }" /> `); await page.getByText(EXPECTED_EMOTICON).click(); await expect.poll(testStateDriver.testState).toBe(EXPECTED_EMOTICON); }); }); ``` -------------------------------------------------------------------------------- /xmlui/src/components/Icon/svg/code-file.svg: -------------------------------------------------------------------------------- ``` <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M8.6665 1.33301H3.99984C3.64622 1.33301 3.30708 1.47348 3.05703 1.72353C2.80698 1.97358 2.6665 2.31272 2.6665 2.66634V13.333C2.6665 13.6866 2.80698 14.0258 3.05703 14.2758C3.30708 14.5259 3.64622 14.6663 3.99984 14.6663H11.9998C12.3535 14.6663 12.6926 14.5259 12.9426 14.2758C13.1927 14.0258 13.3332 13.6866 13.3332 13.333V5.99967L8.6665 1.33301Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> <path d="M8.6665 1.33301V5.99967H13.3332" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> <path d="M9.3335 10.6667L10.6668 9.33333L9.3335 8" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> <path d="M6.6665 8.00033L5.33317 9.33366L6.6665 10.667" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> </svg> ``` -------------------------------------------------------------------------------- /xmlui/src/logging/LoggerContext.tsx: -------------------------------------------------------------------------------- ```typescript import type React from 'react'; import { createContext, useContext, useState, useCallback } from 'react'; type LogEntry = { timestamp: Date; args: any[]; }; type LogContextType = { logs: LogEntry[]; addLog: (args: any[]) => void; }; const LogContext = createContext<LogContextType | undefined>(undefined); export const LoggerProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [logs, setLogs] = useState<LogEntry[]>([]); const addLog = useCallback((args: any[]) => { const newEntry = { timestamp: new Date(), args }; setLogs(prev => [...prev, newEntry]); }, []); return ( <LogContext.Provider value={{ logs, addLog }}> {children} </LogContext.Provider> ); }; export const useLogger = () => { const context = useContext(LogContext); if (!context) throw new Error('useLogger must be used within LoggerProvider'); return context; }; ``` -------------------------------------------------------------------------------- /xmlui/src/components/Select/SelectContext.tsx: -------------------------------------------------------------------------------- ```typescript import { createContext, useContext } from "react"; import type { ReactNode } from "react"; import type { SingleValueType, ValueType } from "./SelectNative"; import type { Option } from "../abstractions"; type SelectContextValue = { multiSelect?: boolean; value: ValueType | null; onChange?: (selectedValue: SingleValueType) => void; setOpen: (open: boolean) => void; setSelectedIndex?: (index: number) => void; options: Set<Option>; optionRenderer?: ( option: Option, selectedValue: SingleValueType, inTrigger: boolean, ) => ReactNode; }; export const SelectContext = createContext<SelectContextValue>({ value: null, onChange: (selectedValue: SingleValueType) => {}, setOpen: (open: boolean) => {}, setSelectedIndex: (index: number) => {}, options: new Set<Option>(), optionRenderer: undefined, }); export function useSelect() { return useContext(SelectContext); } ``` -------------------------------------------------------------------------------- /docs/content/components/xmlui-animations/ScaleAnimation.md: -------------------------------------------------------------------------------- ```markdown # ScaleAnimation [#scaleanimation] The `ScaleAnimation` component represents an animation that scales the content. ## Properties ### `animateWhenInView` Indicates whether the animation should start when the component is in view. ### `delay` (default: 0) The delay before the animation starts in milliseconds ### `duration` The duration of the animation in milliseconds. ### `from` (default: 0) The initial scale of the content. ### `loop` (default: false) Indicates whether the animation should loop ### `reverse` (default: false) Indicates whether the animation should run in reverse ### `to` (default: 1) The final scale of the content. ## Events ### `started` Event fired when the animation starts ### `stopped` Event fired when the animation stops ## Exposed Methods ### `start` Starts the animation ### `stop` Stops the animation ## Styling This component does not have any styles. ``` -------------------------------------------------------------------------------- /docs/content/extensions/xmlui-animations/ScaleAnimation.md: -------------------------------------------------------------------------------- ```markdown # ScaleAnimation [#scaleanimation] The `ScaleAnimation` component represents an animation that scales the content. ## Properties ### `animateWhenInView` Indicates whether the animation should start when the component is in view. ### `delay` (default: 0) The delay before the animation starts in milliseconds ### `duration` The duration of the animation in milliseconds. ### `from` (default: 0) The initial scale of the content. ### `loop` (default: false) Indicates whether the animation should loop ### `reverse` (default: false) Indicates whether the animation should run in reverse ### `to` (default: 1) The final scale of the content. ## Events ### `started` Event fired when the animation starts ### `stopped` Event fired when the animation stops ## Exposed Methods ### `start` Starts the animation ### `stop` Stops the animation ## Styling This component does not have any styles. ``` -------------------------------------------------------------------------------- /xmlui/src/components/PageMetaTitle/PageMetaTitle.tsx: -------------------------------------------------------------------------------- ```typescript import { createComponentRenderer } from "../../components-core/renderers"; import { createMetadata } from "../metadata-helpers"; import { PageMetaTitle, defaultProps } from "./PageMetaTilteNative"; const COMP = "PageMetaTitle"; export const PageMetaTitleMd = createMetadata({ status: "stable", description: "`PageMetaTitle` dynamically sets or updates the browser tab title, enabling " + "pages and components to override the default application name with context-specific titles.", props: { value: { description: `This property sets the page's title to display in the browser tab.`, defaultValue: defaultProps.title, }, }, }); export const pageMetaTitleComponentRenderer = createComponentRenderer( COMP, PageMetaTitleMd, ({ node, extractValue, renderChild }) => { return <PageMetaTitle title={extractValue(node.props.value) || renderChild(node.children)} />; }, ); ``` -------------------------------------------------------------------------------- /docs/public/pages/howto/set-the-initial-value-of-a-select-from-fetched-data.md: -------------------------------------------------------------------------------- ```markdown # Set the initial value of a Select from fetched data ```xmlui-pg noHeader ---app <App> <Test /> </App> ---api { "apiUrl": "/api", "initialize": "$state.users_initial_value = [ { id: 1, username: 'Coder Gal', }, { id: 2, username: 'Tech Ninja', }, { id: 3, username: 'Design Diva', }, ]", "operations": { "get_users_initial_value": { "url": "/users_initial_value", "method": "get", "handler": "$state.users_initial_value" } } } ---comp display <Component name="Test" var.selectedValue=""> <DataSource id="myData" url="/api/users_initial_value" onLoaded="(data) => { selectedValue = data[0].id }" /> <Select initialValue="{selectedValue}"> <Items data="{myData}"> <Option value="{$item.id}" label="{$item.username}" /> </Items> </Select> </Component> ``` ``` -------------------------------------------------------------------------------- /xmlui/src/components/Backdrop/BackdropNative.tsx: -------------------------------------------------------------------------------- ```typescript import { type CSSProperties, type ForwardedRef, forwardRef, type ReactNode } from "react"; import styles from "./Backdrop.module.scss"; import classNames from "classnames"; type Props = { style?: CSSProperties; className?: string; children?: ReactNode; overlayTemplate?: ReactNode; opacity?: string; backgroundColor?: string; }; export const Backdrop = forwardRef(function Backdrop( { style, className, children, overlayTemplate, backgroundColor, opacity, ...rest }: Props, forwardedRef: ForwardedRef<HTMLDivElement>, ) { return ( <div {...rest} className={classNames(styles.backdropContainer, className)} ref={forwardedRef} style={style} > {children} <div className={styles.backdrop} style={{ backgroundColor, opacity }} /> {overlayTemplate && <div className={styles.overlay}>{overlayTemplate}</div>} </div> ); }); ```