@lo-tek/interfaces 0.0.0-stage → 0.37.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 +3254 -0
  2. package/LICENSE +21 -0
  3. package/README.md +129 -2
  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 +35 -0
  161. package/dist/components/default-texts.d.ts.map +1 -0
  162. package/dist/components/default-texts.js +35 -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 +431 -0
  175. package/dist/components/frame/dialog/lt-dialog.js.map +1 -0
  176. package/dist/components/frame/error-summary/error-summary.d.ts +40 -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 +32 -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 +82 -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 +302 -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 +580 -0
  191. package/dist/components/frame/field/lt-field.js.map +1 -0
  192. package/dist/components/frame/popover/lt-popover.d.ts +132 -0
  193. package/dist/components/frame/popover/lt-popover.d.ts.map +1 -0
  194. package/dist/components/frame/popover/lt-popover.js +490 -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 +573 -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 +361 -0
  209. package/dist/components/frame/suggestion/lt-suggestion.d.ts.map +1 -0
  210. package/dist/components/frame/suggestion/lt-suggestion.js +1152 -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 +404 -0
  217. package/dist/components/frame/tabs/lt-tabs.d.ts.map +1 -0
  218. package/dist/components/frame/tabs/lt-tabs.js +1201 -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 +135 -0
  225. package/dist/components/host-element.d.ts.map +1 -0
  226. package/dist/components/host-element.js +366 -0
  227. package/dist/components/host-element.js.map +1 -0
  228. package/dist/components/standalone/connection-status/connection-status.d.ts +28 -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 +22 -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 +81 -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 +216 -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 +137 -0
  245. package/dist/diagnostics/core.d.ts.map +1 -0
  246. package/dist/diagnostics/core.js +72 -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 +492 -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 +1320 -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 +410 -0
  316. package/dist/vocabulary/elements.js.map +1 -0
  317. package/dist/vocabulary/types.d.ts +175 -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 +62 -0
  326. package/manifest/files.json +373 -0
  327. package/manifest/manifest.json +4965 -0
  328. package/manifest/manifest.schema.json +513 -0
  329. package/package.json +404 -4
  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 +34 -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 +510 -0
  407. package/src/components/frame/error-summary/error-summary.css +47 -0
  408. package/src/components/frame/error-summary/error-summary.ts +56 -0
  409. package/src/components/frame/error-summary/lt-error-summary.ts +344 -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 +753 -0
  413. package/src/components/frame/popover/lt-popover.ts +555 -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 +681 -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 +1358 -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 +1319 -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 +400 -0
  426. package/src/components/standalone/connection-status/connection-status.css +41 -0
  427. package/src/components/standalone/connection-status/connection-status.ts +41 -0
  428. package/src/components/standalone/connection-status/lt-connection-status.ts +242 -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 +210 -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 +1322 -0
  453. package/src/vocabulary/elements.ts +412 -0
  454. package/src/vocabulary/types.ts +178 -0
  455. package/src/wasi-host.ts +155 -0
  456. package/web-types.json +800 -0
@@ -0,0 +1,43 @@
1
+ import { attributes, createGuard } from "../shared.js"
2
+
3
+ export const SKELETON_CLASS = "lt-skeleton" as const
4
+
5
+ export const skeletonVariants = ["block", "text", "circle"] as const
6
+
7
+ export type SkeletonVariant = (typeof skeletonVariants)[number]
8
+ export type NonDefaultSkeletonVariant = Exclude<SkeletonVariant, "block">
9
+
10
+ export type SkeletonOptions = {
11
+ /** Shape. Default: `block`. */
12
+ variant?: SkeletonVariant
13
+ }
14
+
15
+ export type SkeletonAttributes = {
16
+ class: typeof SKELETON_CLASS
17
+ "data-variant"?: NonDefaultSkeletonVariant
18
+ "aria-hidden": "true"
19
+ }
20
+
21
+ /**
22
+ * The attributes for a placeholder while the content loads.
23
+ *
24
+ * The shapes are always hidden from screen readers. They say nothing about
25
+ * what is coming, and a row of empty boxes being announced is worse than
26
+ * silence. Announce the wait in one place instead, with `role="status"`.
27
+ *
28
+ * ```ts
29
+ * <div {...skeleton({ variant: "text" })} />
30
+ * ```
31
+ */
32
+ export const skeleton = Object.assign(
33
+ ({ variant = "block" }: SkeletonOptions = {}): SkeletonAttributes =>
34
+ attributes({
35
+ class: SKELETON_CLASS,
36
+ "data-variant": variant === "block" ? undefined : variant,
37
+ "aria-hidden": "true" as const,
38
+ }),
39
+ {
40
+ variants: skeletonVariants,
41
+ isVariant: createGuard(skeletonVariants),
42
+ },
43
+ )
@@ -0,0 +1,41 @@
1
+ @layer lotek {
2
+ /* The link sits off screen until it gets focus. It cannot be hidden with
3
+ display or visibility, because then the keyboard cannot reach it either,
4
+ and the whole point is lost. */
5
+ .lt-skip-link {
6
+ position: absolute;
7
+ inset-inline-start: var(--lt-spacing-2);
8
+ inset-block-start: var(--lt-spacing-2);
9
+ z-index: 100;
10
+ transform: translateY(calc(-100% - var(--lt-spacing-4)));
11
+ display: inline-block;
12
+ padding: var(
13
+ --lt-skip-link-padding,
14
+ var(--lt-spacing-2) var(--lt-spacing-4)
15
+ );
16
+ font-family: inherit;
17
+ font-size: var(--lt-font-size-m);
18
+ line-height: var(--lt-line-height-default);
19
+ color: var(--lt-color-accent-content);
20
+ background: var(--lt-color-accent-fill);
21
+ border-radius: var(--lt-skip-link-radius, var(--lt-spacing-1));
22
+ text-decoration: underline;
23
+ }
24
+
25
+ /* `:focus` and not `:focus-visible`. Focus set from code after a mouse
26
+ click does not count as "visible focus", and the link would then stay
27
+ hidden for someone a script sends there. After a key press it counts as
28
+ visible, but it is the mouse click that decides. */
29
+ .lt-skip-link:focus {
30
+ transform: translateY(0);
31
+ outline: var(--lt-focus-ring);
32
+ outline-color: var(--lt-color-neutral-text-strong);
33
+ outline-offset: 2px;
34
+ }
35
+
36
+ @media (prefers-reduced-motion: no-preference) {
37
+ .lt-skip-link {
38
+ transition: transform 120ms ease;
39
+ }
40
+ }
41
+ }
@@ -0,0 +1,22 @@
1
+ import { attributes } from "../shared.js"
2
+
3
+ export const SKIP_LINK_CLASS = "lt-skip-link" as const
4
+
5
+ export type SkipLinkAttributes = {
6
+ class: typeof SKIP_LINK_CLASS
7
+ }
8
+
9
+ /**
10
+ * The attributes for a skip-to-content link.
11
+ *
12
+ * The link must be the first element in `<body>`, and point to the id of the
13
+ * main content. It sits off screen until it gets focus, and therefore cannot
14
+ * be hidden with `display: none`: the keyboard could not reach it either,
15
+ * and the whole point is lost.
16
+ *
17
+ * ```ts
18
+ * <a {...skipLink()} href="#main-content">Skip to main content</a>
19
+ * ```
20
+ */
21
+ export const skipLink = (): SkipLinkAttributes =>
22
+ attributes({ class: SKIP_LINK_CLASS })
@@ -0,0 +1,48 @@
1
+ @layer lotek {
2
+ .lt-spinner {
3
+ box-sizing: border-box;
4
+ display: inline-block;
5
+ inline-size: var(--lt-spinner-size, var(--lt-spacing-6));
6
+ block-size: var(--lt-spinner-size, var(--lt-spacing-6));
7
+ border: var(--lt-spinner-thickness, 2px) solid
8
+ var(--lt-color-neutral-surface);
9
+ border-block-start-color: var(--lt-color-accent-border);
10
+ border-radius: 50%;
11
+ animation: lt-spinner-rotate 800ms linear infinite;
12
+ }
13
+
14
+ .lt-spinner[data-size="small"] {
15
+ inline-size: var(--lt-spacing-4);
16
+ block-size: var(--lt-spacing-4);
17
+ }
18
+
19
+ .lt-spinner[data-size="large"] {
20
+ inline-size: var(--lt-spacing-10);
21
+ block-size: var(--lt-spacing-10);
22
+ border-width: 3px;
23
+ }
24
+
25
+ @keyframes lt-spinner-rotate {
26
+ to {
27
+ transform: rotate(360deg);
28
+ }
29
+ }
30
+
31
+ /* The user has asked for less motion. It then spins more slowly rather
32
+ than standing still: an indicator that does not move no longer says that
33
+ something is going on. */
34
+ @media (prefers-reduced-motion: reduce) {
35
+ .lt-spinner {
36
+ animation-duration: 2400ms;
37
+ }
38
+ }
39
+
40
+ /* High contrast: all four borders are forced to the same colour, and the
41
+ ring becomes an even circle. It still spins, but `Highlight` brings back
42
+ the mark that shows something is happening. */
43
+ @media (forced-colors: active) {
44
+ .lt-spinner {
45
+ border-block-start-color: Highlight;
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,48 @@
1
+ import { attributes, createGuard } from "../shared.js"
2
+
3
+ export const SPINNER_CLASS = "lt-spinner" as const
4
+
5
+ export const spinnerSizes = ["small", "medium", "large"] as const
6
+
7
+ export type SpinnerSize = (typeof spinnerSizes)[number]
8
+ export type NonDefaultSpinnerSize = Exclude<SpinnerSize, "medium">
9
+
10
+ export type SpinnerOptions = {
11
+ /** Size. Default: `medium`. */
12
+ size?: SpinnerSize
13
+ /** What is loading. Becomes `aria-label`, so the ring has a name for screen readers. */
14
+ label?: string
15
+ }
16
+
17
+ export type SpinnerAttributes = {
18
+ class: typeof SPINNER_CLASS
19
+ "data-size"?: NonDefaultSpinnerSize
20
+ role?: "status"
21
+ "aria-label"?: string
22
+ }
23
+
24
+ /**
25
+ * The attributes for a loading indicator.
26
+ *
27
+ * Without `label` the ring is only a shape, and screen readers announce
28
+ * nothing. With `label` it becomes a `role="status"` that says what is going
29
+ * on. If you already have a visible text next to it, let that carry the
30
+ * message and drop `label`, so the same thing is not announced twice.
31
+ *
32
+ * ```ts
33
+ * <span {...spinner({ label: "Loading applications" })} />
34
+ * ```
35
+ */
36
+ export const spinner = Object.assign(
37
+ ({ size = "medium", label }: SpinnerOptions = {}): SpinnerAttributes =>
38
+ attributes({
39
+ class: SPINNER_CLASS,
40
+ "data-size": size === "medium" ? undefined : size,
41
+ role: label ? ("status" as const) : undefined,
42
+ "aria-label": label,
43
+ }),
44
+ {
45
+ sizes: spinnerSizes,
46
+ isSize: createGuard(spinnerSizes),
47
+ },
48
+ )
@@ -0,0 +1,16 @@
1
+ @layer lotek {
2
+ /* Text that only screen readers should get. `display: none` and
3
+ `visibility: hidden` remove the element for them too, so the content must
4
+ stay in the document and be shrunk away visually instead. */
5
+ .lt-sr-only {
6
+ position: absolute;
7
+ width: 1px;
8
+ height: 1px;
9
+ padding: 0;
10
+ margin: -1px;
11
+ overflow: hidden;
12
+ clip-path: inset(50%);
13
+ white-space: nowrap;
14
+ border-width: 0;
15
+ }
16
+ }
@@ -0,0 +1,21 @@
1
+ import { attributes } from "../shared.js"
2
+
3
+ export const SR_ONLY_CLASS = "lt-sr-only" as const
4
+
5
+ export type SrOnlyAttributes = {
6
+ class: typeof SR_ONLY_CLASS
7
+ }
8
+
9
+ /**
10
+ * The attributes for text that only screen readers should get.
11
+ *
12
+ * ```ts
13
+ * <span {...srOnly()}>Opens in a new tab</span>
14
+ * ```
15
+ *
16
+ * Use it when a label or explanation is needed by someone listening to the
17
+ * page, but would be noise to someone looking at it. If the content should
18
+ * be gone for everyone, use `hidden` instead.
19
+ */
20
+ export const srOnly = (): SrOnlyAttributes =>
21
+ attributes({ class: SR_ONLY_CLASS })
@@ -0,0 +1,105 @@
1
+ @layer lotek {
2
+ .lt-switch {
3
+ box-sizing: border-box;
4
+ appearance: none;
5
+ flex: none;
6
+ display: inline-block;
7
+ inline-size: var(--lt-switch-width, var(--lt-spacing-10));
8
+ block-size: var(--lt-switch-height, var(--lt-spacing-6));
9
+ margin: 0;
10
+ border: 1px solid var(--lt-color-neutral-border);
11
+ border-radius: var(--lt-spacing-4);
12
+ background-color: var(--lt-color-neutral-surface);
13
+ /* The knob is a gradient, not a pseudo-element: Firefox does not render
14
+ ::before and ::after on an <input>. */
15
+ background-image: radial-gradient(
16
+ circle at center,
17
+ var(--lt-color-neutral-text-strong) 0 34%,
18
+ transparent 36%
19
+ );
20
+ background-repeat: no-repeat;
21
+ background-size: var(--lt-switch-height, var(--lt-spacing-6)) 100%;
22
+ /* background-position has no logical variant, so both directions are
23
+ written by hand. Off is at the start, on is at the end. */
24
+ background-position: left center;
25
+ cursor: pointer;
26
+ transition:
27
+ background-color 120ms ease,
28
+ background-position 120ms ease;
29
+ }
30
+
31
+ /* Without `:not(:disabled)`. It raised the specificity above the states
32
+ below, so the mouse removed the border of a switch that was on. The
33
+ rules for checked and disabled come after this one and win on order. */
34
+ .lt-switch:hover {
35
+ border-color: var(--lt-color-neutral-border-strong);
36
+ }
37
+
38
+ .lt-switch:focus-visible {
39
+ outline: var(--lt-focus-ring);
40
+ outline-offset: 2px;
41
+ }
42
+
43
+ .lt-switch:dir(rtl) {
44
+ background-position: right center;
45
+ }
46
+
47
+ .lt-switch:checked {
48
+ background-color: var(--lt-color-accent-fill);
49
+ border-color: var(--lt-color-accent-fill);
50
+ background-position: right center;
51
+ background-image: radial-gradient(
52
+ circle at center,
53
+ var(--lt-color-accent-content) 0 34%,
54
+ transparent 36%
55
+ );
56
+ }
57
+
58
+ .lt-switch:checked:dir(rtl) {
59
+ background-position: left center;
60
+ }
61
+
62
+ .lt-switch:disabled {
63
+ background-color: var(--lt-color-disabled-surface);
64
+ border-color: var(--lt-color-disabled-surface);
65
+ background-image: radial-gradient(
66
+ circle at center,
67
+ var(--lt-color-disabled-text) 0 34%,
68
+ transparent 36%
69
+ );
70
+ cursor: not-allowed;
71
+ }
72
+
73
+ /* The user has asked for less motion. The switch should still change
74
+ state, it just should not slide. */
75
+ @media (prefers-reduced-motion: reduce) {
76
+ .lt-switch {
77
+ transition: none;
78
+ }
79
+ }
80
+
81
+ .lt-switch-row {
82
+ display: flex;
83
+ align-items: center;
84
+ gap: var(--lt-spacing-2);
85
+ line-height: var(--lt-line-height-default);
86
+ }
87
+
88
+ /*
89
+ * High contrast: the knob is a gradient, and disappears in the mode.
90
+ * Without it on and off look exactly alike. Here we fall back to a plain
91
+ * checkbox. The switch loses its shape, but `role="switch"` is still
92
+ * there, so it is announced as on and off, and the state is visible
93
+ * again.
94
+ */
95
+ @media (forced-colors: active) {
96
+ .lt-switch,
97
+ .lt-switch:checked {
98
+ appearance: auto;
99
+ inline-size: auto;
100
+ block-size: auto;
101
+ background-image: none;
102
+ border: 0;
103
+ }
104
+ }
105
+ }
@@ -0,0 +1,50 @@
1
+ import { attributes } from "../shared.js"
2
+
3
+ export const SWITCH_CLASS = "lt-switch" as const
4
+ /** The row that holds the switch and the text next to each other. */
5
+ export const SWITCH_ROW_CLASS = "lt-switch-row" as const
6
+
7
+ export type SwitchOptions = {
8
+ /**
9
+ * The control is disabled. Do not use it to lock the switch while a save
10
+ * is in progress: `disabled` takes focus away from it, and focus does not
11
+ * come back.
12
+ */
13
+ disabled?: boolean
14
+ }
15
+
16
+ export type SwitchAttributes = {
17
+ class: typeof SWITCH_CLASS
18
+ type: "checkbox"
19
+ role: "switch"
20
+ disabled?: true
21
+ }
22
+
23
+ /**
24
+ * The attributes for an on/off switch.
25
+ *
26
+ * The switch is a checkbox with `role="switch"`. Screen readers then
27
+ * announce it as "on" and "off" rather than "checked", while the keyboard
28
+ * and `FormData` work as for a plain checkbox.
29
+ *
30
+ * The switch has no validation state. A choice that is on or off cannot be
31
+ * invalid in itself; if turning it on is required, the requirement belongs
32
+ * in a checkbox with `required`.
33
+ *
34
+ * ```ts
35
+ * <input {...switchControl()} />
36
+ * ```
37
+ */
38
+ export const switchControl = Object.assign(
39
+ ({ disabled }: SwitchOptions = {}): SwitchAttributes =>
40
+ attributes({
41
+ class: SWITCH_CLASS,
42
+ type: "checkbox" as const,
43
+ role: "switch" as const,
44
+ disabled: disabled ? (true as const) : undefined,
45
+ }),
46
+ {
47
+ /** The class on the row around the switch and the text. */
48
+ row: SWITCH_ROW_CLASS,
49
+ },
50
+ )
@@ -0,0 +1,159 @@
1
+ @layer lotek {
2
+ .lt-table {
3
+ box-sizing: border-box;
4
+ inline-size: 100%;
5
+ border-collapse: collapse;
6
+ font-family: inherit;
7
+ font-size: var(--lt-font-size-m);
8
+ line-height: var(--lt-line-height-default);
9
+ color: var(--lt-color-neutral-text-strong);
10
+ /* Numbers stacked under each other must have the same width per digit,
11
+ or the column cannot be read downwards. */
12
+ font-variant-numeric: tabular-nums;
13
+ }
14
+
15
+ .lt-table caption {
16
+ text-align: start;
17
+ font-weight: var(--lt-font-weight-semibold);
18
+ padding-block-end: var(--lt-spacing-2);
19
+ }
20
+
21
+ .lt-table th,
22
+ .lt-table td {
23
+ padding: var(
24
+ --lt-table-cell-padding,
25
+ var(--lt-spacing-2) var(--lt-spacing-3)
26
+ );
27
+ text-align: start;
28
+ vertical-align: top;
29
+ border-block-end: 1px solid var(--lt-color-neutral-border-subtle);
30
+ }
31
+
32
+ .lt-table thead th {
33
+ font-weight: var(--lt-font-weight-semibold);
34
+ border-block-end: 2px solid var(--lt-color-neutral-border-strong);
35
+ }
36
+
37
+ .lt-table tbody tr:last-child th,
38
+ .lt-table tbody tr:last-child td {
39
+ border-block-end: 0;
40
+ }
41
+
42
+ .lt-table[data-variant="striped"] tbody tr:nth-child(even) {
43
+ background: var(--lt-color-neutral-surface);
44
+ }
45
+
46
+ .lt-table[data-hoverable] tbody tr:hover {
47
+ background: var(--lt-color-accent-surface);
48
+ }
49
+
50
+ .lt-table td[data-align="end"],
51
+ .lt-table th[data-align="end"] {
52
+ text-align: end;
53
+ }
54
+
55
+ /*
56
+ * A sortable column has a button in the header, and the button fills the
57
+ * cell. The cell gives up its padding and the button takes it over, so
58
+ * the text sits where it would without a button and the whole cell can be
59
+ * pressed. Without that the header got padding from both the cell and the
60
+ * button, and became taller and shifted against the cells below.
61
+ */
62
+ .lt-table th:has(> .lt-table__sort) {
63
+ padding: 0;
64
+ }
65
+
66
+ .lt-table__sort {
67
+ box-sizing: border-box;
68
+ display: flex;
69
+ align-items: center;
70
+ gap: var(--lt-spacing-2);
71
+ inline-size: 100%;
72
+ margin: 0;
73
+ padding: var(
74
+ --lt-table-cell-padding,
75
+ var(--lt-spacing-2) var(--lt-spacing-3)
76
+ );
77
+ font: inherit;
78
+ color: inherit;
79
+ text-align: inherit;
80
+ background: none;
81
+ border: 0;
82
+ border-radius: 0;
83
+ /* Can also be a link, when the server sorts without JavaScript. */
84
+ text-decoration: none;
85
+ cursor: pointer;
86
+ }
87
+
88
+ .lt-table th[data-align="end"] > .lt-table__sort {
89
+ justify-content: flex-end;
90
+ }
91
+
92
+ .lt-table__sort:hover {
93
+ background: var(--lt-color-neutral-surface);
94
+ }
95
+
96
+ .lt-table__sort:focus-visible {
97
+ outline: var(--lt-focus-ring);
98
+ outline-offset: -2px;
99
+ }
100
+
101
+ /*
102
+ * The arrow is read from `aria-sort` on the cell, not from a class. It is
103
+ * the same attribute the screen reader reads, so what is shown and what is
104
+ * said cannot drift apart. Without the attribute the button shows both
105
+ * arrows, muted, so it is visible that the column can be sorted.
106
+ *
107
+ * The arrow is a mask and not an image, so it takes the text colour and
108
+ * flips with the theme. An empty `content` means it never becomes part of
109
+ * the button's name.
110
+ */
111
+ .lt-table__sort::after {
112
+ content: "";
113
+ flex: none;
114
+ inline-size: var(--lt-spacing-3);
115
+ block-size: var(--lt-spacing-3);
116
+ background-color: var(--lt-color-neutral-text-subtle);
117
+ mask:
118
+ url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 1 13 6.5H3zM8 15 3 9.5H13z'/%3E%3C/svg%3E")
119
+ center / contain no-repeat;
120
+ }
121
+
122
+ .lt-table th[aria-sort="ascending"] > .lt-table__sort::after {
123
+ background-color: currentColor;
124
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 3 14 11H2z'/%3E%3C/svg%3E");
125
+ }
126
+
127
+ .lt-table th[aria-sort="descending"] > .lt-table__sort::after {
128
+ background-color: currentColor;
129
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 13 2 5H14z'/%3E%3C/svg%3E");
130
+ }
131
+
132
+ /* High contrast: the mode forces the background colour to the surface
133
+ colour, and the arrow would then have become invisible. A system colour
134
+ is left alone, so it is drawn in the system text colour. */
135
+ @media (forced-colors: active) {
136
+ .lt-table__sort::after,
137
+ .lt-table th[aria-sort] > .lt-table__sort::after {
138
+ background-color: CanvasText;
139
+ }
140
+ }
141
+
142
+ /* The arrow comes before the text in a right-aligned column, so the text
143
+ ends where the numbers below end. */
144
+ .lt-table th[data-align="end"] > .lt-table__sort::after {
145
+ order: -1;
146
+ }
147
+
148
+ /* A table wider than the screen must be scrollable, and that area must be
149
+ reachable with the keyboard. Hence tabindex="0" on the container. */
150
+ .lt-table-scroll {
151
+ overflow-x: auto;
152
+ max-inline-size: 100%;
153
+ }
154
+
155
+ .lt-table-scroll:focus-visible {
156
+ outline: var(--lt-focus-ring);
157
+ outline-offset: 2px;
158
+ }
159
+ }
@@ -0,0 +1,107 @@
1
+ import { attributes, createGuard } from "../shared.js"
2
+
3
+ export const TABLE_CLASS = "lt-table" as const
4
+ /** The container that lets a wide table scroll sideways. */
5
+ export const TABLE_SCROLL_CLASS = "lt-table-scroll" as const
6
+
7
+ export const tableVariants = ["default", "striped"] as const
8
+
9
+ export type TableVariant = (typeof tableVariants)[number]
10
+ export type NonDefaultTableVariant = Exclude<TableVariant, "default">
11
+
12
+ export type TableOptions = {
13
+ /** Every other row on a muted surface. Default: `default`. */
14
+ variant?: TableVariant
15
+ /** Highlights the row under the mouse. Use only when rows can be pressed. */
16
+ hoverable?: boolean
17
+ }
18
+
19
+ export type TableAttributes = {
20
+ class: typeof TABLE_CLASS
21
+ "data-variant"?: NonDefaultTableVariant
22
+ "data-hoverable"?: ""
23
+ }
24
+
25
+ /**
26
+ * The attributes for a table.
27
+ *
28
+ * The class goes on a real `<table>` with `<thead>` and `<th>`. The header
29
+ * cells are what let screen readers say "Amount, 1,240 kroner" when the user
30
+ * is in a cell. Build the table from `<div>` elements, and that connection
31
+ * does not exist.
32
+ *
33
+ * ```ts
34
+ * <table {...table({ variant: "striped" })}>…</table>
35
+ * ```
36
+ */
37
+ export const table = Object.assign(
38
+ ({ variant = "default", hoverable }: TableOptions = {}): TableAttributes =>
39
+ attributes({
40
+ class: TABLE_CLASS,
41
+ "data-variant": variant === "default" ? undefined : variant,
42
+ "data-hoverable": hoverable ? ("" as const) : undefined,
43
+ }),
44
+ {
45
+ /** The class on the container around a wide table. */
46
+ scroll: TABLE_SCROLL_CLASS,
47
+ variants: tableVariants,
48
+ isVariant: createGuard(tableVariants),
49
+ },
50
+ )
51
+
52
+ /** The class on the button in a sortable column header. */
53
+ export const TABLE_SORT_CLASS = "lt-table__sort" as const
54
+
55
+ export const tableSortDirections = ["ascending", "descending"] as const
56
+
57
+ export type TableSortDirection = (typeof tableSortDirections)[number]
58
+
59
+ export type TableSortOptions = {
60
+ /**
61
+ * The direction the column is sorted in. Left out, it means the table is
62
+ * not sorted by this column, and the header gets no `aria-sort`.
63
+ */
64
+ direction?: TableSortDirection
65
+ }
66
+
67
+ export type TableSortAttributes = {
68
+ header: {
69
+ "aria-sort"?: TableSortDirection
70
+ }
71
+ button: {
72
+ class: typeof TABLE_SORT_CLASS
73
+ type: "button"
74
+ }
75
+ }
76
+
77
+ /**
78
+ * The attributes for a sortable column header.
79
+ *
80
+ * `aria-sort` is on the `<th>`, not on the button, because the cell is what
81
+ * describes the column. Only the sorted column has the attribute. The arrow
82
+ * is drawn from the same attribute, so what the screen reader says and what
83
+ * is shown cannot drift apart. The sorting itself is the app's job.
84
+ *
85
+ * ```ts
86
+ * const date = lt.tableSort({ direction: "descending" })
87
+ * ```
88
+ * ```html
89
+ * <th scope="col" {...date.header}>
90
+ * <button {...date.button}>Date</button>
91
+ * </th>
92
+ * ```
93
+ */
94
+ export const tableSort = Object.assign(
95
+ ({ direction }: TableSortOptions = {}): TableSortAttributes => ({
96
+ header: attributes({ "aria-sort": direction }),
97
+ button: attributes({ class: TABLE_SORT_CLASS, type: "button" as const }),
98
+ }),
99
+ {
100
+ // The list sits next to it, as `tableSortDirections`, and not on the
101
+ // function. The guard for the lists requires the attribute and the class
102
+ // to be on the same element, and here `aria-sort` is on the cell and the
103
+ // class on the button. The table test requires each direction to give its
104
+ // own arrow.
105
+ isDirection: createGuard(tableSortDirections),
106
+ },
107
+ )