lookbook 1.5.3 → 2.0.0.beta.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -25
  3. data/app/assets/lookbook/css/lookbook.css +9 -0
  4. data/app/assets/lookbook/css/themes/blue.css +7 -0
  5. data/app/assets/lookbook/css/themes/green.css +7 -0
  6. data/app/assets/lookbook/css/themes/indigo.css +7 -0
  7. data/app/assets/lookbook/css/themes/rose.css +7 -0
  8. data/app/assets/lookbook/css/themes/zinc.css +7 -0
  9. data/app/assets/lookbook/css/tooltip.css +9 -6
  10. data/app/assets/lookbook/img/lucide-sprite.svg +4960 -0
  11. data/app/assets/lookbook/js/app.js +22 -4
  12. data/app/assets/lookbook/js/helpers/dom.js +4 -7
  13. data/app/assets/lookbook/js/helpers/string.js +4 -11
  14. data/app/assets/lookbook/js/index.js +61 -0
  15. data/app/assets/lookbook/js/lib/lookbook.js +113 -0
  16. data/app/assets/lookbook/js/lib/tippy.js +1 -0
  17. data/app/assets/lookbook/js/lookbook-core.js +1 -0
  18. data/app/assets/lookbook/js/lookbook.js +2 -61
  19. data/app/components/lookbook/base_component.rb +3 -1
  20. data/app/components/lookbook/button/component.html.erb +13 -24
  21. data/app/components/lookbook/button/component.js +13 -3
  22. data/app/components/lookbook/button/component.rb +16 -25
  23. data/app/components/lookbook/code/component.rb +0 -2
  24. data/app/components/lookbook/copy_button/component.html.erb +4 -4
  25. data/app/components/lookbook/copy_button/component.rb +6 -3
  26. data/app/components/lookbook/debug_menu/component.html.erb +1 -0
  27. data/app/components/lookbook/debug_menu/component.rb +12 -1
  28. data/app/components/lookbook/display_options/editor/component.html.erb +1 -1
  29. data/app/components/lookbook/display_options/field/component.css +0 -26
  30. data/app/components/lookbook/display_options/field/component.html.erb +1 -1
  31. data/app/components/lookbook/embed/component.html.erb +6 -51
  32. data/app/components/lookbook/embed/component.rb +17 -16
  33. data/app/components/lookbook/embed/inspector/component.html.erb +102 -0
  34. data/app/components/lookbook/embed/inspector/component.js +46 -0
  35. data/app/components/lookbook/embed/inspector/component.rb +64 -0
  36. data/app/components/lookbook/embed_code_dropdown/component.css +12 -0
  37. data/app/components/lookbook/embed_code_dropdown/component.html.erb +19 -0
  38. data/app/components/lookbook/embed_code_dropdown/component.js +26 -0
  39. data/app/components/lookbook/embed_code_dropdown/component.rb +41 -0
  40. data/app/components/lookbook/header/component.html.erb +7 -6
  41. data/app/components/lookbook/header/component.rb +5 -1
  42. data/app/components/lookbook/icon/component.html.erb +1 -1
  43. data/app/components/lookbook/icon_button/component.html.erb +20 -0
  44. data/app/components/lookbook/icon_button/component.rb +46 -0
  45. data/app/components/lookbook/nav/component.html.erb +0 -1
  46. data/app/components/lookbook/nav/entity/component.rb +2 -2
  47. data/app/components/lookbook/nav/item/component.rb +1 -1
  48. data/app/components/lookbook/params/editor/component.rb +1 -0
  49. data/app/components/lookbook/prose/component.rb +1 -3
  50. data/app/components/lookbook/tabs/component.html.erb +2 -2
  51. data/app/components/lookbook/tabs/component.js +1 -1
  52. data/app/components/lookbook/tag_component.rb +2 -1
  53. data/app/components/lookbook/text_button/component.html.erb +26 -0
  54. data/app/components/lookbook/text_button/component.rb +42 -0
  55. data/app/components/lookbook/toolbar/component.html.erb +1 -1
  56. data/app/components/lookbook/viewport/component.rb +0 -4
  57. data/app/controllers/concerns/lookbook/targetable_concern.rb +26 -22
  58. data/app/controllers/concerns/lookbook/with_panels_concern.rb +30 -0
  59. data/app/controllers/concerns/lookbook/with_preview_controller_concern.rb +4 -3
  60. data/app/controllers/lookbook/application_controller.rb +9 -12
  61. data/app/controllers/lookbook/embeds_controller.rb +148 -0
  62. data/app/controllers/lookbook/inspector_controller.rb +3 -22
  63. data/app/controllers/lookbook/page_controller.rb +7 -6
  64. data/app/controllers/lookbook/pages_controller.rb +3 -4
  65. data/app/controllers/lookbook/preview_controller.rb +17 -0
  66. data/app/controllers/lookbook/previews_controller.rb +10 -30
  67. data/app/helpers/lookbook/application_helper.rb +3 -19
  68. data/app/views/layouts/lookbook/application.html.erb +85 -60
  69. data/app/views/layouts/lookbook/embed.html.erb +16 -0
  70. data/app/views/layouts/lookbook/shell.html.erb +1 -1
  71. data/app/views/layouts/lookbook/skeleton.html.erb +13 -8
  72. data/app/views/lookbook/embeds/show.html.erb +12 -0
  73. data/app/views/lookbook/inspector/panels/_notes.html.erb +1 -1
  74. data/app/views/lookbook/inspector/panels/_output.html.erb +3 -3
  75. data/app/views/lookbook/inspector/panels/_source.html.erb +6 -6
  76. data/app/views/lookbook/inspector/show.html.erb +130 -123
  77. data/app/views/lookbook/pages/show.html.erb +81 -34
  78. data/app/views/lookbook/partials/_iframe_content_scripts.html.erb +1 -0
  79. data/app/views/lookbook/partials/_user_styles.html.erb +5 -0
  80. data/app/views/lookbook/previews/group.html.erb +14 -0
  81. data/app/views/lookbook/previews/preview.html.erb +5 -0
  82. data/app/views/lookbook/previews/show.html.erb +1 -0
  83. data/config/app.yml +31 -16
  84. data/config/panels.yml +23 -25
  85. data/config/routes.rb +3 -1
  86. data/config/tags.yml +6 -2
  87. data/lib/lookbook/cable/cable.rb +53 -0
  88. data/lib/lookbook/engine.rb +105 -93
  89. data/lib/lookbook/entities/collections/entity_collection.rb +11 -6
  90. data/lib/lookbook/entities/collections/page_collection.rb +33 -8
  91. data/lib/lookbook/entities/collections/preview_collection.rb +42 -17
  92. data/lib/lookbook/entities/collections/render_target_collection.rb +4 -0
  93. data/lib/lookbook/entities/collections/scenario_collection.rb +4 -0
  94. data/lib/lookbook/entities/concerns/{annotatable.rb → annotatable_entity.rb} +7 -6
  95. data/lib/lookbook/entities/concerns/{inspectable.rb → inspectable_entity.rb} +2 -1
  96. data/lib/lookbook/entities/concerns/{locatable.rb → locatable_entity.rb} +8 -14
  97. data/lib/lookbook/entities/concerns/navigable_entity.rb +44 -0
  98. data/lib/lookbook/entities/entity.rb +7 -2
  99. data/lib/lookbook/entities/{page.rb → page_entity.rb} +10 -6
  100. data/lib/lookbook/entities/{page_section.rb → page_section_entity.rb} +1 -1
  101. data/lib/lookbook/entities/preview_entity.rb +99 -0
  102. data/lib/lookbook/entities/renderable_entity.rb +50 -0
  103. data/lib/lookbook/entities/rendered_scenario_entity.rb +53 -0
  104. data/lib/lookbook/entities/scenario_entity.rb +112 -0
  105. data/lib/lookbook/entities/scenario_group_entity.rb +53 -0
  106. data/lib/lookbook/error.rb +5 -5
  107. data/lib/lookbook/file_watcher.rb +19 -35
  108. data/lib/lookbook/helpers/class_names_helper.rb +28 -0
  109. data/lib/lookbook/helpers/page_helper.rb +18 -0
  110. data/{app/helpers/lookbook → lib/lookbook/helpers}/preview_helper.rb +3 -0
  111. data/lib/lookbook/helpers/ui_elements_helper.rb +115 -0
  112. data/lib/lookbook/preview.rb +79 -0
  113. data/lib/lookbook/preview_controller_actions.rb +50 -0
  114. data/lib/lookbook/preview_parser.rb +4 -2
  115. data/lib/lookbook/reloaders.rb +71 -0
  116. data/lib/lookbook/runtime_context.rb +49 -0
  117. data/lib/lookbook/services/data/resolvers/data_resolver.rb +4 -6
  118. data/lib/lookbook/services/entities/entity_tree_builder.rb +6 -6
  119. data/lib/lookbook/services/list_resolver.rb +35 -0
  120. data/lib/lookbook/services/markdown_renderer.rb +12 -2
  121. data/lib/lookbook/services/priority_prefix_parser.rb +16 -0
  122. data/lib/lookbook/services/urls/search_param_encoder.rb +16 -0
  123. data/lib/lookbook/services/urls/search_param_parser.rb +7 -6
  124. data/lib/lookbook/stores/config_store.rb +16 -16
  125. data/lib/lookbook/stores/input_store.rb +1 -3
  126. data/lib/lookbook/stores/panel_store.rb +28 -50
  127. data/lib/lookbook/support/deprecation.rb +5 -0
  128. data/lib/lookbook/support/errors/preview_template_error.rb +7 -0
  129. data/lib/lookbook/support/evented_file_update_checker.rb +69 -0
  130. data/lib/lookbook/support/null_websocket.rb +9 -0
  131. data/lib/lookbook/support/store.rb +9 -0
  132. data/lib/lookbook/support/tree_node.rb +7 -7
  133. data/lib/lookbook/support/utils/path_utils.rb +7 -1
  134. data/lib/lookbook/support/utils/utils.rb +8 -0
  135. data/lib/lookbook/tags/{position_tag.rb → priority_tag.rb} +4 -4
  136. data/lib/lookbook/tags/renders_tag.rb +4 -0
  137. data/lib/lookbook/tags/tag_provider.rb +3 -0
  138. data/lib/lookbook/tags/type_tag.rb +7 -0
  139. data/lib/lookbook/tags/yard_tag.rb +1 -2
  140. data/lib/lookbook/version.rb +1 -1
  141. data/lib/lookbook/websocket.rb +6 -53
  142. data/lib/lookbook.rb +179 -53
  143. data/public/lookbook-assets/css/lookbook.css +433 -377
  144. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  145. data/public/lookbook-assets/css/themes/blue.css +7 -0
  146. data/public/lookbook-assets/css/themes/blue.css.map +1 -1
  147. data/public/lookbook-assets/css/themes/green.css +7 -0
  148. data/public/lookbook-assets/css/themes/green.css.map +1 -1
  149. data/public/lookbook-assets/css/themes/indigo.css +7 -0
  150. data/public/lookbook-assets/css/themes/indigo.css.map +1 -1
  151. data/public/lookbook-assets/css/themes/rose.css +7 -0
  152. data/public/lookbook-assets/css/themes/rose.css.map +1 -1
  153. data/public/lookbook-assets/css/themes/zinc.css +7 -0
  154. data/public/lookbook-assets/css/themes/zinc.css.map +1 -1
  155. data/public/lookbook-assets/img/lucide-sprite.svg +4960 -0
  156. data/public/lookbook-assets/js/embed.js +1363 -842
  157. data/public/lookbook-assets/js/embed.js.map +1 -1
  158. data/public/lookbook-assets/js/iframe.js +906 -0
  159. data/public/lookbook-assets/js/iframe.js.map +1 -0
  160. data/public/lookbook-assets/js/index.js +13567 -0
  161. data/public/lookbook-assets/js/index.js.map +1 -0
  162. data/public/lookbook-assets/js/lookbook-core.js +85 -0
  163. data/public/lookbook-assets/js/lookbook-core.js.map +1 -0
  164. data/public/lookbook-assets/js/lookbook.js +143 -12733
  165. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  166. data/public/lookbook-assets/lookbook-esm.js +1427 -0
  167. data/public/lookbook-assets/lookbook-esm.js.map +1 -0
  168. data/public/lookbook-assets/lookbook-global.js +1427 -0
  169. data/public/lookbook-assets/lookbook-global.js.map +1 -0
  170. data/public/lookbook-assets/lookbook.js +1427 -0
  171. data/public/lookbook-assets/lookbook.js.map +1 -0
  172. metadata +80 -72
  173. data/app/components/lookbook/embed/component.js +0 -39
  174. data/app/helpers/lookbook/component_helper.rb +0 -84
  175. data/app/helpers/lookbook/output_helper.rb +0 -19
  176. data/app/helpers/lookbook/page_helper.rb +0 -34
  177. data/app/views/layouts/lookbook/inspector.html.erb +0 -7
  178. data/app/views/layouts/lookbook/page.html.erb +0 -53
  179. data/app/views/layouts/lookbook/standalone.html.erb +0 -5
  180. data/app/views/lookbook/preview.html.erb +0 -14
  181. data/lib/lookbook/entities/collections/component_collection.rb +0 -4
  182. data/lib/lookbook/entities/collections/preview_example_collection.rb +0 -4
  183. data/lib/lookbook/entities/component.rb +0 -31
  184. data/lib/lookbook/entities/concerns/navigable.rb +0 -43
  185. data/lib/lookbook/entities/preview.rb +0 -87
  186. data/lib/lookbook/entities/preview_example.rb +0 -104
  187. data/lib/lookbook/entities/preview_group.rb +0 -52
  188. data/lib/lookbook/preview_actions.rb +0 -43
  189. data/lib/lookbook/process.rb +0 -21
  190. data/lib/lookbook/rendered_example.rb +0 -37
  191. data/lib/lookbook/services/position_prefix_parser.rb +0 -16
  192. data/lib/lookbook/services/urls/search_param_builder.rb +0 -13
  193. data/lib/lookbook/tags/component_tag.rb +0 -13
  194. /data/app/assets/lookbook/js/{embed.js → iframe.js} +0 -0
  195. /data/{app/channels/lookbook → lib/lookbook/cable}/connection.rb +0 -0
  196. /data/{app/channels/lookbook → lib/lookbook/cable}/reload_channel.rb +0 -0
@@ -1,43 +1,90 @@
1
- <div class="px-4 md:px-10 pt-8 md:pt-10 overflow-auto scroll-smooth w-full max-h-full pb-12" x-ref="scroller">
2
- <div class="w-full max-w-screen-lg mx-auto h-full flex flex-col">
3
- <% if @page.header? %>
4
- <header id="page-header" class="mb-8 prose max-w-none flex-none">
5
- <h1><%= @page.title %></h1>
6
- </header>
7
- <% end %>
1
+ <main
2
+ class="h-[calc(100vh_-_40px)]"
3
+ x-data="{}"
4
+ @navigation:complete.window="$refs.scroller.scrollTop = 0;"
5
+ @dom:update-complete.window="Lookbook.initEmbeds();">
6
+ <div class="h-full bg-lookbook-page-bg relative">
7
+ <% unless @error %>
8
+
9
+ <div class="absolute top-0 right-0 pt-1 pr-0 pl-1 pb-1 rounded-bl-md">
10
+ <div class="bg-lookbook-page-bg opacity-90 absolute inset-0 w-full h-full z-0"></div>
11
+ <div class="relative z-10 flex items-center">
12
+
13
+ <% if @previous_page %>
14
+ <%= lookbook_render :icon_button,
15
+ size: :lg,
16
+ icon: :chevron_left,
17
+ tooltip: "Previous page",
18
+ href: lookbook_page_path(@previous_page.lookup_path),
19
+ class: "pr-0.5 bg-transparent" %>
20
+ <% else %>
21
+ <%= lookbook_render :icon_button,
22
+ size: :lg,
23
+ icon: :chevron_left,
24
+ disabled: true,
25
+ class: "opacity-50 !cursor-default pr-0.5 bg-transparent" %>
26
+ <% end %>
8
27
 
9
- <%= lookbook_render :prose, id: "page-content", markdown: false, class: "max-w-none flex-none" do %>
10
- <%= @page_content %>
28
+ <% if @next_page %>
29
+ <%= lookbook_render :icon_button,
30
+ size: :lg,
31
+ icon: :chevron_right,
32
+ tooltip: "Next page",
33
+ href: lookbook_page_path(@next_page.lookup_path),
34
+ class: "pl-0.5 bg-transparent" %>
35
+ <% else %>
36
+ <%= lookbook_render :icon_button,
37
+ size: :lg,
38
+ icon: :chevron_right,
39
+ disabled: true,
40
+ class: "opacity-50 !cursor-default pl-0.5 bg-transparent" %>
41
+ <% end %>
42
+ </div>
43
+ </div>
11
44
  <% end %>
12
45
 
13
- <% if @page.sections.any? %>
14
- <%= lookbook_render :page_tabs, id: "page-tabbed-sections", markdown: false, class: "mt-6" do |page_tabs| %>
15
- <% @page.sections.each do |section| %>
16
- <% page_tabs.with_tab name: "page-section-#{section.name}", label: section.label do %>
17
- <%= page_controller.render_page(section) %>
18
- <% end %>
46
+ <div class="px-4 md:px-10 pt-8 md:pt-10 overflow-auto scroll-smooth w-full max-h-full pb-12" x-ref="scroller">
47
+ <div class="w-full max-w-screen-lg mx-auto h-full flex flex-col">
48
+ <% if @page.header? %>
49
+ <header id="page-header" class="mb-8 prose max-w-none flex-none">
50
+ <h1><%= @page.title %></h1>
51
+ </header>
19
52
  <% end %>
20
- <% end %>
21
- <% end %>
22
53
 
23
- <% if @page.footer? && @pages.many? %>
24
- <footer id="page-footer" class="flex items-center justify-between border-t border-gray-300 mt-12 pt-8 pb-10 ">
25
- <% if @previous_page %>
26
- <a href="<%= lookbook_page_path @previous_page.lookup_path %>"
27
- class="flex items-center flex-none">
28
- <%= icon :arrow_left, size: 4, class: "hover:text-indigo-800" %>
29
- <span class="ml-2 underline"><%= @previous_page.title %></span>
30
- </a>
54
+ <%= lookbook_render :prose, id: "page-content", markdown: false, class: "max-w-none flex-none" do %>
55
+ <%= @page_content %>
31
56
  <% end %>
32
57
 
33
- <% if @next_page %>
34
- <a href="<%= lookbook_page_path @next_page.lookup_path %>"
35
- class="flex items-center flex-none ml-auto">
36
- <span class="mr-2 underline"><%= @next_page.title %></span>
37
- <%= icon :arrow_right, size: 4, class: "hover:text-indigo-800" %>
38
- </a>
58
+ <% if @page.sections.any? %>
59
+ <%= lookbook_render :page_tabs, id: "page-tabbed-sections", markdown: false, class: "mt-6" do |page_tabs| %>
60
+ <% @page.sections.each do |section| %>
61
+ <% page_tabs.tab name: "page-section-#{section.name}", label: section.label do %>
62
+ <%= page_controller.render_page(section) %>
63
+ <% end %>
64
+ <% end %>
65
+ <% end %>
39
66
  <% end %>
40
- </footer>
41
- <% end %>
67
+
68
+ <% if @page.footer? && @pages.many? %>
69
+ <footer id="page-footer" class="flex items-center justify-between border-t border-gray-300 mt-12 pt-8 pb-10 ">
70
+ <% if @previous_page %>
71
+ <a href="<%= lookbook_page_path @previous_page.lookup_path %>"
72
+ class="flex items-center flex-none">
73
+ <%= icon :arrow_left, size: 4, class: "hover:text-indigo-800" %>
74
+ <span class="ml-2 underline"><%= @previous_page.title %></span>
75
+ </a>
76
+ <% end %>
77
+
78
+ <% if @next_page %>
79
+ <a href="<%= lookbook_page_path @next_page.lookup_path %>"
80
+ class="flex items-center flex-none ml-auto">
81
+ <span class="mr-2 underline"><%= @next_page.title %></span>
82
+ <%= icon :arrow_right, size: 4, class: "hover:text-indigo-800" %>
83
+ </a>
84
+ <% end %>
85
+ </footer>
86
+ <% end %>
87
+ </div>
88
+ </div>
42
89
  </div>
43
- </div>
90
+ </main>
@@ -0,0 +1 @@
1
+ <script src="<%= lookbook_asset_path("/js/iframe.js") %>" defer></script>
@@ -0,0 +1,5 @@
1
+ <% if content_for? :user_styles %>
2
+ <style media="all" id="user-styles">
3
+ <%= content_for :user_styles -%>
4
+ </style>
5
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <% if scenarios.many? %>
2
+ <%# Render a group of scenarios %>
3
+ <% scenarios.each do |scenario| %>
4
+ <div style="margin-bottom: 30px !important; display: block !important;">
5
+ <h6 style="all: unset; display: block; color: #999; font-family: sans-serif; font-size: 14px; margin-top: 0; margin-bottom: 10px;">
6
+ <%= scenario.label %>
7
+ </h6>
8
+ <%= scenario.output %>
9
+ </div>
10
+ <% end %>
11
+ <% else %>
12
+ <%# Render a single scenario %>
13
+ <%= scenarios.first.output %>
14
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <% if @render_args[:component] %>
2
+ <%= render(@render_args[:component], @render_args[:args], &@render_args[:block]) %>
3
+ <% else %>
4
+ <%= render(@render_args[:template], **@render_args[:locals], &@render_args[:block]) %>
5
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= @preview_html %>
data/config/app.yml CHANGED
@@ -1,14 +1,30 @@
1
1
  shared:
2
2
  project_name: Lookbook
3
- log_level: 2
4
- log_use_rails_logger: true
5
- auto_refresh: false
6
- components_path: app/components
7
- page_controller: Lookbook::PageController
3
+
4
+ preview_paths: [test/components/previews]
5
+ preview_display_options: {}
6
+ preview_controller: "Lookbook::PreviewController"
7
+ preview_template: lookbook/previews/preview
8
+ preview_inspector:
9
+ main_panels: [preview, output]
10
+ drawer_panels: [source, notes, params, "*"]
11
+ preview_embeds:
12
+ policy: "SAMEORIGIN"
13
+ panels: false
14
+ actions: []
15
+ scenarios: []
16
+ display_option_controls: true
17
+ preview_layout: ~
18
+ preview_disable_action_view_annotations: true
19
+ preview_type_default: view_component
20
+ preview_sort_scenarios: false
21
+
22
+ page_controller: "Lookbook::PageController"
8
23
  page_route: pages
9
24
  page_paths: [test/components/docs]
10
25
  page_extensions: [html.*, md.*]
11
26
  page_options: {}
27
+
12
28
  markdown_options:
13
29
  tables: true
14
30
  fenced_code_blocks: true
@@ -17,30 +33,29 @@ shared:
17
33
  highlight: true
18
34
  with_toc_data: true
19
35
  lax_spacing: true
36
+
20
37
  highlighter_options:
21
38
  theme: github
22
39
  dark: false
23
- sort_examples: false
24
- preview_paths: []
25
- preview_display_options: {}
26
- preview_disable_action_view_annotations: true
27
- preview_params_options_eval: false
28
- listen: false
40
+
41
+ component_paths: [app/views]
42
+
43
+ reload_on_change: ~
29
44
  listen_paths: []
30
45
  listen_extensions: [rb, html.*]
31
- listen_use_polling: false
46
+
32
47
  ui_theme: indigo
33
48
  ui_theme_overrides: {}
34
49
  ui_favicon: true
50
+
51
+ log_level: 2
52
+ log_use_rails_logger: true
53
+
35
54
  debug_menu: false
36
55
  experimental_features: false
37
56
 
38
57
  development:
39
- listen: true
40
- auto_refresh: true
41
58
  debug_menu: true
42
59
 
43
60
  test:
44
- listen: false
45
- auto_refresh: false
46
61
  debug_menu: true
data/config/panels.yml CHANGED
@@ -1,30 +1,28 @@
1
1
  shared:
2
- main:
3
- - name: preview
4
- partial: lookbook/inspector/panels/preview
5
- label: Preview
6
- hotkey: v
2
+ preview:
3
+ partial: lookbook/inspector/panels/preview
4
+ label: Preview
5
+ hotkey: v
7
6
 
8
- - name: output
9
- partial: lookbook/inspector/panels/output
10
- label: HTML
11
- hotkey: h
7
+ output:
8
+ partial: lookbook/inspector/panels/output
9
+ label: HTML
10
+ hotkey: h
12
11
 
13
- drawer:
14
- - name: source
15
- partial: lookbook/inspector/panels/source
16
- label: Source
17
- hotkey: s
18
- copy: "->(data) { data.examples.map { |e| e.source }.join(\n) }"
12
+ source:
13
+ partial: lookbook/inspector/panels/source
14
+ label: Source
15
+ hotkey: s
16
+ copy: "->(data) { data.scenarios.map { |e| e.source }.join(\n) }"
19
17
 
20
- - name: notes
21
- partial: lookbook/inspector/panels/notes
22
- label: Notes
23
- hotkey: n
24
- disabled: ->(data) { data.examples.select { |e| e.notes.present? }.none? }
18
+ notes:
19
+ partial: lookbook/inspector/panels/notes
20
+ label: Notes
21
+ hotkey: n
22
+ disabled: "->(data) { data.scenarios.select { |e| e.notes.present? }.none? }"
25
23
 
26
- - name: params
27
- partial: lookbook/inspector/panels/params
28
- label: Params
29
- hotkey: p
30
- disabled: ->(data) { data.context.params.none? }
24
+ params:
25
+ partial: lookbook/inspector/panels/params
26
+ label: Params
27
+ hotkey: p
28
+ disabled: "->(data) { data.context.params.none? }"
data/config/routes.rb CHANGED
@@ -10,7 +10,9 @@ Lookbook::Engine.routes.draw do
10
10
 
11
11
  get "/previews", to: "previews#index", as: :lookbook_previews
12
12
  get "/preview/*path", to: "previews#show", as: :lookbook_preview
13
+
13
14
  get "/inspect/*path", to: "inspector#show", as: :lookbook_inspect
14
15
 
15
- get "/*path", to: "inspector#show_legacy", as: :lookbook_inspect_legacy
16
+ get "/embed", to: "embeds#lookup", as: :lookbook_embed_lookup
17
+ get "/embed/*path", to: "embeds#show", as: :lookbook_embed
16
18
  end
data/config/tags.yml CHANGED
@@ -11,8 +11,8 @@ shared:
11
11
  label: Display
12
12
  opts: {}
13
13
 
14
- position:
15
- label: Position
14
+ priority:
15
+ label: Priority
16
16
  opts: {}
17
17
 
18
18
  id:
@@ -23,6 +23,10 @@ shared:
23
23
  label: Component
24
24
  opts: {}
25
25
 
26
+ renders:
27
+ label: Renders
28
+ opts: {}
29
+
26
30
  param:
27
31
  label: Param
28
32
  opts: {}
@@ -0,0 +1,53 @@
1
+ require "action_cable/engine"
2
+ require_relative "./connection"
3
+ require_relative "./reload_channel"
4
+
5
+ module Lookbook
6
+ class Cable
7
+ attr_reader :engine_mount_path, :server, :logger
8
+
9
+ def initialize(engine_mount_path, logger: Lookbook.logger)
10
+ @engine_mount_path = engine_mount_path
11
+ @logger = logger
12
+
13
+ logger.info "Initializing websocket"
14
+
15
+ if Gem::Version.new(Rails.version) >= Gem::Version.new(6.0)
16
+ @server = ActionCable::Server::Base.new config: cable_config
17
+ else
18
+ @server = ActionCable::Server::Base.new
19
+ @server.config = cable_config
20
+ end
21
+ end
22
+
23
+ def broadcast(message, payload = nil)
24
+ logger.debug message.to_s
25
+ server.broadcast(message.to_s, payload.to_h)
26
+ end
27
+
28
+ def mount_path
29
+ "/cable"
30
+ end
31
+
32
+ def full_mount_path
33
+ "#{engine_mount_path}/#{mount_path}".gsub("//", "/")
34
+ end
35
+
36
+ def mountable?
37
+ true
38
+ end
39
+
40
+ alias_method :mounted?, :mountable?
41
+
42
+ protected
43
+
44
+ def cable_config
45
+ cable = ActionCable::Server::Configuration.new
46
+ cable.cable = {adapter: "async"}.with_indifferent_access
47
+ cable.mount_path = nil
48
+ cable.connection_class = -> { Lookbook::Connection }
49
+ cable.logger = logger
50
+ cable
51
+ end
52
+ end
53
+ end
@@ -1,6 +1,3 @@
1
- require "view_component"
2
- require "action_cable/engine"
3
- require "listen"
4
1
  require "yard"
5
2
 
6
3
  module Lookbook
@@ -9,105 +6,66 @@ module Lookbook
9
6
 
10
7
  config.autoload_paths << File.expand_path(root.join("app/components"))
11
8
 
12
- config.before_configuration do
13
- config.lookbook = Lookbook.config
14
- end
15
-
16
- initializer "lookbook.viewcomponent.config_sync" do
17
- opts.preview_paths += config.view_component.preview_paths
18
- opts.preview_controller ||= config.view_component.preview_controller
19
-
20
- if config.view_component.view_component_path.present?
21
- opts.components_path = config.view_component.view_component_path
22
- end
23
- end
24
-
25
9
  initializer "lookbook.assets.serve" do
26
10
  config.app_middleware.use(
27
11
  Rack::Static,
28
- urls: ["/lookbook-assets"], root: root.join("public").to_s
12
+ urls: ["/lookbook-assets"],
13
+ root: root.join("public").to_s
29
14
  )
30
15
  end
31
16
 
32
- initializer "lookbook.file_watcher.paths" do
33
- opts.listen_paths += opts.preview_paths
34
- opts.listen_paths << opts.components_path
35
- end
17
+ config.before_configuration do
18
+ config.lookbook = Lookbook.config
36
19
 
37
- initializer "lookbook.file_watcher.previews" do
38
- file_watcher.watch(opts.listen_paths, opts.listen_extensions, wait_for_delay: 0.5) do |changes|
39
- parser.parse { run_hooks(:after_change, changes) }
20
+ if defined?(ViewComponent)
21
+ config.lookbook.using_view_component = true
22
+ else
23
+ require "view_component"
24
+ config.lookbook.using_view_component = false
40
25
  end
41
26
  end
42
27
 
43
- initializer "lookbook.file_watcher.pages" do
44
- file_watcher.watch(opts.page_paths, opts.page_extensions) do |changes|
45
- Engine.pages.load(Engine.page_paths)
46
- Engine.mark_changed
47
- Engine.websocket.broadcast(:reload)
48
- run_hooks(:after_change, changes)
49
- end
50
- end
28
+ config.after_initialize do
29
+ if opts.using_view_component || Rails.env.test?
30
+ vc_config = Engine.host_config.view_component
51
31
 
52
- initializer "lookbook.parser.previews_load_callback" do
53
- parser.after_parse do |code_objects|
54
- Engine.previews.load(code_objects.all(:class))
55
- Engine.mark_changed
56
- Engine.websocket.broadcast(:reload)
57
- end
58
- end
32
+ opts.preview_paths += vc_config.preview_paths
33
+ opts.preview_controller = vc_config.preview_controller
34
+ opts.preview_layout = vc_config.default_preview_layout
59
35
 
60
- # The preview controller handles the rendering of individual previews.
61
- #
62
- # Lookbook injects some actions into whichever controller has been
63
- # specified by the user in order to render previews within the context of
64
- # the particular controller class instance so that any before_action/after_action
65
- # callbacks will be correctly processed.
66
- config.after_initialize do
67
- @preview_controller = opts.preview_controller.constantize
68
- @preview_controller.class_eval { include Lookbook::PreviewActions }
69
- end
36
+ vc_config.show_previews = true
70
37
 
71
- config.after_initialize do
72
- if Rails.application.respond_to?(:server)
73
- Rails.application.server { file_watcher.start if listen? }
74
- elsif process.supports_listening?
75
- file_watcher.start if listen?
38
+ if vc_config.view_component_path.present?
39
+ opts.component_paths << vc_config.view_component_path
40
+ end
76
41
  end
42
+
43
+ opts.reload_on_change = host_config.reload_classes_only_on_change if opts.reload_on_change.nil?
77
44
  end
78
45
 
79
46
  config.after_initialize do
80
- Engine.pages.load(Engine.page_paths)
81
- parser.parse { run_hooks(:after_initialize) }
47
+ reloaders.add(:previews, Engine.preview_watch_paths, opts.listen_extensions, &Engine.method(:load_previews))
48
+ reloaders.add(:pages, Engine.page_watch_paths, opts.page_extensions, &Engine.method(:load_pages))
49
+ reloaders.execute
50
+
51
+ Engine.run_hooks(:after_initialize)
82
52
  end
83
53
 
84
54
  def opts
85
55
  Lookbook.config
86
56
  end
87
57
 
88
- def run_hooks(event_name, *args)
89
- Engine.hooks.for_event(event_name).each do |hook|
90
- hook.call(Lookbook, *args)
91
- end
92
- end
93
-
94
58
  def parser
95
59
  @_parser ||= PreviewParser.new(opts.preview_paths, Engine.tags)
96
60
  end
97
61
 
98
- def file_watcher
99
- @_file_watcher ||= FileWatcher.new(force_polling: opts.listen_use_polling)
100
- end
101
-
102
- def process
103
- @_process ||= Process.new(env: Rails.env)
104
- end
105
-
106
- def listen?
107
- opts.listen && process.supports_listening?
62
+ def reloaders
63
+ @_reloaders ||= Reloaders.new
108
64
  end
109
65
 
110
66
  class << self
67
+ delegate :app_name, to: :runtime_context
68
+
111
69
  def mount_path
112
70
  routes.find_script_name({})
113
71
  end
@@ -116,22 +74,24 @@ module Lookbook
116
74
  mount_path.present?
117
75
  end
118
76
 
119
- def app_name
120
- name = if Rails.application.class.respond_to?(:module_parent_name)
121
- Rails.application.class.module_parent_name
122
- else
123
- Rails.application.class.parent_name
124
- end
125
- name.underscore
77
+ def reloading?
78
+ opts.reload_on_change
79
+ end
80
+
81
+ def auto_refresh?
82
+ reloading? && runtime_context.web? && FileWatcher.evented?
126
83
  end
127
84
 
128
85
  def websocket
129
- if mounted?
130
- use_websocket = opts.auto_refresh && opts.listen && process.supports_listening?
131
- @websocket ||= use_websocket ? Websocket.new(mount_path, logger: Lookbook.logger) : Websocket.noop
132
- else
133
- Websocket.noop
134
- end
86
+ @_websocket ||= auto_refresh? ? Websocket.new(mount_path, logger: Lookbook.logger) : NullWebsocket.new
87
+ end
88
+
89
+ def runtime_context
90
+ @_runtime_context ||= RuntimeContext.new(env: Rails.env)
91
+ end
92
+
93
+ def theme
94
+ @_theme ||= Lookbook::Theme.new(opts.ui_theme, opts.ui_theme_overrides)
135
95
  end
136
96
 
137
97
  def panels
@@ -150,18 +110,50 @@ module Lookbook
150
110
  @_hooks ||= HookStore.init_from_config
151
111
  end
152
112
 
113
+ def run_hooks(event_name, *args)
114
+ hooks.for_event(event_name).each do |hook|
115
+ hook.call(Lookbook, *args)
116
+ end
117
+ end
118
+
119
+ def host_app_path
120
+ Rails.application.root.join("app")
121
+ end
122
+
123
+ def host_config
124
+ Rails.application.config
125
+ end
126
+
127
+ def view_paths
128
+ ActionView::ViewPaths.all_view_paths.flat_map do |view_path|
129
+ view_path.paths.map { |path| Pathname(path.to_s) }
130
+ end
131
+ end
132
+
153
133
  def component_paths
154
- @_component_paths ||= Array(PathUtils.to_absolute(opts.components_path))
134
+ @_component_paths ||= begin
135
+ paths = [*opts.component_paths, *Engine.view_paths, host_app_path]
136
+ PathUtils.normalize_paths(paths)
137
+ end
155
138
  end
156
139
 
157
140
  def page_paths
158
141
  @_page_paths ||= PathUtils.normalize_paths(opts.page_paths)
159
142
  end
160
143
 
144
+ alias_method :page_watch_paths, :page_paths
145
+
161
146
  def preview_paths
162
147
  @_preview_paths ||= PathUtils.normalize_paths(opts.preview_paths)
163
148
  end
164
149
 
150
+ def preview_watch_paths
151
+ return @_preview_watch_paths if @_preview_watch_paths
152
+
153
+ paths = [*opts.preview_paths, opts.components_path, *opts.listen_paths, *view_paths].uniq
154
+ @_preview_watch_paths ||= PathUtils.normalize_paths(paths)
155
+ end
156
+
165
157
  def pages
166
158
  @_pages ||= PageCollection.new
167
159
  end
@@ -170,20 +162,40 @@ module Lookbook
170
162
  @_previews ||= PreviewCollection.new
171
163
  end
172
164
 
173
- def mark_changed
174
- @_last_changed = nil
165
+ def preview_controller
166
+ return @_preview_controller if @_preview_controller
167
+
168
+ @_preview_controller = opts.preview_controller.constantize
169
+ @_preview_controller.include PreviewControllerActions
175
170
  end
176
171
 
177
- def last_changed
178
- @_last_changed ||= (Time.now.to_f * 1000).to_i
172
+ def load_previews(changes = nil)
173
+ changed_files = [*changes[:added], *changes[:modified]] if changes
174
+ parser.parse(changed_files) do |code_objects|
175
+ previews.load(code_objects.all(:class), changes)
176
+ end
177
+ end
178
+
179
+ def load_pages(changes = nil)
180
+ pages.load(Engine.page_paths, changes)
179
181
  end
180
182
 
181
- attr_reader :preview_controller
183
+ def notify_clients(changes = nil)
184
+ return unless changes.present?
185
+
186
+ websocket.broadcast(:reload)
187
+ run_hooks(:after_change, changes.to_h)
188
+ end
189
+
190
+ def files_changed(modified, added, removed)
191
+ changes = {modified: modified, added: added, removed: removed}
192
+ reloaders.register_changes(changes)
193
+ notify_clients(changes)
194
+ end
182
195
  end
183
196
 
184
197
  at_exit do
185
- file_watcher.stop
186
- run_hooks(:before_exit)
198
+ Engine.run_hooks(:before_exit)
187
199
  end
188
200
  end
189
201
  end