@qw-ui/core 0.3.0-next.40 → 0.3.0-next.42

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 (402) hide show
  1. package/README.md +21 -37
  2. package/dist/action-sheet/action-sheet.d.ts +110 -0
  3. package/dist/action-sheet/index.d.ts +2 -0
  4. package/dist/action-sheet/index.js +2 -0
  5. package/dist/action-sheet-Cvcr1S_m.js +183 -0
  6. package/dist/action-sheet-Cvcr1S_m.js.map +1 -0
  7. package/dist/area-picker/area-picker.d.ts +113 -0
  8. package/dist/area-picker/index.d.ts +1 -0
  9. package/dist/area-picker/index.js +348 -0
  10. package/dist/area-picker/index.js.map +1 -0
  11. package/dist/aria-description-CimD2M_C.js +13 -0
  12. package/dist/aria-description-CimD2M_C.js.map +1 -0
  13. package/dist/aria-description.d.ts +2 -0
  14. package/dist/avatar/avatar-load.d.ts +76 -0
  15. package/dist/avatar/avatar.d.ts +22 -5
  16. package/dist/avatar/index.d.ts +1 -0
  17. package/dist/avatar/index.js +57 -18
  18. package/dist/avatar/index.js.map +1 -1
  19. package/dist/avatar-load-w9dq05oV.js +139 -0
  20. package/dist/avatar-load-w9dq05oV.js.map +1 -0
  21. package/dist/back-top/back-top.d.ts +77 -0
  22. package/dist/back-top/index.d.ts +1 -0
  23. package/dist/back-top/index.js +189 -0
  24. package/dist/back-top/index.js.map +1 -0
  25. package/dist/badge/badge.d.ts +9 -0
  26. package/dist/badge/index.js +14 -1
  27. package/dist/badge/index.js.map +1 -1
  28. package/dist/button/button.d.ts +13 -0
  29. package/dist/button/index.js +3 -5
  30. package/dist/button/index.js.map +1 -1
  31. package/dist/calendar/calendar.d.ts +100 -0
  32. package/dist/calendar/index.d.ts +1 -0
  33. package/dist/calendar/index.js +2 -0
  34. package/dist/calendar-CmpK3stz.js +363 -0
  35. package/dist/calendar-CmpK3stz.js.map +1 -0
  36. package/dist/card/card.d.ts +68 -0
  37. package/dist/card/index.d.ts +2 -0
  38. package/dist/card/index.js +2 -0
  39. package/dist/card-DRtWa6Cr.js +107 -0
  40. package/dist/card-DRtWa6Cr.js.map +1 -0
  41. package/dist/cascader/cascader.d.ts +115 -0
  42. package/dist/cascader/index.d.ts +1 -0
  43. package/dist/cascader/index.js +2 -0
  44. package/dist/cascader-D-xMjs7P.js +333 -0
  45. package/dist/cascader-D-xMjs7P.js.map +1 -0
  46. package/dist/cell/cell.d.ts +41 -0
  47. package/dist/cell/index.d.ts +1 -0
  48. package/dist/cell/index.js +43 -0
  49. package/dist/cell/index.js.map +1 -0
  50. package/dist/check-list/check-list.d.ts +78 -0
  51. package/dist/check-list/index.d.ts +2 -0
  52. package/dist/check-list/index.js +2 -0
  53. package/dist/check-list-BvZHQt5w.js +60 -0
  54. package/dist/check-list-BvZHQt5w.js.map +1 -0
  55. package/dist/checkbox/checkbox.d.ts +59 -0
  56. package/dist/checkbox/index.d.ts +2 -0
  57. package/dist/checkbox/index.js +2 -0
  58. package/dist/checkbox-BlndJrz5.js +127 -0
  59. package/dist/checkbox-BlndJrz5.js.map +1 -0
  60. package/dist/checkbox-group/checkbox-group.d.ts +86 -0
  61. package/dist/checkbox-group/index.d.ts +3 -0
  62. package/dist/checkbox-group/index.js +2 -0
  63. package/dist/checkbox-group-gGfsTv-e.js +223 -0
  64. package/dist/checkbox-group-gGfsTv-e.js.map +1 -0
  65. package/dist/choice-group-C4c9m0qe.js +373 -0
  66. package/dist/choice-group-C4c9m0qe.js.map +1 -0
  67. package/dist/circle/circle.d.ts +97 -0
  68. package/dist/circle/index.d.ts +1 -0
  69. package/dist/circle/index.js +119 -0
  70. package/dist/circle/index.js.map +1 -0
  71. package/dist/collapse/collapse.d.ts +98 -0
  72. package/dist/collapse/index.d.ts +2 -0
  73. package/dist/collapse/index.js +2 -0
  74. package/dist/collapse-B969h7-H.js +226 -0
  75. package/dist/collapse-B969h7-H.js.map +1 -0
  76. package/dist/countdown/countdown.d.ts +114 -0
  77. package/dist/countdown/index.d.ts +1 -0
  78. package/dist/countdown/index.js +309 -0
  79. package/dist/countdown/index.js.map +1 -0
  80. package/dist/date-picker/date-picker.d.ts +168 -0
  81. package/dist/date-picker/index.d.ts +1 -0
  82. package/dist/date-picker/index.js +401 -0
  83. package/dist/date-picker/index.js.map +1 -0
  84. package/dist/descriptions/descriptions.d.ts +69 -0
  85. package/dist/descriptions/index.d.ts +1 -0
  86. package/dist/descriptions/index.js +86 -0
  87. package/dist/descriptions/index.js.map +1 -0
  88. package/dist/dialog/dialog.d.ts +32 -3
  89. package/dist/dialog/index.js +58 -3
  90. package/dist/dialog/index.js.map +1 -1
  91. package/dist/divider/divider.d.ts +18 -2
  92. package/dist/divider/index.js +20 -2
  93. package/dist/divider/index.js.map +1 -1
  94. package/dist/dropdown/dropdown.d.ts +172 -0
  95. package/dist/dropdown/index.d.ts +2 -0
  96. package/dist/dropdown/index.js +467 -0
  97. package/dist/dropdown/index.js.map +1 -0
  98. package/dist/ellipsis/ellipsis-layout.d.ts +34 -0
  99. package/dist/ellipsis/ellipsis.d.ts +88 -0
  100. package/dist/ellipsis/index.d.ts +2 -0
  101. package/dist/ellipsis/index.js +320 -0
  102. package/dist/ellipsis/index.js.map +1 -0
  103. package/dist/empty/empty-illustration.d.ts +3 -0
  104. package/dist/empty/empty.d.ts +43 -1
  105. package/dist/empty/index.js +2 -21
  106. package/dist/empty-CAgyvhUI.js +166 -0
  107. package/dist/empty-CAgyvhUI.js.map +1 -0
  108. package/dist/field/field.d.ts +95 -0
  109. package/dist/field/index.d.ts +2 -0
  110. package/dist/field/index.js +2 -0
  111. package/dist/field-DMHGIMZF.js +241 -0
  112. package/dist/field-DMHGIMZF.js.map +1 -0
  113. package/dist/floating-bubble/floating-bubble.d.ts +116 -0
  114. package/dist/floating-bubble/index.d.ts +1 -0
  115. package/dist/floating-bubble/index.js +333 -0
  116. package/dist/floating-bubble/index.js.map +1 -0
  117. package/dist/floating-panel/floating-panel.d.ts +80 -0
  118. package/dist/floating-panel/index.d.ts +2 -0
  119. package/dist/floating-panel/index.js +2 -0
  120. package/dist/floating-panel-Cbm5njBJ.js +363 -0
  121. package/dist/floating-panel-Cbm5njBJ.js.map +1 -0
  122. package/dist/footer/footer.d.ts +94 -0
  123. package/dist/footer/index.d.ts +1 -0
  124. package/dist/footer/index.js +154 -0
  125. package/dist/footer/index.js.map +1 -0
  126. package/dist/form/connect.d.ts +6 -0
  127. package/dist/form/form.d.ts +100 -0
  128. package/dist/form/ids.d.ts +14 -0
  129. package/dist/form/index.d.ts +13 -0
  130. package/dist/form/index.js +3 -0
  131. package/dist/form/methods.d.ts +5 -0
  132. package/dist/form/model.d.ts +24 -0
  133. package/dist/form/native.d.ts +25 -0
  134. package/dist/form/rules.d.ts +40 -0
  135. package/dist/form/ssr.d.ts +7 -0
  136. package/dist/form/types.d.ts +150 -0
  137. package/dist/form-BAGkIEMY.js +1354 -0
  138. package/dist/form-BAGkIEMY.js.map +1 -0
  139. package/dist/format-BDUY0C_c.js +89 -0
  140. package/dist/format-BDUY0C_c.js.map +1 -0
  141. package/dist/gesture-_SRHIvBm.js +30 -0
  142. package/dist/gesture-_SRHIvBm.js.map +1 -0
  143. package/dist/grid/grid-item.d.ts +22 -0
  144. package/dist/grid/grid.d.ts +42 -0
  145. package/dist/grid/index.d.ts +2 -0
  146. package/dist/grid/index.js +73 -0
  147. package/dist/grid/index.js.map +1 -0
  148. package/dist/icon/icon.d.ts +37 -1
  149. package/dist/icon/identity.d.ts +3 -0
  150. package/dist/icon/index.js +2 -20
  151. package/dist/icon-Cgdbnk1u.js +77 -0
  152. package/dist/icon-Cgdbnk1u.js.map +1 -0
  153. package/dist/image/image-load.d.ts +24 -0
  154. package/dist/image/image.d.ts +45 -8
  155. package/dist/image/index.d.ts +1 -0
  156. package/dist/image/index.js +116 -14
  157. package/dist/image/index.js.map +1 -1
  158. package/dist/image-preview/image-preview.d.ts +124 -0
  159. package/dist/image-preview/index.d.ts +1 -0
  160. package/dist/image-preview/index.js +450 -0
  161. package/dist/image-preview/index.js.map +1 -0
  162. package/dist/index-bar/index-bar.d.ts +121 -0
  163. package/dist/index-bar/index.d.ts +1 -0
  164. package/dist/index-bar/index.js +386 -0
  165. package/dist/index-bar/index.js.map +1 -0
  166. package/dist/index.d.ts +107 -14
  167. package/dist/index.js +148 -14
  168. package/dist/index.js.map +1 -0
  169. package/dist/infinite-scroll/index.d.ts +1 -0
  170. package/dist/infinite-scroll/index.js +248 -0
  171. package/dist/infinite-scroll/index.js.map +1 -0
  172. package/dist/infinite-scroll/infinite-scroll.d.ts +95 -0
  173. package/dist/input/index.js +181 -22
  174. package/dist/input/index.js.map +1 -1
  175. package/dist/input/input.d.ts +44 -1
  176. package/dist/layer-IpFrl5--.js +414 -0
  177. package/dist/layer-IpFrl5--.js.map +1 -0
  178. package/dist/layout-BRSqi4AQ.js +43 -0
  179. package/dist/layout-BRSqi4AQ.js.map +1 -0
  180. package/dist/layout.d.ts +13 -0
  181. package/dist/list/index.d.ts +2 -0
  182. package/dist/list/index.js +2 -0
  183. package/dist/list/list.d.ts +30 -0
  184. package/dist/list-6-iz-Irh.js +28 -0
  185. package/dist/list-6-iz-Irh.js.map +1 -0
  186. package/dist/loading/index.js +45 -2
  187. package/dist/loading/index.js.map +1 -1
  188. package/dist/loading/loading.d.ts +45 -2
  189. package/dist/modal-dialog-machine-CF9_z3Dm.js +487 -0
  190. package/dist/modal-dialog-machine-CF9_z3Dm.js.map +1 -0
  191. package/dist/modal-dialog-machine.d.ts +21 -0
  192. package/dist/modal-dismissable-lifetime.d.ts +21 -0
  193. package/dist/modal-registry.d.ts +24 -0
  194. package/dist/modal-render-hydration.d.ts +35 -0
  195. package/dist/modal-render-runtime.d.ts +19 -0
  196. package/dist/modal-render-scope.d.ts +63 -0
  197. package/dist/nav-bar/index.d.ts +1 -0
  198. package/dist/nav-bar/index.js +115 -0
  199. package/dist/nav-bar/index.js.map +1 -0
  200. package/dist/nav-bar/nav-bar.d.ts +76 -0
  201. package/dist/notice-bar/index.d.ts +2 -0
  202. package/dist/notice-bar/index.js +2 -0
  203. package/dist/notice-bar/notice-bar.d.ts +103 -0
  204. package/dist/notice-bar-DMpwLvRb.js +231 -0
  205. package/dist/notice-bar-DMpwLvRb.js.map +1 -0
  206. package/dist/notify/index.d.ts +1 -0
  207. package/dist/notify/index.js +251 -0
  208. package/dist/notify/index.js.map +1 -0
  209. package/dist/notify/notify.d.ts +123 -0
  210. package/dist/number-keyboard/index.d.ts +1 -0
  211. package/dist/number-keyboard/index.js +333 -0
  212. package/dist/number-keyboard/index.js.map +1 -0
  213. package/dist/number-keyboard/number-keyboard.d.ts +141 -0
  214. package/dist/page-indicator/index.d.ts +1 -0
  215. package/dist/page-indicator/index.js +138 -0
  216. package/dist/page-indicator/index.js.map +1 -0
  217. package/dist/page-indicator/page-indicator.d.ts +93 -0
  218. package/dist/pagination/index.d.ts +1 -0
  219. package/dist/pagination/index.js +198 -0
  220. package/dist/pagination/index.js.map +1 -0
  221. package/dist/pagination/pagination.d.ts +125 -0
  222. package/dist/password-input/index.d.ts +1 -0
  223. package/dist/password-input/index.js +317 -0
  224. package/dist/password-input/index.js.map +1 -0
  225. package/dist/password-input/password-input.d.ts +144 -0
  226. package/dist/picker/index.d.ts +8 -0
  227. package/dist/picker/index.js +2 -0
  228. package/dist/picker/picker-machine.d.ts +80 -0
  229. package/dist/picker/picker.d.ts +121 -0
  230. package/dist/picker/platform.d.ts +84 -0
  231. package/dist/picker/selection-connect.d.ts +90 -0
  232. package/dist/picker/selection-model.d.ts +211 -0
  233. package/dist/picker-BykFntQN.js +1675 -0
  234. package/dist/picker-BykFntQN.js.map +1 -0
  235. package/dist/popover/index.d.ts +3 -0
  236. package/dist/popover/index.js +253 -0
  237. package/dist/popover/index.js.map +1 -0
  238. package/dist/popover/layer.d.ts +44 -0
  239. package/dist/popover/popover.d.ts +104 -0
  240. package/dist/popover/positioning.d.ts +132 -0
  241. package/dist/popup/index.d.ts +2 -0
  242. package/dist/popup/index.js +2 -0
  243. package/dist/popup/popup.d.ts +60 -0
  244. package/dist/popup-z5d8IYCt.js +576 -0
  245. package/dist/popup-z5d8IYCt.js.map +1 -0
  246. package/dist/portal-BHCNTWhg.js +78 -0
  247. package/dist/portal-BHCNTWhg.js.map +1 -0
  248. package/dist/portal.d.ts +61 -0
  249. package/dist/price/format.d.ts +19 -0
  250. package/dist/price/index.d.ts +1 -0
  251. package/dist/price/index.js +154 -0
  252. package/dist/price/index.js.map +1 -0
  253. package/dist/price/price.d.ts +88 -0
  254. package/dist/progress/index.d.ts +1 -0
  255. package/dist/progress/index.js +2 -0
  256. package/dist/progress/progress.d.ts +32 -0
  257. package/dist/progress-f3iYEfdA.js +37 -0
  258. package/dist/progress-f3iYEfdA.js.map +1 -0
  259. package/dist/pull-refresh/index.d.ts +1 -0
  260. package/dist/pull-refresh/index.js +414 -0
  261. package/dist/pull-refresh/index.js.map +1 -0
  262. package/dist/pull-refresh/pull-refresh.d.ts +118 -0
  263. package/dist/radio-group/index.d.ts +3 -0
  264. package/dist/radio-group/index.js +2 -0
  265. package/dist/radio-group/radio-group.d.ts +78 -0
  266. package/dist/radio-group-BOIMuqnS.js +230 -0
  267. package/dist/radio-group-BOIMuqnS.js.map +1 -0
  268. package/dist/rate/index.d.ts +1 -0
  269. package/dist/rate/index.js +2 -0
  270. package/dist/rate/rate-form.d.ts +28 -0
  271. package/dist/rate/rate.d.ts +144 -0
  272. package/dist/rate-5XsU2QkY.js +631 -0
  273. package/dist/rate-5XsU2QkY.js.map +1 -0
  274. package/dist/reorder/index.d.ts +1 -0
  275. package/dist/reorder/index.js +720 -0
  276. package/dist/reorder/index.js.map +1 -0
  277. package/dist/reorder/reorder.d.ts +190 -0
  278. package/dist/result/index.d.ts +1 -0
  279. package/dist/result/index.js +123 -0
  280. package/dist/result/index.js.map +1 -0
  281. package/dist/result/result.d.ts +88 -0
  282. package/dist/safe-area/index.d.ts +1 -0
  283. package/dist/safe-area/index.js +42 -0
  284. package/dist/safe-area/index.js.map +1 -0
  285. package/dist/safe-area/safe-area.d.ts +28 -0
  286. package/dist/search-bar/index.js +3 -1
  287. package/dist/search-bar/index.js.map +1 -1
  288. package/dist/search-bar/search-bar.d.ts +4 -0
  289. package/dist/segmented/index.d.ts +2 -0
  290. package/dist/segmented/index.js +2 -0
  291. package/dist/segmented/segmented.d.ts +127 -0
  292. package/dist/segmented-BaU38_L4.js +367 -0
  293. package/dist/segmented-BaU38_L4.js.map +1 -0
  294. package/dist/selection-form-BOM_odUk.js +88 -0
  295. package/dist/selection-form-BOM_odUk.js.map +1 -0
  296. package/dist/selection-form.d.ts +27 -0
  297. package/dist/selection-ivXqO1eu.js +55 -0
  298. package/dist/selection-ivXqO1eu.js.map +1 -0
  299. package/dist/selection.d.ts +29 -0
  300. package/dist/selector/choice-group.d.ts +114 -0
  301. package/dist/selector/index.d.ts +2 -0
  302. package/dist/selector/index.js +2 -0
  303. package/dist/selector/selector.d.ts +90 -0
  304. package/dist/selector-BU2MMJ4N.js +93 -0
  305. package/dist/selector-BU2MMJ4N.js.map +1 -0
  306. package/dist/share-sheet/index.d.ts +1 -0
  307. package/dist/share-sheet/index.js +138 -0
  308. package/dist/share-sheet/index.js.map +1 -0
  309. package/dist/share-sheet/share-sheet.d.ts +139 -0
  310. package/dist/skeleton/index.js +51 -2
  311. package/dist/skeleton/index.js.map +1 -1
  312. package/dist/skeleton/skeleton.d.ts +34 -3
  313. package/dist/slider/index.d.ts +1 -0
  314. package/dist/slider/index.js +482 -0
  315. package/dist/slider/index.js.map +1 -0
  316. package/dist/slider/slider.d.ts +174 -0
  317. package/dist/space/index.d.ts +1 -0
  318. package/dist/space/index.js +52 -0
  319. package/dist/space/index.js.map +1 -0
  320. package/dist/space/space.d.ts +46 -0
  321. package/dist/statistic/index.d.ts +1 -0
  322. package/dist/statistic/index.js +152 -0
  323. package/dist/statistic/index.js.map +1 -0
  324. package/dist/statistic/statistic.d.ts +101 -0
  325. package/dist/stepper/index.js +62 -3
  326. package/dist/stepper/index.js.map +1 -1
  327. package/dist/stepper/stepper.d.ts +44 -4
  328. package/dist/steps/index.d.ts +1 -0
  329. package/dist/steps/index.js +72 -0
  330. package/dist/steps/index.js.map +1 -0
  331. package/dist/steps/steps.d.ts +67 -0
  332. package/dist/sticky/index.d.ts +1 -0
  333. package/dist/sticky/index.js +145 -0
  334. package/dist/sticky/index.js.map +1 -0
  335. package/dist/sticky/sticky.d.ts +70 -0
  336. package/dist/swipe-action/index.d.ts +1 -0
  337. package/dist/swipe-action/index.js +417 -0
  338. package/dist/swipe-action/index.js.map +1 -0
  339. package/dist/swipe-action/swipe-action.d.ts +148 -0
  340. package/dist/swiper/gesture.d.ts +32 -0
  341. package/dist/swiper/index.d.ts +1 -0
  342. package/dist/swiper/index.js +2 -0
  343. package/dist/swiper/swiper.d.ts +177 -0
  344. package/dist/swiper-BKivDkHp.js +550 -0
  345. package/dist/swiper-BKivDkHp.js.map +1 -0
  346. package/dist/switch/index.js +135 -10
  347. package/dist/switch/index.js.map +1 -1
  348. package/dist/switch/switch.d.ts +93 -6
  349. package/dist/tabbar/index.js +46 -1
  350. package/dist/tabbar/index.js.map +1 -1
  351. package/dist/tabbar/tabbar.d.ts +50 -0
  352. package/dist/tabs/index.js +22 -1
  353. package/dist/tabs/index.js.map +1 -1
  354. package/dist/tabs/tabs.d.ts +12 -8
  355. package/dist/tag/index.js +123 -2
  356. package/dist/tag/index.js.map +1 -1
  357. package/dist/tag/tag.d.ts +67 -1
  358. package/dist/textarea/index.d.ts +2 -0
  359. package/dist/textarea/index.js +2 -242
  360. package/dist/textarea/platform.d.ts +22 -0
  361. package/dist/textarea/textarea.d.ts +165 -46
  362. package/dist/textarea-qbnruDUG.js +775 -0
  363. package/dist/textarea-qbnruDUG.js.map +1 -0
  364. package/dist/time-picker/index.d.ts +1 -0
  365. package/dist/time-picker/index.js +228 -0
  366. package/dist/time-picker/index.js.map +1 -0
  367. package/dist/time-picker/time-picker.d.ts +83 -0
  368. package/dist/timeline/index.d.ts +1 -0
  369. package/dist/timeline/index.js +131 -0
  370. package/dist/timeline/index.js.map +1 -0
  371. package/dist/timeline/timeline.d.ts +79 -0
  372. package/dist/toast/index.js +47 -4
  373. package/dist/toast/index.js.map +1 -1
  374. package/dist/toast/toast.d.ts +26 -3
  375. package/dist/top-bar/index.js +16 -2
  376. package/dist/top-bar/index.js.map +1 -1
  377. package/dist/top-bar/top-bar.d.ts +13 -2
  378. package/dist/tree-select/index.d.ts +1 -0
  379. package/dist/tree-select/index.js +512 -0
  380. package/dist/tree-select/index.js.map +1 -0
  381. package/dist/tree-select/tree-select.d.ts +215 -0
  382. package/dist/typography/index.d.ts +1 -0
  383. package/dist/typography/index.js +82 -0
  384. package/dist/typography/index.js.map +1 -0
  385. package/dist/typography/typography.d.ts +54 -0
  386. package/dist/upload/index.d.ts +1 -0
  387. package/dist/upload/index.js +458 -0
  388. package/dist/upload/index.js.map +1 -0
  389. package/dist/upload/upload.d.ts +172 -0
  390. package/dist/virtual-list/index.d.ts +1 -0
  391. package/dist/virtual-list/index.js +445 -0
  392. package/dist/virtual-list/index.js.map +1 -0
  393. package/dist/virtual-list/virtual-list.d.ts +160 -0
  394. package/dist/visual-manifest.d.ts +6 -0
  395. package/dist/watermark/index.d.ts +1 -0
  396. package/dist/watermark/index.js +260 -0
  397. package/dist/watermark/index.js.map +1 -0
  398. package/dist/watermark/watermark.d.ts +106 -0
  399. package/package.json +399 -50
  400. package/dist/empty/index.js.map +0 -1
  401. package/dist/icon/index.js.map +0 -1
  402. package/dist/textarea/index.js.map +0 -1
@@ -0,0 +1,1354 @@
1
+ import { C as setFormValue, S as normalizeFormNamePath, _ as formValuesEqual, b as hasFormValue, d as resolveFieldState, f as cloneFormValue, g as formValueFingerprint, h as formFieldNativeName, m as formFieldKey, p as cloneFormValues, v as freezeFormValues, x as mergeFormValues, y as getFormValue } from "./field-DMHGIMZF.js";
2
+ import { o as normalizeSegmentedItems } from "./segmented-BaU38_L4.js";
3
+ import { createMachine } from "@zag-js/core";
4
+ import { addDomEvent, isDocument, isElement, isHTMLElement, isInputElement, isNode, observeChildren, setProperty } from "@zag-js/dom-query";
5
+ import { ref } from "@zag-js/store";
6
+ //#region src/form/ids.ts
7
+ /** HTML form id owned by one Core instance. */
8
+ function formDomId(scopeId) {
9
+ return `form:${scopeId}`;
10
+ }
11
+ /** Accessible name target for the form landmark. */
12
+ function formLabelId(scopeId) {
13
+ return `form:${scopeId}:label`;
14
+ }
15
+ /**
16
+ * Stable field stem. `formFieldKey` is the injective NamePath encoding.
17
+ * Field root id is `field:` plus this stem.
18
+ */
19
+ function formFieldStem(scopeId, name) {
20
+ return `form:${scopeId}:field:${formFieldKey(name)}`;
21
+ }
22
+ /** Actual control id shared by Input, selection and raw native inputs. */
23
+ function formControlStem(scopeId, name) {
24
+ return `${formFieldStem(scopeId, name)}:control`;
25
+ }
26
+ /** Field root id produced by `resolveFieldState`. */
27
+ function formFieldRootId(scopeId, name) {
28
+ return `field:${formFieldStem(scopeId, name)}`;
29
+ }
30
+ //#endregion
31
+ //#region src/form/native.ts
32
+ const typedHosts = "qw-checkbox, qw-radio-group, qw-segmented";
33
+ const isHtmlElement = (node) => isHTMLElement(node) && node.namespaceURI === "http://www.w3.org/1999/xhtml";
34
+ function textValue$1(value) {
35
+ return typeof value === "string" ? value : typeof value === "number" ? String(value) : "";
36
+ }
37
+ function fieldByControl(port, id) {
38
+ const scopeId = port.scope.id;
39
+ if (!scopeId) return void 0;
40
+ return port.fields().find((field) => formControlStem(scopeId, field.name) === id);
41
+ }
42
+ /**
43
+ * One client lifecycle for raw inputs, supported native selection elements,
44
+ * composite blur, and a single deferred reset transaction.
45
+ * This listener is the only raw input/change transport. Getter props must not
46
+ * subscribe to the same event (Vue normalizes onChange into onInput).
47
+ * Selection controls keep their own reset listeners; user echoes are suppressed
48
+ * until this transaction finishes so they cannot overwrite the Form reset.
49
+ */
50
+ function trackFormNative(port) {
51
+ const root = port.scope.getRootNode?.();
52
+ if (!root || typeof document === "undefined") return () => {
53
+ port.bindSync(void 0);
54
+ };
55
+ let stopped = false;
56
+ let refreshQueued = false;
57
+ const cleanups = [];
58
+ const pending = /* @__PURE__ */ new Set();
59
+ const release = () => {
60
+ cleanups.splice(0).forEach((cleanup) => cleanup());
61
+ };
62
+ const sync = () => {
63
+ if (stopped || !port.scope.id) return;
64
+ for (const field of port.fields()) {
65
+ const rootNode = port.scope.getRootNode();
66
+ if (!("querySelectorAll" in rootNode)) continue;
67
+ const inputs = rootNode.querySelectorAll("input[data-scope=\"form\"]");
68
+ for (const input of inputs) {
69
+ if (!isHtmlElement(input)) continue;
70
+ if ((input.getAttribute("data-form-control") || input.id) !== formControlStem(port.scope.id, field.name)) continue;
71
+ const value = port.value(field.name);
72
+ if (input.type === "checkbox") setProperty(input, "checked", value === true);
73
+ else if (input.type === "radio") setProperty(input, "checked", value === input.value);
74
+ else setProperty(input, "value", textValue$1(value));
75
+ }
76
+ }
77
+ };
78
+ port.bindSync(sync);
79
+ const refreshSoon = () => {
80
+ if (stopped || refreshQueued) return;
81
+ refreshQueued = true;
82
+ queueMicrotask(() => {
83
+ refreshQueued = false;
84
+ refresh();
85
+ });
86
+ };
87
+ function onRaw(event) {
88
+ const input = event.target;
89
+ if (!isInputElement(input) || !isHtmlElement(input) || input.getAttribute("data-scope") !== "form") return;
90
+ if (isHtmlElement(input.closest(typedHosts))) return;
91
+ const field = fieldByControl(port, input.getAttribute("data-form-control") || input.id);
92
+ if (!field) return;
93
+ if (input.type === "checkbox" || input.type === "radio" ? event.type !== "change" : event.type !== "input") return;
94
+ if (input.type === "checkbox") port.change(field.name, input.checked);
95
+ else if (input.type === "radio") port.change(field.name, input.value);
96
+ else if (field.inputType === "number") {
97
+ if (!input.value.trim()) port.change(field.name, null);
98
+ else if (Number.isFinite(input.valueAsNumber)) port.change(field.name, input.valueAsNumber);
99
+ } else port.change(field.name, input.value);
100
+ sync();
101
+ }
102
+ function onTyped(event) {
103
+ const target = event.target;
104
+ if (!isElement(target)) return;
105
+ const host = target.closest(typedHosts);
106
+ if (!isHtmlElement(host) || !host.id) return;
107
+ const field = fieldByControl(port, host.id);
108
+ if (!field) return;
109
+ const detail = event.detail ?? {};
110
+ if (field.control === "checkbox") port.change(field.name, detail.checked === true);
111
+ else if (field.control === "segmented") port.change(field.name, Array.isArray(detail.value) ? [...detail.value] : []);
112
+ else port.change(field.name, detail.value ?? null);
113
+ }
114
+ function refresh() {
115
+ if (stopped) return;
116
+ release();
117
+ const form = port.scope.id ? port.scope.getById(formDomId(port.scope.id)) : null;
118
+ if (!isHtmlElement(form) || form.localName !== "form") return;
119
+ cleanups.push(addDomEvent(form, "reset", (event) => {
120
+ const timer = setTimeout(() => {
121
+ pending.delete(timer);
122
+ if (stopped || event.defaultPrevented) return;
123
+ port.suppressUser(true);
124
+ port.reset();
125
+ sync();
126
+ const done = setTimeout(() => {
127
+ pending.delete(done);
128
+ if (!stopped) port.suppressUser(false);
129
+ }, 0);
130
+ pending.add(done);
131
+ }, 0);
132
+ pending.add(timer);
133
+ }));
134
+ cleanups.push(addDomEvent(form, "focusout", (event) => {
135
+ const target = event.target;
136
+ if (!isElement(target)) return;
137
+ const fieldRoot = target.closest("[data-scope=\"field\"]");
138
+ if (!isHtmlElement(fieldRoot) || !form.contains(fieldRoot)) return;
139
+ const next = event.relatedTarget;
140
+ if (isNode(next) && fieldRoot.contains(next)) return;
141
+ const key = fieldRoot.getAttribute("data-field-key");
142
+ const field = port.fields().find((entry) => formFieldKey(entry.name) === key);
143
+ if (field) port.blur(field.name);
144
+ }));
145
+ cleanups.push(addDomEvent(form, "input", onRaw));
146
+ cleanups.push(addDomEvent(form, "change", onRaw));
147
+ cleanups.push(addDomEvent(form, "checked-change", onTyped));
148
+ cleanups.push(addDomEvent(form, "value-change", onTyped));
149
+ sync();
150
+ }
151
+ const observed = isDocument(root) ? root.body : isHtmlElement(root) ? root : null;
152
+ let stopObserve = observed ? observeChildren(observed, { callback: refreshSoon }) : void 0;
153
+ if (root.nodeType === 11 && "host" in root) {
154
+ const Observer = root.ownerDocument.defaultView?.MutationObserver;
155
+ if (Observer) {
156
+ const observer = new Observer(refreshSoon);
157
+ observer.observe(root, {
158
+ childList: true,
159
+ subtree: true
160
+ });
161
+ stopObserve = () => observer.disconnect();
162
+ }
163
+ }
164
+ refresh();
165
+ return () => {
166
+ stopped = true;
167
+ port.bindSync(void 0);
168
+ port.suppressUser(false);
169
+ release();
170
+ stopObserve?.();
171
+ pending.forEach((timer) => clearTimeout(timer));
172
+ pending.clear();
173
+ };
174
+ }
175
+ //#endregion
176
+ //#region src/form/rules.ts
177
+ const FORM_DEFAULT_MESSAGES = {
178
+ required: "{label}不能为空",
179
+ type: "{label}格式不正确",
180
+ min: "{label}至少为{min}",
181
+ max: "{label}最多为{max}",
182
+ length: "{label}长度应为{length}",
183
+ pattern: "{label}格式不正确",
184
+ enum: "{label}不在可选范围内",
185
+ validator: "{label}校验未通过"
186
+ };
187
+ const FORM_MESSAGES_EN = {
188
+ required: "{label} is required",
189
+ type: "{label} has an invalid format",
190
+ min: "{label} must be at least {min}",
191
+ max: "{label} must be at most {max}",
192
+ length: "{label} must have length {length}",
193
+ pattern: "{label} has an invalid format",
194
+ enum: "{label} is not an allowed value",
195
+ validator: "{label} failed validation"
196
+ };
197
+ const ruleTypes = [
198
+ "string",
199
+ "number",
200
+ "boolean",
201
+ "array",
202
+ "email",
203
+ "url"
204
+ ];
205
+ const triggers = [
206
+ "change",
207
+ "blur",
208
+ "submit",
209
+ "manual"
210
+ ];
211
+ function normalizeFormRule(rule) {
212
+ if (!rule || typeof rule !== "object" || ![Object.prototype, null].includes(Object.getPrototypeOf(rule)) || rule.type !== void 0 && !ruleTypes.includes(rule.type)) throw new TypeError("Invalid Form rule type");
213
+ if (rule.message !== void 0 && typeof rule.message !== "string" || rule.flags !== void 0 && typeof rule.flags !== "string" || rule.enum !== void 0 && !Array.isArray(rule.enum)) throw new TypeError("Invalid Form rule message, flags or enumeration");
214
+ for (const name of [
215
+ "min",
216
+ "max",
217
+ "length"
218
+ ]) if (rule[name] !== void 0 && (typeof rule[name] !== "number" || !Number.isFinite(rule[name]) || name === "length" && (!Number.isInteger(rule[name]) || rule[name] < 0))) throw new TypeError("Form rule bounds must be finite and lengths nonnegative integers");
219
+ if (rule.validator !== void 0 && typeof rule.validator !== "function") throw new TypeError("Form validators must be runtime functions");
220
+ if (rule.pattern !== void 0) {
221
+ if (typeof rule.pattern !== "string") throw new TypeError("Form SSR patterns must be strings");
222
+ try {
223
+ new RegExp(rule.pattern, rule.flags);
224
+ } catch {
225
+ throw new TypeError("Invalid Form rule pattern or flags");
226
+ }
227
+ }
228
+ const trigger = rule.trigger === void 0 ? void 0 : Array.isArray(rule.trigger) ? [...rule.trigger] : [rule.trigger];
229
+ if (trigger?.some((value) => !triggers.includes(value))) throw new TypeError("Invalid Form validation trigger");
230
+ return {
231
+ ...rule,
232
+ trigger,
233
+ enum: rule.enum?.map((value) => cloneFormValue(value))
234
+ };
235
+ }
236
+ function isFormEmpty(value) {
237
+ return value === void 0 || value === null || value === false || typeof value === "string" && !value.trim() || Array.isArray(value) && !value.length;
238
+ }
239
+ function formErrorMessage(error, fallback = "校验失败") {
240
+ return error instanceof Error && error.message ? error.message : typeof error === "string" && error ? error : fallback;
241
+ }
242
+ function message(rule, key, context) {
243
+ const text = rule.message ?? context.messages?.[key] ?? FORM_DEFAULT_MESSAGES[key];
244
+ const values = {
245
+ label: context.label,
246
+ name: normalizeFormNamePath(context.name).join("."),
247
+ min: String(rule.min ?? ""),
248
+ max: String(rule.max ?? ""),
249
+ length: String(rule.length ?? "")
250
+ };
251
+ return text.replace(/\{(label|name|min|max|length)\}/g, (_, key) => values[key]);
252
+ }
253
+ function typeMatches(type, value) {
254
+ if (type === "array") return Array.isArray(value);
255
+ if (type === "email") return typeof value === "string" && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
256
+ if (type === "url") {
257
+ if (typeof value !== "string") return false;
258
+ try {
259
+ new URL(value);
260
+ return true;
261
+ } catch {
262
+ return false;
263
+ }
264
+ }
265
+ return typeof value === type;
266
+ }
267
+ /** One rule returns explicit errors; request ownership is checked by the Form engine. */
268
+ async function validateFormRule(input, value, context) {
269
+ const rule = normalizeFormRule(input);
270
+ if (context.signal.aborted) return [];
271
+ if (isFormEmpty(value)) {
272
+ if (rule.required) return [message(rule, "required", context)];
273
+ if (!rule.validator) return [];
274
+ }
275
+ const errors = [];
276
+ if (value != null && rule.type && !typeMatches(rule.type, value)) errors.push(message(rule, "type", context));
277
+ const size = typeof value === "number" ? value : typeof value === "string" || Array.isArray(value) ? value.length : void 0;
278
+ if (size !== void 0) {
279
+ if (rule.min !== void 0 && size < rule.min) errors.push(message(rule, "min", context));
280
+ if (rule.max !== void 0 && size > rule.max) errors.push(message(rule, "max", context));
281
+ if (rule.length !== void 0 && size !== rule.length) errors.push(message(rule, "length", context));
282
+ }
283
+ if (rule.pattern !== void 0 && value != null && !new RegExp(rule.pattern, rule.flags).test(String(value))) errors.push(message(rule, "pattern", context));
284
+ if (rule.enum && !rule.enum.some((entry) => formValueFingerprint(entry) === formValueFingerprint(value))) errors.push(message(rule, "enum", context));
285
+ if (rule.validator) try {
286
+ const result = await rule.validator(value === void 0 ? void 0 : cloneFormValue(value), context);
287
+ if (result === false) errors.push(message(rule, "validator", context));
288
+ else if (typeof result === "string" && result) errors.push(result);
289
+ else if (result !== void 0 && result !== true && typeof result !== "string") errors.push(message(rule, "validator", context));
290
+ } catch (error) {
291
+ if (!context.signal.aborted) errors.push(formErrorMessage(error, message(rule, "validator", context)));
292
+ }
293
+ return context.signal.aborted ? [] : [...new Set(errors)];
294
+ }
295
+ //#endregion
296
+ //#region src/form/form.ts
297
+ const copyErrors = (errors) => errors.map((entry) => ({
298
+ name: normalizeFormNamePath(entry.name),
299
+ errors: [...entry.errors]
300
+ }));
301
+ /** Feedback is synchronous Core state; bindables publish independent rendering snapshots. */
302
+ function feedbackSnapshot(key, value) {
303
+ const snapshot = key === "errors" ? copyErrors(value) : [...value];
304
+ if (key === "errors") for (const entry of snapshot) {
305
+ Object.freeze(entry.name);
306
+ Object.freeze(entry.errors);
307
+ Object.freeze(entry);
308
+ }
309
+ Object.freeze(snapshot);
310
+ return ref(snapshot);
311
+ }
312
+ function feedback(service) {
313
+ const runtime = service.refs.get("runtime");
314
+ const projections = {
315
+ errors: service.context.get("errors"),
316
+ touched: service.context.get("touched"),
317
+ validated: service.context.get("validated"),
318
+ validating: service.context.get("validating")
319
+ };
320
+ return runtime.feedback ??= {
321
+ errors: feedbackSnapshot("errors", projections.errors),
322
+ touched: feedbackSnapshot("touched", projections.touched),
323
+ validated: feedbackSnapshot("validated", projections.validated),
324
+ validating: feedbackSnapshot("validating", projections.validating)
325
+ };
326
+ }
327
+ function setFeedback(service, key, value) {
328
+ const runtime = service.refs.get("runtime"), current = feedback(service);
329
+ current[key] = feedbackSnapshot(key, value);
330
+ const projection = feedbackSnapshot(key, current[key]);
331
+ const previousPublishing = runtime.publishingFeedback;
332
+ runtime.publishingFeedback = true;
333
+ try {
334
+ service.context.set(key, projection);
335
+ } finally {
336
+ runtime.publishingFeedback = previousPublishing;
337
+ }
338
+ }
339
+ /** Preserve explicit low-level writes without reading later render snapshots back into Core. */
340
+ function acceptFeedback(service, key, value) {
341
+ if (!service.refs.get("runtime").publishingFeedback) setFeedback(service, key, value);
342
+ }
343
+ /** Drop in-flight submit busy. Reconnect cannot resume the old promise. */
344
+ function normalizeFormInteraction(snapshot) {
345
+ if (!snapshot) return void 0;
346
+ const submitStatus = snapshot.submitStatus === "validating" || snapshot.submitStatus === "submitting" ? "canceled" : snapshot.submitStatus;
347
+ return Object.freeze({
348
+ errors: Object.freeze(copyErrors(snapshot.errors).map((entry) => Object.freeze(entry))),
349
+ touched: Object.freeze([...snapshot.touched]),
350
+ validated: Object.freeze([...snapshot.validated]),
351
+ submitStatus
352
+ });
353
+ }
354
+ function normalizeFormFields(fields) {
355
+ const names = /* @__PURE__ */ new Set(), nativeNames = /* @__PURE__ */ new Set();
356
+ return fields.map((field) => {
357
+ const name = normalizeFormNamePath(field.name), key = formFieldKey(name), nativeName = field.nativeName ?? formFieldNativeName(name);
358
+ if (names.has(key) || !nativeName.trim() || nativeNames.has(nativeName)) throw new TypeError("Form field paths and native names must be unique");
359
+ if (typeof field.label !== "string" || !field.label.trim()) throw new TypeError("Form fields require nonempty labels");
360
+ if ((field.control === "radio-group" || field.control === "segmented") && !field.items) throw new TypeError("Form selection fields require actual items");
361
+ names.add(key);
362
+ nativeNames.add(nativeName);
363
+ return {
364
+ ...field,
365
+ name,
366
+ nativeName,
367
+ control: field.control ?? "native",
368
+ rules: field.rules?.map(normalizeFormRule),
369
+ dependencies: field.dependencies?.map(normalizeFormNamePath),
370
+ items: field.items ? normalizeSegmentedItems(field.items) : void 0,
371
+ initialValue: field.initialValue === void 0 ? void 0 : cloneFormValue(field.initialValue)
372
+ };
373
+ });
374
+ }
375
+ function createFormProps(props) {
376
+ if (!props.label?.trim() || props.id !== void 0 && !props.id.trim()) throw new TypeError("Form requires a nonempty label and supplied identity");
377
+ const fields = normalizeFormFields(props.fields), initialValues = cloneFormValues(props.initialValues);
378
+ for (const field of fields) if (!hasFormValue(initialValues, field.name) && field.initialValue !== void 0) Object.assign(initialValues, setFormValue(initialValues, field.name, field.initialValue));
379
+ const { initialInteraction: rawInteraction, ...rest } = props;
380
+ const initialInteraction = normalizeFormInteraction(rawInteraction);
381
+ return {
382
+ ...rest,
383
+ fields,
384
+ values: props.values === void 0 ? void 0 : cloneFormValues(props.values),
385
+ initialValues,
386
+ initialErrors: copyErrors(props.initialErrors ?? []),
387
+ validateTrigger: props.validateTrigger ?? "blur",
388
+ ...initialInteraction ? { initialInteraction } : {}
389
+ };
390
+ }
391
+ const formMachine = createMachine({
392
+ props: ({ props }) => createFormProps({
393
+ ...props,
394
+ label: props.label ?? "",
395
+ fields: props.fields ?? []
396
+ }),
397
+ initialState: () => "ready",
398
+ refs: () => ({ runtime: {
399
+ epoch: 0,
400
+ next: 0,
401
+ alive: true,
402
+ validations: /* @__PURE__ */ new Map(),
403
+ reason: "cancel",
404
+ valueHash: "",
405
+ functions: /* @__PURE__ */ new WeakMap(),
406
+ functionCount: 0,
407
+ known: /* @__PURE__ */ new Map(),
408
+ blurSeen: /* @__PURE__ */ new Set(),
409
+ suppressUser: false
410
+ } }),
411
+ context({ prop, bindable, getRefs, getContext }) {
412
+ const interaction = normalizeFormInteraction(prop("initialInteraction"));
413
+ return {
414
+ values: bindable(() => ({
415
+ defaultValue: prop("initialValues"),
416
+ value: prop("values"),
417
+ isEqual: formValuesEqual,
418
+ onChange: (values) => prop("onValuesChange")?.({ values: cloneFormValues(values) })
419
+ })),
420
+ errors: bindable(() => ({
421
+ defaultValue: feedbackSnapshot("errors", interaction ? [...interaction.errors] : copyErrors(prop("initialErrors"))),
422
+ onChange: (value) => acceptFeedback({
423
+ refs: getRefs(),
424
+ context: getContext()
425
+ }, "errors", value)
426
+ })),
427
+ touched: bindable(() => ({
428
+ defaultValue: feedbackSnapshot("touched", [...interaction?.touched ?? []]),
429
+ onChange: (value) => acceptFeedback({
430
+ refs: getRefs(),
431
+ context: getContext()
432
+ }, "touched", value)
433
+ })),
434
+ validated: bindable(() => ({
435
+ defaultValue: feedbackSnapshot("validated", [...interaction?.validated ?? []]),
436
+ onChange: (value) => acceptFeedback({
437
+ refs: getRefs(),
438
+ context: getContext()
439
+ }, "validated", value)
440
+ })),
441
+ validating: bindable(() => ({
442
+ defaultValue: feedbackSnapshot("validating", []),
443
+ onChange: (value) => acceptFeedback({
444
+ refs: getRefs(),
445
+ context: getContext()
446
+ }, "validating", value)
447
+ })),
448
+ submitStatus: bindable(() => ({ defaultValue: interaction?.submitStatus ?? "idle" }))
449
+ };
450
+ },
451
+ on: { "VALUES.SET": { actions: ["setValues"] } },
452
+ states: { ready: {} },
453
+ effects: ["lifecycle", "trackNative"],
454
+ watch({ track, context, prop, refs }) {
455
+ const runtime = refs.get("runtime");
456
+ track([() => context.hash("values")], () => {
457
+ const hash = formValueFingerprint(context.get("values"));
458
+ if (runtime.valueHash && runtime.valueHash !== hash) cancelRequests({
459
+ context,
460
+ refs,
461
+ prop
462
+ }, "values-change");
463
+ runtime.valueHash = hash;
464
+ runtime.syncNative?.();
465
+ });
466
+ track([() => JSON.stringify(prop("fields"), (_, value) => {
467
+ if (typeof value !== "function") return value;
468
+ let id = runtime.functions.get(value);
469
+ if (!id) {
470
+ id = ++runtime.functionCount;
471
+ runtime.functions.set(value, id);
472
+ }
473
+ return `validator:${id}`;
474
+ })], () => {
475
+ const service = {
476
+ context,
477
+ refs,
478
+ prop
479
+ };
480
+ cancelRequests(service, "fields-change");
481
+ reconcileFormFields(service);
482
+ });
483
+ },
484
+ implementations: {
485
+ effects: {
486
+ lifecycle({ context, refs, prop }) {
487
+ const runtime = refs.get("runtime");
488
+ runtime.alive = true;
489
+ runtime.valueHash = formValueFingerprint(context.get("values"));
490
+ runtime.known = captureKnown(prop("fields"));
491
+ return () => {
492
+ cancelRequests({
493
+ context,
494
+ refs,
495
+ prop
496
+ }, "unmount");
497
+ runtime.alive = false;
498
+ };
499
+ },
500
+ trackNative(params) {
501
+ const service = params;
502
+ const behavior = connectFormBehavior(service);
503
+ return trackFormNative({
504
+ scope: service.scope,
505
+ fields: () => service.prop("fields"),
506
+ value: (name) => behavior.getFieldValue(name),
507
+ change: (name, value) => behavior.changeFieldFromUser(name, value),
508
+ blur: (name) => behavior.blurField(name),
509
+ reset: () => behavior.resetFields(),
510
+ suppressUser: (active) => {
511
+ service.refs.get("runtime").suppressUser = active;
512
+ },
513
+ bindSync: (sync) => {
514
+ service.refs.get("runtime").syncNative = sync;
515
+ }
516
+ });
517
+ }
518
+ },
519
+ actions: { setValues({ event, context }) {
520
+ if (event.type === "VALUES.SET") context.set("values", cloneFormValues(event.values));
521
+ } }
522
+ }
523
+ });
524
+ function cancelRequests(service, reason) {
525
+ const runtime = service.refs.get("runtime");
526
+ runtime.epoch++;
527
+ runtime.reason = reason;
528
+ runtime.validations.forEach((request) => request.controller.abort());
529
+ runtime.validations.clear();
530
+ setFeedback(service, "validating", []);
531
+ if (runtime.submission) {
532
+ runtime.submission.controller.abort();
533
+ runtime.submission = void 0;
534
+ service.context.set("submitStatus", "canceled");
535
+ if (reason !== "unmount") service.prop("onSubmitCancel")?.({ reason });
536
+ }
537
+ }
538
+ /** Await cancellation even when user code does not observe its AbortSignal. */
539
+ function abortable(promise, signal) {
540
+ return new Promise((resolve, reject) => {
541
+ if (signal.aborted) {
542
+ promise.then(() => {}, () => {});
543
+ resolve(void 0);
544
+ return;
545
+ }
546
+ const abort = () => resolve(void 0);
547
+ signal.addEventListener("abort", abort, { once: true });
548
+ promise.then((value) => {
549
+ signal.removeEventListener("abort", abort);
550
+ resolve(value);
551
+ }, (error) => {
552
+ signal.removeEventListener("abort", abort);
553
+ reject(error);
554
+ });
555
+ });
556
+ }
557
+ function captureKnown(fields) {
558
+ return new Map(fields.map((field) => [formFieldKey(field.name), {
559
+ name: normalizeFormNamePath(field.name),
560
+ preserve: field.preserve
561
+ }]));
562
+ }
563
+ /** Drop preserve=false values and seed newly added field.initialValue. Keeps every other stored value. */
564
+ function reconcileFormFields(service) {
565
+ const runtime = service.refs.get("runtime"), nextFields = service.prop("fields"), known = runtime.known;
566
+ let values = cloneFormValues(service.context.get("values"));
567
+ let changed = false;
568
+ const removed = [];
569
+ const nextKeys = new Set(nextFields.map((field) => formFieldKey(field.name)));
570
+ for (const [key, previous] of known) {
571
+ if (nextKeys.has(key)) continue;
572
+ removed.push(key);
573
+ if (previous.preserve === false) {
574
+ values = setFormValue(values, previous.name, void 0);
575
+ changed = true;
576
+ }
577
+ }
578
+ for (const field of nextFields) {
579
+ if (known.has(formFieldKey(field.name)) || field.initialValue === void 0 || hasFormValue(values, field.name)) continue;
580
+ values = setFormValue(values, field.name, field.initialValue);
581
+ changed = true;
582
+ }
583
+ if (changed) {
584
+ runtime.valueHash = formValueFingerprint(values);
585
+ service.context.set("values", values);
586
+ }
587
+ if (removed.length) {
588
+ setFeedback(service, "errors", feedback(service).errors.filter((entry) => !removed.includes(formFieldKey(entry.name))));
589
+ setFeedback(service, "touched", feedback(service).touched.filter((key) => !removed.includes(key)));
590
+ setFeedback(service, "validated", feedback(service).validated.filter((key) => !removed.includes(key)));
591
+ setFeedback(service, "validating", feedback(service).validating.filter((key) => !removed.includes(key)));
592
+ }
593
+ runtime.known = captureKnown(nextFields);
594
+ }
595
+ function enabledChoice(field, value) {
596
+ return !!field.items?.some((item) => item.value === value && !item.disabled);
597
+ }
598
+ /** Unknown and disabled choices stay stored but are not fabricated into the submit snapshot. */
599
+ function submittedFieldValue(field, value) {
600
+ if (field.control === "checkbox" || field.inputType === "checkbox") return typeof value === "boolean" ? {
601
+ include: true,
602
+ value
603
+ } : { include: false };
604
+ if (field.control === "radio-group") {
605
+ if (value === null) return {
606
+ include: true,
607
+ value: null
608
+ };
609
+ if (typeof value === "string" && enabledChoice(field, value)) return {
610
+ include: true,
611
+ value
612
+ };
613
+ return { include: false };
614
+ }
615
+ if (field.control === "segmented") return {
616
+ include: true,
617
+ value: Array.isArray(value) ? value.filter((item) => typeof item === "string" && enabledChoice(field, item)) : []
618
+ };
619
+ return value === void 0 ? { include: false } : {
620
+ include: true,
621
+ value
622
+ };
623
+ }
624
+ function focusableControl(node) {
625
+ if (!isHTMLElement(node) || node.namespaceURI !== "http://www.w3.org/1999/xhtml") return null;
626
+ const nodes = [node, ...node.querySelectorAll("input, select, textarea, button, a[href], [tabindex]")];
627
+ for (const candidate of nodes) {
628
+ if (!isHTMLElement(candidate) || candidate.namespaceURI !== "http://www.w3.org/1999/xhtml") continue;
629
+ if (candidate.hasAttribute("disabled") || candidate.getAttribute("aria-disabled") === "true") continue;
630
+ if (candidate.getAttribute("role") === "group" && !candidate.hasAttribute("tabindex")) continue;
631
+ const tab = candidate.getAttribute("tabindex");
632
+ if (tab === "-1") continue;
633
+ if ([
634
+ "input",
635
+ "select",
636
+ "textarea",
637
+ "button"
638
+ ].includes(candidate.localName) || candidate.localName === "a" && candidate.hasAttribute("href") || tab !== null) return candidate;
639
+ }
640
+ return null;
641
+ }
642
+ /** Headless behavior API; DOM/getter transport is composed separately. */
643
+ function connectFormBehavior(service) {
644
+ const runtime = service.refs.get("runtime");
645
+ const fields = () => service.prop("fields");
646
+ const resolve = (name) => {
647
+ const key = formFieldKey(name), field = fields().find((entry) => formFieldKey(entry.name) === key);
648
+ if (!field) throw new RangeError("Form field is not registered");
649
+ return field;
650
+ };
651
+ const getValues = () => cloneFormValues(service.context.get("values"));
652
+ const getFieldState = (name) => {
653
+ const field = resolve(name), key = formFieldKey(name), errors = feedback(service).errors.find((entry) => formFieldKey(entry.name) === key)?.errors ?? [];
654
+ return {
655
+ name: normalizeFormNamePath(name),
656
+ value: getFormValue(getValues(), name),
657
+ errors: [...errors],
658
+ touched: feedback(service).touched.includes(key),
659
+ dirty: formValueFingerprint(getFormValue(getValues(), name)) !== formValueFingerprint(getFormValue(service.prop("initialValues"), name)),
660
+ validationStatus: feedback(service).validating.includes(key) ? "validating" : errors.length ? "invalid" : feedback(service).validated.includes(key) ? "valid" : "unvalidated",
661
+ disabled: !!service.prop("disabled") || !!field.disabled,
662
+ readOnly: !!service.prop("readOnly") || !!field.readOnly,
663
+ required: !!field.required || !!field.rules?.some((rule) => rule.required)
664
+ };
665
+ };
666
+ const getState = () => ({
667
+ values: getValues(),
668
+ fieldStates: fields().map((field) => getFieldState(field.name)),
669
+ submitting: ["validating", "submitting"].includes(service.context.get("submitStatus")),
670
+ submitStatus: service.context.get("submitStatus")
671
+ });
672
+ const getInteractionSnapshot = () => Object.freeze({
673
+ errors: Object.freeze(copyErrors(feedback(service).errors).map((entry) => Object.freeze(entry))),
674
+ touched: Object.freeze([...feedback(service).touched]),
675
+ validated: Object.freeze([...feedback(service).validated]),
676
+ submitStatus: service.context.get("submitStatus")
677
+ });
678
+ const notify = () => service.prop("onValidationChange")?.({ state: getState() });
679
+ const clearErrors = (keys) => {
680
+ setFeedback(service, "errors", feedback(service).errors.filter((entry) => !keys.includes(formFieldKey(entry.name))));
681
+ setFeedback(service, "validated", feedback(service).validated.filter((key) => !keys.includes(key)));
682
+ };
683
+ const alive = () => {
684
+ if (!runtime.alive) throw new TypeError("Form instance is stopped");
685
+ };
686
+ const fieldTriggers = (field) => {
687
+ const source = field.validateTrigger ?? service.prop("validateTrigger");
688
+ return Array.isArray(source) ? source : [source];
689
+ };
690
+ const markTouched = (name) => {
691
+ const key = formFieldKey(name);
692
+ if (!feedback(service).touched.includes(key)) setFeedback(service, "touched", [...feedback(service).touched, key]);
693
+ };
694
+ const initialFieldValue = (name) => {
695
+ const field = resolve(name);
696
+ return hasFormValue(service.prop("initialValues"), field.name) ? getFormValue(service.prop("initialValues"), field.name) : field.initialValue;
697
+ };
698
+ const mutate = (values, names = []) => {
699
+ alive();
700
+ const next = cloneFormValues(values);
701
+ cancelRequests(service, "values-change");
702
+ clearErrors(names.map(formFieldKey));
703
+ service.context.set("values", next);
704
+ runtime.valueHash = formValueFingerprint(service.context.get("values"));
705
+ notify();
706
+ };
707
+ const dependentNames = (name) => {
708
+ const key = formFieldKey(name);
709
+ return fields().filter((field) => field.dependencies?.some((dependency) => formFieldKey(dependency) === key) && (getFieldState(field.name).touched || !!getFieldState(field.name).errors.length)).map((field) => field.name);
710
+ };
711
+ const setFieldValue = (name, value) => {
712
+ const next = setFormValue(getValues(), name, value);
713
+ if (formValueFingerprint(getValues()) === formValueFingerprint(next)) return;
714
+ mutate(next, [name]);
715
+ const names = dependentNames(name);
716
+ if (names.length) validateFields(names, { trigger: "change" });
717
+ };
718
+ const changeFieldFromUser = (name, value) => {
719
+ alive();
720
+ const field = resolve(name), state = getFieldState(name);
721
+ if (state.disabled || state.readOnly || runtime.suppressUser) return;
722
+ const echoKey = formFieldKey(name), echoValue = formValueFingerprint(value);
723
+ if (runtime.userEcho?.key === echoKey && runtime.userEcho.value === echoValue) return;
724
+ runtime.userEcho = {
725
+ key: echoKey,
726
+ value: echoValue
727
+ };
728
+ queueMicrotask(() => {
729
+ if (runtime.userEcho?.key === echoKey && runtime.userEcho.value === echoValue) runtime.userEcho = void 0;
730
+ });
731
+ const hadErrors = state.errors.length > 0, next = setFormValue(getValues(), name, value), same = formValueFingerprint(getValues()) === formValueFingerprint(next);
732
+ if (!same) mutate(next, [name]);
733
+ markTouched(name);
734
+ const names = [];
735
+ if (!same && (fieldTriggers(field).includes("change") || hadErrors)) names.push(field.name);
736
+ names.push(...dependentNames(name).filter((dependency) => !names.some((entry) => formFieldKey(entry) === formFieldKey(dependency))));
737
+ if (names.length) validateFields(names, { trigger: "change" });
738
+ };
739
+ const blurField = (name) => {
740
+ alive();
741
+ const field = resolve(name), key = formFieldKey(name);
742
+ if (getFieldState(name).disabled || runtime.suppressUser) return;
743
+ if (runtime.blurSeen.has(key)) return;
744
+ runtime.blurSeen.add(key);
745
+ queueMicrotask(() => runtime.blurSeen.delete(key));
746
+ markTouched(name);
747
+ notify();
748
+ if (fieldTriggers(field).includes("blur")) validateFields([name], { trigger: "blur" });
749
+ };
750
+ const focusField = (name) => {
751
+ resolve(name);
752
+ const scopeId = service.scope.id;
753
+ if (typeof document === "undefined" || !scopeId) return false;
754
+ const node = service.scope.getById(formControlStem(scopeId, name));
755
+ const target = node ? focusableControl(node) : null;
756
+ if (!target) return false;
757
+ target.focus();
758
+ return true;
759
+ };
760
+ const setFieldErrors = (name, errors) => {
761
+ alive();
762
+ resolve(name);
763
+ const key = formFieldKey(name);
764
+ runtime.validations.get(key)?.controller.abort();
765
+ runtime.validations.delete(key);
766
+ setFeedback(service, "validating", feedback(service).validating.filter((entry) => entry !== key));
767
+ setFeedback(service, "errors", [...feedback(service).errors.filter((entry) => formFieldKey(entry.name) !== key), {
768
+ name: normalizeFormNamePath(name),
769
+ errors: [...errors]
770
+ }]);
771
+ notify();
772
+ };
773
+ const validateFields = async (names, options = {}) => {
774
+ alive();
775
+ const epoch = runtime.epoch, values = getValues(), snapshot = freezeFormValues(values), chosen = names ? names.map(resolve) : fields();
776
+ const results = await Promise.all(chosen.filter((field) => !getFieldState(field.name).disabled).map(async (field) => {
777
+ const key = formFieldKey(field.name);
778
+ runtime.validations.get(key)?.controller.abort();
779
+ const request = {
780
+ ticket: ++runtime.next,
781
+ controller: new AbortController()
782
+ };
783
+ runtime.validations.set(key, request);
784
+ if (!options.validateOnly) setFeedback(service, "validating", [.../* @__PURE__ */ new Set([...feedback(service).validating, key])]);
785
+ const value = getFormValue(values, field.name), errors = [], rules = [...field.required ? [{ required: true }] : [], ...field.rules ?? []];
786
+ for (const rule of rules) {
787
+ const trigger = options.trigger ?? "manual", triggers = rule.trigger === void 0 ? void 0 : Array.isArray(rule.trigger) ? rule.trigger : [rule.trigger];
788
+ if (trigger !== "submit" && trigger !== "manual" && triggers && !triggers.includes(trigger)) continue;
789
+ let tested = value;
790
+ if (rule.required && field.control === "checkbox" && tested !== true) tested = void 0;
791
+ if (rule.required && (field.control === "radio-group" || field.control === "segmented")) {
792
+ const enabled = field.items?.filter((item) => !item.disabled) ?? [];
793
+ if (!enabled.length) continue;
794
+ if (!enabled.some((item) => Array.isArray(tested) ? tested.includes(item.value) : tested === item.value)) tested = void 0;
795
+ }
796
+ const result = await abortable(validateFormRule(rule, tested, {
797
+ name: normalizeFormNamePath(field.name),
798
+ label: field.label,
799
+ values: snapshot,
800
+ signal: request.controller.signal,
801
+ messages: service.prop("messages")
802
+ }), request.controller.signal);
803
+ if (result) errors.push(...result);
804
+ if (request.controller.signal.aborted || service.prop("validateFirst") && errors.length) break;
805
+ }
806
+ const current = runtime.alive && runtime.epoch === epoch && runtime.validations.get(key)?.ticket === request.ticket && !request.controller.signal.aborted;
807
+ if (current) {
808
+ runtime.validations.delete(key);
809
+ setFeedback(service, "validating", feedback(service).validating.filter((entry) => entry !== key));
810
+ if (!options.validateOnly) {
811
+ setFeedback(service, "errors", [...feedback(service).errors.filter((entry) => formFieldKey(entry.name) !== key), {
812
+ name: normalizeFormNamePath(field.name),
813
+ errors: [...new Set(errors)]
814
+ }]);
815
+ setFeedback(service, "validated", [.../* @__PURE__ */ new Set([...feedback(service).validated, key])]);
816
+ }
817
+ notify();
818
+ }
819
+ return {
820
+ current,
821
+ name: normalizeFormNamePath(field.name),
822
+ errors: [...new Set(errors)]
823
+ };
824
+ }));
825
+ const outOfDate = !runtime.alive || runtime.epoch !== epoch || results.some((result) => !result.current);
826
+ return {
827
+ values,
828
+ errorFields: results.filter((result) => result.errors.length).map(({ name, errors }) => ({
829
+ name,
830
+ errors
831
+ })),
832
+ outOfDate,
833
+ canceled: outOfDate
834
+ };
835
+ };
836
+ const resetFields = (names) => {
837
+ alive();
838
+ cancelRequests(service, "reset");
839
+ const targets = names ? names.map(resolve) : fields();
840
+ let values = names ? getValues() : cloneFormValues(service.prop("initialValues"));
841
+ for (const field of targets) if (names || !hasFormValue(values, field.name)) values = setFormValue(values, field.name, initialFieldValue(field.name));
842
+ const keys = targets.map((field) => formFieldKey(field.name));
843
+ clearErrors(keys);
844
+ setFeedback(service, "touched", feedback(service).touched.filter((key) => !keys.includes(key)));
845
+ service.context.set("values", values);
846
+ runtime.valueHash = formValueFingerprint(service.context.get("values"));
847
+ service.context.set("submitStatus", "idle");
848
+ notify();
849
+ };
850
+ const submit = async () => {
851
+ alive();
852
+ cancelRequests(service, "superseded");
853
+ const request = {
854
+ ticket: ++runtime.next,
855
+ controller: new AbortController()
856
+ };
857
+ runtime.submission = request;
858
+ service.context.set("submitStatus", "validating");
859
+ notify();
860
+ const validation = await validateFields(void 0, { trigger: "submit" });
861
+ const current = () => runtime.alive && runtime.submission?.ticket === request.ticket && !request.controller.signal.aborted;
862
+ /** Drop only the submission this call still owns. A newer submit must keep its busy state. */
863
+ const canceled = () => {
864
+ if (runtime.submission?.ticket === request.ticket) {
865
+ const owned = runtime.submission;
866
+ runtime.submission = void 0;
867
+ owned.controller.abort();
868
+ if (!runtime.submission) {
869
+ service.context.set("submitStatus", "canceled");
870
+ service.prop("onSubmitCancel")?.({ reason: runtime.reason });
871
+ if (!runtime.submission) notify();
872
+ }
873
+ }
874
+ return {
875
+ status: "canceled",
876
+ values: validation.values,
877
+ errorFields: [],
878
+ reason: runtime.reason
879
+ };
880
+ };
881
+ if (!current() || validation.outOfDate) return canceled();
882
+ if (validation.errorFields.length) {
883
+ runtime.submission = void 0;
884
+ service.context.set("submitStatus", "invalid");
885
+ service.prop("onValidationFailed")?.({
886
+ values: cloneFormValues(validation.values),
887
+ errorFields: copyErrors(validation.errorFields)
888
+ });
889
+ notify();
890
+ if (service.prop("focusFirstError")) {
891
+ for (const field of fields()) if (validation.errorFields.some((entry) => formFieldKey(entry.name) === formFieldKey(field.name)) && focusField(field.name)) break;
892
+ }
893
+ return {
894
+ status: "invalid",
895
+ values: validation.values,
896
+ errorFields: validation.errorFields
897
+ };
898
+ }
899
+ let values = {};
900
+ for (const field of fields()) {
901
+ if (getFieldState(field.name).disabled) continue;
902
+ const submitted = submittedFieldValue(field, getFormValue(validation.values, field.name));
903
+ if (submitted.include) values = setFormValue(values, field.name, submitted.value);
904
+ }
905
+ service.context.set("submitStatus", "submitting");
906
+ notify();
907
+ try {
908
+ await abortable(Promise.resolve(service.prop("onSubmit")?.(cloneFormValues(values), { signal: request.controller.signal })), request.controller.signal);
909
+ if (!current()) return canceled();
910
+ runtime.submission = void 0;
911
+ service.context.set("submitStatus", "success");
912
+ service.prop("onSubmitSuccess")?.({ values: cloneFormValues(values) });
913
+ notify();
914
+ return {
915
+ status: "success",
916
+ values,
917
+ errorFields: []
918
+ };
919
+ } catch (error) {
920
+ if (!current()) return canceled();
921
+ runtime.submission = void 0;
922
+ service.context.set("submitStatus", "error");
923
+ const text = formErrorMessage(error, "提交失败");
924
+ service.prop("onSubmitError")?.({
925
+ values: cloneFormValues(values),
926
+ error: text
927
+ });
928
+ notify();
929
+ return {
930
+ status: "error",
931
+ values,
932
+ errorFields: [],
933
+ error: text
934
+ };
935
+ }
936
+ };
937
+ const setFieldsValue = (patch) => {
938
+ const before = getValues(), next = mergeFormValues(before, patch);
939
+ if (formValueFingerprint(before) === formValueFingerprint(next)) return;
940
+ const changed = fields().filter((field) => formValueFingerprint(getFormValue(before, field.name)) !== formValueFingerprint(getFormValue(next, field.name))).map((field) => field.name);
941
+ mutate(next, changed);
942
+ const names = changed.flatMap((name) => dependentNames(name));
943
+ if (names.length) validateFields(names, { trigger: "change" });
944
+ };
945
+ return {
946
+ get values() {
947
+ return getValues();
948
+ },
949
+ get state() {
950
+ return getState();
951
+ },
952
+ getValues,
953
+ getState,
954
+ getFieldState,
955
+ getInteractionSnapshot,
956
+ getFieldValue: (name) => getFormValue(getValues(), name),
957
+ setFieldValue,
958
+ setFieldsValue,
959
+ setFieldErrors,
960
+ validateFields,
961
+ resetFields,
962
+ submit,
963
+ cancelSubmit: () => {
964
+ alive();
965
+ cancelRequests(service, "cancel");
966
+ notify();
967
+ },
968
+ changeFieldFromUser,
969
+ blurField,
970
+ focusField,
971
+ initialFieldValue
972
+ };
973
+ }
974
+ //#endregion
975
+ //#region src/form/connect.ts
976
+ const FORM_PARTS = [
977
+ "root",
978
+ "label",
979
+ "content",
980
+ "error-summary",
981
+ "error-list",
982
+ "error-item",
983
+ "error-link",
984
+ "footer"
985
+ ];
986
+ const part = (name) => ({
987
+ "data-scope": "form",
988
+ "data-part": name
989
+ });
990
+ function defined(props) {
991
+ return Object.fromEntries(Object.entries(props).filter(([, value]) => value !== void 0));
992
+ }
993
+ function labelModeFor(field, readOnly) {
994
+ if (field.control === "checkbox" || field.control === "radio-group" || field.control === "segmented") return "control";
995
+ if (field.control === "custom" || field.control === "input" && readOnly) return "custom";
996
+ return "label";
997
+ }
998
+ function textValue(value) {
999
+ return typeof value === "string" ? value : typeof value === "number" ? String(value) : "";
1000
+ }
1001
+ function choiceItems(field) {
1002
+ return (field.items ?? []).map((item) => ({ ...item }));
1003
+ }
1004
+ /** Public connect. Named connectForm so package barrels do not hide other connects. */
1005
+ function connectForm(service, normalize) {
1006
+ const behavior = connectFormBehavior(service);
1007
+ const active = () => service.refs.get("runtime").alive;
1008
+ const scopeId = service.scope.id;
1009
+ if (!scopeId) throw new TypeError("Form requires a stable scope id");
1010
+ const formId = formDomId(scopeId);
1011
+ const link = (name) => {
1012
+ const state = behavior.getFieldState(name);
1013
+ const definition = service.prop("fields").find((entry) => formFieldKey(entry.name) === formFieldKey(name));
1014
+ if (!definition) throw new RangeError("Form field is not registered");
1015
+ const controlId = formControlStem(scopeId, name);
1016
+ const fieldProps = {
1017
+ id: formFieldStem(scopeId, name),
1018
+ name: state.name,
1019
+ label: definition.label,
1020
+ description: definition.description,
1021
+ errors: state.errors,
1022
+ controlId,
1023
+ labelMode: labelModeFor(definition, state.readOnly),
1024
+ required: state.required,
1025
+ disabled: state.disabled,
1026
+ invalid: state.errors.length > 0,
1027
+ validating: state.validationStatus === "validating"
1028
+ };
1029
+ return {
1030
+ definition,
1031
+ state,
1032
+ controlId,
1033
+ fieldProps,
1034
+ resolved: resolveFieldState(fieldProps)
1035
+ };
1036
+ };
1037
+ const hasErrors = () => behavior.state.fieldStates.some((field) => field.errors.length > 0);
1038
+ return {
1039
+ get values() {
1040
+ return behavior.values;
1041
+ },
1042
+ get state() {
1043
+ return behavior.state;
1044
+ },
1045
+ getValues: () => behavior.getValues(),
1046
+ getFieldValue: (name) => behavior.getFieldValue(name),
1047
+ getFieldState: (name) => behavior.getFieldState(name),
1048
+ getInteractionSnapshot: () => behavior.getInteractionSnapshot(),
1049
+ setFieldValue: (name, value) => behavior.setFieldValue(name, value),
1050
+ setFieldsValue: (values) => behavior.setFieldsValue(values),
1051
+ setFieldErrors: (name, errors) => behavior.setFieldErrors(name, errors),
1052
+ validateFields: (names, options) => behavior.validateFields(names, options),
1053
+ submit: () => behavior.submit(),
1054
+ cancelSubmit: () => behavior.cancelSubmit(),
1055
+ resetFields: (names) => behavior.resetFields(names),
1056
+ focusField: (name) => behavior.focusField(name),
1057
+ getRootProps: () => normalize.element(defined({
1058
+ ...part("root"),
1059
+ id: formId,
1060
+ noValidate: true,
1061
+ "aria-labelledby": formLabelId(scopeId),
1062
+ "aria-busy": behavior.state.submitting || void 0,
1063
+ "data-disabled": service.prop("disabled") ? "" : void 0,
1064
+ "data-readonly": service.prop("readOnly") ? "" : void 0,
1065
+ "data-invalid": hasErrors() ? "" : void 0,
1066
+ onSubmit(event) {
1067
+ if (!active()) return;
1068
+ event.preventDefault();
1069
+ behavior.submit();
1070
+ }
1071
+ })),
1072
+ getLabelProps: () => normalize.element({
1073
+ ...part("label"),
1074
+ id: formLabelId(scopeId)
1075
+ }),
1076
+ getContentProps: () => normalize.element(part("content")),
1077
+ getErrorSummaryProps: () => normalize.element(defined({
1078
+ ...part("error-summary"),
1079
+ id: `${formId}:error-summary`,
1080
+ role: "alert",
1081
+ hidden: hasErrors() ? void 0 : true
1082
+ })),
1083
+ getErrorListProps: () => normalize.element(part("error-list")),
1084
+ getErrorItemProps: (name) => {
1085
+ const state = behavior.getFieldState(name);
1086
+ return normalize.element({
1087
+ ...part("error-item"),
1088
+ "data-field-key": formFieldKey(state.name)
1089
+ });
1090
+ },
1091
+ getErrorLinkProps: (name) => normalize.element({
1092
+ ...part("error-link"),
1093
+ href: `#${formControlStem(scopeId, name)}`,
1094
+ onClick(event) {
1095
+ if (!active()) return;
1096
+ event.preventDefault();
1097
+ behavior.focusField(name);
1098
+ }
1099
+ }),
1100
+ getFooterProps: () => normalize.element(part("footer")),
1101
+ getFieldProps: (name) => link(name).fieldProps,
1102
+ getInputProps: (name) => {
1103
+ const current = link(name);
1104
+ return {
1105
+ id: current.controlId,
1106
+ readOnly: current.state.readOnly,
1107
+ value: textValue(current.state.value),
1108
+ onChange(next) {
1109
+ if (!active()) return;
1110
+ if (current.definition.inputType === "number") {
1111
+ if (!next.trim()) {
1112
+ behavior.changeFieldFromUser(name, null);
1113
+ return;
1114
+ }
1115
+ const numeric = Number(next);
1116
+ if (Number.isFinite(numeric)) behavior.changeFieldFromUser(name, numeric);
1117
+ return;
1118
+ }
1119
+ behavior.changeFieldFromUser(name, next);
1120
+ },
1121
+ onBlur() {
1122
+ if (active()) behavior.blurField(name);
1123
+ },
1124
+ control: defined({
1125
+ id: current.controlId,
1126
+ name: current.definition.nativeName,
1127
+ form: formId,
1128
+ disabled: current.state.disabled || void 0,
1129
+ required: current.state.required || void 0,
1130
+ labelledBy: current.resolved.labelId,
1131
+ describedBy: current.resolved.describedBy,
1132
+ invalid: current.state.errors.length > 0 || void 0
1133
+ })
1134
+ };
1135
+ },
1136
+ getCheckboxProps: (name) => {
1137
+ const current = link(name), initial = behavior.initialFieldValue(name);
1138
+ return defined({
1139
+ id: current.controlId,
1140
+ label: current.definition.label,
1141
+ description: current.definition.controlDescription,
1142
+ describedBy: current.resolved.describedBy,
1143
+ checked: current.state.value === true,
1144
+ defaultChecked: initial === true,
1145
+ disabled: current.state.disabled,
1146
+ readOnly: current.state.readOnly,
1147
+ required: current.state.required,
1148
+ invalid: current.state.errors.length > 0,
1149
+ name: current.definition.nativeName,
1150
+ form: formId,
1151
+ onCheckedChange: (details) => {
1152
+ if (active()) behavior.changeFieldFromUser(name, details.checked === true);
1153
+ }
1154
+ });
1155
+ },
1156
+ getRadioGroupProps: (name) => {
1157
+ const current = link(name), initial = behavior.initialFieldValue(name);
1158
+ if (!current.definition.items) throw new TypeError("Form radio fields require actual items");
1159
+ return defined({
1160
+ id: current.controlId,
1161
+ label: current.definition.label,
1162
+ description: current.definition.controlDescription,
1163
+ describedBy: current.resolved.describedBy,
1164
+ items: choiceItems(current.definition),
1165
+ value: typeof current.state.value === "string" ? current.state.value : null,
1166
+ defaultValue: typeof initial === "string" ? initial : null,
1167
+ disabled: current.state.disabled,
1168
+ readOnly: current.state.readOnly,
1169
+ required: current.state.required,
1170
+ invalid: current.state.errors.length > 0,
1171
+ name: current.definition.nativeName,
1172
+ form: formId,
1173
+ onValueChange: (details) => {
1174
+ if (active()) behavior.changeFieldFromUser(name, details.value);
1175
+ }
1176
+ });
1177
+ },
1178
+ getSegmentedProps: (name) => {
1179
+ const current = link(name), initial = behavior.initialFieldValue(name);
1180
+ if (!current.definition.items) throw new TypeError("Form segmented fields require actual items");
1181
+ const value = Array.isArray(current.state.value) ? current.state.value.filter((item) => typeof item === "string") : [];
1182
+ const fallback = Array.isArray(initial) ? initial.filter((item) => typeof item === "string") : [];
1183
+ return defined({
1184
+ id: current.controlId,
1185
+ label: current.definition.label,
1186
+ description: current.definition.controlDescription,
1187
+ describedBy: current.resolved.describedBy,
1188
+ items: choiceItems(current.definition),
1189
+ selectionMode: current.definition.selectionMode ?? "single",
1190
+ value,
1191
+ defaultValue: fallback,
1192
+ disabled: current.state.disabled,
1193
+ readOnly: current.state.readOnly,
1194
+ required: current.state.required,
1195
+ invalid: current.state.errors.length > 0,
1196
+ name: current.definition.nativeName,
1197
+ form: formId,
1198
+ onValueChange: (details) => {
1199
+ if (active()) behavior.changeFieldFromUser(name, [...details.value]);
1200
+ }
1201
+ });
1202
+ },
1203
+ getNativeControlProps: (name) => {
1204
+ const current = link(name), checkbox = current.definition.inputType === "checkbox" || current.definition.control === "checkbox";
1205
+ return normalize.input(defined({
1206
+ "data-scope": "form",
1207
+ "data-part": "control",
1208
+ id: current.controlId,
1209
+ name: current.definition.nativeName,
1210
+ form: formId,
1211
+ type: checkbox ? "checkbox" : current.definition.inputType ?? "text",
1212
+ value: checkbox ? void 0 : textValue(current.state.value),
1213
+ checked: checkbox ? current.state.value === true : void 0,
1214
+ disabled: current.state.disabled || void 0,
1215
+ readOnly: current.state.readOnly || void 0,
1216
+ required: current.state.required || void 0,
1217
+ "aria-labelledby": current.resolved.labelId,
1218
+ "aria-describedby": current.resolved.describedBy,
1219
+ "aria-invalid": current.state.errors.length > 0 || void 0,
1220
+ "aria-required": current.state.required || void 0,
1221
+ "data-field-root": formFieldRootId(scopeId, name),
1222
+ onBlur() {
1223
+ if (active()) behavior.blurField(name);
1224
+ },
1225
+ onChange() {}
1226
+ }));
1227
+ },
1228
+ getReadonlyProps: (name) => {
1229
+ const current = link(name);
1230
+ return normalize.element(defined({
1231
+ "data-scope": "form",
1232
+ "data-part": "control",
1233
+ id: current.controlId,
1234
+ role: "group",
1235
+ "aria-labelledby": current.resolved.labelId,
1236
+ "aria-describedby": current.resolved.describedBy,
1237
+ "aria-invalid": current.state.errors.length > 0 || void 0
1238
+ }));
1239
+ },
1240
+ getNativeElementProps: (name) => {
1241
+ const current = link(name), initial = behavior.initialFieldValue(name);
1242
+ const common = defined({
1243
+ id: current.controlId,
1244
+ label: current.definition.label,
1245
+ description: current.definition.controlDescription,
1246
+ describedBy: current.resolved.describedBy,
1247
+ name: current.definition.nativeName,
1248
+ form: formId,
1249
+ disabled: current.state.disabled,
1250
+ readOnly: current.state.readOnly,
1251
+ required: current.state.required,
1252
+ invalid: current.state.errors.length > 0
1253
+ });
1254
+ if (current.definition.control === "checkbox") return {
1255
+ ...common,
1256
+ checked: current.state.value === true,
1257
+ defaultChecked: initial === true
1258
+ };
1259
+ if (current.definition.control === "radio-group") return {
1260
+ ...common,
1261
+ items: choiceItems(current.definition),
1262
+ value: typeof current.state.value === "string" ? current.state.value : null,
1263
+ defaultValue: typeof initial === "string" ? initial : null
1264
+ };
1265
+ if (current.definition.control === "segmented") {
1266
+ const value = Array.isArray(current.state.value) ? current.state.value.filter((item) => typeof item === "string") : [];
1267
+ const fallback = Array.isArray(initial) ? initial.filter((item) => typeof item === "string") : [];
1268
+ return {
1269
+ ...common,
1270
+ items: choiceItems(current.definition),
1271
+ selectionMode: current.definition.selectionMode ?? "single",
1272
+ value,
1273
+ defaultValue: fallback
1274
+ };
1275
+ }
1276
+ return {
1277
+ ...common,
1278
+ type: current.definition.inputType ?? "text",
1279
+ value: textValue(current.state.value)
1280
+ };
1281
+ }
1282
+ };
1283
+ }
1284
+ //#endregion
1285
+ //#region src/form/methods.ts
1286
+ /** Live Core dispatch for a connected native method. Unknown names throw. */
1287
+ function invokeFormApi(api, method, args = []) {
1288
+ switch (method) {
1289
+ case "getValues": return api.getValues();
1290
+ case "getFieldValue": return api.getFieldValue(args[0]);
1291
+ case "getFieldState": return api.getFieldState(args[0]);
1292
+ case "setFieldValue":
1293
+ api.setFieldValue(args[0], args[1]);
1294
+ return;
1295
+ case "setFieldsValue":
1296
+ api.setFieldsValue(args[0]);
1297
+ return;
1298
+ case "setFieldErrors":
1299
+ api.setFieldErrors(args[0], [...args[1]]);
1300
+ return;
1301
+ case "validateFields": return api.validateFields(args[0], args[1]);
1302
+ case "submit": return api.submit();
1303
+ case "cancelSubmit":
1304
+ api.cancelSubmit();
1305
+ return;
1306
+ case "resetFields":
1307
+ api.resetFields(args[0]);
1308
+ return;
1309
+ case "focusField": return api.focusField(args[0]);
1310
+ case "getFieldProps": return api.getFieldProps(args[0]);
1311
+ case "getInputProps": return api.getInputProps(args[0]);
1312
+ case "getCheckboxProps": return api.getCheckboxProps(args[0]);
1313
+ case "getRadioGroupProps": return api.getRadioGroupProps(args[0]);
1314
+ case "getSegmentedProps": return api.getSegmentedProps(args[0]);
1315
+ case "getNativeControlProps": return api.getNativeControlProps(args[0]);
1316
+ case "getNativeElementProps": return api.getNativeElementProps(args[0]);
1317
+ case "getReadonlyProps": return api.getReadonlyProps(args[0]);
1318
+ default: throw new TypeError(`Unknown Form method: ${method}`);
1319
+ }
1320
+ }
1321
+ /** Hosts call this before invoke. Disconnected or not-yet-ready calls throw. */
1322
+ function assertFormMethodReady(ready) {
1323
+ if (!ready) throw new TypeError("Form method is unavailable until the element is connected and updateComplete has resolved");
1324
+ }
1325
+ //#endregion
1326
+ //#region src/form/ssr.ts
1327
+ /**
1328
+ * SSR accepts builtin JSON rules only.
1329
+ * Custom validators and business handlers are runtime values: encountering one throws.
1330
+ * Nothing is eval'd or silently dropped.
1331
+ */
1332
+ function assertFormSsrProps(props) {
1333
+ const visit = (value, path) => {
1334
+ if (typeof value === "function") throw new TypeError(`Form SSR cannot accept a runtime function at ${path}`);
1335
+ if (value === null || typeof value === "string" || typeof value === "boolean") return;
1336
+ if (typeof value === "number") {
1337
+ if (!Number.isFinite(value)) throw new TypeError(`Form SSR requires finite numbers at ${path}`);
1338
+ return;
1339
+ }
1340
+ if (typeof value !== "object") throw new TypeError(`Form SSR cannot serialize ${typeof value} at ${path}`);
1341
+ const prototype = Object.getPrototypeOf(value);
1342
+ if (!Array.isArray(value) && prototype !== Object.prototype && prototype !== null) throw new TypeError(`Form SSR requires plain JSON at ${path}`);
1343
+ if (Array.isArray(value)) {
1344
+ value.forEach((item, index) => visit(item, `${path}[${index}]`));
1345
+ return;
1346
+ }
1347
+ for (const [key, child] of Object.entries(value)) visit(child, `${path}.${key}`);
1348
+ };
1349
+ visit(props, "form");
1350
+ }
1351
+ //#endregion
1352
+ export { formLabelId as C, formFieldStem as S, validateFormRule as _, connectForm as a, formDomId as b, formMachine as c, submittedFieldValue as d, FORM_DEFAULT_MESSAGES as f, normalizeFormRule as g, isFormEmpty as h, FORM_PARTS as i, normalizeFormFields as l, formErrorMessage as m, assertFormMethodReady as n, connectFormBehavior as o, FORM_MESSAGES_EN as p, invokeFormApi as r, createFormProps as s, assertFormSsrProps as t, normalizeFormInteraction as u, trackFormNative as v, formFieldRootId as x, formControlStem as y };
1353
+
1354
+ //# sourceMappingURL=form-BAGkIEMY.js.map