cradova 2.2.2 → 2.3.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/README.md +276 -110
- package/dist/index.js +302 -298
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,11 +49,12 @@ Cradova follows the [VJS specification](https://github.com/fridaycandour/cradova
|
|
|
49
49
|
|
|
50
50
|
Cradova is aimed to be fast and simple with and fewer abstractions and yet easily composable.
|
|
51
51
|
|
|
52
|
-
Cradova
|
|
52
|
+
Cradova is not built on visual DOM or diff algorithms.
|
|
53
|
+
Instead, State management is done more elegantly with a simple predictive model, simple and easy with all the speed.
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
## Is this a big benefit?
|
|
55
56
|
|
|
56
|
-
Undoubtedly, this provides a significant advantage. You can experience it firsthand and decide
|
|
57
|
+
Undoubtedly, this provides a significant advantage. You can experience it firsthand and decide.
|
|
57
58
|
|
|
58
59
|
Cradova has already been utilized in multiple production projects, and we will continuously update this page to showcase our advancements as we keep improving.
|
|
59
60
|
|
|
@@ -83,12 +84,10 @@ npm i cradova
|
|
|
83
84
|
|
|
84
85
|
Many aspects of Cradova are not reflected in the following example. More functionality will be entailed in future docs.
|
|
85
86
|
|
|
86
|
-
|
|
87
|
+
## A basic component in Cradova:
|
|
87
88
|
|
|
88
89
|
```js
|
|
89
|
-
|
|
90
|
-
// this gives your app more performance gain.
|
|
91
|
-
import _, { h1 } from "cradova";
|
|
90
|
+
import { div, h1 } from "cradova";
|
|
92
91
|
|
|
93
92
|
function Hello(name) {
|
|
94
93
|
return h1("Hello " + name, {
|
|
@@ -99,88 +98,56 @@ function Hello(name) {
|
|
|
99
98
|
});
|
|
100
99
|
}
|
|
101
100
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const html = _(Hello("peter"), Hello("joe"));
|
|
101
|
+
const html = div(Hello("peter"), Hello("joe"));
|
|
105
102
|
|
|
106
103
|
document.body.append(html);
|
|
107
104
|
```
|
|
108
105
|
|
|
109
|
-
|
|
110
|
-
// regular example
|
|
111
|
-
import _ from "cradova";
|
|
112
|
-
|
|
113
|
-
function Hello(name) {
|
|
114
|
-
return _("h1", "Hello " + name);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const html = _(Hello("peter"), Hello("joe"));
|
|
118
|
-
|
|
119
|
-
document.body.append(html);
|
|
120
|
-
```
|
|
106
|
+
## working with state:
|
|
121
107
|
|
|
122
|
-
|
|
108
|
+
this a collection of basic examples
|
|
109
|
+
you can choose any that best suite what problem you want to solve
|
|
123
110
|
|
|
124
111
|
```js
|
|
125
|
-
import _, {
|
|
112
|
+
import _, {
|
|
113
|
+
button,
|
|
114
|
+
createSignal,
|
|
115
|
+
Ref,
|
|
116
|
+
reference,
|
|
117
|
+
h1,
|
|
118
|
+
br,
|
|
119
|
+
div,
|
|
120
|
+
} from "../dist/index.js";
|
|
126
121
|
|
|
127
|
-
function
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
this.updateState(await name)
|
|
122
|
+
function Hello(name) {
|
|
123
|
+
return h1("Hello " + name, {
|
|
124
|
+
className: "title",
|
|
125
|
+
style: {
|
|
126
|
+
color: "grey",
|
|
127
|
+
},
|
|
134
128
|
});
|
|
135
|
-
// effects can be used to make api calls needed for the page
|
|
136
|
-
return _("div", "Hello " + name);
|
|
137
129
|
}
|
|
138
130
|
|
|
131
|
+
const html = div(Hello("peter"), Hello("joe"));
|
|
132
|
+
|
|
133
|
+
// reference (not state)
|
|
134
|
+
|
|
135
|
+
function typingExample() {
|
|
136
|
+
const re = new reference();
|
|
137
|
+
return _(
|
|
138
|
+
"div",
|
|
139
|
+
input({
|
|
140
|
+
oninput() {
|
|
141
|
+
re.text.innerText = this.value;
|
|
142
|
+
},
|
|
143
|
+
placeholder: "typing simulation",
|
|
144
|
+
}),
|
|
145
|
+
p(" no thing typed yet!", { reference: re.bindAs("text") })
|
|
146
|
+
);
|
|
147
|
+
}
|
|
139
148
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
when using router and screens
|
|
143
|
-
|
|
144
|
-
cradova will create a div with data-cra-id=cradova-app-wrapper
|
|
145
|
-
|
|
146
|
-
if it already exist cradova will use it instead
|
|
147
|
-
|
|
148
|
-
so if you want to use your own mount point then create a div with data-cra-id="cradova-app-wrapper"
|
|
149
|
-
|
|
150
|
-
*/
|
|
151
|
-
|
|
152
|
-
const home = new Screen({
|
|
153
|
-
name: "hello page", // page title
|
|
154
|
-
template: HelloMessage,
|
|
155
|
-
...
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
Router.route("/", home);
|
|
159
|
-
|
|
160
|
-
// navigates to that page
|
|
161
|
-
// Router.navigate("/home", data, force);
|
|
162
|
-
// get the page ready in the background
|
|
163
|
-
// Router.packageScreen("/home");
|
|
164
|
-
// get route params for this page
|
|
165
|
-
// Router.getParams();
|
|
166
|
-
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
## State management
|
|
170
|
-
|
|
171
|
-
```js
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
// element can have this.updateState when the shouldUpdate props is true
|
|
175
|
-
|
|
176
|
-
// Ref components
|
|
177
|
-
|
|
178
|
-
// state can be managed from a store when using createSignal or simpleStores
|
|
179
|
-
// this method is not yet documented
|
|
180
|
-
|
|
181
|
-
import _, { Ref } from "cradova";
|
|
182
|
-
|
|
183
|
-
// simple count
|
|
149
|
+
// setting shouldUpdate to true
|
|
150
|
+
// gives you this.updateState binding
|
|
184
151
|
|
|
185
152
|
function counter() {
|
|
186
153
|
let num = 0;
|
|
@@ -193,32 +160,42 @@ function counter() {
|
|
|
193
160
|
});
|
|
194
161
|
}
|
|
195
162
|
|
|
163
|
+
// Another example with data- attribute
|
|
164
|
+
|
|
196
165
|
function dataCounter() {
|
|
197
166
|
return _("h1| 0", {
|
|
198
167
|
shouldUpdate: true,
|
|
199
168
|
"data-num": "0",
|
|
200
169
|
onclick() {
|
|
201
|
-
|
|
202
|
-
this.updateState({ text: num,
|
|
170
|
+
const num = this.getAttribute("data-num") * 1 + 1;
|
|
171
|
+
this.updateState({ text: num, "data-num": num });
|
|
203
172
|
},
|
|
204
173
|
});
|
|
205
174
|
}
|
|
206
175
|
|
|
207
|
-
|
|
208
|
-
|
|
176
|
+
// hello message
|
|
177
|
+
|
|
178
|
+
function HelloMessage() {
|
|
179
|
+
return div({
|
|
209
180
|
shouldUpdate: true,
|
|
210
|
-
text: "
|
|
181
|
+
text: "Click to get a greeting",
|
|
211
182
|
onclick() {
|
|
212
183
|
const name = prompt("what are your names");
|
|
213
|
-
this.updateState({
|
|
184
|
+
this.updateState({
|
|
185
|
+
text: name ? "hello " + name : "Click to get a greeting",
|
|
186
|
+
});
|
|
214
187
|
},
|
|
215
188
|
});
|
|
216
189
|
}
|
|
217
190
|
|
|
218
|
-
|
|
191
|
+
// using cradova Ref
|
|
192
|
+
|
|
193
|
+
const nameRef = new Ref(function (name) {
|
|
219
194
|
const self = this;
|
|
220
195
|
return _("div.foo#bar", {
|
|
221
|
-
text:
|
|
196
|
+
text: name
|
|
197
|
+
? "hello " + (name || " user 2")
|
|
198
|
+
: "Click to get a second greeting",
|
|
222
199
|
onclick() {
|
|
223
200
|
const name = prompt();
|
|
224
201
|
self.updateState(name);
|
|
@@ -226,62 +203,251 @@ const nameRef = new Ref(function ( name ) {
|
|
|
226
203
|
});
|
|
227
204
|
});
|
|
228
205
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
206
|
+
function App() {
|
|
207
|
+
return div(counter, dataCounter, HelloMessage, br, nameRef);
|
|
208
|
+
}
|
|
232
209
|
|
|
233
|
-
|
|
210
|
+
// add your app to the DOM
|
|
234
211
|
|
|
235
|
-
|
|
212
|
+
document.body.append(App());
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Simple Todo list
|
|
216
|
+
|
|
217
|
+
Let's see a simple TodoList example
|
|
218
|
+
|
|
219
|
+
```js
|
|
220
|
+
import _, {
|
|
221
|
+
button,
|
|
222
|
+
createSignal,
|
|
223
|
+
css,
|
|
224
|
+
div,
|
|
225
|
+
input,
|
|
226
|
+
main,
|
|
227
|
+
p,
|
|
228
|
+
Ref,
|
|
229
|
+
reference,
|
|
230
|
+
} from "../dist/index.js";
|
|
231
|
+
|
|
232
|
+
function TodoList() {
|
|
233
|
+
// can be used to hold multiple references
|
|
234
|
+
const referenceSet = new reference();
|
|
235
|
+
|
|
236
|
+
// creating a store
|
|
237
|
+
const todoStore = new createSignal([
|
|
238
|
+
"take bath",
|
|
239
|
+
"code code code",
|
|
240
|
+
"take a break",
|
|
241
|
+
]);
|
|
242
|
+
|
|
243
|
+
// create actions
|
|
244
|
+
todoStore.createAction("add-todo", function (todo) {
|
|
245
|
+
this.set([...this.value, todo]);
|
|
246
|
+
});
|
|
236
247
|
|
|
248
|
+
todoStore.createAction("remove-todo", function (todo) {
|
|
249
|
+
const ind = this.value.indexOf(todo);
|
|
250
|
+
this.value.splice(ind, 1);
|
|
251
|
+
this.set(this.value);
|
|
252
|
+
});
|
|
237
253
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
254
|
+
// bind Ref to Signal
|
|
255
|
+
todoStore.bindRef(todoList);
|
|
256
|
+
|
|
257
|
+
// markup
|
|
258
|
+
return main(
|
|
259
|
+
_`|Todo List`,
|
|
260
|
+
div(
|
|
261
|
+
input({
|
|
262
|
+
placeholder: "type in todo",
|
|
263
|
+
reference: referenceSet.bindAs("todoInput"),
|
|
264
|
+
}),
|
|
265
|
+
button("Add todo", {
|
|
266
|
+
onclick() {
|
|
267
|
+
todoStore.fireAction("add-todo", referenceSet.todoInput.value);
|
|
268
|
+
referenceSet.todoInput.value = "";
|
|
269
|
+
},
|
|
270
|
+
})
|
|
271
|
+
),
|
|
272
|
+
todoList.render
|
|
244
273
|
);
|
|
245
274
|
}
|
|
246
275
|
|
|
276
|
+
const todoList = new Ref(function () {
|
|
277
|
+
const self = this;
|
|
278
|
+
return div(
|
|
279
|
+
self.Signal.value.map((item) =>
|
|
280
|
+
p(item, {
|
|
281
|
+
title: "click to remove",
|
|
282
|
+
onclick() {
|
|
283
|
+
self.Signal.fireAction("remove-todo", item);
|
|
284
|
+
},
|
|
285
|
+
})
|
|
286
|
+
)
|
|
287
|
+
);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
document.body.appendChild(TodoList());
|
|
291
|
+
|
|
292
|
+
css`
|
|
293
|
+
body {
|
|
294
|
+
box-sizing: border-box;
|
|
295
|
+
display: flex;
|
|
296
|
+
}
|
|
297
|
+
main {
|
|
298
|
+
margin: auto;
|
|
299
|
+
}
|
|
300
|
+
main > p {
|
|
301
|
+
font-size: 2rem;
|
|
302
|
+
}
|
|
303
|
+
`;
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## working with screen and Router:
|
|
307
|
+
|
|
308
|
+
unlike just appending stuff to the DOM,
|
|
309
|
+
a better to build apps is to use a routing system.
|
|
310
|
+
|
|
311
|
+
Cradova Router is a module that allows you do the following:
|
|
312
|
+
|
|
313
|
+
Create specified routes in you application
|
|
314
|
+
help you orchestrate navigation
|
|
315
|
+
render a screen on a route
|
|
316
|
+
pre-render a screen in the background if you want to.
|
|
317
|
+
listen to Navigation changes
|
|
318
|
+
create error boundary at screen level.
|
|
319
|
+
persist rendered screens by default
|
|
320
|
+
allow parallel screen rendering for every unique route scheme
|
|
321
|
+
|
|
322
|
+
let's try an example.
|
|
323
|
+
|
|
324
|
+
```js
|
|
325
|
+
import _, { Screen, Router } from "cradova";
|
|
326
|
+
|
|
327
|
+
// Ref can be used as screens
|
|
328
|
+
|
|
329
|
+
const template = new Ref(function (name) {
|
|
330
|
+
// an effect run once after screen renders
|
|
331
|
+
const self = this;
|
|
332
|
+
self.effect(() => {
|
|
333
|
+
const name = new Promise((res) => {
|
|
334
|
+
res("john doe");
|
|
335
|
+
});
|
|
336
|
+
setTimeout(async () => {
|
|
337
|
+
self.updateState(await name);
|
|
338
|
+
}, 1000);
|
|
339
|
+
});
|
|
340
|
+
// effects can be used to make api calls needed for the page
|
|
341
|
+
return _("div", name ? ">>>>>>>> Hello " + name : " loading...");
|
|
342
|
+
});
|
|
343
|
+
|
|
247
344
|
const home = new Screen({
|
|
248
345
|
name: "home page", // page title
|
|
249
|
-
template
|
|
250
|
-
|
|
346
|
+
template,
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// in your routes.ts file
|
|
350
|
+
Router.BrowserRoutes({
|
|
351
|
+
"/home": home,
|
|
352
|
+
"/lazy-loaded-home": async () => await import("./home"),
|
|
251
353
|
});
|
|
354
|
+
// creates these routes
|
|
252
355
|
|
|
253
|
-
|
|
356
|
+
Router.packageScreen("/home", data);
|
|
357
|
+
// get the page ready in the background
|
|
358
|
+
|
|
359
|
+
Router.navigate("/home", data);
|
|
360
|
+
// navigates to that page
|
|
254
361
|
|
|
255
|
-
|
|
362
|
+
Router.getParams();
|
|
363
|
+
// get route params for this current page
|
|
364
|
+
|
|
365
|
+
Router.onPageEvent((lastRoute, newRoute) => {
|
|
366
|
+
console.log(lastRoute, newRoute);
|
|
367
|
+
});
|
|
368
|
+
// listen for navigation changes
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
### More info
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
More info on cradova Router
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
Every cradova app mounts on a div with attribute data-wrapper="app"
|
|
380
|
+
|
|
381
|
+
if it already exist cradova will use it instead.
|
|
382
|
+
|
|
383
|
+
cradova will create a div with data-wrapper="app" if it doesn't exists already.
|
|
384
|
+
|
|
385
|
+
so if you want to use your own mount point then create a div with data-wrapper="app".
|
|
386
|
+
|
|
387
|
+
---
|
|
388
|
+
|
|
389
|
+
More info on cradova screens
|
|
390
|
+
|
|
391
|
+
---
|
|
256
392
|
|
|
257
393
|
screens are rendered once by default to hack
|
|
258
394
|
responsiveness making your app work fast as user navigates.
|
|
259
395
|
|
|
260
396
|
this behavior can be override
|
|
261
397
|
by passing
|
|
262
|
-
|
|
398
|
+
persist: false
|
|
263
399
|
in the constructor
|
|
264
400
|
|
|
265
|
-
|
|
266
401
|
Cradova screens has
|
|
267
402
|
onActivate() and
|
|
268
|
-
onDeactivate() methods
|
|
403
|
+
onDeactivate() methods which is also available in the
|
|
404
|
+
component function on the this variable bound to it.
|
|
269
405
|
|
|
270
|
-
|
|
271
|
-
circle for each in your app
|
|
406
|
+
this allow you manage rendering
|
|
407
|
+
circle for each screen in your app
|
|
272
408
|
|
|
273
|
-
|
|
409
|
+
---
|
|
274
410
|
|
|
275
|
-
|
|
276
|
-
|
|
411
|
+
More info on cradova Ref
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
Refs are dynamic components, they have simple abstractions like:
|
|
416
|
+
|
|
417
|
+
- Effects
|
|
418
|
+
- stash
|
|
419
|
+
- preRender
|
|
420
|
+
- updateState
|
|
421
|
+
|
|
422
|
+
these behaviors allow you manage rendering
|
|
423
|
+
circle for refs in your app
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
More info on cradova createSignal
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
Cradova Signals allows you to create powerful data stores.
|
|
432
|
+
|
|
433
|
+
with ability to:
|
|
434
|
+
|
|
435
|
+
- create store
|
|
436
|
+
- create actions and fire them
|
|
437
|
+
- bind a Ref
|
|
438
|
+
- listen to changes
|
|
439
|
+
- persist changes to localStorage
|
|
440
|
+
- update a cradova Ref and bindings automatically
|
|
441
|
+
|
|
442
|
+
With these simple and easy abstractions, you can use datastores with powerful convenience.
|
|
277
443
|
|
|
278
444
|
## Documentation
|
|
279
445
|
|
|
280
|
-
At the moment, we're in the process of creating documentation for Cradova, and we have limited resources. If you're interested in lending a hand, we invite you to join our community, gain firsthand experience, and contribute to the advancement of Cradova.
|
|
446
|
+
At the moment, we're in the process of creating a documentation website for Cradova, and we have limited resources. If you're interested in lending a hand, we invite you to join our community, gain firsthand experience, and contribute to the advancement of Cradova.
|
|
281
447
|
|
|
282
448
|
## Getting Help
|
|
283
449
|
|
|
284
|
-
To get further insights and help on Cradova, visit our
|
|
450
|
+
To get further insights and help on Cradova, visit our [Discord](https://discord.gg/b7fvMg38) and [Telegram](https://t.me/cradovaframework) Community Chats.
|
|
285
451
|
|
|
286
452
|
## Contributing
|
|
287
453
|
|