lookbook 1.5.5 → 2.0.0.beta.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -31
  3. data/app/assets/lookbook/css/lookbook.css +9 -0
  4. data/app/assets/lookbook/css/themes/blue.css +7 -0
  5. data/app/assets/lookbook/css/themes/green.css +7 -0
  6. data/app/assets/lookbook/css/themes/indigo.css +7 -0
  7. data/app/assets/lookbook/css/themes/rose.css +7 -0
  8. data/app/assets/lookbook/css/themes/zinc.css +7 -0
  9. data/app/assets/lookbook/css/tooltip.css +9 -6
  10. data/app/assets/lookbook/img/lucide-sprite.svg +4960 -0
  11. data/app/assets/lookbook/js/app.js +22 -4
  12. data/app/assets/lookbook/js/helpers/dom.js +4 -7
  13. data/app/assets/lookbook/js/helpers/string.js +4 -11
  14. data/app/assets/lookbook/js/index.js +61 -0
  15. data/app/assets/lookbook/js/lib/lookbook.js +113 -0
  16. data/app/assets/lookbook/js/lib/tippy.js +1 -0
  17. data/app/assets/lookbook/js/lookbook-core.js +1 -0
  18. data/app/assets/lookbook/js/lookbook.js +2 -61
  19. data/app/components/lookbook/base_component.rb +3 -1
  20. data/app/components/lookbook/button/component.html.erb +13 -24
  21. data/app/components/lookbook/button/component.js +13 -3
  22. data/app/components/lookbook/button/component.rb +16 -25
  23. data/app/components/lookbook/code/component.rb +0 -2
  24. data/app/components/lookbook/copy_button/component.html.erb +5 -5
  25. data/app/components/lookbook/copy_button/component.rb +6 -3
  26. data/app/components/lookbook/debug_menu/component.html.erb +1 -0
  27. data/app/components/lookbook/debug_menu/component.rb +12 -1
  28. data/app/components/lookbook/display_options/editor/component.html.erb +1 -1
  29. data/app/components/lookbook/display_options/field/component.css +0 -26
  30. data/app/components/lookbook/display_options/field/component.html.erb +1 -1
  31. data/app/components/lookbook/embed/component.html.erb +6 -51
  32. data/app/components/lookbook/embed/component.rb +17 -16
  33. data/app/components/lookbook/embed/inspector/component.html.erb +102 -0
  34. data/app/components/lookbook/embed/inspector/component.js +46 -0
  35. data/app/components/lookbook/embed/inspector/component.rb +64 -0
  36. data/app/components/lookbook/embed_code_dropdown/component.css +12 -0
  37. data/app/components/lookbook/embed_code_dropdown/component.html.erb +19 -0
  38. data/app/components/lookbook/embed_code_dropdown/component.js +26 -0
  39. data/app/components/lookbook/embed_code_dropdown/component.rb +41 -0
  40. data/app/components/lookbook/header/component.html.erb +7 -6
  41. data/app/components/lookbook/header/component.rb +5 -1
  42. data/app/components/lookbook/icon/component.html.erb +1 -1
  43. data/app/components/lookbook/icon_button/component.html.erb +20 -0
  44. data/app/components/lookbook/icon_button/component.rb +46 -0
  45. data/app/components/lookbook/nav/component.html.erb +0 -1
  46. data/app/components/lookbook/nav/entity/component.rb +2 -2
  47. data/app/components/lookbook/nav/item/component.rb +1 -1
  48. data/app/components/lookbook/page_tabs/component.html.erb +2 -2
  49. data/app/components/lookbook/params/editor/component.rb +1 -0
  50. data/app/components/lookbook/prose/component.rb +1 -3
  51. data/app/components/lookbook/tabs/component.html.erb +2 -2
  52. data/app/components/lookbook/tabs/component.js +1 -1
  53. data/app/components/lookbook/tag_component.rb +2 -1
  54. data/app/components/lookbook/text_button/component.html.erb +26 -0
  55. data/app/components/lookbook/text_button/component.rb +42 -0
  56. data/app/components/lookbook/toolbar/component.html.erb +1 -1
  57. data/app/components/lookbook/viewport/component.rb +0 -4
  58. data/app/controllers/concerns/lookbook/targetable_concern.rb +26 -22
  59. data/app/controllers/concerns/lookbook/with_panels_concern.rb +30 -0
  60. data/app/controllers/concerns/lookbook/with_preview_controller_concern.rb +4 -3
  61. data/app/controllers/lookbook/application_controller.rb +9 -12
  62. data/app/controllers/lookbook/embeds_controller.rb +148 -0
  63. data/app/controllers/lookbook/inspector_controller.rb +3 -22
  64. data/app/controllers/lookbook/page_controller.rb +7 -6
  65. data/app/controllers/lookbook/pages_controller.rb +3 -4
  66. data/app/controllers/lookbook/preview_controller.rb +17 -0
  67. data/app/controllers/lookbook/previews_controller.rb +10 -30
  68. data/app/helpers/lookbook/application_helper.rb +3 -19
  69. data/app/views/layouts/lookbook/application.html.erb +85 -60
  70. data/app/views/layouts/lookbook/embed.html.erb +16 -0
  71. data/app/views/layouts/lookbook/shell.html.erb +1 -1
  72. data/app/views/layouts/lookbook/skeleton.html.erb +13 -8
  73. data/app/views/lookbook/404.html.erb +2 -2
  74. data/app/views/lookbook/embeds/show.html.erb +12 -0
  75. data/app/views/lookbook/inspector/panels/_notes.html.erb +1 -1
  76. data/app/views/lookbook/inspector/panels/_output.html.erb +3 -3
  77. data/app/views/lookbook/inspector/panels/_source.html.erb +6 -6
  78. data/app/views/lookbook/inspector/show.html.erb +130 -123
  79. data/app/views/lookbook/pages/show.html.erb +81 -34
  80. data/app/views/lookbook/partials/_iframe_content_scripts.html.erb +1 -0
  81. data/app/views/lookbook/partials/_user_styles.html.erb +5 -0
  82. data/app/views/lookbook/previews/group.html.erb +14 -0
  83. data/app/views/lookbook/previews/preview.html.erb +5 -0
  84. data/app/views/lookbook/previews/show.html.erb +1 -0
  85. data/config/app.yml +31 -16
  86. data/config/panels.yml +23 -25
  87. data/config/routes.rb +3 -1
  88. data/config/tags.yml +6 -2
  89. data/lib/lookbook/cable/cable.rb +53 -0
  90. data/lib/lookbook/engine.rb +105 -93
  91. data/lib/lookbook/entities/collections/entity_collection.rb +11 -6
  92. data/lib/lookbook/entities/collections/page_collection.rb +33 -8
  93. data/lib/lookbook/entities/collections/preview_collection.rb +42 -17
  94. data/lib/lookbook/entities/collections/render_target_collection.rb +4 -0
  95. data/lib/lookbook/entities/collections/scenario_collection.rb +4 -0
  96. data/lib/lookbook/entities/concerns/{annotatable.rb → annotatable_entity.rb} +7 -6
  97. data/lib/lookbook/entities/concerns/{inspectable.rb → inspectable_entity.rb} +2 -1
  98. data/lib/lookbook/entities/concerns/{locatable.rb → locatable_entity.rb} +8 -14
  99. data/lib/lookbook/entities/concerns/navigable_entity.rb +44 -0
  100. data/lib/lookbook/entities/entity.rb +7 -2
  101. data/lib/lookbook/entities/{page.rb → page_entity.rb} +10 -6
  102. data/lib/lookbook/entities/{page_section.rb → page_section_entity.rb} +1 -1
  103. data/lib/lookbook/entities/preview_entity.rb +99 -0
  104. data/lib/lookbook/entities/renderable_entity.rb +50 -0
  105. data/lib/lookbook/entities/rendered_scenario_entity.rb +53 -0
  106. data/lib/lookbook/entities/scenario_entity.rb +112 -0
  107. data/lib/lookbook/entities/scenario_group_entity.rb +53 -0
  108. data/lib/lookbook/error.rb +5 -5
  109. data/lib/lookbook/file_watcher.rb +19 -35
  110. data/lib/lookbook/helpers/class_names_helper.rb +28 -0
  111. data/lib/lookbook/helpers/page_helper.rb +18 -0
  112. data/{app/helpers/lookbook → lib/lookbook/helpers}/preview_helper.rb +3 -0
  113. data/lib/lookbook/helpers/ui_elements_helper.rb +115 -0
  114. data/lib/lookbook/preview.rb +79 -0
  115. data/lib/lookbook/preview_controller_actions.rb +50 -0
  116. data/lib/lookbook/preview_parser.rb +4 -2
  117. data/lib/lookbook/reloaders.rb +71 -0
  118. data/lib/lookbook/runtime_context.rb +49 -0
  119. data/lib/lookbook/services/data/resolvers/data_resolver.rb +4 -6
  120. data/lib/lookbook/services/entities/entity_tree_builder.rb +6 -6
  121. data/lib/lookbook/services/list_resolver.rb +35 -0
  122. data/lib/lookbook/services/markdown_renderer.rb +12 -2
  123. data/lib/lookbook/services/priority_prefix_parser.rb +16 -0
  124. data/lib/lookbook/services/urls/search_param_encoder.rb +16 -0
  125. data/lib/lookbook/services/urls/search_param_parser.rb +7 -6
  126. data/lib/lookbook/stores/config_store.rb +16 -16
  127. data/lib/lookbook/stores/input_store.rb +1 -3
  128. data/lib/lookbook/stores/panel_store.rb +28 -50
  129. data/lib/lookbook/support/deprecation.rb +5 -0
  130. data/lib/lookbook/support/errors/preview_template_error.rb +7 -0
  131. data/lib/lookbook/support/evented_file_update_checker.rb +69 -0
  132. data/lib/lookbook/support/null_websocket.rb +9 -0
  133. data/lib/lookbook/support/store.rb +9 -0
  134. data/lib/lookbook/support/tree_node.rb +7 -7
  135. data/lib/lookbook/support/utils/path_utils.rb +7 -1
  136. data/lib/lookbook/support/utils/utils.rb +8 -0
  137. data/lib/lookbook/tags/{position_tag.rb → priority_tag.rb} +4 -4
  138. data/lib/lookbook/tags/renders_tag.rb +4 -0
  139. data/lib/lookbook/tags/tag_provider.rb +3 -0
  140. data/lib/lookbook/tags/type_tag.rb +7 -0
  141. data/lib/lookbook/tags/yard_tag.rb +1 -2
  142. data/lib/lookbook/version.rb +1 -1
  143. data/lib/lookbook/websocket.rb +6 -53
  144. data/lib/lookbook.rb +179 -53
  145. data/public/lookbook-assets/css/lookbook.css +432 -376
  146. data/public/lookbook-assets/css/lookbook.css.map +1 -1
  147. data/public/lookbook-assets/css/themes/blue.css +7 -0
  148. data/public/lookbook-assets/css/themes/blue.css.map +1 -1
  149. data/public/lookbook-assets/css/themes/green.css +7 -0
  150. data/public/lookbook-assets/css/themes/green.css.map +1 -1
  151. data/public/lookbook-assets/css/themes/indigo.css +7 -0
  152. data/public/lookbook-assets/css/themes/indigo.css.map +1 -1
  153. data/public/lookbook-assets/css/themes/rose.css +7 -0
  154. data/public/lookbook-assets/css/themes/rose.css.map +1 -1
  155. data/public/lookbook-assets/css/themes/zinc.css +7 -0
  156. data/public/lookbook-assets/css/themes/zinc.css.map +1 -1
  157. data/public/lookbook-assets/img/lucide-sprite.svg +4960 -0
  158. data/public/lookbook-assets/js/embed.js +1363 -843
  159. data/public/lookbook-assets/js/embed.js.map +1 -1
  160. data/public/lookbook-assets/js/iframe.js +906 -0
  161. data/public/lookbook-assets/js/iframe.js.map +1 -0
  162. data/public/lookbook-assets/js/index.js +13567 -0
  163. data/public/lookbook-assets/js/index.js.map +1 -0
  164. data/public/lookbook-assets/js/lookbook-core.js +85 -0
  165. data/public/lookbook-assets/js/lookbook-core.js.map +1 -0
  166. data/public/lookbook-assets/js/lookbook.js +151 -12726
  167. data/public/lookbook-assets/js/lookbook.js.map +1 -1
  168. data/public/lookbook-assets/lookbook-esm.js +1427 -0
  169. data/public/lookbook-assets/lookbook-esm.js.map +1 -0
  170. data/public/lookbook-assets/lookbook-global.js +1427 -0
  171. data/public/lookbook-assets/lookbook-global.js.map +1 -0
  172. data/public/lookbook-assets/lookbook.js +1427 -0
  173. data/public/lookbook-assets/lookbook.js.map +1 -0
  174. metadata +85 -77
  175. data/app/components/lookbook/embed/component.js +0 -39
  176. data/app/helpers/lookbook/component_helper.rb +0 -84
  177. data/app/helpers/lookbook/output_helper.rb +0 -19
  178. data/app/helpers/lookbook/page_helper.rb +0 -34
  179. data/app/views/layouts/lookbook/inspector.html.erb +0 -7
  180. data/app/views/layouts/lookbook/page.html.erb +0 -53
  181. data/app/views/layouts/lookbook/standalone.html.erb +0 -5
  182. data/app/views/lookbook/preview.html.erb +0 -14
  183. data/lib/lookbook/entities/collections/component_collection.rb +0 -4
  184. data/lib/lookbook/entities/collections/preview_example_collection.rb +0 -4
  185. data/lib/lookbook/entities/component.rb +0 -31
  186. data/lib/lookbook/entities/concerns/navigable.rb +0 -43
  187. data/lib/lookbook/entities/preview.rb +0 -87
  188. data/lib/lookbook/entities/preview_example.rb +0 -104
  189. data/lib/lookbook/entities/preview_group.rb +0 -52
  190. data/lib/lookbook/preview_actions.rb +0 -43
  191. data/lib/lookbook/process.rb +0 -21
  192. data/lib/lookbook/rendered_example.rb +0 -37
  193. data/lib/lookbook/services/position_prefix_parser.rb +0 -16
  194. data/lib/lookbook/services/urls/search_param_builder.rb +0 -13
  195. data/lib/lookbook/tags/component_tag.rb +0 -13
  196. /data/app/assets/lookbook/js/{embed.js → iframe.js} +0 -0
  197. /data/{app/channels/lookbook → lib/lookbook/cable}/connection.rb +0 -0
  198. /data/{app/channels/lookbook → lib/lookbook/cable}/reload_channel.rb +0 -0
@@ -21,7 +21,7 @@ export default function app() {
21
21
 
22
22
  init() {
23
23
  if (window.SOCKET_PATH) {
24
- console.log("SOCKET CREATED");
24
+ this.debug(`Lookbook socket created`);
25
25
  const socket = createSocket(window.SOCKET_PATH);
26
26
  socket.addListener("Lookbook::ReloadChannel", () => this.updateDOM());
27
27
  }
@@ -43,9 +43,19 @@ export default function app() {
43
43
 
44
44
  hijax(evt) {
45
45
  const link = evt.target.closest("a[href]");
46
- if (link && !isExternalLink(link)) {
47
- evt.preventDefault();
48
- this.navigateTo(link.href);
46
+ if (link) {
47
+ const external = isExternalLink(link);
48
+ const embedded = this.isEmbedded();
49
+
50
+ if (embedded && (!link.hasAttribute("target") || external)) {
51
+ evt.preventDefault();
52
+ window.top.location = link.href;
53
+ return;
54
+ } else if (!embedded && !external && !link.hasAttribute("target")) {
55
+ evt.preventDefault();
56
+ this.navigateTo(link.href);
57
+ return;
58
+ }
49
59
  }
50
60
  },
51
61
 
@@ -89,6 +99,14 @@ export default function app() {
89
99
  }
90
100
  },
91
101
 
102
+ isEmbedded() {
103
+ try {
104
+ return window.self !== window.top;
105
+ } catch (e) {
106
+ return true;
107
+ }
108
+ },
109
+
92
110
  ...Alpine.$log,
93
111
  };
94
112
  }
@@ -5,12 +5,12 @@ function morph(from, to) {
5
5
  },
6
6
  lookahead: true,
7
7
  updating(el, toEl, childrenOnly, skip) {
8
- if (
9
- el.getAttribute &&
10
- el.getAttribute("data-morph-strategy") === "replace"
11
- ) {
8
+ if (!el.getAttribute) return;
9
+ if (el.getAttribute("data-morph-strategy") === "replace") {
12
10
  el.innerHTML = toEl.innerHTML;
13
11
  return skip();
12
+ } else if (el.getAttribute("data-morph-strategy") === "skip") {
13
+ return skip();
14
14
  }
15
15
  },
16
16
  });
@@ -33,9 +33,6 @@ function getElementSize(el, opts = {}) {
33
33
  }
34
34
 
35
35
  function isExternalLink(link) {
36
- if (link.getAttribute("target") === "_blank") {
37
- return true;
38
- }
39
36
  if (link.href) {
40
37
  return link.host !== window.location.host;
41
38
  }
@@ -9,20 +9,13 @@ function prefixString(string, prefix = null) {
9
9
  }
10
10
 
11
11
  function parseSearchParamValue(value) {
12
- const params = {};
13
- value.split("|").forEach((pair_str) => {
14
- const [key, value] = pair_str.split(":").map((part) => part.trim());
15
- params[key] = value;
16
- });
17
- return params;
12
+ const json = decodeURIComponent(value);
13
+ return JSON.parse(json);
18
14
  }
19
15
 
20
16
  function buildSearchParamValue(data) {
21
- const pairs = [];
22
- for (const [key, value] of Object.entries(data)) {
23
- pairs.push(`${key}:${value}`);
24
- }
25
- return pairs.join("|");
17
+ const str = JSON.stringify(data);
18
+ return encodeURIComponent(str);
26
19
  }
27
20
 
28
21
  export {
@@ -0,0 +1,61 @@
1
+ import Alpine from "alpinejs";
2
+
3
+ import Morph from "@alpinejs/morph";
4
+ import Persist from "@alpinejs/persist";
5
+ import Collapse from "@alpinejs/morph";
6
+ import Tooltip from "@ryangjchandler/alpine-tooltip";
7
+
8
+ import Logger, { log } from "./plugins/logger";
9
+
10
+ import initLayoutStore from "./stores/layout";
11
+ import initNavStore from "./stores/nav";
12
+ import initInspectorStore from "./stores/inspector";
13
+ import initPagesStore from "./stores/pages";
14
+ import initSettingsStore from "./stores/settings";
15
+ import initWorkbenchStore from "./stores/workbench";
16
+
17
+ import app from "./app";
18
+
19
+ // Note: A ParcelJS issue prevents loading all depths of component JS files in one glob,
20
+ // so need to split it up. Path aliases also do not work with the glob imports.
21
+ import { getComponents } from "./helpers/build";
22
+ import * as components from "../../../components/lookbook/*/*component.js";
23
+ import * as subComponents from "../../../components/lookbook/*/*/component.js";
24
+ import * as jsComponents from "./components/*.js";
25
+
26
+ // Plugins
27
+
28
+ Alpine.plugin(Morph);
29
+ Alpine.plugin(Persist);
30
+ Alpine.plugin(Collapse);
31
+ Alpine.plugin(Tooltip);
32
+ Alpine.plugin(Logger);
33
+
34
+ // Stores
35
+ const prefix = window.APP_NAME;
36
+ Alpine.store("layout", initLayoutStore(Alpine, { prefix }));
37
+ Alpine.store("nav", initNavStore(Alpine, { prefix }));
38
+ Alpine.store("inspector", initInspectorStore(Alpine, { prefix }));
39
+ Alpine.store("pages", initPagesStore(Alpine, { prefix }));
40
+ Alpine.store("settings", initSettingsStore(Alpine, { prefix }));
41
+
42
+ if (process.env.NODE_ENV !== "production") {
43
+ Alpine.store("workbench", initWorkbenchStore(Alpine, { prefix }));
44
+ }
45
+
46
+ // Components
47
+
48
+ Alpine.data("app", app);
49
+
50
+ [components, subComponents, jsComponents].forEach((scripts) => {
51
+ const components = getComponents(scripts);
52
+ Object.keys(components).forEach((name) => {
53
+ Alpine.data(`${name}Component`, components[name]);
54
+ });
55
+ });
56
+
57
+ // Init
58
+
59
+ window.log = log;
60
+ window.Alpine = Alpine;
61
+ Alpine.start();
@@ -0,0 +1,113 @@
1
+ window.Lookbook = window.Lookbook || {};
2
+ window.Lookbook.initEmbeds = initEmbeds;
3
+
4
+ const embedUrlPrefix = "embed";
5
+ const whiteListedAttributes = [
6
+ "preview",
7
+ "scenario",
8
+ "panels",
9
+ "actions",
10
+ "param-*",
11
+ ];
12
+
13
+ function initEmbeds() {
14
+ if (typeof window.iFrameResize !== "function") {
15
+ console.error(
16
+ "Lookbook embeds require the 'iframe-resizer' library to be available. Skipping embed instantiation."
17
+ );
18
+ return;
19
+ }
20
+
21
+ const embeds = Array.from(document.querySelectorAll("lookbook-embed"));
22
+
23
+ embeds.forEach((embed) => {
24
+ const attrs = Array.from(embed.attributes);
25
+ const wrapper = createWrapper();
26
+ const iframe = createIframe(attrs);
27
+
28
+ wrapper.appendChild(iframe);
29
+ embed.replaceWith(wrapper);
30
+ });
31
+
32
+ window.iFrameResize({ checkOrigin: false }, "[data-lookbook-embed-iframe]");
33
+ }
34
+
35
+ function createWrapper() {
36
+ const wrapper = document.createElement("div");
37
+
38
+ wrapper.setAttribute("data-lookbook-embed", "");
39
+ wrapper.classList.add("lookbook-embed");
40
+
41
+ return wrapper;
42
+ }
43
+
44
+ function createIframe(attrs) {
45
+ const src = buildSrc(attrs);
46
+ const id = attrValue(attrs, "id");
47
+ const styles = attrValue(attrs, "style");
48
+ const classes = attrValue(attrs, "class", "")
49
+ .split(" ")
50
+ .map((c) => c.trim())
51
+ .filter((c) => c.length);
52
+
53
+ const iframe = document.createElement("iframe");
54
+ iframe.src = src;
55
+ if (id) iframe.id = id;
56
+
57
+ iframe.setAttribute("frameborder", 0);
58
+ iframe.setAttribute("data-lookbook-embed-iframe", "");
59
+
60
+ if (classes.length) iframe.classList.add(...classes);
61
+ if (styles) iframe.style.cssText = styles;
62
+
63
+ iframe.style.width = "100%";
64
+ iframe.style.transition = "height 0.3s";
65
+
66
+ return iframe;
67
+ }
68
+
69
+ function buildSrc(attrs) {
70
+ const appPath = attrValue(attrs, "app") || guessBasePath();
71
+ const props = {};
72
+
73
+ permittedAttrs(attrs).forEach(({ name, value }) => {
74
+ name = name.replace("-", "_").toLowerCase();
75
+ props[name] = value;
76
+ });
77
+
78
+ return encodeURI(
79
+ [appPath, embedUrlPrefix].join("/") + `?props=${JSON.stringify(props)}`
80
+ );
81
+ }
82
+
83
+ function attrValue(attrs, name, fallback = null) {
84
+ const attr = attrs.find((attr) => attr.name === name);
85
+ return attr ? attr.value : fallback;
86
+ }
87
+
88
+ function permittedAttrs(attrs) {
89
+ return attrs.filter((attr) => {
90
+ return whiteListedAttributes.find((key) => {
91
+ const name = attr.name;
92
+ return (
93
+ key === name ||
94
+ (key.includes("*") && name.startsWith(key.replace("*", "")))
95
+ );
96
+ });
97
+ });
98
+ }
99
+
100
+ function guessBasePath() {
101
+ const script =
102
+ document.currentScript ||
103
+ document.querySelector('script[src*="lookbook.js"]');
104
+ const scriptSrc = script.src;
105
+
106
+ if (scriptSrc && scriptSrc.includes("lookbook-assets")) {
107
+ return scriptSrc.replace("lookbook-assets/js/lookbook.js", "lookbook");
108
+ }
109
+
110
+ return `//${location.host}/lookbook`;
111
+ }
112
+
113
+ document.addEventListener("DOMContentLoaded", () => initEmbeds());
@@ -3,6 +3,7 @@ import tippy from "tippy.js";
3
3
  tippy.setDefaultProps({
4
4
  allowHTML: true,
5
5
  theme: "tooltip",
6
+ appendTo: document.getElementById("app"),
6
7
  });
7
8
 
8
9
  export default tippy;
@@ -0,0 +1 @@
1
+ import "./lib/lookbook";
@@ -1,61 +1,2 @@
1
- import Alpine from "alpinejs";
2
-
3
- import Morph from "@alpinejs/morph";
4
- import Persist from "@alpinejs/persist";
5
- import Collapse from "@alpinejs/morph";
6
- import Tooltip from "@ryangjchandler/alpine-tooltip";
7
-
8
- import Logger, { log } from "./plugins/logger";
9
-
10
- import initLayoutStore from "./stores/layout";
11
- import initNavStore from "./stores/nav";
12
- import initInspectorStore from "./stores/inspector";
13
- import initPagesStore from "./stores/pages";
14
- import initSettingsStore from "./stores/settings";
15
- import initWorkbenchStore from "./stores/workbench";
16
-
17
- import app from "./app";
18
-
19
- // Note: A ParcelJS issue prevents loading all depths of component JS files in one glob,
20
- // so need to split it up. Path aliases also do not work with the glob imports.
21
- import { getComponents } from "./helpers/build";
22
- import * as components from "../../../components/lookbook/*/*component.js";
23
- import * as subComponents from "../../../components/lookbook/*/*/component.js";
24
- import * as jsComponents from "./components/*.js";
25
-
26
- // Plugins
27
-
28
- Alpine.plugin(Morph);
29
- Alpine.plugin(Persist);
30
- Alpine.plugin(Collapse);
31
- Alpine.plugin(Tooltip);
32
- Alpine.plugin(Logger);
33
-
34
- // Stores
35
- const prefix = window.APP_NAME;
36
- Alpine.store("layout", initLayoutStore(Alpine, { prefix }));
37
- Alpine.store("nav", initNavStore(Alpine, { prefix }));
38
- Alpine.store("inspector", initInspectorStore(Alpine, { prefix }));
39
- Alpine.store("pages", initPagesStore(Alpine, { prefix }));
40
- Alpine.store("settings", initSettingsStore(Alpine, { prefix }));
41
-
42
- if (process.env.NODE_ENV !== "production") {
43
- Alpine.store("workbench", initWorkbenchStore(Alpine, { prefix }));
44
- }
45
-
46
- // Components
47
-
48
- Alpine.data("app", app);
49
-
50
- [components, subComponents, jsComponents].forEach((scripts) => {
51
- const components = getComponents(scripts);
52
- Object.keys(components).forEach((name) => {
53
- Alpine.data(`${name}Component`, components[name]);
54
- });
55
- });
56
-
57
- // Init
58
-
59
- window.log = log;
60
- window.Alpine = Alpine;
61
- Alpine.start();
1
+ import "iframe-resizer/js/iframeResizer";
2
+ import "./lib/lookbook";
@@ -1,6 +1,8 @@
1
1
  module Lookbook
2
2
  class BaseComponent < ViewComponent::Base
3
- include Lookbook::ComponentHelper
3
+ include Lookbook::Engine.routes.url_helpers
4
+ include Lookbook::UiElementsHelper
5
+ include Lookbook::ClassNamesHelper if Engine.runtime_context.rails_older_than?("6.1.0")
4
6
 
5
7
  def initialize(alpine_data: [], **html_attrs)
6
8
  @alpine_data ||= alpine_data
@@ -1,28 +1,17 @@
1
- <%= render_component_tag tag_name,
2
- href: @href,
3
- class: [
4
- "block text-lookbook-icon-button-stroke focus:outline-none focus-visible:outline-none #{padding}",
5
- {
6
- "hover:text-lookbook-icon-button-stroke-hover": !@disabled,
7
- "cursor-[not-allowed] opacity-50": @disabled
8
- }
9
- ],
10
- disabled: @disabled,
1
+ <%= lookbook_render button_component.new(
2
+ id: id,
3
+ icon: icon,
4
+ **button_attrs,
11
5
  "@keydown.esc.stop": "hideDropdown",
12
- "@navigation:complete.window": "updateDropdown" do %>
13
- <span x-ref="icon">
14
- <%= icon || lookbook_render(:icon, name: @icon, size: icon_size, ":class": "{'animate-spin': _spinning}") %>
15
- </span>
16
- <% if @tooltip %>
17
- <label class="hidden" x-ref="tooltip"><%= @tooltip %></label>
18
- <% end %>
19
- <% if content %>
20
- <div x-ref="content"><%== content %></div>
21
- <% end %>
22
- <% if dropdown? %>
23
- <div class="hidden" x-ref="dropdown">
24
- <div class="bg-white divide-y divide-lookbook-divider text-left">
25
- <%== dropdown %>
6
+ "@navigation:complete.window": "updateDropdown") do %>
7
+ <%= content %>
8
+ <% end %>
9
+
10
+ <% if dropdown? %>
11
+ <% content_for :dropdowns do %>
12
+ <div data-dropdown-id="<%= id %>">
13
+ <div class="divide-y divide-lookbook-divider text-left">
14
+ <%= dropdown %>
26
15
  </div>
27
16
  </div>
28
17
  <% end %>
@@ -13,9 +13,9 @@ export default function buttonComponent() {
13
13
  });
14
14
  }
15
15
 
16
- if (this.$refs.dropdown) {
16
+ if (this.dropdownContent) {
17
17
  dropdown = tippy(this.$el, {
18
- content: this.$refs.dropdown.innerHTML,
18
+ content: this.dropdownContent,
19
19
  trigger: "click",
20
20
  theme: "menu",
21
21
  triggerTarget: this.$el,
@@ -32,6 +32,16 @@ export default function buttonComponent() {
32
32
  }
33
33
  },
34
34
 
35
+ get dropdownContent() {
36
+ if (this.$root && this.$root.id) {
37
+ const dropdown = document.querySelector(
38
+ `[data-dropdown-id="${this.$root.id}"]`
39
+ );
40
+ return dropdown ? dropdown.innerHTML : null;
41
+ }
42
+ return null;
43
+ },
44
+
35
45
  hideDropdown() {
36
46
  if (dropdown) {
37
47
  dropdown.hide();
@@ -42,7 +52,7 @@ export default function buttonComponent() {
42
52
  if (dropdown) {
43
53
  dropdown.hide();
44
54
  this.$nextTick(() => {
45
- dropdown.setContent(this.$refs.dropdown.innerHTML);
55
+ dropdown.setContent(this.dropdownContent);
46
56
  });
47
57
  }
48
58
  },
@@ -1,44 +1,35 @@
1
1
  module Lookbook
2
2
  class Button::Component < Lookbook::BaseComponent
3
- renders_one :icon, Lookbook::Icon::Component
4
3
  renders_one :dropdown
5
4
 
6
- ICON_SIZES = {
7
- xs: 3,
8
- sm: 3.5,
9
- md: 4,
10
- lg: 6
11
- }
5
+ attr_reader :id, :icon, :button_attrs
12
6
 
13
- def initialize(icon: nil, tooltip: nil, disabled: false, size: :md, href: nil, **html_attrs)
7
+ def initialize(id: nil, icon: nil, **html_attrs)
8
+ @id = id
14
9
  @icon = icon
15
- @tooltip = tooltip
16
- @disabled = disabled
17
- @size = size
18
- @href = href
19
- super(**html_attrs)
10
+ @button_attrs = html_attrs
20
11
  end
21
12
 
22
- def icon_size
23
- ICON_SIZES[@size]
13
+ def dropdown?
14
+ dropdown.present?
24
15
  end
25
16
 
26
- def padding
27
- [:xs, :sm].include?(@size) ? "p-1" : "p-2"
17
+ def text_button?
18
+ content.present?
28
19
  end
29
20
 
30
- def tag_name
31
- @href.present? ? :a : :button
21
+ def icon_button?
22
+ !text_button? && icon
32
23
  end
33
24
 
34
- def dropdown?
35
- dropdown.present?
25
+ def before_render
26
+ if dropdown? && id.nil?
27
+ raise "Dropdown buttons must be given an ID"
28
+ end
36
29
  end
37
30
 
38
- protected
39
-
40
- def alpine_component
41
- "buttonComponent"
31
+ def button_component
32
+ icon_button? ? IconButton::Component : TextButton::Component
42
33
  end
43
34
  end
44
35
  end
@@ -1,7 +1,5 @@
1
1
  module Lookbook
2
2
  class Code::Component < Lookbook::BaseComponent
3
- include Lookbook::OutputHelper
4
-
5
3
  def initialize(
6
4
  source: nil,
7
5
  language: :html,
@@ -1,11 +1,11 @@
1
- <%= lookbook_render :button,
1
+ <%= lookbook_render :icon_button,
2
2
  name: "copy-button",
3
- **@button_attrs,
3
+ **button_attrs,
4
4
  "x-data": prepare_alpine_data,
5
5
  "@click.prevent": "copyToClipboard" do |button| %>
6
- <% button.with_icon name: @icon, size: icon_size, "x-show": "!copied", cloak: true %>
7
- <%= icon :check, size: icon_size, class: "text-green-500", "x-show": "copied", cloak: true %>
6
+ <% button.with_icon name: icon, size: icon_size, "x-show": "!copied", cloak: true %>
7
+ <% button.with_icon name: :check, size: icon_size, class: "text-green-500", "x-show": "copied", cloak: true %>
8
8
  <% if content %>
9
9
  <div x-ref="copyTarget" class="hidden"><%== content %></div>
10
10
  <% end %>
11
- <% end %>
11
+ <% end %>
@@ -1,19 +1,22 @@
1
1
  module Lookbook
2
2
  class CopyButton::Component < Lookbook::BaseComponent
3
- def initialize(target: nil, icon: :code, **attrs)
3
+ attr_reader :icon, :size, :target, :button_attrs
4
+
5
+ def initialize(target: nil, icon: :code, size: :md, **attrs)
4
6
  @icon = icon
7
+ @size = size
5
8
  @target = target
6
9
  @button_attrs = attrs
7
10
  end
8
11
 
9
12
  def icon_size
10
- Lookbook::Button::Component::ICON_SIZES[@size]
13
+ IconButton::Component::ICON_SIZES[size]
11
14
  end
12
15
 
13
16
  protected
14
17
 
15
18
  def alpine_data
16
- content ? nil : alpine_encode(@target)
19
+ content ? nil : alpine_encode(target)
17
20
  end
18
21
 
19
22
  def alpine_component
@@ -27,6 +27,7 @@
27
27
  </li>
28
28
  </ul>
29
29
  </div>
30
+
30
31
  <div class="flex items-center text-xs px-3 py-2 bg-zinc-50">
31
32
  <span class="opacity-70 mr-1">Lookbook</span>
32
33
  <span class="mr-6">v<%= @version %></span>
@@ -1,12 +1,23 @@
1
1
  module Lookbook
2
2
  class DebugMenu::Component < Lookbook::BaseComponent
3
- def initialize(version: nil, docs_url: nil, repo_url: nil, **html_attrs)
3
+ attr_reader :features
4
+
5
+ def initialize(version: nil, docs_url: nil, repo_url: nil, features: {}, **html_attrs)
4
6
  @version = version
5
7
  @docs_url = docs_url
6
8
  @repo_url = repo_url
9
+ @features = features
7
10
  super(**html_attrs)
8
11
  end
9
12
 
13
+ def auto_refresh_enabled?
14
+ feature(:auto_refresh, false)
15
+ end
16
+
17
+ def feature(name, fallback = nil)
18
+ features.fetch(name.to_sym, fallback)
19
+ end
20
+
10
21
  def debug_data
11
22
  content
12
23
  end
@@ -1,6 +1,6 @@
1
1
  <%= render_component_tag class: "px-2" do %>
2
2
  <% if fields.many? %>
3
- <%= lookbook_render :button, icon: :settings, tooltip: "Display options" do |button| %>
3
+ <%= lookbook_render :button, id: "display-options-dropdown-button", icon: :settings, tooltip: "Display options" do |button| %>
4
4
  <% button.with_dropdown do %>
5
5
  <div class="p-3 space-y-3">
6
6
  <%= safe_join(fields) %>
@@ -1,33 +1,7 @@
1
1
  @layer components {
2
2
  [data-component="display-options-field"] {
3
- [type="text"],
4
- [type="email"],
5
- [type="url"],
6
- [type="password"],
7
- [type="number"],
8
- [type="date"],
9
- [type="datetime-local"],
10
- [type="month"],
11
- [type="search"],
12
- [type="tel"],
13
- [type="time"],
14
- [type="week"],
15
- textarea,
16
- select {
17
- padding: 0.26rem 0.6rem;
18
- font-size: 0.8rem;
19
- line-height: 1.1rem;
20
- }
21
-
22
3
  label {
23
4
  @apply text-[0.82rem] text-lookbook-input-text cursor-pointer;
24
5
  }
25
-
26
- select {
27
- border-radius: 0.375rem;
28
- padding-right: 1.5rem;
29
- background-size: 1.2em 1.2em;
30
- background-position: right 0.4rem center;
31
- }
32
6
  }
33
7
  }
@@ -3,6 +3,6 @@
3
3
  <label for="<%= name %>">
4
4
  <%= name.to_s.titleize %>:
5
5
  </label>
6
- <%= select_tag(name, options_for_select(choices, value), "x-model": "value") %>
6
+ <%= select_tag(name, options_for_select(choices, value), "x-model": "value", class: "compact") %>
7
7
  </div>
8
8
  <% end %>