Skip to content

Commit

Permalink
fix(hugo): fixes some hugo bookshop component browser init errors
Browse files Browse the repository at this point in the history
  • Loading branch information
bglw committed Mar 23, 2022
1 parent f5c7646 commit 0d8cc82
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 105 deletions.
2 changes: 1 addition & 1 deletion hugo/v2/core/bookshop_component_browser.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@
<script class="cms-no-rewrite" src="/_bookshop/bookshop-browser.js?cb={{ now.UnixMilli }}"></script>
{{- end -}}
<script>
window.bookshopBrowser = new window.BookshopBrowser({globals: []});
window.bookshopBrowser = new window.BookshopBrowser({globals: []});
window.bookshopBrowser.render();
</script>
144 changes: 80 additions & 64 deletions javascript-modules/browser/lib/app/svelte/browser.svelte
Original file line number Diff line number Diff line change
@@ -1,49 +1,49 @@
<script>
import {onMount} from 'svelte';
import {hydrateComponents, updateUrl, loadYaml} from './lib/helpers.js';
import {iconSvg} from './lib/icons.js';
import Library from './lib/library.svelte';
import InfoPane from './lib/info-pane.svelte';
import Editor from './lib/code-editor/editor.svelte';
import { onMount } from "svelte";
import { hydrateComponents, updateUrl, loadYaml } from "./lib/helpers.js";
import { iconSvg } from "./lib/icons.js";
import Library from "./lib/library.svelte";
import InfoPane from "./lib/info-pane.svelte";
import Editor from "./lib/code-editor/editor.svelte";
export let engines = [];
export let components = {};
export let globalData = {};
export let exclude = [];
let renderTarget, renderMap = {};
let renderTarget,
renderMap = {};
let editProps = true;
let baseYaml = '# Nothing'; // What is currently on disk
let editedYaml = '# Nothing'; // Edited in the browser
let baseYaml = "# Nothing"; // What is currently on disk
let editedYaml = "# Nothing"; // Edited in the browser
let yamlError = false;
let selectingComponent = false;
let selectedComponent = "nothing";
let previousComponent = "nothing";
let framework = "none";
let previousFramework = "none";
let activeEngine = {};
let hydratedComponents = null;
$: {
activeEngine?.destroy?.(renderTarget);
hydratedComponents = hydrateComponents(components, engines, exclude);
console.log(`Components Updated.`);
}
const refreshComponent = async (component, framework) => {
componentDetail = hydratedComponents?.[component];
if (!componentDetail) return;
availableFrameworks = componentDetail.frameworks || [];
if (!availableFrameworks.includes(framework)) {
framework = selectedFramework = availableFrameworks[0] || 'none';
framework = selectedFramework = availableFrameworks[0] || "none";
}
updateUrl(component, framework);
const newComponentSelected = previousComponent !== component;
const newFrameworkSelected = previousFramework !== framework;
const newComponentConfig = baseYaml !== componentDetail.yaml;
Expand All @@ -53,44 +53,57 @@
if (newComponentSelected || newFrameworkSelected) {
destroyPreviousComponent();
renderTarget.innerHTML = ''; // Clean up in case destroy() didn't
renderTarget.innerHTML = ""; // Clean up in case destroy() didn't
renderMap = {};
}
previousComponent = component;
previousFramework = framework;
}
};
$: if (hydratedComponents) refreshComponent(selectedComponent, framework);
const destroyPreviousComponent = () => {
const previousEngine = engines.filter(e => e.key === previousFramework)[0];
const previousEngine = engines.filter(
(e) => e.key === previousFramework
)[0];
if (previousEngine) {
previousEngine.destroy?.(renderTarget, previousComponent);
}
}
};
const buildComponentLadder = () => {
Object.entries(hydratedComponents).filter(([key]) => key !== 'all_bookshop').forEach(([key, component]) => {
const sectionLabel = `<div data-bookshop-browser-section>${iconSvg(component.identity.icon)} ${component.identity.label}</div>`;
renderTarget.insertAdjacentHTML('beforeend', sectionLabel);
const el = document.createElement('div');
renderMap[key] = el;
renderTarget.appendChild(el);
});
}
Object.entries(hydratedComponents)
.filter(([key]) => key !== "all_bookshop")
.forEach(([key, component]) => {
const sectionLabel = `<div data-bookshop-browser-section>${iconSvg(
component.identity.icon
)} ${component.identity.label}</div>`;
renderTarget.insertAdjacentHTML("beforeend", sectionLabel);
const el = document.createElement("div");
renderMap[key] = el;
renderTarget.appendChild(el);
});
};
const renderAllComponents = async (engine) => {
if (!renderTarget.innerHTML) buildComponentLadder();
const componentPromises = Object.entries(hydratedComponents).filter(([key]) => key !== 'all_bookshop').map(([key, component]) => {
return engine.render(renderMap[key], key, component.props, globalData);
});
const componentPromises = Object.entries(hydratedComponents)
.filter(([key]) => key !== "all_bookshop")
.map(([key, component]) => {
return engine.render(
renderMap[key],
key,
component.props,
globalData
);
});
await Promise.all(componentPromises);
}
};
const render = async (component, yamlProps, framework) => {
if (framework === 'none') return;
const engine = engines.filter(e => e.key === framework)[0];
if (framework === "none") return;
const engine = engines.filter((e) => e.key === framework)[0];
if (!engine) {
console.warn(`Engine ${framework} not found.`);
return;
Expand All @@ -100,23 +113,24 @@
return await renderAllComponents(engine);
}
let {props, err} = loadYaml(yamlProps);
let { props, err } = loadYaml(yamlProps);
yamlError = err;
if (yamlError) return;
activeEngine = engine;
await engine.render(renderTarget, component, props, globalData);
}
window.bookshopComponentHasRendered = true;
};
$: if (hydratedComponents) render(selectedComponent, editedYaml, framework);
const updateCode = (event) => {
editedYaml = event.detail.code;
}
};
onMount(() => {
let curUrl = new URL(window.location);
if (curUrl.hash) {
let urlComponent = curUrl.hash.replace(/^#/, '');
let urlComponent = curUrl.hash.replace(/^#/, "");
let [c, f] = urlComponent.split(":");
selectedComponent = c;
framework = f;
Expand All @@ -125,28 +139,32 @@
</script>
<div class="bookshop-browser-menus">
<Library components={hydratedComponents}
bind:selectedComponent={selectedComponent}
bind:selectingComponent={selectingComponent}
bind:framework={framework} />
<InfoPane component={hydratedComponents[selectedComponent]}
bind:selectingComponent={selectingComponent}
bind:framework={framework}
bind:editProps={editProps} />
<Library
components={hydratedComponents}
bind:selectedComponent
bind:selectingComponent
bind:framework
/>
<InfoPane
component={hydratedComponents[selectedComponent]}
bind:selectingComponent
bind:framework
bind:editProps
/>
{#if editProps && hydratedComponents[selectedComponent]?.props}
<Editor code={baseYaml} error={yamlError} on:newcode={updateCode} />
<Editor code={baseYaml} error={yamlError} on:newcode={updateCode} />
{/if}
</div>
<div class="bookshop-browser" bind:this={renderTarget}></div>
<div class="bookshop-browser" bind:this={renderTarget} />
<style>
.bookshop-browser-menus {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",
Helvetica, Arial, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica,
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
font-size: 12px;
display: flex;
position: relative;
Expand All @@ -167,9 +185,9 @@
:global([data-bookshop-browser-section]) {
display: flex;
align-items: center;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",
Helvetica, Arial, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica,
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
font-size: 12px;
width: 100%;
padding: 12px 0 4px;
Expand All @@ -183,5 +201,3 @@
border-bottom: solid 1px #aaa;
}
</style>
75 changes: 45 additions & 30 deletions javascript-modules/browser/lib/app/svelte/lib/library.svelte
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
<script>
import {iconSvg} from './icons.js';
import { iconSvg } from "./icons.js";
export let components = {};
export let selectedComponent = "";
export let selectingComponent = true;
export let framework = "none";
let list, input, searchTerm = "";
let list,
input,
searchTerm = "";
const init = () => {
input.focus();
}
};
$: if (selectingComponent && list) init();
Expand All @@ -20,45 +22,58 @@
framework = components[c]?.frameworks?.[0] ?? "none";
}
blurry();
}
};
const blurry = (e) => {
searchTerm = "";
if (e?.relatedTarget?.dataset?.blur !== "list-child") {
selectingComponent = false;
}
}
};
const filter = (list, term) => list.filter(([k, c]) => {
console.log(term);
if (!term) return true;
let searchKey = (k + c?.identity?.label).toLowerCase();
return searchKey.includes(term.toLowerCase());
});
const filter = (list, term) =>
list.filter(([k, c]) => {
if (!term) return true;
let searchKey = (k + c?.identity?.label).toLowerCase();
return searchKey.includes(term.toLowerCase());
});
</script>
<div class="component-list"
class:show={selectingComponent}
on:blur={blurry}
bind:this={list}
tabindex="-1">
<p class="title animate bookshop-icon-string">{@html iconSvg("folder_open")} Components</p>
<div
class="component-list"
class:show={selectingComponent}
on:blur={blurry}
bind:this={list}
tabindex="-1"
>
<p class="title animate bookshop-icon-string">
{@html iconSvg("folder_open")} Components
</p>
<button class="animate close">{@html iconSvg("close")}</button>
<div class="search animate">
<input data-blur="list-child" on:blur={blurry} bind:this={input} type="text" bind:value={searchTerm} placeholder="Search">
<input
data-blur="list-child"
on:blur={blurry}
bind:this={input}
type="text"
bind:value={searchTerm}
placeholder="Search"
/>
</div>
<ul>
{#each filter(Object.entries(components), searchTerm) as [key, component], i}
<li class="animate" style="transition-delay: {i/70}s;">
<button class="component bookshop-icon-string"
data-blur="list-child"
on:mousedown={set(key)}
on:blur={blurry}>
{@html iconSvg(component?.identity?.icon)}
{component?.identity?.label}
</button>
</li>
{/each}
{#each filter(Object.entries(components), searchTerm) as [key, component], i}
<li class="animate" style="transition-delay: {i / 70}s;">
<button
class="component bookshop-icon-string"
data-blur="list-child"
on:mousedown={set(key)}
on:blur={blurry}
>
{@html iconSvg(component?.identity?.icon)}
{component?.identity?.label}
</button>
</li>
{/each}
</ul>
</div>
Expand All @@ -67,7 +82,7 @@
position: absolute;
z-index: 999999999;
background-color: #fff;
border-right: solid 2px #AAA;
border-right: solid 2px #aaa;
width: 300px;
min-width: 300px;
max-height: 100vh;
Expand Down
Loading

0 comments on commit 0d8cc82

Please sign in to comment.