lookbook 0.9.0 → 1.0.0.beta.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +90 -824
- data/app/assets/lookbook/css/lookbook.css +55 -0
- data/app/assets/lookbook/css/themes/blue.css +42 -0
- data/app/assets/lookbook/css/themes/indigo.css +42 -0
- data/app/assets/lookbook/css/themes/zinc.css +42 -0
- data/app/assets/lookbook/css/{tooltip_theme.css → tooltip.css} +14 -8
- data/app/assets/lookbook/js/app.js +64 -63
- data/app/assets/lookbook/js/components/clipboard.js +47 -0
- data/app/assets/lookbook/js/components/tooltip.js +30 -0
- data/app/assets/lookbook/js/config.js +7 -4
- data/app/assets/lookbook/js/helpers/build.js +22 -0
- data/app/assets/lookbook/js/helpers/dom.js +45 -0
- data/app/assets/lookbook/js/helpers/layout.js +21 -0
- data/app/assets/lookbook/js/helpers/request.js +16 -0
- data/app/assets/lookbook/js/helpers/string.js +11 -0
- data/app/assets/lookbook/js/lib/socket.js +4 -3
- data/app/assets/lookbook/js/lib/tippy.js +8 -0
- data/app/assets/lookbook/js/lookbook.js +61 -0
- data/app/assets/lookbook/js/plugins/logger.js +39 -0
- data/app/assets/lookbook/js/stores/filter.js +2 -2
- data/app/assets/lookbook/js/stores/inspector.js +23 -17
- data/app/assets/lookbook/js/stores/layout.js +101 -5
- data/app/assets/lookbook/js/stores/nav.js +17 -16
- data/app/assets/lookbook/js/stores/pages.js +4 -2
- data/app/assets/lookbook/js/stores/settings.js +7 -0
- data/app/assets/lookbook/js/stores/workbench.js +29 -0
- data/app/components/lookbook/button/component.html.erb +28 -0
- data/app/components/lookbook/button/component.js +55 -0
- data/app/components/lookbook/button/component.rb +39 -0
- data/app/components/lookbook/button_group/component.html.erb +3 -0
- data/app/components/lookbook/button_group/component.rb +18 -0
- data/app/components/lookbook/code/component.css +57 -0
- data/app/components/lookbook/code/component.html.erb +10 -0
- data/app/components/lookbook/code/component.js +3 -0
- data/app/components/lookbook/code/component.rb +56 -0
- data/app/components/lookbook/code/highlight_github_light.css +217 -0
- data/app/components/lookbook/component.rb +41 -0
- data/app/components/lookbook/copy_button/component.html.erb +11 -0
- data/app/components/lookbook/copy_button/component.js +16 -0
- data/app/components/lookbook/copy_button/component.rb +23 -0
- data/app/components/lookbook/dimensions_display/component.html.erb +11 -0
- data/app/components/lookbook/dimensions_display/component.js +37 -0
- data/app/components/lookbook/dimensions_display/component.rb +18 -0
- data/app/components/lookbook/embed/component.html.erb +50 -0
- data/app/components/lookbook/embed/component.js +39 -0
- data/app/components/lookbook/embed/component.rb +22 -0
- data/app/components/lookbook/filter/component.html.erb +17 -0
- data/app/components/lookbook/filter/component.js +21 -0
- data/app/components/lookbook/filter/component.rb +15 -0
- data/app/components/lookbook/header/component.html.erb +79 -0
- data/app/components/lookbook/header/component.rb +9 -0
- data/app/components/lookbook/icon/component.css +11 -0
- data/app/components/lookbook/icon/component.html.erb +5 -0
- data/app/components/lookbook/icon/component.js +5 -0
- data/app/components/lookbook/icon/component.rb +23 -0
- data/app/components/lookbook/nav/component.html.erb +33 -0
- data/app/components/lookbook/nav/component.js +52 -0
- data/app/components/lookbook/nav/component.rb +37 -0
- data/app/components/lookbook/nav/item/component.html.erb +23 -0
- data/app/components/lookbook/nav/item/component.js +66 -0
- data/app/components/lookbook/nav/item/component.rb +84 -0
- data/app/components/lookbook/page_tabs/component.html.erb +18 -0
- data/app/components/lookbook/page_tabs/component.rb +19 -0
- data/app/components/lookbook/params_editor/component.html.erb +3 -0
- data/app/components/lookbook/params_editor/component.js +12 -0
- data/app/components/lookbook/params_editor/component.rb +11 -0
- data/app/components/lookbook/params_editor/field/component.html.erb +50 -0
- data/app/components/lookbook/params_editor/field/component.js +36 -0
- data/app/components/lookbook/params_editor/field/component.rb +41 -0
- data/app/components/lookbook/prose/component.css +12 -0
- data/app/components/lookbook/prose/component.html.erb +3 -0
- data/app/components/lookbook/prose/component.rb +26 -0
- data/app/components/lookbook/split_layout/component.html.erb +13 -0
- data/app/components/lookbook/split_layout/component.js +151 -0
- data/app/components/lookbook/split_layout/component.rb +11 -0
- data/app/components/lookbook/tab_panels/component.html.erb +5 -0
- data/app/components/lookbook/tab_panels/component.js +25 -0
- data/app/components/lookbook/tab_panels/component.rb +20 -0
- data/app/components/lookbook/tab_panels/panel/component.html.erb +8 -0
- data/app/components/lookbook/tab_panels/panel/component.rb +9 -0
- data/app/components/lookbook/tabs/component.css +8 -0
- data/app/components/lookbook/tabs/component.html.erb +20 -0
- data/app/components/lookbook/tabs/component.js +115 -0
- data/app/components/lookbook/tabs/component.rb +28 -0
- data/app/components/lookbook/tabs/dropdown_tab/component.html.erb +20 -0
- data/app/components/lookbook/tabs/dropdown_tab/component.rb +17 -0
- data/app/components/lookbook/tabs/tab/component.html.erb +24 -0
- data/app/components/lookbook/tabs/tab/component.rb +17 -0
- data/app/components/lookbook/tag_component.rb +29 -0
- data/app/components/lookbook/toolbar/component.css +16 -0
- data/app/components/lookbook/toolbar/component.html.erb +5 -0
- data/app/components/lookbook/toolbar/component.rb +26 -0
- data/app/components/lookbook/viewport/component.css +11 -0
- data/app/components/lookbook/viewport/component.html.erb +57 -0
- data/app/{assets/lookbook/js/components/preview-window.js → components/lookbook/viewport/component.js} +57 -14
- data/app/components/lookbook/viewport/component.rb +21 -0
- data/app/controllers/lookbook/application_controller.rb +16 -5
- data/app/controllers/lookbook/pages_controller.rb +17 -8
- data/app/controllers/lookbook/previews_controller.rb +130 -89
- data/app/helpers/lookbook/application_helper.rb +6 -2
- data/app/helpers/lookbook/component_helper.rb +22 -10
- data/app/helpers/lookbook/output_helper.rb +8 -4
- data/app/helpers/lookbook/page_helper.rb +13 -21
- data/app/views/layouts/lookbook/application.html.erb +76 -28
- data/app/views/layouts/lookbook/inspector.html.erb +7 -0
- data/app/views/layouts/lookbook/page.html.erb +53 -0
- data/app/views/layouts/lookbook/shell.html.erb +64 -0
- data/app/views/layouts/lookbook/skeleton.html.erb +27 -10
- data/app/views/layouts/lookbook/standalone.html.erb +5 -0
- data/app/views/lookbook/404.html.erb +15 -0
- data/app/views/lookbook/error.html.erb +34 -34
- data/app/views/lookbook/index.html.erb +11 -6
- data/app/views/lookbook/pages/show.html.erb +37 -91
- data/app/views/{layouts/lookbook → lookbook}/preview.html.erb +6 -8
- data/app/views/lookbook/previews/panels/_content.html.erb +13 -0
- data/app/views/lookbook/previews/panels/_notes.html.erb +19 -25
- data/app/views/lookbook/previews/panels/_output.html.erb +7 -18
- data/app/views/lookbook/previews/panels/_params.html.erb +13 -15
- data/app/views/lookbook/previews/panels/_preview.html.erb +6 -52
- data/app/views/lookbook/previews/panels/_source.html.erb +6 -15
- data/app/views/lookbook/previews/show.html.erb +133 -24
- data/config/routes.rb +5 -5
- data/lib/lookbook/code_formatter.rb +37 -13
- data/lib/lookbook/collection.rb +19 -16
- data/lib/lookbook/config.rb +180 -0
- data/lib/lookbook/engine.rb +66 -59
- data/lib/lookbook/entity.rb +47 -0
- data/lib/lookbook/error.rb +1 -2
- data/lib/lookbook/features.rb +1 -1
- data/lib/lookbook/markdown.rb +3 -4
- data/lib/lookbook/page.rb +40 -34
- data/lib/lookbook/page_collection.rb +8 -0
- data/lib/lookbook/page_section.rb +31 -0
- data/lib/lookbook/params.rb +14 -3
- data/lib/lookbook/preview.rb +16 -7
- data/lib/lookbook/preview_collection.rb +8 -0
- data/lib/lookbook/preview_controller.rb +6 -2
- data/lib/lookbook/preview_example.rb +5 -6
- data/lib/lookbook/preview_group.rb +4 -9
- data/lib/lookbook/{code_inspector.rb → source_inspector.rb} +2 -2
- data/lib/lookbook/store.rb +36 -0
- data/lib/lookbook/theme.rb +29 -0
- data/lib/lookbook/utils.rb +10 -2
- data/lib/lookbook/version.rb +1 -1
- data/lib/lookbook.rb +6 -1
- data/lib/tasks/lookbook_tasks.rake +12 -0
- data/public/lookbook-assets/css/app.css +2340 -1
- data/public/lookbook-assets/css/app.css.map +11 -1
- data/public/lookbook-assets/css/lookbook.css +3069 -0
- data/public/lookbook-assets/css/lookbook.css.map +1 -0
- data/public/lookbook-assets/css/themes/blue.css +44 -0
- data/public/lookbook-assets/css/themes/blue.css.map +1 -0
- data/public/lookbook-assets/css/themes/indigo.css +44 -0
- data/public/lookbook-assets/css/themes/indigo.css.map +1 -0
- data/public/lookbook-assets/css/themes/zinc.css +44 -0
- data/public/lookbook-assets/css/themes/zinc.css.map +1 -0
- data/public/lookbook-assets/js/app.js +10861 -1
- data/public/lookbook-assets/js/app.js.map +2571 -1
- data/public/lookbook-assets/js/embed.js +895 -1
- data/public/lookbook-assets/js/embed.js.map +1 -1
- data/public/lookbook-assets/js/lookbook.js +13541 -0
- data/public/lookbook-assets/js/lookbook.js.map +1 -0
- metadata +133 -116
- data/app/assets/lookbook/css/app.css +0 -161
- data/app/assets/lookbook/css/code_theme.css +0 -214
- data/app/assets/lookbook/js/components/app.js +0 -55
- data/app/assets/lookbook/js/components/code.js +0 -5
- data/app/assets/lookbook/js/components/copy.js +0 -20
- data/app/assets/lookbook/js/components/embed.js +0 -89
- data/app/assets/lookbook/js/components/filter.js +0 -35
- data/app/assets/lookbook/js/components/inspector.js +0 -66
- data/app/assets/lookbook/js/components/nav-group.js +0 -47
- data/app/assets/lookbook/js/components/nav-item.js +0 -29
- data/app/assets/lookbook/js/components/nav.js +0 -28
- data/app/assets/lookbook/js/components/page-tabs.js +0 -9
- data/app/assets/lookbook/js/components/page.js +0 -25
- data/app/assets/lookbook/js/components/param.js +0 -34
- data/app/assets/lookbook/js/components/sidebar.js +0 -18
- data/app/assets/lookbook/js/components/sizes.js +0 -16
- data/app/assets/lookbook/js/components/splitter.js +0 -25
- data/app/assets/lookbook/js/components/tabs.js +0 -52
- data/app/assets/lookbook/js/lib/split.js +0 -15
- data/app/assets/lookbook/js/stores/sidebar.js +0 -26
- data/app/views/layouts/lookbook/basic.html.erb +0 -7
- data/app/views/lookbook/components/_branding.html.erb +0 -8
- data/app/views/lookbook/components/_code.html.erb +0 -17
- data/app/views/lookbook/components/_copy_button.html.erb +0 -11
- data/app/views/lookbook/components/_drawer.html.erb +0 -112
- data/app/views/lookbook/components/_embed.html.erb +0 -39
- data/app/views/lookbook/components/_errors.html.erb +0 -13
- data/app/views/lookbook/components/_filter.html.erb +0 -18
- data/app/views/lookbook/components/_header.html.erb +0 -6
- data/app/views/lookbook/components/_icon.html.erb +0 -5
- data/app/views/lookbook/components/_nav.html.erb +0 -16
- data/app/views/lookbook/components/_nav_collection.html.erb +0 -5
- data/app/views/lookbook/components/_nav_group.html.erb +0 -14
- data/app/views/lookbook/components/_nav_item.html.erb +0 -24
- data/app/views/lookbook/components/_nav_page.html.erb +0 -22
- data/app/views/lookbook/components/_nav_preview.html.erb +0 -13
- data/app/views/lookbook/components/_not_found.html.erb +0 -11
- data/app/views/lookbook/components/_param.html.erb +0 -21
- data/app/views/lookbook/components/_preview.html.erb +0 -77
- data/app/views/lookbook/components/_sidebar.html.erb +0 -69
- data/app/views/lookbook/pages/not_found.html.erb +0 -15
- data/app/views/lookbook/previews/error.html.erb +0 -1
- data/app/views/lookbook/previews/inputs/_select.html.erb +0 -7
- data/app/views/lookbook/previews/inputs/_text.html.erb +0 -8
- data/app/views/lookbook/previews/inputs/_textarea.html.erb +0 -8
- data/app/views/lookbook/previews/inputs/_toggle.html.erb +0 -13
- data/app/views/lookbook/previews/not_found.html.erb +0 -23
@@ -0,0 +1,151 @@
|
|
1
|
+
import Split from "split-grid";
|
2
|
+
import { observeSize } from "@helpers/layout";
|
3
|
+
|
4
|
+
export default function splitLayoutComponent({ split, opts = {} }) {
|
5
|
+
let splitter = null;
|
6
|
+
const shouldSplit = split.sizes !== null;
|
7
|
+
|
8
|
+
return {
|
9
|
+
layoutResizing: false,
|
10
|
+
|
11
|
+
layoutWidth: null,
|
12
|
+
|
13
|
+
layoutHeight: null,
|
14
|
+
|
15
|
+
forceOrientation: null,
|
16
|
+
|
17
|
+
get vertical() {
|
18
|
+
if (this.forceOrientation) {
|
19
|
+
return this.forceOrientation === "vertical";
|
20
|
+
}
|
21
|
+
return split.direction === "vertical";
|
22
|
+
},
|
23
|
+
|
24
|
+
get horizontal() {
|
25
|
+
if (this.forceOrientation) {
|
26
|
+
return this.forceOrientation === "horizontal";
|
27
|
+
}
|
28
|
+
return split.direction === "horizontal";
|
29
|
+
},
|
30
|
+
|
31
|
+
get splits() {
|
32
|
+
if (this.horizontal && split.horizontalSizes) {
|
33
|
+
return split.horizontalSizes;
|
34
|
+
} else if (this.vertical && split.verticalSizes) {
|
35
|
+
return split.verticalSizes;
|
36
|
+
} else {
|
37
|
+
return split.sizes || [];
|
38
|
+
}
|
39
|
+
},
|
40
|
+
|
41
|
+
get minSizes() {
|
42
|
+
if (this.horizontal && opts.minHorizontalSizes) {
|
43
|
+
return opts.minHorizontalSizes;
|
44
|
+
} else if (this.vertical && opts.minVerticalSizes) {
|
45
|
+
return opts.minVerticalSizes;
|
46
|
+
} else {
|
47
|
+
return opts.minSizes || [];
|
48
|
+
}
|
49
|
+
},
|
50
|
+
|
51
|
+
init() {
|
52
|
+
observeSize(this.$el, ({ width, height }) => {
|
53
|
+
this.layoutWidth = width;
|
54
|
+
this.layoutHeight = height;
|
55
|
+
});
|
56
|
+
},
|
57
|
+
|
58
|
+
switchOrientation() {
|
59
|
+
split.direction = this.vertical ? "horizontal" : "vertical";
|
60
|
+
},
|
61
|
+
|
62
|
+
registerGutter() {
|
63
|
+
this._gutters.push(this.$el);
|
64
|
+
},
|
65
|
+
|
66
|
+
initSplit() {
|
67
|
+
if (shouldSplit && this._gutters.length) {
|
68
|
+
this._destroySplit();
|
69
|
+
const dir = this.horizontal ? "row" : "column";
|
70
|
+
splitter = Split({
|
71
|
+
[`${dir}Gutters`]: gutterSplits(this._gutters),
|
72
|
+
[`${dir}MinSizes`]: sizeSplits(this.minSizes),
|
73
|
+
snapOffset: 0,
|
74
|
+
dragInterval: 1,
|
75
|
+
writeStyle() {},
|
76
|
+
onDrag: (dir, gutterTrack, style) => {
|
77
|
+
const splits = style
|
78
|
+
.split(" ")
|
79
|
+
.map((value, i) => (i % 2 == 0 ? value : null))
|
80
|
+
.filter((v) => v);
|
81
|
+
this._setSplits(splits);
|
82
|
+
},
|
83
|
+
onDragStart: () => {
|
84
|
+
this.layoutResizing = true;
|
85
|
+
this.$dispatch("layout:resize-start", { layout: this });
|
86
|
+
},
|
87
|
+
onDragEnd: () => {
|
88
|
+
this.layoutResizing = false;
|
89
|
+
this.$dispatch("layout:resize-end", { layout: this });
|
90
|
+
},
|
91
|
+
});
|
92
|
+
}
|
93
|
+
},
|
94
|
+
|
95
|
+
bindings: {
|
96
|
+
root: {
|
97
|
+
[":style"]() {
|
98
|
+
return {
|
99
|
+
"grid-template-columns":
|
100
|
+
shouldSplit && this.vertical && sizeStr(this.splits),
|
101
|
+
"grid-template-rows":
|
102
|
+
shouldSplit && this.horizontal && sizeStr(this.splits),
|
103
|
+
};
|
104
|
+
},
|
105
|
+
},
|
106
|
+
},
|
107
|
+
|
108
|
+
// protected
|
109
|
+
|
110
|
+
_gutters: [],
|
111
|
+
|
112
|
+
_destroySplit() {
|
113
|
+
if (splitter) splitter.destroy();
|
114
|
+
},
|
115
|
+
|
116
|
+
_setSplits(splits) {
|
117
|
+
if (this.horizontal && split.horizontalSizes) {
|
118
|
+
split.horizontalSizes = splits;
|
119
|
+
} else if (this.vertical && split.verticalSizes) {
|
120
|
+
split.verticalSizes = splits;
|
121
|
+
} else {
|
122
|
+
split.sizes = splits;
|
123
|
+
}
|
124
|
+
},
|
125
|
+
};
|
126
|
+
}
|
127
|
+
|
128
|
+
// utils
|
129
|
+
|
130
|
+
function sizeStr(sizes) {
|
131
|
+
const values = [];
|
132
|
+
sizes.forEach((size) => values.push(size, "1px"));
|
133
|
+
return values.slice(0, -1).join(" ");
|
134
|
+
}
|
135
|
+
|
136
|
+
function gutterSplits(gutters) {
|
137
|
+
return gutters.map((element, i) => {
|
138
|
+
return {
|
139
|
+
track: i * 2 + 1,
|
140
|
+
element,
|
141
|
+
};
|
142
|
+
});
|
143
|
+
}
|
144
|
+
|
145
|
+
function sizeSplits(sizes) {
|
146
|
+
const splits = {};
|
147
|
+
sizes.forEach((value, i) => {
|
148
|
+
if (value !== null) splits[i * 2] = value;
|
149
|
+
});
|
150
|
+
return splits;
|
151
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
export default function tabPanelsComponent(store) {
|
2
|
+
return {
|
3
|
+
get store() {
|
4
|
+
return store || this;
|
5
|
+
},
|
6
|
+
|
7
|
+
get id() {
|
8
|
+
return this.$root.id;
|
9
|
+
},
|
10
|
+
|
11
|
+
get panels() {
|
12
|
+
return Array.from(this.$refs.panels.children);
|
13
|
+
},
|
14
|
+
|
15
|
+
isActive(el) {
|
16
|
+
return this.store.activeTab === this._getRef(el);
|
17
|
+
},
|
18
|
+
|
19
|
+
// protected
|
20
|
+
|
21
|
+
_getRef(el) {
|
22
|
+
return el.getAttribute("x-ref");
|
23
|
+
},
|
24
|
+
};
|
25
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class TabPanels::Component < Lookbook::Component
|
3
|
+
renders_many :panels, ->(**attrs) do
|
4
|
+
@panel_counter += 1
|
5
|
+
attrs[:name] ||= "tab-#{@panel_counter}"
|
6
|
+
Lookbook::TabPanels::Panel::Component.new **attrs
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(**html_attrs)
|
10
|
+
@panel_counter = 0
|
11
|
+
super(**html_attrs)
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def alpine_component
|
17
|
+
"tabPanelsComponent"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<%= render_component_tag class: "flex items-center relative" do %>
|
2
|
+
<div x-ref="tabs" class="<%= class_names [
|
3
|
+
"flex items-stretch select-none min-w-0",
|
4
|
+
{
|
5
|
+
"h-10 space-x-6": @theme == :toolbar,
|
6
|
+
"space-x-3": @theme == :page,
|
7
|
+
}
|
8
|
+
] %>">
|
9
|
+
<%= safe_join(tabs) %>
|
10
|
+
</div>
|
11
|
+
<div x-ref="dropdownTrigger" class="absolute" x-show="hasHiddenTabs" :style="{left: `${triggerLeft}px`}">
|
12
|
+
<%= render_component :button, icon: :chevrons_right, x_show: "visibleTabsCount > 0" %>
|
13
|
+
<%= render_component :button, icon: :menu, class: "-ml-3", x_show: "visibleTabsCount === 0" %>
|
14
|
+
</div>
|
15
|
+
<div class="hidden">
|
16
|
+
<div x-ref="tabsDropdown" data-cloak>
|
17
|
+
<%= safe_join(dropdown_tabs) %>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
<% end %>
|
@@ -0,0 +1,115 @@
|
|
1
|
+
import debounce from "debounce";
|
2
|
+
import tippy from "~/app/assets/lookbook/js/lib/tippy";
|
3
|
+
import { observeSize } from "@helpers/layout";
|
4
|
+
import { getElementSize } from "@helpers/dom";
|
5
|
+
|
6
|
+
export default function tabsComponent(store) {
|
7
|
+
const initial = store ? store.activeTab : null;
|
8
|
+
let dropdown = null;
|
9
|
+
return {
|
10
|
+
visibleTabsCount: 0,
|
11
|
+
|
12
|
+
triggerLeft: 0,
|
13
|
+
|
14
|
+
get store() {
|
15
|
+
return store || this;
|
16
|
+
},
|
17
|
+
|
18
|
+
get tabs() {
|
19
|
+
return Array.from(this.$refs.tabs.children);
|
20
|
+
},
|
21
|
+
|
22
|
+
get dropdownTabs() {
|
23
|
+
return Array.from(
|
24
|
+
this.$refs.tabsDropdown ? this.$refs.tabsDropdown.children : []
|
25
|
+
);
|
26
|
+
},
|
27
|
+
|
28
|
+
get tabWidths() {
|
29
|
+
return this.tabs.map(
|
30
|
+
(tab) => getElementSize(tab, { includeMargins: true }).width
|
31
|
+
);
|
32
|
+
},
|
33
|
+
|
34
|
+
init() {
|
35
|
+
this.$nextTick(() => {
|
36
|
+
dropdown = tippy(this.$refs.dropdownTrigger, {
|
37
|
+
content: this.$refs.tabsDropdown,
|
38
|
+
theme: "menu",
|
39
|
+
interactive: true,
|
40
|
+
trigger: "click",
|
41
|
+
placement: "bottom",
|
42
|
+
appendTo: this.$root,
|
43
|
+
});
|
44
|
+
|
45
|
+
const initialTab = initial
|
46
|
+
? this.tabs.find((t) => this._getRef(t) === initial)
|
47
|
+
: this.tabs[0];
|
48
|
+
this.selectTab(initialTab);
|
49
|
+
|
50
|
+
this.parentObserver = observeSize(
|
51
|
+
this.$root.parentElement,
|
52
|
+
debounce(this.handleResize.bind(this), 10)
|
53
|
+
);
|
54
|
+
|
55
|
+
this.$watch("visibleTabsCount", (value) => {
|
56
|
+
this.debug(`'#${this.$root.id}' visible tabs count:`, value);
|
57
|
+
});
|
58
|
+
});
|
59
|
+
},
|
60
|
+
|
61
|
+
handleResize({ width }) {
|
62
|
+
if (width === this._lastMeasuredWidth) {
|
63
|
+
return;
|
64
|
+
}
|
65
|
+
|
66
|
+
if (width === this.$root.offsetWidth) {
|
67
|
+
console.log("uep");
|
68
|
+
this.visibleTabsCount = this.tabs.length;
|
69
|
+
return;
|
70
|
+
}
|
71
|
+
|
72
|
+
console.log(width);
|
73
|
+
|
74
|
+
let sumTabWidths = 60;
|
75
|
+
let triggerLeft = 20;
|
76
|
+
let visibleTabsCount = 0;
|
77
|
+
this.tabWidths.forEach((tabWidth) => {
|
78
|
+
sumTabWidths += tabWidth;
|
79
|
+
if (sumTabWidths < width) {
|
80
|
+
triggerLeft += tabWidth;
|
81
|
+
visibleTabsCount++;
|
82
|
+
}
|
83
|
+
});
|
84
|
+
|
85
|
+
this.visibleTabsCount = visibleTabsCount;
|
86
|
+
this.triggerLeft = triggerLeft;
|
87
|
+
this._lastMeasuredWidth = width;
|
88
|
+
},
|
89
|
+
|
90
|
+
selectTab(el) {
|
91
|
+
this.store.activeTab = this._getRef(el);
|
92
|
+
dropdown.hide();
|
93
|
+
},
|
94
|
+
|
95
|
+
isSelected(el) {
|
96
|
+
return this.store.activeTab === this._getRef(el);
|
97
|
+
},
|
98
|
+
|
99
|
+
isDisabled(el) {
|
100
|
+
return el.getAttribute("data-disabled") == "true";
|
101
|
+
},
|
102
|
+
|
103
|
+
hasHiddenTabs() {
|
104
|
+
return this.visibleTabsCount < this.tabs.length;
|
105
|
+
},
|
106
|
+
|
107
|
+
// protected
|
108
|
+
|
109
|
+
_lastMeasuredWidth: 0,
|
110
|
+
|
111
|
+
_getRef(el) {
|
112
|
+
return el ? el.getAttribute("x-ref").replace("dropdown-", "") : null;
|
113
|
+
},
|
114
|
+
};
|
115
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class Tabs::Component < Lookbook::Component
|
3
|
+
renders_many :tabs, ->(**attrs) do
|
4
|
+
@tab_counter += 1
|
5
|
+
attrs[:name] ||= "tab-#{@tab_counter}"
|
6
|
+
attrs[:position] ||= @tab_counter
|
7
|
+
attrs[:theme] ||= @theme
|
8
|
+
dropdown_tab(**attrs)
|
9
|
+
Lookbook::Tabs::Tab::Component.new(**attrs)
|
10
|
+
end
|
11
|
+
|
12
|
+
renders_many :dropdown_tabs, ->(name:, **attrs) do
|
13
|
+
Lookbook::Tabs::DropdownTab::Component.new(name: "dropdown-#{name}", **attrs)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(theme: :toolbar, **html_attrs)
|
17
|
+
@theme = theme
|
18
|
+
@tab_counter = 0
|
19
|
+
super(**html_attrs)
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
|
24
|
+
def alpine_component
|
25
|
+
"tabsComponent"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<%= render_component_tag :button,
|
2
|
+
x_ref: @name,
|
3
|
+
class: [
|
4
|
+
"whitespace-nowrap px-4 border-l-2 cursor-pointer block w-full text-left",
|
5
|
+
{
|
6
|
+
"py-2": @theme == :toolbar,
|
7
|
+
"py-2 text-base": @theme == :page,
|
8
|
+
}
|
9
|
+
],
|
10
|
+
":class": "{
|
11
|
+
'border-lookbook-tabs-highlight': isSelected($el),
|
12
|
+
'border-transparent text-lookbook-tabs-text hover:text-lookbook-tabs-text-hover': !isSelected($el),
|
13
|
+
'hidden': visibleTabsCount >= #{@position}
|
14
|
+
}",
|
15
|
+
"@click.prevent": "selectTab($el)",
|
16
|
+
data: {
|
17
|
+
disabled: @disabled
|
18
|
+
} do %>
|
19
|
+
<%= label %>
|
20
|
+
<% end %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class Tabs::DropdownTab::Component < Lookbook::Component
|
3
|
+
def initialize(name:, label: nil, hotkey: nil, disabled: nil, position: 0, theme: :toolbar, **html_attrs)
|
4
|
+
@name = name
|
5
|
+
@label = label
|
6
|
+
@hotkey = hotkey
|
7
|
+
@disabled = disabled
|
8
|
+
@position = position
|
9
|
+
@theme = theme
|
10
|
+
super(**html_attrs)
|
11
|
+
end
|
12
|
+
|
13
|
+
def label
|
14
|
+
@label.presence || content || @name.titleize
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<%= render_component_tag :button,
|
2
|
+
id: @id,
|
3
|
+
x_ref: @name,
|
4
|
+
class: [
|
5
|
+
"whitespace-nowrap cursor-pointer pt-2.5 pb-1.5 border-b-2",
|
6
|
+
{
|
7
|
+
"px-1": @theme == :toolbar,
|
8
|
+
"px-2 text-lg relative -bottom-px": @theme == :page,
|
9
|
+
}
|
10
|
+
],
|
11
|
+
":class": "{
|
12
|
+
'border-lookbook-tabs-highlight': isSelected($el),
|
13
|
+
'border-transparent text-lookbook-tabs-text hover:text-lookbook-tabs-text-hover': !isSelected($el),
|
14
|
+
'!text-lookbook-tabs-text-disabled': isDisabled($el),
|
15
|
+
'invisible pointer-events-none relative z-[-1]': visibleTabsCount < #{@position}
|
16
|
+
}",
|
17
|
+
"@click.prevent": "selectTab($el)",
|
18
|
+
"@keydown.window.prevent.#{@hotkey}": @hotkey.present? ? "$el.click()" : nil,
|
19
|
+
data: {
|
20
|
+
disabled: @disabled
|
21
|
+
},
|
22
|
+
cloak: true do %>
|
23
|
+
<%== label %>
|
24
|
+
<% end %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class Tabs::Tab::Component < Lookbook::Component
|
3
|
+
def initialize(name:, label: nil, hotkey: nil, disabled: nil, position: 0, theme: :toolbar, **html_attrs)
|
4
|
+
@name = name
|
5
|
+
@label = label
|
6
|
+
@hotkey = hotkey
|
7
|
+
@disabled = disabled
|
8
|
+
@position = position
|
9
|
+
@theme = theme
|
10
|
+
super(**html_attrs)
|
11
|
+
end
|
12
|
+
|
13
|
+
def label
|
14
|
+
@label.presence || content || @name.titleize
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class TagComponent < ViewComponent::Base
|
3
|
+
include Lookbook::ComponentHelper
|
4
|
+
|
5
|
+
def initialize(tag: :div, name: nil, cloak: false, **html_attrs)
|
6
|
+
@tag = tag
|
7
|
+
html_attrs[:class] = class_names(html_attrs[:class]) if html_attrs[:class]
|
8
|
+
html_attrs[:data] ||= {}
|
9
|
+
html_attrs[:data][:component] = name if name.present?
|
10
|
+
html_attrs[:x_cloak] = true if cloak == true
|
11
|
+
@html_attrs = convert_attrs(html_attrs)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
@html_attrs[Rails.version.to_f < 7.0 ? :escape_attributes : :escape] = false
|
16
|
+
tag.public_send(@tag, **@html_attrs) do
|
17
|
+
content
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def convert_attrs(html_attrs)
|
24
|
+
html_attrs.map do |name, value|
|
25
|
+
[name.to_s.tr("_", "-"), value]
|
26
|
+
end.to_h
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
@layer components {
|
2
|
+
[data-component="toolbar"] {
|
3
|
+
& .toolbar-sections > * {
|
4
|
+
@apply h-10 flex items-center whitespace-nowrap border-lookbook-toolbar-divider;
|
5
|
+
}
|
6
|
+
|
7
|
+
& [data-component="button-group"] {
|
8
|
+
padding-left: 0.45rem;
|
9
|
+
padding-right: 0.45rem;
|
10
|
+
}
|
11
|
+
|
12
|
+
& [data-component="tabs"] {
|
13
|
+
@apply relative -mb-px px-4;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Lookbook
|
2
|
+
class Toolbar::Component < Lookbook::Component
|
3
|
+
DIVIDE_CLASSES = {
|
4
|
+
left: "border-l",
|
5
|
+
right: "border-r"
|
6
|
+
}
|
7
|
+
|
8
|
+
ALIGN_CLASSES = {
|
9
|
+
right: "ml-auto",
|
10
|
+
left: "mr-auto",
|
11
|
+
middle: "mx-auto"
|
12
|
+
}
|
13
|
+
|
14
|
+
renders_many :sections, ->(align: :nil, divide: nil, padded: false, **attrs, &block) do
|
15
|
+
Lookbook::TagComponent.new class: [
|
16
|
+
"min-w-0",
|
17
|
+
{
|
18
|
+
"px-4": padded,
|
19
|
+
"#{DIVIDE_CLASSES[divide]}": divide.present?,
|
20
|
+
"#{ALIGN_CLASSES[align]}": align.present?
|
21
|
+
},
|
22
|
+
attrs[:class]
|
23
|
+
], **attrs.except(:class), &block
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
@layer components {
|
2
|
+
[data-component="viewport"] {
|
3
|
+
background-color: #ffffff;
|
4
|
+
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");
|
5
|
+
|
6
|
+
.resize-handle {
|
7
|
+
@apply flex items-center justify-center h-full w-full border-lookbook-divider bg-lookbook-viewport-handle hover:bg-indigo-100 hover:bg-opacity-20;
|
8
|
+
@apply text-lookbook-viewport-handle-icon hover:text-lookbook-viewport-handle-icon-hover transition select-none touch-none;
|
9
|
+
}
|
10
|
+
}
|
11
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
<%= render_component_tag class: "h-full min-h-0 w-full overflow-hidden relative", "@viewport:reload.window": "reloadIframe" do %>
|
2
|
+
<div class="absolute border border-lookbook-divider w-full h-full"></div>
|
3
|
+
<div
|
4
|
+
x-ref="wrapper"
|
5
|
+
class="mx-auto h-full w-full border border-b-0 border-lookbook-divider relative"
|
6
|
+
:style="`<% if @resize_width %>max-width: ${maxWidth};<% end %>
|
7
|
+
<% if @resize_height && @max_height.present? %>
|
8
|
+
max-height: min(${maxHeight}, <%= @max_height %>px);
|
9
|
+
<% elsif @resize_height %>
|
10
|
+
max-height: ${maxHeight};
|
11
|
+
<% elsif @max_height.present? %>
|
12
|
+
max-height: <%= @max_height %>px;
|
13
|
+
<% end %>`">
|
14
|
+
<div
|
15
|
+
class="grid bg-white relative -inset-px <%= "grid-cols-[1fr_17px]" if @resize_width %> <%= "grid-rows-[1fr_17px]" if @resize_height %>"
|
16
|
+
style="width: calc(100% + 2px); height: calc(100% + 1px); <%= "max-height: #{@max_height}px;" if @max_height.present? %>">
|
17
|
+
<iframe seamless
|
18
|
+
x-ref="iframe"
|
19
|
+
class="h-full w-full border border-lookbook-divider"
|
20
|
+
:class="{ 'pointer-events-none': reflowing }"
|
21
|
+
style="<%= "max-height: #{@max_height}px;" if @max_height.present? %>"
|
22
|
+
src="<%= @src %>"
|
23
|
+
frameborder="0"
|
24
|
+
@load="$dispatch('viewport:loaded', {viewport: this})"></iframe>
|
25
|
+
<% if @resize_width %>
|
26
|
+
<div
|
27
|
+
class="resize-handle border-r border-t border-lookbook-divider cursor-[col-resize] <%= "border-b" unless @resize_height %>"
|
28
|
+
@pointerdown="onResizeWidthStart"
|
29
|
+
@dblclick="toggleFullWidth">
|
30
|
+
<svg class="h-4 w-4 pointer-events-none" fill="currentColor" viewBox="0 0 24 24">
|
31
|
+
<path d="M8 5h2v14H8zM14 5h2v14h-2z"></path>
|
32
|
+
</svg>
|
33
|
+
</div>
|
34
|
+
<% end %>
|
35
|
+
<% if @resize_height %>
|
36
|
+
<div
|
37
|
+
class="resize-handle border-b border-l border-lookbook-divider cursor-[col-resize] <%= "border-r" unless @resize_width %>"
|
38
|
+
@pointerdown="onResizeHeightStart"
|
39
|
+
@dblclick="toggleFullHeight">
|
40
|
+
<svg class="h-4 w-4 pointer-events-none rotate-90" fill="currentColor" viewBox="0 0 24 24" >
|
41
|
+
<path d="M8 5h2v14H8zM14 5h2v14h-2z"></path>
|
42
|
+
</svg>
|
43
|
+
</div>
|
44
|
+
<% end %>
|
45
|
+
<% if @resize_height && @resize_width %>
|
46
|
+
<div
|
47
|
+
class="resize-handle border-r border-b border-lookbook-divider cursor-[nwse-resize]"
|
48
|
+
@pointerdown="onResizeStart"
|
49
|
+
@dblclick="toggleFullSize">
|
50
|
+
<svg class="h-3.5 w-3.5 pointer-events-none rotate-45 relative -top-px -left-px" fill="currentColor" viewBox="0 0 24 24" >
|
51
|
+
<path d="M8 5h2v14H8zM14 5h2v14h-2z"></path>
|
52
|
+
</svg>
|
53
|
+
</div>
|
54
|
+
<% end %>
|
55
|
+
</div>
|
56
|
+
</div>
|
57
|
+
<% end %>
|