ripple 0.2.164 → 0.2.166
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 +2 -2
- package/src/compiler/phases/3-transform/client/index.js +65 -13
- package/src/runtime/internal/client/index.js +5 -2
- package/src/runtime/internal/client/operations.js +0 -6
- package/src/runtime/internal/client/render.js +22 -16
- package/src/runtime/internal/client/runtime.js +6 -4
- package/tests/client/ref.test.ripple +30 -0
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.166",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"module": "src/runtime/index-client.js",
|
|
9
9
|
"main": "src/runtime/index-client.js",
|
|
@@ -81,6 +81,6 @@
|
|
|
81
81
|
"typescript": "^5.9.2"
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
|
-
"ripple": "0.2.
|
|
84
|
+
"ripple": "0.2.166"
|
|
85
85
|
}
|
|
86
86
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import {Expression, FunctionExpression, Node, Program} from 'estree' */
|
|
1
|
+
/** @import {Expression, FunctionExpression, Node, Program, Statement} from 'estree' */
|
|
2
2
|
|
|
3
3
|
/** @typedef {Map<number, {offset: number, delta: number}>} PostProcessingChanges */
|
|
4
4
|
/** @typedef {number[]} LineOffsets */
|
|
@@ -129,7 +129,7 @@ function visit_head_element(node, context) {
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
function apply_updates(init, update) {
|
|
132
|
+
function apply_updates(init, update, state) {
|
|
133
133
|
if (update.length === 1) {
|
|
134
134
|
init.push(
|
|
135
135
|
b.stmt(
|
|
@@ -155,8 +155,25 @@ function apply_updates(init, update) {
|
|
|
155
155
|
const render_statements = [];
|
|
156
156
|
let index = 0;
|
|
157
157
|
|
|
158
|
+
const grouped_updates = new Map();
|
|
159
|
+
|
|
158
160
|
for (const u of update) {
|
|
159
161
|
if (u.initial) {
|
|
162
|
+
const id =
|
|
163
|
+
u.identity.type === 'Identifier' ? state.scope.get(u.identity.name)?.initial : u.identity;
|
|
164
|
+
let updates = grouped_updates.get(id);
|
|
165
|
+
|
|
166
|
+
if (updates === undefined) {
|
|
167
|
+
updates = [];
|
|
168
|
+
grouped_updates.set(id, updates);
|
|
169
|
+
}
|
|
170
|
+
updates.push(u);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
for (const [, updates] of grouped_updates) {
|
|
175
|
+
if (updates.length === 1) {
|
|
176
|
+
const u = updates[0];
|
|
160
177
|
const key = index_to_key(index);
|
|
161
178
|
index_map.set(u.operation, key);
|
|
162
179
|
initial.push(b.prop('init', b.id(key), u.initial));
|
|
@@ -171,6 +188,29 @@ function apply_updates(init, update) {
|
|
|
171
188
|
);
|
|
172
189
|
index++;
|
|
173
190
|
} else {
|
|
191
|
+
const key = index_to_key(index);
|
|
192
|
+
/** @type {Array<Statement>} */
|
|
193
|
+
const if_body = [
|
|
194
|
+
b.stmt(b.assignment('=', b.member(b.id('__prev'), b.id(key)), b.id('__' + key))),
|
|
195
|
+
];
|
|
196
|
+
initial.push(b.prop('init', b.id(key), updates[0].initial));
|
|
197
|
+
render_statements.push(
|
|
198
|
+
b.var('__' + key, updates[0].expression),
|
|
199
|
+
b.if(
|
|
200
|
+
b.binary('!==', b.member(b.id('__prev'), b.id(key)), b.id('__' + key)),
|
|
201
|
+
b.block(if_body),
|
|
202
|
+
),
|
|
203
|
+
);
|
|
204
|
+
for (const u of updates) {
|
|
205
|
+
index_map.set(u.operation, key);
|
|
206
|
+
if_body.push(u.operation(b.id('__' + key)));
|
|
207
|
+
index++;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
for (const u of update) {
|
|
213
|
+
if (!u.initial) {
|
|
174
214
|
render_statements.push(u.operation);
|
|
175
215
|
}
|
|
176
216
|
}
|
|
@@ -835,6 +875,7 @@ const visitors = {
|
|
|
835
875
|
if (is_dom_element) {
|
|
836
876
|
let class_attribute = null;
|
|
837
877
|
let style_attribute = null;
|
|
878
|
+
/** @type {Array<Statement>} */
|
|
838
879
|
const local_updates = [];
|
|
839
880
|
const is_void = is_void_element(node.id.name);
|
|
840
881
|
|
|
@@ -997,9 +1038,11 @@ const visitors = {
|
|
|
997
1038
|
});
|
|
998
1039
|
} else {
|
|
999
1040
|
local_updates.push({
|
|
1000
|
-
operation:
|
|
1001
|
-
b.call('_$_.set_attribute', id, b.literal(attribute),
|
|
1002
|
-
|
|
1041
|
+
operation: (key) =>
|
|
1042
|
+
b.stmt(b.call('_$_.set_attribute', id, b.literal(attribute), key)),
|
|
1043
|
+
expression,
|
|
1044
|
+
identity: attr.value,
|
|
1045
|
+
initial: b.void0,
|
|
1003
1046
|
});
|
|
1004
1047
|
}
|
|
1005
1048
|
} else {
|
|
@@ -1044,6 +1087,7 @@ const visitors = {
|
|
|
1044
1087
|
operation: (key) =>
|
|
1045
1088
|
b.stmt(b.call('_$_.set_class', id, key, hash_arg, b.literal(is_html))),
|
|
1046
1089
|
expression,
|
|
1090
|
+
identity: class_attribute.value,
|
|
1047
1091
|
initial: b.literal(''),
|
|
1048
1092
|
});
|
|
1049
1093
|
} else {
|
|
@@ -1063,14 +1107,16 @@ const visitors = {
|
|
|
1063
1107
|
const id = state.flush_node();
|
|
1064
1108
|
const metadata = { tracking: false, await: false };
|
|
1065
1109
|
const expression = visit(style_attribute.value, { ...state, metadata });
|
|
1066
|
-
const name = style_attribute.name.name;
|
|
1067
|
-
|
|
1068
|
-
const statement = b.stmt(b.call('_$_.set_attribute', id, b.literal(name), expression));
|
|
1069
1110
|
|
|
1070
1111
|
if (metadata.tracking) {
|
|
1071
|
-
local_updates.push({
|
|
1112
|
+
local_updates.push({
|
|
1113
|
+
operation: (key) => b.stmt(b.call('_$_.set_style', id, key)),
|
|
1114
|
+
identity: style_attribute.value,
|
|
1115
|
+
expression,
|
|
1116
|
+
initial: b.void0,
|
|
1117
|
+
});
|
|
1072
1118
|
} else {
|
|
1073
|
-
state.init.push(
|
|
1119
|
+
state.init.push(b.stmt(b.call('_$_.set_style', id, expression)));
|
|
1074
1120
|
}
|
|
1075
1121
|
}
|
|
1076
1122
|
}
|
|
@@ -1084,7 +1130,9 @@ const visitors = {
|
|
|
1084
1130
|
);
|
|
1085
1131
|
}
|
|
1086
1132
|
|
|
1133
|
+
/** @type {Array<Statement>} */
|
|
1087
1134
|
const init = [];
|
|
1135
|
+
/** @type {Array<Statement>} */
|
|
1088
1136
|
const update = [];
|
|
1089
1137
|
|
|
1090
1138
|
if (!is_void) {
|
|
@@ -1100,7 +1148,7 @@ const visitors = {
|
|
|
1100
1148
|
|
|
1101
1149
|
if (update.length > 0) {
|
|
1102
1150
|
if (state.scope.parent.declarations.size > 0) {
|
|
1103
|
-
apply_updates(init, update);
|
|
1151
|
+
apply_updates(init, update, state);
|
|
1104
1152
|
} else {
|
|
1105
1153
|
state.update.push(...update);
|
|
1106
1154
|
}
|
|
@@ -1159,7 +1207,9 @@ const visitors = {
|
|
|
1159
1207
|
),
|
|
1160
1208
|
);
|
|
1161
1209
|
} else if (attr.type === 'RefAttribute') {
|
|
1162
|
-
|
|
1210
|
+
const ref_id = state.scope.generate('ref');
|
|
1211
|
+
state.setup.push(b.var(ref_id, b.call('_$_.ref_prop')));
|
|
1212
|
+
props.push(b.prop('init', b.id(ref_id), visit(attr.argument, state), true));
|
|
1163
1213
|
} else {
|
|
1164
1214
|
throw new Error('TODO');
|
|
1165
1215
|
}
|
|
@@ -2250,6 +2300,7 @@ function transform_children(children, context) {
|
|
|
2250
2300
|
state.update.push({
|
|
2251
2301
|
operation: (key) => b.stmt(b.call('_$_.set_text', id, key)),
|
|
2252
2302
|
expression,
|
|
2303
|
+
identity: node.expression,
|
|
2253
2304
|
initial: b.literal(' '),
|
|
2254
2305
|
});
|
|
2255
2306
|
if (metadata.await) {
|
|
@@ -2277,6 +2328,7 @@ function transform_children(children, context) {
|
|
|
2277
2328
|
state.update.push({
|
|
2278
2329
|
operation: (key) => b.stmt(b.call('_$_.set_text', id, key)),
|
|
2279
2330
|
expression,
|
|
2331
|
+
identity: node.expression,
|
|
2280
2332
|
initial: b.literal(' '),
|
|
2281
2333
|
});
|
|
2282
2334
|
if (metadata.await) {
|
|
@@ -2354,7 +2406,7 @@ function transform_body(body, { visit, state }) {
|
|
|
2354
2406
|
// In TypeScript mode, just add the update statements directly
|
|
2355
2407
|
body_state.init.push(...body_state.update);
|
|
2356
2408
|
} else {
|
|
2357
|
-
apply_updates(body_state.init, body_state.update);
|
|
2409
|
+
apply_updates(body_state.init, body_state.update, state);
|
|
2358
2410
|
}
|
|
2359
2411
|
}
|
|
2360
2412
|
|
|
@@ -9,13 +9,14 @@ export {
|
|
|
9
9
|
export {
|
|
10
10
|
set_text,
|
|
11
11
|
set_class,
|
|
12
|
+
set_style,
|
|
12
13
|
set_attribute,
|
|
13
14
|
set_value,
|
|
14
15
|
set_checked,
|
|
15
16
|
set_selected,
|
|
16
17
|
} from './render.js';
|
|
17
18
|
|
|
18
|
-
export { render, render_spread, async, ref, branch } from './blocks.js';
|
|
19
|
+
export { render, render_spread, async, ref, branch, destroy_block } from './blocks.js';
|
|
19
20
|
|
|
20
21
|
export { event, delegate } from './events.js';
|
|
21
22
|
|
|
@@ -60,7 +61,7 @@ export { for_block as for, for_block_keyed as for_keyed } from './for.js';
|
|
|
60
61
|
|
|
61
62
|
export { if_block as if } from './if.js';
|
|
62
63
|
|
|
63
|
-
export { try_block as try, aborted } from './try.js';
|
|
64
|
+
export { try_block as try, aborted, suspend } from './try.js';
|
|
64
65
|
|
|
65
66
|
export { switch_block as switch } from './switch.js';
|
|
66
67
|
|
|
@@ -83,3 +84,5 @@ export { html } from './html.js';
|
|
|
83
84
|
export { rpc } from './rpc.js';
|
|
84
85
|
|
|
85
86
|
export { tsx_compat } from './compat.js';
|
|
87
|
+
|
|
88
|
+
export { TRY_BLOCK } from './constants.js';
|
|
@@ -28,12 +28,6 @@ export function init_operations() {
|
|
|
28
28
|
// @ts-expect-error
|
|
29
29
|
element_prototype.__click = undefined;
|
|
30
30
|
// @ts-expect-error
|
|
31
|
-
element_prototype.__attributes = null;
|
|
32
|
-
// @ts-expect-error
|
|
33
|
-
element_prototype.__styles = null;
|
|
34
|
-
// @ts-expect-error
|
|
35
|
-
element_prototype.__e = undefined;
|
|
36
|
-
// @ts-expect-error
|
|
37
31
|
event_target_prototype.__root = undefined;
|
|
38
32
|
}
|
|
39
33
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** @import { Block } from '#client' */
|
|
2
2
|
|
|
3
3
|
import { destroy_block, ref } from './blocks.js';
|
|
4
|
-
import { REF_PROP
|
|
4
|
+
import { REF_PROP } from './constants.js';
|
|
5
5
|
import {
|
|
6
6
|
get_descriptors,
|
|
7
7
|
get_own_property_symbols,
|
|
@@ -69,25 +69,29 @@ function get_setters(element) {
|
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* @param {Element} element
|
|
72
|
-
* @param {string} attribute
|
|
73
72
|
* @param {any} value
|
|
74
73
|
* @returns {void}
|
|
75
74
|
*/
|
|
76
|
-
export function
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
element.__styles = {};
|
|
75
|
+
export function set_style(element, value) {
|
|
76
|
+
if (value == null) {
|
|
77
|
+
element.removeAttribute('style');
|
|
78
|
+
} else if (typeof value !== 'string') {
|
|
79
|
+
apply_styles(/** @type {HTMLElement} */ (element), value);
|
|
80
|
+
} else {
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
element.style.cssText = value;
|
|
85
83
|
}
|
|
84
|
+
}
|
|
86
85
|
|
|
86
|
+
/**
|
|
87
|
+
* @param {Element} element
|
|
88
|
+
* @param {string} attribute
|
|
89
|
+
* @param {any} value
|
|
90
|
+
* @returns {void}
|
|
91
|
+
*/
|
|
92
|
+
export function set_attribute(element, attribute, value) {
|
|
87
93
|
if (value == null) {
|
|
88
94
|
element.removeAttribute(attribute);
|
|
89
|
-
} else if (attribute === 'style' && typeof value !== 'string') {
|
|
90
|
-
apply_styles(/** @type {HTMLElement} */ (element), value);
|
|
91
95
|
} else if (typeof value !== 'string' && get_setters(element).includes(attribute)) {
|
|
92
96
|
/** @type {any} */ (element)[attribute] = value;
|
|
93
97
|
} else {
|
|
@@ -97,13 +101,13 @@ export function set_attribute(element, attribute, value) {
|
|
|
97
101
|
|
|
98
102
|
/**
|
|
99
103
|
* @param {HTMLElement} element
|
|
100
|
-
* @param {HTMLElement['style']}
|
|
104
|
+
* @param {HTMLElement['style']} new_styles
|
|
101
105
|
*/
|
|
102
|
-
export function apply_styles(element,
|
|
106
|
+
export function apply_styles(element, new_styles) {
|
|
103
107
|
const style = element.style;
|
|
104
108
|
const new_properties = new Set();
|
|
105
109
|
|
|
106
|
-
for (const [property, value] of Object.entries(
|
|
110
|
+
for (const [property, value] of Object.entries(new_styles)) {
|
|
107
111
|
const normalized_property = normalize_css_property_name(property);
|
|
108
112
|
const normalized_value = String(value);
|
|
109
113
|
|
|
@@ -132,6 +136,8 @@ function set_attribute_helper(element, key, value) {
|
|
|
132
136
|
if (key === 'class') {
|
|
133
137
|
const is_html = element.namespaceURI === 'http://www.w3.org/1999/xhtml';
|
|
134
138
|
set_class(/** @type {HTMLElement} */ (element), value, undefined, is_html);
|
|
139
|
+
} else if (key === 'style') {
|
|
140
|
+
set_style(/** @type {HTMLElement} */ (element), value);
|
|
135
141
|
} else if (key === '#class') {
|
|
136
142
|
// Special case for static class when spreading props
|
|
137
143
|
element.classList.add(value);
|
|
@@ -933,12 +933,14 @@ export function spread_props(fn) {
|
|
|
933
933
|
* @returns {Object}
|
|
934
934
|
*/
|
|
935
935
|
export function proxy_props(fn) {
|
|
936
|
+
const memo = derived(fn, active_block);
|
|
937
|
+
|
|
936
938
|
return new Proxy(
|
|
937
939
|
{},
|
|
938
940
|
{
|
|
939
941
|
get(_, property) {
|
|
940
942
|
/** @type {Record<string | symbol, any> | Record<string | symbol, any>[]} */
|
|
941
|
-
var obj =
|
|
943
|
+
var obj = get_derived(memo);
|
|
942
944
|
|
|
943
945
|
// Handle array of objects/spreads (for multiple props)
|
|
944
946
|
if (is_array(obj)) {
|
|
@@ -962,7 +964,7 @@ export function proxy_props(fn) {
|
|
|
962
964
|
return true;
|
|
963
965
|
}
|
|
964
966
|
/** @type {Record<string | symbol, any> | Record<string | symbol, any>[]} */
|
|
965
|
-
var obj =
|
|
967
|
+
var obj = get_derived(memo);
|
|
966
968
|
|
|
967
969
|
// Handle array of objects/spreads
|
|
968
970
|
if (is_array(obj)) {
|
|
@@ -978,7 +980,7 @@ export function proxy_props(fn) {
|
|
|
978
980
|
},
|
|
979
981
|
getOwnPropertyDescriptor(_, key) {
|
|
980
982
|
/** @type {Record<string | symbol, any> | Record<string | symbol, any>[]} */
|
|
981
|
-
var obj =
|
|
983
|
+
var obj = get_derived(memo);
|
|
982
984
|
|
|
983
985
|
// Handle array of objects/spreads
|
|
984
986
|
if (is_array(obj)) {
|
|
@@ -999,7 +1001,7 @@ export function proxy_props(fn) {
|
|
|
999
1001
|
},
|
|
1000
1002
|
ownKeys() {
|
|
1001
1003
|
/** @type {Record<string | symbol, any> | Record<string | symbol, any>[]} */
|
|
1002
|
-
var obj =
|
|
1004
|
+
var obj = get_derived(memo);
|
|
1003
1005
|
/** @type {Record<string | symbol, 1>} */
|
|
1004
1006
|
var done = {};
|
|
1005
1007
|
/** @type {(string | symbol)[]} */
|
|
@@ -74,4 +74,34 @@ describe('refs', () => {
|
|
|
74
74
|
|
|
75
75
|
expect(logs).toEqual(['ref called', 'ref called']);
|
|
76
76
|
});
|
|
77
|
+
|
|
78
|
+
it('should handle spreading props with a static ref', () => {
|
|
79
|
+
let logs: string[] = [];
|
|
80
|
+
|
|
81
|
+
component App() {
|
|
82
|
+
let value = track('test');
|
|
83
|
+
|
|
84
|
+
function inputRef(node) {
|
|
85
|
+
logs.push('ref called');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const props = {
|
|
89
|
+
id: 'example',
|
|
90
|
+
@value,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
<input type="text" {ref inputRef} {...props} />
|
|
94
|
+
|
|
95
|
+
<Input {ref inputRef} {...props} />
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
component Input({ id, value, ...rest }) {
|
|
99
|
+
<input type="text" {id} {value} {...rest} />
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
render(App);
|
|
103
|
+
flushSync();
|
|
104
|
+
|
|
105
|
+
expect(logs).toEqual(['ref called', 'ref called']);
|
|
106
|
+
});
|
|
77
107
|
});
|