hakumi_components 0.1.18.pre → 0.1.19.pre

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 (467) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +32 -2
  3. data/README.md +208 -381
  4. data/app/assets/javascripts/hakumi_components.js +40 -34
  5. data/app/assets/stylesheets/hakumi_components.css +1 -1
  6. data/app/components/hakumi_components/admin_panel/component.rb +19 -9
  7. data/app/components/hakumi_components/affix/component.rb +54 -30
  8. data/app/components/hakumi_components/alert/component.html.erb +2 -2
  9. data/app/components/hakumi_components/alert/component.rb +68 -18
  10. data/app/components/hakumi_components/anchor/component.rb +35 -27
  11. data/app/components/hakumi_components/anchor/link/component.html.erb +1 -1
  12. data/app/components/hakumi_components/anchor/link/component.rb +28 -9
  13. data/app/components/hakumi_components/autocomplete/component.html.erb +86 -66
  14. data/app/components/hakumi_components/autocomplete/component.rb +115 -89
  15. data/app/components/hakumi_components/avatar/component.rb +45 -12
  16. data/app/components/hakumi_components/badge/component.rb +99 -45
  17. data/app/components/hakumi_components/base_component.rb +290 -91
  18. data/app/components/hakumi_components/breadcrumb/component.rb +16 -5
  19. data/app/components/hakumi_components/breadcrumb/item/component.html.erb +5 -5
  20. data/app/components/hakumi_components/breadcrumb/item/component.rb +56 -8
  21. data/app/components/hakumi_components/breadcrumb/item/menu_entry.rb +71 -0
  22. data/app/components/hakumi_components/button/component.rb +62 -20
  23. data/app/components/hakumi_components/calendar/component.html.erb +19 -19
  24. data/app/components/hakumi_components/calendar/component.rb +225 -202
  25. data/app/components/hakumi_components/calendar/day_cell.rb +62 -0
  26. data/app/components/hakumi_components/calendar/display_model.rb +237 -0
  27. data/app/components/hakumi_components/calendar/event_entry.rb +54 -0
  28. data/app/components/hakumi_components/calendar/locale_pack.rb +28 -0
  29. data/app/components/hakumi_components/calendar/panel_entry.rb +48 -0
  30. data/app/components/hakumi_components/calendar/week_row.rb +28 -0
  31. data/app/components/hakumi_components/card/component.html.erb +2 -2
  32. data/app/components/hakumi_components/card/component.rb +76 -49
  33. data/app/components/hakumi_components/card/grid/component.html.erb +1 -1
  34. data/app/components/hakumi_components/card/grid/component.rb +23 -17
  35. data/app/components/hakumi_components/card/meta/component.html.erb +8 -8
  36. data/app/components/hakumi_components/card/meta/component.rb +42 -24
  37. data/app/components/hakumi_components/carousel/autoplay_config.rb +27 -0
  38. data/app/components/hakumi_components/carousel/component.rb +85 -67
  39. data/app/components/hakumi_components/carousel/dots_config.rb +36 -0
  40. data/app/components/hakumi_components/cascader/component.html.erb +54 -36
  41. data/app/components/hakumi_components/cascader/component.rb +111 -62
  42. data/app/components/hakumi_components/checkbox/component.html.erb +5 -5
  43. data/app/components/hakumi_components/checkbox/component.rb +40 -6
  44. data/app/components/hakumi_components/checkbox/group/component.html.erb +4 -4
  45. data/app/components/hakumi_components/checkbox/group/component.rb +40 -13
  46. data/app/components/hakumi_components/checkbox/group/option.rb +34 -0
  47. data/app/components/hakumi_components/collapse/component.rb +64 -48
  48. data/app/components/hakumi_components/collapse/panel/component.rb +64 -21
  49. data/app/components/hakumi_components/color_picker/component.html.erb +21 -22
  50. data/app/components/hakumi_components/color_picker/component.rb +159 -49
  51. data/app/components/hakumi_components/color_picker/preset_group.rb +27 -0
  52. data/app/components/hakumi_components/concerns/form_field.rb +169 -68
  53. data/app/components/hakumi_components/concerns/form_field_contract.rb +57 -0
  54. data/app/components/hakumi_components/concerns/form_field_interface.rb +16 -0
  55. data/app/components/hakumi_components/concerns/input_control.rb +111 -0
  56. data/app/components/hakumi_components/concerns/input_control_contract.rb +47 -0
  57. data/app/components/hakumi_components/concerns/input_control_interface.rb +34 -0
  58. data/app/components/hakumi_components/concerns/selection_control.rb +122 -0
  59. data/app/components/hakumi_components/concerns/selection_control_contract.rb +47 -0
  60. data/app/components/hakumi_components/concerns/selection_control_interface.rb +34 -0
  61. data/app/components/hakumi_components/container/component.rb +29 -14
  62. data/app/components/hakumi_components/date_picker/component.html.erb +1 -3
  63. data/app/components/hakumi_components/date_picker/component.rb +130 -16
  64. data/app/components/hakumi_components/date_picker/range_picker.rb +159 -28
  65. data/app/components/hakumi_components/date_picker/shared_rendering.rb +151 -61
  66. data/app/components/hakumi_components/descriptions/component.html.erb +6 -6
  67. data/app/components/hakumi_components/descriptions/component.rb +98 -61
  68. data/app/components/hakumi_components/descriptions/item/component.rb +32 -8
  69. data/app/components/hakumi_components/divider/component.rb +36 -16
  70. data/app/components/hakumi_components/drawer/component.html.erb +2 -2
  71. data/app/components/hakumi_components/drawer/component.rb +112 -29
  72. data/app/components/hakumi_components/dropdown/component.rb +32 -35
  73. data/app/components/hakumi_components/dropdown/divider/component.rb +4 -0
  74. data/app/components/hakumi_components/dropdown/item/component.rb +42 -16
  75. data/app/components/hakumi_components/empty/component.rb +66 -31
  76. data/app/components/hakumi_components/flex/component.rb +39 -21
  77. data/app/components/hakumi_components/float_button/back_top/component.rb +35 -28
  78. data/app/components/hakumi_components/float_button/component.rb +161 -75
  79. data/app/components/hakumi_components/float_button/group/component.rb +85 -98
  80. data/app/components/hakumi_components/float_button/group_cluster/component.rb +46 -54
  81. data/app/components/hakumi_components/float_button/group_spec.rb +259 -0
  82. data/app/components/hakumi_components/float_button/item_spec.rb +115 -0
  83. data/app/components/hakumi_components/float_button/position_config.rb +68 -0
  84. data/app/components/hakumi_components/form/item/component.rb +34 -27
  85. data/app/components/hakumi_components/grid/col/component.rb +88 -17
  86. data/app/components/hakumi_components/grid/row/component.rb +35 -17
  87. data/app/components/hakumi_components/icon/component.rb +49 -49
  88. data/app/components/hakumi_components/image/component.html.erb +7 -7
  89. data/app/components/hakumi_components/image/component.rb +103 -40
  90. data/app/components/hakumi_components/image/preview_group/component.html.erb +1 -1
  91. data/app/components/hakumi_components/image/preview_group/component.rb +41 -36
  92. data/app/components/hakumi_components/image/preview_group/item.rb +48 -0
  93. data/app/components/hakumi_components/input/component.html.erb +1 -1
  94. data/app/components/hakumi_components/input/component.rb +142 -66
  95. data/app/components/hakumi_components/input/password/component.rb +30 -41
  96. data/app/components/hakumi_components/input/text_area/component.html.erb +2 -2
  97. data/app/components/hakumi_components/input/text_area/component.rb +89 -42
  98. data/app/components/hakumi_components/input_number/component.html.erb +5 -5
  99. data/app/components/hakumi_components/input_number/component.rb +137 -55
  100. data/app/components/hakumi_components/layout/component.html.erb +1 -1
  101. data/app/components/hakumi_components/layout/component.rb +23 -16
  102. data/app/components/hakumi_components/layout/content/component.html.erb +1 -1
  103. data/app/components/hakumi_components/layout/content/component.rb +24 -14
  104. data/app/components/hakumi_components/layout/footer/component.html.erb +1 -1
  105. data/app/components/hakumi_components/layout/footer/component.rb +24 -14
  106. data/app/components/hakumi_components/layout/header/component.html.erb +1 -1
  107. data/app/components/hakumi_components/layout/header/component.rb +24 -14
  108. data/app/components/hakumi_components/layout/sider/component.html.erb +1 -1
  109. data/app/components/hakumi_components/layout/sider/component.rb +83 -49
  110. data/app/components/hakumi_components/mentions/coercion.rb +46 -0
  111. data/app/components/hakumi_components/mentions/component.html.erb +6 -6
  112. data/app/components/hakumi_components/mentions/component.rb +131 -67
  113. data/app/components/hakumi_components/mentions/option.rb +30 -0
  114. data/app/components/hakumi_components/menu/component.rb +50 -59
  115. data/app/components/hakumi_components/menu/divider/component.rb +4 -0
  116. data/app/components/hakumi_components/menu/group/component.rb +16 -15
  117. data/app/components/hakumi_components/menu/item/component.rb +42 -19
  118. data/app/components/hakumi_components/menu/sub_menu/component.rb +49 -37
  119. data/app/components/hakumi_components/message/component.rb +62 -27
  120. data/app/components/hakumi_components/modal/component.html.erb +6 -6
  121. data/app/components/hakumi_components/modal/component.rb +93 -40
  122. data/app/components/hakumi_components/modal/confirm/component.html.erb +2 -2
  123. data/app/components/hakumi_components/modal/confirm/component.rb +49 -8
  124. data/app/components/hakumi_components/modal/error/component.rb +8 -39
  125. data/app/components/hakumi_components/modal/info/component.rb +6 -40
  126. data/app/components/hakumi_components/modal/status_component.rb +150 -0
  127. data/app/components/hakumi_components/modal/success/component.rb +6 -40
  128. data/app/components/hakumi_components/modal/warning/component.rb +14 -44
  129. data/app/components/hakumi_components/notification/component.rb +72 -38
  130. data/app/components/hakumi_components/pagination/component.html.erb +7 -11
  131. data/app/components/hakumi_components/pagination/component.rb +105 -72
  132. data/app/components/hakumi_components/pagination/page_item.rb +49 -0
  133. data/app/components/hakumi_components/popconfirm/component.rb +67 -19
  134. data/app/components/hakumi_components/popover/component.html.erb +2 -2
  135. data/app/components/hakumi_components/popover/component.rb +102 -38
  136. data/app/components/hakumi_components/progress/attribute_renderer.rb +354 -0
  137. data/app/components/hakumi_components/progress/circle_geometry.rb +76 -0
  138. data/app/components/hakumi_components/progress/component.html.erb +18 -17
  139. data/app/components/hakumi_components/progress/component.rb +230 -402
  140. data/app/components/hakumi_components/progress/controller_locals_parser.rb +130 -0
  141. data/app/components/hakumi_components/progress/info_tooltip_policy.rb +39 -0
  142. data/app/components/hakumi_components/progress/info_value.rb +75 -0
  143. data/app/components/hakumi_components/progress/status_state.rb +31 -0
  144. data/app/components/hakumi_components/progress/steps_renderer.rb +149 -0
  145. data/app/components/hakumi_components/progress/stroke_gradient_value.rb +90 -0
  146. data/app/components/hakumi_components/qr_code/component.rb +138 -72
  147. data/app/components/hakumi_components/radio/component.html.erb +3 -3
  148. data/app/components/hakumi_components/radio/component.rb +42 -9
  149. data/app/components/hakumi_components/radio/group/component.html.erb +9 -9
  150. data/app/components/hakumi_components/radio/group/component.rb +76 -27
  151. data/app/components/hakumi_components/radio/group/option.rb +43 -0
  152. data/app/components/hakumi_components/rate/component.html.erb +1 -1
  153. data/app/components/hakumi_components/rate/component.rb +55 -9
  154. data/app/components/hakumi_components/result/component.rb +87 -37
  155. data/app/components/hakumi_components/segmented/component.html.erb +1 -1
  156. data/app/components/hakumi_components/segmented/component.rb +81 -118
  157. data/app/components/hakumi_components/segmented/option.rb +191 -0
  158. data/app/components/hakumi_components/select/component.html.erb +19 -19
  159. data/app/components/hakumi_components/select/component.rb +88 -37
  160. data/app/components/hakumi_components/selection_control/coercion.rb +161 -0
  161. data/app/components/hakumi_components/selection_control/entry.rb +22 -0
  162. data/app/components/hakumi_components/selection_control/option.rb +42 -0
  163. data/app/components/hakumi_components/selection_control/option_group.rb +34 -0
  164. data/app/components/hakumi_components/selection_control/tree_node.rb +123 -0
  165. data/app/components/hakumi_components/skeleton/avatar/component.rb +36 -14
  166. data/app/components/hakumi_components/skeleton/avatar_config.rb +79 -0
  167. data/app/components/hakumi_components/skeleton/button/component.rb +32 -14
  168. data/app/components/hakumi_components/skeleton/component.rb +79 -93
  169. data/app/components/hakumi_components/skeleton/image/component.rb +46 -22
  170. data/app/components/hakumi_components/skeleton/input/component.rb +25 -10
  171. data/app/components/hakumi_components/skeleton/node/component.rb +23 -7
  172. data/app/components/hakumi_components/skeleton/paragraph_config.rb +92 -0
  173. data/app/components/hakumi_components/skeleton/title_config.rb +31 -0
  174. data/app/components/hakumi_components/slider/component.html.erb +11 -11
  175. data/app/components/hakumi_components/slider/component.rb +172 -53
  176. data/app/components/hakumi_components/slider/mark.rb +27 -0
  177. data/app/components/hakumi_components/space/compact/component.html.erb +1 -3
  178. data/app/components/hakumi_components/space/compact/component.rb +35 -19
  179. data/app/components/hakumi_components/space/component.html.erb +1 -1
  180. data/app/components/hakumi_components/space/component.rb +75 -39
  181. data/app/components/hakumi_components/spin/component.rb +92 -31
  182. data/app/components/hakumi_components/splitter/component.html.erb +9 -3
  183. data/app/components/hakumi_components/splitter/component.rb +55 -22
  184. data/app/components/hakumi_components/splitter/panel/component.html.erb +1 -3
  185. data/app/components/hakumi_components/splitter/panel/component.rb +64 -39
  186. data/app/components/hakumi_components/statistic/component.rb +143 -59
  187. data/app/components/hakumi_components/steps/component.rb +87 -55
  188. data/app/components/hakumi_components/steps/item/component.rb +59 -20
  189. data/app/components/hakumi_components/switch/component.html.erb +2 -3
  190. data/app/components/hakumi_components/switch/component.rb +62 -36
  191. data/app/components/hakumi_components/table/column/component.rb +80 -23
  192. data/app/components/hakumi_components/table/column_definition.rb +181 -0
  193. data/app/components/hakumi_components/table/column_group/component.rb +32 -21
  194. data/app/components/hakumi_components/table/component.html.erb +22 -31
  195. data/app/components/hakumi_components/table/component.rb +248 -509
  196. data/app/components/hakumi_components/table/concerns/attribute_helpers.rb +22 -0
  197. data/app/components/hakumi_components/table/concerns/cell_rendering.rb +277 -0
  198. data/app/components/hakumi_components/table/concerns/columns.rb +293 -91
  199. data/app/components/hakumi_components/table/concerns/editable.rb +36 -89
  200. data/app/components/hakumi_components/table/concerns/ellipsis.rb +31 -30
  201. data/app/components/hakumi_components/table/concerns/fixed_columns.rb +26 -19
  202. data/app/components/hakumi_components/table/concerns/surface_rendering.rb +365 -0
  203. data/app/components/hakumi_components/table/configs.rb +518 -0
  204. data/app/components/hakumi_components/table/definition_types.rb +40 -0
  205. data/app/components/hakumi_components/table/display_rows.rb +56 -0
  206. data/app/components/hakumi_components/table/ellipsis_config.rb +143 -0
  207. data/app/components/hakumi_components/table/fixed_offset.rb +36 -0
  208. data/app/components/hakumi_components/table/header_cell.rb +23 -0
  209. data/app/components/hakumi_components/table/row_record.rb +60 -0
  210. data/app/components/hakumi_components/table/row_render_state.rb +85 -0
  211. data/app/components/hakumi_components/tabs/component.html.erb +8 -8
  212. data/app/components/hakumi_components/tabs/component.rb +114 -64
  213. data/app/components/hakumi_components/tabs/indicator_config.rb +34 -0
  214. data/app/components/hakumi_components/tabs/item/component.rb +73 -13
  215. data/app/components/hakumi_components/tag/component.rb +142 -47
  216. data/app/components/hakumi_components/tag/group/component.rb +18 -6
  217. data/app/components/hakumi_components/time_picker/component.html.erb +8 -8
  218. data/app/components/hakumi_components/time_picker/component.rb +71 -17
  219. data/app/components/hakumi_components/timeline/component.html.erb +3 -2
  220. data/app/components/hakumi_components/timeline/component.rb +188 -55
  221. data/app/components/hakumi_components/timeline/item/component.html.erb +2 -2
  222. data/app/components/hakumi_components/timeline/item/component.rb +121 -60
  223. data/app/components/hakumi_components/tooltip/component.html.erb +1 -1
  224. data/app/components/hakumi_components/tooltip/component.rb +89 -64
  225. data/app/components/hakumi_components/tour/component.rb +74 -49
  226. data/app/components/hakumi_components/tour/step.rb +86 -0
  227. data/app/components/hakumi_components/transfer/coercion.rb +66 -0
  228. data/app/components/hakumi_components/transfer/component.html.erb +171 -140
  229. data/app/components/hakumi_components/transfer/component.rb +232 -82
  230. data/app/components/hakumi_components/transfer/item.rb +54 -0
  231. data/app/components/hakumi_components/transfer/operations.rb +31 -0
  232. data/app/components/hakumi_components/tree/component.rb +219 -400
  233. data/app/components/hakumi_components/tree/concerns/node_rendering.rb +365 -0
  234. data/app/components/hakumi_components/tree/node.rb +276 -0
  235. data/app/components/hakumi_components/tree_select/component.html.erb +23 -9
  236. data/app/components/hakumi_components/tree_select/component.rb +116 -107
  237. data/app/components/hakumi_components/typography/base_component.rb +69 -36
  238. data/app/components/hakumi_components/typography/link/component.rb +63 -6
  239. data/app/components/hakumi_components/typography/paragraph/component.rb +6 -0
  240. data/app/components/hakumi_components/typography/text/component.rb +4 -0
  241. data/app/components/hakumi_components/typography/title/component.rb +61 -6
  242. data/app/components/hakumi_components/upload/component.html.erb +106 -88
  243. data/app/components/hakumi_components/upload/component.rb +222 -48
  244. data/app/components/hakumi_components/upload/file_entry.rb +53 -0
  245. data/app/controllers/hakumi_components/components_controller.rb +2 -1
  246. data/app/form_builders/hakumi_components/form_builder/contracts.rb +55 -0
  247. data/app/form_builders/hakumi_components/form_builder/field_context.rb +43 -0
  248. data/app/form_builders/hakumi_components/form_builder/model_binding.rb +163 -0
  249. data/app/form_builders/hakumi_components/form_builder.rb +238 -317
  250. data/app/helpers/hakumi_components/form_helper.rb +27 -23
  251. data/app/javascript/hakumi_components/controllers/hakumi/admin_panel_controller.js +5 -7
  252. data/app/javascript/hakumi_components/controllers/hakumi/back_top_controller.js +1 -1
  253. data/app/javascript/hakumi_components/controllers/hakumi/button_controller.js +108 -2
  254. data/app/javascript/hakumi_components/controllers/hakumi/calendar_controller.js +183 -95
  255. data/app/javascript/hakumi_components/controllers/hakumi/color_picker_controller.js +23 -285
  256. data/app/javascript/hakumi_components/controllers/hakumi/date_picker_controller.js +274 -262
  257. data/app/javascript/hakumi_components/controllers/hakumi/float_button_group_controller.js +2 -2
  258. data/app/javascript/hakumi_components/controllers/hakumi/message_controller.js +4 -2
  259. data/app/javascript/hakumi_components/controllers/hakumi/modal_controller.js +119 -125
  260. data/app/javascript/hakumi_components/controllers/hakumi/table/editable.js +291 -0
  261. data/app/javascript/hakumi_components/controllers/hakumi/table_controller.js +166 -366
  262. data/app/javascript/hakumi_components/controllers/hakumi/tabs_controller.js +8 -2
  263. data/app/javascript/hakumi_components/controllers/hakumi/tag_controller.js +27 -25
  264. data/app/javascript/hakumi_components/controllers/hakumi/tag_group_controller.js +19 -18
  265. data/app/javascript/hakumi_components/controllers/hakumi/theme_controller.js +116 -117
  266. data/app/javascript/hakumi_components/controllers/hakumi/transfer_controller.js +17 -1
  267. data/app/javascript/hakumi_components/controllers/hakumi/tree_controller.js +363 -78
  268. data/app/javascript/hakumi_components/controllers/hakumi/typography_controller.js +3 -3
  269. data/app/javascript/hakumi_components/controllers/hakumi/upload_controller.js +320 -204
  270. data/app/javascript/hakumi_components/core/render_component.js +37 -11
  271. data/app/javascript/hakumi_components/utils/color_helper.js +262 -0
  272. data/app/javascript/stylesheets/_base.scss +9 -0
  273. data/app/javascript/stylesheets/_hakumi_components.scss +1 -0
  274. data/app/javascript/stylesheets/components/_breadcrumb.scss +2 -2
  275. data/app/javascript/stylesheets/components/_calendar.scss +13 -13
  276. data/app/javascript/stylesheets/components/_cascader.scss +5 -5
  277. data/app/javascript/stylesheets/components/_checkbox.scss +9 -11
  278. data/app/javascript/stylesheets/components/_color_picker.scss +11 -11
  279. data/app/javascript/stylesheets/components/_date_picker.scss +4 -4
  280. data/app/javascript/stylesheets/components/_descriptions.scss +2 -2
  281. data/app/javascript/stylesheets/components/_drawer.scss +3 -3
  282. data/app/javascript/stylesheets/components/_dropdown.scss +2 -2
  283. data/app/javascript/stylesheets/components/_flex.scss +1 -1
  284. data/app/javascript/stylesheets/components/_float_button.scss +5 -5
  285. data/app/javascript/stylesheets/components/_form_item.scss +92 -0
  286. data/app/javascript/stylesheets/components/_image.scss +15 -15
  287. data/app/javascript/stylesheets/components/_input.scss +23 -113
  288. data/app/javascript/stylesheets/components/_layout.scss +27 -26
  289. data/app/javascript/stylesheets/components/_menu.scss +15 -15
  290. data/app/javascript/stylesheets/components/_modal.scss +13 -13
  291. data/app/javascript/stylesheets/components/_notification.scss +3 -3
  292. data/app/javascript/stylesheets/components/_popover.scss +1 -1
  293. data/app/javascript/stylesheets/components/_segmented.scss +3 -3
  294. data/app/javascript/stylesheets/components/_select.scss +6 -6
  295. data/app/javascript/stylesheets/components/_slider.scss +1 -1
  296. data/app/javascript/stylesheets/components/_spin.scss +2 -2
  297. data/app/javascript/stylesheets/components/_steps.scss +10 -10
  298. data/app/javascript/stylesheets/components/_switch.scss +11 -10
  299. data/app/javascript/stylesheets/components/_table.scss +6 -6
  300. data/app/javascript/stylesheets/components/_tag.scss +2 -2
  301. data/app/javascript/stylesheets/components/_tooltip.scss +4 -4
  302. data/app/javascript/stylesheets/components/_tree_select.scss +3 -3
  303. data/app/javascript/stylesheets/components/_typography.scss +3 -3
  304. data/app/javascript/stylesheets/components/_upload.scss +4 -4
  305. data/app/services/hakumi_components/component_handler.rb +95 -24
  306. data/app/services/hakumi_components/icon/loader.rb +84 -67
  307. data/app/services/hakumi_components/illustrations/loader.rb +35 -27
  308. data/app/views/hakumi/_alert.html.erb +4 -1
  309. data/app/views/hakumi/_drawer.html.erb +1 -1
  310. data/app/views/hakumi/_statistic.html.erb +11 -11
  311. data/lib/generators/hakumi_components/install_generator.rb +14 -1
  312. data/lib/hakumi_components/documentation/models.rb +290 -0
  313. data/lib/hakumi_components/documentation/node.rb +73 -0
  314. data/lib/hakumi_components/documentation.rb +139 -62
  315. data/lib/hakumi_components/engine.rb +17 -11
  316. data/lib/hakumi_components/file_size_checker.rb +215 -0
  317. data/lib/hakumi_components/locales/en.yml +115 -0
  318. data/lib/hakumi_components/rails/attribute_introspection.rb +39 -107
  319. data/lib/hakumi_components/rails/model_reflection.rb +154 -0
  320. data/lib/hakumi_components/rails/validation_introspection.rb +25 -73
  321. data/lib/hakumi_components/rails/validation_mapper.rb +148 -201
  322. data/lib/hakumi_components/rails.rb +2 -0
  323. data/lib/hakumi_components/stylesheet_ownership_checker.rb +191 -0
  324. data/lib/hakumi_components/types/form_field.rb +24 -0
  325. data/lib/hakumi_components/types/html.rb +28 -0
  326. data/lib/hakumi_components/types/rendering.rb +10 -0
  327. data/lib/hakumi_components/types/stimulus.rb +19 -0
  328. data/lib/hakumi_components/types/validation.rb +22 -0
  329. data/lib/hakumi_components/types.rb +13 -0
  330. data/lib/hakumi_components/version.rb +2 -1
  331. data/lib/hakumi_components.rb +26 -6
  332. data/lib/tasks/coverage.rake +1 -0
  333. metadata +100 -136
  334. data/sig/action_view/tag_builder.rbs +0 -24
  335. data/sig/active_support/concern_patch.rbs +0 -7
  336. data/sig/generators/hakumi_components/install_generator.rbs +0 -11
  337. data/sig/hakumi_components/admin_panel/component.rbs +0 -28
  338. data/sig/hakumi_components/affix/component.rbs +0 -44
  339. data/sig/hakumi_components/alert/component.rbs +0 -64
  340. data/sig/hakumi_components/anchor/component.rbs +0 -45
  341. data/sig/hakumi_components/anchor/link/component.rbs +0 -31
  342. data/sig/hakumi_components/autocomplete/component.rbs +0 -68
  343. data/sig/hakumi_components/avatar/component.rbs +0 -44
  344. data/sig/hakumi_components/badge/component.rbs +0 -41
  345. data/sig/hakumi_components/base_component.rbs +0 -82
  346. data/sig/hakumi_components/breadcrumb/component.rbs +0 -21
  347. data/sig/hakumi_components/breadcrumb/item/component.rbs +0 -36
  348. data/sig/hakumi_components/button/component.rbs +0 -56
  349. data/sig/hakumi_components/calendar/component.rbs +0 -41
  350. data/sig/hakumi_components/card/component.rbs +0 -50
  351. data/sig/hakumi_components/card/grid/component.rbs +0 -21
  352. data/sig/hakumi_components/card/meta/component.rbs +0 -25
  353. data/sig/hakumi_components/carousel/component.rbs +0 -88
  354. data/sig/hakumi_components/cascader/component.rbs +0 -52
  355. data/sig/hakumi_components/checkbox/component.rbs +0 -46
  356. data/sig/hakumi_components/checkbox/group/component.rbs +0 -34
  357. data/sig/hakumi_components/collapse/component.rbs +0 -57
  358. data/sig/hakumi_components/collapse/panel/component.rbs +0 -47
  359. data/sig/hakumi_components/color_picker/component.rbs +0 -80
  360. data/sig/hakumi_components/concerns/form_field.rbs +0 -89
  361. data/sig/hakumi_components/container/component.rbs +0 -37
  362. data/sig/hakumi_components/date_picker/component.rbs +0 -72
  363. data/sig/hakumi_components/date_picker/range_picker.rbs +0 -68
  364. data/sig/hakumi_components/date_picker/shared_rendering.rbs +0 -41
  365. data/sig/hakumi_components/descriptions/component.rbs +0 -59
  366. data/sig/hakumi_components/descriptions/item/component.rbs +0 -31
  367. data/sig/hakumi_components/divider/component.rbs +0 -39
  368. data/sig/hakumi_components/drawer/component.rbs +0 -66
  369. data/sig/hakumi_components/dropdown/component.rbs +0 -45
  370. data/sig/hakumi_components/dropdown/divider/component.rbs +0 -11
  371. data/sig/hakumi_components/dropdown/item/component.rbs +0 -45
  372. data/sig/hakumi_components/empty/component.rbs +0 -40
  373. data/sig/hakumi_components/flex/component.rbs +0 -47
  374. data/sig/hakumi_components/float_button/back_top/component.rbs +0 -45
  375. data/sig/hakumi_components/float_button/component.rbs +0 -80
  376. data/sig/hakumi_components/float_button/group/component.rbs +0 -95
  377. data/sig/hakumi_components/float_button/group_cluster/component.rbs +0 -60
  378. data/sig/hakumi_components/form/item/component.rbs +0 -39
  379. data/sig/hakumi_components/form_builder.rbs +0 -37
  380. data/sig/hakumi_components/grid/col/component.rbs +0 -50
  381. data/sig/hakumi_components/grid/row/component.rbs +0 -46
  382. data/sig/hakumi_components/icon/component.rbs +0 -56
  383. data/sig/hakumi_components/image/component.rbs +0 -56
  384. data/sig/hakumi_components/image/preview_group/component.rbs +0 -28
  385. data/sig/hakumi_components/input/component.rbs +0 -71
  386. data/sig/hakumi_components/input/password/component.rbs +0 -27
  387. data/sig/hakumi_components/input/text_area/component.rbs +0 -42
  388. data/sig/hakumi_components/input_number/component.rbs +0 -85
  389. data/sig/hakumi_components/layout/component.rbs +0 -21
  390. data/sig/hakumi_components/layout/content/component.rbs +0 -19
  391. data/sig/hakumi_components/layout/footer/component.rbs +0 -19
  392. data/sig/hakumi_components/layout/header/component.rbs +0 -19
  393. data/sig/hakumi_components/layout/sider/component.rbs +0 -19
  394. data/sig/hakumi_components/mentions/component.rbs +0 -75
  395. data/sig/hakumi_components/menu/component.rbs +0 -52
  396. data/sig/hakumi_components/menu/divider/component.rbs +0 -11
  397. data/sig/hakumi_components/menu/group/component.rbs +0 -20
  398. data/sig/hakumi_components/menu/item/component.rbs +0 -42
  399. data/sig/hakumi_components/menu/sub_menu/component.rbs +0 -37
  400. data/sig/hakumi_components/message/component.rbs +0 -50
  401. data/sig/hakumi_components/modal/component.rbs +0 -76
  402. data/sig/hakumi_components/modal/confirm/component.rbs +0 -32
  403. data/sig/hakumi_components/modal/error/component.rbs +0 -27
  404. data/sig/hakumi_components/modal/info/component.rbs +0 -27
  405. data/sig/hakumi_components/modal/success/component.rbs +0 -27
  406. data/sig/hakumi_components/modal/warning/component.rbs +0 -27
  407. data/sig/hakumi_components/notification/component.rbs +0 -64
  408. data/sig/hakumi_components/pagination/component.rbs +0 -113
  409. data/sig/hakumi_components/popconfirm/component.rbs +0 -52
  410. data/sig/hakumi_components/popover/component.rbs +0 -66
  411. data/sig/hakumi_components/progress/component.rbs +0 -201
  412. data/sig/hakumi_components/qr_code/component.rbs +0 -111
  413. data/sig/hakumi_components/radio/component.rbs +0 -55
  414. data/sig/hakumi_components/radio/group/component.rbs +0 -71
  415. data/sig/hakumi_components/rails/attribute_introspection.rbs +0 -16
  416. data/sig/hakumi_components/rails/validation_introspection.rbs +0 -18
  417. data/sig/hakumi_components/rails/validation_mapper.rbs +0 -53
  418. data/sig/hakumi_components/rails.rbs +0 -6
  419. data/sig/hakumi_components/rate/component.rbs +0 -56
  420. data/sig/hakumi_components/result/component.rbs +0 -65
  421. data/sig/hakumi_components/segmented/component.rbs +0 -72
  422. data/sig/hakumi_components/select/component.rbs +0 -73
  423. data/sig/hakumi_components/skeleton/avatar/component.rbs +0 -23
  424. data/sig/hakumi_components/skeleton/button/component.rbs +0 -24
  425. data/sig/hakumi_components/skeleton/component.rbs +0 -76
  426. data/sig/hakumi_components/skeleton/image/component.rbs +0 -22
  427. data/sig/hakumi_components/skeleton/input/component.rbs +0 -23
  428. data/sig/hakumi_components/skeleton/node/component.rbs +0 -21
  429. data/sig/hakumi_components/slider/component.rbs +0 -85
  430. data/sig/hakumi_components/space/compact/component.rbs +0 -21
  431. data/sig/hakumi_components/space/component.rbs +0 -47
  432. data/sig/hakumi_components/spin/component.rbs +0 -77
  433. data/sig/hakumi_components/splitter/component.rbs +0 -27
  434. data/sig/hakumi_components/splitter/panel/component.rbs +0 -36
  435. data/sig/hakumi_components/statistic/component.rbs +0 -97
  436. data/sig/hakumi_components/steps/component.rbs +0 -82
  437. data/sig/hakumi_components/steps/item/component.rbs +0 -29
  438. data/sig/hakumi_components/switch/component.rbs +0 -52
  439. data/sig/hakumi_components/table/column/component.rbs +0 -57
  440. data/sig/hakumi_components/table/column_group/component.rbs +0 -20
  441. data/sig/hakumi_components/table/component.rbs +0 -279
  442. data/sig/hakumi_components/table/concerns/columns.rbs +0 -95
  443. data/sig/hakumi_components/table/concerns/editable.rbs +0 -40
  444. data/sig/hakumi_components/table/concerns/ellipsis.rbs +0 -27
  445. data/sig/hakumi_components/table/concerns/fixed_columns.rbs +0 -33
  446. data/sig/hakumi_components/tabs/component.rbs +0 -66
  447. data/sig/hakumi_components/tabs/item/component.rbs +0 -29
  448. data/sig/hakumi_components/tag/component.rbs +0 -86
  449. data/sig/hakumi_components/tag/group/component.rbs +0 -24
  450. data/sig/hakumi_components/time_picker/component.rbs +0 -72
  451. data/sig/hakumi_components/timeline/component.rbs +0 -61
  452. data/sig/hakumi_components/timeline/item/component.rbs +0 -70
  453. data/sig/hakumi_components/tooltip/component.rbs +0 -73
  454. data/sig/hakumi_components/tour/component.rbs +0 -84
  455. data/sig/hakumi_components/transfer/component.rbs +0 -75
  456. data/sig/hakumi_components/tree/component.rbs +0 -126
  457. data/sig/hakumi_components/tree_select/component.rbs +0 -122
  458. data/sig/hakumi_components/typography/base_component.rbs +0 -57
  459. data/sig/hakumi_components/typography/link/component.rbs +0 -28
  460. data/sig/hakumi_components/typography/paragraph/component.rbs +0 -13
  461. data/sig/hakumi_components/typography/text/component.rbs +0 -10
  462. data/sig/hakumi_components/typography/title/component.rbs +0 -28
  463. data/sig/hakumi_components/upload/component.rbs +0 -78
  464. data/sig/hakumi_components.rbs +0 -96
  465. data/sig/rails/active_model/validations/comparison_validator.rbs +0 -6
  466. data/sig/rails.rbs +0 -18
  467. data/sig/view_component/base.rbs +0 -28
@@ -1,57 +1,58 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module HakumiComponents
4
5
  module Table
5
6
  module Concerns
6
- # Text ellipsis and tooltip handling for Table cells
7
7
  module Ellipsis
8
8
  extend ActiveSupport::Concern
9
+ extend T::Sig
9
10
 
10
11
  private
11
12
 
13
+ sig { params(column: HakumiComponents::Table::ColumnDefinition).returns(T.nilable(HakumiComponents::Table::EllipsisConfig)) }
12
14
  def ellipsis_config(column)
13
- column[:ellipsis]
15
+ value = column.ellipsis
16
+ value.is_a?(HakumiComponents::Table::EllipsisConfig) ? value : nil
14
17
  end
15
18
 
19
+ sig { params(option: HakumiComponents::Table::EllipsisConfig::Input).returns(T.nilable(HakumiComponents::Table::EllipsisConfig)) }
16
20
  def normalize_ellipsis_option(option)
17
- return nil if option.nil? || option == false
18
-
19
- if option == true
20
- { show_title: true }
21
- elsif option.is_a?(Hash)
22
- normalized = option.deep_symbolize_keys
23
- normalized[:tooltip] = normalize_ellipsis_tooltip_option(normalized[:tooltip])
24
- normalized.compact.presence
25
- else
26
- { tooltip: normalize_ellipsis_tooltip_option(option) }
27
- end
21
+ HakumiComponents::Table::EllipsisConfig.from_input(option)
28
22
  end
29
23
 
30
- def normalize_ellipsis_tooltip_option(option)
31
- return nil if option.nil? || option == false
32
- return {} if option == true
33
- return { title: option } if option.is_a?(String)
34
- return option.deep_symbolize_keys if option.is_a?(Hash)
35
-
36
- nil
24
+ sig do
25
+ params(
26
+ config: T.nilable(HakumiComponents::Table::EllipsisConfig),
27
+ raw_value: HakumiComponents::Table::RowRecord::Source,
28
+ content_fragment: T.untyped
29
+ ).returns(T.nilable(String))
37
30
  end
38
-
39
31
  def ellipsis_title(config, raw_value, content_fragment)
40
- return nil unless config&.dig(:show_title)
32
+ return nil unless config&.show_title
41
33
 
42
- value = raw_value.presence || content_fragment
43
- value = value.to_s if value.respond_to?(:to_s)
44
- value.present? ? value : nil
34
+ value = raw_value.nil? ? content_fragment : raw_value
35
+ return nil if value.nil?
36
+
37
+ text = value.to_s
38
+ text.empty? ? nil : text
45
39
  end
46
40
 
41
+ sig do
42
+ params(
43
+ config: T.nilable(HakumiComponents::Table::EllipsisConfig),
44
+ raw_value: HakumiComponents::Table::RowRecord::Source,
45
+ row: HakumiComponents::Table::RowRecord::Source,
46
+ row_index: Integer
47
+ ).returns(T.nilable(HakumiComponents::Tooltip::Component))
48
+ end
47
49
  def ellipsis_tooltip_component(config, raw_value, row, row_index)
48
- tooltip = config&.dig(:tooltip)
49
- return nil unless tooltip
50
+ return nil unless config.is_a?(HakumiComponents::Table::EllipsisConfig::WithTooltip)
50
51
 
51
- options = tooltip.deep_dup
52
- title = options.delete(:title)
52
+ options = config.tooltip.options.deep_dup
53
+ title = config.tooltip.title
53
54
  title ||= raw_value
54
- title = title.call(row, row_index) if title.respond_to?(:call)
55
+ title = title.call(row, row_index) if title.is_a?(Proc)
55
56
  title = title.to_s if title.respond_to?(:to_s)
56
57
  return nil if title.blank?
57
58
 
@@ -1,74 +1,81 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module HakumiComponents
4
5
  module Table
5
6
  module Concerns
6
- # Fixed (sticky) column positioning for Table component
7
7
  module FixedColumns
8
8
  extend ActiveSupport::Concern
9
+ extend T::Sig
9
10
 
10
- # Check if table has any fixed columns
11
+ include AttributeHelpers
12
+
13
+ sig { returns(T::Boolean) }
11
14
  def fixed_columns?
12
15
  fixed_offsets.present?
13
16
  end
14
17
 
15
18
  private
16
19
 
20
+ sig { returns(T::Hash[Types::HtmlKey, HakumiComponents::Table::FixedOffset]) }
17
21
  def fixed_offsets
22
+ @fixed_offsets = T.let(@fixed_offsets, T.nilable(T::Hash[Types::HtmlKey, HakumiComponents::Table::FixedOffset])) if defined?(@fixed_offsets)
23
+ @fixed_offsets = T.let(nil, T.nilable(T::Hash[Types::HtmlKey, HakumiComponents::Table::FixedOffset])) unless defined?(@fixed_offsets)
18
24
  @fixed_offsets ||= {}
19
25
  end
20
26
 
21
- # Applies fixed column positioning attributes to cell
27
+ sig { params(attrs: Types::HtmlAttributes, column: HakumiComponents::Table::ColumnDefinition, header: T::Boolean).void }
22
28
  def apply_fixed_column_attributes!(attrs, column, header: false)
23
- info = fixed_offsets[column[:key]]
29
+ info = fixed_offsets[column.key]
24
30
  return unless info
25
31
 
26
- attrs[:class] = [ attrs[:class], "hakumi-table-cell-fixed", "hakumi-table-cell-fixed-#{info[:side]}" ].compact.join(" ")
32
+ attrs[:class] = [ attrs[:class], "hakumi-table-cell-fixed", "hakumi-table-cell-fixed-#{info.side}" ].compact.join(" ")
27
33
 
28
34
  style_parts = Array.new
29
35
  style_parts << attrs[:style] if attrs[:style].present?
30
36
  style_parts << "position: sticky"
31
- style_parts << "#{info[:side]}: #{info[:offset]}px"
37
+ style_parts << "#{info.side}: #{info.offset}px"
32
38
  style_parts << "z-index: #{header ? 3 : 2}"
33
39
  attrs[:style] = style_parts.compact.join("; ")
34
40
 
35
- attrs[:data] ||= {}
36
- attrs[:data][:fixed] = info[:side]
41
+ data_attrs = existing_data_attributes(attrs)
42
+ data_attrs[:fixed] = info.side
43
+ attrs[:data] = data_attrs
37
44
  end
38
45
 
39
- # Compute fixed column offsets from left and right
46
+ sig { params(leaf_columns: T::Array[HakumiComponents::Table::ColumnDefinition]).void }
40
47
  def compute_fixed_offsets(leaf_columns)
41
48
  @fixed_offsets = {}
42
49
  return if leaf_columns.blank?
43
50
 
44
- # Calculate left fixed columns
45
- left_offset = 0
51
+ left_offset = T.let(0.0, Float)
46
52
  leaf_columns.each do |column|
47
- next unless column[:fixed] == :left
53
+ next unless column.fixed == :left
48
54
 
49
55
  width = fixed_column_width!(column)
50
- @fixed_offsets[column[:key]] = { side: :left, offset: left_offset }
56
+ @fixed_offsets[column.key] = HakumiComponents::Table::FixedOffset.new(side: :left, offset: left_offset)
51
57
  left_offset += width
52
58
  end
53
59
 
54
- # Calculate right fixed columns (from right to left)
55
- right_offset = 0
60
+ right_offset = T.let(0.0, Float)
56
61
  leaf_columns.reverse_each do |column|
57
- next unless column[:fixed] == :right
62
+ next unless column.fixed == :right
58
63
 
59
64
  width = fixed_column_width!(column)
60
- @fixed_offsets[column[:key]] = { side: :right, offset: right_offset }
65
+ @fixed_offsets[column.key] = HakumiComponents::Table::FixedOffset.new(side: :right, offset: right_offset)
61
66
  right_offset += width
62
67
  end
63
68
  end
64
69
 
70
+ sig { params(column: HakumiComponents::Table::ColumnDefinition).returns(Float) }
65
71
  def fixed_column_width!(column)
66
- width = numeric_width(column[:width])
72
+ width = numeric_width(column.width)
67
73
  return width if width&.positive?
68
74
 
69
- raise ArgumentError, "Column #{column[:key] || column[:data_index] || column[:title]} must define a pixel width when fixed"
75
+ raise ArgumentError, "Column #{column.key} must define a pixel width when fixed"
70
76
  end
71
77
 
78
+ sig { params(value: T.nilable(T.any(String, Numeric))).returns(T.nilable(Float)) }
72
79
  def numeric_width(value)
73
80
  case value
74
81
  when Integer, Float
@@ -0,0 +1,365 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module HakumiComponents
5
+ module Table
6
+ module Concerns
7
+ module SurfaceRendering
8
+ extend ActiveSupport::Concern
9
+ extend T::Sig
10
+ extend T::Helpers
11
+
12
+ abstract!
13
+
14
+ requires_ancestor { HakumiComponents::BaseComponent }
15
+ requires_ancestor { HakumiComponents::Table::Concerns::Columns }
16
+ requires_ancestor { HakumiComponents::Table::Concerns::Editable }
17
+ requires_ancestor { HakumiComponents::Table::Concerns::FixedColumns }
18
+
19
+ TableDisplayRow = T.type_alias { { row: HakumiComponents::Table::RowRecord, depth: Integer } }
20
+ RowSource = T.type_alias { HakumiComponents::Table::RowRecord::Source }
21
+ ScrollValue = T.type_alias { T.nilable(String) }
22
+ TableContent = T.type_alias { T.nilable(T.any(Types::Renderable, Proc)) }
23
+ PaginationValue = T.type_alias { HakumiComponents::Table::Configs::Pagination::Value }
24
+
25
+ sig { abstract.returns(T::Array[TableDisplayRow]) }
26
+ def display_rows; end
27
+
28
+ sig { abstract.params(column: HakumiComponents::Table::ColumnDefinition).returns(T.nilable(Symbol)) }
29
+ def default_sort_order(column); end
30
+
31
+ sig { abstract.returns(Symbol) }
32
+ def surface_size; end
33
+
34
+ sig { abstract.returns(T::Boolean) }
35
+ def surface_bordered?; end
36
+
37
+ sig { abstract.returns(T::Boolean) }
38
+ def surface_sticky?; end
39
+
40
+ sig { abstract.returns(ScrollValue) }
41
+ def surface_scroll_x; end
42
+
43
+ sig { abstract.returns(ScrollValue) }
44
+ def surface_scroll_y; end
45
+
46
+ sig { abstract.returns(Types::HtmlAttributes) }
47
+ def surface_html_options; end
48
+
49
+ sig { abstract.returns(T.nilable(HakumiComponents::Table::Configs::RowSelection)) }
50
+ def surface_row_selection; end
51
+
52
+ sig { abstract.returns(T::Array[Symbol]) }
53
+ def surface_sort_directions; end
54
+
55
+ sig { abstract.returns(T::Boolean) }
56
+ def surface_filter_on_close?; end
57
+
58
+ sig { abstract.returns(Symbol) }
59
+ def surface_filter_mode; end
60
+
61
+ sig { abstract.returns(HakumiComponents::Table::DefinitionTypes::SearchValue) }
62
+ def surface_filter_search; end
63
+
64
+ sig { abstract.returns(T.nilable(HakumiComponents::Table::Configs::Editable)) }
65
+ def surface_editable; end
66
+
67
+ sig { abstract.returns(T.nilable(HakumiComponents::Table::Configs::RowDrag)) }
68
+ def surface_row_drag; end
69
+
70
+ sig { abstract.returns(T::Boolean) }
71
+ def surface_column_drag?; end
72
+
73
+ sig { abstract.returns(PaginationValue) }
74
+ def surface_pagination; end
75
+
76
+ sig { abstract.returns(T.nilable(String)) }
77
+ def surface_data_url; end
78
+
79
+ sig { abstract.returns(TableContent) }
80
+ def surface_empty_text; end
81
+
82
+ sig { abstract.returns(TableContent) }
83
+ def surface_summary; end
84
+
85
+ sig { returns(String) }
86
+ def table_classes
87
+ T.unsafe(self).class_names(
88
+ "table",
89
+ {
90
+ size: surface_size,
91
+ bordered: surface_bordered?,
92
+ empty: display_rows.empty?,
93
+ sticky: surface_sticky?,
94
+ scroll_x: surface_scroll_x.present?,
95
+ scroll_y: surface_scroll_y.present?,
96
+ fixed: T.unsafe(self).fixed_columns?
97
+ },
98
+ T.unsafe(self).html_classes(surface_html_options)
99
+ )
100
+ end
101
+
102
+ sig { returns(Types::HtmlAttributes) }
103
+ def table_container_attributes
104
+ attrs = T.let({
105
+ class: container_classes,
106
+ data: { "hakumi--table-target": "scrollContainer" }
107
+ }, Types::HtmlAttributes)
108
+ styles = scroll_styles
109
+ attrs[:style] = styles if styles.present?
110
+ attrs
111
+ end
112
+
113
+ sig { returns(Types::HtmlAttributes) }
114
+ def table_attributes
115
+ attrs = T.let({ class: "hakumi-table-table" }, Types::HtmlAttributes)
116
+ attrs[:style] = table_style if table_style.present?
117
+ attrs
118
+ end
119
+
120
+ sig { returns(String) }
121
+ def container_classes
122
+ T.unsafe(self).class_names(
123
+ "table-container",
124
+ {
125
+ scroll_x: surface_scroll_x.present?,
126
+ scroll_y: surface_scroll_y.present?
127
+ }
128
+ )
129
+ end
130
+
131
+ sig { returns(Types::HtmlAttributes) }
132
+ def wrapper_attributes
133
+ T.unsafe(self).merge_attributes({ class: table_classes, data: wrapper_data_attributes }, surface_html_options)
134
+ end
135
+
136
+ sig { returns(Types::Renderable) }
137
+ def empty_state
138
+ empty_text = surface_empty_text
139
+ if empty_text
140
+ return T.unsafe(self).render(empty_text) if empty_text.is_a?(ViewComponent::Base)
141
+ return T.unsafe(self).render(empty_text) if empty_text.is_a?(ViewComponent::Slot)
142
+ return empty_text.call if empty_text.is_a?(Proc)
143
+
144
+ empty_text
145
+ else
146
+ T.unsafe(self).render(HakumiComponents::Empty::Component.new)
147
+ end
148
+ end
149
+
150
+ sig { returns(T.nilable(ViewComponent::Base)) }
151
+ def pagination_component
152
+ pagination = surface_pagination
153
+ return nil unless pagination
154
+ return nil if surface_data_url
155
+ return pagination if pagination.is_a?(ViewComponent::Base)
156
+
157
+ pagination.build_component
158
+ end
159
+
160
+ sig { returns(T.nilable(HakumiComponents::Pagination::Component)) }
161
+ def ajax_pagination_component
162
+ pagination = surface_pagination
163
+ return nil unless surface_data_url && pagination.is_a?(HakumiComponents::Table::Configs::Pagination)
164
+
165
+ pagination.build_ajax_component
166
+ end
167
+
168
+ sig { returns(Types::RenderedContent) }
169
+ def summary_content
170
+ summary = surface_summary
171
+ return nil unless summary
172
+
173
+ if summary.is_a?(Proc)
174
+ rows = display_rows.map { |row_data| row_data[:row] }
175
+ summary.call(rows)
176
+ else
177
+ summary
178
+ end
179
+ end
180
+
181
+ sig { returns(String) }
182
+ def scroll_styles
183
+ styles = T.let([], T::Array[String])
184
+ scroll_x = surface_scroll_x
185
+ scroll_y = surface_scroll_y
186
+ styles << "overflow-x: auto" if scroll_x
187
+ if scroll_y
188
+ styles << "max-height: #{T.unsafe(self).__send__(:dimension_to_css, scroll_y)}"
189
+ styles << "overflow-y: auto"
190
+ end
191
+ styles.join("; ")
192
+ end
193
+
194
+ sig { returns(T.nilable(String)) }
195
+ def table_style
196
+ scroll_x = surface_scroll_x
197
+ return nil unless scroll_x
198
+
199
+ "min-width: #{T.unsafe(self).__send__(:dimension_to_css, scroll_x)}"
200
+ end
201
+
202
+ sig { returns(T::Boolean) }
203
+ def selection_actions?
204
+ surface_row_selection&.selections_enabled == true
205
+ end
206
+
207
+ sig { returns(T::Boolean) }
208
+ def selection_all_enabled?
209
+ surface_row_selection&.type == :checkbox
210
+ end
211
+
212
+ sig { params(column: HakumiComponents::Table::ColumnDefinition).returns(T::Array[HakumiComponents::Table::DefinitionTypes::DefinitionHash]) }
213
+ def header_filter_options(column)
214
+ Kernel.Array(column.filters)
215
+ end
216
+
217
+ sig { params(column: HakumiComponents::Table::ColumnDefinition).returns(T::Boolean) }
218
+ def column_filter_multiple?(column)
219
+ column.filter_multiple
220
+ end
221
+
222
+ sig { returns(T.nilable(T::Hash[Symbol, String])) }
223
+ def current_sort_state
224
+ sorted_column = T.unsafe(self).__send__(:leaf_columns).find { |column| default_sort_order(column).present? }
225
+ return nil unless sorted_column
226
+
227
+ field = sorted_column.key.to_s
228
+ order = default_sort_order(sorted_column)
229
+ return nil unless order
230
+
231
+ { field: field, order: order.to_s }
232
+ end
233
+
234
+ sig { returns(T::Hash[Symbol, T::Boolean]) }
235
+ def selection_header_state
236
+ total = display_rows.size
237
+ selected = surface_row_selection&.selected_row_keys&.size || 0
238
+ {
239
+ checked: total.positive? && selected == total,
240
+ indeterminate: selected.positive? && selected < total
241
+ }
242
+ end
243
+
244
+ sig { returns(String) }
245
+ def select_all_text
246
+ T.unsafe(self).t_default(:select_all, default: "Select all")
247
+ end
248
+
249
+ sig { returns(String) }
250
+ def invert_text
251
+ T.unsafe(self).t_default(:invert, default: "Invert")
252
+ end
253
+
254
+ sig { returns(String) }
255
+ def clear_text
256
+ T.unsafe(self).t_default(:clear, default: "Clear")
257
+ end
258
+
259
+ sig { returns(String) }
260
+ def search_placeholder_text
261
+ T.unsafe(self).t_default(:search_placeholder, default: "Search")
262
+ end
263
+
264
+ sig { returns(String) }
265
+ def reset_text
266
+ T.unsafe(self).t_default(:reset, default: "Reset")
267
+ end
268
+
269
+ private
270
+
271
+ sig { returns(Types::DataAttributes) }
272
+ def wrapper_data_attributes
273
+ data_attributes = T.let(base_wrapper_data_attributes, Types::DataAttributes)
274
+ apply_wrapper_editable_data_attributes!(data_attributes)
275
+ apply_wrapper_pagination_data_attributes!(data_attributes)
276
+ apply_wrapper_drag_data_attributes!(data_attributes)
277
+ apply_wrapper_ajax_data_attributes!(data_attributes)
278
+ data_attributes
279
+ end
280
+
281
+ sig { returns(Types::DataAttributes) }
282
+ def base_wrapper_data_attributes
283
+ row_selection = surface_row_selection
284
+ {
285
+ controller: "hakumi--table",
286
+ "hakumi--table-selection-type-value": row_selection&.type,
287
+ "hakumi--table-selected-row-keys-value": row_selection&.selected_row_keys&.to_json || [].to_json,
288
+ "hakumi--table-preserve-selected-row-keys-value": row_selection&.preserve_selected_row_keys || false,
289
+ "hakumi--table-sort-directions-value": surface_sort_directions.join(","),
290
+ "hakumi--table-filter-on-close-value": surface_filter_on_close?,
291
+ "hakumi--table-filter-mode-value": surface_filter_mode,
292
+ "hakumi--table-filter-search-value": surface_filter_search
293
+ }
294
+ end
295
+
296
+ sig { params(data_attributes: Types::DataAttributes).void }
297
+ def apply_wrapper_editable_data_attributes!(data_attributes)
298
+ editable = surface_editable
299
+ editable_json = editable&.to_h&.to_json
300
+ data_attributes["hakumi--table-editable-config-value"] = editable_json if editable_json
301
+ end
302
+
303
+ sig { params(data_attributes: Types::DataAttributes).void }
304
+ def apply_wrapper_pagination_data_attributes!(data_attributes)
305
+ pagination = surface_pagination
306
+ return unless pagination.is_a?(HakumiComponents::Table::Configs::Pagination)
307
+
308
+ if pagination.href
309
+ data_attributes["hakumi--table-href-value"] = pagination.href
310
+ data_attributes["hakumi--table-server-side-value"] = true
311
+ data_attributes["pagination-state"] = true
312
+ apply_wrapper_current_sort_data_attributes!(data_attributes)
313
+ end
314
+
315
+ data_attributes["hakumi--table-turbo-frame-value"] = pagination.turbo_frame if pagination.turbo_frame
316
+ data_attributes["hakumi--table-sort-field-param-value"] = pagination.sort_field_param if pagination.sort_field_param
317
+ data_attributes["hakumi--table-sort-order-param-value"] = pagination.sort_order_param if pagination.sort_order_param
318
+ end
319
+
320
+ sig { params(data_attributes: Types::DataAttributes).void }
321
+ def apply_wrapper_current_sort_data_attributes!(data_attributes)
322
+ current_sort = current_sort_state
323
+ return unless current_sort
324
+
325
+ data_attributes["sort-field"] = current_sort[:field]
326
+ data_attributes["sort-order"] = current_sort[:order]
327
+ end
328
+
329
+ sig { params(data_attributes: Types::DataAttributes).void }
330
+ def apply_wrapper_drag_data_attributes!(data_attributes)
331
+ row_drag = surface_row_drag
332
+ if row_drag
333
+ data_attributes["hakumi--table-row-drag-value"] = row_drag.enabled
334
+ data_attributes["hakumi--table-row-drag-handle-value"] = row_drag.handle
335
+ end
336
+ data_attributes["hakumi--table-column-drag-value"] = true if surface_column_drag?
337
+ end
338
+
339
+ sig { params(data_attributes: Types::DataAttributes).void }
340
+ def apply_wrapper_ajax_data_attributes!(data_attributes)
341
+ data_url = surface_data_url
342
+ pagination = surface_pagination
343
+ return unless data_url
344
+
345
+ data_attributes["hakumi--table-data-url-value"] = data_url
346
+ data_attributes["hakumi--table-columns-config-value"] = columns_config_json
347
+ if pagination.is_a?(HakumiComponents::Table::Configs::Pagination)
348
+ data_attributes["hakumi--table-page-size-value"] = pagination.page_size
349
+ end
350
+ end
351
+
352
+ sig { returns(String) }
353
+ def columns_config_json
354
+ T.unsafe(self).__send__(:leaf_columns).map do |column|
355
+ {
356
+ key: column.key,
357
+ dataIndex: column.data_index,
358
+ sorter: !column.sorter.nil?
359
+ }.compact
360
+ end.to_json
361
+ end
362
+ end
363
+ end
364
+ end
365
+ end