bitwrench 2.0.16 → 2.0.18
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 +127 -38
- package/dist/bitwrench-bccl.cjs.js +13 -9
- package/dist/bitwrench-bccl.cjs.min.js +2 -2
- package/dist/bitwrench-bccl.esm.js +13 -9
- package/dist/bitwrench-bccl.esm.min.js +2 -2
- package/dist/bitwrench-bccl.umd.js +13 -9
- package/dist/bitwrench-bccl.umd.min.js +2 -2
- 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-lean.cjs.js +1438 -920
- package/dist/bitwrench-lean.cjs.min.js +20 -20
- package/dist/bitwrench-lean.es5.js +1518 -1105
- package/dist/bitwrench-lean.es5.min.js +18 -18
- package/dist/bitwrench-lean.esm.js +1437 -920
- package/dist/bitwrench-lean.esm.min.js +20 -20
- package/dist/bitwrench-lean.umd.js +1438 -920
- package/dist/bitwrench-lean.umd.min.js +20 -20
- package/dist/bitwrench-util-css.cjs.js +236 -0
- package/dist/bitwrench-util-css.cjs.min.js +22 -0
- package/dist/bitwrench-util-css.es5.js +414 -0
- package/dist/bitwrench-util-css.es5.min.js +21 -0
- package/dist/bitwrench-util-css.esm.js +230 -0
- package/dist/bitwrench-util-css.esm.min.js +21 -0
- package/dist/bitwrench-util-css.umd.js +242 -0
- package/dist/bitwrench-util-css.umd.min.js +21 -0
- package/dist/bitwrench.cjs.js +1450 -928
- package/dist/bitwrench.cjs.min.js +21 -21
- package/dist/bitwrench.css +456 -132
- package/dist/bitwrench.es5.js +1563 -1140
- package/dist/bitwrench.es5.min.js +19 -19
- package/dist/bitwrench.esm.js +1450 -929
- package/dist/bitwrench.esm.min.js +21 -21
- package/dist/bitwrench.min.css +1 -1
- package/dist/bitwrench.umd.js +1450 -928
- package/dist/bitwrench.umd.min.js +21 -21
- package/dist/builds.json +178 -90
- package/dist/bwserve.cjs.js +528 -68
- package/dist/bwserve.esm.js +527 -69
- package/dist/sri.json +44 -36
- package/package.json +5 -2
- package/readme.html +136 -49
- package/src/bitwrench-bccl.js +12 -8
- package/src/bitwrench-color-utils.js +31 -9
- package/src/bitwrench-esm-entry.js +11 -0
- package/src/bitwrench-styles.js +439 -232
- package/src/bitwrench-util-css.js +229 -0
- package/src/bitwrench.js +979 -630
- package/src/bwserve/attach.js +57 -0
- package/src/bwserve/bwclient.js +141 -0
- package/src/bwserve/bwshell.js +102 -0
- package/src/bwserve/client.js +151 -1
- package/src/bwserve/index.js +139 -29
- package/src/cli/attach.js +555 -0
- package/src/cli/convert.js +2 -5
- package/src/cli/index.js +7 -0
- package/src/cli/inject.js +1 -1
- package/src/cli/layout-default.js +47 -32
- package/src/cli/serve.js +6 -2
- package/src/generate-css.js +11 -4
- package/src/vendor/html2canvas.min.js +20 -0
- package/src/version.js +3 -3
- package/src/bwserve/shell.js +0 -103
package/dist/sri.json
CHANGED
|
@@ -1,41 +1,49 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.0.
|
|
2
|
+
"version": "2.0.18",
|
|
3
3
|
"algorithm": "sha384",
|
|
4
|
-
"generated": "2026-03-
|
|
4
|
+
"generated": "2026-03-17",
|
|
5
5
|
"files": {
|
|
6
|
-
"bitwrench-bccl.cjs.js": "sha384-
|
|
7
|
-
"bitwrench-bccl.cjs.min.js": "sha384-
|
|
8
|
-
"bitwrench-bccl.esm.js": "sha384
|
|
9
|
-
"bitwrench-bccl.esm.min.js": "sha384-
|
|
10
|
-
"bitwrench-bccl.umd.js": "sha384-
|
|
11
|
-
"bitwrench-bccl.umd.min.js": "sha384
|
|
12
|
-
"bitwrench-code-edit.cjs.js": "sha384-
|
|
13
|
-
"bitwrench-code-edit.cjs.min.js": "sha384-
|
|
14
|
-
"bitwrench-code-edit.es5.js": "sha384-
|
|
15
|
-
"bitwrench-code-edit.es5.min.js": "sha384-
|
|
16
|
-
"bitwrench-code-edit.esm.js": "sha384-
|
|
17
|
-
"bitwrench-code-edit.esm.min.js": "sha384-
|
|
18
|
-
"bitwrench-code-edit.umd.js": "sha384-
|
|
19
|
-
"bitwrench-code-edit.umd.min.js": "sha384-
|
|
20
|
-
"bitwrench-lean.cjs.js": "sha384-
|
|
21
|
-
"bitwrench-lean.cjs.min.js": "sha384-
|
|
22
|
-
"bitwrench-lean.es5.js": "sha384-
|
|
23
|
-
"bitwrench-lean.es5.min.js": "sha384-
|
|
24
|
-
"bitwrench-lean.esm.js": "sha384-
|
|
25
|
-
"bitwrench-lean.esm.min.js": "sha384-
|
|
26
|
-
"bitwrench-lean.umd.js": "sha384-
|
|
27
|
-
"bitwrench-lean.umd.min.js": "sha384-
|
|
28
|
-
"bitwrench.cjs.js": "sha384-
|
|
29
|
-
"bitwrench.cjs.min.js": "sha384-
|
|
30
|
-
"bitwrench.
|
|
31
|
-
"bitwrench.es5.js": "sha384-
|
|
32
|
-
"bitwrench.
|
|
33
|
-
"bitwrench.esm.js": "sha384-
|
|
34
|
-
"bitwrench.
|
|
35
|
-
"bitwrench.min.
|
|
36
|
-
"bitwrench.
|
|
37
|
-
"bitwrench.
|
|
38
|
-
"
|
|
39
|
-
"
|
|
6
|
+
"bitwrench-bccl.cjs.js": "sha384-97lxNxsJ943yAFgdsGuThcexgw1H/LYsMZvctuArTBq8Z1Dtfijx98V2F4d0KYSg",
|
|
7
|
+
"bitwrench-bccl.cjs.min.js": "sha384-MYtFH6IOfYgEBHyWrKHK4ijXc3wys3nypVIBNYV0xXCDdfQu7NaI2BVAwUhtMw1A",
|
|
8
|
+
"bitwrench-bccl.esm.js": "sha384-/oduwWIsuFsHgkWg8G5I8X6ci203OOCSMVVkOLE8SHyfTNSXnhodXSyPx5KJfnK1",
|
|
9
|
+
"bitwrench-bccl.esm.min.js": "sha384-um8u9y9aMreWN9Qf/xbL+4NPG+BjyRqffHzIqeYWYsPkJUYkgbR2MdAR6pNYBTKz",
|
|
10
|
+
"bitwrench-bccl.umd.js": "sha384-T8Y7WK/bfR0qsEthhonw17Uvc4GbpGCZyWGNvvqo7fZkrf2r994zlRJGkLJOikZZ",
|
|
11
|
+
"bitwrench-bccl.umd.min.js": "sha384-mylsm8Q+K7ZGMoxz6J3/9PrArvea4e0KJDSEMMIBhUDzXZNotzRbV8J8n/xLXbtG",
|
|
12
|
+
"bitwrench-code-edit.cjs.js": "sha384-eD7kA6fzkUuwgH84uOuPZb9zEvHSNJaYnxPmiSmpKzKxbmsuAwb5jtHNdPKzjhGj",
|
|
13
|
+
"bitwrench-code-edit.cjs.min.js": "sha384-vMircu/dAfERhhyaAHxXcjS7k2ZV43Uc+rfVLjdK1BQGfhsYaXqKy1ONwZ5eJ42A",
|
|
14
|
+
"bitwrench-code-edit.es5.js": "sha384-Uh6/1C2kSnmMVdCiMOlFDK0wDIz/FQ89StJXwQS5U+8BLWpeYitxJRVbXh28JrF0",
|
|
15
|
+
"bitwrench-code-edit.es5.min.js": "sha384-3xLz9CiAm/OTx1EVLV9GPVA5t5nAXAzwXV7ItxwlOcOUHjxvuEhBxvaz2MHU584Z",
|
|
16
|
+
"bitwrench-code-edit.esm.js": "sha384-zvcF0qY6rcpYt5K9o6gORkZpCA9XtiuAMocz4oYT34U0nZhp/65rBC9F4GbrEbQ8",
|
|
17
|
+
"bitwrench-code-edit.esm.min.js": "sha384-GBaXjBmcl0Faro4yGOhDzZekie5Ao5G5bQU7Rl9dRvSg1vtnBHSH0zz6IJBkRypl",
|
|
18
|
+
"bitwrench-code-edit.umd.js": "sha384-SApqDWYJATq6BDr1sj13rGXpr8+d590S+bG03Iuhcbm/6DB++Hxp3sDLVSanfuqC",
|
|
19
|
+
"bitwrench-code-edit.umd.min.js": "sha384-1HZO7M7901ex8J9B902cAI0stT1YbI34fpLoyNlv9+DY4B4to6AF5LmVPoA5hfYO",
|
|
20
|
+
"bitwrench-lean.cjs.js": "sha384-dAkymK30IGH1anOiADEvxFaJvgS37nrHyLXMx+4D4R/jn7xBunASkDbFSeGW2acu",
|
|
21
|
+
"bitwrench-lean.cjs.min.js": "sha384-gp6mLzVlYQHysMzgrw8uOcD03/5/Zn3Gqq0kzT1vFH6m7rlDzdUpF+XLos3ZFlj+",
|
|
22
|
+
"bitwrench-lean.es5.js": "sha384-8bzRIuravBPlP/XQGZT5opCdcdxwxg+ia44NDyxbc693+aPKAk9u2koER0f6hPjF",
|
|
23
|
+
"bitwrench-lean.es5.min.js": "sha384-nh0CvCajmgmEJhYoy9QfGzYGUiTHgyrMVZHWY0oDCW4p8AONoZ1HLHe2OrtPI4HR",
|
|
24
|
+
"bitwrench-lean.esm.js": "sha384-O9MYspI5NPZdHd0UBF0brnXE3AvMXAJwL0yKhZ39MLma0nv+aNPx0+Yxo24Z8OVm",
|
|
25
|
+
"bitwrench-lean.esm.min.js": "sha384-AToyDo6g4hVQzn9S7RtmRJ9rL7KvvpZq2Xs22w74wn2UUPUGHqjk0vPFk0vyUsdJ",
|
|
26
|
+
"bitwrench-lean.umd.js": "sha384-ItPAXRKLQJTE5OG2j4mtteKmF3lJEWc+VNTefDaSkZ4aUXzRgikySBDLJjewEHYg",
|
|
27
|
+
"bitwrench-lean.umd.min.js": "sha384-59DBhjfFHQjrXOMnGR5ZYmHRrhst7HhvMlmfn9GSuHVGV9l6z6VZM6+tgmiDQ7vF",
|
|
28
|
+
"bitwrench-util-css.cjs.js": "sha384-AqKsW+lDWKJ5CTpJmZO3Za04fZKmvOswf5BrepWMN1UHmIRBjakBrIbIeh6KqZ7J",
|
|
29
|
+
"bitwrench-util-css.cjs.min.js": "sha384-PVEORrb3H7E5BcHzWN9yaJKOhTFGUu/PK36fQZVk5XODcIVJ7KCKz6gcTKITLy9f",
|
|
30
|
+
"bitwrench-util-css.es5.js": "sha384-roMO7JpMD8MVfREIC0XQI6SSJC9BuOK8zZOPfdEUGmCfWMzbb+tY2+E/msYovErm",
|
|
31
|
+
"bitwrench-util-css.es5.min.js": "sha384-eCIKVMpbra/Xph9G7yHdFKs9DSu52iFbp0C1J+BeX9AcNUhPa8Zv98zroA6GscVb",
|
|
32
|
+
"bitwrench-util-css.esm.js": "sha384-1JTj1P2bDsNkeFbGsn1ztDtHt2sMC32O5G21qclsgnsBbHBo2EnrI/wTxALHM5OG",
|
|
33
|
+
"bitwrench-util-css.esm.min.js": "sha384-hdFDGI+SW5cIR8i06D8fhPss6grt3ne7D1oPfTGGfyNsdpfgjCgEULfUaAPT9lXw",
|
|
34
|
+
"bitwrench-util-css.umd.js": "sha384-1IXVY7rzxrqiEgqRaVLbX2cZqb92h0NmxdW1qGf9WrEL7hMTspiKcnTcDDGSchD6",
|
|
35
|
+
"bitwrench-util-css.umd.min.js": "sha384-F1bwBKL0ftJe0J0H6LlgPgQej54ODG+dD90cWaIaGrC2yWrvnAc9n/xfw3IfVbkq",
|
|
36
|
+
"bitwrench.cjs.js": "sha384-8Py3ZQbesTdr/Nk6Sb+v27LRJJKT8/kyJyB0xAAmRFbEdvL+bNc+Io4F/y1DLX1F",
|
|
37
|
+
"bitwrench.cjs.min.js": "sha384-crCKn7uRyo/06To1Ms5K2buSHLAvixSsx1ZWGjI8jEyH7XDjFoZLtQryVVQx+vXF",
|
|
38
|
+
"bitwrench.css": "sha384-SxT17YrsGzI+MZpPXHaPdBeki24pSK1nqyNzshNh6EWU4zXRFP4g+21LC1Dlh+YU",
|
|
39
|
+
"bitwrench.es5.js": "sha384-+rZTBmXYipKqS/eCHYwSVQxFCh5YKVjnHQeTzkbtkQ2JzQcHVbRZPcPK5LMau6U2",
|
|
40
|
+
"bitwrench.es5.min.js": "sha384-/N7p37IA8HxOEGXhOF2Y4aEGllv8IQvrMbLAQnnZ7znalyiJvqTSIZXxA951+UcY",
|
|
41
|
+
"bitwrench.esm.js": "sha384-iGz+hH8CSL92LiiHVKSOzkjVojvzYM2BpXcLleUj3eUKyx58Qdh/Eiz9mYVtYmao",
|
|
42
|
+
"bitwrench.esm.min.js": "sha384-bN1Mj511R+uL+z3ZmPMuhPn+vL9iEEaUWYT/iNFkh219BuJuLOsCJpx2ZdIQGM2R",
|
|
43
|
+
"bitwrench.min.css": "sha384-D5Yl1DxoYlVwewe1CTZ2GCeof3BOD8D38YuuMiTLWb1WXS6fsP05wwKDzMGxrkRh",
|
|
44
|
+
"bitwrench.umd.js": "sha384-oi3tmqmiKCCk2j8do9t/A3tjhD14kzImnxAXpH6pBcbigEO3m7ToxrgT9/IECb5Z",
|
|
45
|
+
"bitwrench.umd.min.js": "sha384-koZisx/3J1+mZz9Y8SQ0uCuU21B6bSF1BHkjYAXdTMGFSBocQzqnHm1LoV7PJkWh",
|
|
46
|
+
"bwserve.cjs.js": "sha384-klAeGiVLGQ+v8a/8DOGuD6c46GaWNIhIYAKZkQpRipj57COKzsBxagMDVif0IaJj",
|
|
47
|
+
"bwserve.esm.js": "sha384-C1MUV7+IMPbdewQWvcXLMMZQpdp2X5PaO5oDb7FdgeOLS2aPExD+aGoMQrlfaOiZ"
|
|
40
48
|
}
|
|
41
49
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bitwrench",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.18",
|
|
4
4
|
"description": "A library for javascript UI functions.",
|
|
5
5
|
"main": "./dist/bitwrench.umd.js",
|
|
6
6
|
"repository": {
|
|
@@ -95,8 +95,9 @@
|
|
|
95
95
|
"build_1_x": "./tools/update-bw-package.js package.json package.json && ./tools/export-bw-default-css.js bitwrench.css && uglifyjs bitwrench.js -o bitwrench.min.js && uglifyjs bitwrench_ESM.js -o bitwrench_ESM.min.js && ./tools/umd2ModuleHack.js && npm pack",
|
|
96
96
|
"cleanbuild": "npm run clean && npm run build && npm run build:generated",
|
|
97
97
|
"oldtest": "./node_modules/mocha/bin/mocha test/bitwrench_test.js --reporter spec",
|
|
98
|
-
"test": "c8 --reporter=text mocha ./test/bitwrench_ci.js ./test/bitwrench_test_coverage.js ./test/bitwrench_test_pubsub.js ./test/bitwrench_test_theme.js ./test/bitwrench_test_nodemap.js ./test/bitwrench_test_components.js ./test/bitwrench_test_component_handle.js ./test/bitwrench_test_coverage_gaps.js ./test/bitwrench_test_bwserve.js -r jsdom-global/register",
|
|
98
|
+
"test": "c8 --reporter=text mocha ./test/bitwrench_ci.js ./test/bitwrench_test_coverage.js ./test/bitwrench_test_pubsub.js ./test/bitwrench_test_theme.js ./test/bitwrench_test_nodemap.js ./test/bitwrench_test_components.js ./test/bitwrench_test_component_handle.js ./test/bitwrench_test_coverage_gaps.js ./test/bitwrench_test_bwserve.js ./test/bitwrench_test_attach.js ./test/bitwrench_test_code_edit.js ./test/bitwrench_test_html_page.js ./test/bitwrench_test_util_css.js -r jsdom-global/register",
|
|
99
99
|
"test:bwserve": "mocha ./test/bitwrench_test_bwserve.js -r jsdom-global/register",
|
|
100
|
+
"test:attach": "mocha ./test/bitwrench_test_attach.js -r jsdom-global/register",
|
|
100
101
|
"test:components": "mocha ./test/bitwrench_test_components.js -r jsdom-global/register",
|
|
101
102
|
"test:v1": "c8 --reporter=text mocha ./test/bitwrench_test.js -r jsdom-global/",
|
|
102
103
|
"test:pending": "mocha ./test/bitwrench_test_pending.js -r jsdom-global/",
|
|
@@ -111,6 +112,8 @@
|
|
|
111
112
|
"generate-sri": "node tools/generate-sri.js",
|
|
112
113
|
"test:nodemap": "mocha ./test/bitwrench_test_nodemap.js -r jsdom-global/register",
|
|
113
114
|
"test:cli": "mocha ./test/bitwrench_test_cli.js",
|
|
115
|
+
"test:code-edit": "mocha ./test/bitwrench_test_code_edit.js -r jsdom-global/register",
|
|
116
|
+
"test:html-page": "mocha ./test/bitwrench_test_html_page.js -r jsdom-global/register",
|
|
114
117
|
"test:e2e": "playwright test",
|
|
115
118
|
"test:e2e:headed": "playwright test --headed",
|
|
116
119
|
"test:e2e:debug": "playwright test --debug",
|
package/readme.html
CHANGED
|
@@ -3,12 +3,11 @@
|
|
|
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.0.18">
|
|
7
7
|
<title>bitwrench.js - README</title>
|
|
8
8
|
<link rel="icon" type="image/x-icon" href="images/favicon.ico">
|
|
9
|
-
<script src="dist/bitwrench.umd.js"></script>
|
|
10
|
-
<
|
|
11
|
-
<link rel="stylesheet" href="pages/shared-theme.css">
|
|
9
|
+
<script src="dist/bitwrench.umd.min.js"></script>
|
|
10
|
+
<script src="pages/shared-theme.js"></script>
|
|
12
11
|
<script src="pages/shared-nav.js"></script>
|
|
13
12
|
<style>
|
|
14
13
|
.quikdown-h1 { font-size:2em;font-weight:600;margin:.67em 0;text-align:left;color:#333 }
|
|
@@ -72,34 +71,84 @@
|
|
|
72
71
|
<h1 class="quikdown-h1">bitwrench.js</h1>
|
|
73
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"></a>
|
|
74
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"></a>
|
|
75
|
-
<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"></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"></a></p><p>Bitwrench
|
|
76
|
-
|
|
77
|
-
t: 'div', a: { class: '
|
|
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"></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"></a></p><p>Bitwrench builds UI from plain JavaScript objects — one format for components, styling, state, and server rendering, with no build step and zero dependencies. In bitwrench structure, styles, and state (including client/server) are rendered and managed as javascript objects.</p><pre class="quikdown-pre"><code class="language-javascript">// Describe UI as a JavaScript object (a "TACO")
|
|
75
|
+
var page = {
|
|
76
|
+
t: 'div', a: { class: 'card' },
|
|
78
77
|
c: [
|
|
79
|
-
{ t: '
|
|
80
|
-
{ t: 'p', c: 'UI as native JavaScript objects.' }
|
|
78
|
+
{ t: 'h2', c: 'Hello' },
|
|
79
|
+
{ t: 'p', c: 'UI as native JavaScript objects.' },
|
|
80
|
+
bw.makeButton({ text: 'Click me', variant: 'primary', onclick: fn })
|
|
81
81
|
]
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
-
//
|
|
85
|
-
bw.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
bw.DOM('#app', page); // → live DOM
|
|
85
|
+
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/lifecycle). Nest them, loop them, compose them — it's just JavaScript.</p><p><img class="quikdown-img" src="./images/hero-example.png" alt="Hero example output"></p><h3 class="quikdown-h3">Why bitwrench?</h3>
|
|
86
|
+
<strong class="quikdown-strong">One file, everywhere.</strong> At ~39KB 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">
|
|
87
|
+
<li class="quikdown-li"><strong class="quikdown-strong">No build toolchain</strong> — works with a <code class="quikdown-code"><script></code> tag</li>
|
|
88
|
+
<li class="quikdown-li"><strong class="quikdown-strong">50+ ready-made components</strong> — buttons, tables, modals, forms, charts, toasts — one <code class="quikdown-code">make*()</code> call each, returns a composable TACO</li>
|
|
89
|
+
<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> or <code class="quikdown-code">bw.makeStyles()</code> derives a complete theme from 2 seed colors</li>
|
|
90
|
+
<li class="quikdown-li"><strong class="quikdown-strong">Reactive state</strong> — <code class="quikdown-code">bw.component()</code> provides <code class="quikdown-code">.get()/.set()</code> with <code class="quikdown-code">${template}</code> bindings; <code class="quikdown-code">bw.pub()</code>/<code class="quikdown-code">bw.sub()</code> for cross-component messaging</li>
|
|
91
|
+
<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>
|
|
92
|
+
<li class="quikdown-li"><strong class="quikdown-strong">Server-driven UI</strong> — push UI updates from any backend (Python, C, Rust, Go) over SSE; <code class="quikdown-code">client.screenshot()</code> captures the page back as PNG/JPEG</li>
|
|
93
|
+
<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>
|
|
94
|
+
<li class="quikdown-li"><strong class="quikdown-strong">Utilities</strong> — color interpolation, random data, lorem ipsum, cookies, URL params, file I/O</li>
|
|
95
|
+
</ul><h3 class="quikdown-h3">Coming from other Frameworks</h3>
|
|
96
|
+
<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">
|
|
97
|
+
<thead class="quikdown-thead">
|
|
98
|
+
<tr class="quikdown-tr">
|
|
99
|
+
<th class="quikdown-th">You're using</th>
|
|
100
|
+
<th class="quikdown-th">For</th>
|
|
101
|
+
<th class="quikdown-th">Bitwrench equivalent</th>
|
|
102
|
+
</tr>
|
|
103
|
+
</thead>
|
|
104
|
+
<tbody class="quikdown-tbody">
|
|
105
|
+
<tr class="quikdown-tr">
|
|
106
|
+
<td class="quikdown-td">React / Vue / Svelte</td>
|
|
107
|
+
<td class="quikdown-td">Components + reactivity</td>
|
|
108
|
+
<td class="quikdown-td"><code class="quikdown-code">{t, a, c, o}</code> objects + <code class="quikdown-code">bw.component()</code></td>
|
|
109
|
+
</tr>
|
|
110
|
+
<tr class="quikdown-tr">
|
|
111
|
+
<td class="quikdown-td">JSX / templates</td>
|
|
112
|
+
<td class="quikdown-td">Markup-in-JS</td>
|
|
113
|
+
<td class="quikdown-td">Native JS objects — no compiler</td>
|
|
114
|
+
</tr>
|
|
115
|
+
<tr class="quikdown-tr">
|
|
116
|
+
<td class="quikdown-td">Tailwind / CSS-in-JS</td>
|
|
117
|
+
<td class="quikdown-td">Styling</td>
|
|
118
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.css()</code>, <code class="quikdown-code">bw.s()</code> style composition</td>
|
|
119
|
+
</tr>
|
|
120
|
+
<tr class="quikdown-tr">
|
|
121
|
+
<td class="quikdown-td">Sass / PostCSS</td>
|
|
122
|
+
<td class="quikdown-td">CSS generation</td>
|
|
123
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.css()</code> from JS objects (supports @media, @keyframes)</td>
|
|
124
|
+
</tr>
|
|
125
|
+
<tr class="quikdown-tr">
|
|
126
|
+
<td class="quikdown-td">ThemeProvider / CSS vars</td>
|
|
127
|
+
<td class="quikdown-td">Theming</td>
|
|
128
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.loadStyles()</code> / <code class="quikdown-code">bw.makeStyles()</code> from 2 seed colors</td>
|
|
129
|
+
</tr>
|
|
130
|
+
<tr class="quikdown-tr">
|
|
131
|
+
<td class="quikdown-td">Streamlit / Gradio</td>
|
|
132
|
+
<td class="quikdown-td">Server-driven UI</td>
|
|
133
|
+
<td class="quikdown-td">bwserve SSE — from any language (Python, Go, C, Rust)</td>
|
|
134
|
+
</tr>
|
|
135
|
+
<tr class="quikdown-tr">
|
|
136
|
+
<td class="quikdown-td">Redux / Zustand / Pinia</td>
|
|
137
|
+
<td class="quikdown-td">State management</td>
|
|
138
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.component()</code> <code class="quikdown-code">.get()/.set()</code> + <code class="quikdown-code">bw.pub()/sub()</code></td>
|
|
139
|
+
</tr>
|
|
140
|
+
<tr class="quikdown-tr">
|
|
141
|
+
<td class="quikdown-td">Vite / webpack / Babel</td>
|
|
142
|
+
<td class="quikdown-td">Build tooling</td>
|
|
143
|
+
<td class="quikdown-td">Not needed — open the HTML file</td>
|
|
144
|
+
</tr>
|
|
145
|
+
</tbody>
|
|
146
|
+
</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>
|
|
89
147
|
<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
|
|
90
148
|
import bw from 'bitwrench';
|
|
91
149
|
|
|
92
150
|
// CommonJS
|
|
93
|
-
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">
|
|
94
|
-
<ul class="quikdown-ul">
|
|
95
|
-
<li class="quikdown-li"><strong class="quikdown-strong">HTML from plain objects</strong> — describe UI as JavaScript objects, render to live DOM with <code class="quikdown-code">bw.DOM()</code> or to HTML strings with <code class="quikdown-code">bw.html()</code> for server-side rendering, emails, and static pages</li>
|
|
96
|
-
<li class="quikdown-li"><strong class="quikdown-strong">Built-in reactivity</strong> — <code class="quikdown-code">bw.update()</code> re-renders components when state changes, <code class="quikdown-code">bw.patch()</code> updates individual elements by ID, <code class="quikdown-code">bw.pub()</code>/<code class="quikdown-code">bw.sub()</code> provides decoupled messaging between any part of the application</li>
|
|
97
|
-
<li class="quikdown-li"><strong class="quikdown-strong">CSS and theme generation</strong> — <code class="quikdown-code">bw.css()</code> generates stylesheets from objects, <code class="quikdown-code">bw.generateTheme()</code> derives a complete visual theme (buttons, alerts, badges, cards, forms, tables, dark mode) from 2-3 seed colors</li>
|
|
98
|
-
<li class="quikdown-li"><strong class="quikdown-strong">45+ ready-made components</strong> — cards, buttons, sortable tables, form inputs, modals, dropdowns, accordions, tooltips, popovers, toasts, timelines, steppers, file uploads, stat cards — each a single function call that returns a composable object</li>
|
|
99
|
-
<li class="quikdown-li"><strong class="quikdown-strong">Server-driven UI (bwserve)</strong> — push TACO rendering commands from Node.js to the browser over SSE; same protocol works from C (ESP32), Python, Rust, or any language via the <code class="quikdown-code">bwcli serve</code> pipe server</li>
|
|
100
|
-
<li class="quikdown-li"><strong class="quikdown-strong">Static site CLI</strong> — the <code class="quikdown-code">bwcli</code> command converts Markdown, HTML, and JSON files into styled, self-contained pages with theme support</li>
|
|
101
|
-
<li class="quikdown-li"><strong class="quikdown-strong">Utilities</strong> — color interpolation, random data generation, lorem ipsum, cookies, URL params, file I/O for both browser and Node.js</li>
|
|
102
|
-
</ul><h2 class="quikdown-h2">Getting Started</h2>
|
|
151
|
+
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>
|
|
103
152
|
<p><pre class="quikdown-pre"><code class="language-html"><!DOCTYPE html>
|
|
104
153
|
<html lang="en">
|
|
105
154
|
<head>
|
|
@@ -108,7 +157,7 @@ const bw = require('bitwrench');</code></pre><p>Or include directly in a
|
|
|
108
157
|
<body>
|
|
109
158
|
<div id="app"></div>
|
|
110
159
|
<script>
|
|
111
|
-
bw.
|
|
160
|
+
bw.loadStyles();
|
|
112
161
|
|
|
113
162
|
bw.DOM('#app', {
|
|
114
163
|
t: 'div', a: { class: 'bw-container' },
|
|
@@ -118,7 +167,11 @@ const bw = require('bitwrench');</code></pre><p>Or include directly in a
|
|
|
118
167
|
title: 'Welcome',
|
|
119
168
|
content: 'Built with plain JavaScript objects.'
|
|
120
169
|
}),
|
|
121
|
-
bw.makeButton({
|
|
170
|
+
bw.makeButton({
|
|
171
|
+
text: 'Click me',
|
|
172
|
+
variant: 'primary',
|
|
173
|
+
onclick: function() { alert('Hello!'); }
|
|
174
|
+
})
|
|
122
175
|
]
|
|
123
176
|
});
|
|
124
177
|
</script>
|
|
@@ -141,17 +194,30 @@ const bw = require('bitwrench');</code></pre><p>Or include directly in a
|
|
|
141
194
|
|
|
142
195
|
bw.DOM('#app', counter);
|
|
143
196
|
counter.set('count', 42); // DOM updates automatically
|
|
144
|
-
counter.reset(); // methods from o.methods are callable on the handle</code></pre><p>For low-level control, you can also use <code class="quikdown-code">o.render</code> + <code class="quikdown-code">bw.update()</code> directly — see the <a class="quikdown-a" href="docs/state-management.md">State Management guide</a>.</p><p>For communication between components, use pub/sub:</p><pre class="quikdown-pre"><code class="language-javascript">bw.sub('item-added', function(detail) {
|
|
197
|
+
counter.reset(); // methods from o.methods are callable on the handle</code></pre><blockquote class="quikdown-blockquote"><strong class="quikdown-strong">Important: event handlers go in <code class="quikdown-code">a: { onclick: fn }</code>, not in <code class="quikdown-code">o.mounted</code>.</strong> Handlers attached via <code class="quikdown-code">addEventListener</code> in <code class="quikdown-code">o.mounted</code> are silently lost when a component re-renders. Always use <code class="quikdown-code">onclick</code>/<code class="quikdown-code">onchange</code>/etc. inside <code class="quikdown-code">a:</code> — bitwrench re-attaches them on every render automatically.</blockquote><p>For low-level control, you can also use <code class="quikdown-code">o.render</code> + <code class="quikdown-code">bw.update()</code> directly — see the <a class="quikdown-a" href="docs/state-management.md">State Management guide</a>.</p><p>For communication between components, use pub/sub:</p><pre class="quikdown-pre"><code class="language-javascript">bw.sub('item-added', function(detail) {
|
|
145
198
|
console.log('New item:', detail.name);
|
|
146
199
|
});
|
|
147
200
|
|
|
148
|
-
bw.pub('item-added', { name: 'Widget' });</code></pre><h2 class="quikdown-h2">
|
|
149
|
-
<p>
|
|
201
|
+
bw.pub('item-added', { name: 'Widget' });</code></pre><h2 class="quikdown-h2">CSS from JavaScript</h2>
|
|
202
|
+
<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
|
|
203
|
+
bw.injectCSS(bw.css({
|
|
204
|
+
'.my-card': { padding: '1rem', borderRadius: '8px' }
|
|
205
|
+
}));
|
|
206
|
+
|
|
207
|
+
// Compose inline styles from objects
|
|
208
|
+
{ t: 'div', a: { style: bw.s({ display: 'flex' }, { gap: '1rem' }, { padding: '1rem' }) } }
|
|
209
|
+
|
|
210
|
+
// Responsive breakpoints
|
|
211
|
+
bw.responsive('.hero', {
|
|
212
|
+
base: { fontSize: '1.5rem' },
|
|
213
|
+
md: { fontSize: '2.5rem' }
|
|
214
|
+
});</code></pre><h2 class="quikdown-h2">Theming</h2>
|
|
215
|
+
<p><code class="quikdown-code">bw.loadStyles()</code> derives a design system — buttons, alerts, badges, cards, forms, tables, hover states, focus rings — from two seed colors. Themes are scoped to DOM subtrees, so different sections of a page can use different themes. <code class="quikdown-code">toggleStyles()</code> switches between primary and alternate palettes:</p><pre class="quikdown-pre"><code class="language-javascript">bw.loadStyles({
|
|
150
216
|
primary: '#336699',
|
|
151
217
|
secondary: '#cc6633'
|
|
152
218
|
});
|
|
153
219
|
|
|
154
|
-
bw.
|
|
220
|
+
bw.toggleStyles(); // switch between primary and alternate palettes</code></pre><h2 class="quikdown-h2">Core API</h2>
|
|
155
221
|
<table class="quikdown-table">
|
|
156
222
|
<thead class="quikdown-thead">
|
|
157
223
|
<tr class="quikdown-tr">
|
|
@@ -169,6 +235,10 @@ bw.toggleTheme(); // switch between primary and alternate palettes</code></pre>
|
|
|
169
235
|
<td class="quikdown-td">Mount an object to a DOM element</td>
|
|
170
236
|
</tr>
|
|
171
237
|
<tr class="quikdown-tr">
|
|
238
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.raw(str)</code></td>
|
|
239
|
+
<td class="quikdown-td">Mark a string as pre-escaped HTML (no double-escaping)</td>
|
|
240
|
+
</tr>
|
|
241
|
+
<tr class="quikdown-tr">
|
|
172
242
|
<td class="quikdown-td"><code class="quikdown-code">bw.component(taco)</code></td>
|
|
173
243
|
<td class="quikdown-td">Wrap a TACO in a ComponentHandle with <code class="quikdown-code">.get()/.set()</code> reactive API</td>
|
|
174
244
|
</tr>
|
|
@@ -177,12 +247,24 @@ bw.toggleTheme(); // switch between primary and alternate palettes</code></pre>
|
|
|
177
247
|
<td class="quikdown-td">Generate CSS from a JS object</td>
|
|
178
248
|
</tr>
|
|
179
249
|
<tr class="quikdown-tr">
|
|
180
|
-
<td class="quikdown-td"><code class="quikdown-code">bw.
|
|
181
|
-
<td class="quikdown-td">
|
|
250
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.s(...objs)</code></td>
|
|
251
|
+
<td class="quikdown-td">Compose inline style objects into a style string</td>
|
|
252
|
+
</tr>
|
|
253
|
+
<tr class="quikdown-tr">
|
|
254
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.responsive(sel, breakpoints)</code></td>
|
|
255
|
+
<td class="quikdown-td">Generate <code class="quikdown-code">@media</code> CSS rules from JS</td>
|
|
256
|
+
</tr>
|
|
257
|
+
<tr class="quikdown-tr">
|
|
258
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.loadStyles()</code></td>
|
|
259
|
+
<td class="quikdown-td">Inject the built-in stylesheet (or pass config to theme)</td>
|
|
260
|
+
</tr>
|
|
261
|
+
<tr class="quikdown-tr">
|
|
262
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.makeStyles(config)</code></td>
|
|
263
|
+
<td class="quikdown-td">Generate a scoped theme from seed colors (returns styles object)</td>
|
|
182
264
|
</tr>
|
|
183
265
|
<tr class="quikdown-tr">
|
|
184
|
-
<td class="quikdown-td"><code class="quikdown-code">bw.
|
|
185
|
-
<td class="quikdown-td">
|
|
266
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.toggleStyles()</code></td>
|
|
267
|
+
<td class="quikdown-td">Switch between primary and alternate palettes</td>
|
|
186
268
|
</tr>
|
|
187
269
|
<tr class="quikdown-tr">
|
|
188
270
|
<td class="quikdown-td"><code class="quikdown-code">bw.patch(id, content)</code></td>
|
|
@@ -209,17 +291,9 @@ bw.toggleTheme(); // switch between primary and alternate palettes</code></pre>
|
|
|
209
291
|
<td class="quikdown-td">Debug a component in the browser console</td>
|
|
210
292
|
</tr>
|
|
211
293
|
<tr class="quikdown-tr">
|
|
212
|
-
<td class="quikdown-td"><code class="quikdown-code">bw.
|
|
213
|
-
<td class="quikdown-td">Connect to a bwserve SSE endpoint</td>
|
|
214
|
-
</tr>
|
|
215
|
-
<tr class="quikdown-tr">
|
|
216
|
-
<td class="quikdown-td"><code class="quikdown-code">bw.clientApply(msg)</code></td>
|
|
294
|
+
<td class="quikdown-td"><code class="quikdown-code">bw.apply(msg)</code></td>
|
|
217
295
|
<td class="quikdown-td">Apply a bwserve protocol message to the DOM</td>
|
|
218
296
|
</tr>
|
|
219
|
-
<tr class="quikdown-tr">
|
|
220
|
-
<td class="quikdown-td"><code class="quikdown-code">bw.clientParse(str)</code></td>
|
|
221
|
-
<td class="quikdown-td">Parse strict or r-prefix relaxed JSON</td>
|
|
222
|
-
</tr>
|
|
223
297
|
</tbody>
|
|
224
298
|
</table><p>See the full <a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/08-api-reference.html" rel="noopener noreferrer">API Reference</a> for all functions.</p><h2 class="quikdown-h2">CLI</h2>
|
|
225
299
|
<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
|
|
@@ -263,31 +337,44 @@ curl -X POST http://localhost:9000 -d '{"type":"patch",&
|
|
|
263
337
|
</tr>
|
|
264
338
|
</tbody>
|
|
265
339
|
</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>
|
|
266
|
-
<strong class="quikdown-strong">
|
|
340
|
+
<strong class="quikdown-strong">Start here:</strong></p><ul class="quikdown-ul">
|
|
341
|
+
<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. Covers TACO, styling (<code class="quikdown-code">bw.css</code>, <code class="quikdown-code">bw.s</code>, <code class="quikdown-code">bw.responsive</code>), composition, events, the three-level component model, bwserve, and common patterns</li>
|
|
342
|
+
<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. Designed for AI-assisted development but works as a cheat sheet for anyone</li>
|
|
343
|
+
</ul><p><strong class="quikdown-strong">Reference guides</strong> (in <code class="quikdown-code">docs/</code>):</p><ul class="quikdown-ul">
|
|
267
344
|
<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>
|
|
268
345
|
<li class="quikdown-li"><a class="quikdown-a" href="docs/state-management.md">State Management</a> — three-level component model, ComponentHandle, reactive state</li>
|
|
269
346
|
<li class="quikdown-li"><a class="quikdown-a" href="docs/component-library.md">Component Library</a> — all 50+ <code class="quikdown-code">make*()</code> functions with signatures and examples</li>
|
|
270
347
|
<li class="quikdown-li"><a class="quikdown-a" href="docs/theming.md">Theming</a> — palette-driven theme generation, presets, design tokens</li>
|
|
271
348
|
<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>
|
|
272
349
|
<li class="quikdown-li"><a class="quikdown-a" href="docs/bwserve.md">bwserve</a> — server-driven UI protocol (SSE, actions, embedded devices)</li>
|
|
273
|
-
<li class="quikdown-li"><a class="quikdown-a" href="docs/llm-bitwrench-guide.md">LLM Guide</a> — compact single-file reference for AI-assisted development</li>
|
|
274
350
|
</ul><p><strong class="quikdown-strong">Tutorials:</strong></p><ul class="quikdown-ul">
|
|
275
351
|
<li class="quikdown-li"><a class="quikdown-a" href="docs/tutorial-website.md">Build a Website</a> — multi-section landing page from TACO objects</li>
|
|
276
352
|
<li class="quikdown-li"><a class="quikdown-a" href="docs/tutorial-bwserve.md">bwserve Dashboard</a> — Streamlit-style server-push dashboard</li>
|
|
277
353
|
<li class="quikdown-li"><a class="quikdown-a" href="docs/tutorial-embedded.md">ESP32 IoT Dashboard</a> — embedded sensor dashboard with C macros</li>
|
|
278
354
|
</ul><p><strong class="quikdown-strong">Interactive demos</strong> (live site):</p><ul class="quikdown-ul">
|
|
279
355
|
<li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/00-quick-start.html" rel="noopener noreferrer">Quick Start</a> — first steps with <code class="quikdown-code">bw.DOM()</code></li>
|
|
280
|
-
<li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/01-components.html" rel="noopener noreferrer">Components</a> —
|
|
281
|
-
<li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/03-styling.html" rel="noopener noreferrer">Styling & Theming</a> — CSS generation and theming strategies</li>
|
|
356
|
+
<li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/01-components.html" rel="noopener noreferrer">Components</a> — all 50+ UI components with live demos</li>
|
|
357
|
+
<li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/03-styling.html" rel="noopener noreferrer">Styling & Theming</a> — CSS generation, <code class="quikdown-code">bw.s()</code>, and theming strategies</li>
|
|
282
358
|
<li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/05-state.html" rel="noopener noreferrer">State & Interactivity</a> — state patterns and ComponentHandle</li>
|
|
283
359
|
<li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/06-tic-tac-toe-tutorial.html" rel="noopener noreferrer">Tic Tac Toe Tutorial</a> — step-by-step game with state management</li>
|
|
284
360
|
<li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/07-framework-comparison.html" rel="noopener noreferrer">Framework Comparison</a> — bitwrench vs React, Vue, Svelte</li>
|
|
285
361
|
<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>
|
|
286
|
-
</ul><
|
|
362
|
+
</ul><p><strong class="quikdown-strong">Example apps</strong> (in <code class="quikdown-code">examples/</code>):</p><ul class="quikdown-ul">
|
|
363
|
+
<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>
|
|
364
|
+
<li class="quikdown-li"><a class="quikdown-a" href="examples/landing-page/">SunForge Landing Page</a> — polished marketing page with zero reactive state, pure BCCL composition</li>
|
|
365
|
+
<li class="quikdown-li"><a class="quikdown-a" href="examples/todo-app/">Todo App</a> — bw.component() with pub/sub</li>
|
|
366
|
+
<li class="quikdown-li"><a class="quikdown-a" href="examples/dashboard/">Metrics Dashboard</a> — live stat cards, bar chart, pub/sub, responsive layout</li>
|
|
367
|
+
<li class="quikdown-li"><a class="quikdown-a" href="examples/wizard/">Signup Wizard</a> — multi-step form, state transitions, bw.raw()</li>
|
|
368
|
+
<li class="quikdown-li"><a class="quikdown-a" href="examples/live-feed/">Live Feed</a> — real-time stream, bw.patch(), slide-in animation</li>
|
|
369
|
+
<li class="quikdown-li"><a class="quikdown-a" href="examples/embedded/">IoT Dashboard</a> — ESP32-style sensor dashboard with SSE</li>
|
|
370
|
+
<li class="quikdown-li"><a class="quikdown-a" href="examples/client-server/">bwserve Counter</a> — server-driven UI demo</li>
|
|
371
|
+
<li class="quikdown-li"><a class="quikdown-a" href="examples/llm-chat/">LLM Chat</a> — streaming chat via bwserve + Ollama/OpenAI</li>
|
|
372
|
+
</ul><h2 class="quikdown-h2">FAQ</h2>
|
|
373
|
+
<strong class="quikdown-strong">Is this a framework?</strong> — No. Bitwrench is a library (~39KB gzipped). No lifecycle to learn, no project structure to follow. Import it, call functions, done.</p><p><strong class="quikdown-strong">Does it scale to large apps?</strong> — Bitwrench targets single-page tools, dashboards, prototypes, embedded UIs, and content sites — apps where a single HTML file or a handful of files is the right form factor. For a 500-route SPA with team-scale state management, React or Vue is a better fit.</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 — use whichever fits the job.</p><p><strong class="quikdown-strong">How does CSS work?</strong> — Bitwrench doesn't own your CSS. Use any external stylesheet, Tailwind, or CSS file you want — bitwrench doesn't interfere. 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> or <code class="quikdown-code">bw.makeStyles()</code> derives a complete theme from 2 seed colors. You can use all three together or none at all.</p><p><strong class="quikdown-strong">What's the difference between <code class="quikdown-code">bw.DOM()</code> and <code class="quikdown-code">bw.html()</code>?</strong> — Same TACO input, two outputs. <code class="quikdown-code">bw.DOM('#app', taco)</code> mounts live DOM elements in a browser. <code class="quikdown-code">bw.html(taco)</code> returns an HTML string — use it in Node.js scripts, email generators, static site builds, or anywhere you need markup without a browser. One object format, two rendering modes.</p><p><strong class="quikdown-strong">What is bwserve?</strong> — bwserve lets any server push UI updates to a browser over SSE. The server sends TACO objects as JSON; the browser renders them. It's language-agnostic — the server can be Python, Go, Rust, C, or a shell script. Anything that can write JSON to an HTTP response can drive a bitwrench UI. 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 — this is a primary use case. An ESP32 or Raspberry Pi serves one HTML page with bitwrench loaded, then pushes sensor data as JSON patches over SSE. The device never generates HTML. See the <a class="quikdown-a" href="docs/tutorial-embedded.md">ESP32 tutorial</a>.</p><p><strong class="quikdown-strong">Can I use it with TypeScript?</strong> — Yes. Type declarations are included. TACO objects are plain JSON-compatible objects that TypeScript infers naturally.</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>
|
|
287
374
|
<p><pre class="quikdown-pre"><code class="language-bash">npm install # install dev dependencies
|
|
288
375
|
npm run build # build all dist formats (UMD, ESM, CJS, ES5)
|
|
289
376
|
npm test # run unit tests (1000+ tests)
|
|
290
|
-
npm run test:cli # run CLI tests
|
|
377
|
+
npm run test:cli # run CLI tests
|
|
291
378
|
npm run test:e2e # run Playwright browser tests
|
|
292
379
|
npm run lint # run ESLint
|
|
293
380
|
npm run cleanbuild # full production build with SRI hashes</code></pre></p><h2 class="quikdown-h2">License</h2>
|
package/src/bitwrench-bccl.js
CHANGED
|
@@ -327,7 +327,7 @@ export function makeCol(props = {}) {
|
|
|
327
327
|
if (breakpoint === 'xs') {
|
|
328
328
|
classes.push(`bw_col_${value}`);
|
|
329
329
|
} else {
|
|
330
|
-
classes.push(`bw_col_${breakpoint}
|
|
330
|
+
classes.push(`bw_col_${breakpoint}_${value}`);
|
|
331
331
|
}
|
|
332
332
|
});
|
|
333
333
|
} else if (size) {
|
|
@@ -1710,8 +1710,8 @@ export function makePagination(props = {}) {
|
|
|
1710
1710
|
t: 'li',
|
|
1711
1711
|
a: { class: `bw_page_item ${currentPage <= 1 ? 'bw_disabled' : ''}`.trim() },
|
|
1712
1712
|
c: {
|
|
1713
|
-
t: '
|
|
1714
|
-
a: { class: 'bw_page_link',
|
|
1713
|
+
t: 'button',
|
|
1714
|
+
a: { class: 'bw_page_link', type: 'button', onclick: handleClick(currentPage - 1), 'aria-label': 'Previous', disabled: currentPage <= 1 ? true : undefined },
|
|
1715
1715
|
c: '\u2039'
|
|
1716
1716
|
}
|
|
1717
1717
|
});
|
|
@@ -1723,8 +1723,8 @@ export function makePagination(props = {}) {
|
|
|
1723
1723
|
t: 'li',
|
|
1724
1724
|
a: { class: `bw_page_item ${pageNum === currentPage ? 'bw_active' : ''}`.trim() },
|
|
1725
1725
|
c: {
|
|
1726
|
-
t: '
|
|
1727
|
-
a: { class: 'bw_page_link',
|
|
1726
|
+
t: 'button',
|
|
1727
|
+
a: { class: 'bw_page_link', type: 'button', onclick: handleClick(pageNum), 'aria-current': pageNum === currentPage ? 'page' : undefined },
|
|
1728
1728
|
c: '' + pageNum
|
|
1729
1729
|
}
|
|
1730
1730
|
});
|
|
@@ -1736,8 +1736,8 @@ export function makePagination(props = {}) {
|
|
|
1736
1736
|
t: 'li',
|
|
1737
1737
|
a: { class: `bw_page_item ${currentPage >= pages ? 'bw_disabled' : ''}`.trim() },
|
|
1738
1738
|
c: {
|
|
1739
|
-
t: '
|
|
1740
|
-
a: { class: 'bw_page_link',
|
|
1739
|
+
t: 'button',
|
|
1740
|
+
a: { class: 'bw_page_link', type: 'button', onclick: handleClick(currentPage + 1), 'aria-label': 'Next', disabled: currentPage >= pages ? true : undefined },
|
|
1741
1741
|
c: '\u203A'
|
|
1742
1742
|
}
|
|
1743
1743
|
});
|
|
@@ -3610,5 +3610,9 @@ export var BCCL = {
|
|
|
3610
3610
|
export function make(type, props) {
|
|
3611
3611
|
var def = BCCL[type];
|
|
3612
3612
|
if (!def) throw new Error('bw.make: unknown component type "' + type + '". Available: ' + Object.keys(BCCL).join(', '));
|
|
3613
|
-
|
|
3613
|
+
var taco = def.make(props || {});
|
|
3614
|
+
if (taco && typeof taco === 'object') {
|
|
3615
|
+
taco._bwFactory = { type: type, props: props || {} };
|
|
3616
|
+
}
|
|
3617
|
+
return taco;
|
|
3614
3618
|
}
|
|
@@ -289,13 +289,18 @@ export function harmonize(sourceHex, targetHex, amount) {
|
|
|
289
289
|
*/
|
|
290
290
|
export function deriveShades(hex) {
|
|
291
291
|
var rgb = colorParse(hex);
|
|
292
|
+
// For light input colors (L > 75), mixing toward white produces invisible borders.
|
|
293
|
+
// Darken instead so borders remain visible against light backgrounds.
|
|
294
|
+
var borderColor = hexToHsl(hex)[2] > 75
|
|
295
|
+
? adjustLightness(hex, -18)
|
|
296
|
+
: mixColor(hex, '#ffffff', 0.60);
|
|
292
297
|
return {
|
|
293
298
|
base: hex,
|
|
294
299
|
hover: adjustLightness(hex, -10),
|
|
295
300
|
active: adjustLightness(hex, -15),
|
|
296
301
|
light: mixColor(hex, '#ffffff', 0.85),
|
|
297
302
|
darkText: adjustLightness(hex, -40),
|
|
298
|
-
border:
|
|
303
|
+
border: borderColor,
|
|
299
304
|
focus: 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',0.25)',
|
|
300
305
|
textOn: textOnColor(hex)
|
|
301
306
|
};
|
|
@@ -354,19 +359,27 @@ export function deriveAlternateConfig(config) {
|
|
|
354
359
|
alt.secondary = deriveAlternateSeed(config.secondary);
|
|
355
360
|
alt.tertiary = config.tertiary ? deriveAlternateSeed(config.tertiary) : alt.primary;
|
|
356
361
|
|
|
357
|
-
// Derive alternate surface colors from primary hue
|
|
362
|
+
// Derive alternate surface colors from primary hue.
|
|
363
|
+
// Check actual page surface brightness (not seed color brightness) to decide
|
|
364
|
+
// whether alternate should be dark or light. The page surface is what the
|
|
365
|
+
// user sees; seeds can be dark while the page is still light (default L=96).
|
|
358
366
|
var priHsl = hexToHsl(config.primary);
|
|
359
367
|
var h = priHsl[0];
|
|
360
|
-
var
|
|
368
|
+
var primarySurface = config.surface || hslToHex([h, 8, 96]);
|
|
369
|
+
var isLight = relativeLuminance(primarySurface) > 0.179;
|
|
361
370
|
|
|
362
371
|
if (isLight) {
|
|
363
|
-
//
|
|
372
|
+
// Page surface is light → alternate needs dark surfaces
|
|
364
373
|
alt.light = hslToHex([h, Math.min(priHsl[1], 15), 15]);
|
|
365
374
|
alt.dark = hslToHex([h, 5, 88]);
|
|
375
|
+
alt.surface = hslToHex([h, 12, 18]);
|
|
376
|
+
alt.background = hslToHex([h, 10, 14]);
|
|
366
377
|
} else {
|
|
367
|
-
//
|
|
378
|
+
// Page surface is dark → alternate needs light surfaces
|
|
368
379
|
alt.light = hslToHex([h, Math.min(priHsl[1], 10), 96]);
|
|
369
380
|
alt.dark = hslToHex([h, 10, 18]);
|
|
381
|
+
alt.surface = hslToHex([h, 8, 96]);
|
|
382
|
+
alt.background = hslToHex([h, 6, 98]);
|
|
370
383
|
}
|
|
371
384
|
|
|
372
385
|
// Semantic colors: harmonize toward primary, then invert for alternate
|
|
@@ -414,10 +427,18 @@ export function derivePalette(config) {
|
|
|
414
427
|
var darkBase = config.dark || hslToHex([h, 10, 13]);
|
|
415
428
|
|
|
416
429
|
// Background & surface tokens — tinted with primary hue for theme personality.
|
|
417
|
-
//
|
|
430
|
+
// Saturation high enough that the hue is visible (each theme feels distinct)
|
|
431
|
+
// but low enough to stay neutral and readable.
|
|
418
432
|
// User can override with config.background / config.surface.
|
|
419
|
-
var bgBase = config.background || hslToHex([h,
|
|
420
|
-
var surfBase = config.surface || hslToHex([h,
|
|
433
|
+
var bgBase = config.background || hslToHex([h, 22, 96]);
|
|
434
|
+
var surfBase = config.surface || hslToHex([h, 25, 94]);
|
|
435
|
+
|
|
436
|
+
// surfaceAlt: subtle background variant for striped rows, hover states, headers.
|
|
437
|
+
// Slightly lighter than surface in dark mode, slightly darker in light mode.
|
|
438
|
+
var surfHsl = hexToHsl(surfBase);
|
|
439
|
+
var surfAlt = surfHsl[2] <= 50
|
|
440
|
+
? hslToHex([surfHsl[0], surfHsl[1], Math.min(surfHsl[2] + 8, 100)])
|
|
441
|
+
: hslToHex([surfHsl[0], surfHsl[1], Math.max(surfHsl[2] - 3, 0)]);
|
|
421
442
|
|
|
422
443
|
var palette = {
|
|
423
444
|
primary: deriveShades(config.primary),
|
|
@@ -430,7 +451,8 @@ export function derivePalette(config) {
|
|
|
430
451
|
light: deriveShades(lightBase),
|
|
431
452
|
dark: deriveShades(darkBase),
|
|
432
453
|
background: bgBase,
|
|
433
|
-
surface: surfBase
|
|
454
|
+
surface: surfBase,
|
|
455
|
+
surfaceAlt: surfAlt
|
|
434
456
|
};
|
|
435
457
|
|
|
436
458
|
return palette;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// ESM entry point — adds named exports for tree-shaking.
|
|
2
|
+
// Modern bundlers (Vite, webpack, esbuild) can import individual
|
|
3
|
+
// BCCL components without pulling in the entire library:
|
|
4
|
+
//
|
|
5
|
+
// import bw from 'bitwrench'; // full library
|
|
6
|
+
// import { makeCard, makeButton } from 'bitwrench'; // tree-shakeable
|
|
7
|
+
//
|
|
8
|
+
// UMD/CJS builds use bitwrench.js directly (no named exports).
|
|
9
|
+
|
|
10
|
+
export { default } from './bitwrench.js';
|
|
11
|
+
export * from './bitwrench-bccl.js';
|