@tempots/dom 26.11.0 → 28.0.0

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": "26.11.0",
3
+ "version": "28.0.0",
4
4
  "type": "module",
5
5
  "main": "./index.cjs",
6
6
  "module": "./index.js",
@@ -8,21 +8,84 @@ export type Id<T> = {} & {
8
8
  export type Merge<A, B> = Id<A & B>;
9
9
  export type NonNillable<T> = Merge<T, {}>;
10
10
  /**
11
- * Represents a function that ensures a signal has a value before rendering a TNode.
11
+ * Conditionally renders content based on whether a value is non-null/non-undefined.
12
12
  *
13
- * @typeParam T - The type of the signal value.
14
- * @param value - The signal or literal that may hold a value of type T or null or undefined.
15
- * @param then - The function that returns a TNode when the signal has a value. It takes a signal of the non-nullable type of T.
16
- * @param otherwise - The function that returns a TNode when the signal does not have a value.
17
- * @returns A renderable function that ensures the signal has a value before rendering a TNode.
13
+ * This function provides a type-safe way to handle nullable values in your UI. It only
14
+ * renders the `then` content when the value is not null or undefined, and optionally
15
+ * renders alternative content when the value is null/undefined.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * // With a signal that might be null
20
+ * const user = prop<User | null>(null)
21
+ *
22
+ * Ensure(user,
23
+ * (userSignal) => html.div('Welcome, ', userSignal.map(u => u.name)),
24
+ * () => html.div('Please log in')
25
+ * )
26
+ * ```
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * // With a literal value
31
+ * const maybeData = getData() // returns string | null
32
+ *
33
+ * Ensure(maybeData,
34
+ * (dataSignal) => html.div('Data: ', dataSignal),
35
+ * () => html.div('No data available')
36
+ * )
37
+ * ```
38
+ *
39
+ * @typeParam T - The type of the value when it's not null/undefined
40
+ * @param value - A signal or literal value that may be null or undefined
41
+ * @param then - Function that receives a signal of the non-nullable value and returns content to render
42
+ * @param otherwise - Optional function that returns content to render when value is null/undefined
43
+ * @returns A renderable that conditionally displays content based on the value's nullability
18
44
  * @public
19
45
  */
20
46
  export declare const Ensure: <T>(value: NillifyValue<T>, then: (value: Signal<NonNillable<T>>) => TNode, otherwise?: () => TNode) => Renderable;
21
47
  /**
22
- * Ensures that all signals have a value before rendering a TNode.
48
+ * Conditionally renders content only when ALL provided values are non-null/non-undefined.
49
+ *
50
+ * This function is useful when you need multiple values to be present before rendering content.
51
+ * It waits for all values to be non-null/non-undefined before calling the callback function.
52
+ * If any value becomes null/undefined, it will render the `otherwise` content instead.
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const user = prop<User | null>(null)
57
+ * const profile = prop<Profile | null>(null)
58
+ * const settings = prop<Settings | null>(null)
59
+ *
60
+ * EnsureAll(user, profile, settings)(
61
+ * (userSignal, profileSignal, settingsSignal) => html.div(
62
+ * html.h1('Dashboard'),
63
+ * html.div('User: ', userSignal.map(u => u.name)),
64
+ * html.div('Profile: ', profileSignal.map(p => p.bio)),
65
+ * html.div('Theme: ', settingsSignal.map(s => s.theme))
66
+ * ),
67
+ * () => html.div('Loading user data...')
68
+ * )
69
+ * ```
70
+ *
71
+ * @example
72
+ * ```typescript
73
+ * // Mix of signals and literal values
74
+ * const apiData = prop<Data | null>(null)
75
+ * const staticConfig = { theme: 'dark' }
76
+ *
77
+ * EnsureAll(apiData, staticConfig)(
78
+ * (dataSignal, configSignal) => html.div(
79
+ * 'Data loaded with theme: ',
80
+ * configSignal.map(c => c.theme)
81
+ * ),
82
+ * () => html.div('Waiting for data...')
83
+ * )
84
+ * ```
23
85
  *
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.
86
+ * @typeParam T - Tuple type representing the types of all input values
87
+ * @param signals - Variable number of values (signals or literals) that may be null/undefined
88
+ * @returns A function that takes a callback and optional otherwise function, returning a renderable
26
89
  * @public
27
90
  */
28
91
  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;
@@ -3,13 +3,63 @@ import { Signal } from '../std/signal';
3
3
  import { ElementPosition } from '../std/element-position';
4
4
  import { Value } from '../std/value';
5
5
  /**
6
- * Renders a list of items based on a signal of arrays.
6
+ * Efficiently renders a dynamic list of items from an array signal.
7
7
  *
8
- * @typeParam T - The type of items in the array.
9
- * @param value - The signal of arrays to iterate over.
10
- * @param item - The function that renders each item in the array.
11
- * @param separator - The function that renders the separator between items.
12
- * @returns - The renderable function that renders the list of items.
8
+ * This function creates a reactive list that automatically updates when the source array changes.
9
+ * Each item in the array gets its own signal that tracks changes to that specific item.
10
+ * The list efficiently handles additions, removals, and modifications to the array.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const todos = prop([
15
+ * { id: 1, text: 'Learn Tempo', done: false },
16
+ * { id: 2, text: 'Build an app', done: false }
17
+ * ])
18
+ *
19
+ * ForEach(todos,
20
+ * (todoSignal, position) => html.div(
21
+ * html.input(
22
+ * attr.type('checkbox'),
23
+ * attr.checked(todoSignal.map(t => t.done))
24
+ * ),
25
+ * html.span(todoSignal.map(t => t.text)),
26
+ * html.small(`Item ${position.index + 1}`)
27
+ * )
28
+ * )
29
+ * ```
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * // With separators between items
34
+ * const items = prop(['apple', 'banana', 'cherry'])
35
+ *
36
+ * ForEach(items,
37
+ * (itemSignal) => html.span(itemSignal),
38
+ * () => html.span(', ') // Separator between items
39
+ * )
40
+ * // Renders: apple, banana, cherry
41
+ * ```
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * // Using position information
46
+ * const numbers = prop([10, 20, 30])
47
+ *
48
+ * ForEach(numbers,
49
+ * (numberSignal, position) => html.div(
50
+ * `Position ${position.index}: `,
51
+ * numberSignal,
52
+ * position.isFirst ? ' (first)' : '',
53
+ * position.isLast ? ' (last)' : ''
54
+ * )
55
+ * )
56
+ * ```
57
+ *
58
+ * @typeParam T - The type of items in the array
59
+ * @param value - A signal or literal array to iterate over
60
+ * @param item - Function that renders each item, receives the item signal and position info
61
+ * @param separator - Optional function that renders content between items
62
+ * @returns A renderable that displays the dynamic list
13
63
  * @public
14
64
  */
15
65
  export declare const ForEach: <T>(value: Value<T[]>, item: (value: Signal<T>, position: ElementPosition) => TNode, separator?: (pos: ElementPosition) => TNode) => Renderable;
@@ -9,7 +9,7 @@ import { Renderable } from '../types/domain';
9
9
  * @typeParam T - The type of elements in the array.
10
10
  * @param value - The signal or literal containing the array.
11
11
  * @param display - The component to display when the array is non-empty.
12
- * @param whenEmpty- The component to display when the array is empty.
12
+ * @param whenEmpty - The component to display when the array is empty.
13
13
  * @returns - The renderable component.
14
14
  * @public
15
15
  */
@@ -7,7 +7,59 @@ import { DOMContext } from '../dom/dom-context';
7
7
  */
8
8
  export declare const OnChecked: (fn: (event: boolean, ctx: DOMContext) => void) => Renderable;
9
9
  /**
10
- * Represents a collection of HTML event handlers that can be attached to an element.
10
+ * Provides type-safe event handlers for all HTML events.
11
+ *
12
+ * The `on` object is a proxy that provides access to all standard HTML events with proper
13
+ * TypeScript typing. Each event handler receives the native event object and the DOM context.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Basic click handler
18
+ * html.button(
19
+ * on.click((event, ctx) => {
20
+ * console.log('Button clicked!', event.target)
21
+ * }),
22
+ * 'Click me'
23
+ * )
24
+ * ```
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * // Input event with value extraction
29
+ * const text = prop('')
30
+ *
31
+ * html.input(
32
+ * attr.value(text),
33
+ * on.input((event) => {
34
+ * text.value = (event.target as HTMLInputElement).value
35
+ * })
36
+ * )
37
+ * ```
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // Multiple event handlers on same element
42
+ * html.div(
43
+ * on.mouseenter(() => console.log('Mouse entered')),
44
+ * on.mouseleave(() => console.log('Mouse left')),
45
+ * on.click(() => console.log('Clicked')),
46
+ * 'Hover and click me'
47
+ * )
48
+ * ```
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * // Keyboard event handling
53
+ * html.input(
54
+ * on.keydown((event) => {
55
+ * if (event.key === 'Enter') {
56
+ * console.log('Enter pressed!')
57
+ * event.preventDefault()
58
+ * }
59
+ * })
60
+ * )
61
+ * ```
62
+ *
11
63
  * @public
12
64
  */
13
65
  export declare const on: {
@@ -100,18 +152,78 @@ export declare const on: {
100
152
  waiting: (handler: (event: Event, ctx: DOMContext) => void) => Renderable;
101
153
  };
102
154
  /**
103
- * Creates an event handler that emits the value of an HTMLInputElement.
155
+ * Creates an event handler that extracts and emits the string value from an input element.
156
+ *
157
+ * This utility simplifies handling input events by automatically extracting the value
158
+ * from the target element and passing it to your callback function.
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * const name = prop('')
163
+ *
164
+ * html.input(
165
+ * attr.value(name),
166
+ * on.input(emitValue(value => name.value = value))
167
+ * )
168
+ * ```
169
+ *
170
+ * @example
171
+ * ```typescript
172
+ * // With textarea
173
+ * const description = prop('')
174
+ *
175
+ * html.textarea(
176
+ * attr.value(description),
177
+ * on.input(emitValue(value => {
178
+ * description.value = value
179
+ * console.log('Description updated:', value)
180
+ * }))
181
+ * )
182
+ * ```
104
183
  *
105
- * @param fn - The callback function that will receive the emitted value.
106
- * @returns An event handler function that can be attached to an event listener.
184
+ * @param fn - Callback function that receives the input element's string value
185
+ * @returns Event handler function that can be used with event listeners
107
186
  * @public
108
187
  */
109
188
  export declare const emitValue: (fn: (text: string) => void) => (event: Event) => void;
110
189
  /**
111
- * Calls the provided function with the value of an HTMLInputElement as a number.
190
+ * Creates an event handler that extracts and emits the numeric value from an input element.
112
191
  *
113
- * @param fn - The function to be called with the value as a number.
114
- * @returns A function that can be used as an event handler.
192
+ * This utility automatically converts the input's value to a number using the browser's
193
+ * built-in `valueAsNumber` property, which handles number inputs correctly and returns
194
+ * `NaN` for invalid numeric values.
195
+ *
196
+ * @example
197
+ * ```typescript
198
+ * const age = prop(0)
199
+ *
200
+ * html.input(
201
+ * attr.type('number'),
202
+ * attr.value(age.map(String)),
203
+ * on.input(emitValueAsNumber(value => {
204
+ * if (!isNaN(value)) {
205
+ * age.value = value
206
+ * }
207
+ * }))
208
+ * )
209
+ * ```
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * // With range input
214
+ * const volume = prop(50)
215
+ *
216
+ * html.input(
217
+ * attr.type('range'),
218
+ * attr.min('0'),
219
+ * attr.max('100'),
220
+ * attr.value(volume.map(String)),
221
+ * on.input(emitValueAsNumber(value => volume.value = value))
222
+ * )
223
+ * ```
224
+ *
225
+ * @param fn - Callback function that receives the input element's numeric value (may be NaN)
226
+ * @returns Event handler function that can be used with event listeners
115
227
  * @public
116
228
  */
117
229
  export declare const emitValueAsNumber: (fn: (num: number) => void) => (event: Event) => void;
@@ -144,9 +256,55 @@ export declare const emitValueAsDateTime: (fn: (date: Date) => void) => (event:
144
256
  */
145
257
  export declare const emitValueAsNullableDateTime: (fn: (date: Date | null) => void) => (event: Event) => void;
146
258
  /**
147
- * Calls the provided function with the checked value of the event target.
148
- * @param fn - The function to be called with the checked value.
149
- * @returns A function that takes an event and calls the provided function with the checked value of the event target.
259
+ * Creates an event handler that extracts and emits the checked state from a checkbox or radio input.
260
+ *
261
+ * This utility simplifies handling checkbox and radio button state changes by automatically
262
+ * extracting the `checked` property from the target element.
263
+ *
264
+ * @example
265
+ * ```typescript
266
+ * const isEnabled = prop(false)
267
+ *
268
+ * html.input(
269
+ * attr.type('checkbox'),
270
+ * attr.checked(isEnabled),
271
+ * on.change(emitChecked(checked => isEnabled.value = checked))
272
+ * )
273
+ * ```
274
+ *
275
+ * @example
276
+ * ```typescript
277
+ * // With radio buttons
278
+ * const selectedOption = prop('')
279
+ *
280
+ * html.div(
281
+ * html.label(
282
+ * html.input(
283
+ * attr.type('radio'),
284
+ * attr.name('option'),
285
+ * attr.value('A'),
286
+ * on.change(emitChecked(checked => {
287
+ * if (checked) selectedOption.value = 'A'
288
+ * }))
289
+ * ),
290
+ * 'Option A'
291
+ * ),
292
+ * html.label(
293
+ * html.input(
294
+ * attr.type('radio'),
295
+ * attr.name('option'),
296
+ * attr.value('B'),
297
+ * on.change(emitChecked(checked => {
298
+ * if (checked) selectedOption.value = 'B'
299
+ * }))
300
+ * ),
301
+ * 'Option B'
302
+ * )
303
+ * )
304
+ * ```
305
+ *
306
+ * @param fn - Callback function that receives the input element's checked state
307
+ * @returns Event handler function that can be used with event listeners
150
308
  * @public
151
309
  */
152
310
  export declare const emitChecked: (fn: (checked: boolean) => void) => (event: Event) => void;
@@ -40,26 +40,196 @@ export type ProviderOptions = {
40
40
  * @returns A Clear function that can be used to clean up any resources associated with the execution.
41
41
  * @public
42
42
  */
43
- export declare const WithProvider: (fn: (ctx: ProviderOptions) => TNode | void) => Renderable;
43
+ export declare const WithProvider: (fn: (opts: ProviderOptions) => TNode | void) => Renderable;
44
44
  /**
45
- * Returns a renderable function that sets a provider for the given provider mark and returns a child renderable.
45
+ * Makes a provider available to all child components in the component tree.
46
46
  *
47
- * @param provider - The provider to set.
48
- * @param options - The options to pass to the provider.
49
- * @param child - The child renderable to return.
47
+ * This function creates a provider context that child components can access using `Use`.
48
+ * The provider is automatically disposed when the component is unmounted.
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * // Create a theme provider
53
+ * const ThemeProvider: Provider<Signal<string>> = {
54
+ * mark: makeProviderMark<Signal<string>>('Theme'),
55
+ * create: () => {
56
+ * const theme = prop('light')
57
+ * return {
58
+ * value: theme,
59
+ * dispose: () => theme.dispose()
60
+ * }
61
+ * }
62
+ * }
63
+ *
64
+ * // Provide the theme to child components
65
+ * const App = () =>
66
+ * Provide(
67
+ * ThemeProvider,
68
+ * {}, // options
69
+ * () => html.div(
70
+ * html.h1('My App'),
71
+ * ThemeToggle(), // Can access the theme
72
+ * MainContent() // Can also access the theme
73
+ * )
74
+ * )
75
+ * ```
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * // Provider with options
80
+ * const ConfigProvider: Provider<Config, { apiUrl: string }> = {
81
+ * mark: makeProviderMark<Config>('Config'),
82
+ * create: (options) => {
83
+ * const config = new Config(options.apiUrl)
84
+ * return {
85
+ * value: config,
86
+ * dispose: () => config.cleanup()
87
+ * }
88
+ * }
89
+ * }
90
+ *
91
+ * // Provide with specific options
92
+ * Provide(
93
+ * ConfigProvider,
94
+ * { apiUrl: 'https://api.example.com' },
95
+ * () => AppContent()
96
+ * )
97
+ * ```
98
+ *
99
+ * @template T - The type of value provided by the provider
100
+ * @template O - The type of options passed to the provider
101
+ * @param provider - The provider definition containing mark and create function
102
+ * @param options - Options to pass to the provider's create function
103
+ * @param child - Function that returns the child components that can access the provider
104
+ * @returns A renderable that provides the value to its children
105
+ * @public
50
106
  */
51
107
  export declare const Provide: <T, O>(provider: Provider<T, O>, options: O, child: () => TNode) => Renderable;
52
108
  /**
53
- * Returns a renderable function that uses a provider for the given provider mark and returns a child renderable.
109
+ * Consumes a provider value and makes it available to a child component.
110
+ *
111
+ * This function looks up a provider in the component tree and passes its value
112
+ * to the child function. The provider must have been made available by a parent
113
+ * component using `Provide`.
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * // Use a theme provider
118
+ * const ThemeToggle = () =>
119
+ * Use(
120
+ * ThemeProvider,
121
+ * (theme) => html.button(
122
+ * on.click(() => {
123
+ * theme.value = theme.value === 'light' ? 'dark' : 'light'
124
+ * }),
125
+ * 'Current theme: ', theme
126
+ * )
127
+ * )
128
+ * ```
54
129
  *
55
- * @param provider - The provider mark to use the provider for.
56
- * @param child - The child renderable to return.
130
+ * @example
131
+ * ```typescript
132
+ * // Use multiple properties from a provider
133
+ * const UserProfile = () =>
134
+ * Use(
135
+ * UserProvider,
136
+ * (user) => html.div(
137
+ * html.h2('Welcome, ', user.map(u => u.name)),
138
+ * html.p('Email: ', user.map(u => u.email)),
139
+ * html.p('Role: ', user.map(u => u.role))
140
+ * )
141
+ * )
142
+ * ```
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * // Use provider in conditional rendering
147
+ * const ConditionalContent = () =>
148
+ * Use(
149
+ * AuthProvider,
150
+ * (auth) => auth.map(a => a.isLoggedIn)
151
+ * ? html.div('Welcome back!')
152
+ * : html.div('Please log in')
153
+ * )
154
+ * ```
155
+ *
156
+ * @template T - The type of value provided by the provider
157
+ * @param provider - The provider to consume (must be available in parent components)
158
+ * @param child - Function that receives the provider value and returns content to render
159
+ * @returns A renderable that consumes the provider and renders the child content
160
+ * @throws {ProviderNotFoundError} When the provider is not found in the component tree
161
+ * @public
57
162
  */
58
163
  export declare const Use: <T>(provider: Provider<T>, child: (provider: T) => TNode) => Renderable;
59
164
  /**
60
- * Returns a renderable function that uses a provider for the given provider marks and returns a child renderable.
165
+ * Consumes multiple providers and makes their values available to a child component.
166
+ *
167
+ * This function is a convenience wrapper for consuming multiple providers at once.
168
+ * It's equivalent to nesting multiple `Use` calls but provides a cleaner API when
169
+ * you need access to several providers simultaneously.
61
170
  *
62
- * @param providers - The provider marks to use the providers for.
63
- * @param child - The child renderable to return.
171
+ * @example
172
+ * ```typescript
173
+ * // Use multiple providers together
174
+ * const Dashboard = () =>
175
+ * UseMany(
176
+ * UserProvider,
177
+ * ThemeProvider,
178
+ * ConfigProvider
179
+ * )(
180
+ * (user, theme, config) => html.div(
181
+ * attr.class(theme.map(t => `theme-${t}`)),
182
+ * html.h1('Dashboard for ', user.map(u => u.name)),
183
+ * html.p('API URL: ', config.map(c => c.apiUrl)),
184
+ * html.p('Current theme: ', theme)
185
+ * )
186
+ * )
187
+ * ```
188
+ *
189
+ * @example
190
+ * ```typescript
191
+ * // Equivalent to nested Use calls
192
+ * const Dashboard = () =>
193
+ * Use(UserProvider, user =>
194
+ * Use(ThemeProvider, theme =>
195
+ * Use(ConfigProvider, config =>
196
+ * html.div(
197
+ * // Same content as above
198
+ * )
199
+ * )
200
+ * )
201
+ * )
202
+ * ```
203
+ *
204
+ * @example
205
+ * ```typescript
206
+ * // Type-safe access to multiple providers
207
+ * const SettingsPanel = () =>
208
+ * UseMany(
209
+ * PreferencesProvider,
210
+ * UserProvider
211
+ * )(
212
+ * (preferences, user) => html.div(
213
+ * html.h2('Settings for ', user.map(u => u.name)),
214
+ * html.label(
215
+ * 'Theme: ',
216
+ * html.select(
217
+ * attr.value(preferences.map(p => p.theme)),
218
+ * on.change(emitValue(value => {
219
+ * preferences.update(p => ({ ...p, theme: value }))
220
+ * })),
221
+ * html.option(attr.value('light'), 'Light'),
222
+ * html.option(attr.value('dark'), 'Dark')
223
+ * )
224
+ * )
225
+ * )
226
+ * )
227
+ * ```
228
+ *
229
+ * @template T - Tuple type representing the types of all providers
230
+ * @param providers - Variable number of providers to consume
231
+ * @returns Function that takes a child function and returns a renderable
232
+ * @throws {ProviderNotFoundError} When any of the providers is not found in the component tree
233
+ * @public
64
234
  */
65
235
  export declare const UseMany: <T extends Provider<unknown>[]>(...providers: T) => (child: (...values: ToProviderTypes<T>) => TNode) => Renderable;
@@ -2,12 +2,70 @@ import { ElementPosition } from '../std/element-position';
2
2
  import { Value } from '../std/value';
3
3
  import { TNode, Renderable } from '../types/domain';
4
4
  /**
5
- * Creates a renderable function that repeats a given element a specified number of times.
5
+ * Renders content a specified number of times, with each iteration receiving position information.
6
6
  *
7
- * @param times - A signal representing the number of times the element should be repeated.
8
- * @param element - A function that returns the element to be repeated, based on the current index.
9
- * @param separator - (Optional) A function that returns the separator element to be inserted between repeated elements.
10
- * @returns A renderable function that renders the repeated elements.
7
+ * This function is useful for generating repeated UI elements based on a count rather than an array.
8
+ * Each iteration receives an `ElementPosition` object that provides the current index and position
9
+ * information relative to the total count.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // Create a simple numbered list
14
+ * const count = prop(5)
15
+ *
16
+ * Repeat(count,
17
+ * (position) => html.div(
18
+ * `Item ${position.index + 1} of ${position.total.value}`,
19
+ * position.isFirst ? ' (first)' : '',
20
+ * position.isLast ? ' (last)' : ''
21
+ * )
22
+ * )
23
+ * ```
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // Create a star rating component
28
+ * const rating = prop(3)
29
+ * const maxStars = 5
30
+ *
31
+ * Repeat(maxStars,
32
+ * (position) => html.span(
33
+ * attr.class(position.index < rating.value ? 'star-filled' : 'star-empty'),
34
+ * '★'
35
+ * )
36
+ * )
37
+ * ```
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * // With separators between items
42
+ * Repeat(3,
43
+ * (position) => html.span(`Item ${position.index}`),
44
+ * () => html.span(' | ') // Separator
45
+ * )
46
+ * // Renders: Item 0 | Item 1 | Item 2
47
+ * ```
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * // Dynamic count that updates the UI
52
+ * const itemCount = prop(2)
53
+ *
54
+ * html.div(
55
+ * html.button(
56
+ * on.click(() => itemCount.value++),
57
+ * 'Add Item'
58
+ * ),
59
+ * Repeat(itemCount,
60
+ * (position) => html.div(`Dynamic item ${position.index + 1}`)
61
+ * )
62
+ * )
63
+ * ```
64
+ *
65
+ * @param times - A signal or number representing how many times to repeat the content
66
+ * @param element - Function that returns content for each iteration, receives position information
67
+ * @param separator - Optional function that returns content to place between iterations
68
+ * @returns A renderable that displays the repeated content
11
69
  * @public
12
70
  */
13
71
  export declare const Repeat: (times: Value<number>, element: (index: ElementPosition) => TNode, separator?: (pos: ElementPosition) => TNode) => Renderable;