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,11 +1,40 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module HakumiComponents
4
5
  module DatePicker
5
6
  class RangePicker < HakumiComponents::BaseComponent
7
+ extend T::Sig
8
+
6
9
  include HakumiComponents::Concerns::FormField
7
10
  include SharedRendering
8
11
 
12
+ PlaceholderInput = T.type_alias { T.nilable(T.any(String, T::Array[String])) }
13
+ InputId = T.type_alias { Types::HtmlKey }
14
+
15
+ sig do
16
+ params(
17
+ name: T.nilable(Types::FormFieldName),
18
+ label: T.nilable(String),
19
+ caption: T.nilable(String),
20
+ start_value: Types::FormFieldScalar,
21
+ end_value: Types::FormFieldScalar,
22
+ default_value: Types::FormFieldValue,
23
+ format: T.nilable(String),
24
+ picker: Symbol,
25
+ show_time: T::Boolean,
26
+ disabled: T::Boolean,
27
+ disabled_date: T.nilable(Proc),
28
+ allow_clear: T::Boolean,
29
+ placeholder: PlaceholderInput,
30
+ size: Symbol,
31
+ bordered: T::Boolean,
32
+ required: T::Boolean,
33
+ errors: Types::FormFieldErrors,
34
+ standalone: T::Boolean,
35
+ html_options: Types::HtmlAttributeValue
36
+ ).void
37
+ end
9
38
  def initialize(
10
39
  name: nil,
11
40
  label: nil,
@@ -20,44 +49,54 @@ module HakumiComponents
20
49
  disabled_date: nil,
21
50
  allow_clear: false,
22
51
  placeholder: nil,
23
- size: :middle,
52
+ size: :default,
24
53
  bordered: true,
25
54
  required: false,
26
55
  errors: [],
27
56
  standalone: true,
28
57
  **html_options
29
58
  )
30
- @name = name || generate_id("range_picker")
31
- @label = label
32
- @caption = caption
33
- @start_value = start_value
34
- @end_value = end_value
35
- @value = @start_value || @end_value
36
- @default_value = default_value
37
- @format = format
38
- @picker = picker
39
- @show_time = show_time
40
- @disabled = disabled
41
- @disabled_date = disabled_date
42
- @allow_clear = allow_clear
43
- @placeholder = placeholder
44
- @size = size
45
- @bordered = bordered
46
- @required = required
47
- @errors = Array(errors)
48
- @standalone = standalone
49
- @html_options = html_options
59
+ @name = T.let(name || generate_id("range_picker"), Types::FormFieldName)
60
+ @label = T.let(label, T.nilable(String))
61
+ @caption = T.let(caption, T.nilable(String))
62
+ @start_value = T.let(start_value, Types::FormFieldScalar)
63
+ @end_value = T.let(end_value, Types::FormFieldScalar)
64
+ @value = T.let(@start_value || @end_value, Types::FormFieldValue)
65
+ @default_value = T.let(default_value, Types::FormFieldValue)
66
+ @format = T.let(format, T.nilable(String))
67
+ @picker = T.let(picker, Symbol)
68
+ @show_time = T.let(show_time, T::Boolean)
69
+ @disabled = T.let(disabled, T::Boolean)
70
+ @disabled_date = T.let(disabled_date, T.nilable(Proc))
71
+ @allow_clear = T.let(allow_clear, T::Boolean)
72
+ @placeholder = T.let(placeholder, PlaceholderInput)
73
+ @size = T.let(size, Symbol)
74
+ @bordered = T.let(bordered, T::Boolean)
75
+ @required = T.let(required, T::Boolean)
76
+ @errors = T.let(errors, Types::FormFieldErrors)
77
+ @standalone = T.let(standalone, T::Boolean)
78
+ @html_options = T.let(html_options, Types::HtmlAttributes)
79
+ initialize_form_field_contract!(
80
+ name: @name,
81
+ label: @label,
82
+ caption: @caption,
83
+ errors: @errors,
84
+ standalone: @standalone,
85
+ required: @required,
86
+ html_options: @html_options
87
+ )
50
88
 
51
89
  validate_props!
52
90
  end
53
91
 
92
+ sig { returns(Types::HtmlAttributes) }
54
93
  def wrapper_attributes
55
94
  base_attrs = {
56
- class: base_wrapper_classes(base: "date-picker", extra_classes: [ "hakumi-range-picker", @html_options[:class] ]),
95
+ class: base_wrapper_classes(base: "date-picker", extra_classes: range_picker_classes),
57
96
  data: {
58
97
  controller: "hakumi--date-picker",
59
- hakumi__date_picker_allow_clear_value: @allow_clear ? "true" : "false",
60
- hakumi__date_picker_disabled_value: @disabled ? "true" : "false",
98
+ hakumi__date_picker_allow_clear_value: @allow_clear,
99
+ hakumi__date_picker_disabled_value: @disabled,
61
100
  hakumi__date_picker_format_value: display_format,
62
101
  hakumi__date_picker_picker_value: @picker.to_s,
63
102
  hakumi__date_picker_range_value: "true"
@@ -67,6 +106,7 @@ module HakumiComponents
67
106
  merge_attributes(base_attrs, @html_options.except(:class))
68
107
  end
69
108
 
109
+ sig { returns(Types::HtmlAttributes) }
70
110
  def start_input_attributes
71
111
  {
72
112
  type: :text,
@@ -77,7 +117,7 @@ module HakumiComponents
77
117
  class: "hakumi-date-picker-input-field",
78
118
  readonly: true,
79
119
  disabled: @disabled ? true : nil,
80
- "aria-invalid": has_error? ? "true" : nil,
120
+ "aria-invalid": error? ? "true" : nil,
81
121
  "aria-describedby": describedby_ids,
82
122
  data: {
83
123
  "hakumi--date-picker-target": "startInput",
@@ -86,6 +126,7 @@ module HakumiComponents
86
126
  }.compact
87
127
  end
88
128
 
129
+ sig { returns(Types::HtmlAttributes) }
89
130
  def end_input_attributes
90
131
  {
91
132
  type: :text,
@@ -96,7 +137,7 @@ module HakumiComponents
96
137
  class: "hakumi-date-picker-input-field",
97
138
  readonly: true,
98
139
  disabled: @disabled ? true : nil,
99
- "aria-invalid": has_error? ? "true" : nil,
140
+ "aria-invalid": error? ? "true" : nil,
100
141
  "aria-describedby": describedby_ids,
101
142
  data: {
102
143
  "hakumi--date-picker-target": "endInput",
@@ -105,32 +146,122 @@ module HakumiComponents
105
146
  }.compact
106
147
  end
107
148
 
149
+ sig { returns(String) }
108
150
  def start_input_name
109
151
  "#{@name}_start"
110
152
  end
111
153
 
154
+ sig { returns(String) }
112
155
  def end_input_name
113
156
  "#{@name}_end"
114
157
  end
115
158
 
159
+ sig { returns(InputId) }
116
160
  def start_input_id
117
- @html_options[:start_id] || "#{@name}_start"
161
+ custom_id = @html_options[:start_id]
162
+ return custom_id if custom_id.is_a?(String) || custom_id.is_a?(Symbol)
163
+
164
+ "#{@name}_start"
118
165
  end
119
166
 
167
+ sig { returns(InputId) }
120
168
  def end_input_id
121
- @html_options[:end_id] || "#{@name}_end"
169
+ custom_id = @html_options[:end_id]
170
+ return custom_id if custom_id.is_a?(String) || custom_id.is_a?(Symbol)
171
+
172
+ "#{@name}_end"
122
173
  end
123
174
 
175
+ sig { returns(T::Array[T.nilable(String)]) }
124
176
  def display_values
125
177
  [ formatted_value(@start_value), formatted_value(@end_value) ]
126
178
  end
127
179
 
128
180
  private
129
181
 
182
+ sig { void }
130
183
  def validate_props!
131
184
  validate_inclusion!(:size, SIZES)
132
185
  validate_inclusion!(:picker, PICKERS)
133
186
  end
187
+
188
+ sig { returns(T::Array[T.nilable(String)]) }
189
+ def range_picker_classes
190
+ [ "hakumi-range-picker", html_class_name ]
191
+ end
192
+
193
+ sig { returns(T.nilable(String)) }
194
+ def html_class_name
195
+ css_class = @html_options[:class]
196
+ css_class.is_a?(String) ? css_class : nil
197
+ end
198
+
199
+ public
200
+
201
+ sig { override.returns(T.nilable(String)) }
202
+ def date_picker_format
203
+ @format
204
+ end
205
+
206
+ sig { override.returns(T.nilable(String)) }
207
+ def date_picker_display_format
208
+ nil
209
+ end
210
+
211
+ sig { override.returns(Symbol) }
212
+ def date_picker_picker
213
+ @picker
214
+ end
215
+
216
+ sig { override.returns(T::Boolean) }
217
+ def date_picker_show_time
218
+ @show_time
219
+ end
220
+
221
+ sig { override.returns(T::Boolean) }
222
+ def date_picker_show_seconds
223
+ @show_time
224
+ end
225
+
226
+ sig { override.returns(Symbol) }
227
+ def date_picker_size
228
+ @size
229
+ end
230
+
231
+ sig { override.returns(T::Boolean) }
232
+ def date_picker_bordered
233
+ @bordered
234
+ end
235
+
236
+ sig { override.returns(T::Boolean) }
237
+ def date_picker_disabled
238
+ @disabled
239
+ end
240
+
241
+ sig { override.returns(T::Boolean) }
242
+ def date_picker_allow_clear
243
+ @allow_clear
244
+ end
245
+
246
+ sig { override.returns(Types::FormFieldValue) }
247
+ def date_picker_value
248
+ @value
249
+ end
250
+
251
+ sig { override.returns(Types::FormFieldValue) }
252
+ def date_picker_default_value
253
+ @default_value
254
+ end
255
+
256
+ sig { override.returns(T.nilable(Proc)) }
257
+ def date_picker_disabled_date
258
+ @disabled_date
259
+ end
260
+
261
+ sig { override.returns(T.nilable(T.any(String, T::Array[String]))) }
262
+ def date_picker_placeholder
263
+ @placeholder
264
+ end
134
265
  end
135
266
  end
136
267
  end
@@ -1,71 +1,136 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module HakumiComponents
4
5
  module DatePicker
5
6
  module SharedRendering
6
- SIZES = [ :small, :middle, :large ].freeze
7
- PICKERS = [ :date, :week, :month, :quarter, :year ].freeze
7
+ extend T::Sig
8
+ extend T::Helpers
8
9
 
9
- # Default Day.js display formats
10
- DEFAULT_DATE_FORMAT = "YYYY-MM-DD"
11
- DEFAULT_DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss"
12
- DEFAULT_DATETIME_NO_SECONDS_FORMAT = "YYYY-MM-DD HH:mm"
10
+ abstract!
13
11
 
14
- # ISO value for hidden input (always standard format for Rails)
12
+ requires_ancestor { HakumiComponents::BaseComponent }
13
+
14
+ DateTimeLike = T.type_alias { T.any(Date, Time, DateTime) }
15
+ PlaceholderValue = T.type_alias { T.nilable(T.any(String, T::Array[String])) }
16
+ CalendarOptionValue = T.type_alias do
17
+ T.nilable(T.any(
18
+ Date,
19
+ Types::FormFieldValue,
20
+ Symbol,
21
+ T::Boolean,
22
+ Proc,
23
+ Types::DataAttributes
24
+ ))
25
+ end
26
+
27
+ PICKERS = T.let([ :date, :week, :month, :quarter, :year ].freeze, T::Array[Symbol])
28
+ DEFAULT_DATE_FORMAT = T.let("YYYY-MM-DD", String)
29
+ DEFAULT_DATETIME_FORMAT = T.let("YYYY-MM-DD HH:mm:ss", String)
30
+ DEFAULT_DATETIME_NO_SECONDS_FORMAT = T.let("YYYY-MM-DD HH:mm", String)
31
+
32
+ sig { abstract.returns(T.nilable(String)) }
33
+ def date_picker_format; end
34
+
35
+ sig { abstract.returns(T.nilable(String)) }
36
+ def date_picker_display_format; end
37
+
38
+ sig { abstract.returns(Symbol) }
39
+ def date_picker_picker; end
40
+
41
+ sig { abstract.returns(T::Boolean) }
42
+ def date_picker_show_time; end
43
+
44
+ sig { abstract.returns(T::Boolean) }
45
+ def date_picker_show_seconds; end
46
+
47
+ sig { abstract.returns(Symbol) }
48
+ def date_picker_size; end
49
+
50
+ sig { abstract.returns(T::Boolean) }
51
+ def date_picker_bordered; end
52
+
53
+ sig { abstract.returns(T::Boolean) }
54
+ def date_picker_disabled; end
55
+
56
+ sig { abstract.returns(T::Boolean) }
57
+ def date_picker_allow_clear; end
58
+
59
+ sig { abstract.returns(Types::FormFieldValue) }
60
+ def date_picker_value; end
61
+
62
+ sig { abstract.returns(Types::FormFieldValue) }
63
+ def date_picker_default_value; end
64
+
65
+ sig { abstract.returns(T.nilable(Proc)) }
66
+ def date_picker_disabled_date; end
67
+
68
+ sig { abstract.returns(PlaceholderValue) }
69
+ def date_picker_placeholder; end
70
+
71
+ sig { params(value: Types::FormFieldScalar).returns(T.nilable(String)) }
15
72
  def iso_value(value)
16
73
  return nil if value.blank?
17
74
 
18
75
  datetime_value = parse_datetime(value)
19
76
  return nil if datetime_value.nil?
20
77
 
21
- if @show_time
78
+ if date_picker_show_time
22
79
  show_seconds? ? datetime_value.strftime("%Y-%m-%d %H:%M:%S") : datetime_value.strftime("%Y-%m-%d %H:%M")
23
80
  else
24
81
  datetime_value.strftime("%Y-%m-%d")
25
82
  end
26
83
  end
27
84
 
28
- # Formatted value for visible input (uses display_format or default)
85
+ sig { params(value: Types::FormFieldScalar).returns(T.nilable(String)) }
29
86
  def formatted_value(value)
30
87
  return nil if value.blank?
31
88
 
32
89
  datetime_value = parse_datetime(value)
33
90
  return value.to_s if datetime_value.nil?
34
91
 
35
- return format_quarter(datetime_value) if @picker == :quarter && !@display_format.present? && !@format.present?
92
+ if date_picker_picker == :quarter && date_picker_display_format.blank? && date_picker_format.blank?
93
+ return format_quarter(datetime_value.to_date)
94
+ end
36
95
 
37
- # Priority: display_format (Day.js) > format (strftime legacy) > default
38
- if @display_format.present?
39
- datetime_value.strftime(dayjs_to_strftime(@display_format))
40
- elsif @format.present?
41
- datetime_value.strftime(@format)
96
+ display_format_value = date_picker_display_format
97
+ format_value = date_picker_format
98
+
99
+ if display_format_value.present?
100
+ datetime_value.strftime(dayjs_to_strftime(display_format_value))
101
+ elsif format_value.present?
102
+ datetime_value.strftime(format_value)
42
103
  else
43
104
  datetime_value.strftime(default_strftime_format)
44
105
  end
45
106
  end
46
107
 
47
- # Day.js format string for JS controller
108
+ sig { returns(String) }
48
109
  def js_display_format
49
- return @display_format if @display_format.present?
110
+ display_format_value = date_picker_display_format
111
+ return display_format_value if display_format_value.present?
50
112
 
51
- if @show_time
113
+ if date_picker_show_time
52
114
  show_seconds? ? DEFAULT_DATETIME_FORMAT : DEFAULT_DATETIME_NO_SECONDS_FORMAT
53
115
  else
54
116
  DEFAULT_DATE_FORMAT
55
117
  end
56
118
  end
57
119
 
58
- # Ruby strftime format (for legacy @format support)
120
+ sig { returns(String) }
59
121
  def display_format
60
- return @format if @format.present?
122
+ format_value = date_picker_format
123
+ return format_value if format_value.present?
124
+
61
125
  default_strftime_format
62
126
  end
63
127
 
128
+ sig { returns(String) }
64
129
  def default_strftime_format
65
- if @show_time
130
+ if date_picker_show_time
66
131
  show_seconds? ? "%Y-%m-%d %H:%M:%S" : "%Y-%m-%d %H:%M"
67
132
  else
68
- case @picker
133
+ case date_picker_picker
69
134
  when :month
70
135
  "%Y-%m"
71
136
  when :year
@@ -78,17 +143,17 @@ module HakumiComponents
78
143
  end
79
144
  end
80
145
 
81
- # Convert Day.js format to Ruby strftime format
146
+ sig { params(dayjs_format: String).returns(String) }
82
147
  def dayjs_to_strftime(dayjs_format)
83
148
  dayjs_format
84
149
  .gsub("YYYY", "%Y")
85
150
  .gsub("YY", "%y")
86
- .gsub("MMMM", "%B") # Full month name
87
- .gsub("MMM", "%b") # Abbreviated month name
88
- .gsub("MM", "%m") # Month with zero-padding
89
- .gsub("M", "%-m") # Month without padding
90
- .gsub("DD", "%d") # Day with zero-padding
91
- .gsub("D", "%-d") # Day without padding
151
+ .gsub("MMMM", "%B")
152
+ .gsub("MMM", "%b")
153
+ .gsub("MM", "%m")
154
+ .gsub("M", "%-m")
155
+ .gsub("DD", "%d")
156
+ .gsub("D", "%-d")
92
157
  .gsub("HH", "%H")
93
158
  .gsub("hh", "%I")
94
159
  .gsub("mm", "%M")
@@ -97,102 +162,127 @@ module HakumiComponents
97
162
  .gsub("a", "%P")
98
163
  end
99
164
 
165
+ sig { params(value: Types::FormFieldScalar).returns(T.nilable(DateTimeLike)) }
100
166
  def parse_datetime(value)
101
167
  return nil if value.nil?
102
168
  return value if value.is_a?(Time) || value.is_a?(DateTime)
103
- return @show_time ? value.to_time : value if value.is_a?(Date)
169
+ return Time.parse(value.to_s) if value.is_a?(ActiveSupport::TimeWithZone)
170
+ return date_picker_show_time ? value.to_time : value if value.is_a?(Date)
104
171
 
105
- str = value.to_s
106
- if @show_time && str.include?(" ")
107
- # Parse datetime string like "2026-03-15 14:30:00"
108
- Time.parse(str)
172
+ string_value = value.to_s
173
+ if date_picker_show_time && string_value.include?(" ")
174
+ Time.parse(string_value)
109
175
  else
110
- Date.parse(str)
176
+ Date.parse(string_value)
111
177
  end
112
178
  rescue ArgumentError, TypeError
113
179
  nil
114
180
  end
115
181
 
182
+ sig { params(value: Types::FormFieldScalar).returns(T.nilable(Date)) }
116
183
  def parse_date(value)
117
- parse_datetime(value)&.to_date
184
+ datetime_value = parse_datetime(value)
185
+ datetime_value&.to_date
118
186
  end
119
187
 
188
+ sig { returns(T::Boolean) }
120
189
  def show_seconds?
121
- # Use explicit @show_seconds if defined, otherwise derive from @show_time
122
- return @show_seconds if instance_variable_defined?(:@show_seconds) && !@show_seconds.nil?
123
- @show_time
190
+ date_picker_show_seconds
124
191
  end
125
192
 
193
+ sig { returns(T::Boolean) }
126
194
  def use_12_hours?
127
- return false unless @display_format.present?
128
- # Check if format has 'hh' (12-hour) and 'A' or 'a' (AM/PM)
129
- @display_format.include?("hh") && (@display_format.include?("A") || @display_format.include?("a"))
195
+ display_format_value = date_picker_display_format
196
+ return false unless display_format_value.present?
197
+
198
+ display_format_value.include?("hh") && (display_format_value.include?("A") || display_format_value.include?("a"))
130
199
  end
131
200
 
201
+ sig { params(date_value: Date).returns(String) }
132
202
  def format_quarter(date_value)
133
203
  quarter = ((date_value.month - 1) / 3) + 1
134
204
  "Q#{quarter} #{date_value.year}"
135
205
  end
136
206
 
207
+ sig { returns(Symbol) }
137
208
  def picker_mode
138
- case @picker
209
+ case date_picker_picker
139
210
  when :date, :week
140
- :month # Date and week both show month view
211
+ :month
141
212
  when :month
142
- :year # Month picker shows year view (12 months)
213
+ :year
143
214
  when :quarter
144
- :quarter # Quarter picker shows quarter view (Q1-Q4)
215
+ :quarter
145
216
  when :year
146
- :decade # Year picker shows decade view (years)
217
+ :decade
147
218
  else
148
219
  :month
149
220
  end
150
221
  end
151
222
 
223
+ sig { params(base: String, extra_classes: T.any(String, T::Array[T.nilable(String)])).returns(String) }
152
224
  def base_wrapper_classes(base:, extra_classes: [])
153
225
  class_names(
154
226
  base,
155
227
  {
156
- lg: @size == :large,
157
- sm: @size == :small,
158
- borderless: !@bordered,
159
- disabled: @disabled,
160
- "allow-clear": @allow_clear,
161
- "has-value": value_present?(@value)
228
+ lg: date_picker_size == :large,
229
+ sm: date_picker_size == :small,
230
+ borderless: !date_picker_bordered,
231
+ disabled: date_picker_disabled,
232
+ "allow-clear": date_picker_allow_clear,
233
+ "has-value": value_present?(date_picker_value)
162
234
  },
163
235
  extra_classes
164
236
  )
165
237
  end
166
238
 
239
+ sig { params(range: T.nilable(String)).returns(Types::DataAttributes) }
167
240
  def picker_panel_attributes(range: nil)
168
- data_attrs = {
241
+ data_attrs = T.let({
169
242
  action: "hakumi--calendar:select->hakumi--date-picker#handleCalendarSelect"
170
- }
243
+ }, Types::DataAttributes)
171
244
  data_attrs[:date_range] = range if range
172
245
  data_attrs
173
246
  end
174
247
 
248
+ sig { params(value: T.nilable(Date), range: T.nilable(String)).returns(T::Hash[Symbol, CalendarOptionValue]) }
175
249
  def calendar_component_options(value:, range: nil)
176
250
  {
177
251
  value: value,
178
- default_value: @default_value,
252
+ default_value: date_picker_default_value,
179
253
  fullscreen: false,
180
254
  mode: picker_mode,
181
- show_week: @picker == :week, # Show week column for week picker
255
+ show_week: date_picker_picker == :week,
182
256
  static: true,
183
- disabled_date: @disabled_date,
257
+ disabled_date: date_picker_disabled_date,
184
258
  data: picker_panel_attributes(range: range)
185
259
  }
186
260
  end
187
261
 
262
+ sig { returns(String) }
188
263
  def placeholder_text
189
- @placeholder || "Select date"
264
+ placeholder = date_picker_placeholder
265
+ return placeholder if placeholder.is_a?(String)
266
+
267
+ t_default(:placeholder, default: "Select date")
190
268
  end
191
269
 
270
+ sig { returns(T::Array[String]) }
192
271
  def range_placeholders
193
- return @placeholder if @placeholder.is_a?(Array)
272
+ placeholder = date_picker_placeholder
273
+ if placeholder.is_a?(Array)
274
+ values = placeholder.filter_map do |item|
275
+ next if item.nil?
276
+
277
+ item.to_s
278
+ end
279
+ return values if values.length == 2
280
+ end
194
281
 
195
- [ "Start date", "End date" ]
282
+ [
283
+ t_default(:start_placeholder, default: "Start date"),
284
+ t_default(:end_placeholder, default: "End date")
285
+ ]
196
286
  end
197
287
  end
198
288
  end
@@ -1,11 +1,11 @@
1
1
  <div <%= tag.attributes(wrapper_attributes) %>>
2
- <% if @title || @extra %>
2
+ <% if header? %>
3
3
  <div class="hakumi-descriptions-header">
4
- <% if @title %>
5
- <%= render_title %>
4
+ <% if title_content.present? %>
5
+ <div class="hakumi-descriptions-title"><%= title_content %></div>
6
6
  <% end %>
7
- <% if @extra %>
8
- <%= render_extra %>
7
+ <% if extra_content.present? %>
8
+ <div class="hakumi-descriptions-extra"><%= extra_content %></div>
9
9
  <% end %>
10
10
  </div>
11
11
  <% end %>
@@ -14,7 +14,7 @@
14
14
  <table class="hakumi-descriptions-table">
15
15
  <tbody>
16
16
  <% rows.each do |row| %>
17
- <% if @layout == :vertical %>
17
+ <% if vertical_layout? %>
18
18
  <tr class="hakumi-descriptions-row">
19
19
  <% row.each do |item, span| %>
20
20
  <% col_span = (span.to_i * 2) %>