bitwrench 2.0.18 → 2.0.20

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 (58) hide show
  1. package/README.md +86 -81
  2. package/dist/bitwrench-bccl.cjs.js +221 -48
  3. package/dist/bitwrench-bccl.cjs.min.js +3 -3
  4. package/dist/bitwrench-bccl.esm.js +221 -48
  5. package/dist/bitwrench-bccl.esm.min.js +3 -3
  6. package/dist/bitwrench-bccl.umd.js +221 -48
  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 +250 -1574
  19. package/dist/bitwrench-lean.cjs.min.js +6 -6
  20. package/dist/bitwrench-lean.es5.js +344 -1661
  21. package/dist/bitwrench-lean.es5.min.js +4 -4
  22. package/dist/bitwrench-lean.esm.js +250 -1574
  23. package/dist/bitwrench-lean.esm.min.js +6 -6
  24. package/dist/bitwrench-lean.umd.js +250 -1574
  25. package/dist/bitwrench-lean.umd.min.js +6 -6
  26. package/dist/bitwrench-util-css.cjs.js +1 -1
  27. package/dist/bitwrench-util-css.cjs.min.js +1 -1
  28. package/dist/bitwrench-util-css.es5.js +1 -1
  29. package/dist/bitwrench-util-css.es5.min.js +1 -1
  30. package/dist/bitwrench-util-css.esm.js +1 -1
  31. package/dist/bitwrench-util-css.esm.min.js +1 -1
  32. package/dist/bitwrench-util-css.umd.js +1 -1
  33. package/dist/bitwrench-util-css.umd.min.js +1 -1
  34. package/dist/bitwrench.cjs.js +510 -1660
  35. package/dist/bitwrench.cjs.min.js +7 -7
  36. package/dist/bitwrench.css +80 -33
  37. package/dist/bitwrench.es5.js +569 -1694
  38. package/dist/bitwrench.es5.min.js +5 -5
  39. package/dist/bitwrench.esm.js +510 -1660
  40. package/dist/bitwrench.esm.min.js +7 -7
  41. package/dist/bitwrench.min.css +1 -1
  42. package/dist/bitwrench.umd.js +510 -1660
  43. package/dist/bitwrench.umd.min.js +7 -7
  44. package/dist/builds.json +133 -111
  45. package/dist/bwserve.cjs.js +2 -2
  46. package/dist/bwserve.esm.js +2 -2
  47. package/dist/sri.json +46 -44
  48. package/package.json +5 -3
  49. package/readme.html +86 -75
  50. package/src/bitwrench-bccl-entry.js +3 -4
  51. package/src/bitwrench-bccl.js +217 -43
  52. package/src/bitwrench-code-edit.js +6 -8
  53. package/src/bitwrench-debug.js +245 -0
  54. package/src/bitwrench-styles.js +35 -8
  55. package/src/bitwrench.js +212 -1563
  56. package/src/cli/attach.js +53 -21
  57. package/src/cli/serve.js +179 -3
  58. package/src/version.js +3 -3
package/dist/sri.json CHANGED
@@ -1,49 +1,51 @@
1
1
  {
2
- "version": "2.0.18",
2
+ "version": "2.0.20",
3
3
  "algorithm": "sha384",
4
- "generated": "2026-03-17",
4
+ "generated": "2026-03-23",
5
5
  "files": {
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"
6
+ "bitwrench-bccl.cjs.js": "sha384-hsG+SRlchTGHwVSx7X2FFW4L1ppTyNg9KT1uzWJyCLp/9CSkYsOwf3Uehj2HPMDA",
7
+ "bitwrench-bccl.cjs.min.js": "sha384-no/by83K4+BL3eXopbdqFgjeH6WEWoPN1gjQ1/+LHJa/itpvEvYfT+e+3K+Mmbwr",
8
+ "bitwrench-bccl.esm.js": "sha384-E1k0w73P1elVlYiEgpbZtz9lMvhD0CcvUiKZrvj/SwXa/3pPxm6WJOWod5lNRu8Q",
9
+ "bitwrench-bccl.esm.min.js": "sha384-4LPW295wGjxERN9z0R9wweEsWAX6mRvzkhoIrZAP1F5uUIsJ0o+hWormJZq5vxtl",
10
+ "bitwrench-bccl.umd.js": "sha384-OgwmlT3geJvV5BPhz4qPdaSAIcvhO8Le7IHePMGMkfHZAunEs7pvjzkj2gtVOfyu",
11
+ "bitwrench-bccl.umd.min.js": "sha384-Yw0lmd1sw8lj3CTWIG8wyDfl/XSXYmnAV7TrM8cQLtHYoCIRv0GZPlHATNMukNe9",
12
+ "bitwrench-code-edit.cjs.js": "sha384-WAZniFEFNsDLOe6QiK9Qk1Sa96UDFZ6JfUoojV+P6z++RiFXmKH+4MpWYlOV6eNp",
13
+ "bitwrench-code-edit.cjs.min.js": "sha384-o4cJ5n9xMqFAFKEsPc5UrGJoeeP4ODBi9QugvYW3aKRMdcEr+tFQBE/sJ9eYU9Hz",
14
+ "bitwrench-code-edit.es5.js": "sha384-C8XF36O+LqEt3Zy1gSNiuVr4ii8s360PSn8yFz1Y3yMVjQ3wIn/8Y6WbiF3uxJ2n",
15
+ "bitwrench-code-edit.es5.min.js": "sha384-W4GbRxFa86W2e67VpsV1V40+qbseprNTMKb8JCDxI1JLOnaRO3ILExhP+dNveGWj",
16
+ "bitwrench-code-edit.esm.js": "sha384-DCqqGWMEJHRt/six2L/EWfBvtNlyBNufekZAuJORsNob8ti69GKPOshzeT114fSc",
17
+ "bitwrench-code-edit.esm.min.js": "sha384-by62LgmqD5IsQXbUQH1oIIhkmzOpaQUtUPJ+TIigQiQHyW21n30iQeEDXDCk6qC2",
18
+ "bitwrench-code-edit.umd.js": "sha384-hic4TTfbKwFK5JHpbMZIhiXRM4BX3O28//sjOgskmHUYqxHB/rrgvkOR0O6zPlb/",
19
+ "bitwrench-code-edit.umd.min.js": "sha384-41aFz3LGZf3B67xdkZ651ywsaee1o5BSMBpuZoqDQqx09HlzzVkYqlLeJbSvUz16",
20
+ "bitwrench-debug.js": "sha384-+gc7VSYuLAwZUopr4QTJMKj7lDcSceef7zlYYUW4C8clq0KrvfxsWlqQMvI+nnQo",
21
+ "bitwrench-debug.min.js": "sha384-DsUj88cJvhbR0KiwWSYUvp6SdQ4ynHvD79U3znQrOGofRX979BjhMbAJR2apM3yj",
22
+ "bitwrench-lean.cjs.js": "sha384-7uTzDm5/mb0jJ1L8FUtDAhQOUN4v9F0FAMv4fKf8n6JxsC3GYwCw4qNJZSPwz93v",
23
+ "bitwrench-lean.cjs.min.js": "sha384-l5dYFFrJr38YF+oJOvBseroZ6tG1+yciYbUMfyevlvfquHuqibRxlPaP5VSptSsA",
24
+ "bitwrench-lean.es5.js": "sha384-eBLaZFJsFwHI3kCS6cnmYg0KO+mYWTQhetowKKHAegJ4t4AsD/XRDLPWDmP6ViqM",
25
+ "bitwrench-lean.es5.min.js": "sha384-9EW/XgWiZEb2JM9g7CdDDLESqVr+o+36fXz5f6HqaJKC7iggY0T7UrxRka+cA69i",
26
+ "bitwrench-lean.esm.js": "sha384-fCQIZ448hzC5n9PPHjgaH1Ro9OET5xOldLV/88SujXx/1QofI3FFD3vpPtjiLpYQ",
27
+ "bitwrench-lean.esm.min.js": "sha384-svumIaHcQ6tB1LL+nKDom2KwiWoj9idCgVE4iLuU02qQSpJ9MiI3BdOHUICuAltz",
28
+ "bitwrench-lean.umd.js": "sha384-CLhcAan8KpUEk7Jtiham41bJUiq3GVGBqhbDubxcSlb7kCgqAq2dIoDZbv4yH+Fp",
29
+ "bitwrench-lean.umd.min.js": "sha384-O2Vpv59eyooTCPj0JeghoUEGBq2NvDkSfu2nUzlYV0pJR9VjofrL9NVAhNPGe5Wq",
30
+ "bitwrench-util-css.cjs.js": "sha384-q0BDcA7UILSgcx2w3fvq0XvTlZ9l0bSKPxWTLT0pSBF8P+v80UAuCIiQyQSr6tzv",
31
+ "bitwrench-util-css.cjs.min.js": "sha384-xUYDiCn5GXX62zV4SPB/AR7T5IlNF17uJeff0Ci7cNjbmg/Md1JqjuUMTEy+N87r",
32
+ "bitwrench-util-css.es5.js": "sha384-f6PzdGNhRTce6RrOZXlOzDCyF10WZMYKz+4Fm8RGfcAFutolkQ6jlRE1novmLOhX",
33
+ "bitwrench-util-css.es5.min.js": "sha384-JVgJEoreJ23z/qgzId+Lj/lbfVcIAII5O06u/9Z7AP6BsrNvcXMEav2vZ0hnFEgd",
34
+ "bitwrench-util-css.esm.js": "sha384-5tDzjjiSZMiRRU6x/aZfGC0D6PJDWPPzMBRDJ61FZGUse7wK/KesHDbvqcrmvuoI",
35
+ "bitwrench-util-css.esm.min.js": "sha384-Pt/BFduYTStwP83ama5SLipRI4WvlOE0PYiQK65554EkpWDj52C3PbfLDuzZhouY",
36
+ "bitwrench-util-css.umd.js": "sha384-gKbfkYTW93GdRyAU8V7YKRtLne+CXdt2kdErLjeSIOB6bsAuBftXYHlOK4MSMdHn",
37
+ "bitwrench-util-css.umd.min.js": "sha384-Dub6BkQa3vwTT3aRpD/Fz6V4UmbZ2O+ePw2Io5pEMERr3UAPDx0KHWtLENfP/JCt",
38
+ "bitwrench.cjs.js": "sha384-IHAO4DoKy9YsxqwQBbPwWQQbCSvhsTW3NnQyoZDSuV1UKK0/5VROK8j3QvxkPsAR",
39
+ "bitwrench.cjs.min.js": "sha384-5NJX3oDsLgQOc8ADLs6Da0/ULVYK4KPD5aSUEuM+cP2na/F8UQ+7yqj27MqW7upH",
40
+ "bitwrench.css": "sha384-T0v80gK0QjtmPAgOsHjpImH5Uhy+URqhkDUSfbxkqoGB6cqPWu28AOGF0vYa5jX9",
41
+ "bitwrench.es5.js": "sha384-03nWMck+ffi0E5UnkBzwKINQsT/idYNCUntBg2PyGEoGsasJYvzt8Q+7jhboENT9",
42
+ "bitwrench.es5.min.js": "sha384-TWBcPYlf+/B/p4gSp2cJgH1HcyL0S3b28IssT+xyEMPg1uhBbPyMNmzaJ4XBdzHc",
43
+ "bitwrench.esm.js": "sha384-PNThb7YB8hU4EmWWN2BlWC5vYrTAD5ywQpMZshsSMNIPHh2vPUx08+d5crJ3Tzhu",
44
+ "bitwrench.esm.min.js": "sha384-c9/6JFVUFgUkaP/8L6gJs5R7tSsJJxXKCMBut7f+aZyDLbEp4uXd4TJDWPafYLVd",
45
+ "bitwrench.min.css": "sha384-gY4lHVKePTqTes9lnWPKs6xhVgqj+GgyW6I3d+6idz0CDioCnNVdqf7ffsvWViHf",
46
+ "bitwrench.umd.js": "sha384-C2p1rPZcb8UDfwujPKQq+hEsC1qxIfpW7DtBGE40eLdb1gvqSaTEKYEFiG46jWeE",
47
+ "bitwrench.umd.min.js": "sha384-YXdNNsu5kB8wvn9+4atlNy88uTAm4l0JPI1CvAfkp99vHBSsVHgMGLLtqA8BgkeO",
48
+ "bwserve.cjs.js": "sha384-9fTEjjxJc7/y7jPj5vU/VXexcr/GGeckTsjlPWkKx3DNMfgQVqPcuevKnRZH72qq",
49
+ "bwserve.esm.js": "sha384-fxM0bxVXDPLUAE30wFwO7s1EbukeMMDbBA1N2zF7F6pLMTf+Lq4/NBePzfJ4PMAG"
48
50
  }
49
51
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bitwrench",
3
- "version": "2.0.18",
3
+ "version": "2.0.20",
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,9 +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_attach.js ./test/bitwrench_test_code_edit.js ./test/bitwrench_test_html_page.js ./test/bitwrench_test_util_css.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
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",
101
102
  "test:components": "mocha ./test/bitwrench_test_components.js -r jsdom-global/register",
102
103
  "test:v1": "c8 --reporter=text mocha ./test/bitwrench_test.js -r jsdom-global/",
103
104
  "test:pending": "mocha ./test/bitwrench_test_pending.js -r jsdom-global/",
@@ -112,6 +113,7 @@
112
113
  "generate-sri": "node tools/generate-sri.js",
113
114
  "test:nodemap": "mocha ./test/bitwrench_test_nodemap.js -r jsdom-global/register",
114
115
  "test:cli": "mocha ./test/bitwrench_test_cli.js",
116
+ "test:debug": "mocha ./test/bitwrench_test_debug.js -r jsdom-global/register",
115
117
  "test:code-edit": "mocha ./test/bitwrench_test_code_edit.js -r jsdom-global/register",
116
118
  "test:html-page": "mocha ./test/bitwrench_test_html_page.js -r jsdom-global/register",
117
119
  "test:e2e": "playwright test",
package/readme.html CHANGED
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <meta name="generator" content="bitwrench v2.0.18">
6
+ <meta name="generator" content="bitwrench v2.0.20">
7
7
  <title>bitwrench.js - README</title>
8
8
  <link rel="icon" type="image/x-icon" href="images/favicon.ico">
9
9
  <script src="dist/bitwrench.umd.min.js"></script>
@@ -71,7 +71,8 @@
71
71
  <h1 class="quikdown-h1">bitwrench.js</h1>
72
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>
73
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>
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 &quot;TACO&quot;)
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;)
75
76
  var page = {
76
77
  t: &#39;div&#39;, a: { class: &#39;card&#39; },
77
78
  c: [
@@ -81,17 +82,17 @@ var page = {
81
82
  ]
82
83
  };
83
84
 
84
- bw.DOM(&#39;#app&#39;, 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&#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>
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">&lt;script&gt;</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>
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>
95
96
  </ul><h3 class="quikdown-h3">Coming from other Frameworks</h3>
96
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">
97
98
  <thead class="quikdown-thead">
@@ -105,12 +106,12 @@ bw.html(page); // → HTML string (Node.js, emails, SSR)</code><
105
106
  <tr class="quikdown-tr">
106
107
  <td class="quikdown-td">React / Vue / Svelte</td>
107
108
  <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
+ <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>
109
110
  </tr>
110
111
  <tr class="quikdown-tr">
111
112
  <td class="quikdown-td">JSX / templates</td>
112
113
  <td class="quikdown-td">Markup-in-JS</td>
113
- <td class="quikdown-td">Native JS objects no compiler</td>
114
+ <td class="quikdown-td">Native JS objects -- no compiler</td>
114
115
  </tr>
115
116
  <tr class="quikdown-tr">
116
117
  <td class="quikdown-td">Tailwind / CSS-in-JS</td>
@@ -130,17 +131,17 @@ bw.html(page); // → HTML string (Node.js, emails, SSR)</code><
130
131
  <tr class="quikdown-tr">
131
132
  <td class="quikdown-td">Streamlit / Gradio</td>
132
133
  <td class="quikdown-td">Server-driven UI</td>
133
- <td class="quikdown-td">bwserve SSE from any language (Python, Go, C, Rust)</td>
134
+ <td class="quikdown-td">bwserve SSE -- from any language (Python, Go, C, Rust)</td>
134
135
  </tr>
135
136
  <tr class="quikdown-tr">
136
137
  <td class="quikdown-td">Redux / Zustand / Pinia</td>
137
138
  <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
+ <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>
139
140
  </tr>
140
141
  <tr class="quikdown-tr">
141
142
  <td class="quikdown-td">Vite / webpack / Babel</td>
142
143
  <td class="quikdown-td">Build tooling</td>
143
- <td class="quikdown-td">Not needed open the HTML file</td>
144
+ <td class="quikdown-td">Not needed -- open the HTML file</td>
144
145
  </tr>
145
146
  </tbody>
146
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>
@@ -177,24 +178,26 @@ const bw = require(&#39;bitwrench&#39;);</code></pre><p>Or include directly in a
177
178
  &lt;/script&gt;
178
179
  &lt;/body&gt;
179
180
  &lt;/html&gt;</code></pre></p><h2 class="quikdown-h2">Adding State</h2>
180
- <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({
181
- t: &#39;div&#39;, c: [
182
- { t: &#39;span&#39;, c: &#39;Count: ${count}&#39; },
183
- { t: &#39;button&#39;, c: &#39;+1&#39;, a: {
184
- onclick: function() { counter.set(&#39;count&#39;, counter.get(&#39;count&#39;) + 1); }
185
- }}
186
- ],
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;,
187
183
  o: {
188
184
  state: { count: 0 },
189
- methods: {
190
- 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
+ });
191
196
  }
192
197
  }
193
- });
198
+ };
194
199
 
195
- bw.DOM(&#39;#app&#39;, counter);
196
- counter.set(&#39;count&#39;, 42); // DOM updates automatically
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(&#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) {
198
201
  console.log(&#39;New item:&#39;, detail.name);
199
202
  });
200
203
 
@@ -212,7 +215,7 @@ bw.responsive(&#39;.hero&#39;, {
212
215
  base: { fontSize: &#39;1.5rem&#39; },
213
216
  md: { fontSize: &#39;2.5rem&#39; }
214
217
  });</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({
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({
216
219
  primary: &#39;#336699&#39;,
217
220
  secondary: &#39;#cc6633&#39;
218
221
  });
@@ -228,19 +231,19 @@ bw.toggleStyles(); // switch between primary and alternate palettes</code></pre
228
231
  <tbody class="quikdown-tbody">
229
232
  <tr class="quikdown-tr">
230
233
  <td class="quikdown-td"><code class="quikdown-code">bw.html(obj)</code></td>
231
- <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>
232
235
  </tr>
233
236
  <tr class="quikdown-tr">
234
237
  <td class="quikdown-td"><code class="quikdown-code">bw.DOM(selector, obj)</code></td>
235
- <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>
236
239
  </tr>
237
240
  <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>
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>
240
243
  </tr>
241
244
  <tr class="quikdown-tr">
242
- <td class="quikdown-td"><code class="quikdown-code">bw.component(taco)</code></td>
243
- <td class="quikdown-td">Wrap a TACO in a ComponentHandle with <code class="quikdown-code">.get()/.set()</code> reactive API</td>
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>
244
247
  </tr>
245
248
  <tr class="quikdown-tr">
246
249
  <td class="quikdown-td"><code class="quikdown-code">bw.css(rules)</code></td>
@@ -255,20 +258,28 @@ bw.toggleStyles(); // switch between primary and alternate palettes</code></pre
255
258
  <td class="quikdown-td">Generate <code class="quikdown-code">@media</code> CSS rules from JS</td>
256
259
  </tr>
257
260
  <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>
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>
260
263
  </tr>
261
264
  <tr class="quikdown-tr">
262
265
  <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>
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>
264
271
  </tr>
265
272
  <tr class="quikdown-tr">
266
273
  <td class="quikdown-td"><code class="quikdown-code">bw.toggleStyles()</code></td>
267
274
  <td class="quikdown-td">Switch between primary and alternate palettes</td>
268
275
  </tr>
269
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>
279
+ </tr>
280
+ <tr class="quikdown-tr">
270
281
  <td class="quikdown-td"><code class="quikdown-code">bw.patch(id, content)</code></td>
271
- <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>
272
283
  </tr>
273
284
  <tr class="quikdown-tr">
274
285
  <td class="quikdown-td"><code class="quikdown-code">bw.update(el)</code></td>
@@ -276,7 +287,7 @@ bw.toggleStyles(); // switch between primary and alternate palettes</code></pre
276
287
  </tr>
277
288
  <tr class="quikdown-tr">
278
289
  <td class="quikdown-td"><code class="quikdown-code">bw.message(target, action, data)</code></td>
279
- <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>
280
291
  </tr>
281
292
  <tr class="quikdown-tr">
282
293
  <td class="quikdown-td"><code class="quikdown-code">bw.pub(topic, detail)</code></td>
@@ -288,7 +299,7 @@ bw.toggleStyles(); // switch between primary and alternate palettes</code></pre
288
299
  </tr>
289
300
  <tr class="quikdown-tr">
290
301
  <td class="quikdown-td"><code class="quikdown-code">bw.inspect(target)</code></td>
291
- <td class="quikdown-td">Debug a component in the browser console</td>
302
+ <td class="quikdown-td">Debug a component&#39;s state, handles, and metadata in the console</td>
292
303
  </tr>
293
304
  <tr class="quikdown-tr">
294
305
  <td class="quikdown-td"><code class="quikdown-code">bw.apply(msg)</code></td>
@@ -304,7 +315,7 @@ bwcli doc.md -o doc.html --standalone --theme ocean
304
315
 
305
316
  # Custom colors
306
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>
307
- <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
308
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>
309
320
  <table class="quikdown-table">
310
321
  <thead class="quikdown-thead">
@@ -338,47 +349,47 @@ curl -X POST http://localhost:9000 -d &#39;{&quot;type&quot;:&quot;patch&quot;,&
338
349
  </tbody>
339
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>
340
351
  <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>
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>
343
354
  </ul><p><strong class="quikdown-strong">Reference guides</strong> (in <code class="quikdown-code">docs/</code>):</p><ul class="quikdown-ul">
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>
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>
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>
347
- <li class="quikdown-li"><a class="quikdown-a" href="docs/theming.md">Theming</a> palette-driven theme generation, presets, design tokens</li>
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>
349
- <li class="quikdown-li"><a class="quikdown-a" href="docs/bwserve.md">bwserve</a> server-driven UI protocol (SSE, actions, embedded devices)</li>
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>
350
361
  </ul><p><strong class="quikdown-strong">Tutorials:</strong></p><ul class="quikdown-ul">
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>
352
- <li class="quikdown-li"><a class="quikdown-a" href="docs/tutorial-bwserve.md">bwserve Dashboard</a> Streamlit-style server-push dashboard</li>
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>
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>
354
365
  </ul><p><strong class="quikdown-strong">Interactive demos</strong> (live site):</p><ul class="quikdown-ul">
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>
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 &amp; Theming</a> CSS generation, <code class="quikdown-code">bw.s()</code>, and theming strategies</li>
358
- <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>
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>
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>
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>
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>
362
373
  </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 &amp; 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>
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>
372
383
  </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&#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> 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&#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>
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>
374
385
  <p><pre class="quikdown-pre"><code class="language-bash">npm install # install dev dependencies
375
386
  npm run build # build all dist formats (UMD, ESM, CJS, ES5)
376
- npm test # run unit tests (1000+ tests)
387
+ npm test # run unit tests (1400+ tests, 96% coverage)
377
388
  npm run test:cli # run CLI tests
378
389
  npm run test:e2e # run Playwright browser tests
379
390
  npm run lint # run ESLint
380
391
  npm run cleanbuild # full production build with SRI hashes</code></pre></p><h2 class="quikdown-h2">License</h2>
381
- <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>
382
393
  </p>
383
394
  </div>
384
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
  });