ripple 0.2.115 → 0.2.116
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 +1 -1
- package/src/compiler/phases/1-parse/index.js +79 -0
- package/src/compiler/phases/3-transform/client/index.js +54 -8
- package/src/compiler/phases/3-transform/segments.js +15 -10
- package/src/compiler/types/index.d.ts +16 -0
- package/src/runtime/index-client.js +18 -184
- package/src/runtime/internal/client/bindings.js +443 -0
- package/src/runtime/internal/client/index.js +4 -0
- package/src/runtime/map.js +11 -1
- package/src/runtime/set.js +11 -1
- package/tests/client/map.test.ripple +81 -0
- package/tests/client/set.test.ripple +81 -0
- package/types/index.d.ts +87 -45
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "Ripple is an elegant TypeScript UI framework",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Dominic Gannaway",
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.116",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"module": "src/runtime/index-client.js",
|
|
9
9
|
"main": "src/runtime/index-client.js",
|
|
@@ -167,6 +167,22 @@ function RipplePlugin(config) {
|
|
|
167
167
|
}
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
// Check if this is #Map or #Set
|
|
171
|
+
if (this.input.slice(this.pos, this.pos + 4) === '#Map') {
|
|
172
|
+
const charAfter = this.pos + 4 < this.input.length ? this.input.charCodeAt(this.pos + 4) : -1;
|
|
173
|
+
if (charAfter === 40) { // ( character
|
|
174
|
+
this.pos += 4; // consume '#Map'
|
|
175
|
+
return this.finishToken(tt.name, '#Map');
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (this.input.slice(this.pos, this.pos + 4) === '#Set') {
|
|
179
|
+
const charAfter = this.pos + 4 < this.input.length ? this.input.charCodeAt(this.pos + 4) : -1;
|
|
180
|
+
if (charAfter === 40) { // ( character
|
|
181
|
+
this.pos += 4; // consume '#Set'
|
|
182
|
+
return this.finishToken(tt.name, '#Set');
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
170
186
|
// Check if this is #server
|
|
171
187
|
if (this.input.slice(this.pos, this.pos + 7) === '#server') {
|
|
172
188
|
// Check that next char after 'server' is whitespace, {, . (dot), or EOF
|
|
@@ -186,6 +202,27 @@ function RipplePlugin(config) {
|
|
|
186
202
|
return this.finishToken(tt.name, '#server');
|
|
187
203
|
}
|
|
188
204
|
}
|
|
205
|
+
|
|
206
|
+
// Check if this is an invalid #Identifier pattern
|
|
207
|
+
// Valid patterns: #[, #{, #Map(, #Set(, #server
|
|
208
|
+
// If we see # followed by an uppercase letter that isn't Map or Set, it's an error
|
|
209
|
+
if (nextChar >= 65 && nextChar <= 90) { // A-Z
|
|
210
|
+
// Extract the identifier name
|
|
211
|
+
let identEnd = this.pos + 1;
|
|
212
|
+
while (identEnd < this.input.length) {
|
|
213
|
+
const ch = this.input.charCodeAt(identEnd);
|
|
214
|
+
if ((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122) || (ch >= 48 && ch <= 57) || ch === 95) {
|
|
215
|
+
// A-Z, a-z, 0-9, _
|
|
216
|
+
identEnd++;
|
|
217
|
+
} else {
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const identName = this.input.slice(this.pos + 1, identEnd);
|
|
222
|
+
if (identName !== 'Map' && identName !== 'Set') {
|
|
223
|
+
this.raise(this.pos, `Invalid tracked syntax '#${identName}'. Only #Map and #Set are currently supported using shorthand tracked syntax.`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
189
226
|
}
|
|
190
227
|
}
|
|
191
228
|
if (code === 64) {
|
|
@@ -391,6 +428,12 @@ function RipplePlugin(config) {
|
|
|
391
428
|
return this.finishNode(node, 'ServerIdentifier');
|
|
392
429
|
}
|
|
393
430
|
|
|
431
|
+
// Check if this is #Map( or #Set(
|
|
432
|
+
if (this.type === tt.name && (this.value === '#Map' || this.value === '#Set')) {
|
|
433
|
+
const type = this.value === '#Map' ? 'TrackedMapExpression' : 'TrackedSetExpression';
|
|
434
|
+
return this.parseTrackedCollectionExpression(type);
|
|
435
|
+
}
|
|
436
|
+
|
|
394
437
|
// Check if this is a tuple literal starting with #[
|
|
395
438
|
if (this.type === tt.bracketL && this.value === '#[') {
|
|
396
439
|
return this.parseTrackedArrayExpression();
|
|
@@ -449,6 +492,42 @@ function RipplePlugin(config) {
|
|
|
449
492
|
return this.finishNode(node, 'ServerBlock');
|
|
450
493
|
}
|
|
451
494
|
|
|
495
|
+
/**
|
|
496
|
+
* Parse `#Map(...)` or `#Set(...)` syntax for tracked collections
|
|
497
|
+
* Creates a TrackedMap or TrackedSet node with the arguments property
|
|
498
|
+
* @param {string} type - Either 'TrackedMap' or 'TrackedSet'
|
|
499
|
+
* @returns {any} TrackedMap or TrackedSet node
|
|
500
|
+
*/
|
|
501
|
+
parseTrackedCollectionExpression(type) {
|
|
502
|
+
const node = this.startNode();
|
|
503
|
+
this.next(); // consume '#Map' or '#Set'
|
|
504
|
+
this.expect(tt.parenL); // expect '('
|
|
505
|
+
|
|
506
|
+
node.arguments = [];
|
|
507
|
+
|
|
508
|
+
// Parse arguments similar to function call arguments
|
|
509
|
+
let first = true;
|
|
510
|
+
while (!this.eat(tt.parenR)) {
|
|
511
|
+
if (!first) {
|
|
512
|
+
this.expect(tt.comma);
|
|
513
|
+
if (this.afterTrailingComma(tt.parenR)) break;
|
|
514
|
+
} else {
|
|
515
|
+
first = false;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
if (this.type === tt.ellipsis) {
|
|
519
|
+
// Spread argument
|
|
520
|
+
const arg = this.parseSpread();
|
|
521
|
+
node.arguments.push(arg);
|
|
522
|
+
} else {
|
|
523
|
+
// Regular argument
|
|
524
|
+
node.arguments.push(this.parseMaybeAssign(false));
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
return this.finishNode(node, type);
|
|
529
|
+
}
|
|
530
|
+
|
|
452
531
|
parseTrackedArrayExpression() {
|
|
453
532
|
const node = this.startNode();
|
|
454
533
|
this.next(); // consume the '#['
|
|
@@ -350,11 +350,9 @@ const visitors = {
|
|
|
350
350
|
context.state.imports.add(`import { TrackedArray } from 'ripple'`);
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
-
return b.
|
|
354
|
-
b.
|
|
355
|
-
|
|
356
|
-
node.elements.map((el) => context.visit(el)),
|
|
357
|
-
),
|
|
353
|
+
return b.call(
|
|
354
|
+
b.member(b.id('TrackedArray'), b.id('from')),
|
|
355
|
+
...node.elements.map((el) => context.visit(el)),
|
|
358
356
|
);
|
|
359
357
|
}
|
|
360
358
|
|
|
@@ -384,6 +382,48 @@ const visitors = {
|
|
|
384
382
|
);
|
|
385
383
|
},
|
|
386
384
|
|
|
385
|
+
TrackedMapExpression(node, context) {
|
|
386
|
+
if (context.state.to_ts) {
|
|
387
|
+
if (!context.state.imports.has(`import { TrackedMap } from 'ripple'`)) {
|
|
388
|
+
context.state.imports.add(`import { TrackedMap } from 'ripple'`);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const calleeId = b.id('TrackedMap');
|
|
392
|
+
// Preserve location from original node for Volar mapping
|
|
393
|
+
calleeId.loc = node.loc;
|
|
394
|
+
// Add metadata for Volar mapping - map "TrackedMap" identifier to "#Map" in source
|
|
395
|
+
calleeId.metadata = { tracked_shorthand: '#Map' };
|
|
396
|
+
return b.new(calleeId, ...node.arguments.map((arg) => context.visit(arg)));
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return b.call(
|
|
400
|
+
'_$_.tracked_map',
|
|
401
|
+
b.id('__block'),
|
|
402
|
+
...node.arguments.map((arg) => context.visit(arg)),
|
|
403
|
+
);
|
|
404
|
+
},
|
|
405
|
+
|
|
406
|
+
TrackedSetExpression(node, context) {
|
|
407
|
+
if (context.state.to_ts) {
|
|
408
|
+
if (!context.state.imports.has(`import { TrackedSet } from 'ripple'`)) {
|
|
409
|
+
context.state.imports.add(`import { TrackedSet } from 'ripple'`);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
const calleeId = b.id('TrackedSet');
|
|
413
|
+
// Preserve location from original node for Volar mapping
|
|
414
|
+
calleeId.loc = node.loc;
|
|
415
|
+
// Add metadata for Volar mapping - map "TrackedSet" identifier to "#Set" in source
|
|
416
|
+
calleeId.metadata = { tracked_shorthand: '#Set' };
|
|
417
|
+
return b.new(calleeId, ...node.arguments.map((arg) => context.visit(arg)));
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return b.call(
|
|
421
|
+
'_$_.tracked_set',
|
|
422
|
+
b.id('__block'),
|
|
423
|
+
...node.arguments.map((arg) => context.visit(arg)),
|
|
424
|
+
);
|
|
425
|
+
},
|
|
426
|
+
|
|
387
427
|
TrackedExpression(node, context) {
|
|
388
428
|
return b.call('_$_.get', context.visit(node.argument));
|
|
389
429
|
},
|
|
@@ -459,7 +499,7 @@ const visitors = {
|
|
|
459
499
|
return {
|
|
460
500
|
...node,
|
|
461
501
|
id: { ...node.id, name: capitalizedName },
|
|
462
|
-
init: node.init ? context.visit(node.init) : null
|
|
502
|
+
init: node.init ? context.visit(node.init) : null,
|
|
463
503
|
};
|
|
464
504
|
}
|
|
465
505
|
}
|
|
@@ -1517,12 +1557,18 @@ function transform_ts_child(node, context) {
|
|
|
1517
1557
|
};
|
|
1518
1558
|
}
|
|
1519
1559
|
|
|
1520
|
-
const jsxElement = b.jsx_element(
|
|
1560
|
+
const jsxElement = b.jsx_element(
|
|
1561
|
+
opening_type,
|
|
1562
|
+
attributes,
|
|
1563
|
+
children,
|
|
1564
|
+
node.selfClosing,
|
|
1565
|
+
closing_type,
|
|
1566
|
+
);
|
|
1521
1567
|
// Preserve metadata from Element node for mapping purposes
|
|
1522
1568
|
if (node.metadata && (node.metadata.ts_name || node.metadata.original_name)) {
|
|
1523
1569
|
jsxElement.metadata = {
|
|
1524
1570
|
ts_name: node.metadata.ts_name,
|
|
1525
|
-
original_name: node.metadata.original_name
|
|
1571
|
+
original_name: node.metadata.original_name,
|
|
1526
1572
|
};
|
|
1527
1573
|
}
|
|
1528
1574
|
state.init.push(b.stmt(jsxElement));
|
|
@@ -167,18 +167,23 @@ export function convert_source_map_to_mappings(ast, source, generated_code) {
|
|
|
167
167
|
// Only collect tokens from nodes with .loc (skip synthesized nodes like children attribute)
|
|
168
168
|
if (node.type === 'Identifier' && node.name) {
|
|
169
169
|
if (node.loc) {
|
|
170
|
-
// Check if this identifier
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
// This is a capitalized name in generated code, map to lowercase in source
|
|
174
|
-
tokens.push({ source: originalName, generated: node.name });
|
|
170
|
+
// Check if this identifier has tracked_shorthand metadata (e.g., TrackedMap -> #Map)
|
|
171
|
+
if (node.metadata?.tracked_shorthand) {
|
|
172
|
+
tokens.push({ source: node.metadata.tracked_shorthand, generated: node.name });
|
|
175
173
|
} else {
|
|
176
|
-
// Check if this identifier
|
|
177
|
-
const
|
|
178
|
-
if (
|
|
179
|
-
|
|
174
|
+
// Check if this identifier was capitalized (reverse lookup)
|
|
175
|
+
const originalName = reverseCapitalizedNames.get(node.name);
|
|
176
|
+
if (originalName) {
|
|
177
|
+
// This is a capitalized name in generated code, map to lowercase in source
|
|
178
|
+
tokens.push({ source: originalName, generated: node.name });
|
|
180
179
|
} else {
|
|
181
|
-
|
|
180
|
+
// Check if this identifier should be capitalized (forward lookup)
|
|
181
|
+
const capitalizedName = capitalizedNames.get(node.name);
|
|
182
|
+
if (capitalizedName) {
|
|
183
|
+
tokens.push({ source: node.name, generated: capitalizedName });
|
|
184
|
+
} else {
|
|
185
|
+
tokens.push(node.name);
|
|
186
|
+
}
|
|
182
187
|
}
|
|
183
188
|
}
|
|
184
189
|
}
|
|
@@ -78,6 +78,22 @@ export interface TrackedObjectExpression extends Omit<ObjectExpression, 'type'>
|
|
|
78
78
|
properties: (Property | SpreadElement)[];
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Tracked Map expression node
|
|
83
|
+
*/
|
|
84
|
+
export interface TrackedMapExpression extends Omit<Node, 'type'> {
|
|
85
|
+
type: 'TrackedMapExpression';
|
|
86
|
+
arguments: (Expression | SpreadElement)[];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Tracked Set expression node
|
|
91
|
+
*/
|
|
92
|
+
export interface TrackedSetExpression extends Omit<Node, 'type'> {
|
|
93
|
+
type: 'TrackedSetExpression';
|
|
94
|
+
arguments: (Expression | SpreadElement)[];
|
|
95
|
+
}
|
|
96
|
+
|
|
81
97
|
/**
|
|
82
98
|
* Ripple component node
|
|
83
99
|
*/
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/** @import { Block
|
|
1
|
+
/** @import { Block } from '#client' */
|
|
2
2
|
|
|
3
|
-
import { destroy_block,
|
|
4
|
-
import { handle_root_events
|
|
3
|
+
import { destroy_block, root } from './internal/client/blocks.js';
|
|
4
|
+
import { handle_root_events } from './internal/client/events.js';
|
|
5
5
|
import { init_operations } from './internal/client/operations.js';
|
|
6
|
-
import { active_block
|
|
7
|
-
import { create_anchor
|
|
6
|
+
import { active_block } from './internal/client/runtime.js';
|
|
7
|
+
import { create_anchor } from './internal/client/utils.js';
|
|
8
8
|
import { remove_ssr_css } from './internal/client/css.js';
|
|
9
9
|
|
|
10
10
|
// Re-export JSX runtime functions for jsxImportSource: "ripple"
|
|
@@ -78,182 +78,16 @@ export { ref_prop as createRefKey } from './internal/client/runtime.js';
|
|
|
78
78
|
|
|
79
79
|
export { on } from './internal/client/events.js';
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/** @param {HTMLOptionElement} option */
|
|
97
|
-
function get_option_value(option) {
|
|
98
|
-
return option.value;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Selects the correct option(s) (depending on whether this is a multiple select)
|
|
103
|
-
* @template V
|
|
104
|
-
* @param {HTMLSelectElement} select
|
|
105
|
-
* @param {V} value
|
|
106
|
-
* @param {boolean} mounting
|
|
107
|
-
*/
|
|
108
|
-
function select_option(select, value, mounting = false) {
|
|
109
|
-
if (select.multiple) {
|
|
110
|
-
// If value is null or undefined, keep the selection as is
|
|
111
|
-
if (value == undefined) {
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// If not an array, warn and keep the selection as is
|
|
116
|
-
if (!is_array(value)) {
|
|
117
|
-
// TODO
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Otherwise, update the selection
|
|
121
|
-
for (var option of select.options) {
|
|
122
|
-
option.selected = /** @type {string[]} */ (value).includes(get_option_value(option));
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
for (option of select.options) {
|
|
129
|
-
var option_value = get_option_value(option);
|
|
130
|
-
if (option_value === value) {
|
|
131
|
-
option.selected = true;
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (!mounting || value !== undefined) {
|
|
137
|
-
select.selectedIndex = -1; // no option should be selected
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* @param {unknown} maybe_tracked
|
|
143
|
-
* @returns {(node: HTMLInputElement | HTMLSelectElement) => void}
|
|
144
|
-
*/
|
|
145
|
-
export function bindValue(maybe_tracked) {
|
|
146
|
-
if (!is_tracked_object(maybe_tracked)) {
|
|
147
|
-
throw new TypeError('bindValue() argument is not a tracked object');
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
var block = /** @type {Block} */ (active_block);
|
|
151
|
-
var tracked = /** @type {Tracked} */ (maybe_tracked);
|
|
152
|
-
|
|
153
|
-
return (node) => {
|
|
154
|
-
var clear_event;
|
|
155
|
-
|
|
156
|
-
if (node.tagName === 'SELECT') {
|
|
157
|
-
var select = /** @type {HTMLSelectElement} */ (node);
|
|
158
|
-
var mounting = true;
|
|
159
|
-
|
|
160
|
-
clear_event = on(select, 'change', async () => {
|
|
161
|
-
var query = ':checked';
|
|
162
|
-
/** @type {unknown} */
|
|
163
|
-
var value;
|
|
164
|
-
|
|
165
|
-
if (select.multiple) {
|
|
166
|
-
value = [].map.call(select.querySelectorAll(query), get_option_value);
|
|
167
|
-
} else {
|
|
168
|
-
/** @type {HTMLOptionElement | null} */
|
|
169
|
-
var selected_option =
|
|
170
|
-
select.querySelector(query) ??
|
|
171
|
-
// will fall back to first non-disabled option if no option is selected
|
|
172
|
-
select.querySelector('option:not([disabled])');
|
|
173
|
-
value = selected_option && get_option_value(selected_option);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
set(tracked, value, block);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
effect(() => {
|
|
180
|
-
var value = get(tracked);
|
|
181
|
-
select_option(select, value, mounting);
|
|
182
|
-
|
|
183
|
-
// Mounting and value undefined -> take selection from dom
|
|
184
|
-
if (mounting && value === undefined) {
|
|
185
|
-
/** @type {HTMLOptionElement | null} */
|
|
186
|
-
var selected_option = select.querySelector(':checked');
|
|
187
|
-
if (selected_option !== null) {
|
|
188
|
-
value = get_option_value(selected_option);
|
|
189
|
-
set(tracked, value, block);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
mounting = false;
|
|
194
|
-
});
|
|
195
|
-
} else {
|
|
196
|
-
var input = /** @type {HTMLInputElement} */ (node);
|
|
197
|
-
|
|
198
|
-
clear_event = on(input, 'input', async () => {
|
|
199
|
-
/** @type {any} */
|
|
200
|
-
var value = input.value;
|
|
201
|
-
value = is_numberlike_input(input) ? to_number(value) : value;
|
|
202
|
-
set(tracked, value, block);
|
|
203
|
-
|
|
204
|
-
await tick();
|
|
205
|
-
|
|
206
|
-
if (value !== (value = get(tracked))) {
|
|
207
|
-
var start = input.selectionStart;
|
|
208
|
-
var end = input.selectionEnd;
|
|
209
|
-
input.value = value ?? '';
|
|
210
|
-
|
|
211
|
-
// Restore selection
|
|
212
|
-
if (end !== null) {
|
|
213
|
-
input.selectionStart = start;
|
|
214
|
-
input.selectionEnd = Math.min(end, input.value.length);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
render(() => {
|
|
220
|
-
var value = get(tracked);
|
|
221
|
-
|
|
222
|
-
if (is_numberlike_input(input) && value === to_number(input.value)) {
|
|
223
|
-
return;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
if (input.type === 'date' && !value && !input.value) {
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
if (value !== input.value) {
|
|
231
|
-
input.value = value ?? '';
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
return clear_event;
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
/**
|
|
241
|
-
* @param {unknown} maybe_tracked
|
|
242
|
-
* @returns {(node: HTMLInputElement) => void}
|
|
243
|
-
*/
|
|
244
|
-
export function bindChecked(maybe_tracked) {
|
|
245
|
-
if (!is_tracked_object(maybe_tracked)) {
|
|
246
|
-
throw new TypeError('bindChecked() argument is not a tracked object');
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const block = /** @type {any} */ (active_block);
|
|
250
|
-
const tracked = /** @type {Tracked<any>} */ (maybe_tracked);
|
|
251
|
-
|
|
252
|
-
return (input) => {
|
|
253
|
-
const clear_event = on(input, 'change', () => {
|
|
254
|
-
set(tracked, input.checked, block);
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
return clear_event;
|
|
258
|
-
};
|
|
259
|
-
}
|
|
81
|
+
export {
|
|
82
|
+
bindValue,
|
|
83
|
+
bindChecked,
|
|
84
|
+
bindClientWidth,
|
|
85
|
+
bindClientHeight,
|
|
86
|
+
bindContentRect,
|
|
87
|
+
bindContentBoxSize,
|
|
88
|
+
bindBorderBoxSize,
|
|
89
|
+
bindDevicePixelContentBoxSize,
|
|
90
|
+
bindInnerHTML,
|
|
91
|
+
bindInnerText,
|
|
92
|
+
bindTextContent,
|
|
93
|
+
} from './internal/client/bindings.js';
|