lookbook 1.0.0.beta.0 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +84 -2
  3. data/app/assets/lookbook/js/stores/inspector.js +4 -4
  4. data/app/components/lookbook/dimensions_display/component.html.erb +2 -1
  5. data/app/components/lookbook/dimensions_display/component.js +19 -12
  6. data/app/components/lookbook/header/component.html.erb +2 -2
  7. data/app/components/lookbook/page_tabs/component.html.erb +18 -0
  8. data/app/components/lookbook/page_tabs/component.rb +19 -0
  9. data/app/components/lookbook/tab_panels/component.html.erb +5 -0
  10. data/app/components/lookbook/tab_panels/component.js +25 -0
  11. data/app/components/lookbook/tab_panels/component.rb +20 -0
  12. data/app/components/lookbook/{tabbed_content/section → tab_panels/panel}/component.html.erb +2 -2
  13. data/app/components/lookbook/tab_panels/panel/component.rb +9 -0
  14. data/app/components/lookbook/tabs/component.html.erb +8 -2
  15. data/app/components/lookbook/tabs/component.js +11 -3
  16. data/app/components/lookbook/tabs/component.rb +8 -10
  17. data/app/components/lookbook/tabs/dropdown_tab/component.html.erb +8 -2
  18. data/app/components/lookbook/tabs/dropdown_tab/component.rb +4 -3
  19. data/app/components/lookbook/tabs/tab/component.html.erb +9 -3
  20. data/app/components/lookbook/tabs/tab/component.rb +4 -3
  21. data/app/components/lookbook/toolbar/component.css +1 -1
  22. data/app/controllers/lookbook/application_controller.rb +1 -1
  23. data/app/controllers/lookbook/pages_controller.rb +1 -0
  24. data/app/controllers/lookbook/previews_controller.rb +90 -86
  25. data/app/views/lookbook/pages/show.html.erb +11 -1
  26. data/app/views/lookbook/preview.html.erb +3 -3
  27. data/app/views/lookbook/previews/panels/_content.html.erb +13 -0
  28. data/app/views/lookbook/previews/panels/_notes.html.erb +5 -5
  29. data/app/views/lookbook/previews/panels/_output.html.erb +3 -3
  30. data/app/views/lookbook/previews/panels/_params.html.erb +2 -2
  31. data/app/views/lookbook/previews/panels/_preview.html.erb +1 -1
  32. data/app/views/lookbook/previews/panels/_source.html.erb +6 -6
  33. data/app/views/lookbook/previews/show.html.erb +38 -35
  34. data/lib/lookbook/config.rb +87 -32
  35. data/lib/lookbook/page.rb +31 -8
  36. data/lib/lookbook/page_section.rb +31 -0
  37. data/lib/lookbook/store.rb +36 -0
  38. data/lib/lookbook/theme.rb +7 -0
  39. data/lib/lookbook/utils.rb +1 -1
  40. data/lib/lookbook/version.rb +1 -1
  41. data/lib/lookbook.rb +2 -0
  42. data/public/lookbook-assets/css/lookbook.css +34 -5
  43. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  44. data/public/lookbook-assets/js/lookbook.js +36 -24
  45. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  46. metadata +12 -7
  47. data/app/components/lookbook/tabbed_content/component.html.erb +0 -5
  48. data/app/components/lookbook/tabbed_content/component.js +0 -21
  49. data/app/components/lookbook/tabbed_content/component.rb +0 -20
  50. data/app/components/lookbook/tabbed_content/section/component.rb +0 -9
@@ -8,12 +8,17 @@ module Lookbook
8
8
 
9
9
  before_action :lookup_entities, only: [:preview, :show]
10
10
  before_action :set_title
11
+ before_action :set_params
11
12
 
12
13
  def preview
13
14
  if @example
14
- set_params
15
15
  begin
16
- render html: render_examples(examples_data)
16
+ opts = {layout: @preview.layout}
17
+ if params[:lookbook_embed] == "true"
18
+ opts[:append_html] = "<script src=\"/lookbook-assets/js/embed.js?v=#{Lookbook.version}\"></script>".html_safe
19
+ end
20
+ preview_html = preview_controller.process(:render_in_layout_to_string, "lookbook/preview", inspector_data, **opts)
21
+ render html: preview_html
17
22
  rescue => exception
18
23
  render_in_layout "lookbook/error",
19
24
  layout: "lookbook/standalone",
@@ -27,10 +32,8 @@ module Lookbook
27
32
  def show
28
33
  if @example
29
34
  begin
30
- set_params
31
- @rendered_examples = examples_data
32
- @drawer_panels = drawer_panels.filter { |name, panel| panel[:show] }
33
- @preview_panels = preview_panels.filter { |name, panel| panel[:show] }
35
+ @main_panels = main_panels
36
+ @drawer_panels = drawer_panels
34
37
  rescue => exception
35
38
  render_in_layout "lookbook/error", layout: "lookbook/inspector", error: prettify_error(exception)
36
39
  end
@@ -79,107 +82,108 @@ module Lookbook
79
82
  render_in_layout "lookbook/404", layout: layout, **locals
80
83
  end
81
84
 
85
+ def target_examples
86
+ @example.type == :group ? @example.examples : [@example]
87
+ end
88
+
82
89
  def set_title
83
90
  @title = @example.present? ? [@example&.label, @preview&.label].compact.join(" :: ") : "Not found"
84
91
  end
85
92
 
86
- def examples_data
87
- @examples_data ||= (@example.type == :group ? @example.examples : [@example]).map do |example|
88
- example_data(example)
93
+ def set_params
94
+ if @example
95
+ # cast known params to type
96
+ @example.params.each do |param|
97
+ if preview_controller.params.key?(param[:name])
98
+ preview_controller.params[param[:name]] = Lookbook::Params.cast(preview_controller.params[param[:name]], param[:type])
99
+ end
100
+ end
101
+ # set display params
102
+ preview_controller.params.merge!({
103
+ lookbook: {
104
+ display: @example.display_params
105
+ }
106
+ })
107
+ end
108
+ end
109
+
110
+ def preview_params
111
+ preview_controller.params.permit!
112
+ preview_controller.params.to_h.select do |key, value|
113
+ !!@example.params.find { |param| param[:name] == key }
89
114
  end
90
115
  end
91
116
 
92
- def example_data(example)
93
- render_args = @preview.render_args(example.name, params: preview_controller.params.permit!)
94
- has_template = render_args[:template] != "view_components/preview"
95
- {
96
- label: example.label,
97
- notes: example.notes,
98
- html: preview_controller.process(:render_example_to_string, @preview, example.name),
99
- source: has_template ? example.template_source(render_args[:template]) : example.method_source,
100
- source_lang: has_template ? example.template_lang(render_args[:template]) : example.source_lang,
101
- params: example.params,
102
- display: example.display_params
117
+ def inspector_data
118
+ return @inspector_data if @inspector_data.present?
119
+
120
+ request_data = {
121
+ preview_params: preview_params,
122
+ path: params[:path],
123
+ query_parameters: request.query_parameters,
124
+ original: request
103
125
  }
104
- end
105
126
 
106
- def render_examples(examples)
107
- opts = {layout: @preview.layout}
108
- if params[:lookbook_embed] == "true"
109
- opts[:append_html] = "<script src=\"/lookbook-assets/js/embed.js?v=#{Lookbook.version}\"></script>".html_safe
127
+ preview_data = {
128
+ relative_path: @preview.full_path.relative_path_from(Rails.root.to_s),
129
+ full_path: @preview.full_path,
130
+ example_label: @example.label,
131
+ params: @example.params,
132
+ }
133
+ [:id, :label, :notes, :lookup_path, :full_path].each do |prop|
134
+ preview_data[prop] = @preview.public_send(prop)
110
135
  end
111
- preview_controller.process(:render_in_layout_to_string, "lookbook/preview", {examples: examples}, **opts)
112
- end
113
136
 
114
- def set_params
115
- # cast known params to type
116
- @example.params.each do |param|
117
- if preview_controller.params.key?(param[:name])
118
- preview_controller.params[param[:name]] = Lookbook::Params.cast(preview_controller.params[param[:name]], param[:type])
137
+ examples_data = target_examples.map do |example|
138
+ render_args = @preview.render_args(example.name, params: preview_controller.params)
139
+ has_template = render_args[:template] != "view_components/preview"
140
+ example_data = Lookbook::Store.new({
141
+ output: preview_controller.process(:render_example_to_string, @preview, example.name),
142
+ source: has_template ? example.template_source(render_args[:template]) : example.method_source,
143
+ source_lang: has_template ? example.template_lang(render_args[:template]) : example.source_lang,
144
+ })
145
+ [:id, :label, :notes, :lookup_path, :params, :display_params].each do |prop|
146
+ example_data[prop] = example.public_send(prop)
119
147
  end
148
+ example_data
120
149
  end
121
150
 
122
- # set display params
123
- preview_controller.params.merge!({
124
- lookbook: {
125
- display: @example.display_params
126
- }
151
+ @inspector_data ||= Lookbook::Store.new({
152
+ request: request_data,
153
+ preview: preview_data,
154
+ examples: examples_data
127
155
  })
128
156
  end
129
157
 
130
- def preview_panels
131
- {
132
- preview: {
133
- id: "preview-panel-preview",
134
- label: "Preview",
135
- template: "lookbook/previews/panels/preview",
136
- hotkey: "v",
137
- show: true,
138
- disabled: false,
139
- copy: false
140
- },
141
- output: {
142
- id: "preview-panel-html",
143
- label: "HTML",
144
- template: "lookbook/previews/panels/output",
145
- hotkey: "h",
146
- show: true,
147
- disabled: false,
148
- copy: false
158
+ def panels
159
+ return @panels if @panels.present?
160
+ @panels = []
161
+ Lookbook.config.inspector_panels.each do |name, config|
162
+ config_with_defaults = Lookbook.config.inspector_panel_defaults.merge(config)
163
+
164
+ callable_data = {
165
+ name: name.to_s,
166
+ index_position: (@panels.filter { |p| p.pane == config.pane }.size + 1),
167
+ **inspector_data
149
168
  }
150
- }
169
+
170
+ resolved_config = config_with_defaults.transform_values do |value|
171
+ value.class == Proc ? value.call(Lookbook::Store.new(callable_data)) : value
172
+ end
173
+ resolved_config[:name] = name.to_s
174
+
175
+ @panels << Lookbook::Store.new(resolved_config, deep: false)
176
+ end
177
+
178
+ @panels.filter(&:show).sort_by { |p| [p.position, p.label] }
179
+ end
180
+
181
+ def main_panels
182
+ panels.filter { |panel| panel.pane == :main }
151
183
  end
152
184
 
153
185
  def drawer_panels
154
- {
155
- source: {
156
- id: "drawer-panel-source",
157
- label: "Source",
158
- template: "lookbook/previews/panels/source",
159
- hotkey: "s",
160
- show: true,
161
- disabled: false,
162
- copy: @rendered_examples.map { |e| e[:source] }.join("\n")
163
- },
164
- notes: {
165
- id: "drawer-panel-notes",
166
- label: "Notes",
167
- template: "lookbook/previews/panels/notes",
168
- hotkey: "n",
169
- show: true,
170
- copy: false,
171
- disabled: @rendered_examples.filter { |e| e[:notes].present? }.none?
172
- },
173
- params: {
174
- id: "drawer-panel-params",
175
- label: "Params",
176
- template: "lookbook/previews/panels/params",
177
- hotkey: "p",
178
- show: true,
179
- disabled: @example.params.none?,
180
- copy: false
181
- }
182
- }
186
+ panels.filter { |panel| panel.pane == :drawer }
183
187
  end
184
188
 
185
189
  def preview_controller
@@ -9,7 +9,17 @@
9
9
  <%= render_component :prose, markdown: false, class: "max-w-none flex-none" do %>
10
10
  <%= @page_content %>
11
11
  <% end %>
12
-
12
+
13
+ <% if @page.sections.any? %>
14
+ <%= render_component :page_tabs, markdown: false do |page_tabs| %>
15
+ <% @page.sections.each do |section| %>
16
+ <% page_tabs.tab name: "page-section-#{section.name}", label: section.label do %>
17
+ <%= page_controller.render_page(section) %>
18
+ <% end %>
19
+ <% end %>
20
+ <% end %>
21
+ <% end %>
22
+
13
23
  <% if @page.footer? && @pages.many? %>
14
24
  <footer class="flex items-center justify-between border-t border-gray-300 mt-12 pt-8 pb-10 ">
15
25
  <% if @previous_page %>
@@ -3,12 +3,12 @@
3
3
  <% examples.each do |example| %>
4
4
  <div style="all: unset; margin-bottom: 30px; display: block;">
5
5
  <h6 style="all: unset; display: block; color: #999; font-family: sans-serif; font-size: 14px; margin-top: 0; margin-bottom: 10px;">
6
- <%= example[:label] %>
6
+ <%= example.label %>
7
7
  </h6>
8
- <%= example[:html] %>
8
+ <%= example.output %>
9
9
  </div>
10
10
  <% end %>
11
11
  <% else %>
12
12
  <%# Render a single example %>
13
- <%= examples.first[:html] %>
13
+ <%= examples.first.output %>
14
14
  <% end %>
@@ -0,0 +1,13 @@
1
+ <div class="p-4 bg-lookbook-prose h-full">
2
+ <% if panel.content.present? %>
3
+ <%= render_component :prose, markdown: true do %>
4
+ <%== panel.content %>
5
+ <% end %>
6
+ <% else %>
7
+ <% if Rails.env.development? %>
8
+ <%= render_component :prose do %>
9
+ <em class='opacity-50'>No content has been defined for this panel.</em>
10
+ <% end %>
11
+ <% end %>
12
+ <% end %>
13
+ </div>
@@ -1,19 +1,19 @@
1
- <% items = rendered_examples.filter { |example| example[:notes].present? } %>
1
+ <% items = examples.filter { |example| example.notes.present? } %>
2
2
  <% if items.many? %>
3
3
  <div class="divide-y divide-dashed divide-lookbook-divider bg-lookbook-prose h-full w-full">
4
4
  <% items.each do |item| %>
5
5
  <div class="px-4 py-6 relative">
6
6
  <h6 class="italic font-mono mb-4 opacity-40">
7
- # <%= item[:label] %>
7
+ # <%= item.label %>
8
8
  </h6>
9
- <%= render_component :prose, content: item[:notes] %>
9
+ <%= render_component :prose, content: item.notes %>
10
10
  </div>
11
11
  <% end %>
12
12
  </div>
13
13
  <% else %>
14
- <div class="p-4 py-4 bg-lookbook-prose w-full h-full">
14
+ <div class="p-4 bg-lookbook-prose w-full h-full">
15
15
  <%= render_component :prose do %>
16
- <%== items.any? ? items.first[:notes] : "<em class='opacity-50'>No notes provided.</em>" %>
16
+ <%== items.any? ? items.first.notes : "<em class='opacity-50'>No notes provided.</em>" %>
17
17
  <% end %>
18
18
  </div>
19
19
  <% end %>
@@ -1,7 +1,7 @@
1
1
  <%= render_component :code, line_numbers: true, full_height: true do -%>
2
- <% if rendered_examples.many? -%>
3
- <% rendered_examples.each do |example| -%><%== "<!-- #{example[:label]} -->\n#{beautify(example[:html])}\n\n" -%><% end %>
2
+ <% if examples.many? -%>
3
+ <% examples.each do |example| -%><%== "<!-- #{example.label} -->\n#{beautify(example.output)}\n\n" -%><% end %>
4
4
  <%- else -%>
5
- <%== beautify(rendered_examples.first[:html]) -%>
5
+ <%== beautify(examples.first.output) -%>
6
6
  <%- end %>
7
7
  <% end %>
@@ -1,4 +1,4 @@
1
- <% if @example.params.none? %>
1
+ <% if preview.params.none? %>
2
2
  <div class="p-4 w-full h-full bg-lookbook-prose">
3
3
  <%= render_component :prose do %>
4
4
  <em class='opacity-50'>No params configured.</em>
@@ -7,7 +7,7 @@
7
7
  <% else %>
8
8
  <div class="py-3 h-full">
9
9
  <%= render_component :params_editor do |editor| %>
10
- <% @example.params.each do |param| %>
10
+ <% preview.params.each do |param| %>
11
11
  <% editor.field **param, value: params[param[:name]] %>
12
12
  <% end %>
13
13
  <% end %>
@@ -1,6 +1,6 @@
1
1
  <%= render_component :viewport,
2
2
  src: lookbook.preview_path(request.query_parameters.merge(lookbook_timestamp: Time.now)),
3
- alpine_data: "$store.inspector.preview",
3
+ alpine_data: "$store.inspector.main",
4
4
  class: "-inset-px relative",
5
5
  style: "width: calc(100% + 2px); height: calc(100% + 2px)"
6
6
  %>
@@ -1,11 +1,11 @@
1
1
  <div class="h-full">
2
- <% if rendered_examples.many? %>
3
- <%= render_component :code, language: rendered_examples.first[:source_lang][:name], line_numbers: true, full_height: true do -%>
4
- <%- rendered_examples.each.with_index(1) do |example, i| -%>
5
- <%== "#{sprintf example[:source_lang][:comment], example[:label]}\n#{example[:source]}\n#{"\n" if i < rendered_examples.size}" %><% end %>
2
+ <% if examples.many? %>
3
+ <%= render_component :code, language: examples.first.source_lang[:name], line_numbers: true, full_height: true do -%>
4
+ <%- examples.each.with_index(1) do |example, i| -%>
5
+ <%== "#{sprintf example.source_lang[:comment], example.label}\n#{example.source}\n#{"\n" if i < examples.size}" %><% end %>
6
6
  <% end %>
7
7
  <% else %>
8
- <% example = rendered_examples.first %>
9
- <%= render_component :code, language: example[:source_lang][:name], line_numbers: true, full_height: true do %><%== example[:source] %><% end %>
8
+ <% example = examples.first %>
9
+ <%= render_component :code, language: example.source_lang[:name], line_numbers: true, full_height: true do %><%== example.source %><% end %>
10
10
  <% end %>
11
11
  </div>
@@ -1,20 +1,23 @@
1
1
  <%= render_component :split_layout,
2
2
  alpine_data: "$store.layout.inspector",
3
- ":class": "$store.inspector.drawer.hidden && '!grid-rows-[1fr] !grid-cols-[1fr]'" do |layout| %>
3
+ ":class": "($store.inspector.drawer.hidden || #{@drawer_panels.none?}) && '!grid-rows-[1fr] !grid-cols-[1fr]'" do |layout| %>
4
4
 
5
5
  <%= layout.pane class: "flex flex-col h-full overflow-hidden",
6
6
  x_effect: "forceOrientation = (layoutWidth < $store.inspector.minVerticalSplitWidth) ? 'horizontal' : null" do %>
7
7
 
8
8
  <%= render_component :toolbar do |toolbar| %>
9
9
  <% toolbar.section ":class": "layoutResizing && 'overflow-hidden'" do %>
10
- <%= render_component :tabs, alpine_data: "$store.inspector.preview" do |tabs| %>
11
- <%= @preview_panels.each do |key, panel| %>
12
- <% tabs.tab ref: key, **panel.extract!(:label, :hotkey, :disabled) %>
10
+ <%= render_component :tabs, alpine_data: "$store.inspector.main" do |tabs| %>
11
+ <%= @main_panels.each do |panel| %>
12
+ <% tabs.tab name: panel.name,
13
+ label: panel.label,
14
+ hotkey: panel.hotkey,
15
+ disabled: panel.disabled %>
13
16
  <% end %>
14
17
  <% end %>
15
18
  <% end %>
16
19
 
17
- <% toolbar.section align: :right, padded: true, class: "flex-none min-w-[140px]", ":class": "{invisible: $store.inspector.preview.activeTab !== 'preview'}" do %>
20
+ <% toolbar.section align: :right, padded: true, class: "flex-none min-w-[140px]", ":class": "{invisible: $store.inspector.main.activeTab !== 'preview'}" do %>
18
21
  <%= render_component :dimensions_display,
19
22
  target: "[data-component=viewport] iframe",
20
23
  class: "ml-auto opacity-30 hover:opacity-100" %>
@@ -47,53 +50,57 @@
47
50
  cloak: true %>
48
51
  <% end %>
49
52
  <% end %>
50
- <% end %>
53
+ <% end %>
51
54
 
52
55
  <div class="h-full relative overflow-auto">
53
- <%= render_component :tabbed_content, alpine_data: "$store.inspector.preview" do |content| %>
54
- <%= @preview_panels.each do |key, panel| %>
55
- <% content.section ref: key, class: "overflow-hidden" do %>
56
- <%= render panel[:template],
57
- preview: @preview,
58
- example: @example,
59
- rendered_examples: @rendered_examples,
60
- **panel %>
56
+ <%= render_component :tab_panels, alpine_data: "$store.inspector.main" do |tabs| %>
57
+ <% @main_panels.each do |panel| %>
58
+ <% tabs.panel name: panel.name, class: panel.panel_classes do %>
59
+ <%= render panel.partial, **@inspector_data, panel: panel, **panel.locals %>
61
60
  <% end %>
62
61
  <% end %>
63
62
  <% end %>
64
63
  </div>
65
64
  <% end %>
66
65
 
67
- <%= layout.pane class: "flex flex-col h-full overflow-hidden bg-lookbook-drawer", x_show: "!$store.inspector.drawer.hidden" do %>
66
+ <%= layout.pane class: "flex flex-col h-full overflow-hidden bg-lookbook-drawer",
67
+ x_show: "!$store.inspector.drawer.hidden && #{@drawer_panels.any?}" do %>
68
68
 
69
69
  <%= render_component :toolbar do |toolbar| %>
70
70
  <% toolbar.section ":class": "layoutResizing && 'overflow-hidden'" do %>
71
71
  <%= render_component :tabs, alpine_data: "$store.inspector.drawer" do |tabs| %>
72
- <%= @drawer_panels.each do |key, panel| %>
73
- <% tabs.tab ref: key, **panel.extract!(:label, :hotkey, :disabled) %>
72
+ <%= @drawer_panels.each do |panel| %>
73
+ <% tabs.tab name: panel.name,
74
+ label: panel.label,
75
+ hotkey: panel.hotkey,
76
+ disabled: panel.disabled %>
74
77
  <% end %>
75
78
  <% end %>
76
79
  <% end %>
77
80
 
78
- <% toolbar.section align: :right, divide: :left, class: "flex-none relative z-10" do %>
81
+ <% toolbar.section align: :right, class: "flex-none relative z-10" do %>
79
82
  <%= render_component :button_group do |group| %>
80
-
81
- <%= @drawer_panels.each do |key, panel| %>
82
- <% group.button icon: :clipboard,
83
- tooltip: "Copy to clipboard",
84
- copy: !!panel[:copy],
85
- disabled: panel[:disabled] || !panel[:copy],
86
- x_show: "$store.inspector.drawer.activeTab === '#{key}'",
83
+ <%= @drawer_panels.filter { |p| !p.disabled && p.copy }.each do |panel| %>
84
+ <% group.button icon: :copy,
85
+ tooltip: "Copy panel contents",
86
+ copy: !!panel.copy,
87
+ x_show: "$store.inspector.drawer.activeTab === '#{panel.name}'",
87
88
  cloak: true do %>
88
- <%== panel[:copy] ? panel[:copy] : "" %>
89
+ <%== panel.copy ? panel.copy : "" %>
89
90
  <% end %>
90
- <% end %>
91
+ <% end %>
92
+ <% end %>
93
+ <% end %>
94
+
95
+ <% toolbar.section divide: :left, class: "flex-none relative z-10" do %>
96
+ <%= render_component :button_group do |group| %>
91
97
 
92
98
  <% group.button icon: :corner_up_right,
93
99
  tooltip: "Move drawer to right",
94
100
  "@click": "switchOrientation",
95
101
  x_show: "horizontal && layoutWidth > $store.inspector.minVerticalSplitWidth",
96
102
  cloak: true %>
103
+
97
104
  <% group.button icon: :corner_up_right,
98
105
  x_show: "horizontal && layoutWidth <= $store.inspector.minVerticalSplitWidth",
99
106
  disabled: true,
@@ -114,14 +121,10 @@
114
121
  <% end %>
115
122
 
116
123
  <div class="h-full overflow-auto">
117
- <%= render_component :tabbed_content, alpine_data: "$store.inspector.drawer" do |content| %>
118
- <% @drawer_panels.each do |key, panel| %>
119
- <% content.section ref: key do %>
120
- <%= render panel[:template],
121
- preview: @preview,
122
- example: @example,
123
- rendered_examples: @rendered_examples,
124
- **panel %>
124
+ <%= render_component :tab_panels, alpine_data: "$store.inspector.drawer" do |tabs| %>
125
+ <% @drawer_panels.each do |panel| %>
126
+ <% tabs.panel name: panel.name do %>
127
+ <%= render panel.partial, **@inspector_data, panel: panel, **panel.locals %>
125
128
  <% end %>
126
129
  <% end %>
127
130
  <% end %>
@@ -1,24 +1,13 @@
1
1
  require "lookbook/markdown"
2
+ require "lookbook/theme"
3
+ require "lookbook/store"
2
4
 
3
5
  module Lookbook
4
- class ConfigOptions < ActiveSupport::OrderedOptions
5
- def initialize(**data)
6
- super()
7
- data.keys.each { |key| self[key.to_sym] = data[key] }
8
- end
9
-
10
- def [](key)
11
- super(key.to_sym)
12
- end
13
-
14
- def []=(key, value)
15
- super(key.to_sym, value)
16
- end
17
- end
18
-
19
6
  class Config
20
7
  def initialize
21
- @store = ConfigOptions.new(**{
8
+ @options = Store.new
9
+ foobar = "bax"
10
+ @options.set({
22
11
  project_name: "Lookbook",
23
12
  log_level: 2,
24
13
  auto_refresh: true,
@@ -26,12 +15,12 @@ module Lookbook
26
15
  page_controller: "Lookbook::PageController",
27
16
  page_route: "pages",
28
17
  page_paths: ["test/components/docs"],
29
- page_options: ConfigOptions.new,
30
- markdown_options: ConfigOptions.new(**Markdown::DEFAULT_OPTIONS),
18
+ page_options: {},
19
+ markdown_options: Markdown::DEFAULT_OPTIONS,
31
20
 
32
21
  preview_paths: [],
33
- preview_display_params: ConfigOptions.new,
34
- preview_options: ConfigOptions.new,
22
+ preview_display_params: {},
23
+ preview_options: {},
35
24
  preview_srcdoc: false,
36
25
  sort_examples: true,
37
26
 
@@ -46,22 +35,83 @@ module Lookbook
46
35
  parser_registry_path: "tmp/storage/.yardoc",
47
36
 
48
37
  ui_theme: "indigo",
49
- ui_theme_overrides: ConfigOptions.new,
38
+ ui_theme_overrides: {},
39
+
40
+ inspector_panels: {
41
+ preview: {
42
+ pane: :main,
43
+ position: 1,
44
+ partial: "lookbook/previews/panels/preview",
45
+ hotkey: "v",
46
+ panel_classes: "overflow-hidden"
47
+ },
48
+ output: {
49
+ pane: :main,
50
+ position: 2,
51
+ partial: "lookbook/previews/panels/output",
52
+ label: "HTML",
53
+ hotkey: "h",
54
+ },
55
+ source: {
56
+ pane: :drawer,
57
+ position: 1,
58
+ partial: "lookbook/previews/panels/source",
59
+ label: "Source",
60
+ hotkey: "s",
61
+ copy: ->(data) { data.examples.map { |e| e[:source] }.join("\n") }
62
+ },
63
+ notes: {
64
+ pane: :drawer,
65
+ position: 2,
66
+ partial: "lookbook/previews/panels/notes",
67
+ label: "Notes",
68
+ hotkey: "n",
69
+ disabled: ->(data) { data.examples.filter { |e| e.notes.present? }.none? }
70
+ },
71
+ params: {
72
+ pane: :drawer,
73
+ position: 3,
74
+ partial: "lookbook/previews/panels/params",
75
+ label: "Params",
76
+ hotkey: "p",
77
+ disabled: ->(data) { data.preview.params.none? }
78
+ }
79
+ },
80
+
81
+ inspector_panel_defaults: {
82
+ id: ->(data) { "inspector-panel-#{data.name}" },
83
+ partial: "lookbook/previews/panels/content",
84
+ content: nil,
85
+ label: ->(data) { data.name.titleize },
86
+ pane: :drawer,
87
+ position: ->(data) { data.index_position },
88
+ hotkey: nil,
89
+ disabled: false,
90
+ show: true,
91
+ copy: nil,
92
+ panel_classes: nil,
93
+ locals: {}
94
+ },
95
+
50
96
  experimental_features: false,
51
97
  })
52
98
  end
53
99
 
54
- def ui_theme=(name)
55
- name = name.to_s
56
- if ["indigo", "zinc", "blue"].include?(name)
57
- @store[:ui_theme] = name
100
+ def inspector_panels(&block)
101
+ if block_given?
102
+ yield get(:inspector_panels)
58
103
  else
59
- Lookbook.logger.warn "'#{name}' is not a valid Lookbook theme. Falling back to default."
104
+ get(:inspector_panels)
60
105
  end
61
106
  end
62
107
 
63
- def ui_theme_overrides=(theme)
64
- @store[:ui_theme_overrides] = ConfigOptions.new(theme)
108
+ def ui_theme=(name)
109
+ name = name.to_s
110
+ if Theme.valid_theme?(name)
111
+ @options[:ui_theme] = name
112
+ else
113
+ Lookbook.logger.warn "'#{name}' is not a valid Lookbook theme. Theme setting not changed."
114
+ end
65
115
  end
66
116
 
67
117
  def ui_theme_overrides(&block)
@@ -77,11 +127,11 @@ module Lookbook
77
127
  end
78
128
 
79
129
  def []=(key, value)
80
- @store[key.to_sym] = value
130
+ @options[key.to_sym] = value
81
131
  end
82
132
 
83
133
  def to_h
84
- @store.to_h
134
+ @options.to_h
85
135
  end
86
136
 
87
137
  def to_json(*a)
@@ -90,6 +140,11 @@ module Lookbook
90
140
 
91
141
  protected
92
142
 
143
+ def get_inspector_panels(panels)
144
+ panels.filter! { |key, panel| panel }
145
+ panels
146
+ end
147
+
93
148
  def get_project_name(name)
94
149
  name == false ? nil : name
95
150
  end
@@ -111,11 +166,11 @@ module Lookbook
111
166
 
112
167
  def get(name)
113
168
  getter_name = "get_#{name}".to_sym
114
- respond_to?(getter_name, true) ? send(getter_name, @store[name]) : @store[name]
169
+ respond_to?(getter_name, true) ? send(getter_name, @options[name]) : @options[name]
115
170
  end
116
171
 
117
172
  def set(name, *args)
118
- @store.send(name, *args)
173
+ @options.send(name, *args)
119
174
  end
120
175
 
121
176
  def method_missing(name, *args)