lookbook 1.4.0 → 1.4.2

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 (28) hide show
  1. checksums.yaml +4 -4
  2. data/app/components/lookbook/nav/component.rb +1 -1
  3. data/app/components/lookbook/nav/directory/component.html.erb +2 -0
  4. data/app/components/lookbook/nav/entity/component.html.erb +2 -0
  5. data/app/components/lookbook/nav/entity/component.rb +1 -1
  6. data/app/components/lookbook/nav/item/component.rb +2 -2
  7. data/app/components/lookbook/params/field/component.rb +1 -1
  8. data/app/components/lookbook/tabs/component.html.erb +1 -1
  9. data/app/components/lookbook/tabs/component.js +4 -0
  10. data/app/views/layouts/lookbook/application.html.erb +52 -50
  11. data/app/views/layouts/lookbook/shell.html.erb +1 -0
  12. data/app/views/lookbook/inspector/inputs/_toggle.html.erb +3 -3
  13. data/lib/lookbook/entities/collections/concerns/hierarchical_collection.rb +0 -4
  14. data/lib/lookbook/entities/collections/entity_collection.rb +9 -14
  15. data/lib/lookbook/entities/collections/preview_collection.rb +8 -2
  16. data/lib/lookbook/entities/collections/preview_example_collection.rb +0 -5
  17. data/lib/lookbook/entities/concerns/locatable.rb +2 -2
  18. data/lib/lookbook/entities/concerns/navigable.rb +19 -3
  19. data/lib/lookbook/entities/entity.rb +5 -0
  20. data/lib/lookbook/entities/preview.rb +1 -1
  21. data/lib/lookbook/entities/preview_example.rb +10 -1
  22. data/lib/lookbook/services/data/resolvers/file_resolver.rb +1 -1
  23. data/lib/lookbook/support/tree_node.rb +10 -6
  24. data/lib/lookbook/tags/param_tag.rb +1 -1
  25. data/lib/lookbook/version.rb +1 -1
  26. data/public/lookbook-assets/js/lookbook.js +43 -42
  27. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  28. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3a8ca9a9db0798d392083b4470397bf94260811a1f82f8b89dee0e5646fca156
4
- data.tar.gz: 24fe83948823edd7387b11ca2ee5628f778a15034173491bfdfd20347d6b1484
3
+ metadata.gz: e489fa4bdff458098a029cf9d2bc25d6e16a70e11a92a1be7a77114ad43e0f63
4
+ data.tar.gz: c5efc75e6a4d0b16493cd1eb21d3ace790af22b64ba22e3c00edfb1bb6a58e5d
5
5
  SHA512:
6
- metadata.gz: 1463db9307bc67d9224a4a96f21ee404902fe0e266b40b0456c84e551a26b96a779e816f2780b5c1ea30189b8d94e3e5dfc16ab6d2f0b3df3a0e06d8f2705282
7
- data.tar.gz: ea867f97d2cb0d532e59c3c62de31405dca1fe29e7f9ade020fe6b7eb2cb3d2b04d16d7b110e3479eaa54316d6df9ba3328594c73c659e37f6c513867325ad54
6
+ metadata.gz: 9cf5f58aedde5c3bac838a15f9fc1dadabc46ce667987b689ce4fc9a83c95cd11fe908f1b2fb69f59b20ffdaa85a306e8e8af89988b65de085d73c5a7b73f9d8
7
+ data.tar.gz: 59d122a52a50a77a9e30cfd484789fa1de533ca244b20c7cecefd02521c30fd5c962d59c2d40ff85f1fff786a1d4a864c3f3887625dc08214b2dac96c4a22f10
@@ -12,7 +12,7 @@ module Lookbook
12
12
  end
13
13
 
14
14
  def items
15
- tree.map do |node|
15
+ @items ||= tree.map do |node|
16
16
  item_class = (node.type == :directory) ? Nav::Directory::Component : Nav::Entity::Component
17
17
  lookbook_render item_class.new node, nav_id: id
18
18
  end
@@ -1,10 +1,12 @@
1
1
  <%= render_component_tag :li,
2
2
  id: id,
3
+ key: "#{id}-directory",
3
4
  class: "list-none",
4
5
  "x-show": "!filteredOut",
5
6
  data: { "entity-type": :directory },
6
7
  cloak: true do %>
7
8
  <%= lookbook_tag :button,
9
+ key: "#{id}-action",
8
10
  class: "nav-action",
9
11
  style: "padding-left: #{left_pad}px",
10
12
  "x-bind": "bindings.toggle" do %>
@@ -1,11 +1,13 @@
1
1
  <%= render_component_tag :li,
2
2
  id: id,
3
+ key: "#{id}-entity-#{type}",
3
4
  class: "list-none",
4
5
  "x-show": "!filteredOut",
5
6
  data: { "entity-type": type },
6
7
  cloak: true do %>
7
8
  <%= lookbook_tag href.present? ? :a : :button,
8
9
  href: href,
10
+ key: "#{id}-action",
9
11
  class: "nav-action",
10
12
  style: "padding-left: #{left_pad}px",
11
13
  "x-bind": "bindings.#{href.present? ? "link" : "toggle"}" do %>
@@ -8,7 +8,7 @@ module Lookbook
8
8
  }.freeze
9
9
 
10
10
  def nav_icon
11
- ICONS[type] || :file
11
+ ICONS[collapsed? ? :preview : node.type] || :file
12
12
  end
13
13
 
14
14
  def href
@@ -15,11 +15,11 @@ module Lookbook
15
15
  end
16
16
 
17
17
  def left_pad
18
- ((depth - 1) * 12) + 24
18
+ depth * 12
19
19
  end
20
20
 
21
21
  def children
22
- @children ||= node.map { |node| render_item(node) }
22
+ @children ||= node.sort.map { |node| render_item(node) }
23
23
  end
24
24
 
25
25
  def nav_icon
@@ -34,7 +34,7 @@ module Lookbook
34
34
  value: param.value,
35
35
  value_type: param.value_type,
36
36
  value_default: param.value_default,
37
- input_options: input_options.except(:choices),
37
+ input_options: input_options.except(:choices, :opts),
38
38
  choices: input_options[:choices])
39
39
  end
40
40
 
@@ -13,7 +13,7 @@
13
13
  <%= lookbook_render :button, icon: :menu, class: "-ml-3", "x-show": "visibleTabsCount === 0" %>
14
14
  </div>
15
15
  <div class="hidden">
16
- <div x-ref="tabsDropdown" data-cloak>
16
+ <div x-ref="tabsDropdown" x-cloak>
17
17
  <%= safe_join(dropdown_tabs) %>
18
18
  </div>
19
19
  </div>
@@ -33,6 +33,10 @@ export default function tabsComponent(store) {
33
33
 
34
34
  init() {
35
35
  this.$nextTick(() => {
36
+ if (this.$root.parentElement.offsetWidth === this.$root.offsetWidth) {
37
+ this.visibleTabsCount = this.tabs.length;
38
+ }
39
+
36
40
  dropdown = tippy(this.$refs.dropdownTrigger, {
37
41
  content: this.$refs.tabsDropdown,
38
42
  theme: "menu",
@@ -1,60 +1,62 @@
1
1
  <% content_for :shell do %>
2
2
  <% if @previews.any? || @pages.any? %>
3
- <%= lookbook_render :split_layout,
4
- alpine_data: "$store.layout.main",
5
- ":class": "$store.layout.mobile && '!block'" do |layout| %>
3
+ <% cache do %>
4
+ <%= lookbook_render :split_layout,
5
+ alpine_data: "$store.layout.main",
6
+ ":class": "$store.layout.mobile && '!block'" do |layout| %>
6
7
 
7
- <% layout.pane id: "app-sidebar", class: "flex flex-col bg-lookbook-sidebar-bg relative translate-x-0",
8
- ":class": "{
9
- 'transition': $store.layout.mobile,
10
- 'translate-x-full': $store.layout.mobile && sidebarHidden,
11
- '!absolute right-0 bottom-0 top-[40px] h-[calc(100%_-_40px)] w-full max-w-[420px] z-50 border-l border-lookbook-divider': $store.layout.mobile
12
- }",
13
- "@click.outside": "closeMobileSidebar",
14
- cloak: true do %>
8
+ <% layout.pane id: "app-sidebar", class: "flex flex-col bg-lookbook-sidebar-bg relative translate-x-0",
9
+ ":class": "{
10
+ 'transition': $store.layout.mobile,
11
+ 'translate-x-full': $store.layout.mobile && sidebarHidden,
12
+ '!absolute right-0 bottom-0 top-[40px] h-[calc(100%_-_40px)] w-full max-w-[420px] z-50 border-l border-lookbook-divider': $store.layout.mobile
13
+ }",
14
+ "@click.outside": "closeMobileSidebar",
15
+ cloak: true do %>
15
16
 
16
- <%= lookbook_render :split_layout,
17
- alpine_data: "$store.layout.#{@pages.any? && @previews.any? ? "sidebar" : "singleSectionSidebar"}",
18
- style: "height: calc(100vh - 2.5rem);" do |layout| %>
17
+ <%= lookbook_render :split_layout,
18
+ alpine_data: "$store.layout.#{@pages.any? && @previews.any? ? "sidebar" : "singleSectionSidebar"}",
19
+ style: "height: calc(100vh - 2.5rem);" do |layout| %>
19
20
 
20
- <% if @previews.any? %>
21
- <% layout.pane class: "overflow-hidden" do %>
22
- <%= lookbook_render :nav,
23
- id: "previews-nav",
24
- tree: @previews.to_tree,
25
- alpine_data: "$store.nav.previews" do |nav| %>
26
- <%= nav.toolbar do |toolbar| %>
27
- <% toolbar.section padded: true do %>
28
- <h4 class="pt-1">Previews</h4>
29
- <% end %>
30
- <% toolbar.section align: :right, padded: false do %>
31
- <%= lookbook_render :button_group, size: :xs do |group| %>
32
- <% group.button icon: :minus_square,
33
- tooltip: "Collapse all",
34
- "@click": "closeAll" %>
21
+ <% if @previews.any? %>
22
+ <% layout.pane class: "overflow-hidden" do %>
23
+ <%= lookbook_render :nav,
24
+ id: "previews-nav",
25
+ tree: @previews.to_tree,
26
+ alpine_data: "$store.nav.previews" do |nav| %>
27
+ <%= nav.toolbar do |toolbar| %>
28
+ <% toolbar.section padded: true do %>
29
+ <h4 class="pt-1">Previews</h4>
30
+ <% end %>
31
+ <% toolbar.section align: :right, padded: false do %>
32
+ <%= lookbook_render :button_group, size: :xs do |group| %>
33
+ <% group.button icon: :minus_square,
34
+ tooltip: "Collapse all",
35
+ "@click": "closeAll" %>
36
+ <% end %>
35
37
  <% end %>
36
38
  <% end %>
39
+ <% nav.filter store: "$store.nav.previews.filter", placeholder: "Filter previews by name&hellip;" %>
37
40
  <% end %>
38
- <% nav.filter store: "$store.nav.previews.filter", placeholder: "Filter previews by name&hellip;" %>
39
41
  <% end %>
40
42
  <% end %>
41
- <% end %>
42
43
 
43
- <% if @pages.any? %>
44
- <% layout.pane class: "overflow-hidden" do %>
45
- <%= lookbook_render :nav,
46
- id: "pages-nav",
47
- tree: @pages.to_tree,
48
- alpine_data: "$store.nav.pages" do |nav| %>
49
- <%= nav.toolbar do |toolbar| %>
50
- <% toolbar.section padded: true do %>
51
- <h4 class="pt-1">Pages</h4>
52
- <% end %>
53
- <% toolbar.section align: :right, padded: false do %>
54
- <%= lookbook_render :button_group, size: :xs do |group| %>
55
- <% group.button icon: :minus_square,
56
- tooltip: "Collapse all",
57
- "@click": "closeAll" %>
44
+ <% if @pages.any? %>
45
+ <% layout.pane class: "overflow-hidden" do %>
46
+ <%= lookbook_render :nav,
47
+ id: "pages-nav",
48
+ tree: @pages.to_tree,
49
+ alpine_data: "$store.nav.pages" do |nav| %>
50
+ <%= nav.toolbar do |toolbar| %>
51
+ <% toolbar.section padded: true do %>
52
+ <h4 class="pt-1">Pages</h4>
53
+ <% end %>
54
+ <% toolbar.section align: :right, padded: false do %>
55
+ <%= lookbook_render :button_group, size: :xs do |group| %>
56
+ <% group.button icon: :minus_square,
57
+ tooltip: "Collapse all",
58
+ "@click": "closeAll" %>
59
+ <% end %>
58
60
  <% end %>
59
61
  <% end %>
60
62
  <% end %>
@@ -62,10 +64,10 @@
62
64
  <% end %>
63
65
  <% end %>
64
66
  <% end %>
65
- <% end %>
66
67
 
67
- <% layout.pane id: "app-main", class: "overflow-hidden h-full", ":class": "$store.layout.mobile && 'w-screen'" do %>
68
- <%= content_for?(:main) ? yield(:main) : yield %>
68
+ <% layout.pane id: "app-main", class: "overflow-hidden h-full", ":class": "$store.layout.mobile && 'w-screen'" do %>
69
+ <%= content_for?(:main) ? yield(:main) : yield %>
70
+ <% end %>
69
71
  <% end %>
70
72
  <% end %>
71
73
  <% else %>
@@ -76,4 +78,4 @@
76
78
  <div class="absolute opacity-0 bg-black inset-0 top-[39px] z-[-1] transition-opacity" :class="($store.layout.mobile && !sidebarHidden) && '!opacity-30 !z-40'" data-cloak></div>
77
79
  <% end %>
78
80
 
79
- <%= render template: "layouts/lookbook/shell" %>
81
+ <%= render template: "layouts/lookbook/shell" %>
@@ -2,6 +2,7 @@
2
2
  <div
3
3
  id="app"
4
4
  x-data="app"
5
+ x-cloak
5
6
  @popstate.window="handleNavigation"
6
7
  @click.document="hijax"
7
8
  @navigation:start="closeMobileSidebar"
@@ -11,10 +11,10 @@ span_classes = [
11
11
  ]
12
12
  %>
13
13
 
14
- <%= button_tag **input_options,
14
+ <%= tag.button **input_options,
15
15
  class: class_names(button_classes),
16
16
  role: "switch",
17
17
  type: "button",
18
- "@click.stop": "value = value == 'true' ? 'false' : 'true'" do %>
18
+ "@click.stop": "value = value == 'true' ? 'false' : 'true'", escape: false do %>
19
19
  <%= tag.span "aria-hidden": true, class: class_names(span_classes) %>
20
- <% end %>
20
+ <% end %>
@@ -18,10 +18,6 @@ module Lookbook
18
18
  entities.append(node.content? ? node.content : collect_ordered_entities(node))
19
19
  end.flatten
20
20
  end
21
-
22
- def sort_entities
23
- @entities.sort_by! { |entity| [entity.depth, entity.position, entity.label] }
24
- end
25
21
  end
26
22
  end
27
23
  end
@@ -12,53 +12,48 @@ module Lookbook
12
12
  add(entities)
13
13
  end
14
14
 
15
- def add(entities = nil)
16
- Array(entities).each do |entity|
15
+ def add(to_add = nil)
16
+ Array(to_add).each do |entity|
17
17
  unless find_by_path(entity.path)
18
- clear_cache
19
18
  @entities.push(entity)
20
19
  end
21
20
  end
22
- sort_entities
21
+ clear_cache
23
22
  end
24
23
 
25
24
  def find_by_id(id)
26
25
  id = Utils.id(id)
27
- find { |entity| entity.id == id }
26
+ entities.find { |entity| entity.id == id }
28
27
  end
29
28
 
30
29
  def find_by_path(path)
31
- find { |entity| entity.path.to_s == path.to_s }
30
+ entities.find { |entity| entity.path.to_s == path.to_s }
32
31
  end
33
32
 
34
33
  def next(entity)
35
- index = find_index { |i| i.path == entity.path }
34
+ index = entities.find_index { |i| i.path == entity.path }
36
35
  entities[index + 1] unless index.nil?
37
36
  end
38
37
 
39
38
  def previous(entity)
40
- index = find_index { |i| i.path == entity.path }
39
+ index = entities.find_index { |i| i.path == entity.path }
41
40
  entities[index - 1] if !index.nil? && index > 0
42
41
  end
43
42
 
44
43
  def each(&block)
45
44
  if block
46
- entities.each { |entity| yield entity }
45
+ entities.sort.each { |entity| yield entity }
47
46
  else
48
47
  to_enum(:each)
49
48
  end
50
49
  end
51
50
 
52
51
  def flat_map(...)
53
- map(...).map(&:to_a).flatten
52
+ entities.map(...).map(&:to_a).flatten
54
53
  end
55
54
 
56
55
  protected
57
56
 
58
- def sort_entities
59
- @entities.sort_by! { |entity| [entity.label] }
60
- end
61
-
62
57
  def clear_cache
63
58
  @_cache = {}
64
59
  end
@@ -20,12 +20,18 @@ module Lookbook
20
20
 
21
21
  def self.preview_from_code_object(code_object)
22
22
  klass = code_object.path.constantize
23
- Preview.new(code_object) if klass.ancestors.include?(ViewComponent::Preview)
23
+ Preview.new(code_object) if preview_class?(klass)
24
24
  rescue => exception
25
- Lookbook.logger.error LookbookError.new(exception)
25
+ Lookbook.logger.error exception.to_s
26
26
  nil
27
27
  end
28
28
 
29
+ def self.preview_class?(klass)
30
+ if klass.ancestors.include?(ViewComponent::Preview)
31
+ !klass.respond_to?(:abstract_class) || klass.abstract_class != true
32
+ end
33
+ end
34
+
29
35
  protected
30
36
 
31
37
  def examples
@@ -1,9 +1,4 @@
1
1
  module Lookbook
2
2
  class PreviewExampleCollection < EntityCollection
3
- protected
4
-
5
- def sort_entities
6
- @entities.sort_by!(&:label) if Lookbook.config.sort_examples
7
- end
8
3
  end
9
4
  end
@@ -65,8 +65,8 @@ module Lookbook
65
65
  def base_directory
66
66
  return @_base_directory if @_base_directory
67
67
 
68
- directories = [Rails.root, *Array(base_directories)].map(&:to_s).sort_by(&:length).reverse
69
- @_base_directory ||= directories.first { |dir| file_path.start_with?(dir) }
68
+ directories = Array(base_directories).map(&:to_s).sort_by { |path| path.split("/").size }.reverse
69
+ @_base_directory ||= directories.find { |dir| file_path.to_s.start_with?(dir) }
70
70
  end
71
71
  end
72
72
  end
@@ -12,16 +12,32 @@ module Lookbook
12
12
  end
13
13
 
14
14
  def position
15
- if @position_prefixes && respond_to?(:file_name)
16
- PositionPrefixParser.call(file_name).first || 10000
15
+ return @_position if @_position
16
+
17
+ pos = if @position_prefixes && respond_to?(:file_name)
18
+ PositionPrefixParser.call(file_name).first || default_position
17
19
  else
18
- fetch_config(:position, 10000)
20
+ fetch_config(:position, default_position)
19
21
  end
22
+
23
+ @_position ||= pos.to_i
20
24
  end
21
25
 
22
26
  def depth
23
27
  path.split("/").size
24
28
  end
29
+
30
+ def default_position
31
+ @default_position || 10000
32
+ end
33
+
34
+ def <=>(other)
35
+ if respond_to?(:sort_handler, true)
36
+ sort_handler(other)
37
+ else
38
+ [position, label] <=> [other.position, other.label]
39
+ end
40
+ end
25
41
  end
26
42
  end
27
43
  end
@@ -1,5 +1,6 @@
1
1
  module Lookbook
2
2
  class Entity
3
+ include Comparable
3
4
  include Lookbook::Engine.routes.url_helpers
4
5
 
5
6
  def initialize(lookup_path = nil)
@@ -36,6 +37,10 @@ module Lookbook
36
37
  @_type ||= self.class.name.demodulize.underscore.downcase.to_sym
37
38
  end
38
39
 
40
+ def <=>(other)
41
+ label <=> other.label
42
+ end
43
+
39
44
  alias_method :path, :lookup_path
40
45
  alias_method :logical_path, :lookup_path
41
46
 
@@ -81,7 +81,7 @@ module Lookbook
81
81
  def example_entities
82
82
  public_methods = preview_class.public_instance_methods(false)
83
83
  method_objects = code_object.meths.select { |m| public_methods.include?(m.name) }
84
- method_objects.map { |code_object| PreviewExample.new(code_object, self) }
84
+ method_objects.map.with_index { |code_object, i| PreviewExample.new(code_object, self, position: i) }
85
85
  end
86
86
  end
87
87
  end
@@ -8,9 +8,10 @@ module Lookbook
8
8
 
9
9
  attr_reader :preview
10
10
 
11
- def initialize(code_object, preview)
11
+ def initialize(code_object, preview, position: nil)
12
12
  @code_object = code_object
13
13
  @preview = preview
14
+ @default_position = position
14
15
  @lookup_path = "#{parent.lookup_path}/#{name}"
15
16
  end
16
17
 
@@ -65,6 +66,14 @@ module Lookbook
65
66
 
66
67
  protected
67
68
 
69
+ def sort_handler(other_entity)
70
+ if Lookbook.config.sort_examples
71
+ label <=> other_entity.label
72
+ else
73
+ [position, label] <=> [other_entity.position, other_entity.label]
74
+ end
75
+ end
76
+
68
77
  def format_source(source)
69
78
  source.sub(/^def \w+\s?(\([^)]+\))?/m, "").split("\n")[0..-2].join("\n")
70
79
  end
@@ -22,7 +22,7 @@ module Lookbook
22
22
  end
23
23
 
24
24
  def resolve_path(path, base_dir)
25
- path.start_with?(".") ? File.expand_path(path, base_dir) : Rails.root.join(path)
25
+ Pathname(path.start_with?(".") ? File.expand_path(path, base_dir) : Rails.root.join(path))
26
26
  end
27
27
  end
28
28
  end
@@ -1,6 +1,7 @@
1
1
  module Lookbook
2
2
  class TreeNode
3
3
  include Enumerable
4
+ include Comparable
4
5
 
5
6
  delegate_missing_to :content
6
7
 
@@ -40,7 +41,6 @@ module Lookbook
40
41
 
41
42
  def add_child(name, content = nil, position: 10000)
42
43
  children << TreeNode.new("#{path}/#{name}", content, position: position)
43
- sort_children
44
44
  end
45
45
 
46
46
  def has_child?(name)
@@ -57,7 +57,7 @@ module Lookbook
57
57
 
58
58
  def each(&block)
59
59
  if block
60
- children.each do |child|
60
+ children.sort.each do |child|
61
61
  yield child
62
62
  end
63
63
  else
@@ -65,6 +65,14 @@ module Lookbook
65
65
  end
66
66
  end
67
67
 
68
+ def <=>(other)
69
+ if content?
70
+ content <=> (other.content? ? other.content : other)
71
+ else
72
+ [position, label] <=> [other.position, other.label]
73
+ end
74
+ end
75
+
68
76
  protected
69
77
 
70
78
  def content_value(method_name, fallback = nil)
@@ -72,10 +80,6 @@ module Lookbook
72
80
  value || fallback
73
81
  end
74
82
 
75
- def sort_children
76
- @children.sort_by! { |child| [child.position, child.label] }
77
- end
78
-
79
83
  def segments
80
84
  path.split("/")
81
85
  end
@@ -1,7 +1,7 @@
1
1
  module Lookbook
2
2
  class ParamTag < YardTag
3
3
  VALUE_TYPE_MATCHER = /^(\[\s?([A-Z]{1}\w+)\s?\])/
4
- DESCRIPTION_MATCHER = /"(.*[^\\])"$/
4
+ DESCRIPTION_MATCHER = /(?<=\s|^)"(.*[^\\])"(?:\s|$)/
5
5
 
6
6
  supports_options
7
7
 
@@ -1,3 +1,3 @@
1
1
  module Lookbook
2
- VERSION = "1.4.0"
2
+ VERSION = "1.4.2"
3
3
  end