import { html, LitElement } from "lit"; import { customElement, property, state } from "lit/decorators.js"; import { ancestorAttribute, onAssign, autoSubscribe, awaitConnectedAncestors, dispatchConnectedEvent, } from "@supersoniks/concorde/decorators"; import { PublisherManager, PublisherProxy, } from "@supersoniks/concorde/core/utils/PublisherProxy"; import { Objects } from "@supersoniks/concorde/utils"; import { tailwind } from "../tailwind"; import "./decorators-demo-bind-demos"; import "./decorators-demo-subscribe-publish-get-demos"; @customElement("demo-ancestor-attribute") export class DemoAncestorAttribute extends LitElement { @ancestorAttribute("dataProvider") dataProvider: string | null = null; @ancestorAttribute("testAttribute") testAttribute: string | null = null; render() { return html`

DataProvider property initialized from ancestor: ${this.dataProvider || "null"}

TestAttribute property initialized from ancestor: ${this.testAttribute || "null"}

`; } } @customElement("demo-on-assign") export class DemoOnAssign extends LitElement { static styles = [tailwind]; @state() userWithSettings: any = null; @state() isReady: boolean = false; @state() lastUpdate: string = ""; @onAssign("demoUser", "demoUserSettings") handleDataReady(user: any, settings: any) { this.isReady = Object.keys(user).length > 0 && Object.keys(settings).length > 0; this.userWithSettings = { ...user, ...settings }; this.lastUpdate = new Date().toLocaleTimeString(); this.requestUpdate(); } render() { const { name, email, theme, language } = this.userWithSettings; return html`
Update Data
${this.isReady === false ? html`

No settings yet...

` : html`

${name || "N/A"}

${email || "N/A"}

${theme || "N/A"}

${language || "N/A"}

Last updated: ${this.lastUpdate}

`}
`; } updateData() { const user = PublisherManager.get("demoUser"); const userSettings = PublisherManager.get("demoUserSettings"); const userNumber = Math.floor(Math.random() * 100); user.set({ name: `User n°${userNumber}`, email: `user-${userNumber}@example.com`, }); userSettings.set({ theme: ["light", "dark", "auto"][Math.floor(Math.random() * 3)], language: ["en", "fr", "es"][Math.floor(Math.random() * 3)], }); } } @customElement("demo-on-assign-dynamic") export class DemoOnAssignDynamic extends LitElement { static styles = [tailwind]; @property({ type: String }) dataProvider: "demoUsers" | "demoUsersAlt" = "demoUsers"; @property({ type: Number }) userIndex: number = 0; @state() user: any = null; @state() userSettings: any = null; @onAssign( "${dataProvider}.${userIndex}", "${dataProvider}Settings.${userIndex}", ) handleUserDataReady(user: any, settings: any) { this.user = user; this.userSettings = settings; } updateUserIndex(e: Event) { this.userIndex = parseInt((e.target as HTMLInputElement).value); } updateDataProvider(e: Event) { this.dataProvider = (e.target as HTMLSelectElement).value as | "demoUsers" | "demoUsersAlt"; } updateCurrentUserData() { const usersPublisher = PublisherManager.get(this.dataProvider); const settingsPublisher = PublisherManager.get( `${this.dataProvider}Settings`, ); const userPublisher = Objects.traverse(usersPublisher, [ String(this.userIndex), ]) as PublisherProxy; const settingPublisher = Objects.traverse(settingsPublisher, [ String(this.userIndex), ]) as PublisherProxy; if (userPublisher && settingPublisher) { const randomNames = [ { firstName: "Alice", lastName: "Wonder" }, { firstName: "Bob", lastName: "Builder" }, { firstName: "Charlie", lastName: "Chaplin" }, { firstName: "Diana", lastName: "Prince" }, { firstName: "Eve", lastName: "Adams" }, ]; const randomThemes = ["light", "dark", "auto"]; const randomLanguages = ["en", "fr", "es", "de", "it"]; const randomName = randomNames[Math.floor(Math.random() * randomNames.length)]; const randomEmail = `${randomName.firstName.toLowerCase()}.${randomName.lastName.toLowerCase()}@example.com`; const randomTheme = randomThemes[Math.floor(Math.random() * randomThemes.length)]; const randomLanguage = randomLanguages[Math.floor(Math.random() * randomLanguages.length)]; const currentUser = userPublisher.get() || {}; userPublisher.set({ ...currentUser, firstName: randomName.firstName, lastName: randomName.lastName, email: randomEmail, }); settingPublisher.set({ theme: randomTheme, language: randomLanguage, }); } } render() { return html`
Update current user data
${this.user?.firstName} ${this.user?.lastName}
${this.user?.email}
Theme: ${this.userSettings?.theme} | Language: ${this.userSettings?.language}
`; } } @customElement("demo-auto-subscribe") export class DemoAutoSubscribe extends LitElement { static styles = [tailwind]; @state() displayText: string = ""; @state() computedValue: number = 0; @autoSubscribe() updateDisplay() { const value1 = PublisherManager.get("autoValue1").get() || 0; const value2 = PublisherManager.get("autoValue2").get() || 0; this.computedValue = value1 + value2; this.displayText = `${value1} + ${value2} = ${this.computedValue}`; } render() { return html`

${this.displayText}

this.randomizeValue("autoValue1")}> Randomize Value 1 this.randomizeValue("autoValue2")}> Randomize Value 2
`; } randomizeValue(publisherId: string) { const value = PublisherManager.get(publisherId); value.set(Math.floor(Math.random() * 100)); } } @dispatchConnectedEvent() export class DemoWaitAncestorContainer extends LitElement { render() { return html``; } } @customElement("demo-wait-ancestor-value") @awaitConnectedAncestors("demo-wait-ancestor-container[dataProvider]") export class DemoWaitAncestorValue extends LitElement { @ancestorAttribute("dataProvider") dataProvider: string | null = null; @state() initializedAt = ""; connectedCallback() { super.connectedCallback(); this.initializedAt = new Date().toISOString(); } render() { return html`

DataProvider from ancestor: ${this.dataProvider || "—"}

Initialized at: ${this.initializedAt || "(waiting for parent…)"}

`; } } @customElement("demo-wait-ancestors-section") export class DemoWaitAncestorsSection extends LitElement { static styles = [tailwind]; @state() parentRegistered = false; registerParent() { if (customElements.get("demo-wait-ancestor-container")) { this.parentRegistered = true; return; } customElements.define( "demo-wait-ancestor-container", DemoWaitAncestorContainer, ); this.parentRegistered = true; } render() { return html`
${this.parentRegistered ? "Parent already registered" : "Register parent component"}
`; } } @dispatchConnectedEvent() export class DemoWaitAncestorOuter extends LitElement { render() { return html``; } } @dispatchConnectedEvent() export class DemoWaitAncestorInner extends LitElement { render() { return html``; } } @customElement("demo-wait-ancestor-value-multi") @awaitConnectedAncestors("demo-wait-ancestor-outer", "demo-wait-ancestor-inner") export class DemoWaitAncestorValueMulti extends LitElement { @ancestorAttribute("dataProvider") dataProvider: string | null = null; @state() initializedAt = ""; connectedCallback() { super.connectedCallback(); this.initializedAt = new Date().toISOString(); } render() { return html`

DataProvider from ancestor: ${this.dataProvider || "—"}

Initialized at: ${this.initializedAt || "(waiting for both ancestors…)"}

`; } } @customElement("demo-wait-ancestors-multi-section") export class DemoWaitAncestorsMultiSection extends LitElement { static styles = [tailwind]; @state() outerRegistered = false; @state() innerRegistered = false; registerOuter() { if (!customElements.get("demo-wait-ancestor-outer")) { customElements.define("demo-wait-ancestor-outer", DemoWaitAncestorOuter); } this.outerRegistered = true; } registerInner() { if (!customElements.get("demo-wait-ancestor-inner")) { customElements.define("demo-wait-ancestor-inner", DemoWaitAncestorInner); } this.innerRegistered = true; } render() { return html`
${this.outerRegistered ? "Outer registered" : "Register outer"} ${this.innerRegistered ? "Inner registered" : "Register inner"}
`; } } @customElement("demo-wait-ancestor-ready") @dispatchConnectedEvent() export class DemoWaitAncestorReady extends LitElement { render() { return html``; } } @customElement("demo-wait-ancestor-value-ready") @awaitConnectedAncestors("demo-wait-ancestor-ready") export class DemoWaitAncestorValueReady extends LitElement { @ancestorAttribute("dataProvider") dataProvider: string | null = null; @state() initializedAt = ""; connectedCallback() { super.connectedCallback(); this.initializedAt = new Date().toISOString(); } render() { return html`

DataProvider: ${this.dataProvider || "—"}

Initialized at: ${this.initializedAt}

`; } } @customElement("demo-wait-ancestors-ready-section") export class DemoWaitAncestorsReadySection extends LitElement { static styles = [tailwind]; @state() childInDom = false; addChild() { this.childInDom = true; } render() { return html`

Parent défini au chargement. Ajout dynamique de l’enfant — initialisation immédiate si l’ancêtre est prêt.

${this.childInDom ? "Child added" : "Add child dynamically"} ${this.childInDom ? html`` : html``}
`; } } @customElement("demo-wait-ancestors-static-section") export class DemoWaitAncestorsStaticSection extends LitElement { static styles = [tailwind]; render() { return html`

Parent et enfant présents dès le chargement — pas de délai.

`; } }