This is page 5 of 177. Use http://codebase.md/xmlui-org/xmlui?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 │ ├── twenty-jeans-watch.md │ └── warm-spies-melt.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 │ │ │ ├── OptionContext.ts │ │ │ ├── Select.md │ │ │ ├── Select.module.scss │ │ │ ├── Select.spec.ts │ │ │ ├── Select.tsx │ │ │ ├── SelectContext.tsx │ │ │ └── SelectNative.tsx │ │ ├── SelectionStore │ │ │ ├── SelectionStore.md │ │ │ ├── SelectionStore.tsx │ │ │ └── SelectionStoreNative.tsx │ │ ├── Slider │ │ │ ├── Slider.md │ │ │ ├── Slider.module.scss │ │ │ ├── Slider.spec.ts │ │ │ ├── Slider.tsx │ │ │ └── SliderNative.tsx │ │ ├── Slot │ │ │ ├── Slot.md │ │ │ ├── Slot.spec.ts │ │ │ └── Slot.ts │ │ ├── SlotItem.tsx │ │ ├── SpaceFiller │ │ │ ├── SpaceFiller.md │ │ │ ├── SpaceFiller.module.scss │ │ │ ├── SpaceFiller.spec.ts │ │ │ ├── SpaceFiller.tsx │ │ │ └── SpaceFillerNative.tsx │ │ ├── Spinner │ │ │ ├── Spinner.md │ │ │ ├── Spinner.module.scss │ │ │ ├── Spinner.spec.ts │ │ │ ├── Spinner.tsx │ │ │ └── SpinnerNative.tsx │ │ ├── Splitter │ │ │ ├── HSplitter.md │ │ │ ├── HSplitter.spec.ts │ │ │ ├── Splitter.md │ │ │ ├── Splitter.module.scss │ │ │ ├── Splitter.spec.ts │ │ │ ├── Splitter.tsx │ │ │ ├── SplitterNative.tsx │ │ │ ├── utils.ts │ │ │ ├── VSplitter.md │ │ │ └── VSplitter.spec.ts │ │ ├── Stack │ │ │ ├── CHStack.md │ │ │ ├── CHStack.spec.ts │ │ │ ├── CVStack.md │ │ │ ├── CVStack.spec.ts │ │ │ ├── HStack.md │ │ │ ├── HStack.spec.ts │ │ │ ├── Stack.md │ │ │ ├── Stack.module.scss │ │ │ ├── Stack.spec.ts │ │ │ ├── Stack.tsx │ │ │ ├── StackNative.tsx │ │ │ ├── VStack.md │ │ │ └── VStack.spec.ts │ │ ├── StickyBox │ │ │ ├── StickyBox.md │ │ │ ├── StickyBox.module.scss │ │ │ ├── StickyBox.tsx │ │ │ └── StickyBoxNative.tsx │ │ ├── Switch │ │ │ ├── Switch.md │ │ │ ├── Switch.spec.ts │ │ │ └── Switch.tsx │ │ ├── Table │ │ │ ├── doc-resources │ │ │ │ └── list-component-data.js │ │ │ ├── react-table-config.d.ts │ │ │ ├── Table.md │ │ │ ├── Table.module.scss │ │ │ ├── Table.spec.ts │ │ │ ├── Table.tsx │ │ │ ├── TableNative.tsx │ │ │ └── useRowSelection.tsx │ │ ├── TableOfContents │ │ │ ├── TableOfContents.module.scss │ │ │ ├── TableOfContents.spec.ts │ │ │ ├── TableOfContents.tsx │ │ │ └── TableOfContentsNative.tsx │ │ ├── Tabs │ │ │ ├── TabContext.tsx │ │ │ ├── TabItem.md │ │ │ ├── TabItem.tsx │ │ │ ├── TabItemNative.tsx │ │ │ ├── Tabs.md │ │ │ ├── Tabs.module.scss │ │ │ ├── Tabs.spec.ts │ │ │ ├── Tabs.tsx │ │ │ └── TabsNative.tsx │ │ ├── Text │ │ │ ├── Text.md │ │ │ ├── Text.module.scss │ │ │ ├── Text.spec.ts │ │ │ ├── Text.tsx │ │ │ └── TextNative.tsx │ │ ├── TextArea │ │ │ ├── TextArea.md │ │ │ ├── TextArea.module.scss │ │ │ ├── TextArea.spec.ts │ │ │ ├── TextArea.tsx │ │ │ ├── TextAreaNative.tsx │ │ │ ├── TextAreaResizable.tsx │ │ │ └── useComposedRef.ts │ │ ├── TextBox │ │ │ ├── TextBox.md │ │ │ ├── TextBox.module.scss │ │ │ ├── TextBox.spec.ts │ │ │ ├── TextBox.tsx │ │ │ └── TextBoxNative.tsx │ │ ├── Theme │ │ │ ├── NotificationToast.tsx │ │ │ ├── Theme.md │ │ │ ├── Theme.module.scss │ │ │ ├── Theme.spec.ts │ │ │ ├── Theme.tsx │ │ │ └── ThemeNative.tsx │ │ ├── TimeInput │ │ │ ├── TimeInput.md │ │ │ ├── TimeInput.module.scss │ │ │ ├── TimeInput.spec.ts │ │ │ ├── TimeInput.tsx │ │ │ ├── TimeInputNative.tsx │ │ │ └── utils.ts │ │ ├── Timer │ │ │ ├── Timer.md │ │ │ ├── Timer.spec.ts │ │ │ ├── Timer.tsx │ │ │ └── TimerNative.tsx │ │ ├── Toggle │ │ │ ├── Toggle.module.scss │ │ │ └── Toggle.tsx │ │ ├── ToneChangerButton │ │ │ ├── ToneChangerButton.md │ │ │ ├── ToneChangerButton.spec.ts │ │ │ └── ToneChangerButton.tsx │ │ ├── ToneSwitch │ │ │ ├── ToneSwitch.md │ │ │ ├── ToneSwitch.module.scss │ │ │ ├── ToneSwitch.spec.ts │ │ │ ├── ToneSwitch.tsx │ │ │ └── ToneSwitchNative.tsx │ │ ├── Tooltip │ │ │ ├── Tooltip.md │ │ │ ├── Tooltip.module.scss │ │ │ ├── Tooltip.spec.ts │ │ │ ├── Tooltip.tsx │ │ │ └── TooltipNative.tsx │ │ ├── Tree │ │ │ ├── testData.ts │ │ │ ├── Tree-dynamic.spec.ts │ │ │ ├── Tree-icons.spec.ts │ │ │ ├── Tree.md │ │ │ ├── Tree.spec.ts │ │ │ ├── TreeComponent.module.scss │ │ │ ├── TreeComponent.tsx │ │ │ └── TreeNative.tsx │ │ ├── TreeDisplay │ │ │ ├── TreeDisplay.md │ │ │ ├── TreeDisplay.module.scss │ │ │ ├── TreeDisplay.tsx │ │ │ └── TreeDisplayNative.tsx │ │ ├── ValidationSummary │ │ │ ├── ValidationSummary.module.scss │ │ │ └── ValidationSummary.tsx │ │ └── VisuallyHidden.tsx │ ├── components-core │ │ ├── abstractions │ │ │ ├── ComponentRenderer.ts │ │ │ ├── LoaderRenderer.ts │ │ │ ├── standalone.ts │ │ │ └── treeAbstractions.ts │ │ ├── action │ │ │ ├── actions.ts │ │ │ ├── APICall.tsx │ │ │ ├── FileDownloadAction.tsx │ │ │ ├── FileUploadAction.tsx │ │ │ ├── NavigateAction.tsx │ │ │ └── TimedAction.tsx │ │ ├── ApiBoundComponent.tsx │ │ ├── appContext │ │ │ ├── date-functions.ts │ │ │ ├── math-function.ts │ │ │ └── misc-utils.ts │ │ ├── AppContext.tsx │ │ ├── behaviors │ │ │ ├── Behavior.tsx │ │ │ ├── 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/index-standalone.ts: -------------------------------------------------------------------------------- ```typescript 1 | import React from "react"; 2 | import jsxRuntime from "react/jsx-runtime"; 3 | import ReactDOM from "react-dom"; 4 | 5 | import { startApp } from "./components-core/StandaloneApp"; 6 | import StandaloneExtensionManager from "./components-core/StandaloneExtensionManager"; 7 | import * as xmluiExports from "./index"; 8 | 9 | const Xmlui = new StandaloneExtensionManager(); 10 | 11 | document.addEventListener('DOMContentLoaded', function() { 12 | if(!document.getElementById("root")){ 13 | // Your existing code unmodified... 14 | const div = document.createElement('div'); 15 | div.id = 'root'; 16 | document.getElementsByTagName('body')[0].appendChild(div); 17 | } 18 | startApp(undefined, undefined, Xmlui); 19 | }); 20 | 21 | window.React = React; 22 | // @ts-ignore 23 | window.jsxRuntime = jsxRuntime; 24 | window.ReactDOM = ReactDOM; 25 | 26 | // Export everything from index.ts plus the standalone extension manager 27 | const standaloneExports = { ...xmluiExports, standalone: Xmlui }; 28 | export default standaloneExports; ``` -------------------------------------------------------------------------------- /xmlui/src/components/ModalDialog/ModalVisibilityContext.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import React, { useCallback, useContext, useEffect, useId } from "react"; 2 | 3 | interface IModalVisibilityContext { 4 | registerForm: (id: string) => void; 5 | unRegisterForm: (id: string) => void; 6 | amITheSingleForm: (id: string) => boolean; 7 | requestClose: () => Promise<void>; 8 | } 9 | 10 | export const ModalVisibilityContext = React.createContext<IModalVisibilityContext | null>(null); 11 | 12 | export const useModalFormClose = () => { 13 | const id = useId(); 14 | const { registerForm, unRegisterForm, requestClose, amITheSingleForm } = 15 | useContext(ModalVisibilityContext) || {}; 16 | 17 | useEffect(() => { 18 | if (registerForm) { 19 | registerForm(id); 20 | return () => { 21 | unRegisterForm?.(id); 22 | }; 23 | } 24 | }, [id, registerForm, unRegisterForm]); 25 | 26 | return useCallback(() => { 27 | if (!requestClose) { 28 | return; 29 | } 30 | if (!amITheSingleForm(id)) { 31 | return; 32 | } 33 | return requestClose(); 34 | }, [amITheSingleForm, id, requestClose]); 35 | }; 36 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/SpaceFiller/SpaceFiller.md: -------------------------------------------------------------------------------- ```markdown 1 | %-DESC-START 2 | 3 | ## Using `SpaceFiller` 4 | 5 | In a `Stack`, `SpaceFiller` pushes the children following it to the other end of the container: 6 | 7 | ```xmlui-pg copy display {3} name="SpaceFiller in an HStack" 8 | <App> 9 | <HStack> 10 | <Stack width="36px" height="36px" backgroundColor="red" /> 11 | <SpaceFiller /> 12 | <Stack width="36px" height="36px" backgroundColor="blue" /> 13 | </HStack> 14 | </App> 15 | ``` 16 | 17 | In a `FlowLayout`, `SpaceFiller` acts as a line break for a row. The children following the `SpaceFiller` enters a new line. 18 | 19 | ```xmlui-pg copy display {3} name="Example: in a FlowLayout" 20 | <App> 21 | <FlowLayout> 22 | <Stack width="20%" height="36px" backgroundColor="red" /> 23 | <SpaceFiller /> 24 | <Stack width="20%" height="36px" backgroundColor="green" /> 25 | <Stack width="20%" height="36px" backgroundColor="blue" /> 26 | </FlowLayout> 27 | </App> 28 | ``` 29 | 30 | %-DESC-END 31 | 32 | %-STYLE-START 33 | 34 | `SpaceFiller` ignores all layout properties; it cannot be styled. 35 | 36 | %-STYLE-END 37 | ``` -------------------------------------------------------------------------------- /tools/vscode/.vscode/launch.json: -------------------------------------------------------------------------------- ```json 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | { 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "type": "extensionHost", 7 | "request": "launch", 8 | "name": "Launch Client", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}"], 11 | "outFiles": ["${workspaceRoot}/dist/**/*.js"], 12 | "autoAttachChildProcesses": true, 13 | "preLaunchTask": { 14 | "type": "npm", 15 | "script": "watch" 16 | } 17 | }, 18 | { 19 | "name": "Language Server E2E Test", 20 | "type": "extensionHost", 21 | "request": "launch", 22 | "runtimeExecutable": "${execPath}", 23 | "args": [ 24 | "--extensionDevelopmentPath=${workspaceRoot}", 25 | "--extensionTestsPath=${workspaceRoot}/client/out/test/index", 26 | "${workspaceRoot}/client/testFixture" 27 | ], 28 | "outFiles": ["${workspaceRoot}/client/out/test/**/*.js"] 29 | } 30 | ] 31 | } 32 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/NoResult/NoResultNative.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import type { CSSProperties, ForwardedRef} from "react"; 2 | import { forwardRef } from "react"; 3 | import classnames from "classnames"; 4 | 5 | import styles from "./NoResult.module.scss"; 6 | 7 | import { Icon } from "../Icon/IconNative"; 8 | 9 | // Default props for the NoResult component 10 | export const defaultProps = { 11 | hideIcon: false, 12 | icon: "noresult", 13 | }; 14 | 15 | type Props = { 16 | label: string; 17 | icon?: string; 18 | hideIcon?: boolean; 19 | style?: CSSProperties; 20 | className?: string; 21 | }; 22 | 23 | export const NoResult = forwardRef(function NoResult( 24 | { 25 | label, 26 | icon = defaultProps.icon, 27 | hideIcon = defaultProps.hideIcon, 28 | style, 29 | className, 30 | ...rest 31 | }: Props, 32 | forwardedRef: ForwardedRef<HTMLDivElement>, 33 | ) { 34 | return ( 35 | <div 36 | {...rest} 37 | className={classnames(styles.wrapper, className)} 38 | style={style} 39 | ref={forwardedRef} 40 | > 41 | {!hideIcon && <Icon name={icon} className={styles.icon} />} 42 | {label} 43 | </div> 44 | ); 45 | }); 46 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Icon/svg/admonition_tip.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path d="M5.29297 5.15039H30.6719C31.2902 5.15044 31.7575 5.5568 31.8389 6.09961L31.8496 6.20215V24.1748C31.8496 24.7617 31.3364 25.2273 30.707 25.2275H14.5459L14.5068 25.2539L6.49219 30.7158V25.2275H5.29297C4.63423 25.2273 4.15039 24.7343 4.15039 24.1748V6.20215C4.15058 5.61545 4.66376 5.15058 5.29297 5.15039Z" fill="url(#paint0_linear_11266_27250)" stroke="#666666" stroke-width="0.3"/> 3 | <path d="M25.6739 12.3672H11V12.8057H25.6739V12.3672Z" fill="#666666"/> 4 | <path d="M25.6739 14.7344H11V15.1729H25.6739V14.7344Z" fill="#666666"/> 5 | <path d="M25.6739 17.0742H11V17.5127H25.6739V17.0742Z" fill="#666666"/> 6 | <defs> 7 | <linearGradient id="paint0_linear_11266_27250" x1="16.7273" y1="21.25" x2="12.1155" y2="30.9251" gradientUnits="userSpaceOnUse"> 8 | <stop stop-color="#FEFEFE"/> 9 | <stop offset="1" stop-color="#E0E0E0"/> 10 | </linearGradient> 11 | </defs> 12 | </svg> 13 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/TextArea/useComposedRef.ts: -------------------------------------------------------------------------------- ```typescript 1 | import * as React from 'react' 2 | 3 | // basically Exclude<React.ClassAttributes<T>["ref"], string> 4 | type UserRef<T> = 5 | | ((instance: T | null) => void) 6 | | React.RefObject<T> 7 | | null 8 | | undefined 9 | 10 | type Writable<T> = { -readonly [P in keyof T]: T[P] } 11 | 12 | const updateRef = <T>(ref: NonNullable<UserRef<T>>, value: T | null) => { 13 | if (typeof ref === 'function') { 14 | ref(value) 15 | return 16 | } 17 | 18 | ;(ref as Writable<typeof ref>).current = value 19 | } 20 | 21 | export const useComposedRef = <T extends HTMLElement>( 22 | libRef: React.MutableRefObject<T | null>, 23 | userRef: UserRef<T>, 24 | ) => { 25 | const prevUserRef = React.useRef<UserRef<T>>() 26 | 27 | return React.useCallback( 28 | (instance: T | null) => { 29 | libRef.current = instance 30 | 31 | if (prevUserRef.current) { 32 | updateRef(prevUserRef.current, null) 33 | } 34 | 35 | prevUserRef.current = userRef 36 | 37 | if (!userRef) { 38 | return 39 | } 40 | 41 | updateRef(userRef, instance) 42 | }, 43 | [userRef], 44 | ) 45 | } 46 | ``` -------------------------------------------------------------------------------- /xmlui/dev-docs/glossary.md: -------------------------------------------------------------------------------- ```markdown 1 | # Glossary of Terms 2 | 3 | This article contains a glossary of terms used within xmlui. Understanding them can help you grasp the details of the framework's core and contribute to its development. 4 | 5 | ## Action 6 | 7 | An action is a kind of side activity running asynchronously, such as data fetching, in-app navigation, file uploading, etc. After the action starts, it will eventually be complete, but we cannot know in advance when it will be finished. An action can change the state of the container it lives within, which can influence the behavior of the app. 8 | 9 | ## Layout Properties 10 | 11 | Components may declare layout properties, such as `width`, `height`, `color`, and others. These properties directly set the component's corresponding style (if the component supports that particular setting). The rendering engine extracts most of these layout properties into a`React.CSSProperties` object that can be directly used as a React component's `style` property. ``` -------------------------------------------------------------------------------- /tools/create-app/package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "create-xmlui-app", 3 | "version": "0.10.19", 4 | "scripts": { 5 | "dev": "mkdir -p dist && cp -r templates/default dist/ && ncc build ./index.ts -w -o dist/", 6 | "build": "ncc build ./index.ts -o dist/ --minify --no-cache --no-source-map-register && cp -r templates/default dist/", 7 | "prepublishOnly": "npm run build" 8 | }, 9 | "bin": { 10 | "create-xmlui-app": "./dist/index.js" 11 | }, 12 | "files": [ 13 | "dist" 14 | ], 15 | "devDependencies": { 16 | "@types/cross-spawn": "6.0.0", 17 | "@types/node": "^20.2.5", 18 | "@types/prompts": "2.0.1", 19 | "@types/validate-npm-package-name": "3.0.0", 20 | "@vercel/ncc": "0.34.0", 21 | "fast-glob": "3.3.1", 22 | "commander": "2.20.0", 23 | "cross-spawn": "7.0.5", 24 | "picocolors": "1.0.0", 25 | "prompts": "2.1.0", 26 | "update-check": "1.5.4", 27 | "validate-npm-package-name": "3.0.0" 28 | }, 29 | "engines": { 30 | "node": ">=18.12.0" 31 | }, 32 | "repository": { 33 | "url": "https://github.com/xmlui-com/xmlui.git" 34 | } 35 | } 36 | ``` -------------------------------------------------------------------------------- /docs/content/components/EmojiSelector.md: -------------------------------------------------------------------------------- ```markdown 1 | # EmojiSelector [#emojiselector] 2 | 3 | `EmojiSelector` enables users to browse, search and select emojis from their system's native emoji set. 4 | 5 | ## Properties [#properties] 6 | 7 | ### `autoFocus` (default: false) [#autofocus-default-false] 8 | 9 | If this property is set to `true`, the component gets the focus automatically when displayed. 10 | 11 | ```xmlui-pg copy display name="Example: autoFocus" height="420px" 12 | <App> 13 | <EmojiSelector autoFocus="true" /> 14 | </App> 15 | ``` 16 | 17 | ## Events [#events] 18 | 19 | ### `select` [#select] 20 | 21 | This event is fired when the user selects an emoticon from this component. 22 | 23 | ```xmlui-pg copy display name="Example: select" height="420px" 24 | <App> 25 | <HStack var.selected=""> 26 | <EmojiSelector onSelect="(emoji) => { selected = emoji }" /> 27 | <Text value="Selected emoji: {selected}" /> 28 | </HStack> 29 | </App> 30 | ``` 31 | 32 | ## Exposed Methods [#exposed-methods] 33 | 34 | This component does not expose any methods. 35 | 36 | ## Styling [#styling] 37 | 38 | This component does not have any styles. 39 | ``` -------------------------------------------------------------------------------- /docs/public/resources/images/logos/xmlui2.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="64" height="24" viewBox="0 0 64 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path d="M10.82 18.5H9.66L5.64 12.56L1.56 18.5H0.38L5.1 11.72L0.78 5.3H1.98L5.72 10.88L9.52 5.3H10.66L6.26 11.7L10.82 18.5ZM26.6881 5.3V18.5H25.7281V8.66L25.8481 6.26H25.8281L21.0081 18.5H20.0881L15.2681 6.26H15.2481L15.3681 8.66V18.5H14.4081V5.3H15.9081L19.8881 15.3L20.5481 17.32H20.5681L21.2081 15.32L25.1881 5.3H26.6881ZM32.8534 17.58H40.7734V18.5H31.8534V5.3H32.8534V17.58Z" fill="#143566"/> 3 | <path d="M55.2188 5.3V13.12C55.2188 14.9867 54.7188 16.3867 53.7188 17.32C52.7321 18.24 51.2654 18.7 49.3188 18.7C47.3854 18.7 45.9188 18.24 44.9188 17.32C43.9188 16.3867 43.4188 14.9867 43.4188 13.12V5.3H46.8788V13.18C46.8788 14.1267 47.0788 14.8333 47.4788 15.3C47.8921 15.7667 48.5054 16 49.3188 16C50.1454 16 50.7588 15.7667 51.1588 15.3C51.5721 14.8333 51.7788 14.1267 51.7788 13.18V5.3H55.2188ZM62.318 5.3V18.5H58.878V5.3H62.318Z" fill="#DA020F"/> 4 | </svg> 5 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Accordion/AccordionContext.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { createContext, type ReactNode, useContext } from "react"; 2 | 3 | import type { Accordion } from "../../components/abstractions"; 4 | import { noop } from "../../components-core/constants"; 5 | 6 | export type AccordionItem = Accordion & { 7 | id: string; 8 | headerRenderer?: (header: string) => ReactNode; 9 | }; 10 | 11 | type AccordionContextDefinition = { 12 | rotateExpanded: string; 13 | expandItem: (id: string) => void; 14 | register: (id: string) => void; 15 | unRegister: (id: string) => void; 16 | expandedItems: string[]; 17 | hideIcon: boolean; 18 | expandedIcon: string; 19 | collapsedIcon: string; 20 | triggerPosition: "start" | "end"; 21 | }; 22 | 23 | export const AccordionContext = createContext<AccordionContextDefinition>({ 24 | expandedItems: null, 25 | rotateExpanded: null, 26 | expandItem: noop, 27 | register: noop, 28 | unRegister: noop, 29 | hideIcon: null, 30 | expandedIcon: null, 31 | collapsedIcon: null, 32 | triggerPosition: null, 33 | }); 34 | 35 | export function useAccordionContext() { 36 | return useContext(AccordionContext); 37 | } 38 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Fragment/Fragment.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { Fragment } from "react"; 2 | import { createComponentRenderer } from "../../components-core/renderers"; 3 | import { createMetadata } from "../metadata-helpers"; 4 | 5 | const COMP = "Fragment"; 6 | export const FragmentMd = createMetadata({ 7 | status: "stable", 8 | description: 9 | "`Fragment` provides conditional rendering. You can use `when=` on any " + 10 | "component to render it conditionally, use `Fragment` to apply `when` to a group of components.", 11 | opaque: true, 12 | props: { 13 | // Note: 'when' is a universal property defined in ComponentDefCore, no need to redefine it here 14 | }, 15 | }); 16 | 17 | export const fragmentComponentRenderer = createComponentRenderer( 18 | COMP, 19 | FragmentMd, 20 | ({ node, extractValue, renderChild, layoutContext }) => { 21 | let renderedChild = renderChild(node.children, layoutContext); 22 | if(Array.isArray(renderedChild)) { 23 | return <Fragment key={extractValue(node.uid)}>{renderedChild}</Fragment> 24 | } 25 | return renderedChild; 26 | }, 27 | ); 28 | ``` -------------------------------------------------------------------------------- /docs/public/pages/xmlui-animations/FadeInAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # FadeInAnimation [#fadeinanimation] 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 `FadeInAnimation` component represents an animation that fades in the content. 5 | 6 | ## Properties 7 | 8 | ### `animateWhenInView` 9 | 10 | Indicates whether the animation should start when the component is in view 11 | 12 | ### `delay (default: 0)` 13 | 14 | The delay before the animation starts in milliseconds 15 | 16 | ### `duration` 17 | 18 | The duration of the animation in milliseconds 19 | 20 | ### `loop (default: false)` 21 | 22 | Indicates whether the animation should loop 23 | 24 | ### `reverse (default: false)` 25 | 26 | Indicates whether the animation should run in reverse 27 | 28 | ## Events 29 | 30 | ### `started` 31 | 32 | Event fired when the animation starts 33 | 34 | ### `stopped` 35 | 36 | Event fired when the animation stops 37 | 38 | ## Exposed Methods 39 | 40 | ### `start` 41 | 42 | Starts the animation 43 | 44 | ### `stop` 45 | 46 | Stops the animation 47 | 48 | ## Styling 49 | 50 | This component does not have any styles. 51 | ``` -------------------------------------------------------------------------------- /docs/public/pages/xmlui-animations/FadeOutAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # FadeOutAnimation [#fadeoutanimation] 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 `FadeOutAnimation` component represents an animation that fades out the content. 5 | 6 | ## Properties 7 | 8 | ### `animateWhenInView` 9 | 10 | Indicates whether the animation should start when the component is in view 11 | 12 | ### `delay (default: 0)` 13 | 14 | The delay before the animation starts in milliseconds 15 | 16 | ### `duration` 17 | 18 | The duration of the animation in milliseconds 19 | 20 | ### `loop (default: false)` 21 | 22 | Indicates whether the animation should loop 23 | 24 | ### `reverse (default: false)` 25 | 26 | Indicates whether the animation should run in reverse 27 | 28 | ## Events 29 | 30 | ### `started` 31 | 32 | Event fired when the animation starts 33 | 34 | ### `stopped` 35 | 36 | Event fired when the animation stops 37 | 38 | ## Exposed Methods 39 | 40 | ### `start` 41 | 42 | Starts the animation 43 | 44 | ### `stop` 45 | 46 | Stops the animation 47 | 48 | ## Styling 49 | 50 | This component does not have any styles. 51 | ``` -------------------------------------------------------------------------------- /packages/xmlui-hello-world/src/HelloWorld.module.scss: -------------------------------------------------------------------------------- ```scss 1 | @use "xmlui/themes.scss" 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 | $component: "HelloWorld"; 10 | 11 | // Define basic theme variables 12 | $backgroundColor: createThemeVar("backgroundColor-#{$component}"); 13 | $textColor: createThemeVar("textColor-#{$component}"); 14 | 15 | .container { 16 | background-color: $backgroundColor; 17 | color: $textColor; 18 | padding: 1rem; 19 | border-radius: 8px; 20 | text-align: center; 21 | display: inline-block; 22 | min-width: 200px; 23 | } 24 | 25 | .message { 26 | margin: 0 0 1rem 0; 27 | font-size: 1.5rem; 28 | } 29 | 30 | .button { 31 | background-color: #4a90e2; 32 | color: white; 33 | border: none; 34 | padding: 0.75rem 1.5rem; 35 | border-radius: 4px; 36 | cursor: pointer; 37 | font-size: 1rem; 38 | margin-bottom: 1rem; 39 | 40 | &:hover { 41 | opacity: 0.9; 42 | } 43 | } 44 | 45 | .counter { 46 | font-size: 1.2rem; 47 | font-weight: bold; 48 | } 49 | 50 | :export { 51 | themeVars: t.json-stringify($themeVars); 52 | } ``` -------------------------------------------------------------------------------- /packages/xmlui-spreadsheet/package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "xmlui-spreadsheet", 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 | "jspdf": "^3.0.2", 17 | "jspreadsheet-ce": "^5.0.1", 18 | "jszip": "^3.10.1" 19 | }, 20 | "devDependencies": { 21 | "@jspreadsheet/formula": "^2.0.2", 22 | "@types/jspreadsheet-ce": "^4.7.9", 23 | "xmlui": "*" 24 | }, 25 | "main": "./dist/xmlui-spreadsheet.js", 26 | "module": "./dist/xmlui-spreadsheet.mjs", 27 | "exports": { 28 | ".": { 29 | "import": "./dist/xmlui-spreadsheet.mjs", 30 | "require": "./dist/xmlui-spreadsheet.js" 31 | }, 32 | "./*.css": { 33 | "import": "./dist/*.css", 34 | "require": "./dist/*.css" 35 | } 36 | }, 37 | "files": [ 38 | "dist" 39 | ], 40 | "engines": { 41 | "node": ">=18.0.0" 42 | } 43 | } 44 | ``` -------------------------------------------------------------------------------- /xmlui/tests/parsers/scripting/parser-assignments.test.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { describe, expect, it } from "vitest"; 2 | 3 | import { Parser } from "../../../src/parsers/scripting/Parser"; 4 | import { 5 | BinaryExpression, 6 | AssignmentExpression, 7 | T_ASSIGNMENT_EXPRESSION, 8 | T_IDENTIFIER, 9 | T_BINARY_EXPRESSION, 10 | T_LITERAL, 11 | } from "../../../src/components-core/script-runner/ScriptingSourceTree"; 12 | 13 | describe("Parser - assignment expressions", () => { 14 | it("Assignment with binary expression", () => { 15 | // --- Arrange 16 | const wParser = new Parser("a = 2 + c"); 17 | 18 | // --- Act 19 | const expr = wParser.parseExpr(); 20 | 21 | // --- Assert 22 | expect(expr).not.equal(null); 23 | if (!expr) return; 24 | expect(expr.type).equal(T_ASSIGNMENT_EXPRESSION); 25 | const asgn = expr as AssignmentExpression; 26 | expect(asgn.leftValue.type).equal(T_IDENTIFIER); 27 | expect(asgn.expr.type).equal(T_BINARY_EXPRESSION); 28 | const bExpr = asgn.expr as BinaryExpression; 29 | expect(bExpr.left.type).equal(T_LITERAL); 30 | expect(bExpr.right.type).equal(T_IDENTIFIER); 31 | }); 32 | }); 33 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Icon/svg/file-text.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path d="M9.33317 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.33301L9.33317 1.33301Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> 3 | <path d="M9.3335 1.33301V5.33301H13.3335" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> 4 | <path d="M10.6668 8.66699H5.3335" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> 5 | <path d="M10.6668 11.333H5.3335" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> 6 | <path d="M6.66683 6H6.00016H5.3335" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> 7 | </svg> 8 | ``` -------------------------------------------------------------------------------- /docs/public/resources/images/logos/xmlui3.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="64" height="15" viewBox="0 0 64 15" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path d="M10.82 14H9.66L5.64 8.06L1.56 14H0.38L5.1 7.22L0.78 0.799999H1.98L5.72 6.38L9.52 0.799999H10.66L6.26 7.2L10.82 14ZM27.6881 0.799999V14H26.7281V4.16L26.8481 1.76H26.8281L22.0081 14H21.0881L16.2681 1.76H16.2481L16.3681 4.16V14H15.4081V0.799999H16.9081L20.8881 10.8L21.5481 12.82H21.5681L22.2081 10.82L26.1881 0.799999H27.6881ZM34.8534 13.08H42.7734V14H33.8534V0.799999H34.8534V13.08Z" fill="black"/> 3 | <path d="M56.6123 0.799999V9.18C56.6123 10.82 56.1657 12.0667 55.2723 12.92C54.3923 13.7733 53.1457 14.2 51.5323 14.2C49.919 14.2 48.6657 13.7733 47.7723 12.92C46.879 12.0667 46.4323 10.82 46.4323 9.18V0.799999H47.4323V8.98C47.4323 10.3933 47.779 11.4667 48.4723 12.2C49.179 12.92 50.199 13.28 51.5323 13.28C52.8657 13.28 53.879 12.92 54.5723 12.2C55.2657 11.4667 55.6123 10.3933 55.6123 8.98V0.799999H56.6123ZM63.4628 0.799999V14H62.4628V0.799999H63.4628Z" fill="#DA020F"/> 4 | </svg> 5 | ``` -------------------------------------------------------------------------------- /docs/public/resources/images/logos/xmlui6.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="60" height="15" viewBox="0 0 60 15" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path d="M13.72 14H8.8L6.72 10.2L4.76 14H0.12L4.56 7.4L0.34 0.799999H5.16L7.04 4.44L8.94 0.799999H13.38L9.18 7.28L13.72 14ZM32.0914 0.799999V14H28.4914V8.72L28.5714 4.46H28.5314L25.6314 14H22.3514L19.4914 4.46H19.4314L19.5114 8.72V14H15.9114V0.799999H21.6714L23.4514 7.06L24.1114 9.68H24.1514L24.8114 7.06L26.5914 0.799999H32.0914ZM39.5852 10.94H45.8652V14H35.5052V0.799999H39.5852V10.94Z" fill="black"/> 3 | <path d="M55.3115 6.08V10.676C55.3115 11.828 55.0035 12.692 54.3875 13.268C53.7715 13.836 52.8515 14.12 51.6275 14.12C50.3955 14.12 49.4715 13.836 48.8555 13.268C48.2395 12.692 47.9315 11.828 47.9315 10.676V6.08H50.3915V10.808C50.3915 11.288 50.4955 11.648 50.7035 11.888C50.9115 12.128 51.2195 12.248 51.6275 12.248C52.0355 12.248 52.3435 12.128 52.5515 11.888C52.7595 11.648 52.8635 11.288 52.8635 10.808V6.08H55.3115ZM59.6667 6.08V14H57.2187V6.08H59.6667Z" fill="#DA020F"/> 4 | </svg> 5 | ``` -------------------------------------------------------------------------------- /docs/public/pages/howto/assign-a-complex-json-literal-to-a-component-variable.md: -------------------------------------------------------------------------------- ```markdown 1 | # Assign a complex JSON literal to a component variable 2 | 3 | ```xmlui-pg noHeader 4 | ---app 5 | <App> 6 | <Test /> 7 | </App> 8 | ---api 9 | {} 10 | ---comp display 11 | <Component name="Test" 12 | <!-- double curly braces inside double quote --> 13 | var.appConfig="{{ 14 | name: 'Photo Gallery', 15 | version: '1.2.0', 16 | isPublic: true, 17 | photos: [ 18 | { id: 1, title: 'Sunset Beach', likes: 42 }, 19 | { id: 2, title: 'Mountain View', likes: 38 }, 20 | { id: 3, title: 'City Lights', likes: 55 } 21 | ], 22 | authors: [ 23 | { name: 'Alice Johnson', role: 'Photographer' }, 24 | { name: 'Bob Smith', role: 'Editor' } 25 | ] 26 | }}"> 27 | <!-- double curly braces inside double quote --> 28 | 29 | <Text>{appConfig.name} v{appConfig.version}</Text> 30 | 31 | <Text>Photos ({appConfig.photos.length})</Text> 32 | <Items data="{appConfig.photos}"> 33 | <Text>{$item.title} - {$item.likes} likes</Text> 34 | </Items> 35 | 36 | <Text>Team</Text> 37 | <Items data="{appConfig.authors}"> 38 | <Text>{$item.name} ({$item.role})</Text> 39 | </Items> 40 | 41 | </Component> 42 | ``` 43 | ``` -------------------------------------------------------------------------------- /blog/public/resources/github.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="98" height="96" viewBox="0 0 98 96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="currentColor"/></svg> 2 | ``` -------------------------------------------------------------------------------- /docs/public/resources/github.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="98" height="96" viewBox="0 0 98 96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="currentColor"/></svg> 2 | ``` -------------------------------------------------------------------------------- /docs/public/resources/images/logos/xmlui4.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="66" height="15" viewBox="0 0 66 15" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <path d="M13.72 14H8.8L6.72 10.2L4.76 14H0.12L4.56 7.4L0.34 0.799999H5.16L7.04 4.44L8.94 0.799999H13.38L9.18 7.28L13.72 14ZM32.0914 0.799999V14H28.4914V8.72L28.5714 4.46H28.5314L25.6314 14H22.3514L19.4914 4.46H19.4314L19.5114 8.72V14H15.9114V0.799999H21.6714L23.4514 7.06L24.1114 9.68H24.1514L24.8114 7.06L26.5914 0.799999H32.0914ZM39.5852 10.94H45.8652V14H35.5052V0.799999H39.5852V10.94Z" fill="#091D3D"/> 3 | <path d="M59.3155 0.799999V9.18C59.3155 10.82 58.8688 12.0667 57.9755 12.92C57.0955 13.7733 55.8488 14.2 54.2355 14.2C52.6221 14.2 51.3688 13.7733 50.4755 12.92C49.5821 12.0667 49.1355 10.82 49.1355 9.18V0.799999H50.1355V8.98C50.1355 10.3933 50.4821 11.4667 51.1755 12.2C51.8821 12.92 52.9021 13.28 54.2355 13.28C55.5688 13.28 56.5821 12.92 57.2755 12.2C57.9688 11.4667 58.3155 10.3933 58.3155 8.98V0.799999H59.3155ZM65.1659 0.799999V14H64.1659V0.799999H65.1659Z" fill="#DA020F"/> 4 | </svg> 5 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/component-utils.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { omitBy, isUndefined } from "lodash-es"; 2 | import { composeRefs } from "@radix-ui/react-compose-refs"; 3 | 4 | /** 5 | * Maps a record of query params to a usable local URL path with the params appended at the end 6 | * @param to Either a simple URL endpoint or a URL path with query params (corresponds to a href) 7 | */ 8 | export function createUrlWithQueryParams( 9 | to: string | number | { pathname: string | number; queryParams?: Record<string, any> } 10 | ) { 11 | if (!to || typeof to === "string" || typeof to === "number") { 12 | return to; 13 | } 14 | if (to.queryParams !== undefined) { 15 | return { 16 | ...to, 17 | search: new URLSearchParams(omitBy(to.queryParams, isUndefined)).toString(), 18 | }; 19 | } 20 | return to; 21 | } 22 | 23 | export function getComposedRef(...refs){ 24 | const nonUndefinedRefs = refs.filter(ref => ref !== undefined); 25 | if(nonUndefinedRefs.length === 0){ 26 | return undefined; 27 | } 28 | if(nonUndefinedRefs.length === 1){ 29 | return nonUndefinedRefs[0]; 30 | } 31 | return composeRefs(...nonUndefinedRefs); 32 | } ``` -------------------------------------------------------------------------------- /xmlui/src/components/RealTimeAdapter/RealTimeAdapter.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { createComponentRenderer } from "../../components-core/renderers"; 2 | import { createMetadata, d } from "../metadata-helpers"; 3 | import { RealTimeAdapter, defaultProps } from "./RealTimeAdapterNative"; 4 | 5 | const COMP = "RealTimeAdapter"; 6 | 7 | export const RealTimeAdapterMd = createMetadata({ 8 | status: "experimental", 9 | description: "`RealTimeAdapter` is a non-visual component that listens to real-time events.", 10 | props: { 11 | url: { 12 | description: `This property specifies the URL to use for long-polling.`, 13 | defaultValue: defaultProps.url, 14 | }, 15 | }, 16 | events: { 17 | eventArrived: d(`This event is raised when data arrives from the backend using long-polling.`), 18 | }, 19 | }); 20 | 21 | export const realTimeAdapterComponentRenderer = createComponentRenderer( 22 | COMP, 23 | RealTimeAdapterMd, 24 | ({ node, lookupEventHandler, extractValue }) => { 25 | return ( 26 | <RealTimeAdapter 27 | url={extractValue(node.props.url)} 28 | onEvent={lookupEventHandler("eventArrived")} 29 | /> 30 | ); 31 | }, 32 | ); 33 | ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/utils/actionUtils.ts: -------------------------------------------------------------------------------- ```typescript 1 | import type { ContainerState } from "../rendering/ContainerWrapper"; 2 | import type { AppContextObject } from "../../abstractions/AppContextDefs"; 3 | 4 | import { DataLoaderQueryKeyGenerator } from "../utils/DataLoaderQueryKeyGenerator"; 5 | import { extractParam } from "../utils/extractParam"; 6 | 7 | export async function invalidateQueries( 8 | invalidates: undefined | string | string[], 9 | appContext: AppContextObject, 10 | state: ContainerState, 11 | ) { 12 | if (invalidates) { 13 | let arrayToInvalidate = [invalidates]; 14 | if (Array.isArray(invalidates)) { 15 | arrayToInvalidate = invalidates; 16 | } 17 | arrayToInvalidate.forEach((invalidate) => { 18 | void appContext.queryClient?.invalidateQueries( 19 | new DataLoaderQueryKeyGenerator( 20 | extractParam(state, invalidate, appContext), 21 | undefined, 22 | appContext?.appGlobals.apiUrl, 23 | undefined, 24 | undefined, 25 | ).asPredicate(), 26 | ); 27 | }); 28 | } else { 29 | await appContext.queryClient?.invalidateQueries(); 30 | } 31 | } 32 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Backdrop/Backdrop.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 | $backgroundColor-Backdrop: createThemeVar("backgroundColor-Backdrop"); 11 | $opacity-Backdrop: createThemeVar("opacity-Backdrop"); 12 | 13 | @layer components { 14 | .backdropContainer { 15 | position: relative; 16 | display: inline-block; 17 | width: fit-content; 18 | } 19 | 20 | .backdrop { 21 | position: absolute; 22 | top: 0; 23 | left: 0; 24 | width: 100%; 25 | height: 100%; 26 | background-color: $backgroundColor-Backdrop; 27 | opacity: $opacity-Backdrop; 28 | } 29 | 30 | .overlay { 31 | position: absolute; 32 | top: 0; 33 | left: 0; 34 | width: 100%; 35 | height: 100%; 36 | } 37 | } 38 | 39 | // --- We export the theme variables to add them to the component renderer 40 | :export { 41 | themeVars: t.json-stringify($themeVars); 42 | } 43 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Input/InputAdornment.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import classnames from "classnames"; 2 | 3 | import styles from "./InputAdornment.module.scss"; 4 | 5 | import { Icon } from "../Icon/IconNative"; 6 | import { Text } from "../Text/TextNative"; 7 | 8 | interface AdornmentProps { 9 | iconName?: string; 10 | text?: string; 11 | className?: string; 12 | onClick?: () => void; 13 | } 14 | 15 | export function Adornment({ iconName, text, className, onClick, ...rest }: AdornmentProps) { 16 | return ( 17 | <> 18 | {iconName || text ? ( 19 | <div 20 | {...rest} 21 | className={classnames(styles.wrapper, className, { 22 | [styles.clickable]: !!onClick, 23 | })} 24 | role={onClick ? "button" : "presentation"} 25 | onClick={onClick} 26 | tabIndex={onClick ? 0 : undefined} 27 | > 28 | <Icon name={iconName} style={{ color: "inherit" }} /> 29 | {text && ( 30 | <div style={{ display: "flex", userSelect: "none" }}> 31 | <Text style={{ fontSize: "inherit" }}>{text}</Text> 32 | </div> 33 | )} 34 | </div> 35 | ) : null} 36 | </> 37 | ); 38 | } 39 | ``` -------------------------------------------------------------------------------- /xmlui/src/components-core/component-hooks.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { useMemo } from "react"; 2 | 3 | import styles from "../components/Stack/Stack.module.scss"; 4 | import { capitalizeFirstLetter } from "./utils/misc"; 5 | 6 | // This react hooks prepares CSS style values according to the CSS flex semantics to combine orientation, 7 | // horizontal, and vertical alignments. 8 | export function useContentAlignment(orientation: string, horizontal?: string, vertical?: string) { 9 | return useMemo(() => { 10 | // --- Use CSS flex semantics to combine the orientation with alignment to prepare the CSS properties 11 | return orientation === "horizontal" 12 | ? { 13 | horizontal: horizontal && styles[`justifyItems${capitalizeFirstLetter(horizontal)}`], 14 | vertical: vertical && styles[`alignItems${capitalizeFirstLetter(vertical)}`], 15 | } 16 | : { 17 | horizontal: horizontal && styles[`alignItems${capitalizeFirstLetter(horizontal)}`], 18 | vertical: vertical && styles[`justifyItems${capitalizeFirstLetter(vertical)}`], 19 | }; 20 | }, [orientation, horizontal, vertical]); 21 | } 22 | ``` -------------------------------------------------------------------------------- /docs/content/components/PageMetaTitle.md: -------------------------------------------------------------------------------- ```markdown 1 | # PageMetaTitle [#pagemetatitle] 2 | 3 | `PageMetaTitle` dynamically sets or updates the browser tab title, enabling pages and components to override the default application name with context-specific titles. 4 | 5 | **Key features:** 6 | - **Dynamic title updates**: Change browser tab title based on current page or content 7 | - **App name override**: Supersedes the `App`s name property when present 8 | - **Flexible placement**: Can be positioned anywhere in the component tree 9 | - **Binding support**: Accepts dynamic values and expressions for context-aware titles 10 | - **SEO enhancement**: Improves search engine optimization with descriptive page titles 11 | 12 | ## Properties [#properties] 13 | 14 | ### `value` (default: "XMLUI Application") [#value-default-xmlui-application] 15 | 16 | This property sets the page's title to display in the browser tab. 17 | 18 | ## Events [#events] 19 | 20 | This component does not have any events. 21 | 22 | ## Exposed Methods [#exposed-methods] 23 | 24 | This component does not expose any methods. 25 | 26 | ## Styling [#styling] 27 | 28 | This component does not have any styles. 29 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Carousel/CarouselItemNative.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import type { ForwardedRef, ReactNode } from "react"; 2 | import { forwardRef, useEffect, useId } from "react"; 3 | import classnames from "classnames"; 4 | 5 | import styles from "./Carousel.module.scss"; 6 | 7 | import { useCarousel } from "./CarouselContext"; 8 | 9 | type Props = { 10 | children: ReactNode; 11 | style?: React.CSSProperties; 12 | }; 13 | 14 | export const CarouselItemComponent = forwardRef(function CarouselItemComponent( 15 | { children, style, ...rest }: Props, 16 | forwardedRef: ForwardedRef<HTMLDivElement>, 17 | ) { 18 | const id = useId(); 19 | const { register, unRegister, itemProps } = useCarousel(); 20 | 21 | useEffect(() => { 22 | register({ 23 | id, 24 | }); 25 | }, [id, children, style, register, forwardedRef]); 26 | 27 | useEffect(() => { 28 | return () => { 29 | unRegister(id); 30 | }; 31 | }, [id, unRegister]); 32 | 33 | return ( 34 | <div 35 | {...rest} 36 | key={id} 37 | {...itemProps} 38 | className={classnames(styles.carouselItem)} 39 | > 40 | <div className={styles.innerWrapper} ref={forwardedRef} style={style}> 41 | {children} 42 | </div> 43 | </div> 44 | ); 45 | }); 46 | ``` -------------------------------------------------------------------------------- /docs/public/pages/xmlui-animations/Animation.md: -------------------------------------------------------------------------------- ```markdown 1 | # Animation [#animation] 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. 5 | 6 | ## Properties 7 | 8 | ### `animateWhenInView` 9 | 10 | Indicates whether the animation should start when the component is in view 11 | 12 | ### `animation` 13 | 14 | The animation object to be applied to the component 15 | 16 | ### `delay (default: 0)` 17 | 18 | The delay before the animation starts in milliseconds 19 | 20 | ### `duration` 21 | 22 | The duration of the animation in milliseconds 23 | 24 | ### `loop (default: false)` 25 | 26 | Indicates whether the animation should loop 27 | 28 | ### `once (default: false)` 29 | 30 | Indicates whether the animation should only run once 31 | 32 | ### `reverse (default: false)` 33 | 34 | Indicates whether the animation should run in reverse 35 | 36 | ## Events 37 | 38 | ### `started` 39 | 40 | Event fired when the animation starts 41 | 42 | ### `stopped` 43 | 44 | Event fired when the animation stops 45 | 46 | ## Exposed Methods 47 | 48 | ### `start` 49 | 50 | Starts the animation 51 | 52 | ### `stop` 53 | 54 | Stops the animation 55 | 56 | ## Styling 57 | 58 | This component does not have any styles. 59 | ``` -------------------------------------------------------------------------------- /packages/xmlui-devtools/package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "xmlui-devtools", 3 | "version": "0.1.20", 4 | "sideEffects": false, 5 | "scripts": { 6 | "start": "xmlui start", 7 | "preview": "xmlui preview", 8 | "build:extension": "xmlui build-lib", 9 | "build-watch": "xmlui build-lib --watch", 10 | "build:demo": "xmlui build", 11 | "build:meta": "xmlui build-lib --mode=metadata" 12 | }, 13 | "dependencies": { 14 | "@monaco-editor/loader": "^1.5.0", 15 | "@monaco-editor/react": "^4.7.0", 16 | "@radix-ui/react-dialog": "^1.1.14", 17 | "@radix-ui/react-dropdown-menu": "^2.1.7", 18 | "@radix-ui/react-tooltip": "^1.2.7", 19 | "framer-motion": "^12.18.1", 20 | "react-icons": "^5.5.0" 21 | }, 22 | "devDependencies": { 23 | "xmlui": "*" 24 | }, 25 | "main": "./dist/xmlui-devtools.js", 26 | "module": "./dist/xmlui-devtools.mjs", 27 | "exports": { 28 | ".": { 29 | "import": "./dist/xmlui-devtools.mjs", 30 | "require": "./dist/xmlui-devtools.js" 31 | }, 32 | "./*.css": { 33 | "import": "./dist/*.css", 34 | "require": "./dist/*.css" 35 | } 36 | }, 37 | "files": [ 38 | "dist" 39 | ], 40 | "engines": { 41 | "node": ">=18.0.0" 42 | } 43 | } 44 | ``` -------------------------------------------------------------------------------- /packages/xmlui-playground/src/playground/Editor.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { editorStatusChanged, textChanged } from "../state/store"; 2 | import { startTransition, useCallback, useEffect, useState } from "react"; 3 | import { usePlayground } from "../hooks/usePlayground"; 4 | import { Editor as XMLUIEditor } from "xmlui-devtools"; 5 | 6 | export const Editor = () => { 7 | const { text, dispatch, options } = usePlayground(); 8 | const [value, setValue] = useState(text); 9 | 10 | useEffect(() => { 11 | setValue(text); 12 | }, [text]); 13 | 14 | const updateValue = useCallback( 15 | (value: string) => { 16 | setValue(value); 17 | startTransition(() => { 18 | dispatch(textChanged(value)); 19 | }); 20 | }, 21 | [dispatch], 22 | ); 23 | 24 | useEffect(() => { 25 | dispatch(editorStatusChanged("loading")); 26 | }, [dispatch]); 27 | 28 | return ( 29 | <XMLUIEditor 30 | readOnly={false} 31 | activeThemeTone={options.activeTone} 32 | saveViewState={true} 33 | key={"app"} 34 | onChange={updateValue} 35 | language={options.language} 36 | onMount={() => { 37 | dispatch(editorStatusChanged("loaded")); 38 | }} 39 | value={value} 40 | /> 41 | ); 42 | }; 43 | ``` -------------------------------------------------------------------------------- /docs/public/pages/xmlui-charts/LabelList.md: -------------------------------------------------------------------------------- ```markdown 1 | # LabelList [#labellist] 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.Label list component for a chart component. 5 | 6 | ## Properties 7 | 8 | ### `key` 9 | 10 | The key that needs to be matched to the data series. 11 | 12 | ### `position (default: "inside")` 13 | 14 | The position of the label list 15 | 16 | Available values: `top`, `left`, `right`, `bottom`, `inside` **(default)**, `outside`, `insideLeft`, `insideRight`, `insideTop`, `insideBottom`, `insideTopLeft`, `insideBottomLeft`, `insideTopRight`, `insideBottomRight`, `insideStart`, `insideEnd`, `end`, `center`, `centerTop`, `centerBottom`, `middle` 17 | 18 | ## Events 19 | 20 | This component does not have any events. 21 | 22 | ## Exposed Methods 23 | 24 | This component does not expose any methods. 25 | 26 | ## Styling 27 | 28 | ### Theme Variables 29 | 30 | | Variable | Default Value (Light) | Default Value (Dark) | 31 | | --- | --- | --- | 32 | | [textColor](../styles-and-themes/common-units/#color)-LabelList | $textColor-primary | $textColor-primary | 33 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/PositionedContainer/PositionedContainer.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import styles from "./PositionedContainer.module.scss"; 2 | 3 | import { createComponentRenderer } from "../../components-core/renderers"; 4 | import { parseScssVar } from "../../components-core/theming/themeVars"; 5 | import { PositionedContainer } from "./PositionedContainerNative"; 6 | import { createMetadata, d } from "../metadata-helpers"; 7 | 8 | const COMP = "PositionedContainer"; 9 | 10 | export const PositionedContainerMd = createMetadata({ 11 | status: "deprecated", 12 | description: "(**OBSOLETE**) This component was created for the ChatEngine app.", 13 | props: { 14 | visibleOnHover: d("No description"), 15 | }, 16 | themeVars: parseScssVar(styles.themeVars), 17 | }); 18 | 19 | export const positionedContainerComponentRenderer = createComponentRenderer( 20 | COMP, 21 | PositionedContainerMd, 22 | ({ node, extractValue, renderChild, className }) => { 23 | return ( 24 | <PositionedContainer 25 | className={className} 26 | visibleOnHover={extractValue.asOptionalBoolean(node.props.visibleOnHover)} 27 | > 28 | {renderChild(node.children)} 29 | </PositionedContainer> 30 | ); 31 | }, 32 | ); 33 | ``` -------------------------------------------------------------------------------- /packages/xmlui-playground/package.json: -------------------------------------------------------------------------------- ```json 1 | { 2 | "name": "xmlui-playground", 3 | "version": "0.1.10", 4 | "sideEffects": false, 5 | "scripts": { 6 | "start": "xmlui start", 7 | "preview": "xmlui preview", 8 | "build:extension": "xmlui build-lib", 9 | "build-watch": "xmlui build-lib --watch", 10 | "build:demo": "xmlui build", 11 | "build:meta": "xmlui build-lib --mode=metadata" 12 | }, 13 | "dependencies": { 14 | "@radix-ui/react-dropdown-menu": "^2.1.7", 15 | "@radix-ui/react-toast": "^1.2.13", 16 | "@radix-ui/react-tooltip": "^1.2.6", 17 | "file-saver": "^2.0.5", 18 | "jszip": "^3.10.1", 19 | "react-icons": "^5.5.0", 20 | "xmlui-devtools": "*" 21 | }, 22 | "devDependencies": { 23 | "@types/file-saver": "^2.0.7", 24 | "xmlui": "*" 25 | }, 26 | "main": "./dist/xmlui-playground.js", 27 | "module": "./dist/xmlui-playground.mjs", 28 | "exports": { 29 | ".": { 30 | "import": "./dist/xmlui-playground.mjs", 31 | "require": "./dist/xmlui-playground.js" 32 | }, 33 | "./*.css": { 34 | "import": "./dist/*.css", 35 | "require": "./dist/*.css" 36 | } 37 | }, 38 | "files": [ 39 | "dist" 40 | ], 41 | "engines": { 42 | "node": ">=18.0.0" 43 | } 44 | } 45 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Icon/svg/box.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M14 10.6669V5.33359C13.9998 5.09978 13.938 4.87013 13.821 4.6677C13.704 4.46527 13.5358 4.29717 13.3333 4.18026L8.66667 1.51359C8.46397 1.39657 8.23405 1.33496 8 1.33496C7.76595 1.33496 7.53603 1.39657 7.33333 1.51359L2.66667 4.18026C2.46418 4.29717 2.29599 4.46527 2.17897 4.6677C2.06196 4.87013 2.00024 5.09978 2 5.33359V10.6669C2.00024 10.9007 2.06196 11.1304 2.17897 11.3328C2.29599 11.5353 2.46418 11.7034 2.66667 11.8203L7.33333 14.4869C7.53603 14.604 7.76595 14.6656 8 14.6656C8.23405 14.6656 8.46397 14.604 8.66667 14.4869L13.3333 11.8203C13.5358 11.7034 13.704 11.5353 13.821 11.3328C13.938 11.1304 13.9998 10.9007 14 10.6669Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> <path d="M2.18018 4.63965L8.00018 8.00632L13.8202 4.63965" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> <path d="M8 14.72V8" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> </svg> ``` -------------------------------------------------------------------------------- /xmlui/tests-e2e/assign-to-object-or-array-regression.spec.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { test } from "../src/testing/fixtures"; 2 | import { expect } from "../src/testing/assertions"; 3 | 4 | test("assign to object with number key", async ({ page, initTestBed }) => { 5 | await initTestBed(` 6 | <Fragment> 7 | <script> 8 | var rolesByIds = {}; 9 | </script> 10 | <Button 11 | testId="button" 12 | onClick="rolesByIds[5] = 'EDITOR'" 13 | /> 14 | <Text testId='result'>{JSON.stringify(rolesByIds)}</Text> 15 | </Fragment> 16 | `); 17 | await page.getByTestId("button").click(); 18 | await expect(page.getByTestId("result")).toHaveText("{\"5\":\"EDITOR\"}"); 19 | }); 20 | 21 | test("assign to array with number key", async ({ page, initTestBed }) => { 22 | await initTestBed(` 23 | <Fragment> 24 | <script> 25 | var userIds = [1, 2, 3, 4]; 26 | </script> 27 | <Button 28 | testId="button" 29 | onClick="userIds[1] = 'MODIFIED'" 30 | /> 31 | <Text testId='result'>{JSON.stringify(userIds)}</Text> 32 | </Fragment> 33 | `); 34 | await page.getByTestId("button").click(); 35 | await expect(page.getByTestId("result")).toHaveText("[1,\"MODIFIED\",3,4]"); 36 | }); ``` -------------------------------------------------------------------------------- /docs/public/pages/xmlui-animations/SlideInAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # SlideInAnimation [#slideinanimation] 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 `SlideInAnimation` component represents an animation that slides in the content from the left. 5 | 6 | ## Properties 7 | 8 | ### `animateWhenInView` 9 | 10 | Indicates whether the animation should start when the component is in view. 11 | 12 | ### `delay (default: 0)` 13 | 14 | The delay before the animation starts in milliseconds 15 | 16 | ### `direction (default: "left")` 17 | 18 | The direction of the animation. 19 | 20 | ### `duration` 21 | 22 | The duration of the animation in milliseconds. 23 | 24 | ### `loop (default: false)` 25 | 26 | Indicates whether the animation should loop 27 | 28 | ### `reverse (default: false)` 29 | 30 | Indicates whether the animation should run in reverse 31 | 32 | ## Events 33 | 34 | ### `started` 35 | 36 | Event fired when the animation starts 37 | 38 | ### `stopped` 39 | 40 | Event fired when the animation stops 41 | 42 | ## Exposed Methods 43 | 44 | ### `start` 45 | 46 | Starts the animation 47 | 48 | ### `stop` 49 | 50 | Stops the animation 51 | 52 | ## Styling 53 | 54 | This component does not have any styles. 55 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/ContentSeparator/ContentSeparatorNative.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { forwardRef, type CSSProperties } from "react"; 2 | import classnames from "classnames"; 3 | 4 | import styles from "./ContentSeparator.module.scss"; 5 | 6 | type ContentSeparatorProps = { 7 | size?: number | string; 8 | orientation?: string; 9 | style?: CSSProperties; 10 | className?: string; 11 | }; 12 | 13 | export const defaultProps: Pick<ContentSeparatorProps, "orientation"> = { 14 | orientation: "horizontal", 15 | }; 16 | 17 | export const ContentSeparator = forwardRef<HTMLDivElement, ContentSeparatorProps>( 18 | ({ orientation = defaultProps.orientation, size, style, className, ...rest }, ref) => { 19 | return ( 20 | <div 21 | {...rest} 22 | ref={ref} 23 | className={classnames( 24 | styles.separator, 25 | { 26 | [styles.horizontal]: orientation === "horizontal", 27 | [styles.vertical]: orientation === "vertical", 28 | }, 29 | className, 30 | )} 31 | style={{ 32 | height: orientation === "horizontal" ? size : undefined, 33 | width: orientation === "horizontal" ? "100%" : size, 34 | ...style, 35 | }} 36 | /> 37 | ); 38 | } 39 | ); 40 | ``` -------------------------------------------------------------------------------- /docs/public/resources/files/news-and-reviews.json: -------------------------------------------------------------------------------- ```json 1 | [ 2 | { 3 | "date": "2025-09-08", 4 | "title": "How To Upgrade Your MCP Server With Context Engineering", 5 | "url": "https://thenewstack.io/how-to-upgrade-your-mcp-server-with-context-engineering/", 6 | "source": "thenewstack.io" 7 | }, 8 | { 9 | "date": "2025-07-23", 10 | "title": "XMLUI builds React-based UIs with simple markup", 11 | "url": "https://www.infoworld.com/article/4026889/xmlui-builds-react-based-uis-with-simple-markup.html", 12 | "source": "infoworld.com" 13 | }, 14 | { 15 | "date": "2025-07-22", 16 | "title": "Make React Components With XMLUI, a Visual Basic for the AI Era", 17 | "url": "https://thenewstack.io/make-react-components-with-xmlui-a-visual-basic-for-the-ai-era/", 18 | "source": "thenewstack.io" 19 | }, 20 | { 21 | "date": "2025-07-21", 22 | "title": "Components for Web Apps", 23 | "url": "https://www.windley.com/archives/2025/07/components_for_web_apps.shtml", 24 | "source": "windley.com" 25 | }, 26 | { 27 | "date": "2025-07-18", 28 | "title": "Introducing XMLUI", 29 | "url": "https://blog.jonudell.net/2025/07/18/introducing-xmlui/", 30 | "source": "blog.jonudell.net" 31 | } 32 | ] 33 | ``` -------------------------------------------------------------------------------- /docs/content/components/StickyBox.md: -------------------------------------------------------------------------------- ```markdown 1 | # StickyBox [#stickybox] 2 | 3 | `StickyBox` remains fixed at the top or bottom of the screen as the user scrolls. 4 | 5 | ## Properties [#properties] 6 | 7 | ### `to` (default: "top") [#to-default-top] 8 | 9 | This property determines whether the StickyBox should be anchored to the `top` or `bottom`. 10 | 11 | Available values: `top` **(default)**, `bottom` 12 | 13 | ```xmlui-pg copy display name="Example: to" height="200px" 14 | <App> 15 | <StickyBox to="top"> 16 | This part of the UI sticks to the top 17 | </StickyBox> 18 | <Stack backgroundColor="red" height="80px" width="100%" /> 19 | <Stack backgroundColor="green" height="80px" width="100%" /> 20 | <Stack backgroundColor="blue" height="80px" width="100%" /> 21 | </App> 22 | ``` 23 | 24 | ## Events [#events] 25 | 26 | This component does not have any events. 27 | 28 | ## Exposed Methods [#exposed-methods] 29 | 30 | This component does not expose any methods. 31 | 32 | ## Styling [#styling] 33 | 34 | ### Theme Variables [#theme-variables] 35 | 36 | | Variable | Default Value (Light) | Default Value (Dark) | 37 | | --- | --- | --- | 38 | | [backgroundColor](../styles-and-themes/common-units/#color)-StickyBox | $backgroundColor | $backgroundColor | 39 | ``` -------------------------------------------------------------------------------- /packages/xmlui-pdf/src/index.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { createComponentRenderer, createMetadata, d, parseScssVar } from "xmlui"; 2 | import { LazyPdf } from "./LazyPdfNative"; 3 | import styles from "./Pdf.module.scss"; 4 | 5 | const COMP = "Pdf"; 6 | export const PdfMd = createMetadata({ 7 | description: `The \`${COMP}\` component provides a read-only preview of a pdf document's contents.`, 8 | status: "experimental", 9 | props: { 10 | src: { 11 | description: `This property defines the source URL of the pdf document to display.`, 12 | valueType: "string", 13 | }, 14 | data: d( 15 | `This property contains the binary data that represents the PDF document.`, 16 | ), 17 | }, 18 | themeVars: parseScssVar(styles.themeVars), 19 | defaultThemeVars: { 20 | "boxShadow-page-Pdf": "$boxShadow-md", 21 | "gap-pages-Pdf": "$space-4", 22 | }, 23 | }); 24 | const PdfComponent = createComponentRenderer(COMP, PdfMd, ({ node, extractValue }) => { 25 | const props = node.props as typeof PdfMd.props; 26 | return <LazyPdf src={extractValue(props!.src)} data={extractValue(props!.data)} />; 27 | }); 28 | 29 | export default { 30 | namespace: "XMLUIExtensions", 31 | components: [PdfComponent], 32 | }; 33 | ``` -------------------------------------------------------------------------------- /xmlui/tests-e2e/api-bound-component-regression.spec.ts: -------------------------------------------------------------------------------- ```typescript 1 | import { expect, test } from "../src/testing/fixtures"; 2 | 3 | test("multiple api-bound component don't mix/overwrite state", async ({ initTestBed, page }) => { 4 | await initTestBed( 5 | ` 6 | <Fragment> 7 | <Text testId='data1_text'> 8 | <property name="value"> 9 | <DataSource url="/data1"/> 10 | </property> 11 | </Text> 12 | <Text testId='data2_text'> 13 | <property name="value"> 14 | <DataSource url="/data2"/> 15 | </property> 16 | </Text> 17 | </Fragment> 18 | `, 19 | { 20 | apiInterceptor: { 21 | operations: { 22 | "load-api-data1": { 23 | url: "/data1", 24 | method: "get", 25 | handler: `()=>{ 26 | return 'data1'; 27 | }`, 28 | }, 29 | "load-api-data2": { 30 | url: "/data2", 31 | method: "get", 32 | handler: `()=>{ 33 | return 'data2'; 34 | }`, 35 | }, 36 | }, 37 | }, 38 | }, 39 | ); 40 | 41 | await expect(page.getByTestId("data1_text")).toHaveText("data1"); 42 | await expect(page.getByTestId("data2_text")).toHaveText("data2"); 43 | }); 44 | ``` -------------------------------------------------------------------------------- /packages/xmlui-os-frames/src/IPhoneFrame.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import styles from "./IPhoneFrame.module.scss"; 2 | import classNames from "classnames"; 3 | import type { ReactNode } from "react"; 4 | import { forwardRef } from "react"; 5 | 6 | export const IPhoneFrame = forwardRef(({ children }: {children: ReactNode}, ref) => { 7 | return ( 8 | // simple wrapper, in case if it's in a flowlayout (the device width/height could be overwritten otherwise), temp 9 | <div> 10 | <div className={classNames(styles.device, styles.deviceIphone14Pro)} ref={ref as any}> 11 | <div className={styles.deviceFrame}> 12 | <div className={styles.deviceScreen}> 13 | {children} 14 | </div> 15 | {/*<img className="device-screen" src="assets/img/bg-iphone-14-pro.jpg" loading="lazy" />*/} 16 | </div> 17 | <div className={styles.deviceStripe}></div> 18 | <div className={styles.deviceHeader}></div> 19 | <div className={styles.deviceSensors}></div> 20 | <div className={styles.deviceBtns}></div> 21 | <div className={styles.devicePower}></div> 22 | <div className={styles.deviceHome}></div> 23 | </div> 24 | </div> 25 | ); 26 | }); 27 | ``` -------------------------------------------------------------------------------- /xmlui/src/testing/infrastructure/public/resources/box.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" data-testid="box-svg"> 2 | <path d="M14 10.6669V5.33359C13.9998 5.09978 13.938 4.87013 13.821 4.6677C13.704 4.46527 13.5358 4.29717 13.3333 4.18026L8.66667 1.51359C8.46397 1.39657 8.23405 1.33496 8 1.33496C7.76595 1.33496 7.53603 1.39657 7.33333 1.51359L2.66667 4.18026C2.46418 4.29717 2.29599 4.46527 2.17897 4.6677C2.06196 4.87013 2.00024 5.09978 2 5.33359V10.6669C2.00024 10.9007 2.06196 11.1304 2.17897 11.3328C2.29599 11.5353 2.46418 11.7034 2.66667 11.8203L7.33333 14.4869C7.53603 14.604 7.76595 14.6656 8 14.6656C8.23405 14.6656 8.46397 14.604 8.66667 14.4869L13.3333 11.8203C13.5358 11.7034 13.704 11.5353 13.821 11.3328C13.938 11.1304 13.9998 10.9007 14 10.6669Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> 3 | <path d="M2.18018 4.63965L8.00018 8.00632L13.8202 4.63965" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> 4 | <path d="M8 14.72V8" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"/> 5 | </svg> 6 | ``` -------------------------------------------------------------------------------- /docs/content/components/MenuSeparator.md: -------------------------------------------------------------------------------- ```markdown 1 | # MenuSeparator [#menuseparator] 2 | 3 | `MenuSeparator` displays a separator line between menu items to group related menu options within `DropdownMenu`. 4 | 5 | ## Properties [#properties] 6 | 7 | This component does not have any properties. 8 | 9 | ## Events [#events] 10 | 11 | This component does not have any events. 12 | 13 | ## Exposed Methods [#exposed-methods] 14 | 15 | This component does not expose any methods. 16 | 17 | ## Styling [#styling] 18 | 19 | ### Theme Variables [#theme-variables] 20 | 21 | | Variable | Default Value (Light) | Default Value (Dark) | 22 | | --- | --- | --- | 23 | | [color](../styles-and-themes/common-units/#color)-MenuSeparator | $borderColor-dropdown-item | $borderColor-dropdown-item | 24 | | [height](../styles-and-themes/common-units/#size)-MenuSeparator | 1px | 1px | 25 | | [marginBottom](../styles-and-themes/common-units/#size)-MenuSeparator | $space-1 | $space-1 | 26 | | [margin](../styles-and-themes/common-units/#size)Horizontal-MenuSeparator | 12px | 12px | 27 | | [marginTop](../styles-and-themes/common-units/#size)-MenuSeparator | $space-1 | $space-1 | 28 | | [width](../styles-and-themes/common-units/#size)-MenuSeparator | 100% | 100% | 29 | ``` -------------------------------------------------------------------------------- /docs/public/pages/xmlui-animations/ScaleAnimation.md: -------------------------------------------------------------------------------- ```markdown 1 | # ScaleAnimation [#scaleanimation] 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 `ScaleAnimation` component represents an animation that scales the content. 5 | 6 | ## Properties 7 | 8 | ### `animateWhenInView` 9 | 10 | Indicates whether the animation should start when the component is in view. 11 | 12 | ### `delay (default: 0)` 13 | 14 | The delay before the animation starts in milliseconds 15 | 16 | ### `duration` 17 | 18 | The duration of the animation in milliseconds. 19 | 20 | ### `from (default: 0)` 21 | 22 | The initial scale of the content. 23 | 24 | ### `loop (default: false)` 25 | 26 | Indicates whether the animation should loop 27 | 28 | ### `reverse (default: false)` 29 | 30 | Indicates whether the animation should run in reverse 31 | 32 | ### `to (default: 1)` 33 | 34 | The final scale of the content. 35 | 36 | ## Events 37 | 38 | ### `started` 39 | 40 | Event fired when the animation starts 41 | 42 | ### `stopped` 43 | 44 | Event fired when the animation stops 45 | 46 | ## Exposed Methods 47 | 48 | ### `start` 49 | 50 | Starts the animation 51 | 52 | ### `stop` 53 | 54 | Stops the animation 55 | 56 | ## Styling 57 | 58 | This component does not have any styles. 59 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/AutoComplete/AutoCompleteContext.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import type { ReactNode } from "react"; 2 | import { createContext, useContext } from "react"; 3 | 4 | import type { Option } from "../abstractions"; 5 | import type { SingleValueType } from "../Select/SelectNative"; 6 | 7 | type AutoCompleteContextValue = { 8 | multi?: boolean; 9 | value: string | string[] | null; 10 | onChange?: (selectedValue: string) => void; 11 | inputValue: string; 12 | searchTerm: string; 13 | options: Set<Option>; 14 | open?: boolean; 15 | setOpen?: (open: boolean) => void; 16 | setSelectedIndex?: (index: number) => void; 17 | optionRenderer: (option: Option, selectedValue: SingleValueType, inTrigger: boolean) => ReactNode; 18 | }; 19 | 20 | export const AutoCompleteContext = createContext<AutoCompleteContextValue>({ 21 | value: null, 22 | onChange: (selectedValue: string) => {}, 23 | inputValue: "", 24 | searchTerm: "", 25 | options: new Set<Option>(), 26 | open: false, 27 | setOpen: (open: boolean) => {}, 28 | setSelectedIndex: (index: number) => {}, 29 | optionRenderer: (option: Option, selectedValue: SingleValueType, inTrigger: boolean) => null, 30 | }); 31 | 32 | export function useAutoComplete() { 33 | return useContext(AutoCompleteContext); 34 | } 35 | ``` -------------------------------------------------------------------------------- /tools/create-app/helpers/install.ts: -------------------------------------------------------------------------------- ```typescript 1 | import spawn from "cross-spawn"; 2 | import type { PackageManager } from "./get-pkg-manager"; 3 | 4 | /** 5 | * Spawn a package manager installation based on user preference. 6 | * 7 | * @returns A Promise that resolves once the installation is finished. 8 | */ 9 | export async function install( 10 | /** Indicate which package manager to use. */ 11 | packageManager: PackageManager 12 | ): Promise<void> { 13 | let args: string[] = ["install"]; 14 | /** 15 | * Return a Promise that resolves once the installation is finished. 16 | */ 17 | return new Promise((resolve, reject) => { 18 | /** 19 | * Spawn the installation process. 20 | */ 21 | const child = spawn(packageManager, args, { 22 | stdio: "inherit", 23 | env: { 24 | ...process.env, 25 | ADBLOCK: "1", 26 | // we set NODE_ENV to development as pnpm skips dev 27 | // dependencies when production 28 | NODE_ENV: "development", 29 | DISABLE_OPENCOLLECTIVE: "1", 30 | }, 31 | }); 32 | child.on("close", (code) => { 33 | if (code !== 0) { 34 | reject({ command: `${packageManager} ${args.join(" ")}` }); 35 | return; 36 | } 37 | resolve(); 38 | }); 39 | }); 40 | } 41 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/Icon/svg/img.svg: -------------------------------------------------------------------------------- ``` 1 | <svg width="22" height="28" viewBox="0 0 22 28" fill="none" xmlns="http://www.w3.org/2000/svg"> 2 | <g clip-path="url(#clip0_1960_14704)"> 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="#F2F2F2"/> 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="#F2F2F2"/> 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="#E1E1E1"/> 6 | <path d="M9 17L14.1962 21.5H3.80385L9 17Z" fill="#8BDC6F"/> 7 | <path d="M13 14L18.1963 21.5H7.80396L13 14Z" fill="#8BDC6F"/> 8 | <circle cx="7" cy="11" r="2" fill="#EFC942"/> 9 | </g> 10 | <defs> 11 | <clipPath id="clip0_1960_14704"> 12 | <rect width="22" height="28" fill="white"/> 13 | </clipPath> 14 | </defs> 15 | </svg> ``` -------------------------------------------------------------------------------- /xmlui/src/components/NavPanel/NavPanel.md: -------------------------------------------------------------------------------- ```markdown 1 | %-DESC-START 2 | 3 | **Key features:** 4 | 5 | - **Layout adaptation**: Automatically positions navigation horizontally or vertically based on App layout 6 | - **Navigation organization**: Contains NavLink and NavGroup components to build structured menus 7 | - **Logo integration**: Supports custom logo templates in vertical layouts via logoTemplate property 8 | - **Drawer mode**: Can optionally display navigation in a collapsible drawer interface 9 | - **Theme integration**: Inherits styling from the app's theme system for consistent appearance 10 | 11 | %-DESC-END 12 | 13 | %-PROP-START logoTemplate 14 | 15 | ```xmlui-pg copy {3-8} display name="Example: logoTemplate" height={250} 16 | <App layout="vertical"> 17 | <NavPanel> 18 | <property name="logoTemplate"> 19 | <H3> 20 | <Icon name="drive" /> 21 | DriveDiag (Nav) 22 | </H3> 23 | </property> 24 | <NavLink label="Home" to="/" icon="home"/> 25 | <NavLink label="Page 1" to="/page1"/> 26 | </NavPanel> 27 | <Pages fallbackPath="/"> 28 | <Page url="/"> 29 | <Text value="Home" /> 30 | </Page> 31 | <Page url="/page1"> 32 | <Text value="Page 1" /> 33 | </Page> 34 | </Pages> 35 | </App> 36 | ``` 37 | 38 | %-PROP-END 39 | ``` -------------------------------------------------------------------------------- /xmlui/src/components/NoResult/NoResult.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: "NoResult"; 11 | $themeVars: t.composePaddingVars($themeVars, $component); 12 | $themeVars: t.composeBorderVars($themeVars, $component); 13 | $gap-icon-NoResult: createThemeVar("gap-icon-#{$component}"); 14 | $size-icon-NoResult: createThemeVar("size-icon-#{$component}"); 15 | 16 | @layer components { 17 | .wrapper { 18 | display: flex; 19 | flex-direction: column; 20 | align-items: center; 21 | justify-content: center; 22 | @include t.borderVars($themeVars, $component); 23 | @include t.paddingVars($themeVars, $component); 24 | } 25 | 26 | .icon { 27 | width: $size-icon-NoResult; 28 | height: $size-icon-NoResult; 29 | margin-bottom: $gap-icon-NoResult; 30 | } 31 | } 32 | 33 | // --- We export the theme variables to add them to the component renderer 34 | :export { 35 | themeVars: t.json-stringify($themeVars); 36 | } 37 | ```