xote 5.0.0 → 6.0.1
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/README.md +43 -193
- package/dist/xote.cjs +7 -7
- package/dist/xote.mjs +1267 -1189
- package/dist/xote.umd.js +10 -10
- package/package.json +13 -3
- package/rescript.json +18 -3
- package/src/Computed.res +1 -0
- package/src/Computed.res.mjs +13 -0
- package/src/Effect.res +1 -0
- package/src/Effect.res.mjs +13 -0
- package/src/Html.res +28 -0
- package/src/Html.res.mjs +62 -0
- package/src/{Xote__Hydration.res → Hydration.res} +43 -41
- package/src/{Xote__Hydration.res.mjs → Hydration.res.mjs} +66 -68
- package/src/{Xote__Component.res → Node.res} +3 -26
- package/src/{Xote__Component.res.mjs → Node.res.mjs} +26 -88
- package/src/{Xote__ReactiveProp.res → ReactiveProp.res} +0 -1
- package/src/{Xote__ReactiveProp.res.mjs → ReactiveProp.res.mjs} +2 -2
- package/src/{Xote__Router.res → Router.res} +38 -32
- package/src/{Xote__Router.res.mjs → Router.res.mjs} +28 -28
- package/src/{Xote__SSR.res → SSR.res} +16 -18
- package/src/{Xote__SSR.res.mjs → SSR.res.mjs} +5 -8
- package/src/{Xote__SSRState.res → SSRState.res} +7 -6
- package/src/{Xote__SSRState.res.mjs → SSRState.res.mjs} +12 -12
- package/src/Signal.res +1 -0
- package/src/Signal.res.mjs +31 -0
- package/src/{Xote__JSX.res → XoteJSX.res} +22 -23
- package/src/{Xote__JSX.res.mjs → XoteJSX.res.mjs} +22 -24
- package/src/Xote.res +0 -43
- package/src/Xote.res.mjs +0 -117
- /package/src/{Xote__Route.res → Route.res} +0 -0
- /package/src/{Xote__Route.res.mjs → Route.res.mjs} +0 -0
- /package/src/{Xote__SSRContext.res → SSRContext.res} +0 -0
- /package/src/{Xote__SSRContext.res.mjs → SSRContext.res.mjs} +0 -0
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
open Signals
|
|
2
1
|
|
|
3
|
-
module Component = Xote__Component
|
|
4
2
|
|
|
5
3
|
/* ============================================================================
|
|
6
4
|
* HTML Utilities
|
|
@@ -77,11 +75,11 @@ type renderOptions = {
|
|
|
77
75
|
|
|
78
76
|
module Attributes = {
|
|
79
77
|
/* Render a single attribute to string */
|
|
80
|
-
let renderAttr = ((key, value): (string,
|
|
78
|
+
let renderAttr = ((key, value): (string, Node.attrValue)): string => {
|
|
81
79
|
let attrValue = switch value {
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
80
|
+
| Node.Static(v) => v
|
|
81
|
+
| Node.SignalValue(signal) => Signal.peek(signal)
|
|
82
|
+
| Node.Compute(fn) => fn()
|
|
85
83
|
}
|
|
86
84
|
|
|
87
85
|
/* Handle boolean attributes */
|
|
@@ -104,7 +102,7 @@ module Attributes = {
|
|
|
104
102
|
}
|
|
105
103
|
|
|
106
104
|
/* Render all attributes to string */
|
|
107
|
-
let renderAttrs = (attrs: array<(string,
|
|
105
|
+
let renderAttrs = (attrs: array<(string, Node.attrValue)>): string => {
|
|
108
106
|
let rendered =
|
|
109
107
|
attrs
|
|
110
108
|
->Array.map(renderAttr)
|
|
@@ -123,26 +121,26 @@ module Attributes = {
|
|
|
123
121
|
* ============================================================================ */
|
|
124
122
|
|
|
125
123
|
/* Render a virtual node to an HTML string */
|
|
126
|
-
let rec renderNodeToString = (node:
|
|
124
|
+
let rec renderNodeToString = (node: Node.node): string => {
|
|
127
125
|
switch node {
|
|
128
|
-
|
|
|
126
|
+
| Node.Text(content) => Html.escape(content)
|
|
129
127
|
|
|
130
|
-
|
|
|
128
|
+
| Node.SignalText(signal) => {
|
|
131
129
|
/* Read current signal value and wrap with hydration markers */
|
|
132
130
|
let value = Signal.peek(signal)
|
|
133
131
|
Markers.signalTextStart ++ Html.escape(value) ++ Markers.signalTextEnd
|
|
134
132
|
}
|
|
135
133
|
|
|
136
|
-
|
|
|
134
|
+
| Node.Fragment(children) => children->Array.map(renderNodeToString)->Array.join("")
|
|
137
135
|
|
|
138
|
-
|
|
|
136
|
+
| Node.SignalFragment(signal) => {
|
|
139
137
|
/* Read current signal value and wrap with hydration markers */
|
|
140
138
|
let children = Signal.peek(signal)
|
|
141
139
|
let content = children->Array.map(renderNodeToString)->Array.join("")
|
|
142
140
|
Markers.signalFragmentStart ++ content ++ Markers.signalFragmentEnd
|
|
143
141
|
}
|
|
144
142
|
|
|
145
|
-
|
|
|
143
|
+
| Node.Element({tag, attrs, children, events: _}) => {
|
|
146
144
|
let attrsStr = Attributes.renderAttrs(attrs)
|
|
147
145
|
|
|
148
146
|
if Html.isVoidElement(tag) {
|
|
@@ -153,13 +151,13 @@ let rec renderNodeToString = (node: Component.node): string => {
|
|
|
153
151
|
}
|
|
154
152
|
}
|
|
155
153
|
|
|
156
|
-
|
|
|
154
|
+
| Node.LazyComponent(fn) => {
|
|
157
155
|
/* Execute the lazy component and render its result */
|
|
158
156
|
let childNode = fn()
|
|
159
157
|
Markers.lazyComponentStart ++ renderNodeToString(childNode) ++ Markers.lazyComponentEnd
|
|
160
158
|
}
|
|
161
159
|
|
|
162
|
-
|
|
|
160
|
+
| Node.KeyedList({signal, keyFn, renderItem}) => {
|
|
163
161
|
let items = Signal.peek(signal)
|
|
164
162
|
let content =
|
|
165
163
|
items
|
|
@@ -180,7 +178,7 @@ let rec renderNodeToString = (node: Component.node): string => {
|
|
|
180
178
|
* ============================================================================ */
|
|
181
179
|
|
|
182
180
|
/* Render a component to an HTML string synchronously */
|
|
183
|
-
let renderToString = (component: unit =>
|
|
181
|
+
let renderToString = (component: unit => Node.node, ~options: renderOptions={}): string => {
|
|
184
182
|
let _ = options /* Will be used for nonce/renderId in future phases */
|
|
185
183
|
let node = component()
|
|
186
184
|
renderNodeToString(node)
|
|
@@ -188,7 +186,7 @@ let renderToString = (component: unit => Component.node, ~options: renderOptions
|
|
|
188
186
|
|
|
189
187
|
/* Render a component and wrap with a hydration root marker */
|
|
190
188
|
let renderToStringWithRoot = (
|
|
191
|
-
component: unit =>
|
|
189
|
+
component: unit => Node.node,
|
|
192
190
|
~rootId: string="root",
|
|
193
191
|
~options: renderOptions={},
|
|
194
192
|
): string => {
|
|
@@ -218,7 +216,7 @@ let renderDocument = (
|
|
|
218
216
|
~styles: array<string>=[],
|
|
219
217
|
~stateScript: string="",
|
|
220
218
|
~nonce: option<string>=?,
|
|
221
|
-
component: unit =>
|
|
219
|
+
component: unit => Node.node,
|
|
222
220
|
): string => {
|
|
223
221
|
let content = renderToString(component)
|
|
224
222
|
let hydrationScript = generateHydrationScript(~nonce?)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as
|
|
3
|
+
import * as Signal$Xote from "./Signal.res.mjs";
|
|
4
4
|
|
|
5
5
|
function escape(str) {
|
|
6
6
|
return str.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("\"", """).replaceAll("'", "'");
|
|
@@ -77,7 +77,7 @@ function renderAttr(param) {
|
|
|
77
77
|
attrValue = value._0;
|
|
78
78
|
break;
|
|
79
79
|
case "SignalValue" :
|
|
80
|
-
attrValue =
|
|
80
|
+
attrValue = Signal$Xote.peek(value._0);
|
|
81
81
|
break;
|
|
82
82
|
case "Compute" :
|
|
83
83
|
attrValue = value._0();
|
|
@@ -130,12 +130,12 @@ function renderNodeToString(node) {
|
|
|
130
130
|
case "Text" :
|
|
131
131
|
return escape(node._0);
|
|
132
132
|
case "SignalText" :
|
|
133
|
-
let value =
|
|
133
|
+
let value = Signal$Xote.peek(node._0);
|
|
134
134
|
return signalTextStart + escape(value) + signalTextEnd;
|
|
135
135
|
case "Fragment" :
|
|
136
136
|
return node._0.map(renderNodeToString).join("");
|
|
137
137
|
case "SignalFragment" :
|
|
138
|
-
let children =
|
|
138
|
+
let children = Signal$Xote.peek(node._0);
|
|
139
139
|
let content = children.map(renderNodeToString).join("");
|
|
140
140
|
return signalFragmentStart + content + signalFragmentEnd;
|
|
141
141
|
case "LazyComponent" :
|
|
@@ -144,7 +144,7 @@ function renderNodeToString(node) {
|
|
|
144
144
|
case "KeyedList" :
|
|
145
145
|
let renderItem = node.renderItem;
|
|
146
146
|
let keyFn = node.keyFn;
|
|
147
|
-
let items =
|
|
147
|
+
let items = Signal$Xote.peek(node.signal);
|
|
148
148
|
let content$1 = items.map(item => {
|
|
149
149
|
let key = keyFn(item);
|
|
150
150
|
let itemHtml = renderNodeToString(renderItem(item));
|
|
@@ -202,10 +202,7 @@ function renderDocument(headOpt, bodyAttrsOpt, scriptsOpt, stylesOpt, stateScrip
|
|
|
202
202
|
</html>`;
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
let Component;
|
|
206
|
-
|
|
207
205
|
export {
|
|
208
|
-
Component,
|
|
209
206
|
Html,
|
|
210
207
|
Markers,
|
|
211
208
|
Attributes,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
open Signals
|
|
2
1
|
|
|
3
2
|
/* ============================================================================
|
|
4
3
|
* SSR State Serialization
|
|
@@ -85,6 +84,7 @@ module Codec = {
|
|
|
85
84
|
let tuple2 = (codec1: t<'a>, codec2: t<'b>): t<('a, 'b)> => {
|
|
86
85
|
encode: ((a, b)) => JSON.Encode.array([codec1.encode(a), codec2.encode(b)]),
|
|
87
86
|
decode: json => {
|
|
87
|
+
ignore(json)
|
|
88
88
|
let arr: option<array<JSON.t>> = %raw(`Array.isArray(json) ? json : undefined`)
|
|
89
89
|
switch arr {
|
|
90
90
|
| Some([j1, j2]) =>
|
|
@@ -101,6 +101,7 @@ module Codec = {
|
|
|
101
101
|
encode: ((a, b, c)) =>
|
|
102
102
|
JSON.Encode.array([codec1.encode(a), codec2.encode(b), codec3.encode(c)]),
|
|
103
103
|
decode: json => {
|
|
104
|
+
ignore(json)
|
|
104
105
|
let arr: option<array<JSON.t>> = %raw(`Array.isArray(json) ? json : undefined`)
|
|
105
106
|
switch arr {
|
|
106
107
|
| Some([j1, j2, j3]) =>
|
|
@@ -165,7 +166,7 @@ let registry: Dict.t<JSON.t> = Dict.make()
|
|
|
165
166
|
|
|
166
167
|
/* Register a signal for serialization (server only) */
|
|
167
168
|
let register = (id: string, signal: Signal.t<'a>, codec: Codec.t<'a>): unit => {
|
|
168
|
-
if
|
|
169
|
+
if SSRContext.isServer {
|
|
169
170
|
registry->Dict.set(id, codec.encode(Signal.peek(signal)))
|
|
170
171
|
}
|
|
171
172
|
}
|
|
@@ -192,7 +193,7 @@ let generateScript = (~nonce: option<string>=?): string => {
|
|
|
192
193
|
let json = JSON.stringifyAny(registry)->Option.getOr("{}")
|
|
193
194
|
let escapedJson = escapeForScript(json)
|
|
194
195
|
let nonceAttr = switch nonce {
|
|
195
|
-
| Some(n) => ` nonce="${
|
|
196
|
+
| Some(n) => ` nonce="${SSR.Html.escape(n)}"`
|
|
196
197
|
| None => ""
|
|
197
198
|
}
|
|
198
199
|
`<script${nonceAttr}>window.__XOTE_STATE__=${escapedJson};</script>`
|
|
@@ -204,7 +205,7 @@ let generateScript = (~nonce: option<string>=?): string => {
|
|
|
204
205
|
|
|
205
206
|
/* Get the serialized state from window */
|
|
206
207
|
let getClientState = (): Dict.t<JSON.t> => {
|
|
207
|
-
if
|
|
208
|
+
if SSRContext.isClient {
|
|
208
209
|
%raw(`window.__XOTE_STATE__ || {}`)
|
|
209
210
|
} else {
|
|
210
211
|
Dict.make()
|
|
@@ -213,7 +214,7 @@ let getClientState = (): Dict.t<JSON.t> => {
|
|
|
213
214
|
|
|
214
215
|
/* Restore a signal from serialized state (client only) */
|
|
215
216
|
let restore = (id: string, signal: Signal.t<'a>, codec: Codec.t<'a>): unit => {
|
|
216
|
-
if
|
|
217
|
+
if SSRContext.isClient {
|
|
217
218
|
let state = getClientState()
|
|
218
219
|
switch state->Dict.get(id) {
|
|
219
220
|
| Some(json) =>
|
|
@@ -232,7 +233,7 @@ let restore = (id: string, signal: Signal.t<'a>, codec: Codec.t<'a>): unit => {
|
|
|
232
233
|
|
|
233
234
|
/* Sync a signal: register on server, restore on client */
|
|
234
235
|
let sync = (id: string, signal: Signal.t<'a>, codec: Codec.t<'a>): unit => {
|
|
235
|
-
|
|
236
|
+
SSRContext.match(
|
|
236
237
|
~server=() => register(id, signal, codec),
|
|
237
238
|
~client=() => restore(id, signal, codec),
|
|
238
239
|
)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as
|
|
4
|
-
import * as
|
|
3
|
+
import * as SSR$Xote from "./SSR.res.mjs";
|
|
4
|
+
import * as Signal$Xote from "./Signal.res.mjs";
|
|
5
5
|
import * as Stdlib_Dict from "@rescript/runtime/lib/es6/Stdlib_Dict.js";
|
|
6
6
|
import * as Stdlib_JSON from "@rescript/runtime/lib/es6/Stdlib_JSON.js";
|
|
7
7
|
import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
|
|
8
8
|
import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
|
|
9
|
+
import * as SSRContext$Xote from "./SSRContext.res.mjs";
|
|
9
10
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
10
|
-
import * as Xote__SSRContext from "./Xote__SSRContext.res.mjs";
|
|
11
11
|
|
|
12
12
|
function int_encode(v) {
|
|
13
13
|
return v;
|
|
@@ -215,8 +215,8 @@ let Codec = {
|
|
|
215
215
|
let registry = {};
|
|
216
216
|
|
|
217
217
|
function register(id, signal, codec) {
|
|
218
|
-
if (
|
|
219
|
-
registry[id] = codec.encode(
|
|
218
|
+
if (SSRContext$Xote.isServer) {
|
|
219
|
+
registry[id] = codec.encode(Signal$Xote.peek(signal));
|
|
220
220
|
return;
|
|
221
221
|
}
|
|
222
222
|
}
|
|
@@ -234,12 +234,12 @@ function escapeForScript(str) {
|
|
|
234
234
|
function generateScript(nonce) {
|
|
235
235
|
let json = Stdlib_Option.getOr(JSON.stringify(registry), "{}");
|
|
236
236
|
let escapedJson = escapeForScript(json);
|
|
237
|
-
let nonceAttr = nonce !== undefined ? ` nonce="` +
|
|
237
|
+
let nonceAttr = nonce !== undefined ? ` nonce="` + SSR$Xote.Html.escape(nonce) + `"` : "";
|
|
238
238
|
return `<script` + nonceAttr + `>window.__XOTE_STATE__=` + escapedJson + `;</script>`;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
241
|
function getClientState() {
|
|
242
|
-
if (
|
|
242
|
+
if (SSRContext$Xote.isClient) {
|
|
243
243
|
return (window.__XOTE_STATE__ || {});
|
|
244
244
|
} else {
|
|
245
245
|
return {};
|
|
@@ -247,7 +247,7 @@ function getClientState() {
|
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
function restore(id, signal, codec) {
|
|
250
|
-
if (!
|
|
250
|
+
if (!SSRContext$Xote.isClient) {
|
|
251
251
|
return;
|
|
252
252
|
}
|
|
253
253
|
let state = getClientState();
|
|
@@ -257,16 +257,16 @@ function restore(id, signal, codec) {
|
|
|
257
257
|
}
|
|
258
258
|
let value = codec.decode(json);
|
|
259
259
|
if (value !== undefined) {
|
|
260
|
-
return
|
|
260
|
+
return Signal$Xote.set(signal, Primitive_option.valFromOption(value));
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
function sync(id, signal, codec) {
|
|
265
|
-
|
|
265
|
+
SSRContext$Xote.match(() => register(id, signal, codec), () => restore(id, signal, codec));
|
|
266
266
|
}
|
|
267
267
|
|
|
268
268
|
function make$1(id, initial, codec) {
|
|
269
|
-
let signal =
|
|
269
|
+
let signal = Signal$Xote.make(initial, undefined, undefined);
|
|
270
270
|
sync(id, signal, codec);
|
|
271
271
|
return signal;
|
|
272
272
|
}
|
|
@@ -283,4 +283,4 @@ export {
|
|
|
283
283
|
sync,
|
|
284
284
|
make$1 as make,
|
|
285
285
|
}
|
|
286
|
-
/*
|
|
286
|
+
/* SSRContext-Xote Not a pure module */
|
package/src/Signal.res
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include Signals.Signal
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Signal$Signals from "rescript-signals/src/signals/Signal.res.mjs";
|
|
4
|
+
|
|
5
|
+
let make = Signal$Signals.make;
|
|
6
|
+
|
|
7
|
+
let makeForComputed = Signal$Signals.makeForComputed;
|
|
8
|
+
|
|
9
|
+
let get = Signal$Signals.get;
|
|
10
|
+
|
|
11
|
+
let peek = Signal$Signals.peek;
|
|
12
|
+
|
|
13
|
+
let set = Signal$Signals.set;
|
|
14
|
+
|
|
15
|
+
let update = Signal$Signals.update;
|
|
16
|
+
|
|
17
|
+
let batch = Signal$Signals.batch;
|
|
18
|
+
|
|
19
|
+
let untrack = Signal$Signals.untrack;
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
make,
|
|
23
|
+
makeForComputed,
|
|
24
|
+
get,
|
|
25
|
+
peek,
|
|
26
|
+
set,
|
|
27
|
+
update,
|
|
28
|
+
batch,
|
|
29
|
+
untrack,
|
|
30
|
+
}
|
|
31
|
+
/* No side effect */
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
module Component = Xote__Component
|
|
3
|
-
module ReactiveProp = Xote__ReactiveProp
|
|
1
|
+
module ReactiveProp = ReactiveProp
|
|
4
2
|
|
|
5
3
|
/* ReScript JSX transform type aliases */
|
|
6
|
-
type element =
|
|
4
|
+
type element = Node.node
|
|
7
5
|
|
|
8
6
|
type component<'props> = 'props => element
|
|
9
7
|
|
|
@@ -14,7 +12,7 @@ type componentLike<'props, 'return> = 'props => 'return
|
|
|
14
12
|
* evaluated during a Computed context, which would incorrectly track their
|
|
15
13
|
* dependencies as belonging to the outer computed. */
|
|
16
14
|
let jsx = (component: component<'props>, props: 'props): element =>
|
|
17
|
-
|
|
15
|
+
Node.LazyComponent(() => component(props))
|
|
18
16
|
|
|
19
17
|
let jsxs = jsx
|
|
20
18
|
|
|
@@ -36,14 +34,14 @@ type fragmentProps = {children?: element}
|
|
|
36
34
|
let jsxFragment = (props: fragmentProps): element => {
|
|
37
35
|
switch props.children {
|
|
38
36
|
| Some(child) => child
|
|
39
|
-
| None =>
|
|
37
|
+
| None => Node.fragment([])
|
|
40
38
|
}
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
/* Element converters for JSX expressions */
|
|
44
|
-
let array = (children: array<element>): element =>
|
|
42
|
+
let array = (children: array<element>): element => Node.fragment(children)
|
|
45
43
|
|
|
46
|
-
let null = (): element =>
|
|
44
|
+
let null = (): element => Node.text("")
|
|
47
45
|
|
|
48
46
|
/* Elements module for lowercase HTML tags */
|
|
49
47
|
module Elements = {
|
|
@@ -146,58 +144,59 @@ module Elements = {
|
|
|
146
144
|
|
|
147
145
|
/* Helper to detect if a value is a ReactiveProp variant (checks for Static/Reactive tags) */
|
|
148
146
|
let isReactiveProp = (value: 'a): bool => {
|
|
147
|
+
ignore(value)
|
|
149
148
|
%raw(`value && typeof value === 'object' && ('TAG' in value) && (value.TAG === 'Static' || value.TAG === 'Reactive')`)
|
|
150
149
|
}
|
|
151
150
|
|
|
152
151
|
/* Helper to convert string attribute value (supports raw string, ReactiveProp, Signal, or computed function) */
|
|
153
|
-
let convertAttrValue = (key: string, value: 'a): (string,
|
|
152
|
+
let convertAttrValue = (key: string, value: 'a): (string, Node.attrValue) => {
|
|
154
153
|
if isReactiveProp(value) {
|
|
155
154
|
// It's a ReactiveProp variant - pattern match on it
|
|
156
155
|
let rp: ReactiveProp.t<string> = Obj.magic(value)
|
|
157
156
|
switch rp {
|
|
158
|
-
| Static(s) =>
|
|
159
|
-
| Reactive(signal) =>
|
|
157
|
+
| Static(s) => Node.attr(key, s)
|
|
158
|
+
| Reactive(signal) => Node.signalAttr(key, signal)
|
|
160
159
|
}
|
|
161
160
|
} else if typeof(value) == #function {
|
|
162
161
|
// It's a computed function (for backward compatibility)
|
|
163
162
|
let f: unit => string = Obj.magic(value)
|
|
164
|
-
|
|
163
|
+
Node.computedAttr(key, f)
|
|
165
164
|
} else if typeof(value) == #object {
|
|
166
165
|
// It's a raw signal (for backward compatibility)
|
|
167
166
|
let sig: Signal.t<string> = Obj.magic(value)
|
|
168
|
-
|
|
167
|
+
Node.signalAttr(key, sig)
|
|
169
168
|
} else {
|
|
170
169
|
// It's a raw string
|
|
171
170
|
let s: string = Obj.magic(value)
|
|
172
|
-
|
|
171
|
+
Node.attr(key, s)
|
|
173
172
|
}
|
|
174
173
|
}
|
|
175
174
|
|
|
176
175
|
/* Helper to convert boolean attribute value (supports raw bool, ReactiveProp, Signal, or computed function) */
|
|
177
|
-
let convertBoolAttrValue = (key: string, value: 'a): (string,
|
|
176
|
+
let convertBoolAttrValue = (key: string, value: 'a): (string, Node.attrValue) => {
|
|
178
177
|
if isReactiveProp(value) {
|
|
179
178
|
// It's a ReactiveProp variant - pattern match on it
|
|
180
179
|
let rp: ReactiveProp.t<bool> = Obj.magic(value)
|
|
181
180
|
switch rp {
|
|
182
|
-
| Static(b) =>
|
|
181
|
+
| Static(b) => Node.attr(key, b ? "true" : "false")
|
|
183
182
|
| Reactive(signal) => {
|
|
184
183
|
let strSignal = Computed.make(() => Signal.get(signal) ? "true" : "false")
|
|
185
|
-
|
|
184
|
+
Node.signalAttr(key, strSignal)
|
|
186
185
|
}
|
|
187
186
|
}
|
|
188
187
|
} else if typeof(value) == #function {
|
|
189
188
|
// It's a computed function that returns bool (for backward compatibility)
|
|
190
189
|
let f: unit => bool = Obj.magic(value)
|
|
191
|
-
|
|
190
|
+
Node.computedAttr(key, () => f() ? "true" : "false")
|
|
192
191
|
} else if typeof(value) == #object {
|
|
193
192
|
// It's a raw signal (for backward compatibility)
|
|
194
193
|
let sig: Signal.t<bool> = Obj.magic(value)
|
|
195
194
|
let strSignal = Computed.make(() => Signal.get(sig) ? "true" : "false")
|
|
196
|
-
|
|
195
|
+
Node.signalAttr(key, strSignal)
|
|
197
196
|
} else {
|
|
198
197
|
// It's a raw bool
|
|
199
198
|
let b: bool = Obj.magic(value)
|
|
200
|
-
|
|
199
|
+
Node.attr(key, b ? "true" : "false")
|
|
201
200
|
}
|
|
202
201
|
}
|
|
203
202
|
|
|
@@ -212,7 +211,7 @@ module Elements = {
|
|
|
212
211
|
/* Helper to add optional int attribute */
|
|
213
212
|
let addIntAttr = (attrs, opt, key) => {
|
|
214
213
|
switch opt {
|
|
215
|
-
| Some(v) => attrs->Array.push(
|
|
214
|
+
| Some(v) => attrs->Array.push(Node.attr(key, Int.toString(v)))
|
|
216
215
|
| None => ()
|
|
217
216
|
}
|
|
218
217
|
}
|
|
@@ -251,7 +250,7 @@ module Elements = {
|
|
|
251
250
|
_,
|
|
252
251
|
_,
|
|
253
252
|
>,
|
|
254
|
-
): array<(string,
|
|
253
|
+
): array<(string, Node.attrValue)> => {
|
|
255
254
|
let attrs = []
|
|
256
255
|
|
|
257
256
|
/* Standard attributes */
|
|
@@ -457,7 +456,7 @@ module Elements = {
|
|
|
457
456
|
_,
|
|
458
457
|
>,
|
|
459
458
|
): element => {
|
|
460
|
-
|
|
459
|
+
Node.Element({
|
|
461
460
|
tag,
|
|
462
461
|
attrs: propsToAttrs(props),
|
|
463
462
|
events: propsToEvents(props),
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
2
|
|
|
3
|
-
import * as
|
|
4
|
-
import * as
|
|
3
|
+
import * as Node$Xote from "./Node.res.mjs";
|
|
4
|
+
import * as Signal$Xote from "./Signal.res.mjs";
|
|
5
|
+
import * as Computed$Xote from "./Computed.res.mjs";
|
|
5
6
|
import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
|
|
6
7
|
|
|
7
8
|
function jsx(component, props) {
|
|
@@ -23,14 +24,14 @@ function jsxFragment(props) {
|
|
|
23
24
|
if (child !== undefined) {
|
|
24
25
|
return child;
|
|
25
26
|
} else {
|
|
26
|
-
return
|
|
27
|
+
return Node$Xote.fragment([]);
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
let array =
|
|
31
|
+
let array = Node$Xote.fragment;
|
|
31
32
|
|
|
32
33
|
function $$null() {
|
|
33
|
-
return
|
|
34
|
+
return Node$Xote.text("");
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
function isReactiveProp(value) {
|
|
@@ -40,36 +41,36 @@ function isReactiveProp(value) {
|
|
|
40
41
|
function convertAttrValue(key, value) {
|
|
41
42
|
if (isReactiveProp(value)) {
|
|
42
43
|
if (value.TAG === "Reactive") {
|
|
43
|
-
return
|
|
44
|
+
return Node$Xote.signalAttr(key, value._0);
|
|
44
45
|
} else {
|
|
45
|
-
return
|
|
46
|
+
return Node$Xote.attr(key, value._0);
|
|
46
47
|
}
|
|
47
48
|
} else if (typeof value === "function") {
|
|
48
|
-
return
|
|
49
|
+
return Node$Xote.computedAttr(key, value);
|
|
49
50
|
} else if (typeof value === "object") {
|
|
50
|
-
return
|
|
51
|
+
return Node$Xote.signalAttr(key, value);
|
|
51
52
|
} else {
|
|
52
|
-
return
|
|
53
|
+
return Node$Xote.attr(key, value);
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
function convertBoolAttrValue(key, value) {
|
|
57
58
|
if (isReactiveProp(value)) {
|
|
58
59
|
if (value.TAG !== "Reactive") {
|
|
59
|
-
return
|
|
60
|
+
return Node$Xote.attr(key, value._0 ? "true" : "false");
|
|
60
61
|
}
|
|
61
62
|
let signal = value._0;
|
|
62
|
-
let strSignal =
|
|
63
|
-
if (
|
|
63
|
+
let strSignal = Computed$Xote.make(() => {
|
|
64
|
+
if (Signal$Xote.get(signal)) {
|
|
64
65
|
return "true";
|
|
65
66
|
} else {
|
|
66
67
|
return "false";
|
|
67
68
|
}
|
|
68
69
|
}, undefined);
|
|
69
|
-
return
|
|
70
|
+
return Node$Xote.signalAttr(key, strSignal);
|
|
70
71
|
}
|
|
71
72
|
if (typeof value === "function") {
|
|
72
|
-
return
|
|
73
|
+
return Node$Xote.computedAttr(key, () => {
|
|
73
74
|
if (value()) {
|
|
74
75
|
return "true";
|
|
75
76
|
} else {
|
|
@@ -78,16 +79,16 @@ function convertBoolAttrValue(key, value) {
|
|
|
78
79
|
});
|
|
79
80
|
}
|
|
80
81
|
if (typeof value !== "object") {
|
|
81
|
-
return
|
|
82
|
+
return Node$Xote.attr(key, value ? "true" : "false");
|
|
82
83
|
}
|
|
83
|
-
let strSignal$1 =
|
|
84
|
-
if (
|
|
84
|
+
let strSignal$1 = Computed$Xote.make(() => {
|
|
85
|
+
if (Signal$Xote.get(value)) {
|
|
85
86
|
return "true";
|
|
86
87
|
} else {
|
|
87
88
|
return "false";
|
|
88
89
|
}
|
|
89
90
|
}, undefined);
|
|
90
|
-
return
|
|
91
|
+
return Node$Xote.signalAttr(key, strSignal$1);
|
|
91
92
|
}
|
|
92
93
|
|
|
93
94
|
function addAttr(attrs, opt, key, converter) {
|
|
@@ -99,7 +100,7 @@ function addAttr(attrs, opt, key, converter) {
|
|
|
99
100
|
|
|
100
101
|
function addIntAttr(attrs, opt, key) {
|
|
101
102
|
if (opt !== undefined) {
|
|
102
|
-
attrs.push(
|
|
103
|
+
attrs.push(Node$Xote.attr(key, opt.toString()));
|
|
103
104
|
return;
|
|
104
105
|
}
|
|
105
106
|
}
|
|
@@ -225,8 +226,6 @@ let Elements = {
|
|
|
225
226
|
jsxsKeyed: jsxKeyed$1
|
|
226
227
|
};
|
|
227
228
|
|
|
228
|
-
let Component;
|
|
229
|
-
|
|
230
229
|
let ReactiveProp;
|
|
231
230
|
|
|
232
231
|
let jsxs = jsx;
|
|
@@ -234,7 +233,6 @@ let jsxs = jsx;
|
|
|
234
233
|
let jsxsKeyed = jsxKeyed;
|
|
235
234
|
|
|
236
235
|
export {
|
|
237
|
-
Component,
|
|
238
236
|
ReactiveProp,
|
|
239
237
|
jsx,
|
|
240
238
|
jsxs,
|
|
@@ -245,4 +243,4 @@ export {
|
|
|
245
243
|
$$null,
|
|
246
244
|
Elements,
|
|
247
245
|
}
|
|
248
|
-
/*
|
|
246
|
+
/* Node-Xote Not a pure module */
|
package/src/Xote.res
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
module Signal = {
|
|
2
|
-
include Signals.Signal
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
module Computed = {
|
|
6
|
-
include Signals.Computed
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
module Effect = {
|
|
10
|
-
include Signals.Effect
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
module Component = {
|
|
14
|
-
include Xote__Component
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module Route = {
|
|
18
|
-
include Xote__Route
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
module Router = {
|
|
22
|
-
include Xote__Router
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
module ReactiveProp = {
|
|
26
|
-
include Xote__ReactiveProp
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
module SSR = {
|
|
30
|
-
include Xote__SSR
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
module SSRContext = {
|
|
34
|
-
include Xote__SSRContext
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
module SSRState = {
|
|
38
|
-
include Xote__SSRState
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
module Hydration = {
|
|
42
|
-
include Xote__Hydration
|
|
43
|
-
}
|