@base-framework/base 3.0.112 → 3.0.115
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 +560 -8
- package/dist/base.js +1 -1
- package/dist/base.js.map +3 -3
- package/dist/types/main/data-tracker/tracker-types.d.ts +9 -23
- package/dist/types/modules/layout/html-to-string.d.ts +16 -2
- package/dist/types/shared/strings.d.ts +1 -1
- package/dist/types/shared/types.d.ts +8 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,15 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
## Framework Overview
|
|
4
4
|
|
|
5
|
-
Our goal with Base is to solve many client-side rendering issues. Base focuses on reusability, scalability, and performance.
|
|
5
|
+
Our goal with Base is to solve many client-side and Server-side rendering issues. Base focuses on reusability, scalability, and performance.
|
|
6
6
|
|
|
7
7
|
Base has a core that supports adding and removing events, custom events, data-tracking, element class and attribute modifying, object and type utils, etc.
|
|
8
8
|
|
|
9
9
|
The framework is modular and has additional modules to help with ajax, HTML, layouts, data, data-binding, states, dates, routing, components, atoms, etc.
|
|
10
10
|
|
|
11
|
+
You can learn more about how to use Base in the wiki documentation. [Base Wiki](https://github.com/chrisdurfee/base/wiki)
|
|
12
|
+
|
|
13
|
+
## Base Converter
|
|
14
|
+
|
|
15
|
+
There is a GPT created with ChatGPT that can convert code from other frameworks to Base. The GPT is new so it still has some issues but it is a good start. [Base Converter](https://chatgpt.com/g/g-uNL6KKeCo-base-converter/)
|
|
16
|
+
|
|
17
|
+
|
|
11
18
|
## Layouts
|
|
12
19
|
|
|
13
|
-
Base
|
|
20
|
+
Base uses components to render an application. Base creates and renders components using native JavaScript. Layouts are scaffolded using JavaScript object literals. Because the layouts are rendered client-side or server-side using native JavaScript, the framework does not require a compiling or build process.
|
|
21
|
+
|
|
22
|
+
Layouts are reuable and can be used in multiple components and pages. Layouts can be nested and composed to create complex layouts.
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
|
|
26
|
+
// Layouts use normal JavaScript object literals to create the layout.
|
|
27
|
+
{ class: 'name' } === <div class="name"></div>
|
|
28
|
+
|
|
29
|
+
// Input example
|
|
30
|
+
{ tag: 'input', type: 'text', value: 'name' } === <input type="text" value="name" />
|
|
31
|
+
|
|
32
|
+
// Nested layout example
|
|
33
|
+
{ class: 'name', nest: [ { class: 'child' } ] } === <div class="name"><div class="child"></div></div>
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Base use atoms and components to create reusable layouts.
|
|
38
|
+
|
|
39
|
+
Learn more: [Base Layouts](https://github.com/chrisdurfee/base/wiki/Layout)
|
|
40
|
+
|
|
14
41
|
|
|
15
42
|
## Components and Atoms
|
|
16
43
|
|
|
@@ -40,12 +67,125 @@ export class Page extends Component
|
|
|
40
67
|
|
|
41
68
|
Components have lifecycle methods for actions during creation, setup, and destruction.
|
|
42
69
|
|
|
70
|
+
learn more: [Base Components](https://github.com/chrisdurfee/base/wiki/Components)
|
|
71
|
+
|
|
72
|
+
## Atoms
|
|
43
73
|
Atoms are the building blocks for reusable layouts, allowing common design patterns and elements to be shared between multiple components and other atoms.
|
|
44
74
|
|
|
75
|
+
## Atom Types
|
|
76
|
+
Atoms can be instantiated using various methodologies:
|
|
77
|
+
|
|
78
|
+
### Function Atoms
|
|
79
|
+
These atoms are instantiated with either standard functions or arrow functions, equipped with a props object to transfer properties to the atoms.
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
const Div = (props, children) => ({
|
|
83
|
+
...props,
|
|
84
|
+
children
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Atom Callbacks
|
|
89
|
+
Atoms may be created using the Atom function, which accepts a callback function as its sole parameter. The callback function is passed a props object and children array and returns an object containing the atom's layout.
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { Atom } from '@base-framework/base';
|
|
93
|
+
|
|
94
|
+
const Button = Atom((props, children) => ({
|
|
95
|
+
tag: 'button',
|
|
96
|
+
...props,
|
|
97
|
+
children
|
|
98
|
+
}));
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
#### Atom Nesting
|
|
102
|
+
Atoms should use composition to nest other atoms. This is achieved by passing the children array to the atoms args.
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
import { Atom } from '@base-framework/base';
|
|
106
|
+
|
|
107
|
+
const SecondaryButton = Atom((props, children) => (Button({
|
|
108
|
+
...props,
|
|
109
|
+
class: 'secondary-btn',
|
|
110
|
+
children
|
|
111
|
+
}));
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Adding Event Listeners
|
|
115
|
+
Event listener callbacks within atoms accept two parameters: the originating event object and the "parent" component object in which the atom resides.
|
|
116
|
+
|
|
117
|
+
## Utilization of Atoms
|
|
118
|
+
To leverage an atom, invoke its function and pass the requisite values via a props and children.
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
const Div = (props, children) => ({
|
|
122
|
+
...props,
|
|
123
|
+
children
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
Div({ class: 'text' }, 'text');
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Atoms created with the Base Atom callback function support passing optional params including props or children to the atom. The props object should always be first but if the atom does not require props, the children array or string can be passed as the first argument.
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
import { Atom } from '@base-framework/base';
|
|
133
|
+
|
|
134
|
+
const Div = Atom((props, children) => ({
|
|
135
|
+
...props,
|
|
136
|
+
tag: 'div',
|
|
137
|
+
children
|
|
138
|
+
}));
|
|
139
|
+
|
|
140
|
+
// props only
|
|
141
|
+
Div({class: 'text'});
|
|
142
|
+
|
|
143
|
+
// text child only
|
|
144
|
+
Div('test');
|
|
145
|
+
|
|
146
|
+
// array child only
|
|
147
|
+
Div([
|
|
148
|
+
Div('test')
|
|
149
|
+
]);
|
|
150
|
+
|
|
151
|
+
// props and text child
|
|
152
|
+
Div({class: 'text'}, 'test');
|
|
153
|
+
|
|
154
|
+
// props and array children
|
|
155
|
+
Div({class: 'text'}, [
|
|
156
|
+
Div('test'),
|
|
157
|
+
Div('test')
|
|
158
|
+
]);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Learn more: [Base Atoms](https://github.com/chrisdurfee/base/wiki/Atoms)
|
|
162
|
+
|
|
163
|
+
Base has a package that has already created most of the HTML Atoms needed for rendering layouts. This package can be installed via npm.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
npm install @base-framework/atoms
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Here is the repository for the atoms package: [Base Atoms](https://github.com/chrisdurfee/atoms). Like Base, the atoms package is open-source and free to use.
|
|
170
|
+
|
|
171
|
+
## Organisms
|
|
172
|
+
|
|
173
|
+
Base has a package that has some special organisms that can make building complex layouts quicker. This package can be installed via npm.
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
npm install @base-framework/organisms
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Here is the repository for the organisms package: [Base Organisms](https://github.com/chrisdurfee/organisms). The organisms package is open-source and free to use.
|
|
180
|
+
|
|
181
|
+
|
|
45
182
|
## Element Directives
|
|
46
183
|
|
|
47
184
|
Elements created by Base have access to custom directives, enabling more functionalities than standard HTML elements. These include caching, adding states, binding and watching data, re-rendering contents, declarative routing and switching, array mapping and binding, event listeners, and more.
|
|
48
185
|
|
|
186
|
+
Learn more: [Base Element Directives](https://github.com/chrisdurfee/base/wiki/Directives)
|
|
187
|
+
|
|
188
|
+
|
|
49
189
|
## Data Binding, Watching, and Linking
|
|
50
190
|
|
|
51
191
|
Base supports "bindables" for creating and using data, supporting both shallow and deep nested data. Bindables can be one-way or two-way bindings.
|
|
@@ -55,13 +195,249 @@ Types of bindables include:
|
|
|
55
195
|
- **SimpleData**: A shallow data object.
|
|
56
196
|
- **Models**: Child of Data, with default attributes and server resource connectivity.
|
|
57
197
|
|
|
198
|
+
```javascript
|
|
199
|
+
import { Atom } from '@base-framework/base';
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* If a parent component has a Data object with a "count" property.
|
|
203
|
+
*
|
|
204
|
+
* This will create an input with the value bound of the "count"
|
|
205
|
+
* property. This bind is Bi-directional binding to the
|
|
206
|
+
* "count" property of the parent component's Data object.
|
|
207
|
+
*/
|
|
208
|
+
Input({ bind: 'count' })
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Elements can watch for changes in data and re-render when the data changes.
|
|
212
|
+
*/
|
|
213
|
+
Div({class: '[[className]]'})
|
|
214
|
+
|
|
215
|
+
// Multi-attribute watching
|
|
216
|
+
A({href: '/account/user/[[userId]]'}, '[[userName]] - [[age]]')
|
|
217
|
+
|
|
218
|
+
// Multi-data watcher
|
|
219
|
+
Div({class: ['[[propName]] [[otherPropName]]', [data, otherData]]})
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Base Data objects are bindable. There are a few types of data objects:
|
|
223
|
+
|
|
224
|
+
```javascript
|
|
225
|
+
import { Data, SimpleData, Model } from '@base-framework/base';
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Data object
|
|
229
|
+
*
|
|
230
|
+
* This can store deep nested data including arrays and objects.
|
|
231
|
+
*/
|
|
232
|
+
const data = new Data({
|
|
233
|
+
name: {
|
|
234
|
+
first: 'Bruce',
|
|
235
|
+
last: 'Wayne'
|
|
236
|
+
},
|
|
237
|
+
address: {
|
|
238
|
+
street: '123 Gotham St',
|
|
239
|
+
city: 'Gotham',
|
|
240
|
+
state: 'NY'
|
|
241
|
+
},
|
|
242
|
+
phones: ['555-555-5555', '555-555-5556'],
|
|
243
|
+
age: 21
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* SimpleData object
|
|
248
|
+
*
|
|
249
|
+
* This can store shallow data.
|
|
250
|
+
*/
|
|
251
|
+
const simpleData = new SimpleData({ name: 'batman' });
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* The data objects have are proxies and can be used like objects.
|
|
255
|
+
*/
|
|
256
|
+
|
|
257
|
+
// Retrieval
|
|
258
|
+
let prop = data.name.first;
|
|
259
|
+
// or
|
|
260
|
+
let name = data.get('name.first');
|
|
261
|
+
|
|
262
|
+
// Assignment
|
|
263
|
+
simpleData.name = 'batman';
|
|
264
|
+
// or
|
|
265
|
+
data.set('name', 'batman');
|
|
266
|
+
|
|
267
|
+
// Pushing to an array
|
|
268
|
+
data.push('phones', '555-555-5557');
|
|
269
|
+
|
|
270
|
+
// changing an item in an array
|
|
271
|
+
data.set('phones[0]', '555-555-5558');
|
|
272
|
+
|
|
273
|
+
// Batch updates using an object
|
|
274
|
+
data.set({
|
|
275
|
+
name: 'batman',
|
|
276
|
+
age: 21
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// Deletion
|
|
280
|
+
data.delete('name');
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Model object
|
|
284
|
+
*
|
|
285
|
+
* This can store default attributes and server resource
|
|
286
|
+
* connectivity.
|
|
287
|
+
*
|
|
288
|
+
* The model's service already has methods for adding,
|
|
289
|
+
* updating, deleting, and fetching data from the
|
|
290
|
+
* server.
|
|
291
|
+
*/
|
|
292
|
+
const UserModel = Model.extend({
|
|
293
|
+
defaults: {
|
|
294
|
+
name: {
|
|
295
|
+
first: 'Bruce',
|
|
296
|
+
last: 'Wayne'
|
|
297
|
+
},
|
|
298
|
+
address: {
|
|
299
|
+
street: '123 Gotham St',
|
|
300
|
+
city: 'Gotham',
|
|
301
|
+
state: 'NY'
|
|
302
|
+
},
|
|
303
|
+
age: 21
|
|
304
|
+
},
|
|
305
|
+
url: '/api/user',
|
|
306
|
+
|
|
307
|
+
xhr: {
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Custom methods can be added to the model service.
|
|
311
|
+
*
|
|
312
|
+
* @param {object} instanceParams
|
|
313
|
+
* @param {function} callback
|
|
314
|
+
* @returns {object|bool} The xhr object
|
|
315
|
+
*/
|
|
316
|
+
customMethod(instanceParams, callback)
|
|
317
|
+
{
|
|
318
|
+
if (!this.isValid())
|
|
319
|
+
{
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
let params = 'op=customParam' +
|
|
324
|
+
'&' + this.setupObjectData();
|
|
325
|
+
|
|
326
|
+
// this will be added to the base url of the model
|
|
327
|
+
const URL = "/custom/url";
|
|
328
|
+
return this._post(URL, params, instanceParams, callBack);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
const model = new UserModel();
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* The model can be used to fetch data from the server.
|
|
337
|
+
*
|
|
338
|
+
* The response will be set to the model.
|
|
339
|
+
*/
|
|
340
|
+
model.xhr.get({}, (response) => {
|
|
341
|
+
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
// post
|
|
345
|
+
model.xhr.add({}, (response) => {
|
|
346
|
+
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// put
|
|
350
|
+
model.xhr.update({}, (response) => {
|
|
351
|
+
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// delete
|
|
355
|
+
model.xhr.delete({}, (response) => {
|
|
356
|
+
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
The component also supports the state property. This is another bindable type extended from the SimpleData object so it only supports shallow data.
|
|
361
|
+
|
|
362
|
+
```javascript
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* This will return the state propreties and values that will be
|
|
366
|
+
* use to create the "state" object.
|
|
367
|
+
*
|
|
368
|
+
* @returns {object}
|
|
369
|
+
*/
|
|
370
|
+
setupStates()
|
|
371
|
+
{
|
|
372
|
+
return {
|
|
373
|
+
count: 0,
|
|
374
|
+
loading: false
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Each component can have one "data" proeprty that can be set using the "setData" method.
|
|
381
|
+
|
|
382
|
+
If a component has been created using the "route" or "switch" directive, it will receive a "route" property that will contain the route data which is also bindable.
|
|
383
|
+
|
|
384
|
+
The data objects push changes to the elements that are bound to the data. This allows for re-rendering of the elements when the data changes.
|
|
385
|
+
|
|
386
|
+
Here is an example of how to use data binding in a component:
|
|
387
|
+
|
|
388
|
+
```javascript
|
|
389
|
+
import { Div } from '@base-framework/atoms';
|
|
390
|
+
import { Component } from '@base-framework/base';
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Timer
|
|
394
|
+
*
|
|
395
|
+
* This will create a timer component that uses state watching.
|
|
396
|
+
*
|
|
397
|
+
* @class
|
|
398
|
+
*/
|
|
399
|
+
export class Timer extends Component
|
|
400
|
+
{
|
|
401
|
+
/**
|
|
402
|
+
* This will render the timer.
|
|
403
|
+
*
|
|
404
|
+
* @returns {object}
|
|
405
|
+
*/
|
|
406
|
+
render()
|
|
407
|
+
{
|
|
408
|
+
// This will rerender the div text content when the count state changes.
|
|
409
|
+
return Div('[[count]]');
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* This will setup the states.
|
|
414
|
+
*
|
|
415
|
+
* @returns {object}
|
|
416
|
+
*/
|
|
417
|
+
setupStates()
|
|
418
|
+
{
|
|
419
|
+
return { count: 0 };
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
afterSetup()
|
|
423
|
+
{
|
|
424
|
+
const ONE_SECOND = 1000;
|
|
425
|
+
window.setInterval(() => this.state.increment('count'), ONE_SECOND);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Learn more: [Base Data Binding](https://github.com/chrisdurfee/base/wiki/Directives#binding-to-data)
|
|
431
|
+
|
|
432
|
+
|
|
58
433
|
## Performance
|
|
59
434
|
|
|
60
435
|
Components are static by default, rendering only once per instance. They become dynamic when bound to bindable data sources, allowing for content re-rendering, value changes, function calls, and class additions on data change.
|
|
61
436
|
|
|
437
|
+
|
|
62
438
|
## Getting Started
|
|
63
439
|
|
|
64
|
-
To begin using
|
|
440
|
+
To begin using Base framework in a client-side or server-side rendered project, follow these steps:
|
|
65
441
|
|
|
66
442
|
1. **Clone the repository**:
|
|
67
443
|
```bash
|
|
@@ -84,7 +460,6 @@ import { base } from '@base-framework/base';
|
|
|
84
460
|
|
|
85
461
|
## Usage
|
|
86
462
|
|
|
87
|
-
Basic Component Creation
|
|
88
463
|
Create a new component:
|
|
89
464
|
|
|
90
465
|
```javascript
|
|
@@ -152,13 +527,190 @@ const container = document.body;
|
|
|
152
527
|
Builder.render(page, container);
|
|
153
528
|
```
|
|
154
529
|
|
|
155
|
-
|
|
530
|
+
To allow more reusability, you create static elements as atoms and organisms. Atoms and organisms should use composition. These can be used in multiple components and layouts.
|
|
531
|
+
|
|
532
|
+
```javascript
|
|
533
|
+
import { Atom } from '@base-framework/base';
|
|
534
|
+
|
|
535
|
+
const Button = Atom((props, children) => ({
|
|
536
|
+
tag: 'button',
|
|
537
|
+
...props,
|
|
538
|
+
children
|
|
539
|
+
}));
|
|
540
|
+
|
|
541
|
+
const SecondaryButton = Atom((props, children) => (Button({
|
|
542
|
+
...props,
|
|
543
|
+
class: 'secondary-btn',
|
|
544
|
+
children
|
|
545
|
+
}));
|
|
546
|
+
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
Atoms can be added to components and other atoms:
|
|
550
|
+
|
|
551
|
+
```javascript
|
|
552
|
+
|
|
553
|
+
import { Component } from '@base-framework/base';
|
|
554
|
+
import { Div } from '@base-framework/atoms';
|
|
555
|
+
import { SecondaryButton } from './atoms/button.js';
|
|
556
|
+
|
|
557
|
+
export class Page extends Component
|
|
558
|
+
{
|
|
559
|
+
render()
|
|
560
|
+
{
|
|
561
|
+
return Div([
|
|
562
|
+
SecondaryButton({
|
|
563
|
+
/**
|
|
564
|
+
* This will add a click event listener to the button.
|
|
565
|
+
*
|
|
566
|
+
* @param {Event} event The event object
|
|
567
|
+
* @param {Component} parent The parent component object
|
|
568
|
+
* @returns {void}
|
|
569
|
+
*/
|
|
570
|
+
click(event, parent) =>
|
|
571
|
+
{
|
|
572
|
+
// Code to access the parent component
|
|
573
|
+
}
|
|
574
|
+
})
|
|
575
|
+
]);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
## Code Splitting
|
|
581
|
+
|
|
582
|
+
Base supports code splitting, allowing you to load components and modules on demand. This can help reduce the initial load time of your application. You can import atoms or components on demand using the Import module.
|
|
583
|
+
|
|
584
|
+
```javascript
|
|
585
|
+
import { Import } from "@base-framework/base";
|
|
586
|
+
import { A, Div, H1, Header } from "@base-framework/atoms";
|
|
587
|
+
|
|
588
|
+
// Without using Vite
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* This will create an import buttons.
|
|
592
|
+
*
|
|
593
|
+
* @returns {object}
|
|
594
|
+
*/
|
|
595
|
+
const ImportButtons = () => (
|
|
596
|
+
Div([
|
|
597
|
+
Header([
|
|
598
|
+
H1('Aside')
|
|
599
|
+
]),
|
|
600
|
+
Div({ class: 'card' }, [
|
|
601
|
+
|
|
602
|
+
// Importing the buttons module on demand
|
|
603
|
+
Import('../../../../../../components/atoms/import-buttons.js')
|
|
604
|
+
])
|
|
605
|
+
])
|
|
606
|
+
);
|
|
607
|
+
|
|
608
|
+
// With Vite
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* This will create an import buttons.
|
|
612
|
+
*
|
|
613
|
+
* @returns {object}
|
|
614
|
+
*/
|
|
615
|
+
const ImportButtons = () => (
|
|
616
|
+
Div([
|
|
617
|
+
Header([
|
|
618
|
+
H1('Aside')
|
|
619
|
+
]),
|
|
620
|
+
Div({ class: 'card' }, [
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* This will import the buttons module on demand. The import function
|
|
624
|
+
* needs to be used to add the module to the vite build.
|
|
625
|
+
*/
|
|
626
|
+
Import({ src: import('../../../../../../components/atoms/import-buttons.js') })
|
|
627
|
+
])
|
|
628
|
+
])
|
|
629
|
+
);
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
## Example Todo App
|
|
633
|
+
|
|
634
|
+
Here is an example of a todo app using Base:
|
|
635
|
+
|
|
636
|
+
```javascript
|
|
637
|
+
import { Button, Div, Form, H1, Input, Li, Ul } from "@base-framework/atoms";
|
|
638
|
+
import { Builder, Data } from "@base-framework/base";
|
|
639
|
+
|
|
640
|
+
/**
|
|
641
|
+
* This will create a to-do app.
|
|
642
|
+
*
|
|
643
|
+
* @returns {object}
|
|
644
|
+
*/
|
|
645
|
+
export function ToDoApp()
|
|
646
|
+
{
|
|
647
|
+
/**
|
|
648
|
+
* This will set up the data store for the to-do app.
|
|
649
|
+
*/
|
|
650
|
+
const data = new Data({ items: [] });
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* This will handle the form submission for adding a new to-do item.
|
|
654
|
+
*
|
|
655
|
+
* @param {object} event
|
|
656
|
+
*/
|
|
657
|
+
const handleSubmit = (event) =>
|
|
658
|
+
{
|
|
659
|
+
event.preventDefault();
|
|
660
|
+
const form = event.target;
|
|
661
|
+
const input = form.querySelector('input');
|
|
662
|
+
|
|
663
|
+
// add the new to-do item to the array of items
|
|
664
|
+
data.push('items', input.value);
|
|
665
|
+
input.value = '';
|
|
666
|
+
};
|
|
667
|
+
|
|
668
|
+
/**
|
|
669
|
+
* This will handle removing a to-do item from the list.
|
|
670
|
+
*
|
|
671
|
+
* @param {number} index
|
|
672
|
+
* @returns {boolean}
|
|
673
|
+
*/
|
|
674
|
+
const handleRemove = (index) => data.splice('items', index);
|
|
675
|
+
|
|
676
|
+
return Div([
|
|
677
|
+
H1('To-Do App'),
|
|
678
|
+
Form({ submit: handleSubmit }, [
|
|
679
|
+
Input({ placeholder: 'Add a new item' }),
|
|
680
|
+
Button({ type: 'submit' }, 'Add')
|
|
681
|
+
]),
|
|
682
|
+
Ul({
|
|
683
|
+
for: [data, 'items', (item, index) => Li([
|
|
684
|
+
Span(item),
|
|
685
|
+
Button({ click: () => handleRemove(index) }, 'Remove')
|
|
686
|
+
])]
|
|
687
|
+
})
|
|
688
|
+
]);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* This will render the to-do app to the body of the document.
|
|
693
|
+
*/
|
|
694
|
+
Builder.render(ToDoApp(), document.body);
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
## Example Projects Using Base
|
|
699
|
+
|
|
700
|
+
[Base Platform Example](https://github.com/chrisdurfee/next-app-shell)
|
|
701
|
+
|
|
702
|
+
[Base App Example](https://github.com/chrisdurfee/base-update)
|
|
703
|
+
|
|
704
|
+
[Base Website Example](https://github.com/chrisdurfee/life)
|
|
705
|
+
|
|
706
|
+
[Base Server Example](https://github.com/chrisdurfee/base-server)
|
|
707
|
+
|
|
708
|
+
[Base Game Example](https://github.com/chrisdurfee/multisplode)
|
|
156
709
|
|
|
157
|
-
[Base Framework Example](https://github.com/chrisdurfee/next-app-shell)
|
|
158
710
|
|
|
159
711
|
## Contributing
|
|
160
712
|
|
|
161
|
-
Contributions to Base
|
|
713
|
+
Contributions to Base are welcome. Follow these steps to contribute:
|
|
162
714
|
|
|
163
715
|
- Fork the repository.
|
|
164
716
|
- Create a new branch for your feature or bug fix.
|
|
@@ -168,7 +720,7 @@ Contributions to Base Framework are welcome. Follow these steps to contribute:
|
|
|
168
720
|
|
|
169
721
|
## License
|
|
170
722
|
|
|
171
|
-
Base
|
|
723
|
+
Base is licensed under the MIT License. See the LICENSE file for details.
|
|
172
724
|
|
|
173
725
|
## Contact
|
|
174
726
|
|