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
@@ -0,0 +1,26 @@
1
+ <%= render_component_tag tag_name,
2
+ id: id,
3
+ href: href,
4
+ class: [
5
+ "block px-2 py-1.5 text-xs rounded-md bg-lookbook-button-bg text-lookbook-button-text w-full transition focus:outline-none focus-visible:outline-none",
6
+ {
7
+ "hover:bg-lookbook-button-bg-hover": !disabled,
8
+ "cursor-[not-allowed] opacity-50": disabled
9
+ }
10
+ ],
11
+ disabled: disabled,
12
+ aria: { label: tooltip } do %>
13
+
14
+ <span class="flex items-center space-x-2 justify-center">
15
+ <span x-ref="icon">
16
+ <%= icons.present? ? safe_join(icons) : (lookbook_render(:icon, name: icon, size: icon_size, ":class": "{'animate-spin': _spinning}") if icon) %>
17
+ </span>
18
+ <% if content %>
19
+ <span><%= content %></span>
20
+ <% end %>
21
+ </span>
22
+
23
+ <% if tooltip %>
24
+ <label class="hidden" x-ref="tooltip"><%= tooltip %></label>
25
+ <% end %>
26
+ <% end %>
@@ -0,0 +1,42 @@
1
+ module Lookbook
2
+ class TextButton::Component < Lookbook::BaseComponent
3
+ renders_many :icons, Icon::Component
4
+
5
+ ICON_SIZES = {
6
+ xs: 3,
7
+ sm: 3.5,
8
+ md: 4,
9
+ lg: 6
10
+ }
11
+
12
+ attr_reader :icon, :tooltip, :disabled, :size, :href
13
+
14
+ def initialize(id: nil, icon: nil, tooltip: nil, disabled: false, size: :md, href: nil, **html_attrs)
15
+ @id = id
16
+ @icon = icon
17
+ @tooltip = tooltip
18
+ @disabled = disabled
19
+ @size = size
20
+ @href = href
21
+ super(**html_attrs)
22
+ end
23
+
24
+ def id
25
+ @id ||= Utils.temp_id(prefix: "button")
26
+ end
27
+
28
+ def icon_size
29
+ ICON_SIZES[size]
30
+ end
31
+
32
+ def tag_name
33
+ href.present? ? :a : :button
34
+ end
35
+
36
+ protected
37
+
38
+ def alpine_component
39
+ "buttonComponent"
40
+ end
41
+ end
42
+ end
@@ -1,5 +1,5 @@
1
1
  <%= render_component_tag class: "h-10 border-b border-lookbook-divider w-full flex items-center text-sm flex-none bg-lookbook-toolbar-bg" do %>
2
- <div class="toolbar-sections flex items-stretch w-full">
2
+ <div class="toolbar-sections flex items-stretch w-full h-10">
3
3
  <%= safe_join(sections) %>
4
4
  </div>
5
5
  <% end %>
@@ -9,10 +9,6 @@ module Lookbook
9
9
  super(**html_attrs)
10
10
  end
11
11
 
12
- def generate_id(*args)
13
- args.map { |args| args.delete_prefix("/").tr("&?=/_-", "-") }.join("-")
14
- end
15
-
16
12
  protected
17
13
 
18
14
  def alpine_component
@@ -14,19 +14,17 @@ module Lookbook
14
14
  end
15
15
 
16
16
  def lookup_entities
17
- @target = Lookbook.previews.find_example_by_path(params[:path])
17
+ @target = Engine.previews.find_scenario_by_path(params[:path])
18
18
  if @target.present?
19
19
  @preview = @target.preview
20
- if params[:path] == @preview&.path
21
- redirect_to lookbook_inspect_path("#{params[:path]}/#{@preview.default_example.name}", params.permit!)
20
+ if params[:path] == @preview&.lookup_path
21
+ redirect_to lookbook_inspect_path("#{params[:path]}/#{@preview.default_scenario.name}", params.permit!)
22
22
  end
23
23
  else
24
- @preview = Lookbook.previews.find_by_path(params[:path])
24
+ @preview = Engine.previews.find_by_path(params[:path])
25
25
  if @preview.present?
26
- default_example = @preview.default_example
27
- redirect_to lookbook_inspect_path(default_example.path, params.permit!) if default_example
28
- else
29
- @preview = Lookbook.previews.find_by_path(path_segments.slice(0, path_segments.size - 1).join("/"))
26
+ default_scenario = @preview.default_scenario
27
+ redirect_to lookbook_inspect_path(default_scenario.lookup_path, params.permit!) if default_scenario
30
28
  end
31
29
  end
32
30
  end
@@ -44,22 +42,21 @@ module Lookbook
44
42
  display_params = SearchParamParser.call(params[:_display])
45
43
  display_params.each do |name, value|
46
44
  if @dynamic_display_options.key?(name)
47
- cookies["lookbook-display-#{name}"] = value.is_a?(Array) ? value[1] : value
45
+ cookies["lookbook-display-#{name}"] = value
48
46
  end
49
47
  end
50
48
  end
51
49
 
52
50
  @dynamic_display_options.each do |name, opts|
53
51
  choices = opts.is_a?(Hash) ? opts[:choices].to_a : opts
54
- value = choices.first.is_a?(Array) ? choices.first[1] : choices.first
55
- @static_display_options[name] ||= cookies.fetch("lookbook-display-#{name}", value)
52
+ @static_display_options[name] ||= cookies.fetch("lookbook-display-#{name}", choices.first)
56
53
  end
57
54
 
58
55
  unless params[:_display]
59
- display_params = @dynamic_display_options.map do |name, opts|
60
- [name, @static_display_options[name]]
61
- end.to_h
62
- request.query_parameters[:_display] = SearchParamBuilder.call(display_params)
56
+ display_params = @dynamic_display_options.each_with_object({}) do |(name, opts), hash|
57
+ hash[name] = @static_display_options[name]
58
+ end
59
+ request.query_parameters[:_display] = SearchParamEncoder.call(display_params)
63
60
  end
64
61
  end
65
62
  end
@@ -95,16 +92,23 @@ module Lookbook
95
92
  def inspector_data
96
93
  return @inspector_data if @inspector_data.present?
97
94
 
98
- rendered_examples = @target.examples.map do |example|
99
- output = preview_controller.process(:render_example_to_string, @preview, example.name)
100
- RenderedExample.new(example, output, preview_controller.params)
95
+ scenarios = @target ? @target.scenarios : []
96
+ rendered_scenarios = scenarios.map do |scenario|
97
+ output = preview_controller.process(:render_scenario_to_string, @preview, scenario.name)
98
+ RenderedScenarioEntity.new(scenario, output, preview_controller.params)
101
99
  end
102
100
 
101
+ target = rendered_scenarios.find { |scenario| scenario.id == @target.id } || @target
102
+
103
103
  @inspector_data ||= Lookbook::Store.new({
104
104
  context: Store.new({params: @params, path: params[:path]}),
105
105
  preview: @preview,
106
- examples: rendered_examples,
107
- target: @target,
106
+ scenarios: rendered_scenarios,
107
+ examples: -> do
108
+ Lookbook.logger.warn("The `examples` panel variable has been renamed to `scenarios`. The `examples` variable will be removed in the next major release.")
109
+ rendered_scenarios
110
+ end,
111
+ target: target,
108
112
  data: Lookbook.data,
109
113
  app: Lookbook
110
114
  })
@@ -114,7 +118,7 @@ module Lookbook
114
118
  locals = if @preview
115
119
  {
116
120
  message: "Example not found",
117
- description: "The '#{@preview.label}' preview does not have an example named '#{path_segments.last}'."
121
+ description: "The '#{@preview.label}' preview does not have an scenario named '#{path_segments.last}'."
118
122
  }
119
123
  else
120
124
  {
@@ -122,7 +126,7 @@ module Lookbook
122
126
  description: "Looked for '#{params[:path]}'.<br>The preview may have been renamed or deleted."
123
127
  }
124
128
  end
125
- render_in_layout "lookbook/404", layout: layout, **locals
129
+ render_in_layout "lookbook/404", layout: layout, **locals, status: 404
126
130
  end
127
131
 
128
132
  def path_segments
@@ -0,0 +1,30 @@
1
+ module Lookbook
2
+ module WithPanelsConcern
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ private
7
+
8
+ def main_panel_names
9
+ Lookbook.config.preview_inspector.main_panels
10
+ end
11
+
12
+ def drawer_panel_names
13
+ Lookbook.config.preview_inspector.drawer_panels
14
+ end
15
+
16
+ def main_panels
17
+ Engine.panels.get_panels(*main_panel_names).map do |config|
18
+ PanelStore.resolve_config(config, inspector_data)
19
+ end
20
+ end
21
+
22
+ def drawer_panels
23
+ panels = Engine.panels.get_panels(*drawer_panel_names)
24
+ panels.select { |config| !config.name.to_s.in?(main_panel_names) }.map do |config|
25
+ PanelStore.resolve_config(config, inspector_data)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -3,11 +3,12 @@ module Lookbook
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  def preview_controller
6
- return @preview_controller if @preview_controller
7
- controller = Lookbook::Engine.preview_controller.new
6
+ return @_preview_controller if @_preview_controller
7
+
8
+ controller = Engine.preview_controller.new
8
9
  controller.request = request
9
10
  controller.response = response
10
- @preview_controller ||= controller
11
+ @_preview_controller ||= controller
11
12
  end
12
13
  end
13
14
  end
@@ -4,9 +4,9 @@ module Lookbook
4
4
 
5
5
  protect_from_forgery with: :exception
6
6
 
7
+ helper Lookbook::ClassNamesHelper if Engine.runtime_context.rails_older_than?("6.1.0")
7
8
  helper Lookbook::ApplicationHelper
8
- helper Lookbook::OutputHelper
9
- helper Lookbook::ComponentHelper
9
+ helper Lookbook::UiElementsHelper
10
10
 
11
11
  before_action :generate_theme_overrides
12
12
  before_action :assign_instance_vars
@@ -16,10 +16,9 @@ module Lookbook
16
16
  end
17
17
 
18
18
  def index
19
- landing = Lookbook.pages.find(&:landing?) || Lookbook.pages.first
20
-
19
+ landing = Engine.pages.find(&:landing?) || Engine.pages.first
21
20
  if landing.present?
22
- redirect_to lookbook_page_path(landing.path)
21
+ redirect_to lookbook_page_path(landing.lookup_path)
23
22
  else
24
23
  render "lookbook/index"
25
24
  end
@@ -28,18 +27,16 @@ module Lookbook
28
27
  protected
29
28
 
30
29
  def generate_theme_overrides
31
- @theme_overrides ||= Lookbook.theme.to_css
30
+ @theme_overrides ||= Engine.theme.to_css
32
31
  end
33
32
 
34
33
  def assign_instance_vars
35
- @previews = Lookbook.previews
36
- @pages = Lookbook.pages
34
+ @previews = Engine.previews
35
+ @pages = Engine.pages
36
+ @theme = Engine.theme
37
37
  @config = Lookbook.config
38
38
  @engine = Lookbook.engine
39
- end
40
-
41
- def feature_enabled?(feature)
42
- Lookbook::Features.enabled?(feature)
39
+ @embed = !!params[:lookbook_embed]
43
40
  end
44
41
 
45
42
  def render_in_layout(path, layout: nil, **locals)
@@ -0,0 +1,148 @@
1
+ module Lookbook
2
+ class EmbedsController < ApplicationController
3
+ include ActionView::Helpers::SanitizeHelper
4
+ include TargetableConcern
5
+ include WithPreviewControllerConcern
6
+
7
+ layout "lookbook/embed"
8
+
9
+ before_action :permit_embeds
10
+ before_action :set_options, only: [:show]
11
+ before_action :set_scenario_choices, only: [:show]
12
+ before_action :set_panels, only: [:show]
13
+ before_action :set_actions, only: [:show]
14
+
15
+ def self.controller_path
16
+ "lookbook/embeds"
17
+ end
18
+
19
+ def lookup
20
+ props = Store.new(params[:props] ? JsonParser.call(sanitize(params[:props])) : {})
21
+ if props.preview.present?
22
+ preview = Engine.previews.find_by_preview_class(props.preview)
23
+ if preview.present?
24
+ props.scenarios ||= (props.scenario || "")
25
+ scenario = preview.scenario(Array(props.scenarios).first)
26
+
27
+ boolean_options = ["display_option_controls"]
28
+ array_options = ["panels", "actions", "scenarios"]
29
+ param_prefix = "param_"
30
+
31
+ options = {}
32
+ embed_params = {}
33
+
34
+ props.each do |key, value|
35
+ key = key.to_s.strip.tr("-", "_")
36
+ value.strip!
37
+
38
+ if array_options.include?(key)
39
+ options[key] = if value == "false"
40
+ []
41
+ elsif value == "true"
42
+ ["*"]
43
+ else
44
+ value.split(",").map(&:strip)
45
+ end
46
+ elsif boolean_options.include?(key)
47
+ options[key] = (value == "false") ? false : !!value
48
+ elsif key.start_with?(param_prefix)
49
+ embed_params[key.gsub(param_prefix, "")] = value
50
+ end
51
+ end
52
+
53
+ embed_params[:_options] = SearchParamEncoder.call(options)
54
+ embed_params.symbolize_keys!
55
+
56
+ return redirect_to lookbook_embed_url(scenario ? scenario.path : preview.path, embed_params)
57
+ end
58
+ end
59
+
60
+ show_404 layout: "lookbook/skeleton"
61
+ end
62
+
63
+ def show
64
+ @embed = true
65
+
66
+ unless @target
67
+ @target = @scenario_choices.first || @preview.default_scenario
68
+ if @target
69
+ redirect_to lookbook_embed_path(@target.path, req_params)
70
+ else
71
+ show_404(layout: "lookbook/skeleton") unless @target
72
+ end
73
+ end
74
+ end
75
+
76
+ protected
77
+
78
+ def embed_options
79
+ Lookbook.config.preview_embeds
80
+ end
81
+
82
+ def permit_embeds
83
+ headers["X-Frame-Options"] = embed_options.policy
84
+ end
85
+
86
+ def lookup_entities
87
+ @target = Engine.previews.find_scenario_by_path(params[:path])
88
+ @preview = @target.present? ? @target.preview : Engine.previews.find_by_path(params[:path])
89
+ end
90
+
91
+ def set_params
92
+ @params = []
93
+ @passed_params = req_params.select { |key, value| !key.to_s.start_with?("_") }
94
+
95
+ if @target
96
+ @params = @target.tags("param").map do |param_tag|
97
+ Param.from_tag(
98
+ param_tag,
99
+ value: @passed_params[param_tag.name.to_sym]
100
+ )
101
+ end
102
+
103
+ # cast known param values to correct type
104
+ @params.each do |param|
105
+ if @passed_params.key?(param.name.to_sym)
106
+ @passed_params[param.name.to_sym] = param.cast_value
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ def set_options
113
+ return @options if @options
114
+
115
+ options = SearchParamParser.call(req_params[:_options])
116
+ default_options = embed_options.to_h.except(:policy)
117
+ @options ||= default_options.merge(options || {})
118
+ end
119
+
120
+ def set_scenario_choices
121
+ return @scenario_choices ||= [] unless @preview
122
+
123
+ named_choices = @options.fetch(:scenarios, [])
124
+ @scenario_choices = ListResolver.call(named_choices, @preview.scenarios.map(&:name)) do |name|
125
+ @preview.scenario(name)
126
+ end
127
+ end
128
+
129
+ def set_actions
130
+ @actions ||= ListResolver.call(@options.fetch(:actions, []), Embed::Component::ACTIONS)
131
+ end
132
+
133
+ def set_panels
134
+ return @panels if @panels
135
+
136
+ panels = @options.fetch(:panels, [])
137
+ all_panels = Engine.panels.names.map(&:to_s) - ["preview"]
138
+ @panels = ListResolver.call(panels, all_panels) do |name|
139
+ config = Engine.panels.get_panel(name.to_sym)
140
+ PanelStore.resolve_config(config, inspector_data) if config
141
+ end
142
+ end
143
+
144
+ def req_params
145
+ request.query_parameters
146
+ end
147
+ end
148
+ end
@@ -1,10 +1,10 @@
1
1
  module Lookbook
2
2
  class InspectorController < ApplicationController
3
3
  include TargetableConcern
4
+ include WithPanelsConcern
4
5
  include WithPreviewControllerConcern
5
6
 
6
- layout "lookbook/inspector"
7
- helper Lookbook::PreviewHelper
7
+ layout "lookbook/application"
8
8
 
9
9
  def self.controller_path
10
10
  "lookbook/inspector"
@@ -16,30 +16,11 @@ module Lookbook
16
16
  @main_panels = main_panels
17
17
  @drawer_panels = drawer_panels
18
18
  rescue => exception
19
- render_in_layout "lookbook/error", layout: "lookbook/inspector", error: prettify_error(exception)
19
+ render_in_layout "lookbook/error", layout: "lookbook/application", error: prettify_error(exception)
20
20
  end
21
21
  else
22
22
  show_404
23
23
  end
24
24
  end
25
-
26
- def show_legacy
27
- Lookbook.logger.warn("Legacy URL path detected. These paths are deprecated and will be removed in a future version")
28
- redirect_to lookbook_inspect_path params[:path]
29
- end
30
-
31
- private
32
-
33
- def main_panels
34
- Engine.panels.in_group(:main).map do |config|
35
- PanelStore.resolve_config(config, inspector_data)
36
- end
37
- end
38
-
39
- def drawer_panels
40
- Engine.panels.in_group(:drawer).map do |config|
41
- PanelStore.resolve_config(config, inspector_data)
42
- end
43
- end
44
25
  end
45
26
  end
@@ -1,8 +1,9 @@
1
+ require "rails/application_controller"
2
+
1
3
  module Lookbook
2
- class PageController < ActionController::Base
3
- helper Lookbook::ComponentHelper
4
- helper Lookbook::PageHelper
5
- helper Lookbook::OutputHelper
4
+ class PageController < Rails::ApplicationController
5
+ helper UiElementsHelper
6
+ helper PageHelper
6
7
 
7
8
  Lookbook.config.page_paths.each do |path|
8
9
  prepend_view_path Rails.root.join(path)
@@ -10,7 +11,7 @@ module Lookbook
10
11
 
11
12
  def render_page(page, locals = {})
12
13
  @page = page
13
- @pages = Lookbook.pages
14
+ @pages = Engine.pages
14
15
  @next_page = @pages.next(@page)
15
16
  @previous_page = @pages.previous(@page)
16
17
 
@@ -23,7 +24,7 @@ module Lookbook
23
24
  }
24
25
  end
25
26
 
26
- @page.markdown? ? MarkdownRenderer.call(content, Lookbook.config.markdown_options) : content
27
+ @page.markdown? ? MarkdownRenderer.call(content) : content
27
28
  end
28
29
  end
29
30
  end
@@ -1,15 +1,14 @@
1
1
  module Lookbook
2
2
  class PagesController < ApplicationController
3
- layout "lookbook/page"
3
+ layout "lookbook/application"
4
4
  helper_method :page_controller
5
- helper Lookbook::PageHelper
6
5
 
7
6
  def self.controller_path
8
7
  "lookbook/pages"
9
8
  end
10
9
 
11
10
  def index
12
- landing = Lookbook.pages.find(&:landing?) || Lookbook.pages.first
11
+ landing = Engine.pages.find(&:landing?) || Engine.pages.first
13
12
  if landing.present?
14
13
  redirect_to lookbook_page_path(landing.path)
15
14
  else
@@ -27,7 +26,7 @@ module Lookbook
27
26
  @title = @page.title
28
27
  rescue => exception
29
28
  render_in_layout "lookbook/error",
30
- layout: "lookbook/page",
29
+ layout: "lookbook/application",
31
30
  error: Lookbook::Error.new(exception, file_path: @page.file_path, source_code: @page.content)
32
31
  end
33
32
  else
@@ -0,0 +1,17 @@
1
+ require "rails/application_controller"
2
+
3
+ module Lookbook
4
+ class PreviewController < Rails::ApplicationController
5
+ content_security_policy(false) if respond_to?(:content_security_policy)
6
+
7
+ private
8
+
9
+ [:determine_layout, :prepend_application_view_paths, :prepend_preview_examples_view_path].each do |method_name|
10
+ define_method method_name, ViewComponentsController.instance_method(method_name)
11
+ end
12
+
13
+ def default_preview_layout
14
+ Lookbook.config.preview_layout
15
+ end
16
+ end
17
+ end
@@ -3,10 +3,7 @@ module Lookbook
3
3
  include TargetableConcern
4
4
  include WithPreviewControllerConcern
5
5
 
6
- before_action { response.headers.delete("X-Frame-Options") }
7
-
8
- layout "lookbook/inspector"
9
- helper Lookbook::PreviewHelper
6
+ layout false
10
7
 
11
8
  def self.controller_path
12
9
  "lookbook/previews"
@@ -19,16 +16,11 @@ module Lookbook
19
16
  json: Lookbook.previews.map do |preview|
20
17
  {
21
18
  name: preview.name,
22
- examples: preview.examples.map { |example|
23
- case example
24
- when Lookbook::PreviewExample
25
- example_json(example)
26
- when Lookbook::PreviewGroup
27
- {
28
- name: example.name,
29
- examples: example.examples.map { |ex| example_json(ex) }
30
- }
31
- end
19
+ scenarios: preview.scenarios.map { |scenario|
20
+ {
21
+ inspect_path: scenario.url_path,
22
+ name: scenario.name
23
+ }
32
24
  }
33
25
  }
34
26
  end
@@ -42,29 +34,17 @@ module Lookbook
42
34
  begin
43
35
  opts = {layout: @preview.layout}
44
36
  if params[:lookbook_embed] == "true"
45
- opts[:append_html] = "<script src=\"/lookbook-assets/js/embed.js?v=#{Lookbook.version}\"></script>".html_safe
37
+ opts[:append_html] = render_to_string("lookbook/partials/_iframe_content_scripts", layout: nil)
46
38
  end
47
- preview_html = preview_controller.process(:render_in_layout_to_string, "lookbook/preview", inspector_data, **opts)
48
- render html: preview_html
39
+ @preview_html = preview_controller.process(:render_in_layout_to_string, "lookbook/previews/group", inspector_data, **opts)
49
40
  rescue => exception
50
41
  render_in_layout "lookbook/error",
51
- layout: "lookbook/standalone",
42
+ layout: "lookbook/skeleton",
52
43
  error: prettify_error(exception)
53
44
  end
54
45
  else
55
- show_404 layout: "lookbook/standalone"
46
+ show_404
56
47
  end
57
48
  end
58
-
59
- private
60
-
61
- def example_json(example)
62
- {
63
- inspect_path: example.url_path,
64
- name: example.name,
65
- preview_path: example.preview_path,
66
- lookup_path: example.lookup_path
67
- }
68
- end
69
49
  end
70
50
  end
@@ -1,33 +1,17 @@
1
1
  module Lookbook
2
2
  module ApplicationHelper
3
- def config
4
- Lookbook::Engine.config.lookbook
5
- end
6
-
7
- def theme
8
- Lookbook.theme
9
- end
10
-
11
- def asset_path(file, version: true)
3
+ def lookbook_asset_path(file, version: true)
12
4
  path = "/lookbook-assets/#{file}".gsub("//", "/")
13
5
  version ? "#{path}?v=#{Lookbook::VERSION}" : path
14
6
  end
15
7
 
16
- def feature_enabled?(name)
17
- Lookbook::Features.enabled?(name)
18
- end
19
-
20
- def landing_path
21
- landing = Lookbook.pages.find(&:landing?) || Lookbook.pages.first
8
+ def lookbook_landing_path
9
+ landing = Engine.pages.find(&:landing?) || Engine.pages.first
22
10
  if landing.present?
23
11
  lookbook_page_path landing.lookup_path
24
12
  else
25
13
  lookbook_home_path
26
14
  end
27
15
  end
28
-
29
- def generate_id(*args)
30
- args.map { |args| args.delete_prefix("/").tr("&?=/_-", "-") }.join("-")
31
- end
32
16
  end
33
17
  end