native-document 1.0.165 → 1.0.168
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/.vitepress/config.js +166 -0
- package/CHANGELOG.md +153 -0
- package/components.d.ts +2 -0
- package/components.js +2 -1
- package/devtools/widget.js +1 -1
- package/dist/native-document.components.min.js +11589 -2983
- package/dist/native-document.dev.js +2280 -396
- package/dist/native-document.dev.js.map +1 -1
- package/dist/native-document.min.js +1 -1
- package/docs/advanced-components.md +213 -608
- package/docs/anchor.md +173 -312
- package/docs/cache.md +95 -803
- 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 +170 -588
- package/docs/contributing.md +300 -25
- package/docs/core-concepts.md +205 -374
- package/docs/elements.md +251 -367
- package/docs/extending-native-document-element.md +192 -207
- package/docs/filters.md +153 -1122
- package/docs/getting-started.md +193 -267
- package/docs/i18n.md +241 -0
- package/docs/index.md +76 -0
- package/docs/lifecycle-events.md +143 -75
- package/docs/list-rendering.md +227 -852
- package/docs/memory-management.md +134 -47
- package/docs/native-document-element.md +337 -186
- package/docs/native-fetch.md +99 -630
- package/docs/observable-resource.md +364 -0
- package/docs/observables.md +592 -526
- package/docs/routing.md +244 -653
- package/docs/state-management.md +134 -241
- package/docs/svg-elements.md +231 -0
- package/docs/theming.md +409 -0
- package/docs/validation.md +95 -97
- package/docs/vitepress-conventions.md +219 -0
- package/eslint.config.js +28 -33
- package/i18n.js +1 -1
- package/i18n.ts +2 -0
- package/index.js +3 -0
- package/package.json +36 -14
- package/readme.md +269 -89
- package/src/components/$traits/has-draggable/HasDraggable.d.ts +4 -0
- package/src/components/$traits/has-draggable/HasDraggable.js +13 -0
- package/src/components/$traits/has-items/HasItems.d.ts +9 -0
- package/src/components/$traits/has-items/HasItems.js +6 -6
- package/src/components/$traits/has-position/HasFullPosition.d.ts +14 -0
- package/src/components/$traits/has-position/HasFullPosition.js +44 -0
- package/src/components/$traits/has-position/HasPosition.d.ts +7 -0
- package/src/components/$traits/has-position/HasPosition.js +23 -1
- package/src/components/$traits/has-resizable/HasResizable.d.ts +13 -0
- package/src/components/$traits/has-resizable/HasResizable.js +9 -0
- package/src/components/$traits/has-validation/HasValidation.d.ts +17 -0
- package/src/components/$traits/has-validation/HasValidation.js +54 -7
- package/src/components/BaseComponent.d.ts +32 -0
- package/src/components/BaseComponent.js +65 -9
- package/src/components/accordion/Accordion.js +39 -14
- package/src/components/accordion/AccordionItem.js +45 -14
- package/src/components/accordion/index.js +2 -2
- 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 +70 -38
- package/src/components/alert/index.js +2 -2
- package/src/components/alert/types/Alert.d.ts +62 -0
- package/src/components/avatar/Avatar.js +49 -12
- package/src/components/avatar/AvatarGroup.js +50 -2
- package/src/components/avatar/index.js +2 -2
- 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 +125 -5
- package/src/components/badge/index.js +2 -2
- package/src/components/badge/types/Badge.d.ts +51 -0
- package/src/components/breadcrumb/BreadCrumb.js +61 -5
- package/src/components/breadcrumb/index.js +2 -2
- package/src/components/breadcrumb/types/BreadCrumb.d.ts +42 -0
- package/src/components/button/Button.js +164 -9
- package/src/components/button/index.js +1 -1
- package/src/components/button/types/Button.d.ts +62 -0
- package/src/components/card/Card.js +204 -32
- package/src/components/card/index.js +4 -4
- package/src/components/card/types/Card.d.ts +42 -0
- package/src/components/context-menu/ContextMenu.js +49 -5
- package/src/components/context-menu/ContextMenuGroup.js +15 -2
- package/src/components/context-menu/ContextMenuItem.js +14 -2
- package/src/components/context-menu/index.js +5 -5
- 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 +120 -4
- package/src/components/divider/index.js +3 -3
- package/src/components/divider/types/Divider.d.ts +55 -0
- package/src/components/dropdown/Dropdown.js +239 -16
- package/src/components/dropdown/DropdownDivider.js +22 -2
- package/src/components/dropdown/DropdownGroup.js +44 -5
- package/src/components/dropdown/DropdownItem.js +76 -3
- package/src/components/dropdown/DropdownTrigger.js +49 -20
- package/src/components/dropdown/helpers.js +1 -1
- package/src/components/dropdown/index.js +6 -6
- 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 +156 -13
- package/src/components/form/field/Field.js +172 -9
- package/src/components/form/field/FieldCollection.js +116 -12
- package/src/components/form/field/types/AutocompleteField.js +92 -2
- package/src/components/form/field/types/CheckboxField.js +43 -2
- package/src/components/form/field/types/CheckboxGroupField.js +83 -6
- package/src/components/form/field/types/ColorField.js +56 -3
- package/src/components/form/field/types/DateField.js +155 -4
- package/src/components/form/field/types/EmailField.js +54 -4
- package/src/components/form/field/types/FileField.js +140 -6
- package/src/components/form/field/types/HiddenField.js +27 -1
- package/src/components/form/field/types/ImageField.js +82 -3
- package/src/components/form/field/types/NumberField.js +97 -4
- package/src/components/form/field/types/PasswordField.js +103 -7
- package/src/components/form/field/types/RadioField.js +75 -4
- package/src/components/form/field/types/RangeField.js +67 -1
- package/src/components/form/field/types/SearchField.js +41 -2
- package/src/components/form/field/types/SelectField.js +133 -4
- package/src/components/form/field/types/StringField.js +91 -2
- package/src/components/form/field/types/TelField.js +55 -4
- package/src/components/form/field/types/TextAreaField.js +76 -2
- package/src/components/form/field/types/TimeField.js +120 -5
- package/src/components/form/field/types/UrlField.js +59 -4
- package/src/components/form/field/types/file-field-mode/FileAvatarMode.js +83 -4
- package/src/components/form/field/types/file-field-mode/FileDropzoneMode.js +61 -3
- package/src/components/form/field/types/file-field-mode/FileItemPreview.js +79 -3
- package/src/components/form/field/types/file-field-mode/FileNativeMode.js +24 -2
- package/src/components/form/field/types/file-field-mode/FileUploadButtonMode.js +64 -3
- package/src/components/form/field/types/file-field-mode/FileWallMode.js +56 -3
- package/src/components/form/index.js +28 -28
- 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/validation/Validation.js +54 -54
- package/src/components/index.d.ts +160 -0
- package/src/components/list/HasListItem.js +171 -0
- package/src/components/list/List.js +85 -67
- package/src/components/list/ListDivider.js +39 -0
- package/src/components/list/ListGroup.js +105 -38
- package/src/components/list/ListItem.js +158 -49
- package/src/components/list/index.js +8 -6
- 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 +55 -6
- package/src/components/menu/Menu.js +113 -22
- package/src/components/menu/MenuDivider.js +18 -2
- package/src/components/menu/MenuGroup.js +61 -6
- package/src/components/menu/MenuItem.js +95 -11
- package/src/components/menu/MenuLink.js +27 -2
- package/src/components/menu/index.js +6 -6
- 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 +258 -17
- package/src/components/modal/index.js +3 -3
- package/src/components/modal/types/Modal.d.ts +94 -0
- package/src/components/pagination/Pagination.js +155 -7
- package/src/components/pagination/index.js +3 -3
- package/src/components/pagination/types/Pagination.d.ts +68 -0
- package/src/components/popover/Popover.js +198 -11
- package/src/components/popover/PopoverFooter.js +33 -9
- package/src/components/popover/PopoverHeader.js +33 -8
- package/src/components/popover/index.js +4 -4
- 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 +182 -13
- package/src/components/progress/index.js +3 -3
- package/src/components/progress/types/Progress.d.ts +77 -0
- package/src/components/skeleton/Skeleton.js +117 -49
- package/src/components/skeleton/index.js +3 -3
- package/src/components/skeleton/types/Skeleton.d.ts +55 -0
- package/src/components/slider/Slider.js +207 -10
- package/src/components/slider/index.js +2 -2
- package/src/components/slider/types/Slider.d.ts +82 -0
- package/src/components/spacer/Spacer.js +12 -3
- package/src/components/spacer/index.js +2 -2
- package/src/components/spacer/types/Spacer.d.ts +19 -0
- package/src/components/spinner/Spinner.js +180 -9
- package/src/components/spinner/index.js +3 -3
- package/src/components/spinner/types/Spinner.d.ts +71 -0
- package/src/components/splitter/Splitter.js +76 -13
- package/src/components/splitter/SplitterGutter.js +67 -5
- package/src/components/splitter/SplitterPanel.js +69 -2
- package/src/components/splitter/index.js +5 -5
- 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 +23 -3
- package/src/components/stacks/FixedStack.js +23 -3
- package/src/components/stacks/HStack.js +24 -3
- package/src/components/stacks/PositionStack.js +111 -3
- package/src/components/stacks/RelativeStack.js +23 -3
- package/src/components/stacks/Stack.js +73 -2
- package/src/components/stacks/VStack.js +24 -4
- package/src/components/stacks/index.js +7 -7
- 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 +152 -12
- package/src/components/stepper/StepperStep.js +104 -3
- package/src/components/stepper/index.js +4 -4
- 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 +143 -6
- package/src/components/switch/index.js +1 -1
- package/src/components/switch/types/Switch.d.ts +55 -0
- package/src/components/table/Column.js +105 -6
- package/src/components/table/ColumnGroup.js +48 -3
- package/src/components/table/DataTable.js +256 -19
- package/src/components/table/SimpleTable.js +58 -4
- package/src/components/table/index.js +2 -2
- 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 +192 -5
- package/src/components/tabs/index.js +3 -3
- package/src/components/tabs/types/Tabs.d.ts +78 -0
- package/src/components/toast/Toast.js +133 -5
- package/src/components/toast/index.js +3 -3
- 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 +157 -13
- package/src/components/tooltip/index.js +2 -2
- package/src/components/tooltip/prototypes.js +1 -1
- package/src/components/tooltip/types/Tooltip.d.ts +65 -0
- package/src/core/data/MemoryManager.js +2 -2
- package/src/core/data/Observable.js +15 -18
- package/src/core/data/ObservableArray.js +118 -46
- package/src/core/data/ObservableChecker.js +2 -2
- package/src/core/data/ObservableItem.js +135 -21
- package/src/core/data/ObservableObject.js +126 -35
- package/src/core/data/ObservableResource.js +118 -3
- package/src/core/data/Store.js +142 -26
- package/src/core/data/observable-helpers/observable.is-to.js +196 -1
- package/src/core/data/observable-helpers/observable.prototypes.js +35 -8
- package/src/core/elements/anchor/anchor-with-sentinel.js +23 -2
- package/src/core/elements/anchor/anchor.js +16 -7
- package/src/core/elements/anchor/one-child-anchor-overwriting.js +2 -2
- package/src/core/elements/content-formatter.js +1 -1
- package/src/core/elements/control/for-each-array.js +9 -9
- package/src/core/elements/control/for-each.js +14 -14
- package/src/core/elements/control/show-if.js +11 -11
- package/src/core/elements/control/show-when.js +5 -5
- package/src/core/elements/control/switch.js +14 -14
- package/src/core/elements/description-list.js +1 -1
- package/src/core/elements/form.js +2 -2
- package/src/core/elements/fragment.js +1 -1
- package/src/core/elements/html5-semantics.js +1 -1
- package/src/core/elements/img.js +3 -3
- package/src/core/elements/interactive.js +1 -1
- package/src/core/elements/list.js +1 -1
- package/src/core/elements/medias.js +1 -1
- package/src/core/elements/meta-data.js +1 -1
- package/src/core/elements/svg.js +1 -1
- package/src/core/elements/table.js +1 -1
- package/src/core/errors/ArgTypesError.js +1 -1
- package/src/core/utils/HasEventEmitter.js +36 -2
- package/src/core/utils/args-types.js +9 -9
- package/src/core/utils/cache.js +1 -1
- package/src/core/utils/callback-handler.js +29 -0
- package/src/core/utils/debug-manager.js +6 -6
- package/src/core/utils/events.js +139 -139
- package/src/core/utils/filters/date.js +84 -3
- package/src/core/utils/filters/standard.js +136 -11
- package/src/core/utils/filters/strings.js +34 -2
- package/src/core/utils/filters/utils.js +40 -4
- package/src/core/utils/formatters.js +4 -4
- package/src/core/utils/helpers.js +39 -7
- package/src/core/utils/localstorage.js +11 -11
- package/src/core/utils/memoize.js +56 -3
- package/src/core/utils/plugins-manager.js +3 -3
- package/src/core/utils/property-accumulator.js +6 -6
- package/src/core/utils/prototypes.js +26 -1
- package/src/core/utils/shortcut-manager.js +2 -2
- package/src/core/utils/validator.js +8 -8
- package/src/core/wrappers/AttributesWrapper.js +32 -22
- package/src/core/wrappers/DocumentObserver.js +3 -3
- package/src/core/wrappers/ElementCreator.js +5 -5
- package/src/core/wrappers/HtmlElementWrapper.js +38 -12
- package/src/core/wrappers/NDElement.js +328 -22
- package/src/core/wrappers/NdPrototype.js +60 -16
- package/src/core/wrappers/SingletonView.js +50 -2
- package/src/core/wrappers/SvgElementWrapper.js +1 -1
- package/src/core/wrappers/constants.js +35 -2
- package/src/core/wrappers/prototypes/attributes-extensions.js +7 -7
- package/src/core/wrappers/prototypes/nd-element-extensions.js +72 -6
- package/src/core/wrappers/prototypes/nd-element.transition.extensions.js +42 -2
- package/src/core/wrappers/template-cloner/NodeCloner.js +53 -8
- package/src/core/wrappers/template-cloner/TemplateCloner.js +75 -6
- package/src/core/wrappers/template-cloner/attributes-hydrator.js +58 -2
- package/src/core/wrappers/template-cloner/utils.js +42 -6
- package/src/fetch/NativeFetch.js +3 -3
- package/src/i18n/bin/scan.js +6 -6
- package/src/i18n/index.d.ts +2 -0
- package/src/i18n/service/I18nService.d.ts +27 -0
- package/src/i18n/service/I18nService.js +5 -5
- package/src/i18n/service/functions.d.ts +22 -0
- package/src/i18n/service/functions.js +2 -2
- package/src/router/Route.js +3 -3
- package/src/router/RouteGroupHelper.js +2 -2
- package/src/router/Router.js +15 -15
- package/src/router/RouterComponent.js +33 -7
- package/src/router/link.js +4 -4
- package/src/router/modes/HashRouter.js +2 -2
- package/src/router/modes/HistoryRouter.js +2 -2
- package/src/router/modes/MemoryRouter.js +1 -1
- package/src/ui/components/accordion/AccordionItemRender.js +3 -3
- package/src/ui/components/accordion/AccordionRender.js +1 -1
- package/src/ui/components/alert/AlertRender.js +10 -10
- package/src/ui/components/avatar/avata-group/AvatarGroupRender.js +1 -1
- package/src/ui/components/avatar/avatar/AvatarRender.js +1 -1
- package/src/ui/components/breadcrumb/BreadcrumbRender.js +2 -2
- package/src/ui/components/button/ButtonRender.js +1 -1
- 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 +6 -6
- package/src/ui/components/dropdown/DropdownRender.js +8 -8
- package/src/ui/components/dropdown/group/DropdownGroupRender.js +2 -2
- package/src/ui/components/dropdown/item/DropdownItemRender.js +1 -1
- package/src/ui/components/form/FieldCollectionRender.js +2 -2
- package/src/ui/components/form/FormControlRender.js +5 -5
- package/src/ui/components/form/fields/AutocompleteFieldRender.js +3 -3
- package/src/ui/components/form/fields/CheckboxFieldRender.js +1 -1
- package/src/ui/components/form/fields/CheckboxGroupFieldRender.js +1 -1
- package/src/ui/components/form/fields/DateFieldRender.js +7 -7
- package/src/ui/components/form/fields/EmailFieldRender.js +1 -1
- package/src/ui/components/form/fields/FieldRender.js +4 -4
- package/src/ui/components/form/fields/FileFieldRender.js +1 -1
- package/src/ui/components/form/fields/PasswordFieldRender.js +2 -2
- package/src/ui/components/form/fields/RadioFieldRender.js +1 -1
- package/src/ui/components/form/fields/RangeFieldRender.js +1 -1
- package/src/ui/components/form/fields/SelectFieldRender.js +2 -2
- package/src/ui/components/form/fields/SliderFieldRender.js +6 -6
- package/src/ui/components/form/fields/StringFieldRender.js +1 -1
- package/src/ui/components/form/fields/TelFieldRender.js +1 -1
- package/src/ui/components/form/fields/TextAreaFieldRender.js +1 -1
- package/src/ui/components/form/fields/TimeFieldRender.js +3 -3
- package/src/ui/components/form/fields/UrlFieldRender.js +1 -1
- package/src/ui/components/form/file-upload-mode/FileAvatarModeRender.js +1 -1
- package/src/ui/components/form/file-upload-mode/FileDropzoneModeRender.js +2 -2
- package/src/ui/components/form/file-upload-mode/FileUploadButtonModeRender.js +2 -2
- package/src/ui/components/form/file-upload-mode/FileWallModeRender.js +1 -1
- package/src/ui/components/form/helpers.js +8 -8
- package/src/ui/components/form/index.js +27 -27
- 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 +1 -1
- package/src/ui/components/menu/MenuGroupRender.js +3 -3
- package/src/ui/components/menu/MenuItemRender.js +2 -2
- package/src/ui/components/menu/MenuLinkRender.js +3 -3
- package/src/ui/components/menu/helpers.js +4 -4
- package/src/ui/components/modal/ModalRender.js +4 -4
- package/src/ui/components/pagination/PaginationRender.js +9 -9
- package/src/ui/components/popover/PopoverRender.js +7 -7
- package/src/ui/components/progress/ProgressRender.js +12 -12
- package/src/ui/components/skeleton/SkeletonRender.js +56 -0
- package/src/ui/components/spacer/SpacerRender.js +10 -0
- package/src/ui/components/splitter/SplitterGutterRender.js +1 -1
- package/src/ui/components/splitter/SplitterPanelRender.js +2 -2
- package/src/ui/components/stacks/PositionStackRender.js +1 -1
- package/src/ui/components/stacks/StackRender.js +1 -1
- package/src/ui/components/stacks/absolute-stack/AbsoluteStackRender.js +1 -1
- package/src/ui/components/stacks/fixed-stack/FixedStackRender.js +1 -1
- package/src/ui/components/stacks/h-stack/HStackRender.js +1 -1
- package/src/ui/components/stacks/index.js +5 -5
- package/src/ui/components/stacks/relative-stack/RelativeStackRender.js +1 -1
- package/src/ui/components/stacks/v-stack/VStackRender.js +1 -1
- package/src/ui/components/stepper/StepperRender.js +2 -2
- package/src/ui/components/stepper/StepperStepRender.js +4 -4
- package/src/ui/components/switch/SwitchRender.js +4 -4
- package/src/ui/components/table/data-table/DataTableRender.js +5 -5
- package/src/ui/components/table/data-table/bulk-actions.js +7 -7
- package/src/ui/components/table/data-table/pagination.js +6 -6
- package/src/ui/components/table/data-table/tables.js +25 -25
- package/src/ui/components/table/data-table/toolbar.js +3 -3
- package/src/ui/components/table/simple-table/SimpleTableRender.js +8 -8
- package/src/ui/components/tabs/TabsRender.js +11 -11
- package/src/ui/components/toast/ToastRender.js +3 -3
- package/src/ui/components/tooltip/TooltipRender.js +1 -1
- package/src/ui/index.js +44 -36
- package/types/elements.d.ts +163 -1037
- package/types/forms.d.ts +16 -20
- package/types/globals.d.ts +543 -0
- package/types/images.d.ts +2 -2
- package/types/observable-resource.d.ts +3 -0
- package/types/property-accumulator.d.ts +4 -4
- package/types/store.d.ts +26 -2
- package/types/validator.ts +3 -3
- package/ui.js +1 -0
- package/src/components/form/field/DefaultRender.js +0 -77
- package/src/components/form/field/FieldFactory.js +0 -107
- package/src/components/skeleton/SkeletonList.js +0 -0
- package/src/components/skeleton/SkeletonParagraph.js +0 -0
- package/src/components/skeleton/SkeletonTable.js +0 -0
- /package/{src/components/skeleton/SkeletonCard.js → docs/tutorials/.gitkeep} +0 -0
package/docs/elements.md
CHANGED
|
@@ -1,512 +1,396 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Elements
|
|
3
|
+
description: Create reactive HTML elements with a declarative syntax - every HTML element has a corresponding function in NativeDocument
|
|
4
|
+
---
|
|
5
|
+
|
|
1
6
|
# Elements
|
|
2
7
|
|
|
3
|
-
NativeDocument provides a simple and intuitive way to create HTML elements with a declarative syntax. Every HTML element has a corresponding function that creates reactive DOM
|
|
8
|
+
NativeDocument provides a simple and intuitive way to create HTML elements with a declarative syntax. Every HTML element has a corresponding function that creates a reactive DOM element.
|
|
4
9
|
|
|
5
10
|
## Basic Element Creation
|
|
6
11
|
|
|
7
12
|
```javascript
|
|
8
|
-
//
|
|
9
|
-
const title
|
|
10
|
-
const description = P({ class:
|
|
13
|
+
// With attributes
|
|
14
|
+
const title = H1({ class: 'main-title' }, 'Welcome to my app');
|
|
15
|
+
const description = P({ class: 'description' }, 'This is a paragraph');
|
|
11
16
|
|
|
12
|
-
//
|
|
13
|
-
const simpleTitle = H1(
|
|
14
|
-
const simplePara
|
|
15
|
-
const container
|
|
17
|
+
// Without attributes
|
|
18
|
+
const simpleTitle = H1('Welcome to my app');
|
|
19
|
+
const simplePara = P('This is a paragraph');
|
|
20
|
+
const container = Div('Content here');
|
|
16
21
|
|
|
17
|
-
//
|
|
22
|
+
// Self-closing elements
|
|
18
23
|
const separator = Hr();
|
|
19
|
-
const lineBreak
|
|
24
|
+
const lineBreak = Br();
|
|
20
25
|
```
|
|
21
26
|
|
|
22
27
|
## Element Structure
|
|
23
28
|
|
|
24
29
|
All element functions follow the same pattern:
|
|
30
|
+
|
|
25
31
|
```javascript
|
|
26
32
|
ElementName(attributes, children)
|
|
27
33
|
// or
|
|
28
34
|
ElementName(children) // attributes are optional
|
|
29
35
|
```
|
|
30
36
|
|
|
31
|
-
- **attributes
|
|
32
|
-
- **children
|
|
37
|
+
- **attributes** - object with HTML attributes (optional, can be `null` or omitted)
|
|
38
|
+
- **children** - text, number, observable, other elements, closures (no-param functions), or an array of any of these. Closures are accepted as-is - no need to call them if they take no parameters.
|
|
33
39
|
|
|
34
40
|
## Working with Attributes
|
|
35
41
|
|
|
36
42
|
```javascript
|
|
37
43
|
// Static attributes
|
|
38
|
-
const link = Link({
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
},
|
|
44
|
+
const link = Link({
|
|
45
|
+
href: '/about',
|
|
46
|
+
class: 'nav-link',
|
|
47
|
+
id: 'about-link'
|
|
48
|
+
}, 'About Us');
|
|
43
49
|
|
|
44
50
|
// Boolean attributes
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
const checkbox = Input({
|
|
52
|
+
type: 'checkbox',
|
|
53
|
+
checked: true,
|
|
54
|
+
disabled: false
|
|
49
55
|
});
|
|
50
56
|
|
|
51
57
|
// Data attributes
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
},
|
|
58
|
+
const card = Div({
|
|
59
|
+
'data-id': '123',
|
|
60
|
+
'data-category': 'important'
|
|
61
|
+
}, 'Content');
|
|
56
62
|
```
|
|
57
63
|
|
|
58
|
-
## Reactive Attributes
|
|
64
|
+
## Reactive Attributes
|
|
65
|
+
|
|
66
|
+
Pass an observable directly as an attribute value - it updates automatically when the observable changes:
|
|
59
67
|
|
|
60
68
|
```javascript
|
|
61
69
|
const isVisible = Observable(true);
|
|
62
|
-
const userName
|
|
63
|
-
const theme
|
|
70
|
+
const userName = Observable('Guest');
|
|
71
|
+
const theme = Observable('dark');
|
|
64
72
|
|
|
65
|
-
// Reactive attributes
|
|
66
73
|
const greeting = Div({
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}, ['Hello ', userName, '!']);
|
|
74
|
+
class: theme,
|
|
75
|
+
hidden: isVisible.isFalsy()
|
|
76
|
+
}, ['Hello ', userName, '!']);
|
|
70
77
|
|
|
71
78
|
// Reactive styles
|
|
72
79
|
const box = Div({
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
},
|
|
80
|
+
style: {
|
|
81
|
+
backgroundColor: theme.is('dark').check(v => v ? '#333' : '#fff'),
|
|
82
|
+
color: theme.is('dark').check(v => v ? '#fff' : '#333')
|
|
83
|
+
}
|
|
84
|
+
}, 'Themed content');
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Conditional Classes
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
const isActive = Observable(false);
|
|
91
|
+
const count = Observable(0);
|
|
92
|
+
|
|
93
|
+
const item = Div({
|
|
94
|
+
class: {
|
|
95
|
+
'item': true, // always present
|
|
96
|
+
'active': isActive, // present when isActive is true
|
|
97
|
+
'highlighted': count.check(c => c > 5) // present when count > 5
|
|
98
|
+
}
|
|
99
|
+
}, 'List item');
|
|
78
100
|
```
|
|
79
101
|
|
|
80
102
|
## Children and Content
|
|
81
103
|
|
|
82
104
|
```javascript
|
|
83
|
-
//
|
|
84
|
-
const simple = P(
|
|
105
|
+
// Single text child
|
|
106
|
+
const simple = P('Simple text');
|
|
85
107
|
|
|
86
|
-
// Single child
|
|
87
|
-
const wrapper = Div({ class:
|
|
88
|
-
P("Wrapped paragraph")
|
|
89
|
-
);
|
|
108
|
+
// Single element child
|
|
109
|
+
const wrapper = Div({ class: 'wrapper' }, P('Wrapped paragraph'));
|
|
90
110
|
|
|
91
111
|
// Multiple children as array
|
|
92
|
-
const list = Div({ class:
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
112
|
+
const list = Div({ class: 'item-list' }, [
|
|
113
|
+
P('First item'),
|
|
114
|
+
P('Second item'),
|
|
115
|
+
P('Third item')
|
|
96
116
|
]);
|
|
97
117
|
|
|
98
118
|
// Mixed content
|
|
99
119
|
const mixed = Div([
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
120
|
+
H2('Title'),
|
|
121
|
+
'Some text between elements',
|
|
122
|
+
P('A paragraph'),
|
|
123
|
+
Button('Click me')
|
|
104
124
|
]);
|
|
105
125
|
```
|
|
106
126
|
|
|
107
|
-
## Event Handling with
|
|
127
|
+
## Event Handling with the `.nd` API
|
|
108
128
|
|
|
109
|
-
The `.nd`
|
|
129
|
+
The `.nd` API provides a fluent interface for events, lifecycle, and DOM utilities:
|
|
110
130
|
|
|
111
131
|
```javascript
|
|
112
|
-
const button = Button(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
blur: () => console.log("Input blurred"),
|
|
134
|
-
input: event => console.log("Input value:", event.target.value)
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
// Prevent default behavior
|
|
132
|
+
const button = Button('Click me')
|
|
133
|
+
.nd.onClick(() => console.log('Clicked!'));
|
|
134
|
+
|
|
135
|
+
// With attributes
|
|
136
|
+
const styledButton = Button({ class: 'btn' }, 'Click me')
|
|
137
|
+
.nd.onClick(() => console.log('Clicked!'));
|
|
138
|
+
|
|
139
|
+
// Multiple events - chained
|
|
140
|
+
const input = Input({ type: 'text', placeholder: 'Type here...' })
|
|
141
|
+
.nd
|
|
142
|
+
.onFocus(() => console.log('Focused'))
|
|
143
|
+
.onBlur(() => console.log('Blurred'))
|
|
144
|
+
.onInput(e => console.log('Value:', e.target.value));
|
|
145
|
+
|
|
146
|
+
// Single event via .on() - name, callback, options (standard addEventListener signature)
|
|
147
|
+
const input2 = Input({ type: 'text' })
|
|
148
|
+
.nd
|
|
149
|
+
.on('input', e => console.log('Value:', e.target.value))
|
|
150
|
+
.on('focus', () => console.log('Focused'), { once: true });
|
|
151
|
+
|
|
152
|
+
// Prevent default
|
|
138
153
|
const form = Form()
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
});
|
|
154
|
+
.nd.onPreventSubmit(e => {
|
|
155
|
+
console.log('Submitted without page reload');
|
|
156
|
+
});
|
|
143
157
|
```
|
|
144
158
|
|
|
145
|
-
##
|
|
159
|
+
## Form Elements and Two-Way Binding
|
|
146
160
|
|
|
147
|
-
|
|
161
|
+
Passing an observable to `value` or `checked` creates automatic two-way binding:
|
|
148
162
|
|
|
149
|
-
Use `.nd.with()` to add custom methods to elements:
|
|
150
163
|
```javascript
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
this.$element.style.backgroundColor = 'yellow';
|
|
155
|
-
return this;
|
|
156
|
-
},
|
|
157
|
-
resetStyle() {
|
|
158
|
-
this.$element.style.backgroundColor = '';
|
|
159
|
-
return this;
|
|
160
|
-
}
|
|
161
|
-
})
|
|
162
|
-
.highlight();
|
|
164
|
+
const name = Observable('');
|
|
165
|
+
const email = Observable('');
|
|
166
|
+
const isChecked = Observable(false);
|
|
163
167
|
|
|
164
|
-
|
|
165
|
-
|
|
168
|
+
const nameInput = Input({ type: 'text', value: name, placeholder: 'Your name' });
|
|
169
|
+
const emailInput = Input({ type: 'email', value: email, placeholder: 'Your email' });
|
|
170
|
+
const checkbox = Input({ type: 'checkbox', checked: isChecked });
|
|
166
171
|
```
|
|
167
172
|
|
|
168
|
-
|
|
173
|
+
## Lifecycle Management
|
|
169
174
|
|
|
170
|
-
Build classes and styles programmatically:
|
|
171
175
|
```javascript
|
|
172
|
-
|
|
176
|
+
const component = Div('Component content')
|
|
177
|
+
.nd.mounted(element => {
|
|
178
|
+
console.log('Mounted to DOM');
|
|
179
|
+
})
|
|
180
|
+
.nd.unmounted(element => {
|
|
181
|
+
console.log('Removed from DOM');
|
|
182
|
+
});
|
|
173
183
|
|
|
174
|
-
//
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
184
|
+
// Combined
|
|
185
|
+
const widget = Div('Widget')
|
|
186
|
+
.nd.lifecycle({
|
|
187
|
+
mounted: element => console.log('Mounted'),
|
|
188
|
+
unmounted: element => console.log('Unmounted')
|
|
189
|
+
});
|
|
190
|
+
```
|
|
178
191
|
|
|
179
|
-
|
|
180
|
-
// Result: class="btn primary large"
|
|
192
|
+
## Manual DOM Manipulation
|
|
181
193
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
console.log(classObj.value()); // { btn: true, primary: true, disabled: false }
|
|
194
|
+
```javascript
|
|
195
|
+
// Remove all children
|
|
196
|
+
const container = Div([P('Child 1'), P('Child 2')]);
|
|
197
|
+
container.nd.unmountChildren();
|
|
187
198
|
|
|
188
|
-
//
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
199
|
+
// Remove element from DOM
|
|
200
|
+
const element = Div('Content');
|
|
201
|
+
element.nd.remove();
|
|
202
|
+
```
|
|
192
203
|
|
|
193
|
-
|
|
194
|
-
// Result: style="color: red; font-size: 16px; margin: 10px"
|
|
204
|
+
## Element References
|
|
195
205
|
|
|
196
|
-
|
|
197
|
-
const styleArr = cssPropertyAccumulator('color: red; font-size: 16px');
|
|
198
|
-
styleArr.add('margin', '10px');
|
|
199
|
-
console.log(styleArr.value()); // "color: red; font-size: 16px; margin: 10px;"
|
|
200
|
-
```
|
|
206
|
+
`.ref()` and `.refSelf()` both store a reference on a target object, but they store different things:
|
|
201
207
|
|
|
202
|
-
|
|
208
|
+
- **`.ref(target, name)`** - stores the **native HTML element** (`this.$element`) → use when you need direct DOM access
|
|
209
|
+
- **`.refSelf(target, name)`** - stores the **`NDElement` instance** (`this`) → use when you need to keep calling `.nd` methods
|
|
203
210
|
|
|
204
211
|
```javascript
|
|
205
|
-
const
|
|
206
|
-
const email = Observable("");
|
|
207
|
-
const isChecked = Observable(false);
|
|
212
|
+
const refs = {};
|
|
208
213
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
value: name, // Automatic two-way binding
|
|
213
|
-
placeholder: "Enter your name"
|
|
214
|
-
});
|
|
214
|
+
const app = Div([
|
|
215
|
+
Input({ type: 'text' })
|
|
216
|
+
.nd.ref(refs, 'nameInput'), // refs.nameInput → HTMLInputElement
|
|
215
217
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
type: "email",
|
|
219
|
-
value: email,
|
|
220
|
-
placeholder: "Enter your email"
|
|
221
|
-
});
|
|
218
|
+
Input({ type: 'text' })
|
|
219
|
+
.nd.refSelf(refs, 'emailInput'), // refs.emailInput → NDElement instance
|
|
222
220
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
})
|
|
221
|
+
Button('Actions')
|
|
222
|
+
.nd.onClick(() => {
|
|
223
|
+
refs.nameInput.focus(); // native DOM method
|
|
224
|
+
refs.emailInput.onInput(e => console.log(e.target.value)); // nd method
|
|
225
|
+
})
|
|
226
|
+
]);
|
|
228
227
|
```
|
|
229
228
|
|
|
230
|
-
##
|
|
229
|
+
## `.nd.with()` - Instance-level Custom Methods
|
|
231
230
|
|
|
232
|
-
|
|
233
|
-
const isActive = Observable(false);
|
|
234
|
-
const count = Observable(0);
|
|
235
|
-
|
|
236
|
-
// Conditional classes
|
|
237
|
-
const item = Div({
|
|
238
|
-
class: {
|
|
239
|
-
"item": true, // Always present
|
|
240
|
-
"active": isActive, // Present when isActive is true
|
|
241
|
-
"highlighted": count.check(c => c > 5) // Present when count > 5
|
|
242
|
-
}
|
|
243
|
-
}, "List item");
|
|
244
|
-
|
|
245
|
-
// Dynamic styles
|
|
246
|
-
const progress = Div({
|
|
247
|
-
style: {
|
|
248
|
-
width: count.check(c => `${c}%`),
|
|
249
|
-
backgroundColor: count.check(c => c > 50 ? "green" : "red")
|
|
250
|
-
}
|
|
251
|
-
}, "Progress bar");
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
## Lifecycle Management
|
|
231
|
+
Add custom methods to a single element instance without affecting other elements:
|
|
255
232
|
|
|
256
233
|
```javascript
|
|
257
|
-
const
|
|
258
|
-
.nd.
|
|
259
|
-
|
|
260
|
-
|
|
234
|
+
const customButton = Button('Click me')
|
|
235
|
+
.nd.with({
|
|
236
|
+
highlight() {
|
|
237
|
+
this.$element.style.backgroundColor = 'yellow';
|
|
238
|
+
return this;
|
|
239
|
+
},
|
|
240
|
+
resetStyle() {
|
|
241
|
+
this.$element.style.backgroundColor = '';
|
|
242
|
+
return this;
|
|
243
|
+
}
|
|
261
244
|
})
|
|
262
|
-
.
|
|
263
|
-
console.log("Component removed from DOM");
|
|
264
|
-
// Cleanup resources
|
|
265
|
-
});
|
|
245
|
+
.highlight();
|
|
266
246
|
|
|
267
|
-
|
|
268
|
-
const widget = Div("Widget")
|
|
269
|
-
.nd.lifecycle({
|
|
270
|
-
mounted: element => console.log("Widget mounted"),
|
|
271
|
-
unmounted: element => console.log("Widget unmounted")
|
|
272
|
-
});
|
|
247
|
+
customButton.resetStyle().highlight();
|
|
273
248
|
```
|
|
274
|
-
## Manual DOM Manipulation
|
|
275
249
|
|
|
276
|
-
|
|
250
|
+
> `.nd.with()` only affects the current instance. To add methods to **all** elements, extend `NDElement.prototype` - see [Extending NDElement](./extending-native-document-element.md).
|
|
277
251
|
|
|
278
|
-
|
|
279
|
-
```javascript
|
|
280
|
-
const container = Div([
|
|
281
|
-
P("Child 1"),
|
|
282
|
-
P("Child 2"),
|
|
283
|
-
P("Child 3")
|
|
284
|
-
]);
|
|
252
|
+
## `.nd.attach()` - Template Binding
|
|
285
253
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
254
|
+
Attaches a template binding hydrator to the element. Used internally by the `useCache` and `useSingleton` rendering systems:
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
// methodName - the event/method name to hydrate
|
|
258
|
+
// bindingHydrator - a binding with a $hydrate method, or a plain function
|
|
259
|
+
element.nd.attach('onClick', bindingHydrator);
|
|
289
260
|
```
|
|
290
261
|
|
|
291
|
-
|
|
262
|
+
See [Advanced Components](./advanced-components.md) for practical usage with `useCache`.
|
|
263
|
+
|
|
264
|
+
## Class and Style Accumulators
|
|
265
|
+
|
|
266
|
+
Build classes and styles programmatically before passing them to an element:
|
|
292
267
|
|
|
293
|
-
Remove an element from the DOM:
|
|
294
268
|
```javascript
|
|
295
|
-
|
|
296
|
-
document.body.appendChild(element.nd.node());
|
|
269
|
+
import { classPropertyAccumulator, cssPropertyAccumulator } from 'native-document';
|
|
297
270
|
|
|
298
|
-
//
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
271
|
+
// Class accumulator
|
|
272
|
+
const classes = classPropertyAccumulator(['btn']);
|
|
273
|
+
classes.add('primary');
|
|
274
|
+
classes.add('large');
|
|
302
275
|
|
|
303
|
-
|
|
276
|
+
const button = Button({ class: classes.value() }, 'Submit');
|
|
277
|
+
// class="btn primary large"
|
|
304
278
|
|
|
305
|
-
|
|
306
|
-
const
|
|
279
|
+
// Object form
|
|
280
|
+
const classObj = classPropertyAccumulator({ btn: true });
|
|
281
|
+
classObj.add('primary', true);
|
|
282
|
+
classObj.add('disabled', false);
|
|
283
|
+
classObj.value(); // { btn: true, primary: true, disabled: false }
|
|
307
284
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
285
|
+
// CSS accumulator
|
|
286
|
+
const styles = cssPropertyAccumulator({ color: 'red' });
|
|
287
|
+
styles.add('font-size', '16px');
|
|
288
|
+
styles.add('margin', '10px');
|
|
311
289
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
refs.nameInput.focus(); // Use the reference
|
|
315
|
-
})
|
|
316
|
-
]);
|
|
290
|
+
const element = Div({ style: styles.value() }, 'Styled content');
|
|
291
|
+
// style="color: red; font-size: 16px; margin: 10px"
|
|
317
292
|
```
|
|
318
293
|
|
|
319
294
|
## Shadow DOM
|
|
320
295
|
|
|
321
|
-
NativeDocument supports Shadow DOM for encapsulated components:
|
|
322
296
|
```javascript
|
|
323
|
-
// Open shadow DOM (inspectable)
|
|
324
|
-
const widget = Div(
|
|
297
|
+
// Open shadow DOM (inspectable in DevTools)
|
|
298
|
+
const widget = Div('Widget content')
|
|
325
299
|
.nd.openShadow(`
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
padding: 20px;
|
|
329
|
-
background: #f0f0f0;
|
|
330
|
-
}
|
|
331
|
-
p { color: blue; }
|
|
332
|
-
|
|
300
|
+
:host { display: block; padding: 20px; }
|
|
301
|
+
p { color: blue; }
|
|
333
302
|
`);
|
|
334
303
|
|
|
335
304
|
// Closed shadow DOM (private)
|
|
336
|
-
const privateWidget = Div(
|
|
337
|
-
.nd.closedShadow(`
|
|
338
|
-
p { color: red; }
|
|
339
|
-
|
|
340
|
-
`);
|
|
305
|
+
const privateWidget = Div('Private content')
|
|
306
|
+
.nd.closedShadow(`p { color: red; }`);
|
|
341
307
|
|
|
342
|
-
// Manual
|
|
343
|
-
const customWidget = Div(
|
|
344
|
-
.nd.shadow('open',
|
|
345
|
-
/* Scoped styles */
|
|
346
|
-
|
|
347
|
-
`);
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
## Practical Example: Simple Button with Event
|
|
351
|
-
|
|
352
|
-
```javascript
|
|
353
|
-
const count = Observable(0);
|
|
354
|
-
|
|
355
|
-
const incrementButton = Button({
|
|
356
|
-
class: "btn btn-primary",
|
|
357
|
-
type: "button"
|
|
358
|
-
}, "Increment")
|
|
359
|
-
.nd.onClick(() => {
|
|
360
|
-
count.set(count.val() + 1);
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
const display = Div({ class: "counter-display" }, [
|
|
364
|
-
P("Current count: "),
|
|
365
|
-
Strong(count) // Reactive display
|
|
366
|
-
]);
|
|
367
|
-
|
|
368
|
-
const app = Div({ class: "counter-app" }, [
|
|
369
|
-
display,
|
|
370
|
-
incrementButton
|
|
371
|
-
]);
|
|
308
|
+
// Manual mode
|
|
309
|
+
const customWidget = Div('Custom')
|
|
310
|
+
.nd.shadow('open', `/* scoped styles */`);
|
|
372
311
|
```
|
|
373
312
|
|
|
374
313
|
## Practical Example: Form with Validation
|
|
375
314
|
|
|
376
315
|
```javascript
|
|
377
|
-
const formData = Observable.object({
|
|
378
|
-
|
|
379
|
-
email: "",
|
|
380
|
-
age: ""
|
|
381
|
-
});
|
|
316
|
+
const formData = Observable.object({ name: '', email: '', age: '' });
|
|
317
|
+
const errors = Observable.object({ name: '', email: '', age: '' });
|
|
382
318
|
|
|
383
|
-
const errors = Observable.object({
|
|
384
|
-
name: "",
|
|
385
|
-
email: "",
|
|
386
|
-
age: ""
|
|
387
|
-
});
|
|
388
|
-
|
|
389
|
-
// Validation function
|
|
390
319
|
const validateForm = () => {
|
|
391
320
|
const data = formData.$value;
|
|
392
|
-
const newErrors = {};
|
|
393
|
-
|
|
394
|
-
newErrors.name = data.name.length < 2 ? "Name must be at least 2 characters" : "";
|
|
395
|
-
newErrors.email = !data.email.includes("@") ? "Invalid email address" : "";
|
|
396
|
-
newErrors.age = isNaN(data.age) || data.age < 1 ? "Age must be a valid number" : "";
|
|
397
321
|
|
|
398
|
-
|
|
322
|
+
errors.name.set(data.name.length < 2 ? 'Name must be at least 2 characters' : '');
|
|
323
|
+
errors.email.set(!data.email.includes('@') ? 'Invalid email address' : '');
|
|
324
|
+
errors.age.set(isNaN(data.age) || data.age < 1 ? 'Age must be a valid number' : '');
|
|
399
325
|
|
|
400
|
-
errors.
|
|
401
|
-
|
|
402
|
-
return Object.values(newErrors).every(error => error === "");
|
|
326
|
+
return [errors.name, errors.email, errors.age].every(e => e.val() === '');
|
|
403
327
|
};
|
|
404
328
|
|
|
405
|
-
const contactForm = Form({ class:
|
|
406
|
-
|
|
407
|
-
Div({ class:
|
|
408
|
-
Label(
|
|
409
|
-
Input({
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
placeholder: "Enter your name"
|
|
413
|
-
}).nd.onBlur(validateForm),
|
|
414
|
-
|
|
415
|
-
ShowIf(errors.name.check(err => err !== ""),
|
|
416
|
-
Span({ class: "error" }, errors.name)
|
|
417
|
-
)
|
|
329
|
+
const contactForm = Form({ class: 'contact-form' }, [
|
|
330
|
+
|
|
331
|
+
Div({ class: 'field' }, [
|
|
332
|
+
Label('Name:'),
|
|
333
|
+
Input({ type: 'text', value: formData.name, placeholder: 'Enter your name' })
|
|
334
|
+
.nd.onBlur(validateForm),
|
|
335
|
+
ShowIf(errors.name.isTruthy(), Span({ class: 'error' }, errors.name))
|
|
418
336
|
]),
|
|
419
337
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
value: formData.email,
|
|
426
|
-
placeholder: "Enter your email"
|
|
427
|
-
}).nd.onBlur(validateForm),
|
|
428
|
-
|
|
429
|
-
ShowIf(errors.email.check(err => err !== ""),
|
|
430
|
-
Span({ class: "error" }, errors.email)
|
|
431
|
-
)
|
|
338
|
+
Div({ class: 'field' }, [
|
|
339
|
+
Label('Email:'),
|
|
340
|
+
Input({ type: 'email', value: formData.email, placeholder: 'Enter your email' })
|
|
341
|
+
.nd.onBlur(validateForm),
|
|
342
|
+
ShowIf(errors.email.isTruthy(), Span({ class: 'error' }, errors.email))
|
|
432
343
|
]),
|
|
433
344
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
value: formData.age,
|
|
440
|
-
placeholder: "Enter your age"
|
|
441
|
-
}).nd.onBlur(validateForm),
|
|
442
|
-
|
|
443
|
-
ShowIf(errors.age.check(err => err !== ""),
|
|
444
|
-
Span({ class: "error" }, errors.age)
|
|
445
|
-
)
|
|
345
|
+
Div({ class: 'field' }, [
|
|
346
|
+
Label('Age:'),
|
|
347
|
+
Input({ type: 'number', value: formData.age, placeholder: 'Enter your age' })
|
|
348
|
+
.nd.onBlur(validateForm),
|
|
349
|
+
ShowIf(errors.age.isTruthy(), Span({ class: 'error' }, errors.age))
|
|
446
350
|
]),
|
|
447
351
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
if (validateForm()) {
|
|
456
|
-
console.log("Form is valid!", formData.$value);
|
|
457
|
-
// Handle successful submission
|
|
458
|
-
} else {
|
|
459
|
-
console.log("Form has errors");
|
|
460
|
-
}
|
|
461
|
-
});
|
|
352
|
+
Button({ type: 'submit', class: 'btn btn-primary' }, 'Submit')
|
|
353
|
+
|
|
354
|
+
]).nd.onPreventSubmit(() => {
|
|
355
|
+
if (validateForm()) {
|
|
356
|
+
console.log('Form is valid!', formData.$value);
|
|
357
|
+
}
|
|
358
|
+
});
|
|
462
359
|
```
|
|
463
360
|
|
|
464
|
-
## Available Elements
|
|
361
|
+
## Available HTML Elements
|
|
465
362
|
|
|
466
|
-
|
|
363
|
+
**Text:** `H1`, `H2`, `H3`, `H4`, `H5`, `H6`, `P`, `Span`, `Strong`, `Em`, `Small`, `Mark`, `BlockQuote`, `Pre`, `Code`
|
|
467
364
|
|
|
468
|
-
**
|
|
365
|
+
**Layout:** `Div`, `Section`, `Article`, `Aside`, `Header`, `Footer`, `Nav`, `Main`
|
|
469
366
|
|
|
470
|
-
**
|
|
367
|
+
**Form:** `Form`, `Input`, `TextArea`, `Select`, `Option`, `Button`, `Label`, `FieldSet`, `Legend`
|
|
471
368
|
|
|
472
|
-
**
|
|
369
|
+
**List:** `Ul`, `Ol`, `Li`, `Dl`, `Dt`, `Dd`
|
|
473
370
|
|
|
474
|
-
**
|
|
371
|
+
**Media:** `Img`, `Audio`, `Video`, `Canvas`
|
|
475
372
|
|
|
476
|
-
**
|
|
373
|
+
**Interactive:** `Link`, `Details`, `Summary`, `Dialog`
|
|
477
374
|
|
|
478
|
-
**
|
|
375
|
+
**SVG:** `Svg`, `SvgSvg`, `SvgCircle`, `SvgRect`, `SvgEllipse`, `SvgLine`, `SvgPolyline`, `SvgPolygon`, `SvgPath`, `SvgText`, `SvgTSpan`, `SvgG`, `SvgDefs`, `SvgUse`, `SvgSymbol`, `SvgClipPath`, `SvgMask`, `SvgMarker`, `SvgPattern`, `SvgImage`, `SvgLinearGradient`, `SvgRadialGradient`, `SvgStop`, `SvgFilter`, and more.
|
|
479
376
|
|
|
480
|
-
|
|
377
|
+
> For detailed SVG usage and examples, see [SVG Elements](./svg-elements.md).
|
|
481
378
|
|
|
482
379
|
## Best Practices
|
|
483
380
|
|
|
484
|
-
1.
|
|
485
|
-
2.
|
|
486
|
-
3.
|
|
487
|
-
4.
|
|
488
|
-
5.
|
|
489
|
-
6.
|
|
490
|
-
7. **Use conditional rendering** with `ShowIf` for dynamic content
|
|
381
|
+
1. Use semantic HTML elements for better accessibility
|
|
382
|
+
2. Leverage reactive attributes with observables for dynamic UIs
|
|
383
|
+
3. Use `.nd.with()` for instance-level customization, `NDElement.prototype` for app-wide methods
|
|
384
|
+
4. Store element references with `.nd.ref()` when you need direct DOM access
|
|
385
|
+
5. Use `ShowIf` with `.isTruthy()` / `.isFalsy()` for clean conditional rendering
|
|
386
|
+
6. Group related elements in logical containers
|
|
491
387
|
|
|
492
388
|
## Next Steps
|
|
493
389
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
- **[
|
|
497
|
-
- **[
|
|
498
|
-
- **[
|
|
499
|
-
- **[
|
|
500
|
-
- **[Lifecycle Events](lifecycle-events.md)** -
|
|
501
|
-
- **[NDElement](native-document-element.md)** - Native Document Element
|
|
502
|
-
- **[Extending NDElement](extending-native-document-element.md)** - Custom Methods Guide
|
|
503
|
-
- **[Advanced Components](advanced-components.md)** - Template caching and singleton views
|
|
504
|
-
- **[Args Validation](validation.md)** - Function Argument Validation
|
|
505
|
-
- **[Memory Management](memory-management.md)** - Memory management
|
|
506
|
-
- **[Anchor](anchor.md)** - Anchor
|
|
507
|
-
|
|
508
|
-
## Utilities
|
|
509
|
-
|
|
510
|
-
- **[Cache](docs/utils/cache.md)** - Lazy initialization and singleton patterns
|
|
511
|
-
- **[NativeFetch](docs/utils/native-fetch.md)** - HTTP client with interceptors
|
|
512
|
-
- **[Filters](docs/utils/filters.md)** - Data filtering helpers
|
|
390
|
+
- **[Conditional Rendering](./conditional-rendering.md)** - Dynamic content
|
|
391
|
+
- **[List Rendering](./list-rendering.md)** - ForEach and dynamic lists
|
|
392
|
+
- **[NDElement](./native-document-element.md)** - Full `.nd` API reference
|
|
393
|
+
- **[Extending NDElement](./extending-native-document-element.md)** - Custom methods guide
|
|
394
|
+
- **[SVG Elements](./svg-elements.md)** - SVG wrapper functions
|
|
395
|
+
- **[Advanced Components](./advanced-components.md)** - Template caching and singleton views
|
|
396
|
+
- **[Lifecycle Events](./lifecycle-events.md)** - Mounted, unmounted, beforeUnmount
|