lookbook 0.4.8 → 0.5.0.beta.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 +5 -3
- data/app/assets/lookbook/css/app.css +21 -13
- data/app/assets/lookbook/css/tooltip_theme.css +28 -0
- data/app/assets/lookbook/js/app.js +2 -0
- data/app/assets/lookbook/js/components/filter.js +1 -1
- data/app/assets/lookbook/js/components/inspector.js +44 -7
- 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 +17 -3
- 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 +9 -3
- data/app/assets/lookbook/js/stores/inspector.js +12 -5
- data/app/controllers/lookbook/app_controller.rb +3 -1
- data/app/views/layouts/lookbook/app.html.erb +6 -2
- data/app/views/lookbook/components/_copy.html.erb +7 -3
- data/app/views/lookbook/components/_drawer.html.erb +121 -0
- data/app/views/lookbook/components/_filter.html.erb +1 -1
- data/app/views/lookbook/components/_header.html.erb +1 -1
- 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/_param.html.erb +8 -4
- data/app/views/lookbook/components/_preview.html.erb +49 -21
- data/app/views/lookbook/inputs/_select.html.erb +1 -1
- data/app/views/lookbook/inputs/_text.html.erb +2 -1
- data/app/views/lookbook/inputs/_textarea.html.erb +2 -1
- 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 +1 -1
- data/app/views/lookbook/panels/_params.html.erb +1 -1
- data/app/views/lookbook/panels/_source.html.erb +1 -1
- data/app/views/lookbook/show.html.erb +64 -81
- data/lib/lookbook/code_formatter.rb +3 -3
- 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 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 95624cc7d6d6e9389e87c3b13c6f4980f0be8ae2f13ac81757a9ed7acbaf554d
|
|
4
|
+
data.tar.gz: e8e8c6787b96e23fc3d71bc3b47c4a9253ef8a607f8f41c292c52e2ecc99549d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5ac7b680d183349e374b1a2368b2839fa9c9ec8790f53cbf76a97171c0da7375cf6599d2e4936e2fcb1a0dca685aae9d37cfd54672e68ef0e935086af43b60bc
|
|
7
|
+
data.tar.gz: 03bee3f6b73191fc5bcfd5afed389fee54b3ec41ce31827ddedf647dc17f68740db1314f6f4a0c78d7dfe4960851d9cce12e23e6598970b74d8ec428f258db88
|
data/README.md
CHANGED
|
@@ -79,7 +79,7 @@ Lookbook parses [Yard-style comment tags](https://rubydoc.info/gems/yard/file/do
|
|
|
79
79
|
|
|
80
80
|
```ruby
|
|
81
81
|
# @label Basic Button
|
|
82
|
-
# @display bg_color #fff
|
|
82
|
+
# @display bg_color "#fff"
|
|
83
83
|
class ButtonComponentPreview < ViewComponent::Preview
|
|
84
84
|
|
|
85
85
|
# Primary button
|
|
@@ -110,7 +110,7 @@ class ButtonComponentPreview < ViewComponent::Preview
|
|
|
110
110
|
# ---------------
|
|
111
111
|
# For light-on-dark screens
|
|
112
112
|
#
|
|
113
|
-
# @display bg_color #000
|
|
113
|
+
# @display bg_color "#000"
|
|
114
114
|
def secondary
|
|
115
115
|
render ButtonComponent.new(style: :inverted) do
|
|
116
116
|
"Click me"
|
|
@@ -188,7 +188,7 @@ end
|
|
|
188
188
|
The `@display` tag lets you pass custom parameters to your preview layout so that the component preview can be customised on a per-example basis.
|
|
189
189
|
|
|
190
190
|
```ruby
|
|
191
|
-
# @display bg_color #eee
|
|
191
|
+
# @display bg_color "#eee"
|
|
192
192
|
class FooComponentPreview < ViewComponent::Preview
|
|
193
193
|
|
|
194
194
|
# @display max_width 500px
|
|
@@ -207,6 +207,8 @@ The `@display` tag can be applied at the preview (class) or at the example (meth
|
|
|
207
207
|
- `<key>` must be a valid Ruby hash key name, without quotes or spaces
|
|
208
208
|
- `<value>` will be parsed using the [Ruby YAML parser](https://yaml.org/YAML_for_ruby.html) to resolve the value
|
|
209
209
|
|
|
210
|
+
> Note: Ruby YAML does not (generally) require quoting of string values. However in some cases it _is_ required due to the presence of [indicator characters](https://yaml.org/YAML_for_ruby.html#indicators_in_strings) (such as `#`, `:` etc) - hence why the hex color code in the example above is surrounded by quotes. It's perfectly ok to quote all string values if you prefer.
|
|
211
|
+
|
|
210
212
|
These display parameters can then be accessed via the `params` hash in your preview layout using `params[:lookbook][:display][<key>]`:
|
|
211
213
|
|
|
212
214
|
```html
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
@import "tailwindcss/components";
|
|
3
3
|
@import "tailwindcss/utilities";
|
|
4
4
|
@import "tippy.js/dist/tippy";
|
|
5
|
+
@import "tippy.js/dist/border";
|
|
5
6
|
@import "code_theme";
|
|
6
7
|
@import "tooltip_theme";
|
|
7
8
|
|
|
@@ -57,8 +58,8 @@
|
|
|
57
58
|
}
|
|
58
59
|
|
|
59
60
|
@layer components {
|
|
60
|
-
#nav > ul > li {
|
|
61
|
-
@apply py-1;
|
|
61
|
+
#nav > ul > li > div {
|
|
62
|
+
@apply py-1 border-b border-gray-300;
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
.nav-toggle {
|
|
@@ -75,10 +76,11 @@
|
|
|
75
76
|
|
|
76
77
|
.code pre {
|
|
77
78
|
@apply block;
|
|
79
|
+
/* @apply whitespace-pre-wrap; */
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
.code .line {
|
|
81
|
-
@apply
|
|
83
|
+
@apply leading-relaxed;
|
|
82
84
|
}
|
|
83
85
|
|
|
84
86
|
.code.numbered {
|
|
@@ -87,35 +89,41 @@
|
|
|
87
89
|
|
|
88
90
|
.code.numbered:before {
|
|
89
91
|
content: "";
|
|
90
|
-
left:
|
|
92
|
+
left: 2.7em;
|
|
91
93
|
@apply absolute top-0 bottom-0 border-r border-gray-200;
|
|
92
94
|
}
|
|
93
95
|
|
|
96
|
+
.code.numbered .line {
|
|
97
|
+
padding-left: calc(2.7em + 8px);
|
|
98
|
+
@apply relative;
|
|
99
|
+
}
|
|
100
|
+
|
|
94
101
|
.code .line-number {
|
|
102
|
+
display: inline-block;
|
|
95
103
|
width: calc(2.7em + 8px);
|
|
96
104
|
padding-top: 3px;
|
|
97
105
|
padding-bottom: 3px;
|
|
98
106
|
padding-right: 8px;
|
|
99
107
|
margin-right: 16px;
|
|
100
|
-
@apply font-mono text-right text-gray-400 flex-none text-xs;
|
|
108
|
+
@apply font-mono text-right text-gray-400 flex-none text-xs absolute left-0;
|
|
101
109
|
}
|
|
102
110
|
|
|
103
111
|
.code .line-content {
|
|
104
112
|
@apply flex-none pr-4;
|
|
105
113
|
}
|
|
106
114
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
padding-top: 2px;
|
|
111
|
-
padding-bottom: 2px;
|
|
112
|
-
padding-right: 8px;
|
|
113
|
-
@apply font-mono inline-block text-right mr-4 text-gray-400 border-r border-gray-200;
|
|
114
|
-
} */
|
|
115
|
+
.resize-handle {
|
|
116
|
+
@apply flex items-center justify-center h-full w-full border-gray-300 bg-white hover:bg-indigo-100 hover:bg-opacity-20 text-gray-400 hover:text-gray-700 transition select-none touch-none;
|
|
117
|
+
}
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
@layer utilities {
|
|
118
121
|
.form-input {
|
|
119
122
|
@apply border-gray-300 text-gray-700 focus:ring-indigo-300 focus:border-indigo-300 rounded-sm text-sm w-full;
|
|
120
123
|
}
|
|
124
|
+
|
|
125
|
+
.checked-bg {
|
|
126
|
+
background-color: #ffffff;
|
|
127
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3E%3Cg fill='%23f3f3f3' fill-opacity='1'%3E%3Cpath fill-rule='evenodd' d='M0 0h4v4H0V0zm4 4h4v4H4V4z'/%3E%3C/g%3E%3C/svg%3E");
|
|
128
|
+
}
|
|
121
129
|
}
|
|
@@ -4,13 +4,41 @@
|
|
|
4
4
|
&[data-placement^="top"] > .tippy-arrow::before {
|
|
5
5
|
border-top-color: theme("colors.indigo.500");
|
|
6
6
|
}
|
|
7
|
+
|
|
7
8
|
&[data-placement^="bottom"] > .tippy-arrow::before {
|
|
8
9
|
border-bottom-color: theme("colors.indigo.500");
|
|
9
10
|
}
|
|
11
|
+
|
|
10
12
|
&[data-placement^="left"] > .tippy-arrow::before {
|
|
11
13
|
border-left-color: theme("colors.indigo.500");
|
|
12
14
|
}
|
|
15
|
+
|
|
13
16
|
&[data-placement^="right"] > .tippy-arrow::before {
|
|
14
17
|
border-right-color: theme("colors.indigo.500");
|
|
15
18
|
}
|
|
16
19
|
}
|
|
20
|
+
|
|
21
|
+
.tippy-box[data-theme~="menu"] {
|
|
22
|
+
border: 1px solid theme("colors.gray.300");
|
|
23
|
+
@apply bg-white text-gray-600 shadow-md rounded;
|
|
24
|
+
|
|
25
|
+
& > .tippy-content {
|
|
26
|
+
padding: 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&[data-placement^="top"] > .tippy-arrow::before {
|
|
30
|
+
border-top-color: white;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&[data-placement^="bottom"] > .tippy-arrow::before {
|
|
34
|
+
border-bottom-color: white;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&[data-placement^="left"] > .tippy-arrow::before {
|
|
38
|
+
border-left-color: white;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&[data-placement^="right"] > .tippy-arrow::before {
|
|
42
|
+
border-right-color: white;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -13,6 +13,7 @@ import nav from "./components/nav";
|
|
|
13
13
|
import navItem from "./components/nav-item";
|
|
14
14
|
import navGroup from "./components/nav-group";
|
|
15
15
|
import splitter from "./components/splitter";
|
|
16
|
+
import tabs from "./components/tabs";
|
|
16
17
|
import copy from "./components/copy";
|
|
17
18
|
import sizes from "./components/sizes";
|
|
18
19
|
|
|
@@ -47,6 +48,7 @@ Alpine.data("filter", filter);
|
|
|
47
48
|
Alpine.data("param", param);
|
|
48
49
|
Alpine.data("sizes", sizes);
|
|
49
50
|
Alpine.data("nav", nav);
|
|
51
|
+
Alpine.data("tabs", tabs);
|
|
50
52
|
Alpine.data("navItem", navItem);
|
|
51
53
|
Alpine.data("navGroup", navGroup);
|
|
52
54
|
|
|
@@ -1,17 +1,54 @@
|
|
|
1
|
+
import sizeObserver from "./sizes";
|
|
2
|
+
|
|
1
3
|
export default function inspector() {
|
|
2
4
|
return {
|
|
5
|
+
width: 0,
|
|
6
|
+
height: 0,
|
|
7
|
+
init() {
|
|
8
|
+
const ro = new ResizeObserver((entries) => {
|
|
9
|
+
const rect = entries[0].contentRect;
|
|
10
|
+
this.width = Math.round(rect.width);
|
|
11
|
+
this.height = Math.round(rect.height);
|
|
12
|
+
});
|
|
13
|
+
ro.observe(this.$el);
|
|
14
|
+
this.width = Math.round(this.$el.clientWidth);
|
|
15
|
+
this.height = Math.round(this.$el.clientHeight);
|
|
16
|
+
},
|
|
17
|
+
get orientation() {
|
|
18
|
+
return this.$store.inspector.drawer.orientation;
|
|
19
|
+
},
|
|
20
|
+
get view() {
|
|
21
|
+
return this.$store.inspector.preview.view;
|
|
22
|
+
},
|
|
23
|
+
get horizontal() {
|
|
24
|
+
return this.canBeVertical ? this.orientation === "horizontal" : true;
|
|
25
|
+
},
|
|
26
|
+
get vertical() {
|
|
27
|
+
return !this.horizontal;
|
|
28
|
+
},
|
|
29
|
+
get canBeVertical() {
|
|
30
|
+
return this.width > 800;
|
|
31
|
+
},
|
|
32
|
+
get drawerHidden() {
|
|
33
|
+
return this.$store.inspector.drawer.hidden;
|
|
34
|
+
},
|
|
3
35
|
isActivePanel(panel) {
|
|
4
|
-
return this.$store.inspector.
|
|
36
|
+
return this.$store.inspector.drawer.active == panel;
|
|
5
37
|
},
|
|
6
38
|
switchPanel(panel) {
|
|
7
|
-
this.$store.inspector.
|
|
39
|
+
this.$store.inspector.drawer.active = panel;
|
|
40
|
+
},
|
|
41
|
+
toggleView() {
|
|
42
|
+
this.$store.inspector.preview.view =
|
|
43
|
+
this.view === "html" ? "preview" : "html";
|
|
8
44
|
},
|
|
9
|
-
|
|
10
|
-
|
|
45
|
+
toggleOrientation() {
|
|
46
|
+
this.$store.inspector.drawer.orientation =
|
|
47
|
+
this.orientation === "horizontal" ? "vertical" : "horizontal";
|
|
11
48
|
},
|
|
12
|
-
|
|
13
|
-
this.$store.inspector.
|
|
14
|
-
!this.$store.inspector.
|
|
49
|
+
toggleDrawer() {
|
|
50
|
+
this.$store.inspector.drawer.hidden =
|
|
51
|
+
!this.$store.inspector.drawer.hidden;
|
|
15
52
|
},
|
|
16
53
|
preview: {
|
|
17
54
|
width: null,
|
|
@@ -15,7 +15,7 @@ export default function navGroup() {
|
|
|
15
15
|
},
|
|
16
16
|
getChildren() {
|
|
17
17
|
return this.$refs.items
|
|
18
|
-
? Array.from(this.$refs.items.querySelectorAll(":scope > li"))
|
|
18
|
+
? Array.from(this.$refs.items.querySelectorAll(":scope > li > div"))
|
|
19
19
|
: [];
|
|
20
20
|
},
|
|
21
21
|
navigateToFirstChild() {
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
import createSocket from "../lib/socket";
|
|
2
2
|
|
|
3
|
+
const morphOpts = {
|
|
4
|
+
key(el) {
|
|
5
|
+
return el.getAttribute("key") ? el.getAttribute("key") : el.id;
|
|
6
|
+
},
|
|
7
|
+
updating(el, toEl, childrenOnly, skip) {
|
|
8
|
+
if (
|
|
9
|
+
el.getAttribute &&
|
|
10
|
+
el.getAttribute("data-morph-strategy") === "replace"
|
|
11
|
+
) {
|
|
12
|
+
el.innerHTML = toEl.innerHTML;
|
|
13
|
+
return skip();
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
lookahead: true,
|
|
17
|
+
};
|
|
18
|
+
|
|
3
19
|
export default function page() {
|
|
4
20
|
return {
|
|
5
21
|
init() {
|
|
@@ -22,11 +38,7 @@ export default function page() {
|
|
|
22
38
|
},
|
|
23
39
|
morph(dom) {
|
|
24
40
|
const pageHtml = dom.getElementById(this.$root.id).outerHTML;
|
|
25
|
-
Alpine.morph(this.$root, pageHtml,
|
|
26
|
-
key(el) {
|
|
27
|
-
return el.getAttribute("key") ? el.getAttribute("key") : el.id;
|
|
28
|
-
},
|
|
29
|
-
});
|
|
41
|
+
Alpine.morph(this.$root, pageHtml, morphOpts);
|
|
30
42
|
this.$dispatch("page:morphed");
|
|
31
43
|
},
|
|
32
44
|
};
|
|
@@ -1,13 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
import debounce from "debounce";
|
|
2
|
+
|
|
3
|
+
export default function param(name, value) {
|
|
2
4
|
return {
|
|
5
|
+
name,
|
|
6
|
+
value,
|
|
7
|
+
init() {
|
|
8
|
+
this.$watch(
|
|
9
|
+
"value",
|
|
10
|
+
debounce(() => {
|
|
11
|
+
if (this.validate()) {
|
|
12
|
+
this.update();
|
|
13
|
+
}
|
|
14
|
+
}, 300)
|
|
15
|
+
);
|
|
16
|
+
},
|
|
3
17
|
setFocus() {
|
|
4
18
|
if (this.$refs.input) {
|
|
5
19
|
setTimeout(() => this.$refs.input.focus(), 0);
|
|
6
20
|
}
|
|
7
21
|
},
|
|
8
|
-
update(
|
|
22
|
+
update() {
|
|
9
23
|
const searchParams = new URLSearchParams(window.location.search);
|
|
10
|
-
searchParams.set(name, value);
|
|
24
|
+
searchParams.set(this.name, this.value);
|
|
11
25
|
const path = location.href.replace(location.search, "");
|
|
12
26
|
this.setLocation(`${path}?${searchParams.toString()}`);
|
|
13
27
|
},
|
|
@@ -1,37 +1,106 @@
|
|
|
1
1
|
export default function preview() {
|
|
2
2
|
return {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
this.resizeStartSize - (this.resizeStartPosition - e.pageX) * 2;
|
|
6
|
-
const parentSize = this.$root.parentElement.clientWidth;
|
|
7
|
-
const percentSize = (Math.round(size) / parentSize) * 100;
|
|
8
|
-
const minWidth = (300 / parentSize) * 100;
|
|
9
|
-
this.$store.inspector.preview.width = `${Math.min(
|
|
10
|
-
Math.max(percentSize, minWidth),
|
|
11
|
-
100
|
|
12
|
-
)}%`;
|
|
3
|
+
get store() {
|
|
4
|
+
return this.$store.inspector.preview;
|
|
13
5
|
},
|
|
14
|
-
|
|
6
|
+
get maxWidth() {
|
|
7
|
+
return this.store.width === "100%" ? "100%" : `${this.store.width}px`;
|
|
8
|
+
},
|
|
9
|
+
get maxHeight() {
|
|
10
|
+
return this.store.height === "100%" ? "100%" : `${this.store.height}px`;
|
|
11
|
+
},
|
|
12
|
+
get parentWidth() {
|
|
13
|
+
return Math.round(this.$root.parentElement.clientWidth);
|
|
14
|
+
},
|
|
15
|
+
get parentHeight() {
|
|
16
|
+
return Math.round(this.$root.parentElement.clientHeight);
|
|
17
|
+
},
|
|
18
|
+
start() {
|
|
15
19
|
this.$store.layout.reflowing = true;
|
|
16
|
-
this.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.resizeStartSize = this.$root.clientWidth;
|
|
20
|
-
window.addEventListener("pointermove", this.onResize);
|
|
21
|
-
window.addEventListener("pointerup", this.onResizeEnd);
|
|
22
|
-
},
|
|
23
|
-
onResizeEnd() {
|
|
24
|
-
window.removeEventListener("pointermove", this.onResize);
|
|
25
|
-
window.removeEventListener("pointerup", this.onResizeEnd);
|
|
20
|
+
this.store.resizing = true;
|
|
21
|
+
},
|
|
22
|
+
end() {
|
|
26
23
|
this.$store.layout.reflowing = false;
|
|
24
|
+
this.store.resizing = false;
|
|
25
|
+
},
|
|
26
|
+
onResizeStart(e) {
|
|
27
|
+
this.onResizeWidthStart(e);
|
|
28
|
+
this.onResizeHeightStart(e);
|
|
29
|
+
},
|
|
30
|
+
toggleFullSize() {
|
|
31
|
+
const { height, width } = this.store;
|
|
32
|
+
if (height === "100%" && width === "100%") {
|
|
33
|
+
this.toggleFullHeight();
|
|
34
|
+
this.toggleFullWidth();
|
|
35
|
+
} else {
|
|
36
|
+
if (height !== "100%") this.toggleFullHeight();
|
|
37
|
+
if (width !== "100%") this.toggleFullWidth();
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
onResizeWidth(e) {
|
|
41
|
+
const width =
|
|
42
|
+
this.resizeStartWidth - (this.resizeStartPositionX - e.pageX) * 2;
|
|
43
|
+
const boundedWidth = Math.min(
|
|
44
|
+
Math.max(Math.round(width), 200),
|
|
45
|
+
this.parentWidth
|
|
46
|
+
);
|
|
47
|
+
this.store.width =
|
|
48
|
+
boundedWidth === this.parentWidth ? "100%" : boundedWidth;
|
|
49
|
+
},
|
|
50
|
+
onResizeWidthStart(e) {
|
|
51
|
+
this.start();
|
|
52
|
+
this.onResizeWidth = this.onResizeWidth.bind(this);
|
|
53
|
+
this.onResizeWidthEnd = this.onResizeWidthEnd.bind(this);
|
|
54
|
+
this.resizeStartPositionX = e.pageX;
|
|
55
|
+
this.resizeStartWidth = this.$root.clientWidth;
|
|
56
|
+
window.addEventListener("pointermove", this.onResizeWidth);
|
|
57
|
+
window.addEventListener("pointerup", this.onResizeWidthEnd);
|
|
58
|
+
},
|
|
59
|
+
onResizeWidthEnd() {
|
|
60
|
+
window.removeEventListener("pointermove", this.onResizeWidth);
|
|
61
|
+
window.removeEventListener("pointerup", this.onResizeWidthEnd);
|
|
62
|
+
this.end();
|
|
27
63
|
},
|
|
28
64
|
toggleFullWidth() {
|
|
29
|
-
const
|
|
30
|
-
if (
|
|
31
|
-
|
|
65
|
+
const { width, lastWidth } = this.store;
|
|
66
|
+
if (width === "100%" && lastWidth) {
|
|
67
|
+
this.store.width = lastWidth;
|
|
68
|
+
} else {
|
|
69
|
+
this.store.lastWidth = width;
|
|
70
|
+
this.store.width = "100%";
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
onResizeHeight(e) {
|
|
74
|
+
const height =
|
|
75
|
+
this.resizeStartHeight - (this.resizeStartPositionY - e.pageY);
|
|
76
|
+
const boundedHeight = Math.min(
|
|
77
|
+
Math.max(Math.round(height), 200),
|
|
78
|
+
this.parentHeight
|
|
79
|
+
);
|
|
80
|
+
this.$store.inspector.preview.height =
|
|
81
|
+
boundedHeight === this.parentHeight ? "100%" : boundedHeight;
|
|
82
|
+
},
|
|
83
|
+
onResizeHeightStart(e) {
|
|
84
|
+
this.start();
|
|
85
|
+
this.onResizeHeight = this.onResizeHeight.bind(this);
|
|
86
|
+
this.onResizeHeightEnd = this.onResizeHeightEnd.bind(this);
|
|
87
|
+
this.resizeStartPositionY = e.pageY;
|
|
88
|
+
this.resizeStartHeight = this.$root.clientHeight;
|
|
89
|
+
window.addEventListener("pointermove", this.onResizeHeight);
|
|
90
|
+
window.addEventListener("pointerup", this.onResizeHeightEnd);
|
|
91
|
+
},
|
|
92
|
+
onResizeHeightEnd() {
|
|
93
|
+
window.removeEventListener("pointermove", this.onResizeHeight);
|
|
94
|
+
window.removeEventListener("pointerup", this.onResizeHeightEnd);
|
|
95
|
+
this.end();
|
|
96
|
+
},
|
|
97
|
+
toggleFullHeight() {
|
|
98
|
+
const { height, lastHeight } = this.store;
|
|
99
|
+
if (height === "100%" && lastHeight) {
|
|
100
|
+
this.store.height = lastHeight;
|
|
32
101
|
} else {
|
|
33
|
-
|
|
34
|
-
|
|
102
|
+
this.store.lastHeight = height;
|
|
103
|
+
this.store.height = "100%";
|
|
35
104
|
}
|
|
36
105
|
},
|
|
37
106
|
};
|
|
@@ -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,18 @@ 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
|
-
|
|
9
|
+
drawer: {
|
|
10
|
+
orientation: "horizontal",
|
|
11
|
+
defaultPanel: "source",
|
|
11
12
|
defaultHeight: 200,
|
|
13
|
+
defaultWidth: 500,
|
|
14
|
+
minWidth: 350,
|
|
15
|
+
},
|
|
16
|
+
preview: {
|
|
17
|
+
view: "preview",
|
|
12
18
|
},
|
|
13
19
|
},
|
|
14
20
|
};
|
|
@@ -1,17 +1,24 @@
|
|
|
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
|
+
active: Alpine.$persist(drawer.defaultPanel).as("drawer-active"),
|
|
10
|
+
height: Alpine.$persist(drawer.defaultHeight).as("drawer-height"),
|
|
11
|
+
width: Alpine.$persist(drawer.defaultWidth).as("drawer-width"),
|
|
12
|
+
minWidth: drawer.minWidth,
|
|
13
|
+
visibleTabCount: Infinity,
|
|
9
14
|
},
|
|
10
15
|
preview: {
|
|
11
16
|
width: Alpine.$persist("100%").as("preview-width"),
|
|
12
17
|
height: Alpine.$persist("100%").as("preview-height"),
|
|
13
|
-
|
|
18
|
+
view: Alpine.$persist(preview.view).as("preview-view"),
|
|
14
19
|
lastWidth: null,
|
|
20
|
+
lastHeight: null,
|
|
21
|
+
resizing: false,
|
|
15
22
|
},
|
|
16
23
|
};
|
|
17
24
|
}
|
|
@@ -27,7 +27,9 @@ module Lookbook
|
|
|
27
27
|
begin
|
|
28
28
|
set_params
|
|
29
29
|
@examples = examples_data
|
|
30
|
-
@preview_srcdoc =
|
|
30
|
+
@preview_srcdoc = if Lookbook.config.preview_srcdoc
|
|
31
|
+
render_examples(examples_data).gsub("\"", """)
|
|
32
|
+
end
|
|
31
33
|
@panels = panels.filter { |name, panel| panel[:show] }
|
|
32
34
|
rescue *EXCEPTIONS
|
|
33
35
|
render "error"
|
|
@@ -44,9 +44,13 @@
|
|
|
44
44
|
x-effect="$store.sidebar.width = Math.min(splits[0] || $store.sidebar.width, $store.sidebar.maxWidth)"
|
|
45
45
|
x-cloak
|
|
46
46
|
>
|
|
47
|
-
<div class="w-[9px] h-full bg-transparent hover:bg-indigo-100 hover:bg-opacity-20 transition absolute top-0 bottom-0
|
|
47
|
+
<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
48
|
</div>
|
|
49
|
-
<main
|
|
49
|
+
<main
|
|
50
|
+
id="main"
|
|
51
|
+
class="h-full overflow-hidden w-full"
|
|
52
|
+
x-show="$store.layout.desktop || !$store.sidebar.open" x-cloak
|
|
53
|
+
>
|
|
50
54
|
<%= yield %>
|
|
51
55
|
</main>
|
|
52
56
|
</div>
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
<button
|
|
2
|
-
class="
|
|
2
|
+
class="text-gray-400 transition"
|
|
3
3
|
x-data="copy('<%= target %>')"
|
|
4
4
|
x-tooltip.theme.lookbook="done ? 'copied!' : 'copy to clipboard'"
|
|
5
5
|
@click="save"
|
|
6
6
|
:class="{'!text-green-600 hover:text-green-600': done, 'hover:text-indigo-500': !done}"
|
|
7
|
-
data-tippy-placement="left"
|
|
7
|
+
data-tippy-placement="left"
|
|
8
|
+
<% if defined?(show) %>
|
|
9
|
+
x-show="<%= show %>"
|
|
10
|
+
x-cloak
|
|
11
|
+
<% end %>
|
|
12
|
+
>
|
|
8
13
|
<%= icon "${done ? 'check' : 'clipboard'}", size: 4 %>
|
|
9
|
-
<div class="hidden" x-init="content = $el.innerText"><%== yield %></div>
|
|
10
14
|
</button>
|