@multiplatform.one/table 7.10.0 → 7.15.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 (307) hide show
  1. package/README.md +61 -1
  2. package/dist/cjs/components/ChildTable/index.cjs +8 -2
  3. package/dist/cjs/components/ChildTable/index.native.js +8 -2
  4. package/dist/cjs/components/ChildTable/index.native.js.map +1 -1
  5. package/dist/cjs/components/ColumnHeaderFilter/index.cjs +77 -111
  6. package/dist/cjs/components/ColumnHeaderFilter/index.native.js +89 -129
  7. package/dist/cjs/components/ColumnHeaderFilter/index.native.js.map +1 -1
  8. package/dist/cjs/components/DataTable/DataTableCardControls.cjs +90 -54
  9. package/dist/cjs/components/DataTable/DataTableCardControls.native.js +93 -56
  10. package/dist/cjs/components/DataTable/DataTableCardControls.native.js.map +1 -1
  11. package/dist/cjs/components/DataTable/DataTableRoot.cjs +68 -9
  12. package/dist/cjs/components/DataTable/DataTableRoot.native.js +78 -11
  13. package/dist/cjs/components/DataTable/DataTableRoot.native.js.map +1 -1
  14. package/dist/cjs/components/DataTableCell/CellModalEditor.cjs +72 -70
  15. package/dist/cjs/components/DataTableCell/index.cjs +2 -2
  16. package/dist/cjs/components/DataTableCell/index.native.js +2 -11
  17. package/dist/cjs/components/DataTableCell/index.native.js.map +1 -1
  18. package/dist/cjs/components/DataTableDateFilter/index.cjs +135 -158
  19. package/dist/cjs/components/DataTableDateFilter/index.native.js +153 -183
  20. package/dist/cjs/components/DataTableDateFilter/index.native.js.map +1 -1
  21. package/dist/cjs/components/DataTableExport/index.cjs +122 -139
  22. package/dist/cjs/components/DataTableExport/index.native.js +135 -157
  23. package/dist/cjs/components/DataTableExport/index.native.js.map +1 -1
  24. package/dist/cjs/components/DataTableFilterButton/index.cjs +14 -0
  25. package/dist/cjs/components/DataTableFilterButton/index.native.js +15 -0
  26. package/dist/cjs/components/DataTableFilterButton/index.native.js.map +1 -1
  27. package/dist/cjs/components/DataTableGrouping/index.cjs +192 -212
  28. package/dist/cjs/components/DataTableGrouping/index.native.js +209 -230
  29. package/dist/cjs/components/DataTableGrouping/index.native.js.map +1 -1
  30. package/dist/cjs/components/DataTableSearch/index.cjs +103 -115
  31. package/dist/cjs/components/DataTableSearch/index.native.js +111 -123
  32. package/dist/cjs/components/DataTableSearch/index.native.js.map +1 -1
  33. package/dist/cjs/components/DataTableToolbar/index.cjs +161 -101
  34. package/dist/cjs/components/DataTableToolbar/index.native.js +168 -109
  35. package/dist/cjs/components/DataTableToolbar/index.native.js.map +1 -1
  36. package/dist/cjs/components/DataTableViewOptions/index.cjs +38 -54
  37. package/dist/cjs/components/DataTableViewOptions/index.native.js +40 -56
  38. package/dist/cjs/components/DataTableViewOptions/index.native.js.map +1 -1
  39. package/dist/cjs/components/FilterOperatorValueEditor/index.cjs +3 -11
  40. package/dist/cjs/components/FilterOperatorValueEditor/index.native.js +3 -11
  41. package/dist/cjs/components/FilterOperatorValueEditor/index.native.js.map +1 -1
  42. package/dist/cjs/components/SimpleTable/index.cjs +2 -6
  43. package/dist/cjs/components/SimpleTable/index.native.js +2 -6
  44. package/dist/cjs/components/SimpleTable/index.native.js.map +1 -1
  45. package/dist/cjs/components/TableInput/RowDetailEditor.cjs +190 -0
  46. package/dist/cjs/components/TableInput/RowDetailEditor.native.js +172 -0
  47. package/dist/cjs/components/TableInput/RowDetailEditor.native.js.map +1 -0
  48. package/dist/cjs/components/TableInput/index.cjs +42 -5
  49. package/dist/cjs/components/TableInput/index.native.js +64 -1
  50. package/dist/cjs/components/TableInput/index.native.js.map +1 -1
  51. package/dist/cjs/components/TableInput/shared.cjs +8 -0
  52. package/dist/cjs/components/TableInput/shared.native.js +10 -0
  53. package/dist/cjs/components/TableInput/shared.native.js.map +1 -1
  54. package/dist/cjs/hooks/useDataTable.cjs +43 -2
  55. package/dist/cjs/hooks/useDataTable.native.js +49 -3
  56. package/dist/cjs/hooks/useDataTable.native.js.map +1 -1
  57. package/dist/cjs/index.native.js.map +1 -1
  58. package/dist/cjs/utils/rowPress.cjs +4 -1
  59. package/dist/cjs/utils/rowPress.native.js +4 -1
  60. package/dist/cjs/utils/rowPress.native.js.map +1 -1
  61. package/dist/esm/components/ChildTable/index.mjs +8 -2
  62. package/dist/esm/components/ChildTable/index.mjs.map +1 -1
  63. package/dist/esm/components/ChildTable/index.native.js +8 -2
  64. package/dist/esm/components/ChildTable/index.native.js.map +1 -1
  65. package/dist/esm/components/ColumnHeaderFilter/index.mjs +80 -114
  66. package/dist/esm/components/ColumnHeaderFilter/index.mjs.map +1 -1
  67. package/dist/esm/components/ColumnHeaderFilter/index.native.js +92 -132
  68. package/dist/esm/components/ColumnHeaderFilter/index.native.js.map +1 -1
  69. package/dist/esm/components/DataTable/DataTableCardControls.mjs +89 -54
  70. package/dist/esm/components/DataTable/DataTableCardControls.mjs.map +1 -1
  71. package/dist/esm/components/DataTable/DataTableCardControls.native.js +92 -56
  72. package/dist/esm/components/DataTable/DataTableCardControls.native.js.map +1 -1
  73. package/dist/esm/components/DataTable/DataTableRoot.mjs +70 -11
  74. package/dist/esm/components/DataTable/DataTableRoot.mjs.map +1 -1
  75. package/dist/esm/components/DataTable/DataTableRoot.native.js +80 -13
  76. package/dist/esm/components/DataTable/DataTableRoot.native.js.map +1 -1
  77. package/dist/esm/components/DataTableCell/CellModalEditor.mjs +76 -74
  78. package/dist/esm/components/DataTableCell/CellModalEditor.mjs.map +1 -1
  79. package/dist/esm/components/DataTableCell/index.mjs +3 -3
  80. package/dist/esm/components/DataTableCell/index.mjs.map +1 -1
  81. package/dist/esm/components/DataTableCell/index.native.js +3 -12
  82. package/dist/esm/components/DataTableCell/index.native.js.map +1 -1
  83. package/dist/esm/components/DataTableDateFilter/index.mjs +137 -160
  84. package/dist/esm/components/DataTableDateFilter/index.mjs.map +1 -1
  85. package/dist/esm/components/DataTableDateFilter/index.native.js +155 -185
  86. package/dist/esm/components/DataTableDateFilter/index.native.js.map +1 -1
  87. package/dist/esm/components/DataTableExport/index.mjs +124 -141
  88. package/dist/esm/components/DataTableExport/index.mjs.map +1 -1
  89. package/dist/esm/components/DataTableExport/index.native.js +137 -159
  90. package/dist/esm/components/DataTableExport/index.native.js.map +1 -1
  91. package/dist/esm/components/DataTableFilterButton/index.mjs +14 -1
  92. package/dist/esm/components/DataTableFilterButton/index.mjs.map +1 -1
  93. package/dist/esm/components/DataTableFilterButton/index.native.js +15 -1
  94. package/dist/esm/components/DataTableFilterButton/index.native.js.map +1 -1
  95. package/dist/esm/components/DataTableGrouping/index.mjs +194 -214
  96. package/dist/esm/components/DataTableGrouping/index.mjs.map +1 -1
  97. package/dist/esm/components/DataTableGrouping/index.native.js +211 -232
  98. package/dist/esm/components/DataTableGrouping/index.native.js.map +1 -1
  99. package/dist/esm/components/DataTableSearch/index.mjs +105 -117
  100. package/dist/esm/components/DataTableSearch/index.mjs.map +1 -1
  101. package/dist/esm/components/DataTableSearch/index.native.js +113 -125
  102. package/dist/esm/components/DataTableSearch/index.native.js.map +1 -1
  103. package/dist/esm/components/DataTableToolbar/index.mjs +165 -106
  104. package/dist/esm/components/DataTableToolbar/index.mjs.map +1 -1
  105. package/dist/esm/components/DataTableToolbar/index.native.js +172 -114
  106. package/dist/esm/components/DataTableToolbar/index.native.js.map +1 -1
  107. package/dist/esm/components/DataTableViewOptions/index.mjs +40 -56
  108. package/dist/esm/components/DataTableViewOptions/index.mjs.map +1 -1
  109. package/dist/esm/components/DataTableViewOptions/index.native.js +42 -58
  110. package/dist/esm/components/DataTableViewOptions/index.native.js.map +1 -1
  111. package/dist/esm/components/FilterOperatorValueEditor/index.mjs +3 -11
  112. package/dist/esm/components/FilterOperatorValueEditor/index.mjs.map +1 -1
  113. package/dist/esm/components/FilterOperatorValueEditor/index.native.js +3 -11
  114. package/dist/esm/components/FilterOperatorValueEditor/index.native.js.map +1 -1
  115. package/dist/esm/components/SimpleTable/index.mjs +3 -7
  116. package/dist/esm/components/SimpleTable/index.mjs.map +1 -1
  117. package/dist/esm/components/SimpleTable/index.native.js +3 -7
  118. package/dist/esm/components/SimpleTable/index.native.js.map +1 -1
  119. package/dist/esm/components/TableInput/RowDetailEditor.mjs +165 -0
  120. package/dist/esm/components/TableInput/RowDetailEditor.mjs.map +1 -0
  121. package/dist/esm/components/TableInput/RowDetailEditor.native.js +144 -0
  122. package/dist/esm/components/TableInput/RowDetailEditor.native.js.map +1 -0
  123. package/dist/esm/components/TableInput/index.mjs +42 -5
  124. package/dist/esm/components/TableInput/index.mjs.map +1 -1
  125. package/dist/esm/components/TableInput/index.native.js +64 -1
  126. package/dist/esm/components/TableInput/index.native.js.map +1 -1
  127. package/dist/esm/components/TableInput/shared.mjs +7 -1
  128. package/dist/esm/components/TableInput/shared.mjs.map +1 -1
  129. package/dist/esm/components/TableInput/shared.native.js +9 -1
  130. package/dist/esm/components/TableInput/shared.native.js.map +1 -1
  131. package/dist/esm/hooks/useDataTable.mjs +43 -2
  132. package/dist/esm/hooks/useDataTable.mjs.map +1 -1
  133. package/dist/esm/hooks/useDataTable.native.js +49 -3
  134. package/dist/esm/hooks/useDataTable.native.js.map +1 -1
  135. package/dist/esm/index.mjs.map +1 -1
  136. package/dist/esm/index.native.js.map +1 -1
  137. package/dist/esm/utils/rowPress.mjs +4 -1
  138. package/dist/esm/utils/rowPress.mjs.map +1 -1
  139. package/dist/esm/utils/rowPress.native.js +4 -1
  140. package/dist/esm/utils/rowPress.native.js.map +1 -1
  141. package/dist/jsx/components/ChildTable/index.mjs +8 -2
  142. package/dist/jsx/components/ChildTable/index.mjs.map +1 -1
  143. package/dist/jsx/components/ChildTable/index.native.js +8 -2
  144. package/dist/jsx/components/ChildTable/index.native.js.map +1 -1
  145. package/dist/jsx/components/ColumnHeaderFilter/index.mjs +80 -114
  146. package/dist/jsx/components/ColumnHeaderFilter/index.mjs.map +1 -1
  147. package/dist/jsx/components/ColumnHeaderFilter/index.native.js +89 -129
  148. package/dist/jsx/components/ColumnHeaderFilter/index.native.js.map +1 -1
  149. package/dist/jsx/components/DataTable/DataTableCardControls.mjs +89 -54
  150. package/dist/jsx/components/DataTable/DataTableCardControls.mjs.map +1 -1
  151. package/dist/jsx/components/DataTable/DataTableCardControls.native.js +93 -56
  152. package/dist/jsx/components/DataTable/DataTableCardControls.native.js.map +1 -1
  153. package/dist/jsx/components/DataTable/DataTableRoot.mjs +70 -11
  154. package/dist/jsx/components/DataTable/DataTableRoot.mjs.map +1 -1
  155. package/dist/jsx/components/DataTable/DataTableRoot.native.js +78 -11
  156. package/dist/jsx/components/DataTable/DataTableRoot.native.js.map +1 -1
  157. package/dist/jsx/components/DataTableCell/CellModalEditor.mjs +76 -74
  158. package/dist/jsx/components/DataTableCell/CellModalEditor.mjs.map +1 -1
  159. package/dist/jsx/components/DataTableCell/index.mjs +3 -3
  160. package/dist/jsx/components/DataTableCell/index.mjs.map +1 -1
  161. package/dist/jsx/components/DataTableCell/index.native.js +2 -11
  162. package/dist/jsx/components/DataTableCell/index.native.js.map +1 -1
  163. package/dist/jsx/components/DataTableDateFilter/index.mjs +137 -160
  164. package/dist/jsx/components/DataTableDateFilter/index.mjs.map +1 -1
  165. package/dist/jsx/components/DataTableDateFilter/index.native.js +153 -183
  166. package/dist/jsx/components/DataTableDateFilter/index.native.js.map +1 -1
  167. package/dist/jsx/components/DataTableExport/index.mjs +124 -141
  168. package/dist/jsx/components/DataTableExport/index.mjs.map +1 -1
  169. package/dist/jsx/components/DataTableExport/index.native.js +135 -157
  170. package/dist/jsx/components/DataTableExport/index.native.js.map +1 -1
  171. package/dist/jsx/components/DataTableFilterButton/index.mjs +14 -1
  172. package/dist/jsx/components/DataTableFilterButton/index.mjs.map +1 -1
  173. package/dist/jsx/components/DataTableFilterButton/index.native.js +15 -0
  174. package/dist/jsx/components/DataTableFilterButton/index.native.js.map +1 -1
  175. package/dist/jsx/components/DataTableGrouping/index.mjs +194 -214
  176. package/dist/jsx/components/DataTableGrouping/index.mjs.map +1 -1
  177. package/dist/jsx/components/DataTableGrouping/index.native.js +209 -230
  178. package/dist/jsx/components/DataTableGrouping/index.native.js.map +1 -1
  179. package/dist/jsx/components/DataTableSearch/index.mjs +105 -117
  180. package/dist/jsx/components/DataTableSearch/index.mjs.map +1 -1
  181. package/dist/jsx/components/DataTableSearch/index.native.js +111 -123
  182. package/dist/jsx/components/DataTableSearch/index.native.js.map +1 -1
  183. package/dist/jsx/components/DataTableToolbar/index.mjs +165 -106
  184. package/dist/jsx/components/DataTableToolbar/index.mjs.map +1 -1
  185. package/dist/jsx/components/DataTableToolbar/index.native.js +168 -109
  186. package/dist/jsx/components/DataTableToolbar/index.native.js.map +1 -1
  187. package/dist/jsx/components/DataTableViewOptions/index.mjs +40 -56
  188. package/dist/jsx/components/DataTableViewOptions/index.mjs.map +1 -1
  189. package/dist/jsx/components/DataTableViewOptions/index.native.js +40 -56
  190. package/dist/jsx/components/DataTableViewOptions/index.native.js.map +1 -1
  191. package/dist/jsx/components/FilterOperatorValueEditor/index.mjs +3 -11
  192. package/dist/jsx/components/FilterOperatorValueEditor/index.mjs.map +1 -1
  193. package/dist/jsx/components/FilterOperatorValueEditor/index.native.js +3 -11
  194. package/dist/jsx/components/FilterOperatorValueEditor/index.native.js.map +1 -1
  195. package/dist/jsx/components/SimpleTable/index.mjs +3 -7
  196. package/dist/jsx/components/SimpleTable/index.mjs.map +1 -1
  197. package/dist/jsx/components/SimpleTable/index.native.js +2 -6
  198. package/dist/jsx/components/SimpleTable/index.native.js.map +1 -1
  199. package/dist/jsx/components/TableInput/RowDetailEditor.mjs +165 -0
  200. package/dist/jsx/components/TableInput/RowDetailEditor.mjs.map +1 -0
  201. package/dist/jsx/components/TableInput/RowDetailEditor.native.js +172 -0
  202. package/dist/jsx/components/TableInput/RowDetailEditor.native.js.map +1 -0
  203. package/dist/jsx/components/TableInput/index.mjs +42 -5
  204. package/dist/jsx/components/TableInput/index.mjs.map +1 -1
  205. package/dist/jsx/components/TableInput/index.native.js +64 -1
  206. package/dist/jsx/components/TableInput/index.native.js.map +1 -1
  207. package/dist/jsx/components/TableInput/shared.mjs +7 -1
  208. package/dist/jsx/components/TableInput/shared.mjs.map +1 -1
  209. package/dist/jsx/components/TableInput/shared.native.js +10 -0
  210. package/dist/jsx/components/TableInput/shared.native.js.map +1 -1
  211. package/dist/jsx/hooks/useDataTable.mjs +43 -2
  212. package/dist/jsx/hooks/useDataTable.mjs.map +1 -1
  213. package/dist/jsx/hooks/useDataTable.native.js +49 -3
  214. package/dist/jsx/hooks/useDataTable.native.js.map +1 -1
  215. package/dist/jsx/index.js.map +1 -1
  216. package/dist/jsx/index.mjs.map +1 -1
  217. package/dist/jsx/index.native.js.map +1 -1
  218. package/dist/jsx/utils/rowPress.mjs +4 -1
  219. package/dist/jsx/utils/rowPress.mjs.map +1 -1
  220. package/dist/jsx/utils/rowPress.native.js +4 -1
  221. package/dist/jsx/utils/rowPress.native.js.map +1 -1
  222. package/package.json +16 -16
  223. package/src/components/ChildTable/childTable.cellHidden.spec.tsx +57 -0
  224. package/src/components/ChildTable/childTable.rowDetail.spec.tsx +120 -0
  225. package/src/components/ChildTable/index.tsx +16 -0
  226. package/src/components/ColumnHeaderFilter/index.tsx +89 -116
  227. package/src/components/DataTable/DataTable.stories.tsx +130 -6
  228. package/src/components/DataTable/DataTableCardControls.stories.tsx +61 -2
  229. package/src/components/DataTable/DataTableCardControls.tsx +92 -66
  230. package/src/components/DataTable/DataTableRoot.tsx +109 -18
  231. package/src/components/DataTable/cardLayout.spec.tsx +4 -3
  232. package/src/components/DataTable/cardToolbar.spec.tsx +238 -0
  233. package/src/components/DataTable/chromeInterplay.spec.tsx +7 -5
  234. package/src/components/DataTable/columnWidthLayout.spec.tsx +189 -0
  235. package/src/components/DataTable/dataTableCardControls.spec.tsx +3 -2
  236. package/src/components/DataTable/dataTableMobileCards.spec.tsx +1 -4
  237. package/src/components/DataTable/footerLayout.spec.tsx +250 -0
  238. package/src/components/DataTable/headerContainment.spec.tsx +91 -0
  239. package/src/components/DataTable/pinningGeometry.spec.tsx +66 -1
  240. package/src/components/DataTable/rowPress.spec.tsx +2 -6
  241. package/src/components/DataTableBulkActions/DataTableBulkActions.stories.tsx +5 -4
  242. package/src/components/DataTableCell/CellModalEditor.tsx +95 -75
  243. package/src/components/DataTableCell/cellDraftPolicy.spec.tsx +12 -2
  244. package/src/components/DataTableCell/cellModalEditor.spec.tsx +75 -49
  245. package/src/components/DataTableCell/dataTableCell.spec.tsx +31 -14
  246. package/src/components/DataTableCell/index.tsx +3 -2
  247. package/src/components/DataTableDateFilter/DataTableDateFilter.spec.tsx +6 -3
  248. package/src/components/DataTableDateFilter/index.tsx +151 -180
  249. package/src/components/DataTableExport/DataTableExport.spec.tsx +42 -18
  250. package/src/components/DataTableExport/index.tsx +135 -142
  251. package/src/components/DataTableFilterButton/index.tsx +9 -0
  252. package/src/components/DataTableGrouping/index.tsx +193 -195
  253. package/src/components/DataTableSearch/index.tsx +111 -109
  254. package/src/components/DataTableToolbar/index.tsx +179 -107
  255. package/src/components/DataTableViewOptions/DataTableViewOptions.stories.tsx +52 -0
  256. package/src/components/DataTableViewOptions/index.tsx +32 -40
  257. package/src/components/FilterOperatorValueEditor/FilterOperatorValueEditor.spec.tsx +64 -2
  258. package/src/components/FilterOperatorValueEditor/index.tsx +0 -8
  259. package/src/components/SimpleTable/index.tsx +3 -2
  260. package/src/components/SimpleTable/simpleTable.spec.tsx +15 -0
  261. package/src/components/Table/accessibility.spec.tsx +7 -19
  262. package/src/components/TableInput/RowDetailEditor.native.tsx +134 -0
  263. package/src/components/TableInput/RowDetailEditor.tsx +173 -0
  264. package/src/components/TableInput/index.native.tsx +49 -1
  265. package/src/components/TableInput/index.tsx +65 -10
  266. package/src/components/TableInput/shared.ts +29 -0
  267. package/src/components/tableDropdowns.spec.tsx +172 -0
  268. package/src/hooks/useDataTable.spec.ts +153 -0
  269. package/src/hooks/useDataTable.ts +38 -2
  270. package/src/index.ts +1 -0
  271. package/src/types.ts +14 -12
  272. package/src/utils/rowPress.ts +3 -0
  273. package/types/components/ChildTable/index.d.ts +10 -0
  274. package/types/components/ChildTable/index.d.ts.map +1 -1
  275. package/types/components/ColumnHeaderFilter/index.d.ts +1 -1
  276. package/types/components/ColumnHeaderFilter/index.d.ts.map +1 -1
  277. package/types/components/DataTable/DataTableCardControls.d.ts +3 -0
  278. package/types/components/DataTable/DataTableCardControls.d.ts.map +1 -1
  279. package/types/components/DataTable/DataTableRoot.d.ts.map +1 -1
  280. package/types/components/DataTableCell/CellModalEditor.d.ts +10 -7
  281. package/types/components/DataTableCell/CellModalEditor.d.ts.map +1 -1
  282. package/types/components/DataTableCell/index.d.ts.map +1 -1
  283. package/types/components/DataTableDateFilter/index.d.ts.map +1 -1
  284. package/types/components/DataTableFilterButton/index.d.ts +2 -1
  285. package/types/components/DataTableFilterButton/index.d.ts.map +1 -1
  286. package/types/components/DataTableGrouping/index.d.ts.map +1 -1
  287. package/types/components/DataTableSearch/index.d.ts.map +1 -1
  288. package/types/components/DataTableToolbar/index.d.ts +1 -0
  289. package/types/components/DataTableToolbar/index.d.ts.map +1 -1
  290. package/types/components/FilterOperatorValueEditor/index.d.ts.map +1 -1
  291. package/types/components/SimpleTable/index.d.ts.map +1 -1
  292. package/types/components/TableInput/RowDetailEditor.d.ts +24 -0
  293. package/types/components/TableInput/RowDetailEditor.d.ts.map +1 -0
  294. package/types/components/TableInput/RowDetailEditor.native.d.ts +11 -0
  295. package/types/components/TableInput/RowDetailEditor.native.d.ts.map +1 -0
  296. package/types/components/TableInput/index.d.ts +11 -2
  297. package/types/components/TableInput/index.d.ts.map +1 -1
  298. package/types/components/TableInput/index.native.d.ts +8 -1
  299. package/types/components/TableInput/index.native.d.ts.map +1 -1
  300. package/types/components/TableInput/shared.d.ts +11 -0
  301. package/types/components/TableInput/shared.d.ts.map +1 -1
  302. package/types/hooks/useDataTable.d.ts.map +1 -1
  303. package/types/index.d.ts +1 -0
  304. package/types/index.d.ts.map +1 -1
  305. package/types/types.d.ts +14 -12
  306. package/types/types.d.ts.map +1 -1
  307. package/types/utils/rowPress.d.ts.map +1 -1
@@ -7,9 +7,9 @@ import {
7
7
  } from "@phosphor-icons/react";
8
8
  import { getGroupPosition, stackRadiusProps, useResolvedKnobs } from "@multiplatform.one/theme";
9
9
  import React, { useState } from "react";
10
- import { Button, Input, Slider, Switch } from "@multiplatform.one/forms";
10
+ import { Button, FloatingPanel, Input, Slider, Switch } from "@multiplatform.one/forms";
11
11
  import { DropdownMenu } from "@multiplatform.one/components";
12
- import { Popover, ScrollView, Separator, Text, View, XStack, YStack, useTheme } from "tamagui";
12
+ import { ScrollView, Separator, Text, View, XStack, YStack, useTheme } from "tamagui";
13
13
  import type { TableView } from "../../types";
14
14
  import { t } from "../../shared/t";
15
15
  import { iconSizeForToken } from "../../utils/chromeIcons";
@@ -415,47 +415,39 @@ function ViewManagementSection({
415
415
  </Text>
416
416
 
417
417
  {/* Save Current View */}
418
- <Popover open={showSaveDialog} onOpenChange={setShowSaveDialog}>
419
- <Popover.Trigger asChild>
418
+ <FloatingPanel
419
+ open={showSaveDialog}
420
+ onOpenChange={setShowSaveDialog}
421
+ trigger={
420
422
  <Button size={knobProps.sizeToken} icon={<FloppyDiskIcon size={iconPx} />}>
421
423
  {t("Save Current View")}
422
424
  </Button>
423
- </Popover.Trigger>
424
- <Popover.Content
425
- {...knobProps.elevatedSurface}
426
- enterStyle={{ x: 0, y: -10, opacity: 0 }}
427
- exitStyle={{ x: 0, y: -10, opacity: 0 }}
428
- transition={knobProps.transition}
429
- >
430
- <YStack {...knobProps.panelPadding} gap="$3" minWidth={250}>
431
- <Text {...knobProps.label} fontWeight="400">
432
- {t("Save View")}
433
- </Text>
434
- <Input
435
- placeholder={t("Enter view name...")}
436
- value={viewName}
437
- onChangeText={setViewName}
438
- inputProps={{
439
- onKeyDown: (e: React.KeyboardEvent) => {
440
- if (e.key === "Enter" && viewName.trim()) handleSaveView();
441
- },
442
- }}
443
- />
444
- <XStack gap="$2" justifyContent="flex-end">
445
- <Button size={knobProps.sizeToken} onPress={() => setShowSaveDialog(false)}>
446
- {t("Cancel")}
447
- </Button>
448
- <Button
449
- size={knobProps.sizeToken}
450
- onPress={handleSaveView}
451
- disabled={!viewName.trim()}
452
- >
453
- {t("Save")}
454
- </Button>
455
- </XStack>
456
- </YStack>
457
- </Popover.Content>
458
- </Popover>
425
+ }
426
+ >
427
+ <YStack gap="$3" minWidth={250} data-dismiss-class="compose">
428
+ <Text {...knobProps.label} fontWeight="400">
429
+ {t("Save View")}
430
+ </Text>
431
+ <Input
432
+ placeholder={t("Enter view name...")}
433
+ value={viewName}
434
+ onChangeText={setViewName}
435
+ inputProps={{
436
+ onKeyDown: (e: React.KeyboardEvent) => {
437
+ if (e.key === "Enter" && viewName.trim()) handleSaveView();
438
+ },
439
+ }}
440
+ />
441
+ <XStack gap="$2" justifyContent="flex-end">
442
+ <Button size={knobProps.sizeToken} onPress={() => setShowSaveDialog(false)}>
443
+ {t("Cancel")}
444
+ </Button>
445
+ <Button size={knobProps.sizeToken} onPress={handleSaveView} disabled={!viewName.trim()}>
446
+ {t("Save")}
447
+ </Button>
448
+ </XStack>
449
+ </YStack>
450
+ </FloatingPanel>
459
451
 
460
452
  {/* Saved Views List */}
461
453
  {views.length > 0 && (
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { fireEvent, screen, waitFor } from "@testing-library/react";
9
9
  import { renderWithProviders } from "@multiplatform.one/test-utils";
10
+ import { type Knobs, Preset } from "@multiplatform.one/theme";
10
11
  import React, { useState } from "react";
11
12
  import { describe, expect, it, vi } from "vitest";
12
13
  import type { DataTableColumnType, FilterOperator } from "../../types";
@@ -28,14 +29,16 @@ const selectTriggers = (container: HTMLElement) =>
28
29
  const textInputs = (container: HTMLElement) =>
29
30
  Array.from(container.querySelectorAll("input")) as HTMLInputElement[];
30
31
 
32
+ /** The listbox portals out to the page (MPO-335, LC-90), so options are read from it. */
31
33
  async function openSelect(container: HTMLElement, trigger: HTMLElement) {
34
+ const page = container.ownerDocument.body;
32
35
  fireEvent.pointerDown(trigger);
33
36
  fireEvent.mouseDown(trigger);
34
37
  fireEvent.click(trigger);
35
38
  await waitFor(() => {
36
- expect(container.querySelectorAll('[role="option"]').length).toBeGreaterThan(0);
39
+ expect(page.querySelectorAll('[role="option"]').length).toBeGreaterThan(0);
37
40
  });
38
- return Array.from(container.querySelectorAll('[role="option"]')) as HTMLElement[];
41
+ return Array.from(page.querySelectorAll('[role="option"]')) as HTMLElement[];
39
42
  }
40
43
 
41
44
  /**
@@ -258,4 +261,63 @@ describe("FilterOperatorValueEditor", () => {
258
261
  await waitFor(() => expect(onValue).toHaveBeenLastCalledWith("in-progress"));
259
262
  });
260
263
  });
264
+ describe("knob laws (MPO-118)", () => {
265
+ const valueBox = (container: HTMLElement) =>
266
+ container.querySelector("[data-mp-input-field='true']") as HTMLElement;
267
+
268
+ const padX = (el: Element) =>
269
+ String((el as HTMLElement).className || "")
270
+ .split(" ")
271
+ .filter((c) => c.startsWith("_px-") || c.startsWith("_pl-") || c.startsWith("_pr-"))
272
+ .sort();
273
+
274
+ function renderAtKnobs(overrides: Partial<Knobs>) {
275
+ return renderWithProviders(
276
+ <Preset overrides={overrides}>
277
+ <FilterOperatorValueEditor
278
+ fieldType="text"
279
+ operator="contains"
280
+ value=""
281
+ onOperatorChange={vi.fn()}
282
+ onValueChange={vi.fn()}
283
+ />
284
+ </Preset>,
285
+ );
286
+ }
287
+
288
+ it("size small: Condition and Value both paint the small recipe", () => {
289
+ const { container } = renderAtKnobs({ size: "small" });
290
+ const box = valueBox(container);
291
+ expect(box.getAttribute("data-size")).toBe("$3");
292
+ expect(box.getAttribute("data-visual-height")).toBe("36");
293
+ expect(selectTriggers(container)[0].getAttribute("data-visual-height")).toBe("36");
294
+ });
295
+
296
+ it("size large: the Value input follows the knob instead of a pinned $3", () => {
297
+ const { container } = renderAtKnobs({ size: "large" });
298
+ const box = valueBox(container);
299
+ expect(box.getAttribute("data-size")).toBe("$5");
300
+ expect(box.getAttribute("data-visual-height")).toBe("52");
301
+ expect(selectTriggers(container)[0].getAttribute("data-visual-height")).toBe("52");
302
+ });
303
+
304
+ it("density comfortable: compact is not forced on the inner fields", () => {
305
+ const { container } = renderAtKnobs({ density: "comfortable" });
306
+ expect(valueBox(container).getAttribute("data-density")).toBe("comfortable");
307
+ });
308
+
309
+ it("density compact: the inner fields step with the density knob and keep their height", () => {
310
+ const comfortable = renderAtKnobs({ density: "comfortable", size: "medium" });
311
+ const comfortablePad = padX(selectTriggers(comfortable.container)[0]);
312
+ const comfortableHeight = valueBox(comfortable.container).getAttribute("data-visual-height");
313
+ comfortable.unmount();
314
+
315
+ const { container } = renderAtKnobs({ density: "compact", size: "medium" });
316
+ const box = valueBox(container);
317
+ expect(box.getAttribute("data-density")).toBe("compact");
318
+ expect(box.getAttribute("data-visual-height")).toBe(comfortableHeight);
319
+ expect(comfortablePad.length).toBeGreaterThan(0);
320
+ expect(padX(selectTriggers(container)[0])).not.toEqual(comfortablePad);
321
+ });
322
+ });
261
323
  });
@@ -72,8 +72,6 @@ export function FilterOperatorValueEditor({
72
72
  }
73
73
  }}
74
74
  options={operatorOptions}
75
- size="$3"
76
- compact
77
75
  />
78
76
 
79
77
  {needsValueInput && (
@@ -89,8 +87,6 @@ export function FilterOperatorValueEditor({
89
87
  }}
90
88
  options={booleanOptions}
91
89
  placeholder={t("Select...")}
92
- size="$3"
93
- compact
94
90
  />
95
91
  ) : fieldType === "select" && options ? (
96
92
  <Select
@@ -103,8 +99,6 @@ export function FilterOperatorValueEditor({
103
99
  }}
104
100
  options={selectOptions}
105
101
  placeholder={t("Select...")}
106
- size="$3"
107
- compact
108
102
  />
109
103
  ) : (
110
104
  <Input
@@ -118,8 +112,6 @@ export function FilterOperatorValueEditor({
118
112
  ? t("0.00")
119
113
  : t("Enter value...")
120
114
  }
121
- size="$3"
122
- compact
123
115
  {...((fieldType === "number" || fieldType === "money") && {
124
116
  keyboardType: "numeric",
125
117
  })}
@@ -14,6 +14,7 @@ import {
14
14
  ensureFocusVisibleRing,
15
15
  useResolvedKnobs,
16
16
  type DisabledRecipe,
17
+ transitionProps,
17
18
  } from "@multiplatform.one/theme";
18
19
  import { useCallback, useState, type ReactNode } from "react";
19
20
  import { useTranslation } from "react-i18next";
@@ -331,7 +332,7 @@ function SimpleTableMobileCards({
331
332
  const tableZebraOn = knobProps.tableZebra === "on";
332
333
  const [titleCol, ...detailCols] = columns;
333
334
  const typeSize = knobProps.label.fontSize;
334
- const motion = knobProps.transition ? { transition: knobProps.transition } : {};
335
+ const motion = transitionProps(knobProps.transition);
335
336
 
336
337
  if (data.length === 0) {
337
338
  return (
@@ -478,7 +479,7 @@ export function SimpleTableDesktop({
478
479
  const tableZebraOn = knobProps.tableZebra === "on";
479
480
  const ariaLabel = caption ? undefined : props["aria-label"];
480
481
  const typeSize = knobProps.label.fontSize;
481
- const motion = knobProps.transition ? { transition: knobProps.transition } : {};
482
+ const motion = transitionProps(knobProps.transition);
482
483
  const pad = cellPad(knobProps.gap.gap);
483
484
  const frameBorder = knobProps.surface.borderWidth;
484
485
 
@@ -417,4 +417,19 @@ describe("SimpleTable", () => {
417
417
  fireEvent.click(container.querySelector("tbody tr, [role='row']") as Element);
418
418
  expect(onRowPress).not.toHaveBeenCalled();
419
419
  });
420
+ it("survives the animation knob flipping live from none to bouncy (MPO-327)", () => {
421
+ const columns: SimpleTableColumn[] = [{ accessorKey: "name", header: "Name" }];
422
+ const data = [{ name: "Alice" }, { name: "Bob" }];
423
+ const Flip = ({ animation }: { animation: "none" | "bouncy" }) => (
424
+ <Preset overrides={{ animation }}>
425
+ <SimpleTableDesktop data={data} columns={columns} onRowPress={() => {}} />
426
+ </Preset>
427
+ );
428
+ const { container, rerender } = renderWithProviders(<Flip animation="none" />);
429
+ expect(container.querySelector("table")?.getAttribute("data-animation")).toBe("none");
430
+
431
+ expect(() => rerender(<Flip animation="bouncy" />)).not.toThrow();
432
+ expect(container.querySelector("table")?.getAttribute("data-animation")).toBe("on");
433
+ expect(container.textContent).toContain("Bob");
434
+ });
420
435
  });
@@ -8,6 +8,7 @@
8
8
  */
9
9
 
10
10
  import { renderWithProviders, fireEvent } from "@multiplatform.one/test-utils";
11
+ import { waitFor } from "@testing-library/react";
11
12
  import { describe, expect, it, vi } from "vitest";
12
13
  import { Table } from "@multiplatform.one/table-primitives";
13
14
  import { useTableKeyboard } from "../../hooks/useTableKeyboard";
@@ -111,14 +112,7 @@ describe("Table Accessibility", () => {
111
112
  expect(true).toBe(true);
112
113
  });
113
114
 
114
- it("Escape key behavior: Tamagui Popover handles Escape natively", () => {
115
- // Tamagui's Popover component handles Escape key natively to close.
116
- // We verify the popover can be opened (controlled state) and that
117
- // the Escape key handler exists in the DOM event chain.
118
- //
119
- // Note: In happy-dom test environment, Tamagui popover portals may
120
- // not fully render, so we test the controlled open/close pattern.
121
-
115
+ it("Escape closes the column filter panel", async () => {
122
116
  const onFilterChange = vi.fn();
123
117
 
124
118
  const { container } = renderWithProviders(
@@ -130,22 +124,16 @@ describe("Table Accessibility", () => {
130
124
  />,
131
125
  );
132
126
 
133
- // The filter trigger should be present and clickable
134
127
  const trigger = container.querySelector('[aria-label="Filter column Status"]');
135
128
  expect(trigger).not.toBeNull();
136
129
 
137
- // Click to open the popover
138
130
  fireEvent.click(trigger!);
131
+ const panel = () => document.querySelector('[data-testid="floating-panel-viewport"]');
132
+ await waitFor(() => expect(panel()).not.toBeNull());
139
133
 
140
- // The popover content should now be controlled by internal state.
141
- // In happy-dom, the Popover.Content may or may not portal into the DOM.
142
- // The key verification is that the component structure supports Escape:
143
- // ColumnHeaderFilter uses Tamagui Popover with controlled open/onOpenChange,
144
- // which natively handles Escape key to call onOpenChange(false).
145
- //
146
- // We verify the pattern is correct by checking the trigger exists
147
- // and the component renders without error after click interaction.
148
- expect(trigger).not.toBeNull();
134
+ fireEvent.keyDown(document.activeElement ?? document.body, { key: "Escape" });
135
+ await waitFor(() => expect(panel()).toBeNull());
136
+ expect(onFilterChange).not.toHaveBeenCalled();
149
137
  });
150
138
 
151
139
  it("semantic HTML and ARIA roles on table primitives", () => {
@@ -0,0 +1,134 @@
1
+ /**
2
+ * RowDetailEditor (native) — the row form as a FloatingPanel bottom sheet,
3
+ * the same dialog/sheet split CellModalEditor.native makes. Props, staging
4
+ * and footer match ./RowDetailEditor.tsx; backdrop tap and Android back
5
+ * commit like "Done".
6
+ */
7
+
8
+ import { Button, FloatingPanel } from "@multiplatform.one/forms";
9
+ import { useResolvedKnobs } from "@multiplatform.one/theme";
10
+ import { PencilSimpleIcon } from "@phosphor-icons/react";
11
+ import { useCallback, useRef, useState } from "react";
12
+ import { Text, View, XStack, YStack } from "tamagui";
13
+ import type { DataTableData, DataTableField, DataTableFieldProps } from "../../types";
14
+ import { t } from "../../shared/t";
15
+ import { withInterp } from "../../utils/withInterp";
16
+ import { DataTableCell } from "../DataTableCell";
17
+ import type { RowDetailEditorProps } from "./RowDetailEditor";
18
+ import { changedColumns, columnKey } from "./shared";
19
+
20
+ export type { RowDetailEditorProps } from "./RowDetailEditor";
21
+
22
+ export function RowDetailEditor<TData extends DataTableData>({
23
+ row,
24
+ rowIndex,
25
+ columns,
26
+ readOnly,
27
+ compact,
28
+ isCellHidden,
29
+ onCommit,
30
+ }: RowDetailEditorProps<TData>) {
31
+ const { knobProps } = useResolvedKnobs({ compact });
32
+ const [draft, setDraft] = useState<TData | null>(null);
33
+ const draftRef = useRef(draft);
34
+ draftRef.current = draft;
35
+ const rowRef = useRef(row);
36
+ rowRef.current = row;
37
+ const onCommitRef = useRef(onCommit);
38
+ onCommitRef.current = onCommit;
39
+ const discardRef = useRef(false);
40
+ const rowNumber = rowIndex + 1;
41
+
42
+ const handleOpenChange = useCallback(
43
+ (next: boolean) => {
44
+ if (next) {
45
+ discardRef.current = false;
46
+ const seeded = { ...rowRef.current };
47
+ draftRef.current = seeded;
48
+ setDraft(seeded);
49
+ return;
50
+ }
51
+ const active = draftRef.current;
52
+ if (!discardRef.current && !readOnly && active) {
53
+ const changed = changedColumns(rowRef.current, active, columns);
54
+ if (changed.length > 0) onCommitRef.current(active, changed);
55
+ }
56
+ discardRef.current = false;
57
+ draftRef.current = null;
58
+ setDraft(null);
59
+ },
60
+ [columns, readOnly],
61
+ );
62
+
63
+ const handleCancel = useCallback(() => {
64
+ discardRef.current = true;
65
+ handleOpenChange(false);
66
+ }, [handleOpenChange]);
67
+
68
+ const setDraftValue = useCallback((columnId: string, value: unknown) => {
69
+ const current = draftRef.current;
70
+ if (!current) return;
71
+ const next = { ...current, [columnId]: value } as TData;
72
+ draftRef.current = next;
73
+ setDraft(next);
74
+ }, []);
75
+
76
+ const triggerLabel = withInterp(
77
+ t(readOnly ? "View row {{row}}" : "Edit row {{row}}", { row: rowNumber }),
78
+ { row: rowNumber },
79
+ );
80
+ const current = draft ?? row;
81
+
82
+ return (
83
+ <FloatingPanel
84
+ open={draft !== null}
85
+ onOpenChange={handleOpenChange}
86
+ scrollable
87
+ triggerSizing="content"
88
+ triggerA11y={{ label: triggerLabel }}
89
+ trigger={
90
+ <View alignItems="center" justifyContent="center">
91
+ <PencilSimpleIcon size={16} />
92
+ </View>
93
+ }
94
+ >
95
+ <YStack {...knobProps.gapLg}>
96
+ <Text {...knobProps.heading}>
97
+ {withInterp(t("Row {{row}}", { row: rowNumber }), { row: rowNumber })}
98
+ </Text>
99
+ {columns.map((col) => {
100
+ const columnId = columnKey(col);
101
+ if (isCellHidden?.(current, columnId, rowIndex)) return null;
102
+ const label = typeof col.header === "string" ? col.header : columnId;
103
+ return (
104
+ <YStack key={columnId} {...knobProps.gap}>
105
+ <Text {...knobProps.label}>{label}</Text>
106
+ <DataTableCell
107
+ value={current[columnId as keyof TData]}
108
+ onChange={(value) => setDraftValue(columnId, value)}
109
+ field={(col.field || "input") as DataTableField}
110
+ fieldProps={col.fieldProps as DataTableFieldProps | undefined}
111
+ readOnly={readOnly}
112
+ compact={false}
113
+ columnId={columnId}
114
+ columnLabel={label}
115
+ rowIndex={rowIndex}
116
+ rowData={current}
117
+ />
118
+ </YStack>
119
+ );
120
+ })}
121
+ <XStack {...knobProps.gap} justifyContent="flex-end">
122
+ {readOnly ? (
123
+ <Button onPress={handleCancel}>{t("Close")}</Button>
124
+ ) : (
125
+ <>
126
+ <Button onPress={handleCancel}>{t("Cancel")}</Button>
127
+ <Button onPress={() => handleOpenChange(false)}>{t("Done")}</Button>
128
+ </>
129
+ )}
130
+ </XStack>
131
+ </YStack>
132
+ </FloatingPanel>
133
+ );
134
+ }
@@ -0,0 +1,173 @@
1
+ /**
2
+ * RowDetailEditor — the child-table row opened as a form (Frappe's grid
3
+ * row "Edit" form). The grid shows the list-view columns; the detail editor
4
+ * shows every `columns` entry for one row, full-size, in a dialog.
5
+ *
6
+ * Same staging contract as CellModalEditor (UX-023): the fields edit a draft
7
+ * copy of the row seeded on open. "Done" and an outside click commit the
8
+ * draft once; "Cancel" and Escape discard it. A read-only row opens for
9
+ * viewing with a single "Close".
10
+ */
11
+
12
+ import { DialogContent, DialogOverlay } from "@multiplatform.one/components";
13
+ import { Button } from "@multiplatform.one/forms";
14
+ import { TableCellContext } from "@multiplatform.one/table-primitives";
15
+ import { useResolvedKnobs } from "@multiplatform.one/theme";
16
+ import { PencilSimpleIcon } from "@phosphor-icons/react";
17
+ import { useCallback, useRef, useState } from "react";
18
+ import { Dialog, ScrollView, Text, XStack, YStack } from "tamagui";
19
+ import type {
20
+ DataTableColumn,
21
+ DataTableData,
22
+ DataTableField,
23
+ DataTableFieldProps,
24
+ } from "../../types";
25
+ import { t } from "../../shared/t";
26
+ import { withInterp } from "../../utils/withInterp";
27
+ import { DataTableCell } from "../DataTableCell";
28
+ import { changedColumns, columnKey, type ChildCellHidden } from "./shared";
29
+
30
+ export interface RowDetailEditorProps<TData extends DataTableData> {
31
+ row: TData;
32
+ rowIndex: number;
33
+ columns: DataTableColumn<TData>[];
34
+ readOnly: boolean;
35
+ compact: boolean;
36
+ isCellHidden?: ChildCellHidden<TData>;
37
+ /** Receives the edited row once per session, only when a value changed. */
38
+ onCommit: (row: TData, changed: string[]) => void;
39
+ }
40
+
41
+ export function RowDetailEditor<TData extends DataTableData>({
42
+ row,
43
+ rowIndex,
44
+ columns,
45
+ readOnly,
46
+ compact,
47
+ isCellHidden,
48
+ onCommit,
49
+ }: RowDetailEditorProps<TData>) {
50
+ const { knobProps } = useResolvedKnobs({ compact });
51
+ const [draft, setDraft] = useState<TData | null>(null);
52
+ const draftRef = useRef(draft);
53
+ draftRef.current = draft;
54
+ const rowRef = useRef(row);
55
+ rowRef.current = row;
56
+ const onCommitRef = useRef(onCommit);
57
+ onCommitRef.current = onCommit;
58
+ const discardRef = useRef(false);
59
+ const rowNumber = rowIndex + 1;
60
+
61
+ const handleOpenChange = useCallback(
62
+ (next: boolean) => {
63
+ if (next) {
64
+ discardRef.current = false;
65
+ const seeded = { ...rowRef.current };
66
+ draftRef.current = seeded;
67
+ setDraft(seeded);
68
+ return;
69
+ }
70
+ const active = draftRef.current;
71
+ if (!discardRef.current && !readOnly && active) {
72
+ const changed = changedColumns(rowRef.current, active, columns);
73
+ if (changed.length > 0) onCommitRef.current(active, changed);
74
+ }
75
+ discardRef.current = false;
76
+ draftRef.current = null;
77
+ setDraft(null);
78
+ },
79
+ [columns, readOnly],
80
+ );
81
+
82
+ const handleCancel = useCallback(() => {
83
+ discardRef.current = true;
84
+ handleOpenChange(false);
85
+ }, [handleOpenChange]);
86
+
87
+ const setDraftValue = useCallback((columnId: string, value: unknown) => {
88
+ const current = draftRef.current;
89
+ if (!current) return;
90
+ const next = { ...current, [columnId]: value } as TData;
91
+ draftRef.current = next;
92
+ setDraft(next);
93
+ }, []);
94
+
95
+ const triggerLabel = withInterp(
96
+ t(readOnly ? "View row {{row}}" : "Edit row {{row}}", { row: rowNumber }),
97
+ { row: rowNumber },
98
+ );
99
+ const current = draft ?? row;
100
+
101
+ return (
102
+ <>
103
+ <Button
104
+ chromeless
105
+ compact={compact}
106
+ onPress={() => handleOpenChange(true)}
107
+ hitSlop={knobProps.nestedControl.hitSlop}
108
+ aria-label={triggerLabel}
109
+ aria-haspopup="dialog"
110
+ aria-expanded={draft !== null}
111
+ >
112
+ <PencilSimpleIcon size={16} />
113
+ </Button>
114
+ <Dialog open={draft !== null} onOpenChange={handleOpenChange} modal>
115
+ <Dialog.Portal>
116
+ <DialogOverlay opacity={0.5} />
117
+ <DialogContent
118
+ maxWidth={720}
119
+ maxHeight="80vh"
120
+ width="90vw"
121
+ onEscapeKeyDown={() => {
122
+ discardRef.current = true;
123
+ }}
124
+ >
125
+ <Dialog.Title {...knobProps.heading}>
126
+ {withInterp(t("Row {{row}}", { row: rowNumber }), { row: rowNumber })}
127
+ </Dialog.Title>
128
+ <ScrollView flexShrink={1} minHeight={0}>
129
+ <TableCellContext.Provider value={{ inTableCell: false }}>
130
+ <YStack {...knobProps.gapLg}>
131
+ {columns.map((col) => {
132
+ const columnId = columnKey(col);
133
+ if (isCellHidden?.(current, columnId, rowIndex)) return null;
134
+ const label = typeof col.header === "string" ? col.header : columnId;
135
+ return (
136
+ <YStack key={columnId} {...knobProps.gap}>
137
+ <Text {...knobProps.label}>{label}</Text>
138
+ <DataTableCell
139
+ value={current[columnId as keyof TData]}
140
+ onChange={(value) => setDraftValue(columnId, value)}
141
+ field={(col.field || "input") as DataTableField}
142
+ fieldProps={col.fieldProps as DataTableFieldProps | undefined}
143
+ readOnly={readOnly}
144
+ compact={false}
145
+ columnId={columnId}
146
+ columnLabel={label}
147
+ rowIndex={rowIndex}
148
+ rowData={current}
149
+ />
150
+ </YStack>
151
+ );
152
+ })}
153
+ </YStack>
154
+ </TableCellContext.Provider>
155
+ </ScrollView>
156
+ <XStack {...knobProps.gap} justifyContent="flex-end">
157
+ {readOnly ? (
158
+ <Button onPress={handleCancel}>{t("Close")}</Button>
159
+ ) : (
160
+ <>
161
+ <Button onPress={handleCancel}>{t("Cancel")}</Button>
162
+ <Button theme="accent" onPress={() => handleOpenChange(false)}>
163
+ {t("Done")}
164
+ </Button>
165
+ </>
166
+ )}
167
+ </XStack>
168
+ </DialogContent>
169
+ </Dialog.Portal>
170
+ </Dialog>
171
+ </>
172
+ );
173
+ }