bitwrench 2.0.24 → 2.0.30
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 +17 -9
- package/dist/bitwrench-bccl.cjs.js +1 -1
- package/dist/bitwrench-bccl.cjs.min.js +1 -1
- package/dist/bitwrench-bccl.cjs.min.js.gz +0 -0
- package/dist/bitwrench-bccl.esm.js +1 -1
- package/dist/bitwrench-bccl.esm.min.js +1 -1
- package/dist/bitwrench-bccl.esm.min.js.gz +0 -0
- package/dist/bitwrench-bccl.umd.js +1 -1
- package/dist/bitwrench-bccl.umd.min.js +1 -1
- package/dist/bitwrench-bccl.umd.min.js.gz +0 -0
- package/dist/bitwrench-code-edit.cjs.js +1 -1
- package/dist/bitwrench-code-edit.cjs.min.js +1 -1
- package/dist/bitwrench-code-edit.es5.js +1 -1
- package/dist/bitwrench-code-edit.es5.min.js +1 -1
- package/dist/bitwrench-code-edit.esm.js +1 -1
- package/dist/bitwrench-code-edit.esm.min.js +1 -1
- package/dist/bitwrench-code-edit.umd.js +1 -1
- package/dist/bitwrench-code-edit.umd.min.js +1 -1
- package/dist/bitwrench-code-edit.umd.min.js.gz +0 -0
- package/dist/bitwrench-debug.js +1 -1
- package/dist/bitwrench-debug.min.js +1 -1
- package/dist/bitwrench-lean.cjs.js +661 -174
- package/dist/bitwrench-lean.cjs.min.js +7 -7
- package/dist/bitwrench-lean.cjs.min.js.gz +0 -0
- package/dist/bitwrench-lean.es5.js +690 -178
- package/dist/bitwrench-lean.es5.min.js +5 -5
- package/dist/bitwrench-lean.es5.min.js.gz +0 -0
- package/dist/bitwrench-lean.esm.js +661 -174
- package/dist/bitwrench-lean.esm.min.js +6 -6
- package/dist/bitwrench-lean.esm.min.js.gz +0 -0
- package/dist/bitwrench-lean.umd.js +661 -174
- package/dist/bitwrench-lean.umd.min.js +7 -7
- package/dist/bitwrench-lean.umd.min.js.gz +0 -0
- package/dist/bitwrench-util-css.cjs.js +1 -1
- package/dist/bitwrench-util-css.cjs.min.js +1 -1
- package/dist/bitwrench-util-css.es5.js +1 -1
- package/dist/bitwrench-util-css.es5.min.js +1 -1
- package/dist/bitwrench-util-css.esm.js +1 -1
- package/dist/bitwrench-util-css.esm.min.js +1 -1
- package/dist/bitwrench-util-css.umd.js +1 -1
- package/dist/bitwrench-util-css.umd.min.js +1 -1
- package/dist/bitwrench-util-css.umd.min.js.gz +0 -0
- package/dist/bitwrench.cjs.js +659 -172
- package/dist/bitwrench.cjs.min.js +6 -6
- package/dist/bitwrench.cjs.min.js.gz +0 -0
- package/dist/bitwrench.css +6 -6
- package/dist/bitwrench.d.ts +666 -0
- package/dist/bitwrench.es5.js +687 -175
- package/dist/bitwrench.es5.min.js +6 -6
- package/dist/bitwrench.es5.min.js.gz +0 -0
- package/dist/bitwrench.esm.js +659 -172
- package/dist/bitwrench.esm.min.js +5 -5
- package/dist/bitwrench.esm.min.js.gz +0 -0
- package/dist/bitwrench.min.css +1 -1
- package/dist/bitwrench.umd.js +659 -172
- package/dist/bitwrench.umd.min.js +6 -6
- package/dist/bitwrench.umd.min.js.gz +0 -0
- package/dist/builds.json +96 -96
- package/dist/bwserve.cjs.js +140 -7
- package/dist/bwserve.esm.js +141 -8
- package/dist/sri.json +46 -46
- package/docs/README.md +5 -3
- package/docs/bitwrench-for-wasm.md +851 -0
- package/docs/bitwrench-mcp.md +1 -1
- package/docs/bitwrench-taco-schema-discussion.md +694 -0
- package/docs/bitwrench_api.md +134 -24
- package/docs/bitwrench_typescript_usage.md +441 -0
- package/docs/component-cheatsheet.md +1 -1
- package/docs/framework-translation-table.md +1 -1
- package/docs/llm-bitwrench-guide.md +34 -6
- package/docs/routing.md +1 -1
- package/docs/state-management.md +27 -3
- package/docs/thinking-in-bitwrench.md +6 -5
- package/docs/tutorial-bwserve.md +1 -1
- package/docs/tutorial-website.md +1 -1
- package/package.json +16 -10
- package/readme.html +29 -14
- package/src/bitwrench-styles.js +17 -17
- package/src/bitwrench.d.ts +666 -0
- package/src/bitwrench.js +638 -150
- package/src/bwserve/bwclient.js +3 -3
- package/src/bwserve/client.js +26 -0
- package/src/bwserve/index.js +110 -3
- package/src/cli/attach.js +7 -5
- package/src/cli/serve.js +53 -9
- package/src/mcp/live.js +3 -1
- package/src/mcp/server.js +7 -7
- package/src/version.js +3 -3
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
# Using Bitwrench with TypeScript
|
|
2
|
+
|
|
3
|
+
Bitwrench ships TypeScript type definitions in `dist/bitwrench.d.ts`.
|
|
4
|
+
You get autocomplete, type checking, and documentation hover in VS Code,
|
|
5
|
+
WebStorm, and any TypeScript-aware editor -- no extra packages needed.
|
|
6
|
+
|
|
7
|
+
## Quick Start
|
|
8
|
+
|
|
9
|
+
### Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install bitwrench
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The `types` field in `package.json` points to `dist/bitwrench.d.ts`,
|
|
16
|
+
so TypeScript picks up the types automatically.
|
|
17
|
+
|
|
18
|
+
### Import Styles
|
|
19
|
+
|
|
20
|
+
**Default import (full library):**
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import bw from 'bitwrench';
|
|
24
|
+
|
|
25
|
+
const card = bw.makeCard({ title: 'Hello', content: 'World' });
|
|
26
|
+
bw.DOM('#app', card);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Named imports (tree-shakeable):**
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { makeCard, makeButton, makeNav } from 'bitwrench';
|
|
33
|
+
|
|
34
|
+
const card = makeCard({ title: 'Dashboard', content: 'Stats here' });
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**CommonJS (Node.js):**
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
const bw = require('bitwrench');
|
|
41
|
+
|
|
42
|
+
const html = bw.html({ t: 'h1', c: 'Server-rendered' });
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**UMD (script tag -- no import needed):**
|
|
46
|
+
|
|
47
|
+
```html
|
|
48
|
+
<script src="https://unpkg.com/bitwrench/dist/bitwrench.umd.min.js"></script>
|
|
49
|
+
<script>
|
|
50
|
+
// bw is a global. For TS, add a reference comment or declare it:
|
|
51
|
+
bw.DOM('#app', { t: 'p', c: 'Hello from UMD' });
|
|
52
|
+
</script>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
For UMD in a TypeScript file, add a triple-slash reference:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
/// <reference path="node_modules/bitwrench/dist/bitwrench.d.ts" />
|
|
59
|
+
declare var bw: import('bitwrench').Bitwrench;
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Core Types
|
|
63
|
+
|
|
64
|
+
### Taco
|
|
65
|
+
|
|
66
|
+
The fundamental UI primitive. Every bitwrench component is a `Taco` object.
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
import type { Taco, TacoAttributes, TacoOptions, TacoContent } from 'bitwrench';
|
|
70
|
+
|
|
71
|
+
const myCard: Taco = {
|
|
72
|
+
t: 'div',
|
|
73
|
+
a: { class: 'bw_card', id: 'stats' },
|
|
74
|
+
c: [
|
|
75
|
+
{ t: 'h3', c: 'Revenue' },
|
|
76
|
+
{ t: 'p', c: '$1,234' }
|
|
77
|
+
],
|
|
78
|
+
o: {
|
|
79
|
+
state: { value: 1234 },
|
|
80
|
+
render: (el, state) => {
|
|
81
|
+
el.querySelector('.value')!.textContent = '$' + state!.value;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Field summary:**
|
|
88
|
+
|
|
89
|
+
| Field | Type | Required | Description |
|
|
90
|
+
|-------|------|----------|-------------|
|
|
91
|
+
| `t` | `string` | Yes | HTML tag name |
|
|
92
|
+
| `a` | `TacoAttributes` | No | HTML attributes, event handlers, class, style |
|
|
93
|
+
| `c` | `TacoContent` | No | String, number, nested Taco, array, `bw.raw()`, or null |
|
|
94
|
+
| `o` | `TacoOptions` | No | Lifecycle hooks, state, handle methods, slots |
|
|
95
|
+
|
|
96
|
+
### TacoContent
|
|
97
|
+
|
|
98
|
+
Content can be many types:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// String
|
|
102
|
+
const text: Taco = { t: 'p', c: 'Hello' };
|
|
103
|
+
|
|
104
|
+
// Number (auto-stringified)
|
|
105
|
+
const num: Taco = { t: 'span', c: 42 };
|
|
106
|
+
|
|
107
|
+
// Nested TACO
|
|
108
|
+
const nested: Taco = { t: 'div', c: { t: 'em', c: 'italic' } };
|
|
109
|
+
|
|
110
|
+
// Array of mixed content
|
|
111
|
+
const list: Taco = {
|
|
112
|
+
t: 'ul',
|
|
113
|
+
c: [
|
|
114
|
+
{ t: 'li', c: 'one' },
|
|
115
|
+
{ t: 'li', c: 'two' },
|
|
116
|
+
{ t: 'li', c: 'three' }
|
|
117
|
+
]
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// Raw HTML (skips escaping)
|
|
121
|
+
const raw: Taco = { t: 'div', c: bw.raw('<strong>Pre-escaped</strong>') };
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### TacoAttributes
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
const button: Taco = {
|
|
128
|
+
t: 'button',
|
|
129
|
+
a: {
|
|
130
|
+
class: ['bw_btn', 'bw_primary'], // string or string[]
|
|
131
|
+
style: { padding: '8px', color: '#fff' }, // string or object
|
|
132
|
+
disabled: false, // boolean attrs
|
|
133
|
+
onclick: (e: Event) => handleClick(e), // function or string
|
|
134
|
+
'data-id': '123', // custom attributes
|
|
135
|
+
'aria-label': 'Submit form' // ARIA attributes
|
|
136
|
+
},
|
|
137
|
+
c: 'Submit'
|
|
138
|
+
};
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### TacoOptions (Component Handles)
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
const counter: Taco = {
|
|
145
|
+
t: 'div',
|
|
146
|
+
a: { class: 'counter' },
|
|
147
|
+
c: [
|
|
148
|
+
{ t: 'span', a: { class: 'count' }, c: '0' },
|
|
149
|
+
{ t: 'button', a: { onclick: () => el.bw.increment() }, c: '+' }
|
|
150
|
+
],
|
|
151
|
+
o: {
|
|
152
|
+
state: { count: 0 },
|
|
153
|
+
handle: {
|
|
154
|
+
increment: (el: HTMLElement) => {
|
|
155
|
+
el._bw_state.count++;
|
|
156
|
+
bw.update(el);
|
|
157
|
+
},
|
|
158
|
+
reset: (el: HTMLElement) => {
|
|
159
|
+
el._bw_state.count = 0;
|
|
160
|
+
bw.update(el);
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
slots: {
|
|
164
|
+
count: '.count' // auto-generates el.bw.setCount() / el.bw.getCount()
|
|
165
|
+
},
|
|
166
|
+
render: (el: HTMLElement, state: any) => {
|
|
167
|
+
el.querySelector('.count')!.textContent = String(state.count);
|
|
168
|
+
},
|
|
169
|
+
mounted: (el: HTMLElement) => {
|
|
170
|
+
console.log('Counter mounted');
|
|
171
|
+
},
|
|
172
|
+
unmount: (el: HTMLElement) => {
|
|
173
|
+
console.log('Counter removed');
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// Mount and interact through typed handle
|
|
179
|
+
const el = bw.mount('#app', counter);
|
|
180
|
+
(el as any).bw.increment();
|
|
181
|
+
(el as any).bw.setCount('99');
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## BCCL Component Configs
|
|
185
|
+
|
|
186
|
+
The `make*()` factories have typed config objects for the most common
|
|
187
|
+
components. TypeScript will autocomplete property names and catch typos.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
import bw from 'bitwrench';
|
|
191
|
+
import type { CardConfig, ButtonConfig, TabsConfig, AccordionConfig } from 'bitwrench';
|
|
192
|
+
|
|
193
|
+
// Card -- typed config catches typos
|
|
194
|
+
const card = bw.makeCard({
|
|
195
|
+
title: 'Dashboard',
|
|
196
|
+
content: 'Welcome back',
|
|
197
|
+
footer: 'Last updated: today',
|
|
198
|
+
variant: 'primary',
|
|
199
|
+
shadow: true
|
|
200
|
+
});
|
|
201
|
+
// bw.makeCard({ label: 'Oops' }) // TS error: 'label' not in CardConfig
|
|
202
|
+
|
|
203
|
+
// Button
|
|
204
|
+
const btn = bw.makeButton({
|
|
205
|
+
text: 'Save',
|
|
206
|
+
variant: 'success',
|
|
207
|
+
size: 'lg',
|
|
208
|
+
onclick: () => save()
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// Tabs
|
|
212
|
+
const tabs = bw.makeTabs({
|
|
213
|
+
tabs: [
|
|
214
|
+
{ text: 'Overview', content: 'Tab 1 content', active: true },
|
|
215
|
+
{ text: 'Details', content: { t: 'div', c: 'Tab 2 TACO content' } }
|
|
216
|
+
]
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Accordion -- note: uses title/content, NOT label/header/body
|
|
220
|
+
const acc = bw.makeAccordion({
|
|
221
|
+
items: [
|
|
222
|
+
{ title: 'Section 1', content: 'Content 1' },
|
|
223
|
+
{ title: 'Section 2', content: 'Content 2' }
|
|
224
|
+
]
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## Styles / Theming
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
import bw from 'bitwrench';
|
|
232
|
+
import type { StyleConfig, StylesResult, Palette, ColorShades } from 'bitwrench';
|
|
233
|
+
|
|
234
|
+
// Generate theme from seed colors
|
|
235
|
+
const config: StyleConfig = {
|
|
236
|
+
primary: '#2563eb',
|
|
237
|
+
secondary: '#7c3aed',
|
|
238
|
+
background: '#ffffff',
|
|
239
|
+
surface: '#f8fafc'
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const styles: StylesResult = bw.makeStyles(config);
|
|
243
|
+
bw.applyStyles(styles);
|
|
244
|
+
|
|
245
|
+
// Access palette values
|
|
246
|
+
const p: Palette = styles.palette;
|
|
247
|
+
const primaryBase: string = p.primary.base; // '#2563eb'
|
|
248
|
+
const primaryHover: string = p.primary.hover; // derived shade
|
|
249
|
+
const bg: string = p.background; // plain string (NOT an object)
|
|
250
|
+
|
|
251
|
+
// Toggle dark/light
|
|
252
|
+
bw.toggleStyles();
|
|
253
|
+
|
|
254
|
+
// Shorthand: generate + apply in one call
|
|
255
|
+
bw.loadStyles({ primary: '#dc2626' });
|
|
256
|
+
|
|
257
|
+
// Structural CSS only (no colors)
|
|
258
|
+
bw.loadStyles();
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**Palette gotcha**: `palette.background`, `palette.surface`, and
|
|
262
|
+
`palette.surfaceAlt` are plain strings. All other keys (`primary`,
|
|
263
|
+
`secondary`, etc.) are `ColorShades` objects with `.base`, `.hover`,
|
|
264
|
+
`.active`, `.light`, `.darkText`, `.border`, `.focus`, `.textOn`.
|
|
265
|
+
|
|
266
|
+
## Color Utilities
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
const hsl = bw.hexToHsl('#2563eb'); // [221, 83, 53]
|
|
270
|
+
const hex = bw.hslToHex([221, 83, 53]); // '#2563eb'
|
|
271
|
+
|
|
272
|
+
const lighter = bw.adjustLightness('#2563eb', 20); // lighten by 20
|
|
273
|
+
const mixed = bw.mixColor('#ff0000', '#0000ff', 0.5); // purple
|
|
274
|
+
const lum = bw.relativeLuminance('#2563eb'); // 0.0-1.0
|
|
275
|
+
const textColor = bw.textOnColor('#2563eb'); // '#fff' or '#000'
|
|
276
|
+
|
|
277
|
+
const shades: ColorShades = bw.deriveShades('#2563eb');
|
|
278
|
+
// { base, hover, active, light, darkText, border, focus, textOn }
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Routing
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
import bw from 'bitwrench';
|
|
285
|
+
import type { RouterConfig, RouterHandle } from 'bitwrench';
|
|
286
|
+
|
|
287
|
+
const config: RouterConfig = {
|
|
288
|
+
routes: {
|
|
289
|
+
'/': () => ({ t: 'h1', c: 'Home' }),
|
|
290
|
+
'/user/:id': (params) => ({
|
|
291
|
+
t: 'div',
|
|
292
|
+
c: 'User ' + params.id
|
|
293
|
+
}),
|
|
294
|
+
'*': () => ({ t: 'p', c: '404 Not Found' })
|
|
295
|
+
},
|
|
296
|
+
target: '#app',
|
|
297
|
+
mode: 'hash'
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const router: RouterHandle = bw.router(config);
|
|
301
|
+
router.navigate('/user/42');
|
|
302
|
+
console.log(router.current()); // '/user/42'
|
|
303
|
+
router.destroy();
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
## Server-Side Rendering
|
|
307
|
+
|
|
308
|
+
bitwrench works in Node.js. `bw.html()` renders TACO to HTML strings
|
|
309
|
+
with no DOM dependency.
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
import bw from 'bitwrench';
|
|
313
|
+
|
|
314
|
+
// Render TACO to HTML string (Node.js or browser)
|
|
315
|
+
const html: string = bw.html({
|
|
316
|
+
t: 'div',
|
|
317
|
+
a: { class: 'card' },
|
|
318
|
+
c: [
|
|
319
|
+
{ t: 'h2', c: 'Server Rendered' },
|
|
320
|
+
{ t: 'p', c: 'No DOM needed' }
|
|
321
|
+
]
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
// Generate complete HTML page
|
|
325
|
+
const page: string = bw.htmlPage({
|
|
326
|
+
title: 'My App',
|
|
327
|
+
content: { t: 'h1', c: 'Hello' }
|
|
328
|
+
});
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Extending Types
|
|
332
|
+
|
|
333
|
+
### Custom component config
|
|
334
|
+
|
|
335
|
+
```typescript
|
|
336
|
+
import type { Taco, ComponentConfig } from 'bitwrench';
|
|
337
|
+
|
|
338
|
+
interface MyWidgetConfig extends ComponentConfig {
|
|
339
|
+
label: string;
|
|
340
|
+
value: number;
|
|
341
|
+
onChange?: (newValue: number) => void;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function makeMyWidget(config: MyWidgetConfig): Taco {
|
|
345
|
+
return {
|
|
346
|
+
t: 'div',
|
|
347
|
+
a: { class: 'my-widget' },
|
|
348
|
+
c: [
|
|
349
|
+
{ t: 'label', c: config.label },
|
|
350
|
+
{
|
|
351
|
+
t: 'input',
|
|
352
|
+
a: {
|
|
353
|
+
type: 'number',
|
|
354
|
+
value: String(config.value),
|
|
355
|
+
oninput: (e: Event) => {
|
|
356
|
+
const v = Number((e.target as HTMLInputElement).value);
|
|
357
|
+
if (config.onChange) config.onChange(v);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
]
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### Adding el.bw types for specific components
|
|
367
|
+
|
|
368
|
+
The `el.bw` namespace is dynamically populated from `o.handle` and
|
|
369
|
+
`o.slots`. TypeScript doesn't know the specific methods at compile time.
|
|
370
|
+
You can augment with a cast:
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
interface CardHandle {
|
|
374
|
+
setTitle(v: string): void;
|
|
375
|
+
getTitle(): string;
|
|
376
|
+
setContent(v: string | Taco): void;
|
|
377
|
+
getContent(): string;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const el = bw.mount('#app', bw.makeCard({ title: 'Hello' }));
|
|
381
|
+
const handle = (el as any).bw as CardHandle;
|
|
382
|
+
handle.setTitle('Updated');
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## tsconfig.json Tips
|
|
386
|
+
|
|
387
|
+
bitwrench works with any `moduleResolution` setting. Recommended:
|
|
388
|
+
|
|
389
|
+
```json
|
|
390
|
+
{
|
|
391
|
+
"compilerOptions": {
|
|
392
|
+
"target": "ES2020",
|
|
393
|
+
"module": "ESNext",
|
|
394
|
+
"moduleResolution": "bundler",
|
|
395
|
+
"esModuleInterop": true,
|
|
396
|
+
"strict": true
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
For Node.js (CommonJS):
|
|
402
|
+
|
|
403
|
+
```json
|
|
404
|
+
{
|
|
405
|
+
"compilerOptions": {
|
|
406
|
+
"target": "ES2020",
|
|
407
|
+
"module": "commonjs",
|
|
408
|
+
"moduleResolution": "node",
|
|
409
|
+
"esModuleInterop": true
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## What's Not Typed
|
|
415
|
+
|
|
416
|
+
bitwrench is a JavaScript-first library. Some patterns are inherently
|
|
417
|
+
dynamic and don't have specific types:
|
|
418
|
+
|
|
419
|
+
- **`el.bw.*` methods** -- populated at runtime from `o.handle`/`o.slots`.
|
|
420
|
+
Cast `el.bw` to a custom interface for your components.
|
|
421
|
+
- **`bw.apply()` wire protocol messages** -- typed as `Record<string, any>`.
|
|
422
|
+
The bwserve protocol is documented in `dev/bw-client-server.md`.
|
|
423
|
+
- **Less common `make*()` configs** -- typed as `ComponentConfig` (open
|
|
424
|
+
object). The most-used components (Card, Button, Tabs, Accordion, Modal,
|
|
425
|
+
Alert, Nav, Input, Carousel, Table) have specific config types.
|
|
426
|
+
|
|
427
|
+
## FAQ
|
|
428
|
+
|
|
429
|
+
**Q: Do I need to install `@types/bitwrench`?**
|
|
430
|
+
No. Types ship with the package. There is no separate `@types` package.
|
|
431
|
+
|
|
432
|
+
**Q: Can I use bitwrench without TypeScript?**
|
|
433
|
+
Yes. bitwrench is a JavaScript library. TypeScript support is optional.
|
|
434
|
+
The `.d.ts` file provides editor autocomplete even in plain `.js` files
|
|
435
|
+
if your editor supports it (VS Code does by default).
|
|
436
|
+
|
|
437
|
+
**Q: Why not write bitwrench in TypeScript?**
|
|
438
|
+
bitwrench is designed for zero-toolchain development. You can load it via
|
|
439
|
+
`<script>` tag and start building UI -- no compiler, no bundler, no
|
|
440
|
+
`tsconfig.json`. TypeScript types are provided for developers who choose
|
|
441
|
+
to use TS, without imposing it on everyone.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Component Cheat Sheet
|
|
2
2
|
|
|
3
3
|
> **Before you write custom TACO for a common UI pattern, check this list.**
|
|
4
|
-
> Bitwrench ships
|
|
4
|
+
> Bitwrench ships ready-made `make*()` factories. Each returns a Level 0 TACO object.
|
|
5
5
|
|
|
6
6
|
## Full Component Table
|
|
7
7
|
|
|
@@ -26,7 +26,7 @@ How common UI operations map across frameworks. Each cell shows the idiomatic on
|
|
|
26
26
|
| **Theme / design tokens** | Apply consistent theming | ThemeProvider / CSS vars | CSS vars / provide | CSS custom properties | CSS vars | CSS vars / createContext | `bw.loadStyles({ primary: '#hex' })` or `bw.makeStyles(cfg)` => `styles.palette` |
|
|
27
27
|
| **Build step required** | Required toolchain | Yes (Babel/Vite/webpack) | Yes (Vite or Vue CLI) | No | Yes (Svelte compiler) | Yes (Vite/Babel) | **No** |
|
|
28
28
|
| **Client-side routing** | Map URLs to views | React Router / TanStack Router | Vue Router | Manual `hashchange` | SvelteKit routes | @solidjs/router | `bw.router({ routes: { '/': fn } })` |
|
|
29
|
-
| **Bundle size** | Shipped JS size | ~45KB (React + ReactDOM) | ~33KB (Vue 3) | 0KB | ~2KB (runtime) | ~7KB | **~40KB** (includes
|
|
29
|
+
| **Bundle size** | Shipped JS size | ~45KB (React + ReactDOM) | ~33KB (Vue 3) | 0KB | ~2KB (runtime) | ~7KB | **~40KB** (includes components + CSS gen + router) |
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
@@ -329,7 +329,7 @@ bw.u.css('p4 shadow') // includes your custom token
|
|
|
329
329
|
|
|
330
330
|
## Step 6: BCCL Components
|
|
331
331
|
|
|
332
|
-
**Bitwrench ships
|
|
332
|
+
**Bitwrench ships ready-made components. Check the table below BEFORE writing custom TACO for common UI patterns.** All `bw.make*()` return Level 0 TACO objects. Factory dispatcher: `bw.make('card', props)`.
|
|
333
333
|
|
|
334
334
|
### Most-Used Components
|
|
335
335
|
|
|
@@ -406,7 +406,7 @@ card.bw.setContent({ t: 'b', c: '$42k' });
|
|
|
406
406
|
var el = bw.$('#app')[0];
|
|
407
407
|
el._bw_state; // current state
|
|
408
408
|
el._bw_render; // render function
|
|
409
|
-
bw.inspect(el); //
|
|
409
|
+
bw.inspect(el, 0); // introspect element (state, handles, type, classes)
|
|
410
410
|
```
|
|
411
411
|
|
|
412
412
|
### bwcli attach -- remote debugging REPL
|
|
@@ -612,13 +612,14 @@ bwcli serve # dev server (port 7902)
|
|
|
612
612
|
| `bw.mount(sel, taco)` | Mount + return root element |
|
|
613
613
|
| `bw.cleanup(el)` | Run unmount hooks, clear subscriptions |
|
|
614
614
|
| `bw.patch(id, content)` | Update element by id or UUID |
|
|
615
|
-
| `bw.inspect(el)` |
|
|
615
|
+
| `bw.inspect(el, depth)` | Introspect DOM subtree with bitwrench metadata |
|
|
616
616
|
|
|
617
617
|
### Communication
|
|
618
618
|
| Function | Description |
|
|
619
619
|
|----------|-------------|
|
|
620
|
-
| `bw.pub(topic, data)` | App-wide publish |
|
|
621
|
-
| `bw.sub(topic, fn, el?)` | Subscribe (optional lifecycle tie
|
|
620
|
+
| `bw.pub(topic, data)` | App-wide publish (fires exact + wildcard matches) |
|
|
621
|
+
| `bw.sub(topic, fn, el?)` | Subscribe (supports wildcard `'ns:*'`; optional lifecycle tie) |
|
|
622
|
+
| `bw.once(topic, fn, el?)` | One-shot subscribe (auto-unsub after first fire) |
|
|
622
623
|
| `bw.message(target, action, data)` | Dispatch to `el.bw[action](data)` |
|
|
623
624
|
| `bw.emit(el, event, detail)` | DOM-scoped CustomEvent |
|
|
624
625
|
|
|
@@ -658,7 +659,34 @@ bwcli serve # dev server (port 7902)
|
|
|
658
659
|
9. **CSS classes use `bw-` prefix**: `bw-card`, `bw-btn`, `bw-container`.
|
|
659
660
|
10. **Routing is built in** -- `bw.router()` for SPAs. Hash mode by default, history mode optional.
|
|
660
661
|
11. **Use `bw.mount()` + `el.bw`** for targeted updates. `o.handle` for methods, `o.slots` for content areas. Avoids re-render side effects (lost focus, scroll reset).
|
|
661
|
-
12. **Debug**: `bw.inspect(el)`, `el._bw_state`, `bwcli attach` for remote REPL.
|
|
662
|
+
12. **Debug**: `bw.inspect(el, 0)`, `el._bw_state`, `bwcli attach` for remote REPL.
|
|
663
|
+
|
|
664
|
+
---
|
|
665
|
+
|
|
666
|
+
## TypeScript
|
|
667
|
+
|
|
668
|
+
Full type declarations ship with the package (`dist/bitwrench.d.ts`). No `@types`
|
|
669
|
+
package needed.
|
|
670
|
+
|
|
671
|
+
```typescript
|
|
672
|
+
import bw from 'bitwrench';
|
|
673
|
+
import type { Taco, TacoOptions, StyleConfig, Palette } from 'bitwrench';
|
|
674
|
+
|
|
675
|
+
// TACO objects are fully typed
|
|
676
|
+
var card: Taco = bw.makeCard({ title: 'Hello', content: 'World' });
|
|
677
|
+
|
|
678
|
+
// Style configs get autocomplete
|
|
679
|
+
var styles = bw.makeStyles({ primary: '#336699' } as StyleConfig);
|
|
680
|
+
|
|
681
|
+
// Named BCCL imports for tree-shaking
|
|
682
|
+
import { makeCard, makeTable, makeButton } from 'bitwrench/bccl';
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
Core types: `Taco`, `TacoContent`, `TacoAttributes`, `TacoOptions`, `StyleConfig`,
|
|
686
|
+
`Palette`, `ColorShades`, `Styles`, `RouterConfig`. All component configs are
|
|
687
|
+
typed (e.g. `CardConfig`, `ButtonConfig`, `TableConfig`).
|
|
688
|
+
|
|
689
|
+
See [TypeScript Usage Guide](bitwrench_typescript_usage.md) for full details.
|
|
662
690
|
|
|
663
691
|
---
|
|
664
692
|
|
package/docs/routing.md
CHANGED
|
@@ -558,5 +558,5 @@ After `destroy()`, `bw.navigate()` calls are no-ops and no more `bw:route` event
|
|
|
558
558
|
|
|
559
559
|
- [App Patterns](app-patterns.md) -- Multi-Page SPA pattern with router + shared state
|
|
560
560
|
- [State Management](state-management.md) -- Three-level component model, store pattern
|
|
561
|
-
- [Component Cheat Sheet](component-cheatsheet.md) -- All
|
|
561
|
+
- [Component Cheat Sheet](component-cheatsheet.md) -- All components at a glance
|
|
562
562
|
- [examples/dashboard-spa/](../examples/dashboard-spa/) -- Working SPA with 4 routed views
|
package/docs/state-management.md
CHANGED
|
@@ -567,6 +567,20 @@ var results = {
|
|
|
567
567
|
|
|
568
568
|
Pub/sub is app-scoped -- publishers and subscribers do not need to know about each other. Pass the element as the third argument to `bw.sub()` to tie the subscription's lifetime to the element (auto-cleaned on `bw.cleanup()`).
|
|
569
569
|
|
|
570
|
+
Wildcard subscriptions let you listen to a group of related topics at once:
|
|
571
|
+
|
|
572
|
+
```javascript
|
|
573
|
+
// Listen to ALL search-related topics
|
|
574
|
+
bw.sub('search:*', function(detail, topic) {
|
|
575
|
+
console.log('Search event:', topic, detail);
|
|
576
|
+
}, el);
|
|
577
|
+
|
|
578
|
+
// These all fire the wildcard handler above:
|
|
579
|
+
bw.pub('search:changed', { query: 'foo' });
|
|
580
|
+
bw.pub('search:cleared');
|
|
581
|
+
bw.pub('search:submitted', { query: 'foo' });
|
|
582
|
+
```
|
|
583
|
+
|
|
570
584
|
### Updating child widgets within a parent component
|
|
571
585
|
|
|
572
586
|
When a parent component contains child sub-components (like a progress bar inside a dashboard card), use pub/sub to update the child:
|
|
@@ -622,8 +636,9 @@ These primitives are the building blocks of the stateful TACO model. They are al
|
|
|
622
636
|
| `bw.uuid(prefix)` | Generate a UUID class for addressing |
|
|
623
637
|
| `bw.emit(el, event, detail)` | Dispatch a CustomEvent on a DOM element |
|
|
624
638
|
| `bw.on(el, event, handler)` | Listen for a CustomEvent on a DOM element |
|
|
625
|
-
| `bw.pub(topic, detail)` | Publish to app-wide topic |
|
|
626
|
-
| `bw.sub(topic, handler, el?)` | Subscribe to
|
|
639
|
+
| `bw.pub(topic, detail)` | Publish to app-wide topic (fires exact + wildcard matches) |
|
|
640
|
+
| `bw.sub(topic, handler, el?)` | Subscribe to topic (supports wildcard `'ns:*'` patterns) |
|
|
641
|
+
| `bw.once(topic, handler, el?)` | One-shot subscribe (auto-unsub after first fire) |
|
|
627
642
|
| `bw.unsub(topic, handler)` | Unsubscribe from topic |
|
|
628
643
|
| `bw.cleanup(el)` | Run unmount hooks and clear subscriptions |
|
|
629
644
|
|
|
@@ -725,6 +740,15 @@ bw.sub('store:todos', renderTodos, todosEl);
|
|
|
725
740
|
bw.sub('store:projects', renderProjects, projectsEl);
|
|
726
741
|
```
|
|
727
742
|
|
|
743
|
+
If you need a global listener (e.g. for logging or debug), use a wildcard:
|
|
744
|
+
|
|
745
|
+
```javascript
|
|
746
|
+
// OK for debug/logging -- not for rendering
|
|
747
|
+
bw.sub('store:*', function(data, topic) {
|
|
748
|
+
console.log('[store]', topic, data);
|
|
749
|
+
});
|
|
750
|
+
```
|
|
751
|
+
|
|
728
752
|
### When to use
|
|
729
753
|
|
|
730
754
|
- Multi-view SPAs where views share data
|
|
@@ -758,7 +782,7 @@ bw.router({
|
|
|
758
782
|
| Server pushes UI updates | Level 1 -- `bw.patch()` / `bw.DOM()` |
|
|
759
783
|
| Components need to talk to each other | `bw.pub()`/`bw.sub()` |
|
|
760
784
|
| URL-driven views (SPA) | `bw.router()` -- see [Routing](routing.md) |
|
|
761
|
-
| Debugging component state | `el._bw_state` in the console, or `bw.inspect(selector)` |
|
|
785
|
+
| Debugging component state | `el._bw_state` in the console, or `bw.inspect(selector, 0)` |
|
|
762
786
|
|
|
763
787
|
---
|
|
764
788
|
|
|
@@ -588,7 +588,7 @@ No `v-for`, no `{#each}`, no special key rules. Just JavaScript.
|
|
|
588
588
|
|
|
589
589
|
### What BCCL is and why it exists
|
|
590
590
|
|
|
591
|
-
BCCL (Bitwrench Common Component Library) is a set of
|
|
591
|
+
BCCL (Bitwrench Common Component Library) is a set of factory functions that return TACO objects for common UI patterns — cards, buttons, navbars, tables, forms, modals, alerts, and more. Think of it as Bootstrap or shadcn/ui, but instead of HTML templates you get plain JavaScript objects.
|
|
592
592
|
|
|
593
593
|
The point: you can build a complete, styled page without writing a single line of CSS or HTML. Load the default styles, call the factories, render. Great for quick UIs, prototyping, embedded device interfaces, and internal tools.
|
|
594
594
|
|
|
@@ -1323,7 +1323,7 @@ Key things this example proves:
|
|
|
1323
1323
|
|
|
1324
1324
|
| Feature | Why not | What to use instead |
|
|
1325
1325
|
|---------|---------|-------------------|
|
|
1326
|
-
| TypeScript types | Ships
|
|
1326
|
+
| TypeScript types | Ships `dist/bitwrench.d.ts` with full type declarations | See [TypeScript Usage Guide](bitwrench_typescript_usage.md) |
|
|
1327
1327
|
| Virtual DOM | Targeted patches via UUID refs are sufficient | `bw.patch()`, `o.render` + `bw.update()` |
|
|
1328
1328
|
| CSS purging | You generate only what you use via `bw.css()` | N/A |
|
|
1329
1329
|
| SSR hydration | `bw.html()` for SSR, `bw.DOM()` for client | Full page render via `bw.html()` in Node |
|
|
@@ -1381,9 +1381,10 @@ Key things this example proves:
|
|
|
1381
1381
|
|
|
1382
1382
|
| Function | What it does |
|
|
1383
1383
|
|----------|-------------|
|
|
1384
|
-
| `bw.pub(topic, data)` | Publish to all subscribers |
|
|
1385
|
-
| `bw.sub(topic, fn)` | Subscribe (returns unsub function) |
|
|
1384
|
+
| `bw.pub(topic, data)` | Publish to all subscribers (exact + wildcard) |
|
|
1385
|
+
| `bw.sub(topic, fn)` | Subscribe (returns unsub function; supports wildcard `'ns:*'`) |
|
|
1386
1386
|
| `bw.sub(topic, fn, owner)` | Subscribe with auto-cleanup when owner is removed |
|
|
1387
|
+
| `bw.once(topic, fn, el?)` | One-shot subscribe (auto-unsub after first fire) |
|
|
1387
1388
|
|
|
1388
1389
|
### Routing
|
|
1389
1390
|
|
|
@@ -1450,7 +1451,7 @@ How common UI operations map across frameworks. Each cell is the idiomatic one-l
|
|
|
1450
1451
|
| **Form input binding** | Read form values | `value={x} onChange={...}` | `v-model="x"` | `input.value` | `bind:value={x}` | `value={x()} onInput={...}` | `bw.$('#id')[0].value` or `bw.makeInput({oninput:fn})` |
|
|
1451
1452
|
| **Theme / design tokens** | Apply consistent theming | ThemeProvider / CSS vars | CSS vars / provide | CSS custom properties | CSS vars | CSS vars / createContext | `bw.loadStyles({ primary: '#hex' })` or `bw.makeStyles(cfg)` => `theme.palette` |
|
|
1452
1453
|
| **Build step required** | Required toolchain | Yes (Babel/Vite/webpack) | Yes (Vite or Vue CLI) | No | Yes (Svelte compiler) | Yes (Vite/Babel) | **No** — open the HTML file |
|
|
1453
|
-
| **Bundle size** | Shipped JS size | ~45KB (React + ReactDOM) | ~33KB (Vue 3) | 0KB | ~2KB (runtime) | ~7KB | **~40KB** (bitwrench UMD gzipped, includes
|
|
1454
|
+
| **Bundle size** | Shipped JS size | ~45KB (React + ReactDOM) | ~33KB (Vue 3) | 0KB | ~2KB (runtime) | ~7KB | **~40KB** (bitwrench UMD gzipped, includes components + CSS gen) |
|
|
1454
1455
|
|
|
1455
1456
|
---
|
|
1456
1457
|
|
package/docs/tutorial-bwserve.md
CHANGED
|
@@ -292,6 +292,6 @@ For production, put a reverse proxy (nginx, Caddy) in front for TLS and static a
|
|
|
292
292
|
## Next steps
|
|
293
293
|
|
|
294
294
|
- [bwserve Reference](bwserve.md) — full API documentation
|
|
295
|
-
- [Component Library](component-library.md) — all
|
|
295
|
+
- [Component Library](component-library.md) — all `make*()` components work in bwserve
|
|
296
296
|
- [Tutorial: Embedded](tutorial-embedded.md) — same protocol on ESP32
|
|
297
297
|
- [examples/client-server/](../examples/client-server/) — runnable example
|
package/docs/tutorial-website.md
CHANGED
|
@@ -248,7 +248,7 @@ This produces a self-contained HTML file with the ocean theme baked in — works
|
|
|
248
248
|
|
|
249
249
|
## Next steps
|
|
250
250
|
|
|
251
|
-
- [Component Library](component-library.md) -- all
|
|
251
|
+
- [Component Library](component-library.md) -- all `make*()` functions
|
|
252
252
|
- [Theming](theming.md) -- customize colors, spacing, and radius
|
|
253
253
|
- [State Management](state-management.md) -- add interactivity with `o.state` + `o.render`
|
|
254
254
|
- [Routing](routing.md) -- turn this into a multi-page SPA with `bw.router()`
|