diff --git a/packages/rdom/package.json b/packages/rdom/package.json index 1cae3136c8..282c69db78 100644 --- a/packages/rdom/package.json +++ b/packages/rdom/package.json @@ -101,6 +101,9 @@ "./event": { "default": "./event.js" }, + "./idgen": { + "default": "./idgen.js" + }, "./klist": { "default": "./klist.js" }, diff --git a/packages/rdom/src/idgen.ts b/packages/rdom/src/idgen.ts new file mode 100644 index 0000000000..d6981c902d --- /dev/null +++ b/packages/rdom/src/idgen.ts @@ -0,0 +1,7 @@ +import type { ISubscribable } from "@thi.ng/rstream"; + +let NEXT_ID = 0; + +/** @internal */ +export const __nextID = (name: string, src?: ISubscribable) => + src ? `rdom$${name}-${src.id}-${NEXT_ID++}` : `rdom$${name}-${NEXT_ID++}`; diff --git a/packages/rdom/src/index.ts b/packages/rdom/src/index.ts index b012014e1d..ab893a1fe4 100644 --- a/packages/rdom/src/index.ts +++ b/packages/rdom/src/index.ts @@ -4,6 +4,7 @@ export * from "./compile.js"; export * from "./component.js"; export * from "./dom.js"; export * from "./event.js"; +export * from "./idgen.js"; export * from "./klist.js"; export * from "./list.js"; export * from "./object.js"; diff --git a/packages/rdom/src/klist.ts b/packages/rdom/src/klist.ts index 859edf3dba..8bf2fcf6b7 100644 --- a/packages/rdom/src/klist.ts +++ b/packages/rdom/src/klist.ts @@ -1,11 +1,11 @@ import type { Fn, Fn2, NumOrString } from "@thi.ng/api"; import type { ISubscribable } from "@thi.ng/rstream"; -import { __nextID } from "@thi.ng/rstream/idgen"; import type { IComponent, IMountWithState, NumOrElement } from "./api.js"; import { $compile } from "./compile.js"; import { Component } from "./component.js"; import { $moveTo } from "./dom.js"; -import { $Sub } from "./sub.js"; +import { __nextID } from "./idgen.js"; +import { $subWithID } from "./sub.js"; interface KListItem { k: NumOrString; @@ -71,11 +71,10 @@ export const $klist = ( childCtor: Fn, keyFn?: Fn2 ) => - src.subscribe( - new $Sub( - new KList(tag, attribs, childCtor, keyFn), - `rdom$klist-${src.id}-${__nextID()}` - ) + $subWithID( + src, + new KList(tag, attribs, childCtor, keyFn), + __nextID("klist", src) ); export class KList extends Component implements IMountWithState { diff --git a/packages/rdom/src/list.ts b/packages/rdom/src/list.ts index 9cfa027d88..b351f2ed44 100644 --- a/packages/rdom/src/list.ts +++ b/packages/rdom/src/list.ts @@ -1,10 +1,10 @@ import type { Fn, Predicate2 } from "@thi.ng/api"; import type { ISubscribable } from "@thi.ng/rstream"; -import { __nextID } from "@thi.ng/rstream/idgen"; import type { IComponent, IMountWithState, NumOrElement } from "./api.js"; import { $compile } from "./compile.js"; import { Component } from "./component.js"; -import { $Sub } from "./sub.js"; +import { __nextID } from "./idgen.js"; +import { $subWithID } from "./sub.js"; /** * Creates a generalized and dynamically updating list component from items of @@ -60,11 +60,10 @@ export const $list = ( ctor: Fn, equiv?: Predicate2 ) => - src.subscribe( - new $Sub( - new List(tag, attribs, ctor, equiv), - `rdom$list-${src.id}-${__nextID()}` - ) + $subWithID( + src, + new List(tag, attribs, ctor, equiv), + __nextID("list", src) ); export class List extends Component implements IMountWithState { diff --git a/packages/rdom/src/object.ts b/packages/rdom/src/object.ts index 15a9df2aa2..09bc7e6102 100644 --- a/packages/rdom/src/object.ts +++ b/packages/rdom/src/object.ts @@ -8,7 +8,8 @@ import type { NumOrElement, } from "./api.js"; import { Component } from "./component.js"; -import { $sub } from "./sub.js"; +import { __nextID } from "./idgen.js"; +import { $subWithID } from "./sub.js"; /** * Creates a control component wrapper with an internal stream setup for user @@ -91,7 +92,12 @@ export const $subObject = >( src: ISubscribable, opts: Partial>, inner: Fn["streams"], Promise> -) => $sub(src, $object(src.deref() || {}, opts, inner)); +) => + $subWithID( + src, + $object(src.deref() || {}, opts, inner), + __nextID("obj", src) + ); export class $Object> extends Component diff --git a/packages/rdom/src/replace.ts b/packages/rdom/src/replace.ts index f10bbf2b9d..af637caf1e 100644 --- a/packages/rdom/src/replace.ts +++ b/packages/rdom/src/replace.ts @@ -2,7 +2,8 @@ import type { ISubscribable } from "@thi.ng/rstream"; import type { IComponent, IMountWithState, NumOrElement } from "./api.js"; import { $compile } from "./compile.js"; import { Component } from "./component.js"; -import { $sub } from "./sub.js"; +import { __nextID } from "./idgen.js"; +import { $subWithID } from "./sub.js"; import { $wrapText } from "./wrap.js"; /** @@ -38,7 +39,7 @@ import { $wrapText } from "./wrap.js"; * @param src - */ export const $replace = (src: ISubscribable) => - $sub(src, new Replace()); + $subWithID(src, new Replace(), __nextID("replace", src)); export class Replace extends Component implements IMountWithState { protected parent?: Element; diff --git a/packages/rdom/src/sub.ts b/packages/rdom/src/sub.ts index d880e08e95..dc547112a9 100644 --- a/packages/rdom/src/sub.ts +++ b/packages/rdom/src/sub.ts @@ -52,6 +52,21 @@ export function $sub( ); } +/** + * Version of {@link $sub} which supports specifying an rstream stream ID for + * the resulting subscription (useful for debugging/visualizing the reactive + * graph topology). + * + * @param src + * @param inner + * @param id + */ +export const $subWithID = ( + src: ISubscribable, + inner: IMountWithState, + id: string +): IComponent => <$Sub>src.subscribe(new $Sub(inner, id)); + export class $Sub extends Subscription { el?: Element; diff --git a/packages/rdom/src/switch.ts b/packages/rdom/src/switch.ts index f2ef7caeda..b50c6c9870 100644 --- a/packages/rdom/src/switch.ts +++ b/packages/rdom/src/switch.ts @@ -4,7 +4,8 @@ import type { ISubscribable } from "@thi.ng/rstream"; import type { IComponent, IMountWithState, NumOrElement } from "./api.js"; import { $compile } from "./compile.js"; import { Component } from "./component.js"; -import { $sub } from "./sub.js"; +import { __nextID } from "./idgen.js"; +import { $subWithID } from "./sub.js"; import { $wrapText } from "./wrap.js"; /** @@ -65,7 +66,12 @@ export const $switch = ( ctors: Record>>, error?: Fn>, loader?: Fn> -) => $sub(src, new Switch(keyFn, ctors, error, loader)); +) => + $subWithID( + src, + new Switch(keyFn, ctors, error, loader), + __nextID("switch", src) + ); /** * Syntax sugar for {@link $switch} for cases when there's only a single @@ -79,6 +85,8 @@ export const $switch = ( * `$compile`d and then getting re-mounted. See {@link $switch} for * further details. * + * Also see {@link $replace}. + * * @example * ```ts * $refresh(fromInterval(1000), async (x) => ["div", {}, x]) @@ -94,7 +102,12 @@ export const $refresh = ( ctor: Fn>, error?: Fn>, loader?: Fn> -) => $switch(src, () => 0, { 0: ctor }, error, loader); +) => + $subWithID( + src, + new Switch(() => 0, { 0: ctor }, error, loader), + __nextID("refresh", src) + ); export class Switch extends Component implements IMountWithState { protected val?: T;