@jackuait/blok 0.10.0-beta.3 → 0.10.0-beta.5

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 (251) hide show
  1. package/dist/blok.mjs +2 -2
  2. package/dist/chunks/{blok-CrfCy6RQ.mjs → blok-DH-WEcA8.mjs} +2213 -2200
  3. package/dist/chunks/{constants-BzBmIAnT.mjs → constants-Ccno9NZS.mjs} +86 -64
  4. package/dist/chunks/{i18next-Ch0gVA3V.mjs → i18next-G6FKbZqA.mjs} +1 -1
  5. package/dist/chunks/{i18next-loader-BOlOKRt8.mjs → i18next-loader-CwNimni3.mjs} +2 -2
  6. package/dist/chunks/{lightweight-i18n-D1n0OClP.mjs → lightweight-i18n-DWCdzAw0.mjs} +17 -1
  7. package/dist/{messages-D7Wofcg3.mjs → chunks/messages-1Raf1IK82.mjs} +16 -0
  8. package/dist/chunks/{messages-Du6j7HqD2.mjs → messages-6mikOS4D2.mjs} +16 -0
  9. package/dist/{messages-CyQQ8g9w2.mjs → chunks/messages-B0ffBqzr.mjs} +16 -0
  10. package/dist/{messages-CfaiAQHW2.mjs → chunks/messages-B2pW6jO_.mjs} +16 -0
  11. package/dist/{messages-4kMr3vfK2.mjs → chunks/messages-B3s2vra72.mjs} +16 -0
  12. package/dist/{messages-CBWUNVHy.mjs → chunks/messages-B7MIRzCa2.mjs} +16 -0
  13. package/dist/chunks/{messages-0Nh_GHU02.mjs → messages-BPog17132.mjs} +16 -0
  14. package/dist/chunks/{messages-CbXL5f99.mjs → messages-BS1nOvZ-.mjs} +16 -0
  15. package/dist/{messages-BCIuVjwb.mjs → chunks/messages-BW_7lfqG2.mjs} +16 -0
  16. package/dist/chunks/{messages-naWwXCx3.mjs → messages-BaPZuLjN.mjs} +16 -0
  17. package/dist/chunks/{messages-DcrkPXXn.mjs → messages-BbdNugdi.mjs} +16 -0
  18. package/dist/{messages-CeyO7HXV.mjs → chunks/messages-BdnSVKOw.mjs} +16 -0
  19. package/dist/chunks/{messages-BORQKKT9.mjs → messages-BgVEGd4c.mjs} +16 -0
  20. package/dist/chunks/{messages-C1pm6RWX.mjs → messages-BgsPQXfP.mjs} +16 -0
  21. package/dist/chunks/{messages-CYZgPXFK.mjs → messages-BkCjgGxc.mjs} +16 -0
  22. package/dist/{messages-DB1-0FXB.mjs → chunks/messages-BnznaKEP2.mjs} +16 -0
  23. package/dist/{messages-CIpXgMRr2.mjs → chunks/messages-Bpda_3PM2.mjs} +16 -0
  24. package/dist/{messages-D2GHT83V2.mjs → chunks/messages-BrFl5773.mjs} +16 -0
  25. package/dist/chunks/{messages-BLD1DC722.mjs → messages-C-b6tPad2.mjs} +16 -0
  26. package/dist/chunks/{messages-LiSIeruD2.mjs → messages-C11byid72.mjs} +16 -0
  27. package/dist/chunks/{messages-IKrYzwFq.mjs → messages-C1OqT_nL.mjs} +16 -0
  28. package/dist/chunks/{messages-fitmpwb3.mjs → messages-Cdx4QMR1.mjs} +16 -0
  29. package/dist/{messages-CLB0caVL.mjs → chunks/messages-CgRvtOEY.mjs} +16 -0
  30. package/dist/{messages-BxcqzUx0.mjs → chunks/messages-ClRHDxzh.mjs} +16 -0
  31. package/dist/{messages-DwroI9YW.mjs → chunks/messages-CljStrYi.mjs} +16 -0
  32. package/dist/chunks/{messages-CR48wvl32.mjs → messages-CmXADeab2.mjs} +16 -0
  33. package/dist/{messages-BkZDaKu6.mjs → chunks/messages-CmrMwBv3.mjs} +16 -0
  34. package/dist/chunks/{messages-B7Vlzmgw.mjs → messages-CpzO7KRA.mjs} +16 -0
  35. package/dist/{messages-DwTwecgF2.mjs → chunks/messages-Cqc-6rfh2.mjs} +16 -0
  36. package/dist/chunks/{messages-BN_zp4oj.mjs → messages-CrMfiGu5.mjs} +16 -0
  37. package/dist/{messages-BRlbE8SE.mjs → chunks/messages-Cs9XBt4T.mjs} +16 -0
  38. package/dist/chunks/{messages-DDM4t-j8.mjs → messages-Csvm4mtA.mjs} +16 -0
  39. package/dist/chunks/{messages-CuHxfDvL2.mjs → messages-Ct7AMBS82.mjs} +16 -0
  40. package/dist/{messages-BjEY7_jw.mjs → chunks/messages-CvfKofOP.mjs} +16 -0
  41. package/dist/{messages-Du0fWeyE.mjs → chunks/messages-CyNsByCY.mjs} +16 -0
  42. package/dist/{messages-6Cq_jyNk2.mjs → chunks/messages-Czny5pPT2.mjs} +16 -0
  43. package/dist/{messages-CGqRnKaM.mjs → chunks/messages-D5IgUbBD2.mjs} +16 -0
  44. package/dist/{messages-uP6wmMOs.mjs → chunks/messages-DA7Zk-Cy.mjs} +16 -0
  45. package/dist/chunks/{messages-DJ9yyqUO2.mjs → messages-DAVsuDWh2.mjs} +16 -0
  46. package/dist/chunks/{messages-i9ThpxZk2.mjs → messages-DBpXyvRe2.mjs} +16 -0
  47. package/dist/chunks/{messages-CogKhvJL.mjs → messages-DC7TX-YT.mjs} +16 -0
  48. package/dist/{messages-C-KPP7bC.mjs → chunks/messages-DD7BI6BK.mjs} +16 -0
  49. package/dist/{messages-ZMa-zmIc.mjs → chunks/messages-DHCVA7XQ.mjs} +16 -0
  50. package/dist/chunks/{messages-BPQA3B862.mjs → messages-DJA6fb_P2.mjs} +16 -0
  51. package/dist/chunks/{messages-D9SfB6MI.mjs → messages-DJkIeapn.mjs} +16 -0
  52. package/dist/{messages-CZkwcbV12.mjs → chunks/messages-DPykxECP2.mjs} +16 -0
  53. package/dist/chunks/{messages-BQvBhQem.mjs → messages-DQ5AyNCU.mjs} +16 -0
  54. package/dist/chunks/{messages-rxlf-Ule.mjs → messages-DR09nkcZ.mjs} +16 -0
  55. package/dist/chunks/{messages-B1uFbxNg.mjs → messages-DSjXen8E.mjs} +16 -0
  56. package/dist/chunks/{messages-OFFQT8Fg.mjs → messages-DT7fRpCy.mjs} +16 -0
  57. package/dist/{messages-DnNNd3RW2.mjs → chunks/messages-DUDgFEEe2.mjs} +16 -0
  58. package/dist/chunks/{messages-7PIvzufT.mjs → messages-Df87zXXG.mjs} +16 -0
  59. package/dist/chunks/{messages-CvA7Fbqf.mjs → messages-Dfpi8pDY.mjs} +16 -0
  60. package/dist/{messages-CXlAjnEQ.mjs → chunks/messages-Dm4YVlrm.mjs} +16 -0
  61. package/dist/chunks/{messages-CuJLHCj5.mjs → messages-Dplnp19q.mjs} +16 -0
  62. package/dist/{messages-DEfeDBuV2.mjs → chunks/messages-FHrCEJmY2.mjs} +16 -0
  63. package/dist/chunks/{messages-nZP1GShd.mjs → messages-ID1PHnMv.mjs} +16 -0
  64. package/dist/{messages-BiK5fMYF2.mjs → chunks/messages-IDEUsFhQ2.mjs} +16 -0
  65. package/dist/{messages-C672uqt-.mjs → chunks/messages-JQKFJo7C.mjs} +16 -0
  66. package/dist/{messages-DVHWIOfr2.mjs → chunks/messages-LxumrNue2.mjs} +16 -0
  67. package/dist/chunks/{messages-By-gACFM2.mjs → messages-R2W_rGOo2.mjs} +16 -0
  68. package/dist/chunks/{messages-FEjIF48t.mjs → messages-ZJ0b1C3a.mjs} +16 -0
  69. package/dist/{messages-nosa-xnx2.mjs → chunks/messages-d0Ky6QjR.mjs} +16 -0
  70. package/dist/{messages-CHaVGY89.mjs → chunks/messages-p4byLfvR.mjs} +16 -0
  71. package/dist/{messages-D-bnq2qy.mjs → chunks/messages-u2yxkNTE2.mjs} +16 -0
  72. package/dist/{messages-axsznSTn2.mjs → chunks/messages-wLSVQbsA2.mjs} +16 -0
  73. package/dist/chunks/{messages-DiaQNuPV.mjs → messages-xfjdrZmx.mjs} +16 -0
  74. package/dist/chunks/{objectSpread2-CyPxu8-u.mjs → objectSpread2-BY4mgzrQ.mjs} +1 -1
  75. package/dist/chunks/{tools-B6tibTzs.mjs → tools-C2_IVsQY.mjs} +2868 -1082
  76. package/dist/full.mjs +11 -11
  77. package/dist/locales.mjs +83 -67
  78. package/dist/{messages-BfbYJ8Wk2.mjs → messages--S8_taOd2.mjs} +16 -0
  79. package/dist/{chunks/messages-CkWidbwX2.mjs → messages-B-4fku2H2.mjs} +16 -0
  80. package/dist/{chunks/messages-Dn1ZDZUy.mjs → messages-BAcH6PtT2.mjs} +16 -0
  81. package/dist/{chunks/messages-2nj1xBDo.mjs → messages-BBq0M604.mjs} +16 -0
  82. package/dist/{messages-Dzqb5lg6.mjs → messages-BBvDbp62.mjs} +16 -0
  83. package/dist/{messages-kuLrhtV2.mjs → messages-BCG_evLg.mjs} +16 -0
  84. package/dist/{messages-DEKkIgU6.mjs → messages-BCuTVHBV.mjs} +16 -0
  85. package/dist/{chunks/messages-CYZL_rhV2.mjs → messages-BGsDZTQp2.mjs} +16 -0
  86. package/dist/{chunks/messages-cMwiuDZM.mjs → messages-BJ7BuFZi.mjs} +16 -0
  87. package/dist/{chunks/messages-Dl16RBg1.mjs → messages-BKjqW08U.mjs} +16 -0
  88. package/dist/{messages-Daza4lOM.mjs → messages-BSe3QDnQ.mjs} +16 -0
  89. package/dist/{chunks/messages-CDV8VcSZ2.mjs → messages-BVKZK-3t.mjs} +16 -0
  90. package/dist/{messages-CcPrYMHE.mjs → messages-BXI3qIos.mjs} +16 -0
  91. package/dist/{messages-B_6S7hBj2.mjs → messages-BcFQFcJ92.mjs} +16 -0
  92. package/dist/{chunks/messages-CmSsyItg.mjs → messages-Bio7KYsr2.mjs} +16 -0
  93. package/dist/{chunks/messages-CqdYWY192.mjs → messages-Bk984gRE2.mjs} +16 -0
  94. package/dist/{chunks/messages-CQgP-Fo22.mjs → messages-BmNaAyKS.mjs} +16 -0
  95. package/dist/{messages-DbPt9d2U.mjs → messages-Bo_FUvVH.mjs} +16 -0
  96. package/dist/{chunks/messages-x6GyZWWT.mjs → messages-BokEflKa.mjs} +16 -0
  97. package/dist/{chunks/messages-C9qPNbrJ2.mjs → messages-BtxaN-xx.mjs} +16 -0
  98. package/dist/{messages-6edZhK922.mjs → messages-BvgTQLf72.mjs} +16 -0
  99. package/dist/{chunks/messages-BVl-X2wo2.mjs → messages-BvgXeMSL2.mjs} +16 -0
  100. package/dist/{messages-BBauvpFc.mjs → messages-BywbKcPC.mjs} +16 -0
  101. package/dist/{chunks/messages-D06U2QNl2.mjs → messages-C30Vz-UZ2.mjs} +16 -0
  102. package/dist/{messages-BwyQiBdm2.mjs → messages-C5XPUD9T2.mjs} +16 -0
  103. package/dist/{chunks/messages-BivhofAQ2.mjs → messages-C6OJvnJg2.mjs} +16 -0
  104. package/dist/{chunks/messages-D6ZvH6hX.mjs → messages-C6Y4Jv2N.mjs} +16 -0
  105. package/dist/{messages-DaFDdCrr.mjs → messages-CBdQ3XP9.mjs} +16 -0
  106. package/dist/{chunks/messages-KihEeXdr.mjs → messages-CBzd_x7H.mjs} +16 -0
  107. package/dist/{messages-CsVZUVra.mjs → messages-CHJ5SOZI.mjs} +16 -0
  108. package/dist/{messages-us2JotS-2.mjs → messages-CM5fsPo02.mjs} +16 -0
  109. package/dist/{chunks/messages-DjhgPQtb.mjs → messages-CVcQD-9u.mjs} +16 -0
  110. package/dist/{messages-BQi_l2vs.mjs → messages-CYX48nfg.mjs} +16 -0
  111. package/dist/{chunks/messages-BF8c-lMm.mjs → messages-Ccd587Yn.mjs} +16 -0
  112. package/dist/{chunks/messages-5WyxUYVR2.mjs → messages-CdlsTFB1.mjs} +16 -0
  113. package/dist/{messages-ke15helG2.mjs → messages-CgzbJ8_l2.mjs} +16 -0
  114. package/dist/{messages-D1-_eTfM.mjs → messages-CjmSrt1D.mjs} +16 -0
  115. package/dist/{chunks/messages-C7YpgZ9m.mjs → messages-CqkRG9mH.mjs} +16 -0
  116. package/dist/{messages-Dtw27ih4.mjs → messages-D3cAcyzj.mjs} +16 -0
  117. package/dist/{messages-CLN3oL77.mjs → messages-DA-o8X3A.mjs} +16 -0
  118. package/dist/{chunks/messages-BtZ8oQXS.mjs → messages-DD5pW0zJ.mjs} +16 -0
  119. package/dist/{chunks/messages-A3Z4jxwt2.mjs → messages-DIRha_gg2.mjs} +16 -0
  120. package/dist/{chunks/messages-rnd6qiJ12.mjs → messages-DJKLtW7u.mjs} +16 -0
  121. package/dist/{messages-h_VN1Kyo2.mjs → messages-DJT4Bt_02.mjs} +16 -0
  122. package/dist/{chunks/messages-D3hNTep_.mjs → messages-DOTJ2NvJ.mjs} +16 -0
  123. package/dist/{chunks/messages-B18MZnaY.mjs → messages-DUBHHfEt.mjs} +16 -0
  124. package/dist/{chunks/messages-92ma9RJD2.mjs → messages-DV9e1DW7.mjs} +16 -0
  125. package/dist/{chunks/messages-DQUUtL5v.mjs → messages-DVQNjdPk.mjs} +16 -0
  126. package/dist/{messages-DflAKRLd.mjs → messages-DZEcrbmH.mjs} +16 -0
  127. package/dist/{messages-BLjz6V7y2.mjs → messages-DbxbxUiK2.mjs} +16 -0
  128. package/dist/{messages-QkGAxuVC2.mjs → messages-Dcyrzdxa2.mjs} +16 -0
  129. package/dist/{chunks/messages-DBZ-uuAV.mjs → messages-Dddxv8-f2.mjs} +16 -0
  130. package/dist/{messages-DVILiJw52.mjs → messages-DjJQoYvP2.mjs} +16 -0
  131. package/dist/{messages-B-lXqB1z2.mjs → messages-Dkg99bfr2.mjs} +16 -0
  132. package/dist/{messages-CCBgCmyq.mjs → messages-DnatBKPm.mjs} +16 -0
  133. package/dist/{messages-Dn-khi3a.mjs → messages-DqyqEw1_.mjs} +16 -0
  134. package/dist/{chunks/messages-D4QXMtW52.mjs → messages-DtrSrdfE2.mjs} +16 -0
  135. package/dist/{messages-BHIdzfAS2.mjs → messages-JhoVMjfX2.mjs} +16 -0
  136. package/dist/{messages-YlWV9cSl.mjs → messages-eTourT12.mjs} +16 -0
  137. package/dist/{messages-DzlmoWqQ.mjs → messages-fLi0P2dP.mjs} +16 -0
  138. package/dist/{messages-C-v50b4r.mjs → messages-hTpeKUaW.mjs} +16 -0
  139. package/dist/{chunks/messages-16UmLAWZ2.mjs → messages-i4S6q64n2.mjs} +16 -0
  140. package/dist/{messages-DP9PhNTo.mjs → messages-pgPcitDH.mjs} +16 -0
  141. package/dist/{chunks/messages-D5iRrf9M.mjs → messages-tK67CBqn.mjs} +16 -0
  142. package/dist/{chunks/messages-BTyEo5Kb.mjs → messages-tsHpMdDT2.mjs} +16 -0
  143. package/dist/{chunks/messages-Ct_H_5cB2.mjs → messages-upqrRZQH2.mjs} +16 -0
  144. package/dist/{messages-CyZZ10br.mjs → messages-xEI8gEDK.mjs} +16 -0
  145. package/dist/react.mjs +3 -3
  146. package/dist/tools.mjs +3 -3
  147. package/dist/vendor.LICENSE.txt +136 -1
  148. package/package.json +2 -1
  149. package/src/components/block/style-manager.ts +1 -1
  150. package/src/components/i18n/locales/am/messages.json +16 -0
  151. package/src/components/i18n/locales/ar/messages.json +16 -0
  152. package/src/components/i18n/locales/az/messages.json +16 -0
  153. package/src/components/i18n/locales/bg/messages.json +16 -0
  154. package/src/components/i18n/locales/bn/messages.json +16 -0
  155. package/src/components/i18n/locales/bs/messages.json +16 -0
  156. package/src/components/i18n/locales/cs/messages.json +16 -0
  157. package/src/components/i18n/locales/da/messages.json +16 -0
  158. package/src/components/i18n/locales/de/messages.json +16 -0
  159. package/src/components/i18n/locales/dv/messages.json +16 -0
  160. package/src/components/i18n/locales/el/messages.json +16 -0
  161. package/src/components/i18n/locales/en/messages.json +16 -0
  162. package/src/components/i18n/locales/es/messages.json +16 -0
  163. package/src/components/i18n/locales/et/messages.json +16 -0
  164. package/src/components/i18n/locales/fa/messages.json +16 -0
  165. package/src/components/i18n/locales/fi/messages.json +16 -0
  166. package/src/components/i18n/locales/fil/messages.json +16 -0
  167. package/src/components/i18n/locales/fr/messages.json +16 -0
  168. package/src/components/i18n/locales/gu/messages.json +16 -0
  169. package/src/components/i18n/locales/he/messages.json +16 -0
  170. package/src/components/i18n/locales/hi/messages.json +16 -0
  171. package/src/components/i18n/locales/hr/messages.json +16 -0
  172. package/src/components/i18n/locales/hu/messages.json +16 -0
  173. package/src/components/i18n/locales/hy/messages.json +16 -0
  174. package/src/components/i18n/locales/id/messages.json +16 -0
  175. package/src/components/i18n/locales/it/messages.json +16 -0
  176. package/src/components/i18n/locales/ja/messages.json +16 -0
  177. package/src/components/i18n/locales/ka/messages.json +16 -0
  178. package/src/components/i18n/locales/km/messages.json +16 -0
  179. package/src/components/i18n/locales/kn/messages.json +16 -0
  180. package/src/components/i18n/locales/ko/messages.json +16 -0
  181. package/src/components/i18n/locales/ku/messages.json +16 -0
  182. package/src/components/i18n/locales/lo/messages.json +16 -0
  183. package/src/components/i18n/locales/lt/messages.json +16 -0
  184. package/src/components/i18n/locales/lv/messages.json +16 -0
  185. package/src/components/i18n/locales/mk/messages.json +16 -0
  186. package/src/components/i18n/locales/ml/messages.json +16 -0
  187. package/src/components/i18n/locales/mn/messages.json +16 -0
  188. package/src/components/i18n/locales/mr/messages.json +16 -0
  189. package/src/components/i18n/locales/ms/messages.json +16 -0
  190. package/src/components/i18n/locales/my/messages.json +16 -0
  191. package/src/components/i18n/locales/ne/messages.json +16 -0
  192. package/src/components/i18n/locales/nl/messages.json +16 -0
  193. package/src/components/i18n/locales/no/messages.json +16 -0
  194. package/src/components/i18n/locales/pa/messages.json +16 -0
  195. package/src/components/i18n/locales/pl/messages.json +16 -0
  196. package/src/components/i18n/locales/ps/messages.json +16 -0
  197. package/src/components/i18n/locales/pt/messages.json +16 -0
  198. package/src/components/i18n/locales/ro/messages.json +16 -0
  199. package/src/components/i18n/locales/ru/messages.json +16 -0
  200. package/src/components/i18n/locales/sd/messages.json +16 -0
  201. package/src/components/i18n/locales/si/messages.json +16 -0
  202. package/src/components/i18n/locales/sk/messages.json +16 -0
  203. package/src/components/i18n/locales/sl/messages.json +16 -0
  204. package/src/components/i18n/locales/sq/messages.json +16 -0
  205. package/src/components/i18n/locales/sr/messages.json +16 -0
  206. package/src/components/i18n/locales/sv/messages.json +16 -0
  207. package/src/components/i18n/locales/sw/messages.json +16 -0
  208. package/src/components/i18n/locales/ta/messages.json +16 -0
  209. package/src/components/i18n/locales/te/messages.json +16 -0
  210. package/src/components/i18n/locales/th/messages.json +16 -0
  211. package/src/components/i18n/locales/tr/messages.json +16 -0
  212. package/src/components/i18n/locales/ug/messages.json +16 -0
  213. package/src/components/i18n/locales/uk/messages.json +16 -0
  214. package/src/components/i18n/locales/ur/messages.json +16 -0
  215. package/src/components/i18n/locales/vi/messages.json +16 -0
  216. package/src/components/i18n/locales/yi/messages.json +16 -0
  217. package/src/components/i18n/locales/zh/messages.json +16 -0
  218. package/src/components/icons/index.ts +56 -0
  219. package/src/components/modules/api/tools.ts +19 -0
  220. package/src/components/modules/blockEvents/composers/keyboardNavigation.ts +5 -5
  221. package/src/components/modules/blockManager/blockManager.ts +11 -0
  222. package/src/components/modules/blockManager/event-binder.ts +12 -1
  223. package/src/components/modules/themeManager.ts +3 -1
  224. package/src/components/modules/toolbar/blockSettings.ts +0 -1
  225. package/src/components/modules/toolbar/inline/index.ts +0 -3
  226. package/src/components/modules/uiControllers/controllers/keyboard.ts +29 -0
  227. package/src/components/modules/uiControllers/controllers/selection.ts +14 -2
  228. package/src/components/ui/toolbox.ts +0 -1
  229. package/src/components/utils/popover/popover-position.ts +4 -2
  230. package/src/styles/main.css +1139 -0
  231. package/src/tools/callout/constants.ts +2 -1
  232. package/src/tools/database/database-backend-sync.ts +101 -0
  233. package/src/tools/database/database-board-view.ts +301 -0
  234. package/src/tools/database/database-card-drag.ts +306 -0
  235. package/src/tools/database/database-card-drawer.ts +546 -0
  236. package/src/tools/database/database-column-controls.ts +46 -0
  237. package/src/tools/database/database-column-drag.ts +262 -0
  238. package/src/tools/database/database-keyboard.ts +35 -0
  239. package/src/tools/database/database-list-row-drag.ts +245 -0
  240. package/src/tools/database/database-list-view.ts +333 -0
  241. package/src/tools/database/database-model.ts +246 -0
  242. package/src/tools/database/database-property-type-popover.ts +108 -0
  243. package/src/tools/database/database-tab-bar.ts +532 -0
  244. package/src/tools/database/database-view-popover.ts +109 -0
  245. package/src/tools/database/database-view-renderer.ts +25 -0
  246. package/src/tools/database/index.ts +948 -0
  247. package/src/tools/database/types.ts +144 -0
  248. package/src/tools/index.ts +2 -0
  249. package/types/api/tools.d.ts +18 -0
  250. package/types/index.d.ts +16 -0
  251. package/types/tools/database.d.ts +145 -0
@@ -0,0 +1,546 @@
1
+ import type { I18n, OutputData } from '../../../types';
2
+ import type { ToolsConfig } from '../../../types/api/tools';
3
+ import type { DatabaseRow, PropertyDefinition, PropertyType, PropertyValue } from './types';
4
+ import { IconChevronRight } from '../../components/icons';
5
+ import { DatabasePropertyTypePopover } from './database-property-type-popover';
6
+
7
+ interface BlokInstance {
8
+ save(): Promise<OutputData>;
9
+ destroy(): void;
10
+ isReady: Promise<void>;
11
+ }
12
+
13
+ export interface CardDrawerOptions {
14
+ wrapper: HTMLElement;
15
+ readOnly: boolean;
16
+ i18n?: I18n;
17
+ toolsConfig?: ToolsConfig;
18
+ titlePropertyId: string;
19
+ descriptionPropertyId?: string;
20
+ schema: PropertyDefinition[];
21
+ onTitleChange: (rowId: string, title: string) => void;
22
+ onDescriptionChange: (rowId: string, description: OutputData) => void;
23
+ onClose: () => void;
24
+ onAddProperty?: (type: PropertyType) => void;
25
+ }
26
+
27
+ /**
28
+ * Side drawer that opens when a kanban card is clicked.
29
+ * Sits beside the board as a flex sibling, taking layout space.
30
+ * Contains a title input, status property, and a nested Blok editor for the card description.
31
+ */
32
+ export class DatabaseCardDrawer {
33
+ private readonly wrapper: HTMLElement;
34
+ private readonly readOnly: boolean;
35
+ private readonly i18n: I18n | undefined;
36
+ private readonly toolsConfig: ToolsConfig | undefined;
37
+ private readonly titlePropertyId: string;
38
+ private readonly descriptionPropertyId: string | undefined;
39
+ private schema: PropertyDefinition[];
40
+ private readonly onTitleChange: (rowId: string, title: string) => void;
41
+ private readonly onDescriptionChange: (rowId: string, description: OutputData) => void;
42
+ private readonly onClose: () => void;
43
+ private readonly onAddProperty: ((type: PropertyType) => void) | undefined;
44
+
45
+ private drawer: HTMLDivElement | null = null;
46
+ private currentRowId: string | null = null;
47
+ private currentRow: DatabaseRow | null = null;
48
+ private blokInstance: BlokInstance | null = null;
49
+ private escapeHandler: ((e: KeyboardEvent) => void) | null = null;
50
+ private outsideClickHandler: ((e: MouseEvent) => void) | null = null;
51
+ private propertyTypePopover: DatabasePropertyTypePopover | null = null;
52
+
53
+ constructor(options: CardDrawerOptions) {
54
+ this.wrapper = options.wrapper;
55
+ this.readOnly = options.readOnly;
56
+ this.i18n = options.i18n;
57
+ this.toolsConfig = options.toolsConfig;
58
+ this.titlePropertyId = options.titlePropertyId;
59
+ this.descriptionPropertyId = options.descriptionPropertyId;
60
+ this.schema = options.schema;
61
+ this.onTitleChange = options.onTitleChange;
62
+ this.onDescriptionChange = options.onDescriptionChange;
63
+ this.onClose = options.onClose;
64
+ this.onAddProperty = options.onAddProperty;
65
+ }
66
+
67
+ get isOpen(): boolean {
68
+ return this.drawer !== null;
69
+ }
70
+
71
+ open(row: DatabaseRow): void {
72
+ if (this.drawer) {
73
+ if (row.id === this.currentRowId) {
74
+ return;
75
+ }
76
+
77
+ this.loadCard(row);
78
+
79
+ return;
80
+ }
81
+
82
+ // Remove any drawer still animating out from a previous close
83
+ const exiting = this.wrapper.querySelector('[data-blok-database-drawer]');
84
+
85
+ exiting?.remove();
86
+
87
+ this.currentRowId = row.id;
88
+ this.currentRow = row;
89
+ this.updateActiveCard(row.id);
90
+
91
+ const title = (row.properties[this.titlePropertyId] as string) ?? '';
92
+
93
+ const drawer = document.createElement('div');
94
+
95
+ drawer.setAttribute('data-blok-database-drawer', '');
96
+ drawer.setAttribute('role', 'complementary');
97
+ drawer.setAttribute('aria-label', 'Card details');
98
+
99
+ // --- Top toolbar ---
100
+ const toolbar = document.createElement('div');
101
+
102
+ toolbar.setAttribute('data-blok-database-drawer-toolbar', '');
103
+
104
+ const closeBtn = document.createElement('button');
105
+
106
+ closeBtn.setAttribute('data-blok-database-drawer-close', '');
107
+ closeBtn.setAttribute('aria-label', 'Close');
108
+ closeBtn.innerHTML = IconChevronRight + IconChevronRight;
109
+ closeBtn.addEventListener('click', () => {
110
+ this.close();
111
+ });
112
+ toolbar.appendChild(closeBtn);
113
+
114
+ drawer.appendChild(toolbar);
115
+
116
+ // --- Scrollable content ---
117
+ const content = document.createElement('div');
118
+
119
+ content.setAttribute('data-blok-database-drawer-content', '');
120
+
121
+ // --- Title input ---
122
+ const titleInput = document.createElement('textarea');
123
+
124
+ titleInput.setAttribute('data-blok-database-drawer-title', '');
125
+ titleInput.setAttribute('aria-label', 'Card title');
126
+ titleInput.placeholder = this.i18n?.t('tools.database.cardTitlePlaceholder') ?? 'Empty page';
127
+ titleInput.value = title;
128
+ titleInput.rows = 1;
129
+ titleInput.readOnly = this.readOnly;
130
+ titleInput.addEventListener('input', () => {
131
+ if (this.currentRowId !== null) {
132
+ this.onTitleChange(this.currentRowId, titleInput.value);
133
+ }
134
+ this.autoResizeTitle(titleInput);
135
+ });
136
+ titleInput.addEventListener('keydown', (e) => {
137
+ if (e.key === 'Enter') {
138
+ e.preventDefault();
139
+ }
140
+ });
141
+ content.appendChild(titleInput);
142
+
143
+ // --- Properties section ---
144
+ const renderableSchema = this.getRenderableSchema();
145
+
146
+ content.appendChild(this.buildPropsSection(renderableSchema, row));
147
+
148
+ // --- Divider ---
149
+ const divider = document.createElement('hr');
150
+
151
+ content.appendChild(divider);
152
+
153
+ // --- Editor holder ---
154
+ const editorHolder = document.createElement('div');
155
+
156
+ editorHolder.setAttribute('data-blok-database-drawer-editor', '');
157
+ content.appendChild(editorHolder);
158
+
159
+ drawer.appendChild(content);
160
+ this.wrapper.appendChild(drawer);
161
+ this.drawer = drawer;
162
+
163
+ requestAnimationFrame(() => {
164
+ drawer.style.width = '45%';
165
+ drawer.addEventListener('transitionend', () => {
166
+ this.autoResizeTitle(titleInput);
167
+
168
+ if (!title) {
169
+ titleInput.focus();
170
+ }
171
+ }, { once: true });
172
+ });
173
+
174
+ this.initNestedEditor(editorHolder, row);
175
+
176
+ this.escapeHandler = (e: KeyboardEvent): void => {
177
+ if (e.key !== 'Escape') {
178
+ return;
179
+ }
180
+
181
+ const target = e.target as Node | null;
182
+
183
+ if (target && editorHolder.contains(target)) {
184
+ return;
185
+ }
186
+
187
+ this.close();
188
+ };
189
+ document.addEventListener('keydown', this.escapeHandler);
190
+
191
+ this.outsideClickHandler = (e: MouseEvent): void => {
192
+ const target = e.target as Node | null;
193
+
194
+ if (target && drawer.contains(target)) {
195
+ return;
196
+ }
197
+
198
+ /**
199
+ * Toolbox and other popovers are portaled to document.body,
200
+ * so they sit outside the drawer DOM tree. Without this check,
201
+ * clicking a popover item would be treated as an "outside click"
202
+ * and close the drawer.
203
+ */
204
+ if (target instanceof Element && target.closest('[data-blok-popover-opened]') !== null) {
205
+ return;
206
+ }
207
+
208
+ /**
209
+ * The tab bar lives outside the drawer DOM tree, so clicking a
210
+ * tab to switch views would be treated as an outside click and
211
+ * close the drawer before switchView() runs.
212
+ */
213
+ if (target instanceof Element && target.closest('[data-blok-database-tab-bar]') !== null) {
214
+ return;
215
+ }
216
+
217
+ this.close();
218
+ };
219
+ document.addEventListener('mousedown', this.outsideClickHandler);
220
+
221
+ titleInput.focus();
222
+ }
223
+
224
+ /**
225
+ * Swaps content in the already-open drawer to show a different card
226
+ * without closing/reopening the drawer panel.
227
+ */
228
+ private loadCard(row: DatabaseRow): void {
229
+ if (this.drawer === null) {
230
+ return;
231
+ }
232
+
233
+ this.cleanupEditor();
234
+
235
+ this.currentRowId = row.id;
236
+ this.currentRow = row;
237
+ this.updateActiveCard(row.id);
238
+
239
+ const title = (row.properties[this.titlePropertyId] as string) ?? '';
240
+
241
+ // Update title
242
+ const titleInput = this.drawer.querySelector<HTMLTextAreaElement>('[data-blok-database-drawer-title]');
243
+
244
+ if (titleInput !== null) {
245
+ titleInput.value = title;
246
+ this.autoResizeTitle(titleInput);
247
+
248
+ if (!title) {
249
+ titleInput.focus();
250
+ }
251
+ }
252
+
253
+ // Replace properties section
254
+ this.drawer.querySelector('[data-blok-database-drawer-props]')?.remove();
255
+
256
+ const renderableSchema = this.getRenderableSchema();
257
+ const content = this.drawer.querySelector('[data-blok-database-drawer-content]');
258
+ const divider = content?.querySelector('hr') ?? null;
259
+
260
+ if (content !== null) {
261
+ content.insertBefore(this.buildPropsSection(renderableSchema, row), divider);
262
+ }
263
+
264
+ // Reinitialize editor
265
+ const editorHolder = this.drawer.querySelector<HTMLElement>('[data-blok-database-drawer-editor]');
266
+
267
+ if (editorHolder !== null) {
268
+ editorHolder.innerHTML = '';
269
+ this.initNestedEditor(editorHolder, row);
270
+ }
271
+ }
272
+
273
+ close(): void {
274
+ const wasOpen = this.drawer !== null;
275
+
276
+ this.updateActiveCard(null);
277
+ this.cleanupListeners();
278
+ this.cleanupEditor();
279
+
280
+ if (this.drawer) {
281
+ const drawer = this.drawer;
282
+
283
+ this.drawer = null;
284
+ drawer.style.width = '0px';
285
+ drawer.addEventListener('transitionend', () => {
286
+ drawer.remove();
287
+ }, { once: true });
288
+ }
289
+
290
+ this.currentRowId = null;
291
+ this.currentRow = null;
292
+
293
+ if (wasOpen) {
294
+ this.onClose();
295
+ }
296
+ }
297
+
298
+ destroy(): void {
299
+ this.cleanupListeners();
300
+ this.cleanupEditor();
301
+ this.propertyTypePopover?.destroy();
302
+ this.propertyTypePopover = null;
303
+
304
+ if (this.drawer) {
305
+ this.drawer.remove();
306
+ this.drawer = null;
307
+ }
308
+
309
+ // Remove any drawer still animating out
310
+ const exiting = this.wrapper.querySelector('[data-blok-database-drawer]');
311
+
312
+ exiting?.remove();
313
+
314
+ this.currentRowId = null;
315
+ this.currentRow = null;
316
+ }
317
+
318
+ /**
319
+ * Updates the schema and, if the drawer is currently open, rebuilds the
320
+ * properties section in-place using the current row's data.
321
+ */
322
+ refreshSchema(schema: PropertyDefinition[]): void {
323
+ this.schema = schema;
324
+
325
+ if (this.drawer === null || this.currentRow === null) {
326
+ return;
327
+ }
328
+
329
+ this.drawer.querySelector('[data-blok-database-drawer-props]')?.remove();
330
+
331
+ const renderableSchema = this.getRenderableSchema();
332
+ const content = this.drawer.querySelector('[data-blok-database-drawer-content]');
333
+ const divider = content?.querySelector('hr') ?? null;
334
+
335
+ if (content !== null) {
336
+ content.insertBefore(this.buildPropsSection(renderableSchema, this.currentRow), divider);
337
+ }
338
+ }
339
+
340
+ /**
341
+ * Builds a `[data-blok-database-drawer-props]` section element with one row per
342
+ * renderable schema property.
343
+ */
344
+ private buildPropsSection(renderableSchema: PropertyDefinition[], row: DatabaseRow): HTMLDivElement {
345
+ const propsSection = document.createElement('div');
346
+
347
+ propsSection.setAttribute('data-blok-database-drawer-props', '');
348
+
349
+ for (const def of renderableSchema) {
350
+ propsSection.appendChild(this.createPropertyRow(def, row.properties[def.id] ?? null));
351
+ }
352
+
353
+ if (!this.readOnly) {
354
+ const addBtn = document.createElement('button');
355
+
356
+ addBtn.setAttribute('data-blok-database-drawer-add-prop', '');
357
+ addBtn.textContent = '+ Add a property';
358
+ addBtn.addEventListener('click', () => {
359
+ if (this.propertyTypePopover === null) {
360
+ this.propertyTypePopover = new DatabasePropertyTypePopover({
361
+ onSelect: (type) => {
362
+ this.onAddProperty?.(type);
363
+ this.propertyTypePopover?.close();
364
+ },
365
+ });
366
+ }
367
+
368
+ this.propertyTypePopover.open(addBtn);
369
+ });
370
+ propsSection.appendChild(addBtn);
371
+ }
372
+
373
+ return propsSection;
374
+ }
375
+
376
+ /**
377
+ * Returns schema properties that should be shown in the properties section,
378
+ * sorted by position. Excludes 'title' and 'richText' (rendered separately).
379
+ */
380
+ private getRenderableSchema(): PropertyDefinition[] {
381
+ return [...this.schema]
382
+ .filter((def) => def.type !== 'title' && def.type !== 'richText')
383
+ .sort((a, b) => {
384
+ if (a.position < b.position) return -1;
385
+ if (a.position > b.position) return 1;
386
+
387
+ return 0;
388
+ });
389
+ }
390
+
391
+ /**
392
+ * Creates a pill badge element for a select option.
393
+ */
394
+ private createSelectPill(option: { label: string; color?: string }): HTMLSpanElement {
395
+ const pill = document.createElement('span');
396
+
397
+ pill.setAttribute('data-blok-database-drawer-prop-pill', '');
398
+
399
+ if (option.color !== undefined) {
400
+ pill.style.backgroundColor = `var(--blok-color-${option.color}-bg)`;
401
+ pill.style.color = `var(--blok-color-${option.color}-text)`;
402
+
403
+ const dot = document.createElement('span');
404
+
405
+ dot.setAttribute('data-blok-database-drawer-prop-dot', '');
406
+ dot.style.backgroundColor = `var(--blok-color-${option.color}-text)`;
407
+ pill.appendChild(dot);
408
+ }
409
+
410
+ const pillText = document.createElement('span');
411
+
412
+ pillText.textContent = option.label;
413
+ pill.appendChild(pillText);
414
+
415
+ return pill;
416
+ }
417
+
418
+ /**
419
+ * Creates a property row that dispatches on the property type to render
420
+ * the appropriate value representation.
421
+ */
422
+ private createPropertyRow(def: PropertyDefinition, value: PropertyValue): HTMLDivElement {
423
+ const row = document.createElement('div');
424
+
425
+ row.setAttribute('data-blok-database-drawer-prop-row', '');
426
+
427
+ const label = document.createElement('span');
428
+
429
+ label.setAttribute('data-blok-database-drawer-prop-label', '');
430
+ label.textContent = def.name;
431
+ row.appendChild(label);
432
+
433
+ const valueEl = document.createElement('span');
434
+
435
+ valueEl.setAttribute('data-blok-database-drawer-prop-value', '');
436
+
437
+ if (def.type === 'select') {
438
+ const config = def.config;
439
+ const optionId = typeof value === 'string' ? value : null;
440
+ const option = config?.options.find((o) => o.id === optionId);
441
+
442
+ if (option !== undefined) {
443
+ valueEl.appendChild(this.createSelectPill(option));
444
+ }
445
+ } else if (def.type === 'multiSelect') {
446
+ const config = def.config;
447
+ const selectedIds = Array.isArray(value) ? value : [];
448
+
449
+ selectedIds
450
+ .map((id) => config?.options.find((o) => o.id === id))
451
+ .filter((opt): opt is NonNullable<typeof opt> => opt !== undefined)
452
+ .forEach((opt) => valueEl.appendChild(this.createSelectPill(opt)));
453
+ } else if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
454
+ valueEl.textContent = String(value);
455
+ }
456
+
457
+ row.appendChild(valueEl);
458
+
459
+ return row;
460
+ }
461
+
462
+ private updateActiveCard(rowId: string | null): void {
463
+ const prev = this.wrapper.querySelector('[data-blok-database-card-active]');
464
+
465
+ prev?.removeAttribute('data-blok-database-card-active');
466
+
467
+ if (rowId !== null) {
468
+ const cardEl = this.wrapper.querySelector(`[data-blok-database-card][data-row-id="${rowId}"]`);
469
+
470
+ cardEl?.setAttribute('data-blok-database-card-active', '');
471
+ }
472
+ }
473
+
474
+ private cleanupListeners(): void {
475
+ if (this.escapeHandler) {
476
+ document.removeEventListener('keydown', this.escapeHandler);
477
+ this.escapeHandler = null;
478
+ }
479
+
480
+ if (this.outsideClickHandler) {
481
+ document.removeEventListener('mousedown', this.outsideClickHandler);
482
+ this.outsideClickHandler = null;
483
+ }
484
+ }
485
+
486
+ private cleanupEditor(): void {
487
+ if (this.blokInstance) {
488
+ try {
489
+ const instance = this.blokInstance;
490
+ const rowId = this.currentRowId;
491
+
492
+ instance.save().then((data) => {
493
+ if (rowId !== null) {
494
+ this.onDescriptionChange(rowId, data);
495
+ }
496
+ instance.destroy();
497
+ }).catch(() => {
498
+ instance.destroy();
499
+ });
500
+ } catch {
501
+ // Blok may already be destroyed
502
+ }
503
+ this.blokInstance = null;
504
+ }
505
+ }
506
+
507
+ private autoResizeTitle(textarea: HTMLTextAreaElement): void {
508
+ const { style } = textarea;
509
+
510
+ style.height = 'auto';
511
+
512
+ if (textarea.scrollHeight > 0) {
513
+ style.height = `${textarea.scrollHeight}px`;
514
+ }
515
+ }
516
+
517
+ private initNestedEditor(editorHolder: HTMLElement, row: DatabaseRow): void {
518
+ import('../../blok').then(({ Blok }) => {
519
+ const rowId = row.id;
520
+ const description = this.descriptionPropertyId !== undefined
521
+ ? row.properties[this.descriptionPropertyId]
522
+ : undefined;
523
+ const blok = new Blok({
524
+ ...this.toolsConfig,
525
+ holder: editorHolder,
526
+ data: description as OutputData | undefined,
527
+ readOnly: this.readOnly,
528
+ onChange: async () => {
529
+ try {
530
+ const data = await this.blokInstance?.save();
531
+
532
+ if (data !== undefined) {
533
+ this.onDescriptionChange(rowId, data);
534
+ }
535
+ } catch {
536
+ // save may fail if editor is being destroyed
537
+ }
538
+ },
539
+ });
540
+
541
+ this.blokInstance = blok as unknown as BlokInstance;
542
+ }).catch(() => {
543
+ // Blok import may fail in unit tests (jsdom), drawer still works for title
544
+ });
545
+ }
546
+ }
@@ -0,0 +1,46 @@
1
+ import type { I18n } from '../../../types';
2
+
3
+ export interface ColumnControlsOptions {
4
+ i18n: I18n;
5
+ onRename: (optionId: string, label: string) => void;
6
+ onDelete: (optionId: string) => void;
7
+ }
8
+
9
+ export class DatabaseColumnControls {
10
+ private options: ColumnControlsOptions;
11
+ private readonly i18n: I18n;
12
+
13
+ constructor(options: ColumnControlsOptions) {
14
+ this.options = options;
15
+ this.i18n = options.i18n;
16
+ }
17
+
18
+ makeEditable(headerEl: HTMLElement, optionId: string): void {
19
+ const titleEl = headerEl.querySelector('[data-blok-database-column-title]');
20
+
21
+ if (titleEl) {
22
+ const input = document.createElement('input');
23
+
24
+ input.type = 'text';
25
+ input.value = titleEl.textContent ?? '';
26
+ input.setAttribute('data-blok-database-column-title-input', '');
27
+ input.setAttribute('aria-label', this.i18n.t('tools.database.renameColumn'));
28
+ input.addEventListener('change', () => {
29
+ this.options.onRename(optionId, input.value);
30
+ });
31
+ titleEl.replaceWith(input);
32
+ }
33
+
34
+ const deleteBtn = document.createElement('button');
35
+
36
+ deleteBtn.setAttribute('data-blok-database-delete-column', '');
37
+ deleteBtn.setAttribute('aria-label', this.i18n.t('tools.database.deleteColumn'));
38
+ deleteBtn.setAttribute('data-option-id', optionId);
39
+ deleteBtn.addEventListener('click', () => {
40
+ this.options.onDelete(optionId);
41
+ });
42
+ headerEl.appendChild(deleteBtn);
43
+ }
44
+
45
+ destroy(): void { /* no global listeners */ }
46
+ }