@wippy-fe/webcomponent-core 0.0.37 → 0.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +7 -0
- package/dist/index.js +20 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -292,6 +292,8 @@ declare abstract class WippyElement<Props = Record<string, unknown>, Events = Re
|
|
|
292
292
|
private _lastProps;
|
|
293
293
|
private _lastErrors;
|
|
294
294
|
private _lastContent;
|
|
295
|
+
/** Unsubscribe from host `@theme` broadcasts; set on connect, cleared on disconnect. */
|
|
296
|
+
private _themeUnsub;
|
|
295
297
|
/**
|
|
296
298
|
* Phantom field to retain the `Events` type parameter so it shows up in
|
|
297
299
|
* type errors / `Reflect.get` shape. Adapter typing reads it indirectly
|
|
@@ -356,6 +358,11 @@ declare abstract class WippyElement<Props = Record<string, unknown>, Events = Re
|
|
|
356
358
|
*/
|
|
357
359
|
protected get reactive(): ReactiveAdapter<Props, Events>;
|
|
358
360
|
connectedCallback(): void;
|
|
361
|
+
/**
|
|
362
|
+
* Applies the host's current forced theme mode to the shadow container.
|
|
363
|
+
* No-op if the proxy host doesn't expose `getThemeMode` (older proxy).
|
|
364
|
+
*/
|
|
365
|
+
private _applyThemeToContainer;
|
|
359
366
|
disconnectedCallback(): void;
|
|
360
367
|
attributeChangedCallback(_name: string, oldVal: string | null, newVal: string | null): void;
|
|
361
368
|
/** Called right after shadow DOM is attached, before CSS or container. */
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
4
4
|
|
|
5
5
|
// src/base-element.ts
|
|
6
6
|
import { addCollection } from "@iconify/vue";
|
|
7
|
-
import { addIcons, define } from "@wippy-fe/proxy";
|
|
7
|
+
import { addIcons, applyThemeMode, define, host as wippyHost, on as wippyOn } from "@wippy-fe/proxy";
|
|
8
8
|
|
|
9
9
|
// src/css-loader.ts
|
|
10
10
|
import { hostCss, loadCss } from "@wippy-fe/proxy";
|
|
@@ -239,6 +239,8 @@ var WippyElement = class extends HTMLElement {
|
|
|
239
239
|
__publicField(this, "_lastProps", null);
|
|
240
240
|
__publicField(this, "_lastErrors", []);
|
|
241
241
|
__publicField(this, "_lastContent", null);
|
|
242
|
+
/** Unsubscribe from host `@theme` broadcasts; set on connect, cleared on disconnect. */
|
|
243
|
+
__publicField(this, "_themeUnsub", null);
|
|
242
244
|
this._internals = this.attachInternals();
|
|
243
245
|
}
|
|
244
246
|
/**
|
|
@@ -366,6 +368,9 @@ var WippyElement = class extends HTMLElement {
|
|
|
366
368
|
} else {
|
|
367
369
|
container = this._container;
|
|
368
370
|
}
|
|
371
|
+
this._applyThemeToContainer();
|
|
372
|
+
if (!this._themeUnsub)
|
|
373
|
+
this._themeUnsub = wippyOn("@theme", (mode) => applyThemeMode(mode, this._container ?? void 0));
|
|
369
374
|
const { props, errors } = parseProps(this, config.propsSchema);
|
|
370
375
|
if (config.validateProps) {
|
|
371
376
|
errors.push(...config.validateProps(props));
|
|
@@ -407,7 +412,21 @@ var WippyElement = class extends HTMLElement {
|
|
|
407
412
|
});
|
|
408
413
|
}
|
|
409
414
|
}
|
|
415
|
+
/**
|
|
416
|
+
* Applies the host's current forced theme mode to the shadow container.
|
|
417
|
+
* No-op if the proxy host doesn't expose `getThemeMode` (older proxy).
|
|
418
|
+
*/
|
|
419
|
+
_applyThemeToContainer() {
|
|
420
|
+
if (!this._container)
|
|
421
|
+
return;
|
|
422
|
+
const mode = wippyHost.getThemeMode?.() ?? "auto";
|
|
423
|
+
applyThemeMode(mode, this._container);
|
|
424
|
+
}
|
|
410
425
|
disconnectedCallback() {
|
|
426
|
+
if (this._themeUnsub) {
|
|
427
|
+
this._themeUnsub();
|
|
428
|
+
this._themeUnsub = null;
|
|
429
|
+
}
|
|
411
430
|
if (this._contentObserver) {
|
|
412
431
|
this._contentObserver.disconnect();
|
|
413
432
|
this._contentObserver = null;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/base-element.ts","../src/css-loader.ts","../src/host-scope.ts","../src/prop-parser.ts","../src/reactive-adapter.ts","../src/host-bus.ts"],"sourcesContent":["import type { ReactiveAdapter } from './reactive-adapter.ts'\r\nimport type { WippyElementConfig } from './types.ts'\r\nimport { addCollection } from '@iconify/vue'\r\nimport { addIcons, define } from '@wippy-fe/proxy'\r\nimport { injectInlineCss, loadHostCss } from './css-loader.ts'\r\nimport { getWippyHost } from './host-scope.ts'\r\nimport { parseProps } from './prop-parser.ts'\r\nimport { ReactiveAdapterImpl } from './reactive-adapter.ts'\r\n\r\n/**\r\n * Abstract base class for Wippy web components.\r\n *\r\n * Generic over `Props` — the parsed prop object type. This types `onMount`,\r\n * `onPropsChanged`, and `validateProps`. Defaults to `Record<string, unknown>`.\r\n *\r\n * Lifecycle order (first connect):\r\n * 1. shadow DOM attached\r\n * 2. `onInit(shadow)` — hook for early shadow DOM customization\r\n * 3. inline CSS injected\r\n * 4. host CSS loading started (async, non-blocking)\r\n * 5. container div created and appended\r\n * 6. icons registered\r\n * 7. props parsed from attributes + custom validation\r\n * 8. `onMount(shadow, container, props, errors)` — framework setup\r\n * 9. internals state → ready\r\n * 10. `onReady()` — post-mount hook\r\n * 11. `load` event emitted\r\n *\r\n * On reconnect (move-style DOM op: detach → reattach), the shadow root\r\n * persists across the cycle, so steps 1, 3, 4, 5 (CSS injection +\r\n * container creation) are skipped to avoid duplicating `<style>` and\r\n * container `<div>` siblings inside the persistent shadow. The stored\r\n * container is reused and `onMount` is re-invoked with `isRemount = true`\r\n * so framework adapters can decide between fresh-mount and remount paths.\r\n *\r\n * On error: `onError(error)` → internals state → error → `error` event\r\n * On disconnect: `onUnmount()` → `unload` event → internals cleared.\r\n * Note: `disconnectedCallback` does NOT clear the shadow root or the\r\n * stored container — they're reused on reconnect.\r\n */\r\nexport abstract class WippyElement<\r\n Props = Record<string, unknown>,\r\n Events = Record<string, unknown>,\r\n> extends HTMLElement {\r\n private _internals!: ElementInternals\r\n private _contentObserver: MutationObserver | null = null\r\n /** True after the first successful connectedCallback completes. */\r\n private _initialized: boolean = false\r\n /** Container div created on first connect; reused on subsequent connects. */\r\n private _container: HTMLElement | null = null\r\n /**\r\n * Opt-in reactive adapter. Lazy-allocated on first `this.reactive`\r\n * access, disposed on `disconnectedCallback`, re-allocated on next\r\n * access after reconnect. Subclasses that never touch `this.reactive`\r\n * pay zero allocation cost — `notifyProps`/`notifyContent` short-circuit\r\n * on the null guard.\r\n */\r\n private _reactive: ReactiveAdapterImpl<Props, Events> | null = null\r\n /**\r\n * Cached results of the most recent `parseProps` + `validateProps`\r\n * pass. Set by `connectedCallback` and `attributeChangedCallback`.\r\n * Read by `get reactive()` to avoid re-parsing on lazy allocation —\r\n * means `validateProps` only ever runs once per attribute change,\r\n * even for consumers that touch `this.reactive` inside `onMount`.\r\n */\r\n private _lastProps: Props | null = null\r\n private _lastErrors: readonly string[] = []\r\n private _lastContent: string | null = null\r\n\r\n /**\r\n * Phantom field to retain the `Events` type parameter so it shows up in\r\n * type errors / `Reflect.get` shape. Adapter typing reads it indirectly\r\n * via the generic.\r\n * @internal\r\n */\r\n declare readonly _events: Events\r\n\r\n /**\r\n * Override to provide the component's configuration.\r\n * Must be static because `observedAttributes` reads it before construction.\r\n *\r\n * Specify the generic to get typed `validateProps`:\r\n * ```ts\r\n * static get wippyConfig(): WippyElementConfig<MyProps> { ... }\r\n * ```\r\n */\r\n static get wippyConfig(): WippyElementConfig {\r\n return { propsSchema: { properties: {} } }\r\n }\r\n\r\n /**\r\n * Derived from the props schema + any `extraObservedAttributes`.\r\n */\r\n static get observedAttributes(): string[] {\r\n const config = this.wippyConfig\r\n const schemaAttrs = Object.keys(config.propsSchema.properties)\r\n const extra = config.extraObservedAttributes ?? []\r\n return [...schemaAttrs, ...extra]\r\n }\r\n\r\n constructor() {\r\n super()\r\n this._internals = this.attachInternals()\r\n }\r\n\r\n /**\r\n * Panel-scoped `host` wrapper attached by the managed-layout shell's\r\n * content resolvers (`ComponentResolver` / `WebComponentPackageLoader`).\r\n *\r\n * Inside a managed-layout panel, this is a wrapper around the universal\r\n * `host` API where context-aware calls (`layout.broadcast / send / on`)\r\n * are routed through the panel-bound bus — so `sourcePanelId` is\r\n * attributed correctly without postMessage indirection. Layout\r\n * mutations and other host methods pass through unchanged.\r\n *\r\n * `null` outside a managed-layout context (compat shell, chat sidebar,\r\n * standalone playground). Subclass code that needs a host in those\r\n * cases can fall back to `import { host } from '@wippy-fe/proxy'`.\r\n */\r\n get host(): ReturnType<typeof getWippyHost> {\r\n return getWippyHost(this)\r\n }\r\n\r\n /**\r\n * Emit a CustomEvent that bubbles and crosses shadow DOM boundaries.\r\n */\r\n protected emitEvent(eventName: string, detail?: unknown): void {\r\n this.dispatchEvent(new CustomEvent(eventName, {\r\n bubbles: true,\r\n composed: true,\r\n detail,\r\n }))\r\n }\r\n\r\n /**\r\n * Opt-in reactive adapter — framework-agnostic. Subscribe to prop\r\n * changes, content changes, or emit typed events from a non-Vue\r\n * consumer without re-rolling reactivity.\r\n *\r\n * ```ts\r\n * class MyEl extends WippyElement<{ count: number }, { tick: { n: number } }> {\r\n * protected onMount() {\r\n * const ctrl = new AbortController()\r\n * this.reactive.props.subscribe(({ count }) => {\r\n * this.shadowRoot!.querySelector('.n')!.textContent = String(count)\r\n * }, { signal: ctrl.signal, immediate: true })\r\n * }\r\n * tick(n: number) { this.reactive.events.emit('tick', { n }) }\r\n * }\r\n * ```\r\n *\r\n * Allocation cost is zero unless this getter is touched. Disposed on\r\n * `disconnectedCallback`; a fresh adapter is allocated on the next\r\n * access after reconnect.\r\n */\r\n protected get reactive(): ReactiveAdapter<Props, Events> {\r\n if (!this._reactive) {\r\n const config = (this.constructor as typeof WippyElement).wippyConfig\r\n const hasContent = !!config.contentTemplate\r\n // Reuse the cached parse result from the most recent\r\n // `connectedCallback` / `attributeChangedCallback` whenever we\r\n // have one; otherwise fall back to a fresh parse (this happens\r\n // when `reactive` is touched before the element is ever\r\n // connected — rare but legal).\r\n let props: Props\r\n let errors: readonly string[]\r\n if (this._lastProps !== null) {\r\n props = this._lastProps\r\n errors = this._lastErrors\r\n }\r\n else {\r\n const parsed = parseProps(this, config.propsSchema)\r\n if (config.validateProps) {\r\n parsed.errors.push(...config.validateProps(parsed.props))\r\n }\r\n props = parsed.props as Props\r\n errors = parsed.errors\r\n this._lastProps = props\r\n this._lastErrors = errors\r\n }\r\n const content = hasContent\r\n ? (this._lastContent ?? this._extractContent(config.contentTemplate!))\r\n : null\r\n if (hasContent && this._lastContent === null)\r\n this._lastContent = content\r\n this._reactive = new ReactiveAdapterImpl<Props, Events>(\r\n { props, errors, content, hasContent },\r\n this.emitEvent.bind(this),\r\n )\r\n }\r\n return this._reactive\r\n }\r\n\r\n // ── Lifecycle ──────────────────────────────────────────────\r\n\r\n connectedCallback(): void {\r\n this._internals.states.add('loading')\r\n try {\r\n const config = (this.constructor as typeof WippyElement).wippyConfig\r\n const isRemount = this._initialized\r\n\r\n // 1. Shadow DOM (guard against reconnect — attachShadow throws if called twice)\r\n const shadow = this.shadowRoot ?? this.attachShadow({ mode: config.shadowMode ?? 'open' })\r\n\r\n let container: HTMLElement\r\n if (!isRemount) {\r\n // 2. Early hook — customize shadow before CSS/container\r\n this.onInit(shadow)\r\n\r\n // 3. Inline CSS\r\n if (config.inlineCss) {\r\n injectInlineCss(shadow, config.inlineCss)\r\n }\r\n\r\n // 4. Host CSS (async, non-blocking)\r\n if (config.hostCssKeys === undefined || config.hostCssKeys.length > 0) {\r\n loadHostCss(shadow, config.hostCssKeys)\r\n }\r\n\r\n // 5. Container\r\n container = document.createElement('div')\r\n const classes = config.containerClasses ?? []\r\n if (classes.length > 0) {\r\n container.classList.add(...classes)\r\n }\r\n shadow.appendChild(container)\r\n this._container = container\r\n\r\n // 6. Icons\r\n addIcons(addCollection)\r\n }\r\n else {\r\n // Reconnect path — reuse the existing shadow children + container.\r\n // Skip CSS/icon/container setup so we don't accumulate duplicate\r\n // `<style>` and container `<div>` siblings on every detach/reattach.\r\n // The framework adapter decides whether to remount on the existing\r\n // container or recreate its app instance.\r\n container = this._container!\r\n }\r\n\r\n // 7. Parse initial props + custom validation\r\n const { props, errors } = parseProps(this, config.propsSchema)\r\n if (config.validateProps) {\r\n errors.push(...config.validateProps(props))\r\n }\r\n const typedProps = props as Props\r\n // Cache so a lazy `get reactive()` call from inside `onMount`\r\n // doesn't re-parse / re-validate.\r\n this._lastProps = typedProps\r\n this._lastErrors = errors\r\n\r\n // 7b. Extract children content (if contentTemplate configured)\r\n let initialContent: string | null = null\r\n if (config.contentTemplate) {\r\n initialContent = this._extractContent(config.contentTemplate)\r\n this._lastContent = initialContent\r\n this._contentObserver = new MutationObserver(() => {\r\n const content = this._extractContent(config.contentTemplate!)\r\n this._lastContent = content\r\n // Fan out to the reactive adapter first so subclass overrides of\r\n // `onContentChanged` that read `this.reactive.content.value` see\r\n // the new value. No-op when the adapter hasn't been allocated.\r\n this._reactive?.notifyContent(content)\r\n this.onContentChanged(content)\r\n })\r\n this._contentObserver.observe(this, {\r\n childList: true,\r\n characterData: true,\r\n subtree: true,\r\n })\r\n }\r\n\r\n // 8. Framework mount (first time) or remount (reconnect)\r\n this.onMount(shadow, container, typedProps, errors, initialContent, isRemount)\r\n\r\n // 9. Ready\r\n this._internals.states.delete('loading')\r\n this._internals.states.add('ready')\r\n\r\n // First-connect bookkeeping after a clean mount.\r\n if (!isRemount) {\r\n this._initialized = true\r\n }\r\n\r\n // 10. Post-mount hook\r\n this.onReady()\r\n\r\n // 11. Emit load\r\n this.emitEvent('load')\r\n }\r\n catch (error) {\r\n this.onError(error)\r\n this._internals.states.delete('loading')\r\n this._internals.states.add('error')\r\n this.emitEvent('error', {\r\n message: error instanceof Error ? error.message : String(error),\r\n error,\r\n })\r\n }\r\n }\r\n\r\n disconnectedCallback(): void {\r\n if (this._contentObserver) {\r\n this._contentObserver.disconnect()\r\n this._contentObserver = null\r\n }\r\n this.onUnmount()\r\n this.emitEvent('unload')\r\n this._internals.states.clear()\r\n // Drop the reactive adapter so subscribers from this attachment are\r\n // cleared and a fresh adapter is allocated on the next `this.reactive`\r\n // access (i.e. after reconnect).\r\n this._reactive?.dispose()\r\n this._reactive = null\r\n // Clear cached parse state — `connectedCallback` re-populates on\r\n // reconnect; before then, a lazy `get reactive()` access should\r\n // re-parse from current attributes (rare path).\r\n this._lastProps = null\r\n this._lastErrors = []\r\n this._lastContent = null\r\n // Drop panel-context wires so a detached element held by a\r\n // consumer (or re-inserted into a different panel) doesn't carry\r\n // stale wires that would silently misattribute. The resolver\r\n // re-installs them on the next mount.\r\n delete (this as unknown as { __wippyHost?: unknown }).__wippyHost\r\n delete (this as unknown as { __wippyHostBus?: unknown }).__wippyHostBus\r\n }\r\n\r\n attributeChangedCallback(_name: string, oldVal: string | null, newVal: string | null): void {\r\n if (oldVal === newVal)\r\n return\r\n const config = (this.constructor as typeof WippyElement).wippyConfig\r\n const { props, errors } = parseProps(this, config.propsSchema)\r\n if (config.validateProps) {\r\n errors.push(...config.validateProps(props))\r\n }\r\n const typedProps = props as Props\r\n this._lastProps = typedProps\r\n this._lastErrors = errors\r\n // Fan out to the reactive adapter BEFORE the legacy hook so subclasses\r\n // that override `onPropsChanged` AND read `this.reactive.props.value`\r\n // inside it see consistent state. No-op when the adapter hasn't been\r\n // lazy-allocated.\r\n this._reactive?.notifyProps(typedProps, errors)\r\n this.onPropsChanged(typedProps, errors)\r\n }\r\n\r\n // ── Hooks ──────────────────────────────────────────────────\r\n\r\n /** Called right after shadow DOM is attached, before CSS or container. */\r\n protected onInit(_shadow: ShadowRoot): void {}\r\n\r\n /**\r\n * Called after shadow DOM, CSS, and container are ready. Mount your\r\n * framework here.\r\n *\r\n * Invoked on first connect AND on every subsequent reconnect (move-style\r\n * DOM op: detach → reattach). On reconnect the same `container` instance\r\n * is reused. Adapters that hold a framework app handle should either\r\n * detect `isRemount === true` and re-mount on the existing container, or\r\n * leave the previous app intact across the detach/reattach cycle.\r\n */\r\n protected abstract onMount(\r\n shadow: ShadowRoot,\r\n container: HTMLElement,\r\n initialProps: Props,\r\n initialErrors: string[],\r\n initialContent?: string | null,\r\n isRemount?: boolean,\r\n ): void\r\n\r\n /** Called after internals state is set to ready, before the `load` event. */\r\n protected onReady(): void {}\r\n\r\n /** Called when connectedCallback throws. Default logs to console. */\r\n protected onError(error: unknown): void {\r\n console.error(`${this.constructor.name} initialization failed:`, error)\r\n }\r\n\r\n /** Called during disconnectedCallback — clean up framework resources. */\r\n protected abstract onUnmount(): void\r\n\r\n /** Called when observed attributes change. Override to update framework state. */\r\n protected onPropsChanged(_props: Props, _errors: string[]): void {}\r\n\r\n /**\r\n * Extract text from a child `<template data-type=\"...\">` element.\r\n * Uses `.content.textContent` since `<template>` stores content in a DocumentFragment.\r\n */\r\n private _extractContent(dataType: string): string | null {\r\n const tpl = this.querySelector(`template[data-type=\"${dataType}\"]`) as HTMLTemplateElement | null\r\n return tpl?.content.textContent?.trim() ?? null\r\n }\r\n\r\n /** Called when child `<template>` content changes. Override to update framework state. */\r\n protected onContentChanged(_content: string | null): void {}\r\n}\r\n\r\nexport { define }\r\n","import type { HostCssKey } from './types.ts'\r\nimport { hostCss, loadCss } from '@wippy-fe/proxy'\r\n\r\nconst DEFAULT_HOST_CSS_KEYS: HostCssKey[] = [\r\n 'themeConfigUrl',\r\n 'primeVueCssUrl',\r\n 'markdownCssUrl',\r\n 'iframeCssUrl',\r\n]\r\n\r\n/**\r\n * Loads host CSS URLs into the shadow root as `<style>` elements.\r\n * Non-blocking — returns a promise but the component doesn't need to await it.\r\n */\r\nexport function loadHostCss(shadow: ShadowRoot, keys?: HostCssKey[]): Promise<void> {\r\n const cssKeys = keys ?? DEFAULT_HOST_CSS_KEYS\r\n // Filter out keys whose URL is missing (e.g. removed CSS like fontCssUrl).\r\n // Load each independently so one failure doesn't block the rest.\r\n const jobs = cssKeys.map(async (key) => {\r\n const url = hostCss[key]\r\n if (!url) {\r\n console.warn(`[wippy-fe/webcomponent-core] hostCss key \"${key}\" is undefined — skipping. Remove it from hostCssKeys if the CSS was removed.`)\r\n return null\r\n }\r\n try {\r\n return await loadCss(url)\r\n }\r\n catch (err) {\r\n console.warn(`[wippy-fe/webcomponent-core] Failed to load hostCss \"${key}\" (${url}):`, err)\r\n return null\r\n }\r\n })\r\n return Promise.all(jobs).then((cssChunks) => {\r\n for (const css of cssChunks) {\r\n if (!css)\r\n continue\r\n const style = document.createElement('style')\r\n style.textContent = css\r\n style.setAttribute('role', '@wippy-fe/host-css')\r\n shadow.appendChild(style)\r\n }\r\n })\r\n}\r\n\r\n/**\r\n * Injects inline CSS text into the shadow root.\r\n */\r\nexport function injectInlineCss(shadow: ShadowRoot, text: string): void {\r\n const style = document.createElement('style')\r\n style.textContent = text\r\n shadow.appendChild(style)\r\n}\r\n","/**\n * Element-attached host wrapper reader for web components mounted as\n * `kind: 'component'` panels in the gen-2-chat managed-layout shell.\n *\n * The host stamps a panel-scoped wrapper as `__wippyHost` on each\n * element BEFORE it is appended to the DOM (see the host's\n * `panel-context-wires.ts` and `host-scope.ts`). Consumer web\n * components read it back via `getWippyHost(this)` in\n * `connectedCallback` and onwards.\n *\n * The wrapper is **constructed by the host** — this package only\n * exposes the reader. Outside a managed-layout host (raw mounts,\n * compat shells, tests without the connector) the property is absent\n * and `getWippyHost` returns `null`.\n */\n\n/**\n * Read the panel-scoped host wrapper attached to an element by the\n * managed-layout shell's content resolvers. Returns `null` outside a\n * managed-layout host (or before the element is connected).\n *\n * Subclass authors of `WippyElement` / `WippyVueElement` access this\n * via `this.host` / `useHost()` and rarely need to call this directly.\n * The helper is exposed for raw `HTMLElement` consumers.\n */\nexport function getWippyHost<H = unknown>(el: HTMLElement): H | null {\n return ((el as unknown) as { __wippyHost?: H }).__wippyHost ?? null\n}\n","import type { WippyPropDefinition, WippyPropsSchema } from './types.ts'\r\n\r\nexport interface ParseResult {\r\n props: Record<string, unknown>\r\n errors: string[]\r\n}\r\n\r\n/**\r\n * Converts a kebab-case attribute name to camelCase.\r\n * `allowed-types` → `allowedTypes`\r\n */\r\nexport function attrToCamel(attr: string): string {\r\n return attr.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase())\r\n}\r\n\r\n/**\r\n * Parses a single attribute value according to its schema definition.\r\n */\r\nfunction parseValue(attr: string, raw: string, def: WippyPropDefinition): { value: unknown, error?: string } {\r\n switch (def.type) {\r\n case 'string':\r\n return { value: raw }\r\n\r\n case 'number': {\r\n const n = Number.parseFloat(raw)\r\n if (Number.isNaN(n))\r\n return { value: undefined, error: `Invalid ${attr}: expected a number` }\r\n return { value: n }\r\n }\r\n\r\n case 'integer': {\r\n const n = Number.parseInt(raw, 10)\r\n if (Number.isNaN(n))\r\n return { value: undefined, error: `Invalid ${attr}: expected an integer` }\r\n return { value: n }\r\n }\r\n\r\n case 'boolean':\r\n // Presence of the attribute means true (HTML convention), explicit \"false\" means false\r\n return { value: raw !== 'false' }\r\n\r\n case 'array':\r\n case 'object': {\r\n try {\r\n const parsed = JSON.parse(raw)\r\n if (def.type === 'array' && !Array.isArray(parsed)) {\r\n return { value: undefined, error: `Invalid ${attr}: expected a JSON array` }\r\n }\r\n return { value: parsed }\r\n }\r\n catch {\r\n return { value: undefined, error: `Invalid ${attr}: must be valid JSON` }\r\n }\r\n }\r\n\r\n default:\r\n return { value: raw }\r\n }\r\n}\r\n\r\n/**\r\n * Parses all attributes on an element according to its props schema.\r\n * Returns `{ props, errors }` where errors is an array of human-readable messages.\r\n */\r\nexport function parseProps(element: HTMLElement, schema: WippyPropsSchema): ParseResult {\r\n const props: Record<string, unknown> = {}\r\n const errors: string[] = []\r\n\r\n for (const [attr, def] of Object.entries(schema.properties)) {\r\n const raw = element.getAttribute(attr)\r\n const camel = attrToCamel(attr)\r\n\r\n if (raw === null) {\r\n // Attribute not set — use default if available\r\n if (def.default !== undefined) {\r\n props[camel] = def.default\r\n }\r\n continue\r\n }\r\n\r\n const result = parseValue(attr, raw, def)\r\n if (result.error) {\r\n errors.push(result.error)\r\n }\r\n else {\r\n props[camel] = result.value\r\n }\r\n }\r\n\r\n return { props, errors }\r\n}\r\n","/**\n * Opt-in reactive adapter for `WippyElement`.\n *\n * Framework-agnostic primitive that lets non-Vue consumers subscribe to\n * prop / content updates and emit typed events on a web component without\n * pulling Vue (or any other reactivity library) into the core bundle.\n *\n * Access via `this.reactive` on a `WippyElement` subclass — the getter is\n * lazy, so subclasses that never touch it pay zero allocation cost. See\n * `base-element.ts:get reactive` for the bridge into the lifecycle.\n *\n * The `notifyProps` / `notifyContent` methods are package-visible: the\n * base element calls them from `attributeChangedCallback` and the content\n * MutationObserver callback respectively. They are NOT part of the public\n * API consumers should reach for.\n *\n * Cleanup: `dispose()` runs from `disconnectedCallback`. All listener\n * sets are cleared; subsequent notifyProps/notifyContent are no-ops; the\n * `events.emit` becomes a no-op too. A fresh adapter is allocated on the\n * next `this.reactive` access (i.e. after reconnect).\n */\n\nexport type PropsListener<Props> = (props: Props, errors: readonly string[]) => void\nexport type ContentListener = (content: string | null) => void\n\nexport interface SubscribeOptions {\n /** Cancel the subscription when the signal aborts. */\n signal?: AbortSignal\n /** Fire the listener once synchronously with the current value. */\n immediate?: boolean\n}\n\nexport interface PropsSubscription<Props> {\n /** Current parsed props. Always reflects the latest state. */\n readonly value: Props\n /** Current validation/parse errors. */\n readonly errors: readonly string[]\n /**\n * Register a listener that fires whenever props change. Returns an\n * unsubscribe function. Pass `options.signal` for AbortSignal-driven\n * cleanup (e.g. tied to an element's lifetime). Pass\n * `options.immediate: true` to fire once synchronously with the current\n * value — useful when the subscriber is set up mid-flight.\n *\n * Note: `notifyProps` runs BEFORE the subclass `onPropsChanged()` hook.\n * A subscriber added from inside `onPropsChanged()` therefore does NOT\n * receive the currently-firing change — only the next one. Use\n * `{ immediate: true }` to also see the current value.\n */\n subscribe: (listener: PropsListener<Props>, options?: SubscribeOptions) => () => void\n}\n\nexport interface ContentSubscription {\n /** Current `<template>` content text, or `null` if not set. */\n readonly value: string | null\n /** See `PropsSubscription.subscribe` for the same ordering caveat. */\n subscribe: (listener: ContentListener, options?: SubscribeOptions) => () => void\n}\n\nexport interface EventEmitterHandle<Events> {\n /**\n * Dispatch a typed `CustomEvent` (bubbles + composed, identical\n * semantics to the protected `emitEvent` helper). The key is constrained\n * to `keyof Events & string`, so consumers narrow `Events` to get\n * autocomplete + payload-type checks.\n *\n * No-op after the adapter is disposed (i.e. after the element is\n * detached). The element is the only event target — subscribers on\n * the element itself receive the event.\n */\n emit: <K extends keyof Events & string>(event: K, detail: Events[K]) => void\n}\n\nexport interface ReactiveAdapter<Props, Events> {\n props: PropsSubscription<Props>\n events: EventEmitterHandle<Events>\n /**\n * Present only when the element's `wippyConfig.contentTemplate` is set;\n * `null` otherwise. Avoids fake `.value === null` semantics for elements\n * that don't track children content.\n */\n content: ContentSubscription | null\n}\n\n/**\n * Concrete implementation used by `WippyElement`. The `notify*` methods\n * are intentionally exposed (not private) so the base-element can call\n * them; consumers should never reach for them.\n *\n * @internal\n */\nexport class ReactiveAdapterImpl<Props, Events> implements ReactiveAdapter<Props, Events> {\n private _props: Props\n private _errors: readonly string[]\n private _content: string | null\n private _propsListeners = new Set<PropsListener<Props>>()\n private _contentListeners = new Set<ContentListener>()\n private _disposed = false\n private _emitToDom: (eventName: string, detail?: unknown) => void\n\n readonly props: PropsSubscription<Props>\n readonly events: EventEmitterHandle<Events>\n readonly content: ContentSubscription | null\n\n constructor(\n initial: {\n props: Props\n errors: readonly string[]\n content: string | null\n hasContent: boolean\n },\n emitToDom: (eventName: string, detail?: unknown) => void,\n ) {\n this._props = initial.props\n this._errors = initial.errors\n this._content = initial.content\n this._emitToDom = emitToDom\n\n // Each getter / closure below runs with the surrounding object literal\n // as `this`, not the class instance — so we have to capture the\n // instance explicitly here.\n // eslint-disable-next-line ts/no-this-alias\n const self = this\n\n this.props = {\n get value() {\n return self._props\n },\n get errors() {\n return self._errors\n },\n subscribe(listener, options) {\n return self._subscribeProps(listener, options)\n },\n }\n\n this.events = {\n emit(event, detail) {\n if (self._disposed)\n return\n self._emitToDom(event as string, detail)\n },\n }\n\n this.content = initial.hasContent\n ? {\n get value() {\n return self._content\n },\n subscribe(listener, options) {\n return self._subscribeContent(listener, options)\n },\n }\n : null\n }\n\n /** @internal */\n notifyProps(props: Props, errors: readonly string[]): void {\n if (this._disposed)\n return\n this._props = props\n this._errors = errors\n for (const listener of this._propsListeners)\n listener(props, errors)\n }\n\n /** @internal */\n notifyContent(content: string | null): void {\n if (this._disposed)\n return\n this._content = content\n for (const listener of this._contentListeners)\n listener(content)\n }\n\n /** @internal */\n dispose(): void {\n if (this._disposed)\n return\n this._disposed = true\n this._propsListeners.clear()\n this._contentListeners.clear()\n }\n\n private _subscribeProps(listener: PropsListener<Props>, options?: SubscribeOptions): () => void {\n if (this._disposed || options?.signal?.aborted)\n return () => {}\n // Add to the set BEFORE firing `immediate` so a re-entrant\n // `notifyProps` triggered from inside the immediate callback can\n // find this listener and fire it for the synchronous change too.\n this._propsListeners.add(listener)\n if (options?.immediate)\n listener(this._props, this._errors)\n const unsub = () => {\n this._propsListeners.delete(listener)\n // Manual unsub must also detach the abort listener — otherwise it\n // accumulates on long-lived signals (e.g. an AbortController kept\n // around for the element's whole lifetime that fans out to many\n // subscriptions). `{ once: true }` only auto-removes when 'abort'\n // actually fires.\n options?.signal?.removeEventListener('abort', unsub)\n }\n options?.signal?.addEventListener('abort', unsub, { once: true })\n return unsub\n }\n\n private _subscribeContent(listener: ContentListener, options?: SubscribeOptions): () => void {\n if (this._disposed || options?.signal?.aborted)\n return () => {}\n this._contentListeners.add(listener)\n if (options?.immediate)\n listener(this._content)\n const unsub = () => {\n this._contentListeners.delete(listener)\n options?.signal?.removeEventListener('abort', unsub)\n }\n options?.signal?.addEventListener('abort', unsub, { once: true })\n return unsub\n }\n}\n","/**\n * Layout bus types shared between `@wippy-fe/webcomponent-core` and\n * `@wippy-fe/webcomponent-vue`. Mirror of the host-side\n * `LayoutBusBound` / `BroadcastEnvelope` shapes; structurally\n * compatible so a host-mounted web component can read its\n * `__wippyHostBus` property without importing host-private types.\n *\n * The host (gen-2-chat managed-layout shell) sets:\n * - `el.dataset.wippyPanelId` (string)\n * - `(el as { __wippyHostBus?: LayoutBusBound }).__wippyHostBus`\n * BEFORE the element is appended to the DOM. Web components see them\n * on first `connectedCallback` tick.\n *\n * Outside a managed-layout host, both are absent — read code MUST\n * tolerate `undefined`.\n *\n * The interface bodies live in `@wippy-fe/shared` so the host can\n * import them without dragging in this package's `@wippy-fe/proxy`\n * runtime dependency. Consumers continue to import from\n * `@wippy-fe/webcomponent-core` (this re-export) for backward compat.\n */\n\nimport type { LayoutBusBound } from '@wippy-fe/shared'\n\nexport type { BroadcastEnvelope, LayoutBusBound } from '@wippy-fe/shared'\n\n/**\n * Read the host bus attached to an element by `ComponentResolver` in\n * the managed-layout host. Returns `null` outside a managed-layout\n * host (or before the element is connected). Stable across element\n * remounts of the same panel — the resolver re-attaches a fresh bus\n * each time.\n */\nexport function getWippyHostBus(el: HTMLElement): LayoutBusBound | null {\n return (el as { __wippyHostBus?: LayoutBusBound }).__wippyHostBus ?? null\n}\n\n/**\n * Read the panelId attribute set by `ComponentResolver`. `null`\n * outside a managed-layout host.\n */\nexport function getWippyPanelId(el: HTMLElement): string | null {\n return el.dataset.wippyPanelId ?? null\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/base-element.ts","../src/css-loader.ts","../src/host-scope.ts","../src/prop-parser.ts","../src/reactive-adapter.ts","../src/host-bus.ts"],"sourcesContent":["import type { ReactiveAdapter } from './reactive-adapter.ts'\r\nimport type { WippyElementConfig } from './types.ts'\r\nimport { addCollection } from '@iconify/vue'\r\nimport { addIcons, applyThemeMode, define, host as wippyHost, on as wippyOn } from '@wippy-fe/proxy'\r\nimport { injectInlineCss, loadHostCss } from './css-loader.ts'\r\nimport { getWippyHost } from './host-scope.ts'\r\nimport { parseProps } from './prop-parser.ts'\r\nimport { ReactiveAdapterImpl } from './reactive-adapter.ts'\r\n\r\n/**\r\n * Abstract base class for Wippy web components.\r\n *\r\n * Generic over `Props` — the parsed prop object type. This types `onMount`,\r\n * `onPropsChanged`, and `validateProps`. Defaults to `Record<string, unknown>`.\r\n *\r\n * Lifecycle order (first connect):\r\n * 1. shadow DOM attached\r\n * 2. `onInit(shadow)` — hook for early shadow DOM customization\r\n * 3. inline CSS injected\r\n * 4. host CSS loading started (async, non-blocking)\r\n * 5. container div created and appended\r\n * 6. icons registered\r\n * 7. props parsed from attributes + custom validation\r\n * 8. `onMount(shadow, container, props, errors)` — framework setup\r\n * 9. internals state → ready\r\n * 10. `onReady()` — post-mount hook\r\n * 11. `load` event emitted\r\n *\r\n * On reconnect (move-style DOM op: detach → reattach), the shadow root\r\n * persists across the cycle, so steps 1, 3, 4, 5 (CSS injection +\r\n * container creation) are skipped to avoid duplicating `<style>` and\r\n * container `<div>` siblings inside the persistent shadow. The stored\r\n * container is reused and `onMount` is re-invoked with `isRemount = true`\r\n * so framework adapters can decide between fresh-mount and remount paths.\r\n *\r\n * On error: `onError(error)` → internals state → error → `error` event\r\n * On disconnect: `onUnmount()` → `unload` event → internals cleared.\r\n * Note: `disconnectedCallback` does NOT clear the shadow root or the\r\n * stored container — they're reused on reconnect.\r\n */\r\nexport abstract class WippyElement<\r\n Props = Record<string, unknown>,\r\n Events = Record<string, unknown>,\r\n> extends HTMLElement {\r\n private _internals!: ElementInternals\r\n private _contentObserver: MutationObserver | null = null\r\n /** True after the first successful connectedCallback completes. */\r\n private _initialized: boolean = false\r\n /** Container div created on first connect; reused on subsequent connects. */\r\n private _container: HTMLElement | null = null\r\n /**\r\n * Opt-in reactive adapter. Lazy-allocated on first `this.reactive`\r\n * access, disposed on `disconnectedCallback`, re-allocated on next\r\n * access after reconnect. Subclasses that never touch `this.reactive`\r\n * pay zero allocation cost — `notifyProps`/`notifyContent` short-circuit\r\n * on the null guard.\r\n */\r\n private _reactive: ReactiveAdapterImpl<Props, Events> | null = null\r\n /**\r\n * Cached results of the most recent `parseProps` + `validateProps`\r\n * pass. Set by `connectedCallback` and `attributeChangedCallback`.\r\n * Read by `get reactive()` to avoid re-parsing on lazy allocation —\r\n * means `validateProps` only ever runs once per attribute change,\r\n * even for consumers that touch `this.reactive` inside `onMount`.\r\n */\r\n private _lastProps: Props | null = null\r\n private _lastErrors: readonly string[] = []\r\n private _lastContent: string | null = null\r\n /** Unsubscribe from host `@theme` broadcasts; set on connect, cleared on disconnect. */\r\n private _themeUnsub: (() => void) | null = null\r\n\r\n /**\r\n * Phantom field to retain the `Events` type parameter so it shows up in\r\n * type errors / `Reflect.get` shape. Adapter typing reads it indirectly\r\n * via the generic.\r\n * @internal\r\n */\r\n declare readonly _events: Events\r\n\r\n /**\r\n * Override to provide the component's configuration.\r\n * Must be static because `observedAttributes` reads it before construction.\r\n *\r\n * Specify the generic to get typed `validateProps`:\r\n * ```ts\r\n * static get wippyConfig(): WippyElementConfig<MyProps> { ... }\r\n * ```\r\n */\r\n static get wippyConfig(): WippyElementConfig {\r\n return { propsSchema: { properties: {} } }\r\n }\r\n\r\n /**\r\n * Derived from the props schema + any `extraObservedAttributes`.\r\n */\r\n static get observedAttributes(): string[] {\r\n const config = this.wippyConfig\r\n const schemaAttrs = Object.keys(config.propsSchema.properties)\r\n const extra = config.extraObservedAttributes ?? []\r\n return [...schemaAttrs, ...extra]\r\n }\r\n\r\n constructor() {\r\n super()\r\n this._internals = this.attachInternals()\r\n }\r\n\r\n /**\r\n * Panel-scoped `host` wrapper attached by the managed-layout shell's\r\n * content resolvers (`ComponentResolver` / `WebComponentPackageLoader`).\r\n *\r\n * Inside a managed-layout panel, this is a wrapper around the universal\r\n * `host` API where context-aware calls (`layout.broadcast / send / on`)\r\n * are routed through the panel-bound bus — so `sourcePanelId` is\r\n * attributed correctly without postMessage indirection. Layout\r\n * mutations and other host methods pass through unchanged.\r\n *\r\n * `null` outside a managed-layout context (compat shell, chat sidebar,\r\n * standalone playground). Subclass code that needs a host in those\r\n * cases can fall back to `import { host } from '@wippy-fe/proxy'`.\r\n */\r\n get host(): ReturnType<typeof getWippyHost> {\r\n return getWippyHost(this)\r\n }\r\n\r\n /**\r\n * Emit a CustomEvent that bubbles and crosses shadow DOM boundaries.\r\n */\r\n protected emitEvent(eventName: string, detail?: unknown): void {\r\n this.dispatchEvent(new CustomEvent(eventName, {\r\n bubbles: true,\r\n composed: true,\r\n detail,\r\n }))\r\n }\r\n\r\n /**\r\n * Opt-in reactive adapter — framework-agnostic. Subscribe to prop\r\n * changes, content changes, or emit typed events from a non-Vue\r\n * consumer without re-rolling reactivity.\r\n *\r\n * ```ts\r\n * class MyEl extends WippyElement<{ count: number }, { tick: { n: number } }> {\r\n * protected onMount() {\r\n * const ctrl = new AbortController()\r\n * this.reactive.props.subscribe(({ count }) => {\r\n * this.shadowRoot!.querySelector('.n')!.textContent = String(count)\r\n * }, { signal: ctrl.signal, immediate: true })\r\n * }\r\n * tick(n: number) { this.reactive.events.emit('tick', { n }) }\r\n * }\r\n * ```\r\n *\r\n * Allocation cost is zero unless this getter is touched. Disposed on\r\n * `disconnectedCallback`; a fresh adapter is allocated on the next\r\n * access after reconnect.\r\n */\r\n protected get reactive(): ReactiveAdapter<Props, Events> {\r\n if (!this._reactive) {\r\n const config = (this.constructor as typeof WippyElement).wippyConfig\r\n const hasContent = !!config.contentTemplate\r\n // Reuse the cached parse result from the most recent\r\n // `connectedCallback` / `attributeChangedCallback` whenever we\r\n // have one; otherwise fall back to a fresh parse (this happens\r\n // when `reactive` is touched before the element is ever\r\n // connected — rare but legal).\r\n let props: Props\r\n let errors: readonly string[]\r\n if (this._lastProps !== null) {\r\n props = this._lastProps\r\n errors = this._lastErrors\r\n }\r\n else {\r\n const parsed = parseProps(this, config.propsSchema)\r\n if (config.validateProps) {\r\n parsed.errors.push(...config.validateProps(parsed.props))\r\n }\r\n props = parsed.props as Props\r\n errors = parsed.errors\r\n this._lastProps = props\r\n this._lastErrors = errors\r\n }\r\n const content = hasContent\r\n ? (this._lastContent ?? this._extractContent(config.contentTemplate!))\r\n : null\r\n if (hasContent && this._lastContent === null)\r\n this._lastContent = content\r\n this._reactive = new ReactiveAdapterImpl<Props, Events>(\r\n { props, errors, content, hasContent },\r\n this.emitEvent.bind(this),\r\n )\r\n }\r\n return this._reactive\r\n }\r\n\r\n // ── Lifecycle ──────────────────────────────────────────────\r\n\r\n connectedCallback(): void {\r\n this._internals.states.add('loading')\r\n try {\r\n const config = (this.constructor as typeof WippyElement).wippyConfig\r\n const isRemount = this._initialized\r\n\r\n // 1. Shadow DOM (guard against reconnect — attachShadow throws if called twice)\r\n const shadow = this.shadowRoot ?? this.attachShadow({ mode: config.shadowMode ?? 'open' })\r\n\r\n let container: HTMLElement\r\n if (!isRemount) {\r\n // 2. Early hook — customize shadow before CSS/container\r\n this.onInit(shadow)\r\n\r\n // 3. Inline CSS\r\n if (config.inlineCss) {\r\n injectInlineCss(shadow, config.inlineCss)\r\n }\r\n\r\n // 4. Host CSS (async, non-blocking)\r\n if (config.hostCssKeys === undefined || config.hostCssKeys.length > 0) {\r\n loadHostCss(shadow, config.hostCssKeys)\r\n }\r\n\r\n // 5. Container\r\n container = document.createElement('div')\r\n const classes = config.containerClasses ?? []\r\n if (classes.length > 0) {\r\n container.classList.add(...classes)\r\n }\r\n shadow.appendChild(container)\r\n this._container = container\r\n\r\n // 6. Icons\r\n addIcons(addCollection)\r\n }\r\n else {\r\n // Reconnect path — reuse the existing shadow children + container.\r\n // Skip CSS/icon/container setup so we don't accumulate duplicate\r\n // `<style>` and container `<div>` siblings on every detach/reattach.\r\n // The framework adapter decides whether to remount on the existing\r\n // container or recreate its app instance.\r\n container = this._container!\r\n }\r\n\r\n // Mirror the forced theme onto the shadow container so the WC's own\r\n // Tailwind `dark:` utilities respond — class selectors don't cross the\r\n // shadow boundary (the `--p-*` tokens inherit across it via custom\r\n // properties, so token colors already follow without this).\r\n this._applyThemeToContainer()\r\n if (!this._themeUnsub)\r\n this._themeUnsub = wippyOn('@theme', mode => applyThemeMode(mode, this._container ?? undefined))\r\n\r\n // 7. Parse initial props + custom validation\r\n const { props, errors } = parseProps(this, config.propsSchema)\r\n if (config.validateProps) {\r\n errors.push(...config.validateProps(props))\r\n }\r\n const typedProps = props as Props\r\n // Cache so a lazy `get reactive()` call from inside `onMount`\r\n // doesn't re-parse / re-validate.\r\n this._lastProps = typedProps\r\n this._lastErrors = errors\r\n\r\n // 7b. Extract children content (if contentTemplate configured)\r\n let initialContent: string | null = null\r\n if (config.contentTemplate) {\r\n initialContent = this._extractContent(config.contentTemplate)\r\n this._lastContent = initialContent\r\n this._contentObserver = new MutationObserver(() => {\r\n const content = this._extractContent(config.contentTemplate!)\r\n this._lastContent = content\r\n // Fan out to the reactive adapter first so subclass overrides of\r\n // `onContentChanged` that read `this.reactive.content.value` see\r\n // the new value. No-op when the adapter hasn't been allocated.\r\n this._reactive?.notifyContent(content)\r\n this.onContentChanged(content)\r\n })\r\n this._contentObserver.observe(this, {\r\n childList: true,\r\n characterData: true,\r\n subtree: true,\r\n })\r\n }\r\n\r\n // 8. Framework mount (first time) or remount (reconnect)\r\n this.onMount(shadow, container, typedProps, errors, initialContent, isRemount)\r\n\r\n // 9. Ready\r\n this._internals.states.delete('loading')\r\n this._internals.states.add('ready')\r\n\r\n // First-connect bookkeeping after a clean mount.\r\n if (!isRemount) {\r\n this._initialized = true\r\n }\r\n\r\n // 10. Post-mount hook\r\n this.onReady()\r\n\r\n // 11. Emit load\r\n this.emitEvent('load')\r\n }\r\n catch (error) {\r\n this.onError(error)\r\n this._internals.states.delete('loading')\r\n this._internals.states.add('error')\r\n this.emitEvent('error', {\r\n message: error instanceof Error ? error.message : String(error),\r\n error,\r\n })\r\n }\r\n }\r\n\r\n /**\r\n * Applies the host's current forced theme mode to the shadow container.\r\n * No-op if the proxy host doesn't expose `getThemeMode` (older proxy).\r\n */\r\n private _applyThemeToContainer(): void {\r\n if (!this._container)\r\n return\r\n const mode = wippyHost.getThemeMode?.() ?? 'auto'\r\n applyThemeMode(mode, this._container)\r\n }\r\n\r\n disconnectedCallback(): void {\r\n if (this._themeUnsub) {\r\n this._themeUnsub()\r\n this._themeUnsub = null\r\n }\r\n if (this._contentObserver) {\r\n this._contentObserver.disconnect()\r\n this._contentObserver = null\r\n }\r\n this.onUnmount()\r\n this.emitEvent('unload')\r\n this._internals.states.clear()\r\n // Drop the reactive adapter so subscribers from this attachment are\r\n // cleared and a fresh adapter is allocated on the next `this.reactive`\r\n // access (i.e. after reconnect).\r\n this._reactive?.dispose()\r\n this._reactive = null\r\n // Clear cached parse state — `connectedCallback` re-populates on\r\n // reconnect; before then, a lazy `get reactive()` access should\r\n // re-parse from current attributes (rare path).\r\n this._lastProps = null\r\n this._lastErrors = []\r\n this._lastContent = null\r\n // Drop panel-context wires so a detached element held by a\r\n // consumer (or re-inserted into a different panel) doesn't carry\r\n // stale wires that would silently misattribute. The resolver\r\n // re-installs them on the next mount.\r\n delete (this as unknown as { __wippyHost?: unknown }).__wippyHost\r\n delete (this as unknown as { __wippyHostBus?: unknown }).__wippyHostBus\r\n }\r\n\r\n attributeChangedCallback(_name: string, oldVal: string | null, newVal: string | null): void {\r\n if (oldVal === newVal)\r\n return\r\n const config = (this.constructor as typeof WippyElement).wippyConfig\r\n const { props, errors } = parseProps(this, config.propsSchema)\r\n if (config.validateProps) {\r\n errors.push(...config.validateProps(props))\r\n }\r\n const typedProps = props as Props\r\n this._lastProps = typedProps\r\n this._lastErrors = errors\r\n // Fan out to the reactive adapter BEFORE the legacy hook so subclasses\r\n // that override `onPropsChanged` AND read `this.reactive.props.value`\r\n // inside it see consistent state. No-op when the adapter hasn't been\r\n // lazy-allocated.\r\n this._reactive?.notifyProps(typedProps, errors)\r\n this.onPropsChanged(typedProps, errors)\r\n }\r\n\r\n // ── Hooks ──────────────────────────────────────────────────\r\n\r\n /** Called right after shadow DOM is attached, before CSS or container. */\r\n protected onInit(_shadow: ShadowRoot): void {}\r\n\r\n /**\r\n * Called after shadow DOM, CSS, and container are ready. Mount your\r\n * framework here.\r\n *\r\n * Invoked on first connect AND on every subsequent reconnect (move-style\r\n * DOM op: detach → reattach). On reconnect the same `container` instance\r\n * is reused. Adapters that hold a framework app handle should either\r\n * detect `isRemount === true` and re-mount on the existing container, or\r\n * leave the previous app intact across the detach/reattach cycle.\r\n */\r\n protected abstract onMount(\r\n shadow: ShadowRoot,\r\n container: HTMLElement,\r\n initialProps: Props,\r\n initialErrors: string[],\r\n initialContent?: string | null,\r\n isRemount?: boolean,\r\n ): void\r\n\r\n /** Called after internals state is set to ready, before the `load` event. */\r\n protected onReady(): void {}\r\n\r\n /** Called when connectedCallback throws. Default logs to console. */\r\n protected onError(error: unknown): void {\r\n console.error(`${this.constructor.name} initialization failed:`, error)\r\n }\r\n\r\n /** Called during disconnectedCallback — clean up framework resources. */\r\n protected abstract onUnmount(): void\r\n\r\n /** Called when observed attributes change. Override to update framework state. */\r\n protected onPropsChanged(_props: Props, _errors: string[]): void {}\r\n\r\n /**\r\n * Extract text from a child `<template data-type=\"...\">` element.\r\n * Uses `.content.textContent` since `<template>` stores content in a DocumentFragment.\r\n */\r\n private _extractContent(dataType: string): string | null {\r\n const tpl = this.querySelector(`template[data-type=\"${dataType}\"]`) as HTMLTemplateElement | null\r\n return tpl?.content.textContent?.trim() ?? null\r\n }\r\n\r\n /** Called when child `<template>` content changes. Override to update framework state. */\r\n protected onContentChanged(_content: string | null): void {}\r\n}\r\n\r\nexport { define }\r\n","import type { HostCssKey } from './types.ts'\r\nimport { hostCss, loadCss } from '@wippy-fe/proxy'\r\n\r\nconst DEFAULT_HOST_CSS_KEYS: HostCssKey[] = [\r\n 'themeConfigUrl',\r\n 'primeVueCssUrl',\r\n 'markdownCssUrl',\r\n 'iframeCssUrl',\r\n]\r\n\r\n/**\r\n * Loads host CSS URLs into the shadow root as `<style>` elements.\r\n * Non-blocking — returns a promise but the component doesn't need to await it.\r\n */\r\nexport function loadHostCss(shadow: ShadowRoot, keys?: HostCssKey[]): Promise<void> {\r\n const cssKeys = keys ?? DEFAULT_HOST_CSS_KEYS\r\n // Filter out keys whose URL is missing (e.g. removed CSS like fontCssUrl).\r\n // Load each independently so one failure doesn't block the rest.\r\n const jobs = cssKeys.map(async (key) => {\r\n const url = hostCss[key]\r\n if (!url) {\r\n console.warn(`[wippy-fe/webcomponent-core] hostCss key \"${key}\" is undefined — skipping. Remove it from hostCssKeys if the CSS was removed.`)\r\n return null\r\n }\r\n try {\r\n return await loadCss(url)\r\n }\r\n catch (err) {\r\n console.warn(`[wippy-fe/webcomponent-core] Failed to load hostCss \"${key}\" (${url}):`, err)\r\n return null\r\n }\r\n })\r\n return Promise.all(jobs).then((cssChunks) => {\r\n for (const css of cssChunks) {\r\n if (!css)\r\n continue\r\n const style = document.createElement('style')\r\n style.textContent = css\r\n style.setAttribute('role', '@wippy-fe/host-css')\r\n shadow.appendChild(style)\r\n }\r\n })\r\n}\r\n\r\n/**\r\n * Injects inline CSS text into the shadow root.\r\n */\r\nexport function injectInlineCss(shadow: ShadowRoot, text: string): void {\r\n const style = document.createElement('style')\r\n style.textContent = text\r\n shadow.appendChild(style)\r\n}\r\n","/**\n * Element-attached host wrapper reader for web components mounted as\n * `kind: 'component'` panels in the gen-2-chat managed-layout shell.\n *\n * The host stamps a panel-scoped wrapper as `__wippyHost` on each\n * element BEFORE it is appended to the DOM (see the host's\n * `panel-context-wires.ts` and `host-scope.ts`). Consumer web\n * components read it back via `getWippyHost(this)` in\n * `connectedCallback` and onwards.\n *\n * The wrapper is **constructed by the host** — this package only\n * exposes the reader. Outside a managed-layout host (raw mounts,\n * compat shells, tests without the connector) the property is absent\n * and `getWippyHost` returns `null`.\n */\n\n/**\n * Read the panel-scoped host wrapper attached to an element by the\n * managed-layout shell's content resolvers. Returns `null` outside a\n * managed-layout host (or before the element is connected).\n *\n * Subclass authors of `WippyElement` / `WippyVueElement` access this\n * via `this.host` / `useHost()` and rarely need to call this directly.\n * The helper is exposed for raw `HTMLElement` consumers.\n */\nexport function getWippyHost<H = unknown>(el: HTMLElement): H | null {\n return ((el as unknown) as { __wippyHost?: H }).__wippyHost ?? null\n}\n","import type { WippyPropDefinition, WippyPropsSchema } from './types.ts'\r\n\r\nexport interface ParseResult {\r\n props: Record<string, unknown>\r\n errors: string[]\r\n}\r\n\r\n/**\r\n * Converts a kebab-case attribute name to camelCase.\r\n * `allowed-types` → `allowedTypes`\r\n */\r\nexport function attrToCamel(attr: string): string {\r\n return attr.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase())\r\n}\r\n\r\n/**\r\n * Parses a single attribute value according to its schema definition.\r\n */\r\nfunction parseValue(attr: string, raw: string, def: WippyPropDefinition): { value: unknown, error?: string } {\r\n switch (def.type) {\r\n case 'string':\r\n return { value: raw }\r\n\r\n case 'number': {\r\n const n = Number.parseFloat(raw)\r\n if (Number.isNaN(n))\r\n return { value: undefined, error: `Invalid ${attr}: expected a number` }\r\n return { value: n }\r\n }\r\n\r\n case 'integer': {\r\n const n = Number.parseInt(raw, 10)\r\n if (Number.isNaN(n))\r\n return { value: undefined, error: `Invalid ${attr}: expected an integer` }\r\n return { value: n }\r\n }\r\n\r\n case 'boolean':\r\n // Presence of the attribute means true (HTML convention), explicit \"false\" means false\r\n return { value: raw !== 'false' }\r\n\r\n case 'array':\r\n case 'object': {\r\n try {\r\n const parsed = JSON.parse(raw)\r\n if (def.type === 'array' && !Array.isArray(parsed)) {\r\n return { value: undefined, error: `Invalid ${attr}: expected a JSON array` }\r\n }\r\n return { value: parsed }\r\n }\r\n catch {\r\n return { value: undefined, error: `Invalid ${attr}: must be valid JSON` }\r\n }\r\n }\r\n\r\n default:\r\n return { value: raw }\r\n }\r\n}\r\n\r\n/**\r\n * Parses all attributes on an element according to its props schema.\r\n * Returns `{ props, errors }` where errors is an array of human-readable messages.\r\n */\r\nexport function parseProps(element: HTMLElement, schema: WippyPropsSchema): ParseResult {\r\n const props: Record<string, unknown> = {}\r\n const errors: string[] = []\r\n\r\n for (const [attr, def] of Object.entries(schema.properties)) {\r\n const raw = element.getAttribute(attr)\r\n const camel = attrToCamel(attr)\r\n\r\n if (raw === null) {\r\n // Attribute not set — use default if available\r\n if (def.default !== undefined) {\r\n props[camel] = def.default\r\n }\r\n continue\r\n }\r\n\r\n const result = parseValue(attr, raw, def)\r\n if (result.error) {\r\n errors.push(result.error)\r\n }\r\n else {\r\n props[camel] = result.value\r\n }\r\n }\r\n\r\n return { props, errors }\r\n}\r\n","/**\n * Opt-in reactive adapter for `WippyElement`.\n *\n * Framework-agnostic primitive that lets non-Vue consumers subscribe to\n * prop / content updates and emit typed events on a web component without\n * pulling Vue (or any other reactivity library) into the core bundle.\n *\n * Access via `this.reactive` on a `WippyElement` subclass — the getter is\n * lazy, so subclasses that never touch it pay zero allocation cost. See\n * `base-element.ts:get reactive` for the bridge into the lifecycle.\n *\n * The `notifyProps` / `notifyContent` methods are package-visible: the\n * base element calls them from `attributeChangedCallback` and the content\n * MutationObserver callback respectively. They are NOT part of the public\n * API consumers should reach for.\n *\n * Cleanup: `dispose()` runs from `disconnectedCallback`. All listener\n * sets are cleared; subsequent notifyProps/notifyContent are no-ops; the\n * `events.emit` becomes a no-op too. A fresh adapter is allocated on the\n * next `this.reactive` access (i.e. after reconnect).\n */\n\nexport type PropsListener<Props> = (props: Props, errors: readonly string[]) => void\nexport type ContentListener = (content: string | null) => void\n\nexport interface SubscribeOptions {\n /** Cancel the subscription when the signal aborts. */\n signal?: AbortSignal\n /** Fire the listener once synchronously with the current value. */\n immediate?: boolean\n}\n\nexport interface PropsSubscription<Props> {\n /** Current parsed props. Always reflects the latest state. */\n readonly value: Props\n /** Current validation/parse errors. */\n readonly errors: readonly string[]\n /**\n * Register a listener that fires whenever props change. Returns an\n * unsubscribe function. Pass `options.signal` for AbortSignal-driven\n * cleanup (e.g. tied to an element's lifetime). Pass\n * `options.immediate: true` to fire once synchronously with the current\n * value — useful when the subscriber is set up mid-flight.\n *\n * Note: `notifyProps` runs BEFORE the subclass `onPropsChanged()` hook.\n * A subscriber added from inside `onPropsChanged()` therefore does NOT\n * receive the currently-firing change — only the next one. Use\n * `{ immediate: true }` to also see the current value.\n */\n subscribe: (listener: PropsListener<Props>, options?: SubscribeOptions) => () => void\n}\n\nexport interface ContentSubscription {\n /** Current `<template>` content text, or `null` if not set. */\n readonly value: string | null\n /** See `PropsSubscription.subscribe` for the same ordering caveat. */\n subscribe: (listener: ContentListener, options?: SubscribeOptions) => () => void\n}\n\nexport interface EventEmitterHandle<Events> {\n /**\n * Dispatch a typed `CustomEvent` (bubbles + composed, identical\n * semantics to the protected `emitEvent` helper). The key is constrained\n * to `keyof Events & string`, so consumers narrow `Events` to get\n * autocomplete + payload-type checks.\n *\n * No-op after the adapter is disposed (i.e. after the element is\n * detached). The element is the only event target — subscribers on\n * the element itself receive the event.\n */\n emit: <K extends keyof Events & string>(event: K, detail: Events[K]) => void\n}\n\nexport interface ReactiveAdapter<Props, Events> {\n props: PropsSubscription<Props>\n events: EventEmitterHandle<Events>\n /**\n * Present only when the element's `wippyConfig.contentTemplate` is set;\n * `null` otherwise. Avoids fake `.value === null` semantics for elements\n * that don't track children content.\n */\n content: ContentSubscription | null\n}\n\n/**\n * Concrete implementation used by `WippyElement`. The `notify*` methods\n * are intentionally exposed (not private) so the base-element can call\n * them; consumers should never reach for them.\n *\n * @internal\n */\nexport class ReactiveAdapterImpl<Props, Events> implements ReactiveAdapter<Props, Events> {\n private _props: Props\n private _errors: readonly string[]\n private _content: string | null\n private _propsListeners = new Set<PropsListener<Props>>()\n private _contentListeners = new Set<ContentListener>()\n private _disposed = false\n private _emitToDom: (eventName: string, detail?: unknown) => void\n\n readonly props: PropsSubscription<Props>\n readonly events: EventEmitterHandle<Events>\n readonly content: ContentSubscription | null\n\n constructor(\n initial: {\n props: Props\n errors: readonly string[]\n content: string | null\n hasContent: boolean\n },\n emitToDom: (eventName: string, detail?: unknown) => void,\n ) {\n this._props = initial.props\n this._errors = initial.errors\n this._content = initial.content\n this._emitToDom = emitToDom\n\n // Each getter / closure below runs with the surrounding object literal\n // as `this`, not the class instance — so we have to capture the\n // instance explicitly here.\n // eslint-disable-next-line ts/no-this-alias\n const self = this\n\n this.props = {\n get value() {\n return self._props\n },\n get errors() {\n return self._errors\n },\n subscribe(listener, options) {\n return self._subscribeProps(listener, options)\n },\n }\n\n this.events = {\n emit(event, detail) {\n if (self._disposed)\n return\n self._emitToDom(event as string, detail)\n },\n }\n\n this.content = initial.hasContent\n ? {\n get value() {\n return self._content\n },\n subscribe(listener, options) {\n return self._subscribeContent(listener, options)\n },\n }\n : null\n }\n\n /** @internal */\n notifyProps(props: Props, errors: readonly string[]): void {\n if (this._disposed)\n return\n this._props = props\n this._errors = errors\n for (const listener of this._propsListeners)\n listener(props, errors)\n }\n\n /** @internal */\n notifyContent(content: string | null): void {\n if (this._disposed)\n return\n this._content = content\n for (const listener of this._contentListeners)\n listener(content)\n }\n\n /** @internal */\n dispose(): void {\n if (this._disposed)\n return\n this._disposed = true\n this._propsListeners.clear()\n this._contentListeners.clear()\n }\n\n private _subscribeProps(listener: PropsListener<Props>, options?: SubscribeOptions): () => void {\n if (this._disposed || options?.signal?.aborted)\n return () => {}\n // Add to the set BEFORE firing `immediate` so a re-entrant\n // `notifyProps` triggered from inside the immediate callback can\n // find this listener and fire it for the synchronous change too.\n this._propsListeners.add(listener)\n if (options?.immediate)\n listener(this._props, this._errors)\n const unsub = () => {\n this._propsListeners.delete(listener)\n // Manual unsub must also detach the abort listener — otherwise it\n // accumulates on long-lived signals (e.g. an AbortController kept\n // around for the element's whole lifetime that fans out to many\n // subscriptions). `{ once: true }` only auto-removes when 'abort'\n // actually fires.\n options?.signal?.removeEventListener('abort', unsub)\n }\n options?.signal?.addEventListener('abort', unsub, { once: true })\n return unsub\n }\n\n private _subscribeContent(listener: ContentListener, options?: SubscribeOptions): () => void {\n if (this._disposed || options?.signal?.aborted)\n return () => {}\n this._contentListeners.add(listener)\n if (options?.immediate)\n listener(this._content)\n const unsub = () => {\n this._contentListeners.delete(listener)\n options?.signal?.removeEventListener('abort', unsub)\n }\n options?.signal?.addEventListener('abort', unsub, { once: true })\n return unsub\n }\n}\n","/**\n * Layout bus types shared between `@wippy-fe/webcomponent-core` and\n * `@wippy-fe/webcomponent-vue`. Mirror of the host-side\n * `LayoutBusBound` / `BroadcastEnvelope` shapes; structurally\n * compatible so a host-mounted web component can read its\n * `__wippyHostBus` property without importing host-private types.\n *\n * The host (gen-2-chat managed-layout shell) sets:\n * - `el.dataset.wippyPanelId` (string)\n * - `(el as { __wippyHostBus?: LayoutBusBound }).__wippyHostBus`\n * BEFORE the element is appended to the DOM. Web components see them\n * on first `connectedCallback` tick.\n *\n * Outside a managed-layout host, both are absent — read code MUST\n * tolerate `undefined`.\n *\n * The interface bodies live in `@wippy-fe/shared` so the host can\n * import them without dragging in this package's `@wippy-fe/proxy`\n * runtime dependency. Consumers continue to import from\n * `@wippy-fe/webcomponent-core` (this re-export) for backward compat.\n */\n\nimport type { LayoutBusBound } from '@wippy-fe/shared'\n\nexport type { BroadcastEnvelope, LayoutBusBound } from '@wippy-fe/shared'\n\n/**\n * Read the host bus attached to an element by `ComponentResolver` in\n * the managed-layout host. Returns `null` outside a managed-layout\n * host (or before the element is connected). Stable across element\n * remounts of the same panel — the resolver re-attaches a fresh bus\n * each time.\n */\nexport function getWippyHostBus(el: HTMLElement): LayoutBusBound | null {\n return (el as { __wippyHostBus?: LayoutBusBound }).__wippyHostBus ?? null\n}\n\n/**\n * Read the panelId attribute set by `ComponentResolver`. `null`\n * outside a managed-layout host.\n */\nexport function getWippyPanelId(el: HTMLElement): string | null {\n return el.dataset.wippyPanelId ?? null\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wippy-fe/webcomponent-core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.38",
|
|
4
4
|
"description": "Framework-agnostic base class for Wippy web components - shadow DOM, CSS loading, schema-driven prop parsing, and lifecycle management.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
],
|
|
22
22
|
"peerDependencies": {
|
|
23
23
|
"@iconify/vue": "^5.0.0",
|
|
24
|
-
"@wippy-fe/
|
|
25
|
-
"@wippy-fe/
|
|
24
|
+
"@wippy-fe/shared": "^0.0.38",
|
|
25
|
+
"@wippy-fe/proxy": "^0.0.38"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "tsup",
|