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
@@ -0,0 +1,93 @@
1
+ en:
2
+ poetry:
3
+ button:
4
+ loading: "Loading…"
5
+ calendar:
6
+ month: "Month"
7
+ year: "Year"
8
+ combobox:
9
+ clear: "Clear selection"
10
+ empty: "No results found."
11
+ filter_label: "Filter options"
12
+ remove: "Remove %{label}"
13
+ command:
14
+ empty: "No results found."
15
+ loading: "Loading…"
16
+ results:
17
+ zero: "0 results"
18
+ one: "1 result"
19
+ other: "%{count} results"
20
+ list_label: "Commands"
21
+ input_label: "Search commands"
22
+ dialog_title: "Command palette"
23
+ dialog_description: "Search for a command to run…"
24
+ deferred:
25
+ failed: "This section failed to load."
26
+ retry: "Retry"
27
+ stat:
28
+ trend_up: "trending up"
29
+ trend_down: "trending down"
30
+ trend_flat: "flat"
31
+ file_input:
32
+ prompt: "Drag and drop or click to browse"
33
+ clear: "Clear selection"
34
+ number_field:
35
+ roledescription: "Number field"
36
+ increment: "Increase"
37
+ decrement: "Decrease"
38
+ search_field:
39
+ clear: "Clear search"
40
+ clipboard_text:
41
+ copy: "Copy"
42
+ copied: "Copied to clipboard"
43
+ code_block:
44
+ label: "Code"
45
+ sensitive_input:
46
+ masked_label: "%{label}, masked."
47
+ masked_fallback: "Sensitive value, masked."
48
+ hint: "Click or press Enter to reveal."
49
+ reveal_hint: "Click to reveal"
50
+ hidden: "Value hidden"
51
+ hide: "Hide value"
52
+ data_table:
53
+ select_all: "Select all rows"
54
+ select_row: "Select row"
55
+ selected_count: "%{count} selected"
56
+ tree:
57
+ expand: "Expand"
58
+ collapse: "Collapse"
59
+ empty: "No items"
60
+ tag_group:
61
+ remove: "Remove"
62
+ date_field:
63
+ empty: "Empty"
64
+ year: "year"
65
+ month: "month"
66
+ day: "day"
67
+ hour: "hour"
68
+ minute: "minute"
69
+ second: "second"
70
+ day_period: "AM/PM"
71
+ placeholder_year: "yyyy"
72
+ placeholder_month: "mm"
73
+ placeholder_day: "dd"
74
+ placeholder_time: "––"
75
+ dialog:
76
+ close: "Close"
77
+ sheet:
78
+ close: "Close"
79
+ toast:
80
+ region_label: "Notifications (%{hotkey})"
81
+ close: "Close"
82
+ context_menu:
83
+ menu_label_fallback: "Context menu"
84
+ attachment:
85
+ state:
86
+ uploading: "Uploading attachment"
87
+ processing: "Processing attachment"
88
+ error: "Attachment failed"
89
+ input_otp:
90
+ label: "One-time code"
91
+ message_scroller:
92
+ region: "Conversation"
93
+ scroll_to_end: "Scroll to latest messages"
data/config/routes.rb ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Mounted by the host (mount Poetry::Ui::Engine => "/poetry"); serves the
4
+ # LLM-facing docs generated live from the component registry.
5
+ Poetry::Ui::Engine.routes.draw do
6
+ get "llms.txt", to: "poetry/ui/llms#index", format: false
7
+ get "llms-full.txt", to: "poetry/ui/llms#full", format: false
8
+ end
@@ -0,0 +1,113 @@
1
+ # static template classes - generated by `bin/rake css:template_classes:generate`. DO NOT EDIT.
2
+ absolute
3
+ animate-spin
4
+ aspect-square
5
+ bg-popover
6
+ bg-primary
7
+ bg-sidebar-primary
8
+ border
9
+ border-2
10
+ border-b
11
+ border-border
12
+ border-destructive/50
13
+ border-primary
14
+ bottom-2
15
+ contents
16
+ data-[side]:visible
17
+ data-open:opacity-100
18
+ data-open:translate-y-0
19
+ flex
20
+ flex-1
21
+ flex-col
22
+ flex-wrap
23
+ focus-visible:ring-2
24
+ focus-visible:ring-ring
25
+ font-medium
26
+ font-semibold
27
+ gap-1
28
+ gap-2
29
+ gap-3
30
+ gap-4
31
+ gap-6
32
+ grid
33
+ grid-cols-2
34
+ grid-cols-3
35
+ group-has-data-[collapsible=icon]/sidebar-wrapper:h-12
36
+ h-14
37
+ h-96
38
+ h-px
39
+ inline-block
40
+ inset-x-8
41
+ invisible
42
+ items-center
43
+ items-end
44
+ items-start
45
+ justify-between
46
+ justify-center
47
+ justify-end
48
+ leading-none
49
+ leading-tight
50
+ max-w-2xl
51
+ max-w-3xl
52
+ max-w-5xl
53
+ max-w-md
54
+ max-w-xl
55
+ md:grid-cols-3
56
+ min-h-64
57
+ min-h-72
58
+ min-w-0
59
+ min-w-8
60
+ ms-auto
61
+ mt-6
62
+ mx-auto
63
+ not-data-open:opacity-0
64
+ not-data-open:translate-y-2
65
+ outline-none
66
+ overflow-hidden
67
+ p-2
68
+ p-3
69
+ p-4
70
+ p-6
71
+ pb-16
72
+ px-2
73
+ px-4
74
+ px-6
75
+ py-1
76
+ py-2
77
+ relative
78
+ rounded-full
79
+ rounded-lg
80
+ rounded-md
81
+ shadow-lg
82
+ shrink-0
83
+ size-8
84
+ space-y-0.5
85
+ space-y-1
86
+ space-y-2
87
+ space-y-3
88
+ space-y-4
89
+ sr-only
90
+ tabular-nums
91
+ text-2xl
92
+ text-base
93
+ text-destructive
94
+ text-left
95
+ text-lg
96
+ text-muted-foreground
97
+ text-popover-foreground
98
+ text-primary
99
+ text-primary-foreground
100
+ text-sidebar-primary-foreground
101
+ text-sm
102
+ text-xs
103
+ tracking-tight
104
+ transition-[height]
105
+ transition-[opacity,translate]
106
+ truncate
107
+ underline
108
+ underline-offset-4
109
+ w-64
110
+ w-80
111
+ w-96
112
+ w-full
113
+ z-10
@@ -0,0 +1,218 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "yaml"
5
+ require_relative "../block/block_generator"
6
+
7
+ module Poetry
8
+ # `rails g poetry:add Button [@acme/fancy-chart ...]` - the copy-in tier
9
+ # plus the ecosystem address scheme.
10
+ #
11
+ # Bare names and @poetry/* are the installed gems' own items: component
12
+ # source copies into app/components where Rails autoload precedence
13
+ # shadows the gem ("own the code"; dependencies resolve recursively,
14
+ # existing files are SKIPPED - local edits win, always), and block names
15
+ # hand off to poetry:block. Everything else is a REMOTE registry address -
16
+ # a URL, a local item file, or @namespace/item against the registries:
17
+ # section of config/poetry_components.yml - resolved through
18
+ # RegistryClient + RegistryInstaller: the dependency DAG fetches
19
+ # recursively and writes in topo order, poetry components satisfy at
20
+ # RUNTIME (the gem provides them - no copy), targets are
21
+ # traversal-checked, and gem dependencies are REPORTED, never installed.
22
+ # Every install records provenance in the manifest.
23
+ #
24
+ # @example
25
+ # bin/rails g poetry:add button
26
+ class AddGenerator < Rails::Generators::Base
27
+ argument :addresses, type: :array,
28
+ banner: "Component|@registry/item|https://…/item.json|./item.json ..."
29
+
30
+ # Composition edges - single-sourced on the gem module (the
31
+ # registry items emit the same map as registryDependencies).
32
+ DEPENDENCIES = Poetry::Ui::COMPONENT_DEPENDENCIES
33
+
34
+ # The copy-in provenance manifest poetry:install seeds.
35
+ MANIFEST = "config/poetry_components.yml"
36
+ # The host's Tailwind entry stylesheet (for @source injection).
37
+ TAILWIND_ENTRY = "app/assets/tailwind/application.css"
38
+
39
+ desc "Copy poetry components/blocks (plus dependencies) into the app, from the gems or any registry address"
40
+
41
+ # Generator step: partitions the addresses and installs local
42
+ # (gem-owned) and remote items.
43
+ # @api private
44
+ def add_components
45
+ local, remote = addresses.map { |raw| Poetry::Core::RegistryAddress.parse(raw) }
46
+ .partition { |address| local?(address) }
47
+ install_local(local) if local.any?
48
+ install_remote(remote) if remote.any?
49
+ end
50
+
51
+ private
52
+
53
+ # Bare names and @poetry/* resolve against the installed gems; anything
54
+ # the gems don't ship is a hard error for @poetry (never a fetch - the
55
+ # gem IS the official registry on a poetry host) and a hard error with
56
+ # the classic message for bare names.
57
+ def local?(address)
58
+ address.kind == :bare || (address.kind == :namespace && address.namespace == "@poetry")
59
+ end
60
+
61
+ def install_local(local)
62
+ names = local.map { |address| address.name.tr("-", "_") }
63
+ components, rest = names.partition { |name| source_dir(name).directory? }
64
+ blocks, rest = rest.partition { |name| gem_blocks.include?(name.tr("_", "-")) }
65
+ recipes, missing = rest.partition { |name| gem_recipes.include?(name.tr("_", "-")) }
66
+ raise ArgumentError, "unknown component(s): #{missing.join(", ")}" if missing.any?
67
+
68
+ copy_components(components) if components.any?
69
+ blocks.each { |name| install_block(name.tr("_", "-")) }
70
+ recipes.each { |name| install_recipe(name.tr("_", "-")) }
71
+ end
72
+
73
+ def copy_components(names)
74
+ resolved = resolve(names)
75
+ resolved.each { |name| copy_component(name) }
76
+ record_in_manifest(resolved.to_h { |name| [name, { "version" => Poetry::Ui::VERSION }] })
77
+ # A newly-shadowing file is not hot-reloaded over the already-loaded
78
+ # gem constant.
79
+ say_status :note, "restart your server so the local copies take precedence over the gem", :yellow
80
+ end
81
+
82
+ def resolve(names, seen = [])
83
+ names.each do |name|
84
+ next if seen.include?(name)
85
+
86
+ seen << name
87
+ resolve(DEPENDENCIES.fetch(name, []), seen)
88
+ end
89
+ seen
90
+ end
91
+
92
+ def source_dir(name)
93
+ Poetry::Ui.root.join("app/components/poetry/ui", name)
94
+ end
95
+
96
+ def copy_component(name)
97
+ dir = source_dir(name)
98
+ # Recursive: a component owns its nested subcomponents (command ships
99
+ # command/dialog). skip-if-exists: a customized local copy is never
100
+ # overwritten.
101
+ dir.glob("**/*").select(&:file?).each do |file|
102
+ create_file "app/components/poetry/ui/#{name}/#{file.relative_path_from(dir)}",
103
+ file.read, skip: true
104
+ end
105
+ end
106
+
107
+ # -- the remote path ----------------------------------------------------
108
+
109
+ def install_remote(remote)
110
+ plan = build_plan(remote)
111
+ plan.writes.each { |write| create_file write.target, write.content, skip: true }
112
+ plan.block_installs.each { |name| install_block(name) }
113
+ apply_css(plan)
114
+ report(plan)
115
+ record_in_manifest(plan.manifest)
116
+ end
117
+
118
+ def build_plan(remote)
119
+ config = manifest_config
120
+ client = Poetry::Core::RegistryClient.new(
121
+ registries: config["registries"] || {}, directory: config["directory"],
122
+ base_dir: destination_root
123
+ )
124
+ Poetry::Core::RegistryInstaller.new(
125
+ client: client, destination_root: destination_root,
126
+ local_components: gem_components, local_blocks: gem_blocks
127
+ ).plan(remote)
128
+ end
129
+
130
+ def apply_css(plan)
131
+ plan.css_writes.each { |css| create_file css[:path], css[:content], skip: true }
132
+ return if plan.entry_lines.empty?
133
+
134
+ unless File.exist?(File.join(destination_root, TAILWIND_ENTRY))
135
+ say_status :note, "no #{TAILWIND_ENTRY} - add yourself: #{plan.entry_lines.join(" ")}", :yellow
136
+ return
137
+ end
138
+ plan.entry_lines.each { |line| inject_unless_present(TAILWIND_ENTRY, line) }
139
+ end
140
+
141
+ def report(plan)
142
+ plan.gem_satisfied.each do |name|
143
+ say_status :runtime, "#{name} - provided by the installed poetry gems (no copy needed)", :cyan
144
+ end
145
+ plan.gem_deps.each do |dep|
146
+ say_status :gemfile, "this item needs gem #{dep.inspect} - add it to your Gemfile (never run for you)", :yellow
147
+ end
148
+ plan.docs.each { |docs| say_status :docs, docs, :blue }
149
+ end
150
+
151
+ def install_block(name)
152
+ BlockGenerator.new([name], [], destination_root: destination_root).invoke_all
153
+ end
154
+
155
+ # -- recipes ------------------------------------------------------------
156
+
157
+ # A recipe's files write to their declared targets (skip-if-exists:
158
+ # local edits win, always); its registryDependencies are block names,
159
+ # installed through the same block path. Recorded in the manifest
160
+ # under recipes:.
161
+ def install_recipe(name)
162
+ item = Poetry::Ui.recipe_items.item(name)
163
+ item["files"].each { |file| create_file file["target"], file["content"], skip: true }
164
+ item["registryDependencies"].each { |dep| install_block(dep) }
165
+ record_in_manifest({ name => { "version" => Poetry::Ui::VERSION } }, section: "recipes")
166
+ routes_hint = item["description"][/Add `[^`]+` to routes/]
167
+ say_status :note, routes_hint, :yellow if routes_hint
168
+ end
169
+
170
+ def gem_recipes
171
+ @gem_recipes ||= Poetry::Ui.recipe_items.names
172
+ end
173
+
174
+ # The gems' own item names (kebab), read boot-free from the committed
175
+ # registries - what "provided at runtime" means on this host.
176
+ def gem_components
177
+ @gem_components ||= gem_item_sources.flat_map do |root, prefix|
178
+ registry = YAML.safe_load_file(root.join(Poetry::Core::Registry::RELATIVE_PATH))
179
+ (registry["components"] || {}).keys.map { |path| path.delete_prefix(prefix).tr("/", "_").tr("_", "-") }
180
+ end
181
+ end
182
+
183
+ def gem_blocks
184
+ @gem_blocks ||= begin
185
+ registry = YAML.safe_load_file(Poetry::Ui.root.join(Poetry::Core::Registry::RELATIVE_PATH))
186
+ (registry["blocks"] || {}).keys
187
+ end
188
+ end
189
+
190
+ def gem_item_sources
191
+ sources = [[Poetry::Ui.root, "poetry/ui/"]]
192
+ sources << [Poetry::Charts.root, "poetry/charts/"] if defined?(Poetry::Charts::Engine)
193
+ sources
194
+ end
195
+
196
+ def manifest_config
197
+ path = File.join(destination_root, MANIFEST)
198
+ config = File.exist?(path) ? YAML.safe_load_file(path) : nil
199
+ config.is_a?(Hash) ? config : {}
200
+ end
201
+
202
+ def record_in_manifest(entries, section: "components")
203
+ manifest = manifest_config
204
+ manifest[section] = {} unless manifest[section].is_a?(Hash)
205
+ entries.each { |name, record| manifest[section][name] ||= record }
206
+ create_file MANIFEST, YAML.dump(manifest), force: true
207
+ end
208
+
209
+ # The idempotency lives in the file-mutation primitive - same as
210
+ # poetry:install's.
211
+ def inject_unless_present(relative, line)
212
+ path = File.join(destination_root, relative)
213
+ return if File.exist?(path) && File.read(path).include?(line)
214
+
215
+ append_to_file relative, "#{line}\n"
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module Poetry
6
+ # `rails g poetry:agent_rules` - the two-file, opposite-lifecycle agent
7
+ # ruleset:
8
+ #
9
+ # .poetry/agent-rules.md gem-owned, FORCE-overwritten every run
10
+ # (generated live from the component registry)
11
+ # .poetry/house-rules.md seeded once, then user-owned - never touched again
12
+ #
13
+ # plus an idempotent marker-import into CLAUDE.md and AGENTS.md:
14
+ # insert-between-markers, replace-on-rerun, and detect-but-never-rewrite
15
+ # when a file carries a broken half-marker.
16
+ #
17
+ # @example
18
+ # bin/rails g poetry:agent_rules
19
+ class AgentRulesGenerator < Rails::Generators::Base
20
+ # The opening half of the marker pair bounding the import block.
21
+ START_MARKER = "<!-- poetry:agent-rules:start -->"
22
+ # The closing half of the marker pair bounding the import block.
23
+ END_MARKER = "<!-- poetry:agent-rules:end -->"
24
+
25
+ # The marker-bounded pointer inserted into CLAUDE.md and AGENTS.md.
26
+ IMPORT_BLOCK = <<~MD.freeze
27
+ #{START_MARKER}
28
+ Follow the poetry component rules in `.poetry/agent-rules.md` (generated - do not edit)
29
+ and the project overrides in `.poetry/house-rules.md`.
30
+ #{END_MARKER}
31
+ MD
32
+
33
+ # The once-only seed content of .poetry/house-rules.md.
34
+ HOUSE_RULES_SEED = <<~MD
35
+ # poetry house rules
36
+
37
+ Project-specific overrides and additions to the generated poetry agent
38
+ rules. This file is yours - poetry seeds it once and never touches it
39
+ again.
40
+ MD
41
+
42
+ desc "Install the poetry agent ruleset (.poetry/agent-rules.md + house-rules.md + CLAUDE.md/AGENTS.md import)"
43
+
44
+ # Step: force-writes the generated .poetry/agent-rules.md.
45
+ # @api private
46
+ def create_agent_rules
47
+ create_file ".poetry/agent-rules.md", generated_rules, force: true
48
+ end
49
+
50
+ # Step: seeds .poetry/house-rules.md once (never overwritten).
51
+ # @api private
52
+ def seed_house_rules
53
+ return if File.exist?(File.join(destination_root, ".poetry/house-rules.md"))
54
+
55
+ create_file ".poetry/house-rules.md", HOUSE_RULES_SEED
56
+ end
57
+
58
+ # Step: marker-imports the ruleset into CLAUDE.md and AGENTS.md.
59
+ # @api private
60
+ def import_into_instruction_files
61
+ %w[CLAUDE.md AGENTS.md].each { |file| marker_import(file) }
62
+ end
63
+
64
+ private
65
+
66
+ def generated_rules
67
+ registry = Poetry::Core::Registry.new(source_root: Poetry::Ui.root)
68
+ body = Poetry::Core::LlmsText.new(registry: registry).full
69
+ "<!-- generated by `rails g poetry:agent_rules` - DO NOT EDIT; " \
70
+ "project overrides go in .poetry/house-rules.md -->\n\n#{body}"
71
+ end
72
+
73
+ def marker_import(relative)
74
+ path = File.join(destination_root, relative)
75
+ existing = File.exist?(path) ? File.read(path) : nil
76
+
77
+ if existing.nil?
78
+ create_file relative, IMPORT_BLOCK
79
+ elsif existing.include?(START_MARKER) && existing.include?(END_MARKER)
80
+ replaced = existing.sub(/#{Regexp.escape(START_MARKER)}.*?#{Regexp.escape(END_MARKER)}\n?/mo, IMPORT_BLOCK)
81
+ create_file relative, replaced, force: true
82
+ elsif existing.include?(START_MARKER) || existing.include?(END_MARKER)
83
+ # Detect-but-never-rewrite: a half-marker means a human edited the
84
+ # block - surface it, do not guess.
85
+ say_status :conflict, "#{relative} has a broken poetry marker pair - fix it manually", :red
86
+ else
87
+ append_to_file relative, "\n#{IMPORT_BLOCK}"
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require_relative "../agents_section"
5
+
6
+ module Poetry
7
+ # `rails g poetry:agents` - writes or refreshes the poetry section of the
8
+ # host's AGENTS.md (the agent-facing pointer to llms.txt / poetry check)
9
+ # without running the full install. poetry:install performs the same step.
10
+ #
11
+ # @example
12
+ # bin/rails g poetry:agents
13
+ class AgentsGenerator < Rails::Generators::Base
14
+ include Generators::AgentsSection
15
+
16
+ desc "Write or refresh the poetry section of AGENTS.md (pointer to llms.txt + poetry check)"
17
+
18
+ # Step: applies the shared AGENTS.md section.
19
+ # @api private
20
+ def write_agents_md
21
+ apply_agents_section
22
+ end
23
+ end
24
+ end