lookbook 0.4.8 → 0.5.0
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/README.md +35 -21
- data/app/assets/lookbook/css/app.css +24 -13
- data/app/assets/lookbook/css/tooltip_theme.css +28 -0
- data/app/assets/lookbook/js/app.js +4 -0
- data/app/assets/lookbook/js/components/code.js +5 -0
- data/app/assets/lookbook/js/components/copy.js +4 -2
- data/app/assets/lookbook/js/components/filter.js +1 -1
- data/app/assets/lookbook/js/components/inspector.js +54 -9
- data/app/assets/lookbook/js/components/nav-group.js +1 -1
- data/app/assets/lookbook/js/components/nav-item.js +1 -0
- data/app/assets/lookbook/js/components/nav.js +1 -1
- data/app/assets/lookbook/js/components/page.js +17 -5
- data/app/assets/lookbook/js/components/param.js +23 -7
- data/app/assets/lookbook/js/components/preview-window.js +95 -26
- data/app/assets/lookbook/js/components/tabs.js +50 -0
- data/app/assets/lookbook/js/config.js +11 -4
- data/app/assets/lookbook/js/lib/socket.js +1 -1
- data/app/assets/lookbook/js/stores/inspector.js +13 -5
- data/app/controllers/lookbook/app_controller.rb +23 -9
- data/app/views/layouts/lookbook/app.html.erb +9 -3
- data/app/views/lookbook/components/_code.html.erb +6 -1
- data/app/views/lookbook/components/_drawer.html.erb +124 -0
- data/app/views/lookbook/components/_filter.html.erb +1 -1
- data/app/views/lookbook/components/_header.html.erb +2 -2
- data/app/views/lookbook/components/_nav.html.erb +1 -1
- data/app/views/lookbook/components/_nav_group.html.erb +11 -14
- data/app/views/lookbook/components/_nav_item.html.erb +17 -15
- data/app/views/lookbook/components/_nav_preview.html.erb +4 -2
- data/app/views/lookbook/components/_param.html.erb +6 -5
- data/app/views/lookbook/components/_preview.html.erb +67 -20
- data/app/views/lookbook/inputs/_select.html.erb +2 -3
- data/app/views/lookbook/inputs/_text.html.erb +3 -3
- data/app/views/lookbook/inputs/_textarea.html.erb +3 -3
- data/app/views/lookbook/inputs/_toggle.html.erb +5 -5
- data/app/views/lookbook/panels/_notes.html.erb +1 -1
- data/app/views/lookbook/panels/_output.html.erb +2 -2
- data/app/views/lookbook/panels/_params.html.erb +1 -1
- data/app/views/lookbook/panels/_preview.html.erb +52 -0
- data/app/views/lookbook/panels/_source.html.erb +2 -2
- data/app/views/lookbook/show.html.erb +22 -88
- data/lib/lookbook/code_formatter.rb +3 -3
- data/lib/lookbook/features.rb +1 -1
- data/lib/lookbook/preview.rb +1 -1
- data/lib/lookbook/version.rb +1 -1
- data/public/lookbook-assets/css/app.css +3 -1
- data/public/lookbook-assets/css/app.css.map +1 -1
- data/public/lookbook-assets/js/app.js +1 -1
- data/public/lookbook-assets/js/app.js.map +1 -1
- metadata +6 -3
- data/app/views/lookbook/components/_copy.html.erb +0 -10
@@ -0,0 +1,50 @@
|
|
1
|
+
import tippy from "tippy.js";
|
2
|
+
|
3
|
+
export default function tabs() {
|
4
|
+
return {
|
5
|
+
width: 0,
|
6
|
+
tabsWidth: 0,
|
7
|
+
init() {
|
8
|
+
const ro = new ResizeObserver((entries) => {
|
9
|
+
this.width = Math.round(entries[0].contentRect.width);
|
10
|
+
});
|
11
|
+
ro.observe(this.$refs.tabs);
|
12
|
+
this.dropdown = tippy(this.$refs.toggle, {
|
13
|
+
allowHTML: true,
|
14
|
+
interactive: true,
|
15
|
+
trigger: "click",
|
16
|
+
placement: "bottom-end",
|
17
|
+
theme: "menu",
|
18
|
+
content: this.$refs.dropdown,
|
19
|
+
});
|
20
|
+
},
|
21
|
+
get tabs() {
|
22
|
+
return Array.from(this.$refs.tabs.querySelectorAll(":scope > a"));
|
23
|
+
},
|
24
|
+
get visibleTabCount() {
|
25
|
+
let cumulativeWidth = 0;
|
26
|
+
for (let i = 0; i < this.tabs.length; i++) {
|
27
|
+
const el = this.tabs[i];
|
28
|
+
const margin = parseInt(
|
29
|
+
window
|
30
|
+
.getComputedStyle(el)
|
31
|
+
.getPropertyValue("margin-left")
|
32
|
+
.replace("px", ""),
|
33
|
+
10
|
34
|
+
);
|
35
|
+
cumulativeWidth += el.clientWidth + margin;
|
36
|
+
if (cumulativeWidth > this.width) {
|
37
|
+
this.tabsWidth = cumulativeWidth - el.clientWidth;
|
38
|
+
return i;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
return this.tabs.length;
|
42
|
+
},
|
43
|
+
get hiddenTabs() {
|
44
|
+
return this.tabs.slice(this.visibleTabCount, -1);
|
45
|
+
},
|
46
|
+
hideDropdown() {
|
47
|
+
this.dropdown.hide();
|
48
|
+
},
|
49
|
+
};
|
50
|
+
}
|
@@ -3,12 +3,19 @@ export default {
|
|
3
3
|
sidebar: {
|
4
4
|
defaultWidth: 280,
|
5
5
|
minWidth: 200,
|
6
|
-
maxWidth:
|
6
|
+
maxWidth: 350,
|
7
7
|
},
|
8
8
|
inspector: {
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
drawer: {
|
10
|
+
orientation: "horizontal",
|
11
|
+
defaultPanel: "source",
|
12
|
+
defaultHeight: 300,
|
13
|
+
defaultWidth: 500,
|
14
|
+
minWidth: 350,
|
15
|
+
minHeight: 200,
|
16
|
+
},
|
17
|
+
preview: {
|
18
|
+
defaultPanel: "preview",
|
12
19
|
},
|
13
20
|
},
|
14
21
|
};
|
@@ -1,17 +1,25 @@
|
|
1
1
|
import config from "../config";
|
2
2
|
|
3
3
|
export default function createInspectorStore(Alpine) {
|
4
|
-
const {
|
4
|
+
const { drawer, preview } = config.inspector;
|
5
5
|
return {
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
drawer: {
|
7
|
+
hidden: Alpine.$persist(false).as("drawer-hidden"),
|
8
|
+
orientation: Alpine.$persist(drawer.orientation).as("drawer-orientation"),
|
9
|
+
panel: Alpine.$persist(drawer.defaultPanel).as("drawer-panel"),
|
10
|
+
height: Alpine.$persist(drawer.defaultHeight).as("drawer-height"),
|
11
|
+
width: Alpine.$persist(drawer.defaultWidth).as("drawer-width"),
|
12
|
+
minWidth: drawer.minWidth,
|
13
|
+
minHeight: drawer.minHeight,
|
14
|
+
visibleTabCount: Infinity,
|
9
15
|
},
|
10
16
|
preview: {
|
11
17
|
width: Alpine.$persist("100%").as("preview-width"),
|
12
18
|
height: Alpine.$persist("100%").as("preview-height"),
|
13
|
-
|
19
|
+
panel: Alpine.$persist(preview.defaultPanel).as("preview-panel"),
|
14
20
|
lastWidth: null,
|
21
|
+
lastHeight: null,
|
22
|
+
resizing: false,
|
15
23
|
},
|
16
24
|
};
|
17
25
|
}
|
@@ -27,8 +27,8 @@ module Lookbook
|
|
27
27
|
begin
|
28
28
|
set_params
|
29
29
|
@examples = examples_data
|
30
|
-
@
|
31
|
-
@
|
30
|
+
@drawer_panels = drawer_panels.filter { |name, panel| panel[:show] }
|
31
|
+
@preview_panels = preview_panels.filter { |name, panel| panel[:show] }
|
32
32
|
rescue *EXCEPTIONS
|
33
33
|
render "error"
|
34
34
|
end
|
@@ -117,23 +117,37 @@ module Lookbook
|
|
117
117
|
@nav
|
118
118
|
end
|
119
119
|
|
120
|
-
def
|
120
|
+
def preview_panels
|
121
121
|
{
|
122
|
-
|
123
|
-
label: "
|
124
|
-
template: "lookbook/panels/
|
125
|
-
|
122
|
+
preview: {
|
123
|
+
label: "Preview",
|
124
|
+
template: "lookbook/panels/preview",
|
125
|
+
srcdoc: Lookbook.config.preview_srcdoc ? render_examples(examples_data).gsub("\"", """) : nil,
|
126
|
+
hotkey: "v",
|
126
127
|
show: true,
|
127
128
|
disabled: false,
|
128
|
-
copy:
|
129
|
+
copy: false
|
129
130
|
},
|
130
131
|
output: {
|
131
|
-
label: "
|
132
|
+
label: "HTML",
|
132
133
|
template: "lookbook/panels/output",
|
133
134
|
hotkey: "o",
|
134
135
|
show: true,
|
135
136
|
disabled: false,
|
136
137
|
copy: true
|
138
|
+
}
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
def drawer_panels
|
143
|
+
{
|
144
|
+
source: {
|
145
|
+
label: "Source",
|
146
|
+
template: "lookbook/panels/source",
|
147
|
+
hotkey: "s",
|
148
|
+
show: true,
|
149
|
+
disabled: false,
|
150
|
+
copy: true
|
137
151
|
},
|
138
152
|
notes: {
|
139
153
|
label: "Notes",
|
@@ -6,7 +6,9 @@
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
7
7
|
|
8
8
|
<link href="/lookbook-assets/css/app.css?v=<%= Lookbook::VERSION %>" rel="stylesheet">
|
9
|
-
|
9
|
+
<% if config.ui_favicon != false %>
|
10
|
+
<link rel="icon" href="<%= config.ui_favicon || "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>" %>">
|
11
|
+
<% end %>
|
10
12
|
|
11
13
|
<% if config.auto_refresh %>
|
12
14
|
<script>
|
@@ -44,9 +46,13 @@
|
|
44
46
|
x-effect="$store.sidebar.width = Math.min(splits[0] || $store.sidebar.width, $store.sidebar.maxWidth)"
|
45
47
|
x-cloak
|
46
48
|
>
|
47
|
-
<div class="w-[9px] h-full bg-transparent hover:bg-indigo-100 hover:bg-opacity-20 transition absolute top-0 bottom-0
|
49
|
+
<div class="w-[9px] h-full bg-transparent hover:bg-indigo-100 hover:bg-opacity-20 transition absolute top-0 bottom-0 -translate-x-1/2 cursor-[col-resize] z-10"></div>
|
48
50
|
</div>
|
49
|
-
<main
|
51
|
+
<main
|
52
|
+
id="main"
|
53
|
+
class="h-full overflow-hidden w-full"
|
54
|
+
x-show="$store.layout.desktop || !$store.sidebar.open" x-cloak
|
55
|
+
>
|
50
56
|
<%= yield %>
|
51
57
|
</main>
|
52
58
|
</div>
|
@@ -1,8 +1,13 @@
|
|
1
1
|
<%
|
2
2
|
line_numbers ||= false
|
3
3
|
language ||= "html"
|
4
|
+
wrap ||= nil;
|
4
5
|
%>
|
5
6
|
<% code = capture do %><%= yield %><% end %>
|
6
|
-
<div class="code <%= "numbered" if line_numbers %> <%= classes %>"
|
7
|
+
<div class="code <%= "numbered" if line_numbers %> <%= classes %>"
|
8
|
+
x-data="code"
|
9
|
+
:class="{'wrapped': wrap}"
|
10
|
+
<% if wrap.present? %>x-effect="wrap = <%= wrap %>"<% end %>
|
11
|
+
>
|
7
12
|
<pre><code class="highlight"><%= highlight(code.strip, language, line_numbers: line_numbers) %></code></pre>
|
8
13
|
</div>
|
@@ -0,0 +1,124 @@
|
|
1
|
+
<div id="drawer" class="bg-white w-full h-full flex flex-col min-w-0">
|
2
|
+
<div class="pl-4 border-b border-gray-300 select-none flex-none" x-show="!drawerHidden">
|
3
|
+
<div class="flex cursor-auto relative">
|
4
|
+
<div
|
5
|
+
id="inspector-tabs-<%= example.id %>"
|
6
|
+
x-data="tabs"
|
7
|
+
class="min-w-0 -mb-px"
|
8
|
+
x-effect="$store.inspector.drawer.visibleTabCount = visibleTabCount"
|
9
|
+
>
|
10
|
+
<nav x-ref="tabs" class="flex h-10 space-x-8 flex-grow pr-8">
|
11
|
+
<% panels.each.with_index(1) do |(key,props),i| %>
|
12
|
+
<a
|
13
|
+
id="inspector-tab-<%= key %>-<%= example.id %>"
|
14
|
+
href="#inspector-panel-<%= key %>"
|
15
|
+
class="whitespace-nowrap pt-2.5 pb-1.5 px-1 border-b-2 cursor-pointer <%= "!text-gray-300" if props[:disabled] %>"
|
16
|
+
:class="{
|
17
|
+
'border-indigo-400': isActiveDrawerPanel('<%= key %>'),
|
18
|
+
'border-transparent text-gray-500 hover:text-gray-700': !isActiveDrawerPanel('<%= key %>'),
|
19
|
+
'invisible': (<%= i %> > visibleTabCount)
|
20
|
+
}"
|
21
|
+
@click.stop.prevent="switchDrawerPanel('<%= key %>')"
|
22
|
+
<% if props[:hotkey] %>data-hotkey="<%= props[:hotkey] %>"<% end %>
|
23
|
+
>
|
24
|
+
<%== props[:label] %>
|
25
|
+
</a>
|
26
|
+
<% end %>
|
27
|
+
<div
|
28
|
+
x-ref="toggle"
|
29
|
+
x-show="visibleTabCount !== tabs.length"
|
30
|
+
class="flex-none absolute top-[9px]"
|
31
|
+
:style="`left: ${tabsWidth - 48}px`"
|
32
|
+
>
|
33
|
+
<button class="py-1 px-2 text-gray-500 hover:text-indigo-800">
|
34
|
+
<%= icon "chevrons-right", size: 3.5 %>
|
35
|
+
</button>
|
36
|
+
</div>
|
37
|
+
</nav>
|
38
|
+
<nav class="hidden">
|
39
|
+
<div x-ref="dropdown" class="min-w-[120px]">
|
40
|
+
<% panels.each.with_index(1) do |(key,props),i| %>
|
41
|
+
<template id="inspector-dropdown-tab-<%= key %>-<%= example.id %>" x-if="<%= i %> > $store.inspector.drawer.visibleTabCount">
|
42
|
+
<div :class="{'border-t border-gray-300': (<%= i %> > $store.inspector.drawer.visibleTabCount + 1)}">
|
43
|
+
<a
|
44
|
+
href="#inspector-panel-<%= key %>"
|
45
|
+
class="block whitespace-nowrap py-2 px-4 border-l-2 cursor-pointer <%= "!text-gray-300" if props[:disabled] %>"
|
46
|
+
:class="{
|
47
|
+
'border-indigo-400': $store.inspector.drawer.panel === '<%= key %>',
|
48
|
+
'border-transparent text-gray-500 hover:text-gray-700': $store.inspector.drawer.panel !== '<%= key %>',
|
49
|
+
}"
|
50
|
+
@click.stop.prevent=" hideDropdown(); switchDrawerPanel('<%= key %>')"
|
51
|
+
>
|
52
|
+
<%== props[:label] %>
|
53
|
+
</a>
|
54
|
+
</div>
|
55
|
+
</template>
|
56
|
+
<% end %>
|
57
|
+
</div>
|
58
|
+
</nav>
|
59
|
+
</div>
|
60
|
+
<div class="flex items-center bg-white border-l border-gray-200 ml-auto space-x-3 px-3">
|
61
|
+
<div>
|
62
|
+
<% panels.each do |key, props| %>
|
63
|
+
<div
|
64
|
+
ref="<%= "inspector-panel-#{example.id}-#{key}-copy" %>"
|
65
|
+
class="flex items-center"
|
66
|
+
:class="{'pointer-events-none opacity-30': <%= !props[:copy].present? %>}"
|
67
|
+
x-show="isActiveDrawerPanel('<%= key %>')"
|
68
|
+
x-cloak
|
69
|
+
>
|
70
|
+
<button
|
71
|
+
data-target="<%= "inspector-panel-#{example.id}-#{key}-clipboard" %>"
|
72
|
+
class="text-gray-400 transition"
|
73
|
+
x-data="copy"
|
74
|
+
x-tooltip.theme.lookbook="done ? 'copied!' : 'copy to clipboard'"
|
75
|
+
@click="save"
|
76
|
+
:class="{
|
77
|
+
'!text-green-600 hover:text-green-600': done,
|
78
|
+
'hover:text-indigo-500': !done}"
|
79
|
+
x-cloak
|
80
|
+
<% unless props[:copy].present? %>disabled<% end %>
|
81
|
+
>
|
82
|
+
<%= icon "${done ? 'check' : 'clipboard'}", size: 4 %>
|
83
|
+
</button>
|
84
|
+
</div>
|
85
|
+
<% end %>
|
86
|
+
</div>
|
87
|
+
<button
|
88
|
+
x-tooltip.theme.lookbook="`${horizontal ? 'pin drawer on right' : 'pin drawer on bottom'}`"
|
89
|
+
@click="toggleOrientation"
|
90
|
+
:class="{'pointer-events-none opacity-30': !canBeVertical}"
|
91
|
+
>
|
92
|
+
<%= icon "${horizontal ? 'sidebar' : 'credit-card'}",
|
93
|
+
size: 4,
|
94
|
+
class: "scale-[-1] text-gray-400 hover:text-indigo-800" %>
|
95
|
+
</button>
|
96
|
+
<button
|
97
|
+
x-tooltip.theme.lookbook="`hide drawer`"
|
98
|
+
@click="toggleDrawer"
|
99
|
+
>
|
100
|
+
<%= icon "x-circle",
|
101
|
+
size: 4,
|
102
|
+
class: "text-gray-400 hover:text-indigo-800" %>
|
103
|
+
</button>
|
104
|
+
</div>
|
105
|
+
</div>
|
106
|
+
</div>
|
107
|
+
<div class="bg-white relative flex-grow">
|
108
|
+
<% panels.each do |key, props| %>
|
109
|
+
<div
|
110
|
+
class="h-full w-full absolute inset-0"
|
111
|
+
x-show="isActiveDrawerPanel('<%= key %>')"
|
112
|
+
x-cloak
|
113
|
+
>
|
114
|
+
<div id="inspector-panel-<%= example.id %>-<%= key %>" class="h-full">
|
115
|
+
<%= render props[:template],
|
116
|
+
key: key,
|
117
|
+
examples: examples,
|
118
|
+
clipboard_id: "inspector-panel-#{example.id}-#{key}-clipboard",
|
119
|
+
**props %>
|
120
|
+
</div>
|
121
|
+
</div>
|
122
|
+
<% end %>
|
123
|
+
</div>
|
124
|
+
</div>
|
@@ -9,7 +9,7 @@
|
|
9
9
|
@keyup.stop="checkEsc"
|
10
10
|
@keyup.f.document="focus"
|
11
11
|
>
|
12
|
-
<button class="text-gray-400 hover:text-indigo-500 focus:ring-0 focus:outline-none absolute top-1/2 right-2
|
12
|
+
<button class="text-gray-400 hover:text-indigo-500 focus:ring-0 focus:outline-none absolute top-1/2 right-2 -translate-y-1/2" @click="clear">
|
13
13
|
<%= icon "x", size: 3, class: "hover:text-indigo-500" %>
|
14
14
|
</button>
|
15
15
|
</div>
|
@@ -1,5 +1,5 @@
|
|
1
|
-
<header class="
|
2
|
-
<button class="flex-none mr-
|
1
|
+
<header class="pl-4 w-full flex-none bg-white border-b border-gray-300 flex items-center h-10 select-none min-w-0">
|
2
|
+
<button class="flex-none mr-6" 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>
|
@@ -1,17 +1,14 @@
|
|
1
|
-
<li
|
2
|
-
<div
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
<%= node.
|
1
|
+
<li key="<%= node.id %>" class="<%= classes %>">
|
2
|
+
<div id="nav-group-<%= node.id %>" x-data="navGroup" :class="{hidden}" x-cloak>
|
3
|
+
<div @click="toggle" class="nav-toggle py-[5px]" style="padding-left: calc((<%= node.hierarchy_depth - 1 %> * 12px) + 0.5rem);">
|
4
|
+
<%= icon "${open ? 'chevron-down' : 'chevron-right'}", size: 3, class: "mr-1 text-gray-500" %>
|
5
|
+
<%= icon node.type == :preview ? "layers" : "folder", size: 3.5, class: "mr-1.5 text-indigo-500" %>
|
6
|
+
<div class="nav-label <%= "font-bold" if node.type == :preview %>" <% if node.type == :preview %> @click.stop="toggle(); navigateToFirstChild()"<% end %>>
|
7
|
+
<%= node.label %>
|
8
|
+
</div>
|
7
9
|
</div>
|
10
|
+
<ul x-ref="items" x-show="open" x-cloak>
|
11
|
+
<%= yield %>
|
12
|
+
</ul>
|
8
13
|
</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
14
|
</li>
|
@@ -3,19 +3,21 @@ path = show_path item.path
|
|
3
3
|
display ||= :item
|
4
4
|
label ||= item.label
|
5
5
|
%>
|
6
|
-
<li
|
7
|
-
<
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
<%=
|
16
|
-
|
17
|
-
|
18
|
-
<%=
|
19
|
-
|
20
|
-
|
6
|
+
<li key="<%= item.id %>">
|
7
|
+
<div id="nav-item-<%= item.id %>" x-data="navItem(<%= item.matchers.to_json %>)" :class="{hidden}" data-path="<%= path %>" x-cloak>
|
8
|
+
<a href="<%= path %>"
|
9
|
+
class="nav-link pr-3 py-[5px] flex items-center w-full group transition hover:bg-gray-200 hover:bg-opacity-50"
|
10
|
+
style="padding-left: calc((<%= depth - 1 %> * 12px) + 0.5rem);"
|
11
|
+
x-ref="link"
|
12
|
+
:class="{'!bg-indigo-100':active}"
|
13
|
+
@click.stop.prevent="navigate"
|
14
|
+
>
|
15
|
+
<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'">
|
16
|
+
<%= icon display == :node ? "layers" : "eye", size: 3.5, class: "group-hover:text-indigo-800" %>
|
17
|
+
</div>
|
18
|
+
<div class="truncate whitespace-nowrap select-none <%= "font-bold" if display == :node %>">
|
19
|
+
<%= label %>
|
20
|
+
</div>
|
21
|
+
</a>
|
22
|
+
</div>
|
21
23
|
</li>
|
@@ -6,6 +6,8 @@
|
|
6
6
|
<% end %>
|
7
7
|
<% end %>
|
8
8
|
<% else %>
|
9
|
-
<%
|
10
|
-
|
9
|
+
<% if examples.any? %>
|
10
|
+
<% example = examples.first %>
|
11
|
+
<%= component "nav_item", item: example, depth: example.hierarchy_depth, label: node.label, display: :node %>
|
12
|
+
<% end %>
|
11
13
|
<% end %>
|
@@ -1,10 +1,12 @@
|
|
1
|
+
<%
|
2
|
+
value = params.key?(param[:name]) ? params[param[:name]] : param[:default]
|
3
|
+
%>
|
1
4
|
<div
|
5
|
+
ref="<%= @example.id %>-param-<%= param[:name] %>-input"
|
2
6
|
class="px-4 py-3"
|
3
|
-
x-data="param"
|
4
|
-
<% if i == 0 %>x-effect="if ($store.inspector.panels.active === 'params') setFocus()"<% end %>
|
5
7
|
>
|
6
8
|
<div class="flex items-start max-w-[800px]">
|
7
|
-
<div class="
|
9
|
+
<div class="flex-none py-2" :style="`width: ${horizontal ? '200' : '120' }px`">
|
8
10
|
<label for="param-<%= param[:name] %>" class="font-bold">
|
9
11
|
<%= param[:name].titleize %>
|
10
12
|
</label>
|
@@ -12,8 +14,7 @@
|
|
12
14
|
<div class="flex-grow">
|
13
15
|
<%= render "lookbook/inputs/#{param[:input]}",
|
14
16
|
**param,
|
15
|
-
value:
|
16
|
-
id: "#{@example.id}-param-#{param[:name]}-input"
|
17
|
+
value: value
|
17
18
|
%>
|
18
19
|
</div>
|
19
20
|
</div>
|
@@ -1,24 +1,71 @@
|
|
1
|
-
<div id="preview" class="
|
2
|
-
|
3
|
-
<iframe seamless
|
4
|
-
class="absolute h-full inset-0 w-full border-l border-gray-300 md:pr-4 md:-mx-px"
|
5
|
-
src="<%= url_for lookbook.preview_path %>"
|
6
|
-
srcdoc="<%== srcdoc %>"
|
7
|
-
frameborder="0"
|
8
|
-
x-data="sizes"
|
9
|
-
x-effect="preview.width = width; preview.height = height;"
|
10
|
-
></iframe>
|
11
|
-
<div class="absolute opacity-0 inset-0 pointer-events-none" :class="{ 'pointer-events-none': !$store.layout.reflowing }"></div>
|
1
|
+
<div id="preview" class="grid grid-rows-[40px_1fr]">
|
2
|
+
<%= component "header" do %>
|
12
3
|
<div
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
4
|
+
id="preview-tabs-<%= @example.id %>" class="min-w-0 -mb-px">
|
5
|
+
<nav class="flex h-10 space-x-8 flex-grow pr-8">
|
6
|
+
<% panels.each do |key, props| %>
|
7
|
+
<a
|
8
|
+
id="preview-tab-<%= key %>-<%= @example.id %>"
|
9
|
+
href="#preview-panel-<%= key %>"
|
10
|
+
class="whitespace-nowrap pt-2.5 pb-1.5 px-1 border-b-2 cursor-pointer"
|
11
|
+
:class="{
|
12
|
+
'border-indigo-400': isActivePreviewPanel('<%= key %>'),
|
13
|
+
'border-transparent text-gray-500 hover:text-gray-700': !isActivePreviewPanel('<%= key %>'),
|
14
|
+
}"
|
15
|
+
@click.stop.prevent="switchPreviewPanel('<%= key %>')"
|
16
|
+
<% if props[:hotkey] %>data-hotkey="<%= props[:hotkey] %>"<% end %>
|
17
|
+
>
|
18
|
+
<%== props[:label] %>
|
19
|
+
</a>
|
20
|
+
<% end %>
|
21
|
+
</nav>
|
22
22
|
</div>
|
23
|
+
<div class="flex items-stretch h-full ml-auto space-x-3">
|
24
|
+
<div
|
25
|
+
class="flex items-center text-xs font-monospace text-gray-700 space-x-1 opacity-50 hover:opacity-100 transition"
|
26
|
+
:class="{'opacity-100': $store.inspector.preview.resizing}"
|
27
|
+
x-show="isActivePreviewPanel('preview')">
|
28
|
+
<span x-text="`${preview.width}px`"></span>
|
29
|
+
<span class="text-gray-500">x</span>
|
30
|
+
<span x-text="`${preview.height}px`"></span>
|
31
|
+
</div>
|
32
|
+
<div class="flex items-center bg-white border-l border-gray-200 space-x-3 text-gray-400 divide-x divide-gray-300 px-3">
|
33
|
+
<div class="flex items-center space-x-3">
|
34
|
+
<button
|
35
|
+
x-tooltip.theme.lookbook="`Refresh preview`"
|
36
|
+
@click.prevent.stop="refresh"
|
37
|
+
data-hotkey="r"
|
38
|
+
>
|
39
|
+
<%= icon "refresh-cw", size: 4, class: "hover:text-indigo-800" %>
|
40
|
+
</button>
|
41
|
+
<a
|
42
|
+
href="<%= preview_path %>"
|
43
|
+
target="_blank"
|
44
|
+
x-tooltip.theme.lookbook="`Open in new window`"
|
45
|
+
data-hotkey="w"
|
46
|
+
>
|
47
|
+
<%= icon "external-link", size: 4, class: "hover:text-indigo-800" %>
|
48
|
+
</a>
|
49
|
+
<button
|
50
|
+
x-tooltip.theme.lookbook="`${drawerHidden ? 'show' : 'hide'} drawer`"
|
51
|
+
@click="toggleDrawer"
|
52
|
+
x-show="drawerHidden"
|
53
|
+
data-hotkey="i"
|
54
|
+
>
|
55
|
+
<%= icon "${horizontal ? 'credit-card' : 'sidebar'}", size: 4, class: "hover:text-indigo-800 scale-[-1]" %>
|
56
|
+
</button>
|
57
|
+
</div>
|
58
|
+
|
59
|
+
</div>
|
60
|
+
</div>
|
61
|
+
<% end %>
|
62
|
+
<div class="bg-white relative flex-grow">
|
63
|
+
<% panels.each do |key, props| %>
|
64
|
+
<div class="h-full w-full absolute inset-0" x-show="isActivePreviewPanel('<%= key %>')" x-cloak>
|
65
|
+
<div id="preview-panel-<%= example.id %>-<%= key %>" class="h-full">
|
66
|
+
<%= render props[:template], key: key, examples: examples, **props %>
|
67
|
+
</div>
|
68
|
+
</div>
|
69
|
+
<% end %>
|
23
70
|
</div>
|
24
71
|
</div>
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<input
|
2
|
-
id="<%= id %>"
|
3
2
|
class="form-input"
|
4
3
|
type="<%= input_type %>"
|
5
4
|
name="<%= name %>"
|
6
5
|
value="<%= value %>"
|
7
|
-
|
8
|
-
x-
|
6
|
+
x-data="param('<%= name %>', '<%= value %>', {debounce: 300})"
|
7
|
+
x-model="value"
|
8
|
+
@keyup.stop>
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<textarea
|
2
|
-
id="<%= id %>"
|
3
2
|
class="form-input"
|
4
3
|
name="<%= name %>"
|
5
4
|
rows="4"
|
6
|
-
@keyup.stop
|
7
|
-
x-
|
5
|
+
@keyup.stop
|
6
|
+
x-model="value"
|
7
|
+
x-data="param('<%= name %>', '<%= value %>', {debounce: 300})"
|
8
8
|
><%= value %></textarea>
|
@@ -1,13 +1,13 @@
|
|
1
|
-
<div
|
1
|
+
<div x-data="param('<%= name %>', <%= value %>)" data-morph-strategy="replace">
|
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
|
-
:class="{'bg-indigo-500':
|
4
|
+
:class="{'bg-indigo-500': value, 'bg-gray-300': !value}"
|
5
5
|
role="switch"
|
6
|
-
@click.stop="
|
6
|
+
@click.stop="value = !value;">
|
7
7
|
<span
|
8
8
|
aria-hidden="true"
|
9
|
-
class="pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow
|
10
|
-
:class="{'translate-x-5':
|
9
|
+
class="pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow ring-0 transition ease-in-out duration-200"
|
10
|
+
:class="{'translate-x-5': value, 'translate-x-0': !value}"
|
11
11
|
></span>
|
12
12
|
</button>
|
13
13
|
</div>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% items = examples.filter { |example| example[:notes].present? } %>
|
2
|
-
<div class="text-gray-600 bg-gray-50
|
2
|
+
<div class="text-gray-600 bg-gray-50 h-full overflow-auto" data-morph-strategy="replace">
|
3
3
|
<% if items.many? %>
|
4
4
|
<div class="divide-y divide-dashed divide-gray-300">
|
5
5
|
<% items.each do |item| %>
|