Skip to content

Commit

Permalink
Marcos/navigation (#11)
Browse files Browse the repository at this point in the history
* navigation component

* add a couple of pages

* fix lifecycle bug

* remove lifecycle component
  • Loading branch information
marcoseiza committed Sep 12, 2023
1 parent b949bc2 commit 5898c7e
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 41 deletions.
1 change: 0 additions & 1 deletion manifest-generator/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { readManifestFromLocalStorage } from "./state.js";
const registerServiceWorker = async () => {
try {
await navigator.serviceWorker.register("sw.js");
console.log("Service worker registered");
} catch (e) {
console.log(`Registration failed: ${e}`);
}
Expand Down
45 changes: 38 additions & 7 deletions manifest-generator/components/app-view.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
// A split app-view to show the manifest viewer in the right pane and the editor in the left pane.

import "./manifest-view/index.js";
import "./navigation-view.js";
import "./page-view.js";

const template = document.createElement("template");
template.innerHTML = `
<link rel="stylesheet" href="styles/defaults.css" />
<style>
:host {
display: flex;
Expand All @@ -27,28 +30,56 @@ template.innerHTML = `
}
</style>
<div class="app-view">
<placeholder-component></placeholder-component>
<navigation-view current-id="page-1" page-selector="page-view">
<page-view page-id="page-1" title="Page 1">
<p slot="text">Page 1</p>
</page-view>
<page-view page-id="page-2" title="Page 2">
<p slot="text">Page 2</p>
</page-view>
</navigation-view>
<manifest-view></manifest-view>
</div>
`;

class AppView extends HTMLElement {
constructor() {
super();

this.attachShadow({ mode: "open" });
this.shadowRoot.appendChild(template.content.cloneNode(true));
this.navigationView = this.shadowRoot.querySelector("navigation-view");

this.pageIds = ["page-1", "page-2"];
this.currentPageIdIndex = 0;

this.navigationView.addEventListener("next", () => this.nextPage());
this.navigationView.addEventListener("prev", () => this.prevPage());
this.navigationView.addEventListener("skip", () => this.skipPage());
}

nextPage() {
this.jumpToPage(
Math.min(this.currentPageIdIndex + 1, this.pageIds.length - 1)
);
}

connectedCallback() {
console.log("connected");
prevPage() {
this.jumpToPage(Math.max(this.currentPageIdIndex - 1, 0));
}

disconnectedCallback() {
console.log("disconnected");
skipPage() {
this.jumpToPage(
Math.min(this.currentPageIdIndex + 1, this.pageIds.length - 1)
);
}

render() {
console.log("render");
jumpToPage(pageIndex) {
this.currentPageIdIndex = pageIndex;
this.navigationView.setAttribute(
"current-id",
this.pageIds[this.currentPageIdIndex]
);
}
}

Expand Down
12 changes: 0 additions & 12 deletions manifest-generator/components/manifest-view/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,6 @@ class ManifestView extends HTMLElement {
</div>
`;
}

connectedCallback() {
console.log("connected");
}

disconnectedCallback() {
console.log("disconnected");
}

render() {
console.log("render");
}
}

// create a web component
Expand Down
5 changes: 1 addition & 4 deletions manifest-generator/components/manifest-view/json-array.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,12 @@ class JSONArray extends HTMLElement {
}

connectedCallback() {
console.log("connected");
const jsonValue = this.getAttribute("json");
this.json = JSON.parse(decodeURIComponent(jsonValue));
this.render();
}

disconnectedCallback() {
console.log("disconnected");
}
disconnectedCallback() {}

render() {
const jsonValue = this.json;
Expand Down
6 changes: 1 addition & 5 deletions manifest-generator/components/manifest-view/json.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,10 @@ class JSONView extends HTMLElement {
}

connectedCallback() {
console.log("connected");
const jsonValue = this.getAttribute("json");
this.json = JSON.parse(decodeURIComponent(jsonValue));
this.render();
}

disconnectedCallback() {
console.log("disconnected");
this.render();
}

render() {
Expand Down
5 changes: 0 additions & 5 deletions manifest-generator/components/manifest-view/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,11 @@ class Node extends HTMLElement {
}

connectedCallback() {
console.log("connected");
this.key = this.getAttribute("key");
this.value = this.getAttribute("value");
this.render();
}

disconnectedCallback() {
console.log("disconnected");
}

observedAttributes() {
return ["key", "value"];
}
Expand Down
128 changes: 128 additions & 0 deletions manifest-generator/components/navigation-view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
const template = document.createElement("template");
template.innerHTML = `
<link rel="stylesheet" href="styles/defaults.css" />
<link rel="stylesheet" href="styles/button.css" />
<style>
.left-pane {
height: 100%;
overflow: hidden;
display: flex;
flex-direction: column;
}
.page-wrapper {
flex-grow: 1;
}
.nav-bar {
display: grid;
padding: 10px;
width: 100%;
grid-template-columns: 1fr auto auto;
}
#prev, #skip, #next {
justify-self: start;
}
</style>
<div class="left-pane">
<div class="page-wrapper">
<slot></slot>
</div>
<div class="nav-bar">
<button class="btn-secondary" id="prev">prev</button>
<button class="btn-secondary" id="skip">skip</button>
<button class="btn-primary" id="next">next</button>
</div>
</div>
`;

const attributes = {
currentId: {
name: "current-id",
required: true,
},
pageSelector: {
name: "page-selector",
required: true,
},
};

class NavigationView extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: "open" });
shadow.append(template.content.cloneNode(true));
this.prevButton = this.shadowRoot.querySelector("#prev");
this.nextButton = this.shadowRoot.querySelector("#next");
this.skipButton = this.shadowRoot.querySelector("#skip");

this.prevButton.addEventListener("click", () => {
this.shadowRoot.dispatchEvent(
new CustomEvent("prev", {
composed: true,
bubbles: true,
})
);
});

this.nextButton.addEventListener("click", () => {
this.shadowRoot.dispatchEvent(
new CustomEvent("next", {
composed: true,
bubbles: true,
})
);
});

this.skipButton.addEventListener("click", () => {
this.shadowRoot.dispatchEvent(
new CustomEvent("skip", {
composed: true,
bubbles: true,
})
);
});

this.shadowRoot.querySelector("slot").addEventListener("slotchange", () => {
this.togglePage(this.currentId);
});
}

static get observedAttributes() {
return Object.values(attributes).map((opt) => opt.name);
}

// This method doesn't validate any form inputs, just html attributes.
validateAttributes(changedValue) {
Object.entries(attributes).forEach(([field, opts]) => {
if (changedValue !== undefined && opts.name !== changedValue) return;
const attribute = this.getAttribute(opts.name);
if (opts.required && !attribute)
throw new Error(
`Attribute ${opts.name} should be set in component ${this.tagName}`
);
this[field] = attribute;
});
}

togglePage(id) {
const pages = this.querySelectorAll(this.pageSelector);
pages.forEach((page) => {
page.toggleAttribute("hidden", page.pageId !== id);
});
}

connectedCallback() {
this.validateAttributes();
}

attributeChangedCallback(attr, oldVal, newVal) {
this.validateAttributes();
if (oldVal !== null && attr == attributes.currentId.name) {
this.togglePage(newVal);
}
}
}

customElements.define("navigation-view", NavigationView);
6 changes: 3 additions & 3 deletions manifest-generator/components/page-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@ class PageView extends HTMLElement {

const pageViewTemplate = document.createElement("template");
pageViewTemplate.innerHTML = `
<link rel="stylesheet" href="styles/defaults.css" />
<style>
#title {
text-align: center;
}
</style>
<h1 id="title">${this.getAttribute("title")}</h1>
<slot name="my-text">My Default Text</slot>`;
<slot name="text">My Default Text</slot>`;

// Create a shadow root
this.attachShadow({ mode: "open" });
this.shadowRoot.appendChild(pageViewTemplate.content.cloneNode(true));

// Set the id field based on the id attribute
this.#id = this.getAttribute("page-id");
console.log("this page's ID is = " + this.#id);
}

getId() {
get pageId() {
return this.#id;
}
}
Expand Down
6 changes: 2 additions & 4 deletions manifest-generator/index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
Expand All @@ -14,10 +14,8 @@
/>
</head>
<body>
<h1>Manifest generator</h1>
<a href="/design-reference.html" class="btn-primary">design reference</a>
<!-- <a href="/design-reference.html" class="btn-primary">design reference</a> -->
<script type="module" src="app.js"></script>
<script type="module" src="styles/shared-style.js"></script>
<script type="module" src="state.js"></script>
<script type="module" src="components/app-view.js"></script>
<app-view></app-view>
Expand Down

0 comments on commit 5898c7e

Please sign in to comment.