lookbook 0.4.6 → 0.4.7
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.
- checksums.yaml +4 -4
- data/app/assets/lookbook/css/app.css +55 -5
- data/app/assets/lookbook/js/app.js +38 -54
- data/app/assets/lookbook/js/components/copy.js +16 -0
- data/app/assets/lookbook/js/components/filter.js +24 -0
- data/app/assets/lookbook/js/components/inspector.js +21 -0
- data/app/assets/lookbook/js/{nav/node.js → components/nav-group.js} +16 -15
- data/app/assets/lookbook/js/components/nav-item.js +26 -0
- data/app/assets/lookbook/js/components/nav.js +35 -0
- data/app/assets/lookbook/js/components/page.js +33 -0
- data/app/assets/lookbook/js/{workbench → components}/param.js +3 -4
- data/app/assets/lookbook/js/{workbench/preview.js → components/preview-window.js} +9 -10
- data/app/assets/lookbook/js/components/sidebar.js +3 -0
- data/app/assets/lookbook/js/components/sizes.js +16 -0
- data/app/assets/lookbook/js/components/splitter.js +25 -0
- data/app/assets/lookbook/js/config.js +14 -0
- data/app/assets/lookbook/js/{utils/reloader.js → lib/socket.js} +7 -12
- data/app/assets/lookbook/js/lib/split.js +21 -0
- data/app/assets/lookbook/js/lib/utils.js +3 -0
- data/app/assets/lookbook/js/stores/filter.js +11 -0
- data/app/assets/lookbook/js/stores/inspector.js +17 -0
- data/app/assets/lookbook/js/stores/layout.js +12 -0
- data/app/assets/lookbook/js/stores/nav.js +21 -0
- data/app/assets/lookbook/js/stores/sidebar.js +14 -0
- data/app/controllers/lookbook/app_controller.rb +70 -97
- data/app/helpers/lookbook/application_helper.rb +48 -4
- data/app/views/layouts/lookbook/app.html.erb +54 -0
- data/app/views/layouts/lookbook/preview.html.erb +12 -0
- data/app/views/lookbook/components/_code.html.erb +8 -0
- data/app/views/lookbook/{shared/_clipboard.html.erb → components/_copy.html.erb} +4 -5
- data/app/views/lookbook/components/_filter.html.erb +15 -0
- data/app/views/lookbook/{shared → components}/_header.html.erb +3 -3
- data/app/views/lookbook/components/_icon.html.erb +5 -0
- data/app/views/lookbook/components/_nav.html.erb +17 -0
- data/app/views/lookbook/components/_nav_collection.html.erb +5 -0
- data/app/views/lookbook/components/_nav_group.html.erb +17 -0
- data/app/views/lookbook/components/_nav_item.html.erb +21 -0
- data/app/views/lookbook/components/_nav_preview.html.erb +11 -0
- data/app/views/lookbook/components/_param.html.erb +20 -0
- data/app/views/lookbook/{workbench → components}/_preview.html.erb +8 -8
- data/app/views/lookbook/{app/error.html.erb → error.html.erb} +0 -0
- data/app/views/lookbook/index.html.erb +9 -0
- data/app/views/lookbook/{workbench/inspector/params → inputs}/_select.html.erb +1 -1
- data/app/views/lookbook/{workbench/inspector/params → inputs}/_text.html.erb +1 -1
- data/app/views/lookbook/{workbench/inspector/params → inputs}/_textarea.html.erb +1 -1
- data/app/views/lookbook/{workbench/inspector/params → inputs}/_toggle.html.erb +1 -1
- data/app/views/lookbook/{app/not_found.html.erb → not_found.html.erb} +2 -4
- data/app/views/lookbook/panels/_notes.html.erb +25 -0
- data/app/views/lookbook/panels/_output.html.erb +18 -0
- data/app/views/lookbook/panels/_params.html.erb +17 -0
- data/app/views/lookbook/panels/_source.html.erb +20 -0
- data/app/views/lookbook/show.html.erb +90 -0
- data/lib/lookbook/code_formatter.rb +20 -0
- data/lib/lookbook/engine.rb +4 -1
- data/lib/lookbook/lang.rb +10 -5
- data/lib/lookbook/preview_controller.rb +1 -1
- data/lib/lookbook/preview_group.rb +5 -1
- data/lib/lookbook/version.rb +1 -1
- data/lib/lookbook.rb +1 -0
- data/public/lookbook-assets/css/app.css +2 -0
- data/public/lookbook-assets/css/app.css.map +1 -0
- data/public/lookbook-assets/js/app.js +2 -0
- data/public/lookbook-assets/js/app.js.map +1 -0
- metadata +54 -43
- data/app/assets/lookbook/js/nav/leaf.js +0 -20
- data/app/assets/lookbook/js/nav.js +0 -38
- data/app/assets/lookbook/js/page.js +0 -38
- data/app/assets/lookbook/js/utils/clipboard.js +0 -13
- data/app/assets/lookbook/js/utils/morph.js +0 -19
- data/app/assets/lookbook/js/utils/screen.js +0 -44
- data/app/assets/lookbook/js/utils/size_observer.js +0 -16
- data/app/assets/lookbook/js/utils/split.js +0 -26
- data/app/assets/lookbook/js/workbench/inspector.js +0 -11
- data/app/assets/lookbook/js/workbench.js +0 -14
- data/app/views/lookbook/app/index.html.erb +0 -11
- data/app/views/lookbook/app/show.html.erb +0 -1
- data/app/views/lookbook/layouts/app.html.erb +0 -41
- data/app/views/lookbook/nav/_collection.html.erb +0 -5
- data/app/views/lookbook/nav/_leaf.html.erb +0 -22
- data/app/views/lookbook/nav/_node.html.erb +0 -19
- data/app/views/lookbook/nav/_preview.html.erb +0 -11
- data/app/views/lookbook/preview/group.html.erb +0 -8
- data/app/views/lookbook/shared/_sidebar.html.erb +0 -45
- data/app/views/lookbook/shared/_workbench.html.erb +0 -12
- data/app/views/lookbook/workbench/_header.html.erb +0 -39
- data/app/views/lookbook/workbench/_inspector.html.erb +0 -38
- data/app/views/lookbook/workbench/inspector/_code.html.erb +0 -3
- data/app/views/lookbook/workbench/inspector/_notes.html.erb +0 -24
- data/app/views/lookbook/workbench/inspector/_params.html.erb +0 -28
- data/app/views/lookbook/workbench/inspector/_plain.html.erb +0 -3
- data/public/lookbook-assets/app.css +0 -2626
- data/public/lookbook-assets/app.js +0 -8718
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import config from "../config";
|
|
2
|
+
|
|
3
|
+
export default function createSidebarStore(Alpine) {
|
|
4
|
+
const { defaultWidth, minWidth, maxWidth } = config.sidebar;
|
|
5
|
+
return {
|
|
6
|
+
open: Alpine.$persist(false).as("sidebar-open"),
|
|
7
|
+
width: Alpine.$persist(defaultWidth).as("sidebar-width"),
|
|
8
|
+
minWidth,
|
|
9
|
+
maxWidth,
|
|
10
|
+
toggle() {
|
|
11
|
+
Alpine.store("sidebar").open = !Alpine.store("sidebar").open;
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
}
|
|
@@ -1,52 +1,44 @@
|
|
|
1
|
-
require "htmlbeautifier"
|
|
2
|
-
|
|
3
1
|
module Lookbook
|
|
4
2
|
class AppController < ActionController::Base
|
|
5
3
|
EXCEPTIONS = [ViewComponent::PreviewTemplateError, ViewComponent::ComponentError, ViewComponent::TemplateError, ActionView::Template::Error]
|
|
6
4
|
|
|
7
5
|
protect_from_forgery with: :exception
|
|
8
|
-
prepend_view_path File.expand_path("../../views/lookbook", __dir__)
|
|
9
|
-
|
|
10
|
-
layout "layouts/app"
|
|
11
6
|
helper Lookbook::ApplicationHelper
|
|
12
7
|
|
|
13
8
|
before_action :find_preview, only: [:preview, :show]
|
|
14
9
|
before_action :find_example, only: [:preview, :show]
|
|
15
|
-
before_action :
|
|
16
|
-
|
|
10
|
+
before_action :build_nav
|
|
11
|
+
|
|
12
|
+
def self.controller_path
|
|
13
|
+
"lookbook"
|
|
14
|
+
end
|
|
17
15
|
|
|
18
16
|
def preview
|
|
19
17
|
if @example
|
|
20
|
-
|
|
18
|
+
set_params
|
|
19
|
+
render html: render_examples(examples_data)
|
|
21
20
|
else
|
|
22
|
-
render "
|
|
21
|
+
render "not_found"
|
|
23
22
|
end
|
|
24
23
|
end
|
|
25
24
|
|
|
26
25
|
def show
|
|
27
26
|
if @example
|
|
28
27
|
begin
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
assign_inspector
|
|
28
|
+
set_params
|
|
29
|
+
@examples = examples_data
|
|
30
|
+
@preview_srcdoc = render_examples(examples_data).gsub("\"", """)
|
|
31
|
+
@panels = panels.filter { |name, panel| panel[:show] }
|
|
34
32
|
rescue *EXCEPTIONS
|
|
35
|
-
render "
|
|
33
|
+
render "error"
|
|
36
34
|
end
|
|
37
35
|
else
|
|
38
|
-
render "
|
|
36
|
+
render "not_found"
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
39
|
|
|
42
40
|
private
|
|
43
41
|
|
|
44
|
-
def initialize_inspector
|
|
45
|
-
@source = []
|
|
46
|
-
@output = []
|
|
47
|
-
@notes = []
|
|
48
|
-
end
|
|
49
|
-
|
|
50
42
|
def find_preview
|
|
51
43
|
candidates = []
|
|
52
44
|
params[:path].to_s.scan(%r{/|$}) { candidates << $` }
|
|
@@ -65,101 +57,47 @@ module Lookbook
|
|
|
65
57
|
end
|
|
66
58
|
end
|
|
67
59
|
|
|
68
|
-
def
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
60
|
+
def examples_data
|
|
61
|
+
@examples_data ||= (@example.type == :group ? @example.examples : [@example]).map do |example|
|
|
62
|
+
example_data(example)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def example_data(example)
|
|
75
67
|
render_args = @preview.render_args(example.name, params: preview_controller.params.permit!)
|
|
76
68
|
has_template = render_args[:template] != "view_components/preview"
|
|
77
|
-
|
|
78
|
-
label:
|
|
79
|
-
|
|
80
|
-
|
|
69
|
+
{
|
|
70
|
+
label: example.label,
|
|
71
|
+
notes: example.notes,
|
|
72
|
+
html: preview_controller.render_example_to_string(@preview, example.name),
|
|
73
|
+
source: has_template ? example.template_source(render_args[:template]) : example.method_source,
|
|
74
|
+
source_lang: has_template ? example.template_lang(render_args[:template]) : example.source_lang,
|
|
75
|
+
params: enabled?(:params) ? example.params : []
|
|
81
76
|
}
|
|
82
|
-
if example.notes.present?
|
|
83
|
-
@notes << {
|
|
84
|
-
label: example.label,
|
|
85
|
-
content: example.notes
|
|
86
|
-
}
|
|
87
|
-
end
|
|
88
77
|
end
|
|
89
78
|
|
|
90
|
-
def
|
|
91
|
-
|
|
92
|
-
examples = @example.examples.map do |example|
|
|
93
|
-
{
|
|
94
|
-
label: example.label,
|
|
95
|
-
html: preview_controller.render_example_to_string(@preview, example.name)
|
|
96
|
-
}
|
|
97
|
-
end
|
|
98
|
-
set_params
|
|
99
|
-
preview_controller.render_in_layout_to_string("lookbook/preview/group", {examples: examples}, @preview.lookbook_layout)
|
|
100
|
-
else
|
|
101
|
-
set_params(@example)
|
|
102
|
-
preview_controller.params[:path] = "#{@preview.preview_name}/#{@example.name}".chomp("/")
|
|
103
|
-
preview_controller.process(:previews)
|
|
104
|
-
end
|
|
79
|
+
def render_examples(examples)
|
|
80
|
+
preview_controller.render_in_layout_to_string("layouts/lookbook/preview", {examples: examples}, @preview.lookbook_layout)
|
|
105
81
|
end
|
|
106
82
|
|
|
107
|
-
def set_params
|
|
108
|
-
if
|
|
83
|
+
def set_params
|
|
84
|
+
if enabled?(:params)
|
|
109
85
|
# cast known params to type
|
|
110
|
-
example.params.each do |param|
|
|
86
|
+
@example.params.each do |param|
|
|
111
87
|
if preview_controller.params.key?(param[:name])
|
|
112
88
|
preview_controller.params[param[:name]] = Lookbook::Params.cast(preview_controller.params[param[:name]], param[:type])
|
|
113
89
|
end
|
|
114
90
|
end
|
|
115
91
|
end
|
|
116
92
|
# set display params
|
|
117
|
-
example_params = example.nil? ? @preview.display_params : example.display_params
|
|
118
93
|
preview_controller.params.merge!({
|
|
119
94
|
lookbook: {
|
|
120
|
-
display:
|
|
95
|
+
display: @example.display_params
|
|
121
96
|
}
|
|
122
97
|
})
|
|
123
98
|
end
|
|
124
99
|
|
|
125
|
-
def
|
|
126
|
-
@inspector = {
|
|
127
|
-
panes: {
|
|
128
|
-
source: {
|
|
129
|
-
label: "Source",
|
|
130
|
-
template: "code",
|
|
131
|
-
hotkey: "s",
|
|
132
|
-
items: @source,
|
|
133
|
-
clipboard: @source.map { |s| @source.many? ? "#{s[:label]}\n#{s[:content]}" : s[:content] }.join("\n\n")
|
|
134
|
-
},
|
|
135
|
-
output: {
|
|
136
|
-
label: "Output",
|
|
137
|
-
template: "code",
|
|
138
|
-
hotkey: "o",
|
|
139
|
-
items: @output,
|
|
140
|
-
clipboard: @output.map { |o| @output.many? ? "#{o[:label]}\n#{o[:content]}" : o[:content] }.join("\n\n")
|
|
141
|
-
},
|
|
142
|
-
notes: {
|
|
143
|
-
label: "Notes",
|
|
144
|
-
template: "notes",
|
|
145
|
-
hotkey: "n",
|
|
146
|
-
items: @notes,
|
|
147
|
-
disabled: @notes.none?
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
if enabled?(:params)
|
|
152
|
-
@inspector[:panes][:params] = {
|
|
153
|
-
label: "Params",
|
|
154
|
-
template: "params",
|
|
155
|
-
hotkey: "p",
|
|
156
|
-
items: @source.many? ? [] : @example.params,
|
|
157
|
-
disabled: @source.many? || @example.params.none?
|
|
158
|
-
}
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
def assign_nav
|
|
100
|
+
def build_nav
|
|
163
101
|
@nav = Collection.new
|
|
164
102
|
previews.reject { |p| p.hidden? }.each do |preview|
|
|
165
103
|
current = @nav
|
|
@@ -179,6 +117,41 @@ module Lookbook
|
|
|
179
117
|
@nav
|
|
180
118
|
end
|
|
181
119
|
|
|
120
|
+
def panels
|
|
121
|
+
{
|
|
122
|
+
source: {
|
|
123
|
+
label: "Source",
|
|
124
|
+
template: "lookbook/panels/source",
|
|
125
|
+
hotkey: "s",
|
|
126
|
+
show: true,
|
|
127
|
+
disabled: false,
|
|
128
|
+
copy: true
|
|
129
|
+
},
|
|
130
|
+
output: {
|
|
131
|
+
label: "Output",
|
|
132
|
+
template: "lookbook/panels/output",
|
|
133
|
+
hotkey: "o",
|
|
134
|
+
show: true,
|
|
135
|
+
disabled: false,
|
|
136
|
+
copy: true
|
|
137
|
+
},
|
|
138
|
+
notes: {
|
|
139
|
+
label: "Notes",
|
|
140
|
+
template: "lookbook/panels/notes",
|
|
141
|
+
hotkey: "n",
|
|
142
|
+
show: true,
|
|
143
|
+
disabled: @examples.filter { |e| e[:notes].present? }.none?
|
|
144
|
+
},
|
|
145
|
+
params: {
|
|
146
|
+
label: "Params",
|
|
147
|
+
template: "lookbook/panels/params",
|
|
148
|
+
hotkey: "p",
|
|
149
|
+
show: enabled?(:params),
|
|
150
|
+
disabled: @example.type == :group || @example.params.none?
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
end
|
|
154
|
+
|
|
182
155
|
def previews
|
|
183
156
|
Lookbook::Preview.all.sort_by(&:label)
|
|
184
157
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require "redcarpet"
|
|
2
2
|
require "rouge"
|
|
3
|
+
require "htmlbeautifier"
|
|
3
4
|
|
|
4
5
|
module Lookbook
|
|
5
6
|
module ApplicationHelper
|
|
@@ -16,14 +17,57 @@ module Lookbook
|
|
|
16
17
|
markdown.render(text).html_safe
|
|
17
18
|
end
|
|
18
19
|
|
|
19
|
-
def highlight(source, language)
|
|
20
|
-
formatter =
|
|
20
|
+
def highlight(source, language, opts = {})
|
|
21
|
+
formatter = Lookbook::CodeFormatter.new(opts)
|
|
21
22
|
lexer = Rouge::Lexer.find(language)
|
|
22
23
|
formatter.format(lexer.lex(source)).html_safe
|
|
23
24
|
end
|
|
24
25
|
|
|
25
|
-
def
|
|
26
|
-
|
|
26
|
+
def beautify(source, language = "html")
|
|
27
|
+
source = source.strip
|
|
28
|
+
result = language.downcase == "html" ? HtmlBeautifier.beautify(source) : source
|
|
29
|
+
result.strip.html_safe
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def icon(name = nil, size: 4, **attrs)
|
|
33
|
+
render "lookbook/components/icon",
|
|
34
|
+
name: name,
|
|
35
|
+
size: size,
|
|
36
|
+
classes: class_names(attrs[:class]),
|
|
37
|
+
**attrs.except(:class)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def component(name, **attrs, &block)
|
|
41
|
+
render "lookbook/components/#{name}",
|
|
42
|
+
classes: class_names(attrs[:class]),
|
|
43
|
+
**attrs.except(:class),
|
|
44
|
+
&block
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if Rails.version.to_f < 6.1
|
|
48
|
+
def class_names(*args)
|
|
49
|
+
tokens = build_tag_values(*args).flat_map { |value| value.to_s.split(/\s+/) }.uniq
|
|
50
|
+
safe_join(tokens, " ")
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def build_tag_values(*args)
|
|
57
|
+
tag_values = []
|
|
58
|
+
args.each do |tag_value|
|
|
59
|
+
case tag_value
|
|
60
|
+
when Hash
|
|
61
|
+
tag_value.each do |key, val|
|
|
62
|
+
tag_values << key.to_s if val && key.present?
|
|
63
|
+
end
|
|
64
|
+
when Array
|
|
65
|
+
tag_values.concat build_tag_values(*tag_value)
|
|
66
|
+
else
|
|
67
|
+
tag_values << tag_value.to_s if tag_value.present?
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
tag_values
|
|
27
71
|
end
|
|
28
72
|
end
|
|
29
73
|
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" class="h-screen">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
|
7
|
+
|
|
8
|
+
<link href="/lookbook-assets/css/app.css?v=<%= Lookbook::VERSION %>" rel="stylesheet">
|
|
9
|
+
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>👀</text></svg>">
|
|
10
|
+
|
|
11
|
+
<% if config.auto_refresh %>
|
|
12
|
+
<script>
|
|
13
|
+
window.SOCKET_PATH = "<%= Lookbook::Engine.websocket_mount_path %>";
|
|
14
|
+
</script>
|
|
15
|
+
<% end %>
|
|
16
|
+
<script src="/lookbook-assets/js/app.js?v=<%= Lookbook::VERSION %>" defer></script>
|
|
17
|
+
|
|
18
|
+
<title><%= [@example&.label, @preview&.label, "Lookbook"].compact.join(" :: ") %></title>
|
|
19
|
+
</head>
|
|
20
|
+
<body class="text-gray-800 font-sans text-sm antialiased overflow-hidden">
|
|
21
|
+
<div
|
|
22
|
+
id="page"
|
|
23
|
+
x-data="page"
|
|
24
|
+
:style="`grid-template-columns: ${$store.sidebar.width}px 1px 1fr;`"
|
|
25
|
+
@popstate.window="update"
|
|
26
|
+
@resize.window="$store.layout.desktop = window.innerWidth >= $store.layout.desktopWidth"
|
|
27
|
+
class="md:grid w-screen h-screen"
|
|
28
|
+
>
|
|
29
|
+
<div class="h-full bg-gray-100 overflow-hidden flex flex-col" x-show="$store.layout.desktop || $store.sidebar.open" x-cloak>
|
|
30
|
+
<div class="bg-white h-10 border-b border-gray-300 flex flex-none items-center relative">
|
|
31
|
+
<button class="flex-none ml-4 md:hidden" @click="$store.sidebar.toggle">
|
|
32
|
+
<%= icon "x", size: 4, class: "hover:text-indigo-500" %>
|
|
33
|
+
</button>
|
|
34
|
+
<%= component "filter" %>
|
|
35
|
+
</div>
|
|
36
|
+
<div class="flex-grow overflow-y-auto">
|
|
37
|
+
<%= component "nav", items: @nav.items %>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
<div
|
|
41
|
+
x-data="splitter('vertical', {minSize: $store.sidebar.minWidth})"
|
|
42
|
+
class="h-full gutter border-r border-gray-300 relative"
|
|
43
|
+
x-show="$store.layout.desktop"
|
|
44
|
+
x-effect="$store.sidebar.width = Math.min(splits[0] || $store.sidebar.width, $store.sidebar.maxWidth)"
|
|
45
|
+
x-cloak
|
|
46
|
+
>
|
|
47
|
+
<div class="w-[9px] h-full bg-transparent hover:bg-indigo-100 hover:bg-opacity-20 transition absolute top-0 bottom-0 transform -translate-x-1/2 cursor-[col-resize] z-10"></div>
|
|
48
|
+
</div>
|
|
49
|
+
<main id="main" class="h-full overflow-hidden w-full" x-show="$store.layout.desktop || !$store.sidebar.open" x-cloak>
|
|
50
|
+
<%= yield %>
|
|
51
|
+
</main>
|
|
52
|
+
</div>
|
|
53
|
+
</body>
|
|
54
|
+
</html>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<% if examples.many? %>
|
|
2
|
+
<% examples.each do |example| %>
|
|
3
|
+
<div style="all: unset; margin-bottom: 30px; display: block;">
|
|
4
|
+
<h6 style="all: unset; display: block; color: #999; font-family: sans-serif; font-size: 14px; margin-top: 0; margin-bottom: 10px;">
|
|
5
|
+
<%= example[:label] %>
|
|
6
|
+
</h6>
|
|
7
|
+
<%= example[:html] %>
|
|
8
|
+
</div>
|
|
9
|
+
<% end %>
|
|
10
|
+
<% else %>
|
|
11
|
+
<%= examples.first[:html] %>
|
|
12
|
+
<% end %>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<%
|
|
2
|
+
line_numbers ||= false
|
|
3
|
+
language ||= "html"
|
|
4
|
+
%>
|
|
5
|
+
<% code = capture do %><%= yield %><% end %>
|
|
6
|
+
<div class="code <%= "numbered" if line_numbers %> <%= classes %>">
|
|
7
|
+
<pre><code class="highlight"><%= highlight(code.strip, language, line_numbers: line_numbers) %></code></pre>
|
|
8
|
+
</div>
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
<button
|
|
2
|
-
class="p-1.5 border-b border-l border-gray-200 hover:border-gray-300 rounded-bl-md bg-white absolute top-0 right-0 text-gray-400
|
|
3
|
-
x-data="
|
|
2
|
+
class="p-1.5 border-b border-l border-gray-200 hover:border-gray-300 rounded-bl-md bg-white absolute top-0 right-0 text-gray-400 transition"
|
|
3
|
+
x-data="copy('<%= target %>')"
|
|
4
4
|
x-tooltip.theme.lookbook="done ? 'copied!' : 'copy to clipboard'"
|
|
5
5
|
@click="save"
|
|
6
|
+
:class="{'!text-green-600 hover:text-green-600': done, 'hover:text-indigo-500': !done}"
|
|
6
7
|
data-tippy-placement="left">
|
|
7
|
-
|
|
8
|
-
<use x-bind:href="`/lookbook-assets/feather-sprite.svg#${done ? 'check' : 'clipboard'}`" />
|
|
9
|
-
</svg>
|
|
8
|
+
<%= icon "${done ? 'check' : 'clipboard'}", size: 4 %>
|
|
10
9
|
<div class="hidden" x-init="content = $el.innerText"><%== yield %></div>
|
|
11
10
|
</button>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<div x-data="filter" class="flex items-center w-full">
|
|
2
|
+
<input
|
|
3
|
+
type="text"
|
|
4
|
+
class="text-sm px-4 h-10 w-full border-0 bg-transparent focus:outline-none outline-none focus:ring-0"
|
|
5
|
+
placeholder="Filter previews…"
|
|
6
|
+
x-ref="input"
|
|
7
|
+
x-model="$store.filter.raw"
|
|
8
|
+
x-effect="if (!$store.layout.desktop && $store.sidebar.open) focus()"
|
|
9
|
+
@keyup.stop="checkEsc"
|
|
10
|
+
@keyup.f.document="focus"
|
|
11
|
+
>
|
|
12
|
+
<button class="text-gray-400 hover:text-indigo-500 focus:ring-0 focus:outline-none absolute top-1/2 right-2 transform -translate-y-1/2" @click="clear">
|
|
13
|
+
<%= icon "x", size: 3, class: "hover:text-indigo-500" %>
|
|
14
|
+
</button>
|
|
15
|
+
</div>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<header class="py-2 px-4 w-full flex-none bg-white border-b border-gray-300 flex items-center h-10">
|
|
2
|
-
<button class="flex-none mr-3" x-show="!$
|
|
1
|
+
<header class="py-2 px-4 w-full flex-none bg-white border-b border-gray-300 flex items-center h-10 select-none">
|
|
2
|
+
<button class="flex-none mr-3" x-show="!$store.layout.desktop" @click="$store.sidebar.toggle">
|
|
3
3
|
<svg class="feather w-5 h-5 hover:text-indigo-500 transition">
|
|
4
4
|
<use xlink:href="/lookbook-assets/feather-sprite.svg#menu" />
|
|
5
5
|
</svg>
|
|
6
6
|
</button>
|
|
7
7
|
<%= yield %>
|
|
8
|
-
</header>
|
|
8
|
+
</header>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<nav id="nav" x-data="nav" @popstate.window="setActive">
|
|
2
|
+
<% if items.any? %>
|
|
3
|
+
<ul x-ref="items" class="divide-y divide-gray-300">
|
|
4
|
+
<% items.each do |node| %>
|
|
5
|
+
<%= component "nav_#{node.type}", node: node %>
|
|
6
|
+
<% end %>
|
|
7
|
+
</ul>
|
|
8
|
+
<div class="p-4 text-center" x-show="empty" x-cloak>
|
|
9
|
+
<em class="text-gray-400">No matching previews found.</em>
|
|
10
|
+
</div>
|
|
11
|
+
<% else %>
|
|
12
|
+
<div class="p-4">
|
|
13
|
+
<h4 class="text-gray-500 mb-1">No previews found.</h4>
|
|
14
|
+
<p class="text-gray-400 text-xs">Have you set your <a class="underline" href="https://viewcomponent.org/api.html#preview_paths">preview paths</a> config correctly?</p>
|
|
15
|
+
</div>
|
|
16
|
+
<% end %>
|
|
17
|
+
</nav>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<li id="nav-group-<%= node.id %>" class="<%= classes %>" x-data="navGroup" :class="{hidden}" x-cloak>
|
|
2
|
+
<div @click="toggle" class="nav-toggle py-[5px]" style="padding-left: calc((<%= node.hierarchy_depth - 1 %> * 12px) + 0.5rem);">
|
|
3
|
+
<%= icon "${open ? 'chevron-down' : 'chevron-right'}", size: 3, class: "mr-1 text-gray-500" %>
|
|
4
|
+
<%= icon node.type == :preview ? "layers" : "folder", size: 3.5, class: "mr-1.5 text-indigo-500" %>
|
|
5
|
+
<div class="nav-label <%= "font-bold" if node.type == :preview %>" <% if node.type == :preview %> @click.stop="toggle(); navigateToFirstChild()"<% end %>>
|
|
6
|
+
<%= node.label %>
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
<ul
|
|
10
|
+
x-ref="items"
|
|
11
|
+
x-show="open"
|
|
12
|
+
id="nav-group-<%= node.id %>-children-<%= node.type == :preview ? node.get_examples.reject(&:hidden?).size : node.items.size %> %>"
|
|
13
|
+
x-cloak
|
|
14
|
+
>
|
|
15
|
+
<%= yield %>
|
|
16
|
+
</ul>
|
|
17
|
+
</li>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%
|
|
2
|
+
path = show_path item.path
|
|
3
|
+
display ||= :item
|
|
4
|
+
label ||= item.label
|
|
5
|
+
%>
|
|
6
|
+
<li id="nav-item-<%= item.id %>" x-data="navItem(<%= item.matchers.to_json %>)" :class="{hidden}" data-path="<%= path %>" x-cloak>
|
|
7
|
+
<a href="<%= path %>"
|
|
8
|
+
class="nav-link pr-3 py-[5px] flex items-center w-full group transition hover:bg-gray-200 hover:bg-opacity-50"
|
|
9
|
+
style="padding-left: calc((<%= depth - 1 %> * 12px) + 0.5rem);"
|
|
10
|
+
x-ref="link"
|
|
11
|
+
:class="{'!bg-indigo-100':active}"
|
|
12
|
+
@click.stop.prevent="navigate"
|
|
13
|
+
>
|
|
14
|
+
<div class="relative w-3.5 h-3.5 mr-1.5 <%= "ml-[3px]" if display == :node %> " :class="active ? 'text-gray-900' : 'text-indigo-500'">
|
|
15
|
+
<%= icon display == :node ? "layers" : "eye", size: 3.5, class: "group-hover:text-indigo-800" %>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="truncate whitespace-nowrap select-none <%= "font-bold" if display == :node %>">
|
|
18
|
+
<%= label %>
|
|
19
|
+
</div>
|
|
20
|
+
</a>
|
|
21
|
+
</li>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<% examples = node.get_examples.reject(&:hidden?) %>
|
|
2
|
+
<% if examples.many? %>
|
|
3
|
+
<%= component "nav_group", node: node, path: show_path(examples.first.path) do %>
|
|
4
|
+
<% examples.each do |example| %>
|
|
5
|
+
<%= component "nav_item", item: example, depth: example.hierarchy_depth + 1 %>
|
|
6
|
+
<% end %>
|
|
7
|
+
<% end %>
|
|
8
|
+
<% else %>
|
|
9
|
+
<% example = examples.first %>
|
|
10
|
+
<%= component "nav_item", item: example, depth: example.hierarchy_depth, label: node.label, display: :node %>
|
|
11
|
+
<% end %>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<div
|
|
2
|
+
class="px-4 py-3"
|
|
3
|
+
x-data="param"
|
|
4
|
+
<% if i == 0 %>x-effect="if ($store.inspector.panels.active === 'params') setFocus()"<% end %>
|
|
5
|
+
>
|
|
6
|
+
<div class="flex items-start max-w-[800px]">
|
|
7
|
+
<div class="w-[200px] flex-none py-2">
|
|
8
|
+
<label for="param-<%= param[:name] %>" class="font-bold">
|
|
9
|
+
<%= param[:name].titleize %>
|
|
10
|
+
</label>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="flex-grow">
|
|
13
|
+
<%= render "lookbook/inputs/#{param[:input]}",
|
|
14
|
+
**param,
|
|
15
|
+
value: params.key?(param[:name]) ? params[param[:name]] : param[:default],
|
|
16
|
+
id: "#{@example.id}-param-#{param[:name]}-input"
|
|
17
|
+
%>
|
|
18
|
+
</div>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
<div id="preview" class="h-full md:h-auto md:min-h-0
|
|
2
|
-
<div class="relative mx-auto bg-white" x-data="
|
|
1
|
+
<div id="preview" class="h-full md:h-auto md:min-h-0 w-full bg-gray-50">
|
|
2
|
+
<div class="relative mx-auto bg-white h-full w-full" x-data="previewWindow" :style="`width: ${$store.layout.desktop ? $store.inspector.preview.width : '100%'}`" x-show="!showSource">
|
|
3
3
|
<iframe seamless
|
|
4
4
|
class="absolute h-full inset-0 w-full border-l border-gray-300 md:pr-4 md:-mx-px"
|
|
5
5
|
src="<%= url_for lookbook.preview_path %>"
|
|
6
|
-
|
|
6
|
+
srcdoc="<%== srcdoc %>"
|
|
7
7
|
frameborder="0"
|
|
8
|
-
x-data="
|
|
9
|
-
x-effect="
|
|
8
|
+
x-data="sizes"
|
|
9
|
+
x-effect="preview.width = width; preview.height = height;"
|
|
10
10
|
></iframe>
|
|
11
|
-
<div class="absolute opacity-0 inset-0 pointer-events-none" :class="{ 'pointer-events-none': !$store.
|
|
11
|
+
<div class="absolute opacity-0 inset-0 pointer-events-none" :class="{ 'pointer-events-none': !$store.layout.reflowing }"></div>
|
|
12
12
|
<div
|
|
13
13
|
class="border-l border-r border-gray-300 bg-white hover:bg-indigo-100 hover:bg-opacity-20 transition absolute right-0 inset-y-0 flex items-center w-4 cursor-[col-resize] select-none"
|
|
14
14
|
style="touch-action: none"
|
|
15
15
|
@pointerdown="onResizeStart"
|
|
16
16
|
@dblclick="toggleFullWidth"
|
|
17
|
-
x-show="$
|
|
17
|
+
x-show="$store.layout.desktop"
|
|
18
18
|
>
|
|
19
19
|
<svg class="h-4 w-4 text-gray-600 pointer-events-none" fill="currentColor" viewBox="0 0 24 24">
|
|
20
20
|
<path d="M8 5h2v14H8zM14 5h2v14h-2z"></path>
|
|
21
21
|
</svg>
|
|
22
22
|
</div>
|
|
23
23
|
</div>
|
|
24
|
-
</div>
|
|
24
|
+
</div>
|
|
File without changes
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<div class="flex flex-col h-full w-full">
|
|
2
|
+
<%= component "header" %>
|
|
3
|
+
<div class="flex flex-col items-center justify-center h-full">
|
|
4
|
+
<div class="p-4 text-center">
|
|
5
|
+
<%= icon "layers", size: 10, class: "text-gray-300 mx-auto" %>
|
|
6
|
+
<h5 class="mt-4 text-gray-400 text-base">Select a preview to get started</h5>
|
|
7
|
+
</div>
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<div id="<%= id %>" x-init="checked = <%= value == true || value == "true" ? "true" : "false" %>"
|
|
1
|
+
<div id="<%= id %>" x-init="checked = <%= value == true || value == "true" ? "true" : "false" %>" x-ref="input">
|
|
2
2
|
<button type="button"
|
|
3
3
|
class="relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-400"
|
|
4
4
|
:class="{'bg-indigo-500': checked, 'bg-gray-300': !checked}"
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
<div class="bg-white flex flex-col items-center justify-center h-screen w-full">
|
|
2
2
|
<div class="p-4 text-center">
|
|
3
|
-
|
|
4
|
-
<use xlink:href="/lookbook-assets/feather-sprite.svg#alert-triangle" />
|
|
5
|
-
</svg>
|
|
3
|
+
<%= icon "alert-triangle", size: 10, class: "text-red-300 mx-auto" %>
|
|
6
4
|
<div class="mt-3 text-gray-700 max-w-xs">
|
|
7
5
|
<% if @preview %>
|
|
8
6
|
<div data-role="example-not-found">
|
|
9
7
|
<h5 class="text-base">Not found</h5>
|
|
10
8
|
<p class="mt-2 text-gray-400 text-sm">
|
|
11
|
-
The "<span class="text-gray-500"><%= @preview.
|
|
9
|
+
The "<span class="text-gray-500"><%= @preview.label %></span>" preview does not have an example named "<span class="text-gray-500"><%= @example_name %></span>".
|
|
12
10
|
</p>
|
|
13
11
|
</div>
|
|
14
12
|
<% else %>
|