bitwrench 2.0.31 → 2.1.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 +210 -125
- package/dist/bitwrench-bccl.cjs.js +349 -188
- package/dist/bitwrench-bccl.cjs.min.js +2 -39
- package/dist/bitwrench-bccl.cjs.min.js.gz +0 -0
- package/dist/bitwrench-bccl.esm.js +349 -188
- package/dist/bitwrench-bccl.esm.min.js +2 -39
- package/dist/bitwrench-bccl.esm.min.js.gz +0 -0
- package/dist/bitwrench-bccl.umd.js +349 -188
- package/dist/bitwrench-bccl.umd.min.js +2 -39
- package/dist/bitwrench-bccl.umd.min.js.gz +0 -0
- package/dist/bitwrench-code-edit.cjs.js +17 -6
- package/dist/bitwrench-code-edit.cjs.min.js +2 -20
- package/dist/bitwrench-code-edit.es5.js +8 -3
- package/dist/bitwrench-code-edit.es5.min.js +2 -19
- package/dist/bitwrench-code-edit.esm.js +17 -6
- package/dist/bitwrench-code-edit.esm.min.js +2 -19
- package/dist/bitwrench-code-edit.umd.js +17 -6
- package/dist/bitwrench-code-edit.umd.min.js +2 -19
- 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 +2492 -1628
- package/dist/bitwrench-lean.cjs.min.js +2 -80
- package/dist/bitwrench-lean.cjs.min.js.gz +0 -0
- package/dist/bitwrench-lean.es5.js +2740 -1838
- package/dist/bitwrench-lean.es5.min.js +2 -49
- package/dist/bitwrench-lean.es5.min.js.gz +0 -0
- package/dist/bitwrench-lean.esm.js +2492 -1628
- package/dist/bitwrench-lean.esm.min.js +2 -80
- package/dist/bitwrench-lean.esm.min.js.gz +0 -0
- package/dist/bitwrench-lean.umd.js +2492 -1628
- package/dist/bitwrench-lean.umd.min.js +2 -80
- package/dist/bitwrench-lean.umd.min.js.gz +0 -0
- package/dist/bitwrench-util-color.cjs.js +251 -0
- package/dist/bitwrench-util-color.cjs.min.js +3 -0
- package/dist/bitwrench-util-color.es5.js +256 -0
- package/dist/bitwrench-util-color.es5.min.js +3 -0
- package/dist/bitwrench-util-color.esm.js +241 -0
- package/dist/bitwrench-util-color.esm.min.js +3 -0
- package/dist/bitwrench-util-color.umd.js +257 -0
- package/dist/bitwrench-util-color.umd.min.js +3 -0
- package/dist/bitwrench-util-css.cjs.js +2 -1
- package/dist/bitwrench-util-css.cjs.min.js +2 -21
- package/dist/bitwrench-util-css.es5.js +2 -1
- package/dist/bitwrench-util-css.es5.min.js +2 -20
- package/dist/bitwrench-util-css.esm.js +2 -1
- package/dist/bitwrench-util-css.esm.min.js +1 -19
- package/dist/bitwrench-util-css.umd.js +2 -1
- package/dist/bitwrench-util-css.umd.min.js +2 -20
- package/dist/bitwrench-util-css.umd.min.js.gz +0 -0
- package/dist/bitwrench.cjs.js +2826 -1801
- package/dist/bitwrench.cjs.min.js +2 -99
- package/dist/bitwrench.cjs.min.js.gz +0 -0
- package/dist/bitwrench.css +403 -479
- package/dist/bitwrench.d.ts +70 -73
- package/dist/bitwrench.es5.js +3106 -2020
- package/dist/bitwrench.es5.min.js +2 -67
- package/dist/bitwrench.es5.min.js.gz +0 -0
- package/dist/bitwrench.esm.js +2826 -1801
- package/dist/bitwrench.esm.min.js +2 -99
- package/dist/bitwrench.esm.min.js.gz +0 -0
- package/dist/bitwrench.min.css +1 -1
- package/dist/bitwrench.umd.js +2826 -1801
- package/dist/bitwrench.umd.min.js +2 -99
- package/dist/bitwrench.umd.min.js.gz +0 -0
- package/dist/builds.json +222 -134
- package/dist/bwserve.cjs.js +308 -298
- package/dist/bwserve.d.ts +157 -0
- package/dist/bwserve.esm.js +309 -299
- package/dist/sri.json +54 -46
- package/docs/README.md +6 -3
- package/docs/app-patterns.md +7 -6
- package/docs/bitwrench-for-wasm.md +53 -54
- package/docs/bitwrench-mcp.md +2 -2
- package/docs/bitwrench-northstar-principles.md +406 -0
- package/docs/bitwrench-taco-schema-discussion.md +2 -2
- package/docs/bitwrench_api.md +191 -106
- package/docs/bitwrench_typescript_usage.md +5 -5
- package/docs/bw-attach.md +29 -75
- package/docs/bwserve.md +200 -168
- package/docs/cli.md +36 -12
- package/docs/component-cheatsheet.md +2 -2
- package/docs/component-library.md +4 -4
- package/docs/component-lifecycle.md +234 -0
- package/docs/drift-lint.md +268 -0
- package/docs/framework-translation-table.md +4 -4
- package/docs/llm-bitwrench-guide.md +60 -50
- package/docs/routing.md +11 -13
- package/docs/state-management.md +110 -109
- package/docs/taco-format.md +13 -14
- package/docs/theming.md +13 -3
- package/docs/thinking-in-bitwrench.md +858 -983
- package/docs/tutorial-bwserve.md +37 -36
- package/docs/tutorial-embedded.md +10 -21
- package/docs/tutorial-website.md +2 -2
- package/package.json +38 -7
- package/readme.html +262 -160
- package/src/bitwrench-bccl-entry.js +2 -2
- package/src/bitwrench-bccl.js +346 -185
- package/src/bitwrench-code-edit.js +16 -5
- package/src/bitwrench-color-utils.js +117 -181
- package/src/bitwrench-file-ops.js +2 -2
- package/src/bitwrench-lean.js +4 -3
- package/src/bitwrench-router.js +5 -2
- package/src/bitwrench-styles.js +420 -504
- package/src/bitwrench-util-color.js +240 -0
- package/src/bitwrench-util-css.js +1 -0
- package/src/bitwrench-utils.js +4 -0
- package/src/bitwrench.d.ts +70 -73
- package/src/bitwrench.h +5 -0
- package/src/bitwrench.js +1939 -933
- package/src/bwserve/attach.js +0 -1
- package/src/bwserve/bwclient.js +172 -32
- package/src/bwserve/bwshell.js +0 -4
- package/src/bwserve/client.js +59 -220
- package/src/bwserve/index.js +78 -42
- package/src/bwserve.d.ts +157 -0
- package/src/bwserve.h +5 -0
- package/src/cli/attach.js +12 -75
- package/src/cli/convert.js +2 -2
- package/src/cli/serve.js +37 -35
- package/src/generate-css.js +1 -1
- package/src/mcp/knowledge.js +4 -4
- package/src/mcp/live.js +21 -13
- package/src/mcp/tools.js +0 -1
- package/src/version.js +3 -7
package/readme.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<meta name="generator" content="bitwrench v2.0
|
|
6
|
+
<meta name="generator" content="bitwrench v2.1.0">
|
|
7
7
|
<title>bitwrench.js - README</title>
|
|
8
8
|
<link rel="icon" type="image/x-icon" href="images/favicon.ico">
|
|
9
9
|
<script src="dist/bitwrench.umd.min.js"></script>
|
|
@@ -69,95 +69,27 @@
|
|
|
69
69
|
<div class="demo-content">
|
|
70
70
|
<div class="readme-body">
|
|
71
71
|
<h1 class="quikdown-h1">bitwrench.js</h1>
|
|
72
|
-
<a class="quikdown-a" href="https://opensource.org/licenses/BSD-2-Clause" rel="noopener noreferrer"
|
|
73
|
-
<a class="quikdown-a" href="https://www.npmjs.com/package/bitwrench" rel="noopener noreferrer"
|
|
74
|
-
<a class="quikdown-a" href="https://github.com/deftio/bitwrench/actions/workflows/ci.yml" rel="noopener noreferrer"
|
|
75
|
-
<a class="quikdown-a" href="https://github.com/deftio/bitwrench" rel="noopener noreferrer"
|
|
72
|
+
<a class="quikdown-a" href="https://opensource.org/licenses/BSD-2-Clause" rel="noopener noreferrer"><img class="quikdown-img" src="https://img.shields.io/badge/License-BSD%202--Clause-blue.svg" alt="License" data-qd-alt="License" data-qd-src="https://img.shields.io/badge/License-BSD%202--Clause-blue.svg" data-qd="!"></a>
|
|
73
|
+
<a class="quikdown-a" href="https://www.npmjs.com/package/bitwrench" rel="noopener noreferrer"><img class="quikdown-img" src="https://img.shields.io/npm/v/bitwrench.svg?style=flat-square" alt="NPM version" data-qd-alt="NPM version" data-qd-src="https://img.shields.io/npm/v/bitwrench.svg?style=flat-square" data-qd="!"></a>
|
|
74
|
+
<a class="quikdown-a" href="https://github.com/deftio/bitwrench/actions/workflows/ci.yml" rel="noopener noreferrer"><img class="quikdown-img" src="https://github.com/deftio/bitwrench/actions/workflows/ci.yml/badge.svg" alt="CI" data-qd-alt="CI" data-qd-src="https://github.com/deftio/bitwrench/actions/workflows/ci.yml/badge.svg" data-qd="!"></a>
|
|
75
|
+
<a class="quikdown-a" href="https://github.com/deftio/bitwrench" rel="noopener noreferrer"><img class="quikdown-img" src="https://img.shields.io/badge/coverage-99.1%25-brightgreen.svg" alt="Coverage" data-qd-alt="Coverage" data-qd-src="https://img.shields.io/badge/coverage-99.1%25-brightgreen.svg" data-qd="!"></a></p><p><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/" rel="noopener noreferrer"><img class="quikdown-img" src="./images/bitwrench-logo-med.png" alt="bitwrench" data-qd-alt="bitwrench" data-qd-src="./images/bitwrench-logo-med.png" data-qd="!"></a></p><p>Bitwrench is a UI library that builds interfaces from plain JavaScript objects -- one format for components, styling, state, and server rendering, with no build step and zero dependencies.</p><pre class="quikdown-pre"><code class="language-javascript">// A "TACO" -- Tag, Attributes, Content, Options
|
|
76
76
|
var page = {
|
|
77
77
|
t: 'div', a: { class: 'card' },
|
|
78
78
|
c: [
|
|
79
79
|
{ t: 'h2', c: 'Hello' },
|
|
80
80
|
{ t: 'p', c: 'UI as native JavaScript objects.' },
|
|
81
|
-
|
|
81
|
+
{ t: 'button', a: { onclick: function() { alert('clicked'); } }, c: 'Click me' }
|
|
82
82
|
]
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
-
bw.
|
|
86
|
-
bw.html(page); // -> HTML string (Node.js, emails, SSR)</code></pre><p>Each object has four keys: <strong class="quikdown-strong">t</strong> (tag), <strong class="quikdown-strong">a</strong> (attributes), <strong class="quikdown-strong">c</strong> (content), <strong class="quikdown-strong">o</strong> (options for state
|
|
87
|
-
<strong class="quikdown-strong">One file, everywhere.</strong> At ~40KB gzipped with zero dependencies, bitwrench runs on anything with a browser -- phones, tablets, Raspberry Pi, even ESP32 microcontrollers. The device serves a single HTML page and pushes data as JSON; bitwrench handles all rendering, styling, and state on the client. No Node.js, no build step, no internet connection required.</p><p>Structure, styling, state, and server rendering are all handled as JavaScript objects:</p><ul class="quikdown-ul">
|
|
88
|
-
<li class="quikdown-li"><strong class="quikdown-strong">No build toolchain</strong> -- works with a <code class="quikdown-code"><script></code> tag</li>
|
|
89
|
-
<li class="quikdown-li"><strong class="quikdown-strong">Ready-made components</strong> -- buttons, tables, modals, forms, charts, toasts -- one <code class="quikdown-code">make*()</code> call each, returns a composable TACO</li>
|
|
90
|
-
<li class="quikdown-li"><strong class="quikdown-strong">CSS from JavaScript</strong> -- <code class="quikdown-code">bw.css()</code> generates stylesheets, <code class="quikdown-code">bw.s()</code> composes inline styles, <code class="quikdown-code">bw.loadStyles()</code> derives a complete design system from 2 seed colors</li>
|
|
91
|
-
<li class="quikdown-li"><strong class="quikdown-strong">Reactive state</strong> -- <code class="quikdown-code">o.state</code> + <code class="quikdown-code">o.render</code> + <code class="quikdown-code">bw.update()</code> for stateful components; <code class="quikdown-code">bw.pub()</code>/<code class="quikdown-code">bw.sub()</code> for cross-component messaging</li>
|
|
92
|
-
<li class="quikdown-li"><strong class="quikdown-strong">Dual rendering</strong> -- same object renders to live DOM (<code class="quikdown-code">bw.DOM()</code>) or HTML string (<code class="quikdown-code">bw.html()</code>) for SSR, emails, or static sites</li>
|
|
93
|
-
<li class="quikdown-li"><strong class="quikdown-strong">Server-driven UI</strong> -- push UI updates from any backend (Python, C, Rust, Go) over SSE via the biwrench bwserve protocol; <code class="quikdown-code">client.screenshot()</code> captures the page back as PNG/JPEG</li>
|
|
94
|
-
<li class="quikdown-li"><strong class="quikdown-strong">CLI</strong> -- <code class="quikdown-code">bwcli</code> converts Markdown, HTML, and JSON to styled standalone pages</li>
|
|
95
|
-
<li class="quikdown-li"><strong class="quikdown-strong">Debug tools</strong> -- live client and server debugging with remote incremental inspect, screenshots, and state updates</li>
|
|
96
|
-
<li class="quikdown-li"><strong class="quikdown-strong">TypeScript</strong> -- full type declarations ship with the package (<code class="quikdown-code">dist/bitwrench.d.ts</code>); see the <a class="quikdown-a" href="docs/bitwrench<em class="quikdown-em">typescript</em>usage.md">TypeScript Usage Guide</a></li>
|
|
97
|
-
<li class="quikdown-li"><strong class="quikdown-strong">Utilities</strong> -- color interpolation, random data, lorem ipsum, cookies, URL params, file I/O</li>
|
|
98
|
-
</ul><h3 class="quikdown-h3">Coming from other Frameworks</h3>
|
|
99
|
-
<p>Bitwrench uses JavaScript equivalents for most forms of front-end development. Here is a quick mapping (see the <a class="quikdown-a" href="docs/README.md">docs</a> and <a class="quikdown-a" href="docs/thinking-in-bitwrench.md">Thinking in Bitwrench</a> for more details).</p><table class="quikdown-table">
|
|
100
|
-
<thead class="quikdown-thead">
|
|
101
|
-
<tr class="quikdown-tr">
|
|
102
|
-
<th class="quikdown-th">You're using</th>
|
|
103
|
-
<th class="quikdown-th">For</th>
|
|
104
|
-
<th class="quikdown-th">Bitwrench equivalent</th>
|
|
105
|
-
</tr>
|
|
106
|
-
</thead>
|
|
107
|
-
<tbody class="quikdown-tbody">
|
|
108
|
-
<tr class="quikdown-tr">
|
|
109
|
-
<td class="quikdown-td">React / Vue / Svelte</td>
|
|
110
|
-
<td class="quikdown-td">Components + reactivity</td>
|
|
111
|
-
<td class="quikdown-td"><code class="quikdown-code">{t, a, c, o}</code> objects + <code class="quikdown-code">o.state</code> + <code class="quikdown-code">o.render</code></td>
|
|
112
|
-
</tr>
|
|
113
|
-
<tr class="quikdown-tr">
|
|
114
|
-
<td class="quikdown-td">JSX / templates</td>
|
|
115
|
-
<td class="quikdown-td">Markup-in-JS</td>
|
|
116
|
-
<td class="quikdown-td">Native JS objects -- no compiler</td>
|
|
117
|
-
</tr>
|
|
118
|
-
<tr class="quikdown-tr">
|
|
119
|
-
<td class="quikdown-td">Tailwind / CSS-in-JS</td>
|
|
120
|
-
<td class="quikdown-td">Styling</td>
|
|
121
|
-
<td class="quikdown-td"><code class="quikdown-code">bw.css()</code>, <code class="quikdown-code">bw.s()</code> style composition</td>
|
|
122
|
-
</tr>
|
|
123
|
-
<tr class="quikdown-tr">
|
|
124
|
-
<td class="quikdown-td">Sass / PostCSS</td>
|
|
125
|
-
<td class="quikdown-td">CSS generation</td>
|
|
126
|
-
<td class="quikdown-td"><code class="quikdown-code">bw.css()</code> from JS objects (supports @media, @keyframes)</td>
|
|
127
|
-
</tr>
|
|
128
|
-
<tr class="quikdown-tr">
|
|
129
|
-
<td class="quikdown-td">ThemeProvider / CSS vars</td>
|
|
130
|
-
<td class="quikdown-td">Theming</td>
|
|
131
|
-
<td class="quikdown-td"><code class="quikdown-code">bw.loadStyles()</code> / <code class="quikdown-code">bw.makeStyles()</code> from 2 seed colors</td>
|
|
132
|
-
</tr>
|
|
133
|
-
<tr class="quikdown-tr">
|
|
134
|
-
<td class="quikdown-td">Streamlit / Gradio</td>
|
|
135
|
-
<td class="quikdown-td">Server-driven UI</td>
|
|
136
|
-
<td class="quikdown-td">bwserve SSE -- from any language (Python, Go, C, Rust)</td>
|
|
137
|
-
</tr>
|
|
138
|
-
<tr class="quikdown-tr">
|
|
139
|
-
<td class="quikdown-td">Redux / Zustand / Pinia</td>
|
|
140
|
-
<td class="quikdown-td">State management</td>
|
|
141
|
-
<td class="quikdown-td"><code class="quikdown-code">o.state</code> + <code class="quikdown-code">bw.update()</code> + <code class="quikdown-code">bw.pub()/sub()</code></td>
|
|
142
|
-
</tr>
|
|
143
|
-
<tr class="quikdown-tr">
|
|
144
|
-
<td class="quikdown-td">Vite / webpack / Babel</td>
|
|
145
|
-
<td class="quikdown-td">Build tooling</td>
|
|
146
|
-
<td class="quikdown-td">Not needed -- open the HTML file</td>
|
|
147
|
-
</tr>
|
|
148
|
-
<tr class="quikdown-tr">
|
|
149
|
-
<td class="quikdown-td">DefinitelyTyped / @types</td>
|
|
150
|
-
<td class="quikdown-td">Type declarations</td>
|
|
151
|
-
<td class="quikdown-td">Ships <code class="quikdown-code">dist/bitwrench.d.ts</code> -- nothing extra to install</td>
|
|
152
|
-
</tr>
|
|
153
|
-
</tbody>
|
|
154
|
-
</table><p>See the <a class="quikdown-a" href="docs/framework-translation-table.md">Framework Translation Table</a> for side-by-side code comparisons across 22 operations.</p><h2 class="quikdown-h2">Installation</h2>
|
|
85
|
+
bw.mount('#app', page); // -> live DOM
|
|
86
|
+
bw.html(page); // -> HTML string (Node.js, emails, SSR)</code></pre><p>Each object has four keys: <strong class="quikdown-strong">t</strong> (tag), <strong class="quikdown-strong">a</strong> (attributes, including event handlers like <code class="quikdown-code">onclick</code>), <strong class="quikdown-strong">c</strong> (content -- a string, array, or nested TACO), and <strong class="quikdown-strong">o</strong> (options for state and lifecycle). Nest them, loop them, build them with functions -- they are ordinary JavaScript values.</p><p>A TACO is already a JavaScript object, so there is nothing to compile or transform. This makes bitwrench a good fit for situations where a build pipeline costs more than it buys: dashboards, internal tools, embedded device UIs, server-driven pages, or anything you want to ship as a single HTML file.</p><h2 class="quikdown-h2">Installation</h2>
|
|
155
87
|
<p><pre class="quikdown-pre"><code class="language-bash">npm install bitwrench</code></pre></p><pre class="quikdown-pre"><code class="language-javascript">// ES module
|
|
156
88
|
import bw from 'bitwrench';
|
|
157
89
|
|
|
158
90
|
// CommonJS
|
|
159
91
|
const bw = require('bitwrench');</code></pre><p>Or include directly in a page:</p><pre class="quikdown-pre"><code class="language-html"><script src="https://cdn.jsdelivr.net/npm/bitwrench/dist/bitwrench.umd.min.js"></script></code></pre><h2 class="quikdown-h2">Getting Started</h2>
|
|
160
|
-
<p><pre class="quikdown-pre"><code class="language-html"><!DOCTYPE html>
|
|
92
|
+
<p>A complete page -- no build step, no imports, everything is a plain object:</p><pre class="quikdown-pre"><code class="language-html"><!DOCTYPE html>
|
|
161
93
|
<html lang="en">
|
|
162
94
|
<head>
|
|
163
95
|
<script src="https://cdn.jsdelivr.net/npm/bitwrench/dist/bitwrench.umd.min.js"></script>
|
|
@@ -165,38 +97,44 @@ const bw = require('bitwrench');</code></pre><p>Or include directly in a
|
|
|
165
97
|
<body>
|
|
166
98
|
<div id="app"></div>
|
|
167
99
|
<script>
|
|
168
|
-
bw.loadStyles();
|
|
100
|
+
bw.loadStyles(); // structural CSS + design tokens
|
|
169
101
|
|
|
170
|
-
bw.
|
|
171
|
-
t: 'div', a: { class: '
|
|
102
|
+
bw.mount('#app', {
|
|
103
|
+
t: 'div', a: { class: 'bw_container' },
|
|
172
104
|
c: [
|
|
173
105
|
{ t: 'h1', c: 'My App' },
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
bw.makeButton({
|
|
179
|
-
text: 'Click me',
|
|
180
|
-
variant: 'primary',
|
|
181
|
-
onclick: function() { alert('Hello!'); }
|
|
182
|
-
})
|
|
106
|
+
{ t: 'p', c: 'Built from plain JavaScript objects.' },
|
|
107
|
+
{ t: 'button',
|
|
108
|
+
a: { class: 'bw_btn bw_primary', onclick: function() { alert('Hello!'); } },
|
|
109
|
+
c: 'Click me' }
|
|
183
110
|
]
|
|
184
111
|
});
|
|
185
112
|
</script>
|
|
186
113
|
</body>
|
|
187
|
-
</html></code></pre
|
|
188
|
-
<p>
|
|
114
|
+
</html></code></pre><h2 class="quikdown-h2">Components</h2>
|
|
115
|
+
<p>A component is a function that returns a TACO. Bitwrench ships ~50 factory functions (<code class="quikdown-code">bw.makeCard()</code>, <code class="quikdown-code">bw.makeTable()</code>, <code class="quikdown-code">bw.makeTabs()</code>, etc. -- see the <a class="quikdown-a" href="docs/component-cheatsheet.md">Component Cheat Sheet</a>). Each is a regular function that returns the same <code class="quikdown-code">{t, a, c, o}</code> object you could write by hand. Log the return value and look at it.</p><p>Your own components work the same way:</p><pre class="quikdown-pre"><code class="language-javascript">function statusChip(label, ok) {
|
|
116
|
+
return { t: 'span', a: { class: 'bw_badge ' + (ok ? 'bw_success' : 'bw_warning') }, c: label };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Built-in and custom components compose identically
|
|
120
|
+
bw.mount('#app', {
|
|
121
|
+
t: 'div', a: { class: 'bw_container' },
|
|
122
|
+
c: [
|
|
123
|
+
bw.makeCard({ title: 'Server', content: 'Build 2.1.0' }),
|
|
124
|
+
statusChip('online', true)
|
|
125
|
+
]
|
|
126
|
+
});</code></pre><h2 class="quikdown-h2">State and Updates</h2>
|
|
127
|
+
<p>Add <code class="quikdown-code">o.state</code> and <code class="quikdown-code">o.render</code> to any TACO to make it stateful. The render function receives <code class="quikdown-code">(el, state)</code>, and you call <code class="quikdown-code">bw.refresh(el)</code> when you want it to re-run:</p><pre class="quikdown-pre"><code class="language-javascript">var counter = {
|
|
189
128
|
t: 'div',
|
|
190
129
|
o: {
|
|
191
130
|
state: { count: 0 },
|
|
192
|
-
render: function(el) {
|
|
193
|
-
|
|
194
|
-
bw.DOM(el, {
|
|
131
|
+
render: function(el, state) {
|
|
132
|
+
bw.mount(el, {
|
|
195
133
|
t: 'div', c: [
|
|
196
|
-
{ t: 'h3', c: 'Count: ' +
|
|
134
|
+
{ t: 'h3', c: 'Count: ' + state.count },
|
|
197
135
|
bw.makeButton({ text: '+1', onclick: function() {
|
|
198
|
-
|
|
199
|
-
bw.
|
|
136
|
+
state.count++;
|
|
137
|
+
bw.refresh(el);
|
|
200
138
|
}})
|
|
201
139
|
]
|
|
202
140
|
});
|
|
@@ -204,35 +142,184 @@ const bw = require('bitwrench');</code></pre><p>Or include directly in a
|
|
|
204
142
|
}
|
|
205
143
|
};
|
|
206
144
|
|
|
207
|
-
bw.
|
|
208
|
-
|
|
145
|
+
bw.mount('#app', counter);</code></pre><p>State is also available as <code class="quikdown-code">el._bw_state</code> from outside the render function -- useful for debugging or direct access from event handlers.</p><blockquote class="quikdown-blockquote">Event handlers go in <code class="quikdown-code">a: { onclick: fn }</code>, not in <code class="quikdown-code">o.mounted</code>. Handlers attached via <code class="quikdown-code">addEventListener</code> in <code class="quikdown-code">o.mounted</code> are lost when a component re-renders. Place them in <code class="quikdown-code">a:</code> and bitwrench re-attaches them on every render.</blockquote><p>Bitwrench has no reactivity system. Mutating state does not trigger anything -- the DOM changes only when you call an update function. This is a deliberate trade: you give up automatic re-renders, and in exchange every DOM mutation is a function call you wrote, with a cost you chose.</p><p>The update functions form a cost ladder:</p><table class="quikdown-table">
|
|
146
|
+
<thead class="quikdown-thead">
|
|
147
|
+
<tr class="quikdown-tr">
|
|
148
|
+
<th class="quikdown-th">Update verb</th>
|
|
149
|
+
<th class="quikdown-th">Cost</th>
|
|
150
|
+
<th class="quikdown-th">What happens</th>
|
|
151
|
+
</tr>
|
|
152
|
+
</thead>
|
|
153
|
+
<tbody class="quikdown-tbody">
|
|
154
|
+
<tr class="quikdown-tr">
|
|
155
|
+
<td class="quikdown-td"><code class="quikdown-code">el.bw.method()</code> / slot setters</td>
|
|
156
|
+
<td class="quikdown-td">Surgical</td>
|
|
157
|
+
<td class="quikdown-td">Component updates its own DOM directly</td>
|
|
158
|
+
</tr>
|
|
159
|
+
<tr class="quikdown-tr">
|
|
160
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.update(ref, data)</code></td>
|
|
161
|
+
<td class="quikdown-td">Dispatch</td>
|
|
162
|
+
<td class="quikdown-td">Calls <code class="quikdown-code">el.bw.update(data)</code> -- never rebuilds</td>
|
|
163
|
+
</tr>
|
|
164
|
+
<tr class="quikdown-tr">
|
|
165
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.message(ref, action, data)</code></td>
|
|
166
|
+
<td class="quikdown-td">Dispatch</td>
|
|
167
|
+
<td class="quikdown-td">Calls <code class="quikdown-code">el.bw[action]()</code> by selector or UUID</td>
|
|
168
|
+
</tr>
|
|
169
|
+
<tr class="quikdown-tr">
|
|
170
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.patch(id, content)</code></td>
|
|
171
|
+
<td class="quikdown-td">Targeted</td>
|
|
172
|
+
<td class="quikdown-td">Replaces one element's content</td>
|
|
173
|
+
</tr>
|
|
174
|
+
<tr class="quikdown-tr">
|
|
175
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.refresh(ref)</code></td>
|
|
176
|
+
<td class="quikdown-td">Full rebuild</td>
|
|
177
|
+
<td class="quikdown-td">Re-runs <code class="quikdown-code">o.render</code>; children are unmounted and rebuilt</td>
|
|
178
|
+
</tr>
|
|
179
|
+
</tbody>
|
|
180
|
+
</table><p>Choosing where you sit on this ladder is the programming model. The full <code class="quikdown-code">bw.refresh()</code> re-render shown above is the simplest but most expensive option. The next section introduces slots and handles, which sit at the top of the ladder.</p><h2 class="quikdown-h2">Component API</h2>
|
|
181
|
+
<p>After mounting, the DOM element is the component. The TACO is consumed at mount time -- there is no virtual DOM and no retained tree. State lives on the element (<code class="quikdown-code">el._bw_state</code>), and so does its public API (<code class="quikdown-code">el.bw</code>).</p><p><strong class="quikdown-strong">Slots</strong> map CSS selectors to setter/getter pairs. <strong class="quikdown-strong">Handles</strong> define named methods. Both are attached to <code class="quikdown-code">el.bw</code> at mount time:</p><pre class="quikdown-pre"><code class="language-javascript">var card = bw.mount('#stats', {
|
|
182
|
+
t: 'div', a: { class: 'stats-card' },
|
|
183
|
+
c: [
|
|
184
|
+
{ t: 'h3', a: { class: 'card-title' }, c: 'Revenue' },
|
|
185
|
+
{ t: 'span', a: { class: 'card-value' }, c: '$50,000' }
|
|
186
|
+
],
|
|
187
|
+
o: {
|
|
188
|
+
slots: { title: '.card-title', value: '.card-value' },
|
|
189
|
+
handle: {
|
|
190
|
+
update: function(el, data) { el.bw.setValue('§CB7§#39; + data.value.toLocaleString()); }
|
|
191
|
+
}
|
|
192
|
+
}
|
|
209
193
|
});
|
|
210
194
|
|
|
195
|
+
card.bw.setTitle('Profit'); // slot setter -- updates one text node
|
|
196
|
+
card.bw.update({ value: 120000 }); // handle method -- runs your logic
|
|
197
|
+
bw.update(card, { value: 99000 }); // same call, dispatched by element or UUID</code></pre><p><code class="quikdown-code">slots: { title: '.card-title' }</code> generates <code class="quikdown-code">el.bw.setTitle()</code> and <code class="quikdown-code">el.bw.getTitle()</code> automatically. <code class="quikdown-code">handle</code> methods are attached as-is to <code class="quikdown-code">el.bw</code>. Neither causes a re-render -- they update the DOM directly.</p><p>Because everything lives on the element, debugging needs no extension: select a component in the browser's Elements panel and type <code class="quikdown-code">$0._bw_state</code> or <code class="quikdown-code">$0.bw</code>.</p><p>A component's lifecycle is four explicit calls:</p><table class="quikdown-table">
|
|
198
|
+
<thead class="quikdown-thead">
|
|
199
|
+
<tr class="quikdown-tr">
|
|
200
|
+
<th class="quikdown-th">Phase</th>
|
|
201
|
+
<th class="quikdown-th">You call</th>
|
|
202
|
+
<th class="quikdown-th">Opt-in hook</th>
|
|
203
|
+
</tr>
|
|
204
|
+
</thead>
|
|
205
|
+
<tbody class="quikdown-tbody">
|
|
206
|
+
<tr class="quikdown-tr">
|
|
207
|
+
<td class="quikdown-td">Define</td>
|
|
208
|
+
<td class="quikdown-td">a function that returns a TACO</td>
|
|
209
|
+
<td class="quikdown-td">--</td>
|
|
210
|
+
</tr>
|
|
211
|
+
<tr class="quikdown-tr">
|
|
212
|
+
<td class="quikdown-td">Mount</td>
|
|
213
|
+
<td class="quikdown-td">bw.mount('#app', taco)</td>
|
|
214
|
+
<td class="quikdown-td">o.mounted(el)</td>
|
|
215
|
+
</tr>
|
|
216
|
+
<tr class="quikdown-tr">
|
|
217
|
+
<td class="quikdown-td">Update</td>
|
|
218
|
+
<td class="quikdown-td">el.bw.method() / bw.refresh(el)</td>
|
|
219
|
+
<td class="quikdown-td">--</td>
|
|
220
|
+
</tr>
|
|
221
|
+
<tr class="quikdown-tr">
|
|
222
|
+
<td class="quikdown-td">Unmount</td>
|
|
223
|
+
<td class="quikdown-td">bw.remove(el)</td>
|
|
224
|
+
<td class="quikdown-td">o.unmount(el)</td>
|
|
225
|
+
</tr>
|
|
226
|
+
</tbody>
|
|
227
|
+
</table><p>The <a class="quikdown-a" href="docs/component-lifecycle.md">Component Lifecycle Walkthrough</a> takes one card through all four phases. The <a class="quikdown-a" href="docs/state-management.md">State Management guide</a> covers the full component model.</p><h2 class="quikdown-h2">Cross-Component Communication</h2>
|
|
228
|
+
<p>Components communicate through pub/sub. <code class="quikdown-code">bw.sub()</code> returns an unsubscribe function. Wildcard topics match any suffix after the colon:</p><pre class="quikdown-pre"><code class="language-javascript">bw.sub('item-added', function(detail) { console.log('New:', detail.name); });
|
|
211
229
|
bw.pub('item-added', { name: 'Widget' });
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
bw.
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
<p><code class="quikdown-code">bw.css()</code> generates CSS from objects. <code class="quikdown-code">bw.s()</code> composes inline styles from reusable utility objects:</p><pre class="quikdown-pre"><code class="language-javascript">// Generate and inject a stylesheet
|
|
230
|
+
bw.sub('item:*', function(detail, topic) { /* matches item:added, item:removed, etc. */ });</code></pre><p>Pass an element as the third argument to tie the subscription's lifetime to that element -- when the element is removed from the DOM, the subscription is automatically cleaned up:</p><pre class="quikdown-pre"><code class="language-javascript">bw.sub('cart:updated', function(data) {
|
|
231
|
+
el._bw_state.count = data.count;
|
|
232
|
+
bw.refresh(el);
|
|
233
|
+
}, el);</code></pre><h2 class="quikdown-h2">CSS from JavaScript</h2>
|
|
234
|
+
<p><code class="quikdown-code">bw.css()</code> generates CSS strings from objects. <code class="quikdown-code">bw.injectCSS()</code> inserts a CSS string into the document as a <code class="quikdown-code"><style></code> tag. <code class="quikdown-code">bw.s()</code> composes inline styles. <code class="quikdown-code">bw.responsive()</code> generates <code class="quikdown-code">@media</code> rules from a breakpoint map. These are generation functions -- they return strings, so you can use them anywhere:</p><pre class="quikdown-pre"><code class="language-javascript">// Generate and inject a stylesheet
|
|
218
235
|
bw.injectCSS(bw.css({
|
|
219
236
|
'.my-card': { padding: '1rem', borderRadius: '8px' }
|
|
220
237
|
}));
|
|
221
238
|
|
|
222
|
-
// Compose inline styles from objects
|
|
239
|
+
// Compose inline styles from reusable objects
|
|
223
240
|
{ t: 'div', a: { style: bw.s({ display: 'flex' }, { gap: '1rem' }, { padding: '1rem' }) } }
|
|
224
241
|
|
|
225
242
|
// Responsive breakpoints
|
|
226
243
|
bw.responsive('.hero', {
|
|
227
244
|
base: { fontSize: '1.5rem' },
|
|
228
245
|
md: { fontSize: '2.5rem' }
|
|
229
|
-
});</code></pre><h2 class="quikdown-h2">Theming</h2>
|
|
230
|
-
<p><code class="quikdown-code">bw.loadStyles()</code> derives a complete design system -- buttons, alerts, badges, cards, forms, tables, hover states, focus rings -- from two seed colors.
|
|
246
|
+
});</code></pre><p>Bitwrench does not own your CSS. You can use external stylesheets, Tailwind, or plain CSS alongside any of the above.</p><h2 class="quikdown-h2">Theming</h2>
|
|
247
|
+
<p><code class="quikdown-code">bw.loadStyles()</code> derives a complete design system -- buttons, alerts, badges, cards, forms, tables, hover states, focus rings -- from two seed colors. Call it with no arguments for structural CSS only, or pass a config to generate a full theme. <code class="quikdown-code">bw.toggleThemeMode()</code> switches between primary and alternate palettes:</p><pre class="quikdown-pre"><code class="language-javascript">bw.loadStyles({
|
|
231
248
|
primary: '#336699',
|
|
232
249
|
secondary: '#cc6633'
|
|
233
250
|
});
|
|
234
251
|
|
|
235
|
-
bw.
|
|
252
|
+
bw.toggleThemeMode(); // switch to alternate palette</code></pre><p>Styles can be scoped to DOM subtrees, so different parts of a page can use different themes. See the <a class="quikdown-a" href="docs/theming.md">Theming guide</a> for presets, palette structure, and scoping.</p><h2 class="quikdown-h2">Server-Driven UI</h2>
|
|
253
|
+
<p>Because TACOs are plain objects, they serialize as JSON. This means a backend in any language can push UI updates to the browser.</p><p>Bitwrench includes bwserve, a protocol that sends TACO objects and patches over SSE. Button clicks come back as actions, <code class="quikdown-code">client.inspect()</code> reads DOM state, and <code class="quikdown-code">client.screenshot()</code> captures the live page as a PNG. The browser becomes a display and input device; the application logic lives wherever you want it.</p><p>Here is a C program on an ESP32 pushing a sensor reading to the browser:</p><pre class="quikdown-pre"><code class="language-c">char msg[96], frame[128];
|
|
254
|
+
BW_PATCH(msg, "office-temp", "23.5");
|
|
255
|
+
BW_SSE_FRAME(frame, msg);
|
|
256
|
+
events.send(frame, NULL, millis()); // the browser updates</code></pre><p>The same protocol works from Python, Go, Rust, or a shell script with <code class="quikdown-code">curl</code>. See the <a class="quikdown-a" href="docs/bwserve.md">bwserve docs</a> for the full protocol, and the <a class="quikdown-a" href="docs/tutorial-embedded.md">ESP32 tutorial</a> for a complete embedded walkthrough.</p><p>The library is ~165KB on disk (~45KB gzipped). A lean build without the component library (BCCL) is ~128KB (~35KB gzipped). Both work entirely self-hosted from a microcontroller's flash -- no CDN and no internet required.</p><h2 class="quikdown-h2">CLI</h2>
|
|
257
|
+
<p><code class="quikdown-code">bwcli</code> converts files to styled standalone pages:</p><pre class="quikdown-pre"><code class="language-bash"># Convert Markdown to a self-contained HTML page
|
|
258
|
+
bwcli README.md -o index.html --standalone
|
|
259
|
+
|
|
260
|
+
# Apply a theme preset
|
|
261
|
+
bwcli doc.md -o doc.html --standalone --theme ocean
|
|
262
|
+
|
|
263
|
+
# Custom colors
|
|
264
|
+
bwcli doc.md -o doc.html --standalone --theme "#336699,#cc6633"</code></pre><p>Flags: <code class="quikdown-code">--output/-o</code>, <code class="quikdown-code">--standalone/-s</code>, <code class="quikdown-code">--cdn</code>, <code class="quikdown-code">--theme/-t</code>, <code class="quikdown-code">--css/-c</code>, <code class="quikdown-code">--title</code>, <code class="quikdown-code">--favicon/-f</code>, <code class="quikdown-code">--highlight</code>, <code class="quikdown-code">--verbose/-v</code></p><h3 class="quikdown-h3">Pipe Server</h3>
|
|
265
|
+
<p><code class="quikdown-code">bwcli serve</code> turns any language into a bwserve backend -- send JSON protocol messages via HTTP POST or stdin, and connected browsers update in real time:</p><pre class="quikdown-pre"><code class="language-bash">bwcli serve --port 8080 --input-port 9000
|
|
266
|
+
curl -X POST http://localhost:9000 -d '{"type":"patch","ref":"temp","content":"23.5 C"}'</code></pre><h2 class="quikdown-h2">Coming from Other Frameworks</h2>
|
|
267
|
+
<table class="quikdown-table">
|
|
268
|
+
<thead class="quikdown-thead">
|
|
269
|
+
<tr class="quikdown-tr">
|
|
270
|
+
<th class="quikdown-th">You're using</th>
|
|
271
|
+
<th class="quikdown-th">For</th>
|
|
272
|
+
<th class="quikdown-th">Bitwrench equivalent</th>
|
|
273
|
+
</tr>
|
|
274
|
+
</thead>
|
|
275
|
+
<tbody class="quikdown-tbody">
|
|
276
|
+
<tr class="quikdown-tr">
|
|
277
|
+
<td class="quikdown-td">React / Vue / Svelte</td>
|
|
278
|
+
<td class="quikdown-td">Components</td>
|
|
279
|
+
<td class="quikdown-td">{t, a, c, o} objects + o.state + o.render</td>
|
|
280
|
+
</tr>
|
|
281
|
+
<tr class="quikdown-tr">
|
|
282
|
+
<td class="quikdown-td">JSX / templates</td>
|
|
283
|
+
<td class="quikdown-td">Markup-in-JS</td>
|
|
284
|
+
<td class="quikdown-td">Native JS objects -- no compiler</td>
|
|
285
|
+
</tr>
|
|
286
|
+
<tr class="quikdown-tr">
|
|
287
|
+
<td class="quikdown-td">Tailwind / CSS-in-JS</td>
|
|
288
|
+
<td class="quikdown-td">Styling</td>
|
|
289
|
+
<td class="quikdown-td">bw.css(), bw.s()</td>
|
|
290
|
+
</tr>
|
|
291
|
+
<tr class="quikdown-tr">
|
|
292
|
+
<td class="quikdown-td">Sass / PostCSS</td>
|
|
293
|
+
<td class="quikdown-td">CSS generation</td>
|
|
294
|
+
<td class="quikdown-td">bw.css() from JS objects (supports @media, @keyframes)</td>
|
|
295
|
+
</tr>
|
|
296
|
+
<tr class="quikdown-tr">
|
|
297
|
+
<td class="quikdown-td">ThemeProvider / CSS vars</td>
|
|
298
|
+
<td class="quikdown-td">Theming</td>
|
|
299
|
+
<td class="quikdown-td">bw.loadStyles() / bw.makeStyles() from seed colors</td>
|
|
300
|
+
</tr>
|
|
301
|
+
<tr class="quikdown-tr">
|
|
302
|
+
<td class="quikdown-td">Streamlit / Gradio</td>
|
|
303
|
+
<td class="quikdown-td">Server-driven UI</td>
|
|
304
|
+
<td class="quikdown-td">bwserve SSE -- from any language</td>
|
|
305
|
+
</tr>
|
|
306
|
+
<tr class="quikdown-tr">
|
|
307
|
+
<td class="quikdown-td">Redux / Zustand / Pinia</td>
|
|
308
|
+
<td class="quikdown-td">State management</td>
|
|
309
|
+
<td class="quikdown-td">o.state + bw.refresh() + bw.pub()/sub()</td>
|
|
310
|
+
</tr>
|
|
311
|
+
<tr class="quikdown-tr">
|
|
312
|
+
<td class="quikdown-td">Vite / webpack / Babel</td>
|
|
313
|
+
<td class="quikdown-td">Build tooling</td>
|
|
314
|
+
<td class="quikdown-td">Not needed -- open the HTML file</td>
|
|
315
|
+
</tr>
|
|
316
|
+
<tr class="quikdown-tr">
|
|
317
|
+
<td class="quikdown-td">DefinitelyTyped / @types</td>
|
|
318
|
+
<td class="quikdown-td">Type declarations</td>
|
|
319
|
+
<td class="quikdown-td">Ships dist/bitwrench.d.ts</td>
|
|
320
|
+
</tr>
|
|
321
|
+
</tbody>
|
|
322
|
+
</table><p>See the <a class="quikdown-a" href="docs/framework-translation-table.md">Framework Translation Table</a> for side-by-side code comparisons across 22 operations.</p><h2 class="quikdown-h2">Core API</h2>
|
|
236
323
|
<table class="quikdown-table">
|
|
237
324
|
<thead class="quikdown-thead">
|
|
238
325
|
<tr class="quikdown-tr">
|
|
@@ -242,97 +329,111 @@ bw.toggleStyles(); // switch between primary and alternate palettes</code></pre
|
|
|
242
329
|
</thead>
|
|
243
330
|
<tbody class="quikdown-tbody">
|
|
244
331
|
<tr class="quikdown-tr">
|
|
245
|
-
<td class="quikdown-td"
|
|
332
|
+
<td class="quikdown-td">bw.html(obj)</td>
|
|
246
333
|
<td class="quikdown-td">Convert a TACO to an HTML string</td>
|
|
247
334
|
</tr>
|
|
248
335
|
<tr class="quikdown-tr">
|
|
249
|
-
<td class="quikdown-td"
|
|
250
|
-
<td class="quikdown-td">Mount a TACO
|
|
336
|
+
<td class="quikdown-td">bw.mount(selector, obj)</td>
|
|
337
|
+
<td class="quikdown-td">Mount a TACO into a DOM element; returns the root element</td>
|
|
338
|
+
</tr>
|
|
339
|
+
<tr class="quikdown-tr">
|
|
340
|
+
<td class="quikdown-td">bw.DOM(selector, obj)</td>
|
|
341
|
+
<td class="quikdown-td">Alias of bw.mount()</td>
|
|
342
|
+
</tr>
|
|
343
|
+
<tr class="quikdown-tr">
|
|
344
|
+
<td class="quikdown-td">bw.create(taco)</td>
|
|
345
|
+
<td class="quikdown-td">Create a detached DOM element from a TACO (not inserted into the page)</td>
|
|
346
|
+
</tr>
|
|
347
|
+
<tr class="quikdown-tr">
|
|
348
|
+
<td class="quikdown-td">bw.el(selector, apply?)</td>
|
|
349
|
+
<td class="quikdown-td">Find an element; optionally apply text, TACO, or function to it</td>
|
|
251
350
|
</tr>
|
|
252
351
|
<tr class="quikdown-tr">
|
|
253
|
-
<td class="quikdown-td"
|
|
254
|
-
<td class="quikdown-td">
|
|
352
|
+
<td class="quikdown-td">bw.$(selector)</td>
|
|
353
|
+
<td class="quikdown-td">querySelectorAll as an array</td>
|
|
255
354
|
</tr>
|
|
256
355
|
<tr class="quikdown-tr">
|
|
257
|
-
<td class="quikdown-td"
|
|
356
|
+
<td class="quikdown-td">bw.raw(str)</td>
|
|
258
357
|
<td class="quikdown-td">Mark a string as pre-escaped HTML (no double-escaping)</td>
|
|
259
358
|
</tr>
|
|
260
359
|
<tr class="quikdown-tr">
|
|
261
|
-
<td class="quikdown-td"
|
|
360
|
+
<td class="quikdown-td">bw.css(rules)</td>
|
|
262
361
|
<td class="quikdown-td">Generate CSS from a JS object</td>
|
|
263
362
|
</tr>
|
|
264
363
|
<tr class="quikdown-tr">
|
|
265
|
-
<td class="quikdown-td"
|
|
364
|
+
<td class="quikdown-td">bw.injectCSS(css, opts?)</td>
|
|
365
|
+
<td class="quikdown-td">Insert a CSS string into the document as a style tag</td>
|
|
366
|
+
</tr>
|
|
367
|
+
<tr class="quikdown-tr">
|
|
368
|
+
<td class="quikdown-td">bw.s(...objs)</td>
|
|
266
369
|
<td class="quikdown-td">Compose inline style objects into a style string</td>
|
|
267
370
|
</tr>
|
|
268
371
|
<tr class="quikdown-tr">
|
|
269
|
-
<td class="quikdown-td"
|
|
270
|
-
<td class="quikdown-td">Generate
|
|
372
|
+
<td class="quikdown-td">bw.responsive(sel, breakpoints)</td>
|
|
373
|
+
<td class="quikdown-td">Generate @media CSS rules from a breakpoint map</td>
|
|
271
374
|
</tr>
|
|
272
375
|
<tr class="quikdown-tr">
|
|
273
|
-
<td class="quikdown-td"
|
|
274
|
-
<td class="quikdown-td">
|
|
376
|
+
<td class="quikdown-td">bw.loadStyles(config?)</td>
|
|
377
|
+
<td class="quikdown-td">Structural CSS (no args) or generate + apply a theme from seed colors</td>
|
|
275
378
|
</tr>
|
|
276
379
|
<tr class="quikdown-tr">
|
|
277
|
-
<td class="quikdown-td"
|
|
380
|
+
<td class="quikdown-td">bw.makeStyles(config)</td>
|
|
278
381
|
<td class="quikdown-td">Generate a theme from seed colors (returns styles object)</td>
|
|
279
382
|
</tr>
|
|
280
383
|
<tr class="quikdown-tr">
|
|
281
|
-
<td class="quikdown-td"
|
|
282
|
-
<td class="quikdown-td">Inject a generated styles object
|
|
384
|
+
<td class="quikdown-td">bw.applyStyles(styles)</td>
|
|
385
|
+
<td class="quikdown-td">Inject a generated styles object into the document</td>
|
|
283
386
|
</tr>
|
|
284
387
|
<tr class="quikdown-tr">
|
|
285
|
-
<td class="quikdown-td"
|
|
388
|
+
<td class="quikdown-td">bw.toggleThemeMode(scope?)</td>
|
|
286
389
|
<td class="quikdown-td">Switch between primary and alternate palettes</td>
|
|
287
390
|
</tr>
|
|
288
391
|
<tr class="quikdown-tr">
|
|
289
|
-
<td class="quikdown-td"
|
|
392
|
+
<td class="quikdown-td">bw.clearStyles()</td>
|
|
290
393
|
<td class="quikdown-td">Remove injected theme styles</td>
|
|
291
394
|
</tr>
|
|
292
395
|
<tr class="quikdown-tr">
|
|
293
|
-
<td class="quikdown-td"
|
|
396
|
+
<td class="quikdown-td">bw.patch(id, content)</td>
|
|
294
397
|
<td class="quikdown-td">Update a specific element by id or UUID</td>
|
|
295
398
|
</tr>
|
|
296
399
|
<tr class="quikdown-tr">
|
|
297
|
-
<td class="quikdown-td"
|
|
298
|
-
<td class="quikdown-td">Re-render
|
|
400
|
+
<td class="quikdown-td">bw.refresh(el)</td>
|
|
401
|
+
<td class="quikdown-td">Re-render a stateful component via its o.render function</td>
|
|
402
|
+
</tr>
|
|
403
|
+
<tr class="quikdown-tr">
|
|
404
|
+
<td class="quikdown-td">bw.update(el, data)</td>
|
|
405
|
+
<td class="quikdown-td">Dispatch to el.bw.update(data)</td>
|
|
299
406
|
</tr>
|
|
300
407
|
<tr class="quikdown-tr">
|
|
301
|
-
<td class="quikdown-td"
|
|
302
|
-
<td class="quikdown-td">Dispatch
|
|
408
|
+
<td class="quikdown-td">bw.message(target, action, data)</td>
|
|
409
|
+
<td class="quikdown-td">Dispatch to el.bw[action]() by selector or UUID</td>
|
|
303
410
|
</tr>
|
|
304
411
|
<tr class="quikdown-tr">
|
|
305
|
-
<td class="quikdown-td"
|
|
412
|
+
<td class="quikdown-td">bw.pub(topic, detail)</td>
|
|
306
413
|
<td class="quikdown-td">Publish to subscribers (exact + wildcard matches)</td>
|
|
307
414
|
</tr>
|
|
308
415
|
<tr class="quikdown-tr">
|
|
309
|
-
<td class="quikdown-td"
|
|
310
|
-
<td class="quikdown-td">Subscribe to topic (supports wildcard
|
|
416
|
+
<td class="quikdown-td">bw.sub(topic, handler, el?)</td>
|
|
417
|
+
<td class="quikdown-td">Subscribe to a topic (supports wildcard 'ns:*'); returns unsub function</td>
|
|
311
418
|
</tr>
|
|
312
419
|
<tr class="quikdown-tr">
|
|
313
|
-
<td class="quikdown-td"
|
|
420
|
+
<td class="quikdown-td">bw.once(topic, handler, el?)</td>
|
|
314
421
|
<td class="quikdown-td">One-shot subscribe; auto-unsub after first fire</td>
|
|
315
422
|
</tr>
|
|
316
423
|
<tr class="quikdown-tr">
|
|
317
|
-
<td class="quikdown-td"
|
|
318
|
-
<td class="quikdown-td">
|
|
424
|
+
<td class="quikdown-td">bw.remove(el)</td>
|
|
425
|
+
<td class="quikdown-td">Unmount a component (fires o.unmount hook)</td>
|
|
319
426
|
</tr>
|
|
320
427
|
<tr class="quikdown-tr">
|
|
321
|
-
<td class="quikdown-td"
|
|
428
|
+
<td class="quikdown-td">bw.inspect(target, depth)</td>
|
|
429
|
+
<td class="quikdown-td">Introspect a DOM subtree with bitwrench metadata</td>
|
|
430
|
+
</tr>
|
|
431
|
+
<tr class="quikdown-tr">
|
|
432
|
+
<td class="quikdown-td">bw.apply(msg)</td>
|
|
322
433
|
<td class="quikdown-td">Apply a bwserve protocol message to the DOM</td>
|
|
323
434
|
</tr>
|
|
324
435
|
</tbody>
|
|
325
|
-
</table><p>
|
|
326
|
-
<p>Convert Markdown, HTML, or JSON files to styled standalone pages:</p><pre class="quikdown-pre"><code class="language-bash"># Convert Markdown to a self-contained HTML page
|
|
327
|
-
bwcli README.md -o index.html --standalone
|
|
328
|
-
|
|
329
|
-
# Apply a theme preset
|
|
330
|
-
bwcli doc.md -o doc.html --standalone --theme ocean
|
|
331
|
-
|
|
332
|
-
# Custom colors
|
|
333
|
-
bwcli doc.md -o doc.html --standalone --theme "#336699,#cc6633"</code></pre><p>Flags: <code class="quikdown-code">--output/-o</code>, <code class="quikdown-code">--standalone/-s</code>, <code class="quikdown-code">--cdn</code>, <code class="quikdown-code">--theme/-t</code>, <code class="quikdown-code">--css/-c</code>, <code class="quikdown-code">--title</code>, <code class="quikdown-code">--favicon/-f</code>, <code class="quikdown-code">--highlight</code>, <code class="quikdown-code">--verbose/-v</code></p><h3 class="quikdown-h3">Pipe Server</h3>
|
|
334
|
-
<p><code class="quikdown-code">bwcli serve</code> turns any language into a bwserve backend -- send JSON protocol messages via HTTP POST or stdin, and connected browsers update in real time:</p><pre class="quikdown-pre"><code class="language-bash">bwcli serve --port 8080 --input-port 9000
|
|
335
|
-
curl -X POST http://localhost:9000 -d '{"type":"patch","target":"temp","content":"23.5 C"}'</code></pre><h2 class="quikdown-h2">Build Formats</h2>
|
|
436
|
+
</table><p>The update functions (<code class="quikdown-code">bw.patch</code>, <code class="quikdown-code">bw.refresh</code>, <code class="quikdown-code">bw.update</code>, <code class="quikdown-code">bw.message</code>) form a cost ladder -- see <a class="quikdown-a" href="#state-and-updates">State and Updates</a>. Full <a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/08-api-reference.html" rel="noopener noreferrer">API Reference</a>.</p><h2 class="quikdown-h2">Build Formats</h2>
|
|
336
437
|
<table class="quikdown-table">
|
|
337
438
|
<thead class="quikdown-thead">
|
|
338
439
|
<tr class="quikdown-tr">
|
|
@@ -344,32 +445,33 @@ curl -X POST http://localhost:9000 -d '{"type":"patch",&
|
|
|
344
445
|
<tbody class="quikdown-tbody">
|
|
345
446
|
<tr class="quikdown-tr">
|
|
346
447
|
<td class="quikdown-td">UMD</td>
|
|
347
|
-
<td class="quikdown-td"
|
|
448
|
+
<td class="quikdown-td">bitwrench.umd.min.js</td>
|
|
348
449
|
<td class="quikdown-td">Browsers and Node.js</td>
|
|
349
450
|
</tr>
|
|
350
451
|
<tr class="quikdown-tr">
|
|
351
452
|
<td class="quikdown-td">ESM</td>
|
|
352
|
-
<td class="quikdown-td"
|
|
453
|
+
<td class="quikdown-td">bitwrench.esm.min.js</td>
|
|
353
454
|
<td class="quikdown-td">Modern bundlers (Vite, webpack, etc.)</td>
|
|
354
455
|
</tr>
|
|
355
456
|
<tr class="quikdown-tr">
|
|
356
457
|
<td class="quikdown-td">CJS</td>
|
|
357
|
-
<td class="quikdown-td"
|
|
358
|
-
<td class="quikdown-td">Node.js
|
|
458
|
+
<td class="quikdown-td">bitwrench.cjs.min.js</td>
|
|
459
|
+
<td class="quikdown-td">Node.js require()</td>
|
|
359
460
|
</tr>
|
|
360
461
|
<tr class="quikdown-tr">
|
|
361
462
|
<td class="quikdown-td">ES5</td>
|
|
362
|
-
<td class="quikdown-td"
|
|
463
|
+
<td class="quikdown-td">bitwrench.es5.min.js</td>
|
|
363
464
|
<td class="quikdown-td">Legacy browsers (IE11)</td>
|
|
364
465
|
</tr>
|
|
365
466
|
</tbody>
|
|
366
467
|
</table><p>All formats include source maps. A separate CSS file (<code class="quikdown-code">bitwrench.css</code>) is also available for use without JavaScript.</p><h2 class="quikdown-h2">Documentation</h2>
|
|
367
468
|
<strong class="quikdown-strong">Start here:</strong></p><ul class="quikdown-ul">
|
|
368
|
-
<li class="quikdown-li"><strong class="quikdown-strong"><a class="quikdown-a" href="docs/thinking-in-bitwrench.md">Thinking in Bitwrench</a></strong> -- the complete guide
|
|
369
|
-
<li class="quikdown-li"><strong class="quikdown-strong"><a class="quikdown-a" href="docs/llm-bitwrench-guide.md">LLM Guide</a></strong> -- compact single-file reference with all APIs, patterns, and rules
|
|
469
|
+
<li class="quikdown-li"><strong class="quikdown-strong"><a class="quikdown-a" href="docs/thinking-in-bitwrench.md">Thinking in Bitwrench</a></strong> -- the complete guide: TACO format, styling, composition, events, the component model, bwserve, and common patterns</li>
|
|
470
|
+
<li class="quikdown-li"><strong class="quikdown-strong"><a class="quikdown-a" href="docs/llm-bitwrench-guide.md">LLM Guide</a></strong> -- compact single-file reference with all APIs, patterns, and rules</li>
|
|
370
471
|
</ul><p><strong class="quikdown-strong">Reference guides</strong> (in <code class="quikdown-code">docs/</code>):</p><ul class="quikdown-ul">
|
|
371
472
|
<li class="quikdown-li"><a class="quikdown-a" href="docs/taco-format.md">TACO Format</a> -- the <code class="quikdown-code">{t, a, c, o}</code> object format</li>
|
|
372
|
-
<li class="quikdown-li"><a class="quikdown-a" href="docs/
|
|
473
|
+
<li class="quikdown-li"><a class="quikdown-a" href="docs/component-lifecycle.md">Component Lifecycle Walkthrough</a> -- one stats card through all four phases</li>
|
|
474
|
+
<li class="quikdown-li"><a class="quikdown-a" href="docs/state-management.md">State Management</a> -- component model, explicit updates, cross-component communication</li>
|
|
373
475
|
<li class="quikdown-li"><a class="quikdown-a" href="docs/component-library.md">Component Library</a> -- all <code class="quikdown-code">make*()</code> functions with signatures and examples</li>
|
|
374
476
|
<li class="quikdown-li"><a class="quikdown-a" href="docs/theming.md">Theming</a> -- palette-driven theme generation, presets, design tokens</li>
|
|
375
477
|
<li class="quikdown-li"><a class="quikdown-a" href="docs/cli.md">CLI</a> -- the <code class="quikdown-code">bwcli</code> command for file conversion and pipe server</li>
|
|
@@ -388,7 +490,7 @@ curl -X POST http://localhost:9000 -d '{"type":"patch",&
|
|
|
388
490
|
<li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/10-themes.html" rel="noopener noreferrer">Themes</a> -- interactive theme generator with presets and CSS export</li>
|
|
389
491
|
</ul><p><strong class="quikdown-strong">Example apps</strong> (in <code class="quikdown-code">examples/</code>):</p><ul class="quikdown-ul">
|
|
390
492
|
<li class="quikdown-li"><a class="quikdown-a" href="examples/ember-and-oak/">Ember & Oak Coffee Co.</a> -- full landing page: theme, cart, search, charts, accordion, timeline</li>
|
|
391
|
-
<li class="quikdown-li"><a class="quikdown-a" href="examples/landing-page/">SunForge Landing Page</a> --
|
|
493
|
+
<li class="quikdown-li"><a class="quikdown-a" href="examples/landing-page/">SunForge Landing Page</a> -- marketing page with zero reactive state, pure BCCL composition</li>
|
|
392
494
|
<li class="quikdown-li"><a class="quikdown-a" href="examples/todo-app/">Todo App</a> -- stateful TACO with pub/sub</li>
|
|
393
495
|
<li class="quikdown-li"><a class="quikdown-a" href="examples/dashboard/">Metrics Dashboard</a> -- live stat cards, bar chart, pub/sub, responsive layout</li>
|
|
394
496
|
<li class="quikdown-li"><a class="quikdown-a" href="examples/wizard/">Signup Wizard</a> -- multi-step form, state transitions, bw.raw()</li>
|
|
@@ -397,7 +499,7 @@ curl -X POST http://localhost:9000 -d '{"type":"patch",&
|
|
|
397
499
|
<li class="quikdown-li"><a class="quikdown-a" href="examples/client-server/">bwserve Counter</a> -- server-driven UI demo</li>
|
|
398
500
|
<li class="quikdown-li"><a class="quikdown-a" href="examples/llm-chat/">LLM Chat</a> -- streaming chat via bwserve + Ollama/OpenAI</li>
|
|
399
501
|
</ul><h2 class="quikdown-h2">FAQ</h2>
|
|
400
|
-
<strong class="quikdown-strong">Is this a framework?</strong> -- No.
|
|
502
|
+
<strong class="quikdown-strong">Is this a framework?</strong> -- No. It is a library (165KB on disk, 45KB gzipped). No lifecycle ceremony, no project structure. Import it, call functions, done. Lifecycle hooks (<code class="quikdown-code">o.mounted</code>, <code class="quikdown-code">o.unmount</code>) are opt-in.</p><p><strong class="quikdown-strong">How does bitwrench compare to React/Vue?</strong> -- They solve different problems at different scales. React and Vue provide a component model, virtual DOM, and ecosystem for large team-built SPAs. Bitwrench provides rendering and state primitives in a single file with no build step, aimed at single-page tools, dashboards, embedded devices, and server-driven UIs. They coexist fine.</p><p><strong class="quikdown-strong">How does CSS work?</strong> -- Bitwrench does not own your CSS. Use any external stylesheet, Tailwind, or CSS file you want. On top of that, <code class="quikdown-code">bw.css()</code> generates CSS from JS objects (with <code class="quikdown-code">@media</code>, <code class="quikdown-code">@keyframes</code>, pseudo-classes), <code class="quikdown-code">bw.s()</code> composes inline style objects, and <code class="quikdown-code">bw.loadStyles()</code> derives a complete design system from seed colors. Use all three or none.</p><p><strong class="quikdown-strong">What's the difference between <code class="quikdown-code">bw.mount()</code> and <code class="quikdown-code">bw.html()</code>?</strong> -- Same TACO input, two outputs. <code class="quikdown-code">bw.mount('#app', taco)</code> mounts live DOM elements in a browser. <code class="quikdown-code">bw.html(taco)</code> returns an HTML string for Node.js scripts, email generators, static site builds, or anywhere you need markup without a browser. (<code class="quikdown-code">bw.DOM()</code> is an alias for <code class="quikdown-code">bw.mount()</code>.)</p><p><strong class="quikdown-strong">What is bwserve?</strong> -- A protocol that turns the browser into a display and input device for a program running anywhere. The server pushes TACO objects and patches over SSE; button clicks come back as actions; <code class="quikdown-code">client.inspect()</code> returns DOM state; <code class="quikdown-code">client.screenshot()</code> returns a PNG. Language-agnostic: Python, Go, Rust, C, or a shell script with <code class="quikdown-code">curl</code>. See the <a class="quikdown-a" href="docs/bwserve.md">bwserve docs</a>.</p><p><strong class="quikdown-strong">Can I use bitwrench on embedded devices?</strong> -- Yes. The device serves one HTML page plus the library from flash, no CDN required. Build the UI as TACOs in whatever language the device speaks (C, C++, MicroPython), push updates over SSE, and get button presses back the same way. C macros ship in <code class="quikdown-code">embedded_c/</code>. See the <a class="quikdown-a" href="docs/tutorial-embedded.md">ESP32 tutorial</a> and the <a class="quikdown-a" href="examples/embedded-pico-w/">Pico W example</a>.</p><p><strong class="quikdown-strong">Can I use it with TypeScript?</strong> -- Yes. Type declarations ship with the package (<code class="quikdown-code">dist/bitwrench.d.ts</code>). See the <a class="quikdown-a" href="docs/bitwrench<em class="quikdown-em">typescript</em>usage.md">TypeScript Usage Guide</a>.</p><p><strong class="quikdown-strong">What about accessibility?</strong> -- BCCL components emit semantic HTML with ARIA attributes where applicable. You can add any <code class="quikdown-code">aria-*</code> attribute via <code class="quikdown-code">a: { 'aria-label': '...' }</code>.</p><h2 class="quikdown-h2">Development</h2>
|
|
401
503
|
<p><pre class="quikdown-pre"><code class="language-bash">npm install # install dev dependencies
|
|
402
504
|
npm run build # build all dist formats (UMD, ESM, CJS, ES5)
|
|
403
505
|
npm test # run unit tests
|
|
@@ -405,7 +507,7 @@ npm run test:cli # run CLI tests
|
|
|
405
507
|
npm run test:e2e # run Playwright browser tests
|
|
406
508
|
npm run lint # run ESLint
|
|
407
509
|
npm run cleanbuild # full production build with SRI hashes</code></pre></p><h2 class="quikdown-h2">License</h2>
|
|
408
|
-
<a class="quikdown-a" href="./LICENSE.txt">BSD-2-Clause</a> -- (c) M. A. Chatterjee / <a class="quikdown-a" href="https://github.com/deftio" rel="noopener noreferrer">deftio</a>
|
|
510
|
+
<a class="quikdown-a" href="./LICENSE.txt">BSD-2-Clause</a> -- (c) M. A. Chatterjee / <a class="quikdown-a" href="https://github.com/deftio" rel="noopener noreferrer">deftio</a> -- use it in your own projects or commercially.
|
|
409
511
|
</p>
|
|
410
512
|
</div>
|
|
411
513
|
</div>
|