optikos 0.0.0-stage → 0.1.0

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 (430) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +211 -2
  4. package/THIRD_PARTY_NOTICES.md +83 -0
  5. package/dist/bind.js +2 -0
  6. package/dist/bind.js.map +7 -0
  7. package/dist/chunk-2UPUC4RK.js +2 -0
  8. package/dist/chunk-2UPUC4RK.js.map +7 -0
  9. package/dist/chunk-4AA4FQEM.js +2 -0
  10. package/dist/chunk-4AA4FQEM.js.map +7 -0
  11. package/dist/chunk-4C666HHU.js +2 -0
  12. package/dist/chunk-4C666HHU.js.map +7 -0
  13. package/dist/chunk-4COBH4QJ.js +2 -0
  14. package/dist/chunk-4COBH4QJ.js.map +7 -0
  15. package/dist/chunk-4DHQKECB.js +2 -0
  16. package/dist/chunk-4DHQKECB.js.map +7 -0
  17. package/dist/chunk-4Q67QI7J.js +2 -0
  18. package/dist/chunk-4Q67QI7J.js.map +7 -0
  19. package/dist/chunk-4SUKNSCY.js +2 -0
  20. package/dist/chunk-4SUKNSCY.js.map +7 -0
  21. package/dist/chunk-5AXLYDKU.js +2 -0
  22. package/dist/chunk-5AXLYDKU.js.map +7 -0
  23. package/dist/chunk-5GNEFX6F.js +2 -0
  24. package/dist/chunk-5GNEFX6F.js.map +7 -0
  25. package/dist/chunk-5Q6Y6CM4.js +2 -0
  26. package/dist/chunk-5Q6Y6CM4.js.map +7 -0
  27. package/dist/chunk-666O2GKD.js +2 -0
  28. package/dist/chunk-666O2GKD.js.map +7 -0
  29. package/dist/chunk-676AKAGF.js +2 -0
  30. package/dist/chunk-676AKAGF.js.map +7 -0
  31. package/dist/chunk-6NCXO5ZP.js +2 -0
  32. package/dist/chunk-6NCXO5ZP.js.map +7 -0
  33. package/dist/chunk-6NJW7QFD.js +2 -0
  34. package/dist/chunk-6NJW7QFD.js.map +7 -0
  35. package/dist/chunk-6O2BXCRN.js +2 -0
  36. package/dist/chunk-6O2BXCRN.js.map +7 -0
  37. package/dist/chunk-A66MDXHL.js +2 -0
  38. package/dist/chunk-A66MDXHL.js.map +7 -0
  39. package/dist/chunk-ARCW54L2.js +2 -0
  40. package/dist/chunk-ARCW54L2.js.map +7 -0
  41. package/dist/chunk-BIYNHKSA.js +2 -0
  42. package/dist/chunk-BIYNHKSA.js.map +7 -0
  43. package/dist/chunk-BNPVRIFT.js +2 -0
  44. package/dist/chunk-BNPVRIFT.js.map +7 -0
  45. package/dist/chunk-C3N7QTQB.js +2 -0
  46. package/dist/chunk-C3N7QTQB.js.map +7 -0
  47. package/dist/chunk-CEXY5A4T.js +2 -0
  48. package/dist/chunk-CEXY5A4T.js.map +7 -0
  49. package/dist/chunk-CN7USUJR.js +2 -0
  50. package/dist/chunk-CN7USUJR.js.map +7 -0
  51. package/dist/chunk-CQRHNTEX.js +2 -0
  52. package/dist/chunk-CQRHNTEX.js.map +7 -0
  53. package/dist/chunk-CUPAPOKC.js +2 -0
  54. package/dist/chunk-CUPAPOKC.js.map +7 -0
  55. package/dist/chunk-DXO3UJKL.js +2 -0
  56. package/dist/chunk-DXO3UJKL.js.map +7 -0
  57. package/dist/chunk-GZNQPENR.js +2 -0
  58. package/dist/chunk-GZNQPENR.js.map +7 -0
  59. package/dist/chunk-HFFK6K4K.js +2 -0
  60. package/dist/chunk-HFFK6K4K.js.map +7 -0
  61. package/dist/chunk-IHAYOSBR.js +2 -0
  62. package/dist/chunk-IHAYOSBR.js.map +7 -0
  63. package/dist/chunk-IO66A6G5.js +2 -0
  64. package/dist/chunk-IO66A6G5.js.map +7 -0
  65. package/dist/chunk-IW7PK4VS.js +2 -0
  66. package/dist/chunk-IW7PK4VS.js.map +7 -0
  67. package/dist/chunk-IYPKPLCU.js +2 -0
  68. package/dist/chunk-IYPKPLCU.js.map +7 -0
  69. package/dist/chunk-JTYWZMSZ.js +2 -0
  70. package/dist/chunk-JTYWZMSZ.js.map +7 -0
  71. package/dist/chunk-JVEPKW5X.js +2 -0
  72. package/dist/chunk-JVEPKW5X.js.map +7 -0
  73. package/dist/chunk-JZNEB7A7.js +2 -0
  74. package/dist/chunk-JZNEB7A7.js.map +7 -0
  75. package/dist/chunk-K2DGY6MP.js +2 -0
  76. package/dist/chunk-K2DGY6MP.js.map +7 -0
  77. package/dist/chunk-LBCWEWPN.js +2 -0
  78. package/dist/chunk-LBCWEWPN.js.map +7 -0
  79. package/dist/chunk-LEE2FEEL.js +2 -0
  80. package/dist/chunk-LEE2FEEL.js.map +7 -0
  81. package/dist/chunk-LMGCV35W.js +2 -0
  82. package/dist/chunk-LMGCV35W.js.map +7 -0
  83. package/dist/chunk-LV6HXFHU.js +3 -0
  84. package/dist/chunk-LV6HXFHU.js.map +7 -0
  85. package/dist/chunk-MA5BJL3S.js +2 -0
  86. package/dist/chunk-MA5BJL3S.js.map +7 -0
  87. package/dist/chunk-NDBFYIL6.js +2 -0
  88. package/dist/chunk-NDBFYIL6.js.map +7 -0
  89. package/dist/chunk-NHVEP72K.js +2 -0
  90. package/dist/chunk-NHVEP72K.js.map +7 -0
  91. package/dist/chunk-NV5AIBQP.js +2 -0
  92. package/dist/chunk-NV5AIBQP.js.map +7 -0
  93. package/dist/chunk-NWTTHDIM.js +2 -0
  94. package/dist/chunk-NWTTHDIM.js.map +7 -0
  95. package/dist/chunk-O4DCHALR.js +2 -0
  96. package/dist/chunk-O4DCHALR.js.map +7 -0
  97. package/dist/chunk-ODWPBBVL.js +2 -0
  98. package/dist/chunk-ODWPBBVL.js.map +7 -0
  99. package/dist/chunk-OW2ZSMGS.js +2 -0
  100. package/dist/chunk-OW2ZSMGS.js.map +7 -0
  101. package/dist/chunk-OWEQT2HN.js +2 -0
  102. package/dist/chunk-OWEQT2HN.js.map +7 -0
  103. package/dist/chunk-PSPQH35P.js +2 -0
  104. package/dist/chunk-PSPQH35P.js.map +7 -0
  105. package/dist/chunk-PZSHOSOS.js +2 -0
  106. package/dist/chunk-PZSHOSOS.js.map +7 -0
  107. package/dist/chunk-QEQIJAAB.js +2 -0
  108. package/dist/chunk-QEQIJAAB.js.map +7 -0
  109. package/dist/chunk-SNTHW4K2.js +2 -0
  110. package/dist/chunk-SNTHW4K2.js.map +7 -0
  111. package/dist/chunk-T4OYVG2X.js +2 -0
  112. package/dist/chunk-T4OYVG2X.js.map +7 -0
  113. package/dist/chunk-TBLICXWW.js +2 -0
  114. package/dist/chunk-TBLICXWW.js.map +7 -0
  115. package/dist/chunk-TK2RC3T5.js +2 -0
  116. package/dist/chunk-TK2RC3T5.js.map +7 -0
  117. package/dist/chunk-U3X2FW6U.js +2 -0
  118. package/dist/chunk-U3X2FW6U.js.map +7 -0
  119. package/dist/chunk-UPOBGNJ5.js +2 -0
  120. package/dist/chunk-UPOBGNJ5.js.map +7 -0
  121. package/dist/chunk-VV7CFMPZ.js +2 -0
  122. package/dist/chunk-VV7CFMPZ.js.map +7 -0
  123. package/dist/chunk-X2ASKUFD.js +2 -0
  124. package/dist/chunk-X2ASKUFD.js.map +7 -0
  125. package/dist/chunk-X6AULZI4.js +1 -0
  126. package/dist/chunk-X6AULZI4.js.map +7 -0
  127. package/dist/chunk-XVIC24AW.js +2 -0
  128. package/dist/chunk-XVIC24AW.js.map +7 -0
  129. package/dist/chunk-XZ5CUZZP.js +2 -0
  130. package/dist/chunk-XZ5CUZZP.js.map +7 -0
  131. package/dist/chunk-XZEOSW3Q.js +2 -0
  132. package/dist/chunk-XZEOSW3Q.js.map +7 -0
  133. package/dist/chunk-YET5PM6F.js +2 -0
  134. package/dist/chunk-YET5PM6F.js.map +7 -0
  135. package/dist/chunk-Z25NC4CS.js +2 -0
  136. package/dist/chunk-Z25NC4CS.js.map +7 -0
  137. package/dist/chunk-ZCAAM4NH.js +2 -0
  138. package/dist/chunk-ZCAAM4NH.js.map +7 -0
  139. package/dist/chunk-ZHVSHDLH.js +2 -0
  140. package/dist/chunk-ZHVSHDLH.js.map +7 -0
  141. package/dist/chunk-ZYUXCZX7.js +2 -0
  142. package/dist/chunk-ZYUXCZX7.js.map +7 -0
  143. package/dist/components/breadcrumb.js +2 -0
  144. package/dist/components/breadcrumb.js.map +7 -0
  145. package/dist/components/button.js +2 -0
  146. package/dist/components/button.js.map +7 -0
  147. package/dist/components/calendar.js +2 -0
  148. package/dist/components/calendar.js.map +7 -0
  149. package/dist/components/chat.js +2 -0
  150. package/dist/components/chat.js.map +7 -0
  151. package/dist/components/checkbox.js +2 -0
  152. package/dist/components/checkbox.js.map +7 -0
  153. package/dist/components/combobox.js +2 -0
  154. package/dist/components/combobox.js.map +7 -0
  155. package/dist/components/commandpalette.js +2 -0
  156. package/dist/components/commandpalette.js.map +7 -0
  157. package/dist/components/container.js +2 -0
  158. package/dist/components/container.js.map +7 -0
  159. package/dist/components/dataview.js +2 -0
  160. package/dist/components/dataview.js.map +7 -0
  161. package/dist/components/datefield.js +2 -0
  162. package/dist/components/datefield.js.map +7 -0
  163. package/dist/components/daterangefield.js +2 -0
  164. package/dist/components/daterangefield.js.map +7 -0
  165. package/dist/components/dropdown.js +2 -0
  166. package/dist/components/dropdown.js.map +7 -0
  167. package/dist/components/fieldset.js +2 -0
  168. package/dist/components/fieldset.js.map +7 -0
  169. package/dist/components/filterbuilder.js +2 -0
  170. package/dist/components/filterbuilder.js.map +7 -0
  171. package/dist/components/form.js +2 -0
  172. package/dist/components/form.js.map +7 -0
  173. package/dist/components/grid.js +2 -0
  174. package/dist/components/grid.js.map +7 -0
  175. package/dist/components/icon.js +2 -0
  176. package/dist/components/icon.js.map +7 -0
  177. package/dist/components/label.js +2 -0
  178. package/dist/components/label.js.map +7 -0
  179. package/dist/components/listbox.js +2 -0
  180. package/dist/components/listbox.js.map +7 -0
  181. package/dist/components/lookupfield.js +2 -0
  182. package/dist/components/lookupfield.js.map +7 -0
  183. package/dist/components/menu.js +2 -0
  184. package/dist/components/menu.js.map +7 -0
  185. package/dist/components/messagebox.js +2 -0
  186. package/dist/components/messagebox.js.map +7 -0
  187. package/dist/components/navmenu.js +2 -0
  188. package/dist/components/navmenu.js.map +7 -0
  189. package/dist/components/numberfield.js +2 -0
  190. package/dist/components/numberfield.js.map +7 -0
  191. package/dist/components/pagination.js +2 -0
  192. package/dist/components/pagination.js.map +7 -0
  193. package/dist/components/panel.js +2 -0
  194. package/dist/components/panel.js.map +7 -0
  195. package/dist/components/pickerfield.js +2 -0
  196. package/dist/components/pickerfield.js.map +7 -0
  197. package/dist/components/radiogroup.js +2 -0
  198. package/dist/components/radiogroup.js.map +7 -0
  199. package/dist/components/searchgrid.js +2 -0
  200. package/dist/components/searchgrid.js.map +7 -0
  201. package/dist/components/secretfield.js +2 -0
  202. package/dist/components/secretfield.js.map +7 -0
  203. package/dist/components/select.js +2 -0
  204. package/dist/components/select.js.map +7 -0
  205. package/dist/components/slider.js +2 -0
  206. package/dist/components/slider.js.map +7 -0
  207. package/dist/components/spacer.js +2 -0
  208. package/dist/components/spacer.js.map +7 -0
  209. package/dist/components/spinner.js +2 -0
  210. package/dist/components/spinner.js.map +7 -0
  211. package/dist/components/stepform.js +2 -0
  212. package/dist/components/stepform.js.map +7 -0
  213. package/dist/components/stepper.js +2 -0
  214. package/dist/components/stepper.js.map +7 -0
  215. package/dist/components/suggestfield.js +2 -0
  216. package/dist/components/suggestfield.js.map +7 -0
  217. package/dist/components/table.js +2 -0
  218. package/dist/components/table.js.map +7 -0
  219. package/dist/components/tabs.js +2 -0
  220. package/dist/components/tabs.js.map +7 -0
  221. package/dist/components/textarea.js +2 -0
  222. package/dist/components/textarea.js.map +7 -0
  223. package/dist/components/textfield.js +2 -0
  224. package/dist/components/textfield.js.map +7 -0
  225. package/dist/components/toast.js +2 -0
  226. package/dist/components/toast.js.map +7 -0
  227. package/dist/components/toolbar.js +2 -0
  228. package/dist/components/toolbar.js.map +7 -0
  229. package/dist/components/tooltip.js +2 -0
  230. package/dist/components/tooltip.js.map +7 -0
  231. package/dist/components/viewmanager.js +2 -0
  232. package/dist/components/viewmanager.js.map +7 -0
  233. package/dist/components/viewport.js +2 -0
  234. package/dist/components/viewport.js.map +7 -0
  235. package/dist/components/widget.js +2 -0
  236. package/dist/components/widget.js.map +7 -0
  237. package/dist/components/window.js +2 -0
  238. package/dist/components/window.js.map +7 -0
  239. package/dist/core.js +2 -0
  240. package/dist/core.js.map +7 -0
  241. package/dist/css/base.css +160 -0
  242. package/dist/css/breadcrumb.css +53 -0
  243. package/dist/css/button.css +101 -0
  244. package/dist/css/calendar.css +108 -0
  245. package/dist/css/chat.css +233 -0
  246. package/dist/css/checkbox.css +64 -0
  247. package/dist/css/commandpalette.css +167 -0
  248. package/dist/css/container.css +5 -0
  249. package/dist/css/core.css +88 -0
  250. package/dist/css/dataview.css +56 -0
  251. package/dist/css/dropdown.css +13 -0
  252. package/dist/css/field.css +62 -0
  253. package/dist/css/fieldset.css +32 -0
  254. package/dist/css/filterbuilder.css +125 -0
  255. package/dist/css/form.css +8 -0
  256. package/dist/css/grid.css +367 -0
  257. package/dist/css/icon.css +16 -0
  258. package/dist/css/label.css +12 -0
  259. package/dist/css/layout.css +116 -0
  260. package/dist/css/listbox.css +50 -0
  261. package/dist/css/menu.css +47 -0
  262. package/dist/css/messagebox.css +6 -0
  263. package/dist/css/motion.css +29 -0
  264. package/dist/css/navmenu.css +115 -0
  265. package/dist/css/pagination.css +23 -0
  266. package/dist/css/panel.css +77 -0
  267. package/dist/css/pickerfield.css +85 -0
  268. package/dist/css/radiogroup.css +53 -0
  269. package/dist/css/searchgrid.css +37 -0
  270. package/dist/css/secretfield.css +73 -0
  271. package/dist/css/slider.css +107 -0
  272. package/dist/css/spacer.css +7 -0
  273. package/dist/css/stepform.css +46 -0
  274. package/dist/css/stepper.css +117 -0
  275. package/dist/css/table.css +36 -0
  276. package/dist/css/tabs.css +99 -0
  277. package/dist/css/textarea.css +11 -0
  278. package/dist/css/textfield.css +59 -0
  279. package/dist/css/toast.css +91 -0
  280. package/dist/css/toolbar.css +14 -0
  281. package/dist/css/tooltip.css +17 -0
  282. package/dist/css/viewport.css +9 -0
  283. package/dist/css/widget.css +77 -0
  284. package/dist/css/window.css +31 -0
  285. package/dist/data.js +2 -0
  286. package/dist/data.js.map +7 -0
  287. package/dist/index.js +8 -0
  288. package/dist/index.js.map +7 -0
  289. package/dist/motion.js +2 -0
  290. package/dist/motion.js.map +7 -0
  291. package/dist/optikos.css +3145 -0
  292. package/dist/themes/brand.css +240 -0
  293. package/dist/themes/brutal.css +100 -0
  294. package/dist/themes/compact.css +17 -0
  295. package/dist/themes/corporate.css +112 -0
  296. package/dist/themes/dark.css +38 -0
  297. package/dist/themes/editorial.css +110 -0
  298. package/dist/themes/soft.css +101 -0
  299. package/dist/themes/terminal.css +91 -0
  300. package/dist/types/bind/index.d.ts +23 -0
  301. package/dist/types/components/base/button/button.d.ts +34 -0
  302. package/dist/types/components/base/icon/icon.d.ts +17 -0
  303. package/dist/types/components/base/label/label.d.ts +14 -0
  304. package/dist/types/components/breadcrumb.d.ts +1 -0
  305. package/dist/types/components/button.d.ts +1 -0
  306. package/dist/types/components/calendar.d.ts +1 -0
  307. package/dist/types/components/chat/chat/chat.d.ts +84 -0
  308. package/dist/types/components/chat.d.ts +1 -0
  309. package/dist/types/components/checkbox.d.ts +1 -0
  310. package/dist/types/components/combobox.d.ts +1 -0
  311. package/dist/types/components/commandpalette.d.ts +1 -0
  312. package/dist/types/components/container.d.ts +1 -0
  313. package/dist/types/components/data/dataview/dataview.d.ts +61 -0
  314. package/dist/types/components/data/filterbuilder/filterbuilder.d.ts +71 -0
  315. package/dist/types/components/data/grid/grid.d.ts +151 -0
  316. package/dist/types/components/data/pagination/pagination.d.ts +31 -0
  317. package/dist/types/components/data/searchgrid/searchgrid.d.ts +63 -0
  318. package/dist/types/components/data/table/table.d.ts +26 -0
  319. package/dist/types/components/data/viewmanager/viewmanager.d.ts +86 -0
  320. package/dist/types/components/dataview.d.ts +1 -0
  321. package/dist/types/components/datefield.d.ts +1 -0
  322. package/dist/types/components/daterangefield.d.ts +1 -0
  323. package/dist/types/components/dates/calendar/calendar.d.ts +48 -0
  324. package/dist/types/components/dropdown.d.ts +1 -0
  325. package/dist/types/components/feedback/spinner/spinner.d.ts +11 -0
  326. package/dist/types/components/fields/checkbox/checkbox.d.ts +20 -0
  327. package/dist/types/components/fields/combobox/combobox.d.ts +15 -0
  328. package/dist/types/components/fields/datefield/datefield.d.ts +30 -0
  329. package/dist/types/components/fields/daterangefield/daterangefield.d.ts +32 -0
  330. package/dist/types/components/fields/listbox/listbox.d.ts +54 -0
  331. package/dist/types/components/fields/lookupfield/lookupfield.d.ts +25 -0
  332. package/dist/types/components/fields/numberfield/numberfield.d.ts +31 -0
  333. package/dist/types/components/fields/pickerfield/pickerfield.d.ts +77 -0
  334. package/dist/types/components/fields/radiogroup/radiogroup.d.ts +26 -0
  335. package/dist/types/components/fields/secretfield/secretfield.d.ts +52 -0
  336. package/dist/types/components/fields/select/select.d.ts +10 -0
  337. package/dist/types/components/fields/slider/slider.d.ts +62 -0
  338. package/dist/types/components/fields/suggestfield/suggestfield.d.ts +34 -0
  339. package/dist/types/components/fields/textarea/textarea.d.ts +16 -0
  340. package/dist/types/components/fields/textfield/textfield.d.ts +38 -0
  341. package/dist/types/components/fieldset.d.ts +1 -0
  342. package/dist/types/components/filterbuilder.d.ts +1 -0
  343. package/dist/types/components/form/form/form.d.ts +51 -0
  344. package/dist/types/components/form/stepform/stepform.d.ts +62 -0
  345. package/dist/types/components/form.d.ts +1 -0
  346. package/dist/types/components/grid.d.ts +1 -0
  347. package/dist/types/components/icon.d.ts +1 -0
  348. package/dist/types/components/label.d.ts +1 -0
  349. package/dist/types/components/layout/container/container.d.ts +1 -0
  350. package/dist/types/components/layout/fieldset/fieldset.d.ts +21 -0
  351. package/dist/types/components/layout/panel/panel.d.ts +47 -0
  352. package/dist/types/components/layout/spacer/spacer.d.ts +12 -0
  353. package/dist/types/components/layout/toolbar/toolbar.d.ts +15 -0
  354. package/dist/types/components/layout/viewport/viewport.d.ts +7 -0
  355. package/dist/types/components/listbox.d.ts +1 -0
  356. package/dist/types/components/lookupfield.d.ts +1 -0
  357. package/dist/types/components/menu.d.ts +1 -0
  358. package/dist/types/components/messagebox.d.ts +1 -0
  359. package/dist/types/components/navigation/breadcrumb/breadcrumb.d.ts +32 -0
  360. package/dist/types/components/navigation/navmenu/navmenu.d.ts +63 -0
  361. package/dist/types/components/navigation/stepper/stepper.d.ts +31 -0
  362. package/dist/types/components/navigation/tabs/tabs.d.ts +49 -0
  363. package/dist/types/components/navmenu.d.ts +1 -0
  364. package/dist/types/components/numberfield.d.ts +1 -0
  365. package/dist/types/components/overlays/commandpalette/commandpalette.d.ts +80 -0
  366. package/dist/types/components/overlays/dropdown/dropdown.d.ts +41 -0
  367. package/dist/types/components/overlays/menu/menu.d.ts +41 -0
  368. package/dist/types/components/overlays/messagebox/messagebox.d.ts +53 -0
  369. package/dist/types/components/overlays/toast/toast.d.ts +45 -0
  370. package/dist/types/components/overlays/tooltip/tooltip.d.ts +13 -0
  371. package/dist/types/components/overlays/widget/widget.d.ts +48 -0
  372. package/dist/types/components/overlays/window/window.d.ts +31 -0
  373. package/dist/types/components/pagination.d.ts +1 -0
  374. package/dist/types/components/panel.d.ts +1 -0
  375. package/dist/types/components/pickerfield.d.ts +1 -0
  376. package/dist/types/components/radiogroup.d.ts +1 -0
  377. package/dist/types/components/searchgrid.d.ts +1 -0
  378. package/dist/types/components/secretfield.d.ts +1 -0
  379. package/dist/types/components/select.d.ts +1 -0
  380. package/dist/types/components/slider.d.ts +1 -0
  381. package/dist/types/components/spacer.d.ts +1 -0
  382. package/dist/types/components/spinner.d.ts +1 -0
  383. package/dist/types/components/stepform.d.ts +1 -0
  384. package/dist/types/components/stepper.d.ts +1 -0
  385. package/dist/types/components/suggestfield.d.ts +1 -0
  386. package/dist/types/components/table.d.ts +1 -0
  387. package/dist/types/components/tabs.d.ts +1 -0
  388. package/dist/types/components/textarea.d.ts +1 -0
  389. package/dist/types/components/textfield.d.ts +1 -0
  390. package/dist/types/components/toast.d.ts +1 -0
  391. package/dist/types/components/toolbar.d.ts +1 -0
  392. package/dist/types/components/tooltip.d.ts +1 -0
  393. package/dist/types/components/viewmanager.d.ts +1 -0
  394. package/dist/types/components/viewport.d.ts +1 -0
  395. package/dist/types/components/widget.d.ts +1 -0
  396. package/dist/types/components/window.d.ts +1 -0
  397. package/dist/types/core/component.d.ts +90 -0
  398. package/dist/types/core/container.d.ts +43 -0
  399. package/dist/types/core/date.d.ts +14 -0
  400. package/dist/types/core/dom.d.ts +11 -0
  401. package/dist/types/core/emitter.d.ts +12 -0
  402. package/dist/types/core/field.d.ts +78 -0
  403. package/dist/types/core/focus.d.ts +18 -0
  404. package/dist/types/core/i18n.d.ts +7 -0
  405. package/dist/types/core/index.d.ts +15 -0
  406. package/dist/types/core/layer.d.ts +6 -0
  407. package/dist/types/core/position.d.ts +16 -0
  408. package/dist/types/core/registry.d.ts +12 -0
  409. package/dist/types/core/validators.d.ts +10 -0
  410. package/dist/types/core/virtual.d.ts +24 -0
  411. package/dist/types/data/column.d.ts +27 -0
  412. package/dist/types/data/format.d.ts +4 -0
  413. package/dist/types/data/index.d.ts +5 -0
  414. package/dist/types/data/model.d.ts +28 -0
  415. package/dist/types/data/proxy.d.ts +61 -0
  416. package/dist/types/data/store.d.ts +94 -0
  417. package/dist/types/index.d.ts +53 -0
  418. package/dist/types/layout/layout.d.ts +27 -0
  419. package/dist/types/motion/config.d.ts +83 -0
  420. package/dist/types/motion/core.d.ts +40 -0
  421. package/dist/types/motion/extras.d.ts +66 -0
  422. package/dist/types/motion/index.d.ts +3 -0
  423. package/dist/types/themes/define.d.ts +30 -0
  424. package/dist/types/themes/index.d.ts +1 -0
  425. package/dist/types/ui/enums.d.ts +88 -0
  426. package/dist/types/ui/index.d.ts +2 -0
  427. package/dist/types/ui/ui.d.ts +58 -0
  428. package/dist/ui.js +2 -0
  429. package/dist/ui.js.map +7 -0
  430. package/package.json +99 -4
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/component.ts", "../src/core/registry.ts"],
4
+ "sourcesContent": ["import { Emitter, type Handler } from './emitter';\nimport { h, uid, kebab, px } from './dom';\nimport { t } from './i18n';\n\nexport interface ComponentConfig {\n type?: string;\n id?: string;\n cls?: string;\n style?: string | Record<string, string | number>;\n hidden?: boolean;\n disabled?: boolean;\n width?: number | string;\n height?: number | string;\n flex?: number | string;\n tooltip?: string;\n /** Component-scoped tokens: `{ radius: '0' }` on a button sets `--op-button-radius`. Keys starting with `--` are used as is. */\n theme?: Record<string, string | number>;\n /**\n * Default `true`: the component keeps its size when only its *state* changes (loading, searching, invalid).\n * The CSS reserves room for the state's extra content instead of growing. `false` lets it fit the content.\n * Does not apply to new *content* (`setText` with a longer text).\n */\n stableSize?: boolean;\n /** `true` or a text: shows a mask with a spinner over the component. */\n loading?: boolean | string;\n ariaLabel?: string;\n /** Layout `border`: where the item goes. */\n region?: 'north' | 'south' | 'west' | 'east' | 'center';\n /** Layout `grid`: columns spanned. */\n colspan?: number;\n listeners?: Record<string, Handler>;\n renderTo?: string | HTMLElement;\n /** Free slot for application data. */\n data?: unknown;\n}\n\n/** Anything that owns children (Container) and accepts being asked to drop one. */\nexport interface Parent {\n remove(child: Component, destroy?: boolean): unknown;\n}\n\nexport class Component<C extends ComponentConfig = ComponentConfig> extends Emitter {\n static type?: string;\n config: C;\n readonly id: string;\n parent?: Component & Parent;\n rendered = false;\n mounted = false;\n destroyed = false;\n protected baseCls = 'op-component';\n protected tag: keyof HTMLElementTagNameMap = 'div';\n private _el?: HTMLElement;\n private disposers: Array<() => void> = [];\n private mask?: HTMLElement;\n\n constructor(config: C = {} as C) {\n super();\n this.config = { ...config };\n this.id = config.id ?? uid('op');\n for (const k in config.listeners) this.on(k, config.listeners[k]);\n }\n\n /** The root element. Built on first access. */\n get el(): HTMLElement {\n return this._el ?? this.render();\n }\n\n // ---- lifecycle (template method) ----------------------------------------------------------\n\n /** Builds the root element. Subclasses override to create their own DOM. */\n protected build(): HTMLElement {\n return h(this.tag, this.baseCls);\n }\n protected onRender(): void {}\n protected onMount(): void {}\n protected onDestroy(): void {}\n\n /** Builds the DOM once. Safe to call repeatedly. */\n render(): HTMLElement {\n if (this._el) return this._el;\n const el = (this._el = this.build());\n this.rendered = true;\n const c = this.config;\n el.id = this.id;\n if (c.cls) el.classList.add(...c.cls.split(/\\s+/).filter(Boolean));\n if (typeof c.style === 'string') el.style.cssText += c.style;\n else if (c.style) for (const k in c.style) el.style.setProperty(kebab(k), String(c.style[k]));\n if (c.width != null) el.style.width = px(c.width);\n if (c.height != null) el.style.height = px(c.height);\n if (c.flex != null) el.style.flex = String(c.flex);\n if (c.ariaLabel) el.setAttribute('aria-label', c.ariaLabel);\n this.setStableSize(c.stableSize !== false);\n if (c.hidden) el.hidden = true;\n if (c.tooltip) el.dataset.opTip = c.tooltip;\n if (c.theme) this.setTheme(c.theme);\n this.onRender();\n if (c.disabled) this.setDisabled(true);\n if (c.loading) this.setLoading(c.loading);\n return el;\n }\n\n /** Appends to a target (default `document.body`) and fires `onMount` for the whole subtree. */\n mount(target: string | HTMLElement = document.body): this {\n const parent = typeof target === 'string' ? document.querySelector<HTMLElement>(target) : target;\n if (!parent) throw new Error(`Optikos: mount target not found: ${String(target)}`);\n parent.appendChild(this.el);\n this.notifyMount();\n return this;\n }\n\n /** Called when the element becomes part of a mounted tree. Containers override to reach children. */\n notifyMount(): void {\n if (this.mounted || this.destroyed) return;\n this.mounted = true;\n this.onMount();\n this.emit('mount');\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.onDestroy();\n for (const d of this.disposers.splice(0).reverse()) d();\n this.parent?.remove(this, false);\n this.parent = undefined;\n this._el?.remove();\n this.emit('destroy');\n this.clearListeners();\n }\n\n // ---- resources released on destroy --------------------------------------------------------\n\n /** Registers a function to run on `destroy` (listeners, timers, effects). Returns it. */\n own<F extends () => void>(fn: F): F {\n this.disposers.push(fn);\n return fn;\n }\n\n /** Adds a DOM listener released on `destroy`. */\n listen(target: EventTarget, type: string, fn: (e: any) => void, opts?: AddEventListenerOptions | boolean): () => void {\n target.addEventListener(type, fn, opts);\n return this.own(() => target.removeEventListener(type, fn, opts));\n }\n\n /** `setTimeout` released on `destroy`; returns the cancel function. */\n later(fn: () => void, ms: number): () => void {\n const id = setTimeout(fn, ms);\n return this.own(() => clearTimeout(id));\n }\n\n // ---- common state / setters ---------------------------------------------------------------\n\n protected onDisabled(_disabled: boolean): void {}\n\n setDisabled(disabled: boolean): void {\n this.config.disabled = disabled;\n if (!this.rendered) return;\n this.el.classList.toggle('is-disabled', disabled);\n this.onDisabled(disabled);\n }\n\n show(): void {\n this.config.hidden = false;\n if (this.rendered) this.el.hidden = false;\n this.emit('show');\n }\n hide(): void {\n this.config.hidden = true;\n if (this.rendered) this.el.hidden = true;\n this.emit('hide');\n }\n isHidden(): boolean {\n return !!this.config.hidden;\n }\n\n addCls(name: string): void {\n this.el.classList.add(name);\n }\n removeCls(name: string): void {\n this.el.classList.remove(name);\n }\n toggleCls(name: string, on?: boolean): void {\n this.el.classList.toggle(name, on);\n }\n\n setWidth(v: number | string): void {\n this.config.width = v;\n if (this.rendered) this.el.style.width = px(v);\n }\n setHeight(v: number | string): void {\n this.config.height = v;\n if (this.rendered) this.el.style.height = px(v);\n }\n setFlex(v: number | string): void {\n this.config.flex = v;\n if (this.rendered) this.el.style.flex = String(v);\n }\n\n setStableSize(stable: boolean): void {\n this.config.stableSize = stable;\n if (this.rendered) this.el.classList.toggle('op-stable', stable);\n }\n\n setTooltip(text: string): void {\n this.config.tooltip = text;\n if (!this.rendered) return;\n if (text) this.el.dataset.opTip = text;\n else delete this.el.dataset.opTip;\n }\n\n setTheme(theme: Record<string, string | number>): void {\n const prefix = '--' + this.baseCls + '-';\n for (const k in theme) this.el.style.setProperty(k.startsWith('--') ? k : prefix + kebab(k), String(theme[k]));\n }\n\n /** Shows (or removes) a loading mask. A string is shown as text under the spinner. */\n setLoading(loading: boolean | string): void {\n this.config.loading = loading;\n if (!this.rendered) return;\n const el = this.el;\n this.mask?.remove();\n this.mask = undefined;\n el.classList.toggle('is-loading', !!loading);\n if (loading) el.setAttribute('aria-busy', 'true');\n else el.removeAttribute('aria-busy');\n if (loading) {\n this.mask = h('div', 'op-mask', {}, h('span', 'op-spinner', { role: 'progressbar', 'aria-label': t('loading') }), typeof loading === 'string' ? h('div', 'op-mask__text', {}, loading) : null);\n el.append(this.mask);\n }\n for (const child of Array.from(el.children)) if (child !== this.mask) child.toggleAttribute('inert', !!loading);\n }\n\n /** The element that receives focus on `focus()`. */\n protected focusEl(): HTMLElement {\n return this.el;\n }\n focus(): void {\n this.focusEl().focus();\n }\n}\n", "import type { Component, ComponentConfig } from './component';\n\nexport type ComponentClass = { new (config: any): Component<any>; type?: string };\n/** Config accepted by `create` and `items`: the base keys plus whatever the chosen `type` understands. */\nexport type AnyConfig = ComponentConfig & Record<string, any>;\n\nconst types = new Map<string, ComponentClass>();\n\n/** Registers a component class under a `type`. Users register their own the same way. */\nexport function register(type: string, cls: ComponentClass): void {\n cls.type = type;\n types.set(type, cls);\n}\n\nexport const getType = (type: string): ComponentClass | undefined => types.get(type);\n\n/** Builds a component from a config (or passes an instance through). `renderTo` mounts it. */\nexport function create<T extends Component = Component>(config: AnyConfig | Component): T {\n if (typeof (config as Component).render === 'function') return config as T;\n const cfg = config as AnyConfig;\n const Cls = cfg.type ? types.get(cfg.type) : undefined;\n if (!Cls) throw new Error(`Optikos: unknown component type \"${cfg.type}\". Did you import or register it?`);\n const cmp = new Cls(cfg) as T;\n if (cfg.renderTo) cmp.mount(cfg.renderTo);\n return cmp;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["Component", "Emitter", "config", "uid", "k", "h", "el", "c", "kebab", "px", "target", "parent", "d", "fn", "type", "opts", "ms", "id", "_disabled", "disabled", "name", "on", "v", "stable", "text", "theme", "prefix", "loading", "t", "child", "types", "register", "type", "cls", "getType", "create", "config", "cfg", "Cls", "cmp"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{a as p}from"./chunk-MA5BJL3S.js";var y=0;function g(r,i){return r==null||!i?.type?r:i.type==="number"?r===""?null:Number(r):i.type==="boolean"?r==="false"?!1:!!r:String(r)}var d=class{constructor(i={},e={}){this.def=e;let t={...i};for(let s in e.fields){let o=e.fields[s];t[s]=g(t[s]===void 0?o.default:t[s],o)}this.data=t,this.phantom=this.data[e.idField??"id"]===void 0}def;data;phantom;owner;clientId=`c${++y}`;original={};get id(){return this.data[this.def.idField??"id"]??this.clientId}get(i){return this.data[i]}set(i,e){let t=g(e,this.def.fields?.[i]);this.data[i]!==t&&(i in this.original||(this.original[i]=this.data[i]),this.data[i]=t,this.owner?.recordChanged(this,i))}isDirty(){return Object.keys(this.original).length>0}getChanges(){let i={};for(let e in this.original)i[e]=this.data[e];return i}commit(){this.original={},this.phantom=!1}reject(){Object.assign(this.data,this.original),this.original={}}};var v=(r,i)=>r==null?i==null?0:1:i==null?-1:typeof r=="string"&&typeof i=="string"?r.localeCompare(i,void 0,{numeric:!0}):r<i?-1:r>i?1:0,l=r=>String(r??"").toLowerCase(),c=r=>r==null||r===""||Array.isArray(r)&&!r.length,T=/^\d{4}-\d{2}-\d{2}(T[\d:.]+Z?)?$/,n=r=>r instanceof Date?r.getTime():typeof r=="string"&&T.test(r)?Date.parse(r):r;function b(r,i){let e=r.value,t=n(i),s=()=>!c(i)&&t>=n(e[0])&&t<=n(e[1]),o=()=>e.some(a=>n(a)==t);switch(r.op??"eq"){case"eq":return t==n(e);case"ne":return t!=n(e);case"contains":return l(i).includes(l(e));case"notContains":return!l(i).includes(l(e));case"startsWith":return l(i).startsWith(l(e));case"endsWith":return l(i).endsWith(l(e));case"gt":return t>n(e);case"ge":return t>=n(e);case"lt":return t<n(e);case"le":return t<=n(e);case"between":return s();case"notBetween":return!s();case"in":return o();case"nin":return!o();case"empty":return c(i);case"notEmpty":return!c(i)}}function u(r,i){return"filters"in r?r.filters.length?r.op==="or"?r.filters.some(e=>u(e,i)):r.filters.every(e=>u(e,i)):!0:b(r,i[r.field])}var f=class extends p{constructor(e={}){super();this.cfg=e;this.sorters=e.sorters??[],this.pageLen=e.pageSize??0;for(let t in e.listeners)this.on(t,e.listeners[t]);e.proxy&&(this.proxy=typeof e.proxy=="function"?{read:e.proxy}:e.proxy),e.data&&this.setRecords(e.data.map(t=>this.wrap(t)),e.data.length),e.autoLoad&&this.proxy&&this.load()}cfg;all=[];rows=[];visible=[];removed=[];sorters;filters=[];params={};proxy;pageNo=1;pageLen;total=0;abort;loading=!1;get remote(){return!!this.cfg.remote&&!!this.proxy}wrap(e){let t=e instanceof d?e:new d(e,this.cfg.model);return t.owner=this,t}fire(e,...t){this.emit(e,...t),this.emit("change",{type:e})}get count(){return this.visible.length}get totalCount(){return this.remote?this.total:this.rows.length}getFiltered(){return this.rows}getAt(e){return this.visible[e]}getRange(e=0,t=this.visible.length){return this.visible.slice(e,t)}getById(e){return this.all.find(t=>t.id===e)}indexOf(e){return this.visible.indexOf(e)}getData(){return this.visible.map(e=>e.data)}each(e){this.visible.forEach(e)}loadData(e){this.removed=[],this.setRecords(e.map(t=>this.wrap(t)),e.length),this.fire("load")}async load(e){if(!this.proxy)throw new Error("Optikos Store: load() needs a proxy");e&&(this.params=e);let t={...this.params};if(this.remote&&Object.assign(t,{page:this.pageNo,pageSize:this.pageLen||void 0,sorters:this.sorters,filters:this.filters.filter(o=>typeof o!="function")}),this.emit("before-load",t)===!1)return;this.abort?.abort();let s=this.abort=new AbortController;this.loading=!0,this.emit("loading",!0);try{let o=await this.proxy.read(t,s.signal);if(s.signal.aborted)return;let{data:a,total:h}=Array.isArray(o)?{data:o,total:o.length}:o;this.removed=[],this.setRecords(a.map(m=>this.wrap(m)),h??a.length),this.loading=!1,this.emit("loading",!1),this.fire("load")}catch(o){if(s.signal.aborted)return;this.loading=!1,this.emit("loading",!1),this.emit("load-error",o)}}setRecords(e,t){this.all=e,this.total=t,this.refreshView()}refreshView(){if(this.remote){this.rows=this.visible=this.all;return}let e=this.all;this.filters.length&&(e=e.filter(s=>this.filters.every(o=>typeof o=="function"?o(s):u(o,s.data)))),this.sorters.length&&(e=[...e].sort((s,o)=>{for(let a of this.sorters){let h=v(s.data[a.field],o.data[a.field]);if(h)return a.dir==="desc"?-h:h}return 0})),this.rows=e;let t=this.pageCount;this.pageNo>t&&(this.pageNo=t),this.visible=this.pageLen?e.slice((this.pageNo-1)*this.pageLen,this.pageNo*this.pageLen):e}getSorters(){return this.sorters}sort(e,t){let s=this.sorters[0];this.sorters=e?[{field:e,dir:t??(s?.field===e&&s.dir==="asc"?"desc":"asc")}]:[],this.pageNo=1,this.changeView("sort")}filter(e){return this.filters=Array.isArray(e)?e:[e],this.pageNo=1,this.changeView("filter")}clearFilter(){return this.filters=[],this.pageNo=1,this.changeView("filter")}getFilters(){return this.filters.filter(e=>typeof e!="function")}changeView(e){return this.remote?this.load():(this.refreshView(),this.fire(e),Promise.resolve())}get page(){return this.pageNo}get pageSize(){return this.pageLen}get pageCount(){return this.pageLen?Math.max(1,Math.ceil(this.totalCount/this.pageLen)):1}setPage(e){e=Math.min(Math.max(1,e),this.pageCount),e!==this.pageNo&&(this.pageNo=e,this.remote?this.load():(this.refreshView(),this.fire("page")))}setPageSize(e){this.pageLen=e,this.pageNo=1,this.changeView("page")}add(e){let t=(Array.isArray(e)?e:[e]).map(s=>this.wrap(s));return this.all=[...this.all,...t],this.total+=t.length,this.refreshView(),this.fire("add",t),t}insert(e,t){let s=this.wrap(t);return this.all=[...this.all.slice(0,e),s,...this.all.slice(e)],this.total++,this.refreshView(),this.fire("add",[s]),s}remove(e){let s=(Array.isArray(e)?e:[typeof e=="number"?this.visible[e]:e]).filter(o=>o&&this.all.includes(o));s.length&&(this.all=this.all.filter(o=>!s.includes(o)),this.removed.push(...s.filter(o=>!o.phantom)),this.total-=s.length,this.refreshView(),this.fire("remove",s))}clear(){this.removed.push(...this.all.filter(e=>!e.phantom)),this.setRecords([],0),this.fire("remove",[])}recordChanged(e,t){(this.sorters.some(s=>s.field===t)||this.filters.length)&&this.refreshView(),this.fire("update",e,t)}getModified(){return this.all.filter(e=>e.phantom||e.isDirty())}getRemoved(){return this.removed}commitChanges(){this.all.forEach(e=>e.commit()),this.removed=[]}async sync(){let e=this.proxy;if(!e)throw new Error("Optikos Store: sync() needs a proxy");for(let t of this.removed)await e.destroy?.(t.data);this.removed=[];for(let t of this.all){if(t.phantom)Object.assign(t.data,await e.create?.(t.data)??{});else if(t.isDirty())Object.assign(t.data,await e.update?.(t.data)??{});else continue;t.commit()}this.fire("sync")}subscribe(e){return this.on("change",e)}};export{d as a,u as b,f as c};
2
+ //# sourceMappingURL=chunk-JTYWZMSZ.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/data/model.ts", "../src/data/store.ts"],
4
+ "sourcesContent": ["export interface FieldDef {\n type?: 'string' | 'number' | 'boolean';\n default?: unknown;\n}\nexport interface ModelDef {\n idField?: string;\n fields?: Record<string, FieldDef>;\n}\n\nexport interface RecordOwner {\n recordChanged(rec: Model, field: string): void;\n}\n\nlet cid = 0;\n\nfunction convert(v: unknown, def?: FieldDef): unknown {\n if (v == null || !def?.type) return v;\n if (def.type === 'number') return v === '' ? null : Number(v);\n if (def.type === 'boolean') return v === 'false' ? false : Boolean(v);\n return String(v);\n}\n\n/** One record. `data` holds the values; `set` tracks the original value of each changed field. */\nexport class Model<T extends Record<string, any> = Record<string, any>> {\n data: T;\n phantom: boolean;\n owner?: RecordOwner;\n private readonly clientId = `c${++cid}`;\n private original: Partial<T> = {};\n\n constructor(raw: Partial<T> = {}, private def: ModelDef = {}) {\n const data: Record<string, unknown> = { ...raw };\n for (const f in def.fields) {\n const fd = def.fields[f];\n data[f] = convert(data[f] === undefined ? fd.default : data[f], fd);\n }\n this.data = data as T;\n this.phantom = this.data[def.idField ?? 'id'] === undefined;\n }\n\n get id(): string | number {\n return this.data[this.def.idField ?? 'id'] ?? this.clientId;\n }\n\n get<K extends keyof T>(field: K): T[K] {\n return this.data[field];\n }\n\n set<K extends keyof T>(field: K, value: T[K]): void {\n const v = convert(value, this.def.fields?.[field as string]) as T[K];\n if (this.data[field] === v) return;\n if (!(field in this.original)) this.original[field] = this.data[field];\n this.data[field] = v;\n this.owner?.recordChanged(this as Model, field as string);\n }\n\n isDirty(): boolean {\n return Object.keys(this.original).length > 0;\n }\n getChanges(): Partial<T> {\n const out: Partial<T> = {};\n for (const k in this.original) out[k] = this.data[k];\n return out;\n }\n commit(): void {\n this.original = {};\n this.phantom = false;\n }\n reject(): void {\n Object.assign(this.data, this.original);\n this.original = {};\n }\n}\n", "import { Emitter } from '../core/emitter';\nimport { Model, type ModelDef, type RecordOwner } from './model';\nimport type { FilterNode, FilterSpec, Proxy, ReadParams, ReadResult, Sorter } from './proxy';\n\nexport type StoreProxy<T> = Proxy<T> | ((params: ReadParams, signal?: AbortSignal) => Promise<ReadResult<T> | T[]> | ReadResult<T> | T[]);\nexport type FilterFn<T extends Record<string, any>> = (rec: Model<T>) => boolean;\n\nexport interface StoreConfig<T extends Record<string, any>> {\n data?: Partial<T>[];\n model?: ModelDef;\n proxy?: StoreProxy<T>;\n /** 0 = no paging. */\n pageSize?: number;\n /** Sort, filter and paging are done by the proxy (it receives them in `read`). Default false: done locally. */\n remote?: boolean;\n sorters?: Sorter[];\n autoLoad?: boolean;\n listeners?: Record<string, (...a: any[]) => unknown>;\n}\n\nconst cmp = (a: any, b: any) => (a == null ? (b == null ? 0 : 1) : b == null ? -1 : typeof a === 'string' && typeof b === 'string' ? a.localeCompare(b, undefined, { numeric: true }) : a < b ? -1 : a > b ? 1 : 0);\n\nconst text = (v: any) => String(v ?? '').toLowerCase();\nconst empty = (v: any) => v == null || v === '' || (Array.isArray(v) && !v.length);\nconst ISO = /^\\d{4}-\\d{2}-\\d{2}(T[\\d:.]+Z?)?$/;\n/** Dates (Date objects or ISO strings) compare by time; anything else compares as is. */\nconst num = (v: any) => (v instanceof Date ? v.getTime() : typeof v === 'string' && ISO.test(v) ? Date.parse(v) : v);\n\nfunction test(spec: FilterSpec, raw: any): boolean {\n const x = spec.value as any;\n const v = num(raw);\n const between = () => !empty(raw) && v >= num(x[0]) && v <= num(x[1]);\n const listed = () => (x as unknown[]).some((i) => num(i) == v);\n switch (spec.op ?? 'eq') {\n case 'eq': return v == num(x);\n case 'ne': return v != num(x);\n case 'contains': return text(raw).includes(text(x));\n case 'notContains': return !text(raw).includes(text(x));\n case 'startsWith': return text(raw).startsWith(text(x));\n case 'endsWith': return text(raw).endsWith(text(x));\n case 'gt': return v > num(x);\n case 'ge': return v >= num(x);\n case 'lt': return v < num(x);\n case 'le': return v <= num(x);\n case 'between': return between();\n case 'notBetween': return !between();\n case 'in': return listed();\n case 'nin': return !listed();\n case 'empty': return empty(raw);\n case 'notEmpty': return !empty(raw);\n }\n}\n\n/** Does a record's data satisfy a filter node? Groups are AND/OR; an empty group matches everything. */\nexport function matchFilter(node: FilterNode, data: Record<string, any>): boolean {\n if ('filters' in node) {\n if (!node.filters.length) return true;\n return node.op === 'or' ? node.filters.some((f) => matchFilter(f, data)) : node.filters.every((f) => matchFilter(f, data));\n }\n return test(node, data[node.field]);\n}\n\n/**\n * Records + a view over them (filtered, sorted, paged). Events: `load`, `before-load`, `load-error`, `add`, `remove`,\n * `update`, `sort`, `filter`, `page`, `sync`, and `change` for any of them (payload `{ type }`).\n */\nexport class Store<T extends Record<string, any> = Record<string, any>> extends Emitter implements RecordOwner {\n private all: Model<T>[] = [];\n private rows: Model<T>[] = [];\n private visible: Model<T>[] = [];\n private removed: Model<T>[] = [];\n private sorters: Sorter[];\n private filters: Array<FilterNode | FilterFn<T>> = [];\n private params: Record<string, unknown> = {};\n private proxy?: Proxy<T>;\n private pageNo = 1;\n private pageLen: number;\n private total = 0;\n private abort?: AbortController;\n loading = false;\n\n constructor(private cfg: StoreConfig<T> = {}) {\n super();\n this.sorters = cfg.sorters ?? [];\n this.pageLen = cfg.pageSize ?? 0;\n for (const k in cfg.listeners) this.on(k, cfg.listeners[k]);\n if (cfg.proxy) this.proxy = typeof cfg.proxy === 'function' ? { read: cfg.proxy } : cfg.proxy;\n if (cfg.data) this.setRecords(cfg.data.map((r) => this.wrap(r)), cfg.data.length);\n if (cfg.autoLoad && this.proxy) void this.load();\n }\n\n private get remote() {\n return !!this.cfg.remote && !!this.proxy;\n }\n private wrap(raw: Partial<T> | Model<T>): Model<T> {\n const m = raw instanceof Model ? raw : new Model<T>(raw, this.cfg.model);\n m.owner = this;\n return m;\n }\n private fire(type: string, ...args: unknown[]) {\n this.emit(type, ...args);\n this.emit('change', { type });\n }\n\n // ---- reading -------------------------------------------------------------------------------\n\n /** Number of records in the current view (the current page). */\n get count(): number {\n return this.visible.length;\n }\n /** Records matching the filters, across pages (remote: what the server reported). */\n get totalCount(): number {\n return this.remote ? this.total : this.rows.length;\n }\n /** Every record matching the filters, across pages (a remote store only knows the loaded page). */\n getFiltered(): Model<T>[] {\n return this.rows;\n }\n getAt(i: number): Model<T> | undefined {\n return this.visible[i];\n }\n getRange(start = 0, end = this.visible.length): Model<T>[] {\n return this.visible.slice(start, end);\n }\n getById(id: string | number): Model<T> | undefined {\n return this.all.find((r) => r.id === id);\n }\n indexOf(rec: Model<T>): number {\n return this.visible.indexOf(rec);\n }\n /** Plain data of the current view. */\n getData(): T[] {\n return this.visible.map((r) => r.data);\n }\n each(fn: (rec: Model<T>, i: number) => void): void {\n this.visible.forEach(fn);\n }\n\n // ---- loading -------------------------------------------------------------------------------\n\n /** Replaces all records with local data. */\n loadData(data: Partial<T>[]): void {\n this.removed = [];\n this.setRecords(data.map((r) => this.wrap(r)), data.length);\n this.fire('load');\n }\n\n /** Reads through the proxy. Extra `params` are sent to it and remembered for later reloads. A newer load cancels the older one. */\n async load(params?: Record<string, unknown>): Promise<void> {\n if (!this.proxy) throw new Error('Optikos Store: load() needs a proxy');\n if (params) this.params = params;\n const req: ReadParams = { ...this.params };\n if (this.remote) Object.assign(req, { page: this.pageNo, pageSize: this.pageLen || undefined, sorters: this.sorters, filters: this.filters.filter((f): f is FilterNode => typeof f !== 'function') });\n if (this.emit('before-load', req) === false) return;\n this.abort?.abort();\n const ctl = (this.abort = new AbortController());\n this.loading = true;\n this.emit('loading', true);\n try {\n const res = await this.proxy.read(req, ctl.signal);\n if (ctl.signal.aborted) return;\n const { data, total } = Array.isArray(res) ? { data: res, total: res.length } : res;\n this.removed = [];\n this.setRecords(data.map((r) => this.wrap(r)), total ?? data.length);\n this.loading = false;\n this.emit('loading', false);\n this.fire('load');\n } catch (err) {\n if (ctl.signal.aborted) return;\n this.loading = false;\n this.emit('loading', false);\n this.emit('load-error', err);\n }\n }\n\n private setRecords(recs: Model<T>[], total: number) {\n this.all = recs;\n this.total = total;\n this.refreshView();\n }\n\n /** Recomputes filtered/sorted/paged rows from `all`. */\n private refreshView() {\n if (this.remote) {\n this.rows = this.visible = this.all;\n return;\n }\n let rows = this.all;\n if (this.filters.length) rows = rows.filter((r) => this.filters.every((f) => (typeof f === 'function' ? f(r) : matchFilter(f, r.data))));\n if (this.sorters.length) {\n rows = [...rows].sort((a, b) => {\n for (const s of this.sorters) {\n const d = cmp(a.data[s.field], b.data[s.field]);\n if (d) return s.dir === 'desc' ? -d : d;\n }\n return 0;\n });\n }\n this.rows = rows;\n const pages = this.pageCount;\n if (this.pageNo > pages) this.pageNo = pages;\n this.visible = this.pageLen ? rows.slice((this.pageNo - 1) * this.pageLen, this.pageNo * this.pageLen) : rows;\n }\n\n // ---- sort / filter / paging ----------------------------------------------------------------\n\n getSorters(): Sorter[] {\n return this.sorters;\n }\n /** `sort('name')` toggles asc/desc when already sorted by it; `sort('name', 'desc')` is explicit; `sort(null)` clears. */\n sort(field: string | null, dir?: 'asc' | 'desc'): void {\n const cur = this.sorters[0];\n this.sorters = field ? [{ field, dir: dir ?? (cur?.field === field && cur.dir === 'asc' ? 'desc' : 'asc') }] : [];\n this.pageNo = 1;\n this.changeView('sort');\n }\n\n /**\n * Replaces the filters (top level = AND). Accepts specs, groups (`{ op: 'or', filters }`), or a predicate.\n * Resolves when the view is up to date (for a remote store, after the reload).\n */\n filter(f: FilterNode | FilterNode[] | FilterFn<T>): Promise<void> {\n this.filters = Array.isArray(f) ? f : [f];\n this.pageNo = 1;\n return this.changeView('filter');\n }\n clearFilter(): Promise<void> {\n this.filters = [];\n this.pageNo = 1;\n return this.changeView('filter');\n }\n /** The active filter nodes (predicates are not included). */\n getFilters(): FilterNode[] {\n return this.filters.filter((f): f is FilterNode => typeof f !== 'function');\n }\n\n private changeView(type: string): Promise<void> {\n if (this.remote) return this.load();\n this.refreshView();\n this.fire(type);\n return Promise.resolve();\n }\n\n get page(): number {\n return this.pageNo;\n }\n get pageSize(): number {\n return this.pageLen;\n }\n get pageCount(): number {\n return this.pageLen ? Math.max(1, Math.ceil(this.totalCount / this.pageLen)) : 1;\n }\n setPage(n: number): void {\n n = Math.min(Math.max(1, n), this.pageCount);\n if (n === this.pageNo) return;\n this.pageNo = n;\n if (this.remote) void this.load();\n else {\n this.refreshView();\n this.fire('page');\n }\n }\n setPageSize(n: number): void {\n this.pageLen = n;\n this.pageNo = 1;\n this.changeView('page');\n }\n\n // ---- editing -------------------------------------------------------------------------------\n\n add(raw: Partial<T> | Partial<T>[]): Model<T>[] {\n const recs = (Array.isArray(raw) ? raw : [raw]).map((r) => this.wrap(r));\n this.all = [...this.all, ...recs];\n this.total += recs.length;\n this.refreshView();\n this.fire('add', recs);\n return recs;\n }\n\n insert(index: number, raw: Partial<T>): Model<T> {\n const rec = this.wrap(raw);\n this.all = [...this.all.slice(0, index), rec, ...this.all.slice(index)];\n this.total++;\n this.refreshView();\n this.fire('add', [rec]);\n return rec;\n }\n\n remove(target: Model<T> | number | Array<Model<T>>): void {\n const list = Array.isArray(target) ? target : [typeof target === 'number' ? this.visible[target] : target];\n const gone = list.filter((r) => r && this.all.includes(r));\n if (!gone.length) return;\n this.all = this.all.filter((r) => !gone.includes(r));\n this.removed.push(...gone.filter((r) => !r.phantom));\n this.total -= gone.length;\n this.refreshView();\n this.fire('remove', gone);\n }\n\n clear(): void {\n this.removed.push(...this.all.filter((r) => !r.phantom));\n this.setRecords([], 0);\n this.fire('remove', []);\n }\n\n recordChanged(rec: Model, field: string): void {\n if (this.sorters.some((s) => s.field === field) || this.filters.length) this.refreshView();\n this.fire('update', rec, field);\n }\n\n getModified(): Model<T>[] {\n return this.all.filter((r) => r.phantom || r.isDirty());\n }\n getRemoved(): Model<T>[] {\n return this.removed;\n }\n commitChanges(): void {\n this.all.forEach((r) => r.commit());\n this.removed = [];\n }\n\n /** Writes pending changes through the proxy: deletes, then creates and updates, one at a time. */\n async sync(): Promise<void> {\n const p = this.proxy;\n if (!p) throw new Error('Optikos Store: sync() needs a proxy');\n for (const r of this.removed) await p.destroy?.(r.data);\n this.removed = [];\n for (const r of this.all) {\n if (r.phantom) Object.assign(r.data, (await p.create?.(r.data)) ?? {});\n else if (r.isDirty()) Object.assign(r.data, (await p.update?.(r.data)) ?? {});\n else continue;\n r.commit();\n }\n this.fire('sync');\n }\n\n /** Observable interface used by `optikos/bind`: calls `fn` on any change; returns the unsubscribe function. */\n subscribe(fn: (change: { type: string }) => void): () => void {\n return this.on('change', fn);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["cid", "convert", "v", "def", "Model", "raw", "data", "f", "fd", "field", "value", "out", "k", "cmp", "a", "b", "text", "v", "empty", "ISO", "num", "test", "spec", "raw", "x", "between", "listed", "i", "matchFilter", "node", "data", "f", "Store", "Emitter", "cfg", "k", "r", "m", "Model", "type", "args", "start", "end", "id", "rec", "fn", "params", "req", "ctl", "res", "total", "err", "recs", "rows", "s", "d", "pages", "field", "dir", "cur", "n", "index", "target", "gone", "p"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{c as n}from"./chunk-UPOBGNJ5.js";import{a}from"./chunk-K2DGY6MP.js";import{b as l}from"./chunk-IYPKPLCU.js";var u=(o,t)=>t.split(".").reduce((e,i)=>e?.[i],o);function y(o,t,e){let i=t.split("."),s=i.pop(),d=i.reduce((f,c)=>f[c]??={},o);d[s]=e}var r=class extends n{baseCls="op-form";tag="form";constructor(t={}){let e=[...t.items??[]];t.tabs&&e.push({type:"tabs",flex:1,items:t.tabs.map(i=>({type:"container",title:i.title,icon:i.icon,cls:"op-form__tab",layout:i.layout??{type:"grid",columns:2,gap:12},items:i.items}))}),super({...t,items:e})}build(){let t=super.build();return t.setAttribute("novalidate",""),t}onRender(){if(this.config.layout??={type:"vbox"},this.config.labelPos)for(let t of this.getFields())t.config.labelPos??=this.config.labelPos;super.onRender(),this.config.readonly&&this.setReadonly(!0);for(let t of this.getFields())for(let e of["invalid","valid","dirty-change","change"])t.on(e,()=>this.syncTabs());this.listen(this.el,"submit",t=>{t.preventDefault(),this.submit()}),this.listen(this.el,"keydown",t=>{let e=t.target;t.key==="Enter"&&e instanceof HTMLInputElement&&!t.defaultPrevented&&e.type!=="button"&&(t.preventDefault(),this.submit())})}getFields(){return this.query(t=>t instanceof a)}getField(t){return this.getFields().find(e=>e.name===t)}getValues(t={}){let e={};for(let i of this.getFields())i.name&&(!t.dirtyOnly||i.isDirty())&&y(e,i.name,i.getValue());return e}setValues(t){for(let e of this.getFields()){let i=e.name?u(t,e.name):void 0;i!==void 0&&e.setValue(i,!0)}}load(t){this.setValues("data"in t&&"get"in t?t.data:t),this.markClean(),this.clearErrors(),this.emit("load",t)}reveal(t){let e=t;for(;e.parent;){let i=e.parent;i.items?.includes(e)&&(typeof i.setActive=="function"?i.setActive(e):i.layout?.activate&&i.layout.activate(i,e)),e=i}}syncTabs(){for(let t of this.query(e=>typeof e.setTabState=="function"))for(let e of t.items){let i=e instanceof n?e.query(s=>s instanceof a):[];t.setTabState(e,{errors:i.filter(s=>s.getError()).length,dirty:i.some(s=>s.isDirty())})}}updateRecord(t){let e=this.getValues(),i=new Set(this.getFields().filter(s=>s.name&&s.isDirty()).map(s=>s.name.split(".")[0]));for(let s of i)t.set(s,e[s])}markClean(){this.getFields().forEach(t=>t.markClean()),this.syncTabs()}reset(){this.getFields().forEach(t=>t.reset()),this.syncTabs()}isDirty(){return this.getFields().some(t=>t.isDirty())}isValid(){return this.getFields().every(t=>t.isValid())}clearErrors(){this.getFields().forEach(t=>t.clearError()),this.syncTabs()}validate(){let t=this.getFields().filter(e=>!e.validate());return this.syncTabs(),t.length&&(this.reveal(t[0]),t[0].focus(),this.emit("invalid",t)),this.el.classList.toggle("is-invalid",!!t.length),!t.length}submit(){return this.emit("before-submit")===!1||!this.validate()?!1:(this.emit("submit",this.getValues()),!0)}setReadonly(t){this.config.readonly=t,this.getFields().forEach(e=>e.setReadonly(t))}};l("form",r);export{r as a};
2
+ //# sourceMappingURL=chunk-JVEPKW5X.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/components/form/form/form.ts"],
4
+ "sourcesContent": ["import { Container, type ContainerConfig } from '../../../core/container';\nimport { Field } from '../../../core/field';\nimport { register } from '../../../core/registry';\nimport type { Model } from '../../../data/model';\nimport type { Component } from '../../../core/component';\nimport type { LayoutSpec } from '../../../layout/layout';\n\nexport interface FormTab {\n title: string;\n icon?: string;\n items: ContainerConfig['items'];\n /** Default: two columns (one on a phone). */\n layout?: LayoutSpec;\n}\n\nexport interface FormConfig extends ContainerConfig {\n /** Shortcut: the fields in tabs, still one form (one `getValues`, one `validate`, one dirty). */\n tabs?: FormTab[];\n /** Default `labelPos` for fields that do not set their own. */\n labelPos?: 'top' | 'left';\n readonly?: boolean;\n}\n\nconst getPath = (o: any, path: string) => path.split('.').reduce((v, k) => v?.[k], o);\nfunction setPath(o: any, path: string, value: unknown) {\n const keys = path.split('.');\n const last = keys.pop()!;\n const target = keys.reduce((v, k) => (v[k] ??= {}), o);\n target[last] = value;\n}\n\nexport class Form extends Container<FormConfig> {\n protected override baseCls = 'op-form';\n protected override tag = 'form' as const;\n\n constructor(config: FormConfig = {}) {\n const items = [...(config.items ?? [])];\n if (config.tabs) {\n items.push({\n type: 'tabs',\n flex: 1,\n items: config.tabs.map((t) => ({ type: 'container', title: t.title, icon: t.icon, cls: 'op-form__tab', layout: t.layout ?? { type: 'grid', columns: 2, gap: 12 }, items: t.items })),\n } as never);\n }\n super({ ...config, items });\n }\n\n protected override build() {\n const el = super.build();\n el.setAttribute('novalidate', '');\n return el;\n }\n\n protected override onRender() {\n this.config.layout ??= { type: 'vbox' };\n if (this.config.labelPos) for (const f of this.getFields()) f.config.labelPos ??= this.config.labelPos;\n super.onRender();\n if (this.config.readonly) this.setReadonly(true);\n for (const f of this.getFields()) for (const ev of ['invalid', 'valid', 'dirty-change', 'change']) f.on(ev, () => this.syncTabs());\n // Native submit (a `type=submit` button) and Enter inside a single-line field both go through submit().\n this.listen(this.el, 'submit', (e: Event) => {\n e.preventDefault();\n this.submit();\n });\n this.listen(this.el, 'keydown', (e: KeyboardEvent) => {\n const t = e.target as HTMLElement;\n if (e.key === 'Enter' && t instanceof HTMLInputElement && !e.defaultPrevented && t.type !== 'button') {\n e.preventDefault();\n this.submit();\n }\n });\n }\n\n getFields(): Field<any>[] {\n return this.query((c) => c instanceof Field) as Field<any>[];\n }\n\n getField(name: string): Field<any> | undefined {\n return this.getFields().find((f) => f.name === name);\n }\n\n /** Nested object built from field names (`address.city` \u2192 `{ address: { city } }`). */\n getValues(opts: { dirtyOnly?: boolean } = {}): Record<string, any> {\n const out: Record<string, any> = {};\n for (const f of this.getFields()) if (f.name && (!opts.dirtyOnly || f.isDirty())) setPath(out, f.name, f.getValue());\n return out;\n }\n\n /** Sets the fields present in `values` (silently). */\n setValues(values: Record<string, any>): void {\n for (const f of this.getFields()) {\n const v = f.name ? getPath(values, f.name) : undefined;\n if (v !== undefined) f.setValue(v, true);\n }\n }\n\n /** Fills the form from a plain object or a Model, and makes it the \"clean\" state. */\n load(record: Record<string, any> | Model): void {\n this.setValues('data' in record && 'get' in record ? (record as Model).data : record);\n this.markClean();\n this.clearErrors();\n this.emit('load', record);\n }\n\n /** Brings a field into view: asks every ancestor that shows one child at a time (Tabs, a card layout) to show the branch. */\n protected reveal(field: Component): void {\n let node: Component = field;\n while (node.parent) {\n const p = node.parent as any;\n if (p.items?.includes(node)) {\n if (typeof p.setActive === 'function') p.setActive(node);\n else if (p.layout?.activate) p.layout.activate(p, node);\n }\n node = p;\n }\n }\n\n /** Error counts and \"changed\" dots on the headers of every Tabs inside the form. */\n protected syncTabs(): void {\n for (const tabs of this.query((c) => typeof (c as any).setTabState === 'function') as any[]) {\n for (const panel of tabs.items as Component[]) {\n const fields = panel instanceof Container ? (panel.query((c) => c instanceof Field) as Field<any>[]) : [];\n tabs.setTabState(panel, { errors: fields.filter((f) => f.getError()).length, dirty: fields.some((f) => f.isDirty()) });\n }\n }\n }\n\n /** Writes the changed fields back into a Model. */\n updateRecord(model: Model): void {\n const all = this.getValues();\n const keys = new Set(this.getFields().filter((f) => f.name && f.isDirty()).map((f) => f.name!.split('.')[0]));\n for (const k of keys) model.set(k, all[k]);\n }\n\n markClean(): void {\n this.getFields().forEach((f) => f.markClean());\n this.syncTabs();\n }\n reset(): void {\n this.getFields().forEach((f) => f.reset());\n this.syncTabs();\n }\n isDirty(): boolean {\n return this.getFields().some((f) => f.isDirty());\n }\n isValid(): boolean {\n return this.getFields().every((f) => f.isValid());\n }\n clearErrors(): void {\n this.getFields().forEach((f) => f.clearError());\n this.syncTabs();\n }\n\n /** Validates every field (marks errors) and focuses the first invalid one. */\n validate(): boolean {\n const bad = this.getFields().filter((f) => !f.validate());\n this.syncTabs();\n if (bad.length) {\n this.reveal(bad[0]); // the tab / step that holds it comes forward first\n bad[0].focus();\n this.emit('invalid', bad);\n }\n this.el.classList.toggle('is-invalid', !!bad.length);\n return !bad.length;\n }\n\n submit(): boolean {\n if (this.emit('before-submit') === false) return false;\n if (!this.validate()) return false;\n this.emit('submit', this.getValues());\n return true;\n }\n\n setReadonly(readonly: boolean): void {\n this.config.readonly = readonly;\n this.getFields().forEach((f) => f.setReadonly(readonly));\n }\n}\nregister('form', Form);\n"],
5
+ "mappings": "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",
6
+ "names": ["getPath", "path", "v", "k", "setPath", "value", "keys", "last", "target", "Form", "Container", "config", "items", "t", "el", "f", "ev", "e", "c", "Field", "name", "opts", "out", "values", "record", "field", "node", "p", "tabs", "panel", "fields", "model", "all", "bad", "readonly", "register"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{c as h}from"./chunk-NDBFYIL6.js";import{c as d}from"./chunk-JTYWZMSZ.js";import{a as l,b as c}from"./chunk-IYPKPLCU.js";import{b as e}from"./chunk-PZSHOSOS.js";import{e as p}from"./chunk-MA5BJL3S.js";var r=class extends l{baseCls="op-table";tag="table";store;unsub;onRender(){let t=this.config;this.el.classList.toggle("op-table--striped",!!t.striped),this.bind(t.store??new d({data:t.data??[]})),this.own(()=>this.unsub?.())}bind(t){this.unsub?.(),this.store=t,this.unsub=t.subscribe(()=>this.paint()),this.paint()}cols(){return(this.config.columns??Object.keys(this.store.getAt(0)?.data??{}).map(o=>({field:o}))).filter(o=>!o.hidden)}paint(){let t=this.config,n=this.cols(),o=e("tr","",{},...n.map(i=>e("th",i.align?`op-table__cell--${i.align}`:"",{scope:"col"},i.header??i.field))),a=this.store.getRange().map(i=>e("tr","",{},...n.map(s=>e("td",`${s.align?`op-table__cell--${s.align}`:""} ${s.cls??""}`.trim(),{},h(s,i))))),m=a.length?a:[e("tr","op-table__empty",{},e("td","",{colspan:n.length||1},t.emptyText??p("empty")))];this.el.replaceChildren(...t.caption?[e("caption","",{},t.caption)]:[],e("thead","",{},o),e("tbody","",{},...m))}setData(t){this.config.data=t,this.rendered&&this.store.loadData(t)}setStore(t){this.config.store=t,this.rendered&&this.bind(t)}setColumns(t){this.config.columns=t,this.rendered&&this.paint()}setCaption(t){this.config.caption=t,this.rendered&&this.paint()}};c("table",r);export{r as a};
2
+ //# sourceMappingURL=chunk-JZNEB7A7.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/components/data/table/table.ts"],
4
+ "sourcesContent": ["import { Component, type ComponentConfig } from '../../../core/component';\nimport { register } from '../../../core/registry';\nimport { h } from '../../../core/dom';\nimport { Store } from '../../../data/store';\nimport { t } from '../../../core/i18n';\nimport { cellContent, type Column } from '../../../data/column';\n\nexport interface TableConfig extends ComponentConfig {\n data?: Record<string, any>[];\n store?: Store<any>;\n columns?: Column[];\n caption?: string;\n striped?: boolean;\n emptyText?: string;\n}\n\n/** Plain semantic `<table>` for small datasets. No selection, sorting or virtualization: use Grid for those. */\nexport class Table extends Component<TableConfig> {\n protected override baseCls = 'op-table';\n protected override tag = 'table' as const;\n private store!: Store<any>;\n private unsub?: () => void;\n\n protected override onRender() {\n const c = this.config;\n this.el.classList.toggle('op-table--striped', !!c.striped);\n this.bind(c.store ?? new Store({ data: c.data ?? [] }));\n this.own(() => this.unsub?.());\n }\n\n private bind(store: Store<any>) {\n this.unsub?.();\n this.store = store;\n this.unsub = store.subscribe(() => this.paint());\n this.paint();\n }\n\n private cols(): Column[] {\n const c = this.config;\n const all: Column[] = c.columns ?? Object.keys(this.store.getAt(0)?.data ?? {}).map((field) => ({ field }));\n return all.filter((x) => !x.hidden);\n }\n\n private paint() {\n const c = this.config;\n const cols = this.cols();\n const head = h('tr', '', {}, ...cols.map((col) => h('th', col.align ? `op-table__cell--${col.align}` : '', { scope: 'col' }, col.header ?? col.field)));\n const rows = this.store.getRange().map((rec) =>\n h('tr', '', {}, ...cols.map((col) => h('td', `${col.align ? `op-table__cell--${col.align}` : ''} ${col.cls ?? ''}`.trim(), {}, cellContent(col, rec)))),\n );\n const body = rows.length ? rows : [h('tr', 'op-table__empty', {}, h('td', '', { colspan: cols.length || 1 }, c.emptyText ?? t('empty')))];\n this.el.replaceChildren(...(c.caption ? [h('caption', '', {}, c.caption)] : []), h('thead', '', {}, head), h('tbody', '', {}, ...body));\n }\n\n setData(data: Record<string, any>[]) {\n this.config.data = data;\n if (this.rendered) this.store.loadData(data);\n }\n setStore(store: Store<any>) {\n this.config.store = store;\n if (this.rendered) this.bind(store);\n }\n setColumns(columns: Column[]) {\n this.config.columns = columns;\n if (this.rendered) this.paint();\n }\n setCaption(caption: string) {\n this.config.caption = caption;\n if (this.rendered) this.paint();\n }\n}\nregister('table', Table);\n"],
5
+ "mappings": "+MAiBO,IAAMA,EAAN,cAAoBC,CAAuB,CAC7B,QAAU,WACV,IAAM,QACjB,MACA,MAEW,UAAW,CAC5B,IAAMC,EAAI,KAAK,OACf,KAAK,GAAG,UAAU,OAAO,oBAAqB,CAAC,CAACA,EAAE,OAAO,EACzD,KAAK,KAAKA,EAAE,OAAS,IAAIC,EAAM,CAAE,KAAMD,EAAE,MAAQ,CAAC,CAAE,CAAC,CAAC,EACtD,KAAK,IAAI,IAAM,KAAK,QAAQ,CAAC,CAC/B,CAEQ,KAAKE,EAAmB,CAC9B,KAAK,QAAQ,EACb,KAAK,MAAQA,EACb,KAAK,MAAQA,EAAM,UAAU,IAAM,KAAK,MAAM,CAAC,EAC/C,KAAK,MAAM,CACb,CAEQ,MAAiB,CAGvB,OAFU,KAAK,OACS,SAAW,OAAO,KAAK,KAAK,MAAM,MAAM,CAAC,GAAG,MAAQ,CAAC,CAAC,EAAE,IAAKC,IAAW,CAAE,MAAAA,CAAM,EAAE,GAC/F,OAAQC,GAAM,CAACA,EAAE,MAAM,CACpC,CAEQ,OAAQ,CACd,IAAMJ,EAAI,KAAK,OACTK,EAAO,KAAK,KAAK,EACjBC,EAAOC,EAAE,KAAM,GAAI,CAAC,EAAG,GAAGF,EAAK,IAAKG,GAAQD,EAAE,KAAMC,EAAI,MAAQ,mBAAmBA,EAAI,KAAK,GAAK,GAAI,CAAE,MAAO,KAAM,EAAGA,EAAI,QAAUA,EAAI,KAAK,CAAC,CAAC,EAChJC,EAAO,KAAK,MAAM,SAAS,EAAE,IAAKC,GACtCH,EAAE,KAAM,GAAI,CAAC,EAAG,GAAGF,EAAK,IAAKG,GAAQD,EAAE,KAAM,GAAGC,EAAI,MAAQ,mBAAmBA,EAAI,KAAK,GAAK,EAAE,IAAIA,EAAI,KAAO,EAAE,GAAG,KAAK,EAAG,CAAC,EAAGG,EAAYH,EAAKE,CAAG,CAAC,CAAC,CAAC,CACxJ,EACME,EAAOH,EAAK,OAASA,EAAO,CAACF,EAAE,KAAM,kBAAmB,CAAC,EAAGA,EAAE,KAAM,GAAI,CAAE,QAASF,EAAK,QAAU,CAAE,EAAGL,EAAE,WAAaa,EAAE,OAAO,CAAC,CAAC,CAAC,EACxI,KAAK,GAAG,gBAAgB,GAAIb,EAAE,QAAU,CAACO,EAAE,UAAW,GAAI,CAAC,EAAGP,EAAE,OAAO,CAAC,EAAI,CAAC,EAAIO,EAAE,QAAS,GAAI,CAAC,EAAGD,CAAI,EAAGC,EAAE,QAAS,GAAI,CAAC,EAAG,GAAGK,CAAI,CAAC,CACxI,CAEA,QAAQE,EAA6B,CACnC,KAAK,OAAO,KAAOA,EACf,KAAK,UAAU,KAAK,MAAM,SAASA,CAAI,CAC7C,CACA,SAASZ,EAAmB,CAC1B,KAAK,OAAO,MAAQA,EAChB,KAAK,UAAU,KAAK,KAAKA,CAAK,CACpC,CACA,WAAWa,EAAmB,CAC5B,KAAK,OAAO,QAAUA,EAClB,KAAK,UAAU,KAAK,MAAM,CAChC,CACA,WAAWC,EAAiB,CAC1B,KAAK,OAAO,QAAUA,EAClB,KAAK,UAAU,KAAK,MAAM,CAChC,CACF,EACAC,EAAS,QAASnB,CAAK",
6
+ "names": ["Table", "Component", "c", "Store", "store", "field", "x", "cols", "head", "h", "col", "rows", "rec", "cellContent", "body", "t", "data", "columns", "caption", "register"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{a as o}from"./chunk-IYPKPLCU.js";import{b as r,c as s}from"./chunk-PZSHOSOS.js";import{e as l}from"./chunk-MA5BJL3S.js";var n=class extends o{baseCls="op-field";value;original;error="";inputEl;labelEl;helpEl;errorEl;dirty=!1;cancelSettle;constructor(e={}){super(e),this.value=this.original=e.value??this.emptyValue()}get name(){return this.config.name}emptyValue(){return""}isEmpty(e){return e==null||e===""||Array.isArray(e)&&!e.length}isEqual(e,t){return e===t||JSON.stringify(e)===JSON.stringify(t)}build(){let e=this.config,t=r("div",`${this.baseCls}${e.labelPos==="left"?" op-field--label-left":""}`);this.labelEl=r("label","op-field__label");let i=r("div","op-field__control",{},this.createControl());return this.helpEl=r("div","op-field__help",{id:`${this.id}-help`}),this.errorEl=r("div","op-field__error",{id:`${this.id}-error`,role:"alert"}),t.append(this.labelEl,i,this.helpEl,this.errorEl),t}onRender(){let e=this.config,t=this.inputEl;t.id||=s("op-input"),this.labelEl.htmlFor=t.id,this.setLabel(e.label??""),this.setHelp(e.help??""),this.setRequired(!!e.required),this.setReadonly(!!e.readonly),this.applyValue(this.value),this.paintError(),this.listen(this.el,"focusin",()=>{this.el.classList.add("is-focused"),this.emit("focus")}),this.listen(this.el,"focusout",i=>{this.el.contains(i.relatedTarget)||(this.flushSettled(),this.el.classList.remove("is-focused"),(e.validateOn??"blur")==="blur"&&this.validate(),this.emit("blur"))})}focusEl(){return this.render(),this.inputEl}getValue(){return this.value}setValue(e,t=!1){let i=this.value;this.value=e,this.rendered&&this.applyValue(e),this.isEqual(i,e)||this.changed(i,t)}commit(e){let t=this.value;this.value=e,this.isEqual(t,e)||this.changed(t,!1)}changed(e,t){this.updateDirty(),!t&&((this.config.validateOn==="change"||this.error)&&this.validate(),this.emit("change",this.value,e),this.queueSettled())}queueSettled(){this.cancelSettle?.(),this.cancelSettle=void 0;let e=this.config.debounce;if(!e)return void this.emit("settled",this.value);this.cancelSettle=this.later(()=>{this.cancelSettle=void 0,this.emit("settled",this.value)},e)}flushSettled(){this.cancelSettle&&(this.cancelSettle(),this.cancelSettle=void 0,this.emit("settled",this.value))}updateDirty(){let e=this.isDirty();e!==this.dirty&&(this.dirty=e,this.rendered&&this.el.classList.toggle("is-dirty",e),this.emit("dirty-change",e))}getDisplayText(){let e=this.value;return this.isEmpty(e)?"":String(e)}clear(){this.setValue(this.emptyValue())}isDirty(){return!this.isEqual(this.value,this.original)}markClean(){this.original=this.value,this.updateDirty()}reset(){this.setValue(this.original,!0),this.clearError()}check(){let e=this.value;if(this.isEmpty(e))return this.config.required?l("required"):"";for(let t of this.config.validators??[]){let i=t(e,this);if(typeof i=="string")return i}return""}validate(){let e=this.check();return e?this.setError(e):this.clearError(),!e}isValid(){return!this.check()}getError(){return this.error}setError(e){let t=this.error;this.error=e,this.paintError(),e&&e!==t&&this.emit("invalid",e)}clearError(){this.error&&(this.error="",this.paintError(),this.emit("valid"))}paintError(){this.rendered&&(this.errorEl.textContent=this.error,this.el.classList.toggle("is-invalid",!!this.error),this.inputEl.setAttribute("aria-invalid",String(!!this.error)),this.describe())}describe(){let e=[this.error&&this.errorEl.id,this.config.help&&this.helpEl.id].filter(Boolean);e.length?this.inputEl.setAttribute("aria-describedby",e.join(" ")):this.inputEl.removeAttribute("aria-describedby")}setLabel(e){this.config.label=e,this.rendered&&(this.labelEl.textContent=e,this.labelEl.hidden=!e)}setHelp(e){this.config.help=e,this.rendered&&(this.helpEl.textContent=e,this.helpEl.hidden=!e,this.describe())}setRequired(e){this.config.required=e,this.rendered&&(this.el.classList.toggle("is-required",e),this.inputEl.setAttribute("aria-required",String(e)))}setReadonly(e){this.config.readonly=e,this.rendered&&(this.el.classList.toggle("is-readonly",e),this.onReadonly(e))}setValidators(e){this.config.validators=e}onReadonly(e){}};export{n as a};
2
+ //# sourceMappingURL=chunk-K2DGY6MP.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/field.ts"],
4
+ "sourcesContent": ["import { Component, type ComponentConfig } from './component';\nimport { h, uid } from './dom';\nimport { t } from './i18n';\nimport type { Validator } from './validators';\n\nexport interface FieldConfig<V = unknown> extends ComponentConfig {\n name?: string;\n label?: string;\n labelPos?: 'top' | 'left';\n value?: V;\n required?: boolean;\n readonly?: boolean;\n help?: string;\n validators?: Validator<V>[];\n /** When to validate on its own. After the first error it revalidates on every change. Default `blur`. */\n validateOn?: 'blur' | 'change' | 'submit';\n /** ms of quiet after the last change before `settled` fires (0 = right away). `change` itself is never delayed. */\n debounce?: number;\n}\n\n/**\n * Base of every field: value, validation, dirty tracking, label and messages.\n * Subclasses implement `createControl` (build the control, assign `inputEl`), `applyValue` (value \u2192 DOM)\n * and call `commit` when the user edits (DOM \u2192 value).\n */\nexport abstract class Field<V = unknown, C extends FieldConfig<V> = FieldConfig<V>> extends Component<C> {\n protected override baseCls = 'op-field';\n protected value: V;\n protected original: V;\n protected error = '';\n /** The focusable control; `label for`, `aria-invalid` and `aria-describedby` point at it. */\n protected inputEl!: HTMLElement;\n private labelEl!: HTMLElement;\n private helpEl!: HTMLElement;\n private errorEl!: HTMLElement;\n private dirty = false;\n private cancelSettle?: () => void;\n\n constructor(config: C = {} as C) {\n super(config);\n this.value = this.original = config.value ?? this.emptyValue();\n }\n\n get name(): string | undefined {\n return this.config.name;\n }\n\n protected abstract createControl(): HTMLElement;\n protected abstract applyValue(value: V): void;\n protected emptyValue(): V {\n return '' as V;\n }\n protected isEmpty(v: V): boolean {\n return v == null || (v as unknown) === '' || (Array.isArray(v) && !v.length);\n }\n protected isEqual(a: V, b: V): boolean {\n return a === b || JSON.stringify(a) === JSON.stringify(b);\n }\n\n protected override build(): HTMLElement {\n const c = this.config;\n const el = h('div', `${this.baseCls}${c.labelPos === 'left' ? ' op-field--label-left' : ''}`);\n this.labelEl = h('label', 'op-field__label');\n const control = h('div', 'op-field__control', {}, this.createControl());\n this.helpEl = h('div', 'op-field__help', { id: `${this.id}-help` });\n this.errorEl = h('div', 'op-field__error', { id: `${this.id}-error`, role: 'alert' });\n el.append(this.labelEl, control, this.helpEl, this.errorEl);\n return el;\n }\n\n protected override onRender(): void {\n const c = this.config;\n const input = this.inputEl;\n input.id ||= uid('op-input');\n (this.labelEl as HTMLLabelElement).htmlFor = input.id;\n this.setLabel(c.label ?? '');\n this.setHelp(c.help ?? '');\n this.setRequired(!!c.required);\n this.setReadonly(!!c.readonly);\n this.applyValue(this.value);\n this.paintError();\n this.listen(this.el, 'focusin', () => {\n this.el.classList.add('is-focused');\n this.emit('focus');\n });\n this.listen(this.el, 'focusout', (e: FocusEvent) => {\n if (this.el.contains(e.relatedTarget as Node)) return;\n this.flushSettled();\n this.el.classList.remove('is-focused');\n if ((c.validateOn ?? 'blur') === 'blur') this.validate();\n this.emit('blur');\n });\n }\n\n protected override focusEl(): HTMLElement {\n this.render();\n return this.inputEl;\n }\n\n // ---- value ---------------------------------------------------------------------------------\n\n getValue(): V {\n return this.value;\n }\n\n /** Sets the value programmatically. `silent` skips the `change` event and validation. */\n setValue(v: V, silent = false): void {\n const old = this.value;\n this.value = v;\n if (this.rendered) this.applyValue(v);\n if (!this.isEqual(old, v)) this.changed(old, silent);\n }\n\n /** For subclasses: the user edited the control and the DOM already shows `v`. */\n protected commit(v: V): void {\n const old = this.value;\n this.value = v;\n if (!this.isEqual(old, v)) this.changed(old, false);\n }\n\n private changed(old: V, silent: boolean): void {\n this.updateDirty();\n if (silent) return;\n if (this.config.validateOn === 'change' || this.error) this.validate();\n this.emit('change', this.value, old);\n this.queueSettled();\n }\n\n /** `settled(value)`: the value after the user stopped changing it for `debounce` ms (immediately without `debounce`). */\n private queueSettled(): void {\n this.cancelSettle?.();\n this.cancelSettle = undefined;\n const ms = this.config.debounce;\n if (!ms) return void this.emit('settled', this.value);\n this.cancelSettle = this.later(() => {\n this.cancelSettle = undefined;\n this.emit('settled', this.value);\n }, ms);\n }\n\n /** Fires a pending `settled` now (Enter, blur, end of a drag...). No-op when nothing is waiting. */\n protected flushSettled(): void {\n if (!this.cancelSettle) return;\n this.cancelSettle();\n this.cancelSettle = undefined;\n this.emit('settled', this.value);\n }\n\n private updateDirty(): void {\n const d = this.isDirty();\n if (d === this.dirty) return;\n this.dirty = d;\n if (this.rendered) this.el.classList.toggle('is-dirty', d);\n this.emit('dirty-change', d);\n }\n\n /** What the user sees as this field's value (a select's label, a formatted date); used by summaries such as the StepForm review. */\n getDisplayText(): string {\n const v = this.value;\n return this.isEmpty(v) ? '' : String(v);\n }\n\n /** Sets the empty value (`''`, `null`, `false`...) and emits `change`. */\n clear(): void {\n this.setValue(this.emptyValue());\n }\n\n isDirty(): boolean {\n return !this.isEqual(this.value, this.original);\n }\n\n /** The current value becomes the \"original\" (as after loading or saving). */\n markClean(): void {\n this.original = this.value;\n this.updateDirty();\n }\n\n reset(): void {\n this.setValue(this.original, true);\n this.clearError();\n }\n\n // ---- validation ----------------------------------------------------------------------------\n\n /** Returns the error message for the current value, or `''`. No UI side effects. */\n protected check(): string {\n const v = this.value;\n if (this.isEmpty(v)) return this.config.required ? t('required') : '';\n for (const fn of this.config.validators ?? []) {\n const r = fn(v, this as Field<any>);\n if (typeof r === 'string') return r;\n }\n return '';\n }\n\n validate(): boolean {\n const msg = this.check();\n if (msg) this.setError(msg);\n else this.clearError();\n return !msg;\n }\n\n isValid(): boolean {\n return !this.check();\n }\n\n getError(): string {\n return this.error;\n }\n\n setError(msg: string): void {\n const was = this.error;\n this.error = msg;\n this.paintError();\n if (msg && msg !== was) this.emit('invalid', msg);\n }\n\n clearError(): void {\n if (!this.error) return;\n this.error = '';\n this.paintError();\n this.emit('valid');\n }\n\n private paintError(): void {\n if (!this.rendered) return;\n this.errorEl.textContent = this.error;\n this.el.classList.toggle('is-invalid', !!this.error);\n this.inputEl.setAttribute('aria-invalid', String(!!this.error));\n this.describe();\n }\n\n private describe(): void {\n const ids = [this.error && this.errorEl.id, this.config.help && this.helpEl.id].filter(Boolean);\n if (ids.length) this.inputEl.setAttribute('aria-describedby', ids.join(' '));\n else this.inputEl.removeAttribute('aria-describedby');\n }\n\n // ---- setters -------------------------------------------------------------------------------\n\n setLabel(label: string): void {\n this.config.label = label;\n if (!this.rendered) return;\n this.labelEl.textContent = label;\n this.labelEl.hidden = !label;\n }\n\n setHelp(help: string): void {\n this.config.help = help;\n if (!this.rendered) return;\n this.helpEl.textContent = help;\n this.helpEl.hidden = !help;\n this.describe();\n }\n\n setRequired(required: boolean): void {\n this.config.required = required;\n if (!this.rendered) return;\n this.el.classList.toggle('is-required', required);\n this.inputEl.setAttribute('aria-required', String(required));\n }\n\n setReadonly(readonly: boolean): void {\n this.config.readonly = readonly;\n if (!this.rendered) return;\n this.el.classList.toggle('is-readonly', readonly);\n this.onReadonly(readonly);\n }\n\n setValidators(validators: Validator<V>[]): void {\n this.config.validators = validators;\n }\n\n protected onReadonly(_readonly: boolean): void {}\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["Field", "Component", "config", "v", "a", "b", "c", "el", "h", "control", "input", "uid", "e", "silent", "old", "ms", "d", "t", "fn", "r", "msg", "was", "ids", "label", "help", "required", "readonly", "validators", "_readonly"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{c as o}from"./chunk-UPOBGNJ5.js";import{c as i}from"./chunk-VV7CFMPZ.js";import{b as r}from"./chunk-IYPKPLCU.js";var n="button:not(:disabled)",e=class extends o{baseCls="op-toolbar";rover;shorthand(t){if(t==="->")return{type:"spacer"};if(t==="-")return{type:"spacer",line:!0};if(t===" ")return{type:"spacer",width:8};throw new Error(`Optikos: unknown toolbar shorthand "${t}"`)}build(){let t=super.build();return t.setAttribute("role","toolbar"),this.config.vertical&&t.setAttribute("aria-orientation","vertical"),t}onRender(){this.config.layout??=this.config.vertical?{type:"vbox",align:"stretch"}:{type:"hbox",align:"center"},super.onRender(),this.el.classList.toggle("op-toolbar--vertical",!!this.config.vertical),this.rover=i(this.el,{selector:n,orientation:this.config.vertical?"vertical":"horizontal"}),this.own(()=>this.rover?.destroy())}notifyMount(){super.notifyMount(),this.rover?.sync()}};r("toolbar",e);export{e as a};
2
+ //# sourceMappingURL=chunk-LBCWEWPN.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/components/layout/toolbar/toolbar.ts"],
4
+ "sourcesContent": ["import { Container, type ContainerConfig } from '../../../core/container';\nimport { register, type AnyConfig } from '../../../core/registry';\nimport { roving } from '../../../core/focus';\nimport '../spacer/spacer';\n\nexport interface ToolbarConfig extends ContainerConfig {\n vertical?: boolean;\n}\n\n// Only buttons join the roving tab stop; text fields keep their own arrow-key behavior.\nconst FOCUSABLE = 'button:not(:disabled)';\n\n/** Items may be `'->'` (fill space), `'-'` (separator) or `' '` (small gap). */\nexport class Toolbar extends Container<ToolbarConfig> {\n protected override baseCls = 'op-toolbar';\n private rover?: ReturnType<typeof roving>;\n\n protected override shorthand(s: string): AnyConfig {\n if (s === '->') return { type: 'spacer' };\n if (s === '-') return { type: 'spacer', line: true };\n if (s === ' ') return { type: 'spacer', width: 8 };\n throw new Error(`Optikos: unknown toolbar shorthand \"${s}\"`);\n }\n\n protected override build() {\n const el = super.build();\n el.setAttribute('role', 'toolbar');\n if (this.config.vertical) el.setAttribute('aria-orientation', 'vertical');\n return el;\n }\n\n protected override onRender() {\n this.config.layout ??= this.config.vertical ? { type: 'vbox', align: 'stretch' } : { type: 'hbox', align: 'center' };\n super.onRender();\n this.el.classList.toggle('op-toolbar--vertical', !!this.config.vertical);\n // Roving tabindex over buttons: one Tab stop, arrows move.\n this.rover = roving(this.el, { selector: FOCUSABLE, orientation: this.config.vertical ? 'vertical' : 'horizontal' });\n this.own(() => this.rover?.destroy());\n }\n\n override notifyMount() {\n super.notifyMount();\n this.rover?.sync();\n }\n}\nregister('toolbar', Toolbar);\n"],
5
+ "mappings": "wHAUA,IAAMA,EAAY,wBAGLC,EAAN,cAAsBC,CAAyB,CACjC,QAAU,aACrB,MAEW,UAAUC,EAAsB,CACjD,GAAIA,IAAM,KAAM,MAAO,CAAE,KAAM,QAAS,EACxC,GAAIA,IAAM,IAAK,MAAO,CAAE,KAAM,SAAU,KAAM,EAAK,EACnD,GAAIA,IAAM,IAAK,MAAO,CAAE,KAAM,SAAU,MAAO,CAAE,EACjD,MAAM,IAAI,MAAM,uCAAuCA,CAAC,GAAG,CAC7D,CAEmB,OAAQ,CACzB,IAAMC,EAAK,MAAM,MAAM,EACvB,OAAAA,EAAG,aAAa,OAAQ,SAAS,EAC7B,KAAK,OAAO,UAAUA,EAAG,aAAa,mBAAoB,UAAU,EACjEA,CACT,CAEmB,UAAW,CAC5B,KAAK,OAAO,SAAW,KAAK,OAAO,SAAW,CAAE,KAAM,OAAQ,MAAO,SAAU,EAAI,CAAE,KAAM,OAAQ,MAAO,QAAS,EACnH,MAAM,SAAS,EACf,KAAK,GAAG,UAAU,OAAO,uBAAwB,CAAC,CAAC,KAAK,OAAO,QAAQ,EAEvE,KAAK,MAAQC,EAAO,KAAK,GAAI,CAAE,SAAUL,EAAW,YAAa,KAAK,OAAO,SAAW,WAAa,YAAa,CAAC,EACnH,KAAK,IAAI,IAAM,KAAK,OAAO,QAAQ,CAAC,CACtC,CAES,aAAc,CACrB,MAAM,YAAY,EAClB,KAAK,OAAO,KAAK,CACnB,CACF,EACAM,EAAS,UAAWL,CAAO",
6
+ "names": ["FOCUSABLE", "Toolbar", "Container", "s", "el", "roving", "register"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{a as u}from"./chunk-DXO3UJKL.js";import{a as f}from"./chunk-PSPQH35P.js";import{b as c,c as h,d as g}from"./chunk-4DHQKECB.js";import{c as a}from"./chunk-IHAYOSBR.js";import{b as p}from"./chunk-IYPKPLCU.js";import{b as d}from"./chunk-PZSHOSOS.js";import{e as s}from"./chunk-MA5BJL3S.js";var l=class extends u{baseCls="op-field op-textfield op-picker op-suggest op-lookup";def;suggestStore;win;constructor(e){let t=c(e.lookup);super({...e,icon:!1,valueField:t.valueField??"id",displayField:t.displayField??"name",query:o=>this.suggest(o)}),this.def=t}async suggest(e){let t=this.suggestStore??=h(this.def),o=this.def.queryField??this.def.filters?.[0]?.name??this.config.displayField,i=this.def.filters?.find(n=>n.name===o)?.field??o;return await t.filter({field:i,op:"contains",value:e}),t.getData()}createControl(){let e=super.createControl(),t=d("button","op-picker__trigger op-lookup__btn",{type:"button",tabindex:-1,"aria-label":s("lookupOpen"),"aria-haspopup":"dialog"},a("search"));return this.listen(t,"mousedown",o=>o.preventDefault()),this.listen(t,"click",()=>this.openDialog()),e.append(t),this.own(()=>this.win?.destroy()),e}onKey(e){e.key==="F4"||e.altKey&&e.key==="ArrowDown"?(e.preventDefault(),this.openDialog()):super.onKey(e)}onDisabled(e){super.onDisabled(e),this.el.querySelector(".op-lookup__btn").disabled=e}openDialog(){if(this.win||this.config.disabled||this.config.readonly||!this.rendered)return;this.close();let e=this.def,t=new g({lookup:e,flex:1}),o=this.typed?this.input.value:"";t.on("confirm",r=>i(r));let i=r=>{r[0]&&this.pickRecord(r[0]),n.close()},n=this.win=new f({title:e.title??s("search"),width:e.width??720,height:e.height??520,layout:"fit",items:[t],buttons:[{text:s("cancel"),handler:()=>n.close()},{text:s("lookupSelect"),variant:"primary",handler:()=>i(t.getSelection())}]});n.on("destroy",()=>{this.win=void 0,this.rendered&&this.input.focus()}),n.show(),o&&t.search(o),t.focus()}pickRecord(e){let{valueField:t,displayField:o}=this.config,i={value:e.get(t),label:String(e.get(o)??e.get(t)??""),raw:e.data};this.pick(i)}};p("lookupfield",l);export{l as a};
2
+ //# sourceMappingURL=chunk-LEE2FEEL.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/components/fields/lookupfield/lookupfield.ts"],
4
+ "sourcesContent": ["import { SuggestField, type SuggestConfig } from '../suggestfield/suggestfield';\nimport { register } from '../../../core/registry';\nimport { h } from '../../../core/dom';\nimport { t } from '../../../core/i18n';\nimport type { Model } from '../../../data/model';\nimport type { Store } from '../../../data/store';\nimport { iconEl } from '../../base/icon/icon';\nimport { Window } from '../../overlays/window/window';\nimport { SearchGrid, resolveLookup, lookupStore, type LookupDef } from '../../data/searchgrid/searchgrid';\n\nexport interface LookupFieldConfig<V = unknown> extends SuggestConfig<V> {\n /** A definition or the name given to `registerLookup`. */\n lookup: LookupDef | string;\n}\n\n/**\n * Pick a record from a big set: type to get suggestions, or press the magnifier (or F4) to open a search window\n * with filters and a grid. The value is the record's `valueField`; the text is its `displayField`.\n */\nexport class LookupField<V = unknown> extends SuggestField<V> {\n protected override baseCls = 'op-field op-textfield op-picker op-suggest op-lookup';\n private def: LookupDef;\n private suggestStore?: Store<any>;\n private win?: Window;\n\n constructor(config: LookupFieldConfig<V>) {\n const def = resolveLookup(config.lookup);\n super({\n ...config,\n icon: false,\n valueField: def.valueField ?? 'id',\n displayField: def.displayField ?? 'name',\n query: (text) => this.suggest(text),\n });\n this.def = def;\n }\n\n /** Typing: filter a private store by the quick-search field and offer its page of records. */\n private async suggest(text: string) {\n const s = (this.suggestStore ??= lookupStore(this.def));\n const name = this.def.queryField ?? this.def.filters?.[0]?.name ?? this.config.displayField!;\n const field = this.def.filters?.find((f) => f.name === name)?.field ?? name;\n await s.filter({ field, op: 'contains', value: text });\n return s.getData();\n }\n\n protected override createControl() {\n const wrap = super.createControl();\n const btn = h('button', 'op-picker__trigger op-lookup__btn', { type: 'button', tabindex: -1, 'aria-label': t('lookupOpen'), 'aria-haspopup': 'dialog' }, iconEl('search'));\n this.listen(btn, 'mousedown', (e: Event) => e.preventDefault());\n this.listen(btn, 'click', () => this.openDialog());\n wrap.append(btn);\n this.own(() => this.win?.destroy());\n return wrap;\n }\n\n protected override onKey(e: KeyboardEvent) {\n if (e.key === 'F4' || (e.altKey && e.key === 'ArrowDown')) {\n e.preventDefault();\n this.openDialog();\n } else super.onKey(e);\n }\n\n protected override onDisabled(disabled: boolean) {\n super.onDisabled(disabled);\n (this.el.querySelector('.op-lookup__btn') as HTMLButtonElement).disabled = disabled;\n }\n\n /** Opens the search window; the text typed so far pre-fills the quick-search field. */\n openDialog(): void {\n if (this.win || this.config.disabled || this.config.readonly || !this.rendered) return;\n this.close();\n const d = this.def;\n const sg = new SearchGrid({ lookup: d, flex: 1 });\n const text = this.typed ? this.input.value : '';\n sg.on('confirm', (recs: Model[]) => done(recs));\n const done = (recs: Model[]) => {\n if (recs[0]) this.pickRecord(recs[0]);\n win.close();\n };\n const win: Window = (this.win = new Window({\n title: d.title ?? t('search'),\n width: d.width ?? 720,\n height: d.height ?? 520,\n layout: 'fit',\n items: [sg],\n buttons: [{ text: t('cancel'), handler: () => win.close() }, { text: t('lookupSelect'), variant: 'primary', handler: () => done(sg.getSelection()) }],\n }));\n win.on('destroy', () => {\n this.win = undefined;\n if (this.rendered) this.input.focus();\n });\n win.show();\n if (text) void sg.search(text);\n sg.focus();\n }\n\n private pickRecord(rec: Model): void {\n const { valueField, displayField } = this.config;\n const item = { value: rec.get(valueField!), label: String(rec.get(displayField!) ?? rec.get(valueField!) ?? ''), raw: rec.data };\n this.pick(item as any);\n }\n}\nregister('lookupfield', LookupField);\n"],
5
+ "mappings": "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",
6
+ "names": ["LookupField", "SuggestField", "config", "def", "resolveLookup", "text", "s", "lookupStore", "name", "field", "f", "wrap", "btn", "h", "t", "iconEl", "e", "disabled", "d", "sg", "SearchGrid", "recs", "done", "win", "Window", "rec", "valueField", "displayField", "item", "register"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{c as g}from"./chunk-IHAYOSBR.js";import{a as m,b}from"./chunk-IYPKPLCU.js";import{b as h,f}from"./chunk-PZSHOSOS.js";import{e as s}from"./chunk-MA5BJL3S.js";var c=class extends m{baseCls="op-pagination";tag="nav";unsub;onRender(){this.el.setAttribute("aria-label",s("pageLabel")),this.listen(this.el,"click",t=>{let n=t.target.closest("button[data-page]");n&&!n.disabled&&this.setPage(Number(n.dataset.page))}),this.bindStore(this.config.store),this.own(()=>this.unsub?.()),this.paint()}bindStore(t){this.unsub?.(),this.unsub=t?.subscribe(()=>this.paint())}getPage(){return this.config.store?.page??this.config.page??1}size(){return this.config.store?.pageSize||this.config.pageSize||20}total(){return this.config.store?.totalCount??this.config.total??0}pages(){return Math.max(1,Math.ceil(this.total()/this.size()))}setPage(t){t=f(t,1,this.pages()),!(t===this.getPage()||this.emit("before-page-change",t)===!1)&&(this.config.store?this.config.store.setPage(t):(this.config.page=t,this.paint()),this.emit("page-change",t))}setTotal(t){this.config.total=t,this.paint()}setPageSize(t){this.config.pageSize=t,this.paint()}setStore(t){this.config.store=t,this.bindStore(t),this.paint()}window(){let t=this.pages(),n=this.getPage(),o=this.config.siblings??1;if(t<=o*2+5)return Array.from({length:t},(i,a)=>a+1);let p=new Set([1,t,...Array.from({length:o*2+1},(i,a)=>n-o+a)].filter(i=>i>=1&&i<=t)),r=[],e=0;for(let i of[...p].sort((a,l)=>a-l))i-e>1&&r.push(i-e===2?i-1:null),r.push(i),e=i;return r}paint(){if(!this.rendered)return;let t=this.getPage(),n=this.pages(),o=(e,i,a,l=!1,u=!1)=>h("button",`op-button op-button--ghost op-pagination__btn${u?" is-current":""}`,{type:"button","data-page":e,"aria-label":a,"aria-current":u?"page":null,disabled:l},i),p=[o(1,g("chevrons-left"),s("pageFirst"),t===1),o(t-1,g("chevron-left"),s("pagePrev"),t===1),...this.window().map(e=>e==null?h("span","op-pagination__gap",{"aria-hidden":"true"},"\u2026"):o(e,String(e),s("pageGoto",{n:e}),!1,e===t)),o(t+1,g("chevron-right"),s("pageNext"),t===n),o(n,g("chevrons-right"),s("pageLast"),t===n)];if(this.config.showInfo!==!1){let e=this.total(),i=this.size();p.push(h("span","op-pagination__info",{},e?s("pageInfo",{from:(t-1)*i+1,to:Math.min(t*i,e),total:e}):""))}let r=this.el.contains(document.activeElement)?document.activeElement.dataset.page:void 0;this.el.replaceChildren(...p),r&&this.el.querySelector(`[data-page="${r}"]:not(:disabled)`)?.focus()}};b("pagination",c);export{c as a};
2
+ //# sourceMappingURL=chunk-LMGCV35W.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/components/data/pagination/pagination.ts"],
4
+ "sourcesContent": ["import { Component, type ComponentConfig } from '../../../core/component';\nimport { register } from '../../../core/registry';\nimport { h, clamp } from '../../../core/dom';\nimport { t } from '../../../core/i18n';\nimport { iconEl } from '../../base/icon/icon';\nimport type { Store } from '../../../data/store';\n\nexport interface PaginationConfig extends ComponentConfig {\n /** Reads and drives the store's page. Without it, use `total`/`pageSize`/`page`. */\n store?: Store<any>;\n total?: number;\n pageSize?: number;\n page?: number;\n /** Page buttons shown on each side of the current one. Default 1. */\n siblings?: number;\n showInfo?: boolean;\n}\n\nexport class Pagination extends Component<PaginationConfig> {\n protected override baseCls = 'op-pagination';\n protected override tag = 'nav' as const;\n private unsub?: () => void;\n\n protected override onRender() {\n this.el.setAttribute('aria-label', t('pageLabel'));\n this.listen(this.el, 'click', (e: Event) => {\n const b = (e.target as HTMLElement).closest<HTMLButtonElement>('button[data-page]');\n if (b && !b.disabled) this.setPage(Number(b.dataset.page));\n });\n this.bindStore(this.config.store);\n this.own(() => this.unsub?.());\n this.paint();\n }\n\n private bindStore(store?: Store<any>) {\n this.unsub?.();\n this.unsub = store?.subscribe(() => this.paint());\n }\n\n getPage(): number {\n return this.config.store?.page ?? this.config.page ?? 1;\n }\n private size(): number {\n return this.config.store?.pageSize || this.config.pageSize || 20;\n }\n private total(): number {\n return this.config.store?.totalCount ?? this.config.total ?? 0;\n }\n private pages(): number {\n return Math.max(1, Math.ceil(this.total() / this.size()));\n }\n\n /** Goes to a page (`before-page-change` can cancel), updating the store when there is one. */\n setPage(page: number): void {\n page = clamp(page, 1, this.pages());\n if (page === this.getPage() || this.emit('before-page-change', page) === false) return;\n if (this.config.store) this.config.store.setPage(page);\n else {\n this.config.page = page;\n this.paint();\n }\n this.emit('page-change', page);\n }\n setTotal(total: number) {\n this.config.total = total;\n this.paint();\n }\n setPageSize(size: number) {\n this.config.pageSize = size;\n this.paint();\n }\n setStore(store: Store<any>) {\n this.config.store = store;\n this.bindStore(store);\n this.paint();\n }\n\n /** Page numbers with `null` where a gap is collapsed: 1 \u2026 4 5 6 \u2026 20. */\n private window(): Array<number | null> {\n const last = this.pages();\n const cur = this.getPage();\n const s = this.config.siblings ?? 1;\n if (last <= s * 2 + 5) return Array.from({ length: last }, (_, i) => i + 1); // small sets: no gaps\n const set = new Set([1, last, ...Array.from({ length: s * 2 + 1 }, (_, i) => cur - s + i)].filter((n) => n >= 1 && n <= last));\n const out: Array<number | null> = [];\n let prev = 0;\n for (const n of [...set].sort((a, b) => a - b)) {\n if (n - prev > 1) out.push(n - prev === 2 ? n - 1 : null);\n out.push(n);\n prev = n;\n }\n return out;\n }\n\n private paint() {\n if (!this.rendered) return;\n const cur = this.getPage();\n const last = this.pages();\n const btn = (page: number, content: Node | string, label: string, disabled = false, current = false) =>\n h('button', `op-button op-button--ghost op-pagination__btn${current ? ' is-current' : ''}`, { type: 'button', 'data-page': page, 'aria-label': label, 'aria-current': current ? 'page' : null, disabled }, content);\n const nodes: Node[] = [\n btn(1, iconEl('chevrons-left'), t('pageFirst'), cur === 1),\n btn(cur - 1, iconEl('chevron-left'), t('pagePrev'), cur === 1),\n ...this.window().map((n) => (n == null ? h('span', 'op-pagination__gap', { 'aria-hidden': 'true' }, '\u2026') : btn(n, String(n), t('pageGoto', { n }), false, n === cur))),\n btn(cur + 1, iconEl('chevron-right'), t('pageNext'), cur === last),\n btn(last, iconEl('chevrons-right'), t('pageLast'), cur === last),\n ];\n if (this.config.showInfo !== false) {\n const total = this.total();\n const size = this.size();\n nodes.push(h('span', 'op-pagination__info', {}, total ? t('pageInfo', { from: (cur - 1) * size + 1, to: Math.min(cur * size, total), total }) : ''));\n }\n const focusPage = this.el.contains(document.activeElement) ? (document.activeElement as HTMLElement).dataset.page : undefined;\n this.el.replaceChildren(...nodes);\n if (focusPage) this.el.querySelector<HTMLElement>(`[data-page=\"${focusPage}\"]:not(:disabled)`)?.focus();\n }\n}\nregister('pagination', Pagination);\n"],
5
+ "mappings": "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",
6
+ "names": ["Pagination", "Component", "t", "e", "b", "store", "page", "clamp", "total", "size", "last", "cur", "s", "_", "i", "set", "n", "out", "prev", "btn", "content", "label", "disabled", "current", "nodes", "iconEl", "focusPage", "register"]
7
+ }
@@ -0,0 +1,3 @@
1
+ import{a as E}from"./chunk-XZEOSW3Q.js";import{c as m}from"./chunk-IHAYOSBR.js";import{a as y,b as v}from"./chunk-IYPKPLCU.js";import{b as n}from"./chunk-PZSHOSOS.js";import{d as f,e as a}from"./chunk-MA5BJL3S.js";var _=/(\*\*[^*\n]+\*\*|\*[^*\n]+\*|`[^`\n]+`)/;function T(d){let t=[];return d.split(`
2
+ `).forEach((e,s)=>{s&&t.push(document.createElement("br"));for(let i of e.split(_))i&&(i.startsWith("**")&&i.endsWith("**")&&i.length>4?t.push(n("strong","",{},i.slice(2,-2))):i.startsWith("`")&&i.endsWith("`")&&i.length>2?t.push(n("code","op-chat__code",{},i.slice(1,-1))):i.startsWith("*")&&i.endsWith("*")&&i.length>2?t.push(n("em","",{},i.slice(1,-1))):t.push(document.createTextNode(i)))}),t}var h=d=>new Date(d).toDateString(),b=()=>f()._lang,p=class extends y{baseCls="op-chat";msgs=[];seq=0;logEl;emptyEl;typingEl;chipsEl;input;sendBtn;busy=!1;build(){let t=this.config;return this.logEl=n("div","op-chat__log",{role:"log","aria-live":"polite","aria-relevant":"additions","aria-label":a("chatLog"),tabindex:0}),this.emptyEl=n("div","op-chat__empty",{},a("chatEmpty")),this.typingEl=n("div","op-chat__typing",{"aria-hidden":"true"},n("span","op-chat__dots",{},n("i"),n("i"),n("i")),n("span","op-chat__typing-text")),this.typingEl.hidden=!0,this.chipsEl=n("div","op-chat__suggestions",{role:"group","aria-label":a("chatSuggestions")}),this.input=n("textarea","op-chat__input",{rows:1,placeholder:t.placeholder??a("chatPlaceholder"),"aria-label":t.placeholder??a("chatPlaceholder"),maxlength:t.maxLength??null}),this.sendBtn=new E({icon:"send",variant:"primary",ariaLabel:a("chatSend"),handler:()=>this.submit()}),this.own(()=>this.sendBtn.destroy()),n("div",this.baseCls,{},this.logEl,this.chipsEl,n("div","op-chat__composer",{},this.input,this.sendBtn.el))}onRender(){let t=this.config;this.listen(this.input,"input",()=>this.grow()),this.listen(this.input,"keydown",e=>{e.key!=="Enter"||e.shiftKey||e.isComposing||t.sendOnEnter===!1||(e.preventDefault(),this.submit())}),this.listen(this.chipsEl,"click",e=>{let s=e.target.closest("[data-s]");s&&(this.emit("suggestion",s.dataset.s),this.send(s.dataset.s))}),this.listen(this.logEl,"click",e=>{let s=e.target.closest(".op-chat__msg"),i=s&&this.msgs.find(o=>String(o.id)===s.dataset.id);i&&this.emit("message-click",i)}),this.setReadonly(!!t.readonly),this.msgs=(t.messages??[]).map(e=>this.norm(e)),this.setSuggestions(t.suggestions??[]),this.renderAll()}notifyMount(){super.notifyMount(),this.rendered&&(this.sendBtn.notifyMount(),this.scrollToBottom())}norm(t){let e=t.time==null?Date.now():new Date(t.time).getTime();return{...t,id:t.id??`m${++this.seq}`,at:e}}getMessages(){return this.msgs}addMessage(t){let e=this.norm(t);if(this.msgs.push(e),!this.rendered)return this.config.messages=this.msgs,e;let s=this.nearBottom()||e.from===this.config.me;return this.mountMsg(e,this.msgs.length-1),this.syncEmpty(),s&&this.scrollToBottom(),e}setMessages(t){this.msgs=t.map(e=>this.norm(e)),this.config.messages=this.msgs,this.rendered&&(this.renderAll(),this.scrollToBottom())}updateMessage(t,e){let s=this.msgs.findIndex(g=>g.id===t);if(s<0)return;let i=this.nearBottom();if(this.msgs[s]={...this.msgs[s],...e,at:e.time!=null?new Date(e.time).getTime():this.msgs[s].at},!this.rendered)return;let o=this.msgEl(t),r=this.buildMsg(this.msgs[s],s);o?o.replaceWith(r):this.logEl.insertBefore(r,this.typingEl),this.decorate(s),i&&this.scrollToBottom()}appendToMessage(t,e){let s=this.msgs.find(r=>r.id===t);if(!s)return;s.text+=e;let i=this.msgEl(t)?.querySelector(".op-chat__text");if(!i)return;let o=this.nearBottom();this.fill(i,s),o&&this.scrollToBottom()}removeMessage(t){this.msgs=this.msgs.filter(e=>e.id!==t),this.rendered&&this.renderAll()}msgEl(t){return this.logEl.querySelector(`[data-id="${CSS.escape(String(t))}"]`)}renderAll(){this.logEl.replaceChildren(this.emptyEl,...this.msgs.flatMap((t,e)=>this.nodesFor(t,e)),this.typingEl),this.syncEmpty()}nodesFor(t,e){let s=this.msgs[e-1],i=[];return(!s||h(s.at)!==h(t.at))&&i.push(n("div","op-chat__day",{role:"separator"},n("span","",{},this.dayLabel(t.at)))),i.push(this.buildMsg(t,e)),i}mountMsg(t,e){for(let s of this.nodesFor(t,e))this.logEl.insertBefore(s,this.typingEl);this.decorate(e-1),this.decorate(e)}dayLabel(t){let e=h(t),s=Date.now();return e===h(s)?a("chatToday"):e===h(s-864e5)?a("chatYesterday"):new Intl.DateTimeFormat(b(),{dateStyle:"medium"}).format(t)}fill(t,e){let s=this.config.renderer?this.config.renderer(e):T(e.text);t.replaceChildren(...Array.isArray(s)?s:[s])}buildMsg(t,e){let s=this.config,i=t.from===s.me,o=s.users?.[t.from],r=n("article",`op-chat__msg ${i?"is-me":"is-them"}`,{"data-id":String(t.id)}),g=n("div","op-chat__bubble");if(!i&&s.showAuthors!==!1&&o){let c=n("div","op-chat__author",{},o.name);o.color&&(c.style.color=o.color),g.append(c)}let l=t.replyTo!=null?this.msgs.find(c=>c.id===t.replyTo):void 0;l&&g.append(n("div","op-chat__reply",{"aria-label":a("chatReply")},n("strong","",{},l.from===s.me?"":s.users?.[l.from]?.name??l.from),l.text.length>80?`${l.text.slice(0,80)}\u2026`:l.text));let u=n("div","op-chat__text");this.fill(u,t);let M=new Intl.DateTimeFormat(b(),{hour:"2-digit",minute:"2-digit"}).format(t.at);return g.append(u,n("span","op-chat__meta",{},n("time","",{datetime:new Date(t.at).toISOString()},M),i&&t.status?this.statusEl(t.status):"")),r.append(g),this.group(r,e),r}statusEl(t){let e=n("span",`op-chat__status is-${t}`,{role:"img","aria-label":t});return t==="error"?e.append(m("alert")):t!=="sending"&&e.append(m("check"),...t==="sent"?[]:[m("check")]),e}group(t,e){let s=this.msgs[e],i=(o,r)=>!!o&&!!r&&o.from===r.from&&h(o.at)===h(r.at);t.classList.toggle("is-first",!i(this.msgs[e-1],s)),t.classList.toggle("is-last",!i(s,this.msgs[e+1])),t.querySelector(".op-chat__author")?.toggleAttribute("hidden",i(this.msgs[e-1],s))}decorate(t){let e=this.msgs[t],s=e&&this.msgEl(e.id);s&&this.group(s,t)}syncEmpty(){this.emptyEl.hidden=this.msgs.length>0,this.el.classList.toggle("is-empty",!this.msgs.length)}nearBottom(){let t=this.logEl;return t.scrollHeight-t.scrollTop-t.clientHeight<48}scrollToBottom(){this.render(),this.logEl.scrollTop=this.logEl.scrollHeight}setTyping(t){let e=this.nearBottom();this.typingEl.hidden=!t,this.typingEl.querySelector(".op-chat__typing-text").textContent=typeof t=="string"?a("chatTyping",{n:t}):"",t&&e&&this.scrollToBottom()}setSuggestions(t){this.config.suggestions=t,this.rendered&&(this.chipsEl.hidden=!t.length,this.chipsEl.replaceChildren(...t.map(e=>n("button","op-chat__chip",{type:"button","data-s":e},e))))}setBusy(t){this.busy=t,this.el.classList.toggle("is-busy",t),this.logEl.setAttribute("aria-busy",String(t)),this.sendBtn.setDisabled(t||!!this.config.readonly);for(let e of Array.from(this.chipsEl.children))e.disabled=t||!!this.config.readonly}setReadonly(t){this.config.readonly=t,this.rendered&&(this.input.readOnly=t,this.el.classList.toggle("is-readonly",t),this.setBusy(this.busy))}setPlaceholder(t){this.config.placeholder=t,this.rendered&&(this.input.placeholder=t)}focus(){this.render(),this.input.focus()}grow(){this.input.style.height="auto",this.input.style.height=`${this.input.scrollHeight}px`}submit(){let t=this.input.value;this.send(t)&&(this.input.value="",this.grow())}send(t){if(t=t.trim(),!t||this.busy||this.config.readonly||this.emit("before-send",t)===!1)return!1;let e=this.addMessage({from:this.config.me,text:t,time:Date.now(),status:"sending"});return this.emit("send",t,e),!0}};v("chat",p);export{p as a};
3
+ //# sourceMappingURL=chunk-LV6HXFHU.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/components/chat/chat/chat.ts"],
4
+ "sourcesContent": ["import { Component, type ComponentConfig } from '../../../core/component';\nimport { register } from '../../../core/registry';\nimport { h } from '../../../core/dom';\nimport { t, getLocale } from '../../../core/i18n';\nimport { Button } from '../../base/button/button';\nimport { iconEl } from '../../base/icon/icon';\n\nexport interface ChatMessage {\n id?: string | number;\n /** The author's id (compare with the `me` of the config). */\n from: string;\n text: string;\n time?: number | Date | string;\n status?: 'sending' | 'sent' | 'delivered' | 'read' | 'error';\n /** The id of the message this one answers (shown as a quote). */\n replyTo?: string | number;\n /** Anything the app wants to keep with the message. */\n meta?: unknown;\n}\n\nexport interface ChatConfig extends ComponentConfig {\n messages?: ChatMessage[];\n /** The id of whoever is using the chat: their messages go on the right. */\n me: string;\n users?: Record<string, { name: string; color?: string }>;\n /** Show the author's name above the first bubble of a group of theirs. Default true. */\n showAuthors?: boolean;\n placeholder?: string;\n /** Prompt chips above the composer; clicking one sends it. */\n suggestions?: string[];\n readonly?: boolean;\n /** Enter sends and Shift+Enter breaks the line. Default true. */\n sendOnEnter?: boolean;\n maxLength?: number;\n /** Custom bubble content. The default is a minimal, safe formatting (`**bold**`, `*italic*`, `` `code` ``, line breaks). */\n renderer?: (msg: ChatMessage) => string | Node;\n}\n\ntype Msg = ChatMessage & { id: string | number; at: number };\n\nconst INLINE = /(\\*\\*[^*\\n]+\\*\\*|\\*[^*\\n]+\\*|`[^`\\n]+`)/;\n\n/** Text \u2192 nodes: bold, italic, code and line breaks only. Everything else stays text, so nothing can inject markup. */\nfunction format(text: string): Node[] {\n const out: Node[] = [];\n text.split('\\n').forEach((line, i) => {\n if (i) out.push(document.createElement('br'));\n for (const part of line.split(INLINE)) {\n if (!part) continue;\n if (part.startsWith('**') && part.endsWith('**') && part.length > 4) out.push(h('strong', '', {}, part.slice(2, -2)));\n else if (part.startsWith('`') && part.endsWith('`') && part.length > 2) out.push(h('code', 'op-chat__code', {}, part.slice(1, -1)));\n else if (part.startsWith('*') && part.endsWith('*') && part.length > 2) out.push(h('em', '', {}, part.slice(1, -1)));\n else out.push(document.createTextNode(part));\n }\n });\n return out;\n}\n\nconst dayKey = (at: number) => new Date(at).toDateString();\nconst lang = () => getLocale()._lang;\n\n/** Conversation view: bubbles grouped by author and day, delivery ticks, typing dots, streaming text, prompt chips and a composer. */\nexport class Chat extends Component<ChatConfig> {\n protected override baseCls = 'op-chat';\n private msgs: Msg[] = [];\n private seq = 0;\n private logEl!: HTMLElement;\n private emptyEl!: HTMLElement;\n private typingEl!: HTMLElement;\n private chipsEl!: HTMLElement;\n private input!: HTMLTextAreaElement;\n private sendBtn!: Button;\n private busy = false;\n\n protected override build() {\n const c = this.config;\n this.logEl = h('div', 'op-chat__log', { role: 'log', 'aria-live': 'polite', 'aria-relevant': 'additions', 'aria-label': t('chatLog'), tabindex: 0 });\n this.emptyEl = h('div', 'op-chat__empty', {}, t('chatEmpty'));\n this.typingEl = h('div', 'op-chat__typing', { 'aria-hidden': 'true' }, h('span', 'op-chat__dots', {}, h('i'), h('i'), h('i')), h('span', 'op-chat__typing-text'));\n this.typingEl.hidden = true;\n this.chipsEl = h('div', 'op-chat__suggestions', { role: 'group', 'aria-label': t('chatSuggestions') });\n this.input = h('textarea', 'op-chat__input', { rows: 1, placeholder: c.placeholder ?? t('chatPlaceholder'), 'aria-label': c.placeholder ?? t('chatPlaceholder'), maxlength: c.maxLength ?? null });\n this.sendBtn = new Button({ icon: 'send', variant: 'primary', ariaLabel: t('chatSend'), handler: () => this.submit() });\n this.own(() => this.sendBtn.destroy());\n return h('div', this.baseCls, {}, this.logEl, this.chipsEl, h('div', 'op-chat__composer', {}, this.input, this.sendBtn.el));\n }\n\n protected override onRender() {\n const c = this.config;\n this.listen(this.input, 'input', () => this.grow());\n this.listen(this.input, 'keydown', (e: KeyboardEvent) => {\n if (e.key !== 'Enter' || e.shiftKey || e.isComposing || c.sendOnEnter === false) return;\n e.preventDefault();\n this.submit();\n });\n this.listen(this.chipsEl, 'click', (e: Event) => {\n const b = (e.target as HTMLElement).closest<HTMLElement>('[data-s]');\n if (!b) return;\n this.emit('suggestion', b.dataset.s);\n this.send(b.dataset.s!);\n });\n this.listen(this.logEl, 'click', (e: Event) => {\n const el = (e.target as HTMLElement).closest<HTMLElement>('.op-chat__msg');\n const m = el && this.msgs.find((x) => String(x.id) === el.dataset.id);\n if (m) this.emit('message-click', m);\n });\n this.setReadonly(!!c.readonly);\n this.msgs = (c.messages ?? []).map((m) => this.norm(m));\n this.setSuggestions(c.suggestions ?? []);\n this.renderAll();\n }\n\n override notifyMount() {\n super.notifyMount();\n if (!this.rendered) return; // a Chat in a lazy tab is told it is mounted before it has a DOM\n this.sendBtn.notifyMount();\n this.scrollToBottom();\n }\n\n // ---- messages ------------------------------------------------------------------------------\n\n private norm(m: ChatMessage): Msg {\n const at = m.time == null ? Date.now() : new Date(m.time).getTime();\n return { ...m, id: m.id ?? `m${++this.seq}`, at };\n }\n\n getMessages(): ChatMessage[] {\n return this.msgs;\n }\n\n addMessage(msg: ChatMessage): ChatMessage {\n const m = this.norm(msg);\n this.msgs.push(m);\n if (!this.rendered) return (this.config.messages = this.msgs, m);\n const stick = this.nearBottom() || m.from === this.config.me;\n this.mountMsg(m, this.msgs.length - 1);\n this.syncEmpty();\n if (stick) this.scrollToBottom();\n return m;\n }\n\n setMessages(list: ChatMessage[]): void {\n this.msgs = list.map((m) => this.norm(m));\n this.config.messages = this.msgs; // so a chat that is not rendered yet (a lazy tab) starts with them\n if (this.rendered) {\n this.renderAll();\n this.scrollToBottom();\n }\n }\n\n updateMessage(id: string | number, patch: Partial<ChatMessage>): void {\n const i = this.msgs.findIndex((m) => m.id === id);\n if (i < 0) return;\n const stick = this.nearBottom();\n this.msgs[i] = { ...this.msgs[i], ...patch, at: patch.time != null ? new Date(patch.time).getTime() : this.msgs[i].at };\n if (!this.rendered) return;\n const old = this.msgEl(id);\n const fresh = this.buildMsg(this.msgs[i], i);\n old ? old.replaceWith(fresh) : this.logEl.insertBefore(fresh, this.typingEl);\n this.decorate(i);\n if (stick) this.scrollToBottom();\n }\n\n /** Adds text to a message: for answers that arrive in pieces (AI streaming). Only that bubble's text is redrawn. */\n appendToMessage(id: string | number, text: string): void {\n const m = this.msgs.find((x) => x.id === id);\n if (!m) return;\n m.text += text;\n const el = this.msgEl(id)?.querySelector('.op-chat__text');\n if (!el) return;\n const stick = this.nearBottom();\n this.fill(el as HTMLElement, m);\n if (stick) this.scrollToBottom();\n }\n\n removeMessage(id: string | number): void {\n this.msgs = this.msgs.filter((m) => m.id !== id);\n if (this.rendered) this.renderAll();\n }\n\n private msgEl(id: string | number): HTMLElement | null {\n return this.logEl.querySelector(`[data-id=\"${CSS.escape(String(id))}\"]`);\n }\n\n // ---- rendering -----------------------------------------------------------------------------\n\n private renderAll(): void {\n this.logEl.replaceChildren(this.emptyEl, ...this.msgs.flatMap((m, i) => this.nodesFor(m, i)), this.typingEl);\n this.syncEmpty();\n }\n\n /** The day separator (when the day changes) and the message itself. */\n private nodesFor(m: Msg, i: number): HTMLElement[] {\n const prev = this.msgs[i - 1];\n const nodes: HTMLElement[] = [];\n if (!prev || dayKey(prev.at) !== dayKey(m.at)) nodes.push(h('div', 'op-chat__day', { role: 'separator' }, h('span', '', {}, this.dayLabel(m.at))));\n nodes.push(this.buildMsg(m, i));\n return nodes;\n }\n\n private mountMsg(m: Msg, i: number): void {\n for (const n of this.nodesFor(m, i)) this.logEl.insertBefore(n, this.typingEl);\n this.decorate(i - 1);\n this.decorate(i);\n }\n\n private dayLabel(at: number): string {\n const d = dayKey(at);\n const now = Date.now();\n if (d === dayKey(now)) return t('chatToday');\n if (d === dayKey(now - 864e5)) return t('chatYesterday');\n return new Intl.DateTimeFormat(lang(), { dateStyle: 'medium' }).format(at);\n }\n\n private fill(el: HTMLElement, m: Msg): void {\n const out = this.config.renderer ? this.config.renderer(m) : format(m.text);\n el.replaceChildren(...(Array.isArray(out) ? out : [out]));\n }\n\n private buildMsg(m: Msg, i: number): HTMLElement {\n const c = this.config;\n const mine = m.from === c.me;\n const user = c.users?.[m.from];\n const el = h('article', `op-chat__msg ${mine ? 'is-me' : 'is-them'}`, { 'data-id': String(m.id) });\n const bubble = h('div', 'op-chat__bubble');\n if (!mine && c.showAuthors !== false && user) {\n const name = h('div', 'op-chat__author', {}, user.name);\n if (user.color) name.style.color = user.color;\n bubble.append(name);\n }\n const quoted = m.replyTo != null ? this.msgs.find((x) => x.id === m.replyTo) : undefined;\n if (quoted) bubble.append(h('div', 'op-chat__reply', { 'aria-label': t('chatReply') }, h('strong', '', {}, quoted.from === c.me ? '' : (c.users?.[quoted.from]?.name ?? quoted.from)), quoted.text.length > 80 ? `${quoted.text.slice(0, 80)}\u2026` : quoted.text));\n const text = h('div', 'op-chat__text');\n this.fill(text, m);\n const time = new Intl.DateTimeFormat(lang(), { hour: '2-digit', minute: '2-digit' }).format(m.at);\n bubble.append(text, h('span', 'op-chat__meta', {}, h('time', '', { datetime: new Date(m.at).toISOString() }, time), mine && m.status ? this.statusEl(m.status) : ''));\n el.append(bubble);\n this.group(el, i);\n return el;\n }\n\n private statusEl(s: NonNullable<ChatMessage['status']>): HTMLElement {\n const el = h('span', `op-chat__status is-${s}`, { role: 'img', 'aria-label': s });\n if (s === 'error') el.append(iconEl('alert'));\n else if (s !== 'sending') el.append(iconEl('check'), ...(s === 'sent' ? [] : [iconEl('check')]));\n return el;\n }\n\n /** Group classes: first/last bubble of a run by the same author on the same day. */\n private group(el: HTMLElement, i: number): void {\n const m = this.msgs[i];\n const same = (a?: Msg, b?: Msg) => !!a && !!b && a.from === b.from && dayKey(a.at) === dayKey(b.at);\n el.classList.toggle('is-first', !same(this.msgs[i - 1], m));\n el.classList.toggle('is-last', !same(m, this.msgs[i + 1]));\n el.querySelector('.op-chat__author')?.toggleAttribute('hidden', same(this.msgs[i - 1], m));\n }\n\n private decorate(i: number): void {\n const m = this.msgs[i];\n const el = m && this.msgEl(m.id);\n if (el) this.group(el, i);\n }\n\n private syncEmpty(): void {\n this.emptyEl.hidden = this.msgs.length > 0;\n this.el.classList.toggle('is-empty', !this.msgs.length);\n }\n\n private nearBottom(): boolean {\n const l = this.logEl;\n return l.scrollHeight - l.scrollTop - l.clientHeight < 48;\n }\n\n scrollToBottom(): void {\n this.render();\n this.logEl.scrollTop = this.logEl.scrollHeight;\n }\n\n // ---- typing, suggestions, state ------------------------------------------------------------\n\n /** `true` shows the dots, a name shows \"name is typing\u2026\", `false` hides them. */\n setTyping(who: boolean | string): void {\n const stick = this.nearBottom();\n this.typingEl.hidden = !who;\n this.typingEl.querySelector('.op-chat__typing-text')!.textContent = typeof who === 'string' ? t('chatTyping', { n: who }) : '';\n if (who && stick) this.scrollToBottom();\n }\n\n setSuggestions(list: string[]): void {\n this.config.suggestions = list;\n if (!this.rendered) return;\n this.chipsEl.hidden = !list.length;\n this.chipsEl.replaceChildren(...list.map((s) => h('button', 'op-chat__chip', { type: 'button', 'data-s': s }, s)));\n }\n\n /** While busy (an answer is on its way) sending is off and the log tells assistive tech to wait. */\n setBusy(busy: boolean): void {\n this.busy = busy;\n this.el.classList.toggle('is-busy', busy);\n this.logEl.setAttribute('aria-busy', String(busy));\n this.sendBtn.setDisabled(busy || !!this.config.readonly);\n for (const b of Array.from(this.chipsEl.children) as HTMLButtonElement[]) b.disabled = busy || !!this.config.readonly;\n }\n\n setReadonly(readonly: boolean): void {\n this.config.readonly = readonly;\n if (!this.rendered) return;\n this.input.readOnly = readonly;\n this.el.classList.toggle('is-readonly', readonly);\n this.setBusy(this.busy);\n }\n\n setPlaceholder(text: string): void {\n this.config.placeholder = text;\n if (this.rendered) this.input.placeholder = text;\n }\n\n override focus(): void {\n this.render();\n this.input.focus();\n }\n\n // ---- sending -------------------------------------------------------------------------------\n\n private grow(): void {\n this.input.style.height = 'auto';\n this.input.style.height = `${this.input.scrollHeight}px`;\n }\n\n private submit(): void {\n const text = this.input.value;\n if (this.send(text)) {\n this.input.value = '';\n this.grow();\n }\n }\n\n /** The same path as the send button. Returns false when nothing was sent (empty, busy, read-only or cancelled). */\n send(text: string): boolean {\n text = text.trim();\n if (!text || this.busy || this.config.readonly || this.emit('before-send', text) === false) return false;\n const msg = this.addMessage({ from: this.config.me, text, time: Date.now(), status: 'sending' });\n this.emit('send', text, msg);\n return true;\n }\n}\nregister('chat', Chat);\n"],
5
+ "mappings": "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",
6
+ "names": ["INLINE", "format", "text", "out", "line", "i", "part", "h", "dayKey", "at", "lang", "getLocale", "Chat", "Component", "c", "t", "Button", "b", "el", "m", "x", "msg", "stick", "list", "id", "patch", "old", "fresh", "prev", "nodes", "n", "d", "now", "mine", "user", "bubble", "name", "quoted", "time", "s", "iconEl", "same", "a", "l", "who", "busy", "readonly", "register"]
7
+ }
@@ -0,0 +1,2 @@
1
+ var l=class{handlers=new Map;on(e,a){let t=this.handlers.get(e);return t?t.push(a):this.handlers.set(e,[a]),()=>this.off(e,a)}once(e,a){let t=this.on(e,(...r)=>(t(),a(...r)));return t}off(e,a){if(!a)this.handlers.delete(e);else{let t=this.handlers.get(e);t&&this.handlers.set(e,t.filter(r=>r!==a))}}emit(e,...a){let t=!0;for(let r of this.handlers.get(e)??[])r(...a)===!1&&(t=!1);return t}clearListeners(){this.handlers.clear()}};var i={_lang:"en",_currency:"USD",_firstDay:"0",required:"This field is required",minLength:"Enter at least {n} characters",maxLength:"Enter at most {n} characters",pattern:"Invalid format",email:"Enter a valid email address",min:"Must be at least {n}",max:"Must be at most {n}",range:"Must be between {min} and {max}",number:"Enter a valid number",date:"Enter a valid date",dateMin:"Date must be on or after {n}",dateMax:"Date must be on or before {n}",notInList:"Choose a value from the list",loading:"Loading",close:"Close",ok:"OK",cancel:"Cancel",clear:"Clear",collapse:"Collapse",expand:"Expand",empty:"No data",search:"Search",lookupOpen:"Open search",lookupSelect:"Select",fbEq:"equals",fbNe:"does not equal",fbContains:"contains",fbNotContains:"does not contain",fbStarts:"starts with",fbEnds:"ends with",fbGt:"greater than",fbGe:"greater than or equal",fbLt:"less than",fbLe:"less than or equal",fbBetween:"is between",fbNotBetween:"is not between",fbIn:"is any of",fbNin:"is none of",fbEmpty:"is empty",fbNotEmpty:"is not empty",fbAnd:"Match all (AND)",fbOr:"Match any (OR)",fbAddFilter:"Add filter",fbAddGroup:"Add group",fbRemove:"Remove",fbClear:"Clear all",fbApply:"Apply",fbField:"Field",fbOperator:"Operator",fbValue:"Value",fbTo:"and",fbList:"a, b, c",fbNone:"No filters",fbLabel:"Filters",views:"Views",viewsName:"Name for this view",viewsSave:"Save view",viewsSaveAs:"Save as new view\u2026",viewsDefault:"Open with this view",viewsDelete:"Delete view",viewsConfirmDelete:'Delete the view "{n}"?',viewsReset:"Reset to initial",cpPlaceholder:"Type a command or search\u2026",cpLabel:"Command palette",cpFilters:"Categories",cpAll:"All",cpEmpty:"No matching commands",cpHint:"\u2191\u2193 navigate \xB7 Enter run \xB7 Esc close",chatPlaceholder:"Type a message",chatSend:"Send",chatTyping:"{n} is typing\u2026",chatToday:"Today",chatYesterday:"Yesterday",chatEmpty:"No messages yet",chatLog:"Conversation",chatSuggestions:"Suggestions",chatReply:"Reply",wDockLeft:"Dock to the left",wDockRight:"Dock to the right",wDockTop:"Dock to the top",wDockBottom:"Dock to the bottom",tabErrors:"errors",stepOptional:"optional",stepDone:"completed",stepError:"has errors",stepBack:"Back",stepNext:"Next",stepFinish:"Finish",stepReview:"Review",stepSteps:"Steps",stepOf:"Step {n} of {total}",secretShow:"Show value",secretHide:"Hide value",secretStored:"A value is saved. It cannot be shown again.",secretReplace:"Replace",secretKeep:"Keep current",secretWarnTitle:"Replace the saved value?",secretWarn:"The saved value cannot be displayed and will be discarded as soon as you replace it. Type the new value next; it takes effect when you save.",gridSelected:"{n} selected",gridSelectAll:"Select all {n}",gridClearSel:"Clear selection",gridSelectRow:"Select row",gridSelectPage:"Select all rows",gridRowActions:"Row actions",gridColumns:"Columns",gridResize:"Resize column",gridGroupAll:"All",gridOtherCols:"Other",gridGroups:"Column groups",gridColumnSearch:"Search columns",gridNoColumns:"No matching columns",noResults:"No results",results:"{n} results",pageFirst:"First page",pagePrev:"Previous page",pageNext:"Next page",pageLast:"Last page",pageLabel:"Pagination",pageGoto:"Page {n}",pageInfo:"{from}\u2013{to} of {total}",calPrev:"Previous",calNext:"Next",calOpen:"Open calendar",calMonth:"Choose month",breadcrumb:"Breadcrumb",breadcrumbMore:"Show more",sortAsc:"sorted ascending",sortDesc:"sorted descending"},c={_lang:"pt-BR",_currency:"BRL",_firstDay:"0",required:"Campo obrigat\xF3rio",minLength:"Informe ao menos {n} caracteres",maxLength:"Informe no m\xE1ximo {n} caracteres",pattern:"Formato inv\xE1lido",email:"Informe um e-mail v\xE1lido",min:"Deve ser no m\xEDnimo {n}",max:"Deve ser no m\xE1ximo {n}",range:"Deve estar entre {min} e {max}",number:"Informe um n\xFAmero v\xE1lido",date:"Informe uma data v\xE1lida",dateMin:"A data deve ser {n} ou posterior",dateMax:"A data deve ser {n} ou anterior",notInList:"Escolha um valor da lista",loading:"Carregando",close:"Fechar",ok:"OK",cancel:"Cancelar",clear:"Limpar",collapse:"Recolher",expand:"Expandir",empty:"Sem dados",search:"Pesquisar",lookupOpen:"Abrir pesquisa",lookupSelect:"Selecionar",fbEq:"igual a",fbNe:"diferente de",fbContains:"cont\xE9m",fbNotContains:"n\xE3o cont\xE9m",fbStarts:"come\xE7a com",fbEnds:"termina com",fbGt:"maior que",fbGe:"maior ou igual a",fbLt:"menor que",fbLe:"menor ou igual a",fbBetween:"entre",fbNotBetween:"fora do intervalo",fbIn:"\xE9 um de",fbNin:"n\xE3o \xE9 nenhum de",fbEmpty:"est\xE1 vazio",fbNotEmpty:"n\xE3o est\xE1 vazio",fbAnd:"Todas (E)",fbOr:"Qualquer uma (OU)",fbAddFilter:"Adicionar filtro",fbAddGroup:"Adicionar grupo",fbRemove:"Remover",fbClear:"Limpar tudo",fbApply:"Aplicar",fbField:"Campo",fbOperator:"Operador",fbValue:"Valor",fbTo:"e",fbList:"a, b, c",fbNone:"Sem filtros",fbLabel:"Filtros",views:"Vis\xF5es",viewsName:"Nome desta vis\xE3o",viewsSave:"Salvar vis\xE3o",viewsSaveAs:"Salvar como nova vis\xE3o\u2026",viewsDefault:"Abrir com esta vis\xE3o",viewsDelete:"Excluir vis\xE3o",viewsConfirmDelete:'Excluir a vis\xE3o "{n}"?',viewsReset:"Voltar ao inicial",cpPlaceholder:"Digite um comando ou pesquise\u2026",cpLabel:"Paleta de comandos",cpFilters:"Categorias",cpAll:"Todas",cpEmpty:"Nenhum comando encontrado",cpHint:"\u2191\u2193 navegar \xB7 Enter executar \xB7 Esc fechar",chatPlaceholder:"Digite uma mensagem",chatSend:"Enviar",chatTyping:"{n} est\xE1 digitando\u2026",chatToday:"Hoje",chatYesterday:"Ontem",chatEmpty:"Nenhuma mensagem ainda",chatLog:"Conversa",chatSuggestions:"Sugest\xF5es",chatReply:"Responder",wDockLeft:"Fixar \xE0 esquerda",wDockRight:"Fixar \xE0 direita",wDockTop:"Fixar em cima",wDockBottom:"Fixar embaixo",tabErrors:"erros",stepOptional:"opcional",stepDone:"conclu\xEDda",stepError:"com erros",stepBack:"Voltar",stepNext:"Pr\xF3ximo",stepFinish:"Concluir",stepReview:"Revis\xE3o",stepSteps:"Etapas",stepOf:"Etapa {n} de {total}",secretShow:"Mostrar valor",secretHide:"Ocultar valor",secretStored:"H\xE1 um valor salvo. Ele n\xE3o pode ser exibido novamente.",secretReplace:"Substituir",secretKeep:"Manter o atual",secretWarnTitle:"Substituir o valor salvo?",secretWarn:"O valor salvo n\xE3o pode ser exibido e ser\xE1 descartado assim que voc\xEA o substituir. Digite o novo valor em seguida; ele s\xF3 vale quando voc\xEA salvar.",gridSelected:"{n} selecionado(s)",gridSelectAll:"Selecionar todos os {n}",gridClearSel:"Limpar sele\xE7\xE3o",gridSelectRow:"Selecionar linha",gridSelectPage:"Selecionar todas as linhas",gridRowActions:"A\xE7\xF5es da linha",gridColumns:"Colunas",gridResize:"Redimensionar coluna",gridGroupAll:"Todas",gridOtherCols:"Outras",gridGroups:"Grupos de colunas",gridColumnSearch:"Buscar colunas",gridNoColumns:"Nenhuma coluna encontrada",noResults:"Nenhum resultado",results:"{n} resultados",pageFirst:"Primeira p\xE1gina",pagePrev:"P\xE1gina anterior",pageNext:"Pr\xF3xima p\xE1gina",pageLast:"\xDAltima p\xE1gina",pageLabel:"Pagina\xE7\xE3o",pageGoto:"P\xE1gina {n}",pageInfo:"{from}\u2013{to} de {total}",calPrev:"Anterior",calNext:"Pr\xF3ximo",calOpen:"Abrir calend\xE1rio",calMonth:"Escolher m\xEAs",breadcrumb:"Trilha de navega\xE7\xE3o",breadcrumbMore:"Mostrar mais",sortAsc:"ordenado crescente",sortDesc:"ordenado decrescente"},n={en:i,"pt-BR":c},s=i;function p(o){typeof o=="string"?s=n[o]??n[Object.keys(n).find(e=>e.startsWith(o.split("-")[0]))??"en"]:(s={...i,...o},o._lang&&(n[o._lang]=s))}var m=()=>s;function u(o,e){let a=s[o]??i[o]??o;return e?a.replace(/\{(\w+)\}/g,(t,r)=>String(e[r]??"")):a}export{l as a,n as b,p as c,m as d,u as e};
2
+ //# sourceMappingURL=chunk-MA5BJL3S.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/emitter.ts", "../src/core/i18n.ts"],
4
+ "sourcesContent": ["export type Handler = (...args: any[]) => unknown;\n\n/** Minimal observer. A handler that returns `false` makes `emit` return `false` (used by `before-*` events). */\nexport class Emitter {\n private handlers = new Map<string, Handler[]>();\n\n /** Subscribes; returns the unsubscribe function. */\n on(name: string, fn: Handler): () => void {\n const list = this.handlers.get(name);\n if (list) list.push(fn);\n else this.handlers.set(name, [fn]);\n return () => this.off(name, fn);\n }\n\n once(name: string, fn: Handler): () => void {\n const off = this.on(name, (...a) => {\n off();\n return fn(...a);\n });\n return off;\n }\n\n off(name: string, fn?: Handler): void {\n if (!fn) this.handlers.delete(name);\n else {\n const list = this.handlers.get(name);\n if (list) this.handlers.set(name, list.filter((f) => f !== fn));\n }\n }\n\n /** Returns `false` if any handler returned `false` (the event was cancelled). */\n emit(name: string, ...args: unknown[]): boolean {\n let ok = true;\n for (const fn of this.handlers.get(name) ?? []) if (fn(...args) === false) ok = false;\n return ok;\n }\n\n clearListeners(): void {\n this.handlers.clear();\n }\n}\n", "export type Locale = Record<string, string>;\n\nconst en: Locale = {\n _lang: 'en',\n _currency: 'USD',\n _firstDay: '0',\n required: 'This field is required',\n minLength: 'Enter at least {n} characters',\n maxLength: 'Enter at most {n} characters',\n pattern: 'Invalid format',\n email: 'Enter a valid email address',\n min: 'Must be at least {n}',\n max: 'Must be at most {n}',\n range: 'Must be between {min} and {max}',\n number: 'Enter a valid number',\n date: 'Enter a valid date',\n dateMin: 'Date must be on or after {n}',\n dateMax: 'Date must be on or before {n}',\n notInList: 'Choose a value from the list',\n loading: 'Loading',\n close: 'Close',\n ok: 'OK',\n cancel: 'Cancel',\n clear: 'Clear',\n collapse: 'Collapse',\n expand: 'Expand',\n empty: 'No data',\n search: 'Search',\n lookupOpen: 'Open search',\n lookupSelect: 'Select',\n fbEq: 'equals',\n fbNe: 'does not equal',\n fbContains: 'contains',\n fbNotContains: 'does not contain',\n fbStarts: 'starts with',\n fbEnds: 'ends with',\n fbGt: 'greater than',\n fbGe: 'greater than or equal',\n fbLt: 'less than',\n fbLe: 'less than or equal',\n fbBetween: 'is between',\n fbNotBetween: 'is not between',\n fbIn: 'is any of',\n fbNin: 'is none of',\n fbEmpty: 'is empty',\n fbNotEmpty: 'is not empty',\n fbAnd: 'Match all (AND)',\n fbOr: 'Match any (OR)',\n fbAddFilter: 'Add filter',\n fbAddGroup: 'Add group',\n fbRemove: 'Remove',\n fbClear: 'Clear all',\n fbApply: 'Apply',\n fbField: 'Field',\n fbOperator: 'Operator',\n fbValue: 'Value',\n fbTo: 'and',\n fbList: 'a, b, c',\n fbNone: 'No filters',\n fbLabel: 'Filters',\n views: 'Views',\n viewsName: 'Name for this view',\n viewsSave: 'Save view',\n viewsSaveAs: 'Save as new view\u2026',\n viewsDefault: 'Open with this view',\n viewsDelete: 'Delete view',\n viewsConfirmDelete: 'Delete the view \"{n}\"?',\n viewsReset: 'Reset to initial',\n cpPlaceholder: 'Type a command or search\u2026',\n cpLabel: 'Command palette',\n cpFilters: 'Categories',\n cpAll: 'All',\n cpEmpty: 'No matching commands',\n cpHint: '\u2191\u2193 navigate \u00B7 Enter run \u00B7 Esc close',\n chatPlaceholder: 'Type a message',\n chatSend: 'Send',\n chatTyping: '{n} is typing\u2026',\n chatToday: 'Today',\n chatYesterday: 'Yesterday',\n chatEmpty: 'No messages yet',\n chatLog: 'Conversation',\n chatSuggestions: 'Suggestions',\n chatReply: 'Reply',\n wDockLeft: 'Dock to the left',\n wDockRight: 'Dock to the right',\n wDockTop: 'Dock to the top',\n wDockBottom: 'Dock to the bottom',\n tabErrors: 'errors',\n stepOptional: 'optional',\n stepDone: 'completed',\n stepError: 'has errors',\n stepBack: 'Back',\n stepNext: 'Next',\n stepFinish: 'Finish',\n stepReview: 'Review',\n stepSteps: 'Steps',\n stepOf: 'Step {n} of {total}',\n secretShow: 'Show value',\n secretHide: 'Hide value',\n secretStored: 'A value is saved. It cannot be shown again.',\n secretReplace: 'Replace',\n secretKeep: 'Keep current',\n secretWarnTitle: 'Replace the saved value?',\n secretWarn: 'The saved value cannot be displayed and will be discarded as soon as you replace it. Type the new value next; it takes effect when you save.',\n gridSelected: '{n} selected',\n gridSelectAll: 'Select all {n}',\n gridClearSel: 'Clear selection',\n gridSelectRow: 'Select row',\n gridSelectPage: 'Select all rows',\n gridRowActions: 'Row actions',\n gridColumns: 'Columns',\n gridResize: 'Resize column',\n gridGroupAll: 'All',\n gridOtherCols: 'Other',\n gridGroups: 'Column groups',\n gridColumnSearch: 'Search columns',\n gridNoColumns: 'No matching columns',\n noResults: 'No results',\n results: '{n} results',\n pageFirst: 'First page',\n pagePrev: 'Previous page',\n pageNext: 'Next page',\n pageLast: 'Last page',\n pageLabel: 'Pagination',\n pageGoto: 'Page {n}',\n pageInfo: '{from}\u2013{to} of {total}',\n calPrev: 'Previous',\n calNext: 'Next',\n calOpen: 'Open calendar',\n calMonth: 'Choose month',\n breadcrumb: 'Breadcrumb',\n breadcrumbMore: 'Show more',\n sortAsc: 'sorted ascending',\n sortDesc: 'sorted descending',\n};\n\nconst ptBR: Locale = {\n _lang: 'pt-BR',\n _currency: 'BRL',\n _firstDay: '0',\n required: 'Campo obrigat\u00F3rio',\n minLength: 'Informe ao menos {n} caracteres',\n maxLength: 'Informe no m\u00E1ximo {n} caracteres',\n pattern: 'Formato inv\u00E1lido',\n email: 'Informe um e-mail v\u00E1lido',\n min: 'Deve ser no m\u00EDnimo {n}',\n max: 'Deve ser no m\u00E1ximo {n}',\n range: 'Deve estar entre {min} e {max}',\n number: 'Informe um n\u00FAmero v\u00E1lido',\n date: 'Informe uma data v\u00E1lida',\n dateMin: 'A data deve ser {n} ou posterior',\n dateMax: 'A data deve ser {n} ou anterior',\n notInList: 'Escolha um valor da lista',\n loading: 'Carregando',\n close: 'Fechar',\n ok: 'OK',\n cancel: 'Cancelar',\n clear: 'Limpar',\n collapse: 'Recolher',\n expand: 'Expandir',\n empty: 'Sem dados',\n search: 'Pesquisar',\n lookupOpen: 'Abrir pesquisa',\n lookupSelect: 'Selecionar',\n fbEq: 'igual a',\n fbNe: 'diferente de',\n fbContains: 'cont\u00E9m',\n fbNotContains: 'n\u00E3o cont\u00E9m',\n fbStarts: 'come\u00E7a com',\n fbEnds: 'termina com',\n fbGt: 'maior que',\n fbGe: 'maior ou igual a',\n fbLt: 'menor que',\n fbLe: 'menor ou igual a',\n fbBetween: 'entre',\n fbNotBetween: 'fora do intervalo',\n fbIn: '\u00E9 um de',\n fbNin: 'n\u00E3o \u00E9 nenhum de',\n fbEmpty: 'est\u00E1 vazio',\n fbNotEmpty: 'n\u00E3o est\u00E1 vazio',\n fbAnd: 'Todas (E)',\n fbOr: 'Qualquer uma (OU)',\n fbAddFilter: 'Adicionar filtro',\n fbAddGroup: 'Adicionar grupo',\n fbRemove: 'Remover',\n fbClear: 'Limpar tudo',\n fbApply: 'Aplicar',\n fbField: 'Campo',\n fbOperator: 'Operador',\n fbValue: 'Valor',\n fbTo: 'e',\n fbList: 'a, b, c',\n fbNone: 'Sem filtros',\n fbLabel: 'Filtros',\n views: 'Vis\u00F5es',\n viewsName: 'Nome desta vis\u00E3o',\n viewsSave: 'Salvar vis\u00E3o',\n viewsSaveAs: 'Salvar como nova vis\u00E3o\u2026',\n viewsDefault: 'Abrir com esta vis\u00E3o',\n viewsDelete: 'Excluir vis\u00E3o',\n viewsConfirmDelete: 'Excluir a vis\u00E3o \"{n}\"?',\n viewsReset: 'Voltar ao inicial',\n cpPlaceholder: 'Digite um comando ou pesquise\u2026',\n cpLabel: 'Paleta de comandos',\n cpFilters: 'Categorias',\n cpAll: 'Todas',\n cpEmpty: 'Nenhum comando encontrado',\n cpHint: '\u2191\u2193 navegar \u00B7 Enter executar \u00B7 Esc fechar',\n chatPlaceholder: 'Digite uma mensagem',\n chatSend: 'Enviar',\n chatTyping: '{n} est\u00E1 digitando\u2026',\n chatToday: 'Hoje',\n chatYesterday: 'Ontem',\n chatEmpty: 'Nenhuma mensagem ainda',\n chatLog: 'Conversa',\n chatSuggestions: 'Sugest\u00F5es',\n chatReply: 'Responder',\n wDockLeft: 'Fixar \u00E0 esquerda',\n wDockRight: 'Fixar \u00E0 direita',\n wDockTop: 'Fixar em cima',\n wDockBottom: 'Fixar embaixo',\n tabErrors: 'erros',\n stepOptional: 'opcional',\n stepDone: 'conclu\u00EDda',\n stepError: 'com erros',\n stepBack: 'Voltar',\n stepNext: 'Pr\u00F3ximo',\n stepFinish: 'Concluir',\n stepReview: 'Revis\u00E3o',\n stepSteps: 'Etapas',\n stepOf: 'Etapa {n} de {total}',\n secretShow: 'Mostrar valor',\n secretHide: 'Ocultar valor',\n secretStored: 'H\u00E1 um valor salvo. Ele n\u00E3o pode ser exibido novamente.',\n secretReplace: 'Substituir',\n secretKeep: 'Manter o atual',\n secretWarnTitle: 'Substituir o valor salvo?',\n secretWarn: 'O valor salvo n\u00E3o pode ser exibido e ser\u00E1 descartado assim que voc\u00EA o substituir. Digite o novo valor em seguida; ele s\u00F3 vale quando voc\u00EA salvar.',\n gridSelected: '{n} selecionado(s)',\n gridSelectAll: 'Selecionar todos os {n}',\n gridClearSel: 'Limpar sele\u00E7\u00E3o',\n gridSelectRow: 'Selecionar linha',\n gridSelectPage: 'Selecionar todas as linhas',\n gridRowActions: 'A\u00E7\u00F5es da linha',\n gridColumns: 'Colunas',\n gridResize: 'Redimensionar coluna',\n gridGroupAll: 'Todas',\n gridOtherCols: 'Outras',\n gridGroups: 'Grupos de colunas',\n gridColumnSearch: 'Buscar colunas',\n gridNoColumns: 'Nenhuma coluna encontrada',\n noResults: 'Nenhum resultado',\n results: '{n} resultados',\n pageFirst: 'Primeira p\u00E1gina',\n pagePrev: 'P\u00E1gina anterior',\n pageNext: 'Pr\u00F3xima p\u00E1gina',\n pageLast: '\u00DAltima p\u00E1gina',\n pageLabel: 'Pagina\u00E7\u00E3o',\n pageGoto: 'P\u00E1gina {n}',\n pageInfo: '{from}\u2013{to} de {total}',\n calPrev: 'Anterior',\n calNext: 'Pr\u00F3ximo',\n calOpen: 'Abrir calend\u00E1rio',\n calMonth: 'Escolher m\u00EAs',\n breadcrumb: 'Trilha de navega\u00E7\u00E3o',\n breadcrumbMore: 'Mostrar mais',\n sortAsc: 'ordenado crescente',\n sortDesc: 'ordenado decrescente',\n};\n\nexport const locales: Record<string, Locale> = { en, 'pt-BR': ptBR };\nlet current: Locale = en;\n\n/** Picks a registered locale by name (`'pt-BR'`, or `'pt'` as a prefix) or merges a custom object over English. */\nexport function setLocale(l: string | Locale): void {\n if (typeof l === 'string') {\n current = locales[l] ?? locales[Object.keys(locales).find((k) => k.startsWith(l.split('-')[0])) ?? 'en'];\n } else {\n current = { ...en, ...l };\n if (l._lang) locales[l._lang] = current;\n }\n}\n\nexport const getLocale = (): Locale => current;\n\n/** Translates a key, replacing `{name}` placeholders. */\nexport function t(key: string, vars?: Record<string, string | number>): string {\n const s = current[key] ?? en[key] ?? key;\n return vars ? s.replace(/\\{(\\w+)\\}/g, (_, k) => String(vars[k] ?? '')) : s;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["Emitter", "name", "fn", "list", "off", "a", "f", "args", "ok", "en", "ptBR", "locales", "current", "setLocale", "l", "k", "getLocale", "t", "key", "vars", "s", "_"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{d as o}from"./chunk-MA5BJL3S.js";var n=()=>o()._lang,i=(t,e)=>{if(t==null||t==="")return"";let r=t instanceof Date?t:typeof t=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(t)?new Date(+t.slice(0,4),+t.slice(5,7)-1,+t.slice(8,10)):new Date(t);return isNaN(+r)?String(t):new Intl.DateTimeFormat(n(),e).format(r)},a={number:(t,e)=>t==null||t===""?"":new Intl.NumberFormat(n(),e).format(t),money:(t,e)=>t==null||t===""?"":new Intl.NumberFormat(n(),{style:"currency",currency:o()._currency,...e}).format(t),percent:(t,e)=>t==null||t===""?"":new Intl.NumberFormat(n(),{style:"percent",maximumFractionDigits:1,...e}).format(t),date:(t,e)=>i(t,{dateStyle:"medium",...e}),datetime:(t,e)=>i(t,{dateStyle:"medium",timeStyle:"short",...e}),bool:t=>t?"\u2713":""};function s(t,e){a[t]=e}function m(t,e){let r=typeof t=="function"?t:a[t];if(!r)throw new Error(`Optikos: unknown format "${t}"`);return r(e)}function f(t,e){let r=e.data[t.field];return t.renderer?t.renderer(r,e,t):t.format?m(t.format,r):r==null?"":String(r)}export{s as a,m as b,f as c};
2
+ //# sourceMappingURL=chunk-NDBFYIL6.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/data/format.ts", "../src/data/column.ts"],
4
+ "sourcesContent": ["import { getLocale } from '../core/i18n';\n\nexport type Formatter = (value: any, options?: Record<string, any>) => string;\n\nconst lang = () => getLocale()._lang;\nconst date = (v: any, opts: Intl.DateTimeFormatOptions) => {\n if (v == null || v === '') return '';\n // ISO dates without time are local dates, not UTC.\n const d = v instanceof Date ? v : typeof v === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(v) ? new Date(+v.slice(0, 4), +v.slice(5, 7) - 1, +v.slice(8, 10)) : new Date(v);\n return isNaN(+d) ? String(v) : new Intl.DateTimeFormat(lang(), opts).format(d);\n};\n\nconst formats: Record<string, Formatter> = {\n number: (v, o) => (v == null || v === '' ? '' : new Intl.NumberFormat(lang(), o).format(v)),\n money: (v, o) => (v == null || v === '' ? '' : new Intl.NumberFormat(lang(), { style: 'currency', currency: getLocale()._currency, ...o }).format(v)),\n percent: (v, o) => (v == null || v === '' ? '' : new Intl.NumberFormat(lang(), { style: 'percent', maximumFractionDigits: 1, ...o }).format(v)),\n date: (v, o) => date(v, { dateStyle: 'medium', ...o }),\n datetime: (v, o) => date(v, { dateStyle: 'medium', timeStyle: 'short', ...o }),\n bool: (v) => (v ? '\u2713' : ''),\n};\n\n/** Registers a named formatter, usable as `format: 'name'` in columns. */\nexport function registerFormat(name: string, fn: Formatter): void {\n formats[name] = fn;\n}\n\nexport function format(fmt: string | Formatter, value: unknown): string {\n const fn = typeof fmt === 'function' ? fmt : formats[fmt];\n if (!fn) throw new Error(`Optikos: unknown format \"${fmt}\"`);\n return fn(value);\n}\n", "import { format, type Formatter } from './format';\nimport type { Model } from './model';\n\nexport interface Column {\n field: string;\n header?: string;\n /** Fixed width in px. */\n width?: number;\n /** Share of the free space (like CSS `fr`). Default 1 when there is no `width`. */\n flex?: number;\n /** A label that groups columns (\"Identification\", \"Values\"...): a band over the header and sections in the column menu. */\n group?: string;\n minWidth?: number;\n /** Upper bound when the user resizes it. */\n maxWidth?: number;\n /** `false` keeps a column's width fixed even when the grid has `resizableColumns`. */\n resizable?: boolean;\n align?: 'left' | 'center' | 'right';\n sortable?: boolean;\n hidden?: boolean;\n /** Name registered with `registerFormat` (`money`, `date`, `number`, `percent`, `bool`) or a function. */\n format?: string | Formatter;\n /** Full control over the cell content. Text is escaped; return a Node for markup. */\n renderer?: (value: any, rec: Model, col: Column) => string | Node;\n cls?: string;\n}\n\n/** Cell content for a record: `renderer` first, then `format`, then the plain value. */\nexport function cellContent(col: Column, rec: Model): string | Node {\n const v = rec.data[col.field];\n if (col.renderer) return col.renderer(v, rec, col);\n if (col.format) return format(col.format, v);\n return v == null ? '' : String(v);\n}\n"],
5
+ "mappings": "wCAIA,IAAMA,EAAO,IAAMC,EAAU,EAAE,MACzBC,EAAO,CAACC,EAAQC,IAAqC,CACzD,GAAID,GAAK,MAAQA,IAAM,GAAI,MAAO,GAElC,IAAME,EAAIF,aAAa,KAAOA,EAAI,OAAOA,GAAM,UAAY,sBAAsB,KAAKA,CAAC,EAAI,IAAI,KAAK,CAACA,EAAE,MAAM,EAAG,CAAC,EAAG,CAACA,EAAE,MAAM,EAAG,CAAC,EAAI,EAAG,CAACA,EAAE,MAAM,EAAG,EAAE,CAAC,EAAI,IAAI,KAAKA,CAAC,EACrK,OAAO,MAAM,CAACE,CAAC,EAAI,OAAOF,CAAC,EAAI,IAAI,KAAK,eAAeH,EAAK,EAAGI,CAAI,EAAE,OAAOC,CAAC,CAC/E,EAEMC,EAAqC,CACzC,OAAQ,CAACH,EAAGI,IAAOJ,GAAK,MAAQA,IAAM,GAAK,GAAK,IAAI,KAAK,aAAaH,EAAK,EAAGO,CAAC,EAAE,OAAOJ,CAAC,EACzF,MAAO,CAACA,EAAGI,IAAOJ,GAAK,MAAQA,IAAM,GAAK,GAAK,IAAI,KAAK,aAAaH,EAAK,EAAG,CAAE,MAAO,WAAY,SAAUC,EAAU,EAAE,UAAW,GAAGM,CAAE,CAAC,EAAE,OAAOJ,CAAC,EACnJ,QAAS,CAACA,EAAGI,IAAOJ,GAAK,MAAQA,IAAM,GAAK,GAAK,IAAI,KAAK,aAAaH,EAAK,EAAG,CAAE,MAAO,UAAW,sBAAuB,EAAG,GAAGO,CAAE,CAAC,EAAE,OAAOJ,CAAC,EAC7I,KAAM,CAACA,EAAGI,IAAML,EAAKC,EAAG,CAAE,UAAW,SAAU,GAAGI,CAAE,CAAC,EACrD,SAAU,CAACJ,EAAGI,IAAML,EAAKC,EAAG,CAAE,UAAW,SAAU,UAAW,QAAS,GAAGI,CAAE,CAAC,EAC7E,KAAOJ,GAAOA,EAAI,SAAM,EAC1B,EAGO,SAASK,EAAeC,EAAcC,EAAqB,CAChEJ,EAAQG,CAAI,EAAIC,CAClB,CAEO,SAASC,EAAOC,EAAyBC,EAAwB,CACtE,IAAMH,EAAK,OAAOE,GAAQ,WAAaA,EAAMN,EAAQM,CAAG,EACxD,GAAI,CAACF,EAAI,MAAM,IAAI,MAAM,4BAA4BE,CAAG,GAAG,EAC3D,OAAOF,EAAGG,CAAK,CACjB,CCFO,SAASC,EAAYC,EAAaC,EAA2B,CAClE,IAAMC,EAAID,EAAI,KAAKD,EAAI,KAAK,EAC5B,OAAIA,EAAI,SAAiBA,EAAI,SAASE,EAAGD,EAAKD,CAAG,EAC7CA,EAAI,OAAeG,EAAOH,EAAI,OAAQE,CAAC,EACpCA,GAAK,KAAO,GAAK,OAAOA,CAAC,CAClC",
6
+ "names": ["lang", "getLocale", "date", "v", "opts", "d", "formats", "o", "registerFormat", "name", "fn", "format", "fmt", "value", "cellContent", "col", "rec", "v", "format"]
7
+ }