@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
@@ -1,72 +1,50 @@
1
- import { NavHeader, NavHeaderAction } from './chunk-NTQ2F3AU.js';
2
- import { ListRow } from './chunk-C4GTDLRC.js';
3
- import { ContextMenu } from './chunk-U5NLHYV6.js';
4
- import { EmptyState } from './chunk-KFJGFLMW.js';
5
- import { SegmentedControl } from './chunk-TQVAIKFD.js';
6
- import { Sheet } from './chunk-QYPE5JX3.js';
7
- import { DescriptionList } from './chunk-QIKT7LIB.js';
8
- import { Skeleton } from './chunk-PNF3NKB5.js';
9
- import { TextField } from './chunk-7BUIKDD6.js';
10
- import { Dialog, DialogFooter } from './chunk-GDKVKNR2.js';
11
- import { Button } from './chunk-E2E3I5W2.js';
1
+ import { NavHeaderAction, NavHeader } from './chunk-WFMQ3WKM.js';
2
+ import { useDelayedLoading } from './chunk-KRBUZV45.js';
3
+ import { useFileManagerLabels, NameConflictDialog } from './chunk-CHPX4MFI.js';
4
+ import { ListRow } from './chunk-JA6TK7H2.js';
5
+ import { DescriptionList } from './chunk-PFLNFIVB.js';
6
+ import { Checkbox } from './chunk-KNILMM4H.js';
7
+ import { EmptyState } from './chunk-QJMMM4RC.js';
8
+ import { IconTile } from './chunk-XBXUBBJZ.js';
9
+ import { ContextMenu, ContextMenuOverlay } from './chunk-7CGJBQUA.js';
10
+ import { Alert } from './chunk-Z7I4ZSO6.js';
11
+ import { Sheet } from './chunk-B7JZ3N5G.js';
12
+ import { Dialog, DialogFooter } from './chunk-AQ5FIG74.js';
13
+ import { Button } from './chunk-5DTKORLI.js';
14
+ import { Text as Text$1, resolveTextRole } from './chunk-L4D5LHCH.js';
15
+ import { Badge } from './chunk-LGNTP5XA.js';
16
+ import { Skeleton } from './chunk-YJ5PXOX3.js';
17
+ import { softToneSkin } from './chunk-PJLTKDVY.js';
18
+ import { SegmentedControl } from './chunk-NZG75DGA.js';
19
+ import { TextField } from './chunk-KXLDK6HB.js';
12
20
  import { haptics } from './chunk-NY2U3PBI.js';
13
- import { useLabels, useLoamLocale } from './chunk-APCWFOZW.js';
14
- import { Icon } from './chunk-UXGIW7OK.js';
15
- import { __export, __reExport } from './chunk-I2KLQ2HA.js';
16
- import * as React5 from 'react';
21
+ import { isAndroidIdiom } from './chunk-TH4PW2WU.js';
22
+ import { useLoamLocale } from './chunk-APCWFOZW.js';
23
+ import { Icon } from './chunk-PCEFCOLN.js';
24
+ import * as React3 from 'react';
17
25
  import { View, Image, Text, ScrollView, FlatList, Pressable } from 'react-native';
18
26
  import { createStyleSheet, useLoamTheme, useStyles } from '@btndprojects/loam-theme-native';
19
- import * as loam_file_manager_core_star from '@btndprojects/loam-file-manager-core';
20
- import { resolveFileManagerLabels, fileCategory, FILE_CATEGORY_ICON, DEFAULT_FILE_SORT, childrenOf, formatFileSize, indexEntries, pathTo, summarize, applyPending, isPlaceholderId, sortEntries, searchEntries, recentFiles, flattenRows, validateFileName, uniqueFileName, moveRefusal, placeholderId, topLevelIds } from '@btndprojects/loam-file-manager-core';
21
- import { TIMING } from '@btndprojects/loam-tokens';
22
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
27
+ import { fileCategory, FILE_CATEGORY_ICON, DEFAULT_FILE_SORT, childrenOf, formatFileSize, indexEntries, pathTo, summarize, applyPending, isPlaceholderId, sortEntries, searchEntries, recentFiles, flattenRows, validateFileName, uniqueFileName, newerSide, answerNameConflict, moveRefusal, placeholderId, topLevelIds, findNameConflicts, resolveNameConflicts } from '@btndprojects/loam-file-manager-core';
28
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
23
29
 
24
- // src/file-manager/file-manager-labels.ts
25
- var file_manager_labels_exports = {};
26
- __export(file_manager_labels_exports, {
27
- useFileManagerLabels: () => useFileManagerLabels
28
- });
29
- __reExport(file_manager_labels_exports, loam_file_manager_core_star);
30
- var NO_DEFAULTS = {};
31
- function useFileManagerLabels(own) {
32
- const provided = useLabels("fileManager", NO_DEFAULTS);
33
- return React5.useMemo(
34
- () => resolveFileManagerLabels({
35
- ...provided,
36
- ...own,
37
- sortKey: { ...provided.sortKey, ...own?.sortKey },
38
- category: { ...provided.category, ...own?.category },
39
- nameError: { ...provided.nameError, ...own?.nameError }
40
- }),
41
- [provided, own]
42
- );
43
- }
44
- function useDelayedLoading(loading, delay = TIMING.loadingFloor) {
45
- const [visible, setVisible] = React5.useState(false);
46
- const shownAt = React5.useRef(0);
47
- React5.useEffect(() => {
48
- if (loading) {
49
- if (visible) return;
50
- const t2 = setTimeout(() => {
51
- shownAt.current = Date.now();
52
- setVisible(true);
53
- }, delay);
54
- return () => clearTimeout(t2);
55
- }
56
- if (!visible) return;
57
- const remaining = Math.max(0, delay - (Date.now() - shownAt.current));
58
- const t = setTimeout(() => setVisible(false), remaining);
59
- return () => clearTimeout(t);
60
- }, [loading, visible, delay]);
61
- return visible;
62
- }
63
- function FileIcon({ entry, size = "md" }) {
30
+ var STEP_DOWN = { sm: "sm", md: "sm", lg: "md", xl: "lg" };
31
+ function FileIcon({
32
+ entry,
33
+ size: sizeProp = "md",
34
+ open = false,
35
+ tone,
36
+ shape,
37
+ status,
38
+ density = "comfortable",
39
+ loading = false
40
+ }) {
41
+ const size = density === "compact" ? STEP_DOWN[sizeProp] : sizeProp;
64
42
  const theme = useLoamTheme("file-manager");
65
43
  const { styles } = useStyles(sheet, { size });
66
- const [broken, setBroken] = React5.useState(false);
67
- const [loaded, setLoaded] = React5.useState(false);
44
+ const [broken, setBroken] = React3.useState(false);
45
+ const [loaded, setLoaded] = React3.useState(false);
68
46
  const thumb = entry.thumbnailUrl;
69
- React5.useEffect(() => {
47
+ React3.useEffect(() => {
70
48
  setBroken(false);
71
49
  setLoaded(false);
72
50
  }, [thumb]);
@@ -74,27 +52,60 @@ function FileIcon({ entry, size = "md" }) {
74
52
  const showThumb = Boolean(thumb) && !broken && (size === "lg" || size === "xl");
75
53
  const glyph = { sm: theme.icon.sm, md: theme.icon.md, lg: theme.space.s6, xl: theme.space.s7 }[size];
76
54
  const large = size === "lg" || size === "xl";
77
- return /* @__PURE__ */ jsxs(View, { style: [styles.frame, showThumb && styles.thumbFrame], accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", children: [
78
- !showThumb || !loaded ? /* @__PURE__ */ jsx(
79
- Icon,
80
- {
81
- name: FILE_CATEGORY_ICON[category],
82
- size: glyph,
83
- strokeWidth: large ? 1.25 : 1.5,
84
- color: category === "folder" ? theme.color.accentStrong : theme.color.text3
85
- }
86
- ) : null,
87
- showThumb ? /* @__PURE__ */ jsx(
88
- Image,
89
- {
90
- source: { uri: thumb },
91
- resizeMode: "cover",
92
- onLoad: () => setLoaded(true),
93
- onError: () => setBroken(true),
94
- style: [styles.thumb, { opacity: loaded ? 1 : 0 }]
95
- }
96
- ) : null
97
- ] });
55
+ const skin = tone ? softToneSkin(theme, tone) : null;
56
+ const statusColor = status ? theme.color[status] : void 0;
57
+ const radius = shape === "circle" ? theme.radius.full : shape === "rounded" ? theme.radius.md : shape === "square" ? 0 : void 0;
58
+ const frameSize = {
59
+ sm: theme.icon.sm,
60
+ md: theme.icon.md,
61
+ lg: theme.space[48],
62
+ xl: theme.space[64]
63
+ }[size];
64
+ if (loading) {
65
+ return /* @__PURE__ */ jsx(View, { style: styles.frame, accessibilityElementsHidden: true, children: /* @__PURE__ */ jsx(Skeleton, { variant: "rect", width: frameSize, height: frameSize, decorative: true }) });
66
+ }
67
+ return /* @__PURE__ */ jsxs(
68
+ View,
69
+ {
70
+ style: [
71
+ styles.frame,
72
+ showThumb && styles.thumbFrame,
73
+ skin ? { backgroundColor: skin.fill } : null,
74
+ radius !== void 0 ? { borderRadius: radius } : null,
75
+ statusColor ? { overflow: "visible" } : null
76
+ ],
77
+ accessibilityElementsHidden: true,
78
+ importantForAccessibility: "no-hide-descendants",
79
+ children: [
80
+ !showThumb || !loaded ? /* @__PURE__ */ jsx(
81
+ Icon,
82
+ {
83
+ name: category === "folder" && open ? "folder-open" : FILE_CATEGORY_ICON[category],
84
+ size: glyph,
85
+ strokeWidth: large ? 1.25 : 1.5,
86
+ color: skin ? skin.ink : category === "folder" ? theme.color.accentStrong : theme.color.text3
87
+ }
88
+ ) : null,
89
+ showThumb ? /* @__PURE__ */ jsx(
90
+ Image,
91
+ {
92
+ source: { uri: thumb },
93
+ resizeMode: "cover",
94
+ onLoad: () => setLoaded(true),
95
+ onError: () => setBroken(true),
96
+ style: [styles.thumb, { opacity: loaded ? 1 : 0 }]
97
+ }
98
+ ) : null,
99
+ statusColor ? /* @__PURE__ */ jsx(
100
+ View,
101
+ {
102
+ testID: "file-icon-status",
103
+ style: [styles.statusDot, { backgroundColor: statusColor }]
104
+ }
105
+ ) : null
106
+ ]
107
+ }
108
+ );
98
109
  }
99
110
  var sheet = createStyleSheet((theme) => ({
100
111
  frame: {
@@ -115,6 +126,16 @@ var sheet = createStyleSheet((theme) => ({
115
126
  borderWidth: theme.borderWidth.hair,
116
127
  borderColor: theme.color.border
117
128
  },
129
+ statusDot: {
130
+ position: "absolute",
131
+ right: 0,
132
+ bottom: 0,
133
+ width: theme.space[8],
134
+ height: theme.space[8],
135
+ borderRadius: theme.radius.full,
136
+ borderWidth: theme.borderWidth.thin,
137
+ borderColor: theme.color.surface
138
+ },
118
139
  thumb: {
119
140
  position: "absolute",
120
141
  top: 0,
@@ -134,32 +155,33 @@ function ChoiceRow({
134
155
  }) {
135
156
  const theme = useLoamTheme("file-manager");
136
157
  const { styles } = useStyles(sheet2);
137
- return /* @__PURE__ */ jsxs(
138
- Pressable,
158
+ return /* @__PURE__ */ jsx(View, { style: { paddingStart: indent * theme.space.s5 }, children: /* @__PURE__ */ jsx(
159
+ ListRow,
139
160
  {
140
- accessibilityRole: "button",
141
- accessibilityState: { selected: Boolean(selected), disabled: Boolean(disabled) },
161
+ density: "compact",
162
+ title: label,
142
163
  accessibilityLabel: detail ? `${label}, ${detail}` : label,
143
164
  disabled,
144
165
  onPress,
145
- style: ({ pressed }) => [
146
- styles.choice,
147
- { paddingStart: theme.space.s4 + indent * theme.space.s5 },
148
- pressed && styles.choicePressed,
149
- disabled && styles.choiceDisabled
150
- ],
151
- children: [
152
- icon ? /* @__PURE__ */ jsx(Icon, { name: icon, size: theme.icon.md, color: selected ? theme.color.accentStrong : theme.color.text2 }) : null,
153
- /* @__PURE__ */ jsx(Text, { style: [styles.choiceLabel, selected && styles.choiceLabelSelected], numberOfLines: 1, children: label }),
166
+ leading: icon ? /* @__PURE__ */ jsx(Icon, { name: icon, size: theme.icon.md, color: theme.color.text2 }) : void 0,
167
+ trailing: detail || selected ? /* @__PURE__ */ jsxs(View, { style: styles.choiceTrail, children: [
154
168
  detail ? /* @__PURE__ */ jsx(Text, { style: styles.choiceDetail, children: detail }) : null,
155
169
  selected ? /* @__PURE__ */ jsx(Icon, { name: "check", size: theme.icon.md, color: theme.color.accentStrong }) : null
156
- ]
170
+ ] }) : void 0
157
171
  }
158
- );
172
+ ) });
159
173
  }
160
174
  function GroupLabel({ children }) {
175
+ const theme = useLoamTheme("file-manager");
161
176
  const { styles } = useStyles(sheet2);
162
- return /* @__PURE__ */ jsx(Text, { style: styles.groupLabel, accessibilityRole: "header", children });
177
+ return /* @__PURE__ */ jsx(
178
+ Text,
179
+ {
180
+ style: [styles.groupLabel, resolveTextRole(theme, "overline", isAndroidIdiom(theme))],
181
+ accessibilityRole: "header",
182
+ children
183
+ }
184
+ );
163
185
  }
164
186
  var SORT_KEYS = ["name", "modified", "size", "type"];
165
187
  function FileOptionsSheet({
@@ -175,86 +197,151 @@ function FileOptionsSheet({
175
197
  motion
176
198
  }) {
177
199
  const { styles } = useStyles(sheet2);
178
- return /* @__PURE__ */ jsxs(Sheet, { open, onClose, title: labels.view, closeLabel: labels.close, safeAreaBottom, motion, children: [
179
- /* @__PURE__ */ jsx(View, { style: styles.segment, children: /* @__PURE__ */ jsx(
180
- SegmentedControl,
181
- {
182
- accessibilityLabel: labels.view,
183
- items: [
184
- { value: "grid", label: labels.viewGrid, icon: "grid" },
185
- { value: "list", label: labels.viewList, icon: "list-ul" }
186
- ],
187
- value: view,
188
- onValueChange: (v) => onViewChange(v),
189
- motion
190
- }
191
- ) }),
192
- /* @__PURE__ */ jsx(GroupLabel, { children: labels.sort }),
193
- SORT_KEYS.map((key) => {
194
- const chosen = sort.key === key;
195
- return /* @__PURE__ */ jsx(
196
- ChoiceRow,
197
- {
198
- icon: chosen ? sort.direction === "asc" ? "arrow-up" : "arrow-down" : void 0,
199
- label: labels.sortKey[key],
200
- detail: chosen ? sort.direction === "asc" ? labels.ascending : labels.descending : void 0,
201
- selected: chosen,
202
- onPress: () => {
203
- haptics.selection();
204
- onSortChange(
205
- chosen ? { key, direction: sort.direction === "asc" ? "desc" : "asc" } : { key, direction: key === "modified" || key === "size" ? "desc" : DEFAULT_FILE_SORT.direction }
206
- );
207
- }
208
- },
209
- key
210
- );
211
- }),
212
- onNewFolder ? /* @__PURE__ */ jsxs(Fragment, { children: [
213
- /* @__PURE__ */ jsx(View, { style: styles.rule }),
214
- /* @__PURE__ */ jsx(
215
- ChoiceRow,
216
- {
217
- icon: "folder-plus",
218
- label: labels.newFolder,
219
- onPress: () => {
220
- onClose();
221
- onNewFolder();
200
+ return /* @__PURE__ */ jsxs(
201
+ Sheet,
202
+ {
203
+ open,
204
+ onClose,
205
+ title: labels.view,
206
+ closeLabel: labels.close,
207
+ safeAreaBottom,
208
+ motion,
209
+ children: [
210
+ /* @__PURE__ */ jsx(View, { style: styles.segment, children: /* @__PURE__ */ jsx(
211
+ SegmentedControl,
212
+ {
213
+ accessibilityLabel: labels.view,
214
+ items: [
215
+ { value: "grid", label: labels.viewGrid, icon: "grid" },
216
+ { value: "list", label: labels.viewList, icon: "list-ul" }
217
+ ],
218
+ value: view,
219
+ onValueChange: (v) => onViewChange(v),
220
+ motion
222
221
  }
223
- }
224
- )
225
- ] }) : null
226
- ] });
222
+ ) }),
223
+ /* @__PURE__ */ jsx(GroupLabel, { children: labels.sort }),
224
+ SORT_KEYS.map((key) => {
225
+ const chosen = sort.key === key;
226
+ return /* @__PURE__ */ jsx(
227
+ ChoiceRow,
228
+ {
229
+ icon: chosen ? sort.direction === "asc" ? "arrow-up" : "arrow-down" : void 0,
230
+ label: labels.sortKey[key],
231
+ detail: chosen ? sort.direction === "asc" ? labels.ascending : labels.descending : void 0,
232
+ selected: chosen,
233
+ onPress: () => {
234
+ haptics.selection();
235
+ onSortChange(
236
+ chosen ? { key, direction: sort.direction === "asc" ? "desc" : "asc" } : {
237
+ key,
238
+ direction: key === "modified" || key === "size" ? "desc" : DEFAULT_FILE_SORT.direction
239
+ }
240
+ );
241
+ }
242
+ },
243
+ key
244
+ );
245
+ }),
246
+ onNewFolder ? /* @__PURE__ */ jsxs(Fragment, { children: [
247
+ /* @__PURE__ */ jsx(View, { style: styles.rule }),
248
+ /* @__PURE__ */ jsx(
249
+ ChoiceRow,
250
+ {
251
+ icon: "folder-plus",
252
+ label: labels.newFolder,
253
+ onPress: () => {
254
+ onClose();
255
+ onNewFolder();
256
+ }
257
+ }
258
+ )
259
+ ] }) : null
260
+ ]
261
+ }
262
+ );
227
263
  }
228
- function FileLocations({ location, onLocationChange, folders, recents, favorites, labels }) {
264
+ function FileLocations({
265
+ location,
266
+ onLocationChange,
267
+ folders,
268
+ recents,
269
+ favorites,
270
+ labels
271
+ }) {
229
272
  const at = (l) => l.kind === location.kind && (l.kind !== "folder" || location.kind === "folder" && location.id === l.id);
230
273
  return (
231
274
  // A labelled group, not a list: its children are headings and choice rows,
232
275
  // and a `list` that owns no `listitem` is an invalid ARIA tree on the web.
233
276
  /* @__PURE__ */ jsxs(View, { role: "group", accessibilityLabel: labels.locations, children: [
234
277
  /* @__PURE__ */ jsx(GroupLabel, { children: labels.locations }),
235
- /* @__PURE__ */ jsx(ChoiceRow, { icon: "folder", label: labels.root, selected: at({ kind: "folder", id: null }), onPress: () => onLocationChange({ kind: "folder", id: null }) }),
236
- recents ? /* @__PURE__ */ jsx(ChoiceRow, { icon: "clock", label: labels.recent, selected: at({ kind: "recent" }), onPress: () => onLocationChange({ kind: "recent" }) }) : null,
237
- favorites ? /* @__PURE__ */ jsx(ChoiceRow, { icon: "star", label: labels.favorites, selected: at({ kind: "favorites" }), onPress: () => onLocationChange({ kind: "favorites" }) }) : null,
278
+ /* @__PURE__ */ jsx(
279
+ ChoiceRow,
280
+ {
281
+ icon: "folder",
282
+ label: labels.root,
283
+ selected: at({ kind: "folder", id: null }),
284
+ onPress: () => onLocationChange({ kind: "folder", id: null })
285
+ }
286
+ ),
287
+ recents ? /* @__PURE__ */ jsx(
288
+ ChoiceRow,
289
+ {
290
+ icon: "clock",
291
+ label: labels.recent,
292
+ selected: at({ kind: "recent" }),
293
+ onPress: () => onLocationChange({ kind: "recent" })
294
+ }
295
+ ) : null,
296
+ favorites ? /* @__PURE__ */ jsx(
297
+ ChoiceRow,
298
+ {
299
+ icon: "star",
300
+ label: labels.favorites,
301
+ selected: at({ kind: "favorites" }),
302
+ onPress: () => onLocationChange({ kind: "favorites" })
303
+ }
304
+ ) : null,
238
305
  folders.length > 0 ? /* @__PURE__ */ jsx(GroupLabel, { children: labels.folders }) : null,
239
- folders.map((f) => /* @__PURE__ */ jsx(ChoiceRow, { icon: "folder", label: f.name, selected: at({ kind: "folder", id: f.id }), onPress: () => onLocationChange({ kind: "folder", id: f.id }) }, f.id))
306
+ folders.map((f) => /* @__PURE__ */ jsx(
307
+ ChoiceRow,
308
+ {
309
+ icon: "folder",
310
+ label: f.name,
311
+ selected: at({ kind: "folder", id: f.id }),
312
+ onPress: () => onLocationChange({ kind: "folder", id: f.id })
313
+ },
314
+ f.id
315
+ ))
240
316
  ] })
241
317
  );
242
318
  }
243
319
  function entryMeta(entry, items, labels, locale) {
244
320
  if (entry.type === "folder") return labels.items(childrenOf(items, entry.id).length);
245
- return [labels.category[fileCategory(entry)], entry.size !== void 0 ? formatFileSize(entry.size, locale) : ""].filter(Boolean).join(" \xB7 ");
321
+ return [
322
+ labels.category[fileCategory(entry)],
323
+ entry.size !== void 0 ? formatFileSize(entry.size, locale) : ""
324
+ ].filter(Boolean).join(" \xB7 ");
246
325
  }
247
326
  function formatDate(value, locale) {
248
327
  if (value === void 0) return "";
249
328
  const d = new Date(value);
250
329
  return Number.isNaN(d.getTime()) ? "" : d.toLocaleString(locale, { dateStyle: "medium", timeStyle: "short" });
251
330
  }
252
- function FileInfoSheet({ entry, items, onClose, labels, locale, safeAreaBottom, motion }) {
331
+ function FileInfoSheet({
332
+ entry,
333
+ items,
334
+ onClose,
335
+ labels,
336
+ locale,
337
+ safeAreaBottom,
338
+ motion
339
+ }) {
253
340
  const { styles } = useStyles(sheet2);
254
- const last = React5.useRef(entry);
341
+ const last = React3.useRef(entry);
255
342
  if (entry) last.current = entry;
256
343
  const shown = last.current;
257
- const rows = React5.useMemo(() => {
344
+ const rows = React3.useMemo(() => {
258
345
  if (!shown) return [];
259
346
  const index = indexEntries(items);
260
347
  const where = [labels.root, ...pathTo(index, shown.parentId).map((e) => e.name)].join(" \u203A ");
@@ -271,16 +358,27 @@ function FileInfoSheet({ entry, items, onClose, labels, locale, safeAreaBottom,
271
358
  if (shown.tags?.length) out.push({ term: labels.tags, description: shown.tags.join(", ") });
272
359
  return out;
273
360
  }, [shown, items, labels, locale]);
274
- return /* @__PURE__ */ jsxs(Sheet, { open: entry !== null, onClose, title: labels.getInfo, closeLabel: labels.close, safeAreaBottom, motion, children: [
275
- shown ? /* @__PURE__ */ jsxs(View, { style: styles.infoHead, children: [
276
- /* @__PURE__ */ jsx(FileIcon, { entry: shown, size: "lg" }),
277
- /* @__PURE__ */ jsxs(View, { style: styles.infoTitle, children: [
278
- /* @__PURE__ */ jsx(Text, { style: styles.infoName, numberOfLines: 2, children: shown.name }),
279
- /* @__PURE__ */ jsx(Text, { style: styles.infoMeta, numberOfLines: 1, children: entryMeta(shown, items, labels, locale) })
280
- ] })
281
- ] }) : null,
282
- /* @__PURE__ */ jsx(View, { style: styles.infoBody, children: /* @__PURE__ */ jsx(DescriptionList, { items: rows }) })
283
- ] });
361
+ return /* @__PURE__ */ jsxs(
362
+ Sheet,
363
+ {
364
+ open: entry !== null,
365
+ onClose,
366
+ title: labels.getInfo,
367
+ closeLabel: labels.close,
368
+ safeAreaBottom,
369
+ motion,
370
+ children: [
371
+ shown ? /* @__PURE__ */ jsxs(View, { style: styles.infoHead, children: [
372
+ /* @__PURE__ */ jsx(FileIcon, { entry: shown, size: "lg" }),
373
+ /* @__PURE__ */ jsxs(View, { style: styles.infoTitle, children: [
374
+ /* @__PURE__ */ jsx(Text, { style: styles.infoName, numberOfLines: 2, children: shown.name }),
375
+ /* @__PURE__ */ jsx(Text, { style: styles.infoMeta, numberOfLines: 1, children: entryMeta(shown, items, labels, locale) })
376
+ ] })
377
+ ] }) : null,
378
+ /* @__PURE__ */ jsx(View, { style: styles.infoBody, children: /* @__PURE__ */ jsx(DescriptionList, { items: rows }) })
379
+ ]
380
+ }
381
+ );
284
382
  }
285
383
  function FilePreviewSheet({
286
384
  entry,
@@ -295,11 +393,11 @@ function FilePreviewSheet({
295
393
  motion
296
394
  }) {
297
395
  const { styles } = useStyles(sheet2);
298
- const last = React5.useRef(entry);
396
+ const last = React3.useRef(entry);
299
397
  if (entry) last.current = entry;
300
398
  const shown = last.current;
301
- const [failed, setFailed] = React5.useState(false);
302
- React5.useEffect(() => setFailed(false), [shown?.id]);
399
+ const [failed, setFailed] = React3.useState(false);
400
+ React3.useEffect(() => setFailed(false), [shown?.id]);
303
401
  const at = shown ? files.findIndex((f) => f.id === shown.id) : -1;
304
402
  const step = (by) => {
305
403
  const next = files[at + by];
@@ -323,9 +421,31 @@ function FilePreviewSheet({
323
421
  safeAreaBottom,
324
422
  motion,
325
423
  footer: files.length > 1 ? /* @__PURE__ */ jsxs(View, { style: styles.stepper, children: [
326
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", leadingIcon: "chevron-left", disabled: at <= 0, onPress: () => step(-1), accessibilityLabel: labels.previous, children: labels.previous }),
424
+ /* @__PURE__ */ jsx(
425
+ Button,
426
+ {
427
+ variant: "ghost",
428
+ size: "sm",
429
+ leadingIcon: "chevron-left",
430
+ disabled: at <= 0,
431
+ onPress: () => step(-1),
432
+ accessibilityLabel: labels.previous,
433
+ children: labels.previous
434
+ }
435
+ ),
327
436
  /* @__PURE__ */ jsx(Text, { style: styles.stepperCount, children: at >= 0 ? `${at + 1} / ${files.length}` : "" }),
328
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", trailingIcon: "chevron-right", disabled: at < 0 || at >= files.length - 1, onPress: () => step(1), accessibilityLabel: labels.next, children: labels.next })
437
+ /* @__PURE__ */ jsx(
438
+ Button,
439
+ {
440
+ variant: "ghost",
441
+ size: "sm",
442
+ trailingIcon: "chevron-right",
443
+ disabled: at < 0 || at >= files.length - 1,
444
+ onPress: () => step(1),
445
+ accessibilityLabel: labels.next,
446
+ children: labels.next
447
+ }
448
+ )
329
449
  ] }) : void 0,
330
450
  children: shown ? custom !== void 0 ? /* @__PURE__ */ jsx(View, { style: styles.previewBody, children: custom }) : isImage ? /* @__PURE__ */ jsx(View, { style: styles.previewImageWrap, children: /* @__PURE__ */ jsx(
331
451
  Image,
@@ -344,17 +464,26 @@ function FilePreviewSheet({
344
464
  }
345
465
  );
346
466
  }
347
- function FileMoveSheet({ entries, items, onMove, onClose, labels, locale, safeAreaBottom, motion }) {
348
- const last = React5.useRef(entries);
467
+ function FileMoveSheet({
468
+ entries,
469
+ items,
470
+ onMove,
471
+ onClose,
472
+ labels,
473
+ locale,
474
+ safeAreaBottom,
475
+ motion
476
+ }) {
477
+ const last = React3.useRef(entries);
349
478
  if (entries.length > 0) last.current = entries;
350
479
  const moving = last.current;
351
- const [target, setTarget] = React5.useState(void 0);
352
- React5.useEffect(() => {
480
+ const [target, setTarget] = React3.useState(void 0);
481
+ React3.useEffect(() => {
353
482
  if (entries.length > 0) setTarget(void 0);
354
483
  }, [entries]);
355
- const index = React5.useMemo(() => indexEntries(items), [items]);
356
- const ids = React5.useMemo(() => moving.map((e) => e.id), [moving]);
357
- const tree = React5.useMemo(() => {
484
+ const index = React3.useMemo(() => indexEntries(items), [items]);
485
+ const ids = React3.useMemo(() => moving.map((e) => e.id), [moving]);
486
+ const tree = React3.useMemo(() => {
358
487
  const out = [];
359
488
  const walk = (parentId, depth) => {
360
489
  for (const f of sortEntries(childrenOf(items, parentId), DEFAULT_FILE_SORT, locale)) {
@@ -391,7 +520,16 @@ function FileMoveSheet({ entries, items, onMove, onClose, labels, locale, safeAr
391
520
  }
392
521
  ),
393
522
  children: /* @__PURE__ */ jsxs(ScrollView, { children: [
394
- /* @__PURE__ */ jsx(ChoiceRow, { icon: "folder", label: labels.root, selected: target === null, disabled: !allowed(null), onPress: () => setTarget(null) }),
523
+ /* @__PURE__ */ jsx(
524
+ ChoiceRow,
525
+ {
526
+ icon: "folder",
527
+ label: labels.root,
528
+ selected: target === null,
529
+ disabled: !allowed(null),
530
+ onPress: () => setTarget(null)
531
+ }
532
+ ),
395
533
  tree.map(({ entry, depth }) => /* @__PURE__ */ jsx(
396
534
  ChoiceRow,
397
535
  {
@@ -408,10 +546,21 @@ function FileMoveSheet({ entries, items, onMove, onClose, labels, locale, safeAr
408
546
  }
409
547
  );
410
548
  }
411
- function FileNameDialog({ open, title, initialName, confirmLabel, validate, onSubmit, onClose, labels, motion }) {
412
- const [name, setName] = React5.useState(initialName);
413
- const [touched, setTouched] = React5.useState(false);
414
- React5.useEffect(() => {
549
+ function FileNameDialog({
550
+ open,
551
+ title,
552
+ initialName,
553
+ confirmLabel,
554
+ validate,
555
+ onSubmit,
556
+ onClose,
557
+ labels: labelsProp,
558
+ motion
559
+ }) {
560
+ const labels = useFileManagerLabels(labelsProp);
561
+ const [name, setName] = React3.useState(initialName);
562
+ const [touched, setTouched] = React3.useState(false);
563
+ React3.useEffect(() => {
415
564
  if (open) {
416
565
  setName(initialName);
417
566
  setTouched(false);
@@ -454,15 +603,23 @@ function FileNameDialog({ open, title, initialName, confirmLabel, validate, onSu
454
603
  ] })
455
604
  ] });
456
605
  }
457
- function FileDeleteDialog({ entries, onConfirm, onClose, labels, motion }) {
458
- const last = React5.useRef(entries);
459
- if (entries) last.current = entries;
460
- const list = last.current ?? [];
606
+ function FileDeleteDialog({
607
+ open,
608
+ entries,
609
+ onConfirm,
610
+ onClose,
611
+ labels: labelsProp,
612
+ motion
613
+ }) {
614
+ const labels = useFileManagerLabels(labelsProp);
615
+ const last = React3.useRef(entries);
616
+ if (entries.length > 0) last.current = entries;
617
+ const list = last.current;
461
618
  const first = list[0];
462
619
  return /* @__PURE__ */ jsx(
463
620
  Dialog,
464
621
  {
465
- open: entries !== null,
622
+ open,
466
623
  onClose,
467
624
  title: labels.deleteTitle(list.length, first?.name ?? ""),
468
625
  description: labels.deleteDescription,
@@ -475,35 +632,14 @@ function FileDeleteDialog({ entries, onConfirm, onClose, labels, motion }) {
475
632
  );
476
633
  }
477
634
  var sheet2 = createStyleSheet((theme) => ({
478
- choice: {
479
- flexDirection: "row",
480
- alignItems: "center",
481
- gap: theme.space.s3,
482
- minHeight: theme.ctl.lg,
483
- paddingEnd: theme.space.s4,
484
- paddingVertical: theme.space.s2,
485
- borderRadius: theme.radius.md
486
- },
487
- choicePressed: { backgroundColor: theme.color.surface2 },
488
- choiceDisabled: { opacity: theme.state.disabledOpacity },
489
- choiceLabel: {
490
- flex: 1,
491
- minWidth: 0,
492
- fontFamily: theme.font.sans,
493
- fontSize: theme.type.body.fontSize,
494
- lineHeight: theme.type.body.lineHeight,
495
- color: theme.color.text
496
- },
497
- choiceLabelSelected: { color: theme.color.accentStrong, fontWeight: theme.type.headline.fontWeight },
635
+ choiceTrail: { flexDirection: "row", alignItems: "center", gap: theme.space.s2 },
498
636
  choiceDetail: {
499
637
  fontFamily: theme.font.sans,
500
638
  fontSize: theme.type.footnote.fontSize,
501
- color: theme.color.text3
639
+ color: theme.color.text2
502
640
  },
503
641
  groupLabel: {
504
642
  fontFamily: theme.font.sans,
505
- fontSize: theme.type.footnote.fontSize,
506
- fontWeight: theme.type.headline.fontWeight,
507
643
  color: theme.color.text3,
508
644
  paddingHorizontal: theme.space.s4,
509
645
  paddingTop: theme.space.s4,
@@ -546,7 +682,8 @@ var sheet2 = createStyleSheet((theme) => ({
546
682
  stepperCount: {
547
683
  fontFamily: theme.font.sans,
548
684
  fontSize: theme.type.footnote.fontSize,
549
- color: theme.color.text3,
685
+ fontWeight: theme.type.headline.fontWeight,
686
+ color: theme.color.text2,
550
687
  fontVariant: ["tabular-nums"]
551
688
  },
552
689
  previewBody: { flex: 1, paddingHorizontal: theme.space.s4 },
@@ -576,9 +713,9 @@ var sheet2 = createStyleSheet((theme) => ({
576
713
  }));
577
714
  var SIDEBAR_MIN_WIDTH = 768;
578
715
  function useControllable(value, initial, onChange) {
579
- const [inner, setInner] = React5.useState(initial);
716
+ const [inner, setInner] = React3.useState(initial);
580
717
  const current = value !== void 0 ? value : inner;
581
- const set = React5.useCallback(
718
+ const set = React3.useCallback(
582
719
  (next) => {
583
720
  if (value === void 0) setInner(next);
584
721
  onChange?.(next);
@@ -611,7 +748,7 @@ function FileManager({
611
748
  renderPreview,
612
749
  onNotify,
613
750
  loading = false,
614
- error = false,
751
+ failed = false,
615
752
  onRetry,
616
753
  recents = true,
617
754
  nested = true,
@@ -636,37 +773,41 @@ function FileManager({
636
773
  );
637
774
  const [view, setView] = useControllable(viewProp, defaultView, onViewChange);
638
775
  const [sort, setSort] = useControllable(sortProp, defaultSort, onSortChange);
639
- const [special, setSpecial] = React5.useState(null);
640
- const [query, setQuery] = React5.useState("");
641
- const [selecting, setSelecting] = React5.useState(false);
642
- const [selection, setSelection] = React5.useState([]);
643
- const [expanded, setExpanded] = React5.useState(
776
+ const [special, setSpecial] = React3.useState(null);
777
+ const [query, setQuery] = React3.useState("");
778
+ const android = isAndroidIdiom(
779
+ theme,
780
+ platform === "android" || platform === "ios" ? platform : void 0
781
+ );
782
+ const [selecting, setSelecting] = React3.useState(false);
783
+ const [selection, setSelection] = React3.useState([]);
784
+ const [expanded, setExpanded] = React3.useState(
644
785
  () => new Set(defaultExpanded)
645
786
  );
646
- const [pending, setPending] = React5.useState([]);
647
- const [width, setWidth] = React5.useState(0);
648
- const [optionsOpen, setOptionsOpen] = React5.useState(false);
649
- const [locationsOpen, setLocationsOpen] = React5.useState(false);
650
- const [info, setInfo] = React5.useState(null);
651
- const [preview, setPreview] = React5.useState(null);
652
- const [moving, setMoving] = React5.useState([]);
653
- const [naming, setNaming] = React5.useState(null);
654
- const [deleting, setDeleting] = React5.useState(null);
655
- const { entries: drawn, pendingIds } = React5.useMemo(
787
+ const [pending, setPending] = React3.useState([]);
788
+ const [width, setWidth] = React3.useState(0);
789
+ const [optionsOpen, setOptionsOpen] = React3.useState(false);
790
+ const [locationsOpen, setLocationsOpen] = React3.useState(false);
791
+ const [info, setInfo] = React3.useState(null);
792
+ const [preview, setPreview] = React3.useState(null);
793
+ const [moving, setMoving] = React3.useState([]);
794
+ const [naming, setNaming] = React3.useState(null);
795
+ const [deleting, setDeleting] = React3.useState(null);
796
+ const { entries: drawn, pendingIds } = React3.useMemo(
656
797
  () => applyPending(items, pending),
657
798
  [items, pending]
658
799
  );
659
- const index = React5.useMemo(() => indexEntries(drawn), [drawn]);
800
+ const index = React3.useMemo(() => indexEntries(drawn), [drawn]);
660
801
  const favoritesOn = Boolean(onFavoriteChange) || drawn.some((e) => e.favorite);
661
- React5.useEffect(() => {
802
+ React3.useEffect(() => {
662
803
  if (folderId !== null && !index.has(folderId) && !isPlaceholderId(folderId)) setFolderId(null);
663
804
  }, [folderId, index, setFolderId]);
664
805
  const location = special ? { kind: special } : { kind: "folder", id: folderId };
665
806
  const folder = folderId !== null ? index.get(folderId) ?? null : null;
666
- const crumbs = React5.useMemo(() => pathTo(index, folderId), [index, folderId]);
807
+ const crumbs = React3.useMemo(() => pathTo(index, folderId), [index, folderId]);
667
808
  const parent = crumbs.length > 1 ? crumbs[crumbs.length - 2] : null;
668
809
  const searching = query.trim().length > 0;
669
- const listed = React5.useMemo(() => {
810
+ const listed = React3.useMemo(() => {
670
811
  if (searching)
671
812
  return sortEntries(searchEntries(drawn, query, special ? null : folderId), sort, locale);
672
813
  if (special === "recent") return recentFiles(drawn);
@@ -678,12 +819,12 @@ function FileManager({
678
819
  );
679
820
  return sortEntries(childrenOf(drawn, folderId), sort, locale);
680
821
  }, [drawn, query, searching, special, folderId, sort, locale]);
681
- const rows = React5.useMemo(
822
+ const rows = React3.useMemo(
682
823
  () => nested && view === "list" && !searching && special === null ? flattenRows(listed, expanded, (f) => sortEntries(childrenOf(drawn, f.id), sort, locale)) : listed.map((entry) => ({ kind: "entry", entry, depth: 0 })),
683
824
  [nested, view, searching, special, listed, expanded, drawn, sort, locale]
684
825
  );
685
- const files = React5.useMemo(() => listed.filter((e) => e.type === "file"), [listed]);
686
- const selectedEntries = React5.useMemo(
826
+ const files = React3.useMemo(() => listed.filter((e) => e.type === "file"), [listed]);
827
+ const selectedEntries = React3.useMemo(
687
828
  () => selection.map((id) => index.get(id)).filter((e) => e !== void 0),
688
829
  [selection, index]
689
830
  );
@@ -725,23 +866,50 @@ function FileManager({
725
866
  });
726
867
  };
727
868
  const askDelete = (entries) => confirmDelete ? setDeleting([...entries]) : remove(entries);
869
+ const [asking, setAsking] = React3.useState(null);
870
+ const settleConflicts = (entries, targetId, proceed) => {
871
+ const ids = new Set(entries.map((e) => e.id));
872
+ const siblings = childrenOf(drawn, targetId).filter((e) => !ids.has(e.id));
873
+ const conflicts = findNameConflicts(entries, siblings);
874
+ if (conflicts.length === 0) {
875
+ proceed([...entries]);
876
+ return;
877
+ }
878
+ setAsking({
879
+ conflicts,
880
+ choices: [],
881
+ done: (choices) => {
882
+ if (choices) proceed(...resolveNameConflicts(entries, siblings, conflicts, choices));
883
+ }
884
+ });
885
+ };
886
+ const answerConflict = (choice, applyToAll) => {
887
+ if (!asking) return;
888
+ const next = answerNameConflict(asking.conflicts, asking.choices, choice, applyToAll);
889
+ if (next.length >= asking.conflicts.length) {
890
+ setAsking(null);
891
+ asking.done(next);
892
+ } else setAsking({ ...asking, choices: next });
893
+ };
728
894
  const move = (entries, targetId) => {
729
895
  if (!onMove) return;
730
896
  const ids = entries.map((e) => e.id);
731
897
  const refusal = moveRefusal(index, ids, targetId);
732
898
  if (refusal === "into-itself") onNotify?.({ title: labels.cannotMoveIntoItself, tone: "warn" });
733
899
  if (refusal) return;
734
- const list = topLevel(entries);
735
- void run(
736
- labels.moveTo,
737
- () => onMove(list, targetId),
738
- labels.moved(list.length, folderName(targetId)),
739
- {
740
- kind: "move",
741
- ids: list.map((e) => e.id),
742
- targetId
743
- }
744
- );
900
+ settleConflicts(topLevel(entries), targetId, (list, resolution) => {
901
+ if (list.length === 0) return;
902
+ void run(
903
+ labels.moveTo,
904
+ () => resolution ? onMove(list, targetId, resolution) : onMove(list, targetId),
905
+ labels.moved(list.length, folderName(targetId)),
906
+ {
907
+ kind: "move",
908
+ ids: list.map((e) => e.id),
909
+ targetId
910
+ }
911
+ );
912
+ });
745
913
  };
746
914
  const favorite = (entry) => {
747
915
  if (!onFavoriteChange) return;
@@ -796,6 +964,11 @@ function FileManager({
796
964
  haptics.selection();
797
965
  setSelection((s) => s.includes(id) ? s.filter((x) => x !== id) : [...s, id]);
798
966
  };
967
+ const startSelecting = (id) => {
968
+ haptics.selection();
969
+ setSelecting(true);
970
+ setSelection((s) => s.includes(id) ? s : [...s, id]);
971
+ };
799
972
  const endSelecting = () => {
800
973
  setSelecting(false);
801
974
  setSelection([]);
@@ -905,8 +1078,15 @@ function FileManager({
905
1078
  collapses: !confirmDelete,
906
1079
  onAction: () => askDelete([entry])
907
1080
  } : null;
908
- if (!star && !relocate && !trash) return void 0;
909
- const trailing = relocate && trash ? [relocate, trash] : relocate ? [relocate] : trash ? [trash] : [];
1081
+ const share = onShare && entry.type === "file" ? {
1082
+ key: "share",
1083
+ label: labels.download,
1084
+ icon: "upload",
1085
+ onAction: () => onShare([entry])
1086
+ } : null;
1087
+ if (!star && !relocate && !trash && !share) return void 0;
1088
+ const picked = [share ?? relocate, trash].filter((a) => a !== null);
1089
+ const trailing = picked.length === 2 ? [picked[0], picked[1]] : picked.length === 1 ? [picked[0]] : [];
910
1090
  return { leading: star ? [star] : [], trailing };
911
1091
  };
912
1092
  const pad = theme.space.s4;
@@ -934,49 +1114,78 @@ function FileManager({
934
1114
  const treeable = nested && view === "list" && !searching && special === null;
935
1115
  const meta = entryMeta(entry, drawn, labels, locale);
936
1116
  const where = searching || special ? folderName(entry.parentId) : null;
937
- return /* @__PURE__ */ jsx(View, { style: busy && styles.busy, children: /* @__PURE__ */ jsx(
938
- ListRow,
939
- {
940
- title: entry.name,
941
- subtitle: where ? `${where} \xB7 ${meta}` : meta,
942
- density,
943
- divider: true,
944
- leading: /* @__PURE__ */ jsxs(View, { style: [styles.lead, { paddingStart: indentOf(depth, theme) }], children: [
945
- treeable ? entry.type === "folder" ? (
946
- // No button role: the row is the button, and the disclosure is
947
- // reachable to assistive tech through the row's actions.
948
- /* @__PURE__ */ jsx(
949
- Pressable,
950
- {
951
- accessibilityLabel: isOpen ? labels.collapseFolder(entry.name) : labels.expandFolder(entry.name),
952
- accessibilityState: { expanded: isOpen },
953
- hitSlop: theme.space.s3,
954
- onPress: () => toggleExpanded(entry.id),
955
- style: styles.disclosure,
956
- children: /* @__PURE__ */ jsx(View, { style: isOpen && styles.disclosureOpen, children: /* @__PURE__ */ jsx(
957
- Icon,
958
- {
959
- name: "chevron-right",
960
- size: theme.icon.sm,
961
- color: theme.color.text3,
962
- strokeWidth: 2
963
- }
964
- ) })
965
- }
966
- )
967
- ) : /* @__PURE__ */ jsx(View, { style: styles.disclosure }) : null,
968
- /* @__PURE__ */ jsx(FileIcon, { entry, size: density === "compact" ? "md" : "lg" })
969
- ] }),
970
- trailing: entry.favorite ? /* @__PURE__ */ jsx(Icon, { name: "star", size: theme.icon.sm, color: theme.color.text3 }) : entry.type === "folder" && !selecting && !treeable ? /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: theme.icon.sm, color: theme.color.text3 }) : void 0,
971
- selectable: selecting,
972
- selected: selection.includes(entry.id),
973
- onSelectedChange: () => toggleSelected(entry.id),
974
- onPress: () => open(entry),
975
- swipeActions: swipesFor(entry),
976
- menuItems: selecting ? void 0 : menuFor(entry),
977
- motion
978
- }
979
- ) });
1117
+ const hasDisclosure = treeable && entry.type === "folder";
1118
+ const hasOverflow = android && !selecting;
1119
+ return /* @__PURE__ */ jsxs(View, { style: [styles.rowWrap, busy && styles.busy], children: [
1120
+ /* @__PURE__ */ jsx(
1121
+ ListRow,
1122
+ {
1123
+ title: entry.name,
1124
+ subtitle: where ? `${where} \xB7 ${meta}` : meta,
1125
+ density,
1126
+ divider: true,
1127
+ leading: /* @__PURE__ */ jsxs(View, { style: [styles.lead, { paddingStart: indentOf(depth, theme) }], children: [
1128
+ treeable ? entry.type === "folder" ? (
1129
+ // Holds the disclosure's place; the button itself is a sibling of
1130
+ // the row (below) so two buttons are never nested.
1131
+ /* @__PURE__ */ jsx(View, { style: styles.disclosure })
1132
+ ) : /* @__PURE__ */ jsx(View, { style: styles.disclosure }) : null,
1133
+ /* @__PURE__ */ jsx(FileIcon, { entry, size: density === "compact" ? "md" : "lg" })
1134
+ ] }),
1135
+ trailing: android && !selecting ? (
1136
+ // Android: no swipe or press-and-hold menu (that gesture starts a
1137
+ // selection), so the row's actions sit behind a ghost overflow.
1138
+ /* @__PURE__ */ jsxs(View, { style: styles.trailingRow, children: [
1139
+ entry.favorite ? /* @__PURE__ */ jsx(Icon, { name: "star", size: theme.icon.sm, color: theme.color.text3 }) : null,
1140
+ /* @__PURE__ */ jsx(View, { style: styles.overflow })
1141
+ ] })
1142
+ ) : entry.favorite ? /* @__PURE__ */ jsx(Icon, { name: "star", size: theme.icon.sm, color: theme.color.text3 }) : entry.type === "folder" && !selecting && !treeable ? /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: theme.icon.sm, color: theme.color.text3 }) : void 0,
1143
+ selectable: selecting,
1144
+ selected: selection.includes(entry.id),
1145
+ onSelectedChange: () => toggleSelected(entry.id),
1146
+ onPress: () => open(entry),
1147
+ swipeActions: android ? void 0 : swipesFor(entry),
1148
+ menuItems: selecting || android ? void 0 : menuFor(entry),
1149
+ onLongPress: android && !selecting ? () => startSelecting(entry.id) : void 0,
1150
+ motion
1151
+ }
1152
+ ),
1153
+ hasDisclosure ? /* @__PURE__ */ jsx(
1154
+ View,
1155
+ {
1156
+ pointerEvents: "box-none",
1157
+ style: [styles.slot, { start: theme.space.s4 + indentOf(depth, theme) }],
1158
+ children: /* @__PURE__ */ jsx(
1159
+ Pressable,
1160
+ {
1161
+ accessibilityRole: "button",
1162
+ accessibilityLabel: isOpen ? labels.collapseFolder(entry.name) : labels.expandFolder(entry.name),
1163
+ accessibilityState: { expanded: isOpen },
1164
+ hitSlop: theme.space.s3,
1165
+ onPress: () => toggleExpanded(entry.id),
1166
+ style: styles.disclosure,
1167
+ children: /* @__PURE__ */ jsx(View, { style: isOpen && styles.disclosureOpen, children: /* @__PURE__ */ jsx(
1168
+ Icon,
1169
+ {
1170
+ name: "chevron-right",
1171
+ size: theme.icon.sm,
1172
+ color: theme.color.text3,
1173
+ strokeWidth: 2
1174
+ }
1175
+ ) })
1176
+ }
1177
+ )
1178
+ }
1179
+ ) : null,
1180
+ hasOverflow ? /* @__PURE__ */ jsx(View, { pointerEvents: "box-none", style: [styles.slot, { end: theme.space.s4 }], children: /* @__PURE__ */ jsx(
1181
+ OverflowAction,
1182
+ {
1183
+ label: labels.moreActions(entry.name),
1184
+ items: menuFor(entry),
1185
+ motion
1186
+ }
1187
+ ) }) : null
1188
+ ] });
980
1189
  };
981
1190
  const renderTile = ({ item: entry }) => {
982
1191
  const busy = pendingIds.has(entry.id);
@@ -984,15 +1193,7 @@ function FileManager({
984
1193
  const body = /* @__PURE__ */ jsxs(View, { style: [styles.tile, { width: tileWidth }, busy && styles.busy], children: [
985
1194
  /* @__PURE__ */ jsxs(View, { style: [styles.tileArt, chosen && styles.tileArtChosen], children: [
986
1195
  /* @__PURE__ */ jsx(FileIcon, { entry, size: "xl" }),
987
- selecting ? /* @__PURE__ */ jsx(View, { style: [styles.check, chosen && styles.checkOn], children: chosen ? /* @__PURE__ */ jsx(
988
- Icon,
989
- {
990
- name: "check",
991
- size: theme.icon.xs,
992
- color: theme.color.surface,
993
- strokeWidth: 2.5
994
- }
995
- ) : null }) : null
1196
+ selecting ? /* @__PURE__ */ jsx(View, { style: styles.check, pointerEvents: "none", children: /* @__PURE__ */ jsx(Checkbox, { size: "sm", checked: chosen, accessibilityLabel: entry.name }) }) : null
996
1197
  ] }),
997
1198
  /* @__PURE__ */ jsx(Text, { style: styles.tileName, numberOfLines: 2, children: entry.name }),
998
1199
  /* @__PURE__ */ jsx(Text, { style: styles.tileMeta, numberOfLines: 1, children: entryMeta(entry, drawn, labels, locale) })
@@ -1009,6 +1210,18 @@ function FileManager({
1009
1210
  }
1010
1211
  );
1011
1212
  }
1213
+ if (android) {
1214
+ return /* @__PURE__ */ jsx(
1215
+ Pressable,
1216
+ {
1217
+ accessibilityRole: "button",
1218
+ accessibilityLabel: entry.name,
1219
+ onPress: () => open(entry),
1220
+ onLongPress: () => startSelecting(entry.id),
1221
+ children: body
1222
+ }
1223
+ );
1224
+ }
1012
1225
  return /* @__PURE__ */ jsx(
1013
1226
  ContextMenu,
1014
1227
  {
@@ -1026,7 +1239,7 @@ function FileManager({
1026
1239
  const canBack = special === null && folderId !== null;
1027
1240
  const hasLocations = recents || favoritesOn || childrenOf(drawn, null).some((e) => e.type === "folder");
1028
1241
  const empty = (() => {
1029
- if (error)
1242
+ if (failed)
1030
1243
  return /* @__PURE__ */ jsx(
1031
1244
  EmptyState,
1032
1245
  {
@@ -1036,7 +1249,8 @@ function FileManager({
1036
1249
  onAction: onRetry
1037
1250
  }
1038
1251
  );
1039
- if (showSkeleton) return /* @__PURE__ */ jsx(SkeletonRows, { view, columns, tileWidth, label: labels.loading });
1252
+ if (showSkeleton)
1253
+ return /* @__PURE__ */ jsx(SkeletonRows, { view, columns, tileWidth, label: labels.loading });
1040
1254
  if (loading) return null;
1041
1255
  if (searching)
1042
1256
  return /* @__PURE__ */ jsx(
@@ -1083,7 +1297,40 @@ function FileManager({
1083
1297
  children: [
1084
1298
  wide ? /* @__PURE__ */ jsx(View, { style: styles.side, children: locationsList }) : null,
1085
1299
  /* @__PURE__ */ jsxs(View, { style: styles.main, children: [
1086
- /* @__PURE__ */ jsx(
1300
+ android && selecting ? /* @__PURE__ */ jsxs(View, { style: styles.appBar, accessibilityRole: "toolbar", children: [
1301
+ /* @__PURE__ */ jsx(NavHeaderAction, { icon: "x", accessibilityLabel: labels.done, onPress: endSelecting }),
1302
+ /* @__PURE__ */ jsx(Text, { style: styles.appBarTitle, accessibilityRole: "header", children: labels.selected(selection.length) }),
1303
+ /* @__PURE__ */ jsx(
1304
+ NavHeaderAction,
1305
+ {
1306
+ icon: "folder-input",
1307
+ accessibilityLabel: labels.moveTo,
1308
+ disabled: !onMove || selectedEntries.length === 0,
1309
+ onPress: () => setMoving(selectedEntries)
1310
+ }
1311
+ ),
1312
+ onShare ? /* @__PURE__ */ jsx(
1313
+ NavHeaderAction,
1314
+ {
1315
+ icon: "upload",
1316
+ accessibilityLabel: labels.download,
1317
+ disabled: !selectedEntries.some((e) => e.type === "file"),
1318
+ onPress: () => onShare(selectedEntries.filter((e) => e.type === "file"))
1319
+ }
1320
+ ) : null,
1321
+ /* @__PURE__ */ jsx(
1322
+ NavHeaderAction,
1323
+ {
1324
+ icon: "trash",
1325
+ accessibilityLabel: labels.delete,
1326
+ disabled: !onDelete || selectedEntries.length === 0,
1327
+ onPress: () => {
1328
+ askDelete(selectedEntries);
1329
+ if (!confirmDelete) setSelecting(false);
1330
+ }
1331
+ }
1332
+ )
1333
+ ] }) : /* @__PURE__ */ jsx(
1087
1334
  NavHeader,
1088
1335
  {
1089
1336
  title: selecting ? labels.selected(selection.length) : title,
@@ -1099,7 +1346,7 @@ function FileManager({
1099
1346
  onPress: () => setLocationsOpen(true)
1100
1347
  }
1101
1348
  ) : void 0,
1102
- search: !selecting,
1349
+ showSearch: !selecting,
1103
1350
  searchPlaceholder: labels.searchPlaceholder,
1104
1351
  searchValue: query,
1105
1352
  onSearchChangeText: setQuery,
@@ -1125,7 +1372,7 @@ function FileManager({
1125
1372
  ] })
1126
1373
  }
1127
1374
  ),
1128
- listed.length === 0 || error ? /* @__PURE__ */ jsx(View, { style: styles.empty, children: empty }) : view === "grid" ? /* @__PURE__ */ jsx(
1375
+ listed.length === 0 || failed ? /* @__PURE__ */ jsx(View, { style: styles.empty, children: empty }) : view === "grid" ? /* @__PURE__ */ jsx(
1129
1376
  FlatList,
1130
1377
  {
1131
1378
  data: listed,
@@ -1153,7 +1400,7 @@ function FileManager({
1153
1400
  },
1154
1401
  "list"
1155
1402
  ),
1156
- selecting ? /* @__PURE__ */ jsxs(View, { style: [styles.bar, { paddingBottom: theme.space.s2 + safeAreaBottom }], children: [
1403
+ selecting && !android ? /* @__PURE__ */ jsxs(View, { style: [styles.bar, { paddingBottom: theme.space.s2 + safeAreaBottom }], children: [
1157
1404
  /* @__PURE__ */ jsx(
1158
1405
  Button,
1159
1406
  {
@@ -1279,10 +1526,28 @@ function FileManager({
1279
1526
  motion
1280
1527
  }
1281
1528
  ),
1529
+ asking ? /* @__PURE__ */ jsx(
1530
+ NameConflictDialog,
1531
+ {
1532
+ open: true,
1533
+ onClose: () => {
1534
+ setAsking(null);
1535
+ asking.done(null);
1536
+ },
1537
+ existing: asking.conflicts[asking.choices.length].existing,
1538
+ incoming: asking.conflicts[asking.choices.length].incoming,
1539
+ index: asking.choices.length + 1,
1540
+ total: asking.conflicts.length,
1541
+ onResolve: answerConflict,
1542
+ labels,
1543
+ motion
1544
+ }
1545
+ ) : null,
1282
1546
  /* @__PURE__ */ jsx(
1283
1547
  FileDeleteDialog,
1284
1548
  {
1285
- entries: deleting,
1549
+ open: deleting !== null,
1550
+ entries: deleting ?? [],
1286
1551
  onClose: () => setDeleting(null),
1287
1552
  onConfirm: () => {
1288
1553
  const list = deleting ?? [];
@@ -1344,6 +1609,51 @@ function SkeletonRows({
1344
1609
  var SIDEBAR_WIDTH = (theme) => theme.space[256];
1345
1610
  var DISCLOSURE = (theme) => theme.space.s5;
1346
1611
  var indentOf = (depth, theme) => depth * theme.space[20];
1612
+ function OverflowAction({
1613
+ label,
1614
+ items,
1615
+ motion
1616
+ }) {
1617
+ const { styles, theme } = useStyles(sheet3);
1618
+ const ref = React3.useRef(null);
1619
+ const [open, setOpen] = React3.useState(false);
1620
+ const [anchor, setAnchor] = React3.useState(null);
1621
+ const show = () => {
1622
+ const node = ref.current;
1623
+ if (node && typeof node.measureInWindow === "function") {
1624
+ node.measureInWindow((x, y, width, height) => setAnchor({ x, y, width, height }));
1625
+ }
1626
+ setOpen(true);
1627
+ };
1628
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1629
+ /* @__PURE__ */ jsx(
1630
+ Pressable,
1631
+ {
1632
+ ref,
1633
+ testID: "file-manager-overflow",
1634
+ accessibilityRole: "button",
1635
+ accessibilityLabel: label,
1636
+ onPress: show,
1637
+ hitSlop: Math.max(0, (theme.hit.sm - theme.ctl.sm) / 2),
1638
+ android_ripple: { color: theme.state.pressed, borderless: true },
1639
+ style: styles.overflow,
1640
+ children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: theme.icon.md, color: theme.color.text2 })
1641
+ }
1642
+ ),
1643
+ /* @__PURE__ */ jsx(
1644
+ ContextMenuOverlay,
1645
+ {
1646
+ open,
1647
+ onClose: () => setOpen(false),
1648
+ items,
1649
+ anchor,
1650
+ platform: "android",
1651
+ accessibilityLabel: label,
1652
+ motion
1653
+ }
1654
+ )
1655
+ ] });
1656
+ }
1347
1657
  var sheet3 = createStyleSheet((theme) => ({
1348
1658
  root: { flex: 1, flexDirection: "row", backgroundColor: theme.color.bg },
1349
1659
  side: {
@@ -1358,6 +1668,14 @@ var sheet3 = createStyleSheet((theme) => ({
1358
1668
  headerActions: { flexDirection: "row", alignItems: "center", gap: theme.space.s1 },
1359
1669
  empty: { flex: 1, justifyContent: "center" },
1360
1670
  lead: { flexDirection: "row", alignItems: "center", gap: theme.space.s1 },
1671
+ trailingRow: { flexDirection: "row", alignItems: "center", gap: theme.space.s2 },
1672
+ overflow: {
1673
+ width: theme.ctl.sm,
1674
+ height: theme.ctl.sm,
1675
+ borderRadius: theme.radius.full,
1676
+ alignItems: "center",
1677
+ justifyContent: "center"
1678
+ },
1361
1679
  disclosure: {
1362
1680
  width: DISCLOSURE(theme),
1363
1681
  height: DISCLOSURE(theme),
@@ -1365,6 +1683,8 @@ var sheet3 = createStyleSheet((theme) => ({
1365
1683
  justifyContent: "center"
1366
1684
  },
1367
1685
  disclosureOpen: { transform: [{ rotate: "90deg" }] },
1686
+ rowWrap: { position: "relative" },
1687
+ slot: { position: "absolute", top: 0, bottom: 0, justifyContent: "center" },
1368
1688
  busy: { opacity: theme.state.disabledOpacity },
1369
1689
  standIn: {
1370
1690
  minHeight: theme.ctl.lg,
@@ -1374,10 +1694,9 @@ var sheet3 = createStyleSheet((theme) => ({
1374
1694
  standInText: {
1375
1695
  fontFamily: theme.font.sans,
1376
1696
  fontSize: theme.type.footnote.fontSize,
1377
- fontStyle: "italic",
1378
- color: theme.color.text3
1697
+ color: theme.color.text2
1379
1698
  },
1380
- standInError: { color: theme.color.dangerOnSoft, fontStyle: "normal" },
1699
+ standInError: { color: theme.color.dangerOnSoft },
1381
1700
  gridContent: {
1382
1701
  paddingHorizontal: theme.space.s4,
1383
1702
  paddingTop: theme.space.s2,
@@ -1390,14 +1709,11 @@ var sheet3 = createStyleSheet((theme) => ({
1390
1709
  height: theme.space[76],
1391
1710
  alignItems: "center",
1392
1711
  justifyContent: "center",
1393
- borderRadius: theme.radius.lg,
1712
+ borderRadius: theme.radius.md,
1394
1713
  marginBottom: theme.space.s1
1395
1714
  },
1396
1715
  tileArtChosen: {
1397
- backgroundColor: theme.color.accentSoft,
1398
- borderWidth: theme.borderWidth.base,
1399
- // The measured accent: a selection edge is a graphical object held to 3:1.
1400
- borderColor: theme.focus.ringColor
1716
+ backgroundColor: theme.state.selected
1401
1717
  },
1402
1718
  tileName: {
1403
1719
  fontFamily: theme.font.sans,
@@ -1414,20 +1730,22 @@ var sheet3 = createStyleSheet((theme) => ({
1414
1730
  color: theme.color.text3,
1415
1731
  textAlign: "center"
1416
1732
  },
1417
- check: {
1418
- position: "absolute",
1419
- bottom: theme.space.s1,
1420
- end: theme.space.s1,
1421
- width: theme.space.s5,
1422
- height: theme.space.s5,
1423
- borderRadius: theme.radius.full,
1424
- borderWidth: theme.borderWidth.base,
1425
- borderColor: theme.color.borderStrong,
1426
- backgroundColor: theme.color.surface,
1733
+ // Top-start, where web draws it, so it never sits under the status badge.
1734
+ check: { position: "absolute", top: theme.space.s1, start: theme.space.s1 },
1735
+ appBar: {
1736
+ flexDirection: "row",
1427
1737
  alignItems: "center",
1428
- justifyContent: "center"
1738
+ gap: theme.space.s1,
1739
+ minHeight: theme.layout.appbarH,
1740
+ paddingHorizontal: theme.space.s2,
1741
+ backgroundColor: theme.color.surface2
1742
+ },
1743
+ appBarTitle: {
1744
+ flex: 1,
1745
+ fontFamily: theme.font.sans,
1746
+ fontSize: theme.type.title3.fontSize,
1747
+ color: theme.color.text
1429
1748
  },
1430
- checkOn: { backgroundColor: theme.color.accent, borderColor: theme.color.accent },
1431
1749
  bar: {
1432
1750
  flexDirection: "row",
1433
1751
  justifyContent: "space-around",
@@ -1452,5 +1770,223 @@ var sheet3 = createStyleSheet((theme) => ({
1452
1770
  },
1453
1771
  skeletonText: { gap: theme.space.s2 }
1454
1772
  }));
1773
+ var isPromise = (value) => typeof value?.then === "function";
1774
+ var DEFAULT_NAME_CONFLICT_LABELS = {
1775
+ counter: (i, n) => `Conflict ${i} of ${n}`,
1776
+ title: (name) => `\u201C${name}\u201D already exists`,
1777
+ description: (folder, destination) => `A ${folder ? "folder" : "file"} with this name is already in ${destination ?? "this folder"}.`,
1778
+ existing: (destination) => `In ${destination ?? "this folder"}`,
1779
+ incoming: "Uploading",
1780
+ newer: "Newer",
1781
+ modified: (date) => `Modified ${date}`,
1782
+ skip: "Skip",
1783
+ keepBoth: "Keep both",
1784
+ replace: "Replace",
1785
+ merge: "Merge",
1786
+ applyToAll: (others) => `Do this for the other ${others} ${others === 1 ? "conflict" : "conflicts"}`,
1787
+ keepBothNote: (newName) => `Keep both saves it as \u201C${newName}\u201D.`,
1788
+ folderConsequence: (items) => items === void 0 ? "Replace removes the existing folder and everything in it." : `Replace removes the ${items.toLocaleString()} ${items === 1 ? "file" : "files"} in the existing folder.`,
1789
+ cannotReplace: "The existing item is locked, so it cannot be replaced.",
1790
+ failed: (action) => `${action} failed.`,
1791
+ tryAgain: "Try again"
1792
+ };
1793
+ function keepBothName(name) {
1794
+ const dot = name.lastIndexOf(".");
1795
+ return dot > 0 ? `${name.slice(0, dot)} (1)${name.slice(dot)}` : `${name} (1)`;
1796
+ }
1797
+ function ConflictRow({
1798
+ kind,
1799
+ name,
1800
+ origin,
1801
+ side,
1802
+ newer,
1803
+ labels
1804
+ }) {
1805
+ const { styles: s } = useStyles(sheet4);
1806
+ const date = side?.modifiedAt === void 0 ? "" : new Date(side.modifiedAt).toLocaleDateString(void 0, { day: "numeric", month: "short" });
1807
+ const meta = [
1808
+ kind === "file" && side?.size !== void 0 ? formatFileSize(side.size) : "",
1809
+ date ? labels.modified(date) : ""
1810
+ ].filter(Boolean).join(" \xB7 ");
1811
+ return /* @__PURE__ */ jsxs(View, { style: s.row, children: [
1812
+ /* @__PURE__ */ jsx(
1813
+ IconTile,
1814
+ {
1815
+ icon: FILE_CATEGORY_ICON[fileCategory({ name, type: kind })],
1816
+ tone: kind === "folder" ? "accent" : "neutral",
1817
+ size: "md"
1818
+ }
1819
+ ),
1820
+ /* @__PURE__ */ jsxs(View, { style: s.rowText, children: [
1821
+ /* @__PURE__ */ jsx(Text$1, { variant: "overline", tone: "secondary", children: origin }),
1822
+ /* @__PURE__ */ jsx(Text$1, { variant: "subheadline", style: s.name, numberOfLines: 1, ellipsizeMode: "middle", children: name }),
1823
+ meta ? /* @__PURE__ */ jsx(Text$1, { variant: "caption1", tone: "secondary", style: s.meta, children: meta }) : null
1824
+ ] }),
1825
+ newer ? /* @__PURE__ */ jsx(Badge, { variant: "good", size: "sm", children: labels.newer }) : null
1826
+ ] });
1827
+ }
1828
+ function NameConflictCard({
1829
+ name,
1830
+ kind = "file",
1831
+ destination,
1832
+ existing,
1833
+ incoming,
1834
+ existingItems,
1835
+ index,
1836
+ total,
1837
+ onResolve,
1838
+ loading,
1839
+ error,
1840
+ cannotReplace,
1841
+ labels: labelsProp
1842
+ }) {
1843
+ const { styles: s } = useStyles(sheet4);
1844
+ const labels = React3.useMemo(() => ({ ...DEFAULT_NAME_CONFLICT_LABELS, ...labelsProp }), [labelsProp]);
1845
+ const [pending, setPending] = React3.useState(null);
1846
+ const [failed, setFailed] = React3.useState(null);
1847
+ const [all, setAll] = React3.useState(false);
1848
+ const mounted = React3.useRef(true);
1849
+ React3.useEffect(
1850
+ () => () => {
1851
+ mounted.current = false;
1852
+ },
1853
+ []
1854
+ );
1855
+ const folder = kind === "folder";
1856
+ const batch = total !== void 0 && total > 1;
1857
+ const busy = loading ?? pending;
1858
+ const newer = newerSide(existing?.modifiedAt, incoming?.modifiedAt);
1859
+ const resolve = (choice) => () => {
1860
+ if (busy) return;
1861
+ setFailed(null);
1862
+ const result = onResolve(choice, batch && all);
1863
+ if (!isPromise(result)) return;
1864
+ setPending(choice);
1865
+ result.then(
1866
+ () => {
1867
+ if (mounted.current) setPending(null);
1868
+ },
1869
+ () => {
1870
+ if (!mounted.current) return;
1871
+ setPending(null);
1872
+ setFailed(choice);
1873
+ }
1874
+ );
1875
+ };
1876
+ const choices = folder ? [
1877
+ { choice: "skip", label: labels.skip },
1878
+ { choice: "replace", label: labels.replace },
1879
+ { choice: "merge", label: labels.merge, primary: true }
1880
+ ] : [
1881
+ { choice: "skip", label: labels.skip },
1882
+ { choice: "keep-both", label: labels.keepBoth },
1883
+ { choice: "replace", label: labels.replace, primary: true }
1884
+ ];
1885
+ const primary = choices.find((c) => c.primary);
1886
+ const retry = failed ?? primary.choice;
1887
+ const showError = error !== void 0 || failed !== null;
1888
+ return /* @__PURE__ */ jsxs(View, { style: s.card, accessibilityRole: "alert", children: [
1889
+ /* @__PURE__ */ jsxs(View, { style: s.header, children: [
1890
+ index !== void 0 && total !== void 0 ? /* @__PURE__ */ jsx(Text$1, { variant: "overline", tone: "secondary", children: labels.counter(index, total) }) : null,
1891
+ /* @__PURE__ */ jsx(Text$1, { variant: "headline", style: s.title, children: labels.title(name) }),
1892
+ /* @__PURE__ */ jsx(Text$1, { variant: "subheadline", tone: "secondary", children: labels.description(folder, destination) })
1893
+ ] }),
1894
+ /* @__PURE__ */ jsxs(View, { style: s.compare, children: [
1895
+ /* @__PURE__ */ jsx(
1896
+ ConflictRow,
1897
+ {
1898
+ kind,
1899
+ name,
1900
+ origin: labels.existing(destination),
1901
+ side: existing,
1902
+ newer: newer === "a",
1903
+ labels
1904
+ }
1905
+ ),
1906
+ /* @__PURE__ */ jsx(
1907
+ ConflictRow,
1908
+ {
1909
+ kind,
1910
+ name,
1911
+ origin: labels.incoming,
1912
+ side: incoming,
1913
+ newer: newer === "b",
1914
+ labels
1915
+ }
1916
+ )
1917
+ ] }),
1918
+ folder ? /* @__PURE__ */ jsx(View, { style: s.consequence, children: /* @__PURE__ */ jsx(Text$1, { variant: "footnote", children: labels.folderConsequence(existingItems) }) }) : null,
1919
+ cannotReplace ? /* @__PURE__ */ jsx(Text$1, { variant: "footnote", tone: "secondary", children: cannotReplace }) : null,
1920
+ batch ? /* @__PURE__ */ jsx(
1921
+ Checkbox,
1922
+ {
1923
+ size: "sm",
1924
+ label: labels.applyToAll((total ?? 1) - 1),
1925
+ checked: all,
1926
+ disabled: !!busy,
1927
+ onCheckedChange: setAll
1928
+ }
1929
+ ) : null,
1930
+ showError ? /* @__PURE__ */ jsx(
1931
+ Alert,
1932
+ {
1933
+ tone: "danger",
1934
+ size: "compact",
1935
+ title: error ?? labels.failed(choices.find((c) => c.choice === retry)?.label ?? ""),
1936
+ action: /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", disabled: !!busy, onPress: resolve(retry), children: labels.tryAgain })
1937
+ }
1938
+ ) : null,
1939
+ /* @__PURE__ */ jsx(View, { style: s.actions, children: choices.map((c) => /* @__PURE__ */ jsx(
1940
+ Button,
1941
+ {
1942
+ variant: c.primary ? "primary" : "outline",
1943
+ size: "md",
1944
+ loading: busy === c.choice,
1945
+ disabled: !!busy && busy !== c.choice || c.choice === "replace" && !!cannotReplace,
1946
+ onPress: resolve(c.choice),
1947
+ children: c.label
1948
+ },
1949
+ c.choice
1950
+ )) }),
1951
+ !folder ? /* @__PURE__ */ jsx(Text$1, { variant: "footnote", tone: "secondary", children: labels.keepBothNote(keepBothName(name)) }) : null
1952
+ ] });
1953
+ }
1954
+ var sheet4 = createStyleSheet((theme) => ({
1955
+ card: {
1956
+ width: "100%",
1957
+ maxWidth: theme.panel.xl,
1958
+ backgroundColor: theme.color.surface,
1959
+ borderRadius: theme.radius.xl,
1960
+ borderWidth: theme.borderWidth.base,
1961
+ borderColor: theme.color.border,
1962
+ padding: theme.space.s5,
1963
+ gap: theme.space.s3,
1964
+ ...theme.shadow.lg
1965
+ },
1966
+ header: { gap: theme.space.s1 },
1967
+ title: { color: theme.color.text },
1968
+ compare: {
1969
+ gap: theme.space.s3,
1970
+ padding: theme.space.s3,
1971
+ borderRadius: theme.radius.md,
1972
+ backgroundColor: theme.color.surface2
1973
+ },
1974
+ row: { flexDirection: "row", alignItems: "center", gap: theme.space.s3 },
1975
+ rowText: { flex: 1, minWidth: 0, gap: theme.space[2] },
1976
+ name: { fontWeight: theme.type.headline.fontWeight, color: theme.color.text },
1977
+ meta: { fontVariant: ["tabular-nums"] },
1978
+ consequence: {
1979
+ borderRadius: theme.radius.md,
1980
+ backgroundColor: theme.color.surface2,
1981
+ paddingHorizontal: theme.space.s4,
1982
+ paddingVertical: theme.space.s3
1983
+ },
1984
+ actions: {
1985
+ flexDirection: "row",
1986
+ flexWrap: "wrap",
1987
+ justifyContent: "flex-end",
1988
+ gap: theme.space.s2
1989
+ }
1990
+ }));
1455
1991
 
1456
- export { FileDeleteDialog, FileIcon, FileInfoSheet, FileLocations, FileManager, FileMoveSheet, FileNameDialog, FileOptionsSheet, FilePreviewSheet, entryMeta, file_manager_labels_exports, useDelayedLoading, useFileManagerLabels };
1992
+ export { DEFAULT_NAME_CONFLICT_LABELS, FileDeleteDialog, FileIcon, FileInfoSheet, FileLocations, FileManager, FileMoveSheet, FileNameDialog, FileOptionsSheet, FilePreviewSheet, NameConflictCard, entryMeta, keepBothName };