@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-Ccmc8YO0.js","names":["React","say","say","_Fragment","say","say","kept","say","say","say","say","say","_Fragment","say","say","say","_Fragment","say","say","_Fragment","say","say","_Fragment","askedFor","say","sayCopy","say","say","say","sayCopy","say","_Fragment"],"sources":["../../../../node_modules/@tanstack/react-query/build/modern/useIsFetching.js","../../../kit/src/client/components/suggestPart.ts","../../../kit/src/client/copy/workbench/components/History.ts","../../../kit/src/client/components/History.tsx","../../../kit/src/client/copy/workbench/history.ts","../../../kit/src/client/history.js","../../../kit/src/client/connectionScope.ts","../../../kit/src/client/roleLabels.ts","../../../kit/src/client/copy/forms/components/NewRecordButton.ts","../../../kit/src/client/components/NewRecordButton.tsx","../../../kit/src/client/components/pageStep.ts","../../../kit/src/client/copy/workbench/components/Export.ts","../../../kit/src/client/components/ExportHold.tsx","../../../kit/src/client/copy/lists/components/useBulkSelection.ts","../../../kit/src/client/components/useBulkSelection.tsx","../../../kit/src/client/copy/lists/components/GridSelection.ts","../../../kit/src/client/components/GridSelection.tsx","../../../kit/src/client/copy/lists/components/TableView.ts","../../../kit/src/client/components/TableView.tsx","../../../kit/src/client/copy/lists/components/TableRoom.ts","../../../kit/src/client/components/TableRoom.tsx","../../src/client/copy/dashboards/components/Funnel.ts","../../src/client/components/Funnel.tsx","../../../engine/src/shared/dashLayout.ts","../../../engine/src/shared/autoBucket.ts","../../../engine/src/shared/dashboardTrend.ts","../../../engine/src/shared/weekStart.ts","../../../kit/src/client/components/autoChart.ts","../../src/client/copy/shell/components/FirstRun.ts","../../src/client/components/FirstRun.tsx","../../src/client/copy/public/components/LandingData.ts","../../src/client/components/LandingData.tsx","../../src/client/copy/dashboards/components/Dashboard.ts","../../src/client/components/Dashboard.tsx"],"sourcesContent":[null,"/* The suggesting search box, as a part loaded on demand: every box that offers it names this one loader, and the\n first paint of a list or a landing carries none of it (SuggestBox.tsx). */\nimport { onDemand } from './onDemand.js';\n\nexport const SuggestBox = onDemand(() => import('./SuggestBox.js'), 'SuggestBox', { quiet: true });\n","/** What History says, in the Workbench room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n justNow: 'just now',\n minutesAgo: '{minutes}m ago',\n hoursAgo: '{hours}h ago',\n daysAgo: '{days}d ago',\n nothingYetQueriesAppear: 'Nothing yet. Queries appear here once they run.',\n clearQueries: { one: 'Clear {count} query', other: 'Clear {count} queries' },\n});\n","/**\n * The query history panel: what ran, how long ago, and one button to\n * forget it all. The store, the ↑/↓ stepping and the panel's open state\n * stay in `history.js`, which draws this into the panel it owns.\n */\nimport { say } from '../copy/workbench/components/History.js';\n\ninterface HistoryEntry {\n q: string;\n at?: number;\n}\n\nfunction ago(at: number): string {\n const seconds = Math.max(0, Math.round((Date.now() - at) / 1000));\n if (seconds < 60) return say('justNow');\n if (seconds < 3600) return say('minutesAgo', { minutes: Math.round(seconds / 60) });\n if (seconds < 86400) return say('hoursAgo', { hours: Math.round(seconds / 3600) });\n return say('daysAgo', { days: Math.round(seconds / 86400) });\n}\n\nexport function HistoryPanel({ entries, onRun, onClear }: { entries: HistoryEntry[]; onRun: (q: string) => void; onClear: () => void }) {\n if (!entries.length) return <p className=\"history-empty\">{say('nothingYetQueriesAppear')}</p>;\n return (\n <>\n <ul className=\"history-list\">\n {entries.map((entry) => (\n <li key={entry.q}>\n <button type=\"button\" className=\"history-item\" onClick={() => onRun(entry.q)}>\n <span className=\"history-q\">{entry.q}</span>\n <span className=\"history-age\">{ago(entry.at ?? Date.now())}</span>\n </button>\n </li>\n ))}\n </ul>\n <button type=\"button\" className=\"history-clear\" onClick={onClear}>\n {say('clearQueries', { count: entries.length })}\n </button>\n </>\n );\n}\n","/** What history says, in the Workbench room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../messages.js';\n\nexport const say = defineMessages({\n queryHistoryCleared: 'Query history cleared.',\n});\n","/**\n * Query history: the last 50 queries that ran, per connection.\n *\n * Two things shape this file.\n *\n * The first is that history is a convenience, never a dependency. Every\n * `localStorage` call is wrapped, because the API throws rather than returning\n * null in three ordinary situations — Safari's private mode, a browser set to\n * block site data, and a full quota — and a database browser that fails to\n * paint because it could not remember what you typed is worse than one that\n * never offered to. When storage refuses, the list falls back to memory and\n * works until the tab is closed.\n *\n * The second is that history is per connection. The stored value is keyed by\n * `state.activeConnection`, so switching from staging to production does not\n * offer you queries against tables the new database may not even have.\n */\nimport { createElement } from 'react';\nimport { $, el, loadJson, saveJson, state, toast } from './core.js';\nimport { mount } from './components/mount.js';\nimport { HistoryPanel } from './components/History.js';\nimport { say } from './copy/workbench/history.js';\nimport { addHostListener } from './shellHost.js';\n\nconst KEY = 'mistri.history.v1';\n\n/* Enough to cover a session's worth of exploration, small enough that the\n whole record stays well inside a quota even with long queries. */\nconst MAX_ENTRIES = 50;\n\n/** The whole record: `{ [connectionId]: [{ q, at }] }`. Never throws. */\nfunction readAll() {\n const parsed = loadJson(KEY, {});\n // Anything could be under this key — an older shape, or another tool's.\n // Refusing to trust it is cheaper than defending every read site.\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};\n}\n\n/* The in-memory mirror, and the reason a failed write is not a failed feature:\n the dropdown reads from here, so history keeps working for the session even\n when nothing can be persisted. */\nconst cache = new Map();\n\nconst scope = () => state.activeConnection ?? 'default';\n\n/** The history for the connection in use, newest first. */\nexport function historyFor(connection = scope()) {\n if (!cache.has(connection)) {\n const stored = readAll()[connection];\n cache.set(connection, Array.isArray(stored) ? stored.filter((e) => e && typeof e.q === 'string') : []);\n }\n return cache.get(connection);\n}\n\n/**\n * Remember a query that ran.\n *\n * Re-running something moves it to the top instead of adding a second copy:\n * the list is meant to answer \"what have I been looking at\", and twelve\n * identical rows of `customer` push the query you actually want off the end.\n */\nexport function recordQuery(text) {\n const q = String(text ?? '').trim();\n if (!q) return;\n const connection = scope();\n const kept = historyFor(connection).filter((entry) => entry.q !== q);\n kept.unshift({ q, at: Date.now() });\n kept.length = Math.min(kept.length, MAX_ENTRIES);\n cache.set(connection, kept);\n\n const all = readAll();\n all[connection] = kept;\n // Best effort: saveJson swallows a full or unavailable localStorage, and\n // the in-memory copy above keeps the list working for the session either way.\n saveJson(KEY, all);\n cursor = -1;\n draft = null;\n if (panel && !panel.hidden) fillPanel();\n}\n\nfunction clearHistory() {\n const connection = scope();\n cache.set(connection, []);\n const all = readAll();\n delete all[connection];\n saveJson(KEY, all);\n fillPanel();\n toast(say('queryHistoryCleared'));\n}\n\n/* ---------- the control ---------- */\n\nlet panel = null;\nlet toggle = null;\nlet installed = false;\n\n/* Where in the list the ↑/↓ walk currently is: -1 means \"on what you typed\",\n and `draft` holds that text so walking back down returns it rather than\n leaving the last history entry in the box. */\nlet cursor = -1;\nlet draft = null;\n\nfunction fillPanel() {\n mount(panel, createElement(HistoryPanel, { entries: historyFor(), onRun: runEntry, onClear: clearHistory }));\n}\n\nfunction runEntry(q) {\n const input = $('query');\n input.value = q;\n setOpen(false);\n cursor = -1;\n draft = null;\n /* `requestSubmit` rather than `submit`: it fires the form's submit event, so\n the one handler in app.js decides what a query means. `submit()` would\n skip it and reload the page. */\n $('querybar').requestSubmit();\n}\n\nfunction setOpen(open) {\n panel.hidden = !open;\n toggle.setAttribute('aria-expanded', String(open));\n if (open) fillPanel();\n}\n\n/** Step through the list in the input itself, without opening the panel. */\nfunction step(direction) {\n const entries = historyFor();\n if (!entries.length) return;\n const input = $('query');\n if (cursor === -1) draft = input.value;\n const next = Math.min(Math.max(cursor + direction, -1), entries.length - 1);\n cursor = next;\n input.value = next === -1 ? (draft ?? '') : entries[next].q;\n // Caret to the end, or the browser leaves it where it was and the next\n // keystroke lands in the middle of the recalled query.\n input.setSelectionRange(input.value.length, input.value.length);\n}\n\n/**\n * Attached on import rather than from a boot function.\n *\n * app.js wires the chrome, and this feature deliberately adds no line to it:\n * importing the module is enough to get the control, which keeps the query bar\n * working the same whether or not history is compiled in.\n */\nfunction initHistory() {\n if (installed) return;\n const bar = $('querybar');\n const input = $('query');\n if (!bar || !input) return;\n installed = true;\n\n /* No button in the header any more.\n\n Recent queries are reached two better ways: Ctrl/Cmd+↑ in the query bar,\n which is where your hands already are, and ⌘K, which searches them\n alongside everything else. A permanent button for a list you open once a\n session was the most expensive way to offer it. */\n toggle = el('button', { type: 'button', class: 'ghost history-toggle', hidden: true });\n panel = el('div', { class: 'history-panel', hidden: true });\n bar.append(panel);\n\n input.addEventListener('keydown', (e) => {\n // Ctrl/Cmd rather than a bare arrow: the query bar is a text field, and\n // stealing plain ↑/↓ would break moving the caret in a long query.\n if ((e.metaKey || e.ctrlKey) && (e.key === 'ArrowUp' || e.key === 'ArrowDown')) {\n e.preventDefault();\n step(e.key === 'ArrowUp' ? 1 : -1);\n return;\n }\n if (e.key === 'Escape' && !panel.hidden) {\n e.stopPropagation();\n setOpen(false);\n }\n });\n\n // Typing means you have left the recalled entry and are writing your own.\n input.addEventListener('input', () => {\n cursor = -1;\n draft = null;\n });\n\n /* Closed by a click anywhere else, which is what a menu is expected to do —\n on pointerdown so it happens before the click lands on whatever is behind. */\n addHostListener(document, 'pointerdown', (e) => {\n if (!panel.hidden && !panel.contains(e.target) && e.target !== toggle) setOpen(false);\n });\n}\n\nif (document.readyState === 'loading') {\n addHostListener(document, 'DOMContentLoaded', initHistory, { once: true });\n} else {\n initHistory();\n}\n","import { pageBridge } from './uiBridge.js';\nimport { appRequestScope, setAppRequestScope } from './requestIdentity.js';\n\n/** Listener metadata remains available before a failed app database can open. */\nexport function setAppConfigured(configured: boolean | null): void {\n setAppRequestScope(configured);\n}\n\n/** UI scope only. This does not replace server authorization. */\nexport function canManageConnections(): boolean {\n return appRequestScope() === false && !pageBridge.activeApp();\n}\n\n/** App Workbench uses the same listener boundary as the app itself. */\nexport function canUseDatabaseTools(): boolean {\n return appRequestScope() === false && !pageBridge.activeApp();\n}\n","/**\n * What this App calls its roles (`auth.roles.<id>.label`), as the sign-in\n * answer said them. Words for a person only: every choice and request still\n * names the id, so a missing or odd label never changes what is granted.\n */\nconst labels = new Map<string, string>();\n\nconst isLabel = (value: unknown): value is string =>\n typeof value === 'string' && value.length > 0 && value.length <= 60 && value.trim() === value && !/\\p{Cc}/u.test(value);\n\n/** The labels from `/api/whoami`'s `roleLabels`; anything else there is ignored, and the previous App's go. */\nexport function setRoleLabels(value: unknown): void {\n labels.clear();\n if (!value || typeof value !== 'object' || Array.isArray(value)) return;\n for (const [role, label] of Object.entries(value)) if (isLabel(label)) labels.set(role, label);\n}\n\nlet kept = false;\n/** From `/api/whoami`'s `hasRoles`: whether the App names roles at all. */\nexport function setAppKeepsRoles(value: unknown): void {\n kept = value === true;\n}\nexport const appKeepsRoles = (): boolean => kept;\n\n/** The App's own name for a role, where it gave one. */\nexport const roleLabel = (role: string): string | undefined => labels.get(role);\n","/** What NewRecordButton says, in the forms room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n addARow: 'Add a {name} row',\n newRow: '+ New row',\n create: 'Create a {label}',\n plusNew: '+ New',\n});\n","/**\n * The two New buttons.\n *\n * The workbench's \"+ New row\" behind the same gate every write affordance\n * uses: writable, write mode on, a table. The app list's \"New\": offered\n * whenever the connection accepts writes, whether or not editing is on — an\n * app's reader does not know the padlock exists, and a primary action that\n * only appears after finding it is not a primary action. Creating a record\n * does not change the editing mode for existing records. Absent on a read-only connection, where the server would\n * refuse the row anyway.\n */\nimport { canInsert, openInsert, openNewRecord } from '../insert.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { say } from '../copy/forms/components/NewRecordButton.js';\n\nexport interface FormSpec {\n show?: string[];\n defaults?: Record<string, unknown>;\n}\n\nexport function NewRowButton({ table }: { table: TableMeta }) {\n if (!canInsert(table)) return null;\n return (\n <button type=\"button\" className=\"ghost table-new-row\" title={say('addARow', { name: table.name })} onClick={() => openInsert(table)}>\n {say('newRow')}\n </button>\n );\n}\n\nexport function NewRecordButton({ table, label, form }: { table: TableMeta | undefined; label?: string; form?: FormSpec }) {\n /* The one rule every New entry point follows (insert.js): a table the reader's `create` grant leaves out is\n `insertable: false` in their catalog, and offering its form only to have the server refuse is a dead end. */\n if (!table || !canInsert(table, true)) return null;\n return (\n <button\n type=\"button\"\n className=\"ghost table-new-row applist-new\"\n title={say('create', { label: label ?? table.name })}\n onClick={() => {\n openNewRecord(table, form);\n }}\n >\n {/* The noun is its own span so a phone's crumb bar can say \"+ New\"\n beside a long title (structure.css); the name keeps the noun. */}\n {say('plusNew')} <span className=\"applist-new-noun\">{label ?? table.name}</span>\n </button>\n );\n}\n","/**\n * How the pager reached the page on screen, so the next read of it is by key\n * (shared/keysetPage.ts): Next is the rows after the last row shown,\n * Previous the rows before the first, Last the list's final rows read from\n * its end. A page reached by number — the page box, an address, First —\n * carries no step and is read by offset, which is cheap near the top and\n * refused past 10,000 rows.\n *\n * One step is kept, for one list and one page: it names the list by its\n * question and page size, so a step taken on another list, or before the\n * size changed, is never read as this one's. The page number stays what the\n * pager and the range say; the step only decides how it is read.\n */\nimport type { Boundary } from '@mistriwork/engine/shared/keysetPage.js';\n\ntype PageStepBody = { after: Boundary } | { before: Boundary } | { end: true };\ninterface Kept {\n list: string;\n page: number;\n body: PageStepBody;\n limit?: number;\n}\n\nlet kept: Kept | undefined;\n\n/** The list a step belongs to: its connection, table, question and page size. */\nexport function stepList(source: unknown, table: string, query: string, size: number): string {\n return JSON.stringify([source ?? null, table, query, size]);\n}\n\n/** Remember how `page` of `list` is reached; nothing, for a page reached by number. */\nexport function takePageStep(list: string, page: number, body?: PageStepBody, limit?: number): void {\n kept = body ? { list, page, body, ...(limit === undefined ? {} : { limit }) } : undefined;\n}\n\n/** How `page` of `list` is read, when the pager stepped to it: the request's step, and a limit of its own for the end. */\nexport function pageStepFor(list: string, page: number): { body: PageStepBody; limit?: number } | undefined {\n return kept && kept.list === list && kept.page === page\n ? { body: kept.body, ...(kept.limit === undefined ? {} : { limit: kept.limit }) }\n : undefined;\n}\n","/** What Export says, in the Workbench room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n none: 'None',\n thatQueryNoLonger: 'That query no longer returns rows.',\n thisPageRows: { one: 'this page ({count} row)', other: 'this page ({count} rows)' },\n allMatchingRows: 'all matching rows ({capped})',\n downloadThisResult: 'Download this result',\n export: 'Export',\n chooseColumns: 'Choose columns…',\n fetching: 'Fetching…',\n agent: 'Agent',\n theQueryTheShape: 'The query, the shape and how to run it over MCP — not the rows',\n copyThisPosition: 'Copy this position',\n cappedAtRowsTheSame: 'Capped at {max} rows — the same ceiling every read in this tool has. Narrow the query to export the rest.',\n pickAtLeastOne: 'Pick at least one column to export.',\n columnsToExport: 'Columns to export',\n tickedColumnsAreWritten:\n 'Ticked columns are written in the order the table declares them. Choosing a column that is not on screen re-runs the query to fetch it.',\n asDisplayed: 'As displayed',\n ofSelected: '{filterCount} of {columnsCount} selected',\n notShown: 'not shown',\n rememberedForThisTable: 'Remembered for this table on this connection.',\n useTheseColumns: 'Use these columns',\n selectedOfDeclared: '{selected} of {declared}',\n});\n","/**\n * Export's trigger, held: the control itself (Export.tsx), with its chooser,\n * serialisers and the agent hand-off, is a part that loads on demand, and\n * this is what stands in its place until it has — the same trigger, laid out\n * and unseen. The crumb bar is right-aligned, so a trigger arriving late\n * beside New would push New a button's width to the left. The part is asked\n * for as soon as a list is on its way, so it is usually here before the rows.\n */\nimport { useEffect, type ComponentProps } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useCrumbSlots, verbsAt } from './crumbSlot.js';\nimport { onDemand, useArrived } from './onDemand.js';\nimport { say } from '../copy/workbench/components/Export.js';\n\nconst ExportPart = onDemand(() => import('./Export.js'), 'ExportControl', { quiet: true });\n\nfunction HeldTrigger() {\n return (\n <div className=\"export\" aria-hidden=\"true\" inert style={{ visibility: 'hidden' }}>\n <button type=\"button\" className=\"export-summary\" tabIndex={-1}>\n <span className=\"export-word\">{say('export')}</span>\n <span className=\"export-more\">⋯</span>\n </button>\n </div>\n );\n}\n\n/** Export's place at the end of the crumb bar, or of the list's heading row, while the rows are on their way. */\nexport function ExportHold() {\n const tools = verbsAt(useCrumbSlots());\n useEffect(() => void ExportPart.ready(), []);\n if (!tools) return null;\n return createPortal(<HeldTrigger />, tools);\n}\n\n/** The Export control, or its held trigger until the part has arrived. */\nexport function ExportControl(props: ComponentProps<typeof ExportPart>) {\n return useArrived(ExportPart) ? <ExportPart {...props} /> : <HeldTrigger />;\n}\n","/** What useBulkSelection says, in the lists and grid room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n setColumn: 'Set {column}',\n doesNotMatchNow: 'Does not match \"{when}\" now.',\n selectedRecords: 'Selected records',\n selected: '{selectionCount} selected',\n setField: 'Set field…',\n oneRequestForTheWhole: 'One request for the whole selection: every record or none.',\n clearSelection: 'Clear selection',\n applying: 'Applying {done} of {total}…',\n selectionIsLimitedToRecords: 'Selection is limited to {max} records.',\n applyToSelectedRecords: { one: 'Apply to {count} selected record', other: 'Apply to {count} selected records' },\n willBeSkipped: '; {skipped} will be skipped',\n countSelectedRecords: { one: '{count} selected record', other: '{count} selected records' },\n});\n","/**\n * A selection of loaded records and the bulk actions offered for exactly\n * those keys — shared by the queue (a listbox) and the grid (a checkbox in\n * each row's host), so the two are one contract: the exact keys of loaded\n * records, never \"everything matching\"; a fixed update written per record\n * through `applyBulk`, each answered on its own; a bulk command sent once\n * for the group through its form.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { expectedValues, type TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport type { AppAction, AppCommandAction, AppUpdateAction } from '@mistriwork/engine/schema/model.js';\nimport { commandFieldsDeep, commandKeyText } from '@mistriwork/engine/shared/commandWire.js';\nimport { columnLabel, findTable, state, writeAllowed } from '../core.js';\nimport { humanName } from '@mistriwork/engine/shared/model.js';\nimport { onDemand, useArrived } from './onDemand.js';\nimport type { CountedMessage } from './CountedLabel.js';\nimport { messageLanguage, servedLanguage } from '../messages.js';\nimport { grantedActionIds } from '../actionGrants.js';\nimport {\n applyBulk,\n bulkCommandSummary,\n bulkKey,\n bulkSummary,\n countedLabel,\n matchingKeys,\n BULK_LIMIT,\n type BulkRecordOutcome,\n type BulkResult,\n type BulkTarget,\n} from '../bulkActions.js';\nimport { sessionIdentity, subscribeSessionIdentity } from '../sessionIdentity.js';\nimport { updateAttempts } from '../updateAttempts.js';\nimport { shell, type BulkCommandOperation, type BulkCommandOwner } from '../shellMode.js';\nimport { Modal } from '@mistriwork/ui/Modal.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { formatLocale, formatNumber } from '../locale.js';\nimport { resourceOf } from './appRooms.js';\nimport { pluralOf, recordNoun } from '@mistriwork/engine/shared/appNoun.js';\nimport { say } from '../copy/lists/components/useBulkSelection.js';\n\n/* A selection's App commands are the shell's (shellMode.ts `bulkCommands`): where it has none, a list offers none, and\n these stand in so the hooks below are asked the same way in either shell. */\nconst NO_RUNS = { subscribe: () => () => {}, version: () => 0, unresolvedGroups: (): BulkCommandOperation[] => [] };\nconst NO_ANSWERS: boolean[] = [];\nconst noAvailability = () => NO_ANSWERS;\n\n/* \"Set field…\" draws its own dialog, fetched the first time it is chosen. */\nconst SetFieldDialog = onDemand(() => import('./SetFieldDialog.js'), 'SetFieldDialog', { quiet: true });\nconst Counted = onDemand(() => import('./CountedLabel.js'), 'CountedLabel', { quiet: true });\n\n/**\n * An action's label for the selection. One whose App message counts (server\n * appMessages.ts countedLabels) is said by the formatter, loaded the first\n * time a selection of several needs it, the words for one record standing in\n * meanwhile; any other is counted as English counts it (countedLabel), or not\n * at all.\n */\nfunction ActionLabel({ action, count, noun }: { action: AppAction; count: number; noun?: { one: string; many: string } }) {\n const message = (action as { counted?: CountedMessage }).counted;\n const wanted = Boolean(message) && count > 1;\n const here = useArrived(Counted, wanted);\n if (message && wanted && here)\n return <Counted message={message} count={count} locale={servedLanguage() ?? formatLocale() ?? messageLanguage()} />;\n return <>{!message && noun ? countedLabel(action.label, count, noun) : action.label}</>;\n}\n\n/** A record the selection can name: its bulk key, its key, what it is called, its row. */\nexport interface BulkRecord extends BulkTarget {\n id: string;\n row: Record<string, unknown>;\n}\ninterface Run {\n label: string;\n done: number;\n total: number;\n}\ninterface Asking {\n action: AppUpdateAction;\n count: number;\n skipped: number;\n answer: (yes: boolean) => void;\n}\n/** `summary` replaces the per-record sentence for a group's single outcome. */\ninterface Reported {\n label: string;\n result: BulkResult;\n summary?: string;\n}\n/** A bulk command's form: the records it names, in list order. */\ninterface CommandRun {\n action: AppCommandAction;\n targets: BulkTarget[];\n epoch: number;\n}\n\nconst said = (v: unknown) => (v === null ? 'null' : String(v));\n/* What the resource's records are called: its noun, else its table's name\n as a person says it, made plural by rule unless it already reads so. */\nfunction nounOf(table: TableMeta): { one: string; many: string } {\n const app = shell().app();\n const authored = app?.resources ? resourceOf(app, table.id)?.noun : undefined;\n if (authored) return authored;\n const one = recordNoun(undefined, table.name);\n return { one, many: /[^s]s$/i.test(one) ? one : pluralOf(one) };\n}\nconst setSummary = (action: AppUpdateAction) =>\n Object.entries(action.set)\n .map(([c, v]) => `${c} → ${said(v)}`)\n .join(', ');\nconst isUpdate = (action: AppAction): action is AppUpdateAction => action.command === undefined;\nconst isCommand = (action: AppAction): action is AppCommandAction => action.command !== undefined;\nconst tally = (outcomes: BulkRecordOutcome[], stopped = false): BulkResult => {\n const counts: BulkResult['counts'] = { applied: 0, rejected: 0, uncertain: 0, blocked: 0, skipped: 0 };\n for (const outcome of outcomes) counts[outcome.kind]++;\n return { outcomes, counts, stopped };\n};\n\n/** The bulk updates and commands this reader may run over the resource now. */\nexport function offeredBulk(\n table: TableMeta,\n actions: AppAction[],\n interactive: boolean,\n identity = sessionIdentity(),\n connection: string | null = state.activeConnection ?? null,\n editable: readonly string[] = [],\n) {\n const writable = () => {\n const current = findTable(table.id) as TableMeta | undefined;\n return (\n interactive &&\n writeAllowed(table.id) &&\n Boolean(current) &&\n !current!.isView &&\n !table.isView &&\n Boolean(state.connections?.some((c) => c.id === connection && c.writable))\n );\n };\n const columnWritable = (action: AppUpdateAction) => {\n const current = findTable(table.id) as TableMeta | undefined;\n return Object.keys(action.set).every((name) => {\n const column = current?.columns.find((c) => c.name === name);\n return column && !column.primaryKey && column.writable !== false;\n });\n };\n /* Or a fixed action a role of this reader runs without write: the server\n admits it per record as that action and nothing else. */\n const granted = (action: AppUpdateAction) =>\n interactive &&\n grantedActionIds(shell().app(), table.id).includes(action.id) &&\n !table.isView &&\n Boolean(findTable(table.id)) &&\n Boolean(state.connections?.some((c) => c.id === connection && c.writable));\n const bulk = actions\n .filter(isUpdate)\n .filter((action) => action.bulk === true && ((writable() && columnWritable(action)) || granted(action)));\n /* A command needs its own grant, not generic write: the manager who may\n assign cannot edit the application, and that is the point. */\n const grantedCommands = shell().app()?.grantedCommands ?? [];\n const commandAllowed = (action: AppCommandAction) =>\n interactive &&\n action.bulk === true &&\n action.command.targets === 'many' &&\n identity.mode === 'authenticated' &&\n identity.appId === connection &&\n grantedCommands.includes(action.command.id) &&\n action.command.target === table.id &&\n Boolean(findTable(table.id)) &&\n // Every type the form draws; a reference, at any depth, only over a resource this person reads.\n [...commandFieldsDeep(action.command.input)].every(({ field }) => field.type !== 'reference' || Boolean(findTable(field.from)));\n const commands = shell().slots.bulkCommands ? actions.filter(isCommand).filter(commandAllowed) : [];\n /* \"Set field…\" writes one of the list's editable columns, under the same\n gate as a fixed update: each still a writable column of this reader's. */\n const fields = writable() ? editable.filter((name) => columnWritable({ id: `set:${name}`, label: name, set: { [name]: null } })) : [];\n return { bulk, commands, fields };\n}\n\nexport function useBulkSelection({\n table,\n keyed,\n actions = [],\n interactive = true,\n editable = [],\n}: {\n table: TableMeta;\n keyed: BulkRecord[];\n actions?: AppAction[];\n interactive?: boolean;\n /** The list's editable columns, offered to the selection as \"Set field…\". */\n editable?: readonly string[];\n}) {\n const client = useQueryClient();\n const commanding = shell().slots.bulkCommands;\n const commandOperations = commanding?.operations ?? NO_RUNS;\n const useCommandAvailability = commanding?.useAvailability ?? noAvailability;\n const CommandForm = commanding?.Form;\n useSyncExternalStore(updateAttempts.subscribe, updateAttempts.version, updateAttempts.version);\n useSyncExternalStore(commandOperations.subscribe, commandOperations.version, commandOperations.version);\n const identity = useSyncExternalStore(subscribeSessionIdentity, sessionIdentity, sessionIdentity);\n const [selected, setSelected] = useState<string[]>([]);\n const [capped, setCapped] = useState(false);\n const [running, setRunning] = useState<Run | null>(null);\n const [asking, setAsking] = useState<Asking | null>(null);\n const [reported, setReported] = useState<Reported | null>(null);\n const [commandRun, setCommandRun] = useState<CommandRun | null>(null);\n const resultRef = useRef<HTMLDivElement>(null);\n /* Where a closing command form sends focus. The dialog resolves it while it\n unmounts, before anything mounted in the same commit has a ref, so the\n report region is always in the tree (hidden until it has a report) and\n this points at it only when the close produces one; a Cancel with nothing\n sent leaves it empty, and focus goes back to the toolbar button. */\n const returnFocus = useRef<HTMLElement | null>(null);\n const alive = useRef(true);\n useEffect(() => {\n alive.current = true;\n return () => {\n alive.current = false;\n };\n }, []);\n\n const connection = state.activeConnection ?? null;\n const byId = new Map(keyed.map((record) => [record.id, record]));\n // A record that left the list leaves the selection; one that returns is not re-selected.\n const present = keyed.map((record) => record.id).join('\\n');\n useEffect(() => {\n const ids = new Set(present.split('\\n'));\n setSelected((current) => (current.every((id) => ids.has(id)) ? current : current.filter((id) => ids.has(id))));\n }, [present]);\n const selection = useMemo(() => selected.filter((id) => byId.has(id)), [selected, present]);\n\n const { bulk, commands, fields } = offeredBulk(table, actions, interactive, identity, connection, editable);\n const [setting, setSetting] = useState(false);\n const selectedRecords = keyed.filter((record) => selection.includes(record.id));\n const availability = useCommandAvailability(\n commands.flatMap((action) =>\n selectedRecords.map((record) => ({\n command: action.command.id,\n commandVersion: action.command.version,\n key: record.key,\n })),\n ),\n interactive,\n );\n const availableCommands = commands.filter(\n (_action, index) =>\n selectedRecords.length > 0 &&\n selectedRecords.every((_record, offset) => availability[index * selectedRecords.length + offset] === true),\n );\n\n // Navigation can unmount the queue; coming back resumes an unconfirmed group.\n const resumed = commandRun\n ? undefined\n : commandOperations\n .unresolvedGroups(connection ?? '', table.id)\n .find((operation) => operation.identity === identity && operation.action && operation.owner.keys);\n const commandForm: CommandRun | null =\n commandRun && commandRun.epoch === identity.epoch\n ? commandRun\n : resumed\n ? {\n action: resumed.action!,\n epoch: identity.epoch,\n targets: resumed.owner.keys!.map((key, index) => ({ key, label: resumed.owner.labels?.[index] ?? commandKeyText(key) })),\n }\n : null;\n const groupOwner = (run: CommandRun): BulkCommandOwner => ({\n connection: connection ?? '',\n target: run.action.command.target,\n command: run.action.command.id,\n commandVersion: run.action.command.version,\n key: {},\n keys: run.targets.map((target) => ({ ...target.key })),\n labels: run.targets.map((target) => target.label),\n });\n const formEpoch = commandForm?.epoch;\n const formCurrent = useCallback(\n () => alive.current && sessionIdentity().epoch === formEpoch && (state.activeConnection ?? null) === connection,\n [formEpoch, connection],\n );\n\n const change = (keys: string[]) => {\n const over = keys.length > BULK_LIMIT;\n setCapped(over);\n setSelected(over ? keys.slice(0, BULK_LIMIT) : keys);\n };\n const clear = () => {\n setSelected([]);\n setCapped(false);\n setReported(null);\n };\n\n const run = (action: AppUpdateAction) => (bulk.includes(action) ? write(action) : Promise.resolve());\n /* \"Set field…\": one value for one column, written per record exactly as a\n fixed update is — the dialog that chose it was the confirmation. */\n const setField = (column: string, value: string | null) => {\n setSetting(false);\n if (!fields.includes(column)) return Promise.resolve();\n return write({\n id: `set:${column}`,\n label: say('setColumn', { column: columnLabel(table.id, column) ?? humanName(column) }),\n set: { [column]: value },\n });\n };\n const write = async (action: AppUpdateAction) => {\n if (running || commandForm) return;\n const targets = keyed.filter((record) => selection.includes(record.id));\n if (!targets.length) return;\n const epoch = sessionIdentity().epoch;\n const current = () => alive.current && sessionIdentity().epoch === epoch && (state.activeConnection ?? null) === connection;\n setReported(null);\n setRunning({ label: action.label, done: 0, total: targets.length });\n const matching = await matchingKeys(\n table,\n targets.map((record) => record.key),\n action.when,\n connection,\n );\n if (!current()) {\n if (alive.current) setRunning(null);\n return;\n }\n const applicable = targets.filter((record) => matching.has(record.id));\n const skipped = new Map(\n targets\n .filter((record) => !matching.has(record.id))\n .map((record): [string, BulkRecordOutcome] => [\n record.id,\n { key: record.key, label: record.label, kind: 'skipped', message: say('doesNotMatchNow', { when: action.when ?? '' }) },\n ]),\n );\n // Nothing to write needs no permission; the report says why.\n if (action.confirm && applicable.length) {\n const yes = await new Promise<boolean>((answer) => setAsking({ action, count: applicable.length, skipped: skipped.size, answer }));\n if (alive.current) setAsking(null);\n if (!yes || !current()) {\n if (alive.current) setRunning(null);\n return;\n }\n }\n const applied = await applyBulk(\n { connection, table: table.id },\n action.set,\n applicable.map(({ key, label, row }) => {\n const expected = expectedValues(table, action.set, row);\n return { key, label, ...(expected ? { expected } : {}) };\n }),\n current,\n (done, total) => {\n if (alive.current) setRunning({ label: action.label, done, total });\n },\n );\n if (!alive.current) return;\n setRunning(null);\n const written = new Map(applied.outcomes.map((outcome) => [bulkKey(table, outcome.key), outcome]));\n const result = tally(\n targets.map((record) => written.get(record.id) ?? skipped.get(record.id)!),\n applied.stopped,\n );\n setReported({ label: action.label, result });\n if (result.counts.applied && current()) {\n void shell().undo.refresh();\n void client.invalidateQueries({ queryKey: ['run', connection] });\n void client.invalidateQueries({ queryKey: ['count', connection] });\n void client.invalidateQueries({ queryKey: ['when', table.id] });\n }\n };\n\n /* A bulk command prepares, asks and sends inside the command form. Its\n records are the selection at the press, in list order; the form may\n only narrow them (Deselect ineligible), never widen them. */\n const openCommand = (action: AppCommandAction) => {\n if (running || commandForm || !availableCommands.includes(action)) return;\n const targets = keyed.filter((record) => selection.includes(record.id)).map(({ key, label }) => ({ key, label }));\n if (!targets.length) return;\n setReported(null);\n setCommandRun({ action, targets, epoch: identity.epoch });\n };\n const deselect = (keys: Array<Record<string, unknown>>) => {\n const drop = new Set(keys.map(commandKeyText));\n setSelected((current) =>\n current.filter((id) => {\n const record = byId.get(id);\n return !record || !drop.has(commandKeyText(record.key));\n }),\n );\n setCommandRun((current) => {\n if (!current) return current;\n const targets = current.targets.filter((target) => !drop.has(commandKeyText(target.key)));\n return targets.length ? { ...current, targets } : null;\n });\n };\n // One outcome for the group; an unconfirmed one keeps the form open instead.\n const closeCommand = (settled?: BulkCommandOperation) => {\n const finished = commandForm;\n setCommandRun(null);\n returnFocus.current = null;\n if (!finished || !settled || !alive.current) return;\n if (settled.phase === 'success' || settled.phase === 'error') returnFocus.current = resultRef.current;\n const count = settled.owner.keys?.length ?? finished.targets.length;\n if (settled.phase === 'success') {\n setReported({\n label: finished.action.label,\n summary: bulkCommandSummary(finished.action.label, count, 'applied'),\n result: tally(finished.targets.map((target) => ({ ...target, kind: 'applied', message: '' }))),\n });\n } else if (settled.phase === 'error') {\n const named =\n settled.refusedKey && finished.targets.find((target) => commandKeyText(target.key) === commandKeyText(settled.refusedKey));\n const message = `${settled.message}${named ? ` (${named.label})` : ''}`;\n setReported({\n label: finished.action.label,\n summary: bulkCommandSummary(finished.action.label, count, 'rejected', message),\n result: tally(finished.targets.map((target) => ({ ...target, kind: 'rejected', message }))),\n });\n }\n };\n // The report is the answer to the press; a reader hears it where they are.\n // After a command form the dialog hands focus here itself (`returnFocus`),\n // once the page behind it is no longer inert.\n useEffect(() => {\n if (reported) resultRef.current?.focus();\n }, [reported]);\n\n const failed = reported && (reported.result.counts.rejected > 0 || reported.result.counts.uncertain > 0);\n const busy = Boolean(running) || Boolean(commandForm);\n const bar = (\n <>\n {/* Nothing until something is chosen: a row of disabled verbs and \"0\n selected\" above every list was a bar of things that could not be done. */}\n {(bulk.length > 0 || commands.length > 0 || fields.length > 0) && (selection.length > 0 || running) && (\n <div role=\"toolbar\" aria-label={say('selectedRecords')} className=\"queue-bulk\" aria-busy={Boolean(running)}>\n <span className=\"queue-count\">{say('selected', { selectionCount: selection.length })}</span>\n {fields.length > 0 && (\n <button\n type=\"button\"\n className=\"ghost\"\n disabled={busy}\n onClick={() => {\n setReported(null);\n setSetting(true);\n }}\n >\n {say('setField')}\n </button>\n )}\n {bulk.map((action) => (\n <button\n key={action.label}\n type=\"button\"\n className=\"ghost\"\n title={setSummary(action)}\n disabled={busy}\n onClick={() => {\n void run(action);\n }}\n >\n <ActionLabel action={action} count={selection.length} />\n </button>\n ))}\n {availableCommands.map((action) => (\n <button\n key={`command:${action.command.id}:${action.label}`}\n type=\"button\"\n className=\"ghost\"\n title={say('oneRequestForTheWhole')}\n disabled={busy}\n onClick={() => openCommand(action)}\n >\n <ActionLabel action={action} count={selection.length} noun={nounOf(table)} />\n </button>\n ))}\n <button type=\"button\" className=\"ghost queue-clear\" disabled={Boolean(running)} onClick={clear}>\n {say('clearSelection')}\n </button>\n {running && (\n <span className=\"queue-progress\" role=\"status\">\n {say('applying', { done: running.done, total: running.total })}\n </span>\n )}\n </div>\n )}\n {capped && (\n <p className=\"queue-status\" role=\"status\">\n {say('selectionIsLimitedToRecords', { max: BULK_LIMIT })}\n </p>\n )}\n {/* Dismiss stands beside the report, not in it: the report is where a\n closing command form sends focus, and a dialog sends it to the first\n control inside its target when there is one. */}\n <div className=\"queue-report\">\n <div className=\"queue-result\" role={failed ? 'alert' : 'status'} tabIndex={-1} ref={resultRef} hidden={!reported}>\n {reported && <p>{reported.summary ?? bulkSummary(reported.label, reported.result)}</p>}\n {reported && !reported.summary && reported.result.outcomes.some((outcome) => outcome.kind !== 'applied') && (\n <ul>\n {reported.result.outcomes\n .filter((outcome) => outcome.kind !== 'applied')\n .map((outcome) => (\n <li key={bulkKey(table, outcome.key)}>\n {outcome.label}: {outcome.message}\n </li>\n ))}\n </ul>\n )}\n </div>\n {reported && !running && (\n <button type=\"button\" className=\"ghost queue-dismiss\" onClick={clear}>\n {say('common.dismiss')}\n </button>\n )}\n </div>\n </>\n );\n const dialogs = (\n <>\n {setting && (\n <SetFieldDialog\n table={table}\n columns={fields}\n count={selection.length}\n row={selectedRecords[0]?.row}\n onApply={(column, value) => {\n void setField(column, value);\n }}\n onClose={() => setSetting(false)}\n />\n )}\n {asking && (\n <Confirm\n asking={asking}\n onAnswer={(yes) => {\n setAsking(null);\n asking.answer(yes);\n }}\n />\n )}\n {commandForm && CommandForm && (\n <CommandForm\n key={`${commandForm.epoch}:${commandForm.action.command.id}`}\n action={commandForm.action}\n owner={groupOwner(commandForm)}\n targets={commandForm.targets}\n onDeselect={deselect}\n noun={nounOf(table)}\n label={say('countSelectedRecords', { count: commandForm.targets.length })}\n onClose={closeCommand}\n onDone={() => {}}\n isCurrent={formCurrent}\n finalFocus={returnFocus}\n />\n )}\n </>\n );\n return { offered: bulk.length > 0 || commands.length > 0 || fields.length > 0, selection, change, clear, byId, bar, dialogs };\n}\n\n/** Ask before writing the selection, in the page's own dialog. */\nfunction Confirm({ asking, onAnswer }: { asking: Asking; onAnswer: (yes: boolean) => void }) {\n const { action, count, skipped } = asking;\n const answered = useRef(false);\n const answer = (yes: boolean) => {\n if (answered.current) return;\n answered.current = true;\n onAnswer(yes);\n };\n return (\n <Modal className=\"confirm action-confirm\" ariaLabel={`${action.label}?`} onClose={() => answer(false)}>\n <h2>{action.label}?</h2>\n <p>\n {say('applyToSelectedRecords', { count })}\n {skipped ? say('willBeSkipped', { skipped: formatNumber(skipped) }) : ''}.\n </p>\n <p>\n <strong>{setSummary(action)}</strong>\n </p>\n <div className=\"confirm-actions\">\n <Button intent=\"secondary\" onClick={() => answer(false)}>\n {say('common.cancel')}\n </Button>\n <Button intent=\"primary\" onClick={() => answer(true)}>\n {action.label}\n </Button>\n </div>\n </Modal>\n );\n}\n","/** What GridSelection says, in the lists and grid room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n selectAll: 'Select all {noun}',\n select: 'Select {label}',\n});\n","/**\n * The queue's selection on a grid: a checkbox in each row's leading cell —\n * the row host, so the grid is not told about it — one in the header row's\n * for every row at once, and the same bulk bar, the same keys and the same\n * per-record writes as a queue over the resource.\n */\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport type { AppAction } from '@mistriwork/engine/schema/model.js';\nimport { keyOf, rowLabel } from '../core.js';\nimport { shell } from '../shellMode.js';\nimport { bulkKey } from '../bulkActions.js';\nimport { resourceOf } from './appRooms.js';\nimport { RowDecoration, RowHeadDecoration } from './RowHost.js';\nimport { useBulkSelection, type BulkRecord } from './useBulkSelection.js';\nimport { say } from '../copy/lists/components/GridSelection.js';\n\nexport function GridSelection({\n table,\n rows,\n actions,\n interactive,\n editable = [],\n}: {\n table: TableMeta;\n rows: Array<Record<string, unknown>>;\n actions: AppAction[];\n interactive: boolean;\n /** The list's editable columns: the selection offers \"Set field…\" over them. */\n editable?: readonly string[];\n}) {\n const keyed: BulkRecord[] = rows.flatMap((row) => {\n const key = keyOf(table, row) as Record<string, unknown> | null;\n return key ? [{ id: bulkKey(table, key), key, label: String(rowLabel(table, row) ?? say('common.untitled')), row }] : [];\n });\n const { offered, selection, change, bar, dialogs } = useBulkSelection({ table, keyed, actions, interactive, editable });\n if (!offered) return null;\n const chosen = new Set(selection);\n const every = keyed.length > 0 && selection.length === keyed.length;\n const partly = selection.length > 0 && !every;\n /* The box every table has in its header row: no label and no count, since\n the column says what it is. Its name says what \"all\" takes — the rows\n loaded here, as before — in the resource's own word where it has one. */\n const noun = resourceOf(shell().app(), table.id)?.noun?.many ?? 'rows';\n return (\n <>\n <div className=\"grid-select-bar\">{bar}</div>\n {keyed.length > 0 && (\n <RowHeadDecoration>\n {/* Mixed is a property, not an attribute: set on every paint, because\n the box may reach the header after the selection changed. */}\n <input\n type=\"checkbox\"\n className=\"row-select\"\n aria-label={say('selectAll', { noun })}\n checked={every}\n ref={(box) => {\n if (box) box.indeterminate = partly;\n }}\n onChange={() => change(every ? [] : keyed.map((record) => record.id))}\n />\n </RowHeadDecoration>\n )}\n {keyed.map((record) => (\n <RowDecoration key={record.id} rowKey={record.id}>\n {/* Choosing is not opening: the click stays on the box. */}\n <input\n type=\"checkbox\"\n className=\"row-select\"\n aria-label={say('select', { label: record.label })}\n checked={chosen.has(record.id)}\n onClick={(event) => event.stopPropagation()}\n onChange={(event) => change(event.target.checked ? [...selection, record.id] : selection.filter((id) => id !== record.id))}\n />\n </RowDecoration>\n ))}\n {dialogs}\n </>\n );\n}\n","/** What TableView says, in the lists and grid room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n tableViews: 'Table views',\n rows: 'Rows',\n diagram: 'Diagram',\n definition: 'Definition',\n aPageAboutOne: 'A page about one record of this table',\n page: 'Page →',\n copyThisListAsAnApp: 'Copy this list as an App list view',\n copyAppEntry: 'Copy app entry',\n rowsShown: 'rows {range} shown',\n roughlyFromTheDatabases: 'Roughly, from the database’s own statistics — no rows were counted. Click to count them.',\n rowsRangeOfAbout: 'rows {range} of ~{total}',\n countingStoppedHereClick: 'Counting stopped here. Click to count every matching row.',\n rowsRangeOfAtLeast: 'rows {range} of {total}+',\n totalRows: '{total}+ rows',\n rowsRangeOfTotal: 'rows {range} of {total}',\n ms: '{ms} ms',\n rowsHaveToCome: 'Rows have to come back in some order. Click to make this one explicit.',\n sortedBy: 'sorted by {column}',\n rowsPerPage: 'Rows per page',\n previous: 'Previous',\n next: 'Next',\n previousPage: 'Previous page',\n nextPage: 'Next page',\n first: 'First',\n firstPage: 'First page',\n ofPages: 'of {count}',\n pagePage: 'Page {page}',\n last: 'Last',\n lastPage: 'Last page',\n pageNumber: 'Page number',\n nothingHereRightNow: 'Nothing here right now. Add a record or choose another view.',\n shown: '{rowsCount} shown',\n countShown: '{rows} shown',\n shownOfTotal: '{shown} shown of {total}',\n aboutTotalRows: '~{total} rows',\n});\n","/**\n * The table view around the grid: the result's head, the grid, the pager —\n * and, in the workbench, the tab strip above them.\n *\n * The fetch is not here: TableRoom asks, keyed by the question, and hands\n * the answer in. A page, a page size or a header's sort re-asks in place\n * (core.js `refine`), so this stays mounted while the previous answer stays\n * on screen; `at` says which page that answer is, and `busy` that the next\n * is on its way. What this draws is the answer.\n */\nimport { PresentationSwitch } from './PresentationSwitch.js';\nimport { createPortal } from 'react-dom';\nimport { useCrumbSlots, verbsAt } from './crumbSlot.js';\nimport {\n PAGE_SIZES,\n beginNavigation,\n currentEntry,\n findTable,\n go,\n keyOf,\n pageSize,\n pageView,\n prefersPages,\n refine,\n render,\n setPageSize,\n state,\n} from '../core.js';\nimport { explicitLimit, sortCount, sortDirection } from '../clauses.js';\nimport { NewRowButton } from './NewRecordButton.js';\nimport { copyListView } from '../filterbar.js';\nimport { pagesFor } from '../page.js';\nimport { sortBy } from '../thmenu.js';\nimport { primaryKey, type TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { Dropdown } from './Dropdown.js';\nimport { stepList, takePageStep } from './pageStep.js';\nimport { formatApprox, formatNumber } from '../locale.js';\nimport { ExportControl } from './ExportHold.js';\nimport { Grid, type GridData } from './Grid.js';\nimport { trailListFor } from '../recordTrail.js';\nimport { useContext, useEffect, useMemo, useRef, useState, type ReactNode, type RefObject } from 'react';\nimport { BesideDetail } from './besideDetail.js';\nimport { editableCells, type CellDraw } from './gridCellModel.js';\nimport { canEditRow } from '../rowEditing.js';\nimport { RecordSummaries, tableSaysMore } from './RecordSummaries.js';\nimport { canUseDatabaseTools } from '../connectionScope.js';\nimport { shell } from '../shellMode.js';\nimport { onDemand, useArrived } from './onDemand.js';\nimport { RowHosts, RowTrailHosts } from './RowHost.js';\nimport { RowActions } from './RowActions.js';\nimport { GridSelection } from './GridSelection.js';\nimport { offeredBulk } from './useBulkSelection.js';\nimport { GridOrder, type ListOrder } from './useListOrder.js';\nimport { say } from '../copy/lists/components/TableView.js';\nimport { Icon } from './Icon.js';\n\n/** A grid draws a selection column only for a reader offered a bulk action — or \"Set field…\" — on keyed rows. */\nfunction selectableGrid(table: TableMeta, actions: AppAction[], interactive: boolean, editable: readonly string[]): boolean {\n if (!interactive || (!actions.length && !editable.length) || !primaryKey(table).length) return false;\n const offered = offeredBulk(table, actions, interactive, undefined, undefined, editable);\n return offered.bulk.length > 0 || offered.commands.length > 0 || offered.fields.length > 0;\n}\nimport type { AppAction } from '@mistriwork/engine/schema/model.js';\nimport type { AppListPresentation } from '@mistriwork/engine/shared/listPresentations.js';\n\n/* A cell's editor, fetched the first time a list that edits in place is\n drawn. The list waits for it (TableRoom.tsx, Rows) as it waits for its rows,\n so a click on a cell never opens the row for want of the editor. */\nexport const GridCellEdit = onDemand(() => import('./GridCellEditor.js'), 'GridCellEdit', { quiet: true });\n\n/** Whether the connection on screen is an API (adapters/http), whose tables get the API tab (ApiOperations.tsx). */\nexport function isApiConnection(): boolean {\n return (state as { schema?: { dialect?: string } | null }).schema?.dialect === 'http';\n}\n\nexport interface TableEntry {\n kind: 'table';\n table: string;\n query: string;\n tab?: string;\n exactCount?: boolean;\n}\n\n/** What a list's presentation is drawn from (`present`): the list's own props, and the page of rows it holds. */\nexport interface PresentArgs {\n presentation: AppListPresentation;\n table: TableMeta | undefined;\n data: TableViewProps['data'];\n entry: TableEntry;\n actions: AppAction[] | undefined;\n listLabel: string | undefined;\n referenceLabels: Record<string, string> | undefined;\n interactive: boolean;\n recordNavigation: boolean;\n /** The list these rows are a page of, for a record opened from it to step past the page (recordTrail.ts). */\n list: ReturnType<typeof trailListFor> | undefined;\n /** The record beside this list (a split's detail), marked in it. */\n current: Record<string, unknown> | undefined;\n order: ListOrder | undefined;\n at: PageAt;\n}\n\n/**\n * A presentation drawn in the grid's place. `whole`: it asks its own question\n * (a calendar's month, a tree's every branch) and is the list entire;\n * otherwise it draws this page's rows, under the count and over the pager\n * where it `pages`.\n */\nexport interface PresentedList {\n whole: boolean;\n element: ReactNode;\n pages: boolean;\n}\n\n/** Draws a list's presentation, or null where it cannot be drawn from this answer and the grid stands. */\nexport type Present = (args: PresentArgs) => PresentedList | null;\n\nexport interface TableViewProps {\n /** How the view's rows draw instead of the grid: a checklist, a queue or a board. */\n presentation?: AppListPresentation;\n /** What draws `presentation`: the App's (presentedList.tsx), handed down by its lists. The Workbench passes none, and draws the grid. */\n present?: Present;\n /** The entry's fixed actions, for the presentations that offer them. */\n actions?: AppAction[];\n /** The entry's label: what a queue or board is called to assistive technology. */\n listLabel?: string;\n /** The view's hand-order column, where it keeps one: its rows are put in place by an editor (useListOrder.tsx). */\n order?: string;\n /** An otherwise read-only card list may open a record. */\n recordNavigation?: boolean;\n sizing?: import('@mistriwork/engine/shared/tableSizing.js').TableSizing;\n entry: TableEntry;\n data: GridData & { table: string; rows: Array<Record<string, unknown>>; total?: number; ms: number };\n /** The explorer's own view, or an embedded one (an app list, a page's chooser). */\n chrome: boolean;\n interactive: boolean;\n hide?: string[];\n labels?: Record<string, string>;\n /** A reference column → the fetched path its record's name is read from, drawn in its place by the grid, a queue and cards. */\n referenceLabels?: Record<string, string>;\n /** Column → its total over the whole query, for the grid's footer. */\n totals?: Record<string, unknown>;\n density?: 'comfortable' | 'compact';\n /** A ⋯ menu at the end of each row with the record's own actions. */\n rowActions?: boolean;\n /** The view's `editable`: cells edited in place, and the selection's \"Set field…\" (GridCellEditor.tsx). */\n editable?: true | string[];\n /** The page's own list: Export goes to the crumb bar, the range to the pager. */\n inCrumbs?: boolean;\n export?: boolean;\n summaries?: boolean;\n /**\n * Drawn inside another room — a dashboard's section. It keeps to its width,\n * leaving out the columns past it rather than scrolling to them, and on a\n * phone says its rows as record summaries, with no Records/Table switch:\n * the switch is the list's own, one click away.\n */\n embedded?: boolean;\n /** The page and page size this answer was asked for; the walk's own when not given. */\n at?: PageAt;\n /** The next answer is on its way; this one stays on screen until it lands. */\n busy?: boolean;\n}\n\nexport interface PageAt {\n page: number;\n size: number;\n}\n\n/** Open this table's page: the configured one if there is one, else the suggested. */\nasync function openPageFor(tableId: string): Promise<void> {\n const isCurrent = beginNavigation();\n let pageId = `suggested:${tableId}`;\n try {\n const [configured] = await pagesFor(tableId);\n if (configured && !configured.error) pageId = configured.id;\n } catch {\n // No config pages to read is not a reason to refuse the suggested one.\n }\n if (isCurrent()) go(pageView(pageId, tableId), 'push');\n}\n\n/** The explorer's tabs over a table: rows, definition, diagram — and the doors beside them. */\nexport function ViewTabs({ entry }: { entry: TableEntry }) {\n return (\n <div className=\"tabs\" data-scrolls=\"\">\n {/* The tabs are a tablist of their own: the doors beside them are not\n tabs, and a tablist may hold only tabs. It lays out as if absent. */}\n <div className=\"tabs-list\" role=\"tablist\" aria-label={say('tableViews')}>\n {/* An API's definition is its description, so its tables trade Definition\n for API: its documented reads, tried from here (ApiOperations.tsx). */}\n {(isApiConnection()\n ? ([\n ['rows', say('rows')],\n ['api', 'API'],\n ['diagram', say('diagram')],\n ] as const)\n : ([\n ['rows', say('rows')],\n ['ddl', say('definition')],\n ['diagram', say('diagram')],\n ] as const)\n )\n .filter(([id]) => (id !== 'ddl' && id !== 'api') || canUseDatabaseTools())\n .map(([id, label]) => (\n <button\n key={id}\n type=\"button\"\n role=\"tab\"\n className=\"tab\"\n aria-selected={(entry.tab ?? 'rows') === id}\n onClick={() => go({ ...entry, tab: id }, 'replace')}\n >\n {label}\n </button>\n ))}\n </div>\n {/* The way into a page from a table: not a tab of this table, but this\n is where someone looks for it. */}\n <button type=\"button\" className=\"tab tab-page\" title={say('aPageAboutOne')} onClick={() => void openPageFor(entry.table)}>\n {say('page')}\n </button>\n {/* The authoring bridge: this list as a paste-ready App list view. */}\n <button type=\"button\" className=\"tab tab-copy-entry\" title={say('copyThisListAsAnApp')} onClick={() => void copyListView(entry)}>\n {say('copyAppEntry')}\n </button>\n </div>\n );\n}\n\nfunction ResultHead({\n entry,\n data,\n chrome,\n interactive,\n exportOn,\n at,\n headRef,\n inCrumbs = false,\n}: {\n entry: TableEntry;\n data: TableViewProps['data'];\n chrome: boolean;\n interactive: boolean;\n exportOn: boolean;\n at: PageAt;\n headRef: RefObject<HTMLDivElement | null>;\n inCrumbs?: boolean;\n}) {\n const tools = verbsAt(useCrumbSlots());\n /* The page's own list says its count in the crumb bar (or its heading row,\n where no bar is drawn) and its range in the pager; Export joins New at\n that row's end, and no stats row is drawn. */\n if (inCrumbs && tools) {\n return (\n <div className=\"result-head-anchor\" ref={headRef}>\n {exportOn && createPortal(<ExportControl entry={entry} data={data} />, tools)}\n </div>\n );\n }\n /* Any other App list (one drawn inside a record or a dashboard) names its\n count in its own title: \"2 rows\" and \"sorted by id ↓\" under it were the\n Workbench's instruments, which stay in the Workbench. */\n if (shell().inApp() && !chrome) {\n const own = findTable(data.table) as TableMeta | undefined;\n return (\n <div className=\"result-head result-head-app\" ref={headRef}>\n {!prefersPages() && own && <NewRowButton table={own} />}\n {exportOn && <ExportControl entry={entry} data={data} />}\n </div>\n );\n }\n const first = at.page * at.size + 1;\n const shown = at.page * at.size + data.rows.length;\n const total = data.total;\n /* The range on screen. \"60 of 907\" on page three read as sixty rows\n shown, and the last page's bare total read as a table that fits. It is\n the answer's own page: while the next one is fetched, these are still\n the rows in front of the reader. */\n const range = at.page > 0 || (total !== undefined && total > shown) ? `${formatNumber(first)}–${formatNumber(shown)}` : null;\n const table = findTable(data.table) as TableMeta | undefined;\n return (\n <div className=\"result-head\" ref={headRef}>\n {chrome && <h1 className=\"result-title\">{data.table}</h1>}\n {total === undefined ? (\n <span className=\"stat\">\n {range && data.rows.length > 0\n ? say('rowsShown', { range })\n : say('countShown', { rows: say('common.rows2', { count: data.rows.length }) })}\n </span>\n ) : data.exactTotal === false ? (\n /* An estimate says so, and offers the real number: above a threshold\n the count comes from the catalog's statistics, and \"~2.4M\" is\n honest where \"2,400,113\" would not be. */\n <button\n type=\"button\"\n className=\"stat stat-estimate\"\n title={say('roughlyFromTheDatabases')}\n onClick={() => go({ ...entry, exactCount: true }, 'replace')}\n >\n {range ? say('rowsRangeOfAbout', { range, total: formatApprox(total) }) : say('aboutTotalRows', { total: formatApprox(total) })}\n </button>\n ) : data.cappedTotal ? (\n /* A filtered total is counted to a bound (10,000 by default), which\n is what keeps a filter over a large table from spending most of\n its time counting. Past it the head says \"10,000+\" and offers the\n exact number, one click and one full count away. */\n <button\n type=\"button\"\n className=\"stat stat-estimate\"\n title={say('countingStoppedHereClick')}\n onClick={() => go({ ...entry, exactCount: true }, 'replace')}\n >\n {range ? say('rowsRangeOfAtLeast', { range, total: formatNumber(total) }) : say('totalRows', { total: formatNumber(total) })}\n </button>\n ) : (\n <span className=\"stat\">\n {range ? say('rowsRangeOfTotal', { range, total: formatNumber(total) }) : say('common.rows2', { count: total })}\n </span>\n )}\n {/* The query's time is the Workbench's instrument; in an App's list it\n was a number beside the count nobody there asked for. */}\n {!shell().inApp() && <span className=\"stat\">{say('ms', { ms: data.ms })}</span>}\n {/* The default order, named, because the column it sorted by may not\n be on screen. Clicking writes it into the query. */}\n {interactive && data.order?.implicit && data.order.order.length > 0 && (\n <button\n type=\"button\"\n className=\"stat stat-order\"\n title={say('rowsHaveToCome')}\n onClick={() => sortBy(data.order!.order[0].column, data.order!.order[0].direction)}\n >\n {say('sortedBy', { column: data.order.order[0].column })}\n {data.order.order[0].direction === 'desc' ? ' ↓' : ' ↑'}\n </button>\n )}\n {/* Not where the app's list head already offers \"New\". */}\n {!prefersPages() && table && <NewRowButton table={table} />}\n {exportOn && <ExportControl entry={entry} data={data} />}\n </div>\n );\n}\n\n/**\n * Paging, for a table somebody might actually reach the end of. The size\n * control sits on the left whether or not there is a second page; \"Last\"\n * and the page box appear only when the total is a real count.\n *\n * The controls say where the reader asked to be (`state.page`), at once;\n * the rows follow when they land. Every move is a refinement (core.js\n * `refine`): the room is re-asked in place rather than started over.\n */\nfunction Pager({ entry, data, at, range = false }: { entry: TableEntry; data: TableViewProps['data']; at: PageAt; range?: boolean }) {\n if (data.total === 0 && state.page === 0) return null;\n const app = shell().inApp();\n // A query that names its own limit defines the whole result.\n if (explicitLimit(entry.query)) return app ? null : <div className=\"pager\" />;\n const size = pageSize();\n const shown = state.page * size + data.rows.length;\n /* An estimated total cannot decide whether there is a next page; a full\n page returned is the honest signal. */\n const full = data.rows.length >= size;\n const total = data.total;\n // A bounded total says \"at least\", which cannot name the last page either.\n const counted = data.exactTotal !== false && !data.cappedTotal && typeof total === 'number';\n const more = counted ? total > shown : full;\n const lastPage = counted ? Math.max(0, Math.ceil(total / size) - 1) : null;\n /* An App's list that fits one page draws no pager at all: twelve rows\n under \"« First ← Previous Page [1] of 1 Next → Last »\" was five\n controls that could do nothing. */\n if (app && state.page === 0 && !more) return null;\n /* Next, Previous and Last step from the rows on screen (pageStep.ts), so a\n deep page is read by key and costs what the first does; a number typed\n in the box, and First, are read by offset. */\n const list = stepList((state as { activeConnection?: string }).activeConnection ?? '', entry.table, entry.query, size);\n const goTo = (page: number, how?: 'next' | 'previous' | 'last') => {\n const wanted = Math.max(0, lastPage === null ? page : Math.min(page, lastPage));\n if (wanted === state.page) return;\n /* Only the page the pager is on can be stepped from: while the next one\n is fetched the rows on screen are the last answer's, and a second\n click would step from them to the page already being read. */\n const bounds = at.page === state.page && at.size === size ? data.bounds : undefined;\n if (how === 'last' && counted) takePageStep(list, wanted, { end: true }, total! - wanted * size);\n else if (how === 'next' && bounds) takePageStep(list, wanted, { after: bounds.last });\n else if (how === 'previous' && bounds && wanted > 0) takePageStep(list, wanted, { before: bounds.first });\n else takePageStep(list, wanted);\n refine(() => {\n state.page = wanted;\n render();\n });\n };\n const step = (text: string, label: string, to: number, enabled: boolean, how?: 'next' | 'previous' | 'last') => (\n <button type=\"button\" className=\"step-button\" aria-label={label} disabled={!enabled} onClick={() => goTo(to, how)}>\n {how !== 'next' && how !== 'last' && <Icon name=\"caret-left\" size={16} />}\n <span className=\"step-label\">{text}</span>\n {(how === 'next' || how === 'last') && <Icon name=\"caret-right\" size={16} />}\n </button>\n );\n const sizes = (\n <div className=\"pager-size\">\n <span>{say('rows')}</span>\n <Dropdown\n ariaLabel={say('rowsPerPage')}\n value={String(size)}\n items={(PAGE_SIZES as number[]).map((n) => ({ value: String(n), label: String(n) }))}\n onChange={(n) =>\n refine(() => {\n setPageSize(Number(n));\n render();\n })\n }\n />\n </div>\n );\n const said = data.rows.length > 0 && (\n <span className={`pager-range${app ? ' step-position' : ''}`}>\n {formatNumber(state.page * size + 1)}–{formatNumber(shown)}\n {counted ? say('common.ofTotal', { total: formatNumber(total!) }) : ''}\n </span>\n );\n /* An App's reader pages on: where they are, then Previous and Next. First,\n Last and the page box are the Workbench's, where a table is walked. */\n if (app) {\n return (\n <div className=\"pager pager-app\">\n {/* How many rows a page holds is the operator's instrument, not a buyer's. */}\n {!shell().publicVisitor() && sizes}\n <div className=\"pager-steps step-control\">\n {step(say('previous'), say('previousPage'), state.page - 1, state.page > 0, 'previous')}\n {said}\n {step(say('next'), say('nextPage'), state.page + 1, more, 'next')}\n </div>\n </div>\n );\n }\n return (\n <div className=\"pager\">\n {sizes}\n {range && said}\n <div className=\"pager-steps pager-workbench step-control\">\n {step(say('first'), say('firstPage'), 0, state.page > 0)}\n {step(say('previous'), say('previousPage'), state.page - 1, state.page > 0, 'previous')}\n {counted ? (\n <span className=\"page-label step-position\">\n <span>{say('common.page')}</span>\n <PageBox page={state.page} last={lastPage!} onGo={goTo} />\n <span>{say('ofPages', { count: formatNumber(lastPage! + 1) })}</span>\n </span>\n ) : (\n <span className=\"page-label step-position\">{say('pagePage', { page: formatNumber(state.page + 1) })}</span>\n )}\n {step(say('next'), say('nextPage'), state.page + 1, more, 'next')}\n {counted && step(say('last'), say('lastPage'), lastPage!, state.page < lastPage!, 'last')}\n </div>\n </div>\n );\n}\n\n/**\n * The page box. It used to be uncontrolled and was reset by the repaint\n * that followed every move; the pager is kept now, so the box follows the\n * page it is on. What is typed stays typed while it names no page yet (an\n * emptied box on the way to another number), and goes on leaving the box.\n */\nfunction PageBox({ page, last, onGo }: { page: number; last: number; onGo: (page: number) => void }) {\n const [typed, setTyped] = useState<string | null>(null);\n return (\n <input\n className=\"page-input\"\n type=\"number\"\n min={1}\n max={last + 1}\n value={typed ?? String(page + 1)}\n aria-label={say('pageNumber')}\n onBlur={() => setTyped(null)}\n onChange={(e) => {\n const text = e.target.value;\n if (text === '') {\n setTyped('');\n return;\n }\n setTyped(null);\n const asked = Number(text);\n if (Number.isFinite(asked)) onGo(Math.round(asked) - 1);\n }}\n />\n );\n}\n\nexport function TableView({\n entry,\n data,\n chrome,\n interactive,\n hide,\n labels,\n referenceLabels,\n totals,\n density,\n rowActions,\n editable,\n inCrumbs,\n sizing,\n export: exportOn = true,\n summaries = false,\n embedded = false,\n presentation,\n present,\n actions,\n listLabel,\n order,\n recordNavigation = false,\n at: given,\n busy = false,\n}: TableViewProps) {\n /* Records or table: how a narrow screen shows the rows, the reader's pick. The page's own list draws the switch at\n the end of its control strip (AppList), beside the tabs; anywhere else, over the rows. */\n const [layout, setLayout] = useState('records');\n const { controls } = useCrumbSlots();\n const presentationSwitch = (element: ReactNode) => (inCrumbs && controls ? createPortal(element, controls) : element);\n const table = findTable(data.table) as TableMeta | undefined;\n /* The cells this reader may edit in place: the view's `editable` over the\n columns drawn, each still asked of the row (canEditRow) when drawn. */\n const shownColumns = (data.columns ?? []).filter((name) => !hide?.includes(name));\n const cells = interactive && !embedded && !presentation ? editableCells(table, editable, shownColumns) : new Map<string, string>();\n /* A dashboard's list that works as its room (embedded, interactive) offers its selection's \"Set field…\"\n over the same columns, and edits no cell in place: a dashboard is not where a cell is typed into. */\n const editing = [...new Set((interactive && embedded && !presentation ? editableCells(table, editable, shownColumns) : cells).values())];\n const cellsKey = [...cells].join('\\n');\n const editorHere = useArrived(GridCellEdit, cells.size > 0);\n /* The shell's marks in empty cells (a suggestion waiting on one); the slot is the shell's for its whole life, so the hook's place is fixed. */\n const adornCell = shell().slots.useCellMarks?.(table, data?.rows ?? []);\n const editCell = useMemo(() => {\n if (!table || !cells.size || !editorHere) return undefined;\n return (row: Record<string, unknown>, drawn: string, draw: CellDraw, drawnLabel?: unknown) => {\n const column = cells.get(drawn);\n const key = keyOf(table, row) as Record<string, unknown> | null;\n const meta = column === undefined ? undefined : table.columns.find((c) => c.name === column);\n // A reference drawn by name is edited only when its key rode along with the row (appListModel's showClause).\n if (!key || !meta || !Object.hasOwn(row, meta.name) || !canEditRow(table, key)) return undefined;\n /* The name the cell already says — its label, or the path it draws by name — so the editor opens on it. */\n const named = drawn !== meta.name ? row[drawn] : drawnLabel;\n return (\n <GridCellEdit\n table={table}\n row={row}\n column={meta}\n recordKey={key}\n draw={draw}\n byName={drawn !== meta.name}\n {...(named === null || named === undefined || named === '' ? {} : { valueLabel: String(named) })}\n />\n );\n };\n }, [table, cellsKey, editorHere]); // eslint-disable-line react-hooks/exhaustive-deps\n const at = given ?? { page: state.page, size: pageSize() as number };\n /* Beside a split's detail pane the grid keeps to its width, as an embedded one does. */\n const beside = useContext(BesideDetail);\n const hasSummaries =\n (summaries || embedded) &&\n table &&\n data.rows.length > 0 &&\n primaryKey(table).length > 0 &&\n primaryKey(table).every((c: string) => data.columns?.includes(c));\n /* Records and Table are a choice only where the table says more than the records do; a list whose records say it all\n has one reading, and two tabs for it are a decision with nothing to decide. */\n const choice =\n hasSummaries &&\n tableSaysMore(\n table,\n (data.columns ?? []).filter((name: string) => !hide?.includes(name)),\n data.rows,\n entry.query,\n referenceLabels,\n );\n const firstRow = explicitLimit(currentEntry()?.query ?? '') ? 0 : at.page * at.size;\n /* A new page is read from its top. When every page was a repaint the room\n emptied while the next one loaded and the pane fell back to the top by\n itself; the room is kept now, so the head is brought back into view on\n purpose, once the new page has landed and only if it had scrolled away.\n Not for a sort: the header under the pointer is where the reader is. */\n const head = useRef<HTMLDivElement>(null);\n const turned = useRef(`${at.page}:${at.size}`);\n useEffect(() => {\n const now = `${at.page}:${at.size}`;\n if (turned.current === now) return;\n turned.current = now;\n head.current?.scrollIntoView({ block: 'nearest' });\n }, [at.page, at.size]);\n /* A presentation stands in for the grid only when the answer carries every\n column it reads; an advanced query that dropped one keeps the grid. */\n /* The list these rows are a page of, for every presentation of it: a\n record opened from the grid, a card, a queue or a checklist steps past\n the page with the same question (recordTrail.ts). A query that names its\n own limit is the whole list, so no page follows this one. */\n const list = explicitLimit(entry.query) ? undefined : trailListFor(entry.query, data);\n /* The record beside this list — a split's detail — marked in it and kept\n in view while J and K step (Rooms.tsx). */\n const top = currentEntry() as { kind?: string; table?: string; key?: Record<string, unknown> } | undefined;\n const current = top?.kind === 'row' && top.table === entry.table ? top.key : undefined;\n /* A view's hand order is live only while the question reads in it — its\n sort is that column, ascending, and nothing else. A header, a tab's own\n sort or the Sort menu reads the rows another way, and the handles go\n until the order is back. */\n const listOrder: ListOrder | undefined = order\n ? {\n column: order,\n active: sortCount(entry.query) === 1 && sortDirection(entry.query, order) === 'asc',\n partial: at.page > 0 || (typeof data.total === 'number' ? data.total > data.rows.length : data.rows.length >= at.size),\n }\n : undefined;\n const presented =\n presentation && present\n ? present({\n presentation,\n table,\n data,\n entry,\n actions,\n listLabel,\n referenceLabels,\n interactive,\n recordNavigation,\n list,\n current,\n order: listOrder,\n at,\n })\n : null;\n if (presented?.whole) return presented.element;\n if (presented)\n return (\n <>\n {data.rows.length ? presented.element : <p className=\"checklist-empty\">{say('nothingHereRightNow')}</p>}\n {chrome && data.rows.length > 0 && (\n <p className=\"checklist-count\">\n {typeof data.total === 'number' && data.exactTotal !== false && data.total > data.rows.length\n ? say('shownOfTotal', { shown: data.rows.length, total: `${data.total}${data.cappedTotal ? '+' : ''}` })\n : say('shown', { rowsCount: data.rows.length })}\n </p>\n )}\n {/* An App's cards, queue or checklist page as its grid does: they drew\n the first twenty of fifty-five cars and no way to the rest. A board\n reads its lanes whole (BoardList), so it has no page to turn. */}\n {presented.pages && (chrome ? state.page > 0 || data.rows.length >= pageSize() : shell().inApp()) && (\n <Pager entry={entry} data={data} at={at} />\n )}\n </>\n );\n /* The grid, then what decorates its rows from outside: a checkbox in the\n leading cell for a reader offered bulk actions, a grip there for a view\n kept in hand order, a ⋯ at the end of each row when the view asks for\n row menus. */\n const gridOf = (rows: typeof data.rows) => (\n <Grid\n table={table}\n data={rows === data.rows ? data : { ...data, rows }}\n hide={hide}\n labels={labels}\n referenceLabels={referenceLabels}\n totals={totals}\n density={density}\n sizing={sizing}\n interactive={interactive}\n firstRow={firstRow}\n list={list}\n current={current}\n dropColumns={embedded || beside}\n editCell={editCell}\n {...(adornCell ? { adornCell } : {})}\n />\n );\n const hasOrder = Boolean(listOrder && table);\n const ordered =\n hasOrder && listOrder && table ? (\n <GridOrder table={table} rows={data.rows} order={listOrder} interactive={interactive}>\n {gridOf}\n </GridOrder>\n ) : (\n gridOf(data.rows)\n );\n const selected =\n table && selectableGrid(table, actions ?? [], interactive, editing) ? (\n <RowHosts>\n <GridSelection table={table} rows={data.rows} actions={actions ?? []} interactive={interactive} editable={editing} />\n {ordered}\n </RowHosts>\n ) : !hasOrder ? (\n ordered\n ) : (\n <RowHosts>{ordered}</RowHosts>\n );\n // A row's menu draws what the record's bar draws, so an action kept out of it (`header: false`) is no reason for a ⋯.\n const tableGrid =\n rowActions && (interactive || embedded) && table && actions?.some((action) => action.header !== false) && primaryKey(table).length ? (\n <RowTrailHosts>\n <RowActions table={table} rows={data.rows} actions={actions} onDone={() => render()} />\n {selected}\n </RowTrailHosts>\n ) : (\n selected\n );\n return (\n <>\n <ResultHead\n entry={entry}\n data={data}\n chrome={chrome}\n interactive={interactive}\n exportOn={exportOn}\n at={at}\n headRef={head}\n inCrumbs={inCrumbs}\n />\n <div className={hasSummaries ? `responsive-results show-${embedded || !choice ? 'records' : layout}` : undefined}>\n {hasSummaries && (\n <>\n {!embedded &&\n choice &&\n presentationSwitch(\n <PresentationSwitch\n layout={layout}\n onChange={setLayout}\n label={say('common.listPresentation')}\n records={say('common.records')}\n table={say('common.table')}\n />,\n )}\n {/* A reference says its record's name here too, as the grid beside it does. */}\n <RecordSummaries\n table={table}\n data={data}\n columns={(data.columns ?? []).filter((name) => !hide?.includes(name))}\n labels={labels}\n referenceLabels={referenceLabels}\n list={list}\n query={entry.query}\n {...(adornCell ? { adornFact: (row: Record<string, unknown>, column: string) => adornCell(row, column, 'summary') } : {})}\n />\n </>\n )}\n <div className=\"result-table\" aria-busy={busy || undefined}>\n {tableGrid}\n </div>\n </div>\n <Pager entry={entry} data={data} at={at} range={inCrumbs} />\n </>\n );\n}\n","/** What TableRoom says, in the lists and grid room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n fixTheQueryAbove: 'Fix the query above to see results.',\n notAvailableToYou: 'This {thing} is not available to your role.',\n notAvailableHere: 'This {thing} is not available.',\n signInToSeeThis: 'This {thing} is for signed-in members.',\n thingList: 'list',\n thingRecord: 'record',\n thingPage: 'page',\n storedDefinition: 'Stored definition. ',\n thisIsTheStatement: 'This is the statement the database itself keeps, verbatim.',\n rebuiltFromTheCatalog: 'Rebuilt from the catalog. Indexes, checks and triggers are not shown.',\n});\n","/**\n * The table view as a room: the fetch, what it touches, and the components\n * that draw the answer.\n *\n * The request is a Query keyed by everything that changes the answer — the\n * connection, the table, the line, the page and its size — so a reply that\n * outlived its question never paints: the key it was fetched under is no\n * longer the one on screen. The room owns that result. A page, a page size\n * or a header's sort or filter is a refinement (core.js `refine`): the room\n * stays mounted, the key moves, and the previous answer stays on screen\n * until the next lands, so the grid re-renders in place and whatever lives\n * in its rows keeps its state. Nothing is kept between visits (`gcTime: 0`):\n * any other paint starts the room over and re-asks, the way it always was,\n * and a write that repaints the room sees its own effect.\n *\n * With `chrome` the room is the explorer's own — the tabs, the filter\n * boxes, the query bar's text, and the globals a shared result touches:\n * the nested cache, the error banner, the SQL pane, the history. Off, it\n * is a grid embedded in someone else's surface — an app list, a dashboard\n * section, a page's chooser — and touches nothing but its own box.\n */\nimport { useEffect, type ReactNode } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { $, api, columnLabel, findTable, go, pageSize, setExplain, showErrors, state, tableView } from '../core.js';\nimport { explicitLimit } from '../clauses.js';\nimport { deriveFilterNames } from '../filterbar.js';\nimport { recordQuery } from '../history.js';\nimport { resetNested } from '../nested.js';\nimport { canUseDatabaseTools } from '../connectionScope.js';\nimport { shell } from '../shellMode.js';\nimport { appKeepsRoles } from '../roleLabels.js';\nimport { arrivedPlacement } from '../addressMount.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport type { ResourceClientReply, ResourceHttpSuccess } from '@mistriwork/engine/shared/resourceHttp.js';\nimport { onDemand, useArrived } from './onDemand.js';\nimport { FilterBar } from './FilterBoxes.js';\nimport { Delayed, GridSkeleton } from './Skeleton.js';\nimport { Problem, Refused } from './Notes.js';\nimport type { GridData } from './Grid.js';\nimport { GridCellEdit, isApiConnection, TableView, ViewTabs, type PageAt, type TableEntry, type TableViewProps } from './TableView.js';\nimport { pageStepFor, stepList } from './pageStep.js';\nimport { ExportHold } from './ExportHold.js';\nimport { batchedRun } from '../breakdownBatch.js';\nimport { useListHold } from '../liveState.js';\nimport { say } from '../copy/lists/components/TableRoom.js';\n\n/* The diagrams are a chunk of their own, loaded when the Diagram tab is first opened. */\n/**\n * A list this reader's catalog leaves out. Signed in, the role is the reason.\n * Signed out of an App the public browses, the list may well be a member's:\n * the refusal offers the sign-in, drawn in place so the visitor comes back to\n * this address once signed in (the shell's `signInHere`, publicSurface.js). A visitor on a\n * tenant's public address keeps the top bar's door, which leaves that address\n * behind on purpose (app.js, showAccount).\n */\nfunction NotYours({ thing }: { thing: string }) {\n const app = state.activeConnection;\n const noun = { thing };\n // An App with no roles has none to blame: the list is simply not one this address names.\n if (!shell().publicVisitor()) return <Refused text={say(appKeepsRoles() ? 'notAvailableToYou' : 'notAvailableHere', noun)} />;\n // Signed out, no role is the reason, wherever the door is.\n if (typeof app !== 'string' || arrivedPlacement()) return <Refused text={say('signInToSeeThis', noun)} />;\n return (\n <Refused\n text={say('signInToSeeThis', noun)}\n action={\n <button type=\"button\" className=\"ghost\" onClick={() => shell().signInHere(app)}>\n {say('common.signIn')}\n </button>\n }\n />\n );\n}\n\nconst NeighbourhoodDiagram = onDemand(() => import('./Diagram.js'), 'NeighbourhoodDiagram');\n/* An API's documented reads, tried from here: only a connection to an API has the tab. */\n/* The pill over a list that is held (liveState.ts): a part of its own, fetched when the first change is held. */\nconst LivePill = onDemand(() => import('./LiveNotices.js'), 'LivePill', { quiet: true });\nconst ApiOperations = onDemand(() => import('./ApiOperations.js'), 'ApiOperations');\n\ntype RunData = ResourceHttpSuccess<'/api/run'>;\n\ninterface TableRoomProps {\n empty?: ReactNode;\n presentation?: TableViewProps['presentation'];\n /** What draws `presentation` (TableView.tsx): the App's, which its lists hand down. */\n present?: TableViewProps['present'];\n /** The entry's fixed actions; a queue offers the bulk ones, a board its lane moves. */\n actions?: TableViewProps['actions'];\n /** The entry's label, the accessible name a presentation goes by. */\n listLabel?: string;\n /** The view's hand-order column, where it keeps one. */\n order?: string;\n /** A read-only card may still be a doorway to its record. */\n recordNavigation?: boolean;\n sizing?: TableViewProps['sizing'];\n entry: TableEntry;\n /** The explorer's own view: tabs, boxes, the query bar, the shared globals. Default on. */\n chrome?: boolean;\n /** A gutter on both sides; embedded grids sit in sections that already pad. Defaults to `chrome`. */\n inset?: boolean;\n interactive?: boolean;\n hide?: string[];\n labels?: Record<string, string>;\n /** A reference column → the fetched path its record's name is read from (appListModel's referenceNames). */\n referenceLabels?: Record<string, string>;\n /** Column → its total over the whole query; undefined while it is asked. */\n totals?: Record<string, unknown>;\n density?: 'comfortable' | 'compact';\n /** A ⋯ menu at the end of each row with the record's own actions. */\n rowActions?: boolean;\n /** The view's `editable`: cells edited in place and the selection's \"Set field…\". */\n editable?: true | string[];\n /** The page's own list: its verbs go to the crumb bar and its range to the pager. */\n inCrumbs?: boolean;\n export?: boolean;\n summaries?: boolean;\n /** Drawn inside another room (a dashboard's section): see TableViewProps.embedded. */\n embedded?: boolean;\n /** Re-asked when this changes — a dashboard's refresh clock. */\n version?: number;\n /** The answer, once it has rows and columns. */\n onResult?: (data: RunData) => void;\n}\n\n/** The noun a refused room is: a record when the address names one, a list over a table the reader's catalog has,\n and a page for whatever else (the catalog leaves out what the role cannot see, so its kind is not known). */\nconst thingOf = (entry: TableEntry, table: TableMeta | undefined): string => {\n const { kind, table: named } = entry as { kind?: string; table?: string };\n return kind === 'row' || (kind === 'page' && named) ? say('thingRecord') : table ? say('thingList') : say('thingPage');\n};\n\nconst connection = () => (state as { activeConnection?: string }).activeConnection ?? '';\n\nexport function TableRoom({\n entry,\n chrome = true,\n inset = chrome,\n interactive = true,\n hide,\n labels,\n referenceLabels,\n totals,\n density,\n rowActions,\n editable,\n inCrumbs,\n sizing,\n export: exportOn = true,\n summaries = false,\n embedded = false,\n version = 0,\n onResult,\n presentation,\n present,\n actions,\n listLabel,\n order,\n recordNavigation = false,\n empty,\n}: TableRoomProps) {\n /* A tab this reader cannot have here falls back to Rows: Definition and API\n are the operator's, API only over an API, and an API's definition is its\n description, so it has no Definition tab. */\n const wanted = entry.tab ?? 'rows';\n const overApi = isApiConnection();\n const tab =\n (wanted === 'ddl' || wanted === 'api') && !canUseDatabaseTools()\n ? 'rows'\n : (wanted === 'api' && !overApi) || (wanted === 'ddl' && overApi)\n ? 'rows'\n : wanted;\n /* Only the explorer's own table view owns the query bar. Chrome off means\n an app list or an embedded chooser: their entry is synthetic, and a bar\n showing a query the walk is not on is the bar lying about where you are. */\n useEffect(() => {\n if (!chrome) return;\n const bar = $('query') as HTMLInputElement | null;\n if (bar) bar.value = entry.query;\n }, [chrome, entry.query]);\n return (\n <>\n {chrome && (\n <div className=\"grid-host\">\n <ViewTabs entry={entry} />\n </div>\n )}\n {/* Keyed by the line: the boxes hold what was typed and not yet sent, and\n a header's filter that changed the line under them starts them over,\n as the repaint it used to be did. A page keeps them. */}\n {chrome && tab === 'rows' && <FilterSection key={entry.query} entry={entry} />}\n <div className={inset ? 'grid-inset' : undefined}>\n {tab === 'diagram' ? (\n <div className=\"panel-pad\">\n <div className=\"diagram\">\n <NeighbourhoodDiagram tableId={entry.table} />\n </div>\n </div>\n ) : tab === 'api' ? (\n <ApiOperations table={entry.table} />\n ) : tab === 'ddl' ? (\n <DdlPane table={entry.table} />\n ) : (\n <Rows\n entry={entry}\n chrome={chrome}\n interactive={interactive}\n hide={hide}\n labels={labels}\n referenceLabels={referenceLabels}\n totals={totals}\n density={density}\n rowActions={rowActions}\n editable={editable}\n inCrumbs={inCrumbs}\n sizing={sizing}\n exportOn={exportOn}\n summaries={summaries}\n embedded={embedded}\n version={version}\n onResult={onResult}\n presentation={presentation}\n present={present}\n actions={actions}\n listLabel={listLabel}\n order={order}\n recordNavigation={recordNavigation}\n empty={empty}\n />\n )}\n </div>\n </>\n );\n}\n\nconst escaped = (text: string) => text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/**\n * A refusal in the reader's words. An API's refusal quotes columns as the API\n * names them (`carrier_id`) and lists which (`columns`); an App calls them by\n * its captions (\"Carrier\"). Only the listed names are swapped, as whole words,\n * and never inside a documented sort value such as `-created_at`. Outside an\n * App there are no captions, and the message stays as it is.\n */\nexport function inCaptions(error: unknown, table: TableMeta | undefined): string {\n const message = (error as Error).message;\n const columns = (error as { columns?: unknown }).columns;\n if (!table || !Array.isArray(columns)) return message;\n return columns.reduce<string>((text, name) => {\n const caption = typeof name === 'string' ? columnLabel(table.id, name) : null;\n return caption && caption !== name ? text.replace(new RegExp(`(?<![\\\\w+-])${escaped(name)}(?![\\\\w:])`, 'g'), () => caption) : text;\n }, message);\n}\n\n/**\n * The named filter boxes over a table (components/FilterBoxes.tsx), in a host\n * that takes no room. Standing alone a new question goes to the walk;\n * embedded (a rootless page's chooser) the host says where it goes.\n */\nexport function FilterSection({ entry, names, navigate }: { entry: TableEntry; names?: string[]; navigate?: (query: string) => void }) {\n const table = findTable(entry.table) as TableMeta | undefined;\n if (!table) return null;\n const chosen = names ?? (deriveFilterNames(table) as string[]);\n if (!chosen.length) return null;\n const to = navigate ?? ((query: string) => go(tableView(entry.table, query, entry.tab), 'replace'));\n return (\n <div className=\"host-contents\">\n <FilterBar table={table} entry={entry} names={chosen} navigate={to} />\n </div>\n );\n}\n\n/* The page each answer was asked for, by the answer. While the next page is\n fetched the previous answer is what is on screen, and the head's range and\n the keyboard's row numbers describe the rows that are there. */\nconst askedFor = new WeakMap<object, PageAt>();\n\n/* A list's total, by the question and not the page: turning a page asks for\n rows only (`count: 'none'`) and says the total the list already has. It\n was recounted on every page turn — the offset is in the rows' key — and\n a filtered total is most of a filtered read's time. The key carries the\n room's version, so a write that could change the total recounts it; page\n one always counts, so going back to the start refreshes it. */\ntype Totals = Pick<GridData, 'total' | 'exactTotal' | 'cappedTotal'>;\nconst listTotals = new Map<string, Totals>();\nconst TOTALS_KEPT = 50;\nfunction keepTotal(key: string, reply: unknown): void {\n if (!reply || typeof reply !== 'object' || !('ms' in reply)) return;\n const { total, exactTotal, cappedTotal } = reply as Totals;\n if (typeof total !== 'number') return;\n listTotals.delete(key);\n if (listTotals.size >= TOTALS_KEPT) listTotals.delete(listTotals.keys().next().value!);\n listTotals.set(key, { total, ...(exactTotal !== undefined ? { exactTotal } : {}), ...(cappedTotal ? { cappedTotal } : {}) });\n}\n\nfunction Rows({\n entry,\n chrome,\n interactive,\n hide,\n labels,\n referenceLabels,\n totals,\n density,\n rowActions,\n editable,\n inCrumbs,\n sizing,\n exportOn,\n summaries,\n embedded,\n version,\n onResult,\n presentation,\n present,\n actions,\n listLabel,\n order,\n recordNavigation,\n empty,\n}: {\n empty?: ReactNode;\n embedded: boolean;\n presentation?: TableViewProps['presentation'];\n present?: TableViewProps['present'];\n actions?: TableViewProps['actions'];\n listLabel?: string;\n order?: string;\n recordNavigation: boolean;\n sizing?: TableViewProps['sizing'];\n entry: TableEntry;\n chrome: boolean;\n interactive: boolean;\n hide?: string[];\n labels?: Record<string, string>;\n referenceLabels?: Record<string, string>;\n totals?: Record<string, unknown>;\n density?: 'comfortable' | 'compact';\n rowActions?: boolean;\n editable?: true | string[];\n inCrumbs?: boolean;\n exportOn: boolean;\n summaries: boolean;\n version: number;\n onResult?: (data: RunData) => void;\n}) {\n const table = findTable(entry.table) as TableMeta | undefined;\n /* An explicit `limit` in the query is a deliberate statement and beats the page size. */\n const asked = explicitLimit(entry.query) as number | null;\n const size = pageSize() as number;\n const page = (state as { page: number }).page;\n const source = connection();\n /* A page the pager stepped to is read by key, the end with its own length (pageStep.ts). */\n const step = asked ? undefined : pageStepFor(stepList(source, entry.table, entry.query, size), page);\n const limit = asked ?? step?.limit ?? size;\n const offset = asked ? 0 : page * size;\n const exact = entry.exactCount === true;\n const run = useQuery<ResourceClientReply<'/api/run'>>({\n queryKey: ['run', source, entry.table, entry.query, limit, offset, exact, version, step?.body],\n queryFn: async () => {\n const totalKey = JSON.stringify([source, entry.table, entry.query, exact, version]);\n const known = offset > 0 ? listTotals.get(totalKey) : undefined;\n const asked = { q: entry.query, limit, offset, exactCount: exact, ...(known ? { count: 'none' as const } : {}) };\n /* A table on a dashboard is asked with the dashboard's other sections,\n in one request (breakdownBatch.ts); a room's own list, and a page\n stepped to by key, are asked alone. */\n const answer: ResourceClientReply<'/api/run'> =\n embedded && !step ? await batchedRun<ResourceClientReply<'/api/run'>>(asked) : await api('/api/run', { ...asked, ...step?.body });\n const reply = (\n known && answer && typeof answer === 'object' && 'ms' in answer ? { ...answer, ...known } : answer\n ) as ResourceClientReply<'/api/run'>;\n if (!known) keepTotal(totalKey, reply);\n if (reply && typeof reply === 'object') askedFor.set(reply, { page, size });\n return reply;\n },\n staleTime: 0,\n gcTime: 0,\n /* The previous answer stays while the next is fetched, but only an\n answer about this table from this connection: rows of another table\n under this one's header would be a lie, however brief. */\n placeholderData: (previous, previousQuery) =>\n previousQuery?.queryKey[1] === source && previousQuery.queryKey[2] === entry.table ? previous : undefined,\n });\n const data = run.data;\n /* A list its reader is working in is held still when another person's change would redraw it, and says so in a pill\n (liveState.ts); a table on a dashboard or a short related list never is. */\n const held = useListHold(\n embedded || limit <= 5\n ? undefined\n : {\n table: entry.table,\n owns: (key) => key[0] === 'run' && key[1] === source && key[2] === entry.table && key[3] === entry.query,\n },\n );\n /* A list that edits in place waits for its cells' editor beside its rows (TableView.tsx). */\n const edits = Boolean(editable) && interactive && !embedded && !presentation;\n const editorHere = useArrived(GridCellEdit, edits);\n useEffect(() => {\n if (!data) return;\n if (chrome) {\n resetNested();\n showErrors(data.errors ?? []);\n setExplain('explain' in data ? data.explain : undefined);\n }\n if (!('ms' in data)) return;\n /* Recorded here rather than at submit: this is the point where the query\n is known to have compiled and run. Only queries a person typed. */\n if (chrome) recordQuery(entry.query);\n onResult?.(data);\n }, [data]); // eslint-disable-line react-hooks/exhaustive-deps\n\n /* A signed-out visitor asking past what the App opens to the public is asked to sign in (401), whether the table\n is a member's or no table at all: offered in place. */\n if (run.isError && (run.error as { code?: string }).code === 'members_only' && !chrome) return <NotYours thing={thingOf(entry, table)} />;\n /* An App's list that could not be read says so as every place does (Notes.tsx): the warn mark, the sentence and Try\n again on the list's edge. A bare grey line was a dead end only a reload got out of. The Workbench keeps its note\n under the query bar it can fix the question in. */\n if (run.isError)\n return chrome ? (\n <p className=\"note\">{inCaptions(run.error, table)}</p>\n ) : (\n <div className=\"list-problem\">\n <Problem text={inCaptions(run.error, table)} />\n </div>\n );\n /* Shaped like the grid that is about to replace it, and only if the query\n takes long enough to be worth acknowledging. */\n if (!data || (edits && !editorHere))\n return (\n <>\n {inCrumbs && exportOn && !presentation && <ExportHold />}\n <Delayed>\n <div className=\"host-contents\">\n <GridSkeleton columns={Math.max((table?.columns.length ?? 5) - (hide?.length ?? 0), 1)} rows={limit} />\n </div>\n </Delayed>\n </>\n );\n /* An App's list over a table the role cannot read is answered \"No table called ...\" (the catalog it sees leaves the table out):\n there is no query bar to fix, only a list that is not this reader's. */\n if (!('ms' in data))\n return !chrome && !table ? <NotYours thing={thingOf(entry, table)} /> : <p className=\"note\">{say('fixTheQueryAbove')}</p>;\n /* Not over a question that failed: its error says why there are no rows. */\n if (empty && !run.isPlaceholderData && data.rows.length === 0 && page === 0 && !data.errors?.length) return <>{empty}</>;\n return (\n <>\n {held.held ? <LivePill held={held.held} show={held.show} /> : null}\n <TableView\n entry={entry}\n data={data}\n chrome={chrome}\n interactive={interactive}\n hide={hide}\n labels={labels}\n referenceLabels={referenceLabels}\n totals={totals}\n density={density}\n rowActions={rowActions}\n editable={editable}\n inCrumbs={inCrumbs}\n sizing={sizing}\n export={exportOn}\n summaries={summaries}\n embedded={embedded}\n presentation={presentation}\n present={present}\n actions={actions}\n listLabel={listLabel}\n order={order}\n recordNavigation={recordNavigation}\n at={askedFor.get(data) ?? { page, size }}\n busy={run.isPlaceholderData}\n />\n </>\n );\n}\n\n/** The table's definition: the statement the database keeps, or one rebuilt from its catalog. */\nfunction DdlPane({ table }: { table: string }) {\n const ddl = useQuery<{ sql: string; exact: boolean }>({\n queryKey: ['ddl', connection(), table],\n queryFn: () => api(`/api/ddl?table=${encodeURIComponent(table)}`),\n });\n if (ddl.isError) return <p className=\"note\">{(ddl.error as Error).message}</p>;\n if (!ddl.data)\n return (\n <Delayed>\n <div className=\"host-contents\">\n <GridSkeleton columns={2} rows={6} />\n </div>\n </Delayed>\n );\n return (\n <>\n <p className=\"ddl-note\">\n <strong>{ddl.data.exact ? say('storedDefinition') : 'Reconstructed. '}</strong>\n {ddl.data.exact ? say('thisIsTheStatement') : say('rebuiltFromTheCatalog')}\n </p>\n <pre className=\"ddl\">{ddl.data.sql}</pre>\n </>\n );\n}\n","/** What Funnel says, in the dashboards 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 summary: '{count} stages from {first} to {last}',\n ofBasis: '{share} of {basis}',\n dropped: '−{figure}',\n droppedTitle: '{figure} reached {basis} and stopped before {stage}',\n optional: 'Optional',\n openReached: 'Open the {table} that reached {stage}',\n openDropped: 'Open the {table} that stopped before {stage}',\n});\n","/**\n * A funnel section (`funnel()`): the rows of one table that reach each of its stages, in order. Every stage is a bar\n * against the first stage's length, its count, and its share of the stage it follows (\"62% of Qualified\") with the rows\n * it lost beside it (\"−12\"). An optional stage is a side road: marked, and a share of the last stage that is required.\n *\n * Presentational: the counts come from one statement (shared/funnel.ts, funnelText), so a later stage can never be\n * longer than the one before it. The stages' names are known before the counts arrive, so the list holds its height\n * while it loads and nothing moves when the figures land (docs/design.md, layout shift).\n */\nimport type { ReactNode } from 'react';\nimport { say as sayCopy } from '../copy/dashboards/components/Funnel.js';\nimport { formatPercent } from '@mistriwork/kit/client/locale.js';\nimport type { ViewLink } from '@mistriwork/kit/client/components/viewLink.js';\nimport './Funnel.css';\n\n/** Where a figure goes: a link where the address is a list's, else a button that walks there. */\nexport interface FunnelDoor {\n link?: ViewLink;\n open?: () => void;\n}\n\nexport interface FunnelStep {\n title: string;\n optional?: boolean;\n /** Absent while the answer is on its way. */\n count?: number;\n /** The stage this one is a share of (the last required stage before it), absent on the first. */\n basis: number | null;\n reached?: FunnelDoor;\n dropped?: FunnelDoor;\n}\n\nfunction Door({ door, className, title, children }: { door?: FunnelDoor; className: string; title: string; children: ReactNode }) {\n if (door?.link)\n return (\n <a className={`${className} dash-funnel-door`} href={door.link.href} title={title} onClick={door.link.onClick}>\n {children}\n </a>\n );\n if (door?.open)\n return (\n <button type=\"button\" className={`${className} dash-funnel-door`} title={title} onClick={door.open}>\n {children}\n </button>\n );\n return <div className={className}>{children}</div>;\n}\n\nexport function Funnel({\n steps,\n say,\n table,\n label,\n}: {\n steps: FunnelStep[];\n /** How a count is said (the section's figure rule). */\n say: (value: unknown) => string;\n table: string;\n label?: string;\n}) {\n const ready = steps.every((step) => step.count !== undefined);\n const first = steps[0]?.count || Math.max(0, ...steps.map((step) => step.count ?? 0)) || 1;\n return (\n <div className=\"dash-funnel-host\">\n <ol\n className=\"dash-funnel\"\n aria-busy={!ready || undefined}\n aria-label={\n label ?? sayCopy('summary', { count: steps.length, first: steps[0]?.title ?? '', last: steps[steps.length - 1]?.title ?? '' })\n }\n >\n {steps.map((step, i) => {\n const basis = step.basis === null ? undefined : steps[step.basis];\n const share = basis?.count ? (step.count ?? 0) / basis.count : undefined;\n const lost =\n basis && step.count !== undefined && basis.count !== undefined && !step.optional ? basis.count - step.count : undefined;\n const width = step.count === undefined ? 0 : Math.max(2, Math.min(100, (step.count / first) * 100));\n return (\n <li key={i} className={`dash-funnel-step${step.optional ? ' is-optional' : ''}`}>\n <Door door={step.reached} className=\"dash-funnel-main\" title={sayCopy('openReached', { table, stage: step.title })}>\n <span className=\"dash-funnel-name\">\n {step.title}\n {step.optional && <span className=\"dash-funnel-tag\">{sayCopy('optional')}</span>}\n </span>\n <span className=\"dash-funnel-track\" aria-hidden=\"true\">\n <span className=\"dash-funnel-fill\" style={{ width: `${width}%` }} />\n </span>\n <span className=\"dash-funnel-value\">{step.count === undefined ? ' ' : say(step.count)}</span>\n <span className=\"dash-funnel-share\">\n {basis && share !== undefined && step.count !== undefined\n ? sayCopy('ofBasis', { share: formatPercent(share * 100, { maximumFractionDigits: 0 }), basis: basis.title })\n : ' '}\n </span>\n </Door>\n <Door\n door={lost ? step.dropped : undefined}\n className=\"dash-funnel-drop\"\n title={sayCopy('openDropped', { table, stage: step.title })}\n >\n {lost ? (\n <span title={basis ? sayCopy('droppedTitle', { figure: say(lost), basis: basis.title, stage: step.title }) : undefined}>\n {sayCopy('dropped', { figure: say(lost) })}\n </span>\n ) : (\n ' '\n )}\n </Door>\n </li>\n );\n })}\n </ol>\n </div>\n );\n}\n","/**\n * A dashboard's `areas`: sections placed in named areas of a grid of equal columns.\n *\n * One reading on both sides — the parser that refuses a template (appViews.ts), the lint that judges an area's\n * width (designLint.ts) and the client that draws it (components/Dashboard.tsx) — so a template means the same\n * thing wherever it is read. Pure data in, data out.\n */\nimport { nearest } from './suggest.js';\n\n/** An area's name: a lowercase word that is also a CSS identifier, since the client names the grid area with it. */\nconst AREA_NAME = /^[a-z][a-z0-9-]{0,23}$/;\n/** Words CSS reads before an area name: `grid-area: span` or `auto` is not a name. */\nconst CSS_WORDS = new Set(['auto', 'span', 'initial', 'inherit', 'unset', 'revert', 'default']);\nconst LAYOUT_MAX_ROWS = 8;\nconst LAYOUT_MAX_COLUMNS = 4;\n/** The cell that holds no area. */\nconst EMPTY_CELL = '.';\n\n/** A template as cells: `grid[row][column]` is an area's name or `.`. */\nexport type LayoutGrid = string[][];\n\n/** Whether a word may name an area. */\nexport const isAreaName = (word: string): boolean => AREA_NAME.test(word) && !CSS_WORDS.has(word);\n\n/** The rows of a template as cells. Ragged rows stay ragged: `layoutProblems` is what says so. */\nexport function layoutGrid(layout: readonly string[]): LayoutGrid {\n return layout.map((row) => row.trim().split(/\\s+/).filter(Boolean));\n}\n\n/** The areas a template names, in reading order: row by row, each at its first cell. */\nexport function layoutAreas(grid: LayoutGrid): string[] {\n const seen: string[] = [];\n for (const row of grid) for (const cell of row) if (cell !== EMPTY_CELL && !seen.includes(cell)) seen.push(cell);\n return seen;\n}\n\n/** The cells an area covers, 0-based, in reading order. */\nfunction cellsOf(grid: LayoutGrid, name: string): Array<{ row: number; column: number }> {\n const cells: Array<{ row: number; column: number }> = [];\n grid.forEach((row, r) => row.forEach((cell, c) => cell === name && cells.push({ row: r, column: c })));\n return cells;\n}\n\n/** An area's box: where it starts, and how many rows and columns it spans. Absent when the template does not name it. */\nexport function areaBox(grid: LayoutGrid, name: string): { row: number; column: number; rows: number; columns: number } | undefined {\n const cells = cellsOf(grid, name);\n if (!cells.length) return undefined;\n const rows = cells.map((cell) => cell.row);\n const columns = cells.map((cell) => cell.column);\n const row = Math.min(...rows);\n const column = Math.min(...columns);\n return { row, column, rows: Math.max(...rows) - row + 1, columns: Math.max(...columns) - column + 1 };\n}\n\nconst place = (cell: { row: number; column: number }): string => `row ${cell.row + 1} column ${cell.column + 1}`;\n\n/** \"a, b and c\". */\nconst said = (words: string[]): string =>\n words.length < 2 ? (words[0] ?? '') : `${words.slice(0, -1).join(', ')} and ${words[words.length - 1]}`;\n\n/** Whether an area's cells fill their box exactly. */\nfunction isRectangle(grid: LayoutGrid, name: string): boolean {\n const box = areaBox(grid, name);\n return !box || cellsOf(grid, name).length === box.rows * box.columns;\n}\n\n/**\n * Everything wrong with a template, in words, one pass: a template is judged whole so one run names every refusal.\n * `at` is the dashboard, as the other refusals name it.\n */\nexport function layoutProblems(layout: unknown, at: string): string[] {\n const here = `${at}, \"areas\"`;\n if (!Array.isArray(layout) || !layout.length || layout.some((row) => typeof row !== 'string')) {\n return [`${here} is not a list of rows, each a string of area names: ['kpis kpis', 'trend side'].`];\n }\n const problems: string[] = [];\n if (layout.length > LAYOUT_MAX_ROWS) problems.push(`${here} has ${layout.length} rows. At most ${LAYOUT_MAX_ROWS}.`);\n const grid = layoutGrid(layout as string[]);\n const widest = Math.max(...grid.map((row) => row.length));\n if (grid.some((row) => !row.length)) problems.push(`${here} has an empty row. Write . for a cell with nothing in it.`);\n if (widest > LAYOUT_MAX_COLUMNS)\n problems.push(\n `${here} has ${widest} columns in a row. At most ${LAYOUT_MAX_COLUMNS}: wider than that, a column is too narrow to read.`,\n );\n const counts = new Set(grid.filter((row) => row.length).map((row) => row.length));\n if (counts.size > 1) {\n problems.push(\n `${here} has rows of different lengths (${grid.map((row, i) => `row ${i + 1} has ${row.length}`).join(', ')}). Every row has the same number of cells; write . for one with nothing in it.`,\n );\n }\n for (const word of new Set(grid.flat())) {\n if (word !== EMPTY_CELL && !isAreaName(word)) {\n problems.push(\n `${here} has \"${word}\", which is not an area name. An area is a lowercase word (letters, digits and hyphens, at most 24, starting with a letter, and not ${[...CSS_WORDS].join(' or ')}); . is a cell with nothing in it.`,\n );\n }\n }\n if (problems.length) return problems;\n for (const name of layoutAreas(grid)) {\n if (isRectangle(grid, name)) continue;\n problems.push(\n `${here}: \"${name}\" is not a rectangle: it covers ${said(cellsOf(grid, name).map(place))}. An area is one block of cells; give each separate block its own name.`,\n );\n }\n return problems;\n}\n\n/**\n * The areas a layout leaves for a reader when `hidden` ones have nothing to draw: a hidden area's cells go to its left\n * neighbour in that row (the right one when it is first), and a row left with no area in it is dropped. A neighbour that\n * would stop being a rectangle by it is not given the cells, which stand empty. Pure: a template in, a template out.\n */\nexport function reflowLayout(grid: LayoutGrid, hidden: ReadonlySet<string>): LayoutGrid {\n let next = grid.map((row) => [...row]);\n for (const name of layoutAreas(grid)) {\n if (!hidden.has(name)) continue;\n const trial = next.map((row) => [...row]);\n const touched = new Set<string>();\n next.forEach((row, r) => {\n const first = row.indexOf(name);\n if (first < 0) return;\n const last = row.lastIndexOf(name);\n const neighbour = first > 0 ? row[first - 1]! : (row[last + 1] ?? EMPTY_CELL);\n for (let c = first; c <= last; c++) trial[r]![c] = neighbour;\n touched.add(neighbour);\n });\n for (const other of touched) {\n if (other !== EMPTY_CELL && !isRectangle(trial, other)) {\n trial.forEach((row, r) =>\n row.forEach((cell, c) => {\n if (cell === other && next[r]![c] === name) row[c] = EMPTY_CELL;\n }),\n );\n }\n }\n next = trial;\n }\n return next.filter((row) => row.some((cell) => cell !== EMPTY_CELL));\n}\n\n/** The template as the strings a CSS `grid-template-areas` takes: one quoted row each. */\nexport const gridTemplateAreas = (grid: LayoutGrid): string => grid.map((row) => `\"${row.join(' ')}\"`).join(' ');\n\n/** An area that no section is placed in, or a section placed in none: the nearest name for a slip. */\nexport function nearestArea(name: string, areas: readonly string[]): string | undefined {\n return nearest(name, areas);\n}\n","/**\n * The time unit a chart cuts its dates into when its author did not fix one: `chart('Signups', 'account', 'auto\n * created_at', { over: 'created_at' })`.\n *\n * A fixed unit is right for one window and wrong for the next: `day` over 34 days with three days of data drew 34\n * bars, 31 of them empty, and `day` over a year draws 365. The right unit depends on the window the reader picks and\n * on how the data falls, so `auto` is decided where both are known, on the client, before the read. It is not a SQL\n * bucket: the server never sees the word (`withUnit` writes the unit in), and the grammar's `DATE_UNITS` is unchanged.\n *\n * Two rules choose the unit, both pure so a table of cases can hold them:\n * 1. The span picks a base unit: up to 45 days a day, up to 26 weeks a week, up to 36 months a month, past that a\n * quarter.\n * 2. Where the measure can be added up again (count, sum, min, max, avg as sum over count, and arithmetic of those),\n * the base answer is coarsened locally while fewer than a third of its buckets hold data, as long as at least four\n * buckets would remain. No second read. A median cannot be added up from its parts, so it follows the span only.\n */\nimport { dateWindow } from './queryDates.js';\n\nexport type AutoUnit = 'day' | 'week' | 'month' | 'quarter';\n\n/** Finest to coarsest: the order a sparse chart steps up through. */\nconst AUTO_UNITS: readonly AutoUnit[] = ['day', 'week', 'month', 'quarter'];\n\n/** A bucket needs a third of its periods to hold data before the chart is left at the unit the span chose. */\nconst DENSE = 1 / 3;\n/** Stepping up stops before the chart is left with fewer buckets than this. */\nconst FEWEST_BUCKETS = 4;\n\n/* ---------- the word in a `by` ---------- */\n\nconst AUTO_KEY = /^auto\\s+([\\w.$+]+)(\\s+as\\s+[\\w$]+)?$/i;\n\n/** The key of a `by` written `auto <column>`, wherever it stands in the list: its place and its column. */\nexport function autoKeyOf(by: string | undefined): { index: number; column: string } | null {\n const keys = (by ?? '').split(',');\n for (const [index, key] of keys.entries()) {\n const m = AUTO_KEY.exec(key.trim());\n if (m) return { index, column: m[1] };\n }\n return null;\n}\n\n/** The `by` with its `auto` key written as the unit the chart chose, which is the word the grammar reads. */\nexport function withUnit(by: string, unit: AutoUnit): string {\n const at = autoKeyOf(by);\n if (!at) return by;\n return by\n .split(',')\n .map((key, index) => (index === at.index ? key.trim().replace(/^auto/i, unit) : key.trim()))\n .join(', ');\n}\n\n/* ---------- the span ---------- */\n\nconst DAY = 86_400_000;\n\n/**\n * The days a section's query asks about on its `over` column — `created_at = last 90 days`, `this month` — or null\n * where it sets no window the date grammar can bound (the data's own extent is then the span).\n */\nexport function spanDaysOf(query: string | undefined, over: string | undefined, now: Date): number | null {\n const phrase = windowPhraseOf(query, over);\n const window = phrase ? dateWindow(phrase, now) : undefined;\n return window ? Math.max(1, Math.round((window.end.getTime() - window.start.getTime()) / DAY)) : null;\n}\n\n/** The phrase a query windows its `over` column by — `last 90 days` in `due_on = last 90 days` — or null. */\nexport function windowPhraseOf(query: string | undefined, over: string | undefined): string | null {\n if (!query || !over) return null;\n const escaped = over.replace(/[.$+]/g, '\\\\$&');\n const found = new RegExp(`(?:^|[\\\\s(])${escaped}\\\\s*=\\\\s*(.+?)(?=\\\\s+(?:and|or)\\\\b|\\\\)|$)`, 'i').exec(query);\n return found ? found[1].trim() : null;\n}\n\n/** The days between two dates the data holds, both ends counted. Null where either is not a date. */\nexport function spanDaysBetween(min: unknown, max: unknown): number | null {\n const from = dayNumber(String(min ?? '').slice(0, 10));\n const to = dayNumber(String(max ?? '').slice(0, 10));\n return from === null || to === null || to < from ? null : to - from + 1;\n}\n\n/** The unit a span of this many days is drawn in, before the data is looked at. */\nexport function unitForSpan(days: number): AutoUnit {\n if (days <= 45) return 'day';\n if (days <= 26 * 7) return 'week';\n if (days <= 36 * 30.4375) return 'month';\n return 'quarter';\n}\n\n/**\n * The unit the read asks the server for. Where the measure adds up again, a day or a week is read as days and\n * bucketed here: a week crosses a month's edge, so weeks read from the server could not be coarsened into months\n * without handing a whole week to one of them. Months and quarters nest, so those are read as they are drawn.\n */\nexport function readUnit(base: AutoUnit, addsUp: boolean): AutoUnit {\n return addsUp && (base === 'day' || base === 'week') ? 'day' : base;\n}\n\n/* ---------- periods, by their labels ---------- */\n\nconst pad = (n: number) => String(n).padStart(2, '0');\n\nfunction dayNumber(key: string): number | null {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(key);\n return m ? Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3])) / DAY : null;\n}\n\nconst dayKey = (n: number): string => {\n const d = new Date(n * DAY);\n return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`;\n};\n\n/** The label of the period a day, month or quarter label falls in, spelled as the server spells it. */\nexport function bucketKey(key: string, unit: AutoUnit, weekStart = 1): string {\n if (unit === 'day') return key;\n if (unit === 'week') {\n const n = dayNumber(key);\n if (n === null) return key;\n /* ISO weekday 1..7; a day is that many days past its week's first. */\n const weekday = ((new Date(n * DAY).getUTCDay() + 6) % 7) + 1;\n return dayKey(n - ((weekday - weekStart + 7) % 7));\n }\n const month = Number(key.slice(5, 7));\n if (unit === 'month') return key.slice(0, 7);\n return /Q[1-4]$/.test(key) ? key : `${key.slice(0, 4)}-Q${Math.ceil(month / 3)}`;\n}\n\nfunction nextKey(key: string, unit: AutoUnit): string {\n if (unit === 'day' || unit === 'week') return dayKey((dayNumber(key) ?? 0) + (unit === 'week' ? 7 : 1));\n if (unit === 'month') {\n const [y, m] = [Number(key.slice(0, 4)), Number(key.slice(5, 7))];\n return m === 12 ? `${y + 1}-01` : `${y}-${pad(m + 1)}`;\n }\n const [y, q] = [Number(key.slice(0, 4)), Number(key.slice(6))];\n return q === 4 ? `${y + 1}-Q1` : `${y}-Q${q + 1}`;\n}\n\nconst SPELLED: Record<AutoUnit, RegExp> = {\n day: /^\\d{4}-\\d{2}-\\d{2}$/,\n week: /^\\d{4}-\\d{2}-\\d{2}$/,\n month: /^\\d{4}-\\d{2}$/,\n quarter: /^\\d{4}-Q[1-4]$/,\n};\n\n/** The local calendar day of a date, as the server spells a day. */\nconst localDay = (d: Date): string => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n\n/**\n * A trend's points over its window: the periods that held no rows put back as zero, from the window's first period\n * to today's, and the read periods added up into the unit the span is drawn in. A count of nothing is 0, and a line\n * drawn through only the days that had rows said a quiet week was a steady one; three busy days of a week drew no\n * line at all. Only a count or a sum adds up so: any other measure's points are drawn as read, and labels the read\n * unit does not spell are left as they came.\n */\nexport function trendPoints<R extends { key: unknown; value: unknown }>(\n rows: readonly R[],\n read: AutoUnit,\n unit: AutoUnit,\n measure: string | undefined,\n window: { start: Date; end: Date } | undefined,\n now: Date,\n): Array<{ key: unknown; value: unknown }> {\n if (!/^(count|sum\\s+[\\w.$+]+)(\\s+as\\s+[\\w$]+)?$/i.test((measure ?? 'count').trim())) return [...rows];\n const keys = rows.map((row) => String(row.key ?? ''));\n if (keys.some((key) => !SPELLED[read].test(key))) return [...rows];\n const ends = window ? [window.start, new Date(Math.min(window.end.getTime() - 1, now.getTime()))] : [];\n const sorted = [...keys, ...ends.map((d) => bucketKey(localDay(d), read))].sort();\n if (!sorted.length) return [...rows];\n const held = new Map(rows.map((row) => [String(row.key), Number(row.value) || 0]));\n const into = new Map<string, number>();\n for (let key = sorted[0], n = 0; key <= sorted[sorted.length - 1] && n < 5000; key = nextKey(key, read), n++) {\n const label = bucketKey(key, unit);\n into.set(label, (into.get(label) ?? 0) + (held.get(key) ?? 0));\n }\n return [...into].map(([key, value]) => ({ key, value }));\n}\n\n/** How many periods of the unit run from the first label to the last, both ends counted. */\nfunction periodsBetween(first: string, last: string, unit: AutoUnit): number {\n let count = 1;\n for (let key = first; key < last && count < 5000; key = nextKey(key, unit)) count++;\n return count;\n}\n\n/**\n * The unit a chart is drawn in: the span's, stepped up while the data is sparse in it.\n *\n * `keys` are the labels of the buckets that hold data, as read (days, or months or quarters, per `readUnit`).\n * `addsUp` is whether the measure can be re-aggregated; without it the span alone decides.\n */\nexport function chooseUnit({\n spanDays,\n base: given,\n keys,\n addsUp,\n weekStart = 1,\n}: {\n /** The span in days; or the `base` already chosen for it, where the caller has kept one. */\n spanDays?: number;\n base?: AutoUnit;\n keys: readonly string[];\n addsUp: boolean;\n weekStart?: number;\n}): { base: AutoUnit; unit: AutoUnit } {\n const base = given ?? unitForSpan(spanDays ?? 0);\n if (!addsUp || !keys.length || base === 'quarter') return { base, unit: base };\n const at = (unit: AutoUnit) => {\n const labels = [...new Set(keys.map((k) => bucketKey(k, unit, weekStart)))].sort();\n return { filled: labels.length, total: periodsBetween(labels[0], labels[labels.length - 1], unit) };\n };\n let unit: AutoUnit = base;\n for (;;) {\n const here = at(unit);\n if (here.filled / here.total >= DENSE) break;\n const next: AutoUnit | undefined = AUTO_UNITS[AUTO_UNITS.indexOf(unit) + 1];\n if (!next || at(next).total < FEWEST_BUCKETS) break;\n unit = next;\n }\n return { base, unit };\n}\n\n/* ---------- the measure, taken apart so it can be added up again ---------- */\n\ntype Combine = 'add' | 'min' | 'max';\n\nexport interface MeasurePlan {\n /** What to read per bucket, in the grammar's words: each aggregate the measure is made of, once. */\n reads: string[];\n /** How the same aggregate of two buckets becomes one of their union. */\n combine: Combine[];\n /** The measure's value from its aggregates, null where it has none (a ratio over nothing). */\n value(terms: readonly (number | null)[]): number | null;\n}\n\nconst TERM = /^(count|sum|avg|min|max)\\s*([\\w.$+]+)?$/i;\n\n/**\n * A measure as the aggregates it is made of, or null where it cannot be added up again: a median, a distinct\n * count, a `when` count, or words this does not read. `avg x` is `sum x` over `count x`, which can.\n */\nexport function planMeasure(measure: string | undefined): MeasurePlan | null {\n const text = (measure ?? 'count').replace(/\\s+as\\s+[\\w$]+\\s*$/i, '').trim();\n if (/\\b(distinct|when|median)\\b|[,[\\]()]/i.test(text)) return null;\n const parts = text.split(/\\s+([+\\-*/])\\s+/);\n const reads: string[] = [];\n const combine: Combine[] = [];\n const read = (aggregate: string, how: Combine): number => {\n const at = reads.indexOf(aggregate);\n if (at >= 0) return at;\n reads.push(aggregate);\n combine.push(how);\n return reads.length - 1;\n };\n type Operand = { number: number } | { term: number } | { ratio: [number, number] };\n const operands: Operand[] = [];\n for (let i = 0; i < parts.length; i += 2) {\n const part = parts[i].trim();\n if (/^\\d+(?:\\.\\d+)?$/.test(part)) {\n operands.push({ number: Number(part) });\n continue;\n }\n const m = TERM.exec(part);\n if (!m) return null;\n const fn = m[1].toLowerCase();\n const column = m[2];\n if (fn !== 'count' && !column) return null;\n if (fn === 'avg') operands.push({ ratio: [read(`sum ${column}`, 'add'), read(`count ${column}`, 'add')] });\n else operands.push({ term: read(column ? `${fn} ${column}` : fn, fn === 'min' ? 'min' : fn === 'max' ? 'max' : 'add') });\n }\n const ops = parts.filter((_, i) => i % 2 === 1);\n const value = (terms: readonly (number | null)[]): number | null => {\n const values = operands.map((o): number | null => {\n if ('number' in o) return o.number;\n if ('term' in o) return terms[o.term];\n const [sum, count] = [terms[o.ratio[0]], terms[o.ratio[1]]];\n return sum === null || !count ? null : sum / count;\n });\n /* SQL's precedence: `*` and `/` bind first; a division by zero is null, as the server's is. */\n const sums: Array<number | null> = [values[0]];\n const signs: string[] = [];\n for (const [i, op] of ops.entries()) {\n const right = values[i + 1];\n const left = sums[sums.length - 1];\n if (op === '*' || op === '/') {\n sums[sums.length - 1] =\n left === null || right === null || (op === '/' && right === 0) ? null : op === '*' ? left * right : left / right;\n } else {\n sums.push(right);\n signs.push(op);\n }\n }\n return sums.reduce<number | null>(\n (acc, v, i) => {\n if (i === 0) return v;\n return acc === null || v === null ? null : signs[i - 1] === '+' ? acc + v : acc - v;\n },\n sums[0] === undefined ? null : sums[0],\n );\n };\n return { reads, combine, value };\n}\n\n/** One bucket as read: its label, the second key's value where the chart has one, and one number per aggregate the plan reads. */\ninterface ReadBucket {\n key: string;\n series?: string;\n terms: readonly (number | null)[];\n}\n\n/** The read buckets cut into the chosen unit, each aggregate added up (or min'd, or max'd) across the ones it takes in. */\nexport function coarsen(\n buckets: readonly ReadBucket[],\n plan: MeasurePlan,\n unit: AutoUnit,\n weekStart = 1,\n): Array<{ key: string; series?: string; value: number }> {\n /* A chart over a second key (a line or a stack per value) is coarsened per value: a cross is the period and the series. */\n const into = new Map<string, Array<number | null>>();\n const SPLIT = '\\u0000';\n for (const bucket of buckets) {\n const key = `${bucketKey(bucket.key, unit, weekStart)}${bucket.series === undefined ? '' : SPLIT + bucket.series}`;\n const held = into.get(key);\n if (!held) {\n into.set(key, [...bucket.terms]);\n continue;\n }\n plan.combine.forEach((how, i) => {\n const [a, b] = [held[i], bucket.terms[i]];\n held[i] = a === null ? b : b === null ? a : how === 'add' ? a + b : how === 'min' ? Math.min(a, b) : Math.max(a, b);\n });\n }\n return [...into.entries()]\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .flatMap(([joined, terms]) => {\n const value = plan.value(terms);\n const [key, series] = joined.split(SPLIT);\n return value === null || !Number.isFinite(value) ? [] : [{ key, ...(series === undefined ? {} : { series }), value }];\n });\n}\n\n/* ---------- what a section asks, for the check ---------- */\n\n/** The most days a window may span before a fixed `day` chart over it is worth a word. */\nexport const DAY_BARS_ADVISED = 90;\n\n/**\n * The days a dashboard window phrase covers, as it would be said (\"last 12 months\" is 365): the nominal length of a\n * `last N unit`, else the dates the phrase resolves to, or null where it is not one the date grammar bounds. (A\n * resolved `last N` runs to tomorrow, a day more than it is called, which a count of bars should not repeat.)\n */\nexport function windowDays(phrase: string, now: Date): number | null {\n const last = /^last\\s+(\\d+)\\s+(day|week|month|year)s?$/i.exec(phrase.trim());\n if (last) return Math.round(Number(last[1]) * { day: 1, week: 7, month: 365 / 12, year: 365 }[last[2].toLowerCase() as 'day']);\n const window = dateWindow(phrase, now);\n return window ? Math.round((window.end.getTime() - window.start.getTime()) / DAY) : null;\n}\n\n/** Whether a chart's `by` cuts days: `day created_at`, in any position. */\nexport const cutsDays = (by: string | undefined): boolean => (by ?? '').split(',').some((key) => /^day\\s+[\\w.$+]+/i.test(key.trim()));\n","/**\n * A metric's trend, in the words it is asked: the window it is drawn over and the read that draws it. Apart from\n * dashboardAsks.ts because it reads the window's span through autoBucket.ts, which only a drawn dashboard needs:\n * held there, every App's first page carried the bucketing a chart and a trend use (scripts/bundle-budget.mjs).\n * Asked by the client's metric (client/components/Dashboard.tsx) and by the server for a first page\n * (server/http/firstPaintRooms.ts), in the same words.\n */\nimport { andQuery } from './query.js';\nimport { type AutoUnit, unitForSpan, windowDays, windowPhraseOf } from './autoBucket.js';\nimport type { AskedSection } from './dashboardAsks.js';\n\n/**\n * The window a metric's trend is drawn over — the reader's, else the author's own on `over` — and the units it is\n * read and drawn in: the span's unit (autoBucket.ts), read as days under a week so a week is added up on the client\n * (`trendPoints`) and never handed whole to one month. Null where the metric has no window the date grammar bounds.\n */\nexport function sparkWindow(\n section: Pick<AskedSection, 'query' | 'over' | 'windowPhrase'>,\n now = new Date(),\n): { phrase: string; read: AutoUnit; unit: AutoUnit } | null {\n if (!section.over) return null;\n const phrase = section.windowPhrase ?? windowPhraseOf(section.query, section.over);\n const days = phrase ? windowDays(phrase, now) : null;\n if (!phrase || !days) return null;\n /* \"today\" is one day: a trend of fewer than four points is no line, and no slot is held for it. */\n if (days < 4) return null;\n const unit = unitForSpan(days);\n return { phrase, unit, read: unit === 'week' ? 'day' : unit };\n}\n\n/** The most periods a windowed trend reads: 182 days, or months and quarters past them, with room to spare. */\nconst TREND_PERIODS = 400;\n\n/**\n * A metric's trend. Over a window, the metric over that window in the span's unit, so \"last 30 days\" draws thirty\n * days and \"last 12 months\" twelve months: every windowed metric has one, beside its change, unless its author said\n * `spark: false`. With no window, the author's `spark: true` is the measure's last twelve months, bucketed monthly by\n * the section's own clock (`over`), composed with whatever the card is narrowed to by other than time. None without a\n * clock.\n */\nexport function sparkText(\n section: Pick<AskedSection, 'table' | 'query' | 'windowBase' | 'windowPhrase' | 'measure' | 'over' | 'spark'>,\n): string | null {\n /* An authored false is heard over a window too: a card can be a figure alone, which it once could not say. */\n if (!section.over || section.spark === false) return null;\n const window = sparkWindow(section);\n if (window)\n return [section.table, section.query, `${section.measure ?? 'count'} by ${window.read} ${section.over}`, `limit ${TREND_PERIODS}`]\n .filter(Boolean)\n .join(' ');\n if (!section.spark) return null;\n const trendBase = section.windowBase ?? section.query;\n return `${section.table} ${andQuery(trendBase, `${section.over} = last 12 months`)} ${section.measure ?? 'count'} by month ${section.over}`;\n}\n","/**\n * Which weekday a week starts on in a reader's locale, read once and remembered. Shared by the server's date\n * buckets and the client's charts, so a `week` means the same seven days on both sides.\n */\nconst weekStarts = new Map<string, number>();\n/**\n * The day a week starts on where an App is read: its `ui.locale`'s own first\n * day (Sunday in the US, Monday in most of the world), and Monday — ISO's —\n * where the App names no locale. Said as an ISO weekday, 1 (Monday) to 7\n * (Sunday), the number a `week` bucket's SQL takes (filter.ts).\n */\nexport function localeWeekStart(locale: string | undefined): number {\n if (!locale) return 1;\n /* Asked for every date a request reads, of the same few locales; building\n an Intl.Locale each time was measurable on a busy server. Bounded,\n because a locale can come from a person's own setting. */\n const known = weekStarts.get(locale);\n if (known !== undefined) return known;\n if (weekStarts.size >= 64) weekStarts.clear();\n const first = readWeekStart(locale);\n weekStarts.set(locale, first);\n return first;\n}\n\nfunction readWeekStart(locale: string): number {\n try {\n const tag = new Intl.Locale(locale) as Intl.Locale & {\n getWeekInfo?: () => { firstDay: number };\n weekInfo?: { firstDay: number };\n };\n const first = (tag.getWeekInfo?.() ?? tag.weekInfo)?.firstDay;\n return typeof first === 'number' && Number.isInteger(first) && first >= 1 && first <= 7 ? first : 1;\n } catch {\n return 1;\n }\n}\n","/**\n * A chart whose `by` says `auto` (shared/autoBucket.ts): the unit it is cut into, decided before the read from the\n * window and, where the window does not say, the data's own extent; then coarsened locally while the answer is sparse.\n *\n * The unit is decided once per window. A refresh that finds the data a little denser or sparser keeps the unit the\n * reader is looking at, because a chart that changes its bars under a pointer, on a timer, is the layout shift this\n * product refuses; a reader's own pick of a window chooses again.\n */\nimport { useRef } from 'react';\nimport {\n autoKeyOf,\n chooseUnit,\n coarsen,\n planMeasure,\n readUnit,\n spanDaysBetween,\n spanDaysOf,\n unitForSpan,\n withUnit,\n type AutoUnit,\n type MeasurePlan,\n} from '@mistriwork/engine/shared/autoBucket.js';\nimport { localeWeekStart } from '@mistriwork/engine/shared/weekStart.js';\nimport { shell } from '../shellMode.js';\nimport type { Section } from './dashboardModel.js';\n\ninterface Answer {\n columns?: string[];\n rows?: Array<Record<string, unknown>>;\n names?: Record<string, Record<string, string>>;\n}\n\n/** What a read gives back that this needs: the answer, and whether it is the last window's held while the next loads. */\nexport interface Read {\n data?: Answer;\n isPlaceholderData?: boolean;\n}\n\ninterface AutoDrawn {\n answer: Answer | undefined;\n /** The unit the bars or points are in, said under the title. Absent until there is one to say. */\n unit: AutoUnit | undefined;\n /** A line with too few filled buckets to draw a line through: its points stand alone. */\n dots: boolean;\n}\n\ninterface AutoChart {\n /** The section to ask, in the unit chosen; null while the span is still being read from the data. */\n ask: Section | null;\n /** The read's answer as it is drawn: coarsened where it adds up, and the unit it came to. */\n draw(read: Read): AutoDrawn;\n}\n\n/** The fewest filled buckets a line is drawn through: two points are a segment, and a segment says nothing of a trend. */\nconst LINE_FROM = 3;\n\nconst numberOrNull = (value: unknown): number | null => {\n const n = Number(value);\n return value === null || value === undefined || value === '' || !Number.isFinite(n) ? null : n;\n};\n\n/**\n * The plan for a section, or null for a chart that does not say `auto`. Called every render of every chart, in the\n * same order, so the hooks it makes (the span's read, the kept unit) are the chart's own.\n *\n * `read` asks the server in the dashboard's way (its cache, its refresh), so this module holds no fetching of its own.\n */\nexport function useAutoChart(section: Section, read: (text: string | null) => Read): AutoChart | null {\n const auto = autoKeyOf(section.by);\n const plan = planMeasure(section.measure);\n /* A measure adds up again when the date is the first key: the answer is then a row per period (and per value of a\n second key, which the period is coarsened within). A date second has its rows grouped by another key first. */\n const keys = (section.by ?? '').split(',').length;\n const addsUp = plan !== null && auto?.index === 0 && keys <= 2;\n const weekStart = localeWeekStart((shell().app() as { ui?: { locale?: string } } | null)?.ui?.locale);\n\n /* The window the reader picked rides on `over`; a chart with none of its own is held to the window its query\n writes on the date it cuts. */\n const windowDays = auto ? spanDaysOf(section.query, section.over ?? auto.column, new Date()) : null;\n /* What a window is, and so when the unit is chosen again: the table and column, and the window's own phrase. A\n pick of another filter changes the section's query and not this. */\n const epoch = auto ? `${section.table}|${section.over ?? ''}|${auto.column}|${windowDays ?? 'data'}` : '';\n const kept = useRef<{ epoch: string; base?: AutoUnit; unit?: AutoUnit; drawn?: AutoDrawn }>({ epoch: '' });\n if (kept.current.epoch !== epoch) kept.current = { epoch, drawn: kept.current.drawn };\n\n /* Under no window the span is the data's own: its first and last date, as the one-row answer of two measures, the\n grammar's own `min` and `max` (a read with no `by` is one group). */\n const needsExtent = Boolean(auto) && windowDays === null && !kept.current.base;\n const extent = read(\n needsExtent && auto ? [section.table, section.query, `min ${auto.column}, max ${auto.column}`].filter(Boolean).join(' ') : null,\n );\n\n if (!auto) return null;\n\n let base = kept.current.base;\n if (!base && windowDays !== null) base = unitForSpan(windowDays);\n if (!base && extent.data && !extent.isPlaceholderData) {\n const [from, to] = extent.data.columns ?? [];\n const row = extent.data.rows?.[0];\n const days = row ? spanDaysBetween(row[from], row[to]) : null;\n /* A table with no dates has nothing to draw: the finest unit is as good as any. */\n base = days === null ? 'day' : unitForSpan(days);\n }\n if (base) kept.current.base = base;\n if (!base) {\n return {\n ask: null,\n draw: () => kept.current.drawn ?? { answer: undefined, unit: undefined, dots: false },\n };\n }\n\n const reading = readUnit(base, addsUp);\n const ask: Section = {\n ...section,\n by: withUnit(section.by ?? '', reading),\n ...(addsUp && plan ? { measure: plan.reads.join(', ') } : {}),\n };\n /* One line, of few filled buckets; several lines are drawn as they are. */\n const dotted = (filled: number) => (!section.shape || section.shape === 'line') && keys === 1 && filled > 0 && filled < LINE_FROM;\n\n const draw = ({ data, isPlaceholderData }: Read): AutoDrawn => {\n /* A held answer is the last window's, in the last window's unit: drawn as it was, and never the data the unit\n is chosen from. */\n if (!data || isPlaceholderData) return kept.current.drawn ?? { answer: undefined, unit: undefined, dots: false };\n const columns = data.columns ?? [];\n let drawn: AutoDrawn;\n if (addsUp && plan && columns.length === keys + plan.reads.length && !(data.rows ?? []).some((row) => row[columns[0]] == null)) {\n const buckets = (data.rows ?? []).map((row) => ({\n key: String(row[columns[0]]),\n ...(keys === 2 ? { series: String(row[columns[1]]) } : {}),\n terms: plan.reads.map((_, i) => numberOrNull(row[columns[keys + i]])),\n }));\n const unit = kept.current.unit ?? chooseUnit({ base, keys: buckets.map((b) => b.key), addsUp: true, weekStart }).unit;\n kept.current.unit = unit;\n const rows = coarsen(buckets, plan as MeasurePlan, unit, weekStart);\n drawn = {\n answer: {\n columns: [...columns.slice(0, keys), 'value'],\n rows: rows.map((r) => ({ [columns[0]]: r.key, ...(keys === 2 ? { [columns[1]]: r.series } : {}), value: r.value })),\n },\n unit,\n dots: dotted(rows.length),\n };\n } else {\n kept.current.unit = base;\n drawn = { answer: data, unit: base, dots: dotted((data.rows ?? []).length) };\n }\n kept.current.drawn = drawn;\n return drawn;\n };\n return { ask, draw };\n}\n","/** What FirstRun says, in the shell 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 getStarted: 'Get started',\n done: '(done)',\n open: 'Open',\n});\n","/**\n * A new App's first steps. A home over empty tables draws charts of nothing\n * and counts of zero, which say the App is broken when it is only new; this\n * says what to do instead — add the first record here, then there — each\n * step a link to its list with the New form open.\n *\n * A step is done when its table has a row the reader can see, read as one\n * bounded row per step. `useFirstRun` says where the dashboard stands:\n * `fresh` (no step done) draws the welcome alone, `started` draws it above\n * the dashboard, `done` (or no steps this reader can take) draws nothing.\n */\nimport { useQueries } from '@tanstack/react-query';\nimport { findTable, state } from '@mistriwork/kit/client/core.js';\nimport { batchedRun } from '@mistriwork/kit/client/breakdownBatch.js';\nimport { canInsert } from '@mistriwork/kit/client/insert.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { buttonClass } from '@mistriwork/ui/Button.js';\nimport { Icon } from '@mistriwork/kit/client/components/Icon.js';\nimport { viewLink } from '@mistriwork/kit/client/components/viewLink.js';\nimport type { Section } from '@mistriwork/kit/client/components/dashboardModel.js';\nimport './FirstRun.css';\nimport { say } from '../copy/shell/components/FirstRun.js';\n\ntype FirstRunStage = 'unknown' | 'fresh' | 'started' | 'done';\n\n/** Which steps are done, and so what the dashboard draws. */\nexport function useFirstRun(section: Section | undefined): { stage: FirstRunStage; done: boolean[] } {\n const steps = section?.steps ?? [];\n const reads = useQueries({\n queries: steps.map((step) => ({\n queryKey: ['first-run', state.activeConnection ?? '', step.table],\n queryFn: async () => {\n // Asked with the dashboard's other reads, in one request, and not counted (breakdownBatch.ts).\n const data = await batchedRun<{ rows?: unknown[] }>({ q: step.table ?? '', limit: 1, offset: 0, count: 'none' });\n return Boolean(data.rows?.length);\n },\n // Read again whenever the home is drawn: the reader has just come back from adding the first record.\n staleTime: 0,\n })),\n });\n if (!section || !steps.length) return { stage: 'done', done: [] };\n /* A step that cannot be read is not a reason to hide the dashboard: it counts as done. */\n const done = reads.map((read) => read.isError || read.data === true);\n if (reads.some((read) => read.isPending)) return { stage: 'unknown', done };\n return { stage: done.every(Boolean) ? 'done' : done.some(Boolean) ? 'started' : 'fresh', done };\n}\n\nexport function FirstRun({ section, done, fresh }: { section: Section; done: boolean[]; fresh: boolean }) {\n const steps = section.steps ?? [];\n const next = done.indexOf(false);\n return (\n <section className={`page-section width-full dash-first-run${fresh ? ' is-fresh' : ''}`} aria-labelledby=\"first-run-title\">\n <h2 className=\"page-section-title\" id=\"first-run-title\">\n {section.title ?? say('getStarted')}\n </h2>\n {section.text && <p className=\"first-run-text\">{section.text}</p>}\n <ol className=\"first-run-steps\">\n {steps.map((step, i) => {\n const table = findTable(step.table ?? '') as TableMeta | undefined;\n /* The New form where the reader may add; the list itself where they may only read. */\n const adding = !done[i] && Boolean(table && canInsert(table, true));\n const link = viewLink(step.view, 'push', adding);\n return (\n <li key={step.view} className={`first-run-step${done[i] ? ' is-done' : ''}`}>\n <span className=\"first-run-mark\" aria-hidden=\"true\">\n {done[i] ? <Icon name=\"check-circle\" size={20} weight=\"bold\" /> : <span className=\"first-run-number\">{i + 1}</span>}\n </span>\n <span className=\"first-run-words\">\n <span className=\"first-run-label\">\n {step.label}\n {done[i] ? <span className=\"visually-hidden\"> {say('done')}</span> : null}\n </span>\n {step.detail && <span className=\"first-run-detail\">{step.detail}</span>}\n </span>\n {link &&\n (done[i] ? (\n <a className={buttonClass({ intent: 'quiet', size: 'compact' })} {...link}>\n {say('open')}\n </a>\n ) : (\n <a className={buttonClass({ intent: i === next ? 'primary' : 'secondary', size: 'compact' })} {...link}>\n {adding ? say('common.add') : say('open')}\n </a>\n ))}\n </li>\n );\n })}\n </ol>\n </section>\n );\n}\n","/** What LandingData says, in the public pages 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 nothingToShowHere: 'Nothing to show here right now.',\n seeAll: 'See all {things}',\n maxLabel: 'Max {label}',\n search: 'Search {label}',\n noLimit: 'No limit',\n});\n","/**\n * The landing's sections that read the App's rows — a list view's cards,\n * and a search over its own filters — and its calls to action that open a\n * view, drawn inside the App for a visitor the public grant lets read them.\n * LandingSurface stays a page of the author's text; the App hands it these.\n *\n * A search writes exactly what the list's filter boxes would: a choice is\n * `= value`, typed text is `contains`, a most-you-would-pay is `<=`, each\n * through the same condition writer, into the list's own address. The\n * result is the list, and a link to it is the search.\n */\nimport { useState, type FormEvent } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { activeApp } from '../appState.js';\nimport { api, columnDisplay, columnLabel, findTable, go, quote, state, tableView } from '@mistriwork/kit/client/core.js';\nimport { equalsTail, withCondition } from '@mistriwork/kit/client/filterbar.js';\nimport { ownedBy } from '@mistriwork/kit/client/requestIdentity.js';\nimport { formatMoney } from '@mistriwork/kit/client/locale.js';\nimport { andQuery } from '@mistriwork/engine/shared/query.js';\nimport { columnKind, primaryKey, type ColumnMeta, type TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { type LandingImage, type LandingSection } from '../../shared/appModel.js';\nimport { humanName } from '@mistriwork/engine/shared/model.js';\nimport { listPresentationColumns } from '@mistriwork/engine/shared/appListColumns.js';\nimport { appListQuery, specTabs, visibleQuestion, wholeQuery, type ListSpec } from '@mistriwork/kit/client/components/appListModel.js';\nimport { isListRoom, viewRoom } from '@mistriwork/kit/client/components/appRooms.js';\nimport { viewLink } from '@mistriwork/kit/client/components/viewLink.js';\nimport { choiceWord, dressFor, type DisplayRule } from '@mistriwork/kit/client/components/valueModel.js';\nimport { inlineFileAddress } from '@mistriwork/kit/client/components/cardsModel.js';\nimport { Dropdown } from '@mistriwork/kit/client/components/Dropdown.js';\nimport { onDemand, useArrived } from '@mistriwork/kit/client/components/onDemand.js';\nimport { SuggestBox } from '@mistriwork/kit/client/components/suggestPart.js';\nimport { say } from '../copy/public/components/LandingData.js';\n\nconst CardsList = onDemand(() => import('@mistriwork/kit/client/components/CardsList.js'), 'CardsList');\n\ntype Section<K extends LandingSection['kind']> = Extract<LandingSection, { kind: K }>;\ntype Row = Record<string, unknown>;\n\n/** A text column with this many values or fewer is offered as a choice; past it, typed. */\nconst CHOICES = 24;\n\nfunction listRoom(key: string): ListSpec | undefined {\n const app = activeApp() as Parameters<typeof viewRoom>[0] | null;\n const room = app ? viewRoom(app, key) : undefined;\n return room && isListRoom(room) ? room : undefined;\n}\n\nconst connection = () => state.activeConnection ?? null;\nconst owned = () => (connection() ? ownedBy(connection()) : {});\n\n/** A list view's rows as its cards, the first `limit` by `sort`: the list's own question, narrowed. */\nexport function LandingCards({ section }: { section: Section<'view'> }) {\n const spec = listRoom(section.view);\n const table = spec ? (findTable(spec.table) as TableMeta | undefined) : undefined;\n const cards = spec?.presentation?.kind === 'cards' ? spec.presentation : undefined;\n const text =\n spec && table && cards\n ? [\n spec.table,\n andQuery(spec.query, specTabs(spec)[0]?.query),\n section.sort ? `sort ${section.sort}` : '',\n `show ${[...new Set([...(spec.show ?? []), ...listPresentationColumns(cards), ...primaryKey(table)])].join(', ')}`,\n ]\n .filter(Boolean)\n .join(' ')\n : '';\n const limit = section.limit ?? 6;\n const answer = useQuery({\n queryKey: ['run', connection() ?? '', 'landing-cards', text, limit],\n enabled: Boolean(text),\n queryFn: async () => {\n const data = (await api('/api/run', { q: text, limit, offset: 0, count: 'none', ...owned() })) as {\n rows?: Row[];\n errors?: Array<{ message: string }>;\n };\n if (data.errors?.length) throw new Error(data.errors[0].message);\n return data.rows ?? [];\n },\n });\n /* The cards come with the rows: asked for beside them, and the section stays empty until both are here. */\n const cardsHere = useArrived(CardsList, Boolean(cards));\n if (!spec || !table || !cards) return null;\n if (answer.isError) return <p className=\"front-note\">{(answer.error as Error).message}</p>;\n if (!answer.data || !cardsHere) return null;\n if (!answer.data.length) return <p className=\"front-note\">{say('nothingToShowHere')}</p>;\n const more = viewLink(section.view);\n return (\n <>\n <CardsList table={table} rows={answer.data} spec={cards} label={section.title ?? spec.label} />\n {more && (\n <p className=\"front-more\">\n <a href={more.href} onClick={more.onClick}>\n {say('seeAll', { things: (spec.label ?? '').toLocaleLowerCase() })}\n </a>\n </p>\n )}\n </>\n );\n}\n\n/** Round figures up to the highest value, for a most-you-would-pay: 1, 1.5, 2, 2.5, 3, 4, 5, 7.5 of each power of ten. */\nexport function priceSteps(max: number): number[] {\n if (!Number.isFinite(max) || max <= 0) return [];\n const steps: number[] = [];\n for (let power = 10 ** Math.max(0, Math.floor(Math.log10(max)) - 1); steps.length < 40; power *= 10) {\n for (const lead of [1, 1.5, 2, 2.5, 3, 4, 5, 7.5]) {\n const step = lead * power;\n if (step >= max / 12) steps.push(step);\n if (step >= max) return steps;\n }\n }\n return steps;\n}\n\ntype Field = {\n name: string;\n label: string;\n column: ColumnMeta;\n kind: 'choice' | 'text' | 'max';\n options?: Array<{ value: string; label: string }>;\n};\n\n/** How a field is asked: a vocabulary or a short list of values is a choice; a number, a ceiling; other text, typed. */\nfunction useFields(table: TableMeta | undefined, spec: ListSpec | undefined, names: readonly string[]): Field[] | undefined {\n const where = spec ? andQuery(spec.query, specTabs(spec)[0]?.query) : '';\n const columns = names\n .map((name) => table?.columns.find((column) => column.name === name))\n .filter((column): column is ColumnMeta => Boolean(column));\n const answer = useQuery({\n queryKey: ['breakdown', 'landing-search', table?.id, where, names],\n enabled: Boolean(table && spec),\n queryFn: () =>\n Promise.all(\n columns.map(async (column): Promise<Field> => {\n const label = (columnLabel(table!.id, column.name) as string | null) ?? humanName(column.name);\n const allowed = (column as ColumnMeta & { allowed?: string[] }).allowed;\n if (allowed?.length)\n return {\n name: column.name,\n label,\n column,\n kind: 'choice',\n options: allowed.map((value) => ({\n value,\n label: choiceWord(columnDisplay(table!.id, column.name) as DisplayRule | null, value),\n })),\n };\n if (columnKind(column.type) === 'number') {\n const data = (await api('/api/breakdown', {\n text: [table!.id, where, `max ${column.name}`].filter(Boolean).join(' '),\n limit: 1,\n ...owned(),\n })) as { rows?: Row[] };\n const top = Number(Object.values(data.rows?.[0] ?? {})[0]);\n const rule = columnDisplay(table!.id, column.name) as DisplayRule | null;\n return {\n name: column.name,\n label: say('maxLabel', { label: label.toLocaleLowerCase() }),\n column,\n kind: 'max',\n options: priceSteps(top).map((step) => ({\n value: String(step),\n label:\n rule?.format === 'money'\n ? formatMoney(step, rule.currency, { maximumFractionDigits: 0 })\n : (dressFor(rule, step)?.text ?? step.toLocaleString()),\n })),\n };\n }\n const data = (await api('/api/breakdown', {\n text: [table!.id, where, `count by ${column.name}`].filter(Boolean).join(' '),\n limit: CHOICES + 1,\n ...owned(),\n })) as { rows?: Row[]; columns?: string[] };\n const values = (data.rows ?? [])\n .map((row) => row[data.columns?.[0] ?? column.name])\n .filter((value) => value !== null && value !== undefined && value !== '')\n .map(String);\n return values.length && values.length <= CHOICES\n ? {\n name: column.name,\n label,\n column,\n kind: 'choice',\n options: [...values].sort((a, b) => a.localeCompare(b)).map((value) => ({ value, label: value })),\n }\n : { name: column.name, label, column, kind: 'text' };\n }),\n ),\n });\n return answer.data;\n}\n\n/** A search over a list view: its own filters up front, submitted as the list's conditions. */\nexport function LandingSearch({ section }: { section: Section<'search'> }) {\n const spec = listRoom(section.view);\n const table = spec ? (findTable(spec.table) as TableMeta | undefined) : undefined;\n const fields = useFields(table, spec, section.filters);\n const [values, setValues] = useState<Record<string, string>>({});\n /* A text field the list suggests for suggests here too: the hero is the list's search, asked early. */\n const suggesting = useArrived(SuggestBox, Boolean(spec?.suggest));\n if (!spec || !table || !fields) return null;\n const set = (name: string, value: string) => setValues((current) => ({ ...current, [name]: value }));\n const submit = (event: FormEvent) => {\n event.preventDefault();\n let text = visibleQuestion(spec, appListQuery(spec, 0));\n for (const field of fields) {\n const value = (values[field.name] ?? '').trim();\n if (!value) continue;\n const tail = field.kind === 'text' ? `contains ${quote(value)}` : field.kind === 'max' ? `<= ${value}` : equalsTail(value);\n text = withCondition(text, field.name, tail) as string;\n }\n (state as { page: number }).page = 0;\n go({ ...tableView(spec.table, wholeQuery(spec, text)), view: section.view }, 'push');\n };\n return (\n <form\n className=\"front-search-form\"\n role=\"search\"\n aria-label={section.title ?? say('search', { label: spec.label ?? '' }).trim()}\n onSubmit={submit}\n >\n <div className=\"front-search-fields\">\n {fields.map((field) => (\n <label key={field.name} className=\"front-search-field\">\n <span className=\"front-search-label\">{field.label}</span>\n {field.kind === 'text' && suggesting && spec.suggest?.[field.name] ? (\n /* A pick fills the field; the form's own button searches, with whatever else the hero asks. */\n <SuggestBox\n table={table.id}\n columns={spec.suggest[field.name]}\n standing={spec.query ?? ''}\n text={values[field.name] ?? ''}\n onText={(value) => set(field.name, value)}\n onPick={(value) => set(field.name, value)}\n inputProps={{ type: 'search', className: 'front-search-input', placeholder: say('common.any') }}\n />\n ) : field.kind === 'text' ? (\n <input\n type=\"search\"\n className=\"front-search-input\"\n placeholder={say('common.any')}\n value={values[field.name] ?? ''}\n onChange={(event) => set(field.name, event.target.value)}\n />\n ) : (\n <Dropdown\n ariaLabel={field.label}\n value={values[field.name] ?? ''}\n onChange={(value) => set(field.name, value)}\n items={[{ value: '', label: field.kind === 'max' ? say('noLimit') : say('common.any') }, ...(field.options ?? [])]}\n />\n )}\n </label>\n ))}\n </div>\n <button type=\"submit\" className=\"front-action front-action-primary front-search-go\">\n {section.submitLabel ?? say('navigation.search')}\n </button>\n </form>\n );\n}\n\n/** The hero's photo: its row of the App's files, by key, drawn inline through the file route. */\nexport function landingImage(image: LandingImage): string | undefined {\n const table = findTable(image.from) as TableMeta | undefined;\n const key = table ? primaryKey(table) : [];\n return table && key.length === 1 ? inlineFileAddress(table.id, { [key[0]]: image.key }, state.activeConnection ?? null) : undefined;\n}\n\n/** The two sections the App draws for the landing; anything else is the landing's own. */\nexport function landingSection(section: LandingSection) {\n if (section.kind === 'view') return <LandingCards section={section} />;\n if (section.kind === 'search') return <LandingSearch section={section} />;\n return null;\n}\n","/** What Dashboard says, in the dashboards 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 target: 'Target {goal}',\n nothingToCountYet: 'Nothing to count yet.',\n nothingToDrawYet: 'Nothing to draw yet.',\n thisSectionHasNoBreakdown: 'This section has no breakdown query.',\n thisSectionHasNoRecord: 'This section has no record query.',\n vsTheCompareWindow: 'vs the compare window',\n inTheCompareWindow: '{b} in the compare window ({compare})',\n sameAsBefore: 'Same as before',\n sameAsTheCompareWindow: 'Same as the compare window',\n ofTarget: '{reached} of {goal} target',\n ofWhole: '{figure} of {whole} ({reached})',\n ofWholeSaid: '{figure} of {whole}, {percent} percent',\n theTimeWindowAbove: 'The time window above does not change this figure.',\n fixedWindow: 'Right now',\n allTime: 'All time',\n noToCount: 'No {table} to count.',\n openTableWhereBy: 'Open {table} where {by} = {key}',\n noToDraw: 'No {table} to draw.',\n byDay: 'by day',\n byWeek: 'by week',\n byMonth: 'by month',\n byQuarter: 'by quarter',\n nothingToCrossYet: 'Nothing to cross yet.',\n noToCross: 'No {table} to cross.',\n theFullListWithItsTabs: 'The full list, with its tabs and filters',\n figureInAll: '{figure} in all',\n nothingToLayOut: 'Nothing to lay out yet.',\n noToLayOut: 'No {table} to lay out.',\n moreCount: '+ {figure} more',\n timeWindow: 'Time window',\n allTimeWindow: 'All time',\n nothingInThisTimeWindow: 'Nothing in this time window.',\n showAllTime: 'Show all time',\n defaultWindow: 'Default',\n windowRange: '{from} – {to}',\n pickWindow: 'Time window: {window}',\n any: 'Any {label}',\n filter: 'Filter by {label}',\n latestChanges: 'Latest changes',\n branding: 'Branding',\n integrations: 'Integrations',\n dashboardContext: 'Dashboard context',\n vsPrior: 'vs prior {period}',\n sameAsPrior: 'Same as prior {period}',\n});\n","/**\n * A dashboard: the app's own screen, composed like a page but about the\n * whole table instead of one record.\n *\n * Every section rides machinery that already exists — a metric is the\n * home card's one-group breakdown with a width, a breakdown is the same\n * def the page sections run, a list is the real table view with the\n * chrome off — so this module is composition, not a new engine. The\n * sections wear the page's own layout classes, because a dashboard and a\n * page are the same room at two zoom levels and should read as such.\n *\n * Every fetch is a Query. That is what makes a refresh a refetch — the\n * numbers change in place, the reader never sees a loading state — and\n * what makes fifteen sections on one screen fifteen cache entries rather\n * than fifteen requests per paint: a pick changes the sections it lands\n * on and the rest keep what they have.\n */\nimport { shell } from '@mistriwork/kit/client/shellMode.js';\nimport {\n createContext,\n memo,\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type CSSProperties,\n type ReactNode,\n} from 'react';\nimport { keepPreviousData, useIsFetching, useQuery, useQueryClient } from '@tanstack/react-query';\nimport {\n columnDisplay,\n findTable,\n go,\n labelColumn,\n labelPath,\n openRecord,\n primaryKey,\n quote,\n refsFrom,\n tableView,\n} from '@mistriwork/kit/client/core.js';\nimport { splitQuery } from '@mistriwork/kit/client/clauses.js';\nimport { batchedBreakdown, batchedRun } from '@mistriwork/kit/client/breakdownBatch.js';\nimport { ListEmpty } from '@mistriwork/kit/client/components/ListEmpty.js';\nimport { andQuery } from '@mistriwork/engine/shared/query.js';\nimport { droppedQuery, funnelBasis, funnelChains, funnelText, stageColumn } from '@mistriwork/engine/shared/funnel.js';\nimport { Funnel, type FunnelDoor } from './Funnel.js';\nimport { exportOffered, type AppListEmpty } from '@mistriwork/engine/shared/listPresentations.js';\nimport { gridTemplateAreas, layoutAreas, layoutGrid, reflowLayout, type LayoutGrid } from '@mistriwork/engine/shared/dashLayout.js';\nimport {\n boardCountText,\n chartLimit,\n dashboardListQuery,\n groupsAskedFor,\n measureText,\n pickQuery,\n type AskLookups,\n} from '@mistriwork/engine/shared/dashboardAsks.js';\nimport { sparkText, sparkWindow } from '@mistriwork/engine/shared/dashboardTrend.js';\nimport { trendPoints } from '@mistriwork/engine/shared/autoBucket.js';\nimport type { ColumnMeta, ForeignKey, TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { message, messageLanguage, subscribeMessages } from '@mistriwork/kit/client/messages.js';\nimport { activeApp, inAppMode } from '../appState.js';\nimport { mayRunAny } from '@mistriwork/kit/client/actionGrants.js';\nimport { appRooms, isListRoom, offeredBy, resourceOf, viewRoom } from '@mistriwork/kit/client/components/appRooms.js';\nimport { listEntry, listLink, type ViewLink } from '@mistriwork/kit/client/components/viewLink.js';\nimport { TableRoom } from '@mistriwork/kit/client/components/TableRoom.js';\nimport { referenceNames } from '@mistriwork/kit/client/components/appListModel.js';\nimport { namedCell } from '@mistriwork/kit/client/components/listColumn.js';\nimport { dressFor, groupLabel, maskedText, ruleSays, type DisplayRule } from '@mistriwork/kit/client/components/valueModel.js';\nimport { AvatarText, Dressed, Value } from '@mistriwork/kit/client/components/Value.js';\nimport { avatarOwner, useAvatarPhotos } from '@mistriwork/kit/client/components/avatarPhotos.js';\nimport { Sparkline, TONE_INK, periodTick } from '@mistriwork/kit/client/components/Chart.js';\nimport { useAutoChart } from '@mistriwork/kit/client/components/autoChart.js';\nimport { ChartFigure, ChartShapeFigure, EXTRA_SHAPES, type ExtraShape } from '@mistriwork/kit/client/components/ChartFigure.js';\nimport { Dropdown } from '@mistriwork/kit/client/components/Dropdown.js';\nimport { DashboardNote } from '@mistriwork/kit/client/components/DashboardNote.js';\nimport { Icon } from '@mistriwork/kit/client/components/Icon.js';\nimport { FirstRun, useFirstRun } from './FirstRun.js';\nimport { ErrorBoundary } from '@mistriwork/kit/client/components/ErrorBoundary.js';\nimport { Empty, Problem, ProblemScopeProvider } from '@mistriwork/kit/client/components/Notes.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { landingImage } from './LandingData.js';\nimport type { AppIconName } from '@mistriwork/engine/shared/appIcons.js';\nimport { currencyPath } from '@mistriwork/engine/shared/money.js';\nimport { targetText } from '@mistriwork/engine/shared/dashboardAsks.js';\nimport {\n allSections,\n barShare,\n boardSection,\n breakdownText,\n CurrencyFigures,\n pinnedCurrency,\n figure,\n fullQuery,\n legendSayer,\n namedGroups,\n orderGroups,\n picked,\n sayer,\n sectionPeriod,\n windowed,\n windowTitle,\n metricWindow,\n type DashboardDef,\n type DashboardProps,\n type Periods,\n type Picks,\n type Section,\n} from '@mistriwork/kit/client/components/dashboardModel.js';\nimport { declaredOrder, orderDeclared } from '@mistriwork/kit/client/components/groupOrder.js';\nimport { formatApprox, formatDate, formatLocale, formatPercent } from '@mistriwork/kit/client/locale.js';\nimport { dateWindow } from '@mistriwork/engine/shared/queryDates.js';\nimport { DropItem, DropMenu } from '@mistriwork/ui/DropMenu.js';\n/* The dashboard's own blocks' sheet travels with this chunk (onDemand), not in the first stylesheet. */\nimport './DashboardBlocks.css';\nimport { onDemand } from '@mistriwork/kit/client/components/onDemand.js';\nimport { say as sayCopy } from '../copy/dashboards/components/Dashboard.js';\nimport { liveFollowing } from '@mistriwork/kit/client/liveState.js';\n\n/* An author's component, and the page's side of @mistriwork/mistri/ui with it: fetched\n the first time a dashboard holds one, never for a dashboard without. */\nconst CustomDashSection = onDemand(() => import('./sdk/CustomSection.js'), 'CustomDashSection');\n/* A list that works as its room does, and the feed of recent changes: each fetched the first time a dashboard holds one. */\nconst InteractiveList = onDemand(() => import('@mistriwork/kit/client/components/DashboardList.js'), 'InteractiveList');\nconst ActivityFeed = onDemand(() => import('./DashboardActivity.js'), 'ActivityFeed');\nconst FindSection = onDemand(() => import('./DashboardFind.js'), 'FindSection');\nconst BrandingForm = onDemand(() => import('./BrandingForm.js'), 'BrandingForm');\nconst IntegrationsForm = onDemand(() => import('./IntegrationsForm.js'), 'IntegrationsForm');\n/* A section's own period picker, with the rules of the heading row that holds it. */\nconst SectionPeriod = onDemand(() => import('@mistriwork/kit/client/components/SectionPeriod.js'), 'SectionPeriod');\n\ninterface Breakdown {\n columns?: string[];\n rows?: Array<Record<string, unknown>>;\n names?: Record<string, Record<string, string>>;\n}\ninterface Rows {\n rows?: Array<Record<string, unknown>>;\n}\ntype Row = Record<string, unknown>;\n\n/* What a read says about the time it is asked at: a window (\"last 30 days\"), a day or a period named from now. A\n figure that says none changes only when the data does, and live sync (liveSync.ts) tells the page when. */\nconst TIME_RELATIVE =\n /\\b(?:now|today|yesterday|tomorrow|ago|(?:this|last|next|past|previous)\\s+(?:\\d+\\s+)?(?:day|week|month|quarter|year)s?)\\b/i;\n\n/* The youngest answer the minute reads again. Query asks the interval again after every answer, so a tile read at\n :00.2 ticks at the next :00, a minute old; one read at :58 waits for the minute after. */\nconst TICK_FLOOR = 15_000;\n\n/**\n * The minute tick: asked again on the wall-clock minute, asleep with the tab (Query's refetchIntervalInBackground is\n * off). A read that depends on the time always ticks; every other read ticks while the page follows no changes to its\n * table (an App without `live: true`, `--no-live`, or a resource's own `live: false`), since nothing else would tell a\n * dashboard left on a wall that its data moved.\n */\nexport const minuteTick = (\n text: string | null | undefined,\n table?: string,\n following: (table?: string) => boolean = liveFollowing,\n): ((query?: { state: { dataUpdatedAt: number } }) => number | false) | false => {\n if (!text) return false;\n const timed = TIME_RELATIVE.test(text);\n return (query) => {\n if (!timed && following(table)) return false;\n const now = Date.now();\n const next = 60_000 - (now % 60_000);\n /* An answer read moments before the minute (a page opened at :58, the first paint's carried answers) is not read\n again at :00: the tick that would land on it goes to the minute after. */\n const read = query?.state.dataUpdatedAt;\n return read && now + next - read < TICK_FLOOR ? next + 60_000 : next;\n };\n};\n\n/* A tile is an aggregate, and says what it is as of: re-read when a change\n to its tables is announced (liveSync.ts), a write that invalidates it, the\n minute for a read that depends on the time, or after two minutes, not every\n time the dashboard is opened again or its tab regains focus. */\nconst TILE_FRESH = 120_000;\n/* The most currencies a figure says apart: more than this is a report, not a card. */\nconst CURRENCIES_SAID = 6;\n\n/* Here, not in dashboardModel.ts: only a dashboard sums a measure apart per currency, and that model is first-page code (PageMetrics). */\n/** The path a section's money measure is grouped by, where each row says its own currency and the section's query does not pin one. */\nfunction currencySplit(section: Pick<Section, 'table' | 'measure' | 'format' | 'query'>): string | undefined {\n if (section.format || /\\s[*/+-]\\s/.test(section.measure ?? '')) return undefined;\n const m = /^(?:sum|avg|min|max|median)\\s+([A-Za-z0-9_.]+)(?:\\s+as\\s+\\w+)?$/i.exec((section.measure ?? '').trim());\n const rule = m && section.table ? (columnDisplay(section.table, m[1]) as { format?: string; currencyColumn?: string } | null) : null;\n const path = rule?.format === 'money' ? currencyPath(rule, m![1]) : undefined;\n return path && !pinnedCurrency(section.query, path) ? path : undefined;\n}\n\n/* `table`: the resource the read is over, whose own `live: false` keeps it on the minute tick on a live App. */\nfunction useBreakdown(text: string | null, table?: string, limit?: number) {\n return useQuery<Breakdown>({\n queryKey: ['breakdown', text, limit ?? null],\n queryFn: () => {\n if (!text) throw new Error(sayCopy('thisSectionHasNoBreakdown'));\n // Asked with the other sections of this paint, in one request (breakdownBatch.ts).\n return batchedBreakdown<Breakdown>({ text, limit });\n },\n enabled: Boolean(text),\n refetchInterval: minuteTick(text, table),\n staleTime: TILE_FRESH,\n placeholderData: keepPreviousData,\n });\n}\n\nfunction useRows(q: string | null, limit: number, table?: string) {\n return useQuery<Rows>({\n queryKey: ['run', q, limit],\n queryFn: () => {\n if (!q) throw new Error(sayCopy('thisSectionHasNoRecord'));\n // With the section's numbers, in one request (breakdownBatch.ts).\n return batchedRun<Rows>({ q, limit, offset: 0, count: 'none' });\n },\n enabled: Boolean(q),\n refetchInterval: minuteTick(q, table),\n staleTime: TILE_FRESH,\n placeholderData: keepPreviousData,\n });\n}\n\n/** One measure over one query, as a number — the home card's fetch. */\nfunction useMeasure(section: Pick<Section, 'table' | 'measure' | 'format'>, query: string | undefined, enabled = true) {\n /* Money each row says its own currency for is summed apart per currency (CurrencyFigures). */\n const split = currencySplit({ ...section, query });\n const text = split ? `${measureText(section, query)} by ${split}` : measureText(section, query);\n return useQuery<unknown>({\n queryKey: ['measure', text],\n queryFn: async () => {\n const data = await batchedBreakdown<Breakdown>({ text, limit: split ? CURRENCIES_SAID : 1 });\n if (split) {\n /* The currency first, the figure last, whatever the server says between them. */\n const figures = (data.rows ?? []).flatMap((row) => {\n const keys = Object.keys(row);\n const code = row[keys[0]];\n return typeof code === 'string' && code.trim() ? [[code.trim().toUpperCase(), row[keys[keys.length - 1]]] as const] : [];\n });\n return figures.length ? new CurrencyFigures(figures) : null;\n }\n const row = data.rows?.[0];\n return row ? row[Object.keys(row)[0]] : null;\n },\n enabled,\n refetchInterval: minuteTick(text, section.table),\n staleTime: TILE_FRESH,\n placeholderData: keepPreviousData,\n });\n}\n\n/**\n * A section authored `empty: 'hide'` that has nothing to draw says so to the shell round it, which leaves the whole\n * section out — its heading and its place in the grid with it — rather than drawing a title over an empty note.\n * The section stays mounted, so its question keeps being asked and it returns when something arrives.\n */\nconst LeaveOutContext = createContext<(gone: boolean) => void>(() => {});\nfunction LeaveOut() {\n const leave = useContext(LeaveOutContext);\n useEffect(() => {\n leave(true);\n return () => leave(false);\n }, [leave]);\n return null;\n}\n\n/**\n * One dashboard section's own box, hidden while the section inside it has asked to be left out. On a layout the grid\n * decides when (`report` says what each section asks, `hidden` is what the grid has settled on): a section that left\n * out the moment its own answer arrived would move the areas round it once for every tile that answers.\n */\nfunction SectionShell({\n className,\n children,\n at,\n report,\n hidden,\n}: {\n className: string;\n children: ReactNode;\n at?: number;\n report?: (at: number, gone: boolean) => void;\n hidden?: boolean;\n}) {\n const [gone, setGone] = useState(false);\n const leave = useCallback(\n (now: boolean) => {\n setGone(now);\n if (at !== undefined) report?.(at, now);\n },\n [at, report],\n );\n return (\n <section className={className} hidden={(report ? hidden : gone) || undefined}>\n <LeaveOutContext.Provider value={leave}>{children}</LeaveOutContext.Provider>\n </section>\n );\n}\n\n/**\n * Where a section's groups go. In an App that is one of its lists, never the database browser: the list its `to`\n * names, else the one list over its table this reader is served; with none, or several, the groups are text\n * (`null`) and `mistri check` says which. In the browser (`undefined`) a group opens the table's rows.\n */\nfunction drillTarget(section: Section): string | null | undefined {\n if (section.noDrill) return null;\n const app = activeApp() as Parameters<typeof appRooms>[0] | null;\n if (!inAppMode() || !app) return undefined;\n if (section.view) {\n const room = viewRoom(app, section.view);\n return room && isListRoom(room) && !room.error ? section.view : null;\n }\n const lists = appRooms(app).filter((room) => isListRoom(room) && !room.error && room.table === section.table);\n return lists.length === 1 ? lists[0].id : null;\n}\n\n/** A group's doorway: followed in place, and where a list takes it, also a link a reader can open in a new tab. */\ntype Drill = ((value: unknown) => void) & { link: (value: unknown) => ViewLink | undefined };\n\n/**\n * A group is a doorway when the `by` is a plain column path: clicking\n * \"on_hold · 70\" opens the list filtered to that group, on top of\n * whatever the section (and the reader's window) already narrowed. A\n * bucketed by — \"month opened_on\" — stays read-only: its groups are\n * derived values the filter grammar does not take as equalities.\n */\nfunction drillFor(section: Section): Drill | null {\n if (!section.by || /\\s/.test(section.by)) return null;\n const target = drillTarget(section);\n if (target === null) return null;\n const queryFor = (value: unknown) => `${section.table} ${andQuery(section.query, `${section.by} = ${quote(String(value))}`)}`;\n const open = (value: unknown) => {\n if (value == null) return;\n if (target === undefined) go(tableView(section.table, queryFor(value)), 'push');\n else {\n const entry = listEntry(target, queryFor(value));\n if (entry) go(entry, 'push');\n }\n };\n return Object.assign(open, {\n link: (value: unknown) => (target && value != null ? listLink(target, queryFor(value)) : undefined),\n });\n}\n\n/** A group's key as its reader says it: the column's display rule, and in an\n App the column's vocabulary as words (valueModel.ts, groupLabel). */\nfunction sayGroup(table: string | undefined, column: string | undefined) {\n /* A weekday bucket answers 1 (Monday) to 7, an hour bucket 00 to 23: said as the reader's day and hour. */\n const bucket = /^(weekday|hour)\\s/i.exec(column ?? '')?.[1]?.toLowerCase();\n if (bucket) return (key: unknown) => sayBucket(bucket, key);\n const rule = columnDisplay(table ?? '', column ?? '') as DisplayRule | null;\n const allowed = (findTable(table ?? '') as TableMeta | undefined)?.columns.find((c) => c.name === column)?.allowed;\n return (key: unknown) => groupLabel(rule, key, allowed);\n}\n\n/** A weekday or hour bucket's key in the reader's words: 2024-01-01 was a Monday. */\nfunction sayBucket(bucket: string, key: unknown): string {\n const n = Number(key);\n if (key == null || key === '' || !Number.isInteger(n)) return String(key ?? '—');\n const at = bucket === 'weekday' ? new Date(Date.UTC(2024, 0, n)) : new Date(Date.UTC(2024, 0, 1, n));\n const options: Intl.DateTimeFormatOptions =\n bucket === 'weekday' ? { weekday: 'short', timeZone: 'UTC' } : { hour: 'numeric', timeZone: 'UTC' };\n return at.toLocaleString(formatLocale(), options);\n}\n\n/* The schema as the dashboard's asks read it (shared/dashboardAsks.ts), through the walk's own helpers. */\nconst lookups: AskLookups = {\n table: (id) => findTable(id) as TableMeta | undefined,\n references: (id) => refsFrom(id) as ForeignKey[],\n referenceNames,\n naming: (table) => labelPath(table) as string | undefined,\n};\n\n/* ---------- metric ---------- */\n\n/** A section's mark, leading its title: one of the App's curated icons, its glyph in the App payload. */\nfunction Mark({ section }: { section: Section }) {\n return section.icon ? <Icon name={section.icon} size={16} className=\"dash-section-icon\" /> : null;\n}\n\n/** A change's news, as a class: ' good' or ' bad' where the metric says which way is better, else nothing. */\nexport function changeTone(diff: number, better: 'up' | 'down' | undefined): '' | ' good' | ' bad' {\n if (!better || diff === 0 || !Number.isFinite(diff)) return '';\n return diff > 0 === (better === 'up') ? ' good' : ' bad';\n}\n\n/** What a compare window is, as a card says it beside its change: \"vs prior 90 days\". */\nexport function comparedWith(compare: string | undefined, level = false): string | undefined {\n const period = /\\bprevious\\s+(\\d+)\\s+(minute|hour|day|week|month|year)s?\\b/i.exec(compare ?? '');\n if (!period) return compare ? sayCopy(level ? 'sameAsTheCompareWindow' : 'vsTheCompareWindow') : undefined;\n const n = Number(period[1]);\n return sayCopy(level ? 'sameAsPrior' : 'vsPrior', { period: n === 1 ? period[2].toLowerCase() : `${n} ${period[2].toLowerCase()}s` });\n}\n\ninterface MetricProps {\n section: Section;\n /** The section's own period picker, when it has windows of its own (SectionPeriod). */\n period?: ReactNode;\n /** The reader has picked a window on this dashboard: a card it does not move says so. */\n windowed?: boolean;\n /** A card beside it in the row says the window it is over: a card with none says it is the present, so\n the row reads evenly rather than one figure standing with nothing under it. */\n dated?: boolean;\n /** Home keeps its own click and its own way of saying what went wrong. */\n onOpen?: () => void;\n onErrorClick?: () => void;\n}\n\n/**\n * One KPI card: the number, its label, its delta when a compare window is\n * given. The app home's cards and a dashboard's metrics are this same\n * card. A card carrying a resolution `error` shows the honest dash.\n */\nexport const Metric = memo(function Metric({\n section,\n windowed: offered = false,\n dated = false,\n period,\n onOpen,\n onErrorClick,\n}: MetricProps) {\n const label = section.title ?? section.table ?? '';\n const windowNote = section.windowNote;\n const live = !section.error;\n const now = useMeasure(section, section.query, live);\n const say = sayer(section, now.data, { card: true });\n /* The figure whole, where the card says it compact: its title, and what a screen reader hears. */\n const sayWhole = sayer(section, now.data, { whole: true });\n const then = useMeasure(section, section.compare, live && Boolean(section.compare));\n /* A goal read from data is a second measure, in the metric's own words; a number needs no read. */\n const goalAsk = typeof section.target === 'object' && section.target ? section.target : undefined;\n const goalData = useMeasure(goalAsk ?? section, goalAsk?.query, live && Boolean(goalAsk));\n /* The spark: over a window, the metric across that window in the span's\n unit — thirty days of \"last 30 days\", twelve months of \"last 12\n months\" — drawn under the number beside its change; with none, the\n author's `spark: true` is the last twelve months by the section's own\n clock (`over`). It composes with whatever the card is narrowed to by\n other than time: a picked owner's card shows a picked owner's trend. */\n /* No trend line through several currencies' sums: there is no one line to draw. */\n const sparkAsk = live && !currencySplit(section) ? sparkText(section) : null;\n const spark = useBreakdown(sparkAsk, section.table);\n\n const shown = section.error ? '—' : now.isError ? '—' : now.data === undefined ? '…' : say(now.data);\n const whole = section.error || now.isError || now.data === undefined ? shown : sayWhole(now.data);\n /* While the figure is read it is a placeholder at the figure's own size, not \"…\" set at the figure's 32px, which\n stood on the card as three heavy dots. Heard as \"…\" still (heard, below). */\n const figure = shown === '…' ? <span className=\"sk-bar home-card-wait\" aria-hidden=\"true\" /> : shown;\n let delta: ReactNode = null;\n /* The change's news, which the trend beside it is drawn in too. */\n let tone = '';\n if (section.compare && now.data != null && then.data != null) {\n const a = Number(now.data);\n const b = Number(then.data);\n if (Number.isFinite(a) && Number.isFinite(b)) {\n const diff = a - b;\n /* Coloured only when the author said which way is good news. \"More\"\n is not always \"better\", so without a word the tone stays neutral. */\n tone = changeTone(diff, section.better);\n /* A change says what it is a change from: \"↓ $785.1K\" alone left the\n reader to guess the period it was measured against. */\n const against = comparedWith(section.compare, diff === 0);\n /* Unchanged is one phrase, \"Same as prior 30 days\", not a figure with nothing to say. */\n delta =\n diff === 0 ? (\n <span className=\"dash-delta\" title={sayCopy('inTheCompareWindow', { b: say(b), compare: section.compare })}>\n <span className=\"dash-delta-whole\">{against ?? sayCopy('sameAsBefore')}</span>\n </span>\n ) : (\n <span className={`dash-delta${tone}`} title={sayCopy('inTheCompareWindow', { b: say(b), compare: section.compare })}>\n <span className=\"dash-delta-figure\">{`${diff > 0 ? '↑' : '↓'} ${say(Math.abs(diff))}`}</span>\n {against && (\n <>\n {' '}\n <span className=\"dash-delta-period\">{against}</span>\n </>\n )}\n </span>\n );\n }\n }\n const sparkPoints = useMemo(() => {\n const rows = spark.data;\n if (!rows) return null;\n const [keyName, valueName] = rows.columns ?? [];\n const read = (rows.rows ?? [])\n .map((r) => ({ key: r[keyName], value: r[valueName] }))\n .sort((a, b) => (String(a.key) < String(b.key) ? -1 : String(a.key) > String(b.key) ? 1 : 0));\n const over = sparkWindow(section);\n const now = new Date();\n return over ? trendPoints(read, over.read, over.unit, section.measure, dateWindow(over.phrase, now), now) : read;\n }, [spark.data, section]);\n /* Both slots stand from the first paint: a change the card will show holds its line while the two figures are\n read, and a trend its height, so neither arrives by pushing the card taller. */\n const deltaSlot = delta ?? (\n <span className=\"dash-delta\" aria-hidden={section.compare ? 'true' : undefined}>\n {section.compare && !section.error ? '\\u00a0' : null}\n </span>\n );\n const sparkSlot = sparkAsk ? <SparkHost points={sparkPoints} say={say} tone={tone} /> : null;\n /* A goal makes the card a meter: the share reached drawn under the number\n and said beside it, the bar full at the goal and never past it. */\n const goalAt = typeof section.target === 'number' ? section.target : goalAsk ? Number(goalData.data ?? NaN) : NaN;\n const goal = Number.isFinite(goalAt) && goalAt > 0 ? goalAt : undefined;\n const reached =\n goal !== undefined && !section.error && now.data != null && Number.isFinite(Number(now.data)) ? Number(now.data) / goal : undefined;\n /* A whole is the figure's own cohort counted without its extra conditions: said as a share of it, \"118 of 159\n (74%)\", not as a goal reached. */\n const share = reached === undefined ? undefined : formatPercent(reached * 100, { maximumFractionDigits: 0 });\n const wholeWords = section.targetWhole && goal !== undefined && share !== undefined;\n const goalWords =\n goal === undefined\n ? ''\n : reached === undefined\n ? sayCopy('target', { goal: say(goal) })\n : section.targetWhole\n ? sayCopy('ofWhole', { figure: say(now.data), whole: say(goal), reached: share! })\n : sayCopy('ofTarget', { reached: share!, goal: say(goal) });\n /* What a screen reader hears: the figure once, then its share, never the visible words after the figure again. */\n const heard = wholeWords\n ? `${label}: ${sayCopy('ofWholeSaid', { figure: sayWhole(now.data), whole: sayWhole(goal), percent: String(Math.round(reached! * 100)) })}`\n : `${label}: ${whole}${goalWords ? `, ${goalWords}` : ''}`;\n /* A metric that names a list view opens that room — its tabs, its\n presentation — on the rows it counted, and says so with an arrow: the\n whole card is the way in. One the reader is not served opens the table. */\n const app = activeApp();\n const opens = section.view && app && viewRoom(app, section.view) ? section.view : undefined;\n /* `to: false`: a figure that is read where it stands, not a way into rows, so nothing in it is a control. */\n const still = section.noDrill === true && !section.error;\n const open = section.error\n ? (onErrorClick ?? (() => {}))\n : (onOpen ?? (() => go({ ...tableView(section.table, fullQuery(section)), ...(opens ? { view: opens } : {}) }, 'push')));\n /* A card with its own period holds the picker, and a button cannot hold\n another control: the card is a box, its label the way in. */\n if (period) {\n return (\n <div className={`home-card home-card-period${opens ? ' opens-view' : ''}`} title={section.error ?? fullQuery(section)}>\n <span className=\"home-card-value\" aria-hidden=\"true\" title={whole === shown ? undefined : whole}>\n {figure}\n </span>\n <span className=\"home-card-label\">\n {still ? (\n <span className=\"home-card-open\" aria-label={heard}>\n <Mark section={section} />\n {label}\n </span>\n ) : (\n <button type=\"button\" className=\"home-card-open\" aria-label={heard} onClick={open}>\n <Mark section={section} />\n {label}\n {opens && (\n <>\n {/* A word joiner: the arrow follows the label's last word, never wraps alone. */}\n {'\\u2060'}\n <span className=\"home-card-go\" aria-hidden=\"true\">\n →\n </span>\n </>\n )}\n </button>\n )}\n {period}\n </span>\n {deltaSlot}\n {windowNote && !section.error && <span className=\"dash-fixed dash-window\">{windowNote}</span>}\n {goal !== undefined && (\n <span className=\"dash-target\">\n <span className=\"dash-target-meter\" aria-hidden=\"true\">\n <span style={{ width: `${Math.round(Math.min(1, Math.max(0, reached ?? 0)) * 100)}%` }} />\n </span>\n <span className=\"dash-target-text\">{goalWords}</span>\n </span>\n )}\n {sparkSlot}\n </div>\n );\n }\n const Card = still ? 'div' : 'button';\n return (\n <Card\n {...(still ? { role: 'group' } : { type: 'button' as const, onClick: open })}\n className={`home-card${still ? ' home-card-still' : opens ? ' opens-view' : ''}`}\n aria-label={heard}\n title={section.error ?? fullQuery(section)}\n >\n <span className=\"home-card-value\" title={whole === shown ? undefined : whole}>\n {figure}\n </span>\n <span className=\"home-card-label\">\n <Mark section={section} />\n {label}\n {opens && (\n <>\n {/* A word joiner: the arrow follows the label's last word, never wraps alone. */}\n {'\\u2060'}\n <span className=\"home-card-go\" aria-hidden=\"true\">\n →\n </span>\n </>\n )}\n </span>\n {deltaSlot}\n {/* The window above moves every card that has a clock; once the reader\n has picked one, a card without says so, quietly. Under All time no\n card is narrowed, so the note would only be noise on a card that\n was never about time — what is on order, what is short. */}\n {offered && !section.over && !section.error && (\n <span className=\"dash-fixed\" title={sayCopy('theTimeWindowAbove')}>\n {sayCopy('fixedWindow')}\n </span>\n )}\n {/* A card over a clock with no window counts every time; one with no clock counts what stands now. */}\n {dated && !offered && !windowNote && !section.error && (\n <span className=\"dash-fixed\">{sayCopy(section.over ? 'allTime' : 'fixedWindow')}</span>\n )}\n {/* The window the author set, said under the figure rather than wrapped into its label (metricWindow). */}\n {windowNote && !section.error && <span className=\"dash-fixed dash-window\">{windowNote}</span>}\n {goal !== undefined && (\n <span className=\"dash-target\">\n <span className=\"dash-target-meter\" aria-hidden=\"true\">\n <span style={{ width: `${Math.round(Math.min(1, Math.max(0, reached ?? 0)) * 100)}%` }} />\n </span>\n <span className=\"dash-target-text\">{goalWords}</span>\n </span>\n )}\n {sparkSlot}\n </Card>\n );\n});\n\n/** The measure's shape inside the card, its height held while it is read and where it has too few points to draw. */\nfunction SparkHost({\n points,\n say,\n tone,\n}: {\n points: Array<{ key: unknown; value: unknown }> | null;\n say: (v: unknown) => string;\n tone: string;\n}) {\n return <span className={`spark-host is-reserved${tone}`}>{points && points.length >= 4 && <Sparkline rows={points} say={say} />}</span>;\n}\n\n/* ---------- breakdown, chart, matrix ---------- */\n\n/* How many groups a breakdown asks for before it orders them itself (orderGroups): shared/dashboardAsks.ts. */\nconst askedFor = groupsAskedFor;\n\n/** The order of the column a section groups by, where it declares one (groupOrder.ts, declaredOrder). */\nfunction orderOf(table: string | undefined, by: string | undefined): { vocabulary?: string[]; scale: boolean } {\n /* A computed column (an age in days) is not among the table's own columns: its declared type says whether it is a\n scale (shared/computed.ts). */\n const meta = findTable(table ?? '') as TableMeta | undefined;\n const computed = by && meta?.computed && Object.hasOwn(meta.computed, by) ? meta.computed[by] : undefined;\n const column = meta?.columns.find((c) => c.name === by) ?? (computed ? { type: computed.type } : undefined);\n return declaredOrder(column, by ? (columnDisplay(table ?? '', by) as DisplayRule | null) : null, by);\n}\n\n/**\n * A breakdown's goals by group key (G76): each group's goal, the groups with a goal and nothing measured yet (a seller\n * with a quota and no wins is at 0%, not missing), and the goal answer's names for those.\n */\nfunction goalsOf(section: Section, answer: Breakdown | undefined, keyName: string, countName: string) {\n const goal = section.target;\n if (typeof goal !== 'object' || !goal.by || !answer) return undefined;\n const [goalKey, goalValue] = answer.columns ?? [];\n const goals = new Map<string, number>();\n for (const row of answer.rows ?? []) {\n const value = Number(row[goalValue]);\n if (row[goalKey] != null && Number.isFinite(value) && value > 0) goals.set(String(row[goalKey]), value);\n }\n return {\n of: (key: unknown) => (key == null ? undefined : goals.get(String(key))),\n /* Each goal's group the measure has no row for, at nothing reached. */\n unmet: (measured: readonly Record<string, unknown>[]) => {\n const seen = new Set(measured.map((row) => String(row[keyName])));\n return (answer.rows ?? [])\n .filter((row) => row[goalKey] != null && goals.has(String(row[goalKey])) && !seen.has(String(row[goalKey])))\n .map((row) => ({ [keyName]: row[goalKey], [countName]: 0 }));\n },\n sayKey: namedGroups(answer, goalKey, sayGroup(goal.table, goal.by)),\n };\n}\n\n/** The vocabulary of the column a section groups by, where one is declared. */\nconst vocabularyOf = (table: string | undefined, column: string | undefined): string[] | undefined => orderOf(table, column).vocabulary;\n\nconst BreakdownRows = memo(function BreakdownRows({ section }: { section: Section }) {\n const data = useBreakdown(breakdownText(section, askedFor(section)), section.table);\n /* A goal per group (G76): the target table's measure by its own column, a seller's quota beside their won. */\n const goals = useBreakdown(targetText(section), typeof section.target === 'object' ? section.target?.table : undefined);\n const drill = drillFor(section);\n const say = sayer(section);\n if (data.isError) return <Problem text={(data.error as Error).message} />;\n if (goals.isError) return <Problem text={(goals.error as Error).message} />;\n /* While read, its rows as they will stand — a group's word, its count's place, its bar — one per group the\n vocabulary or the limit says will come: an empty box was nothing tall, and the rows arriving pushed the sections\n under it down. */\n if (!data.data || (targetText(section) && !goals.data)) {\n const expected = Math.min(Math.max(section.limit ?? vocabularyOf(section.table, section.by)?.length ?? 3, 1), 8);\n return (\n <div className=\"page-breakdown-rows\" role=\"status\" aria-busy=\"true\">\n {Array.from({ length: expected }, (_, i) => (\n <div key={i} className=\"pbd-row pbd-wait\" aria-hidden=\"true\">\n <span className=\"pbd-label\">\n <span className=\"sk-bar\" style={{ width: `${[58, 44, 66, 38][i % 4]}%`, height: '10px' }} />\n </span>\n <span className=\"pbd-bar\" />\n <span className=\"pbd-count\">{'\\u00a0'}</span>\n </div>\n ))}\n </div>\n );\n }\n const [keyName, countName] = data.data.columns ?? [];\n const goal = goalsOf(section, goals.data, keyName, countName);\n const { vocabulary, scale } = orderOf(section.table, section.by);\n /* A scale with a limit keeps its largest groups, then reads them in its order: the first five days of an age\n histogram are not its five busiest. */\n const measured = [...(data.data.rows ?? []), ...(goal?.unmet(data.data.rows ?? []) ?? [])];\n const kept = scale && !vocabulary && section.limit ? orderGroups(measured, keyName, countName).slice(0, section.limit) : measured;\n const rows = orderDeclared(kept, keyName, countName, vocabulary, scale).slice(0, section.limit);\n if (!rows.length)\n return section.emptyMode === 'hide' ? (\n <LeaveOut />\n ) : (\n <Nothing text={inAppMode() ? sayCopy('nothingToCountYet') : sayCopy('noToCount', { table: section.table ?? '' })} />\n );\n const largest = Math.max(...rows.map((r) => Number(r[countName]) || 0));\n const sayRow = say.among(rows.map((r) => r[countName]));\n const sayKey = namedGroups(data.data, keyName, goal?.sayKey ?? sayGroup(section.table, section.by));\n /* A group of a column that colors its values (a severity, a state) wears that color, as its chip does in a list and\n a chart's bar does (G209). Against a goal the bar is progress, not the group's meaning, so it keeps the accent. */\n const toneOf =\n !goal && section.by && !/\\s/.test(section.by)\n ? (key: unknown) => TONE_INK[ruleSays(columnDisplay(section.table ?? '', section.by!) as DisplayRule | null, key).tone ?? '']\n : undefined;\n return (\n <div className=\"page-breakdown-rows\">\n {rows.map((row, i) => {\n const key = row[keyName];\n /* Against a goal the bar is the share reached, full at the goal and never past it, as a metric's meter. */\n const target = goal?.of(key);\n const reached = target ? (Number(row[countName]) || 0) / target : undefined;\n const ink = toneOf?.(key);\n const parts = (\n <>\n <span className=\"pbd-label\">{sayKey(key)}</span>\n <span className=\"pbd-bar\">\n <span\n className={`pbd-fill${ink ? ' is-toned' : ''}`}\n style={{\n width: `${goal ? Math.round(Math.min(1, Math.max(0, reached ?? 0)) * 100) : barShare(row[countName], largest)}%`,\n ...(ink ? { ['--bar-ink' as string]: ink } : {}),\n }}\n />\n </span>\n <span className=\"pbd-count\">\n {sayRow(row[countName])}\n {target !== undefined && (\n <span className=\"pbd-goal\">\n {' '}\n {sayCopy('ofTarget', { reached: formatPercent(reached! * 100, { maximumFractionDigits: 0 }), goal: say(target) })}\n </span>\n )}\n </span>\n </>\n );\n /* A row that goes somewhere is a button; one that cannot (a null\n group, no drill) stays text — no dead cursors. */\n const link = drill && key != null ? drill.link(key) : undefined;\n const title = sayCopy('openTableWhereBy', { table: section.table ?? '', by: section.by ?? '', key: String(key) });\n if (link)\n return (\n <a key={i} className=\"pbd-row pbd-drill\" href={link.href} title={title} onClick={link.onClick}>\n {parts}\n </a>\n );\n return drill && key != null ? (\n <button key={i} type=\"button\" className=\"pbd-row pbd-drill\" title={title} onClick={() => drill(key)}>\n {parts}\n </button>\n ) : (\n <div key={i} className=\"pbd-row\">\n {parts}\n </div>\n );\n })}\n </div>\n );\n});\n\n/**\n * A funnel: how many of a table's rows reach each stage, in order. The stages are counted in one statement\n * (shared/funnel.ts), so a later stage is never longer than the one before it. A stage opens the rows that reached it,\n * and the figure it lost opens the rows that stopped there — where the language can say them exactly.\n */\nconst FunnelSection = memo(function FunnelSection({ section }: { section: Section }) {\n const data = useBreakdown(funnelText(section), section.table);\n const say = sayer(section);\n const stages = section.stages ?? [];\n if (data.isError) return <Problem text={(data.error as Error).message} />;\n const row = data.data?.rows?.[0];\n if (row && !Number(row[stageColumn(0)]) && section.emptyMode === 'hide') return <LeaveOut />;\n const target = drillTarget(section);\n const door = (query: string | undefined): FunnelDoor | undefined => {\n if (target === null || !section.table) return undefined;\n if (query === undefined) return undefined;\n const text = `${section.table} ${andQuery(section.query, query)}`.trim();\n if (target === undefined) return { open: () => go(tableView(section.table, text), 'push') };\n const entry = listEntry(target, text);\n return entry ? { link: listLink(target, text), open: () => go(entry, 'push') } : undefined;\n };\n const chains = funnelChains(stages);\n const basis = funnelBasis(stages);\n return (\n <Funnel\n table={section.table ?? ''}\n say={say}\n steps={stages.map((stage, i) => ({\n title: stage.label,\n optional: stage.optional,\n count: row ? Number(row[stageColumn(i)]) || 0 : undefined,\n basis: basis[i],\n reached: door(chains[i] || ''),\n dropped: door(droppedQuery(stages, i)),\n }))}\n />\n );\n});\n\n/**\n * A breakdown drawn as steps: a card for each value of the column, in its\n * own order (the vocabulary's, else the counts'), joined by arrows — orders\n * received, picked, packed, shipped. A step's mark is the value's icon from\n * the column's display rule, in its tone; one without an icon has no mark (a number beside the count read as a second count).\n * A step goes to its list as a breakdown's row does. Every value of the\n * vocabulary is a step, so a stage with nothing in it still holds its place.\n */\nconst StepCards = memo(function StepCards({ section }: { section: Section }) {\n const data = useBreakdown(breakdownText(section, askedFor(section)), section.table);\n const drill = drillFor(section);\n const say = sayer(section);\n const vocabulary = vocabularyOf(section.table, section.by);\n const rule = columnDisplay(section.table ?? '', section.by ?? '') as DisplayRule | null;\n const sayKey = sayGroup(section.table, section.by);\n if (data.isError) return <Problem text={(data.error as Error).message} />;\n const [keyName = '', countName = ''] = data.data?.columns ?? [];\n const counted = data.data ? orderGroups(data.data.rows ?? [], keyName, countName, vocabulary) : [];\n const keys = vocabulary ?? counted.map((row) => row[keyName]);\n const countOf = new Map(counted.map((row) => [String(row[keyName]), row[countName]]));\n const steps = keys.filter((key) => key != null).slice(0, section.limit ?? 8);\n if (data.data && !steps.length) return section.emptyMode === 'hide' ? <LeaveOut /> : <Nothing text={sayCopy('nothingToCountYet')} />;\n // Rows of four or fewer, as even as the count allows (eight steps are two rows of four, not six and two): the\n // columns are named here so a step that starts a row is known to the looks that part the cells with hairlines.\n const cols = steps.length <= 4 ? Math.max(steps.length, 1) : Math.ceil(steps.length / Math.ceil(steps.length / 4));\n return (\n <ol\n className=\"dash-steps\"\n style={{ ['--steps' as string]: Math.max(steps.length, 1), ['--cols' as string]: cols }}\n aria-busy={!data.data || undefined}\n >\n {steps.map((key, index) => {\n const text = String(key);\n const { tone } = ruleSays(rule, text);\n const icon = rule?.icons && Object.hasOwn(rule.icons, text) ? (rule.icons[text] as AppIconName) : undefined;\n const note = section.notes?.[text];\n const figure = data.data ? say(countOf.get(text) ?? 0) : '\\u00a0';\n const body = (\n <>\n {icon && (\n <span className={`dash-step-mark${tone ? ` tone-${tone}` : ''}`} aria-hidden=\"true\">\n <Icon name={icon} size={16} />\n </span>\n )}\n <span className=\"dash-step-words\">\n <span className=\"dash-step-title\">{sayKey(key)}</span>\n {note && <span className=\"dash-step-note\">{note}</span>}\n </span>\n <span className=\"dash-step-figure\">{figure}</span>\n </>\n );\n return (\n <li\n key={text}\n className={`dash-step${tone ? ` is-${tone}` : ''}${index % cols === 0 ? ' is-row-start' : ''}${icon ? '' : ' no-mark'}`}\n >\n {drill ? (\n (() => {\n const link = drill.link(key);\n const title = sayCopy('openTableWhereBy', { table: section.table ?? '', by: section.by ?? '', key: text });\n return link ? (\n <a className=\"dash-step-card\" href={link.href} title={title} onClick={link.onClick}>\n {body}\n </a>\n ) : (\n <button type=\"button\" className=\"dash-step-card\" title={title} onClick={() => drill(key)}>\n {body}\n </button>\n );\n })()\n ) : (\n <div className=\"dash-step-card\">{body}</div>\n )}\n {index < steps.length - 1 && <Icon name=\"caret-right\" size={14} className=\"dash-step-arrow\" />}\n </li>\n );\n })}\n </ol>\n );\n});\n\n/**\n * A chart is a breakdown drawn instead of listed: same fetch, same\n * grammar, the rows handed to the SVG. Money measures speak money in the\n * ticks, the tooltips and the legend, through the same rule as everywhere.\n */\n/** The unit an `auto` chart chose, in words. */\nconst sayUnit = (unit: 'day' | 'week' | 'month' | 'quarter'): string =>\n unit === 'day' ? sayCopy('byDay') : unit === 'week' ? sayCopy('byWeek') : unit === 'month' ? sayCopy('byMonth') : sayCopy('byQuarter');\n\nconst Chart = memo(function Chart({ section }: { section: Section }) {\n /* Stacked bars cross two keys, as a matrix does: every cross is fetched\n and the chart keeps the longest bars, so `limit` counts bars, not rows. */\n const stacked = section.shape === 'stacked';\n const donut = section.shape === 'donut';\n const nothing = useNothing(inAppMode() ? sayCopy('nothingToDrawYet') : sayCopy('noToDraw', { table: section.table ?? '' }));\n /* Bars over categories are ordered here, as a donut's slices are, so they ask for every group first. */\n /* `auto` (autoChart.ts): the unit is chosen from the window and the data, so what is asked is the section in that\n unit (or nothing, while the data's extent is read), and what is drawn is the answer coarsened to it. */\n const auto = useAutoChart(section, (text) => useBreakdown(text, section.table));\n const data = useBreakdown(\n auto ? (auto.ask ? breakdownText(auto.ask, chartLimit(section)) : null) : breakdownText(section, chartLimit(section)),\n section.table,\n );\n const drawn = auto?.draw(data);\n const answer = auto ? drawn?.answer : data.data;\n const [firstKey = '', secondKey = ''] = (section.by ?? '').split(',').map((key) => key.trim());\n if (data.isError) return <Problem text={(data.error as Error).message} />;\n const label = namedGroups(answer, answer?.columns?.[0], sayGroup(section.table, firstKey));\n const seriesLabel = namedGroups(answer, secondKey ? answer?.columns?.[1] : undefined, sayGroup(section.table, secondKey));\n if (section.emptyMode === 'hide' && answer && !(answer.rows ?? []).length) return <LeaveOut />;\n /* The unit the chart chose, said as text under the title: the slot is held from the first paint so naming it moves nothing. */\n const unitNote = auto ? <p className=\"chart-unit\">{drawn?.unit ? sayUnit(drawn.unit) : null}</p> : null;\n if (section.shape && EXTRA_SHAPES.includes(section.shape))\n return (\n <>\n {unitNote}\n <ChartShapeFigure\n shape={section.shape as ExtraShape}\n answer={answer}\n say={sayer(section).among((answer?.rows ?? []).map((row) => row[answer?.columns?.at(-1) ?? '']))}\n /* The section's `format` and `unit` say its measure, the one up the side; the across measure is said by its own column. */\n sayX={section.x ? sayer({ ...section, measure: section.x, format: undefined, unit: undefined }) : undefined}\n names={{ x: section.x ?? '', y: section.measure ?? 'count' }}\n label={label}\n seriesLabel={seriesLabel}\n vocabulary={vocabularyOf(section.table, firstKey)}\n seriesVocabulary={secondKey ? vocabularyOf(section.table, secondKey) : undefined}\n limit={section.limit}\n target={typeof section.target === 'number' ? section.target : undefined}\n height={section.height}\n empty={nothing.text}\n emptyDetail={nothing.detail}\n emptyAction={nothing.action}\n />\n </>\n );\n return (\n <>\n {unitNote}\n <ChartFigure\n answer={answer}\n dots={drawn?.dots}\n shape={section.shape as 'line' | 'bar' | 'donut' | 'stacked' | undefined}\n limit={section.limit}\n target={typeof section.target === 'number' ? section.target : undefined}\n height={section.height}\n say={sayer(section)}\n label={label}\n seriesLabel={seriesLabel}\n vocabulary={vocabularyOf(section.table, firstKey)}\n seriesVocabulary={secondKey ? vocabularyOf(section.table, secondKey) : undefined}\n scale={orderOf(section.table, firstKey).scale}\n seriesScale={secondKey ? orderOf(section.table, secondKey).scale : undefined}\n seriesTone={\n stacked && secondKey\n ? (key) => ruleSays(columnDisplay(section.table ?? '', secondKey) as DisplayRule | null, key).tone\n : undefined\n }\n tone={\n (donut || section.shape === 'bar') && firstKey && !/\\s/.test(firstKey)\n ? (key) => ruleSays(columnDisplay(section.table ?? '', firstKey) as DisplayRule | null, key).tone\n : undefined\n }\n sayLegend={stacked ? (totals) => legendSayer(section, totals) : undefined}\n onPick={\n donut || section.shape === 'line'\n ? drillFor(section)\n : stacked && !/\\s/.test(firstKey)\n ? drillFor({ ...section, by: firstKey })\n : null\n }\n empty={nothing.text}\n emptyDetail={nothing.detail}\n emptyAction={nothing.action}\n curve={section.curve}\n total={section.total}\n />\n </>\n );\n});\n\n/**\n * A matrix: the measure crossed over two keys — rows by the first,\n * columns by the second, heat by the value. The pivot happens here (the\n * breakdown answers flat groups), columns sort ascending when they read\n * as dates and by weight otherwise, and the biggest cell sets the scale.\n */\n/**\n * Whether a matrix wider than its section is folded: each row said as its figures, each under its column's name,\n * rather than scrolled sideways (docs/design.md: nothing scrolls sideways inside a section). Its natural width is\n * read while it stands as a table, so it stands as one again when the room grows to hold it; `shape` is its rows\n * and columns, a change of which reads the width afresh.\n */\nfunction useMatrixFold(host: { current: HTMLDivElement | null }, shape: string): boolean {\n const [fold, setFold] = useState<{ shape: string; natural: number } | null>(null);\n useLayoutEffect(() => {\n const element = host.current;\n if (!element) return;\n const judge = () => {\n const table = element.querySelector('table');\n if (!table) return;\n const natural = fold?.shape === shape ? fold.natural : table.offsetWidth;\n const folds = natural > element.clientWidth + 1;\n setFold((was) => (folds ? (was?.shape === shape && was.natural === natural ? was : { shape, natural }) : null));\n };\n judge();\n const observer = new ResizeObserver(judge);\n observer.observe(element);\n return () => observer.disconnect();\n }, [host, shape, fold]);\n return fold?.shape === shape;\n}\n\nconst Matrix = memo(function Matrix({ section }: { section: Section }) {\n const data = useBreakdown(breakdownText(section, 400), section.table);\n const host = useRef<HTMLDivElement>(null);\n const shape = `${data.data?.rows?.length ?? 0}:${(data.data?.columns ?? []).join(',')}`;\n const folded = useMatrixFold(host, shape);\n if (data.isError) return <Problem text={(data.error as Error).message} />;\n if (!data.data) return <div className=\"matrix-host\" ref={host} />;\n const [rowKey, colKey, valueName] = data.data.columns ?? [];\n const cells = new Map<string, unknown>();\n const rowTotals = new Map<string, number>();\n const colTotals = new Map<string, number>();\n for (const r of data.data.rows ?? []) {\n const a = r[rowKey] == null ? '—' : String(r[rowKey]);\n const b = r[colKey] == null ? '—' : String(r[colKey]);\n const v = Number(r[valueName]) || 0;\n cells.set(`${a}\\u0000${b}`, r[valueName]);\n rowTotals.set(a, (rowTotals.get(a) ?? 0) + v);\n colTotals.set(b, (colTotals.get(b) ?? 0) + v);\n }\n if (!cells.size)\n return section.emptyMode === 'hide' ? (\n <LeaveOut />\n ) : (\n <Nothing text={inAppMode() ? sayCopy('nothingToCrossYet') : sayCopy('noToCross', { table: section.table ?? '' })} />\n );\n /* Rows in the first key's vocabulary order where it has one (a stage reads\n as a pipeline), else heaviest first; ten at most. */\n const rowKeyColumn = (section.by ?? '').split(',')[0].trim();\n const rows = orderGroups(\n [...rowTotals.entries()].map(([key, total]) => ({ key, total })),\n 'key',\n 'total',\n vocabularyOf(section.table, rowKeyColumn),\n )\n .slice(0, 10)\n .map(({ key }) => key);\n const dated = [...colTotals.keys()].every((k) => /^\\d{4}(-\\d{2})?/.test(k) || k === '—');\n /* Columns as the rows are: in the second key's vocabulary order where it\n has one (low, medium, high, urgent), else heaviest first; and said in\n its words, as a breakdown says them (\"Urgent\", not \"urgent\"). */\n const colKeyColumn = ((section.by ?? '').split(',')[1] ?? '').trim();\n const cols = dated\n ? [...colTotals.keys()].sort()\n : orderGroups(\n [...colTotals.entries()].map(([key, total]) => ({ key, total })),\n 'key',\n 'total',\n vocabularyOf(section.table, colKeyColumn),\n )\n .slice(0, 12)\n .map(({ key }) => key);\n const sayCol = namedGroups(data.data, colKey, sayGroup(section.table, colKeyColumn));\n const max = Math.max(...rows.flatMap((a) => cols.map((b) => Number(cells.get(`${a}\\u0000${b}`)) || 0)), 1);\n /* One form across the grid: where any cell reaches a thousand every cell is said compact, so \"$4,470\" never\n stands beside \"$548K\". The cell's title says the figure whole. */\n const sayWhole = sayer(section);\n const say = max >= 1000 ? sayWhole.tick : sayWhole;\n const firstKey = (section.by ?? '').split(',')[0].trim();\n const sayRow = namedGroups(data.data, rowKey, sayGroup(section.table, firstKey));\n const drill = !/\\s/.test(firstKey) ? drillFor({ ...section, by: firstKey }) : null;\n const colLabel = (b: string, at: number) => (dated ? periodTick(b, at ? cols[at - 1] : undefined) : sayCol(b === '—' ? null : b));\n /* Folded, the rows and cells are drawn as a grid, which drops a table's own roles: they are said, so a reader\n still hears each figure under its row and column. */\n return (\n <div className=\"matrix-host\" ref={host} data-fold={folded || undefined}>\n <div className=\"table-wrap matrix-wrap\">\n <table className=\"matrix\" role=\"table\">\n <thead role=\"rowgroup\">\n <tr role=\"row\">\n <th className=\"matrix-corner\" role=\"columnheader\" />\n {cols.map((b, at) => (\n <th key={b} className=\"matrix-col\" role=\"columnheader\">\n {colLabel(b, at)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody role=\"rowgroup\">\n {rows.map((a) => (\n <tr key={a} role=\"row\">\n <th className=\"matrix-row\" role=\"rowheader\">\n {drill ? (\n <button type=\"button\" className=\"matrix-drill\" onClick={() => drill(a)}>\n {sayRow(a)}\n </button>\n ) : (\n <span>{sayRow(a)}</span>\n )}\n </th>\n {cols.map((b, at) => {\n const raw = cells.get(`${a}\\u0000${b}`);\n const v = Number(raw) || 0;\n /* Heat says weight; the number stays the fact. Empty stays\n empty — a zero someone wrote and a cross nobody made are\n different silences. */\n return (\n <td\n key={b}\n className=\"matrix-cell\"\n role=\"cell\"\n data-label={folded ? String(colLabel(b, at) ?? '') : undefined}\n style={\n v\n ? ({\n /* Its share of the heaviest; features.css tints it up to the palette's heat top. */\n '--heat': (v / max).toFixed(3),\n background: 'var(--heat-fill)',\n } as CSSProperties)\n : undefined\n }\n title={v ? `${sayRow(a)} × ${dated ? b : sayCol(b === '—' ? null : b)}: ${sayWhole(raw)}` : undefined}\n >\n {v ? say(raw) : ''}\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n});\n\n/* ---------- list and board ---------- */\n\n/**\n * The full list, with its tabs and filters. An embed opens its view's own\n * room — its tabs, its presentation, its actions — on the rows the section\n * shows; any other section, the list its table and query suggest.\n */\nfunction OpenFull({ section }: { section: Section }) {\n useSyncExternalStore(subscribeMessages, messageLanguage, messageLanguage);\n return (\n <button\n type=\"button\"\n className=\"ghost dash-open\"\n title={sayCopy('theFullListWithItsTabs')}\n onClick={() => go({ ...tableView(section.table, fullQuery(section)), ...(section.view ? { view: section.view } : {}) }, 'push')}\n >\n {message('list.viewAll')}\n </button>\n );\n}\n\n/** A column a list says, a label path dressed as the column it ends in. */\nfunction columnAt(table: TableMeta | undefined, name: string): ColumnMeta | undefined {\n if (!table) return undefined;\n if (!name.includes('.')) return table.columns.find((column) => column.name === name);\n const [reference, terminal] = name.split('.');\n const fk = (refsFrom(table.id) as Array<{ from: { columns: string[] }; to: { table: string } }>).find(\n (candidate) => candidate.from.columns.length === 1 && candidate.from.columns[0] === reference,\n );\n const target = fk ? (findTable(fk.to.table) as TableMeta | undefined) : undefined;\n const column = target?.columns.find((candidate) => candidate.name === terminal);\n return column ? { ...column, name } : undefined;\n}\n\n/**\n * A list in the aside: names, not a table. The aside is a narrow column,\n * and a grid there cut its names short (\"Riley C…\") to keep columns nobody\n * compares. Each row is its first column, whole and wrapping; the second a\n * quiet line under it; a third a value at the row's end. The row opens its\n * record, the month's other rows its neighbours.\n */\nfunction AsideRows({\n section,\n table,\n query,\n empty,\n onRows,\n}: {\n section: Section;\n table: TableMeta | undefined;\n query: string;\n empty?: ReactNode;\n onRows: (data: { total?: number; exactTotal?: boolean }) => void;\n}) {\n const rows = useQuery<Rows & { total?: number; exactTotal?: boolean; errors?: Array<{ message: string }> }>({\n queryKey: ['run', query, section.limit ?? 5],\n queryFn: () => batchedRun({ q: query, limit: section.limit ?? 5, offset: 0 }),\n refetchInterval: minuteTick(query, section.table),\n staleTime: TILE_FRESH,\n placeholderData: keepPreviousData,\n });\n const data = rows.data;\n useEffect(() => {\n if (data && !data.errors?.length) onRows(data);\n }, [data]); // eslint-disable-line react-hooks/exhaustive-deps\n const [first, second, third] = section.show?.length ? section.show : table ? [labelColumn(table) ?? primaryKey(table)[0]] : [];\n /* A person named first wears their photo where the rule names one (avatarPhotos.tsx). */\n const nameRule = first ? (columnDisplay(section.table, first) as DisplayRule | null) : null;\n const photoOwner = first ? avatarOwner(table, first, nameRule, data?.rows?.length ? Object.keys(data.rows[0]) : undefined) : undefined;\n const photoOf = useAvatarPhotos(first ? [{ name: first, display: nameRule, photoOwner }] : [], data?.rows ?? []);\n if (rows.isError || data?.errors?.length) return <Problem text={(rows.error as Error | null)?.message ?? data!.errors![0].message} />;\n if (!data) return <div className=\"dash-mini\" />;\n const got = data.rows ?? [];\n if (!got.length) return <>{empty ?? <Empty text={message('list.nothing')} />}</>;\n const [name, line, value] = [first, second, third].map((path) => (path ? columnAt(table, path) : undefined));\n const pk: string[] = table ? primaryKey(table) : [];\n /* A reference says its record's name, which the section fetched beside it (List). */\n const referenceLabels = table && section.show?.length ? referenceNames(section.table as string, section.show) : undefined;\n const said = (column: ColumnMeta | undefined, row: Row) => {\n if (!column || !table) return null;\n const { column: drawn, value } = namedCell(table, column.name, row, referenceLabels);\n return value != null && value !== '' ? <Value tableId={section.table} col={drawn} value={value} compact /> : null;\n };\n const named = (row: Row) => {\n const photo = photoOwner && name ? photoOf(first, row[photoOwner]) : undefined;\n return photo && name && row[name.name] != null ? <AvatarText text={String(row[name.name])} photo={photo} /> : said(name, row);\n };\n const keyed = got.map((row) => ({ row, key: Object.fromEntries(pk.map((k) => [k, row[k]])), label: String(row[first] ?? '') }));\n const records = keyed.map(({ key, label }) => ({ key, label }));\n return (\n <ul className=\"dash-mini\" aria-label={section.title ?? section.table}>\n {keyed.map(({ row, key, label }, i) => (\n <li key={i}>\n <button\n type=\"button\"\n className=\"dash-mini-row\"\n disabled={!pk.length}\n onClick={() => void openRecord(section.table, key, label, 'push', { records })}\n >\n <span className=\"dash-mini-text\">\n <span className=\"dash-mini-name\">{named(row) ?? label}</span>\n {said(line, row) && <span className=\"dash-mini-line\">{said(line, row)}</span>}\n </span>\n {said(value, row) && <span className=\"dash-mini-value\">{said(value, row)}</span>}\n </button>\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * A list is the real table view with the chrome off — the vanilla grid,\n * drawn into a host. Its own stat row (count, timing, Export) is hidden\n * by CSS in here; the one number worth keeping — how many there are in\n * all — moves up beside the title once the answer knows it. In the aside\n * it is names instead (AsideRows), unless it embeds a view drawn its own way.\n */\nconst List = memo(function List({ section, aside = false, period }: { section: Section; aside?: boolean; period?: ReactNode }) {\n const [count, setCount] = useState('');\n /* How many the section matched, once known: \"View all\" over none is a door to an empty room. */\n const [matched, setMatched] = useState<number | undefined>();\n const table = findTable(section.table) as TableMeta | undefined;\n /* An explicit view embed keeps the dashboard's already-resolved question,\n but borrows the served view's dress and every column that dress reads.\n A raw dashboard list has no source view, so it stays the vanilla grid. */\n const app = activeApp();\n const room = section.view === undefined || !app ? undefined : viewRoom(app, section.view);\n const source = room && isListRoom(room) && room.table === section.table ? room : undefined;\n // A narrower dashboard question cannot promise the whole source list is empty.\n /* The section's own guidance first: a rows section may say what belongs in it, as a list view does. */\n const authoredEmpty = (section as { empty?: AppListEmpty }).empty;\n const sourceEmpty = authoredEmpty ? (\n <ListEmpty spec={authoredEmpty} />\n ) : source?.empty &&\n splitQuery(`rows ${source.query ?? ''}`).filter.trim() === splitQuery(`rows ${section.query ?? ''}`).filter.trim() ? (\n <ListEmpty spec={source.empty} />\n ) : undefined;\n /* The key columns ride along unseen when the section projects, the same\n bargain the app list strikes: a row with no key on it is a row that\n cannot open, and \"see the record\" is the whole point of a list. A\n reference is drawn by its record's name, fetched beside it and kept out\n of sight (shared/dashboardAsks.ts, whose words a first page is asked in). */\n const { query, keys, named, referenceLabels } = dashboardListQuery(lookups, section, source?.presentation);\n const onRows = (data: { total?: number; exactTotal?: boolean }) => {\n setMatched(data.total);\n if (!data.total) {\n setCount('');\n return;\n }\n setCount(data.exactTotal === false ? `~${formatApprox(data.total)}` : sayCopy('figureInAll', { figure: figure(data.total) }));\n };\n const presented = source?.presentation && source.presentation.kind !== 'split';\n const mini = aside && !presented && (section.show?.length ?? 0) <= 3;\n /* An embed that opted in works as its room does, under this heading (DashboardList.tsx). */\n const works = section.interactive && source && table;\n return (\n <>\n {section.emptyMode === 'hide' && matched === 0 && <LeaveOut />}\n <div className=\"dash-list-head\">\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title ?? section.table}\n </h2>\n <span className=\"stat dash-count\">{count}</span>\n {period}\n {matched !== 0 && <OpenFull section={section} />}\n </div>\n {works ? (\n <div className=\"dash-list dash-list-works\">\n <InteractiveList section={section} source={source} onTotal={(total: number | undefined) => onRows({ total })} />\n </div>\n ) : mini ? (\n <AsideRows section={section} table={table} query={query} empty={sourceEmpty} onRows={onRows} />\n ) : (\n <div className=\"dash-list\">\n <TableRoom\n entry={{ kind: 'table', table: section.table as string, query }}\n sizing={section.sizing}\n chrome={false}\n interactive={false}\n embedded\n hide={[...keys, ...named]}\n referenceLabels={referenceLabels}\n labels={section.labels}\n recordNavigation={source?.presentation?.kind === 'cards' || source?.presentation?.kind === 'queue'}\n {...(section.rowActions &&\n app &&\n mayRunAny(app, section.table as string, offeredBy(resourceOf(app, section.table as string)).actions ?? [])\n ? { rowActions: true, actions: offeredBy(resourceOf(app, section.table as string)).actions }\n : {})}\n presentation={source?.presentation}\n present={shell().present ?? undefined}\n listLabel={source?.label}\n order={source?.order}\n empty={sourceEmpty}\n export={exportOffered(app, section.table as string | undefined) ? undefined : false}\n onResult={onRows}\n />\n </div>\n )}\n </>\n );\n});\n\n/**\n * A board: lanes of cards by a column's values — the pipeline read every\n * CRM and queue screen is built around, here as one word of config. The\n * lanes are the column's declared vocabulary when the schema states one\n * (every stage shows, empty ones included — an empty lane is a fact),\n * and the observed values by weight when it does not. Read-only on\n * purpose: this layer curates reading, and a drag that writes belongs\n * to the write arc.\n */\nconst Board = memo(function Board({ section: authored }: { section: Section }) {\n const section = boardSection(authored);\n const table = findTable(section.table) as TableMeta | undefined;\n const counts = useBreakdown(boardCountText(section), section.table);\n const pk: string[] = table ? primaryKey(table) : [];\n const naming = table && labelColumn(table);\n const shown: string[] = section.show?.length ? section.show : naming ? [naming] : pk;\n const rule = columnDisplay(section.table, section.by);\n let lanes: ReactNode;\n if (counts.isError) lanes = <Problem text={(counts.error as Error).message} />;\n else if (counts.data) {\n const [keyName, countName] = counts.data.columns ?? [];\n const byValue = new Map(\n (counts.data.rows ?? []).filter((r) => r[keyName] != null).map((r) => [String(r[keyName]), Number(r[countName]) || 0] as const),\n );\n const vocabulary = (table?.columns.find((c) => c.name === section.by) as (ColumnMeta & { allowed?: string[] }) | undefined)?.allowed;\n const values = section.lanes ?? (vocabulary ?? [...byValue.keys()]).slice(0, 8);\n lanes = values.length ? (\n values.map((value) => (\n <Lane key={value} section={section} value={value} count={byValue.get(value) ?? 0} rule={rule} pk={pk} shown={shown} />\n ))\n ) : (\n <Empty text={inAppMode() ? sayCopy('nothingToLayOut') : sayCopy('noToLayOut', { table: section.table ?? '' })} />\n );\n }\n const nothingOnIt =\n Boolean(counts.data) && [...(counts.data?.rows ?? [])].every((r) => !(Number(r[counts.data?.columns?.[1] ?? '']) || 0));\n return (\n <>\n {authored.emptyMode === 'hide' && nothingOnIt && <LeaveOut />}\n <div className=\"board-head\">\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title ?? `${section.table} by ${section.by}`}\n </h2>\n <OpenFull section={section} />\n </div>\n <div className=\"dash-board\">{lanes}</div>\n </>\n );\n});\n\nfunction Lane({\n section,\n value,\n count,\n rule,\n pk,\n shown,\n}: {\n section: Section;\n value: string;\n count: number;\n rule: unknown;\n pk: string[];\n shown: string[];\n}) {\n const laneLimit = section.limit ?? 7;\n const laneQuery = andQuery(section.query, `${section.by} = ${quote(value)}`);\n const q = count\n ? [section.table, laneQuery, section.sort ? `sort ${section.sort}` : '', `show ${[...new Set([...shown, ...pk])].join(', ')}`]\n .filter(Boolean)\n .join(' ')\n : null;\n const rows = useRows(q, laneLimit, section.table);\n const got = rows.data?.rows ?? [];\n const [head, ...rest] = shown;\n return (\n <div className=\"board-lane\">\n <div className=\"board-lane-head\">\n {dressFor(rule as DisplayRule | null, value) ? (\n <Dressed dress={dressFor(rule as DisplayRule | null, value)!} compact={(rule as DisplayRule | null)?.format === 'richText'} />\n ) : (\n <span className=\"board-lane-name\">{value}</span>\n )}\n <span className=\"board-lane-count\">{figure(count)}</span>\n </div>\n <div className=\"board-cards\">\n {got.map((row: Row, i) => {\n const key = Object.fromEntries(pk.map((k) => [k, row[k]]));\n const said =\n row[head] == null\n ? '—'\n : (maskedText(columnDisplay(section.table, head) as DisplayRule | null, row[head]) ?? String(row[head]));\n return (\n <button key={i} type=\"button\" className=\"board-card\" onClick={() => void openRecord(section.table, key, said, 'push')}>\n <span className=\"board-card-title\">{said}</span>\n {rest.map((path) => {\n const v = row[path];\n if (v === null || v === undefined) return null;\n const dress = dressFor(columnDisplay(section.table, path) as DisplayRule | null, v);\n return (\n <span key={path} className=\"board-card-line\">\n {dress ? <Dressed dress={dress} compact={dress.kind === 'richText'} /> : <span>{String(v)}</span>}\n </span>\n );\n })}\n </button>\n );\n })}\n {count > got.length && rows.data && (\n <button\n type=\"button\"\n className=\"ghost board-more\"\n onClick={() => go(tableView(section.table, `${section.table} ${laneQuery}`), 'push')}\n >\n {sayCopy('moreCount', { figure: figure(count - got.length) })}\n </button>\n )}\n </div>\n </div>\n );\n}\n\n/* ---------- the controls ---------- */\n\n/**\n * The window picker: the unpicked state and the dashboard's offered phrases.\n * Unpicked is \"All time\" only when it is: where a section keeps a window of\n * its own (`close_date = last 90 days`), the pressed \"All time\" sat over\n * figures still counting their ninety days, so it says \"Default\" there, and\n * each figure says its own window (windowTitle, metricWindow).\n */\nfunction WindowRow({\n windows,\n current,\n onPick,\n ownWindows,\n control = 'segmented',\n}: {\n windows: string[];\n current: string | null;\n onPick: (w: string | null) => void;\n ownWindows: boolean;\n control?: 'segmented' | 'button';\n}) {\n const word = (w: string | null) => (w ? w.charAt(0).toUpperCase() + w.slice(1) : sayCopy(ownWindows ? 'defaultWindow' : 'allTimeWindow'));\n if (control === 'button') {\n /* The dates the window covers, its last day inclusive (the window's end is the next day's start); a phrase the\n calendar cannot place is said as itself. */\n const span = current ? dateWindow(current, new Date()) : undefined;\n const shown = span\n ? sayCopy('windowRange', {\n from: formatDate(span.start, { month: 'short', day: 'numeric' }),\n to: formatDate(new Date(span.end.getTime() - 86_400_000), { month: 'short', day: 'numeric', year: 'numeric' }),\n })\n : word(current);\n return (\n <DropMenu\n className=\"dash-window-menu\"\n triggerClassName=\"dash-window-button\"\n triggerLabel={sayCopy('pickWindow', { window: word(current) })}\n label={\n <>\n <Icon name=\"calendar-blank\" size={15} className=\"dash-window-icon\" />\n <span className=\"dash-window-range\">{shown}</span>\n <Icon name=\"caret-down\" size={12} className=\"dash-window-caret\" />\n </>\n }\n popupClassName=\"more-list dash-window-list\"\n align=\"end\"\n >\n {[null, ...windows].map((w) => (\n <DropItem key={w ?? ''} className=\"more-item\" onClick={() => onPick(w)}>\n <span className=\"more-tick\" aria-hidden=\"true\">\n {w === current ? '✓' : ''}\n </span>\n <span className=\"more-label\">{word(w)}</span>\n </DropItem>\n ))}\n </DropMenu>\n );\n }\n return (\n <div className=\"dash-windows\" role=\"group\" aria-label={sayCopy('timeWindow')}>\n {[null, ...windows].map((w) => (\n <button key={w ?? ''} type=\"button\" className=\"dash-window\" aria-pressed={w === current} onClick={() => onPick(w)}>\n {word(w)}\n </button>\n ))}\n </div>\n );\n}\n\n/**\n * The pick controls: one quiet dropdown per configured column. A\n * vocabulary column offers its own values; a whole single-column\n * reference offers the records it points at, said by name and filtered\n * by id — nobody picks an owner by remembering 7.\n */\nfunction Pick({\n dashboard,\n column,\n picks,\n onChange,\n}: {\n dashboard: DashboardDef;\n column: string;\n picks: Picks;\n onChange: (column: string, value: string) => void;\n}) {\n const home = [...dashboard.sections, ...(dashboard.aside ?? [])].find(\n (s) => s.table && (findTable(s.table) as TableMeta | undefined)?.columns.some((c) => c.name === column),\n );\n const table = home && (findTable(home.table) as TableMeta | undefined);\n const meta = table?.columns.find((c) => c.name === column) as (ColumnMeta & { allowed?: string[] }) | undefined;\n /* A reference: the values are the target's records. Fifty at most —\n a filter over more rows than a dropdown holds wants the list page's\n boxes, not this control. */\n const fk =\n table && !meta?.allowed?.length\n ? (refsFrom(table.id) as Array<{ from: { columns: string[] }; to: { table: string } }>).find(\n (f) => f.from.columns.length === 1 && f.from.columns[0] === column,\n )\n : undefined;\n const target = fk && (findTable(fk.to.table) as TableMeta | undefined);\n const naming = target ? labelColumn(target) : undefined;\n const pk = target ? primaryKey(target)[0] : undefined;\n const q = pickQuery(lookups, [...dashboard.sections, ...(dashboard.aside ?? [])], column);\n const records = useRows(q, 50);\n if (!meta || !table) return null;\n if (!meta.allowed?.length && !naming) return null;\n const label = (labelColumn(table) === column ? column : column.replace(/_id$/, '')).replace(/_/g, ' ');\n const items = meta.allowed?.length\n ? meta.allowed.map((v) => ({ value: v, label: groupLabel(columnDisplay(table!.id, column) as DisplayRule | null, v, meta.allowed) }))\n : (records.data?.rows ?? []).map((r) => ({ value: String(r[pk!]), label: String(r[naming!] ?? r[pk!]) }));\n return (\n <span className=\"dash-pick\">\n <Dropdown\n items={[{ value: '', label: sayCopy('any', { label }) }, ...items]}\n value={picks[column] ?? ''}\n ariaLabel={sayCopy('filter', { label })}\n onChange={(value) => onChange(column, value)}\n />\n </span>\n );\n}\n\n/* ---------- the screen ---------- */\n\nconst NO_PERIODS: Periods = {};\nconst NO_SECTIONS: ReadonlySet<number> = new Set();\n\n/* A section over the window the reader picked, where all time is the unpicked state: widening it is offered by whatever\n is empty inside it, so \"Nothing to count yet.\" after a 90-day pick does not read as an empty table. */\nconst AllTimeOffer = createContext<{ window: string; showAll: () => void } | null>(null);\n\n/** An empty section's words: the plain sentence, or under a window picked, that it is empty there and a way to see all time. */\nfunction useNothing(plain: string): { text: string; detail?: string; action?: ReactNode } {\n const offer = useContext(AllTimeOffer);\n if (!offer) return { text: plain };\n return {\n text: sayCopy('nothingInThisTimeWindow'),\n detail: offer.window.charAt(0).toUpperCase() + offer.window.slice(1),\n action: (\n <Button intent=\"quiet\" size=\"compact\" onClick={offer.showAll}>\n {sayCopy('showAllTime')}\n </Button>\n ),\n };\n}\n\n/** What a section says when it has nothing to draw. */\nfunction Nothing({ text }: { text: string }) {\n return <Empty {...useNothing(text)} />;\n}\n\nconst Sections = memo(function Sections({\n dashboard,\n sections,\n windowNow,\n picks,\n periods,\n onPeriod,\n onAllTime,\n served,\n aside = false,\n}: {\n dashboard: DashboardDef;\n sections: Section[];\n windowNow: string | null;\n picks: Picks;\n /** The periods picked on sections with windows of their own, and where a new pick goes. */\n periods: Periods;\n onPeriod: (key: string, phrase: string) => void;\n /** The window picker's unpicked state, which is all time where no section keeps a window of its own. */\n onAllTime: () => void;\n /** Each authored section's place among the dashboard's as served, which is how an activity names itself to the server. */\n served: ReadonlyMap<Section, number>;\n aside?: boolean;\n}) {\n /* Each tile is memoized and handed the section it draws, so that section\n is made once per window and pick, not on every paint: a dashboard redrew\n all its tiles each time any one of them answered, some 4,000 component\n renders to draw ten figures. */\n const resolved = useMemo(\n () =>\n sections.map((raw) => {\n /* A section with windows of its own is over the period picked in its\n heading, and its picker says which, so its title says nothing more. */\n if (raw.windows?.length) return picked(windowed(raw, sectionPeriod(raw, periods)), picks);\n /* The title says the window the figure is over (dashboardModel.ts,\n windowTitle): the reader's pick stands where the author's window was\n named, and a section the author windowed says nothing more until then. */\n const said = raw.kind === 'metric' ? metricWindow(raw.title ?? raw.table ?? '', raw, windowNow) : undefined;\n const scoped = said\n ? { ...raw, title: said.title, ...(said.note ? { windowNote: said.note } : {}) }\n : raw.over\n ? { ...raw, title: windowTitle(raw.title ?? raw.table ?? '', raw, windowNow) }\n : raw;\n return picked(windowed(scoped, windowNow), picks);\n }),\n [sections, windowNow, picks, periods],\n );\n /* Where the reader's window is what a section is over, and unpicking it is all time (the picker says \"Default\" over a\n section that keeps a window of its own), an empty section offers to widen it. */\n const widened = (section: Section) =>\n windowNow !== null && Boolean(section.over) && section.windowBase === undefined && !section.windows?.length\n ? { window: windowNow, showAll: onAllTime }\n : null;\n /* A layout places every section in an area of a grid (the aside is never beside one: the parser refuses both). */\n const layout = !aside && dashboard.areas?.length ? layoutGrid(dashboard.areas) : undefined;\n /* Sections flow into the page's rows, or into an area of the layout: the same walk over the sections of one flow. */\n const flow = (indices: number[], pairing: boolean, gate?: Gate): ReactNode[] => {\n /* Consecutive metrics coalesce into one KPI strip — the way every\n operations screen reads its top row — and everything else keeps the\n page grid's widths. */\n const out: ReactNode[] = [];\n let strip: ReactNode[] | null = null;\n const there = indices.map((i) => resolved[i]!);\n /* Charts and breakdowns the author gave no width stand two to a row where two come together: one chart a\n page wide under another a page wide made a dashboard a long scroll of short plots with white either side.\n A pair is a pair; a third alone keeps the page's width rather than standing half-empty beside nothing.\n Tables, heat maps, boards and notes keep theirs. Narrow, every half stacks (page.css). In an area nothing\n pairs: the author placed the sections, and the area is as wide as the author made it. */\n const paired = new Set<number>();\n for (let k = 0; pairing && k < there.length; k++) {\n const pairs = (section: Section | undefined) =>\n Boolean(section && (section.kind === 'chart' || section.kind === 'breakdown' || section.kind === 'funnel') && !section.width);\n if (pairs(there[k]) && pairs(there[k + 1])) {\n paired.add(indices[k]!).add(indices[k + 1]!);\n k++;\n }\n }\n /* The rows of metrics in which some card is over a time (see MetricProps.dated), by each card's index. */\n const dated = new Set<number>();\n for (let start = 0; start < there.length; start++) {\n if (there[start]!.kind !== 'metric') continue;\n let end = start;\n while (end < there.length && there[end]!.kind === 'metric') end++;\n if (there.slice(start, end).some((card) => card.windowNote)) for (let k = start; k < end; k++) dated.add(indices[k]!);\n start = end;\n }\n indices.forEach((i) => {\n const section = resolved[i]!;\n const current = sectionPeriod(section, periods);\n const period =\n current && section.windowKey ? (\n <SectionPeriod section={section} current={current} onPick={(phrase) => onPeriod(section.windowKey!, phrase)} />\n ) : undefined;\n if (section.kind === 'metric') {\n if (!strip) {\n strip = [];\n out.push(\n <section key={`strip-${i}`} className=\"page-section width-full dash-strip\">\n <div className=\"home-cards\">{strip}</div>\n </section>,\n );\n }\n /* A card that throws stands as its note in the strip; its neighbours stay. */\n strip.push(\n <ErrorBoundary key={i} fallback={(note) => <div className=\"home-card home-card-broken\">{note}</div>}>\n <Metric\n section={section}\n period={period}\n windowed={Boolean(dashboard.windows?.length) && windowNow !== null && !section.windows}\n dated={dated.has(i)}\n />\n </ErrorBoundary>,\n );\n return;\n }\n strip = null;\n const width = section.kind === 'board' ? 'full' : (section.width ?? (paired.has(i) ? 'half' : 'full'));\n let body: ReactNode;\n if (section.kind === 'note') {\n const image = section.image ? landingImage(section.image) : undefined;\n body = (\n <DashboardNote\n title={section.title}\n text={String(section.text ?? '')}\n icon={section.icon}\n action={section.action}\n variant={section.variant}\n eyebrow={section.eyebrow}\n image={image && section.image ? { src: image, alt: section.image.alt } : undefined}\n />\n );\n } else if (section.kind === 'breakdown' || section.kind === 'chart' || section.kind === 'matrix' || section.kind === 'funnel') {\n const heading = (\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title ?? `${section.table} by ${section.by}`}\n </h2>\n );\n body = (\n <>\n {period ? (\n <div className=\"dash-section-head\">\n {heading}\n {period}\n </div>\n ) : (\n heading\n )}\n {section.kind === 'chart' ? (\n <Chart section={section} />\n ) : section.kind === 'funnel' ? (\n <FunnelSection section={section} />\n ) : section.shape === 'steps' ? (\n <StepCards section={section} />\n ) : section.kind === 'matrix' ? (\n <Matrix section={section} />\n ) : (\n <BreakdownRows section={section} />\n )}\n </>\n );\n } else if (section.kind === 'board') {\n body = <Board section={section} />;\n } else if (section.kind === 'custom') {\n body = <CustomDashSection section={section} windowNow={windowNow} picks={picks} aside={aside} />;\n } else if (section.kind === 'activity') {\n body = (\n <>\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title ?? sayCopy('latestChanges')}\n </h2>\n <ActivityFeed section={section} dashboard={dashboard.id} at={served.get(sections[i]) ?? -1} />\n </>\n );\n } else if (section.kind === 'find') {\n body = (\n <>\n {section.title ? (\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title}\n </h2>\n ) : null}\n <FindSection section={section} />\n </>\n );\n } else if (section.kind === 'branding' || section.kind === 'integrations') {\n /* Alone on its page, the form is the page: the page's heading already names it, and \"Branding\" said twice\n read as two things. A title of its own that the page does not say is still drawn. */\n const alone = allSections(dashboard).length === 1 && (!section.title || section.title === dashboard.label);\n body = (\n <>\n {alone ? null : (\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title ?? (section.kind === 'branding' ? sayCopy('branding') : sayCopy('integrations'))}\n </h2>\n )}\n {section.kind === 'branding' ? <BrandingForm /> : <IntegrationsForm />}\n </>\n );\n } else {\n body = <List section={section} aside={aside} period={period} />;\n }\n const app = activeApp();\n const source = section.view && app ? viewRoom(app, section.view) : undefined;\n const cards = source && isListRoom(source) && source.presentation?.kind === 'cards';\n out.push(\n <SectionShell\n key={i}\n {...(gate ? { at: i, report: gate.report, hidden: gate.settled.has(i) } : {})}\n className={`page-section width-${width}${section.kind === 'note' ? ` dash-note${section.variant ? ` dash-${section.variant}` : ''}` : ''}${cards ? ' dash-cards-section' : ''}${section.kind === 'custom' ? ' dash-custom' : ''}`}\n >\n {/* A section that throws says so under its title; the rest of the dashboard stays. */}\n <ErrorBoundary\n fallback={(note) => (\n <>\n {section.title ? <h2 className=\"page-section-title\">{section.title}</h2> : null}\n {note}\n </>\n )}\n >\n <AllTimeOffer.Provider value={widened(section)}>{body}</AllTimeOffer.Provider>\n </ErrorBoundary>\n </SectionShell>,\n );\n });\n return out;\n };\n if (!layout)\n return (\n <>\n {flow(\n resolved.map((_, i) => i),\n true,\n )}\n </>\n );\n const inArea = new Map<string, number[]>();\n resolved.forEach((section, i) => {\n if (section.area) inArea.set(section.area, [...(inArea.get(section.area) ?? []), i]);\n });\n const epoch = `${windowNow}|${JSON.stringify(picks)}|${JSON.stringify(periods)}`;\n return <LaidOut layout={layout} inArea={inArea} epoch={epoch} flow={flow} />;\n});\n\n/** What the grid acts on when sections ask to be left out: who asks, and who has been settled as gone. */\ninterface Gate {\n report: (at: number, gone: boolean) => void;\n settled: ReadonlySet<number>;\n}\n\n/** A dashboard's layout drawn: one grid, an area for each name in the template, in reading order. */\nfunction LaidOut({\n layout,\n inArea,\n epoch,\n flow,\n}: {\n layout: LayoutGrid;\n inArea: ReadonlyMap<string, number[]>;\n /** What the reader has picked, as one word: the grid is re-shaped once for each. */\n epoch: string;\n flow: (indices: number[], pairing: boolean, gate: Gate) => ReactNode[];\n}) {\n /* Which sections ask to be left out is held here, and what the grid acts on is settled once per reader's pick. */\n const queries = useQueryClient();\n const asking = useIsFetching();\n const askedNow = useRef<ReadonlySet<number>>(NO_SECTIONS);\n const [asked, setAsked] = useState<ReadonlySet<number>>(NO_SECTIONS);\n const [settled, setSettled] = useState<ReadonlySet<number>>(NO_SECTIONS);\n const report = useCallback((at: number, gone: boolean) => {\n if (askedNow.current.has(at) === gone) return;\n const next = new Set(askedNow.current);\n if (gone) next.add(at);\n else next.delete(at);\n askedNow.current = next;\n setAsked(next);\n }, []);\n /* The areas are re-flowed once for each thing the reader picks, when every tile has its answer to it: until then the\n tiles keep their last answers (keepPreviousData) and the grid its last shape, so the change lands as one finished\n swap and not a move for every tile that answers. A live refresh is not a pick: a section that empties on one shows\n its empty line where it stands, and the grid is left alone until the reader's next pick. The timer lets the\n tiles' own effects, which start the questions and report the answers, run first. */\n const decided = useRef<string | null>(null);\n useEffect(() => {\n const timer = setTimeout(() => {\n if (queries.isFetching() > 0 || decided.current === epoch) return;\n decided.current = epoch;\n setSettled(askedNow.current);\n }, 0);\n return () => clearTimeout(timer);\n }, [queries, epoch, asking, asked]);\n /* In reading order, so the DOM is the order a reader and a keyboard go in whatever the template draws. */\n const areas = layoutAreas(layout);\n const away = new Set(areas.filter((area) => (inArea.get(area) ?? []).every((i) => settled.has(i))));\n const columns = layout[0]?.length ?? 1;\n const gate = { report, settled };\n return (\n <div\n className=\"dash-grid\"\n data-columns={columns}\n style={{ '--dash-columns': columns, '--dash-template': gridTemplateAreas(reflowLayout(layout, away)) } as CSSProperties}\n >\n {areas.map((area) => (\n <div key={area} className=\"dash-area\" style={{ '--area': area } as CSSProperties} hidden={away.has(area) || undefined}>\n {flow(inArea.get(area) ?? [], false, gate)}\n </div>\n ))}\n </div>\n );\n}\n\n/* A free-form page's block (sdk/blocks.tsx): one section, as a dashboard draws it, standing among the page's own. */\nconst BLOCK_DASHBOARD = { id: 'page-block', label: '', sections: [] } as unknown as DashboardDef;\nconst NO_PICKS: Picks = {};\nconst NO_SERVED: ReadonlyMap<Section, number> = new Map();\nconst noPeriod = () => {};\n\n/**\n * One section drawn where a page places it: its own `page-section`, with no dashboard around it, so a page's grid\n * lays it out with its neighbours. A metric is its card in a strip of its own width (a third, unless it says).\n */\nexport function DashboardBlock({ section }: { section: Section }) {\n const sections = useMemo(() => [section], [section]);\n return (\n <ProblemScopeProvider>\n {section.kind === 'metric' ? (\n <section className={`page-section width-${section.width ?? 'third'} dash-strip`}>\n <div className=\"home-cards\">\n <ErrorBoundary fallback={(note) => <div className=\"home-card home-card-broken\">{note}</div>}>\n <Metric section={section} />\n </ErrorBoundary>\n </div>\n </section>\n ) : (\n <Sections\n dashboard={BLOCK_DASHBOARD}\n sections={sections}\n windowNow={null}\n picks={NO_PICKS}\n periods={NO_PERIODS}\n onPeriod={noPeriod}\n onAllTime={noPeriod}\n served={NO_SERVED}\n />\n )}\n </ProblemScopeProvider>\n );\n}\n\n/**\n * The sections and the reader's controls over them. The window is the\n * query grammar's own phrase, landing on every section that declared\n * `over`; a metric's `compare` is the author's chosen window and stays\n * out of the reader's — two hands on one clock would tell no time. The\n * picks are column → chosen value, landing on every section whose table\n * has the column. Both arrive from a link and every change is reported\n * the same way, so a picked board is a place worth sending someone too.\n */\nexport function Dashboard({\n dashboard,\n window: fromLink = null,\n picks: pickedFromLink = {},\n periods: periodsFromLink = NO_PERIODS,\n onWindow,\n onPick,\n onPeriods,\n}: DashboardProps) {\n const [windowNow, setWindow] = useState<string | null>(fromLink);\n const [picks, setPicks] = useState<Picks>(pickedFromLink);\n const [periods, setPeriods] = useState<Periods>(periodsFromLink);\n /* Where each section stands among the dashboard's as it was served, before a first run is taken out below. */\n const served = useMemo(() => new Map(allSections(dashboard).map((section, at) => [section, at])), [dashboard]);\n const periodsNow = useRef(periods);\n const onPeriod = useMemo(\n () => (key: string, phrase: string) => {\n const next = { ...periodsNow.current, [key]: phrase };\n periodsNow.current = next;\n setPeriods(next);\n onPeriods?.(next);\n },\n [onPeriods],\n );\n /* A first run leads the dashboard until its steps are done; while none is,\n it is the dashboard — charts of empty tables say nothing but \"broken\". */\n const firstRun = dashboard.sections.find((section) => section.kind === 'firstRun');\n const run = useFirstRun(firstRun);\n if (firstRun && run.stage === 'unknown') return <div className=\"page-body dash-body\" aria-busy=\"true\" />;\n if (firstRun && run.stage === 'fresh') {\n return (\n <div className=\"page-body dash-body\">\n <FirstRun section={firstRun} done={run.done} fresh />\n </div>\n );\n }\n const lead = firstRun && run.stage === 'started' ? <FirstRun section={firstRun} done={run.done} fresh={false} /> : null;\n dashboard = firstRun ? { ...dashboard, sections: dashboard.sections.filter((section) => section !== firstRun) } : dashboard;\n const onAllTime = () => {\n setWindow(null);\n onWindow?.(null);\n };\n const controls = Boolean(dashboard.windows?.length) || Boolean(dashboard.filters?.length);\n return (\n <ProblemScopeProvider>\n <div>\n {lead && <div className=\"page-body dash-body\">{lead}</div>}\n {controls && (\n <div className=\"dash-controls\">\n {dashboard.windows?.length ? (\n <WindowRow\n windows={dashboard.windows}\n current={windowNow}\n onPick={(w) => {\n setWindow(w);\n onWindow?.(w);\n }}\n ownWindows={allSections(dashboard).some((section) => section.over && section.windowBase !== undefined)}\n control={dashboard.windowControl}\n />\n ) : null}\n {dashboard.filters?.length ? (\n <div className=\"dash-picks\">\n {dashboard.filters.map((column) => (\n <Pick\n key={column}\n dashboard={dashboard}\n column={column}\n picks={picks}\n onChange={(c, value) => {\n const next = { ...picks };\n if (value === '') delete next[c];\n else next[c] = value;\n setPicks(next);\n onPick?.(next);\n }}\n />\n ))}\n </div>\n ) : null}\n </div>\n )}\n {dashboard.aside?.length ? (\n <div className=\"dashboard-layout page-layout\">\n <div className=\"page-body page-main dash-body\">\n <Sections\n dashboard={dashboard}\n sections={dashboard.sections}\n windowNow={windowNow}\n picks={picks}\n periods={periods}\n onPeriod={onPeriod}\n onAllTime={onAllTime}\n served={served}\n />\n </div>\n <aside className=\"page-body page-aside dash-body\" aria-label={sayCopy('dashboardContext')}>\n <Sections\n dashboard={dashboard}\n sections={dashboard.aside}\n windowNow={windowNow}\n picks={picks}\n periods={periods}\n onPeriod={onPeriod}\n onAllTime={onAllTime}\n served={served}\n aside\n />\n </aside>\n </div>\n ) : (\n <div className={`page-body dash-body${dashboard.areas?.length ? ' dash-laid' : ''}`}>\n <Sections\n dashboard={dashboard}\n sections={dashboard.sections}\n windowNow={windowNow}\n picks={picks}\n periods={periods}\n onPeriod={onPeriod}\n onAllTime={onAllTime}\n served={served}\n />\n </div>\n )}\n </div>\n </ProblemScopeProvider>\n );\n}\n"],"ignoreList":[0],"mappings":"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"}
1
+ {"version":3,"file":"shared-DSUICuaJ.js","names":["React","say","say","_Fragment","say","say","kept","say","say","say","say","say","_Fragment","say","say","say","_Fragment","say","say","_Fragment","say","say","_Fragment","askedFor","say","sayCopy","say","say","say","sayCopy","say","_Fragment"],"sources":["../../../../node_modules/@tanstack/react-query/build/modern/useIsFetching.js","../../../kit/src/client/components/suggestPart.ts","../../../kit/src/client/copy/workbench/components/History.ts","../../../kit/src/client/components/History.tsx","../../../kit/src/client/copy/workbench/history.ts","../../../kit/src/client/history.js","../../../kit/src/client/connectionScope.ts","../../../kit/src/client/roleLabels.ts","../../../kit/src/client/copy/forms/components/NewRecordButton.ts","../../../kit/src/client/components/NewRecordButton.tsx","../../../kit/src/client/components/pageStep.ts","../../../kit/src/client/copy/workbench/components/Export.ts","../../../kit/src/client/components/ExportHold.tsx","../../../kit/src/client/copy/lists/components/useBulkSelection.ts","../../../kit/src/client/components/useBulkSelection.tsx","../../../kit/src/client/copy/lists/components/GridSelection.ts","../../../kit/src/client/components/GridSelection.tsx","../../../kit/src/client/copy/lists/components/TableView.ts","../../../kit/src/client/components/TableView.tsx","../../../kit/src/client/copy/lists/components/TableRoom.ts","../../../kit/src/client/components/TableRoom.tsx","../../src/client/copy/dashboards/components/Funnel.ts","../../src/client/components/Funnel.tsx","../../../engine/src/shared/dashLayout.ts","../../../engine/src/shared/autoBucket.ts","../../../engine/src/shared/dashboardTrend.ts","../../../engine/src/shared/weekStart.ts","../../../kit/src/client/components/autoChart.ts","../../src/client/copy/shell/components/FirstRun.ts","../../src/client/components/FirstRun.tsx","../../src/client/copy/public/components/LandingData.ts","../../src/client/components/LandingData.tsx","../../src/client/copy/dashboards/components/Dashboard.ts","../../src/client/components/Dashboard.tsx"],"sourcesContent":[null,"/* The suggesting search box, as a part loaded on demand: every box that offers it names this one loader, and the\n first paint of a list or a landing carries none of it (SuggestBox.tsx). */\nimport { onDemand } from './onDemand.js';\n\nexport const SuggestBox = onDemand(() => import('./SuggestBox.js'), 'SuggestBox', { quiet: true });\n","/** What History says, in the Workbench room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n justNow: 'just now',\n minutesAgo: '{minutes}m ago',\n hoursAgo: '{hours}h ago',\n daysAgo: '{days}d ago',\n nothingYetQueriesAppear: 'Nothing yet. Queries appear here once they run.',\n clearQueries: { one: 'Clear {count} query', other: 'Clear {count} queries' },\n});\n","/**\n * The query history panel: what ran, how long ago, and one button to\n * forget it all. The store, the ↑/↓ stepping and the panel's open state\n * stay in `history.js`, which draws this into the panel it owns.\n */\nimport { say } from '../copy/workbench/components/History.js';\n\ninterface HistoryEntry {\n q: string;\n at?: number;\n}\n\nfunction ago(at: number): string {\n const seconds = Math.max(0, Math.round((Date.now() - at) / 1000));\n if (seconds < 60) return say('justNow');\n if (seconds < 3600) return say('minutesAgo', { minutes: Math.round(seconds / 60) });\n if (seconds < 86400) return say('hoursAgo', { hours: Math.round(seconds / 3600) });\n return say('daysAgo', { days: Math.round(seconds / 86400) });\n}\n\nexport function HistoryPanel({ entries, onRun, onClear }: { entries: HistoryEntry[]; onRun: (q: string) => void; onClear: () => void }) {\n if (!entries.length) return <p className=\"history-empty\">{say('nothingYetQueriesAppear')}</p>;\n return (\n <>\n <ul className=\"history-list\">\n {entries.map((entry) => (\n <li key={entry.q}>\n <button type=\"button\" className=\"history-item\" onClick={() => onRun(entry.q)}>\n <span className=\"history-q\">{entry.q}</span>\n <span className=\"history-age\">{ago(entry.at ?? Date.now())}</span>\n </button>\n </li>\n ))}\n </ul>\n <button type=\"button\" className=\"history-clear\" onClick={onClear}>\n {say('clearQueries', { count: entries.length })}\n </button>\n </>\n );\n}\n","/** What history says, in the Workbench room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../messages.js';\n\nexport const say = defineMessages({\n queryHistoryCleared: 'Query history cleared.',\n});\n","/**\n * Query history: the last 50 queries that ran, per connection.\n *\n * Two things shape this file.\n *\n * The first is that history is a convenience, never a dependency. Every\n * `localStorage` call is wrapped, because the API throws rather than returning\n * null in three ordinary situations — Safari's private mode, a browser set to\n * block site data, and a full quota — and a database browser that fails to\n * paint because it could not remember what you typed is worse than one that\n * never offered to. When storage refuses, the list falls back to memory and\n * works until the tab is closed.\n *\n * The second is that history is per connection. The stored value is keyed by\n * `state.activeConnection`, so switching from staging to production does not\n * offer you queries against tables the new database may not even have.\n */\nimport { createElement } from 'react';\nimport { $, el, loadJson, saveJson, state, toast } from './core.js';\nimport { mount } from './components/mount.js';\nimport { HistoryPanel } from './components/History.js';\nimport { say } from './copy/workbench/history.js';\nimport { addHostListener } from './shellHost.js';\n\nconst KEY = 'mistri.history.v1';\n\n/* Enough to cover a session's worth of exploration, small enough that the\n whole record stays well inside a quota even with long queries. */\nconst MAX_ENTRIES = 50;\n\n/** The whole record: `{ [connectionId]: [{ q, at }] }`. Never throws. */\nfunction readAll() {\n const parsed = loadJson(KEY, {});\n // Anything could be under this key — an older shape, or another tool's.\n // Refusing to trust it is cheaper than defending every read site.\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};\n}\n\n/* The in-memory mirror, and the reason a failed write is not a failed feature:\n the dropdown reads from here, so history keeps working for the session even\n when nothing can be persisted. */\nconst cache = new Map();\n\nconst scope = () => state.activeConnection ?? 'default';\n\n/** The history for the connection in use, newest first. */\nexport function historyFor(connection = scope()) {\n if (!cache.has(connection)) {\n const stored = readAll()[connection];\n cache.set(connection, Array.isArray(stored) ? stored.filter((e) => e && typeof e.q === 'string') : []);\n }\n return cache.get(connection);\n}\n\n/**\n * Remember a query that ran.\n *\n * Re-running something moves it to the top instead of adding a second copy:\n * the list is meant to answer \"what have I been looking at\", and twelve\n * identical rows of `customer` push the query you actually want off the end.\n */\nexport function recordQuery(text) {\n const q = String(text ?? '').trim();\n if (!q) return;\n const connection = scope();\n const kept = historyFor(connection).filter((entry) => entry.q !== q);\n kept.unshift({ q, at: Date.now() });\n kept.length = Math.min(kept.length, MAX_ENTRIES);\n cache.set(connection, kept);\n\n const all = readAll();\n all[connection] = kept;\n // Best effort: saveJson swallows a full or unavailable localStorage, and\n // the in-memory copy above keeps the list working for the session either way.\n saveJson(KEY, all);\n cursor = -1;\n draft = null;\n if (panel && !panel.hidden) fillPanel();\n}\n\nfunction clearHistory() {\n const connection = scope();\n cache.set(connection, []);\n const all = readAll();\n delete all[connection];\n saveJson(KEY, all);\n fillPanel();\n toast(say('queryHistoryCleared'));\n}\n\n/* ---------- the control ---------- */\n\nlet panel = null;\nlet toggle = null;\nlet installed = false;\n\n/* Where in the list the ↑/↓ walk currently is: -1 means \"on what you typed\",\n and `draft` holds that text so walking back down returns it rather than\n leaving the last history entry in the box. */\nlet cursor = -1;\nlet draft = null;\n\nfunction fillPanel() {\n mount(panel, createElement(HistoryPanel, { entries: historyFor(), onRun: runEntry, onClear: clearHistory }));\n}\n\nfunction runEntry(q) {\n const input = $('query');\n input.value = q;\n setOpen(false);\n cursor = -1;\n draft = null;\n /* `requestSubmit` rather than `submit`: it fires the form's submit event, so\n the one handler in app.js decides what a query means. `submit()` would\n skip it and reload the page. */\n $('querybar').requestSubmit();\n}\n\nfunction setOpen(open) {\n panel.hidden = !open;\n toggle.setAttribute('aria-expanded', String(open));\n if (open) fillPanel();\n}\n\n/** Step through the list in the input itself, without opening the panel. */\nfunction step(direction) {\n const entries = historyFor();\n if (!entries.length) return;\n const input = $('query');\n if (cursor === -1) draft = input.value;\n const next = Math.min(Math.max(cursor + direction, -1), entries.length - 1);\n cursor = next;\n input.value = next === -1 ? (draft ?? '') : entries[next].q;\n // Caret to the end, or the browser leaves it where it was and the next\n // keystroke lands in the middle of the recalled query.\n input.setSelectionRange(input.value.length, input.value.length);\n}\n\n/**\n * Attached on import rather than from a boot function.\n *\n * app.js wires the chrome, and this feature deliberately adds no line to it:\n * importing the module is enough to get the control, which keeps the query bar\n * working the same whether or not history is compiled in.\n */\nfunction initHistory() {\n if (installed) return;\n const bar = $('querybar');\n const input = $('query');\n if (!bar || !input) return;\n installed = true;\n\n /* No button in the header any more.\n\n Recent queries are reached two better ways: Ctrl/Cmd+↑ in the query bar,\n which is where your hands already are, and ⌘K, which searches them\n alongside everything else. A permanent button for a list you open once a\n session was the most expensive way to offer it. */\n toggle = el('button', { type: 'button', class: 'ghost history-toggle', hidden: true });\n panel = el('div', { class: 'history-panel', hidden: true });\n bar.append(panel);\n\n input.addEventListener('keydown', (e) => {\n // Ctrl/Cmd rather than a bare arrow: the query bar is a text field, and\n // stealing plain ↑/↓ would break moving the caret in a long query.\n if ((e.metaKey || e.ctrlKey) && (e.key === 'ArrowUp' || e.key === 'ArrowDown')) {\n e.preventDefault();\n step(e.key === 'ArrowUp' ? 1 : -1);\n return;\n }\n if (e.key === 'Escape' && !panel.hidden) {\n e.stopPropagation();\n setOpen(false);\n }\n });\n\n // Typing means you have left the recalled entry and are writing your own.\n input.addEventListener('input', () => {\n cursor = -1;\n draft = null;\n });\n\n /* Closed by a click anywhere else, which is what a menu is expected to do —\n on pointerdown so it happens before the click lands on whatever is behind. */\n addHostListener(document, 'pointerdown', (e) => {\n if (!panel.hidden && !panel.contains(e.target) && e.target !== toggle) setOpen(false);\n });\n}\n\nif (document.readyState === 'loading') {\n addHostListener(document, 'DOMContentLoaded', initHistory, { once: true });\n} else {\n initHistory();\n}\n","import { pageBridge } from './uiBridge.js';\nimport { appRequestScope, setAppRequestScope } from './requestIdentity.js';\n\n/** Listener metadata remains available before a failed app database can open. */\nexport function setAppConfigured(configured: boolean | null): void {\n setAppRequestScope(configured);\n}\n\n/** UI scope only. This does not replace server authorization. */\nexport function canManageConnections(): boolean {\n return appRequestScope() === false && !pageBridge.activeApp();\n}\n\n/** App Workbench uses the same listener boundary as the app itself. */\nexport function canUseDatabaseTools(): boolean {\n return appRequestScope() === false && !pageBridge.activeApp();\n}\n","/**\n * What this App calls its roles (`auth.roles.<id>.label`), as the sign-in\n * answer said them. Words for a person only: every choice and request still\n * names the id, so a missing or odd label never changes what is granted.\n */\nconst labels = new Map<string, string>();\n\nconst isLabel = (value: unknown): value is string =>\n typeof value === 'string' && value.length > 0 && value.length <= 60 && value.trim() === value && !/\\p{Cc}/u.test(value);\n\n/** The labels from `/api/whoami`'s `roleLabels`; anything else there is ignored, and the previous App's go. */\nexport function setRoleLabels(value: unknown): void {\n labels.clear();\n if (!value || typeof value !== 'object' || Array.isArray(value)) return;\n for (const [role, label] of Object.entries(value)) if (isLabel(label)) labels.set(role, label);\n}\n\nlet kept = false;\n/** From `/api/whoami`'s `hasRoles`: whether the App names roles at all. */\nexport function setAppKeepsRoles(value: unknown): void {\n kept = value === true;\n}\nexport const appKeepsRoles = (): boolean => kept;\n\n/** The App's own name for a role, where it gave one. */\nexport const roleLabel = (role: string): string | undefined => labels.get(role);\n","/** What NewRecordButton says, in the forms room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n addARow: 'Add a {name} row',\n newRow: '+ New row',\n create: 'Create a {label}',\n plusNew: '+ New',\n});\n","/**\n * The two New buttons.\n *\n * The workbench's \"+ New row\" behind the same gate every write affordance\n * uses: writable, write mode on, a table. The app list's \"New\": offered\n * whenever the connection accepts writes, whether or not editing is on — an\n * app's reader does not know the padlock exists, and a primary action that\n * only appears after finding it is not a primary action. Creating a record\n * does not change the editing mode for existing records. Absent on a read-only connection, where the server would\n * refuse the row anyway.\n */\nimport { canInsert, openInsert, openNewRecord } from '../insert.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { say } from '../copy/forms/components/NewRecordButton.js';\n\nexport interface FormSpec {\n show?: string[];\n defaults?: Record<string, unknown>;\n}\n\nexport function NewRowButton({ table }: { table: TableMeta }) {\n if (!canInsert(table)) return null;\n return (\n <button type=\"button\" className=\"ghost table-new-row\" title={say('addARow', { name: table.name })} onClick={() => openInsert(table)}>\n {say('newRow')}\n </button>\n );\n}\n\nexport function NewRecordButton({ table, label, form }: { table: TableMeta | undefined; label?: string; form?: FormSpec }) {\n /* The one rule every New entry point follows (insert.js): a table the reader's `create` grant leaves out is\n `insertable: false` in their catalog, and offering its form only to have the server refuse is a dead end. */\n if (!table || !canInsert(table, true)) return null;\n return (\n <button\n type=\"button\"\n className=\"ghost table-new-row applist-new\"\n title={say('create', { label: label ?? table.name })}\n onClick={() => {\n openNewRecord(table, form);\n }}\n >\n {/* The noun is its own span so a phone's crumb bar can say \"+ New\"\n beside a long title (structure.css); the name keeps the noun. */}\n {say('plusNew')} <span className=\"applist-new-noun\">{label ?? table.name}</span>\n </button>\n );\n}\n","/**\n * How the pager reached the page on screen, so the next read of it is by key\n * (shared/keysetPage.ts): Next is the rows after the last row shown,\n * Previous the rows before the first, Last the list's final rows read from\n * its end. A page reached by number — the page box, an address, First —\n * carries no step and is read by offset, which is cheap near the top and\n * refused past 10,000 rows.\n *\n * One step is kept, for one list and one page: it names the list by its\n * question and page size, so a step taken on another list, or before the\n * size changed, is never read as this one's. The page number stays what the\n * pager and the range say; the step only decides how it is read.\n */\nimport type { Boundary } from '@mistriwork/engine/shared/keysetPage.js';\n\ntype PageStepBody = { after: Boundary } | { before: Boundary } | { end: true };\ninterface Kept {\n list: string;\n page: number;\n body: PageStepBody;\n limit?: number;\n}\n\nlet kept: Kept | undefined;\n\n/** The list a step belongs to: its connection, table, question and page size. */\nexport function stepList(source: unknown, table: string, query: string, size: number): string {\n return JSON.stringify([source ?? null, table, query, size]);\n}\n\n/** Remember how `page` of `list` is reached; nothing, for a page reached by number. */\nexport function takePageStep(list: string, page: number, body?: PageStepBody, limit?: number): void {\n kept = body ? { list, page, body, ...(limit === undefined ? {} : { limit }) } : undefined;\n}\n\n/** How `page` of `list` is read, when the pager stepped to it: the request's step, and a limit of its own for the end. */\nexport function pageStepFor(list: string, page: number): { body: PageStepBody; limit?: number } | undefined {\n return kept && kept.list === list && kept.page === page\n ? { body: kept.body, ...(kept.limit === undefined ? {} : { limit: kept.limit }) }\n : undefined;\n}\n","/** What Export says, in the Workbench room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n none: 'None',\n thatQueryNoLonger: 'That query no longer returns rows.',\n thisPageRows: { one: 'this page ({count} row)', other: 'this page ({count} rows)' },\n allMatchingRows: 'all matching rows ({capped})',\n downloadThisResult: 'Download this result',\n export: 'Export',\n chooseColumns: 'Choose columns…',\n fetching: 'Fetching…',\n agent: 'Agent',\n theQueryTheShape: 'The query, the shape and how to run it over MCP — not the rows',\n copyThisPosition: 'Copy this position',\n cappedAtRowsTheSame: 'Capped at {max} rows — the same ceiling every read in this tool has. Narrow the query to export the rest.',\n pickAtLeastOne: 'Pick at least one column to export.',\n columnsToExport: 'Columns to export',\n tickedColumnsAreWritten:\n 'Ticked columns are written in the order the table declares them. Choosing a column that is not on screen re-runs the query to fetch it.',\n asDisplayed: 'As displayed',\n ofSelected: '{filterCount} of {columnsCount} selected',\n notShown: 'not shown',\n rememberedForThisTable: 'Remembered for this table on this connection.',\n useTheseColumns: 'Use these columns',\n selectedOfDeclared: '{selected} of {declared}',\n});\n","/**\n * Export's trigger, held: the control itself (Export.tsx), with its chooser,\n * serialisers and the agent hand-off, is a part that loads on demand, and\n * this is what stands in its place until it has — the same trigger, laid out\n * and unseen. The crumb bar is right-aligned, so a trigger arriving late\n * beside New would push New a button's width to the left. The part is asked\n * for as soon as a list is on its way, so it is usually here before the rows.\n */\nimport { useEffect, type ComponentProps } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useCrumbSlots, verbsAt } from './crumbSlot.js';\nimport { onDemand, useArrived } from './onDemand.js';\nimport { say } from '../copy/workbench/components/Export.js';\n\nconst ExportPart = onDemand(() => import('./Export.js'), 'ExportControl', { quiet: true });\n\nfunction HeldTrigger() {\n return (\n <div className=\"export\" aria-hidden=\"true\" inert style={{ visibility: 'hidden' }}>\n <button type=\"button\" className=\"export-summary\" tabIndex={-1}>\n <span className=\"export-word\">{say('export')}</span>\n <span className=\"export-more\">⋯</span>\n </button>\n </div>\n );\n}\n\n/** Export's place at the end of the crumb bar, or of the list's heading row, while the rows are on their way. */\nexport function ExportHold() {\n const tools = verbsAt(useCrumbSlots());\n useEffect(() => void ExportPart.ready(), []);\n if (!tools) return null;\n return createPortal(<HeldTrigger />, tools);\n}\n\n/** The Export control, or its held trigger until the part has arrived. */\nexport function ExportControl(props: ComponentProps<typeof ExportPart>) {\n return useArrived(ExportPart) ? <ExportPart {...props} /> : <HeldTrigger />;\n}\n","/** What useBulkSelection says, in the lists and grid room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n setColumn: 'Set {column}',\n doesNotMatchNow: 'Does not match \"{when}\" now.',\n selectedRecords: 'Selected records',\n selected: '{selectionCount} selected',\n setField: 'Set field…',\n oneRequestForTheWhole: 'One request for the whole selection: every record or none.',\n clearSelection: 'Clear selection',\n applying: 'Applying {done} of {total}…',\n selectionIsLimitedToRecords: 'Selection is limited to {max} records.',\n applyToSelectedRecords: { one: 'Apply to {count} selected record', other: 'Apply to {count} selected records' },\n willBeSkipped: '; {skipped} will be skipped',\n countSelectedRecords: { one: '{count} selected record', other: '{count} selected records' },\n});\n","/**\n * A selection of loaded records and the bulk actions offered for exactly\n * those keys — shared by the queue (a listbox) and the grid (a checkbox in\n * each row's host), so the two are one contract: the exact keys of loaded\n * records, never \"everything matching\"; a fixed update written per record\n * through `applyBulk`, each answered on its own; a bulk command sent once\n * for the group through its form.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport { useQueryClient } from '@tanstack/react-query';\nimport { expectedValues, type TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport type { AppAction, AppCommandAction, AppUpdateAction } from '@mistriwork/engine/schema/model.js';\nimport { commandFieldsDeep, commandKeyText } from '@mistriwork/engine/shared/commandWire.js';\nimport { columnLabel, findTable, state, writeAllowed } from '../core.js';\nimport { humanName } from '@mistriwork/engine/shared/model.js';\nimport { onDemand, useArrived } from './onDemand.js';\nimport type { CountedMessage } from './CountedLabel.js';\nimport { messageLanguage, servedLanguage } from '../messages.js';\nimport { grantedActionIds } from '../actionGrants.js';\nimport {\n applyBulk,\n bulkCommandSummary,\n bulkKey,\n bulkSummary,\n countedLabel,\n matchingKeys,\n BULK_LIMIT,\n type BulkRecordOutcome,\n type BulkResult,\n type BulkTarget,\n} from '../bulkActions.js';\nimport { sessionIdentity, subscribeSessionIdentity } from '../sessionIdentity.js';\nimport { updateAttempts } from '../updateAttempts.js';\nimport { shell, type BulkCommandOperation, type BulkCommandOwner } from '../shellMode.js';\nimport { Modal } from '@mistriwork/ui/Modal.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { formatLocale, formatNumber } from '../locale.js';\nimport { resourceOf } from './appRooms.js';\nimport { pluralOf, recordNoun } from '@mistriwork/engine/shared/appNoun.js';\nimport { say } from '../copy/lists/components/useBulkSelection.js';\n\n/* A selection's App commands are the shell's (shellMode.ts `bulkCommands`): where it has none, a list offers none, and\n these stand in so the hooks below are asked the same way in either shell. */\nconst NO_RUNS = { subscribe: () => () => {}, version: () => 0, unresolvedGroups: (): BulkCommandOperation[] => [] };\nconst NO_ANSWERS: boolean[] = [];\nconst noAvailability = () => NO_ANSWERS;\n\n/* \"Set field…\" draws its own dialog, fetched the first time it is chosen. */\nconst SetFieldDialog = onDemand(() => import('./SetFieldDialog.js'), 'SetFieldDialog', { quiet: true });\nconst Counted = onDemand(() => import('./CountedLabel.js'), 'CountedLabel', { quiet: true });\n\n/**\n * An action's label for the selection. One whose App message counts (server\n * appMessages.ts countedLabels) is said by the formatter, loaded the first\n * time a selection of several needs it, the words for one record standing in\n * meanwhile; any other is counted as English counts it (countedLabel), or not\n * at all.\n */\nfunction ActionLabel({ action, count, noun }: { action: AppAction; count: number; noun?: { one: string; many: string } }) {\n const message = (action as { counted?: CountedMessage }).counted;\n const wanted = Boolean(message) && count > 1;\n const here = useArrived(Counted, wanted);\n if (message && wanted && here)\n return <Counted message={message} count={count} locale={servedLanguage() ?? formatLocale() ?? messageLanguage()} />;\n return <>{!message && noun ? countedLabel(action.label, count, noun) : action.label}</>;\n}\n\n/** A record the selection can name: its bulk key, its key, what it is called, its row. */\nexport interface BulkRecord extends BulkTarget {\n id: string;\n row: Record<string, unknown>;\n}\ninterface Run {\n label: string;\n done: number;\n total: number;\n}\ninterface Asking {\n action: AppUpdateAction;\n count: number;\n skipped: number;\n answer: (yes: boolean) => void;\n}\n/** `summary` replaces the per-record sentence for a group's single outcome. */\ninterface Reported {\n label: string;\n result: BulkResult;\n summary?: string;\n}\n/** A bulk command's form: the records it names, in list order. */\ninterface CommandRun {\n action: AppCommandAction;\n targets: BulkTarget[];\n epoch: number;\n}\n\nconst said = (v: unknown) => (v === null ? 'null' : String(v));\n/* What the resource's records are called: its noun, else its table's name\n as a person says it, made plural by rule unless it already reads so. */\nfunction nounOf(table: TableMeta): { one: string; many: string } {\n const app = shell().app();\n const authored = app?.resources ? resourceOf(app, table.id)?.noun : undefined;\n if (authored) return authored;\n const one = recordNoun(undefined, table.name);\n return { one, many: /[^s]s$/i.test(one) ? one : pluralOf(one) };\n}\nconst setSummary = (action: AppUpdateAction) =>\n Object.entries(action.set)\n .map(([c, v]) => `${c} → ${said(v)}`)\n .join(', ');\nconst isUpdate = (action: AppAction): action is AppUpdateAction => action.command === undefined;\nconst isCommand = (action: AppAction): action is AppCommandAction => action.command !== undefined;\nconst tally = (outcomes: BulkRecordOutcome[], stopped = false): BulkResult => {\n const counts: BulkResult['counts'] = { applied: 0, rejected: 0, uncertain: 0, blocked: 0, skipped: 0 };\n for (const outcome of outcomes) counts[outcome.kind]++;\n return { outcomes, counts, stopped };\n};\n\n/** The bulk updates and commands this reader may run over the resource now. */\nexport function offeredBulk(\n table: TableMeta,\n actions: AppAction[],\n interactive: boolean,\n identity = sessionIdentity(),\n connection: string | null = state.activeConnection ?? null,\n editable: readonly string[] = [],\n) {\n const writable = () => {\n const current = findTable(table.id) as TableMeta | undefined;\n return (\n interactive &&\n writeAllowed(table.id) &&\n Boolean(current) &&\n !current!.isView &&\n !table.isView &&\n Boolean(state.connections?.some((c) => c.id === connection && c.writable))\n );\n };\n const columnWritable = (action: AppUpdateAction) => {\n const current = findTable(table.id) as TableMeta | undefined;\n return Object.keys(action.set).every((name) => {\n const column = current?.columns.find((c) => c.name === name);\n return column && !column.primaryKey && column.writable !== false;\n });\n };\n /* Or a fixed action a role of this reader runs without write: the server\n admits it per record as that action and nothing else. */\n const granted = (action: AppUpdateAction) =>\n interactive &&\n grantedActionIds(shell().app(), table.id).includes(action.id) &&\n !table.isView &&\n Boolean(findTable(table.id)) &&\n Boolean(state.connections?.some((c) => c.id === connection && c.writable));\n const bulk = actions\n .filter(isUpdate)\n .filter((action) => action.bulk === true && ((writable() && columnWritable(action)) || granted(action)));\n /* A command needs its own grant, not generic write: the manager who may\n assign cannot edit the application, and that is the point. */\n const grantedCommands = shell().app()?.grantedCommands ?? [];\n const commandAllowed = (action: AppCommandAction) =>\n interactive &&\n action.bulk === true &&\n action.command.targets === 'many' &&\n identity.mode === 'authenticated' &&\n identity.appId === connection &&\n grantedCommands.includes(action.command.id) &&\n action.command.target === table.id &&\n Boolean(findTable(table.id)) &&\n // Every type the form draws; a reference, at any depth, only over a resource this person reads.\n [...commandFieldsDeep(action.command.input)].every(({ field }) => field.type !== 'reference' || Boolean(findTable(field.from)));\n const commands = shell().slots.bulkCommands ? actions.filter(isCommand).filter(commandAllowed) : [];\n /* \"Set field…\" writes one of the list's editable columns, under the same\n gate as a fixed update: each still a writable column of this reader's. */\n const fields = writable() ? editable.filter((name) => columnWritable({ id: `set:${name}`, label: name, set: { [name]: null } })) : [];\n return { bulk, commands, fields };\n}\n\nexport function useBulkSelection({\n table,\n keyed,\n actions = [],\n interactive = true,\n editable = [],\n}: {\n table: TableMeta;\n keyed: BulkRecord[];\n actions?: AppAction[];\n interactive?: boolean;\n /** The list's editable columns, offered to the selection as \"Set field…\". */\n editable?: readonly string[];\n}) {\n const client = useQueryClient();\n const commanding = shell().slots.bulkCommands;\n const commandOperations = commanding?.operations ?? NO_RUNS;\n const useCommandAvailability = commanding?.useAvailability ?? noAvailability;\n const CommandForm = commanding?.Form;\n useSyncExternalStore(updateAttempts.subscribe, updateAttempts.version, updateAttempts.version);\n useSyncExternalStore(commandOperations.subscribe, commandOperations.version, commandOperations.version);\n const identity = useSyncExternalStore(subscribeSessionIdentity, sessionIdentity, sessionIdentity);\n const [selected, setSelected] = useState<string[]>([]);\n const [capped, setCapped] = useState(false);\n const [running, setRunning] = useState<Run | null>(null);\n const [asking, setAsking] = useState<Asking | null>(null);\n const [reported, setReported] = useState<Reported | null>(null);\n const [commandRun, setCommandRun] = useState<CommandRun | null>(null);\n const resultRef = useRef<HTMLDivElement>(null);\n /* Where a closing command form sends focus. The dialog resolves it while it\n unmounts, before anything mounted in the same commit has a ref, so the\n report region is always in the tree (hidden until it has a report) and\n this points at it only when the close produces one; a Cancel with nothing\n sent leaves it empty, and focus goes back to the toolbar button. */\n const returnFocus = useRef<HTMLElement | null>(null);\n const alive = useRef(true);\n useEffect(() => {\n alive.current = true;\n return () => {\n alive.current = false;\n };\n }, []);\n\n const connection = state.activeConnection ?? null;\n const byId = new Map(keyed.map((record) => [record.id, record]));\n // A record that left the list leaves the selection; one that returns is not re-selected.\n const present = keyed.map((record) => record.id).join('\\n');\n useEffect(() => {\n const ids = new Set(present.split('\\n'));\n setSelected((current) => (current.every((id) => ids.has(id)) ? current : current.filter((id) => ids.has(id))));\n }, [present]);\n const selection = useMemo(() => selected.filter((id) => byId.has(id)), [selected, present]);\n\n const { bulk, commands, fields } = offeredBulk(table, actions, interactive, identity, connection, editable);\n const [setting, setSetting] = useState(false);\n const selectedRecords = keyed.filter((record) => selection.includes(record.id));\n const availability = useCommandAvailability(\n commands.flatMap((action) =>\n selectedRecords.map((record) => ({\n command: action.command.id,\n commandVersion: action.command.version,\n key: record.key,\n })),\n ),\n interactive,\n );\n const availableCommands = commands.filter(\n (_action, index) =>\n selectedRecords.length > 0 &&\n selectedRecords.every((_record, offset) => availability[index * selectedRecords.length + offset] === true),\n );\n\n // Navigation can unmount the queue; coming back resumes an unconfirmed group.\n const resumed = commandRun\n ? undefined\n : commandOperations\n .unresolvedGroups(connection ?? '', table.id)\n .find((operation) => operation.identity === identity && operation.action && operation.owner.keys);\n const commandForm: CommandRun | null =\n commandRun && commandRun.epoch === identity.epoch\n ? commandRun\n : resumed\n ? {\n action: resumed.action!,\n epoch: identity.epoch,\n targets: resumed.owner.keys!.map((key, index) => ({ key, label: resumed.owner.labels?.[index] ?? commandKeyText(key) })),\n }\n : null;\n const groupOwner = (run: CommandRun): BulkCommandOwner => ({\n connection: connection ?? '',\n target: run.action.command.target,\n command: run.action.command.id,\n commandVersion: run.action.command.version,\n key: {},\n keys: run.targets.map((target) => ({ ...target.key })),\n labels: run.targets.map((target) => target.label),\n });\n const formEpoch = commandForm?.epoch;\n const formCurrent = useCallback(\n () => alive.current && sessionIdentity().epoch === formEpoch && (state.activeConnection ?? null) === connection,\n [formEpoch, connection],\n );\n\n const change = (keys: string[]) => {\n const over = keys.length > BULK_LIMIT;\n setCapped(over);\n setSelected(over ? keys.slice(0, BULK_LIMIT) : keys);\n };\n const clear = () => {\n setSelected([]);\n setCapped(false);\n setReported(null);\n };\n\n const run = (action: AppUpdateAction) => (bulk.includes(action) ? write(action) : Promise.resolve());\n /* \"Set field…\": one value for one column, written per record exactly as a\n fixed update is — the dialog that chose it was the confirmation. */\n const setField = (column: string, value: string | null) => {\n setSetting(false);\n if (!fields.includes(column)) return Promise.resolve();\n return write({\n id: `set:${column}`,\n label: say('setColumn', { column: columnLabel(table.id, column) ?? humanName(column) }),\n set: { [column]: value },\n });\n };\n const write = async (action: AppUpdateAction) => {\n if (running || commandForm) return;\n const targets = keyed.filter((record) => selection.includes(record.id));\n if (!targets.length) return;\n const epoch = sessionIdentity().epoch;\n const current = () => alive.current && sessionIdentity().epoch === epoch && (state.activeConnection ?? null) === connection;\n setReported(null);\n setRunning({ label: action.label, done: 0, total: targets.length });\n const matching = await matchingKeys(\n table,\n targets.map((record) => record.key),\n action.when,\n connection,\n );\n if (!current()) {\n if (alive.current) setRunning(null);\n return;\n }\n const applicable = targets.filter((record) => matching.has(record.id));\n const skipped = new Map(\n targets\n .filter((record) => !matching.has(record.id))\n .map((record): [string, BulkRecordOutcome] => [\n record.id,\n { key: record.key, label: record.label, kind: 'skipped', message: say('doesNotMatchNow', { when: action.when ?? '' }) },\n ]),\n );\n // Nothing to write needs no permission; the report says why.\n if (action.confirm && applicable.length) {\n const yes = await new Promise<boolean>((answer) => setAsking({ action, count: applicable.length, skipped: skipped.size, answer }));\n if (alive.current) setAsking(null);\n if (!yes || !current()) {\n if (alive.current) setRunning(null);\n return;\n }\n }\n const applied = await applyBulk(\n { connection, table: table.id },\n action.set,\n applicable.map(({ key, label, row }) => {\n const expected = expectedValues(table, action.set, row);\n return { key, label, ...(expected ? { expected } : {}) };\n }),\n current,\n (done, total) => {\n if (alive.current) setRunning({ label: action.label, done, total });\n },\n );\n if (!alive.current) return;\n setRunning(null);\n const written = new Map(applied.outcomes.map((outcome) => [bulkKey(table, outcome.key), outcome]));\n const result = tally(\n targets.map((record) => written.get(record.id) ?? skipped.get(record.id)!),\n applied.stopped,\n );\n setReported({ label: action.label, result });\n if (result.counts.applied && current()) {\n void shell().undo.refresh();\n void client.invalidateQueries({ queryKey: ['run', connection] });\n void client.invalidateQueries({ queryKey: ['count', connection] });\n void client.invalidateQueries({ queryKey: ['when', table.id] });\n }\n };\n\n /* A bulk command prepares, asks and sends inside the command form. Its\n records are the selection at the press, in list order; the form may\n only narrow them (Deselect ineligible), never widen them. */\n const openCommand = (action: AppCommandAction) => {\n if (running || commandForm || !availableCommands.includes(action)) return;\n const targets = keyed.filter((record) => selection.includes(record.id)).map(({ key, label }) => ({ key, label }));\n if (!targets.length) return;\n setReported(null);\n setCommandRun({ action, targets, epoch: identity.epoch });\n };\n const deselect = (keys: Array<Record<string, unknown>>) => {\n const drop = new Set(keys.map(commandKeyText));\n setSelected((current) =>\n current.filter((id) => {\n const record = byId.get(id);\n return !record || !drop.has(commandKeyText(record.key));\n }),\n );\n setCommandRun((current) => {\n if (!current) return current;\n const targets = current.targets.filter((target) => !drop.has(commandKeyText(target.key)));\n return targets.length ? { ...current, targets } : null;\n });\n };\n // One outcome for the group; an unconfirmed one keeps the form open instead.\n const closeCommand = (settled?: BulkCommandOperation) => {\n const finished = commandForm;\n setCommandRun(null);\n returnFocus.current = null;\n if (!finished || !settled || !alive.current) return;\n if (settled.phase === 'success' || settled.phase === 'error') returnFocus.current = resultRef.current;\n const count = settled.owner.keys?.length ?? finished.targets.length;\n if (settled.phase === 'success') {\n setReported({\n label: finished.action.label,\n summary: bulkCommandSummary(finished.action.label, count, 'applied'),\n result: tally(finished.targets.map((target) => ({ ...target, kind: 'applied', message: '' }))),\n });\n } else if (settled.phase === 'error') {\n const named =\n settled.refusedKey && finished.targets.find((target) => commandKeyText(target.key) === commandKeyText(settled.refusedKey));\n const message = `${settled.message}${named ? ` (${named.label})` : ''}`;\n setReported({\n label: finished.action.label,\n summary: bulkCommandSummary(finished.action.label, count, 'rejected', message),\n result: tally(finished.targets.map((target) => ({ ...target, kind: 'rejected', message }))),\n });\n }\n };\n // The report is the answer to the press; a reader hears it where they are.\n // After a command form the dialog hands focus here itself (`returnFocus`),\n // once the page behind it is no longer inert.\n useEffect(() => {\n if (reported) resultRef.current?.focus();\n }, [reported]);\n\n const failed = reported && (reported.result.counts.rejected > 0 || reported.result.counts.uncertain > 0);\n const busy = Boolean(running) || Boolean(commandForm);\n const bar = (\n <>\n {/* Nothing until something is chosen: a row of disabled verbs and \"0\n selected\" above every list was a bar of things that could not be done. */}\n {(bulk.length > 0 || commands.length > 0 || fields.length > 0) && (selection.length > 0 || running) && (\n <div role=\"toolbar\" aria-label={say('selectedRecords')} className=\"queue-bulk\" aria-busy={Boolean(running)}>\n <span className=\"queue-count\">{say('selected', { selectionCount: selection.length })}</span>\n {fields.length > 0 && (\n <button\n type=\"button\"\n className=\"ghost\"\n disabled={busy}\n onClick={() => {\n setReported(null);\n setSetting(true);\n }}\n >\n {say('setField')}\n </button>\n )}\n {bulk.map((action) => (\n <button\n key={action.label}\n type=\"button\"\n className=\"ghost\"\n title={setSummary(action)}\n disabled={busy}\n onClick={() => {\n void run(action);\n }}\n >\n <ActionLabel action={action} count={selection.length} />\n </button>\n ))}\n {availableCommands.map((action) => (\n <button\n key={`command:${action.command.id}:${action.label}`}\n type=\"button\"\n className=\"ghost\"\n title={say('oneRequestForTheWhole')}\n disabled={busy}\n onClick={() => openCommand(action)}\n >\n <ActionLabel action={action} count={selection.length} noun={nounOf(table)} />\n </button>\n ))}\n <button type=\"button\" className=\"ghost queue-clear\" disabled={Boolean(running)} onClick={clear}>\n {say('clearSelection')}\n </button>\n {running && (\n <span className=\"queue-progress\" role=\"status\">\n {say('applying', { done: running.done, total: running.total })}\n </span>\n )}\n </div>\n )}\n {capped && (\n <p className=\"queue-status\" role=\"status\">\n {say('selectionIsLimitedToRecords', { max: BULK_LIMIT })}\n </p>\n )}\n {/* Dismiss stands beside the report, not in it: the report is where a\n closing command form sends focus, and a dialog sends it to the first\n control inside its target when there is one. */}\n <div className=\"queue-report\">\n <div className=\"queue-result\" role={failed ? 'alert' : 'status'} tabIndex={-1} ref={resultRef} hidden={!reported}>\n {reported && <p>{reported.summary ?? bulkSummary(reported.label, reported.result)}</p>}\n {reported && !reported.summary && reported.result.outcomes.some((outcome) => outcome.kind !== 'applied') && (\n <ul>\n {reported.result.outcomes\n .filter((outcome) => outcome.kind !== 'applied')\n .map((outcome) => (\n <li key={bulkKey(table, outcome.key)}>\n {outcome.label}: {outcome.message}\n </li>\n ))}\n </ul>\n )}\n </div>\n {reported && !running && (\n <button type=\"button\" className=\"ghost queue-dismiss\" onClick={clear}>\n {say('common.dismiss')}\n </button>\n )}\n </div>\n </>\n );\n const dialogs = (\n <>\n {setting && (\n <SetFieldDialog\n table={table}\n columns={fields}\n count={selection.length}\n row={selectedRecords[0]?.row}\n onApply={(column, value) => {\n void setField(column, value);\n }}\n onClose={() => setSetting(false)}\n />\n )}\n {asking && (\n <Confirm\n asking={asking}\n onAnswer={(yes) => {\n setAsking(null);\n asking.answer(yes);\n }}\n />\n )}\n {commandForm && CommandForm && (\n <CommandForm\n key={`${commandForm.epoch}:${commandForm.action.command.id}`}\n action={commandForm.action}\n owner={groupOwner(commandForm)}\n targets={commandForm.targets}\n onDeselect={deselect}\n noun={nounOf(table)}\n label={say('countSelectedRecords', { count: commandForm.targets.length })}\n onClose={closeCommand}\n onDone={() => {}}\n isCurrent={formCurrent}\n finalFocus={returnFocus}\n />\n )}\n </>\n );\n return { offered: bulk.length > 0 || commands.length > 0 || fields.length > 0, selection, change, clear, byId, bar, dialogs };\n}\n\n/** Ask before writing the selection, in the page's own dialog. */\nfunction Confirm({ asking, onAnswer }: { asking: Asking; onAnswer: (yes: boolean) => void }) {\n const { action, count, skipped } = asking;\n const answered = useRef(false);\n const answer = (yes: boolean) => {\n if (answered.current) return;\n answered.current = true;\n onAnswer(yes);\n };\n return (\n <Modal className=\"confirm action-confirm\" ariaLabel={`${action.label}?`} onClose={() => answer(false)}>\n <h2>{action.label}?</h2>\n <p>\n {say('applyToSelectedRecords', { count })}\n {skipped ? say('willBeSkipped', { skipped: formatNumber(skipped) }) : ''}.\n </p>\n <p>\n <strong>{setSummary(action)}</strong>\n </p>\n <div className=\"confirm-actions\">\n <Button intent=\"secondary\" onClick={() => answer(false)}>\n {say('common.cancel')}\n </Button>\n <Button intent=\"primary\" onClick={() => answer(true)}>\n {action.label}\n </Button>\n </div>\n </Modal>\n );\n}\n","/** What GridSelection says, in the lists and grid room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n selectAll: 'Select all {noun}',\n select: 'Select {label}',\n});\n","/**\n * The queue's selection on a grid: a checkbox in each row's leading cell —\n * the row host, so the grid is not told about it — one in the header row's\n * for every row at once, and the same bulk bar, the same keys and the same\n * per-record writes as a queue over the resource.\n */\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport type { AppAction } from '@mistriwork/engine/schema/model.js';\nimport { keyOf, rowLabel } from '../core.js';\nimport { shell } from '../shellMode.js';\nimport { bulkKey } from '../bulkActions.js';\nimport { resourceOf } from './appRooms.js';\nimport { RowDecoration, RowHeadDecoration } from './RowHost.js';\nimport { useBulkSelection, type BulkRecord } from './useBulkSelection.js';\nimport { say } from '../copy/lists/components/GridSelection.js';\n\nexport function GridSelection({\n table,\n rows,\n actions,\n interactive,\n editable = [],\n}: {\n table: TableMeta;\n rows: Array<Record<string, unknown>>;\n actions: AppAction[];\n interactive: boolean;\n /** The list's editable columns: the selection offers \"Set field…\" over them. */\n editable?: readonly string[];\n}) {\n const keyed: BulkRecord[] = rows.flatMap((row) => {\n const key = keyOf(table, row) as Record<string, unknown> | null;\n return key ? [{ id: bulkKey(table, key), key, label: String(rowLabel(table, row) ?? say('common.untitled')), row }] : [];\n });\n const { offered, selection, change, bar, dialogs } = useBulkSelection({ table, keyed, actions, interactive, editable });\n if (!offered) return null;\n const chosen = new Set(selection);\n const every = keyed.length > 0 && selection.length === keyed.length;\n const partly = selection.length > 0 && !every;\n /* The box every table has in its header row: no label and no count, since\n the column says what it is. Its name says what \"all\" takes — the rows\n loaded here, as before — in the resource's own word where it has one. */\n const noun = resourceOf(shell().app(), table.id)?.noun?.many ?? 'rows';\n return (\n <>\n <div className=\"grid-select-bar\">{bar}</div>\n {keyed.length > 0 && (\n <RowHeadDecoration>\n {/* Mixed is a property, not an attribute: set on every paint, because\n the box may reach the header after the selection changed. */}\n <input\n type=\"checkbox\"\n className=\"row-select\"\n aria-label={say('selectAll', { noun })}\n checked={every}\n ref={(box) => {\n if (box) box.indeterminate = partly;\n }}\n onChange={() => change(every ? [] : keyed.map((record) => record.id))}\n />\n </RowHeadDecoration>\n )}\n {keyed.map((record) => (\n <RowDecoration key={record.id} rowKey={record.id}>\n {/* Choosing is not opening: the click stays on the box. */}\n <input\n type=\"checkbox\"\n className=\"row-select\"\n aria-label={say('select', { label: record.label })}\n checked={chosen.has(record.id)}\n onClick={(event) => event.stopPropagation()}\n onChange={(event) => change(event.target.checked ? [...selection, record.id] : selection.filter((id) => id !== record.id))}\n />\n </RowDecoration>\n ))}\n {dialogs}\n </>\n );\n}\n","/** What TableView says, in the lists and grid room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n tableViews: 'Table views',\n rows: 'Rows',\n diagram: 'Diagram',\n definition: 'Definition',\n aPageAboutOne: 'A page about one record of this table',\n page: 'Page →',\n copyThisListAsAnApp: 'Copy this list as an App list view',\n copyAppEntry: 'Copy app entry',\n rowsShown: 'rows {range} shown',\n roughlyFromTheDatabases: 'Roughly, from the database’s own statistics — no rows were counted. Click to count them.',\n rowsRangeOfAbout: 'rows {range} of ~{total}',\n countingStoppedHereClick: 'Counting stopped here. Click to count every matching row.',\n rowsRangeOfAtLeast: 'rows {range} of {total}+',\n totalRows: '{total}+ rows',\n rowsRangeOfTotal: 'rows {range} of {total}',\n ms: '{ms} ms',\n rowsHaveToCome: 'Rows have to come back in some order. Click to make this one explicit.',\n sortedBy: 'sorted by {column}',\n rowsPerPage: 'Rows per page',\n previous: 'Previous',\n next: 'Next',\n previousPage: 'Previous page',\n nextPage: 'Next page',\n first: 'First',\n firstPage: 'First page',\n ofPages: 'of {count}',\n pagePage: 'Page {page}',\n last: 'Last',\n lastPage: 'Last page',\n pageNumber: 'Page number',\n nothingHereRightNow: 'Nothing here right now. Add a record or choose another view.',\n shown: '{rowsCount} shown',\n countShown: '{rows} shown',\n shownOfTotal: '{shown} shown of {total}',\n aboutTotalRows: '~{total} rows',\n});\n","/**\n * The table view around the grid: the result's head, the grid, the pager —\n * and, in the workbench, the tab strip above them.\n *\n * The fetch is not here: TableRoom asks, keyed by the question, and hands\n * the answer in. A page, a page size or a header's sort re-asks in place\n * (core.js `refine`), so this stays mounted while the previous answer stays\n * on screen; `at` says which page that answer is, and `busy` that the next\n * is on its way. What this draws is the answer.\n */\nimport { PresentationSwitch } from './PresentationSwitch.js';\nimport { createPortal } from 'react-dom';\nimport { useCrumbSlots, verbsAt } from './crumbSlot.js';\nimport {\n PAGE_SIZES,\n beginNavigation,\n currentEntry,\n findTable,\n go,\n keyOf,\n pageSize,\n pageView,\n prefersPages,\n refine,\n render,\n setPageSize,\n state,\n} from '../core.js';\nimport { explicitLimit, sortCount, sortDirection } from '../clauses.js';\nimport { NewRowButton } from './NewRecordButton.js';\nimport { copyListView } from '../filterbar.js';\nimport { pagesFor } from '../page.js';\nimport { sortBy } from '../thmenu.js';\nimport { primaryKey, type TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { Dropdown } from './Dropdown.js';\nimport { stepList, takePageStep } from './pageStep.js';\nimport { formatApprox, formatNumber } from '../locale.js';\nimport { ExportControl } from './ExportHold.js';\nimport { Grid, type GridData } from './Grid.js';\nimport { trailListFor } from '../recordTrail.js';\nimport { useContext, useEffect, useMemo, useRef, useState, type ReactNode, type RefObject } from 'react';\nimport { BesideDetail } from './besideDetail.js';\nimport { editableCells, type CellDraw } from './gridCellModel.js';\nimport { canEditRow } from '../rowEditing.js';\nimport { RecordSummaries, tableSaysMore } from './RecordSummaries.js';\nimport { canUseDatabaseTools } from '../connectionScope.js';\nimport { shell } from '../shellMode.js';\nimport { onDemand, useArrived } from './onDemand.js';\nimport { RowHosts, RowTrailHosts } from './RowHost.js';\nimport { RowActions } from './RowActions.js';\nimport { GridSelection } from './GridSelection.js';\nimport { offeredBulk } from './useBulkSelection.js';\nimport { GridOrder, type ListOrder } from './useListOrder.js';\nimport { say } from '../copy/lists/components/TableView.js';\nimport { Icon } from './Icon.js';\n\n/** A grid draws a selection column only for a reader offered a bulk action — or \"Set field…\" — on keyed rows. */\nfunction selectableGrid(table: TableMeta, actions: AppAction[], interactive: boolean, editable: readonly string[]): boolean {\n if (!interactive || (!actions.length && !editable.length) || !primaryKey(table).length) return false;\n const offered = offeredBulk(table, actions, interactive, undefined, undefined, editable);\n return offered.bulk.length > 0 || offered.commands.length > 0 || offered.fields.length > 0;\n}\nimport type { AppAction } from '@mistriwork/engine/schema/model.js';\nimport type { AppListPresentation } from '@mistriwork/engine/shared/listPresentations.js';\n\n/* A cell's editor, fetched the first time a list that edits in place is\n drawn. The list waits for it (TableRoom.tsx, Rows) as it waits for its rows,\n so a click on a cell never opens the row for want of the editor. */\nexport const GridCellEdit = onDemand(() => import('./GridCellEditor.js'), 'GridCellEdit', { quiet: true });\n\n/** Whether the connection on screen is an API (adapters/http), whose tables get the API tab (ApiOperations.tsx). */\nexport function isApiConnection(): boolean {\n return (state as { schema?: { dialect?: string } | null }).schema?.dialect === 'http';\n}\n\nexport interface TableEntry {\n kind: 'table';\n table: string;\n query: string;\n tab?: string;\n exactCount?: boolean;\n}\n\n/** What a list's presentation is drawn from (`present`): the list's own props, and the page of rows it holds. */\nexport interface PresentArgs {\n presentation: AppListPresentation;\n table: TableMeta | undefined;\n data: TableViewProps['data'];\n entry: TableEntry;\n actions: AppAction[] | undefined;\n listLabel: string | undefined;\n referenceLabels: Record<string, string> | undefined;\n interactive: boolean;\n recordNavigation: boolean;\n /** The list these rows are a page of, for a record opened from it to step past the page (recordTrail.ts). */\n list: ReturnType<typeof trailListFor> | undefined;\n /** The record beside this list (a split's detail), marked in it. */\n current: Record<string, unknown> | undefined;\n order: ListOrder | undefined;\n at: PageAt;\n}\n\n/**\n * A presentation drawn in the grid's place. `whole`: it asks its own question\n * (a calendar's month, a tree's every branch) and is the list entire;\n * otherwise it draws this page's rows, under the count and over the pager\n * where it `pages`.\n */\nexport interface PresentedList {\n whole: boolean;\n element: ReactNode;\n pages: boolean;\n}\n\n/** Draws a list's presentation, or null where it cannot be drawn from this answer and the grid stands. */\nexport type Present = (args: PresentArgs) => PresentedList | null;\n\nexport interface TableViewProps {\n /** How the view's rows draw instead of the grid: a checklist, a queue or a board. */\n presentation?: AppListPresentation;\n /** What draws `presentation`: the App's (presentedList.tsx), handed down by its lists. The Workbench passes none, and draws the grid. */\n present?: Present;\n /** The entry's fixed actions, for the presentations that offer them. */\n actions?: AppAction[];\n /** The entry's label: what a queue or board is called to assistive technology. */\n listLabel?: string;\n /** The view's hand-order column, where it keeps one: its rows are put in place by an editor (useListOrder.tsx). */\n order?: string;\n /** An otherwise read-only card list may open a record. */\n recordNavigation?: boolean;\n sizing?: import('@mistriwork/engine/shared/tableSizing.js').TableSizing;\n entry: TableEntry;\n data: GridData & { table: string; rows: Array<Record<string, unknown>>; total?: number; ms: number };\n /** The explorer's own view, or an embedded one (an app list, a page's chooser). */\n chrome: boolean;\n interactive: boolean;\n hide?: string[];\n labels?: Record<string, string>;\n /** A reference column → the fetched path its record's name is read from, drawn in its place by the grid, a queue and cards. */\n referenceLabels?: Record<string, string>;\n /** Column → its total over the whole query, for the grid's footer. */\n totals?: Record<string, unknown>;\n density?: 'comfortable' | 'compact';\n /** A ⋯ menu at the end of each row with the record's own actions. */\n rowActions?: boolean;\n /** The view's `editable`: cells edited in place, and the selection's \"Set field…\" (GridCellEditor.tsx). */\n editable?: true | string[];\n /** The page's own list: Export goes to the crumb bar, the range to the pager. */\n inCrumbs?: boolean;\n export?: boolean;\n summaries?: boolean;\n /**\n * Drawn inside another room — a dashboard's section. It keeps to its width,\n * leaving out the columns past it rather than scrolling to them, and on a\n * phone says its rows as record summaries, with no Records/Table switch:\n * the switch is the list's own, one click away.\n */\n embedded?: boolean;\n /** The page and page size this answer was asked for; the walk's own when not given. */\n at?: PageAt;\n /** The next answer is on its way; this one stays on screen until it lands. */\n busy?: boolean;\n}\n\nexport interface PageAt {\n page: number;\n size: number;\n}\n\n/** Open this table's page: the configured one if there is one, else the suggested. */\nasync function openPageFor(tableId: string): Promise<void> {\n const isCurrent = beginNavigation();\n let pageId = `suggested:${tableId}`;\n try {\n const [configured] = await pagesFor(tableId);\n if (configured && !configured.error) pageId = configured.id;\n } catch {\n // No config pages to read is not a reason to refuse the suggested one.\n }\n if (isCurrent()) go(pageView(pageId, tableId), 'push');\n}\n\n/** The explorer's tabs over a table: rows, definition, diagram — and the doors beside them. */\nexport function ViewTabs({ entry }: { entry: TableEntry }) {\n return (\n <div className=\"tabs\" data-scrolls=\"\">\n {/* The tabs are a tablist of their own: the doors beside them are not\n tabs, and a tablist may hold only tabs. It lays out as if absent. */}\n <div className=\"tabs-list\" role=\"tablist\" aria-label={say('tableViews')}>\n {/* An API's definition is its description, so its tables trade Definition\n for API: its documented reads, tried from here (ApiOperations.tsx). */}\n {(isApiConnection()\n ? ([\n ['rows', say('rows')],\n ['api', 'API'],\n ['diagram', say('diagram')],\n ] as const)\n : ([\n ['rows', say('rows')],\n ['ddl', say('definition')],\n ['diagram', say('diagram')],\n ] as const)\n )\n .filter(([id]) => (id !== 'ddl' && id !== 'api') || canUseDatabaseTools())\n .map(([id, label]) => (\n <button\n key={id}\n type=\"button\"\n role=\"tab\"\n className=\"tab\"\n aria-selected={(entry.tab ?? 'rows') === id}\n onClick={() => go({ ...entry, tab: id }, 'replace')}\n >\n {label}\n </button>\n ))}\n </div>\n {/* The way into a page from a table: not a tab of this table, but this\n is where someone looks for it. */}\n <button type=\"button\" className=\"tab tab-page\" title={say('aPageAboutOne')} onClick={() => void openPageFor(entry.table)}>\n {say('page')}\n </button>\n {/* The authoring bridge: this list as a paste-ready App list view. */}\n <button type=\"button\" className=\"tab tab-copy-entry\" title={say('copyThisListAsAnApp')} onClick={() => void copyListView(entry)}>\n {say('copyAppEntry')}\n </button>\n </div>\n );\n}\n\nfunction ResultHead({\n entry,\n data,\n chrome,\n interactive,\n exportOn,\n at,\n headRef,\n inCrumbs = false,\n}: {\n entry: TableEntry;\n data: TableViewProps['data'];\n chrome: boolean;\n interactive: boolean;\n exportOn: boolean;\n at: PageAt;\n headRef: RefObject<HTMLDivElement | null>;\n inCrumbs?: boolean;\n}) {\n const tools = verbsAt(useCrumbSlots());\n /* The page's own list says its count in the crumb bar (or its heading row,\n where no bar is drawn) and its range in the pager; Export joins New at\n that row's end, and no stats row is drawn. */\n if (inCrumbs && tools) {\n return (\n <div className=\"result-head-anchor\" ref={headRef}>\n {exportOn && createPortal(<ExportControl entry={entry} data={data} />, tools)}\n </div>\n );\n }\n /* Any other App list (one drawn inside a record or a dashboard) names its\n count in its own title: \"2 rows\" and \"sorted by id ↓\" under it were the\n Workbench's instruments, which stay in the Workbench. */\n if (shell().inApp() && !chrome) {\n const own = findTable(data.table) as TableMeta | undefined;\n return (\n <div className=\"result-head result-head-app\" ref={headRef}>\n {!prefersPages() && own && <NewRowButton table={own} />}\n {exportOn && <ExportControl entry={entry} data={data} />}\n </div>\n );\n }\n const first = at.page * at.size + 1;\n const shown = at.page * at.size + data.rows.length;\n const total = data.total;\n /* The range on screen. \"60 of 907\" on page three read as sixty rows\n shown, and the last page's bare total read as a table that fits. It is\n the answer's own page: while the next one is fetched, these are still\n the rows in front of the reader. */\n const range = at.page > 0 || (total !== undefined && total > shown) ? `${formatNumber(first)}–${formatNumber(shown)}` : null;\n const table = findTable(data.table) as TableMeta | undefined;\n return (\n <div className=\"result-head\" ref={headRef}>\n {chrome && <h1 className=\"result-title\">{data.table}</h1>}\n {total === undefined ? (\n <span className=\"stat\">\n {range && data.rows.length > 0\n ? say('rowsShown', { range })\n : say('countShown', { rows: say('common.rows2', { count: data.rows.length }) })}\n </span>\n ) : data.exactTotal === false ? (\n /* An estimate says so, and offers the real number: above a threshold\n the count comes from the catalog's statistics, and \"~2.4M\" is\n honest where \"2,400,113\" would not be. */\n <button\n type=\"button\"\n className=\"stat stat-estimate\"\n title={say('roughlyFromTheDatabases')}\n onClick={() => go({ ...entry, exactCount: true }, 'replace')}\n >\n {range ? say('rowsRangeOfAbout', { range, total: formatApprox(total) }) : say('aboutTotalRows', { total: formatApprox(total) })}\n </button>\n ) : data.cappedTotal ? (\n /* A filtered total is counted to a bound (10,000 by default), which\n is what keeps a filter over a large table from spending most of\n its time counting. Past it the head says \"10,000+\" and offers the\n exact number, one click and one full count away. */\n <button\n type=\"button\"\n className=\"stat stat-estimate\"\n title={say('countingStoppedHereClick')}\n onClick={() => go({ ...entry, exactCount: true }, 'replace')}\n >\n {range ? say('rowsRangeOfAtLeast', { range, total: formatNumber(total) }) : say('totalRows', { total: formatNumber(total) })}\n </button>\n ) : (\n <span className=\"stat\">\n {range ? say('rowsRangeOfTotal', { range, total: formatNumber(total) }) : say('common.rows2', { count: total })}\n </span>\n )}\n {/* The query's time is the Workbench's instrument; in an App's list it\n was a number beside the count nobody there asked for. */}\n {!shell().inApp() && <span className=\"stat\">{say('ms', { ms: data.ms })}</span>}\n {/* The default order, named, because the column it sorted by may not\n be on screen. Clicking writes it into the query. */}\n {interactive && data.order?.implicit && data.order.order.length > 0 && (\n <button\n type=\"button\"\n className=\"stat stat-order\"\n title={say('rowsHaveToCome')}\n onClick={() => sortBy(data.order!.order[0].column, data.order!.order[0].direction)}\n >\n {say('sortedBy', { column: data.order.order[0].column })}\n {data.order.order[0].direction === 'desc' ? ' ↓' : ' ↑'}\n </button>\n )}\n {/* Not where the app's list head already offers \"New\". */}\n {!prefersPages() && table && <NewRowButton table={table} />}\n {exportOn && <ExportControl entry={entry} data={data} />}\n </div>\n );\n}\n\n/**\n * Paging, for a table somebody might actually reach the end of. The size\n * control sits on the left whether or not there is a second page; \"Last\"\n * and the page box appear only when the total is a real count.\n *\n * The controls say where the reader asked to be (`state.page`), at once;\n * the rows follow when they land. Every move is a refinement (core.js\n * `refine`): the room is re-asked in place rather than started over.\n */\nfunction Pager({ entry, data, at, range = false }: { entry: TableEntry; data: TableViewProps['data']; at: PageAt; range?: boolean }) {\n if (data.total === 0 && state.page === 0) return null;\n const app = shell().inApp();\n // A query that names its own limit defines the whole result.\n if (explicitLimit(entry.query)) return app ? null : <div className=\"pager\" />;\n const size = pageSize();\n const shown = state.page * size + data.rows.length;\n /* An estimated total cannot decide whether there is a next page; a full\n page returned is the honest signal. */\n const full = data.rows.length >= size;\n const total = data.total;\n // A bounded total says \"at least\", which cannot name the last page either.\n const counted = data.exactTotal !== false && !data.cappedTotal && typeof total === 'number';\n const more = counted ? total > shown : full;\n const lastPage = counted ? Math.max(0, Math.ceil(total / size) - 1) : null;\n /* An App's list that fits one page draws no pager at all: twelve rows\n under \"« First ← Previous Page [1] of 1 Next → Last »\" was five\n controls that could do nothing. */\n if (app && state.page === 0 && !more) return null;\n /* Next, Previous and Last step from the rows on screen (pageStep.ts), so a\n deep page is read by key and costs what the first does; a number typed\n in the box, and First, are read by offset. */\n const list = stepList((state as { activeConnection?: string }).activeConnection ?? '', entry.table, entry.query, size);\n const goTo = (page: number, how?: 'next' | 'previous' | 'last') => {\n const wanted = Math.max(0, lastPage === null ? page : Math.min(page, lastPage));\n if (wanted === state.page) return;\n /* Only the page the pager is on can be stepped from: while the next one\n is fetched the rows on screen are the last answer's, and a second\n click would step from them to the page already being read. */\n const bounds = at.page === state.page && at.size === size ? data.bounds : undefined;\n if (how === 'last' && counted) takePageStep(list, wanted, { end: true }, total! - wanted * size);\n else if (how === 'next' && bounds) takePageStep(list, wanted, { after: bounds.last });\n else if (how === 'previous' && bounds && wanted > 0) takePageStep(list, wanted, { before: bounds.first });\n else takePageStep(list, wanted);\n refine(() => {\n state.page = wanted;\n render();\n });\n };\n const step = (text: string, label: string, to: number, enabled: boolean, how?: 'next' | 'previous' | 'last') => (\n <button type=\"button\" className=\"step-button\" aria-label={label} disabled={!enabled} onClick={() => goTo(to, how)}>\n {how !== 'next' && how !== 'last' && <Icon name=\"caret-left\" size={16} />}\n <span className=\"step-label\">{text}</span>\n {(how === 'next' || how === 'last') && <Icon name=\"caret-right\" size={16} />}\n </button>\n );\n const sizes = (\n <div className=\"pager-size\">\n <span>{say('rows')}</span>\n <Dropdown\n ariaLabel={say('rowsPerPage')}\n value={String(size)}\n items={(PAGE_SIZES as number[]).map((n) => ({ value: String(n), label: String(n) }))}\n onChange={(n) =>\n refine(() => {\n setPageSize(Number(n));\n render();\n })\n }\n />\n </div>\n );\n const said = data.rows.length > 0 && (\n <span className={`pager-range${app ? ' step-position' : ''}`}>\n {formatNumber(state.page * size + 1)}–{formatNumber(shown)}\n {counted ? say('common.ofTotal', { total: formatNumber(total!) }) : ''}\n </span>\n );\n /* An App's reader pages on: where they are, then Previous and Next. First,\n Last and the page box are the Workbench's, where a table is walked. */\n if (app) {\n return (\n <div className=\"pager pager-app\">\n {/* How many rows a page holds is the operator's instrument, not a buyer's. */}\n {!shell().publicVisitor() && sizes}\n <div className=\"pager-steps step-control\">\n {step(say('previous'), say('previousPage'), state.page - 1, state.page > 0, 'previous')}\n {said}\n {step(say('next'), say('nextPage'), state.page + 1, more, 'next')}\n </div>\n </div>\n );\n }\n return (\n <div className=\"pager\">\n {sizes}\n {range && said}\n <div className=\"pager-steps pager-workbench step-control\">\n {step(say('first'), say('firstPage'), 0, state.page > 0)}\n {step(say('previous'), say('previousPage'), state.page - 1, state.page > 0, 'previous')}\n {counted ? (\n <span className=\"page-label step-position\">\n <span>{say('common.page')}</span>\n <PageBox page={state.page} last={lastPage!} onGo={goTo} />\n <span>{say('ofPages', { count: formatNumber(lastPage! + 1) })}</span>\n </span>\n ) : (\n <span className=\"page-label step-position\">{say('pagePage', { page: formatNumber(state.page + 1) })}</span>\n )}\n {step(say('next'), say('nextPage'), state.page + 1, more, 'next')}\n {counted && step(say('last'), say('lastPage'), lastPage!, state.page < lastPage!, 'last')}\n </div>\n </div>\n );\n}\n\n/**\n * The page box. It used to be uncontrolled and was reset by the repaint\n * that followed every move; the pager is kept now, so the box follows the\n * page it is on. What is typed stays typed while it names no page yet (an\n * emptied box on the way to another number), and goes on leaving the box.\n */\nfunction PageBox({ page, last, onGo }: { page: number; last: number; onGo: (page: number) => void }) {\n const [typed, setTyped] = useState<string | null>(null);\n return (\n <input\n className=\"page-input\"\n type=\"number\"\n min={1}\n max={last + 1}\n value={typed ?? String(page + 1)}\n aria-label={say('pageNumber')}\n onBlur={() => setTyped(null)}\n onChange={(e) => {\n const text = e.target.value;\n if (text === '') {\n setTyped('');\n return;\n }\n setTyped(null);\n const asked = Number(text);\n if (Number.isFinite(asked)) onGo(Math.round(asked) - 1);\n }}\n />\n );\n}\n\nexport function TableView({\n entry,\n data,\n chrome,\n interactive,\n hide,\n labels,\n referenceLabels,\n totals,\n density,\n rowActions,\n editable,\n inCrumbs,\n sizing,\n export: exportOn = true,\n summaries = false,\n embedded = false,\n presentation,\n present,\n actions,\n listLabel,\n order,\n recordNavigation = false,\n at: given,\n busy = false,\n}: TableViewProps) {\n /* Records or table: how a narrow screen shows the rows, the reader's pick. The page's own list draws the switch at\n the end of its control strip (AppList), beside the tabs; anywhere else, over the rows. */\n const [layout, setLayout] = useState('records');\n const { controls } = useCrumbSlots();\n const presentationSwitch = (element: ReactNode) => (inCrumbs && controls ? createPortal(element, controls) : element);\n const table = findTable(data.table) as TableMeta | undefined;\n /* The cells this reader may edit in place: the view's `editable` over the\n columns drawn, each still asked of the row (canEditRow) when drawn. */\n const shownColumns = (data.columns ?? []).filter((name) => !hide?.includes(name));\n const cells = interactive && !embedded && !presentation ? editableCells(table, editable, shownColumns) : new Map<string, string>();\n /* A dashboard's list that works as its room (embedded, interactive) offers its selection's \"Set field…\"\n over the same columns, and edits no cell in place: a dashboard is not where a cell is typed into. */\n const editing = [...new Set((interactive && embedded && !presentation ? editableCells(table, editable, shownColumns) : cells).values())];\n const cellsKey = [...cells].join('\\n');\n const editorHere = useArrived(GridCellEdit, cells.size > 0);\n /* The shell's marks in empty cells (a suggestion waiting on one); the slot is the shell's for its whole life, so the hook's place is fixed. */\n const adornCell = shell().slots.useCellMarks?.(table, data?.rows ?? []);\n const editCell = useMemo(() => {\n if (!table || !cells.size || !editorHere) return undefined;\n return (row: Record<string, unknown>, drawn: string, draw: CellDraw, drawnLabel?: unknown) => {\n const column = cells.get(drawn);\n const key = keyOf(table, row) as Record<string, unknown> | null;\n const meta = column === undefined ? undefined : table.columns.find((c) => c.name === column);\n // A reference drawn by name is edited only when its key rode along with the row (appListModel's showClause).\n if (!key || !meta || !Object.hasOwn(row, meta.name) || !canEditRow(table, key)) return undefined;\n /* The name the cell already says — its label, or the path it draws by name — so the editor opens on it. */\n const named = drawn !== meta.name ? row[drawn] : drawnLabel;\n return (\n <GridCellEdit\n table={table}\n row={row}\n column={meta}\n recordKey={key}\n draw={draw}\n byName={drawn !== meta.name}\n {...(named === null || named === undefined || named === '' ? {} : { valueLabel: String(named) })}\n />\n );\n };\n }, [table, cellsKey, editorHere]); // eslint-disable-line react-hooks/exhaustive-deps\n const at = given ?? { page: state.page, size: pageSize() as number };\n /* Beside a split's detail pane the grid keeps to its width, as an embedded one does. */\n const beside = useContext(BesideDetail);\n const hasSummaries =\n (summaries || embedded) &&\n table &&\n data.rows.length > 0 &&\n primaryKey(table).length > 0 &&\n primaryKey(table).every((c: string) => data.columns?.includes(c));\n /* Records and Table are a choice only where the table says more than the records do; a list whose records say it all\n has one reading, and two tabs for it are a decision with nothing to decide. */\n const choice =\n hasSummaries &&\n tableSaysMore(\n table,\n (data.columns ?? []).filter((name: string) => !hide?.includes(name)),\n data.rows,\n entry.query,\n referenceLabels,\n );\n const firstRow = explicitLimit(currentEntry()?.query ?? '') ? 0 : at.page * at.size;\n /* A new page is read from its top. When every page was a repaint the room\n emptied while the next one loaded and the pane fell back to the top by\n itself; the room is kept now, so the head is brought back into view on\n purpose, once the new page has landed and only if it had scrolled away.\n Not for a sort: the header under the pointer is where the reader is. */\n const head = useRef<HTMLDivElement>(null);\n const turned = useRef(`${at.page}:${at.size}`);\n useEffect(() => {\n const now = `${at.page}:${at.size}`;\n if (turned.current === now) return;\n turned.current = now;\n head.current?.scrollIntoView({ block: 'nearest' });\n }, [at.page, at.size]);\n /* A presentation stands in for the grid only when the answer carries every\n column it reads; an advanced query that dropped one keeps the grid. */\n /* The list these rows are a page of, for every presentation of it: a\n record opened from the grid, a card, a queue or a checklist steps past\n the page with the same question (recordTrail.ts). A query that names its\n own limit is the whole list, so no page follows this one. */\n const list = explicitLimit(entry.query) ? undefined : trailListFor(entry.query, data);\n /* The record beside this list — a split's detail — marked in it and kept\n in view while J and K step (Rooms.tsx). */\n const top = currentEntry() as { kind?: string; table?: string; key?: Record<string, unknown> } | undefined;\n const current = top?.kind === 'row' && top.table === entry.table ? top.key : undefined;\n /* A view's hand order is live only while the question reads in it — its\n sort is that column, ascending, and nothing else. A header, a tab's own\n sort or the Sort menu reads the rows another way, and the handles go\n until the order is back. */\n const listOrder: ListOrder | undefined = order\n ? {\n column: order,\n active: sortCount(entry.query) === 1 && sortDirection(entry.query, order) === 'asc',\n partial: at.page > 0 || (typeof data.total === 'number' ? data.total > data.rows.length : data.rows.length >= at.size),\n }\n : undefined;\n const presented =\n presentation && present\n ? present({\n presentation,\n table,\n data,\n entry,\n actions,\n listLabel,\n referenceLabels,\n interactive,\n recordNavigation,\n list,\n current,\n order: listOrder,\n at,\n })\n : null;\n if (presented?.whole) return presented.element;\n if (presented)\n return (\n <>\n {data.rows.length ? presented.element : <p className=\"checklist-empty\">{say('nothingHereRightNow')}</p>}\n {chrome && data.rows.length > 0 && (\n <p className=\"checklist-count\">\n {typeof data.total === 'number' && data.exactTotal !== false && data.total > data.rows.length\n ? say('shownOfTotal', { shown: data.rows.length, total: `${data.total}${data.cappedTotal ? '+' : ''}` })\n : say('shown', { rowsCount: data.rows.length })}\n </p>\n )}\n {/* An App's cards, queue or checklist page as its grid does: they drew\n the first twenty of fifty-five cars and no way to the rest. A board\n reads its lanes whole (BoardList), so it has no page to turn. */}\n {presented.pages && (chrome ? state.page > 0 || data.rows.length >= pageSize() : shell().inApp()) && (\n <Pager entry={entry} data={data} at={at} />\n )}\n </>\n );\n /* The grid, then what decorates its rows from outside: a checkbox in the\n leading cell for a reader offered bulk actions, a grip there for a view\n kept in hand order, a ⋯ at the end of each row when the view asks for\n row menus. */\n const gridOf = (rows: typeof data.rows) => (\n <Grid\n table={table}\n data={rows === data.rows ? data : { ...data, rows }}\n hide={hide}\n labels={labels}\n referenceLabels={referenceLabels}\n totals={totals}\n density={density}\n sizing={sizing}\n interactive={interactive}\n firstRow={firstRow}\n list={list}\n current={current}\n dropColumns={embedded || beside}\n editCell={editCell}\n {...(adornCell ? { adornCell } : {})}\n />\n );\n const hasOrder = Boolean(listOrder && table);\n const ordered =\n hasOrder && listOrder && table ? (\n <GridOrder table={table} rows={data.rows} order={listOrder} interactive={interactive}>\n {gridOf}\n </GridOrder>\n ) : (\n gridOf(data.rows)\n );\n const selected =\n table && selectableGrid(table, actions ?? [], interactive, editing) ? (\n <RowHosts>\n <GridSelection table={table} rows={data.rows} actions={actions ?? []} interactive={interactive} editable={editing} />\n {ordered}\n </RowHosts>\n ) : !hasOrder ? (\n ordered\n ) : (\n <RowHosts>{ordered}</RowHosts>\n );\n // A row's menu draws what the record's bar draws, so an action kept out of it (`header: false`) is no reason for a ⋯.\n const tableGrid =\n rowActions && (interactive || embedded) && table && actions?.some((action) => action.header !== false) && primaryKey(table).length ? (\n <RowTrailHosts>\n <RowActions table={table} rows={data.rows} actions={actions} onDone={() => render()} />\n {selected}\n </RowTrailHosts>\n ) : (\n selected\n );\n return (\n <>\n <ResultHead\n entry={entry}\n data={data}\n chrome={chrome}\n interactive={interactive}\n exportOn={exportOn}\n at={at}\n headRef={head}\n inCrumbs={inCrumbs}\n />\n <div className={hasSummaries ? `responsive-results show-${embedded || !choice ? 'records' : layout}` : undefined}>\n {hasSummaries && (\n <>\n {!embedded &&\n choice &&\n presentationSwitch(\n <PresentationSwitch\n layout={layout}\n onChange={setLayout}\n label={say('common.listPresentation')}\n records={say('common.records')}\n table={say('common.table')}\n />,\n )}\n {/* A reference says its record's name here too, as the grid beside it does. */}\n <RecordSummaries\n table={table}\n data={data}\n columns={(data.columns ?? []).filter((name) => !hide?.includes(name))}\n labels={labels}\n referenceLabels={referenceLabels}\n list={list}\n query={entry.query}\n {...(adornCell ? { adornFact: (row: Record<string, unknown>, column: string) => adornCell(row, column, 'summary') } : {})}\n />\n </>\n )}\n <div className=\"result-table\" aria-busy={busy || undefined}>\n {tableGrid}\n </div>\n </div>\n <Pager entry={entry} data={data} at={at} range={inCrumbs} />\n </>\n );\n}\n","/** What TableRoom says, in the lists and grid room (packages/kit/src/client/messages.ts says how the catalog is split). */\nimport { defineMessages } from '../../../messages.js';\n\nexport const say = defineMessages({\n fixTheQueryAbove: 'Fix the query above to see results.',\n notAvailableToYou: 'This {thing} is not available to your role.',\n notAvailableHere: 'This {thing} is not available.',\n signInToSeeThis: 'This {thing} is for signed-in members.',\n thingList: 'list',\n thingRecord: 'record',\n thingPage: 'page',\n storedDefinition: 'Stored definition. ',\n thisIsTheStatement: 'This is the statement the database itself keeps, verbatim.',\n rebuiltFromTheCatalog: 'Rebuilt from the catalog. Indexes, checks and triggers are not shown.',\n});\n","/**\n * The table view as a room: the fetch, what it touches, and the components\n * that draw the answer.\n *\n * The request is a Query keyed by everything that changes the answer — the\n * connection, the table, the line, the page and its size — so a reply that\n * outlived its question never paints: the key it was fetched under is no\n * longer the one on screen. The room owns that result. A page, a page size\n * or a header's sort or filter is a refinement (core.js `refine`): the room\n * stays mounted, the key moves, and the previous answer stays on screen\n * until the next lands, so the grid re-renders in place and whatever lives\n * in its rows keeps its state. Nothing is kept between visits (`gcTime: 0`):\n * any other paint starts the room over and re-asks, the way it always was,\n * and a write that repaints the room sees its own effect.\n *\n * With `chrome` the room is the explorer's own — the tabs, the filter\n * boxes, the query bar's text, and the globals a shared result touches:\n * the nested cache, the error banner, the SQL pane, the history. Off, it\n * is a grid embedded in someone else's surface — an app list, a dashboard\n * section, a page's chooser — and touches nothing but its own box.\n */\nimport { useEffect, type ReactNode } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { $, api, columnLabel, findTable, go, pageSize, setExplain, showErrors, state, tableView } from '../core.js';\nimport { explicitLimit } from '../clauses.js';\nimport { deriveFilterNames } from '../filterbar.js';\nimport { recordQuery } from '../history.js';\nimport { resetNested } from '../nested.js';\nimport { canUseDatabaseTools } from '../connectionScope.js';\nimport { shell } from '../shellMode.js';\nimport { appKeepsRoles } from '../roleLabels.js';\nimport { arrivedPlacement } from '../addressMount.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport type { ResourceClientReply, ResourceHttpSuccess } from '@mistriwork/engine/shared/resourceHttp.js';\nimport { onDemand, useArrived } from './onDemand.js';\nimport { FilterBar } from './FilterBoxes.js';\nimport { Delayed, GridSkeleton } from './Skeleton.js';\nimport { Problem, Refused } from './Notes.js';\nimport type { GridData } from './Grid.js';\nimport { GridCellEdit, isApiConnection, TableView, ViewTabs, type PageAt, type TableEntry, type TableViewProps } from './TableView.js';\nimport { pageStepFor, stepList } from './pageStep.js';\nimport { ExportHold } from './ExportHold.js';\nimport { batchedRun } from '../breakdownBatch.js';\nimport { useListHold } from '../liveState.js';\nimport { say } from '../copy/lists/components/TableRoom.js';\n\n/* The diagrams are a chunk of their own, loaded when the Diagram tab is first opened. */\n/**\n * A list this reader's catalog leaves out. Signed in, the role is the reason.\n * Signed out of an App the public browses, the list may well be a member's:\n * the refusal offers the sign-in, drawn in place so the visitor comes back to\n * this address once signed in (the shell's `signInHere`, publicSurface.js). A visitor on a\n * tenant's public address keeps the top bar's door, which leaves that address\n * behind on purpose (app.js, showAccount).\n */\nfunction NotYours({ thing }: { thing: string }) {\n const app = state.activeConnection;\n const noun = { thing };\n // An App with no roles has none to blame: the list is simply not one this address names.\n if (!shell().publicVisitor()) return <Refused text={say(appKeepsRoles() ? 'notAvailableToYou' : 'notAvailableHere', noun)} />;\n // Signed out, no role is the reason, wherever the door is.\n if (typeof app !== 'string' || arrivedPlacement()) return <Refused text={say('signInToSeeThis', noun)} />;\n return (\n <Refused\n text={say('signInToSeeThis', noun)}\n action={\n <button type=\"button\" className=\"ghost\" onClick={() => shell().signInHere(app)}>\n {say('common.signIn')}\n </button>\n }\n />\n );\n}\n\nconst NeighbourhoodDiagram = onDemand(() => import('./Diagram.js'), 'NeighbourhoodDiagram');\n/* An API's documented reads, tried from here: only a connection to an API has the tab. */\n/* The pill over a list that is held (liveState.ts): a part of its own, fetched when the first change is held. */\nconst LivePill = onDemand(() => import('./LiveNotices.js'), 'LivePill', { quiet: true });\nconst ApiOperations = onDemand(() => import('./ApiOperations.js'), 'ApiOperations');\n\ntype RunData = ResourceHttpSuccess<'/api/run'>;\n\ninterface TableRoomProps {\n empty?: ReactNode;\n presentation?: TableViewProps['presentation'];\n /** What draws `presentation` (TableView.tsx): the App's, which its lists hand down. */\n present?: TableViewProps['present'];\n /** The entry's fixed actions; a queue offers the bulk ones, a board its lane moves. */\n actions?: TableViewProps['actions'];\n /** The entry's label, the accessible name a presentation goes by. */\n listLabel?: string;\n /** The view's hand-order column, where it keeps one. */\n order?: string;\n /** A read-only card may still be a doorway to its record. */\n recordNavigation?: boolean;\n sizing?: TableViewProps['sizing'];\n entry: TableEntry;\n /** The explorer's own view: tabs, boxes, the query bar, the shared globals. Default on. */\n chrome?: boolean;\n /** A gutter on both sides; embedded grids sit in sections that already pad. Defaults to `chrome`. */\n inset?: boolean;\n interactive?: boolean;\n hide?: string[];\n labels?: Record<string, string>;\n /** A reference column → the fetched path its record's name is read from (appListModel's referenceNames). */\n referenceLabels?: Record<string, string>;\n /** Column → its total over the whole query; undefined while it is asked. */\n totals?: Record<string, unknown>;\n density?: 'comfortable' | 'compact';\n /** A ⋯ menu at the end of each row with the record's own actions. */\n rowActions?: boolean;\n /** The view's `editable`: cells edited in place and the selection's \"Set field…\". */\n editable?: true | string[];\n /** The page's own list: its verbs go to the crumb bar and its range to the pager. */\n inCrumbs?: boolean;\n export?: boolean;\n summaries?: boolean;\n /** Drawn inside another room (a dashboard's section): see TableViewProps.embedded. */\n embedded?: boolean;\n /** Re-asked when this changes — a dashboard's refresh clock. */\n version?: number;\n /** The answer, once it has rows and columns. */\n onResult?: (data: RunData) => void;\n}\n\n/** The noun a refused room is: a record when the address names one, a list over a table the reader's catalog has,\n and a page for whatever else (the catalog leaves out what the role cannot see, so its kind is not known). */\nconst thingOf = (entry: TableEntry, table: TableMeta | undefined): string => {\n const { kind, table: named } = entry as { kind?: string; table?: string };\n return kind === 'row' || (kind === 'page' && named) ? say('thingRecord') : table ? say('thingList') : say('thingPage');\n};\n\nconst connection = () => (state as { activeConnection?: string }).activeConnection ?? '';\n\nexport function TableRoom({\n entry,\n chrome = true,\n inset = chrome,\n interactive = true,\n hide,\n labels,\n referenceLabels,\n totals,\n density,\n rowActions,\n editable,\n inCrumbs,\n sizing,\n export: exportOn = true,\n summaries = false,\n embedded = false,\n version = 0,\n onResult,\n presentation,\n present,\n actions,\n listLabel,\n order,\n recordNavigation = false,\n empty,\n}: TableRoomProps) {\n /* A tab this reader cannot have here falls back to Rows: Definition and API\n are the operator's, API only over an API, and an API's definition is its\n description, so it has no Definition tab. */\n const wanted = entry.tab ?? 'rows';\n const overApi = isApiConnection();\n const tab =\n (wanted === 'ddl' || wanted === 'api') && !canUseDatabaseTools()\n ? 'rows'\n : (wanted === 'api' && !overApi) || (wanted === 'ddl' && overApi)\n ? 'rows'\n : wanted;\n /* Only the explorer's own table view owns the query bar. Chrome off means\n an app list or an embedded chooser: their entry is synthetic, and a bar\n showing a query the walk is not on is the bar lying about where you are. */\n useEffect(() => {\n if (!chrome) return;\n const bar = $('query') as HTMLInputElement | null;\n if (bar) bar.value = entry.query;\n }, [chrome, entry.query]);\n return (\n <>\n {chrome && (\n <div className=\"grid-host\">\n <ViewTabs entry={entry} />\n </div>\n )}\n {/* Keyed by the line: the boxes hold what was typed and not yet sent, and\n a header's filter that changed the line under them starts them over,\n as the repaint it used to be did. A page keeps them. */}\n {chrome && tab === 'rows' && <FilterSection key={entry.query} entry={entry} />}\n <div className={inset ? 'grid-inset' : undefined}>\n {tab === 'diagram' ? (\n <div className=\"panel-pad\">\n <div className=\"diagram\">\n <NeighbourhoodDiagram tableId={entry.table} />\n </div>\n </div>\n ) : tab === 'api' ? (\n <ApiOperations table={entry.table} />\n ) : tab === 'ddl' ? (\n <DdlPane table={entry.table} />\n ) : (\n <Rows\n entry={entry}\n chrome={chrome}\n interactive={interactive}\n hide={hide}\n labels={labels}\n referenceLabels={referenceLabels}\n totals={totals}\n density={density}\n rowActions={rowActions}\n editable={editable}\n inCrumbs={inCrumbs}\n sizing={sizing}\n exportOn={exportOn}\n summaries={summaries}\n embedded={embedded}\n version={version}\n onResult={onResult}\n presentation={presentation}\n present={present}\n actions={actions}\n listLabel={listLabel}\n order={order}\n recordNavigation={recordNavigation}\n empty={empty}\n />\n )}\n </div>\n </>\n );\n}\n\nconst escaped = (text: string) => text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/**\n * A refusal in the reader's words. An API's refusal quotes columns as the API\n * names them (`carrier_id`) and lists which (`columns`); an App calls them by\n * its captions (\"Carrier\"). Only the listed names are swapped, as whole words,\n * and never inside a documented sort value such as `-created_at`. Outside an\n * App there are no captions, and the message stays as it is.\n */\nexport function inCaptions(error: unknown, table: TableMeta | undefined): string {\n const message = (error as Error).message;\n const columns = (error as { columns?: unknown }).columns;\n if (!table || !Array.isArray(columns)) return message;\n return columns.reduce<string>((text, name) => {\n const caption = typeof name === 'string' ? columnLabel(table.id, name) : null;\n return caption && caption !== name ? text.replace(new RegExp(`(?<![\\\\w+-])${escaped(name)}(?![\\\\w:])`, 'g'), () => caption) : text;\n }, message);\n}\n\n/**\n * The named filter boxes over a table (components/FilterBoxes.tsx), in a host\n * that takes no room. Standing alone a new question goes to the walk;\n * embedded (a rootless page's chooser) the host says where it goes.\n */\nexport function FilterSection({ entry, names, navigate }: { entry: TableEntry; names?: string[]; navigate?: (query: string) => void }) {\n const table = findTable(entry.table) as TableMeta | undefined;\n if (!table) return null;\n const chosen = names ?? (deriveFilterNames(table) as string[]);\n if (!chosen.length) return null;\n const to = navigate ?? ((query: string) => go(tableView(entry.table, query, entry.tab), 'replace'));\n return (\n <div className=\"host-contents\">\n <FilterBar table={table} entry={entry} names={chosen} navigate={to} />\n </div>\n );\n}\n\n/* The page each answer was asked for, by the answer. While the next page is\n fetched the previous answer is what is on screen, and the head's range and\n the keyboard's row numbers describe the rows that are there. */\nconst askedFor = new WeakMap<object, PageAt>();\n\n/* A list's total, by the question and not the page: turning a page asks for\n rows only (`count: 'none'`) and says the total the list already has. It\n was recounted on every page turn — the offset is in the rows' key — and\n a filtered total is most of a filtered read's time. The key carries the\n room's version, so a write that could change the total recounts it; page\n one always counts, so going back to the start refreshes it. */\ntype Totals = Pick<GridData, 'total' | 'exactTotal' | 'cappedTotal'>;\nconst listTotals = new Map<string, Totals>();\nconst TOTALS_KEPT = 50;\nfunction keepTotal(key: string, reply: unknown): void {\n if (!reply || typeof reply !== 'object' || !('ms' in reply)) return;\n const { total, exactTotal, cappedTotal } = reply as Totals;\n if (typeof total !== 'number') return;\n listTotals.delete(key);\n if (listTotals.size >= TOTALS_KEPT) listTotals.delete(listTotals.keys().next().value!);\n listTotals.set(key, { total, ...(exactTotal !== undefined ? { exactTotal } : {}), ...(cappedTotal ? { cappedTotal } : {}) });\n}\n\nfunction Rows({\n entry,\n chrome,\n interactive,\n hide,\n labels,\n referenceLabels,\n totals,\n density,\n rowActions,\n editable,\n inCrumbs,\n sizing,\n exportOn,\n summaries,\n embedded,\n version,\n onResult,\n presentation,\n present,\n actions,\n listLabel,\n order,\n recordNavigation,\n empty,\n}: {\n empty?: ReactNode;\n embedded: boolean;\n presentation?: TableViewProps['presentation'];\n present?: TableViewProps['present'];\n actions?: TableViewProps['actions'];\n listLabel?: string;\n order?: string;\n recordNavigation: boolean;\n sizing?: TableViewProps['sizing'];\n entry: TableEntry;\n chrome: boolean;\n interactive: boolean;\n hide?: string[];\n labels?: Record<string, string>;\n referenceLabels?: Record<string, string>;\n totals?: Record<string, unknown>;\n density?: 'comfortable' | 'compact';\n rowActions?: boolean;\n editable?: true | string[];\n inCrumbs?: boolean;\n exportOn: boolean;\n summaries: boolean;\n version: number;\n onResult?: (data: RunData) => void;\n}) {\n const table = findTable(entry.table) as TableMeta | undefined;\n /* An explicit `limit` in the query is a deliberate statement and beats the page size. */\n const asked = explicitLimit(entry.query) as number | null;\n const size = pageSize() as number;\n const page = (state as { page: number }).page;\n const source = connection();\n /* A page the pager stepped to is read by key, the end with its own length (pageStep.ts). */\n const step = asked ? undefined : pageStepFor(stepList(source, entry.table, entry.query, size), page);\n const limit = asked ?? step?.limit ?? size;\n const offset = asked ? 0 : page * size;\n const exact = entry.exactCount === true;\n const run = useQuery<ResourceClientReply<'/api/run'>>({\n queryKey: ['run', source, entry.table, entry.query, limit, offset, exact, version, step?.body],\n queryFn: async () => {\n const totalKey = JSON.stringify([source, entry.table, entry.query, exact, version]);\n const known = offset > 0 ? listTotals.get(totalKey) : undefined;\n const asked = { q: entry.query, limit, offset, exactCount: exact, ...(known ? { count: 'none' as const } : {}) };\n /* A table on a dashboard is asked with the dashboard's other sections,\n in one request (breakdownBatch.ts); a room's own list, and a page\n stepped to by key, are asked alone. */\n const answer: ResourceClientReply<'/api/run'> =\n embedded && !step ? await batchedRun<ResourceClientReply<'/api/run'>>(asked) : await api('/api/run', { ...asked, ...step?.body });\n const reply = (\n known && answer && typeof answer === 'object' && 'ms' in answer ? { ...answer, ...known } : answer\n ) as ResourceClientReply<'/api/run'>;\n if (!known) keepTotal(totalKey, reply);\n if (reply && typeof reply === 'object') askedFor.set(reply, { page, size });\n return reply;\n },\n staleTime: 0,\n gcTime: 0,\n /* The previous answer stays while the next is fetched, but only an\n answer about this table from this connection: rows of another table\n under this one's header would be a lie, however brief. */\n placeholderData: (previous, previousQuery) =>\n previousQuery?.queryKey[1] === source && previousQuery.queryKey[2] === entry.table ? previous : undefined,\n });\n const data = run.data;\n /* A list its reader is working in is held still when another person's change would redraw it, and says so in a pill\n (liveState.ts); a table on a dashboard or a short related list never is. */\n const held = useListHold(\n embedded || limit <= 5\n ? undefined\n : {\n table: entry.table,\n owns: (key) => key[0] === 'run' && key[1] === source && key[2] === entry.table && key[3] === entry.query,\n },\n );\n /* A list that edits in place waits for its cells' editor beside its rows (TableView.tsx). */\n const edits = Boolean(editable) && interactive && !embedded && !presentation;\n const editorHere = useArrived(GridCellEdit, edits);\n useEffect(() => {\n if (!data) return;\n if (chrome) {\n resetNested();\n showErrors(data.errors ?? []);\n setExplain('explain' in data ? data.explain : undefined);\n }\n if (!('ms' in data)) return;\n /* Recorded here rather than at submit: this is the point where the query\n is known to have compiled and run. Only queries a person typed. */\n if (chrome) recordQuery(entry.query);\n onResult?.(data);\n }, [data]); // eslint-disable-line react-hooks/exhaustive-deps\n\n /* A signed-out visitor asking past what the App opens to the public is asked to sign in (401), whether the table\n is a member's or no table at all: offered in place. */\n if (run.isError && (run.error as { code?: string }).code === 'members_only' && !chrome) return <NotYours thing={thingOf(entry, table)} />;\n /* An App's list that could not be read says so as every place does (Notes.tsx): the warn mark, the sentence and Try\n again on the list's edge. A bare grey line was a dead end only a reload got out of. The Workbench keeps its note\n under the query bar it can fix the question in. */\n if (run.isError)\n return chrome ? (\n <p className=\"note\">{inCaptions(run.error, table)}</p>\n ) : (\n <div className=\"list-problem\">\n <Problem text={inCaptions(run.error, table)} />\n </div>\n );\n /* Shaped like the grid that is about to replace it, and only if the query\n takes long enough to be worth acknowledging. */\n if (!data || (edits && !editorHere))\n return (\n <>\n {inCrumbs && exportOn && !presentation && <ExportHold />}\n <Delayed>\n <div className=\"host-contents\">\n <GridSkeleton columns={Math.max((table?.columns.length ?? 5) - (hide?.length ?? 0), 1)} rows={limit} />\n </div>\n </Delayed>\n </>\n );\n /* An App's list over a table the role cannot read is answered \"No table called ...\" (the catalog it sees leaves the table out):\n there is no query bar to fix, only a list that is not this reader's. */\n if (!('ms' in data))\n return !chrome && !table ? <NotYours thing={thingOf(entry, table)} /> : <p className=\"note\">{say('fixTheQueryAbove')}</p>;\n /* Not over a question that failed: its error says why there are no rows. */\n if (empty && !run.isPlaceholderData && data.rows.length === 0 && page === 0 && !data.errors?.length) return <>{empty}</>;\n return (\n <>\n {held.held ? <LivePill held={held.held} show={held.show} /> : null}\n <TableView\n entry={entry}\n data={data}\n chrome={chrome}\n interactive={interactive}\n hide={hide}\n labels={labels}\n referenceLabels={referenceLabels}\n totals={totals}\n density={density}\n rowActions={rowActions}\n editable={editable}\n inCrumbs={inCrumbs}\n sizing={sizing}\n export={exportOn}\n summaries={summaries}\n embedded={embedded}\n presentation={presentation}\n present={present}\n actions={actions}\n listLabel={listLabel}\n order={order}\n recordNavigation={recordNavigation}\n at={askedFor.get(data) ?? { page, size }}\n busy={run.isPlaceholderData}\n />\n </>\n );\n}\n\n/** The table's definition: the statement the database keeps, or one rebuilt from its catalog. */\nfunction DdlPane({ table }: { table: string }) {\n const ddl = useQuery<{ sql: string; exact: boolean }>({\n queryKey: ['ddl', connection(), table],\n queryFn: () => api(`/api/ddl?table=${encodeURIComponent(table)}`),\n });\n if (ddl.isError) return <p className=\"note\">{(ddl.error as Error).message}</p>;\n if (!ddl.data)\n return (\n <Delayed>\n <div className=\"host-contents\">\n <GridSkeleton columns={2} rows={6} />\n </div>\n </Delayed>\n );\n return (\n <>\n <p className=\"ddl-note\">\n <strong>{ddl.data.exact ? say('storedDefinition') : 'Reconstructed. '}</strong>\n {ddl.data.exact ? say('thisIsTheStatement') : say('rebuiltFromTheCatalog')}\n </p>\n <pre className=\"ddl\">{ddl.data.sql}</pre>\n </>\n );\n}\n","/** What Funnel says, in the dashboards 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 summary: '{count} stages from {first} to {last}',\n ofBasis: '{share} of {basis}',\n dropped: '−{figure}',\n droppedTitle: '{figure} reached {basis} and stopped before {stage}',\n optional: 'Optional',\n openReached: 'Open the {table} that reached {stage}',\n openDropped: 'Open the {table} that stopped before {stage}',\n});\n","/**\n * A funnel section (`funnel()`): the rows of one table that reach each of its stages, in order. Every stage is a bar\n * against the first stage's length, its count, and its share of the stage it follows (\"62% of Qualified\") with the rows\n * it lost beside it (\"−12\"). An optional stage is a side road: marked, and a share of the last stage that is required.\n *\n * Presentational: the counts come from one statement (shared/funnel.ts, funnelText), so a later stage can never be\n * longer than the one before it. The stages' names are known before the counts arrive, so the list holds its height\n * while it loads and nothing moves when the figures land (docs/design.md, layout shift).\n */\nimport type { ReactNode } from 'react';\nimport { say as sayCopy } from '../copy/dashboards/components/Funnel.js';\nimport { formatPercent } from '@mistriwork/kit/client/locale.js';\nimport type { ViewLink } from '@mistriwork/kit/client/components/viewLink.js';\nimport './Funnel.css';\n\n/** Where a figure goes: a link where the address is a list's, else a button that walks there. */\nexport interface FunnelDoor {\n link?: ViewLink;\n open?: () => void;\n}\n\nexport interface FunnelStep {\n title: string;\n optional?: boolean;\n /** Absent while the answer is on its way. */\n count?: number;\n /** The stage this one is a share of (the last required stage before it), absent on the first. */\n basis: number | null;\n reached?: FunnelDoor;\n dropped?: FunnelDoor;\n}\n\nfunction Door({ door, className, title, children }: { door?: FunnelDoor; className: string; title: string; children: ReactNode }) {\n if (door?.link)\n return (\n <a className={`${className} dash-funnel-door`} href={door.link.href} title={title} onClick={door.link.onClick}>\n {children}\n </a>\n );\n if (door?.open)\n return (\n <button type=\"button\" className={`${className} dash-funnel-door`} title={title} onClick={door.open}>\n {children}\n </button>\n );\n return <div className={className}>{children}</div>;\n}\n\nexport function Funnel({\n steps,\n say,\n table,\n label,\n}: {\n steps: FunnelStep[];\n /** How a count is said (the section's figure rule). */\n say: (value: unknown) => string;\n table: string;\n label?: string;\n}) {\n const ready = steps.every((step) => step.count !== undefined);\n const first = steps[0]?.count || Math.max(0, ...steps.map((step) => step.count ?? 0)) || 1;\n return (\n <div className=\"dash-funnel-host\">\n <ol\n className=\"dash-funnel\"\n aria-busy={!ready || undefined}\n aria-label={\n label ?? sayCopy('summary', { count: steps.length, first: steps[0]?.title ?? '', last: steps[steps.length - 1]?.title ?? '' })\n }\n >\n {steps.map((step, i) => {\n const basis = step.basis === null ? undefined : steps[step.basis];\n const share = basis?.count ? (step.count ?? 0) / basis.count : undefined;\n const lost =\n basis && step.count !== undefined && basis.count !== undefined && !step.optional ? basis.count - step.count : undefined;\n const width = step.count === undefined ? 0 : Math.max(2, Math.min(100, (step.count / first) * 100));\n return (\n <li key={i} className={`dash-funnel-step${step.optional ? ' is-optional' : ''}`}>\n <Door door={step.reached} className=\"dash-funnel-main\" title={sayCopy('openReached', { table, stage: step.title })}>\n <span className=\"dash-funnel-name\">\n {step.title}\n {step.optional && <span className=\"dash-funnel-tag\">{sayCopy('optional')}</span>}\n </span>\n <span className=\"dash-funnel-track\" aria-hidden=\"true\">\n <span className=\"dash-funnel-fill\" style={{ width: `${width}%` }} />\n </span>\n <span className=\"dash-funnel-value\">{step.count === undefined ? ' ' : say(step.count)}</span>\n <span className=\"dash-funnel-share\">\n {basis && share !== undefined && step.count !== undefined\n ? sayCopy('ofBasis', { share: formatPercent(share * 100, { maximumFractionDigits: 0 }), basis: basis.title })\n : ' '}\n </span>\n </Door>\n <Door\n door={lost ? step.dropped : undefined}\n className=\"dash-funnel-drop\"\n title={sayCopy('openDropped', { table, stage: step.title })}\n >\n {lost ? (\n <span title={basis ? sayCopy('droppedTitle', { figure: say(lost), basis: basis.title, stage: step.title }) : undefined}>\n {sayCopy('dropped', { figure: say(lost) })}\n </span>\n ) : (\n ' '\n )}\n </Door>\n </li>\n );\n })}\n </ol>\n </div>\n );\n}\n","/**\n * A dashboard's `areas`: sections placed in named areas of a grid of equal columns.\n *\n * One reading on both sides — the parser that refuses a template (appViews.ts), the lint that judges an area's\n * width (designLint.ts) and the client that draws it (components/Dashboard.tsx) — so a template means the same\n * thing wherever it is read. Pure data in, data out.\n */\nimport { nearest } from './suggest.js';\n\n/** An area's name: a lowercase word that is also a CSS identifier, since the client names the grid area with it. */\nconst AREA_NAME = /^[a-z][a-z0-9-]{0,23}$/;\n/** Words CSS reads before an area name: `grid-area: span` or `auto` is not a name. */\nconst CSS_WORDS = new Set(['auto', 'span', 'initial', 'inherit', 'unset', 'revert', 'default']);\nconst LAYOUT_MAX_ROWS = 8;\nconst LAYOUT_MAX_COLUMNS = 4;\n/** The cell that holds no area. */\nconst EMPTY_CELL = '.';\n\n/** A template as cells: `grid[row][column]` is an area's name or `.`. */\nexport type LayoutGrid = string[][];\n\n/** Whether a word may name an area. */\nexport const isAreaName = (word: string): boolean => AREA_NAME.test(word) && !CSS_WORDS.has(word);\n\n/** The rows of a template as cells. Ragged rows stay ragged: `layoutProblems` is what says so. */\nexport function layoutGrid(layout: readonly string[]): LayoutGrid {\n return layout.map((row) => row.trim().split(/\\s+/).filter(Boolean));\n}\n\n/** The areas a template names, in reading order: row by row, each at its first cell. */\nexport function layoutAreas(grid: LayoutGrid): string[] {\n const seen: string[] = [];\n for (const row of grid) for (const cell of row) if (cell !== EMPTY_CELL && !seen.includes(cell)) seen.push(cell);\n return seen;\n}\n\n/** The cells an area covers, 0-based, in reading order. */\nfunction cellsOf(grid: LayoutGrid, name: string): Array<{ row: number; column: number }> {\n const cells: Array<{ row: number; column: number }> = [];\n grid.forEach((row, r) => row.forEach((cell, c) => cell === name && cells.push({ row: r, column: c })));\n return cells;\n}\n\n/** An area's box: where it starts, and how many rows and columns it spans. Absent when the template does not name it. */\nexport function areaBox(grid: LayoutGrid, name: string): { row: number; column: number; rows: number; columns: number } | undefined {\n const cells = cellsOf(grid, name);\n if (!cells.length) return undefined;\n const rows = cells.map((cell) => cell.row);\n const columns = cells.map((cell) => cell.column);\n const row = Math.min(...rows);\n const column = Math.min(...columns);\n return { row, column, rows: Math.max(...rows) - row + 1, columns: Math.max(...columns) - column + 1 };\n}\n\nconst place = (cell: { row: number; column: number }): string => `row ${cell.row + 1} column ${cell.column + 1}`;\n\n/** \"a, b and c\". */\nconst said = (words: string[]): string =>\n words.length < 2 ? (words[0] ?? '') : `${words.slice(0, -1).join(', ')} and ${words[words.length - 1]}`;\n\n/** Whether an area's cells fill their box exactly. */\nfunction isRectangle(grid: LayoutGrid, name: string): boolean {\n const box = areaBox(grid, name);\n return !box || cellsOf(grid, name).length === box.rows * box.columns;\n}\n\n/**\n * Everything wrong with a template, in words, one pass: a template is judged whole so one run names every refusal.\n * `at` is the dashboard, as the other refusals name it.\n */\nexport function layoutProblems(layout: unknown, at: string): string[] {\n const here = `${at}, \"areas\"`;\n if (!Array.isArray(layout) || !layout.length || layout.some((row) => typeof row !== 'string')) {\n return [`${here} is not a list of rows, each a string of area names: ['kpis kpis', 'trend side'].`];\n }\n const problems: string[] = [];\n if (layout.length > LAYOUT_MAX_ROWS) problems.push(`${here} has ${layout.length} rows. At most ${LAYOUT_MAX_ROWS}.`);\n const grid = layoutGrid(layout as string[]);\n const widest = Math.max(...grid.map((row) => row.length));\n if (grid.some((row) => !row.length)) problems.push(`${here} has an empty row. Write . for a cell with nothing in it.`);\n if (widest > LAYOUT_MAX_COLUMNS)\n problems.push(\n `${here} has ${widest} columns in a row. At most ${LAYOUT_MAX_COLUMNS}: wider than that, a column is too narrow to read.`,\n );\n const counts = new Set(grid.filter((row) => row.length).map((row) => row.length));\n if (counts.size > 1) {\n problems.push(\n `${here} has rows of different lengths (${grid.map((row, i) => `row ${i + 1} has ${row.length}`).join(', ')}). Every row has the same number of cells; write . for one with nothing in it.`,\n );\n }\n for (const word of new Set(grid.flat())) {\n if (word !== EMPTY_CELL && !isAreaName(word)) {\n problems.push(\n `${here} has \"${word}\", which is not an area name. An area is a lowercase word (letters, digits and hyphens, at most 24, starting with a letter, and not ${[...CSS_WORDS].join(' or ')}); . is a cell with nothing in it.`,\n );\n }\n }\n if (problems.length) return problems;\n for (const name of layoutAreas(grid)) {\n if (isRectangle(grid, name)) continue;\n problems.push(\n `${here}: \"${name}\" is not a rectangle: it covers ${said(cellsOf(grid, name).map(place))}. An area is one block of cells; give each separate block its own name.`,\n );\n }\n return problems;\n}\n\n/**\n * The areas a layout leaves for a reader when `hidden` ones have nothing to draw: a hidden area's cells go to its left\n * neighbour in that row (the right one when it is first), and a row left with no area in it is dropped. A neighbour that\n * would stop being a rectangle by it is not given the cells, which stand empty. Pure: a template in, a template out.\n */\nexport function reflowLayout(grid: LayoutGrid, hidden: ReadonlySet<string>): LayoutGrid {\n let next = grid.map((row) => [...row]);\n for (const name of layoutAreas(grid)) {\n if (!hidden.has(name)) continue;\n const trial = next.map((row) => [...row]);\n const touched = new Set<string>();\n next.forEach((row, r) => {\n const first = row.indexOf(name);\n if (first < 0) return;\n const last = row.lastIndexOf(name);\n const neighbour = first > 0 ? row[first - 1]! : (row[last + 1] ?? EMPTY_CELL);\n for (let c = first; c <= last; c++) trial[r]![c] = neighbour;\n touched.add(neighbour);\n });\n for (const other of touched) {\n if (other !== EMPTY_CELL && !isRectangle(trial, other)) {\n trial.forEach((row, r) =>\n row.forEach((cell, c) => {\n if (cell === other && next[r]![c] === name) row[c] = EMPTY_CELL;\n }),\n );\n }\n }\n next = trial;\n }\n return next.filter((row) => row.some((cell) => cell !== EMPTY_CELL));\n}\n\n/** The template as the strings a CSS `grid-template-areas` takes: one quoted row each. */\nexport const gridTemplateAreas = (grid: LayoutGrid): string => grid.map((row) => `\"${row.join(' ')}\"`).join(' ');\n\n/** An area that no section is placed in, or a section placed in none: the nearest name for a slip. */\nexport function nearestArea(name: string, areas: readonly string[]): string | undefined {\n return nearest(name, areas);\n}\n","/**\n * The time unit a chart cuts its dates into when its author did not fix one: `chart('Signups', 'account', 'auto\n * created_at', { over: 'created_at' })`.\n *\n * A fixed unit is right for one window and wrong for the next: `day` over 34 days with three days of data drew 34\n * bars, 31 of them empty, and `day` over a year draws 365. The right unit depends on the window the reader picks and\n * on how the data falls, so `auto` is decided where both are known, on the client, before the read. It is not a SQL\n * bucket: the server never sees the word (`withUnit` writes the unit in), and the grammar's `DATE_UNITS` is unchanged.\n *\n * Two rules choose the unit, both pure so a table of cases can hold them:\n * 1. The span picks a base unit: up to 45 days a day, up to 26 weeks a week, up to 36 months a month, past that a\n * quarter.\n * 2. Where the measure can be added up again (count, sum, min, max, avg as sum over count, and arithmetic of those),\n * the base answer is coarsened locally while fewer than a third of its buckets hold data, as long as at least four\n * buckets would remain. No second read. A median cannot be added up from its parts, so it follows the span only.\n */\nimport { dateWindow } from './queryDates.js';\n\nexport type AutoUnit = 'day' | 'week' | 'month' | 'quarter';\n\n/** Finest to coarsest: the order a sparse chart steps up through. */\nconst AUTO_UNITS: readonly AutoUnit[] = ['day', 'week', 'month', 'quarter'];\n\n/** A bucket needs a third of its periods to hold data before the chart is left at the unit the span chose. */\nconst DENSE = 1 / 3;\n/** Stepping up stops before the chart is left with fewer buckets than this. */\nconst FEWEST_BUCKETS = 4;\n\n/* ---------- the word in a `by` ---------- */\n\nconst AUTO_KEY = /^auto\\s+([\\w.$+]+)(\\s+as\\s+[\\w$]+)?$/i;\n\n/** The key of a `by` written `auto <column>`, wherever it stands in the list: its place and its column. */\nexport function autoKeyOf(by: string | undefined): { index: number; column: string } | null {\n const keys = (by ?? '').split(',');\n for (const [index, key] of keys.entries()) {\n const m = AUTO_KEY.exec(key.trim());\n if (m) return { index, column: m[1] };\n }\n return null;\n}\n\n/** The `by` with its `auto` key written as the unit the chart chose, which is the word the grammar reads. */\nexport function withUnit(by: string, unit: AutoUnit): string {\n const at = autoKeyOf(by);\n if (!at) return by;\n return by\n .split(',')\n .map((key, index) => (index === at.index ? key.trim().replace(/^auto/i, unit) : key.trim()))\n .join(', ');\n}\n\n/* ---------- the span ---------- */\n\nconst DAY = 86_400_000;\n\n/**\n * The days a section's query asks about on its `over` column — `created_at = last 90 days`, `this month` — or null\n * where it sets no window the date grammar can bound (the data's own extent is then the span).\n */\nexport function spanDaysOf(query: string | undefined, over: string | undefined, now: Date): number | null {\n const phrase = windowPhraseOf(query, over);\n const window = phrase ? dateWindow(phrase, now) : undefined;\n return window ? Math.max(1, Math.round((window.end.getTime() - window.start.getTime()) / DAY)) : null;\n}\n\n/** The phrase a query windows its `over` column by — `last 90 days` in `due_on = last 90 days` — or null. */\nexport function windowPhraseOf(query: string | undefined, over: string | undefined): string | null {\n if (!query || !over) return null;\n const escaped = over.replace(/[.$+]/g, '\\\\$&');\n const found = new RegExp(`(?:^|[\\\\s(])${escaped}\\\\s*=\\\\s*(.+?)(?=\\\\s+(?:and|or)\\\\b|\\\\)|$)`, 'i').exec(query);\n return found ? found[1].trim() : null;\n}\n\n/** The days between two dates the data holds, both ends counted. Null where either is not a date. */\nexport function spanDaysBetween(min: unknown, max: unknown): number | null {\n const from = dayNumber(String(min ?? '').slice(0, 10));\n const to = dayNumber(String(max ?? '').slice(0, 10));\n return from === null || to === null || to < from ? null : to - from + 1;\n}\n\n/** The unit a span of this many days is drawn in, before the data is looked at. */\nexport function unitForSpan(days: number): AutoUnit {\n if (days <= 45) return 'day';\n if (days <= 26 * 7) return 'week';\n if (days <= 36 * 30.4375) return 'month';\n return 'quarter';\n}\n\n/**\n * The unit the read asks the server for. Where the measure adds up again, a day or a week is read as days and\n * bucketed here: a week crosses a month's edge, so weeks read from the server could not be coarsened into months\n * without handing a whole week to one of them. Months and quarters nest, so those are read as they are drawn.\n */\nexport function readUnit(base: AutoUnit, addsUp: boolean): AutoUnit {\n return addsUp && (base === 'day' || base === 'week') ? 'day' : base;\n}\n\n/* ---------- periods, by their labels ---------- */\n\nconst pad = (n: number) => String(n).padStart(2, '0');\n\nfunction dayNumber(key: string): number | null {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(key);\n return m ? Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3])) / DAY : null;\n}\n\nconst dayKey = (n: number): string => {\n const d = new Date(n * DAY);\n return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`;\n};\n\n/** The label of the period a day, month or quarter label falls in, spelled as the server spells it. */\nexport function bucketKey(key: string, unit: AutoUnit, weekStart = 1): string {\n if (unit === 'day') return key;\n if (unit === 'week') {\n const n = dayNumber(key);\n if (n === null) return key;\n /* ISO weekday 1..7; a day is that many days past its week's first. */\n const weekday = ((new Date(n * DAY).getUTCDay() + 6) % 7) + 1;\n return dayKey(n - ((weekday - weekStart + 7) % 7));\n }\n const month = Number(key.slice(5, 7));\n if (unit === 'month') return key.slice(0, 7);\n return /Q[1-4]$/.test(key) ? key : `${key.slice(0, 4)}-Q${Math.ceil(month / 3)}`;\n}\n\nfunction nextKey(key: string, unit: AutoUnit): string {\n if (unit === 'day' || unit === 'week') return dayKey((dayNumber(key) ?? 0) + (unit === 'week' ? 7 : 1));\n if (unit === 'month') {\n const [y, m] = [Number(key.slice(0, 4)), Number(key.slice(5, 7))];\n return m === 12 ? `${y + 1}-01` : `${y}-${pad(m + 1)}`;\n }\n const [y, q] = [Number(key.slice(0, 4)), Number(key.slice(6))];\n return q === 4 ? `${y + 1}-Q1` : `${y}-Q${q + 1}`;\n}\n\nconst SPELLED: Record<AutoUnit, RegExp> = {\n day: /^\\d{4}-\\d{2}-\\d{2}$/,\n week: /^\\d{4}-\\d{2}-\\d{2}$/,\n month: /^\\d{4}-\\d{2}$/,\n quarter: /^\\d{4}-Q[1-4]$/,\n};\n\n/** The local calendar day of a date, as the server spells a day. */\nconst localDay = (d: Date): string => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\n\n/**\n * A trend's points over its window: the periods that held no rows put back as zero, from the window's first period\n * to today's, and the read periods added up into the unit the span is drawn in. A count of nothing is 0, and a line\n * drawn through only the days that had rows said a quiet week was a steady one; three busy days of a week drew no\n * line at all. Only a count or a sum adds up so: any other measure's points are drawn as read, and labels the read\n * unit does not spell are left as they came.\n */\nexport function trendPoints<R extends { key: unknown; value: unknown }>(\n rows: readonly R[],\n read: AutoUnit,\n unit: AutoUnit,\n measure: string | undefined,\n window: { start: Date; end: Date } | undefined,\n now: Date,\n): Array<{ key: unknown; value: unknown }> {\n if (!/^(count|sum\\s+[\\w.$+]+)(\\s+as\\s+[\\w$]+)?$/i.test((measure ?? 'count').trim())) return [...rows];\n const keys = rows.map((row) => String(row.key ?? ''));\n if (keys.some((key) => !SPELLED[read].test(key))) return [...rows];\n const ends = window ? [window.start, new Date(Math.min(window.end.getTime() - 1, now.getTime()))] : [];\n const sorted = [...keys, ...ends.map((d) => bucketKey(localDay(d), read))].sort();\n if (!sorted.length) return [...rows];\n const held = new Map(rows.map((row) => [String(row.key), Number(row.value) || 0]));\n const into = new Map<string, number>();\n for (let key = sorted[0], n = 0; key <= sorted[sorted.length - 1] && n < 5000; key = nextKey(key, read), n++) {\n const label = bucketKey(key, unit);\n into.set(label, (into.get(label) ?? 0) + (held.get(key) ?? 0));\n }\n return [...into].map(([key, value]) => ({ key, value }));\n}\n\n/** How many periods of the unit run from the first label to the last, both ends counted. */\nfunction periodsBetween(first: string, last: string, unit: AutoUnit): number {\n let count = 1;\n for (let key = first; key < last && count < 5000; key = nextKey(key, unit)) count++;\n return count;\n}\n\n/**\n * The unit a chart is drawn in: the span's, stepped up while the data is sparse in it.\n *\n * `keys` are the labels of the buckets that hold data, as read (days, or months or quarters, per `readUnit`).\n * `addsUp` is whether the measure can be re-aggregated; without it the span alone decides.\n */\nexport function chooseUnit({\n spanDays,\n base: given,\n keys,\n addsUp,\n weekStart = 1,\n}: {\n /** The span in days; or the `base` already chosen for it, where the caller has kept one. */\n spanDays?: number;\n base?: AutoUnit;\n keys: readonly string[];\n addsUp: boolean;\n weekStart?: number;\n}): { base: AutoUnit; unit: AutoUnit } {\n const base = given ?? unitForSpan(spanDays ?? 0);\n if (!addsUp || !keys.length || base === 'quarter') return { base, unit: base };\n const at = (unit: AutoUnit) => {\n const labels = [...new Set(keys.map((k) => bucketKey(k, unit, weekStart)))].sort();\n return { filled: labels.length, total: periodsBetween(labels[0], labels[labels.length - 1], unit) };\n };\n let unit: AutoUnit = base;\n for (;;) {\n const here = at(unit);\n if (here.filled / here.total >= DENSE) break;\n const next: AutoUnit | undefined = AUTO_UNITS[AUTO_UNITS.indexOf(unit) + 1];\n if (!next || at(next).total < FEWEST_BUCKETS) break;\n unit = next;\n }\n return { base, unit };\n}\n\n/* ---------- the measure, taken apart so it can be added up again ---------- */\n\ntype Combine = 'add' | 'min' | 'max';\n\nexport interface MeasurePlan {\n /** What to read per bucket, in the grammar's words: each aggregate the measure is made of, once. */\n reads: string[];\n /** How the same aggregate of two buckets becomes one of their union. */\n combine: Combine[];\n /** The measure's value from its aggregates, null where it has none (a ratio over nothing). */\n value(terms: readonly (number | null)[]): number | null;\n}\n\nconst TERM = /^(count|sum|avg|min|max)\\s*([\\w.$+]+)?$/i;\n\n/**\n * A measure as the aggregates it is made of, or null where it cannot be added up again: a median, a distinct\n * count, a `when` count, or words this does not read. `avg x` is `sum x` over `count x`, which can.\n */\nexport function planMeasure(measure: string | undefined): MeasurePlan | null {\n const text = (measure ?? 'count').replace(/\\s+as\\s+[\\w$]+\\s*$/i, '').trim();\n if (/\\b(distinct|when|median)\\b|[,[\\]()]/i.test(text)) return null;\n const parts = text.split(/\\s+([+\\-*/])\\s+/);\n const reads: string[] = [];\n const combine: Combine[] = [];\n const read = (aggregate: string, how: Combine): number => {\n const at = reads.indexOf(aggregate);\n if (at >= 0) return at;\n reads.push(aggregate);\n combine.push(how);\n return reads.length - 1;\n };\n type Operand = { number: number } | { term: number } | { ratio: [number, number] };\n const operands: Operand[] = [];\n for (let i = 0; i < parts.length; i += 2) {\n const part = parts[i].trim();\n if (/^\\d+(?:\\.\\d+)?$/.test(part)) {\n operands.push({ number: Number(part) });\n continue;\n }\n const m = TERM.exec(part);\n if (!m) return null;\n const fn = m[1].toLowerCase();\n const column = m[2];\n if (fn !== 'count' && !column) return null;\n if (fn === 'avg') operands.push({ ratio: [read(`sum ${column}`, 'add'), read(`count ${column}`, 'add')] });\n else operands.push({ term: read(column ? `${fn} ${column}` : fn, fn === 'min' ? 'min' : fn === 'max' ? 'max' : 'add') });\n }\n const ops = parts.filter((_, i) => i % 2 === 1);\n const value = (terms: readonly (number | null)[]): number | null => {\n const values = operands.map((o): number | null => {\n if ('number' in o) return o.number;\n if ('term' in o) return terms[o.term];\n const [sum, count] = [terms[o.ratio[0]], terms[o.ratio[1]]];\n return sum === null || !count ? null : sum / count;\n });\n /* SQL's precedence: `*` and `/` bind first; a division by zero is null, as the server's is. */\n const sums: Array<number | null> = [values[0]];\n const signs: string[] = [];\n for (const [i, op] of ops.entries()) {\n const right = values[i + 1];\n const left = sums[sums.length - 1];\n if (op === '*' || op === '/') {\n sums[sums.length - 1] =\n left === null || right === null || (op === '/' && right === 0) ? null : op === '*' ? left * right : left / right;\n } else {\n sums.push(right);\n signs.push(op);\n }\n }\n return sums.reduce<number | null>(\n (acc, v, i) => {\n if (i === 0) return v;\n return acc === null || v === null ? null : signs[i - 1] === '+' ? acc + v : acc - v;\n },\n sums[0] === undefined ? null : sums[0],\n );\n };\n return { reads, combine, value };\n}\n\n/** One bucket as read: its label, the second key's value where the chart has one, and one number per aggregate the plan reads. */\ninterface ReadBucket {\n key: string;\n series?: string;\n terms: readonly (number | null)[];\n}\n\n/** The read buckets cut into the chosen unit, each aggregate added up (or min'd, or max'd) across the ones it takes in. */\nexport function coarsen(\n buckets: readonly ReadBucket[],\n plan: MeasurePlan,\n unit: AutoUnit,\n weekStart = 1,\n): Array<{ key: string; series?: string; value: number }> {\n /* A chart over a second key (a line or a stack per value) is coarsened per value: a cross is the period and the series. */\n const into = new Map<string, Array<number | null>>();\n const SPLIT = '\\u0000';\n for (const bucket of buckets) {\n const key = `${bucketKey(bucket.key, unit, weekStart)}${bucket.series === undefined ? '' : SPLIT + bucket.series}`;\n const held = into.get(key);\n if (!held) {\n into.set(key, [...bucket.terms]);\n continue;\n }\n plan.combine.forEach((how, i) => {\n const [a, b] = [held[i], bucket.terms[i]];\n held[i] = a === null ? b : b === null ? a : how === 'add' ? a + b : how === 'min' ? Math.min(a, b) : Math.max(a, b);\n });\n }\n return [...into.entries()]\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .flatMap(([joined, terms]) => {\n const value = plan.value(terms);\n const [key, series] = joined.split(SPLIT);\n return value === null || !Number.isFinite(value) ? [] : [{ key, ...(series === undefined ? {} : { series }), value }];\n });\n}\n\n/* ---------- what a section asks, for the check ---------- */\n\n/** The most days a window may span before a fixed `day` chart over it is worth a word. */\nexport const DAY_BARS_ADVISED = 90;\n\n/**\n * The days a dashboard window phrase covers, as it would be said (\"last 12 months\" is 365): the nominal length of a\n * `last N unit`, else the dates the phrase resolves to, or null where it is not one the date grammar bounds. (A\n * resolved `last N` runs to tomorrow, a day more than it is called, which a count of bars should not repeat.)\n */\nexport function windowDays(phrase: string, now: Date): number | null {\n const last = /^last\\s+(\\d+)\\s+(day|week|month|year)s?$/i.exec(phrase.trim());\n if (last) return Math.round(Number(last[1]) * { day: 1, week: 7, month: 365 / 12, year: 365 }[last[2].toLowerCase() as 'day']);\n const window = dateWindow(phrase, now);\n return window ? Math.round((window.end.getTime() - window.start.getTime()) / DAY) : null;\n}\n\n/** Whether a chart's `by` cuts days: `day created_at`, in any position. */\nexport const cutsDays = (by: string | undefined): boolean => (by ?? '').split(',').some((key) => /^day\\s+[\\w.$+]+/i.test(key.trim()));\n","/**\n * A metric's trend, in the words it is asked: the window it is drawn over and the read that draws it. Apart from\n * dashboardAsks.ts because it reads the window's span through autoBucket.ts, which only a drawn dashboard needs:\n * held there, every App's first page carried the bucketing a chart and a trend use (scripts/bundle-budget.mjs).\n * Asked by the client's metric (client/components/Dashboard.tsx) and by the server for a first page\n * (server/http/firstPaintRooms.ts), in the same words.\n */\nimport { andQuery } from './query.js';\nimport { type AutoUnit, unitForSpan, windowDays, windowPhraseOf } from './autoBucket.js';\nimport type { AskedSection } from './dashboardAsks.js';\n\n/**\n * The window a metric's trend is drawn over — the reader's, else the author's own on `over` — and the units it is\n * read and drawn in: the span's unit (autoBucket.ts), read as days under a week so a week is added up on the client\n * (`trendPoints`) and never handed whole to one month. Null where the metric has no window the date grammar bounds.\n */\nexport function sparkWindow(\n section: Pick<AskedSection, 'query' | 'over' | 'windowPhrase'>,\n now = new Date(),\n): { phrase: string; read: AutoUnit; unit: AutoUnit } | null {\n if (!section.over) return null;\n const phrase = section.windowPhrase ?? windowPhraseOf(section.query, section.over);\n const days = phrase ? windowDays(phrase, now) : null;\n if (!phrase || !days) return null;\n /* \"today\" is one day: a trend of fewer than four points is no line, and no slot is held for it. */\n if (days < 4) return null;\n const unit = unitForSpan(days);\n return { phrase, unit, read: unit === 'week' ? 'day' : unit };\n}\n\n/** The most periods a windowed trend reads: 182 days, or months and quarters past them, with room to spare. */\nconst TREND_PERIODS = 400;\n\n/**\n * A metric's trend. Over a window, the metric over that window in the span's unit, so \"last 30 days\" draws thirty\n * days and \"last 12 months\" twelve months: every windowed metric has one, beside its change, unless its author said\n * `spark: false`. With no window, the author's `spark: true` is the measure's last twelve months, bucketed monthly by\n * the section's own clock (`over`), composed with whatever the card is narrowed to by other than time. None without a\n * clock.\n */\nexport function sparkText(\n section: Pick<AskedSection, 'table' | 'query' | 'windowBase' | 'windowPhrase' | 'measure' | 'over' | 'spark'>,\n): string | null {\n /* An authored false is heard over a window too: a card can be a figure alone, which it once could not say. */\n if (!section.over || section.spark === false) return null;\n const window = sparkWindow(section);\n if (window)\n return [section.table, section.query, `${section.measure ?? 'count'} by ${window.read} ${section.over}`, `limit ${TREND_PERIODS}`]\n .filter(Boolean)\n .join(' ');\n if (!section.spark) return null;\n const trendBase = section.windowBase ?? section.query;\n return `${section.table} ${andQuery(trendBase, `${section.over} = last 12 months`)} ${section.measure ?? 'count'} by month ${section.over}`;\n}\n","/**\n * Which weekday a week starts on in a reader's locale, read once and remembered. Shared by the server's date\n * buckets and the client's charts, so a `week` means the same seven days on both sides.\n */\nconst weekStarts = new Map<string, number>();\n/**\n * The day a week starts on where an App is read: its `ui.locale`'s own first\n * day (Sunday in the US, Monday in most of the world), and Monday — ISO's —\n * where the App names no locale. Said as an ISO weekday, 1 (Monday) to 7\n * (Sunday), the number a `week` bucket's SQL takes (filter.ts).\n */\nexport function localeWeekStart(locale: string | undefined): number {\n if (!locale) return 1;\n /* Asked for every date a request reads, of the same few locales; building\n an Intl.Locale each time was measurable on a busy server. Bounded,\n because a locale can come from a person's own setting. */\n const known = weekStarts.get(locale);\n if (known !== undefined) return known;\n if (weekStarts.size >= 64) weekStarts.clear();\n const first = readWeekStart(locale);\n weekStarts.set(locale, first);\n return first;\n}\n\nfunction readWeekStart(locale: string): number {\n try {\n const tag = new Intl.Locale(locale) as Intl.Locale & {\n getWeekInfo?: () => { firstDay: number };\n weekInfo?: { firstDay: number };\n };\n const first = (tag.getWeekInfo?.() ?? tag.weekInfo)?.firstDay;\n return typeof first === 'number' && Number.isInteger(first) && first >= 1 && first <= 7 ? first : 1;\n } catch {\n return 1;\n }\n}\n","/**\n * A chart whose `by` says `auto` (shared/autoBucket.ts): the unit it is cut into, decided before the read from the\n * window and, where the window does not say, the data's own extent; then coarsened locally while the answer is sparse.\n *\n * The unit is decided once per window. A refresh that finds the data a little denser or sparser keeps the unit the\n * reader is looking at, because a chart that changes its bars under a pointer, on a timer, is the layout shift this\n * product refuses; a reader's own pick of a window chooses again.\n */\nimport { useRef } from 'react';\nimport {\n autoKeyOf,\n chooseUnit,\n coarsen,\n planMeasure,\n readUnit,\n spanDaysBetween,\n spanDaysOf,\n unitForSpan,\n withUnit,\n type AutoUnit,\n type MeasurePlan,\n} from '@mistriwork/engine/shared/autoBucket.js';\nimport { localeWeekStart } from '@mistriwork/engine/shared/weekStart.js';\nimport { shell } from '../shellMode.js';\nimport type { Section } from './dashboardModel.js';\n\ninterface Answer {\n columns?: string[];\n rows?: Array<Record<string, unknown>>;\n names?: Record<string, Record<string, string>>;\n}\n\n/** What a read gives back that this needs: the answer, and whether it is the last window's held while the next loads. */\nexport interface Read {\n data?: Answer;\n isPlaceholderData?: boolean;\n}\n\ninterface AutoDrawn {\n answer: Answer | undefined;\n /** The unit the bars or points are in, said under the title. Absent until there is one to say. */\n unit: AutoUnit | undefined;\n /** A line with too few filled buckets to draw a line through: its points stand alone. */\n dots: boolean;\n}\n\ninterface AutoChart {\n /** The section to ask, in the unit chosen; null while the span is still being read from the data. */\n ask: Section | null;\n /** The read's answer as it is drawn: coarsened where it adds up, and the unit it came to. */\n draw(read: Read): AutoDrawn;\n}\n\n/** The fewest filled buckets a line is drawn through: two points are a segment, and a segment says nothing of a trend. */\nconst LINE_FROM = 3;\n\nconst numberOrNull = (value: unknown): number | null => {\n const n = Number(value);\n return value === null || value === undefined || value === '' || !Number.isFinite(n) ? null : n;\n};\n\n/**\n * The plan for a section, or null for a chart that does not say `auto`. Called every render of every chart, in the\n * same order, so the hooks it makes (the span's read, the kept unit) are the chart's own.\n *\n * `read` asks the server in the dashboard's way (its cache, its refresh), so this module holds no fetching of its own.\n */\nexport function useAutoChart(section: Section, read: (text: string | null) => Read): AutoChart | null {\n const auto = autoKeyOf(section.by);\n const plan = planMeasure(section.measure);\n /* A measure adds up again when the date is the first key: the answer is then a row per period (and per value of a\n second key, which the period is coarsened within). A date second has its rows grouped by another key first. */\n const keys = (section.by ?? '').split(',').length;\n const addsUp = plan !== null && auto?.index === 0 && keys <= 2;\n const weekStart = localeWeekStart((shell().app() as { ui?: { locale?: string } } | null)?.ui?.locale);\n\n /* The window the reader picked rides on `over`; a chart with none of its own is held to the window its query\n writes on the date it cuts. */\n const windowDays = auto ? spanDaysOf(section.query, section.over ?? auto.column, new Date()) : null;\n /* What a window is, and so when the unit is chosen again: the table and column, and the window's own phrase. A\n pick of another filter changes the section's query and not this. */\n const epoch = auto ? `${section.table}|${section.over ?? ''}|${auto.column}|${windowDays ?? 'data'}` : '';\n const kept = useRef<{ epoch: string; base?: AutoUnit; unit?: AutoUnit; drawn?: AutoDrawn }>({ epoch: '' });\n if (kept.current.epoch !== epoch) kept.current = { epoch, drawn: kept.current.drawn };\n\n /* Under no window the span is the data's own: its first and last date, as the one-row answer of two measures, the\n grammar's own `min` and `max` (a read with no `by` is one group). */\n const needsExtent = Boolean(auto) && windowDays === null && !kept.current.base;\n const extent = read(\n needsExtent && auto ? [section.table, section.query, `min ${auto.column}, max ${auto.column}`].filter(Boolean).join(' ') : null,\n );\n\n if (!auto) return null;\n\n let base = kept.current.base;\n if (!base && windowDays !== null) base = unitForSpan(windowDays);\n if (!base && extent.data && !extent.isPlaceholderData) {\n const [from, to] = extent.data.columns ?? [];\n const row = extent.data.rows?.[0];\n const days = row ? spanDaysBetween(row[from], row[to]) : null;\n /* A table with no dates has nothing to draw: the finest unit is as good as any. */\n base = days === null ? 'day' : unitForSpan(days);\n }\n if (base) kept.current.base = base;\n if (!base) {\n return {\n ask: null,\n draw: () => kept.current.drawn ?? { answer: undefined, unit: undefined, dots: false },\n };\n }\n\n const reading = readUnit(base, addsUp);\n const ask: Section = {\n ...section,\n by: withUnit(section.by ?? '', reading),\n ...(addsUp && plan ? { measure: plan.reads.join(', ') } : {}),\n };\n /* One line, of few filled buckets; several lines are drawn as they are. */\n const dotted = (filled: number) => (!section.shape || section.shape === 'line') && keys === 1 && filled > 0 && filled < LINE_FROM;\n\n const draw = ({ data, isPlaceholderData }: Read): AutoDrawn => {\n /* A held answer is the last window's, in the last window's unit: drawn as it was, and never the data the unit\n is chosen from. */\n if (!data || isPlaceholderData) return kept.current.drawn ?? { answer: undefined, unit: undefined, dots: false };\n const columns = data.columns ?? [];\n let drawn: AutoDrawn;\n if (addsUp && plan && columns.length === keys + plan.reads.length && !(data.rows ?? []).some((row) => row[columns[0]] == null)) {\n const buckets = (data.rows ?? []).map((row) => ({\n key: String(row[columns[0]]),\n ...(keys === 2 ? { series: String(row[columns[1]]) } : {}),\n terms: plan.reads.map((_, i) => numberOrNull(row[columns[keys + i]])),\n }));\n const unit = kept.current.unit ?? chooseUnit({ base, keys: buckets.map((b) => b.key), addsUp: true, weekStart }).unit;\n kept.current.unit = unit;\n const rows = coarsen(buckets, plan as MeasurePlan, unit, weekStart);\n drawn = {\n answer: {\n columns: [...columns.slice(0, keys), 'value'],\n rows: rows.map((r) => ({ [columns[0]]: r.key, ...(keys === 2 ? { [columns[1]]: r.series } : {}), value: r.value })),\n },\n unit,\n dots: dotted(rows.length),\n };\n } else {\n kept.current.unit = base;\n drawn = { answer: data, unit: base, dots: dotted((data.rows ?? []).length) };\n }\n kept.current.drawn = drawn;\n return drawn;\n };\n return { ask, draw };\n}\n","/** What FirstRun says, in the shell 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 getStarted: 'Get started',\n done: '(done)',\n open: 'Open',\n});\n","/**\n * A new App's first steps. A home over empty tables draws charts of nothing\n * and counts of zero, which say the App is broken when it is only new; this\n * says what to do instead — add the first record here, then there — each\n * step a link to its list with the New form open.\n *\n * A step is done when its table has a row the reader can see, read as one\n * bounded row per step. `useFirstRun` says where the dashboard stands:\n * `fresh` (no step done) draws the welcome alone, `started` draws it above\n * the dashboard, `done` (or no steps this reader can take) draws nothing.\n */\nimport { useQueries } from '@tanstack/react-query';\nimport { findTable, state } from '@mistriwork/kit/client/core.js';\nimport { batchedRun } from '@mistriwork/kit/client/breakdownBatch.js';\nimport { canInsert } from '@mistriwork/kit/client/insert.js';\nimport type { TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { buttonClass } from '@mistriwork/ui/Button.js';\nimport { Icon } from '@mistriwork/kit/client/components/Icon.js';\nimport { viewLink } from '@mistriwork/kit/client/components/viewLink.js';\nimport type { Section } from '@mistriwork/kit/client/components/dashboardModel.js';\nimport './FirstRun.css';\nimport { say } from '../copy/shell/components/FirstRun.js';\n\ntype FirstRunStage = 'unknown' | 'fresh' | 'started' | 'done';\n\n/** Which steps are done, and so what the dashboard draws. */\nexport function useFirstRun(section: Section | undefined): { stage: FirstRunStage; done: boolean[] } {\n const steps = section?.steps ?? [];\n const reads = useQueries({\n queries: steps.map((step) => ({\n queryKey: ['first-run', state.activeConnection ?? '', step.table],\n queryFn: async () => {\n // Asked with the dashboard's other reads, in one request, and not counted (breakdownBatch.ts).\n const data = await batchedRun<{ rows?: unknown[] }>({ q: step.table ?? '', limit: 1, offset: 0, count: 'none' });\n return Boolean(data.rows?.length);\n },\n // Read again whenever the home is drawn: the reader has just come back from adding the first record.\n staleTime: 0,\n })),\n });\n if (!section || !steps.length) return { stage: 'done', done: [] };\n /* A step that cannot be read is not a reason to hide the dashboard: it counts as done. */\n const done = reads.map((read) => read.isError || read.data === true);\n if (reads.some((read) => read.isPending)) return { stage: 'unknown', done };\n return { stage: done.every(Boolean) ? 'done' : done.some(Boolean) ? 'started' : 'fresh', done };\n}\n\nexport function FirstRun({ section, done, fresh }: { section: Section; done: boolean[]; fresh: boolean }) {\n const steps = section.steps ?? [];\n const next = done.indexOf(false);\n return (\n <section className={`page-section width-full dash-first-run${fresh ? ' is-fresh' : ''}`} aria-labelledby=\"first-run-title\">\n <h2 className=\"page-section-title\" id=\"first-run-title\">\n {section.title ?? say('getStarted')}\n </h2>\n {section.text && <p className=\"first-run-text\">{section.text}</p>}\n <ol className=\"first-run-steps\">\n {steps.map((step, i) => {\n const table = findTable(step.table ?? '') as TableMeta | undefined;\n /* The New form where the reader may add; the list itself where they may only read. */\n const adding = !done[i] && Boolean(table && canInsert(table, true));\n const link = viewLink(step.view, 'push', adding);\n return (\n <li key={step.view} className={`first-run-step${done[i] ? ' is-done' : ''}`}>\n <span className=\"first-run-mark\" aria-hidden=\"true\">\n {done[i] ? <Icon name=\"check-circle\" size={20} weight=\"bold\" /> : <span className=\"first-run-number\">{i + 1}</span>}\n </span>\n <span className=\"first-run-words\">\n <span className=\"first-run-label\">\n {step.label}\n {done[i] ? <span className=\"visually-hidden\"> {say('done')}</span> : null}\n </span>\n {step.detail && <span className=\"first-run-detail\">{step.detail}</span>}\n </span>\n {link &&\n (done[i] ? (\n <a className={buttonClass({ intent: 'quiet', size: 'compact' })} {...link}>\n {say('open')}\n </a>\n ) : (\n <a className={buttonClass({ intent: i === next ? 'primary' : 'secondary', size: 'compact' })} {...link}>\n {adding ? say('common.add') : say('open')}\n </a>\n ))}\n </li>\n );\n })}\n </ol>\n </section>\n );\n}\n","/** What LandingData says, in the public pages 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 nothingToShowHere: 'Nothing to show here right now.',\n seeAll: 'See all {things}',\n maxLabel: 'Max {label}',\n search: 'Search {label}',\n noLimit: 'No limit',\n});\n","/**\n * The landing's sections that read the App's rows — a list view's cards,\n * and a search over its own filters — and its calls to action that open a\n * view, drawn inside the App for a visitor the public grant lets read them.\n * LandingSurface stays a page of the author's text; the App hands it these.\n *\n * A search writes exactly what the list's filter boxes would: a choice is\n * `= value`, typed text is `contains`, a most-you-would-pay is `<=`, each\n * through the same condition writer, into the list's own address. The\n * result is the list, and a link to it is the search.\n */\nimport { useState, type FormEvent } from 'react';\nimport { useQuery } from '@tanstack/react-query';\nimport { activeApp } from '../appState.js';\nimport { api, columnDisplay, columnLabel, findTable, go, quote, state, tableView } from '@mistriwork/kit/client/core.js';\nimport { equalsTail, withCondition } from '@mistriwork/kit/client/filterbar.js';\nimport { ownedBy } from '@mistriwork/kit/client/requestIdentity.js';\nimport { formatMoney } from '@mistriwork/kit/client/locale.js';\nimport { andQuery } from '@mistriwork/engine/shared/query.js';\nimport { columnKind, primaryKey, type ColumnMeta, type TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { type LandingImage, type LandingSection } from '../../shared/appModel.js';\nimport { humanName } from '@mistriwork/engine/shared/model.js';\nimport { listPresentationColumns } from '@mistriwork/engine/shared/appListColumns.js';\nimport { appListQuery, specTabs, visibleQuestion, wholeQuery, type ListSpec } from '@mistriwork/kit/client/components/appListModel.js';\nimport { isListRoom, viewRoom } from '@mistriwork/kit/client/components/appRooms.js';\nimport { viewLink } from '@mistriwork/kit/client/components/viewLink.js';\nimport { choiceWord, dressFor, type DisplayRule } from '@mistriwork/kit/client/components/valueModel.js';\nimport { inlineFileAddress } from '@mistriwork/kit/client/components/cardsModel.js';\nimport { Dropdown } from '@mistriwork/kit/client/components/Dropdown.js';\nimport { onDemand, useArrived } from '@mistriwork/kit/client/components/onDemand.js';\nimport { SuggestBox } from '@mistriwork/kit/client/components/suggestPart.js';\nimport { say } from '../copy/public/components/LandingData.js';\n\nconst CardsList = onDemand(() => import('@mistriwork/kit/client/components/CardsList.js'), 'CardsList');\n\ntype Section<K extends LandingSection['kind']> = Extract<LandingSection, { kind: K }>;\ntype Row = Record<string, unknown>;\n\n/** A text column with this many values or fewer is offered as a choice; past it, typed. */\nconst CHOICES = 24;\n\nfunction listRoom(key: string): ListSpec | undefined {\n const app = activeApp() as Parameters<typeof viewRoom>[0] | null;\n const room = app ? viewRoom(app, key) : undefined;\n return room && isListRoom(room) ? room : undefined;\n}\n\nconst connection = () => state.activeConnection ?? null;\nconst owned = () => (connection() ? ownedBy(connection()) : {});\n\n/** A list view's rows as its cards, the first `limit` by `sort`: the list's own question, narrowed. */\nexport function LandingCards({ section }: { section: Section<'view'> }) {\n const spec = listRoom(section.view);\n const table = spec ? (findTable(spec.table) as TableMeta | undefined) : undefined;\n const cards = spec?.presentation?.kind === 'cards' ? spec.presentation : undefined;\n const text =\n spec && table && cards\n ? [\n spec.table,\n andQuery(spec.query, specTabs(spec)[0]?.query),\n section.sort ? `sort ${section.sort}` : '',\n `show ${[...new Set([...(spec.show ?? []), ...listPresentationColumns(cards), ...primaryKey(table)])].join(', ')}`,\n ]\n .filter(Boolean)\n .join(' ')\n : '';\n const limit = section.limit ?? 6;\n const answer = useQuery({\n queryKey: ['run', connection() ?? '', 'landing-cards', text, limit],\n enabled: Boolean(text),\n queryFn: async () => {\n const data = (await api('/api/run', { q: text, limit, offset: 0, count: 'none', ...owned() })) as {\n rows?: Row[];\n errors?: Array<{ message: string }>;\n };\n if (data.errors?.length) throw new Error(data.errors[0].message);\n return data.rows ?? [];\n },\n });\n /* The cards come with the rows: asked for beside them, and the section stays empty until both are here. */\n const cardsHere = useArrived(CardsList, Boolean(cards));\n if (!spec || !table || !cards) return null;\n if (answer.isError) return <p className=\"front-note\">{(answer.error as Error).message}</p>;\n if (!answer.data || !cardsHere) return null;\n if (!answer.data.length) return <p className=\"front-note\">{say('nothingToShowHere')}</p>;\n const more = viewLink(section.view);\n return (\n <>\n <CardsList table={table} rows={answer.data} spec={cards} label={section.title ?? spec.label} />\n {more && (\n <p className=\"front-more\">\n <a href={more.href} onClick={more.onClick}>\n {say('seeAll', { things: (spec.label ?? '').toLocaleLowerCase() })}\n </a>\n </p>\n )}\n </>\n );\n}\n\n/** Round figures up to the highest value, for a most-you-would-pay: 1, 1.5, 2, 2.5, 3, 4, 5, 7.5 of each power of ten. */\nexport function priceSteps(max: number): number[] {\n if (!Number.isFinite(max) || max <= 0) return [];\n const steps: number[] = [];\n for (let power = 10 ** Math.max(0, Math.floor(Math.log10(max)) - 1); steps.length < 40; power *= 10) {\n for (const lead of [1, 1.5, 2, 2.5, 3, 4, 5, 7.5]) {\n const step = lead * power;\n if (step >= max / 12) steps.push(step);\n if (step >= max) return steps;\n }\n }\n return steps;\n}\n\ntype Field = {\n name: string;\n label: string;\n column: ColumnMeta;\n kind: 'choice' | 'text' | 'max';\n options?: Array<{ value: string; label: string }>;\n};\n\n/** How a field is asked: a vocabulary or a short list of values is a choice; a number, a ceiling; other text, typed. */\nfunction useFields(table: TableMeta | undefined, spec: ListSpec | undefined, names: readonly string[]): Field[] | undefined {\n const where = spec ? andQuery(spec.query, specTabs(spec)[0]?.query) : '';\n const columns = names\n .map((name) => table?.columns.find((column) => column.name === name))\n .filter((column): column is ColumnMeta => Boolean(column));\n const answer = useQuery({\n queryKey: ['breakdown', 'landing-search', table?.id, where, names],\n enabled: Boolean(table && spec),\n queryFn: () =>\n Promise.all(\n columns.map(async (column): Promise<Field> => {\n const label = (columnLabel(table!.id, column.name) as string | null) ?? humanName(column.name);\n const allowed = (column as ColumnMeta & { allowed?: string[] }).allowed;\n if (allowed?.length)\n return {\n name: column.name,\n label,\n column,\n kind: 'choice',\n options: allowed.map((value) => ({\n value,\n label: choiceWord(columnDisplay(table!.id, column.name) as DisplayRule | null, value),\n })),\n };\n if (columnKind(column.type) === 'number') {\n const data = (await api('/api/breakdown', {\n text: [table!.id, where, `max ${column.name}`].filter(Boolean).join(' '),\n limit: 1,\n ...owned(),\n })) as { rows?: Row[] };\n const top = Number(Object.values(data.rows?.[0] ?? {})[0]);\n const rule = columnDisplay(table!.id, column.name) as DisplayRule | null;\n return {\n name: column.name,\n label: say('maxLabel', { label: label.toLocaleLowerCase() }),\n column,\n kind: 'max',\n options: priceSteps(top).map((step) => ({\n value: String(step),\n label:\n rule?.format === 'money'\n ? formatMoney(step, rule.currency, { maximumFractionDigits: 0 })\n : (dressFor(rule, step)?.text ?? step.toLocaleString()),\n })),\n };\n }\n const data = (await api('/api/breakdown', {\n text: [table!.id, where, `count by ${column.name}`].filter(Boolean).join(' '),\n limit: CHOICES + 1,\n ...owned(),\n })) as { rows?: Row[]; columns?: string[] };\n const values = (data.rows ?? [])\n .map((row) => row[data.columns?.[0] ?? column.name])\n .filter((value) => value !== null && value !== undefined && value !== '')\n .map(String);\n return values.length && values.length <= CHOICES\n ? {\n name: column.name,\n label,\n column,\n kind: 'choice',\n options: [...values].sort((a, b) => a.localeCompare(b)).map((value) => ({ value, label: value })),\n }\n : { name: column.name, label, column, kind: 'text' };\n }),\n ),\n });\n return answer.data;\n}\n\n/** A search over a list view: its own filters up front, submitted as the list's conditions. */\nexport function LandingSearch({ section }: { section: Section<'search'> }) {\n const spec = listRoom(section.view);\n const table = spec ? (findTable(spec.table) as TableMeta | undefined) : undefined;\n const fields = useFields(table, spec, section.filters);\n const [values, setValues] = useState<Record<string, string>>({});\n /* A text field the list suggests for suggests here too: the hero is the list's search, asked early. */\n const suggesting = useArrived(SuggestBox, Boolean(spec?.suggest));\n if (!spec || !table || !fields) return null;\n const set = (name: string, value: string) => setValues((current) => ({ ...current, [name]: value }));\n const submit = (event: FormEvent) => {\n event.preventDefault();\n let text = visibleQuestion(spec, appListQuery(spec, 0));\n for (const field of fields) {\n const value = (values[field.name] ?? '').trim();\n if (!value) continue;\n const tail = field.kind === 'text' ? `contains ${quote(value)}` : field.kind === 'max' ? `<= ${value}` : equalsTail(value);\n text = withCondition(text, field.name, tail) as string;\n }\n (state as { page: number }).page = 0;\n go({ ...tableView(spec.table, wholeQuery(spec, text)), view: section.view }, 'push');\n };\n return (\n <form\n className=\"front-search-form\"\n role=\"search\"\n aria-label={section.title ?? say('search', { label: spec.label ?? '' }).trim()}\n onSubmit={submit}\n >\n <div className=\"front-search-fields\">\n {fields.map((field) => (\n <label key={field.name} className=\"front-search-field\">\n <span className=\"front-search-label\">{field.label}</span>\n {field.kind === 'text' && suggesting && spec.suggest?.[field.name] ? (\n /* A pick fills the field; the form's own button searches, with whatever else the hero asks. */\n <SuggestBox\n table={table.id}\n columns={spec.suggest[field.name]}\n standing={spec.query ?? ''}\n text={values[field.name] ?? ''}\n onText={(value) => set(field.name, value)}\n onPick={(value) => set(field.name, value)}\n inputProps={{ type: 'search', className: 'front-search-input', placeholder: say('common.any') }}\n />\n ) : field.kind === 'text' ? (\n <input\n type=\"search\"\n className=\"front-search-input\"\n placeholder={say('common.any')}\n value={values[field.name] ?? ''}\n onChange={(event) => set(field.name, event.target.value)}\n />\n ) : (\n <Dropdown\n ariaLabel={field.label}\n value={values[field.name] ?? ''}\n onChange={(value) => set(field.name, value)}\n items={[{ value: '', label: field.kind === 'max' ? say('noLimit') : say('common.any') }, ...(field.options ?? [])]}\n />\n )}\n </label>\n ))}\n </div>\n <button type=\"submit\" className=\"front-action front-action-primary front-search-go\">\n {section.submitLabel ?? say('navigation.search')}\n </button>\n </form>\n );\n}\n\n/** The hero's photo: its row of the App's files, by key, drawn inline through the file route. */\nexport function landingImage(image: LandingImage): string | undefined {\n const table = findTable(image.from) as TableMeta | undefined;\n const key = table ? primaryKey(table) : [];\n return table && key.length === 1 ? inlineFileAddress(table.id, { [key[0]]: image.key }, state.activeConnection ?? null) : undefined;\n}\n\n/** The two sections the App draws for the landing; anything else is the landing's own. */\nexport function landingSection(section: LandingSection) {\n if (section.kind === 'view') return <LandingCards section={section} />;\n if (section.kind === 'search') return <LandingSearch section={section} />;\n return null;\n}\n","/** What Dashboard says, in the dashboards 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 target: 'Target {goal}',\n nothingToCountYet: 'Nothing to count yet.',\n nothingToDrawYet: 'Nothing to draw yet.',\n thisSectionHasNoBreakdown: 'This section has no breakdown query.',\n thisSectionHasNoRecord: 'This section has no record query.',\n vsTheCompareWindow: 'vs the compare window',\n inTheCompareWindow: '{b} in the compare window ({compare})',\n sameAsBefore: 'Same as before',\n sameAsTheCompareWindow: 'Same as the compare window',\n ofTarget: '{reached} of {goal} target',\n ofWhole: '{figure} of {whole} ({reached})',\n ofWholeSaid: '{figure} of {whole}, {percent} percent',\n theTimeWindowAbove: 'The time window above does not change this figure.',\n fixedWindow: 'Right now',\n allTime: 'All time',\n noToCount: 'No {table} to count.',\n openTableWhereBy: 'Open {table} where {by} = {key}',\n noToDraw: 'No {table} to draw.',\n byDay: 'by day',\n byWeek: 'by week',\n byMonth: 'by month',\n byQuarter: 'by quarter',\n nothingToCrossYet: 'Nothing to cross yet.',\n noToCross: 'No {table} to cross.',\n theFullListWithItsTabs: 'The full list, with its tabs and filters',\n figureInAll: '{figure} in all',\n nothingToLayOut: 'Nothing to lay out yet.',\n noToLayOut: 'No {table} to lay out.',\n moreCount: '+ {figure} more',\n timeWindow: 'Time window',\n allTimeWindow: 'All time',\n nothingInThisTimeWindow: 'Nothing in this time window.',\n showAllTime: 'Show all time',\n defaultWindow: 'Default',\n windowRange: '{from} – {to}',\n pickWindow: 'Time window: {window}',\n any: 'Any {label}',\n filter: 'Filter by {label}',\n latestChanges: 'Latest changes',\n branding: 'Branding',\n integrations: 'Integrations',\n dashboardContext: 'Dashboard context',\n vsPrior: 'vs prior {period}',\n sameAsPrior: 'Same as prior {period}',\n});\n","/**\n * A dashboard: the app's own screen, composed like a page but about the\n * whole table instead of one record.\n *\n * Every section rides machinery that already exists — a metric is the\n * home card's one-group breakdown with a width, a breakdown is the same\n * def the page sections run, a list is the real table view with the\n * chrome off — so this module is composition, not a new engine. The\n * sections wear the page's own layout classes, because a dashboard and a\n * page are the same room at two zoom levels and should read as such.\n *\n * Every fetch is a Query. That is what makes a refresh a refetch — the\n * numbers change in place, the reader never sees a loading state — and\n * what makes fifteen sections on one screen fifteen cache entries rather\n * than fifteen requests per paint: a pick changes the sections it lands\n * on and the rest keep what they have.\n */\nimport { shell } from '@mistriwork/kit/client/shellMode.js';\nimport {\n createContext,\n memo,\n useCallback,\n useContext,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type CSSProperties,\n type ReactNode,\n} from 'react';\nimport { keepPreviousData, useIsFetching, useQuery, useQueryClient } from '@tanstack/react-query';\nimport {\n columnDisplay,\n findTable,\n go,\n labelColumn,\n labelPath,\n openRecord,\n primaryKey,\n quote,\n refsFrom,\n tableView,\n} from '@mistriwork/kit/client/core.js';\nimport { splitQuery } from '@mistriwork/kit/client/clauses.js';\nimport { batchedBreakdown, batchedRun } from '@mistriwork/kit/client/breakdownBatch.js';\nimport { ListEmpty } from '@mistriwork/kit/client/components/ListEmpty.js';\nimport { andQuery } from '@mistriwork/engine/shared/query.js';\nimport { droppedQuery, funnelBasis, funnelChains, funnelText, stageColumn } from '@mistriwork/engine/shared/funnel.js';\nimport { Funnel, type FunnelDoor } from './Funnel.js';\nimport { exportOffered, type AppListEmpty } from '@mistriwork/engine/shared/listPresentations.js';\nimport { gridTemplateAreas, layoutAreas, layoutGrid, reflowLayout, type LayoutGrid } from '@mistriwork/engine/shared/dashLayout.js';\nimport {\n boardCountText,\n chartLimit,\n dashboardListQuery,\n groupsAskedFor,\n measureText,\n pickQuery,\n type AskLookups,\n} from '@mistriwork/engine/shared/dashboardAsks.js';\nimport { sparkText, sparkWindow } from '@mistriwork/engine/shared/dashboardTrend.js';\nimport { trendPoints } from '@mistriwork/engine/shared/autoBucket.js';\nimport type { ColumnMeta, ForeignKey, TableMeta } from '@mistriwork/engine/shared/schema.js';\nimport { message, messageLanguage, subscribeMessages } from '@mistriwork/kit/client/messages.js';\nimport { activeApp, inAppMode } from '../appState.js';\nimport { mayRunAny } from '@mistriwork/kit/client/actionGrants.js';\nimport { appRooms, isListRoom, offeredBy, resourceOf, viewRoom } from '@mistriwork/kit/client/components/appRooms.js';\nimport { listEntry, listLink, type ViewLink } from '@mistriwork/kit/client/components/viewLink.js';\nimport { TableRoom } from '@mistriwork/kit/client/components/TableRoom.js';\nimport { referenceNames } from '@mistriwork/kit/client/components/appListModel.js';\nimport { namedCell } from '@mistriwork/kit/client/components/listColumn.js';\nimport { dressFor, groupLabel, maskedText, ruleSays, type DisplayRule } from '@mistriwork/kit/client/components/valueModel.js';\nimport { AvatarText, Dressed, Value } from '@mistriwork/kit/client/components/Value.js';\nimport { avatarOwner, useAvatarPhotos } from '@mistriwork/kit/client/components/avatarPhotos.js';\nimport { Sparkline, TONE_INK, periodTick } from '@mistriwork/kit/client/components/Chart.js';\nimport { useAutoChart } from '@mistriwork/kit/client/components/autoChart.js';\nimport { ChartFigure, ChartShapeFigure, EXTRA_SHAPES, type ExtraShape } from '@mistriwork/kit/client/components/ChartFigure.js';\nimport { Dropdown } from '@mistriwork/kit/client/components/Dropdown.js';\nimport { DashboardNote } from '@mistriwork/kit/client/components/DashboardNote.js';\nimport { Icon } from '@mistriwork/kit/client/components/Icon.js';\nimport { FirstRun, useFirstRun } from './FirstRun.js';\nimport { ErrorBoundary } from '@mistriwork/kit/client/components/ErrorBoundary.js';\nimport { Empty, Problem, ProblemScopeProvider } from '@mistriwork/kit/client/components/Notes.js';\nimport { Button } from '@mistriwork/ui/Button.js';\nimport { landingImage } from './LandingData.js';\nimport type { AppIconName } from '@mistriwork/engine/shared/appIcons.js';\nimport { currencyPath } from '@mistriwork/engine/shared/money.js';\nimport { targetText } from '@mistriwork/engine/shared/dashboardAsks.js';\nimport {\n allSections,\n barShare,\n boardSection,\n breakdownText,\n CurrencyFigures,\n pinnedCurrency,\n figure,\n fullQuery,\n legendSayer,\n namedGroups,\n orderGroups,\n picked,\n sayer,\n sectionPeriod,\n windowed,\n windowTitle,\n metricWindow,\n type DashboardDef,\n type DashboardProps,\n type Periods,\n type Picks,\n type Section,\n} from '@mistriwork/kit/client/components/dashboardModel.js';\nimport { declaredOrder, orderDeclared } from '@mistriwork/kit/client/components/groupOrder.js';\nimport { formatApprox, formatDate, formatLocale, formatPercent } from '@mistriwork/kit/client/locale.js';\nimport { dateWindow } from '@mistriwork/engine/shared/queryDates.js';\nimport { DropItem, DropMenu } from '@mistriwork/ui/DropMenu.js';\n/* The dashboard's own blocks' sheet travels with this chunk (onDemand), not in the first stylesheet. */\nimport './DashboardBlocks.css';\nimport { onDemand } from '@mistriwork/kit/client/components/onDemand.js';\nimport { say as sayCopy } from '../copy/dashboards/components/Dashboard.js';\nimport { liveFollowing } from '@mistriwork/kit/client/liveState.js';\n\n/* An author's component, and the page's side of @mistriwork/mistri/ui with it: fetched\n the first time a dashboard holds one, never for a dashboard without. */\nconst CustomDashSection = onDemand(() => import('./sdk/CustomSection.js'), 'CustomDashSection');\n/* A list that works as its room does, and the feed of recent changes: each fetched the first time a dashboard holds one. */\nconst InteractiveList = onDemand(() => import('@mistriwork/kit/client/components/DashboardList.js'), 'InteractiveList');\nconst ActivityFeed = onDemand(() => import('./DashboardActivity.js'), 'ActivityFeed');\nconst FindSection = onDemand(() => import('./DashboardFind.js'), 'FindSection');\nconst BrandingForm = onDemand(() => import('./BrandingForm.js'), 'BrandingForm');\nconst IntegrationsForm = onDemand(() => import('./IntegrationsForm.js'), 'IntegrationsForm');\n/* A section's own period picker, with the rules of the heading row that holds it. */\nconst SectionPeriod = onDemand(() => import('@mistriwork/kit/client/components/SectionPeriod.js'), 'SectionPeriod');\n\ninterface Breakdown {\n columns?: string[];\n rows?: Array<Record<string, unknown>>;\n names?: Record<string, Record<string, string>>;\n}\ninterface Rows {\n rows?: Array<Record<string, unknown>>;\n}\ntype Row = Record<string, unknown>;\n\n/* What a read says about the time it is asked at: a window (\"last 30 days\"), a day or a period named from now. A\n figure that says none changes only when the data does, and live sync (liveSync.ts) tells the page when. */\nconst TIME_RELATIVE =\n /\\b(?:now|today|yesterday|tomorrow|ago|(?:this|last|next|past|previous)\\s+(?:\\d+\\s+)?(?:day|week|month|quarter|year)s?)\\b/i;\n\n/* The youngest answer the minute reads again. Query asks the interval again after every answer, so a tile read at\n :00.2 ticks at the next :00, a minute old; one read at :58 waits for the minute after. */\nconst TICK_FLOOR = 15_000;\n\n/**\n * The minute tick: asked again on the wall-clock minute, asleep with the tab (Query's refetchIntervalInBackground is\n * off). A read that depends on the time always ticks; every other read ticks while the page follows no changes to its\n * table (an App without `live: true`, `--no-live`, or a resource's own `live: false`), since nothing else would tell a\n * dashboard left on a wall that its data moved.\n */\nexport const minuteTick = (\n text: string | null | undefined,\n table?: string,\n following: (table?: string) => boolean = liveFollowing,\n): ((query?: { state: { dataUpdatedAt: number } }) => number | false) | false => {\n if (!text) return false;\n const timed = TIME_RELATIVE.test(text);\n return (query) => {\n if (!timed && following(table)) return false;\n const now = Date.now();\n const next = 60_000 - (now % 60_000);\n /* An answer read moments before the minute (a page opened at :58, the first paint's carried answers) is not read\n again at :00: the tick that would land on it goes to the minute after. */\n const read = query?.state.dataUpdatedAt;\n return read && now + next - read < TICK_FLOOR ? next + 60_000 : next;\n };\n};\n\n/* A tile is an aggregate, and says what it is as of: re-read when a change\n to its tables is announced (liveSync.ts), a write that invalidates it, the\n minute for a read that depends on the time, or after two minutes, not every\n time the dashboard is opened again or its tab regains focus. */\nconst TILE_FRESH = 120_000;\n/* The most currencies a figure says apart: more than this is a report, not a card. */\nconst CURRENCIES_SAID = 6;\n\n/* Here, not in dashboardModel.ts: only a dashboard sums a measure apart per currency, and that model is first-page code (PageMetrics). */\n/** The path a section's money measure is grouped by, where each row says its own currency and the section's query does not pin one. */\nfunction currencySplit(section: Pick<Section, 'table' | 'measure' | 'format' | 'query'>): string | undefined {\n if (section.format || /\\s[*/+-]\\s/.test(section.measure ?? '')) return undefined;\n const m = /^(?:sum|avg|min|max|median)\\s+([A-Za-z0-9_.]+)(?:\\s+as\\s+\\w+)?$/i.exec((section.measure ?? '').trim());\n const rule = m && section.table ? (columnDisplay(section.table, m[1]) as { format?: string; currencyColumn?: string } | null) : null;\n const path = rule?.format === 'money' ? currencyPath(rule, m![1]) : undefined;\n return path && !pinnedCurrency(section.query, path) ? path : undefined;\n}\n\n/* `table`: the resource the read is over, whose own `live: false` keeps it on the minute tick on a live App. */\nfunction useBreakdown(text: string | null, table?: string, limit?: number) {\n return useQuery<Breakdown>({\n queryKey: ['breakdown', text, limit ?? null],\n queryFn: () => {\n if (!text) throw new Error(sayCopy('thisSectionHasNoBreakdown'));\n // Asked with the other sections of this paint, in one request (breakdownBatch.ts).\n return batchedBreakdown<Breakdown>({ text, limit });\n },\n enabled: Boolean(text),\n refetchInterval: minuteTick(text, table),\n staleTime: TILE_FRESH,\n placeholderData: keepPreviousData,\n });\n}\n\nfunction useRows(q: string | null, limit: number, table?: string) {\n return useQuery<Rows>({\n queryKey: ['run', q, limit],\n queryFn: () => {\n if (!q) throw new Error(sayCopy('thisSectionHasNoRecord'));\n // With the section's numbers, in one request (breakdownBatch.ts).\n return batchedRun<Rows>({ q, limit, offset: 0, count: 'none' });\n },\n enabled: Boolean(q),\n refetchInterval: minuteTick(q, table),\n staleTime: TILE_FRESH,\n placeholderData: keepPreviousData,\n });\n}\n\n/** One measure over one query, as a number — the home card's fetch. */\nfunction useMeasure(section: Pick<Section, 'table' | 'measure' | 'format'>, query: string | undefined, enabled = true) {\n /* Money each row says its own currency for is summed apart per currency (CurrencyFigures). */\n const split = currencySplit({ ...section, query });\n const text = split ? `${measureText(section, query)} by ${split}` : measureText(section, query);\n return useQuery<unknown>({\n queryKey: ['measure', text],\n queryFn: async () => {\n const data = await batchedBreakdown<Breakdown>({ text, limit: split ? CURRENCIES_SAID : 1 });\n if (split) {\n /* The currency first, the figure last, whatever the server says between them. */\n const figures = (data.rows ?? []).flatMap((row) => {\n const keys = Object.keys(row);\n const code = row[keys[0]];\n return typeof code === 'string' && code.trim() ? [[code.trim().toUpperCase(), row[keys[keys.length - 1]]] as const] : [];\n });\n return figures.length ? new CurrencyFigures(figures) : null;\n }\n const row = data.rows?.[0];\n return row ? row[Object.keys(row)[0]] : null;\n },\n enabled,\n refetchInterval: minuteTick(text, section.table),\n staleTime: TILE_FRESH,\n placeholderData: keepPreviousData,\n });\n}\n\n/**\n * A section authored `empty: 'hide'` that has nothing to draw says so to the shell round it, which leaves the whole\n * section out — its heading and its place in the grid with it — rather than drawing a title over an empty note.\n * The section stays mounted, so its question keeps being asked and it returns when something arrives.\n */\nconst LeaveOutContext = createContext<(gone: boolean) => void>(() => {});\nfunction LeaveOut() {\n const leave = useContext(LeaveOutContext);\n useEffect(() => {\n leave(true);\n return () => leave(false);\n }, [leave]);\n return null;\n}\n\n/**\n * One dashboard section's own box, hidden while the section inside it has asked to be left out. On a layout the grid\n * decides when (`report` says what each section asks, `hidden` is what the grid has settled on): a section that left\n * out the moment its own answer arrived would move the areas round it once for every tile that answers.\n */\nfunction SectionShell({\n className,\n children,\n at,\n report,\n hidden,\n}: {\n className: string;\n children: ReactNode;\n at?: number;\n report?: (at: number, gone: boolean) => void;\n hidden?: boolean;\n}) {\n const [gone, setGone] = useState(false);\n const leave = useCallback(\n (now: boolean) => {\n setGone(now);\n if (at !== undefined) report?.(at, now);\n },\n [at, report],\n );\n return (\n <section className={className} hidden={(report ? hidden : gone) || undefined}>\n <LeaveOutContext.Provider value={leave}>{children}</LeaveOutContext.Provider>\n </section>\n );\n}\n\n/**\n * Where a section's groups go. In an App that is one of its lists, never the database browser: the list its `to`\n * names, else the one list over its table this reader is served; with none, or several, the groups are text\n * (`null`) and `mistri check` says which. In the browser (`undefined`) a group opens the table's rows.\n */\nfunction drillTarget(section: Section): string | null | undefined {\n if (section.noDrill) return null;\n const app = activeApp() as Parameters<typeof appRooms>[0] | null;\n if (!inAppMode() || !app) return undefined;\n if (section.view) {\n const room = viewRoom(app, section.view);\n return room && isListRoom(room) && !room.error ? section.view : null;\n }\n const lists = appRooms(app).filter((room) => isListRoom(room) && !room.error && room.table === section.table);\n return lists.length === 1 ? lists[0].id : null;\n}\n\n/** A group's doorway: followed in place, and where a list takes it, also a link a reader can open in a new tab. */\ntype Drill = ((value: unknown) => void) & { link: (value: unknown) => ViewLink | undefined };\n\n/**\n * A group is a doorway when the `by` is a plain column path: clicking\n * \"on_hold · 70\" opens the list filtered to that group, on top of\n * whatever the section (and the reader's window) already narrowed. A\n * bucketed by — \"month opened_on\" — stays read-only: its groups are\n * derived values the filter grammar does not take as equalities.\n */\nfunction drillFor(section: Section): Drill | null {\n if (!section.by || /\\s/.test(section.by)) return null;\n const target = drillTarget(section);\n if (target === null) return null;\n const queryFor = (value: unknown) => `${section.table} ${andQuery(section.query, `${section.by} = ${quote(String(value))}`)}`;\n const open = (value: unknown) => {\n if (value == null) return;\n if (target === undefined) go(tableView(section.table, queryFor(value)), 'push');\n else {\n const entry = listEntry(target, queryFor(value));\n if (entry) go(entry, 'push');\n }\n };\n return Object.assign(open, {\n link: (value: unknown) => (target && value != null ? listLink(target, queryFor(value)) : undefined),\n });\n}\n\n/** A group's key as its reader says it: the column's display rule, and in an\n App the column's vocabulary as words (valueModel.ts, groupLabel). */\nfunction sayGroup(table: string | undefined, column: string | undefined) {\n /* A weekday bucket answers 1 (Monday) to 7, an hour bucket 00 to 23: said as the reader's day and hour. */\n const bucket = /^(weekday|hour)\\s/i.exec(column ?? '')?.[1]?.toLowerCase();\n if (bucket) return (key: unknown) => sayBucket(bucket, key);\n const rule = columnDisplay(table ?? '', column ?? '') as DisplayRule | null;\n const allowed = (findTable(table ?? '') as TableMeta | undefined)?.columns.find((c) => c.name === column)?.allowed;\n return (key: unknown) => groupLabel(rule, key, allowed);\n}\n\n/** A weekday or hour bucket's key in the reader's words: 2024-01-01 was a Monday. */\nfunction sayBucket(bucket: string, key: unknown): string {\n const n = Number(key);\n if (key == null || key === '' || !Number.isInteger(n)) return String(key ?? '—');\n const at = bucket === 'weekday' ? new Date(Date.UTC(2024, 0, n)) : new Date(Date.UTC(2024, 0, 1, n));\n const options: Intl.DateTimeFormatOptions =\n bucket === 'weekday' ? { weekday: 'short', timeZone: 'UTC' } : { hour: 'numeric', timeZone: 'UTC' };\n return at.toLocaleString(formatLocale(), options);\n}\n\n/* The schema as the dashboard's asks read it (shared/dashboardAsks.ts), through the walk's own helpers. */\nconst lookups: AskLookups = {\n table: (id) => findTable(id) as TableMeta | undefined,\n references: (id) => refsFrom(id) as ForeignKey[],\n referenceNames,\n naming: (table) => labelPath(table) as string | undefined,\n};\n\n/* ---------- metric ---------- */\n\n/** A section's mark, leading its title: one of the App's curated icons, its glyph in the App payload. */\nfunction Mark({ section }: { section: Section }) {\n return section.icon ? <Icon name={section.icon} size={16} className=\"dash-section-icon\" /> : null;\n}\n\n/** A change's news, as a class: ' good' or ' bad' where the metric says which way is better, else nothing. */\nexport function changeTone(diff: number, better: 'up' | 'down' | undefined): '' | ' good' | ' bad' {\n if (!better || diff === 0 || !Number.isFinite(diff)) return '';\n return diff > 0 === (better === 'up') ? ' good' : ' bad';\n}\n\n/** What a compare window is, as a card says it beside its change: \"vs prior 90 days\". */\nexport function comparedWith(compare: string | undefined, level = false): string | undefined {\n const period = /\\bprevious\\s+(\\d+)\\s+(minute|hour|day|week|month|year)s?\\b/i.exec(compare ?? '');\n if (!period) return compare ? sayCopy(level ? 'sameAsTheCompareWindow' : 'vsTheCompareWindow') : undefined;\n const n = Number(period[1]);\n return sayCopy(level ? 'sameAsPrior' : 'vsPrior', { period: n === 1 ? period[2].toLowerCase() : `${n} ${period[2].toLowerCase()}s` });\n}\n\ninterface MetricProps {\n section: Section;\n /** The section's own period picker, when it has windows of its own (SectionPeriod). */\n period?: ReactNode;\n /** The reader has picked a window on this dashboard: a card it does not move says so. */\n windowed?: boolean;\n /** A card beside it in the row says the window it is over: a card with none says it is the present, so\n the row reads evenly rather than one figure standing with nothing under it. */\n dated?: boolean;\n /** Home keeps its own click and its own way of saying what went wrong. */\n onOpen?: () => void;\n onErrorClick?: () => void;\n}\n\n/**\n * One KPI card: the number, its label, its delta when a compare window is\n * given. The app home's cards and a dashboard's metrics are this same\n * card. A card carrying a resolution `error` shows the honest dash.\n */\nexport const Metric = memo(function Metric({\n section,\n windowed: offered = false,\n dated = false,\n period,\n onOpen,\n onErrorClick,\n}: MetricProps) {\n const label = section.title ?? section.table ?? '';\n const windowNote = section.windowNote;\n const live = !section.error;\n const now = useMeasure(section, section.query, live);\n const say = sayer(section, now.data, { card: true });\n /* The figure whole, where the card says it compact: its title, and what a screen reader hears. */\n const sayWhole = sayer(section, now.data, { whole: true });\n const then = useMeasure(section, section.compare, live && Boolean(section.compare));\n /* A goal read from data is a second measure, in the metric's own words; a number needs no read. */\n const goalAsk = typeof section.target === 'object' && section.target ? section.target : undefined;\n const goalData = useMeasure(goalAsk ?? section, goalAsk?.query, live && Boolean(goalAsk));\n /* The spark: over a window, the metric across that window in the span's\n unit — thirty days of \"last 30 days\", twelve months of \"last 12\n months\" — drawn under the number beside its change; with none, the\n author's `spark: true` is the last twelve months by the section's own\n clock (`over`). It composes with whatever the card is narrowed to by\n other than time: a picked owner's card shows a picked owner's trend. */\n /* No trend line through several currencies' sums: there is no one line to draw. */\n const sparkAsk = live && !currencySplit(section) ? sparkText(section) : null;\n const spark = useBreakdown(sparkAsk, section.table);\n\n const shown = section.error ? '—' : now.isError ? '—' : now.data === undefined ? '…' : say(now.data);\n const whole = section.error || now.isError || now.data === undefined ? shown : sayWhole(now.data);\n /* While the figure is read it is a placeholder at the figure's own size, not \"…\" set at the figure's 32px, which\n stood on the card as three heavy dots. Heard as \"…\" still (heard, below). */\n const figure = shown === '…' ? <span className=\"sk-bar home-card-wait\" aria-hidden=\"true\" /> : shown;\n let delta: ReactNode = null;\n /* The change's news, which the trend beside it is drawn in too. */\n let tone = '';\n if (section.compare && now.data != null && then.data != null) {\n const a = Number(now.data);\n const b = Number(then.data);\n if (Number.isFinite(a) && Number.isFinite(b)) {\n const diff = a - b;\n /* Coloured only when the author said which way is good news. \"More\"\n is not always \"better\", so without a word the tone stays neutral. */\n tone = changeTone(diff, section.better);\n /* A change says what it is a change from: \"↓ $785.1K\" alone left the\n reader to guess the period it was measured against. */\n const against = comparedWith(section.compare, diff === 0);\n /* Unchanged is one phrase, \"Same as prior 30 days\", not a figure with nothing to say. */\n delta =\n diff === 0 ? (\n <span className=\"dash-delta\" title={sayCopy('inTheCompareWindow', { b: say(b), compare: section.compare })}>\n <span className=\"dash-delta-whole\">{against ?? sayCopy('sameAsBefore')}</span>\n </span>\n ) : (\n <span className={`dash-delta${tone}`} title={sayCopy('inTheCompareWindow', { b: say(b), compare: section.compare })}>\n <span className=\"dash-delta-figure\">{`${diff > 0 ? '↑' : '↓'} ${say(Math.abs(diff))}`}</span>\n {against && (\n <>\n {' '}\n <span className=\"dash-delta-period\">{against}</span>\n </>\n )}\n </span>\n );\n }\n }\n const sparkPoints = useMemo(() => {\n const rows = spark.data;\n if (!rows) return null;\n const [keyName, valueName] = rows.columns ?? [];\n const read = (rows.rows ?? [])\n .map((r) => ({ key: r[keyName], value: r[valueName] }))\n .sort((a, b) => (String(a.key) < String(b.key) ? -1 : String(a.key) > String(b.key) ? 1 : 0));\n const over = sparkWindow(section);\n const now = new Date();\n return over ? trendPoints(read, over.read, over.unit, section.measure, dateWindow(over.phrase, now), now) : read;\n }, [spark.data, section]);\n /* Both slots stand from the first paint: a change the card will show holds its line while the two figures are\n read, and a trend its height, so neither arrives by pushing the card taller. */\n const deltaSlot = delta ?? (\n <span className=\"dash-delta\" aria-hidden={section.compare ? 'true' : undefined}>\n {section.compare && !section.error ? '\\u00a0' : null}\n </span>\n );\n const sparkSlot = sparkAsk ? <SparkHost points={sparkPoints} say={say} tone={tone} /> : null;\n /* A goal makes the card a meter: the share reached drawn under the number\n and said beside it, the bar full at the goal and never past it. */\n const goalAt = typeof section.target === 'number' ? section.target : goalAsk ? Number(goalData.data ?? NaN) : NaN;\n const goal = Number.isFinite(goalAt) && goalAt > 0 ? goalAt : undefined;\n const reached =\n goal !== undefined && !section.error && now.data != null && Number.isFinite(Number(now.data)) ? Number(now.data) / goal : undefined;\n /* A whole is the figure's own cohort counted without its extra conditions: said as a share of it, \"118 of 159\n (74%)\", not as a goal reached. */\n const share = reached === undefined ? undefined : formatPercent(reached * 100, { maximumFractionDigits: 0 });\n const wholeWords = section.targetWhole && goal !== undefined && share !== undefined;\n const goalWords =\n goal === undefined\n ? ''\n : reached === undefined\n ? sayCopy('target', { goal: say(goal) })\n : section.targetWhole\n ? sayCopy('ofWhole', { figure: say(now.data), whole: say(goal), reached: share! })\n : sayCopy('ofTarget', { reached: share!, goal: say(goal) });\n /* What a screen reader hears: the figure once, then its share, never the visible words after the figure again. */\n const heard = wholeWords\n ? `${label}: ${sayCopy('ofWholeSaid', { figure: sayWhole(now.data), whole: sayWhole(goal), percent: String(Math.round(reached! * 100)) })}`\n : `${label}: ${whole}${goalWords ? `, ${goalWords}` : ''}`;\n /* A metric that names a list view opens that room — its tabs, its\n presentation — on the rows it counted, and says so with an arrow: the\n whole card is the way in. One the reader is not served opens the table. */\n const app = activeApp();\n const opens = section.view && app && viewRoom(app, section.view) ? section.view : undefined;\n /* `to: false`: a figure that is read where it stands, not a way into rows, so nothing in it is a control. */\n const still = section.noDrill === true && !section.error;\n const open = section.error\n ? (onErrorClick ?? (() => {}))\n : (onOpen ?? (() => go({ ...tableView(section.table, fullQuery(section)), ...(opens ? { view: opens } : {}) }, 'push')));\n /* A card with its own period holds the picker, and a button cannot hold\n another control: the card is a box, its label the way in. */\n if (period) {\n return (\n <div className={`home-card home-card-period${opens ? ' opens-view' : ''}`} title={section.error ?? fullQuery(section)}>\n <span className=\"home-card-value\" aria-hidden=\"true\" title={whole === shown ? undefined : whole}>\n {figure}\n </span>\n <span className=\"home-card-label\">\n {still ? (\n <span className=\"home-card-open\" aria-label={heard}>\n <Mark section={section} />\n {label}\n </span>\n ) : (\n <button type=\"button\" className=\"home-card-open\" aria-label={heard} onClick={open}>\n <Mark section={section} />\n {label}\n {opens && (\n <>\n {/* A word joiner: the arrow follows the label's last word, never wraps alone. */}\n {'\\u2060'}\n <span className=\"home-card-go\" aria-hidden=\"true\">\n →\n </span>\n </>\n )}\n </button>\n )}\n {period}\n </span>\n {deltaSlot}\n {windowNote && !section.error && <span className=\"dash-fixed dash-window\">{windowNote}</span>}\n {goal !== undefined && (\n <span className=\"dash-target\">\n <span className=\"dash-target-meter\" aria-hidden=\"true\">\n <span style={{ width: `${Math.round(Math.min(1, Math.max(0, reached ?? 0)) * 100)}%` }} />\n </span>\n <span className=\"dash-target-text\">{goalWords}</span>\n </span>\n )}\n {sparkSlot}\n </div>\n );\n }\n const Card = still ? 'div' : 'button';\n return (\n <Card\n {...(still ? { role: 'group' } : { type: 'button' as const, onClick: open })}\n className={`home-card${still ? ' home-card-still' : opens ? ' opens-view' : ''}`}\n aria-label={heard}\n title={section.error ?? fullQuery(section)}\n >\n <span className=\"home-card-value\" title={whole === shown ? undefined : whole}>\n {figure}\n </span>\n <span className=\"home-card-label\">\n <Mark section={section} />\n {label}\n {opens && (\n <>\n {/* A word joiner: the arrow follows the label's last word, never wraps alone. */}\n {'\\u2060'}\n <span className=\"home-card-go\" aria-hidden=\"true\">\n →\n </span>\n </>\n )}\n </span>\n {deltaSlot}\n {/* The window above moves every card that has a clock; once the reader\n has picked one, a card without says so, quietly. Under All time no\n card is narrowed, so the note would only be noise on a card that\n was never about time — what is on order, what is short. */}\n {offered && !section.over && !section.error && (\n <span className=\"dash-fixed\" title={sayCopy('theTimeWindowAbove')}>\n {sayCopy('fixedWindow')}\n </span>\n )}\n {/* A card over a clock with no window counts every time; one with no clock counts what stands now. */}\n {dated && !offered && !windowNote && !section.error && (\n <span className=\"dash-fixed\">{sayCopy(section.over ? 'allTime' : 'fixedWindow')}</span>\n )}\n {/* The window the author set, said under the figure rather than wrapped into its label (metricWindow). */}\n {windowNote && !section.error && <span className=\"dash-fixed dash-window\">{windowNote}</span>}\n {goal !== undefined && (\n <span className=\"dash-target\">\n <span className=\"dash-target-meter\" aria-hidden=\"true\">\n <span style={{ width: `${Math.round(Math.min(1, Math.max(0, reached ?? 0)) * 100)}%` }} />\n </span>\n <span className=\"dash-target-text\">{goalWords}</span>\n </span>\n )}\n {sparkSlot}\n </Card>\n );\n});\n\n/** The measure's shape inside the card, its height held while it is read and where it has too few points to draw. */\nfunction SparkHost({\n points,\n say,\n tone,\n}: {\n points: Array<{ key: unknown; value: unknown }> | null;\n say: (v: unknown) => string;\n tone: string;\n}) {\n return <span className={`spark-host is-reserved${tone}`}>{points && points.length >= 4 && <Sparkline rows={points} say={say} />}</span>;\n}\n\n/* ---------- breakdown, chart, matrix ---------- */\n\n/* How many groups a breakdown asks for before it orders them itself (orderGroups): shared/dashboardAsks.ts. */\nconst askedFor = groupsAskedFor;\n\n/** The order of the column a section groups by, where it declares one (groupOrder.ts, declaredOrder). */\nfunction orderOf(table: string | undefined, by: string | undefined): { vocabulary?: string[]; scale: boolean } {\n /* A computed column (an age in days) is not among the table's own columns: its declared type says whether it is a\n scale (shared/computed.ts). */\n const meta = findTable(table ?? '') as TableMeta | undefined;\n const computed = by && meta?.computed && Object.hasOwn(meta.computed, by) ? meta.computed[by] : undefined;\n const column = meta?.columns.find((c) => c.name === by) ?? (computed ? { type: computed.type } : undefined);\n return declaredOrder(column, by ? (columnDisplay(table ?? '', by) as DisplayRule | null) : null, by);\n}\n\n/**\n * A breakdown's goals by group key (G76): each group's goal, the groups with a goal and nothing measured yet (a seller\n * with a quota and no wins is at 0%, not missing), and the goal answer's names for those.\n */\nfunction goalsOf(section: Section, answer: Breakdown | undefined, keyName: string, countName: string) {\n const goal = section.target;\n if (typeof goal !== 'object' || !goal.by || !answer) return undefined;\n const [goalKey, goalValue] = answer.columns ?? [];\n const goals = new Map<string, number>();\n for (const row of answer.rows ?? []) {\n const value = Number(row[goalValue]);\n if (row[goalKey] != null && Number.isFinite(value) && value > 0) goals.set(String(row[goalKey]), value);\n }\n return {\n of: (key: unknown) => (key == null ? undefined : goals.get(String(key))),\n /* Each goal's group the measure has no row for, at nothing reached. */\n unmet: (measured: readonly Record<string, unknown>[]) => {\n const seen = new Set(measured.map((row) => String(row[keyName])));\n return (answer.rows ?? [])\n .filter((row) => row[goalKey] != null && goals.has(String(row[goalKey])) && !seen.has(String(row[goalKey])))\n .map((row) => ({ [keyName]: row[goalKey], [countName]: 0 }));\n },\n sayKey: namedGroups(answer, goalKey, sayGroup(goal.table, goal.by)),\n };\n}\n\n/** The vocabulary of the column a section groups by, where one is declared. */\nconst vocabularyOf = (table: string | undefined, column: string | undefined): string[] | undefined => orderOf(table, column).vocabulary;\n\nconst BreakdownRows = memo(function BreakdownRows({ section }: { section: Section }) {\n const data = useBreakdown(breakdownText(section, askedFor(section)), section.table);\n /* A goal per group (G76): the target table's measure by its own column, a seller's quota beside their won. */\n const goals = useBreakdown(targetText(section), typeof section.target === 'object' ? section.target?.table : undefined);\n const drill = drillFor(section);\n const say = sayer(section);\n if (data.isError) return <Problem text={(data.error as Error).message} />;\n if (goals.isError) return <Problem text={(goals.error as Error).message} />;\n /* While read, its rows as they will stand — a group's word, its count's place, its bar — one per group the\n vocabulary or the limit says will come: an empty box was nothing tall, and the rows arriving pushed the sections\n under it down. */\n if (!data.data || (targetText(section) && !goals.data)) {\n const expected = Math.min(Math.max(section.limit ?? vocabularyOf(section.table, section.by)?.length ?? 3, 1), 8);\n return (\n <div className=\"page-breakdown-rows\" role=\"status\" aria-busy=\"true\">\n {Array.from({ length: expected }, (_, i) => (\n <div key={i} className=\"pbd-row pbd-wait\" aria-hidden=\"true\">\n <span className=\"pbd-label\">\n <span className=\"sk-bar\" style={{ width: `${[58, 44, 66, 38][i % 4]}%`, height: '10px' }} />\n </span>\n <span className=\"pbd-bar\" />\n <span className=\"pbd-count\">{'\\u00a0'}</span>\n </div>\n ))}\n </div>\n );\n }\n const [keyName, countName] = data.data.columns ?? [];\n const goal = goalsOf(section, goals.data, keyName, countName);\n const { vocabulary, scale } = orderOf(section.table, section.by);\n /* A scale with a limit keeps its largest groups, then reads them in its order: the first five days of an age\n histogram are not its five busiest. */\n const measured = [...(data.data.rows ?? []), ...(goal?.unmet(data.data.rows ?? []) ?? [])];\n const kept = scale && !vocabulary && section.limit ? orderGroups(measured, keyName, countName).slice(0, section.limit) : measured;\n const rows = orderDeclared(kept, keyName, countName, vocabulary, scale).slice(0, section.limit);\n if (!rows.length)\n return section.emptyMode === 'hide' ? (\n <LeaveOut />\n ) : (\n <Nothing text={inAppMode() ? sayCopy('nothingToCountYet') : sayCopy('noToCount', { table: section.table ?? '' })} />\n );\n const largest = Math.max(...rows.map((r) => Number(r[countName]) || 0));\n const sayRow = say.among(rows.map((r) => r[countName]));\n const sayKey = namedGroups(data.data, keyName, goal?.sayKey ?? sayGroup(section.table, section.by));\n /* A group of a column that colors its values (a severity, a state) wears that color, as its chip does in a list and\n a chart's bar does (G209). Against a goal the bar is progress, not the group's meaning, so it keeps the accent. */\n const toneOf =\n !goal && section.by && !/\\s/.test(section.by)\n ? (key: unknown) => TONE_INK[ruleSays(columnDisplay(section.table ?? '', section.by!) as DisplayRule | null, key).tone ?? '']\n : undefined;\n return (\n <div className=\"page-breakdown-rows\">\n {rows.map((row, i) => {\n const key = row[keyName];\n /* Against a goal the bar is the share reached, full at the goal and never past it, as a metric's meter. */\n const target = goal?.of(key);\n const reached = target ? (Number(row[countName]) || 0) / target : undefined;\n const ink = toneOf?.(key);\n const parts = (\n <>\n <span className=\"pbd-label\">{sayKey(key)}</span>\n <span className=\"pbd-bar\">\n <span\n className={`pbd-fill${ink ? ' is-toned' : ''}`}\n style={{\n width: `${goal ? Math.round(Math.min(1, Math.max(0, reached ?? 0)) * 100) : barShare(row[countName], largest)}%`,\n ...(ink ? { ['--bar-ink' as string]: ink } : {}),\n }}\n />\n </span>\n <span className=\"pbd-count\">\n {sayRow(row[countName])}\n {target !== undefined && (\n <span className=\"pbd-goal\">\n {' '}\n {sayCopy('ofTarget', { reached: formatPercent(reached! * 100, { maximumFractionDigits: 0 }), goal: say(target) })}\n </span>\n )}\n </span>\n </>\n );\n /* A row that goes somewhere is a button; one that cannot (a null\n group, no drill) stays text — no dead cursors. */\n const link = drill && key != null ? drill.link(key) : undefined;\n const title = sayCopy('openTableWhereBy', { table: section.table ?? '', by: section.by ?? '', key: String(key) });\n if (link)\n return (\n <a key={i} className=\"pbd-row pbd-drill\" href={link.href} title={title} onClick={link.onClick}>\n {parts}\n </a>\n );\n return drill && key != null ? (\n <button key={i} type=\"button\" className=\"pbd-row pbd-drill\" title={title} onClick={() => drill(key)}>\n {parts}\n </button>\n ) : (\n <div key={i} className=\"pbd-row\">\n {parts}\n </div>\n );\n })}\n </div>\n );\n});\n\n/**\n * A funnel: how many of a table's rows reach each stage, in order. The stages are counted in one statement\n * (shared/funnel.ts), so a later stage is never longer than the one before it. A stage opens the rows that reached it,\n * and the figure it lost opens the rows that stopped there — where the language can say them exactly.\n */\nconst FunnelSection = memo(function FunnelSection({ section }: { section: Section }) {\n const data = useBreakdown(funnelText(section), section.table);\n const say = sayer(section);\n const stages = section.stages ?? [];\n if (data.isError) return <Problem text={(data.error as Error).message} />;\n const row = data.data?.rows?.[0];\n if (row && !Number(row[stageColumn(0)]) && section.emptyMode === 'hide') return <LeaveOut />;\n const target = drillTarget(section);\n const door = (query: string | undefined): FunnelDoor | undefined => {\n if (target === null || !section.table) return undefined;\n if (query === undefined) return undefined;\n const text = `${section.table} ${andQuery(section.query, query)}`.trim();\n if (target === undefined) return { open: () => go(tableView(section.table, text), 'push') };\n const entry = listEntry(target, text);\n return entry ? { link: listLink(target, text), open: () => go(entry, 'push') } : undefined;\n };\n const chains = funnelChains(stages);\n const basis = funnelBasis(stages);\n return (\n <Funnel\n table={section.table ?? ''}\n say={say}\n steps={stages.map((stage, i) => ({\n title: stage.label,\n optional: stage.optional,\n count: row ? Number(row[stageColumn(i)]) || 0 : undefined,\n basis: basis[i],\n reached: door(chains[i] || ''),\n dropped: door(droppedQuery(stages, i)),\n }))}\n />\n );\n});\n\n/**\n * A breakdown drawn as steps: a card for each value of the column, in its\n * own order (the vocabulary's, else the counts'), joined by arrows — orders\n * received, picked, packed, shipped. A step's mark is the value's icon from\n * the column's display rule, in its tone; one without an icon has no mark (a number beside the count read as a second count).\n * A step goes to its list as a breakdown's row does. Every value of the\n * vocabulary is a step, so a stage with nothing in it still holds its place.\n */\nconst StepCards = memo(function StepCards({ section }: { section: Section }) {\n const data = useBreakdown(breakdownText(section, askedFor(section)), section.table);\n const drill = drillFor(section);\n const say = sayer(section);\n const vocabulary = vocabularyOf(section.table, section.by);\n const rule = columnDisplay(section.table ?? '', section.by ?? '') as DisplayRule | null;\n const sayKey = sayGroup(section.table, section.by);\n if (data.isError) return <Problem text={(data.error as Error).message} />;\n const [keyName = '', countName = ''] = data.data?.columns ?? [];\n const counted = data.data ? orderGroups(data.data.rows ?? [], keyName, countName, vocabulary) : [];\n const keys = vocabulary ?? counted.map((row) => row[keyName]);\n const countOf = new Map(counted.map((row) => [String(row[keyName]), row[countName]]));\n const steps = keys.filter((key) => key != null).slice(0, section.limit ?? 8);\n if (data.data && !steps.length) return section.emptyMode === 'hide' ? <LeaveOut /> : <Nothing text={sayCopy('nothingToCountYet')} />;\n // Rows of four or fewer, as even as the count allows (eight steps are two rows of four, not six and two): the\n // columns are named here so a step that starts a row is known to the looks that part the cells with hairlines.\n const cols = steps.length <= 4 ? Math.max(steps.length, 1) : Math.ceil(steps.length / Math.ceil(steps.length / 4));\n return (\n <ol\n className=\"dash-steps\"\n style={{ ['--steps' as string]: Math.max(steps.length, 1), ['--cols' as string]: cols }}\n aria-busy={!data.data || undefined}\n >\n {steps.map((key, index) => {\n const text = String(key);\n const { tone } = ruleSays(rule, text);\n const icon = rule?.icons && Object.hasOwn(rule.icons, text) ? (rule.icons[text] as AppIconName) : undefined;\n const note = section.notes?.[text];\n const figure = data.data ? say(countOf.get(text) ?? 0) : '\\u00a0';\n const body = (\n <>\n {icon && (\n <span className={`dash-step-mark${tone ? ` tone-${tone}` : ''}`} aria-hidden=\"true\">\n <Icon name={icon} size={16} />\n </span>\n )}\n <span className=\"dash-step-words\">\n <span className=\"dash-step-title\">{sayKey(key)}</span>\n {note && <span className=\"dash-step-note\">{note}</span>}\n </span>\n <span className=\"dash-step-figure\">{figure}</span>\n </>\n );\n return (\n <li\n key={text}\n className={`dash-step${tone ? ` is-${tone}` : ''}${index % cols === 0 ? ' is-row-start' : ''}${icon ? '' : ' no-mark'}`}\n >\n {drill ? (\n (() => {\n const link = drill.link(key);\n const title = sayCopy('openTableWhereBy', { table: section.table ?? '', by: section.by ?? '', key: text });\n return link ? (\n <a className=\"dash-step-card\" href={link.href} title={title} onClick={link.onClick}>\n {body}\n </a>\n ) : (\n <button type=\"button\" className=\"dash-step-card\" title={title} onClick={() => drill(key)}>\n {body}\n </button>\n );\n })()\n ) : (\n <div className=\"dash-step-card\">{body}</div>\n )}\n {index < steps.length - 1 && <Icon name=\"caret-right\" size={14} className=\"dash-step-arrow\" />}\n </li>\n );\n })}\n </ol>\n );\n});\n\n/**\n * A chart is a breakdown drawn instead of listed: same fetch, same\n * grammar, the rows handed to the SVG. Money measures speak money in the\n * ticks, the tooltips and the legend, through the same rule as everywhere.\n */\n/** The unit an `auto` chart chose, in words. */\nconst sayUnit = (unit: 'day' | 'week' | 'month' | 'quarter'): string =>\n unit === 'day' ? sayCopy('byDay') : unit === 'week' ? sayCopy('byWeek') : unit === 'month' ? sayCopy('byMonth') : sayCopy('byQuarter');\n\nconst Chart = memo(function Chart({ section }: { section: Section }) {\n /* Stacked bars cross two keys, as a matrix does: every cross is fetched\n and the chart keeps the longest bars, so `limit` counts bars, not rows. */\n const stacked = section.shape === 'stacked';\n const donut = section.shape === 'donut';\n const nothing = useNothing(inAppMode() ? sayCopy('nothingToDrawYet') : sayCopy('noToDraw', { table: section.table ?? '' }));\n /* Bars over categories are ordered here, as a donut's slices are, so they ask for every group first. */\n /* `auto` (autoChart.ts): the unit is chosen from the window and the data, so what is asked is the section in that\n unit (or nothing, while the data's extent is read), and what is drawn is the answer coarsened to it. */\n const auto = useAutoChart(section, (text) => useBreakdown(text, section.table));\n const data = useBreakdown(\n auto ? (auto.ask ? breakdownText(auto.ask, chartLimit(section)) : null) : breakdownText(section, chartLimit(section)),\n section.table,\n );\n const drawn = auto?.draw(data);\n const answer = auto ? drawn?.answer : data.data;\n const [firstKey = '', secondKey = ''] = (section.by ?? '').split(',').map((key) => key.trim());\n if (data.isError) return <Problem text={(data.error as Error).message} />;\n const label = namedGroups(answer, answer?.columns?.[0], sayGroup(section.table, firstKey));\n const seriesLabel = namedGroups(answer, secondKey ? answer?.columns?.[1] : undefined, sayGroup(section.table, secondKey));\n if (section.emptyMode === 'hide' && answer && !(answer.rows ?? []).length) return <LeaveOut />;\n /* The unit the chart chose, said as text under the title: the slot is held from the first paint so naming it moves nothing. */\n const unitNote = auto ? <p className=\"chart-unit\">{drawn?.unit ? sayUnit(drawn.unit) : null}</p> : null;\n if (section.shape && EXTRA_SHAPES.includes(section.shape))\n return (\n <>\n {unitNote}\n <ChartShapeFigure\n shape={section.shape as ExtraShape}\n answer={answer}\n say={sayer(section).among((answer?.rows ?? []).map((row) => row[answer?.columns?.at(-1) ?? '']))}\n /* The section's `format` and `unit` say its measure, the one up the side; the across measure is said by its own column. */\n sayX={section.x ? sayer({ ...section, measure: section.x, format: undefined, unit: undefined }) : undefined}\n names={{ x: section.x ?? '', y: section.measure ?? 'count' }}\n label={label}\n seriesLabel={seriesLabel}\n vocabulary={vocabularyOf(section.table, firstKey)}\n seriesVocabulary={secondKey ? vocabularyOf(section.table, secondKey) : undefined}\n limit={section.limit}\n target={typeof section.target === 'number' ? section.target : undefined}\n height={section.height}\n empty={nothing.text}\n emptyDetail={nothing.detail}\n emptyAction={nothing.action}\n />\n </>\n );\n return (\n <>\n {unitNote}\n <ChartFigure\n answer={answer}\n dots={drawn?.dots}\n shape={section.shape as 'line' | 'bar' | 'donut' | 'stacked' | undefined}\n limit={section.limit}\n target={typeof section.target === 'number' ? section.target : undefined}\n height={section.height}\n say={sayer(section)}\n label={label}\n seriesLabel={seriesLabel}\n vocabulary={vocabularyOf(section.table, firstKey)}\n seriesVocabulary={secondKey ? vocabularyOf(section.table, secondKey) : undefined}\n scale={orderOf(section.table, firstKey).scale}\n seriesScale={secondKey ? orderOf(section.table, secondKey).scale : undefined}\n seriesTone={\n stacked && secondKey\n ? (key) => ruleSays(columnDisplay(section.table ?? '', secondKey) as DisplayRule | null, key).tone\n : undefined\n }\n tone={\n (donut || section.shape === 'bar') && firstKey && !/\\s/.test(firstKey)\n ? (key) => ruleSays(columnDisplay(section.table ?? '', firstKey) as DisplayRule | null, key).tone\n : undefined\n }\n sayLegend={stacked ? (totals) => legendSayer(section, totals) : undefined}\n onPick={\n donut || section.shape === 'line'\n ? drillFor(section)\n : stacked && !/\\s/.test(firstKey)\n ? drillFor({ ...section, by: firstKey })\n : null\n }\n empty={nothing.text}\n emptyDetail={nothing.detail}\n emptyAction={nothing.action}\n curve={section.curve}\n total={section.total}\n />\n </>\n );\n});\n\n/**\n * A matrix: the measure crossed over two keys — rows by the first,\n * columns by the second, heat by the value. The pivot happens here (the\n * breakdown answers flat groups), columns sort ascending when they read\n * as dates and by weight otherwise, and the biggest cell sets the scale.\n */\n/**\n * Whether a matrix wider than its section is folded: each row said as its figures, each under its column's name,\n * rather than scrolled sideways (docs/design.md: nothing scrolls sideways inside a section). Its natural width is\n * read while it stands as a table, so it stands as one again when the room grows to hold it; `shape` is its rows\n * and columns, a change of which reads the width afresh.\n */\nfunction useMatrixFold(host: { current: HTMLDivElement | null }, shape: string): boolean {\n const [fold, setFold] = useState<{ shape: string; natural: number } | null>(null);\n useLayoutEffect(() => {\n const element = host.current;\n if (!element) return;\n const judge = () => {\n const table = element.querySelector('table');\n if (!table) return;\n const natural = fold?.shape === shape ? fold.natural : table.offsetWidth;\n const folds = natural > element.clientWidth + 1;\n setFold((was) => (folds ? (was?.shape === shape && was.natural === natural ? was : { shape, natural }) : null));\n };\n judge();\n const observer = new ResizeObserver(judge);\n observer.observe(element);\n return () => observer.disconnect();\n }, [host, shape, fold]);\n return fold?.shape === shape;\n}\n\nconst Matrix = memo(function Matrix({ section }: { section: Section }) {\n const data = useBreakdown(breakdownText(section, 400), section.table);\n const host = useRef<HTMLDivElement>(null);\n const shape = `${data.data?.rows?.length ?? 0}:${(data.data?.columns ?? []).join(',')}`;\n const folded = useMatrixFold(host, shape);\n if (data.isError) return <Problem text={(data.error as Error).message} />;\n if (!data.data) return <div className=\"matrix-host\" ref={host} />;\n const [rowKey, colKey, valueName] = data.data.columns ?? [];\n const cells = new Map<string, unknown>();\n const rowTotals = new Map<string, number>();\n const colTotals = new Map<string, number>();\n for (const r of data.data.rows ?? []) {\n const a = r[rowKey] == null ? '—' : String(r[rowKey]);\n const b = r[colKey] == null ? '—' : String(r[colKey]);\n const v = Number(r[valueName]) || 0;\n cells.set(`${a}\\u0000${b}`, r[valueName]);\n rowTotals.set(a, (rowTotals.get(a) ?? 0) + v);\n colTotals.set(b, (colTotals.get(b) ?? 0) + v);\n }\n if (!cells.size)\n return section.emptyMode === 'hide' ? (\n <LeaveOut />\n ) : (\n <Nothing text={inAppMode() ? sayCopy('nothingToCrossYet') : sayCopy('noToCross', { table: section.table ?? '' })} />\n );\n /* Rows in the first key's vocabulary order where it has one (a stage reads\n as a pipeline), else heaviest first; ten at most. */\n const rowKeyColumn = (section.by ?? '').split(',')[0].trim();\n const rows = orderGroups(\n [...rowTotals.entries()].map(([key, total]) => ({ key, total })),\n 'key',\n 'total',\n vocabularyOf(section.table, rowKeyColumn),\n )\n .slice(0, 10)\n .map(({ key }) => key);\n const dated = [...colTotals.keys()].every((k) => /^\\d{4}(-\\d{2})?/.test(k) || k === '—');\n /* Columns as the rows are: in the second key's vocabulary order where it\n has one (low, medium, high, urgent), else heaviest first; and said in\n its words, as a breakdown says them (\"Urgent\", not \"urgent\"). */\n const colKeyColumn = ((section.by ?? '').split(',')[1] ?? '').trim();\n const cols = dated\n ? [...colTotals.keys()].sort()\n : orderGroups(\n [...colTotals.entries()].map(([key, total]) => ({ key, total })),\n 'key',\n 'total',\n vocabularyOf(section.table, colKeyColumn),\n )\n .slice(0, 12)\n .map(({ key }) => key);\n const sayCol = namedGroups(data.data, colKey, sayGroup(section.table, colKeyColumn));\n const max = Math.max(...rows.flatMap((a) => cols.map((b) => Number(cells.get(`${a}\\u0000${b}`)) || 0)), 1);\n /* One form across the grid: where any cell reaches a thousand every cell is said compact, so \"$4,470\" never\n stands beside \"$548K\". The cell's title says the figure whole. */\n const sayWhole = sayer(section);\n const say = max >= 1000 ? sayWhole.tick : sayWhole;\n const firstKey = (section.by ?? '').split(',')[0].trim();\n const sayRow = namedGroups(data.data, rowKey, sayGroup(section.table, firstKey));\n const drill = !/\\s/.test(firstKey) ? drillFor({ ...section, by: firstKey }) : null;\n const colLabel = (b: string, at: number) => (dated ? periodTick(b, at ? cols[at - 1] : undefined) : sayCol(b === '—' ? null : b));\n /* Folded, the rows and cells are drawn as a grid, which drops a table's own roles: they are said, so a reader\n still hears each figure under its row and column. */\n return (\n <div className=\"matrix-host\" ref={host} data-fold={folded || undefined}>\n <div className=\"table-wrap matrix-wrap\">\n <table className=\"matrix\" role=\"table\">\n <thead role=\"rowgroup\">\n <tr role=\"row\">\n <th className=\"matrix-corner\" role=\"columnheader\" />\n {cols.map((b, at) => (\n <th key={b} className=\"matrix-col\" role=\"columnheader\">\n {colLabel(b, at)}\n </th>\n ))}\n </tr>\n </thead>\n <tbody role=\"rowgroup\">\n {rows.map((a) => (\n <tr key={a} role=\"row\">\n <th className=\"matrix-row\" role=\"rowheader\">\n {drill ? (\n <button type=\"button\" className=\"matrix-drill\" onClick={() => drill(a)}>\n {sayRow(a)}\n </button>\n ) : (\n <span>{sayRow(a)}</span>\n )}\n </th>\n {cols.map((b, at) => {\n const raw = cells.get(`${a}\\u0000${b}`);\n const v = Number(raw) || 0;\n /* Heat says weight; the number stays the fact. Empty stays\n empty — a zero someone wrote and a cross nobody made are\n different silences. */\n return (\n <td\n key={b}\n className=\"matrix-cell\"\n role=\"cell\"\n data-label={folded ? String(colLabel(b, at) ?? '') : undefined}\n style={\n v\n ? ({\n /* Its share of the heaviest; features.css tints it up to the palette's heat top. */\n '--heat': (v / max).toFixed(3),\n background: 'var(--heat-fill)',\n } as CSSProperties)\n : undefined\n }\n title={v ? `${sayRow(a)} × ${dated ? b : sayCol(b === '—' ? null : b)}: ${sayWhole(raw)}` : undefined}\n >\n {v ? say(raw) : ''}\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n );\n});\n\n/* ---------- list and board ---------- */\n\n/**\n * The full list, with its tabs and filters. An embed opens its view's own\n * room — its tabs, its presentation, its actions — on the rows the section\n * shows; any other section, the list its table and query suggest.\n */\nfunction OpenFull({ section }: { section: Section }) {\n useSyncExternalStore(subscribeMessages, messageLanguage, messageLanguage);\n return (\n <button\n type=\"button\"\n className=\"ghost dash-open\"\n title={sayCopy('theFullListWithItsTabs')}\n onClick={() => go({ ...tableView(section.table, fullQuery(section)), ...(section.view ? { view: section.view } : {}) }, 'push')}\n >\n {message('list.viewAll')}\n </button>\n );\n}\n\n/** A column a list says, a label path dressed as the column it ends in. */\nfunction columnAt(table: TableMeta | undefined, name: string): ColumnMeta | undefined {\n if (!table) return undefined;\n if (!name.includes('.')) return table.columns.find((column) => column.name === name);\n const [reference, terminal] = name.split('.');\n const fk = (refsFrom(table.id) as Array<{ from: { columns: string[] }; to: { table: string } }>).find(\n (candidate) => candidate.from.columns.length === 1 && candidate.from.columns[0] === reference,\n );\n const target = fk ? (findTable(fk.to.table) as TableMeta | undefined) : undefined;\n const column = target?.columns.find((candidate) => candidate.name === terminal);\n return column ? { ...column, name } : undefined;\n}\n\n/**\n * A list in the aside: names, not a table. The aside is a narrow column,\n * and a grid there cut its names short (\"Riley C…\") to keep columns nobody\n * compares. Each row is its first column, whole and wrapping; the second a\n * quiet line under it; a third a value at the row's end. The row opens its\n * record, the month's other rows its neighbours.\n */\nfunction AsideRows({\n section,\n table,\n query,\n empty,\n onRows,\n}: {\n section: Section;\n table: TableMeta | undefined;\n query: string;\n empty?: ReactNode;\n onRows: (data: { total?: number; exactTotal?: boolean }) => void;\n}) {\n const rows = useQuery<Rows & { total?: number; exactTotal?: boolean; errors?: Array<{ message: string }> }>({\n queryKey: ['run', query, section.limit ?? 5],\n queryFn: () => batchedRun({ q: query, limit: section.limit ?? 5, offset: 0 }),\n refetchInterval: minuteTick(query, section.table),\n staleTime: TILE_FRESH,\n placeholderData: keepPreviousData,\n });\n const data = rows.data;\n useEffect(() => {\n if (data && !data.errors?.length) onRows(data);\n }, [data]); // eslint-disable-line react-hooks/exhaustive-deps\n const [first, second, third] = section.show?.length ? section.show : table ? [labelColumn(table) ?? primaryKey(table)[0]] : [];\n /* A person named first wears their photo where the rule names one (avatarPhotos.tsx). */\n const nameRule = first ? (columnDisplay(section.table, first) as DisplayRule | null) : null;\n const photoOwner = first ? avatarOwner(table, first, nameRule, data?.rows?.length ? Object.keys(data.rows[0]) : undefined) : undefined;\n const photoOf = useAvatarPhotos(first ? [{ name: first, display: nameRule, photoOwner }] : [], data?.rows ?? []);\n if (rows.isError || data?.errors?.length) return <Problem text={(rows.error as Error | null)?.message ?? data!.errors![0].message} />;\n if (!data) return <div className=\"dash-mini\" />;\n const got = data.rows ?? [];\n if (!got.length) return <>{empty ?? <Empty text={message('list.nothing')} />}</>;\n const [name, line, value] = [first, second, third].map((path) => (path ? columnAt(table, path) : undefined));\n const pk: string[] = table ? primaryKey(table) : [];\n /* A reference says its record's name, which the section fetched beside it (List). */\n const referenceLabels = table && section.show?.length ? referenceNames(section.table as string, section.show) : undefined;\n const said = (column: ColumnMeta | undefined, row: Row) => {\n if (!column || !table) return null;\n const { column: drawn, value } = namedCell(table, column.name, row, referenceLabels);\n return value != null && value !== '' ? <Value tableId={section.table} col={drawn} value={value} compact /> : null;\n };\n const named = (row: Row) => {\n const photo = photoOwner && name ? photoOf(first, row[photoOwner]) : undefined;\n return photo && name && row[name.name] != null ? <AvatarText text={String(row[name.name])} photo={photo} /> : said(name, row);\n };\n const keyed = got.map((row) => ({ row, key: Object.fromEntries(pk.map((k) => [k, row[k]])), label: String(row[first] ?? '') }));\n const records = keyed.map(({ key, label }) => ({ key, label }));\n return (\n <ul className=\"dash-mini\" aria-label={section.title ?? section.table}>\n {keyed.map(({ row, key, label }, i) => (\n <li key={i}>\n <button\n type=\"button\"\n className=\"dash-mini-row\"\n disabled={!pk.length}\n onClick={() => void openRecord(section.table, key, label, 'push', { records })}\n >\n <span className=\"dash-mini-text\">\n <span className=\"dash-mini-name\">{named(row) ?? label}</span>\n {said(line, row) && <span className=\"dash-mini-line\">{said(line, row)}</span>}\n </span>\n {said(value, row) && <span className=\"dash-mini-value\">{said(value, row)}</span>}\n </button>\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * A list is the real table view with the chrome off — the vanilla grid,\n * drawn into a host. Its own stat row (count, timing, Export) is hidden\n * by CSS in here; the one number worth keeping — how many there are in\n * all — moves up beside the title once the answer knows it. In the aside\n * it is names instead (AsideRows), unless it embeds a view drawn its own way.\n */\nconst List = memo(function List({ section, aside = false, period }: { section: Section; aside?: boolean; period?: ReactNode }) {\n const [count, setCount] = useState('');\n /* How many the section matched, once known: \"View all\" over none is a door to an empty room. */\n const [matched, setMatched] = useState<number | undefined>();\n const table = findTable(section.table) as TableMeta | undefined;\n /* An explicit view embed keeps the dashboard's already-resolved question,\n but borrows the served view's dress and every column that dress reads.\n A raw dashboard list has no source view, so it stays the vanilla grid. */\n const app = activeApp();\n const room = section.view === undefined || !app ? undefined : viewRoom(app, section.view);\n const source = room && isListRoom(room) && room.table === section.table ? room : undefined;\n // A narrower dashboard question cannot promise the whole source list is empty.\n /* The section's own guidance first: a rows section may say what belongs in it, as a list view does. */\n const authoredEmpty = (section as { empty?: AppListEmpty }).empty;\n const sourceEmpty = authoredEmpty ? (\n <ListEmpty spec={authoredEmpty} />\n ) : source?.empty &&\n splitQuery(`rows ${source.query ?? ''}`).filter.trim() === splitQuery(`rows ${section.query ?? ''}`).filter.trim() ? (\n <ListEmpty spec={source.empty} />\n ) : undefined;\n /* The key columns ride along unseen when the section projects, the same\n bargain the app list strikes: a row with no key on it is a row that\n cannot open, and \"see the record\" is the whole point of a list. A\n reference is drawn by its record's name, fetched beside it and kept out\n of sight (shared/dashboardAsks.ts, whose words a first page is asked in). */\n const { query, keys, named, referenceLabels } = dashboardListQuery(lookups, section, source?.presentation);\n const onRows = (data: { total?: number; exactTotal?: boolean }) => {\n setMatched(data.total);\n if (!data.total) {\n setCount('');\n return;\n }\n setCount(data.exactTotal === false ? `~${formatApprox(data.total)}` : sayCopy('figureInAll', { figure: figure(data.total) }));\n };\n const presented = source?.presentation && source.presentation.kind !== 'split';\n const mini = aside && !presented && (section.show?.length ?? 0) <= 3;\n /* An embed that opted in works as its room does, under this heading (DashboardList.tsx). */\n const works = section.interactive && source && table;\n return (\n <>\n {section.emptyMode === 'hide' && matched === 0 && <LeaveOut />}\n <div className=\"dash-list-head\">\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title ?? section.table}\n </h2>\n <span className=\"stat dash-count\">{count}</span>\n {period}\n {matched !== 0 && <OpenFull section={section} />}\n </div>\n {works ? (\n <div className=\"dash-list dash-list-works\">\n <InteractiveList section={section} source={source} onTotal={(total: number | undefined) => onRows({ total })} />\n </div>\n ) : mini ? (\n <AsideRows section={section} table={table} query={query} empty={sourceEmpty} onRows={onRows} />\n ) : (\n <div className=\"dash-list\">\n <TableRoom\n entry={{ kind: 'table', table: section.table as string, query }}\n sizing={section.sizing}\n chrome={false}\n interactive={false}\n embedded\n hide={[...keys, ...named]}\n referenceLabels={referenceLabels}\n labels={section.labels}\n recordNavigation={source?.presentation?.kind === 'cards' || source?.presentation?.kind === 'queue'}\n {...(section.rowActions &&\n app &&\n mayRunAny(app, section.table as string, offeredBy(resourceOf(app, section.table as string)).actions ?? [])\n ? { rowActions: true, actions: offeredBy(resourceOf(app, section.table as string)).actions }\n : {})}\n presentation={source?.presentation}\n present={shell().present ?? undefined}\n listLabel={source?.label}\n order={source?.order}\n empty={sourceEmpty}\n export={exportOffered(app, section.table as string | undefined) ? undefined : false}\n onResult={onRows}\n />\n </div>\n )}\n </>\n );\n});\n\n/**\n * A board: lanes of cards by a column's values — the pipeline read every\n * CRM and queue screen is built around, here as one word of config. The\n * lanes are the column's declared vocabulary when the schema states one\n * (every stage shows, empty ones included — an empty lane is a fact),\n * and the observed values by weight when it does not. Read-only on\n * purpose: this layer curates reading, and a drag that writes belongs\n * to the write arc.\n */\nconst Board = memo(function Board({ section: authored }: { section: Section }) {\n const section = boardSection(authored);\n const table = findTable(section.table) as TableMeta | undefined;\n const counts = useBreakdown(boardCountText(section), section.table);\n const pk: string[] = table ? primaryKey(table) : [];\n const naming = table && labelColumn(table);\n const shown: string[] = section.show?.length ? section.show : naming ? [naming] : pk;\n const rule = columnDisplay(section.table, section.by);\n let lanes: ReactNode;\n if (counts.isError) lanes = <Problem text={(counts.error as Error).message} />;\n else if (counts.data) {\n const [keyName, countName] = counts.data.columns ?? [];\n const byValue = new Map(\n (counts.data.rows ?? []).filter((r) => r[keyName] != null).map((r) => [String(r[keyName]), Number(r[countName]) || 0] as const),\n );\n const vocabulary = (table?.columns.find((c) => c.name === section.by) as (ColumnMeta & { allowed?: string[] }) | undefined)?.allowed;\n const values = section.lanes ?? (vocabulary ?? [...byValue.keys()]).slice(0, 8);\n lanes = values.length ? (\n values.map((value) => (\n <Lane key={value} section={section} value={value} count={byValue.get(value) ?? 0} rule={rule} pk={pk} shown={shown} />\n ))\n ) : (\n <Empty text={inAppMode() ? sayCopy('nothingToLayOut') : sayCopy('noToLayOut', { table: section.table ?? '' })} />\n );\n }\n const nothingOnIt =\n Boolean(counts.data) && [...(counts.data?.rows ?? [])].every((r) => !(Number(r[counts.data?.columns?.[1] ?? '']) || 0));\n return (\n <>\n {authored.emptyMode === 'hide' && nothingOnIt && <LeaveOut />}\n <div className=\"board-head\">\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title ?? `${section.table} by ${section.by}`}\n </h2>\n <OpenFull section={section} />\n </div>\n <div className=\"dash-board\">{lanes}</div>\n </>\n );\n});\n\nfunction Lane({\n section,\n value,\n count,\n rule,\n pk,\n shown,\n}: {\n section: Section;\n value: string;\n count: number;\n rule: unknown;\n pk: string[];\n shown: string[];\n}) {\n const laneLimit = section.limit ?? 7;\n const laneQuery = andQuery(section.query, `${section.by} = ${quote(value)}`);\n const q = count\n ? [section.table, laneQuery, section.sort ? `sort ${section.sort}` : '', `show ${[...new Set([...shown, ...pk])].join(', ')}`]\n .filter(Boolean)\n .join(' ')\n : null;\n const rows = useRows(q, laneLimit, section.table);\n const got = rows.data?.rows ?? [];\n const [head, ...rest] = shown;\n return (\n <div className=\"board-lane\">\n <div className=\"board-lane-head\">\n {dressFor(rule as DisplayRule | null, value) ? (\n <Dressed dress={dressFor(rule as DisplayRule | null, value)!} compact={(rule as DisplayRule | null)?.format === 'richText'} />\n ) : (\n <span className=\"board-lane-name\">{value}</span>\n )}\n <span className=\"board-lane-count\">{figure(count)}</span>\n </div>\n <div className=\"board-cards\">\n {got.map((row: Row, i) => {\n const key = Object.fromEntries(pk.map((k) => [k, row[k]]));\n const said =\n row[head] == null\n ? '—'\n : (maskedText(columnDisplay(section.table, head) as DisplayRule | null, row[head]) ?? String(row[head]));\n return (\n <button key={i} type=\"button\" className=\"board-card\" onClick={() => void openRecord(section.table, key, said, 'push')}>\n <span className=\"board-card-title\">{said}</span>\n {rest.map((path) => {\n const v = row[path];\n if (v === null || v === undefined) return null;\n const dress = dressFor(columnDisplay(section.table, path) as DisplayRule | null, v);\n return (\n <span key={path} className=\"board-card-line\">\n {dress ? <Dressed dress={dress} compact={dress.kind === 'richText'} /> : <span>{String(v)}</span>}\n </span>\n );\n })}\n </button>\n );\n })}\n {count > got.length && rows.data && (\n <button\n type=\"button\"\n className=\"ghost board-more\"\n onClick={() => go(tableView(section.table, `${section.table} ${laneQuery}`), 'push')}\n >\n {sayCopy('moreCount', { figure: figure(count - got.length) })}\n </button>\n )}\n </div>\n </div>\n );\n}\n\n/* ---------- the controls ---------- */\n\n/**\n * The window picker: the unpicked state and the dashboard's offered phrases.\n * Unpicked is \"All time\" only when it is: where a section keeps a window of\n * its own (`close_date = last 90 days`), the pressed \"All time\" sat over\n * figures still counting their ninety days, so it says \"Default\" there, and\n * each figure says its own window (windowTitle, metricWindow).\n */\nfunction WindowRow({\n windows,\n current,\n onPick,\n ownWindows,\n control = 'segmented',\n}: {\n windows: string[];\n current: string | null;\n onPick: (w: string | null) => void;\n ownWindows: boolean;\n control?: 'segmented' | 'button';\n}) {\n const word = (w: string | null) => (w ? w.charAt(0).toUpperCase() + w.slice(1) : sayCopy(ownWindows ? 'defaultWindow' : 'allTimeWindow'));\n if (control === 'button') {\n /* The dates the window covers, its last day inclusive (the window's end is the next day's start); a phrase the\n calendar cannot place is said as itself. */\n const span = current ? dateWindow(current, new Date()) : undefined;\n const shown = span\n ? sayCopy('windowRange', {\n from: formatDate(span.start, { month: 'short', day: 'numeric' }),\n to: formatDate(new Date(span.end.getTime() - 86_400_000), { month: 'short', day: 'numeric', year: 'numeric' }),\n })\n : word(current);\n return (\n <DropMenu\n className=\"dash-window-menu\"\n triggerClassName=\"dash-window-button\"\n triggerLabel={sayCopy('pickWindow', { window: word(current) })}\n label={\n <>\n <Icon name=\"calendar-blank\" size={15} className=\"dash-window-icon\" />\n <span className=\"dash-window-range\">{shown}</span>\n <Icon name=\"caret-down\" size={12} className=\"dash-window-caret\" />\n </>\n }\n popupClassName=\"more-list dash-window-list\"\n align=\"end\"\n >\n {[null, ...windows].map((w) => (\n <DropItem key={w ?? ''} className=\"more-item\" onClick={() => onPick(w)}>\n <span className=\"more-tick\" aria-hidden=\"true\">\n {w === current ? '✓' : ''}\n </span>\n <span className=\"more-label\">{word(w)}</span>\n </DropItem>\n ))}\n </DropMenu>\n );\n }\n return (\n <div className=\"dash-windows\" role=\"group\" aria-label={sayCopy('timeWindow')}>\n {[null, ...windows].map((w) => (\n <button key={w ?? ''} type=\"button\" className=\"dash-window\" aria-pressed={w === current} onClick={() => onPick(w)}>\n {word(w)}\n </button>\n ))}\n </div>\n );\n}\n\n/**\n * The pick controls: one quiet dropdown per configured column. A\n * vocabulary column offers its own values; a whole single-column\n * reference offers the records it points at, said by name and filtered\n * by id — nobody picks an owner by remembering 7.\n */\nfunction Pick({\n dashboard,\n column,\n picks,\n onChange,\n}: {\n dashboard: DashboardDef;\n column: string;\n picks: Picks;\n onChange: (column: string, value: string) => void;\n}) {\n const home = [...dashboard.sections, ...(dashboard.aside ?? [])].find(\n (s) => s.table && (findTable(s.table) as TableMeta | undefined)?.columns.some((c) => c.name === column),\n );\n const table = home && (findTable(home.table) as TableMeta | undefined);\n const meta = table?.columns.find((c) => c.name === column) as (ColumnMeta & { allowed?: string[] }) | undefined;\n /* A reference: the values are the target's records. Fifty at most —\n a filter over more rows than a dropdown holds wants the list page's\n boxes, not this control. */\n const fk =\n table && !meta?.allowed?.length\n ? (refsFrom(table.id) as Array<{ from: { columns: string[] }; to: { table: string } }>).find(\n (f) => f.from.columns.length === 1 && f.from.columns[0] === column,\n )\n : undefined;\n const target = fk && (findTable(fk.to.table) as TableMeta | undefined);\n const naming = target ? labelColumn(target) : undefined;\n const pk = target ? primaryKey(target)[0] : undefined;\n const q = pickQuery(lookups, [...dashboard.sections, ...(dashboard.aside ?? [])], column);\n const records = useRows(q, 50);\n if (!meta || !table) return null;\n if (!meta.allowed?.length && !naming) return null;\n const label = (labelColumn(table) === column ? column : column.replace(/_id$/, '')).replace(/_/g, ' ');\n const items = meta.allowed?.length\n ? meta.allowed.map((v) => ({ value: v, label: groupLabel(columnDisplay(table!.id, column) as DisplayRule | null, v, meta.allowed) }))\n : (records.data?.rows ?? []).map((r) => ({ value: String(r[pk!]), label: String(r[naming!] ?? r[pk!]) }));\n return (\n <span className=\"dash-pick\">\n <Dropdown\n items={[{ value: '', label: sayCopy('any', { label }) }, ...items]}\n value={picks[column] ?? ''}\n ariaLabel={sayCopy('filter', { label })}\n onChange={(value) => onChange(column, value)}\n />\n </span>\n );\n}\n\n/* ---------- the screen ---------- */\n\nconst NO_PERIODS: Periods = {};\nconst NO_SECTIONS: ReadonlySet<number> = new Set();\n\n/* A section over the window the reader picked, where all time is the unpicked state: widening it is offered by whatever\n is empty inside it, so \"Nothing to count yet.\" after a 90-day pick does not read as an empty table. */\nconst AllTimeOffer = createContext<{ window: string; showAll: () => void } | null>(null);\n\n/** An empty section's words: the plain sentence, or under a window picked, that it is empty there and a way to see all time. */\nfunction useNothing(plain: string): { text: string; detail?: string; action?: ReactNode } {\n const offer = useContext(AllTimeOffer);\n if (!offer) return { text: plain };\n return {\n text: sayCopy('nothingInThisTimeWindow'),\n detail: offer.window.charAt(0).toUpperCase() + offer.window.slice(1),\n action: (\n <Button intent=\"quiet\" size=\"compact\" onClick={offer.showAll}>\n {sayCopy('showAllTime')}\n </Button>\n ),\n };\n}\n\n/** What a section says when it has nothing to draw. */\nfunction Nothing({ text }: { text: string }) {\n return <Empty {...useNothing(text)} />;\n}\n\nconst Sections = memo(function Sections({\n dashboard,\n sections,\n windowNow,\n picks,\n periods,\n onPeriod,\n onAllTime,\n served,\n aside = false,\n}: {\n dashboard: DashboardDef;\n sections: Section[];\n windowNow: string | null;\n picks: Picks;\n /** The periods picked on sections with windows of their own, and where a new pick goes. */\n periods: Periods;\n onPeriod: (key: string, phrase: string) => void;\n /** The window picker's unpicked state, which is all time where no section keeps a window of its own. */\n onAllTime: () => void;\n /** Each authored section's place among the dashboard's as served, which is how an activity names itself to the server. */\n served: ReadonlyMap<Section, number>;\n aside?: boolean;\n}) {\n /* Each tile is memoized and handed the section it draws, so that section\n is made once per window and pick, not on every paint: a dashboard redrew\n all its tiles each time any one of them answered, some 4,000 component\n renders to draw ten figures. */\n const resolved = useMemo(\n () =>\n sections.map((raw) => {\n /* A section with windows of its own is over the period picked in its\n heading, and its picker says which, so its title says nothing more. */\n if (raw.windows?.length) return picked(windowed(raw, sectionPeriod(raw, periods)), picks);\n /* The title says the window the figure is over (dashboardModel.ts,\n windowTitle): the reader's pick stands where the author's window was\n named, and a section the author windowed says nothing more until then. */\n const said = raw.kind === 'metric' ? metricWindow(raw.title ?? raw.table ?? '', raw, windowNow) : undefined;\n const scoped = said\n ? { ...raw, title: said.title, ...(said.note ? { windowNote: said.note } : {}) }\n : raw.over\n ? { ...raw, title: windowTitle(raw.title ?? raw.table ?? '', raw, windowNow) }\n : raw;\n return picked(windowed(scoped, windowNow), picks);\n }),\n [sections, windowNow, picks, periods],\n );\n /* Where the reader's window is what a section is over, and unpicking it is all time (the picker says \"Default\" over a\n section that keeps a window of its own), an empty section offers to widen it. */\n const widened = (section: Section) =>\n windowNow !== null && Boolean(section.over) && section.windowBase === undefined && !section.windows?.length\n ? { window: windowNow, showAll: onAllTime }\n : null;\n /* A layout places every section in an area of a grid (the aside is never beside one: the parser refuses both). */\n const layout = !aside && dashboard.areas?.length ? layoutGrid(dashboard.areas) : undefined;\n /* Sections flow into the page's rows, or into an area of the layout: the same walk over the sections of one flow. */\n const flow = (indices: number[], pairing: boolean, gate?: Gate): ReactNode[] => {\n /* Consecutive metrics coalesce into one KPI strip — the way every\n operations screen reads its top row — and everything else keeps the\n page grid's widths. */\n const out: ReactNode[] = [];\n let strip: ReactNode[] | null = null;\n const there = indices.map((i) => resolved[i]!);\n /* Charts and breakdowns the author gave no width stand two to a row where two come together: one chart a\n page wide under another a page wide made a dashboard a long scroll of short plots with white either side.\n A pair is a pair; a third alone keeps the page's width rather than standing half-empty beside nothing.\n Tables, heat maps, boards and notes keep theirs. Narrow, every half stacks (page.css). In an area nothing\n pairs: the author placed the sections, and the area is as wide as the author made it. */\n const paired = new Set<number>();\n for (let k = 0; pairing && k < there.length; k++) {\n const pairs = (section: Section | undefined) =>\n Boolean(section && (section.kind === 'chart' || section.kind === 'breakdown' || section.kind === 'funnel') && !section.width);\n if (pairs(there[k]) && pairs(there[k + 1])) {\n paired.add(indices[k]!).add(indices[k + 1]!);\n k++;\n }\n }\n /* The rows of metrics in which some card is over a time (see MetricProps.dated), by each card's index. */\n const dated = new Set<number>();\n for (let start = 0; start < there.length; start++) {\n if (there[start]!.kind !== 'metric') continue;\n let end = start;\n while (end < there.length && there[end]!.kind === 'metric') end++;\n if (there.slice(start, end).some((card) => card.windowNote)) for (let k = start; k < end; k++) dated.add(indices[k]!);\n start = end;\n }\n indices.forEach((i) => {\n const section = resolved[i]!;\n const current = sectionPeriod(section, periods);\n const period =\n current && section.windowKey ? (\n <SectionPeriod section={section} current={current} onPick={(phrase) => onPeriod(section.windowKey!, phrase)} />\n ) : undefined;\n if (section.kind === 'metric') {\n if (!strip) {\n strip = [];\n out.push(\n <section key={`strip-${i}`} className=\"page-section width-full dash-strip\">\n <div className=\"home-cards\">{strip}</div>\n </section>,\n );\n }\n /* A card that throws stands as its note in the strip; its neighbours stay. */\n strip.push(\n <ErrorBoundary key={i} fallback={(note) => <div className=\"home-card home-card-broken\">{note}</div>}>\n <Metric\n section={section}\n period={period}\n windowed={Boolean(dashboard.windows?.length) && windowNow !== null && !section.windows}\n dated={dated.has(i)}\n />\n </ErrorBoundary>,\n );\n return;\n }\n strip = null;\n const width = section.kind === 'board' ? 'full' : (section.width ?? (paired.has(i) ? 'half' : 'full'));\n let body: ReactNode;\n if (section.kind === 'note') {\n const image = section.image ? landingImage(section.image) : undefined;\n body = (\n <DashboardNote\n title={section.title}\n text={String(section.text ?? '')}\n icon={section.icon}\n action={section.action}\n variant={section.variant}\n eyebrow={section.eyebrow}\n image={image && section.image ? { src: image, alt: section.image.alt } : undefined}\n />\n );\n } else if (section.kind === 'breakdown' || section.kind === 'chart' || section.kind === 'matrix' || section.kind === 'funnel') {\n const heading = (\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title ?? `${section.table} by ${section.by}`}\n </h2>\n );\n body = (\n <>\n {period ? (\n <div className=\"dash-section-head\">\n {heading}\n {period}\n </div>\n ) : (\n heading\n )}\n {section.kind === 'chart' ? (\n <Chart section={section} />\n ) : section.kind === 'funnel' ? (\n <FunnelSection section={section} />\n ) : section.shape === 'steps' ? (\n <StepCards section={section} />\n ) : section.kind === 'matrix' ? (\n <Matrix section={section} />\n ) : (\n <BreakdownRows section={section} />\n )}\n </>\n );\n } else if (section.kind === 'board') {\n body = <Board section={section} />;\n } else if (section.kind === 'custom') {\n body = <CustomDashSection section={section} windowNow={windowNow} picks={picks} aside={aside} />;\n } else if (section.kind === 'activity') {\n body = (\n <>\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title ?? sayCopy('latestChanges')}\n </h2>\n <ActivityFeed section={section} dashboard={dashboard.id} at={served.get(sections[i]) ?? -1} />\n </>\n );\n } else if (section.kind === 'find') {\n body = (\n <>\n {section.title ? (\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title}\n </h2>\n ) : null}\n <FindSection section={section} />\n </>\n );\n } else if (section.kind === 'branding' || section.kind === 'integrations') {\n /* Alone on its page, the form is the page: the page's heading already names it, and \"Branding\" said twice\n read as two things. A title of its own that the page does not say is still drawn. */\n const alone = allSections(dashboard).length === 1 && (!section.title || section.title === dashboard.label);\n body = (\n <>\n {alone ? null : (\n <h2 className=\"page-section-title\">\n <Mark section={section} />\n {section.title ?? (section.kind === 'branding' ? sayCopy('branding') : sayCopy('integrations'))}\n </h2>\n )}\n {section.kind === 'branding' ? <BrandingForm /> : <IntegrationsForm />}\n </>\n );\n } else {\n body = <List section={section} aside={aside} period={period} />;\n }\n const app = activeApp();\n const source = section.view && app ? viewRoom(app, section.view) : undefined;\n const cards = source && isListRoom(source) && source.presentation?.kind === 'cards';\n out.push(\n <SectionShell\n key={i}\n {...(gate ? { at: i, report: gate.report, hidden: gate.settled.has(i) } : {})}\n className={`page-section width-${width}${section.kind === 'note' ? ` dash-note${section.variant ? ` dash-${section.variant}` : ''}` : ''}${cards ? ' dash-cards-section' : ''}${section.kind === 'custom' ? ' dash-custom' : ''}`}\n >\n {/* A section that throws says so under its title; the rest of the dashboard stays. */}\n <ErrorBoundary\n fallback={(note) => (\n <>\n {section.title ? <h2 className=\"page-section-title\">{section.title}</h2> : null}\n {note}\n </>\n )}\n >\n <AllTimeOffer.Provider value={widened(section)}>{body}</AllTimeOffer.Provider>\n </ErrorBoundary>\n </SectionShell>,\n );\n });\n return out;\n };\n if (!layout)\n return (\n <>\n {flow(\n resolved.map((_, i) => i),\n true,\n )}\n </>\n );\n const inArea = new Map<string, number[]>();\n resolved.forEach((section, i) => {\n if (section.area) inArea.set(section.area, [...(inArea.get(section.area) ?? []), i]);\n });\n const epoch = `${windowNow}|${JSON.stringify(picks)}|${JSON.stringify(periods)}`;\n return <LaidOut layout={layout} inArea={inArea} epoch={epoch} flow={flow} />;\n});\n\n/** What the grid acts on when sections ask to be left out: who asks, and who has been settled as gone. */\ninterface Gate {\n report: (at: number, gone: boolean) => void;\n settled: ReadonlySet<number>;\n}\n\n/** A dashboard's layout drawn: one grid, an area for each name in the template, in reading order. */\nfunction LaidOut({\n layout,\n inArea,\n epoch,\n flow,\n}: {\n layout: LayoutGrid;\n inArea: ReadonlyMap<string, number[]>;\n /** What the reader has picked, as one word: the grid is re-shaped once for each. */\n epoch: string;\n flow: (indices: number[], pairing: boolean, gate: Gate) => ReactNode[];\n}) {\n /* Which sections ask to be left out is held here, and what the grid acts on is settled once per reader's pick. */\n const queries = useQueryClient();\n const asking = useIsFetching();\n const askedNow = useRef<ReadonlySet<number>>(NO_SECTIONS);\n const [asked, setAsked] = useState<ReadonlySet<number>>(NO_SECTIONS);\n const [settled, setSettled] = useState<ReadonlySet<number>>(NO_SECTIONS);\n const report = useCallback((at: number, gone: boolean) => {\n if (askedNow.current.has(at) === gone) return;\n const next = new Set(askedNow.current);\n if (gone) next.add(at);\n else next.delete(at);\n askedNow.current = next;\n setAsked(next);\n }, []);\n /* The areas are re-flowed once for each thing the reader picks, when every tile has its answer to it: until then the\n tiles keep their last answers (keepPreviousData) and the grid its last shape, so the change lands as one finished\n swap and not a move for every tile that answers. A live refresh is not a pick: a section that empties on one shows\n its empty line where it stands, and the grid is left alone until the reader's next pick. The timer lets the\n tiles' own effects, which start the questions and report the answers, run first. */\n const decided = useRef<string | null>(null);\n useEffect(() => {\n const timer = setTimeout(() => {\n if (queries.isFetching() > 0 || decided.current === epoch) return;\n decided.current = epoch;\n setSettled(askedNow.current);\n }, 0);\n return () => clearTimeout(timer);\n }, [queries, epoch, asking, asked]);\n /* In reading order, so the DOM is the order a reader and a keyboard go in whatever the template draws. */\n const areas = layoutAreas(layout);\n const away = new Set(areas.filter((area) => (inArea.get(area) ?? []).every((i) => settled.has(i))));\n const columns = layout[0]?.length ?? 1;\n const gate = { report, settled };\n return (\n <div\n className=\"dash-grid\"\n data-columns={columns}\n style={{ '--dash-columns': columns, '--dash-template': gridTemplateAreas(reflowLayout(layout, away)) } as CSSProperties}\n >\n {areas.map((area) => (\n <div key={area} className=\"dash-area\" style={{ '--area': area } as CSSProperties} hidden={away.has(area) || undefined}>\n {flow(inArea.get(area) ?? [], false, gate)}\n </div>\n ))}\n </div>\n );\n}\n\n/* A free-form page's block (sdk/blocks.tsx): one section, as a dashboard draws it, standing among the page's own. */\nconst BLOCK_DASHBOARD = { id: 'page-block', label: '', sections: [] } as unknown as DashboardDef;\nconst NO_PICKS: Picks = {};\nconst NO_SERVED: ReadonlyMap<Section, number> = new Map();\nconst noPeriod = () => {};\n\n/**\n * One section drawn where a page places it: its own `page-section`, with no dashboard around it, so a page's grid\n * lays it out with its neighbours. A metric is its card in a strip of its own width (a third, unless it says).\n */\nexport function DashboardBlock({ section }: { section: Section }) {\n const sections = useMemo(() => [section], [section]);\n return (\n <ProblemScopeProvider>\n {section.kind === 'metric' ? (\n <section className={`page-section width-${section.width ?? 'third'} dash-strip`}>\n <div className=\"home-cards\">\n <ErrorBoundary fallback={(note) => <div className=\"home-card home-card-broken\">{note}</div>}>\n <Metric section={section} />\n </ErrorBoundary>\n </div>\n </section>\n ) : (\n <Sections\n dashboard={BLOCK_DASHBOARD}\n sections={sections}\n windowNow={null}\n picks={NO_PICKS}\n periods={NO_PERIODS}\n onPeriod={noPeriod}\n onAllTime={noPeriod}\n served={NO_SERVED}\n />\n )}\n </ProblemScopeProvider>\n );\n}\n\n/**\n * The sections and the reader's controls over them. The window is the\n * query grammar's own phrase, landing on every section that declared\n * `over`; a metric's `compare` is the author's chosen window and stays\n * out of the reader's — two hands on one clock would tell no time. The\n * picks are column → chosen value, landing on every section whose table\n * has the column. Both arrive from a link and every change is reported\n * the same way, so a picked board is a place worth sending someone too.\n */\nexport function Dashboard({\n dashboard,\n window: fromLink = null,\n picks: pickedFromLink = {},\n periods: periodsFromLink = NO_PERIODS,\n onWindow,\n onPick,\n onPeriods,\n}: DashboardProps) {\n const [windowNow, setWindow] = useState<string | null>(fromLink);\n const [picks, setPicks] = useState<Picks>(pickedFromLink);\n const [periods, setPeriods] = useState<Periods>(periodsFromLink);\n /* Where each section stands among the dashboard's as it was served, before a first run is taken out below. */\n const served = useMemo(() => new Map(allSections(dashboard).map((section, at) => [section, at])), [dashboard]);\n const periodsNow = useRef(periods);\n const onPeriod = useMemo(\n () => (key: string, phrase: string) => {\n const next = { ...periodsNow.current, [key]: phrase };\n periodsNow.current = next;\n setPeriods(next);\n onPeriods?.(next);\n },\n [onPeriods],\n );\n /* A first run leads the dashboard until its steps are done; while none is,\n it is the dashboard — charts of empty tables say nothing but \"broken\". */\n const firstRun = dashboard.sections.find((section) => section.kind === 'firstRun');\n const run = useFirstRun(firstRun);\n if (firstRun && run.stage === 'unknown') return <div className=\"page-body dash-body\" aria-busy=\"true\" />;\n if (firstRun && run.stage === 'fresh') {\n return (\n <div className=\"page-body dash-body\">\n <FirstRun section={firstRun} done={run.done} fresh />\n </div>\n );\n }\n const lead = firstRun && run.stage === 'started' ? <FirstRun section={firstRun} done={run.done} fresh={false} /> : null;\n dashboard = firstRun ? { ...dashboard, sections: dashboard.sections.filter((section) => section !== firstRun) } : dashboard;\n const onAllTime = () => {\n setWindow(null);\n onWindow?.(null);\n };\n const controls = Boolean(dashboard.windows?.length) || Boolean(dashboard.filters?.length);\n return (\n <ProblemScopeProvider>\n <div>\n {lead && <div className=\"page-body dash-body\">{lead}</div>}\n {controls && (\n <div className=\"dash-controls\">\n {dashboard.windows?.length ? (\n <WindowRow\n windows={dashboard.windows}\n current={windowNow}\n onPick={(w) => {\n setWindow(w);\n onWindow?.(w);\n }}\n ownWindows={allSections(dashboard).some((section) => section.over && section.windowBase !== undefined)}\n control={dashboard.windowControl}\n />\n ) : null}\n {dashboard.filters?.length ? (\n <div className=\"dash-picks\">\n {dashboard.filters.map((column) => (\n <Pick\n key={column}\n dashboard={dashboard}\n column={column}\n picks={picks}\n onChange={(c, value) => {\n const next = { ...picks };\n if (value === '') delete next[c];\n else next[c] = value;\n setPicks(next);\n onPick?.(next);\n }}\n />\n ))}\n </div>\n ) : null}\n </div>\n )}\n {dashboard.aside?.length ? (\n <div className=\"dashboard-layout page-layout\">\n <div className=\"page-body page-main dash-body\">\n <Sections\n dashboard={dashboard}\n sections={dashboard.sections}\n windowNow={windowNow}\n picks={picks}\n periods={periods}\n onPeriod={onPeriod}\n onAllTime={onAllTime}\n served={served}\n />\n </div>\n <aside className=\"page-body page-aside dash-body\" aria-label={sayCopy('dashboardContext')}>\n <Sections\n dashboard={dashboard}\n sections={dashboard.aside}\n windowNow={windowNow}\n picks={picks}\n periods={periods}\n onPeriod={onPeriod}\n onAllTime={onAllTime}\n served={served}\n aside\n />\n </aside>\n </div>\n ) : (\n <div className={`page-body dash-body${dashboard.areas?.length ? ' dash-laid' : ''}`}>\n <Sections\n dashboard={dashboard}\n sections={dashboard.sections}\n windowNow={windowNow}\n picks={picks}\n periods={periods}\n onPeriod={onPeriod}\n onAllTime={onAllTime}\n served={served}\n />\n </div>\n )}\n </div>\n </ProblemScopeProvider>\n );\n}\n"],"ignoreList":[0],"mappings":"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"}