native-document 1.0.14 → 1.0.16-8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmrc.example +1 -0
- package/.vitepress/config.js +166 -0
- package/CHANGELOG.md +153 -0
- package/cdn.js +19 -0
- package/components.d.ts +2 -0
- package/components.js +30 -0
- package/devtools/ComponentRegistry.js +113 -0
- package/devtools/index.js +8 -0
- package/devtools/plugin/dev-tools-plugin.js +15 -0
- package/devtools/transformers/nd-vite-devtools.js +55 -0
- package/devtools/transformers/src/transformComponentForHrm.js +73 -0
- package/devtools/transformers/src/transformJsFile.js +9 -0
- package/devtools/transformers/src/utils.js +79 -0
- package/devtools/transformers/templates/hrm.hook.template.js +46 -0
- package/devtools/transformers/templates/hrm.orbservable.hook.template.js +76 -0
- package/devtools/widget/Widget.js +49 -0
- package/devtools/widget/widget.css +81 -0
- package/devtools/widget.js +23 -0
- package/dist/native-document.components.min.css +1 -0
- package/dist/native-document.components.min.js +23847 -0
- package/dist/native-document.dev.js +8665 -1313
- package/dist/native-document.dev.js.map +1 -0
- package/dist/native-document.devtools.min.js +1 -0
- package/dist/native-document.min.js +1 -1
- package/docs/advanced-components.md +419 -0
- package/docs/anchor.md +218 -131
- package/docs/cache.md +180 -0
- package/docs/cli.md +179 -0
- package/docs/components/accordion.md +172 -0
- package/docs/components/alert.md +99 -0
- package/docs/components/avatar.md +160 -0
- package/docs/components/badge.md +102 -0
- package/docs/components/breadcrumb.md +89 -0
- package/docs/components/button.md +183 -0
- package/docs/components/card.md +69 -0
- package/docs/components/context-menu.md +118 -0
- package/docs/components/data-table.md +345 -0
- package/docs/components/dropdown.md +214 -0
- package/docs/components/form/autocomplete-field.md +81 -0
- package/docs/components/form/checkbox-field.md +41 -0
- package/docs/components/form/checkbox-group-field.md +54 -0
- package/docs/components/form/color-field.md +64 -0
- package/docs/components/form/date-field.md +92 -0
- package/docs/components/form/field-collection.md +63 -0
- package/docs/components/form/file-field.md +203 -0
- package/docs/components/form/form-control.md +87 -0
- package/docs/components/form/image-field.md +90 -0
- package/docs/components/form/index.md +115 -0
- package/docs/components/form/number-field.md +65 -0
- package/docs/components/form/radio-field.md +51 -0
- package/docs/components/form/select-field.md +123 -0
- package/docs/components/form/slider.md +136 -0
- package/docs/components/form/string-field.md +134 -0
- package/docs/components/form/textarea-field.md +65 -0
- package/docs/components/form-fields.md +372 -0
- package/docs/components/getting-started.md +264 -0
- package/docs/components/index.md +337 -0
- package/docs/components/layout.md +279 -0
- package/docs/components/list.md +73 -0
- package/docs/components/menu.md +215 -0
- package/docs/components/modal.md +156 -0
- package/docs/components/pagination.md +95 -0
- package/docs/components/popover.md +131 -0
- package/docs/components/progress.md +111 -0
- package/docs/components/shortcut-manager.md +221 -0
- package/docs/components/simple-table.md +107 -0
- package/docs/components/skeleton.md +155 -0
- package/docs/components/spinner.md +100 -0
- package/docs/components/splitter.md +133 -0
- package/docs/components/stepper.md +163 -0
- package/docs/components/switch.md +113 -0
- package/docs/components/tabs.md +153 -0
- package/docs/components/toast.md +119 -0
- package/docs/components/tooltip.md +151 -0
- package/docs/components/traits.md +261 -0
- package/docs/conditional-rendering.md +177 -501
- package/docs/contributing.md +300 -25
- package/docs/core-concepts.md +209 -367
- package/docs/elements.md +268 -255
- package/docs/extending-native-document-element.md +259 -0
- package/docs/filters.md +247 -0
- package/docs/getting-started.md +199 -260
- package/docs/i18n.md +241 -0
- package/docs/index.md +76 -0
- package/docs/lifecycle-events.md +146 -67
- package/docs/list-rendering.md +387 -0
- package/docs/memory-management.md +135 -46
- package/docs/native-document-element.md +487 -0
- package/docs/native-fetch.md +213 -0
- package/docs/observable-resource.md +364 -0
- package/docs/observables.md +690 -356
- package/docs/routing.md +246 -646
- package/docs/state-management.md +213 -306
- package/docs/svg-elements.md +231 -0
- package/docs/theming.md +409 -0
- package/docs/tutorials/.gitkeep +0 -0
- package/docs/validation.md +98 -93
- package/docs/vitepress-conventions.md +219 -0
- package/elements.d.ts +7 -0
- package/elements.js +3 -4
- package/eslint.config.js +35 -0
- package/i18n.js +1 -0
- package/i18n.ts +2 -0
- package/index.d.ts +21 -0
- package/index.def.js +1086 -0
- package/index.js +19 -8
- package/package.json +59 -9
- package/readme.md +294 -90
- package/rollup.config.js +52 -3
- package/router.d.ts +7 -0
- package/router.js +0 -0
- package/src/components/$traits/has-draggable/HasDraggable.d.ts +4 -0
- package/src/components/$traits/has-draggable/HasDraggable.js +82 -0
- package/src/components/$traits/has-draggable/has-draggable.css +8 -0
- package/src/components/$traits/has-items/HasItems.d.ts +9 -0
- package/src/components/$traits/has-items/HasItems.js +64 -0
- package/src/components/$traits/has-position/HasFullPosition.d.ts +14 -0
- package/src/components/$traits/has-position/HasFullPosition.js +95 -0
- package/src/components/$traits/has-position/HasPosition.d.ts +7 -0
- package/src/components/$traits/has-position/HasPosition.js +45 -0
- package/src/components/$traits/has-resizable/HasResizable.d.ts +13 -0
- package/src/components/$traits/has-resizable/HasResizable.js +122 -0
- package/src/components/$traits/has-resizable/has-resizable.css +121 -0
- package/src/components/$traits/has-validation/HasValidation.d.ts +17 -0
- package/src/components/$traits/has-validation/HasValidation.js +133 -0
- package/src/components/BaseComponent.d.ts +32 -0
- package/src/components/BaseComponent.js +247 -0
- package/src/components/accordion/Accordion.js +268 -0
- package/src/components/accordion/AccordionItem.js +233 -0
- package/src/components/accordion/index.js +7 -0
- package/src/components/accordion/types/Accordion.d.ts +47 -0
- package/src/components/accordion/types/AccordionItem.d.ts +48 -0
- package/src/components/alert/Alert.js +350 -0
- package/src/components/alert/index.js +6 -0
- package/src/components/alert/types/Alert.d.ts +62 -0
- package/src/components/avatar/Avatar.js +430 -0
- package/src/components/avatar/AvatarGroup.js +97 -0
- package/src/components/avatar/index.js +7 -0
- package/src/components/avatar/types/Avatar.d.ts +74 -0
- package/src/components/avatar/types/AvatarGroup.d.ts +32 -0
- package/src/components/badge/Badge.js +245 -0
- package/src/components/badge/index.js +6 -0
- package/src/components/badge/types/Badge.d.ts +51 -0
- package/src/components/base-component.css +0 -0
- package/src/components/breadcrumb/BreadCrumb.js +138 -0
- package/src/components/breadcrumb/index.js +5 -0
- package/src/components/breadcrumb/types/BreadCrumb.d.ts +42 -0
- package/src/components/button/Button.js +320 -0
- package/src/components/button/index.js +5 -0
- package/src/components/button/types/Button.d.ts +62 -0
- package/src/components/card/Card.js +282 -0
- package/src/components/card/index.js +5 -0
- package/src/components/card/types/Card.d.ts +42 -0
- package/src/components/context-menu/ContextMenu.js +127 -0
- package/src/components/context-menu/ContextMenuGroup.js +29 -0
- package/src/components/context-menu/ContextMenuItem.js +28 -0
- package/src/components/context-menu/index.js +10 -0
- package/src/components/context-menu/types/ContextMenu.d.ts +30 -0
- package/src/components/context-menu/types/ContextMenuGroup.d.ts +18 -0
- package/src/components/context-menu/types/ContextMenuItem.d.ts +18 -0
- package/src/components/divider/Divider.js +256 -0
- package/src/components/divider/index.js +6 -0
- package/src/components/divider/types/Divider.d.ts +55 -0
- package/src/components/dropdown/Dropdown.js +531 -0
- package/src/components/dropdown/DropdownDivider.js +45 -0
- package/src/components/dropdown/DropdownGroup.js +83 -0
- package/src/components/dropdown/DropdownItem.js +150 -0
- package/src/components/dropdown/DropdownTrigger.js +93 -0
- package/src/components/dropdown/helpers.js +53 -0
- package/src/components/dropdown/index.js +13 -0
- package/src/components/dropdown/types/Dropdown.d.ts +88 -0
- package/src/components/dropdown/types/DropdownDivider.d.ts +20 -0
- package/src/components/dropdown/types/DropdownGroup.d.ts +25 -0
- package/src/components/dropdown/types/DropdownItem.d.ts +41 -0
- package/src/components/dropdown/types/DropdownTrigger.d.ts +32 -0
- package/src/components/form/FormControl.js +498 -0
- package/src/components/form/field/Field.js +419 -0
- package/src/components/form/field/FieldCollection.js +292 -0
- package/src/components/form/field/types/AutocompleteField.js +168 -0
- package/src/components/form/field/types/CheckboxField.js +77 -0
- package/src/components/form/field/types/CheckboxGroupField.js +171 -0
- package/src/components/form/field/types/ColorField.js +102 -0
- package/src/components/form/field/types/DateField.js +315 -0
- package/src/components/form/field/types/EmailField.js +104 -0
- package/src/components/form/field/types/FileField.js +276 -0
- package/src/components/form/field/types/HiddenField.js +44 -0
- package/src/components/form/field/types/ImageField.js +138 -0
- package/src/components/form/field/types/NumberField.js +177 -0
- package/src/components/form/field/types/PasswordField.js +200 -0
- package/src/components/form/field/types/RadioField.js +145 -0
- package/src/components/form/field/types/RangeField.js +117 -0
- package/src/components/form/field/types/SearchField.js +66 -0
- package/src/components/form/field/types/SelectField.js +247 -0
- package/src/components/form/field/types/StringField.js +148 -0
- package/src/components/form/field/types/TelField.js +98 -0
- package/src/components/form/field/types/TextAreaField.js +142 -0
- package/src/components/form/field/types/TimeField.js +215 -0
- package/src/components/form/field/types/UrlField.js +115 -0
- package/src/components/form/field/types/file-field-mode/FileAvatarMode.js +183 -0
- package/src/components/form/field/types/file-field-mode/FileDropzoneMode.js +117 -0
- package/src/components/form/field/types/file-field-mode/FileItemPreview.js +150 -0
- package/src/components/form/field/types/file-field-mode/FileNativeMode.js +43 -0
- package/src/components/form/field/types/file-field-mode/FileUploadButtonMode.js +120 -0
- package/src/components/form/field/types/file-field-mode/FileWallMode.js +106 -0
- package/src/components/form/index.js +61 -0
- package/src/components/form/merge +0 -0
- package/src/components/form/types/Field.d.ts +73 -0
- package/src/components/form/types/FieldCollection.d.ts +53 -0
- package/src/components/form/types/FormControl.d.ts +64 -0
- package/src/components/form/types/fields/AutocompleteField.d.ts +48 -0
- package/src/components/form/types/fields/CheckboxField.d.ts +33 -0
- package/src/components/form/types/fields/CheckboxGroupField.d.ts +49 -0
- package/src/components/form/types/fields/ColorField.d.ts +37 -0
- package/src/components/form/types/fields/DateField.d.ts +70 -0
- package/src/components/form/types/fields/EmailField.d.ts +35 -0
- package/src/components/form/types/fields/FileAvatarMode.d.ts +46 -0
- package/src/components/form/types/fields/FileDropzoneMode.d.ts +28 -0
- package/src/components/form/types/fields/FileField.d.ts +56 -0
- package/src/components/form/types/fields/FileItemPreview.d.ts +35 -0
- package/src/components/form/types/fields/FileNativeMode.d.ts +21 -0
- package/src/components/form/types/fields/FileUploadButtonMode.d.ts +34 -0
- package/src/components/form/types/fields/FileWallMode.d.ts +32 -0
- package/src/components/form/types/fields/HiddenField.d.ts +26 -0
- package/src/components/form/types/fields/ImageField.d.ts +45 -0
- package/src/components/form/types/fields/NumberField.d.ts +48 -0
- package/src/components/form/types/fields/PasswordField.d.ts +46 -0
- package/src/components/form/types/fields/RadioField.d.ts +48 -0
- package/src/components/form/types/fields/RangeField.d.ts +44 -0
- package/src/components/form/types/fields/SearchField.d.ts +34 -0
- package/src/components/form/types/fields/SelectField.d.ts +71 -0
- package/src/components/form/types/fields/StringField.d.ts +48 -0
- package/src/components/form/types/fields/TelField.d.ts +37 -0
- package/src/components/form/types/fields/TextAreaField.d.ts +44 -0
- package/src/components/form/types/fields/TimeField.d.ts +51 -0
- package/src/components/form/types/fields/UrlField.d.ts +35 -0
- package/src/components/form/utils.js +17 -0
- package/src/components/form/validation/Validation.js +565 -0
- package/src/components/index.d.ts +160 -0
- package/src/components/list/HasListItem.js +171 -0
- package/src/components/list/List.js +125 -0
- package/src/components/list/ListDivider.js +39 -0
- package/src/components/list/ListGroup.js +135 -0
- package/src/components/list/ListItem.js +212 -0
- package/src/components/list/index.js +12 -0
- package/src/components/list/types/List.d.ts +43 -0
- package/src/components/list/types/ListGroup.d.ts +37 -0
- package/src/components/list/types/ListItem.d.ts +53 -0
- package/src/components/menu/HasMenuItem.js +182 -0
- package/src/components/menu/Menu.js +227 -0
- package/src/components/menu/MenuDivider.js +37 -0
- package/src/components/menu/MenuGroup.js +126 -0
- package/src/components/menu/MenuItem.js +190 -0
- package/src/components/menu/MenuLink.js +51 -0
- package/src/components/menu/index.js +14 -0
- package/src/components/menu/types/Menu.d.ts +60 -0
- package/src/components/menu/types/MenuDivider.d.ts +19 -0
- package/src/components/menu/types/MenuGroup.d.ts +44 -0
- package/src/components/menu/types/MenuItem.d.ts +46 -0
- package/src/components/menu/types/MenuLink.d.ts +16 -0
- package/src/components/modal/Modal.js +524 -0
- package/src/components/modal/index.js +5 -0
- package/src/components/modal/types/Modal.d.ts +94 -0
- package/src/components/pagination/Pagination.js +411 -0
- package/src/components/pagination/index.js +5 -0
- package/src/components/pagination/types/Pagination.d.ts +68 -0
- package/src/components/popover/Popover.js +459 -0
- package/src/components/popover/PopoverFooter.js +61 -0
- package/src/components/popover/PopoverHeader.js +68 -0
- package/src/components/popover/index.js +10 -0
- package/src/components/popover/types/Popover.d.ts +83 -0
- package/src/components/popover/types/PopoverFooter.d.ts +24 -0
- package/src/components/popover/types/PopoverHeader.d.ts +26 -0
- package/src/components/progress/Progress.js +401 -0
- package/src/components/progress/index.js +6 -0
- package/src/components/progress/types/Progress.d.ts +77 -0
- package/src/components/skeleton/Skeleton.js +228 -0
- package/src/components/skeleton/index.js +6 -0
- package/src/components/skeleton/types/Skeleton.d.ts +55 -0
- package/src/components/slider/Slider.js +406 -0
- package/src/components/slider/index.js +5 -0
- package/src/components/slider/types/Slider.d.ts +82 -0
- package/src/components/spacer/Spacer.js +27 -0
- package/src/components/spacer/index.js +5 -0
- package/src/components/spacer/types/Spacer.d.ts +19 -0
- package/src/components/spinner/Spinner.js +350 -0
- package/src/components/spinner/index.js +5 -0
- package/src/components/spinner/types/Spinner.d.ts +71 -0
- package/src/components/splitter/Splitter.js +164 -0
- package/src/components/splitter/SplitterGutter.js +140 -0
- package/src/components/splitter/SplitterPanel.js +143 -0
- package/src/components/splitter/index.js +10 -0
- package/src/components/splitter/types/Splitter.d.ts +38 -0
- package/src/components/splitter/types/SplitterGutter.d.ts +38 -0
- package/src/components/splitter/types/SplitterPanel.d.ts +41 -0
- package/src/components/stacks/AbsoluteStack.js +53 -0
- package/src/components/stacks/FixedStack.js +53 -0
- package/src/components/stacks/HStack.js +54 -0
- package/src/components/stacks/PositionStack.js +254 -0
- package/src/components/stacks/RelativeStack.js +53 -0
- package/src/components/stacks/Stack.js +166 -0
- package/src/components/stacks/VStack.js +55 -0
- package/src/components/stacks/index.js +21 -0
- package/src/components/stacks/types/AbsoluteStack.d.ts +16 -0
- package/src/components/stacks/types/FixedStack.d.ts +16 -0
- package/src/components/stacks/types/HStack.d.ts +16 -0
- package/src/components/stacks/types/PositionStack.d.ts +54 -0
- package/src/components/stacks/types/RelativeStack.d.ts +17 -0
- package/src/components/stacks/types/Stack.d.ts +39 -0
- package/src/components/stacks/types/VStack.d.ts +16 -0
- package/src/components/stepper/Stepper.js +461 -0
- package/src/components/stepper/StepperStep.js +241 -0
- package/src/components/stepper/index.js +8 -0
- package/src/components/stepper/types/Stepper.d.ts +68 -0
- package/src/components/stepper/types/StepperStep.d.ts +54 -0
- package/src/components/switch/Switch.js +266 -0
- package/src/components/switch/index.js +6 -0
- package/src/components/switch/types/Switch.d.ts +55 -0
- package/src/components/table/Column.js +212 -0
- package/src/components/table/ColumnGroup.js +90 -0
- package/src/components/table/DataTable.js +720 -0
- package/src/components/table/SimpleTable.js +139 -0
- package/src/components/table/index.js +7 -0
- package/src/components/table/types/Column.d.ts +49 -0
- package/src/components/table/types/ColumnGroup.d.ts +28 -0
- package/src/components/table/types/DataTable.d.ts +97 -0
- package/src/components/table/types/SimpleTable.d.ts +40 -0
- package/src/components/tabs/Tabs.js +395 -0
- package/src/components/tabs/index.js +6 -0
- package/src/components/tabs/types/Tabs.d.ts +78 -0
- package/src/components/toast/Toast.js +262 -0
- package/src/components/toast/ToastError.js +0 -0
- package/src/components/toast/ToastInfo.js +0 -0
- package/src/components/toast/ToastSuccess.js +0 -0
- package/src/components/toast/ToastWarning.js +0 -0
- package/src/components/toast/index.js +5 -0
- package/src/components/toast/types/Toast.d.ts +57 -0
- package/src/components/toast/types/ToastError.d.ts +7 -0
- package/src/components/toast/types/ToastInfo.d.ts +7 -0
- package/src/components/toast/types/ToastSuccess.d.ts +7 -0
- package/src/components/toast/types/ToastWarning.d.ts +7 -0
- package/src/components/tooltip/Tooltip.js +359 -0
- package/src/components/tooltip/index.js +5 -0
- package/src/components/tooltip/prototypes.js +6 -0
- package/src/components/tooltip/types/Tooltip.d.ts +65 -0
- package/src/{data → core/data}/MemoryManager.js +9 -22
- package/src/core/data/Observable.js +227 -0
- package/src/core/data/ObservableArray.js +522 -0
- package/src/core/data/ObservableChecker.js +39 -0
- package/src/core/data/ObservableItem.js +611 -0
- package/src/core/data/ObservableObject.js +274 -0
- package/src/core/data/ObservableResource.js +315 -0
- package/src/core/data/ObservableWhen.js +54 -0
- package/src/core/data/Store.js +520 -0
- package/src/core/data/observable-helpers/observable.is-to.js +390 -0
- package/src/core/data/observable-helpers/observable.prototypes.js +145 -0
- package/src/core/elements/anchor/anchor-with-sentinel.js +66 -0
- package/src/core/elements/anchor/anchor.js +210 -0
- package/src/core/elements/anchor/one-child-anchor-overwriting.js +66 -0
- package/src/core/elements/content-formatter.js +169 -0
- package/src/core/elements/control/for-each-array.js +292 -0
- package/src/core/elements/control/for-each.js +170 -0
- package/src/core/elements/control/show-if.js +94 -0
- package/src/core/elements/control/show-when.js +54 -0
- package/src/core/elements/control/switch.js +141 -0
- package/src/core/elements/description-list.js +19 -0
- package/src/core/elements/form.js +255 -0
- package/src/core/elements/fragment.js +8 -0
- package/src/core/elements/html5-semantics.js +55 -0
- package/src/core/elements/img.js +59 -0
- package/src/{elements → core/elements}/index.js +5 -4
- package/src/core/elements/interactive.js +25 -0
- package/src/core/elements/list.js +37 -0
- package/src/core/elements/medias.js +37 -0
- package/src/core/elements/meta-data.js +43 -0
- package/src/core/elements/svg.js +61 -0
- package/src/core/elements/table.js +73 -0
- package/src/{errors → core/errors}/ArgTypesError.js +1 -1
- package/src/{errors → core/errors}/NativeDocumentError.js +0 -0
- package/src/core/utils/HasEventEmitter.js +85 -0
- package/src/core/utils/args-types.js +140 -0
- package/src/core/utils/cache.js +5 -0
- package/src/core/utils/callback-handler.js +50 -0
- package/src/core/utils/debug-manager.js +40 -0
- package/src/core/utils/events.js +148 -0
- package/src/core/utils/filters/date.js +178 -0
- package/src/core/utils/filters/index.js +4 -0
- package/src/core/utils/filters/standard.js +263 -0
- package/src/core/utils/filters/strings.js +67 -0
- package/src/core/utils/filters/utils.js +77 -0
- package/src/core/utils/formatters.js +90 -0
- package/src/core/utils/helpers.js +144 -0
- package/src/core/utils/localstorage.js +57 -0
- package/src/core/utils/memoize.js +115 -0
- package/src/core/utils/plugins-manager.js +81 -0
- package/src/core/utils/property-accumulator.js +72 -0
- package/src/core/utils/prototypes.js +44 -0
- package/src/core/utils/shortcut-manager.js +242 -0
- package/src/{utils → core/utils}/validator.js +58 -22
- package/src/core/wrappers/AttributesWrapper.js +181 -0
- package/src/core/wrappers/DocumentObserver.js +182 -0
- package/src/core/wrappers/ElementCreator.js +110 -0
- package/src/core/wrappers/HtmlElementWrapper.js +98 -0
- package/src/core/wrappers/NDElement.js +613 -0
- package/src/core/wrappers/NdPrototype.js +233 -0
- package/src/core/wrappers/SingletonView.js +99 -0
- package/src/core/wrappers/SvgElementWrapper.js +15 -0
- package/src/core/wrappers/TemplateBinding.js +7 -0
- package/src/core/wrappers/constants.js +66 -0
- package/src/core/wrappers/prototypes/attributes-extensions.js +24 -0
- package/src/core/wrappers/prototypes/bind-class-extensions.js +0 -0
- package/src/core/wrappers/prototypes/nd-element-extensions.js +149 -0
- package/src/core/wrappers/prototypes/nd-element.transition.extensions.js +127 -0
- package/src/core/wrappers/template-cloner/NodeCloner.js +209 -0
- package/src/core/wrappers/template-cloner/TemplateCloner.js +192 -0
- package/src/core/wrappers/template-cloner/attributes-hydrator.js +142 -0
- package/src/core/wrappers/template-cloner/utils.js +173 -0
- package/src/fetch/NativeFetch.js +89 -0
- package/src/i18n/bin/scan.js +132 -0
- package/src/i18n/index.d.ts +2 -0
- package/src/i18n/service/I18nService.d.ts +27 -0
- package/src/i18n/service/I18nService.js +46 -0
- package/src/i18n/service/functions.d.ts +22 -0
- package/src/i18n/service/functions.js +29 -0
- package/src/router/Route.js +33 -8
- package/src/router/RouteGroupHelper.js +10 -2
- package/src/router/Router.js +63 -22
- package/src/router/RouterComponent.js +114 -6
- package/src/{errors → router/errors}/RouterError.js +0 -1
- package/src/router/link.js +9 -10
- package/src/router/modes/HashRouter.js +2 -2
- package/src/router/modes/HistoryRouter.js +2 -3
- package/src/router/modes/MemoryRouter.js +1 -1
- package/src/ui/components/accordion/AccordionItemRender.js +63 -0
- package/src/ui/components/accordion/AccordionRender.js +35 -0
- package/src/ui/components/accordion/accordion.css +121 -0
- package/src/ui/components/alert/AlertRender.js +81 -0
- package/src/ui/components/alert/alert.css +163 -0
- package/src/ui/components/avatar/avata-group/AvatarGroupRender.js +50 -0
- package/src/ui/components/avatar/avata-group/avatar-group.css +38 -0
- package/src/ui/components/avatar/avatar/AvatarRender.js +87 -0
- package/src/ui/components/avatar/avatar/avatar.css +189 -0
- package/src/ui/components/badge/BadgeRender.js +25 -0
- package/src/ui/components/badge/badge.css +168 -0
- package/src/ui/components/breadcrumb/BreadcrumbRender.js +44 -0
- package/src/ui/components/breadcrumb/breadcrumb.css +55 -0
- package/src/ui/components/button/ButtonRender.js +65 -0
- package/src/ui/components/button/button.css +296 -0
- package/src/ui/components/card/CardRender.js +133 -0
- package/src/ui/components/card/card.css +169 -0
- package/src/ui/components/contextmenu/ContextmenuRender.js +68 -0
- package/src/ui/components/contextmenu/contextmenu.css +36 -0
- package/src/ui/components/divider/DividerRender.js +70 -0
- package/src/ui/components/divider/divider.css +70 -0
- package/src/ui/components/dropdown/DropdownRender.js +92 -0
- package/src/ui/components/dropdown/divider/DropdownDividerRender.js +9 -0
- package/src/ui/components/dropdown/divider/dropdown-divider.css +0 -0
- package/src/ui/components/dropdown/dropdown.css +179 -0
- package/src/ui/components/dropdown/group/DropdownGroupRender.js +23 -0
- package/src/ui/components/dropdown/group/dropdown-group.css +0 -0
- package/src/ui/components/dropdown/item/DropdownItemRender.js +29 -0
- package/src/ui/components/dropdown/item/dropdown-item.css +0 -0
- package/src/ui/components/form/FieldCollectionRender.js +110 -0
- package/src/ui/components/form/FormControlRender.js +85 -0
- package/src/ui/components/form/field-collection.css +55 -0
- package/src/ui/components/form/fields/AutocompleteFieldRender.js +143 -0
- package/src/ui/components/form/fields/CheckboxFieldRender.js +59 -0
- package/src/ui/components/form/fields/CheckboxGroupFieldRender.js +92 -0
- package/src/ui/components/form/fields/ColorFieldRender.js +30 -0
- package/src/ui/components/form/fields/DateFieldRender.js +155 -0
- package/src/ui/components/form/fields/EmailFieldRender.js +5 -0
- package/src/ui/components/form/fields/FieldRender.js +118 -0
- package/src/ui/components/form/fields/FileFieldRender.js +41 -0
- package/src/ui/components/form/fields/HiddenFieldRender.js +13 -0
- package/src/ui/components/form/fields/ImageFieldRender.js +0 -0
- package/src/ui/components/form/fields/NumberFieldRender.js +52 -0
- package/src/ui/components/form/fields/PasswordFieldRender.js +65 -0
- package/src/ui/components/form/fields/RadioFieldRender.js +77 -0
- package/src/ui/components/form/fields/RangeFieldRender.js +122 -0
- package/src/ui/components/form/fields/SelectFieldRender.js +248 -0
- package/src/ui/components/form/fields/SliderFieldRender.js +359 -0
- package/src/ui/components/form/fields/StringFieldRender.js +6 -0
- package/src/ui/components/form/fields/TelFieldRender.js +6 -0
- package/src/ui/components/form/fields/TextAreaFieldRender.js +96 -0
- package/src/ui/components/form/fields/TimeFieldRender.js +142 -0
- package/src/ui/components/form/fields/UrlFieldRender.js +6 -0
- package/src/ui/components/form/fields/date-field.css +32 -0
- package/src/ui/components/form/fields/field.css +402 -0
- package/src/ui/components/form/fields/file-field.css +79 -0
- package/src/ui/components/form/fields/password-field.css +50 -0
- package/src/ui/components/form/fields/range-field.css +120 -0
- package/src/ui/components/form/fields/slider.css +195 -0
- package/src/ui/components/form/file-upload-mode/FileAvatarModeRender.js +143 -0
- package/src/ui/components/form/file-upload-mode/FileDropzoneModeRender.js +108 -0
- package/src/ui/components/form/file-upload-mode/FileNativeModeRender.js +22 -0
- package/src/ui/components/form/file-upload-mode/FileUploadButtonModeRender.js +89 -0
- package/src/ui/components/form/file-upload-mode/FileWallModeRender.js +90 -0
- package/src/ui/components/form/file-upload-mode/file-avatar-mode.css +139 -0
- package/src/ui/components/form/file-upload-mode/file-dropzone-mode.css +88 -0
- package/src/ui/components/form/file-upload-mode/file-upload-button-mode.css +44 -0
- package/src/ui/components/form/file-upload-mode/file-wall-mode.css +88 -0
- package/src/ui/components/form/form-control.css +40 -0
- package/src/ui/components/form/helpers.js +111 -0
- package/src/ui/components/form/index.js +27 -0
- package/src/ui/components/list/ListRender.js +18 -0
- package/src/ui/components/list/divider/ListDividerRender.js +10 -0
- package/src/ui/components/list/divider/list-divider.css +12 -0
- package/src/ui/components/list/group/ListGroupRender.js +61 -0
- package/src/ui/components/list/group/list-group.css +62 -0
- package/src/ui/components/list/item/ListItemRender.js +238 -0
- package/src/ui/components/list/item/list-item.css +191 -0
- package/src/ui/components/list/list.css +24 -0
- package/src/ui/components/menu/MenuDividerRender.js +12 -0
- package/src/ui/components/menu/MenuGroupRender.js +59 -0
- package/src/ui/components/menu/MenuItemRender.js +57 -0
- package/src/ui/components/menu/MenuLinkRender.js +55 -0
- package/src/ui/components/menu/MenuRender.js +22 -0
- package/src/ui/components/menu/helpers.js +121 -0
- package/src/ui/components/menu/menu.css +308 -0
- package/src/ui/components/modal/ModalRender.js +118 -0
- package/src/ui/components/modal/modal.css +156 -0
- package/src/ui/components/pagination/PaginationRender.js +112 -0
- package/src/ui/components/pagination/pagination.css +63 -0
- package/src/ui/components/popover/PopoverRender.js +233 -0
- package/src/ui/components/popover/popover.css +139 -0
- package/src/ui/components/progress/ProgressRender.js +168 -0
- package/src/ui/components/progress/progress.css +197 -0
- package/src/ui/components/skeleton/SkeletonRender.js +136 -0
- package/src/ui/components/skeleton/skeleton.css +154 -0
- package/src/ui/components/spacer/SpacerRender.js +10 -0
- package/src/ui/components/spinner/SpinnerRender.js +47 -0
- package/src/ui/components/spinner/spinner.css +152 -0
- package/src/ui/components/splitter/SplitterGutterRender.js +94 -0
- package/src/ui/components/splitter/SplitterPanelRender.js +38 -0
- package/src/ui/components/splitter/SplitterRender.js +75 -0
- package/src/ui/components/splitter/splitter.css +128 -0
- package/src/ui/components/stacks/PositionStackRender.js +39 -0
- package/src/ui/components/stacks/StackRender.js +41 -0
- package/src/ui/components/stacks/absolute-stack/AbsoluteStackRender.js +5 -0
- package/src/ui/components/stacks/fixed-stack/FixedStackRender.js +5 -0
- package/src/ui/components/stacks/h-stack/HStackRender.js +7 -0
- package/src/ui/components/stacks/h-stack/h-stack.css +4 -0
- package/src/ui/components/stacks/index.js +5 -0
- package/src/ui/components/stacks/position-stack.css +62 -0
- package/src/ui/components/stacks/relative-stack/RelativeStackRender.js +7 -0
- package/src/ui/components/stacks/relative-stack/relative-stack.css +3 -0
- package/src/ui/components/stacks/stack.css +78 -0
- package/src/ui/components/stacks/v-stack/VStackRender.js +6 -0
- package/src/ui/components/stacks/v-stack/v-stack.css +4 -0
- package/src/ui/components/stepper/StepperRender.js +71 -0
- package/src/ui/components/stepper/StepperStepRender.js +67 -0
- package/src/ui/components/stepper/stepper.css +359 -0
- package/src/ui/components/switch/SwitchRender.js +83 -0
- package/src/ui/components/switch/switch.css +143 -0
- package/src/ui/components/table/data-table/DataTableRender.js +50 -0
- package/src/ui/components/table/data-table/bulk-actions.js +34 -0
- package/src/ui/components/table/data-table/data-table.css +246 -0
- package/src/ui/components/table/data-table/pagination.js +56 -0
- package/src/ui/components/table/data-table/tables.js +368 -0
- package/src/ui/components/table/data-table/toolbar.js +67 -0
- package/src/ui/components/table/simple-table/SimpleTableRender.js +203 -0
- package/src/ui/components/table/simple-table/simple-table.css +50 -0
- package/src/ui/components/tabs/TabsRender.js +226 -0
- package/src/ui/components/tabs/tabs.css +253 -0
- package/src/ui/components/toast/ToastRender.js +99 -0
- package/src/ui/components/toast/toast.css +201 -0
- package/src/ui/components/tooltip/TooltipRender.js +8 -0
- package/src/ui/components/tooltip/tooltip.css +113 -0
- package/src/ui/index.js +47 -0
- package/src/ui/theme.js +0 -0
- package/src/ui/theme.scss +1 -0
- package/src/ui/tokens/animation.scss +36 -0
- package/src/ui/tokens/colors-dark.scss +58 -0
- package/src/ui/tokens/colors.scss +54 -0
- package/src/ui/tokens/components.scss +32 -0
- package/src/ui/tokens/fonts.scss +57 -0
- package/src/ui/tokens/glass.scss +10 -0
- package/src/ui/tokens/index.scss +38 -0
- package/src/ui/tokens/layouts.scss +228 -0
- package/src/ui/tokens/opacity.scss +21 -0
- package/src/ui/tokens/others.scss +11 -0
- package/src/ui/tokens/radius.scss +6 -0
- package/src/ui/tokens/reset.scss +51 -0
- package/src/ui/tokens/shadows.scss +29 -0
- package/src/ui/tokens/spacings.scss +13 -0
- package/src/ui/tokens/vars.scss +35 -0
- package/src/ui/tokens/viewports.scss +30 -0
- package/types/args-types.d.ts +58 -0
- package/types/control-flow.d.ts +62 -0
- package/types/elements.d.ts +231 -0
- package/types/filters/dates.d.ts +43 -0
- package/types/filters/index.d.ts +4 -0
- package/types/filters/standard.d.ts +70 -0
- package/types/filters/strings.d.ts +21 -0
- package/types/filters/types.d.ts +20 -0
- package/types/forms.d.ts +84 -0
- package/types/globals.d.ts +543 -0
- package/types/images.d.ts +23 -0
- package/types/localStorage.ts +102 -0
- package/types/memoize.d.ts +26 -0
- package/types/native-fetch.d.ts +72 -0
- package/types/nd-element.d.ts +407 -0
- package/types/observable-resource.d.ts +3 -0
- package/types/observable.d.ts +227 -0
- package/types/plugins-manager.d.ts +65 -0
- package/types/polyfill.d.ts +18 -0
- package/types/property-accumulator.d.ts +33 -0
- package/types/router.d.ts +85 -0
- package/types/service.d.ts +23 -0
- package/types/singleton.d.ts +19 -0
- package/types/store.d.ts +63 -0
- package/types/template-cloner.ts +43 -0
- package/types/validator.ts +66 -0
- package/ui.js +1 -0
- package/utils.d.ts +4 -0
- package/utils.js +12 -0
- package/src/data/Observable.js +0 -233
- package/src/data/ObservableChecker.js +0 -38
- package/src/data/ObservableItem.js +0 -116
- package/src/data/Store.js +0 -74
- package/src/elements/anchor.js +0 -84
- package/src/elements/content-formatter.js +0 -32
- package/src/elements/control/for-each.js +0 -174
- package/src/elements/control/show-if.js +0 -79
- package/src/elements/control/switch.js +0 -98
- package/src/elements/description-list.js +0 -5
- package/src/elements/form.js +0 -71
- package/src/elements/html5-semantics.js +0 -12
- package/src/elements/img.js +0 -45
- package/src/elements/interactive.js +0 -7
- package/src/elements/list.js +0 -6
- package/src/elements/medias.js +0 -8
- package/src/elements/meta-data.js +0 -9
- package/src/elements/table.js +0 -14
- package/src/utils/args-types.js +0 -100
- package/src/utils/debug-manager.js +0 -31
- package/src/utils/helpers.js +0 -37
- package/src/utils/plugins-manager.js +0 -12
- package/src/utils/prototypes.js +0 -45
- package/src/wrappers/AttributesWrapper.js +0 -157
- package/src/wrappers/DocumentObserver.js +0 -51
- package/src/wrappers/HtmlElementEventsWrapper.js +0 -77
- package/src/wrappers/HtmlElementWrapper.js +0 -206
- package/src/wrappers/constants.js +0 -2
|
@@ -1,628 +1,304 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
---
|
|
2
|
+
title: Conditional Rendering
|
|
3
|
+
description: Dynamically show, hide, or switch between content based on reactive state - ShowIf, Switch, Match, When, and more
|
|
4
|
+
---
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
# Conditional Rendering
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
NativeDocument's conditional rendering utilities automatically update the DOM when observable values change. All functions work with observables and manage DOM updates for you.
|
|
8
9
|
|
|
9
10
|
```javascript
|
|
10
|
-
import { ShowIf,
|
|
11
|
-
|
|
12
|
-
const isVisible = Observable(false);
|
|
13
|
-
|
|
14
|
-
// Content automatically appears/disappears based on isVisible
|
|
15
|
-
const conditionalContent = ShowIf(isVisible, 'This content toggles!');
|
|
11
|
+
import { ShowIf, HideIf, ShowWhen, Switch, Match, When } from 'native-document/elements';
|
|
16
12
|
```
|
|
17
13
|
|
|
18
|
-
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## `ShowIf` - Basic Conditional Display
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
Renders content only when the condition is truthy. When false, the content is removed from the DOM.
|
|
21
19
|
|
|
22
20
|
```javascript
|
|
23
|
-
const
|
|
21
|
+
const isVisible = Observable(false);
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
Button('Logout').nd.on.click(() =>
|
|
30
|
-
user.set({ ...user.val(), isLoggedIn: false })
|
|
31
|
-
),
|
|
32
|
-
|
|
33
|
-
// Shows only when user is logged in
|
|
34
|
-
ShowIf(user.check(u => u.isLoggedIn), 'Welcome back!')
|
|
35
|
-
]);
|
|
23
|
+
ShowIf(isVisible, Div('Hello!'))
|
|
24
|
+
|
|
25
|
+
// With a boolean (non-reactive)
|
|
26
|
+
ShowIf(true, Div('Always visible'))
|
|
36
27
|
```
|
|
37
28
|
|
|
38
|
-
###
|
|
29
|
+
### Function children
|
|
39
30
|
|
|
40
|
-
|
|
31
|
+
Pass a function to create content that reflects current observable values:
|
|
41
32
|
|
|
42
33
|
```javascript
|
|
43
34
|
const notifications = Observable.array([]);
|
|
44
35
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
// When notifications change, the badge updates automatically
|
|
51
|
-
notifications.push('New message');
|
|
36
|
+
ShowIf(notifications.isNotEmpty(),
|
|
37
|
+
() => Span({ class: 'badge' }, notifications.toLength())
|
|
38
|
+
)
|
|
52
39
|
```
|
|
53
40
|
|
|
54
|
-
###
|
|
55
|
-
|
|
56
|
-
Observable checkers create derived conditions for cleaner code:
|
|
41
|
+
### Options
|
|
57
42
|
|
|
58
43
|
```javascript
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const WeatherApp = Div([
|
|
64
|
-
Div(['Current temperature: ', temperature, '°C']),
|
|
65
|
-
ShowIf(isCold, Div({ class: 'cold' }, '🧥 It\'s cold! Wear a jacket.')),
|
|
66
|
-
ShowIf(isHot, Div({ class: 'hot' }, '☀️ It\'s hot! Stay hydrated.')),
|
|
67
|
-
Div([
|
|
68
|
-
Button('-').nd.on.click(() => --temperature.$value),
|
|
69
|
-
Button('+').nd.on.click(() => ++temperature.$value),
|
|
70
|
-
])
|
|
71
|
-
]);
|
|
44
|
+
ShowIf(condition, content, {
|
|
45
|
+
comment: 'my-component', // label visible in DOM comments (debug)
|
|
46
|
+
shouldKeepInCache: false // default true - set to false to recreate on each show
|
|
47
|
+
})
|
|
72
48
|
```
|
|
73
49
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
These functions provide convenient inverses to `ShowIf`:
|
|
50
|
+
### Practical example
|
|
77
51
|
|
|
78
52
|
```javascript
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
HideIfNot(isLoading, Div({ class: 'spinner' }, 'Loading...')),
|
|
53
|
+
const user = Observable({ name: 'Alice', isLoggedIn: false });
|
|
54
|
+
|
|
55
|
+
Div([
|
|
56
|
+
Button('Login').nd.onClick(() =>
|
|
57
|
+
user.set({ ...user.val(), isLoggedIn: true })
|
|
58
|
+
),
|
|
59
|
+
ShowIf(user.is(u => u.isLoggedIn),
|
|
60
|
+
() => Div(['Welcome back, ', user.select(u => u.name), '!'])
|
|
61
|
+
)
|
|
89
62
|
]);
|
|
90
63
|
```
|
|
91
64
|
|
|
92
|
-
|
|
93
|
-
```javascript
|
|
94
|
-
const condition = Observable(true);
|
|
95
|
-
|
|
96
|
-
// These are equivalent:
|
|
97
|
-
ShowIf(condition, content)
|
|
98
|
-
HideIfNot(condition, content)
|
|
65
|
+
---
|
|
99
66
|
|
|
100
|
-
|
|
101
|
-
HideIf(condition, content)
|
|
102
|
-
ShowIf(condition.check(val => !val), content)
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
## Switch - Binary Content Switching
|
|
67
|
+
## `HideIf` / `HideIfNot` - Inverse Conditions
|
|
106
68
|
|
|
107
|
-
|
|
69
|
+
Convenient inverses of `ShowIf`:
|
|
108
70
|
|
|
109
71
|
```javascript
|
|
110
|
-
const
|
|
72
|
+
const isLoading = Observable(true);
|
|
111
73
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
Switch(isDarkMode,
|
|
116
|
-
Div({ class: 'dark-indicator' }, '🌙 Dark Mode'), // when true
|
|
117
|
-
Div({ class: 'light-indicator' }, '☀️ Light Mode') // when false
|
|
118
|
-
)
|
|
119
|
-
]);
|
|
120
|
-
```
|
|
74
|
+
// Hide content while loading
|
|
75
|
+
HideIf(isLoading, Div('Data is ready'))
|
|
121
76
|
|
|
122
|
-
|
|
77
|
+
// Show content only while loading (equivalent to ShowIf)
|
|
78
|
+
HideIfNot(isLoading, Div('Loading...'))
|
|
79
|
+
```
|
|
123
80
|
|
|
124
|
-
|
|
81
|
+
Equivalences:
|
|
125
82
|
|
|
126
83
|
```javascript
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const UserGreeting = Switch(
|
|
130
|
-
user.check(u => u.isAuthenticated),
|
|
131
|
-
() => Div({ class: 'welcome' }, `Welcome back, ${user.val().name}!`),
|
|
132
|
-
() => Div({ class: 'login-prompt' }, 'Please sign in to continue')
|
|
133
|
-
);
|
|
84
|
+
ShowIf(condition, content) // same as HideIfNot(condition, content)
|
|
85
|
+
HideIf(condition, content) // same as ShowIf(condition.isFalsy(), content)
|
|
134
86
|
```
|
|
135
87
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
`Match` provides switch-case like functionality for handling multiple states:
|
|
139
|
-
|
|
140
|
-
```javascript
|
|
141
|
-
const requestStatus = Observable('idle');
|
|
88
|
+
---
|
|
142
89
|
|
|
143
|
-
|
|
144
|
-
idle: Div({ class: 'status-idle' }, 'Ready to make request'),
|
|
145
|
-
loading: Div({ class: 'status-loading' }, [
|
|
146
|
-
Span({ class: 'spinner' }),
|
|
147
|
-
' Loading...'
|
|
148
|
-
]),
|
|
149
|
-
success: Div({ class: 'status-success' }, '✅ Request completed'),
|
|
150
|
-
error: Div({ class: 'status-error' }, '❌ Request failed'),
|
|
151
|
-
timeout: Div({ class: 'status-timeout' }, '⏰ Request timed out')
|
|
152
|
-
});
|
|
153
|
-
```
|
|
90
|
+
## `ShowWhen` - Value Matching
|
|
154
91
|
|
|
155
|
-
|
|
92
|
+
Shows content when an observable matches a specific value.
|
|
156
93
|
|
|
157
|
-
|
|
94
|
+
**Two-argument form** - pass an `ObservableWhen` result from `.when()`:
|
|
158
95
|
|
|
159
96
|
```javascript
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
score: 0,
|
|
163
|
-
level: 1
|
|
164
|
-
});
|
|
97
|
+
const theme = Observable('light');
|
|
98
|
+
const isDark = theme.when('dark'); // ObservableWhen result
|
|
165
99
|
|
|
166
|
-
|
|
167
|
-
menu: () => Div({ class: 'game-menu' }, [
|
|
168
|
-
H1('Welcome to the Game'),
|
|
169
|
-
Button('Start Game').nd.on.click(() =>
|
|
170
|
-
gameState.set({ ...gameState.val(), phase: 'playing' })
|
|
171
|
-
)
|
|
172
|
-
]),
|
|
173
|
-
|
|
174
|
-
playing: () => Div({ class: 'game-ui' }, [
|
|
175
|
-
Div(['Score: ', gameState.check(s => s.score)]),
|
|
176
|
-
Div(['Level: ', gameState.check(s => s.level)]),
|
|
177
|
-
Button('Pause').nd.on.click(() =>
|
|
178
|
-
gameState.set({ ...gameState.val(), phase: 'paused' })
|
|
179
|
-
),
|
|
180
|
-
Button('Game Over').nd.on.click(() =>
|
|
181
|
-
gameState.set({ ...gameState.val(), phase: 'gameOver' })
|
|
182
|
-
)
|
|
183
|
-
]),
|
|
184
|
-
|
|
185
|
-
paused: () => Div({ class: 'game-paused' }, [
|
|
186
|
-
H2('Game Paused'),
|
|
187
|
-
Button('Resume').nd.on.click(() =>
|
|
188
|
-
gameState.set({ ...gameState.val(), phase: 'playing' })
|
|
189
|
-
)
|
|
190
|
-
]),
|
|
191
|
-
|
|
192
|
-
gameOver: () => Div({ class: 'game-over' }, [
|
|
193
|
-
H2('Game Over'),
|
|
194
|
-
Div(['Final Score: ', gameState.check(s => s.score)]),
|
|
195
|
-
Button('Play Again').nd.on.click(() =>
|
|
196
|
-
gameState.set({ phase: 'menu', score: 0, level: 1 })
|
|
197
|
-
)
|
|
198
|
-
])
|
|
199
|
-
});
|
|
100
|
+
ShowWhen(isDark, Div('Dark mode active'))
|
|
200
101
|
```
|
|
201
102
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
Handle unexpected values with default cases:
|
|
103
|
+
**Three-argument form** - pass the observable, the target value, and the content:
|
|
205
104
|
|
|
206
105
|
```javascript
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
const RoleBasedMenu = Match(userRole, {
|
|
210
|
-
admin: AdminMenu(),
|
|
211
|
-
moderator: ModeratorMenu(),
|
|
212
|
-
user: UserMenu(),
|
|
213
|
-
// Default case for unknown roles
|
|
214
|
-
default: GuestMenu()
|
|
215
|
-
});
|
|
106
|
+
ShowWhen(theme, 'dark', Div('Dark mode active'))
|
|
216
107
|
```
|
|
217
108
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
`When` provides a chainable interface for conditional rendering:
|
|
109
|
+
### Practical example
|
|
221
110
|
|
|
222
111
|
```javascript
|
|
223
|
-
const
|
|
112
|
+
const status = Observable('disconnected');
|
|
224
113
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
114
|
+
Div({ class: 'status-bar' }, [
|
|
115
|
+
ShowWhen(status, 'connecting', Span('Connecting...')),
|
|
116
|
+
ShowWhen(status, 'connected', Span('Connected')),
|
|
117
|
+
ShowWhen(status, 'disconnected', Span('Disconnected')),
|
|
118
|
+
ShowWhen(status, 'error', Span('Connection Error'))
|
|
119
|
+
]);
|
|
228
120
|
```
|
|
229
121
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
```javascript
|
|
233
|
-
const user = Observable({
|
|
234
|
-
age: 25,
|
|
235
|
-
hasLicense: true,
|
|
236
|
-
hasInsurance: false
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
const DrivingEligibility = When(user.check(u =>
|
|
240
|
-
u.age >= 18 && u.hasLicense && u.hasInsurance
|
|
241
|
-
))
|
|
242
|
-
.show(() => Div({ class: 'eligible' }, [
|
|
243
|
-
'✅ You can drive legally',
|
|
244
|
-
Div(`Age: ${user.val().age}, License: Yes, Insurance: Yes`)
|
|
245
|
-
]))
|
|
246
|
-
.otherwise(() => {
|
|
247
|
-
const u = user.val();
|
|
248
|
-
const issues = [];
|
|
249
|
-
if (u.age < 18) issues.push('Must be 18 or older');
|
|
250
|
-
if (!u.hasLicense) issues.push('Need a valid license');
|
|
251
|
-
if (!u.hasInsurance) issues.push('Need insurance coverage');
|
|
252
|
-
|
|
253
|
-
return Div({ class: 'not-eligible' }, [
|
|
254
|
-
'❌ Cannot drive legally',
|
|
255
|
-
Div(['Issues: ', issues.join(', ')])
|
|
256
|
-
]);
|
|
257
|
-
});
|
|
258
|
-
```
|
|
122
|
+
---
|
|
259
123
|
|
|
260
|
-
##
|
|
124
|
+
## `Switch` - Binary Content
|
|
261
125
|
|
|
262
|
-
|
|
126
|
+
Toggles between exactly two pieces of content based on a boolean observable:
|
|
263
127
|
|
|
264
128
|
```javascript
|
|
265
|
-
const
|
|
266
|
-
email: '',
|
|
267
|
-
password: '',
|
|
268
|
-
confirmPassword: ''
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
const isValidEmail = formData.email.check(e =>
|
|
272
|
-
e.includes('@') && e.includes('.') && e.length > 5
|
|
273
|
-
);
|
|
274
|
-
|
|
275
|
-
const isValidPassword = formData.password.check(p => p.length >= 8);
|
|
276
|
-
|
|
277
|
-
const passwordsMatch = Observable.computed(() => {
|
|
278
|
-
const data = formData.$val();
|
|
279
|
-
return data.password === data.confirmPassword && data.password.length > 0;
|
|
280
|
-
}, [formData.password, formData.confirmPassword]);
|
|
281
|
-
|
|
282
|
-
const canSubmit = Observable.computed(() =>
|
|
283
|
-
isValidEmail.val() && isValidPassword.val() && passwordsMatch.val(),
|
|
284
|
-
[isValidEmail, isValidPassword, passwordsMatch]
|
|
285
|
-
);
|
|
129
|
+
const isDarkMode = Observable(false);
|
|
286
130
|
|
|
287
|
-
|
|
288
|
-
//
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
placeholder: 'Email',
|
|
292
|
-
value: formData.email
|
|
293
|
-
}),
|
|
294
|
-
ShowIf(formData.email.check(e => e.length > 0 && !isValidEmail.val()),
|
|
295
|
-
Div({ class: 'error' }, 'Please enter a valid email address')
|
|
296
|
-
),
|
|
297
|
-
|
|
298
|
-
// Password field
|
|
299
|
-
Input({
|
|
300
|
-
type: 'password',
|
|
301
|
-
placeholder: 'Password',
|
|
302
|
-
value: formData.password
|
|
303
|
-
}),
|
|
304
|
-
ShowIf(formData.password.check(p => p.length > 0 && p.length < 8),
|
|
305
|
-
Div({ class: 'error' }, 'Password must be at least 8 characters')
|
|
306
|
-
),
|
|
307
|
-
|
|
308
|
-
// Confirm password (only show after password is valid)
|
|
309
|
-
ShowIf(isValidPassword, [
|
|
310
|
-
Input({
|
|
311
|
-
type: 'password',
|
|
312
|
-
placeholder: 'Confirm Password',
|
|
313
|
-
value: formData.confirmPassword
|
|
314
|
-
}),
|
|
315
|
-
ShowIf(formData.confirmPassword.check(p => p.length > 0 && !passwordsMatch.val()),
|
|
316
|
-
Div({ class: 'error' }, 'Passwords do not match')
|
|
317
|
-
)
|
|
318
|
-
]),
|
|
319
|
-
|
|
320
|
-
// Submit button
|
|
321
|
-
Switch(canSubmit,
|
|
322
|
-
Button('Create Account').nd.on.click(() => {
|
|
323
|
-
console.log('Creating account...', formData.$val());
|
|
324
|
-
}),
|
|
325
|
-
Button({ disabled: true, class: 'disabled' }, 'Create Account')
|
|
326
|
-
)
|
|
327
|
-
]);
|
|
131
|
+
Switch(isDarkMode,
|
|
132
|
+
Div('Dark mode'), // when true
|
|
133
|
+
Div('Light mode') // when false
|
|
134
|
+
)
|
|
328
135
|
```
|
|
329
136
|
|
|
330
|
-
|
|
137
|
+
With function children:
|
|
331
138
|
|
|
332
139
|
```javascript
|
|
333
|
-
const
|
|
334
|
-
user: null,
|
|
335
|
-
currentView: 'welcome',
|
|
336
|
-
settings: { theme: 'light', notifications: true }
|
|
337
|
-
});
|
|
140
|
+
const user = Observable({ name: 'Guest', isLoggedIn: false });
|
|
338
141
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
// Header - changes based on auth state
|
|
344
|
-
Header({ class: 'app-header' }, [
|
|
345
|
-
H1('My App'),
|
|
346
|
-
Switch(isLoggedIn,
|
|
347
|
-
// Authenticated header
|
|
348
|
-
() => Div({ class: 'user-menu' }, [
|
|
349
|
-
Span(['Welcome, ', appState.user.val().name]),
|
|
350
|
-
Button('Settings').nd.on.click(() =>
|
|
351
|
-
appState.currentView.set('settings')
|
|
352
|
-
),
|
|
353
|
-
Button('Logout').nd.on.click(() => {
|
|
354
|
-
appState.user.set(null);
|
|
355
|
-
appState.currentView.set('welcome');
|
|
356
|
-
})
|
|
357
|
-
]),
|
|
358
|
-
// Guest header
|
|
359
|
-
Div({ class: 'auth-buttons' }, [
|
|
360
|
-
Button('Sign In').nd.on.click(() =>
|
|
361
|
-
appState.currentView.set('login')
|
|
362
|
-
),
|
|
363
|
-
Button('Sign Up').nd.on.click(() =>
|
|
364
|
-
appState.currentView.set('register')
|
|
365
|
-
)
|
|
366
|
-
])
|
|
367
|
-
)
|
|
368
|
-
]),
|
|
369
|
-
|
|
370
|
-
// Main content area
|
|
371
|
-
Match(appState.currentView, {
|
|
372
|
-
welcome: WelcomeView(),
|
|
373
|
-
login: LoginView(appState),
|
|
374
|
-
register: RegisterView(appState),
|
|
375
|
-
dashboard: When(isLoggedIn)
|
|
376
|
-
.show(() => DashboardView(appState.user.val()))
|
|
377
|
-
.otherwise(() => {
|
|
378
|
-
appState.currentView.set('welcome');
|
|
379
|
-
return Div('Redirecting...');
|
|
380
|
-
}),
|
|
381
|
-
settings: When(isLoggedIn)
|
|
382
|
-
.show(() => SettingsView(appState))
|
|
383
|
-
.otherwise(() => {
|
|
384
|
-
appState.currentView.set('welcome');
|
|
385
|
-
return Div('Please log in to access settings');
|
|
386
|
-
})
|
|
387
|
-
})
|
|
388
|
-
]);
|
|
142
|
+
Switch(user.is(u => u.isLoggedIn),
|
|
143
|
+
() => Div(['Welcome back, ', user.select(u => u.name)]),
|
|
144
|
+
() => Div('Please sign in')
|
|
145
|
+
)
|
|
389
146
|
```
|
|
390
147
|
|
|
391
|
-
|
|
148
|
+
> `Switch` is built on top of `Match` using `.toBoolean()`.
|
|
392
149
|
|
|
393
|
-
|
|
150
|
+
---
|
|
394
151
|
|
|
395
|
-
|
|
152
|
+
## `Match` - Multiple States
|
|
396
153
|
|
|
397
|
-
|
|
398
|
-
const isVisible = Observable(true);
|
|
154
|
+
Handles multiple states like a switch-case. Each key maps to a content value or function:
|
|
399
155
|
|
|
400
|
-
|
|
401
|
-
const
|
|
402
|
-
console.log('Creating expensive content'); // Only called when becoming visible
|
|
403
|
-
return createComplexComponent();
|
|
404
|
-
});
|
|
156
|
+
```javascript
|
|
157
|
+
const status = Observable('idle');
|
|
405
158
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
159
|
+
Match(status, {
|
|
160
|
+
idle: Div('Ready'),
|
|
161
|
+
loading: Div('Loading...'),
|
|
162
|
+
success: Div('Done!'),
|
|
163
|
+
error: Div('Something went wrong'),
|
|
164
|
+
default: Div('Unknown state')
|
|
165
|
+
})
|
|
410
166
|
```
|
|
411
167
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
Functions in conditional rendering are called only when needed, preventing memory waste:
|
|
168
|
+
With function values for access to current observable state:
|
|
415
169
|
|
|
416
170
|
```javascript
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
});
|
|
171
|
+
const phase = Observable('menu');
|
|
172
|
+
|
|
173
|
+
Match(phase, {
|
|
174
|
+
menu: () => Div([
|
|
175
|
+
H1('Welcome'),
|
|
176
|
+
Button('Start').nd.onClick(() => phase.set('playing'))
|
|
177
|
+
]),
|
|
178
|
+
playing: () => Div([
|
|
179
|
+
Div(['Score: ', score]),
|
|
180
|
+
Button('Pause').nd.onClick(() => phase.set('paused'))
|
|
181
|
+
]),
|
|
182
|
+
paused: () => Div([
|
|
183
|
+
H2('Paused'),
|
|
184
|
+
Button('Resume').nd.onClick(() => phase.set('playing'))
|
|
185
|
+
])
|
|
186
|
+
})
|
|
434
187
|
```
|
|
435
188
|
|
|
436
|
-
###
|
|
189
|
+
### Dynamic add / remove
|
|
437
190
|
|
|
438
|
-
|
|
191
|
+
`Match` exposes `.add()` and `.remove()` methods to update the available states at runtime:
|
|
439
192
|
|
|
440
193
|
```javascript
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
const filteredItems = Observable.computed(() => {
|
|
446
|
-
return items.val().filter(item =>
|
|
447
|
-
item.name.toLowerCase().includes(searchTerm.val().toLowerCase())
|
|
448
|
-
);
|
|
449
|
-
}, [items, searchTerm]);
|
|
194
|
+
const view = Match(status, {
|
|
195
|
+
idle: Div('Ready'),
|
|
196
|
+
loading: Div('Loading...')
|
|
197
|
+
});
|
|
450
198
|
|
|
451
|
-
|
|
199
|
+
// Add a new state
|
|
200
|
+
view.nd.add('success', Div('Done!'));
|
|
201
|
+
view.nd.add('success', Div('Done!'), true); // third arg: immediately switch to this state
|
|
452
202
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
ForEach(filteredItems, item => ItemComponent(item))
|
|
456
|
-
),
|
|
457
|
-
HideIf(hasResults, 'No results found')
|
|
458
|
-
]);
|
|
203
|
+
// Remove a state
|
|
204
|
+
view.nd.remove('idle');
|
|
459
205
|
```
|
|
460
206
|
|
|
461
|
-
|
|
207
|
+
### `shouldKeepInCache`
|
|
462
208
|
|
|
463
|
-
|
|
209
|
+
By default, `Match` caches each rendered state. Pass `false` to recreate content on every switch:
|
|
464
210
|
|
|
465
211
|
```javascript
|
|
466
|
-
|
|
467
|
-
ShowIf(isVisible, content)
|
|
468
|
-
|
|
469
|
-
// Good: Use Switch for binary choices
|
|
470
|
-
Switch(isLoggedIn, welcomeMessage, loginPrompt)
|
|
471
|
-
|
|
472
|
-
// Good: Use Match for multiple states
|
|
473
|
-
Match(status, { loading: '...', success: '...', error: '...' })
|
|
474
|
-
|
|
475
|
-
// Less ideal: Using Match for simple boolean
|
|
476
|
-
Match(isVisible, { true: content, false: null })
|
|
212
|
+
Match(status, { loading: Div('...'), success: Div('Done') }, false)
|
|
477
213
|
```
|
|
478
214
|
|
|
479
|
-
|
|
215
|
+
---
|
|
480
216
|
|
|
481
|
-
|
|
482
|
-
// Good: Function creates fresh content with current values
|
|
483
|
-
ShowIf(user.check(u => u.isAdmin),
|
|
484
|
-
() => Div(`Admin: ${user.val().name}`)
|
|
485
|
-
)
|
|
486
|
-
|
|
487
|
-
// Problematic: Static content won't update
|
|
488
|
-
ShowIf(user.check(u => u.isAdmin),
|
|
489
|
-
Div(`Admin: ${user.val().name}`) // Name won't update if user changes
|
|
490
|
-
)
|
|
491
|
-
```
|
|
217
|
+
## `When` - Fluent Builder
|
|
492
218
|
|
|
493
|
-
|
|
219
|
+
A chainable interface for conditional rendering:
|
|
494
220
|
|
|
495
221
|
```javascript
|
|
496
|
-
|
|
497
|
-
const canEdit = Observable.computed(() => {
|
|
498
|
-
const u = user.val();
|
|
499
|
-
const p = post.val();
|
|
500
|
-
return u.isLoggedIn && (u.role === 'admin' || u.id === p.authorId);
|
|
501
|
-
}, [user, post]);
|
|
502
|
-
|
|
503
|
-
ShowIf(canEdit, editButton)
|
|
222
|
+
const score = Observable(85);
|
|
504
223
|
|
|
505
|
-
|
|
506
|
-
|
|
224
|
+
When(score.isGreaterThanOrEqualTo(90))
|
|
225
|
+
.show(() => Div('Excellent!'))
|
|
226
|
+
.otherwise(() => Div('Keep going'))
|
|
507
227
|
```
|
|
508
228
|
|
|
509
|
-
|
|
229
|
+
Convert to a DOM element explicitly with `.toNdElement()`:
|
|
510
230
|
|
|
511
231
|
```javascript
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
() =>
|
|
515
|
-
)
|
|
232
|
+
const greeting = When(isLoggedIn)
|
|
233
|
+
.show(() => Div('Welcome back!'))
|
|
234
|
+
.otherwise(() => Div('Please sign in'));
|
|
516
235
|
|
|
517
|
-
//
|
|
518
|
-
|
|
236
|
+
// .otherwise() already returns the element
|
|
237
|
+
// .toNdElement() is available if you build the chain without calling .otherwise()
|
|
238
|
+
const el = greeting.toNdElement();
|
|
519
239
|
```
|
|
520
240
|
|
|
521
|
-
|
|
241
|
+
---
|
|
522
242
|
|
|
523
|
-
|
|
524
|
-
// Good: Clear intent
|
|
525
|
-
const isUserAuthenticated = user.check(u => u.token !== null);
|
|
526
|
-
const hasUnreadMessages = messages.check(m => m.some(msg => !msg.read));
|
|
243
|
+
## Choosing the Right Tool
|
|
527
244
|
|
|
528
|
-
|
|
245
|
+
| Situation | Use |
|
|
246
|
+
|---|---|
|
|
247
|
+
| Simple show / hide | `ShowIf` |
|
|
248
|
+
| Inverse show / hide | `HideIf` / `HideIfNot` |
|
|
249
|
+
| Show when value matches | `ShowWhen` |
|
|
250
|
+
| Two options (true / false) | `Switch` |
|
|
251
|
+
| Multiple named states | `Match` |
|
|
252
|
+
| Fluent chaining style | `When` |
|
|
529
253
|
|
|
530
|
-
|
|
531
|
-
const check1 = user.check(u => u.token !== null);
|
|
532
|
-
const check2 = messages.check(m => m.some(msg => !msg.read));
|
|
533
|
-
```
|
|
254
|
+
---
|
|
534
255
|
|
|
535
|
-
##
|
|
256
|
+
## Best Practices
|
|
536
257
|
|
|
537
|
-
|
|
258
|
+
**Use functions for dynamic content** - static values are evaluated once at creation time:
|
|
538
259
|
|
|
539
260
|
```javascript
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
data: null,
|
|
543
|
-
error: null
|
|
544
|
-
});
|
|
261
|
+
// Good - content reflects current value when shown
|
|
262
|
+
ShowIf(isAdmin, () => Div(user.select(u => u.name)))
|
|
545
263
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
loading: Div({ class: 'loading' }, 'Loading...'),
|
|
549
|
-
success: () => DataDisplay(requestState.data.val()),
|
|
550
|
-
error: () => Div({ class: 'error' }, [
|
|
551
|
-
'Error: ', requestState.error,
|
|
552
|
-
Button('Retry').nd.on.click(loadData)
|
|
553
|
-
])
|
|
554
|
-
});
|
|
264
|
+
// Risky - name captured at creation, won't update
|
|
265
|
+
ShowIf(isAdmin, Div(user.val().name))
|
|
555
266
|
```
|
|
556
267
|
|
|
557
|
-
|
|
268
|
+
**Use `Observable.computed()` for complex conditions:**
|
|
558
269
|
|
|
559
270
|
```javascript
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
});
|
|
271
|
+
const canEdit = Observable.computed((u, p) =>
|
|
272
|
+
u.isLoggedIn && (u.role === 'admin' || u.id === p.authorId),
|
|
273
|
+
[user, post]
|
|
274
|
+
);
|
|
565
275
|
|
|
566
|
-
|
|
567
|
-
// Theme switching
|
|
568
|
-
Switch(features.darkMode,
|
|
569
|
-
Div({ class: 'app dark-theme' }, content),
|
|
570
|
-
Div({ class: 'app light-theme' }, content)
|
|
571
|
-
),
|
|
572
|
-
|
|
573
|
-
// Beta features for power users
|
|
574
|
-
ShowIf(features.betaFeatures, BetaPanel()),
|
|
575
|
-
|
|
576
|
-
// A/B testing new dashboard
|
|
577
|
-
Switch(features.newDashboard,
|
|
578
|
-
NewDashboard(),
|
|
579
|
-
LegacyDashboard()
|
|
580
|
-
)
|
|
581
|
-
]);
|
|
276
|
+
ShowIf(canEdit, editButton)
|
|
582
277
|
```
|
|
583
278
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
### Using Console Logs in Conditions
|
|
279
|
+
**Use shorthand checkers instead of manual conditions:**
|
|
587
280
|
|
|
588
281
|
```javascript
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
});
|
|
282
|
+
// Good
|
|
283
|
+
ShowIf(list.isEmpty(), Div('No items'))
|
|
284
|
+
ShowIf(name.isTruthy(), Div(['Hello, ', name]))
|
|
593
285
|
|
|
594
|
-
|
|
286
|
+
// Avoid
|
|
287
|
+
ShowIf(list.check(l => l.length === 0), Div('No items'))
|
|
595
288
|
```
|
|
596
289
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
```javascript
|
|
600
|
-
const status = Observable('idle');
|
|
601
|
-
|
|
602
|
-
// Log all status changes
|
|
603
|
-
status.subscribe(newStatus => {
|
|
604
|
-
console.log('Status changed to:', newStatus);
|
|
605
|
-
});
|
|
606
|
-
|
|
607
|
-
// Debug what content is being rendered
|
|
608
|
-
const StatusContent = Match(status, {
|
|
609
|
-
idle: () => {
|
|
610
|
-
console.log('Rendering idle state');
|
|
611
|
-
return IdleComponent();
|
|
612
|
-
},
|
|
613
|
-
loading: () => {
|
|
614
|
-
console.log('Rendering loading state');
|
|
615
|
-
return LoadingComponent();
|
|
616
|
-
}
|
|
617
|
-
});
|
|
618
|
-
```
|
|
290
|
+
---
|
|
619
291
|
|
|
620
292
|
## Next Steps
|
|
621
293
|
|
|
622
|
-
|
|
294
|
+
- **[List Rendering](./list-rendering.md)** - ForEach and dynamic lists
|
|
295
|
+
- **[Observables](./observables.md)** - Reactive state management
|
|
296
|
+
- **[Elements](./elements.md)** - Creating and composing UI
|
|
297
|
+
- **[State Management](./state-management.md)** - Global state patterns
|
|
298
|
+
- **[Anchor](./anchor.md)** - How conditional rendering works under the hood
|
|
299
|
+
|
|
300
|
+
## Utilities
|
|
623
301
|
|
|
624
|
-
- **[
|
|
625
|
-
- **[
|
|
626
|
-
- **[
|
|
627
|
-
- **[Memory Management](docs/memory-management.md)** - Memory management
|
|
628
|
-
- **[Anchor](docs/anchor.md)** - Anchor
|
|
302
|
+
- **[Cache](./cache.md)** - Lazy initialization and singleton patterns
|
|
303
|
+
- **[NativeFetch](./native-fetch.md)** - HTTP client with interceptors
|
|
304
|
+
- **[Filters](./filters.md)** - Data filtering helpers
|