@btndprojects/loam-ui-native 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (365) hide show
  1. package/dist/accordion/index.js +4 -2
  2. package/dist/adaptive/index.js +12 -2
  3. package/dist/address-block/index.js +23 -0
  4. package/dist/alert/index.js +5 -2
  5. package/dist/analyzer/index.js +13 -5
  6. package/dist/announcement/index.js +15 -5
  7. package/dist/appearance-picker/index.js +15 -0
  8. package/dist/audio-player/index.js +26 -2
  9. package/dist/avatar/index.js +2 -2
  10. package/dist/avatar-group/index.js +5 -3
  11. package/dist/badge/index.js +6 -3
  12. package/dist/banner/index.js +3 -2
  13. package/dist/board/index.js +13 -6
  14. package/dist/button/index.js +6 -3
  15. package/dist/camera-permission/index.js +19 -11
  16. package/dist/capture-result/index.js +26 -16
  17. package/dist/card/index.js +7 -3
  18. package/dist/card-form/index.js +15 -9
  19. package/dist/carousel/index.js +3 -1
  20. package/dist/chart/index.js +15 -5
  21. package/dist/charts/index.js +18 -5
  22. package/dist/chat/index.js +35 -10
  23. package/dist/checkbox/index.js +6 -4
  24. package/dist/checklist/index.js +16 -7
  25. package/dist/checkout/index.js +25 -12
  26. package/dist/chip/index.js +7 -4
  27. package/dist/chunk-2BZD3NAP.js +1110 -0
  28. package/dist/chunk-2YKVID2V.js +35 -0
  29. package/dist/{chunk-H7DWSL4O.js → chunk-36DA3IPO.js} +115 -27
  30. package/dist/chunk-3A56MIAN.js +599 -0
  31. package/dist/{chunk-AEB7KCHQ.js → chunk-3SCKCWF5.js} +39 -28
  32. package/dist/chunk-3TZNDHKO.js +187 -0
  33. package/dist/chunk-43K3BLXV.js +9 -0
  34. package/dist/chunk-46ZJIQ2Z.js +208 -0
  35. package/dist/{chunk-PMMTGBBS.js → chunk-4CZMQDQL.js} +75 -22
  36. package/dist/chunk-4QCR3K2J.js +1 -0
  37. package/dist/{chunk-E2E3I5W2.js → chunk-5DTKORLI.js} +54 -45
  38. package/dist/{chunk-5VFZRGVD.js → chunk-5J4WFXFA.js} +32 -15
  39. package/dist/{chunk-JBMLWFSJ.js → chunk-5KJ7TEQ6.js} +83 -48
  40. package/dist/chunk-5NU33TXK.js +529 -0
  41. package/dist/chunk-6KSUS7DF.js +690 -0
  42. package/dist/{chunk-3WEZCGHX.js → chunk-6RV6UW2J.js} +140 -56
  43. package/dist/chunk-6RZM7RP2.js +520 -0
  44. package/dist/{chunk-JJLPBRVZ.js → chunk-75BDCC7K.js} +2 -0
  45. package/dist/{chunk-U5NLHYV6.js → chunk-7CGJBQUA.js} +333 -22
  46. package/dist/{chunk-I4FHVKEC.js → chunk-7IVF6JLJ.js} +16 -5
  47. package/dist/chunk-7IWCGXYA.js +143 -0
  48. package/dist/chunk-7LM4ASFH.js +172 -0
  49. package/dist/chunk-7MCEJFWV.js +341 -0
  50. package/dist/{chunk-2SY63FCH.js → chunk-7NGMUVNU.js} +66 -30
  51. package/dist/chunk-7PBSIXT7.js +355 -0
  52. package/dist/chunk-7QOYGENL.js +443 -0
  53. package/dist/{chunk-TDMG26JI.js → chunk-A7SWYDE5.js} +40 -9
  54. package/dist/chunk-ADHPJALR.js +3051 -0
  55. package/dist/{chunk-ZLTO5VQI.js → chunk-ALJYZLNQ.js} +131 -61
  56. package/dist/{chunk-GDKVKNR2.js → chunk-AQ5FIG74.js} +110 -30
  57. package/dist/chunk-B2MMZZQB.js +426 -0
  58. package/dist/{chunk-QYPE5JX3.js → chunk-B7JZ3N5G.js} +142 -105
  59. package/dist/{chunk-QHTVYA65.js → chunk-BL37SW6G.js} +388 -102
  60. package/dist/chunk-BTRMA7GC.js +21 -0
  61. package/dist/{chunk-FUMHAAF3.js → chunk-C7IUWIUZ.js} +243 -92
  62. package/dist/chunk-CA3DUVYD.js +10 -0
  63. package/dist/{chunk-FYWNRX4F.js → chunk-CBCJSO2B.js} +143 -13
  64. package/dist/chunk-CHPX4MFI.js +239 -0
  65. package/dist/chunk-CLGAMIOT.js +648 -0
  66. package/dist/chunk-CUE7VML6.js +1141 -0
  67. package/dist/{chunk-D5N5QWI7.js → chunk-CVU6S2E5.js} +497 -235
  68. package/dist/{chunk-U23FYWME.js → chunk-CXPQMA6Z.js} +101 -34
  69. package/dist/{chunk-36EC2T6P.js → chunk-D2LN4I7I.js} +1 -1
  70. package/dist/{chunk-TLCIR6RG.js → chunk-D34LNBO5.js} +411 -155
  71. package/dist/{chunk-FV6HMP7W.js → chunk-D4BCQICM.js} +207 -65
  72. package/dist/chunk-EABKIIA4.js +1 -0
  73. package/dist/chunk-EICSYRAG.js +341 -0
  74. package/dist/chunk-EMWAJMAS.js +83 -0
  75. package/dist/chunk-EOLZWRV6.js +149 -0
  76. package/dist/chunk-EOQVTGB6.js +350 -0
  77. package/dist/{chunk-ZVATDZOM.js → chunk-ESGUHNB2.js} +106 -28
  78. package/dist/{chunk-46MMSDGL.js → chunk-F2KNBPKY.js} +104 -73
  79. package/dist/{chunk-KQZ3GLHR.js → chunk-G7H3NX3G.js} +40 -17
  80. package/dist/{chunk-3QMEOFW5.js → chunk-GM7YIPB7.js} +421 -207
  81. package/dist/{chunk-QHAITQIF.js → chunk-GVQQG435.js} +256 -86
  82. package/dist/chunk-HE43OMEL.js +1056 -0
  83. package/dist/{chunk-XIDTBCBA.js → chunk-HHOMFQ7R.js} +1049 -207
  84. package/dist/chunk-HNAKS4Z3.js +207 -0
  85. package/dist/chunk-HP6ST2OW.js +352 -0
  86. package/dist/chunk-HW3OWDTU.js +1 -0
  87. package/dist/{chunk-QP3KMOVF.js → chunk-HZDB44K4.js} +24 -14
  88. package/dist/chunk-I6CUP2LW.js +1155 -0
  89. package/dist/chunk-ICV4Y2WY.js +27 -0
  90. package/dist/chunk-IHSIENOE.js +3950 -0
  91. package/dist/{chunk-T5LTPKX6.js → chunk-IMMALLRU.js} +53 -25
  92. package/dist/{chunk-C4GTDLRC.js → chunk-JA6TK7H2.js} +154 -67
  93. package/dist/{chunk-EVOIGUBI.js → chunk-JAVZ5JPV.js} +43 -13
  94. package/dist/{chunk-CPTOADB2.js → chunk-JCMTP3E4.js} +527 -201
  95. package/dist/{chunk-OJQUBQWA.js → chunk-JCXFFK64.js} +73 -16
  96. package/dist/{chunk-V2OEB75Z.js → chunk-JWCVBFDU.js} +75 -35
  97. package/dist/chunk-JXRTD5RI.js +414 -0
  98. package/dist/chunk-JYIUZUIQ.js +1567 -0
  99. package/dist/chunk-K3TK3GIV.js +219 -0
  100. package/dist/chunk-KEVZIHM2.js +1511 -0
  101. package/dist/{chunk-VAOAKWUK.js → chunk-KHZDNQQD.js} +42 -8
  102. package/dist/chunk-KL4GDV4V.js +131 -0
  103. package/dist/{chunk-Q6NKEPRE.js → chunk-KNILMM4H.js} +73 -28
  104. package/dist/chunk-KRBUZV45.js +25 -0
  105. package/dist/{chunk-7BUIKDD6.js → chunk-KXLDK6HB.js} +91 -30
  106. package/dist/chunk-KZ3X7TSL.js +196 -0
  107. package/dist/{chunk-5UTRIXQ6.js → chunk-L2WMOA2V.js} +187 -43
  108. package/dist/chunk-L4D5LHCH.js +109 -0
  109. package/dist/{chunk-W63AJTM7.js → chunk-LAUJPLDB.js} +236 -71
  110. package/dist/{chunk-TN2ZNJUI.js → chunk-LGNTP5XA.js} +47 -13
  111. package/dist/chunk-LUZFCCSD.js +271 -0
  112. package/dist/{chunk-XTORZWRF.js → chunk-LXJCP4PL.js} +111 -30
  113. package/dist/chunk-MCOZJWPU.js +731 -0
  114. package/dist/{chunk-SATMR6SG.js → chunk-MG4SKWLL.js} +780 -142
  115. package/dist/{chunk-JUYWSSKW.js → chunk-MPEPTSER.js} +95 -16
  116. package/dist/chunk-MWPJ4YGP.js +1 -0
  117. package/dist/{chunk-LUMVGO2K.js → chunk-N7AX4OA4.js} +80 -29
  118. package/dist/chunk-NHSLM6SE.js +523 -0
  119. package/dist/{chunk-IT6FUXXG.js → chunk-NNJLVA7M.js} +43 -11
  120. package/dist/{chunk-TQVAIKFD.js → chunk-NZG75DGA.js} +102 -62
  121. package/dist/chunk-O76QXRBV.js +431 -0
  122. package/dist/chunk-OANH27AK.js +223 -0
  123. package/dist/chunk-OCHPK5YV.js +609 -0
  124. package/dist/chunk-OMHVEVX4.js +436 -0
  125. package/dist/{chunk-SWS5JQIF.js → chunk-ONKQUJWD.js} +187 -60
  126. package/dist/chunk-OVTK7A6T.js +615 -0
  127. package/dist/{chunk-UXGIW7OK.js → chunk-PCEFCOLN.js} +5 -1
  128. package/dist/{chunk-QIKT7LIB.js → chunk-PFLNFIVB.js} +91 -23
  129. package/dist/chunk-PHSZY37H.js +300 -0
  130. package/dist/chunk-PJLTKDVY.js +18 -0
  131. package/dist/{chunk-SHHY5OMK.js → chunk-PK7BN3MI.js} +83 -15
  132. package/dist/{chunk-YXOAPXMU.js → chunk-PWFRDRGS.js} +101 -14
  133. package/dist/{chunk-TY4MTKQJ.js → chunk-PYPMD46W.js} +332 -66
  134. package/dist/chunk-Q6CCHDI7.js +331 -0
  135. package/dist/chunk-QFA5WS2A.js +750 -0
  136. package/dist/chunk-QJMMM4RC.js +124 -0
  137. package/dist/chunk-QYWEVAM6.js +407 -0
  138. package/dist/chunk-R5T4VZ7Z.js +126 -0
  139. package/dist/chunk-R77HFLZD.js +1 -0
  140. package/dist/{chunk-LMPHCVJJ.js → chunk-RAESDNU5.js} +162 -68
  141. package/dist/chunk-RBYQUXNL.js +1 -0
  142. package/dist/chunk-RCM3DT5E.js +1 -0
  143. package/dist/chunk-RGNY56L7.js +282 -0
  144. package/dist/chunk-RIK6UX2K.js +344 -0
  145. package/dist/{chunk-5LAAAXFP.js → chunk-RJA3RXO3.js} +63 -54
  146. package/dist/chunk-RJYRJ3LD.js +1 -0
  147. package/dist/chunk-RMA3NOY4.js +599 -0
  148. package/dist/{chunk-VDPK5CY4.js → chunk-RSWKKAHK.js} +143 -61
  149. package/dist/{chunk-B7N4ASYE.js → chunk-RVOIIX3V.js} +17 -45
  150. package/dist/chunk-SA2RRBGT.js +1077 -0
  151. package/dist/{chunk-7OVVSVEZ.js → chunk-SG3J4R45.js} +440 -169
  152. package/dist/chunk-SPUK7JD4.js +238 -0
  153. package/dist/chunk-SWXV2K5N.js +434 -0
  154. package/dist/chunk-SYJEPXP6.js +1303 -0
  155. package/dist/{chunk-LKFC4CS7.js → chunk-SZLI34TA.js} +18 -9
  156. package/dist/{chunk-NBEF4EPJ.js → chunk-T77WJA74.js} +131 -16
  157. package/dist/chunk-TDWWVJA4.js +630 -0
  158. package/dist/chunk-TFHI5XDR.js +610 -0
  159. package/dist/chunk-TH4PW2WU.js +17 -0
  160. package/dist/chunk-TTQ24HQX.js +12 -0
  161. package/dist/chunk-TUACVJNG.js +12 -0
  162. package/dist/{chunk-F5B3UINI.js → chunk-TUL5RUIA.js} +171 -62
  163. package/dist/{chunk-C6APNDVA.js → chunk-TYOSA7JG.js} +63 -34
  164. package/dist/chunk-TYQTMMEV.js +1 -0
  165. package/dist/{chunk-DW3L54DQ.js → chunk-TZO6YDS7.js} +53 -12
  166. package/dist/{chunk-67IZZ2MJ.js → chunk-U3ETF22F.js} +75 -30
  167. package/dist/{chunk-EDCBJV7J.js → chunk-U6BYHD2N.js} +87 -31
  168. package/dist/{chunk-ENP3BMZU.js → chunk-UF6EJXPQ.js} +16 -1
  169. package/dist/{chunk-IPUNJMAQ.js → chunk-UNNQIPGK.js} +304 -68
  170. package/dist/chunk-UQVO6AJV.js +171 -0
  171. package/dist/{chunk-FZGAAOKS.js → chunk-VFDQAAIW.js} +138 -32
  172. package/dist/chunk-VIUE3VQT.js +1 -0
  173. package/dist/{chunk-5RENVKBQ.js → chunk-VJLSSSGC.js} +126 -30
  174. package/dist/chunk-VLMT6KYT.js +350 -0
  175. package/dist/chunk-VMHGBUGS.js +35 -0
  176. package/dist/{chunk-4IZXHVFJ.js → chunk-VQKPBYW6.js} +228 -172
  177. package/dist/{chunk-G6UESEVN.js → chunk-VSSTWLC5.js} +49 -11
  178. package/dist/{chunk-TRGFFU6A.js → chunk-VZYYZRPN.js} +866 -330
  179. package/dist/{chunk-JLC6PM5S.js → chunk-WAIJCD2V.js} +128 -54
  180. package/dist/chunk-WFMQ3WKM.js +378 -0
  181. package/dist/chunk-WJ2KDRMY.js +66 -0
  182. package/dist/chunk-WKFZJO54.js +437 -0
  183. package/dist/{chunk-QEYFDRHR.js → chunk-WVVD3XOV.js} +146 -84
  184. package/dist/chunk-XAIWMSLB.js +1 -0
  185. package/dist/chunk-XBXUBBJZ.js +98 -0
  186. package/dist/chunk-XCU7MYBJ.js +1 -0
  187. package/dist/chunk-XHE4PGCI.js +717 -0
  188. package/dist/chunk-XRSJ32M3.js +331 -0
  189. package/dist/chunk-XTCVOEAW.js +1 -0
  190. package/dist/chunk-XWGXVQF6.js +58 -0
  191. package/dist/{chunk-MKSNFG7H.js → chunk-Y3XKKO5K.js} +191 -109
  192. package/dist/chunk-Y4QNMBLO.js +533 -0
  193. package/dist/chunk-Y5H4CTKO.js +1 -0
  194. package/dist/chunk-YBQIN75A.js +403 -0
  195. package/dist/{chunk-PNF3NKB5.js → chunk-YJ5PXOX3.js} +28 -11
  196. package/dist/{chunk-M656FYNH.js → chunk-YLRSRUPS.js} +63 -49
  197. package/dist/chunk-YM6MPJ4A.js +1 -0
  198. package/dist/chunk-YV7KZENV.js +200 -0
  199. package/dist/chunk-Z7I4ZSO6.js +316 -0
  200. package/dist/{chunk-EY4DD67D.js → chunk-ZIRMWD2B.js} +199 -126
  201. package/dist/chunk-ZPMG3FWU.js +75 -0
  202. package/dist/{chunk-QRUMA22E.js → chunk-ZTXMK2G7.js} +92 -43
  203. package/dist/{chunk-2OLKPG4E.js → chunk-ZVJCWXAL.js} +189 -87
  204. package/dist/{chunk-YAAHPATV.js → chunk-ZYQ23DPT.js} +49 -34
  205. package/dist/coachmark/index.js +7 -3
  206. package/dist/code-block/index.js +4 -3
  207. package/dist/color-field/index.js +12 -4
  208. package/dist/color-picker/index.js +23 -0
  209. package/dist/commerce/index.js +27 -16
  210. package/dist/confirm/index.js +31 -0
  211. package/dist/connection-card/index.js +34 -0
  212. package/dist/connectivity/index.js +3 -2
  213. package/dist/context-menu/index.js +10 -2
  214. package/dist/copy-button/index.js +3 -2
  215. package/dist/data-grid/index.js +30 -17
  216. package/dist/date-range-picker/index.js +19 -9
  217. package/dist/description-list/index.js +4 -1
  218. package/dist/device-frame/index.js +30 -0
  219. package/dist/dialog/index.js +8 -2
  220. package/dist/divider/index.js +2 -0
  221. package/dist/empty-state/index.js +13 -2
  222. package/dist/error-summary/index.js +7 -2
  223. package/dist/fab/index.js +4 -2
  224. package/dist/file-manager/index.js +33 -17
  225. package/dist/file-upload/index.js +12 -6
  226. package/dist/filter-bar/index.js +10 -6
  227. package/dist/flow-run/index.js +19 -12
  228. package/dist/form/index.js +30 -3
  229. package/dist/gallery/index.js +5 -2
  230. package/dist/hold-to-confirm/index.js +4 -2
  231. package/dist/hover-card/index.js +18 -0
  232. package/dist/icon-tile/index.js +10 -0
  233. package/dist/image/index.js +9 -0
  234. package/dist/index.d.ts +29826 -17941
  235. package/dist/index.js +197 -141
  236. package/dist/infinite-list/index.js +4 -2
  237. package/dist/inline-edit/index.js +5 -4
  238. package/dist/input/index.js +4 -3
  239. package/dist/interactions/index.js +4 -1
  240. package/dist/invoice/index.js +18 -9
  241. package/dist/job-row/index.js +22 -0
  242. package/dist/json-inspector/index.js +20 -0
  243. package/dist/kbd/index.js +2 -2
  244. package/dist/keyboard/index.js +7 -2
  245. package/dist/level-meter/index.js +9 -0
  246. package/dist/list-row/index.js +11 -3
  247. package/dist/log-viewer/index.js +9 -2
  248. package/dist/map-view/index.js +13 -2
  249. package/dist/markdown/index.js +8 -5
  250. package/dist/metric/index.js +6 -3
  251. package/dist/metric-strip/index.js +12 -0
  252. package/dist/money/index.js +11 -4
  253. package/dist/nav-drawer/index.js +6 -2
  254. package/dist/nav-header/index.js +10 -4
  255. package/dist/navigation/index.js +29 -2
  256. package/dist/notification-center/index.js +24 -10
  257. package/dist/number-roll/index.js +3 -1
  258. package/dist/onboarding-pager/index.js +22 -0
  259. package/dist/one-handed/index.js +2 -2
  260. package/dist/os-surfaces/index.js +6 -3
  261. package/dist/otp/index.js +5 -4
  262. package/dist/page-header/index.js +2 -1
  263. package/dist/pagination/index.js +4 -2
  264. package/dist/payment-method/index.js +17 -11
  265. package/dist/payment-status/index.js +22 -14
  266. package/dist/permission/index.js +18 -2
  267. package/dist/picker/index.js +17 -6
  268. package/dist/progress/index.js +7 -2
  269. package/dist/provenance/index.js +16 -0
  270. package/dist/pull-to-refresh/index.js +2 -2
  271. package/dist/qr-code/index.js +16 -0
  272. package/dist/query-builder/index.js +30 -0
  273. package/dist/radio-group/index.js +6 -4
  274. package/dist/rating/index.js +7 -2
  275. package/dist/receivables/index.js +31 -18
  276. package/dist/recording-indicator/index.js +21 -0
  277. package/dist/refund/index.js +24 -15
  278. package/dist/repeatable-rows/index.js +19 -0
  279. package/dist/save-status/index.js +5 -3
  280. package/dist/screen/index.js +3 -0
  281. package/dist/scroll-area/index.js +1 -1
  282. package/dist/search-field/index.js +8 -3
  283. package/dist/secret-field/index.js +19 -0
  284. package/dist/section-header/index.js +4 -0
  285. package/dist/segmented-control/index.js +2 -2
  286. package/dist/sheet/index.js +9 -3
  287. package/dist/shortcuts-sheet/index.js +2 -0
  288. package/dist/sign-in-screen/index.js +25 -0
  289. package/dist/skeleton/index.js +3 -1
  290. package/dist/slider/index.js +2 -1
  291. package/dist/sortable/index.js +4 -3
  292. package/dist/spinner/index.js +2 -1
  293. package/dist/split-button/index.js +17 -5
  294. package/dist/spotlight/index.js +7 -1
  295. package/dist/stack/index.js +2 -0
  296. package/dist/stage-timeline/index.js +6 -3
  297. package/dist/status-dot/index.js +6 -2
  298. package/dist/stepper/index.js +7 -3
  299. package/dist/streaming-text/index.js +2 -1
  300. package/dist/survey/index.js +24 -14
  301. package/dist/switch/index.js +6 -2
  302. package/dist/system-state/index.js +12 -4
  303. package/dist/tab-bar/index.js +10 -2
  304. package/dist/tabs/index.js +10 -2
  305. package/dist/tags-input/index.js +8 -5
  306. package/dist/text/index.js +4 -0
  307. package/dist/textarea/index.js +5 -4
  308. package/dist/thinking/index.js +4 -1
  309. package/dist/tile-rail/index.js +10 -0
  310. package/dist/time-field/index.js +15 -7
  311. package/dist/time-range-control/index.js +26 -12
  312. package/dist/timeline/index.js +2 -2
  313. package/dist/toast/index.js +4 -2
  314. package/dist/toolbar/index.js +3 -2
  315. package/dist/tour/index.js +12 -10
  316. package/dist/transcript/index.js +28 -0
  317. package/dist/truncation-notice/index.js +2 -2
  318. package/dist/update-notice/index.js +15 -8
  319. package/dist/video-player/index.js +26 -2
  320. package/dist/viewfinder/index.js +12 -4
  321. package/dist/widget/index.js +11 -4
  322. package/dist/wizard/index.js +7 -4
  323. package/package.json +13 -13
  324. package/dist/chunk-2PKYGLQ6.js +0 -268
  325. package/dist/chunk-2SWKL3AJ.js +0 -466
  326. package/dist/chunk-2TXERVVA.js +0 -1081
  327. package/dist/chunk-3DUWIYV5.js +0 -437
  328. package/dist/chunk-3NMD74ZU.js +0 -4
  329. package/dist/chunk-4DS5ZWVC.js +0 -83
  330. package/dist/chunk-6YAQBXB3.js +0 -93
  331. package/dist/chunk-74FLKD24.js +0 -237
  332. package/dist/chunk-CMTVNF3D.js +0 -104
  333. package/dist/chunk-DN7MNQIP.js +0 -799
  334. package/dist/chunk-DVGBZ3TX.js +0 -455
  335. package/dist/chunk-F3H33DQX.js +0 -300
  336. package/dist/chunk-FAJI7BSC.js +0 -443
  337. package/dist/chunk-G3AFC24V.js +0 -60
  338. package/dist/chunk-HJLPZA4X.js +0 -369
  339. package/dist/chunk-HYEOQWT7.js +0 -647
  340. package/dist/chunk-IDM7JJMO.js +0 -110
  341. package/dist/chunk-IVKMZ7BB.js +0 -326
  342. package/dist/chunk-IXKWIFWZ.js +0 -334
  343. package/dist/chunk-JV5YOTOB.js +0 -164
  344. package/dist/chunk-KFJGFLMW.js +0 -158
  345. package/dist/chunk-LQP4KEXZ.js +0 -214
  346. package/dist/chunk-NTQ2F3AU.js +0 -257
  347. package/dist/chunk-O5V4TG3V.js +0 -329
  348. package/dist/chunk-OWAMM2DK.js +0 -280
  349. package/dist/chunk-PID3NJB7.js +0 -405
  350. package/dist/chunk-QDZGFXQD.js +0 -176
  351. package/dist/chunk-QPWDDJJ4.js +0 -385
  352. package/dist/chunk-ROCUG24E.js +0 -416
  353. package/dist/chunk-RU3ZPNL6.js +0 -1986
  354. package/dist/chunk-RXSCIO6W.js +0 -153
  355. package/dist/chunk-SKWO3SZF.js +0 -2284
  356. package/dist/chunk-UQGBTPXH.js +0 -218
  357. package/dist/chunk-UYGDJWMN.js +0 -273
  358. package/dist/chunk-W74TXYFB.js +0 -107
  359. package/dist/chunk-WRDSPUE7.js +0 -417
  360. package/dist/chunk-XBZGDDMR.js +0 -105
  361. package/dist/chunk-XN4KG3P4.js +0 -1040
  362. package/dist/chunk-XQXMLMH3.js +0 -211
  363. package/dist/chunk-ZECZOOSB.js +0 -245
  364. /package/dist/{chunk-VFCUIDRT.js → chunk-3BKLBYPK.js} +0 -0
  365. /package/dist/{chunk-GEIGMWNF.js → chunk-QNZII37O.js} +0 -0
@@ -0,0 +1,1110 @@
1
+ import { DateRangePicker } from './chunk-CLGAMIOT.js';
2
+ import { MonthList } from './chunk-TZO6YDS7.js';
3
+ import { Sheet } from './chunk-B7JZ3N5G.js';
4
+ import { Button } from './chunk-5DTKORLI.js';
5
+ import { resolveTextRole } from './chunk-L4D5LHCH.js';
6
+ import { Skeleton } from './chunk-YJ5PXOX3.js';
7
+ import { SegmentedControl } from './chunk-NZG75DGA.js';
8
+ import { FieldMessage } from './chunk-BTRMA7GC.js';
9
+ import { Input } from './chunk-KXLDK6HB.js';
10
+ import { isAndroidIdiom } from './chunk-TH4PW2WU.js';
11
+ import { useLoamLocale } from './chunk-APCWFOZW.js';
12
+ import { Icon } from './chunk-PCEFCOLN.js';
13
+ import * as React2 from 'react';
14
+ import { View, Pressable, Text, ScrollView } from 'react-native';
15
+ import { createStyleSheet, useLoamTheme, useStyles } from '@btndprojects/loam-theme-native';
16
+ import { dateZone, absolute } from '@btndprojects/loam-date';
17
+ import { jsxs, jsx } from 'react/jsx-runtime';
18
+
19
+ var ISO = /^(\d{4})-(\d{2})-(\d{2})$/;
20
+ var Z = dateZone();
21
+ var DAY_MS = 864e5;
22
+ var RADIUS = 6;
23
+ function isoToMs(value) {
24
+ const m = value ? ISO.exec(value) : null;
25
+ return m ? Z.ms(Number(m[1]), Number(m[2]) - 1, Number(m[3]), 0, 0, 0) : null;
26
+ }
27
+ function msToIso(ms) {
28
+ const w = Z.wall(ms);
29
+ return `${String(w.y).padStart(4, "0")}-${String(w.mo + 1).padStart(2, "0")}-${String(w.d).padStart(2, "0")}`;
30
+ }
31
+ function QueryDateField({
32
+ value,
33
+ onChange,
34
+ label,
35
+ android,
36
+ surface
37
+ }) {
38
+ const { styles } = useStyles(sheet);
39
+ const locale = useLoamLocale();
40
+ const ms = isoToMs(value);
41
+ const ctx = React2.useMemo(
42
+ () => ({ Z, now: Date.now(), weekStartsOn: 1, granularity: "day", mode: "single", locale }),
43
+ [locale]
44
+ );
45
+ if (android) {
46
+ return /* @__PURE__ */ jsx(
47
+ DateRangePicker,
48
+ {
49
+ mode: "single",
50
+ platform: "android",
51
+ surface,
52
+ label,
53
+ placeholder: "YYYY-MM-DD",
54
+ presets: false,
55
+ clearable: false,
56
+ value: ms === null ? null : absolute(ms, ms + DAY_MS),
57
+ onChange: (_, resolved) => {
58
+ if (resolved.from !== null) onChange(msToIso(resolved.from));
59
+ }
60
+ }
61
+ );
62
+ }
63
+ return /* @__PURE__ */ jsx(View, { accessibilityLabel: label, style: styles.calendar, children: /* @__PURE__ */ jsx(
64
+ MonthList,
65
+ {
66
+ Z,
67
+ anchorMs: ms ?? ctx.now ?? Date.now(),
68
+ radius: RADIUS,
69
+ ctx,
70
+ from: ms,
71
+ to: ms === null ? null : Z.startOfDay(ms + DAY_MS),
72
+ onPick: (picked) => onChange(msToIso(Z.startOfDay(picked)))
73
+ }
74
+ ) });
75
+ }
76
+ var sheet = createStyleSheet((theme) => ({
77
+ calendar: { height: theme.space[256], minHeight: theme.space[224] }
78
+ }));
79
+
80
+ // src/query-builder/query-model.ts
81
+ function isGroup(node) {
82
+ return "children" in node;
83
+ }
84
+ var counter = 0;
85
+ function newGroupId() {
86
+ counter += 1;
87
+ return `g${counter}`;
88
+ }
89
+ function makeGroup(join = "AND", children = []) {
90
+ return { id: newGroupId(), join, children };
91
+ }
92
+ var NO_VALUE = /^(is (not )?(empty|set|null)|has no value|is blank)$/i;
93
+ var BETWEEN = /\bbetween\b/i;
94
+ var MULTI = /\b(any|none) of\b|\bin\b$|^in$/i;
95
+ var WITHIN = /^(in the last|within|in the next)$/i;
96
+ function editorFor(def, operator) {
97
+ if (NO_VALUE.test(operator)) return "none";
98
+ const type = def?.type;
99
+ if (!type) return "enum";
100
+ const between = BETWEEN.test(operator);
101
+ if (type === "text") return "text";
102
+ if (type === "number") return between ? "between" : "number";
103
+ if (type === "date") return between ? "between-date" : WITHIN.test(operator) ? "relative" : "date";
104
+ if (type === "boolean") return "boolean";
105
+ return def?.multiple || MULTI.test(operator) ? "multi" : "enum";
106
+ }
107
+ function emptyValue(def, operator) {
108
+ switch (editorFor(def, operator)) {
109
+ case "none":
110
+ return null;
111
+ case "enum":
112
+ return def?.values[0] ?? "";
113
+ case "multi":
114
+ return [];
115
+ case "between":
116
+ case "between-date":
117
+ return [null, null];
118
+ case "relative":
119
+ return { amount: null, unit: def?.units?.[0] ?? "days" };
120
+ case "boolean":
121
+ return null;
122
+ default:
123
+ return null;
124
+ }
125
+ }
126
+ var ISO2 = /^\d{4}-\d{2}-\d{2}$/;
127
+ function toNum(v) {
128
+ return typeof v === "number" ? v : Number(String(v ?? "").replace(/[,\s]/g, ""));
129
+ }
130
+ function blank(v) {
131
+ return v === null || v === void 0 || v === "" || typeof v === "number" && Number.isNaN(v);
132
+ }
133
+ function conditionIssue(c, def) {
134
+ const kind = editorFor(def, c.operator);
135
+ const v = c.value;
136
+ switch (kind) {
137
+ case "none":
138
+ return null;
139
+ case "enum":
140
+ return !def?.type ? null : blank(v) ? { kind: "empty", message: "Add a value, or remove this condition." } : null;
141
+ case "multi":
142
+ return Array.isArray(v) && v.length > 0 ? null : { kind: "empty", message: "Pick at least one value, or remove this condition." };
143
+ case "between":
144
+ case "between-date": {
145
+ const [a, b] = Array.isArray(v) ? v : [null, null];
146
+ if (blank(a) || blank(b)) return { kind: "empty", message: "Add both values, or remove this condition." };
147
+ if (kind === "between-date" && !(ISO2.test(String(a)) && ISO2.test(String(b)))) {
148
+ return { kind: "parse", message: "Use dates like 2026-10-12." };
149
+ }
150
+ const na = toNum(a);
151
+ const nb = toNum(b);
152
+ const larger = kind === "between" ? nb > na : String(b) > String(a);
153
+ if (kind === "between" && (Number.isNaN(na) || Number.isNaN(nb))) {
154
+ return { kind: "parse", message: "Enter numbers." };
155
+ }
156
+ return larger ? null : { kind: "range", message: "The second value must be larger than the first." };
157
+ }
158
+ case "relative": {
159
+ const amount = v && typeof v === "object" && !Array.isArray(v) ? v.amount : null;
160
+ return blank(amount) ? { kind: "empty", message: "Add a number, or remove this condition." } : null;
161
+ }
162
+ case "number": {
163
+ if (blank(v)) return { kind: "empty", message: "Add a value, or remove this condition." };
164
+ const n = toNum(v);
165
+ if (Number.isNaN(n)) return { kind: "parse", message: "Enter a number." };
166
+ if (def?.min !== void 0 && n < def.min) return { kind: "range", message: `Use ${def.min} or more.` };
167
+ if (def?.max !== void 0 && n > def.max) return { kind: "range", message: `Use ${def.max} or less.` };
168
+ return null;
169
+ }
170
+ case "date":
171
+ if (blank(v)) return { kind: "empty", message: "Add a value, or remove this condition." };
172
+ return ISO2.test(String(v)) ? null : { kind: "parse", message: "Use a date like 2026-10-12." };
173
+ default:
174
+ return blank(v) ? { kind: "empty", message: "Add a value, or remove this condition." } : null;
175
+ }
176
+ }
177
+ function collectIssues(root, fields) {
178
+ const out = [];
179
+ const walk = (g, path) => {
180
+ g.children.forEach((n, i) => {
181
+ if (isGroup(n)) return walk(n, [...path, i]);
182
+ const issue = conditionIssue(n, fields.find((f) => f.name === n.field));
183
+ if (issue) out.push({ path: [...path, i], ...issue });
184
+ });
185
+ };
186
+ walk(root, []);
187
+ return out;
188
+ }
189
+ function appliedGroup(root, fields) {
190
+ const prune = (g) => ({
191
+ ...g,
192
+ children: g.children.flatMap((n) => {
193
+ if (isGroup(n)) {
194
+ const inner = prune(n);
195
+ return inner.children.length > 0 ? [inner] : [];
196
+ }
197
+ return conditionIssue(n, fields.find((f) => f.name === n.field)) ? [] : [n];
198
+ })
199
+ });
200
+ return prune(root);
201
+ }
202
+ function countConditions(g) {
203
+ return g.children.reduce((n, c) => n + (isGroup(c) ? countConditions(c) : 1), 0);
204
+ }
205
+ function groupAt(root, path) {
206
+ let g = root;
207
+ for (const i of path) g = g.children[i];
208
+ return g;
209
+ }
210
+ function updateGroup(root, path, fn) {
211
+ if (path.length === 0) return fn(root);
212
+ const [head, ...rest] = path;
213
+ return {
214
+ ...root,
215
+ children: root.children.map((c, i) => i === head ? updateGroup(c, rest, fn) : c)
216
+ };
217
+ }
218
+ function escapeLiteral(value) {
219
+ return value.replace(/'/g, "''");
220
+ }
221
+ var SQL = {
222
+ is: "=",
223
+ "=": "=",
224
+ "is not": "!=",
225
+ "!=": "!=",
226
+ ">": ">",
227
+ "is over": ">",
228
+ "is greater than": ">",
229
+ after: ">",
230
+ "is after": ">",
231
+ "<": "<",
232
+ "is under": "<",
233
+ "is less than": "<",
234
+ before: "<",
235
+ "is before": "<",
236
+ ">=": ">=",
237
+ "is at least": ">=",
238
+ "is on or after": ">=",
239
+ "<=": "<=",
240
+ "is at most": "<=",
241
+ "is on or before": "<="
242
+ };
243
+ var quote = (s) => `'${escapeLiteral(s)}'`;
244
+ function formatCondition(c, def) {
245
+ const col = c.field.toLowerCase();
246
+ const kind = editorFor(def, c.operator);
247
+ const v = c.value;
248
+ const op = c.operator.toLowerCase();
249
+ if (!def?.type) return `${col} ${c.operator} ${quote(String(v ?? ""))}`;
250
+ if (kind === "none") return `${col} ${/not/.test(op) ? "IS NOT NULL" : "IS NULL"}`;
251
+ if (kind === "multi") {
252
+ const list = (Array.isArray(v) ? v : []).map((x) => quote(String(x))).join(", ");
253
+ return `${col} ${/none of|not in/.test(op) ? "NOT IN" : "IN"} (${list})`;
254
+ }
255
+ if (kind === "between" || kind === "between-date") {
256
+ const [a, b] = Array.isArray(v) ? v : [null, null];
257
+ const f = (x) => kind === "between" ? String(toNum(x)) : quote(String(x));
258
+ return `${col} ${/not/.test(op) ? "NOT BETWEEN" : "BETWEEN"} ${f(a)} AND ${f(b)}`;
259
+ }
260
+ if (kind === "relative") {
261
+ const r = v;
262
+ return `${col} >= now() - INTERVAL ${quote(`${r.amount} ${r.unit}`)}`;
263
+ }
264
+ if (kind === "boolean") {
265
+ const t = v === true || v === "Yes";
266
+ return `${col} ${/not/.test(op) ? "!=" : "="} ${t ? "TRUE" : "FALSE"}`;
267
+ }
268
+ if (kind === "text") {
269
+ const s = String(v ?? "");
270
+ if (op === "contains") return `${col} LIKE ${quote(`%${s}%`)}`;
271
+ if (op === "does not contain") return `${col} NOT LIKE ${quote(`%${s}%`)}`;
272
+ if (op === "starts with") return `${col} LIKE ${quote(`${s}%`)}`;
273
+ return `${col} ${SQL[op] ?? c.operator} ${quote(s)}`;
274
+ }
275
+ if (kind === "number") return `${col} ${SQL[op] ?? c.operator} ${toNum(v)}`;
276
+ return `${col} ${SQL[op] ?? c.operator} ${quote(String(v ?? ""))}`;
277
+ }
278
+ function formatNode(n, fields, nested) {
279
+ if (!isGroup(n)) return formatCondition(n, fields.find((f) => f.name === n.field));
280
+ const inner = n.children.map((c) => formatNode(c, fields, true)).join(` ${n.join} `);
281
+ return nested ? `(${inner})` : inner;
282
+ }
283
+ function formatGroup(root, fields, table = "projects") {
284
+ if (root.children.length === 0) return "";
285
+ const lines = root.children.map((c) => formatNode(c, fields, true));
286
+ return `SELECT * FROM ${table}
287
+ WHERE ${lines.join(`
288
+ ${root.join} `)}`;
289
+ }
290
+ function formatBody(root, fields) {
291
+ return root.children.map((c) => formatNode(c, fields, true)).join(`
292
+ ${root.join} `);
293
+ }
294
+ function tokenize(text) {
295
+ const out = [];
296
+ let line = 1;
297
+ let i = 0;
298
+ while (i < text.length) {
299
+ const ch = text[i];
300
+ if (ch === "\n") {
301
+ line += 1;
302
+ i += 1;
303
+ continue;
304
+ }
305
+ if (/\s/.test(ch)) {
306
+ i += 1;
307
+ continue;
308
+ }
309
+ if (ch === "-" && text[i + 1] === "-") {
310
+ while (i < text.length && text[i] !== "\n") i += 1;
311
+ continue;
312
+ }
313
+ if (ch === "'") {
314
+ let s = "";
315
+ i += 1;
316
+ while (i < text.length) {
317
+ if (text[i] === "'" && text[i + 1] === "'") {
318
+ s += "'";
319
+ i += 2;
320
+ continue;
321
+ }
322
+ if (text[i] === "'") break;
323
+ s += text[i];
324
+ i += 1;
325
+ }
326
+ if (text[i] !== "'") return { line, message: "A quoted value is missing its closing quote." };
327
+ i += 1;
328
+ out.push({ t: "str", v: s, line });
329
+ continue;
330
+ }
331
+ const num = /^-?\d+(\.\d+)?/.exec(text.slice(i));
332
+ if (num && (ch !== "-" || !/\w/.test(text[i - 1] ?? " "))) {
333
+ out.push({ t: "num", v: num[0], line });
334
+ i += num[0].length;
335
+ continue;
336
+ }
337
+ const word = /^[A-Za-z_][\w.]*/.exec(text.slice(i));
338
+ if (word) {
339
+ out.push({ t: "word", v: word[0], line });
340
+ i += word[0].length;
341
+ continue;
342
+ }
343
+ const sym = /^(!=|<>|<=|>=|=|<|>|\(|\)|,|%|\*|-)/.exec(text.slice(i));
344
+ if (sym) {
345
+ out.push({ t: "sym", v: sym[0], line });
346
+ i += sym[0].length;
347
+ continue;
348
+ }
349
+ return { line, message: `Unexpected \u201C${ch}\u201D.` };
350
+ }
351
+ out.push({ t: "end", v: "", line });
352
+ return out;
353
+ }
354
+ function distance(a, b) {
355
+ const d = Array.from({ length: a.length + 1 }, (_, i) => [i, ...Array(b.length).fill(0)]);
356
+ for (let j = 1; j <= b.length; j += 1) d[0][j] = j;
357
+ for (let i = 1; i <= a.length; i += 1)
358
+ for (let j = 1; j <= b.length; j += 1)
359
+ d[i][j] = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
360
+ return d[a.length][b.length];
361
+ }
362
+ function operatorFor(def, sql, kinds) {
363
+ return def.operators.find((o) => {
364
+ const k = editorFor(def, o);
365
+ if (!kinds.includes(k)) return false;
366
+ const low = o.toLowerCase();
367
+ if (sql === "IS NULL") return NO_VALUE.test(o) && !/not/.test(low);
368
+ if (sql === "IS NOT NULL") return NO_VALUE.test(o) && /not/.test(low);
369
+ if (sql === "IN") return k === "multi" && !/none|not/.test(low);
370
+ if (sql === "NOT IN") return k === "multi" && /none|not/.test(low);
371
+ if (sql === "BETWEEN") return /between/.test(low) && !/not/.test(low);
372
+ if (sql === "NOT BETWEEN") return /not between/.test(low);
373
+ if (sql === "WITHIN") return k === "relative";
374
+ if (sql === "LIKE_C") return low === "contains";
375
+ if (sql === "NOT LIKE_C") return low === "does not contain";
376
+ if (sql === "LIKE_S") return low === "starts with";
377
+ return (SQL[low] ?? low) === sql;
378
+ });
379
+ }
380
+ function parseQuery(text, fields) {
381
+ const toks = tokenize(text);
382
+ if (!Array.isArray(toks)) return { error: toks };
383
+ let p = 0;
384
+ const peek = () => toks[p];
385
+ const isW = (t, w) => t.t === "word" && t.v.toUpperCase() === w;
386
+ const fail = (message, fix, at = peek()) => ({
387
+ error: { line: at.line, message, ...{} }
388
+ });
389
+ if (isW(peek(), "SELECT")) {
390
+ while (!isW(peek(), "WHERE") && peek().t !== "end") p += 1;
391
+ }
392
+ if (isW(peek(), "WHERE")) p += 1;
393
+ if (peek().t === "end") return { value: makeGroup("AND") };
394
+ const readValue = () => {
395
+ const t = peek();
396
+ if (t.t === "str") {
397
+ p += 1;
398
+ return { ok: t.v };
399
+ }
400
+ if (t.t === "num") {
401
+ p += 1;
402
+ return { ok: Number(t.v) };
403
+ }
404
+ if (t.t === "word" && /^(TRUE|FALSE)$/i.test(t.v)) {
405
+ p += 1;
406
+ return { ok: t.v.toUpperCase() };
407
+ }
408
+ return { error: { line: t.line, message: "Expected a value here." } };
409
+ };
410
+ const cond = () => {
411
+ const ft = peek();
412
+ if (ft.t !== "word") return { error: { line: ft.line, message: "Expected a field name here." } };
413
+ const def = fields.find((f) => f.name.toLowerCase() === ft.v.toLowerCase());
414
+ if (!def) {
415
+ const best = [...fields].sort((a, b) => distance(a.name.toLowerCase(), ft.v.toLowerCase()) - distance(b.name.toLowerCase(), ft.v.toLowerCase()))[0];
416
+ const near = best && distance(best.name.toLowerCase(), ft.v.toLowerCase()) <= 2 ? best.name.toLowerCase() : void 0;
417
+ return {
418
+ error: {
419
+ line: ft.line,
420
+ message: `there is no field called \u201C${ft.v}\u201D.${near ? ` Use \u201C${near}\u201D` : ""}`,
421
+ ...near ? { fix: { label: `Use \u201C${near}\u201D`, text: text.replace(new RegExp(`\\b${ft.v}\\b`), near) } } : {}
422
+ }
423
+ };
424
+ }
425
+ p += 1;
426
+ const t = peek();
427
+ const mk = (sql, kinds, value) => {
428
+ const operator = operatorFor(def, sql, kinds);
429
+ if (!operator) return { error: { line: t.line, message: `\u201C${def.name.toLowerCase()}\u201D does not support ${sql}.` } };
430
+ return { ok: { field: def.name, operator, value } };
431
+ };
432
+ const typed = !!def.type;
433
+ if (isW(t, "IS")) {
434
+ p += 1;
435
+ const not2 = isW(peek(), "NOT");
436
+ if (not2) p += 1;
437
+ if (!isW(peek(), "NULL")) return { error: { line: peek().line, message: "Expected NULL after IS." } };
438
+ p += 1;
439
+ return mk(not2 ? "IS NOT NULL" : "IS NULL", ["none"], null);
440
+ }
441
+ let not = false;
442
+ if (isW(t, "NOT")) {
443
+ not = true;
444
+ p += 1;
445
+ }
446
+ const k = peek();
447
+ if (isW(k, "IN")) {
448
+ p += 1;
449
+ if (peek().v !== "(") return { error: { line: peek().line, message: "Expected ( after IN." } };
450
+ p += 1;
451
+ const list = [];
452
+ for (; ; ) {
453
+ const v = readValue();
454
+ if ("error" in v) return v;
455
+ list.push(String(v.ok));
456
+ if (peek().v === ",") {
457
+ p += 1;
458
+ continue;
459
+ }
460
+ break;
461
+ }
462
+ if (peek().v !== ")") return { error: { line: peek().line, message: "Expected ) to close the list." } };
463
+ p += 1;
464
+ return mk(not ? "NOT IN" : "IN", ["multi"], list);
465
+ }
466
+ if (isW(k, "BETWEEN")) {
467
+ p += 1;
468
+ const a = readValue();
469
+ if ("error" in a) return a;
470
+ if (!isW(peek(), "AND")) return { error: { line: peek().line, message: "Expected AND between the two values." } };
471
+ p += 1;
472
+ const b = readValue();
473
+ if ("error" in b) return b;
474
+ return mk(not ? "NOT BETWEEN" : "BETWEEN", ["between", "between-date"], [a.ok, b.ok]);
475
+ }
476
+ if (isW(k, "LIKE")) {
477
+ p += 1;
478
+ const v = readValue();
479
+ if ("error" in v) return v;
480
+ const s = String(v.ok);
481
+ const lead = s.startsWith("%");
482
+ const trail = s.endsWith("%");
483
+ const core = s.replace(/^%|%$/g, "");
484
+ if (lead && trail) return mk(not ? "NOT LIKE_C" : "LIKE_C", ["text"], core);
485
+ if (trail && !not) return mk("LIKE_S", ["text"], core);
486
+ return { error: { line: k.line, message: "Use LIKE with %value% or value%." } };
487
+ }
488
+ if (k.t === "sym" && ["=", "!=", "<>", "<", ">", "<=", ">="].includes(k.v)) {
489
+ p += 1;
490
+ const sql = k.v === "<>" ? "!=" : k.v;
491
+ if (isW(peek(), "NOW")) {
492
+ p += 1;
493
+ while (peek().v === "(" || peek().v === ")" || peek().v === "-" || isW(peek(), "INTERVAL")) p += 1;
494
+ const v2 = readValue();
495
+ if ("error" in v2) return v2;
496
+ const [amount, unit] = String(v2.ok).split(" ");
497
+ return mk("WITHIN", ["relative"], { amount: Number(amount), unit: unit ?? "days" });
498
+ }
499
+ const v = readValue();
500
+ if ("error" in v) return v;
501
+ if (typed && def.type === "boolean") {
502
+ return mk(sql, ["boolean"], String(v.ok).toUpperCase() === "TRUE");
503
+ }
504
+ const kinds = ["text", "number", "date", "enum"];
505
+ return mk(sql, kinds, typeof v.ok === "number" ? v.ok : v.ok);
506
+ }
507
+ return { error: { line: k.line, message: "Expected an operator after the field." } };
508
+ };
509
+ const expr = (depth) => {
510
+ const children = [];
511
+ let join = null;
512
+ for (; ; ) {
513
+ if (peek().v === "(") {
514
+ p += 1;
515
+ const inner = expr();
516
+ if ("error" in inner) return inner;
517
+ if (peek().v !== ")") return { error: { line: peek().line, message: "Expected ) to close the group." } };
518
+ p += 1;
519
+ children.push(inner.ok);
520
+ } else {
521
+ const c = cond();
522
+ if ("error" in c) return c;
523
+ children.push(c.ok);
524
+ }
525
+ const n = peek();
526
+ if (isW(n, "AND") || isW(n, "OR")) {
527
+ const j = n.v.toUpperCase();
528
+ if (join && join !== j) {
529
+ return { error: { line: n.line, message: "Mixing AND with OR needs parentheses." } };
530
+ }
531
+ join = j;
532
+ p += 1;
533
+ continue;
534
+ }
535
+ break;
536
+ }
537
+ return { ok: makeGroup(join ?? "AND", children) };
538
+ };
539
+ const r = expr();
540
+ if ("error" in r) return r;
541
+ if (peek().t !== "end") return fail("Unexpected text after the query.");
542
+ return { value: { ...r.ok, id: "root" } };
543
+ }
544
+ var DEFAULT_LABELS = {
545
+ title: "Filter",
546
+ addCondition: "Add condition",
547
+ addGroup: "Add group",
548
+ apply: "Apply",
549
+ cancel: "Cancel",
550
+ back: "Back",
551
+ field: "Field",
552
+ operator: "Operator",
553
+ value: "Value",
554
+ needsValue: "Needs a value",
555
+ remove: "Remove condition",
556
+ empty: "No conditions yet",
557
+ group: "Group",
558
+ conditions: "conditions",
559
+ conditionsOne: "condition",
560
+ and: "All",
561
+ or: "Any",
562
+ yes: "Yes",
563
+ no: "No",
564
+ leftOut: "left out",
565
+ done: "Done",
566
+ condition: "Condition",
567
+ match: "Match",
568
+ matchOf: "of",
569
+ from: "From",
570
+ to: "To"
571
+ };
572
+ var QUERY_ROW_HEIGHT = { ios: 60, android: 72 };
573
+ function displayValue(c) {
574
+ const v = c.value;
575
+ if (v === null || v === "") return "";
576
+ if (Array.isArray(v)) return v.join(" \u2013 ");
577
+ if (typeof v === "object") return `${v.amount ?? ""} ${v.unit}`.trim();
578
+ return String(v);
579
+ }
580
+ function QueryBuilder(props) {
581
+ const {
582
+ fields,
583
+ onChange,
584
+ onApply,
585
+ onCancel,
586
+ maxDepth = 2,
587
+ platform,
588
+ testID,
589
+ surface,
590
+ disabled = false,
591
+ readOnly = false,
592
+ size = "md",
593
+ loading = false,
594
+ error
595
+ } = props;
596
+ const locked = disabled || readOnly;
597
+ const labels = React2.useMemo(() => ({ ...DEFAULT_LABELS, ...props.labels }), [props.labels]);
598
+ const theme = useLoamTheme();
599
+ const android = isAndroidIdiom(theme, platform);
600
+ const { styles } = useStyles(sheet2);
601
+ const rowH = size === "sm" ? theme.space[android ? 56 : 44] : size === "lg" ? theme.space[android ? 80 : 72] : android ? QUERY_ROW_HEIGHT.android : QUERY_ROW_HEIGHT.ios;
602
+ const bodyRole = resolveTextRole(theme, "body", android);
603
+ const subRole = resolveTextRole(theme, "subheadline", android);
604
+ const rowPress = ({ pressed }) => !android && pressed ? { backgroundColor: theme.state.pressed } : null;
605
+ const ripple = android ? { color: theme.state.pressed } : void 0;
606
+ const [inner, setInner] = React2.useState(
607
+ () => props.defaultValue ?? makeGroup("AND")
608
+ );
609
+ const root = props.value ?? inner;
610
+ const [stack, setStack] = React2.useState([{ kind: "list", path: [] }]);
611
+ const top = stack[stack.length - 1] ?? { kind: "list", path: [] };
612
+ const sheetOpen = !android && top.kind === "row";
613
+ const shown = sheetOpen ? stack[stack.length - 2] ?? { kind: "list", path: [] } : top;
614
+ const commit = (next) => {
615
+ if (props.value === void 0) setInner(next);
616
+ onChange?.(next);
617
+ };
618
+ const push = (s) => setStack((st) => [...st, s]);
619
+ const pop = () => setStack((st) => st.length > 1 ? st.slice(0, -1) : st);
620
+ const defOf = (name) => fields.find((f) => f.name === name);
621
+ const issues = collectIssues(root, fields);
622
+ const issueKey = new Set(issues.map((i) => i.path.join(".")));
623
+ const edit = (path, fn) => {
624
+ if (locked) return;
625
+ commit(updateGroup(root, path, fn));
626
+ };
627
+ const setChild = (parent, index, node) => edit(parent, (g) => ({ ...g, children: g.children.map((c, i) => i === index ? node : c) }));
628
+ const addCondition = (path) => {
629
+ if (locked) return;
630
+ const f = fields[0];
631
+ if (!f) return;
632
+ const operator = f.operators[0] ?? "";
633
+ const cond = { field: f.name, operator, value: emptyValue(f, operator) };
634
+ edit(path, (g) => ({ ...g, children: [...g.children, cond] }));
635
+ push({ kind: "row", path: [...path, groupAt(root, path).children.length] });
636
+ };
637
+ const addGroup = (path) => {
638
+ if (locked) return;
639
+ edit(path, (g) => ({
640
+ ...g,
641
+ children: [...g.children, makeGroup(g.join === "AND" ? "OR" : "AND")]
642
+ }));
643
+ push({ kind: "list", path: [...path, groupAt(root, path).children.length] });
644
+ };
645
+ const renderList = (path) => {
646
+ const g = groupAt(root, path);
647
+ const depth = path.length;
648
+ const nodes = g.children.map((node, i) => {
649
+ const p = [...path, i];
650
+ const bad = isGroup(node) ? false : issueKey.has(p.join("."));
651
+ const title = isGroup(node) ? `${labels.group} \xB7 ${countConditions(node)} ${countConditions(node) === 1 ? labels.conditionsOne : labels.conditions}` : `${node.field} ${node.operator} ${displayValue(node)}`.trim();
652
+ return /* @__PURE__ */ jsxs(
653
+ Pressable,
654
+ {
655
+ accessibilityRole: "button",
656
+ accessibilityLabel: title,
657
+ onPress: () => push(isGroup(node) ? { kind: "list", path: p } : { kind: "row", path: p }),
658
+ android_ripple: ripple,
659
+ style: (st) => [
660
+ styles.row,
661
+ { minHeight: rowH },
662
+ i > 0 ? styles.rowDivider : null,
663
+ rowPress(st)
664
+ ],
665
+ children: [
666
+ /* @__PURE__ */ jsxs(View, { style: styles.rowText, children: [
667
+ /* @__PURE__ */ jsx(Text, { style: [styles.rowTitle, bodyRole], numberOfLines: 1, children: isGroup(node) ? `${labels.group} \xB7 ${countConditions(node)} ${labels.conditions}` : node.field }),
668
+ bad ? /* @__PURE__ */ jsx(Text, { style: styles.needs, children: labels.needsValue }) : /* @__PURE__ */ jsx(Text, { style: [styles.rowSub, subRole], numberOfLines: 1, children: isGroup(node) ? node.join === "AND" ? labels.and : labels.or : `${node.operator} ${displayValue(node)}`.trim() })
669
+ ] }),
670
+ /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: theme.icon.sm, color: theme.color.text3 })
671
+ ]
672
+ },
673
+ isGroup(node) ? node.id : `c${i}`
674
+ );
675
+ });
676
+ return /* @__PURE__ */ jsxs(View, { style: styles.screen, children: [
677
+ /* @__PURE__ */ jsxs(View, { style: styles.joinWrap, children: [
678
+ /* @__PURE__ */ jsx(Text, { style: styles.joinLabel, children: labels.match }),
679
+ /* @__PURE__ */ jsx(
680
+ SegmentedControl,
681
+ {
682
+ size: android ? "md" : "sm",
683
+ value: g.join,
684
+ onValueChange: (v) => edit(path, (x) => ({ ...x, join: v })),
685
+ items: [
686
+ { value: "AND", label: labels.and },
687
+ { value: "OR", label: labels.or }
688
+ ]
689
+ }
690
+ ),
691
+ /* @__PURE__ */ jsx(Text, { style: styles.joinLabel, children: labels.matchOf })
692
+ ] }),
693
+ /* @__PURE__ */ jsx(View, { style: [styles.group, android ? styles.groupAndroid : null], children: nodes.length === 0 ? /* @__PURE__ */ jsx(Text, { style: styles.empty, children: labels.empty }) : nodes }),
694
+ android ? /* @__PURE__ */ jsxs(View, { style: styles.actions, children: [
695
+ /* @__PURE__ */ jsx(
696
+ Button,
697
+ {
698
+ variant: "tonal",
699
+ leadingIcon: "plus",
700
+ disabled: locked,
701
+ onPress: () => addCondition(path),
702
+ children: labels.addCondition
703
+ }
704
+ ),
705
+ depth < maxDepth ? /* @__PURE__ */ jsx(Button, { variant: "outline", disabled: locked, onPress: () => addGroup(path), children: labels.addGroup }) : null
706
+ ] }) : /* @__PURE__ */ jsxs(View, { style: styles.group, children: [
707
+ /* @__PURE__ */ jsxs(
708
+ Pressable,
709
+ {
710
+ accessibilityRole: "button",
711
+ accessibilityLabel: labels.addCondition,
712
+ accessibilityState: { disabled: locked },
713
+ disabled: locked,
714
+ onPress: () => addCondition(path),
715
+ android_ripple: ripple,
716
+ style: (st) => [styles.row, { minHeight: QUERY_ROW_HEIGHT.ios }, rowPress(st)],
717
+ children: [
718
+ /* @__PURE__ */ jsx(Icon, { name: "plus", size: theme.icon.md, color: theme.color.accent }),
719
+ /* @__PURE__ */ jsx(Text, { style: [styles.addText, bodyRole], children: labels.addCondition })
720
+ ]
721
+ }
722
+ ),
723
+ depth < maxDepth ? /* @__PURE__ */ jsxs(
724
+ Pressable,
725
+ {
726
+ accessibilityRole: "button",
727
+ accessibilityLabel: labels.addGroup,
728
+ accessibilityState: { disabled: locked },
729
+ disabled: locked,
730
+ onPress: () => addGroup(path),
731
+ android_ripple: ripple,
732
+ style: (st) => [
733
+ styles.row,
734
+ styles.rowDivider,
735
+ { minHeight: QUERY_ROW_HEIGHT.ios },
736
+ rowPress(st)
737
+ ],
738
+ children: [
739
+ /* @__PURE__ */ jsx(Icon, { name: "plus", size: theme.icon.md, color: theme.color.accent }),
740
+ /* @__PURE__ */ jsx(Text, { style: [styles.addText, bodyRole], children: labels.addGroup })
741
+ ]
742
+ }
743
+ ) : null
744
+ ] })
745
+ ] });
746
+ };
747
+ const renderRow = (path) => {
748
+ const parent = path.slice(0, -1);
749
+ const index = path[path.length - 1] ?? 0;
750
+ const node = groupAt(root, parent).children[index];
751
+ if (!node || isGroup(node)) return null;
752
+ const def = defOf(node.field);
753
+ const kind = editorFor(def, node.operator);
754
+ const set = (patch) => setChild(parent, index, { ...node, ...patch });
755
+ const issue = conditionIssue(node, def);
756
+ const setValue = (value) => set({ value });
757
+ const choice = (text, on, press, multi = false) => /* @__PURE__ */ jsxs(
758
+ Pressable,
759
+ {
760
+ accessibilityRole: multi ? "checkbox" : "radio",
761
+ accessibilityState: multi ? { checked: on, disabled: locked } : { selected: on, disabled: locked },
762
+ disabled: locked,
763
+ onPress: press,
764
+ android_ripple: ripple,
765
+ style: (st) => [styles.row, { minHeight: theme.space[android ? 56 : 44] }, rowPress(st)],
766
+ children: [
767
+ /* @__PURE__ */ jsx(Text, { style: [styles.rowTitle, bodyRole], children: text }),
768
+ on ? /* @__PURE__ */ jsx(Icon, { name: "check", size: theme.icon.sm, color: theme.color.accent }) : null
769
+ ]
770
+ },
771
+ text
772
+ );
773
+ const pair = Array.isArray(node.value) ? node.value : [null, null];
774
+ const rel = node.value && typeof node.value === "object" && !Array.isArray(node.value) ? node.value : { amount: null, unit: def?.units?.[0] ?? "days" };
775
+ return /* @__PURE__ */ jsxs(View, { style: styles.screen, children: [
776
+ /* @__PURE__ */ jsx(Text, { style: styles.section, children: labels.field }),
777
+ /* @__PURE__ */ jsx(View, { style: styles.group, children: fields.map(
778
+ (f) => choice(f.name, f.name === node.field, () => {
779
+ const op = f.operators[0] ?? "";
780
+ set({ field: f.name, operator: op, value: emptyValue(f, op) });
781
+ })
782
+ ) }),
783
+ /* @__PURE__ */ jsx(Text, { style: styles.section, children: labels.operator }),
784
+ /* @__PURE__ */ jsx(View, { style: styles.group, children: (def?.operators ?? []).map(
785
+ (o) => choice(o, o === node.operator, () => set({ operator: o, value: emptyValue(def, o) }))
786
+ ) }),
787
+ kind !== "none" ? /* @__PURE__ */ jsx(Text, { style: styles.section, children: labels.value }) : null,
788
+ /* @__PURE__ */ jsxs(
789
+ View,
790
+ {
791
+ style: kind === "enum" || kind === "multi" || kind === "boolean" ? styles.group : styles.field,
792
+ children: [
793
+ kind === "text" ? /* @__PURE__ */ jsx(
794
+ Input,
795
+ {
796
+ size: "lg",
797
+ platform: android ? "android" : "ios",
798
+ surface,
799
+ editable: !locked,
800
+ accessibilityLabel: labels.value,
801
+ value: node.value === null ? "" : String(node.value),
802
+ onChangeText: (t) => setValue(t)
803
+ }
804
+ ) : null,
805
+ kind === "date" ? /* @__PURE__ */ jsx(
806
+ QueryDateField,
807
+ {
808
+ android,
809
+ surface,
810
+ label: labels.value,
811
+ value: typeof node.value === "string" ? node.value : "",
812
+ onChange: (iso) => setValue(iso)
813
+ }
814
+ ) : null,
815
+ kind === "number" ? /* @__PURE__ */ jsx(
816
+ Input,
817
+ {
818
+ size: "lg",
819
+ platform: android ? "android" : "ios",
820
+ surface,
821
+ editable: !locked,
822
+ accessibilityLabel: labels.value,
823
+ keyboardType: "numeric",
824
+ value: node.value === null ? "" : String(node.value),
825
+ onChangeText: (t) => setValue(t === "" ? null : toNum(t))
826
+ }
827
+ ) : null,
828
+ kind === "between" ? /* @__PURE__ */ jsx(View, { style: styles.pair, children: [0, 1].map((k) => /* @__PURE__ */ jsx(
829
+ Input,
830
+ {
831
+ size: "lg",
832
+ platform: android ? "android" : "ios",
833
+ surface,
834
+ editable: !locked,
835
+ accessibilityLabel: `${labels.value} ${k + 1}`,
836
+ keyboardType: "numeric",
837
+ value: pair[k] === null || pair[k] === void 0 ? "" : String(pair[k]),
838
+ onChangeText: (t) => {
839
+ const next = [
840
+ pair[0] ?? null,
841
+ pair[1] ?? null
842
+ ];
843
+ next[k] = t === "" ? null : toNum(t);
844
+ setValue(next);
845
+ }
846
+ },
847
+ k
848
+ )) }) : null,
849
+ kind === "between-date" ? /* @__PURE__ */ jsx(View, { style: styles.pair, children: [0, 1].map((k) => /* @__PURE__ */ jsxs(View, { style: styles.field, children: [
850
+ /* @__PURE__ */ jsx(Text, { style: styles.section, children: k === 0 ? labels.from : labels.to }),
851
+ /* @__PURE__ */ jsx(
852
+ QueryDateField,
853
+ {
854
+ android,
855
+ surface,
856
+ label: `${labels.value} ${k + 1}`,
857
+ value: typeof pair[k] === "string" ? pair[k] : "",
858
+ onChange: (iso) => {
859
+ const next = [
860
+ pair[0] ?? null,
861
+ pair[1] ?? null
862
+ ];
863
+ next[k] = iso;
864
+ setValue(next);
865
+ }
866
+ }
867
+ )
868
+ ] }, k)) }) : null,
869
+ kind === "relative" ? /* @__PURE__ */ jsxs(View, { style: styles.pair, children: [
870
+ /* @__PURE__ */ jsx(
871
+ Input,
872
+ {
873
+ size: "lg",
874
+ platform: android ? "android" : "ios",
875
+ surface,
876
+ editable: !locked,
877
+ accessibilityLabel: labels.value,
878
+ keyboardType: "numeric",
879
+ value: rel.amount === null ? "" : String(rel.amount),
880
+ onChangeText: (t) => setValue({ amount: t === "" ? null : toNum(t), unit: rel.unit })
881
+ }
882
+ ),
883
+ /* @__PURE__ */ jsx(
884
+ SegmentedControl,
885
+ {
886
+ size: android ? "md" : "sm",
887
+ value: rel.unit,
888
+ onValueChange: (u) => setValue({ amount: rel.amount, unit: u }),
889
+ items: (def?.units ?? ["days", "weeks", "months"]).map((u) => ({
890
+ value: u,
891
+ label: u
892
+ }))
893
+ }
894
+ )
895
+ ] }) : null,
896
+ kind === "enum" ? (def?.values ?? []).map((v) => choice(v, node.value === v, () => setValue(v))) : null,
897
+ kind === "multi" ? (def?.values ?? []).map((v) => {
898
+ const cur = Array.isArray(node.value) ? node.value : [];
899
+ const on = cur.includes(v);
900
+ return choice(
901
+ v,
902
+ on,
903
+ () => setValue(on ? cur.filter((x) => x !== v) : [...cur, v]),
904
+ true
905
+ );
906
+ }) : null,
907
+ kind === "boolean" ? [
908
+ choice(labels.yes, node.value === true, () => setValue(true)),
909
+ choice(labels.no, node.value === false, () => setValue(false))
910
+ ] : null,
911
+ issue && kind !== "none" ? /* @__PURE__ */ jsx(Text, { accessibilityRole: "alert", style: styles.needs, children: issue.kind === "empty" ? labels.needsValue : issue.message }) : null
912
+ ]
913
+ }
914
+ ),
915
+ /* @__PURE__ */ jsx(View, { style: styles.actions, children: /* @__PURE__ */ jsx(
916
+ Button,
917
+ {
918
+ variant: "danger",
919
+ disabled: locked,
920
+ onPress: () => {
921
+ edit(parent, (g) => ({ ...g, children: g.children.filter((_, i) => i !== index) }));
922
+ pop();
923
+ },
924
+ children: labels.remove
925
+ }
926
+ ) })
927
+ ] });
928
+ };
929
+ const skipped = issues.length;
930
+ const apply = () => {
931
+ if (locked) return;
932
+ const applied = appliedGroup(root, fields);
933
+ onApply?.(applied, formatBody(applied, fields));
934
+ };
935
+ const nested = stack.length > 1 && !sheetOpen;
936
+ const goBack = pop;
937
+ return /* @__PURE__ */ jsxs(
938
+ View,
939
+ {
940
+ testID,
941
+ accessibilityState: disabled || loading ? { disabled: disabled || void 0, busy: loading || void 0 } : void 0,
942
+ "aria-busy": loading || void 0,
943
+ pointerEvents: disabled || loading ? "none" : void 0,
944
+ style: [
945
+ styles.root,
946
+ android ? styles.rootAndroid : styles.rootIos,
947
+ error ? styles.rootError : null,
948
+ disabled ? { opacity: theme.state.disabledOpacity } : null
949
+ ],
950
+ children: [
951
+ android ? /* @__PURE__ */ jsxs(View, { style: styles.appBar, children: [
952
+ /* @__PURE__ */ jsx(
953
+ Pressable,
954
+ {
955
+ accessibilityRole: "button",
956
+ accessibilityLabel: nested ? labels.back : labels.cancel,
957
+ onPress: nested ? goBack : () => onCancel?.(),
958
+ style: styles.iconBtn,
959
+ children: /* @__PURE__ */ jsx(
960
+ Icon,
961
+ {
962
+ name: nested ? "arrow-left" : "x",
963
+ size: theme.icon.lg,
964
+ color: theme.color.text
965
+ }
966
+ )
967
+ }
968
+ ),
969
+ /* @__PURE__ */ jsx(Text, { accessibilityRole: "header", style: styles.appBarTitle, numberOfLines: 1, children: labels.title }),
970
+ skipped > 0 ? /* @__PURE__ */ jsxs(Text, { style: styles.rowSub, children: [
971
+ skipped,
972
+ " ",
973
+ labels.leftOut
974
+ ] }) : null,
975
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", disabled: disabled || readOnly, onPress: apply, children: labels.apply })
976
+ ] }) : /* @__PURE__ */ jsxs(View, { style: styles.navBar, children: [
977
+ /* @__PURE__ */ jsx(View, { style: [styles.navSide, styles.navLeft], children: nested ? /* @__PURE__ */ jsx(
978
+ Pressable,
979
+ {
980
+ accessibilityRole: "button",
981
+ accessibilityLabel: labels.back,
982
+ onPress: goBack,
983
+ style: styles.back,
984
+ children: /* @__PURE__ */ jsx(Icon, { name: "chevron-left", size: theme.icon.md, color: theme.color.accent })
985
+ }
986
+ ) : /* @__PURE__ */ jsx(Button, { variant: "ghost", onPress: () => onCancel?.(), children: labels.cancel }) }),
987
+ /* @__PURE__ */ jsxs(View, { style: styles.navTitle, children: [
988
+ /* @__PURE__ */ jsx(Text, { accessibilityRole: "header", style: styles.title, numberOfLines: 1, children: labels.title }),
989
+ skipped > 0 ? /* @__PURE__ */ jsxs(Text, { style: styles.rowSub, children: [
990
+ skipped,
991
+ " ",
992
+ labels.leftOut
993
+ ] }) : null
994
+ ] }),
995
+ /* @__PURE__ */ jsx(View, { style: [styles.navSide, styles.navRight], children: /* @__PURE__ */ jsx(Button, { variant: "ghost", disabled: disabled || readOnly, onPress: apply, children: labels.apply }) })
996
+ ] }),
997
+ typeof error === "string" && error ? /* @__PURE__ */ jsx(View, { accessibilityRole: "alert", style: styles.errorLine, children: /* @__PURE__ */ jsx(FieldMessage, { invalid: true, children: error }) }) : null,
998
+ /* @__PURE__ */ jsx(ScrollView, { contentContainerStyle: styles.scroll, children: loading ? /* @__PURE__ */ jsx(View, { testID: testID ? `${testID}-loading` : void 0, style: styles.group, children: [0, 1, 2].map((k) => /* @__PURE__ */ jsx(
999
+ View,
1000
+ {
1001
+ style: [styles.row, { minHeight: rowH }, k > 0 ? styles.rowDivider : null],
1002
+ children: /* @__PURE__ */ jsx(Skeleton, { variant: "text" })
1003
+ },
1004
+ k
1005
+ )) }) : shown.kind === "list" ? renderList(shown.path) : renderRow(shown.path) }),
1006
+ !android ? /* @__PURE__ */ jsx(
1007
+ Sheet,
1008
+ {
1009
+ open: sheetOpen,
1010
+ onClose: pop,
1011
+ title: labels.condition,
1012
+ detents: ["full"],
1013
+ footer: /* @__PURE__ */ jsx(View, { style: styles.sheetFooter, children: /* @__PURE__ */ jsx(Button, { size: "lg", fullWidth: true, onPress: pop, children: labels.done }) }),
1014
+ children: sheetOpen ? renderRow(top.path) : null
1015
+ }
1016
+ ) : null
1017
+ ]
1018
+ }
1019
+ );
1020
+ }
1021
+ var sheet2 = createStyleSheet((theme) => ({
1022
+ // iOS sits on the grouped background with surface cards; Android is one surface.
1023
+ root: { flex: 1, backgroundColor: theme.color.bg },
1024
+ rootError: { borderWidth: theme.borderWidth.base, borderColor: theme.edge.danger },
1025
+ errorLine: { paddingHorizontal: theme.space.s4, paddingBottom: theme.space.s2 },
1026
+ rootIos: { backgroundColor: theme.color.surface2 },
1027
+ rootAndroid: { backgroundColor: theme.color.surface },
1028
+ // iOS nav bar: Cancel | title | Apply.
1029
+ navBar: {
1030
+ flexDirection: "row",
1031
+ alignItems: "center",
1032
+ minHeight: theme.space[56],
1033
+ paddingHorizontal: theme.space.s2
1034
+ },
1035
+ navSide: { flex: 1, flexDirection: "row", alignItems: "center" },
1036
+ navLeft: { justifyContent: "flex-start" },
1037
+ navRight: { justifyContent: "flex-end" },
1038
+ navTitle: { alignItems: "center", justifyContent: "center" },
1039
+ title: { color: theme.color.text, ...theme.type.headline, textAlign: "center" },
1040
+ back: {
1041
+ minHeight: theme.hit.sm,
1042
+ minWidth: theme.hit.sm,
1043
+ alignItems: "center",
1044
+ justifyContent: "center"
1045
+ },
1046
+ // Android top app bar: close | title | Apply, 64 tall.
1047
+ appBar: {
1048
+ flexDirection: "row",
1049
+ alignItems: "center",
1050
+ gap: theme.space.s2,
1051
+ minHeight: theme.space[64],
1052
+ paddingHorizontal: theme.space.s2
1053
+ },
1054
+ appBarTitle: { flex: 1, color: theme.color.text, ...theme.type.title2 },
1055
+ iconBtn: {
1056
+ minHeight: theme.hit.sm,
1057
+ minWidth: theme.hit.sm,
1058
+ alignItems: "center",
1059
+ justifyContent: "center"
1060
+ },
1061
+ scroll: { paddingHorizontal: theme.space.s4, paddingBottom: theme.space.s4 },
1062
+ screen: { gap: theme.space.s4 },
1063
+ joinWrap: { flexDirection: "row", alignItems: "center", gap: theme.space.s2 },
1064
+ joinLabel: { color: theme.color.text2, ...theme.type.footnote },
1065
+ // Grouped list card: r 10 on iOS; Android rows run edge to edge on the dialog surface.
1066
+ group: {
1067
+ backgroundColor: theme.color.surface,
1068
+ borderRadius: theme.radius[10],
1069
+ overflow: "hidden"
1070
+ },
1071
+ groupAndroid: {
1072
+ borderRadius: 0,
1073
+ backgroundColor: "transparent",
1074
+ marginHorizontal: -theme.space.s4
1075
+ },
1076
+ field: { gap: theme.space.s2 },
1077
+ pair: { gap: theme.space.s2 },
1078
+ row: {
1079
+ flexDirection: "row",
1080
+ alignItems: "center",
1081
+ gap: theme.space.s3,
1082
+ paddingHorizontal: theme.space.s4,
1083
+ paddingVertical: theme.space.s2
1084
+ },
1085
+ rowDivider: { borderTopWidth: theme.borderWidth.thin, borderTopColor: theme.color.border },
1086
+ rowText: { flex: 1, gap: theme.space[2] },
1087
+ rowTitle: { flex: 1, color: theme.color.text },
1088
+ rowSub: { color: theme.color.text2, fontSize: theme.type.footnote.fontSize },
1089
+ addText: { color: theme.color.accentStrong },
1090
+ needs: {
1091
+ color: theme.color.dangerOnSoft,
1092
+ backgroundColor: theme.color.dangerSoft,
1093
+ borderWidth: theme.borderWidth.base,
1094
+ borderColor: theme.edge.danger,
1095
+ borderRadius: theme.radius.sm,
1096
+ paddingHorizontal: theme.space.s2,
1097
+ fontSize: theme.type.footnote.fontSize,
1098
+ alignSelf: "flex-start"
1099
+ },
1100
+ section: {
1101
+ color: theme.color.text2,
1102
+ fontSize: theme.type.footnote.fontSize,
1103
+ marginTop: theme.space.s2
1104
+ },
1105
+ empty: { color: theme.color.text2, padding: theme.space.s4, textAlign: "center" },
1106
+ actions: { gap: theme.space.s2, alignItems: "flex-start" },
1107
+ sheetFooter: { padding: theme.space.s4 }
1108
+ }));
1109
+
1110
+ export { QUERY_ROW_HEIGHT, QueryBuilder, formatGroup, makeGroup, parseQuery };