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,15 +1,41 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module HakumiComponents
4
5
  module Radio
5
6
  module Group
6
7
  class Component < HakumiComponents::BaseComponent
8
+ extend T::Sig
9
+
7
10
  include HakumiComponents::Concerns::FormField
8
11
 
9
- SIZES = [ :small, :middle, :large ].freeze
10
- VARIANTS = [ :default, :button, :solid ].freeze
11
- DIRECTIONS = [ :horizontal, :vertical ].freeze
12
+ OptionHash = T.type_alias do
13
+ T::Hash[T.any(Symbol, String), T.nilable(T.any(String, Symbol, Numeric, T::Boolean))]
14
+ end
15
+ OptionInput = T.type_alias do
16
+ T.any(HakumiComponents::Radio::Group::Option, OptionHash, String, Symbol, Numeric)
17
+ end
12
18
 
19
+ VARIANTS = T.let([ :default, :button, :solid ].freeze, T::Array[Symbol])
20
+ DIRECTIONS = T.let([ :horizontal, :vertical ].freeze, T::Array[Symbol])
21
+
22
+ sig do
23
+ params(
24
+ name: T.nilable(Types::FormFieldName),
25
+ value: HakumiComponents::Types::FormFieldScalar,
26
+ options: T::Array[OptionInput],
27
+ label: T.nilable(String),
28
+ caption: T.nilable(String),
29
+ variant: Symbol,
30
+ direction: Symbol,
31
+ size: Symbol,
32
+ disabled: T::Boolean,
33
+ standalone: T::Boolean,
34
+ required: T::Boolean,
35
+ errors: Types::FormFieldErrors,
36
+ html_options: Types::HtmlAttributeValue
37
+ ).void
38
+ end
13
39
  def initialize(
14
40
  name: nil,
15
41
  value: nil,
@@ -18,30 +44,40 @@ module HakumiComponents
18
44
  caption: nil,
19
45
  variant: :default,
20
46
  direction: :horizontal,
21
- size: :middle,
47
+ size: :default,
22
48
  disabled: false,
23
49
  standalone: true,
24
50
  required: false,
25
51
  errors: [],
26
52
  **html_options
27
53
  )
28
- @name = name || generate_id("radio_group")
29
- @value = value
30
- @options = normalize_options(options)
54
+ @name = T.let(name || generate_id("radio_group"), Types::FormFieldName)
55
+ @value = T.let(value, HakumiComponents::Types::FormFieldScalar)
56
+ @options = T.let(normalize_options(options), T::Array[HakumiComponents::Radio::Group::Option])
31
57
  @label = label
32
58
  @caption = caption
33
- @variant = variant.to_sym
34
- @direction = direction.to_sym
59
+ @variant = T.let(variant.to_sym, Symbol)
60
+ @direction = T.let(direction.to_sym, Symbol)
35
61
  @size = size
36
62
  @disabled = disabled
37
63
  @standalone = standalone
38
64
  @required = required
39
- @errors = Array(errors)
40
- @html_options = html_options
65
+ @errors = T.let(errors, Types::FormFieldErrors)
66
+ @html_options = T.let(html_options, Types::HtmlAttributes)
67
+ initialize_form_field_contract!(
68
+ name: @name,
69
+ label: @label,
70
+ caption: @caption,
71
+ errors: @errors,
72
+ standalone: @standalone,
73
+ required: @required,
74
+ html_options: @html_options
75
+ )
41
76
 
42
77
  validate_props!
43
78
  end
44
79
 
80
+ sig { returns(Types::HtmlAttributes) }
45
81
  def wrapper_attributes
46
82
  attrs = {
47
83
  class: wrapper_classes,
@@ -52,75 +88,88 @@ module HakumiComponents
52
88
  merge_attributes(attrs, @html_options)
53
89
  end
54
90
 
91
+ sig { returns(T::Array[HakumiComponents::Radio::Group::Option]) }
55
92
  def normalized_options
56
93
  @options
57
94
  end
58
95
 
96
+ sig { params(option_value: HakumiComponents::Types::FormFieldScalar).returns(T::Boolean) }
59
97
  def option_checked?(option_value)
60
98
  return false if @value.nil?
61
99
 
62
100
  @value.to_s == option_value.to_s
63
101
  end
64
102
 
103
+ sig { params(option: HakumiComponents::Radio::Group::Option).returns(T::Boolean) }
65
104
  def option_disabled?(option)
66
- @disabled || option[:disabled]
105
+ @disabled || option.disabled
67
106
  end
68
107
 
108
+ sig { params(option: HakumiComponents::Radio::Group::Option).returns(String) }
69
109
  def button_wrapper_classes(option)
70
110
  modifiers = {
71
- checked: option_checked?(option[:value]),
111
+ checked: option_checked?(option.value),
72
112
  disabled: option_disabled?(option)
73
113
  }
74
- modifiers[@size] = true if @size != :middle
114
+ modifiers[@size] = true if @size != :default
75
115
 
76
116
  class_names("radio-button-wrapper", modifiers)
77
117
  end
78
118
 
119
+ sig { params(index: Integer).returns(String) }
79
120
  def option_id(index)
80
- "#{@name}_#{index}"
121
+ "#{form_field_name}_#{index}"
81
122
  end
82
123
 
124
+ sig { returns(T::Boolean) }
83
125
  def button_group?
84
126
  @variant == :button || @variant == :solid
85
127
  end
86
128
 
87
129
  private
88
130
 
131
+ sig { returns(String) }
89
132
  def wrapper_classes
90
133
  modifiers = {
91
134
  button: button_group?,
92
135
  vertical: @direction == :vertical,
93
136
  disabled: @disabled
94
137
  }
95
- modifiers[@size] = true if @size != :middle
138
+ modifiers[@size] = true if @size != :default
96
139
  modifiers[:solid] = true if @variant == :solid
97
140
  modifiers[:outline] = true if @variant == :button
98
141
 
99
142
  class_names("radio-group", modifiers)
100
143
  end
101
144
 
145
+ sig { params(options: T::Array[OptionInput]).returns(T::Array[HakumiComponents::Radio::Group::Option]) }
102
146
  def normalize_options(options)
103
- Array(options).map do |option|
147
+ options.map do |option|
148
+ next option if option.is_a?(HakumiComponents::Radio::Group::Option)
149
+
104
150
  if option.is_a?(Hash)
105
- option = option.deep_symbolize_keys if option.respond_to?(:deep_symbolize_keys)
106
- label_value = option[:label]
107
- value_value = option[:value] || label_value
151
+ label_value = option[:label] || option["label"]
152
+ value_value = option[:value] || option["value"] || label_value
108
153
 
109
154
  raise ArgumentError, "Option must have :label key" if label_value.nil?
110
155
 
111
- {
112
- label: label_value,
156
+ HakumiComponents::Radio::Group::Option.new(
157
+ label: normalize_option_label(label_value),
113
158
  value: value_value,
114
- disabled: !!option[:disabled]
115
- }
116
- elsif option.is_a?(String)
117
- { label: option, value: option, disabled: false }
159
+ disabled: !!(option[:disabled] || option["disabled"])
160
+ )
118
161
  else
119
- raise ArgumentError, "Option must be a Hash with :label and :value, or a String. Got: #{option.class}"
162
+ HakumiComponents::Radio::Group::Option.new(label: option, value: option, disabled: false)
120
163
  end
121
164
  end
122
165
  end
123
166
 
167
+ sig { params(label: T.any(String, Symbol, Numeric, T::Boolean)).returns(T.any(String, Symbol, Numeric)) }
168
+ def normalize_option_label(label)
169
+ label == true || label == false ? label.to_s : label
170
+ end
171
+
172
+ sig { void }
124
173
  def validate_props!
125
174
  validate_inclusion!(:size, SIZES)
126
175
  validate_inclusion!(:variant, VARIANTS)
@@ -0,0 +1,43 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module HakumiComponents
5
+ module Radio
6
+ module Group
7
+ class Option
8
+ extend T::Sig
9
+
10
+ sig do
11
+ params(
12
+ label: T.any(String, Symbol, Numeric),
13
+ value: HakumiComponents::Types::FormFieldScalar,
14
+ disabled: T::Boolean
15
+ ).void
16
+ end
17
+ def initialize(label:, value:, disabled: false)
18
+ @label = label
19
+ @value = value
20
+ @disabled = disabled
21
+ end
22
+
23
+ sig { returns(T.any(String, Symbol, Numeric)) }
24
+ attr_reader :label
25
+
26
+ sig { returns(HakumiComponents::Types::FormFieldScalar) }
27
+ attr_reader :value
28
+
29
+ sig { returns(T::Boolean) }
30
+ attr_reader :disabled
31
+
32
+ sig { returns(T::Hash[Symbol, T.any(T.any(String, Symbol, Numeric), HakumiComponents::Types::FormFieldScalar, T::Boolean)]) }
33
+ def to_h
34
+ {
35
+ label: @label,
36
+ value: @value,
37
+ disabled: @disabled
38
+ }
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -29,7 +29,7 @@
29
29
  </div>
30
30
  <% end %>
31
31
 
32
- <% if @standalone %>
32
+ <% if standalone? %>
33
33
  <%= rate_control %>
34
34
  <% else %>
35
35
  <div <%= tag.attributes(form_item_attributes).to_s.html_safe %>>
@@ -1,12 +1,33 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module HakumiComponents
4
5
  module Rate
5
- # Hakumi Rate component
6
- # Supports half selection, clearing, and form integration.
7
6
  class Component < HakumiComponents::BaseComponent
7
+ extend T::Sig
8
+
8
9
  include HakumiComponents::Concerns::FormField
9
10
 
11
+ sig do
12
+ params(
13
+ name: T.nilable(Types::FormFieldName),
14
+ label: T.nilable(String),
15
+ caption: T.nilable(String),
16
+ value: T.nilable(T.any(Numeric, String)),
17
+ default_value: T.any(Numeric, String),
18
+ count: Integer,
19
+ allow_half: T::Boolean,
20
+ allow_clear: T::Boolean,
21
+ disabled: T::Boolean,
22
+ readonly: T::Boolean,
23
+ tooltips: T::Array[String],
24
+ character: Types::Renderable,
25
+ required: T::Boolean,
26
+ standalone: T::Boolean,
27
+ errors: Types::FormFieldErrors,
28
+ html_options: Types::HtmlAttributeValue
29
+ ).void
30
+ end
10
31
  def initialize(
11
32
  name: nil,
12
33
  label: nil,
@@ -25,7 +46,7 @@ module HakumiComponents
25
46
  errors: [],
26
47
  **html_options
27
48
  )
28
- @name = name || generate_id("rate")
49
+ @name = T.let(name || generate_id("rate"), Types::FormFieldName)
29
50
  @label = label
30
51
  @caption = caption
31
52
  @value = value
@@ -35,19 +56,30 @@ module HakumiComponents
35
56
  @allow_clear = allow_clear
36
57
  @disabled = disabled
37
58
  @readonly = readonly
38
- @tooltips = Array(tooltips)
59
+ @tooltips = T.let(tooltips, T::Array[String])
39
60
  @character = character
40
61
  @required = required
41
62
  @standalone = standalone
42
- @errors = Array(errors)
43
- @html_options = html_options
63
+ @errors = T.let(errors, Types::FormFieldErrors)
64
+ @html_options = T.let(html_options, Types::HtmlAttributes)
65
+ initialize_form_field_contract!(
66
+ name: @name,
67
+ label: @label,
68
+ caption: @caption,
69
+ errors: @errors,
70
+ standalone: @standalone,
71
+ required: @required,
72
+ html_options: @html_options
73
+ )
44
74
  end
45
75
 
76
+ sig { returns(Float) }
46
77
  def current_value
47
78
  base_value = @value.nil? ? @default_value : @value
48
79
  base_value.to_f
49
80
  end
50
81
 
82
+ sig { returns(String) }
51
83
  def rate_classes
52
84
  class_names(
53
85
  "rate",
@@ -57,10 +89,11 @@ module HakumiComponents
57
89
  "allow-clear": @allow_clear,
58
90
  "has-value": current_value.positive?
59
91
  },
60
- [ @html_options[:class] ]
92
+ [ html_class_name ]
61
93
  )
62
94
  end
63
95
 
96
+ sig { returns(Types::HtmlAttributes) }
64
97
  def rate_wrapper_attributes
65
98
  base_attrs = {
66
99
  class: rate_classes,
@@ -85,6 +118,7 @@ module HakumiComponents
85
118
  merge_attributes(base_attrs, @html_options.except(:class))
86
119
  end
87
120
 
121
+ sig { params(index: Integer).returns(Symbol) }
88
122
  def star_state(index)
89
123
  value = current_value
90
124
  return :full if value >= index + 1
@@ -93,6 +127,7 @@ module HakumiComponents
93
127
  :zero
94
128
  end
95
129
 
130
+ sig { params(state: Symbol).returns(String) }
96
131
  def star_classes(state)
97
132
  class_names(
98
133
  "rate-star",
@@ -104,28 +139,39 @@ module HakumiComponents
104
139
  )
105
140
  end
106
141
 
142
+ sig { params(index: Integer).returns(T.nilable(String)) }
107
143
  def tooltip_for(index)
108
144
  @tooltips[index]
109
145
  end
110
146
 
147
+ sig { returns(Types::Renderable) }
111
148
  def character_content
112
149
  render_value(@character || "★")
113
150
  end
114
151
 
152
+ sig { returns(Types::HtmlAttributes) }
115
153
  def input_attributes
116
154
  {
117
155
  type: "hidden",
118
- name: @name,
156
+ name: form_field_name,
119
157
  id: input_id,
120
158
  value: current_value,
121
159
  disabled: @disabled ? true : nil,
122
- "aria-invalid": has_error? ? "true" : nil,
160
+ "aria-invalid": error? ? "true" : nil,
123
161
  "aria-describedby": describedby_ids,
124
162
  data: {
125
163
  hakumi__rate_target: "input"
126
164
  }
127
165
  }.compact
128
166
  end
167
+
168
+ private
169
+
170
+ sig { returns(T.nilable(String)) }
171
+ def html_class_name
172
+ css_class = @html_options[:class]
173
+ css_class.is_a?(String) ? css_class : nil
174
+ end
129
175
  end
130
176
  end
131
177
  end
@@ -1,46 +1,77 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module HakumiComponents
4
5
  module Result
5
6
  class Component < HakumiComponents::BaseComponent
6
- STATUSES = %w[success info warning error].freeze
7
-
8
- DEFAULT_TITLES = {
9
- "success" => "Success",
10
- "info" => "Information",
11
- "warning" => "Warning",
12
- "error" => "Error"
13
- }.freeze
14
-
15
- DEFAULT_ICON_NAME = "result_success"
16
- STATUS_ICON_MAP = {
17
- "success" => { name: "check-circle", theme: :filled, color: "var(--color-success)" },
18
- "info" => { name: "info-circle", theme: :filled, color: "var(--color-primary)" },
19
- "warning" => { name: "exclamation-circle", theme: :filled, color: "var(--color-warning)" },
20
- "error" => { name: "close-circle", theme: :filled, color: "var(--color-error)" }
21
- }.freeze
22
- STATUS_ICON_SIZE = 72
23
-
7
+ extend T::Sig
8
+
9
+ Status = T.type_alias { T.any(Symbol, String) }
10
+ IconOverride = T.type_alias { T.any(FalseClass, HakumiComponents::Types::Renderable) }
11
+ STATUSES = T.let(%i[success info warning error].freeze, T::Array[Symbol])
12
+
13
+ DEFAULT_TITLES = T.let({
14
+ success: "Success",
15
+ info: "Information",
16
+ warning: "Warning",
17
+ error: "Error"
18
+ }.freeze, T::Hash[Symbol, String])
19
+
20
+ DEFAULT_ICON_NAME = T.let("result_success", String)
21
+ STATUS_ICON_MAP = T.let({
22
+ success: [ "check-circle", :filled, "var(--color-success)" ],
23
+ info: [ "info-circle", :filled, "var(--color-primary)" ],
24
+ warning: [ "exclamation-circle", :filled, "var(--color-warning)" ],
25
+ error: [ "close-circle", :filled, "var(--color-error)" ]
26
+ }.freeze, T::Hash[Symbol, [ String, Symbol, String ]])
27
+ STATUS_ICON_SIZE = T.let(72, Integer)
28
+
29
+ renders_one :title
30
+ renders_one :sub_title
31
+ renders_one :extra
32
+
33
+ sig do
34
+ params(
35
+ params: T.any(ActionController::Parameters, HakumiComponents::Types::HtmlAttributes)
36
+ ).returns(HakumiComponents::Types::HtmlAttributes)
37
+ end
24
38
  def self.extract_controller_locals(params)
25
39
  {
26
- status: params[:status],
27
- title: params[:title],
28
- sub_title: params[:sub_title],
29
- extra: params[:extra]
40
+ status: symbol_html_param(html_param(params, :status)),
41
+ title: html_primitive_param(html_param(params, :title)),
42
+ sub_title: html_primitive_param(html_param(params, :sub_title)),
43
+ icon: icon_html_param(html_param(params, :icon)),
44
+ extra: html_primitive_param(html_param(params, :extra))
30
45
  }
31
46
  end
32
47
 
48
+ sig { params(value: HakumiComponents::Types::HtmlAttributeValue).returns(T.nilable(FalseClass)) }
49
+ def self.icon_html_param(value)
50
+ boolean_html_param(value) == false ? false : nil
51
+ end
52
+
53
+ sig do
54
+ params(
55
+ status: Status,
56
+ title: HakumiComponents::Types::Renderable,
57
+ sub_title: HakumiComponents::Types::Renderable,
58
+ icon: T.nilable(IconOverride),
59
+ extra: HakumiComponents::Types::Renderable,
60
+ html_options: HakumiComponents::Types::HtmlAttributeValue
61
+ ).void
62
+ end
33
63
  def initialize(status: :info, title: nil, sub_title: nil, icon: nil, extra: nil, **html_options)
34
- @status = (status || :info).to_s
35
- @title = title || DEFAULT_TITLES[@status]
36
- @sub_title = sub_title
37
- @icon = icon
38
- @extra = extra
39
- @html_options = html_options
64
+ @status = T.let(status.to_sym, Symbol)
65
+ @title = T.let(title || DEFAULT_TITLES[@status], HakumiComponents::Types::Renderable)
66
+ @sub_title = T.let(sub_title, HakumiComponents::Types::Renderable)
67
+ @icon = T.let(icon, T.nilable(IconOverride))
68
+ @extra = T.let(extra, HakumiComponents::Types::Renderable)
69
+ @html_options = T.let(html_options, HakumiComponents::Types::HtmlAttributes)
40
70
 
41
71
  validate_props!
42
72
  end
43
73
 
74
+ sig { returns(HakumiComponents::Types::HtmlAttributes) }
44
75
  def wrapper_attributes
45
76
  merge_attributes(
46
77
  {
@@ -52,71 +83,90 @@ module HakumiComponents
52
83
  )
53
84
  end
54
85
 
86
+ sig { returns(T::Boolean) }
55
87
  def icon_present?
56
88
  @icon != false
57
89
  end
58
90
 
91
+ sig { returns(HakumiComponents::Types::Renderable) }
59
92
  def icon_content
60
93
  return nil unless icon_present?
61
94
 
62
95
  render_value(@icon || status_icon_component || default_icon)
63
96
  end
64
97
 
98
+ sig { returns(HakumiComponents::Types::Renderable) }
65
99
  def title_content
100
+ return render_value(title) if title?
101
+
66
102
  render_value(@title)
67
103
  end
68
104
 
105
+ sig { returns(HakumiComponents::Types::Renderable) }
69
106
  def sub_title_content
107
+ return render_value(sub_title) if sub_title?
108
+
70
109
  render_value(@sub_title)
71
110
  end
72
111
 
112
+ sig { returns(HakumiComponents::Types::Renderable) }
73
113
  def extra_content
114
+ return render_value(extra) if extra?
115
+
74
116
  render_value(@extra)
75
117
  end
76
118
 
119
+ sig { returns(T::Boolean) }
77
120
  def content_present?
78
121
  content.present?
79
122
  end
80
123
 
124
+ sig { returns(T::Boolean) }
81
125
  def extra_present?
82
- @extra.present?
126
+ extra? || @extra.present?
83
127
  end
84
128
 
129
+ sig { returns(T::Boolean) }
85
130
  def title_present?
86
- @title.present?
131
+ title? || @title.present?
87
132
  end
88
133
 
134
+ sig { returns(T::Boolean) }
89
135
  def sub_title_present?
90
- @sub_title.present?
136
+ sub_title? || @sub_title.present?
91
137
  end
92
138
 
93
139
  private
94
140
 
141
+ sig { void }
95
142
  def validate_props!
96
143
  validate_inclusion!(:status, STATUSES)
97
144
  end
98
145
 
146
+ sig { returns(String) }
99
147
  def wrapper_classes
100
- class_names(
148
+ component_classes(
101
149
  "result",
102
150
  { @status => true },
103
- [ @html_options[:class] ]
151
+ @html_options
104
152
  )
105
153
  end
106
154
 
107
-
155
+ sig { returns(T.nilable(HakumiComponents::Icon::Component)) }
108
156
  def status_icon_component
109
157
  config = STATUS_ICON_MAP[@status]
110
158
  return unless config
111
159
 
160
+ name, theme, color = config
112
161
  HakumiComponents::Icon::Component.new(
113
- name: config[:name],
114
- theme: config[:theme],
162
+ name: name,
163
+ theme: theme,
115
164
  size: STATUS_ICON_SIZE,
116
- color: config[:color]
165
+ color: color
117
166
  )
118
167
  end
119
168
 
169
+ sig { returns(HakumiComponents::Types::Renderable) }
120
170
  def default_icon
121
171
  HakumiComponents::Illustrations::Loader.load(DEFAULT_ICON_NAME)
122
172
  end
@@ -4,7 +4,7 @@
4
4
  <%= tag.label(class: option_classes(option), data: option_data_attributes(option)) do %>
5
5
  <%= radio_button_tag(
6
6
  @name,
7
- option[:value],
7
+ option.value,
8
8
  option_selected?(option),
9
9
  **option_input_attributes(option, index)
10
10
  ) %>