diff --git a/README.md b/README.md index be0c35ae..5800b26d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - # Joist **Sponsored by:** diff --git a/package-lock.json b/package-lock.json index ac418ca3..fcc39e03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { "name": "joist", - "version": "4.0.0-next.41", + "version": "4.0.0-next.42", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "joist", - "version": "4.0.0-next.41", + "version": "4.0.0-next.42", "license": "MIT", "workspaces": [ "packages/**", - "integration/**" + "integration/**", + "website" ], "devDependencies": { "@types/chai": "^5.0.0", @@ -669,6 +670,10 @@ "resolved": "packages/ssr", "link": true }, + "node_modules/@joist/website": { + "resolved": "website", + "link": true + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -1151,7 +1156,8 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/cookies": { "version": "0.9.0", @@ -1170,6 +1176,7 @@ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -1867,6 +1874,7 @@ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", "dev": true, + "license": "MIT", "engines": { "node": "^4.5.0 || >= 5.9" } @@ -2671,6 +2679,7 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2693,6 +2702,7 @@ "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "dev": true, + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -3085,6 +3095,7 @@ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", "dev": true, + "license": "MIT", "dependencies": { "@types/cookie": "^0.4.1", "@types/cors": "^2.8.12", @@ -3149,6 +3160,7 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, @@ -5639,6 +5651,7 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -6878,6 +6891,7 @@ "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.8.1.tgz", "integrity": "sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg==", "dev": true, + "license": "MIT", "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", @@ -7990,22 +8004,22 @@ }, "packages/di": { "name": "@joist/di", - "version": "4.0.0-next.40", + "version": "4.0.0-next.42", "license": "MIT" }, "packages/element": { "name": "@joist/element", - "version": "4.0.0-next.40", + "version": "4.0.0-next.42", "license": "MIT" }, "packages/observable": { "name": "@joist/observable", - "version": "4.0.0-next.40", + "version": "4.0.0-next.42", "license": "MIT" }, "packages/plugin-vite": { "name": "@joist/plugin-vite", - "version": "4.0.0-next.40", + "version": "4.0.0-next.42", "license": "MIT", "devDependencies": { "vite": "^6.0.0" @@ -8013,11 +8027,134 @@ }, "packages/ssr": { "name": "@joist/ssr", - "version": "4.0.0-next.40", + "version": "4.0.0-next.42", "license": "MIT", "dependencies": { "cheerio": "^1.0.0-rc.12" } + }, + "website": { + "name": "@joist/website", + "devDependencies": { + "vite": "6.0.0-beta.2" + } + }, + "website/node_modules/@esbuild/linux-x64": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz", + "integrity": "sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "website/node_modules/esbuild": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz", + "integrity": "sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.24.0", + "@esbuild/android-arm": "0.24.0", + "@esbuild/android-arm64": "0.24.0", + "@esbuild/android-x64": "0.24.0", + "@esbuild/darwin-arm64": "0.24.0", + "@esbuild/darwin-x64": "0.24.0", + "@esbuild/freebsd-arm64": "0.24.0", + "@esbuild/freebsd-x64": "0.24.0", + "@esbuild/linux-arm": "0.24.0", + "@esbuild/linux-arm64": "0.24.0", + "@esbuild/linux-ia32": "0.24.0", + "@esbuild/linux-loong64": "0.24.0", + "@esbuild/linux-mips64el": "0.24.0", + "@esbuild/linux-ppc64": "0.24.0", + "@esbuild/linux-riscv64": "0.24.0", + "@esbuild/linux-s390x": "0.24.0", + "@esbuild/linux-x64": "0.24.0", + "@esbuild/netbsd-x64": "0.24.0", + "@esbuild/openbsd-arm64": "0.24.0", + "@esbuild/openbsd-x64": "0.24.0", + "@esbuild/sunos-x64": "0.24.0", + "@esbuild/win32-arm64": "0.24.0", + "@esbuild/win32-ia32": "0.24.0", + "@esbuild/win32-x64": "0.24.0" + } + }, + "website/node_modules/vite": { + "version": "6.0.0-beta.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.0-beta.2.tgz", + "integrity": "sha512-TdrjEhCnVNjT3kjohFhVJQL9V3SguxMAphP2RW085QbE0Xc+lRvql9l5hTIr/mttO2jhivYXEP4xfaIRPjzqiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.24.0", + "postcss": "^8.4.47", + "rollup": "^4.22.5" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } } } } diff --git a/package.json b/package.json index 5684a65f..1b22ecbe 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,14 @@ { "name": "joist", - "version": "4.0.0-next.41", + "version": "4.0.0-next.42", "description": "", "type": "module", - "author": "", + "author": "deebloo", "license": "MIT", "workspaces": [ "packages/**", - "integration/**" + "integration/**", + "website" ], "scripts": { "prepare": "husky" diff --git a/packages/di/package.json b/packages/di/package.json index 7cc19ab7..ff15255c 100644 --- a/packages/di/package.json +++ b/packages/di/package.json @@ -1,6 +1,6 @@ { "name": "@joist/di", - "version": "4.0.0-next.40", + "version": "4.0.0-next.42", "type": "module", "main": "./target/lib.js", "module": "./target/lib.js", diff --git a/packages/di/src/lib/dom-injector.test.ts b/packages/di/src/lib/dom-injector.test.ts index 38ca9c17..abdfe3e4 100644 --- a/packages/di/src/lib/dom-injector.test.ts +++ b/packages/di/src/lib/dom-injector.test.ts @@ -1,4 +1,5 @@ import { assert } from 'chai'; + import { DOMInjector } from './dom-injector.js'; import { INJECTOR_CTX } from './context/injector.js'; import { Injector } from './injector.js'; @@ -29,20 +30,23 @@ describe('DOMInjector', () => { it('should send request looking for other injector contexts', () => { const parent = new Injector(); const injector = new DOMInjector(); - - const cb = (e: any) => { - if (e.context === INJECTOR_CTX) { - e.callback(parent); - } - }; - - document.body.addEventListener('context-request', cb); + const controller = new AbortController(); + + document.body.addEventListener( + 'context-request', + (e: any) => { + if (e.context === INJECTOR_CTX) { + e.callback(parent); + } + }, + { signal: controller.signal } + ); injector.attach(document.body); assert.equal(injector.parent, parent); injector.detach(); - document.body.removeEventListener('context-request', cb); + controller.abort(); }); }); diff --git a/packages/di/src/lib/dom-injector.ts b/packages/di/src/lib/dom-injector.ts index c24ae62e..2e0d17a2 100644 --- a/packages/di/src/lib/dom-injector.ts +++ b/packages/di/src/lib/dom-injector.ts @@ -1,35 +1,39 @@ -import { ContextRequestEvent } from './context/protocol.js'; +import { ContextRequestEvent, UnknownContext } from './context/protocol.js'; import { INJECTOR_CTX } from './context/injector.js'; import { Injector } from './injector.js'; export class DOMInjector extends Injector { - #contextCallback = (e: ContextRequestEvent<{ __context__: unknown }>) => { - if (e.context === INJECTOR_CTX) { - if (e.target !== this.#element) { - e.stopPropagation(); - - e.callback(this); - } - } - }; - #element: HTMLElement | null = null; + #controller: AbortController | null = null; attach(element: HTMLElement): void { this.#element = element; + this.#controller = new AbortController(); - this.#element.addEventListener('context-request', this.#contextCallback); + this.#element.addEventListener( + 'context-request', + (e: ContextRequestEvent) => { + if (e.context === INJECTOR_CTX) { + if (e.target !== this.#element) { + e.stopPropagation(); + + e.callback(this); + } + } + }, + { signal: this.#controller.signal } + ); this.#element.dispatchEvent( new ContextRequestEvent(INJECTOR_CTX, (parent) => { - this.setParent(parent); + this.parent = parent; }) ); } detach(): void { - if (this.#element) { - this.#element.removeEventListener('context-request', this.#contextCallback); + if (this.#controller) { + this.#controller.abort(); } } } diff --git a/packages/di/src/lib/injectable-el.ts b/packages/di/src/lib/injectable-el.ts index 14c7e615..7715c84e 100644 --- a/packages/di/src/lib/injectable-el.ts +++ b/packages/di/src/lib/injectable-el.ts @@ -18,17 +18,15 @@ export function injectableEl>( const injector = injectables.get(this); - this.addEventListener('context-request', (e) => { - if (e.target !== this && e.context === INJECTOR_CTX) { - e.stopPropagation(); + if (injector) { + this.addEventListener('context-request', (e) => { + if (e.target !== this && e.context === INJECTOR_CTX) { + e.stopPropagation(); - if (injector) { e.callback(injector); } - } - }); + }); - if (injector) { callLifecycle(this, injector, metadata?.onCreated); } } @@ -36,15 +34,13 @@ export function injectableEl>( connectedCallback() { const injector = injectables.get(this); - this.dispatchEvent( - new ContextRequestEvent(INJECTOR_CTX, (parent) => { - if (injector) { - injector.setParent(parent); - } - }) - ); - if (injector) { + this.dispatchEvent( + new ContextRequestEvent(INJECTOR_CTX, (ctx) => { + injector.parent = ctx; + }) + ); + callLifecycle(this, injector, metadata?.onInjected); } @@ -54,7 +50,11 @@ export function injectableEl>( } disconnectedCallback() { - injectables.get(this)?.setParent(undefined); + const i = injectables.get(this); + + if (i) { + delete i.parent; + } if (super.disconnectedCallback) { super.disconnectedCallback(); diff --git a/packages/di/src/lib/injector.ts b/packages/di/src/lib/injector.ts index 1bf48332..0a4b43bb 100644 --- a/packages/di/src/lib/injector.ts +++ b/packages/di/src/lib/injector.ts @@ -89,10 +89,6 @@ export class Injector { return this.#createAndCache(token, () => new token()); } - setParent(parent: Injector | undefined): void { - this.parent = parent; - } - clear(): void { this.#instances = new WeakMap(); } @@ -115,7 +111,7 @@ export class Injector { * this means that each calling injector will be the parent of what it creates. * this allows the created service to navigate up it's chain to find a root */ - injector.setParent(this); + injector.parent = this; } /** diff --git a/packages/di/src/lib/lifecycle.ts b/packages/di/src/lib/lifecycle.ts index a91b26c9..34a03eda 100644 --- a/packages/di/src/lib/lifecycle.ts +++ b/packages/di/src/lib/lifecycle.ts @@ -1,5 +1,3 @@ -(Symbol as any).metadata ??= Symbol('Symbol.metadata'); - import { Injector } from './injector.js'; import { InjectableMetadata, LifecycleCallback } from './metadata.js'; @@ -9,8 +7,8 @@ export function injected() { ctx: ClassMethodDecoratorContext ): void { const metadata: InjectableMetadata = ctx.metadata; - metadata.onInjected ??= []; - metadata.onInjected.push(val); + metadata.onInjected ??= new Set(); + metadata.onInjected.add(val); }; } @@ -20,12 +18,16 @@ export function created() { ctx: ClassMethodDecoratorContext ): void { const metadata: InjectableMetadata = ctx.metadata; - metadata.onCreated ??= []; - metadata.onCreated.push(val); + metadata.onCreated ??= new Set(); + metadata.onCreated.add(val); }; } -export function callLifecycle(instance: object, i: Injector, methods?: LifecycleCallback[]): void { +export function callLifecycle( + instance: object, + i: Injector, + methods?: Set +): void { if (methods) { for (let cb of methods) { cb.call(instance, i); diff --git a/packages/di/src/lib/metadata.ts b/packages/di/src/lib/metadata.ts index 07eea67a..f6cba970 100644 --- a/packages/di/src/lib/metadata.ts +++ b/packages/di/src/lib/metadata.ts @@ -1,11 +1,13 @@ +(Symbol as any).metadata ??= Symbol('Symbol.metadata'); + import { Injector } from './injector.js'; import { InjectionToken } from './provider.js'; export type LifecycleCallback = (i: Injector) => void; export interface InjectableMetadata { - onCreated?: LifecycleCallback[]; - onInjected?: LifecycleCallback[]; + onCreated?: Set; + onInjected?: Set; } export function readMetadata(target: InjectionToken): InjectableMetadata | null { diff --git a/packages/di/src/lib/provider.ts b/packages/di/src/lib/provider.ts index b56ca832..47f3a703 100644 --- a/packages/di/src/lib/provider.ts +++ b/packages/di/src/lib/provider.ts @@ -6,7 +6,7 @@ export class StaticToken { #name: string; #factory?: ProviderFactory; - [Symbol.metadata] = {}; + [Symbol.metadata] = null; get name(): string { return this.#name; diff --git a/packages/element/package.json b/packages/element/package.json index 197bb76f..664c9686 100644 --- a/packages/element/package.json +++ b/packages/element/package.json @@ -1,6 +1,6 @@ { "name": "@joist/element", - "version": "4.0.0-next.40", + "version": "4.0.0-next.42", "type": "module", "main": "./target/lib.js", "module": "./target/lib.js", diff --git a/packages/element/src/lib/element.ts b/packages/element/src/lib/element.ts index 65626b0a..32e3b1e0 100644 --- a/packages/element/src/lib/element.ts +++ b/packages/element/src/lib/element.ts @@ -27,7 +27,7 @@ export function element(opts?: ElementOpts) { [Base.name]: class extends Base { static observedAttributes: string[] = Array.from(meta.attrs.keys()); - #removeListeners: Set = new Set(); + #abortController: AbortController | null = null; constructor(...args: any[]) { super(...args); @@ -73,8 +73,10 @@ export function element(opts?: ElementOpts) { } } - if (super.attributeChangedCallback) { - super.attributeChangedCallback(name, oldValue, newValue); + if (attr.observe) { + if (super.attributeChangedCallback) { + super.attributeChangedCallback(name, oldValue, newValue); + } } } } @@ -85,12 +87,10 @@ export function element(opts?: ElementOpts) { const root = selector(this); if (root) { - const thisCb = cb.bind(this); - - root.addEventListener(event, thisCb); + this.#abortController = new AbortController(); - this.#removeListeners.add(() => { - root.removeEventListener(event, thisCb); + root.addEventListener(event, cb.bind(this), { + signal: this.#abortController.signal }); } else { throw new Error(`could not add listener to ${root}`); @@ -106,8 +106,9 @@ export function element(opts?: ElementOpts) { } disconnectedCallback(): void { - for (let remove of this.#removeListeners) { - remove(); + if (this.#abortController) { + this.#abortController.abort(); + this.#abortController = null; } if (super.disconnectedCallback) { diff --git a/packages/observable/package.json b/packages/observable/package.json index c643d88e..fa1d5ec2 100644 --- a/packages/observable/package.json +++ b/packages/observable/package.json @@ -1,6 +1,6 @@ { "name": "@joist/observable", - "version": "4.0.0-next.40", + "version": "4.0.0-next.42", "type": "module", "main": "./target/lib.js", "module": "./target/lib.js", diff --git a/packages/plugin-vite/package.json b/packages/plugin-vite/package.json index aeaa08e8..1a59266d 100644 --- a/packages/plugin-vite/package.json +++ b/packages/plugin-vite/package.json @@ -1,6 +1,6 @@ { "name": "@joist/plugin-vite", - "version": "4.0.0-next.40", + "version": "4.0.0-next.42", "type": "module", "main": "./target/lib.js", "module": "./target/lib.js", diff --git a/packages/ssr/README.md b/packages/ssr/README.md index 58d96628..10191506 100644 --- a/packages/ssr/README.md +++ b/packages/ssr/README.md @@ -21,7 +21,7 @@ applicator.apply(document, []) ## Vite ```TS -import { Applicator. NoopTemplateCache, FileSysTemplateLoader } from '@joist/ssr'; +import { Applicator, NoopTemplateCache, FileSysTemplateLoader } from '@joist/ssr'; import { defineConfig } from 'vite'; const applicator = new Applicator( @@ -35,13 +35,24 @@ const applicator = new Applicator( export default defineConfig({ plugins: [ { + name: 'Web Component SSR', transformIndexHtml: { - enforce: "pre", - transform(html) { - return applicator.apply(html, ['my-element', 'my-dropdown']); + order: 'pre', + handler(html) { + return applicator.apply(html, ['joist-header', 'joist-nav']); + } + }, + handleHotUpdate({ file, server }) { + if (file.includes('elements') && (file.endsWith('.html') || file.endsWith('.css'))) { + console.log(`${file} updated...`); + + server.ws.send({ + type: 'full-reload', + path: '*' + }); } } } - ], + ] }); ``` diff --git a/packages/ssr/package.json b/packages/ssr/package.json index 05109858..935f7ed7 100644 --- a/packages/ssr/package.json +++ b/packages/ssr/package.json @@ -1,6 +1,6 @@ { "name": "@joist/ssr", - "version": "4.0.0-next.40", + "version": "4.0.0-next.42", "type": "module", "main": "./target/lib.js", "module": "./target/lib.js", diff --git a/website/index.html b/website/index.html new file mode 100644 index 00000000..01f79bf9 --- /dev/null +++ b/website/index.html @@ -0,0 +1,48 @@ + + + + + + Document + + + + + + + + + + +
+

Hello World

+ +

Welcome to Joist

+
+
+ + + + + + diff --git a/website/package.json b/website/package.json new file mode 100644 index 00000000..d69ce771 --- /dev/null +++ b/website/package.json @@ -0,0 +1,12 @@ +{ + "name": "@joist/website", + "type": "module", + "scripts": { + "start": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "devDependencies": { + "vite": "6.0.0-beta.2" + } +} diff --git a/website/src/elements/joist-header/joist-header.css b/website/src/elements/joist-header/joist-header.css new file mode 100644 index 00000000..9fc1b875 --- /dev/null +++ b/website/src/elements/joist-header/joist-header.css @@ -0,0 +1,8 @@ +:host { + display: contents; +} + +header { + padding: 1rem; + background: blue; +} diff --git a/website/src/elements/joist-header/joist-header.html b/website/src/elements/joist-header/joist-header.html new file mode 100644 index 00000000..32442ee0 --- /dev/null +++ b/website/src/elements/joist-header/joist-header.html @@ -0,0 +1 @@ +
Joist
diff --git a/website/src/elements/joist-header/joist-header.ts b/website/src/elements/joist-header/joist-header.ts new file mode 100644 index 00000000..395c450b --- /dev/null +++ b/website/src/elements/joist-header/joist-header.ts @@ -0,0 +1,8 @@ +import { element } from '@joist/element'; + +@element({ + tagName: 'joist-header' +}) +class JoistHeaderElement extends HTMLElement {} + +export { JoistHeaderElement }; diff --git a/website/src/elements/joist-main/joist-main.css b/website/src/elements/joist-main/joist-main.css new file mode 100644 index 00000000..04525cb5 --- /dev/null +++ b/website/src/elements/joist-main/joist-main.css @@ -0,0 +1,11 @@ +:host { + display: flex; +} + +#nav { + display: block; +} + +#main { + display: block; +} diff --git a/website/src/elements/joist-main/joist-main.html b/website/src/elements/joist-main/joist-main.html new file mode 100644 index 00000000..5416026b --- /dev/null +++ b/website/src/elements/joist-main/joist-main.html @@ -0,0 +1,3 @@ + + + diff --git a/website/src/elements/joist-main/joist-main.ts b/website/src/elements/joist-main/joist-main.ts new file mode 100644 index 00000000..7fe1b205 --- /dev/null +++ b/website/src/elements/joist-main/joist-main.ts @@ -0,0 +1,8 @@ +import { element } from '@joist/element'; + +@element({ + tagName: 'joist-main' +}) +class JoistMainElement extends HTMLElement {} + +export { JoistMainElement }; diff --git a/website/src/elements/joist-nav/joist-nav.css b/website/src/elements/joist-nav/joist-nav.css new file mode 100644 index 00000000..0bdda21f --- /dev/null +++ b/website/src/elements/joist-nav/joist-nav.css @@ -0,0 +1,9 @@ +:host { + display: contents; +} + +nav { + display: flex; + flex-direction: column; + padding: 1rem; +} diff --git a/website/src/elements/joist-nav/joist-nav.html b/website/src/elements/joist-nav/joist-nav.html new file mode 100644 index 00000000..bd29a2e8 --- /dev/null +++ b/website/src/elements/joist-nav/joist-nav.html @@ -0,0 +1,4 @@ + diff --git a/website/src/elements/joist-nav/joist-nav.ts b/website/src/elements/joist-nav/joist-nav.ts new file mode 100644 index 00000000..762587d6 --- /dev/null +++ b/website/src/elements/joist-nav/joist-nav.ts @@ -0,0 +1,12 @@ +import { element } from '@joist/element'; + +@element({ + tagName: 'joist-nav' +}) +class JoistNavElement extends HTMLElement { + connectedCallback(): void { + alert('test'); + } +} + +export { JoistNavElement }; diff --git a/website/src/vite-env.d.ts b/website/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/website/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/website/tsconfig.json b/website/tsconfig.json new file mode 100644 index 00000000..0511b9f0 --- /dev/null +++ b/website/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/website/vite.config.js b/website/vite.config.js new file mode 100644 index 00000000..ac1965cf --- /dev/null +++ b/website/vite.config.js @@ -0,0 +1,20 @@ +import { Applicator, NoopTemplateCache, FileSysTemplateLoader } from '@joist/ssr'; +import joist from '@joist/plugin-vite'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + esbuild: { + target: 'es2020' + }, + plugins: [ + joist( + new Applicator( + new NoopTemplateCache(), + new FileSysTemplateLoader( + (tag) => `./src/elements/${tag}/${tag}.html`, + (tag) => `./src/elements/${tag}/${tag}.css` + ) + ) + ) + ] +});