native-document 1.0.16 → 1.0.17-1.2

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.
Files changed (680) hide show
  1. package/.npmrc.example +1 -0
  2. package/.vitepress/config.js +166 -0
  3. package/CHANGELOG.md +223 -0
  4. package/cdn.js +19 -0
  5. package/components.d.ts +2 -0
  6. package/components.js +32 -0
  7. package/devtools/ComponentRegistry.js +113 -0
  8. package/devtools/index.js +8 -0
  9. package/devtools/plugin/dev-tools-plugin.js +15 -0
  10. package/devtools/transformers/nd-vite-devtools.js +55 -0
  11. package/devtools/transformers/src/transformComponentForHrm.js +73 -0
  12. package/devtools/transformers/src/transformJsFile.js +9 -0
  13. package/devtools/transformers/src/utils.js +79 -0
  14. package/devtools/transformers/templates/hrm.hook.template.js +46 -0
  15. package/devtools/transformers/templates/hrm.orbservable.hook.template.js +76 -0
  16. package/devtools/widget/Widget.js +49 -0
  17. package/devtools/widget/widget.css +81 -0
  18. package/devtools/widget.js +23 -0
  19. package/dist/native-document.components.min.css +1 -0
  20. package/dist/native-document.components.min.js +23873 -0
  21. package/dist/native-document.dev.js +8464 -1515
  22. package/dist/native-document.dev.js.map +1 -0
  23. package/dist/native-document.devtools.min.js +1 -0
  24. package/dist/native-document.min.js +1 -1
  25. package/docs/advanced-components.md +419 -0
  26. package/docs/anchor.md +181 -257
  27. package/docs/cache.md +180 -0
  28. package/docs/cli.md +179 -0
  29. package/docs/components/accordion.md +172 -0
  30. package/docs/components/alert.md +99 -0
  31. package/docs/components/avatar.md +160 -0
  32. package/docs/components/badge.md +102 -0
  33. package/docs/components/breadcrumb.md +89 -0
  34. package/docs/components/button.md +183 -0
  35. package/docs/components/card.md +69 -0
  36. package/docs/components/context-menu.md +118 -0
  37. package/docs/components/data-table.md +345 -0
  38. package/docs/components/dropdown.md +214 -0
  39. package/docs/components/form/autocomplete-field.md +81 -0
  40. package/docs/components/form/checkbox-field.md +41 -0
  41. package/docs/components/form/checkbox-group-field.md +54 -0
  42. package/docs/components/form/color-field.md +64 -0
  43. package/docs/components/form/date-field.md +92 -0
  44. package/docs/components/form/field-collection.md +63 -0
  45. package/docs/components/form/file-field.md +203 -0
  46. package/docs/components/form/form-control.md +87 -0
  47. package/docs/components/form/image-field.md +90 -0
  48. package/docs/components/form/index.md +115 -0
  49. package/docs/components/form/number-field.md +65 -0
  50. package/docs/components/form/radio-field.md +51 -0
  51. package/docs/components/form/select-field.md +123 -0
  52. package/docs/components/form/slider.md +136 -0
  53. package/docs/components/form/string-field.md +134 -0
  54. package/docs/components/form/textarea-field.md +65 -0
  55. package/docs/components/form-fields.md +372 -0
  56. package/docs/components/getting-started.md +264 -0
  57. package/docs/components/icons.md +321 -0
  58. package/docs/components/index.md +337 -0
  59. package/docs/components/layout.md +279 -0
  60. package/docs/components/list.md +73 -0
  61. package/docs/components/menu.md +215 -0
  62. package/docs/components/modal.md +156 -0
  63. package/docs/components/pagination.md +95 -0
  64. package/docs/components/popover.md +131 -0
  65. package/docs/components/progress.md +111 -0
  66. package/docs/components/shortcut-manager.md +221 -0
  67. package/docs/components/simple-table.md +107 -0
  68. package/docs/components/skeleton.md +155 -0
  69. package/docs/components/spinner.md +100 -0
  70. package/docs/components/splitter.md +133 -0
  71. package/docs/components/stepper.md +163 -0
  72. package/docs/components/switch.md +113 -0
  73. package/docs/components/tabs.md +153 -0
  74. package/docs/components/toast.md +119 -0
  75. package/docs/components/tooltip.md +151 -0
  76. package/docs/components/traits.md +261 -0
  77. package/docs/conditional-rendering.md +177 -502
  78. package/docs/contributing.md +300 -25
  79. package/docs/core-concepts.md +207 -366
  80. package/docs/elements.md +266 -254
  81. package/docs/extending-native-document-element.md +259 -0
  82. package/docs/filters.md +247 -0
  83. package/docs/getting-started.md +195 -257
  84. package/docs/i18n.md +241 -0
  85. package/docs/index.md +76 -0
  86. package/docs/lifecycle-events.md +146 -67
  87. package/docs/list-rendering.md +240 -460
  88. package/docs/memory-management.md +135 -46
  89. package/docs/native-document-element.md +487 -0
  90. package/docs/native-fetch.md +213 -0
  91. package/docs/observable-resource.md +364 -0
  92. package/docs/observables.md +690 -357
  93. package/docs/routing.md +246 -646
  94. package/docs/state-management.md +213 -306
  95. package/docs/svg-elements.md +231 -0
  96. package/docs/theming.md +409 -0
  97. package/docs/tutorials/.gitkeep +0 -0
  98. package/docs/validation.md +98 -91
  99. package/docs/vitepress-conventions.md +219 -0
  100. package/elements.d.ts +7 -0
  101. package/elements.js +3 -4
  102. package/eslint.config.js +35 -0
  103. package/i18n.js +1 -0
  104. package/i18n.ts +2 -0
  105. package/index.d.ts +21 -0
  106. package/index.def.js +1086 -0
  107. package/index.js +19 -13
  108. package/package.json +65 -8
  109. package/readme.md +296 -93
  110. package/rollup.config.js +52 -3
  111. package/router.d.ts +7 -0
  112. package/router.js +0 -0
  113. package/src/components/$traits/has-draggable/HasDraggable.d.ts +4 -0
  114. package/src/components/$traits/has-draggable/HasDraggable.js +82 -0
  115. package/src/components/$traits/has-draggable/has-draggable.css +8 -0
  116. package/src/components/$traits/has-items/HasItems.d.ts +9 -0
  117. package/src/components/$traits/has-items/HasItems.js +64 -0
  118. package/src/components/$traits/has-position/HasFullPosition.d.ts +14 -0
  119. package/src/components/$traits/has-position/HasFullPosition.js +95 -0
  120. package/src/components/$traits/has-position/HasPosition.d.ts +7 -0
  121. package/src/components/$traits/has-position/HasPosition.js +45 -0
  122. package/src/components/$traits/has-resizable/HasResizable.d.ts +13 -0
  123. package/src/components/$traits/has-resizable/HasResizable.js +122 -0
  124. package/src/components/$traits/has-resizable/has-resizable.css +121 -0
  125. package/src/components/$traits/has-validation/HasValidation.d.ts +17 -0
  126. package/src/components/$traits/has-validation/HasValidation.js +133 -0
  127. package/src/components/BaseComponent.d.ts +32 -0
  128. package/src/components/BaseComponent.js +289 -0
  129. package/src/components/accordion/Accordion.js +269 -0
  130. package/src/components/accordion/AccordionItem.js +234 -0
  131. package/src/components/accordion/index.js +7 -0
  132. package/src/components/accordion/types/Accordion.d.ts +47 -0
  133. package/src/components/accordion/types/AccordionItem.d.ts +48 -0
  134. package/src/components/alert/Alert.js +354 -0
  135. package/src/components/alert/index.js +6 -0
  136. package/src/components/alert/types/Alert.d.ts +62 -0
  137. package/src/components/avatar/Avatar.js +431 -0
  138. package/src/components/avatar/AvatarGroup.js +98 -0
  139. package/src/components/avatar/index.js +7 -0
  140. package/src/components/avatar/types/Avatar.d.ts +74 -0
  141. package/src/components/avatar/types/AvatarGroup.d.ts +32 -0
  142. package/src/components/badge/Badge.js +246 -0
  143. package/src/components/badge/index.js +6 -0
  144. package/src/components/badge/types/Badge.d.ts +51 -0
  145. package/src/components/base-component.css +0 -0
  146. package/src/components/breadcrumb/BreadCrumb.js +142 -0
  147. package/src/components/breadcrumb/index.js +5 -0
  148. package/src/components/breadcrumb/types/BreadCrumb.d.ts +42 -0
  149. package/src/components/button/Button.js +321 -0
  150. package/src/components/button/index.js +5 -0
  151. package/src/components/button/types/Button.d.ts +62 -0
  152. package/src/components/card/Card.js +283 -0
  153. package/src/components/card/index.js +5 -0
  154. package/src/components/card/types/Card.d.ts +42 -0
  155. package/src/components/context-menu/ContextMenu.js +129 -0
  156. package/src/components/context-menu/ContextMenuGroup.js +31 -0
  157. package/src/components/context-menu/ContextMenuItem.js +30 -0
  158. package/src/components/context-menu/index.js +10 -0
  159. package/src/components/context-menu/types/ContextMenu.d.ts +30 -0
  160. package/src/components/context-menu/types/ContextMenuGroup.d.ts +18 -0
  161. package/src/components/context-menu/types/ContextMenuItem.d.ts +18 -0
  162. package/src/components/divider/Divider.js +258 -0
  163. package/src/components/divider/index.js +6 -0
  164. package/src/components/divider/types/Divider.d.ts +55 -0
  165. package/src/components/dropdown/Dropdown.js +532 -0
  166. package/src/components/dropdown/DropdownDivider.js +46 -0
  167. package/src/components/dropdown/DropdownGroup.js +84 -0
  168. package/src/components/dropdown/DropdownItem.js +151 -0
  169. package/src/components/dropdown/DropdownTrigger.js +94 -0
  170. package/src/components/dropdown/helpers.js +53 -0
  171. package/src/components/dropdown/index.js +13 -0
  172. package/src/components/dropdown/types/Dropdown.d.ts +88 -0
  173. package/src/components/dropdown/types/DropdownDivider.d.ts +20 -0
  174. package/src/components/dropdown/types/DropdownGroup.d.ts +25 -0
  175. package/src/components/dropdown/types/DropdownItem.d.ts +41 -0
  176. package/src/components/dropdown/types/DropdownTrigger.d.ts +32 -0
  177. package/src/components/form/FormControl.js +499 -0
  178. package/src/components/form/field/Field.js +420 -0
  179. package/src/components/form/field/FieldCollection.js +292 -0
  180. package/src/components/form/field/types/AutocompleteField.js +168 -0
  181. package/src/components/form/field/types/CheckboxField.js +77 -0
  182. package/src/components/form/field/types/CheckboxGroupField.js +171 -0
  183. package/src/components/form/field/types/ColorField.js +102 -0
  184. package/src/components/form/field/types/DateField.js +315 -0
  185. package/src/components/form/field/types/EmailField.js +104 -0
  186. package/src/components/form/field/types/FileField.js +276 -0
  187. package/src/components/form/field/types/HiddenField.js +44 -0
  188. package/src/components/form/field/types/ImageField.js +138 -0
  189. package/src/components/form/field/types/NumberField.js +177 -0
  190. package/src/components/form/field/types/PasswordField.js +200 -0
  191. package/src/components/form/field/types/RadioField.js +145 -0
  192. package/src/components/form/field/types/RangeField.js +117 -0
  193. package/src/components/form/field/types/SearchField.js +66 -0
  194. package/src/components/form/field/types/SelectField.js +247 -0
  195. package/src/components/form/field/types/StringField.js +148 -0
  196. package/src/components/form/field/types/TelField.js +98 -0
  197. package/src/components/form/field/types/TextAreaField.js +142 -0
  198. package/src/components/form/field/types/TimeField.js +215 -0
  199. package/src/components/form/field/types/UrlField.js +115 -0
  200. package/src/components/form/field/types/file-field-mode/FileAvatarMode.js +183 -0
  201. package/src/components/form/field/types/file-field-mode/FileDropzoneMode.js +117 -0
  202. package/src/components/form/field/types/file-field-mode/FileItemPreview.js +150 -0
  203. package/src/components/form/field/types/file-field-mode/FileNativeMode.js +43 -0
  204. package/src/components/form/field/types/file-field-mode/FileUploadButtonMode.js +120 -0
  205. package/src/components/form/field/types/file-field-mode/FileWallMode.js +106 -0
  206. package/src/components/form/index.js +61 -0
  207. package/src/components/form/merge +0 -0
  208. package/src/components/form/types/Field.d.ts +73 -0
  209. package/src/components/form/types/FieldCollection.d.ts +53 -0
  210. package/src/components/form/types/FormControl.d.ts +64 -0
  211. package/src/components/form/types/fields/AutocompleteField.d.ts +48 -0
  212. package/src/components/form/types/fields/CheckboxField.d.ts +33 -0
  213. package/src/components/form/types/fields/CheckboxGroupField.d.ts +49 -0
  214. package/src/components/form/types/fields/ColorField.d.ts +37 -0
  215. package/src/components/form/types/fields/DateField.d.ts +70 -0
  216. package/src/components/form/types/fields/EmailField.d.ts +35 -0
  217. package/src/components/form/types/fields/FileAvatarMode.d.ts +46 -0
  218. package/src/components/form/types/fields/FileDropzoneMode.d.ts +28 -0
  219. package/src/components/form/types/fields/FileField.d.ts +56 -0
  220. package/src/components/form/types/fields/FileItemPreview.d.ts +35 -0
  221. package/src/components/form/types/fields/FileNativeMode.d.ts +21 -0
  222. package/src/components/form/types/fields/FileUploadButtonMode.d.ts +34 -0
  223. package/src/components/form/types/fields/FileWallMode.d.ts +32 -0
  224. package/src/components/form/types/fields/HiddenField.d.ts +26 -0
  225. package/src/components/form/types/fields/ImageField.d.ts +45 -0
  226. package/src/components/form/types/fields/NumberField.d.ts +48 -0
  227. package/src/components/form/types/fields/PasswordField.d.ts +46 -0
  228. package/src/components/form/types/fields/RadioField.d.ts +48 -0
  229. package/src/components/form/types/fields/RangeField.d.ts +44 -0
  230. package/src/components/form/types/fields/SearchField.d.ts +34 -0
  231. package/src/components/form/types/fields/SelectField.d.ts +71 -0
  232. package/src/components/form/types/fields/StringField.d.ts +48 -0
  233. package/src/components/form/types/fields/TelField.d.ts +37 -0
  234. package/src/components/form/types/fields/TextAreaField.d.ts +44 -0
  235. package/src/components/form/types/fields/TimeField.d.ts +51 -0
  236. package/src/components/form/types/fields/UrlField.d.ts +35 -0
  237. package/src/components/form/utils.js +17 -0
  238. package/src/components/form/validation/Validation.js +565 -0
  239. package/src/components/icon/Icon.js +108 -0
  240. package/src/components/icon/icon-getters.js +142 -0
  241. package/src/components/icon/icons.js +171 -0
  242. package/src/components/icon/index.js +17 -0
  243. package/src/components/icon/types/Icon.d.ts +191 -0
  244. package/src/components/index.d.ts +165 -0
  245. package/src/components/list/HasListItem.js +171 -0
  246. package/src/components/list/List.js +125 -0
  247. package/src/components/list/ListDivider.js +39 -0
  248. package/src/components/list/ListGroup.js +135 -0
  249. package/src/components/list/ListItem.js +213 -0
  250. package/src/components/list/index.js +12 -0
  251. package/src/components/list/types/List.d.ts +56 -0
  252. package/src/components/list/types/ListDivider.ts +16 -0
  253. package/src/components/list/types/ListGroup.d.ts +59 -0
  254. package/src/components/list/types/ListItem.d.ts +52 -0
  255. package/src/components/menu/HasMenuItem.js +182 -0
  256. package/src/components/menu/Menu.js +230 -0
  257. package/src/components/menu/MenuDivider.js +38 -0
  258. package/src/components/menu/MenuGroup.js +127 -0
  259. package/src/components/menu/MenuItem.js +191 -0
  260. package/src/components/menu/MenuLink.js +52 -0
  261. package/src/components/menu/index.js +14 -0
  262. package/src/components/menu/types/Menu.d.ts +60 -0
  263. package/src/components/menu/types/MenuDivider.d.ts +19 -0
  264. package/src/components/menu/types/MenuGroup.d.ts +44 -0
  265. package/src/components/menu/types/MenuItem.d.ts +46 -0
  266. package/src/components/menu/types/MenuLink.d.ts +16 -0
  267. package/src/components/modal/Modal.js +528 -0
  268. package/src/components/modal/index.js +5 -0
  269. package/src/components/modal/types/Modal.d.ts +94 -0
  270. package/src/components/pagination/Pagination.js +412 -0
  271. package/src/components/pagination/index.js +5 -0
  272. package/src/components/pagination/types/Pagination.d.ts +68 -0
  273. package/src/components/popover/Popover.js +460 -0
  274. package/src/components/popover/PopoverFooter.js +62 -0
  275. package/src/components/popover/PopoverHeader.js +69 -0
  276. package/src/components/popover/index.js +10 -0
  277. package/src/components/popover/types/Popover.d.ts +83 -0
  278. package/src/components/popover/types/PopoverFooter.d.ts +24 -0
  279. package/src/components/popover/types/PopoverHeader.d.ts +26 -0
  280. package/src/components/progress/Progress.js +406 -0
  281. package/src/components/progress/index.js +6 -0
  282. package/src/components/progress/types/Progress.d.ts +77 -0
  283. package/src/components/skeleton/Skeleton.js +232 -0
  284. package/src/components/skeleton/index.js +6 -0
  285. package/src/components/skeleton/types/Skeleton.d.ts +55 -0
  286. package/src/components/slider/Slider.js +407 -0
  287. package/src/components/slider/index.js +5 -0
  288. package/src/components/slider/types/Slider.d.ts +82 -0
  289. package/src/components/spacer/Spacer.js +28 -0
  290. package/src/components/spacer/index.js +5 -0
  291. package/src/components/spacer/types/Spacer.d.ts +19 -0
  292. package/src/components/spinner/Spinner.js +351 -0
  293. package/src/components/spinner/index.js +5 -0
  294. package/src/components/spinner/types/Spinner.d.ts +71 -0
  295. package/src/components/splitter/Splitter.js +165 -0
  296. package/src/components/splitter/SplitterGutter.js +146 -0
  297. package/src/components/splitter/SplitterPanel.js +144 -0
  298. package/src/components/splitter/index.js +10 -0
  299. package/src/components/splitter/types/Splitter.d.ts +38 -0
  300. package/src/components/splitter/types/SplitterGutter.d.ts +38 -0
  301. package/src/components/splitter/types/SplitterPanel.d.ts +41 -0
  302. package/src/components/stacks/AbsoluteStack.js +54 -0
  303. package/src/components/stacks/FixedStack.js +54 -0
  304. package/src/components/stacks/HStack.js +55 -0
  305. package/src/components/stacks/PositionStack.js +255 -0
  306. package/src/components/stacks/RelativeStack.js +54 -0
  307. package/src/components/stacks/Stack.js +167 -0
  308. package/src/components/stacks/VStack.js +56 -0
  309. package/src/components/stacks/index.js +21 -0
  310. package/src/components/stacks/types/AbsoluteStack.d.ts +16 -0
  311. package/src/components/stacks/types/FixedStack.d.ts +16 -0
  312. package/src/components/stacks/types/HStack.d.ts +16 -0
  313. package/src/components/stacks/types/PositionStack.d.ts +54 -0
  314. package/src/components/stacks/types/RelativeStack.d.ts +17 -0
  315. package/src/components/stacks/types/Stack.d.ts +39 -0
  316. package/src/components/stacks/types/VStack.d.ts +16 -0
  317. package/src/components/stepper/Stepper.js +462 -0
  318. package/src/components/stepper/StepperStep.js +242 -0
  319. package/src/components/stepper/index.js +8 -0
  320. package/src/components/stepper/types/Stepper.d.ts +68 -0
  321. package/src/components/stepper/types/StepperStep.d.ts +54 -0
  322. package/src/components/switch/Switch.js +267 -0
  323. package/src/components/switch/index.js +6 -0
  324. package/src/components/switch/types/Switch.d.ts +55 -0
  325. package/src/components/table/Column.js +212 -0
  326. package/src/components/table/ColumnGroup.js +90 -0
  327. package/src/components/table/DataTable.js +721 -0
  328. package/src/components/table/SimpleTable.js +140 -0
  329. package/src/components/table/index.js +7 -0
  330. package/src/components/table/types/Column.d.ts +49 -0
  331. package/src/components/table/types/ColumnGroup.d.ts +28 -0
  332. package/src/components/table/types/DataTable.d.ts +97 -0
  333. package/src/components/table/types/SimpleTable.d.ts +40 -0
  334. package/src/components/tabs/Tabs.js +396 -0
  335. package/src/components/tabs/index.js +6 -0
  336. package/src/components/tabs/types/Tabs.d.ts +78 -0
  337. package/src/components/toast/Toast.js +263 -0
  338. package/src/components/toast/ToastError.js +0 -0
  339. package/src/components/toast/ToastInfo.js +0 -0
  340. package/src/components/toast/ToastSuccess.js +0 -0
  341. package/src/components/toast/ToastWarning.js +0 -0
  342. package/src/components/toast/index.js +5 -0
  343. package/src/components/toast/types/Toast.d.ts +57 -0
  344. package/src/components/toast/types/ToastError.d.ts +7 -0
  345. package/src/components/toast/types/ToastInfo.d.ts +7 -0
  346. package/src/components/toast/types/ToastSuccess.d.ts +7 -0
  347. package/src/components/toast/types/ToastWarning.d.ts +7 -0
  348. package/src/components/tooltip/Tooltip.js +360 -0
  349. package/src/components/tooltip/index.js +5 -0
  350. package/src/components/tooltip/prototypes.js +6 -0
  351. package/src/components/tooltip/types/Tooltip.d.ts +65 -0
  352. package/src/{data → core/data}/MemoryManager.js +2 -3
  353. package/src/core/data/Observable.js +227 -0
  354. package/src/core/data/ObservableArray.js +522 -0
  355. package/src/core/data/ObservableChecker.js +39 -0
  356. package/src/core/data/ObservableItem.js +611 -0
  357. package/src/core/data/ObservableObject.js +274 -0
  358. package/src/core/data/ObservableResource.js +315 -0
  359. package/src/core/data/ObservableWhen.js +54 -0
  360. package/src/core/data/Store.js +520 -0
  361. package/src/core/data/observable-helpers/observable.is-to.js +390 -0
  362. package/src/core/data/observable-helpers/observable.prototypes.js +145 -0
  363. package/src/core/elements/anchor/anchor-with-sentinel.js +66 -0
  364. package/src/core/elements/anchor/anchor.js +210 -0
  365. package/src/core/elements/anchor/one-child-anchor-overwriting.js +66 -0
  366. package/src/core/elements/content-formatter.js +183 -0
  367. package/src/core/elements/control/for-each-array.js +292 -0
  368. package/src/{elements → core/elements}/control/for-each.js +42 -23
  369. package/src/core/elements/control/show-if.js +94 -0
  370. package/src/core/elements/control/show-when.js +54 -0
  371. package/src/core/elements/control/switch.js +141 -0
  372. package/src/core/elements/description-list.js +19 -0
  373. package/src/core/elements/form.js +255 -0
  374. package/src/core/elements/fragment.js +8 -0
  375. package/src/core/elements/html5-semantics.js +55 -0
  376. package/src/core/elements/img.js +59 -0
  377. package/src/{elements → core/elements}/index.js +4 -4
  378. package/src/core/elements/interactive.js +25 -0
  379. package/src/core/elements/list.js +37 -0
  380. package/src/core/elements/medias.js +37 -0
  381. package/src/core/elements/meta-data.js +43 -0
  382. package/src/core/elements/svg.js +61 -0
  383. package/src/core/elements/table.js +73 -0
  384. package/src/{errors → core/errors}/ArgTypesError.js +1 -1
  385. package/src/{errors → core/errors}/NativeDocumentError.js +0 -0
  386. package/src/core/utils/HasEventEmitter.js +85 -0
  387. package/src/core/utils/args-types.js +140 -0
  388. package/src/core/utils/cache.js +5 -0
  389. package/src/core/utils/callback-handler.js +50 -0
  390. package/src/core/utils/debug-manager.js +40 -0
  391. package/src/core/utils/events.js +148 -0
  392. package/src/core/utils/filters/date.js +178 -0
  393. package/src/core/utils/filters/index.js +4 -0
  394. package/src/core/utils/filters/standard.js +263 -0
  395. package/src/core/utils/filters/strings.js +67 -0
  396. package/src/core/utils/filters/utils.js +77 -0
  397. package/src/core/utils/formatters.js +90 -0
  398. package/src/core/utils/helpers.js +144 -0
  399. package/src/core/utils/localstorage.js +57 -0
  400. package/src/core/utils/memoize.js +115 -0
  401. package/src/core/utils/plugins-manager.js +81 -0
  402. package/src/core/utils/property-accumulator.js +72 -0
  403. package/src/core/utils/prototypes.js +44 -0
  404. package/src/core/utils/shortcut-manager.js +242 -0
  405. package/src/{utils → core/utils}/validator.js +58 -22
  406. package/src/core/wrappers/AttributesWrapper.js +196 -0
  407. package/src/core/wrappers/DocumentObserver.js +182 -0
  408. package/src/core/wrappers/ElementCreator.js +117 -0
  409. package/src/core/wrappers/HtmlElementWrapper.js +117 -0
  410. package/src/core/wrappers/NDElement.js +635 -0
  411. package/src/core/wrappers/NdPrototype.js +233 -0
  412. package/src/core/wrappers/SingletonView.js +99 -0
  413. package/src/core/wrappers/SvgElementWrapper.js +15 -0
  414. package/src/core/wrappers/TemplateBinding.js +7 -0
  415. package/src/core/wrappers/constants.js +66 -0
  416. package/src/core/wrappers/prototypes/attributes-extensions.js +24 -0
  417. package/src/core/wrappers/prototypes/bind-class-extensions.js +0 -0
  418. package/src/core/wrappers/prototypes/nd-element-extensions.js +125 -0
  419. package/src/core/wrappers/prototypes/nd-element.transition.extensions.js +127 -0
  420. package/src/core/wrappers/template-cloner/NodeCloner.js +209 -0
  421. package/src/core/wrappers/template-cloner/TemplateCloner.js +192 -0
  422. package/src/core/wrappers/template-cloner/attributes-hydrator.js +142 -0
  423. package/src/core/wrappers/template-cloner/utils.js +173 -0
  424. package/src/fetch/NativeFetch.js +89 -0
  425. package/src/i18n/bin/scan.js +132 -0
  426. package/src/i18n/index.d.ts +2 -0
  427. package/src/i18n/service/I18nService.d.ts +27 -0
  428. package/src/i18n/service/I18nService.js +46 -0
  429. package/src/i18n/service/functions.d.ts +22 -0
  430. package/src/i18n/service/functions.js +29 -0
  431. package/src/router/Route.js +33 -8
  432. package/src/router/RouteGroupHelper.js +10 -2
  433. package/src/router/Router.js +63 -22
  434. package/src/router/RouterComponent.js +114 -6
  435. package/src/{errors → router/errors}/RouterError.js +0 -1
  436. package/src/router/link.js +8 -9
  437. package/src/router/modes/HashRouter.js +2 -2
  438. package/src/router/modes/HistoryRouter.js +2 -3
  439. package/src/router/modes/MemoryRouter.js +1 -1
  440. package/src/ui/components/accordion/AccordionItemRender.js +85 -0
  441. package/src/ui/components/accordion/AccordionRender.js +35 -0
  442. package/src/ui/components/accordion/accordion.css +121 -0
  443. package/src/ui/components/alert/AlertRender.js +87 -0
  444. package/src/ui/components/alert/alert.css +163 -0
  445. package/src/ui/components/avatar/avata-group/AvatarGroupRender.js +50 -0
  446. package/src/ui/components/avatar/avata-group/avatar-group.css +38 -0
  447. package/src/ui/components/avatar/avatar/AvatarRender.js +87 -0
  448. package/src/ui/components/avatar/avatar/avatar.css +189 -0
  449. package/src/ui/components/badge/BadgeRender.js +25 -0
  450. package/src/ui/components/badge/badge.css +168 -0
  451. package/src/ui/components/breadcrumb/BreadcrumbRender.js +52 -0
  452. package/src/ui/components/breadcrumb/breadcrumb.css +55 -0
  453. package/src/ui/components/button/ButtonRender.js +68 -0
  454. package/src/ui/components/button/button.css +296 -0
  455. package/src/ui/components/card/CardRender.js +133 -0
  456. package/src/ui/components/card/card.css +169 -0
  457. package/src/ui/components/contextmenu/ContextmenuRender.js +70 -0
  458. package/src/ui/components/contextmenu/contextmenu.css +36 -0
  459. package/src/ui/components/divider/DividerRender.js +70 -0
  460. package/src/ui/components/divider/divider.css +70 -0
  461. package/src/ui/components/dropdown/DropdownRender.js +95 -0
  462. package/src/ui/components/dropdown/divider/DropdownDividerRender.js +9 -0
  463. package/src/ui/components/dropdown/divider/dropdown-divider.css +0 -0
  464. package/src/ui/components/dropdown/dropdown.css +179 -0
  465. package/src/ui/components/dropdown/group/DropdownGroupRender.js +23 -0
  466. package/src/ui/components/dropdown/group/dropdown-group.css +0 -0
  467. package/src/ui/components/dropdown/item/DropdownItemRender.js +34 -0
  468. package/src/ui/components/dropdown/item/dropdown-item.css +0 -0
  469. package/src/ui/components/form/FieldCollectionRender.js +114 -0
  470. package/src/ui/components/form/FormControlRender.js +85 -0
  471. package/src/ui/components/form/field-collection.css +55 -0
  472. package/src/ui/components/form/fields/AutocompleteFieldRender.js +143 -0
  473. package/src/ui/components/form/fields/CheckboxFieldRender.js +63 -0
  474. package/src/ui/components/form/fields/CheckboxGroupFieldRender.js +96 -0
  475. package/src/ui/components/form/fields/ColorFieldRender.js +30 -0
  476. package/src/ui/components/form/fields/DateFieldRender.js +155 -0
  477. package/src/ui/components/form/fields/EmailFieldRender.js +5 -0
  478. package/src/ui/components/form/fields/FieldRender.js +118 -0
  479. package/src/ui/components/form/fields/FileFieldRender.js +41 -0
  480. package/src/ui/components/form/fields/HiddenFieldRender.js +13 -0
  481. package/src/ui/components/form/fields/ImageFieldRender.js +0 -0
  482. package/src/ui/components/form/fields/NumberFieldRender.js +52 -0
  483. package/src/ui/components/form/fields/PasswordFieldRender.js +65 -0
  484. package/src/ui/components/form/fields/RadioFieldRender.js +81 -0
  485. package/src/ui/components/form/fields/RangeFieldRender.js +126 -0
  486. package/src/ui/components/form/fields/SelectFieldRender.js +253 -0
  487. package/src/ui/components/form/fields/SliderFieldRender.js +362 -0
  488. package/src/ui/components/form/fields/StringFieldRender.js +6 -0
  489. package/src/ui/components/form/fields/TelFieldRender.js +6 -0
  490. package/src/ui/components/form/fields/TextAreaFieldRender.js +96 -0
  491. package/src/ui/components/form/fields/TimeFieldRender.js +142 -0
  492. package/src/ui/components/form/fields/UrlFieldRender.js +6 -0
  493. package/src/ui/components/form/fields/date-field.css +32 -0
  494. package/src/ui/components/form/fields/field.css +402 -0
  495. package/src/ui/components/form/fields/file-field.css +79 -0
  496. package/src/ui/components/form/fields/password-field.css +50 -0
  497. package/src/ui/components/form/fields/range-field.css +120 -0
  498. package/src/ui/components/form/fields/slider.css +195 -0
  499. package/src/ui/components/form/file-upload-mode/FileAvatarModeRender.js +143 -0
  500. package/src/ui/components/form/file-upload-mode/FileDropzoneModeRender.js +108 -0
  501. package/src/ui/components/form/file-upload-mode/FileNativeModeRender.js +22 -0
  502. package/src/ui/components/form/file-upload-mode/FileUploadButtonModeRender.js +89 -0
  503. package/src/ui/components/form/file-upload-mode/FileWallModeRender.js +90 -0
  504. package/src/ui/components/form/file-upload-mode/file-avatar-mode.css +139 -0
  505. package/src/ui/components/form/file-upload-mode/file-dropzone-mode.css +88 -0
  506. package/src/ui/components/form/file-upload-mode/file-upload-button-mode.css +44 -0
  507. package/src/ui/components/form/file-upload-mode/file-wall-mode.css +88 -0
  508. package/src/ui/components/form/form-control.css +40 -0
  509. package/src/ui/components/form/helpers.js +111 -0
  510. package/src/ui/components/form/index.js +27 -0
  511. package/src/ui/components/icon/material/MaterialIconRender.js +71 -0
  512. package/src/ui/components/icon/material/material.css +15 -0
  513. package/src/ui/components/icon/material/material.map.js +170 -0
  514. package/src/ui/components/icon/phosphor/PhosphorIconRender.js +71 -0
  515. package/src/ui/components/icon/phosphor/phosphor.css +17 -0
  516. package/src/ui/components/icon/phosphor/phosphor.map.js +165 -0
  517. package/src/ui/components/icon/tabler/TablerIconRender.js +58 -0
  518. package/src/ui/components/icon/tabler/tabler.css +14 -0
  519. package/src/ui/components/icon/tabler/tabler.map.js +165 -0
  520. package/src/ui/components/list/ListRender.js +18 -0
  521. package/src/ui/components/list/divider/ListDividerRender.js +10 -0
  522. package/src/ui/components/list/divider/list-divider.css +12 -0
  523. package/src/ui/components/list/group/ListGroupRender.js +61 -0
  524. package/src/ui/components/list/group/list-group.css +62 -0
  525. package/src/ui/components/list/item/ListItemRender.js +242 -0
  526. package/src/ui/components/list/item/list-item.css +191 -0
  527. package/src/ui/components/list/list.css +24 -0
  528. package/src/ui/components/menu/MenuDividerRender.js +12 -0
  529. package/src/ui/components/menu/MenuGroupRender.js +59 -0
  530. package/src/ui/components/menu/MenuItemRender.js +65 -0
  531. package/src/ui/components/menu/MenuLinkRender.js +66 -0
  532. package/src/ui/components/menu/MenuRender.js +27 -0
  533. package/src/ui/components/menu/helpers.js +122 -0
  534. package/src/ui/components/menu/menu.css +308 -0
  535. package/src/ui/components/modal/ModalRender.js +124 -0
  536. package/src/ui/components/modal/modal.css +156 -0
  537. package/src/ui/components/pagination/PaginationRender.js +112 -0
  538. package/src/ui/components/pagination/pagination.css +63 -0
  539. package/src/ui/components/popover/PopoverRender.js +233 -0
  540. package/src/ui/components/popover/popover.css +139 -0
  541. package/src/ui/components/progress/ProgressRender.js +177 -0
  542. package/src/ui/components/progress/progress.css +197 -0
  543. package/src/ui/components/skeleton/SkeletonRender.js +138 -0
  544. package/src/ui/components/skeleton/skeleton.css +154 -0
  545. package/src/ui/components/spacer/SpacerRender.js +10 -0
  546. package/src/ui/components/spinner/SpinnerRender.js +50 -0
  547. package/src/ui/components/spinner/spinner.css +152 -0
  548. package/src/ui/components/splitter/SplitterGutterRender.js +98 -0
  549. package/src/ui/components/splitter/SplitterPanelRender.js +42 -0
  550. package/src/ui/components/splitter/SplitterRender.js +77 -0
  551. package/src/ui/components/splitter/splitter.css +128 -0
  552. package/src/ui/components/stacks/PositionStackRender.js +39 -0
  553. package/src/ui/components/stacks/StackRender.js +41 -0
  554. package/src/ui/components/stacks/absolute-stack/AbsoluteStackRender.js +5 -0
  555. package/src/ui/components/stacks/fixed-stack/FixedStackRender.js +5 -0
  556. package/src/ui/components/stacks/h-stack/HStackRender.js +7 -0
  557. package/src/ui/components/stacks/h-stack/h-stack.css +4 -0
  558. package/src/ui/components/stacks/index.js +5 -0
  559. package/src/ui/components/stacks/position-stack.css +62 -0
  560. package/src/ui/components/stacks/relative-stack/RelativeStackRender.js +7 -0
  561. package/src/ui/components/stacks/relative-stack/relative-stack.css +3 -0
  562. package/src/ui/components/stacks/stack.css +78 -0
  563. package/src/ui/components/stacks/v-stack/VStackRender.js +6 -0
  564. package/src/ui/components/stacks/v-stack/v-stack.css +4 -0
  565. package/src/ui/components/stepper/StepperRender.js +72 -0
  566. package/src/ui/components/stepper/StepperStepRender.js +74 -0
  567. package/src/ui/components/stepper/stepper.css +359 -0
  568. package/src/ui/components/switch/SwitchRender.js +86 -0
  569. package/src/ui/components/switch/switch.css +143 -0
  570. package/src/ui/components/table/data-table/DataTableRender.js +54 -0
  571. package/src/ui/components/table/data-table/bulk-actions.js +34 -0
  572. package/src/ui/components/table/data-table/data-table.css +246 -0
  573. package/src/ui/components/table/data-table/pagination.js +56 -0
  574. package/src/ui/components/table/data-table/tables.js +368 -0
  575. package/src/ui/components/table/data-table/toolbar.js +67 -0
  576. package/src/ui/components/table/simple-table/SimpleTableRender.js +205 -0
  577. package/src/ui/components/table/simple-table/simple-table.css +50 -0
  578. package/src/ui/components/tabs/TabsRender.js +226 -0
  579. package/src/ui/components/tabs/tabs.css +253 -0
  580. package/src/ui/components/toast/ToastRender.js +103 -0
  581. package/src/ui/components/toast/toast.css +201 -0
  582. package/src/ui/components/tooltip/TooltipRender.js +8 -0
  583. package/src/ui/components/tooltip/tooltip.css +113 -0
  584. package/src/ui/index.js +52 -0
  585. package/src/ui/theme.js +0 -0
  586. package/src/ui/theme.scss +1 -0
  587. package/src/ui/tokens/animation.scss +36 -0
  588. package/src/ui/tokens/colors-dark.scss +58 -0
  589. package/src/ui/tokens/colors.scss +54 -0
  590. package/src/ui/tokens/components.scss +32 -0
  591. package/src/ui/tokens/fonts.scss +57 -0
  592. package/src/ui/tokens/glass.scss +10 -0
  593. package/src/ui/tokens/index.scss +38 -0
  594. package/src/ui/tokens/layouts.scss +228 -0
  595. package/src/ui/tokens/opacity.scss +21 -0
  596. package/src/ui/tokens/others.scss +11 -0
  597. package/src/ui/tokens/radius.scss +6 -0
  598. package/src/ui/tokens/reset.scss +51 -0
  599. package/src/ui/tokens/shadows.scss +29 -0
  600. package/src/ui/tokens/spacings.scss +13 -0
  601. package/src/ui/tokens/vars.scss +35 -0
  602. package/src/ui/tokens/viewports.scss +30 -0
  603. package/src/ui/utils/aria.js +19 -0
  604. package/tests/integration/ui/attributes-wrapper.test.js +177 -0
  605. package/tests/integration/ui/for-each-array.test.js +167 -0
  606. package/tests/integration/ui/lifecycle.test.js +146 -0
  607. package/tests/integration/ui/show-if.test.js +168 -0
  608. package/tests/unit/core/observable-array.test.js +404 -0
  609. package/tests/unit/core/observable-item.test.js +428 -0
  610. package/tests/unit/core/observable-object.test.js +239 -0
  611. package/tests/unit/core/observable-resource.test.js +323 -0
  612. package/tests/unit/core/store.test.js +347 -0
  613. package/tests/unit/router/route-matching.test.js +169 -0
  614. package/tests/unit/router/router-guards.test.js +189 -0
  615. package/tests/unit/utils/cache.test.js +120 -0
  616. package/tests/unit/utils/filters.test.js +394 -0
  617. package/types/args-types.d.ts +58 -0
  618. package/types/control-flow.d.ts +62 -0
  619. package/types/elements.d.ts +231 -0
  620. package/types/filters/dates.d.ts +43 -0
  621. package/types/filters/index.d.ts +4 -0
  622. package/types/filters/standard.d.ts +70 -0
  623. package/types/filters/strings.d.ts +21 -0
  624. package/types/filters/types.d.ts +20 -0
  625. package/types/forms.d.ts +84 -0
  626. package/types/globals.d.ts +543 -0
  627. package/types/images.d.ts +23 -0
  628. package/types/localStorage.ts +102 -0
  629. package/types/memoize.d.ts +26 -0
  630. package/types/native-fetch.d.ts +72 -0
  631. package/types/nd-element.d.ts +407 -0
  632. package/types/observable-resource.d.ts +3 -0
  633. package/types/observable.d.ts +227 -0
  634. package/types/plugins-manager.d.ts +65 -0
  635. package/types/polyfill.d.ts +18 -0
  636. package/types/property-accumulator.d.ts +33 -0
  637. package/types/router.d.ts +85 -0
  638. package/types/service.d.ts +23 -0
  639. package/types/singleton.d.ts +19 -0
  640. package/types/store.d.ts +63 -0
  641. package/types/template-cloner.ts +43 -0
  642. package/types/validator.ts +66 -0
  643. package/ui.js +1 -0
  644. package/utils.d.ts +4 -0
  645. package/utils.js +12 -0
  646. package/vitest.config.js +15 -0
  647. package/src/data/Observable.js +0 -55
  648. package/src/data/ObservableChecker.js +0 -39
  649. package/src/data/ObservableItem.js +0 -195
  650. package/src/data/Store.js +0 -74
  651. package/src/data/observable-helpers/array.js +0 -74
  652. package/src/data/observable-helpers/batch.js +0 -22
  653. package/src/data/observable-helpers/computed.js +0 -28
  654. package/src/data/observable-helpers/object.js +0 -111
  655. package/src/elements/anchor.js +0 -129
  656. package/src/elements/content-formatter.js +0 -32
  657. package/src/elements/control/for-each-array.js +0 -280
  658. package/src/elements/control/show-if.js +0 -79
  659. package/src/elements/control/switch.js +0 -98
  660. package/src/elements/description-list.js +0 -5
  661. package/src/elements/form.js +0 -71
  662. package/src/elements/html5-semantics.js +0 -12
  663. package/src/elements/img.js +0 -45
  664. package/src/elements/interactive.js +0 -7
  665. package/src/elements/list.js +0 -10
  666. package/src/elements/medias.js +0 -8
  667. package/src/elements/meta-data.js +0 -9
  668. package/src/elements/table.js +0 -14
  669. package/src/utils/args-types.js +0 -100
  670. package/src/utils/debug-manager.js +0 -31
  671. package/src/utils/helpers.js +0 -60
  672. package/src/utils/plugins-manager.js +0 -12
  673. package/src/utils/prototypes.js +0 -45
  674. package/src/wrappers/AttributesWrapper.js +0 -144
  675. package/src/wrappers/DocumentObserver.js +0 -80
  676. package/src/wrappers/ElementCreator.js +0 -114
  677. package/src/wrappers/HtmlElementEventsWrapper.js +0 -64
  678. package/src/wrappers/HtmlElementWrapper.js +0 -50
  679. package/src/wrappers/NdPrototype.js +0 -106
  680. package/src/wrappers/constants.js +0 -2
@@ -0,0 +1,635 @@
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
+ import attributesWrapper, {
6
+ bindAttributeWithObservable,
7
+ bindClassAttribute,
8
+ bindStyleAttribute,
9
+ } from './AttributesWrapper';
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
+ */
18
+ export function NDElement(element) {
19
+ this.$element = element;
20
+ this.$attachements = null;
21
+ if(process.env.NODE_ENV === 'development') {
22
+ PluginsManager.emit('NDElementCreated', element, this);
23
+ }
24
+ }
25
+
26
+
27
+ NDElement.prototype.__$isNDElement = true;
28
+
29
+ NDElement.$getChild = (el) => el;
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
+ */
38
+ NDElement.prototype.ghostDom = function(element) {
39
+ if(!this.$attachements) {
40
+ this.$attachements = document.createDocumentFragment();
41
+ this.toNdElement = () => {
42
+ const fragment = document.createDocumentFragment();
43
+ if(!this.$attachements.contains(this.$element)) {
44
+ fragment.appendChild(this.$element);
45
+ }
46
+ fragment.appendChild(this.$attachements);
47
+ return fragment;
48
+ };
49
+ }
50
+ const child = NDElement.$getChild(element);
51
+ if(child) {
52
+ this.$attachements.appendChild(child);
53
+ }
54
+ return this;
55
+ };
56
+
57
+ /**
58
+ * Returns the underlying HTMLElement. Used internally for type coercion.
59
+ *
60
+ * @returns {HTMLElement}
61
+ */
62
+ NDElement.prototype.valueOf = function() {
63
+ return this.$element;
64
+ };
65
+
66
+ /**
67
+ * Stores the underlying HTMLElement in target[name].
68
+ * Use this to keep a reference to the raw DOM node.
69
+ *
70
+ * @param {Record<string, any>} target - Object to store the reference in
71
+ * @param {string} name - Property name to assign on the target object
72
+ * @returns {this}
73
+ * @example
74
+ * const refs = {};
75
+ * Input({ type: 'text' }).nd.ref(refs, 'emailInput');
76
+ * refs.emailInput.focus();
77
+ */
78
+ NDElement.prototype.ref = function(target, name) {
79
+ target[name] = this.$element;
80
+ return this;
81
+ };
82
+
83
+ /**
84
+ * Stores the NDElement instance itself in target[name].
85
+ * Use this to expose a component's public API to a parent (via .with()).
86
+ *
87
+ * @param {Record<string, any>} target - Object to store the reference in
88
+ * @param {string} name - Property name to assign on the target object
89
+ * @returns {this}
90
+ * @example
91
+ * const refs = {};
92
+ * Counter()
93
+ * .nd.with({ increment() { count.$value++; return this; } })
94
+ * .refSelf(refs, 'counter');
95
+ *
96
+ * refs.counter.increment();
97
+ */
98
+ NDElement.prototype.refSelf = function(target, name) {
99
+ target[name] = this;
100
+ // TODO: @DIM to check
101
+ // target[name] = new NDElement(this.$element);
102
+ return this;
103
+ };
104
+
105
+ /**
106
+ * Calls .nd.remove() on all child NDElements before removing this element.
107
+ * Used to propagate lifecycle cleanup through the component tree.
108
+ *
109
+ * @returns {this}
110
+ */
111
+ NDElement.prototype.unmountChildren = function() {
112
+ let element = this.$element;
113
+ for(let i = 0, length = element.children.length; i < length; i++) {
114
+ let elementChildren = element.children[i];
115
+ if(!elementChildren.$ndProx) {
116
+ elementChildren.nd?.remove();
117
+ }
118
+ elementChildren = null;
119
+ }
120
+ element = null;
121
+ return this;
122
+ };
123
+
124
+ /**
125
+ * Removes the element from the DOM and cleans up its lifecycle observers.
126
+ * Also calls unmountChildren() recursively.
127
+ *
128
+ * @returns {this}
129
+ */
130
+ NDElement.prototype.remove = function() {
131
+ let element = this.$element;
132
+ element.nd.unmountChildren();
133
+ element.$ndProx = null;
134
+
135
+ $lifeCycleObservers.delete(element);
136
+
137
+ element = null;
138
+ return this;
139
+ };
140
+
141
+ const $lifeCycleObservers = new WeakMap();
142
+
143
+ /**
144
+ * Registers mounted and/or unmounted lifecycle callbacks for this element.
145
+ * Uses MutationObserver internally to detect DOM insertion and removal.
146
+ *
147
+ * @param {{ mounted?: (el: HTMLElement) => void, unmounted?: (el: HTMLElement) => boolean|void }} states - Lifecycle hooks
148
+ * @returns {this}
149
+ * @example
150
+ * Div({}).nd.lifecycle({
151
+ * mounted: (el) => console.log('mounted', el),
152
+ * unmounted: (el) => console.log('unmounted', el),
153
+ * });
154
+ */
155
+ NDElement.prototype.lifecycle = function(states) {
156
+ const el = this.$element;
157
+ if (!$lifeCycleObservers.has(el)) {
158
+ $lifeCycleObservers.set(el, DocumentObserver.watch(el));
159
+ }
160
+ const observer = $lifeCycleObservers.get(el);
161
+
162
+ if(states.mounted) {
163
+ this.$element.setAttribute('data--nd-mounted', '1');
164
+ observer.mounted(states.mounted);
165
+ }
166
+ if(states.unmounted) {
167
+ this.$element.setAttribute('data--nd-unmounted', '1');
168
+ observer.unmounted(states.unmounted);
169
+ }
170
+ return this;
171
+ };
172
+
173
+ /**
174
+ * Registers an unmounted callback that cleans up all beforeUnmount handlers
175
+ * and aborts any pending async operations on this element and its children.
176
+ *
177
+ * @returns {this}
178
+ */
179
+ NDElement.prototype.destroyOnUnmount = function() {
180
+ this.unmounted(() => this.destroy());
181
+ return this;
182
+ };
183
+
184
+ /**
185
+ * aborts any pending async operations on this element and its children.
186
+ *
187
+ * @returns {this}
188
+ */
189
+ NDElement.prototype.destroy = function() {
190
+ if(!this.$element) {
191
+ return this;
192
+ }
193
+ const observer = $lifeCycleObservers.get(this.$element);
194
+ if(observer) {
195
+ observer.disconnect();
196
+ }
197
+
198
+ const children = this.$element?.querySelectorAll('[data--nd-before-unmount]');
199
+
200
+ for(let i = 0, length = children.length; i < length; i++) {
201
+ const child = children[i];
202
+ child.remove();
203
+ child.__$controller?.abort();
204
+ child.__$controller = null;
205
+ $lifeCycleObservers.delete(child);
206
+ }
207
+
208
+ this.$element.__$controller?.abort();
209
+ this.$element.__$controller = null;
210
+ $lifeCycleObservers.delete(this.$element);
211
+ this.$element = null;
212
+ };
213
+
214
+ /**
215
+ * Shorthand for lifecycle({ mounted: callback }).
216
+ *
217
+ * @param {(el: HTMLElement) => void} callback - Called when element is inserted into the DOM
218
+ * @returns {this}
219
+ */
220
+ NDElement.prototype.mounted = function(callback) {
221
+ return this.lifecycle({ mounted: callback });
222
+ };
223
+
224
+ /**
225
+ * Shorthand for lifecycle({ unmounted: callback }).
226
+ *
227
+ * @param {(el: HTMLElement) => boolean|void} callback - Called when element is removed from the DOM
228
+ * @returns {this}
229
+ */
230
+ NDElement.prototype.unmounted = function(callback) {
231
+ return this.lifecycle({ unmounted: callback });
232
+ };
233
+
234
+ /**
235
+ * Registers an async callback to run before this element is removed from the DOM.
236
+ * The element's .remove() is delayed until all beforeUnmount callbacks resolve.
237
+ *
238
+ * @param {string} id - Unique identifier for this callback (allows overwriting)
239
+ * @param {(this: NDElement, el: HTMLElement) => void|Promise<void>} callback - Async-compatible callback
240
+ * @returns {this}
241
+ * @example
242
+ * Div({}).nd.beforeUnmount('fade-out', async (el) => {
243
+ * await el.animate([{ opacity: 1 }, { opacity: 0 }], { duration: 300 }).finished;
244
+ * });
245
+ */
246
+ NDElement.prototype.beforeUnmount = function(id, callback) {
247
+ const el = this.$element;
248
+
249
+ if(!DocumentObserver.beforeUnmount.has(el)) {
250
+ DocumentObserver.beforeUnmount.set(el, new Map());
251
+ const originalRemove = el.remove.bind(el);
252
+
253
+ let $isUnmounting = false;
254
+ this.$element.setAttribute('data--nd-before-unmount', '1');
255
+
256
+ el.remove = async () => {
257
+ if($isUnmounting) {
258
+ return;
259
+ }
260
+ $isUnmounting = true;
261
+
262
+ try {
263
+ const callbacks = DocumentObserver.beforeUnmount.get(el);
264
+ for (const cb of callbacks.values()) {
265
+ await cb.call(this, el);
266
+ }
267
+ } finally {
268
+ originalRemove();
269
+ $isUnmounting = false;
270
+ }
271
+ };
272
+ }
273
+
274
+ DocumentObserver.beforeUnmount.get(el).set(id, callback);
275
+ return this;
276
+ };
277
+
278
+ /**
279
+ * Returns the underlying HTMLElement.
280
+ * Alias: .node()
281
+ *
282
+ * @returns {HTMLElement}
283
+ */
284
+ NDElement.prototype.htmlElement = function() {
285
+ return this.$element;
286
+ };
287
+
288
+ NDElement.prototype.node = NDElement.prototype.htmlElement;
289
+
290
+ /**
291
+ * Attaches a Shadow DOM to this element, redirecting all child appends to the shadow root.
292
+ *
293
+ * @param {'open'|'closed'} mode - Shadow DOM encapsulation mode
294
+ * @param {string|null} [style=null] - Optional CSS string to inject into the shadow root
295
+ * @returns {this}
296
+ */
297
+ NDElement.prototype.shadow = function(mode, style = null) {
298
+ const $element = this.$element;
299
+ const children = Array.from($element.childNodes);
300
+ const shadowRoot = $element.attachShadow({ mode });
301
+ if(style) {
302
+ const styleNode = document.createElement('style');
303
+ styleNode.textContent = style;
304
+ shadowRoot.appendChild(styleNode);
305
+ }
306
+ $element.append = shadowRoot.append.bind(shadowRoot);
307
+ $element.appendChild = shadowRoot.appendChild.bind(shadowRoot);
308
+ shadowRoot.append(...children);
309
+
310
+ return this;
311
+ };
312
+
313
+ /**
314
+ * Shorthand for .shadow('open', style).
315
+ *
316
+ * @param {string|null} [style=null] - Optional CSS string to inject into the shadow root
317
+ * @returns {this}
318
+ */
319
+ NDElement.prototype.openShadow = function(style = null) {
320
+ return this.shadow('open', style);
321
+ };
322
+
323
+ /**
324
+ * Shorthand for .shadow('closed', style).
325
+ *
326
+ * @param {string|null} [style=null] - Optional CSS string to inject into the shadow root
327
+ * @returns {this}
328
+ */
329
+ NDElement.prototype.closedShadow = function(style = null) {
330
+ return this.shadow('closed', style);
331
+ };
332
+
333
+ /**
334
+ * Extends the current NDElement instance with custom methods.
335
+ * Methods are bound to the instance and available for chaining.
336
+ *
337
+ * @param {Object} methods - Object containing method definitions
338
+ * @returns {this} The NDElement instance with added methods for chaining
339
+ * @example
340
+ * element.nd.with({
341
+ * highlight() {
342
+ * this.$element.style.background = 'yellow';
343
+ * return this;
344
+ * }
345
+ * }).highlight().onClick(() => console.log('Clicked'));
346
+ */
347
+ NDElement.prototype.with = function(methods) {
348
+ if (!methods || typeof methods !== 'object') {
349
+ throw new NativeDocumentError('extend() requires an object of methods');
350
+ }
351
+ if(process.env.NODE_ENV === 'development') {
352
+ if (!this.$localExtensions) {
353
+ this.$localExtensions = new Map();
354
+ }
355
+ }
356
+
357
+ for (const name in methods) {
358
+ const method = methods[name];
359
+
360
+ if (typeof method !== 'function') {
361
+ DebugManager.warn(`⚠️ extends(): "${name}" is not a function, skipping`);
362
+ continue;
363
+ }
364
+ if(process.env.NODE_ENV === 'development') {
365
+ if (this[name] && !this.$localExtensions.has(name)) {
366
+ DebugManager.warn('NDElement.extend', `Method "${name}" already exists and will be overwritten`);
367
+ }
368
+ this.$localExtensions.set(name, method);
369
+ }
370
+
371
+ this[name] = method.bind(this);
372
+ }
373
+
374
+ return this;
375
+ };
376
+
377
+ /**
378
+ * Sets a single attribute on the element.
379
+ * If value is an ObservableItem, the attribute is updated reactively.
380
+ *
381
+ * @param {string} name - Attribute name
382
+ * @param {string|ObservableItem<string>} value - Attribute value, static or reactive
383
+ * @returns {this}
384
+ * @example
385
+ * Input({}).nd.attr('placeholder', label); // reactive placeholder
386
+ */
387
+ NDElement.prototype.attr = function(name, value) {
388
+ if(value?.__$Observable) {
389
+ bindAttributeWithObservable(this.$element, name, value);
390
+ return this;
391
+ }
392
+ this.$element.setAttribute(name, value);
393
+ return this;
394
+ };
395
+
396
+ /**
397
+ * Applies a batch of attributes to the element via AttributesWrapper.
398
+ * Supports reactive values, class maps, and style maps.
399
+ *
400
+ * @param {Object} attrs - Attributes object (same format as HtmlElementWrapper props)
401
+ * @returns {this}
402
+ */
403
+ NDElement.prototype.attrs = function(attrs) {
404
+ attributesWrapper(this.$element, attrs);
405
+ return this;
406
+ };
407
+
408
+ /**
409
+ * Applies a reactive class map to the element.
410
+ * Each key is a class name; each value is a boolean or ObservableItem<boolean>.
411
+ *
412
+ * @param {Record<string, boolean|ObservableItem<boolean>>} classes - Class map
413
+ * @returns {this}
414
+ */
415
+ NDElement.prototype.class = function(classes) {
416
+ bindClassAttribute(this.$element, classes);
417
+ return this;
418
+ };
419
+
420
+ /**
421
+ * Applies a reactive style map to the element.
422
+ * Each key is a CSS property; each value is a string or ObservableItem<string>.
423
+ *
424
+ * @param {Record<string, string|ObservableItem<string>>} style - Style map
425
+ * @returns {this}
426
+ */
427
+ NDElement.prototype.style = function(style) {
428
+ bindStyleAttribute(this.$element, style);
429
+ return this;
430
+ };
431
+
432
+
433
+ /**
434
+ * Extends the NDElement prototype with new methods available to all NDElement instances.
435
+ * Use this to add global methods to all NDElements.
436
+ *
437
+ * @param {Object} methods - Object containing method definitions to add to prototype
438
+ * @returns {typeof NDElement} The NDElement constructor
439
+ * @throws {NativeDocumentError} If methods is not an object or contains non-function values
440
+ * @example
441
+ * NDElement.extend({
442
+ * fadeIn() {
443
+ * this.$element.style.opacity = '1';
444
+ * return this;
445
+ * }
446
+ * });
447
+ * // Now all NDElements have .fadeIn() method
448
+ * Div().nd.fadeIn();
449
+ */
450
+ NDElement.extend = function(methods) {
451
+ if (!methods || typeof methods !== 'object') {
452
+ throw new NativeDocumentError('NDElement.extend() requires an object of methods');
453
+ }
454
+
455
+ if (Array.isArray(methods)) {
456
+ throw new NativeDocumentError('NDElement.extend() requires an object, not an array');
457
+ }
458
+
459
+ const protectedMethods = new Set([
460
+ 'constructor', 'valueOf', '$element', '$observer',
461
+ 'ref', 'remove', 'cleanup', 'with', 'extend', 'attach',
462
+ 'lifecycle', 'mounted', 'unmounted', 'unmountChildren',
463
+ ]);
464
+
465
+ for (const name in methods) {
466
+ if (!Object.hasOwn(methods, name)) {
467
+ continue;
468
+ }
469
+
470
+ const method = methods[name];
471
+
472
+ if (typeof method !== 'function') {
473
+ DebugManager.warn('NDElement.extend', `"${name}" is not a function, skipping`);
474
+ continue;
475
+ }
476
+
477
+ if (protectedMethods.has(name)) {
478
+ DebugManager.error('NDElement.extend', `Cannot override protected method "${name}"`);
479
+ throw new NativeDocumentError(`Cannot override protected method "${name}"`);
480
+ }
481
+
482
+ if (NDElement.prototype[name]) {
483
+ DebugManager.warn('NDElement.extend', `Overwriting existing prototype method "${name}"`);
484
+ }
485
+
486
+ NDElement.prototype[name] = method;
487
+ }
488
+ if(process.env.NODE_ENV === 'development') {
489
+ PluginsManager.emit('NDElementExtended', methods);
490
+ }
491
+
492
+ return NDElement;
493
+ };
494
+
495
+
496
+ /**
497
+ * The global sanitizer function used by nd.html() when sanitize option is enabled.
498
+ * Must be set via NDElement.setSanitizer() before using {sanitize: true}.
499
+ *
500
+ * @type {Function|null}
501
+ */
502
+ NDElement.$sanitizer = null;
503
+
504
+ /**
505
+ * Configures the global sanitizer for nd.html().
506
+ * The sanitizer function receives the HTML string and an optional config object.
507
+ * Designed to be decoupled from any specific sanitizer library.
508
+ *
509
+ * @param {Function} sanitizerFn - Sanitizer function (html, config) => string
510
+ * @returns {typeof NDElement}
511
+ * @throws {NativeDocumentError} If sanitizerFn is not a function
512
+ * @example
513
+ * import DOMPurify from 'dompurify';
514
+ * NDElement.setSanitizer((html, config) => DOMPurify.sanitize(html, config));
515
+ */
516
+ NDElement.setSanitizer = function(sanitizerFn) {
517
+ if(typeof sanitizerFn !== 'function') {
518
+ throw new NativeDocumentError('NDElement.setSanitizer() expects a function');
519
+ }
520
+ NDElement.$sanitizer = sanitizerFn;
521
+ return NDElement;
522
+ };
523
+
524
+ /**
525
+ * Sets the inner HTML of the element.
526
+ * Requires either {unsafe: true} to bypass security checks,
527
+ * or {sanitize: true|Object|Function} to sanitize the content.
528
+ * Supports Observable values for reactive HTML updates.
529
+ *
530
+ * @param {string|ObservableItem} content - HTML string or Observable<string>
531
+ * @param {Object} [options={}]
532
+ * @param {boolean} [options.unsafe=false] - Bypass security check. Use only with trusted content.
533
+ * @param {boolean|Object|Function} [options.sanitize=false] - Sanitize strategy:
534
+ * - true: use global sanitizer with default config
535
+ * - Object: use global sanitizer with custom config
536
+ * - Function: use this function directly as sanitizer (html) => string
537
+ * @returns {this}
538
+ * @throws {NativeDocumentError} If sanitize is true/Object but no global sanitizer is configured
539
+ * @example
540
+ * // Unsafe — trusted content only
541
+ * el.nd.html('<strong>Hello</strong>', {unsafe: true})
542
+ *
543
+ * // Global sanitizer with default config
544
+ * el.nd.html($userContent, {sanitize: true})
545
+ *
546
+ * // Global sanitizer with custom config
547
+ * el.nd.html($userContent, {sanitize: {
548
+ * ALLOWED_TAGS: ['b', 'i', 'strong', 'a'],
549
+ * ALLOWED_ATTR: ['href'],
550
+ * }})
551
+ *
552
+ * // Custom sanitizer function for this specific case
553
+ * el.nd.html($userContent, {sanitize: (html) => myCustomSanitizer(html)})
554
+ *
555
+ * // Reactive with sanitize
556
+ * el.nd.html($content, {sanitize: true})
557
+ */
558
+ NDElement.prototype.html = function(content, {unsafe = false, sanitize = false} = {}) {
559
+ const $element = this.$element;
560
+ const apply = (value) => {
561
+ if(sanitize) {
562
+ if(typeof sanitize === 'function') {
563
+ $element.innerHTML = sanitize(value);
564
+ return;
565
+ }
566
+
567
+ if(!NDElement.$sanitizer) {
568
+ throw new NativeDocumentError('nd.html() — no sanitizer configured. Call NDElement.setSanitizer() first.');
569
+ }
570
+ const config = sanitize === true ? {} : sanitize;
571
+ $element.innerHTML = NDElement.$sanitizer(value, config);
572
+ return;
573
+ }
574
+
575
+ if(!unsafe) {
576
+ console.warn('nd.html() — use {unsafe: true} or {sanitize: true|Object|Function}');
577
+ return;
578
+ }
579
+
580
+ $element.innerHTML = value;
581
+ };
582
+
583
+ if(content?.__$Observable) {
584
+ content.subscribe(apply);
585
+ apply(content.val());
586
+ return this;
587
+ }
588
+
589
+ apply(content);
590
+ return this;
591
+ };
592
+
593
+ /**
594
+ * Makes the element content editable and binds it to an Observable.
595
+ * Changes in the DOM update the Observable, and changes to the Observable
596
+ * update the DOM (only when the element is not focused to avoid cursor issues).
597
+ *
598
+ * @param {ObservableItem} $obs - Observable to bind to the element content
599
+ * @param {Object} [options={}]
600
+ * @param {string} [options.format='html'] - 'html' uses innerHTML, 'text' uses innerText
601
+ * @returns {this}
602
+ * @example
603
+ * // Basic usage
604
+ * const $content = $('<b>Hello</b>');
605
+ * Div({}).nd.contentEditable($content)
606
+ *
607
+ * // Text only
608
+ * Div({}).nd.contentEditable($content, {format: 'text'})
609
+ */
610
+ NDElement.prototype.contentEditable = function($obs, {format = 'html'} = {}) {
611
+ this.$element.contentEditable = true;
612
+
613
+ const getValue = format === 'text'
614
+ ? () => this.$element.innerText
615
+ : () => this.$element.innerHTML;
616
+
617
+ const setValue = format === 'text'
618
+ ? (value) => { this.$element.innerText = value; }
619
+ : (value) => { this.$element.innerHTML = value; };
620
+
621
+ if($obs?.__$Observable) {
622
+ $obs.subscribe((value) => {
623
+ if(document.activeElement !== this.$element) {
624
+ setValue(value);
625
+ }
626
+ });
627
+ setValue($obs.val() || '');
628
+ }
629
+
630
+ this.$element.addEventListener('input', () => {
631
+ $obs?.set(getValue());
632
+ }, { signal: this.$getSignal() });
633
+
634
+ return this;
635
+ };