@pie-lib/delivery-events-svelte 0.1.1-next.1 → 0.2.0-next.2

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.
@@ -0,0 +1,47 @@
1
+ export interface DeliveryElementOptions<Model, Session> {
2
+ /**
3
+ * Whether `session` is a complete response to `model`. It is the `complete`
4
+ * flag of every `model-set` and `session-changed` the element dispatches, which
5
+ * is what a player gates the item's answered state on.
6
+ */
7
+ isComplete(model: Model | undefined, session: Session | undefined): boolean;
8
+ }
9
+ /**
10
+ * The delivery custom element a player mounts: it owns the session the player
11
+ * hands it and announces every change to it.
12
+ */
13
+ export interface DeliveryElement<Model = unknown, Session = unknown> extends HTMLElement {
14
+ model: Model | undefined;
15
+ /** The session object the player set, with every update written into it. */
16
+ session: Session | undefined;
17
+ /**
18
+ * The component's `onSessionChange` prop, which it calls with each update:
19
+ * writes the update and dispatches `session-changed`.
20
+ */
21
+ onSessionChange: (session: Session) => void;
22
+ /** `isComplete` for the current model and session. A subclass adds its own conditions here. */
23
+ isComplete(): boolean;
24
+ /**
25
+ * Writes `next` into the player's session and hands the component `next`,
26
+ * a fresh reference its `$derived` reads re-run on. Dispatches nothing.
27
+ */
28
+ writeSession(next: Session): void;
29
+ dispatchSessionChanged(): void;
30
+ }
31
+ export type DeliveryElementConstructor<Model = unknown, Session = unknown> = new () => DeliveryElement<Model, Session>;
32
+ /**
33
+ * The delivery custom element for `Component`, a Svelte component compiled
34
+ * with `customElement` that declares `model`, `session` and an
35
+ * `onSessionChange` callback prop.
36
+ *
37
+ * The session contract lives here, once, for every Svelte element: the update
38
+ * is written into the object the player handed the element (`writeSessionInPlace`),
39
+ * and `session-changed` and `model-set` are dispatched under the tag the player
40
+ * registered the element with, carrying `complete` from `options.isComplete`.
41
+ *
42
+ * `onSessionChange` is an ordinary prop of the component, which the element
43
+ * assigns in its constructor through the accessor Svelte generates for it; a
44
+ * component mounted with `mount()` takes it like any other prop. A subclass
45
+ * assigns its own callback props the same way.
46
+ */
47
+ export declare function defineDeliveryElement<Model = unknown, Session = unknown>(Component: object, options: DeliveryElementOptions<Model, Session>): DeliveryElementConstructor<Model, Session>;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * @pie-lib/delivery-events-svelte
3
3
  *
4
- * Shared host/session bridge utilities for Svelte delivery custom elements.
4
+ * The delivery custom element shell and session write-through for Svelte elements.
5
5
  */
6
- export * from './session-bridge.js';
6
+ export * from './delivery-element.js';
7
+ export * from './write-session-in-place.js';
7
8
  export { ModelSetEvent, SessionChangedEvent } from '@pie-element/shared-player-events';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
- import { forwardSessionChange as e, resolveDeliveryHost as t, writeSessionInPlace as n } from "./index2.js";
2
- import { ModelSetEvent as r, SessionChangedEvent as i } from "@pie-element/shared-player-events";
3
- export { r as ModelSetEvent, i as SessionChangedEvent, e as forwardSessionChange, t as resolveDeliveryHost, n as writeSessionInPlace };
1
+ import { writeSessionInPlace as e } from "./index2.js";
2
+ import { defineDeliveryElement as t } from "./index3.js";
3
+ import { ModelSetEvent as n, SessionChangedEvent as r } from "@pie-element/shared-player-events";
4
+ export { n as ModelSetEvent, r as SessionChangedEvent, t as defineDeliveryElement, e as writeSessionInPlace };
package/dist/index2.js CHANGED
@@ -1,50 +1,17 @@
1
- import { SessionChangedEvent as e } from "@pie-element/shared-player-events";
2
- //#region src/session-bridge.ts
3
- var t = (e) => {
4
- let t = e;
5
- return t ? typeof t.onSessionChange == "function" || typeof t.onAudioStarted == "function" || typeof t.onAudioEnded == "function" : !1;
6
- };
7
- function n(e) {
8
- if (e.parentElement) return e.parentElement;
9
- let t = e.getRootNode();
10
- return t instanceof ShadowRoot ? t.host : null;
11
- }
12
- function r(e, r = {}) {
13
- let i = r.hostPredicate ?? t, a = e;
14
- for (; a;) {
15
- if (i(a)) return a;
16
- a = n(a);
17
- }
18
- return null;
19
- }
20
- function i(e) {
1
+ //#region src/write-session-in-place.ts
2
+ function e(e) {
21
3
  return !!e && typeof e == "object" && !Array.isArray(e);
22
4
  }
23
- function a(e, t) {
24
- if (e === t) return e;
25
- if (!i(e) || !i(t) || Object.isFrozen(e) || !Object.isExtensible(e)) return t;
5
+ function t(t, n) {
6
+ if (t === n) return t;
7
+ if (!e(t) || !e(n) || Object.isFrozen(t) || !Object.isExtensible(t)) return n;
26
8
  try {
27
- for (let n of Object.keys(e)) n in t || delete e[n];
28
- Object.assign(e, t);
9
+ for (let e of Object.keys(t)) e in n || delete t[e];
10
+ Object.assign(t, n);
29
11
  } catch {
30
- return t;
12
+ return n;
31
13
  }
32
- return e;
33
- }
34
- var o = {}, s = /* @__PURE__ */ new WeakSet();
35
- function c(e) {
36
- let t = e ?? o;
37
- if (s.has(t)) return;
38
- s.add(t);
39
- let n = e ? `above <${e.tagName.toLowerCase()}>` : "for an update with no source element";
40
- console.warn(`[session-bridge] no delivery host ${n}; the session change was not forwarded to the player`);
41
- }
42
- function l({ sourceEl: t, complete: n, session: i }) {
43
- let o = r(t);
44
- if (!o) return c(t), null;
45
- if (typeof o.onSessionChange == "function") return o.onSessionChange(i), o;
46
- let s = a(o.session, i);
47
- return s !== o.session && (o.session = s), o.dispatchEvent(new e(o.tagName.toLowerCase(), n)), o;
14
+ return t;
48
15
  }
49
16
  //#endregion
50
- export { l as forwardSessionChange, r as resolveDeliveryHost, a as writeSessionInPlace };
17
+ export { t as writeSessionInPlace };
package/dist/index3.js ADDED
@@ -0,0 +1,42 @@
1
+ import { writeSessionInPlace as e } from "./index2.js";
2
+ import { ModelSetEvent as t, SessionChangedEvent as n } from "@pie-element/shared-player-events";
3
+ //#region src/delivery-element.ts
4
+ function r(r, i) {
5
+ let a = r.element;
6
+ if (!a) throw TypeError("defineDeliveryElement: the component was not compiled with `customElement`");
7
+ class o extends a {
8
+ #e;
9
+ #t;
10
+ constructor() {
11
+ super(), this.onSessionChange = (e) => {
12
+ this.writeSession(e), this.dispatchSessionChanged();
13
+ };
14
+ }
15
+ set model(e) {
16
+ this.#e = e, super.model = e, queueMicrotask(() => {
17
+ this.dispatchEvent(new t(this.tagName.toLowerCase(), this.isComplete(), this.#e !== void 0));
18
+ });
19
+ }
20
+ get model() {
21
+ return this.#e;
22
+ }
23
+ set session(e) {
24
+ this.#t = e, super.session = e, this.dispatchSessionChanged();
25
+ }
26
+ get session() {
27
+ return this.#t;
28
+ }
29
+ isComplete() {
30
+ return i.isComplete(this.#e, this.#t);
31
+ }
32
+ writeSession(t) {
33
+ this.#t = e(this.#t, t), super.session = t;
34
+ }
35
+ dispatchSessionChanged() {
36
+ this.dispatchEvent(new n(this.tagName.toLowerCase(), this.isComplete()));
37
+ }
38
+ }
39
+ return o;
40
+ }
41
+ //#endregion
42
+ export { r as defineDeliveryElement };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Assign a delivery update into the session object the player owns, keeping the
3
+ * reference.
4
+ *
5
+ * A player hands the element a session object and reads the learner's response
6
+ * back off that same object: `pie-player` pushes its entry into the host's own
7
+ * `session.data` array, and `pie-item-player`'s renderer forwards the array it
8
+ * holds rather than `element.session`. An element that only replaces its own
9
+ * reference leaves the player's entry at its load-time value, so the forwarded
10
+ * container compares equal to the previous one and normalizes to
11
+ * `intent: "metadata-only"` with `session: null` - the element reports a change
12
+ * and the response never arrives. The React elements mutate the session they
13
+ * were given (`updateSessionValue`); this is that contract for the Svelte
14
+ * elements, which additionally hand their component a fresh reference so
15
+ * `$derived` reads of `props.session` still re-run.
16
+ *
17
+ * Keys absent from `next` are removed, so clearing a response clears it on the
18
+ * player's object too. Anything that is not a plain object on both sides is
19
+ * returned as the replacement it already was, and so is a frozen or sealed
20
+ * target: writing into one throws in strict mode, which would take the
21
+ * learner's update with it before the element ever stored it.
22
+ */
23
+ export declare function writeSessionInPlace(target: unknown, next: unknown): unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pie-lib/delivery-events-svelte",
3
- "version": "0.1.1-next.1",
3
+ "version": "0.2.0-next.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/pie-framework/pie-elements-ng.git",
@@ -1,58 +0,0 @@
1
- export type DeliveryHostElement = HTMLElement & {
2
- session?: unknown;
3
- onSessionChange?: (session: unknown) => void;
4
- onAudioStarted?: () => void;
5
- onAudioEnded?: () => void;
6
- };
7
- type HostPredicate = (node: unknown) => boolean;
8
- export interface ResolveDeliveryHostOptions {
9
- hostPredicate?: HostPredicate;
10
- }
11
- /**
12
- * Walk up the DOM from a source element and find the nearest delivery host wrapper.
13
- * The walk continues from a shadow root to its host, so a wrapper that renders the
14
- * element inside its own shadow root is still found.
15
- *
16
- * There is no lookup by tag name: a player registers the element under a tag it
17
- * chooses (versioned, e.g. `simple-cloze--version-0-2-0`), so the element cannot
18
- * know it, and a document-wide query could reach a different instance.
19
- */
20
- export declare function resolveDeliveryHost(sourceEl?: HTMLElement | null, options?: ResolveDeliveryHostOptions): DeliveryHostElement | null;
21
- /**
22
- * Assign a delivery update into the session object the player owns, keeping the
23
- * reference.
24
- *
25
- * A player hands the element a session object and reads the learner's response
26
- * back off that same object: `pie-player` pushes its entry into the host's own
27
- * `session.data` array, and `pie-item-player`'s renderer forwards the array it
28
- * holds rather than `element.session`. An element that only replaces its own
29
- * reference leaves the player's entry at its load-time value, so the forwarded
30
- * container compares equal to the previous one and normalizes to
31
- * `intent: "metadata-only"` with `session: null` - the element reports a change
32
- * and the response never arrives. The React elements mutate the session they
33
- * were given (`updateSessionValue`); this is that contract for the Svelte
34
- * elements, which additionally hand their component a fresh reference so
35
- * `$derived` reads of `props.session` still re-run.
36
- *
37
- * Keys absent from `next` are removed, so clearing a response clears it on the
38
- * player's object too. Anything that is not a plain object on both sides is
39
- * returned as the replacement it already was, and so is a frozen or sealed
40
- * target: writing into one throws in strict mode, which would take the
41
- * learner's update with it before the element ever stored it.
42
- */
43
- export declare function writeSessionInPlace(target: unknown, next: unknown): unknown;
44
- export interface ForwardSessionChangeOptions {
45
- sourceEl?: HTMLElement | null;
46
- complete: boolean;
47
- session: unknown;
48
- }
49
- /**
50
- * Forward a delivery session update using the host callback when available.
51
- * If no callback is exposed, write the update into the host's session, as
52
- * `writeSessionInPlace` does for a wrapper, and dispatch the canonical
53
- * session-changed metadata event, named for the tag the host was registered
54
- * under: the event carries no session, so a player reads the response off it.
55
- * Returns `null`, and warns, when the source element has no delivery host.
56
- */
57
- export declare function forwardSessionChange({ sourceEl, complete, session, }: ForwardSessionChangeOptions): DeliveryHostElement | null;
58
- export {};