lookbook 1.0.0.beta.1 → 1.0.0.beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +180 -40
  3. data/app/components/lookbook/{component.rb → base_component.rb} +1 -1
  4. data/app/components/lookbook/button/component.rb +1 -1
  5. data/app/components/lookbook/button_group/component.rb +1 -1
  6. data/app/components/lookbook/code/component.rb +1 -1
  7. data/app/components/lookbook/copy_button/component.html.erb +1 -1
  8. data/app/components/lookbook/copy_button/component.rb +1 -1
  9. data/app/components/lookbook/dimensions_display/component.rb +1 -1
  10. data/app/components/lookbook/embed/component.html.erb +6 -5
  11. data/app/components/lookbook/embed/component.rb +1 -1
  12. data/app/components/lookbook/filter/component.html.erb +1 -1
  13. data/app/components/lookbook/filter/component.rb +1 -1
  14. data/app/components/lookbook/header/component.html.erb +6 -11
  15. data/app/components/lookbook/header/component.rb +6 -1
  16. data/app/components/lookbook/icon/component.rb +1 -1
  17. data/app/components/lookbook/nav/component.rb +1 -1
  18. data/app/components/lookbook/nav/item/component.html.erb +2 -2
  19. data/app/components/lookbook/nav/item/component.rb +1 -1
  20. data/app/components/lookbook/page_tabs/component.rb +1 -1
  21. data/app/components/lookbook/params_editor/component.rb +1 -1
  22. data/app/components/lookbook/params_editor/field/component.rb +1 -1
  23. data/app/components/lookbook/prose/component.rb +1 -1
  24. data/app/components/lookbook/split_layout/component.rb +1 -1
  25. data/app/components/lookbook/tab_panels/component.rb +1 -1
  26. data/app/components/lookbook/tab_panels/panel/component.rb +2 -2
  27. data/app/components/lookbook/tabs/component.js +6 -6
  28. data/app/components/lookbook/tabs/component.rb +1 -1
  29. data/app/components/lookbook/tabs/dropdown_tab/component.rb +1 -1
  30. data/app/components/lookbook/tabs/tab/component.rb +1 -1
  31. data/app/components/lookbook/toolbar/component.rb +1 -1
  32. data/app/components/lookbook/viewport/component.rb +1 -1
  33. data/app/controllers/lookbook/application_controller.rb +1 -1
  34. data/app/controllers/lookbook/pages_controller.rb +1 -1
  35. data/app/controllers/lookbook/previews_controller.rb +27 -32
  36. data/app/helpers/lookbook/application_helper.rb +8 -2
  37. data/app/helpers/lookbook/component_helper.rb +4 -0
  38. data/app/helpers/lookbook/page_helper.rb +2 -2
  39. data/app/views/layouts/lookbook/application.html.erb +5 -3
  40. data/app/views/layouts/lookbook/page.html.erb +2 -2
  41. data/app/views/layouts/lookbook/shell.html.erb +2 -48
  42. data/app/views/layouts/lookbook/skeleton.html.erb +7 -1
  43. data/app/views/lookbook/404.html.erb +1 -1
  44. data/app/views/lookbook/index.html.erb +1 -1
  45. data/app/views/lookbook/pages/show.html.erb +8 -8
  46. data/app/views/lookbook/previews/panels/_notes.html.erb +1 -1
  47. data/app/views/lookbook/previews/panels/_preview.html.erb +1 -1
  48. data/app/views/lookbook/previews/show.html.erb +4 -4
  49. data/config/routes.rb +6 -6
  50. data/lib/lookbook/collection.rb +1 -1
  51. data/lib/lookbook/component.rb +31 -0
  52. data/lib/lookbook/config.rb +94 -41
  53. data/lib/lookbook/engine.rb +72 -12
  54. data/lib/lookbook/page.rb +3 -3
  55. data/lib/lookbook/parser.rb +1 -4
  56. data/lib/lookbook/preview.rb +25 -8
  57. data/lib/lookbook/preview_example.rb +2 -2
  58. data/lib/lookbook/preview_group.rb +1 -1
  59. data/lib/lookbook/source_inspector.rb +10 -0
  60. data/lib/lookbook/utils.rb +2 -2
  61. data/lib/lookbook/version.rb +1 -1
  62. data/lib/lookbook.rb +1 -12
  63. data/public/lookbook-assets/css/lookbook.css +24 -28
  64. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  65. data/public/lookbook-assets/js/lookbook.js +50 -49
  66. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  67. metadata +3 -2
@@ -6,11 +6,13 @@ module Lookbook
6
6
  class Config
7
7
  def initialize
8
8
  @options = Store.new
9
- foobar = "bax"
9
+
10
10
  @options.set({
11
11
  project_name: "Lookbook",
12
12
  log_level: 2,
13
13
  auto_refresh: true,
14
+
15
+ components_path: "app/components",
14
16
 
15
17
  page_controller: "Lookbook::PageController",
16
18
  page_route: "pages",
@@ -37,13 +39,24 @@ module Lookbook
37
39
  ui_theme: "indigo",
38
40
  ui_theme_overrides: {},
39
41
 
42
+ hooks: {
43
+ after_initialize: [],
44
+ before_exit: [],
45
+ after_change: [],
46
+ },
47
+
48
+ debug_menu: Rails.env.development?,
49
+
50
+ experimental_features: false,
51
+
40
52
  inspector_panels: {
41
53
  preview: {
42
54
  pane: :main,
43
55
  position: 1,
44
56
  partial: "lookbook/previews/panels/preview",
45
57
  hotkey: "v",
46
- panel_classes: "overflow-hidden"
58
+ panel_classes: "overflow-hidden",
59
+ padded: false
47
60
  },
48
61
  output: {
49
62
  pane: :main,
@@ -51,6 +64,7 @@ module Lookbook
51
64
  partial: "lookbook/previews/panels/output",
52
65
  label: "HTML",
53
66
  hotkey: "h",
67
+ padded: false
54
68
  },
55
69
  source: {
56
70
  pane: :drawer,
@@ -58,7 +72,8 @@ module Lookbook
58
72
  partial: "lookbook/previews/panels/source",
59
73
  label: "Source",
60
74
  hotkey: "s",
61
- copy: ->(data) { data.examples.map { |e| e[:source] }.join("\n") }
75
+ copy: ->(data) { data.examples.map { |e| e.source }.join("\n") },
76
+ padded: false
62
77
  },
63
78
  notes: {
64
79
  pane: :drawer,
@@ -66,7 +81,8 @@ module Lookbook
66
81
  partial: "lookbook/previews/panels/notes",
67
82
  label: "Notes",
68
83
  hotkey: "n",
69
- disabled: ->(data) { data.examples.filter { |e| e.notes.present? }.none? }
84
+ disabled: ->(data) { data.examples.select { |e| e.notes.present? }.none? },
85
+ padded: false
70
86
  },
71
87
  params: {
72
88
  pane: :drawer,
@@ -74,7 +90,8 @@ module Lookbook
74
90
  partial: "lookbook/previews/panels/params",
75
91
  label: "Params",
76
92
  hotkey: "p",
77
- disabled: ->(data) { data.preview.params.none? }
93
+ disabled: ->(data) { data.preview.params.none? },
94
+ padded: false
78
95
  }
79
96
  },
80
97
 
@@ -90,25 +107,76 @@ module Lookbook
90
107
  show: true,
91
108
  copy: nil,
92
109
  panel_classes: nil,
93
- locals: {}
110
+ locals: {},
111
+ padded: true
94
112
  },
95
-
96
- experimental_features: false,
97
113
  })
98
114
  end
99
115
 
116
+ def project_name
117
+ @options.project_name == false ? nil : @options.project_name
118
+ end
119
+
120
+ def components_path
121
+ absolute_path(@options.components_path)
122
+ end
123
+
124
+ def page_paths
125
+ normalize_paths(@options.page_paths)
126
+ end
127
+
128
+ def preview_paths
129
+ normalize_paths(@options.preview_paths)
130
+ end
131
+
132
+ def listen_paths
133
+ normalize_paths(@options.listen_paths)
134
+ end
135
+
136
+ def parser_registry_path
137
+ absolute_path(@options.parser_registry_path)
138
+ end
139
+
100
140
  def inspector_panels(&block)
141
+ panels = Store.new(@options.inspector_panels.select { |key, panel| panel != false })
101
142
  if block_given?
102
- yield get(:inspector_panels)
143
+ yield panels
144
+ else
145
+ panels
146
+ end
147
+ end
148
+
149
+ def define_inspector_panel(name, opts = {})
150
+ @options.inspector_panels[name] = opts
151
+ if opts[:position].present?
152
+ pane = inspector_panels[name].pane.presence || :drawer
153
+ siblings = inspector_panels.select do |key, panel|
154
+ panel.pane == pane && key != name.to_sym
155
+ end
156
+ siblings.each do |key, panel|
157
+ if panel.position >= opts[:position]
158
+ panel.position += 1
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ def amend_inspector_panel(name, opts = {})
165
+ if opts == false
166
+ @options.inspector_panels[name] = false
103
167
  else
104
- get(:inspector_panels)
168
+ @options.inspector_panels[name].merge!(opts)
105
169
  end
106
170
  end
107
171
 
172
+ def remove_inspector_panel(name)
173
+ amend_inspector_panel(name, false)
174
+ end
175
+
108
176
  def ui_theme=(name)
109
177
  name = name.to_s
110
178
  if Theme.valid_theme?(name)
111
- @options[:ui_theme] = name
179
+ @options.ui_theme = name
112
180
  else
113
181
  Lookbook.logger.warn "'#{name}' is not a valid Lookbook theme. Theme setting not changed."
114
182
  end
@@ -116,18 +184,27 @@ module Lookbook
116
184
 
117
185
  def ui_theme_overrides(&block)
118
186
  if block_given?
119
- yield get(:ui_theme_overrides)
187
+ yield @options.ui_theme_overrides
120
188
  else
121
- get(:ui_theme_overrides)
189
+ @options.ui_theme_overrides
122
190
  end
123
191
  end
124
192
 
125
193
  def [](key)
126
- get(key.to_sym)
194
+ if respond_to? key.to_sym
195
+ public_send(key.to_sym)
196
+ else
197
+ @options[key.to_sym]
198
+ end
127
199
  end
128
200
 
129
201
  def []=(key, value)
130
- @options[key.to_sym] = value
202
+ setter_key = "#{key}=".to_sym
203
+ if respond_to? setter_key
204
+ public_send(setter_key, value)
205
+ else
206
+ @options[key.to_sym] = value
207
+ end
131
208
  end
132
209
 
133
210
  def to_h
@@ -140,41 +217,17 @@ module Lookbook
140
217
 
141
218
  protected
142
219
 
143
- def get_inspector_panels(panels)
144
- panels.filter! { |key, panel| panel }
145
- panels
146
- end
147
-
148
- def get_project_name(name)
149
- name == false ? nil : name
150
- end
151
-
152
220
  def normalize_paths(paths)
153
221
  paths.map! { |path| absolute_path(path) }
154
- paths.filter! { |path| Dir.exist?(path) }
155
- paths
222
+ paths.select { |path| Dir.exist?(path) }
156
223
  end
157
224
 
158
225
  def absolute_path(path)
159
226
  File.absolute_path(path.to_s, Rails.root)
160
227
  end
161
228
 
162
- alias_method :get_page_paths, :normalize_paths
163
- alias_method :get_preview_paths, :normalize_paths
164
- alias_method :get_listen_paths, :normalize_paths
165
- alias_method :get_parser_registry_path, :absolute_path
166
-
167
- def get(name)
168
- getter_name = "get_#{name}".to_sym
169
- respond_to?(getter_name, true) ? send(getter_name, @options[name]) : @options[name]
170
- end
171
-
172
- def set(name, *args)
173
- @options.send(name, *args)
174
- end
175
-
176
229
  def method_missing(name, *args)
177
- args.any? ? set(name, *args) : get(name)
230
+ @options.send(name, *args)
178
231
  end
179
232
  end
180
233
  end
@@ -8,16 +8,20 @@ module Lookbook
8
8
  autoload :Config, "lookbook/config"
9
9
 
10
10
  class << self
11
+ def version
12
+ Lookbook::VERSION
13
+ end
14
+
11
15
  def config
12
16
  @config ||= Config.new
13
17
  end
14
18
 
15
- def logger
16
- @logger ||= Rails.env.development? ? Logger.new($stdout) : Rails.logger
19
+ def configure
20
+ yield(config)
17
21
  end
18
22
 
19
- def version
20
- Lookbook::VERSION
23
+ def logger
24
+ @logger ||= Rails.env.development? ? Logger.new($stdout) : Rails.logger
21
25
  end
22
26
 
23
27
  def debug_data
@@ -28,8 +32,46 @@ module Lookbook
28
32
  }
29
33
  end
30
34
 
31
- def configure
32
- yield(config)
35
+ def previews
36
+ Preview.all
37
+ end
38
+
39
+ def pages
40
+ Page.all
41
+ end
42
+
43
+ def after_initialize(&block)
44
+ add_hook(:after_initialize, block)
45
+ end
46
+
47
+ def before_exit(&block)
48
+ add_hook(:before_exit, block)
49
+ end
50
+
51
+ def after_change(&block)
52
+ add_hook(:after_change, block)
53
+ end
54
+
55
+ def define_panel(name, opts = {})
56
+ config.define_inspector_panel(name, opts)
57
+ end
58
+
59
+ def amend_panel(name, opts = {})
60
+ config.amend_inspector_panel(name, opts)
61
+ end
62
+
63
+ def remove_panel(name)
64
+ config.remove_inspector_panel(name)
65
+ end
66
+
67
+ def broadcast(event_name, data = {})
68
+ Engine.websocket&.broadcast(event_name.to_s, data)
69
+ end
70
+
71
+ protected
72
+
73
+ def add_hook(event_name, block)
74
+ config.hooks[event_name] << block
33
75
  end
34
76
  end
35
77
 
@@ -43,8 +85,10 @@ module Lookbook
43
85
  config.lookbook.preview_paths += config.view_component.preview_paths
44
86
  config.lookbook.preview_controller ||= config.view_component.preview_controller
45
87
 
88
+ config.lookbook.components_path = config.view_component.view_component_path if config.view_component.view_component_path.present?
89
+
46
90
  config.lookbook.listen_paths += config.lookbook.preview_paths
47
- config.lookbook.listen_paths << (config.view_component.view_component_path.presence || "app/components")
91
+ config.lookbook.listen_paths << config.lookbook.components_path
48
92
  end
49
93
 
50
94
  initializer "lookbook.logging.development" do
@@ -73,12 +117,14 @@ module Lookbook
73
117
  only: /\.(rb|html.*)$/,
74
118
  force_polling: Lookbook.config.listen_use_polling
75
119
  ) do |modified, added, removed|
120
+ changes = { modified: modified, added: added, removed: removed }
76
121
  begin
77
122
  parser.parse
78
123
  rescue
79
124
  end
80
125
  Lookbook::Preview.clear_cache
81
- Lookbook::Engine.websocket&.broadcast("reload", {})
126
+ Lookbook::Engine.reload_ui(changes)
127
+ Lookbook::Engine.run_hooks(:after_change, changes)
82
128
  end
83
129
  Lookbook::Engine.register_listener(preview_listener)
84
130
 
@@ -87,7 +133,9 @@ module Lookbook
87
133
  only: /\.(html.*|md.*)$/,
88
134
  force_polling: Lookbook.config.listen_use_polling
89
135
  ) do |modified, added, removed|
90
- Lookbook::Engine.websocket&.broadcast("reload", {})
136
+ changes = { modified: modified, added: added, removed: removed }
137
+ Lookbook::Engine.reload_ui(changes)
138
+ Lookbook::Engine.run_hooks(:after_change, changes)
91
139
  end
92
140
  Lookbook::Engine.register_listener(page_listener)
93
141
  end
@@ -103,18 +151,20 @@ module Lookbook
103
151
  "
104
152
  end
105
153
  end
154
+
155
+ Lookbook::Engine.run_hooks(:after_initialize)
106
156
  end
107
157
 
108
158
  at_exit do
109
159
  if config.lookbook.listen
110
160
  Lookbook.logger.debug "Stopping listeners"
111
- Lookbook::Engine.listeners.each do |listener|
112
- listener.stop
113
- end
161
+ Lookbook::Engine.listeners.each { |listener| listener.stop }
114
162
  end
163
+ Lookbook::Engine.run_hooks(:before_exit)
115
164
  end
116
165
 
117
166
  class << self
167
+
118
168
  def websocket
119
169
  if config.lookbook.auto_refresh
120
170
  cable = ActionCable::Server::Configuration.new
@@ -162,6 +212,16 @@ module Lookbook
162
212
  @listeners ||= []
163
213
  end
164
214
 
215
+ def run_hooks(event_name, *args)
216
+ Lookbook.config.hooks[event_name].each do |hook|
217
+ hook.call(Lookbook, *args)
218
+ end
219
+ end
220
+
221
+ def reload_ui(changed = {})
222
+ websocket&.broadcast("reload", changed)
223
+ end
224
+
165
225
  attr_reader :preview_controller
166
226
  end
167
227
  end
data/lib/lookbook/page.rb CHANGED
@@ -19,7 +19,7 @@ module Lookbook
19
19
 
20
20
  def initialize(path, base_path)
21
21
  @pathname = Pathname.new path
22
- @base_path = base_path
22
+ @base_path = Pathname.new base_path
23
23
  @options = nil
24
24
  @errors = []
25
25
  @sections = []
@@ -30,7 +30,7 @@ module Lookbook
30
30
  end
31
31
 
32
32
  def url_path
33
- page_path lookup_path
33
+ lookbook_page_path lookup_path
34
34
  end
35
35
 
36
36
  def full_path
@@ -177,7 +177,7 @@ module Lookbook
177
177
  end
178
178
 
179
179
  def page_paths
180
- Lookbook.config.page_paths.filter { |dir| Dir.exist? dir }
180
+ Lookbook.config.page_paths.select { |dir| Dir.exist? dir }
181
181
  end
182
182
 
183
183
  def section_path?(path)
@@ -23,10 +23,6 @@ module Lookbook
23
23
  registry.get(path)
24
24
  end
25
25
 
26
- # def yardoc_file_path
27
- # Rails&.root ? Rails.root.join(YARDOC_FILE_PATH) : YARDOC_FILE_PATH
28
- # end
29
-
30
26
  class << self
31
27
  def define_tags
32
28
  YARD::Tags::Library.define_tag("Hidden status", :hidden)
@@ -34,6 +30,7 @@ module Lookbook
34
30
  YARD::Tags::Library.define_tag("Display", :display)
35
31
  YARD::Tags::Library.define_tag("Position", :position)
36
32
  YARD::Tags::Library.define_tag("ID", :id)
33
+ YARD::Tags::Library.define_tag("Component", :component)
37
34
  end
38
35
  end
39
36
  end
@@ -8,7 +8,7 @@ module Lookbook
8
8
  def initialize(preview)
9
9
  @preview = preview
10
10
  @preview_inspector = SourceInspector.new(@preview.name)
11
- super(preview_class_name(preview_class_basename(@preview.name)))
11
+ super(preview_class_path(@preview.name))
12
12
  end
13
13
 
14
14
  def id
@@ -34,7 +34,7 @@ module Lookbook
34
34
  def examples
35
35
  return @examples if @examples.present?
36
36
  public_methods = @preview.public_instance_methods(false)
37
- public_method_objects = @preview_inspector&.methods&.filter { |m| public_methods.include?(m.name) }
37
+ public_method_objects = @preview_inspector&.methods&.select { |m| public_methods.include?(m.name) }
38
38
  examples = (public_method_objects || []).map { |m| PreviewExample.new(m.name.to_s, self) }
39
39
  sorted = Lookbook.config.sort_examples ? examples.sort_by(&:label) : examples
40
40
  @examples = []
@@ -62,18 +62,14 @@ module Lookbook
62
62
  end
63
63
 
64
64
  def full_path
65
- base_path = Array(preview_paths).detect do |preview_path|
65
+ base_path = Array(Lookbook.config.preview_paths).detect do |preview_path|
66
66
  Dir["#{preview_path}/#{name.underscore}.rb"].first
67
67
  end
68
68
  Pathname.new(Dir["#{base_path}/#{name.underscore}.rb"].first)
69
69
  end
70
70
 
71
71
  def url_path
72
- inspect_path lookup_path
73
- end
74
-
75
- def preview_paths
76
- ViewComponent::Base.preview_paths
72
+ lookbook_inspect_path lookup_path
77
73
  end
78
74
 
79
75
  def parent_collections_names
@@ -96,6 +92,27 @@ module Lookbook
96
92
  true
97
93
  end
98
94
 
95
+ def component
96
+ components.first
97
+ end
98
+
99
+ def components
100
+ component_classes = @preview_inspector&.components.any? ? @preview_inspector&.components : [guess_component]
101
+ component_classes.map do |class_name|
102
+ Component.new(class_name.to_s)
103
+ end
104
+ end
105
+
106
+ protected
107
+
108
+ def guess_component
109
+ begin
110
+ name.chomp("Preview").constantize
111
+ rescue
112
+ nil
113
+ end
114
+ end
115
+
99
116
  class << self
100
117
  def find(path)
101
118
  all.find { |p| p.lookup_path == path }
@@ -15,7 +15,7 @@ module Lookbook
15
15
  end
16
16
 
17
17
  def url_path
18
- inspect_path lookup_path
18
+ lookbook_inspect_path lookup_path
19
19
  end
20
20
 
21
21
  def label
@@ -30,7 +30,7 @@ module Lookbook
30
30
  @example_inspector.source.split("\n")[1..-2].join("\n").strip_heredoc
31
31
  end
32
32
 
33
- def source_lang
33
+ def lang
34
34
  Lookbook::Lang.find(:ruby)
35
35
  end
36
36
 
@@ -10,7 +10,7 @@ module Lookbook
10
10
  end
11
11
 
12
12
  def url_path
13
- inspect_path lookup_path
13
+ lookbook_inspect_path lookup_path
14
14
  end
15
15
 
16
16
  def label
@@ -39,6 +39,16 @@ module Lookbook
39
39
  code_object&.tag(:position)&.text&.to_i || 10000
40
40
  end
41
41
 
42
+ def components
43
+ if code_object&.tags(:component).present?
44
+ code_object.tags(:component).map do |component|
45
+ component.text.constantize
46
+ end
47
+ else
48
+ []
49
+ end
50
+ end
51
+
42
52
  def display_params
43
53
  display_params = {}.with_indifferent_access
44
54
  if code_object&.tags(:display).present?
@@ -16,7 +16,7 @@ module Lookbook
16
16
  class_name(klass).to_s.chomp("ComponentPreview").chomp("Component::Preview").chomp("::Preview").chomp("Component").chomp("Preview").chomp("::")
17
17
  end
18
18
 
19
- def preview_class_name(klass)
19
+ def preview_class_path(klass)
20
20
  preview_class_basename(klass).underscore
21
21
  end
22
22
 
@@ -49,7 +49,7 @@ module Lookbook
49
49
  end
50
50
 
51
51
  def to_preview_path(*args)
52
- args.flatten.map { |arg| preview_class_name(arg) }.join("/")
52
+ args.flatten.map { |arg| preview_class_path(arg) }.join("/")
53
53
  end
54
54
 
55
55
  protected
@@ -1,3 +1,3 @@
1
1
  module Lookbook
2
- VERSION = "1.0.0.beta.1"
2
+ VERSION = "1.0.0.beta.4"
3
3
  end
data/lib/lookbook.rb CHANGED
@@ -27,16 +27,5 @@ module Lookbook
27
27
  autoload :Markdown, "lookbook/markdown"
28
28
  autoload :Theme, "lookbook/theme"
29
29
  autoload :Store, "lookbook/store"
30
-
31
- class << self
32
- include Utils
33
-
34
- def previews
35
- Preview.all
36
- end
37
-
38
- def pages
39
- Page.all
40
- end
41
- end
30
+ autoload :Component, "lookbook/component"
42
31
  end