poetry-ui 0.0.2

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 (442) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +6 -0
  3. data/CHANGELOG.md +3 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +87 -0
  6. data/THIRD_PARTY_NOTICES.md +201 -0
  7. data/app/components/poetry/ui/accordion/component.html.erb +3 -0
  8. data/app/components/poetry/ui/accordion/component.rb +197 -0
  9. data/app/components/poetry/ui/accordion/preview.rb +39 -0
  10. data/app/components/poetry/ui/accordion/style.rb +37 -0
  11. data/app/components/poetry/ui/alert/component.html.erb +6 -0
  12. data/app/components/poetry/ui/alert/component.rb +61 -0
  13. data/app/components/poetry/ui/alert/preview.rb +35 -0
  14. data/app/components/poetry/ui/alert/style.rb +24 -0
  15. data/app/components/poetry/ui/alert_dialog/component.html.erb +17 -0
  16. data/app/components/poetry/ui/alert_dialog/component.rb +208 -0
  17. data/app/components/poetry/ui/alert_dialog/preview.rb +48 -0
  18. data/app/components/poetry/ui/alert_dialog/style.rb +46 -0
  19. data/app/components/poetry/ui/aspect_ratio/component.rb +63 -0
  20. data/app/components/poetry/ui/aspect_ratio/preview.rb +29 -0
  21. data/app/components/poetry/ui/aspect_ratio/style.rb +13 -0
  22. data/app/components/poetry/ui/attachment/component.html.erb +13 -0
  23. data/app/components/poetry/ui/attachment/component.rb +139 -0
  24. data/app/components/poetry/ui/attachment/preview.rb +83 -0
  25. data/app/components/poetry/ui/attachment/style.rb +59 -0
  26. data/app/components/poetry/ui/autocomplete/component.html.erb +16 -0
  27. data/app/components/poetry/ui/autocomplete/component.rb +193 -0
  28. data/app/components/poetry/ui/autocomplete/preview.rb +39 -0
  29. data/app/components/poetry/ui/autocomplete/style.rb +18 -0
  30. data/app/components/poetry/ui/avatar/component.rb +103 -0
  31. data/app/components/poetry/ui/avatar/group_preview.html.erb +11 -0
  32. data/app/components/poetry/ui/avatar/preview.rb +50 -0
  33. data/app/components/poetry/ui/avatar/style.rb +34 -0
  34. data/app/components/poetry/ui/badge/component.rb +73 -0
  35. data/app/components/poetry/ui/badge/preview.rb +54 -0
  36. data/app/components/poetry/ui/badge/style.rb +35 -0
  37. data/app/components/poetry/ui/breadcrumb/component.html.erb +32 -0
  38. data/app/components/poetry/ui/breadcrumb/component.rb +102 -0
  39. data/app/components/poetry/ui/breadcrumb/dropdown_crumb_preview.html.erb +21 -0
  40. data/app/components/poetry/ui/breadcrumb/preview.rb +45 -0
  41. data/app/components/poetry/ui/breadcrumb/style.rb +25 -0
  42. data/app/components/poetry/ui/bubble/component.html.erb +4 -0
  43. data/app/components/poetry/ui/bubble/component.rb +106 -0
  44. data/app/components/poetry/ui/bubble/preview.rb +62 -0
  45. data/app/components/poetry/ui/bubble/style.rb +47 -0
  46. data/app/components/poetry/ui/button/component.html.erb +14 -0
  47. data/app/components/poetry/ui/button/component.rb +168 -0
  48. data/app/components/poetry/ui/button/preview.rb +94 -0
  49. data/app/components/poetry/ui/button/style.rb +41 -0
  50. data/app/components/poetry/ui/button_group/component.rb +70 -0
  51. data/app/components/poetry/ui/button_group/popup_triggers_preview.html.erb +21 -0
  52. data/app/components/poetry/ui/button_group/preview.rb +46 -0
  53. data/app/components/poetry/ui/button_group/style.rb +27 -0
  54. data/app/components/poetry/ui/button_group/text_prefix_preview.html.erb +7 -0
  55. data/app/components/poetry/ui/calendar/component.html.erb +72 -0
  56. data/app/components/poetry/ui/calendar/component.rb +366 -0
  57. data/app/components/poetry/ui/calendar/preview.rb +55 -0
  58. data/app/components/poetry/ui/calendar/style.rb +55 -0
  59. data/app/components/poetry/ui/card/component.html.erb +11 -0
  60. data/app/components/poetry/ui/card/component.rb +90 -0
  61. data/app/components/poetry/ui/card/preview.rb +29 -0
  62. data/app/components/poetry/ui/card/style.rb +23 -0
  63. data/app/components/poetry/ui/carousel/component.html.erb +17 -0
  64. data/app/components/poetry/ui/carousel/component.rb +179 -0
  65. data/app/components/poetry/ui/carousel/preview.rb +67 -0
  66. data/app/components/poetry/ui/carousel/style.rb +39 -0
  67. data/app/components/poetry/ui/checkbox/component.html.erb +22 -0
  68. data/app/components/poetry/ui/checkbox/component.rb +179 -0
  69. data/app/components/poetry/ui/checkbox/preview.rb +68 -0
  70. data/app/components/poetry/ui/checkbox/style.rb +28 -0
  71. data/app/components/poetry/ui/clipboard_text/component.html.erb +15 -0
  72. data/app/components/poetry/ui/clipboard_text/component.rb +154 -0
  73. data/app/components/poetry/ui/clipboard_text/preview.rb +24 -0
  74. data/app/components/poetry/ui/clipboard_text/style.rb +23 -0
  75. data/app/components/poetry/ui/code_block/component.html.erb +13 -0
  76. data/app/components/poetry/ui/code_block/component.rb +141 -0
  77. data/app/components/poetry/ui/code_block/preview.rb +40 -0
  78. data/app/components/poetry/ui/code_block/style.rb +38 -0
  79. data/app/components/poetry/ui/collapsible/component.html.erb +4 -0
  80. data/app/components/poetry/ui/collapsible/component.rb +134 -0
  81. data/app/components/poetry/ui/collapsible/preview.rb +24 -0
  82. data/app/components/poetry/ui/combobox/component.html.erb +49 -0
  83. data/app/components/poetry/ui/combobox/component.rb +1086 -0
  84. data/app/components/poetry/ui/combobox/preview.rb +164 -0
  85. data/app/components/poetry/ui/combobox/style.rb +148 -0
  86. data/app/components/poetry/ui/command/component.html.erb +20 -0
  87. data/app/components/poetry/ui/command/component.rb +526 -0
  88. data/app/components/poetry/ui/command/dialog_component.html.erb +14 -0
  89. data/app/components/poetry/ui/command/dialog_component.rb +206 -0
  90. data/app/components/poetry/ui/command/dialog_preview.rb +39 -0
  91. data/app/components/poetry/ui/command/preview.rb +121 -0
  92. data/app/components/poetry/ui/command/style.rb +78 -0
  93. data/app/components/poetry/ui/composable_trigger.rb +63 -0
  94. data/app/components/poetry/ui/context_menu/component.html.erb +6 -0
  95. data/app/components/poetry/ui/context_menu/component.rb +358 -0
  96. data/app/components/poetry/ui/context_menu/preview.rb +111 -0
  97. data/app/components/poetry/ui/context_menu/style.rb +59 -0
  98. data/app/components/poetry/ui/data_table/component.html.erb +78 -0
  99. data/app/components/poetry/ui/data_table/component.rb +277 -0
  100. data/app/components/poetry/ui/data_table/preview.rb +68 -0
  101. data/app/components/poetry/ui/data_table/state.rb +115 -0
  102. data/app/components/poetry/ui/data_table/style.rb +42 -0
  103. data/app/components/poetry/ui/date_field/component.html.erb +7 -0
  104. data/app/components/poetry/ui/date_field/component.rb +209 -0
  105. data/app/components/poetry/ui/date_field/preview.rb +42 -0
  106. data/app/components/poetry/ui/date_field/style.rb +35 -0
  107. data/app/components/poetry/ui/date_picker/component.html.erb +23 -0
  108. data/app/components/poetry/ui/date_picker/component.rb +242 -0
  109. data/app/components/poetry/ui/date_picker/preview.rb +31 -0
  110. data/app/components/poetry/ui/date_picker/style.rb +25 -0
  111. data/app/components/poetry/ui/deferred/component.html.erb +16 -0
  112. data/app/components/poetry/ui/deferred/component.rb +90 -0
  113. data/app/components/poetry/ui/deferred/preview.rb +24 -0
  114. data/app/components/poetry/ui/dialog/component.html.erb +21 -0
  115. data/app/components/poetry/ui/dialog/component.rb +194 -0
  116. data/app/components/poetry/ui/dialog/preview.rb +33 -0
  117. data/app/components/poetry/ui/dialog/style.rb +30 -0
  118. data/app/components/poetry/ui/drawer/component.html.erb +16 -0
  119. data/app/components/poetry/ui/drawer/component.rb +207 -0
  120. data/app/components/poetry/ui/drawer/preview.rb +69 -0
  121. data/app/components/poetry/ui/drawer/style.rb +105 -0
  122. data/app/components/poetry/ui/dropdown_menu/component.html.erb +6 -0
  123. data/app/components/poetry/ui/dropdown_menu/component.rb +350 -0
  124. data/app/components/poetry/ui/dropdown_menu/preview.rb +101 -0
  125. data/app/components/poetry/ui/dropdown_menu/style.rb +60 -0
  126. data/app/components/poetry/ui/empty/component.html.erb +10 -0
  127. data/app/components/poetry/ui/empty/component.rb +79 -0
  128. data/app/components/poetry/ui/empty/preview.rb +27 -0
  129. data/app/components/poetry/ui/empty/style.rb +27 -0
  130. data/app/components/poetry/ui/family_identity.rb +52 -0
  131. data/app/components/poetry/ui/field/component.html.erb +19 -0
  132. data/app/components/poetry/ui/field/component.rb +183 -0
  133. data/app/components/poetry/ui/field/preview.html.erb +30 -0
  134. data/app/components/poetry/ui/field/preview.rb +72 -0
  135. data/app/components/poetry/ui/field/style.rb +68 -0
  136. data/app/components/poetry/ui/field_group/component.rb +61 -0
  137. data/app/components/poetry/ui/field_group/preview.html.erb +30 -0
  138. data/app/components/poetry/ui/field_group/preview.rb +20 -0
  139. data/app/components/poetry/ui/field_group/style.rb +25 -0
  140. data/app/components/poetry/ui/field_separator/component.rb +70 -0
  141. data/app/components/poetry/ui/field_separator/preview.rb +18 -0
  142. data/app/components/poetry/ui/field_separator/style.rb +20 -0
  143. data/app/components/poetry/ui/fieldset/component.rb +90 -0
  144. data/app/components/poetry/ui/fieldset/preview.html.erb +22 -0
  145. data/app/components/poetry/ui/fieldset/preview.rb +25 -0
  146. data/app/components/poetry/ui/fieldset/style.rb +18 -0
  147. data/app/components/poetry/ui/file_input/component.html.erb +14 -0
  148. data/app/components/poetry/ui/file_input/component.rb +188 -0
  149. data/app/components/poetry/ui/file_input/preview.rb +30 -0
  150. data/app/components/poetry/ui/file_input/style.rb +35 -0
  151. data/app/components/poetry/ui/hover_card/component.html.erb +6 -0
  152. data/app/components/poetry/ui/hover_card/component.rb +201 -0
  153. data/app/components/poetry/ui/hover_card/preview.rb +60 -0
  154. data/app/components/poetry/ui/hover_card/style.rb +17 -0
  155. data/app/components/poetry/ui/icon/component.rb +127 -0
  156. data/app/components/poetry/ui/icon/preview.rb +21 -0
  157. data/app/components/poetry/ui/input/component.rb +80 -0
  158. data/app/components/poetry/ui/input/preview.rb +35 -0
  159. data/app/components/poetry/ui/input/style.rb +18 -0
  160. data/app/components/poetry/ui/input_group/button_preview.html.erb +12 -0
  161. data/app/components/poetry/ui/input_group/component.rb +69 -0
  162. data/app/components/poetry/ui/input_group/preview.rb +23 -0
  163. data/app/components/poetry/ui/input_group/search_preview.html.erb +13 -0
  164. data/app/components/poetry/ui/input_group/style.rb +40 -0
  165. data/app/components/poetry/ui/input_group/textarea_preview.html.erb +10 -0
  166. data/app/components/poetry/ui/input_group_field.rb +61 -0
  167. data/app/components/poetry/ui/input_otp/component.html.erb +25 -0
  168. data/app/components/poetry/ui/input_otp/component.rb +250 -0
  169. data/app/components/poetry/ui/input_otp/preview.rb +91 -0
  170. data/app/components/poetry/ui/input_otp/style.rb +36 -0
  171. data/app/components/poetry/ui/item/component.html.erb +13 -0
  172. data/app/components/poetry/ui/item/component.rb +99 -0
  173. data/app/components/poetry/ui/item/group_preview.html.erb +15 -0
  174. data/app/components/poetry/ui/item/preview.rb +52 -0
  175. data/app/components/poetry/ui/item/style.rb +45 -0
  176. data/app/components/poetry/ui/kbd/component.rb +47 -0
  177. data/app/components/poetry/ui/kbd/group_preview.html.erb +4 -0
  178. data/app/components/poetry/ui/kbd/preview.rb +23 -0
  179. data/app/components/poetry/ui/kbd/style.rb +13 -0
  180. data/app/components/poetry/ui/label/component.rb +46 -0
  181. data/app/components/poetry/ui/label/preview.html.erb +5 -0
  182. data/app/components/poetry/ui/label/preview.rb +16 -0
  183. data/app/components/poetry/ui/label/style.rb +13 -0
  184. data/app/components/poetry/ui/link/component.rb +62 -0
  185. data/app/components/poetry/ui/link/preview.rb +31 -0
  186. data/app/components/poetry/ui/link/style.rb +20 -0
  187. data/app/components/poetry/ui/marker/component.html.erb +4 -0
  188. data/app/components/poetry/ui/marker/component.rb +81 -0
  189. data/app/components/poetry/ui/marker/preview.rb +43 -0
  190. data/app/components/poetry/ui/marker/style.rb +24 -0
  191. data/app/components/poetry/ui/menubar/component.html.erb +3 -0
  192. data/app/components/poetry/ui/menubar/component.rb +493 -0
  193. data/app/components/poetry/ui/menubar/preview.rb +164 -0
  194. data/app/components/poetry/ui/menubar/style.rb +71 -0
  195. data/app/components/poetry/ui/menus.rb +386 -0
  196. data/app/components/poetry/ui/message/component.html.erb +8 -0
  197. data/app/components/poetry/ui/message/component.rb +64 -0
  198. data/app/components/poetry/ui/message/preview.rb +33 -0
  199. data/app/components/poetry/ui/message/style.rb +29 -0
  200. data/app/components/poetry/ui/message_scroller/component.html.erb +15 -0
  201. data/app/components/poetry/ui/message_scroller/component.rb +163 -0
  202. data/app/components/poetry/ui/message_scroller/preview.rb +33 -0
  203. data/app/components/poetry/ui/message_scroller/style.rb +39 -0
  204. data/app/components/poetry/ui/metadata_list/component.rb +88 -0
  205. data/app/components/poetry/ui/metadata_list/preview.rb +55 -0
  206. data/app/components/poetry/ui/metadata_list/style.rb +35 -0
  207. data/app/components/poetry/ui/meter/component.rb +117 -0
  208. data/app/components/poetry/ui/meter/preview.rb +28 -0
  209. data/app/components/poetry/ui/meter/style.rb +16 -0
  210. data/app/components/poetry/ui/native_select/component.rb +124 -0
  211. data/app/components/poetry/ui/native_select/labelled_preview.html.erb +7 -0
  212. data/app/components/poetry/ui/native_select/preview.rb +20 -0
  213. data/app/components/poetry/ui/native_select/style.rb +22 -0
  214. data/app/components/poetry/ui/navigation_menu/bar_preview.html.erb +14 -0
  215. data/app/components/poetry/ui/navigation_menu/component.html.erb +25 -0
  216. data/app/components/poetry/ui/navigation_menu/component.rb +254 -0
  217. data/app/components/poetry/ui/navigation_menu/preview.rb +20 -0
  218. data/app/components/poetry/ui/navigation_menu/style.rb +73 -0
  219. data/app/components/poetry/ui/navigation_menu/viewport_preview.html.erb +23 -0
  220. data/app/components/poetry/ui/number_field/component.html.erb +19 -0
  221. data/app/components/poetry/ui/number_field/component.rb +263 -0
  222. data/app/components/poetry/ui/number_field/preview.rb +66 -0
  223. data/app/components/poetry/ui/number_field/style.rb +14 -0
  224. data/app/components/poetry/ui/pagination/component.html.erb +40 -0
  225. data/app/components/poetry/ui/pagination/component.rb +182 -0
  226. data/app/components/poetry/ui/pagination/preview.rb +47 -0
  227. data/app/components/poetry/ui/pagination/style.rb +27 -0
  228. data/app/components/poetry/ui/popover/component.html.erb +17 -0
  229. data/app/components/poetry/ui/popover/component.rb +203 -0
  230. data/app/components/poetry/ui/popover/preview.html.erb +29 -0
  231. data/app/components/poetry/ui/popover/preview.rb +66 -0
  232. data/app/components/poetry/ui/popover/style.rb +26 -0
  233. data/app/components/poetry/ui/popper_consumer.rb +69 -0
  234. data/app/components/poetry/ui/progress/component.rb +95 -0
  235. data/app/components/poetry/ui/progress/preview.rb +22 -0
  236. data/app/components/poetry/ui/progress/style.rb +19 -0
  237. data/app/components/poetry/ui/questionnaire/component.html.erb +80 -0
  238. data/app/components/poetry/ui/questionnaire/component.rb +396 -0
  239. data/app/components/poetry/ui/questionnaire/preview.rb +99 -0
  240. data/app/components/poetry/ui/questionnaire/style.rb +53 -0
  241. data/app/components/poetry/ui/radio_group/component.html.erb +4 -0
  242. data/app/components/poetry/ui/radio_group/component.rb +323 -0
  243. data/app/components/poetry/ui/radio_group/preview.rb +109 -0
  244. data/app/components/poetry/ui/radio_group/style.rb +53 -0
  245. data/app/components/poetry/ui/resizable/component.html.erb +10 -0
  246. data/app/components/poetry/ui/resizable/component.rb +178 -0
  247. data/app/components/poetry/ui/resizable/preview.rb +42 -0
  248. data/app/components/poetry/ui/resizable/style.rb +30 -0
  249. data/app/components/poetry/ui/scroll_area/component.rb +76 -0
  250. data/app/components/poetry/ui/scroll_area/preview.rb +35 -0
  251. data/app/components/poetry/ui/scroll_area/style.rb +19 -0
  252. data/app/components/poetry/ui/search_field/component.html.erb +15 -0
  253. data/app/components/poetry/ui/search_field/component.rb +137 -0
  254. data/app/components/poetry/ui/search_field/preview.rb +23 -0
  255. data/app/components/poetry/ui/search_field/style.rb +18 -0
  256. data/app/components/poetry/ui/select/component.html.erb +15 -0
  257. data/app/components/poetry/ui/select/component.rb +639 -0
  258. data/app/components/poetry/ui/select/preview.rb +113 -0
  259. data/app/components/poetry/ui/select/style.rb +58 -0
  260. data/app/components/poetry/ui/sensitive_input/component.html.erb +29 -0
  261. data/app/components/poetry/ui/sensitive_input/component.rb +274 -0
  262. data/app/components/poetry/ui/sensitive_input/preview.rb +40 -0
  263. data/app/components/poetry/ui/sensitive_input/style.rb +49 -0
  264. data/app/components/poetry/ui/separator/component.rb +57 -0
  265. data/app/components/poetry/ui/separator/preview.rb +19 -0
  266. data/app/components/poetry/ui/separator/style.rb +15 -0
  267. data/app/components/poetry/ui/sheet/component.html.erb +21 -0
  268. data/app/components/poetry/ui/sheet/component.rb +97 -0
  269. data/app/components/poetry/ui/sheet/preview.rb +57 -0
  270. data/app/components/poetry/ui/sheet/style.rb +47 -0
  271. data/app/components/poetry/ui/sidebar/component.html.erb +20 -0
  272. data/app/components/poetry/ui/sidebar/component.rb +249 -0
  273. data/app/components/poetry/ui/sidebar/preview.rb +21 -0
  274. data/app/components/poetry/ui/sidebar/shell_preview.html.erb +47 -0
  275. data/app/components/poetry/ui/sidebar/style.rb +139 -0
  276. data/app/components/poetry/ui/skeleton/component.rb +39 -0
  277. data/app/components/poetry/ui/skeleton/preview.rb +22 -0
  278. data/app/components/poetry/ui/skeleton/style.rb +13 -0
  279. data/app/components/poetry/ui/slider/component.html.erb +13 -0
  280. data/app/components/poetry/ui/slider/component.rb +360 -0
  281. data/app/components/poetry/ui/slider/preview.rb +73 -0
  282. data/app/components/poetry/ui/slider/style.rb +55 -0
  283. data/app/components/poetry/ui/spinner/component.rb +58 -0
  284. data/app/components/poetry/ui/spinner/preview.rb +22 -0
  285. data/app/components/poetry/ui/spinner/style.rb +12 -0
  286. data/app/components/poetry/ui/stat/component.html.erb +13 -0
  287. data/app/components/poetry/ui/stat/component.rb +102 -0
  288. data/app/components/poetry/ui/stat/preview.rb +47 -0
  289. data/app/components/poetry/ui/stat/style.rb +29 -0
  290. data/app/components/poetry/ui/switch/component.html.erb +15 -0
  291. data/app/components/poetry/ui/switch/component.rb +136 -0
  292. data/app/components/poetry/ui/switch/preview.rb +66 -0
  293. data/app/components/poetry/ui/switch/style.rb +22 -0
  294. data/app/components/poetry/ui/table/component.html.erb +3 -0
  295. data/app/components/poetry/ui/table/component.rb +93 -0
  296. data/app/components/poetry/ui/table/preview.rb +96 -0
  297. data/app/components/poetry/ui/table/style.rb +26 -0
  298. data/app/components/poetry/ui/tabs/component.html.erb +10 -0
  299. data/app/components/poetry/ui/tabs/component.rb +253 -0
  300. data/app/components/poetry/ui/tabs/preview.rb +43 -0
  301. data/app/components/poetry/ui/tabs/style.rb +49 -0
  302. data/app/components/poetry/ui/tag_group/component.html.erb +8 -0
  303. data/app/components/poetry/ui/tag_group/component.rb +203 -0
  304. data/app/components/poetry/ui/tag_group/preview.rb +43 -0
  305. data/app/components/poetry/ui/tag_group/style.rb +29 -0
  306. data/app/components/poetry/ui/textarea/component.rb +64 -0
  307. data/app/components/poetry/ui/textarea/preview.rb +75 -0
  308. data/app/components/poetry/ui/textarea/style.rb +18 -0
  309. data/app/components/poetry/ui/time_field/component.html.erb +6 -0
  310. data/app/components/poetry/ui/time_field/component.rb +85 -0
  311. data/app/components/poetry/ui/time_field/preview.rb +40 -0
  312. data/app/components/poetry/ui/time_field/style.rb +30 -0
  313. data/app/components/poetry/ui/timeline/component.rb +134 -0
  314. data/app/components/poetry/ui/timeline/preview.rb +61 -0
  315. data/app/components/poetry/ui/timeline/style.rb +54 -0
  316. data/app/components/poetry/ui/toast/component.html.erb +24 -0
  317. data/app/components/poetry/ui/toast/component.rb +178 -0
  318. data/app/components/poetry/ui/toast/preview.rb +69 -0
  319. data/app/components/poetry/ui/toast/style.rb +33 -0
  320. data/app/components/poetry/ui/toast_trigger/addressed_preview.html.erb +12 -0
  321. data/app/components/poetry/ui/toast_trigger/component.html.erb +3 -0
  322. data/app/components/poetry/ui/toast_trigger/component.rb +82 -0
  323. data/app/components/poetry/ui/toast_trigger/default_preview.html.erb +11 -0
  324. data/app/components/poetry/ui/toast_trigger/preview.rb +19 -0
  325. data/app/components/poetry/ui/toaster/component.html.erb +1 -0
  326. data/app/components/poetry/ui/toaster/component.rb +99 -0
  327. data/app/components/poetry/ui/toaster/positions_preview.html.erb +24 -0
  328. data/app/components/poetry/ui/toaster/preview.rb +46 -0
  329. data/app/components/poetry/ui/toaster/stamp_preview.html.erb +15 -0
  330. data/app/components/poetry/ui/toaster/style.rb +26 -0
  331. data/app/components/poetry/ui/toggle/component.rb +120 -0
  332. data/app/components/poetry/ui/toggle/preview.rb +79 -0
  333. data/app/components/poetry/ui/toggle/style.rb +33 -0
  334. data/app/components/poetry/ui/toggle_group/component.html.erb +4 -0
  335. data/app/components/poetry/ui/toggle_group/component.rb +252 -0
  336. data/app/components/poetry/ui/toggle_group/preview.rb +143 -0
  337. data/app/components/poetry/ui/toggle_group/style.rb +33 -0
  338. data/app/components/poetry/ui/toolbar/component.rb +125 -0
  339. data/app/components/poetry/ui/toolbar/preview.rb +41 -0
  340. data/app/components/poetry/ui/toolbar/style.rb +20 -0
  341. data/app/components/poetry/ui/tooltip/component.html.erb +20 -0
  342. data/app/components/poetry/ui/tooltip/component.rb +185 -0
  343. data/app/components/poetry/ui/tooltip/preview.rb +74 -0
  344. data/app/components/poetry/ui/tooltip/previews/provider_row.html.erb +25 -0
  345. data/app/components/poetry/ui/tooltip/style.rb +24 -0
  346. data/app/components/poetry/ui/tree/component.html.erb +32 -0
  347. data/app/components/poetry/ui/tree/component.rb +233 -0
  348. data/app/components/poetry/ui/tree/preview.rb +55 -0
  349. data/app/components/poetry/ui/tree/style.rb +29 -0
  350. data/app/components/poetry/ui/typeset/component.rb +73 -0
  351. data/app/components/poetry/ui/typeset/preview.rb +45 -0
  352. data/app/components/poetry/ui/typeset/style.rb +15 -0
  353. data/app/controllers/poetry/ui/llms_controller.rb +28 -0
  354. data/app/helpers/poetry/ui/components_helper.rb +1794 -0
  355. data/app/helpers/poetry/ui/form_builder/type_inference.rb +117 -0
  356. data/app/helpers/poetry/ui/form_builder.rb +916 -0
  357. data/app/helpers/poetry/ui/optimistic_form_builder.rb +55 -0
  358. data/app/helpers/poetry/ui/toast_stream_actions.rb +27 -0
  359. data/config/component_descriptions.yml +96 -0
  360. data/config/component_registry.yml +12257 -0
  361. data/config/locales/en.yml +93 -0
  362. data/config/routes.rb +8 -0
  363. data/config/template_classes.txt +113 -0
  364. data/lib/generators/poetry/add/add_generator.rb +218 -0
  365. data/lib/generators/poetry/agent_rules/agent_rules_generator.rb +91 -0
  366. data/lib/generators/poetry/agents/agents_generator.rb +24 -0
  367. data/lib/generators/poetry/agents_section.rb +148 -0
  368. data/lib/generators/poetry/block/block_generator.rb +67 -0
  369. data/lib/generators/poetry/block/templates/action_bar.html.erb +45 -0
  370. data/lib/generators/poetry/block/templates/app_shell.html.erb +139 -0
  371. data/lib/generators/poetry/block/templates/data_index.html.erb +85 -0
  372. data/lib/generators/poetry/block/templates/destructive_panel.html.erb +26 -0
  373. data/lib/generators/poetry/block/templates/page_header.html.erb +25 -0
  374. data/lib/generators/poetry/block/templates/section_card.html.erb +42 -0
  375. data/lib/generators/poetry/block/templates/stepper.html.erb +79 -0
  376. data/lib/generators/poetry/block/templates/top_nav.html.erb +44 -0
  377. data/lib/generators/poetry/diff/diff_generator.rb +135 -0
  378. data/lib/generators/poetry/editor/editor_generator.rb +344 -0
  379. data/lib/generators/poetry/editor/templates/poetry-check-hook +81 -0
  380. data/lib/generators/poetry/install/install_generator.rb +364 -0
  381. data/lib/generators/poetry/pagination/pagination_generator.rb +76 -0
  382. data/lib/generators/poetry/pagination/templates/kaminari_paginator.html.erb +29 -0
  383. data/lib/generators/poetry/pagination/templates/poetry_link_renderer.rb +34 -0
  384. data/lib/generators/poetry/pagination/templates/poetry_pagy_helper.rb +28 -0
  385. data/lib/generators/poetry/recipes/agent_embed/app/javascript/controllers/agent_demo_controller.js +131 -0
  386. data/lib/generators/poetry/recipes/screen_data_index/app/controllers/orders_controller.rb +15 -0
  387. data/lib/generators/poetry/recipes/screen_data_index/app/views/orders/index.html.erb +7 -0
  388. data/lib/generators/poetry/recipes/screen_data_index/test/system/orders_index_test.rb +16 -0
  389. data/lib/generators/poetry/recipes/screen_settings/app/controllers/settings_controller.rb +14 -0
  390. data/lib/generators/poetry/recipes/screen_settings/app/views/settings/show.html.erb +9 -0
  391. data/lib/generators/poetry/recipes/screen_settings/test/system/settings_show_test.rb +16 -0
  392. data/lib/generators/poetry/scaffold_templates/scaffold_templates_generator.rb +60 -0
  393. data/lib/generators/poetry/scaffold_templates/templates/_form.html.erb.tt +77 -0
  394. data/lib/generators/poetry/scaffold_templates/templates/controller.rb.tt +78 -0
  395. data/lib/generators/poetry/scaffold_templates/templates/edit.html.erb.tt +14 -0
  396. data/lib/generators/poetry/scaffold_templates/templates/index.html.erb.tt +24 -0
  397. data/lib/generators/poetry/scaffold_templates/templates/new.html.erb.tt +11 -0
  398. data/lib/generators/poetry/scaffold_templates/templates/partial.html.erb.tt +13 -0
  399. data/lib/generators/poetry/scaffold_templates/templates/show.html.erb.tt +18 -0
  400. data/lib/generators/poetry/skill/skill_generator.rb +34 -0
  401. data/lib/generators/poetry/skill/templates/poetry-component/SKILL.md +58 -0
  402. data/lib/generators/poetry/skill/templates/poetry-component/references/anatomy.md +152 -0
  403. data/lib/generators/poetry/skill/templates/poetry-component/references/checklist.md +67 -0
  404. data/lib/generators/poetry/skill/templates/poetry-component/references/documentation.md +137 -0
  405. data/lib/generators/poetry/skill/templates/poetry-design/SKILL.md +56 -0
  406. data/lib/generators/poetry/skill/templates/poetry-design/references/audit.md +123 -0
  407. data/lib/generators/poetry/skill/templates/poetry-design/references/compose.md +73 -0
  408. data/lib/generators/poetry/skill/templates/poetry-design/references/figma.md +68 -0
  409. data/lib/generators/poetry/skill/templates/poetry-design/references/paper.md +56 -0
  410. data/lib/generators/poetry/skill/templates/poetry-design/references/study.md +47 -0
  411. data/lib/generators/poetry/skill/templates/poetry-design/references/theme.md +70 -0
  412. data/lib/generators/poetry/skills_section.rb +58 -0
  413. data/lib/poetry/ui/chat.rb +283 -0
  414. data/lib/poetry/ui/code_block_highlighter.rb +60 -0
  415. data/lib/poetry/ui/engine.rb +55 -0
  416. data/lib/poetry/ui/recipes.rb +157 -0
  417. data/lib/poetry/ui/testing/combobox.rb +167 -0
  418. data/lib/poetry/ui/testing/dialog.rb +73 -0
  419. data/lib/poetry/ui/testing/menu.rb +127 -0
  420. data/lib/poetry/ui/testing/registration.rb +58 -0
  421. data/lib/poetry/ui/testing/select.rb +147 -0
  422. data/lib/poetry/ui/testing/tester.rb +130 -0
  423. data/lib/poetry/ui/testing.rb +130 -0
  424. data/lib/poetry/ui/themes.rb +109 -0
  425. data/lib/poetry/ui/version.rb +8 -0
  426. data/lib/poetry/ui/webmcp.rb +91 -0
  427. data/lib/poetry/ui.rb +285 -0
  428. data/lib/poetry-ui.rb +5 -0
  429. data/lib/tasks/poetry/check.rake +73 -0
  430. data/lib/tasks/poetry/design.rake +293 -0
  431. data/lib/tasks/poetry/verify.rake +36 -0
  432. data/themes/default.css +1793 -0
  433. data/themes/luma.css +1764 -0
  434. data/themes/lyra.css +1768 -0
  435. data/themes/maia.css +1768 -0
  436. data/themes/mira.css +1760 -0
  437. data/themes/nova.css +1755 -0
  438. data/themes/rhea.css +1771 -0
  439. data/themes/sera.css +1757 -0
  440. data/themes/vega.css +1775 -0
  441. data/typeset/typeset.css +499 -0
  442. metadata +502 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a7e5a4ac13adb19047199d51de9fc0077d10f3b89d74302fc738a10db528dc63
4
+ data.tar.gz: 2100d959fc3e89a3c189b6b8350ca4a22d41eda259a286fb071b898e88c9b56d
5
+ SHA512:
6
+ metadata.gz: 8416f0e954b93265431f796ad2f2f42aea2a68c0f912dc7d6d83f224dc30c0c264a0ece1d806e4a0fca567c558e1a592eaa63e445fb8e25c20f98e1ff870c3dc
7
+ data.tar.gz: a92f9fb002bb8eb856c2f9810d6733a6234fe95e72131d60cd8e173f943210b7a616681626afc0a40c3cd90ecdcd1c4da0791722cc2b09574395780a734bba6c
data/.gitattributes ADDED
@@ -0,0 +1,6 @@
1
+ # GitHub language stats (Linguist). The eval results are harness output
2
+ # (generated markup, judge verdicts, captures), and the Hotwire files under
3
+ # the dummy's vendor dir are vendored test assets; neither is this gem's
4
+ # source. Without this the repo reads as HTML instead of Ruby.
5
+ eval/results/** linguist-generated
6
+ test/dummy/public/vendor/** linguist-vendored
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased]
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2026 Matt Solt
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # poetry-ui
2
+
3
+ Server-rendered UI components for Rails — the shadcn/ui component set as
4
+ ViewComponents on Stimulus, with nine complete visual themes, a
5
+ machine-readable component registry, and a full agent surface (llms.txt,
6
+ MCP, Claude Code skills, `poetry check`). Names are working titles; the
7
+ gems are unpublished.
8
+
9
+ ## Install
10
+
11
+ ```ruby
12
+ # Gemfile
13
+ gem "poetry-core"
14
+ gem "poetry-ui"
15
+ gem "poetry-lucide" # default icon set
16
+ # gem "poetry-charts" # optional
17
+ ```
18
+
19
+ ```bash
20
+ bundle install
21
+ bin/rails g poetry:install --theme default # or vega, nova, mira, rhea, maia, luma, lyra, sera
22
+ ```
23
+
24
+ The installer wires everything a host needs: the vendored token/theme CSS
25
+ set under `app/assets/tailwind/poetry/`, the Tailwind entry imports, the
26
+ class safelist, Stimulus controller registration, the engine mount
27
+ (llms.txt), an `AGENTS.md` section, and the Claude Code skills. Every step
28
+ is idempotent — file creations skip what exists, injections append only
29
+ missing lines, and the section/skills refresh in place.
30
+
31
+ Add `--charts` to wire poetry-charts (requires the gem in the bundle).
32
+
33
+ ## Upgrade
34
+
35
+ **The install generator is the upgrade path, not a one-shot.** After
36
+ bumping the gems, re-run it:
37
+
38
+ ```bash
39
+ bundle update poetry-core poetry-ui poetry-charts
40
+ bin/rails g poetry:install # your theme choice sticks; --theme switches
41
+ bin/rails tailwindcss:build # or your CSS build
42
+ bin/rails test # confirm the app still renders
43
+ ```
44
+
45
+ The re-run refreshes what only it can refresh: the vendored CSS files
46
+ (new components ship their theme rules there) and the safelist (new
47
+ classes would otherwise be purged), plus any new wiring lines, the
48
+ AGENTS.md section, and the skills. Gem-owned code — components, templates,
49
+ Stimulus controllers, the registry and MCP surface — upgrades with
50
+ `bundle update` alone.
51
+
52
+ Copied-in code is yours and is never rewritten. To see where your copies
53
+ stand against the gems you now have installed:
54
+
55
+ ```bash
56
+ bin/rails g poetry:diff # read-only drift report for copy-ins
57
+ bin/rails g poetry:add <name> # adds newly-shipped files, never overwrites
58
+ ```
59
+
60
+ And `rails g scaffold` itself can produce poetry-composed views — a
61
+ DataTable index with sanitized URL state, Field-composed forms, and a
62
+ matching controller — by installing the app-owned template overrides once:
63
+
64
+ ```bash
65
+ bin/rails g poetry:scaffold_templates
66
+ ```
67
+
68
+ Three ownership tiers, three upgrade behaviors:
69
+
70
+ | Tier | Examples | Upgrades via |
71
+ |---|---|---|
72
+ | Gem-owned | components, controllers, registry, MCP | `bundle update` |
73
+ | Vendored into the app | `app/assets/tailwind/poetry/*`, safelist | re-run `poetry:install` |
74
+ | App-owned copy-ins | `poetry:add` components, blocks, `base.css`, initializer | you — `poetry:diff` reports |
75
+
76
+ ## Agent surface
77
+
78
+ `/poetry/llms.txt` and `/poetry/llms-full.txt` (engine routes), the
79
+ `poetry` MCP server (`bundle exec poetry-agent` from the poetry-agent gem, boot-free), `bin/rails
80
+ poetry:check` (template verification — run it last), and the `poetry` /
81
+ `poetry-design` / `poetry-component` Claude Code skills. See the generated
82
+ `AGENTS.md` section in your app.
83
+
84
+ ## License
85
+
86
+ Available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
87
+ See `THIRD_PARTY_NOTICES.md` for adapted code.
@@ -0,0 +1,201 @@
1
+ # Third-party notices - poetry-ui
2
+
3
+ poetry-ui's component surface ports or adapts design and behavior from
4
+ the MIT-licensed projects below. This file is the canonical source
5
+ attribution; the license texts are reproduced here.
6
+
7
+ ## shadcn/ui
8
+
9
+ - Source: https://github.com/shadcn-ui/ui (MIT)
10
+ - The component vocabulary, markup anatomy, class dictionaries, themes, and the typeset port are derived from shadcn/ui
11
+
12
+ ```
13
+ MIT License
14
+
15
+ Copyright (c) 2023 shadcn
16
+
17
+ Permission is hereby granted, free of charge, to any person obtaining a copy
18
+ of this software and associated documentation files (the "Software"), to deal
19
+ in the Software without restriction, including without limitation the rights
20
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21
+ copies of the Software, and to permit persons to whom the Software is
22
+ furnished to do so, subject to the following conditions:
23
+
24
+ The above copyright notice and this permission notice shall be included in all
25
+ copies or substantial portions of the Software.
26
+
27
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
+ SOFTWARE.
34
+ ```
35
+
36
+ ## Base UI
37
+
38
+ - Source: https://github.com/mui/base-ui (MIT)
39
+ - Part anatomy and interaction behavior for the primitive-backed components
40
+
41
+ ```
42
+ MIT License
43
+
44
+ Copyright (c) 2019 Material-UI SAS
45
+
46
+ Permission is hereby granted, free of charge, to any person obtaining a copy
47
+ of this software and associated documentation files (the "Software"), to deal
48
+ in the Software without restriction, including without limitation the rights
49
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
50
+ copies of the Software, and to permit persons to whom the Software is
51
+ furnished to do so, subject to the following conditions:
52
+
53
+ The above copyright notice and this permission notice shall be included in all
54
+ copies or substantial portions of the Software.
55
+
56
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
57
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
58
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
59
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
60
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
61
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
62
+ SOFTWARE.
63
+ ```
64
+
65
+ ## Radix Primitives
66
+
67
+ - Source: https://github.com/radix-ui/primitives (MIT)
68
+ - Earlier behavior reference for several parts (pre-Base UI alignment)
69
+
70
+ ```
71
+ MIT License
72
+
73
+ Copyright (c) 2022 WorkOS
74
+
75
+ Permission is hereby granted, free of charge, to any person obtaining a copy
76
+ of this software and associated documentation files (the "Software"), to deal
77
+ in the Software without restriction, including without limitation the rights
78
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
79
+ copies of the Software, and to permit persons to whom the Software is
80
+ furnished to do so, subject to the following conditions:
81
+
82
+ The above copyright notice and this permission notice shall be included in all
83
+ copies or substantial portions of the Software.
84
+
85
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
88
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
91
+ SOFTWARE.
92
+ ```
93
+
94
+ ## kumo
95
+
96
+ - Source: https://github.com/cloudflare/kumo (MIT)
97
+ - Adapted: the ClipboardText, SensitiveInput, and CodeBlock components
98
+
99
+ ```
100
+ MIT License Copyright (c) 2026 Cloudflare, Inc.
101
+
102
+ Permission is hereby granted, free of
103
+ charge, to any person obtaining a copy of this software and associated
104
+ documentation files (the "Software"), to deal in the Software without
105
+ restriction, including without limitation the rights to use, copy, modify, merge,
106
+ publish, distribute, sublicense, and/or sell copies of the Software, and to
107
+ permit persons to whom the Software is furnished to do so, subject to the
108
+ following conditions:
109
+
110
+ The above copyright notice and this permission notice
111
+ (including the next paragraph) shall be included in all copies or substantial
112
+ portions of the Software.
113
+
114
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
115
+ ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
116
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
117
+ EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
118
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
119
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
120
+ THE SOFTWARE.
121
+ ```
122
+
123
+ ## ReUI
124
+
125
+ - Source: https://github.com/keenthemes/reui (MIT)
126
+ - The Timeline component's anatomy and styling follow ReUI's Timeline
127
+
128
+ ```
129
+ MIT License
130
+
131
+ Copyright (c) 2025 Keenthemes Inc
132
+
133
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
134
+
135
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
136
+
137
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
138
+ ```
139
+
140
+ ## hotwire_club-toolbox
141
+
142
+ - Source: https://github.com/TheHotwireClub/hotwire_club-toolbox (MIT)
143
+ - Adapted: the OptimisticForm component and form-builder integration
144
+
145
+ ```
146
+ Copyright Julian Rubisch
147
+
148
+ Permission is hereby granted, free of charge, to any person obtaining
149
+ a copy of this software and associated documentation files (the
150
+ "Software"), to deal in the Software without restriction, including
151
+ without limitation the rights to use, copy, modify, merge, publish,
152
+ distribute, sublicense, and/or sell copies of the Software, and to
153
+ permit persons to whom the Software is furnished to do so, subject to
154
+ the following conditions:
155
+
156
+ The above copyright notice and this permission notice shall be
157
+ included in all copies or substantial portions of the Software.
158
+
159
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
160
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
162
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
163
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
164
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
165
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
166
+ ```
167
+
168
+
169
+ ## simple_form
170
+
171
+ - Source: https://github.com/heartcombo/simple_form (MIT)
172
+ - The FormBuilder's type-inference pipeline (attribute-type mapping, name heuristics on string columns, and the validator-to-control-attribute extractors) adapts conventions and heuristics from simple_form
173
+
174
+ ```
175
+ Copyright (c) 2020-CURRENT Rafael França, Carlos Antonio da Silva
176
+ Copyright (c) 2009-2019 Plataformatec
177
+
178
+ Permission is hereby granted, free of charge, to any person obtaining
179
+ a copy of this software and associated documentation files (the
180
+ "Software"), to deal in the Software without restriction, including
181
+ without limitation the rights to use, copy, modify, merge, publish,
182
+ distribute, sublicense, and/or sell copies of the Software, and to
183
+ permit persons to whom the Software is furnished to do so, subject to
184
+ the following conditions:
185
+
186
+ The above copyright notice and this permission notice shall be
187
+ included in all copies or substantial portions of the Software.
188
+
189
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
190
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
191
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
192
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
193
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
194
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
195
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
196
+ ```
197
+
198
+ ## Hotwire test assets
199
+
200
+ - Source: https://github.com/hotwired/turbo (Turbo 8.0.13) and https://github.com/hotwired/stimulus (Stimulus 3.2.2), both MIT (37signals / Basecamp)
201
+ - Vendored: `test/dummy/public/vendor/turbo.es2017-esm.js` and `test/dummy/public/vendor/stimulus.umd.js`, the unmodified dist builds with their license banners; test-only (the stable-id gate and the dommy tier), never shipped in the gem
@@ -0,0 +1,3 @@
1
+ <%= content_tag(:div, **root_attributes.to_attributes) do %>
2
+ <% items.each do |item| %><%= item %><% end %>
3
+ <% end %>
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ # Vertically stacked expand/collapse sections.
6
+ module Accordion
7
+ # An expand/collapse list of sections keyed by value. type: :single
8
+ # (the default) keeps one section open at a time; type: :multiple
9
+ # allows several. Pass open: to server-render the expanded sections.
10
+ #
11
+ # Triggers are real buttons inside headings, so every section stays
12
+ # reachable by Tab; arrow keys also move focus between triggers.
13
+ # Panels are labelled regions. A single non-collapsible accordion
14
+ # marks the locked-open trigger disabled to assistive tech.
15
+ #
16
+ # @example Single-open accordion with the first item expanded
17
+ # render Poetry::Ui::Accordion::Component.new(open: %w[a]) do |accordion|
18
+ # accordion.with_item(value: "a", title: "First") { "First panel" }
19
+ # accordion.with_item(value: "b", title: "Second") { "Second panel" }
20
+ # end
21
+ class Component < Poetry::Core::Component
22
+ # The closed vocabulary for the type axis.
23
+ TYPES = %i[single multiple].freeze
24
+ # The closed vocabulary for the heading_level axis.
25
+ HEADINGS = %i[h2 h3 h4 h5 h6].freeze
26
+
27
+ # Projected into the registry, llms.txt, and the agent surface.
28
+ AGENT_RULES = [
29
+ "Items via with_item(value:, title:) { panel content } - value is the open-state key.",
30
+ "type: :single (default) opens one at a time; pass collapsible: true to allow closing it.",
31
+ "Server-render the open item(s) via open: %w[value] - never toggle data-open/data-closed by hand.",
32
+ "heading_level: fits the page outline (h3 default) - the trigger button lives inside it.",
33
+ "The chevron is built in - never add another indicator icon to the trigger.",
34
+ "disabled: true on with_item locks that item (native disabled on the trigger; roving focus skips it)."
35
+ ].freeze
36
+
37
+ # Slots the component cannot render without; static checks read this without rendering.
38
+ REQUIRED_SLOTS = { item: "at least one item" }.freeze
39
+
40
+ renders_many :items,
41
+ doc: "The accordion sections. Each takes value: (its open-state key), title:, and a block of " \
42
+ "panel content; disabled: true locks the section closed.",
43
+ renders: lambda { |value:, title:, disabled: false, **options, &block|
44
+ open_item = open_values.include?(value.to_s)
45
+ item_id = "#{instance_id}-#{value}"
46
+ item_attrs = { class: css(:item, class: options.delete(:class)),
47
+ "data-slot" => "accordion-item", "data-value" => value,
48
+ (open_item ? "data-open" : "data-closed") => "", **options }
49
+ item_attrs["data-disabled"] = "" if disabled
50
+ content_tag(:div, **item_attrs) do
51
+ safe_join([accordion_header(item_id, title, open_item, disabled: disabled),
52
+ accordion_panel(item_id, open_item, &block)])
53
+ end
54
+ }
55
+
56
+ use_stimulus do
57
+ on :root do
58
+ controller :accordion do
59
+ register
60
+ value :type
61
+ value :collapsible
62
+ end
63
+ controller :roving_focus do
64
+ register
65
+ value :orientation, "vertical"
66
+ value :manage_tabindex, false
67
+ action :keydown, on: :keydown
68
+ end
69
+ end
70
+ on :trigger do
71
+ controller(:accordion) { action :toggle, on: :click }
72
+ end
73
+ end
74
+
75
+ option :type, :symbol, default: :single,
76
+ doc: "Whether one section (:single) or several (:multiple) may be open at once."
77
+ option :collapsible, :boolean, default: false,
78
+ doc: "With type: :single, allows the open section to be closed again."
79
+ option :open, :list, default: -> { [] }, doc: "Value keys of the sections rendered expanded on load."
80
+ option :heading_level, :symbol, default: :h3,
81
+ doc: "The heading element wrapping each trigger; pick it to fit the page " \
82
+ "outline."
83
+
84
+ validates :type, inclusion: { in: TYPES }
85
+ validates :heading_level, inclusion: { in: HEADINGS }
86
+
87
+ part "accordion", "The list root - both controllers (the open-set machine and roving " \
88
+ "focus) ride here",
89
+ states: {
90
+ "data-orientation" => { condition: "always vertical - the only axis the accordion ships",
91
+ values: %w[vertical] }
92
+ }
93
+ part "accordion-item", "One value-keyed section wrapping its header and panel",
94
+ states: {
95
+ "data-open" => "the item is expanded (server-rendered from open:; the controller " \
96
+ "flips the pair at runtime)",
97
+ "data-closed" => "the item is collapsed",
98
+ "data-value" => "the item's open-state key (always present)",
99
+ "data-disabled" => "with_item(disabled: true) - the item is locked (styling hook; " \
100
+ "the trigger carries the native disabled attribute)"
101
+ }
102
+ part "accordion-header", "The heading element (heading_level:, h3 default) hosting the trigger button"
103
+ part "accordion-trigger", "The toggle button inside the header - the chevron rotation rides " \
104
+ "aria-expanded, not a data attribute",
105
+ states: {
106
+ "data-panel-open" => "its panel is open (controller-written; " \
107
+ "absent while closed)",
108
+ "data-disabled" => "with_item(disabled: true) - stamped beside the native disabled " \
109
+ "attribute; roving focus filters it out at query time"
110
+ }
111
+ part "accordion-trigger-icon", "The chevron svg inside the trigger (aria-hidden) - rotates with the item"
112
+ part "accordion-content", "The role=region panel - the presence animation and the measured " \
113
+ "height var ride here",
114
+ states: {
115
+ "data-open" => "panel is open or entering",
116
+ "data-closed" => "panel is closed or animating out (hidden lands after the exit finishes)"
117
+ },
118
+ vars: {
119
+ "--accordion-panel-height" => "the measured content height (controller-written) that " \
120
+ "feeds the accordion-down/up keyframes"
121
+ }
122
+
123
+ # Enforces the required item slot.
124
+ # @api private
125
+ def before_render
126
+ raise ArgumentError, "Accordion requires at least one with_item" unless items?
127
+ end
128
+
129
+ # The open: values normalized to strings.
130
+ # @api private
131
+ def open_values
132
+ Array(open).map(&:to_s)
133
+ end
134
+
135
+ # @api private
136
+ def root_attributes
137
+ html_attributes.merge_if_not_set(
138
+ { "data-slot" => "accordion", "data-orientation" => "vertical" }
139
+ .merge(stimulus_attributes_for(:root))
140
+ .merge(component_data_attributes)
141
+ )
142
+ end
143
+
144
+ private
145
+
146
+ def instance_id
147
+ @instance_id ||= poetry_instance_id("poetry-accordion")
148
+ end
149
+
150
+ def accordion_header(item_id, title, open_item, disabled: false)
151
+ trigger_attrs = {
152
+ type: "button", id: "#{item_id}-trigger", class: css(:trigger),
153
+ # No state attribute on the trigger: the controller reflects only
154
+ # aria-expanded here (the open/closed pair lives on the item and
155
+ # panel) - aria-expanded IS the trigger's styling hook.
156
+ "data-slot" => "accordion-trigger",
157
+ "data-poetry-collection-item" => "",
158
+ "aria-expanded" => open_item.to_s, "aria-controls" => "#{item_id}-panel"
159
+ }.merge(stimulus_attributes_for(:trigger))
160
+ trigger_attrs["aria-disabled"] = "true" if open_item && type == :single && !collapsible
161
+ # Native disabled owns interaction and focus; data-disabled is the
162
+ # roving-focus query filter (a natively disabled button already
163
+ # drops from the tab order on its own).
164
+ if disabled
165
+ trigger_attrs[:disabled] = true
166
+ trigger_attrs["data-disabled"] = ""
167
+ end
168
+
169
+ content_tag(heading_level, class: css(:header), "data-slot" => "accordion-header") do
170
+ content_tag(:button, trigger_attrs) do
171
+ safe_join([title, chevron])
172
+ end
173
+ end
174
+ end
175
+
176
+ def accordion_panel(item_id, open_item, &)
177
+ attrs = {
178
+ id: "#{item_id}-panel", role: "region", class: css(:content),
179
+ "data-slot" => "accordion-content", (open_item ? "data-open" : "data-closed") => "",
180
+ "aria-labelledby" => "#{item_id}-trigger"
181
+ }
182
+ attrs[:hidden] = true unless open_item
183
+ content_tag(:div, attrs) do
184
+ content_tag(:div, capture(&), class: css(:inner))
185
+ end
186
+ end
187
+
188
+ def chevron
189
+ render(Icon::Component.new(name: :"chevron-down", class: css(:indicator),
190
+ data: { slot: "accordion-trigger-icon" }))
191
+ end
192
+
193
+ private :open_values, :root_attributes
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module Accordion
6
+ # The Accordion preview matrix.
7
+ class Preview < Poetry::Core::Preview::Base
8
+ def default
9
+ render_component(open: %w[shipping]) do |accordion|
10
+ accordion.with_item(value: "shipping", title: "Shipping") { "Free over $50, worldwide." }
11
+ accordion.with_item(value: "returns", title: "Returns") { "30 days, no questions." }
12
+ accordion.with_item(value: "warranty", title: "Warranty") { "Two years, parts and labor." }
13
+ end
14
+ end
15
+
16
+ def multiple
17
+ render_component(type: :multiple, open: %w[a b]) do |accordion|
18
+ accordion.with_item(value: "a", title: "First") { "Open together" }
19
+ accordion.with_item(value: "b", title: "Second") { "with the first." }
20
+ end
21
+ end
22
+
23
+ def single_collapsible
24
+ render_component(collapsible: true, open: %w[only]) do |accordion|
25
+ accordion.with_item(value: "only", title: "Toggle me") { "I can close." }
26
+ end
27
+ end
28
+
29
+ def disabled
30
+ render_component(collapsible: true) do |accordion|
31
+ accordion.with_item(value: "history", title: "Account history") { "All transactions and plan changes." }
32
+ accordion.with_item(value: "premium", title: "Premium features", disabled: true) { "Upgrade to access." }
33
+ accordion.with_item(value: "email", title: "Update email") { "Change it in account settings." }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module Accordion
6
+ # Re-expressed through the cn-* theme layer. The panel
7
+ # animation classes ride the theme (the vendored accordion-down/up
8
+ # keyframes still fed by --accordion-panel-height); the chevron's
9
+ # aria-expanded rotation + motion stay inline (state mechanism).
10
+ class Style < Poetry::Core::Style
11
+ # Root hook: several themes (mira, rhea, luma, maia) style the
12
+ # root as a box - the name must compile in EVERY theme, so each
13
+ # fragment carries a rule (default: w-full).
14
+ base "cn-accordion flex flex-col w-full"
15
+
16
+ element :item, "cn-accordion-item"
17
+
18
+ element :header, "flex"
19
+
20
+ # The chevron flips on aria-expanded, not a data attribute: the
21
+ # controller reflects only aria-expanded on the trigger (the
22
+ # data-open/data-closed pair lives on the item and panel).
23
+ element :trigger, "cn-accordion-trigger flex flex-1 items-start justify-between transition-all " \
24
+ "outline-none disabled:pointer-events-none disabled:opacity-50 " \
25
+ "[&[aria-expanded=true]>svg]:rotate-180 border border-transparent " \
26
+ "group/accordion-trigger relative"
27
+
28
+ element :indicator, "cn-accordion-trigger-icon pointer-events-none shrink-0 " \
29
+ "transition-transform duration-200"
30
+
31
+ element :content, "cn-accordion-content overflow-hidden"
32
+
33
+ element :inner, "cn-accordion-content-inner"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,6 @@
1
+ <%= content_tag(:div, **root_attributes.to_attributes) do %>
2
+ <%= icon %>
3
+ <% if title? %><div data-slot="alert-title" class="<%= css(:title) %>"><%= title %></div><% end %>
4
+ <div data-slot="alert-description" class="<%= css(:description) %>"><%= content %></div>
5
+ <% if action? %><div data-slot="alert-action" class="<%= css(:action) %>"><%= action %></div><% end %>
6
+ <% end %>