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
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import DocumentObserver from
|
|
2
|
-
import PluginsManager from
|
|
3
|
-
import NativeDocumentError from
|
|
4
|
-
import DebugManager from
|
|
1
|
+
import DocumentObserver from './DocumentObserver';
|
|
2
|
+
import PluginsManager from '../utils/plugins-manager';
|
|
3
|
+
import NativeDocumentError from '../errors/NativeDocumentError.js';
|
|
4
|
+
import DebugManager from '../utils/debug-manager.js';
|
|
5
5
|
import attributesWrapper, {
|
|
6
6
|
bindAttributeWithObservable,
|
|
7
7
|
bindClassAttribute,
|
|
8
|
-
bindStyleAttribute
|
|
9
|
-
} from
|
|
8
|
+
bindStyleAttribute,
|
|
9
|
+
} from './AttributesWrapper';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Wraps an HTMLElement with NativeDocument's reactivity and lifecycle API.
|
|
13
|
+
* Created automatically by HtmlElementWrapper — not intended to be instantiated directly.
|
|
14
|
+
*
|
|
15
|
+
* @constructor
|
|
16
|
+
* @param {HTMLElement} element - The underlying HTML element to wrap
|
|
17
|
+
*/
|
|
11
18
|
export function NDElement(element) {
|
|
12
19
|
this.$element = element;
|
|
13
20
|
this.$attachements = null;
|
|
@@ -16,10 +23,18 @@ export function NDElement(element) {
|
|
|
16
23
|
}
|
|
17
24
|
}
|
|
18
25
|
|
|
26
|
+
|
|
19
27
|
NDElement.prototype.__$isNDElement = true;
|
|
20
28
|
|
|
21
29
|
NDElement.$getChild = (el) => el;
|
|
22
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Appends a child element to an internal DocumentFragment (ghost DOM),
|
|
33
|
+
* keeping it detached from the main document until explicitly mounted.
|
|
34
|
+
*
|
|
35
|
+
* @param {HTMLElement|DocumentFragment|NDElement} element - Element to append
|
|
36
|
+
* @returns {this}
|
|
37
|
+
*/
|
|
23
38
|
NDElement.prototype.ghostDom = function(element) {
|
|
24
39
|
if(!this.$attachements) {
|
|
25
40
|
this.$attachements = document.createDocumentFragment();
|
|
@@ -28,15 +43,47 @@ NDElement.prototype.ghostDom = function(element) {
|
|
|
28
43
|
return this;
|
|
29
44
|
};
|
|
30
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Returns the underlying HTMLElement. Used internally for type coercion.
|
|
48
|
+
*
|
|
49
|
+
* @returns {HTMLElement}
|
|
50
|
+
*/
|
|
31
51
|
NDElement.prototype.valueOf = function() {
|
|
32
52
|
return this.$element;
|
|
33
53
|
};
|
|
34
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Stores the underlying HTMLElement in target[name].
|
|
57
|
+
* Use this to keep a reference to the raw DOM node.
|
|
58
|
+
*
|
|
59
|
+
* @param {Record<string, any>} target - Object to store the reference in
|
|
60
|
+
* @param {string} name - Property name to assign on the target object
|
|
61
|
+
* @returns {this}
|
|
62
|
+
* @example
|
|
63
|
+
* const refs = {};
|
|
64
|
+
* Input({ type: 'text' }).nd.ref(refs, 'emailInput');
|
|
65
|
+
* refs.emailInput.focus();
|
|
66
|
+
*/
|
|
35
67
|
NDElement.prototype.ref = function(target, name) {
|
|
36
68
|
target[name] = this.$element;
|
|
37
69
|
return this;
|
|
38
70
|
};
|
|
39
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Stores the NDElement instance itself in target[name].
|
|
74
|
+
* Use this to expose a component's public API to a parent (via .with()).
|
|
75
|
+
*
|
|
76
|
+
* @param {Record<string, any>} target - Object to store the reference in
|
|
77
|
+
* @param {string} name - Property name to assign on the target object
|
|
78
|
+
* @returns {this}
|
|
79
|
+
* @example
|
|
80
|
+
* const refs = {};
|
|
81
|
+
* Counter()
|
|
82
|
+
* .nd.with({ increment() { count.$value++; return this; } })
|
|
83
|
+
* .refSelf(refs, 'counter');
|
|
84
|
+
*
|
|
85
|
+
* refs.counter.increment();
|
|
86
|
+
*/
|
|
40
87
|
NDElement.prototype.refSelf = function(target, name) {
|
|
41
88
|
target[name] = this;
|
|
42
89
|
// TODO: @DIM to check
|
|
@@ -44,6 +91,12 @@ NDElement.prototype.refSelf = function(target, name) {
|
|
|
44
91
|
return this;
|
|
45
92
|
};
|
|
46
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Calls .nd.remove() on all child NDElements before removing this element.
|
|
96
|
+
* Used to propagate lifecycle cleanup through the component tree.
|
|
97
|
+
*
|
|
98
|
+
* @returns {this}
|
|
99
|
+
*/
|
|
47
100
|
NDElement.prototype.unmountChildren = function() {
|
|
48
101
|
let element = this.$element;
|
|
49
102
|
for(let i = 0, length = element.children.length; i < length; i++) {
|
|
@@ -57,6 +110,12 @@ NDElement.prototype.unmountChildren = function() {
|
|
|
57
110
|
return this;
|
|
58
111
|
};
|
|
59
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Removes the element from the DOM and cleans up its lifecycle observers.
|
|
115
|
+
* Also calls unmountChildren() recursively.
|
|
116
|
+
*
|
|
117
|
+
* @returns {this}
|
|
118
|
+
*/
|
|
60
119
|
NDElement.prototype.remove = function() {
|
|
61
120
|
let element = this.$element;
|
|
62
121
|
element.nd.unmountChildren();
|
|
@@ -69,6 +128,19 @@ NDElement.prototype.remove = function() {
|
|
|
69
128
|
};
|
|
70
129
|
|
|
71
130
|
const $lifeCycleObservers = new WeakMap();
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Registers mounted and/or unmounted lifecycle callbacks for this element.
|
|
134
|
+
* Uses MutationObserver internally to detect DOM insertion and removal.
|
|
135
|
+
*
|
|
136
|
+
* @param {{ mounted?: (el: HTMLElement) => void, unmounted?: (el: HTMLElement) => boolean|void }} states - Lifecycle hooks
|
|
137
|
+
* @returns {this}
|
|
138
|
+
* @example
|
|
139
|
+
* Div({}).nd.lifecycle({
|
|
140
|
+
* mounted: (el) => console.log('mounted', el),
|
|
141
|
+
* unmounted: (el) => console.log('unmounted', el),
|
|
142
|
+
* });
|
|
143
|
+
*/
|
|
72
144
|
NDElement.prototype.lifecycle = function(states) {
|
|
73
145
|
const el = this.$element;
|
|
74
146
|
if (!$lifeCycleObservers.has(el)) {
|
|
@@ -87,31 +159,68 @@ NDElement.prototype.lifecycle = function(states) {
|
|
|
87
159
|
return this;
|
|
88
160
|
};
|
|
89
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Registers an unmounted callback that cleans up all beforeUnmount handlers
|
|
164
|
+
* and aborts any pending async operations on this element and its children.
|
|
165
|
+
*
|
|
166
|
+
* @returns {this}
|
|
167
|
+
*/
|
|
90
168
|
NDElement.prototype.destroyOnUnmount = function() {
|
|
91
|
-
this.unmounted(() =>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
child.__$controller?.abort();
|
|
95
|
-
child.__$controller = null;
|
|
96
|
-
$lifeCycleObservers.delete(child);
|
|
97
|
-
});
|
|
169
|
+
this.unmounted(() => this.destroy());
|
|
170
|
+
return this;
|
|
171
|
+
};
|
|
98
172
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
173
|
+
/**
|
|
174
|
+
* aborts any pending async operations on this element and its children.
|
|
175
|
+
*
|
|
176
|
+
* @returns {this}
|
|
177
|
+
*/
|
|
178
|
+
NDElement.prototype.destroy = function() {
|
|
179
|
+
this.$element?.querySelectorAll('[data--nd-before-unmount]').forEach(child => {
|
|
180
|
+
child.remove();
|
|
181
|
+
child.__$controller?.abort();
|
|
182
|
+
child.__$controller = null;
|
|
183
|
+
$lifeCycleObservers.delete(child);
|
|
103
184
|
});
|
|
104
|
-
|
|
185
|
+
|
|
186
|
+
this.$element.__$controller?.abort();
|
|
187
|
+
this.$element.__$controller = null;
|
|
188
|
+
$lifeCycleObservers.delete(this.$element);
|
|
189
|
+
this.$element = null;
|
|
105
190
|
};
|
|
106
191
|
|
|
192
|
+
/**
|
|
193
|
+
* Shorthand for lifecycle({ mounted: callback }).
|
|
194
|
+
*
|
|
195
|
+
* @param {(el: HTMLElement) => void} callback - Called when element is inserted into the DOM
|
|
196
|
+
* @returns {this}
|
|
197
|
+
*/
|
|
107
198
|
NDElement.prototype.mounted = function(callback) {
|
|
108
199
|
return this.lifecycle({ mounted: callback });
|
|
109
200
|
};
|
|
110
201
|
|
|
202
|
+
/**
|
|
203
|
+
* Shorthand for lifecycle({ unmounted: callback }).
|
|
204
|
+
*
|
|
205
|
+
* @param {(el: HTMLElement) => boolean|void} callback - Called when element is removed from the DOM
|
|
206
|
+
* @returns {this}
|
|
207
|
+
*/
|
|
111
208
|
NDElement.prototype.unmounted = function(callback) {
|
|
112
209
|
return this.lifecycle({ unmounted: callback });
|
|
113
210
|
};
|
|
114
211
|
|
|
212
|
+
/**
|
|
213
|
+
* Registers an async callback to run before this element is removed from the DOM.
|
|
214
|
+
* The element's .remove() is delayed until all beforeUnmount callbacks resolve.
|
|
215
|
+
*
|
|
216
|
+
* @param {string} id - Unique identifier for this callback (allows overwriting)
|
|
217
|
+
* @param {(this: NDElement, el: HTMLElement) => void|Promise<void>} callback - Async-compatible callback
|
|
218
|
+
* @returns {this}
|
|
219
|
+
* @example
|
|
220
|
+
* Div({}).nd.beforeUnmount('fade-out', async (el) => {
|
|
221
|
+
* await el.animate([{ opacity: 1 }, { opacity: 0 }], { duration: 300 }).finished;
|
|
222
|
+
* });
|
|
223
|
+
*/
|
|
115
224
|
NDElement.prototype.beforeUnmount = function(id, callback) {
|
|
116
225
|
const el = this.$element;
|
|
117
226
|
|
|
@@ -144,18 +253,31 @@ NDElement.prototype.beforeUnmount = function(id, callback) {
|
|
|
144
253
|
return this;
|
|
145
254
|
};
|
|
146
255
|
|
|
256
|
+
/**
|
|
257
|
+
* Returns the underlying HTMLElement.
|
|
258
|
+
* Alias: .node()
|
|
259
|
+
*
|
|
260
|
+
* @returns {HTMLElement}
|
|
261
|
+
*/
|
|
147
262
|
NDElement.prototype.htmlElement = function() {
|
|
148
263
|
return this.$element;
|
|
149
264
|
};
|
|
150
265
|
|
|
151
266
|
NDElement.prototype.node = NDElement.prototype.htmlElement;
|
|
152
267
|
|
|
268
|
+
/**
|
|
269
|
+
* Attaches a Shadow DOM to this element, redirecting all child appends to the shadow root.
|
|
270
|
+
*
|
|
271
|
+
* @param {'open'|'closed'} mode - Shadow DOM encapsulation mode
|
|
272
|
+
* @param {string|null} [style=null] - Optional CSS string to inject into the shadow root
|
|
273
|
+
* @returns {this}
|
|
274
|
+
*/
|
|
153
275
|
NDElement.prototype.shadow = function(mode, style = null) {
|
|
154
276
|
const $element = this.$element;
|
|
155
|
-
const children = Array.from($element.childNodes)
|
|
277
|
+
const children = Array.from($element.childNodes);
|
|
156
278
|
const shadowRoot = $element.attachShadow({ mode });
|
|
157
279
|
if(style) {
|
|
158
|
-
const styleNode = document.createElement(
|
|
280
|
+
const styleNode = document.createElement('style');
|
|
159
281
|
styleNode.textContent = style;
|
|
160
282
|
shadowRoot.appendChild(styleNode);
|
|
161
283
|
}
|
|
@@ -166,10 +288,22 @@ NDElement.prototype.shadow = function(mode, style = null) {
|
|
|
166
288
|
return this;
|
|
167
289
|
};
|
|
168
290
|
|
|
291
|
+
/**
|
|
292
|
+
* Shorthand for .shadow('open', style).
|
|
293
|
+
*
|
|
294
|
+
* @param {string|null} [style=null] - Optional CSS string to inject into the shadow root
|
|
295
|
+
* @returns {this}
|
|
296
|
+
*/
|
|
169
297
|
NDElement.prototype.openShadow = function(style = null) {
|
|
170
298
|
return this.shadow('open', style);
|
|
171
299
|
};
|
|
172
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Shorthand for .shadow('closed', style).
|
|
303
|
+
*
|
|
304
|
+
* @param {string|null} [style=null] - Optional CSS string to inject into the shadow root
|
|
305
|
+
* @returns {this}
|
|
306
|
+
*/
|
|
173
307
|
NDElement.prototype.closedShadow = function(style = null) {
|
|
174
308
|
return this.shadow('closed', style);
|
|
175
309
|
};
|
|
@@ -218,7 +352,16 @@ NDElement.prototype.with = function(methods) {
|
|
|
218
352
|
return this;
|
|
219
353
|
};
|
|
220
354
|
|
|
221
|
-
|
|
355
|
+
/**
|
|
356
|
+
* Sets a single attribute on the element.
|
|
357
|
+
* If value is an ObservableItem, the attribute is updated reactively.
|
|
358
|
+
*
|
|
359
|
+
* @param {string} name - Attribute name
|
|
360
|
+
* @param {string|ObservableItem<string>} value - Attribute value, static or reactive
|
|
361
|
+
* @returns {this}
|
|
362
|
+
* @example
|
|
363
|
+
* Input({}).nd.attr('placeholder', label); // reactive placeholder
|
|
364
|
+
*/
|
|
222
365
|
NDElement.prototype.attr = function(name, value) {
|
|
223
366
|
if(value?.__$Observable) {
|
|
224
367
|
bindAttributeWithObservable(this.$element, name, value);
|
|
@@ -228,16 +371,37 @@ NDElement.prototype.attr = function(name, value) {
|
|
|
228
371
|
return this;
|
|
229
372
|
};
|
|
230
373
|
|
|
374
|
+
/**
|
|
375
|
+
* Applies a batch of attributes to the element via AttributesWrapper.
|
|
376
|
+
* Supports reactive values, class maps, and style maps.
|
|
377
|
+
*
|
|
378
|
+
* @param {Object} attrs - Attributes object (same format as HtmlElementWrapper props)
|
|
379
|
+
* @returns {this}
|
|
380
|
+
*/
|
|
231
381
|
NDElement.prototype.attrs = function(attrs) {
|
|
232
382
|
attributesWrapper(this.$element, attrs);
|
|
233
383
|
return this;
|
|
234
384
|
};
|
|
235
385
|
|
|
386
|
+
/**
|
|
387
|
+
* Applies a reactive class map to the element.
|
|
388
|
+
* Each key is a class name; each value is a boolean or ObservableItem<boolean>.
|
|
389
|
+
*
|
|
390
|
+
* @param {Record<string, boolean|ObservableItem<boolean>>} classes - Class map
|
|
391
|
+
* @returns {this}
|
|
392
|
+
*/
|
|
236
393
|
NDElement.prototype.class = function(classes) {
|
|
237
394
|
bindClassAttribute(this.$element, classes);
|
|
238
395
|
return this;
|
|
239
396
|
};
|
|
240
397
|
|
|
398
|
+
/**
|
|
399
|
+
* Applies a reactive style map to the element.
|
|
400
|
+
* Each key is a CSS property; each value is a string or ObservableItem<string>.
|
|
401
|
+
*
|
|
402
|
+
* @param {Record<string, string|ObservableItem<string>>} style - Style map
|
|
403
|
+
* @returns {this}
|
|
404
|
+
*/
|
|
241
405
|
NDElement.prototype.style = function(style) {
|
|
242
406
|
bindStyleAttribute(this.$element, style);
|
|
243
407
|
return this;
|
|
@@ -273,7 +437,7 @@ NDElement.extend = function(methods) {
|
|
|
273
437
|
const protectedMethods = new Set([
|
|
274
438
|
'constructor', 'valueOf', '$element', '$observer',
|
|
275
439
|
'ref', 'remove', 'cleanup', 'with', 'extend', 'attach',
|
|
276
|
-
'lifecycle', 'mounted', 'unmounted', 'unmountChildren'
|
|
440
|
+
'lifecycle', 'mounted', 'unmounted', 'unmountChildren',
|
|
277
441
|
]);
|
|
278
442
|
|
|
279
443
|
for (const name in methods) {
|
|
@@ -304,4 +468,146 @@ NDElement.extend = function(methods) {
|
|
|
304
468
|
}
|
|
305
469
|
|
|
306
470
|
return NDElement;
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* The global sanitizer function used by nd.html() when sanitize option is enabled.
|
|
476
|
+
* Must be set via NDElement.setSanitizer() before using {sanitize: true}.
|
|
477
|
+
*
|
|
478
|
+
* @type {Function|null}
|
|
479
|
+
*/
|
|
480
|
+
NDElement.$sanitizer = null;
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Configures the global sanitizer for nd.html().
|
|
484
|
+
* The sanitizer function receives the HTML string and an optional config object.
|
|
485
|
+
* Designed to be decoupled from any specific sanitizer library.
|
|
486
|
+
*
|
|
487
|
+
* @param {Function} sanitizerFn - Sanitizer function (html, config) => string
|
|
488
|
+
* @returns {typeof NDElement}
|
|
489
|
+
* @throws {NativeDocumentError} If sanitizerFn is not a function
|
|
490
|
+
* @example
|
|
491
|
+
* import DOMPurify from 'dompurify';
|
|
492
|
+
* NDElement.setSanitizer((html, config) => DOMPurify.sanitize(html, config));
|
|
493
|
+
*/
|
|
494
|
+
NDElement.setSanitizer = function(sanitizerFn) {
|
|
495
|
+
if(typeof sanitizerFn !== 'function') {
|
|
496
|
+
throw new NativeDocumentError('NDElement.setSanitizer() expects a function');
|
|
497
|
+
}
|
|
498
|
+
NDElement.$sanitizer = sanitizerFn;
|
|
499
|
+
return NDElement;
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Sets the inner HTML of the element.
|
|
504
|
+
* Requires either {unsafe: true} to bypass security checks,
|
|
505
|
+
* or {sanitize: true|Object|Function} to sanitize the content.
|
|
506
|
+
* Supports Observable values for reactive HTML updates.
|
|
507
|
+
*
|
|
508
|
+
* @param {string|ObservableItem} content - HTML string or Observable<string>
|
|
509
|
+
* @param {Object} [options={}]
|
|
510
|
+
* @param {boolean} [options.unsafe=false] - Bypass security check. Use only with trusted content.
|
|
511
|
+
* @param {boolean|Object|Function} [options.sanitize=false] - Sanitize strategy:
|
|
512
|
+
* - true: use global sanitizer with default config
|
|
513
|
+
* - Object: use global sanitizer with custom config
|
|
514
|
+
* - Function: use this function directly as sanitizer (html) => string
|
|
515
|
+
* @returns {this}
|
|
516
|
+
* @throws {NativeDocumentError} If sanitize is true/Object but no global sanitizer is configured
|
|
517
|
+
* @example
|
|
518
|
+
* // Unsafe — trusted content only
|
|
519
|
+
* el.nd.html('<strong>Hello</strong>', {unsafe: true})
|
|
520
|
+
*
|
|
521
|
+
* // Global sanitizer with default config
|
|
522
|
+
* el.nd.html($userContent, {sanitize: true})
|
|
523
|
+
*
|
|
524
|
+
* // Global sanitizer with custom config
|
|
525
|
+
* el.nd.html($userContent, {sanitize: {
|
|
526
|
+
* ALLOWED_TAGS: ['b', 'i', 'strong', 'a'],
|
|
527
|
+
* ALLOWED_ATTR: ['href'],
|
|
528
|
+
* }})
|
|
529
|
+
*
|
|
530
|
+
* // Custom sanitizer function for this specific case
|
|
531
|
+
* el.nd.html($userContent, {sanitize: (html) => myCustomSanitizer(html)})
|
|
532
|
+
*
|
|
533
|
+
* // Reactive with sanitize
|
|
534
|
+
* el.nd.html($content, {sanitize: true})
|
|
535
|
+
*/
|
|
536
|
+
NDElement.prototype.html = function(content, {unsafe = false, sanitize = false} = {}) {
|
|
537
|
+
const $element = this.$element;
|
|
538
|
+
const apply = (value) => {
|
|
539
|
+
if(sanitize) {
|
|
540
|
+
if(typeof sanitize === 'function') {
|
|
541
|
+
$element.innerHTML = sanitize(value);
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if(!NDElement.$sanitizer) {
|
|
546
|
+
throw new NativeDocumentError('nd.html() — no sanitizer configured. Call NDElement.setSanitizer() first.');
|
|
547
|
+
}
|
|
548
|
+
const config = sanitize === true ? {} : sanitize;
|
|
549
|
+
$element.innerHTML = NDElement.$sanitizer(value, config);
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
if(!unsafe) {
|
|
554
|
+
console.warn('nd.html() — use {unsafe: true} or {sanitize: true|Object|Function}');
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
$element.innerHTML = value;
|
|
559
|
+
};
|
|
560
|
+
|
|
561
|
+
if(content?.__$Observable) {
|
|
562
|
+
content.subscribe(apply);
|
|
563
|
+
apply(content.val());
|
|
564
|
+
return this;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
apply(content);
|
|
568
|
+
return this;
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Makes the element content editable and binds it to an Observable.
|
|
573
|
+
* Changes in the DOM update the Observable, and changes to the Observable
|
|
574
|
+
* update the DOM (only when the element is not focused to avoid cursor issues).
|
|
575
|
+
*
|
|
576
|
+
* @param {ObservableItem} $obs - Observable to bind to the element content
|
|
577
|
+
* @param {Object} [options={}]
|
|
578
|
+
* @param {string} [options.format='html'] - 'html' uses innerHTML, 'text' uses innerText
|
|
579
|
+
* @returns {this}
|
|
580
|
+
* @example
|
|
581
|
+
* // Basic usage
|
|
582
|
+
* const $content = $('<b>Hello</b>');
|
|
583
|
+
* Div({}).nd.contentEditable($content)
|
|
584
|
+
*
|
|
585
|
+
* // Text only
|
|
586
|
+
* Div({}).nd.contentEditable($content, {format: 'text'})
|
|
587
|
+
*/
|
|
588
|
+
NDElement.prototype.contentEditable = function($obs, {format = 'html'} = {}) {
|
|
589
|
+
this.$element.contentEditable = true;
|
|
590
|
+
|
|
591
|
+
const getValue = format === 'text'
|
|
592
|
+
? () => this.$element.innerText
|
|
593
|
+
: () => this.$element.innerHTML;
|
|
594
|
+
|
|
595
|
+
const setValue = format === 'text'
|
|
596
|
+
? (value) => { this.$element.innerText = value; }
|
|
597
|
+
: (value) => { this.$element.innerHTML = value; };
|
|
598
|
+
|
|
599
|
+
if($obs?.__$Observable) {
|
|
600
|
+
$obs.subscribe((value) => {
|
|
601
|
+
if(document.activeElement !== this.$element) {
|
|
602
|
+
setValue(value);
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
setValue($obs.val() || '');
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
this.$element.addEventListener('input', () => {
|
|
609
|
+
$obs?.set(getValue());
|
|
610
|
+
}, { signal: this.$getSignal() });
|
|
611
|
+
|
|
612
|
+
return this;
|
|
307
613
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { NDElement } from
|
|
2
|
-
import {EVENTS, EVENTS_WITH_PREVENT, EVENTS_WITH_STOP} from
|
|
1
|
+
import { NDElement } from './NDElement';
|
|
2
|
+
import {EVENTS, EVENTS_WITH_PREVENT, EVENTS_WITH_STOP} from '../utils/events';
|
|
3
3
|
|
|
4
4
|
const property = {
|
|
5
5
|
configurable: true,
|
|
6
6
|
get() {
|
|
7
7
|
return new NDElement(this);
|
|
8
|
-
}
|
|
8
|
+
},
|
|
9
9
|
};
|
|
10
10
|
|
|
11
11
|
Object.defineProperty(HTMLElement.prototype, 'nd', property);
|
|
@@ -16,7 +16,7 @@ Object.defineProperty(NDElement.prototype, 'nd', {
|
|
|
16
16
|
configurable: true,
|
|
17
17
|
get: function() {
|
|
18
18
|
return this;
|
|
19
|
-
}
|
|
19
|
+
},
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
|
|
@@ -29,25 +29,25 @@ EVENTS.forEach(eventSourceName => {
|
|
|
29
29
|
NDElement.prototype['on'+eventSourceName] = function(callback = null, options = {}) {
|
|
30
30
|
this.$element.addEventListener(eventName, callback, {
|
|
31
31
|
signal: this.$getSignal(),
|
|
32
|
-
...options
|
|
32
|
+
...options,
|
|
33
33
|
});
|
|
34
34
|
return this;
|
|
35
35
|
};
|
|
36
|
-
})
|
|
36
|
+
});
|
|
37
37
|
|
|
38
38
|
EVENTS_WITH_STOP.forEach(eventSourceName => {
|
|
39
39
|
const eventName = eventSourceName.toLowerCase();
|
|
40
40
|
NDElement.prototype['onStop'+eventSourceName] = function(callback = null, options = {}) {
|
|
41
41
|
_stop(this.$element, eventName, callback, {
|
|
42
42
|
signal: this.$getSignal(),
|
|
43
|
-
...options
|
|
43
|
+
...options,
|
|
44
44
|
});
|
|
45
45
|
return this;
|
|
46
46
|
};
|
|
47
47
|
NDElement.prototype['onPreventStop'+eventSourceName] = function(callback = null, options = {}) {
|
|
48
48
|
_preventStop(this.$element, eventName, callback, {
|
|
49
49
|
signal: this.$getSignal(),
|
|
50
|
-
...options
|
|
50
|
+
...options,
|
|
51
51
|
});
|
|
52
52
|
return this;
|
|
53
53
|
};
|
|
@@ -58,12 +58,20 @@ EVENTS_WITH_PREVENT.forEach(eventSourceName => {
|
|
|
58
58
|
NDElement.prototype['onPrevent'+eventSourceName] = function(callback = null, options = {}) {
|
|
59
59
|
_prevent(this.$element, eventName, callback, {
|
|
60
60
|
signal: this.$getSignal(),
|
|
61
|
-
...options
|
|
61
|
+
...options,
|
|
62
62
|
});
|
|
63
63
|
return this;
|
|
64
64
|
};
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Retrieves or creates an AbortController signal tied to this element's lifecycle.
|
|
69
|
+
* The signal is automatically aborted when the element is removed via .nd.remove().
|
|
70
|
+
* Used internally by all event listeners (onClick, onInput, etc.) to auto-cleanup on unmount.
|
|
71
|
+
*
|
|
72
|
+
* @internal
|
|
73
|
+
* @returns {AbortSignal} The signal for this element's AbortController
|
|
74
|
+
*/
|
|
67
75
|
NDElement.prototype.$getSignal = function() {
|
|
68
76
|
if(!this.$element.__$controller) {
|
|
69
77
|
this.$element.__$controller = new AbortController();
|
|
@@ -71,27 +79,63 @@ NDElement.prototype.$getSignal = function() {
|
|
|
71
79
|
return this.$element.__$controller.signal;
|
|
72
80
|
};
|
|
73
81
|
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Adds a native event listener to the underlying HTMLElement.
|
|
85
|
+
* The listener is automatically removed when the element is unmounted (via AbortSignal).
|
|
86
|
+
*
|
|
87
|
+
* @param {string} name - Event name (case-insensitive, e.g. 'click', 'input')
|
|
88
|
+
* @param {EventListener} callback - Handler to call when the event fires
|
|
89
|
+
* @param {boolean|AddEventListenerOptions} [options] - Listener options merged with the element's AbortSignal
|
|
90
|
+
* @returns {this}
|
|
91
|
+
*/
|
|
74
92
|
NDElement.prototype.on = function(name, callback, options) {
|
|
75
93
|
this.$element.addEventListener(name.toLowerCase(), callback, {
|
|
76
94
|
signal: this.$getSignal(),
|
|
77
|
-
...options
|
|
95
|
+
...options,
|
|
78
96
|
});
|
|
79
97
|
return this;
|
|
80
98
|
};
|
|
81
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Removes a previously registered event listener from the underlying HTMLElement.
|
|
102
|
+
*
|
|
103
|
+
* @param {string} name - Event name (case-insensitive)
|
|
104
|
+
* @param {EventListener} callback - The exact handler reference to remove
|
|
105
|
+
* @returns {this}
|
|
106
|
+
*/
|
|
82
107
|
NDElement.prototype.off = function(name, callback) {
|
|
83
108
|
this.$element.removeEventListener(name.toLowerCase(), callback);
|
|
84
109
|
return this;
|
|
85
110
|
};
|
|
86
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Adds a one-time event listener that removes itself after the first call.
|
|
114
|
+
* Uses the element's AbortSignal for lifecycle-safe cleanup.
|
|
115
|
+
*
|
|
116
|
+
* @param {string} name - Event name (case-insensitive)
|
|
117
|
+
* @param {EventListener} callback - Handler called once when the event fires
|
|
118
|
+
* @returns {this}
|
|
119
|
+
*/
|
|
87
120
|
NDElement.prototype.once = function(name, callback) {
|
|
88
121
|
this.$element.addEventListener(name.toLowerCase(), callback, {
|
|
89
122
|
signal: this.$getSignal(),
|
|
90
|
-
once: true
|
|
123
|
+
once: true,
|
|
91
124
|
});
|
|
92
125
|
return this;
|
|
93
126
|
};
|
|
94
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Dispatches a custom event on the underlying HTMLElement.
|
|
130
|
+
* The event bubbles and is cancelable by default.
|
|
131
|
+
*
|
|
132
|
+
* @param {string} name - Custom event name
|
|
133
|
+
* @param {*} [detail=null] - Data passed in event.detail
|
|
134
|
+
* @returns {this}
|
|
135
|
+
* @example
|
|
136
|
+
* Button('Save').nd.emit('saved', { id: 42 });
|
|
137
|
+
* // Triggers: element.addEventListener('saved', e => console.log(e.detail.id))
|
|
138
|
+
*/
|
|
95
139
|
NDElement.prototype.emit = function(name, detail = null) {
|
|
96
140
|
const event = new CustomEvent(name, {
|
|
97
141
|
detail,
|
|
@@ -109,7 +153,7 @@ const _prevent = function(element, eventName, callback, options) {
|
|
|
109
153
|
};
|
|
110
154
|
element.addEventListener(eventName, handler, options);
|
|
111
155
|
return this;
|
|
112
|
-
}
|
|
156
|
+
};
|
|
113
157
|
|
|
114
158
|
const _stop = function(element, eventName, callback, options) {
|
|
115
159
|
const handler = (event) => {
|
|
@@ -175,15 +219,15 @@ const classListMethods = {
|
|
|
175
219
|
},
|
|
176
220
|
contains(value) {
|
|
177
221
|
return this.getClasses().indexOf(value) >= 0;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
222
|
+
},
|
|
223
|
+
};
|
|
180
224
|
|
|
181
225
|
Object.defineProperty(HTMLElement.prototype, 'classes', {
|
|
182
226
|
configurable: true,
|
|
183
227
|
get() {
|
|
184
228
|
return {
|
|
185
229
|
$element: this,
|
|
186
|
-
...classListMethods
|
|
230
|
+
...classListMethods,
|
|
187
231
|
};
|
|
188
|
-
}
|
|
232
|
+
},
|
|
189
233
|
});
|