lookbook 2.0.0.beta.3 → 2.0.0.beta.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/lookbook/css/lookbook.css +6 -0
  3. data/app/assets/lookbook/css/themes/blue.css +4 -1
  4. data/app/assets/lookbook/css/themes/green.css +4 -1
  5. data/app/assets/lookbook/css/themes/indigo.css +4 -1
  6. data/app/assets/lookbook/css/themes/rose.css +4 -1
  7. data/app/assets/lookbook/css/themes/zinc.css +4 -1
  8. data/app/assets/lookbook/img/lucide-sprite.svg +869 -869
  9. data/app/components/lookbook/code/highlight_github.css +16 -17
  10. data/app/components/lookbook/dimensions_display/component.js +4 -7
  11. data/app/components/lookbook/file_source/component.html.erb +9 -0
  12. data/app/components/lookbook/file_source/component.rb +73 -0
  13. data/app/components/lookbook/header/component.html.erb +11 -8
  14. data/app/components/lookbook/icon/component.css +1 -1
  15. data/app/components/lookbook/icon/component.html.erb +1 -1
  16. data/app/components/lookbook/icon/component.rb +4 -1
  17. data/app/components/lookbook/logo/component.html.erb +6 -0
  18. data/app/components/lookbook/logo/component.rb +15 -0
  19. data/app/components/lookbook/message/component.css +33 -0
  20. data/app/components/lookbook/message/component.html.erb +26 -0
  21. data/app/components/lookbook/message/component.rb +13 -0
  22. data/app/components/lookbook/nav/entity/component.html.erb +1 -1
  23. data/app/components/lookbook/nav/entity/component.rb +1 -1
  24. data/app/components/lookbook/params/field/component.css +3 -3
  25. data/app/components/lookbook/prose/component.css +8 -1
  26. data/app/components/lookbook/prose/component.html.erb +6 -1
  27. data/app/components/lookbook/prose/component.rb +2 -2
  28. data/app/controllers/concerns/lookbook/targetable_concern.rb +2 -16
  29. data/app/controllers/lookbook/application_controller.rb +38 -14
  30. data/app/controllers/lookbook/embeds_controller.rb +3 -4
  31. data/app/controllers/lookbook/inspector_controller.rb +4 -12
  32. data/app/controllers/lookbook/pages_controller.rb +15 -27
  33. data/app/controllers/lookbook/preview_controller.rb +30 -2
  34. data/app/controllers/lookbook/previews_controller.rb +13 -15
  35. data/app/views/layouts/lookbook/application.html.erb +1 -0
  36. data/app/views/layouts/lookbook/skeleton.html.erb +2 -2
  37. data/app/views/lookbook/errors/default.html.erb +40 -0
  38. data/app/views/lookbook/errors/not_found.html.erb +10 -0
  39. data/app/views/lookbook/index.html.erb +29 -24
  40. data/app/views/lookbook/pages/show.html.erb +6 -5
  41. data/app/views/lookbook/partials/_blank_slate.html.erb +7 -0
  42. data/config/app.yml +8 -0
  43. data/config/routes.rb +2 -0
  44. data/lib/lookbook/engine.rb +6 -3
  45. data/lib/lookbook/entities/concerns/annotatable_entity.rb +26 -1
  46. data/lib/lookbook/entities/concerns/inspectable_entity.rb +17 -2
  47. data/lib/lookbook/entities/concerns/locatable_entity.rb +51 -7
  48. data/lib/lookbook/entities/concerns/navigable_entity.rb +14 -1
  49. data/lib/lookbook/entities/entity.rb +34 -12
  50. data/lib/lookbook/entities/page_entity.rb +68 -10
  51. data/lib/lookbook/entities/page_section_entity.rb +4 -0
  52. data/lib/lookbook/entities/preview_entity.rb +107 -17
  53. data/lib/lookbook/entities/renderable_entity.rb +47 -9
  54. data/lib/lookbook/entities/rendered_scenario_entity.rb +17 -6
  55. data/lib/lookbook/entities/scenario_entity.rb +77 -16
  56. data/lib/lookbook/entities/scenario_group_entity.rb +82 -9
  57. data/lib/lookbook/helpers/page_helper.rb +26 -1
  58. data/lib/lookbook/helpers/ui_elements_helper.rb +0 -24
  59. data/lib/lookbook/param.rb +1 -1
  60. data/lib/lookbook/stores/config_store.rb +0 -12
  61. data/lib/lookbook/support/errors/config_error.rb +1 -1
  62. data/lib/lookbook/support/errors/error.rb +64 -0
  63. data/lib/lookbook/support/errors/parser_error.rb +1 -1
  64. data/lib/lookbook/support/errors/preview_template_error.rb +1 -1
  65. data/lib/lookbook/support/errors/routing_error.rb +7 -0
  66. data/lib/lookbook/support/errors/template_error.rb +7 -0
  67. data/lib/lookbook/version.rb +1 -1
  68. data/public/lookbook-assets/css/lookbook.css +374 -53
  69. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  70. data/public/lookbook-assets/css/themes/blue.css +4 -1
  71. data/public/lookbook-assets/css/themes/blue.css.map +1 -1
  72. data/public/lookbook-assets/css/themes/green.css +4 -1
  73. data/public/lookbook-assets/css/themes/green.css.map +1 -1
  74. data/public/lookbook-assets/css/themes/indigo.css +4 -1
  75. data/public/lookbook-assets/css/themes/indigo.css.map +1 -1
  76. data/public/lookbook-assets/css/themes/rose.css +4 -1
  77. data/public/lookbook-assets/css/themes/rose.css.map +1 -1
  78. data/public/lookbook-assets/css/themes/zinc.css +4 -1
  79. data/public/lookbook-assets/css/themes/zinc.css.map +1 -1
  80. data/public/lookbook-assets/img/lucide-sprite.svg +869 -869
  81. data/public/lookbook-assets/js/index.js +125 -125
  82. data/public/lookbook-assets/js/index.js.map +1 -1
  83. metadata +15 -7
  84. data/app/views/layouts/lookbook/shell.html.erb +0 -25
  85. data/app/views/lookbook/404.html.erb +0 -15
  86. data/app/views/lookbook/error.html.erb +0 -46
  87. data/lib/lookbook/error.rb +0 -120
  88. data/lib/lookbook/support/errors/lookbook_error.rb +0 -21
@@ -162,14 +162,13 @@
162
162
  } /* Comment */
163
163
  .err {
164
164
  color: var(--hl-error-fg);
165
- background-color: var(--hl-error-bg);
166
165
  } /* Error */
167
166
  .g {
168
167
  color: var(--hl-subtle-fg);
169
168
  } /* Generic */
170
169
  .k {
171
170
  color: var(--hl-keyword);
172
- font-weight: bold;
171
+ font-weight: 600;
173
172
  } /* Keyword; catches prefixes and css3 */
174
173
  .l {
175
174
  color: var(--hl-subtle-fg);
@@ -180,7 +179,7 @@
180
179
  } /* Name */
181
180
  .o {
182
181
  color: var(--hl-operator);
183
- font-weight: bold;
182
+ font-weight: 600;
184
183
  } /* Operator */
185
184
  .x {
186
185
  color: var(--hl-subtle-fg);
@@ -194,7 +193,7 @@
194
193
  } /* Comment.Multiline */
195
194
  .cp {
196
195
  color: var(--hl-comment-preproc);
197
- font-weight: bold;
196
+ font-weight: 600;
198
197
  } /* Comment.Preproc */
199
198
  .c1 {
200
199
  color: var(--hl-comment);
@@ -203,7 +202,7 @@
203
202
  .cs {
204
203
  color: var(--hl-comment-special-fg);
205
204
  background-color: var(--hl-comment-special-bg);
206
- font-weight: bold;
205
+ font-weight: 600;
207
206
  font-style: italic;
208
207
  } /* Comment.Special */
209
208
  .gd {
@@ -232,38 +231,38 @@
232
231
  } /* Generic.Prompt */
233
232
  .gs {
234
233
  color: var(--hl-subtle-fg);
235
- font-weight: bold;
234
+ font-weight: 600;
236
235
  } /* Generic.Strong */
237
236
  .gu {
238
237
  color: var(--hl-subheading);
239
- font-weight: bold;
238
+ font-weight: 600;
240
239
  } /* Generic.Subheading */
241
240
  .gt {
242
241
  color: var(--hl-danger);
243
242
  } /* Generic.Traceback */
244
243
  .kc {
245
244
  color: var(--hl-keyword-crude);
246
- font-weight: bold;
245
+ font-weight: 600;
247
246
  } /* Keyword.Constant */
248
247
  .kd {
249
248
  color: var(--hl-keyword-crude);
250
- font-weight: bold;
249
+ font-weight: 600;
251
250
  } /* Keyword.Declaration */
252
251
  .kn {
253
252
  color: var(--hl-keyword-crude);
254
- font-weight: bold;
253
+ font-weight: 600;
255
254
  } /* Keyword.Namespace */
256
255
  .kp {
257
256
  color: var(--hl-keyword-crude);
258
- font-weight: bold;
257
+ font-weight: 600;
259
258
  } /* Keyword.Pseudo */
260
259
  .kr {
261
260
  color: var(--hl-keyword-crude);
262
- font-weight: bold;
261
+ font-weight: 600;
263
262
  } /* Keyword.Reserved */
264
263
  .kt {
265
264
  color: var(--hl-keyword-subtle);
266
- font-weight: bold;
265
+ font-weight: 600;
267
266
  } /* Keyword.Type */
268
267
  .ld {
269
268
  color: var(--hl-subtle-fg);
@@ -282,7 +281,7 @@
282
281
  } /* Name.Builtin */
283
282
  .nc {
284
283
  color: var(--hl-class);
285
- font-weight: bold;
284
+ font-weight: 600;
286
285
  } /* Name.Class */
287
286
  .no {
288
287
  color: var(--hl-variable);
@@ -295,11 +294,11 @@
295
294
  } /* Name.Entity */
296
295
  .ne {
297
296
  color: var(--hl-exception);
298
- font-weight: bold;
297
+ font-weight: 600;
299
298
  } /* Name.Exception */
300
299
  .nf {
301
300
  color: var(--hl-function);
302
- font-weight: bold;
301
+ font-weight: 600;
303
302
  } /* Name.Function */
304
303
  .nl {
305
304
  color: var(--hl-subtle-fg);
@@ -321,7 +320,7 @@
321
320
  } /* Name.Variable */
322
321
  .ow {
323
322
  color: var(--hl-word);
324
- font-weight: bold;
323
+ font-weight: 600;
325
324
  } /* Operator.Word */
326
325
  .w {
327
326
  color: var(--hl-whitespace);
@@ -18,13 +18,10 @@ export default function dimensionsDisplayComponent(targetSelector) {
18
18
 
19
19
  createObserver() {
20
20
  if (this.target) {
21
- this.observer = observeSize(
22
- document.querySelector(targetSelector),
23
- ({ width, height }) => {
24
- this.width = width;
25
- this.height = height;
26
- }
27
- );
21
+ this.observer = observeSize(this.target, ({ width, height }) => {
22
+ this.width = width;
23
+ this.height = height;
24
+ });
28
25
  }
29
26
  },
30
27
 
@@ -0,0 +1,9 @@
1
+ <%= render_component_tag do %>
2
+ <%= lookbook_render :code,
3
+ language: source_lang,
4
+ highlight_lines: highlight_lines,
5
+ start_line: start_line_number,
6
+ line_numbers: true do %>
7
+ <%= trimmed_source %>
8
+ <% end %>
9
+ <% end %>
@@ -0,0 +1,73 @@
1
+ module Lookbook
2
+ class FileSource::Component < Lookbook::BaseComponent
3
+ attr_reader :file_path, :lines_around_highlight
4
+
5
+ def initialize(file_path:, source: nil, highlight_lines: [], lines_around_highlight: nil,
6
+ start_line: 1, end_line: nil, start_line_number: nil, **html_attrs)
7
+ @file_path = file_path
8
+ @source = source
9
+ @highlight_lines = highlight_lines.map(&:to_i)
10
+ @start_line = start_line
11
+ @end_line = end_line
12
+ @start_line_number = start_line_number
13
+ @lines_around_highlight = lines_around_highlight
14
+ super(**html_attrs)
15
+ end
16
+
17
+ def render?
18
+ source.present?
19
+ end
20
+
21
+ def trimmed_source
22
+ return unless source.present?
23
+
24
+ from = start_line - 1
25
+ to = end_line - 1
26
+ source_lines[from..to].join("\n")
27
+ end
28
+
29
+ def source
30
+ return @source if @source.present?
31
+
32
+ @_source ||= File.read(file_path)
33
+ rescue
34
+ nil
35
+ end
36
+
37
+ def source_lang
38
+ lang = Lang.guess(file_path)
39
+ lang.present? ? lang[:name] : "plaintext"
40
+ end
41
+
42
+ def highlight_lines
43
+ @highlight_lines.map { |num| num - start_line + 1 }
44
+ end
45
+
46
+ def source_lines
47
+ @_source_lines ||= source&.split("\n")
48
+ end
49
+
50
+ def start_line
51
+ if lines_around_highlight && @highlight_lines.any?
52
+ start = @highlight_lines.first - lines_around_highlight
53
+ (start > 0) ? start : 1
54
+ else
55
+ @start_line
56
+ end
57
+ end
58
+
59
+ def start_line_number
60
+ @start_line_number || start_line
61
+ end
62
+
63
+ def end_line
64
+ line_count = source_lines.size
65
+ if lines_around_highlight && @highlight_lines.any?
66
+ last = @highlight_lines.last + lines_around_highlight
67
+ (last <= line_count) ? last : line_count
68
+ else
69
+ (@end_line && (@end_line <= line_count)) ? @end_line : line_count
70
+ end
71
+ end
72
+ end
73
+ end
@@ -1,13 +1,16 @@
1
1
  <%= render_component_tag :header do %>
2
2
  <%= lookbook_render :toolbar, class: "!bg-lookbook-header-bg !text-lookbook-header-text !border-lookbook-header-border" do |toolbar| %>
3
3
  <% toolbar.with_section padded: true do %>
4
- <% if branding.present? %>
5
- <a
6
- <% if landing_path %>href="<%= landing_path %>"<% end %>
7
- class="text-sm truncate uppercase font-black tracking-wider text-lookbook-branding-text">
8
- <%= branding %>
9
- </a>
10
- <% end %>
4
+ <div class="flex items-center space-x-3">
5
+ <%= lookbook_render :logo, size: 4 %>
6
+ <% if branding.present? %>
7
+ <a
8
+ <% if landing_path %>href="<%= landing_path %>"<% end %>
9
+ class="text-sm truncate uppercase font-black tracking-wider text-lookbook-branding-text">
10
+ <%= branding %>
11
+ </a>
12
+ <% end %>
13
+ </div>
11
14
  <% end %>
12
15
 
13
16
  <% toolbar.with_section padded: false, align: :right, class: "flex items-center -mt-px" do %>
@@ -22,7 +25,7 @@
22
25
  <% if @debug_menu %>
23
26
  <% group.with_button id: "debug-menu-button",
24
27
  icon: :help_circle,
25
- class: "opacity-50 hover:opacity-100 transition !text-lookbook-header-text", "x-show": "!loading" do |button| %>
28
+ class: "!text-lookbook-header-text", "x-show": "!loading" do |button| %>
26
29
  <% menu = lookbook_render :debug_menu,
27
30
  version: Lookbook::VERSION,
28
31
  docs_url: "https://lookbook.build/guide",
@@ -3,7 +3,7 @@
3
3
  @apply transition block flex-none leading-none;
4
4
 
5
5
  svg {
6
- @apply w-full h-full stroke-current stroke-2 fill-transparent;
6
+ @apply w-full h-full stroke-current fill-transparent;
7
7
  stroke-linecap: round;
8
8
  stroke-linejoin: round;
9
9
  }
@@ -1,5 +1,5 @@
1
1
  <%= render_component_tag :i, style: "height: #{size_rems}; width: #{size_rems}; #{@html_attrs[:style]}" do %>
2
- <svg>
2
+ <svg stroke-width="<%= stroke %>">
3
3
  <use :href="`/lookbook-assets/img/lucide-sprite.svg#${iconName}`" x-cloak />
4
4
  </svg>
5
5
  <% end %>
@@ -1,8 +1,11 @@
1
1
  module Lookbook
2
2
  class Icon::Component < Lookbook::BaseComponent
3
- def initialize(name:, size: 4, **html_attrs)
3
+ attr_reader :stroke
4
+
5
+ def initialize(name:, size: 4, stroke: 2, **html_attrs)
4
6
  @alpine_data = name.is_a?(Symbol) ? alpine_encode(name.to_s.tr("_", "-")) : name
5
7
  @size = size || 4
8
+ @stroke = stroke
6
9
  super(**html_attrs)
7
10
  end
8
11
 
@@ -0,0 +1,6 @@
1
+ <svg width="<%= size_rems %>" viewBox="0 0 18 22" xmlns="http://www.w3.org/2000/svg">
2
+ <g stroke="currentColor" stroke-width="<%= stroke %>" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
3
+ <path d="M3.5 1H17v20H3.5A2.5 2.5 0 0 1 1 18.5v-15A2.5 2.5 0 0 1 3.5 1Z"/>
4
+ <path d="M1.153 19.36c0-.737.261-1.188.596-1.57.417-.475.985-.79 1.751-.79H17M6.801 5.1v7.554L6.8 12.7h5.57"/>
5
+ </g>
6
+ </svg>
@@ -0,0 +1,15 @@
1
+ module Lookbook
2
+ class Logo::Component < Lookbook::BaseComponent
3
+ attr_reader :stroke
4
+
5
+ def initialize(size: 4, stroke: 2, **html_attrs)
6
+ @size = size || 4
7
+ @stroke = stroke
8
+ super(**html_attrs)
9
+ end
10
+
11
+ def size_rems
12
+ "#{@size * 0.25}rem"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ @layer components {
2
+ [data-component="message"] {
3
+ @apply bg-lookbook-message-bg p-4 xs:p-6 shadow border border-lookbook-divider rounded flex gap-6 w-full;
4
+
5
+ &.icon-right {
6
+ @apply flex-row-reverse items-center;
7
+ }
8
+
9
+ &.icon-left {
10
+ @apply items-start;
11
+ }
12
+
13
+ & .message-title {
14
+ @apply text-base text-lookbook-message-title truncate uppercase font-bold tracking-wide mb-2;
15
+ }
16
+
17
+ & .message-icon {
18
+ @apply flex-none opacity-30 hidden xs:block;
19
+ }
20
+
21
+ &.theme-error {
22
+ @apply border-red-200;
23
+
24
+ & .message-title {
25
+ @apply text-red-700;
26
+ }
27
+
28
+ & .message-icon {
29
+ @apply text-red-600 opacity-50;
30
+ }
31
+ }
32
+ }
33
+ }
@@ -0,0 +1,26 @@
1
+ <%= render_component_tag class: {
2
+ "icon-left": (icon_position == :left),
3
+ "icon-right": (icon_position == :right),
4
+ "theme-info": (theme == :info),
5
+ "theme-error": (theme == :error),
6
+ } do %>
7
+ <% if icon_name %>
8
+ <div class="message-icon">
9
+ <% if icon_name == :logo %>
10
+ <%= lookbook_render :logo, stroke: 1, size: 10 %>
11
+ <% else %>
12
+ <%= icon icon_name, stroke: 1, size: 10 %>
13
+ <% end %>
14
+ </div>
15
+ <% end %>
16
+ <div class="flex-grow">
17
+ <% if title %>
18
+ <h4 class="message-title">
19
+ <%= title %>
20
+ </h4>
21
+ <% end %>
22
+ <div class="opacity-70">
23
+ <%= lookbook_render :prose, size: :sm, content: content %>
24
+ </div>
25
+ </div>
26
+ <% end %>
@@ -0,0 +1,13 @@
1
+ module Lookbook
2
+ class Message::Component < Lookbook::BaseComponent
3
+ attr_reader :title, :icon_name, :icon_position, :theme
4
+
5
+ def initialize(title: nil, icon: nil, icon_position: :left, theme: :info, **html_attrs)
6
+ @title = title
7
+ @icon_name = icon
8
+ @icon_position = icon_position
9
+ @theme = theme
10
+ super(**html_attrs)
11
+ end
12
+ end
13
+ end
@@ -3,7 +3,7 @@
3
3
  key: "#{id}-entity-#{type}",
4
4
  class: "list-none",
5
5
  "x-show": "!filteredOut",
6
- data: { "entity-type": type },
6
+ data: { "entity-type": type.to_s.tr("_","-") },
7
7
  cloak: true do %>
8
8
  <%= lookbook_tag href.present? ? :a : :button,
9
9
  href: href,
@@ -4,7 +4,7 @@ module Lookbook
4
4
  page: :file,
5
5
  preview: :layers,
6
6
  scenario: :eye,
7
- group: :eye
7
+ scenario_group: :eye
8
8
  }.freeze
9
9
 
10
10
  def nav_icon
@@ -7,7 +7,7 @@
7
7
  }
8
8
 
9
9
  th {
10
- @apply font-bold py-4 px-4 align-middle text-left;
10
+ @apply font-semibold py-4 px-4 align-middle text-left;
11
11
  }
12
12
 
13
13
  th.param-label {
@@ -29,7 +29,7 @@
29
29
  }
30
30
 
31
31
  td.param-label {
32
- @apply font-bold;
32
+ @apply font-semibold;
33
33
  }
34
34
 
35
35
  .param-input-wrapper {
@@ -65,7 +65,7 @@
65
65
  }
66
66
 
67
67
  td.param-label {
68
- @apply font-bold;
68
+ @apply font-semibold;
69
69
  }
70
70
 
71
71
  td.param-description-empty {
@@ -1,12 +1,19 @@
1
1
  @layer components {
2
2
  [data-component="prose"] {
3
+ letter-spacing: -0.015em !important;
4
+
3
5
  [data-component="code"] {
4
6
  @apply border border-lookbook-divider rounded-md;
5
7
  }
6
8
 
7
9
  [data-component="embed"],
8
- [data-component="code"] {
10
+ [data-component="code"],
11
+ [data-lookbook-embed] {
9
12
  @apply my-8;
10
13
  }
14
+
15
+ [data-lookbook-embed] {
16
+ @apply rounded-md;
17
+ }
11
18
  }
12
19
  }
@@ -1,3 +1,8 @@
1
- <%= render_component_tag class: "prose #{size_class} text-lookbook-prose-text bg-lookbook-prose-bg prose-a:text-lookbook-prose-link" do %>
1
+ <%= render_component_tag class: "
2
+ prose #{size_class}
3
+ text-lookbook-prose-text bg-lookbook-prose-bg prose-a:text-lookbook-prose-link
4
+ prose-headings:font-semibold
5
+ prose-h1:font-bold
6
+ " do %>
2
7
  <%== rendered_content %>
3
8
  <% end %>
@@ -1,6 +1,6 @@
1
1
  module Lookbook
2
2
  class Prose::Component < Lookbook::BaseComponent
3
- def initialize(size: :md, markdown: true, **html_attrs)
3
+ def initialize(size: :sm, markdown: true, **html_attrs)
4
4
  @size = size
5
5
  @markdown = markdown
6
6
  super(**html_attrs)
@@ -17,7 +17,7 @@ module Lookbook
17
17
  when :lg
18
18
  "prose-lg"
19
19
  else
20
- ""
20
+ "prose-sm lg:prose-base"
21
21
  end
22
22
  end
23
23
  end
@@ -66,7 +66,8 @@ module Lookbook
66
66
  @params = []
67
67
 
68
68
  if @target
69
- @params = @target.tags("param").map do |param_tag|
69
+ param_tags = @target.tags("param").uniq(&:name)
70
+ @params = param_tags.map do |param_tag|
70
71
  Param.from_tag(
71
72
  param_tag,
72
73
  value: preview_controller.params[param_tag.name]
@@ -115,21 +116,6 @@ module Lookbook
115
116
  })
116
117
  end
117
118
 
118
- def show_404(layout: nil)
119
- locals = if @preview
120
- {
121
- message: "Example not found",
122
- description: "The '#{@preview.label}' preview does not have an scenario named '#{path_segments.last}'."
123
- }
124
- else
125
- {
126
- message: "Not found",
127
- description: "Looked for '#{params[:path]}'.<br>The preview may have been renamed or deleted."
128
- }
129
- end
130
- render_in_layout "lookbook/404", layout: layout, **locals, status: 404
131
- end
132
-
133
119
  def path_segments
134
120
  params[:path].split("/")
135
121
  end
@@ -4,13 +4,20 @@ module Lookbook
4
4
 
5
5
  protect_from_forgery with: :exception
6
6
 
7
+ layout "lookbook/application"
8
+
7
9
  helper Lookbook::ClassNamesHelper if Engine.runtime_context.rails_older_than?("6.1.0")
8
10
  helper Lookbook::ApplicationHelper
9
11
  helper Lookbook::UiElementsHelper
10
12
 
11
- before_action :generate_theme_overrides
13
+ before_action :assign_theme_overrides
12
14
  before_action :assign_instance_vars
13
15
 
16
+ rescue_from ActionController::RoutingError do |err|
17
+ raise Lookbook::RoutingError, err.message, original: err
18
+ end
19
+ rescue_from StandardError, with: :handle_error
20
+
14
21
  def self.controller_path
15
22
  "lookbook"
16
23
  end
@@ -24,9 +31,13 @@ module Lookbook
24
31
  end
25
32
  end
26
33
 
34
+ def not_found
35
+ raise_not_found
36
+ end
37
+
27
38
  protected
28
39
 
29
- def generate_theme_overrides
40
+ def assign_theme_overrides
30
41
  @theme_overrides ||= Engine.theme.to_css
31
42
  end
32
43
 
@@ -37,23 +48,36 @@ module Lookbook
37
48
  @config = Lookbook.config
38
49
  @engine = Lookbook.engine
39
50
  @embed = !!params[:lookbook_embed]
51
+ @blank_slate = Engine.pages.none? && Engine.previews.none?
40
52
  end
41
53
 
42
- def render_in_layout(path, layout: nil, **locals)
43
- @error = locals[:error]
44
- render path, layout: layout.presence || (params[:lookbook_embed] ? "lookbook/basic" : "lookbook/application"), locals: locals
54
+ def raise_not_found(message = "Page not found")
55
+ raise Lookbook::RoutingError, message
45
56
  end
46
57
 
47
- def prettify_error(exception)
48
- error_params = {}
49
- if exception.is_a?(ViewComponent::PreviewTemplateError)
50
- error_params = {
51
- file_path: @preview&.file_path,
52
- line_number: 0,
53
- source_code: @target&.source
54
- }
58
+ def handle_error(err)
59
+ @error = err.is_a?(Lookbook::Error) ? err : Lookbook::Error.new(original: err)
60
+ @status_code = get_status_code(err)
61
+
62
+ view = (@status_code == :not_found) ? "not_found" : "default"
63
+ layout = current_layout || "lookbook/skeleton"
64
+
65
+ render "lookbook/errors/#{view}", layout: layout, status: @status_code
66
+ end
67
+
68
+ def current_layout
69
+ self.class.send(:_layout)
70
+ end
71
+
72
+ private
73
+
74
+ def get_status_code(err)
75
+ if err.respond_to?(:status)
76
+ err.status
77
+ else
78
+ status_map = ActionDispatch::ExceptionWrapper.rescue_responses
79
+ status_map.fetch(err.class.name, :internal_server_error)
55
80
  end
56
- Lookbook::Error.new(exception, **error_params)
57
81
  end
58
82
  end
59
83
  end
@@ -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