From dc06a33a724bd2ed3ee7939023f0fd0a26858965 Mon Sep 17 00:00:00 2001 From: Tim Rijkse Date: Wed, 14 Jan 2026 15:05:12 +0100 Subject: [PATCH] fix: initial commit --- .dockerignore | 30 + .gitignore | 29 + Dockerfile | 22 + book.html | 147 ++++ css/styles.css | 623 +++++++++++++++++ index.html | 127 ++++ js/app.js | 18 + js/components/book-card.js | 211 ++++++ js/components/horizontal-scroll-nav.js | 113 ++++ js/components/search-bar.js | 98 +++ js/components/site-content.js | 35 + js/components/site-footer.js | 111 +++ js/components/site-header.js | 41 ++ js/components/top-bar.js | 110 +++ package-lock.json | 891 +++++++++++++++++++++++++ package.json | 15 + 16 files changed, 2621 insertions(+) create mode 100644 .dockerignore create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 book.html create mode 100644 css/styles.css create mode 100644 index.html create mode 100644 js/app.js create mode 100644 js/components/book-card.js create mode 100644 js/components/horizontal-scroll-nav.js create mode 100644 js/components/search-bar.js create mode 100644 js/components/site-content.js create mode 100644 js/components/site-footer.js create mode 100644 js/components/site-header.js create mode 100644 js/components/top-bar.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4bb7877 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,30 @@ +# Git +.git +.gitignore + +# Editor directories and files +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# OS generated files +.DS_Store +Thumbs.db + +# Documentation +README.md +*.md + +# Local environment +.env +.env.local +.env.*.local + +# Logs +*.log + +# Temporary files +tmp/ +temp/ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4cf1684 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db +node_modules/ + +# Editor directories and files +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# Logs +*.log + +# Local environment +.env +.env.local +.env.*.local + +# Temporary files +tmp/ +temp/ +*.tmp diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f3c15af --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM node:20-alpine + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm install --production + +# Copy static files +COPY . . + +# Set environment +ENV NODE_ENV=production +ENV PORT=3000 + +# Expose port +EXPOSE 3000 + +# Start the server +CMD ["npm", "start"] diff --git a/book.html b/book.html new file mode 100644 index 0000000..bf73bcc --- /dev/null +++ b/book.html @@ -0,0 +1,147 @@ + + + + + + + The Midnight Library - BookStore + + + +
+ + + + + + + +
+ + + + + + Back to Books + + + +
+
+ + + +
+
+ + +
+

The Midnight Library

+

by Matt Haig

+ +
+
+ + + + + +
+ 4.5 (2,847 reviews) +
+ +
+
+ Format + Hardcover +
+
+ Pages + 304 +
+
+ Language + English +
+
+
+ + +
+
+ $14.99 + $24.99 + 40% OFF +
+ +
+ + +
+
+ + +
+

About this book

+

Between life and death there is a library, and within that library, the shelves go on forever. Every book provides a chance to try another life you could have lived. To see how things would be if you had made other choices... Would you have done anything different, if you had the chance to undo your regrets?

+

A dazzling novel about all the choices that go into a life well lived, from the internationally bestselling author of Reasons to Stay Alive and How to Stop Time.

+
+ + +
+

Customer Reviews

+ +
+
+
+ Sarah M. + December 2025 +
+
+ + + + + +
+
+

This book changed my perspective on life. Beautifully written and deeply thought-provoking. A must-read for anyone going through a difficult time.

+
+ +
+
+
+ James K. + November 2025 +
+
+ + + + + +
+
+

Great concept and well-executed. The writing flows effortlessly and keeps you engaged throughout. Highly recommend!

+
+ + +
+
+
+ + +
+ + + + diff --git a/css/styles.css b/css/styles.css new file mode 100644 index 0000000..4cd0d11 --- /dev/null +++ b/css/styles.css @@ -0,0 +1,623 @@ +/* ========================================================================== + CSS Reset & Normalize (Modern Best Practices) + Based on normalize.css v8.0.1 + modern resets + ========================================================================== */ + +/* Box sizing rules */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +/* Prevent font size inflation */ +html { + -moz-text-size-adjust: none; + -webkit-text-size-adjust: none; + text-size-adjust: none; +} + +/* Remove default margin and padding */ +* { + margin: 0; + padding: 0; +} + +/* Set core root defaults */ +html { + font-size: 16px; + line-height: 1.5; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* Set core body defaults */ +body { + min-height: 100vh; + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, + Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + line-height: 1.5; + text-rendering: optimizeSpeed; +} + +/* Remove list styles on ul, ol elements */ +ul, +ol { + list-style: none; +} + +/* Anchor elements that don't have a class get default styles */ +a:not([class]) { + text-decoration-skip-ink: auto; +} + +/* Make images easier to work with */ +img, +picture, +video, +canvas, +svg { + display: block; + max-width: 100%; + height: auto; +} + +/* Inherit fonts for inputs and buttons */ +input, +button, +textarea, +select { + font: inherit; + color: inherit; +} + +/* Remove default button styles */ +button { + background: none; + border: none; + cursor: pointer; +} + +/* Make sure textareas without a rows attribute are not tiny */ +textarea:not([rows]) { + min-height: 10em; +} + +/* Anything that has been anchored to should have extra scroll margin */ +:target { + scroll-margin-block: 5ex; +} + +/* Remove all animations, transitions and smooth scroll for people that prefer not to see them */ +@media (prefers-reduced-motion: reduce) { + html:focus-within { + scroll-behavior: auto; + } + + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} + +/* Remove the inner border and padding in Firefox */ +::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/* Restore the focus styles unset by the previous rule */ +:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/* Remove the additional ':invalid' styles in Firefox */ +:-moz-ui-invalid { + box-shadow: none; +} + +/* Correct the cursor style of increment and decrement buttons in Safari */ +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* Correct the outline style in Safari */ +[type="search"] { + outline-offset: -2px; +} + +/* Remove the inner padding in Chrome and Safari on macOS */ +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* Correct the inability to style clickable types in iOS and Safari */ +::-webkit-file-upload-button { + -webkit-appearance: button; + font: inherit; +} + +/* Interactive elements */ +summary { + display: list-item; +} + +/* Table */ +table { + border-collapse: collapse; + border-spacing: 0; +} + +/* ========================================================================== + CSS Custom Properties (Design Tokens) + ========================================================================== */ + +:root { + /* Colors */ + --color-primary: #2563eb; + --color-primary-dark: #1d4ed8; + --color-secondary: #64748b; + --color-accent: #f59e0b; + + --color-text: #1e293b; + --color-text-light: #64748b; + --color-text-inverse: #ffffff; + + --color-background: #ffffff; + --color-background-secondary: #f8fafc; + --color-background-tertiary: #f1f5f9; + + --color-border: #e2e8f0; + --color-border-light: #f1f5f9; + + --color-success: #22c55e; + --color-error: #ef4444; + --color-warning: #f59e0b; + + /* Typography */ + --font-family-base: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', + Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', + 'Helvetica Neue', sans-serif; + --font-family-heading: var(--font-family-base); + + --font-size-xs: 0.75rem; /* 12px */ + --font-size-sm: 0.875rem; /* 14px */ + --font-size-base: 1rem; /* 16px */ + --font-size-lg: 1.125rem; /* 18px */ + --font-size-xl: 1.25rem; /* 20px */ + --font-size-2xl: 1.5rem; /* 24px */ + --font-size-3xl: 1.875rem; /* 30px */ + + --font-weight-normal: 400; + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + + --line-height-tight: 1.25; + --line-height-normal: 1.5; + --line-height-relaxed: 1.75; + + /* Spacing */ + --spacing-xs: 0.25rem; /* 4px */ + --spacing-sm: 0.5rem; /* 8px */ + --spacing-md: 1rem; /* 16px */ + --spacing-lg: 1.5rem; /* 24px */ + --spacing-xl: 2rem; /* 32px */ + --spacing-2xl: 3rem; /* 48px */ + + /* Border Radius */ + --radius-sm: 0.25rem; /* 4px */ + --radius-md: 0.5rem; /* 8px */ + --radius-lg: 0.75rem; /* 12px */ + --radius-xl: 1rem; /* 16px */ + --radius-full: 9999px; + + /* Shadows */ + --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); + --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); + --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + + /* Transitions */ + --transition-fast: 150ms ease; + --transition-normal: 250ms ease; + --transition-slow: 350ms ease; + + /* Layout */ + --mobile-max-width: 430px; + --header-height: auto; + --footer-height: auto; +} + +/* ========================================================================== + Base Styles + ========================================================================== */ + +body { + font-family: var(--font-family-base); + font-size: var(--font-size-base); + color: var(--color-text); + background-color: var(--color-background-secondary); +} + +/* ========================================================================== + Mobile Container (for desktop viewing) + Centers content in a phone-sized container on larger screens + ========================================================================== */ + +.mobile-container { + width: 100%; + min-height: 100vh; + margin: 0 auto; + background-color: var(--color-background); + position: relative; +} + +@media (min-width: 431px) { + body { + display: flex; + justify-content: center; + align-items: flex-start; + padding: var(--spacing-lg) 0; + } + + .mobile-container { + max-width: var(--mobile-max-width); + min-height: calc(100vh - var(--spacing-lg) * 2); + border-radius: var(--radius-xl); + box-shadow: var(--shadow-lg); + overflow: hidden; + } +} + +/* ========================================================================== + Utility Classes + ========================================================================== */ + +.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.truncate-2 { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* ========================================================================== + Page Components + ========================================================================== */ + +/* Section */ +.section { + margin-bottom: var(--spacing-xl); +} + +.section-title { + font-size: var(--font-size-lg); + font-weight: var(--font-weight-semibold); + color: var(--color-text); + margin-bottom: var(--spacing-md); +} + +.section-heading { + font-size: var(--font-size-base); + font-weight: var(--font-weight-semibold); + color: var(--color-text); + margin-bottom: var(--spacing-md); +} + +/* Book Grid */ +.book-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: var(--spacing-md); +} + +/* ========================================================================== + Book Detail Page + ========================================================================== */ + +.book-detail { + display: flex; + flex-direction: column; + gap: var(--spacing-lg); +} + +/* Back Link */ +.back-link { + display: inline-flex; + align-items: center; + gap: var(--spacing-xs); + font-size: var(--font-size-sm); + color: var(--color-text-light); + text-decoration: none; + transition: color var(--transition-fast); +} + +.back-link:hover { + color: var(--color-primary); +} + +/* Book Cover */ +.book-cover { + display: flex; + justify-content: center; +} + +.book-cover-placeholder { + width: 180px; + height: 270px; + background-color: var(--color-background-tertiary); + border-radius: var(--radius-lg); + display: flex; + align-items: center; + justify-content: center; + color: var(--color-text-light); + box-shadow: var(--shadow-md); +} + +.book-cover-placeholder svg { + width: 64px; + height: 64px; + opacity: 0.5; +} + +.book-cover img { + width: 180px; + height: auto; + border-radius: var(--radius-lg); + box-shadow: var(--shadow-md); +} + +/* Book Info */ +.book-info { + text-align: center; +} + +.book-title { + font-size: var(--font-size-2xl); + font-weight: var(--font-weight-bold); + color: var(--color-text); + margin-bottom: var(--spacing-xs); + line-height: var(--line-height-tight); +} + +.book-author { + font-size: var(--font-size-base); + color: var(--color-text-light); + margin-bottom: var(--spacing-md); +} + +.book-rating { + display: flex; + align-items: center; + justify-content: center; + gap: var(--spacing-sm); + margin-bottom: var(--spacing-md); +} + +.book-rating .stars { + display: flex; + gap: 2px; +} + +.book-rating .stars svg { + width: 18px; + height: 18px; + color: var(--color-accent); +} + +.rating-text { + font-size: var(--font-size-sm); + color: var(--color-text-light); +} + +.book-meta { + display: flex; + justify-content: center; + gap: var(--spacing-lg); + padding: var(--spacing-md); + background-color: var(--color-background-tertiary); + border-radius: var(--radius-lg); +} + +.meta-item { + display: flex; + flex-direction: column; + align-items: center; + gap: var(--spacing-xs); +} + +.meta-label { + font-size: var(--font-size-xs); + color: var(--color-text-light); + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.meta-value { + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); + color: var(--color-text); +} + +/* Purchase Section */ +.purchase-section { + padding: var(--spacing-md); + background-color: var(--color-background-secondary); + border-radius: var(--radius-lg); +} + +.price-container { + display: flex; + align-items: center; + gap: var(--spacing-sm); + margin-bottom: var(--spacing-md); +} + +.current-price { + font-size: var(--font-size-2xl); + font-weight: var(--font-weight-bold); + color: var(--color-text); +} + +.original-price { + font-size: var(--font-size-base); + color: var(--color-text-light); + text-decoration: line-through; +} + +.discount-badge { + padding: var(--spacing-xs) var(--spacing-sm); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); + color: var(--color-text-inverse); + background-color: var(--color-success); + border-radius: var(--radius-sm); +} + +.purchase-actions { + display: flex; + gap: var(--spacing-sm); +} + +/* Buttons */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--spacing-sm); + padding: var(--spacing-sm) var(--spacing-md); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); + border-radius: var(--radius-lg); + border: none; + cursor: pointer; + transition: all var(--transition-fast); +} + +.btn-primary { + flex: 1; + color: var(--color-text-inverse); + background-color: var(--color-primary); +} + +.btn-primary:hover { + background-color: var(--color-primary-dark); +} + +.btn-secondary { + padding: var(--spacing-sm); + color: var(--color-text); + background-color: var(--color-background); + border: 1px solid var(--color-border); +} + +.btn-secondary:hover { + background-color: var(--color-background-tertiary); +} + +.btn-outline { + color: var(--color-primary); + background-color: transparent; + border: 1px solid var(--color-primary); +} + +.btn-outline:hover { + background-color: var(--color-primary); + color: var(--color-text-inverse); +} + +.btn-large { + padding: var(--spacing-md) var(--spacing-lg); + font-size: var(--font-size-base); +} + +.btn-full { + width: 100%; +} + +/* Book Description */ +.book-description p { + font-size: var(--font-size-sm); + color: var(--color-text); + line-height: var(--line-height-relaxed); + margin-bottom: var(--spacing-md); +} + +.book-description p:last-child { + margin-bottom: 0; +} + +/* Reviews Section */ +.reviews-section { + display: flex; + flex-direction: column; + gap: var(--spacing-md); +} + +.review-card { + padding: var(--spacing-md); + background-color: var(--color-background-secondary); + border-radius: var(--radius-lg); +} + +.review-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: var(--spacing-sm); +} + +.reviewer-info { + display: flex; + flex-direction: column; +} + +.reviewer-name { + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); + color: var(--color-text); +} + +.review-date { + font-size: var(--font-size-xs); + color: var(--color-text-light); +} + +.review-stars { + display: flex; + gap: 2px; +} + +.review-stars svg { + width: 14px; + height: 14px; + color: var(--color-accent); +} + +.review-text { + font-size: var(--font-size-sm); + color: var(--color-text); + line-height: var(--line-height-normal); +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..e68914e --- /dev/null +++ b/index.html @@ -0,0 +1,127 @@ + + + + + + + BookStore - Home + + + +
+ + + + + + + +
+

Featured Books

+
+ + + + +
+
+ +
+

New Releases

+
+ + + + +
+
+ +
+

Best Sellers

+
+ + + + +
+
+
+ + +
+ + + + diff --git a/js/app.js b/js/app.js new file mode 100644 index 0000000..d1b66f1 --- /dev/null +++ b/js/app.js @@ -0,0 +1,18 @@ +/** + * Main Application Entry Point + * Imports and registers all web components + */ + +// Import all components +import './components/site-header.js'; +import './components/top-bar.js'; +import './components/horizontal-scroll-nav.js'; +import './components/search-bar.js'; +import './components/site-content.js'; +import './components/site-footer.js'; +import './components/book-card.js'; + +// App initialization (if needed) +document.addEventListener('DOMContentLoaded', () => { + console.log('BookStore app initialized'); +}); diff --git a/js/components/book-card.js b/js/components/book-card.js new file mode 100644 index 0000000..a700d77 --- /dev/null +++ b/js/components/book-card.js @@ -0,0 +1,211 @@ +/** + * Book Card Component + * Reusable card displaying book thumbnail, title, author, and price + */ +class BookCard extends HTMLElement { + static get observedAttributes() { + return ['title', 'author', 'price', 'image', 'href', 'rating']; + } + + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + } + + connectedCallback() { + this.render(); + } + + attributeChangedCallback() { + if (this.shadowRoot) { + this.render(); + } + } + + get title() { + return this.getAttribute('title') || 'Book Title'; + } + + get author() { + return this.getAttribute('author') || 'Author Name'; + } + + get price() { + return this.getAttribute('price') || '$0.00'; + } + + get image() { + return this.getAttribute('image') || ''; + } + + get href() { + return this.getAttribute('href') || 'book.html'; + } + + get rating() { + return parseFloat(this.getAttribute('rating')) || 0; + } + + renderStars(rating) { + const fullStars = Math.floor(rating); + const hasHalf = rating % 1 >= 0.5; + const emptyStars = 5 - fullStars - (hasHalf ? 1 : 0); + + let stars = ''; + + // Full stars + for (let i = 0; i < fullStars; i++) { + stars += ` + + `; + } + + // Half star + if (hasHalf) { + stars += ` + + + + + + + + `; + } + + // Empty stars + for (let i = 0; i < emptyStars; i++) { + stars += ` + + `; + } + + return stars; + } + + render() { + // Generate placeholder image if none provided + const imageHtml = this.image + ? `${this.title}` + : `
+ + + +
`; + + this.shadowRoot.innerHTML = ` + + +
+ ${imageHtml} +
+
+

${this.title}

+

${this.author}

+ ${this.rating > 0 ? `
${this.renderStars(this.rating)}
` : ''} +

${this.price}

+
+
+ `; + } +} + +customElements.define('book-card', BookCard); diff --git a/js/components/horizontal-scroll-nav.js b/js/components/horizontal-scroll-nav.js new file mode 100644 index 0000000..0c7bc7d --- /dev/null +++ b/js/components/horizontal-scroll-nav.js @@ -0,0 +1,113 @@ +/** + * Horizontal Scroll Nav Component + * Pill-style category buttons in a horizontal scroller + */ +class HorizontalScrollNav extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + this.categories = [ + { id: 'all', label: 'All', active: true }, + { id: 'fiction', label: 'Fiction', active: false }, + { id: 'non-fiction', label: 'Non-Fiction', active: false }, + { id: 'mystery', label: 'Mystery', active: false }, + { id: 'romance', label: 'Romance', active: false }, + { id: 'sci-fi', label: 'Sci-Fi', active: false }, + { id: 'biography', label: 'Biography', active: false }, + { id: 'history', label: 'History', active: false }, + ]; + } + + connectedCallback() { + this.render(); + this.addEventListeners(); + } + + addEventListeners() { + const buttons = this.shadowRoot.querySelectorAll('.nav-pill'); + buttons.forEach(button => { + button.addEventListener('click', (e) => { + this.setActiveCategory(e.target.dataset.id); + }); + }); + } + + setActiveCategory(id) { + this.categories = this.categories.map(cat => ({ + ...cat, + active: cat.id === id + })); + this.render(); + this.addEventListeners(); + + // Dispatch custom event for parent components + this.dispatchEvent(new CustomEvent('category-change', { + detail: { categoryId: id }, + bubbles: true, + composed: true + })); + } + + render() { + this.shadowRoot.innerHTML = ` + + + `; + } +} + +customElements.define('horizontal-scroll-nav', HorizontalScrollNav); diff --git a/js/components/search-bar.js b/js/components/search-bar.js new file mode 100644 index 0000000..e2a39fd --- /dev/null +++ b/js/components/search-bar.js @@ -0,0 +1,98 @@ +/** + * Search Bar Component + * Search input with icon + */ +class SearchBar extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + } + + connectedCallback() { + this.render(); + this.addEventListeners(); + } + + addEventListeners() { + const input = this.shadowRoot.querySelector('.search-input'); + const form = this.shadowRoot.querySelector('.search-form'); + + form.addEventListener('submit', (e) => { + e.preventDefault(); + this.dispatchEvent(new CustomEvent('search', { + detail: { query: input.value }, + bubbles: true, + composed: true + })); + }); + + input.addEventListener('input', (e) => { + this.dispatchEvent(new CustomEvent('search-input', { + detail: { query: e.target.value }, + bubbles: true, + composed: true + })); + }); + } + + render() { + this.shadowRoot.innerHTML = ` + + + `; + } +} + +customElements.define('search-bar', SearchBar); diff --git a/js/components/site-content.js b/js/components/site-content.js new file mode 100644 index 0000000..81ec2ca --- /dev/null +++ b/js/components/site-content.js @@ -0,0 +1,35 @@ +/** + * Site Content Component + * Main content area wrapper with slot for page content + */ +class SiteContent extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + } + + connectedCallback() { + this.render(); + } + + render() { + this.shadowRoot.innerHTML = ` + +
+ +
+ `; + } +} + +customElements.define('site-content', SiteContent); diff --git a/js/components/site-footer.js b/js/components/site-footer.js new file mode 100644 index 0000000..35cfae3 --- /dev/null +++ b/js/components/site-footer.js @@ -0,0 +1,111 @@ +/** + * Site Footer Component + * Footer with navigation links, social icons, and copyright + */ +class SiteFooter extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + } + + connectedCallback() { + this.render(); + } + + render() { + this.shadowRoot.innerHTML = ` + + + `; + } +} + +customElements.define('site-footer', SiteFooter); diff --git a/js/components/site-header.js b/js/components/site-header.js new file mode 100644 index 0000000..b30323d --- /dev/null +++ b/js/components/site-header.js @@ -0,0 +1,41 @@ +/** + * Site Header Component + * Sticky header container that holds top-bar, navigation, and search + */ +class SiteHeader extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + } + + connectedCallback() { + this.render(); + } + + render() { + this.shadowRoot.innerHTML = ` + +
+ +
+ `; + } +} + +customElements.define('site-header', SiteHeader); diff --git a/js/components/top-bar.js b/js/components/top-bar.js new file mode 100644 index 0000000..07ba20c --- /dev/null +++ b/js/components/top-bar.js @@ -0,0 +1,110 @@ +/** + * Top Bar Component + * Contains logo, menu icon, and cart icon + */ +class TopBar extends HTMLElement { + constructor() { + super(); + this.attachShadow({ mode: 'open' }); + } + + connectedCallback() { + this.render(); + } + + render() { + this.shadowRoot.innerHTML = ` + +
+ +
+ + +
+
+ `; + } +} + +customElements.define('top-bar', TopBar); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7ee550c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,891 @@ +{ + "name": "milinda-pitch", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "milinda-pitch", + "version": "1.0.0", + "dependencies": { + "serve": "^14.2.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@zeit/schemas": { + "version": "2.36.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.36.0.tgz", + "integrity": "sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg==" + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-align/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/boxen": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.0.0.tgz", + "integrity": "sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg==", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^7.0.0", + "chalk": "^5.0.1", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.0.1.tgz", + "integrity": "sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk-template": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", + "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "dependencies": { + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clipboardy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-3.0.0.tgz", + "integrity": "sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg==", + "dependencies": { + "arch": "^2.2.0", + "execa": "^5.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-port-reachable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", + "integrity": "sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dependencies": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", + "dependencies": { + "rc": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/serve": { + "version": "14.2.5", + "resolved": "https://registry.npmjs.org/serve/-/serve-14.2.5.tgz", + "integrity": "sha512-Qn/qMkzCcMFVPb60E/hQy+iRLpiU8PamOfOSYoAHmmF+fFFmpPpqa6Oci2iWYpTdOUM3VF+TINud7CfbQnsZbA==", + "dependencies": { + "@zeit/schemas": "2.36.0", + "ajv": "8.12.0", + "arg": "5.0.2", + "boxen": "7.0.0", + "chalk": "5.0.1", + "chalk-template": "0.4.0", + "clipboardy": "3.0.0", + "compression": "1.8.1", + "is-port-reachable": "4.0.0", + "serve-handler": "6.1.6", + "update-check": "1.5.4" + }, + "bin": { + "serve": "build/main.js" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/serve-handler": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", + "integrity": "sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "3.3.0", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-check": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.4.tgz", + "integrity": "sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ==", + "dependencies": { + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..f7d75b4 --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "milinda-pitch", + "version": "1.0.0", + "description": "BookStore - Discover and buy your next favorite book", + "scripts": { + "start": "serve -s . -l ${PORT:-3000}", + "serve": "serve -s . -l 3000" + }, + "dependencies": { + "serve": "^14.2.4" + }, + "engines": { + "node": ">=18.0.0" + } +}