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,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module Command
6
+ # The Command palette inside a modal dialog - the app-wide "press
7
+ # Cmd+K" search. The native <dialog> focus trap does the overlay
8
+ # work; the dialog's title and description are screen-reader-only
9
+ # (localized defaults name the dialog), so the visible surface is
10
+ # the palette itself.
11
+ #
12
+ # The global hotkey is OPT-IN (hotkey: "meta+k") and toggles the
13
+ # dialog from anywhere; the trigger button remains the visible way
14
+ # in. Items use Command's contract: act on poetry:command:select.
15
+ #
16
+ # @example
17
+ # render Poetry::Ui::Command::DialogComponent.new(hotkey: "meta+k") do |dialog|
18
+ # dialog.with_trigger(variant: :outline) { "Open palette" }
19
+ # dialog.with_item(value: "settings") { "Settings" }
20
+ # end
21
+ class DialogComponent < Poetry::Core::Component
22
+ # The palette surface delegates to the embedded Command - callers
23
+ # use the same slot API as bare poetry_command.
24
+ delegate :with_item, :with_group, :with_separator, :with_empty, :with_loading, to: :command
25
+
26
+ # Projected into the registry, llms.txt, and the agent surface.
27
+ AGENT_RULES = [
28
+ "App-wide palettes use poetry_command_dialog with hotkey: ('meta+k') - never a hand-wired " \
29
+ "window keydown listener around poetry_dialog.",
30
+ "Open it with with_trigger(...) too - the hotkey is an accelerator, not the only way in.",
31
+ "The sr-only title/description default to the source strings - override title:/description: " \
32
+ "rather than removing them (they are the dialog's accessible name).",
33
+ "Item wiring is Command's: act on poetry:command:select; close the dialog in the listener if " \
34
+ "the action should dismiss the palette.",
35
+ "The close X is off by default (keyboard-first: Esc, the backdrop, or picking an item closes it) " \
36
+ "and appears with dismissible: false; show_close_button: true forces it - it seats in the input " \
37
+ "row, never over it."
38
+ ].freeze
39
+
40
+ renders_one :trigger,
41
+ doc: "The trigger is a poetry Button wired to open - the Dialog pattern: with_trigger(variant: " \
42
+ ":outline) { \"Open palette\" }.",
43
+ renders: lambda { |**options, &block|
44
+ options[:data] = { action: stimulus_action(:open) }.merge(options[:data] || {})
45
+ Button::Component.new(**options, &block)
46
+ }
47
+
48
+ # The SHARED dialog controller (zero new JS) - hotkey included.
49
+ use_stimulus do
50
+ on :root do
51
+ controller :dialog do
52
+ register
53
+ value :dismissible
54
+ value :hotkey, if: -> { hotkey.present? }
55
+ end
56
+ end
57
+ on :content do
58
+ controller :dialog do
59
+ target :dialog
60
+ action :close, on: :cancel
61
+ action :backdrop_close, on: :click
62
+ end
63
+ end
64
+ on :trigger do
65
+ controller(:dialog) { action :open }
66
+ end
67
+ on :close do
68
+ controller(:dialog) { action :close }
69
+ end
70
+ end
71
+
72
+ option :title, :string, default: -> { I18n.t("poetry.command.dialog_title") },
73
+ doc: "The dialog's sr-only accessible name (localized default) - override rather " \
74
+ "than remove."
75
+ option :description, :string, default: -> { I18n.t("poetry.command.dialog_description") },
76
+ doc: "The sr-only description wired to aria-describedby (localized default)."
77
+ option :hotkey, :string,
78
+ doc: "A global shortcut (\"meta+k\") that toggles the palette from anywhere; an accelerator, not the " \
79
+ "only way in."
80
+ option :dismissible, :boolean, default: true, doc: "Backdrop clicks close the palette; false keeps it open."
81
+ option :show_close_button, :boolean,
82
+ default: -> { !dismissible },
83
+ doc: "The close X, seated in the input row. Off by default while backdrop clicks close the " \
84
+ "palette (Esc, the backdrop, or picking an item all close it); on when dismissible: " \
85
+ "false so a pointer has a way out. Pass true to always show it."
86
+ option :filter, :boolean, default: true, doc: "Passed through to the embedded Command: client-side filtering."
87
+ option :loop, :boolean, default: false, doc: "Passed through: wraps arrow-key highlight movement at the ends."
88
+ option :placeholder, :string, doc: "Passed through: the filter input's placeholder text."
89
+ option :list_label, :string, doc: "Passed through: the listbox's accessible name."
90
+ option :value, :string, doc: "Passed through: seats the initial highlight on this item value."
91
+ option :id, :string, doc: "Passed through: the embedded palette's base DOM id."
92
+
93
+ part "command-dialog", "Root wrapper around the trigger and the <dialog> - the " \
94
+ "palette's own chrome; the embedded Command inside carries its " \
95
+ "own part contract"
96
+ # The dialog-* parts below are Dialog's panel chrome REUSED (same
97
+ # controller, own template) - declared here because this component
98
+ # renders them itself, retuned for the palette.
99
+ part "dialog-content", "The <dialog> panel (Dialog's chrome retuned to overflow-hidden " \
100
+ "p-0) - positioning, animation, and the open state ride here",
101
+ states: {
102
+ "data-open" => "panel is open (the dialog controller flips the pair at runtime)",
103
+ "data-closed" => "panel is closed or animating out (the server-rendered state)"
104
+ }
105
+ part "dialog-header", "Dialog's title block, sr-only here - the palette owns the " \
106
+ "visible surface"
107
+ part "dialog-title", "The sr-only heading - the dialog's accessible name (defaults to " \
108
+ "the source string)"
109
+ part "dialog-description", "The sr-only description wired to aria-describedby"
110
+
111
+ # data-component self-id: "command-dialog", not the path-derived
112
+ # "dialog" (which would shadow Dialog's own self-identification).
113
+ # @api private
114
+ def self.component_title
115
+ "command-dialog"
116
+ end
117
+
118
+ # The embedded Command. Its sizing inside the dialog is the theme's
119
+ # own (the default theme's .cn-command-dialog rule carries the
120
+ # classic h-12 chain; the styled ports keep their well and rows).
121
+ # @api private
122
+ def command
123
+ @command ||= begin
124
+ options = {
125
+ filter: filter, loop: loop, value: value,
126
+ "aria-label" => I18n.t("poetry.command.input_label")
127
+ }
128
+ options[:placeholder] = placeholder if placeholder.present?
129
+ options[:list_label] = list_label if list_label.present?
130
+ options[:id] = id if id.present?
131
+ Component.new(**options).tap do |palette|
132
+ palette.input_trailing = -> { close_button } if show_close_button
133
+ end
134
+ end
135
+ end
136
+
137
+ # The close X: Dialog's ghost icon-sm button, seated in the input row
138
+ # by the embedded Command (static beats the themed absolute offset).
139
+ # Rendered in THIS component's view context when the row renders.
140
+ # @api private
141
+ def close_button
142
+ classes = Poetry::Ui::Dialog::Style.css(:close, class: Style.css(:dialog_close))
143
+ render(Poetry::Ui::Button::Component.new(variant: :ghost, size: :"icon-sm",
144
+ label: t("poetry.dialog.close"),
145
+ class: classes, data: { action: close_action })) do
146
+ render(Poetry::Ui::Icon::Component.new(name: :x))
147
+ end
148
+ end
149
+
150
+ # The sr-only title's id - the dialog's aria-labelledby target.
151
+ # @api private
152
+ def title_id
153
+ "#{instance_id}-title"
154
+ end
155
+
156
+ # The sr-only description's id - the aria-describedby target.
157
+ # @api private
158
+ def description_id
159
+ "#{instance_id}-description"
160
+ end
161
+
162
+ # Attributes for the root wrapper.
163
+ # @api private
164
+ def root_attributes
165
+ html_attributes.merge_if_not_set(
166
+ { "data-slot" => "command-dialog" }
167
+ .merge(stimulus_attributes_for(:root))
168
+ .merge(component_data_attributes)
169
+ )
170
+ end
171
+
172
+ # Dialog's content chrome retuned for the palette (overflow-hidden
173
+ # p-0 win on conflicts); labelled/described by the sr-only header.
174
+ # @api private
175
+ def dialog_attributes
176
+ {
177
+ "class" => Poetry::Ui::Dialog::Style.css(:content, class: Style.css(:dialog_content)),
178
+ "data-slot" => "dialog-content",
179
+ "data-closed" => "",
180
+ "aria-labelledby" => title_id,
181
+ "aria-describedby" => description_id
182
+ }.merge(stimulus_attributes_for(:content))
183
+ end
184
+
185
+ # Validated action descriptor for the template's close button.
186
+ # @api private
187
+ def close_action
188
+ stimulus_action(:close)
189
+ end
190
+
191
+ private
192
+
193
+ # (Descriptor strings resolve through the declared elements above,
194
+ # never through hand-written wiring.)
195
+
196
+ # Server-stable unique id for the aria wiring (two palettes on one
197
+ # page must not share label ids).
198
+ def instance_id
199
+ @instance_id ||= poetry_instance_id("poetry-command-dialog")
200
+ end
201
+
202
+ private :command, :close_button, :title_id, :description_id, :root_attributes, :dialog_attributes, :close_action
203
+ end
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module Command
6
+ # The CommandDialog preview - the trigger-opened palette (the modal
7
+ # behaviors live in the browser pass; previews cover markup).
8
+ class DialogPreview < Poetry::Core::Preview::Base
9
+ def default
10
+ render_component do |palette|
11
+ palette.with_trigger(variant: :outline) { "Open command palette" }
12
+ palette.with_group(heading: "Suggestions") do |group|
13
+ group.with_item(value: "calendar") { "Calendar" }
14
+ group.with_item(value: "emoji") { "Search Emoji" }
15
+ end
16
+ palette.with_group(heading: "Settings") do |group|
17
+ group.with_item(value: "profile", shortcut: "⌘P") { "Profile" }
18
+ end
19
+ end
20
+ end
21
+
22
+ def close_button
23
+ render_component(show_close_button: true) do |palette|
24
+ palette.with_trigger(variant: :outline) { "Open with a close button" }
25
+ palette.with_item(value: "calendar") { "Calendar" }
26
+ palette.with_item(value: "emoji") { "Search Emoji" }
27
+ end
28
+ end
29
+
30
+ def with_hotkey
31
+ render_component(hotkey: "meta+k") do |palette|
32
+ palette.with_trigger(variant: :outline) { "⌘K" }
33
+ palette.with_item(value: "calendar") { "Calendar" }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module Command
6
+ # The Command preview matrix: the ported command-demo composition
7
+ # (inline, groups + shortcuts + keywords), the ⌘K dialog variant,
8
+ # the zero-match empty state, disabled items, the filter:false
9
+ # server mode, an initial value: highlight, and RTL.
10
+ class Preview < Poetry::Core::Preview::Base
11
+ # The command-demo port: grouped commands with shortcuts; Calendar
12
+ # carries keywords ("schedule" finds it), Calculator is disabled.
13
+ # Type to filter live; a non-matching query shows the empty part
14
+ # and announces "0 results".
15
+ def default
16
+ render_component(placeholder: "Type a command or search...",
17
+ "aria-label": "Command palette",
18
+ class: "rounded-lg border shadow-md") do |command|
19
+ command.with_group(heading: "Suggestions") do |group|
20
+ group.with_item(value: "calendar", keywords: %w[schedule dates]) { "Calendar" }
21
+ group.with_item(value: "emoji") { "Search Emoji" }
22
+ group.with_item(value: "calculator", disabled: true) { "Calculator" }
23
+ end
24
+ command.with_separator
25
+ command.with_group(heading: "Settings") do |group|
26
+ group.with_item(value: "profile", shortcut: "⌘P") { "Profile" }
27
+ group.with_item(value: "billing", shortcut: "⌘B") { "Billing" }
28
+ group.with_item(value: "settings", shortcut: "⌘S") { "Settings" }
29
+ end
30
+ end
31
+ end
32
+
33
+ # command-dialog parity: the ⌘K palette - the trigger button (and
34
+ # the opt-in meta+k hotkey) open the Dialog; focus lands in the
35
+ # input; Esc closes via the platform dialog.
36
+ def dialog
37
+ render(Poetry::Ui::Command::DialogComponent.new(hotkey: "meta+k",
38
+ placeholder: "Type a command or search...")) do |palette|
39
+ palette.with_trigger(variant: :outline) { "Open command palette (⌘K)" }
40
+ palette.with_group(heading: "Suggestions") do |group|
41
+ group.with_item(value: "calendar") { "Calendar" }
42
+ group.with_item(value: "emoji") { "Search Emoji" }
43
+ end
44
+ palette.with_separator
45
+ palette.with_group(heading: "Settings") do |group|
46
+ group.with_item(value: "profile", shortcut: "⌘P") { "Profile" }
47
+ group.with_item(value: "settings", shortcut: "⌘S") { "Settings" }
48
+ end
49
+ end
50
+ end
51
+
52
+ # The zero-match state: type any non-matching query ("zzz") - every
53
+ # item hides, the custom empty part shows, and the status region
54
+ # announces "0 results". The pinned group survives via
55
+ # always_render (the source's forceMount).
56
+ def zero_match
57
+ render_component("aria-label": "Jump to", placeholder: "Search pages…",
58
+ class: "rounded-lg border shadow-md") do |command|
59
+ command.with_empty { "Nothing matches - try fewer letters." }
60
+ command.with_item(value: "dashboard") { "Dashboard" }
61
+ command.with_item(value: "reports") { "Reports" }
62
+ command.with_group(heading: "Recent", always_render: true) do |group|
63
+ group.with_item(value: "readme", always_render: true) { "README.md" }
64
+ end
65
+ end
66
+ end
67
+
68
+ # Disabled items: skipped by arrows and the filter re-seat; the
69
+ # first ENABLED item takes the server-rendered initial highlight.
70
+ def disabled_items
71
+ render_component("aria-label": "Actions", class: "rounded-lg border shadow-md") do |command|
72
+ command.with_item(value: "cut", disabled: true) { "Cut" }
73
+ command.with_item(value: "copy") { "Copy" }
74
+ command.with_item(value: "paste", disabled: true) { "Paste" }
75
+ command.with_item(value: "delete") { "Delete" }
76
+ end
77
+ end
78
+
79
+ # An initial value: highlight, server-rendered (data-highlighted +
80
+ # the input's aria-activedescendant point at Billing before any JS).
81
+ def valued
82
+ render_component(value: "billing", "aria-label": "Settings",
83
+ class: "rounded-lg border shadow-md") do |command|
84
+ command.with_item(value: "profile") { "Profile" }
85
+ command.with_item(value: "billing") { "Billing" }
86
+ command.with_item(value: "notifications") { "Notifications" }
87
+ end
88
+ end
89
+
90
+ # filter: false - the SERVER-DRIVEN mode (the source's shouldFilter=false):
91
+ # typing never hides items client-side; the host re-renders the
92
+ # list (Turbo frame ?q=) and Command keeps highlight + activation +
93
+ # the count announcement. The loading part is the host-toggled
94
+ # pending affordance.
95
+ def server_mode
96
+ render_component(filter: false, "aria-label": "Search records",
97
+ placeholder: "Search customers…",
98
+ class: "rounded-lg border shadow-md") do |command|
99
+ command.with_loading { "Searching…" }
100
+ command.with_item(value: "acme") { "Acme Corp" }
101
+ command.with_item(value: "globex") { "Globex" }
102
+ command.with_item(value: "initech") { "Initech" }
103
+ end
104
+ end
105
+
106
+ # dir=rtl: the search icon leads via flex order, the shortcut's
107
+ # ms-auto keeps it on the reading-order end (the logical-property
108
+ # fix over the source's ml-auto).
109
+ def rtl
110
+ render_component(dir: :rtl, "aria-label": "الأوامر", list_label: "الأوامر",
111
+ placeholder: "ابحث عن أمر…", class: "rounded-lg border shadow-md") do |command|
112
+ command.with_group(heading: "اقتراحات") do |group|
113
+ group.with_item(value: "calendar", shortcut: "⌘C") { "التقويم" }
114
+ group.with_item(value: "search") { "بحث" }
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ module Command
6
+ # Re-expressed through the cn-* theme layer. The two deliberate
7
+ # source deltas (data-[highlighted] over data-[selected=true]; the
8
+ # ms-auto RTL shortcut) now live in the theme rules. The
9
+ # CommandDialog's overflow-hidden/p-0 stays INLINE (the source's
10
+ # structural pair, carried on the component in every style); its
11
+ # classic h-12 sizing chain is the DEFAULT theme's .cn-command-dialog
12
+ # rule - the styled sources carry no chain, so the dictionary must
13
+ # not either (an inline utility would override all nine themes).
14
+ class Style < Poetry::Core::Style
15
+ base "cn-command flex flex-col overflow-hidden size-full"
16
+
17
+ element :input_wrapper, "cn-command-input-wrapper flex items-center"
18
+
19
+ # h-10 input inside the h-9 wrapper is source-exact (it clips
20
+ # identically in source; the dialog chain retunes both to h-12) -
21
+ # do not "fix" it to h-9/h-9.
22
+ element :input, "cn-command-input flex w-full outline-hidden " \
23
+ "disabled:cursor-not-allowed disabled:opacity-50"
24
+
25
+ element :list, "cn-command-list overflow-x-hidden overflow-y-auto"
26
+
27
+ element :empty, "cn-command-empty"
28
+
29
+ # POETRY ADDITION: the async-pending affordance (host-toggled).
30
+ element :loading, "py-6 text-center text-sm"
31
+
32
+ element :group, "cn-command-group overflow-hidden"
33
+
34
+ # The source's group-heading descendant chain, landed on the part.
35
+ element :heading, "cn-command-group-heading"
36
+
37
+ # group/command-item: bare marker, no CSS - the vega shortcut
38
+ # re-color (group-data-selected/command-item) keys on it.
39
+ element :item, "cn-command-item group/command-item relative flex cursor-default items-center " \
40
+ "outline-hidden select-none [&_svg]:pointer-events-none [&_svg]:shrink-0 " \
41
+ "data-disabled:opacity-50 data-disabled:pointer-events-none"
42
+
43
+ # POETRY ADDITION: the label wrapper is layout-transparent - it
44
+ # mirrors the item's own row (preflight blockifies svg, so a bare
45
+ # span would stack an icon above its text).
46
+ element :item_text, "flex min-w-0 items-center gap-2"
47
+
48
+ element :shortcut, "cn-command-shortcut"
49
+
50
+ element :separator, "cn-command-separator"
51
+
52
+ # POETRY ADDITION: the polite result-count live region.
53
+ element :status, "sr-only"
54
+
55
+ # Visually-hidden text fragments (the loading part's sr copy).
56
+ element :sr_only, "sr-only"
57
+
58
+ # The source's inline SearchIcon classes, named per part.
59
+ element :search_icon, "cn-command-input-icon"
60
+
61
+ # CommandDialog: the DialogContent override - the themes' radius
62
+ # retune hook plus the source's structural pair (overflow-hidden
63
+ # p-0), inline so it beats every theme's cn-dialog-content padding
64
+ # (the ports that repeat p-0 in their rule are the source's own
65
+ # duplicates; three ports do not, and relied on this pair).
66
+ element :dialog_content, "cn-command-dialog overflow-hidden p-0"
67
+
68
+ # CommandDialog: the close X seats in the input row as its trailing
69
+ # flex item - never laid over the input, centered by the row in
70
+ # every theme. static beats the themed cn-dialog-close absolute
71
+ # offset (utilities win), shrink-0 keeps the icon button whole
72
+ # beside the w-full input; size and hover stay the theme's ghost
73
+ # icon-sm. Dictionary-held so the safelist harvests it.
74
+ element :dialog_close, "static shrink-0"
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Poetry
4
+ module Ui
5
+ # Gives an including overlay component a composable trigger:
6
+ # with_trigger(compose: true) yields the trigger's wiring to the
7
+ # block, and the block's output IS the trigger. Without compose: the
8
+ # classic path renders (a composed Button). compose: must be passed
9
+ # explicitly - the slot cannot infer intent from the block itself.
10
+ #
11
+ # The wiring hash is flat and symbol-keyed: the Stimulus behavior the
12
+ # overlay needs on its trigger, plus id/aria/slot where the overlay's
13
+ # trigger anatomy carries them - popper-positioned overlays (popover,
14
+ # hover card, tooltip, dropdown) hand over their full trigger anatomy,
15
+ # the modal family (dialog, alert, sheet, drawer) hands only the open
16
+ # action. data-component stays the caller's either way, so the
17
+ # composed control keeps its own name. Splat the wiring onto a
18
+ # WIRING-FREE control: a receiver with its own data-action would end
19
+ # up with two attributes and the first parsed wins.
20
+ #
21
+ # @example Composing your own control as the trigger
22
+ # <% menu.with_trigger(compose: true) do |wiring| %>
23
+ # <%= poetry_sidebar_menu_button(size: :lg, **wiring) do %>...<% end %>
24
+ # <% end %>
25
+ module ComposableTrigger
26
+ # The compose-mode bullet shared by every includer's AGENT_RULES -
27
+ # projected into the registry, llms.txt, and the agent surface.
28
+ AGENT_RULE =
29
+ "with_trigger(compose: true) { |wiring| ... } composes YOUR control as the trigger: " \
30
+ "the block is yielded the trigger wiring (the Stimulus behavior the overlay needs; " \
31
+ "poppers add id/aria and their trigger slot, modals hand only the open action) - " \
32
+ "splat it onto a wiring-free control (poetry_sidebar_menu_button, a plain tag); " \
33
+ "without compose: the classic composed Button renders."
34
+
35
+ private
36
+
37
+ # The custom-trigger markup when compose: true, or nil for the
38
+ # default path. Other slot options don't combine with compose -
39
+ # style the composed control itself.
40
+ def composed_trigger(wiring, options = {}, &block)
41
+ return nil unless options.delete(:compose)
42
+ raise ArgumentError, "compose: true requires a block taking |wiring|" unless block
43
+
44
+ if options.any?
45
+ raise ArgumentError,
46
+ "with_trigger options #{options.keys.inspect} don't combine with compose: " \
47
+ "true - put styling on the composed control itself"
48
+ end
49
+
50
+ attrs = { data: {} }
51
+ wiring.except(:type, "type").each do |key, value|
52
+ name = key.to_s
53
+ if name.start_with?("data-")
54
+ attrs[:data][name.delete_prefix("data-").to_sym] = value
55
+ else
56
+ attrs[name.to_sym] = value
57
+ end
58
+ end
59
+ yield(attrs)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,6 @@
1
+ <%= content_tag(:div, **root_attributes.to_attributes) do %>
2
+ <%= trigger %>
3
+ <%= content_tag(:div, **Poetry::Core::HTML::Attributes.new(content_attributes).to_attributes) do %>
4
+ <% items.each do |item| %><%= item %><% end %>
5
+ <% end %>
6
+ <% end %>