@devera_se/bedrockjs 0.1.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 +519 -0
- package/package.json +65 -0
- package/src/component.d.ts +36 -0
- package/src/component.js +357 -0
- package/src/html.d.ts +12 -0
- package/src/html.js +148 -0
- package/src/index.d.ts +12 -0
- package/src/index.js +50 -0
- package/src/reactive.d.ts +20 -0
- package/src/reactive.js +277 -0
- package/src/render.d.ts +5 -0
- package/src/render.js +326 -0
- package/src/router.d.ts +52 -0
- package/src/router.js +356 -0
package/README.md
ADDED
|
@@ -0,0 +1,519 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
A lightweight web framework built on Web Components with lit-html-style templating, reactive state management, and a router with async data fetching.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Tagged Template Literals** - Declarative UI with `html` tagged templates
|
|
8
|
+
- **Web Components** - Native custom elements with reactive properties
|
|
9
|
+
- **Efficient DOM Updates** - Comment-marker-based patching (no virtual DOM)
|
|
10
|
+
- **Reactive State** - Proxy-based reactivity with automatic dependency tracking
|
|
11
|
+
- **Router** - History API routing with async data loaders
|
|
12
|
+
- **Shadow DOM Support** - Optional style encapsulation per component
|
|
13
|
+
- **Zero Dependencies** - Pure JavaScript, no build step required
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
JSR (Deno or `jsr:` import):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
deno add jsr:@devera/bedrockjs
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
NPM (via JSR CLI):
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npx jsr add @devera/bedrockjs
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
NPM (via JSR package):
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install @jsr/devera__bedrockjs
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
PNPM:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pnpm add jsr:@devera/bedrockjs
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Yarn:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
yarn add jsr:@devera/bedrockjs
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
VLT:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
vlt add jsr:@devera/bedrockjs
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Or include directly in your HTML:
|
|
54
|
+
|
|
55
|
+
```html
|
|
56
|
+
<script type="module">
|
|
57
|
+
import { html, Component, createRouter } from './src/index.js';
|
|
58
|
+
</script>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Quick Start
|
|
62
|
+
|
|
63
|
+
### Hello World
|
|
64
|
+
|
|
65
|
+
```javascript
|
|
66
|
+
import { html, Component } from '@devera/bedrockjs';
|
|
67
|
+
|
|
68
|
+
class HelloWorld extends Component {
|
|
69
|
+
static tag = 'hello-world';
|
|
70
|
+
static properties = {
|
|
71
|
+
name: { type: String, default: 'World' }
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
render() {
|
|
75
|
+
return html`<h1>Hello, ${this.name}!</h1>`;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
HelloWorld.register();
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<hello-world name="BedrockJS"></hello-world>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Counter with Events
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
import { html, Component } from '@devera/bedrockjs';
|
|
90
|
+
|
|
91
|
+
class MyCounter extends Component {
|
|
92
|
+
static tag = 'my-counter';
|
|
93
|
+
static properties = {
|
|
94
|
+
count: { type: Number, default: 0 }
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
render() {
|
|
98
|
+
return html`
|
|
99
|
+
<div>
|
|
100
|
+
<p>Count: ${this.count}</p>
|
|
101
|
+
<button on-click=${() => this.count++}>Increment</button>
|
|
102
|
+
<button on-click=${() => this.count--}>Decrement</button>
|
|
103
|
+
</div>
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
MyCounter.register();
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Core Concepts
|
|
112
|
+
|
|
113
|
+
### Templates
|
|
114
|
+
|
|
115
|
+
BedrockJS uses tagged template literals for declarative UI:
|
|
116
|
+
|
|
117
|
+
```javascript
|
|
118
|
+
import { html } from '@devera/bedrockjs';
|
|
119
|
+
|
|
120
|
+
const template = html`
|
|
121
|
+
<div class=${className}>
|
|
122
|
+
<input .value=${text} on-input=${handleInput}>
|
|
123
|
+
<button on-click=${handleClick}>Submit</button>
|
|
124
|
+
${items.map(item => html`<li>${item}</li>`)}
|
|
125
|
+
</div>
|
|
126
|
+
`;
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Binding Types
|
|
130
|
+
|
|
131
|
+
| Syntax | Description | Example |
|
|
132
|
+
|--------|-------------|---------|
|
|
133
|
+
| `${value}` | Text content | `<p>${message}</p>` |
|
|
134
|
+
| `attr=${value}` | Attribute | `<div class=${cls}>` |
|
|
135
|
+
| `.prop=${value}` | Property | `<input .value=${text}>` |
|
|
136
|
+
| `on-event=${fn}` | Event listener | `<button on-click=${handler}>` |
|
|
137
|
+
|
|
138
|
+
#### Conditional Rendering
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
render() {
|
|
142
|
+
return html`
|
|
143
|
+
<div>
|
|
144
|
+
${this.isLoading
|
|
145
|
+
? html`<span>Loading...</span>`
|
|
146
|
+
: html`<span>Ready!</span>`
|
|
147
|
+
}
|
|
148
|
+
</div>
|
|
149
|
+
`;
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### List Rendering
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
import { html, keyed } from 'bedrockjs';
|
|
157
|
+
|
|
158
|
+
render() {
|
|
159
|
+
return html`
|
|
160
|
+
<ul>
|
|
161
|
+
${this.items.map(item =>
|
|
162
|
+
keyed(item.id, html`<li>${item.name}</li>`)
|
|
163
|
+
)}
|
|
164
|
+
</ul>
|
|
165
|
+
`;
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Use `keyed()` for efficient updates when items can be reordered or removed.
|
|
170
|
+
|
|
171
|
+
### Components
|
|
172
|
+
|
|
173
|
+
Components extend the `Component` base class:
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
import { html, Component } from 'bedrockjs';
|
|
177
|
+
|
|
178
|
+
class UserCard extends Component {
|
|
179
|
+
// Required: unique tag name
|
|
180
|
+
static tag = 'user-card';
|
|
181
|
+
|
|
182
|
+
// Optional: enable Shadow DOM (default: false)
|
|
183
|
+
static shadow = true;
|
|
184
|
+
|
|
185
|
+
// Optional: reactive properties
|
|
186
|
+
static properties = {
|
|
187
|
+
name: { type: String, default: 'Anonymous' },
|
|
188
|
+
age: { type: Number },
|
|
189
|
+
active: { type: Boolean, default: false },
|
|
190
|
+
data: { type: Object, default: () => ({}) }
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Called after each render
|
|
194
|
+
updated() {
|
|
195
|
+
console.log('Component updated');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Return template
|
|
199
|
+
render() {
|
|
200
|
+
return html`
|
|
201
|
+
<div class="card">
|
|
202
|
+
<h2>${this.name}</h2>
|
|
203
|
+
<p>Age: ${this.age}</p>
|
|
204
|
+
</div>
|
|
205
|
+
`;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Register with custom elements
|
|
210
|
+
UserCard.register();
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### Property Types
|
|
214
|
+
|
|
215
|
+
| Type | Coercion | Default |
|
|
216
|
+
|------|----------|---------|
|
|
217
|
+
| `String` | `String(value)` | `undefined` |
|
|
218
|
+
| `Number` | `Number(value)` | `undefined` |
|
|
219
|
+
| `Boolean` | `Boolean(value)` | `false` |
|
|
220
|
+
| `Array` | Pass through | `[]` |
|
|
221
|
+
| `Object` | Pass through | `{}` |
|
|
222
|
+
|
|
223
|
+
Properties are automatically synced with attributes (camelCase to kebab-case):
|
|
224
|
+
|
|
225
|
+
```html
|
|
226
|
+
<user-card name="John" age="30" active></user-card>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### Shadow DOM
|
|
230
|
+
|
|
231
|
+
Enable Shadow DOM for style encapsulation:
|
|
232
|
+
|
|
233
|
+
```javascript
|
|
234
|
+
class StyledButton extends Component {
|
|
235
|
+
static tag = 'styled-button';
|
|
236
|
+
static shadow = true;
|
|
237
|
+
|
|
238
|
+
render() {
|
|
239
|
+
return html`
|
|
240
|
+
<style>
|
|
241
|
+
button {
|
|
242
|
+
background: blue;
|
|
243
|
+
color: white;
|
|
244
|
+
padding: 10px 20px;
|
|
245
|
+
}
|
|
246
|
+
</style>
|
|
247
|
+
<button><slot></slot></button>
|
|
248
|
+
`;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Reactive State
|
|
254
|
+
|
|
255
|
+
For state shared between components or outside component context:
|
|
256
|
+
|
|
257
|
+
```javascript
|
|
258
|
+
import { reactive, watch, computed } from 'bedrockjs';
|
|
259
|
+
|
|
260
|
+
// Create reactive object
|
|
261
|
+
const state = reactive({
|
|
262
|
+
count: 0,
|
|
263
|
+
items: []
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
// Watch for changes
|
|
267
|
+
const stopWatch = watch(() => {
|
|
268
|
+
console.log('Count changed:', state.count);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
// Computed values
|
|
272
|
+
const doubled = computed(() => state.count * 2);
|
|
273
|
+
console.log(doubled.value); // Access with .value
|
|
274
|
+
|
|
275
|
+
// Update state (triggers watchers)
|
|
276
|
+
state.count++;
|
|
277
|
+
state.items.push('new item');
|
|
278
|
+
|
|
279
|
+
// Stop watching
|
|
280
|
+
stopWatch();
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
#### Signals
|
|
284
|
+
|
|
285
|
+
For simple reactive values:
|
|
286
|
+
|
|
287
|
+
```javascript
|
|
288
|
+
import { signal } from 'bedrockjs';
|
|
289
|
+
|
|
290
|
+
const [getCount, setCount] = signal(0);
|
|
291
|
+
|
|
292
|
+
console.log(getCount()); // 0
|
|
293
|
+
setCount(5);
|
|
294
|
+
console.log(getCount()); // 5
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
#### Batching Updates
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
import { reactive, batch } from 'bedrockjs';
|
|
301
|
+
|
|
302
|
+
const state = reactive({ a: 1, b: 2 });
|
|
303
|
+
|
|
304
|
+
// Multiple updates trigger only one flush
|
|
305
|
+
batch(() => {
|
|
306
|
+
state.a = 10;
|
|
307
|
+
state.b = 20;
|
|
308
|
+
});
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Router
|
|
312
|
+
|
|
313
|
+
Create a single-page application with the router:
|
|
314
|
+
|
|
315
|
+
```javascript
|
|
316
|
+
import { createRouter } from 'bedrockjs';
|
|
317
|
+
|
|
318
|
+
const router = createRouter({
|
|
319
|
+
// Optional: base path for deployment in subdirectory
|
|
320
|
+
base: '/app',
|
|
321
|
+
|
|
322
|
+
routes: [
|
|
323
|
+
{
|
|
324
|
+
path: '/',
|
|
325
|
+
component: 'home-page'
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
path: '/users',
|
|
329
|
+
component: 'users-page',
|
|
330
|
+
loader: async () => {
|
|
331
|
+
const res = await fetch('/api/users');
|
|
332
|
+
return res.json();
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
path: '/users/:id',
|
|
337
|
+
component: 'user-detail',
|
|
338
|
+
loader: async ({ id }) => {
|
|
339
|
+
const res = await fetch(`/api/users/${id}`);
|
|
340
|
+
return res.json();
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
]
|
|
344
|
+
});
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
```html
|
|
348
|
+
<nav>
|
|
349
|
+
<router-link to="/">Home</router-link>
|
|
350
|
+
<router-link to="/users">Users</router-link>
|
|
351
|
+
</nav>
|
|
352
|
+
|
|
353
|
+
<main>
|
|
354
|
+
<router-outlet></router-outlet>
|
|
355
|
+
</main>
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
#### Route Data
|
|
359
|
+
|
|
360
|
+
Components receive `routeData` with loading state:
|
|
361
|
+
|
|
362
|
+
```javascript
|
|
363
|
+
class UserDetail extends Component {
|
|
364
|
+
static tag = 'user-detail';
|
|
365
|
+
|
|
366
|
+
render() {
|
|
367
|
+
const { loading, data, error, params } = this.routeData || {};
|
|
368
|
+
|
|
369
|
+
if (loading) {
|
|
370
|
+
return html`<div>Loading...</div>`;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (error) {
|
|
374
|
+
return html`<div>Error: ${error.message}</div>`;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
return html`
|
|
378
|
+
<div>
|
|
379
|
+
<h1>${data.name}</h1>
|
|
380
|
+
<p>ID: ${params.id}</p>
|
|
381
|
+
</div>
|
|
382
|
+
`;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
#### Programmatic Navigation
|
|
388
|
+
|
|
389
|
+
```javascript
|
|
390
|
+
import { navigate } from 'bedrockjs';
|
|
391
|
+
|
|
392
|
+
// Navigate to a path
|
|
393
|
+
navigate('/users/123');
|
|
394
|
+
|
|
395
|
+
// Replace current history entry
|
|
396
|
+
navigate('/login', { replace: true });
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
#### Route Parameters
|
|
400
|
+
|
|
401
|
+
| Pattern | URL | Params |
|
|
402
|
+
|---------|-----|--------|
|
|
403
|
+
| `/users/:id` | `/users/123` | `{ id: '123' }` |
|
|
404
|
+
| `/posts/:category/:slug` | `/posts/tech/hello` | `{ category: 'tech', slug: 'hello' }` |
|
|
405
|
+
|
|
406
|
+
## API Reference
|
|
407
|
+
|
|
408
|
+
### Template Functions
|
|
409
|
+
|
|
410
|
+
| Function | Description |
|
|
411
|
+
|----------|-------------|
|
|
412
|
+
| `html` | Tagged template literal for creating templates |
|
|
413
|
+
| `render(result, container)` | Render a template into a container |
|
|
414
|
+
| `keyed(key, template)` | Create a keyed template for list rendering |
|
|
415
|
+
|
|
416
|
+
### Component
|
|
417
|
+
|
|
418
|
+
| Static Property | Type | Description |
|
|
419
|
+
|-----------------|------|-------------|
|
|
420
|
+
| `tag` | `string` | Custom element tag name (required) |
|
|
421
|
+
| `shadow` | `boolean` | Enable Shadow DOM (default: `false`) |
|
|
422
|
+
| `properties` | `object` | Reactive property definitions |
|
|
423
|
+
|
|
424
|
+
| Instance Property | Description |
|
|
425
|
+
|-------------------|-------------|
|
|
426
|
+
| `renderRoot` | The root element for rendering (shadow root or element) |
|
|
427
|
+
| `routeData` | Route data when used with router |
|
|
428
|
+
|
|
429
|
+
| Method | Description |
|
|
430
|
+
|--------|-------------|
|
|
431
|
+
| `render()` | Return template (override in subclass) |
|
|
432
|
+
| `updated()` | Called after each render |
|
|
433
|
+
| `requestUpdate()` | Manually trigger a re-render |
|
|
434
|
+
| `static register(tagName?)` | Register the custom element |
|
|
435
|
+
|
|
436
|
+
### Reactive
|
|
437
|
+
|
|
438
|
+
| Function | Description |
|
|
439
|
+
|----------|-------------|
|
|
440
|
+
| `reactive(obj)` | Create a reactive proxy |
|
|
441
|
+
| `watch(fn, options?)` | Watch reactive dependencies, returns stop function |
|
|
442
|
+
| `computed(fn)` | Create a computed value (access via `.value`) |
|
|
443
|
+
| `signal(initial)` | Create a signal, returns `[getter, setter]` |
|
|
444
|
+
| `batch(fn)` | Batch multiple updates |
|
|
445
|
+
|
|
446
|
+
### Router
|
|
447
|
+
|
|
448
|
+
| Function | Description |
|
|
449
|
+
|----------|-------------|
|
|
450
|
+
| `createRouter(options)` | Create and start a router |
|
|
451
|
+
| `navigate(path, options?)` | Navigate programmatically |
|
|
452
|
+
|
|
453
|
+
| Router Options | Type | Description |
|
|
454
|
+
|----------------|------|-------------|
|
|
455
|
+
| `routes` | `array` | Route definitions |
|
|
456
|
+
| `base` | `string` | Base path prefix |
|
|
457
|
+
| `hash` | `boolean` | Use hash-based routing |
|
|
458
|
+
|
|
459
|
+
| Route Definition | Type | Description |
|
|
460
|
+
|------------------|------|-------------|
|
|
461
|
+
| `path` | `string` | URL pattern with optional `:params` |
|
|
462
|
+
| `component` | `string` | Tag name of component to render |
|
|
463
|
+
| `loader` | `function` | Async function to load data |
|
|
464
|
+
|
|
465
|
+
## Browser Support
|
|
466
|
+
|
|
467
|
+
BedrockJS uses modern JavaScript features:
|
|
468
|
+
- ES Modules
|
|
469
|
+
- Custom Elements v1
|
|
470
|
+
- Proxy
|
|
471
|
+
- Private class fields
|
|
472
|
+
|
|
473
|
+
Supported in all modern browsers (Chrome, Firefox, Safari, Edge).
|
|
474
|
+
|
|
475
|
+
## Development
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
# Clone the repository
|
|
479
|
+
git clone https://github.com/your-repo/bedrockjs.git
|
|
480
|
+
cd bedrockjs
|
|
481
|
+
|
|
482
|
+
# Install dependencies
|
|
483
|
+
npm install
|
|
484
|
+
|
|
485
|
+
# Start development server
|
|
486
|
+
npm run dev
|
|
487
|
+
|
|
488
|
+
# Open examples
|
|
489
|
+
open http://localhost:3000/examples/
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
## Architecture
|
|
493
|
+
|
|
494
|
+
### How Templates Work
|
|
495
|
+
|
|
496
|
+
1. **Parse**: The `html` tagged template creates a `TemplateResult` with static strings and dynamic values
|
|
497
|
+
2. **Compile**: On first render, strings are joined with comment markers and parsed into a `<template>` element
|
|
498
|
+
3. **Walk**: The template DOM is walked to find marker positions and create a parts array
|
|
499
|
+
4. **Clone**: The template is cloned for each render instance
|
|
500
|
+
5. **Patch**: Only the dynamic parts are updated on subsequent renders
|
|
501
|
+
|
|
502
|
+
### How Reactivity Works
|
|
503
|
+
|
|
504
|
+
1. **Proxy**: `reactive()` wraps objects in a Proxy that tracks property access
|
|
505
|
+
2. **Track**: When a watcher runs, accessed properties are recorded as dependencies
|
|
506
|
+
3. **Trigger**: When a property changes, dependent watchers are queued
|
|
507
|
+
4. **Flush**: Queued watchers run in the next microtask (batched)
|
|
508
|
+
|
|
509
|
+
### How Components Work
|
|
510
|
+
|
|
511
|
+
1. **Define**: Class extends `Component` with static `tag` and `properties`
|
|
512
|
+
2. **Register**: `customElements.define()` registers the element
|
|
513
|
+
3. **Connect**: When added to DOM, `connectedCallback` initializes and renders
|
|
514
|
+
4. **Update**: Property changes schedule a re-render via microtask
|
|
515
|
+
5. **Render**: `render()` returns a template that patches the DOM
|
|
516
|
+
|
|
517
|
+
## License
|
|
518
|
+
|
|
519
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@devera_se/bedrockjs",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "A lightweight web framework built on web components",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"types": "src/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"default": "./src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./html": {
|
|
14
|
+
"types": "./src/html.d.ts",
|
|
15
|
+
"default": "./src/html.js"
|
|
16
|
+
},
|
|
17
|
+
"./render": {
|
|
18
|
+
"types": "./src/render.d.ts",
|
|
19
|
+
"default": "./src/render.js"
|
|
20
|
+
},
|
|
21
|
+
"./component": {
|
|
22
|
+
"types": "./src/component.d.ts",
|
|
23
|
+
"default": "./src/component.js"
|
|
24
|
+
},
|
|
25
|
+
"./reactive": {
|
|
26
|
+
"types": "./src/reactive.d.ts",
|
|
27
|
+
"default": "./src/reactive.js"
|
|
28
|
+
},
|
|
29
|
+
"./router": {
|
|
30
|
+
"types": "./src/router.d.ts",
|
|
31
|
+
"default": "./src/router.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"src"
|
|
36
|
+
],
|
|
37
|
+
"sideEffects": false,
|
|
38
|
+
"scripts": {
|
|
39
|
+
"dev": "serve -p 3000 .",
|
|
40
|
+
"start": "serve -p 3000 .",
|
|
41
|
+
"examples": "serve -p 3000 . -o /examples"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"serve": "^14.2.0"
|
|
45
|
+
},
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/stonetwig/bedrockjs.git"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/stonetwig/bedrockjs/issues"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/stonetwig/bedrockjs#readme",
|
|
54
|
+
"keywords": [
|
|
55
|
+
"web-components",
|
|
56
|
+
"framework",
|
|
57
|
+
"reactive",
|
|
58
|
+
"router",
|
|
59
|
+
"template",
|
|
60
|
+
"lit",
|
|
61
|
+
"custom-elements",
|
|
62
|
+
"signals"
|
|
63
|
+
],
|
|
64
|
+
"license": "MIT"
|
|
65
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { TemplateResult } from './html.js';
|
|
2
|
+
|
|
3
|
+
export interface ComponentPropertyConfig<T = any> {
|
|
4
|
+
type?: { new (...args: any[]): T } | Function;
|
|
5
|
+
default?: T | (() => T);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type ComponentProperties = Record<string, ComponentPropertyConfig | Function>;
|
|
9
|
+
|
|
10
|
+
export class Component extends HTMLElement {
|
|
11
|
+
static tag: string | null;
|
|
12
|
+
static shadow: boolean;
|
|
13
|
+
static properties: ComponentProperties;
|
|
14
|
+
static autoRegister: boolean;
|
|
15
|
+
|
|
16
|
+
readonly renderRoot: Element | ShadowRoot;
|
|
17
|
+
|
|
18
|
+
routeData: any;
|
|
19
|
+
|
|
20
|
+
render(): TemplateResult | null;
|
|
21
|
+
updated(): void;
|
|
22
|
+
requestUpdate(): void;
|
|
23
|
+
|
|
24
|
+
static register(tagName?: string): typeof Component;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function defineComponent(
|
|
28
|
+
tag: string,
|
|
29
|
+
options?: {
|
|
30
|
+
shadow?: boolean;
|
|
31
|
+
properties?: ComponentProperties;
|
|
32
|
+
autoRegister?: boolean;
|
|
33
|
+
}
|
|
34
|
+
): <T extends typeof Component>(ComponentClass: T) => T;
|
|
35
|
+
|
|
36
|
+
export function autoRegister<T extends typeof Component>(ComponentClass: T): T;
|