@lo-tek/interfaces 0.0.0 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (456) hide show
  1. package/CHANGELOG.md +3389 -0
  2. package/LICENSE +21 -0
  3. package/README.md +129 -1
  4. package/agent/astro.md +400 -0
  5. package/agent/bundles.md +429 -0
  6. package/agent/datastar.md +409 -0
  7. package/agent/html.md +388 -0
  8. package/agent/react.md +440 -0
  9. package/agent/templates.md +472 -0
  10. package/core/lotek-core.wasm +0 -0
  11. package/core/lotek.wasm +0 -0
  12. package/dist/cli.d.ts +12 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +14 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/components/css/accordion/accordion.d.ts +37 -0
  17. package/dist/components/css/accordion/accordion.d.ts.map +1 -0
  18. package/dist/components/css/accordion/accordion.js +31 -0
  19. package/dist/components/css/accordion/accordion.js.map +1 -0
  20. package/dist/components/css/alert/alert.d.ts +35 -0
  21. package/dist/components/css/alert/alert.d.ts.map +1 -0
  22. package/dist/components/css/alert/alert.js +29 -0
  23. package/dist/components/css/alert/alert.js.map +1 -0
  24. package/dist/components/css/avatar/avatar.d.ts +40 -0
  25. package/dist/components/css/avatar/avatar.d.ts.map +1 -0
  26. package/dist/components/css/avatar/avatar.js +30 -0
  27. package/dist/components/css/avatar/avatar.js.map +1 -0
  28. package/dist/components/css/badge/badge.d.ts +24 -0
  29. package/dist/components/css/badge/badge.d.ts.map +1 -0
  30. package/dist/components/css/badge/badge.js +24 -0
  31. package/dist/components/css/badge/badge.js.map +1 -0
  32. package/dist/components/css/breadcrumbs/breadcrumbs.d.ts +26 -0
  33. package/dist/components/css/breadcrumbs/breadcrumbs.d.ts.map +1 -0
  34. package/dist/components/css/breadcrumbs/breadcrumbs.js +24 -0
  35. package/dist/components/css/breadcrumbs/breadcrumbs.js.map +1 -0
  36. package/dist/components/css/button/button.d.ts +26 -0
  37. package/dist/components/css/button/button.d.ts.map +1 -0
  38. package/dist/components/css/button/button.js +25 -0
  39. package/dist/components/css/button/button.js.map +1 -0
  40. package/dist/components/css/card/card.d.ts +36 -0
  41. package/dist/components/css/card/card.d.ts.map +1 -0
  42. package/dist/components/css/card/card.js +28 -0
  43. package/dist/components/css/card/card.js.map +1 -0
  44. package/dist/components/css/checkbox/checkbox.d.ts +32 -0
  45. package/dist/components/css/checkbox/checkbox.d.ts.map +1 -0
  46. package/dist/components/css/checkbox/checkbox.js +27 -0
  47. package/dist/components/css/checkbox/checkbox.js.map +1 -0
  48. package/dist/components/css/divider/divider.d.ts +29 -0
  49. package/dist/components/css/divider/divider.d.ts.map +1 -0
  50. package/dist/components/css/divider/divider.js +23 -0
  51. package/dist/components/css/divider/divider.js.map +1 -0
  52. package/dist/components/css/error-text/error-text.d.ts +24 -0
  53. package/dist/components/css/error-text/error-text.d.ts.map +1 -0
  54. package/dist/components/css/error-text/error-text.js +18 -0
  55. package/dist/components/css/error-text/error-text.js.map +1 -0
  56. package/dist/components/css/fieldset/fieldset.d.ts +55 -0
  57. package/dist/components/css/fieldset/fieldset.d.ts.map +1 -0
  58. package/dist/components/css/fieldset/fieldset.js +39 -0
  59. package/dist/components/css/fieldset/fieldset.js.map +1 -0
  60. package/dist/components/css/file-upload/file-upload.d.ts +41 -0
  61. package/dist/components/css/file-upload/file-upload.d.ts.map +1 -0
  62. package/dist/components/css/file-upload/file-upload.js +32 -0
  63. package/dist/components/css/file-upload/file-upload.js.map +1 -0
  64. package/dist/components/css/heading/heading.d.ts +29 -0
  65. package/dist/components/css/heading/heading.d.ts.map +1 -0
  66. package/dist/components/css/heading/heading.js +23 -0
  67. package/dist/components/css/heading/heading.js.map +1 -0
  68. package/dist/components/css/help-text/help-text.d.ts +24 -0
  69. package/dist/components/css/help-text/help-text.d.ts.map +1 -0
  70. package/dist/components/css/help-text/help-text.js +23 -0
  71. package/dist/components/css/help-text/help-text.js.map +1 -0
  72. package/dist/components/css/icon/icon.d.ts +34 -0
  73. package/dist/components/css/icon/icon.d.ts.map +1 -0
  74. package/dist/components/css/icon/icon.js +25 -0
  75. package/dist/components/css/icon/icon.js.map +1 -0
  76. package/dist/components/css/input/input.d.ts +40 -0
  77. package/dist/components/css/input/input.d.ts.map +1 -0
  78. package/dist/components/css/input/input.js +45 -0
  79. package/dist/components/css/input/input.js.map +1 -0
  80. package/dist/components/css/label/label.d.ts +33 -0
  81. package/dist/components/css/label/label.d.ts.map +1 -0
  82. package/dist/components/css/label/label.js +23 -0
  83. package/dist/components/css/label/label.js.map +1 -0
  84. package/dist/components/css/link/link.d.ts +28 -0
  85. package/dist/components/css/link/link.d.ts.map +1 -0
  86. package/dist/components/css/link/link.js +20 -0
  87. package/dist/components/css/link/link.js.map +1 -0
  88. package/dist/components/css/list/list.d.ts +31 -0
  89. package/dist/components/css/list/list.d.ts.map +1 -0
  90. package/dist/components/css/list/list.js +25 -0
  91. package/dist/components/css/list/list.js.map +1 -0
  92. package/dist/components/css/pagination/pagination.d.ts +27 -0
  93. package/dist/components/css/pagination/pagination.d.ts.map +1 -0
  94. package/dist/components/css/pagination/pagination.js +25 -0
  95. package/dist/components/css/pagination/pagination.js.map +1 -0
  96. package/dist/components/css/paragraph/paragraph.d.ts +36 -0
  97. package/dist/components/css/paragraph/paragraph.d.ts.map +1 -0
  98. package/dist/components/css/paragraph/paragraph.js +26 -0
  99. package/dist/components/css/paragraph/paragraph.js.map +1 -0
  100. package/dist/components/css/progress/progress.d.ts +53 -0
  101. package/dist/components/css/progress/progress.d.ts.map +1 -0
  102. package/dist/components/css/progress/progress.js +38 -0
  103. package/dist/components/css/progress/progress.js.map +1 -0
  104. package/dist/components/css/radio/radio.d.ts +32 -0
  105. package/dist/components/css/radio/radio.d.ts.map +1 -0
  106. package/dist/components/css/radio/radio.js +27 -0
  107. package/dist/components/css/radio/radio.js.map +1 -0
  108. package/dist/components/css/search/search.d.ts +34 -0
  109. package/dist/components/css/search/search.d.ts.map +1 -0
  110. package/dist/components/css/search/search.js +32 -0
  111. package/dist/components/css/search/search.js.map +1 -0
  112. package/dist/components/css/select/select.d.ts +40 -0
  113. package/dist/components/css/select/select.d.ts.map +1 -0
  114. package/dist/components/css/select/select.js +31 -0
  115. package/dist/components/css/select/select.js.map +1 -0
  116. package/dist/components/css/shared.d.ts +90 -0
  117. package/dist/components/css/shared.d.ts.map +1 -0
  118. package/dist/components/css/shared.js +167 -0
  119. package/dist/components/css/shared.js.map +1 -0
  120. package/dist/components/css/skeleton/skeleton.d.ts +29 -0
  121. package/dist/components/css/skeleton/skeleton.d.ts.map +1 -0
  122. package/dist/components/css/skeleton/skeleton.js +23 -0
  123. package/dist/components/css/skeleton/skeleton.js.map +1 -0
  124. package/dist/components/css/skip-link/skip-link.d.ts +18 -0
  125. package/dist/components/css/skip-link/skip-link.d.ts.map +1 -0
  126. package/dist/components/css/skip-link/skip-link.js +16 -0
  127. package/dist/components/css/skip-link/skip-link.js.map +1 -0
  128. package/dist/components/css/spinner/spinner.d.ts +33 -0
  129. package/dist/components/css/spinner/spinner.d.ts.map +1 -0
  130. package/dist/components/css/spinner/spinner.js +25 -0
  131. package/dist/components/css/spinner/spinner.js.map +1 -0
  132. package/dist/components/css/sr-only/sr-only.d.ts +17 -0
  133. package/dist/components/css/sr-only/sr-only.d.ts.map +1 -0
  134. package/dist/components/css/sr-only/sr-only.js +15 -0
  135. package/dist/components/css/sr-only/sr-only.js.map +1 -0
  136. package/dist/components/css/switch/switch.d.ts +37 -0
  137. package/dist/components/css/switch/switch.d.ts.map +1 -0
  138. package/dist/components/css/switch/switch.js +29 -0
  139. package/dist/components/css/switch/switch.js.map +1 -0
  140. package/dist/components/css/table/table.d.ts +76 -0
  141. package/dist/components/css/table/table.d.ts.map +1 -0
  142. package/dist/components/css/table/table.js +59 -0
  143. package/dist/components/css/table/table.js.map +1 -0
  144. package/dist/components/css/tag/tag.d.ts +35 -0
  145. package/dist/components/css/tag/tag.d.ts.map +1 -0
  146. package/dist/components/css/tag/tag.js +27 -0
  147. package/dist/components/css/tag/tag.js.map +1 -0
  148. package/dist/components/css/textarea/textarea.d.ts +23 -0
  149. package/dist/components/css/textarea/textarea.d.ts.map +1 -0
  150. package/dist/components/css/textarea/textarea.js +18 -0
  151. package/dist/components/css/textarea/textarea.js.map +1 -0
  152. package/dist/components/css/toggle-group/toggle-group.d.ts +31 -0
  153. package/dist/components/css/toggle-group/toggle-group.d.ts.map +1 -0
  154. package/dist/components/css/toggle-group/toggle-group.js +29 -0
  155. package/dist/components/css/toggle-group/toggle-group.js.map +1 -0
  156. package/dist/components/css/tooltip/tooltip.d.ts +31 -0
  157. package/dist/components/css/tooltip/tooltip.d.ts.map +1 -0
  158. package/dist/components/css/tooltip/tooltip.js +29 -0
  159. package/dist/components/css/tooltip/tooltip.js.map +1 -0
  160. package/dist/components/default-texts.d.ts +41 -0
  161. package/dist/components/default-texts.d.ts.map +1 -0
  162. package/dist/components/default-texts.js +41 -0
  163. package/dist/components/default-texts.js.map +1 -0
  164. package/dist/components/events.d.ts +77 -0
  165. package/dist/components/events.d.ts.map +1 -0
  166. package/dist/components/events.js +3 -0
  167. package/dist/components/events.js.map +1 -0
  168. package/dist/components/frame/dialog/dialog.d.ts +122 -0
  169. package/dist/components/frame/dialog/dialog.d.ts.map +1 -0
  170. package/dist/components/frame/dialog/dialog.js +112 -0
  171. package/dist/components/frame/dialog/dialog.js.map +1 -0
  172. package/dist/components/frame/dialog/lt-dialog.d.ts +104 -0
  173. package/dist/components/frame/dialog/lt-dialog.d.ts.map +1 -0
  174. package/dist/components/frame/dialog/lt-dialog.js +434 -0
  175. package/dist/components/frame/dialog/lt-dialog.js.map +1 -0
  176. package/dist/components/frame/error-summary/error-summary.d.ts +53 -0
  177. package/dist/components/frame/error-summary/error-summary.d.ts.map +1 -0
  178. package/dist/components/frame/error-summary/error-summary.js +54 -0
  179. package/dist/components/frame/error-summary/error-summary.js.map +1 -0
  180. package/dist/components/frame/error-summary/lt-error-summary.d.ts +93 -0
  181. package/dist/components/frame/error-summary/lt-error-summary.d.ts.map +1 -0
  182. package/dist/components/frame/error-summary/lt-error-summary.js +408 -0
  183. package/dist/components/frame/error-summary/lt-error-summary.js.map +1 -0
  184. package/dist/components/frame/field/field-core.d.ts +92 -0
  185. package/dist/components/frame/field/field-core.d.ts.map +1 -0
  186. package/dist/components/frame/field/field-core.js +63 -0
  187. package/dist/components/frame/field/field-core.js.map +1 -0
  188. package/dist/components/frame/field/lt-field.d.ts +173 -0
  189. package/dist/components/frame/field/lt-field.d.ts.map +1 -0
  190. package/dist/components/frame/field/lt-field.js +600 -0
  191. package/dist/components/frame/field/lt-field.js.map +1 -0
  192. package/dist/components/frame/popover/lt-popover.d.ts +136 -0
  193. package/dist/components/frame/popover/lt-popover.d.ts.map +1 -0
  194. package/dist/components/frame/popover/lt-popover.js +520 -0
  195. package/dist/components/frame/popover/lt-popover.js.map +1 -0
  196. package/dist/components/frame/popover/popover.d.ts +49 -0
  197. package/dist/components/frame/popover/popover.d.ts.map +1 -0
  198. package/dist/components/frame/popover/popover.js +64 -0
  199. package/dist/components/frame/popover/popover.js.map +1 -0
  200. package/dist/components/frame/session-timeout/lt-session-timeout.d.ts +198 -0
  201. package/dist/components/frame/session-timeout/lt-session-timeout.d.ts.map +1 -0
  202. package/dist/components/frame/session-timeout/lt-session-timeout.js +610 -0
  203. package/dist/components/frame/session-timeout/lt-session-timeout.js.map +1 -0
  204. package/dist/components/frame/session-timeout/session-timeout.d.ts +113 -0
  205. package/dist/components/frame/session-timeout/session-timeout.d.ts.map +1 -0
  206. package/dist/components/frame/session-timeout/session-timeout.js +101 -0
  207. package/dist/components/frame/session-timeout/session-timeout.js.map +1 -0
  208. package/dist/components/frame/suggestion/lt-suggestion.d.ts +367 -0
  209. package/dist/components/frame/suggestion/lt-suggestion.d.ts.map +1 -0
  210. package/dist/components/frame/suggestion/lt-suggestion.js +1171 -0
  211. package/dist/components/frame/suggestion/lt-suggestion.js.map +1 -0
  212. package/dist/components/frame/suggestion/suggestion.d.ts +143 -0
  213. package/dist/components/frame/suggestion/suggestion.d.ts.map +1 -0
  214. package/dist/components/frame/suggestion/suggestion.js +127 -0
  215. package/dist/components/frame/suggestion/suggestion.js.map +1 -0
  216. package/dist/components/frame/tabs/lt-tabs.d.ts +426 -0
  217. package/dist/components/frame/tabs/lt-tabs.d.ts.map +1 -0
  218. package/dist/components/frame/tabs/lt-tabs.js +1265 -0
  219. package/dist/components/frame/tabs/lt-tabs.js.map +1 -0
  220. package/dist/components/frame/tabs/tabs.d.ts +112 -0
  221. package/dist/components/frame/tabs/tabs.d.ts.map +1 -0
  222. package/dist/components/frame/tabs/tabs.js +107 -0
  223. package/dist/components/frame/tabs/tabs.js.map +1 -0
  224. package/dist/components/host-element.d.ts +184 -0
  225. package/dist/components/host-element.d.ts.map +1 -0
  226. package/dist/components/host-element.js +440 -0
  227. package/dist/components/host-element.js.map +1 -0
  228. package/dist/components/standalone/connection-status/connection-status.d.ts +32 -0
  229. package/dist/components/standalone/connection-status/connection-status.d.ts.map +1 -0
  230. package/dist/components/standalone/connection-status/connection-status.js +26 -0
  231. package/dist/components/standalone/connection-status/connection-status.js.map +1 -0
  232. package/dist/components/standalone/connection-status/lt-connection-status.d.ts +86 -0
  233. package/dist/components/standalone/connection-status/lt-connection-status.d.ts.map +1 -0
  234. package/dist/components/standalone/connection-status/lt-connection-status.js +240 -0
  235. package/dist/components/standalone/connection-status/lt-connection-status.js.map +1 -0
  236. package/dist/components/standalone/toast/lt-toast.d.ts +109 -0
  237. package/dist/components/standalone/toast/lt-toast.d.ts.map +1 -0
  238. package/dist/components/standalone/toast/lt-toast.js +256 -0
  239. package/dist/components/standalone/toast/lt-toast.js.map +1 -0
  240. package/dist/components/standalone/toast/toast.d.ts +52 -0
  241. package/dist/components/standalone/toast/toast.d.ts.map +1 -0
  242. package/dist/components/standalone/toast/toast.js +42 -0
  243. package/dist/components/standalone/toast/toast.js.map +1 -0
  244. package/dist/diagnostics/core.d.ts +171 -0
  245. package/dist/diagnostics/core.d.ts.map +1 -0
  246. package/dist/diagnostics/core.js +84 -0
  247. package/dist/diagnostics/core.js.map +1 -0
  248. package/dist/diagnostics/default-core.d.ts +10 -0
  249. package/dist/diagnostics/default-core.d.ts.map +1 -0
  250. package/dist/diagnostics/default-core.js +72 -0
  251. package/dist/diagnostics/default-core.js.map +1 -0
  252. package/dist/diagnostics/index.d.ts +84 -0
  253. package/dist/diagnostics/index.d.ts.map +1 -0
  254. package/dist/diagnostics/index.js +106 -0
  255. package/dist/diagnostics/index.js.map +1 -0
  256. package/dist/dom.d.ts +55 -0
  257. package/dist/dom.d.ts.map +1 -0
  258. package/dist/dom.js +162 -0
  259. package/dist/dom.js.map +1 -0
  260. package/dist/index.d.ts +97 -0
  261. package/dist/index.d.ts.map +1 -0
  262. package/dist/index.js +58 -0
  263. package/dist/index.js.map +1 -0
  264. package/dist/jsx/react.d.ts +180 -0
  265. package/dist/jsx/react.d.ts.map +1 -0
  266. package/dist/jsx/react.js +2 -0
  267. package/dist/jsx/react.js.map +1 -0
  268. package/dist/lotek.css +3617 -0
  269. package/dist/lt.d.ts +325 -0
  270. package/dist/lt.d.ts.map +1 -0
  271. package/dist/lt.js +183 -0
  272. package/dist/lt.js.map +1 -0
  273. package/dist/react.d.ts +494 -0
  274. package/dist/react.d.ts.map +1 -0
  275. package/dist/react.js +296 -0
  276. package/dist/react.js.map +1 -0
  277. package/dist/register.d.ts +17 -0
  278. package/dist/register.d.ts.map +1 -0
  279. package/dist/register.js +35 -0
  280. package/dist/register.js.map +1 -0
  281. package/dist/tokens/color.d.ts +43 -0
  282. package/dist/tokens/color.d.ts.map +1 -0
  283. package/dist/tokens/color.js +123 -0
  284. package/dist/tokens/color.js.map +1 -0
  285. package/dist/tokens/contract.d.ts +18 -0
  286. package/dist/tokens/contract.d.ts.map +1 -0
  287. package/dist/tokens/contract.js +18 -0
  288. package/dist/tokens/contract.js.map +1 -0
  289. package/dist/tokens/matrix-cells.d.ts +30 -0
  290. package/dist/tokens/matrix-cells.d.ts.map +1 -0
  291. package/dist/tokens/matrix-cells.js +273 -0
  292. package/dist/tokens/matrix-cells.js.map +1 -0
  293. package/dist/tokens/matrix.d.ts +18 -0
  294. package/dist/tokens/matrix.d.ts.map +1 -0
  295. package/dist/tokens/matrix.js +21 -0
  296. package/dist/tokens/matrix.js.map +1 -0
  297. package/dist/tokens/theme-check.d.ts +42 -0
  298. package/dist/tokens/theme-check.d.ts.map +1 -0
  299. package/dist/tokens/theme-check.js +10 -0
  300. package/dist/tokens/theme-check.js.map +1 -0
  301. package/dist/tokens/theme.d.ts +94 -0
  302. package/dist/tokens/theme.d.ts.map +1 -0
  303. package/dist/tokens/theme.js +14 -0
  304. package/dist/tokens/theme.js.map +1 -0
  305. package/dist/tokens/tokens.d.ts +122 -0
  306. package/dist/tokens/tokens.d.ts.map +1 -0
  307. package/dist/tokens/tokens.js +158 -0
  308. package/dist/tokens/tokens.js.map +1 -0
  309. package/dist/vocabulary/classes.d.ts +3 -0
  310. package/dist/vocabulary/classes.d.ts.map +1 -0
  311. package/dist/vocabulary/classes.js +1354 -0
  312. package/dist/vocabulary/classes.js.map +1 -0
  313. package/dist/vocabulary/elements.d.ts +3 -0
  314. package/dist/vocabulary/elements.d.ts.map +1 -0
  315. package/dist/vocabulary/elements.js +490 -0
  316. package/dist/vocabulary/elements.js.map +1 -0
  317. package/dist/vocabulary/types.d.ts +229 -0
  318. package/dist/vocabulary/types.d.ts.map +1 -0
  319. package/dist/vocabulary/types.js +11 -0
  320. package/dist/vocabulary/types.js.map +1 -0
  321. package/dist/wasi-host.d.ts +24 -0
  322. package/dist/wasi-host.d.ts.map +1 -0
  323. package/dist/wasi-host.js +140 -0
  324. package/dist/wasi-host.js.map +1 -0
  325. package/live-templates.xml +63 -0
  326. package/manifest/files.json +373 -0
  327. package/manifest/manifest.json +5090 -0
  328. package/manifest/manifest.schema.json +586 -0
  329. package/package.json +399 -5
  330. package/src/cli.ts +21 -0
  331. package/src/components/css/accordion/accordion.css +102 -0
  332. package/src/components/css/accordion/accordion.ts +50 -0
  333. package/src/components/css/alert/alert.css +53 -0
  334. package/src/components/css/alert/alert.ts +48 -0
  335. package/src/components/css/avatar/avatar.css +96 -0
  336. package/src/components/css/avatar/avatar.ts +57 -0
  337. package/src/components/css/badge/badge.css +42 -0
  338. package/src/components/css/badge/badge.ts +43 -0
  339. package/src/components/css/breadcrumbs/breadcrumbs.css +62 -0
  340. package/src/components/css/breadcrumbs/breadcrumbs.ts +30 -0
  341. package/src/components/css/button/button.css +128 -0
  342. package/src/components/css/button/button.ts +44 -0
  343. package/src/components/css/card/card.css +65 -0
  344. package/src/components/css/card/card.ts +50 -0
  345. package/src/components/css/checkbox/checkbox.css +114 -0
  346. package/src/components/css/checkbox/checkbox.ts +50 -0
  347. package/src/components/css/divider/divider.css +38 -0
  348. package/src/components/css/divider/divider.ts +42 -0
  349. package/src/components/css/error-text/error-text.css +21 -0
  350. package/src/components/css/error-text/error-text.ts +37 -0
  351. package/src/components/css/fieldset/fieldset.css +72 -0
  352. package/src/components/css/fieldset/fieldset.ts +87 -0
  353. package/src/components/css/file-upload/file-upload.css +102 -0
  354. package/src/components/css/file-upload/file-upload.ts +65 -0
  355. package/src/components/css/heading/heading.css +33 -0
  356. package/src/components/css/heading/heading.ts +42 -0
  357. package/src/components/css/help-text/help-text.css +24 -0
  358. package/src/components/css/help-text/help-text.ts +42 -0
  359. package/src/components/css/icon/icon.css +20 -0
  360. package/src/components/css/icon/icon.ts +44 -0
  361. package/src/components/css/input/input.css +145 -0
  362. package/src/components/css/input/input.ts +77 -0
  363. package/src/components/css/label/label.css +42 -0
  364. package/src/components/css/label/label.ts +51 -0
  365. package/src/components/css/link/link.css +38 -0
  366. package/src/components/css/link/link.ts +38 -0
  367. package/src/components/css/list/list.css +53 -0
  368. package/src/components/css/list/list.ts +44 -0
  369. package/src/components/css/pagination/pagination.css +95 -0
  370. package/src/components/css/pagination/pagination.ts +33 -0
  371. package/src/components/css/paragraph/paragraph.css +31 -0
  372. package/src/components/css/paragraph/paragraph.ts +53 -0
  373. package/src/components/css/progress/progress.css +161 -0
  374. package/src/components/css/progress/progress.ts +78 -0
  375. package/src/components/css/radio/radio.css +94 -0
  376. package/src/components/css/radio/radio.ts +50 -0
  377. package/src/components/css/search/search.css +50 -0
  378. package/src/components/css/search/search.ts +56 -0
  379. package/src/components/css/select/select.css +321 -0
  380. package/src/components/css/select/select.ts +63 -0
  381. package/src/components/css/shared.ts +199 -0
  382. package/src/components/css/skeleton/skeleton.css +62 -0
  383. package/src/components/css/skeleton/skeleton.ts +43 -0
  384. package/src/components/css/skip-link/skip-link.css +41 -0
  385. package/src/components/css/skip-link/skip-link.ts +22 -0
  386. package/src/components/css/spinner/spinner.css +48 -0
  387. package/src/components/css/spinner/spinner.ts +48 -0
  388. package/src/components/css/sr-only/sr-only.css +16 -0
  389. package/src/components/css/sr-only/sr-only.ts +21 -0
  390. package/src/components/css/switch/switch.css +105 -0
  391. package/src/components/css/switch/switch.ts +50 -0
  392. package/src/components/css/table/table.css +159 -0
  393. package/src/components/css/table/table.ts +107 -0
  394. package/src/components/css/tag/tag.css +58 -0
  395. package/src/components/css/tag/tag.ts +49 -0
  396. package/src/components/css/textarea/textarea.css +83 -0
  397. package/src/components/css/textarea/textarea.ts +40 -0
  398. package/src/components/css/toggle-group/toggle-group.css +92 -0
  399. package/src/components/css/toggle-group/toggle-group.ts +37 -0
  400. package/src/components/css/tooltip/tooltip.css +89 -0
  401. package/src/components/css/tooltip/tooltip.ts +37 -0
  402. package/src/components/default-texts.ts +41 -0
  403. package/src/components/events.ts +68 -0
  404. package/src/components/frame/dialog/dialog.css +306 -0
  405. package/src/components/frame/dialog/dialog.ts +166 -0
  406. package/src/components/frame/dialog/lt-dialog.ts +513 -0
  407. package/src/components/frame/error-summary/error-summary.css +47 -0
  408. package/src/components/frame/error-summary/error-summary.ts +90 -0
  409. package/src/components/frame/error-summary/lt-error-summary.ts +458 -0
  410. package/src/components/frame/field/field-core.ts +152 -0
  411. package/src/components/frame/field/field.css +17 -0
  412. package/src/components/frame/field/lt-field.ts +790 -0
  413. package/src/components/frame/popover/lt-popover.ts +586 -0
  414. package/src/components/frame/popover/popover.css +50 -0
  415. package/src/components/frame/popover/popover.ts +102 -0
  416. package/src/components/frame/session-timeout/lt-session-timeout.ts +715 -0
  417. package/src/components/frame/session-timeout/session-timeout.css +50 -0
  418. package/src/components/frame/session-timeout/session-timeout.ts +156 -0
  419. package/src/components/frame/suggestion/lt-suggestion.ts +1379 -0
  420. package/src/components/frame/suggestion/suggestion.css +132 -0
  421. package/src/components/frame/suggestion/suggestion.ts +172 -0
  422. package/src/components/frame/tabs/lt-tabs.ts +1395 -0
  423. package/src/components/frame/tabs/tabs.css +128 -0
  424. package/src/components/frame/tabs/tabs.ts +188 -0
  425. package/src/components/host-element.ts +493 -0
  426. package/src/components/standalone/connection-status/connection-status.css +41 -0
  427. package/src/components/standalone/connection-status/connection-status.ts +47 -0
  428. package/src/components/standalone/connection-status/lt-connection-status.ts +268 -0
  429. package/src/components/standalone/toast/lt-toast.ts +300 -0
  430. package/src/components/standalone/toast/toast.css +78 -0
  431. package/src/components/standalone/toast/toast.ts +70 -0
  432. package/src/diagnostics/core.ts +227 -0
  433. package/src/diagnostics/default-core.ts +81 -0
  434. package/src/diagnostics/index.ts +150 -0
  435. package/src/dom.ts +185 -0
  436. package/src/index.ts +218 -0
  437. package/src/jsx/react.ts +212 -0
  438. package/src/lt.ts +192 -0
  439. package/src/react.ts +411 -0
  440. package/src/register.ts +43 -0
  441. package/src/tailwind/tailwind.css +169 -0
  442. package/src/tokens/boundary.css +104 -0
  443. package/src/tokens/color-contract.json +231 -0
  444. package/src/tokens/color.ts +150 -0
  445. package/src/tokens/contract.ts +24 -0
  446. package/src/tokens/matrix-cells.ts +375 -0
  447. package/src/tokens/matrix.ts +32 -0
  448. package/src/tokens/theme-check.ts +51 -0
  449. package/src/tokens/theme.ts +104 -0
  450. package/src/tokens/tokens.css +569 -0
  451. package/src/tokens/tokens.ts +223 -0
  452. package/src/vocabulary/classes.ts +1356 -0
  453. package/src/vocabulary/elements.ts +492 -0
  454. package/src/vocabulary/types.ts +228 -0
  455. package/src/wasi-host.ts +155 -0
  456. package/web-types.json +800 -0
@@ -0,0 +1,493 @@
1
+ /**
2
+ * The base the web components inherit from, and their registration.
3
+ *
4
+ * `HTMLElement` and `customElements` only exist in the browser. A
5
+ * `class X extends HTMLElement` is evaluated when the module loads, so a
6
+ * server that only wanted `lt.button()` from the package stopped with
7
+ * "HTMLElement is not defined" before it got that far. That hit nine of the
8
+ * entry points, the main entry included, and made the package useless in
9
+ * exactly the situation it is built for: the server writing the markup.
10
+ *
11
+ * The fallback is an empty class. It is never used for anything, because
12
+ * without `customElements` nothing is registered, and without registration
13
+ * the browser never creates an instance. It only exists so the module can
14
+ * load.
15
+ */
16
+
17
+ export const HostElement =
18
+ typeof HTMLElement === "undefined"
19
+ ? (class {} as unknown as typeof HTMLElement)
20
+ : HTMLElement
21
+
22
+ /*
23
+ * The types of the events, such as `dialog-toggle` with `detail.open`. Every
24
+ * web component inherits from here, so the types come with all their entry
25
+ * points, and `addEventListener` on an element is typed without a separate
26
+ * import.
27
+ */
28
+ export type { LtEventMap } from "./events.js"
29
+
30
+ /**
31
+ * Registers a web component, once, and only in the browser.
32
+ *
33
+ * When `defineLt*` is called from a module that also runs on the server, as
34
+ * in TanStack Start or a server-rendered React app, nothing happens. There is
35
+ * no `customElements` there to register in.
36
+ *
37
+ * A constructor can only be in the registry once. If the class is already
38
+ * there under another name, a subclass is registered:
39
+ * `defineLtToast("app-toast")` followed by `defineLt()` otherwise threw
40
+ * NotSupportedError on `lt-toast`, and the components after it in the list
41
+ * were never registered. With the subclass both names work, and `instanceof`
42
+ * holds for both.
43
+ */
44
+ export function defineElement(
45
+ tagName: string,
46
+ element: CustomElementConstructor,
47
+ ): void {
48
+ if (typeof customElements === "undefined") return
49
+ if (customElements.get(tagName)) return
50
+ if (isRegistered(element)) {
51
+ customElements.define(tagName, class extends element {})
52
+ return
53
+ }
54
+ try {
55
+ customElements.define(tagName, element)
56
+ } catch (error) {
57
+ // The fallback for browsers without `getName`: the name is free, so a
58
+ // NotSupportedError here means the constructor is already in use.
59
+ if (!(error instanceof DOMException && error.name === "NotSupportedError"))
60
+ throw error
61
+ customElements.define(tagName, class extends element {})
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Whether the constructor is already in the registry, under any name.
67
+ * `getName` arrived in Chrome 117, Firefox 116 and Safari 17; without it the
68
+ * answer is `false`, and `define` reports the problem itself.
69
+ */
70
+ function isRegistered(element: CustomElementConstructor): boolean {
71
+ if (typeof customElements.getName !== "function") return false
72
+ return customElements.getName(element) !== null
73
+ }
74
+
75
+ /**
76
+ * Sets an attribute, but only when the value actually differs.
77
+ *
78
+ * The components observe the attributes they set themselves, so they can set
79
+ * them back after a patch. Writing a value that is already there counts as a
80
+ * change, so the observer calls itself, writes again, and the microtask queue
81
+ * never empties. The page freezes, and a test run hangs without an error: no
82
+ * stack trace, no assertion, just silence. That is why no test can catch it,
83
+ * and why writes go through one function all the components use.
84
+ *
85
+ * `null` removes the attribute.
86
+ */
87
+ export function setAttr(
88
+ element: Element,
89
+ name: string,
90
+ value: string | null | undefined,
91
+ ): void {
92
+ if (value === null || value === undefined) {
93
+ if (element.hasAttribute(name)) element.removeAttribute(name)
94
+ } else if (element.getAttribute(name) !== value) {
95
+ element.setAttribute(name, value)
96
+ }
97
+ }
98
+
99
+ /**
100
+ * The attribute a component marks what it wrote with: the names of the
101
+ * attributes on the element whose value is the component's, separated by
102
+ * spaces.
103
+ *
104
+ * Some attributes are both the server's and the component's: `aria-invalid`
105
+ * on a field, `aria-selected` on a tab. To tell the server's word from its
106
+ * own echo, a component remembered the value it wrote, and read anything
107
+ * else as the server's. A server that sent the same value was never seen: a
108
+ * morph does not touch an attribute whose value is already right, and the
109
+ * component took the server's `aria-invalid="true"` for its own and removed
110
+ * it. The mark is what a morph does touch. The server never sends it, so a
111
+ * morph from the server removes it, and an attribute without the mark is the
112
+ * server's, whatever its value. A script that changes the element without a
113
+ * morph leaves the mark, and is seen as before, by the value.
114
+ *
115
+ * Only what differs from the server's word is marked. A value that is the
116
+ * server's has nothing to tell apart, and markup that is already right, as
117
+ * React renders `lt.tabs()` with the state, must not be touched: hydration
118
+ * reports every attribute it did not render.
119
+ */
120
+ export const WRITTEN = "data-lt-written"
121
+
122
+ /**
123
+ * Marks `name` on `element` as the component's when `mine`, that is, when
124
+ * what the component wrote differs from the server's word, and removes the
125
+ * mark otherwise.
126
+ */
127
+ export function markWritten(
128
+ element: Element,
129
+ name: string,
130
+ mine: boolean,
131
+ ): void {
132
+ const marked = new Set(
133
+ (element.getAttribute(WRITTEN) ?? "").split(/\s+/).filter(Boolean),
134
+ )
135
+ if (mine) marked.add(name)
136
+ else marked.delete(name)
137
+ setAttr(
138
+ element,
139
+ WRITTEN,
140
+ marked.size > 0 ? [...marked].sort().join(" ") : null,
141
+ )
142
+ }
143
+
144
+ /**
145
+ * Warns when `element` carries the mark before the component has written on
146
+ * it: the mark is in the markup it was given, copied into a template from
147
+ * the browser's developer tools. A morph then never removes it, and the
148
+ * component takes the server's word for its own echo again. Called where the
149
+ * component meets the element for the first time; the check cannot wait, so
150
+ * the warning is not checked again when the page has settled.
151
+ */
152
+ export function warnAboutCopiedMark(host: Element, element: Element): void {
153
+ if (!element.hasAttribute(WRITTEN)) return
154
+ warnAboutMarkup(
155
+ host,
156
+ `found ${WRITTEN} in the markup it was given. The browser writes the ` +
157
+ "attribute to tell the component's own values from the server's; " +
158
+ "copied into a template, it makes the component take what the " +
159
+ "server sends for its own. Remove it from the template.",
160
+ () => true,
161
+ )
162
+ }
163
+
164
+ /**
165
+ * Whether the component's mark for `name` is still on `element`: no morph
166
+ * from the server has been there since the component wrote it.
167
+ */
168
+ export function stillMarked(element: Element, name: string): boolean {
169
+ return (element.getAttribute(WRITTEN) ?? "").split(/\s+/).includes(name)
170
+ }
171
+
172
+ /**
173
+ * Turns a boolean attribute on or off, without writing when it is already so.
174
+ *
175
+ * `el.hidden = true` on something already hidden writes the attribute again,
176
+ * and that counts as a change. `toggleAttribute` does not: if the attribute
177
+ * is already as it should be, nothing happens. So it is the only permitted
178
+ * way to `hidden`, `disabled` and the other boolean attributes in a component
179
+ * that observes the attributes it writes.
180
+ *
181
+ * `Boolean(on)` and not `on` alone: with `undefined` as the second argument
182
+ * `toggleAttribute` toggles instead of removing. React 19 writes
183
+ * `el.open = undefined` when a prop goes from `true` to absent, and the
184
+ * setter then put the attribute back: a dialog the user had closed opened
185
+ * again as the app followed along.
186
+ */
187
+ export function setFlag(element: Element, name: string, on: boolean): void {
188
+ element.toggleAttribute(name, Boolean(on))
189
+ }
190
+
191
+ /**
192
+ * The language nearest the element, or `undefined` when the page does not
193
+ * say.
194
+ *
195
+ * `undefined` gives `Intl` the browser's language. A `lang` that is not a
196
+ * valid language tag makes `Intl` throw, and then the browser's language is
197
+ * better than no text.
198
+ */
199
+ export function languageOf(element: Element): string | undefined {
200
+ /*
201
+ * `closest()` stops at a shadow root. If the element is in one, as in
202
+ * every preview in the documentation, the search continues from the host;
203
+ * otherwise it never found `lang` on `<html>`.
204
+ */
205
+ let node: Element | null = element
206
+ while (node) {
207
+ const owner = node.closest("[lang]")
208
+ // `lang=""` means "unknown language" and stops inheritance from the ancestors.
209
+ if (owner) {
210
+ const lang = owner.getAttribute("lang")?.trim()
211
+ if (!lang) return undefined
212
+ try {
213
+ Intl.getCanonicalLocales(lang)
214
+ return lang
215
+ } catch {
216
+ return undefined
217
+ }
218
+ }
219
+ const root = node.getRootNode()
220
+ node = root instanceof ShadowRoot ? root.host : null
221
+ }
222
+ return undefined
223
+ }
224
+
225
+ /**
226
+ * Writes text in an element, but only when the text differs.
227
+ *
228
+ * `textContent` is a `childList` change, and the components observe their
229
+ * children. Writing the same text again counts as a change, and then the
230
+ * observer calls itself.
231
+ *
232
+ * `textContent` is all the text in the subtree joined, so the comparison does
233
+ * not tell `<b>3</b> matches` from `3 matches`. The function is meant for
234
+ * elements the component fills with plain text, such as the match count in
235
+ * the suggestion field.
236
+ */
237
+ export function setText(element: Element, text: string): void {
238
+ if (element.textContent !== text) element.textContent = text
239
+ }
240
+
241
+ /** Adds a class, but only when it is not already there. */
242
+ export function addClass(element: Element, name: string): void {
243
+ if (!element.classList.contains(name)) element.classList.add(name)
244
+ }
245
+
246
+ /** An id the component creates itself, when the markup had none. */
247
+ export function uniqueId(prefix: string): string {
248
+ return `${prefix}-${Math.random().toString(36).slice(2, 9)}`
249
+ }
250
+
251
+ /**
252
+ * The id an element should have: the one it has, otherwise the one the
253
+ * component created for that node before. A morph keeps the node and tears
254
+ * the id off, and it gets the same one back, so a screen reader does not
255
+ * follow a reference that changes under it.
256
+ */
257
+ export function rememberedId(
258
+ memory: WeakMap<Element, string>,
259
+ element: Element,
260
+ prefix: string,
261
+ ): string {
262
+ if (element.id) return element.id
263
+ let id = memory.get(element)
264
+ if (!id) {
265
+ id = uniqueId(prefix)
266
+ memory.set(element, id)
267
+ }
268
+ return id
269
+ }
270
+
271
+ /**
272
+ * The parts with a role, and those without only when the component set the
273
+ * roles itself.
274
+ *
275
+ * The components fill in roles where the markup came without them: a button
276
+ * in the row becomes a tab, an `<li>` in the list becomes an option. But if
277
+ * the server wrote the roles, an element without a role is something else,
278
+ * such as a "close" button in the row, and must not get a role, an id and
279
+ * `tabindex="-1"` from the component. `roledByHost` holds the roles the
280
+ * component set itself: if every role present was set by the component, the
281
+ * markup is bare, and an element without a role that the server sends later
282
+ * is a new part. The parts are limited to the host, since components inside
283
+ * components are ordinary markup.
284
+ */
285
+ export function derivedParts<T extends Element>(
286
+ host: Element,
287
+ selector: string,
288
+ role: string,
289
+ roledByHost: WeakSet<Element>,
290
+ ): T[] {
291
+ const own = [...host.querySelectorAll<T>(selector)].filter(
292
+ (part) => part.closest(host.localName) === host,
293
+ )
294
+ const bare = own
295
+ .filter((part) => part.getAttribute("role") === role)
296
+ .every((part) => roledByHost.has(part))
297
+ return bare ? own : own.filter((part) => part.getAttribute("role") === role)
298
+ }
299
+
300
+ /**
301
+ * The attribute that gives the state back to the server.
302
+ *
303
+ * By default the components repair what the user has done: the selected tab,
304
+ * the open popover, the expanded suggestion list. A morph tears it away,
305
+ * since none of it was in the HTML the server sent, and the component sets it
306
+ * back. Then no template needs to know the attributes.
307
+ *
308
+ * Sometimes the server should decide: "go on to step 2" is a real thing a
309
+ * server wants to be able to do. With `server-controlled` on the host, the
310
+ * component does not set back what the user did, and each patch decides. It
311
+ * still does the wiring and the keyboard, and what the attribute means for
312
+ * each component is documented in the component.
313
+ *
314
+ * This replaces `data-preserve-attr`, which required the template to copy the
315
+ * name of every attribute the component would touch. One attribute to
316
+ * remember instead of nine, and the default is the right choice almost
317
+ * always.
318
+ *
319
+ * Preserving is also a mechanism of one particular morpher:
320
+ * `data-preserve-attr` is a `data-*` attribute, and such an attribute only
321
+ * means something to the code that reads it. Repair reads the markup, and
322
+ * works whoever does the morphing.
323
+ */
324
+ export const SERVER_CONTROLLED = "server-controlled" as const
325
+
326
+ /** Whether the server decides the state in this element. */
327
+ export function isServerControlled(element: Element): boolean {
328
+ return element.hasAttribute(SERVER_CONTROLLED)
329
+ }
330
+
331
+ /**
332
+ * Warns when the markup a component received does not fit together.
333
+ *
334
+ * A component that cannot find its parts cannot do its job, and the only
335
+ * alternative to a message is silence. It was silent for a long time: a
336
+ * template without a control in `<lt-field>` gave a field without wiring,
337
+ * and nothing said so until someone read the page with a screen reader.
338
+ *
339
+ * The message comes once per element and message. A component syncs on every
340
+ * patch, and a warning per patch would fill the console so fast it became
341
+ * useless. So the message must be the same every time: interpolate a number
342
+ * into it and every round is a new message, and the deduplication is gone.
343
+ *
344
+ * `stillBroken` is why the warning can be trusted. It is called again when
345
+ * the page has settled, and only then is anything written. A component sees
346
+ * its markup as it connects, and the markup is often unfinished then: HTML
347
+ * streamed from a Go or Kotlin server arrives in chunks, and a break between
348
+ * the label and the field is perfectly normal. Without the final check the
349
+ * component warned about markup that was fine a moment later, and a warning
350
+ * that also fires on correct markup gets switched off.
351
+ *
352
+ * It comes in every environment, not only during development. The package
353
+ * has no build step that could remove it, and a warning that only fires on
354
+ * markup that really is wrong belongs where it happens.
355
+ */
356
+ const reported = new WeakMap<Element, Set<string>>()
357
+ const queued = new WeakMap<Element, Set<string>>()
358
+
359
+ export function warnAboutMarkup(
360
+ element: Element,
361
+ message: string,
362
+ stillBroken: () => boolean,
363
+ ): void {
364
+ if (typeof console === "undefined") return
365
+ if (reported.get(element)?.has(message)) return
366
+
367
+ let pending = queued.get(element)
368
+ if (!pending) {
369
+ pending = new Set()
370
+ queued.set(element, pending)
371
+ }
372
+ if (pending.has(message)) return
373
+ pending.add(message)
374
+
375
+ whenSettled(() => {
376
+ pending.delete(message)
377
+ if (!element.isConnected || !stillBroken()) return
378
+
379
+ let said = reported.get(element)
380
+ if (!said) {
381
+ said = new Set()
382
+ reported.set(element, said)
383
+ }
384
+ if (said.has(message)) return
385
+ said.add(message)
386
+
387
+ console.warn(`${element.tagName.toLowerCase()}: ${message}`, element)
388
+ })
389
+ }
390
+
391
+ /**
392
+ * Runs once the page has settled.
393
+ *
394
+ * First the parser must be done, or we only see the part of the markup that
395
+ * has arrived so far. Then two frames, so a morph, a React hydration or a
396
+ * script that fills the element in the next task has time to finish first.
397
+ */
398
+ function whenSettled(run: () => void): void {
399
+ let done = false
400
+ const once = () => {
401
+ if (done) return
402
+ done = true
403
+ run()
404
+ }
405
+
406
+ const afterTwoFrames = () => {
407
+ if (typeof requestAnimationFrame === "undefined") {
408
+ once()
409
+ return
410
+ }
411
+ /*
412
+ * A fallback, because `requestAnimationFrame` does not always fire in a
413
+ * frame that is not painted. Tested in an `<iframe>` with
414
+ * `display: none`: Chromium and WebKit fire anyway, Firefox does not.
415
+ * Without the fallback the message stayed in the queue there for ever,
416
+ * and blocked a later, real warning about the same thing.
417
+ *
418
+ * It is not cancelled. An attempt to cancel it in the first frame was
419
+ * worse than the problem: if the first frame fires and the tab is hidden
420
+ * before the second, both the fallback and the second frame are gone,
421
+ * and the check never runs. `once` runs only once, so it does no harm
422
+ * that both paths are running, and whichever comes first wins.
423
+ *
424
+ * One second is chosen so two frames win in anything but a page that is
425
+ * completely stalled. If that happens, a warning about markup that is
426
+ * still unfinished is a small problem next to a frozen page.
427
+ */
428
+ setTimeout(once, 1000)
429
+ requestAnimationFrame(() => requestAnimationFrame(once))
430
+ }
431
+
432
+ if (typeof document !== "undefined" && document.readyState === "loading") {
433
+ document.addEventListener("DOMContentLoaded", afterTwoFrames, {
434
+ once: true,
435
+ })
436
+ return
437
+ }
438
+
439
+ afterTwoFrames()
440
+ }
441
+
442
+ /**
443
+ * Waits until the element has been upgraded to its component, and returns it
444
+ * with the right type.
445
+ *
446
+ * The components with an imperative API have `show()`, `reportFailure()` and
447
+ * `extend()`. If one of them is called before `defineLt*` has run, the
448
+ * element is still a plain `HTMLElement`, and the call fails with
449
+ * "reportSuccess is not a function". In production it happened in the gap
450
+ * between the server's HTML being there and the registration being loaded:
451
+ * the first message from the event stream arrived in that gap, and the app
452
+ * put a `typeof` guard around every call to get around it.
453
+ *
454
+ * The helpers around the methods instead wait for `whenDefined` on the
455
+ * element's actual tag name, so a call that comes too early is made as soon
456
+ * as the registration is there. `upgrade()` covers an element not yet in the
457
+ * document; one that is in it is already upgraded when `whenDefined`
458
+ * resolves.
459
+ *
460
+ * An element nobody registers would otherwise wait silently for ever. After
461
+ * three seconds the helper says so in the console, once per tag name, and
462
+ * keeps waiting: if the registration comes late, the call should still be
463
+ * made.
464
+ */
465
+ const UPGRADE_WARNING_MS = 3000
466
+ const warnedTags = new Set<string>()
467
+
468
+ export async function whenUpgraded<T extends HTMLElement>(
469
+ element: Element,
470
+ ): Promise<T> {
471
+ const tag = element.localName
472
+ if (!customElements.get(tag)) {
473
+ const timer = setTimeout(() => {
474
+ if (customElements.get(tag) || warnedTags.has(tag)) return
475
+ warnedTags.add(tag)
476
+ console.warn(
477
+ `<${tag}> is not registered after ${UPGRADE_WARNING_MS / 1000} seconds. ` +
478
+ `Call defineLt() from @lo-tek/interfaces/register at startup, not in an effect.`,
479
+ element,
480
+ )
481
+ }, UPGRADE_WARNING_MS)
482
+ // `finally`: `whenDefined` rejects a name without a hyphen, and without
483
+ // the cleanup the timer would have warned "not registered" three seconds
484
+ // after the call had already failed with the right error.
485
+ try {
486
+ await customElements.whenDefined(tag)
487
+ } finally {
488
+ clearTimeout(timer)
489
+ }
490
+ }
491
+ customElements.upgrade(element)
492
+ return element as T
493
+ }
@@ -0,0 +1,41 @@
1
+ @layer lotek {
2
+ /* Both the element and the class. `lt.connectionStatus()` outputs
3
+ `lt-connection-status`, and a class a builder function advertises must do
4
+ something. Only the element selector was here, so the class was dead. */
5
+ lt-connection-status,
6
+ .lt-connection-status {
7
+ display: contents;
8
+ }
9
+
10
+ .lt-connection-status__bar {
11
+ position: fixed;
12
+ inset-block-start: 0;
13
+ inset-inline: 0;
14
+ z-index: var(--lt-connection-status-layer, 1000);
15
+ padding: var(
16
+ --lt-connection-status-padding,
17
+ var(--lt-spacing-2) var(--lt-spacing-4)
18
+ );
19
+ font-size: var(--lt-font-size-s);
20
+ line-height: var(--lt-line-height-compact);
21
+ text-align: center;
22
+ color: var(--lt-color-danger-text);
23
+ background: var(--lt-color-danger-surface);
24
+ border-block-end: 1px solid var(--lt-color-danger-text);
25
+ }
26
+
27
+ .lt-connection-status__bar[data-state="online"] {
28
+ color: var(--lt-color-success-text);
29
+ background: var(--lt-color-success-surface);
30
+ border-block-end-color: var(--lt-color-success-text);
31
+ }
32
+
33
+ /* Forced colours mode removes custom colours and backgrounds. Without a
34
+ border the bar would be invisible, and it is the bar that says something
35
+ is wrong. */
36
+ @media (forced-colors: active) {
37
+ .lt-connection-status__bar {
38
+ border: 2px solid CanvasText;
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,47 @@
1
+ import { attributes } from "../../css/shared.js"
2
+
3
+ export const CONNECTION_STATUS_CLASS = "lt-connection-status" as const
4
+ export const CONNECTION_STATUS_BAR_CLASS = "lt-connection-status__bar" as const
5
+
6
+ export type ConnectionStatusOptions = {
7
+ /** The text when the connection is lost. */
8
+ offlineText?: string
9
+ /** The text when it comes back. Shown for a short while. */
10
+ onlineText?: string
11
+ }
12
+
13
+ export type ConnectionStatusAttributes = {
14
+ class: typeof CONNECTION_STATUS_CLASS
15
+ role: "status"
16
+ "aria-live": "polite"
17
+ "offline-text"?: string
18
+ "online-text"?: string
19
+ "data-ignore-morph": ""
20
+ }
21
+
22
+ /**
23
+ * The attributes for the bar that says the connection is lost.
24
+ *
25
+ * By definition the server cannot tell you it is unreachable. When it is
26
+ * down, nothing comes from it to render. So the component creates all the
27
+ * content itself, and `data-ignore-morph` stops a later patch from tearing
28
+ * it away the moment the connection is back. The host is the live region,
29
+ * `role="status"` with `aria-live="polite"`, so the region exists before the
30
+ * bar and its text arrive.
31
+ *
32
+ * ```ts
33
+ * <lt-connection-status {...lt.connectionStatus()} />
34
+ * ```
35
+ */
36
+ export const connectionStatus = ({
37
+ offlineText,
38
+ onlineText,
39
+ }: ConnectionStatusOptions = {}): ConnectionStatusAttributes =>
40
+ attributes({
41
+ class: CONNECTION_STATUS_CLASS,
42
+ role: "status" as const,
43
+ "aria-live": "polite" as const,
44
+ "offline-text": offlineText,
45
+ "online-text": onlineText,
46
+ "data-ignore-morph": "" as const,
47
+ })