ariadne_view_components 0.0.59 → 0.0.65

Sign up to get free protection for your applications and to get access to all the features.
Files changed (279) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -0
  3. data/LICENSE.txt +661 -49
  4. data/README.md +52 -4
  5. data/app/assets/javascripts/ariadne_view_components.js +98 -7
  6. data/app/assets/javascripts/ariadne_view_components.js.br +0 -0
  7. data/app/assets/javascripts/ariadne_view_components.js.gz +0 -0
  8. data/app/assets/javascripts/ariadne_view_components.js.map +1 -1
  9. data/app/assets/stylesheets/ariadne_view_components.css +1 -7
  10. data/app/assets/stylesheets/ariadne_view_components.css.br +0 -0
  11. data/app/assets/stylesheets/ariadne_view_components.css.gz +0 -0
  12. data/app/components/ariadne/base_component.rb +79 -27
  13. data/app/components/ariadne/behaviors/tooltipable.rb +120 -0
  14. data/app/components/ariadne/conditional_wrapper.rb +21 -0
  15. data/app/components/ariadne/form/base_component.rb +74 -0
  16. data/app/components/ariadne/form/base_input_component.rb +60 -0
  17. data/app/components/ariadne/form/caption/component.html.erb +10 -0
  18. data/app/components/ariadne/form/caption/component.rb +29 -0
  19. data/app/components/ariadne/form/form_control/component.html.erb +19 -0
  20. data/app/components/ariadne/form/form_control/component.rb +27 -0
  21. data/app/components/ariadne/form/form_reference/component.html.erb +1 -0
  22. data/app/components/ariadne/form/form_reference/component.rb +18 -0
  23. data/app/components/ariadne/form/group/component.html.erb +5 -0
  24. data/app/components/ariadne/form/group/component.rb +27 -0
  25. data/app/components/ariadne/form/hidden_field/component.html.erb +1 -0
  26. data/app/components/ariadne/form/hidden_field/component.rb +15 -0
  27. data/app/components/ariadne/form/separator/component.html.erb +1 -0
  28. data/app/components/ariadne/form/separator/component.rb +8 -0
  29. data/app/components/ariadne/form/spacing_wrapper/component.html.erb +3 -0
  30. data/app/components/ariadne/form/spacing_wrapper/component.rb +8 -0
  31. data/app/components/ariadne/form/text_field/component.html.erb +25 -0
  32. data/app/components/ariadne/form/text_field/component.rb +132 -0
  33. data/app/components/ariadne/form/validation_message/component.html.erb +5 -0
  34. data/app/components/ariadne/form/validation_message/component.rb +14 -0
  35. data/app/components/ariadne/layout/narrow/component.html.erb +10 -0
  36. data/app/components/ariadne/layout/narrow/component.rb +24 -0
  37. data/app/components/ariadne/layout/nav_bar/component.css +0 -0
  38. data/app/components/ariadne/layout/nav_bar/component.html.erb +123 -0
  39. data/app/components/ariadne/layout/nav_bar/component.rb +77 -0
  40. data/app/components/ariadne/ui/button/component.html.erb +5 -0
  41. data/app/components/ariadne/ui/button/component.rb +184 -0
  42. data/app/components/ariadne/ui/clipboard_copy/component.html.erb +8 -0
  43. data/app/components/ariadne/ui/clipboard_copy/component.rb +102 -0
  44. data/app/components/ariadne/ui/clipboard_copy/component.ts +54 -0
  45. data/app/components/ariadne/ui/combobox/component.html.erb +32 -0
  46. data/app/components/ariadne/ui/combobox/component.rb +83 -0
  47. data/app/components/ariadne/ui/combobox/component.ts +119 -0
  48. data/app/components/ariadne/ui/combobox/menu_item/component.html.erb +9 -0
  49. data/app/components/ariadne/ui/combobox/menu_item/component.rb +53 -0
  50. data/app/components/ariadne/ui/combobox/option/component.html.erb +11 -0
  51. data/app/components/ariadne/ui/combobox/option/component.rb +45 -0
  52. data/app/components/ariadne/ui/heroicon/component.html.erb +3 -0
  53. data/app/components/ariadne/ui/heroicon/component.rb +141 -0
  54. data/app/components/ariadne/ui/image/component.rb +69 -0
  55. data/app/components/ariadne/ui/link/component.html.erb +3 -0
  56. data/app/components/ariadne/ui/link/component.rb +56 -0
  57. data/app/components/ariadne/ui/typography/component.html.erb +3 -0
  58. data/app/components/ariadne/ui/typography/component.rb +41 -0
  59. data/app/frontend/ariadne/index.ts +14 -0
  60. data/app/frontend/ariadne/stimulus_app.ts +53 -0
  61. data/app/frontend/ariadne/theme.ts +8 -0
  62. data/app/frontend/controllers/tooltip.ts +75 -0
  63. data/app/frontend/entrypoints/application.ts +1 -0
  64. data/app/frontend/stylesheets/ariadne_view_components.css +18 -0
  65. data/app/frontend/stylesheets/scrollbar.css +28 -0
  66. data/app/frontend/stylesheets/tippy.js/themes/tomato.css +4 -0
  67. data/app/frontend/stylesheets/typography.css +117 -0
  68. data/app/frontend/utils/createController.ts +95 -0
  69. data/app/helpers/ariadne/form_helper.rb +31 -0
  70. data/app/lib/ariadne/attributes_helper.rb +119 -0
  71. data/app/lib/ariadne/fetch_or_fallback_helper.rb +1 -1
  72. data/app/lib/ariadne/form.rb +16 -0
  73. data/app/lib/ariadne/view_helper.rb +2 -5
  74. data/app/lib/view_components_contrib/html_attrs.rb +64 -0
  75. data/app/lib/view_components_contrib/style_variants.rb +14 -0
  76. data/lib/ariadne/forms/acts_as_component.rb +125 -0
  77. data/lib/ariadne/forms/base.html.erb +8 -0
  78. data/lib/ariadne/forms/base.rb +132 -0
  79. data/lib/ariadne/forms/buffer_rewriter.rb +51 -0
  80. data/lib/ariadne/forms/builder.rb +88 -0
  81. data/lib/ariadne/forms/dsl/button_input.rb +33 -0
  82. data/lib/ariadne/forms/dsl/form_object.rb +26 -0
  83. data/lib/ariadne/forms/dsl/input.rb +322 -0
  84. data/lib/ariadne/forms/dsl/input_group.rb +34 -0
  85. data/lib/ariadne/forms/dsl/input_methods.rb +157 -0
  86. data/lib/ariadne/forms/dsl/submit_button_input.rb +36 -0
  87. data/lib/ariadne/forms/dsl/text_field_input.rb +73 -0
  88. data/lib/ariadne/forms/utils.rb +34 -0
  89. data/lib/ariadne/generate.rb +11 -0
  90. data/lib/ariadne/view_components/engine.rb +24 -7
  91. data/lib/ariadne/view_components/version.rb +1 -1
  92. data/lib/ariadne/view_components.rb +1 -1
  93. data/lib/ariadne/yard/backend.rb +24 -0
  94. data/lib/ariadne/yard/component_manifest.rb +148 -0
  95. data/lib/ariadne/yard/component_ref.rb +49 -0
  96. data/lib/ariadne/yard/docs_helper.rb +98 -0
  97. data/lib/ariadne/yard/info_arch_docs_helper.rb +31 -0
  98. data/lib/ariadne/yard/lookbook_docs_helper.rb +32 -0
  99. data/lib/ariadne/yard/lookbook_pages_backend.rb +235 -0
  100. data/lib/ariadne/yard/registry.rb +136 -0
  101. data/lib/ariadne/yard/renders_many_handler.rb +23 -0
  102. data/lib/ariadne/yard/renders_one_handler.rb +23 -0
  103. data/lib/ariadne/yard.rb +19 -0
  104. data/static/arguments.yml +141 -48
  105. data/static/audited_at.json +0 -9
  106. data/static/classes.yml +210 -209
  107. data/static/constants.json +2 -209
  108. data/static/statuses.json +0 -9
  109. metadata +140 -210
  110. data/app/assets/builds/ariadne_view_components.css +0 -2202
  111. data/app/assets/javascripts/components/ariadne/accumulator_controller/accumulator_controller.d.ts +0 -22
  112. data/app/assets/javascripts/components/ariadne/ariadne-form.d.ts +0 -22
  113. data/app/assets/javascripts/components/ariadne/ariadne.d.ts +0 -2
  114. data/app/assets/javascripts/components/ariadne/clipboard_copy_component/clipboard-copy-component.d.ts +0 -4
  115. data/app/assets/javascripts/components/ariadne/dropdown/menu_component.d.ts +0 -1
  116. data/app/assets/javascripts/components/ariadne/events_controller/events_controller.d.ts +0 -4
  117. data/app/assets/javascripts/components/ariadne/options_controller/options_controller.d.ts +0 -39
  118. data/app/assets/javascripts/components/ariadne/outlet_manager_controller/outlet_manager_controller.d.ts +0 -42
  119. data/app/assets/javascripts/components/ariadne/slideover_component/slideover-component.d.ts +0 -9
  120. data/app/assets/javascripts/components/ariadne/string_match_controller/string_match_controller.d.ts +0 -27
  121. data/app/assets/javascripts/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.d.ts +0 -48
  122. data/app/assets/javascripts/components/ariadne/tab_container_component/tab-container-component.d.ts +0 -1
  123. data/app/assets/javascripts/components/ariadne/tab_nav_component/tab-nav-component.d.ts +0 -9
  124. data/app/assets/javascripts/components/ariadne/time_ago_component/time-ago-component.d.ts +0 -1
  125. data/app/assets/javascripts/components/ariadne/toggleable_controller/toggleable_controller.d.ts +0 -34
  126. data/app/assets/javascripts/components/ariadne/tooltip_component/tooltip-component.d.ts +0 -24
  127. data/app/assets/stylesheets/dropdown.css +0 -46
  128. data/app/assets/stylesheets/prosemirror.css +0 -323
  129. data/app/assets/stylesheets/tooltip-component.css +0 -37
  130. data/app/components/ariadne/accumulator_controller/accumulator_controller.d.ts +0 -22
  131. data/app/components/ariadne/accumulator_controller/accumulator_controller.js +0 -39
  132. data/app/components/ariadne/accumulator_controller/accumulator_controller.ts +0 -48
  133. data/app/components/ariadne/action_card_component.html.erb +0 -13
  134. data/app/components/ariadne/action_card_component.rb +0 -88
  135. data/app/components/ariadne/ariadne-form.d.ts +0 -22
  136. data/app/components/ariadne/ariadne-form.js +0 -85
  137. data/app/components/ariadne/ariadne.d.ts +0 -2
  138. data/app/components/ariadne/ariadne.js +0 -24
  139. data/app/components/ariadne/ariadne.ts +0 -29
  140. data/app/components/ariadne/avatar_component.rb +0 -81
  141. data/app/components/ariadne/avatar_stack_component/avatar_stack_component.html.erb +0 -12
  142. data/app/components/ariadne/avatar_stack_component.rb +0 -75
  143. data/app/components/ariadne/base_button.rb +0 -70
  144. data/app/components/ariadne/blankslate_component/blankslate_component.html.erb +0 -26
  145. data/app/components/ariadne/blankslate_component.rb +0 -148
  146. data/app/components/ariadne/body_component.rb +0 -30
  147. data/app/components/ariadne/bottom_tab_component.html.erb +0 -4
  148. data/app/components/ariadne/bottom_tab_component.rb +0 -44
  149. data/app/components/ariadne/bottom_tab_nav_component.html.erb +0 -5
  150. data/app/components/ariadne/bottom_tab_nav_component.rb +0 -33
  151. data/app/components/ariadne/breadcrumbs_component.html.erb +0 -13
  152. data/app/components/ariadne/breadcrumbs_component.rb +0 -31
  153. data/app/components/ariadne/button_component/button_component.html.erb +0 -4
  154. data/app/components/ariadne/button_component.rb +0 -165
  155. data/app/components/ariadne/checkbox_component.html.erb +0 -5
  156. data/app/components/ariadne/checkbox_component.rb +0 -43
  157. data/app/components/ariadne/clipboard_copy_component/clipboard-copy-component.d.ts +0 -4
  158. data/app/components/ariadne/clipboard_copy_component/clipboard-copy-component.js +0 -18
  159. data/app/components/ariadne/clipboard_copy_component/clipboard-copy-component.ts +0 -19
  160. data/app/components/ariadne/clipboard_copy_component/clipboard_copy_component.html.erb +0 -9
  161. data/app/components/ariadne/clipboard_copy_component.rb +0 -90
  162. data/app/components/ariadne/close_button_component.html.erb +0 -4
  163. data/app/components/ariadne/close_button_component.rb +0 -33
  164. data/app/components/ariadne/combobox_component.html.erb +0 -14
  165. data/app/components/ariadne/combobox_component.rb +0 -76
  166. data/app/components/ariadne/component.rb +0 -127
  167. data/app/components/ariadne/container_component/container_component.html.erb +0 -3
  168. data/app/components/ariadne/container_component.rb +0 -25
  169. data/app/components/ariadne/content.rb +0 -12
  170. data/app/components/ariadne/counter_component.rb +0 -100
  171. data/app/components/ariadne/details_component/details_component.html.erb +0 -4
  172. data/app/components/ariadne/details_component.rb +0 -81
  173. data/app/components/ariadne/dropdown/menu_component.d.ts +0 -1
  174. data/app/components/ariadne/dropdown/menu_component.html.erb +0 -20
  175. data/app/components/ariadne/dropdown/menu_component.js +0 -1
  176. data/app/components/ariadne/dropdown/menu_component.rb +0 -101
  177. data/app/components/ariadne/dropdown/menu_component.ts +0 -1
  178. data/app/components/ariadne/dropdown_component/dropdown_component.html.erb +0 -8
  179. data/app/components/ariadne/dropdown_component.rb +0 -172
  180. data/app/components/ariadne/events_controller/events_controller.d.ts +0 -4
  181. data/app/components/ariadne/events_controller/events_controller.js +0 -6
  182. data/app/components/ariadne/events_controller/events_controller.ts +0 -7
  183. data/app/components/ariadne/flash_component/flash_component.html.erb +0 -31
  184. data/app/components/ariadne/flash_component.rb +0 -128
  185. data/app/components/ariadne/flex_component/flex_component.html.erb +0 -5
  186. data/app/components/ariadne/flex_component.rb +0 -56
  187. data/app/components/ariadne/footer_component/footer_component.html.erb +0 -7
  188. data/app/components/ariadne/footer_component.rb +0 -23
  189. data/app/components/ariadne/grid_component/grid_component.html.erb +0 -26
  190. data/app/components/ariadne/grid_component.rb +0 -67
  191. data/app/components/ariadne/header_component/header_component.html.erb +0 -29
  192. data/app/components/ariadne/header_component.rb +0 -111
  193. data/app/components/ariadne/heading_component.rb +0 -49
  194. data/app/components/ariadne/heroicon_component/heroicon_component.html.erb +0 -4
  195. data/app/components/ariadne/heroicon_component.rb +0 -166
  196. data/app/components/ariadne/image_component.rb +0 -53
  197. data/app/components/ariadne/inline_flex_component/inline_flex_component.html.erb +0 -6
  198. data/app/components/ariadne/inline_flex_component.rb +0 -72
  199. data/app/components/ariadne/layout_component.html.erb +0 -21
  200. data/app/components/ariadne/layout_component.rb +0 -69
  201. data/app/components/ariadne/link_component.rb +0 -65
  202. data/app/components/ariadne/list_component/list_component.html.erb +0 -3
  203. data/app/components/ariadne/list_component.rb +0 -70
  204. data/app/components/ariadne/modal_component.html.erb +0 -11
  205. data/app/components/ariadne/modal_component.rb +0 -88
  206. data/app/components/ariadne/narrow_container_component/narrow_container_component.html.erb +0 -3
  207. data/app/components/ariadne/narrow_container_component.rb +0 -30
  208. data/app/components/ariadne/options_controller/options_controller.d.ts +0 -39
  209. data/app/components/ariadne/options_controller/options_controller.js +0 -89
  210. data/app/components/ariadne/options_controller/options_controller.ts +0 -122
  211. data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.d.ts +0 -42
  212. data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.js +0 -237
  213. data/app/components/ariadne/outlet_manager_controller/outlet_manager_controller.ts +0 -278
  214. data/app/components/ariadne/panel_bar_component/panel_bar_component.html.erb +0 -20
  215. data/app/components/ariadne/panel_bar_component.rb +0 -80
  216. data/app/components/ariadne/pill_component/pill_component.html.erb +0 -3
  217. data/app/components/ariadne/pill_component.rb +0 -44
  218. data/app/components/ariadne/popover_component.html.erb +0 -10
  219. data/app/components/ariadne/popover_component.rb +0 -81
  220. data/app/components/ariadne/progress_bar_component.html.erb +0 -5
  221. data/app/components/ariadne/progress_bar_component.rb +0 -63
  222. data/app/components/ariadne/relative_time_component.html.erb +0 -3
  223. data/app/components/ariadne/relative_time_component.rb +0 -61
  224. data/app/components/ariadne/show_more_button_component.html.erb +0 -11
  225. data/app/components/ariadne/show_more_button_component.rb +0 -47
  226. data/app/components/ariadne/slideover_component/slideover-component.d.ts +0 -9
  227. data/app/components/ariadne/slideover_component/slideover-component.js +0 -11
  228. data/app/components/ariadne/slideover_component/slideover-component.ts +0 -17
  229. data/app/components/ariadne/slideover_component/slideover_component.html.erb +0 -9
  230. data/app/components/ariadne/slideover_component.rb +0 -66
  231. data/app/components/ariadne/spinner_component.html.erb +0 -16
  232. data/app/components/ariadne/spinner_component.rb +0 -45
  233. data/app/components/ariadne/string_match_controller/string_match_controller.d.ts +0 -27
  234. data/app/components/ariadne/string_match_controller/string_match_controller.js +0 -51
  235. data/app/components/ariadne/string_match_controller/string_match_controller.ts +0 -65
  236. data/app/components/ariadne/subheader_component.html.erb +0 -11
  237. data/app/components/ariadne/subheader_component.rb +0 -65
  238. data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.d.ts +0 -48
  239. data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.js +0 -207
  240. data/app/components/ariadne/synced_boolean_attributes_controller/synced_boolean_attributes_controller.ts +0 -256
  241. data/app/components/ariadne/tab_component/tab_component.html.erb +0 -3
  242. data/app/components/ariadne/tab_component.rb +0 -98
  243. data/app/components/ariadne/tab_container_component/tab-container-component.d.ts +0 -1
  244. data/app/components/ariadne/tab_container_component/tab-container-component.js +0 -23
  245. data/app/components/ariadne/tab_container_component/tab-container-component.ts +0 -24
  246. data/app/components/ariadne/tab_container_component.erb +0 -10
  247. data/app/components/ariadne/tab_container_component.rb +0 -68
  248. data/app/components/ariadne/tab_nav_component/tab-nav-component.d.ts +0 -9
  249. data/app/components/ariadne/tab_nav_component/tab-nav-component.js +0 -33
  250. data/app/components/ariadne/tab_nav_component/tab-nav-component.ts +0 -34
  251. data/app/components/ariadne/tab_nav_component/tab_nav_component.html.erb +0 -7
  252. data/app/components/ariadne/tab_nav_component.rb +0 -72
  253. data/app/components/ariadne/table_nav_component/table_nav_component.html.erb +0 -52
  254. data/app/components/ariadne/table_nav_component.rb +0 -338
  255. data/app/components/ariadne/text.rb +0 -25
  256. data/app/components/ariadne/time_ago_component/time-ago-component.d.ts +0 -1
  257. data/app/components/ariadne/time_ago_component/time-ago-component.js +0 -1
  258. data/app/components/ariadne/time_ago_component/time-ago-component.ts +0 -1
  259. data/app/components/ariadne/time_ago_component.rb +0 -56
  260. data/app/components/ariadne/timeline_component/timeline_component.html.erb +0 -19
  261. data/app/components/ariadne/timeline_component.rb +0 -34
  262. data/app/components/ariadne/toggle_component/toggle_component.html.erb +0 -15
  263. data/app/components/ariadne/toggle_component.rb +0 -95
  264. data/app/components/ariadne/toggleable_controller/toggleable_controller.d.ts +0 -34
  265. data/app/components/ariadne/toggleable_controller/toggleable_controller.js +0 -54
  266. data/app/components/ariadne/toggleable_controller/toggleable_controller.ts +0 -77
  267. data/app/components/ariadne/tooltip_component/tooltip-component.d.ts +0 -24
  268. data/app/components/ariadne/tooltip_component/tooltip-component.js +0 -43
  269. data/app/components/ariadne/tooltip_component/tooltip-component.ts +0 -57
  270. data/app/components/ariadne/tooltip_component/tooltip_component.html.erb +0 -4
  271. data/app/components/ariadne/tooltip_component.rb +0 -108
  272. data/app/lib/ariadne/action_view_extensions/form_helper.rb +0 -30
  273. data/app/lib/ariadne/audited/dsl.rb +0 -32
  274. data/app/lib/ariadne/form_builder.rb +0 -80
  275. data/app/lib/ariadne/status/dsl.rb +0 -41
  276. data/config/importmap.rb +0 -3
  277. data/exe/tailwindcss +0 -21
  278. data/lib/rubocop/cop/ariadne/base_cop.rb +0 -26
  279. data/tailwind.config.js +0 -70
@@ -0,0 +1,25 @@
1
+ <div class="ariadne-space-y-2">
2
+ <label
3
+ class="<%= style(:label) %>"
4
+ for="<%= @name %>"><%= @label %></label>
5
+ <% if required? %>
6
+ <span aria-hidden="true">*</span>
7
+ <% end %>
8
+
9
+ <%= content_tag(
10
+ :input,
11
+ nil,
12
+ class: html_attrs[:class],
13
+ **html_attrs.except(:class)
14
+ ) %>
15
+
16
+ <% if @validation_message %>
17
+ <%= render(Primer::BaseComponent.new(tag: :div, **@validation_arguments)) do %>
18
+ <span class="FormControl-inlineValidation--visual"><%= render(Primer::Beta::Octicon.new(icon: :"alert-fill", size: :xsmall, aria: { hidden: true })) %></span>
19
+ <span><%= @validation_message %></span>
20
+ <% end %>
21
+ <% end %>
22
+ <% if caption? %>
23
+ <p id="<%= @name %>-description" class="<%= style(:caption, theme:, size:, width:) %>"><%= @caption %></p>
24
+ <% end %>
25
+ </div>
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ module Form
5
+ module TextField
6
+ class Component < Ariadne::Form::BaseInputComponent
7
+ option :name
8
+ option :label
9
+ option :type, default: proc { :text }
10
+
11
+ # renders_one :leading_visual, ACCEPT_ANYTHING
12
+ # renders_one :trailing_visual, ACCEPT_ANYTHING
13
+
14
+ option :theme, default: proc { :primary }
15
+ option :size, default: proc { :base }
16
+ option :width, default: proc { :narrow }
17
+
18
+ accepts_html_attributes do |html_attrs|
19
+ html_attrs[:class] = style(theme:, size:, width:)
20
+ html_attrs[:type] = @type
21
+ end
22
+
23
+ def type
24
+ :text_field
25
+ end
26
+
27
+ def focusable?
28
+ true
29
+ end
30
+
31
+ style do
32
+ base do
33
+ [
34
+ "focus:ariadne-border-blue-300",
35
+ "focus:ariadne-bg-blue-300/20",
36
+ "dark:focus:ariadne-border-blue-600",
37
+ "dark:focus:ariadne-bg-blue-600/20",
38
+
39
+ "placeholder:ariadne-text-zinc-600",
40
+ "dark:placeholder:ariadne-text-zinc-400",
41
+
42
+ "disabled:ariadne-bg-zinc-200",
43
+ "disabled:ariadne-text-zinc-400",
44
+ "dark:disabled:ariadne-bg-zinc-800",
45
+ "dark:disabled:ariadne-text-zinc-600",
46
+ "disabled:ariadne-cursor-not-allowed",
47
+
48
+ "ariadne-bg-white",
49
+ "dark:ariadne-bg-zinc-900",
50
+
51
+ "ariadne-border",
52
+ "ariadne-border-solid",
53
+ "ariadne-border-zinc-200",
54
+ "ariadne-dark:border-zinc-700",
55
+
56
+ "[&:not(:focus)]:enabled:hover:ariadne-border-zinc-300",
57
+ "[&:not(:focus)]:enabled:hover:ariadne-bg-zinc-200/20",
58
+ "[&:not(:focus)]:dark:enabled:hover:ariadne-border-zinc-600",
59
+ "[&:not(:focus)]:dark:enabled:hover:ariadne-bg-zinc-700/20",
60
+
61
+ "focus:ariadne-border-blue-300",
62
+ "focus:ariadne-bg-blue-300/20",
63
+ "dark:focus:ariadne-border-blue-600",
64
+ "dark:focus:ariadne-bg-blue-600/20",
65
+ ]
66
+ end
67
+
68
+ variants do
69
+ theme do
70
+ primary do
71
+ []
72
+ end
73
+
74
+ error do
75
+ [
76
+ "ariadne-border",
77
+ "ariadne-border-solid",
78
+ "ariadne-border-red-600",
79
+ "ariadne-bg-red-200",
80
+ "dark:ariadne-bg-red-900",
81
+ "[&:not(:focus)]:enabled:hover:ariadne-border-red-700",
82
+ "[&:not(:focus)]:enabled:hover:ariadne-bg-red-300/80",
83
+ "[&:not(:focus)]:dark:enabled:hover:ariadne-border-red-700",
84
+ "[&:not(:focus)]:dark:enabled:hover:ariadne-bg-red-900/80",
85
+ ]
86
+ end
87
+ end
88
+
89
+ size do
90
+ sm { "ariadne-text-sm ariadne-px-1 ariadne-leading-5 ariadne-rounded" }
91
+ base { "ariadne-text-base ariadne-px-1.5 ariadne-leading-7 ariadne-rounded-md" }
92
+ lg { "ariadne-text-lg ariadne-leading-10 ariadne-px-2.5 ariadne-rounded-lg" }
93
+ end
94
+
95
+ width do
96
+ narrow { "" }
97
+ full { "ariadne-w-full" }
98
+ end
99
+ end
100
+ end
101
+
102
+ style(:label) do
103
+ base do
104
+ [
105
+ "peer-disabled:ariadne-cursor-not-allowed",
106
+ "peer-disabled:ariadne-opacity-70",
107
+ "ariadne-leading-none",
108
+ "ariadne-font-medium",
109
+ ]
110
+ end
111
+
112
+ variants do
113
+ size do
114
+ sm { "ariadne-px-1 ariadne-rounded" }
115
+ base { "ariadne-px-1.5 ariadne-rounded-md" }
116
+ md { "ariadne-px-1.5 ariadne-rounded-md" }
117
+ lg { "ariadne-px-2.5 ariadne-rounded-lg" }
118
+ end
119
+ end
120
+ end
121
+
122
+ style(:caption) do
123
+ [
124
+ "ariadne-mt-2",
125
+ "ariadne-text-sm",
126
+ "ariadne-text-gray-500",
127
+ ]
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,5 @@
1
+ <%= content_tag(:div, **@input.validation_arguments) do %>
2
+ <span class="FormControl-inlineValidation--visual" data-target="<%= @input.validation_success_icon_target %>" hidden><%= render(Ariadne::UI::Heroicon::Component.new(icon: :"check-circle", variant: HeroiconsHelper::Icon::VARIANT_SOLID, size: :xs, html_attrs: { aria: { hidden: true }})) %></span>
3
+ <span class=" FormControl-inlineValidation--visual" data-target="<%= @input.validation_error_icon_target %>"><%= render(Ariadne::UI::Heroicon::Component.new(icon: :"exclamation-triangle", variant: HeroiconsHelper::Icon::VARIANT_SOLID, size: :xs, html_attrs: { aria: { hidden: true }})) %></span>
4
+ <%= content_tag(:span, @input.invalid? ? @input.validation_messages.first : "", **@input.validation_message_arguments) %>
5
+ <% end %>
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ariadne
4
+ module Form
5
+ # :nodoc:
6
+ class ValidationMessage < BaseComponent
7
+ attr_reader :input
8
+
9
+ def initialize(input:)
10
+ @input = input
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ <main class="ariadne-grow ariadne-py-6 ariadne-px-1">
2
+ <div class="ariadne-mt-10 sm:ariadne-mx-auto sm:ariadne-w-full sm:ariadne-max-w-[480px]">
3
+ <div class="ariadne-bg-white ariadne-px-6 ariadne-py-12 ariadne-shadow sm:ariadne-rounded-lg sm:ariadne-px-12">
4
+ <%= content %>
5
+ </div>
6
+ <% if footer? %>
7
+ <%= footer %>
8
+ <% end %>
9
+ </div>
10
+ </main>
@@ -0,0 +1,24 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ module Ariadne
5
+ module Layout
6
+ module Narrow
7
+ class Component < BaseComponent
8
+ renders_one :footer, Ariadne::BaseComponent::ACCEPT_ANYTHING
9
+
10
+ style do
11
+ base do
12
+ [
13
+ "ariadne-grow",
14
+ "ariadne-bg-zinc-50",
15
+ "dark:ariadne-bg-zinc-900",
16
+ "ariadne-py-6",
17
+ "ariadne-px-1",
18
+ ]
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,123 @@
1
+ <header class="<%= style %>">
2
+ <div class="ariadne-mx-auto ariadne-px-2 sm:ariadne-px-4 lg:ariadne-px-8">
3
+ <nav class="ariadne-flex ariadne-h-16 ariadne-justify-between">
4
+ <div class="ariadne-flex ariadne-w-16 ariadne-px-2 lg:ariadne-px-0">
5
+ <% leading_items.each_with_index do |leading_item, idx| %>
6
+ <div class="<%= style(:leading_item, initial: initial?(idx)) %>">
7
+ <%= leading_item %>
8
+ </div>
9
+ <% end %>
10
+ </div>
11
+ <%# <div class="flex flex-1 items-center justify-center px-2 lg:ml-6 lg:justify-end">
12
+ <div class="w-full max-w-lg lg:max-w-xs">
13
+ <label for="search" class="sr-only">Search</label>
14
+ <div class="relative">
15
+ <div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
16
+ Heroicon(icon: :search)
17
+ </div>
18
+ <input id="search" name="search" class="block w-full rounded-md border-0 bg-white py-1.5 pl-10 pr-3 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" placeholder="Search" type="search">
19
+ </div>
20
+ </div>
21
+ </div> %>
22
+ <%# <div class="flex items-center lg:hidden">
23
+ <!-- Mobile menu button -->
24
+ <button type="button" class="relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500" aria-controls="mobile-menu" aria-expanded="false">
25
+ <span class="absolute -inset-0.5"></span>
26
+ <span class="sr-only">Open main menu</span>
27
+ <!--
28
+ Icon when menu is closed.
29
+
30
+ Menu open: "hidden", Menu closed: "block"
31
+ -->
32
+ <svg class="block h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
33
+ <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
34
+ </svg>
35
+ <!--
36
+ Icon when menu is open.
37
+
38
+ Menu open: "block", Menu closed: "hidden"
39
+ -->
40
+ <svg class="hidden h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
41
+ <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
42
+ </svg>
43
+ </button>
44
+ </div> %>
45
+ <div class="ariadne-hidden lg:ariadne-ml-4 lg:ariadne-flex lg:ariadne-items-center">
46
+ <% trailing_items.each_with_index do |trailing_item, idx| %>
47
+ <div class="<%= style(:trailing_item, initial: final?(idx)) %>">
48
+ <%= trailing_item %>
49
+ </div>
50
+ <% end %>
51
+ <%# <button type="button" class="relative flex-shrink-0 rounded-full bg-white p-1 text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
52
+ <span class="absolute -inset-1.5"></span>
53
+ <span class="sr-only">View notifications</span>
54
+ <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
55
+ <path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
56
+ </svg>
57
+ </button> %>
58
+
59
+ <!-- Profile dropdown -->
60
+ <%# <div class="relative ml-4 flex-shrink-0">
61
+ <div>
62
+ <button type="button" class="relative flex rounded-full bg-white text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2" id="user-menu-button" aria-expanded="false" aria-haspopup="true">
63
+ <span class="absolute -inset-1.5"></span>
64
+ <span class="sr-only">Open user menu</span>
65
+ <img class="h-8 w-8 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="">
66
+ </button>
67
+ </div>
68
+
69
+ <!--
70
+ Dropdown menu, show/hide based on menu state.
71
+
72
+ Entering: "transition ease-out duration-100"
73
+ From: "transform opacity-0 scale-95"
74
+ To: "transform opacity-100 scale-100"
75
+ Leaving: "transition ease-in duration-75"
76
+ From: "transform opacity-100 scale-100"
77
+ To: "transform opacity-0 scale-95"
78
+ -->
79
+ <div class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabindex="-1">
80
+ <!-- Active: "bg-gray-100", Not Active: "" -->
81
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-0">Your Profile</a>
82
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-1">Settings</a>
83
+ <a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="user-menu-item-2">Sign out</a>
84
+ </div>
85
+ </div> %>
86
+ </div>
87
+ </nav>
88
+ </div>
89
+
90
+ <!-- Mobile menu, show/hide based on menu state. -->
91
+ <%# <div class="lg:hidden" id="mobile-menu">
92
+ <div class="space-y-1 pb-3 pt-2">
93
+ <!-- Current: "bg-indigo-50 border-indigo-500 text-indigo-700", Default: "border-transparent text-gray-600 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-800" -->
94
+ <a href="#" class="block border-l-4 border-indigo-500 bg-indigo-50 py-2 pl-3 pr-4 text-base font-medium text-indigo-700">Dashboard</a>
95
+ <a href="#" class="block border-l-4 border-transparent py-2 pl-3 pr-4 text-base font-medium text-gray-600 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-800">Team</a>
96
+ <a href="#" class="block border-l-4 border-transparent py-2 pl-3 pr-4 text-base font-medium text-gray-600 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-800">Projects</a>
97
+ <a href="#" class="block border-l-4 border-transparent py-2 pl-3 pr-4 text-base font-medium text-gray-600 hover:border-gray-300 hover:bg-gray-50 hover:text-gray-800">Calendar</a>
98
+ </div>
99
+ <div class="border-t border-gray-200 pb-3 pt-4">
100
+ <div class="flex items-center px-4">
101
+ <div class="flex-shrink-0">
102
+ <img class="h-10 w-10 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="">
103
+ </div>
104
+ <div class="ml-3">
105
+ <div class="text-base font-medium text-gray-800">Tom Cook</div>
106
+ <div class="text-sm font-medium text-gray-500">tom@example.com</div>
107
+ </div>
108
+ <button type="button" class="relative ml-auto flex-shrink-0 rounded-full bg-white p-1 text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2">
109
+ <span class="absolute -inset-1.5"></span>
110
+ <span class="sr-only">View notifications</span>
111
+ <svg class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
112
+ <path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
113
+ </svg>
114
+ </button>
115
+ </div>
116
+ <div class="mt-3 space-y-1">
117
+ <a href="#" class="block px-4 py-2 text-base font-medium text-gray-500 hover:bg-gray-100 hover:text-gray-800">Your Profile</a>
118
+ <a href="#" class="block px-4 py-2 text-base font-medium text-gray-500 hover:bg-gray-100 hover:text-gray-800">Settings</a>
119
+ <a href="#" class="block px-4 py-2 text-base font-medium text-gray-500 hover:bg-gray-100 hover:text-gray-800">Sign out</a>
120
+ </div>
121
+ </div>
122
+ </div> %>
123
+ </header>
@@ -0,0 +1,77 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ module Ariadne
5
+ module Layout
6
+ module NavBar
7
+ class Component < Ariadne::BaseComponent
8
+ # Leading items at the far left of the header.
9
+ renders_many :leading_items, BaseComponent::ACCEPT_ANYTHING
10
+
11
+ # Leading items at the far left of the header.
12
+ renders_many :trailing_items, lambda { |static_content = nil, &block|
13
+ next static_content if static_content.present?
14
+
15
+ view_context.capture { block&.call }
16
+ }
17
+
18
+ renders_many :navigation_items, lambda { |static_content = nil, &block|
19
+ next static_content if static_content.present?
20
+
21
+ view_context.capture { block&.call }
22
+ }
23
+
24
+ def initial?(position)
25
+ position.zero?
26
+ end
27
+
28
+ def final?(position)
29
+ position == (leading_items.size - 1)
30
+ end
31
+
32
+ style do
33
+ base do
34
+ [
35
+ "ariadne-bg-white",
36
+ "ariadne-border-b",
37
+ "ariadne-z-50",
38
+ "ariadne-overflow-hidden",
39
+ "ariadne-border-zinc-100",
40
+ "dark:ariadne-border-zinc-900",
41
+ ]
42
+ end
43
+ end
44
+
45
+ style(:leading_item) do
46
+ base do
47
+ [
48
+ "",
49
+ ]
50
+ end
51
+
52
+ variants do
53
+ initial do
54
+ yes { "ariadne-flex ariadne-flex-shrink-0 ariadne-items-center" }
55
+ no { "ariadne-hidden lg:ariadne-ml-6 lg:ariadne-flex lg:ariadne-space-x-8" }
56
+ end
57
+ end
58
+ end
59
+
60
+ style(:trailing_item) do
61
+ base do
62
+ [
63
+ "ariadne-flex",
64
+ "ariadne-flex-1",
65
+ "ariadne-items-center",
66
+ "ariadne-justify-end",
67
+ "ariadne-gap-x-1",
68
+ ]
69
+ end
70
+
71
+ variants do
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,5 @@
1
+ <%= content_tag(button? ? :button : :a, class: html_attrs[:class], **html_attrs.except(:class)) do %>
2
+ <span class="ariadne-flex ariadne-display-grid ariadne-gap-x-1.5">
3
+ <%= leading_visual_icon %><%= content %>
4
+ </span>
5
+ <% end %>
@@ -0,0 +1,184 @@
1
+ # typed: false
2
+ # frozen_string_literal: true
3
+
4
+ module Ariadne
5
+ module UI
6
+ module Button
7
+ class Component < Ariadne::BaseComponent
8
+ include Ariadne::Behaviors::Tooltipable
9
+
10
+ option :as, default: proc { :button }
11
+ option :href, default: proc { nil }
12
+
13
+ option :type, default: proc { "button" }
14
+ option :state, default: proc { "" }
15
+ option :theme, default: proc { :primary }
16
+ option :size, default: proc { :base }
17
+ option :icon_only, default: proc { :no }
18
+ option :width, default: proc { :narrow }
19
+
20
+ renders_one :leading_visual_icon, lambda { |**attrs|
21
+ Ariadne::UI::Heroicon::Component.new(**attrs)
22
+ }
23
+
24
+ accepts_html_attributes do |html_attrs|
25
+ html_attrs[:class] = Ariadne::ViewComponents.tailwind_merger.merge([style(theme:, size:, icon_only:, width:), html_attrs[:class]].join(" "))
26
+
27
+ if link?
28
+ html_attrs[:href] = href
29
+ html_attrs.delete(:disabled)
30
+ else
31
+ html_attrs[:type] = type
32
+ html_attrs[:disabled] ||= false
33
+ end
34
+ end
35
+
36
+ style do
37
+ base do
38
+ [
39
+ "ariadne-inline-flex",
40
+ "ariadne-items-center",
41
+ "ariadne-justify-center",
42
+ "ariadne-gap-x-1.5",
43
+ "ariadne-rounded",
44
+ "ariadne-px-2",
45
+ "ariadne-py-1",
46
+ "ariadne-font-semibold",
47
+ "ariadne-shadow-sm",
48
+ "ariadne-text-black",
49
+ "focus-visible:ariadne-outline",
50
+ "focus-visible:ariadne-outline-2",
51
+ "focus-visible:ariadne-outline-offset-2",
52
+
53
+ "disabled:ariadne-border-transparent",
54
+ "disabled:ariadne-cursor-not-allowed",
55
+ ]
56
+ end
57
+
58
+ variants do
59
+ theme do
60
+ primary do
61
+ [
62
+ "ariadne-text-white",
63
+
64
+ "ariadne-bg-emerald-600",
65
+ "hover:ariadne-bg-emerald-700",
66
+ "active:ariadne-bg-emerald-800",
67
+
68
+ "disabled:ariadne-bg-emerald-100",
69
+ "disabled:ariadne-text-emerald-400",
70
+ "disabled:dark:ariadne-bg-emerald-900",
71
+ "disabled:dark:ariadne-text-emerald-600",
72
+ ]
73
+ end
74
+ secondary do
75
+ [
76
+ "ariadne-text-black",
77
+
78
+ "ariadne-bg-zinc-100",
79
+ "hover:ariadne-bg-zinc-300/20",
80
+ "active:ariadne-bg-zinc-200/80",
81
+
82
+ "dark:ariadne-text-slate-100",
83
+ "dark:ariadne-bg-zinc-900",
84
+ "dark:ariadne-hover:bg-zinc-800/80",
85
+ "dark:active:ariadne-bg-zinc-700/20",
86
+ ]
87
+ end
88
+ ghost do
89
+ [
90
+ "ariadne-text-black",
91
+ "dark:ariadne-text-white",
92
+ "ariadne-shadow-none",
93
+
94
+ "hover:ariadne-bg-zinc-200/20",
95
+ "active:ariadne-bg-zinc-500/10",
96
+ "active:ariadne-border-transparent",
97
+ "dark:hover:ariadne-bg-zinc-600/20",
98
+ "dark:active:ariadne-bg-zinc-500/10",
99
+ ]
100
+ end
101
+ danger do
102
+ [
103
+ "ariadne-border",
104
+ "ariadne-border-solid",
105
+ "ariadne-border-red-600",
106
+ "ariadne-bg-transparent",
107
+ "ariadne-text-red-600",
108
+ "hover:ariadne-bg-red-500",
109
+ "hover:ariadne-text-white",
110
+ "active:ariadne-text-white",
111
+ "active:ariadne-bg-red-600",
112
+ "dark:active:ariadne-bg-red-400",
113
+ ]
114
+ end
115
+ end
116
+
117
+ size do
118
+ xs do
119
+ [
120
+ "ariadne-text-xs",
121
+ ]
122
+ end
123
+ sm do
124
+ [
125
+ "ariadne-text-sm",
126
+ "ariadne-leading-5",
127
+ ]
128
+ end
129
+ base do
130
+ [
131
+ "ariadne-rounded-md",
132
+ "ariadne-px-2.5",
133
+ "ariadne-py-1.5",
134
+ "ariadne-text-base",
135
+ "ariadne-leading-7",
136
+ ]
137
+ end
138
+ lg do
139
+ [
140
+ "ariadne-rounded-md",
141
+ "ariadne-px-3",
142
+ "ariadne-py-2",
143
+ "ariadne-text-lg",
144
+ "ariadne-leading-8",
145
+ ]
146
+ end
147
+ xl do
148
+ [
149
+ "ariadne-rounded-md",
150
+ "ariadne-px-3.5",
151
+ "ariadne-py-2.5",
152
+ "ariadne-text-xl",
153
+ "ariadne-leading-10",
154
+ ]
155
+ end
156
+ end
157
+
158
+ icon_only do
159
+ yes {}
160
+ no {}
161
+ end
162
+ width do
163
+ narrow {}
164
+ full { "ariadne-w-full ariadne-justify-between" }
165
+ end
166
+ end
167
+ end
168
+
169
+ private
170
+
171
+ def button_tag
172
+ if link?
173
+ "a"
174
+ else
175
+ "button"
176
+ end
177
+ end
178
+
179
+ def link? = as == :link
180
+ def button? = as == :button
181
+ end
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,8 @@
1
+ <clipboard-copy class="<%= style(size:) %>" <%= html_attributes %>>
2
+ <% if content.present? %>
3
+ <%= content %>
4
+ <% else %>
5
+ <%= render Ariadne::UI::Heroicon::Component.new(icon: :"document-duplicate", variant: HeroiconsHelper::Icon::VARIANT_OUTLINE, html_attrs: { data: { "ariadne-ui-clipboard-copy-target" => "initial" }}) %>
6
+ <%= render Ariadne::UI::Heroicon::Component.new(icon: :check, variant: HeroiconsHelper::Icon::VARIANT_OUTLINE, html_attrs: { class: "text-green-600 hidden", data: { "ariadne-ui-clipboard-copy-target" => "confirmed" }}) %>
7
+ <% end %>
8
+ </clipboard-copy>