This is page 98 of 190. Use http://codebase.md/xmlui-org/xmlui/0.9.23.js?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .changeset
│ ├── config.json
│ └── small-tires-beg.md
├── .eslintrc.cjs
├── .github
│ ├── build-checklist.png
│ ├── ISSUE_TEMPLATE
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ └── workflows
│ ├── deploy-blog-optimized.yml
│ ├── deploy-blog-swa.yml
│ ├── deploy-blog.yml
│ ├── deploy-docs-optimized.yml
│ ├── deploy-docs-swa.yml
│ ├── deploy-docs.yml
│ ├── prepare-versions.yml
│ ├── release-packages.yml
│ ├── run-all-tests.yml
│ └── run-smoke-tests.yml
├── .gitignore
├── .prettierrc.js
├── .vscode
│ ├── launch.json
│ └── settings.json
├── blog
│ ├── .gitignore
│ ├── .gitkeep
│ ├── CHANGELOG.md
│ ├── extensions.ts
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── public
│ │ ├── blog
│ │ │ ├── images
│ │ │ │ ├── an-advanced-codefence.gif
│ │ │ │ ├── an-advanced-codefence.mp4
│ │ │ │ ├── blog-page-component.png
│ │ │ │ ├── blog-scrabble.png
│ │ │ │ ├── codefence-runner.png
│ │ │ │ ├── integrated-blog-search.png
│ │ │ │ ├── lorem-ipsum.png
│ │ │ │ ├── playground-checkbox-source.png
│ │ │ │ ├── playground.png
│ │ │ │ ├── use-xmlui-mcp-to-find-a-howto.png
│ │ │ │ └── xmlui-demo-gallery.png
│ │ │ ├── introducing-xmlui.md
│ │ │ ├── lorem-ipsum.md
│ │ │ ├── newest-post.md
│ │ │ ├── older-post.md
│ │ │ ├── xmlui-playground.md
│ │ │ └── xmlui-powered-blog.md
│ │ ├── mockServiceWorker.js
│ │ ├── resources
│ │ │ ├── favicon.ico
│ │ │ ├── files
│ │ │ │ └── for-download
│ │ │ │ └── xmlui
│ │ │ │ └── xmlui-standalone.umd.js
│ │ │ ├── github.svg
│ │ │ ├── icons
│ │ │ │ ├── github.svg
│ │ │ │ └── rss.svg
│ │ │ ├── llms.txt
│ │ │ ├── logo-dark.svg
│ │ │ ├── logo.svg
│ │ │ ├── pg-popout.svg
│ │ │ ├── rss.svg
│ │ │ └── xmlui-logo.svg
│ │ ├── serve.json
│ │ ├── staticwebapp.config.json
│ │ └── web.config
│ ├── scripts
│ │ ├── download-latest-xmlui.js
│ │ ├── generate-rss.js
│ │ ├── get-releases.js
│ │ └── utils.js
│ ├── src
│ │ ├── components
│ │ │ ├── BlogOverview.xmlui
│ │ │ ├── BlogPage.xmlui
│ │ │ ├── LinkButton.xmlui
│ │ │ ├── PageNotFound.xmlui
│ │ │ └── Separator.xmlui
│ │ ├── config.ts
│ │ ├── Main.xmlui
│ │ └── themes
│ │ └── blog-theme.ts
│ └── tsconfig.json
├── CONTRIBUTING.md
├── docs
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── ComponentRefLinks.txt
│ ├── content
│ │ ├── _meta.json
│ │ ├── components
│ │ │ ├── _meta.json
│ │ │ ├── _overview.md
│ │ │ ├── APICall.md
│ │ │ ├── App.md
│ │ │ ├── AppHeader.md
│ │ │ ├── AppState.md
│ │ │ ├── AutoComplete.md
│ │ │ ├── Avatar.md
│ │ │ ├── Backdrop.md
│ │ │ ├── Badge.md
│ │ │ ├── BarChart.md
│ │ │ ├── Bookmark.md
│ │ │ ├── Breakout.md
│ │ │ ├── Button.md
│ │ │ ├── Card.md
│ │ │ ├── Carousel.md
│ │ │ ├── ChangeListener.md
│ │ │ ├── Checkbox.md
│ │ │ ├── CHStack.md
│ │ │ ├── ColorPicker.md
│ │ │ ├── Column.md
│ │ │ ├── ContentSeparator.md
│ │ │ ├── CVStack.md
│ │ │ ├── DataSource.md
│ │ │ ├── DateInput.md
│ │ │ ├── DatePicker.md
│ │ │ ├── DonutChart.md
│ │ │ ├── DropdownMenu.md
│ │ │ ├── EmojiSelector.md
│ │ │ ├── ExpandableItem.md
│ │ │ ├── FileInput.md
│ │ │ ├── FileUploadDropZone.md
│ │ │ ├── FlowLayout.md
│ │ │ ├── Footer.md
│ │ │ ├── Form.md
│ │ │ ├── FormItem.md
│ │ │ ├── FormSection.md
│ │ │ ├── Fragment.md
│ │ │ ├── H1.md
│ │ │ ├── H2.md
│ │ │ ├── H3.md
│ │ │ ├── H4.md
│ │ │ ├── H5.md
│ │ │ ├── H6.md
│ │ │ ├── Heading.md
│ │ │ ├── HSplitter.md
│ │ │ ├── HStack.md
│ │ │ ├── Icon.md
│ │ │ ├── IFrame.md
│ │ │ ├── Image.md
│ │ │ ├── Items.md
│ │ │ ├── LabelList.md
│ │ │ ├── Legend.md
│ │ │ ├── LineChart.md
│ │ │ ├── Link.md
│ │ │ ├── List.md
│ │ │ ├── Logo.md
│ │ │ ├── Markdown.md
│ │ │ ├── MenuItem.md
│ │ │ ├── MenuSeparator.md
│ │ │ ├── ModalDialog.md
│ │ │ ├── NavGroup.md
│ │ │ ├── NavLink.md
│ │ │ ├── NavPanel.md
│ │ │ ├── NoResult.md
│ │ │ ├── NumberBox.md
│ │ │ ├── Option.md
│ │ │ ├── Page.md
│ │ │ ├── PageMetaTitle.md
│ │ │ ├── Pages.md
│ │ │ ├── Pagination.md
│ │ │ ├── PasswordInput.md
│ │ │ ├── PieChart.md
│ │ │ ├── ProgressBar.md
│ │ │ ├── Queue.md
│ │ │ ├── RadioGroup.md
│ │ │ ├── RealTimeAdapter.md
│ │ │ ├── Redirect.md
│ │ │ ├── Select.md
│ │ │ ├── Slider.md
│ │ │ ├── Slot.md
│ │ │ ├── SpaceFiller.md
│ │ │ ├── Spinner.md
│ │ │ ├── Splitter.md
│ │ │ ├── Stack.md
│ │ │ ├── StickyBox.md
│ │ │ ├── SubMenuItem.md
│ │ │ ├── Switch.md
│ │ │ ├── TabItem.md
│ │ │ ├── Table.md
│ │ │ ├── TableOfContents.md
│ │ │ ├── Tabs.md
│ │ │ ├── Text.md
│ │ │ ├── TextArea.md
│ │ │ ├── TextBox.md
│ │ │ ├── Theme.md
│ │ │ ├── TimeInput.md
│ │ │ ├── Timer.md
│ │ │ ├── ToneChangerButton.md
│ │ │ ├── ToneSwitch.md
│ │ │ ├── Tooltip.md
│ │ │ ├── Tree.md
│ │ │ ├── VSplitter.md
│ │ │ ├── VStack.md
│ │ │ ├── xmlui-animations
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ ├── Animation.md
│ │ │ │ ├── FadeAnimation.md
│ │ │ │ ├── FadeInAnimation.md
│ │ │ │ ├── FadeOutAnimation.md
│ │ │ │ ├── ScaleAnimation.md
│ │ │ │ └── SlideInAnimation.md
│ │ │ ├── xmlui-pdf
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ └── Pdf.md
│ │ │ ├── xmlui-spreadsheet
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ └── Spreadsheet.md
│ │ │ └── xmlui-website-blocks
│ │ │ ├── _meta.json
│ │ │ ├── _overview.md
│ │ │ ├── Carousel.md
│ │ │ ├── HelloMd.md
│ │ │ ├── HeroSection.md
│ │ │ └── ScrollToTop.md
│ │ └── extensions
│ │ ├── _meta.json
│ │ ├── xmlui-animations
│ │ │ ├── _meta.json
│ │ │ ├── _overview.md
│ │ │ ├── Animation.md
│ │ │ ├── FadeAnimation.md
│ │ │ ├── FadeInAnimation.md
│ │ │ ├── FadeOutAnimation.md
│ │ │ ├── ScaleAnimation.md
│ │ │ └── SlideInAnimation.md
│ │ └── xmlui-website-blocks
│ │ ├── _meta.json
│ │ ├── _overview.md
│ │ ├── Carousel.md
│ │ ├── HelloMd.md
│ │ ├── HeroSection.md
│ │ └── ScrollToTop.md
│ ├── extensions.ts
│ ├── index.html
│ ├── index.ts
│ ├── package.json
│ ├── public
│ │ ├── feed.rss
│ │ ├── mockServiceWorker.js
│ │ ├── pages
│ │ │ ├── _meta.json
│ │ │ ├── app-structure.md
│ │ │ ├── build-editor-component.md
│ │ │ ├── build-hello-world-component.md
│ │ │ ├── components-intro.md
│ │ │ ├── context-variables.md
│ │ │ ├── forms.md
│ │ │ ├── globals.md
│ │ │ ├── glossary.md
│ │ │ ├── helper-tags.md
│ │ │ ├── hosted-deployment.md
│ │ │ ├── howto
│ │ │ │ ├── assign-a-complex-json-literal-to-a-component-variable.md
│ │ │ │ ├── chain-a-refetch.md
│ │ │ │ ├── control-cache-invalidation.md
│ │ │ │ ├── debounce-user-input-for-api-calls.md
│ │ │ │ ├── debounce-with-changelistener.md
│ │ │ │ ├── debug-a-component.md
│ │ │ │ ├── delay-a-datasource-until-another-datasource-is-ready.md
│ │ │ │ ├── delegate-a-method.md
│ │ │ │ ├── do-custom-form-validation.md
│ │ │ │ ├── expose-a-method-from-a-component.md
│ │ │ │ ├── filter-and-transform-data-from-an-api.md
│ │ │ │ ├── group-items-in-list-by-a-property.md
│ │ │ │ ├── handle-background-operations.md
│ │ │ │ ├── hide-an-element-until-its-datasource-is-ready.md
│ │ │ │ ├── make-a-set-of-equal-width-cards.md
│ │ │ │ ├── make-a-table-responsive.md
│ │ │ │ ├── make-navpanel-width-responsive.md
│ │ │ │ ├── modify-a-value-reported-in-a-column.md
│ │ │ │ ├── paginate-a-list.md
│ │ │ │ ├── pass-data-to-a-modal-dialog.md
│ │ │ │ ├── react-to-button-click-not-keystrokes.md
│ │ │ │ ├── set-the-initial-value-of-a-select-from-fetched-data.md
│ │ │ │ ├── share-a-modaldialog-across-components.md
│ │ │ │ ├── sync-selections-between-table-and-list-views.md
│ │ │ │ ├── update-ui-optimistically.md
│ │ │ │ ├── use-built-in-form-validation.md
│ │ │ │ └── use-the-same-modaldialog-to-add-or-edit.md
│ │ │ ├── howto.md
│ │ │ ├── intro.md
│ │ │ ├── layout.md
│ │ │ ├── markup.md
│ │ │ ├── mcp.md
│ │ │ ├── modal-dialogs.md
│ │ │ ├── news-and-reviews.md
│ │ │ ├── reactive-intro.md
│ │ │ ├── refactoring.md
│ │ │ ├── routing-and-links.md
│ │ │ ├── samples
│ │ │ │ ├── color-palette.xmlui
│ │ │ │ ├── color-values.xmlui
│ │ │ │ ├── shadow-sizes.xmlui
│ │ │ │ ├── spacing-sizes.xmlui
│ │ │ │ ├── swatch.xmlui
│ │ │ │ ├── theme-gallery-brief.xmlui
│ │ │ │ └── theme-gallery.xmlui
│ │ │ ├── scoping.md
│ │ │ ├── scripting.md
│ │ │ ├── styles-and-themes
│ │ │ │ ├── common-units.md
│ │ │ │ ├── layout-props.md
│ │ │ │ ├── theme-variable-defaults.md
│ │ │ │ ├── theme-variables.md
│ │ │ │ └── themes.md
│ │ │ ├── template-properties.md
│ │ │ ├── test.md
│ │ │ ├── tutorial-01.md
│ │ │ ├── tutorial-02.md
│ │ │ ├── tutorial-03.md
│ │ │ ├── tutorial-04.md
│ │ │ ├── tutorial-05.md
│ │ │ ├── tutorial-06.md
│ │ │ ├── tutorial-07.md
│ │ │ ├── tutorial-08.md
│ │ │ ├── tutorial-09.md
│ │ │ ├── tutorial-10.md
│ │ │ ├── tutorial-11.md
│ │ │ ├── tutorial-12.md
│ │ │ ├── universal-properties.md
│ │ │ ├── user-defined-components.md
│ │ │ ├── vscode.md
│ │ │ ├── working-with-markdown.md
│ │ │ ├── working-with-text.md
│ │ │ ├── xmlui-animations
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ ├── Animation.md
│ │ │ │ ├── FadeAnimation.md
│ │ │ │ ├── FadeInAnimation.md
│ │ │ │ ├── FadeOutAnimation.md
│ │ │ │ ├── ScaleAnimation.md
│ │ │ │ └── SlideInAnimation.md
│ │ │ ├── xmlui-charts
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ ├── BarChart.md
│ │ │ │ ├── DonutChart.md
│ │ │ │ ├── LabelList.md
│ │ │ │ ├── Legend.md
│ │ │ │ ├── LineChart.md
│ │ │ │ └── PieChart.md
│ │ │ ├── xmlui-pdf
│ │ │ │ ├── _meta.json
│ │ │ │ ├── _overview.md
│ │ │ │ └── Pdf.md
│ │ │ └── xmlui-spreadsheet
│ │ │ ├── _meta.json
│ │ │ ├── _overview.md
│ │ │ └── Spreadsheet.md
│ │ ├── resources
│ │ │ ├── devdocs
│ │ │ │ ├── debug-proxy-object-2.png
│ │ │ │ ├── debug-proxy-object.png
│ │ │ │ ├── table_editor_01.png
│ │ │ │ ├── table_editor_02.png
│ │ │ │ ├── table_editor_03.png
│ │ │ │ ├── table_editor_04.png
│ │ │ │ ├── table_editor_05.png
│ │ │ │ ├── table_editor_06.png
│ │ │ │ ├── table_editor_07.png
│ │ │ │ ├── table_editor_08.png
│ │ │ │ ├── table_editor_09.png
│ │ │ │ ├── table_editor_10.png
│ │ │ │ ├── table_editor_11.png
│ │ │ │ ├── table-editor-01.png
│ │ │ │ ├── table-editor-02.png
│ │ │ │ ├── table-editor-03.png
│ │ │ │ ├── table-editor-04.png
│ │ │ │ ├── table-editor-06.png
│ │ │ │ ├── table-editor-07.png
│ │ │ │ ├── table-editor-08.png
│ │ │ │ ├── table-editor-09.png
│ │ │ │ └── xmlui-rendering-of-tiptap-markdown.png
│ │ │ ├── favicon.ico
│ │ │ ├── files
│ │ │ │ ├── clients.json
│ │ │ │ ├── daily-revenue.json
│ │ │ │ ├── dashboard-stats.json
│ │ │ │ ├── demo.xmlui
│ │ │ │ ├── demo.xmlui.xs
│ │ │ │ ├── downloads
│ │ │ │ │ └── downloads.json
│ │ │ │ ├── for-download
│ │ │ │ │ ├── index-with-api.html
│ │ │ │ │ ├── index.html
│ │ │ │ │ ├── mockApi.js
│ │ │ │ │ ├── start-darwin.sh
│ │ │ │ │ ├── start-linux.sh
│ │ │ │ │ ├── start.bat
│ │ │ │ │ └── xmlui
│ │ │ │ │ └── xmlui-standalone.umd.js
│ │ │ │ ├── getting-started
│ │ │ │ │ ├── cl-tutorial-final.zip
│ │ │ │ │ ├── cl-tutorial.zip
│ │ │ │ │ ├── cl-tutorial2.zip
│ │ │ │ │ ├── cl-tutorial3.zip
│ │ │ │ │ ├── cl-tutorial4.zip
│ │ │ │ │ ├── cl-tutorial5.zip
│ │ │ │ │ ├── cl-tutorial6.zip
│ │ │ │ │ ├── getting-started.zip
│ │ │ │ │ ├── hello-xmlui.zip
│ │ │ │ │ ├── xmlui-empty.zip
│ │ │ │ │ └── xmlui-starter.zip
│ │ │ │ ├── howto
│ │ │ │ │ └── component-icons
│ │ │ │ │ └── up-arrow.svg
│ │ │ │ ├── invoices.json
│ │ │ │ ├── monthly-status.json
│ │ │ │ ├── news-and-reviews.json
│ │ │ │ ├── products.json
│ │ │ │ ├── releases.json
│ │ │ │ ├── tutorials
│ │ │ │ │ ├── datasource
│ │ │ │ │ │ └── api.ts
│ │ │ │ │ └── p2do
│ │ │ │ │ ├── api.ts
│ │ │ │ │ └── todo-logo.svg
│ │ │ │ └── xmlui.json
│ │ │ ├── icons
│ │ │ │ ├── github.svg
│ │ │ │ └── rss.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
│ │ ├── staticwebapp.config.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
│ │ │ ├── LinkButton.xmlui
│ │ │ ├── NameValue.xmlui
│ │ │ ├── PageNotFound.xmlui
│ │ │ ├── PaletteItem.xmlui
│ │ │ ├── Palettes.xmlui
│ │ │ ├── SectionHeader.xmlui
│ │ │ ├── Separator.xmlui
│ │ │ ├── TBD.xmlui
│ │ │ ├── Test.xmlui
│ │ │ ├── ThemesIntro.xmlui
│ │ │ ├── ThousandThemes.xmlui
│ │ │ ├── TubeStops.xmlui
│ │ │ ├── TubeStops.xmlui.xs
│ │ │ └── TwoColumnCode.xmlui
│ │ ├── config.ts
│ │ ├── Main.xmlui
│ │ └── themes
│ │ ├── docs-theme.ts
│ │ ├── earthtone.ts
│ │ ├── xmlui-gray-on-default.ts
│ │ ├── xmlui-green-on-default.ts
│ │ └── xmlui-orange-on-default.ts
│ └── tsconfig.json
├── LICENSE
├── package-lock.json
├── package.json
├── packages
│ ├── tsconfig.json
│ ├── xmlui-animations
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── Animation.tsx
│ │ ├── AnimationNative.tsx
│ │ ├── FadeAnimation.tsx
│ │ ├── FadeInAnimation.tsx
│ │ ├── FadeOutAnimation.tsx
│ │ ├── index.tsx
│ │ ├── ScaleAnimation.tsx
│ │ └── SlideInAnimation.tsx
│ ├── xmlui-devtools
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ ├── src
│ │ │ ├── devtools
│ │ │ │ ├── DevTools.tsx
│ │ │ │ ├── DevToolsNative.module.scss
│ │ │ │ ├── DevToolsNative.tsx
│ │ │ │ ├── ModalDialog.module.scss
│ │ │ │ ├── ModalDialog.tsx
│ │ │ │ ├── ModalVisibilityContext.tsx
│ │ │ │ ├── Tooltip.module.scss
│ │ │ │ ├── Tooltip.tsx
│ │ │ │ └── utils.ts
│ │ │ ├── editor
│ │ │ │ └── Editor.tsx
│ │ │ └── index.tsx
│ │ └── vite.config-overrides.ts
│ ├── xmlui-hello-world
│ │ ├── .gitignore
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── HelloWorld.module.scss
│ │ ├── HelloWorld.tsx
│ │ ├── HelloWorldNative.tsx
│ │ └── index.tsx
│ ├── xmlui-os-frames
│ │ ├── .gitignore
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── index.tsx
│ │ ├── IPhoneFrame.module.scss
│ │ ├── IPhoneFrame.tsx
│ │ ├── MacOSAppFrame.module.scss
│ │ ├── MacOSAppFrame.tsx
│ │ ├── WindowsAppFrame.module.scss
│ │ └── WindowsAppFrame.tsx
│ ├── xmlui-pdf
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── demo
│ │ │ ├── components
│ │ │ │ └── Pdf.xmlui
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── index.tsx
│ │ ├── LazyPdfNative.tsx
│ │ ├── Pdf.module.scss
│ │ └── Pdf.tsx
│ ├── xmlui-playground
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── hooks
│ │ │ ├── usePlayground.ts
│ │ │ └── useToast.ts
│ │ ├── index.tsx
│ │ ├── playground
│ │ │ ├── Box.module.scss
│ │ │ ├── Box.tsx
│ │ │ ├── CodeSelector.module.scss
│ │ │ ├── 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.tsx
│ │ │ ├── StandalonePlayground.tsx
│ │ │ ├── StandalonePlaygroundNative.module.scss
│ │ │ ├── StandalonePlaygroundNative.tsx
│ │ │ ├── ThemeSwitcher.module.scss
│ │ │ ├── ThemeSwitcher.tsx
│ │ │ └── utils.ts
│ │ ├── providers
│ │ │ ├── Toast.module.scss
│ │ │ └── ToastProvider.tsx
│ │ ├── state
│ │ │ └── store.ts
│ │ ├── themes
│ │ │ └── theme.ts
│ │ └── utils
│ │ └── helpers.ts
│ ├── xmlui-search
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── index.tsx
│ │ ├── Search.module.scss
│ │ └── Search.tsx
│ ├── xmlui-spreadsheet
│ │ ├── .gitignore
│ │ ├── demo
│ │ │ └── Main.xmlui
│ │ ├── index.html
│ │ ├── index.ts
│ │ ├── meta
│ │ │ └── componentsMetadata.ts
│ │ ├── package.json
│ │ └── src
│ │ ├── index.tsx
│ │ ├── Spreadsheet.tsx
│ │ └── SpreadsheetNative.tsx
│ └── xmlui-website-blocks
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── demo
│ │ ├── components
│ │ │ ├── HeroBackgroundBreakoutPage.xmlui
│ │ │ ├── HeroBackgroundsPage.xmlui
│ │ │ ├── HeroContentsPage.xmlui
│ │ │ ├── HeroTextAlignPage.xmlui
│ │ │ ├── HeroTextPage.xmlui
│ │ │ └── HeroTonesPage.xmlui
│ │ ├── Main.xmlui
│ │ └── themes
│ │ └── default.ts
│ ├── index.html
│ ├── index.ts
│ ├── meta
│ │ └── componentsMetadata.ts
│ ├── package.json
│ ├── public
│ │ └── resources
│ │ ├── building.jpg
│ │ └── xmlui-logo.svg
│ └── src
│ ├── Carousel
│ │ ├── Carousel.module.scss
│ │ ├── Carousel.tsx
│ │ ├── CarouselContext.tsx
│ │ └── CarouselNative.tsx
│ ├── FancyButton
│ │ ├── FancyButton.module.scss
│ │ ├── FancyButton.tsx
│ │ └── FancyButton.xmlui
│ ├── Hello
│ │ ├── Hello.tsx
│ │ ├── Hello.xmlui
│ │ └── Hello.xmlui.xs
│ ├── HeroSection
│ │ ├── HeroSection.module.scss
│ │ ├── HeroSection.spec.ts
│ │ ├── HeroSection.tsx
│ │ └── HeroSectionNative.tsx
│ ├── index.tsx
│ ├── ScrollToTop
│ │ ├── ScrollToTop.module.scss
│ │ ├── ScrollToTop.tsx
│ │ └── ScrollToTopNative.tsx
│ └── vite-env.d.ts
├── playwright.config.ts
├── README.md
├── tools
│ ├── codefence
│ │ └── xmlui-code-fence-docs.md
│ ├── create-app
│ │ ├── .gitignore
│ │ ├── CHANGELOG.md
│ │ ├── create-app.ts
│ │ ├── helpers
│ │ │ ├── copy.ts
│ │ │ ├── get-pkg-manager.ts
│ │ │ ├── git.ts
│ │ │ ├── install.ts
│ │ │ ├── is-folder-empty.ts
│ │ │ ├── is-writeable.ts
│ │ │ ├── make-dir.ts
│ │ │ └── validate-pkg.ts
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── templates
│ │ │ ├── default
│ │ │ │ └── ts
│ │ │ │ ├── gitignore
│ │ │ │ ├── index.html
│ │ │ │ ├── index.ts
│ │ │ │ ├── public
│ │ │ │ │ ├── mockServiceWorker.js
│ │ │ │ │ ├── resources
│ │ │ │ │ │ ├── favicon.ico
│ │ │ │ │ │ └── xmlui-logo.svg
│ │ │ │ │ └── serve.json
│ │ │ │ └── src
│ │ │ │ ├── components
│ │ │ │ │ ├── ApiAware.xmlui
│ │ │ │ │ ├── Home.xmlui
│ │ │ │ │ ├── IncButton.xmlui
│ │ │ │ │ └── PagePanel.xmlui
│ │ │ │ ├── config.ts
│ │ │ │ └── Main.xmlui
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ └── tsconfig.json
│ ├── create-xmlui-hello-world
│ │ ├── index.js
│ │ └── package.json
│ └── vscode
│ ├── .gitignore
│ ├── .vscode
│ │ ├── launch.json
│ │ └── tasks.json
│ ├── .vscodeignore
│ ├── build.sh
│ ├── CHANGELOG.md
│ ├── esbuild.js
│ ├── eslint.config.mjs
│ ├── formatter-docs.md
│ ├── generate-test-sample.sh
│ ├── LICENSE.md
│ ├── package-lock.json
│ ├── package.json
│ ├── README.md
│ ├── resources
│ │ ├── xmlui-logo.png
│ │ └── xmlui-markup-syntax-highlighting.png
│ ├── src
│ │ ├── extension.ts
│ │ └── server.ts
│ ├── syntaxes
│ │ └── xmlui.tmLanguage.json
│ ├── test-samples
│ │ └── sample.xmlui
│ ├── tsconfig.json
│ └── tsconfig.tsbuildinfo
├── turbo.json
└── xmlui
├── .gitignore
├── bin
│ ├── bootstrap.cjs
│ ├── bootstrap.js
│ ├── build-lib.ts
│ ├── build.ts
│ ├── index.ts
│ ├── preview.ts
│ ├── start.ts
│ ├── vite-xmlui-plugin.ts
│ └── viteConfig.ts
├── CHANGELOG.md
├── conventions
│ ├── component-qa-checklist.md
│ ├── copilot-conventions.md
│ ├── create-xmlui-components.md
│ ├── mermaid.md
│ ├── testing-conventions.md
│ └── xmlui-in-a-nutshell.md
├── dev-docs
│ ├── accessibility.md
│ ├── build-system.md
│ ├── build-xmlui.md
│ ├── component-behaviors.md
│ ├── component-metadata.md
│ ├── components-with-options.md
│ ├── containers.md
│ ├── data-operations.md
│ ├── glossary.md
│ ├── index.md
│ ├── next
│ │ ├── component-dev-guide.md
│ │ ├── configuration-management-enhancement-summary.md
│ │ ├── documentation-scripts-refactoring-complete-summary.md
│ │ ├── documentation-scripts-refactoring-plan.md
│ │ ├── duplicate-pattern-extraction-summary.md
│ │ ├── error-handling-standardization-summary.md
│ │ ├── generating-component-reference.md
│ │ ├── index.md
│ │ ├── logging-consistency-implementation-summary.md
│ │ ├── project-build.md
│ │ ├── project-structure.md
│ │ ├── theme-context.md
│ │ ├── tiptap-design-considerations.md
│ │ ├── working-with-code.md
│ │ ├── xmlui-runtime-architecture
│ │ └── xmlui-wcag-accessibility-report.md
│ ├── react-fundamentals.md
│ ├── release-method.md
│ ├── standalone-app.md
│ ├── theme-variables-refactoring.md
│ ├── ud-components.md
│ └── xmlui-repo.md
├── package.json
├── scripts
│ ├── coverage-only.js
│ ├── e2e-test-summary.js
│ ├── extract-component-metadata.js
│ ├── generate-docs
│ │ ├── build-downloads-map.mjs
│ │ ├── build-pages-map.mjs
│ │ ├── components-config.json
│ │ ├── configuration-management.mjs
│ │ ├── constants.mjs
│ │ ├── create-theme-files.mjs
│ │ ├── DocsGenerator.mjs
│ │ ├── error-handling.mjs
│ │ ├── extensions-config.json
│ │ ├── folders.mjs
│ │ ├── generate-summary-files.mjs
│ │ ├── get-docs.mjs
│ │ ├── input-handler.mjs
│ │ ├── logger.mjs
│ │ ├── logging-standards.mjs
│ │ ├── MetadataProcessor.mjs
│ │ ├── pattern-utilities.mjs
│ │ └── utils.mjs
│ ├── generate-metadata-markdown.js
│ ├── get-langserver-metadata.js
│ ├── inline-links.mjs
│ └── README-e2e-summary.md
├── src
│ ├── abstractions
│ │ ├── _conventions.md
│ │ ├── ActionDefs.ts
│ │ ├── AppContextDefs.ts
│ │ ├── ComponentDefs.ts
│ │ ├── ContainerDefs.ts
│ │ ├── ExtensionDefs.ts
│ │ ├── FunctionDefs.ts
│ │ ├── RendererDefs.ts
│ │ ├── scripting
│ │ │ ├── BlockScope.ts
│ │ │ ├── Compilation.ts
│ │ │ ├── LogicalThread.ts
│ │ │ ├── LoopScope.ts
│ │ │ ├── modules.ts
│ │ │ ├── ScriptParserError.ts
│ │ │ ├── Token.ts
│ │ │ ├── TryScope.ts
│ │ │ └── TryScopeExp.ts
│ │ └── ThemingDefs.ts
│ ├── components
│ │ ├── _conventions.md
│ │ ├── abstractions.ts
│ │ ├── Accordion
│ │ │ ├── Accordion.md
│ │ │ ├── Accordion.module.scss
│ │ │ ├── Accordion.spec.ts
│ │ │ ├── Accordion.tsx
│ │ │ ├── AccordionContext.tsx
│ │ │ ├── AccordionItem.tsx
│ │ │ ├── AccordionItemNative.tsx
│ │ │ └── AccordionNative.tsx
│ │ ├── Animation
│ │ │ └── AnimationNative.tsx
│ │ ├── APICall
│ │ │ ├── APICall.md
│ │ │ ├── APICall.spec.ts
│ │ │ ├── APICall.tsx
│ │ │ └── APICallNative.tsx
│ │ ├── App
│ │ │ ├── App.md
│ │ │ ├── App.module.scss
│ │ │ ├── App.spec.ts
│ │ │ ├── App.tsx
│ │ │ ├── AppLayoutContext.ts
│ │ │ ├── AppNative.tsx
│ │ │ ├── AppStateContext.ts
│ │ │ ├── doc-resources
│ │ │ │ ├── condensed-sticky.xmlui
│ │ │ │ ├── condensed.xmlui
│ │ │ │ ├── horizontal-sticky.xmlui
│ │ │ │ ├── horizontal.xmlui
│ │ │ │ ├── vertical-full-header.xmlui
│ │ │ │ ├── vertical-sticky.xmlui
│ │ │ │ └── vertical.xmlui
│ │ │ ├── IndexerContext.ts
│ │ │ ├── LinkInfoContext.ts
│ │ │ ├── SearchContext.tsx
│ │ │ ├── Sheet.module.scss
│ │ │ └── Sheet.tsx
│ │ ├── AppHeader
│ │ │ ├── AppHeader.md
│ │ │ ├── AppHeader.module.scss
│ │ │ ├── AppHeader.spec.ts
│ │ │ ├── AppHeader.tsx
│ │ │ └── AppHeaderNative.tsx
│ │ ├── AppState
│ │ │ ├── AppState.md
│ │ │ ├── AppState.spec.ts
│ │ │ ├── AppState.tsx
│ │ │ └── AppStateNative.tsx
│ │ ├── AutoComplete
│ │ │ ├── AutoComplete.md
│ │ │ ├── AutoComplete.module.scss
│ │ │ ├── AutoComplete.spec.ts
│ │ │ ├── AutoComplete.tsx
│ │ │ ├── AutoCompleteContext.tsx
│ │ │ └── AutoCompleteNative.tsx
│ │ ├── Avatar
│ │ │ ├── Avatar.md
│ │ │ ├── Avatar.module.scss
│ │ │ ├── Avatar.spec.ts
│ │ │ ├── Avatar.tsx
│ │ │ └── AvatarNative.tsx
│ │ ├── Backdrop
│ │ │ ├── Backdrop.md
│ │ │ ├── Backdrop.module.scss
│ │ │ ├── Backdrop.spec.ts
│ │ │ ├── Backdrop.tsx
│ │ │ └── BackdropNative.tsx
│ │ ├── Badge
│ │ │ ├── Badge.md
│ │ │ ├── Badge.module.scss
│ │ │ ├── Badge.spec.ts
│ │ │ ├── Badge.tsx
│ │ │ └── BadgeNative.tsx
│ │ ├── Bookmark
│ │ │ ├── Bookmark.md
│ │ │ ├── Bookmark.module.scss
│ │ │ ├── Bookmark.spec.ts
│ │ │ ├── Bookmark.tsx
│ │ │ └── BookmarkNative.tsx
│ │ ├── Breakout
│ │ │ ├── Breakout.module.scss
│ │ │ ├── Breakout.spec.ts
│ │ │ ├── Breakout.tsx
│ │ │ └── BreakoutNative.tsx
│ │ ├── Button
│ │ │ ├── Button-style.spec.ts
│ │ │ ├── Button.md
│ │ │ ├── Button.module.scss
│ │ │ ├── Button.spec.ts
│ │ │ ├── Button.tsx
│ │ │ └── ButtonNative.tsx
│ │ ├── Card
│ │ │ ├── Card.md
│ │ │ ├── Card.module.scss
│ │ │ ├── Card.spec.ts
│ │ │ ├── Card.tsx
│ │ │ └── CardNative.tsx
│ │ ├── Carousel
│ │ │ ├── Carousel.md
│ │ │ ├── Carousel.module.scss
│ │ │ ├── Carousel.spec.ts
│ │ │ ├── Carousel.tsx
│ │ │ ├── CarouselContext.tsx
│ │ │ ├── CarouselItem.tsx
│ │ │ ├── CarouselItemNative.tsx
│ │ │ └── CarouselNative.tsx
│ │ ├── ChangeListener
│ │ │ ├── ChangeListener.md
│ │ │ ├── ChangeListener.spec.ts
│ │ │ ├── ChangeListener.tsx
│ │ │ └── ChangeListenerNative.tsx
│ │ ├── chart-color-schemes.ts
│ │ ├── Charts
│ │ │ ├── AreaChart
│ │ │ │ ├── AreaChart.md
│ │ │ │ ├── AreaChart.spec.ts
│ │ │ │ ├── AreaChart.tsx
│ │ │ │ └── AreaChartNative.tsx
│ │ │ ├── BarChart
│ │ │ │ ├── BarChart.md
│ │ │ │ ├── BarChart.module.scss
│ │ │ │ ├── BarChart.spec.ts
│ │ │ │ ├── BarChart.tsx
│ │ │ │ └── BarChartNative.tsx
│ │ │ ├── DonutChart
│ │ │ │ ├── DonutChart.spec.ts
│ │ │ │ └── DonutChart.tsx
│ │ │ ├── LabelList
│ │ │ │ ├── LabelList.module.scss
│ │ │ │ ├── LabelList.spec.ts
│ │ │ │ ├── LabelList.tsx
│ │ │ │ └── LabelListNative.tsx
│ │ │ ├── Legend
│ │ │ │ ├── Legend.spec.ts
│ │ │ │ ├── Legend.tsx
│ │ │ │ └── LegendNative.tsx
│ │ │ ├── LineChart
│ │ │ │ ├── LineChart.md
│ │ │ │ ├── LineChart.module.scss
│ │ │ │ ├── LineChart.spec.ts
│ │ │ │ ├── LineChart.tsx
│ │ │ │ └── LineChartNative.tsx
│ │ │ ├── PieChart
│ │ │ │ ├── PieChart.md
│ │ │ │ ├── PieChart.spec.ts
│ │ │ │ ├── PieChart.tsx
│ │ │ │ ├── PieChartNative.module.scss
│ │ │ │ └── PieChartNative.tsx
│ │ │ ├── RadarChart
│ │ │ │ ├── RadarChart.md
│ │ │ │ ├── RadarChart.spec.ts
│ │ │ │ ├── RadarChart.tsx
│ │ │ │ └── RadarChartNative.tsx
│ │ │ ├── Tooltip
│ │ │ │ ├── TooltipContent.module.scss
│ │ │ │ ├── TooltipContent.spec.ts
│ │ │ │ └── TooltipContent.tsx
│ │ │ └── utils
│ │ │ ├── abstractions.ts
│ │ │ └── ChartProvider.tsx
│ │ ├── Checkbox
│ │ │ ├── Checkbox.md
│ │ │ ├── Checkbox.spec.ts
│ │ │ └── Checkbox.tsx
│ │ ├── CodeBlock
│ │ │ ├── CodeBlock.module.scss
│ │ │ ├── CodeBlock.spec.ts
│ │ │ ├── CodeBlock.tsx
│ │ │ ├── CodeBlockNative.tsx
│ │ │ └── highlight-code.ts
│ │ ├── collectedComponentMetadata.ts
│ │ ├── ColorPicker
│ │ │ ├── ColorPicker.md
│ │ │ ├── ColorPicker.module.scss
│ │ │ ├── ColorPicker.spec.ts
│ │ │ ├── ColorPicker.tsx
│ │ │ └── ColorPickerNative.tsx
│ │ ├── Column
│ │ │ ├── Column.md
│ │ │ ├── Column.tsx
│ │ │ ├── ColumnNative.tsx
│ │ │ ├── doc-resources
│ │ │ │ └── list-component-data.js
│ │ │ └── TableContext.tsx
│ │ ├── component-utils.ts
│ │ ├── ComponentProvider.tsx
│ │ ├── ComponentRegistryContext.tsx
│ │ ├── container-helpers.tsx
│ │ ├── ContentSeparator
│ │ │ ├── ContentSeparator.md
│ │ │ ├── ContentSeparator.module.scss
│ │ │ ├── ContentSeparator.spec.ts
│ │ │ ├── ContentSeparator.tsx
│ │ │ ├── ContentSeparatorNative.tsx
│ │ │ └── test-padding.xmlui
│ │ ├── DataSource
│ │ │ ├── DataSource.md
│ │ │ └── DataSource.tsx
│ │ ├── DateInput
│ │ │ ├── DateInput.md
│ │ │ ├── DateInput.module.scss
│ │ │ ├── DateInput.spec.ts
│ │ │ ├── DateInput.tsx
│ │ │ └── DateInputNative.tsx
│ │ ├── DatePicker
│ │ │ ├── DatePicker.md
│ │ │ ├── DatePicker.module.scss
│ │ │ ├── DatePicker.spec.ts
│ │ │ ├── DatePicker.tsx
│ │ │ └── DatePickerNative.tsx
│ │ ├── DropdownMenu
│ │ │ ├── DropdownMenu.md
│ │ │ ├── DropdownMenu.module.scss
│ │ │ ├── DropdownMenu.spec.ts
│ │ │ ├── DropdownMenu.tsx
│ │ │ ├── DropdownMenuNative.tsx
│ │ │ ├── MenuItem.md
│ │ │ └── SubMenuItem.md
│ │ ├── EmojiSelector
│ │ │ ├── EmojiSelector.md
│ │ │ ├── EmojiSelector.spec.ts
│ │ │ ├── EmojiSelector.tsx
│ │ │ └── EmojiSelectorNative.tsx
│ │ ├── ExpandableItem
│ │ │ ├── ExpandableItem.module.scss
│ │ │ ├── ExpandableItem.spec.ts
│ │ │ ├── ExpandableItem.tsx
│ │ │ └── ExpandableItemNative.tsx
│ │ ├── FileInput
│ │ │ ├── FileInput.md
│ │ │ ├── FileInput.module.scss
│ │ │ ├── FileInput.spec.ts
│ │ │ ├── FileInput.tsx
│ │ │ └── FileInputNative.tsx
│ │ ├── FileUploadDropZone
│ │ │ ├── FileUploadDropZone.md
│ │ │ ├── FileUploadDropZone.module.scss
│ │ │ ├── FileUploadDropZone.spec.ts
│ │ │ ├── FileUploadDropZone.tsx
│ │ │ └── FileUploadDropZoneNative.tsx
│ │ ├── FlowLayout
│ │ │ ├── FlowLayout.md
│ │ │ ├── FlowLayout.module.scss
│ │ │ ├── FlowLayout.spec.ts
│ │ │ ├── FlowLayout.spec.ts-snapshots
│ │ │ │ └── Edge-cases-boxShadow-is-not-clipped-1-non-smoke-darwin.png
│ │ │ ├── FlowLayout.tsx
│ │ │ └── FlowLayoutNative.tsx
│ │ ├── Footer
│ │ │ ├── Footer.md
│ │ │ ├── Footer.module.scss
│ │ │ ├── Footer.spec.ts
│ │ │ ├── Footer.tsx
│ │ │ └── FooterNative.tsx
│ │ ├── Form
│ │ │ ├── Form.md
│ │ │ ├── Form.module.scss
│ │ │ ├── Form.spec.ts
│ │ │ ├── Form.tsx
│ │ │ ├── formActions.ts
│ │ │ ├── FormContext.ts
│ │ │ └── FormNative.tsx
│ │ ├── FormItem
│ │ │ ├── FormItem.md
│ │ │ ├── FormItem.module.scss
│ │ │ ├── FormItem.spec.ts
│ │ │ ├── FormItem.tsx
│ │ │ ├── FormItemNative.tsx
│ │ │ ├── HelperText.module.scss
│ │ │ ├── HelperText.tsx
│ │ │ ├── ItemWithLabel.tsx
│ │ │ └── Validations.ts
│ │ ├── FormSection
│ │ │ ├── FormSection.md
│ │ │ ├── FormSection.ts
│ │ │ └── FormSection.xmlui
│ │ ├── Fragment
│ │ │ ├── Fragment.spec.ts
│ │ │ └── Fragment.tsx
│ │ ├── Heading
│ │ │ ├── abstractions.ts
│ │ │ ├── H1.md
│ │ │ ├── H1.spec.ts
│ │ │ ├── H2.md
│ │ │ ├── H2.spec.ts
│ │ │ ├── H3.md
│ │ │ ├── H3.spec.ts
│ │ │ ├── H4.md
│ │ │ ├── H4.spec.ts
│ │ │ ├── H5.md
│ │ │ ├── H5.spec.ts
│ │ │ ├── H6.md
│ │ │ ├── H6.spec.ts
│ │ │ ├── Heading.md
│ │ │ ├── Heading.module.scss
│ │ │ ├── Heading.spec.ts
│ │ │ ├── Heading.tsx
│ │ │ └── HeadingNative.tsx
│ │ ├── HoverCard
│ │ │ ├── HoverCard.tsx
│ │ │ └── HovercardNative.tsx
│ │ ├── HtmlTags
│ │ │ ├── HtmlTags.module.scss
│ │ │ ├── HtmlTags.spec.ts
│ │ │ └── HtmlTags.tsx
│ │ ├── Icon
│ │ │ ├── AdmonitionDanger.tsx
│ │ │ ├── AdmonitionInfo.tsx
│ │ │ ├── AdmonitionNote.tsx
│ │ │ ├── AdmonitionTip.tsx
│ │ │ ├── AdmonitionWarning.tsx
│ │ │ ├── ApiIcon.tsx
│ │ │ ├── ArrowDropDown.module.scss
│ │ │ ├── ArrowDropDown.tsx
│ │ │ ├── ArrowDropUp.module.scss
│ │ │ ├── ArrowDropUp.tsx
│ │ │ ├── ArrowLeft.module.scss
│ │ │ ├── ArrowLeft.tsx
│ │ │ ├── ArrowRight.module.scss
│ │ │ ├── ArrowRight.tsx
│ │ │ ├── Attach.tsx
│ │ │ ├── Binding.module.scss
│ │ │ ├── Binding.tsx
│ │ │ ├── BoardIcon.tsx
│ │ │ ├── BoxIcon.tsx
│ │ │ ├── CheckIcon.tsx
│ │ │ ├── ChevronDownIcon.tsx
│ │ │ ├── ChevronLeft.tsx
│ │ │ ├── ChevronRight.tsx
│ │ │ ├── ChevronUpIcon.tsx
│ │ │ ├── CodeFileIcon.tsx
│ │ │ ├── CodeSandbox.tsx
│ │ │ ├── CompactListIcon.tsx
│ │ │ ├── ContentCopyIcon.tsx
│ │ │ ├── DarkToLightIcon.tsx
│ │ │ ├── DatabaseIcon.module.scss
│ │ │ ├── DatabaseIcon.tsx
│ │ │ ├── DocFileIcon.tsx
│ │ │ ├── DocIcon.tsx
│ │ │ ├── DotMenuHorizontalIcon.tsx
│ │ │ ├── DotMenuIcon.tsx
│ │ │ ├── EmailIcon.tsx
│ │ │ ├── EmptyFolderIcon.tsx
│ │ │ ├── ErrorIcon.tsx
│ │ │ ├── ExpressionIcon.tsx
│ │ │ ├── FillPlusCricleIcon.tsx
│ │ │ ├── FilterIcon.tsx
│ │ │ ├── FolderIcon.tsx
│ │ │ ├── GlobeIcon.tsx
│ │ │ ├── HomeIcon.tsx
│ │ │ ├── HyperLinkIcon.tsx
│ │ │ ├── Icon.md
│ │ │ ├── Icon.module.scss
│ │ │ ├── Icon.spec.ts
│ │ │ ├── Icon.tsx
│ │ │ ├── IconNative.tsx
│ │ │ ├── ImageFileIcon.tsx
│ │ │ ├── Inspect.tsx
│ │ │ ├── LightToDark.tsx
│ │ │ ├── LinkIcon.tsx
│ │ │ ├── ListIcon.tsx
│ │ │ ├── LooseListIcon.tsx
│ │ │ ├── MoonIcon.tsx
│ │ │ ├── MoreOptionsIcon.tsx
│ │ │ ├── NoSortIcon.tsx
│ │ │ ├── PDFIcon.tsx
│ │ │ ├── PenIcon.tsx
│ │ │ ├── PhoneIcon.tsx
│ │ │ ├── PhotoIcon.tsx
│ │ │ ├── PlusIcon.tsx
│ │ │ ├── SearchIcon.tsx
│ │ │ ├── ShareIcon.tsx
│ │ │ ├── SortAscendingIcon.tsx
│ │ │ ├── SortDescendingIcon.tsx
│ │ │ ├── StarsIcon.tsx
│ │ │ ├── SunIcon.tsx
│ │ │ ├── svg
│ │ │ │ ├── admonition_danger.svg
│ │ │ │ ├── admonition_info.svg
│ │ │ │ ├── admonition_note.svg
│ │ │ │ ├── admonition_tip.svg
│ │ │ │ ├── admonition_warning.svg
│ │ │ │ ├── api.svg
│ │ │ │ ├── arrow-dropdown.svg
│ │ │ │ ├── arrow-left.svg
│ │ │ │ ├── arrow-right.svg
│ │ │ │ ├── arrow-up.svg
│ │ │ │ ├── attach.svg
│ │ │ │ ├── binding.svg
│ │ │ │ ├── box.svg
│ │ │ │ ├── bulb.svg
│ │ │ │ ├── code-file.svg
│ │ │ │ ├── code-sandbox.svg
│ │ │ │ ├── dark_to_light.svg
│ │ │ │ ├── database.svg
│ │ │ │ ├── doc.svg
│ │ │ │ ├── empty-folder.svg
│ │ │ │ ├── expression.svg
│ │ │ │ ├── eye-closed.svg
│ │ │ │ ├── eye-dark.svg
│ │ │ │ ├── eye.svg
│ │ │ │ ├── file-text.svg
│ │ │ │ ├── filter.svg
│ │ │ │ ├── folder.svg
│ │ │ │ ├── img.svg
│ │ │ │ ├── inspect.svg
│ │ │ │ ├── light_to_dark.svg
│ │ │ │ ├── moon.svg
│ │ │ │ ├── pdf.svg
│ │ │ │ ├── photo.svg
│ │ │ │ ├── share.svg
│ │ │ │ ├── stars.svg
│ │ │ │ ├── sun.svg
│ │ │ │ ├── trending-down.svg
│ │ │ │ ├── trending-level.svg
│ │ │ │ ├── trending-up.svg
│ │ │ │ ├── txt.svg
│ │ │ │ ├── unknown-file.svg
│ │ │ │ ├── unlink.svg
│ │ │ │ └── xls.svg
│ │ │ ├── TableDeleteColumnIcon.tsx
│ │ │ ├── TableDeleteRowIcon.tsx
│ │ │ ├── TableInsertColumnIcon.tsx
│ │ │ ├── TableInsertRowIcon.tsx
│ │ │ ├── TrashIcon.tsx
│ │ │ ├── TrendingDownIcon.tsx
│ │ │ ├── TrendingLevelIcon.tsx
│ │ │ ├── TrendingUpIcon.tsx
│ │ │ ├── TxtIcon.tsx
│ │ │ ├── UnknownFileIcon.tsx
│ │ │ ├── UnlinkIcon.tsx
│ │ │ ├── UserIcon.tsx
│ │ │ ├── WarningIcon.tsx
│ │ │ └── XlsIcon.tsx
│ │ ├── IconProvider.tsx
│ │ ├── IconRegistryContext.tsx
│ │ ├── IFrame
│ │ │ ├── IFrame.md
│ │ │ ├── IFrame.module.scss
│ │ │ ├── IFrame.spec.ts
│ │ │ ├── IFrame.tsx
│ │ │ └── IFrameNative.tsx
│ │ ├── Image
│ │ │ ├── Image.md
│ │ │ ├── Image.module.scss
│ │ │ ├── Image.spec.ts
│ │ │ ├── Image.tsx
│ │ │ └── ImageNative.tsx
│ │ ├── Input
│ │ │ ├── index.ts
│ │ │ ├── InputAdornment.module.scss
│ │ │ ├── InputAdornment.tsx
│ │ │ ├── InputDivider.module.scss
│ │ │ ├── InputDivider.tsx
│ │ │ ├── InputLabel.module.scss
│ │ │ ├── InputLabel.tsx
│ │ │ ├── PartialInput.module.scss
│ │ │ └── PartialInput.tsx
│ │ ├── InspectButton
│ │ │ ├── InspectButton.module.scss
│ │ │ └── InspectButton.tsx
│ │ ├── Items
│ │ │ ├── Items.md
│ │ │ ├── Items.spec.ts
│ │ │ ├── Items.tsx
│ │ │ └── ItemsNative.tsx
│ │ ├── Link
│ │ │ ├── Link.md
│ │ │ ├── Link.module.scss
│ │ │ ├── Link.spec.ts
│ │ │ ├── Link.tsx
│ │ │ └── LinkNative.tsx
│ │ ├── List
│ │ │ ├── doc-resources
│ │ │ │ └── list-component-data.js
│ │ │ ├── List.md
│ │ │ ├── List.module.scss
│ │ │ ├── List.spec.ts
│ │ │ ├── List.tsx
│ │ │ └── ListNative.tsx
│ │ ├── Logo
│ │ │ ├── doc-resources
│ │ │ │ └── xmlui-logo.svg
│ │ │ ├── Logo.md
│ │ │ ├── Logo.tsx
│ │ │ └── LogoNative.tsx
│ │ ├── Markdown
│ │ │ ├── CodeText.module.scss
│ │ │ ├── CodeText.tsx
│ │ │ ├── Markdown.md
│ │ │ ├── Markdown.module.scss
│ │ │ ├── Markdown.spec.ts
│ │ │ ├── Markdown.tsx
│ │ │ ├── MarkdownNative.tsx
│ │ │ ├── parse-binding-expr.ts
│ │ │ └── utils.ts
│ │ ├── metadata-helpers.ts
│ │ ├── ModalDialog
│ │ │ ├── ConfirmationModalContextProvider.tsx
│ │ │ ├── Dialog.module.scss
│ │ │ ├── Dialog.tsx
│ │ │ ├── ModalDialog.md
│ │ │ ├── ModalDialog.module.scss
│ │ │ ├── ModalDialog.spec.ts
│ │ │ ├── ModalDialog.tsx
│ │ │ ├── ModalDialogNative.tsx
│ │ │ └── ModalVisibilityContext.tsx
│ │ ├── NavGroup
│ │ │ ├── NavGroup.md
│ │ │ ├── NavGroup.module.scss
│ │ │ ├── NavGroup.spec.ts
│ │ │ ├── NavGroup.tsx
│ │ │ ├── NavGroupContext.ts
│ │ │ └── NavGroupNative.tsx
│ │ ├── NavLink
│ │ │ ├── NavLink.md
│ │ │ ├── NavLink.module.scss
│ │ │ ├── NavLink.spec.ts
│ │ │ ├── NavLink.tsx
│ │ │ └── NavLinkNative.tsx
│ │ ├── NavPanel
│ │ │ ├── NavPanel.md
│ │ │ ├── NavPanel.module.scss
│ │ │ ├── NavPanel.spec.ts
│ │ │ ├── NavPanel.tsx
│ │ │ └── NavPanelNative.tsx
│ │ ├── NestedApp
│ │ │ ├── AppWithCodeView.module.scss
│ │ │ ├── AppWithCodeView.tsx
│ │ │ ├── AppWithCodeViewNative.tsx
│ │ │ ├── defaultProps.tsx
│ │ │ ├── logo.svg
│ │ │ ├── NestedApp.module.scss
│ │ │ ├── NestedApp.tsx
│ │ │ ├── NestedAppNative.tsx
│ │ │ ├── Tooltip.module.scss
│ │ │ ├── Tooltip.tsx
│ │ │ └── utils.ts
│ │ ├── NoResult
│ │ │ ├── NoResult.md
│ │ │ ├── NoResult.module.scss
│ │ │ ├── NoResult.spec.ts
│ │ │ ├── NoResult.tsx
│ │ │ └── NoResultNative.tsx
│ │ ├── NumberBox
│ │ │ ├── numberbox-abstractions.ts
│ │ │ ├── NumberBox.md
│ │ │ ├── NumberBox.module.scss
│ │ │ ├── NumberBox.spec.ts
│ │ │ ├── NumberBox.tsx
│ │ │ └── NumberBoxNative.tsx
│ │ ├── Option
│ │ │ ├── Option.md
│ │ │ ├── Option.spec.ts
│ │ │ ├── Option.tsx
│ │ │ ├── OptionNative.tsx
│ │ │ └── OptionTypeProvider.tsx
│ │ ├── PageMetaTitle
│ │ │ ├── PageMetaTilteNative.tsx
│ │ │ ├── PageMetaTitle.md
│ │ │ ├── PageMetaTitle.spec.ts
│ │ │ └── PageMetaTitle.tsx
│ │ ├── Pages
│ │ │ ├── Page.md
│ │ │ ├── Pages.md
│ │ │ ├── Pages.module.scss
│ │ │ ├── Pages.tsx
│ │ │ └── PagesNative.tsx
│ │ ├── Pagination
│ │ │ ├── Pagination.md
│ │ │ ├── Pagination.module.scss
│ │ │ ├── Pagination.spec.ts
│ │ │ ├── Pagination.tsx
│ │ │ └── PaginationNative.tsx
│ │ ├── PositionedContainer
│ │ │ ├── PositionedContainer.module.scss
│ │ │ ├── PositionedContainer.tsx
│ │ │ └── PositionedContainerNative.tsx
│ │ ├── ProfileMenu
│ │ │ ├── ProfileMenu.module.scss
│ │ │ └── ProfileMenu.tsx
│ │ ├── ProgressBar
│ │ │ ├── ProgressBar.md
│ │ │ ├── ProgressBar.module.scss
│ │ │ ├── ProgressBar.spec.ts
│ │ │ ├── ProgressBar.tsx
│ │ │ └── ProgressBarNative.tsx
│ │ ├── Queue
│ │ │ ├── Queue.md
│ │ │ ├── Queue.spec.ts
│ │ │ ├── Queue.tsx
│ │ │ ├── queueActions.ts
│ │ │ └── QueueNative.tsx
│ │ ├── RadioGroup
│ │ │ ├── RadioGroup.md
│ │ │ ├── RadioGroup.module.scss
│ │ │ ├── RadioGroup.spec.ts
│ │ │ ├── RadioGroup.tsx
│ │ │ ├── RadioGroupNative.tsx
│ │ │ ├── RadioItem.tsx
│ │ │ └── RadioItemNative.tsx
│ │ ├── RealTimeAdapter
│ │ │ ├── RealTimeAdapter.tsx
│ │ │ └── RealTimeAdapterNative.tsx
│ │ ├── Redirect
│ │ │ ├── Redirect.md
│ │ │ ├── Redirect.spec.ts
│ │ │ └── Redirect.tsx
│ │ ├── ResponsiveBar
│ │ │ ├── README.md
│ │ │ ├── ResponsiveBar.md
│ │ │ ├── ResponsiveBar.module.scss
│ │ │ ├── ResponsiveBar.spec.ts
│ │ │ ├── ResponsiveBar.tsx
│ │ │ └── ResponsiveBarNative.tsx
│ │ ├── Select
│ │ │ ├── HiddenOption.tsx
│ │ │ ├── OptionContext.ts
│ │ │ ├── Select.md
│ │ │ ├── Select.module.scss
│ │ │ ├── Select.spec.ts
│ │ │ ├── Select.tsx
│ │ │ ├── SelectContext.tsx
│ │ │ └── SelectNative.tsx
│ │ ├── SelectionStore
│ │ │ ├── SelectionStore.md
│ │ │ ├── SelectionStore.tsx
│ │ │ └── SelectionStoreNative.tsx
│ │ ├── Slider
│ │ │ ├── Slider.md
│ │ │ ├── Slider.module.scss
│ │ │ ├── Slider.spec.ts
│ │ │ ├── Slider.tsx
│ │ │ └── SliderNative.tsx
│ │ ├── Slot
│ │ │ ├── Slot.md
│ │ │ ├── Slot.spec.ts
│ │ │ └── Slot.ts
│ │ ├── SlotItem.tsx
│ │ ├── SpaceFiller
│ │ │ ├── SpaceFiller.md
│ │ │ ├── SpaceFiller.module.scss
│ │ │ ├── SpaceFiller.spec.ts
│ │ │ ├── SpaceFiller.tsx
│ │ │ └── SpaceFillerNative.tsx
│ │ ├── Spinner
│ │ │ ├── Spinner.md
│ │ │ ├── Spinner.module.scss
│ │ │ ├── Spinner.spec.ts
│ │ │ ├── Spinner.tsx
│ │ │ └── SpinnerNative.tsx
│ │ ├── Splitter
│ │ │ ├── HSplitter.md
│ │ │ ├── HSplitter.spec.ts
│ │ │ ├── Splitter.md
│ │ │ ├── Splitter.module.scss
│ │ │ ├── Splitter.spec.ts
│ │ │ ├── Splitter.tsx
│ │ │ ├── SplitterNative.tsx
│ │ │ ├── utils.ts
│ │ │ ├── VSplitter.md
│ │ │ └── VSplitter.spec.ts
│ │ ├── Stack
│ │ │ ├── CHStack.md
│ │ │ ├── CHStack.spec.ts
│ │ │ ├── CVStack.md
│ │ │ ├── CVStack.spec.ts
│ │ │ ├── HStack.md
│ │ │ ├── HStack.spec.ts
│ │ │ ├── Stack.md
│ │ │ ├── Stack.module.scss
│ │ │ ├── Stack.spec.ts
│ │ │ ├── Stack.tsx
│ │ │ ├── StackNative.tsx
│ │ │ ├── VStack.md
│ │ │ └── VStack.spec.ts
│ │ ├── StickyBox
│ │ │ ├── StickyBox.md
│ │ │ ├── StickyBox.module.scss
│ │ │ ├── StickyBox.tsx
│ │ │ └── StickyBoxNative.tsx
│ │ ├── Switch
│ │ │ ├── Switch.md
│ │ │ ├── Switch.spec.ts
│ │ │ └── Switch.tsx
│ │ ├── Table
│ │ │ ├── doc-resources
│ │ │ │ └── list-component-data.js
│ │ │ ├── react-table-config.d.ts
│ │ │ ├── Table.md
│ │ │ ├── Table.module.scss
│ │ │ ├── Table.spec.ts
│ │ │ ├── Table.tsx
│ │ │ ├── TableNative.tsx
│ │ │ └── useRowSelection.tsx
│ │ ├── TableOfContents
│ │ │ ├── TableOfContents.module.scss
│ │ │ ├── TableOfContents.spec.ts
│ │ │ ├── TableOfContents.tsx
│ │ │ └── TableOfContentsNative.tsx
│ │ ├── Tabs
│ │ │ ├── TabContext.tsx
│ │ │ ├── TabItem.md
│ │ │ ├── TabItem.tsx
│ │ │ ├── TabItemNative.tsx
│ │ │ ├── Tabs.md
│ │ │ ├── Tabs.module.scss
│ │ │ ├── Tabs.spec.ts
│ │ │ ├── Tabs.tsx
│ │ │ └── TabsNative.tsx
│ │ ├── Text
│ │ │ ├── Text.md
│ │ │ ├── Text.module.scss
│ │ │ ├── Text.spec.ts
│ │ │ ├── Text.tsx
│ │ │ └── TextNative.tsx
│ │ ├── TextArea
│ │ │ ├── TextArea.md
│ │ │ ├── TextArea.module.scss
│ │ │ ├── TextArea.spec.ts
│ │ │ ├── TextArea.tsx
│ │ │ ├── TextAreaNative.tsx
│ │ │ ├── TextAreaResizable.tsx
│ │ │ └── useComposedRef.ts
│ │ ├── TextBox
│ │ │ ├── TextBox.md
│ │ │ ├── TextBox.module.scss
│ │ │ ├── TextBox.spec.ts
│ │ │ ├── TextBox.tsx
│ │ │ └── TextBoxNative.tsx
│ │ ├── Theme
│ │ │ ├── NotificationToast.tsx
│ │ │ ├── Theme.md
│ │ │ ├── Theme.module.scss
│ │ │ ├── Theme.spec.ts
│ │ │ ├── Theme.tsx
│ │ │ └── ThemeNative.tsx
│ │ ├── TimeInput
│ │ │ ├── TimeInput.md
│ │ │ ├── TimeInput.module.scss
│ │ │ ├── TimeInput.spec.ts
│ │ │ ├── TimeInput.tsx
│ │ │ ├── TimeInputNative.tsx
│ │ │ └── utils.ts
│ │ ├── Timer
│ │ │ ├── Timer.md
│ │ │ ├── Timer.spec.ts
│ │ │ ├── Timer.tsx
│ │ │ └── TimerNative.tsx
│ │ ├── Toggle
│ │ │ ├── Toggle.module.scss
│ │ │ └── Toggle.tsx
│ │ ├── ToneChangerButton
│ │ │ ├── ToneChangerButton.md
│ │ │ ├── ToneChangerButton.spec.ts
│ │ │ └── ToneChangerButton.tsx
│ │ ├── ToneSwitch
│ │ │ ├── ToneSwitch.md
│ │ │ ├── ToneSwitch.module.scss
│ │ │ ├── ToneSwitch.spec.ts
│ │ │ ├── ToneSwitch.tsx
│ │ │ └── ToneSwitchNative.tsx
│ │ ├── Tooltip
│ │ │ ├── Tooltip.md
│ │ │ ├── Tooltip.module.scss
│ │ │ ├── Tooltip.spec.ts
│ │ │ ├── Tooltip.tsx
│ │ │ └── TooltipNative.tsx
│ │ ├── Tree
│ │ │ ├── testData.ts
│ │ │ ├── Tree-dynamic.spec.ts
│ │ │ ├── Tree-icons.spec.ts
│ │ │ ├── Tree.md
│ │ │ ├── Tree.spec.ts
│ │ │ ├── TreeComponent.module.scss
│ │ │ ├── TreeComponent.tsx
│ │ │ └── TreeNative.tsx
│ │ ├── TreeDisplay
│ │ │ ├── TreeDisplay.md
│ │ │ ├── TreeDisplay.module.scss
│ │ │ ├── TreeDisplay.tsx
│ │ │ └── TreeDisplayNative.tsx
│ │ ├── ValidationSummary
│ │ │ ├── ValidationSummary.module.scss
│ │ │ └── ValidationSummary.tsx
│ │ └── VisuallyHidden.tsx
│ ├── components-core
│ │ ├── abstractions
│ │ │ ├── ComponentRenderer.ts
│ │ │ ├── LoaderRenderer.ts
│ │ │ ├── standalone.ts
│ │ │ └── treeAbstractions.ts
│ │ ├── action
│ │ │ ├── actions.ts
│ │ │ ├── APICall.tsx
│ │ │ ├── FileDownloadAction.tsx
│ │ │ ├── FileUploadAction.tsx
│ │ │ ├── NavigateAction.tsx
│ │ │ └── TimedAction.tsx
│ │ ├── ApiBoundComponent.tsx
│ │ ├── appContext
│ │ │ ├── date-functions.ts
│ │ │ ├── math-function.ts
│ │ │ └── misc-utils.ts
│ │ ├── AppContext.tsx
│ │ ├── behaviors
│ │ │ ├── Behavior.tsx
│ │ │ └── CoreBehaviors.tsx
│ │ ├── component-hooks.ts
│ │ ├── ComponentDecorator.tsx
│ │ ├── ComponentViewer.tsx
│ │ ├── CompoundComponent.tsx
│ │ ├── constants.ts
│ │ ├── DebugViewProvider.tsx
│ │ ├── descriptorHelper.ts
│ │ ├── devtools
│ │ │ ├── InspectorDialog.module.scss
│ │ │ ├── InspectorDialog.tsx
│ │ │ └── InspectorDialogVisibilityContext.tsx
│ │ ├── EngineError.ts
│ │ ├── event-handlers.ts
│ │ ├── InspectorButton.module.scss
│ │ ├── InspectorContext.tsx
│ │ ├── interception
│ │ │ ├── abstractions.ts
│ │ │ ├── ApiInterceptor.ts
│ │ │ ├── ApiInterceptorProvider.tsx
│ │ │ ├── apiInterceptorWorker.ts
│ │ │ ├── Backend.ts
│ │ │ ├── Errors.ts
│ │ │ ├── IndexedDb.ts
│ │ │ ├── initMock.ts
│ │ │ ├── InMemoryDb.ts
│ │ │ ├── ReadonlyCollection.ts
│ │ │ └── useApiInterceptorContext.tsx
│ │ ├── loader
│ │ │ ├── ApiLoader.tsx
│ │ │ ├── DataLoader.tsx
│ │ │ ├── ExternalDataLoader.tsx
│ │ │ ├── Loader.tsx
│ │ │ ├── MockLoaderRenderer.tsx
│ │ │ └── PageableLoader.tsx
│ │ ├── LoaderComponent.tsx
│ │ ├── markup-check.ts
│ │ ├── parts.ts
│ │ ├── renderers.ts
│ │ ├── rendering
│ │ │ ├── AppContent.tsx
│ │ │ ├── AppRoot.tsx
│ │ │ ├── AppWrapper.tsx
│ │ │ ├── buildProxy.ts
│ │ │ ├── collectFnVarDeps.ts
│ │ │ ├── ComponentAdapter.tsx
│ │ │ ├── ComponentWrapper.tsx
│ │ │ ├── Container.tsx
│ │ │ ├── containers.ts
│ │ │ ├── ContainerWrapper.tsx
│ │ │ ├── ErrorBoundary.module.scss
│ │ │ ├── ErrorBoundary.tsx
│ │ │ ├── InvalidComponent.module.scss
│ │ │ ├── InvalidComponent.tsx
│ │ │ ├── nodeUtils.ts
│ │ │ ├── reducer.ts
│ │ │ ├── renderChild.tsx
│ │ │ ├── StandaloneComponent.tsx
│ │ │ ├── StateContainer.tsx
│ │ │ ├── UnknownComponent.module.scss
│ │ │ ├── UnknownComponent.tsx
│ │ │ └── valueExtractor.ts
│ │ ├── reportEngineError.ts
│ │ ├── RestApiProxy.ts
│ │ ├── script-runner
│ │ │ ├── asyncProxy.ts
│ │ │ ├── AttributeValueParser.ts
│ │ │ ├── bannedFunctions.ts
│ │ │ ├── BindingTreeEvaluationContext.ts
│ │ │ ├── eval-tree-async.ts
│ │ │ ├── eval-tree-common.ts
│ │ │ ├── eval-tree-sync.ts
│ │ │ ├── ParameterParser.ts
│ │ │ ├── process-statement-async.ts
│ │ │ ├── process-statement-common.ts
│ │ │ ├── process-statement-sync.ts
│ │ │ ├── ScriptingSourceTree.ts
│ │ │ ├── simplify-expression.ts
│ │ │ ├── statement-queue.ts
│ │ │ └── visitors.ts
│ │ ├── StandaloneApp.tsx
│ │ ├── StandaloneExtensionManager.ts
│ │ ├── TableOfContentsContext.tsx
│ │ ├── theming
│ │ │ ├── _themes.scss
│ │ │ ├── component-layout-resolver.ts
│ │ │ ├── extendThemeUtils.ts
│ │ │ ├── hvar.ts
│ │ │ ├── layout-resolver.ts
│ │ │ ├── parse-layout-props.ts
│ │ │ ├── StyleContext.tsx
│ │ │ ├── StyleRegistry.ts
│ │ │ ├── ThemeContext.tsx
│ │ │ ├── ThemeProvider.tsx
│ │ │ ├── themes
│ │ │ │ ├── base-utils.ts
│ │ │ │ ├── palette.ts
│ │ │ │ ├── root.ts
│ │ │ │ ├── solid.ts
│ │ │ │ ├── theme-colors.ts
│ │ │ │ └── xmlui.ts
│ │ │ ├── themeVars.module.scss
│ │ │ ├── themeVars.ts
│ │ │ ├── transformThemeVars.ts
│ │ │ └── utils.ts
│ │ ├── utils
│ │ │ ├── actionUtils.ts
│ │ │ ├── audio-utils.ts
│ │ │ ├── base64-utils.ts
│ │ │ ├── compound-utils.ts
│ │ │ ├── css-utils.ts
│ │ │ ├── DataLoaderQueryKeyGenerator.ts
│ │ │ ├── date-utils.ts
│ │ │ ├── extractParam.ts
│ │ │ ├── hooks.tsx
│ │ │ ├── LruCache.ts
│ │ │ ├── mergeProps.ts
│ │ │ ├── misc.ts
│ │ │ ├── request-params.ts
│ │ │ ├── statementUtils.ts
│ │ │ └── treeUtils.ts
│ │ └── xmlui-parser.ts
│ ├── index-standalone.ts
│ ├── index.scss
│ ├── index.ts
│ ├── language-server
│ │ ├── server-common.ts
│ │ ├── server-web-worker.ts
│ │ ├── server.ts
│ │ ├── services
│ │ │ ├── common
│ │ │ │ ├── docs-generation.ts
│ │ │ │ ├── lsp-utils.ts
│ │ │ │ ├── metadata-utils.ts
│ │ │ │ └── syntax-node-utilities.ts
│ │ │ ├── completion.ts
│ │ │ ├── diagnostic.ts
│ │ │ ├── format.ts
│ │ │ └── hover.ts
│ │ └── xmlui-metadata-generated.js
│ ├── logging
│ │ ├── LoggerContext.tsx
│ │ ├── LoggerInitializer.tsx
│ │ ├── LoggerService.ts
│ │ └── xmlui.ts
│ ├── logo.svg
│ ├── parsers
│ │ ├── common
│ │ │ ├── GenericToken.ts
│ │ │ ├── InputStream.ts
│ │ │ └── utils.ts
│ │ ├── scripting
│ │ │ ├── code-behind-collect.ts
│ │ │ ├── Lexer.ts
│ │ │ ├── modules.ts
│ │ │ ├── Parser.ts
│ │ │ ├── ParserError.ts
│ │ │ ├── ScriptingNodeTypes.ts
│ │ │ ├── TokenTrait.ts
│ │ │ ├── TokenType.ts
│ │ │ └── tree-visitor.ts
│ │ ├── style-parser
│ │ │ ├── errors.ts
│ │ │ ├── source-tree.ts
│ │ │ ├── StyleInputStream.ts
│ │ │ ├── StyleLexer.ts
│ │ │ ├── StyleParser.ts
│ │ │ └── tokens.ts
│ │ └── xmlui-parser
│ │ ├── CharacterCodes.ts
│ │ ├── diagnostics.ts
│ │ ├── fileExtensions.ts
│ │ ├── index.ts
│ │ ├── lint.ts
│ │ ├── parser.ts
│ │ ├── ParserError.ts
│ │ ├── scanner.ts
│ │ ├── syntax-kind.ts
│ │ ├── syntax-node.ts
│ │ ├── transform.ts
│ │ ├── utils.ts
│ │ ├── xmlui-serializer.ts
│ │ └── xmlui-tree.ts
│ ├── react-app-env.d.ts
│ ├── syntax
│ │ ├── monaco
│ │ │ ├── grammar.monacoLanguage.ts
│ │ │ ├── index.ts
│ │ │ ├── xmlui-dark.ts
│ │ │ ├── xmlui-light.ts
│ │ │ └── xmluiscript.monacoLanguage.ts
│ │ └── textMate
│ │ ├── index.ts
│ │ ├── xmlui-dark.json
│ │ ├── xmlui-light.json
│ │ ├── xmlui.json
│ │ └── xmlui.tmLanguage.json
│ ├── testing
│ │ ├── assertions.ts
│ │ ├── component-test-helpers.ts
│ │ ├── ComponentDrivers.ts
│ │ ├── drivers
│ │ │ ├── DateInputDriver.ts
│ │ │ ├── index.ts
│ │ │ ├── ModalDialogDriver.ts
│ │ │ ├── NumberBoxDriver.ts
│ │ │ ├── TextBoxDriver.ts
│ │ │ ├── TimeInputDriver.ts
│ │ │ ├── TimerDriver.ts
│ │ │ └── TreeDriver.ts
│ │ ├── fixtures.ts
│ │ ├── index.ts
│ │ └── infrastructure
│ │ ├── index.html
│ │ ├── main.tsx
│ │ ├── public
│ │ │ ├── mockServiceWorker.js
│ │ │ ├── resources
│ │ │ │ ├── bell.svg
│ │ │ │ ├── box.svg
│ │ │ │ ├── doc.svg
│ │ │ │ ├── eye.svg
│ │ │ │ ├── flower-640x480.jpg
│ │ │ │ ├── sun.svg
│ │ │ │ ├── test-image-100x100.jpg
│ │ │ │ └── txt.svg
│ │ │ └── serve.json
│ │ └── TestBed.tsx
│ └── 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.json
├── tsdown.config.ts
├── vite.config.ts
└── vitest.config.ts
```
# Files
--------------------------------------------------------------------------------
/xmlui/src/components/NumberBox/NumberBoxNative.tsx:
--------------------------------------------------------------------------------
```typescript
1 | import React, {
2 | type CSSProperties,
3 | type ForwardedRef,
4 | forwardRef,
5 | useCallback,
6 | useEffect,
7 | useId,
8 | useRef,
9 | } from "react";
10 | import classnames from "classnames";
11 |
12 | import styles from "./NumberBox.module.scss";
13 |
14 | import type { RegisterComponentApiFn, UpdateStateFn } from "../../abstractions/RendererDefs";
15 | import { noop } from "../../components-core/constants";
16 | import { useEvent } from "../../components-core/utils/misc";
17 | import {
18 | clamp,
19 | DECIMAL_SEPARATOR,
20 | DEFAULT_STEP,
21 | EXPONENTIAL_SEPARATOR,
22 | FLOAT_REGEXP,
23 | INT_REGEXP,
24 | isEmptyLike,
25 | mapToRepresentation,
26 | NUMBERBOX_MAX_VALUE,
27 | toUsableNumber,
28 | } from "./numberbox-abstractions";
29 | import { type ValidationStatus } from "../abstractions";
30 | import { Icon } from "../Icon/IconNative";
31 | import { Adornment } from "../Input/InputAdornment";
32 | import { Button } from "../Button/ButtonNative";
33 | import { PART_END_ADORNMENT, PART_INPUT, PART_START_ADORNMENT } from "../../components-core/parts";
34 |
35 | const PART_SPINNER_UP = "spinnerUp";
36 | const PART_SPINNER_DOWN = "spinnerDown";
37 |
38 | // Default props for NumberBox component
39 | export const defaultProps = {
40 | enabled: true,
41 | validationStatus: "none" as ValidationStatus,
42 | hasSpinBox: true,
43 | integersOnly: false,
44 | zeroOrPositive: false,
45 | min: -NUMBERBOX_MAX_VALUE,
46 | max: NUMBERBOX_MAX_VALUE,
47 | step: 1,
48 | updateState: noop,
49 | onDidChange: noop,
50 | onFocus: noop,
51 | onBlur: noop,
52 | };
53 |
54 | // =====================================================================================================================
55 | // React NumberBox component definition
56 |
57 | type Props = {
58 | id?: string;
59 | value?: number | string | null;
60 | initialValue?: number | string | null;
61 | style?: CSSProperties;
62 | className?: string;
63 | step?: number | string;
64 | enabled?: boolean;
65 | placeholder?: string;
66 | hasSpinBox?: boolean;
67 | validationStatus?: ValidationStatus;
68 | min?: number;
69 | max?: number;
70 | maxLength?: number;
71 | integersOnly?: boolean;
72 | zeroOrPositive?: boolean;
73 | updateState?: UpdateStateFn;
74 | onDidChange?: (newValue: number | string | null | undefined) => void;
75 | onFocus?: () => void;
76 | onBlur?: () => void;
77 | registerComponentApi?: RegisterComponentApiFn;
78 | startText?: string;
79 | startIcon?: string;
80 | endText?: string;
81 | endIcon?: string;
82 | gap?: string;
83 | spinnerUpIcon?: string;
84 | spinnerDownIcon?: string;
85 | autoFocus?: boolean;
86 | readOnly?: boolean;
87 | required?: boolean;
88 | direction?: "ltr" | "rtl";
89 | };
90 |
91 | export const NumberBox = forwardRef(function NumberBox(
92 | {
93 | id,
94 | value,
95 | initialValue,
96 | style,
97 | className,
98 | enabled = defaultProps.enabled,
99 | placeholder,
100 | validationStatus = defaultProps.validationStatus,
101 | hasSpinBox = defaultProps.hasSpinBox,
102 | step = defaultProps.step,
103 | integersOnly = defaultProps.integersOnly,
104 | zeroOrPositive = defaultProps.zeroOrPositive,
105 | min = zeroOrPositive ? 0 : defaultProps.min,
106 | max = defaultProps.max,
107 | maxLength,
108 | updateState = defaultProps.updateState,
109 | onDidChange = defaultProps.onDidChange,
110 | onFocus = defaultProps.onFocus,
111 | onBlur = defaultProps.onBlur,
112 | registerComponentApi,
113 | startText,
114 | startIcon,
115 | endText,
116 | endIcon,
117 | gap,
118 | spinnerUpIcon,
119 | spinnerDownIcon,
120 | autoFocus,
121 | readOnly,
122 | required,
123 | direction,
124 | ...rest
125 | }: Props,
126 | forwardedRef: ForwardedRef<HTMLDivElement>,
127 | ) {
128 | const _id = useId();
129 | id = id || _id;
130 | // --- Ensure the provided value is a number or null
131 |
132 | // Ensure the provided minimum is not smaller than the 0 if zeroOrPositive is set to true
133 | min = Math.max(zeroOrPositive ? 0 : -NUMBERBOX_MAX_VALUE, min);
134 |
135 | // Step must be an integer since floating point arithmetic needs a deeper dive.
136 | // probably some way to integrate with https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat
137 | // since there are footguns, like 0.1 + 0.2 = 0.0000...04
138 | const _step = toUsableNumber(step, true) ?? DEFAULT_STEP;
139 |
140 | const inputRef = useRef<HTMLInputElement>(null);
141 | const upButton = useRef<HTMLButtonElement>(null);
142 | const downButton = useRef<HTMLButtonElement>(null);
143 |
144 | useEffect(() => {
145 | if (autoFocus) {
146 | setTimeout(() => {
147 | inputRef.current?.focus();
148 | }, 0);
149 | }
150 | }, [autoFocus]);
151 |
152 | // --- Convert to representable string value (from number | null | undefined)
153 | const [valueStrRep, setValueStrRep] = React.useState<string>(mapToRepresentation(value));
154 | useEffect(() => {
155 | setValueStrRep(mapToRepresentation(value));
156 | }, [value]);
157 |
158 | // --- Initialize the related field with the input's initial value
159 | useEffect(() => {
160 | updateState({ value: initialValue }, { initial: true });
161 | }, [initialValue, updateState]);
162 |
163 | // --- Handle the value change events for this input
164 | const updateValue = useCallback(
165 | (newValue: string | number | null | undefined, rep: string) => {
166 | setValueStrRep(rep);
167 | updateState({ value: newValue });
168 | onDidChange(newValue);
169 | },
170 | [onDidChange, updateState],
171 | );
172 |
173 | // --- Keypress
174 | const onInputChange = useCallback(
175 | (event: React.ChangeEvent<HTMLInputElement>) => {
176 | // const newValue = sanitizeInput(event.target.value.trim(), value, integersOnly, zeroOrPositive, min, max);
177 | // if (!newValue) return;
178 | // updateValue(newValue[0], newValue[1]);
179 | const value = event.target.value;
180 | const repr = value;
181 | updateValue(value, repr);
182 | },
183 | [updateValue],
184 | );
185 |
186 | // --- Stepper logic
187 | const handleIncStep = useCallback(() => {
188 | if (readOnly) return;
189 | const newValue = applyStep(valueStrRep, _step, min, max, integersOnly);
190 |
191 | if (newValue === undefined) return;
192 | updateValue(newValue, newValue.toString());
193 | }, [valueStrRep, _step, min, max, integersOnly, updateValue, readOnly]);
194 |
195 | const handleDecStep = useCallback(() => {
196 | if (readOnly) return;
197 | const newValue = applyStep(valueStrRep, -_step, min, max, integersOnly);
198 |
199 | if (newValue === undefined) return;
200 | updateValue(newValue, newValue.toString());
201 | }, [valueStrRep, _step, min, max, integersOnly, updateValue, readOnly]);
202 |
203 | // --- Register stepper logic to buttons
204 | useLongPress(upButton.current, handleIncStep);
205 | useLongPress(downButton.current, handleDecStep);
206 |
207 | // --- Shared character validation logic
208 | const processCharacterInput = useCallback(
209 | (
210 | char: string,
211 | currentValue: string,
212 | currentPos: number,
213 | predictedValue: string,
214 | isForPaste: boolean = false,
215 | ): {
216 | shouldAccept: boolean;
217 | newValue?: string;
218 | newPos?: number;
219 | shouldPreventDefault?: boolean;
220 | } => {
221 | // --- Are the caret after the exponential separator?
222 | const beforeCaret = currentValue.substring(0, currentPos);
223 | const expPos = beforeCaret.indexOf(EXPONENTIAL_SEPARATOR);
224 |
225 | let shouldAccept = true;
226 | let shouldPreventDefault = false;
227 | let newValue = currentValue;
228 | let newPos = currentPos;
229 |
230 | switch (char) {
231 | case "-":
232 | shouldAccept = false;
233 | shouldPreventDefault = true;
234 | if (zeroOrPositive) {
235 | // --- No minus sign allowed
236 | break;
237 | }
238 | if (expPos === -1) {
239 | // --- Change the first char to "-" if we are before the exponential separator and it's not already there
240 | if (!currentValue.startsWith("-")) {
241 | newValue = "-" + currentValue;
242 | newPos = currentPos + 1;
243 | }
244 | } else {
245 | // --- Change the char after the exponential separator to "-" if it's not already there
246 | if (currentValue[expPos + 1] !== "-") {
247 | newValue =
248 | currentValue.substring(0, expPos + 1) + "-" + currentValue.substring(expPos + 1);
249 | newPos = currentPos + 1;
250 | }
251 | }
252 | break;
253 | case "+":
254 | shouldAccept = false;
255 | shouldPreventDefault = true;
256 | if (expPos === -1) {
257 | // --- Remove the first char if it's "-" and we are before the exponential separator
258 | if (currentValue.startsWith("-")) {
259 | newValue = currentValue.substring(1);
260 | newPos = Math.max(0, currentPos - 1);
261 | }
262 | } else {
263 | // --- Remove the char after the exponential separator if it's "-"
264 | if (currentValue[expPos + 1] === "-") {
265 | newValue = currentValue.substring(0, expPos + 1) + currentValue.substring(expPos + 2);
266 | newPos = Math.max(expPos + 1, currentPos - 1);
267 | }
268 | }
269 | break;
270 | case "0":
271 | // --- Prevent leading zeros (before decimal or exponential separator)
272 | if (currentValue === "0") {
273 | shouldAccept = false;
274 | shouldPreventDefault = true;
275 | }
276 | break;
277 | case "1":
278 | case "2":
279 | case "3":
280 | case "4":
281 | case "5":
282 | case "6":
283 | case "7":
284 | case "8":
285 | case "9":
286 | // --- Replace leading zero with this digit
287 | if (currentValue === "0" && currentPos === 1) {
288 | if (isForPaste) {
289 | newValue = char;
290 | shouldAccept = false; // Don't add it again for paste
291 | } else {
292 | newValue = char;
293 | newPos = 1;
294 | shouldPreventDefault = true;
295 | }
296 | }
297 | break;
298 | case DECIMAL_SEPARATOR:
299 | // --- Prevent multiple decimal separators (integers only),
300 | // --- or decimal separator after the exponential separator
301 | if (integersOnly || currentValue.includes(DECIMAL_SEPARATOR) || expPos !== -1) {
302 | shouldAccept = false;
303 | shouldPreventDefault = true;
304 | } else if (predictedValue.startsWith(DECIMAL_SEPARATOR) && currentPos === 0) {
305 | newValue = "0" + predictedValue;
306 | newPos = currentPos + 2;
307 | shouldPreventDefault = true;
308 | }
309 | break;
310 | case EXPONENTIAL_SEPARATOR:
311 | // --- Prevent exponential notation for integers
312 | if (integersOnly) {
313 | shouldAccept = false;
314 | shouldPreventDefault = true;
315 | break;
316 | }
317 | // --- Prevent multiple exponential separators
318 | if (currentValue.includes(EXPONENTIAL_SEPARATOR)) {
319 | shouldAccept = false;
320 | shouldPreventDefault = true;
321 | }
322 | break;
323 | default:
324 | // --- Only allow digits for single characters
325 | if (char >= "0" && char <= "9") {
326 | // --- Prevent digits before minus sign
327 | if (currentValue.startsWith("-") && currentPos === 0) {
328 | shouldAccept = false;
329 | shouldPreventDefault = true;
330 | break;
331 | }
332 |
333 | // --- For beforeInput, check for too many digits after exponential separator
334 | if (!isForPaste && expPos !== -1) {
335 | const tooManyDigitsAfterExponentialSeparator = (
336 | pos: number,
337 | maxDigits: number,
338 | ): boolean => {
339 | let numDigitsAfter = 0;
340 | while (pos < currentValue.length) {
341 | if (/\d/.test(currentValue[pos++])) {
342 | numDigitsAfter++;
343 | } else {
344 | numDigitsAfter = maxDigits + 1;
345 | break;
346 | }
347 | }
348 | return numDigitsAfter > maxDigits;
349 | };
350 |
351 | if (tooManyDigitsAfterExponentialSeparator(expPos + 1, 1)) {
352 | shouldAccept = false;
353 | shouldPreventDefault = true;
354 | }
355 | }
356 | } else {
357 | // --- Reject non-digit characters
358 | shouldAccept = false;
359 | shouldPreventDefault = true;
360 | }
361 | break;
362 | }
363 |
364 | return { shouldAccept, newValue, newPos, shouldPreventDefault };
365 | },
366 | [integersOnly, zeroOrPositive],
367 | );
368 |
369 | // --- This logic prevents the user from typing invalid characters (in the current typing context)
370 | const handleOnBeforeInput = (event: any) => {
371 | const currentValue: string = event.target.value ?? "";
372 | const currentPos = event.target.selectionStart;
373 | const expectedNewValue =
374 | currentValue.substring(0, currentPos) +
375 | event.data +
376 | currentValue.substring(event.target.selectionEnd);
377 |
378 | // --- Handle multi-character input (paste) through the legacy path
379 | if (event.data?.length > 1) {
380 | let shouldPreventDefault = false;
381 | const selectionStart = event.target.selectionStart;
382 | let newInput = event.data;
383 |
384 | // --- Decide whether to accept the optional sign character
385 | if (newInput.startsWith("-")) {
386 | if (selectionStart > 0) {
387 | shouldPreventDefault = true;
388 | }
389 | } else if (newInput.startsWith("+")) {
390 | shouldPreventDefault = true;
391 | }
392 |
393 | if (!shouldPreventDefault) {
394 | // --- Check for integers
395 | if (integersOnly && !INT_REGEXP.test(expectedNewValue)) {
396 | // --- The result is not an integer, drop the pasted input
397 | shouldPreventDefault = true;
398 | } else if (!FLOAT_REGEXP.test(expectedNewValue)) {
399 | // --- The result is not a float, drop the pasted input
400 | shouldPreventDefault = true;
401 | }
402 | }
403 |
404 | if (shouldPreventDefault) {
405 | event.preventDefault();
406 | }
407 | return;
408 | }
409 |
410 | // --- Single character processing
411 | const result = processCharacterInput(
412 | event.data,
413 | currentValue,
414 | currentPos,
415 | expectedNewValue,
416 | false,
417 | );
418 |
419 | if (result.shouldPreventDefault) {
420 | event.preventDefault();
421 | }
422 |
423 | // --- Apply value changes if needed
424 | if (result.newValue !== currentValue) {
425 | const setNewValue = (newValue: string, pos: number) => {
426 | event.target.value = newValue;
427 | updateValue(newValue, newValue);
428 | inputRef.current?.setSelectionRange(pos, pos);
429 | };
430 | setNewValue(result.newValue!, result.newPos!);
431 | }
432 | };
433 |
434 | // --- Handle paste events by applying the same character validation logic
435 | const handleOnPaste = useCallback(
436 | (event: React.ClipboardEvent<HTMLInputElement>) => {
437 | event.preventDefault();
438 |
439 | const pastedText = event.clipboardData.getData("text/plain");
440 | if (!pastedText) return;
441 |
442 | const inputElement = event.currentTarget;
443 | const currentValue = inputElement.value ?? "";
444 | const selectionStart = inputElement.selectionStart ?? 0;
445 | const selectionEnd = inputElement.selectionEnd ?? 0;
446 | const expectedNewValue =
447 | currentValue.substring(0, selectionStart) +
448 | pastedText +
449 | currentValue.substring(selectionEnd);
450 |
451 | // --- Start with the value before the selection
452 | let resultValue = currentValue.substring(0, selectionStart);
453 | let currentPos = selectionStart;
454 |
455 | // --- Process each character from the pasted text
456 | for (let i = 0; i < pastedText.length; i++) {
457 | const char = pastedText[i];
458 |
459 | const result = processCharacterInput(char, resultValue, currentPos, expectedNewValue, true);
460 |
461 | if (result.shouldAccept) {
462 | resultValue =
463 | resultValue.substring(0, currentPos) + char + resultValue.substring(currentPos);
464 | currentPos++;
465 | } else if (result.newValue !== resultValue) {
466 | // --- Handle special cases like sign changes or zero replacement
467 | resultValue = result.newValue!;
468 | currentPos = result.newPos!;
469 | }
470 | }
471 |
472 | // --- Add the rest of the original value after the selection
473 | resultValue += currentValue.substring(selectionEnd);
474 |
475 | // --- Final validation - ensure the result is a valid number format
476 | let isValidFinal = false;
477 | if (integersOnly) {
478 | isValidFinal = INT_REGEXP.test(resultValue) || resultValue === "" || resultValue === "-";
479 | } else {
480 | isValidFinal = FLOAT_REGEXP.test(resultValue) || resultValue === "" || resultValue === "-";
481 | }
482 |
483 | // --- Apply the result if valid
484 | if (isValidFinal) {
485 | inputElement.value = resultValue;
486 | updateValue(resultValue, resultValue);
487 | inputElement.setSelectionRange(currentPos, currentPos);
488 | }
489 | },
490 | [processCharacterInput, updateValue, integersOnly],
491 | );
492 |
493 | // --- Setting steppers with keyboard
494 | const handleOnKey = useCallback(
495 | (event: React.KeyboardEvent<HTMLInputElement>) => {
496 | if (event.code === "ArrowUp") {
497 | event.preventDefault();
498 | handleIncStep();
499 | }
500 | if (event.code === "ArrowDown") {
501 | event.preventDefault();
502 | handleDecStep();
503 | }
504 | },
505 | [handleIncStep, handleDecStep],
506 | );
507 |
508 | // --- Manage obtaining and losing focus & blur
509 | const handleOnFocus = useCallback(() => {
510 | onFocus?.();
511 | }, [onFocus]);
512 |
513 | const handleOnBlur = useCallback(() => {
514 | // --- Get the current input value
515 | const currentInputValue = inputRef.current?.value ?? "";
516 |
517 | // --- Check if we need to add a trailing zero
518 | let finalValue = currentInputValue;
519 | if (!integersOnly && currentInputValue.endsWith(DECIMAL_SEPARATOR)) {
520 | // --- Add trailing zero if the value ends with decimal separator
521 | finalValue = currentInputValue + "0";
522 | }
523 |
524 | // --- Convert to number and clamp to min/max bounds
525 | const numericValue = toUsableNumber(finalValue, integersOnly);
526 | if (!isEmptyLike(numericValue)) {
527 | const clampedValue = clamp(numericValue, min, max);
528 | if (clampedValue !== numericValue) {
529 | const clampedString = clampedValue.toString();
530 | finalValue = clampedString;
531 |
532 | // --- Update the input field immediately
533 | if (inputRef.current) {
534 | inputRef.current.value = clampedString;
535 | }
536 | }
537 | }
538 |
539 | // --- Update the state if the final value is different from current input
540 | if (finalValue !== currentInputValue) {
541 | updateValue(finalValue, finalValue);
542 | } else {
543 | // --- Use the standard representation mapping
544 | setValueStrRep(mapToRepresentation(value));
545 | }
546 |
547 | onBlur?.();
548 | }, [value, onBlur, integersOnly, updateValue, min, max]);
549 |
550 | const focus = useCallback(() => {
551 | inputRef.current?.focus();
552 | }, []);
553 |
554 | const setValue = useEvent((newValue) => {
555 | updateValue(newValue, isEmptyLike(newValue) ? "" : String(newValue));
556 | });
557 |
558 | useEffect(() => {
559 | registerComponentApi?.({
560 | focus,
561 | setValue,
562 | });
563 | }, [focus, registerComponentApi, setValue]);
564 |
565 | return (
566 | <div
567 | {...rest}
568 | className={classnames(className, styles.inputRoot,{
569 | [styles.readOnly]: readOnly,
570 | [styles.disabled]: !enabled,
571 | [styles.noSpinBox]: !hasSpinBox,
572 | [styles.error]: validationStatus === "error",
573 | [styles.warning]: validationStatus === "warning",
574 | [styles.valid]: validationStatus === "valid",
575 | [styles.rtl]: direction === "rtl",
576 | })}
577 | id={id}
578 | ref={forwardedRef}
579 | tabIndex={-1}
580 | onFocus={() => {
581 | inputRef.current?.focus();
582 | }}
583 | style={{ ...style, gap }}
584 | >
585 | <Adornment
586 | data-part-id={PART_START_ADORNMENT}
587 | text={startText}
588 | iconName={startIcon}
589 | className={classnames(styles.adornment)}
590 | />
591 | <input
592 | id={id}
593 | data-part-id={PART_INPUT}
594 | type="text"
595 | inputMode="numeric"
596 | className={classnames(styles.input, {
597 | [styles.readOnly]: readOnly,
598 | })}
599 | disabled={!enabled}
600 | value={valueStrRep}
601 | step={step}
602 | placeholder={placeholder}
603 | onChange={onInputChange}
604 | onFocus={handleOnFocus}
605 | onBlur={handleOnBlur}
606 | onBeforeInput={handleOnBeforeInput}
607 | onPaste={handleOnPaste}
608 | onKeyDown={handleOnKey}
609 | readOnly={readOnly}
610 | ref={inputRef}
611 | autoFocus={autoFocus}
612 | maxLength={maxLength}
613 | required={required}
614 | />
615 | <Adornment
616 | data-part-id={PART_END_ADORNMENT}
617 | text={endText}
618 | iconName={endIcon}
619 | className={classnames(styles.adornment)}
620 | />
621 | {hasSpinBox && (
622 | <div className={styles.spinnerBox}>
623 | <Button
624 | data-part-id={PART_SPINNER_UP}
625 | data-spinner="up"
626 | type="button"
627 | role="spinbutton"
628 | variant={"ghost"}
629 | themeColor={"secondary"}
630 | tabIndex={-1}
631 | className={styles.spinnerButton}
632 | disabled={!enabled || readOnly}
633 | ref={upButton}
634 | >
635 | <Icon name={spinnerUpIcon || "spinnerUp:NumberBox"} fallback="chevronup" size="sm" />
636 | </Button>
637 | <Button
638 | data-part-id={PART_SPINNER_DOWN}
639 | data-spinner="down"
640 | type="button"
641 | role="spinbutton"
642 | tabIndex={-1}
643 | variant={"ghost"}
644 | themeColor={"secondary"}
645 | className={styles.spinnerButton}
646 | disabled={!enabled || readOnly}
647 | ref={downButton}
648 | >
649 | <Icon
650 | name={spinnerDownIcon || "spinnerDown:NumberBox"}
651 | fallback="chevrondown"
652 | size="sm"
653 | />
654 | </Button>
655 | </div>
656 | )}
657 | </div>
658 | );
659 | });
660 |
661 | function applyStep(
662 | valueStrRep: string,
663 | step: number,
664 | min: number,
665 | max: number,
666 | integersOnly: boolean,
667 | ) {
668 | const currentValue = toUsableNumber(valueStrRep, integersOnly);
669 | if (isEmptyLike(currentValue)) {
670 | return;
671 | }
672 | return clamp(currentValue + step, min, max);
673 | }
674 |
675 | function useLongPress(elementRef: HTMLElement | null, action: () => void, delay: number = 500) {
676 | const timeoutId = useRef(0);
677 | const intervalId = useRef(0);
678 | const savedAction = useRef<() => void>(action);
679 |
680 | // Remember the latest action callback, since it is different every render
681 | useEffect(() => {
682 | savedAction.current = action;
683 | }, [action]);
684 |
685 | useEffect(() => {
686 | const onMouseDown = () => {
687 | savedAction.current?.();
688 |
689 | timeoutId.current = window.setTimeout(() => {
690 | intervalId.current = window.setInterval(() => {
691 | savedAction.current?.();
692 | }, 100);
693 | }, delay);
694 | };
695 |
696 | const onMouseUp = () => {
697 | clearTimeout(timeoutId.current);
698 | clearInterval(intervalId.current);
699 | };
700 |
701 | const onMouseOut = () => {
702 | clearTimeout(timeoutId.current);
703 | clearInterval(intervalId.current);
704 | };
705 |
706 | elementRef?.addEventListener("mousedown", onMouseDown);
707 | elementRef?.addEventListener("mouseup", onMouseUp);
708 | elementRef?.addEventListener("mouseout", onMouseOut);
709 |
710 | return () => {
711 | elementRef?.removeEventListener("mousedown", onMouseDown);
712 | elementRef?.removeEventListener("mouseup", onMouseUp);
713 | elementRef?.removeEventListener("mouseout", onMouseOut);
714 | };
715 | }, [elementRef, action, delay]);
716 | }
717 |
```
--------------------------------------------------------------------------------
/docs/content/components/_overview.md:
--------------------------------------------------------------------------------
```markdown
1 | # Components Overview [#components-overview]
2 |
3 | | Component | Description |
4 | | :---: | --- |
5 | | [APICall](./APICall) | `APICall` creates, updates or deletes data on the backend, versus [`DataSource`](/components/DataSource) which fetches data. Unlike DataSource, APICall doesn't automatically execute - you must trigger it manually with the `execute()` method, typically from form submissions or button clicks. |
6 | | [App](./App) | The `App` component is the root container that defines your application's overall structure and layout. It provides a complete UI framework with built-in navigation, header, footer, and content areas that work together seamlessly. |
7 | | [AppHeader](./AppHeader) | `AppHeader` defines the top navigation bar of your application within the [`App`](/components/App) component. It automatically handles logo placement, application title, and user profile areas with built-in responsive behavior. |
8 | | [AppState](./AppState) | `AppState` is an invisible component that provides global state management across your entire application. Unlike component variables that are scoped locally, AppState allows any component to access and update shared state without prop drilling. |
9 | | [AutoComplete](./AutoComplete) | `AutoComplete` is a searchable dropdown input that allows users to type and filter through options, with support for single or multiple selections. Unlike a basic [`Select`](/components/Select), it provides type-ahead functionality and can allow users to create new options. |
10 | | [Avatar](./Avatar) | `Avatar` displays a user or entity's profile picture as a circular image, with automatic fallback to initials when no image is provided. It's commonly used in headers, user lists, comments, and anywhere you need to represent a person or organization. |
11 | | [Backdrop](./Backdrop) | The `Backdrop` component is a semi-transparent overlay that appears on top of its child component to obscure or highlight the content behind it. |
12 | | [Badge](./Badge) | `Badge` displays small text labels with colored backgrounds, commonly used for status indicators, categories, tags, and counts. It supports dynamic color mapping based on content values, useful for status systems and data categorization. |
13 | | [BarChart](./BarChart) | `BarChart` displays data as horizontal or vertical bars, supporting both grouped and stacked layouts. It's ideal for comparing values across categories, showing revenue trends, or displaying any quantitative data over time or categories. |
14 | | [Bookmark](./Bookmark) | As its name suggests, this component places a bookmark into its parent component's view. The component has an `id` that you can use in links to navigate (scroll to) the bookmark's location. |
15 | | [Breakout](./Breakout) | The `Breakout` component creates a breakout section. It allows its child to occupy the entire width of the UI even if the app or the parent container constrains the maximum content width. |
16 | | [Button](./Button) | `Button` is the primary interactive component for triggering actions like form submissions, navigation, opening modals, and API calls. It supports multiple visual styles and sizes to match different UI contexts and importance levels. |
17 | | [Card](./Card) | `Card` is a versatile container that groups related content with a visual boundary, typically featuring background color, padding, borders, and rounded corners. It's ideal for organizing information, creating sections, and establishing visual hierarchy in your interface. |
18 | | [Carousel](./Carousel) | This component displays a slideshow by cycling through elements (images, text, or custom slides) like a carousel. |
19 | | [ChangeListener](./ChangeListener) | `ChangeListener` is an invisible component that watches for changes in values and triggers actions in response. It's essential for creating reactive behavior when you need to respond to data changes, state updates, or component property modifications outside of normal event handlers. |
20 | | [Checkbox](./Checkbox) | `Checkbox` allows users to make binary choices with a clickable box that shows checked/unchecked states. It's essential for settings, preferences, multi-select lists, and accepting terms or conditions. |
21 | | [CHStack](./CHStack) | This component represents a stack that renders its contents horizontally and aligns that in the center along both axes. |
22 | | [ColorPicker](./ColorPicker) | `ColorPicker` enables users to choose colors by specifying RGB, HSL, or HEX values. |
23 | | [Column](./Column) | `Column` defines the structure and behavior of individual table columns within a [`Table`](/components/Table) component. Each Column controls data binding, header display, sorting capabilities, sizing, and can contain any XMLUI components for rich cell content. |
24 | | [ContentSeparator](./ContentSeparator) | `ContentSeparator` creates visual dividers between content sections using horizontal or vertical lines. It's essential for improving readability by breaking up dense content, separating list items, or creating clear boundaries between different UI sections. |
25 | | [CVStack](./CVStack) | This component represents a stack that renders its contents vertically and aligns that in the center along both axes. |
26 | | [DataSource](./DataSource) | `DataSource` fetches and caches data from API endpoints, versus [`APICall`](/components/APICall) which creates, updates or deletes data. |
27 | | [DateInput](./DateInput) | `DateInput` provides a text-based date input interface for selecting single dates or date ranges, with direct keyboard input similar to TimeInput. It offers customizable formatting and validation options without dropdown calendars. |
28 | | [DatePicker](./DatePicker) | `DatePicker` provides an interactive calendar interface for selecting single dates or date ranges, with customizable formatting and validation options. It displays a text input that opens a calendar popup when clicked, offering both keyboard and mouse interaction. |
29 | | [DonutChart](./DonutChart) | A derivative of [PieChart](/components/PieChart) with a hollow center. Note that the height of the component or its parent needs to be set explicitly. |
30 | | [DropdownMenu](./DropdownMenu) | `DropdownMenu` provides a space-efficient way to present multiple options or actions through a collapsible interface. When clicked, the trigger button reveals a menu that can include items, separators, and nested submenus, making it ideal for navigation, action lists, or any situation requiring many options without permanent screen space. |
31 | | [EmojiSelector](./EmojiSelector) | `EmojiSelector` enables users to browse, search and select emojis from their system's native emoji set. |
32 | | [ExpandableItem](./ExpandableItem) | `ExpandableItem` creates expandable/collapsible section, similar to the HTML details disclosure element. When the user clicks on the `summary` the content expands or collapses. |
33 | | [FileInput](./FileInput) | `FileInput` enables users to select files from their device's file system for upload or processing. It combines a text field displaying selected files with a customizable button that opens the system file browser. Use it for forms, media uploads, and document processing workflows. |
34 | | [FileUploadDropZone](./FileUploadDropZone) | `FileUploadDropZone` enables users to upload files by dragging and dropping files from their local file system onto a designated area within the UI. |
35 | | [FlowLayout](./FlowLayout) | `FlowLayout` positions content in rows with automatic wrapping. When items exceed the available horizontal space, they automatically wrap to a new line. |
36 | | [Footer](./Footer) | `Footer` provides a designated area at the bottom of your application for footer content such as branding, copyright notices, or utility controls like theme toggles. |
37 | | [Form](./Form) | `Form` provides a structured container for collecting and validating user input, with built-in data binding, validation, and submission handling. It automatically manages form state and provides context for nested form controls to work together. |
38 | | [FormItem](./FormItem) | `FormItem` wraps individual input controls within a `Form`, providing data binding, validation, labeling, and layout functionality. It connects form controls to the parent form's data model and handles validation feedback automatically. **Note:** `FormItem` must be used inside a `Form` component. |
39 | | [FormSection](./FormSection) | `FormSection` groups elements within a `Form`. Child components are placed in a [FlowLayout](/components/FlowLayout). |
40 | | [Fragment](./Fragment) | `Fragment` provides conditional rendering. You can use `when=` on any component to render it conditionally, use `Fragment` to apply `when` to a group of components. |
41 | | [H1](./H1) | Represents a heading level 1 text |
42 | | [H2](./H2) | Represents a heading level 2 text |
43 | | [H3](./H3) | Represents a heading level 3 text |
44 | | [H4](./H4) | Represents a heading level 4 text |
45 | | [H5](./H5) | Represents a heading level 5 text |
46 | | [H6](./H6) | Represents a heading level 6 text |
47 | | [Heading](./Heading) | `Heading` displays hierarchical text headings with semantic importance levels from H1 to H6, following HTML heading standards. It provides text overflow handling, anchor link generation, and integrates with [TableOfContents](/components/TableOfContents). |
48 | | [HSplitter](./HSplitter) | `Splitter` component divides a container into two resizable sections. These are are identified by their names: primary and secondary. They have a draggable bar between them. When only a single child is visible (due to conditional rendering with `when` attributes), the splitter bar is not displayed and the single panel stretches to fill the entire viewport of the splitter container. |
49 | | [HStack](./HStack) | This component represents a stack rendering its contents horizontally. |
50 | | [Icon](./Icon) | `Icon` displays scalable vector icons from XMLUI's built-in icon registry using simple name references. Icons are commonly used in buttons, navigation elements, and status indicators. |
51 | | [IFrame](./IFrame) | `IFrame` embeds external content from another HTML document into the current page. It provides security controls through sandbox and allow attributes, and supports features like fullscreen display and referrer policy configuration. |
52 | | [Image](./Image) | `Image` displays pictures from URLs or local sources with built-in responsive sizing, aspect ratio control, and accessibility features. It handles different image formats and provides options for lazy loading and click interactions. |
53 | | [Items](./Items) | `Items` renders data arrays without built-in layout or styling, providing a lightweight alternative to `List`. Unlike `List`, it provides no virtualization, grouping, or visual formatting — just pure data iteration. |
54 | | [LabelList](./LabelList) | `LabelList` adds custom data labels to chart components when automatic labeling isn't sufficient. It's a specialized component for advanced chart customization scenarios where you need precise control over label positioning and appearance. |
55 | | [Legend](./Legend) | `Legend` provides a standalone legend for chart components when you need custom positioning or styling beyond the chart's built-in `showLegend` property. Most charts can display legends automatically, but this component offers precise control over legend placement and alignment. |
56 | | [LineChart](./LineChart) | `LineChart` displays data as connected points over a continuous axis, ideal for showing trends, changes over time, or relationships between variables. Use it time series data, progress tracking, and comparing multiple data series on the same scale. |
57 | | [Link](./Link) | `Link` creates clickable navigation elements for internal app routes or external URLs. You can use the `label` and `icon` properties for simple text links, or embed custom components like buttons, cards, or complex layouts for rich interactive link presentations. |
58 | | [List](./List) | `List` is a high-performance, virtualized container for rendering large datasets with built-in grouping, sorting, and visual formatting. It only renders visible items in the viewport, making it ideal for displaying thousands of records while maintaining smooth scrolling performance. |
59 | | [Logo](./Logo) | `Logo` displays your application's brand symbol by automatically loading logo images defined in the app manifest. While logos are typically configured using App-level properties (`logo`, `logo-dark`), this component provides direct control when you need custom logo placement or templating. |
60 | | [Markdown](./Markdown) | `Markdown` renders formatted text using markdown syntax. Use [Text](/working-with-text) for simple, styled text content, and `Markdown` when you need [rich formatting](/working-with-markdown). |
61 | | [MenuItem](./MenuItem) | `MenuItem` represents individual clickable items within dropdown menus and other menu components. Each menu item can display text, icons, and respond to clicks with either navigation or custom actions, making it the building block for interactive menu systems. |
62 | | [MenuSeparator](./MenuSeparator) | `MenuSeparator` displays a separator line between menu items to group related menu options within `DropdownMenu`. |
63 | | [ModalDialog](./ModalDialog) | `ModalDialog` creates overlay dialogs that appear on top of the main interface, ideal for forms, confirmations, detailed views, or any content that requires focused user attention. Dialogs are programmatically opened using the `open()` method and can receive parameters for dynamic content. |
64 | | [NavGroup](./NavGroup) | `NavGroup` creates collapsible containers for organizing related navigation items into hierarchical menu structures. It groups `NavLink` components and other `NavGroup` components, providing expandable submenus with customizable icons and states. |
65 | | [NavLink](./NavLink) | `NavLink` creates interactive navigation items that connect users to different destinations within an app or external URLs. It automatically indicates active states, supports custom icons and labels, and can execute custom actions instead of navigation when needed. |
66 | | [NavPanel](./NavPanel) | `NavPanel` defines the navigation structure within an App, serving as a container for NavLink and NavGroup components that create your application's primary navigation menu. Its appearance and behavior automatically adapt based on the App's layout configuration. |
67 | | [NoResult](./NoResult) | `NoResult` displays a visual indication that a query or search returned nothing. |
68 | | [NumberBox](./NumberBox) | `NumberBox` provides a specialized input field for numeric values with built-in validation, spinner buttons, and flexible formatting options. It supports both integer and floating-point numbers, handles empty states as null values, and integrates seamlessly with form validation. |
69 | | [Option](./Option) | `Option` defines selectable items for choice-based components, providing both the underlying value and display text for selection interfaces. It serves as a non-visual data structure that describes individual choices within [Select](/components/Select), [AutoComplete](/components/AutoComplete), and other selection components. |
70 | | [Page](./Page) | `Page` defines route endpoints within an application, mapping specific URL patterns to content that displays when users navigate to those routes. Each Page represents a distinct view or screen in your single-page application's routing system. |
71 | | [PageMetaTitle](./PageMetaTitle) | `PageMetaTitle` dynamically sets or updates the browser tab title, enabling pages and components to override the default application name with context-specific titles. |
72 | | [Pages](./Pages) | `Pages` serves as the routing coordinator within an [App](/components/App), managing which [Page](/components/Page) displays based on the current URL. |
73 | | [Pagination](./Pagination) | `Pagination` enables navigation through large datasets by dividing content into pages. It provides controls for page navigation and can display current page information. |
74 | | [PasswordInput](./PasswordInput) | `Password` is a specialized [TextBox](/components/TextBox) that enables users to input and edit passwords. |
75 | | [PieChart](./PieChart) | `PieChart` visualizes proportional data as circular segments; each slice represents a percentage of the whole. Note that the height of the component or its parent needs to be set explicitly. |
76 | | [ProgressBar](./ProgressBar) | `ProgressBar` provides a visual indicator showing the completion percentage of tasks, processes, or any measurable progress. It displays as a horizontal bar that fills from left to right based on the provided value between 0 (empty) and 1 (complete). |
77 | | [Queue](./Queue) | `Queue` manages sequential processing of items in FIFO (first-in, first-out) order. It is a non-visual component but provides UI progress reporting and result display. |
78 | | [RadioGroup](./RadioGroup) | `RadioGroup` creates a mutually exclusive selection interface where users can choose only one option from a group of radio buttons. It manages the selection state and ensures that selecting one option automatically deselects all others in the group.Radio options store their values as strings. Numbers and booleans are converted to strings when assigned, while objects, functions and arrays default to an empty string unless resolved via binding expressions. |
79 | | [RealTimeAdapter](./RealTimeAdapter) | `RealTimeAdapter` is a non-visual component that listens to real-time events. |
80 | | [Redirect](./Redirect) | `Redirect` immediately redirects the browser to the URL in its `to` property when it gets visible (its `when` property gets `true`). It works only within [App](/components/App), not externally. |
81 | | [Select](./Select) | `Select` provides a dropdown interface for choosing from a list of options, supporting both single and multiple selection modes. It offers extensive customization capabilities including search functionality, custom templates, and comprehensive form integration. |
82 | | [Slider](./Slider) | `Slider` provides an interactive control for selecting numeric values within a defined range, supporting both single value selection and range selection with multiple thumbs. It offers precise control through customizable steps and visual feedback with formatted value display.Hover over the component to see the tooltip with the current value. On mobile, tap the thumb to see the tooltip. |
83 | | [Slot](./Slot) | Placeholder in a reusable component. Signs the slot where the component's injected children should be rendered. |
84 | | [SpaceFiller](./SpaceFiller) | `SpaceFiller` works well in layout containers to fill remaining (unused) space. Its behavior depends on the layout container in which it is used. |
85 | | [Spinner](./Spinner) | `Spinner` is an animated indicator that represents an action in progress with no deterministic progress value. |
86 | | [Splitter](./Splitter) | `Splitter` component divides a container into two resizable sections. These are are identified by their names: primary and secondary. They have a draggable bar between them. When only a single child is visible (due to conditional rendering with `when` attributes), the splitter bar is not displayed and the single panel stretches to fill the entire viewport of the splitter container. |
87 | | [Stack](./Stack) | `Stack` is the fundamental layout container that organizes child elements in configurable horizontal or vertical arrangements. As the most versatile building block in XMLUI's layout system, it provides comprehensive alignment, spacing, and flow control options that serve as the foundation for all specialized stack variants. |
88 | | [StickyBox](./StickyBox) | `StickyBox` remains fixed at the top or bottom of the screen as the user scrolls. |
89 | | [SubMenuItem](./SubMenuItem) | `SubMenuItem` creates hierarchical menu structures by acting as both a menu item and a container for nested menu items. When clicked or hovered, it reveals a submenu containing additional [MenuItem](/components/MenuItem), [MenuSeparator](/components/MenuSeparator), or other [SubMenuItem](/components/SubMenuItems) components, enabling complex multi-level navigation and action organization. |
90 | | [Switch](./Switch) | `Switch` enables users to toggle between two states: on and off. |
91 | | [TabItem](./TabItem) | `TabItem` defines individual tabs within a [Tabs](/components/Tabs) component, providing both the tab header label and the content that displays when the tab is selected. As a non-visual structural component, it serves as a container that organizes content into distinct, switchable sections. |
92 | | [Table](./Table) | `Table` presents structured data for viewing, sorting, selection, and interaction. |
93 | | [TableOfContents](./TableOfContents) | `TableOfContents` component collects [Heading](/components/Heading) and [Bookmark](/components/Bookmark) within the current page and displays them in a navigable tree. |
94 | | [Tabs](./Tabs) | `Tabs` enables users to switch among content panels using clickable tab headers. It provides an efficient way to present multiple related sections in a single interface area, with each tab containing distinct content defined by [TabItem](/components/TabItem) components. |
95 | | [Text](./Text) | The `Text` component displays textual information in a number of optional styles and variants. |
96 | | [TextArea](./TextArea) | `TextArea` provides a multiline text input area. |
97 | | [TextBox](./TextBox) | `TextBox` captures user text input for forms, search fields, and data entry with support for validation, icons, and formatting hints. |
98 | | [Theme](./Theme) | `Theme` creates styling contexts to customize the appearance of nested components without using CSS. |
99 | | [TimeInput](./TimeInput) | `TimeInput` provides time input with support for 12-hour and 24-hour formats and configurable precision for hours, minutes, and seconds. |
100 | | [Timer](./Timer) | `Timer` is a non-visual component that fires events at regular intervals. It can be enabled or disabled and ensures that the timer event handler completes before firing the next event. |
101 | | [ToneChangerButton](./ToneChangerButton) | `ToneChangerButton` enables the user to switch between light and dark modes. |
102 | | [ToneSwitch](./ToneSwitch) | `ToneSwitch` enables the user to switch between light and dark modes using a switch control. |
103 | | [Tooltip](./Tooltip) | A tooltip component that displays text when hovering over trigger content. |
104 | | [Tree](./Tree) | The `Tree` component is a virtualized tree component that displays hierarchical data with support for flat and hierarchy data formats. |
105 | | [VSplitter](./VSplitter) | `Splitter` component divides a container into two resizable sections. These are are identified by their names: primary and secondary. They have a draggable bar between them. When only a single child is visible (due to conditional rendering with `when` attributes), the splitter bar is not displayed and the single panel stretches to fill the entire viewport of the splitter container. |
106 | | [VStack](./VStack) | This component represents a stack rendering its contents vertically. |
107 |
108 |
```
--------------------------------------------------------------------------------
/docs/content/components/NumberBox.md:
--------------------------------------------------------------------------------
```markdown
1 | # NumberBox [#numberbox]
2 |
3 | `NumberBox` provides a specialized input field for numeric values with built-in validation, spinner buttons, and flexible formatting options. It supports both integer and floating-point numbers, handles empty states as null values, and integrates seamlessly with form validation.
4 |
5 | **Key features:**
6 | - **Flexible numeric input**: Accepts integers, floating-point numbers, or empty values (stored as null)
7 | - **Input constraints**: Configure minimum/maximum values, integer-only mode, and positive-only restrictions
8 | - **Spinner buttons**: Built-in increment/decrement buttons with customizable step values and icons
9 | - **Visual adornments**: Add icons or text to the start and end of the input field
10 | - **Validation**: Built-in validation status indicators and form compatibility
11 | - **Smart paste handling**: Only accepts pasted content that results in valid numeric values
12 |
13 | The `NumberBox` is often used in forms. See the [this guide](/forms) for details.
14 |
15 | ## Properties [#properties]
16 |
17 | ### `autoFocus` (default: false) [#autofocus-default-false]
18 |
19 | If this property is set to `true`, the component gets the focus automatically when displayed.
20 |
21 | If this boolean prop is set to true, the `NumberBox` input will be focused when appearing on the UI.
22 |
23 | ### `enabled` (default: true) [#enabled-default-true]
24 |
25 | This boolean property value indicates whether the component responds to user events (`true`) or not (`false`).
26 |
27 | Controls whether the input field is enabled (`true`) or disabled (`false`).
28 |
29 | ```xmlui-pg copy display name="Example: enabled"
30 | <App>
31 | <NumberBox enabled="false" />
32 | </App>
33 | ```
34 |
35 | ### `endIcon` [#endicon]
36 |
37 | This property sets an optional icon to appear on the end (right side when the left-to-right direction is set) of the input.
38 |
39 | This string prop enables the display of an icon on the right side (left-to-right display) of the input field by providing a valid [icon name]().
40 |
41 | ```xmlui-pg copy display name="Example: endIcon"
42 | <App>
43 | <NumberBox endIcon="email" />
44 | </App>
45 | ```
46 |
47 | It is possible to set the other adornments as well: [`endText`](#endtext), [`startIcon`](#starticon) and [`startText`](#starttext).
48 |
49 | ```xmlui-pg copy display name="Example: all adornments"
50 | <App>
51 | <NumberBox startIcon="hyperlink" startText="www." endIcon="email" endText=".com" />
52 | </App>
53 | ```
54 |
55 | ### `endText` [#endtext]
56 |
57 | This property sets an optional text to appear on the end (right side when the left-to-right direction is set) of the input.
58 |
59 | This string prop enables the display of a custom string on the right side (left-to-right display) of the input field.
60 |
61 | ```xmlui-pg copy display name="Example: endText"
62 | <App>
63 | <NumberBox endText=".com" />
64 | </App>
65 | ```
66 |
67 | It is possible to set the other adornments as well: [`endIcon`](#endicon), [`startIcon`](#starticon) and [`startText`](#starttext).
68 |
69 | ```xmlui-pg copy display name="Example: all adornments"
70 | <App>
71 | <NumberBox startIcon="hyperlink" startText="www." endIcon="email" endText=".com" />
72 | </App>
73 | ```
74 |
75 | ### `gap` [#gap]
76 |
77 | This property defines the gap between the adornments and the input area.
78 |
79 | ### `hasSpinBox` (default: true) [#hasspinbox-default-true]
80 |
81 | This boolean prop shows (`true`) or hides (`false`) the spinner buttons for the input field.
82 |
83 | ```xmlui-pg copy display name="Example: hasSpinBox"
84 | <App>
85 | <NumberBox hasSpinBox="true" initialValue="3" />
86 | <NumberBox hasSpinBox="false" initialValue="34" />
87 | </App>
88 | ```
89 |
90 | ### `initialValue` [#initialvalue]
91 |
92 | This property sets the component's initial value.
93 |
94 | The initial value displayed in the input field.
95 |
96 | ```xmlui-pg copy display name="Example: initialValue"
97 | <App>
98 | <NumberBox initialValue="123" />
99 | </App>
100 | ```
101 |
102 | ### `integersOnly` (default: false) [#integersonly-default-false]
103 |
104 | This boolean property signs whether the input field accepts integers only (`true`) or not (`false`).
105 |
106 | ```xmlui-pg copy display name="Example: integersOnly"
107 | <App>
108 | <NumberBox integersOnly="true" initialValue="42" />
109 | <NumberBox integersOnly="false" initialValue="{Math.PI}" />
110 | </App>
111 | ```
112 |
113 | ### `maxLength` [#maxlength]
114 |
115 | This property sets the maximum length of the input it accepts.
116 |
117 | ### `maxValue` (default: 999999999999999) [#maxvalue-default-999999999999999]
118 |
119 | The maximum value the input field allows. Can be a float or an integer if [`integersOnly`](#integersonly) is set to `false`, otherwise it can only be an integer.If not set, no maximum value check is done.
120 |
121 | The maximum value the input field allows.
122 | Can be a float or an integer if [`integersOnly`](#integersonly) is set to `false`,
123 | otherwise it can only be an integer.
124 |
125 | Try to enter a bigger value into the input field below than the maximum allowed.
126 |
127 | ```xmlui-pg copy display name="Example: maxValue"
128 | <App>
129 | <NumberBox maxValue="100" initialValue="99" />
130 | </App>
131 | ```
132 |
133 | ### `minValue` (default: -999999999999999) [#minvalue-default-999999999999999]
134 |
135 | The minimum value the input field allows. Can be a float or an integer if [`integersOnly`](#integersonly) is set to `false`, otherwise it can only be an integer.If not set, no minimum value check is done.
136 |
137 | Try to enter a bigger value into the input field below than the minimum allowed.
138 |
139 | ```xmlui-pg copy display name="Example: minValue"
140 | <App>
141 | <NumberBox minValue="-100" initialValue="-99" />
142 | </App>
143 | ```
144 |
145 | ### `placeholder` [#placeholder]
146 |
147 | An optional placeholder text that is visible in the input field when its empty.
148 |
149 | A placeholder text that is visible in the input field when its empty.
150 |
151 | ```xmlui-pg copy display name="Example: placeholder"
152 | <App>
153 | <NumberBox placeholder="This is a placeholder" />
154 | </App>
155 | ```
156 |
157 | ### `readOnly` (default: false) [#readonly-default-false]
158 |
159 | Set this property to `true` to disallow changing the component value.
160 |
161 | If true, the component's value cannot be modified with user interactions.
162 |
163 | ```xmlui-pg copy display name="Example: readOnly"
164 | <App>
165 | <NumberBox initialValue="123" readOnly="true" />
166 | </App>
167 | ```
168 |
169 | ### `required` (default: false) [#required-default-false]
170 |
171 | Set this property to `true` to indicate it must have a value before submitting the containing form.
172 |
173 | ### `spinnerDownIcon` [#spinnerdownicon]
174 |
175 | Allows setting an alternate icon displayed in the NumberBox spinner for decrementing values. You can change the default icon for all NumberBox instances with the "icon.spinnerDown:NumberBox" declaration in the app configuration file.
176 |
177 | ### `spinnerUpIcon` [#spinnerupicon]
178 |
179 | Allows setting an alternate icon displayed in the NumberBox spinner for incrementing values. You can change the default icon for all NumberBox instances with the "icon.spinnerUp:NumberBox" declaration in the app configuration file.
180 |
181 | ### `startIcon` [#starticon]
182 |
183 | This property sets an optional icon to appear at the start (left side when the left-to-right direction is set) of the input.
184 |
185 | This string prop enables the display of an icon on the left side (left-to-right display) of the input field by providing a valid [icon name]().
186 |
187 | ```xmlui-pg copy display name="Example: startIcon"
188 | <App>
189 | <NumberBox startIcon="hyperlink" />
190 | </App>
191 | ```
192 |
193 | It is possible to set the other adornments as well: [`endText`](#endtext), [`startIcon`](#starticon) and [`startText`](#starttext).
194 |
195 | ```xmlui-pg copy display name="Example: all adornments"
196 | <App>
197 | <NumberBox startIcon="hyperlink" startText="www." endIcon="email" endText=".com" />
198 | </App>
199 | ```
200 |
201 | ### `startText` [#starttext]
202 |
203 | This property sets an optional text to appear at the start (left side when the left-to-right direction is set) of the input.
204 |
205 | This string prop enables the display of a custom string on the left side (left-to-right display) of the input field.
206 |
207 | ```xmlui-pg copy display name="Example: startText"
208 | <App>
209 | <NumberBox startText="www." />
210 | </App>
211 | ```
212 |
213 | It is possible to set the other adornments as well: [`endIcon`](#endicon), [`startIcon`](#starticon) and [`endText`](#endtext).
214 |
215 | ```xmlui-pg copy display name="Example: all adornments"
216 | <App>
217 | <NumberBox startIcon="hyperlink" startText="www." endIcon="email" endText=".com" />
218 | </App>
219 | ```
220 |
221 | ### `step` (default: 1) [#step-default-1]
222 |
223 | This prop governs how big the step when clicking on the spinner of the field.
224 |
225 | The default stepping value is **1**.
226 |
227 | Note that only integers are allowed to be entered.
228 |
229 | ```xmlui-pg copy display name="Example: step"
230 | <App>
231 | <NumberBox initialValue="10" step="10" />
232 | </App>
233 | ```
234 |
235 | ### `validationStatus` (default: "none") [#validationstatus-default-none]
236 |
237 | This property allows you to set the validation status of the input component.
238 |
239 | Available values:
240 |
241 | | Value | Description |
242 | | --- | --- |
243 | | `valid` | Visual indicator for an input that is accepted |
244 | | `warning` | Visual indicator for an input that produced a warning |
245 | | `error` | Visual indicator for an input that produced an error |
246 |
247 | This prop is used to visually indicate status changes reacting to form field validation.
248 |
249 | | Value | Description |
250 | | :-------- | :---------------------------------------------------- |
251 | | `valid` | Visual indicator for an input that is accepted |
252 | | `warning` | Visual indicator for an input that produced a warning |
253 | | `error` | Visual indicator for an input that produced an error |
254 |
255 | ```xmlui-pg copy display name="Example: validationStatus"
256 | <App>
257 | <NumberBox />
258 | <NumberBox validationStatus="valid" />
259 | <NumberBox validationStatus="warning" />
260 | <NumberBox validationStatus="error" />
261 | </App>
262 | ```
263 |
264 | ### `zeroOrPositive` (default: false) [#zeroorpositive-default-false]
265 |
266 | This boolean property determines whether the input value can only be 0 or positive numbers (`true`) or also negative (`false`).
267 |
268 | This boolean property determines whether the input value can only be 0 or positive numbers (`true`) or also negative (`false`).
269 | By default, this property is set to `false`.
270 |
271 | ```xmlui-pg copy display name="Example: zeroOrPositive"
272 | <App>
273 | <NumberBox initialValue="123" zeroOrPositive="true" />
274 | </App>
275 | ```
276 |
277 | ## Events [#events]
278 |
279 | ### `didChange` [#didchange]
280 |
281 | This event is triggered when value of NumberBox has changed.
282 |
283 | This event is triggered after the user has changed the field value.
284 |
285 | Write in the input field and see how the `Text` underneath it is updated in parallel.
286 |
287 | ```xmlui-pg copy {2} display name="Example: didChange"
288 | <App var.field="0">
289 | <NumberBox initialValue="{field}" onDidChange="(val) => field = val" />
290 | <Text value="{field}" />
291 | </App>
292 | ```
293 |
294 | ### `gotFocus` [#gotfocus]
295 |
296 | This event is triggered when the NumberBox has received the focus.
297 |
298 | This event is triggered when the `NumberBox` receives focus. The following sample demonstrates this event.
299 |
300 | ```xmlui-pg
301 | ---app copy {3-4} display name="Example: gotFocus"
302 | <App var.focused="{false}">
303 | <NumberBox
304 | onGotFocus="focused = true"
305 | onLostFocus="focused = false" />
306 | <Text>The NumberBox is {focused ? '' : 'not'} focused</Text>
307 | </App>
308 | ---desc
309 | Click into the `NumberBox` (and then click the text below):
310 | ```
311 |
312 | ### `lostFocus` [#lostfocus]
313 |
314 | This event is triggered when the NumberBox has lost the focus.
315 |
316 | This event is triggered when the `NumberBox` loses focus.
317 |
318 | (See the example above)
319 |
320 | ## Exposed Methods [#exposed-methods]
321 |
322 | ### `focus` [#focus]
323 |
324 | This API focuses the input field of the `NumberBox`. You can use it to programmatically focus the field.
325 |
326 | **Signature**: `focus(): void`
327 |
328 | ### `setValue` [#setvalue]
329 |
330 | This API sets the value of the `NumberBox`. You can use it to programmatically change the value.
331 |
332 | **Signature**: `setValue(value: number | undefined): void`
333 |
334 | You can use this method to set the component's current value programmatically.
335 |
336 | ```xmlui-pg copy {3, 9, 12} display name="Example: value and setValue"
337 | <App>
338 | <NumberBox
339 | id="numberbox"
340 | readOnly="true"
341 | />
342 | <HStack>
343 | <Button
344 | label="Set to 100"
345 | onClick="numberbox.setValue(100)" />
346 | <Button
347 | label="Set to 0"
348 | onClick="numberbox.setValue(0)" />
349 | </HStack>
350 | </App>
351 | ```
352 |
353 | ### `value` [#value]
354 |
355 | This API retrieves the current value of the `NumberBox`. You can use it to get the value programmatically.
356 |
357 | **Signature**: `get value(): number | undefined`
358 |
359 | You can query this read-only API property to get the input component's current value.
360 |
361 | See an example in the `setValue` API method.
362 |
363 | ## Parts [#parts]
364 |
365 | The component has some parts that can be styled through layout properties and theme variables separately:
366 |
367 | - **`endAdornment`**: The adornment displayed at the end of the text box.
368 | - **`input`**: The text box input area.
369 | - **`label`**: The label displayed for the text box.
370 | - **`startAdornment`**: The adornment displayed at the start of the text box.
371 |
372 | ## Styling [#styling]
373 |
374 | ### Theme Variables [#theme-variables]
375 |
376 | | Variable | Default Value (Light) | Default Value (Dark) |
377 | | --- | --- | --- |
378 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--default | *none* | *none* |
379 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--default--focus | *none* | *none* |
380 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--default--hover | *none* | *none* |
381 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--disabled | *none* | *none* |
382 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--error | *none* | *none* |
383 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--error--focus | *none* | *none* |
384 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--error--hover | *none* | *none* |
385 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--success | *none* | *none* |
386 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--success--focus | *none* | *none* |
387 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--success--hover | *none* | *none* |
388 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--warning | *none* | *none* |
389 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--warning--focus | *none* | *none* |
390 | | [backgroundColor](../styles-and-themes/common-units/#color)-NumberBox--warning--hover | *none* | *none* |
391 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--default | *none* | *none* |
392 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--default--focus | *none* | *none* |
393 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--default--hover | *none* | *none* |
394 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--disabled | *none* | *none* |
395 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--error | *none* | *none* |
396 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--error--focus | *none* | *none* |
397 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--error--hover | *none* | *none* |
398 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--success | *none* | *none* |
399 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--success--focus | *none* | *none* |
400 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--success--hover | *none* | *none* |
401 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--warning | *none* | *none* |
402 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--warning--focus | *none* | *none* |
403 | | [borderColor](../styles-and-themes/common-units/#color)-NumberBox--warning--hover | *none* | *none* |
404 | | [borderRadius](../styles-and-themes/common-units/#border-rounding)-NumberBox--default | *none* | *none* |
405 | | [borderRadius](../styles-and-themes/common-units/#border-rounding)-NumberBox--error | *none* | *none* |
406 | | [borderRadius](../styles-and-themes/common-units/#border-rounding)-NumberBox--success | *none* | *none* |
407 | | [borderRadius](../styles-and-themes/common-units/#border-rounding)-NumberBox--warning | *none* | *none* |
408 | | [borderStyle](../styles-and-themes/common-units/#border-style)-NumberBox--default | *none* | *none* |
409 | | [borderStyle](../styles-and-themes/common-units/#border-style)-NumberBox--error | *none* | *none* |
410 | | [borderStyle](../styles-and-themes/common-units/#border-style)-NumberBox--success | *none* | *none* |
411 | | [borderStyle](../styles-and-themes/common-units/#border-style)-NumberBox--warning | *none* | *none* |
412 | | [borderWidth](../styles-and-themes/common-units/#size)-NumberBox--default | *none* | *none* |
413 | | [borderWidth](../styles-and-themes/common-units/#size)-NumberBox--error | *none* | *none* |
414 | | [borderWidth](../styles-and-themes/common-units/#size)-NumberBox--success | *none* | *none* |
415 | | [borderWidth](../styles-and-themes/common-units/#size)-NumberBox--warning | *none* | *none* |
416 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--default | *none* | *none* |
417 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--default--focus | *none* | *none* |
418 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--default--hover | *none* | *none* |
419 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--error | *none* | *none* |
420 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--error--focus | *none* | *none* |
421 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--error--hover | *none* | *none* |
422 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--success | *none* | *none* |
423 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--success--focus | *none* | *none* |
424 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--success--hover | *none* | *none* |
425 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--warning | *none* | *none* |
426 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--warning--focus | *none* | *none* |
427 | | [boxShadow](../styles-and-themes/common-units/#boxShadow)-NumberBox--warning--hover | *none* | *none* |
428 | | [color](../styles-and-themes/common-units/#color)-adornment-NumberBox--default | *none* | *none* |
429 | | [color](../styles-and-themes/common-units/#color)-adornment-NumberBox--error | *none* | *none* |
430 | | [color](../styles-and-themes/common-units/#color)-adornment-NumberBox--success | *none* | *none* |
431 | | [color](../styles-and-themes/common-units/#color)-adornment-NumberBox--warning | *none* | *none* |
432 | | [fontSize](../styles-and-themes/common-units/#size)-NumberBox--default | *none* | *none* |
433 | | [fontSize](../styles-and-themes/common-units/#size)-NumberBox--error | *none* | *none* |
434 | | [fontSize](../styles-and-themes/common-units/#size)-NumberBox--success | *none* | *none* |
435 | | [fontSize](../styles-and-themes/common-units/#size)-NumberBox--warning | *none* | *none* |
436 | | [fontSize](../styles-and-themes/common-units/#size)-placeholder-NumberBox--default | *none* | *none* |
437 | | [fontSize](../styles-and-themes/common-units/#size)-placeholder-NumberBox--error | *none* | *none* |
438 | | [fontSize](../styles-and-themes/common-units/#size)-placeholder-NumberBox--success | *none* | *none* |
439 | | [fontSize](../styles-and-themes/common-units/#size)-placeholder-NumberBox--warning | *none* | *none* |
440 | | [gap](../styles-and-themes/common-units/#size)-adornment-NumberBox | *none* | *none* |
441 | | [outlineColor](../styles-and-themes/common-units/#color)-NumberBox--default--focus | *none* | *none* |
442 | | [outlineColor](../styles-and-themes/common-units/#color)-NumberBox--error--focus | *none* | *none* |
443 | | [outlineColor](../styles-and-themes/common-units/#color)-NumberBox--success--focus | *none* | *none* |
444 | | [outlineColor](../styles-and-themes/common-units/#color)-NumberBox--warning--focus | *none* | *none* |
445 | | [outlineOffset](../styles-and-themes/common-units/#size)-NumberBox--default--focus | *none* | *none* |
446 | | [outlineOffset](../styles-and-themes/common-units/#size)-NumberBox--error--focus | *none* | *none* |
447 | | [outlineOffset](../styles-and-themes/common-units/#size)-NumberBox--success--focus | *none* | *none* |
448 | | [outlineOffset](../styles-and-themes/common-units/#size)-NumberBox--warning--focus | *none* | *none* |
449 | | [outlineStyle](../styles-and-themes/common-units/#border)-NumberBox--default--focus | *none* | *none* |
450 | | [outlineStyle](../styles-and-themes/common-units/#border)-NumberBox--error--focus | *none* | *none* |
451 | | [outlineStyle](../styles-and-themes/common-units/#border)-NumberBox--success--focus | *none* | *none* |
452 | | [outlineStyle](../styles-and-themes/common-units/#border)-NumberBox--warning--focus | *none* | *none* |
453 | | [outlineWidth](../styles-and-themes/common-units/#size)-NumberBox--default--focus | *none* | *none* |
454 | | [outlineWidth](../styles-and-themes/common-units/#size)-NumberBox--error--focus | *none* | *none* |
455 | | [outlineWidth](../styles-and-themes/common-units/#size)-NumberBox--success--focus | *none* | *none* |
456 | | [outlineWidth](../styles-and-themes/common-units/#size)-NumberBox--warning--focus | *none* | *none* |
457 | | [padding](../styles-and-themes/common-units/#size)-NumberBox | *none* | *none* |
458 | | [paddingBottom](../styles-and-themes/common-units/#size)-NumberBox | *none* | *none* |
459 | | [paddingHorizontal](../styles-and-themes/common-units/#size)-NumberBox | $space-2 | $space-2 |
460 | | [paddingLeft](../styles-and-themes/common-units/#size)-NumberBox | *none* | *none* |
461 | | [paddingRight](../styles-and-themes/common-units/#size)-NumberBox | *none* | *none* |
462 | | [paddingTop](../styles-and-themes/common-units/#size)-NumberBox | *none* | *none* |
463 | | [paddingVertical](../styles-and-themes/common-units/#size)-NumberBox | $space-2 | $space-2 |
464 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--default | *none* | *none* |
465 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--default--focus | *none* | *none* |
466 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--default--hover | *none* | *none* |
467 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--disabled | *none* | *none* |
468 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--error | *none* | *none* |
469 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--error--focus | *none* | *none* |
470 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--error--hover | *none* | *none* |
471 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--success | *none* | *none* |
472 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--success--focus | *none* | *none* |
473 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--success--hover | *none* | *none* |
474 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--warning | *none* | *none* |
475 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--warning--focus | *none* | *none* |
476 | | [textColor](../styles-and-themes/common-units/#color)-NumberBox--warning--hover | *none* | *none* |
477 | | [textColor](../styles-and-themes/common-units/#color)-placeholder-NumberBox--default | *none* | *none* |
478 | | [textColor](../styles-and-themes/common-units/#color)-placeholder-NumberBox--error | *none* | *none* |
479 | | [textColor](../styles-and-themes/common-units/#color)-placeholder-NumberBox--success | *none* | *none* |
480 | | [textColor](../styles-and-themes/common-units/#color)-placeholder-NumberBox--warning | *none* | *none* |
481 |
```