lookbook 0.2.4 → 0.3.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 +81 -0
- data/app/assets/lookbook/css/app.css +28 -0
- data/app/assets/lookbook/js/app.js +49 -24
- data/app/assets/lookbook/js/nav/leaf.js +20 -0
- data/app/assets/lookbook/js/nav/node.js +31 -0
- data/app/assets/lookbook/js/nav.js +39 -0
- data/app/assets/lookbook/js/page.js +33 -0
- data/app/assets/lookbook/js/utils/clipboard.js +13 -0
- data/app/assets/lookbook/js/utils/morph.js +16 -0
- data/app/assets/lookbook/js/{reloader.js → utils/reloader.js} +0 -0
- data/app/assets/lookbook/js/utils/screen.js +44 -0
- data/app/assets/lookbook/js/{size_observer.js → utils/size_observer.js} +1 -1
- data/app/assets/lookbook/js/{split.js → utils/split.js} +4 -4
- data/app/assets/lookbook/js/workbench/inspector.js +11 -0
- data/app/assets/lookbook/js/workbench/preview.js +39 -0
- data/app/assets/lookbook/js/workbench.js +14 -0
- data/app/controllers/lookbook/{browser_controller.rb → app_controller.rb} +58 -31
- data/app/helpers/lookbook/application_helper.rb +1 -1
- data/app/views/lookbook/_sidebar.html.erb +45 -0
- data/app/views/lookbook/_workbench.html.erb +12 -0
- data/app/views/lookbook/{browser → app}/error.html.erb +0 -0
- data/app/views/lookbook/app/index.html.erb +11 -0
- data/app/views/lookbook/{browser → app}/not_found.html.erb +1 -1
- data/app/views/lookbook/app/show.html.erb +1 -0
- data/app/views/lookbook/layouts/app.html.erb +16 -26
- data/app/views/lookbook/nav/_collection.html.erb +5 -0
- data/app/views/lookbook/nav/_leaf.html.erb +22 -0
- data/app/views/lookbook/nav/_node.html.erb +19 -0
- data/app/views/lookbook/nav/_preview.html.erb +11 -0
- data/app/views/lookbook/preview_group.html.erb +8 -0
- data/app/views/lookbook/shared/_clipboard.html.erb +11 -0
- data/app/views/lookbook/shared/_header.html.erb +8 -0
- data/app/views/lookbook/workbench/_header.html.erb +39 -0
- data/app/views/lookbook/workbench/_inspector.html.erb +32 -0
- data/app/views/lookbook/workbench/_preview.html.erb +24 -0
- data/app/views/lookbook/workbench/inspector/_code.html.erb +3 -0
- data/app/views/lookbook/workbench/inspector/_notes.html.erb +24 -0
- data/app/views/lookbook/{partials → workbench}/inspector/_plain.html.erb +0 -0
- data/config/routes.rb +3 -3
- data/lib/lookbook/preview.rb +26 -3
- data/lib/lookbook/preview_controller.rb +6 -1
- data/lib/lookbook/preview_example.rb +3 -2
- data/lib/lookbook/preview_group.rb +37 -0
- data/lib/lookbook/taggable.rb +5 -1
- data/lib/lookbook/version.rb +1 -1
- data/lib/lookbook.rb +1 -0
- data/lib/tasks/lookbook_tasks.rake +1 -1
- data/public/lookbook-assets/app.css +229 -99
- data/public/lookbook-assets/app.js +882 -56
- data/{app/views/lookbook/partials/_icon_sprite.html.erb → public/lookbook-assets/feather-sprite.svg} +1 -1
- metadata +51 -22
- data/app/assets/lookbook/js/preview.js +0 -76
- data/app/views/lookbook/browser/index.html.erb +0 -8
- data/app/views/lookbook/browser/show.html.erb +0 -33
- data/app/views/lookbook/partials/_preview.html.erb +0 -18
- data/app/views/lookbook/partials/_sidebar.html.erb +0 -21
- data/app/views/lookbook/partials/inspector/_code.html.erb +0 -1
- data/app/views/lookbook/partials/inspector/_inspector.html.erb +0 -43
- data/app/views/lookbook/partials/inspector/_prose.html.erb +0 -3
- data/app/views/lookbook/partials/nav/_collection.html.erb +0 -17
- data/app/views/lookbook/partials/nav/_label.html.erb +0 -13
- data/app/views/lookbook/partials/nav/_nav.html.erb +0 -27
- data/app/views/lookbook/partials/nav/_preview.html.erb +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55670a652a3259ba1f28e3c6ec9be4201ce3348e7a7190e2d6ca2b8f05628e72
|
4
|
+
data.tar.gz: a77a7b1b038ba8d4bdd5262cd4e97542244788e1812d86f6ee31ba753e9396d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 136864d246c2269673654d2dae4dac3b6688abb0b9812a443b7e47d3bf0ab378103b3d070bdf6c0e78b15be56740a88d223cd86b241d0428cde7aa194dbf316f
|
7
|
+
data.tar.gz: 3458476f1781994cc442d11b9142976cd30ddc447bb4afa9cf41911dfbcd5813d56e6e67179288f18325fea61e8bd6e41b34fe2e2e75bb634f278e7639508ba3
|
data/README.md
CHANGED
@@ -112,6 +112,29 @@ class ButtonComponentPreview < ViewComponent::Preview
|
|
112
112
|
"Click me"
|
113
113
|
end
|
114
114
|
end
|
115
|
+
|
116
|
+
# @!group More examples
|
117
|
+
|
118
|
+
def short_text
|
119
|
+
render ButtonComponent.new do
|
120
|
+
"Go"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def long_text
|
125
|
+
render ButtonComponent.new do
|
126
|
+
"Click here to do this thing because it's the best way to do it"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def emoji_text
|
131
|
+
render ButtonComponent.new do
|
132
|
+
"👀📗"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# @!endgroup
|
137
|
+
|
115
138
|
end
|
116
139
|
```
|
117
140
|
|
@@ -153,6 +176,52 @@ class FooComponentPreview < ViewComponent::Preview
|
|
153
176
|
end
|
154
177
|
```
|
155
178
|
|
179
|
+
#### `@!group <name> ... @!endgroup`
|
180
|
+
|
181
|
+
For smaller components, it can often make sense to render a set of preview examples in a single window, rather than representing them as individual items in the navigation which can start to look a bit cluttered.
|
182
|
+
|
183
|
+
You can group a set of examples by wrapping them in `@!group <name>` / `@!endgroup` tags within your preview file:
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
class HeaderComponentPreview < ViewComponent::Preview
|
187
|
+
|
188
|
+
def standard
|
189
|
+
render Elements::HeaderComponent.new do
|
190
|
+
"Standard header"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# @!group Sizes
|
195
|
+
|
196
|
+
def small
|
197
|
+
render Elements::HeaderComponent.new(size: 12) do
|
198
|
+
"Small header"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def medium
|
203
|
+
render Elements::HeaderComponent.new(size: 16) do
|
204
|
+
"Small header"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def big
|
209
|
+
render Elements::HeaderComponent.new(size: 24) do
|
210
|
+
"Small header"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
# @!endgroup
|
215
|
+
|
216
|
+
end
|
217
|
+
```
|
218
|
+
|
219
|
+
The example above would display the `Sizes` examples grouped together on a single page, rather than as indiviual items in the navigation:
|
220
|
+
|
221
|
+
<img src=".github/assets/nav_group.png">
|
222
|
+
|
223
|
+
You can have as many groups as you like within a single preview class, but each example can only belong to one group.
|
224
|
+
|
156
225
|
#### Adding notes
|
157
226
|
|
158
227
|
All comment text other than tags will be treated as markdown and rendered in the **Notes** panel for that example in the Lookbook UI.
|
@@ -193,6 +262,18 @@ If you wish to add additional paths to listen for changes in, you can use the `l
|
|
193
262
|
config.lookbook.listen_paths << Rails.root.join('app/other/directory')
|
194
263
|
```
|
195
264
|
|
265
|
+
## Keyboard shortcuts
|
266
|
+
|
267
|
+
Lookbook provides a few keyboard shortcuts to help you quickly move around the UI.
|
268
|
+
|
269
|
+
- `f` - move focus to the nav filter box
|
270
|
+
- `Esc` [when focus is in nav filter box] - Clear contents if text is present, or return focus to the UI if the box is already empty
|
271
|
+
- `s` - Switch to Source tab in the inspector
|
272
|
+
- `o` - Switch to Output tab in the inspector
|
273
|
+
- `n` - Switch to Notes tab in the inspector
|
274
|
+
- `r` - Refresh the preview (useful if using something like Faker to generate randomised data for the preview)
|
275
|
+
- `w` - Open the standalone rendered preview in a new window
|
276
|
+
|
196
277
|
## Troubleshooting
|
197
278
|
|
198
279
|
#### Blank preview window
|
@@ -34,4 +34,32 @@
|
|
34
34
|
stroke-linejoin: round;
|
35
35
|
fill: none;
|
36
36
|
}
|
37
|
+
|
38
|
+
.h-fill {
|
39
|
+
height: fill-available;
|
40
|
+
}
|
41
|
+
|
42
|
+
.min-h-fill {
|
43
|
+
min-height: fill-available;
|
44
|
+
}
|
45
|
+
|
46
|
+
::-webkit-scrollbar {
|
47
|
+
width: 8px;
|
48
|
+
height: 8px;
|
49
|
+
}
|
50
|
+
|
51
|
+
::-webkit-scrollbar-track {
|
52
|
+
background: transparent;
|
53
|
+
}
|
54
|
+
|
55
|
+
::-webkit-scrollbar-thumb {
|
56
|
+
@apply bg-gray-300 transition-colors;
|
57
|
+
border-radius: 6px;
|
58
|
+
border: 2px solid transparent;
|
59
|
+
background-clip: content-box;
|
60
|
+
}
|
61
|
+
|
62
|
+
::-webkit-scrollbar-thumb:hover {
|
63
|
+
@apply bg-gray-400;
|
64
|
+
}
|
37
65
|
}
|
@@ -1,49 +1,74 @@
|
|
1
|
+
import { install } from "@github/hotkey";
|
1
2
|
import Alpine from "alpinejs";
|
2
3
|
import Fern from "@ryangjchandler/fern";
|
3
|
-
import
|
4
|
-
import
|
5
|
-
import
|
6
|
-
import
|
7
|
-
import
|
8
|
-
import
|
4
|
+
import AlpineTooltip from "@ryangjchandler/alpine-tooltip";
|
5
|
+
import AlpineClipboard from "@ryangjchandler/alpine-clipboard";
|
6
|
+
import Screen from "./utils/screen";
|
7
|
+
import split from "./utils/split";
|
8
|
+
import page from "./page";
|
9
|
+
import workbench from "./workbench";
|
10
|
+
import preview from "./workbench/preview";
|
11
|
+
import inspector from "./workbench/inspector";
|
12
|
+
import nav from "./nav";
|
13
|
+
import navNode from "./nav/node";
|
14
|
+
import navLeaf from "./nav/leaf";
|
15
|
+
import sizeObserver from "./utils/size_observer";
|
16
|
+
import reloader from "./utils/reloader";
|
17
|
+
import clipboard from "./utils/clipboard";
|
18
|
+
|
19
|
+
window.Alpine = Alpine;
|
9
20
|
|
10
21
|
// Plugins
|
11
22
|
|
12
23
|
Alpine.plugin(Fern);
|
13
|
-
Alpine.plugin(
|
14
|
-
Alpine.plugin(
|
15
|
-
|
16
|
-
// Data
|
17
|
-
|
18
|
-
Alpine.data("preview", preview);
|
19
|
-
Alpine.data("sizeObserver", observeSize);
|
20
|
-
Alpine.data("split", split);
|
24
|
+
Alpine.plugin(AlpineTooltip);
|
25
|
+
Alpine.plugin(AlpineClipboard);
|
26
|
+
Alpine.plugin(Screen);
|
21
27
|
|
22
28
|
// Stores
|
23
29
|
|
24
|
-
Alpine.store("
|
30
|
+
Alpine.store("page", {
|
31
|
+
reflowing: false,
|
32
|
+
doc: window.document,
|
33
|
+
});
|
34
|
+
|
25
35
|
Alpine.persistedStore("nav", {
|
26
36
|
width: 280,
|
27
37
|
filter: "",
|
28
38
|
open: {},
|
29
|
-
scrollTop: 0,
|
30
|
-
shouldDisplay(previewName) {
|
31
|
-
const cleanFilter = this.filter.replace(/\s/g, "");
|
32
|
-
return (
|
33
|
-
cleanFilter === "" || previewName.includes(cleanFilter.toLowerCase())
|
34
|
-
);
|
35
|
-
},
|
36
39
|
});
|
37
|
-
|
40
|
+
|
38
41
|
Alpine.persistedStore("inspector", {
|
39
42
|
height: 200,
|
40
43
|
active: "source",
|
41
44
|
});
|
42
45
|
|
46
|
+
Alpine.persistedStore("preview", {
|
47
|
+
width: "100%",
|
48
|
+
});
|
49
|
+
|
50
|
+
// Components & utils
|
51
|
+
|
52
|
+
Alpine.data("page", page);
|
53
|
+
Alpine.data("nav", nav);
|
54
|
+
Alpine.data("navNode", navNode);
|
55
|
+
Alpine.data("navLeaf", navLeaf);
|
56
|
+
Alpine.data("workbench", workbench);
|
57
|
+
Alpine.data("preview", preview);
|
58
|
+
Alpine.data("inspector", inspector);
|
59
|
+
Alpine.data("clipboard", clipboard);
|
60
|
+
Alpine.data("sizeObserver", sizeObserver);
|
61
|
+
Alpine.data("split", split);
|
62
|
+
|
43
63
|
// Init
|
44
64
|
|
45
|
-
|
65
|
+
for (const el of document.querySelectorAll("[data-hotkey]")) {
|
66
|
+
install(el);
|
67
|
+
}
|
68
|
+
|
46
69
|
if (window.SOCKET_PATH) {
|
47
70
|
reloader(window.SOCKET_PATH).start();
|
48
71
|
}
|
72
|
+
|
73
|
+
window.Alpine = Alpine;
|
49
74
|
Alpine.start();
|
@@ -0,0 +1,20 @@
|
|
1
|
+
export default function navLeaf() {
|
2
|
+
return {
|
3
|
+
path: null,
|
4
|
+
matchers: [],
|
5
|
+
active: false,
|
6
|
+
hidden: false,
|
7
|
+
setActive() {
|
8
|
+
this.active = this.path === window.location.pathname;
|
9
|
+
},
|
10
|
+
filter() {
|
11
|
+
if (this.$store.nav.filtering) {
|
12
|
+
const text = this.$store.nav.filterText;
|
13
|
+
const matched = this.matchers.map((m) => m.includes(text));
|
14
|
+
this.hidden = !matched.filter((m) => m).length;
|
15
|
+
} else {
|
16
|
+
this.hidden = false;
|
17
|
+
}
|
18
|
+
},
|
19
|
+
};
|
20
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
export default function navNode() {
|
2
|
+
return {
|
3
|
+
id: null,
|
4
|
+
hidden: true,
|
5
|
+
children: [],
|
6
|
+
init() {
|
7
|
+
this.id = this.$el.id;
|
8
|
+
},
|
9
|
+
open() {
|
10
|
+
return this.$store.nav.open[this.id];
|
11
|
+
},
|
12
|
+
getChildren() {
|
13
|
+
return this.$refs.items
|
14
|
+
? Array.from(this.$refs.items.querySelectorAll(":scope > li"))
|
15
|
+
: [];
|
16
|
+
},
|
17
|
+
filter() {
|
18
|
+
this.hidden = true;
|
19
|
+
this.getChildren().forEach((child) => {
|
20
|
+
const data = child._x_dataStack[0];
|
21
|
+
data.filter();
|
22
|
+
if (!data.hidden) {
|
23
|
+
this.hidden = false;
|
24
|
+
}
|
25
|
+
});
|
26
|
+
},
|
27
|
+
toggle() {
|
28
|
+
this.$store.nav.open[this.id] = !this.$store.nav.open[this.id];
|
29
|
+
},
|
30
|
+
};
|
31
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import morph from "./utils/morph";
|
2
|
+
|
3
|
+
export default function () {
|
4
|
+
return {
|
5
|
+
clearFilter() {
|
6
|
+
this.$store.nav.filter = "";
|
7
|
+
},
|
8
|
+
init() {
|
9
|
+
this.$watch("$store.nav.filter", (value) => {
|
10
|
+
const nav = this.$store.nav;
|
11
|
+
nav.filterText = value.replace(/\s/g, "").toLowerCase();
|
12
|
+
nav.filtering = nav.filterText.length > 0;
|
13
|
+
});
|
14
|
+
},
|
15
|
+
updateNav(event) {
|
16
|
+
const nav = document.getElementById("nav");
|
17
|
+
nav.style.height = `${this.$refs.shim.offsetHeight}px`;
|
18
|
+
morph(nav, event.detail.doc.getElementById("nav"));
|
19
|
+
Promise.resolve().then(() => {
|
20
|
+
this.$refs.shim.style.height = "auto";
|
21
|
+
this.$dispatch("nav:updated");
|
22
|
+
});
|
23
|
+
},
|
24
|
+
navigate(path) {
|
25
|
+
if (path instanceof Event) {
|
26
|
+
path = path.currentTarget.href;
|
27
|
+
}
|
28
|
+
history.pushState({}, null, path);
|
29
|
+
this.$dispatch("popstate");
|
30
|
+
},
|
31
|
+
focusFilter() {
|
32
|
+
this.currentFocus = this.$refs.filter;
|
33
|
+
setTimeout(() => this.$refs.filter.focus(), 0);
|
34
|
+
},
|
35
|
+
unfocusFilter() {
|
36
|
+
this.$refs.filter.blur();
|
37
|
+
},
|
38
|
+
};
|
39
|
+
}
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import morph from "./utils/morph";
|
2
|
+
|
3
|
+
export default function page() {
|
4
|
+
const store = Alpine.store("page");
|
5
|
+
return {
|
6
|
+
ready: false,
|
7
|
+
sidebarOpenMobile: false,
|
8
|
+
init() {
|
9
|
+
this.$nextTick(() => (this.ready = true));
|
10
|
+
},
|
11
|
+
splitProps: {
|
12
|
+
minSize: 200,
|
13
|
+
onDrag(splits) {
|
14
|
+
Alpine.store("nav").width = Math.min(splits[0], 500);
|
15
|
+
},
|
16
|
+
},
|
17
|
+
async fetchHTML() {
|
18
|
+
const response = await fetch(window.document.location);
|
19
|
+
if (!response.ok) return window.location.reload();
|
20
|
+
const html = await response.text();
|
21
|
+
store.doc = new DOMParser().parseFromString(html, "text/html");
|
22
|
+
return store.doc;
|
23
|
+
},
|
24
|
+
updateTitle() {
|
25
|
+
document.title = store.doc.title;
|
26
|
+
},
|
27
|
+
render() {
|
28
|
+
if (this.ready) {
|
29
|
+
morph(this.$el, store.doc.getElementById(this.$el.id));
|
30
|
+
}
|
31
|
+
},
|
32
|
+
};
|
33
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import morph from "morphdom";
|
2
|
+
|
3
|
+
export default function (from, to, opts = {}) {
|
4
|
+
morph(from, to, {
|
5
|
+
onBeforeElUpdated: function (fromEl, toEl) {
|
6
|
+
if (fromEl._x_dataStack) {
|
7
|
+
Alpine.clone(fromEl, toEl);
|
8
|
+
}
|
9
|
+
if (fromEl.isEqualNode(toEl)) {
|
10
|
+
return false;
|
11
|
+
}
|
12
|
+
return true;
|
13
|
+
},
|
14
|
+
...opts,
|
15
|
+
});
|
16
|
+
}
|
File without changes
|
@@ -0,0 +1,44 @@
|
|
1
|
+
// Adapted from: https://github.com/alpine-collective/toolkit
|
2
|
+
|
3
|
+
export default function (Alpine) {
|
4
|
+
// Create reactive data context
|
5
|
+
let data = Alpine.reactive({ screensize: window.innerWidth });
|
6
|
+
|
7
|
+
// Configuration
|
8
|
+
const defaultBreakpoints = {
|
9
|
+
xs: 0,
|
10
|
+
sm: 640,
|
11
|
+
md: 768,
|
12
|
+
lg: 1024,
|
13
|
+
xl: 1280,
|
14
|
+
"2xl": 1536,
|
15
|
+
};
|
16
|
+
|
17
|
+
const breakpoints =
|
18
|
+
window.AlpineMagicHelpersConfig &&
|
19
|
+
window.AlpineMagicHelpersConfig.breakpoints
|
20
|
+
? window.AlpineMagicHelpersConfig.breakpoints
|
21
|
+
: defaultBreakpoints;
|
22
|
+
|
23
|
+
window.addEventListener("resize", () => {
|
24
|
+
data.screensize = window.innerWidth;
|
25
|
+
});
|
26
|
+
|
27
|
+
Alpine.magic("screen", () => (breakpoint) => {
|
28
|
+
let width = data.screensize;
|
29
|
+
|
30
|
+
if (Number.isInteger(breakpoint)) return breakpoint <= width;
|
31
|
+
|
32
|
+
// Check if breakpoint exists
|
33
|
+
if (breakpoints[breakpoint] === undefined) {
|
34
|
+
throw Error(
|
35
|
+
"Undefined $screen property: " +
|
36
|
+
breakpoint +
|
37
|
+
". Supported properties: " +
|
38
|
+
Object.keys(breakpoints).join(", ")
|
39
|
+
);
|
40
|
+
}
|
41
|
+
|
42
|
+
return breakpoints[breakpoint] <= width;
|
43
|
+
});
|
44
|
+
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import Split from "split-grid";
|
2
2
|
|
3
3
|
export default function (props) {
|
4
|
-
const
|
4
|
+
const page = Alpine.store("page");
|
5
5
|
return {
|
6
6
|
init() {
|
7
7
|
Split({
|
@@ -11,14 +11,14 @@ export default function (props) {
|
|
11
11
|
minSize: props.minSize,
|
12
12
|
writeStyle() {},
|
13
13
|
onDrag(dir, track, style) {
|
14
|
-
splits = style.split(" ").map((num) => parseInt(num));
|
14
|
+
const splits = style.split(" ").map((num) => parseInt(num));
|
15
15
|
props.onDrag(splits);
|
16
16
|
},
|
17
17
|
onDragStart() {
|
18
|
-
|
18
|
+
page.reflowing = true;
|
19
19
|
},
|
20
20
|
onDragEnd() {
|
21
|
-
|
21
|
+
page.reflowing = false;
|
22
22
|
},
|
23
23
|
});
|
24
24
|
},
|
@@ -0,0 +1,39 @@
|
|
1
|
+
export default function preview() {
|
2
|
+
const app = Alpine.store("page");
|
3
|
+
const preview = Alpine.store("preview");
|
4
|
+
return {
|
5
|
+
init() {
|
6
|
+
this.root = this.$el;
|
7
|
+
},
|
8
|
+
onResize(e) {
|
9
|
+
const size =
|
10
|
+
this.resizeStartSize - (this.resizeStartPosition - e.pageX) * 2;
|
11
|
+
const parentSize = this.root.parentElement.clientWidth;
|
12
|
+
const percentSize = (Math.round(size) / parentSize) * 100;
|
13
|
+
const minWidth = (300 / parentSize) * 100;
|
14
|
+
preview.width = `${Math.min(Math.max(percentSize, minWidth), 100)}%`;
|
15
|
+
},
|
16
|
+
onResizeStart(e) {
|
17
|
+
app.reflowing = true;
|
18
|
+
this.onResize = this.onResize.bind(this);
|
19
|
+
this.onResizeEnd = this.onResizeEnd.bind(this);
|
20
|
+
this.resizeStartPosition = e.pageX;
|
21
|
+
this.resizeStartSize = this.root.clientWidth;
|
22
|
+
window.addEventListener("pointermove", this.onResize);
|
23
|
+
window.addEventListener("pointerup", this.onResizeEnd);
|
24
|
+
},
|
25
|
+
onResizeEnd() {
|
26
|
+
window.removeEventListener("pointermove", this.onResize);
|
27
|
+
window.removeEventListener("pointerup", this.onResizeEnd);
|
28
|
+
app.reflowing = false;
|
29
|
+
},
|
30
|
+
toggleFullWidth() {
|
31
|
+
if (preview.width === "100%" && preview.lastWidth) {
|
32
|
+
preview.width = preview.lastWidth;
|
33
|
+
} else {
|
34
|
+
preview.lastWidth = preview.width;
|
35
|
+
preview.width = "100%";
|
36
|
+
}
|
37
|
+
},
|
38
|
+
};
|
39
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
export default function workbench() {
|
2
|
+
const inspector = Alpine.store("inspector");
|
3
|
+
return {
|
4
|
+
previewViewportHeight: 0,
|
5
|
+
previewViewportWidth: 0,
|
6
|
+
splitProps: {
|
7
|
+
direction: "vertical",
|
8
|
+
minSize: 200,
|
9
|
+
onDrag(splits) {
|
10
|
+
inspector.height = splits[2];
|
11
|
+
},
|
12
|
+
},
|
13
|
+
};
|
14
|
+
}
|