@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,112 @@
1
+ import { attributes, createGuard, idOrFallback } from "../../css/shared.js";
2
+ export const DIALOG_CLASS = "lt-dialog";
3
+ export const DIALOG_HEADER_CLASS = "lt-dialog__header";
4
+ export const DIALOG_TITLE_CLASS = "lt-dialog__title";
5
+ export const DIALOG_SUBTITLE_CLASS = "lt-dialog__subtitle";
6
+ export const DIALOG_BODY_CLASS = "lt-dialog__body";
7
+ export const DIALOG_FOOTER_CLASS = "lt-dialog__footer";
8
+ /**
9
+ * The colour of the header, and what it means.
10
+ *
11
+ * `neutral` is the default and gives no colour. The four status colours are
12
+ * the same ones the alert uses, and `brand` is the brand colour, for a header
13
+ * that says who is speaking rather than how it went.
14
+ */
15
+ export const dialogColors = [
16
+ "neutral",
17
+ "brand",
18
+ "info",
19
+ "success",
20
+ "warning",
21
+ "danger",
22
+ ];
23
+ /**
24
+ * The attributes for a dialog.
25
+ *
26
+ * Opening a dialog is a call, not an attribute: only `showModal()` moves
27
+ * focus in, keeps focus inside the dialog, closes on Escape and makes the
28
+ * rest of the page inert. A `<dialog open>` in the markup is a box on the page.
29
+ *
30
+ * That is a problem for a server that only sends HTML, since it cannot call
31
+ * anything in the browser. So the server says the dialog is open, and
32
+ * `<lt-dialog>` makes the call.
33
+ *
34
+ * The two `open`s are not the same, and it is worth keeping them apart:
35
+ *
36
+ * - `open` on the **host** is the server saying the dialog should be shown.
37
+ * It is not preserved. If it were, the server could never open the dialog
38
+ * again after the user had closed it once. If the server sends the region
39
+ * again with `open` still set, the dialog opens again. For a dismissal to
40
+ * last, the app must tell the server.
41
+ * - `open` on the **`<dialog>`** is set by the browser itself when
42
+ * `showModal()` is called. It is not in the server's HTML, so a morph
43
+ * removes it, and the component puts it back. The server also writes it
44
+ * when it knows the dialog should be shown: without JavaScript a `<dialog>`
45
+ * without `open` is hidden, and its content does not exist for the reader.
46
+ * With the attribute it stands as a box on the page until the component
47
+ * turns it into a modal.
48
+ *
49
+ * ```ts
50
+ * const box = lt.dialog({ titleId: "delete-title", open: true })
51
+ * ```
52
+ * ```html
53
+ * <lt-dialog {...box.host}>
54
+ * <dialog {...box.dialog}>
55
+ * <h2 {...box.title}>Delete the application?</h2>
56
+ * <div {...box.body}>The application and its attachments will be gone.</div>
57
+ * <form method="dialog" {...box.footer}>
58
+ * <button class="lt-button" value="cancel">Cancel</button>
59
+ * </form>
60
+ * </dialog>
61
+ * </lt-dialog>
62
+ * ```
63
+ */
64
+ export const dialog = Object.assign(({ titleId: givenId, open = false, color = "neutral", }) => {
65
+ // The fallback only matters to someone without a type check.
66
+ const titleId = idOrFallback("lt.dialog()", givenId, "titleId");
67
+ return {
68
+ host: attributes({
69
+ open: open ? true : undefined,
70
+ }),
71
+ dialog: attributes({
72
+ class: DIALOG_CLASS,
73
+ "aria-labelledby": titleId,
74
+ /*
75
+ * `open` is in both places when the dialog should be shown, on
76
+ * purpose.
77
+ *
78
+ * Without JavaScript a `<dialog>` without `open` is hidden, so the
79
+ * content the server wanted to show did not exist for the reader. With
80
+ * `open` it stands there as a box on the page, and the component turns
81
+ * it into a real modal with `showModal()` once it gets to run.
82
+ *
83
+ * In React it is also the only thing that matches: the component sets
84
+ * `open` on the `<dialog>` before React hydrates, and when it was not in
85
+ * the server's HTML, React reported a mismatch on every single page load.
86
+ */
87
+ open: open ? true : undefined,
88
+ "data-color": color === "neutral" ? undefined : color,
89
+ }),
90
+ header: attributes({ class: DIALOG_HEADER_CLASS }),
91
+ title: attributes({ class: DIALOG_TITLE_CLASS, id: titleId }),
92
+ subtitle: attributes({ class: DIALOG_SUBTITLE_CLASS }),
93
+ body: attributes({ class: DIALOG_BODY_CLASS }),
94
+ footer: attributes({ class: DIALOG_FOOTER_CLASS }),
95
+ };
96
+ }, {
97
+ /** The class on the `<dialog>` itself. */
98
+ dialog: DIALOG_CLASS,
99
+ /** The class on the header, which `color` can colour. */
100
+ header: DIALOG_HEADER_CLASS,
101
+ /** The class on the heading in the dialog. */
102
+ title: DIALOG_TITLE_CLASS,
103
+ /** The class on the subtitle in the header. */
104
+ subtitle: DIALOG_SUBTITLE_CLASS,
105
+ /** The class on the content, which scrolls when the dialog gets too tall. */
106
+ body: DIALOG_BODY_CLASS,
107
+ /** The class on the row of buttons at the bottom. */
108
+ footer: DIALOG_FOOTER_CLASS,
109
+ colors: dialogColors,
110
+ isColor: createGuard(dialogColors),
111
+ });
112
+ //# sourceMappingURL=dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialog.js","sourceRoot":"","sources":["../../../../src/components/frame/dialog/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAE3E,MAAM,CAAC,MAAM,YAAY,GAAG,WAAoB,CAAA;AAChD,MAAM,CAAC,MAAM,mBAAmB,GAAG,mBAA4B,CAAA;AAC/D,MAAM,CAAC,MAAM,kBAAkB,GAAG,kBAA2B,CAAA;AAC7D,MAAM,CAAC,MAAM,qBAAqB,GAAG,qBAA8B,CAAA;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAAG,iBAA0B,CAAA;AAC3D,MAAM,CAAC,MAAM,mBAAmB,GAAG,mBAA4B,CAAA;AAE/D;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,SAAS;IACT,OAAO;IACP,MAAM;IACN,SAAS;IACT,SAAS;IACT,QAAQ;CACA,CAAA;AA8CV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CACjC,CAAC,EACC,OAAO,EAAE,OAAO,EAChB,IAAI,GAAG,KAAK,EACZ,KAAK,GAAG,SAAS,GACH,EAAoB,EAAE;IACpC,6DAA6D;IAC7D,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,EAAE,OAAO,EAAE,SAAS,CAAC,CAAA;IAE/D,OAAO;QACL,IAAI,EAAE,UAAU,CAAC;YACf,IAAI,EAAE,IAAI,CAAC,CAAC,CAAE,IAAc,CAAC,CAAC,CAAC,SAAS;SACzC,CAAC;QACF,MAAM,EAAE,UAAU,CAAC;YACjB,KAAK,EAAE,YAAY;YACnB,iBAAiB,EAAE,OAAO;YAC1B;;;;;;;;;;;;eAYG;YACH,IAAI,EAAE,IAAI,CAAC,CAAC,CAAE,IAAc,CAAC,CAAC,CAAC,SAAS;YACxC,YAAY,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK;SACtD,CAAC;QACF,MAAM,EAAE,UAAU,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC;QAClD,KAAK,EAAE,UAAU,CAAC,EAAE,KAAK,EAAE,kBAAkB,EAAE,EAAE,EAAE,OAAO,EAAE,CAAC;QAC7D,QAAQ,EAAE,UAAU,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC;QACtD,IAAI,EAAE,UAAU,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;QAC9C,MAAM,EAAE,UAAU,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC;KACnD,CAAA;AACH,CAAC,EACD;IACE,0CAA0C;IAC1C,MAAM,EAAE,YAAY;IACpB,yDAAyD;IACzD,MAAM,EAAE,mBAAmB;IAC3B,8CAA8C;IAC9C,KAAK,EAAE,kBAAkB;IACzB,+CAA+C;IAC/C,QAAQ,EAAE,qBAAqB;IAC/B,6EAA6E;IAC7E,IAAI,EAAE,iBAAiB;IACvB,qDAAqD;IACrD,MAAM,EAAE,mBAAmB;IAC3B,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,WAAW,CAAC,YAAY,CAAC;CACnC,CACF,CAAA"}
@@ -0,0 +1,104 @@
1
+ import { HostElement } from "../../host-element.js";
2
+ export declare const LT_DIALOG_TAG: "lt-dialog";
3
+ /**
4
+ * The parts the dialog finds, as selectors relative to the element. The
5
+ * component finds the parts with these, and the manifest describes them for
6
+ * whoever assembles the markup by hand, so the two cannot say different things.
7
+ */
8
+ export declare const LT_DIALOG_PARTS: {
9
+ readonly dialog: ":scope > dialog";
10
+ readonly title: "h1, h2, h3, h4, h5, h6";
11
+ readonly body: ".lt-dialog__body";
12
+ };
13
+ export declare class LtDialog extends HostElement {
14
+ static observedAttributes: readonly ["open", "server-controlled"];
15
+ private observer?;
16
+ /**
17
+ * A separate observer for `open` on the `<dialog>` itself.
18
+ *
19
+ * It cannot be merged with the other one. When the user closes the dialog,
20
+ * the browser removes the attribute first and sends `close` afterwards, and
21
+ * an observer running all of `sync()` there would have seen a host still
22
+ * saying "open" and a dialog that was not modal, and opened it again before
23
+ * `close` was handled. This one does only one thing: it puts the attribute
24
+ * back on a dialog that is still in the top layer.
25
+ */
26
+ private openObserver?;
27
+ private dialogElement?;
28
+ /**
29
+ * What the component last reported, so it reports only when the state
30
+ * changes.
31
+ *
32
+ * A morph that moves the host or the dialog takes the dialog out of the top
33
+ * layer, and the component opens it again. Before, it then reported
34
+ * `open: true` for a dialog that had been open the whole time. The field
35
+ * survives the host being disconnected and reconnected.
36
+ */
37
+ private lastNotified?;
38
+ /** Whether the dialog is open. Mirrors the `open` attribute. */
39
+ get open(): boolean;
40
+ set open(value: boolean);
41
+ connectedCallback(): void;
42
+ disconnectedCallback(): void;
43
+ attributeChangedCallback(): void;
44
+ /**
45
+ * The dialog the component controls.
46
+ *
47
+ * Only a direct child. A `<dialog>` further down the tree can belong to
48
+ * something else, and must not be opened by this component.
49
+ */
50
+ private get dialog();
51
+ /** The id the component gave the heading, so a patch gets the same one back. */
52
+ private titleId?;
53
+ /** The wiring alone, for an attribute record. See the observer. */
54
+ private rewire;
55
+ /**
56
+ * The heading that is the dialog's title when the server did not point to
57
+ * one.
58
+ *
59
+ * The first heading in this dialog that is not in the body. A heading in
60
+ * `.lt-dialog__body` is a heading in the content, not the dialog's name: a
61
+ * settings dialog in three sections got the first section's heading as its
62
+ * title, with the class and the styling that come with it. A heading in a
63
+ * nested dialog belongs to the nested one, and the body that counts is only
64
+ * a body in this dialog: if this dialog is itself in the body of another,
65
+ * the outer body is not its body.
66
+ */
67
+ private headingOf;
68
+ /**
69
+ * Whether the dialog has no name: no reference, no `aria-label` and no
70
+ * title. An empty `<dialog>` is a region the server has not filled yet, and
71
+ * does not count.
72
+ */
73
+ private nameless;
74
+ /**
75
+ * Fills in what a template without JavaScript did not write: the class on
76
+ * the dialog, and the title. The title is what `aria-labelledby` points to
77
+ * when the server wrote it, otherwise the first heading outside the body,
78
+ * and only when the dialog does not already have a name from `aria-label`.
79
+ * The class and the id are written only on the title: a heading in the body
80
+ * of a dialog with `aria-label` is not the title, and must not be styled as
81
+ * one.
82
+ */
83
+ private wire;
84
+ private notify;
85
+ /**
86
+ * Puts `open` back on a dialog that is still in the top layer.
87
+ *
88
+ * `showModal()` sets the attribute itself, and the server did not send it,
89
+ * so the morph removes it. The browser's own stylesheet then hides a
90
+ * `<dialog>` without `open`, and the dialog disappeared for the user in the
91
+ * middle of what she was doing. Before, the template had to write
92
+ * `data-preserve-attr="open"` to prevent it.
93
+ *
94
+ * The condition is `:modal` and not `this.open`, and that is precise: when
95
+ * the user closes the dialog, it leaves the top layer, and then the missing
96
+ * attribute is real. Only a dialog that is still modal without saying so is
97
+ * a dialog someone has taken the attribute from.
98
+ */
99
+ private repairOpen;
100
+ private handleClose;
101
+ private sync;
102
+ }
103
+ export declare function defineLtDialog(tagName?: string): void;
104
+ //# sourceMappingURL=lt-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lt-dialog.d.ts","sourceRoot":"","sources":["../../../../src/components/frame/dialog/lt-dialog.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,WAAW,EAOZ,MAAM,uBAAuB,CAAA;AAO9B,eAAO,MAAM,aAAa,EAAG,WAAoB,CAAA;AAEjD;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;CAIlB,CAAA;AA4DV,qBAAa,QAAS,SAAQ,WAAW;IACvC,MAAM,CAAC,kBAAkB,yCAAuC;IAEhE,OAAO,CAAC,QAAQ,CAAC,CAAkB;IACnC;;;;;;;;;OASG;IACH,OAAO,CAAC,YAAY,CAAC,CAAkB;IACvC,OAAO,CAAC,aAAa,CAAC,CAAmB;IACzC;;;;;;;;OAQG;IACH,OAAO,CAAC,YAAY,CAAC,CAAS;IAE9B,gEAAgE;IAChE,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;IAED,iBAAiB,IAAI,IAAI;IA4CzB,oBAAoB,IAAI,IAAI;IAS5B,wBAAwB,IAAI,IAAI;IAIhC;;;;;OAKG;IACH,OAAO,KAAK,MAAM,GAEjB;IAED,gFAAgF;IAChF,OAAO,CAAC,OAAO,CAAC,CAAQ;IAExB,mEAAmE;IACnE,OAAO,CAAC,MAAM;IAKd;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,SAAS;IAYjB;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IAShB;;;;;;;;OAQG;IACH,OAAO,CAAC,IAAI;IAwCZ,OAAO,CAAC,MAAM;IAed;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,UAAU;IA4BlB,OAAO,CAAC,WAAW,CAYlB;IAED,OAAO,CAAC,IAAI;CAsJb;AAED,wBAAgB,cAAc,CAAC,OAAO,GAAE,MAAsB,GAAG,IAAI,CAEpE"}
@@ -0,0 +1,434 @@
1
+ import { addClass, defineElement, HostElement, isServerControlled, SERVER_CONTROLLED, setAttr, setFlag, uniqueId, warnAboutMarkup, } from "../../host-element.js";
2
+ import { DIALOG_BODY_CLASS, DIALOG_CLASS, DIALOG_TITLE_CLASS, } from "./dialog.js";
3
+ export const LT_DIALOG_TAG = "lt-dialog";
4
+ /**
5
+ * The parts the dialog finds, as selectors relative to the element. The
6
+ * component finds the parts with these, and the manifest describes them for
7
+ * whoever assembles the markup by hand, so the two cannot say different things.
8
+ */
9
+ export const LT_DIALOG_PARTS = {
10
+ dialog: ":scope > dialog",
11
+ title: "h1, h2, h3, h4, h5, h6",
12
+ body: `.${DIALOG_BODY_CLASS}`,
13
+ };
14
+ /**
15
+ * A modal dialog a server can open.
16
+ *
17
+ * Opening a `<dialog>` is a call and not an attribute. `showModal()` moves
18
+ * focus in, keeps focus inside the dialog, closes on Escape and makes the rest
19
+ * of the page inert. `<dialog open>` does none of that: it is a box on the
20
+ * page.
21
+ *
22
+ * A server that only sends HTML cannot call anything. Without this component
23
+ * an app in Datastar, htmx or a Go template could not open a dialog at all
24
+ * without writing a script of its own alongside. Here the server says instead
25
+ * that the dialog is open, and the component makes the call.
26
+ *
27
+ * When the user closes the dialog, with Escape or with a button in a
28
+ * `<form method="dialog">`, `open` is removed from the host again, so the
29
+ * markup says the same as the screen. The component reports it with
30
+ * `dialog-toggle`, which carries `open` and `returnValue`. A click on the
31
+ * backdrop does not close it: neither does it on a plain `<dialog>`, and the
32
+ * component adds nothing.
33
+ *
34
+ * `open` on the **host** comes from the server. If the server sends the
35
+ * region again with `open` still set, the dialog opens again. `open` on the
36
+ * `<dialog>` itself comes from the browser, set by `showModal()`, and the
37
+ * component puts it back when a patch removes it. The template needs no
38
+ * `data-preserve-attr`.
39
+ *
40
+ * Write `open` on the `<dialog>` itself too when the dialog should be shown.
41
+ * Without JavaScript a `<dialog>` without `open` is hidden, and then the
42
+ * content does not exist at all. `lt.dialog({ open: true })` gives both.
43
+ *
44
+ * `server-controlled` on the host turns off the repair of `open` on the
45
+ * `<dialog>`. Then every patch decides whether the dialog is shown, also when
46
+ * it is in the top layer.
47
+ *
48
+ * ```html
49
+ * <lt-dialog open>
50
+ * <dialog class="lt-dialog" aria-labelledby="title" open>
51
+ * <h2 class="lt-dialog__title" id="title">The decision is registered</h2>
52
+ * <div class="lt-dialog__body">The case has been processed.</div>
53
+ * <form method="dialog" class="lt-dialog__footer">
54
+ * <button class="lt-button" value="close">Close</button>
55
+ * </form>
56
+ * </dialog>
57
+ * </lt-dialog>
58
+ * ```
59
+ */
60
+ /**
61
+ * The dialogs already checked for a close before upgrade.
62
+ *
63
+ * The check applies only the first time a dialog is seen, not every time a
64
+ * host is connected. A morph that moves the host disconnects and reconnects
65
+ * it, and then `returnValue` was left over from a close the user made long
66
+ * ago. The component thought it had been closed before the script arrived,
67
+ * and took `open` from the host the server had just opened. The set lives
68
+ * outside the class, so the same applies to a dialog moved into a new host.
69
+ */
70
+ const upgradeChecked = new WeakSet();
71
+ export class LtDialog extends HostElement {
72
+ constructor() {
73
+ super(...arguments);
74
+ this.handleClose = () => {
75
+ // `close` is queued, not synchronous. If the server manages to close and
76
+ // open again in the same task, this event no longer applies, and without
77
+ // the guard the component closed the dialog it had just opened.
78
+ if (this.dialog?.matches(":modal"))
79
+ return;
80
+ // If the server closed it, the host is already in step, and `sync()` has
81
+ // reported it.
82
+ if (!this.open)
83
+ return;
84
+ this.removeAttribute("open");
85
+ this.notify(false, this.dialog?.returnValue ?? "");
86
+ };
87
+ }
88
+ /** Whether the dialog is open. Mirrors the `open` attribute. */
89
+ get open() {
90
+ return this.hasAttribute("open");
91
+ }
92
+ set open(value) {
93
+ setFlag(this, "open", value);
94
+ }
95
+ connectedCallback() {
96
+ /*
97
+ * The server can send the dialog into a region already on the page, and
98
+ * then the `<dialog>` does not exist yet when the component connects. Only
99
+ * a change among the host's direct children runs all of `sync()`: the
100
+ * dialog is always a direct child, and the content inside it changes with
101
+ * every patch without saying anything about which dialog is the
102
+ * component's.
103
+ *
104
+ * `open` on the `<dialog>` itself is included. The browser sets it when
105
+ * `showModal()` is called, and a morph removes it again, since the server
106
+ * did not send it. Without this an open dialog disappeared as soon as
107
+ * something in the region around it was patched, and the template had to
108
+ * write `data-preserve-attr="open"` to prevent it.
109
+ */
110
+ /*
111
+ * The attributes are included for the wiring the component fills in when
112
+ * the markup came without it: the class, the heading's id and
113
+ * `aria-labelledby`. But an attribute record runs only the wiring, not all
114
+ * of `sync()`. `close()` removes `open` synchronously and queues the
115
+ * `close` event as a separate task, and the observer runs before it. When
116
+ * a click changed a class on the button in the same task as it closed the
117
+ * dialog, `sync()` saw a host with `open` and a dialog that was not modal,
118
+ * and opened it again before the close was handled. Every write compares
119
+ * first, or the observer would trigger itself.
120
+ */
121
+ this.observer = new MutationObserver((records) => {
122
+ const swapped = records.some((record) => record.type === "childList" && record.target === this);
123
+ if (swapped)
124
+ this.sync();
125
+ else
126
+ this.rewire();
127
+ });
128
+ this.observer.observe(this, {
129
+ childList: true,
130
+ subtree: true,
131
+ attributes: true,
132
+ // `aria-label` too: removed, the dialog is named after its title
133
+ // again, and without it here the dialog was left without a name.
134
+ attributeFilter: ["class", "id", "aria-labelledby", "aria-label"],
135
+ });
136
+ this.sync();
137
+ }
138
+ disconnectedCallback() {
139
+ this.observer?.disconnect();
140
+ this.observer = undefined;
141
+ this.openObserver?.disconnect();
142
+ this.openObserver = undefined;
143
+ this.dialogElement?.removeEventListener("close", this.handleClose);
144
+ this.dialogElement = undefined;
145
+ }
146
+ attributeChangedCallback() {
147
+ this.sync();
148
+ }
149
+ /**
150
+ * The dialog the component controls.
151
+ *
152
+ * Only a direct child. A `<dialog>` further down the tree can belong to
153
+ * something else, and must not be opened by this component.
154
+ */
155
+ get dialog() {
156
+ return this.querySelector(LT_DIALOG_PARTS.dialog);
157
+ }
158
+ /** The wiring alone, for an attribute record. See the observer. */
159
+ rewire() {
160
+ const dialog = this.dialog;
161
+ if (dialog?.isConnected)
162
+ this.wire(dialog);
163
+ }
164
+ /**
165
+ * The heading that is the dialog's title when the server did not point to
166
+ * one.
167
+ *
168
+ * The first heading in this dialog that is not in the body. A heading in
169
+ * `.lt-dialog__body` is a heading in the content, not the dialog's name: a
170
+ * settings dialog in three sections got the first section's heading as its
171
+ * title, with the class and the styling that come with it. A heading in a
172
+ * nested dialog belongs to the nested one, and the body that counts is only
173
+ * a body in this dialog: if this dialog is itself in the body of another,
174
+ * the outer body is not its body.
175
+ */
176
+ headingOf(dialog) {
177
+ return ([...dialog.querySelectorAll(LT_DIALOG_PARTS.title)].find((heading) => {
178
+ if (heading.closest("dialog") !== dialog)
179
+ return false;
180
+ const body = heading.closest(LT_DIALOG_PARTS.body);
181
+ return body === null || !dialog.contains(body);
182
+ }) ?? null);
183
+ }
184
+ /**
185
+ * Whether the dialog has no name: no reference, no `aria-label` and no
186
+ * title. An empty `<dialog>` is a region the server has not filled yet, and
187
+ * does not count.
188
+ */
189
+ nameless(dialog) {
190
+ return (dialog.childElementCount > 0 &&
191
+ !dialog.hasAttribute("aria-labelledby") &&
192
+ !dialog.hasAttribute("aria-label") &&
193
+ this.headingOf(dialog) === null);
194
+ }
195
+ /**
196
+ * Fills in what a template without JavaScript did not write: the class on
197
+ * the dialog, and the title. The title is what `aria-labelledby` points to
198
+ * when the server wrote it, otherwise the first heading outside the body,
199
+ * and only when the dialog does not already have a name from `aria-label`.
200
+ * The class and the id are written only on the title: a heading in the body
201
+ * of a dialog with `aria-label` is not the title, and must not be styled as
202
+ * one.
203
+ */
204
+ wire(dialog) {
205
+ addClass(dialog, DIALOG_CLASS);
206
+ const named = dialog.getAttribute("aria-labelledby");
207
+ if (named) {
208
+ // The attribute can list several ids. The title is the first one that
209
+ // is inside the dialog.
210
+ const root = this.getRootNode();
211
+ const title = named
212
+ .split(/\s+/)
213
+ .map((id) => root.getElementById?.(id) ?? null)
214
+ .find((element) => element !== null && dialog.contains(element));
215
+ if (title)
216
+ addClass(title, DIALOG_TITLE_CLASS);
217
+ return;
218
+ }
219
+ if (dialog.hasAttribute("aria-label"))
220
+ return;
221
+ const title = this.headingOf(dialog);
222
+ if (!title) {
223
+ warnAboutMarkup(this, "the dialog has no name: it has no aria-labelledby, no " +
224
+ "aria-label and no heading outside the body, so a screen reader " +
225
+ 'announces it as "dialog" without saying what it is about. Give ' +
226
+ "it a heading, or aria-label on the <dialog>.", () => {
227
+ const now = this.dialog;
228
+ return now !== null && this.nameless(now);
229
+ });
230
+ return;
231
+ }
232
+ addClass(title, DIALOG_TITLE_CLASS);
233
+ if (!title.id) {
234
+ this.titleId ??= uniqueId("lt-dialog-title");
235
+ setAttr(title, "id", this.titleId);
236
+ }
237
+ setAttr(dialog, "aria-labelledby", title.id);
238
+ }
239
+ notify(open, returnValue = "") {
240
+ // A dialog starts closed: one that never opened reported a close.
241
+ if (open === (this.lastNotified ?? false))
242
+ return;
243
+ this.lastNotified = open;
244
+ this.dispatchEvent(new CustomEvent("dialog-toggle", {
245
+ bubbles: true,
246
+ // Without `composed` the event stops at a shadow root, and a listener
247
+ // outside never learns that the dialog was closed.
248
+ composed: true,
249
+ detail: { open, returnValue },
250
+ }));
251
+ }
252
+ /**
253
+ * Puts `open` back on a dialog that is still in the top layer.
254
+ *
255
+ * `showModal()` sets the attribute itself, and the server did not send it,
256
+ * so the morph removes it. The browser's own stylesheet then hides a
257
+ * `<dialog>` without `open`, and the dialog disappeared for the user in the
258
+ * middle of what she was doing. Before, the template had to write
259
+ * `data-preserve-attr="open"` to prevent it.
260
+ *
261
+ * The condition is `:modal` and not `this.open`, and that is precise: when
262
+ * the user closes the dialog, it leaves the top layer, and then the missing
263
+ * attribute is real. Only a dialog that is still modal without saying so is
264
+ * a dialog someone has taken the attribute from.
265
+ */
266
+ repairOpen() {
267
+ const dialog = this.dialogElement;
268
+ if (!dialog?.isConnected || !dialog.matches(":modal") || dialog.open) {
269
+ return;
270
+ }
271
+ // The attribute must come back either way: without it `close()` does
272
+ // nothing, and the dialog stayed in the top layer, invisible, with the
273
+ // rest of the page inert.
274
+ setAttr(dialog, "open", "");
275
+ if (!isServerControlled(this))
276
+ return;
277
+ /*
278
+ * The server decides the state, and the patch took `open` from a modal
279
+ * dialog. Then the message is that it should close, not be put back.
280
+ * Without this the dialog stood with `:modal` and `display: none`, and
281
+ * nothing on the page could be clicked. The host follows along here, so
282
+ * `handleClose` has nothing left to do and the event comes once.
283
+ */
284
+ dialog.close();
285
+ // The event comes whoever removed `open` from the host. If React has
286
+ // already taken it, in its order with children before parent, this is
287
+ // the one time anyone can report it: `sync()` and `handleClose` then see
288
+ // a dialog that is already closed, and stay quiet.
289
+ if (this.open)
290
+ this.removeAttribute("open");
291
+ this.notify(false, dialog.returnValue);
292
+ }
293
+ sync() {
294
+ const dialog = this.dialog;
295
+ // `showModal()` throws "The element is not in a Document" if the dialog
296
+ // is not on the page. That is not theoretical: a morph builds the
297
+ // server's version in a detached tree before comparing, and a web
298
+ // component is used there too. Without this line the component threw on
299
+ // every single patch that touched the dialog. If it is detached now,
300
+ // `sync()` runs again anyway when it is connected.
301
+ if (!dialog?.isConnected) {
302
+ // Let go of a dialog that is gone. Otherwise the observer and the
303
+ // listener stayed attached to a detached node for as long as the host
304
+ // lived.
305
+ if (!dialog) {
306
+ this.openObserver?.disconnect();
307
+ this.openObserver = undefined;
308
+ this.dialogElement?.removeEventListener("close", this.handleClose);
309
+ this.dialogElement = undefined;
310
+ }
311
+ warnAboutMarkup(this, "found no <dialog> as a direct child. Without it nothing can " +
312
+ "open as a modal, and the content stays on the page as a plain " +
313
+ "box.",
314
+ // If the component is detached, a morph is building the server's
315
+ // version in a separate tree, and there is nothing to report. An
316
+ // empty element is a region the server has not filled yet.
317
+ () => this.childElementCount > 0 && this.dialog === null);
318
+ return;
319
+ }
320
+ this.wire(dialog);
321
+ const first = dialog !== this.dialogElement;
322
+ if (first) {
323
+ this.dialogElement?.removeEventListener("close", this.handleClose);
324
+ this.dialogElement = dialog;
325
+ dialog.addEventListener("close", this.handleClose);
326
+ this.openObserver?.disconnect();
327
+ this.openObserver = new MutationObserver(() => this.repairOpen());
328
+ this.openObserver.observe(dialog, { attributeFilter: ["open"] });
329
+ }
330
+ this.repairOpen();
331
+ /*
332
+ * Did the user close the dialog before the component got to run?
333
+ *
334
+ * The server writes `open` in both places, so the content exists without
335
+ * JavaScript, and `<form method="dialog">` closes the box without
336
+ * JavaScript too. If that happens before the script has loaded, there is
337
+ * no listener, and the first `sync()` would see a host saying "open" and a
338
+ * dialog that is closed, and open it again. So the dialog popped up again
339
+ * right after the user had closed it, and on mobile the window was large
340
+ * enough for it to happen every time.
341
+ *
342
+ * `returnValue` tells the two cases apart. The browser sets it to the
343
+ * value of the button that closed the dialog, so a dialog that has never
344
+ * been open has it empty. A template that only wrote `open` on the host,
345
+ * as the documentation showed for a long time, also has it empty, and is
346
+ * opened as before.
347
+ *
348
+ * This works only when the button has a `value`. If the dialog is closed
349
+ * with a button without a value, or with `close()` without an argument,
350
+ * the browser leaves nothing to look for, and the dialog opens again as it
351
+ * did before. That is why every `<form method="dialog">` in the
352
+ * documentation has a `value`, and it is worth keeping.
353
+ */
354
+ if (!upgradeChecked.has(dialog)) {
355
+ upgradeChecked.add(dialog);
356
+ if (this.open && !dialog.open && dialog.returnValue !== "") {
357
+ this.removeAttribute("open");
358
+ return;
359
+ }
360
+ }
361
+ // `:modal` and not `open`. The two are not the same: a `<dialog open>`
362
+ // in the markup, and a dialog that was moved in the DOM while it was
363
+ // open, have `open` without being modal. Then it is a box on the page,
364
+ // without a focus trap and without Escape, which is exactly what the
365
+ // component exists to prevent.
366
+ const modal = dialog.matches(":modal");
367
+ /*
368
+ * The user has just closed the dialog with a button, and `close` has not
369
+ * arrived yet. The browser removes `open` at once and sends the event in a
370
+ * later task, and the host still says "open" until `handleClose` gets to
371
+ * run. When something wrote `open` on the host in the meantime, such as a
372
+ * framework setting the same value again, the component opened the dialog
373
+ * again and cleared `returnValue`, and a listener on `close` read an empty
374
+ * value instead of "delete". `returnValue` is cleared every time the
375
+ * dialog opens, so a value here comes from a button in this round.
376
+ */
377
+ if (this.open &&
378
+ !modal &&
379
+ this.lastNotified === true &&
380
+ dialog.returnValue !== "") {
381
+ return;
382
+ }
383
+ if (this.open && !modal) {
384
+ /*
385
+ * `showModal()` throws `InvalidStateError` when `open` is already there
386
+ * without the dialog being modal. So the attribute must go first.
387
+ *
388
+ * But not with `close()`. It sends a real `close` event, and since the
389
+ * server now writes `open` on the `<dialog>` itself, that event would
390
+ * have come on every single load of a dialog that is open. An app
391
+ * listening for `close` directly on the `<dialog>`, as the complete
392
+ * example in the documentation does, then got a phantom close before the
393
+ * user had seen the dialog. `removeAttribute` makes room without the
394
+ * event.
395
+ */
396
+ dialog.removeAttribute("open");
397
+ /*
398
+ * Escape and `close()` without an argument leave the previous
399
+ * `returnValue` in place. A dialog the server opened again then
400
+ * reported "delete" from last time when it was closed from the server,
401
+ * and the app that tells "Cancel" from "Delete" by the value deleted
402
+ * something the user never asked for.
403
+ */
404
+ dialog.returnValue = "";
405
+ dialog.showModal();
406
+ this.notify(true);
407
+ }
408
+ else if (!this.open && (modal || dialog.open)) {
409
+ /*
410
+ * `modal` and not only `dialog.open`: the attribute can be gone while
411
+ * the dialog is still in the top layer.
412
+ *
413
+ * React is the reason. The server writes `open` on the `<dialog>`, so
414
+ * React manages the attribute, and React updates children before the
415
+ * parent. When the app closes the dialog, React first removes `open`
416
+ * from the `<dialog>` and then from `<lt-dialog>`. So we get here with
417
+ * `dialog.open` already false.
418
+ *
419
+ * `close()` does nothing without the attribute, so without this the
420
+ * dialog stayed in the top layer, invisible, with the rest of the page
421
+ * inert. The user was left with a page where nothing could be clicked,
422
+ * and nothing visible to explain why.
423
+ */
424
+ setAttr(dialog, "open", "");
425
+ dialog.close();
426
+ this.notify(false, dialog.returnValue);
427
+ }
428
+ }
429
+ }
430
+ LtDialog.observedAttributes = ["open", SERVER_CONTROLLED];
431
+ export function defineLtDialog(tagName = LT_DIALOG_TAG) {
432
+ defineElement(tagName, LtDialog);
433
+ }
434
+ //# sourceMappingURL=lt-dialog.js.map