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
@@ -31,32 +31,48 @@ const isInIframe = () => {
31
31
  }
32
32
 
33
33
 
34
- const cacheKeyFor = (normalizedName, format) => `hakumi:rcache:${format}:${normalizedName}`
35
- const cacheMetaKeyFor = (normalizedName, format) => `hakumi:rcachemeta:${format}:${normalizedName}`
34
+ const stableParamHash = (params) => {
35
+ const sorted = Object.keys(params).sort().map(k => `${k}=${params[k]}`).join("&")
36
+ if (!sorted) return ""
37
+ let h = 0
38
+ for (let i = 0; i < sorted.length; i++) {
39
+ h = ((h << 5) - h + sorted.charCodeAt(i)) | 0
40
+ }
41
+ return h.toString(36)
42
+ }
43
+
44
+ const cacheKeyFor = (normalizedName, format, params = {}) => {
45
+ const ph = stableParamHash(params)
46
+ return `hakumi:rcache:${format}:${normalizedName}${ph ? `:${ph}` : ""}`
47
+ }
48
+ const cacheMetaKeyFor = (normalizedName, format, params = {}) => {
49
+ const ph = stableParamHash(params)
50
+ return `hakumi:rcachemeta:${format}:${normalizedName}${ph ? `:${ph}` : ""}`
51
+ }
36
52
 
37
53
  const resolveComponentData = (element) => element?.hakumiComponent
38
54
 
39
- const loadCache = (normalizedName, format, ttlMs) => {
40
- const metaRaw = safeSessionGet(cacheMetaKeyFor(normalizedName, format))
55
+ const loadCache = (normalizedName, format, ttlMs, params = {}) => {
56
+ const metaRaw = safeSessionGet(cacheMetaKeyFor(normalizedName, format, params))
41
57
  if (!metaRaw) return null
42
58
 
43
59
  let meta
44
60
  try {
45
61
  meta = JSON.parse(metaRaw)
46
62
  } catch {
47
- safeSessionRemove(cacheMetaKeyFor(normalizedName, format))
63
+ safeSessionRemove(cacheMetaKeyFor(normalizedName, format, params))
48
64
  return null
49
65
  }
50
66
 
51
67
  if (!meta?.ts || typeof meta.ts !== "number") return null
52
68
  if (ttlMs != null && Date.now() - meta.ts > ttlMs) return null
53
69
 
54
- return safeSessionGet(cacheKeyFor(normalizedName, format))
70
+ return safeSessionGet(cacheKeyFor(normalizedName, format, params))
55
71
  }
56
72
 
57
- const saveCache = (normalizedName, format, html) => {
58
- safeSessionSet(cacheKeyFor(normalizedName, format), html)
59
- safeSessionSet(cacheMetaKeyFor(normalizedName, format), JSON.stringify({ ts: Date.now() }))
73
+ const saveCache = (normalizedName, format, html, params = {}) => {
74
+ safeSessionSet(cacheKeyFor(normalizedName, format, params), html)
75
+ safeSessionSet(cacheMetaKeyFor(normalizedName, format, params), JSON.stringify({ ts: Date.now() }))
60
76
  }
61
77
 
62
78
  export const renderComponent = async (
@@ -112,11 +128,12 @@ export const renderComponent = async (
112
128
 
113
129
  let optimisticElement = null
114
130
  if (cache && mode !== "replace") {
115
- const cachedHtml = loadCache(normalizedName, format, cacheTtlMs)
131
+ const cachedHtml = loadCache(normalizedName, format, cacheTtlMs, finalParams)
116
132
  if (cachedHtml) {
117
133
  try {
118
134
  optimisticElement = elementFromHtml(cachedHtml, name)
119
135
  optimisticElement.setAttribute("data-hakumi-render-cache", "1")
136
+ optimisticElement.setAttribute("data-hakumi-render-pending", "")
120
137
  resolvedTarget.appendChild(optimisticElement)
121
138
  ensureId(optimisticElement, `hakumi-${name}`)
122
139
  } catch {}
@@ -129,9 +146,14 @@ export const renderComponent = async (
129
146
 
130
147
  const html = format === "json" ? (await response.json()).html : await response.text()
131
148
 
132
- if (cache) saveCache(normalizedName, format, html)
149
+ if (cache) saveCache(normalizedName, format, html, finalParams)
133
150
 
134
151
  const element = elementFromHtml(html, name)
152
+ const optimisticWasReady = optimisticElement?.dataset.hakumiReady === "true"
153
+
154
+ if (!optimisticWasReady) {
155
+ element.setAttribute("data-hakumi-render-pending", "")
156
+ }
135
157
 
136
158
  if (mode === "replace") {
137
159
  resolvedTarget.innerHTML = ""
@@ -156,6 +178,10 @@ export const renderComponent = async (
156
178
 
157
179
  await nextFrame()
158
180
 
181
+ if (element.dataset.hakumiRenderPending !== undefined && element.dataset.hakumiReady !== "true") {
182
+ element.dataset.hakumiReady = "true"
183
+ }
184
+
159
185
  let instance = get(id)
160
186
  if (!instance) {
161
187
  register(id, element)
@@ -0,0 +1,262 @@
1
+ const DEFAULT_HSV = Object.freeze({ h: 215, s: 91, v: 100 })
2
+
3
+ export function defaultHsv() {
4
+ return { ...DEFAULT_HSV }
5
+ }
6
+
7
+ export function formatHsvColor(hsv, alpha, format, { disabledAlpha = false } = {}) {
8
+ switch (format) {
9
+ case "hex":
10
+ return hsvToHex(hsv.h, hsv.s, hsv.v, alpha, { disabledAlpha })
11
+ case "rgb":
12
+ return hsvToRgbString(hsv.h, hsv.s, hsv.v, alpha, { disabledAlpha })
13
+ case "hsl":
14
+ return hsvToHslString(hsv.h, hsv.s, hsv.v, alpha, { disabledAlpha })
15
+ case "hsb":
16
+ return hsvToHsbString(hsv.h, hsv.s, hsv.v, alpha, { disabledAlpha })
17
+ default:
18
+ return hsvToHex(hsv.h, hsv.s, hsv.v, alpha, { disabledAlpha })
19
+ }
20
+ }
21
+
22
+ export function parseColorToHsv(color) {
23
+ if (!color) return defaultHsv()
24
+
25
+ const normalizedColor = color.trim()
26
+
27
+ if (normalizedColor.startsWith("#")) {
28
+ return hexToHsv(normalizedColor)
29
+ }
30
+
31
+ if (normalizedColor.startsWith("rgb")) {
32
+ return rgbStringToHsv(normalizedColor)
33
+ }
34
+
35
+ if (normalizedColor.startsWith("hsl")) {
36
+ return hslStringToHsv(normalizedColor)
37
+ }
38
+
39
+ if (normalizedColor.startsWith("hsb")) {
40
+ return hsbStringToHsv(normalizedColor)
41
+ }
42
+
43
+ return defaultHsv()
44
+ }
45
+
46
+ export function extractAlpha(color) {
47
+ if (!color) return 1
48
+
49
+ const normalizedColor = color.trim()
50
+
51
+ if (normalizedColor.startsWith("rgba")) {
52
+ const match = normalizedColor.match(/rgba?\(([^)]+)\)/)
53
+ if (match) {
54
+ const parts = match[1].split(",").map(part => part.trim())
55
+ if (parts[3]) return parseFloat(parts[3])
56
+ }
57
+ }
58
+
59
+ if (normalizedColor.startsWith("hsla")) {
60
+ const match = normalizedColor.match(/hsla?\(([^)]+)\)/)
61
+ if (match) {
62
+ const parts = match[1].split(",").map(part => part.trim())
63
+ if (parts[3]) return parseFloat(parts[3])
64
+ }
65
+ }
66
+
67
+ if (normalizedColor.startsWith("#") && normalizedColor.length === 9) {
68
+ const alpha = parseInt(normalizedColor.slice(7, 9), 16)
69
+ return Math.round((alpha / 255) * 100) / 100
70
+ }
71
+
72
+ return 1
73
+ }
74
+
75
+ export function hsvToRgb(h, s, v) {
76
+ const normalizedH = h / 360
77
+ const normalizedS = s / 100
78
+ const normalizedV = v / 100
79
+
80
+ const i = Math.floor(normalizedH * 6)
81
+ const f = normalizedH * 6 - i
82
+ const p = normalizedV * (1 - normalizedS)
83
+ const q = normalizedV * (1 - f * normalizedS)
84
+ const t = normalizedV * (1 - (1 - f) * normalizedS)
85
+
86
+ let r
87
+ let g
88
+ let b
89
+
90
+ switch (i % 6) {
91
+ case 0: r = normalizedV; g = t; b = p; break
92
+ case 1: r = q; g = normalizedV; b = p; break
93
+ case 2: r = p; g = normalizedV; b = t; break
94
+ case 3: r = p; g = q; b = normalizedV; break
95
+ case 4: r = t; g = p; b = normalizedV; break
96
+ case 5: r = normalizedV; g = p; b = q; break
97
+ }
98
+
99
+ return {
100
+ r: Math.round(r * 255),
101
+ g: Math.round(g * 255),
102
+ b: Math.round(b * 255)
103
+ }
104
+ }
105
+
106
+ export function isValidColor(color) {
107
+ if (!color) return false
108
+
109
+ const normalizedColor = color.trim()
110
+
111
+ if (/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(normalizedColor)) return true
112
+ if (/^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(,\s*[\d.]+\s*)?\)$/.test(normalizedColor)) return true
113
+ if (/^hsla?\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*(,\s*[\d.]+\s*)?\)$/.test(normalizedColor)) return true
114
+ if (/^hsba?\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*(,\s*[\d.]+\s*)?\)$/.test(normalizedColor)) return true
115
+
116
+ return false
117
+ }
118
+
119
+ function rgbToHsv(r, g, b) {
120
+ const normalizedR = r / 255
121
+ const normalizedG = g / 255
122
+ const normalizedB = b / 255
123
+
124
+ const max = Math.max(normalizedR, normalizedG, normalizedB)
125
+ const min = Math.min(normalizedR, normalizedG, normalizedB)
126
+ const delta = max - min
127
+
128
+ let h = 0
129
+ const s = max === 0 ? 0 : delta / max
130
+ const v = max
131
+
132
+ if (delta !== 0) {
133
+ if (max === normalizedR) {
134
+ h = ((normalizedG - normalizedB) / delta + (normalizedG < normalizedB ? 6 : 0)) / 6
135
+ } else if (max === normalizedG) {
136
+ h = ((normalizedB - normalizedR) / delta + 2) / 6
137
+ } else {
138
+ h = ((normalizedR - normalizedG) / delta + 4) / 6
139
+ }
140
+ }
141
+
142
+ return {
143
+ h: Math.round(h * 360),
144
+ s: Math.round(s * 100),
145
+ v: Math.round(v * 100)
146
+ }
147
+ }
148
+
149
+ function hexToHsv(hex) {
150
+ const normalizedHex = hex.replace("#", "")
151
+
152
+ const r = parseInt(normalizedHex.slice(0, 2), 16)
153
+ const g = parseInt(normalizedHex.slice(2, 4), 16)
154
+ const b = parseInt(normalizedHex.slice(4, 6), 16)
155
+
156
+ return rgbToHsv(r, g, b)
157
+ }
158
+
159
+ function hsvToHex(h, s, v, alpha = 1, { disabledAlpha = false } = {}) {
160
+ const rgb = hsvToRgb(h, s, v)
161
+ const hex = `#${toHex(rgb.r)}${toHex(rgb.g)}${toHex(rgb.b)}`
162
+
163
+ if (alpha < 1 && !disabledAlpha) {
164
+ const alphaHex = toHex(Math.round(alpha * 255))
165
+ return `${hex}${alphaHex}`
166
+ }
167
+
168
+ return hex
169
+ }
170
+
171
+ function toHex(n) {
172
+ const hex = n.toString(16)
173
+ return hex.length === 1 ? "0" + hex : hex
174
+ }
175
+
176
+ function rgbStringToHsv(rgbString) {
177
+ const match = rgbString.match(/rgba?\(([^)]+)\)/)
178
+ if (!match) return defaultHsv()
179
+
180
+ const [r, g, b] = match[1].split(",").map(part => parseInt(part.trim()))
181
+ return rgbToHsv(r, g, b)
182
+ }
183
+
184
+ function hsvToRgbString(h, s, v, alpha = 1, { disabledAlpha = false } = {}) {
185
+ const rgb = hsvToRgb(h, s, v)
186
+
187
+ if (alpha < 1 && !disabledAlpha) {
188
+ return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})`
189
+ }
190
+
191
+ return `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})`
192
+ }
193
+
194
+ function hslStringToHsv(hslString) {
195
+ const match = hslString.match(/hsla?\(([^)]+)\)/)
196
+ if (!match) return defaultHsv()
197
+
198
+ const parts = match[1].split(",").map(part => part.trim())
199
+ const h = parseFloat(parts[0])
200
+ const s = parseFloat(parts[1])
201
+ const l = parseFloat(parts[2])
202
+
203
+ return hslToHsv(h, s, l)
204
+ }
205
+
206
+ function hslToHsv(h, s, l) {
207
+ const normalizedS = s / 100
208
+ const normalizedL = l / 100
209
+
210
+ const v = normalizedL + normalizedS * Math.min(normalizedL, 1 - normalizedL)
211
+ const sv = v === 0 ? 0 : 2 * (1 - normalizedL / v)
212
+
213
+ return {
214
+ h: Math.round(h),
215
+ s: Math.round(sv * 100),
216
+ v: Math.round(v * 100)
217
+ }
218
+ }
219
+
220
+ function hsvToHsl(h, s, v) {
221
+ const normalizedS = s / 100
222
+ const normalizedV = v / 100
223
+
224
+ const l = normalizedV * (1 - normalizedS / 2)
225
+ const sl = l === 0 || l === 1 ? 0 : (normalizedV - l) / Math.min(l, 1 - l)
226
+
227
+ return {
228
+ h: Math.round(h),
229
+ s: Math.round(sl * 100),
230
+ l: Math.round(l * 100)
231
+ }
232
+ }
233
+
234
+ function hsvToHslString(h, s, v, alpha = 1, { disabledAlpha = false } = {}) {
235
+ const hsl = hsvToHsl(h, s, v)
236
+
237
+ if (alpha < 1 && !disabledAlpha) {
238
+ return `hsla(${hsl.h}, ${hsl.s}%, ${hsl.l}%, ${alpha})`
239
+ }
240
+
241
+ return `hsl(${hsl.h}, ${hsl.s}%, ${hsl.l}%)`
242
+ }
243
+
244
+ function hsbStringToHsv(hsbString) {
245
+ const match = hsbString.match(/hsba?\(([^)]+)\)/)
246
+ if (!match) return defaultHsv()
247
+
248
+ const parts = match[1].split(",").map(part => part.trim())
249
+ return {
250
+ h: Math.round(parseFloat(parts[0])),
251
+ s: Math.round(parseFloat(parts[1])),
252
+ v: Math.round(parseFloat(parts[2]))
253
+ }
254
+ }
255
+
256
+ function hsvToHsbString(h, s, v, alpha = 1, { disabledAlpha = false } = {}) {
257
+ if (alpha < 1 && !disabledAlpha) {
258
+ return `hsba(${h}, ${s}%, ${v}%, ${alpha})`
259
+ }
260
+
261
+ return `hsb(${h}, ${s}%, ${v}%)`
262
+ }
@@ -31,6 +31,15 @@ body {
31
31
  display: none !important;
32
32
  }
33
33
 
34
+ [data-hakumi-render-pending]:not([data-hakumi-ready="true"]) {
35
+ opacity: 0;
36
+ }
37
+
38
+ [data-hakumi-render-pending][data-hakumi-ready="true"] {
39
+ opacity: 1;
40
+ transition: opacity 0.15s ease;
41
+ }
42
+
34
43
  .hakumi-fade-enter,
35
44
  .hakumi-fade-appear {
36
45
  animation-duration: $transition-duration-base;
@@ -27,6 +27,7 @@
27
27
  @use "components/splitter";
28
28
  @use 'components/modal';
29
29
  @use 'components/drawer';
30
+ @use "components/form_item";
30
31
  @use "components/input";
31
32
  @use "components/input_number";
32
33
  @use "components/date_picker";
@@ -27,7 +27,7 @@
27
27
  .hakumi-breadcrumb-link {
28
28
  color: var(--color-text-secondary);
29
29
  text-decoration: none;
30
- transition: all 0.2s;
30
+ transition: all $transition-duration-base;
31
31
  }
32
32
 
33
33
  a.hakumi-breadcrumb-link {
@@ -63,7 +63,7 @@ a.hakumi-breadcrumb-link {
63
63
  padding: 2px 6px;
64
64
  border-radius: var(--border-radius-sm);
65
65
  cursor: pointer;
66
- transition: all 0.2s;
66
+ transition: all $transition-duration-base;
67
67
 
68
68
  &:hover {
69
69
  color: var(--color-text);
@@ -93,7 +93,7 @@
93
93
  margin: 0 4px;
94
94
  border-top: 2px solid transparent;
95
95
  border-radius: var(--border-radius);
96
- transition: background 0.2s;
96
+ transition: background $transition-duration-base;
97
97
  box-sizing: border-box;
98
98
 
99
99
  &:hover {
@@ -119,7 +119,7 @@
119
119
 
120
120
  .hakumi-calendar-cell-today .hakumi-calendar-date-value {
121
121
  background: var(--color-primary);
122
- color: #fff;
122
+ color: var(--color-text-inverse);
123
123
  border-radius: 50%;
124
124
  width: 24px;
125
125
  height: 24px;
@@ -138,7 +138,7 @@
138
138
  .hakumi-calendar-cell-range-start .hakumi-calendar-date-value,
139
139
  .hakumi-calendar-cell-range-end .hakumi-calendar-date-value {
140
140
  background: var(--color-primary);
141
- color: #fff;
141
+ color: var(--color-text-inverse);
142
142
  border-radius: 50%;
143
143
  width: 24px;
144
144
  height: 24px;
@@ -184,7 +184,7 @@
184
184
  height: 80px;
185
185
  padding: 8px 12px;
186
186
  border-radius: var(--border-radius);
187
- transition: background 0.2s;
187
+ transition: background $transition-duration-base;
188
188
  cursor: pointer;
189
189
 
190
190
  &:hover {
@@ -301,7 +301,7 @@
301
301
  line-height: 32px;
302
302
  border-radius: var(--border-radius);
303
303
  cursor: pointer;
304
- transition: all 0.2s;
304
+ transition: all $transition-duration-base;
305
305
 
306
306
  &:hover {
307
307
  background: var(--color-bg-spot);
@@ -318,7 +318,7 @@
318
318
 
319
319
  .hakumi-calendar-cell-selected .hakumi-calendar-date {
320
320
  background: var(--color-primary);
321
- color: #fff;
321
+ color: var(--color-text-inverse);
322
322
 
323
323
  &:hover {
324
324
  background: var(--color-primary-hover);
@@ -350,7 +350,7 @@
350
350
  justify-content: center;
351
351
  border-radius: var(--border-radius);
352
352
  cursor: pointer;
353
- transition: all 0.2s;
353
+ transition: all $transition-duration-base;
354
354
 
355
355
  &:hover {
356
356
  background: var(--color-bg-spot);
@@ -359,7 +359,7 @@
359
359
 
360
360
  .hakumi-calendar-cell-month.hakumi-calendar-cell-selected .hakumi-calendar-month-cell-inner {
361
361
  background: var(--color-primary);
362
- color: #fff;
362
+ color: var(--color-text-inverse);
363
363
  }
364
364
 
365
365
  .hakumi-calendar-month-value {
@@ -375,7 +375,7 @@
375
375
  .hakumi-calendar-cell-range-end {
376
376
  .hakumi-calendar-date {
377
377
  background: var(--color-primary);
378
- color: #fff;
378
+ color: var(--color-text-inverse);
379
379
 
380
380
  &:hover {
381
381
  background: var(--color-primary-hover);
@@ -494,7 +494,7 @@
494
494
  position: relative;
495
495
  cursor: pointer;
496
496
  color: var(--color-text);
497
- transition: background 0.2s, color 0.2s;
497
+ transition: background $transition-duration-base, color $transition-duration-base;
498
498
 
499
499
  &-in-view {
500
500
  color: var(--color-text);
@@ -547,7 +547,7 @@
547
547
  color: var(--color-text-tertiary);
548
548
  font-size: 12px;
549
549
  cursor: pointer;
550
- transition: background 0.2s, color 0.2s;
550
+ transition: background $transition-duration-base, color $transition-duration-base;
551
551
  }
552
552
 
553
553
  .hakumi-calendar-week-number {
@@ -644,7 +644,7 @@
644
644
  padding: 16px;
645
645
  border: 1px solid var(--color-border);
646
646
  border-radius: var(--border-radius-lg);
647
- transition: all 0.2s;
647
+ transition: all $transition-duration-base;
648
648
  cursor: pointer;
649
649
  display: flex;
650
650
  align-items: center;
@@ -699,7 +699,7 @@
699
699
  height: 60px;
700
700
  padding: 8px;
701
701
  border-radius: var(--border-radius);
702
- transition: all 0.2s;
702
+ transition: all $transition-duration-base;
703
703
  cursor: pointer;
704
704
  display: flex;
705
705
  align-items: center;
@@ -25,7 +25,7 @@
25
25
  background-color: var(--color-bg-container);
26
26
  border: 1px solid var(--color-border);
27
27
  border-radius: 6px;
28
- transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
28
+ transition: all $transition-duration-base $ease-in-out;
29
29
  width: 100%;
30
30
  height: 32px;
31
31
  padding: 0 30px 0 11px;
@@ -126,7 +126,7 @@
126
126
  margin-top: -6px;
127
127
  font-size: 12px;
128
128
  pointer-events: none;
129
- transition: transform 0.3s;
129
+ transition: transform $transition-duration-slow;
130
130
 
131
131
  .hakumi-cascader-open & {
132
132
  transform: rotate(180deg);
@@ -149,7 +149,7 @@
149
149
  background: var(--color-bg-container);
150
150
  cursor: pointer;
151
151
  opacity: 0;
152
- transition: color 0.3s ease, opacity 0.15s ease;
152
+ transition: color $transition-duration-slow ease, opacity 0.15s ease;
153
153
 
154
154
  &:hover {
155
155
  color: var(--color-text-tertiary);
@@ -173,7 +173,7 @@
173
173
  margin-top: 4px;
174
174
  background-color: var(--color-bg-elevated);
175
175
  border-radius: 8px;
176
- box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05);
176
+ box-shadow: var(--shadow-lg);
177
177
  display: flex;
178
178
  flex-direction: row;
179
179
  overflow: hidden;
@@ -217,7 +217,7 @@
217
217
  white-space: nowrap;
218
218
  text-overflow: ellipsis;
219
219
  cursor: pointer;
220
- transition: all 0.3s;
220
+ transition: all $transition-duration-slow;
221
221
  color: var(--color-text);
222
222
 
223
223
  &:hover {
@@ -78,15 +78,15 @@
78
78
  &::after {
79
79
  opacity: 1;
80
80
  transform: rotate(45deg) scale(1) translate(-50%, -50%);
81
- transition: all 0.2s cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
81
+ transition: all $transition-duration-base cubic-bezier(0.12, 0.4, 0.29, 1.46) 0.1s;
82
82
  }
83
83
  }
84
84
  }
85
85
 
86
86
  &-indeterminate {
87
87
  .hakumi-checkbox-inner {
88
- background-color: #fff;
89
- border-color: #d9d9d9;
88
+ background-color: var(--color-bg-container);
89
+ border-color: var(--color-border);
90
90
 
91
91
  &::after {
92
92
  top: 50%;
@@ -153,7 +153,7 @@
153
153
  border: 1px solid var(--color-border);
154
154
  border-radius: var(--border-radius-sm);
155
155
  border-collapse: separate;
156
- transition: all 0.3s;
156
+ transition: all $transition-duration-slow;
157
157
 
158
158
  &:after {
159
159
  position: absolute;
@@ -162,7 +162,7 @@
162
162
  display: table;
163
163
  width: 5.7142857142857135px;
164
164
  height: 9.142857142857142px;
165
- border: 2px solid #fff;
165
+ border: 2px solid var(--color-text-inverse);
166
166
  border-top: 0;
167
167
  border-left: 0;
168
168
  transform: rotate(45deg) scale(0) translate(-50%, -50%);
@@ -197,20 +197,18 @@
197
197
  }
198
198
 
199
199
 
200
- [data-theme='dark'] {
200
+ [data-theme="dark"] {
201
201
  .hakumi-checkbox-inner {
202
202
  background-color: transparent;
203
203
  }
204
204
 
205
205
  .hakumi-checkbox-disabled {
206
206
  .hakumi-checkbox-inner {
207
- background-color: rgba(255, 255, 255, 0.08);
208
-
209
- border-color: #434343;
210
-
207
+ background-color: var(--color-fill-secondary);
208
+ border-color: var(--color-border);
211
209
 
212
210
  &::after {
213
- border-color: rgba(255, 255, 255, 0.25);
211
+ border-color: var(--color-disabled);
214
212
  }
215
213
  }
216
214
  }