@mistriwork/mistri 1.0.0-rc.12 → 1.0.0-rc.13

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 (221) hide show
  1. package/README.md +4 -3
  2. package/dist/client/assets/LayoutBuilder-MPzkVU2e.js.map +1 -1
  3. package/dist/client/assets/index-D2dHI6hR.js.map +1 -1
  4. package/dist/client/assets/shell-TreN_uLs.js.map +1 -1
  5. package/dist/docs/access-model.md +1 -1
  6. package/dist/docs/build-and-deploy.md +0 -1
  7. package/dist/docs/cli.md +1 -1
  8. package/dist/docs/glossary.md +3 -3
  9. package/dist/docs/query.md +9 -21
  10. package/dist/docs/status.md +3 -3
  11. package/dist/embed/react/chunks/LayoutBuilder-Cbxa_wve.js.map +1 -1
  12. package/dist/embed/react/chunks/app-0UZ1Re1k.js.map +1 -1
  13. package/dist/embed/react/chunks/page-Bx4o1kpQ.js.map +1 -1
  14. package/dist/embed/react/chunks/palette-Bb7Lf6eo.js.map +1 -1
  15. package/dist/embed/react/chunks/shell-DZRACiB9.js.map +1 -1
  16. package/dist/embed/react/chunks/write-BQO4CFc9.js.map +1 -1
  17. package/dist/embed/react/index.js +1 -1
  18. package/dist/server/build/dockerfile.js +1 -1
  19. package/dist/server/cli/usage.js +2 -2
  20. package/dist/ui/index.js +2 -2
  21. package/dist/ui/page.js +2 -2
  22. package/dist/ui/{shared-N4Ej8yRD.js → shared-1PD7TOTJ.js} +5 -5
  23. package/dist/ui/{shared-N4Ej8yRD.js.map → shared-1PD7TOTJ.js.map} +1 -1
  24. package/dist/ui/{shared-D5m86-4o.js → shared-1gMnOu9J.js} +6 -6
  25. package/dist/ui/{shared-D5m86-4o.js.map → shared-1gMnOu9J.js.map} +1 -1
  26. package/dist/ui/{shared-Ctaj8mR2.js → shared-5RQMi4BR.js} +3 -3
  27. package/dist/ui/{shared-Ctaj8mR2.js.map → shared-5RQMi4BR.js.map} +1 -1
  28. package/dist/ui/{shared-DpLeIATZ.js → shared-B-BUF9fx.js} +2 -2
  29. package/dist/ui/{shared-DpLeIATZ.js.map → shared-B-BUF9fx.js.map} +1 -1
  30. package/dist/ui/{shared-DWYnjItP.js → shared-B-MhiPIN.js} +9 -9
  31. package/dist/ui/{shared-DWYnjItP.js.map → shared-B-MhiPIN.js.map} +1 -1
  32. package/dist/ui/{shared-0fNuhSbG.js → shared-B07qIMlE.js} +5 -5
  33. package/dist/ui/{shared-0fNuhSbG.js.map → shared-B07qIMlE.js.map} +1 -1
  34. package/dist/ui/{shared-lYtMadRU.js → shared-B1SAS_J-.js} +3 -3
  35. package/dist/ui/{shared-lYtMadRU.js.map → shared-B1SAS_J-.js.map} +1 -1
  36. package/dist/ui/{shared-CpI0Y8M5.js → shared-B4jgU8h9.js} +6 -6
  37. package/dist/ui/{shared-CpI0Y8M5.js.map → shared-B4jgU8h9.js.map} +1 -1
  38. package/dist/ui/{shared-Cxu1c35l.js → shared-B5aBCUi7.js} +30 -30
  39. package/dist/ui/{shared-Cxu1c35l.js.map → shared-B5aBCUi7.js.map} +1 -1
  40. package/dist/ui/{shared-CAe-US1q.js → shared-B9H7_Pji.js} +5 -5
  41. package/dist/ui/{shared-CAe-US1q.js.map → shared-B9H7_Pji.js.map} +1 -1
  42. package/dist/ui/{shared-Q2bgBaYo.js → shared-BAXr20S-.js} +4 -4
  43. package/dist/ui/{shared-Q2bgBaYo.js.map → shared-BAXr20S-.js.map} +1 -1
  44. package/dist/ui/{shared-CyEefFFb.js → shared-BDDUzH-f.js} +19 -19
  45. package/dist/ui/{shared-CyEefFFb.js.map → shared-BDDUzH-f.js.map} +1 -1
  46. package/dist/ui/{shared-BdhPI6dq.js → shared-BGmkeDeW.js} +3 -3
  47. package/dist/ui/{shared-BdhPI6dq.js.map → shared-BGmkeDeW.js.map} +1 -1
  48. package/dist/ui/{shared-DONIpq2q.js → shared-BHCQ60yN.js} +2 -2
  49. package/dist/ui/{shared-DONIpq2q.js.map → shared-BHCQ60yN.js.map} +1 -1
  50. package/dist/ui/{shared-CNmaAv64.js → shared-BHsjawAG.js} +8 -8
  51. package/dist/ui/{shared-CNmaAv64.js.map → shared-BHsjawAG.js.map} +1 -1
  52. package/dist/ui/{shared-DgjU9kOy.js → shared-BIQuK_nq.js} +4 -4
  53. package/dist/ui/{shared-DgjU9kOy.js.map → shared-BIQuK_nq.js.map} +1 -1
  54. package/dist/ui/{shared-icSQAj21.js → shared-BOe4W2FI.js} +3 -3
  55. package/dist/ui/{shared-icSQAj21.js.map → shared-BOe4W2FI.js.map} +1 -1
  56. package/dist/ui/{shared-BlxoOJSk.js → shared-BPpC08ip.js} +3 -3
  57. package/dist/ui/{shared-BlxoOJSk.js.map → shared-BPpC08ip.js.map} +1 -1
  58. package/dist/ui/{shared-BtiFL37J.js → shared-BdA3LPCB.js} +2 -2
  59. package/dist/ui/{shared-BtiFL37J.js.map → shared-BdA3LPCB.js.map} +1 -1
  60. package/dist/ui/{shared-CvR94vn4.js → shared-Be3nbWsd.js} +11 -11
  61. package/dist/ui/{shared-CvR94vn4.js.map → shared-Be3nbWsd.js.map} +1 -1
  62. package/dist/ui/{shared-Bl_nF_IH.js → shared-Bf30ZLoS.js} +8 -4
  63. package/dist/ui/shared-Bf30ZLoS.js.map +1 -0
  64. package/dist/ui/{shared-DijrJ_V-.js → shared-BguP_BaR.js} +7 -7
  65. package/dist/ui/{shared-DijrJ_V-.js.map → shared-BguP_BaR.js.map} +1 -1
  66. package/dist/ui/{shared-DPAVoWY0.js → shared-BoLbc2WD.js} +17 -2
  67. package/dist/ui/{shared-DPAVoWY0.js.map → shared-BoLbc2WD.js.map} +1 -1
  68. package/dist/ui/{shared-BkdBTYwx.js → shared-BttyOW4W.js} +3 -3
  69. package/dist/ui/{shared-BkdBTYwx.js.map → shared-BttyOW4W.js.map} +1 -1
  70. package/dist/ui/{shared-CQWLz8uT.js → shared-BumxsBlA.js} +10 -10
  71. package/dist/ui/{shared-CQWLz8uT.js.map → shared-BumxsBlA.js.map} +1 -1
  72. package/dist/ui/{shared-Dzu7tFiC.js → shared-Bw73ktBk.js} +3 -3
  73. package/dist/ui/{shared-Dzu7tFiC.js.map → shared-Bw73ktBk.js.map} +1 -1
  74. package/dist/ui/{shared-BhAYErSx.js → shared-C1B0GH0e.js} +4 -4
  75. package/dist/ui/{shared-BhAYErSx.js.map → shared-C1B0GH0e.js.map} +1 -1
  76. package/dist/ui/{shared-BQJQcGgj.js → shared-C2FsyYr7.js} +4 -4
  77. package/dist/ui/{shared-BQJQcGgj.js.map → shared-C2FsyYr7.js.map} +1 -1
  78. package/dist/ui/{shared-B9lw2Ryh.js → shared-C2RU1qjv.js} +4 -4
  79. package/dist/ui/{shared-B9lw2Ryh.js.map → shared-C2RU1qjv.js.map} +1 -1
  80. package/dist/ui/{shared-DQYNI9wO.js → shared-C42f07hJ.js} +5 -5
  81. package/dist/ui/{shared-DQYNI9wO.js.map → shared-C42f07hJ.js.map} +1 -1
  82. package/dist/ui/{shared-CqCZ8wMY.js → shared-C4LkPCU4.js} +3 -3
  83. package/dist/ui/{shared-CqCZ8wMY.js.map → shared-C4LkPCU4.js.map} +1 -1
  84. package/dist/ui/{shared-BhtpgOpa.js → shared-C4wSfz6k.js} +9 -9
  85. package/dist/ui/{shared-BhtpgOpa.js.map → shared-C4wSfz6k.js.map} +1 -1
  86. package/dist/ui/{shared-BHc2Izkj.js → shared-C9DZtSFH.js} +2 -2
  87. package/dist/ui/{shared-BHc2Izkj.js.map → shared-C9DZtSFH.js.map} +1 -1
  88. package/dist/ui/{shared-DW1YuiNS.js → shared-CA52ClGo.js} +2 -2
  89. package/dist/ui/{shared-DW1YuiNS.js.map → shared-CA52ClGo.js.map} +1 -1
  90. package/dist/ui/{shared-BbSbilkh.js → shared-CBciTwm6.js} +9 -9
  91. package/dist/ui/{shared-BbSbilkh.js.map → shared-CBciTwm6.js.map} +1 -1
  92. package/dist/ui/{shared-C-J32eBn.js → shared-CL3RLKDA.js} +16 -16
  93. package/dist/ui/{shared-C-J32eBn.js.map → shared-CL3RLKDA.js.map} +1 -1
  94. package/dist/ui/{shared-Ck8S4OxW.js → shared-CLq3-_hW.js} +3 -3
  95. package/dist/ui/{shared-Ck8S4OxW.js.map → shared-CLq3-_hW.js.map} +1 -1
  96. package/dist/ui/{shared-Q5WefT7G.js → shared-CMjK-Ucd.js} +3 -3
  97. package/dist/ui/{shared-Q5WefT7G.js.map → shared-CMjK-Ucd.js.map} +1 -1
  98. package/dist/ui/{shared-D3MAuEA3.js → shared-CPjpSFGh.js} +2 -2
  99. package/dist/ui/{shared-D3MAuEA3.js.map → shared-CPjpSFGh.js.map} +1 -1
  100. package/dist/ui/{shared-VshXGwXP.js → shared-CSPhENq3.js} +2 -2
  101. package/dist/ui/{shared-VshXGwXP.js.map → shared-CSPhENq3.js.map} +1 -1
  102. package/dist/ui/{shared-DJrJaE73.js → shared-CZJE4Bmp.js} +3 -3
  103. package/dist/ui/{shared-DJrJaE73.js.map → shared-CZJE4Bmp.js.map} +1 -1
  104. package/dist/ui/{shared-D7ONOwI7.js → shared-C_BhUL2I.js} +7 -7
  105. package/dist/ui/{shared-D7ONOwI7.js.map → shared-C_BhUL2I.js.map} +1 -1
  106. package/dist/ui/{shared-j-2peBIB.js → shared-CbeujwdU.js} +4 -4
  107. package/dist/ui/{shared-j-2peBIB.js.map → shared-CbeujwdU.js.map} +1 -1
  108. package/dist/ui/{shared-D5GrOEa2.js → shared-Cbf-o4Dt.js} +4 -4
  109. package/dist/ui/{shared-D5GrOEa2.js.map → shared-Cbf-o4Dt.js.map} +1 -1
  110. package/dist/ui/{shared-HwiPIajr.js → shared-CdNmeNHh.js} +3 -3
  111. package/dist/ui/{shared-HwiPIajr.js.map → shared-CdNmeNHh.js.map} +1 -1
  112. package/dist/ui/{shared-ZCFt-CPb.js → shared-CdQOMD8J.js} +3 -3
  113. package/dist/ui/{shared-ZCFt-CPb.js.map → shared-CdQOMD8J.js.map} +1 -1
  114. package/dist/ui/{shared-ClhXSGGK.js → shared-CdiPYlTh.js} +2 -2
  115. package/dist/ui/{shared-ClhXSGGK.js.map → shared-CdiPYlTh.js.map} +1 -1
  116. package/dist/ui/{shared-DA8_pVRZ.js → shared-CepLAhwm.js} +2 -2
  117. package/dist/ui/{shared-DA8_pVRZ.js.map → shared-CepLAhwm.js.map} +1 -1
  118. package/dist/ui/{shared-BrYKjrnM.js → shared-Ch82h_Fu.js} +6 -6
  119. package/dist/ui/{shared-BrYKjrnM.js.map → shared-Ch82h_Fu.js.map} +1 -1
  120. package/dist/ui/{shared-C4UrE8Fb.js → shared-Chp88all.js} +3 -3
  121. package/dist/ui/{shared-C4UrE8Fb.js.map → shared-Chp88all.js.map} +1 -1
  122. package/dist/ui/{shared-CWa80DTO.js → shared-Ci16s2rN.js} +9 -9
  123. package/dist/ui/{shared-CWa80DTO.js.map → shared-Ci16s2rN.js.map} +1 -1
  124. package/dist/ui/{shared-tksTLD6Q.js → shared-CiqNkoE1.js} +5 -5
  125. package/dist/ui/{shared-tksTLD6Q.js.map → shared-CiqNkoE1.js.map} +1 -1
  126. package/dist/ui/{shared-yt7DjSrq.js → shared-CpMhOq8F.js} +2 -2
  127. package/dist/ui/{shared-yt7DjSrq.js.map → shared-CpMhOq8F.js.map} +1 -1
  128. package/dist/ui/{shared-Dm0z5WUl.js → shared-CrWv5JKH.js} +6 -6
  129. package/dist/ui/{shared-Dm0z5WUl.js.map → shared-CrWv5JKH.js.map} +1 -1
  130. package/dist/ui/{shared-CQL3FGHc.js → shared-Csfi3Pti.js} +2 -2
  131. package/dist/ui/{shared-CQL3FGHc.js.map → shared-Csfi3Pti.js.map} +1 -1
  132. package/dist/ui/{shared-BKNRbm-V.js → shared-CuZt26rm.js} +2 -2
  133. package/dist/ui/{shared-BKNRbm-V.js.map → shared-CuZt26rm.js.map} +1 -1
  134. package/dist/ui/{shared-Guq3upiR.js → shared-Cws_z-TS.js} +2 -2
  135. package/dist/ui/{shared-Guq3upiR.js.map → shared-Cws_z-TS.js.map} +1 -1
  136. package/dist/ui/{shared-Bw_qZeIj.js → shared-D1KWuCg6.js} +2 -2
  137. package/dist/ui/{shared-Bw_qZeIj.js.map → shared-D1KWuCg6.js.map} +1 -1
  138. package/dist/ui/{shared-CuCZKwXW.js → shared-D66ju_Cb.js} +23 -23
  139. package/dist/ui/{shared-CuCZKwXW.js.map → shared-D66ju_Cb.js.map} +1 -1
  140. package/dist/ui/{shared-DYfX7NSM.js → shared-DGaQZXnw.js} +2 -2
  141. package/dist/ui/{shared-DYfX7NSM.js.map → shared-DGaQZXnw.js.map} +1 -1
  142. package/dist/ui/{shared-B3Hp8tOv.js → shared-DHy41sET.js} +6 -6
  143. package/dist/ui/{shared-B3Hp8tOv.js.map → shared-DHy41sET.js.map} +1 -1
  144. package/dist/ui/{shared-CXyd7IKi.js → shared-DKEOMQ6l.js} +2 -2
  145. package/dist/ui/{shared-CXyd7IKi.js.map → shared-DKEOMQ6l.js.map} +1 -1
  146. package/dist/ui/{shared-Ccmc8YO0.js → shared-DSUICuaJ.js} +33 -33
  147. package/dist/ui/{shared-Ccmc8YO0.js.map → shared-DSUICuaJ.js.map} +1 -1
  148. package/dist/ui/{shared-CL2iw_js.js → shared-DUPMRoO0.js} +13 -13
  149. package/dist/ui/{shared-CL2iw_js.js.map → shared-DUPMRoO0.js.map} +1 -1
  150. package/dist/ui/{shared-Dtp4eRul.js → shared-DVfdm6ah.js} +2 -2
  151. package/dist/ui/{shared-Dtp4eRul.js.map → shared-DVfdm6ah.js.map} +1 -1
  152. package/dist/ui/{shared-BJ5Ex32G.js → shared-DXM7d7lJ.js} +3 -3
  153. package/dist/ui/{shared-BJ5Ex32G.js.map → shared-DXM7d7lJ.js.map} +1 -1
  154. package/dist/ui/{shared-BFr6ld0e.js → shared-DXbMlcev.js} +2 -2
  155. package/dist/ui/{shared-BFr6ld0e.js.map → shared-DXbMlcev.js.map} +1 -1
  156. package/dist/ui/{shared-BUp3jv-N.js → shared-D_SkPtJ9.js} +6 -6
  157. package/dist/ui/{shared-BUp3jv-N.js.map → shared-D_SkPtJ9.js.map} +1 -1
  158. package/dist/ui/{shared-CdNomVzH.js → shared-Dd21k2ic.js} +4 -4
  159. package/dist/ui/{shared-CdNomVzH.js.map → shared-Dd21k2ic.js.map} +1 -1
  160. package/dist/ui/{shared-gRMbxmpu.js → shared-Dh0nHtLZ.js} +8 -8
  161. package/dist/ui/{shared-gRMbxmpu.js.map → shared-Dh0nHtLZ.js.map} +1 -1
  162. package/dist/ui/{shared-BKGJgjog.js → shared-DkOdSpSK.js} +3 -3
  163. package/dist/ui/{shared-BKGJgjog.js.map → shared-DkOdSpSK.js.map} +1 -1
  164. package/dist/ui/{shared-BMsh72Uq.js → shared-Dkph5ckT.js} +2 -2
  165. package/dist/ui/{shared-BMsh72Uq.js.map → shared-Dkph5ckT.js.map} +1 -1
  166. package/dist/ui/{shared-Be1HpDOB.js → shared-Dl1_Nx--.js} +3 -3
  167. package/dist/ui/{shared-Be1HpDOB.js.map → shared-Dl1_Nx--.js.map} +1 -1
  168. package/dist/ui/{shared-BQIZWOoJ.js → shared-Dm0IGbAf.js} +2 -2
  169. package/dist/ui/{shared-BQIZWOoJ.js.map → shared-Dm0IGbAf.js.map} +1 -1
  170. package/dist/ui/{shared-DSUtcU5S.js → shared-DnIkTpPr.js} +5 -5
  171. package/dist/ui/{shared-DSUtcU5S.js.map → shared-DnIkTpPr.js.map} +1 -1
  172. package/dist/ui/{shared-DsxGbYlV.js → shared-Docl_0tq.js} +3 -3
  173. package/dist/ui/{shared-DsxGbYlV.js.map → shared-Docl_0tq.js.map} +1 -1
  174. package/dist/ui/{shared-DZskrV26.js → shared-DprrHC72.js} +2 -2
  175. package/dist/ui/{shared-DZskrV26.js.map → shared-DprrHC72.js.map} +1 -1
  176. package/dist/ui/{shared-Bmw43Hwf.js → shared-DyKsJTZs.js} +2 -2
  177. package/dist/ui/{shared-Bmw43Hwf.js.map → shared-DyKsJTZs.js.map} +1 -1
  178. package/dist/ui/{shared-BLG88Pya.js → shared-FO7vfI3F.js} +4 -4
  179. package/dist/ui/{shared-BLG88Pya.js.map → shared-FO7vfI3F.js.map} +1 -1
  180. package/dist/ui/{shared-DLSd80D1.js → shared-HalAVHjv.js} +3 -3
  181. package/dist/ui/{shared-DLSd80D1.js.map → shared-HalAVHjv.js.map} +1 -1
  182. package/dist/ui/{shared-D1mMBLdj.js → shared-JvcI-LWp.js} +15 -15
  183. package/dist/ui/{shared-D1mMBLdj.js.map → shared-JvcI-LWp.js.map} +1 -1
  184. package/dist/ui/{shared-C6Hv_4O0.js → shared-K7Ym27yg.js} +2 -2
  185. package/dist/ui/{shared-C6Hv_4O0.js.map → shared-K7Ym27yg.js.map} +1 -1
  186. package/dist/ui/{shared-B39ln7oi.js → shared-SzlnwfJO.js} +3 -3
  187. package/dist/ui/{shared-B39ln7oi.js.map → shared-SzlnwfJO.js.map} +1 -1
  188. package/dist/ui/{shared-DgPn_Jll.js → shared-TrGbd1FY.js} +3 -3
  189. package/dist/ui/{shared-DgPn_Jll.js.map → shared-TrGbd1FY.js.map} +1 -1
  190. package/dist/ui/{shared-DrFb-XtA.js → shared-WhbuObEW.js} +2 -2
  191. package/dist/ui/{shared-DrFb-XtA.js.map → shared-WhbuObEW.js.map} +1 -1
  192. package/dist/ui/{shared-DiFQljcq.js → shared-XcSKDp6N.js} +11 -11
  193. package/dist/ui/{shared-DiFQljcq.js.map → shared-XcSKDp6N.js.map} +1 -1
  194. package/dist/ui/{shared-CMAg58rY.js → shared-Z4uBJU6I.js} +7 -6
  195. package/dist/ui/shared-Z4uBJU6I.js.map +1 -0
  196. package/dist/ui/{shared-BnUptuUp.js → shared-bAgeiRa5.js} +2 -2
  197. package/dist/ui/{shared-BnUptuUp.js.map → shared-bAgeiRa5.js.map} +1 -1
  198. package/dist/ui/{shared-BxMvSjey.js → shared-cgXG7OgZ.js} +5 -5
  199. package/dist/ui/{shared-BxMvSjey.js.map → shared-cgXG7OgZ.js.map} +1 -1
  200. package/dist/ui/{shared-u4CG2kQJ.js → shared-eZ0SB_zm.js} +2 -2
  201. package/dist/ui/{shared-u4CG2kQJ.js.map → shared-eZ0SB_zm.js.map} +1 -1
  202. package/dist/ui/{shared-L90bWW8e.js → shared-frKFb79C.js} +2 -2
  203. package/dist/ui/{shared-L90bWW8e.js.map → shared-frKFb79C.js.map} +1 -1
  204. package/dist/ui/{shared-Dd34nhkw.js → shared-hAayNSRA.js} +3 -3
  205. package/dist/ui/{shared-Dd34nhkw.js.map → shared-hAayNSRA.js.map} +1 -1
  206. package/dist/ui/{shared-DzC64cpp.js → shared-j_J16p2B.js} +2 -2
  207. package/dist/ui/{shared-DzC64cpp.js.map → shared-j_J16p2B.js.map} +1 -1
  208. package/dist/ui/{shared-DX7HRIV-.js → shared-tqpl5N3g.js} +6 -6
  209. package/dist/ui/{shared-DX7HRIV-.js.map → shared-tqpl5N3g.js.map} +1 -1
  210. package/dist/ui/{shared-BS5dBMpA.js → shared-y-6_ZDts.js} +2 -2
  211. package/dist/ui/{shared-BS5dBMpA.js.map → shared-y-6_ZDts.js.map} +1 -1
  212. package/dist/ui/{shared-Cv5v_MP1.js → shared-zG6e1Rhz.js} +13 -13
  213. package/dist/ui/{shared-Cv5v_MP1.js.map → shared-zG6e1Rhz.js.map} +1 -1
  214. package/dist/ui/testing.js +1 -1
  215. package/package.json +4 -4
  216. package/dist/docs/cli-browser.md +0 -232
  217. package/dist/docs/database-browser.md +0 -115
  218. package/dist/docs/keyboard.md +0 -63
  219. package/dist/docs/mcp.md +0 -86
  220. package/dist/ui/shared-Bl_nF_IH.js.map +0 -1
  221. package/dist/ui/shared-CMAg58rY.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"shared-CWa80DTO.js","names":[],"sources":["../../src/shared/commandLineCell.ts","../../src/shared/formLines.ts","../../src/client/copy/forms/components/FormLines.ts","../../src/client/components/FormLines.tsx","../../src/client/components/CommandLines.tsx"],"sourcesContent":["/*\n * A command line's cell read as its column's kind (`field.lines`): the server\n * reads every line with it where the command runs, and the browser with the\n * catalog it is served once a form's grid has loaded. Its own module, so that a\n * page with no lines grid — a public form's first page — carries none of it.\n */\nimport { isIsoDate, isoInstant } from './command.js';\nimport type { CommandInputReason } from './commandInput.js';\nimport { columnKind, isFlagColumn, type TableMeta } from '@mistriwork/engine/shared/schema.js';\n\n/**\n * A line's cell as its column holds it: a number for a number (an amount typed\n * as text included), yes or no for a flag, a day or a moment for a date, one of\n * a vocabulary's values, text for the rest. What a grid's box holds is text,\n * so text that reads as the kind is read as it.\n */\nexport function lineCell(table: TableMeta, column: string, value: string | number | boolean): { value: unknown } | CommandInputReason {\n const meta = table.columns.find((c) => c.name === column);\n if (!meta) return 'shape';\n const said = typeof value === 'string' ? value.trim() : value;\n if (isFlagColumn(meta)) {\n if (typeof said === 'boolean') return { value: said };\n if (said === 1 || said === 'true' || said === '1') return { value: true };\n if (said === 0 || said === 'false' || said === '0') return { value: false };\n return 'type';\n }\n if (meta.allowed?.length) return meta.allowed.includes(String(said)) ? { value: String(said) } : 'choice';\n const kind = columnKind(meta.type);\n if (kind === 'number') {\n const n = typeof said === 'number' ? said : typeof said === 'string' && /^-?\\d+(\\.\\d+)?$/.test(said) ? Number(said) : NaN;\n return Number.isFinite(n) ? { value: n } : 'type';\n }\n if (typeof said !== 'string') return 'type';\n if (kind === 'date') return isIsoDate(said) || isoInstant(said) !== undefined ? { value: said } : 'type';\n return { value: said };\n}\n","/**\n * A New form's child rows and the figures it says as they are typed.\n *\n * `form.lines` asks an order's lines (a bundle's items, a pay run's lines)\n * as a grid under the record's fields, and the server inserts them with the\n * record, in its transaction, each one the insert the reader could make of\n * that row alone (dataWriteRoutes.ts). `form.live` names the resource's own\n * computed columns and rollups — `subtotal: sum('order_line', 'line_total')`,\n * `total: computed.number('subtotal + shipping')` — and the form says each as\n * its fields and lines change, worked out by the one evaluator the server's\n * statement agrees with (computedValue.ts `evaluateComputed`). What the form says\n * is a preview: the record's figures are the server's, read from the rows it\n * stored, so nothing the browser works out is ever written.\n *\n * Two readers. The load judges the declarations against the catalog\n * (`formLinesProblems`); the browser works out the values (`liveValues`)\n * from the catalog it is served, where each computed column comes with its\n * constants folded and each rollup with the reference it walks.\n */\nimport type { AppDef, FormLines } from './appModel.js';\nimport { computedReads, type ComputedNode, type ComputedValue } from '@mistriwork/engine/shared/computed.js';\nimport { evaluateComputed } from '@mistriwork/engine/shared/computedValue.js';\nimport { columnKind, tableNamed, type DatabaseSchema, type TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport type { Rollup } from '@mistriwork/engine/shared/rollups.js';\nimport { typedValue } from '@mistriwork/engine/shared/formValues.js';\nexport { typedValue } from '@mistriwork/engine/shared/formValues.js';\n\n/** The child table and the column a rollup reads its rows by: `order_line.order_id` → those two, or undefined for a composite. */\nfunction viaOf(rollup: Pick<Rollup, 'via'>): { table: string; column: string } | undefined {\n const dot = rollup.via.lastIndexOf('.');\n const column = rollup.via.slice(dot + 1);\n return dot < 0 || column.includes('+') ? undefined : { table: rollup.via.slice(0, dot), column };\n}\n\n/** The one reference from `child.whose` to the parent table, if the catalog has exactly that. */\nfunction bindsTo(schema: DatabaseSchema, child: TableMeta, whose: string, parent: TableMeta): boolean {\n return (schema.foreignKeys ?? []).some(\n (fk) => fk.from.table === child.id && fk.to.table === parent.id && fk.from.columns.length === 1 && fk.from.columns[0] === whose,\n );\n}\n\n/**\n * Each resource form's `lines` and `live` against the catalog — rollups and\n * computed columns resolved on it (withRollups, withComputed) — as problems\n * naming the fix. A form whose declarations do not hold would offer a grid\n * the server refuses or a figure that never comes.\n */\nexport function formLinesProblems(app: AppDef, schema: DatabaseSchema): string[] {\n const problems: string[] = [];\n for (const [name, resource] of Object.entries(app.resources ?? {})) {\n const form = resource.form;\n if (!form?.lines && !form?.live) continue;\n const table = tableNamed(schema, name);\n if (!table) continue;\n const at = `resources \"${name}\"`;\n const lines = form.lines ?? [];\n for (const line of lines) {\n const here = `${at}: form.lines \"${line.label}\"`;\n const child = tableNamed(schema, line.from);\n if (!child || !Object.hasOwn(app.resources ?? {}, line.from)) {\n problems.push(`${here}: \"${line.from}\" is not one of this App's resources; declare it, with access: 'write'.`);\n continue;\n }\n if (app.resources![line.from].access !== 'write')\n problems.push(`${here}: the App does not write \"${line.from}\"; give it access: 'write' so its rows can be added with the record.`);\n if (!bindsTo(schema, child, line.whose, table))\n problems.push(\n `${here}: \"${line.whose}\" is not a reference from ${child.name} to ${table.name}; name the column that points at the new record.`,\n );\n for (const column of [...line.show, ...(line.order ? [line.order] : [])]) {\n const meta = child.columns.find((c) => c.name === column);\n if (!meta) problems.push(`${here}: \"${column}\" is not a column of ${child.name}.`);\n else if (meta.writable === false) problems.push(`${here}: \"${column}\" is not written by a form (the database fills it).`);\n }\n if (line.show.includes(line.whose))\n problems.push(`${here} shows \"${line.whose}\", which the server fills with the new record; leave it out.`);\n if (line.order && line.show.includes(line.order))\n problems.push(`${here} shows its order column \"${line.order}\", which the rows' places fill; leave it out of show.`);\n if (line.order && columnKind(child.columns.find((c) => c.name === line.order)?.type ?? '') !== 'number')\n problems.push(`${here}: the order column \"${line.order}\" is not a number.`);\n }\n for (const live of form.live ?? []) {\n const problem = liveProblem(table, live, lines, schema, new Set());\n if (problem) problems.push(`${at}: form.live \"${live}\" ${problem}`);\n }\n }\n return problems;\n}\n\n/** Why a name cannot be worked out live on this form, or undefined when it can. */\nfunction liveProblem(\n table: TableMeta,\n name: string,\n lines: readonly FormLines[],\n schema: DatabaseSchema,\n seen: Set<string>,\n): string | undefined {\n if (seen.has(name)) return `reads itself.`;\n seen.add(name);\n const rollup = table.rollups?.[name];\n if (rollup) {\n const via = viaOf(rollup);\n const childId = via && tableNamed(schema, via.table)?.id;\n const line = childId && lines.find((l) => tableNamed(schema, l.from)?.id === childId && l.whose === via.column);\n if (!via || !line) return `is a rollup of rows this form does not ask; add its rows to form.lines, by the reference it counts.`;\n if (rollup.of) return `rolls up another rollup, which a form's lines do not hold.`;\n if (rollup.fn === 'latest') return `reads the newest of its rows, which a form's lines have no order for until they are saved.`;\n if (rollup.filter)\n return `narrows its rows by a query; a form adds up every line it holds, so roll up a computed column of the line instead.`;\n const reads = rollup.expression ? rollup.expression.reads : rollup.column ? [rollup.column] : [];\n const missing = reads.find((column) => !line.show.includes(column) && column !== line.order);\n if (missing) return `reads \"${missing}\", which the lines \"${line.label}\" do not ask; add it to their show.`;\n return undefined;\n }\n const computed = table.computed?.[name];\n if (!computed) return `is not a computed column or a rollup of ${table.name}.`;\n for (const path of computedReads(computed.expr)) {\n if (path.includes('.')) return `reads \"${path}\" through a reference, which a form does not hold until it is saved.`;\n if (table.rollups?.[path] || table.computed?.[path]) {\n const inner = liveProblem(table, path, lines, schema, seen);\n if (inner) return `reads \"${path}\", which ${inner}`;\n } else if (!table.columns.some((c) => c.name === path)) return `reads \"${path}\", which is not a column of ${table.name}.`;\n }\n return undefined;\n}\n\n/* ---------- the values, in the browser ---------- */\n\n/** A form's draft as text, the way its inputs hold each value: stored units, an empty box as ''. */\nexport type DraftValues = Readonly<Record<string, string | null | undefined>>;\n\n/**\n * The form's live values, by name: each of `names` worked out from the\n * draft (`values`) and its lines (`rows`, keyed by the child table's id), in\n * the catalog's own reading — a computed column's folded expression, a\n * rollup's reference and column. A name the catalog does not serve this\n * reader is left out, as it would be from a list. `today` and `now` were\n * folded where the catalog was served, so a form says what a list would.\n */\nexport function liveValues(\n schema: DatabaseSchema,\n table: TableMeta,\n names: readonly string[],\n values: DraftValues,\n rows: Readonly<Record<string, readonly DraftValues[]>>,\n): Record<string, ComputedValue> {\n const clock = { today: new Date().toISOString().slice(0, 10), now: new Date(), me: null };\n const memo = new Map<string, ComputedValue>();\n const rowValue = (child: TableMeta, row: DraftValues, column: string, expression?: Pick<Rollup, 'expression'>['expression']) =>\n expression\n ? evaluateComputed(expression.expr as ComputedNode, clock, (path) => typedValue(child, path, row[path]))\n : typedValue(child, column, row[column]);\n const value = (name: string): ComputedValue => {\n if (memo.has(name)) return memo.get(name)!;\n memo.set(name, null);\n let result: ComputedValue = null;\n const rollup = table.rollups?.[name];\n const computed = table.computed?.[name];\n if (rollup) {\n const via = viaOf(rollup);\n const child = via && tableNamed(schema, via.table);\n const held = (child && rows[child.id]) ?? [];\n if (child && !rollup.of && !rollup.filter && rollup.fn !== 'latest') {\n /* As the aggregate does: a count of the rows, a sum of their values (0 where none has one), and a least or most with nothing where none has one. */\n const figures = held\n .map((row) => rowValue(child, row, rollup.column ?? '', rollup.expression))\n .filter((v): v is number => typeof v === 'number' && Number.isFinite(v));\n result =\n rollup.fn === 'count'\n ? held.length\n : rollup.fn === 'sum'\n ? figures.reduce((a, b) => a + b, 0)\n : !figures.length\n ? null\n : rollup.fn === 'min'\n ? Math.min(...figures)\n : Math.max(...figures);\n }\n } else if (computed) {\n result = evaluateComputed(computed.expr, clock, (path) =>\n table.rollups?.[path] || table.computed?.[path] ? value(path) : typedValue(table, path, values[path]),\n );\n }\n memo.set(name, result);\n return result;\n };\n return Object.fromEntries(names.filter((name) => table.rollups?.[name] || table.computed?.[name]).map((name) => [name, value(name)]));\n}\n","/** What FormLines says, in the forms room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '@mistriwork/kit/client/messages.js';\n\nexport const say = defineMessages({\n fill: 'Fill in {column}.',\n addLine: 'Add line',\n removeLine: 'Remove line',\n moveUp: 'Move up',\n moveDown: 'Move down',\n moveLine: 'Move line {n}',\n moveLineHint: 'Drag, or press Alt and an arrow key, to move this line',\n lineActions: 'Line {n} actions',\n lineActionsHeading: 'Actions',\n lineMoved: 'Line moved to place {n} of {count}.',\n noLinesYet: 'No lines yet.',\n subtotal: 'Subtotal',\n});\n","/**\n * A record's lines, edited as a grid, and the figures its form says live.\n *\n * Two places draw the grid. A New form with `form.lines` asks the record's\n * lines under its fields, and they are inserted with it (NewRecord.tsx). The\n * save is one request the server writes in one transaction\n * (server/http/formLinesWrite.ts), each row judged as its own write would be.\n * And a command's `field.lines` input asks them in its form (CommandLines.tsx),\n * for its handler to write: there a column may be copied from the record a\n * line's reference names as it is picked (a variant's price), shown and never\n * sent, and the line's money figures are added up under the grid.\n * What is checked here (a required value, an amount) only saves a round trip;\n * the server judges again.\n *\n * The grid reads as an order's lines read on paper, and becomes a form only\n * where it is touched: each cell is a box with no edge until its row is under\n * the pointer or the box has the focus. A column is laid out by its kind — a\n * reference wide, with the record's photo and its second line where the\n * referenced resource's display rule names them; a count narrow, right-aligned,\n * in tabular figures; money with its currency's sign in the box and its\n * minor-unit decimals once it is left. A computed column of the line that\n * reads only what the line holds (`amount: quantity * unit_price`) is said\n * beside it, read-only, as the line is filled in. Moving a line is a drag on\n * its handle, Alt and an arrow on the handle, or its menu; removing it is the\n * menu's. Narrower than a grid fits (a drawer, a phone), each line is a block\n * of its own: its reference across the top, its figures under it.\n *\n * `LiveValues` says the form's computed columns and rollups as it is filled\n * in, worked out by the evaluator the server's statement agrees with\n * (shared/formLines.ts), as an order's summary: the parts a total adds up,\n * each with its sign, then the total. It writes nothing: the saved record's\n * figures are the server's.\n *\n * Fetched the first time a New form has lines or live figures (appnav.js names it\n * for the kit's form: shellMode.ts `formLines`), and with a command form that asks lines.\n */\nimport { useEffect, useMemo, useRef, useState, type KeyboardEvent, type ReactNode } from 'react';\nimport { useQueries } from '@tanstack/react-query';\nimport { api, columnDisplay, columnLabel, findTable, labelPath, recordLabel, state } from '@mistriwork/kit/client/core.js';\nimport { ownedBy } from '@mistriwork/kit/client/requestIdentity.js';\nimport { defaultCurrency, formatLocale, formatMoney, formatNumber } from '@mistriwork/kit/client/locale.js';\nimport { autoKey, isRequired } from '@mistriwork/engine/shared/form.js';\nimport { liveValues, typedValue, type DraftValues } from '../../shared/formLines.js';\nimport { currencyDigits, minorFigure, rowCurrency } from '@mistriwork/engine/shared/money.js';\nimport { humanName } from '@mistriwork/engine/shared/model.js';\nimport { columnKind, primaryKey, type ColumnMeta, type DatabaseSchema, type TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { sumTerms } from './totalTerms.js';\nimport { computedReads, type ComputedValue } from '@mistriwork/engine/shared/computed.js';\nimport type { FieldError } from '@mistriwork/kit/client/fieldErrors.js';\nimport { booleanChoices } from '@mistriwork/kit/client/rowEditing.js';\nimport { ValueControl } from '@mistriwork/kit/client/components/GridCellEditor.js';\nimport { singleReference } from '@mistriwork/kit/client/components/gridCellModel.js';\nimport { columnInput } from '@mistriwork/kit/client/components/inputRenderers.js';\nimport { MinorMoneyInput, minorProblem } from '@mistriwork/kit/client/components/MinorMoneyInput.js';\nimport type { LineDraft } from '@mistriwork/kit/client/shellMode.js';\nimport { RecordPicker } from '@mistriwork/kit/client/components/RecordPicker.js';\nimport { DropItem, DropMenu } from '@mistriwork/ui/DropMenu.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { useAvatarPhotos } from '@mistriwork/kit/client/components/avatarPhotos.js';\nimport { usePointerDrag, type DropPoint } from '@mistriwork/kit/client/components/usePointerDrag.js';\nimport { dressFor, type DisplayRule } from '@mistriwork/kit/client/components/valueModel.js';\nimport { say } from '../copy/forms/components/FormLines.js';\nimport './FormLines.css';\n\n/* One row of the grid, as the kit's New form holds it (shellMode.ts): its values as the inputs hold them (stored units). */\nexport type { LineDraft };\n\nlet lastLine = 0;\nexport const blankLine = (): LineDraft => ({ id: ++lastLine, values: {} });\n\nconst ruleOf = (table: TableMeta, column: string) => columnDisplay(table.id, column) as DisplayRule | null;\nconst minorRule = (table: TableMeta, column: string) => {\n const rule = ruleOf(table, column);\n return rule?.format === 'money' && rule.minor ? rule : undefined;\n};\n\n/**\n * What is wrong with each line before the wire, keyed `${row}.${column}`: a\n * required value left empty, an amount that is not one of its currency.\n * `filled` names the columns the save fills (the reference, the place).\n */\nexport function lineProblems(\n table: TableMeta,\n columns: readonly string[],\n rows: readonly LineDraft[],\n filled: readonly string[] = [],\n): Record<string, string> {\n const problems: Record<string, string> = {};\n const assigned = autoKey(table);\n rows.forEach((row, i) => {\n for (const name of columns) {\n const column = table.columns.find((c) => c.name === name);\n if (!column || filled.includes(name)) continue;\n const value = row.values[name] ?? '';\n const rule = minorRule(table, name);\n if (value === '' && isRequired(column, assigned))\n problems[`${i}.${name}`] = say('fill', {\n column: labelOf(table, column),\n });\n else if (rule) {\n const problem = minorProblem(value, rowCurrency(rule, row.values, rule.currency || defaultCurrency()));\n if (problem) problems[`${i}.${name}`] = problem;\n }\n }\n });\n return problems;\n}\n\n/** A line's values as the save sends them: what its inputs hold, an empty box left to the database on a new row and cleared on a kept one. */\nexport function lineValues(row: LineDraft, columns: readonly string[]): Record<string, string | null> {\n const values: Record<string, string | null> = {};\n for (const name of columns) {\n const value = row.values[name];\n if (value === undefined || (value === '' && !row.key)) continue;\n values[name] = value === '' ? null : value;\n }\n return values;\n}\n\n/** The server's word on a line's field, which it says as `order_line[2].quantity` (recordWriteOperations.ts). */\nexport function lineServerProblems(table: TableMeta, errors: readonly FieldError[]): Record<string, string> {\n const prefix = `${table.name}[`;\n return Object.fromEntries(\n errors.flatMap((error) => {\n if (!error.field.startsWith(prefix)) return [];\n const m = /^\\[(\\d+)\\]\\.(.+)$/.exec(error.field.slice(table.name.length));\n return m ? [[`${m[1]}.${m[2]}`, error.message]] : [];\n }),\n );\n}\n\nfunction labelOf(table: TableMeta, column: ColumnMeta): string {\n return (columnLabel(table.id, column.name) as string | null) ?? humanName(column.name);\n}\n\n/** The sign a currency is written with here: \"$\", \"€\", \"CHF\". */\nexport function currencySymbol(currency: string): string {\n try {\n return (\n new Intl.NumberFormat(formatLocale(), { style: 'currency', currency }).formatToParts(0).find((part) => part.type === 'currency')\n ?.value ?? currency\n );\n } catch {\n return currency;\n }\n}\n\n/* ---------- columns by kind ---------- */\n\n/**\n * How a line's column is drawn. The App's own input for it (`inputs`), a\n * vocabulary and a date keep the control a cell edits with (GridCellEditor's\n * `ValueControl`); a reference, money, a number and text are the grid's own\n * cells, which read as a table until touched.\n */\ntype CellKind = 'reference' | 'money' | 'number' | 'text' | 'control';\n\nfunction cellKind(table: TableMeta, column: ColumnMeta): CellKind {\n if (columnInput(table.id, column.name)) return 'control';\n if (column.references && singleReference(table, column) && findTable(column.references.table)) return 'reference';\n if (column.allowed?.length || booleanChoices(column, null)) return 'control';\n const kind = columnKind(column.type);\n if (kind === 'date') return 'control';\n if (ruleOf(table, column.name)?.format === 'money') return 'money';\n return kind === 'number' ? 'number' : 'text';\n}\n\n/**\n * The line's own figures: each computed column that reads nothing but the\n * line's plain columns (`quantity * unit_price`), worked out as it is typed.\n * One that reads through a reference or a rollup waits for the saved row.\n */\nfunction lineFigures(table: TableMeta, shown: readonly string[]): string[] {\n return Object.entries(table.computed ?? {})\n .filter(([name, computed]) => {\n if (shown.includes(name)) return false;\n const reads = computedReads(computed.expr);\n return reads.length > 0 && reads.every((path) => !path.includes('.') && table.columns.some((c) => c.name === path));\n })\n .map(([name]) => name);\n}\n\n/**\n * A computed figure's dress: its own rule, else — an amount worked out of one\n * money column, `quantity * unit_price` — that column's, so a line's amount\n * is money in the same units and currency as the price it was made of.\n */\nfunction figureRule(table: TableMeta, name: string): DisplayRule | null {\n const own = ruleOf(table, name);\n if (own || !table.computed?.[name]) return own;\n const money = computedReads(table.computed[name].expr).filter((path) => ruleOf(table, path)?.format === 'money');\n return money.length === 1 ? ruleOf(table, money[0]) : null;\n}\n\n/** A live figure in its column's dress: money as money, minor units in their currency, a count as a number. */\nfunction sayFigure(rule: DisplayRule | null, value: ComputedValue, draft: DraftValues): string {\n if (value === null) return '—';\n if (typeof value === 'object') return 'day' in value ? value.day : value.instant.toISOString();\n const shaped = rule?.currencyColumn\n ? {\n ...rule,\n currency: rowCurrency(rule, draft, rule.currency ?? '') || undefined,\n }\n : rule;\n const dress = typeof value === 'number' ? dressFor(shaped, value) : null;\n /* Beside the money typed in this grid, which keeps its cents, a figure keeps them too: a line of 2 × $38.00 is\n $76.00, not the \"$76\" a whole number says elsewhere (formatMoney), which read as rounded next to its price.\n A part taken off a total is said with the minus sign, not a hyphen. */\n if (dress && 'text' in dress && typeof dress.text === 'string' && dress.kind === 'money') {\n const currency = shaped?.currency || defaultCurrency();\n const major = Number(shaped?.minor ? (minorFigure(value as number, currency) ?? value) : value);\n const digits = currencyDigits(currency);\n const said = Number.isFinite(major)\n ? formatMoney(major, currency, { minimumFractionDigits: digits, maximumFractionDigits: digits })\n : dress.text;\n return said.replace(/^-/, '−');\n }\n if (typeof value === 'number') return formatNumber(value);\n return typeof value === 'boolean' ? (value ? say('common.yes') : say('common.no')) : value;\n}\n\n/** Figures worked out of one row, by the evaluator the server agrees with; nothing where the catalog has changed under it. */\nfunction figuresOf(schema: DatabaseSchema | null, table: TableMeta, names: readonly string[], values: DraftValues, lines = {}) {\n if (!schema || !names.length) return {} as Record<string, ComputedValue>;\n try {\n return liveValues(schema, table, names, values, lines);\n } catch {\n return {} as Record<string, ComputedValue>;\n }\n}\n\n/* ---------- a reference, with its record's photo and second line ---------- */\n\ntype Photo = Exclude<NonNullable<DisplayRule['avatar']>, boolean>;\n\n/** What a reference cell draws of the record it names, beside the name: from the referenced resource's own display rule. */\ninterface Face {\n column: string;\n target: TableMeta;\n valueColumn: string;\n key: string;\n /** The record's column holding the key its photo is of: its own key, or the reference it is named through. */\n owner: string;\n subtitle?: string;\n photo?: Photo;\n}\n\nfunction faceOf(column: ColumnMeta): Face | undefined {\n const target = column.references ? (findTable(column.references.table) as TableMeta | undefined) : undefined;\n const key = target ? primaryKey(target) : [];\n /* The column the record is named by: its label path, or a label template's first column (`{title} · {sku}`). */\n const path = target ? (labelPath(target) as string | undefined) : undefined;\n const naming = path && !path.startsWith('$') ? path : /\\{([^}]+)\\}/.exec(String((target && recordLabel(target)) ?? ''))?.[1];\n if (!target || key.length !== 1 || !naming) return undefined;\n const [own, far, more] = naming.split('.');\n if (more !== undefined) return undefined;\n const second = (rule: DisplayRule | null) =>\n typeof rule?.subtitle === 'string' ? target.columns.find((c) => c.name === rule.subtitle && !c.references) : undefined;\n const photoOf = (rule: DisplayRule | null) => (rule?.avatar && typeof rule.avatar === 'object' ? rule.avatar : undefined);\n let face: Pick<Face, 'owner' | 'subtitle' | 'photo'>;\n if (far === undefined) {\n const rule = ruleOf(target, own);\n const sub = second(rule);\n const photo = photoOf(rule);\n face = { owner: key[0], ...(sub ? { subtitle: sub.name } : {}), ...(photo ? { photo } : {}) };\n } else {\n /* Named through a reference (a variant as `{product_id.title} · {color} / {size}`): the photo is the record\n it names, by that column's own rule there, owned through the reference; the second line is the rule on\n the reference itself, a column of this record (`product_id: { subtitle: 'sku' }`). */\n const via = target.columns.find((c) => c.name === own && c.references);\n const named = via ? (findTable(via.references!.table) as TableMeta | undefined) : undefined;\n if (!via || !named || via.references!.column !== primaryKey(named)[0]) return undefined;\n const sub = second(ruleOf(target, own));\n const photo = photoOf(ruleOf(named, far));\n face = { owner: own, ...(sub ? { subtitle: sub.name } : {}), ...(photo ? { photo } : {}) };\n }\n if (!face.subtitle && !face.photo) return undefined;\n return { column: column.name, target, valueColumn: column.references!.column, key: key[0], ...face };\n}\n\nconst said = (value: unknown) => (value === null || value === undefined ? '' : String(value));\n\n/** A record's photo in its square, or the square alone: the cell keeps its size whether the picture has come or not. */\nfunction Thumb({ src }: { src?: string }) {\n return <span className=\"lines-thumb\">{src ? <img src={src} alt=\"\" loading=\"lazy\" decoding=\"async\" /> : null}</span>;\n}\n\n/** One choice in a reference cell's list: its photo, its name and its second line. */\nfunction FaceOption({\n face,\n row,\n label,\n rows,\n}: {\n face: Face;\n row: Record<string, unknown>;\n label: string;\n rows: readonly Record<string, unknown>[];\n}) {\n /* Every choice asks with the same rows, so the list's photos are one question. */\n const photos = useAvatarPhotos(\n face.photo\n ? [\n {\n name: 'choice',\n display: { avatar: face.photo },\n photoOwner: face.owner,\n },\n ]\n : [],\n rows,\n );\n return (\n <span className=\"lines-choice\">\n {face.photo && <Thumb src={photos('choice', row[face.owner])} />}\n <span className=\"lines-choice-text\">\n <span className=\"picker-option-label\">{label}</span>\n {face.subtitle && <span className=\"lines-ref-sub\">{said(row[face.subtitle])}</span>}\n </span>\n </span>\n );\n}\n\n/** The chosen records of every reference column with a face, one question per column, and their photos. */\nfunction useFaces(faces: readonly Face[], rows: readonly LineDraft[]) {\n const connection = state.activeConnection;\n const asked = faces.map((face) => [...new Set(rows.map((row) => row.values[face.column]).filter(Boolean))].sort());\n const answers = useQueries({\n queries: faces.map((face, i) => ({\n queryKey: ['lines-faces', connection, face.target.id, face.valueColumn, face.owner, face.subtitle, asked[i]],\n enabled: asked[i].length > 0,\n staleTime: 60_000,\n placeholderData: (previous: Record<string, unknown>[] | undefined) => previous,\n queryFn: async () => {\n const data = (await api('/api/query', {\n ...ownedBy(connection),\n table: face.target.id,\n columns: [...new Set([face.key, face.owner, face.valueColumn, ...(face.subtitle ? [face.subtitle] : [])])],\n filter: {\n groups: [\n [\n {\n column: face.valueColumn,\n op: 'in' as const,\n value: asked[i],\n },\n ],\n ],\n },\n limit: asked[i].length,\n offset: 0,\n })) as { rows?: Record<string, unknown>[] };\n return data.rows ?? [];\n },\n })),\n });\n const owners = faces.flatMap((face, i) =>\n face.photo ? (answers[i]?.data ?? []).map((row) => ({ [face.column]: row[face.owner] }) as Record<string, unknown>) : [],\n );\n const photos = useAvatarPhotos(\n faces.flatMap((face) =>\n face.photo\n ? [\n {\n name: face.column,\n display: { avatar: face.photo },\n photoOwner: face.column,\n },\n ]\n : [],\n ),\n owners,\n );\n return (column: string, value: string): { photo?: string; subtitle?: string } => {\n const i = faces.findIndex((face) => face.column === column);\n if (i < 0 || !value) return {};\n const row = answers[i]?.data?.find((each) => said(each[faces[i].valueColumn]) === value);\n return {\n photo: row ? photos(column, row[faces[i].owner]) : undefined,\n subtitle: row && faces[i].subtitle ? said(row[faces[i].subtitle!]) : '',\n };\n };\n}\n\n/* ---------- columns copied from the record a reference names ---------- */\n\n/**\n * A command's `copy`: each copied column of a line filled from the record its\n * reference names (`unit_price_amount` ← `variant_id.price_amount`), asked once\n * per reference column for every record the lines name. A line whose reference\n * is empty, or names a record not yet read, holds nothing there.\n */\nfunction useCopies(\n table: TableMeta,\n copy: Readonly<Record<string, string>>,\n rows: readonly LineDraft[],\n onChange: (rows: LineDraft[]) => void,\n) {\n const connection = state.activeConnection;\n const vias = [...new Set(Object.values(copy).map((path) => path.split('.')[0]))].flatMap((via) => {\n const reference = table.columns.find((c) => c.name === via)?.references;\n const target = reference ? (findTable(reference.table) as TableMeta | undefined) : undefined;\n if (!reference || !target) return [];\n const reads = Object.entries(copy)\n .filter(([, path]) => path.split('.')[0] === via)\n .map(([column, path]) => ({ column, read: path.split('.')[1] }));\n const asked = [...new Set(rows.map((row) => row.values[via]).filter(Boolean))].sort();\n return [{ via, target, valueColumn: reference.column, reads, asked }];\n });\n const answers = useQueries({\n queries: vias.map((each) => ({\n queryKey: ['lines-copies', connection, each.target.id, each.valueColumn, each.reads.map((r) => r.read), each.asked],\n enabled: each.asked.length > 0,\n staleTime: 60_000,\n placeholderData: (previous: Record<string, unknown>[] | undefined) => previous,\n queryFn: async () => {\n const data = (await api('/api/query', {\n ...ownedBy(connection),\n table: each.target.id,\n columns: [...new Set([each.valueColumn, ...each.reads.map((r) => r.read)])],\n filter: { groups: [[{ column: each.valueColumn, op: 'in' as const, value: each.asked }]] },\n limit: each.asked.length,\n offset: 0,\n })) as { rows?: Record<string, unknown>[] };\n return data.rows ?? [];\n },\n })),\n });\n const read = vias.map((_, i) => answers[i]?.data);\n useEffect(() => {\n let changed = false;\n const next = rows.map((row) => {\n const values = { ...row.values };\n vias.forEach((each, i) => {\n const record = read[i]?.find((candidate) => said(candidate[each.valueColumn]) === (row.values[each.via] ?? ''));\n for (const { column, read: from } of each.reads) {\n const value = record ? said(record[from]) : '';\n if ((values[column] ?? '') !== value) {\n values[column] = value;\n changed = true;\n }\n }\n });\n return { ...row, values };\n });\n if (changed) onChange(next);\n });\n}\n\n/* ---------- money ---------- */\n\n/** An amount as the cell shows it once left: in its currency, with its decimals; text that is no amount stays as typed. */\nfunction shownMoney(text: string, digits: number, currency: string): string {\n if (!/^-?\\d+(\\.\\d*)?$/.test(text.trim())) return text;\n const [, decimals = ''] = text.trim().split('.');\n return decimals.length > digits\n ? text\n : formatMoney(Number(text), currency, { minimumFractionDigits: digits, maximumFractionDigits: digits });\n}\n\nfunction MoneyCell({\n value,\n currency,\n minor,\n onChange,\n input,\n}: {\n value: string;\n currency: string;\n minor: boolean;\n onChange: (value: string) => void;\n input: {\n 'aria-label': string;\n 'aria-invalid'?: true;\n 'aria-describedby'?: string;\n };\n}) {\n const [focused, setFocused] = useState(false);\n const digits = currencyDigits(currency);\n /* At rest the figure reads as the amount column's do, \"$148.00\"; in the box the sign stands before what is typed. */\n const box = (text: string, typed: (next: string) => void) => (\n <span className=\"lines-box lines-money\">\n {focused && (\n <span className=\"lines-affix\" aria-hidden=\"true\">\n {currencySymbol(currency)}\n </span>\n )}\n <input\n type=\"text\"\n inputMode=\"decimal\"\n className=\"lines-input is-figure\"\n autoComplete=\"off\"\n {...input}\n value={focused ? text : shownMoney(text, digits, currency)}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n onChange={(event) => typed(event.target.value)}\n />\n </span>\n );\n return minor ? (\n <MinorMoneyInput value={value} currency={currency} onChange={onChange}>\n {box}\n </MinorMoneyInput>\n ) : (\n box(value, onChange)\n );\n}\n\n/* ---------- the grid ---------- */\n\n/** Six dots: what a line is lifted by. */\nfunction Grip() {\n return (\n <svg width=\"8\" height=\"14\" viewBox=\"0 0 8 14\" aria-hidden=\"true\" focusable=\"false\">\n {[2, 7, 12].flatMap((y) => [1.5, 6.5].map((x) => <circle key={`${x}-${y}`} cx={x} cy={y} r=\"1.3\" fill=\"currentColor\" />))}\n </svg>\n );\n}\n\nexport function LinesEditor({\n title,\n table,\n columns,\n rows,\n onChange,\n ordered = false,\n max = 64,\n problems = {},\n disabled = false,\n titleShown = true,\n summary,\n description,\n copy,\n where,\n subtotal = false,\n}: {\n title: string;\n /** A line under the title: what the lines are for, or what happens to them. */\n description?: string;\n /** Columns of the line filled from the record a reference names, shown read-only and never typed (`useCopies`). */\n copy?: Readonly<Record<string, string>>;\n /** A reference column → the rows its picker offers (a command's `query`): a variant for sale, not every variant. */\n where?: Readonly<Record<string, string>>;\n /** Where no `summary` is given, the line's money figures added up under the grid. */\n subtotal?: boolean;\n /** False where a section's own heading already says it: the legend is then for assistive technology alone. */\n titleShown?: boolean;\n table: TableMeta;\n columns: readonly string[];\n rows: readonly LineDraft[];\n onChange: (rows: LineDraft[]) => void;\n /** The rows' places are kept (`order`): each can move up and down. */\n ordered?: boolean;\n max?: number;\n /** What is wrong, by `${row}.${column}`: the form's own checks, then the server's. */\n problems?: Record<string, string>;\n disabled?: boolean;\n /** The figures the lines add up to, beside Add line, their values under the amounts (`LiveValues`). */\n summary?: ReactNode;\n}) {\n const shown = columns.map((name) => table.columns.find((c) => c.name === name)).filter((c): c is ColumnMeta => Boolean(c));\n const kinds = shown.map((column) => cellKind(table, column));\n const copied = Object.keys(copy ?? {}).filter((name) => table.columns.some((c) => c.name === name));\n const figures = useMemo(() => lineFigures(table, [...columns, ...copied]), [table, columns, copied.join()]);\n useCopies(table, copy ?? {}, rows, onChange);\n const figured = rows.map((row) => figuresOf(state.schema as DatabaseSchema | null, table, figures, row.values));\n /* The money a line works out, added up: an order's subtotal, said as the line's own figures are. */\n const sums = subtotal && !summary ? figures.filter((name) => figureRule(table, name)?.format === 'money') : [];\n const faces = shown.flatMap((column, i) => (kinds[i] === 'reference' ? (faceOf(column) ?? []) : []));\n const faceFor = useFaces(faces, rows);\n const added = useRef<number | null>(null);\n /* After a move the focus stays on what moved it: the handle, or the menu's button. */\n const refocus = useRef<{ line: number; what: string } | null>(null);\n const body = useRef<HTMLTableSectionElement>(null);\n const [moved, setMoved] = useState('');\n const [dropAt, setDropAt] = useState<{\n line: number;\n side: 'before' | 'after';\n } | null>(null);\n /* A new line takes the focus in its first box, so a keyboard adds lines as fast as it types them. */\n useEffect(() => {\n if (added.current !== null) {\n body.current?.querySelector<HTMLElement>(`tr[data-line=\"${added.current}\"] input`)?.focus();\n added.current = null;\n }\n if (refocus.current) {\n body.current?.querySelector<HTMLElement>(`tr[data-line=\"${refocus.current.line}\"] ${refocus.current.what}`)?.focus();\n refocus.current = null;\n }\n });\n const set = (i: number, name: string, value: string | null) =>\n onChange(rows.map((row, at) => (at === i ? { ...row, values: { ...row.values, [name]: value ?? '' } } : row)));\n const place = (from: number, to: number, focus?: string) => {\n if (to < 0 || to >= rows.length || to === from) return;\n const next = [...rows];\n const [line] = next.splice(from, 1);\n next.splice(to, 0, line);\n if (focus) refocus.current = { line: line.id, what: focus };\n setMoved(say('lineMoved', { n: to + 1, count: rows.length }));\n onChange(next);\n };\n const remove = (i: number) => {\n const next = rows.filter((_, at) => at !== i);\n /* The focus goes to the line that took its place, else the one above, else Add line. */\n const heir = next[Math.min(i, next.length - 1)];\n if (heir) refocus.current = { line: heir.id, what: '.row-actions-trigger' };\n onChange(next);\n };\n const drag = usePointerDrag<number>({\n over: (line, at) => setDropAt(dropOf(line, at)),\n drop: (line, at) => {\n const target = dropOf(line, at);\n const from = rows.findIndex((row) => row.id === line);\n if (!target || from < 0) return;\n let to = rows.findIndex((row) => row.id === target.line) + (target.side === 'after' ? 1 : 0);\n if (to > from) to -= 1;\n place(from, to, '.lines-grip');\n },\n end: () => setDropAt(null),\n items: 'tr[data-line]',\n });\n /* Where a line let go over `at` lands: before or after the row under it, never beside itself. */\n const dropOf = (line: number, at: DropPoint | null): { line: number; side: 'before' | 'after' } | null => {\n if (!at) return null;\n const under = at.item ? Number(at.item.dataset.line) : rows[rows.length - 1]?.id;\n if (under === undefined || under === line) return null;\n return { line: under, side: at.item && at.upper ? 'before' : 'after' };\n };\n const gripKeys = (event: KeyboardEvent, i: number) => {\n const by = event.key === 'ArrowUp' ? -1 : event.key === 'ArrowDown' ? 1 : 0;\n if (!by || event.ctrlKey || event.metaKey || event.shiftKey) return;\n event.preventDefault();\n place(i, i + by, '.lines-grip');\n };\n const currencyOf = (column: ColumnMeta, row: LineDraft) => {\n const rule = ruleOf(table, column.name);\n return rowCurrency(rule ?? {}, row.values, rule?.currency || defaultCurrency());\n };\n const columnClass = (kind: CellKind) => `is-${kind}`;\n const span = shown.length + copied.length + figures.length + (ordered ? 1 : 0) + 1;\n const copiedLabel = (name: string) => (columnLabel(table.id, name) as string | null) ?? humanName(name);\n return (\n <fieldset className=\"form-lines\" disabled={disabled}>\n <legend className={titleShown ? undefined : 'visually-hidden'}>{title}</legend>\n {description && <p className=\"form-lines-description\">{description}</p>}\n <div className=\"form-lines-body\">\n <table className={`form-lines-grid${ordered ? ' is-ordered' : ''}`}>\n <colgroup>\n {ordered && <col className=\"lines-col-grip\" />}\n {shown.map((column, i) => (\n <col key={column.name} className={`lines-col-${kinds[i]}`} />\n ))}\n {copied.map((name) => (\n <col key={name} className=\"lines-col-figure\" />\n ))}\n {figures.map((name) => (\n <col key={name} className=\"lines-col-figure\" />\n ))}\n <col className=\"lines-col-menu\" />\n </colgroup>\n <thead>\n <tr>\n {ordered && <th aria-hidden=\"true\" />}\n {shown.map((column, i) => (\n <th key={column.name} scope=\"col\" className={columnClass(kinds[i])}>\n {labelOf(table, column)}\n </th>\n ))}\n {copied.map((name) => (\n <th key={name} scope=\"col\" className=\"is-figure\">\n {copiedLabel(name)}\n </th>\n ))}\n {figures.map((name) => (\n <th key={name} scope=\"col\" className=\"is-figure\">\n {(columnLabel(table.id, name) as string | null) ?? humanName(name)}\n </th>\n ))}\n <th>\n <span className=\"visually-hidden\">{say('lineActionsHeading')}</span>\n </th>\n </tr>\n </thead>\n <tbody ref={body} data-drop-zone=\"\">\n {rows.map((row, i) => {\n const n = i + 1;\n return (\n <tr\n key={row.id}\n data-line={row.id}\n {...(dropAt?.line === row.id ? { 'data-drop': dropAt.side } : {})}\n {...(drag.dragging === row.id ? { 'data-lifted': '' } : {})}\n >\n {ordered && (\n <td className=\"lines-handle\">\n <button\n type=\"button\"\n className=\"lines-grip\"\n aria-label={say('moveLine', { n })}\n aria-keyshortcuts=\"Alt+ArrowUp Alt+ArrowDown\"\n title={say('moveLineHint')}\n onPointerDown={(event) => {\n const line = event.currentTarget.closest('tr');\n if (line) drag.start(event, row.id, line);\n }}\n onKeyDown={(event) => gripKeys(event, i)}\n >\n <Grip />\n </button>\n </td>\n )}\n {shown.map((column, at) => {\n const kind = kinds[at];\n const problem = problems[`${i}.${column.name}`];\n const errorId = problem ? `line-${row.id}-${column.name}-error` : undefined;\n const label = `${labelOf(table, column)}, ${n}`;\n const value = row.values[column.name] ?? '';\n const input = {\n 'aria-label': label,\n ...(problem\n ? {\n 'aria-invalid': true as const,\n 'aria-describedby': errorId,\n }\n : {}),\n };\n let cell: ReactNode;\n if (kind === 'reference') {\n const face = faces.find((each) => each.column === column.name);\n const target = findTable(column.references!.table) as TableMeta;\n const known = face ? faceFor(column.name, value) : {};\n cell = (\n <span className={`lines-box lines-ref${face?.photo ? ' has-thumb' : ''}${face?.subtitle ? ' has-sub' : ''}`}>\n {face?.photo && <Thumb src={known.photo} />}\n <span className=\"lines-ref-text\">\n <RecordPicker\n table={target}\n valueColumn={column.references!.column}\n value={value}\n onChange={(next) => set(i, column.name, next)}\n ariaLabel={label}\n invalid={input['aria-invalid'] === true}\n {...(input['aria-describedby'] ? { describedBy: input['aria-describedby'] } : {})}\n app\n hideKey={Boolean(face)}\n {...(where?.[column.name] ? { where: where[column.name] } : {})}\n editing={{ onStateChange: () => {} }}\n {...(face\n ? {\n face: {\n columns: [...new Set([face.key, face.owner, ...(face.subtitle ? [face.subtitle] : [])])],\n draw: (choice, name, all) => <FaceOption face={face} row={choice} label={name} rows={all} />,\n },\n }\n : {})}\n />\n {face?.subtitle && <span className=\"lines-ref-sub\">{known.subtitle}</span>}\n </span>\n </span>\n );\n } else if (kind === 'money') {\n cell = (\n <MoneyCell\n value={value}\n currency={currencyOf(column, row)}\n minor={Boolean(minorRule(table, column.name))}\n onChange={(next) => set(i, column.name, next)}\n input={input}\n />\n );\n } else if (kind === 'number' || kind === 'text') {\n cell = (\n <span className=\"lines-box\">\n <input\n type=\"text\"\n className={`lines-input${kind === 'number' ? ' is-figure' : ''}`}\n autoComplete=\"off\"\n {...(kind === 'number' ? { inputMode: 'decimal' as const } : {})}\n {...input}\n value={value}\n onChange={(event) => set(i, column.name, event.target.value)}\n />\n </span>\n );\n } else {\n cell = (\n <span className=\"lines-box lines-control\">\n <ValueControl\n table={table}\n column={column}\n value={value}\n onChange={(next) => set(i, column.name, next)}\n label={label}\n row={row.values}\n invalid={Boolean(problem)}\n describedBy={errorId}\n />\n </span>\n );\n }\n return (\n <td\n key={column.name}\n className={`${columnClass(kind)}${at === 0 ? ' lines-lead' : ''}${problem ? ' is-invalid' : ''}`}\n data-label={labelOf(table, column)}\n >\n {cell}\n {problem && (\n <span id={errorId} className=\"insert-missing\">\n {problem}\n </span>\n )}\n </td>\n );\n })}\n {copied.map((name) => (\n <td key={name} className=\"is-figure lines-figure lines-copied\" data-label={copiedLabel(name)}>\n {sayFigure(ruleOf(table, name), typedValue(table, name, row.values[name]), row.values)}\n </td>\n ))}\n {figures.map((name) => (\n <td\n key={name}\n className=\"is-figure lines-figure\"\n data-label={(columnLabel(table.id, name) as string | null) ?? humanName(name)}\n >\n {sayFigure(figureRule(table, name), figured[i][name] ?? null, row.values)}\n </td>\n ))}\n <td className=\"lines-menu\">\n <DropMenu\n className=\"row-actions-menu\"\n triggerClassName=\"ghost row-actions-trigger\"\n triggerLabel={say('lineActions', { n })}\n triggerTitle={say('lineActions', { n })}\n label=\"⋯\"\n popupClassName=\"page-actions-popup\"\n align=\"end\"\n >\n {ordered && (\n <DropItem className=\"page-actions-item\" disabled={i === 0} onClick={() => place(i, i - 1, '.row-actions-trigger')}>\n {say('moveUp')}\n </DropItem>\n )}\n {ordered && (\n <DropItem\n className=\"page-actions-item\"\n disabled={i === rows.length - 1}\n onClick={() => place(i, i + 1, '.row-actions-trigger')}\n >\n {say('moveDown')}\n </DropItem>\n )}\n <DropItem className=\"page-actions-item is-danger\" onClick={() => remove(i)}>\n {say('removeLine')}\n </DropItem>\n </DropMenu>\n </td>\n </tr>\n );\n })}\n {!rows.length && (\n <tr className=\"lines-empty\">\n <td colSpan={span}>{say('noLinesYet')}</td>\n </tr>\n )}\n </tbody>\n </table>\n <div className=\"form-lines-foot\">\n <Button\n intent=\"quiet\"\n size=\"compact\"\n className=\"lines-add\"\n disabled={rows.length >= max}\n onClick={() => {\n const line = blankLine();\n added.current = line.id;\n onChange([...rows, line]);\n }}\n >\n + {say('addLine')}\n </Button>\n {summary}\n {sums.length > 0 && (\n <dl className=\"form-live lines-summary\" aria-live=\"polite\">\n {sums.map((name) => {\n const amounts = figured.map((each) => each[name]).filter((v): v is number => typeof v === 'number');\n const total = amounts.length ? amounts.reduce((a, b) => a + b, 0) : null;\n return (\n <div key={name} className=\"lines-summary-row\">\n <dt>{sums.length === 1 ? say('subtotal') : copiedLabel(name)}</dt>\n <dd>{sayFigure(figureRule(table, name), total, rows[0]?.values ?? {})}</dd>\n </div>\n );\n })}\n </dl>\n )}\n </div>\n <div className=\"visually-hidden\" aria-live=\"polite\">\n {moved}\n </div>\n </div>\n </fieldset>\n );\n}\n\n/* ---------- the summary ---------- */\n\n/** The summary's rows: the live names, and where the last is a sum, the record's own columns it adds, in its order. */\nfunction summaryRows(table: TableMeta, names: readonly string[]): Array<{ name: string; sign: number; live: boolean }> {\n const total = names[names.length - 1];\n const terms = total && table.computed?.[total] ? sumTerms(table.computed[total].expr) : undefined;\n const live = (name: string) => names.includes(name);\n const parts =\n terms\n ?.filter(\n (term) => live(term.path) || (ruleOf(table, term.path)?.format === 'money' && table.columns.some((c) => c.name === term.path)),\n )\n .map((term) => ({\n name: term.path,\n sign: term.sign,\n live: live(term.path),\n })) ?? [];\n const before = names.slice(0, -1).filter((name) => !parts.some((part) => part.name === name));\n return [\n ...before.map((name) => ({ name, sign: 1, live: true })),\n ...parts.filter((part) => part.name !== total),\n ...(total ? [{ name: total, sign: 1, live: true }] : []),\n ];\n}\n\n/** The form's `live` figures, worked out from its draft and lines as they change: an order's summary, its total last. */\nexport function LiveValues({\n table,\n names,\n values,\n lines,\n}: {\n table: TableMeta;\n names: readonly string[];\n values: DraftValues;\n /** Each collection's rows, by the child table's id. */\n lines: Readonly<Record<string, readonly LineDraft[]>>;\n}) {\n const figures = useMemo(() => {\n const rows = Object.fromEntries(Object.entries(lines).map(([id, held]) => [id, held.map((row) => row.values)]));\n /* A catalog that changed under the form says nothing rather than something wrong. */\n return figuresOf(state.schema as DatabaseSchema | null, table, names, values, rows);\n }, [table, names, values, lines]);\n const known = names.filter((name) => Object.hasOwn(figures, name));\n if (!known.length) return null;\n const rows = summaryRows(table, known);\n return (\n <dl className=\"form-live lines-summary\" aria-live=\"polite\">\n {rows.map(({ name, sign, live }, i) => {\n const value = live ? figures[name] : typedValue(table, name, values[name]);\n const signed = typeof value === 'number' && sign < 0 ? -value : value;\n return (\n <div key={name} className={i === rows.length - 1 ? 'lines-summary-row is-total' : 'lines-summary-row'}>\n <dt>{(columnLabel(table.id, name) as string | null) ?? humanName(name)}</dt>\n <dd>{sayFigure(ruleOf(table, name), signed ?? null, values)}</dd>\n </div>\n );\n })}\n </dl>\n );\n}\n","/**\n * A command's lines (`field.lines`), drawn with the record's lines grid\n * (FormLines.tsx): the same cells by kind, the reference with its photo and\n * second line, money in its currency, the handle a line moves by, the line's\n * computed figures beside it and their money added up under the grid. The\n * values are the form's (CommandFields.tsx), held as the grid holds them; what\n * is sent is read by the command's own reader, and the handler writes the rows.\n *\n * Loaded with the first form that asks lines, never by a public form, which\n * cannot.\n */\nimport { columnLabel, findTable } from '@mistriwork/kit/client/core.js';\nimport type { AppCommandField, AppCommandLines } from '../../shared/command.js';\nimport { lineCell } from '../../shared/commandLineCell.js';\nimport { humanName } from '@mistriwork/engine/shared/model.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { LinesEditor, type LineDraft } from './FormLines.js';\n\n/** A line's cell read as its column's kind, from the catalog the form is served (the server reads it again). */\nexport function lineCellOf(table: string, column: string, value: string | number | boolean) {\n const meta = findTable(table) as TableMeta | undefined;\n return meta ? lineCell(meta, column, value) : { value };\n}\n\n/** A grid line's cell and its words: `lines[1].quantity` → the lines field, its row and its column's caption. */\nexport function lineAt(\n fields: readonly AppCommandField[],\n path: string,\n): { field: AppCommandLines; row: number; label: string } | undefined {\n const m = /^([A-Za-z_][A-Za-z0-9_]*)\\[(\\d+)\\]\\.([A-Za-z_][A-Za-z0-9_]*)$/.exec(path);\n const field = m ? fields.find((candidate) => candidate.name === m[1]) : undefined;\n if (!m || field?.type !== 'lines') return undefined;\n const table = findTable(field.from) as TableMeta | undefined;\n return { field, row: Number(m[2]), label: (table && (columnLabel(table.id, m[3]) as string | null)) || humanName(m[3]) };\n}\n\n/** The grid's problems, `${row}.${column}`, from the form's by path (`lines[1].quantity`). */\nfunction cellProblems(path: string, problems: Readonly<Record<string, string>> | undefined): Record<string, string> {\n const prefix = `${path}[`;\n return Object.fromEntries(\n Object.entries(problems ?? {}).flatMap(([at, said]) => {\n if (!at.startsWith(prefix)) return [];\n const m = /^\\[(\\d+)\\]\\.(.+)$/.exec(at.slice(path.length));\n return m ? [[`${m[1]}.${m[2]}`, said]] : [];\n }),\n );\n}\n\nexport function CommandLines({\n field,\n path,\n rows,\n problems,\n disabled,\n onChange,\n}: {\n field: AppCommandLines;\n path: string;\n rows: readonly LineDraft[];\n problems?: Readonly<Record<string, string>>;\n disabled?: boolean;\n onChange: (rows: LineDraft[], path: string) => void;\n}) {\n const table = findTable(field.from) as TableMeta | undefined;\n /* A reader who cannot read the rows' resource is not offered its grid: the form says the input is missing when sent. */\n if (!table) return null;\n return (\n <LinesEditor\n title={field.label}\n {...(field.help ? { description: field.help } : {})}\n table={table}\n columns={field.show}\n rows={rows}\n onChange={(next) => onChange(next, path)}\n ordered\n max={field.max}\n problems={cellProblems(path, problems)}\n disabled={disabled === true}\n {...(field.copy ? { copy: field.copy } : {})}\n {...(field.query ? { where: field.query } : {})}\n subtotal\n />\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"shared-Ci16s2rN.js","names":[],"sources":["../../src/shared/commandLineCell.ts","../../src/shared/formLines.ts","../../src/client/copy/forms/components/FormLines.ts","../../src/client/components/FormLines.tsx","../../src/client/components/CommandLines.tsx"],"sourcesContent":["/*\n * A command line's cell read as its column's kind (`field.lines`): the server\n * reads every line with it where the command runs, and the browser with the\n * catalog it is served once a form's grid has loaded. Its own module, so that a\n * page with no lines grid — a public form's first page — carries none of it.\n */\nimport { isIsoDate, isoInstant } from './command.js';\nimport type { CommandInputReason } from './commandInput.js';\nimport { columnKind, isFlagColumn, type TableMeta } from '@mistriwork/engine/shared/schema.js';\n\n/**\n * A line's cell as its column holds it: a number for a number (an amount typed\n * as text included), yes or no for a flag, a day or a moment for a date, one of\n * a vocabulary's values, text for the rest. What a grid's box holds is text,\n * so text that reads as the kind is read as it.\n */\nexport function lineCell(table: TableMeta, column: string, value: string | number | boolean): { value: unknown } | CommandInputReason {\n const meta = table.columns.find((c) => c.name === column);\n if (!meta) return 'shape';\n const said = typeof value === 'string' ? value.trim() : value;\n if (isFlagColumn(meta)) {\n if (typeof said === 'boolean') return { value: said };\n if (said === 1 || said === 'true' || said === '1') return { value: true };\n if (said === 0 || said === 'false' || said === '0') return { value: false };\n return 'type';\n }\n if (meta.allowed?.length) return meta.allowed.includes(String(said)) ? { value: String(said) } : 'choice';\n const kind = columnKind(meta.type);\n if (kind === 'number') {\n const n = typeof said === 'number' ? said : typeof said === 'string' && /^-?\\d+(\\.\\d+)?$/.test(said) ? Number(said) : NaN;\n return Number.isFinite(n) ? { value: n } : 'type';\n }\n if (typeof said !== 'string') return 'type';\n if (kind === 'date') return isIsoDate(said) || isoInstant(said) !== undefined ? { value: said } : 'type';\n return { value: said };\n}\n","/**\n * A New form's child rows and the figures it says as they are typed.\n *\n * `form.lines` asks an order's lines (a bundle's items, a pay run's lines)\n * as a grid under the record's fields, and the server inserts them with the\n * record, in its transaction, each one the insert the reader could make of\n * that row alone (dataWriteRoutes.ts). `form.live` names the resource's own\n * computed columns and rollups — `subtotal: sum('order_line', 'line_total')`,\n * `total: computed.number('subtotal + shipping')` — and the form says each as\n * its fields and lines change, worked out by the one evaluator the server's\n * statement agrees with (computedValue.ts `evaluateComputed`). What the form says\n * is a preview: the record's figures are the server's, read from the rows it\n * stored, so nothing the browser works out is ever written.\n *\n * Two readers. The load judges the declarations against the catalog\n * (`formLinesProblems`); the browser works out the values (`liveValues`)\n * from the catalog it is served, where each computed column comes with its\n * constants folded and each rollup with the reference it walks.\n */\nimport type { AppDef, FormLines } from './appModel.js';\nimport { computedReads, type ComputedNode, type ComputedValue } from '@mistriwork/engine/shared/computed.js';\nimport { evaluateComputed } from '@mistriwork/engine/shared/computedValue.js';\nimport { columnKind, tableNamed, type DatabaseSchema, type TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport type { Rollup } from '@mistriwork/engine/shared/rollups.js';\nimport { typedValue } from '@mistriwork/engine/shared/formValues.js';\nexport { typedValue } from '@mistriwork/engine/shared/formValues.js';\n\n/** The child table and the column a rollup reads its rows by: `order_line.order_id` → those two, or undefined for a composite. */\nfunction viaOf(rollup: Pick<Rollup, 'via'>): { table: string; column: string } | undefined {\n const dot = rollup.via.lastIndexOf('.');\n const column = rollup.via.slice(dot + 1);\n return dot < 0 || column.includes('+') ? undefined : { table: rollup.via.slice(0, dot), column };\n}\n\n/** The one reference from `child.whose` to the parent table, if the catalog has exactly that. */\nfunction bindsTo(schema: DatabaseSchema, child: TableMeta, whose: string, parent: TableMeta): boolean {\n return (schema.foreignKeys ?? []).some(\n (fk) => fk.from.table === child.id && fk.to.table === parent.id && fk.from.columns.length === 1 && fk.from.columns[0] === whose,\n );\n}\n\n/**\n * Each resource form's `lines` and `live` against the catalog — rollups and\n * computed columns resolved on it (withRollups, withComputed) — as problems\n * naming the fix. A form whose declarations do not hold would offer a grid\n * the server refuses or a figure that never comes.\n */\nexport function formLinesProblems(app: AppDef, schema: DatabaseSchema): string[] {\n const problems: string[] = [];\n for (const [name, resource] of Object.entries(app.resources ?? {})) {\n const form = resource.form;\n if (!form?.lines && !form?.live) continue;\n const table = tableNamed(schema, name);\n if (!table) continue;\n const at = `resources \"${name}\"`;\n const lines = form.lines ?? [];\n for (const line of lines) {\n const here = `${at}: form.lines \"${line.label}\"`;\n const child = tableNamed(schema, line.from);\n if (!child || !Object.hasOwn(app.resources ?? {}, line.from)) {\n problems.push(`${here}: \"${line.from}\" is not one of this App's resources; declare it, with access: 'write'.`);\n continue;\n }\n if (app.resources![line.from].access !== 'write')\n problems.push(`${here}: the App does not write \"${line.from}\"; give it access: 'write' so its rows can be added with the record.`);\n if (!bindsTo(schema, child, line.whose, table))\n problems.push(\n `${here}: \"${line.whose}\" is not a reference from ${child.name} to ${table.name}; name the column that points at the new record.`,\n );\n for (const column of [...line.show, ...(line.order ? [line.order] : [])]) {\n const meta = child.columns.find((c) => c.name === column);\n if (!meta) problems.push(`${here}: \"${column}\" is not a column of ${child.name}.`);\n else if (meta.writable === false) problems.push(`${here}: \"${column}\" is not written by a form (the database fills it).`);\n }\n if (line.show.includes(line.whose))\n problems.push(`${here} shows \"${line.whose}\", which the server fills with the new record; leave it out.`);\n if (line.order && line.show.includes(line.order))\n problems.push(`${here} shows its order column \"${line.order}\", which the rows' places fill; leave it out of show.`);\n if (line.order && columnKind(child.columns.find((c) => c.name === line.order)?.type ?? '') !== 'number')\n problems.push(`${here}: the order column \"${line.order}\" is not a number.`);\n }\n for (const live of form.live ?? []) {\n const problem = liveProblem(table, live, lines, schema, new Set());\n if (problem) problems.push(`${at}: form.live \"${live}\" ${problem}`);\n }\n }\n return problems;\n}\n\n/** Why a name cannot be worked out live on this form, or undefined when it can. */\nfunction liveProblem(\n table: TableMeta,\n name: string,\n lines: readonly FormLines[],\n schema: DatabaseSchema,\n seen: Set<string>,\n): string | undefined {\n if (seen.has(name)) return `reads itself.`;\n seen.add(name);\n const rollup = table.rollups?.[name];\n if (rollup) {\n const via = viaOf(rollup);\n const childId = via && tableNamed(schema, via.table)?.id;\n const line = childId && lines.find((l) => tableNamed(schema, l.from)?.id === childId && l.whose === via.column);\n if (!via || !line) return `is a rollup of rows this form does not ask; add its rows to form.lines, by the reference it counts.`;\n if (rollup.of) return `rolls up another rollup, which a form's lines do not hold.`;\n if (rollup.fn === 'latest') return `reads the newest of its rows, which a form's lines have no order for until they are saved.`;\n if (rollup.filter)\n return `narrows its rows by a query; a form adds up every line it holds, so roll up a computed column of the line instead.`;\n const reads = rollup.expression ? rollup.expression.reads : rollup.column ? [rollup.column] : [];\n const missing = reads.find((column) => !line.show.includes(column) && column !== line.order);\n if (missing) return `reads \"${missing}\", which the lines \"${line.label}\" do not ask; add it to their show.`;\n return undefined;\n }\n const computed = table.computed?.[name];\n if (!computed) return `is not a computed column or a rollup of ${table.name}.`;\n for (const path of computedReads(computed.expr)) {\n if (path.includes('.')) return `reads \"${path}\" through a reference, which a form does not hold until it is saved.`;\n if (table.rollups?.[path] || table.computed?.[path]) {\n const inner = liveProblem(table, path, lines, schema, seen);\n if (inner) return `reads \"${path}\", which ${inner}`;\n } else if (!table.columns.some((c) => c.name === path)) return `reads \"${path}\", which is not a column of ${table.name}.`;\n }\n return undefined;\n}\n\n/* ---------- the values, in the browser ---------- */\n\n/** A form's draft as text, the way its inputs hold each value: stored units, an empty box as ''. */\nexport type DraftValues = Readonly<Record<string, string | null | undefined>>;\n\n/**\n * The form's live values, by name: each of `names` worked out from the\n * draft (`values`) and its lines (`rows`, keyed by the child table's id), in\n * the catalog's own reading — a computed column's folded expression, a\n * rollup's reference and column. A name the catalog does not serve this\n * reader is left out, as it would be from a list. `today` and `now` were\n * folded where the catalog was served, so a form says what a list would.\n */\nexport function liveValues(\n schema: DatabaseSchema,\n table: TableMeta,\n names: readonly string[],\n values: DraftValues,\n rows: Readonly<Record<string, readonly DraftValues[]>>,\n): Record<string, ComputedValue> {\n const clock = { today: new Date().toISOString().slice(0, 10), now: new Date(), me: null };\n const memo = new Map<string, ComputedValue>();\n const rowValue = (child: TableMeta, row: DraftValues, column: string, expression?: Pick<Rollup, 'expression'>['expression']) =>\n expression\n ? evaluateComputed(expression.expr as ComputedNode, clock, (path) => typedValue(child, path, row[path]))\n : typedValue(child, column, row[column]);\n const value = (name: string): ComputedValue => {\n if (memo.has(name)) return memo.get(name)!;\n memo.set(name, null);\n let result: ComputedValue = null;\n const rollup = table.rollups?.[name];\n const computed = table.computed?.[name];\n if (rollup) {\n const via = viaOf(rollup);\n const child = via && tableNamed(schema, via.table);\n const held = (child && rows[child.id]) ?? [];\n if (child && !rollup.of && !rollup.filter && rollup.fn !== 'latest') {\n /* As the aggregate does: a count of the rows, a sum of their values (0 where none has one), and a least or most with nothing where none has one. */\n const figures = held\n .map((row) => rowValue(child, row, rollup.column ?? '', rollup.expression))\n .filter((v): v is number => typeof v === 'number' && Number.isFinite(v));\n result =\n rollup.fn === 'count'\n ? held.length\n : rollup.fn === 'sum'\n ? figures.reduce((a, b) => a + b, 0)\n : !figures.length\n ? null\n : rollup.fn === 'min'\n ? Math.min(...figures)\n : Math.max(...figures);\n }\n } else if (computed) {\n result = evaluateComputed(computed.expr, clock, (path) =>\n table.rollups?.[path] || table.computed?.[path] ? value(path) : typedValue(table, path, values[path]),\n );\n }\n memo.set(name, result);\n return result;\n };\n return Object.fromEntries(names.filter((name) => table.rollups?.[name] || table.computed?.[name]).map((name) => [name, value(name)]));\n}\n","/** What FormLines says, in the forms room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '@mistriwork/kit/client/messages.js';\n\nexport const say = defineMessages({\n fill: 'Fill in {column}.',\n addLine: 'Add line',\n removeLine: 'Remove line',\n moveUp: 'Move up',\n moveDown: 'Move down',\n moveLine: 'Move line {n}',\n moveLineHint: 'Drag, or press Alt and an arrow key, to move this line',\n lineActions: 'Line {n} actions',\n lineActionsHeading: 'Actions',\n lineMoved: 'Line moved to place {n} of {count}.',\n noLinesYet: 'No lines yet.',\n subtotal: 'Subtotal',\n});\n","/**\n * A record's lines, edited as a grid, and the figures its form says live.\n *\n * Two places draw the grid. A New form with `form.lines` asks the record's\n * lines under its fields, and they are inserted with it (NewRecord.tsx). The\n * save is one request the server writes in one transaction\n * (server/http/formLinesWrite.ts), each row judged as its own write would be.\n * And a command's `field.lines` input asks them in its form (CommandLines.tsx),\n * for its handler to write: there a column may be copied from the record a\n * line's reference names as it is picked (a variant's price), shown and never\n * sent, and the line's money figures are added up under the grid.\n * What is checked here (a required value, an amount) only saves a round trip;\n * the server judges again.\n *\n * The grid reads as an order's lines read on paper, and becomes a form only\n * where it is touched: each cell is a box with no edge until its row is under\n * the pointer or the box has the focus. A column is laid out by its kind — a\n * reference wide, with the record's photo and its second line where the\n * referenced resource's display rule names them; a count narrow, right-aligned,\n * in tabular figures; money with its currency's sign in the box and its\n * minor-unit decimals once it is left. A computed column of the line that\n * reads only what the line holds (`amount: quantity * unit_price`) is said\n * beside it, read-only, as the line is filled in. Moving a line is a drag on\n * its handle, Alt and an arrow on the handle, or its menu; removing it is the\n * menu's. Narrower than a grid fits (a drawer, a phone), each line is a block\n * of its own: its reference across the top, its figures under it.\n *\n * `LiveValues` says the form's computed columns and rollups as it is filled\n * in, worked out by the evaluator the server's statement agrees with\n * (shared/formLines.ts), as an order's summary: the parts a total adds up,\n * each with its sign, then the total. It writes nothing: the saved record's\n * figures are the server's.\n *\n * Fetched the first time a New form has lines or live figures (appnav.js names it\n * for the kit's form: shellMode.ts `formLines`), and with a command form that asks lines.\n */\nimport { useEffect, useMemo, useRef, useState, type KeyboardEvent, type ReactNode } from 'react';\nimport { useQueries } from '@tanstack/react-query';\nimport { api, columnDisplay, columnLabel, findTable, labelPath, recordLabel, state } from '@mistriwork/kit/client/core.js';\nimport { ownedBy } from '@mistriwork/kit/client/requestIdentity.js';\nimport { defaultCurrency, formatLocale, formatMoney, formatNumber } from '@mistriwork/kit/client/locale.js';\nimport { autoKey, isRequired } from '@mistriwork/engine/shared/form.js';\nimport { liveValues, typedValue, type DraftValues } from '../../shared/formLines.js';\nimport { currencyDigits, minorFigure, rowCurrency } from '@mistriwork/engine/shared/money.js';\nimport { humanName } from '@mistriwork/engine/shared/model.js';\nimport { columnKind, primaryKey, type ColumnMeta, type DatabaseSchema, type TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { sumTerms } from './totalTerms.js';\nimport { computedReads, type ComputedValue } from '@mistriwork/engine/shared/computed.js';\nimport type { FieldError } from '@mistriwork/kit/client/fieldErrors.js';\nimport { booleanChoices } from '@mistriwork/kit/client/rowEditing.js';\nimport { ValueControl } from '@mistriwork/kit/client/components/GridCellEditor.js';\nimport { singleReference } from '@mistriwork/kit/client/components/gridCellModel.js';\nimport { columnInput } from '@mistriwork/kit/client/components/inputRenderers.js';\nimport { MinorMoneyInput, minorProblem } from '@mistriwork/kit/client/components/MinorMoneyInput.js';\nimport type { LineDraft } from '@mistriwork/kit/client/shellMode.js';\nimport { RecordPicker } from '@mistriwork/kit/client/components/RecordPicker.js';\nimport { DropItem, DropMenu } from '@mistriwork/ui/DropMenu.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { useAvatarPhotos } from '@mistriwork/kit/client/components/avatarPhotos.js';\nimport { usePointerDrag, type DropPoint } from '@mistriwork/kit/client/components/usePointerDrag.js';\nimport { dressFor, type DisplayRule } from '@mistriwork/kit/client/components/valueModel.js';\nimport { say } from '../copy/forms/components/FormLines.js';\nimport './FormLines.css';\n\n/* One row of the grid, as the kit's New form holds it (shellMode.ts): its values as the inputs hold them (stored units). */\nexport type { LineDraft };\n\nlet lastLine = 0;\nexport const blankLine = (): LineDraft => ({ id: ++lastLine, values: {} });\n\nconst ruleOf = (table: TableMeta, column: string) => columnDisplay(table.id, column) as DisplayRule | null;\nconst minorRule = (table: TableMeta, column: string) => {\n const rule = ruleOf(table, column);\n return rule?.format === 'money' && rule.minor ? rule : undefined;\n};\n\n/**\n * What is wrong with each line before the wire, keyed `${row}.${column}`: a\n * required value left empty, an amount that is not one of its currency.\n * `filled` names the columns the save fills (the reference, the place).\n */\nexport function lineProblems(\n table: TableMeta,\n columns: readonly string[],\n rows: readonly LineDraft[],\n filled: readonly string[] = [],\n): Record<string, string> {\n const problems: Record<string, string> = {};\n const assigned = autoKey(table);\n rows.forEach((row, i) => {\n for (const name of columns) {\n const column = table.columns.find((c) => c.name === name);\n if (!column || filled.includes(name)) continue;\n const value = row.values[name] ?? '';\n const rule = minorRule(table, name);\n if (value === '' && isRequired(column, assigned))\n problems[`${i}.${name}`] = say('fill', {\n column: labelOf(table, column),\n });\n else if (rule) {\n const problem = minorProblem(value, rowCurrency(rule, row.values, rule.currency || defaultCurrency()));\n if (problem) problems[`${i}.${name}`] = problem;\n }\n }\n });\n return problems;\n}\n\n/** A line's values as the save sends them: what its inputs hold, an empty box left to the database on a new row and cleared on a kept one. */\nexport function lineValues(row: LineDraft, columns: readonly string[]): Record<string, string | null> {\n const values: Record<string, string | null> = {};\n for (const name of columns) {\n const value = row.values[name];\n if (value === undefined || (value === '' && !row.key)) continue;\n values[name] = value === '' ? null : value;\n }\n return values;\n}\n\n/** The server's word on a line's field, which it says as `order_line[2].quantity` (recordWriteOperations.ts). */\nexport function lineServerProblems(table: TableMeta, errors: readonly FieldError[]): Record<string, string> {\n const prefix = `${table.name}[`;\n return Object.fromEntries(\n errors.flatMap((error) => {\n if (!error.field.startsWith(prefix)) return [];\n const m = /^\\[(\\d+)\\]\\.(.+)$/.exec(error.field.slice(table.name.length));\n return m ? [[`${m[1]}.${m[2]}`, error.message]] : [];\n }),\n );\n}\n\nfunction labelOf(table: TableMeta, column: ColumnMeta): string {\n return (columnLabel(table.id, column.name) as string | null) ?? humanName(column.name);\n}\n\n/** The sign a currency is written with here: \"$\", \"€\", \"CHF\". */\nexport function currencySymbol(currency: string): string {\n try {\n return (\n new Intl.NumberFormat(formatLocale(), { style: 'currency', currency }).formatToParts(0).find((part) => part.type === 'currency')\n ?.value ?? currency\n );\n } catch {\n return currency;\n }\n}\n\n/* ---------- columns by kind ---------- */\n\n/**\n * How a line's column is drawn. The App's own input for it (`inputs`), a\n * vocabulary and a date keep the control a cell edits with (GridCellEditor's\n * `ValueControl`); a reference, money, a number and text are the grid's own\n * cells, which read as a table until touched.\n */\ntype CellKind = 'reference' | 'money' | 'number' | 'text' | 'control';\n\nfunction cellKind(table: TableMeta, column: ColumnMeta): CellKind {\n if (columnInput(table.id, column.name)) return 'control';\n if (column.references && singleReference(table, column) && findTable(column.references.table)) return 'reference';\n if (column.allowed?.length || booleanChoices(column, null)) return 'control';\n const kind = columnKind(column.type);\n if (kind === 'date') return 'control';\n if (ruleOf(table, column.name)?.format === 'money') return 'money';\n return kind === 'number' ? 'number' : 'text';\n}\n\n/**\n * The line's own figures: each computed column that reads nothing but the\n * line's plain columns (`quantity * unit_price`), worked out as it is typed.\n * One that reads through a reference or a rollup waits for the saved row.\n */\nfunction lineFigures(table: TableMeta, shown: readonly string[]): string[] {\n return Object.entries(table.computed ?? {})\n .filter(([name, computed]) => {\n if (shown.includes(name)) return false;\n const reads = computedReads(computed.expr);\n return reads.length > 0 && reads.every((path) => !path.includes('.') && table.columns.some((c) => c.name === path));\n })\n .map(([name]) => name);\n}\n\n/**\n * A computed figure's dress: its own rule, else — an amount worked out of one\n * money column, `quantity * unit_price` — that column's, so a line's amount\n * is money in the same units and currency as the price it was made of.\n */\nfunction figureRule(table: TableMeta, name: string): DisplayRule | null {\n const own = ruleOf(table, name);\n if (own || !table.computed?.[name]) return own;\n const money = computedReads(table.computed[name].expr).filter((path) => ruleOf(table, path)?.format === 'money');\n return money.length === 1 ? ruleOf(table, money[0]) : null;\n}\n\n/** A live figure in its column's dress: money as money, minor units in their currency, a count as a number. */\nfunction sayFigure(rule: DisplayRule | null, value: ComputedValue, draft: DraftValues): string {\n if (value === null) return '—';\n if (typeof value === 'object') return 'day' in value ? value.day : value.instant.toISOString();\n const shaped = rule?.currencyColumn\n ? {\n ...rule,\n currency: rowCurrency(rule, draft, rule.currency ?? '') || undefined,\n }\n : rule;\n const dress = typeof value === 'number' ? dressFor(shaped, value) : null;\n /* Beside the money typed in this grid, which keeps its cents, a figure keeps them too: a line of 2 × $38.00 is\n $76.00, not the \"$76\" a whole number says elsewhere (formatMoney), which read as rounded next to its price.\n A part taken off a total is said with the minus sign, not a hyphen. */\n if (dress && 'text' in dress && typeof dress.text === 'string' && dress.kind === 'money') {\n const currency = shaped?.currency || defaultCurrency();\n const major = Number(shaped?.minor ? (minorFigure(value as number, currency) ?? value) : value);\n const digits = currencyDigits(currency);\n const said = Number.isFinite(major)\n ? formatMoney(major, currency, { minimumFractionDigits: digits, maximumFractionDigits: digits })\n : dress.text;\n return said.replace(/^-/, '−');\n }\n if (typeof value === 'number') return formatNumber(value);\n return typeof value === 'boolean' ? (value ? say('common.yes') : say('common.no')) : value;\n}\n\n/** Figures worked out of one row, by the evaluator the server agrees with; nothing where the catalog has changed under it. */\nfunction figuresOf(schema: DatabaseSchema | null, table: TableMeta, names: readonly string[], values: DraftValues, lines = {}) {\n if (!schema || !names.length) return {} as Record<string, ComputedValue>;\n try {\n return liveValues(schema, table, names, values, lines);\n } catch {\n return {} as Record<string, ComputedValue>;\n }\n}\n\n/* ---------- a reference, with its record's photo and second line ---------- */\n\ntype Photo = Exclude<NonNullable<DisplayRule['avatar']>, boolean>;\n\n/** What a reference cell draws of the record it names, beside the name: from the referenced resource's own display rule. */\ninterface Face {\n column: string;\n target: TableMeta;\n valueColumn: string;\n key: string;\n /** The record's column holding the key its photo is of: its own key, or the reference it is named through. */\n owner: string;\n subtitle?: string;\n photo?: Photo;\n}\n\nfunction faceOf(column: ColumnMeta): Face | undefined {\n const target = column.references ? (findTable(column.references.table) as TableMeta | undefined) : undefined;\n const key = target ? primaryKey(target) : [];\n /* The column the record is named by: its label path, or a label template's first column (`{title} · {sku}`). */\n const path = target ? (labelPath(target) as string | undefined) : undefined;\n const naming = path && !path.startsWith('$') ? path : /\\{([^}]+)\\}/.exec(String((target && recordLabel(target)) ?? ''))?.[1];\n if (!target || key.length !== 1 || !naming) return undefined;\n const [own, far, more] = naming.split('.');\n if (more !== undefined) return undefined;\n const second = (rule: DisplayRule | null) =>\n typeof rule?.subtitle === 'string' ? target.columns.find((c) => c.name === rule.subtitle && !c.references) : undefined;\n const photoOf = (rule: DisplayRule | null) => (rule?.avatar && typeof rule.avatar === 'object' ? rule.avatar : undefined);\n let face: Pick<Face, 'owner' | 'subtitle' | 'photo'>;\n if (far === undefined) {\n const rule = ruleOf(target, own);\n const sub = second(rule);\n const photo = photoOf(rule);\n face = { owner: key[0], ...(sub ? { subtitle: sub.name } : {}), ...(photo ? { photo } : {}) };\n } else {\n /* Named through a reference (a variant as `{product_id.title} · {color} / {size}`): the photo is the record\n it names, by that column's own rule there, owned through the reference; the second line is the rule on\n the reference itself, a column of this record (`product_id: { subtitle: 'sku' }`). */\n const via = target.columns.find((c) => c.name === own && c.references);\n const named = via ? (findTable(via.references!.table) as TableMeta | undefined) : undefined;\n if (!via || !named || via.references!.column !== primaryKey(named)[0]) return undefined;\n const sub = second(ruleOf(target, own));\n const photo = photoOf(ruleOf(named, far));\n face = { owner: own, ...(sub ? { subtitle: sub.name } : {}), ...(photo ? { photo } : {}) };\n }\n if (!face.subtitle && !face.photo) return undefined;\n return { column: column.name, target, valueColumn: column.references!.column, key: key[0], ...face };\n}\n\nconst said = (value: unknown) => (value === null || value === undefined ? '' : String(value));\n\n/** A record's photo in its square, or the square alone: the cell keeps its size whether the picture has come or not. */\nfunction Thumb({ src }: { src?: string }) {\n return <span className=\"lines-thumb\">{src ? <img src={src} alt=\"\" loading=\"lazy\" decoding=\"async\" /> : null}</span>;\n}\n\n/** One choice in a reference cell's list: its photo, its name and its second line. */\nfunction FaceOption({\n face,\n row,\n label,\n rows,\n}: {\n face: Face;\n row: Record<string, unknown>;\n label: string;\n rows: readonly Record<string, unknown>[];\n}) {\n /* Every choice asks with the same rows, so the list's photos are one question. */\n const photos = useAvatarPhotos(\n face.photo\n ? [\n {\n name: 'choice',\n display: { avatar: face.photo },\n photoOwner: face.owner,\n },\n ]\n : [],\n rows,\n );\n return (\n <span className=\"lines-choice\">\n {face.photo && <Thumb src={photos('choice', row[face.owner])} />}\n <span className=\"lines-choice-text\">\n <span className=\"picker-option-label\">{label}</span>\n {face.subtitle && <span className=\"lines-ref-sub\">{said(row[face.subtitle])}</span>}\n </span>\n </span>\n );\n}\n\n/** The chosen records of every reference column with a face, one question per column, and their photos. */\nfunction useFaces(faces: readonly Face[], rows: readonly LineDraft[]) {\n const connection = state.activeConnection;\n const asked = faces.map((face) => [...new Set(rows.map((row) => row.values[face.column]).filter(Boolean))].sort());\n const answers = useQueries({\n queries: faces.map((face, i) => ({\n queryKey: ['lines-faces', connection, face.target.id, face.valueColumn, face.owner, face.subtitle, asked[i]],\n enabled: asked[i].length > 0,\n staleTime: 60_000,\n placeholderData: (previous: Record<string, unknown>[] | undefined) => previous,\n queryFn: async () => {\n const data = (await api('/api/query', {\n ...ownedBy(connection),\n table: face.target.id,\n columns: [...new Set([face.key, face.owner, face.valueColumn, ...(face.subtitle ? [face.subtitle] : [])])],\n filter: {\n groups: [\n [\n {\n column: face.valueColumn,\n op: 'in' as const,\n value: asked[i],\n },\n ],\n ],\n },\n limit: asked[i].length,\n offset: 0,\n })) as { rows?: Record<string, unknown>[] };\n return data.rows ?? [];\n },\n })),\n });\n const owners = faces.flatMap((face, i) =>\n face.photo ? (answers[i]?.data ?? []).map((row) => ({ [face.column]: row[face.owner] }) as Record<string, unknown>) : [],\n );\n const photos = useAvatarPhotos(\n faces.flatMap((face) =>\n face.photo\n ? [\n {\n name: face.column,\n display: { avatar: face.photo },\n photoOwner: face.column,\n },\n ]\n : [],\n ),\n owners,\n );\n return (column: string, value: string): { photo?: string; subtitle?: string } => {\n const i = faces.findIndex((face) => face.column === column);\n if (i < 0 || !value) return {};\n const row = answers[i]?.data?.find((each) => said(each[faces[i].valueColumn]) === value);\n return {\n photo: row ? photos(column, row[faces[i].owner]) : undefined,\n subtitle: row && faces[i].subtitle ? said(row[faces[i].subtitle!]) : '',\n };\n };\n}\n\n/* ---------- columns copied from the record a reference names ---------- */\n\n/**\n * A command's `copy`: each copied column of a line filled from the record its\n * reference names (`unit_price_amount` ← `variant_id.price_amount`), asked once\n * per reference column for every record the lines name. A line whose reference\n * is empty, or names a record not yet read, holds nothing there.\n */\nfunction useCopies(\n table: TableMeta,\n copy: Readonly<Record<string, string>>,\n rows: readonly LineDraft[],\n onChange: (rows: LineDraft[]) => void,\n) {\n const connection = state.activeConnection;\n const vias = [...new Set(Object.values(copy).map((path) => path.split('.')[0]))].flatMap((via) => {\n const reference = table.columns.find((c) => c.name === via)?.references;\n const target = reference ? (findTable(reference.table) as TableMeta | undefined) : undefined;\n if (!reference || !target) return [];\n const reads = Object.entries(copy)\n .filter(([, path]) => path.split('.')[0] === via)\n .map(([column, path]) => ({ column, read: path.split('.')[1] }));\n const asked = [...new Set(rows.map((row) => row.values[via]).filter(Boolean))].sort();\n return [{ via, target, valueColumn: reference.column, reads, asked }];\n });\n const answers = useQueries({\n queries: vias.map((each) => ({\n queryKey: ['lines-copies', connection, each.target.id, each.valueColumn, each.reads.map((r) => r.read), each.asked],\n enabled: each.asked.length > 0,\n staleTime: 60_000,\n placeholderData: (previous: Record<string, unknown>[] | undefined) => previous,\n queryFn: async () => {\n const data = (await api('/api/query', {\n ...ownedBy(connection),\n table: each.target.id,\n columns: [...new Set([each.valueColumn, ...each.reads.map((r) => r.read)])],\n filter: { groups: [[{ column: each.valueColumn, op: 'in' as const, value: each.asked }]] },\n limit: each.asked.length,\n offset: 0,\n })) as { rows?: Record<string, unknown>[] };\n return data.rows ?? [];\n },\n })),\n });\n const read = vias.map((_, i) => answers[i]?.data);\n useEffect(() => {\n let changed = false;\n const next = rows.map((row) => {\n const values = { ...row.values };\n vias.forEach((each, i) => {\n const record = read[i]?.find((candidate) => said(candidate[each.valueColumn]) === (row.values[each.via] ?? ''));\n for (const { column, read: from } of each.reads) {\n const value = record ? said(record[from]) : '';\n if ((values[column] ?? '') !== value) {\n values[column] = value;\n changed = true;\n }\n }\n });\n return { ...row, values };\n });\n if (changed) onChange(next);\n });\n}\n\n/* ---------- money ---------- */\n\n/** An amount as the cell shows it once left: in its currency, with its decimals; text that is no amount stays as typed. */\nfunction shownMoney(text: string, digits: number, currency: string): string {\n if (!/^-?\\d+(\\.\\d*)?$/.test(text.trim())) return text;\n const [, decimals = ''] = text.trim().split('.');\n return decimals.length > digits\n ? text\n : formatMoney(Number(text), currency, { minimumFractionDigits: digits, maximumFractionDigits: digits });\n}\n\nfunction MoneyCell({\n value,\n currency,\n minor,\n onChange,\n input,\n}: {\n value: string;\n currency: string;\n minor: boolean;\n onChange: (value: string) => void;\n input: {\n 'aria-label': string;\n 'aria-invalid'?: true;\n 'aria-describedby'?: string;\n };\n}) {\n const [focused, setFocused] = useState(false);\n const digits = currencyDigits(currency);\n /* At rest the figure reads as the amount column's do, \"$148.00\"; in the box the sign stands before what is typed. */\n const box = (text: string, typed: (next: string) => void) => (\n <span className=\"lines-box lines-money\">\n {focused && (\n <span className=\"lines-affix\" aria-hidden=\"true\">\n {currencySymbol(currency)}\n </span>\n )}\n <input\n type=\"text\"\n inputMode=\"decimal\"\n className=\"lines-input is-figure\"\n autoComplete=\"off\"\n {...input}\n value={focused ? text : shownMoney(text, digits, currency)}\n onFocus={() => setFocused(true)}\n onBlur={() => setFocused(false)}\n onChange={(event) => typed(event.target.value)}\n />\n </span>\n );\n return minor ? (\n <MinorMoneyInput value={value} currency={currency} onChange={onChange}>\n {box}\n </MinorMoneyInput>\n ) : (\n box(value, onChange)\n );\n}\n\n/* ---------- the grid ---------- */\n\n/** Six dots: what a line is lifted by. */\nfunction Grip() {\n return (\n <svg width=\"8\" height=\"14\" viewBox=\"0 0 8 14\" aria-hidden=\"true\" focusable=\"false\">\n {[2, 7, 12].flatMap((y) => [1.5, 6.5].map((x) => <circle key={`${x}-${y}`} cx={x} cy={y} r=\"1.3\" fill=\"currentColor\" />))}\n </svg>\n );\n}\n\nexport function LinesEditor({\n title,\n table,\n columns,\n rows,\n onChange,\n ordered = false,\n max = 64,\n problems = {},\n disabled = false,\n titleShown = true,\n summary,\n description,\n copy,\n where,\n subtotal = false,\n}: {\n title: string;\n /** A line under the title: what the lines are for, or what happens to them. */\n description?: string;\n /** Columns of the line filled from the record a reference names, shown read-only and never typed (`useCopies`). */\n copy?: Readonly<Record<string, string>>;\n /** A reference column → the rows its picker offers (a command's `query`): a variant for sale, not every variant. */\n where?: Readonly<Record<string, string>>;\n /** Where no `summary` is given, the line's money figures added up under the grid. */\n subtotal?: boolean;\n /** False where a section's own heading already says it: the legend is then for assistive technology alone. */\n titleShown?: boolean;\n table: TableMeta;\n columns: readonly string[];\n rows: readonly LineDraft[];\n onChange: (rows: LineDraft[]) => void;\n /** The rows' places are kept (`order`): each can move up and down. */\n ordered?: boolean;\n max?: number;\n /** What is wrong, by `${row}.${column}`: the form's own checks, then the server's. */\n problems?: Record<string, string>;\n disabled?: boolean;\n /** The figures the lines add up to, beside Add line, their values under the amounts (`LiveValues`). */\n summary?: ReactNode;\n}) {\n const shown = columns.map((name) => table.columns.find((c) => c.name === name)).filter((c): c is ColumnMeta => Boolean(c));\n const kinds = shown.map((column) => cellKind(table, column));\n const copied = Object.keys(copy ?? {}).filter((name) => table.columns.some((c) => c.name === name));\n const figures = useMemo(() => lineFigures(table, [...columns, ...copied]), [table, columns, copied.join()]);\n useCopies(table, copy ?? {}, rows, onChange);\n const figured = rows.map((row) => figuresOf(state.schema as DatabaseSchema | null, table, figures, row.values));\n /* The money a line works out, added up: an order's subtotal, said as the line's own figures are. */\n const sums = subtotal && !summary ? figures.filter((name) => figureRule(table, name)?.format === 'money') : [];\n const faces = shown.flatMap((column, i) => (kinds[i] === 'reference' ? (faceOf(column) ?? []) : []));\n const faceFor = useFaces(faces, rows);\n const added = useRef<number | null>(null);\n /* After a move the focus stays on what moved it: the handle, or the menu's button. */\n const refocus = useRef<{ line: number; what: string } | null>(null);\n const body = useRef<HTMLTableSectionElement>(null);\n const [moved, setMoved] = useState('');\n const [dropAt, setDropAt] = useState<{\n line: number;\n side: 'before' | 'after';\n } | null>(null);\n /* A new line takes the focus in its first box, so a keyboard adds lines as fast as it types them. */\n useEffect(() => {\n if (added.current !== null) {\n body.current?.querySelector<HTMLElement>(`tr[data-line=\"${added.current}\"] input`)?.focus();\n added.current = null;\n }\n if (refocus.current) {\n body.current?.querySelector<HTMLElement>(`tr[data-line=\"${refocus.current.line}\"] ${refocus.current.what}`)?.focus();\n refocus.current = null;\n }\n });\n const set = (i: number, name: string, value: string | null) =>\n onChange(rows.map((row, at) => (at === i ? { ...row, values: { ...row.values, [name]: value ?? '' } } : row)));\n const place = (from: number, to: number, focus?: string) => {\n if (to < 0 || to >= rows.length || to === from) return;\n const next = [...rows];\n const [line] = next.splice(from, 1);\n next.splice(to, 0, line);\n if (focus) refocus.current = { line: line.id, what: focus };\n setMoved(say('lineMoved', { n: to + 1, count: rows.length }));\n onChange(next);\n };\n const remove = (i: number) => {\n const next = rows.filter((_, at) => at !== i);\n /* The focus goes to the line that took its place, else the one above, else Add line. */\n const heir = next[Math.min(i, next.length - 1)];\n if (heir) refocus.current = { line: heir.id, what: '.row-actions-trigger' };\n onChange(next);\n };\n const drag = usePointerDrag<number>({\n over: (line, at) => setDropAt(dropOf(line, at)),\n drop: (line, at) => {\n const target = dropOf(line, at);\n const from = rows.findIndex((row) => row.id === line);\n if (!target || from < 0) return;\n let to = rows.findIndex((row) => row.id === target.line) + (target.side === 'after' ? 1 : 0);\n if (to > from) to -= 1;\n place(from, to, '.lines-grip');\n },\n end: () => setDropAt(null),\n items: 'tr[data-line]',\n });\n /* Where a line let go over `at` lands: before or after the row under it, never beside itself. */\n const dropOf = (line: number, at: DropPoint | null): { line: number; side: 'before' | 'after' } | null => {\n if (!at) return null;\n const under = at.item ? Number(at.item.dataset.line) : rows[rows.length - 1]?.id;\n if (under === undefined || under === line) return null;\n return { line: under, side: at.item && at.upper ? 'before' : 'after' };\n };\n const gripKeys = (event: KeyboardEvent, i: number) => {\n const by = event.key === 'ArrowUp' ? -1 : event.key === 'ArrowDown' ? 1 : 0;\n if (!by || event.ctrlKey || event.metaKey || event.shiftKey) return;\n event.preventDefault();\n place(i, i + by, '.lines-grip');\n };\n const currencyOf = (column: ColumnMeta, row: LineDraft) => {\n const rule = ruleOf(table, column.name);\n return rowCurrency(rule ?? {}, row.values, rule?.currency || defaultCurrency());\n };\n const columnClass = (kind: CellKind) => `is-${kind}`;\n const span = shown.length + copied.length + figures.length + (ordered ? 1 : 0) + 1;\n const copiedLabel = (name: string) => (columnLabel(table.id, name) as string | null) ?? humanName(name);\n return (\n <fieldset className=\"form-lines\" disabled={disabled}>\n <legend className={titleShown ? undefined : 'visually-hidden'}>{title}</legend>\n {description && <p className=\"form-lines-description\">{description}</p>}\n <div className=\"form-lines-body\">\n <table className={`form-lines-grid${ordered ? ' is-ordered' : ''}`}>\n <colgroup>\n {ordered && <col className=\"lines-col-grip\" />}\n {shown.map((column, i) => (\n <col key={column.name} className={`lines-col-${kinds[i]}`} />\n ))}\n {copied.map((name) => (\n <col key={name} className=\"lines-col-figure\" />\n ))}\n {figures.map((name) => (\n <col key={name} className=\"lines-col-figure\" />\n ))}\n <col className=\"lines-col-menu\" />\n </colgroup>\n <thead>\n <tr>\n {ordered && <th aria-hidden=\"true\" />}\n {shown.map((column, i) => (\n <th key={column.name} scope=\"col\" className={columnClass(kinds[i])}>\n {labelOf(table, column)}\n </th>\n ))}\n {copied.map((name) => (\n <th key={name} scope=\"col\" className=\"is-figure\">\n {copiedLabel(name)}\n </th>\n ))}\n {figures.map((name) => (\n <th key={name} scope=\"col\" className=\"is-figure\">\n {(columnLabel(table.id, name) as string | null) ?? humanName(name)}\n </th>\n ))}\n <th>\n <span className=\"visually-hidden\">{say('lineActionsHeading')}</span>\n </th>\n </tr>\n </thead>\n <tbody ref={body} data-drop-zone=\"\">\n {rows.map((row, i) => {\n const n = i + 1;\n return (\n <tr\n key={row.id}\n data-line={row.id}\n {...(dropAt?.line === row.id ? { 'data-drop': dropAt.side } : {})}\n {...(drag.dragging === row.id ? { 'data-lifted': '' } : {})}\n >\n {ordered && (\n <td className=\"lines-handle\">\n <button\n type=\"button\"\n className=\"lines-grip\"\n aria-label={say('moveLine', { n })}\n aria-keyshortcuts=\"Alt+ArrowUp Alt+ArrowDown\"\n title={say('moveLineHint')}\n onPointerDown={(event) => {\n const line = event.currentTarget.closest('tr');\n if (line) drag.start(event, row.id, line);\n }}\n onKeyDown={(event) => gripKeys(event, i)}\n >\n <Grip />\n </button>\n </td>\n )}\n {shown.map((column, at) => {\n const kind = kinds[at];\n const problem = problems[`${i}.${column.name}`];\n const errorId = problem ? `line-${row.id}-${column.name}-error` : undefined;\n const label = `${labelOf(table, column)}, ${n}`;\n const value = row.values[column.name] ?? '';\n const input = {\n 'aria-label': label,\n ...(problem\n ? {\n 'aria-invalid': true as const,\n 'aria-describedby': errorId,\n }\n : {}),\n };\n let cell: ReactNode;\n if (kind === 'reference') {\n const face = faces.find((each) => each.column === column.name);\n const target = findTable(column.references!.table) as TableMeta;\n const known = face ? faceFor(column.name, value) : {};\n cell = (\n <span className={`lines-box lines-ref${face?.photo ? ' has-thumb' : ''}${face?.subtitle ? ' has-sub' : ''}`}>\n {face?.photo && <Thumb src={known.photo} />}\n <span className=\"lines-ref-text\">\n <RecordPicker\n table={target}\n valueColumn={column.references!.column}\n value={value}\n onChange={(next) => set(i, column.name, next)}\n ariaLabel={label}\n invalid={input['aria-invalid'] === true}\n {...(input['aria-describedby'] ? { describedBy: input['aria-describedby'] } : {})}\n app\n hideKey={Boolean(face)}\n {...(where?.[column.name] ? { where: where[column.name] } : {})}\n editing={{ onStateChange: () => {} }}\n {...(face\n ? {\n face: {\n columns: [...new Set([face.key, face.owner, ...(face.subtitle ? [face.subtitle] : [])])],\n draw: (choice, name, all) => <FaceOption face={face} row={choice} label={name} rows={all} />,\n },\n }\n : {})}\n />\n {face?.subtitle && <span className=\"lines-ref-sub\">{known.subtitle}</span>}\n </span>\n </span>\n );\n } else if (kind === 'money') {\n cell = (\n <MoneyCell\n value={value}\n currency={currencyOf(column, row)}\n minor={Boolean(minorRule(table, column.name))}\n onChange={(next) => set(i, column.name, next)}\n input={input}\n />\n );\n } else if (kind === 'number' || kind === 'text') {\n cell = (\n <span className=\"lines-box\">\n <input\n type=\"text\"\n className={`lines-input${kind === 'number' ? ' is-figure' : ''}`}\n autoComplete=\"off\"\n {...(kind === 'number' ? { inputMode: 'decimal' as const } : {})}\n {...input}\n value={value}\n onChange={(event) => set(i, column.name, event.target.value)}\n />\n </span>\n );\n } else {\n cell = (\n <span className=\"lines-box lines-control\">\n <ValueControl\n table={table}\n column={column}\n value={value}\n onChange={(next) => set(i, column.name, next)}\n label={label}\n row={row.values}\n invalid={Boolean(problem)}\n describedBy={errorId}\n />\n </span>\n );\n }\n return (\n <td\n key={column.name}\n className={`${columnClass(kind)}${at === 0 ? ' lines-lead' : ''}${problem ? ' is-invalid' : ''}`}\n data-label={labelOf(table, column)}\n >\n {cell}\n {problem && (\n <span id={errorId} className=\"insert-missing\">\n {problem}\n </span>\n )}\n </td>\n );\n })}\n {copied.map((name) => (\n <td key={name} className=\"is-figure lines-figure lines-copied\" data-label={copiedLabel(name)}>\n {sayFigure(ruleOf(table, name), typedValue(table, name, row.values[name]), row.values)}\n </td>\n ))}\n {figures.map((name) => (\n <td\n key={name}\n className=\"is-figure lines-figure\"\n data-label={(columnLabel(table.id, name) as string | null) ?? humanName(name)}\n >\n {sayFigure(figureRule(table, name), figured[i][name] ?? null, row.values)}\n </td>\n ))}\n <td className=\"lines-menu\">\n <DropMenu\n className=\"row-actions-menu\"\n triggerClassName=\"ghost row-actions-trigger\"\n triggerLabel={say('lineActions', { n })}\n triggerTitle={say('lineActions', { n })}\n label=\"⋯\"\n popupClassName=\"page-actions-popup\"\n align=\"end\"\n >\n {ordered && (\n <DropItem className=\"page-actions-item\" disabled={i === 0} onClick={() => place(i, i - 1, '.row-actions-trigger')}>\n {say('moveUp')}\n </DropItem>\n )}\n {ordered && (\n <DropItem\n className=\"page-actions-item\"\n disabled={i === rows.length - 1}\n onClick={() => place(i, i + 1, '.row-actions-trigger')}\n >\n {say('moveDown')}\n </DropItem>\n )}\n <DropItem className=\"page-actions-item is-danger\" onClick={() => remove(i)}>\n {say('removeLine')}\n </DropItem>\n </DropMenu>\n </td>\n </tr>\n );\n })}\n {!rows.length && (\n <tr className=\"lines-empty\">\n <td colSpan={span}>{say('noLinesYet')}</td>\n </tr>\n )}\n </tbody>\n </table>\n <div className=\"form-lines-foot\">\n <Button\n intent=\"quiet\"\n size=\"compact\"\n className=\"lines-add\"\n disabled={rows.length >= max}\n onClick={() => {\n const line = blankLine();\n added.current = line.id;\n onChange([...rows, line]);\n }}\n >\n + {say('addLine')}\n </Button>\n {summary}\n {sums.length > 0 && (\n <dl className=\"form-live lines-summary\" aria-live=\"polite\">\n {sums.map((name) => {\n const amounts = figured.map((each) => each[name]).filter((v): v is number => typeof v === 'number');\n const total = amounts.length ? amounts.reduce((a, b) => a + b, 0) : null;\n return (\n <div key={name} className=\"lines-summary-row\">\n <dt>{sums.length === 1 ? say('subtotal') : copiedLabel(name)}</dt>\n <dd>{sayFigure(figureRule(table, name), total, rows[0]?.values ?? {})}</dd>\n </div>\n );\n })}\n </dl>\n )}\n </div>\n <div className=\"visually-hidden\" aria-live=\"polite\">\n {moved}\n </div>\n </div>\n </fieldset>\n );\n}\n\n/* ---------- the summary ---------- */\n\n/** The summary's rows: the live names, and where the last is a sum, the record's own columns it adds, in its order. */\nfunction summaryRows(table: TableMeta, names: readonly string[]): Array<{ name: string; sign: number; live: boolean }> {\n const total = names[names.length - 1];\n const terms = total && table.computed?.[total] ? sumTerms(table.computed[total].expr) : undefined;\n const live = (name: string) => names.includes(name);\n const parts =\n terms\n ?.filter(\n (term) => live(term.path) || (ruleOf(table, term.path)?.format === 'money' && table.columns.some((c) => c.name === term.path)),\n )\n .map((term) => ({\n name: term.path,\n sign: term.sign,\n live: live(term.path),\n })) ?? [];\n const before = names.slice(0, -1).filter((name) => !parts.some((part) => part.name === name));\n return [\n ...before.map((name) => ({ name, sign: 1, live: true })),\n ...parts.filter((part) => part.name !== total),\n ...(total ? [{ name: total, sign: 1, live: true }] : []),\n ];\n}\n\n/** The form's `live` figures, worked out from its draft and lines as they change: an order's summary, its total last. */\nexport function LiveValues({\n table,\n names,\n values,\n lines,\n}: {\n table: TableMeta;\n names: readonly string[];\n values: DraftValues;\n /** Each collection's rows, by the child table's id. */\n lines: Readonly<Record<string, readonly LineDraft[]>>;\n}) {\n const figures = useMemo(() => {\n const rows = Object.fromEntries(Object.entries(lines).map(([id, held]) => [id, held.map((row) => row.values)]));\n /* A catalog that changed under the form says nothing rather than something wrong. */\n return figuresOf(state.schema as DatabaseSchema | null, table, names, values, rows);\n }, [table, names, values, lines]);\n const known = names.filter((name) => Object.hasOwn(figures, name));\n if (!known.length) return null;\n const rows = summaryRows(table, known);\n return (\n <dl className=\"form-live lines-summary\" aria-live=\"polite\">\n {rows.map(({ name, sign, live }, i) => {\n const value = live ? figures[name] : typedValue(table, name, values[name]);\n const signed = typeof value === 'number' && sign < 0 ? -value : value;\n return (\n <div key={name} className={i === rows.length - 1 ? 'lines-summary-row is-total' : 'lines-summary-row'}>\n <dt>{(columnLabel(table.id, name) as string | null) ?? humanName(name)}</dt>\n <dd>{sayFigure(ruleOf(table, name), signed ?? null, values)}</dd>\n </div>\n );\n })}\n </dl>\n );\n}\n","/**\n * A command's lines (`field.lines`), drawn with the record's lines grid\n * (FormLines.tsx): the same cells by kind, the reference with its photo and\n * second line, money in its currency, the handle a line moves by, the line's\n * computed figures beside it and their money added up under the grid. The\n * values are the form's (CommandFields.tsx), held as the grid holds them; what\n * is sent is read by the command's own reader, and the handler writes the rows.\n *\n * Loaded with the first form that asks lines, never by a public form, which\n * cannot.\n */\nimport { columnLabel, findTable } from '@mistriwork/kit/client/core.js';\nimport type { AppCommandField, AppCommandLines } from '../../shared/command.js';\nimport { lineCell } from '../../shared/commandLineCell.js';\nimport { humanName } from '@mistriwork/engine/shared/model.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { LinesEditor, type LineDraft } from './FormLines.js';\n\n/** A line's cell read as its column's kind, from the catalog the form is served (the server reads it again). */\nexport function lineCellOf(table: string, column: string, value: string | number | boolean) {\n const meta = findTable(table) as TableMeta | undefined;\n return meta ? lineCell(meta, column, value) : { value };\n}\n\n/** A grid line's cell and its words: `lines[1].quantity` → the lines field, its row and its column's caption. */\nexport function lineAt(\n fields: readonly AppCommandField[],\n path: string,\n): { field: AppCommandLines; row: number; label: string } | undefined {\n const m = /^([A-Za-z_][A-Za-z0-9_]*)\\[(\\d+)\\]\\.([A-Za-z_][A-Za-z0-9_]*)$/.exec(path);\n const field = m ? fields.find((candidate) => candidate.name === m[1]) : undefined;\n if (!m || field?.type !== 'lines') return undefined;\n const table = findTable(field.from) as TableMeta | undefined;\n return { field, row: Number(m[2]), label: (table && (columnLabel(table.id, m[3]) as string | null)) || humanName(m[3]) };\n}\n\n/** The grid's problems, `${row}.${column}`, from the form's by path (`lines[1].quantity`). */\nfunction cellProblems(path: string, problems: Readonly<Record<string, string>> | undefined): Record<string, string> {\n const prefix = `${path}[`;\n return Object.fromEntries(\n Object.entries(problems ?? {}).flatMap(([at, said]) => {\n if (!at.startsWith(prefix)) return [];\n const m = /^\\[(\\d+)\\]\\.(.+)$/.exec(at.slice(path.length));\n return m ? [[`${m[1]}.${m[2]}`, said]] : [];\n }),\n );\n}\n\nexport function CommandLines({\n field,\n path,\n rows,\n problems,\n disabled,\n onChange,\n}: {\n field: AppCommandLines;\n path: string;\n rows: readonly LineDraft[];\n problems?: Readonly<Record<string, string>>;\n disabled?: boolean;\n onChange: (rows: LineDraft[], path: string) => void;\n}) {\n const table = findTable(field.from) as TableMeta | undefined;\n /* A reader who cannot read the rows' resource is not offered its grid: the form says the input is missing when sent. */\n if (!table) return null;\n return (\n <LinesEditor\n title={field.label}\n {...(field.help ? { description: field.help } : {})}\n table={table}\n columns={field.show}\n rows={rows}\n onChange={(next) => onChange(next, path)}\n ordered\n max={field.max}\n problems={cellProblems(path, problems)}\n disabled={disabled === true}\n {...(field.copy ? { copy: field.copy } : {})}\n {...(field.query ? { where: field.query } : {})}\n subtotal\n />\n );\n}\n"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import "./shared-poc11xxo.js";
2
2
  import { gt as defineMessages } from "./shared-DJZjSi3J.js";
3
- import "./shared-CNmaAv64.js";
4
- import { L as state } from "./shared-DPAVoWY0.js";
3
+ import "./shared-BHsjawAG.js";
4
+ import { L as state } from "./shared-BoLbc2WD.js";
5
5
  import "./shared-DOvMIC4W.js";
6
6
  import "./shared-DUlM0U0V.js";
7
7
  import { m as viewOrder, t as ASSISTANT_PAGE } from "./shared-DpVb48sM.js";
8
- import { t as activeApp } from "./shared-DYfX7NSM.js";
9
- import { y as appAddressBook } from "./shared-C-J32eBn.js";
8
+ import { t as activeApp } from "./shared-DGaQZXnw.js";
9
+ import { y as appAddressBook } from "./shared-CL3RLKDA.js";
10
10
  // packages/mistri/src/client/copy/public/publicAddress.ts
11
11
  /** What publicAddress says, in the public pages room (packages/kit/src/client/messages.ts says how the catalog is split). */
12
12
  var say = defineMessages({
@@ -87,4 +87,4 @@ var assistantEntry = (conversation) => ({
87
87
  });
88
88
  export { viewPath as n, assistantEntry as t };
89
89
 
90
- //# sourceMappingURL=shared-tksTLD6Q.js.map
90
+ //# sourceMappingURL=shared-CiqNkoE1.js.map