#
tokens: 59001/50000 1/1632 files (page 174/182)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 174 of 182. Use http://codebase.md/xmlui-org/xmlui/assets/img/bg-iphone-14-pro.jpg?lines=true&page={x} to view the full context.

# Directory Structure

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

# Files

--------------------------------------------------------------------------------
/xmlui/dev-docs/react-fundamentals.md:
--------------------------------------------------------------------------------

```markdown
   1 | # React Fundamentals
   2 | 
   3 | This document is a concise reference for React patterns and hooks used in XMLUI. It assumes you're familiar with [React basics](https://react.dev/learn) and provides practical guidance for reading and maintaining XMLUI source code.
   4 | 
   5 | ## React Hooks: Quick Overview
   6 | 
   7 | **What are hooks?** Functions that let you "hook into" React features from function components. They always start with `use` (e.g., `useState`, `useEffect`).
   8 | 
   9 | **Core hooks in XMLUI:**
  10 | - **`useState`** - Add local state to components
  11 | - **`useEffect`** - Run side effects (data fetching, subscriptions, DOM updates)
  12 | - **`useRef`** - Store mutable values that don't trigger re-renders
  13 | - **`useMemo`** - Cache expensive calculations
  14 | - **`useCallback`** - Cache function definitions
  15 | - **`useReducer`** - Manage complex state with reducer pattern
  16 | - **`useContext`** - Access context values from providers
  17 | 
  18 | **Two critical rules:**
  19 | 1. Only call hooks at the top level (not in loops, conditions, or nested functions)
  20 | 2. Only call hooks from React functions (components or custom hooks)
  21 | 
  22 | **Why?** React tracks hooks by call order. Breaking these rules causes state mismatches and bugs.
  23 | 
  24 | ## Component Rendering Lifecycle
  25 | 
  26 | React components re-render whenever their state or props change. Understanding this cycle prevents performance issues and unexpected behavior.
  27 | 
  28 | **The 5-Phase Render Cycle:**
  29 | 
  30 | 1. **Trigger** → Something requests a render:
  31 |    - Parent component re-renders
  32 |    - Props change
  33 |    - State changes (`useState`, `useReducer`)
  34 | 
  35 | 2. **Render** → React calls your component function, which returns JSX
  36 | 
  37 | 3. **Reconciliation** → React's diffing algorithm determines what changed in the virtual DOM
  38 | 
  39 | 4. **Commit** → React updates the actual DOM with minimal changes
  40 | 
  41 | 5. **Effects** → React runs effects in order:
  42 |    - `useLayoutEffect` (synchronous, blocks paint)
  43 |    - Browser paints the screen
  44 |    - `useEffect` (asynchronous, after paint)
  45 | 
  46 | **Key insight:** Re-rendering is cheap (just a function call), but DOM updates are expensive. React optimizes by batching and minimizing DOM changes.
  47 | 
  48 | **Common performance pitfalls:**
  49 | ```tsx
  50 | // ❌ WRONG - Parent re-renders cause all children to re-render
  51 | function Parent() {
  52 |   const [count, setCount] = useState(0);
  53 |   return (
  54 |     <div>
  55 |       <ExpensiveChild data={data} />  {/* Re-renders unnecessarily */}
  56 |       <button onClick={() => setCount(c => c + 1)}>Update</button>
  57 |     </div>
  58 |   );
  59 | }
  60 | 
  61 | // ✅ CORRECT - Memoize to prevent unnecessary re-renders
  62 | const MemoizedChild = React.memo(ExpensiveChild);
  63 | 
  64 | function Parent() {
  65 |   const [count, setCount] = useState(0);
  66 |   const data = useMemo(() => computeData(), []); // Stable reference
  67 |   return (
  68 |     <div>
  69 |       <MemoizedChild data={data} />  {/* Only re-renders when data changes */}
  70 |       <button onClick={() => setCount(c => c + 1)}>Update</button>
  71 |     </div>
  72 |   );
  73 | }
  74 | ```
  75 | 
  76 | ## Rules of Hooks
  77 | 
  78 | These rules are enforced by React and ESLint. Violating them causes hard-to-debug errors.
  79 | 
  80 | **Rule 1: Call hooks at the top level**
  81 | ```tsx
  82 | // ❌ WRONG - Conditional hook
  83 | function Bad({ show }: Props) {
  84 |   if (show) {
  85 |     const [value, setValue] = useState(""); // Hook order changes!
  86 |   }
  87 |   return <div>...</div>;
  88 | }
  89 | 
  90 | // ✅ CORRECT - Hook always called
  91 | function Good({ show }: Props) {
  92 |   const [value, setValue] = useState("");
  93 |   if (!show) return null;
  94 |   return <div>{value}</div>;
  95 | }
  96 | ```
  97 | 
  98 | **Rule 2: Only call from React functions**
  99 | ```tsx
 100 | // ❌ WRONG - Hook in regular function
 101 | function getUser() {
 102 |   const [user, setUser] = useState(null); // Not allowed!
 103 |   return user;
 104 | }
 105 | 
 106 | // ✅ CORRECT - Hook in component or custom hook
 107 | function useUser() {
 108 |   const [user, setUser] = useState(null);
 109 |   return user;
 110 | }
 111 | 
 112 | function Component() {
 113 |   const user = useUser(); // OK
 114 |   return <div>{user?.name}</div>;
 115 | }
 116 | ```
 117 | 
 118 | **Why these rules exist:** React stores hook state in a sequential array tied to each component instance. The array index depends on call order. Conditional hooks break this indexing, causing state to be assigned to the wrong hooks.
 119 | 
 120 | ---
 121 | 
 122 | ## React State Management Patterns
 123 | 
 124 | Fundamental patterns for managing state in React, from local component state to shared state across component trees.
 125 | 
 126 | ### `useState` - Local State
 127 | 
 128 | **Syntax:** `const [state, setState] = useState(initialValue)`
 129 | 
 130 | ```tsx
 131 | // Basic
 132 | const [count, setCount] = useState(0);
 133 | 
 134 | // Functional update (when new state depends on old)
 135 | setCount(prev => prev + 1);
 136 | 
 137 | // Lazy initialization (expensive initial state)
 138 | const [data, setData] = useState(() => expensiveComputation());
 139 | 
 140 | // Immutable updates
 141 | setUser(prev => ({ ...prev, name }));
 142 | setItems(prev => [...prev, newItem]);
 143 | ```
 144 | 
 145 | **Use when:** State is local, updates are simple, no complex transitions.  
 146 | **Consider alternatives:** Multiple components → Context, complex logic → useReducer.
 147 | 
 148 | ---
 149 | 
 150 | ### `useReducer` - Complex State Logic
 151 | 
 152 | **Syntax:** `const [state, dispatch] = useReducer(reducer, initialState)`
 153 | 
 154 | ```tsx
 155 | type Action = { type: 'increment' } | { type: 'decrement' } | { type: 'reset' };
 156 | 
 157 | function reducer(state: State, action: Action): State {
 158 |   switch (action.type) {
 159 |     case 'increment': return { count: state.count + 1 };
 160 |     case 'decrement': return { count: state.count - 1 };
 161 |     case 'reset': return { count: 0 };
 162 |     default: return state;
 163 |   }
 164 | }
 165 | 
 166 | const [state, dispatch] = useReducer(reducer, { count: 0 });
 167 | dispatch({ type: 'increment' });
 168 | ```
 169 | 
 170 | **With Immer (XMLUI pattern):**
 171 | ```tsx
 172 | import produce from 'immer';
 173 | 
 174 | const reducer = produce((draft, action) => {
 175 |   switch (action.type) {
 176 |     case 'ADD_TODO':
 177 |       draft.todos.push(action.payload); // Direct mutation
 178 |       break;
 179 |   }
 180 | });
 181 | ```
 182 | 
 183 | **Use when:** Multiple related state values, complex transitions, want to separate state logic.  
 184 | **Use useState when:** Simple independent values, straightforward updates.
 185 | 
 186 | ---
 187 | 
 188 | ### Context API - Avoid Prop Drilling
 189 | 
 190 | **Purpose:** Share state across component tree without passing props through every level.
 191 | 
 192 | **Pattern:** Create context → Provider component → Custom hook → Consume
 193 | 
 194 | ```tsx
 195 | // 1. Create context
 196 | const AuthContext = createContext<AuthContext | null>(null);
 197 | 
 198 | // 2. Custom hook with validation
 199 | function useAuth() {
 200 |   const context = useContext(AuthContext);
 201 |   if (!context) throw new Error('useAuth must be used within AuthProvider');
 202 |   return context;
 203 | }
 204 | 
 205 | // 3. Provider component
 206 | function AuthProvider({ children }: Props) {
 207 |   const [user, setUser] = useState<User | null>(null);
 208 |   
 209 |   const value = useMemo(() => ({
 210 |     user,
 211 |     login: async (creds: Credentials) => { /* ... */ },
 212 |     logout: () => setUser(null),
 213 |   }), [user]);
 214 |   
 215 |   return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
 216 | }
 217 | 
 218 | // 4. Consume anywhere in tree
 219 | function Component() {
 220 |   const { user, logout } = useAuth(); // No prop drilling!
 221 |   return <button onClick={logout}>{user.name}</button>;
 222 | }
 223 | ```
 224 | 
 225 | **XMLUI Example:**
 226 | ```tsx
 227 | // AppLayoutContext - Provides layout state to nested navigation
 228 | const AppLayoutContext = createContext<IAppLayoutContext | null>(null);
 229 | 
 230 | export const App = forwardRef(function App(props, ref) {
 231 |   const layoutContextValue = useMemo(() => ({
 232 |     layout,
 233 |     navPanelVisible,
 234 |     toggleDrawer,
 235 |   }), [layout, navPanelVisible, toggleDrawer]);
 236 |   
 237 |   return (
 238 |     <AppLayoutContext.Provider value={layoutContextValue}>
 239 |       {content}
 240 |     </AppLayoutContext.Provider>
 241 |   );
 242 | });
 243 | 
 244 | // NavLink accesses layout directly
 245 | export const NavLink = forwardRef(function NavLink(props, ref) {
 246 |   const { layout } = useAppLayoutContext();
 247 |   // No prop drilling!
 248 | });
 249 | ```
 250 | 
 251 | **Use when:** Many nested components need access, >3 levels of prop drilling, global state (theme, auth).  
 252 | **Don't use when:** 1-2 levels of nesting (props fine), high-frequency updates (re-renders all consumers).
 253 | 
 254 | **Performance tip:** Split contexts by update frequency - separate user/theme/settings contexts instead of one combined context.
 255 | 
 256 | ---
 257 | 
 258 | ### State Lifting
 259 | 
 260 | **Pattern:** Move state to common ancestor to share between siblings.
 261 | 
 262 | ```tsx
 263 | // ❌ WRONG - Siblings can't communicate
 264 | <Parent><InputA /><InputB /></Parent>
 265 | 
 266 | // ✅ CORRECT - Lift state to parent
 267 | function Parent() {
 268 |   const [value, setValue] = useState('');
 269 |   return (
 270 |     <>
 271 |       <InputA value={value} onChange={setValue} />
 272 |       <InputB value={value} />
 273 |     </>
 274 |   );
 275 | }
 276 | ```
 277 | 
 278 | **XMLUI Pattern:** Container-based state flows down automatically:
 279 | ```tsx
 280 | <Stack var.selectedId="{null}">
 281 |   <Button onClick={"{() => selectedId = 'item1'}" />
 282 |   <Display value="{selectedId}" />
 283 | </Stack>
 284 | ```
 285 | 
 286 | **Use when:** Siblings need to coordinate, parent orchestrates behavior.  
 287 | **Don't use when:** State only used by one component, excessive prop drilling (use context).
 288 | 
 289 | ---
 290 | 
 291 | ### Controlled vs Uncontrolled Components
 292 | 
 293 | **Controlled:** Parent manages state via `value` prop.
 294 | ```tsx
 295 | function Controlled({ value, onChange }: Props) {
 296 |   return <input value={value} onChange={e => onChange(e.target.value)} />;
 297 | }
 298 | ```
 299 | 
 300 | **Uncontrolled:** Component manages own state via `initialValue`.
 301 | ```tsx
 302 | function Uncontrolled({ initialValue = '', onDidChange }: Props) {
 303 |   const [value, setValue] = useState(initialValue);
 304 |   return <input value={value} onChange={e => { setValue(e.target.value); onDidChange?.(e.target.value); }} />;
 305 | }
 306 | ```
 307 | 
 308 | **Hybrid (XMLUI pattern):** Support both modes.
 309 | ```tsx
 310 | function Flexible({ value, initialValue = '', onDidChange }: Props) {
 311 |   const [localValue, setLocalValue] = useState(initialValue);
 312 |   
 313 |   useEffect(() => {
 314 |     if (value !== undefined) setLocalValue(value);
 315 |   }, [value]);
 316 |   
 317 |   const handleChange = (e) => {
 318 |     setLocalValue(e.target.value);
 319 |     onDidChange?.(e.target.value);
 320 |   };
 321 |   
 322 |   return <input value={localValue} onChange={handleChange} />;
 323 | }
 324 | ```
 325 | 
 326 | **Use controlled:** Validate/format input, value affects other UI, programmatic changes.  
 327 | **Use uncontrolled:** Simple forms (read on submit), performance critical.  
 328 | **Use hybrid:** Reusable component libraries.
 329 | 
 330 | ---
 331 | 
 332 | ### Compound Components
 333 | 
 334 | **Purpose:** Components work together as cohesive unit, sharing state via context.
 335 | 
 336 | ```tsx
 337 | const TabsContext = createContext<{
 338 |   activeTab: string;
 339 |   setActiveTab: (id: string) => void;
 340 | } | null>(null);
 341 | 
 342 | function Tabs({ children }: Props) {
 343 |   const [activeTab, setActiveTab] = useState('tab1');
 344 |   return (
 345 |     <TabsContext.Provider value={{ activeTab, setActiveTab }}>
 346 |       <div className="tabs">{children}</div>
 347 |     </TabsContext.Provider>
 348 |   );
 349 | }
 350 | 
 351 | function Tab({ id, children }: Props) {
 352 |   const { activeTab, setActiveTab } = useContext(TabsContext)!;
 353 |   return (
 354 |     <button
 355 |       className={activeTab === id ? 'active' : ''}
 356 |       onClick={() => setActiveTab(id)}
 357 |     >
 358 |       {children}
 359 |     </button>
 360 |   );
 361 | }
 362 | 
 363 | Tabs.Tab = Tab;
 364 | Tabs.Panel = TabPanel;
 365 | 
 366 | // Usage - Flexible composition
 367 | <Tabs>
 368 |   <Tabs.Tab id="tab1">First</Tabs.Tab>
 369 |   <Tabs.Tab id="tab2">Second</Tabs.Tab>
 370 |   <Tabs.Panel id="tab1">Content 1</Tabs.Panel>
 371 |   <Tabs.Panel id="tab2">Content 2</Tabs.Panel>
 372 | </Tabs>
 373 | ```
 374 | 
 375 | **Use when:** Tightly coupled components (tabs, accordion), need flexible composition, building libraries.  
 376 | **Don't use when:** Simple parent-child, no shared state, prop drilling is simple.
 377 | 
 378 | ---
 379 | 
 380 | ### Advanced Patterns
 381 | 
 382 | **Provider Composition:**
 383 | ```tsx
 384 | function AppProviders({ children }: Props) {
 385 |   return (
 386 |     <ThemeProvider>
 387 |       <AuthProvider>
 388 |         <RouterProvider>
 389 |           {children}
 390 |         </RouterProvider>
 391 |       </AuthProvider>
 392 |     </ThemeProvider>
 393 |   );
 394 | }
 395 | ```
 396 | 
 397 | **Async Initialization:**
 398 | ```tsx
 399 | function AuthProvider({ children }: Props) {
 400 |   const [user, setUser] = useState(null);
 401 |   const [loading, setLoading] = useState(true);
 402 |   
 403 |   useEffect(() => {
 404 |     checkAuth().then(user => { setUser(user); setLoading(false); });
 405 |   }, []);
 406 |   
 407 |   if (loading) return <LoadingScreen />;
 408 |   return <AuthContext.Provider value={{ user }}>{children}</AuthContext.Provider>;
 409 | }
 410 | ```
 411 | 
 412 | **Reducer with Immer (XMLUI):**
 413 | ```tsx
 414 | // StateContainer reducer
 415 | export function createContainerReducer(debugView: IDebugViewContext) {
 416 |   return produce((state: ContainerState, action: ContainerAction) => {
 417 |     switch (action.type) {
 418 |       case ContainerActionKind.COMPONENT_STATE_CHANGED:
 419 |         state[uid] = { ...state[uid], ...action.payload.state };
 420 |         break;
 421 |     }
 422 |   });
 423 | }
 424 | ```
 425 | 
 426 | ---
 427 | 
 428 | ## React Performance Optimization Patterns
 429 | 
 430 | This section covers React's performance optimization tools and patterns. **Always profile before optimizing**—premature optimization adds complexity without real benefits.
 431 | 
 432 | ### Core Optimization Hooks
 433 | 
 434 | #### `useMemo` - Computation Caching
 435 | 
 436 | Cache expensive calculations between renders.
 437 | 
 438 | ```tsx
 439 | const filtered = useMemo(() => 
 440 |   items.filter(item => item.includes(filter)), 
 441 |   [items, filter]
 442 | );
 443 | ```
 444 | 
 445 | **Use when:** Computation is expensive (>10ms), creating objects/arrays for memoized children, or calculations in dependency arrays.  
 446 | **Don't use when:** Computation is cheap (<1ms), result used only once, or component rarely re-renders.
 447 | 
 448 | #### `useCallback` - Function Caching
 449 | 
 450 | Cache function definitions to prevent child re-renders.
 451 | 
 452 | ```tsx
 453 | const handleClick = useCallback(() => {
 454 |   doSomething(value);
 455 | }, [value]);
 456 | ```
 457 | 
 458 | **Use when:** Passing callbacks to memoized children or to dependency arrays.  
 459 | **Don't use when:** Function isn't passed to memoized components or deps arrays.
 460 | 
 461 | **Note:** `useCallback(fn, deps)` is equivalent to `useMemo(() => fn, deps)`.
 462 | 
 463 | #### `useTransition` - Non-Urgent Updates
 464 | 
 465 | Mark state updates as low-priority to keep UI responsive.
 466 | 
 467 | ```tsx
 468 | const [isPending, startTransition] = useTransition();
 469 | 
 470 | startTransition(() => {
 471 |   setExpensiveState(newValue); // Won't block UI
 472 | });
 473 | ```
 474 | 
 475 | **Use when:** Updating expensive state that doesn't need immediate feedback (filtering large lists, complex calculations).
 476 | 
 477 | #### `memo` - Component Memoization
 478 | 
 479 | Prevent re-renders when props haven't changed.
 480 | 
 481 | ```tsx
 482 | const MemoChild = memo(function MemoChild({ data }: Props) {
 483 |   return <div>{data.value}</div>;
 484 | });
 485 | ```
 486 | 
 487 | **Use when:** Component renders frequently with same props, has expensive rendering, or is in large lists.  
 488 | **Don't use when:** Component rarely re-renders, props change every render, or rendering is cheap.
 489 | 
 490 | **Important:** `memo` only works if props are stable. Use `useMemo`/`useCallback` for object/function props.
 491 | 
 492 | ---
 493 | 
 494 | ### Memoization Strategy Pattern
 495 | 
 496 | **Principle:** `memo` + `useMemo` + `useCallback` work together. `memo` prevents re-renders, but only if props stay stable. Use `useMemo`/`useCallback` to keep props stable.
 497 | 
 498 | #### The Memoization Cascade
 499 | 
 500 | ```tsx
 501 | // ❌ ANTI-PATTERN - memo without stable props
 502 | const Child = memo(({ data, onClick }: Props) => <div onClick={onClick}>{data.value}</div>);
 503 | 
 504 | function Parent() {
 505 |   return <Child data={{ value: 123 }} onClick={() => {}} />; // New refs every render!
 506 | }
 507 | 
 508 | // ✅ CORRECT - memo with stable props
 509 | function Parent() {
 510 |   const data = useMemo(() => ({ value: 123 }), []);
 511 |   const onClick = useCallback(() => console.log('clicked'), []);
 512 |   return <Child data={data} onClick={onClick} />;
 513 | }
 514 | ```
 515 | 
 516 | #### Decision Tree
 517 | 
 518 | 1. **Performance problem?** No → Don't optimize. Yes → Step 2.
 519 | 2. **What's the cause?**
 520 |    - Parent re-renders often → Use `memo()` on child
 521 |    - Expensive computation → Use `useMemo()` on calculation  
 522 |    - New function props → Use `useCallback()` on function
 523 | 3. **Passing objects/arrays/functions to memoized component?** Yes → Memoize those too.
 524 | 
 525 | #### Common Patterns
 526 | 
 527 | ```tsx
 528 | // Pattern 1: Context values
 529 | const contextValue = useMemo(() => ({
 530 |   state,
 531 |   setState,
 532 |   isLoading: state.status === 'loading',
 533 | }), [state]);
 534 | 
 535 | // Pattern 2: Event handlers with deps
 536 | const handleSearch = useCallback(() => {
 537 |   if (query.length >= minLength) onSearch(query);
 538 | }, [query, minLength, onSearch]);
 539 | 
 540 | // Pattern 3: Expensive selectors
 541 | const filteredData = useMemo(() => {
 542 |   return data.filter(item => item.name.includes(filter)).sort((a, b) => a.name.localeCompare(b.name));
 543 | }, [data, filter]);
 544 | 
 545 | // Pattern 4: Derived state
 546 | const summary = useMemo(() => ({
 547 |   total: items.reduce((sum, item) => sum + item.price * item.quantity, 0),
 548 |   itemCount: items.reduce((sum, item) => sum + item.quantity, 0),
 549 | }), [items]);
 550 | ```
 551 | 
 552 | #### Anti-Patterns
 553 | 
 554 | ```tsx
 555 | // ❌ Over-memoization
 556 | const greeting = useMemo(() => `Hello, ${name}`, [name]); // Too simple!
 557 | 
 558 | // ❌ Incomplete chain
 559 | <MemoChild config={{ theme: 'dark' }} />; // New object defeats memo
 560 | 
 561 | // ❌ Unstable dependencies
 562 | useMemo(() => formatUser(user), [user]); // user object recreated every render
 563 | // ✅ Fix: useMemo(() => formatUser(user), [user.id, user.name]);
 564 | ```
 565 | 
 566 | #### Checklist
 567 | 
 568 | **✅ DO memoize:**
 569 | - Components rendering frequently with same props
 570 | - Expensive computations (>10ms)
 571 | - Objects/arrays/functions passed to memoized children
 572 | - Context values
 573 | 
 574 | **❌ DON'T memoize:**
 575 | - Cheap operations (<1ms)
 576 | - Values that change every render
 577 | - Without profiling first
 578 | 
 579 | ---
 580 | 
 581 | ### Virtualization Pattern
 582 | 
 583 | **Purpose:** Render only visible items in large lists by using "windowing." Instead of rendering 10,000 items, render only ~10 visible items.
 584 | 
 585 | **Libraries:** XMLUI uses two based on component needs:
 586 | - **virtua** (Tree, List) - Chat interfaces, reverse scrolling, auto-sizing, fixed-size lists
 587 | - **@tanstack/react-virtual** (Table) - Dynamic measurements, flexible
 588 | 
 589 | **Library Comparison:**
 590 | 
 591 | | Feature | virtua | @tanstack/react-virtual |
 592 | |---------|--------|------------------------|
 593 | | **Bundle Size** | ~6KB | ~4KB |
 594 | | **API** | Render props | Hooks |
 595 | | **Dynamic heights** | Automatic | Automatic |
 596 | | **Reverse scroll** | ✅ Built-in | Manual |
 597 | | **Auto-sizing** | ✅ Built-in | Manual |
 598 | | **XMLUI Usage** | Tree, List | Table |
 599 | 
 600 | **virtua Example (XMLUI List):**
 601 | 
 602 | ```tsx
 603 | import { Virtualizer } from 'virtua';
 604 | 
 605 | function ChatList({ messages }: Props) {
 606 |   return (
 607 |     <Virtualizer count={messages.length}>
 608 |       {(index) => {
 609 |         const msg = messages[index];
 610 |         return (
 611 |           <div key={msg.id}>
 612 |             <div>{msg.author}</div>
 613 |             <div>{msg.content}</div>
 614 |           </div>
 615 |         );
 616 |       }}
 617 |     </Virtualizer>
 618 |   );
 619 | }
 620 | ```
 621 | 
 622 | **@tanstack/react-virtual Example:**
 623 | 
 624 | ```tsx
 625 | import { useVirtualizer } from '@tanstack/react-virtual';
 626 | 
 627 | function DataTable({ rows }: Props) {
 628 |   const tableRef = useRef<HTMLDivElement>(null);
 629 |   
 630 |   const rowVirtualizer = useVirtualizer({
 631 |     count: rows.length,
 632 |     getScrollElement: () => tableRef.current,
 633 |     estimateSize: () => 30,
 634 |     overscan: 5,
 635 |   });
 636 |   
 637 |   return (
 638 |     <div ref={tableRef} style={{ height: '400px', overflow: 'auto' }}>
 639 |       {rowVirtualizer.getVirtualItems().map((virtualRow) => (
 640 |         <div
 641 |           key={virtualRow.index}
 642 |           ref={(el) => rowVirtualizer.measureElement(el)}
 643 |           style={{ transform: `translateY(${virtualRow.start}px)` }}
 644 |         >
 645 |           {rows[virtualRow.index].content}
 646 |         </div>
 647 |       ))}
 648 |     </div>
 649 |   );
 650 | }
 651 | ```
 652 | 
 653 | **Critical Rules:**
 654 | 1. **Memoize row components** - Use `React.memo()`
 655 | 2. **Apply transform/style** - Required for positioning (@tanstack)
 656 | 3. **Memoize data** - Prevent row re-renders
 657 | 4. **Handle scroll container** - Each library handles sizing differently
 658 | 
 659 | **Performance Impact:**
 660 | 
 661 | | Items | Normal | Virtualized | Improvement |
 662 | |-------|--------|-------------|-------------|
 663 | | 100 | 50ms | 10ms | 5x faster |
 664 | | 1,000 | 500ms | 10ms | 50x faster |
 665 | | 10,000 | 5s | 10ms | 500x faster |
 666 | 
 667 | **When to Use:**
 668 | - ✅ >100 items
 669 | - ✅ Uniform item sizes
 670 | - ✅ Scrollable datasets
 671 | - ❌ <100 items (overhead not worth it)
 672 | - ❌ Already paginated
 673 | - ❌ Complex/unpredictable heights
 674 | 
 675 | ---
 676 | 
 677 | ### Rate Limiting: Debouncing and Throttling
 678 | 
 679 | **Purpose:** Control the frequency of expensive operations during high-frequency events (user input, scrolling, resizing).
 680 | 
 681 | **Key Difference:**
 682 | - **Debouncing**: Wait until activity **stops** (search, autosave)
 683 | - **Throttling**: Execute at **regular intervals** during activity (scroll, mousemove)
 684 | 
 685 | ```tsx
 686 | // User types "search" continuously
 687 | 
 688 | // DEBOUNCING: Executes ONCE after user stops typing
 689 | // Timeline: [type...type...type...STOP] → Execute
 690 | 
 691 | // THROTTLING: Executes EVERY 200ms while typing  
 692 | // Timeline: Execute → [200ms] → Execute → [200ms] → Execute...
 693 | ```
 694 | 
 695 | #### Debouncing Solutions
 696 | 
 697 | **1. useDeferredValue (React 18+) - Recommended**
 698 | 
 699 | ```tsx
 700 | function Search() {
 701 |   const [query, setQuery] = useState('');
 702 |   const deferredQuery = useDeferredValue(query);
 703 |   
 704 |   const results = useMemo(() => {
 705 |     if (deferredQuery.length < 2) return [];
 706 |     return performSearch(deferredQuery);
 707 |   }, [deferredQuery]);
 708 |   
 709 |   return (
 710 |     <>
 711 |       <input value={query} onChange={e => setQuery(e.target.value)} />
 712 |       <ResultsList results={results} />
 713 |     </>
 714 |   );
 715 | }
 716 | ```
 717 | 
 718 | **2. Custom useDebounce Hook**
 719 | 
 720 | ```tsx
 721 | function useDebounce<T>(value: T, delay: number = 500): T {
 722 |   const [debouncedValue, setDebouncedValue] = useState<T>(value);
 723 |   
 724 |   useEffect(() => {
 725 |     const timer = setTimeout(() => setDebouncedValue(value), delay);
 726 |     return () => clearTimeout(timer);
 727 |   }, [value, delay]);
 728 |   
 729 |   return debouncedValue;
 730 | }
 731 | 
 732 | // Usage
 733 | const debouncedQuery = useDebounce(query, 300);
 734 | ```
 735 | 
 736 | **3. Lodash debounce**
 737 | 
 738 | ```tsx
 739 | const debouncedSave = useMemo(
 740 |   () => debounce((text: string) => saveToServer(text), 1000),
 741 |   []
 742 | );
 743 | 
 744 | useEffect(() => {
 745 |   return () => debouncedSave.cancel();
 746 | }, [debouncedSave]);
 747 | ```
 748 | 
 749 | #### Throttling Solutions
 750 | 
 751 | **1. Custom useThrottle Hook**
 752 | 
 753 | ```tsx
 754 | function useThrottle<T extends (...args: any[]) => any>(
 755 |   callback: T,
 756 |   delay: number = 200
 757 | ): T {
 758 |   const lastRun = useRef(Date.now());
 759 |   
 760 |   return useCallback((...args: Parameters<T>) => {
 761 |     const now = Date.now();
 762 |     if (now - lastRun.current >= delay) {
 763 |       lastRun.current = now;
 764 |       return callback(...args);
 765 |     }
 766 |   }, [callback, delay]) as T;
 767 | }
 768 | 
 769 | // Usage
 770 | const handleScroll = useThrottle(() => {
 771 |   setScrollPos(window.scrollY);
 772 | }, 200);
 773 | ```
 774 | 
 775 | **2. Lodash throttle**
 776 | 
 777 | ```tsx
 778 | const throttledScroll = useMemo(
 779 |   () => throttle(() => {
 780 |     updateScrollPosition();
 781 |   }, 200, {
 782 |     leading: true,   // Execute on first call
 783 |     trailing: true   // Execute after interval ends
 784 |   }),
 785 |   []
 786 | );
 787 | 
 788 | useEffect(() => {
 789 |   return () => throttledScroll.cancel();
 790 | }, [throttledScroll]);
 791 | ```
 792 | 
 793 | #### XMLUI Examples
 794 | 
 795 | **Debounced Search (Search.tsx):**
 796 | ```tsx
 797 | function Search({ data, limit }: Props) {
 798 |   const [inputValue, setInputValue] = useState("");
 799 |   const debouncedValue = useDeferredValue(inputValue);
 800 |   
 801 |   const results = useMemo(() => {
 802 |     if (debouncedValue.length <= 1) return [];
 803 |     return fuse.search(debouncedValue, { limit });
 804 |   }, [debouncedValue, limit]);
 805 |   
 806 |   return (
 807 |     <>
 808 |       <input value={inputValue} onChange={e => setInputValue(e.target.value)} />
 809 |       <SearchResults results={results} />
 810 |     </>
 811 |   );
 812 | }
 813 | ```
 814 | 
 815 | **Throttled Change Listener (ChangeListenerNative.tsx):**
 816 | ```tsx
 817 | function ChangeListener({ listenTo, onChange, throttleWaitInMs = 0 }: Props) {
 818 |   const throttledOnChange = useMemo(() => {
 819 |     if (throttleWaitInMs !== 0 && onChange) {
 820 |       return throttle(onChange, throttleWaitInMs, { leading: true });
 821 |     }
 822 |     return onChange;
 823 |   }, [onChange, throttleWaitInMs]);
 824 |   
 825 |   useEffect(() => {
 826 |     if (throttledOnChange) {
 827 |       throttledOnChange({ prevValue, newValue: listenTo });
 828 |     }
 829 |   }, [listenTo, throttledOnChange]);
 830 | }
 831 | ```
 832 | 
 833 | **Async Throttle for Validation (misc.ts):**
 834 | ```tsx
 835 | function asyncThrottle<F extends (...args: any[]) => Promise<any>>(
 836 |   func: F,
 837 |   wait?: number,
 838 |   options?: ThrottleSettings
 839 | ) {
 840 |   const throttled = throttle(
 841 |     (resolve, reject, args: Parameters<F>) => {
 842 |       void func(...args).then(resolve).catch(reject);
 843 |     },
 844 |     wait,
 845 |     options
 846 |   );
 847 |   
 848 |   return (...args: Parameters<F>): ReturnType<F> =>
 849 |     new Promise((resolve, reject) => {
 850 |       throttled(resolve, reject, args);
 851 |     }) as ReturnType<F>;
 852 | }
 853 | ```
 854 | 
 855 | #### Decision Guide
 856 | 
 857 | | Scenario | Solution | Timing |
 858 | |----------|----------|--------|
 859 | | Search input | Debounce | 300ms |
 860 | | Form validation | Debounce | 500ms |
 861 | | Autosave | Debounce | 1000ms |
 862 | | Scroll position | Throttle | 100-200ms |
 863 | | Window resize | Throttle | 200-300ms |
 864 | | Mouse tracking | Throttle | 50-100ms |
 865 | | API rate limiting | Throttle | 500-1000ms |
 866 | 
 867 | #### Performance Impact
 868 | 
 869 | | Operation | Without | With (300ms) | Improvement |
 870 | |-----------|---------|--------------|-------------|
 871 | | Search (6 chars typed) | 6 API calls | 1 API call | 83% reduction |
 872 | | Scroll (1s) | ~60 events | 5 events | 92% reduction |
 873 | | Window resize | ~30 events | 5 events | 83% reduction |
 874 | 
 875 | #### Critical Rules
 876 | 
 877 | **1. Always memoize** rate-limited functions:
 878 | ```tsx
 879 | // ❌ WRONG - Creates new function every render
 880 | const handle = debounce(() => search(), 500);
 881 | 
 882 | // ✅ CORRECT - Memoized
 883 | const handle = useMemo(() => debounce(() => search(), 500), []);
 884 | ```
 885 | 
 886 | **2. Always cleanup**:
 887 | ```tsx
 888 | useEffect(() => {
 889 |   return () => debouncedFn.cancel();
 890 | }, [debouncedFn]);
 891 | ```
 892 | 
 893 | **3. Don't rate-limit UI state** - only side effects:
 894 | ```tsx
 895 | // ❌ WRONG - UI lags
 896 | const handleChange = debounce((e) => setValue(e.target.value), 300);
 897 | 
 898 | // ✅ CORRECT - Immediate UI, debounced side effect
 899 | const handleChange = (e) => {
 900 |   setValue(e.target.value); // Instant
 901 |   debouncedSearch(e.target.value); // Delayed
 902 | };
 903 | ```
 904 | 
 905 | **4. Choose appropriate delays**:
 906 | - Search: 300ms
 907 | - Autosave: 1000ms  
 908 | - Scroll/resize: 100-200ms
 909 | - Mousemove: 50ms
 910 | 
 911 | #### When to Use
 912 | 
 913 | **Debouncing:**
 914 | - ✅ Search, autosave, validation
 915 | - ✅ Wait for user to finish action
 916 | - ❌ Don't use for immediate feedback
 917 | 
 918 | **Throttling:**
 919 | - ✅ Scroll, resize, mousemove
 920 | - ✅ Execute during continuous activity
 921 | - ❌ Don't use when only final value matters
 922 | 
 923 | #### Resources
 924 | 
 925 | - [useDeferredValue](https://react.dev/reference/react/useDeferredValue) - React 18 docs
 926 | - [lodash.debounce](https://lodash.com/docs/#debounce) - Debounce docs
 927 | - [lodash.throttle](https://lodash.com/docs/#throttle) - Throttle docs
 928 | - [XMLUI Search](packages/xmlui-search/src/Search.tsx) - Production example
 929 | 
 930 | ---
 931 | 
 932 | ## React Event Handling Patterns
 933 | 
 934 | Patterns for handling user interactions efficiently and correctly in React applications.
 935 | 
 936 | ### Event Delegation Pattern
 937 | 
 938 | **Purpose:** Handle events for multiple children at parent level instead of attaching handlers to each child.
 939 | 
 940 | **Benefits:**
 941 | - Fewer event listeners (better memory usage)
 942 | - Works with dynamically added/removed children
 943 | - Simplifies event handler management
 944 | 
 945 | ```tsx
 946 | // ❌ ANTI-PATTERN - Handler on every item
 947 | function List({ items }: Props) {
 948 |   return (
 949 |     <ul>
 950 |       {items.map(item => (
 951 |         <li key={item.id} onClick={() => handleClick(item.id)}>
 952 |           {item.name}
 953 |         </li>
 954 |       ))}
 955 |     </ul>
 956 |   );
 957 | }
 958 | 
 959 | // ✅ CORRECT - Single handler on parent
 960 | function List({ items }: Props) {
 961 |   const handleClick = (e: React.MouseEvent<HTMLUListElement>) => {
 962 |     const target = e.target as HTMLElement;
 963 |     const li = target.closest('li');
 964 |     if (li) {
 965 |       const itemId = li.dataset.id;
 966 |       console.log('Clicked item:', itemId);
 967 |     }
 968 |   };
 969 |   
 970 |   return (
 971 |     <ul onClick={handleClick}>
 972 |       {items.map(item => (
 973 |         <li key={item.id} data-id={item.id}>
 974 |           {item.name}
 975 |         </li>
 976 |       ))}
 977 |     </ul>
 978 |   );
 979 | }
 980 | ```
 981 | 
 982 | **XMLUI Example (Tree component):**
 983 | ```tsx
 984 | function Tree({ items }: Props) {
 985 |   // Single click handler for entire tree
 986 |   const handleTreeClick = useCallback((e: React.MouseEvent) => {
 987 |     const target = e.target as HTMLElement;
 988 |     const treeItem = target.closest('[data-tree-item]');
 989 |     
 990 |     if (treeItem) {
 991 |       const itemId = treeItem.getAttribute('data-item-id');
 992 |       const action = target.getAttribute('data-action');
 993 |       
 994 |       if (action === 'expand') {
 995 |         toggleExpand(itemId);
 996 |       } else if (action === 'select') {
 997 |         selectItem(itemId);
 998 |       }
 999 |     }
1000 |   }, [toggleExpand, selectItem]);
1001 |   
1002 |   return (
1003 |     <div className="tree" onClick={handleTreeClick}>
1004 |       {renderTreeItems(items)}
1005 |     </div>
1006 |   );
1007 | }
1008 | ```
1009 | 
1010 | **When to use:**
1011 | - Lists with many items (>50)
1012 | - Dynamic children (added/removed frequently)
1013 | - Multiple event types on same children
1014 | - Performance-critical rendering
1015 | 
1016 | **When NOT to use:**
1017 | - Few items (<10) - overhead not worth it
1018 | - Need precise event target info
1019 | - Event handler logic is complex per-item
1020 | 
1021 | ---
1022 | 
1023 | ### Synthetic Event Pattern
1024 | 
1025 | **Purpose:** React wraps native browser events in `SyntheticEvent` for cross-browser consistency.
1026 | 
1027 | **Key differences from native events:**
1028 | 
1029 | | Feature | Native Event | Synthetic Event |
1030 | |---------|-------------|-----------------|
1031 | | **Type** | Browser-specific | Unified React type |
1032 | | **Pooling (React 16)** | No | Yes (reused) |
1033 | | **Pooling (React 17+)** | No | No (deprecated) |
1034 | | **Properties** | Browser-specific | Normalized |
1035 | | **Access after handler** | ✅ Always available | ⚠️ Nullified (React 16 only) |
1036 | 
1037 | **Basic usage:**
1038 | ```tsx
1039 | function Input() {
1040 |   const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
1041 |     // e is SyntheticEvent, not native Event
1042 |     console.log(e.target.value); // ✅ Works
1043 |     console.log(e.currentTarget); // ✅ Works
1044 |     
1045 |     // Access native event if needed
1046 |     const nativeEvent = e.nativeEvent;
1047 |   };
1048 |   
1049 |   return <input onChange={handleChange} />;
1050 | }
1051 | ```
1052 | 
1053 | **Event pooling (React 16 only):**
1054 | ```tsx
1055 | // ❌ WRONG - Async access (React 16)
1056 | function Bad() {
1057 |   const handleClick = (e: React.MouseEvent) => {
1058 |     setTimeout(() => {
1059 |       console.log(e.target); // null in React 16!
1060 |     }, 1000);
1061 |   };
1062 |   return <button onClick={handleClick}>Click</button>;
1063 | }
1064 | 
1065 | // ✅ CORRECT - Persist event (React 16)
1066 | function Good() {
1067 |   const handleClick = (e: React.MouseEvent) => {
1068 |     e.persist(); // Keep event alive
1069 |     setTimeout(() => {
1070 |       console.log(e.target); // ✅ Works
1071 |     }, 1000);
1072 |   };
1073 |   return <button onClick={handleClick}>Click</button>;
1074 | }
1075 | 
1076 | // ✅ BETTER - Extract values (React 16 & 17+)
1077 | function Better() {
1078 |   const handleClick = (e: React.MouseEvent) => {
1079 |     const target = e.target; // Capture immediately
1080 |     setTimeout(() => {
1081 |       console.log(target); // ✅ Works in all versions
1082 |     }, 1000);
1083 |   };
1084 |   return <button onClick={handleClick}>Click</button>;
1085 | }
1086 | ```
1087 | 
1088 | **Note:** React 17+ removed event pooling, so `e.persist()` is no longer needed.
1089 | 
1090 | **Common event types:**
1091 | ```tsx
1092 | // Mouse events
1093 | const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {};
1094 | const handleDoubleClick = (e: React.MouseEvent) => {};
1095 | 
1096 | // Keyboard events
1097 | const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
1098 |   if (e.key === 'Enter') submitForm();
1099 | };
1100 | 
1101 | // Form events
1102 | const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {};
1103 | const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
1104 |   e.preventDefault();
1105 | };
1106 | 
1107 | // Focus events
1108 | const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => {};
1109 | const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {};
1110 | 
1111 | // Clipboard events
1112 | const handleCopy = (e: React.ClipboardEvent) => {};
1113 | const handlePaste = (e: React.ClipboardEvent) => {
1114 |   const text = e.clipboardData.getData('text');
1115 | };
1116 | 
1117 | // Drag events
1118 | const handleDragStart = (e: React.DragEvent) => {};
1119 | const handleDrop = (e: React.DragEvent) => {
1120 |   e.preventDefault();
1121 |   const data = e.dataTransfer.getData('text');
1122 | };
1123 | ```
1124 | 
1125 | **Accessing native event:**
1126 | ```tsx
1127 | function Component() {
1128 |   const handleClick = (e: React.MouseEvent) => {
1129 |     // React synthetic event
1130 |     console.log(e.currentTarget); // Element handler is attached to
1131 |     console.log(e.target); // Element that triggered event
1132 |     
1133 |     // Native browser event
1134 |     const nativeEvent = e.nativeEvent;
1135 |     console.log(nativeEvent); // MouseEvent object
1136 |   };
1137 |   
1138 |   return <button onClick={handleClick}>Click</button>;
1139 | }
1140 | ```
1141 | 
1142 | ---
1143 | 
1144 | ### Event Callback Composition Pattern
1145 | 
1146 | **Purpose:** Combine multiple event handlers into a single handler, useful for library components that accept user callbacks.
1147 | 
1148 | **Pattern 1: Sequential execution**
1149 | ```tsx
1150 | function composeHandlers<E>(...handlers: Array<((e: E) => void) | undefined>) {
1151 |   return (event: E) => {
1152 |     handlers.forEach(handler => {
1153 |       if (handler) {
1154 |         handler(event);
1155 |       }
1156 |     });
1157 |   };
1158 | }
1159 | 
1160 | // Usage
1161 | function Button({ onClick, onClickInternal }: Props) {
1162 |   const handleClick = composeHandlers(onClickInternal, onClick);
1163 |   return <button onClick={handleClick}>Click</button>;
1164 | }
1165 | ```
1166 | 
1167 | **Pattern 2: Conditional execution (stop on preventDefault)**
1168 | ```tsx
1169 | function composeEventHandlers<E extends React.SyntheticEvent>(
1170 |   internalHandler?: (e: E) => void,
1171 |   externalHandler?: (e: E) => void
1172 | ) {
1173 |   return (event: E) => {
1174 |     internalHandler?.(event);
1175 |     
1176 |     // If internal handler called preventDefault, stop
1177 |     if (!event.defaultPrevented) {
1178 |       externalHandler?.(event);
1179 |     }
1180 |   };
1181 | }
1182 | 
1183 | // Usage - XMLUI pattern
1184 | function Select({ onChange, onDidChange }: Props) {
1185 |   const handleInternalChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
1186 |     // Internal logic (validation, state updates)
1187 |     validateValue(e.target.value);
1188 |     
1189 |     // Prevent external handler if validation fails
1190 |     if (!isValid) {
1191 |       e.preventDefault();
1192 |     }
1193 |   };
1194 |   
1195 |   const handleChange = composeEventHandlers(handleInternalChange, onChange);
1196 |   
1197 |   return <select onChange={handleChange}>...</select>;
1198 | }
1199 | ```
1200 | 
1201 | **Pattern 3: Merge handlers from props**
1202 | ```tsx
1203 | function mergeEventHandlers<T extends React.SyntheticEvent>(
1204 |   ours: ((e: T) => void) | undefined,
1205 |   theirs: ((e: T) => void) | undefined
1206 | ): ((e: T) => void) | undefined {
1207 |   if (!ours) return theirs;
1208 |   if (!theirs) return ours;
1209 |   
1210 |   return (event: T) => {
1211 |     ours(event);
1212 |     if (!event.defaultPrevented) {
1213 |       theirs(event);
1214 |     }
1215 |   };
1216 | }
1217 | 
1218 | // Usage - Wrapper component
1219 | function Wrapper({ children, onClick }: Props) {
1220 |   const internalClick = (e: React.MouseEvent) => {
1221 |     console.log('Wrapper clicked');
1222 |   };
1223 |   
1224 |   return cloneElement(children, {
1225 |     onClick: mergeEventHandlers(internalClick, children.props.onClick),
1226 |   });
1227 | }
1228 | ```
1229 | 
1230 | **XMLUI Example (Container component):**
1231 | ```tsx
1232 | function Container({ children, ...props }: Props, ref: Ref<HTMLElement>) {
1233 |   const renderedChild = renderChild(children);
1234 |   
1235 |   if (ref && renderedChild && isValidElement(renderedChild)) {
1236 |     // Merge event handlers from both Container and child
1237 |     const mergedProps = {
1238 |       ...renderedChild.props,
1239 |       onClick: composeEventHandlers(props.onClick, renderedChild.props.onClick),
1240 |       onKeyDown: composeEventHandlers(props.onKeyDown, renderedChild.props.onKeyDown),
1241 |       ref: composeRefs(ref, (renderedChild as any).ref),
1242 |     };
1243 |     
1244 |     return cloneElement(renderedChild, mergedProps);
1245 |   }
1246 |   
1247 |   return renderedChild;
1248 | }
1249 | ```
1250 | 
1251 | **Pattern 4: Callback with additional args**
1252 | ```tsx
1253 | function withArgs<E, T>(
1254 |   handler: ((e: E, ...args: T[]) => void) | undefined,
1255 |   ...args: T[]
1256 | ) {
1257 |   if (!handler) return undefined;
1258 |   
1259 |   return (event: E) => {
1260 |     handler(event, ...args);
1261 |   };
1262 | }
1263 | 
1264 | // Usage
1265 | function List({ items, onItemClick }: Props) {
1266 |   return (
1267 |     <ul>
1268 |       {items.map(item => (
1269 |         <li key={item.id} onClick={withArgs(onItemClick, item.id)}>
1270 |           {item.name}
1271 |         </li>
1272 |       ))}
1273 |     </ul>
1274 |   );
1275 | }
1276 | ```
1277 | 
1278 | **When to compose handlers:**
1279 | - Building reusable component libraries
1280 | - Wrapper components that add behavior
1281 | - Components with internal + external handlers
1282 | - Need to call parent handler conditionally
1283 | 
1284 | **Best practices:**
1285 | - Always check if handler exists before calling
1286 | - Respect `preventDefault()` and `stopPropagation()`
1287 | - Execute internal handlers first
1288 | - Document composition order clearly
1289 | 
1290 | ---
1291 | 
1292 | ## React Lifecycle and Effect Patterns
1293 | 
1294 | Patterns for managing side effects, synchronization, and component lifecycle in React applications.
1295 | 
1296 | ### `useEffect` - Side Effects and Lifecycle
1297 | 
1298 | **Purpose:** Run side effects after render (data fetching, subscriptions, DOM manipulation).
1299 | 
1300 | **Syntax:** `useEffect(() => { /* effect */ return () => { /* cleanup */ } }, [dependencies])`
1301 | 
1302 | **Basic usage:**
1303 | ```tsx
1304 | function UserProfile({ userId }: Props) {
1305 |   const [user, setUser] = useState(null);
1306 |   
1307 |   useEffect(() => {
1308 |     // Effect runs after render
1309 |     fetch(`/api/users/${userId}`)
1310 |       .then(res => res.json())
1311 |       .then(data => setUser(data));
1312 |   }, [userId]); // Re-run when userId changes
1313 |   
1314 |   return <div>{user?.name}</div>;
1315 | }
1316 | ```
1317 | 
1318 | **With async/await:**
1319 | ```tsx
1320 | useEffect(() => {
1321 |   // Can't make callback async directly, use IIFE
1322 |   (async () => {
1323 |     const res = await fetch(`/api/users/${userId}`);
1324 |     const data = await res.json();
1325 |     setUser(data);
1326 |   })();
1327 | }, [userId]);
1328 | ```
1329 | 
1330 | **Use when:** Data fetching, subscriptions, event listeners, DOM manipulation, integrating with non-React libraries.  
1331 | **Avoid when:** Computing derived values (use `useMemo`), handling events (use handlers), initializing state (use initializer).
1332 | 
1333 | ---
1334 | 
1335 | ### Effect Cleanup Pattern
1336 | 
1337 | **Purpose:** Properly clean up subscriptions, timers, and event listeners to prevent memory leaks.
1338 | 
1339 | **Pattern: Always return cleanup function for subscriptions**
1340 | ```tsx
1341 | function Chat({ roomId }: Props) {
1342 |   useEffect(() => {
1343 |     const connection = createConnection(roomId);
1344 |     connection.connect();
1345 |     
1346 |     // ✅ Cleanup runs before next effect and on unmount
1347 |     return () => {
1348 |       connection.disconnect();
1349 |     };
1350 |   }, [roomId]);
1351 |   
1352 |   return <div>Connected to {roomId}</div>;
1353 | }
1354 | ```
1355 | 
1356 | **Pattern: Cancel async operations**
1357 | ```tsx
1358 | function DataComponent({ url }: Props) {
1359 |   const [data, setData] = useState(null);
1360 |   
1361 |   useEffect(() => {
1362 |     let cancelled = false;
1363 |     
1364 |     fetch(url)
1365 |       .then(res => res.json())
1366 |       .then(data => {
1367 |         if (!cancelled) setData(data);
1368 |       });
1369 |     
1370 |     // ✅ Prevent state updates after unmount
1371 |     return () => { cancelled = true; };
1372 |   }, [url]);
1373 |   
1374 |   return <div>{JSON.stringify(data)}</div>;
1375 | }
1376 | ```
1377 | 
1378 | **Pattern: Remove event listeners**
1379 | ```tsx
1380 | function WindowSize() {
1381 |   const [size, setSize] = useState({ width: 0, height: 0 });
1382 |   
1383 |   useEffect(() => {
1384 |     const handleResize = () => {
1385 |       setSize({ width: window.innerWidth, height: window.innerHeight });
1386 |     };
1387 |     
1388 |     window.addEventListener('resize', handleResize);
1389 |     handleResize(); // Initial size
1390 |     
1391 |     // ✅ Always remove listeners
1392 |     return () => window.removeEventListener('resize', handleResize);
1393 |   }, []);
1394 |   
1395 |   return <div>{size.width} x {size.height}</div>;
1396 | }
1397 | ```
1398 | 
1399 | **Pattern: Clear timers and intervals**
1400 | ```tsx
1401 | function Timer() {
1402 |   const [count, setCount] = useState(0);
1403 |   
1404 |   useEffect(() => {
1405 |     const interval = setInterval(() => {
1406 |       setCount(c => c + 1);
1407 |     }, 1000);
1408 |     
1409 |     // ✅ Clear interval on unmount
1410 |     return () => clearInterval(interval);
1411 |   }, []);
1412 |   
1413 |   return <div>{count}s</div>;
1414 | }
1415 | ```
1416 | 
1417 | **Pattern: Unsubscribe from external stores**
1418 | ```tsx
1419 | function ExternalStore({ store }: Props) {
1420 |   const [value, setValue] = useState(store.getValue());
1421 |   
1422 |   useEffect(() => {
1423 |     const unsubscribe = store.subscribe(newValue => {
1424 |       setValue(newValue);
1425 |     });
1426 |     
1427 |     // ✅ Unsubscribe when component unmounts
1428 |     return unsubscribe;
1429 |   }, [store]);
1430 |   
1431 |   return <div>{value}</div>;
1432 | }
1433 | ```
1434 | 
1435 | **Critical rules:**
1436 | - Return cleanup for subscriptions, listeners, timers
1437 | - Use cancellation flags for async operations
1438 | - Cleanup runs before next effect and on unmount
1439 | - Don't forget to remove event listeners
1440 | 
1441 | ---
1442 | 
1443 | ### Effect Dependencies Pattern
1444 | 
1445 | **Purpose:** Correctly manage dependency arrays to avoid stale closures and unnecessary re-runs.
1446 | 
1447 | **Anti-pattern: Missing dependencies (stale closure bug)**
1448 | ```tsx
1449 | // ❌ WRONG - Stale closure
1450 | function Counter() {
1451 |   const [count, setCount] = useState(0);
1452 |   
1453 |   useEffect(() => {
1454 |     setInterval(() => {
1455 |       console.log(count); // Always logs 0!
1456 |     }, 1000);
1457 |   }, []); // Missing count
1458 |   
1459 |   return <button onClick={() => setCount(count + 1)}>Increment</button>;
1460 | }
1461 | 
1462 | // ✅ CORRECT - Use functional update
1463 | useEffect(() => {
1464 |   setInterval(() => {
1465 |     setCount(c => c + 1); // Uses latest value
1466 |   }, 1000);
1467 | }, []); // No dependencies needed
1468 | ```
1469 | 
1470 | **Anti-pattern: Object/array in dependencies**
1471 | ```tsx
1472 | // ❌ WRONG - Object recreated every render
1473 | function Component({ config }: Props) {
1474 |   useEffect(() => {
1475 |     fetchData(config);
1476 |   }, [config]); // Runs every render if config is new object
1477 | }
1478 | 
1479 | // ✅ CORRECT - Destructure primitive values
1480 | useEffect(() => {
1481 |   fetchData(config);
1482 | }, [config.id, config.filter]); // Only re-run when these change
1483 | ```
1484 | 
1485 | **Pattern: Empty array = run once on mount**
1486 | ```tsx
1487 | useEffect(() => {
1488 |   // Initialization logic
1489 |   initializeApp();
1490 |   
1491 |   return () => {
1492 |     // Cleanup on unmount
1493 |     cleanupApp();
1494 |   };
1495 | }, []); // Runs once on mount, cleanup on unmount
1496 | ```
1497 | 
1498 | **Pattern: No array = run after every render**
1499 | ```tsx
1500 | useEffect(() => {
1501 |   // Runs after every render (rarely needed)
1502 |   updateDocumentTitle(`Page - ${count}`);
1503 | }); // No dependency array
1504 | ```
1505 | 
1506 | **Pattern: Avoid callback dependencies with useRef**
1507 | ```tsx
1508 | function Component({ callback }: Props) {
1509 |   const callbackRef = useRef(callback);
1510 |   
1511 |   // Keep ref updated
1512 |   useEffect(() => {
1513 |     callbackRef.current = callback;
1514 |   }, [callback]);
1515 |   
1516 |   useEffect(() => {
1517 |     const interval = setInterval(() => {
1518 |       // ✅ Always uses latest callback
1519 |       callbackRef.current();
1520 |     }, 1000);
1521 |     
1522 |     return () => clearInterval(interval);
1523 |   }, []); // No callback in deps
1524 | }
1525 | ```
1526 | 
1527 | **Common mistakes:**
1528 | ```tsx
1529 | // ❌ Wrong - Missing dependencies
1530 | useEffect(() => {
1531 |   doSomething(prop); // prop not in deps
1532 | }, []);
1533 | 
1534 | // ❌ Wrong - Object identity
1535 | useEffect(() => {
1536 |   fetchData(user);
1537 | }, [user]); // user object changes every render
1538 | 
1539 | // ❌ Wrong - Function identity
1540 | useEffect(() => {
1541 |   callback();
1542 | }, [callback]); // callback recreated every render
1543 | 
1544 | // ✅ Correct - Destructure objects
1545 | useEffect(() => {
1546 |   fetchData({ id: user.id, name: user.name });
1547 | }, [user.id, user.name]);
1548 | 
1549 | // ✅ Correct - Memoize callbacks
1550 | const memoizedCallback = useCallback(callback, [dep]);
1551 | useEffect(() => {
1552 |   memoizedCallback();
1553 | }, [memoizedCallback]);
1554 | ```
1555 | 
1556 | **ESLint rule:** Always enable `react-hooks/exhaustive-deps` to catch dependency issues.
1557 | 
1558 | ---
1559 | 
1560 | ### Layout Effect Pattern
1561 | 
1562 | **Purpose:** Run effects synchronously after DOM mutations but before browser paint to prevent visual flickering.
1563 | 
1564 | **When to use `useLayoutEffect`:**
1565 | 
1566 | **Pattern: DOM measurements before paint**
1567 | ```tsx
1568 | function Tooltip() {
1569 |   const [position, setPosition] = useState({ x: 0, y: 0 });
1570 |   const ref = useRef<HTMLDivElement>(null);
1571 |   
1572 |   // ✅ CORRECT - Measure before paint
1573 |   useLayoutEffect(() => {
1574 |     if (ref.current) {
1575 |       const rect = ref.current.getBoundingClientRect();
1576 |       setPosition({
1577 |         x: rect.left + rect.width / 2,
1578 |         y: rect.top - 10,
1579 |       });
1580 |     }
1581 |   }, []);
1582 |   
1583 |   return <div ref={ref} style={{ left: position.x, top: position.y }}>Tooltip</div>;
1584 | }
1585 | 
1586 | // ❌ WRONG - useEffect causes visible flicker
1587 | useEffect(() => {
1588 |   // DOM measurements happen AFTER paint
1589 |   // User sees element jump from old to new position
1590 | }, []);
1591 | ```
1592 | 
1593 | **Pattern: Synchronize scroll position**
1594 | ```tsx
1595 | function ScrollSync({ targetRef }: Props) {
1596 |   useLayoutEffect(() => {
1597 |     if (targetRef.current) {
1598 |       // ✅ Scroll before paint, no flicker
1599 |       targetRef.current.scrollTop = savedPosition;
1600 |     }
1601 |   }, [targetRef, savedPosition]);
1602 | }
1603 | ```
1604 | 
1605 | **Pattern: Prevent layout shift**
1606 | ```tsx
1607 | function AutoResizeTextarea({ value }: Props) {
1608 |   const ref = useRef<HTMLTextAreaElement>(null);
1609 |   
1610 |   useLayoutEffect(() => {
1611 |     if (ref.current) {
1612 |       // ✅ Adjust height before paint
1613 |       ref.current.style.height = 'auto';
1614 |       ref.current.style.height = `${ref.current.scrollHeight}px`;
1615 |     }
1616 |   }, [value]);
1617 |   
1618 |   return <textarea ref={ref} value={value} />;
1619 | }
1620 | ```
1621 | 
1622 | **Pattern: Third-party DOM library integration**
1623 | ```tsx
1624 | function Chart({ data }: Props) {
1625 |   const containerRef = useRef<HTMLDivElement>(null);
1626 |   
1627 |   useLayoutEffect(() => {
1628 |     if (containerRef.current) {
1629 |       // ✅ Initialize library before paint
1630 |       const chart = new ChartLibrary(containerRef.current);
1631 |       chart.render(data);
1632 |       
1633 |       return () => chart.destroy();
1634 |     }
1635 |   }, [data]);
1636 |   
1637 |   return <div ref={containerRef} />;
1638 | }
1639 | ```
1640 | 
1641 | **Comparison: useEffect vs useLayoutEffect**
1642 | 
1643 | | Aspect | `useEffect` | `useLayoutEffect` |
1644 | |--------|------------|-------------------|
1645 | | **Timing** | After paint (async) | Before paint (sync) |
1646 | | **Blocks rendering** | ❌ No | ✅ Yes |
1647 | | **Use for** | Data fetching, subscriptions | DOM measurements, preventing flicker |
1648 | | **Performance** | Better (non-blocking) | Worse (blocks paint) |
1649 | | **SSR** | ✅ Works | ⚠️ Warning (no DOM on server) |
1650 | 
1651 | **When to use each:**
1652 | - **useEffect**: 99% of cases - data fetching, subscriptions, analytics
1653 | - **useLayoutEffect**: DOM measurements, scroll sync, preventing visual flicker
1654 | 
1655 | **Warning:** `useLayoutEffect` blocks visual updates. Only use when you need synchronous DOM access before paint.
1656 | 
1657 | **SSR consideration:**
1658 | ```tsx
1659 | // ⚠️ useLayoutEffect doesn't run on server
1660 | useLayoutEffect(() => {
1661 |   // This code only runs in browser
1662 |   measureDOM();
1663 | }, []);
1664 | 
1665 | // ✅ Better: Use useEffect for SSR-compatible code
1666 | useEffect(() => {
1667 |   measureDOM();
1668 | }, []);
1669 | ```
1670 | 
1671 | ---
1672 | 
1673 | ### Insertion Effect Pattern
1674 | 
1675 | **Purpose:** Insert styles into DOM before layout effects run. Used by CSS-in-JS libraries.
1676 | 
1677 | **Syntax:** `useInsertionEffect(() => { /* insert styles */ }, [dependencies])`
1678 | 
1679 | **Effect execution order:**
1680 | 1. `useInsertionEffect` - Insert styles
1681 | 2. `useLayoutEffect` - Measure layout (reads styles)
1682 | 3. Browser paints
1683 | 4. `useEffect` - Other side effects
1684 | 
1685 | **Pattern: CSS-in-JS style injection**
1686 | ```tsx
1687 | function useCSS(rule: string) {
1688 |   useInsertionEffect(() => {
1689 |     // ✅ Inject styles before layout reads
1690 |     const style = document.createElement('style');
1691 |     style.textContent = rule;
1692 |     document.head.appendChild(style);
1693 |     
1694 |     return () => document.head.removeChild(style);
1695 |   }, [rule]);
1696 | }
1697 | 
1698 | // Usage
1699 | function Button({ color }: Props) {
1700 |   useCSS(`
1701 |     .button-${color} {
1702 |       background: ${color};
1703 |       border: 1px solid ${darken(color)};
1704 |     }
1705 |   `);
1706 |   
1707 |   return <button className={`button-${color}`}>Click</button>;
1708 | }
1709 | ```
1710 | 
1711 | **Pattern: Dynamic theme injection (XMLUI)**
1712 | ```tsx
1713 | function ThemeProvider({ theme, children }: Props) {
1714 |   useInsertionEffect(() => {
1715 |     // ✅ Insert theme CSS before components measure
1716 |     const styleElement = document.createElement('style');
1717 |     styleElement.id = 'theme-styles';
1718 |     styleElement.textContent = generateThemeCSS(theme);
1719 |     document.head.appendChild(styleElement);
1720 |     
1721 |     return () => {
1722 |       document.getElementById('theme-styles')?.remove();
1723 |     };
1724 |   }, [theme]);
1725 |   
1726 |   return children;
1727 | }
1728 | ```
1729 | 
1730 | **Pattern: Critical CSS injection**
1731 | ```tsx
1732 | function useCriticalCSS(css: string) {
1733 |   useInsertionEffect(() => {
1734 |     // ✅ Inject before any layout calculations
1735 |     const style = document.createElement('style');
1736 |     style.setAttribute('data-critical', 'true');
1737 |     style.textContent = css;
1738 |     document.head.insertBefore(style, document.head.firstChild);
1739 |     
1740 |     return () => style.remove();
1741 |   }, [css]);
1742 | }
1743 | ```
1744 | 
1745 | **When to use:**
1746 | - Building CSS-in-JS libraries
1747 | - Dynamic style generation
1748 | - Theme system implementation
1749 | - Critical CSS injection
1750 | 
1751 | **When NOT to use:**
1752 | - Regular application code (use `useEffect`)
1753 | - Static stylesheets (use `<link>` tags)
1754 | - Non-style DOM manipulation
1755 | 
1756 | **Note:** Rarely used directly in application code. Primarily for library authors. XMLUI uses this in `StyleContext` for theme style injection.
1757 | 
1758 | **Comparison with other effects:**
1759 | 
1760 | ```tsx
1761 | // ❌ WRONG - useEffect runs too late
1762 | useEffect(() => {
1763 |   injectStyles(); // Styles added after layout measured
1764 | }, []);
1765 | 
1766 | // ❌ WRONG - useLayoutEffect causes double layout
1767 | useLayoutEffect(() => {
1768 |   injectStyles(); // Layout measured, then styles added, then re-measured
1769 | }, []);
1770 | 
1771 | // ✅ CORRECT - useInsertionEffect runs first
1772 | useInsertionEffect(() => {
1773 |   injectStyles(); // Styles ready before any layout measurement
1774 | }, []);
1775 | ```
1776 | 
1777 | ---
1778 | 
1779 | ### Effect Best Practices Summary
1780 | 
1781 | **1. Always clean up:**
1782 | ```tsx
1783 | useEffect(() => {
1784 |   const subscription = subscribe();
1785 |   return () => subscription.unsubscribe(); // ✅ Cleanup
1786 | }, []);
1787 | ```
1788 | 
1789 | **2. Handle dependencies correctly:**
1790 | ```tsx
1791 | // ✅ Include all dependencies
1792 | useEffect(() => {
1793 |   doSomething(prop, state);
1794 | }, [prop, state]);
1795 | 
1796 | // ✅ Or use functional updates
1797 | useEffect(() => {
1798 |   setState(prev => prev + 1);
1799 | }, []); // No state dependency needed
1800 | ```
1801 | 
1802 | **3. Choose the right effect hook:**
1803 | - `useEffect` - Default choice (async, after paint)
1804 | - `useLayoutEffect` - DOM measurements, prevent flicker (sync, before paint)
1805 | - `useInsertionEffect` - CSS-in-JS only (before layout)
1806 | 
1807 | **4. Avoid common pitfalls:**
1808 | ```tsx
1809 | // ❌ Don't use objects in deps
1810 | useEffect(() => {}, [config]); // Runs every render
1811 | 
1812 | // ✅ Destructure primitive values
1813 | useEffect(() => {}, [config.id, config.name]);
1814 | 
1815 | // ❌ Don't make effect callback async
1816 | useEffect(async () => {}, []); // Type error
1817 | 
1818 | // ✅ Use IIFE for async
1819 | useEffect(() => {
1820 |   (async () => await fetch())();
1821 | }, []);
1822 | ```
1823 | 
1824 | **5. Profile before optimizing:**
1825 | - Most effects are cheap
1826 | - Don't prematurely optimize with `useLayoutEffect`
1827 | - Measure actual performance impact
1828 | 
1829 | ---
1830 | 
1831 | ## `useRef` - Persistent Mutable References
1832 | 
1833 | **Purpose:** Store mutable values that persist across renders without triggering re-renders.
1834 | 
1835 | **Syntax:** `const ref = useRef(initialValue)`
1836 | 
1837 | ### DOM References
1838 | 
1839 | ```tsx
1840 | function TextInput() {
1841 |   const inputRef = useRef<HTMLInputElement>(null);
1842 |   
1843 |   const focusInput = () => {
1844 |     inputRef.current?.focus();
1845 |   };
1846 |   
1847 |   return (
1848 |     <div>
1849 |       <input ref={inputRef} />
1850 |       <button onClick={focusInput}>Focus</button>
1851 |     </div>
1852 |   );
1853 | }
1854 | ```
1855 | 
1856 | ### Storing Mutable Values
1857 | 
1858 | ```tsx
1859 | function Timer() {
1860 |   const [count, setCount] = useState(0);
1861 |   const intervalRef = useRef<NodeJS.Timeout>();
1862 |   
1863 |   useEffect(() => {
1864 |     intervalRef.current = setInterval(() => {
1865 |       setCount(c => c + 1);
1866 |     }, 1000);
1867 |     
1868 |     return () => clearInterval(intervalRef.current);
1869 |   }, []);
1870 |   
1871 |   const stop = () => {
1872 |     clearInterval(intervalRef.current);
1873 |   };
1874 |   
1875 |   return (
1876 |     <div>
1877 |       {count} seconds
1878 |       <button onClick={stop}>Stop</button>
1879 |     </div>
1880 |   );
1881 | }
1882 | ```
1883 | 
1884 | ### Avoiding Stale Closures
1885 | 
1886 | ```tsx
1887 | function Component({ callback }: Props) {
1888 |   const callbackRef = useRef(callback);
1889 |   
1890 |   // Keep ref updated with latest callback
1891 |   useEffect(() => {
1892 |     callbackRef.current = callback;
1893 |   }, [callback]);
1894 |   
1895 |   useEffect(() => {
1896 |     const interval = setInterval(() => {
1897 |       // Always uses latest callback
1898 |       callbackRef.current();
1899 |     }, 1000);
1900 |     
1901 |     return () => clearInterval(interval);
1902 |   }, []); // No callback dependency needed
1903 |   
1904 |   return <div>Running...</div>;
1905 | }
1906 | ```
1907 | 
1908 | ### Common Patterns in XMLUI
1909 | 
1910 | **Previous Value Tracking:**
1911 | ```tsx
1912 | function usePrevious<T>(value: T): T | undefined {
1913 |   const ref = useRef<T>();
1914 |   
1915 |   useEffect(() => {
1916 |     ref.current = value;
1917 |   }, [value]);
1918 |   
1919 |   return ref.current;
1920 | }
1921 | 
1922 | function Component({ count }: Props) {
1923 |   const prevCount = usePrevious(count);
1924 |   
1925 |   return <div>Now: {count}, Before: {prevCount}</div>;
1926 | }
1927 | ```
1928 | 
1929 | ### Key Differences: useState vs useRef
1930 | 
1931 | | Feature | `useState` | `useRef` |
1932 | |---------|-----------|---------|
1933 | | Triggers re-render | ✅ Yes | ❌ No |
1934 | | Persists across renders | ✅ Yes | ✅ Yes |
1935 | | Use for UI state | ✅ Yes | ❌ No |
1936 | | Use for DOM access | ❌ No | ✅ Yes |
1937 | | Use for mutable timers/intervals | ❌ No | ✅ Yes |
1938 | 
1939 | ---
1940 | 
1941 | ## `useId` - Unique ID Generation
1942 | 
1943 | **Purpose:** Generate stable unique IDs for accessibility attributes.
1944 | 
1945 | **Syntax:** `const id = useId()`
1946 | 
1947 | ### Basic Usage
1948 | 
1949 | ```tsx
1950 | function FormField({ label }: Props) {
1951 |   const id = useId();
1952 |   
1953 |   return (
1954 |     <div>
1955 |       <label htmlFor={id}>{label}</label>
1956 |       <input id={id} />
1957 |     </div>
1958 |   );
1959 | }
1960 | ```
1961 | 
1962 | ### Multiple IDs
1963 | 
1964 | ```tsx
1965 | function ComplexForm() {
1966 |   const id = useId();
1967 |   
1968 |   return (
1969 |     <div>
1970 |       <label htmlFor={`${id}-name`}>Name</label>
1971 |       <input id={`${id}-name`} aria-describedby={`${id}-name-hint`} />
1972 |       <span id={`${id}-name-hint`}>Enter your full name</span>
1973 |       
1974 |       <label htmlFor={`${id}-email`}>Email</label>
1975 |       <input id={`${id}-email`} />
1976 |     </div>
1977 |   );
1978 | }
1979 | ```
1980 | 
1981 | **Why not just use a counter?** `useId` generates IDs that are stable across server and client rendering, preventing hydration mismatches.
1982 | 
1983 | ---
1984 | 
1985 | ## `forwardRef` - Ref Forwarding to Child Components
1986 | 
1987 | **Purpose:** Allow parent components to access DOM nodes or component instances of child components by forwarding refs through component boundaries.
1988 | 
1989 | **Syntax:** `const Component = forwardRef((props, ref) => { ... })`
1990 | 
1991 | ### Basic Usage
1992 | 
1993 | ```tsx
1994 | const TextInput = forwardRef<HTMLInputElement, Props>(
1995 |   function TextInput({ label, ...props }, forwardedRef) {
1996 |     return (
1997 |       <div>
1998 |         <label>{label}</label>
1999 |         <input ref={forwardedRef} {...props} />
2000 |       </div>
2001 |     );
2002 |   }
2003 | );
2004 | 
2005 | // Parent can now access the input element
2006 | function Form() {
2007 |   const inputRef = useRef<HTMLInputElement>(null);
2008 |   
2009 |   const focusInput = () => {
2010 |     inputRef.current?.focus();
2011 |   };
2012 |   
2013 |   return (
2014 |     <div>
2015 |       <TextInput ref={inputRef} label="Name" />
2016 |       <button onClick={focusInput}>Focus Input</button>
2017 |     </div>
2018 |   );
2019 | }
2020 | ```
2021 | 
2022 | ### TypeScript Generic Syntax
2023 | 
2024 | ```tsx
2025 | // Explicitly type both the ref and props
2026 | const Component = forwardRef<RefType, PropsType>(
2027 |   function Component(props, ref) {
2028 |     return <div ref={ref}>...</div>;
2029 |   }
2030 | );
2031 | 
2032 | // Example with HTMLDivElement
2033 | const Card = forwardRef<HTMLDivElement, CardProps>(
2034 |   function Card({ children, className }, ref) {
2035 |     return (
2036 |       <div ref={ref} className={className}>
2037 |         {children}
2038 |       </div>
2039 |     );
2040 |   }
2041 | );
2042 | ```
2043 | 
2044 | **Why explicit typing matters:**
2045 | 
2046 | Without generic syntax, TypeScript infers types from the function signature, which can lead to several issues:
2047 | 
2048 | ```tsx
2049 | // ❌ WRONG - Without explicit generics
2050 | const Input = forwardRef(function Input(props: Props, ref) {
2051 |   // TypeScript infers ref as: ForwardedRef<unknown>
2052 |   // This means:
2053 |   // 1. No autocomplete for ref.current properties
2054 |   // 2. No type checking when assigning ref to JSX elements
2055 |   // 3. Parent components can pass wrong ref type without errors
2056 |   return <input ref={ref} />; // Type error: ref might not be compatible!
2057 | });
2058 | 
2059 | // Usage - TypeScript won't catch this error:
2060 | const divRef = useRef<HTMLDivElement>(null);
2061 | <Input ref={divRef} /> // Should error but doesn't - expecting HTMLInputElement!
2062 | 
2063 | // ✅ CORRECT - With explicit generics
2064 | const Input = forwardRef<HTMLInputElement, Props>(
2065 |   function Input(props, ref) {
2066 |     // TypeScript knows ref is: ForwardedRef<HTMLInputElement>
2067 |     // Benefits:
2068 |     // 1. Autocomplete works: ref.current?.focus()
2069 |     // 2. Type checking ensures ref matches JSX element
2070 |     // 3. Parent must pass correct ref type
2071 |     return <input ref={ref} />; // Type safe!
2072 |   }
2073 | );
2074 | 
2075 | // Usage - TypeScript catches the error:
2076 | const divRef = useRef<HTMLDivElement>(null);
2077 | <Input ref={divRef} /> // ❌ Type error: expected RefObject<HTMLInputElement>
2078 | ```
2079 | 
2080 | **Key problems without explicit generics:**
2081 | 1. **Loss of type safety** - Parent can pass incompatible ref types
2082 | 2. **No IntelliSense** - No autocomplete for `ref.current` properties
2083 | 3. **Runtime errors** - Type mismatches only discovered at runtime
2084 | 4. **Harder refactoring** - Changes to ref type don't propagate to consumers
2085 | 
2086 | **Best practice:** Always specify both generic parameters explicitly in XMLUI components.
2087 | 
2088 | ### Composing Multiple Refs
2089 | 
2090 | **The Problem:** Components often need to manage multiple refs pointing to the same DOM element:
2091 | 1. **Internal ref** - Component's own logic (measurements, animations, focus)
2092 | 2. **Forwarded ref** - Parent needs access to the DOM element
2093 | 3. **Third-party refs** - Integration with libraries (Popper, Radix UI, etc.)
2094 | 
2095 | **The Solution:** Use `composeRefs` from `@radix-ui/react-compose-refs` to merge multiple refs into one.
2096 | 
2097 | **Why you need to compose refs:**
2098 | 
2099 | | Use Case | Example | Reason |
2100 | |----------|---------|--------|
2101 | | **Internal logic + parent access** | Auto-resize textarea | Component measures scrollHeight, parent needs focus() |
2102 | | **Library integration** | Popover/Tooltip | Popper needs ref for positioning, parent needs ref for control |
2103 | | **Wrapper components** | Container with single child | Parent ref applies to child, child has own ref |
2104 | | **Multiple behaviors** | Draggable element | Drag library needs ref, resize observer needs ref, parent needs ref |
2105 | 
2106 | **Key differences: Inner vs Forwarded refs:**
2107 | 
2108 | | Aspect | Inner Ref | Forwarded Ref |
2109 | |--------|-----------|---------------|
2110 | | **Created by** | Component itself with `useRef()` | Parent component |
2111 | | **Purpose** | Internal component logic | Parent needs DOM access |
2112 | | **Type** | Always `RefObject<T>` | Can be `RefObject<T>`, `RefCallback<T>`, or `null` |
2113 | | **Guaranteed to exist** | Yes - always has `.current` property | No - parent might not pass a ref |
2114 | | **When to use** | Component needs DOM access for its own behavior | Expose DOM element to parent |
2115 | 
2116 | **Example 1: Internal + Forwarded (most common in XMLUI):**
2117 | 
2118 | ```tsx
2119 | import { composeRefs } from "@radix-ui/react-compose-refs";
2120 | 
2121 | function TextArea({ value, onChange }: Props, forwardedRef: Ref<HTMLTextAreaElement>) {
2122 |   // Inner ref: Component creates and owns this for auto-resize logic
2123 |   const innerRef = useRef<HTMLTextAreaElement>(null);
2124 |   
2125 |   // Compose both refs - textarea element needs both
2126 |   const composedRef = forwardedRef 
2127 |     ? composeRefs(innerRef, forwardedRef) 
2128 |     : innerRef;
2129 |   
2130 |   useEffect(() => {
2131 |     // ✅ CORRECT: Use innerRef for internal logic
2132 |     // It's guaranteed to exist and have .current property
2133 |     if (innerRef.current) {
2134 |       innerRef.current.style.height = 'auto';
2135 |       innerRef.current.style.height = `${innerRef.current.scrollHeight}px`;
2136 |     }
2137 |     
2138 |     // ❌ WRONG: Don't use forwardedRef directly
2139 |     // if (forwardedRef?.current) { ... } // Type error: Ref<T> might be a callback!
2140 |   }, [value]);
2141 |   
2142 |   return <textarea ref={composedRef} value={value} onChange={onChange} />;
2143 | }
2144 | 
2145 | export const AutoResizeTextArea = forwardRef(TextArea);
2146 | 
2147 | // Parent usage:
2148 | function Form() {
2149 |   const textareaRef = useRef<HTMLTextAreaElement>(null);
2150 |   
2151 |   const focusTextarea = () => {
2152 |     textareaRef.current?.focus(); // Parent can access via forwarded ref
2153 |   };
2154 |   
2155 |   return <AutoResizeTextArea ref={textareaRef} />; // Component auto-resizes via inner ref
2156 | }
2157 | ```
2158 | 
2159 | **Example 2: Library Integration (Popper + Forwarded):**
2160 | 
2161 | ```tsx
2162 | function Select({ options }: Props, forwardedRef: Ref<HTMLButtonElement>) {
2163 |   // Popper library needs a ref for positioning
2164 |   const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
2165 |   
2166 |   // Compose library ref setter with forwarded ref
2167 |   const composedRef = forwardedRef 
2168 |     ? composeRefs(setReferenceElement, forwardedRef) 
2169 |     : setReferenceElement;
2170 |   
2171 |   return (
2172 |     <>
2173 |       <button ref={composedRef}>Select</button>
2174 |       <Popper referenceElement={referenceElement}>
2175 |         {/* Dropdown content */}
2176 |       </Popper>
2177 |     </>
2178 |   );
2179 | }
2180 | 
2181 | export const SelectComponent = forwardRef(Select);
2182 | ```
2183 | 
2184 | **Example 3: Wrapper Component (Parent + Child refs):**
2185 | 
2186 | ```tsx
2187 | function Container({ children }: Props, ref: Ref<HTMLElement>) {
2188 |   const renderedChild = renderChild(children);
2189 |   
2190 |   // If single child, compose parent's ref with child's existing ref
2191 |   if (isValidElement(renderedChild)) {
2192 |     return cloneElement(renderedChild, {
2193 |       ref: composeRefs(ref, (renderedChild as any).ref),
2194 |     });
2195 |   }
2196 |   
2197 |   return renderedChild;
2198 | }
2199 | 
2200 | export const ContainerComponent = forwardRef(Container);
2201 | ```
2202 | 
2203 | **Example 4: Multiple Behaviors (Drag + Resize + Forward):**
2204 | 
2205 | ```tsx
2206 | function DraggablePanel(props: Props, forwardedRef: Ref<HTMLDivElement>) {
2207 |   const dragRef = useRef<HTMLDivElement>(null);
2208 |   const resizeObserverRef = useRef<HTMLDivElement>(null);
2209 |   
2210 |   // Compose all three refs
2211 |   const composedRef = composeRefs(
2212 |     dragRef,
2213 |     resizeObserverRef,
2214 |     forwardedRef || null
2215 |   );
2216 |   
2217 |   useDragLogic(dragRef);
2218 |   useResizeObserver(resizeObserverRef);
2219 |   
2220 |   return <div ref={composedRef}>Draggable and resizable</div>;
2221 | }
2222 | ```
2223 | 
2224 | **When to compose refs:**
2225 | - Component needs internal ref AND parent needs access
2226 | - Integrating with libraries that require refs (Popper, React DnD, etc.)
2227 | - Wrapping components that need to forward refs to children
2228 | - Multiple hooks/effects need refs to the same element
2229 | 
2230 | **How `composeRefs` works:**
2231 | - Accepts multiple refs (RefObjects, callbacks, or null)
2232 | - Returns a single callback ref that updates all provided refs
2233 | - Handles both RefObject (sets `.current`) and callback refs (calls function)
2234 | - Safely ignores `null`/`undefined` refs
2235 | 
2236 | ### When to Use forwardRef
2237 | 
2238 | **Use `forwardRef` when:**
2239 | - Building reusable components that wrap DOM elements
2240 | - Parent needs direct DOM access (focus, scroll, measurements)
2241 | - Integrating with third-party libraries requiring refs
2242 | - Creating form components that need imperative control
2243 | 
2244 | **Don't use `forwardRef` when:**
2245 | - Component doesn't wrap a single DOM element
2246 | - Refs aren't needed by parent components
2247 | - You can solve the problem with callbacks/props instead
2248 | 
2249 | ### Common Mistakes
2250 | 
2251 | ```tsx
2252 | // ❌ WRONG - Forgetting to attach ref to DOM element
2253 | const Bad = forwardRef((props, ref) => {
2254 |   return <div>{props.children}</div>; // ref is ignored!
2255 | });
2256 | 
2257 | // ✅ CORRECT - Always attach ref to actual DOM element
2258 | const Good = forwardRef((props, ref) => {
2259 |   return <div ref={ref}>{props.children}</div>;
2260 | });
2261 | 
2262 | // ❌ WRONG - Attaching ref to component (won't work)
2263 | const AlsoBad = forwardRef((props, ref) => {
2264 |   return <CustomComponent ref={ref} />; // CustomComponent must also use forwardRef
2265 | });
2266 | 
2267 | // ✅ CORRECT - Forward through nested components
2268 | const CustomComponent = forwardRef((props, ref) => {
2269 |   return <div ref={ref}>...</div>;
2270 | });
2271 | 
2272 | const AlsoGood = forwardRef((props, ref) => {
2273 |   return <CustomComponent ref={ref} />; // Works because CustomComponent forwards
2274 | });
2275 | ```
2276 | 
2277 | ---
2278 | 
2279 | ## `createPortal` - Render Outside Hierarchy
2280 | 
2281 | **Purpose:** Render children into a DOM node outside the parent component's hierarchy.
2282 | 
2283 | **Syntax:** `createPortal(children, domNode, key?)`
2284 | 
2285 | ### Basic Usage
2286 | 
2287 | ```tsx
2288 | import { createPortal } from 'react-dom';
2289 | 
2290 | function Modal({ isOpen, children }: Props) {
2291 |   if (!isOpen) return null;
2292 |   
2293 |   // Render into document.body instead of parent component
2294 |   return createPortal(
2295 |     <div className="modal-overlay">
2296 |       <div className="modal-content">
2297 |         {children}
2298 |       </div>
2299 |     </div>,
2300 |     document.body
2301 |   );
2302 | }
2303 | 
2304 | // Usage
2305 | function App() {
2306 |   return (
2307 |     <div className="app">
2308 |       <Modal isOpen={true}>
2309 |         <h1>This renders in document.body, not .app!</h1>
2310 |       </Modal>
2311 |     </div>
2312 |   );
2313 | }
2314 | ```
2315 | 
2316 | ### Common Use Cases
2317 | 
2318 | **1. Tooltips/Popovers (avoid z-index issues):**
2319 | ```tsx
2320 | function Tooltip({ targetRef, content }: Props) {
2321 |   return createPortal(
2322 |     <div className="tooltip" style={calculatePosition(targetRef)}>
2323 |       {content}
2324 |     </div>,
2325 |     document.body
2326 |   );
2327 | }
2328 | ```
2329 | 
2330 | **2. Notifications/Toasts:**
2331 | ```tsx
2332 | function NotificationToast() {
2333 |   const [shouldRender, setShouldRender] = useState(false);
2334 |   
2335 |   useEffect(() => {
2336 |     setShouldRender(true);
2337 |   }, []);
2338 |   
2339 |   if (!shouldRender) return null;
2340 |   
2341 |   return createPortal(
2342 |     <Toaster position="top-right">
2343 |       {(t) => <ToastBar toast={t} />}
2344 |     </Toaster>,
2345 |     document.body
2346 |   );
2347 | }
2348 | ```
2349 | 
2350 | **3. Modal Dialogs:**
2351 | ```tsx
2352 | function ModalDialog({ isOpen, children }: Props) {
2353 |   if (!isOpen) return null;
2354 |   
2355 |   return createPortal(
2356 |     <div className="modal-backdrop">
2357 |       <div className="modal-dialog">
2358 |         {children}
2359 |       </div>
2360 |     </div>,
2361 |     document.getElementById('modal-root') || document.body
2362 |   );
2363 | }
2364 | ```
2365 | 
2366 | **4. Full-Screen Overlays:**
2367 | ```tsx
2368 | function FullScreenOverlay({ show, children }: Props) {
2369 |   if (!show) return null;
2370 |   
2371 |   return createPortal(
2372 |     <div className="fullscreen-overlay">
2373 |       {children}
2374 |     </div>,
2375 |     document.body
2376 |   );
2377 | }
2378 | ```
2379 | 
2380 | ### Event Bubbling Still Works
2381 | 
2382 | ```tsx
2383 | // Event bubbling works despite DOM hierarchy
2384 | function Parent() {
2385 |   const handleClick = () => {
2386 |     console.log('Clicked!'); // This fires even though button is portaled
2387 |   };
2388 |   
2389 |   return (
2390 |     <div onClick={handleClick}>
2391 |       <PortaledButton />
2392 |     </div>
2393 |   );
2394 | }
2395 | 
2396 | function PortaledButton() {
2397 |   return createPortal(
2398 |     <button>Click me</button>,
2399 |     document.body
2400 |   );
2401 | }
2402 | ```
2403 | 
2404 | ### Common Pattern in XMLUI
2405 | 
2406 | ```tsx
2407 | // App component portals theme styles
2408 | function App({ children }: Props) {
2409 |   return (
2410 |     <>
2411 |       {children}
2412 |       {createPortal(
2413 |         <style>{themeCSS}</style>,
2414 |         document.head
2415 |       )}
2416 |     </>
2417 |   );
2418 | }
2419 | 
2420 | // Inspector portals debugging UI
2421 | function Inspector() {
2422 |   return createPortal(
2423 |     <div className="inspector-panel">
2424 |       {/* Debug tools */}
2425 |     </div>,
2426 |     document.body
2427 |   );
2428 | }
2429 | ```
2430 | 
2431 | ### When to Use createPortal
2432 | 
2433 | **Use `createPortal` when:**
2434 | - Modals, dialogs, and overlays
2435 | - Tooltips and popovers
2436 | - Notifications and toasts
2437 | - Avoiding parent overflow/z-index issues
2438 | - Rendering into different parts of DOM (head, body)
2439 | 
2440 | **Don't use when:**
2441 | - Normal component rendering is sufficient
2442 | - No CSS stacking or overflow issues
2443 | - Adds unnecessary complexity
2444 | 
2445 | ---
2446 | 
2447 | ## `Fragment` - Grouping Without DOM Nodes
2448 | 
2449 | **Purpose:** Group multiple elements without adding extra nodes to the DOM.
2450 | 
2451 | **Syntax:** `<Fragment>...</Fragment>` or `<>...</>`
2452 | 
2453 | ### Basic Usage
2454 | 
2455 | ```tsx
2456 | // ❌ WRONG - Adds unnecessary div wrapper
2457 | function List() {
2458 |   return (
2459 |     <div>
2460 |       <li>Item 1</li>
2461 |       <li>Item 2</li>
2462 |     </div>
2463 |   );
2464 | }
2465 | 
2466 | // ✅ CORRECT - No extra DOM node
2467 | function List() {
2468 |   return (
2469 |     <>
2470 |       <li>Item 1</li>
2471 |       <li>Item 2</li>
2472 |     </>
2473 |   );
2474 | }
2475 | ```
2476 | 
2477 | ### Short vs Long Syntax
2478 | 
2479 | ```tsx
2480 | // Short syntax <> - Use for most cases
2481 | function Component() {
2482 |   return (
2483 |     <>
2484 |       <Header />
2485 |       <Content />
2486 |     </>
2487 |   );
2488 | }
2489 | 
2490 | // Long syntax <Fragment> - Required when you need a key
2491 | function List({ items }: Props) {
2492 |   return (
2493 |     <ul>
2494 |       {items.map(item => (
2495 |         <Fragment key={item.id}>
2496 |           <li>{item.name}</li>
2497 |           <li>{item.description}</li>
2498 |         </Fragment>
2499 |       ))}
2500 |     </ul>
2501 |   );
2502 | }
2503 | ```
2504 | 
2505 | **Limitations of short syntax:**
2506 | - ❌ Cannot add `key` prop (use `<Fragment key={...}>` instead)
2507 | - ❌ Cannot add any other props (only `key` is allowed on Fragment)
2508 | - ✅ Use short syntax everywhere else (cleaner, less verbose)
2509 | 
2510 | ### Common Use Cases
2511 | 
2512 | **1. Returning Multiple Elements:**
2513 | ```tsx
2514 | function Header() {
2515 |   return (
2516 |     <>
2517 |       <h1>Title</h1>
2518 |       <nav>Navigation</nav>
2519 |     </>
2520 |   );
2521 | }
2522 | ```
2523 | 
2524 | **2. Conditional Rendering:**
2525 | ```tsx
2526 | function Component({ showExtra }: Props) {
2527 |   return (
2528 |     <div>
2529 |       <h1>Always shown</h1>
2530 |       {showExtra && (
2531 |         <>
2532 |           <p>Extra content</p>
2533 |           <button>Extra button</button>
2534 |         </>
2535 |       )}
2536 |     </div>
2537 |   );
2538 | }
2539 | ```
2540 | 
2541 | **3. Table Rows:**
2542 | ```tsx
2543 | function TableRows({ data }: Props) {
2544 |   return (
2545 |     <>
2546 |       {data.map(row => (
2547 |         <Fragment key={row.id}>
2548 |           <tr>
2549 |             <td>{row.name}</td>
2550 |             <td>{row.value}</td>
2551 |           </tr>
2552 |           {row.hasDetails && (
2553 |             <tr>
2554 |               <td colSpan={2}>{row.details}</td>
2555 |             </tr>
2556 |           )}
2557 |         </Fragment>
2558 |       ))}
2559 |     </>
2560 |   );
2561 | }
2562 | ```
2563 | 
2564 | **4. Avoiding Invalid HTML:**
2565 | ```tsx
2566 | // ❌ WRONG - div inside p is invalid HTML
2567 | function Text() {
2568 |   return (
2569 |     <p>
2570 |       <div>This is invalid!</div>
2571 |     </p>
2572 |   );
2573 | }
2574 | 
2575 | // ✅ CORRECT - Fragment doesn't create DOM node
2576 | function Text() {
2577 |   return (
2578 |     <p>
2579 |       <>
2580 |         <span>This is valid!</span>
2581 |       </>
2582 |     </p>
2583 |   );
2584 | }
2585 | ```
2586 | 
2587 | ### When to Use Fragment
2588 | 
2589 | **Use `Fragment` when:**
2590 | - Component must return multiple elements
2591 | - Avoiding wrapper divs that break CSS (flexbox, grid)
2592 | - Keeping HTML semantically valid
2593 | - Conditional rendering of multiple elements
2594 | 
2595 | **Don't use when:**
2596 | - Single element (no need to wrap)
2597 | - Wrapper div doesn't cause issues
2598 | - Need to attach events or refs (Fragment can't have them)
2599 | 
2600 | ---
2601 | 
2602 | ## `cloneElement` - Clone and Modify React Elements
2603 | 
2604 | **Purpose:** Clone a React element and override its props, refs, or children.
2605 | 
2606 | **Syntax:** `cloneElement(element, props?, ...children?)`
2607 | 
2608 | ### Basic Usage
2609 | 
2610 | ```tsx
2611 | import { cloneElement, isValidElement } from 'react';
2612 | 
2613 | function Container({ children }: Props) {
2614 |   if (!isValidElement(children)) {
2615 |     return children;
2616 |   }
2617 |   
2618 |   // Clone child and add extra props
2619 |   return cloneElement(children, {
2620 |     className: 'container-child',
2621 |     style: { padding: '10px' },
2622 |   });
2623 | }
2624 | 
2625 | // Usage
2626 | <Container>
2627 |   <div>Original</div> {/* Becomes <div className="container-child" style={{padding: '10px'}}>Original</div> */}
2628 | </Container>
2629 | ```
2630 | 
2631 | ### Adding Props to Children
2632 | 
2633 | ```tsx
2634 | function Animation({ children, duration = 300 }: Props) {
2635 |   if (!isValidElement(children)) {
2636 |     return children;
2637 |   }
2638 |   
2639 |   // Add animation props to child
2640 |   return cloneElement(children, {
2641 |     style: {
2642 |       ...children.props.style,
2643 |       transition: `all ${duration}ms`,
2644 |     },
2645 |   });
2646 | }
2647 | ```
2648 | 
2649 | ### Forwarding Refs Through Clone
2650 | 
2651 | ```tsx
2652 | function Wrapper({ children, ...rest }: Props, forwardedRef: Ref<any>) {
2653 |   if (!isValidElement(children)) {
2654 |     return children;
2655 |   }
2656 |   
2657 |   // Clone and forward ref + other props
2658 |   return cloneElement(children, {
2659 |     ...rest,
2660 |     ref: forwardedRef,
2661 |   });
2662 | }
2663 | 
2664 | export const WrapperComponent = forwardRef(Wrapper);
2665 | ```
2666 | 
2667 | ### Common Pattern in XMLUI
2668 | 
2669 | **Container with single child ref forwarding:**
2670 | ```tsx
2671 | function Container({ children }: Props, ref: Ref<HTMLElement>) {
2672 |   const renderedChild = renderChild(children);
2673 |   
2674 |   // If single valid child, compose refs and merge props
2675 |   if (ref && renderedChild && isValidElement(renderedChild)) {
2676 |     return cloneElement(renderedChild, {
2677 |       ref: composeRefs(ref, (renderedChild as any).ref),
2678 |       ...mergeProps(renderedChild.props, rest),
2679 |     });
2680 |   }
2681 |   
2682 |   return renderedChild;
2683 | }
2684 | ```
2685 | 
2686 | **Form field with label integration:**
2687 | ```tsx
2688 | function ItemWithLabel({ children, label }: Props) {
2689 |   const id = useId();
2690 |   
2691 |   return (
2692 |     <div>
2693 |       <label htmlFor={id}>{label}</label>
2694 |       {cloneElement(children as ReactElement, {
2695 |         id,
2696 |         'aria-labelledby': id,
2697 |       })}
2698 |     </div>
2699 |   );
2700 | }
2701 | ```
2702 | 
2703 | ### When to Use cloneElement
2704 | 
2705 | **Use `cloneElement` when:**
2706 | - Wrapping components need to add props to children
2707 | - Forwarding refs through wrapper components
2708 | - Adding common behavior to arbitrary children
2709 | - Integrating with child elements you don't control
2710 | 
2711 | **Don't use when:**
2712 | - You can pass props directly (prefer explicit props)
2713 | - You need to modify deeply nested children (use context instead)
2714 | - Children are not React elements (check with `isValidElement` first)
2715 | 
2716 | ### Common Mistakes
2717 | 
2718 | ```tsx
2719 | // ❌ WRONG - Not checking if child is valid element
2720 | function Bad({ children }: Props) {
2721 |   return cloneElement(children, { className: 'bad' }); // Crashes if children is string/number
2722 | }
2723 | 
2724 | // ✅ CORRECT - Always validate first (see isValidElement section)
2725 | function Good({ children }: Props) {
2726 |   if (!isValidElement(children)) {
2727 |     return children;
2728 |   }
2729 |   return cloneElement(children, { className: 'good' });
2730 | }
2731 | 
2732 | // ❌ WRONG - Overriding all existing props
2733 | return cloneElement(child, { style: { color: 'red' } }); // Loses child's existing style
2734 | 
2735 | // ✅ CORRECT - Merge with existing props
2736 | return cloneElement(child, {
2737 |   style: { ...child.props.style, color: 'red' },
2738 | });
2739 | ```
2740 | 
2741 | ---
2742 | 
2743 | ## `isValidElement` - Type Check for React Elements
2744 | 
2745 | **Purpose:** Check if a value is a valid React element (created with JSX or `createElement`). Always use before `cloneElement`.
2746 | 
2747 | **Syntax:** `isValidElement(value)`
2748 | 
2749 | ### Basic Usage
2750 | 
2751 | ```tsx
2752 | import { isValidElement } from 'react';
2753 | 
2754 | function processChild(child: React.ReactNode) {
2755 |   // child could be anything: string, number, element, array, etc.
2756 |   
2757 |   if (isValidElement(child)) {
2758 |     // TypeScript now knows child is ReactElement
2759 |     console.log(child.props); // ✅ OK - access props safely
2760 |     console.log(child.type);  // ✅ OK - access type safely
2761 |     return child;
2762 |   }
2763 |   
2764 |   // Not an element - return as is
2765 |   return child;
2766 | }
2767 | ```
2768 | 
2769 | ### Common Pattern in XMLUI
2770 | 
2771 | **Conditional element wrapping:**
2772 | ```tsx
2773 | function ConditionalWrapper({ condition, children }: Props) {
2774 |   if (!condition) {
2775 |     return children;
2776 |   }
2777 |   
2778 |   // Only wrap if child is valid element
2779 |   return isValidElement(children) 
2780 |     ? <div className="wrapper">{children}</div>
2781 |     : children;
2782 | }
2783 | ```
2784 | 
2785 | ### What isValidElement Checks
2786 | 
2787 | ```tsx
2788 | isValidElement(<div />);              // ✅ true - JSX element
2789 | isValidElement(React.createElement('div')); // ✅ true - created element
2790 | isValidElement(<Component />);        // ✅ true - component element
2791 | isValidElement('hello');              // ❌ false - string
2792 | isValidElement(123);                  // ❌ false - number
2793 | isValidElement(null);                 // ❌ false - null
2794 | isValidElement(undefined);            // ❌ false - undefined
2795 | isValidElement([<div key="1" />]);    // ❌ false - array of elements
2796 | ```
2797 | 
2798 | ### When to Use isValidElement
2799 | 
2800 | **Use `isValidElement` when:**
2801 | - Before calling `cloneElement` (required to avoid crashes)
2802 | - Type narrowing for TypeScript (ReactNode → ReactElement)
2803 | - Validating `children` prop type
2804 | - Conditional element manipulation
2805 | 
2806 | **Note:** See `cloneElement` section for examples of using these two functions together.
2807 | 
2808 | ---
2809 | 
2810 | ## `flushSync` - Synchronous State Updates
2811 | 
2812 | **Purpose:** Force React to flush state updates synchronously, bypassing automatic batching.
2813 | 
2814 | **Syntax:** `flushSync(() => { /* state updates */ })`
2815 | 
2816 | **Warning:** Use sparingly - breaks React's batching optimization and can hurt performance.
2817 | 
2818 | ### Basic Usage
2819 | 
2820 | ```tsx
2821 | import { flushSync } from 'react-dom';
2822 | 
2823 | function Form() {
2824 |   const [value, setValue] = useState('');
2825 |   
2826 |   const handleSubmit = () => {
2827 |     // Normal: state updates are batched
2828 |     setValue('');
2829 |     setError(null);
2830 |     // Both updates happen together
2831 |     
2832 |     // With flushSync: update happens immediately
2833 |     flushSync(() => {
2834 |       setValue('');
2835 |     });
2836 |     // DOM is updated here, before next line
2837 |     inputRef.current?.focus();
2838 |   };
2839 | }
2840 | ```
2841 | 
2842 | ### When DOM Must Update Immediately
2843 | 
2844 | ```tsx
2845 | function Table({ data }: Props) {
2846 |   const [selectedRow, setSelectedRow] = useState(0);
2847 |   const rowRef = useRef<HTMLTableRowElement>(null);
2848 |   
2849 |   const selectRow = (index: number) => {
2850 |     // Must update DOM before scrolling
2851 |     flushSync(() => {
2852 |       setSelectedRow(index);
2853 |     });
2854 |     
2855 |     // DOM is updated, can now scroll
2856 |     rowRef.current?.scrollIntoView();
2857 |   };
2858 | }
2859 | ```
2860 | 
2861 | ### Common Pattern in XMLUI
2862 | 
2863 | **Form reset with focus:**
2864 | ```tsx
2865 | function Form({ onSubmit }: Props) {
2866 |   const doReset = () => {
2867 |     // Reset all fields
2868 |   };
2869 |   
2870 |   const handleSuccess = () => {
2871 |     const prevFocused = document.activeElement;
2872 |     
2873 |     // Force synchronous reset before restoring focus
2874 |     flushSync(() => {
2875 |       doReset();
2876 |     });
2877 |     
2878 |     // DOM is reset, restore focus
2879 |     if (prevFocused && typeof (prevFocused as HTMLElement).focus === 'function') {
2880 |       (prevFocused as HTMLElement).focus();
2881 |     }
2882 |   };
2883 | }
2884 | ```
2885 | 
2886 | **Table with immediate scroll:**
2887 | ```tsx
2888 | function DataTable({ data }: Props) {
2889 |   const handleSort = (column: string) => {
2890 |     // Update sort synchronously before scrolling
2891 |     flushSync(() => {
2892 |       setSortColumn(column);
2893 |       setSortedData(sortData(data, column));
2894 |     });
2895 |     
2896 |     // Table is re-rendered, can scroll to top
2897 |     tableRef.current?.scrollTo(0, 0);
2898 |   };
2899 | }
2900 | ```
2901 | 
2902 | ### Why flushSync Exists
2903 | 
2904 | ```tsx
2905 | // ❌ Problem: Without flushSync
2906 | function Component() {
2907 |   const [text, setText] = useState('');
2908 |   
2909 |   const update = () => {
2910 |     setText('new value');
2911 |     // DOM not updated yet!
2912 |     inputRef.current?.focus(); // Focuses old state
2913 |   };
2914 | }
2915 | 
2916 | // ✅ Solution: With flushSync
2917 | function Component() {
2918 |   const [text, setText] = useState('');
2919 |   
2920 |   const update = () => {
2921 |     flushSync(() => {
2922 |       setText('new value');
2923 |     });
2924 |     // DOM is updated
2925 |     inputRef.current?.focus(); // Focuses new state
2926 |   };
2927 | }
2928 | ```
2929 | 
2930 | ### When to Use flushSync
2931 | 
2932 | **Use `flushSync` when:**
2933 | - Need DOM measurements after state change
2934 | - Synchronizing with third-party libraries
2935 | - Scrolling after state update
2936 | - Focus management after state change
2937 | 
2938 | **Don't use when:**
2939 | - Normal state updates (let React batch)
2940 | - Performance-critical code paths
2941 | - You can solve it with `useLayoutEffect`
2942 | - Inside render (not allowed)
2943 | 
2944 | **Performance impact:**
2945 | ```tsx
2946 | // ❌ BAD - Multiple flushSync calls
2947 | data.forEach(item => {
2948 |   flushSync(() => {
2949 |     processItem(item); // Forces re-render each time
2950 |   });
2951 | });
2952 | 
2953 | // ✅ GOOD - Single batch update
2954 | const processedItems = data.map(processItem);
2955 | flushSync(() => {
2956 |   setItems(processedItems); // Single re-render
2957 | });
2958 | ```
2959 | 
2960 | ---
2961 | 
2962 | ## `createRoot` - React 18 Root API
2963 | 
2964 | **Purpose:** Create a root to render React components into a DOM container (React 18+).
2965 | 
2966 | **Syntax:** `const root = createRoot(container); root.render(<App />)`
2967 | 
2968 | ### Basic Usage
2969 | 
2970 | ```tsx
2971 | import { createRoot } from 'react-dom/client';
2972 | 
2973 | // Old way (React 17)
2974 | ReactDOM.render(<App />, document.getElementById('root'));
2975 | 
2976 | // New way (React 18+)
2977 | const root = createRoot(document.getElementById('root')!);
2978 | root.render(<App />);
2979 | ```
2980 | 
2981 | ### With TypeScript
2982 | 
2983 | ```tsx
2984 | import { createRoot } from 'react-dom/client';
2985 | 
2986 | const container = document.getElementById('root');
2987 | if (!container) {
2988 |   throw new Error('Root element not found');
2989 | }
2990 | 
2991 | const root = createRoot(container);
2992 | root.render(<App />);
2993 | ```
2994 | 
2995 | ### Unmounting
2996 | 
2997 | ```tsx
2998 | const root = createRoot(container);
2999 | root.render(<App />);
3000 | 
3001 | // Later: unmount
3002 | root.unmount();
3003 | ```
3004 | 
3005 | ### Common Pattern in XMLUI
3006 | 
3007 | **Standalone app rendering:**
3008 | ```tsx
3009 | function renderStandaloneApp(rootElement: HTMLElement) {
3010 |   let contentRoot: Root;
3011 |   
3012 |   if (!contentRoot) {
3013 |     contentRoot = createRoot(rootElement);
3014 |   }
3015 |   
3016 |   contentRoot.render(
3017 |     <StrictMode>
3018 |       <App />
3019 |     </StrictMode>
3020 |   );
3021 |   
3022 |   return contentRoot;
3023 | }
3024 | ```
3025 | 
3026 | **Shadow DOM rendering:**
3027 | ```tsx
3028 | function NestedApp({ children }: Props) {
3029 |   const shadowRef = useRef<ShadowRoot>(null);
3030 |   const contentRootRef = useRef<Root | null>(null);
3031 |   
3032 |   useEffect(() => {
3033 |     if (shadowRef.current && !contentRootRef.current) {
3034 |       // Create root in shadow DOM
3035 |       contentRootRef.current = createRoot(shadowRef.current);
3036 |       contentRootRef.current.render(<NestedContent />);
3037 |     }
3038 |     
3039 |     return () => {
3040 |       contentRootRef.current?.unmount();
3041 |     };
3042 |   }, []);
3043 | }
3044 | ```
3045 | 
3046 | ### Benefits of createRoot (React 18)
3047 | 
3048 | 1. **Automatic batching** - All updates batched, even in promises/setTimeout
3049 | 2. **Concurrent features** - Enables `useTransition`, `useDeferredValue`, etc.
3050 | 3. **Improved hydration** - Better SSR support
3051 | 4. **Suspense improvements** - Better streaming SSR
3052 | 
3053 | ### When to Use createRoot
3054 | 
3055 | **Use `createRoot` when:**
3056 | - Starting a new React 18+ application
3057 | - Rendering React into a DOM container
3058 | - Creating multiple roots in one app
3059 | - Rendering into shadow DOM
3060 | 
3061 | **Migration from React 17:**
3062 | ```tsx
3063 | // React 17
3064 | import ReactDOM from 'react-dom';
3065 | ReactDOM.render(<App />, container);
3066 | ReactDOM.unmountComponentAtNode(container);
3067 | 
3068 | // React 18
3069 | import { createRoot } from 'react-dom/client';
3070 | const root = createRoot(container);
3071 | root.render(<App />);
3072 | root.unmount();
3073 | ```
3074 | 
3075 | ---
3076 | 
3077 | ## React Accessibility Patterns
3078 | 
3079 | ### ARIA Attributes Pattern
3080 | 
3081 | **Key ARIA attributes:** `role`, `aria-label`, `aria-labelledby`, `aria-describedby`, `aria-hidden`, `aria-live`, `aria-expanded`, `aria-selected`, `aria-disabled`, `aria-current`
3082 | 
3083 | **Common patterns:**
3084 | 
3085 | ```tsx
3086 | // Icon button with accessible label
3087 | <button onClick={onClick} aria-label="Close dialog">
3088 |   <Icon name="close" aria-hidden="true" />
3089 | </button>
3090 | 
3091 | // Form field with error/help text
3092 | function FormField({ label, error, helpText }: Props) {
3093 |   const id = useId();
3094 |   return (
3095 |     <>
3096 |       <label htmlFor={id}>{label}</label>
3097 |       <input id={id} aria-describedby={`${id}-desc`} aria-invalid={!!error} />
3098 |       <span id={`${id}-desc`} role={error ? "alert" : undefined}>
3099 |         {error || helpText}
3100 |       </span>
3101 |     </>
3102 |   );
3103 | }
3104 | 
3105 | // Accordion/expandable section
3106 | <button aria-expanded={isOpen} aria-controls={contentId}>
3107 |   {title}
3108 | </button>
3109 | <div id={contentId} hidden={!isOpen} role="region">
3110 |   {children}
3111 | </div>
3112 | 
3113 | // Live region for announcements
3114 | <div role="status" aria-live="polite" aria-atomic="true">
3115 |   {message}
3116 | </div>
3117 | 
3118 | // Modal dialog
3119 | <div role="dialog" aria-modal="true" aria-labelledby={titleId}>
3120 |   <h2 id={titleId}>{title}</h2>
3121 |   {children}
3122 | </div>
3123 | 
3124 | // Tab navigation
3125 | <div role="tablist">
3126 |   <button role="tab" aria-selected={isActive} aria-controls={panelId}>
3127 |     {label}
3128 |   </button>
3129 | </div>
3130 | <div role="tabpanel" id={panelId} aria-labelledby={tabId}>
3131 |   {content}
3132 | </div>
3133 | ```
3134 | 
3135 | **Rules:** Use semantic HTML first, add ARIA only when needed, keep attributes in sync with state, test with screen readers.
3136 | 
3137 | ---
3138 | 
3139 | ### Focus Management Pattern
3140 | 
3141 | **Common scenarios:** Auto-focus on mount, focus traps in modals, focus restoration, roving tab index.
3142 | 
3143 | ```tsx
3144 | // Auto-focus first element in dialog
3145 | function Dialog({ isOpen }: Props) {
3146 |   const buttonRef = useRef<HTMLButtonElement>(null);
3147 |   
3148 |   useEffect(() => {
3149 |     if (isOpen) buttonRef.current?.focus();
3150 |   }, [isOpen]);
3151 |   
3152 |   return <button ref={buttonRef}>Close</button>;
3153 | }
3154 | 
3155 | // Focus trap + restoration in modal
3156 | function Modal({ isOpen, onClose, children }: Props) {
3157 |   const modalRef = useRef<HTMLDivElement>(null);
3158 |   const restoreFocusRef = useRef<HTMLElement | null>(null);
3159 |   
3160 |   useEffect(() => {
3161 |     if (!isOpen) return;
3162 |     
3163 |     restoreFocusRef.current = document.activeElement as HTMLElement;
3164 |     modalRef.current?.querySelector<HTMLElement>('button')?.focus();
3165 |     
3166 |     return () => restoreFocusRef.current?.focus();
3167 |   }, [isOpen]);
3168 |   
3169 |   const handleKeyDown = (e: React.KeyboardEvent) => {
3170 |     if (e.key === 'Escape') onClose();
3171 |     
3172 |     // Trap Tab key
3173 |     if (e.key === 'Tab') {
3174 |       const focusable = modalRef.current?.querySelectorAll<HTMLElement>(
3175 |         'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
3176 |       );
3177 |       if (!focusable?.length) return;
3178 |       
3179 |       const first = focusable[0];
3180 |       const last = focusable[focusable.length - 1];
3181 |       
3182 |       if (e.shiftKey && document.activeElement === first) {
3183 |         e.preventDefault();
3184 |         last.focus();
3185 |       } else if (!e.shiftKey && document.activeElement === last) {
3186 |         e.preventDefault();
3187 |         first.focus();
3188 |       }
3189 |     }
3190 |   };
3191 |   
3192 |   return (
3193 |     <div ref={modalRef} role="dialog" aria-modal="true" onKeyDown={handleKeyDown}>
3194 |       {children}
3195 |     </div>
3196 |   );
3197 | }
3198 | 
3199 | // Focus after delete action
3200 | function DeleteButton({ itemId, onDelete }: Props) {
3201 |   const handleDelete = () => {
3202 |     const current = document.getElementById(`item-${itemId}`);
3203 |     const next = (current?.nextElementSibling || current?.previousElementSibling)
3204 |       ?.querySelector('button') as HTMLElement;
3205 |     
3206 |     onDelete(itemId);
3207 |     setTimeout(() => next?.focus(), 0);
3208 |   };
3209 |   
3210 |   return <button onClick={handleDelete}>Delete</button>;
3211 | }
3212 | 
3213 | // Roving tab index for lists
3214 | function RadioGroup({ options, value, onChange }: Props) {
3215 |   const [focusedIndex, setFocusedIndex] = useState(0);
3216 |   
3217 |   const handleKeyDown = (e: React.KeyboardEvent, index: number) => {
3218 |     let newIndex = index;
3219 |     if (e.key === 'ArrowDown') newIndex = (index + 1) % options.length;
3220 |     if (e.key === 'ArrowUp') newIndex = index === 0 ? options.length - 1 : index - 1;
3221 |     if (e.key === 'Home') newIndex = 0;
3222 |     if (e.key === 'End') newIndex = options.length - 1;
3223 |     
3224 |     if (newIndex !== index) {
3225 |       e.preventDefault();
3226 |       setFocusedIndex(newIndex);
3227 |     }
3228 |   };
3229 |   
3230 |   return (
3231 |     <div role="radiogroup">
3232 |       {options.map((opt, i) => (
3233 |         <div
3234 |           key={opt.id}
3235 |           role="radio"
3236 |           aria-checked={value === opt.id}
3237 |           tabIndex={focusedIndex === i ? 0 : -1}
3238 |           onClick={() => onChange(opt.id)}
3239 |           onKeyDown={(e) => handleKeyDown(e, i)}
3240 |           onFocus={() => setFocusedIndex(i)}
3241 |         >
3242 |           {opt.label}
3243 |         </div>
3244 |       ))}
3245 |     </div>
3246 |   );
3247 | }
3248 | ```
3249 | 
3250 | **Rules:** Always restore focus when closing modals, trap focus within modal contexts, use `focus-visible` for keyboard-only indicators, test thoroughly.
3251 | 
3252 | ---
3253 | 
3254 | ### Keyboard Navigation Pattern
3255 | 
3256 | **Standard keyboard shortcuts:** Escape (close), Tab/Shift+Tab (navigate), Arrow keys (move focus), Enter/Space (activate), Home/End (first/last).
3257 | 
3258 | ```tsx
3259 | // Dropdown with full keyboard support
3260 | function Dropdown({ trigger, items, onSelect }: Props) {
3261 |   const [isOpen, setIsOpen] = useState(false);
3262 |   const [focusedIndex, setFocusedIndex] = useState(0);
3263 |   const itemsRef = useRef<(HTMLButtonElement | null)[]>([]);
3264 |   
3265 |   const handleKeyDown = (e: React.KeyboardEvent) => {
3266 |     switch (e.key) {
3267 |       case 'ArrowDown':
3268 |         e.preventDefault();
3269 |         if (!isOpen) {
3270 |           setIsOpen(true);
3271 |         } else {
3272 |           const next = (focusedIndex + 1) % items.length;
3273 |           setFocusedIndex(next);
3274 |           itemsRef.current[next]?.focus();
3275 |         }
3276 |         break;
3277 |       case 'ArrowUp':
3278 |         e.preventDefault();
3279 |         if (isOpen) {
3280 |           const prev = focusedIndex === 0 ? items.length - 1 : focusedIndex - 1;
3281 |           setFocusedIndex(prev);
3282 |           itemsRef.current[prev]?.focus();
3283 |         }
3284 |         break;
3285 |       case 'Escape':
3286 |         e.preventDefault();
3287 |         setIsOpen(false);
3288 |         break;
3289 |       case 'Enter':
3290 |       case ' ':
3291 |         e.preventDefault();
3292 |         if (isOpen) {
3293 |           onSelect(items[focusedIndex]);
3294 |           setIsOpen(false);
3295 |         } else {
3296 |           setIsOpen(true);
3297 |         }
3298 |         break;
3299 |     }
3300 |   };
3301 |   
3302 |   return (
3303 |     <div onKeyDown={handleKeyDown}>
3304 |       <button onClick={() => setIsOpen(!isOpen)} aria-expanded={isOpen}>
3305 |         {trigger}
3306 |       </button>
3307 |       {isOpen && (
3308 |         <ul role="menu">
3309 |           {items.map((item, i) => (
3310 |             <li key={item.id} role="none">
3311 |               <button
3312 |                 ref={el => itemsRef.current[i] = el}
3313 |                 role="menuitem"
3314 |                 onClick={() => { onSelect(item); setIsOpen(false); }}
3315 |                 onFocus={() => setFocusedIndex(i)}
3316 |               >
3317 |                 {item.label}
3318 |               </button>
3319 |             </li>
3320 |           ))}
3321 |         </ul>
3322 |       )}
3323 |     </div>
3324 |   );
3325 | }
3326 | 
3327 | // Global keyboard shortcuts hook
3328 | function useKeyboardShortcuts(shortcuts: Record<string, () => void>) {
3329 |   useEffect(() => {
3330 |     const handleKeyDown = (e: KeyboardEvent) => {
3331 |       const keys: string[] = [];
3332 |       if (e.ctrlKey || e.metaKey) keys.push('Ctrl');
3333 |       if (e.shiftKey) keys.push('Shift');
3334 |       if (e.altKey) keys.push('Alt');
3335 |       keys.push(e.key.toUpperCase());
3336 |       
3337 |       const handler = shortcuts[keys.join('+')];
3338 |       if (handler) {
3339 |         e.preventDefault();
3340 |         handler();
3341 |       }
3342 |     };
3343 |     
3344 |     document.addEventListener('keydown', handleKeyDown);
3345 |     return () => document.removeEventListener('keydown', handleKeyDown);
3346 |   }, [shortcuts]);
3347 | }
3348 | 
3349 | // Usage: Editor with shortcuts
3350 | function Editor() {
3351 |   useKeyboardShortcuts({
3352 |     'Ctrl+S': handleSave,
3353 |     'Ctrl+Z': handleUndo,
3354 |     'Ctrl+Shift+Z': handleRedo,
3355 |   });
3356 |   return <div>Editor</div>;
3357 | }
3358 | 
3359 | // Data table with arrow key navigation
3360 | function DataTable({ columns, rows }: Props) {
3361 |   const [focusedCell, setFocusedCell] = useState({ row: 0, col: 0 });
3362 |   const cellRefs = useRef<(HTMLTableCellElement | null)[][]>([]);
3363 |   
3364 |   const handleKeyDown = (e: React.KeyboardEvent, rowIndex: number, colIndex: number) => {
3365 |     let newRow = rowIndex, newCol = colIndex;
3366 |     
3367 |     if (e.key === 'ArrowUp') newRow = Math.max(0, rowIndex - 1);
3368 |     if (e.key === 'ArrowDown') newRow = Math.min(rows.length - 1, rowIndex + 1);
3369 |     if (e.key === 'ArrowLeft') newCol = Math.max(0, colIndex - 1);
3370 |     if (e.key === 'ArrowRight') newCol = Math.min(columns.length - 1, colIndex + 1);
3371 |     if (e.key === 'Home') newCol = 0;
3372 |     if (e.key === 'End') newCol = columns.length - 1;
3373 |     
3374 |     if (newRow !== rowIndex || newCol !== colIndex) {
3375 |       e.preventDefault();
3376 |       setFocusedCell({ row: newRow, col: newCol });
3377 |       cellRefs.current[newRow]?.[newCol]?.focus();
3378 |     }
3379 |   };
3380 |   
3381 |   return (
3382 |     <table>
3383 |       <tbody>
3384 |         {rows.map((row, ri) => (
3385 |           <tr key={row.id}>
3386 |             {columns.map((col, ci) => (
3387 |               <td
3388 |                 key={col.id}
3389 |                 ref={el => {
3390 |                   if (!cellRefs.current[ri]) cellRefs.current[ri] = [];
3391 |                   cellRefs.current[ri][ci] = el;
3392 |                 }}
3393 |                 tabIndex={focusedCell.row === ri && focusedCell.col === ci ? 0 : -1}
3394 |                 onKeyDown={e => handleKeyDown(e, ri, ci)}
3395 |                 onFocus={() => setFocusedCell({ row: ri, col: ci })}
3396 |               >
3397 |                 {row[col.id]}
3398 |               </td>
3399 |             ))}
3400 |           </tr>
3401 |         ))}
3402 |       </tbody>
3403 |     </table>
3404 |   );
3405 | }
3406 | ```
3407 | 
3408 | **Rules:** Support standard shortcuts (Escape, Tab, Arrows), don't override browser/OS shortcuts, provide visible focus feedback, test keyboard-only navigation.
3409 | 
3410 | ---
3411 | 
3412 | ### Accessibility Best Practices Summary
3413 | 
3414 | **Key principles:**
3415 | - Use semantic HTML first (`<button>`, `<nav>`, `<main>`)
3416 | - Add ARIA only when semantic HTML isn't enough
3417 | - All interactive elements must be keyboard accessible
3418 | - Provide visible focus indicators (use `:focus-visible`)
3419 | - Keep ARIA attributes in sync with visual state
3420 | - Restore focus after closing modals/dialogs
3421 | - Test with screen readers and keyboard only
3422 | 
3423 | **Testing checklist:**
3424 | - [ ] Navigate entire app with keyboard only
3425 | - [ ] Focus indicators visible and high contrast
3426 | - [ ] Screen reader announces all content correctly
3427 | - [ ] Color not the only state indicator
3428 | - [ ] Text contrast ≥ 4.5:1 for normal text
3429 | - [ ] Interactive elements have accessible names
3430 | - [ ] Form fields have associated labels
3431 | - [ ] Error messages are announced
3432 | 
3433 | **Tools:** [axe DevTools](https://www.deque.com/axe/devtools/), [WAVE](https://wave.webaim.org/), [Lighthouse](https://developers.google.com/web/tools/lighthouse), screen readers (NVDA, JAWS, VoiceOver)
3434 | 
```
Page 174/182FirstPrevNextLast