@tempots/dom 24.0.0-next.2 → 24.0.0-next.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tempots/dom",
3
- "version": "24.0.0-next.2",
3
+ "version": "24.0.0-next.21",
4
4
  "type": "module",
5
5
  "main": "./index.cjs",
6
6
  "module": "./index.js",
@@ -37,12 +37,12 @@ export type UseMany<C extends Record<string, Consumer<unknown>>> = {
37
37
  /**
38
38
  * Creates a renderable function that consumes data from multiple consumers and renders the result.
39
39
  *
40
- * @param consumers - An object containing consumer functions.
40
+ * @param providers - An object containing consumer functions.
41
41
  * @param fn - A function that receives the data from the consumers and returns a renderable function.
42
42
  * @returns A renderable function that can be called with a DOMContext and returns a cleanup function.
43
43
  * @public
44
44
  */
45
- export declare const Use: <C extends Record<string, Consumer<unknown>>>(consumers: C, fn: (data: UseMany<C>) => Renderable) => Renderable;
45
+ export declare const Use: <C extends Record<string, Consumer<unknown>>>(providers: C, fn: (data: UseMany<C>) => Renderable) => Renderable;
46
46
  /**
47
47
  * Creates a renderable function that consumes a provider value and renders a `TNode`.
48
48
  *
@@ -1,6 +1,12 @@
1
1
  import { TNode, Renderable } from '../types/domain';
2
2
  import { Signal } from '../std/signal';
3
3
  import { Value } from '../std/value';
4
+ export type NillifyValue<T> = Value<T | null | undefined> | Value<T | undefined> | Value<T | null>;
5
+ export type Id<T> = {} & {
6
+ [P in keyof T]: T[P];
7
+ };
8
+ export type Merge<A, B> = Id<A & B>;
9
+ export type NonNillable<T> = Merge<T, {}>;
4
10
  /**
5
11
  * Represents a function that ensures a signal has a value before rendering a TNode.
6
12
  *
@@ -11,4 +17,12 @@ import { Value } from '../std/value';
11
17
  * @returns A renderable function that ensures the signal has a value before rendering a TNode.
12
18
  * @public
13
19
  */
14
- export declare const Ensure: <T>(value: Value<T | null> | Value<T | undefined> | Value<T | null | undefined>, then: (value: Signal<NonNullable<T>>) => TNode, otherwise?: () => TNode) => Renderable;
20
+ export declare const Ensure: <T>(value: NillifyValue<T>, then: (value: Signal<NonNillable<T>>) => TNode, otherwise?: () => TNode) => Renderable;
21
+ /**
22
+ * Ensures that all signals have a value before rendering a TNode.
23
+ *
24
+ * @param signals - The signals to ensure have a value.
25
+ * @returns A renderable function that ensures all signals have a value before rendering a TNode.
26
+ * @public
27
+ */
28
+ export declare const EnsureAll: <T extends readonly Value<any>[]>(...signals: { [K in keyof T]: NillifyValue<T[K]>; }) => (callback: (...values: { [K in keyof T]: Signal<NonNillable<T[K] extends Value<infer U> ? U : never>>; }) => TNode, otherwise?: () => TNode) => Renderable;
@@ -1,4 +1,4 @@
1
- import { Renderable } from '../types/domain';
1
+ import { Renderable, TNode } from '../types/domain';
2
2
  import { Value } from '../std/value';
3
3
  /**
4
4
  * Maps the values emitted by a signal to a renderable function and returns a new renderable function.
@@ -11,8 +11,8 @@ import { Value } from '../std/value';
11
11
  *
12
12
  * @typeParam T - The type of values emitted by the signal.
13
13
  * @param vlaue - The signal or value to map.
14
- * @param fn - The function to map the signal values to renderable functions.
14
+ * @param fn - The function to map the signal values to a renderable/TNode.
15
15
  * @returns - A new renderable function that represents the mapped signal.
16
16
  * @public
17
17
  */
18
- export declare const MapSignal: <T>(value: Value<T>, fn: (value: T) => Renderable) => Renderable;
18
+ export declare const MapSignal: <T>(value: Value<T>, fn: (value: T) => TNode) => Renderable;
@@ -1,9 +1,10 @@
1
1
  import { Renderable } from '../types/domain';
2
2
  import { DOMContext } from '../dom/dom-context';
3
+ export type DisposeCallback = (removeTree: boolean, ctx: DOMContext) => void;
3
4
  /**
4
5
  * Creates a renderable function that will be called when the component is unmounted.
5
- * @param fn - The function to be called when the component is unmounted.
6
+ * @param fns - The function(s) to be called when the component is unmounted.
6
7
  * @returns A renderable function that takes a DOMContext and returns a function that takes a boolean indicating whether to remove the tree.
7
8
  * @public
8
9
  */
9
- export declare const OnDispose: (fn: (removeTree: boolean, ctx: DOMContext) => void) => Renderable;
10
+ export declare const OnDispose: (...fns: DisposeCallback[]) => Renderable;
@@ -9,6 +9,16 @@ import { Renderable, TNode } from '../types/domain';
9
9
  export type OneOfOptions<T extends Record<string, unknown>> = {
10
10
  [KK in keyof T]: (value: Signal<T[KK]>) => TNode;
11
11
  };
12
+ /**
13
+ * Converts an object to a union of its keys.
14
+ * @typeParam T - The type of the object.
15
+ * @public
16
+ */
17
+ export type ObjectToUnion<T> = {
18
+ [K in keyof T]: {
19
+ [P in K]: T[K];
20
+ };
21
+ }[keyof T];
12
22
  /**
13
23
  * Creates a renderable function that renders different components based on the value of a signal.
14
24
  *
@@ -3,7 +3,8 @@ import { Renderable, TNode } from '../types/domain';
3
3
  * A provider mark for a signal representing the current appearance type.
4
4
  * @public
5
5
  */
6
- export declare const probeMarker: import('../types/domain').ProviderMark<(identifier: symbol) => void>;
6
+ export declare const probeMarker: import('..').ProviderMark<(identifier: symbol) => void>;
7
+ export type ProbeResolution = 'resolved' | 'timeout';
7
8
  /**
8
9
  * Provides a child component with a probe, which can be used to trigger a callback when all probes with the same identifier are resolved.
9
10
  * To resolve a probe, call the `done` function passed using the `UseProbe` renderable.
@@ -14,7 +15,12 @@ export declare const probeMarker: import('../types/domain').ProviderMark<(identi
14
15
  * @returns The child component with the probe.
15
16
  * @public
16
17
  */
17
- export declare const ProvideProbe: (identifier: symbol, callback: () => void, child: TNode) => Renderable;
18
+ export declare const ProvideProbe: ({ identifier, callback, child, timeout, }: {
19
+ identifier: symbol;
20
+ callback?: (resolution: ProbeResolution) => void;
21
+ child: TNode;
22
+ timeout?: number;
23
+ }) => Renderable;
18
24
  /**
19
25
  * Uses a probe, which can be used to trigger a callback when all probes with the same identifier are resolved.
20
26
  * To resolve a probe, call the `done` function.
@@ -34,7 +40,10 @@ export declare const UseProbe: (identifier: symbol, fn: (done: () => void) => TN
34
40
  * @returns The child component with the probe.
35
41
  * @public
36
42
  */
37
- export declare const ProvideGlobalProbe: (callback: () => void, child: TNode) => Renderable;
43
+ export declare const ProvideGlobalProbe: ({ callback, timeout, }: {
44
+ callback?: (resolution: ProbeResolution) => void;
45
+ timeout?: number;
46
+ }, child: TNode) => Renderable;
38
47
  /**
39
48
  * Uses a global probe, which can be used to trigger a callback when all probes with the same identifier are resolved.
40
49
  * To resolve a probe, call the `done` function.
@@ -36,6 +36,16 @@ export type RenderOptions = {
36
36
  * @public
37
37
  */
38
38
  export declare const render: (node: Renderable, parent: Node | string, { doc, clear }?: RenderOptions) => () => void;
39
+ /**
40
+ * Runs a renderable function in a headless environment.
41
+ *
42
+ * @param makeRenderable - A function that returns a Renderable to be rendered in the headless environment.
43
+ * @param options - Optional configuration for the headless environment.
44
+ * @param options.startUrl - The initial URL for the headless environment. Defaults to 'https://example.com'.
45
+ * @param options.selector - The selector used to find the root element in the headless environment. Defaults to ':root'.
46
+ * @returns An object containing the clear function, root element, and current URL Signal of the headless environment.
47
+ * @public
48
+ */
39
49
  export declare const runHeadless: (makeRenderable: () => Renderable, { startUrl, selector, }?: {
40
50
  startUrl?: Value<string>;
41
51
  selector?: string;
@@ -51,3 +61,173 @@ export declare const runHeadless: (makeRenderable: () => Renderable, { startUrl,
51
61
  export declare class RenderingError extends Error {
52
62
  constructor(message: string);
53
63
  }
64
+ /**
65
+ * @internal
66
+ */
67
+ export declare const _NODE_PLACEHOLDER_ATTR = "data-tts-node";
68
+ export declare const CLASS_PLACEHOLDER_ATTR = "data-tts-class";
69
+ /**
70
+ * Represents an adapter for headless rendering environments.
71
+ * This class provides methods to interact with elements in a headless context.
72
+ *
73
+ * This class is used to adapt the HeadlesContext to whatever you want to use to render your final HTML.
74
+ * You can use libraries like cheerio to render your HTML.
75
+ *
76
+ * For cheerio an adapter could look like this:
77
+ *
78
+ * ```ts
79
+ * const renderWithCheerio = (html: string, root: HeadlessPortal) => {
80
+ * const $ = cheerio.load(html)
81
+ *
82
+ * // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
+ * const adapter = new HeadlessAdapter<cheerio.Cheerio<any>>({
84
+ * // eslint-disable-next-line @typescript-eslint/no-explicit-any
85
+ * select: (selector: string): cheerio.Cheerio<any>[] => [$(selector)],
86
+ * getAttribute: (el, name: string) => el.attr(name) ?? null,
87
+ * setAttribute: (el, name: string, value: string | null) => {
88
+ * if (value === null) {
89
+ * el.removeAttr(name)
90
+ * } else {
91
+ * el.attr(name, value)
92
+ * }
93
+ * },
94
+ * getClass: el => el.attr('class') ?? '',
95
+ * setClass: (el, value: string | null) => {
96
+ * if (value === null) {
97
+ * el.removeAttr('class')
98
+ * } else {
99
+ * el.attr('class', value)
100
+ * }
101
+ * },
102
+ * getStyles: el => el.attr('style') ?? {},
103
+ * setStyles: (el, value: Record<string, string>) => {
104
+ * if (Object.keys(value).length === 0) {
105
+ * el.removeAttr('style')
106
+ * } else {
107
+ * el.css(value)
108
+ * }
109
+ * },
110
+ * appendHTML: (el, html) => el.append(html),
111
+ * getInnerHTML: el => el.html() ?? '',
112
+ * setInnerHTML: (el, html) => el.html(html),
113
+ * getInnerText: el => el.text() ?? '',
114
+ * setInnerText: (el, text) => el.text(text),
115
+ * })
116
+ *
117
+ * adapter.setFromRoot(root, true)
118
+ *
119
+ * return $.html()
120
+ * }
121
+ * ```
122
+ *
123
+ * This function will return the rendered HTML as a string.
124
+ *
125
+ * @typeParam EL - The type of elements in the headless environment.
126
+ * @public
127
+ */
128
+ export declare class HeadlessAdapter<EL> {
129
+ /**
130
+ * Selects elements from the headless environment.
131
+ * @param selector - The selector to select elements from. The supported selectors are CSS selectors whose complexity depends on the adapter implementation.
132
+ * @returns An array of elements.
133
+ */
134
+ readonly select: (selector: string) => EL[];
135
+ /**
136
+ * Gets the value of an attribute from an element.
137
+ * @param el - The element to get the attribute from.
138
+ * @param attr - The attribute to get the value from.
139
+ * @returns The value of the attribute or null if the attribute is not set.
140
+ */
141
+ readonly getAttribute: (el: EL, attr: string) => string | null;
142
+ /**
143
+ * Sets the value of an attribute on an element.
144
+ * @param el - The element to set the attribute on.
145
+ * @param attr - The attribute to set the value of.
146
+ * @param value - The value to set the attribute to.
147
+ */
148
+ readonly setAttribute: (el: EL, attr: string, value: string | null) => void;
149
+ /**
150
+ * Gets the class of an element.
151
+ * @param el - The element to get the class from.
152
+ * @returns The class of the element or an empty string if the class is not set.
153
+ */
154
+ readonly getClass: (el: EL) => string | null;
155
+ /**
156
+ * Sets the class of an element.
157
+ * @param el - The element to set the class on.
158
+ * @param cls - The class to set.
159
+ */
160
+ readonly setClass: (el: EL, cls: string | null) => void;
161
+ /**
162
+ * Gets the styles of an element.
163
+ * @param el - The element to get the styles from.
164
+ * @returns The styles of the element.
165
+ */
166
+ readonly getStyles: (el: EL) => Record<string, string>;
167
+ /**
168
+ * Sets the styles of an element.
169
+ * @param el - The element to set the styles on.
170
+ */
171
+ readonly setStyles: (el: EL, styles: Record<string, string>) => void;
172
+ /**
173
+ * Appends HTML to an element.
174
+ * @param el - The element to append the HTML to.
175
+ * @param html - The HTML to append.
176
+ */
177
+ readonly appendHTML: (el: EL, html: string) => void;
178
+ /**
179
+ * Gets the inner HTML of an element.
180
+ * @param el - The element to get the inner HTML from.
181
+ * @returns The inner HTML of the element or an empty string if the inner HTML is not set.
182
+ */
183
+ readonly getInnerHTML: (el: EL) => string | null;
184
+ /**
185
+ * Sets the inner HTML of an element.
186
+ * @param el - The element to set the inner HTML on.
187
+ * @param html - The inner HTML to set.
188
+ */
189
+ readonly setInnerHTML: (el: EL, html: string) => void;
190
+ /**
191
+ * Gets the inner text of an element.
192
+ * @param el - The element to get the inner text from.
193
+ * @returns The inner text of the element or an empty string if the inner text is not set.
194
+ */
195
+ readonly getInnerText: (el: EL) => string | null;
196
+ /**
197
+ * Sets the inner text of an element.
198
+ * @param el - The element to set the inner text on.
199
+ * @param text - The inner text to set.
200
+ */
201
+ readonly setInnerText: (el: EL, text: string) => void;
202
+ constructor({ select, getAttribute, setAttribute, getClass, setClass, getStyles, setStyles, appendHTML, getInnerHTML, setInnerHTML, getInnerText, setInnerText, }: {
203
+ select: (selector: string) => EL[];
204
+ getAttribute: (el: EL, attr: string) => string | null;
205
+ setAttribute: (el: EL, attr: string, value: string | null) => void;
206
+ getClass: (el: EL) => string | null;
207
+ setClass: (el: EL, cls: string | null) => void;
208
+ getStyles: (el: EL) => Record<string, string>;
209
+ setStyles: (el: EL, styles: Record<string, string>) => void;
210
+ appendHTML: (el: EL, html: string) => void;
211
+ getInnerHTML: (el: EL) => string | null;
212
+ setInnerHTML: (el: EL, html: string) => void;
213
+ getInnerText: (el: EL) => string | null;
214
+ setInnerText: (el: EL, text: string) => void;
215
+ });
216
+ /**
217
+ * Sets the content of the root element from a HeadlessPortal. Generally this will be the same instance that is
218
+ * returned by `runHeadless`.
219
+ *
220
+ * @param root - The HeadlessPortal containing the content to set.
221
+ * @param setPlaceholders - Whether to set placeholders for the content. This allows you to restore the original content
222
+ * when you render on the server and then hydrate on the client.
223
+ */
224
+ readonly setFromRoot: (root: HeadlessPortal, setPlaceholders: boolean) => void;
225
+ }
226
+ /**
227
+ * Restores all placeholders in the DOM. This function is useful when the HTML is rendered on the server and then
228
+ * hydrated on the client. It restores the original content that was replaced with placeholders during the initial
229
+ * render. When you render on the server side, make sure to call `HeadlessAdapter.setFromRoot` with the result of
230
+ * `runHeadless` and the second parameter `setPlaceholders` to `true`.
231
+ * @public
232
+ */
233
+ export declare const restoreTempoPlaceholders: () => void;
@@ -5,7 +5,6 @@ import { NValue, Renderable } from '../types/domain';
5
5
  */
6
6
  export declare const style: {
7
7
  all: (value: NValue<string>) => Renderable;
8
- [Symbol.iterator]: (value: NValue<string>) => Renderable;
9
8
  accentColor: (value: NValue<string>) => Renderable;
10
9
  alignContent: (value: NValue<string>) => Renderable;
11
10
  alignItems: (value: NValue<string>) => Renderable;
@@ -327,6 +326,7 @@ export declare const style: {
327
326
  right: (value: NValue<string>) => Renderable;
328
327
  rotate: (value: NValue<string>) => Renderable;
329
328
  rowGap: (value: NValue<string>) => Renderable;
329
+ rubyAlign: (value: NValue<string>) => Renderable;
330
330
  rubyPosition: (value: NValue<string>) => Renderable;
331
331
  rx: (value: NValue<string>) => Renderable;
332
332
  ry: (value: NValue<string>) => Renderable;
@@ -418,6 +418,7 @@ export declare const style: {
418
418
  userSelect: (value: NValue<string>) => Renderable;
419
419
  vectorEffect: (value: NValue<string>) => Renderable;
420
420
  verticalAlign: (value: NValue<string>) => Renderable;
421
+ viewTransitionName: (value: NValue<string>) => Renderable;
421
422
  visibility: (value: NValue<string>) => Renderable;
422
423
  webkitAlignContent: (value: NValue<string>) => Renderable;
423
424
  webkitAlignItems: (value: NValue<string>) => Renderable;
package/std/signal.d.ts CHANGED
@@ -14,6 +14,11 @@ export type AnySignal<T = any> = Signal<T> | Prop<T> | Computed<T>;
14
14
  export type AtGetter<T> = {
15
15
  [K in keyof T]-?: Signal<T[K]>;
16
16
  };
17
+ export type ListenerOptions = {
18
+ skipInitial?: boolean;
19
+ once?: boolean;
20
+ abortSignal?: AbortSignal;
21
+ };
17
22
  /**
18
23
  * Represents a signal that holds a value and notifies its listeners when the value changes.
19
24
  * @typeParam T - The type of the value held by the signal.
@@ -54,7 +59,7 @@ export declare class Signal<T> {
54
59
  /**
55
60
  * @internal
56
61
  */
57
- protected readonly _onValueListeners: Array<(value: T) => void>;
62
+ protected readonly _onValueListeners: Array<(value: T, previousValue: T | undefined) => void>;
58
63
  /**
59
64
  * @internal
60
65
  */
@@ -88,8 +93,9 @@ export declare class Signal<T> {
88
93
  * Returns a function that can be called to unregister the listener.
89
94
  *
90
95
  * @param listener - The listener function to be called when the value of the signal changes.
96
+ * @param options - Options for the listener.
91
97
  */
92
- readonly on: (listener: (value: T) => void) => () => void;
98
+ readonly on: (listener: (value: T, previousValue: T | undefined) => void, options?: ListenerOptions) => () => void;
93
99
  /**
94
100
  * @internal
95
101
  */
@@ -205,10 +211,20 @@ export declare class Signal<T> {
205
211
  readonly feedProp: (prop: Prop<T>, autoDisposeProp?: boolean) => Prop<T>;
206
212
  /**
207
213
  * Derives a new property from the current signal.
208
- * @param autoDisposeProp - Determines whether the derived property should be automatically disposed.
214
+ * @param options - The options for the derived property.
215
+ * @param options.autoDisposeProp - Determines whether the derived property should be automatically disposed.
216
+ * @param options.equals - A function that determines if two values are equal.
209
217
  * @returns The derived property.
210
218
  */
211
- readonly deriveProp: (autoDisposeProp?: boolean) => Prop<T>;
219
+ readonly deriveProp: ({ autoDisposeProp, equals, }?: {
220
+ autoDisposeProp?: boolean;
221
+ equals?: (a: T, b: T) => boolean;
222
+ }) => Prop<T>;
223
+ /**
224
+ * Derives a new signal from the current signal. Useful to create a new signal that emits the same values as the current signal but can be disposed independently.
225
+ * @returns A new signal that emits the same values as the current signal.
226
+ */
227
+ readonly derive: () => Computed<T>;
212
228
  /**
213
229
  * Returns a signal that emits the count of values received so far.
214
230
  * @returns A signal that emits the count of values received so far.
@@ -391,7 +407,7 @@ export declare const makeComputed: <T>(fn: () => T, dependencies: Array<AnySigna
391
407
  * @returns A disposable object that can be used to stop the effect.
392
408
  * @public
393
409
  */
394
- export declare const makeEffect: (fn: () => void, signals: Array<AnySignal>) => () => void;
410
+ export declare const makeEffect: (fn: () => void, signals: Array<AnySignal>, options?: ListenerOptions) => () => void;
395
411
  /**
396
412
  * Creates a new Prop object with the specified value and equality function.
397
413
  *
package/std/value.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { GetValueTypes } from '../types/domain';
2
- import { Signal } from './signal';
2
+ import { ListenerOptions, Prop, Signal } from './signal';
3
3
  /**
4
4
  * Represents a value that can either be a `Signal<T>` or a generic type `T`.
5
5
  *
@@ -57,6 +57,20 @@ export declare const Value: {
57
57
  * @param value - The value or Signal instance to dispose of.
58
58
  */
59
59
  dispose: <T>(value: Value<T>) => void;
60
+ /**
61
+ * Derives a Prop from a Signal.
62
+ * If the value is a Signal, it returns a new Prop with the derived value.
63
+ * If the value is not a Signal, it returns a new Prop with the value.
64
+ * @param value - The value or Signal instance to derive the Prop from.
65
+ * @param options - The options for the derived Prop.
66
+ * @param options.autoDisposeProp - Determines whether the derived Prop should be automatically disposed.
67
+ * @param options.equals - A function that determines if two values are equal.
68
+ * @returns A Prop instance.
69
+ */
70
+ deriveProp: <T>(value: Value<T>, { autoDisposeProp, equals, }?: {
71
+ autoDisposeProp?: boolean;
72
+ equals?: (a: T, b: T) => boolean;
73
+ }) => Prop<T>;
60
74
  };
61
75
  /**
62
76
  * Creates a computed signal that depends on other signals or literal values and updates when any of the dependencies change.
@@ -75,4 +89,4 @@ export declare const makeComputedOf: <T extends Value<unknown>[]>(...args: T) =>
75
89
  * @returns A disposable object that can be used to stop the effect.
76
90
  * @public
77
91
  */
78
- export declare const makeEffectOf: <T extends Value<unknown>[]>(...args: T) => (fn: (...args: GetValueTypes<T>) => void) => void;
92
+ export declare const makeEffectOf: <T extends Value<unknown>[]>(...args: T) => (fn: (...args: GetValueTypes<T>) => void, options?: ListenerOptions) => () => void;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * @public
5
5
  */
6
- export type ExcludeFromStyle = 'getPropertyPriority' | 'getPropertyValue' | 'item' | 'removeProperty' | 'setProperty' | 'parentRule' | 'length' | 'name' | number;
6
+ export type ExcludeFromStyle = 'getPropertyPriority' | 'getPropertyValue' | 'item' | 'removeProperty' | 'setProperty' | 'parentRule' | 'length' | 'name' | number | typeof Symbol.iterator;
7
7
  /**
8
8
  * Represents a subset of CSS styles.
9
9
  * It is a type that excludes certain properties from the `CSSStyleDeclaration` type.