lookbook 1.5.5 → 2.0.0.beta.0

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 (198) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -31
  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 +5 -5
  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/page_tabs/component.html.erb +2 -2
  49. data/app/components/lookbook/params/editor/component.rb +1 -0
  50. data/app/components/lookbook/prose/component.rb +1 -3
  51. data/app/components/lookbook/tabs/component.html.erb +2 -2
  52. data/app/components/lookbook/tabs/component.js +1 -1
  53. data/app/components/lookbook/tag_component.rb +2 -1
  54. data/app/components/lookbook/text_button/component.html.erb +26 -0
  55. data/app/components/lookbook/text_button/component.rb +42 -0
  56. data/app/components/lookbook/toolbar/component.html.erb +1 -1
  57. data/app/components/lookbook/viewport/component.rb +0 -4
  58. data/app/controllers/concerns/lookbook/targetable_concern.rb +26 -22
  59. data/app/controllers/concerns/lookbook/with_panels_concern.rb +30 -0
  60. data/app/controllers/concerns/lookbook/with_preview_controller_concern.rb +4 -3
  61. data/app/controllers/lookbook/application_controller.rb +9 -12
  62. data/app/controllers/lookbook/embeds_controller.rb +148 -0
  63. data/app/controllers/lookbook/inspector_controller.rb +3 -22
  64. data/app/controllers/lookbook/page_controller.rb +7 -6
  65. data/app/controllers/lookbook/pages_controller.rb +3 -4
  66. data/app/controllers/lookbook/preview_controller.rb +17 -0
  67. data/app/controllers/lookbook/previews_controller.rb +10 -30
  68. data/app/helpers/lookbook/application_helper.rb +3 -19
  69. data/app/views/layouts/lookbook/application.html.erb +85 -60
  70. data/app/views/layouts/lookbook/embed.html.erb +16 -0
  71. data/app/views/layouts/lookbook/shell.html.erb +1 -1
  72. data/app/views/layouts/lookbook/skeleton.html.erb +13 -8
  73. data/app/views/lookbook/404.html.erb +2 -2
  74. data/app/views/lookbook/embeds/show.html.erb +12 -0
  75. data/app/views/lookbook/inspector/panels/_notes.html.erb +1 -1
  76. data/app/views/lookbook/inspector/panels/_output.html.erb +3 -3
  77. data/app/views/lookbook/inspector/panels/_source.html.erb +6 -6
  78. data/app/views/lookbook/inspector/show.html.erb +130 -123
  79. data/app/views/lookbook/pages/show.html.erb +81 -34
  80. data/app/views/lookbook/partials/_iframe_content_scripts.html.erb +1 -0
  81. data/app/views/lookbook/partials/_user_styles.html.erb +5 -0
  82. data/app/views/lookbook/previews/group.html.erb +14 -0
  83. data/app/views/lookbook/previews/preview.html.erb +5 -0
  84. data/app/views/lookbook/previews/show.html.erb +1 -0
  85. data/config/app.yml +31 -16
  86. data/config/panels.yml +23 -25
  87. data/config/routes.rb +3 -1
  88. data/config/tags.yml +6 -2
  89. data/lib/lookbook/cable/cable.rb +53 -0
  90. data/lib/lookbook/engine.rb +105 -93
  91. data/lib/lookbook/entities/collections/entity_collection.rb +11 -6
  92. data/lib/lookbook/entities/collections/page_collection.rb +33 -8
  93. data/lib/lookbook/entities/collections/preview_collection.rb +42 -17
  94. data/lib/lookbook/entities/collections/render_target_collection.rb +4 -0
  95. data/lib/lookbook/entities/collections/scenario_collection.rb +4 -0
  96. data/lib/lookbook/entities/concerns/{annotatable.rb → annotatable_entity.rb} +7 -6
  97. data/lib/lookbook/entities/concerns/{inspectable.rb → inspectable_entity.rb} +2 -1
  98. data/lib/lookbook/entities/concerns/{locatable.rb → locatable_entity.rb} +8 -14
  99. data/lib/lookbook/entities/concerns/navigable_entity.rb +44 -0
  100. data/lib/lookbook/entities/entity.rb +7 -2
  101. data/lib/lookbook/entities/{page.rb → page_entity.rb} +10 -6
  102. data/lib/lookbook/entities/{page_section.rb → page_section_entity.rb} +1 -1
  103. data/lib/lookbook/entities/preview_entity.rb +99 -0
  104. data/lib/lookbook/entities/renderable_entity.rb +50 -0
  105. data/lib/lookbook/entities/rendered_scenario_entity.rb +53 -0
  106. data/lib/lookbook/entities/scenario_entity.rb +112 -0
  107. data/lib/lookbook/entities/scenario_group_entity.rb +53 -0
  108. data/lib/lookbook/error.rb +5 -5
  109. data/lib/lookbook/file_watcher.rb +19 -35
  110. data/lib/lookbook/helpers/class_names_helper.rb +28 -0
  111. data/lib/lookbook/helpers/page_helper.rb +18 -0
  112. data/{app/helpers/lookbook → lib/lookbook/helpers}/preview_helper.rb +3 -0
  113. data/lib/lookbook/helpers/ui_elements_helper.rb +115 -0
  114. data/lib/lookbook/preview.rb +79 -0
  115. data/lib/lookbook/preview_controller_actions.rb +50 -0
  116. data/lib/lookbook/preview_parser.rb +4 -2
  117. data/lib/lookbook/reloaders.rb +71 -0
  118. data/lib/lookbook/runtime_context.rb +49 -0
  119. data/lib/lookbook/services/data/resolvers/data_resolver.rb +4 -6
  120. data/lib/lookbook/services/entities/entity_tree_builder.rb +6 -6
  121. data/lib/lookbook/services/list_resolver.rb +35 -0
  122. data/lib/lookbook/services/markdown_renderer.rb +12 -2
  123. data/lib/lookbook/services/priority_prefix_parser.rb +16 -0
  124. data/lib/lookbook/services/urls/search_param_encoder.rb +16 -0
  125. data/lib/lookbook/services/urls/search_param_parser.rb +7 -6
  126. data/lib/lookbook/stores/config_store.rb +16 -16
  127. data/lib/lookbook/stores/input_store.rb +1 -3
  128. data/lib/lookbook/stores/panel_store.rb +28 -50
  129. data/lib/lookbook/support/deprecation.rb +5 -0
  130. data/lib/lookbook/support/errors/preview_template_error.rb +7 -0
  131. data/lib/lookbook/support/evented_file_update_checker.rb +69 -0
  132. data/lib/lookbook/support/null_websocket.rb +9 -0
  133. data/lib/lookbook/support/store.rb +9 -0
  134. data/lib/lookbook/support/tree_node.rb +7 -7
  135. data/lib/lookbook/support/utils/path_utils.rb +7 -1
  136. data/lib/lookbook/support/utils/utils.rb +8 -0
  137. data/lib/lookbook/tags/{position_tag.rb → priority_tag.rb} +4 -4
  138. data/lib/lookbook/tags/renders_tag.rb +4 -0
  139. data/lib/lookbook/tags/tag_provider.rb +3 -0
  140. data/lib/lookbook/tags/type_tag.rb +7 -0
  141. data/lib/lookbook/tags/yard_tag.rb +1 -2
  142. data/lib/lookbook/version.rb +1 -1
  143. data/lib/lookbook/websocket.rb +6 -53
  144. data/lib/lookbook.rb +179 -53
  145. data/public/lookbook-assets/css/lookbook.css +432 -376
  146. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  147. data/public/lookbook-assets/css/themes/blue.css +7 -0
  148. data/public/lookbook-assets/css/themes/blue.css.map +1 -1
  149. data/public/lookbook-assets/css/themes/green.css +7 -0
  150. data/public/lookbook-assets/css/themes/green.css.map +1 -1
  151. data/public/lookbook-assets/css/themes/indigo.css +7 -0
  152. data/public/lookbook-assets/css/themes/indigo.css.map +1 -1
  153. data/public/lookbook-assets/css/themes/rose.css +7 -0
  154. data/public/lookbook-assets/css/themes/rose.css.map +1 -1
  155. data/public/lookbook-assets/css/themes/zinc.css +7 -0
  156. data/public/lookbook-assets/css/themes/zinc.css.map +1 -1
  157. data/public/lookbook-assets/img/lucide-sprite.svg +4960 -0
  158. data/public/lookbook-assets/js/embed.js +1363 -843
  159. data/public/lookbook-assets/js/embed.js.map +1 -1
  160. data/public/lookbook-assets/js/iframe.js +906 -0
  161. data/public/lookbook-assets/js/iframe.js.map +1 -0
  162. data/public/lookbook-assets/js/index.js +13567 -0
  163. data/public/lookbook-assets/js/index.js.map +1 -0
  164. data/public/lookbook-assets/js/lookbook-core.js +85 -0
  165. data/public/lookbook-assets/js/lookbook-core.js.map +1 -0
  166. data/public/lookbook-assets/js/lookbook.js +151 -12726
  167. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  168. data/public/lookbook-assets/lookbook-esm.js +1427 -0
  169. data/public/lookbook-assets/lookbook-esm.js.map +1 -0
  170. data/public/lookbook-assets/lookbook-global.js +1427 -0
  171. data/public/lookbook-assets/lookbook-global.js.map +1 -0
  172. data/public/lookbook-assets/lookbook.js +1427 -0
  173. data/public/lookbook-assets/lookbook.js.map +1 -0
  174. metadata +85 -77
  175. data/app/components/lookbook/embed/component.js +0 -39
  176. data/app/helpers/lookbook/component_helper.rb +0 -84
  177. data/app/helpers/lookbook/output_helper.rb +0 -19
  178. data/app/helpers/lookbook/page_helper.rb +0 -34
  179. data/app/views/layouts/lookbook/inspector.html.erb +0 -7
  180. data/app/views/layouts/lookbook/page.html.erb +0 -53
  181. data/app/views/layouts/lookbook/standalone.html.erb +0 -5
  182. data/app/views/lookbook/preview.html.erb +0 -14
  183. data/lib/lookbook/entities/collections/component_collection.rb +0 -4
  184. data/lib/lookbook/entities/collections/preview_example_collection.rb +0 -4
  185. data/lib/lookbook/entities/component.rb +0 -31
  186. data/lib/lookbook/entities/concerns/navigable.rb +0 -43
  187. data/lib/lookbook/entities/preview.rb +0 -87
  188. data/lib/lookbook/entities/preview_example.rb +0 -104
  189. data/lib/lookbook/entities/preview_group.rb +0 -52
  190. data/lib/lookbook/preview_actions.rb +0 -43
  191. data/lib/lookbook/process.rb +0 -21
  192. data/lib/lookbook/rendered_example.rb +0 -37
  193. data/lib/lookbook/services/position_prefix_parser.rb +0 -16
  194. data/lib/lookbook/services/urls/search_param_builder.rb +0 -13
  195. data/lib/lookbook/tags/component_tag.rb +0 -13
  196. /data/app/assets/lookbook/js/{embed.js → iframe.js} +0 -0
  197. /data/{app/channels/lookbook → lib/lookbook/cable}/connection.rb +0 -0
  198. /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