lookbook 2.0.0.beta.2 → 2.0.0.beta.4

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 (126) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/lookbook/css/fonts.css +33 -0
  3. data/app/assets/lookbook/css/lookbook.css +7 -0
  4. data/app/assets/lookbook/css/themes/blue.css +4 -1
  5. data/app/assets/lookbook/css/themes/green.css +4 -1
  6. data/app/assets/lookbook/css/themes/indigo.css +4 -1
  7. data/app/assets/lookbook/css/themes/rose.css +4 -1
  8. data/app/assets/lookbook/css/themes/zinc.css +4 -1
  9. data/app/assets/lookbook/fonts/Inter-italic.var.woff2 +0 -0
  10. data/app/assets/lookbook/fonts/Inter-roman.var.woff2 +0 -0
  11. data/app/assets/lookbook/fonts/SourceCodeVariable-Italic.ttf.woff2 +0 -0
  12. data/app/assets/lookbook/fonts/SourceCodeVariable-Roman.ttf.woff2 +0 -0
  13. data/app/assets/lookbook/img/lucide-sprite.svg +869 -869
  14. data/app/assets/lookbook/js/lib/lookbook.js +12 -2
  15. data/app/components/lookbook/code/highlight_github.css +16 -17
  16. data/app/components/lookbook/dimensions_display/component.js +4 -7
  17. data/app/components/lookbook/file_source/component.html.erb +9 -0
  18. data/app/components/lookbook/file_source/component.rb +73 -0
  19. data/app/components/lookbook/header/component.html.erb +11 -8
  20. data/app/components/lookbook/icon/component.css +1 -1
  21. data/app/components/lookbook/icon/component.html.erb +1 -1
  22. data/app/components/lookbook/icon/component.rb +4 -1
  23. data/app/components/lookbook/logo/component.html.erb +6 -0
  24. data/app/components/lookbook/logo/component.rb +15 -0
  25. data/app/components/lookbook/message/component.css +33 -0
  26. data/app/components/lookbook/message/component.html.erb +26 -0
  27. data/app/components/lookbook/message/component.rb +13 -0
  28. data/app/components/lookbook/nav/entity/component.html.erb +2 -2
  29. data/app/components/lookbook/nav/entity/component.rb +1 -1
  30. data/app/components/lookbook/page_tabs/component.html.erb +2 -2
  31. data/app/components/lookbook/params/field/component.css +3 -3
  32. data/app/components/lookbook/prose/component.css +8 -1
  33. data/app/components/lookbook/prose/component.html.erb +6 -1
  34. data/app/components/lookbook/prose/component.rb +2 -2
  35. data/app/controllers/concerns/lookbook/targetable_concern.rb +2 -16
  36. data/app/controllers/lookbook/application_controller.rb +38 -14
  37. data/app/controllers/lookbook/embeds_controller.rb +3 -4
  38. data/app/controllers/lookbook/inspector_controller.rb +4 -12
  39. data/app/controllers/lookbook/pages_controller.rb +15 -27
  40. data/app/controllers/lookbook/preview_controller.rb +30 -2
  41. data/app/controllers/lookbook/previews_controller.rb +13 -15
  42. data/app/views/layouts/lookbook/application.html.erb +1 -0
  43. data/app/views/layouts/lookbook/skeleton.html.erb +2 -2
  44. data/app/views/lookbook/errors/default.html.erb +40 -0
  45. data/app/views/lookbook/errors/not_found.html.erb +10 -0
  46. data/app/views/lookbook/index.html.erb +29 -24
  47. data/app/views/lookbook/pages/show.html.erb +9 -8
  48. data/app/views/lookbook/partials/_blank_slate.html.erb +7 -0
  49. data/config/app.yml +8 -0
  50. data/config/routes.rb +2 -0
  51. data/lib/lookbook/engine.rb +12 -5
  52. data/lib/lookbook/entities/concerns/annotatable_entity.rb +26 -1
  53. data/lib/lookbook/entities/concerns/inspectable_entity.rb +17 -2
  54. data/lib/lookbook/entities/concerns/locatable_entity.rb +51 -7
  55. data/lib/lookbook/entities/concerns/navigable_entity.rb +14 -1
  56. data/lib/lookbook/entities/entity.rb +34 -12
  57. data/lib/lookbook/entities/page_entity.rb +68 -10
  58. data/lib/lookbook/entities/page_section_entity.rb +4 -0
  59. data/lib/lookbook/entities/preview_entity.rb +107 -17
  60. data/lib/lookbook/entities/renderable_entity.rb +47 -9
  61. data/lib/lookbook/entities/rendered_scenario_entity.rb +17 -6
  62. data/lib/lookbook/entities/scenario_entity.rb +77 -16
  63. data/lib/lookbook/entities/scenario_group_entity.rb +82 -9
  64. data/lib/lookbook/helpers/page_helper.rb +26 -1
  65. data/lib/lookbook/helpers/ui_elements_helper.rb +0 -24
  66. data/lib/lookbook/param.rb +1 -1
  67. data/lib/lookbook/services/markdown_renderer.rb +2 -4
  68. data/lib/lookbook/stores/config_store.rb +0 -12
  69. data/lib/lookbook/support/errors/config_error.rb +1 -1
  70. data/lib/lookbook/support/errors/error.rb +64 -0
  71. data/lib/lookbook/support/errors/parser_error.rb +1 -1
  72. data/lib/lookbook/support/errors/preview_template_error.rb +1 -1
  73. data/lib/lookbook/support/errors/routing_error.rb +7 -0
  74. data/lib/lookbook/support/errors/template_error.rb +7 -0
  75. data/lib/lookbook/version.rb +1 -1
  76. data/public/lookbook-assets/Inter-italic.var.69eb0fe1.woff2 +0 -0
  77. data/public/lookbook-assets/Inter-italic.var.736a7044.woff2 +0 -0
  78. data/public/lookbook-assets/Inter-roman.var.b695afbe.woff2 +0 -0
  79. data/public/lookbook-assets/Inter-roman.var.fbdd51d0.woff2 +0 -0
  80. data/public/lookbook-assets/SourceCodeVariable-Italic.cad97b83.otf +0 -0
  81. data/public/lookbook-assets/SourceCodeVariable-Italic.ttf.09b4354a.woff2 +0 -0
  82. data/public/lookbook-assets/SourceCodeVariable-Italic.ttf.fcd7e9f4.woff2 +0 -0
  83. data/public/lookbook-assets/SourceCodeVariable-Roman.185ddb17.otf +0 -0
  84. data/public/lookbook-assets/SourceCodeVariable-Roman.ttf.118e9f22.woff2 +0 -0
  85. data/public/lookbook-assets/SourceCodeVariable-Roman.ttf.91043609.woff2 +0 -0
  86. data/public/lookbook-assets/css/lookbook.css +417 -58
  87. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  88. data/public/lookbook-assets/css/themes/blue.css +4 -1
  89. data/public/lookbook-assets/css/themes/blue.css.map +1 -1
  90. data/public/lookbook-assets/css/themes/green.css +4 -1
  91. data/public/lookbook-assets/css/themes/green.css.map +1 -1
  92. data/public/lookbook-assets/css/themes/indigo.css +4 -1
  93. data/public/lookbook-assets/css/themes/indigo.css.map +1 -1
  94. data/public/lookbook-assets/css/themes/rose.css +4 -1
  95. data/public/lookbook-assets/css/themes/rose.css.map +1 -1
  96. data/public/lookbook-assets/css/themes/zinc.css +4 -1
  97. data/public/lookbook-assets/css/themes/zinc.css.map +1 -1
  98. data/public/lookbook-assets/img/lucide-sprite.svg +869 -869
  99. data/public/lookbook-assets/js/index.js +173 -173
  100. data/public/lookbook-assets/js/index.js.map +1 -1
  101. data/public/lookbook-assets/js/lookbook-core.js +4 -2
  102. data/public/lookbook-assets/js/lookbook.js +4 -2
  103. metadata +31 -26
  104. data/app/views/layouts/lookbook/shell.html.erb +0 -25
  105. data/app/views/lookbook/404.html.erb +0 -15
  106. data/app/views/lookbook/error.html.erb +0 -46
  107. data/lib/lookbook/error.rb +0 -120
  108. data/lib/lookbook/support/errors/lookbook_error.rb +0 -21
  109. data/lib/tasks/lookbook_tasks.rake +0 -10
  110. data/public/lookbook-assets/css/app.css +0 -2341
  111. data/public/lookbook-assets/css/app.css.map +0 -11
  112. data/public/lookbook-assets/css/themes/zinc.css.map.91837.5 +0 -1
  113. data/public/lookbook-assets/feather-sprite.svg +0 -1
  114. data/public/lookbook-assets/js/app.js +0 -10862
  115. data/public/lookbook-assets/js/app.js.map +0 -2571
  116. data/public/lookbook-assets/js/embed.js +0 -1427
  117. data/public/lookbook-assets/js/embed.js.91837.6 +0 -0
  118. data/public/lookbook-assets/js/embed.js.map +0 -1
  119. data/public/lookbook-assets/js/lookbook-core.js.map +0 -1
  120. data/public/lookbook-assets/js/lookbook.js.map +0 -1
  121. data/public/lookbook-assets/lookbook-esm.js +0 -1427
  122. data/public/lookbook-assets/lookbook-esm.js.map +0 -1
  123. data/public/lookbook-assets/lookbook-global.js +0 -1427
  124. data/public/lookbook-assets/lookbook-global.js.map +0 -1
  125. data/public/lookbook-assets/lookbook.js +0 -1427
  126. data/public/lookbook-assets/lookbook.js.map +0 -1
@@ -57,18 +57,17 @@ module Lookbook
57
57
  end
58
58
  end
59
59
 
60
- show_404 layout: "lookbook/skeleton"
60
+ raise_not_found("Preview not found")
61
61
  end
62
62
 
63
63
  def show
64
64
  @embed = true
65
-
66
65
  unless @target
67
- @target = @scenario_choices.first || @preview.default_scenario
66
+ @target = @scenario_choices.first || @preview&.default_scenario
68
67
  if @target
69
68
  redirect_to lookbook_embed_path(@target.path, req_params)
70
69
  else
71
- show_404(layout: "lookbook/skeleton") unless @target
70
+ raise_not_found("Preview not found")
72
71
  end
73
72
  end
74
73
  end
@@ -4,23 +4,15 @@ module Lookbook
4
4
  include WithPanelsConcern
5
5
  include WithPreviewControllerConcern
6
6
 
7
- layout "lookbook/application"
8
-
9
7
  def self.controller_path
10
8
  "lookbook/inspector"
11
9
  end
12
10
 
13
11
  def show
14
- if @target
15
- begin
16
- @main_panels = main_panels
17
- @drawer_panels = drawer_panels
18
- rescue => exception
19
- render_in_layout "lookbook/error", layout: "lookbook/application", error: prettify_error(exception)
20
- end
21
- else
22
- show_404
23
- end
12
+ raise_not_found("Preview not found") unless @target
13
+
14
+ @main_panels = main_panels
15
+ @drawer_panels = drawer_panels
24
16
  end
25
17
  end
26
18
  end
@@ -1,6 +1,5 @@
1
1
  module Lookbook
2
2
  class PagesController < ApplicationController
3
- layout "lookbook/application"
4
3
  helper_method :page_controller
5
4
 
6
5
  def self.controller_path
@@ -9,40 +8,29 @@ module Lookbook
9
8
 
10
9
  def index
11
10
  landing = Engine.pages.find(&:landing?) || Engine.pages.first
12
- if landing.present?
13
- redirect_to lookbook_page_path(landing.path)
14
- else
15
- show_404
16
- end
11
+ raise_not_found("Page not found") unless landing.present?
12
+
13
+ redirect_to lookbook_page_path(landing.path)
17
14
  end
18
15
 
19
16
  def show
20
17
  @page = @pages.find_by_path(params[:path])
21
- if @page
22
- @next_page = @pages.next(@page)
23
- @previous_page = @pages.previous(@page)
24
- begin
25
- @page_content = page_controller.render_page(@page)
26
- @title = @page.title
27
- rescue => exception
28
- render_in_layout "lookbook/error",
29
- layout: "lookbook/application",
30
- error: Lookbook::Error.new(exception, file_path: @page.file_path, source_code: @page.content)
31
- end
32
- else
33
- show_404
34
- end
18
+ raise_not_found("Page not found") unless @page
19
+
20
+ @page_content = page_controller.render_page(@page)
21
+ @title = @page.title
22
+ @next_page = @pages.next(@page)
23
+ @previous_page = @pages.previous(@page)
24
+ rescue ActionView::Template::Error => err
25
+ raise Lookbook::TemplateError.new(
26
+ original: err,
27
+ file_path: @page.file_path,
28
+ source: @page.content
29
+ )
35
30
  end
36
31
 
37
32
  protected
38
33
 
39
- def show_404
40
- render "lookbook/404", locals: {
41
- message: "Page not found",
42
- description: "The page may have been removed or renamed."
43
- }
44
- end
45
-
46
34
  def page_controller
47
35
  controller_class = Lookbook.config.page_controller.constantize
48
36
  controller = controller_class.new
@@ -6,12 +6,40 @@ module Lookbook
6
6
 
7
7
  private
8
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)
9
+ def set_locale(&block)
10
+ I18n.with_locale(params[:locale] || I18n.default_locale, &block)
11
+ end
12
+
13
+ # Returns either {} or {layout: value} depending on configuration
14
+ def determine_layout(layout_override = nil, prepend_views: true)
15
+ return {} unless defined?(Rails.root)
16
+
17
+ layout_declaration = {}
18
+
19
+ if !layout_override.nil?
20
+ # Allow component-level override, even if false (thus no layout rendered)
21
+ layout_declaration[:layout] = layout_override
22
+ elsif default_preview_layout.present?
23
+ layout_declaration[:layout] = default_preview_layout
24
+ end
25
+
26
+ prepend_application_view_paths if layout_declaration[:layout].present? && prepend_views
27
+
28
+ layout_declaration
11
29
  end
12
30
 
13
31
  def default_preview_layout
14
32
  Lookbook.config.preview_layout
15
33
  end
34
+
35
+ def prepend_application_view_paths
36
+ prepend_view_path Rails.root.join("app/views") if defined?(Rails.root)
37
+ end
38
+
39
+ def prepend_preview_scenarios_view_path
40
+ prepend_view_path(Engine.preview_paths)
41
+ end
42
+
43
+ alias_method :prepend_preview_examples_view_path, :prepend_preview_scenarios_view_path
16
44
  end
17
45
  end
@@ -37,21 +37,15 @@ module Lookbook
37
37
  end
38
38
 
39
39
  def show
40
- if @target
41
- begin
42
- opts = {layout: @preview.layout}
43
- if embedded?
44
- opts[:append_html] = render_to_string("lookbook/partials/_iframe_content_scripts", layout: nil)
45
- end
46
- @preview_html = preview_controller.process(:render_in_layout_to_string, "lookbook/previews/group", inspector_data, **opts)
47
- rescue => exception
48
- render_in_layout "lookbook/error",
49
- layout: "lookbook/skeleton",
50
- error: prettify_error(exception)
51
- end
52
- else
53
- show_404
54
- end
40
+ raise_not_found("Preview not found") unless @target
41
+
42
+ @preview_html = preview_controller.process(
43
+ :render_in_layout_to_string,
44
+ "lookbook/previews/group",
45
+ inspector_data,
46
+ layout: @preview.layout,
47
+ append_html: (iframe_content_scripts if embedded?)
48
+ )
55
49
  end
56
50
 
57
51
  private
@@ -60,6 +54,10 @@ module Lookbook
60
54
  params[:lookbook_embed] == "true"
61
55
  end
62
56
 
57
+ def iframe_content_scripts
58
+ render_to_string("lookbook/partials/_iframe_content_scripts", layout: nil)
59
+ end
60
+
63
61
  def scenario_json(scenario)
64
62
  {
65
63
  name: scenario.name,
@@ -6,6 +6,7 @@
6
6
  @popstate.window="handleNavigation"
7
7
  @click.document="hijax"
8
8
  @navigation:start="closeMobileSidebar"
9
+ @dom:update-complete.window="Lookbook.initEmbeds()"
9
10
  class="w-screen h-screen grid grid-rows-[40px_1fr] relative">
10
11
 
11
12
  <%= render "lookbook/partials/user_styles" %>
@@ -17,11 +17,11 @@
17
17
  <% if @config.ui_favicon == true %>
18
18
  <link
19
19
  rel="icon"
20
- href="data:image/svg+xml,%3Csvg width='96' height='84' viewBox='0 0 96 84' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3CclipPath id='a'%3E%3Cpath d='M96 0v84H0V0h96Z'/%3E%3C/clipPath%3E%3CclipPath id='b'%3E%3Cpath d='M71.897 0a1.5 1.5 0 0 1 1.31.769l22.605 40.5a1.5 1.5 0 0 1 0 1.462l-22.605 40.5a1.5 1.5 0 0 1-1.31.769H49.481a1 1 0 0 1-.873-1.487L70.812 42.73a1.5 1.5 0 0 0 0-1.462L48.608 1.487A1 1 0 0 1 49.481 0ZM24.655.564l22.72 40.705a1.5 1.5 0 0 1 0 1.462l-22.72 40.705a1 1 0 0 1-1.746 0L.19 42.73a1.5 1.5 0 0 1 0-1.462L22.91.564a1 1 0 0 1 1.746 0Z'/%3E%3C/clipPath%3E%3C/defs%3E%3Cg clip-path='url(%23a)'%3E%3Cg clip-path='url(%23b)'%3E%3Cpath fill='<%= url_encode @theme.favicon_dark_mode %>' d='M0 0h96v84H0V0z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"
20
+ href="data:image/svg+xml,%3Csvg viewBox='0 0 167 204' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23FFF' fill-rule='nonzero'%3E%3Cpath d='M157 0c5.523 0 10 4.477 10 10v184c0 5.523-4.477 10-10 10H32.969C17 204 3.687 192.638.65 177.554A9.97 9.97 0 0 1 0 174c0-.512.011-1.017.033-1.516A33.115 33.115 0 0 1 0 171V33C0 14.778 14.758 0 32.969 0H157Zm-10 166H32.969c-8.292 0-12.22 2.22-12.871 6.606.79 6.424 6.253 11.394 12.87 11.394H147v-18Zm0-146H32.969c-7.056 0-12.8 5.65-12.965 12.689L20 33v114.762c3.932-1.167 8.3-1.762 12.969-1.762H147V20Z'/%3E%3Cpath d='M64.022 126c-4.107 0-7.304-1.143-9.591-3.428-2.287-2.285-3.431-5.48-3.431-9.583l.14-63.978c0-4.197 1.12-7.415 3.36-9.653C56.74 37.119 59.916 36 64.023 36c4.2 0 7.398 1.12 9.592 3.358 2.193 2.238 3.29 5.456 3.29 9.653l-.14 55.584h34.166c3.547 0 6.277.91 8.19 2.728 1.915 1.819 2.871 4.454 2.871 7.905 0 3.45-.956 6.109-2.87 7.974-1.914 1.865-4.644 2.798-8.191 2.798H64.022Z'/%3E%3C/g%3E%3C/svg%3E"
21
21
  media="(prefers-color-scheme: dark)">
22
22
  <link
23
23
  rel="icon"
24
- href="data:image/svg+xml,%3Csvg width='96' height='84' viewBox='0 0 96 84' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3CclipPath id='a'%3E%3Cpath d='M96 0v84H0V0h96Z'/%3E%3C/clipPath%3E%3CclipPath id='b'%3E%3Cpath d='M71.897 0a1.5 1.5 0 0 1 1.31.769l22.605 40.5a1.5 1.5 0 0 1 0 1.462l-22.605 40.5a1.5 1.5 0 0 1-1.31.769H49.481a1 1 0 0 1-.873-1.487L70.812 42.73a1.5 1.5 0 0 0 0-1.462L48.608 1.487A1 1 0 0 1 49.481 0ZM24.655.564l22.72 40.705a1.5 1.5 0 0 1 0 1.462l-22.72 40.705a1 1 0 0 1-1.746 0L.19 42.73a1.5 1.5 0 0 1 0-1.462L22.91.564a1 1 0 0 1 1.746 0Z'/%3E%3C/clipPath%3E%3C/defs%3E%3Cg clip-path='url(%23a)'%3E%3Cg clip-path='url(%23b)'%3E%3Cpath fill='<%= url_encode @theme.favicon_light_mode %>' d='M0 0h96v84H0V0z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"
24
+ href="data:image/svg+xml,%3Csvg viewBox='0 0 167 204' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%233730A3' fill-rule='nonzero'%3E%3Cpath d='M157 0c5.523 0 10 4.477 10 10v184c0 5.523-4.477 10-10 10H32.969C17 204 3.687 192.638.65 177.554A9.97 9.97 0 0 1 0 174c0-.512.011-1.017.033-1.516A33.115 33.115 0 0 1 0 171V33C0 14.778 14.758 0 32.969 0H157Zm-10 166H32.969c-8.292 0-12.22 2.22-12.871 6.606.79 6.424 6.253 11.394 12.87 11.394H147v-18Zm0-146H32.969c-7.056 0-12.8 5.65-12.965 12.689L20 33v114.762c3.932-1.167 8.3-1.762 12.969-1.762H147V20Z'/%3E%3Cpath d='M64.022 126c-4.107 0-7.304-1.143-9.591-3.428-2.287-2.285-3.431-5.48-3.431-9.583l.14-63.978c0-4.197 1.12-7.415 3.36-9.653C56.74 37.119 59.916 36 64.023 36c4.2 0 7.398 1.12 9.592 3.358 2.193 2.238 3.29 5.456 3.29 9.653l-.14 55.584h34.166c3.547 0 6.277.91 8.19 2.728 1.915 1.819 2.871 4.454 2.871 7.905 0 3.45-.956 6.109-2.87 7.974-1.914 1.865-4.644 2.798-8.191 2.798H64.022Z'/%3E%3C/g%3E%3C/svg%3E"
25
25
  media="(prefers-color-scheme: light)">
26
26
  <% end %>
27
27
 
@@ -0,0 +1,40 @@
1
+ <div class="bg-red-50 h-[calc(100vh_-_40px)] w-full overflow-y-auto">
2
+ <div>
3
+ <header class="px-8 py-6">
4
+ <h2 class="text-xl font-bold text-red-700"><%= @error.type %></h2>
5
+ </header>
6
+
7
+ <div class="px-8 py-6 mb-8 border-t border-b border-red-200 bg-red-100 text-base leading-relaxed">
8
+ <pre class="whitespace-pre-wrap font-sans leading-tight text-red-900"><%= @error.message %></pre>
9
+ </div>
10
+
11
+ <% if @error.file_path %>
12
+ <div class="text-sm mx-8 mb-3 font-mono">
13
+ <span><%= @error.relative_file_path %></span>
14
+ <% if @error.line_number %>
15
+ <span>[line <strong><%= @error.line_number %></strong>]</span>
16
+ <% end %>
17
+ </div>
18
+
19
+ <div class="px-8">
20
+ <%= lookbook_render :file_source,
21
+ file_path: @error.file_path,
22
+ highlight_lines: [@error.line_number],
23
+ lines_around_highlight: 5,
24
+ source: @error.source,
25
+ class: "border border-red-200" %>
26
+ </div>
27
+ <% end %>
28
+
29
+ <h3 class="font-bold mb-2 px-8 py-2 mt-8">Full stack trace:</h3>
30
+ <div class="text-xs font-mono w-full overflow-auto">
31
+ <div class="px-8 pb-10 text-gray-400 leading-relaxed whitespace-nowrap">
32
+ <% @error.backtrace.each do |line| %>
33
+ <div class="hover:text-gray-900 transition-colors duration-100">
34
+ <%= line %>
35
+ </div>
36
+ <% end %>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </div>
@@ -0,0 +1,10 @@
1
+ <%= render "lookbook/partials/blank_slate" do %>
2
+ <%= lookbook_render :message,
3
+ id: "not-found-message",
4
+ title: @error.message,
5
+ icon: :file_x,
6
+ icon_position: :right,
7
+ theme: :error do %>
8
+ <%= @error.detail || "It may have been moved or deleted." %>
9
+ <% end %>
10
+ <% end %>
@@ -1,25 +1,30 @@
1
- <div id="landing" class="flex flex-col items-center justify-center h-full w-full">
2
- <div class="text-center" id="landing-<%= @previews.any? ? "with" : "no" %>-content">
3
- <% if @config.project_name.downcase == "lookbook" %>
4
- <div class="flex justify-center pb-4">
5
- <svg class="flex-none mx-auto w-[140px]" viewBox="0 0 275 36">
6
- <g fill-rule="nonzero" fill="none">
7
- <path d="M4.536 35c-1.408 0-2.504-.392-3.288-1.176-.784-.784-1.176-1.88-1.176-3.288V5.576c0-1.44.384-2.544 1.152-3.312.768-.768 1.856-1.152 3.264-1.152 1.44 0 2.536.384 3.288 1.152.752.768 1.128 1.872 1.128 3.312v22.08h11.712c1.216 0 2.152.312 2.808.936.656.624.984 1.528.984 2.712 0 1.184-.328 2.096-.984 2.736-.656.64-1.592.96-2.808.96H4.536ZM42.066.632c3.425 0 6.425.72 9 2.16 2.577 1.44 4.585 3.464 6.025 6.072 1.44 2.608 2.16 5.672 2.16 9.192 0 2.624-.408 5.008-1.224 7.152-.816 2.144-1.984 3.992-3.504 5.544-1.52 1.552-3.336 2.736-5.448 3.552-2.112.816-4.448 1.224-7.008 1.224-3.424 0-6.432-.728-9.024-2.184-2.592-1.456-4.6-3.496-6.024-6.12-1.424-2.624-2.136-5.68-2.136-9.168 0-2.624.408-5.008 1.224-7.152.816-2.144 1.984-3.984 3.504-5.52 1.52-1.536 3.336-2.712 5.448-3.528C37.17 1.04 39.507.632 42.067.632Zm0 7.392c-1.663 0-3.095.392-4.295 1.176-1.2.784-2.12 1.92-2.76 3.408-.64 1.488-.96 3.304-.96 5.448 0 3.168.704 5.64 2.112 7.416 1.408 1.776 3.376 2.664 5.904 2.664 1.696 0 3.136-.4 4.32-1.2 1.07-.723 1.917-1.733 2.543-3.031-.39-1.314-.934-2.855-2.087-5.286-.07-.147-.07-.233 0-.38l2.187-5.84a8.262 8.262 0 0 0-1.06-1.735c-1.407-1.76-3.375-2.64-5.903-2.64ZM80.27.632c3.424 0 6.424.72 9 2.16 2.576 1.44 4.584 3.464 6.024 6.072 1.44 2.608 2.16 5.672 2.16 9.192 0 2.624-.408 5.008-1.224 7.152-.816 2.144-1.984 3.992-3.504 5.544-1.52 1.552-3.336 2.736-5.448 3.552-2.112.816-4.448 1.224-7.008 1.224-3.424 0-6.432-.728-9.024-2.184-2.592-1.456-4.6-3.496-6.024-6.12-1.424-2.624-2.136-5.68-2.136-9.168 0-2.624.408-5.008 1.224-7.152.816-2.144 1.984-3.984 3.504-5.52 1.52-1.536 3.336-2.712 5.448-3.528C75.373 1.04 77.71.632 80.27.632Zm0 7.392c-1.664 0-3.096.392-4.296 1.176-1.2.784-2.12 1.92-2.76 3.408-.64 1.488-.96 3.304-.96 5.448 0 3.168.704 5.64 2.112 7.416 1.408 1.776 3.376 2.664 5.904 2.664 1.696 0 3.136-.4 4.32-1.2.999-.675 1.804-1.6 2.416-2.775-.395-1.37-.933-2.95-2.162-5.542-.07-.147-.07-.233 0-.38l2.276-6.08a8.166 8.166 0 0 0-.946-1.495c-1.408-1.76-3.376-2.64-5.904-2.64Zm26.299 27.408c-1.408 0-2.496-.392-3.264-1.176-.768-.784-1.152-1.88-1.152-3.288V5.192c0-1.472.384-2.584 1.152-3.336.768-.752 1.856-1.128 3.264-1.128 1.44 0 2.536.376 3.288 1.128.752.752 1.128 1.864 1.128 3.336v10.464h.096l11.664-12.864a7.705 7.705 0 0 1 1.944-1.512c.688-.368 1.464-.552 2.328-.552 1.344 0 2.312.344 2.904 1.032.592.688.864 1.488.816 2.4-.048.912-.424 1.752-1.128 2.52l-11.616 12.336v-3.6l12.192 13.776c.832.928 1.248 1.88 1.248 2.856s-.328 1.784-.984 2.424c-.656.64-1.624.96-2.904.96-1.088 0-1.96-.216-2.616-.648-.656-.432-1.368-1.08-2.136-1.944L111.08 19.736h-.096v11.232c0 1.408-.368 2.504-1.104 3.288-.736.784-1.84 1.176-3.312 1.176Z" fill="#919191"/>
8
- <path d="M140.403 35c-1.504 0-2.648-.392-3.432-1.176-.784-.784-1.176-1.912-1.176-3.384V5.72c0-1.472.392-2.6 1.176-3.384.784-.784 1.928-1.176 3.432-1.176h11.712c2.432 0 4.504.36 6.216 1.08 1.712.72 3.016 1.736 3.912 3.048.896 1.312 1.344 2.848 1.344 4.608 0 1.984-.568 3.68-1.704 5.088-1.136 1.408-2.68 2.368-4.632 2.88v-.768c2.304.416 4.088 1.344 5.352 2.784 1.264 1.44 1.896 3.28 1.896 5.52 0 2.976-1.064 5.32-3.192 7.032-2.128 1.712-5.032 2.568-8.712 2.568h-12.192Zm3.84-6.48h7.152c1.632 0 2.824-.312 3.576-.936.752-.624 1.128-1.56 1.128-2.808 0-1.248-.376-2.176-1.128-2.784-.752-.608-1.944-.912-3.576-.912h-7.152v7.44Zm0-13.92h6.288c1.6 0 2.776-.288 3.528-.864.752-.576 1.128-1.456 1.128-2.64 0-1.184-.376-2.056-1.128-2.616-.752-.56-1.928-.84-3.528-.84h-6.288v6.96Zm41.034 20.928c-3.424 0-6.432-.728-9.024-2.184-2.592-1.456-4.6-3.496-6.024-6.12-1.424-2.624-2.136-5.68-2.136-9.168 0-2.624.408-5.008 1.224-7.152.816-2.144 1.984-3.984 3.504-5.52 1.52-1.536 3.336-2.712 5.448-3.528 2.112-.816 4.448-1.224 7.008-1.224 3.424 0 6.424.72 9 2.16 2.576 1.44 4.584 3.464 6.024 6.072 1.44 2.608 2.16 5.672 2.16 9.192 0 2.624-.408 5.008-1.224 7.152-.816 2.144-1.984 3.992-3.504 5.544-1.52 1.552-3.336 2.736-5.448 3.552-2.112.816-4.448 1.224-7.008 1.224Zm0-7.392c1.696 0 3.136-.4 4.32-1.2 1.184-.8 2.096-1.952 2.736-3.456.64-1.504.96-3.312.96-5.424 0-3.168-.704-5.632-2.112-7.392-1.408-1.76-3.376-2.64-5.904-2.64-1.664 0-3.096.392-4.296 1.176-1.2.784-2.12 1.92-2.76 3.408-.64 1.488-.96 3.304-.96 5.448 0 3.168.704 5.64 2.112 7.416 1.408 1.776 3.376 2.664 5.904 2.664Zm38.203 7.392c-3.424 0-6.432-.728-9.024-2.184-2.592-1.456-4.6-3.496-6.024-6.12-1.424-2.624-2.136-5.68-2.136-9.168 0-2.624.408-5.008 1.224-7.152.816-2.144 1.984-3.984 3.504-5.52 1.52-1.536 3.336-2.712 5.448-3.528 2.112-.816 4.448-1.224 7.008-1.224 3.424 0 6.424.72 9 2.16 2.576 1.44 4.584 3.464 6.024 6.072 1.44 2.608 2.16 5.672 2.16 9.192 0 2.624-.408 5.008-1.224 7.152-.816 2.144-1.984 3.992-3.504 5.544-1.52 1.552-3.336 2.736-5.448 3.552-2.112.816-4.448 1.224-7.008 1.224Zm0-7.392c1.696 0 3.136-.4 4.32-1.2 1.184-.8 2.096-1.952 2.736-3.456.64-1.504.96-3.312.96-5.424 0-3.168-.704-5.632-2.112-7.392-1.408-1.76-3.376-2.64-5.904-2.64-1.664 0-3.096.392-4.296 1.176-1.2.784-2.12 1.92-2.76 3.408-.64 1.488-.96 3.304-.96 5.448 0 3.168.704 5.64 2.112 7.416 1.408 1.776 3.376 2.664 5.904 2.664Zm26.299 7.296c-1.408 0-2.496-.392-3.264-1.176-.768-.784-1.152-1.88-1.152-3.288V5.192c0-1.472.384-2.584 1.152-3.336.768-.752 1.856-1.128 3.264-1.128 1.44 0 2.536.376 3.288 1.128.752.752 1.128 1.864 1.128 3.336v10.464h.096l11.664-12.864a7.705 7.705 0 0 1 1.944-1.512c.688-.368 1.464-.552 2.328-.552 1.344 0 2.312.344 2.904 1.032.592.688.864 1.488.816 2.4-.048.912-.424 1.752-1.128 2.52l-11.616 12.336v-3.6l12.192 13.776c.832.928 1.248 1.88 1.248 2.856s-.328 1.784-.984 2.424c-.656.64-1.624.96-2.904.96-1.088 0-1.96-.216-2.616-.648-.656-.432-1.368-1.08-2.136-1.944L254.29 19.736h-.096v11.232c0 1.408-.368 2.504-1.104 3.288-.736.784-1.84 1.176-3.312 1.176Z" fill="#ABABAB"/>
9
- </g>
10
- </svg>
11
- </div>
12
- <% elsif @config.project_name != false %>
13
- <h5 class="text-base text-lookbook-blank-slate-title truncate uppercase font-black tracking-wide mb-2">
14
- <%= @config.project_name %>
15
- </h5>
1
+ <%= render "lookbook/partials/blank_slate" do %>
2
+ <% if @blank_slate %>
3
+ <%= lookbook_render :message,
4
+ id: "welcome-message",
5
+ title: "Welcome to your Lookbook!",
6
+ icon: :logo do %>
7
+ <p>
8
+ There isn't much to see yet, but
9
+ <%= link_to "component previews",
10
+ "#{@config.links.docs}/guide/previews",
11
+ target: "_blank"
12
+ %>
13
+ and
14
+ <%= link_to "content pages",
15
+ "#{@config.links.docs}/guide/pages",
16
+ target: "_blank"
17
+ %>
18
+ will show up here as soon as they are added.
19
+ </p>
20
+ <% end %>
21
+ <% else %>
22
+ <%= lookbook_render :message,
23
+ id: "get-started-message",
24
+ title: @config.project_name,
25
+ icon: :inspect,
26
+ icon_position: :right do %>
27
+ <p>Select a preview from the nav to get started.</p>
28
+ <% end %>
16
29
  <% end %>
17
- <div class="opacity-60">
18
- <% if @previews.any? %>
19
- <p>Select a preview from the nav to get started.</p>
20
- <% else %>
21
- <p><a class="underline" href="https://lookbook.build/guide/previews" target="_blank">Create a preview</a> to get started.</p>
22
- <% end %>
23
- </div>
24
- </div>
25
- </div>
30
+ <% end %>
@@ -1,15 +1,14 @@
1
1
  <main
2
2
  class="h-[calc(100vh_-_40px)]"
3
3
  x-data="{}"
4
- @navigation:complete.window="$refs.scroller.scrollTop = 0;"
5
- @dom:update-complete.window="Lookbook.initEmbeds();">
4
+ @navigation:complete.window="$refs.scroller.scrollTop = 0">
6
5
  <div class="h-full bg-lookbook-page-bg relative">
7
6
  <% unless @error %>
8
-
7
+
9
8
  <div class="absolute top-0 right-0 pt-1 pr-0 pl-1 pb-1 rounded-bl-md">
10
9
  <div class="bg-lookbook-page-bg opacity-90 absolute inset-0 w-full h-full z-0"></div>
11
10
  <div class="relative z-10 flex items-center">
12
-
11
+
13
12
  <% if @previous_page %>
14
13
  <%= lookbook_render :icon_button,
15
14
  size: :lg,
@@ -46,19 +45,21 @@
46
45
  <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
46
  <div class="w-full max-w-screen-lg mx-auto h-full flex flex-col">
48
47
  <% if @page.header? %>
49
- <header id="page-header" class="mb-8 prose max-w-none flex-none">
50
- <h1><%= @page.title %></h1>
48
+ <header id="page-header" class="mb-7 pb-6 lg:mb-9 lg:pb-8 border-b border-lookbook-divider">
49
+ <%= lookbook_render :prose, size: :md, markdown: false, class: "max-w-none flex-none" do %>
50
+ <h1><%= @page.title %></h1>
51
+ <% end %>
51
52
  </header>
52
53
  <% end %>
53
54
 
54
- <%= lookbook_render :prose, id: "page-content", markdown: false, class: "max-w-none flex-none" do %>
55
+ <%= lookbook_render :prose, size: :md, id: "page-content", markdown: false, class: "max-w-none flex-none min-h-[50vh]" do %>
55
56
  <%= @page_content %>
56
57
  <% end %>
57
58
 
58
59
  <% if @page.sections.any? %>
59
60
  <%= lookbook_render :page_tabs, id: "page-tabbed-sections", markdown: false, class: "mt-6" do |page_tabs| %>
60
61
  <% @page.sections.each do |section| %>
61
- <% page_tabs.tab name: "page-section-#{section.name}", label: section.label do %>
62
+ <% page_tabs.with_tab name: "page-section-#{section.name}", label: section.label do %>
62
63
  <%= page_controller.render_page(section) %>
63
64
  <% end %>
64
65
  <% end %>
@@ -0,0 +1,7 @@
1
+ <div class="flex justify-center w-full h-full bg-checked">
2
+ <div class="px-4 py-6 xs:py-8 sm:p-8 md:p-12">
3
+ <div class="w-full xs:w-auto xs:mx-auto xs:min-w-[440px] xs:max-w-[680px]">
4
+ <%= yield %>
5
+ </div>
6
+ </div>
7
+ </div>
data/config/app.yml CHANGED
@@ -42,6 +42,7 @@ shared:
42
42
  component_paths: [app/views]
43
43
 
44
44
  reload_on_change: ~
45
+ live_updates: false
45
46
  listen_paths: []
46
47
  listen_extensions: [rb, html.*]
47
48
 
@@ -55,8 +56,15 @@ shared:
55
56
  debug_menu: false
56
57
  experimental_features: false
57
58
 
59
+ links:
60
+ docs: https://v2.lookbook.build
61
+ demo: https://v2-demo.lookbook.build
62
+ repo: https://github.com/ViewComponent/lookbook/tree/v2
63
+
58
64
  development:
59
65
  debug_menu: true
66
+ live_updates: true
60
67
 
61
68
  test:
62
69
  debug_menu: true
70
+ live_updates: false
data/config/routes.rb CHANGED
@@ -17,4 +17,6 @@ Lookbook::Engine.routes.draw do
17
17
  get "/embed", to: "embeds#lookup", as: :lookbook_embed_lookup
18
18
  get "/embed/*path", to: "embeds#show", as: :lookbook_embed
19
19
  end
20
+
21
+ get "/*path", to: "application#not_found", via: :all
20
22
  end
@@ -26,7 +26,7 @@ module Lookbook
26
26
  end
27
27
 
28
28
  config.after_initialize do
29
- if opts.using_view_component || Rails.env.test?
29
+ if opts.using_view_component
30
30
  vc_config = Engine.host_config.view_component
31
31
 
32
32
  opts.preview_paths += vc_config.preview_paths
@@ -79,7 +79,10 @@ module Lookbook
79
79
  end
80
80
 
81
81
  def auto_refresh?
82
- reloading? && runtime_context.web? && FileWatcher.evented?
82
+ opts.live_updates == true &&
83
+ reloading? &&
84
+ runtime_context.web? &&
85
+ FileWatcher.evented?
83
86
  end
84
87
 
85
88
  def preview_embeds_allowed?
@@ -129,14 +132,18 @@ module Lookbook
129
132
  end
130
133
 
131
134
  def view_paths
132
- ActionView::ViewPaths.all_view_paths.flat_map do |view_path|
133
- view_path.paths.map { |path| Pathname(path.to_s) }
135
+ # handle view path registry changes in Rails 7.1
136
+ paths = if defined?(ActionView::PathRegistry)
137
+ ActionView::PathRegistry.all_file_system_resolvers.map(&:path)
138
+ else
139
+ ActionView::ViewPaths.all_view_paths.flat_map(&paths)
134
140
  end
141
+ paths.map { |path| Pathname(path.to_s) }
135
142
  end
136
143
 
137
144
  def component_paths
138
145
  @_component_paths ||= begin
139
- paths = [*opts.component_paths, *Engine.view_paths, host_app_path]
146
+ paths = [*opts.component_paths, *view_paths, host_app_path]
140
147
  PathUtils.normalize_paths(paths)
141
148
  end
142
149
  end
@@ -1,23 +1,48 @@
1
1
  module Lookbook
2
- # @api private
3
2
  module AnnotatableEntity
4
3
  extend ActiveSupport::Concern
5
4
 
6
5
  included do
7
6
  delegate :has_tag?, to: :code_object
8
7
 
8
+ # @!group Annotations
9
+
10
+ # Any notes added to the entity.
11
+ # Returns the raw (unrendered) string which may contain markdown formatting.
12
+ #
13
+ # @return [String] The notes, or an empty string if none have been added
9
14
  def notes
10
15
  code_object.docstring.to_s.strip
11
16
  end
12
17
 
18
+ # All tags that have been added to the entity.
19
+ # Can be filtered by tag name by providing the name as an argument.
20
+ #
21
+ # @example :ruby
22
+ # all_tags = entity.tags
23
+ # display_tags = entity.tags(:display)
24
+ #
25
+ # @param name [Symbol] Optional tag type to filter by
26
+ # @return [Array<YardTag>] Array of tags
13
27
  def tags(name = nil)
14
28
  code_object.tags(name)
15
29
  end
16
30
 
31
+ # The first tag (optionally of a particular type)
32
+ # added to the entity.
33
+ #
34
+ # @example :ruby
35
+ # first_tag = entity.tag
36
+ # first_display_tag = entity.tag(:display)
37
+ #
38
+ # @param name [Symbol] Optional tag type to filter by
39
+ # @return [Array<YardTag>] Array of tags
17
40
  def tag(name = nil)
18
41
  tags(name).first
19
42
  end
20
43
 
44
+ # @!endgroup
45
+
21
46
  protected
22
47
 
23
48
  attr_reader :code_object
@@ -1,9 +1,13 @@
1
1
  module Lookbook
2
- # @api private
3
2
  module InspectableEntity
4
3
  extend ActiveSupport::Concern
5
4
 
6
5
  included do
6
+ # @!group Source
7
+
8
+ # Scenario method source code
9
+ #
10
+ # @return [String] The source code0
7
11
  def source
8
12
  source_code = if custom_source?
9
13
  File.read(source_file_path)
@@ -19,10 +23,21 @@ module Lookbook
19
23
  source_code.strip_heredoc.strip
20
24
  end
21
25
 
26
+ # Source code language info.
27
+ #
28
+ # Returns a Hash with `name`, `ext` & `label` entries.
29
+ #
30
+ # @example :ruby
31
+ # source_lang_name = entity.lang[:name]
32
+ #
33
+ # @return [Hash] Language info hash
22
34
  def source_lang
23
35
  custom_source? ? Lang.guess(source_file_path, :ruby) : Lang.find(:ruby)
24
36
  end
25
37
 
38
+ # @!endgroup
39
+
40
+ # @api private
26
41
  def custom_source?
27
42
  source_file_path.present?
28
43
  end
@@ -35,7 +50,7 @@ module Lookbook
35
50
  @_source_path ||= if code_object.has_tag?(:source)
36
51
  source_path = code_object.tag(:source).value
37
52
  unless source_path.present? && File.exist?(source_path)
38
- raise LookbookError, "Could not find source file '#{source_path}'"
53
+ raise Lookbook::Error, "Could not find source file '#{source_path}'"
39
54
  end
40
55
  source_path
41
56
  end