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,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ # Inline callouts for statuses and errors.
6
+ module Alert
7
+ # An inline callout for statuses and errors, with the live-region
8
+ # wiring built in. The default variant announces politely
9
+ # (role=status); :destructive announces assertively (role=alert),
10
+ # so reserve it for genuine errors.
11
+ #
12
+ # @example Destructive alert with a title
13
+ # render Poetry::Ui::Alert::Component.new(variant: :destructive) do |alert|
14
+ # alert.with_title { "Payment failed" }
15
+ # "Your card was declined. Update your billing details."
16
+ # end
17
+ class Component < Poetry::Core::Component
18
+ # The closed vocabulary for the variant axis.
19
+ VARIANTS = %i[default destructive].freeze
20
+
21
+ # Projected into the registry, llms.txt, and the agent surface.
22
+ AGENT_RULES = [
23
+ "Use poetry_alert for inline callouts - it carries role/aria-live; never a hand-rolled div.",
24
+ "destructive announces assertively (role=alert) - reserve it for errors, not emphasis."
25
+ ].freeze
26
+
27
+ renders_one :icon, Poetry::Ui::Icon::Component, doc: "Optional leading icon; pass icon props (e.g. name: " \
28
+ ":\"triangle-alert\"), not a block."
29
+ renders_one :title, doc: "The heading line of the callout."
30
+ renders_one :action, doc: "Optional corner action (a dismiss button or link), pinned to the top-right."
31
+
32
+ style :variant, default: :default, required: true, variants: VARIANTS,
33
+ doc: "The intent axis; :destructive marks errors and announces assertively."
34
+
35
+ part "alert", "The callout root - role rides the variant (destructive announces " \
36
+ "assertively via role=alert; default is a polite role=status)",
37
+ states: {
38
+ "data-variant" => { condition: "always - the resolved variant",
39
+ values: VARIANTS.map(&:to_s) }
40
+ }
41
+ part "alert-title", "The heading line, rendered when the title slot is set"
42
+ part "alert-action", "The corner action well (with_action) - a dismiss or link " \
43
+ "pinned to the top-right by the theme"
44
+ part "alert-description", "The body copy - the content block renders here"
45
+
46
+ # @api private
47
+ def root_attributes
48
+ html_attributes.merge_if_not_set(
49
+ {
50
+ "data-slot" => "alert",
51
+ "data-variant" => variant,
52
+ "role" => (variant == :destructive ? "alert" : "status")
53
+ }.merge(component_data_attributes)
54
+ )
55
+ end
56
+
57
+ private :root_attributes
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module Alert
6
+ class Preview < Poetry::Core::Preview::Base
7
+ def default
8
+ render_component do |alert|
9
+ alert.with_title { "Heads up" }
10
+ "You can adjust preferences at any time."
11
+ end
12
+ end
13
+
14
+ def destructive
15
+ render_component(variant: :destructive) do |alert|
16
+ alert.with_icon(name: :"triangle-alert")
17
+ alert.with_title { "Payment failed" }
18
+ "Your card was declined - update your billing details."
19
+ end
20
+ end
21
+
22
+ # The corner action well (theme pins it top-right).
23
+ def with_action
24
+ render_component(variant: :default) do |alert|
25
+ alert.with_title { "Update available" }
26
+ alert.with_action do
27
+ tag.button("Dismiss", type: "button", class: "text-sm underline-offset-4 hover:underline")
28
+ end
29
+ "A new version is ready to install."
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module Alert
6
+ # Re-expressed through the cn-* theme layer: entries carry the
7
+ # stable names + the structural inline set; themes/default.css holds
8
+ # the design (the grid treatment, variants).
9
+ class Style < Poetry::Core::Style
10
+ base "cn-alert relative w-full group/alert"
11
+
12
+ variant :variant, {
13
+ default: "cn-alert-variant-default",
14
+ destructive: "cn-alert-variant-destructive"
15
+ }
16
+
17
+ element :title, "cn-alert-title [&_a]:hover:text-foreground [&_a]:underline [&_a]:underline-offset-3"
18
+ element :action, "cn-alert-action"
19
+ element :description, "cn-alert-description [&_a]:hover:text-foreground [&_a]:underline " \
20
+ "[&_a]:underline-offset-3"
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ <%= content_tag(:div, **root_attributes.to_attributes) do %>
2
+ <%= trigger %>
3
+ <%= content_tag(:dialog, **Poetry::Core::HTML::Attributes.new(dialog_attributes).to_attributes) do %>
4
+ <div data-slot="alert-dialog-header" class="<%= header_classes %>">
5
+ <% if media? %>
6
+ <div data-slot="alert-dialog-media" class="<%= media_classes %>"><%= media %></div>
7
+ <% end %>
8
+ <h2 id="<%= title_id %>" data-slot="alert-dialog-title" class="<%= title_classes %>"><%= title %></h2>
9
+ <p id="<%= description_id %>" data-slot="alert-dialog-description" class="<%= css(:description) %>"><%= description %></p>
10
+ </div>
11
+ <%= content %>
12
+ <div data-slot="alert-dialog-footer" class="<%= footer_classes %>">
13
+ <%= cancel %>
14
+ <%= action %>
15
+ </div>
16
+ <% end %>
17
+ <% end %>
@@ -0,0 +1,208 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ # Modal confirmations that must be answered.
6
+ module AlertDialog
7
+ # A modal confirmation that must be answered before anything else.
8
+ # Built on the native <dialog> element: clicking the backdrop never
9
+ # dismisses it, though Esc still cancels. Use it for destructive or
10
+ # irreversible actions; for anything needing input, use Dialog.
11
+ #
12
+ # Title and description are both required, as are the action and
13
+ # cancel buttons - both close the dialog when activated, and cancel
14
+ # (the least-destructive choice) takes initial focus. There is no
15
+ # corner close button.
16
+ #
17
+ # @example Destructive confirmation
18
+ # render Poetry::Ui::AlertDialog::Component.new do |dialog|
19
+ # dialog.with_trigger(variant: :destructive) { "Delete project" }
20
+ # dialog.with_title { "Delete this project?" }
21
+ # dialog.with_description { "This cannot be undone." }
22
+ # dialog.with_cancel { "Cancel" }
23
+ # dialog.with_action(variant: :destructive) { "Delete" }
24
+ # end
25
+ class Component < Poetry::Core::Component
26
+ include Poetry::Ui::ComposableTrigger
27
+ include Poetry::Ui::FamilyIdentity
28
+
29
+ # The closed vocabulary for the size axis.
30
+ SIZES = %i[default sm].freeze
31
+
32
+ # Projected into the registry, llms.txt, and the agent surface.
33
+ AGENT_RULES = [
34
+ ComposableTrigger::AGENT_RULE,
35
+ "Destructive confirmations use AlertDialog with with_action(variant: :destructive) - " \
36
+ "never a bare Dialog, never data-turbo-confirm.",
37
+ "with_title AND with_description are REQUIRED (both raise).",
38
+ "The action must be an explicit user activation - agents NEVER auto-submit the action.",
39
+ "No extra form fields inside an AlertDialog - if input is needed, use a Dialog.",
40
+ "Cancel keeps variant: :outline; do not make cancel visually primary."
41
+ ].freeze
42
+
43
+ # Slots the component cannot render without; static checks read this without rendering.
44
+ REQUIRED_SLOTS = {
45
+ title: "the accessible name", description: "the alertdialog must explain itself",
46
+ action: "the confirming choice", cancel: "the safe way out"
47
+ }.freeze
48
+
49
+ # Slots that render a Button; slot keywords are forwarded as Button props.
50
+ SLOT_RENDERS = { trigger: Button::Component, action: Button::Component, cancel: Button::Component }.freeze
51
+
52
+ renders_one :trigger,
53
+ doc: "The button that opens the dialog; keywords are forwarded as Button props.",
54
+ renders: lambda { |**options, &block|
55
+ composed_trigger({ "data-action" => stimulus_action(:open) }, options, &block) || begin
56
+ merger = Poetry::Core::Config.current.stimulus_merger
57
+ wired_data = { action: stimulus_action(:open) }
58
+ options[:data] = wired_data.merge(options[:data] || {}) do |key, wired, caller|
59
+ key == :action ? merger.merge_actions(wired, caller) : caller
60
+ end
61
+ Button::Component.new(**options, &block)
62
+ end
63
+ }
64
+ renders_one :title, doc: "The heading - the dialog's accessible name (required)."
65
+ renders_one :description, doc: "The explanation read alongside the title by assistive tech (required)."
66
+ renders_one :media, doc: "Optional icon/illustration well above the title."
67
+ renders_one :action,
68
+ doc: "The confirming choice (required) - a Button; pass variant: :destructive for deletes. " \
69
+ "Activating it also closes the dialog (a caller-supplied data-action opts out).",
70
+ renders: lambda { |**options, &block|
71
+ options[:data] =
72
+ { slot: "alert-dialog-action", action: stimulus_action(:close) }.merge(options[:data] || {})
73
+ Button::Component.new(**options, &block)
74
+ }
75
+ renders_one :cancel,
76
+ doc: "The safe way out (required) - an outline Button that takes initial focus and closes the " \
77
+ "dialog on activation.",
78
+ renders: lambda { |**options, &block|
79
+ merger = Poetry::Core::Config.current.stimulus_merger
80
+ wired_data = { slot: "alert-dialog-cancel", action: stimulus_action(:close) }
81
+ options[:data] = wired_data.merge(options[:data] || {}) do |key, wired, caller|
82
+ key == :action ? merger.merge_actions(wired, caller) : caller
83
+ end
84
+ Button::Component.new(variant: :outline, autofocus: true, **options, &block)
85
+ }
86
+
87
+ # The SHARED dialog controller (zero new JS) under AlertDialog's
88
+ # own declarations - dismissible is the hard-coded false posture.
89
+ use_stimulus do
90
+ on :root do
91
+ controller :dialog do
92
+ register
93
+ # The posture IS the identity - never caller-settable.
94
+ value :dismissible, false
95
+ end
96
+ end
97
+ on :content do
98
+ controller :dialog do
99
+ target :dialog
100
+ action :close, on: :cancel
101
+ # Wired but inert: backdropClose no-ops on dismissibleValue
102
+ # false. Keep it - removing it would fork the Dialog wiring.
103
+ action :backdrop_close, on: :click
104
+ end
105
+ end
106
+ on :trigger do
107
+ controller(:dialog) { action :open }
108
+ end
109
+ # Both the action and cancel Buttons close (same descriptor).
110
+ on :close do
111
+ controller(:dialog) { action :close }
112
+ end
113
+ end
114
+
115
+ style :size, default: :default, required: true, variants: SIZES,
116
+ doc: "The panel size; :sm compacts the layout and switches the footer to a two-column grid."
117
+
118
+ option :content_class, :string, doc: "Extra classes merged onto the panel element."
119
+
120
+ part "alert-dialog", "Root wrapper around the trigger and the <dialog> element"
121
+ part "alert-dialog-content", "The role=alertdialog <dialog> panel - sizing, animation, " \
122
+ "and the open state ride here",
123
+ states: {
124
+ "data-open" => "panel is open (the shared dialog controller flips the pair " \
125
+ "at runtime)",
126
+ "data-closed" => "panel is closed (the server-rendered state)",
127
+ "data-size" => { condition: "always - the resolved size",
128
+ values: SIZES.map(&:to_s) }
129
+ }
130
+ part "alert-dialog-header", "Title block - holds the optional media well, the title, " \
131
+ "and the description"
132
+ part "alert-dialog-media", "The optional media well above the title (an icon or illustration) - the " \
133
+ "header's first row; absent unless with_media is used"
134
+ part "alert-dialog-title", "The heading - the alertdialog's accessible name " \
135
+ "(required slot)"
136
+ part "alert-dialog-description", "The explanation, wired to aria-describedby " \
137
+ "(required slot)"
138
+ part "alert-dialog-footer", "The choice row - cancel then action"
139
+
140
+ # Enforces the four required slots.
141
+ # @api private
142
+ def before_render
143
+ raise ArgumentError, "AlertDialog requires with_title (the accessible name)" unless title?
144
+ unless description?
145
+ raise ArgumentError, "AlertDialog requires with_description (the alertdialog must explain itself)"
146
+ end
147
+ raise ArgumentError, "AlertDialog requires with_action (the confirming choice)" unless action?
148
+ raise ArgumentError, "AlertDialog requires with_cancel (the safe way out)" unless cancel?
149
+ end
150
+
151
+ # @api private
152
+ def title_id
153
+ "#{instance_id}-title"
154
+ end
155
+
156
+ # @api private
157
+ def description_id
158
+ "#{instance_id}-description"
159
+ end
160
+
161
+ # @api private
162
+ def dialog_attributes
163
+ {
164
+ "class" => css(:content, class: content_class),
165
+ # Explicit role: overrides the implicit dialog role (aria-modal
166
+ # still comes from showModal).
167
+ "role" => "alertdialog",
168
+ "data-slot" => "alert-dialog-content",
169
+ "data-size" => size,
170
+ "data-closed" => "",
171
+ "aria-labelledby" => title_id,
172
+ "aria-describedby" => description_id
173
+ }.merge(stimulus_attributes_for(:content))
174
+ end
175
+
176
+ # The media/size layout branches emitted as explicit server-side
177
+ # conditionals - poetry knows at render time whether media exists
178
+ # and which size was picked, so no CSS selector gymnastics.
179
+ # @api private
180
+ def header_classes
181
+ css(:header, class: [
182
+ (css(:header_with_media) if media?),
183
+ (css(:header_size_default) if size == :default),
184
+ (css(:header_size_default_with_media) if media? && size == :default)
185
+ ].compact.join(" "))
186
+ end
187
+
188
+ # @api private
189
+ def media_classes
190
+ css(:media, class: (css(:media_size_default) if size == :default))
191
+ end
192
+
193
+ # @api private
194
+ def title_classes
195
+ css(:title, class: (css(:title_beside_media) if media? && size == :default))
196
+ end
197
+
198
+ # @api private
199
+ def footer_classes
200
+ css(:footer, class: (css(:footer_size_sm) if size == :sm))
201
+ end
202
+
203
+ private :title_id, :description_id, :dialog_attributes, :header_classes, :media_classes, :title_classes
204
+ private :footer_classes
205
+ end
206
+ end
207
+ end
208
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module AlertDialog
6
+ class Preview < Poetry::Core::Preview::Base
7
+ # The canonical recipe: a destructive confirmation. Backdrop clicks
8
+ # never dismiss it; Esc still cancels (source-exact posture).
9
+ def destructive_confirm
10
+ render_component do |dialog|
11
+ dialog.with_trigger(variant: :destructive) { "Delete account" }
12
+ dialog.with_title { "Are you absolutely sure?" }
13
+ dialog.with_description { "This permanently deletes your account and all of its data." }
14
+ dialog.with_cancel { "Cancel" }
15
+ dialog.with_action(variant: :destructive) { "Delete account" }
16
+ ""
17
+ end
18
+ end
19
+
20
+ # The media well above the title (an icon), the header's third row.
21
+ def with_media
22
+ render_component do |dialog|
23
+ dialog.with_trigger(variant: :outline) { "Archive project" }
24
+ dialog.with_media { embed(Icon::Component.new(name: :archive)) }
25
+ dialog.with_title { "Archive this project?" }
26
+ dialog.with_description { "Archived projects are read-only until restored." }
27
+ dialog.with_cancel { "Keep it" }
28
+ dialog.with_action { "Archive" }
29
+ ""
30
+ end
31
+ end
32
+
33
+ # Initial focus lands on Cancel (autofocus - APG: focus the
34
+ # least-destructive action); the compact sm size for quick confirms.
35
+ def cancel_autofocus
36
+ render_component(size: :sm) do |dialog|
37
+ dialog.with_trigger(variant: :outline) { "Publish changes" }
38
+ dialog.with_title { "Publish these changes?" }
39
+ dialog.with_description { "Your edits go live immediately." }
40
+ dialog.with_cancel { "Cancel" }
41
+ dialog.with_action { "Publish" }
42
+ ""
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module AlertDialog
6
+ # Re-expressed through the cn-* theme layer, ported like the
7
+ # parent Dialog: panel chrome + size branches + backdrop + enter
8
+ # animation ride themes/default.css; native-dialog mechanisms and
9
+ # the explicit server-side media/size layout branches stay inline
10
+ # (the source's group/has- gymnastics remain conditionals, not CSS).
11
+ class Style < Poetry::Core::Style
12
+ # open:grid, NOT grid (the Dialog's UA display:none lesson). No
13
+ # `relative`: it is discarded in the top layer (the UA reasserts
14
+ # `absolute`, pinning the panel to the document origin so it scrolls
15
+ # off-screen below the fold); the UA `:modal` rule keeps it fixed and
16
+ # viewport-centered instead. See the parent Dialog.
17
+ element :content, "cn-alert-dialog-content m-auto open:grid group/alert-dialog-content"
18
+
19
+ element :header, "cn-alert-dialog-header grid grid-rows-[auto_1fr] place-items-center text-center"
20
+ # The with-media x-gap is theme-side (.cn-alert-dialog-header
21
+ # has-data-[slot=alert-dialog-media]:gap-x-*) - inline it and no
22
+ # theme could ever tighten it.
23
+ element :header_with_media, "grid-rows-[auto_auto_1fr]"
24
+ # default size: centered on mobile, left from sm (sm size stays
25
+ # centered at every breakpoint - source).
26
+ element :header_size_default, "sm:place-items-start sm:text-left"
27
+ element :header_size_default_with_media, "sm:grid-rows-[auto_1fr]"
28
+
29
+ element :media, "cn-alert-dialog-media inline-flex items-center justify-center"
30
+ element :media_size_default, "sm:row-span-2"
31
+
32
+ element :title, "cn-alert-dialog-title"
33
+ element :title_beside_media, "sm:col-start-2"
34
+
35
+ element :description, "cn-alert-dialog-description"
36
+
37
+ # Footer hook is themable (nova bands it); gap-2 moved
38
+ # theme-side with the name - direction/justify stay inline (the
39
+ # sm-size grid branch below replaces them via the class: merge).
40
+ element :footer, "cn-alert-dialog-footer flex flex-col-reverse sm:flex-row sm:justify-end"
41
+ # sm size: the compact 2-col grid footer (source).
42
+ element :footer_size_sm, "grid grid-cols-2"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ # Ratio-locked media containers.
6
+ module AspectRatio
7
+ # A container that locks its width:height ratio (CSS aspect-ratio
8
+ # via the --ratio custom property). The content is whatever should
9
+ # keep the shape: an image, an embed, a placeholder.
10
+ #
11
+ # @example A 16:9 media box
12
+ # render Poetry::Ui::AspectRatio::Component.new(ratio: "16/9") do
13
+ # image_tag "cover.jpg", class: "size-full object-cover"
14
+ # end
15
+ class Component < Poetry::Core::Component
16
+ # The accepted CSS <ratio> grammar for ratio: ("16/9", "1", "1.5").
17
+ RATIO = %r{\A\d+(\.\d+)?(\s*/\s*\d+(\.\d+)?)?\z}
18
+
19
+ # Projected into the registry, llms.txt, and the agent surface.
20
+ AGENT_RULES = [
21
+ "Pass ratio: as a string fraction ('16/9', '1/1') - Ruby's 16/9 is integer division (1).",
22
+ "The child fills the box itself (size-full object-cover on an image)."
23
+ ].freeze
24
+
25
+ option :ratio, :string, required: true,
26
+ doc: "A CSS <ratio>: \"16/9\", \"1\", \"1.5\" - kept a string so the fraction " \
27
+ "survives verbatim into the --ratio custom property."
28
+
29
+ part "aspect-ratio", "The ratio-locked box - the content block fills it",
30
+ vars: {
31
+ "--ratio" => "always - the ratio: fraction verbatim ('16/9'), consumed by the " \
32
+ "theme's aspect-ratio rule"
33
+ }
34
+
35
+ # Validates the ratio: grammar.
36
+ # @api private
37
+ def before_render
38
+ return if ratio.present? && ratio.match?(RATIO)
39
+
40
+ raise ArgumentError,
41
+ "AspectRatio ratio: must be a CSS ratio ('16/9', '1', '1.5') - got #{ratio.inspect}"
42
+ end
43
+
44
+ # @api private
45
+ def call
46
+ content_tag(:div, content, **root_attributes.to_attributes)
47
+ end
48
+
49
+ # @api private
50
+ def root_attributes
51
+ html_attributes.merge_if_not_set(
52
+ {
53
+ "data-slot" => "aspect-ratio",
54
+ "style" => "--ratio: #{ratio}"
55
+ }.merge(component_data_attributes)
56
+ )
57
+ end
58
+
59
+ private :root_attributes
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module AspectRatio
6
+ # The AspectRatio preview: the common shapes, each holding a muted
7
+ # placeholder that fills the locked box.
8
+ class Preview < Poetry::Core::Preview::Base
9
+ def video
10
+ render_component(ratio: "16/9", class: "w-64 overflow-hidden rounded-lg bg-muted") do
11
+ tag.div("16 / 9", class: "flex size-full items-center justify-center text-sm text-muted-foreground")
12
+ end
13
+ end
14
+
15
+ def square
16
+ render_component(ratio: "1", class: "w-40 overflow-hidden rounded-lg bg-muted") do
17
+ tag.div("1 / 1", class: "flex size-full items-center justify-center text-sm text-muted-foreground")
18
+ end
19
+ end
20
+
21
+ def portrait
22
+ render_component(ratio: "9/16", class: "w-24 overflow-hidden rounded-lg bg-muted") do
23
+ tag.div("9 / 16", class: "flex size-full items-center justify-center text-sm text-muted-foreground")
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module AspectRatio
6
+ # Style dictionary for the AspectRatio family: aspect-(--ratio) reads
7
+ # the --ratio custom property the component writes inline.
8
+ class Style < Poetry::Core::Style
9
+ base "relative aspect-(--ratio)"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ <%= content_tag(:div, **root_attributes.to_attributes) do %>
2
+ <%= trigger %>
3
+ <%= media %>
4
+ <% if title? || description? %>
5
+ <div data-slot="attachment-content" class="<%= css(:content) %>">
6
+ <% if title? %><span data-slot="attachment-title" class="<%= css(:title) %>"><%= title %></span><% end %>
7
+ <% if description? %><span data-slot="attachment-description" class="<%= css(:description) %>"><%= description %></span><% end %>
8
+ </div>
9
+ <% end %>
10
+ <%= content %>
11
+ <% if actions? %><div data-slot="attachment-actions" class="<%= css(:actions) %>"><% actions.each do |action| %><%= action %><% end %></div><% end %>
12
+ <% if announced? %><span data-slot="attachment-status" role="status" class="sr-only"><%= t("poetry.attachment.state.#{state}") %></span><% end %>
13
+ <% end %>