native-document 1.0.14 → 1.0.16-8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (643) hide show
  1. package/.npmrc.example +1 -0
  2. package/.vitepress/config.js +166 -0
  3. package/CHANGELOG.md +153 -0
  4. package/cdn.js +19 -0
  5. package/components.d.ts +2 -0
  6. package/components.js +30 -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 +23847 -0
  21. package/dist/native-document.dev.js +8665 -1313
  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 +218 -131
  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/index.md +337 -0
  58. package/docs/components/layout.md +279 -0
  59. package/docs/components/list.md +73 -0
  60. package/docs/components/menu.md +215 -0
  61. package/docs/components/modal.md +156 -0
  62. package/docs/components/pagination.md +95 -0
  63. package/docs/components/popover.md +131 -0
  64. package/docs/components/progress.md +111 -0
  65. package/docs/components/shortcut-manager.md +221 -0
  66. package/docs/components/simple-table.md +107 -0
  67. package/docs/components/skeleton.md +155 -0
  68. package/docs/components/spinner.md +100 -0
  69. package/docs/components/splitter.md +133 -0
  70. package/docs/components/stepper.md +163 -0
  71. package/docs/components/switch.md +113 -0
  72. package/docs/components/tabs.md +153 -0
  73. package/docs/components/toast.md +119 -0
  74. package/docs/components/tooltip.md +151 -0
  75. package/docs/components/traits.md +261 -0
  76. package/docs/conditional-rendering.md +177 -501
  77. package/docs/contributing.md +300 -25
  78. package/docs/core-concepts.md +209 -367
  79. package/docs/elements.md +268 -255
  80. package/docs/extending-native-document-element.md +259 -0
  81. package/docs/filters.md +247 -0
  82. package/docs/getting-started.md +199 -260
  83. package/docs/i18n.md +241 -0
  84. package/docs/index.md +76 -0
  85. package/docs/lifecycle-events.md +146 -67
  86. package/docs/list-rendering.md +387 -0
  87. package/docs/memory-management.md +135 -46
  88. package/docs/native-document-element.md +487 -0
  89. package/docs/native-fetch.md +213 -0
  90. package/docs/observable-resource.md +364 -0
  91. package/docs/observables.md +690 -356
  92. package/docs/routing.md +246 -646
  93. package/docs/state-management.md +213 -306
  94. package/docs/svg-elements.md +231 -0
  95. package/docs/theming.md +409 -0
  96. package/docs/tutorials/.gitkeep +0 -0
  97. package/docs/validation.md +98 -93
  98. package/docs/vitepress-conventions.md +219 -0
  99. package/elements.d.ts +7 -0
  100. package/elements.js +3 -4
  101. package/eslint.config.js +35 -0
  102. package/i18n.js +1 -0
  103. package/i18n.ts +2 -0
  104. package/index.d.ts +21 -0
  105. package/index.def.js +1086 -0
  106. package/index.js +19 -8
  107. package/package.json +59 -9
  108. package/readme.md +294 -90
  109. package/rollup.config.js +52 -3
  110. package/router.d.ts +7 -0
  111. package/router.js +0 -0
  112. package/src/components/$traits/has-draggable/HasDraggable.d.ts +4 -0
  113. package/src/components/$traits/has-draggable/HasDraggable.js +82 -0
  114. package/src/components/$traits/has-draggable/has-draggable.css +8 -0
  115. package/src/components/$traits/has-items/HasItems.d.ts +9 -0
  116. package/src/components/$traits/has-items/HasItems.js +64 -0
  117. package/src/components/$traits/has-position/HasFullPosition.d.ts +14 -0
  118. package/src/components/$traits/has-position/HasFullPosition.js +95 -0
  119. package/src/components/$traits/has-position/HasPosition.d.ts +7 -0
  120. package/src/components/$traits/has-position/HasPosition.js +45 -0
  121. package/src/components/$traits/has-resizable/HasResizable.d.ts +13 -0
  122. package/src/components/$traits/has-resizable/HasResizable.js +122 -0
  123. package/src/components/$traits/has-resizable/has-resizable.css +121 -0
  124. package/src/components/$traits/has-validation/HasValidation.d.ts +17 -0
  125. package/src/components/$traits/has-validation/HasValidation.js +133 -0
  126. package/src/components/BaseComponent.d.ts +32 -0
  127. package/src/components/BaseComponent.js +247 -0
  128. package/src/components/accordion/Accordion.js +268 -0
  129. package/src/components/accordion/AccordionItem.js +233 -0
  130. package/src/components/accordion/index.js +7 -0
  131. package/src/components/accordion/types/Accordion.d.ts +47 -0
  132. package/src/components/accordion/types/AccordionItem.d.ts +48 -0
  133. package/src/components/alert/Alert.js +350 -0
  134. package/src/components/alert/index.js +6 -0
  135. package/src/components/alert/types/Alert.d.ts +62 -0
  136. package/src/components/avatar/Avatar.js +430 -0
  137. package/src/components/avatar/AvatarGroup.js +97 -0
  138. package/src/components/avatar/index.js +7 -0
  139. package/src/components/avatar/types/Avatar.d.ts +74 -0
  140. package/src/components/avatar/types/AvatarGroup.d.ts +32 -0
  141. package/src/components/badge/Badge.js +245 -0
  142. package/src/components/badge/index.js +6 -0
  143. package/src/components/badge/types/Badge.d.ts +51 -0
  144. package/src/components/base-component.css +0 -0
  145. package/src/components/breadcrumb/BreadCrumb.js +138 -0
  146. package/src/components/breadcrumb/index.js +5 -0
  147. package/src/components/breadcrumb/types/BreadCrumb.d.ts +42 -0
  148. package/src/components/button/Button.js +320 -0
  149. package/src/components/button/index.js +5 -0
  150. package/src/components/button/types/Button.d.ts +62 -0
  151. package/src/components/card/Card.js +282 -0
  152. package/src/components/card/index.js +5 -0
  153. package/src/components/card/types/Card.d.ts +42 -0
  154. package/src/components/context-menu/ContextMenu.js +127 -0
  155. package/src/components/context-menu/ContextMenuGroup.js +29 -0
  156. package/src/components/context-menu/ContextMenuItem.js +28 -0
  157. package/src/components/context-menu/index.js +10 -0
  158. package/src/components/context-menu/types/ContextMenu.d.ts +30 -0
  159. package/src/components/context-menu/types/ContextMenuGroup.d.ts +18 -0
  160. package/src/components/context-menu/types/ContextMenuItem.d.ts +18 -0
  161. package/src/components/divider/Divider.js +256 -0
  162. package/src/components/divider/index.js +6 -0
  163. package/src/components/divider/types/Divider.d.ts +55 -0
  164. package/src/components/dropdown/Dropdown.js +531 -0
  165. package/src/components/dropdown/DropdownDivider.js +45 -0
  166. package/src/components/dropdown/DropdownGroup.js +83 -0
  167. package/src/components/dropdown/DropdownItem.js +150 -0
  168. package/src/components/dropdown/DropdownTrigger.js +93 -0
  169. package/src/components/dropdown/helpers.js +53 -0
  170. package/src/components/dropdown/index.js +13 -0
  171. package/src/components/dropdown/types/Dropdown.d.ts +88 -0
  172. package/src/components/dropdown/types/DropdownDivider.d.ts +20 -0
  173. package/src/components/dropdown/types/DropdownGroup.d.ts +25 -0
  174. package/src/components/dropdown/types/DropdownItem.d.ts +41 -0
  175. package/src/components/dropdown/types/DropdownTrigger.d.ts +32 -0
  176. package/src/components/form/FormControl.js +498 -0
  177. package/src/components/form/field/Field.js +419 -0
  178. package/src/components/form/field/FieldCollection.js +292 -0
  179. package/src/components/form/field/types/AutocompleteField.js +168 -0
  180. package/src/components/form/field/types/CheckboxField.js +77 -0
  181. package/src/components/form/field/types/CheckboxGroupField.js +171 -0
  182. package/src/components/form/field/types/ColorField.js +102 -0
  183. package/src/components/form/field/types/DateField.js +315 -0
  184. package/src/components/form/field/types/EmailField.js +104 -0
  185. package/src/components/form/field/types/FileField.js +276 -0
  186. package/src/components/form/field/types/HiddenField.js +44 -0
  187. package/src/components/form/field/types/ImageField.js +138 -0
  188. package/src/components/form/field/types/NumberField.js +177 -0
  189. package/src/components/form/field/types/PasswordField.js +200 -0
  190. package/src/components/form/field/types/RadioField.js +145 -0
  191. package/src/components/form/field/types/RangeField.js +117 -0
  192. package/src/components/form/field/types/SearchField.js +66 -0
  193. package/src/components/form/field/types/SelectField.js +247 -0
  194. package/src/components/form/field/types/StringField.js +148 -0
  195. package/src/components/form/field/types/TelField.js +98 -0
  196. package/src/components/form/field/types/TextAreaField.js +142 -0
  197. package/src/components/form/field/types/TimeField.js +215 -0
  198. package/src/components/form/field/types/UrlField.js +115 -0
  199. package/src/components/form/field/types/file-field-mode/FileAvatarMode.js +183 -0
  200. package/src/components/form/field/types/file-field-mode/FileDropzoneMode.js +117 -0
  201. package/src/components/form/field/types/file-field-mode/FileItemPreview.js +150 -0
  202. package/src/components/form/field/types/file-field-mode/FileNativeMode.js +43 -0
  203. package/src/components/form/field/types/file-field-mode/FileUploadButtonMode.js +120 -0
  204. package/src/components/form/field/types/file-field-mode/FileWallMode.js +106 -0
  205. package/src/components/form/index.js +61 -0
  206. package/src/components/form/merge +0 -0
  207. package/src/components/form/types/Field.d.ts +73 -0
  208. package/src/components/form/types/FieldCollection.d.ts +53 -0
  209. package/src/components/form/types/FormControl.d.ts +64 -0
  210. package/src/components/form/types/fields/AutocompleteField.d.ts +48 -0
  211. package/src/components/form/types/fields/CheckboxField.d.ts +33 -0
  212. package/src/components/form/types/fields/CheckboxGroupField.d.ts +49 -0
  213. package/src/components/form/types/fields/ColorField.d.ts +37 -0
  214. package/src/components/form/types/fields/DateField.d.ts +70 -0
  215. package/src/components/form/types/fields/EmailField.d.ts +35 -0
  216. package/src/components/form/types/fields/FileAvatarMode.d.ts +46 -0
  217. package/src/components/form/types/fields/FileDropzoneMode.d.ts +28 -0
  218. package/src/components/form/types/fields/FileField.d.ts +56 -0
  219. package/src/components/form/types/fields/FileItemPreview.d.ts +35 -0
  220. package/src/components/form/types/fields/FileNativeMode.d.ts +21 -0
  221. package/src/components/form/types/fields/FileUploadButtonMode.d.ts +34 -0
  222. package/src/components/form/types/fields/FileWallMode.d.ts +32 -0
  223. package/src/components/form/types/fields/HiddenField.d.ts +26 -0
  224. package/src/components/form/types/fields/ImageField.d.ts +45 -0
  225. package/src/components/form/types/fields/NumberField.d.ts +48 -0
  226. package/src/components/form/types/fields/PasswordField.d.ts +46 -0
  227. package/src/components/form/types/fields/RadioField.d.ts +48 -0
  228. package/src/components/form/types/fields/RangeField.d.ts +44 -0
  229. package/src/components/form/types/fields/SearchField.d.ts +34 -0
  230. package/src/components/form/types/fields/SelectField.d.ts +71 -0
  231. package/src/components/form/types/fields/StringField.d.ts +48 -0
  232. package/src/components/form/types/fields/TelField.d.ts +37 -0
  233. package/src/components/form/types/fields/TextAreaField.d.ts +44 -0
  234. package/src/components/form/types/fields/TimeField.d.ts +51 -0
  235. package/src/components/form/types/fields/UrlField.d.ts +35 -0
  236. package/src/components/form/utils.js +17 -0
  237. package/src/components/form/validation/Validation.js +565 -0
  238. package/src/components/index.d.ts +160 -0
  239. package/src/components/list/HasListItem.js +171 -0
  240. package/src/components/list/List.js +125 -0
  241. package/src/components/list/ListDivider.js +39 -0
  242. package/src/components/list/ListGroup.js +135 -0
  243. package/src/components/list/ListItem.js +212 -0
  244. package/src/components/list/index.js +12 -0
  245. package/src/components/list/types/List.d.ts +43 -0
  246. package/src/components/list/types/ListGroup.d.ts +37 -0
  247. package/src/components/list/types/ListItem.d.ts +53 -0
  248. package/src/components/menu/HasMenuItem.js +182 -0
  249. package/src/components/menu/Menu.js +227 -0
  250. package/src/components/menu/MenuDivider.js +37 -0
  251. package/src/components/menu/MenuGroup.js +126 -0
  252. package/src/components/menu/MenuItem.js +190 -0
  253. package/src/components/menu/MenuLink.js +51 -0
  254. package/src/components/menu/index.js +14 -0
  255. package/src/components/menu/types/Menu.d.ts +60 -0
  256. package/src/components/menu/types/MenuDivider.d.ts +19 -0
  257. package/src/components/menu/types/MenuGroup.d.ts +44 -0
  258. package/src/components/menu/types/MenuItem.d.ts +46 -0
  259. package/src/components/menu/types/MenuLink.d.ts +16 -0
  260. package/src/components/modal/Modal.js +524 -0
  261. package/src/components/modal/index.js +5 -0
  262. package/src/components/modal/types/Modal.d.ts +94 -0
  263. package/src/components/pagination/Pagination.js +411 -0
  264. package/src/components/pagination/index.js +5 -0
  265. package/src/components/pagination/types/Pagination.d.ts +68 -0
  266. package/src/components/popover/Popover.js +459 -0
  267. package/src/components/popover/PopoverFooter.js +61 -0
  268. package/src/components/popover/PopoverHeader.js +68 -0
  269. package/src/components/popover/index.js +10 -0
  270. package/src/components/popover/types/Popover.d.ts +83 -0
  271. package/src/components/popover/types/PopoverFooter.d.ts +24 -0
  272. package/src/components/popover/types/PopoverHeader.d.ts +26 -0
  273. package/src/components/progress/Progress.js +401 -0
  274. package/src/components/progress/index.js +6 -0
  275. package/src/components/progress/types/Progress.d.ts +77 -0
  276. package/src/components/skeleton/Skeleton.js +228 -0
  277. package/src/components/skeleton/index.js +6 -0
  278. package/src/components/skeleton/types/Skeleton.d.ts +55 -0
  279. package/src/components/slider/Slider.js +406 -0
  280. package/src/components/slider/index.js +5 -0
  281. package/src/components/slider/types/Slider.d.ts +82 -0
  282. package/src/components/spacer/Spacer.js +27 -0
  283. package/src/components/spacer/index.js +5 -0
  284. package/src/components/spacer/types/Spacer.d.ts +19 -0
  285. package/src/components/spinner/Spinner.js +350 -0
  286. package/src/components/spinner/index.js +5 -0
  287. package/src/components/spinner/types/Spinner.d.ts +71 -0
  288. package/src/components/splitter/Splitter.js +164 -0
  289. package/src/components/splitter/SplitterGutter.js +140 -0
  290. package/src/components/splitter/SplitterPanel.js +143 -0
  291. package/src/components/splitter/index.js +10 -0
  292. package/src/components/splitter/types/Splitter.d.ts +38 -0
  293. package/src/components/splitter/types/SplitterGutter.d.ts +38 -0
  294. package/src/components/splitter/types/SplitterPanel.d.ts +41 -0
  295. package/src/components/stacks/AbsoluteStack.js +53 -0
  296. package/src/components/stacks/FixedStack.js +53 -0
  297. package/src/components/stacks/HStack.js +54 -0
  298. package/src/components/stacks/PositionStack.js +254 -0
  299. package/src/components/stacks/RelativeStack.js +53 -0
  300. package/src/components/stacks/Stack.js +166 -0
  301. package/src/components/stacks/VStack.js +55 -0
  302. package/src/components/stacks/index.js +21 -0
  303. package/src/components/stacks/types/AbsoluteStack.d.ts +16 -0
  304. package/src/components/stacks/types/FixedStack.d.ts +16 -0
  305. package/src/components/stacks/types/HStack.d.ts +16 -0
  306. package/src/components/stacks/types/PositionStack.d.ts +54 -0
  307. package/src/components/stacks/types/RelativeStack.d.ts +17 -0
  308. package/src/components/stacks/types/Stack.d.ts +39 -0
  309. package/src/components/stacks/types/VStack.d.ts +16 -0
  310. package/src/components/stepper/Stepper.js +461 -0
  311. package/src/components/stepper/StepperStep.js +241 -0
  312. package/src/components/stepper/index.js +8 -0
  313. package/src/components/stepper/types/Stepper.d.ts +68 -0
  314. package/src/components/stepper/types/StepperStep.d.ts +54 -0
  315. package/src/components/switch/Switch.js +266 -0
  316. package/src/components/switch/index.js +6 -0
  317. package/src/components/switch/types/Switch.d.ts +55 -0
  318. package/src/components/table/Column.js +212 -0
  319. package/src/components/table/ColumnGroup.js +90 -0
  320. package/src/components/table/DataTable.js +720 -0
  321. package/src/components/table/SimpleTable.js +139 -0
  322. package/src/components/table/index.js +7 -0
  323. package/src/components/table/types/Column.d.ts +49 -0
  324. package/src/components/table/types/ColumnGroup.d.ts +28 -0
  325. package/src/components/table/types/DataTable.d.ts +97 -0
  326. package/src/components/table/types/SimpleTable.d.ts +40 -0
  327. package/src/components/tabs/Tabs.js +395 -0
  328. package/src/components/tabs/index.js +6 -0
  329. package/src/components/tabs/types/Tabs.d.ts +78 -0
  330. package/src/components/toast/Toast.js +262 -0
  331. package/src/components/toast/ToastError.js +0 -0
  332. package/src/components/toast/ToastInfo.js +0 -0
  333. package/src/components/toast/ToastSuccess.js +0 -0
  334. package/src/components/toast/ToastWarning.js +0 -0
  335. package/src/components/toast/index.js +5 -0
  336. package/src/components/toast/types/Toast.d.ts +57 -0
  337. package/src/components/toast/types/ToastError.d.ts +7 -0
  338. package/src/components/toast/types/ToastInfo.d.ts +7 -0
  339. package/src/components/toast/types/ToastSuccess.d.ts +7 -0
  340. package/src/components/toast/types/ToastWarning.d.ts +7 -0
  341. package/src/components/tooltip/Tooltip.js +359 -0
  342. package/src/components/tooltip/index.js +5 -0
  343. package/src/components/tooltip/prototypes.js +6 -0
  344. package/src/components/tooltip/types/Tooltip.d.ts +65 -0
  345. package/src/{data → core/data}/MemoryManager.js +9 -22
  346. package/src/core/data/Observable.js +227 -0
  347. package/src/core/data/ObservableArray.js +522 -0
  348. package/src/core/data/ObservableChecker.js +39 -0
  349. package/src/core/data/ObservableItem.js +611 -0
  350. package/src/core/data/ObservableObject.js +274 -0
  351. package/src/core/data/ObservableResource.js +315 -0
  352. package/src/core/data/ObservableWhen.js +54 -0
  353. package/src/core/data/Store.js +520 -0
  354. package/src/core/data/observable-helpers/observable.is-to.js +390 -0
  355. package/src/core/data/observable-helpers/observable.prototypes.js +145 -0
  356. package/src/core/elements/anchor/anchor-with-sentinel.js +66 -0
  357. package/src/core/elements/anchor/anchor.js +210 -0
  358. package/src/core/elements/anchor/one-child-anchor-overwriting.js +66 -0
  359. package/src/core/elements/content-formatter.js +169 -0
  360. package/src/core/elements/control/for-each-array.js +292 -0
  361. package/src/core/elements/control/for-each.js +170 -0
  362. package/src/core/elements/control/show-if.js +94 -0
  363. package/src/core/elements/control/show-when.js +54 -0
  364. package/src/core/elements/control/switch.js +141 -0
  365. package/src/core/elements/description-list.js +19 -0
  366. package/src/core/elements/form.js +255 -0
  367. package/src/core/elements/fragment.js +8 -0
  368. package/src/core/elements/html5-semantics.js +55 -0
  369. package/src/core/elements/img.js +59 -0
  370. package/src/{elements → core/elements}/index.js +5 -4
  371. package/src/core/elements/interactive.js +25 -0
  372. package/src/core/elements/list.js +37 -0
  373. package/src/core/elements/medias.js +37 -0
  374. package/src/core/elements/meta-data.js +43 -0
  375. package/src/core/elements/svg.js +61 -0
  376. package/src/core/elements/table.js +73 -0
  377. package/src/{errors → core/errors}/ArgTypesError.js +1 -1
  378. package/src/{errors → core/errors}/NativeDocumentError.js +0 -0
  379. package/src/core/utils/HasEventEmitter.js +85 -0
  380. package/src/core/utils/args-types.js +140 -0
  381. package/src/core/utils/cache.js +5 -0
  382. package/src/core/utils/callback-handler.js +50 -0
  383. package/src/core/utils/debug-manager.js +40 -0
  384. package/src/core/utils/events.js +148 -0
  385. package/src/core/utils/filters/date.js +178 -0
  386. package/src/core/utils/filters/index.js +4 -0
  387. package/src/core/utils/filters/standard.js +263 -0
  388. package/src/core/utils/filters/strings.js +67 -0
  389. package/src/core/utils/filters/utils.js +77 -0
  390. package/src/core/utils/formatters.js +90 -0
  391. package/src/core/utils/helpers.js +144 -0
  392. package/src/core/utils/localstorage.js +57 -0
  393. package/src/core/utils/memoize.js +115 -0
  394. package/src/core/utils/plugins-manager.js +81 -0
  395. package/src/core/utils/property-accumulator.js +72 -0
  396. package/src/core/utils/prototypes.js +44 -0
  397. package/src/core/utils/shortcut-manager.js +242 -0
  398. package/src/{utils → core/utils}/validator.js +58 -22
  399. package/src/core/wrappers/AttributesWrapper.js +181 -0
  400. package/src/core/wrappers/DocumentObserver.js +182 -0
  401. package/src/core/wrappers/ElementCreator.js +110 -0
  402. package/src/core/wrappers/HtmlElementWrapper.js +98 -0
  403. package/src/core/wrappers/NDElement.js +613 -0
  404. package/src/core/wrappers/NdPrototype.js +233 -0
  405. package/src/core/wrappers/SingletonView.js +99 -0
  406. package/src/core/wrappers/SvgElementWrapper.js +15 -0
  407. package/src/core/wrappers/TemplateBinding.js +7 -0
  408. package/src/core/wrappers/constants.js +66 -0
  409. package/src/core/wrappers/prototypes/attributes-extensions.js +24 -0
  410. package/src/core/wrappers/prototypes/bind-class-extensions.js +0 -0
  411. package/src/core/wrappers/prototypes/nd-element-extensions.js +149 -0
  412. package/src/core/wrappers/prototypes/nd-element.transition.extensions.js +127 -0
  413. package/src/core/wrappers/template-cloner/NodeCloner.js +209 -0
  414. package/src/core/wrappers/template-cloner/TemplateCloner.js +192 -0
  415. package/src/core/wrappers/template-cloner/attributes-hydrator.js +142 -0
  416. package/src/core/wrappers/template-cloner/utils.js +173 -0
  417. package/src/fetch/NativeFetch.js +89 -0
  418. package/src/i18n/bin/scan.js +132 -0
  419. package/src/i18n/index.d.ts +2 -0
  420. package/src/i18n/service/I18nService.d.ts +27 -0
  421. package/src/i18n/service/I18nService.js +46 -0
  422. package/src/i18n/service/functions.d.ts +22 -0
  423. package/src/i18n/service/functions.js +29 -0
  424. package/src/router/Route.js +33 -8
  425. package/src/router/RouteGroupHelper.js +10 -2
  426. package/src/router/Router.js +63 -22
  427. package/src/router/RouterComponent.js +114 -6
  428. package/src/{errors → router/errors}/RouterError.js +0 -1
  429. package/src/router/link.js +9 -10
  430. package/src/router/modes/HashRouter.js +2 -2
  431. package/src/router/modes/HistoryRouter.js +2 -3
  432. package/src/router/modes/MemoryRouter.js +1 -1
  433. package/src/ui/components/accordion/AccordionItemRender.js +63 -0
  434. package/src/ui/components/accordion/AccordionRender.js +35 -0
  435. package/src/ui/components/accordion/accordion.css +121 -0
  436. package/src/ui/components/alert/AlertRender.js +81 -0
  437. package/src/ui/components/alert/alert.css +163 -0
  438. package/src/ui/components/avatar/avata-group/AvatarGroupRender.js +50 -0
  439. package/src/ui/components/avatar/avata-group/avatar-group.css +38 -0
  440. package/src/ui/components/avatar/avatar/AvatarRender.js +87 -0
  441. package/src/ui/components/avatar/avatar/avatar.css +189 -0
  442. package/src/ui/components/badge/BadgeRender.js +25 -0
  443. package/src/ui/components/badge/badge.css +168 -0
  444. package/src/ui/components/breadcrumb/BreadcrumbRender.js +44 -0
  445. package/src/ui/components/breadcrumb/breadcrumb.css +55 -0
  446. package/src/ui/components/button/ButtonRender.js +65 -0
  447. package/src/ui/components/button/button.css +296 -0
  448. package/src/ui/components/card/CardRender.js +133 -0
  449. package/src/ui/components/card/card.css +169 -0
  450. package/src/ui/components/contextmenu/ContextmenuRender.js +68 -0
  451. package/src/ui/components/contextmenu/contextmenu.css +36 -0
  452. package/src/ui/components/divider/DividerRender.js +70 -0
  453. package/src/ui/components/divider/divider.css +70 -0
  454. package/src/ui/components/dropdown/DropdownRender.js +92 -0
  455. package/src/ui/components/dropdown/divider/DropdownDividerRender.js +9 -0
  456. package/src/ui/components/dropdown/divider/dropdown-divider.css +0 -0
  457. package/src/ui/components/dropdown/dropdown.css +179 -0
  458. package/src/ui/components/dropdown/group/DropdownGroupRender.js +23 -0
  459. package/src/ui/components/dropdown/group/dropdown-group.css +0 -0
  460. package/src/ui/components/dropdown/item/DropdownItemRender.js +29 -0
  461. package/src/ui/components/dropdown/item/dropdown-item.css +0 -0
  462. package/src/ui/components/form/FieldCollectionRender.js +110 -0
  463. package/src/ui/components/form/FormControlRender.js +85 -0
  464. package/src/ui/components/form/field-collection.css +55 -0
  465. package/src/ui/components/form/fields/AutocompleteFieldRender.js +143 -0
  466. package/src/ui/components/form/fields/CheckboxFieldRender.js +59 -0
  467. package/src/ui/components/form/fields/CheckboxGroupFieldRender.js +92 -0
  468. package/src/ui/components/form/fields/ColorFieldRender.js +30 -0
  469. package/src/ui/components/form/fields/DateFieldRender.js +155 -0
  470. package/src/ui/components/form/fields/EmailFieldRender.js +5 -0
  471. package/src/ui/components/form/fields/FieldRender.js +118 -0
  472. package/src/ui/components/form/fields/FileFieldRender.js +41 -0
  473. package/src/ui/components/form/fields/HiddenFieldRender.js +13 -0
  474. package/src/ui/components/form/fields/ImageFieldRender.js +0 -0
  475. package/src/ui/components/form/fields/NumberFieldRender.js +52 -0
  476. package/src/ui/components/form/fields/PasswordFieldRender.js +65 -0
  477. package/src/ui/components/form/fields/RadioFieldRender.js +77 -0
  478. package/src/ui/components/form/fields/RangeFieldRender.js +122 -0
  479. package/src/ui/components/form/fields/SelectFieldRender.js +248 -0
  480. package/src/ui/components/form/fields/SliderFieldRender.js +359 -0
  481. package/src/ui/components/form/fields/StringFieldRender.js +6 -0
  482. package/src/ui/components/form/fields/TelFieldRender.js +6 -0
  483. package/src/ui/components/form/fields/TextAreaFieldRender.js +96 -0
  484. package/src/ui/components/form/fields/TimeFieldRender.js +142 -0
  485. package/src/ui/components/form/fields/UrlFieldRender.js +6 -0
  486. package/src/ui/components/form/fields/date-field.css +32 -0
  487. package/src/ui/components/form/fields/field.css +402 -0
  488. package/src/ui/components/form/fields/file-field.css +79 -0
  489. package/src/ui/components/form/fields/password-field.css +50 -0
  490. package/src/ui/components/form/fields/range-field.css +120 -0
  491. package/src/ui/components/form/fields/slider.css +195 -0
  492. package/src/ui/components/form/file-upload-mode/FileAvatarModeRender.js +143 -0
  493. package/src/ui/components/form/file-upload-mode/FileDropzoneModeRender.js +108 -0
  494. package/src/ui/components/form/file-upload-mode/FileNativeModeRender.js +22 -0
  495. package/src/ui/components/form/file-upload-mode/FileUploadButtonModeRender.js +89 -0
  496. package/src/ui/components/form/file-upload-mode/FileWallModeRender.js +90 -0
  497. package/src/ui/components/form/file-upload-mode/file-avatar-mode.css +139 -0
  498. package/src/ui/components/form/file-upload-mode/file-dropzone-mode.css +88 -0
  499. package/src/ui/components/form/file-upload-mode/file-upload-button-mode.css +44 -0
  500. package/src/ui/components/form/file-upload-mode/file-wall-mode.css +88 -0
  501. package/src/ui/components/form/form-control.css +40 -0
  502. package/src/ui/components/form/helpers.js +111 -0
  503. package/src/ui/components/form/index.js +27 -0
  504. package/src/ui/components/list/ListRender.js +18 -0
  505. package/src/ui/components/list/divider/ListDividerRender.js +10 -0
  506. package/src/ui/components/list/divider/list-divider.css +12 -0
  507. package/src/ui/components/list/group/ListGroupRender.js +61 -0
  508. package/src/ui/components/list/group/list-group.css +62 -0
  509. package/src/ui/components/list/item/ListItemRender.js +238 -0
  510. package/src/ui/components/list/item/list-item.css +191 -0
  511. package/src/ui/components/list/list.css +24 -0
  512. package/src/ui/components/menu/MenuDividerRender.js +12 -0
  513. package/src/ui/components/menu/MenuGroupRender.js +59 -0
  514. package/src/ui/components/menu/MenuItemRender.js +57 -0
  515. package/src/ui/components/menu/MenuLinkRender.js +55 -0
  516. package/src/ui/components/menu/MenuRender.js +22 -0
  517. package/src/ui/components/menu/helpers.js +121 -0
  518. package/src/ui/components/menu/menu.css +308 -0
  519. package/src/ui/components/modal/ModalRender.js +118 -0
  520. package/src/ui/components/modal/modal.css +156 -0
  521. package/src/ui/components/pagination/PaginationRender.js +112 -0
  522. package/src/ui/components/pagination/pagination.css +63 -0
  523. package/src/ui/components/popover/PopoverRender.js +233 -0
  524. package/src/ui/components/popover/popover.css +139 -0
  525. package/src/ui/components/progress/ProgressRender.js +168 -0
  526. package/src/ui/components/progress/progress.css +197 -0
  527. package/src/ui/components/skeleton/SkeletonRender.js +136 -0
  528. package/src/ui/components/skeleton/skeleton.css +154 -0
  529. package/src/ui/components/spacer/SpacerRender.js +10 -0
  530. package/src/ui/components/spinner/SpinnerRender.js +47 -0
  531. package/src/ui/components/spinner/spinner.css +152 -0
  532. package/src/ui/components/splitter/SplitterGutterRender.js +94 -0
  533. package/src/ui/components/splitter/SplitterPanelRender.js +38 -0
  534. package/src/ui/components/splitter/SplitterRender.js +75 -0
  535. package/src/ui/components/splitter/splitter.css +128 -0
  536. package/src/ui/components/stacks/PositionStackRender.js +39 -0
  537. package/src/ui/components/stacks/StackRender.js +41 -0
  538. package/src/ui/components/stacks/absolute-stack/AbsoluteStackRender.js +5 -0
  539. package/src/ui/components/stacks/fixed-stack/FixedStackRender.js +5 -0
  540. package/src/ui/components/stacks/h-stack/HStackRender.js +7 -0
  541. package/src/ui/components/stacks/h-stack/h-stack.css +4 -0
  542. package/src/ui/components/stacks/index.js +5 -0
  543. package/src/ui/components/stacks/position-stack.css +62 -0
  544. package/src/ui/components/stacks/relative-stack/RelativeStackRender.js +7 -0
  545. package/src/ui/components/stacks/relative-stack/relative-stack.css +3 -0
  546. package/src/ui/components/stacks/stack.css +78 -0
  547. package/src/ui/components/stacks/v-stack/VStackRender.js +6 -0
  548. package/src/ui/components/stacks/v-stack/v-stack.css +4 -0
  549. package/src/ui/components/stepper/StepperRender.js +71 -0
  550. package/src/ui/components/stepper/StepperStepRender.js +67 -0
  551. package/src/ui/components/stepper/stepper.css +359 -0
  552. package/src/ui/components/switch/SwitchRender.js +83 -0
  553. package/src/ui/components/switch/switch.css +143 -0
  554. package/src/ui/components/table/data-table/DataTableRender.js +50 -0
  555. package/src/ui/components/table/data-table/bulk-actions.js +34 -0
  556. package/src/ui/components/table/data-table/data-table.css +246 -0
  557. package/src/ui/components/table/data-table/pagination.js +56 -0
  558. package/src/ui/components/table/data-table/tables.js +368 -0
  559. package/src/ui/components/table/data-table/toolbar.js +67 -0
  560. package/src/ui/components/table/simple-table/SimpleTableRender.js +203 -0
  561. package/src/ui/components/table/simple-table/simple-table.css +50 -0
  562. package/src/ui/components/tabs/TabsRender.js +226 -0
  563. package/src/ui/components/tabs/tabs.css +253 -0
  564. package/src/ui/components/toast/ToastRender.js +99 -0
  565. package/src/ui/components/toast/toast.css +201 -0
  566. package/src/ui/components/tooltip/TooltipRender.js +8 -0
  567. package/src/ui/components/tooltip/tooltip.css +113 -0
  568. package/src/ui/index.js +47 -0
  569. package/src/ui/theme.js +0 -0
  570. package/src/ui/theme.scss +1 -0
  571. package/src/ui/tokens/animation.scss +36 -0
  572. package/src/ui/tokens/colors-dark.scss +58 -0
  573. package/src/ui/tokens/colors.scss +54 -0
  574. package/src/ui/tokens/components.scss +32 -0
  575. package/src/ui/tokens/fonts.scss +57 -0
  576. package/src/ui/tokens/glass.scss +10 -0
  577. package/src/ui/tokens/index.scss +38 -0
  578. package/src/ui/tokens/layouts.scss +228 -0
  579. package/src/ui/tokens/opacity.scss +21 -0
  580. package/src/ui/tokens/others.scss +11 -0
  581. package/src/ui/tokens/radius.scss +6 -0
  582. package/src/ui/tokens/reset.scss +51 -0
  583. package/src/ui/tokens/shadows.scss +29 -0
  584. package/src/ui/tokens/spacings.scss +13 -0
  585. package/src/ui/tokens/vars.scss +35 -0
  586. package/src/ui/tokens/viewports.scss +30 -0
  587. package/types/args-types.d.ts +58 -0
  588. package/types/control-flow.d.ts +62 -0
  589. package/types/elements.d.ts +231 -0
  590. package/types/filters/dates.d.ts +43 -0
  591. package/types/filters/index.d.ts +4 -0
  592. package/types/filters/standard.d.ts +70 -0
  593. package/types/filters/strings.d.ts +21 -0
  594. package/types/filters/types.d.ts +20 -0
  595. package/types/forms.d.ts +84 -0
  596. package/types/globals.d.ts +543 -0
  597. package/types/images.d.ts +23 -0
  598. package/types/localStorage.ts +102 -0
  599. package/types/memoize.d.ts +26 -0
  600. package/types/native-fetch.d.ts +72 -0
  601. package/types/nd-element.d.ts +407 -0
  602. package/types/observable-resource.d.ts +3 -0
  603. package/types/observable.d.ts +227 -0
  604. package/types/plugins-manager.d.ts +65 -0
  605. package/types/polyfill.d.ts +18 -0
  606. package/types/property-accumulator.d.ts +33 -0
  607. package/types/router.d.ts +85 -0
  608. package/types/service.d.ts +23 -0
  609. package/types/singleton.d.ts +19 -0
  610. package/types/store.d.ts +63 -0
  611. package/types/template-cloner.ts +43 -0
  612. package/types/validator.ts +66 -0
  613. package/ui.js +1 -0
  614. package/utils.d.ts +4 -0
  615. package/utils.js +12 -0
  616. package/src/data/Observable.js +0 -233
  617. package/src/data/ObservableChecker.js +0 -38
  618. package/src/data/ObservableItem.js +0 -116
  619. package/src/data/Store.js +0 -74
  620. package/src/elements/anchor.js +0 -84
  621. package/src/elements/content-formatter.js +0 -32
  622. package/src/elements/control/for-each.js +0 -174
  623. package/src/elements/control/show-if.js +0 -79
  624. package/src/elements/control/switch.js +0 -98
  625. package/src/elements/description-list.js +0 -5
  626. package/src/elements/form.js +0 -71
  627. package/src/elements/html5-semantics.js +0 -12
  628. package/src/elements/img.js +0 -45
  629. package/src/elements/interactive.js +0 -7
  630. package/src/elements/list.js +0 -6
  631. package/src/elements/medias.js +0 -8
  632. package/src/elements/meta-data.js +0 -9
  633. package/src/elements/table.js +0 -14
  634. package/src/utils/args-types.js +0 -100
  635. package/src/utils/debug-manager.js +0 -31
  636. package/src/utils/helpers.js +0 -37
  637. package/src/utils/plugins-manager.js +0 -12
  638. package/src/utils/prototypes.js +0 -45
  639. package/src/wrappers/AttributesWrapper.js +0 -157
  640. package/src/wrappers/DocumentObserver.js +0 -51
  641. package/src/wrappers/HtmlElementEventsWrapper.js +0 -77
  642. package/src/wrappers/HtmlElementWrapper.js +0 -206
  643. package/src/wrappers/constants.js +0 -2
@@ -0,0 +1,387 @@
1
+ ---
2
+ title: List Rendering
3
+ description: Efficiently render dynamic collections with ForEach and ForEachArray - automatic DOM updates, keyed diffing, and reactive filtering
4
+ ---
5
+
6
+ # List Rendering
7
+
8
+ NativeDocument provides two functions for rendering dynamic collections: `ForEach` for generic iteration over arrays and objects, and `ForEachArray` for high-performance array-specific operations.
9
+
10
+ ```javascript
11
+ import { ForEach, ForEachArray } from 'native-document/elements';
12
+ ```
13
+
14
+ ---
15
+
16
+ ## `ForEach` - Generic Collection Rendering
17
+
18
+ `ForEach` works with both observable arrays and observable objects.
19
+
20
+ ```javascript
21
+ ForEach(data, callback, key?, options?)
22
+ ```
23
+
24
+ ### Array iteration
25
+
26
+ ```javascript
27
+ const fruits = Observable.array(['Apple', 'Banana', 'Cherry']);
28
+
29
+ Ul(
30
+ ForEach(fruits, fruit => Li(fruit))
31
+ )
32
+
33
+ // All array operations trigger DOM updates
34
+ fruits.push('Orange');
35
+ fruits.splice(1, 1);
36
+ fruits.sort();
37
+ ```
38
+
39
+ ### Object iteration
40
+
41
+ ```javascript
42
+ const roles = Observable({
43
+ admin: 'Administrator',
44
+ editor: 'Content Editor',
45
+ viewer: 'Read Only'
46
+ });
47
+
48
+ Ul(
49
+ ForEach(roles, (roleName, roleKey) =>
50
+ Li([Strong(roleKey), ': ', roleName])
51
+ )
52
+ )
53
+ ```
54
+
55
+ ### Index parameter
56
+
57
+ The second callback argument is an **observable** tracking the item's current index:
58
+
59
+ ```javascript
60
+ const tasks = Observable.array(['Review PRs', 'Update docs', 'Fix bugs']);
61
+
62
+ Ol(ForEach(tasks, (task, index) =>
63
+ Li([
64
+ Strong(index.transform(i => i + 1)), '. ',
65
+ task,
66
+ Button('Remove').nd.onClick(() => tasks.remove(index.val()))
67
+ ])
68
+ ))
69
+ ```
70
+
71
+ ### Key function
72
+
73
+ Use a key to help NativeDocument identify items for efficient reordering. Pass a property name string or a function:
74
+
75
+ ```javascript
76
+ const users = Observable.array([
77
+ { id: 1, name: 'Alice', role: 'admin' },
78
+ { id: 2, name: 'Bob', role: 'user' }
79
+ ]);
80
+
81
+ // Property name shorthand
82
+ ForEach(users, user => Div(user.name), 'id')
83
+
84
+ // Function
85
+ ForEach(users, user => Div(user.name), item => item.id)
86
+ ```
87
+
88
+ ### Options
89
+
90
+ ```javascript
91
+ ForEach(data, callback, key, { shouldKeepItemsInCache: true })
92
+ ```
93
+
94
+ `shouldKeepItemsInCache` - when `true`, rendered items stay in cache even when removed. Useful when items toggle frequently:
95
+
96
+ ```javascript
97
+ // Items are cached - re-adding won't re-render them
98
+ ForEach(items, renderItem, 'id', { shouldKeepItemsInCache: true })
99
+ ```
100
+
101
+ ---
102
+
103
+ ## `ForEachArray` - High-Performance Array Rendering
104
+
105
+ `ForEachArray` is specifically optimized for arrays of objects. Use it when performance matters.
106
+
107
+ ```javascript
108
+ ForEachArray(data, callback, configs?)
109
+ ```
110
+
111
+ ```javascript
112
+ const messages = Observable.array([
113
+ { id: 1, text: 'Hello!', timestamp: Date.now() },
114
+ { id: 2, text: 'How are you?', timestamp: Date.now() + 1000 }
115
+ ]);
116
+
117
+ Div({ class: 'chat' },
118
+ ForEachArray(messages, message =>
119
+ Div({ class: 'message' }, [
120
+ Div(message.text),
121
+ Div(new Date(message.timestamp).toLocaleTimeString())
122
+ ])
123
+ )
124
+ )
125
+ ```
126
+
127
+ ### Index in `ForEachArray`
128
+
129
+ The index is a **computed observable** derived from the array - always reactive, no need to call `.val()` to use it in the DOM:
130
+
131
+ ```javascript
132
+ ForEachArray(playlist, (song, index) =>
133
+ Div([
134
+ index.transform(i => i + 1), '. ',
135
+ song.title,
136
+ Button('Up').nd.onClick(() => {
137
+ const i = index.$value;
138
+ if (i > 0) {
139
+ playlist.swap(i, i - 1);
140
+ }
141
+ }),
142
+ Button('Down').nd.onClick(() => {
143
+ const i = index.$value;
144
+ if (i < playlist.val().length - 1) {
145
+ playlist.swap(i, i + 1);
146
+ }
147
+ }),
148
+ Button('Remove').nd.onClick(() => playlist.remove(index.$value))
149
+ ])
150
+ )
151
+ ```
152
+
153
+ ### Configs
154
+
155
+ ```javascript
156
+ ForEachArray(data, callback, {
157
+ shouldKeepItemsInCache: false, // same as ForEach
158
+ pushDelay: (items) => items.length > 100 ? 50 : 0 // throttle large batch inserts
159
+ })
160
+ ```
161
+
162
+ ---
163
+
164
+ ## Choosing Between `ForEach` and `ForEachArray`
165
+
166
+ | | `ForEach` | `ForEachArray` |
167
+ |---|---|---|
168
+ | Arrays of objects | yes | yes (optimized) |
169
+ | Arrays of primitives | yes | yes |
170
+ | Object (non-array) iteration | yes | no |
171
+ | Index is observable | yes | yes (computed) |
172
+ | Key argument | third arg (string/fn) | inside configs |
173
+ | Best for | objects, primitives, small lists | large or frequently updated arrays |
174
+
175
+ ---
176
+
177
+ ## Filtering with `.where()`
178
+
179
+ `.where()` is available on `ObservableArray` only. It returns a new live `ObservableArray` that re-filters automatically. See [Observables](./observables.md) for the full `.where()` reference.
180
+
181
+ ```javascript
182
+ import { equals, greaterThan, lessThan, between, includes, match,
183
+ startsWith, endsWith, inArray, notIn, custom,
184
+ and, or, not } from 'native-document/filters';
185
+
186
+ const products = Observable.array([
187
+ { id: 1, name: 'Phone', price: 599, inStock: true, category: 'electronics' },
188
+ { id: 2, name: 'Laptop', price: 999, inStock: false, category: 'electronics' },
189
+ { id: 3, name: 'Book', price: 29, inStock: true, category: 'books' }
190
+ ]);
191
+ ```
192
+
193
+ ### Comparison
194
+
195
+ ```javascript
196
+ products.where({ price: greaterThan(500) })
197
+ products.where({ price: lessThan(100) })
198
+ products.where({ price: between(200, 800) })
199
+ products.where({ inStock: equals(true) })
200
+ products.where({ name: notEquals('Phone') })
201
+ ```
202
+
203
+ ### String
204
+
205
+ ```javascript
206
+ products.where({ name: includes('phone') }) // case-insensitive by default
207
+ products.where({ name: startsWith('P') })
208
+ products.where({ name: endsWith('book') })
209
+ products.where({ name: match(/^[A-Z]/) }) // regex
210
+ products.where({ name: match('lap', false) }) // plain string, no regex
211
+ ```
212
+
213
+ ### Array membership
214
+
215
+ ```javascript
216
+ const allowed = Observable.array(['electronics', 'books']);
217
+
218
+ products.where({ category: inArray(allowed) }) // reactive
219
+ products.where({ category: notIn(['clothing']) })
220
+ ```
221
+
222
+ ### Reactive filters
223
+
224
+ Pass an observable as the filter value - re-filters automatically when it changes:
225
+
226
+ ```javascript
227
+ const search = Observable('');
228
+ const minPrice = Observable(0);
229
+ const maxPrice = Observable(1000);
230
+
231
+ const filtered = products.where({
232
+ name: includes(search),
233
+ price: between(minPrice, maxPrice)
234
+ });
235
+ ```
236
+
237
+ ### Custom filter
238
+
239
+ ```javascript
240
+ const minRating = Observable(4);
241
+
242
+ products.where({
243
+ _: custom((product, min) => {
244
+ return product.rating >= min && product.reviews > 10;
245
+ }, minRating) // observables passed as extra args
246
+ })
247
+ ```
248
+
249
+ ### Combining
250
+
251
+ ```javascript
252
+ // and - field must pass ALL conditions
253
+ products.where({ price: and(greaterThan(100), lessThan(500)) })
254
+
255
+ // or - field must pass AT LEAST ONE
256
+ products.where({ category: or(equals('electronics'), equals('books')) })
257
+
258
+ // not - invert
259
+ products.where({ inStock: not(equals(true)) })
260
+
261
+ // cross-field - use _ key with plain function
262
+ products.where({
263
+ _: item => item.inStock && item.price < 500
264
+ })
265
+ ```
266
+
267
+ ### Date and time filters
268
+
269
+ ```javascript
270
+ import { dateEquals, dateBefore, dateAfter, dateBetween,
271
+ timeBefore, timeBetween } from 'native-document/filters';
272
+
273
+ const events = Observable.array([
274
+ { name: 'Meeting', date: '2024-03-15' },
275
+ { name: 'Conference', date: '2024-06-20' }
276
+ ]);
277
+
278
+ events.where({ date: dateAfter(new Date()) })
279
+ events.where({ date: dateBetween('2024-06-01', '2024-08-31') })
280
+ events.where({ date: timeBetween(
281
+ new Date('2024-01-01 09:00:00'),
282
+ new Date('2024-01-01 17:00:00')
283
+ )})
284
+ ```
285
+
286
+ ---
287
+
288
+ ## Common Patterns
289
+
290
+ ### Empty state
291
+
292
+ ```javascript
293
+ const items = Observable.array([]);
294
+
295
+ Div([
296
+ ShowIf(items.isEmpty(), Div({ class: 'empty' }, 'No items yet')),
297
+ ForEachArray(items, item => ItemComponent(item))
298
+ ])
299
+ ```
300
+
301
+ ### Search + filter
302
+
303
+ ```javascript
304
+ const search = Observable('');
305
+ const category = Observable('all');
306
+
307
+ const filtered = products.where({
308
+ name: includes(search),
309
+ category: or(equals('all'), equals(category))
310
+ });
311
+
312
+ Div([
313
+ Input({ placeholder: 'Search...', value: search }),
314
+ ForEachArray(filtered, product => ProductCard(product))
315
+ ])
316
+ ```
317
+
318
+ ### Drag-and-drop reordering
319
+
320
+ ```javascript
321
+ let draggedIndex = null;
322
+
323
+ ForEachArray(items, (item, index) =>
324
+ Div({ class: 'item', draggable: true }, item.text)
325
+ .nd
326
+ .onDragStart(() => { draggedIndex = index.$value; })
327
+ .onDragOver(e => e.preventDefault())
328
+ .onDrop(e => {
329
+ e.preventDefault();
330
+ const dropIndex = index.$value;
331
+ if (draggedIndex !== null && draggedIndex !== dropIndex) {
332
+ items.swap(draggedIndex, dropIndex);
333
+ }
334
+ draggedIndex = null;
335
+ })
336
+ )
337
+ ```
338
+
339
+ ### Infinite scroll
340
+
341
+ ```javascript
342
+ const items = Observable.array([]);
343
+ const isLoading = Observable(false);
344
+ const hasMore = Observable(true);
345
+
346
+ const loadMore = async () => {
347
+ if (isLoading.val()) return;
348
+ isLoading.set(true);
349
+ const next = await fetchItems(items.val().length);
350
+ next.length ? items.merge(next) : hasMore.set(false);
351
+ isLoading.set(false);
352
+ };
353
+
354
+ Div([
355
+ ForEachArray(items, item => ItemComponent(item)),
356
+ ShowIf(isLoading.isTruthy(), Div('Loading...')),
357
+ ShowIf(hasMore.isTruthy(),
358
+ Button('Load more').nd.onClick(loadMore)
359
+ )
360
+ ])
361
+ ```
362
+
363
+ ---
364
+
365
+ ## Best Practices
366
+
367
+ 1. Use `ForEachArray` for arrays of objects - it's optimized for that case
368
+ 2. Use `ForEach` for objects (non-array) and arrays of primitives
369
+ 3. Always pass a key when items can be reordered - avoids unnecessary re-rendering
370
+ 4. Use `.where()` for filtering instead of filtering inside the callback
371
+ 5. Use `shouldKeepItemsInCache: true` when items toggle in and out frequently
372
+ 6. Never mutate `.val()` directly - use observable array methods (`push`, `splice`, `swap`, etc.)
373
+
374
+ ---
375
+
376
+ ## Next Steps
377
+
378
+ - **[Conditional Rendering](./conditional-rendering.md)** - ShowIf, Match, Switch
379
+ - **[Observables](./observables.md)** - Observable arrays and `.where()` in depth
380
+ - **[Advanced Components](./advanced-components.md)** - `ForEachArray` with `useCache`
381
+ - **[Filters](./filters.md)** - Full filter reference
382
+
383
+ ## Utilities
384
+
385
+ - **[Cache](./cache.md)** - Lazy initialization and singleton patterns
386
+ - **[NativeFetch](./native-fetch.md)** - HTTP client with interceptors
387
+ - **[Filters](./filters.md)** - Data filtering helpers
@@ -1,90 +1,179 @@
1
- # Memory Management
1
+ ---
2
+ title: Memory Management
3
+ description: NativeDocument's automatic memory management system using WeakRef and FinalizationRegistry - how it works and how to control it
4
+ ---
2
5
 
3
- NativeDocument includes an advanced automatic memory management system that prevents memory leaks and optimizes performance using modern browser APIs like FinalizationRegistry.
6
+ # Memory Management
4
7
 
5
- ## Automatic Observable Cleanup
8
+ NativeDocument includes an automatic memory management system that prevents memory leaks using modern browser APIs - `WeakRef` and `FinalizationRegistry`. In most cases you don't need to think about this at all.
6
9
 
7
- ### How It Works
10
+ ---
8
11
 
9
- ```javascript
10
- const data = Observable("test");
12
+ ## How It Works
11
13
 
12
- // When 'data' goes out of scope and is garbage collected,
13
- // NativeDocument automatically cleans up its internal listeners
14
- // No manual cleanup required!
14
+ Every observable is registered in the `MemoryManager` using a `WeakRef`. When an observable goes out of scope and is garbage collected, the `FinalizationRegistry` notifies the system and the entry is cleaned up automatically.
15
15
 
16
+ ```javascript
16
17
  function createComponent() {
17
18
  const localObservable = Observable(42);
18
- return Div(localObservable); // Observable auto-cleaned when component is GC'd
19
+ return Div(localObservable);
20
+ // When the component is removed and localObservable goes out of scope,
21
+ // MemoryManager cleans up its entry automatically via FinalizationRegistry
19
22
  }
20
23
  ```
21
24
 
22
- ### Memory Registry System
25
+ Each observable gets an internal numeric ID on creation, accessible via `Observable.getById()`. Note that `.toString()` now returns the current value as a string, not the internal ID:
23
26
 
24
27
  ```javascript
25
- // Each observable is automatically registered for cleanup
26
- const count = Observable(0);
27
- console.log(count.toString()); // "{{#ObItem::(1)}}" - Shows internal ID
28
-
29
- // When count becomes unreachable, cleanup happens automatically
30
- // via FinalizationRegistry
28
+ const count = Observable(42);
29
+ console.log(count.toString()); // "42" - current value as string
31
30
  ```
32
31
 
33
- ## Manual Memory Management
32
+ ---
34
33
 
35
- ### Force Cleanup
34
+ ## Manual Cleanup
35
+
36
+ ### `observable.cleanup()`
37
+
38
+ Removes all listeners from an observable immediately and prevents new subscriptions:
36
39
 
37
40
  ```javascript
38
- const obs = Observable("data");
41
+ const obs = Observable('data');
39
42
  const unsubscribe = obs.subscribe(console.log);
40
43
 
41
- // Manual cleanup if needed
42
- obs.cleanup(); // Removes all listeners immediately
43
- // obs is now unusable - will warn on new subscriptions
44
+ obs.cleanup(); // removes all listeners
45
+ // obs is now unusable
46
+ ```
47
+
48
+ ### `observable.onCleanup(callback)`
49
+
50
+ Register a callback that runs when the observable is cleaned up:
51
+
52
+ ```javascript
53
+ const obs = Observable('data');
54
+
55
+ obs.onCleanup(() => {
56
+ console.log('Observable cleaned up');
57
+ });
58
+
59
+ obs.cleanup(); // triggers the callback
44
60
  ```
45
61
 
46
- ### Global Cleanup
62
+ ### `Observable.cleanup(observable)`
63
+
64
+ Static alias for `observable.cleanup()`:
47
65
 
48
66
  ```javascript
49
- // Clean all orphaned observables
50
- Observable.cleanup(); // Force cleanup of all registered observables
67
+ Observable.cleanup(myObservable);
68
+ ```
51
69
 
52
- // Auto-cleanup configuration
70
+ ---
71
+
72
+ ## Auto-Cleanup
73
+
74
+ ### `Observable.autoCleanup(enable, options?)`
75
+
76
+ Enables automatic periodic cleanup of orphaned observables (those that have been garbage collected but whose `WeakRef` entries remain in the registry):
77
+
78
+ ```javascript
53
79
  Observable.autoCleanup(true, {
54
- interval: 60000, // Check every minute
55
- threshold: 100 // Clean when 100+ orphaned observables
80
+ interval: 60000, // run cleanup every 60 seconds (default)
81
+ threshold: 100 // only run when more than 100 entries exist (default)
56
82
  });
57
83
  ```
58
84
 
59
- ## Performance Monitoring
85
+ Use this in long-running applications to prevent the registry from growing unbounded.
86
+
87
+ ---
60
88
 
61
- ### Debug Mode
89
+ ## MemoryManager API
90
+
91
+ `MemoryManager` is the internal registry that tracks all observables via `WeakRef`. It is not exported but its behavior is exposed through `Observable` static methods.
92
+
93
+ | Method | Description |
94
+ |---|---|
95
+ | `MemoryManager.register(observable)` | Registers an observable, returns its internal ID |
96
+ | `MemoryManager.unregister(id)` | Removes an observable from the registry |
97
+ | `MemoryManager.getObservableById(id)` | Retrieves an observable by ID (via `Observable.getById()`) |
98
+ | `MemoryManager.cleanup()` | Calls `.cleanup()` on all registered observables and clears the registry |
99
+ | `MemoryManager.cleanObservables(threshold)` | Removes entries for GC'd observables when registry size exceeds threshold |
100
+
101
+ Access `getObservableById` via the public API:
102
+
103
+ ```javascript
104
+ // getById is useful for debugging - the ID is the internal MemoryManager key
105
+ // Access it via Observable.debug tools or the MemoryManager directly
106
+ Observable.getById(1); // returns the first observable registered
107
+ ```
108
+
109
+ ---
110
+
111
+ ## Manual Subscriptions
112
+
113
+ The most common source of memory leaks is forgetting to clean up manual subscriptions. `.subscribe()` does not return an unsubscribe function - use `.cleanup()` to remove all listeners, or `.off()` to remove a specific watcher registered via `.on()`:
62
114
 
63
115
  ```javascript
64
- // Enable memory debugging
65
- NativeDocument.debug.enable();
116
+ const count = Observable(0);
117
+
118
+ // Remove all listeners at once
119
+ count.subscribe(value => console.log('Count:', value));
120
+ count.cleanup();
66
121
 
67
- // Monitor cleanup events in console
68
- const obs = Observable("test");
69
- obs = null; // Will log cleanup when GC runs
122
+ // Remove a specific .on() watcher
123
+ const handler = isActive => console.log('Loading:', isActive);
124
+ count.on('loading', handler);
125
+ count.off('loading', handler);
70
126
  ```
71
127
 
72
- ### Memory Leak Detection
128
+ In element lifecycle hooks, only clean up **external resources**. Do not clean up observables unless the element is permanently destroyed:
73
129
 
74
130
  ```javascript
75
- // Check for potential leaks
76
- window.addEventListener('beforeunload', () => {
77
- // Force cleanup on page unload
78
- });
131
+ Div('Content')
132
+ .nd
133
+ .mounted(el => {
134
+ el.intervalId = setInterval(() => doWork(), 1000);
135
+ })
136
+ .unmounted(el => {
137
+ clearInterval(el.intervalId); // external resource - clean up
138
+ // do NOT call observable.cleanup() here unless permanently destroying
139
+ });
79
140
  ```
80
141
 
142
+ ---
143
+
144
+ ## Debug Mode
145
+
146
+ Enable debug mode during development to log memory-related events:
147
+
148
+ ```javascript
149
+ Observable.debug.enable();
150
+
151
+ // MemoryManager will log when orphaned observables are cleaned:
152
+ // "🧹 Cleaned 3 orphaned observables"
153
+ ```
154
+
155
+ ---
156
+
81
157
  ## Best Practices
82
158
 
83
- 1. **Trust the system** - Let automatic cleanup handle most cases
84
- 2. **Manual cleanup** only for critical resources or immediate needs
85
- 3. **Enable auto-cleanup** in long-running applications
86
- 4. **Use debug mode** during development to monitor memory usage
159
+ 1. Trust the automatic system - `WeakRef` + `FinalizationRegistry` handles most cases
160
+ 2. Always store and call the unsubscribe function for manual subscriptions
161
+ 3. Use `Observable.autoCleanup(true)` in long-running SPAs
162
+ 4. Only call `.cleanup()` manually when you need immediate release of resources
163
+ 5. In `unmounted()` hooks, only clean up external resources (timers, websockets) - not observables
164
+ 6. Use `Observable.resource()` for async data - it handles its own cleanup via `AbortController`
165
+
166
+ ---
87
167
 
88
168
  ## Next Steps
89
169
 
90
- - **[Anchor](docs/anchor.md)** - Anchor
170
+ - **[Observables](./observables.md)** - `cleanup()`, `onCleanup()`, `autoCleanup()`
171
+ - **[Lifecycle Events](./lifecycle-events.md)** - When to clean up in `unmounted()`
172
+ - **[Observable Resource](./observable-resource.md)** - Async data with built-in cleanup
173
+ - **[Anchor](./anchor.md)** - Anchor cleanup
174
+
175
+ ## Utilities
176
+
177
+ - **[Cache](./cache.md)** - Lazy initialization and singleton patterns
178
+ - **[NativeFetch](./native-fetch.md)** - HTTP client with interceptors
179
+ - **[Filters](./filters.md)** - Data filtering helpers