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

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 (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)