bitwrench 2.0.17 → 2.0.19

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.
Files changed (72) hide show
  1. package/README.md +169 -75
  2. package/dist/bitwrench-bccl.cjs.js +228 -55
  3. package/dist/bitwrench-bccl.cjs.min.js +3 -3
  4. package/dist/bitwrench-bccl.esm.js +228 -55
  5. package/dist/bitwrench-bccl.esm.min.js +3 -3
  6. package/dist/bitwrench-bccl.umd.js +228 -55
  7. package/dist/bitwrench-bccl.umd.min.js +3 -3
  8. package/dist/bitwrench-code-edit.cjs.js +7 -9
  9. package/dist/bitwrench-code-edit.cjs.min.js +5 -7
  10. package/dist/bitwrench-code-edit.es5.js +6 -8
  11. package/dist/bitwrench-code-edit.es5.min.js +5 -7
  12. package/dist/bitwrench-code-edit.esm.js +7 -9
  13. package/dist/bitwrench-code-edit.esm.min.js +5 -7
  14. package/dist/bitwrench-code-edit.umd.js +7 -9
  15. package/dist/bitwrench-code-edit.umd.min.js +5 -7
  16. package/dist/bitwrench-debug.js +268 -0
  17. package/dist/bitwrench-debug.min.js +3 -0
  18. package/dist/bitwrench-lean.cjs.js +1190 -2348
  19. package/dist/bitwrench-lean.cjs.min.js +20 -20
  20. package/dist/bitwrench-lean.es5.js +1285 -2551
  21. package/dist/bitwrench-lean.es5.min.js +18 -18
  22. package/dist/bitwrench-lean.esm.js +1190 -2348
  23. package/dist/bitwrench-lean.esm.min.js +20 -20
  24. package/dist/bitwrench-lean.umd.js +1190 -2348
  25. package/dist/bitwrench-lean.umd.min.js +20 -20
  26. package/dist/bitwrench-util-css.cjs.js +236 -0
  27. package/dist/bitwrench-util-css.cjs.min.js +22 -0
  28. package/dist/bitwrench-util-css.es5.js +414 -0
  29. package/dist/bitwrench-util-css.es5.min.js +21 -0
  30. package/dist/bitwrench-util-css.esm.js +230 -0
  31. package/dist/bitwrench-util-css.esm.min.js +21 -0
  32. package/dist/bitwrench-util-css.umd.js +242 -0
  33. package/dist/bitwrench-util-css.umd.min.js +21 -0
  34. package/dist/bitwrench.cjs.js +1404 -2388
  35. package/dist/bitwrench.cjs.min.js +21 -21
  36. package/dist/bitwrench.css +503 -132
  37. package/dist/bitwrench.es5.js +1588 -2659
  38. package/dist/bitwrench.es5.min.js +19 -19
  39. package/dist/bitwrench.esm.js +1405 -2389
  40. package/dist/bitwrench.esm.min.js +21 -21
  41. package/dist/bitwrench.min.css +1 -1
  42. package/dist/bitwrench.umd.js +1404 -2388
  43. package/dist/bitwrench.umd.min.js +21 -21
  44. package/dist/builds.json +214 -104
  45. package/dist/bwserve.cjs.js +514 -68
  46. package/dist/bwserve.esm.js +513 -69
  47. package/dist/sri.json +46 -36
  48. package/package.json +6 -3
  49. package/readme.html +183 -85
  50. package/src/bitwrench-bccl-entry.js +3 -4
  51. package/src/bitwrench-bccl.js +224 -50
  52. package/src/bitwrench-code-edit.js +6 -8
  53. package/src/bitwrench-color-utils.js +31 -9
  54. package/src/bitwrench-debug.js +245 -0
  55. package/src/bitwrench-esm-entry.js +11 -0
  56. package/src/bitwrench-styles.js +474 -240
  57. package/src/bitwrench-util-css.js +229 -0
  58. package/src/bitwrench.js +689 -2042
  59. package/src/bwserve/attach.js +57 -0
  60. package/src/bwserve/bwclient.js +141 -0
  61. package/src/bwserve/bwshell.js +102 -0
  62. package/src/bwserve/client.js +151 -1
  63. package/src/bwserve/index.js +127 -28
  64. package/src/cli/attach.js +587 -0
  65. package/src/cli/convert.js +2 -5
  66. package/src/cli/index.js +7 -0
  67. package/src/cli/inject.js +1 -1
  68. package/src/cli/serve.js +185 -5
  69. package/src/generate-css.js +11 -4
  70. package/src/vendor/html2canvas.min.js +20 -0
  71. package/src/version.js +3 -3
  72. package/src/bwserve/shell.js +0 -106
package/dist/sri.json CHANGED
@@ -1,41 +1,51 @@
1
1
  {
2
- "version": "2.0.17",
2
+ "version": "2.0.19",
3
3
  "algorithm": "sha384",
4
- "generated": "2026-03-13",
4
+ "generated": "2026-03-22",
5
5
  "files": {
6
- "bitwrench-bccl.cjs.js": "sha384-JtHrGKdL2R+Np/4hJCUnnKa+gVhO1HMojkcUDQsnX4iyyf/CVq4SaTuCWQyz1q1q",
7
- "bitwrench-bccl.cjs.min.js": "sha384-gKYoqvlm7yhCh7//O/fkRZtdC6X2j7+cTrl85bAj6fNfB8DnZqvhqnXGPdKSthF7",
8
- "bitwrench-bccl.esm.js": "sha384-go+h+i6cxCy1JnOTEQ3ukm9RCf5KwBInhSnofh++ktdhKAfqoWmB766VseRGCtXY",
9
- "bitwrench-bccl.esm.min.js": "sha384-zt2eb/zS5QAotiywhp3nZXmxwBRR4rb4R8A8mKo0IpZIXL3tWYTwSrr87k+aUOa5",
10
- "bitwrench-bccl.umd.js": "sha384-85C9Wud5azObw2tgX7KVS0zOo/+GhNSYldFZehW5f917xe86WR6ai28Yqb2bV7BG",
11
- "bitwrench-bccl.umd.min.js": "sha384-MnURAnFgYO7gpv2AD/nSra7oCppx/LaeWr7Zhn++o66Grw+tfBcIjmbmTBzR8suQ",
12
- "bitwrench-code-edit.cjs.js": "sha384-pYMU67JSAuOzmvDIptwgJU9l1ATHRZVIKYIbmJtxJJiwmbTBF023aYxNYuU2kCFh",
13
- "bitwrench-code-edit.cjs.min.js": "sha384-gyKZwcVfwGq+oJdbhzOrjROdtQUW9GR+m1iU69kh+ybPZ+OzSAH7cOx1Z3Cib0EM",
14
- "bitwrench-code-edit.es5.js": "sha384-i6eXPifX0VPfeKo4jI1JYD26PQJh2HxtDQblAFeeFC0k5y8jmOgLKtk86UPT14vs",
15
- "bitwrench-code-edit.es5.min.js": "sha384-I2r5vCUHcQT/UqKdbMqLk5uhc7rqBKhP4qJzoItEHBcuLFdzMbfRrTj5l3lk15QJ",
16
- "bitwrench-code-edit.esm.js": "sha384-CVdqruuHB4k6wehD26cio10tl8xCcQfdQmdMWlDuYFYF3R2re7ZjTZClz1TAvxlb",
17
- "bitwrench-code-edit.esm.min.js": "sha384-kKtUe03iCRXxIV1bpLffhl1apf8JJeteXVSdfM2HS9HyKkvf5uiFN96CC2VzFt24",
18
- "bitwrench-code-edit.umd.js": "sha384-qzPZG4wK/7oBf+uXwbUBNNRA9zuOsxChJXXipoZBg8gt51e/uhmkiD5jVBDsXPNF",
19
- "bitwrench-code-edit.umd.min.js": "sha384-zEBjo8SgTdGymQQwRYva/iW2iCUjT0Tdtocik63xi00qE88OEFl8kejj5KCrxCNc",
20
- "bitwrench-lean.cjs.js": "sha384-XP0qyS4rfU2MUK93n0zgpIhOMjyTxEqMtTrErOopcsDRuYIsY0b4zeS/wa+6GEJn",
21
- "bitwrench-lean.cjs.min.js": "sha384-Aep5GOW8Qu0H5ZDbMXna4ku9QQQgrAAfpJFMBiRHY+XuglwZooFfgSTezhR1eftj",
22
- "bitwrench-lean.es5.js": "sha384-bkwm+dTlJQ/DyPOz04TVSpDd0UqdCY7B6/y01N/P9pAnTlx/S94mkm8TQfzQW+gy",
23
- "bitwrench-lean.es5.min.js": "sha384-+JD7oSIx3Gl1wsUNWXeSZqBz1mOLcjpI+ScQR1d0oFyhf62zyyWSl02KhC1vO46m",
24
- "bitwrench-lean.esm.js": "sha384-5lIJxbMwgIeJnNk9yNMvUf7PnIdt4e6b1QzQD3psRv46xDLDcTFRxXA1rloyAY1i",
25
- "bitwrench-lean.esm.min.js": "sha384-XLQK7n6rfH6mXKYJFWi0TlwDyE20YyzGtkuFffQRwKCLD7yMn1ZAHxQxwKP1MvuW",
26
- "bitwrench-lean.umd.js": "sha384-HHotDwMh/Ipq3JcDJzr2anOJcLynPS8XBJkPFsbUOz+Irbwd1LyEYZ7HkUCgmrJu",
27
- "bitwrench-lean.umd.min.js": "sha384-G18BfqAXGt/2VzZ0oCTxpdZZSh/eriVzz8xlf0MxFrEDfj6NWLWn6Rqp9pHEtyHf",
28
- "bitwrench.cjs.js": "sha384-TjEj7ETG/CylzHHnyc3dbxjJ9A8CXoaCouPzBpdex/u6wU68YayPG+yXyt+Jcg83",
29
- "bitwrench.cjs.min.js": "sha384-w1Gl0tTOOSMBqXYVAKMudrFfXJ+nNf5va7q5GEPKMYtxVQQyDpDP4yL9+/uyZtTW",
30
- "bitwrench.css": "sha384-TLf4tWABJynZ7cb9epG9VhRM1IvuK5k4VD5wHE2esbGXcuKzG6iArqimHPzZDLD2",
31
- "bitwrench.es5.js": "sha384-FE2hzUIF9en6TGljWhEr1vKvofcNSLQJsjU6XlDiezwG3DgJgDKIafuSDu00NWfK",
32
- "bitwrench.es5.min.js": "sha384-c3gOIHjeEUGSVtcv6M1N6KmGoWuOUz3H8hGbcIOh90dIZY7Xflx2SLdSaSl5yRWJ",
33
- "bitwrench.esm.js": "sha384-08iatqu6LAtx8cZsgXkE34sK7FvN99nn+wXNx0YEEMMRuGRRq35uATUNKv7FcO5U",
34
- "bitwrench.esm.min.js": "sha384-S/DNxHQzWvbbrszBTs9wc78m7NnO6Ml7iw18/V5mki40a7WKfckhLGmsFMKfQw+N",
35
- "bitwrench.min.css": "sha384-Sl7+BxWfINNnNdN+ZCL1s/p4Hn+5WeJPciWS9svNuzal8h9baX19xGeOJNzradRY",
36
- "bitwrench.umd.js": "sha384-8nLO+4nHEnvnbslfteLo04OfUqDTZcB/Q5uelctfeIuPU2MXP02BO3iE4Jsz3Bp5",
37
- "bitwrench.umd.min.js": "sha384-y+l0IvKb1/9dBiradZkR1Alh6o0KtJgrkupdlYVLw/x4By7+tNtJcSu5D7N5u4IE",
38
- "bwserve.cjs.js": "sha384-ShnkqIcaohORoeDTsw/KEij2kTbtuj6dFtZExUgLJdvgy3hWmHWVpktT9jhUczTg",
39
- "bwserve.esm.js": "sha384-Je3FPrcpT8TjizTUMW3tzlRgmJxKnLFabVV+eaCfZRnPDx5uJVARuS+TEXbnrWWt"
6
+ "bitwrench-bccl.cjs.js": "sha384-tU0kR6yE/u3qmVJF+fIubtL7W97PNaKveGiJMiIg73RTCUeV2d93+FZUeJJwbKeR",
7
+ "bitwrench-bccl.cjs.min.js": "sha384-KfaZ24lp6M/jMwVaZEvEn+OfZMD6op4JD/XzQr101IxcmXRMgU/3roJIEdabeOis",
8
+ "bitwrench-bccl.esm.js": "sha384-JflWSggVZ/DjXRtKAFpg3if7XkqGopeWIReqNpw78ykaS4QR37QSUF8UAH7tyJyg",
9
+ "bitwrench-bccl.esm.min.js": "sha384-ONbJiMmnhDvgv9LF81dsAOq7bOZ2FGvis4I+MUTpreFgZf5FY2Mv37tF+u8htIux",
10
+ "bitwrench-bccl.umd.js": "sha384-yX7TO/3TkBjjDoiRDcl/ImWorC70Ehxu+MdN1T5AH9K0zOEWUuF+6IbH99gESZu5",
11
+ "bitwrench-bccl.umd.min.js": "sha384-6UumjIdVjj8wm4sowabrDkqzc4uEuwezO0jeUaiK77++l51ih/22hS223HngMfYL",
12
+ "bitwrench-code-edit.cjs.js": "sha384-GHgg57SlYc4996n7w5j1RGcrq/XWw7HF0F0XXjaaTKi4IO1hIlZwcXW2tsqrjdq7",
13
+ "bitwrench-code-edit.cjs.min.js": "sha384-Gv1FU+M69IecIaQ/igevIBoqHB4PpeMY6/Bl2jyqTxQorKy9KvqTuGw2FB0E92Cc",
14
+ "bitwrench-code-edit.es5.js": "sha384-ujeo++ERLhCkk99i1x6GI9Jr1oq+/ZLlCQzt8y6s9w8J/Q9l7/s8rv1Vz3GeFGba",
15
+ "bitwrench-code-edit.es5.min.js": "sha384-ZQ8Vyp+ExE4clA7ifFhlgvyIAgnM7z7S7R/+XRiMR2Q8yyHTSUMYmKEAPusFhNF5",
16
+ "bitwrench-code-edit.esm.js": "sha384-6UTzDNd4crnmo4Ld1tOkxYEjFDKOtJb+7Teve02AX3n4seXORDnlX2Y4RFsfzoWD",
17
+ "bitwrench-code-edit.esm.min.js": "sha384-jiAOgUaRDsVj9pfdaRN/RIXrX916PtBXF5BqUJE4Ry3uVfhFOcOiRGPyA86riyJR",
18
+ "bitwrench-code-edit.umd.js": "sha384-xdQu8xl0kRbbBLzYXnHnv/QKx3bzWy4PvK0f2RG19wMDMS8tf1t2gzmLIDqShPh7",
19
+ "bitwrench-code-edit.umd.min.js": "sha384-8ZTHYUf23cc53on2HtJJHHoZuX+1yXceZCtCFGNKUhmh5PjTVxOT294e1SzSpr86",
20
+ "bitwrench-debug.js": "sha384-neWYtWf9EtBqAQ9/cPEMqD571dGQUGkw9Lt5eaowjIZaAbt11iwjUVJvhW9LsO9Q",
21
+ "bitwrench-debug.min.js": "sha384-XqGyvUcX0ZvxhXNQXrFpgYLRqAQimS2r2qX+YQzoT84TFhiIs7Qp8mxGVoBwjpyg",
22
+ "bitwrench-lean.cjs.js": "sha384-Kg93DwvfM8hR1S9WtTHoH+EFe+QVZXYJfh51wb94CDjDlz2ICUJKXpr5vCg3hGel",
23
+ "bitwrench-lean.cjs.min.js": "sha384-7ZxV5q0ctUGPNf5BrKagV1Z68Ton0RX9uveQqtUVi1LcwS3aogdYGptcUkh2Aj9r",
24
+ "bitwrench-lean.es5.js": "sha384-Gin1VqdtYyyYjKo5FPT4cgtckU+58IaEsidMRUXLEsA9M3YMf0fzSy+g8WSXh9PO",
25
+ "bitwrench-lean.es5.min.js": "sha384-UWrbdhA7gtrdC+pWKwip1maiSpE/LHKteaiFbJUYaD2ykJxaSv61VPzgE6LDwNCJ",
26
+ "bitwrench-lean.esm.js": "sha384-5vW+YpC4mNT9yt6TQqejl6VwNuK9SKcDTnWtPUe+j6MOROQWDajcJt6LsHM8Autz",
27
+ "bitwrench-lean.esm.min.js": "sha384-Saptfscrnk972hQwdcKn2dR91XxlbVU07fAa7nd3heO7GUorrYWZPAuPs//oAU4U",
28
+ "bitwrench-lean.umd.js": "sha384-ZYBAIjnRhx0DkTN4wwTGv/amPB+5AtaOlpLuoss3+bog6HqU2huJdLOjNTBYXTCJ",
29
+ "bitwrench-lean.umd.min.js": "sha384-Vz3fKgDKXX+dtuo1nh+u/InW8lVO52kB6Jhdlv78sYIv0/djitGOn4AmO5n0q03J",
30
+ "bitwrench-util-css.cjs.js": "sha384-1yv6Ss9ZZmqE9ZNPxsvwMa7cXDIRbRDtb0AZMJVQFvLGg7MhQw+2JFGT6J9vEG1y",
31
+ "bitwrench-util-css.cjs.min.js": "sha384-HxVa2HmqGQRu+S6JXtdhMw+vl+Q3s9dyn2nFej7UIF0kZGiX52fnqpwcRIi3TGbS",
32
+ "bitwrench-util-css.es5.js": "sha384-FcYTUpIOmpKxWH6BwDJajnDSPTLbG6png6hv0BzoQ4UCiM2Md7xXl2jkiY03mxIW",
33
+ "bitwrench-util-css.es5.min.js": "sha384-TKVgDvkvqi6UrtOoAaP0rtRNDgf/jchW5I0jLOy7RY8eo8mzilF73L3WxI3LR70x",
34
+ "bitwrench-util-css.esm.js": "sha384-JH6kfqLkfdP3V5u9agouomOUxImhCR2NGn+yPv4Qoma9n3xTzHCAGvo0Zn/zGhS4",
35
+ "bitwrench-util-css.esm.min.js": "sha384-gDSnSPpcskWjQkWL7BZPfgw2Rwz1U9wqc7qjhTFt45S8UNi31mDpCIX5GxFJyJWJ",
36
+ "bitwrench-util-css.umd.js": "sha384-2MM7bwF6NRmNBOYgVGCi2CQQoaix2QXPf9mrHOWOI2DJoxty5SWbu68jNPGwgHBv",
37
+ "bitwrench-util-css.umd.min.js": "sha384-MO5Qrn6aji1Vy6zXeWI/82y47v6hic514JTDUURjmEglnbvZWorOxyUPnnxeaGzw",
38
+ "bitwrench.cjs.js": "sha384-PiVAkba6SrlpTgeLJpgOw+V4iF5UMszH56kVngSA5gii28+82t3cuyW5XQRaycHf",
39
+ "bitwrench.cjs.min.js": "sha384-VO0c3YbkPcWu+WNqswic0wxc1KQ6+7BRfEowfVqxCQxqpVEowevPZUzBgFWZwrrL",
40
+ "bitwrench.css": "sha384-+8yiBHrjrRWTcZ8t8GIyrhylqC/nvQk2z2xUGoQAv63ZRN8zesrYHErqK5UwlN+g",
41
+ "bitwrench.es5.js": "sha384-W2As3FMDb4ZOYDmB2BEUEN4RdwroK/4U4+cz2pa1p6/A9veR2U/5j7CYopzqXt1M",
42
+ "bitwrench.es5.min.js": "sha384-mNEUUvz7AVxzZ2sU/WtvMGkDfEKqgfhCP4DybyYMPBgrgEZc54+t9vs/67vzuCmu",
43
+ "bitwrench.esm.js": "sha384-Rrty92szmiFnNw58C2BmWWkrcBGmHyQ4uiQvxpMm6mPgi3ilfAwlOUzjaFVU3YUB",
44
+ "bitwrench.esm.min.js": "sha384-Ao2D8CxHN70fNzVPFKhgl/fSBD+hoYQxulZRAq/IXhEEJzjpJnv2HV9QF/sHaUsd",
45
+ "bitwrench.min.css": "sha384-gY4lHVKePTqTes9lnWPKs6xhVgqj+GgyW6I3d+6idz0CDioCnNVdqf7ffsvWViHf",
46
+ "bitwrench.umd.js": "sha384-0ozr4VOgCnrIcz/Oqll30CmzbBONL26x6EREo8w6gnIhgvrAXyvdIBm64zczZLmN",
47
+ "bitwrench.umd.min.js": "sha384-tHfp09enPr7Knehnhp3KnI84Li3knJJP/JkFPXLJbdpbWEfdR+qV7X645Bq3xl/A",
48
+ "bwserve.cjs.js": "sha384-9HtLsWSWrJLoYL3LWEoMn4fx6mS3dQcoO+Zsd4nURriDJzFFpWBcpRrMYlYGRrFp",
49
+ "bwserve.esm.js": "sha384-VBS3sQM1VeYSZwojK/fz1uoFbc6Uhz9bJB+rQ1zjocozpP739kBI1R7WBgCURNov"
40
50
  }
41
51
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitwrench",
3
- "version": "2.0.17",
3
+ "version": "2.0.19",
4
4
  "description": "A library for javascript UI functions.",
5
5
  "main": "./dist/bitwrench.umd.js",
6
6
  "repository": {
@@ -87,7 +87,7 @@
87
87
  "scripts": {
88
88
  "generate-version": "node tools/generate-version.cjs",
89
89
  "prebuild": "npm run generate-version && npm run lint",
90
- "build": "rollup --config && npm run build:css && npm run build:metrics",
90
+ "build": "rollup --config && npm run build:css && npm run build:metrics && npm run build:builds",
91
91
  "build:css": "node src/generate-css.js",
92
92
  "build:readme": "node tools/build-readme.js",
93
93
  "build:watch": "rollup --config --watch",
@@ -95,8 +95,10 @@
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 ./test/bitwrench_test_code_edit.js ./test/bitwrench_test_html_page.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_coverage_gaps.js ./test/bitwrench_test_bwserve.js ./test/bitwrench_test_attach.js ./test/bitwrench_test_serve.js ./test/bitwrench_test_code_edit.js ./test/bitwrench_test_html_page.js ./test/bitwrench_test_util_css.js ./test/bitwrench_test_handle.js ./test/bitwrench_test_debug.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",
101
+ "test:serve": "mocha ./test/bitwrench_test_serve.js -r jsdom-global/register --exit",
100
102
  "test:components": "mocha ./test/bitwrench_test_components.js -r jsdom-global/register",
101
103
  "test:v1": "c8 --reporter=text mocha ./test/bitwrench_test.js -r jsdom-global/",
102
104
  "test:pending": "mocha ./test/bitwrench_test_pending.js -r jsdom-global/",
@@ -111,6 +113,7 @@
111
113
  "generate-sri": "node tools/generate-sri.js",
112
114
  "test:nodemap": "mocha ./test/bitwrench_test_nodemap.js -r jsdom-global/register",
113
115
  "test:cli": "mocha ./test/bitwrench_test_cli.js",
116
+ "test:debug": "mocha ./test/bitwrench_test_debug.js -r jsdom-global/register",
114
117
  "test:code-edit": "mocha ./test/bitwrench_test_code_edit.js -r jsdom-global/register",
115
118
  "test:html-page": "mocha ./test/bitwrench_test_html_page.js -r jsdom-global/register",
116
119
  "test:e2e": "playwright test",
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.17">
6
+ <meta name="generator" content="bitwrench v2.0.19">
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
- <link rel="stylesheet" href="dist/bitwrench.css">
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,85 @@
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 is a UI library in a single script that provides HTML generation, reactive state, CSS and theme generation, 30+ components, and a static site CLI — all from plain JavaScript objects, with zero dependencies and zero compile steps. Works in browsers (including IE11) and Node.js.</p><h2 class="quikdown-h2">Quick Example</h2>
76
- <p><pre class="quikdown-pre"><code class="language-javascript">const card = {
77
- t: &#39;div&#39;, a: { class: &#39;bw-card&#39; },
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>
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-96.3%25-brightgreen.svg" alt="Coverage"></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.</p><pre class="quikdown-pre"><code class="language-javascript">// Describe UI as a JavaScript object (a &quot;TACO&quot;)
76
+ var page = {
77
+ t: &#39;div&#39;, a: { class: &#39;card&#39; },
78
78
  c: [
79
- { t: &#39;h3&#39;, c: &#39;Hello bitwrench&#39; },
80
- { t: &#39;p&#39;, c: &#39;UI as native JavaScript objects.&#39; }
79
+ { t: &#39;h2&#39;, c: &#39;Hello&#39; },
80
+ { t: &#39;p&#39;, c: &#39;UI as native JavaScript objects.&#39; },
81
+ bw.makeButton({ text: &#39;Click me&#39;, variant: &#39;primary&#39;, onclick: fn })
81
82
  ]
82
83
  };
83
84
 
84
- // Mount to the DOM
85
- bw.DOM(&#39;#app&#39;, card);
86
-
87
- // Or render to an HTML string (Node.js, emails, static pages)
88
- const html = bw.html(card);</code></pre></p><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), and optionally <strong class="quikdown-strong">o</strong> (options for state and lifecycle). Nest them, loop them, compose them — it&#39;s just JavaScript.</p><h2 class="quikdown-h2">Installation</h2>
85
+ bw.DOM(&#39;#app&#39;, page); // -&gt; live DOM
86
+ bw.html(page); // -&gt; 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&#39;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>
87
+ <strong class="quikdown-strong">One file, everywhere.</strong> At ~38KB 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">&lt;script&gt;</code> tag</li>
89
+ <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>
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; <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">Utilities</strong> -- color interpolation, random data, lorem ipsum, cookies, URL params, file I/O</li>
96
+ </ul><h3 class="quikdown-h3">Coming from other Frameworks</h3>
97
+ <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">
98
+ <thead class="quikdown-thead">
99
+ <tr class="quikdown-tr">
100
+ <th class="quikdown-th">You&#39;re using</th>
101
+ <th class="quikdown-th">For</th>
102
+ <th class="quikdown-th">Bitwrench equivalent</th>
103
+ </tr>
104
+ </thead>
105
+ <tbody class="quikdown-tbody">
106
+ <tr class="quikdown-tr">
107
+ <td class="quikdown-td">React / Vue / Svelte</td>
108
+ <td class="quikdown-td">Components + reactivity</td>
109
+ <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>
110
+ </tr>
111
+ <tr class="quikdown-tr">
112
+ <td class="quikdown-td">JSX / templates</td>
113
+ <td class="quikdown-td">Markup-in-JS</td>
114
+ <td class="quikdown-td">Native JS objects -- no compiler</td>
115
+ </tr>
116
+ <tr class="quikdown-tr">
117
+ <td class="quikdown-td">Tailwind / CSS-in-JS</td>
118
+ <td class="quikdown-td">Styling</td>
119
+ <td class="quikdown-td"><code class="quikdown-code">bw.css()</code>, <code class="quikdown-code">bw.s()</code> style composition</td>
120
+ </tr>
121
+ <tr class="quikdown-tr">
122
+ <td class="quikdown-td">Sass / PostCSS</td>
123
+ <td class="quikdown-td">CSS generation</td>
124
+ <td class="quikdown-td"><code class="quikdown-code">bw.css()</code> from JS objects (supports @media, @keyframes)</td>
125
+ </tr>
126
+ <tr class="quikdown-tr">
127
+ <td class="quikdown-td">ThemeProvider / CSS vars</td>
128
+ <td class="quikdown-td">Theming</td>
129
+ <td class="quikdown-td"><code class="quikdown-code">bw.loadStyles()</code> / <code class="quikdown-code">bw.makeStyles()</code> from 2 seed colors</td>
130
+ </tr>
131
+ <tr class="quikdown-tr">
132
+ <td class="quikdown-td">Streamlit / Gradio</td>
133
+ <td class="quikdown-td">Server-driven UI</td>
134
+ <td class="quikdown-td">bwserve SSE -- from any language (Python, Go, C, Rust)</td>
135
+ </tr>
136
+ <tr class="quikdown-tr">
137
+ <td class="quikdown-td">Redux / Zustand / Pinia</td>
138
+ <td class="quikdown-td">State management</td>
139
+ <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>
140
+ </tr>
141
+ <tr class="quikdown-tr">
142
+ <td class="quikdown-td">Vite / webpack / Babel</td>
143
+ <td class="quikdown-td">Build tooling</td>
144
+ <td class="quikdown-td">Not needed -- open the HTML file</td>
145
+ </tr>
146
+ </tbody>
147
+ </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
148
  <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
149
  import bw from &#39;bitwrench&#39;;
91
150
 
92
151
  // CommonJS
93
- const bw = require(&#39;bitwrench&#39;);</code></pre><p>Or include directly in a page:</p><pre class="quikdown-pre"><code class="language-html">&lt;script src=&quot;https://cdn.jsdelivr.net/npm/bitwrench/dist/bitwrench.umd.min.js&quot;&gt;&lt;/script&gt;</code></pre><h2 class="quikdown-h2">Features</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>
152
+ const bw = require(&#39;bitwrench&#39;);</code></pre><p>Or include directly in a page:</p><pre class="quikdown-pre"><code class="language-html">&lt;script src=&quot;https://cdn.jsdelivr.net/npm/bitwrench/dist/bitwrench.umd.min.js&quot;&gt;&lt;/script&gt;</code></pre><h2 class="quikdown-h2">Getting Started</h2>
103
153
  <p><pre class="quikdown-pre"><code class="language-html">&lt;!DOCTYPE html&gt;
104
154
  &lt;html lang=&quot;en&quot;&gt;
105
155
  &lt;head&gt;
@@ -108,7 +158,7 @@ const bw = require(&#39;bitwrench&#39;);</code></pre><p>Or include directly in a
108
158
  &lt;body&gt;
109
159
  &lt;div id=&quot;app&quot;&gt;&lt;/div&gt;
110
160
  &lt;script&gt;
111
- bw.loadDefaultStyles();
161
+ bw.loadStyles();
112
162
 
113
163
  bw.DOM(&#39;#app&#39;, {
114
164
  t: &#39;div&#39;, a: { class: &#39;bw-container&#39; },
@@ -118,40 +168,59 @@ const bw = require(&#39;bitwrench&#39;);</code></pre><p>Or include directly in a
118
168
  title: &#39;Welcome&#39;,
119
169
  content: &#39;Built with plain JavaScript objects.&#39;
120
170
  }),
121
- bw.makeButton({ text: &#39;Click me&#39;, variant: &#39;primary&#39; })
171
+ bw.makeButton({
172
+ text: &#39;Click me&#39;,
173
+ variant: &#39;primary&#39;,
174
+ onclick: function() { alert(&#39;Hello!&#39;); }
175
+ })
122
176
  ]
123
177
  });
124
178
  &lt;/script&gt;
125
179
  &lt;/body&gt;
126
180
  &lt;/html&gt;</code></pre></p><h2 class="quikdown-h2">Adding State</h2>
127
- <p>Wrap any TACO in <code class="quikdown-code">bw.component()</code> to get a reactive component with <code class="quikdown-code">.get()</code>, <code class="quikdown-code">.set()</code>, and template bindings:</p><pre class="quikdown-pre"><code class="language-javascript">var counter = bw.component({
128
- t: &#39;div&#39;, c: [
129
- { t: &#39;span&#39;, c: &#39;Count: ${count}&#39; },
130
- { t: &#39;button&#39;, c: &#39;+1&#39;, a: {
131
- onclick: function() { counter.set(&#39;count&#39;, counter.get(&#39;count&#39;) + 1); }
132
- }}
133
- ],
181
+ <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 is called with the DOM element, and state lives on <code class="quikdown-code">el._bw_state</code>. Call <code class="quikdown-code">bw.update(el)</code> to re-render:</p><pre class="quikdown-pre"><code class="language-javascript">var counter = {
182
+ t: &#39;div&#39;,
134
183
  o: {
135
184
  state: { count: 0 },
136
- methods: {
137
- reset: function(comp) { comp.set(&#39;count&#39;, 0); }
185
+ render: function(el) {
186
+ var s = el._bw_state;
187
+ bw.DOM(el, {
188
+ t: &#39;div&#39;, c: [
189
+ { t: &#39;h3&#39;, c: &#39;Count: &#39; + s.count },
190
+ bw.makeButton({ text: &#39;+1&#39;, onclick: function() {
191
+ s.count++;
192
+ bw.update(el);
193
+ }})
194
+ ]
195
+ });
138
196
  }
139
197
  }
140
- });
198
+ };
141
199
 
142
- bw.DOM(&#39;#app&#39;, counter);
143
- counter.set(&#39;count&#39;, 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(&#39;item-added&#39;, function(detail) {
200
+ bw.DOM(&#39;#app&#39;, counter);</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>See the <a class="quikdown-a" href="docs/state-management.md">State Management guide</a> for the full three-level component model.</p><p>For communication between components, use pub/sub:</p><pre class="quikdown-pre"><code class="language-javascript">bw.sub(&#39;item-added&#39;, function(detail) {
145
201
  console.log(&#39;New item:&#39;, detail.name);
146
202
  });
147
203
 
148
- bw.pub(&#39;item-added&#39;, { name: &#39;Widget&#39; });</code></pre><h2 class="quikdown-h2">Theming</h2>
149
- <p>Generate a complete theme from two seed colors. All components buttons, alerts, badges, cards, forms, tables — are styled automatically:</p><pre class="quikdown-pre"><code class="language-javascript">bw.generateTheme(&#39;my-theme&#39;, {
204
+ bw.pub(&#39;item-added&#39;, { name: &#39;Widget&#39; });</code></pre><h2 class="quikdown-h2">CSS from JavaScript</h2>
205
+ <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
206
+ bw.injectCSS(bw.css({
207
+ &#39;.my-card&#39;: { padding: &#39;1rem&#39;, borderRadius: &#39;8px&#39; }
208
+ }));
209
+
210
+ // Compose inline styles from objects
211
+ { t: &#39;div&#39;, a: { style: bw.s({ display: &#39;flex&#39; }, { gap: &#39;1rem&#39; }, { padding: &#39;1rem&#39; }) } }
212
+
213
+ // Responsive breakpoints
214
+ bw.responsive(&#39;.hero&#39;, {
215
+ base: { fontSize: &#39;1.5rem&#39; },
216
+ md: { fontSize: &#39;2.5rem&#39; }
217
+ });</code></pre><h2 class="quikdown-h2">Theming</h2>
218
+ <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. Styles can be scoped to DOM subtrees, so different sections of a page can use different themes. <code class="quikdown-code">bw.toggleStyles()</code> switches between primary and alternate palettes:</p><pre class="quikdown-pre"><code class="language-javascript">bw.loadStyles({
150
219
  primary: &#39;#336699&#39;,
151
220
  secondary: &#39;#cc6633&#39;
152
221
  });
153
222
 
154
- bw.toggleTheme(); // switch between primary and alternate palettes</code></pre><h2 class="quikdown-h2">Core API</h2>
223
+ bw.toggleStyles(); // switch between primary and alternate palettes</code></pre><h2 class="quikdown-h2">Core API</h2>
155
224
  <table class="quikdown-table">
156
225
  <thead class="quikdown-thead">
157
226
  <tr class="quikdown-tr">
@@ -162,31 +231,55 @@ bw.toggleTheme(); // switch between primary and alternate palettes</code></pre>
162
231
  <tbody class="quikdown-tbody">
163
232
  <tr class="quikdown-tr">
164
233
  <td class="quikdown-td"><code class="quikdown-code">bw.html(obj)</code></td>
165
- <td class="quikdown-td">Convert an object to an HTML string</td>
234
+ <td class="quikdown-td">Convert a TACO to an HTML string</td>
166
235
  </tr>
167
236
  <tr class="quikdown-tr">
168
237
  <td class="quikdown-td"><code class="quikdown-code">bw.DOM(selector, obj)</code></td>
169
- <td class="quikdown-td">Mount an object to a DOM element</td>
238
+ <td class="quikdown-td">Mount a TACO to a DOM element</td>
170
239
  </tr>
171
240
  <tr class="quikdown-tr">
172
- <td class="quikdown-td"><code class="quikdown-code">bw.component(taco)</code></td>
173
- <td class="quikdown-td">Wrap a TACO in a ComponentHandle with <code class="quikdown-code">.get()/.set()</code> reactive API</td>
241
+ <td class="quikdown-td"><code class="quikdown-code">bw.mount(selector, obj)</code></td>
242
+ <td class="quikdown-td">Like <code class="quikdown-code">bw.DOM()</code> but returns the root element for <code class="quikdown-code">el.bw</code> access</td>
243
+ </tr>
244
+ <tr class="quikdown-tr">
245
+ <td class="quikdown-td"><code class="quikdown-code">bw.raw(str)</code></td>
246
+ <td class="quikdown-td">Mark a string as pre-escaped HTML (no double-escaping)</td>
174
247
  </tr>
175
248
  <tr class="quikdown-tr">
176
249
  <td class="quikdown-td"><code class="quikdown-code">bw.css(rules)</code></td>
177
250
  <td class="quikdown-td">Generate CSS from a JS object</td>
178
251
  </tr>
179
252
  <tr class="quikdown-tr">
180
- <td class="quikdown-td"><code class="quikdown-code">bw.loadDefaultStyles()</code></td>
181
- <td class="quikdown-td">Inject the built-in stylesheet</td>
253
+ <td class="quikdown-td"><code class="quikdown-code">bw.s(...objs)</code></td>
254
+ <td class="quikdown-td">Compose inline style objects into a style string</td>
255
+ </tr>
256
+ <tr class="quikdown-tr">
257
+ <td class="quikdown-td"><code class="quikdown-code">bw.responsive(sel, breakpoints)</code></td>
258
+ <td class="quikdown-td">Generate <code class="quikdown-code">@media</code> CSS rules from JS</td>
259
+ </tr>
260
+ <tr class="quikdown-tr">
261
+ <td class="quikdown-td"><code class="quikdown-code">bw.loadStyles(config?)</code></td>
262
+ <td class="quikdown-td">Load structural CSS (no args) or generate + apply a theme from seed colors</td>
182
263
  </tr>
183
264
  <tr class="quikdown-tr">
184
- <td class="quikdown-td"><code class="quikdown-code">bw.generateTheme(name, config)</code></td>
185
- <td class="quikdown-td">Generate a scoped theme from seed colors</td>
265
+ <td class="quikdown-td"><code class="quikdown-code">bw.makeStyles(config)</code></td>
266
+ <td class="quikdown-td">Generate a theme from seed colors (returns styles object)</td>
267
+ </tr>
268
+ <tr class="quikdown-tr">
269
+ <td class="quikdown-td"><code class="quikdown-code">bw.applyStyles(styles)</code></td>
270
+ <td class="quikdown-td">Inject a generated styles object&#39;s CSS into the document</td>
271
+ </tr>
272
+ <tr class="quikdown-tr">
273
+ <td class="quikdown-td"><code class="quikdown-code">bw.toggleStyles()</code></td>
274
+ <td class="quikdown-td">Switch between primary and alternate palettes</td>
275
+ </tr>
276
+ <tr class="quikdown-tr">
277
+ <td class="quikdown-td"><code class="quikdown-code">bw.clearStyles()</code></td>
278
+ <td class="quikdown-td">Remove injected theme styles</td>
186
279
  </tr>
187
280
  <tr class="quikdown-tr">
188
281
  <td class="quikdown-td"><code class="quikdown-code">bw.patch(id, content)</code></td>
189
- <td class="quikdown-td">Update a specific element by UUID</td>
282
+ <td class="quikdown-td">Update a specific element by id or UUID</td>
190
283
  </tr>
191
284
  <tr class="quikdown-tr">
192
285
  <td class="quikdown-td"><code class="quikdown-code">bw.update(el)</code></td>
@@ -194,7 +287,7 @@ bw.toggleTheme(); // switch between primary and alternate palettes</code></pre>
194
287
  </tr>
195
288
  <tr class="quikdown-tr">
196
289
  <td class="quikdown-td"><code class="quikdown-code">bw.message(target, action, data)</code></td>
197
- <td class="quikdown-td">Send a message to a component by tag name</td>
290
+ <td class="quikdown-td">Dispatch a method call to a component&#39;s <code class="quikdown-code">el.bw</code> handle</td>
198
291
  </tr>
199
292
  <tr class="quikdown-tr">
200
293
  <td class="quikdown-td"><code class="quikdown-code">bw.pub(topic, detail)</code></td>
@@ -206,20 +299,12 @@ bw.toggleTheme(); // switch between primary and alternate palettes</code></pre>
206
299
  </tr>
207
300
  <tr class="quikdown-tr">
208
301
  <td class="quikdown-td"><code class="quikdown-code">bw.inspect(target)</code></td>
209
- <td class="quikdown-td">Debug a component in the browser console</td>
210
- </tr>
211
- <tr class="quikdown-tr">
212
- <td class="quikdown-td"><code class="quikdown-code">bw.clientConnect(url, opts)</code></td>
213
- <td class="quikdown-td">Connect to a bwserve SSE endpoint</td>
302
+ <td class="quikdown-td">Debug a component&#39;s state, handles, and metadata in the console</td>
214
303
  </tr>
215
304
  <tr class="quikdown-tr">
216
- <td class="quikdown-td"><code class="quikdown-code">bw.clientApply(msg)</code></td>
305
+ <td class="quikdown-td"><code class="quikdown-code">bw.apply(msg)</code></td>
217
306
  <td class="quikdown-td">Apply a bwserve protocol message to the DOM</td>
218
307
  </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
308
  </tbody>
224
309
  </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
310
  <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
@@ -230,7 +315,7 @@ bwcli doc.md -o doc.html --standalone --theme ocean
230
315
 
231
316
  # Custom colors
232
317
  bwcli doc.md -o doc.html --standalone --theme &quot;#336699,#cc6633&quot;</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>
233
- <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
318
+ <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
234
319
  curl -X POST http://localhost:9000 -d &#39;{&quot;type&quot;:&quot;patch&quot;,&quot;target&quot;:&quot;temp&quot;,&quot;content&quot;:&quot;23.5 C&quot;}&#39;</code></pre><h2 class="quikdown-h2">Build Formats</h2>
235
320
  <table class="quikdown-table">
236
321
  <thead class="quikdown-thead">
@@ -263,35 +348,48 @@ curl -X POST http://localhost:9000 -d &#39;{&quot;type&quot;:&quot;patch&quot;,&
263
348
  </tr>
264
349
  </tbody>
265
350
  </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">Guides</strong> (in <code class="quikdown-code">docs/</code>):</p><ul class="quikdown-ul">
267
- <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
- <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
- <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
- <li class="quikdown-li"><a class="quikdown-a" href="docs/theming.md">Theming</a> palette-driven theme generation, presets, design tokens</li>
271
- <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
- <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>
351
+ <strong class="quikdown-strong">Start here:</strong></p><ul class="quikdown-ul">
352
+ <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>
353
+ <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>
354
+ </ul><p><strong class="quikdown-strong">Reference guides</strong> (in <code class="quikdown-code">docs/</code>):</p><ul class="quikdown-ul">
355
+ <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>
356
+ <li class="quikdown-li"><a class="quikdown-a" href="docs/state-management.md">State Management</a> -- three-level component model, stateful TACO, reactive state</li>
357
+ <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>
358
+ <li class="quikdown-li"><a class="quikdown-a" href="docs/theming.md">Theming</a> -- palette-driven theme generation, presets, design tokens</li>
359
+ <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>
360
+ <li class="quikdown-li"><a class="quikdown-a" href="docs/bwserve.md">bwserve</a> -- server-driven UI protocol (SSE, actions, embedded devices)</li>
274
361
  </ul><p><strong class="quikdown-strong">Tutorials:</strong></p><ul class="quikdown-ul">
275
- <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
- <li class="quikdown-li"><a class="quikdown-a" href="docs/tutorial-bwserve.md">bwserve Dashboard</a> Streamlit-style server-push dashboard</li>
277
- <li class="quikdown-li"><a class="quikdown-a" href="docs/tutorial-embedded.md">ESP32 IoT Dashboard</a> embedded sensor dashboard with C macros</li>
362
+ <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>
363
+ <li class="quikdown-li"><a class="quikdown-a" href="docs/tutorial-bwserve.md">bwserve Dashboard</a> -- Streamlit-style server-push dashboard</li>
364
+ <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
365
  </ul><p><strong class="quikdown-strong">Interactive demos</strong> (live site):</p><ul class="quikdown-ul">
279
- <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> buttons, cards, alerts, badges, navbars</li>
281
- <li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/03-styling.html" rel="noopener noreferrer">Styling &amp; Theming</a> CSS generation and theming strategies</li>
282
- <li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/05-state.html" rel="noopener noreferrer">State &amp; Interactivity</a> state patterns and ComponentHandle</li>
283
- <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
- <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
- <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><h2 class="quikdown-h2">Development</h2>
366
+ <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>
367
+ <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>
368
+ <li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/03-styling.html" rel="noopener noreferrer">Styling &amp; Theming</a> -- CSS generation, <code class="quikdown-code">bw.s()</code>, and theming strategies</li>
369
+ <li class="quikdown-li"><a class="quikdown-a" href="https://deftio.github.io/bitwrench/pages/05-state.html" rel="noopener noreferrer">State &amp; Interactivity</a> -- state patterns and stateful TACO</li>
370
+ <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>
371
+ <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>
372
+ <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>
373
+ </ul><p><strong class="quikdown-strong">Example apps</strong> (in <code class="quikdown-code">examples/</code>):</p><ul class="quikdown-ul">
374
+ <li class="quikdown-li"><a class="quikdown-a" href="examples/ember-and-oak/">Ember &amp; Oak Coffee Co.</a> -- full landing page: theme, cart, search, charts, accordion, timeline</li>
375
+ <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>
376
+ <li class="quikdown-li"><a class="quikdown-a" href="examples/todo-app/">Todo App</a> -- stateful TACO with pub/sub</li>
377
+ <li class="quikdown-li"><a class="quikdown-a" href="examples/dashboard/">Metrics Dashboard</a> -- live stat cards, bar chart, pub/sub, responsive layout</li>
378
+ <li class="quikdown-li"><a class="quikdown-a" href="examples/wizard/">Signup Wizard</a> -- multi-step form, state transitions, bw.raw()</li>
379
+ <li class="quikdown-li"><a class="quikdown-a" href="examples/live-feed/">Live Feed</a> -- real-time stream, bw.patch(), slide-in animation</li>
380
+ <li class="quikdown-li"><a class="quikdown-a" href="examples/embedded/">IoT Dashboard</a> -- ESP32-style sensor dashboard with SSE</li>
381
+ <li class="quikdown-li"><a class="quikdown-a" href="examples/client-server/">bwserve Counter</a> -- server-driven UI demo</li>
382
+ <li class="quikdown-li"><a class="quikdown-a" href="examples/llm-chat/">LLM Chat</a> -- streaming chat via bwserve + Ollama/OpenAI</li>
383
+ </ul><h2 class="quikdown-h2">FAQ</h2>
384
+ <strong class="quikdown-strong">Is this a framework?</strong> -- No. Bitwrench is a library (~38KB 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&#39;t own your CSS. Use any external stylesheet, Tailwind, or CSS file you want -- bitwrench doesn&#39;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> derives a complete design system from 2 seed colors. You can use all three together or none at all.</p><p><strong class="quikdown-strong">What&#39;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(&#39;#app&#39;, 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&#39;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: { &#39;aria-label&#39;: &#39;...&#39; }</code>.</p><h2 class="quikdown-h2">Development</h2>
287
385
  <p><pre class="quikdown-pre"><code class="language-bash">npm install # install dev dependencies
288
386
  npm run build # build all dist formats (UMD, ESM, CJS, ES5)
289
- npm test # run unit tests (1000+ tests)
290
- npm run test:cli # run CLI tests (49 tests)
387
+ npm test # run unit tests (1400+ tests, 96% coverage)
388
+ npm run test:cli # run CLI tests
291
389
  npm run test:e2e # run Playwright browser tests
292
390
  npm run lint # run ESLint
293
391
  npm run cleanbuild # full production build with SRI hashes</code></pre></p><h2 class="quikdown-h2">License</h2>
294
- <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>
392
+ <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>
295
393
  </p>
296
394
  </div>
297
395
  </div>
@@ -46,15 +46,14 @@ export function registerBCCL(bw) {
46
46
  // Variant class helper
47
47
  bw.variantClass = components.variantClass;
48
48
 
49
- // Create functions that return handles
50
- if (typeof bw.renderComponent === 'function') {
49
+ // Create functions that return DOM elements
50
+ if (typeof bw.createDOM === 'function') {
51
51
  Object.entries(components).forEach(function(entry) {
52
52
  var name = entry[0], fn = entry[1];
53
53
  if (name.indexOf('make') === 0) {
54
54
  var createName = 'create' + name.substring(4);
55
55
  bw[createName] = function(props) {
56
- var taco = fn(props);
57
- return bw.renderComponent(taco);
56
+ return bw.createDOM(fn(props));
58
57
  };
59
58
  }
60
59
  });