This is page 4 of 179. Use http://codebase.md/xmlui-org/xmlui/tools/vscode/resources/xmlui-markup-syntax-highlighting.png?lines=true&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 -------------------------------------------------------------------------------- /xmlui/src/components/Column/doc-resources/list-component-data.js: -------------------------------------------------------------------------------- ```javascript 1 | const data = [ 2 | { 3 | id: 0, 4 | name: "Apples", 5 | quantity: 5, 6 | unit: "pieces", 7 | category: "fruits", 8 | key: 5, 9 | }, 10 | { 11 | id: 1, 12 | name: "Bananas", 13 | quantity: 6, 14 | unit: "pieces", 15 | category: "fruits", 16 | key: 4, 17 | }, 18 | { 19 | id: 2, 20 | name: "Carrots", 21 | quantity: 100, 22 | unit: "grams", 23 | category: "vegetables", 24 | key: 3, 25 | }, 26 | { 27 | id: 3, 28 | name: "Spinach", 29 | quantity: 1, 30 | unit: "bunch", 31 | category: "vegetables", 32 | key: 2, 33 | }, 34 | { 35 | id: 4, 36 | name: "Milk", 37 | quantity: 10, 38 | unit: "liter", 39 | category: "dairy", 40 | key: 1, 41 | }, 42 | { 43 | id: 5, 44 | name: "Cheese", 45 | quantity: 200, 46 | unit: "grams", 47 | category: "dairy", 48 | key: 0, 49 | }, 50 | ]; 51 | 52 | export default data; 53 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/List/doc-resources/list-component-data.js: -------------------------------------------------------------------------------- ```javascript 1 | const data = [ 2 | { 3 | id: 0, 4 | name: "Apples", 5 | quantity: 5, 6 | unit: "pieces", 7 | category: "fruits", 8 | key: 5, 9 | }, 10 | { 11 | id: 1, 12 | name: "Bananas", 13 | quantity: 6, 14 | unit: "pieces", 15 | category: "fruits", 16 | key: 4, 17 | }, 18 | { 19 | id: 2, 20 | name: "Carrots", 21 | quantity: 100, 22 | unit: "grams", 23 | category: "vegetables", 24 | key: 3, 25 | }, 26 | { 27 | id: 3, 28 | name: "Spinach", 29 | quantity: 1, 30 | unit: "bunch", 31 | category: "vegetables", 32 | key: 2, 33 | }, 34 | { 35 | id: 4, 36 | name: "Milk", 37 | quantity: 10, 38 | unit: "liter", 39 | category: "dairy", 40 | key: 1, 41 | }, 42 | { 43 | id: 5, 44 | name: "Cheese", 45 | quantity: 200, 46 | unit: "grams", 47 | category: "dairy", 48 | key: 0, 49 | }, 50 | ]; 51 | 52 | export default data; 53 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Table/doc-resources/list-component-data.js: -------------------------------------------------------------------------------- ```javascript 1 | const data = [ 2 | { 3 | id: 0, 4 | name: "Apples", 5 | quantity: 5, 6 | unit: "pieces", 7 | category: "fruits", 8 | key: 5, 9 | }, 10 | { 11 | id: 1, 12 | name: "Bananas", 13 | quantity: 6, 14 | unit: "pieces", 15 | category: "fruits", 16 | key: 4, 17 | }, 18 | { 19 | id: 2, 20 | name: "Carrots", 21 | quantity: 100, 22 | unit: "grams", 23 | category: "vegetables", 24 | key: 3, 25 | }, 26 | { 27 | id: 3, 28 | name: "Spinach", 29 | quantity: 1, 30 | unit: "bunch", 31 | category: "vegetables", 32 | key: 2, 33 | }, 34 | { 35 | id: 4, 36 | name: "Milk", 37 | quantity: 10, 38 | unit: "liter", 39 | category: "dairy", 40 | key: 1, 41 | }, 42 | { 43 | id: 5, 44 | name: "Cheese", 45 | quantity: 200, 46 | unit: "grams", 47 | category: "dairy", 48 | key: 0, 49 | }, 50 | ]; 51 | 52 | export default data; 53 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Form/Form.module.scss: -------------------------------------------------------------------------------- ```scss 1 | @use "../../components-core/theming/themes" as t; 2 | 3 | $themeVars: (); 4 | @function createThemeVar($componentVariable) { 5 | $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; 6 | @return t.getThemeVar($themeVars, $componentVariable); 7 | } 8 | 9 | @layer components { 10 | .wrapper { 11 | display: flex; 12 | flex-direction: column; 13 | gap: createThemeVar("gap-Form"); 14 | } 15 | 16 | .buttonRow { 17 | display: flex; 18 | flex-direction: row; 19 | align-items: center; 20 | justify-content: flex-end; 21 | gap: createThemeVar("gap-buttonRow-Form"); 22 | margin-top: createThemeVar("marginTop-buttonRow-Form"); 23 | } 24 | } 25 | 26 | // --- We export the theme variables to add them to the component renderer 27 | :export { 28 | themeVars: t.json-stringify($themeVars); 29 | } 30 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/ProgressBar/ProgressBar.md: -------------------------------------------------------------------------------- ```markdown 1 | %-DESC-START 2 | 3 | **Key features:** 4 | - **Percentage visualization**: Displays progress as a filled portion of a horizontal bar 5 | - **Flexible value handling**: Accepts values from 0 to 1, with automatic bounds handling for out-of-range values 6 | - **Extensive theming**: Customizable background color, indicator color, thickness, and border radius 7 | - **Responsive design**: Adapts to container width while maintaining consistent height 8 | 9 | %-DESC-END 10 | 11 | %-PROP-START value 12 | 13 | The following example demonstrates using it: 14 | 15 | ```xmlui-pg copy {2-6} display name="Example: value" height="200px" 16 | <App> 17 | <ProgressBar /> 18 | <ProgressBar value="0.2"/> 19 | <ProgressBar value="0.6"/> 20 | <ProgressBar value="1"/> 21 | <ProgressBar value="1.2"/> 22 | </App> 23 | ``` 24 | 25 | %-PROP-END 26 | ``` -------------------------------------------------------------------------------- /docs/content/components/HStack.md: -------------------------------------------------------------------------------- ```markdown 1 | # HStack [#hstack] 2 | 3 | This component is inherited from [Stack](/components/Stack) 4 | 5 | See also: [CHStack](/components/CHStack), [CVStack](/components/CVStack), [VStack](/components/VStack) 6 | 7 | `HStack` is a specialized, shorthand version for the regular `Stack` component with a horizontal orientation. 8 | 9 | ```xmlui-pg copy display name="Example: HStack" 10 | <App> 11 | <HStack> 12 | <Stack height="32px" width="32px" backgroundColor="red" /> 13 | <Stack height="32px" width="32px" backgroundColor="blue" /> 14 | <Stack height="32px" width="32px" backgroundColor="green" /> 15 | </HStack> 16 | </App> 17 | ``` 18 | 19 | >[!INFO] 20 | > You cannot change the orientation of `HStack` from horizontal to vertical by setting the `orientation` prop, as the engine ignores that setting. 21 | 22 | 23 | ``` -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- ```markdown 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Description:** 11 | [A clear and concise description of what the bug is.] 12 | 13 | **Steps to Reproduce:** 14 | 1. [First Step] 15 | 2. [Second Step] 16 | 3. [and so on...] 17 | 18 | **Expected Behavior:** 19 | [A clear and concise description of what you expected to happen.] 20 | 21 | **Actual Behavior:** 22 | [A clear and concise description of what actually happened.] 23 | 24 | **Screenshots/Additional Information:** 25 | [If applicable, add screenshots or any additional information that may help explain the issue.] 26 | 27 | **Environment:** 28 | - **xmlui Version:** [e.g., 1.0.0] 29 | - **Browser/Environment:** [e.g., Chrome 90.0.4430.212 on macOS 11.3] 30 | - **Operating System:** [e.g., macOS, Windows, Linux] 31 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Image/Image.module.scss: -------------------------------------------------------------------------------- ```scss 1 | @use "../../components-core/theming/themes" as t; 2 | 3 | // --- This code snippet is required to collect the theme variables used in this module 4 | $themeVars: (); 5 | @function createThemeVar($componentVariable) { 6 | $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; 7 | @return t.getThemeVar($themeVars, $componentVariable); 8 | } 9 | 10 | @layer components { 11 | .img { 12 | display: block; 13 | width: 100%; 14 | height: 100%; 15 | object-fit: contain; 16 | border-radius: createThemeVar("borderRadius-Image"); 17 | border-color: createThemeVar("borderColor-Image"); 18 | 19 | &.clickable { 20 | cursor: pointer; 21 | } 22 | } 23 | } 24 | 25 | // --- We export the theme variables to add them to the component renderer 26 | :export{ 27 | themeVars: t.json-stringify($themeVars) 28 | } 29 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/NoResult/NoResult.md: -------------------------------------------------------------------------------- ```markdown 1 | %-PROP-START hideIcon 2 | 3 | ```xmlui-pg copy display name="Example: hideIcon" 4 | <App> 5 | <FlowLayout> 6 | <NoResult hideIcon="true" width="50%" /> 7 | <NoResult hideIcon="false" width="50%" /> 8 | </FlowLayout> 9 | </App> 10 | ``` 11 | 12 | %-PROP-END 13 | 14 | %-PROP-START icon 15 | 16 | This property defines the icon to display with the component. For a list of of available icons consult [`Icon` documentation](/components/Icon). 17 | 18 | ```xmlui-pg copy display name="Example: icon" 19 | <App> 20 | <NoResult icon="error" height="100%" /> 21 | </App> 22 | ``` 23 | 24 | %-PROP-END 25 | 26 | %-PROP-START label 27 | 28 | Customize the displayed text using this property. Leave empty to omit it. 29 | 30 | ```xmlui-pg copy display name="Example: label" 31 | <App> 32 | <NoResult label="Sorry, found nothing!" height="100%" /> 33 | </App> 34 | ``` 35 | 36 | %-PROP-END 37 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/PositionedContainer/PositionedContainer.module.scss: -------------------------------------------------------------------------------- ```scss 1 | @use "../../components-core/theming/themes" as t; 2 | 3 | // --- This code snippet is required to collect the theme variables used in this module 4 | $themeVars: (); 5 | @function createThemeVar($componentVariable) { 6 | $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; 7 | @return t.getThemeVar($themeVars, $componentVariable); 8 | } 9 | 10 | @layer components { 11 | .wrapper { 12 | position: absolute; 13 | 14 | &.visibleOnHover { 15 | transition: opacity 0.1s; 16 | opacity: 0; 17 | } 18 | } 19 | 20 | :has(> .wrapper) { 21 | position: relative; 22 | 23 | &:hover { 24 | .wrapper.visibleOnHover { 25 | opacity: 1; 26 | } 27 | } 28 | } 29 | } 30 | 31 | // --- We export the theme variables to add them to the component renderer 32 | :export { 33 | themeVars: t.json-stringify($themeVars); 34 | } 35 | ``` -------------------------------------------------------------------------------- /docs/content/components/VStack.md: -------------------------------------------------------------------------------- ```markdown 1 | # VStack [#vstack] 2 | 3 | This component is inherited from [Stack](/components/Stack) 4 | 5 | See also: [CHStack](/components/CHStack), [CVStack](/components/CVStack), [HStack](/components/HStack) 6 | 7 | `VStack` is a specialized, shorthand version for the regular [Stack](./Stack) component with a vertical orientation. 8 | 9 | ```xmlui-pg copy display name="Example: VStack" 10 | <App> 11 | <VStack> 12 | <Stack height="32px" width="32px" backgroundColor="red" /> 13 | <Stack height="32px" width="32px" backgroundColor="blue" /> 14 | <Stack height="32px" width="32px" backgroundColor="green" /> 15 | </VStack> 16 | </App> 17 | ``` 18 | 19 | >[!INFO] 20 | > You cannot change the orientation of `VStack` from vertical to horizontal by setting the `orientation` prop, as the engine ignores that setting. 21 | 22 | 23 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/IFrame/IFrame.module.scss: -------------------------------------------------------------------------------- ```scss 1 | @use "../../components-core/theming/themes" as t; 2 | 3 | // --- This code snippet is required to collect the theme variables used in this module 4 | $themeVars: (); 5 | @function createThemeVar($componentVariable) { 6 | $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; 7 | @return t.getThemeVar($themeVars, $componentVariable); 8 | } 9 | 10 | $component: "IFrame"; 11 | $themeVars: t.composeBorderVars($themeVars, $component); 12 | 13 | 14 | @layer components { 15 | .iframe { 16 | @include t.borderVars($themeVars, $component); 17 | 18 | display: block; 19 | width: createThemeVar("width-IFrame"); 20 | height: createThemeVar("height-IFrame"); 21 | } 22 | } 23 | 24 | 25 | // --- We export the theme variables to add them to the component renderer 26 | :export{ 27 | themeVars: t.json-stringify($themeVars) 28 | } 29 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/SpaceFiller/SpaceFiller.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import styles from "./SpaceFiller.module.scss"; 2 | 3 | import { createComponentRenderer } from "../../components-core/renderers"; 4 | import { parseScssVar } from "../../components-core/theming/themeVars"; 5 | import { SpaceFiller } from "./SpaceFillerNative"; 6 | import { createMetadata } from "../metadata-helpers"; 7 | 8 | const COMP = "SpaceFiller"; 9 | 10 | export const SpaceFillerMd = createMetadata({ 11 | status: "stable", 12 | description: 13 | "`SpaceFiller` works well in layout containers to fill remaining (unused) " + 14 | "space. Its behavior depends on the layout container in which it is used.", 15 | themeVars: parseScssVar(styles.themeVars), 16 | }); 17 | 18 | export const spaceFillerComponentRenderer = createComponentRenderer(COMP, SpaceFillerMd, () => ( 19 | <SpaceFiller /> 20 | )); 21 | ``` -------------------------------------------------------------------------------- /xmlui/tests/components-core/scripts-runner/parser-regression.test.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { describe, expect, it } from "vitest"; 2 | import { Parser } from "../../../src/parsers/scripting/Parser"; 3 | import { evalBinding } from "../../../src/components-core/script-runner/eval-tree-sync"; 4 | import { createEvalContext } from "../../../src/components-core/script-runner/BindingTreeEvaluationContext"; 5 | 6 | describe("Parser - regression (exp)", () => { 7 | it("Function call: 'true.toString()'", () => { 8 | // --- Arrange 9 | const wParser = new Parser("true.toString()"); 10 | const expr = wParser.parseExpr(); 11 | expect(expr).not.equal(null); 12 | if (!expr) return; 13 | 14 | // --- Act 15 | const context = createEvalContext({ localContext: {} }); 16 | const value = evalBinding(expr, context); 17 | 18 | // --- Assert 19 | expect(value).equal("true"); 20 | }); 21 | }); 22 | ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/action/NavigateAction.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import type { ActionExecutionContext } from "../../abstractions/ActionDefs"; 2 | import { createUrlWithQueryParams } from "../../components/component-utils"; 3 | import { createAction } from "./actions"; 4 | 5 | function navigate( 6 | { navigate, location }: ActionExecutionContext, 7 | pathname: string | number, 8 | queryParams?: Record<string, any>, 9 | ) { 10 | // https://stackoverflow.com/questions/37385570/how-to-know-if-react-router-can-go-back-to-display-back-button-in-react-app 11 | if (pathname === -1 && location.key === "default") { 12 | navigate("."); 13 | return; 14 | } 15 | const to = queryParams 16 | ? createUrlWithQueryParams({ 17 | pathname, 18 | queryParams, 19 | }) 20 | : pathname; 21 | navigate(to); 22 | } 23 | 24 | export const navigateAction = createAction("navigate", navigate); 25 | ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/appContext/date-functions.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { 2 | formatDate, 3 | formatDateTime, 4 | formatDateWithoutYear, 5 | formatTime, 6 | formatTimeWithoutSeconds, 7 | getDate, 8 | getDateUntilNow, 9 | isDateToday, 10 | isDateTomorrow, 11 | isDateYesterday, 12 | isoDateString, 13 | smartFormatDate, 14 | smartFormatDateTime, 15 | formatHumanElapsedTime 16 | } from "../utils/date-utils"; 17 | import { differenceInMinutes, isSameDay, isThisYear } from "date-fns"; 18 | 19 | export const dateFunctions = { 20 | isoDateString, 21 | formatDate, 22 | formatDateTime, 23 | formatTime, 24 | formatTimeWithoutSeconds, 25 | formatDateWithoutYear, 26 | getDate, 27 | getDateUntilNow, 28 | smartFormatDateTime, 29 | smartFormatDate, 30 | isToday: isDateToday, 31 | isYesterday: isDateYesterday, 32 | isTomorrow: isDateTomorrow, 33 | differenceInMinutes, 34 | isSameDay, 35 | isThisYear, 36 | formatHumanElapsedTime 37 | }; 38 | ``` -------------------------------------------------------------------------------- /docs/public/pages/howto/hide-an-element-until-its-datasource-is-ready.md: -------------------------------------------------------------------------------- ```markdown 1 | # Hide an element until its DataSource is ready 2 | 3 | ```xmlui-pg noHeader 4 | ---app 5 | <App> 6 | <Test /> 7 | </App> 8 | ---api 9 | { 10 | "apiUrl": "/api", 11 | "initialize": "$state.fruits = [ 12 | { id: 1, name: 'Orange' }, 13 | { id: 2, name: 'Apple' }, 14 | { id: 3, name: 'Pear' }, 15 | ]", 16 | "operations": { 17 | "get-fruits": { 18 | "url": "/fruits", 19 | "method": "get", 20 | "handler": "delay(3000); return $state.fruits;" 21 | } 22 | } 23 | } 24 | ---comp display 25 | <Component name="Test" var.nonce="{0}"> 26 | 27 | <DataSource 28 | id="fruits" 29 | url="/api/fruits?{nonce}" 30 | inProgressNotificationMessage="Loading fruits" 31 | when="{nonce > 0}" 32 | /> 33 | 34 | <Button 35 | label="Run" 36 | onClick="{nonce++}" 37 | /> 38 | 39 | <Fragment when="{fruits.loaded}"> 40 | <Text>Fruits: {fruits.value.length} found</Text> 41 | </Fragment> 42 | 43 | </Component> 44 | ``` 45 | ``` -------------------------------------------------------------------------------- /blog/index.html: -------------------------------------------------------------------------------- ```html 1 | <!doctype html> 2 | <html lang="en"> 3 | 4 | <head> 5 | <meta charset="UTF-8" /> 6 | <link rel="icon" type="image/svg+xml" href="/resources/favicon.ico" /> 7 | <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 8 | <link rel="alternate" type="application/rss+xml" title="XMLUI Blog" href="/feed.rss" /> 9 | <script>window.__PUBLIC_PATH = '/'</script> 10 | <base href="/"> 11 | <!-- 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> 12 | </head> 13 | 14 | <body> 15 | <div id="root"></div> 16 | <script type="module" src="/index.ts"></script> 17 | 18 | </body> 19 | 20 | </html> ``` -------------------------------------------------------------------------------- /docs/public/pages/xmlui-pdf/Pdf.md: -------------------------------------------------------------------------------- ```markdown 1 | # Pdf [#pdf] 2 | 3 | >[!WARNING] 4 | > 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. 5 | 6 | ## Properties 7 | 8 | ### `src` 9 | 10 | This property defines the source URL of the pdf document to display. 11 | 12 | ## Events 13 | 14 | This component does not have any events. 15 | 16 | ## Exposed Methods 17 | 18 | This component does not expose any methods. 19 | 20 | ## Styling 21 | 22 | ### Theme Variables 23 | 24 | | Variable | Default Value (Light) | Default Value (Dark) | 25 | | --- | --- | --- | 26 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-page-Pdf | $boxShadow-md | $boxShadow-md | 27 | | [gap](../styles-and-themes/common-units/#size)-pages-Pdf | $space-4 | $space-4 | 28 | ``` -------------------------------------------------------------------------------- /xmlui/scripts/coverage-only.js: -------------------------------------------------------------------------------- ```javascript 1 | #!/usr/bin/env node 2 | 3 | const script = require('./e2e-test-summary.js'); 4 | 5 | // Run without executing tests, just show coverage 6 | console.log('XMLUI E2E Test Coverage Report'); 7 | console.log('===============================\n'); 8 | 9 | console.log('1. Extracting XMLUI components from metadata...'); 10 | const components = script.getXMLUIComponents(); 11 | console.log(` Found ${components.length} XMLUI components`); 12 | 13 | console.log('2. Scanning for e2e test files...'); 14 | const testFiles = script.getE2ETestFiles(); 15 | console.log(` Found ${testFiles.length} e2e test files`); 16 | 17 | console.log('3. Mapping components to test files...'); 18 | const componentTestMap = script.mapComponentsToTestFiles(components, testFiles); 19 | 20 | // Display summary without test results 21 | script.displaySummary(components, componentTestMap, null); 22 | ``` -------------------------------------------------------------------------------- /docs/content/components/CHStack.md: -------------------------------------------------------------------------------- ```markdown 1 | # CHStack [#chstack] 2 | 3 | This component is inherited from [Stack](/components/Stack) 4 | 5 | See also: [CVStack](/components/CVStack), [HStack](/components/HStack), [VStack](/components/VStack) 6 | 7 | `CHStack` is a specialized, shorthand version for the regular `Stack` component that has a horizontal orientation with its contents centered. 8 | 9 | ```xmlui-pg copy display name="Example: CHStack" 10 | <App> 11 | <CHStack backgroundColor="cyan"> 12 | <Stack height="32px" width="32px" backgroundColor="red" /> 13 | <Stack height="32px" width="32px" backgroundColor="blue" /> 14 | <Stack height="32px" width="32px" backgroundColor="green" /> 15 | </CHStack> 16 | </App> 17 | ``` 18 | 19 | >[!INFO] 20 | > You cannot change the orientation of `CHStack` from horizontal to vertical by setting the `orientation` prop, as the engine ignores that setting. 21 | 22 | 23 | ``` -------------------------------------------------------------------------------- /docs/content/components/CVStack.md: -------------------------------------------------------------------------------- ```markdown 1 | # CVStack [#cvstack] 2 | 3 | This component is inherited from [Stack](/components/Stack) 4 | 5 | See also: [CHStack](/components/CHStack), [HStack](/components/HStack), [VStack](/components/VStack) 6 | 7 | `CVStack` is a specialized, shorthand version for the regular `Stack` component with a vertical orientation centered on its contents. 8 | 9 | ```xmlui-pg copy display name="Example: CVStack" 10 | <App> 11 | <CVStack width="33%" backgroundColor="cyan"> 12 | <Stack height="32px" width="32px" backgroundColor="red" /> 13 | <Stack height="32px" width="32px" backgroundColor="blue" /> 14 | <Stack height="32px" width="32px" backgroundColor="green" /> 15 | </CVStack> 16 | </App> 17 | ``` 18 | 19 | >[!INFO] 20 | > You cannot change the orientation of `CVStack` from vertical to horizontal by setting the `orientation` prop, as the engine ignores that setting. 21 | 22 | 23 | ``` -------------------------------------------------------------------------------- /xmlui/bin/preview.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { preview as vitePreview } from "vite"; 2 | import { getViteConfig } from "./viteConfig"; 3 | 4 | export const preview = async ({proxy}) => { 5 | try { 6 | let proxyDef; 7 | if (proxy) { 8 | const splitProxy = proxy.split("->"); 9 | if (splitProxy.length !== 2) { 10 | console.error("Invalid proxy definition. Example: /api->http://localhost:3000"); 11 | } else { 12 | proxyDef = { 13 | [splitProxy[0]]: { 14 | target: splitProxy[1], 15 | changeOrigin: true, 16 | }, 17 | }; 18 | } 19 | } 20 | const server = await vitePreview({ ...getViteConfig(), 21 | server: { 22 | proxy: proxyDef, 23 | }, 24 | }); 25 | 26 | if (!server.httpServer) { 27 | throw new Error("HTTP server not available"); 28 | } 29 | 30 | server.printUrls(); 31 | } catch (e) { 32 | process.exit(1); 33 | } 34 | }; 35 | ``` -------------------------------------------------------------------------------- /docs/content/components/xmlui-animations/FadeInAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # FadeInAnimation [#fadeinanimation] 2 | 3 | The `FadeInAnimation` component represents an animation that fades in the content. 4 | 5 | ## Properties 6 | 7 | ### `animateWhenInView` 8 | 9 | Indicates whether the animation should start when the component is in view 10 | 11 | ### `delay` (default: 0) 12 | 13 | The delay before the animation starts in milliseconds 14 | 15 | ### `duration` 16 | 17 | The duration of the animation in milliseconds 18 | 19 | ### `loop` (default: false) 20 | 21 | Indicates whether the animation should loop 22 | 23 | ### `reverse` (default: false) 24 | 25 | Indicates whether the animation should run in reverse 26 | 27 | ## Events 28 | 29 | ### `started` 30 | 31 | Event fired when the animation starts 32 | 33 | ### `stopped` 34 | 35 | Event fired when the animation stops 36 | 37 | ## Exposed Methods 38 | 39 | ### `start` 40 | 41 | Starts the animation 42 | 43 | ### `stop` 44 | 45 | Stops the animation 46 | 47 | ## Styling 48 | 49 | This component does not have any styles. 50 | ``` -------------------------------------------------------------------------------- /docs/content/extensions/xmlui-animations/FadeInAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # FadeInAnimation [#fadeinanimation] 2 | 3 | The `FadeInAnimation` component represents an animation that fades in the content. 4 | 5 | ## Properties 6 | 7 | ### `animateWhenInView` 8 | 9 | Indicates whether the animation should start when the component is in view 10 | 11 | ### `delay` (default: 0) 12 | 13 | The delay before the animation starts in milliseconds 14 | 15 | ### `duration` 16 | 17 | The duration of the animation in milliseconds 18 | 19 | ### `loop` (default: false) 20 | 21 | Indicates whether the animation should loop 22 | 23 | ### `reverse` (default: false) 24 | 25 | Indicates whether the animation should run in reverse 26 | 27 | ## Events 28 | 29 | ### `started` 30 | 31 | Event fired when the animation starts 32 | 33 | ### `stopped` 34 | 35 | Event fired when the animation stops 36 | 37 | ## Exposed Methods 38 | 39 | ### `start` 40 | 41 | Starts the animation 42 | 43 | ### `stop` 44 | 45 | Stops the animation 46 | 47 | ## Styling 48 | 49 | This component does not have any styles. 50 | ``` -------------------------------------------------------------------------------- /docs/content/components/xmlui-animations/FadeOutAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # FadeOutAnimation [#fadeoutanimation] 2 | 3 | The `FadeOutAnimation` component represents an animation that fades out the content. 4 | 5 | ## Properties 6 | 7 | ### `animateWhenInView` 8 | 9 | Indicates whether the animation should start when the component is in view 10 | 11 | ### `delay` (default: 0) 12 | 13 | The delay before the animation starts in milliseconds 14 | 15 | ### `duration` 16 | 17 | The duration of the animation in milliseconds 18 | 19 | ### `loop` (default: false) 20 | 21 | Indicates whether the animation should loop 22 | 23 | ### `reverse` (default: false) 24 | 25 | Indicates whether the animation should run in reverse 26 | 27 | ## Events 28 | 29 | ### `started` 30 | 31 | Event fired when the animation starts 32 | 33 | ### `stopped` 34 | 35 | Event fired when the animation stops 36 | 37 | ## Exposed Methods 38 | 39 | ### `start` 40 | 41 | Starts the animation 42 | 43 | ### `stop` 44 | 45 | Stops the animation 46 | 47 | ## Styling 48 | 49 | This component does not have any styles. 50 | ``` -------------------------------------------------------------------------------- /docs/content/extensions/xmlui-animations/FadeOutAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # FadeOutAnimation [#fadeoutanimation] 2 | 3 | The `FadeOutAnimation` component represents an animation that fades out the content. 4 | 5 | ## Properties 6 | 7 | ### `animateWhenInView` 8 | 9 | Indicates whether the animation should start when the component is in view 10 | 11 | ### `delay` (default: 0) 12 | 13 | The delay before the animation starts in milliseconds 14 | 15 | ### `duration` 16 | 17 | The duration of the animation in milliseconds 18 | 19 | ### `loop` (default: false) 20 | 21 | Indicates whether the animation should loop 22 | 23 | ### `reverse` (default: false) 24 | 25 | Indicates whether the animation should run in reverse 26 | 27 | ## Events 28 | 29 | ### `started` 30 | 31 | Event fired when the animation starts 32 | 33 | ### `stopped` 34 | 35 | Event fired when the animation stops 36 | 37 | ## Exposed Methods 38 | 39 | ### `start` 40 | 41 | Starts the animation 42 | 43 | ### `stop` 44 | 45 | Stops the animation 46 | 47 | ## Styling 48 | 49 | This component does not have any styles. 50 | ``` -------------------------------------------------------------------------------- /packages/xmlui-os-frames/package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "xmlui-os-frames", 3 | "version": "0.1.0", 4 | "sideEffects": false, 5 | "type": "module", 6 | "private": true, 7 | "scripts": { 8 | "start": "xmlui start", 9 | "preview": "xmlui preview", 10 | "build:extension": "xmlui build-lib", 11 | "build-watch": "xmlui build-lib --watch", 12 | "build:demo": "xmlui build", 13 | "build:meta": "xmlui build-lib --mode=metadata" 14 | }, 15 | "dependencies": {}, 16 | "devDependencies": { 17 | "xmlui": "*" 18 | }, 19 | "main": "./dist/xmlui-os-frames.js", 20 | "module": "./dist/xmlui-os-frames.mjs", 21 | "exports": { 22 | ".": { 23 | "import": "./dist/xmlui-os-frames.mjs", 24 | "require": "./dist/xmlui-os-frames.js" 25 | }, 26 | "./*.css": { 27 | "import": "./dist/*.css", 28 | "require": "./dist/*.css" 29 | } 30 | }, 31 | "files": [ 32 | "dist" 33 | ], 34 | "engines": { 35 | "node": ">=18.0.0" 36 | } 37 | } 38 | ``` -------------------------------------------------------------------------------- /packages/xmlui-pdf/package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "xmlui-pdf", 3 | "version": "0.1.11", 4 | "sideEffects": false, 5 | "type": "module", 6 | "scripts": { 7 | "start": "xmlui start", 8 | "preview": "xmlui preview", 9 | "build:extension": "xmlui build-lib", 10 | "build-watch": "xmlui build-lib --watch", 11 | "build:demo": "xmlui build", 12 | "build:meta": "xmlui build-lib --mode=metadata" 13 | }, 14 | "dependencies": { 15 | "pdfjs-dist": "5.3.93", 16 | "react-pdf": "^10.1.0" 17 | }, 18 | "devDependencies": { 19 | "xmlui": "*" 20 | }, 21 | "main": "./dist/xmlui-pdf.js", 22 | "module": "./dist/xmlui-pdf.mjs", 23 | "exports": { 24 | ".": { 25 | "import": "./dist/xmlui-pdf.mjs", 26 | "require": "./dist/xmlui-pdf.js" 27 | }, 28 | "./*.css": { 29 | "import": "./dist/*.css", 30 | "require": "./dist/*.css" 31 | } 32 | }, 33 | "files": [ 34 | "dist" 35 | ], 36 | "engines": { 37 | "node": ">=18.0.0" 38 | } 39 | } 40 | ``` -------------------------------------------------------------------------------- /docs/public/pages/howto/react-to-button-click-not-keystrokes.md: -------------------------------------------------------------------------------- ```markdown 1 | # React to button click not keystrokes 2 | 3 | ```xmlui-pg noHeader 4 | ---app 5 | <App> 6 | <Test /> 7 | </App> 8 | ---comp display 9 | <!-- Use two different variables --> 10 | <Component name="Test" var.searchText="" var.triggerSearch="{false}"> 11 | <TextBox 12 | id="searchInput" 13 | placeholder="Type something..." 14 | width="300px" 15 | /> 16 | <Button 17 | label="Search" 18 | onClick="searchText = searchInput.value; triggerSearch = true" 19 | /> 20 | <DataSource 21 | id="searchResults" 22 | url="https://httpbin.org/post" 23 | body="{JSON.stringify({query: searchText})}" 24 | method="POST" 25 | when="{triggerSearch}" 26 | onDidLoad="triggerSearch = false" 27 | /> 28 | <Fragment when="{searchResults.loaded}"> 29 | <Text>Search results for: {searchText}</Text> 30 | <Text>Response received: {searchResults.value.json ? 'Yes' : 'No'}</Text> 31 | </Fragment> 32 | </Component> 33 | ``` 34 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/StickyBox/StickyBox.module.scss: -------------------------------------------------------------------------------- ```scss 1 | @use "../../components-core/theming/themes" as t; 2 | 3 | // --- This code snippet is required to collect the theme variables used in this module 4 | $themeVars: (); 5 | @function createThemeVar($componentVariable) { 6 | $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; 7 | @return t.getThemeVar($themeVars, $componentVariable); 8 | } 9 | 10 | @layer components { 11 | .wrapper { 12 | z-index: 1; 13 | } 14 | 15 | .sentinel ~ *:has([data-anchor="true"]) { 16 | [data-anchor="true"] { 17 | //my-scroll-margin-top is set by the heading component, we have to take that into account, too 18 | scroll-margin-top: calc( 19 | var(--my-scroll-margin-top, 0px) + var(--xmlui-scroll-margin-top, 0px) 20 | ); 21 | } 22 | } 23 | } 24 | 25 | // --- We export the theme variables to add them to the component renderer 26 | :export { 27 | themeVars: t.json-stringify($themeVars); 28 | } 29 | ``` -------------------------------------------------------------------------------- /blog/CHANGELOG.md: -------------------------------------------------------------------------------- ```markdown 1 | # xmlui-blog 2 | 3 | ## 0.0.9 4 | 5 | ### Patch Changes 6 | 7 | - eb6454f: refactor: change LineChart/BarChart property names 8 | - Updated dependencies [f12a042] 9 | - Updated dependencies [8731eb8] 10 | - Updated dependencies [eb6454f] 11 | - Updated dependencies [1210852] 12 | - [email protected] 13 | 14 | ## 0.0.8 15 | 16 | ### Patch Changes 17 | 18 | - 819b563: Update fontSize and lineHeight themes and style (may break existing xmlui code) 19 | - Updated dependencies [8c76c8d] 20 | - Updated dependencies [d56c3e5] 21 | - Updated dependencies [e42d367] 22 | - Updated dependencies [f539526] 23 | - Updated dependencies [19ce234] 24 | - Updated dependencies [455b6c0] 25 | - Updated dependencies [e90dc73] 26 | - Updated dependencies [819b563] 27 | - Updated dependencies [b57dfa2] 28 | - Updated dependencies [9dd0f97] 29 | - Updated dependencies [19ce234] 30 | - Updated dependencies [898346d] 31 | - Updated dependencies [705dd04] 32 | - [email protected] 33 | ``` -------------------------------------------------------------------------------- /tools/vscode/.vscode/tasks.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "watch", 6 | "dependsOn": ["npm: watch:tsc", "npm: watch:esbuild"], 7 | "presentation": { 8 | "reveal": "never" 9 | }, 10 | "group": { 11 | "kind": "build", 12 | "isDefault": true 13 | } 14 | }, 15 | { 16 | "type": "npm", 17 | "script": "watch:esbuild", 18 | "group": "build", 19 | "problemMatcher": "$esbuild-watch", 20 | "isBackground": true, 21 | "label": "npm: watch:esbuild", 22 | "presentation": { 23 | "group": "watch", 24 | "reveal": "never" 25 | } 26 | }, 27 | { 28 | "type": "npm", 29 | "script": "watch:tsc", 30 | "group": "build", 31 | "problemMatcher": "$tsc-watch", 32 | "isBackground": true, 33 | "label": "npm: watch:tsc", 34 | "presentation": { 35 | "group": "watch", 36 | "reveal": "never" 37 | } 38 | } 39 | ] 40 | } 41 | ``` -------------------------------------------------------------------------------- /packages/xmlui-animations/package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "xmlui-animations", 3 | "version": "0.1.15", 4 | "sideEffects": false, 5 | "type": "module", 6 | "scripts": { 7 | "start": "xmlui start", 8 | "preview": "xmlui preview", 9 | "build:extension": "xmlui build-lib", 10 | "build-watch": "xmlui build-lib --watch", 11 | "build:demo": "xmlui build", 12 | "build:meta": "xmlui build-lib --mode=metadata" 13 | }, 14 | "dependencies": { 15 | "@react-spring/web": "^9.7.5" 16 | }, 17 | "devDependencies": { 18 | "xmlui": "*" 19 | }, 20 | "main": "./dist/xmlui-animations.js", 21 | "module": "./dist/xmlui-animations.mjs", 22 | "exports": { 23 | ".": { 24 | "import": "./dist/xmlui-animations.mjs", 25 | "require": "./dist/xmlui-animations.js" 26 | }, 27 | "./*.css": { 28 | "import": "./dist/*.css", 29 | "require": "./dist/*.css" 30 | } 31 | }, 32 | "files": [ 33 | "dist" 34 | ], 35 | "engines": { 36 | "node": ">=18.0.0" 37 | } 38 | } 39 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Accordion/Accordion.md: -------------------------------------------------------------------------------- ```markdown 1 | # Accordion 2 | 3 | %-PROP-START positionInGroup 4 | 5 | The possible values are: 6 | 7 | | Value | Description | 8 | | :------- | :----------------------------------------------------------------------- | 9 | | `single` | The accordion stands alone (not in a group) | 10 | | `first` | This accordion is the first in a group | 11 | | `middle` | This accordion is between the first and last items in an accordion group | 12 | | `last` | This accordion is the last in a group | 13 | 14 | By default, this value is `single`. 15 | 16 | %-PROP-END 17 | 18 | %-PROP-START rotateExpanded 19 | 20 | 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. 21 | 22 | %-PROP-END 23 | ``` -------------------------------------------------------------------------------- /xmlui/src/testing/drivers/NumberBoxDriver.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { PART_START_ADORNMENT, PART_END_ADORNMENT, PART_INPUT } from "../../components-core/parts"; 2 | import { InputComponentDriver } from "../ComponentDrivers"; 3 | 4 | const PART_SPINNER_UP = "spinnerUp"; 5 | const PART_SPINNER_DOWN = "spinnerDown"; 6 | 7 | export class NumberBoxDriver extends InputComponentDriver { 8 | get input() { 9 | return this.getByPartName(PART_INPUT); 10 | } 11 | 12 | get startAdornment() { 13 | return this.getByPartName(PART_START_ADORNMENT); 14 | } 15 | 16 | get endAdornment() { 17 | return this.getByPartName(PART_END_ADORNMENT); 18 | } 19 | 20 | get spinnerUp() { 21 | return this.getByPartName(PART_SPINNER_UP); 22 | } 23 | 24 | get spinnerDown() { 25 | return this.getByPartName(PART_SPINNER_DOWN); 26 | } 27 | 28 | async increment() { 29 | await this.spinnerUp.click({ force: true }); 30 | } 31 | 32 | async decrement() { 33 | await this.spinnerDown.click({ force: true }); 34 | } 35 | } 36 | ``` -------------------------------------------------------------------------------- /packages/xmlui-hello-world/package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "xmlui-hello-world", 3 | "version": "0.1.0", 4 | "sideEffects": false, 5 | "type": "module", 6 | "scripts": { 7 | "start": "xmlui start", 8 | "preview": "xmlui preview", 9 | "build:extension": "xmlui build-lib", 10 | "build-watch": "xmlui build-lib --watch", 11 | "build:demo": "xmlui build", 12 | "build:meta": "xmlui build-lib --mode=metadata" 13 | }, 14 | "devDependencies": { 15 | "xmlui": "*" 16 | }, 17 | "main": "./dist/xmlui-hello-world.js", 18 | "module": "./dist/xmlui-hello-world.mjs", 19 | "exports": { 20 | ".": { 21 | "import": "./dist/xmlui-hello-world.mjs", 22 | "require": "./dist/xmlui-hello-world.js" 23 | }, 24 | "./*.css": { 25 | "import": "./dist/*.css", 26 | "require": "./dist/*.css" 27 | } 28 | }, 29 | "files": [ 30 | "dist" 31 | ], 32 | "engines": { 33 | "node": ">=18.0.0" 34 | }, 35 | "author": "", 36 | "license": "ISC", 37 | "description": "" 38 | } 39 | ``` -------------------------------------------------------------------------------- /xmlui/tests-e2e/datasource-onLoaded-regression.spec.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { expect, test } from "../src/testing/fixtures"; 2 | 3 | test("onLoaded has access to the loaded datasource state", async ({ page, initTestBed }) => { 4 | await initTestBed( 5 | ` 6 | <Fragment var.dataFromOnLoaded="{[]}"> 7 | <DataSource url="/data1" id="data" onLoaded="dataFromOnLoaded = data.value;"/> 8 | <List data="{dataFromOnLoaded}" testId="list"> 9 | <property name="emptyListTemplate"> 10 | <Text testId="emptyLabel">Empty</Text> 11 | </property> 12 | </List> 13 | </Fragment> 14 | `, 15 | { 16 | apiInterceptor: { 17 | operations: { 18 | "load-api-data1": { 19 | url: "/data1", 20 | method: "get", 21 | handler: `() => { return ['data1', 'data2']; }`, 22 | }, 23 | }, 24 | }, 25 | }, 26 | ); 27 | await expect(page.getByTestId("list")).toHaveText("data1data2"); 28 | }); 29 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Timer/Timer.md: -------------------------------------------------------------------------------- ```markdown 1 | %-DESC-START 2 | 3 | ## Using Timer 4 | 5 | The following sample demonstrates many aspects of the `Timer` component. Use the switches and the buttons to observe how the component works. 6 | 7 | ```xmlui-pg display copy name="Using Timer" 8 | <App var.count="{0}"> 9 | <Text> 10 | Count: {count} | Timer is {timer.isPaused() ? 'paused' : 'running'} 11 | </Text> 12 | <Timer 13 | id="timer" 14 | initialDelay="2000" 15 | interval="200" 16 | onTick="count++;" 17 | enabled="{enable.value}" 18 | once="{once.value}" /> 19 | <Switch id="enable" label="Enable Timer" initialValue="true" /> 20 | <Switch id="once" label="Run Once" initialValue="{false}" /> 21 | <HStack> 22 | <Button onClick="timer.pause()" enabled="{!timer.isPaused()}"> 23 | Pause 24 | </Button> 25 | <Button onClick="timer.resume()" enabled="{timer.isPaused()}"> 26 | Resume 27 | </Button> 28 | </HStack> 29 | </App> 30 | ``` 31 | 32 | %-DESC-END 33 | 34 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/HoverCard/HoverCard.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { createComponentRenderer } from "../../components-core/renderers"; 2 | import { createMetadata, dComponent } from "../metadata-helpers"; 3 | import { HoverCardComponent } from "./HovercardNative"; 4 | 5 | const COMP = "HoverCard"; 6 | 7 | export const HoverCardMd = createMetadata({ 8 | status: "deprecated", 9 | description: "(**OBSOLETE**) This component displays some content when its parent component is hovered.", 10 | props: { 11 | triggerTemplate: dComponent("The component that opens the hover card when hovered."), 12 | }, 13 | }); 14 | 15 | export const hoverCardComponentRenderer = createComponentRenderer( 16 | COMP, 17 | HoverCardMd, 18 | ({ node, extractValue, renderChild }) => { 19 | return ( 20 | <HoverCardComponent triggerTemplate={renderChild(extractValue(node.props.triggerTemplate))}> 21 | {renderChild(node.children)} 22 | </HoverCardComponent> 23 | ); 24 | }, 25 | ); 26 | ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/theming/themes/base-utils.ts: -------------------------------------------------------------------------------- ```typescript 1 | type PaddingValue = { 2 | left?: string; 3 | right?: string; 4 | top?: string; 5 | bottom?: string; 6 | horizontal?: string; 7 | vertical?: string; 8 | all?: string; 9 | }; 10 | 11 | export function paddingSubject(name: string, valueSpec?: PaddingValue): Record<string, string> { 12 | return { 13 | [`paddingLeft-${name}`]: valueSpec?.left ?? `$paddingHorizontal-${name}`, 14 | [`paddingRight-${name}`]: valueSpec?.right ?? `$paddingHorizontal-${name}`, 15 | [`paddingTop-${name}`]: valueSpec?.top ?? `$paddingVertical-${name}`, 16 | [`paddingBottom-${name}`]: valueSpec?.bottom ?? `$paddingVertical-${name}`, 17 | [`paddingHorizontal-${name}`]: valueSpec?.horizontal ?? "", 18 | [`paddingVertical-${name}`]: valueSpec?.vertical ?? "", 19 | [`padding-${name}`]: 20 | valueSpec?.all ?? `$paddingTop-${name} $paddingRight-${name} $paddingBottom-${name} $paddingLeft-${name}`, 21 | }; 22 | } 23 | ``` -------------------------------------------------------------------------------- /packages/xmlui-website-blocks/package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "xmlui-website-blocks", 3 | "version": "0.1.4", 4 | "sideEffects": false, 5 | "type": "module", 6 | "scripts": { 7 | "start": "xmlui start", 8 | "preview": "xmlui preview", 9 | "build:extension": "xmlui build-lib", 10 | "build-watch": "xmlui build-lib --watch", 11 | "build:demo": "xmlui build", 12 | "build:meta": "xmlui build-lib --mode=metadata" 13 | }, 14 | "dependencies": { 15 | "@react-spring/web": "^9.7.5" 16 | }, 17 | "devDependencies": { 18 | "xmlui": "*" 19 | }, 20 | "main": "./dist/xmlui-website-blocks.js", 21 | "module": "./dist/xmlui-website-blocks.mjs", 22 | "exports": { 23 | ".": { 24 | "import": "./dist/xmlui-website-blocks.mjs", 25 | "require": "./dist/xmlui-website-blocks.js" 26 | }, 27 | "./*.css": { 28 | "import": "./dist/*.css", 29 | "require": "./dist/*.css" 30 | } 31 | }, 32 | "files": [ 33 | "dist" 34 | ], 35 | "engines": { 36 | "node": ">=18.0.0" 37 | } 38 | } 39 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Select/HiddenOption.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import type { Option } from "../abstractions"; 2 | import { useOption } from "./OptionContext"; 3 | import React, { useEffect, useMemo, useState } from "react"; 4 | 5 | export function HiddenOption(option: Option) { 6 | const { label } = option; 7 | const { onOptionRemove, onOptionAdd } = useOption(); 8 | const [node, setNode] = useState(null); 9 | 10 | const opt: Option = useMemo(() => { 11 | return { 12 | ...option, 13 | label: label ?? node?.textContent ?? "", 14 | keywords: option.keywords || [label ?? node?.textContent ?? ""], 15 | // Store the rendered ReactNode for dropdown display 16 | }; 17 | }, [option, node, label]); 18 | 19 | useEffect(() => { 20 | onOptionAdd(opt); 21 | return () => onOptionRemove(opt); 22 | }, [opt, onOptionAdd, onOptionRemove]); 23 | 24 | return ( 25 | <div ref={(el) => setNode(el)} style={{ display: "none" }}> 26 | {option.children} 27 | </div> 28 | ); 29 | } 30 | ``` -------------------------------------------------------------------------------- /docs/content/components/Legend.md: -------------------------------------------------------------------------------- ```markdown 1 | # Legend [#legend] 2 | 3 | `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. 4 | 5 | ## Properties [#properties] 6 | 7 | ### `align` (default: "center") [#align-default-center] 8 | 9 | The alignment of the legend 10 | 11 | Available values: `left`, `right`, `center` **(default)** 12 | 13 | ### `verticalAlign` (default: "bottom") [#verticalalign-default-bottom] 14 | 15 | The vertical alignment of the legend 16 | 17 | Available values: `top`, `bottom` **(default)**, `middle` 18 | 19 | ## Events [#events] 20 | 21 | This component does not have any events. 22 | 23 | ## Exposed Methods [#exposed-methods] 24 | 25 | This component does not expose any methods. 26 | 27 | ## Styling [#styling] 28 | 29 | This component does not have any styles. 30 | ``` -------------------------------------------------------------------------------- /packages/xmlui-search/package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "xmlui-search", 3 | "version": "0.1.4", 4 | "sideEffects": false, 5 | "type": "module", 6 | "scripts": { 7 | "start": "xmlui start", 8 | "preview": "xmlui preview", 9 | "build:extension": "xmlui build-lib", 10 | "build-watch": "xmlui build-lib --watch", 11 | "build:demo": "xmlui build", 12 | "build:meta": "xmlui build-lib --mode=metadata" 13 | }, 14 | "devDependencies": { 15 | "xmlui": "*" 16 | }, 17 | "main": "./dist/xmlui-search.js", 18 | "module": "./dist/xmlui-search.mjs", 19 | "exports": { 20 | ".": { 21 | "import": "./dist/xmlui-search.mjs", 22 | "require": "./dist/xmlui-search.js" 23 | }, 24 | "./*.css": { 25 | "import": "./dist/*.css", 26 | "require": "./dist/*.css" 27 | } 28 | }, 29 | "files": [ 30 | "dist" 31 | ], 32 | "engines": { 33 | "node": ">=18.0.0" 34 | }, 35 | "author": "", 36 | "license": "ISC", 37 | "description": "", 38 | "dependencies": { 39 | "fuse.js": "^7.1.0" 40 | } 41 | } 42 | ``` -------------------------------------------------------------------------------- /xmlui/src/syntax/monaco/xmlui-dark.ts: -------------------------------------------------------------------------------- ```typescript 1 | const darkTheme = { 2 | base: "vs-dark", 3 | inherit: true, 4 | rules: [ 5 | { token: "comment", foreground: "#9296a9" }, 6 | { token: "comment.content", foreground: "#9296a9", fontStyle: "italic" }, 7 | { token: "tag-component", foreground: "#FE6BAD" }, 8 | { token: "tag-event", foreground: "#80A6F8" }, 9 | { token: "tag-helper", foreground: "#80A6F8" }, 10 | { token: "attribute", foreground: "#cbd5e1" }, 11 | { token: "operators", foreground: "#cbd5e1" }, 12 | { token: "delimiter.angle", foreground: "#97A7C5" }, 13 | { token: "delimiter.curly", foreground: "#FFD502" }, 14 | { token: "string", foreground: "#7dd3fc" }, 15 | { token: "tag-cdata", foreground: "#5CC1F9" }, 16 | { token: "tag-script", foreground: "#78DBDB" }, 17 | { token: "string.escape", foreground: "#BAF80A" }, 18 | ], 19 | colors: { 20 | "editor.background": "#17232b", 21 | }, 22 | }; 23 | 24 | export default darkTheme; 25 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/ProgressBar/ProgressBarNative.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import type { CSSProperties, ForwardedRef} from "react"; 2 | import { forwardRef } from "react"; 3 | import classnames from "classnames"; 4 | 5 | import styles from "./ProgressBar.module.scss"; 6 | 7 | interface Props { 8 | value: number; 9 | style?: CSSProperties; 10 | className?: string; 11 | } 12 | 13 | export const defaultProps = { 14 | value: 0, 15 | }; 16 | 17 | export const ProgressBar = forwardRef(function ProgressBar( 18 | { value = defaultProps.value, style, className, ...rest }: Props, 19 | forwardedRef: ForwardedRef<HTMLDivElement>, 20 | ) { 21 | return ( 22 | <div 23 | {...rest} 24 | className={classnames(styles.wrapper, className)} 25 | style={style} 26 | ref={forwardedRef} 27 | > 28 | <div 29 | role="progressbar" 30 | aria-valuenow={value * 100} 31 | aria-valuemin={0} 32 | aria-valuemax={100} 33 | style={{ width: `${value * 100}%` }} 34 | className={styles.bar} 35 | /> 36 | </div> 37 | ); 38 | }); 39 | ``` -------------------------------------------------------------------------------- /packages/xmlui-search/CHANGELOG.md: -------------------------------------------------------------------------------- ```markdown 1 | # xmlui-search 2 | 3 | ## 0.1.4 4 | 5 | ### Patch Changes 6 | 7 | - 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. 8 | - ccb4bf7: Fixed an extra scrollbar appearing when a navigation group is open in the drawer alongside the Search dropdown. 9 | 10 | ## 0.1.3 11 | 12 | ### Patch Changes 13 | 14 | - d349036: Tweaked Search dropdown panel styles. Corrected Link component text and decoration hover and active colors 15 | 16 | ## 0.1.2 17 | 18 | ### Patch Changes 19 | 20 | - 4f1f4b7: Refined search term highlighting to better fit results. 21 | 22 | ## 0.1.1 23 | 24 | ### Patch Changes 25 | 26 | - 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. 27 | - fb6ba38: Fixed inconsistent styling of keyboard item selection and mouse hover. 28 | ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/InspectorButton.module.scss: -------------------------------------------------------------------------------- ```scss 1 | @use "./theming/themes" as themes; 2 | 3 | .wrapper { 4 | position: relative; 5 | opacity: .6; 6 | gap: themes.$space-1; 7 | padding: themes.$space-1_5 !important; 8 | 9 | 10 | &:hover { 11 | opacity: 1; 12 | } 13 | 14 | button[data-popper-reference-hidden='true'] { 15 | opacity: 0; 16 | pointer-events: none; 17 | display: none; 18 | } 19 | } 20 | 21 | .inspectableNode { 22 | outline: 1px solid themes.$outlineColor--focus; 23 | outline-offset: 4px; 24 | position: relative; 25 | } 26 | 27 | .inspectableNode:hover { 28 | outline: 2px solid themes.$color-primary-500; 29 | } 30 | 31 | .inspectOverlay { 32 | cursor: pointer; 33 | position: absolute; 34 | top: 0; 35 | left: 0; 36 | width: 100%; 37 | height: 100%; 38 | background: transparent; 39 | z-index: 1000; 40 | pointer-events: auto; 41 | } 42 | 43 | .inspectOverlay:hover { 44 | background: rgba(32, 107, 196, 0.1); 45 | } 46 | 47 | .inspectedNode { 48 | outline: 2px solid themes.$color-primary-500; 49 | 50 | .inspectOverlay { 51 | background: rgba(32, 107, 196, 0.1); 52 | } 53 | } 54 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/ComponentRegistryContext.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import React, { useContext } from "react"; 2 | 3 | import type { ComponentRendererFn } from "../abstractions/RendererDefs"; 4 | import type { ComponentMetadata } from "../abstractions/ComponentDefs"; 5 | 6 | import type { ComponentRegistry } from "./ComponentProvider"; 7 | 8 | // A single registry entry 9 | export type ComponentRegistryEntry = { 10 | // The function that renders a component definition into a React component 11 | renderer: ComponentRendererFn<any>; 12 | 13 | // Component descriptor (hints and other metadata) 14 | descriptor?: ComponentMetadata; 15 | isCompoundComponent?: boolean; 16 | }; 17 | 18 | // Context object that makes the component registry available 19 | export const ComponentRegistryContext = React.createContext<ComponentRegistry | null>(null); 20 | 21 | // Use this hook within a component to access the component registry 22 | export function useComponentRegistry() { 23 | return useContext(ComponentRegistryContext)!; 24 | } 25 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Icon/svg/unknown-file.svg: -------------------------------------------------------------------------------- ``` 1 | <svg viewBox="0 0 22 28" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <g clip-path="url(#clip0_1811_14989)"> 3 | <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"/> 4 | <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"/> 5 | <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"/> 6 | </g> 7 | <defs> 8 | <clipPath id="clip0_1811_14989"> 9 | <rect width="22" height="28" fill="white"/> 10 | </clipPath> 11 | </defs> 12 | </svg> ``` -------------------------------------------------------------------------------- /xmlui/src/syntax/monaco/xmlui-light.ts: -------------------------------------------------------------------------------- ```typescript 1 | const lightTheme = { 2 | base: "vs", 3 | inherit: true, 4 | rules: [ 5 | { token: "comment", foreground: "#606060" }, 6 | { token: "comment.content", foreground: "#606060", fontStyle: "italic" }, 7 | { token: "tag-component", foreground: "#B33175" }, 8 | { token: "tag-event", foreground: "#005AE1" }, 9 | { token: "tag-helper", foreground: "#005AE1" }, 10 | { token: "attribute", foreground: "#2D2D2D" }, 11 | { token: "operators", foreground: "#2D2D2D" }, 12 | { token: "delimiter.angle", foreground: "#66748E" }, 13 | { token: "delimiter.curly", foreground: "#F07100", fontStyle: "bold" }, 14 | { token: "string", foreground: "#0074a9"}, 15 | { token: "tag-cdata", foreground: "#079CF1" }, 16 | { token: "tag-script", foreground: "#02A1A1" }, 17 | { token: "string.escape", foreground: "#708C00" }, 18 | ], 19 | colors: { 20 | "editor.foreground": "#0D458C", 21 | }, 22 | }; 23 | 24 | export default lightTheme; 25 | ``` -------------------------------------------------------------------------------- /blog/public/resources/pg-popout.svg: -------------------------------------------------------------------------------- ``` 1 | <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> 2 | ``` -------------------------------------------------------------------------------- /docs/public/resources/pg-popout.svg: -------------------------------------------------------------------------------- ``` 1 | <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> 2 | ``` -------------------------------------------------------------------------------- /docs/content/components/xmlui-animations/Animation.md: -------------------------------------------------------------------------------- ```markdown 1 | # Animation [#animation] 2 | 3 | No description provided. 4 | 5 | ## Properties 6 | 7 | ### `animateWhenInView` 8 | 9 | Indicates whether the animation should start when the component is in view 10 | 11 | ### `animation` 12 | 13 | The animation object to be applied to the component 14 | 15 | ### `delay` (default: 0) 16 | 17 | The delay before the animation starts in milliseconds 18 | 19 | ### `duration` 20 | 21 | The duration of the animation in milliseconds 22 | 23 | ### `loop` (default: false) 24 | 25 | Indicates whether the animation should loop 26 | 27 | ### `once` (default: false) 28 | 29 | Indicates whether the animation should only run once 30 | 31 | ### `reverse` (default: false) 32 | 33 | Indicates whether the animation should run in reverse 34 | 35 | ## Events 36 | 37 | ### `started` 38 | 39 | Event fired when the animation starts 40 | 41 | ### `stopped` 42 | 43 | Event fired when the animation stops 44 | 45 | ## Exposed Methods 46 | 47 | ### `start` 48 | 49 | Starts the animation 50 | 51 | ### `stop` 52 | 53 | Stops the animation 54 | 55 | ## Styling 56 | 57 | This component does not have any styles. 58 | ``` -------------------------------------------------------------------------------- /docs/content/extensions/xmlui-animations/Animation.md: -------------------------------------------------------------------------------- ```markdown 1 | # Animation [#animation] 2 | 3 | No description provided. 4 | 5 | ## Properties 6 | 7 | ### `animateWhenInView` 8 | 9 | Indicates whether the animation should start when the component is in view 10 | 11 | ### `animation` 12 | 13 | The animation object to be applied to the component 14 | 15 | ### `delay` (default: 0) 16 | 17 | The delay before the animation starts in milliseconds 18 | 19 | ### `duration` 20 | 21 | The duration of the animation in milliseconds 22 | 23 | ### `loop` (default: false) 24 | 25 | Indicates whether the animation should loop 26 | 27 | ### `once` (default: false) 28 | 29 | Indicates whether the animation should only run once 30 | 31 | ### `reverse` (default: false) 32 | 33 | Indicates whether the animation should run in reverse 34 | 35 | ## Events 36 | 37 | ### `started` 38 | 39 | Event fired when the animation starts 40 | 41 | ### `stopped` 42 | 43 | Event fired when the animation stops 44 | 45 | ## Exposed Methods 46 | 47 | ### `start` 48 | 49 | Starts the animation 50 | 51 | ### `stop` 52 | 53 | Stops the animation 54 | 55 | ## Styling 56 | 57 | This component does not have any styles. 58 | ``` -------------------------------------------------------------------------------- /docs/content/components/xmlui-animations/SlideInAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # SlideInAnimation [#slideinanimation] 2 | 3 | The `SlideInAnimation` component represents an animation that slides in the content from the left. 4 | 5 | ## Properties 6 | 7 | ### `animateWhenInView` 8 | 9 | Indicates whether the animation should start when the component is in view. 10 | 11 | ### `delay` (default: 0) 12 | 13 | The delay before the animation starts in milliseconds 14 | 15 | ### `direction` (default: "left") 16 | 17 | The direction of the animation. 18 | 19 | ### `duration` 20 | 21 | The duration of the animation in milliseconds. 22 | 23 | ### `loop` (default: false) 24 | 25 | Indicates whether the animation should loop 26 | 27 | ### `reverse` (default: false) 28 | 29 | Indicates whether the animation should run in reverse 30 | 31 | ## Events 32 | 33 | ### `started` 34 | 35 | Event fired when the animation starts 36 | 37 | ### `stopped` 38 | 39 | Event fired when the animation stops 40 | 41 | ## Exposed Methods 42 | 43 | ### `start` 44 | 45 | Starts the animation 46 | 47 | ### `stop` 48 | 49 | Stops the animation 50 | 51 | ## Styling 52 | 53 | This component does not have any styles. 54 | ``` -------------------------------------------------------------------------------- /docs/content/extensions/xmlui-animations/SlideInAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # SlideInAnimation [#slideinanimation] 2 | 3 | The `SlideInAnimation` component represents an animation that slides in the content from the left. 4 | 5 | ## Properties 6 | 7 | ### `animateWhenInView` 8 | 9 | Indicates whether the animation should start when the component is in view. 10 | 11 | ### `delay` (default: 0) 12 | 13 | The delay before the animation starts in milliseconds 14 | 15 | ### `direction` (default: "left") 16 | 17 | The direction of the animation. 18 | 19 | ### `duration` 20 | 21 | The duration of the animation in milliseconds. 22 | 23 | ### `loop` (default: false) 24 | 25 | Indicates whether the animation should loop 26 | 27 | ### `reverse` (default: false) 28 | 29 | Indicates whether the animation should run in reverse 30 | 31 | ## Events 32 | 33 | ### `started` 34 | 35 | Event fired when the animation starts 36 | 37 | ### `stopped` 38 | 39 | Event fired when the animation stops 40 | 41 | ## Exposed Methods 42 | 43 | ### `start` 44 | 45 | Starts the animation 46 | 47 | ### `stop` 48 | 49 | Stops the animation 50 | 51 | ## Styling 52 | 53 | This component does not have any styles. 54 | ``` -------------------------------------------------------------------------------- /tools/vscode/eslint.config.mjs: -------------------------------------------------------------------------------- ``` 1 | /** 2 | * ESLint configuration for the project. 3 | * 4 | * See https://eslint.style and https://typescript-eslint.io for additional linting options. 5 | */ 6 | // @ts-check 7 | import js from '@eslint/js'; 8 | import tseslint from 'typescript-eslint'; 9 | import stylistic from '@stylistic/eslint-plugin'; 10 | 11 | export default tseslint.config( 12 | { 13 | ignores: [ 14 | '**/.vscode-test', 15 | '**/out', 16 | ] 17 | }, 18 | js.configs.recommended, 19 | ...tseslint.configs.recommended, 20 | ...tseslint.configs.stylistic, 21 | { 22 | plugins: { 23 | '@stylistic': stylistic 24 | }, 25 | rules: { 26 | 'curly': 'warn', 27 | '@stylistic/semi': ['warn', 'always'], 28 | '@typescript-eslint/no-empty-function': 'off', 29 | '@typescript-eslint/naming-convention': [ 30 | 'warn', 31 | { 32 | 'selector': 'import', 33 | 'format': ['camelCase', 'PascalCase'] 34 | } 35 | ], 36 | '@typescript-eslint/no-unused-vars': [ 37 | 'error', 38 | { 39 | 'argsIgnorePattern': '^_' 40 | } 41 | ] 42 | } 43 | } 44 | ); ``` -------------------------------------------------------------------------------- /xmlui/src/components/EmojiSelector/EmojiSelector.spec.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { test, expect } from "../../testing/fixtures"; 2 | 3 | // ============================================================================= 4 | // BASIC FUNCTIONALITY TESTS 5 | // ============================================================================= 6 | 7 | test.describe("Basic Functionality", () => { 8 | test("component renders with default properties", async ({ page, initTestBed }) => { 9 | await initTestBed(`<EmojiSelector testId="emoji-selector" />`, {}); 10 | 11 | await expect(page.getByTestId("emoji-selector")).toBeVisible(); 12 | }); 13 | 14 | test("display selected emoji", async ({ page, initTestBed }) => { 15 | const EXPECTED_EMOTICON = "😀"; 16 | const { testStateDriver } = await initTestBed(` 17 | <EmojiSelector onSelect="(emoji) => { testState = emoji }" /> 18 | `); 19 | await page.getByText(EXPECTED_EMOTICON).click(); 20 | await expect.poll(testStateDriver.testState).toBe(EXPECTED_EMOTICON); 21 | }); 22 | }); 23 | 24 | 25 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Icon/svg/code-file.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <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"/> 3 | <path d="M8.6665 1.33301V5.99967H13.3332" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> 4 | <path d="M9.3335 10.6667L10.6668 9.33333L9.3335 8" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> 5 | <path d="M6.6665 8.00033L5.33317 9.33366L6.6665 10.667" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> 6 | </svg> 7 | ``` -------------------------------------------------------------------------------- /xmlui/src/logging/LoggerContext.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import type React from 'react'; 2 | import { createContext, useContext, useState, useCallback } from 'react'; 3 | 4 | type LogEntry = { 5 | timestamp: Date; 6 | args: any[]; 7 | }; 8 | 9 | type LogContextType = { 10 | logs: LogEntry[]; 11 | addLog: (args: any[]) => void; 12 | }; 13 | 14 | const LogContext = createContext<LogContextType | undefined>(undefined); 15 | 16 | export const LoggerProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { 17 | const [logs, setLogs] = useState<LogEntry[]>([]); 18 | 19 | const addLog = useCallback((args: any[]) => { 20 | const newEntry = { timestamp: new Date(), args }; 21 | setLogs(prev => [...prev, newEntry]); 22 | }, []); 23 | 24 | return ( 25 | <LogContext.Provider value={{ logs, addLog }}> 26 | {children} 27 | </LogContext.Provider> 28 | ); 29 | }; 30 | 31 | export const useLogger = () => { 32 | const context = useContext(LogContext); 33 | if (!context) throw new Error('useLogger must be used within LoggerProvider'); 34 | return context; 35 | }; 36 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Select/SelectContext.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { createContext, useContext } from "react"; 2 | import type { ReactNode } from "react"; 3 | 4 | import type { SingleValueType, ValueType } from "./SelectNative"; 5 | import type { Option } from "../abstractions"; 6 | 7 | type SelectContextValue = { 8 | multiSelect?: boolean; 9 | value: ValueType | null; 10 | onChange?: (selectedValue: SingleValueType) => void; 11 | setOpen: (open: boolean) => void; 12 | setSelectedIndex?: (index: number) => void; 13 | options: Set<Option>; 14 | optionRenderer?: ( 15 | option: Option, 16 | selectedValue: SingleValueType, 17 | inTrigger: boolean, 18 | ) => ReactNode; 19 | }; 20 | 21 | export const SelectContext = createContext<SelectContextValue>({ 22 | value: null, 23 | onChange: (selectedValue: SingleValueType) => {}, 24 | setOpen: (open: boolean) => {}, 25 | setSelectedIndex: (index: number) => {}, 26 | options: new Set<Option>(), 27 | optionRenderer: undefined, 28 | }); 29 | 30 | export function useSelect() { 31 | return useContext(SelectContext); 32 | } 33 | ``` -------------------------------------------------------------------------------- /docs/content/components/xmlui-animations/ScaleAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # ScaleAnimation [#scaleanimation] 2 | 3 | The `ScaleAnimation` component represents an animation that scales the content. 4 | 5 | ## Properties 6 | 7 | ### `animateWhenInView` 8 | 9 | Indicates whether the animation should start when the component is in view. 10 | 11 | ### `delay` (default: 0) 12 | 13 | The delay before the animation starts in milliseconds 14 | 15 | ### `duration` 16 | 17 | The duration of the animation in milliseconds. 18 | 19 | ### `from` (default: 0) 20 | 21 | The initial scale of the content. 22 | 23 | ### `loop` (default: false) 24 | 25 | Indicates whether the animation should loop 26 | 27 | ### `reverse` (default: false) 28 | 29 | Indicates whether the animation should run in reverse 30 | 31 | ### `to` (default: 1) 32 | 33 | The final scale of the content. 34 | 35 | ## Events 36 | 37 | ### `started` 38 | 39 | Event fired when the animation starts 40 | 41 | ### `stopped` 42 | 43 | Event fired when the animation stops 44 | 45 | ## Exposed Methods 46 | 47 | ### `start` 48 | 49 | Starts the animation 50 | 51 | ### `stop` 52 | 53 | Stops the animation 54 | 55 | ## Styling 56 | 57 | This component does not have any styles. 58 | ``` -------------------------------------------------------------------------------- /docs/content/extensions/xmlui-animations/ScaleAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # ScaleAnimation [#scaleanimation] 2 | 3 | The `ScaleAnimation` component represents an animation that scales the content. 4 | 5 | ## Properties 6 | 7 | ### `animateWhenInView` 8 | 9 | Indicates whether the animation should start when the component is in view. 10 | 11 | ### `delay` (default: 0) 12 | 13 | The delay before the animation starts in milliseconds 14 | 15 | ### `duration` 16 | 17 | The duration of the animation in milliseconds. 18 | 19 | ### `from` (default: 0) 20 | 21 | The initial scale of the content. 22 | 23 | ### `loop` (default: false) 24 | 25 | Indicates whether the animation should loop 26 | 27 | ### `reverse` (default: false) 28 | 29 | Indicates whether the animation should run in reverse 30 | 31 | ### `to` (default: 1) 32 | 33 | The final scale of the content. 34 | 35 | ## Events 36 | 37 | ### `started` 38 | 39 | Event fired when the animation starts 40 | 41 | ### `stopped` 42 | 43 | Event fired when the animation stops 44 | 45 | ## Exposed Methods 46 | 47 | ### `start` 48 | 49 | Starts the animation 50 | 51 | ### `stop` 52 | 53 | Stops the animation 54 | 55 | ## Styling 56 | 57 | This component does not have any styles. 58 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/PageMetaTitle/PageMetaTitle.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { createComponentRenderer } from "../../components-core/renderers"; 2 | import { createMetadata } from "../metadata-helpers"; 3 | import { PageMetaTitle, defaultProps } from "./PageMetaTilteNative"; 4 | 5 | const COMP = "PageMetaTitle"; 6 | 7 | export const PageMetaTitleMd = createMetadata({ 8 | status: "stable", 9 | description: 10 | "`PageMetaTitle` dynamically sets or updates the browser tab title, enabling " + 11 | "pages and components to override the default application name with context-specific titles.", 12 | props: { 13 | value: { 14 | description: `This property sets the page's title to display in the browser tab.`, 15 | defaultValue: defaultProps.title, 16 | }, 17 | }, 18 | }); 19 | 20 | export const pageMetaTitleComponentRenderer = createComponentRenderer( 21 | COMP, 22 | PageMetaTitleMd, 23 | ({ node, extractValue, renderChild }) => { 24 | return <PageMetaTitle title={extractValue(node.props.value) || renderChild(node.children)} />; 25 | }, 26 | ); 27 | ``` -------------------------------------------------------------------------------- /docs/public/pages/howto/set-the-initial-value-of-a-select-from-fetched-data.md: -------------------------------------------------------------------------------- ```markdown 1 | # Set the initial value of a Select from fetched data 2 | 3 | ```xmlui-pg noHeader 4 | ---app 5 | <App> 6 | <Test /> 7 | </App> 8 | ---api 9 | { 10 | "apiUrl": "/api", 11 | "initialize": "$state.users_initial_value = [ 12 | { 13 | id: 1, 14 | username: 'Coder Gal', 15 | }, 16 | { 17 | id: 2, 18 | username: 'Tech Ninja', 19 | }, 20 | { 21 | id: 3, 22 | username: 'Design Diva', 23 | }, 24 | ]", 25 | "operations": { 26 | "get_users_initial_value": { 27 | "url": "/users_initial_value", 28 | "method": "get", 29 | "handler": "$state.users_initial_value" 30 | } 31 | } 32 | } 33 | ---comp display 34 | <Component name="Test" var.selectedValue=""> 35 | 36 | <DataSource 37 | id="myData" 38 | url="/api/users_initial_value" 39 | onLoaded="(data) => { selectedValue = data[0].id }" 40 | /> 41 | 42 | <Select initialValue="{selectedValue}"> 43 | <Items data="{myData}"> 44 | <Option value="{$item.id}" label="{$item.username}" /> 45 | </Items> 46 | </Select> 47 | 48 | </Component> 49 | ``` 50 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Backdrop/BackdropNative.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { type CSSProperties, type ForwardedRef, forwardRef, type ReactNode } from "react"; 2 | 3 | import styles from "./Backdrop.module.scss"; 4 | import classNames from "classnames"; 5 | 6 | type Props = { 7 | style?: CSSProperties; 8 | className?: string; 9 | children?: ReactNode; 10 | overlayTemplate?: ReactNode; 11 | opacity?: string; 12 | backgroundColor?: string; 13 | }; 14 | 15 | export const Backdrop = forwardRef(function Backdrop( 16 | { 17 | style, 18 | className, 19 | children, 20 | overlayTemplate, 21 | backgroundColor, 22 | opacity, 23 | ...rest 24 | }: Props, 25 | forwardedRef: ForwardedRef<HTMLDivElement>, 26 | ) { 27 | return ( 28 | <div 29 | {...rest} 30 | className={classNames(styles.backdropContainer, className)} 31 | ref={forwardedRef} 32 | style={style} 33 | > 34 | {children} 35 | <div className={styles.backdrop} style={{ backgroundColor, opacity }} /> 36 | {overlayTemplate && <div className={styles.overlay}>{overlayTemplate}</div>} 37 | </div> 38 | ); 39 | }); 40 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Logo/LogoNative.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import type { CSSProperties, ForwardedRef} from "react"; 2 | import { forwardRef } from "react"; 3 | 4 | import { Image } from "../Image/ImageNative"; 5 | import { useLogoUrl } from "../AppHeader/AppHeaderNative"; 6 | 7 | // Default props for Logo component 8 | export const defaultProps = { 9 | alt: "Logo", 10 | inline: false, 11 | }; 12 | 13 | type LogoProps = { 14 | alt?: string; 15 | style?: CSSProperties; 16 | className?: string; 17 | inline?: boolean; 18 | }; 19 | 20 | export const Logo = forwardRef(function Logo( 21 | { style, alt = defaultProps.alt, inline = defaultProps.inline, className, ...rest }: LogoProps, 22 | forwardedRef: ForwardedRef<HTMLImageElement>, 23 | ) { 24 | const logoUrl = useLogoUrl(); 25 | if (!logoUrl) { 26 | return null; 27 | } 28 | //width auto for safari 29 | return ( 30 | <Image 31 | {...rest} 32 | ref={forwardedRef} 33 | src={logoUrl} 34 | alt={alt} 35 | inline={inline} 36 | className={className} 37 | style={{ width: "auto", boxShadow: "none", ...style }} 38 | /> 39 | ); 40 | }); 41 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Icon/Icon.module.scss: -------------------------------------------------------------------------------- ```scss 1 | @use "../../components-core/theming/themes" as t; 2 | 3 | $themeVars: (); 4 | @function createThemeVar($componentVariable) { 5 | $themeVars: t.appendThemeVar($themeVars, $componentVariable) !global; 6 | @return t.getThemeVar($themeVars, $componentVariable); 7 | } 8 | 9 | @layer components { 10 | .base { 11 | display: inline-block; 12 | vertical-align: text-bottom; 13 | color: inherit; 14 | width: t.useVar(var(--icon-width), createThemeVar("size-Icon")); 15 | height: t.useVar(var(--icon-height), createThemeVar("size-Icon")); 16 | 17 | // NOTE: browser compat problems with "revert-layer" 18 | // NOTE #2: this solution is necessary because of the default stroke widths applied to our icons coming from react-icons: 19 | // Different icons have different default stroke widths. 20 | stroke-width: revert-layer; 21 | 22 | &.clickable { 23 | cursor: pointer; 24 | } 25 | 26 | * { 27 | color: inherit !important; 28 | } 29 | } 30 | } 31 | 32 | :export { 33 | themeVars: t.json-stringify($themeVars); 34 | } 35 | ```