lookbook 1.0.0.beta.0 → 1.0.0.beta.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +231 -9
  3. data/app/assets/lookbook/js/stores/inspector.js +4 -4
  4. data/app/components/lookbook/{component.rb → base_component.rb} +1 -1
  5. data/app/components/lookbook/button/component.rb +1 -1
  6. data/app/components/lookbook/button_group/component.rb +1 -1
  7. data/app/components/lookbook/code/component.rb +1 -1
  8. data/app/components/lookbook/copy_button/component.html.erb +1 -1
  9. data/app/components/lookbook/copy_button/component.rb +1 -1
  10. data/app/components/lookbook/dimensions_display/component.html.erb +2 -1
  11. data/app/components/lookbook/dimensions_display/component.js +19 -12
  12. data/app/components/lookbook/dimensions_display/component.rb +1 -1
  13. data/app/components/lookbook/embed/component.html.erb +6 -5
  14. data/app/components/lookbook/embed/component.rb +1 -1
  15. data/app/components/lookbook/filter/component.html.erb +1 -1
  16. data/app/components/lookbook/filter/component.rb +1 -1
  17. data/app/components/lookbook/header/component.html.erb +7 -12
  18. data/app/components/lookbook/header/component.rb +1 -1
  19. data/app/components/lookbook/icon/component.rb +1 -1
  20. data/app/components/lookbook/nav/component.rb +1 -1
  21. data/app/components/lookbook/nav/item/component.html.erb +2 -2
  22. data/app/components/lookbook/nav/item/component.rb +1 -1
  23. data/app/components/lookbook/page_tabs/component.html.erb +18 -0
  24. data/app/components/lookbook/page_tabs/component.rb +19 -0
  25. data/app/components/lookbook/params_editor/component.rb +1 -1
  26. data/app/components/lookbook/params_editor/field/component.rb +1 -1
  27. data/app/components/lookbook/prose/component.rb +1 -1
  28. data/app/components/lookbook/split_layout/component.rb +1 -1
  29. data/app/components/lookbook/tab_panels/component.html.erb +5 -0
  30. data/app/components/lookbook/tab_panels/component.js +25 -0
  31. data/app/components/lookbook/tab_panels/component.rb +20 -0
  32. data/app/components/lookbook/{tabbed_content/section → tab_panels/panel}/component.html.erb +2 -2
  33. data/app/components/lookbook/tab_panels/panel/component.rb +9 -0
  34. data/app/components/lookbook/tabs/component.html.erb +8 -2
  35. data/app/components/lookbook/tabs/component.js +14 -6
  36. data/app/components/lookbook/tabs/component.rb +9 -11
  37. data/app/components/lookbook/tabs/dropdown_tab/component.html.erb +8 -2
  38. data/app/components/lookbook/tabs/dropdown_tab/component.rb +5 -4
  39. data/app/components/lookbook/tabs/tab/component.html.erb +9 -3
  40. data/app/components/lookbook/tabs/tab/component.rb +5 -4
  41. data/app/components/lookbook/toolbar/component.css +1 -1
  42. data/app/components/lookbook/toolbar/component.rb +1 -1
  43. data/app/components/lookbook/viewport/component.rb +1 -1
  44. data/app/controllers/lookbook/application_controller.rb +2 -2
  45. data/app/controllers/lookbook/pages_controller.rb +2 -1
  46. data/app/controllers/lookbook/previews_controller.rb +90 -91
  47. data/app/helpers/lookbook/application_helper.rb +8 -2
  48. data/app/helpers/lookbook/component_helper.rb +4 -0
  49. data/app/helpers/lookbook/page_helper.rb +2 -2
  50. data/app/views/layouts/lookbook/application.html.erb +1 -1
  51. data/app/views/layouts/lookbook/page.html.erb +2 -2
  52. data/app/views/layouts/lookbook/shell.html.erb +1 -1
  53. data/app/views/layouts/lookbook/skeleton.html.erb +7 -1
  54. data/app/views/lookbook/404.html.erb +1 -1
  55. data/app/views/lookbook/index.html.erb +1 -1
  56. data/app/views/lookbook/pages/show.html.erb +15 -5
  57. data/app/views/lookbook/preview.html.erb +3 -3
  58. data/app/views/lookbook/previews/panels/_content.html.erb +13 -0
  59. data/app/views/lookbook/previews/panels/_notes.html.erb +5 -5
  60. data/app/views/lookbook/previews/panels/_output.html.erb +3 -3
  61. data/app/views/lookbook/previews/panels/_params.html.erb +2 -2
  62. data/app/views/lookbook/previews/panels/_preview.html.erb +2 -2
  63. data/app/views/lookbook/previews/panels/_source.html.erb +6 -6
  64. data/app/views/lookbook/previews/show.html.erb +39 -36
  65. data/config/routes.rb +6 -6
  66. data/lib/lookbook/collection.rb +1 -1
  67. data/lib/lookbook/component.rb +31 -0
  68. data/lib/lookbook/config.rb +133 -33
  69. data/lib/lookbook/engine.rb +72 -12
  70. data/lib/lookbook/page.rb +34 -11
  71. data/lib/lookbook/page_section.rb +31 -0
  72. data/lib/lookbook/parser.rb +1 -4
  73. data/lib/lookbook/preview.rb +25 -8
  74. data/lib/lookbook/preview_example.rb +2 -2
  75. data/lib/lookbook/preview_group.rb +1 -1
  76. data/lib/lookbook/source_inspector.rb +10 -0
  77. data/lib/lookbook/store.rb +36 -0
  78. data/lib/lookbook/theme.rb +7 -0
  79. data/lib/lookbook/utils.rb +3 -3
  80. data/lib/lookbook/version.rb +1 -1
  81. data/lib/lookbook.rb +3 -12
  82. data/public/lookbook-assets/css/lookbook.css +34 -5
  83. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  84. data/public/lookbook-assets/js/lookbook.js +84 -71
  85. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  86. metadata +14 -8
  87. data/app/components/lookbook/tabbed_content/component.html.erb +0 -5
  88. data/app/components/lookbook/tabbed_content/component.js +0 -21
  89. data/app/components/lookbook/tabbed_content/component.rb +0 -20
  90. data/app/components/lookbook/tabbed_content/section/component.rb +0 -9
@@ -0,0 +1,25 @@
1
+ export default function tabPanelsComponent(store) {
2
+ return {
3
+ get store() {
4
+ return store || this;
5
+ },
6
+
7
+ get id() {
8
+ return this.$root.id;
9
+ },
10
+
11
+ get panels() {
12
+ return Array.from(this.$refs.panels.children);
13
+ },
14
+
15
+ isActive(el) {
16
+ return this.store.activeTab === this._getRef(el);
17
+ },
18
+
19
+ // protected
20
+
21
+ _getRef(el) {
22
+ return el.getAttribute("x-ref");
23
+ },
24
+ };
25
+ }
@@ -0,0 +1,20 @@
1
+ module Lookbook
2
+ class TabPanels::Component < Lookbook::BaseComponent
3
+ renders_many :panels, ->(**attrs) do
4
+ @panel_counter += 1
5
+ attrs[:name] ||= "tab-#{@panel_counter}"
6
+ Lookbook::TabPanels::Panel::Component.new **attrs
7
+ end
8
+
9
+ def initialize(**html_attrs)
10
+ @panel_counter = 0
11
+ super(**html_attrs)
12
+ end
13
+
14
+ protected
15
+
16
+ def alpine_component
17
+ "tabPanelsComponent"
18
+ end
19
+ end
20
+ end
@@ -1,8 +1,8 @@
1
1
  <%= render_component_tag :section,
2
2
  id: @id,
3
- x_ref: @ref,
3
+ x_ref: @name,
4
4
  x_cloak: true,
5
5
  class: "h-full",
6
6
  ":class": "{ hidden: !isActive($el) }" do %>
7
- <%= content %>
7
+ <%== content %>
8
8
  <% end %>
@@ -0,0 +1,9 @@
1
+ module Lookbook
2
+ class TabPanels::Panel::Component < Lookbook::BaseComponent
3
+ def initialize(name:, id: nil, **html_attrs)
4
+ @name = name
5
+ @id = "#{id || "panel-#{name}"}"
6
+ super(**html_attrs)
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,11 @@
1
- <%= render_component_tag class: "px-4 flex items-center relative" do %>
2
- <div x-ref="tabs" class="flex items-stretch h-10 space-x-6 select-none min-w-0">
1
+ <%= render_component_tag class: "flex items-center relative" do %>
2
+ <div x-ref="tabs" class="<%= class_names [
3
+ "flex items-stretch select-none min-w-0",
4
+ {
5
+ "h-10 space-x-6": @theme == :toolbar,
6
+ "space-x-3": @theme == :page,
7
+ }
8
+ ] %>">
3
9
  <%= safe_join(tabs) %>
4
10
  </div>
5
11
  <div x-ref="dropdownTrigger" class="absolute" x-show="hasHiddenTabs" :style="{left: `${triggerLeft}px`}">
@@ -4,15 +4,19 @@ import { observeSize } from "@helpers/layout";
4
4
  import { getElementSize } from "@helpers/dom";
5
5
 
6
6
  export default function tabsComponent(store) {
7
- const initial = store.activeTab || null;
7
+ const initial = store ? store.activeTab : null;
8
8
  let dropdown = null;
9
9
  return {
10
10
  visibleTabsCount: 0,
11
11
 
12
12
  triggerLeft: 0,
13
13
 
14
+ get store() {
15
+ return store || this;
16
+ },
17
+
14
18
  get tabs() {
15
- return Array.from(this.$refs.tabs.children);
19
+ return this.$refs.tabs ? Array.from(this.$refs.tabs.children) : [];
16
20
  },
17
21
 
18
22
  get dropdownTabs() {
@@ -34,13 +38,14 @@ export default function tabsComponent(store) {
34
38
  theme: "menu",
35
39
  interactive: true,
36
40
  trigger: "click",
41
+ placement: "bottom",
37
42
  appendTo: this.$root,
38
43
  });
39
44
 
40
45
  const initialTab = initial
41
46
  ? this.tabs.find((t) => this._getRef(t) === initial)
42
47
  : this.tabs[0];
43
- this.selectTab(initialTab);
48
+ this.selectTab(initialTab, true);
44
49
 
45
50
  this.parentObserver = observeSize(
46
51
  this.$root.parentElement,
@@ -79,13 +84,16 @@ export default function tabsComponent(store) {
79
84
  this._lastMeasuredWidth = width;
80
85
  },
81
86
 
82
- selectTab(el) {
83
- store.activeTab = this._getRef(el);
87
+ selectTab(el, initial = false) {
88
+ this.store.activeTab = this._getRef(el);
84
89
  dropdown.hide();
90
+ if (!initial) {
91
+ this.$dispatch("tabs:change", { tabs: this });
92
+ }
85
93
  },
86
94
 
87
95
  isSelected(el) {
88
- return store.activeTab === this._getRef(el);
96
+ return this.store.activeTab === this._getRef(el);
89
97
  },
90
98
 
91
99
  isDisabled(el) {
@@ -1,22 +1,20 @@
1
1
  module Lookbook
2
- class Tabs::Component < Lookbook::Component
3
- renders_many :tabs, ->(ref: nil, **attrs) do
2
+ class Tabs::Component < Lookbook::BaseComponent
3
+ renders_many :tabs, ->(**attrs) do
4
4
  @tab_counter += 1
5
- ref ||= "tab-#{@tab_counter}"
6
- attrs = {
7
- ref: ref,
8
- position: @tab_counter,
9
- **attrs
10
- }
5
+ attrs[:name] ||= "tab-#{@tab_counter}"
6
+ attrs[:position] ||= @tab_counter
7
+ attrs[:theme] ||= @theme
11
8
  dropdown_tab(**attrs)
12
9
  Lookbook::Tabs::Tab::Component.new(**attrs)
13
10
  end
14
11
 
15
- renders_many :dropdown_tabs, ->(ref:, **attrs) do
16
- Lookbook::Tabs::DropdownTab::Component.new(ref: "dropdown-#{ref}", **attrs)
12
+ renders_many :dropdown_tabs, ->(name:, **attrs) do
13
+ Lookbook::Tabs::DropdownTab::Component.new(name: "dropdown-#{name}", **attrs)
17
14
  end
18
15
 
19
- def initialize(**html_attrs)
16
+ def initialize(theme: :toolbar, **html_attrs)
17
+ @theme = theme
20
18
  @tab_counter = 0
21
19
  super(**html_attrs)
22
20
  end
@@ -1,6 +1,12 @@
1
1
  <%= render_component_tag :button,
2
- x_ref: @ref,
3
- class: "whitespace-nowrap px-4 py-2 border-l-2 cursor-pointer block w-full text-left",
2
+ x_ref: @name,
3
+ class: [
4
+ "whitespace-nowrap px-4 border-l-2 cursor-pointer block w-full text-left",
5
+ {
6
+ "py-2": @theme == :toolbar,
7
+ "py-2 text-base": @theme == :page,
8
+ }
9
+ ],
4
10
  ":class": "{
5
11
  'border-lookbook-tabs-highlight': isSelected($el),
6
12
  'border-transparent text-lookbook-tabs-text hover:text-lookbook-tabs-text-hover': !isSelected($el),
@@ -1,16 +1,17 @@
1
1
  module Lookbook
2
- class Tabs::DropdownTab::Component < Lookbook::Component
3
- def initialize(ref:, label: nil, hotkey: nil, disabled: nil, position: 0, **html_attrs)
4
- @ref = ref
2
+ class Tabs::DropdownTab::Component < Lookbook::BaseComponent
3
+ def initialize(name:, label: nil, hotkey: nil, disabled: nil, position: 0, theme: :toolbar, **html_attrs)
4
+ @name = name
5
5
  @label = label
6
6
  @hotkey = hotkey
7
7
  @disabled = disabled
8
8
  @position = position
9
+ @theme = theme
9
10
  super(**html_attrs)
10
11
  end
11
12
 
12
13
  def label
13
- @label.presence || content
14
+ @label.presence || content || @name.titleize
14
15
  end
15
16
  end
16
17
  end
@@ -1,7 +1,13 @@
1
1
  <%= render_component_tag :button,
2
2
  id: @id,
3
- x_ref: @ref,
4
- class: "whitespace-nowrap pt-2.5 pb-1.5 px-1 border-b-2 cursor-pointer",
3
+ x_ref: @name,
4
+ class: [
5
+ "whitespace-nowrap cursor-pointer pt-2.5 pb-1.5 border-b-2",
6
+ {
7
+ "px-1": @theme == :toolbar,
8
+ "px-2 text-lg relative -bottom-px": @theme == :page,
9
+ }
10
+ ],
5
11
  ":class": "{
6
12
  'border-lookbook-tabs-highlight': isSelected($el),
7
13
  'border-transparent text-lookbook-tabs-text hover:text-lookbook-tabs-text-hover': !isSelected($el),
@@ -14,5 +20,5 @@
14
20
  disabled: @disabled
15
21
  },
16
22
  cloak: true do %>
17
- <%= label %>
23
+ <%== label %>
18
24
  <% end %>
@@ -1,16 +1,17 @@
1
1
  module Lookbook
2
- class Tabs::Tab::Component < Lookbook::Component
3
- def initialize(ref:, label: nil, hotkey: nil, disabled: nil, position: 0, **html_attrs)
4
- @ref = ref
2
+ class Tabs::Tab::Component < Lookbook::BaseComponent
3
+ def initialize(name:, label: nil, hotkey: nil, disabled: nil, position: 0, theme: :toolbar, **html_attrs)
4
+ @name = name
5
5
  @label = label
6
6
  @hotkey = hotkey
7
7
  @disabled = disabled
8
8
  @position = position
9
+ @theme = theme
9
10
  super(**html_attrs)
10
11
  end
11
12
 
12
13
  def label
13
- @label.presence || content
14
+ @label.presence || content || @name.titleize
14
15
  end
15
16
  end
16
17
  end
@@ -10,7 +10,7 @@
10
10
  }
11
11
 
12
12
  & [data-component="tabs"] {
13
- @apply relative -mb-px;
13
+ @apply relative -mb-px px-4;
14
14
  }
15
15
  }
16
16
  }
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Toolbar::Component < Lookbook::Component
2
+ class Toolbar::Component < Lookbook::BaseComponent
3
3
  DIVIDE_CLASSES = {
4
4
  left: "border-l",
5
5
  right: "border-r"
@@ -1,5 +1,5 @@
1
1
  module Lookbook
2
- class Viewport::Component < Lookbook::Component
2
+ class Viewport::Component < Lookbook::BaseComponent
3
3
  def initialize(src:, resize_height: true, resize_width: true, max_height: nil, **html_attrs)
4
4
  @src = src
5
5
  @resize_height = resize_height
@@ -15,7 +15,7 @@ module Lookbook
15
15
  def index
16
16
  landing = Lookbook.pages.find(&:landing) || Lookbook.pages.first
17
17
  if landing.present?
18
- redirect_to page_path(landing.lookup_path)
18
+ redirect_to lookbook_page_path(landing.lookup_path)
19
19
  else
20
20
  render "lookbook/index", layout: Lookbook.previews.any? ? "lookbook/application" : "lookbook/shell"
21
21
  end
@@ -24,7 +24,7 @@ module Lookbook
24
24
  protected
25
25
 
26
26
  def generate_theme_overrides
27
- @theme_overrides = Lookbook::Theme.new(Lookbook.config.ui_theme_overrides).to_css
27
+ @theme_overrides ||= Lookbook::Theme.new(Lookbook.config.ui_theme_overrides).to_css
28
28
  end
29
29
 
30
30
  def feature_enabled?(feature)
@@ -1,6 +1,7 @@
1
1
  module Lookbook
2
2
  class PagesController < ApplicationController
3
3
  layout "lookbook/page"
4
+ helper_method :page_controller
4
5
 
5
6
  def self.controller_path
6
7
  "lookbook/pages"
@@ -9,7 +10,7 @@ module Lookbook
9
10
  def index
10
11
  landing = Lookbook.pages.find(&:landing) || Lookbook.pages.first
11
12
  if landing.present?
12
- redirect_to page_path landing.lookup_path
13
+ redirect_to lookbook_page_path landing.lookup_path
13
14
  else
14
15
  show_404
15
16
  end
@@ -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
@@ -41,7 +44,7 @@ module Lookbook
41
44
 
42
45
  def show_legacy
43
46
  Lookbook.logger.warn("Legacy URL path detected. These paths are deprecated and will be removed in a future version")
44
- redirect_to inspect_path params[:path]
47
+ redirect_to lookbook_inspect_path params[:path]
45
48
  end
46
49
 
47
50
  private
@@ -51,13 +54,13 @@ module Lookbook
51
54
  if @example.present?
52
55
  @preview = @example.preview
53
56
  if params[:path] == @preview&.lookup_path
54
- redirect_to inspect_path "#{params[:path]}/#{@preview.default_example.name}"
57
+ redirect_to lookbook_inspect_path "#{params[:path]}/#{@preview.default_example.name}"
55
58
  end
56
59
  else
57
60
  @preview = Lookbook.previews.find(params[:path])
58
61
  if @preview.present?
59
62
  first_example = @preview.examples.first
60
- redirect_to inspect_path(first_example.lookup_path) if first_example
63
+ redirect_to lookbook_inspect_path(first_example.lookup_path) if first_example
61
64
  else
62
65
  @preview = Lookbook.previews.find(path_segments.slice(0, path_segments.size - 1).join("/"))
63
66
  end
@@ -79,107 +82,103 @@ 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
+ })
89
107
  end
90
108
  end
91
109
 
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
103
- }
104
- end
105
-
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
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 }
110
114
  end
111
- preview_controller.process(:render_in_layout_to_string, "lookbook/preview", {examples: examples}, **opts)
112
115
  end
113
116
 
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])
119
- end
117
+ def inspector_data
118
+ return @inspector_data if @inspector_data.present?
119
+
120
+ context_data = {
121
+ preview_params: preview_params,
122
+ path: params[:path],
123
+ }
124
+
125
+ example = @example
126
+ preview = @preview
127
+ preview.define_singleton_method(:params, proc {
128
+ example.params
129
+ })
130
+
131
+ examples = target_examples.map do |example|
132
+ render_args = @preview.render_args(example.name, params: preview_controller.params)
133
+ has_template = render_args[:template] != "view_components/preview"
134
+ output = preview_controller.process(:render_example_to_string, @preview, example.name)
135
+ source = has_template ? example.template_source(render_args[:template]) : example.method_source
136
+ source_lang = has_template ? example.template_lang(render_args[:template]) : example.lang
137
+
138
+ example.define_singleton_method(:output, proc { output })
139
+ example.define_singleton_method(:source, proc { source })
140
+ example.define_singleton_method(:source_lang, proc { source_lang })
141
+ example
120
142
  end
121
143
 
122
- # set display params
123
- preview_controller.params.merge!({
124
- lookbook: {
125
- display: @example.display_params
126
- }
144
+ @inspector_data ||= Lookbook::Store.new({
145
+ context: context_data,
146
+ preview: preview,
147
+ examples: examples,
148
+ components: preview.components,
149
+ app: Lookbook
127
150
  })
128
151
  end
129
152
 
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
153
+ def panels
154
+ return @panels if @panels.present?
155
+ @panels = []
156
+ Lookbook.config.inspector_panels.each do |name, config|
157
+ config_with_defaults = Lookbook.config.inspector_panel_defaults.merge(config)
158
+
159
+ callable_data = {
160
+ name: name.to_s,
161
+ index_position: (@panels.select { |p| p.pane == config.pane }.size + 1),
162
+ **inspector_data
149
163
  }
150
- }
164
+
165
+ resolved_config = config_with_defaults.transform_values do |value|
166
+ value.class == Proc ? value.call(Lookbook::Store.new(callable_data)) : value
167
+ end
168
+ resolved_config[:name] = name.to_s
169
+
170
+ @panels << Lookbook::Store.new(resolved_config, deep: false)
171
+ end
172
+
173
+ @panels = @panels.select(&:show).sort_by { |p| [p.position, p.label] }
174
+ end
175
+
176
+ def main_panels
177
+ panels.select { |panel| panel.pane == :main }
151
178
  end
152
179
 
153
180
  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
- }
181
+ panels.select { |panel| panel.pane == :drawer }
183
182
  end
184
183
 
185
184
  def preview_controller
@@ -11,14 +11,20 @@ module Lookbook
11
11
  def landing_path
12
12
  landing = Lookbook.pages.find(&:landing) || Lookbook.pages.first
13
13
  if landing.present?
14
- page_path(landing.lookup_path)
14
+ lookbook_page_path landing.lookup_path
15
15
  else
16
- home_path
16
+ lookbook_home_path
17
17
  end
18
18
  end
19
19
 
20
20
  def generate_id(*args)
21
21
  args.map { |args| args.delete_prefix("/").tr("&?=/_\-", "-") }.join("-")
22
22
  end
23
+
24
+ def append_styles(&block)
25
+ content_for :styles do
26
+ capture(&block)
27
+ end
28
+ end
23
29
  end
24
30
  end
@@ -2,6 +2,10 @@ module Lookbook
2
2
  module ComponentHelper
3
3
  COMPONENT_CLASSES = {} # cache for constantized references
4
4
 
5
+ def icon(name, **attrs)
6
+ render Lookbook::Icon::Component.new(name: name, **attrs)
7
+ end
8
+
5
9
  def render_component(ref, **attrs, &block)
6
10
  klass = component_class(ref)
7
11
  comp = attrs.key?(:content) ? klass.new(**attrs.except(:content)).with_content(attrs[:content]) : klass.new(**attrs)
@@ -5,7 +5,7 @@ module Lookbook
5
5
  def page_path(id)
6
6
  page = id.is_a?(Page) ? id : Lookbook.pages.find(id)
7
7
  if page.present?
8
- lookbook.page_path page.lookup_path
8
+ lookbook_page_path page.lookup_path
9
9
  else
10
10
  Lookbook.logger.warn "Could not find page with id ':#{id}'"
11
11
  end
@@ -16,7 +16,7 @@ module Lookbook
16
16
 
17
17
  @embed_counter ||= 0
18
18
 
19
- preview_lookup = args.first.is_a?(Symbol) ? args.first : preview_class_name(args.first)
19
+ preview_lookup = args.first.is_a?(Symbol) ? args.first : preview_class_path(args.first)
20
20
  preview = Lookbook.previews.find(preview_lookup)
21
21
  example = args[1] ? preview&.example(args[1]) : preview&.default_example
22
22
 
@@ -40,7 +40,7 @@
40
40
  <div x-data="{hidden: false}" class="flex-none border-t border-lookbook-divider absolute bottom-0 left-0 right-0" x-show="!hidden">
41
41
  <%= render_component :toolbar do |toolbar| %>
42
42
  <% toolbar.section padded: true, class: "flex items-center" do %>
43
- <%= render_component :icon, name: :alert_triangle, size: 4, class: "text-red-700" %>
43
+ <%= icon :alert_triangle, size: 4, class: "text-red-700" %>
44
44
  <span class="ml-2">Preview load errors</span>
45
45
  <% end %>
46
46
  <% toolbar.section align: :right do %>
@@ -16,7 +16,7 @@
16
16
  size: :lg,
17
17
  icon: :chevron_left,
18
18
  tooltip: "Previous page",
19
- href: page_path(@previous_page.lookup_path),
19
+ href: lookbook_page_path(@previous_page.lookup_path),
20
20
  class: "pr-0.5 bg-transparent" %>
21
21
  <% else %>
22
22
  <%= render_component :button,
@@ -31,7 +31,7 @@
31
31
  size: :lg,
32
32
  icon: :chevron_right,
33
33
  tooltip: "Next page",
34
- href: page_path(@next_page.lookup_path),
34
+ href: lookbook_page_path(@next_page.lookup_path),
35
35
  class: "pl-0.5 bg-transparent" %>
36
36
  <% else %>
37
37
  <%= render_component :button,
@@ -28,7 +28,7 @@
28
28
  <span class="opacity-60 mr-1">Lookbook</span>
29
29
  <span class="mr-6">v<%= Lookbook::VERSION %></span>
30
30
  <a href="https://github.com/allmarkedup/lookbook" target="_blank" class="ml-auto opacity-70">
31
- <%= render_component :icon, name: :github, size: 3 %>
31
+ <%= icon :github, size: 3 %>
32
32
  </a>
33
33
  </div>
34
34
  <div class="px-3 py-2">