@multiplatform.one/frappe-ui 7.7.6 → 7.8.0

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 (491) hide show
  1. package/dist/cjs/ChartCard.native.js.map +1 -1
  2. package/dist/cjs/FileBrowser/AttachLibrary.native.js.map +1 -1
  3. package/dist/cjs/FileBrowser/folderTree.native.js.map +1 -1
  4. package/dist/cjs/FileBrowser/index.native.js.map +1 -1
  5. package/dist/cjs/FileBrowser/types.native.js.map +1 -1
  6. package/dist/cjs/FileBrowser/viewPersistence.native.js.map +1 -1
  7. package/dist/cjs/FormSidebar.native.js.map +1 -1
  8. package/dist/cjs/FrappeAssignment.native.js.map +1 -1
  9. package/dist/cjs/FrappeCalendar.cjs +20 -17
  10. package/dist/cjs/FrappeCalendar.native.js +22 -21
  11. package/dist/cjs/FrappeCalendar.native.js.map +1 -1
  12. package/dist/cjs/FrappeChartCard.native.js.map +1 -1
  13. package/dist/cjs/FrappeConnectionIndicator.native.js.map +1 -1
  14. package/dist/cjs/FrappeDashboard.native.js.map +1 -1
  15. package/dist/cjs/FrappeForm.cjs +1 -1
  16. package/dist/cjs/FrappeForm.native.js +2 -2
  17. package/dist/cjs/FrappeForm.native.js.map +1 -1
  18. package/dist/cjs/FrappeGantt.cjs +25 -34
  19. package/dist/cjs/FrappeGantt.native.js +27 -38
  20. package/dist/cjs/FrappeGantt.native.js.map +1 -1
  21. package/dist/cjs/FrappeImageView.cjs +4 -2
  22. package/dist/cjs/FrappeImageView.native.js +8 -4
  23. package/dist/cjs/FrappeImageView.native.js.map +1 -1
  24. package/dist/cjs/FrappeKPICard.cjs +26 -1
  25. package/dist/cjs/FrappeKPICard.native.js +26 -1
  26. package/dist/cjs/FrappeKPICard.native.js.map +1 -1
  27. package/dist/cjs/FrappeKanban.cjs +16 -17
  28. package/dist/cjs/FrappeKanban.native.js +18 -21
  29. package/dist/cjs/FrappeKanban.native.js.map +1 -1
  30. package/dist/cjs/FrappeLikedBy.cjs +1 -1
  31. package/dist/cjs/FrappeLikedBy.native.js +1 -1
  32. package/dist/cjs/FrappeLikedBy.native.js.map +1 -1
  33. package/dist/cjs/FrappeList.cjs +2 -2
  34. package/dist/cjs/FrappeList.native.js +2 -2
  35. package/dist/cjs/FrappeList.native.js.map +1 -1
  36. package/dist/cjs/FrappeListView.native.js.map +1 -1
  37. package/dist/cjs/FrappeProvider.native.js.map +1 -1
  38. package/dist/cjs/FrappeReconnectIndicator.native.js.map +1 -1
  39. package/dist/cjs/FrappeReportBuilder.cjs +2 -2
  40. package/dist/cjs/FrappeReportBuilder.native.js +2 -2
  41. package/dist/cjs/FrappeReportBuilder.native.js.map +1 -1
  42. package/dist/cjs/FrappeReportView.native.js +3 -3
  43. package/dist/cjs/FrappeReportView.native.js.map +1 -1
  44. package/dist/cjs/FrappeTable.cjs +35 -38
  45. package/dist/cjs/FrappeTable.native.js +38 -39
  46. package/dist/cjs/FrappeTable.native.js.map +1 -1
  47. package/dist/cjs/FrappeTreeView.cjs +85 -50
  48. package/dist/cjs/FrappeTreeView.native.js +129 -50
  49. package/dist/cjs/FrappeTreeView.native.js.map +1 -1
  50. package/dist/cjs/SyncErrorNotice.native.js.map +1 -1
  51. package/dist/cjs/commentActions.cjs +1 -1
  52. package/dist/cjs/commentActions.native.js +1 -1
  53. package/dist/cjs/commentActions.native.js.map +1 -1
  54. package/dist/cjs/components/attachments.native.js.map +1 -1
  55. package/dist/cjs/components/tags.native.js.map +1 -1
  56. package/dist/cjs/components/timeline.cjs +1 -1
  57. package/dist/cjs/components/timeline.native.js +1 -1
  58. package/dist/cjs/components/timeline.native.js.map +1 -1
  59. package/dist/cjs/dependsOn.native.js.map +1 -1
  60. package/dist/cjs/desk/DeskFormPage.native.js.map +1 -1
  61. package/dist/cjs/desk/DeskFormSidebar.native.js.map +1 -1
  62. package/dist/cjs/desk/DeskListPage.native.js.map +1 -1
  63. package/dist/cjs/desk/DeskShell.cjs +2 -0
  64. package/dist/cjs/desk/DeskShell.native.js +2 -0
  65. package/dist/cjs/desk/DeskShell.native.js.map +1 -1
  66. package/dist/cjs/desk/DeskSidebar.native.js.map +1 -1
  67. package/dist/cjs/desk/awesomebar.cjs +1 -1
  68. package/dist/cjs/desk/awesomebar.native.js +1 -1
  69. package/dist/cjs/desk/awesomebar.native.js.map +1 -1
  70. package/dist/cjs/fieldOverrides.native.js.map +1 -1
  71. package/dist/cjs/fieldRegistry.native.js +31 -31
  72. package/dist/cjs/fieldRegistry.native.js.map +1 -1
  73. package/dist/cjs/fields/Barcode/index.native.js.map +1 -1
  74. package/dist/cjs/fields/Check/index.native.js.map +1 -1
  75. package/dist/cjs/fields/CodeEditor/index.native.js.map +1 -1
  76. package/dist/cjs/fields/Color/index.native.js.map +1 -1
  77. package/dist/cjs/fields/Data/index.native.js.map +1 -1
  78. package/dist/cjs/fields/Date/sheetKeyboard.native.js.map +1 -1
  79. package/dist/cjs/fields/Date/types.native.js.map +1 -1
  80. package/dist/cjs/fields/Date/wire.native.js.map +1 -1
  81. package/dist/cjs/fields/DateRange/index.native.js.map +1 -1
  82. package/dist/cjs/fields/Duration/index.native.js.map +1 -1
  83. package/dist/cjs/fields/DynamicLink.native.js.map +1 -1
  84. package/dist/cjs/fields/FileUpload.native.js.map +1 -1
  85. package/dist/cjs/fields/FileUploadField/index.native.js.map +1 -1
  86. package/dist/cjs/fields/Geolocation/index.native.js.map +1 -1
  87. package/dist/cjs/fields/HTML/index.native.js.map +1 -1
  88. package/dist/cjs/fields/Heading/index.native.js.map +1 -1
  89. package/dist/cjs/fields/Icon/index.native.js.map +1 -1
  90. package/dist/cjs/fields/Link.native.js.map +1 -1
  91. package/dist/cjs/fields/LinkTree.native.js.map +1 -1
  92. package/dist/cjs/fields/LongText/index.native.js.map +1 -1
  93. package/dist/cjs/fields/MentionInput/index.cjs +4 -1
  94. package/dist/cjs/fields/MentionInput/index.native.js +4 -1
  95. package/dist/cjs/fields/MentionInput/index.native.js.map +1 -1
  96. package/dist/cjs/fields/Numeric/index.native.js.map +1 -1
  97. package/dist/cjs/fields/OTPInput/index.native.js.map +1 -1
  98. package/dist/cjs/fields/Password/index.native.js.map +1 -1
  99. package/dist/cjs/fields/Phone/index.native.js.map +1 -1
  100. package/dist/cjs/fields/Progress/index.native.js.map +1 -1
  101. package/dist/cjs/fields/RadioGroup/index.native.js.map +1 -1
  102. package/dist/cjs/fields/Rating/index.native.js.map +1 -1
  103. package/dist/cjs/fields/ReadOnly/index.native.js.map +1 -1
  104. package/dist/cjs/fields/Select/index.native.js.map +1 -1
  105. package/dist/cjs/fields/Signature/index.native.js.map +1 -1
  106. package/dist/cjs/fields/Slider/index.native.js.map +1 -1
  107. package/dist/cjs/fields/SmallText/index.native.js.map +1 -1
  108. package/dist/cjs/fields/Switch/index.native.js.map +1 -1
  109. package/dist/cjs/fields/TableMultiSelect.native.js.map +1 -1
  110. package/dist/cjs/fields/TextEditor/types.native.js.map +1 -1
  111. package/dist/cjs/fields/TimePicker/index.native.js.map +1 -1
  112. package/dist/cjs/fields/ToggleGroup/index.native.js.map +1 -1
  113. package/dist/cjs/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  114. package/dist/cjs/filterFields.native.js.map +1 -1
  115. package/dist/cjs/formEngine/createPrefill.native.js.map +1 -1
  116. package/dist/cjs/formEngine/dirtyTracking.native.js.map +1 -1
  117. package/dist/cjs/formEngine/doctypeMeta.native.js.map +1 -1
  118. package/dist/cjs/formEngine/fetchFrom.native.js.map +1 -1
  119. package/dist/cjs/formEngine/fieldPermissions.native.js.map +1 -1
  120. package/dist/cjs/formEngine/formActions.native.js.map +1 -1
  121. package/dist/cjs/formEngine/formLayout.native.js.map +1 -1
  122. package/dist/cjs/formEngine/index.native.js.map +1 -1
  123. package/dist/cjs/formEngine/useFormEngine.native.js.map +1 -1
  124. package/dist/cjs/frappeEventColor.native.js.map +1 -1
  125. package/dist/cjs/frappeStoryTarget.native.js.map +1 -1
  126. package/dist/cjs/frappeUsers.native.js.map +1 -1
  127. package/dist/cjs/index.cjs +4 -0
  128. package/dist/cjs/index.native.js +38 -34
  129. package/dist/cjs/index.native.js.map +1 -1
  130. package/dist/cjs/liveErrors.native.js.map +1 -1
  131. package/dist/cjs/resolveControl.native.js.map +1 -1
  132. package/dist/cjs/schemaForm/SchemaWizard.native.js.map +1 -1
  133. package/dist/cjs/schemaForm/applyFieldOrder.native.js.map +1 -1
  134. package/dist/cjs/schemaForm/index.cjs +10 -9
  135. package/dist/cjs/schemaForm/index.native.js +11 -10
  136. package/dist/cjs/schemaForm/index.native.js.map +1 -1
  137. package/dist/cjs/shared/devWarn.cjs +40 -0
  138. package/dist/cjs/shared/devWarn.native.js +45 -0
  139. package/dist/cjs/shared/devWarn.native.js.map +1 -0
  140. package/dist/cjs/shared/useKeyboardInset.native.js.map +1 -1
  141. package/dist/cjs/syncError.native.js.map +1 -1
  142. package/dist/cjs/useFrappeAggregate.cjs +15 -8
  143. package/dist/cjs/useFrappeAggregate.native.js +15 -9
  144. package/dist/cjs/useFrappeAggregate.native.js.map +1 -1
  145. package/dist/cjs/useFrappeFacets.cjs +10 -9
  146. package/dist/cjs/useFrappeFacets.native.js +10 -10
  147. package/dist/cjs/useFrappeFacets.native.js.map +1 -1
  148. package/dist/cjs/useFrappePagination.native.js.map +1 -1
  149. package/dist/cjs/useFrappeRows.cjs +113 -0
  150. package/dist/cjs/useFrappeRows.native.js +129 -0
  151. package/dist/cjs/useFrappeRows.native.js.map +1 -0
  152. package/dist/esm/ChartCard.native.js.map +1 -1
  153. package/dist/esm/FileBrowser/AttachLibrary.native.js.map +1 -1
  154. package/dist/esm/FileBrowser/folderTree.native.js.map +1 -1
  155. package/dist/esm/FileBrowser/index.native.js.map +1 -1
  156. package/dist/esm/FileBrowser/types.native.js.map +1 -1
  157. package/dist/esm/FileBrowser/viewPersistence.native.js.map +1 -1
  158. package/dist/esm/FormSidebar.native.js.map +1 -1
  159. package/dist/esm/FrappeAssignment.native.js.map +1 -1
  160. package/dist/esm/FrappeCalendar.mjs +20 -17
  161. package/dist/esm/FrappeCalendar.mjs.map +1 -1
  162. package/dist/esm/FrappeCalendar.native.js +22 -21
  163. package/dist/esm/FrappeCalendar.native.js.map +1 -1
  164. package/dist/esm/FrappeChartCard.native.js.map +1 -1
  165. package/dist/esm/FrappeConnectionIndicator.native.js.map +1 -1
  166. package/dist/esm/FrappeDashboard.native.js.map +1 -1
  167. package/dist/esm/FrappeForm.mjs +1 -1
  168. package/dist/esm/FrappeForm.mjs.map +1 -1
  169. package/dist/esm/FrappeForm.native.js +1 -1
  170. package/dist/esm/FrappeForm.native.js.map +1 -1
  171. package/dist/esm/FrappeGantt.mjs +27 -36
  172. package/dist/esm/FrappeGantt.mjs.map +1 -1
  173. package/dist/esm/FrappeGantt.native.js +29 -40
  174. package/dist/esm/FrappeGantt.native.js.map +1 -1
  175. package/dist/esm/FrappeImageView.mjs +5 -3
  176. package/dist/esm/FrappeImageView.mjs.map +1 -1
  177. package/dist/esm/FrappeImageView.native.js +9 -5
  178. package/dist/esm/FrappeImageView.native.js.map +1 -1
  179. package/dist/esm/FrappeKPICard.mjs +27 -2
  180. package/dist/esm/FrappeKPICard.mjs.map +1 -1
  181. package/dist/esm/FrappeKPICard.native.js +27 -2
  182. package/dist/esm/FrappeKPICard.native.js.map +1 -1
  183. package/dist/esm/FrappeKanban.mjs +16 -17
  184. package/dist/esm/FrappeKanban.mjs.map +1 -1
  185. package/dist/esm/FrappeKanban.native.js +18 -21
  186. package/dist/esm/FrappeKanban.native.js.map +1 -1
  187. package/dist/esm/FrappeLikedBy.mjs +1 -1
  188. package/dist/esm/FrappeLikedBy.mjs.map +1 -1
  189. package/dist/esm/FrappeLikedBy.native.js +1 -1
  190. package/dist/esm/FrappeLikedBy.native.js.map +1 -1
  191. package/dist/esm/FrappeList.mjs +2 -2
  192. package/dist/esm/FrappeList.mjs.map +1 -1
  193. package/dist/esm/FrappeList.native.js +2 -2
  194. package/dist/esm/FrappeList.native.js.map +1 -1
  195. package/dist/esm/FrappeListView.native.js.map +1 -1
  196. package/dist/esm/FrappeProvider.mjs.map +1 -1
  197. package/dist/esm/FrappeProvider.native.js.map +1 -1
  198. package/dist/esm/FrappeReconnectIndicator.native.js.map +1 -1
  199. package/dist/esm/FrappeReportBuilder.mjs +2 -2
  200. package/dist/esm/FrappeReportBuilder.mjs.map +1 -1
  201. package/dist/esm/FrappeReportBuilder.native.js +2 -2
  202. package/dist/esm/FrappeReportBuilder.native.js.map +1 -1
  203. package/dist/esm/FrappeReportView.native.js.map +1 -1
  204. package/dist/esm/FrappeTable.mjs +36 -39
  205. package/dist/esm/FrappeTable.mjs.map +1 -1
  206. package/dist/esm/FrappeTable.native.js +39 -40
  207. package/dist/esm/FrappeTable.native.js.map +1 -1
  208. package/dist/esm/FrappeTreeView.mjs +89 -55
  209. package/dist/esm/FrappeTreeView.mjs.map +1 -1
  210. package/dist/esm/FrappeTreeView.native.js +133 -55
  211. package/dist/esm/FrappeTreeView.native.js.map +1 -1
  212. package/dist/esm/SyncErrorNotice.native.js.map +1 -1
  213. package/dist/esm/commentActions.mjs +1 -1
  214. package/dist/esm/commentActions.mjs.map +1 -1
  215. package/dist/esm/commentActions.native.js +1 -1
  216. package/dist/esm/commentActions.native.js.map +1 -1
  217. package/dist/esm/components/attachments.native.js.map +1 -1
  218. package/dist/esm/components/tags.native.js.map +1 -1
  219. package/dist/esm/components/timeline.mjs +1 -1
  220. package/dist/esm/components/timeline.mjs.map +1 -1
  221. package/dist/esm/components/timeline.native.js +1 -1
  222. package/dist/esm/components/timeline.native.js.map +1 -1
  223. package/dist/esm/dependsOn.native.js.map +1 -1
  224. package/dist/esm/desk/DeskFormPage.native.js.map +1 -1
  225. package/dist/esm/desk/DeskFormSidebar.native.js.map +1 -1
  226. package/dist/esm/desk/DeskListPage.native.js.map +1 -1
  227. package/dist/esm/desk/DeskShell.mjs +2 -0
  228. package/dist/esm/desk/DeskShell.mjs.map +1 -1
  229. package/dist/esm/desk/DeskShell.native.js +2 -0
  230. package/dist/esm/desk/DeskShell.native.js.map +1 -1
  231. package/dist/esm/desk/DeskSidebar.native.js.map +1 -1
  232. package/dist/esm/desk/awesomebar.mjs +1 -1
  233. package/dist/esm/desk/awesomebar.mjs.map +1 -1
  234. package/dist/esm/desk/awesomebar.native.js +1 -1
  235. package/dist/esm/desk/awesomebar.native.js.map +1 -1
  236. package/dist/esm/fieldOverrides.native.js.map +1 -1
  237. package/dist/esm/fieldRegistry.native.js.map +1 -1
  238. package/dist/esm/fields/Barcode/index.native.js.map +1 -1
  239. package/dist/esm/fields/Check/index.native.js.map +1 -1
  240. package/dist/esm/fields/CodeEditor/index.native.js.map +1 -1
  241. package/dist/esm/fields/Color/index.native.js.map +1 -1
  242. package/dist/esm/fields/Data/index.native.js.map +1 -1
  243. package/dist/esm/fields/Date/sheetKeyboard.native.js.map +1 -1
  244. package/dist/esm/fields/Date/types.native.js.map +1 -1
  245. package/dist/esm/fields/Date/wire.native.js.map +1 -1
  246. package/dist/esm/fields/DateRange/index.native.js.map +1 -1
  247. package/dist/esm/fields/Duration/index.native.js.map +1 -1
  248. package/dist/esm/fields/DynamicLink.native.js.map +1 -1
  249. package/dist/esm/fields/FileUpload.native.js.map +1 -1
  250. package/dist/esm/fields/FileUploadField/index.native.js.map +1 -1
  251. package/dist/esm/fields/Geolocation/index.native.js.map +1 -1
  252. package/dist/esm/fields/HTML/index.native.js.map +1 -1
  253. package/dist/esm/fields/Heading/index.native.js.map +1 -1
  254. package/dist/esm/fields/Icon/index.native.js.map +1 -1
  255. package/dist/esm/fields/Link.native.js.map +1 -1
  256. package/dist/esm/fields/LinkTree.native.js.map +1 -1
  257. package/dist/esm/fields/LongText/index.native.js.map +1 -1
  258. package/dist/esm/fields/MentionInput/index.mjs +4 -1
  259. package/dist/esm/fields/MentionInput/index.mjs.map +1 -1
  260. package/dist/esm/fields/MentionInput/index.native.js +4 -1
  261. package/dist/esm/fields/MentionInput/index.native.js.map +1 -1
  262. package/dist/esm/fields/Numeric/index.native.js.map +1 -1
  263. package/dist/esm/fields/OTPInput/index.native.js.map +1 -1
  264. package/dist/esm/fields/Password/index.native.js.map +1 -1
  265. package/dist/esm/fields/Phone/index.native.js.map +1 -1
  266. package/dist/esm/fields/Progress/index.native.js.map +1 -1
  267. package/dist/esm/fields/RadioGroup/index.native.js.map +1 -1
  268. package/dist/esm/fields/Rating/index.native.js.map +1 -1
  269. package/dist/esm/fields/ReadOnly/index.native.js.map +1 -1
  270. package/dist/esm/fields/Select/index.native.js.map +1 -1
  271. package/dist/esm/fields/Signature/index.native.js.map +1 -1
  272. package/dist/esm/fields/Slider/index.native.js.map +1 -1
  273. package/dist/esm/fields/SmallText/index.native.js.map +1 -1
  274. package/dist/esm/fields/Switch/index.native.js.map +1 -1
  275. package/dist/esm/fields/TableMultiSelect.native.js.map +1 -1
  276. package/dist/esm/fields/TextEditor/types.native.js.map +1 -1
  277. package/dist/esm/fields/TimePicker/index.native.js.map +1 -1
  278. package/dist/esm/fields/ToggleGroup/index.native.js.map +1 -1
  279. package/dist/esm/fields/shared/EditorPreviewPanes.native.js.map +1 -1
  280. package/dist/esm/filterFields.native.js.map +1 -1
  281. package/dist/esm/formEngine/createPrefill.native.js.map +1 -1
  282. package/dist/esm/formEngine/dirtyTracking.native.js.map +1 -1
  283. package/dist/esm/formEngine/doctypeMeta.native.js.map +1 -1
  284. package/dist/esm/formEngine/fetchFrom.native.js.map +1 -1
  285. package/dist/esm/formEngine/fieldPermissions.native.js.map +1 -1
  286. package/dist/esm/formEngine/formActions.native.js.map +1 -1
  287. package/dist/esm/formEngine/formLayout.native.js.map +1 -1
  288. package/dist/esm/formEngine/index.native.js.map +1 -1
  289. package/dist/esm/formEngine/useFormEngine.native.js.map +1 -1
  290. package/dist/esm/frappeEventColor.native.js.map +1 -1
  291. package/dist/esm/frappeStoryTarget.native.js.map +1 -1
  292. package/dist/esm/frappeUsers.native.js.map +1 -1
  293. package/dist/esm/index.mjs +2 -1
  294. package/dist/esm/index.mjs.map +1 -1
  295. package/dist/esm/index.native.js +2 -1
  296. package/dist/esm/index.native.js.map +1 -1
  297. package/dist/esm/liveErrors.native.js.map +1 -1
  298. package/dist/esm/resolveControl.native.js.map +1 -1
  299. package/dist/esm/schemaForm/SchemaWizard.native.js.map +1 -1
  300. package/dist/esm/schemaForm/applyFieldOrder.native.js.map +1 -1
  301. package/dist/esm/schemaForm/index.mjs +8 -7
  302. package/dist/esm/schemaForm/index.mjs.map +1 -1
  303. package/dist/esm/schemaForm/index.native.js +8 -7
  304. package/dist/esm/schemaForm/index.native.js.map +1 -1
  305. package/dist/esm/shared/devWarn.mjs +14 -0
  306. package/dist/esm/shared/devWarn.mjs.map +1 -0
  307. package/dist/esm/shared/devWarn.native.js +16 -0
  308. package/dist/esm/shared/devWarn.native.js.map +1 -0
  309. package/dist/esm/shared/useKeyboardInset.native.js.map +1 -1
  310. package/dist/esm/syncError.native.js.map +1 -1
  311. package/dist/esm/useFrappeAggregate.mjs +15 -8
  312. package/dist/esm/useFrappeAggregate.mjs.map +1 -1
  313. package/dist/esm/useFrappeAggregate.native.js +15 -9
  314. package/dist/esm/useFrappeAggregate.native.js.map +1 -1
  315. package/dist/esm/useFrappeFacets.mjs +10 -9
  316. package/dist/esm/useFrappeFacets.mjs.map +1 -1
  317. package/dist/esm/useFrappeFacets.native.js +10 -10
  318. package/dist/esm/useFrappeFacets.native.js.map +1 -1
  319. package/dist/esm/useFrappePagination.native.js.map +1 -1
  320. package/dist/esm/useFrappeRows.mjs +86 -0
  321. package/dist/esm/useFrappeRows.mjs.map +1 -0
  322. package/dist/esm/useFrappeRows.native.js +99 -0
  323. package/dist/esm/useFrappeRows.native.js.map +1 -0
  324. package/dist/jsx/FrappeCalendar.mjs +20 -17
  325. package/dist/jsx/FrappeCalendar.mjs.map +1 -1
  326. package/dist/jsx/FrappeCalendar.native.js +22 -21
  327. package/dist/jsx/FrappeCalendar.native.js.map +1 -1
  328. package/dist/jsx/FrappeForm.mjs +1 -1
  329. package/dist/jsx/FrappeForm.mjs.map +1 -1
  330. package/dist/jsx/FrappeForm.native.js +1 -1
  331. package/dist/jsx/FrappeForm.native.js.map +1 -1
  332. package/dist/jsx/FrappeGantt.mjs +27 -36
  333. package/dist/jsx/FrappeGantt.mjs.map +1 -1
  334. package/dist/jsx/FrappeGantt.native.js +27 -38
  335. package/dist/jsx/FrappeGantt.native.js.map +1 -1
  336. package/dist/jsx/FrappeImageView.mjs +5 -3
  337. package/dist/jsx/FrappeImageView.mjs.map +1 -1
  338. package/dist/jsx/FrappeImageView.native.js +8 -4
  339. package/dist/jsx/FrappeImageView.native.js.map +1 -1
  340. package/dist/jsx/FrappeKPICard.mjs +27 -2
  341. package/dist/jsx/FrappeKPICard.mjs.map +1 -1
  342. package/dist/jsx/FrappeKPICard.native.js +26 -1
  343. package/dist/jsx/FrappeKPICard.native.js.map +1 -1
  344. package/dist/jsx/FrappeKanban.mjs +16 -17
  345. package/dist/jsx/FrappeKanban.mjs.map +1 -1
  346. package/dist/jsx/FrappeKanban.native.js +18 -21
  347. package/dist/jsx/FrappeKanban.native.js.map +1 -1
  348. package/dist/jsx/FrappeLikedBy.mjs +1 -1
  349. package/dist/jsx/FrappeLikedBy.mjs.map +1 -1
  350. package/dist/jsx/FrappeLikedBy.native.js +1 -1
  351. package/dist/jsx/FrappeLikedBy.native.js.map +1 -1
  352. package/dist/jsx/FrappeList.mjs +2 -2
  353. package/dist/jsx/FrappeList.mjs.map +1 -1
  354. package/dist/jsx/FrappeList.native.js +2 -2
  355. package/dist/jsx/FrappeList.native.js.map +1 -1
  356. package/dist/jsx/FrappeProvider.mjs.map +1 -1
  357. package/dist/jsx/FrappeProvider.native.js.map +1 -1
  358. package/dist/jsx/FrappeReportBuilder.mjs +2 -2
  359. package/dist/jsx/FrappeReportBuilder.mjs.map +1 -1
  360. package/dist/jsx/FrappeReportBuilder.native.js +2 -2
  361. package/dist/jsx/FrappeReportBuilder.native.js.map +1 -1
  362. package/dist/jsx/FrappeTable.mjs +36 -39
  363. package/dist/jsx/FrappeTable.mjs.map +1 -1
  364. package/dist/jsx/FrappeTable.native.js +38 -39
  365. package/dist/jsx/FrappeTable.native.js.map +1 -1
  366. package/dist/jsx/FrappeTreeView.mjs +89 -55
  367. package/dist/jsx/FrappeTreeView.mjs.map +1 -1
  368. package/dist/jsx/FrappeTreeView.native.js +129 -50
  369. package/dist/jsx/FrappeTreeView.native.js.map +1 -1
  370. package/dist/jsx/commentActions.mjs +1 -1
  371. package/dist/jsx/commentActions.mjs.map +1 -1
  372. package/dist/jsx/commentActions.native.js +1 -1
  373. package/dist/jsx/commentActions.native.js.map +1 -1
  374. package/dist/jsx/components/timeline.mjs +1 -1
  375. package/dist/jsx/components/timeline.mjs.map +1 -1
  376. package/dist/jsx/components/timeline.native.js +1 -1
  377. package/dist/jsx/desk/DeskShell.mjs +2 -0
  378. package/dist/jsx/desk/DeskShell.mjs.map +1 -1
  379. package/dist/jsx/desk/DeskShell.native.js +2 -0
  380. package/dist/jsx/desk/DeskShell.native.js.map +1 -1
  381. package/dist/jsx/desk/awesomebar.mjs +1 -1
  382. package/dist/jsx/desk/awesomebar.mjs.map +1 -1
  383. package/dist/jsx/desk/awesomebar.native.js +1 -1
  384. package/dist/jsx/desk/awesomebar.native.js.map +1 -1
  385. package/dist/jsx/fields/MentionInput/index.mjs +4 -1
  386. package/dist/jsx/fields/MentionInput/index.mjs.map +1 -1
  387. package/dist/jsx/fields/MentionInput/index.native.js +4 -1
  388. package/dist/jsx/fields/MentionInput/index.native.js.map +1 -1
  389. package/dist/jsx/index.js +2 -1
  390. package/dist/jsx/index.js.map +1 -1
  391. package/dist/jsx/index.mjs +2 -1
  392. package/dist/jsx/index.mjs.map +1 -1
  393. package/dist/jsx/index.native.js +4 -0
  394. package/dist/jsx/index.native.js.map +1 -1
  395. package/dist/jsx/schemaForm/index.mjs +8 -7
  396. package/dist/jsx/schemaForm/index.mjs.map +1 -1
  397. package/dist/jsx/schemaForm/index.native.js +10 -9
  398. package/dist/jsx/schemaForm/index.native.js.map +1 -1
  399. package/dist/jsx/shared/devWarn.mjs +14 -0
  400. package/dist/jsx/shared/devWarn.mjs.map +1 -0
  401. package/dist/jsx/shared/devWarn.native.js +45 -0
  402. package/dist/jsx/shared/devWarn.native.js.map +1 -0
  403. package/dist/jsx/useFrappeAggregate.mjs +15 -8
  404. package/dist/jsx/useFrappeAggregate.mjs.map +1 -1
  405. package/dist/jsx/useFrappeAggregate.native.js +15 -9
  406. package/dist/jsx/useFrappeAggregate.native.js.map +1 -1
  407. package/dist/jsx/useFrappeFacets.mjs +10 -9
  408. package/dist/jsx/useFrappeFacets.mjs.map +1 -1
  409. package/dist/jsx/useFrappeFacets.native.js +10 -10
  410. package/dist/jsx/useFrappeFacets.native.js.map +1 -1
  411. package/dist/jsx/useFrappeRows.mjs +86 -0
  412. package/dist/jsx/useFrappeRows.mjs.map +1 -0
  413. package/dist/jsx/useFrappeRows.native.js +129 -0
  414. package/dist/jsx/useFrappeRows.native.js.map +1 -0
  415. package/package.json +17 -16
  416. package/src/FileBrowser/FileBrowser.spec.tsx +11 -1
  417. package/src/FrappeCalendar.tsx +25 -22
  418. package/src/FrappeForm.tsx +7 -3
  419. package/src/FrappeGantt.tsx +29 -39
  420. package/src/FrappeImageView.tsx +5 -3
  421. package/src/FrappeKPICard.spec.tsx +128 -0
  422. package/src/FrappeKPICard.tsx +44 -4
  423. package/src/FrappeKanban.tsx +24 -17
  424. package/src/FrappeLikedBy.tsx +1 -1
  425. package/src/FrappeList.tsx +3 -2
  426. package/src/FrappeProvider.fixturesOnly.spec.tsx +129 -0
  427. package/src/FrappeProvider.tsx +16 -6
  428. package/src/FrappeReportBuilder.tsx +4 -2
  429. package/src/FrappeTable.autoHeight.spec.tsx +142 -0
  430. package/src/FrappeTable.rowAccumulator.spec.tsx +110 -0
  431. package/src/FrappeTable.tsx +75 -48
  432. package/src/FrappeTreeView.stories.tsx +59 -0
  433. package/src/FrappeTreeView.tsx +166 -56
  434. package/src/commentActions.ts +1 -1
  435. package/src/components/timeline.tsx +1 -1
  436. package/src/desk/DeskShell.tsx +2 -0
  437. package/src/desk/awesomebar.tsx +5 -2
  438. package/src/fields/CodeEditor/CodeEditor.spec.tsx +10 -9
  439. package/src/fields/Date/typeParity.spec.tsx +19 -9
  440. package/src/fields/Duration/Duration.spec.tsx +73 -0
  441. package/src/fields/MentionInput/MentionInput.spec.tsx +110 -0
  442. package/src/fields/MentionInput/index.tsx +4 -1
  443. package/src/fields/Password/index.tsx +1 -1
  444. package/src/fields/Progress/Progress.spec.tsx +9 -0
  445. package/src/fields/RadioGroup/RadioGroup.spec.tsx +93 -0
  446. package/src/fields/Signature/Signature.spec.tsx +105 -0
  447. package/src/fields/Slider/Slider.spec.tsx +73 -0
  448. package/src/fields/Switch/Switch.spec.tsx +65 -0
  449. package/src/fields/TextEditor/TextEditor.spec.tsx +2 -3
  450. package/src/fields/TextEditor/TextEditor.stories.tsx +31 -1
  451. package/src/fields/ToggleGroup/ToggleGroup.spec.tsx +110 -0
  452. package/src/frappeViews.designLaw.spec.ts +11 -7
  453. package/src/index.ts +13 -0
  454. package/src/schemaForm/index.tsx +6 -7
  455. package/src/shared/devWarn.ts +42 -0
  456. package/src/useFrappeAggregate.ts +17 -11
  457. package/src/useFrappeFacets.ts +17 -10
  458. package/src/useFrappeRows.spec.tsx +176 -0
  459. package/src/useFrappeRows.ts +293 -0
  460. package/types/FrappeCalendar.d.ts.map +1 -1
  461. package/types/FrappeForm.d.ts +6 -2
  462. package/types/FrappeForm.d.ts.map +1 -1
  463. package/types/FrappeGantt.d.ts.map +1 -1
  464. package/types/FrappeImageView.d.ts.map +1 -1
  465. package/types/FrappeKPICard.d.ts +9 -1
  466. package/types/FrappeKPICard.d.ts.map +1 -1
  467. package/types/FrappeKanban.d.ts.map +1 -1
  468. package/types/FrappeList.d.ts.map +1 -1
  469. package/types/FrappeProvider.d.ts +16 -6
  470. package/types/FrappeProvider.d.ts.map +1 -1
  471. package/types/FrappeReportBuilder.d.ts.map +1 -1
  472. package/types/FrappeTable.d.ts +20 -1
  473. package/types/FrappeTable.d.ts.map +1 -1
  474. package/types/FrappeTreeView.d.ts +38 -1
  475. package/types/FrappeTreeView.d.ts.map +1 -1
  476. package/types/desk/DeskShell.d.ts.map +1 -1
  477. package/types/desk/awesomebar.d.ts.map +1 -1
  478. package/types/fields/MentionInput/index.d.ts.map +1 -1
  479. package/types/fields/Password/index.d.ts +1 -1
  480. package/types/fields/Password/index.d.ts.map +1 -1
  481. package/types/index.d.ts +1 -0
  482. package/types/index.d.ts.map +1 -1
  483. package/types/schemaForm/index.d.ts.map +1 -1
  484. package/types/shared/devWarn.d.ts +23 -0
  485. package/types/shared/devWarn.d.ts.map +1 -0
  486. package/types/useFrappeAggregate.d.ts +2 -1
  487. package/types/useFrappeAggregate.d.ts.map +1 -1
  488. package/types/useFrappeFacets.d.ts +2 -1
  489. package/types/useFrappeFacets.d.ts.map +1 -1
  490. package/types/useFrappeRows.d.ts +186 -0
  491. package/types/useFrappeRows.d.ts.map +1 -0
@@ -0,0 +1,110 @@
1
+ /**
2
+ * MentionInputField contract specs. The registry hands `value` and `onChange`
3
+ * straight to this adapter (MentionAdapter in fieldRegistry). The failure
4
+ * mode of a thin adapter is dropping those two, so a saved comment never
5
+ * paints and a typed comment never emits (LC-14). Pin the hop.
6
+ */
7
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
8
+ import { act, cleanup, fireEvent } from "@testing-library/react";
9
+ import type React from "react";
10
+ import { afterEach, describe, expect, it, vi } from "vitest";
11
+ import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
12
+ import { MentionInputField, type MentionValue } from ".";
13
+
14
+ afterEach(cleanup);
15
+
16
+ const mentions = [{ trigger: "@", data: [{ id: "u1", display: "Ada" }] }];
17
+
18
+ const seeded: MentionValue = { text: "hello ada", mentions: [] };
19
+
20
+ const textarea = (container: HTMLElement) =>
21
+ container.querySelector("textarea") as HTMLTextAreaElement | null;
22
+
23
+ describe("MentionInputField composes the forms MentionInput", () => {
24
+ it("paints a controlled value onto the textarea", () => {
25
+ const result = renderWithProviders(
26
+ <MentionInputField label="Comment" mentions={mentions} value={seeded} onChange={() => {}} />,
27
+ );
28
+ expect(textarea(result.container)?.value).toBe("hello ada");
29
+ });
30
+
31
+ it("emits a MentionValue through canonical onChange", async () => {
32
+ const onChange = vi.fn();
33
+ const result = renderWithProviders(
34
+ <MentionInputField
35
+ label="Comment"
36
+ mentions={mentions}
37
+ value={{ text: "", mentions: [] }}
38
+ onChange={onChange}
39
+ />,
40
+ );
41
+ await act(async () => {
42
+ fireEvent.change(textarea(result.container) as HTMLTextAreaElement, {
43
+ target: { value: "typed" },
44
+ });
45
+ });
46
+ expect(onChange).toHaveBeenCalled();
47
+ const emitted = onChange.mock.calls.at(-1)?.[0] as MentionValue;
48
+ expect(emitted.text).toBe("typed");
49
+ expect(Array.isArray(emitted.mentions)).toBe(true);
50
+ });
51
+
52
+ it("forwards disabled onto the textarea", () => {
53
+ const result = renderWithProviders(
54
+ <MentionInputField
55
+ label="Comment"
56
+ mentions={mentions}
57
+ value={seeded}
58
+ disabled
59
+ onChange={() => {}}
60
+ />,
61
+ );
62
+ const el = textarea(result.container);
63
+ expect(el?.disabled || el?.getAttribute("aria-disabled") === "true").toBe(true);
64
+ });
65
+
66
+ it("forwards readOnly onto the textarea", () => {
67
+ const result = renderWithProviders(
68
+ <MentionInputField
69
+ label="Comment"
70
+ mentions={mentions}
71
+ value={seeded}
72
+ readOnly
73
+ onChange={() => {}}
74
+ />,
75
+ );
76
+ const el = textarea(result.container);
77
+ expect(el?.readOnly || el?.getAttribute("aria-readonly") === "true").toBe(true);
78
+ });
79
+
80
+ it("shows the label and error", () => {
81
+ const result = renderWithProviders(
82
+ <MentionInputField
83
+ label="Comment"
84
+ mentions={mentions}
85
+ value={seeded}
86
+ error="too short"
87
+ onChange={() => {}}
88
+ />,
89
+ );
90
+ expect(result.container.textContent).toContain("Comment");
91
+ expect(result.container.textContent).toContain("too short");
92
+ });
93
+ });
94
+
95
+ describe("registry resolution (Mention fieldtype)", () => {
96
+ function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
97
+ return { value: "", onChange: () => {}, ...overrides };
98
+ }
99
+
100
+ it("resolves 'Mention' to MentionInputField and hands value through", () => {
101
+ const Component = getFieldComponent("Mention")!;
102
+ expect(Component).toBeTruthy();
103
+ const element = (Component as Function)(
104
+ propsFor({ value: "hello ada", label: "Comment" }),
105
+ ) as React.ReactElement<Record<string, unknown>>;
106
+ expect(element.type).toBe(MentionInputField);
107
+ expect(element.props.value).toBe("hello ada");
108
+ expect(element.props.label).toBe("Comment");
109
+ });
110
+ });
@@ -79,7 +79,8 @@ export function MentionInputField<
79
79
  _preserveValue,
80
80
  validators,
81
81
  disabled,
82
- _value,
82
+ value,
83
+ onChange,
83
84
  mentions,
84
85
  placeholder,
85
86
  onMentionSelect,
@@ -103,6 +104,8 @@ export function MentionInputField<
103
104
  id={fieldProps.id}
104
105
  size={fieldProps.size}
105
106
  disabled={disabled}
107
+ value={value}
108
+ onChange={onChange}
106
109
  mentions={mentions ?? []}
107
110
  placeholder={placeholder}
108
111
  onMentionSelect={onMentionSelect}
@@ -45,7 +45,7 @@ export type PasswordProps<
45
45
  unknown,
46
46
  string
47
47
  >,
48
- "children" | "field"
48
+ "children" | "field" | "onChange"
49
49
  > &
50
50
  Partial<
51
51
  Omit<
@@ -57,6 +57,15 @@ describe("ProgressField chrome", () => {
57
57
  expect(container.firstElementChild).toBeTruthy();
58
58
  expect(container.textContent).toContain("Completion");
59
59
  });
60
+
61
+ it("forwards the controlled value onto the progressbar", () => {
62
+ const { container } = renderWithProviders(
63
+ <ProgressField label="Completion" value={65} max={100} />,
64
+ );
65
+ expect(container.querySelector("[role='progressbar']")?.getAttribute("aria-valuenow")).toBe(
66
+ "65",
67
+ );
68
+ });
60
69
  });
61
70
 
62
71
  /**
@@ -0,0 +1,93 @@
1
+ /**
2
+ * RadioGroupField contract specs. The adapter maps `onChange` onto the forms
3
+ * RadioGroup's `onValueChange`. Pin that value, onChange, disabled, label
4
+ * and error survive the hop.
5
+ */
6
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
7
+ import { act, cleanup, fireEvent } from "@testing-library/react";
8
+ import type React from "react";
9
+ import { afterEach, describe, expect, it, vi } from "vitest";
10
+ import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
11
+ import { RadioGroupField } from ".";
12
+
13
+ afterEach(cleanup);
14
+
15
+ const options = [
16
+ { label: "Red", value: "red" },
17
+ { label: "Blue", value: "blue" },
18
+ ];
19
+
20
+ const radios = (container: HTMLElement) =>
21
+ Array.from(container.querySelectorAll('[role="radio"]')) as HTMLElement[];
22
+
23
+ describe("RadioGroupField composes the forms RadioGroup", () => {
24
+ it("paints a controlled value onto the matching radio", () => {
25
+ const result = renderWithProviders(
26
+ <RadioGroupField label="Color" value="blue" options={options} onChange={() => {}} />,
27
+ );
28
+ const all = radios(result.container);
29
+ const checked = all.find((el) => el.getAttribute("aria-checked") === "true");
30
+ expect(checked).toBeTruthy();
31
+ // option order is Red, Blue — the disc itself has no text
32
+ expect(checked).toBe(all[1]);
33
+ });
34
+
35
+ it("emits the option value through canonical onChange", async () => {
36
+ const onChange = vi.fn();
37
+ const result = renderWithProviders(
38
+ <RadioGroupField label="Color" value="red" options={options} onChange={onChange} />,
39
+ );
40
+ const blue = radios(result.container).find((el) => (el.textContent || "").includes("Blue"));
41
+ expect(blue || radios(result.container)[1]).toBeTruthy();
42
+ await act(async () => {
43
+ fireEvent.click(blue ?? radios(result.container)[1]);
44
+ });
45
+ expect(onChange).toHaveBeenCalledWith("blue");
46
+ });
47
+
48
+ it("forwards disabled onto the radios", () => {
49
+ const result = renderWithProviders(
50
+ <RadioGroupField label="Color" value="red" options={options} disabled onChange={() => {}} />,
51
+ );
52
+ const el = radios(result.container)[0];
53
+ expect(el?.getAttribute("aria-disabled") === "true" || el?.hasAttribute("disabled")).toBe(true);
54
+ });
55
+
56
+ it("shows the label and error", () => {
57
+ const result = renderWithProviders(
58
+ <RadioGroupField
59
+ label="Color"
60
+ value="red"
61
+ options={options}
62
+ error="pick one"
63
+ onChange={() => {}}
64
+ />,
65
+ );
66
+ expect(result.container.textContent).toContain("Color");
67
+ expect(result.container.textContent).toContain("pick one");
68
+ });
69
+ });
70
+
71
+ describe("registry resolution (Radio fieldtype)", () => {
72
+ function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
73
+ return { value: "", onChange: () => {}, ...overrides };
74
+ }
75
+
76
+ it("resolves 'Radio' to RadioGroupField and splits df.options on newlines", () => {
77
+ const Component = getFieldComponent("Radio")!;
78
+ const element = (Component as Function)(
79
+ propsFor({
80
+ value: "Red",
81
+ label: "Color",
82
+ fieldMeta: { options: "Red\nBlue" },
83
+ } as Partial<FieldRenderProps>),
84
+ ) as React.ReactElement<Record<string, unknown>>;
85
+ expect(element.type).toBe(RadioGroupField);
86
+ expect(element.props.value).toBe("Red");
87
+ expect(element.props.label).toBe("Color");
88
+ expect(element.props.options).toEqual([
89
+ { label: "Red", value: "Red" },
90
+ { label: "Blue", value: "Blue" },
91
+ ]);
92
+ });
93
+ });
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Signature adapter contract specs. The Frappe Signature field stores a
3
+ * data URL; this adapter must hand value / onChange / disabled / label /
4
+ * error to the forms Signature pad. Drawing lives in the forms spec.
5
+ */
6
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
7
+ import { cleanup, fireEvent } from "@testing-library/react";
8
+ import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
9
+ import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
10
+ import type React from "react";
11
+ import { Signature } from ".";
12
+
13
+ function encodeSignature(strokes: number[][][]): string {
14
+ const json = JSON.stringify({ v: 2, s: strokes });
15
+ return `data:application/json;base64,${btoa(json)}`;
16
+ }
17
+
18
+ const inkedValue = encodeSignature([
19
+ [
20
+ [0.1, 0.2, 0.5],
21
+ [0.4, 0.3, 0.5],
22
+ [0.7, 0.25, 0.5],
23
+ ],
24
+ ]);
25
+
26
+ function getPad(container: HTMLElement): HTMLElement {
27
+ const label = container.querySelector("label[for]") as HTMLLabelElement | null;
28
+ const id = label?.htmlFor;
29
+ const pad = id ? (container.querySelector(`#${CSS.escape(id)}`) as HTMLElement | null) : null;
30
+ if (!pad) throw new Error("signature pad not found");
31
+ return pad;
32
+ }
33
+
34
+ beforeAll(() => {
35
+ HTMLCanvasElement.prototype.getContext = vi.fn(() => ({
36
+ clearRect: vi.fn(),
37
+ beginPath: vi.fn(),
38
+ moveTo: vi.fn(),
39
+ lineTo: vi.fn(),
40
+ stroke: vi.fn(),
41
+ fillRect: vi.fn(),
42
+ drawImage: vi.fn(),
43
+ })) as unknown as typeof HTMLCanvasElement.prototype.getContext;
44
+ });
45
+
46
+ afterEach(cleanup);
47
+
48
+ describe("Signature composes the forms Signature", () => {
49
+ it("paints a controlled value as a signed pad", () => {
50
+ const result = renderWithProviders(
51
+ <Signature label="Sign here" value={inkedValue} onChange={() => {}} />,
52
+ );
53
+ expect(getPad(result.container).getAttribute("data-signed")).toBe("true");
54
+ });
55
+
56
+ it("emits an empty string through canonical onChange on Delete", () => {
57
+ const onChange = vi.fn();
58
+ const result = renderWithProviders(
59
+ <Signature label="Sign here" value={inkedValue} onChange={onChange} />,
60
+ );
61
+ const pad = getPad(result.container);
62
+ fireEvent.focus(pad);
63
+ fireEvent.keyDown(pad, { key: "Delete" });
64
+ expect(onChange).toHaveBeenCalledWith("");
65
+ });
66
+
67
+ it("forwards readOnly onto the pad", () => {
68
+ const result = renderWithProviders(
69
+ <Signature label="Sign here" value={inkedValue} readOnly onChange={() => {}} />,
70
+ );
71
+ expect(getPad(result.container).getAttribute("aria-readonly")).toBe("true");
72
+ });
73
+
74
+ it("forwards disabled onto the pad", () => {
75
+ const result = renderWithProviders(
76
+ <Signature label="Sign here" value={inkedValue} disabled onChange={() => {}} />,
77
+ );
78
+ const pad = getPad(result.container);
79
+ expect(pad.getAttribute("aria-disabled") === "true" || pad.hasAttribute("disabled")).toBe(true);
80
+ });
81
+
82
+ it("shows the label and error", () => {
83
+ const result = renderWithProviders(
84
+ <Signature label="Sign here" value="" error="signature required" onChange={() => {}} />,
85
+ );
86
+ expect(result.container.textContent).toContain("Sign here");
87
+ expect(result.container.textContent).toContain("signature required");
88
+ });
89
+ });
90
+
91
+ describe("registry resolution (Signature fieldtype)", () => {
92
+ function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
93
+ return { value: "", onChange: () => {}, ...overrides };
94
+ }
95
+
96
+ it("resolves 'Signature' to the Signature adapter and hands value through", () => {
97
+ const Component = getFieldComponent("Signature")!;
98
+ const element = (Component as Function)(
99
+ propsFor({ value: inkedValue, label: "Sign here" }),
100
+ ) as React.ReactElement<Record<string, unknown>>;
101
+ expect(element.type).toBe(Signature);
102
+ expect(element.props.value).toBe(inkedValue);
103
+ expect(element.props.label).toBe("Sign here");
104
+ });
105
+ });
@@ -0,0 +1,73 @@
1
+ /**
2
+ * SliderField contract specs. The adapter wraps a scalar number as the
3
+ * forms Slider's `[number]` tuple. Pin that value, onChange, disabled,
4
+ * label and error survive the hop.
5
+ */
6
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
7
+ import { cleanup, fireEvent } from "@testing-library/react";
8
+ import type React from "react";
9
+ import { afterEach, describe, expect, it, vi } from "vitest";
10
+ import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
11
+ import { SliderField } from ".";
12
+
13
+ afterEach(cleanup);
14
+
15
+ const thumb = (container: HTMLElement) =>
16
+ container.querySelector('[role="slider"]') as HTMLElement | null;
17
+
18
+ describe("SliderField composes the forms Slider", () => {
19
+ it("paints a controlled value onto the thumb", () => {
20
+ const result = renderWithProviders(
21
+ <SliderField label="Volume" value={40} min={0} max={100} onChange={() => {}} />,
22
+ );
23
+ expect(thumb(result.container)?.getAttribute("aria-valuenow")).toBe("40");
24
+ });
25
+
26
+ it("emits a scalar through canonical onChange", () => {
27
+ const onChange = vi.fn();
28
+ const result = renderWithProviders(
29
+ <SliderField label="Volume" value={40} min={0} max={100} step={1} onChange={onChange} />,
30
+ );
31
+ const el = thumb(result.container) as HTMLElement;
32
+ el.focus();
33
+ fireEvent.keyDown(el, { key: "ArrowRight" });
34
+ expect(onChange).toHaveBeenCalled();
35
+ expect(typeof onChange.mock.calls.at(-1)?.[0]).toBe("number");
36
+ });
37
+
38
+ it("forwards disabled onto the thumb", () => {
39
+ const result = renderWithProviders(
40
+ <SliderField label="Volume" value={40} disabled onChange={() => {}} />,
41
+ );
42
+ const el = thumb(result.container);
43
+ const disabledMarker =
44
+ el?.getAttribute("aria-disabled") === "true" ||
45
+ el?.hasAttribute("data-disabled") ||
46
+ Boolean(el?.closest("[data-disabled]"));
47
+ expect(disabledMarker).toBe(true);
48
+ });
49
+
50
+ it("shows the label and error", () => {
51
+ const result = renderWithProviders(
52
+ <SliderField label="Volume" value={40} error="out of range" onChange={() => {}} />,
53
+ );
54
+ expect(result.container.textContent).toContain("Volume");
55
+ expect(result.container.textContent).toContain("out of range");
56
+ });
57
+ });
58
+
59
+ describe("registry resolution (Slider fieldtype)", () => {
60
+ function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
61
+ return { value: "", onChange: () => {}, ...overrides };
62
+ }
63
+
64
+ it("resolves 'Slider' to SliderField and coerces a non-number to 0", () => {
65
+ const Component = getFieldComponent("Slider")!;
66
+ const element = (Component as Function)(
67
+ propsFor({ value: "nope", label: "Volume" }),
68
+ ) as React.ReactElement<Record<string, unknown>>;
69
+ expect(element.type).toBe(SliderField);
70
+ expect(element.props.value).toBe(0);
71
+ expect(element.props.label).toBe("Volume");
72
+ });
73
+ });
@@ -0,0 +1,65 @@
1
+ /**
2
+ * SwitchField contract specs. Frappe Switch is 1/0 in the doc; this adapter
3
+ * maps that onto the forms Switch's boolean checked/onCheckedChange. Pin
4
+ * that value, onChange, disabled, label and error survive the hop.
5
+ */
6
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
7
+ import { act, cleanup, fireEvent } from "@testing-library/react";
8
+ import type React from "react";
9
+ import { afterEach, describe, expect, it, vi } from "vitest";
10
+ import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
11
+ import { SwitchField } from ".";
12
+
13
+ afterEach(cleanup);
14
+
15
+ describe("SwitchField composes the forms Switch", () => {
16
+ it("paints a controlled true value as aria-checked=true", () => {
17
+ const result = renderWithProviders(
18
+ <SwitchField label="Enabled" value={true} onChange={() => {}} />,
19
+ );
20
+ expect(result.getSwitch()?.getAttribute("aria-checked")).toBe("true");
21
+ });
22
+
23
+ it("emits a boolean through canonical onChange", async () => {
24
+ const onChange = vi.fn();
25
+ const result = renderWithProviders(
26
+ <SwitchField label="Enabled" value={false} onChange={onChange} />,
27
+ );
28
+ await act(async () => {
29
+ fireEvent.click(result.getSwitch() as HTMLElement);
30
+ });
31
+ expect(onChange).toHaveBeenCalledWith(true);
32
+ });
33
+
34
+ it("forwards disabled onto the switch", () => {
35
+ const result = renderWithProviders(
36
+ <SwitchField label="Enabled" value={false} disabled onChange={() => {}} />,
37
+ );
38
+ const el = result.getSwitch();
39
+ expect(el?.hasAttribute("disabled") || el?.getAttribute("aria-disabled") === "true").toBe(true);
40
+ });
41
+
42
+ it("shows the label and error", () => {
43
+ const result = renderWithProviders(
44
+ <SwitchField label="Enabled" value={false} error="cannot enable" onChange={() => {}} />,
45
+ );
46
+ expect(result.container.textContent).toContain("Enabled");
47
+ expect(result.container.textContent).toContain("cannot enable");
48
+ });
49
+ });
50
+
51
+ describe("registry resolution (Switch fieldtype)", () => {
52
+ function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
53
+ return { value: "", onChange: () => {}, ...overrides };
54
+ }
55
+
56
+ it("resolves 'Switch' to SwitchField and maps a truthy doc value to true", () => {
57
+ const Component = getFieldComponent("Switch")!;
58
+ const element = (Component as Function)(
59
+ propsFor({ value: 1, label: "Enabled" }),
60
+ ) as React.ReactElement<Record<string, unknown>>;
61
+ expect(element.type).toBe(SwitchField);
62
+ expect(element.props.value).toBe(true);
63
+ expect(element.props.label).toBe("Enabled");
64
+ });
65
+ });
@@ -51,11 +51,10 @@ describe("TextEditor initialization emissions", () => {
51
51
  await waitFor(() => {
52
52
  expect(utils.container.querySelector(".ProseMirror")).toBeTruthy();
53
53
  });
54
- // House RichTextEditor seeds via initialContent (mount). External HTML
55
- // sync is the house editor's contract, not a forked TipTap in this wrapper.
54
+ // An external update changes the actual document without echoing an edit.
56
55
  utils.rerender(<TextEditor label="Description" value="<p>second</p>" onChange={onChange} />);
57
56
  await waitFor(() => {
58
- expect(utils.container.querySelector(".ProseMirror")).toBeTruthy();
57
+ expect(utils.container.querySelector(".ProseMirror")?.textContent).toBe("second");
59
58
  });
60
59
  expect(onChange).not.toHaveBeenCalled();
61
60
  });
@@ -1,7 +1,8 @@
1
1
  import { action } from "@multiplatform.one/storybook";
2
+ import { Button } from "@multiplatform.one/forms";
2
3
  import { DataTable, type DataTableColumn } from "@multiplatform.one/table";
3
4
  import { useState } from "react";
4
- import { YStack } from "tamagui";
5
+ import { Text, YStack } from "tamagui";
5
6
  import { fieldtypeToTableField } from "../../fieldRegistry";
6
7
  import { FrappeStoryProvider } from "../../frappeStoryTarget";
7
8
  import { TextEditor, type TextEditorProps } from ".";
@@ -51,6 +52,35 @@ Main.args = {
51
52
  } as Partial<StoryProps>;
52
53
  Main.storyName = "Main";
53
54
 
55
+ export const ExternalValueUpdates = {
56
+ name: "External value updates",
57
+ render: function ExternalValueUpdatesStory() {
58
+ const [value, setValue] = useState("<p>Original note</p>");
59
+ const [edits, setEdits] = useState(0);
60
+ return (
61
+ <YStack gap="$3" maxWidth={640}>
62
+ <TextEditor
63
+ label="Note"
64
+ value={value}
65
+ onChange={(next) => {
66
+ setValue(next);
67
+ setEdits((count) => count + 1);
68
+ }}
69
+ />
70
+ <Button
71
+ onPress={() => {
72
+ setEdits(0);
73
+ setValue("<p>Saved note</p>");
74
+ }}
75
+ >
76
+ Load saved note
77
+ </Button>
78
+ <Text testID="editor-user-edits">User edits: {edits}</Text>
79
+ </YStack>
80
+ );
81
+ },
82
+ };
83
+
54
84
  export const Empty = (args: StoryProps) => <Controlled {...args} />;
55
85
  Empty.args = {
56
86
  label: "Empty editor",
@@ -0,0 +1,110 @@
1
+ /**
2
+ * ToggleGroupField contract specs. The adapter maps `onChange` onto the forms
3
+ * ToggleGroup's `onValueChange`. Pin that value, onChange, disabled, label
4
+ * and error survive the hop.
5
+ */
6
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
7
+ import { cleanup, fireEvent } from "@testing-library/react";
8
+ import type React from "react";
9
+ import { afterEach, describe, expect, it, vi } from "vitest";
10
+ import { getFieldComponent, type FieldRenderProps } from "../../fieldRegistry";
11
+ import { ToggleGroupField } from ".";
12
+
13
+ afterEach(cleanup);
14
+
15
+ const options = [
16
+ { label: "Left", value: "left" },
17
+ { label: "Center", value: "center" },
18
+ { label: "Right", value: "right" },
19
+ ];
20
+
21
+ describe("ToggleGroupField composes the forms ToggleGroup", () => {
22
+ it("paints a controlled value onto the matching item", () => {
23
+ const result = renderWithProviders(
24
+ <ToggleGroupField
25
+ label="Align"
26
+ type="single"
27
+ value="center"
28
+ options={options}
29
+ onChange={() => {}}
30
+ />,
31
+ );
32
+ expect(result.container.textContent).toContain("Center");
33
+ const pressed = result.container.querySelector('[aria-pressed="true"], [data-state="on"]');
34
+ expect(pressed).toBeTruthy();
35
+ });
36
+
37
+ it("emits the item value through canonical onChange", () => {
38
+ const onChange = vi.fn();
39
+ const result = renderWithProviders(
40
+ <ToggleGroupField
41
+ label="Align"
42
+ type="single"
43
+ value="left"
44
+ options={options}
45
+ onChange={onChange}
46
+ />,
47
+ );
48
+ const center = result.findTextElement("Center");
49
+ expect(center).toBeTruthy();
50
+ fireEvent.click(center as HTMLElement);
51
+ expect(onChange).toHaveBeenCalledWith("center");
52
+ });
53
+
54
+ it("forwards disabled onto the group", () => {
55
+ const result = renderWithProviders(
56
+ <ToggleGroupField
57
+ label="Align"
58
+ type="single"
59
+ value="left"
60
+ options={options}
61
+ disabled
62
+ onChange={() => {}}
63
+ />,
64
+ );
65
+ const el =
66
+ result.container.querySelector('[role="group"]') ||
67
+ result.container.querySelector('[data-disabled="true"]') ||
68
+ result.container.querySelector("[disabled]");
69
+ expect(el).toBeTruthy();
70
+ });
71
+
72
+ it("shows the label and error", () => {
73
+ const result = renderWithProviders(
74
+ <ToggleGroupField
75
+ label="Align"
76
+ type="single"
77
+ value="left"
78
+ options={options}
79
+ error="pick a side"
80
+ onChange={() => {}}
81
+ />,
82
+ );
83
+ expect(result.container.textContent).toContain("Align");
84
+ expect(result.container.textContent).toContain("pick a side");
85
+ });
86
+ });
87
+
88
+ describe("registry resolution (Toggle Group fieldtype)", () => {
89
+ function propsFor(overrides: Partial<FieldRenderProps> = {}): FieldRenderProps {
90
+ return { value: "", onChange: () => {}, ...overrides };
91
+ }
92
+
93
+ it("resolves 'Toggle Group' to ToggleGroupField and splits df.options on newlines", () => {
94
+ const Component = getFieldComponent("Toggle Group")!;
95
+ const element = (Component as Function)(
96
+ propsFor({
97
+ value: "Left",
98
+ label: "Align",
99
+ fieldMeta: { options: "Left\nCenter" },
100
+ } as Partial<FieldRenderProps>),
101
+ ) as React.ReactElement<Record<string, unknown>>;
102
+ expect(element.type).toBe(ToggleGroupField);
103
+ expect(element.props.value).toBe("Left");
104
+ expect(element.props.label).toBe("Align");
105
+ expect(element.props.options).toEqual([
106
+ { label: "Left", value: "Left" },
107
+ { label: "Center", value: "Center" },
108
+ ]);
109
+ });
110
+ });