@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,136 @@
1
+ import { HostElement } from "../../host-element.js";
2
+ import { type PopoverPlacement } from "./popover.js";
3
+ export declare const LT_POPOVER_TAG: "lt-popover";
4
+ /**
5
+ * The parts the popover 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 declare const LT_POPOVER_PARTS: {
10
+ readonly trigger: "button, [role='button']";
11
+ readonly panel: "[popover], .lt-popover";
12
+ };
13
+ /**
14
+ * A panel that hangs below a button, and closes itself.
15
+ *
16
+ * The panel uses the browser's own `popover`, so it goes into the top layer
17
+ * and lies above everything else without `z-index`. `lt.popover()` writes
18
+ * `popover="manual"`, so Escape and clicks outside are handled by the
19
+ * component: with `auto` the browser closed the panel before the button got
20
+ * its click, and the button could not be used to close it again. Handwritten
21
+ * markup with a bare `popover` is `auto`, and then the component follows along
22
+ * when the browser closes it.
23
+ *
24
+ * What the top layer does not do is place the panel. `position-anchor` is not
25
+ * yet in every browser, so the position is worked out here.
26
+ *
27
+ * When the markup is made with JavaScript, `lt.popover()` writes the wiring:
28
+ * `aria-controls` on the button, and the class, the id and `popover` on the
29
+ * panel. When the markup comes from a template without JavaScript, the
30
+ * template writes a button and a panel with the class `lt-popover` and an id:
31
+ * the component sets `popover="manual"` and writes `aria-controls` on the
32
+ * button from the id. Only what is missing, so what the server wrote stays.
33
+ * The component sets `open` on the host, `aria-expanded` on the button and the
34
+ * position on the panel, and puts back everything it has written when a patch
35
+ * removes it. The template needs no `data-preserve-attr`.
36
+ *
37
+ * The component never writes an id on the panel. Datastar and idiomorph
38
+ * recognise an element by its id, and a panel with an id the server did not
39
+ * send was replaced on the next patch, along with focus and what the user had
40
+ * done in it. Without an id the panel is kept, but the button cannot be
41
+ * connected to it with `aria-controls`, and the component says so in the
42
+ * console.
43
+ *
44
+ * The repair works one way: if someone has asked for the popover to be open,
45
+ * it stays open through a patch. If the server sends `open`, it opens, since
46
+ * that is something the server actually said.
47
+ *
48
+ * For the server to decide the state, set `server-controlled` on the host.
49
+ * That is also the answer when the page controls `open` with an attribute from
50
+ * outside, as with Datastar's `data-attr:open`: a removed attribute cannot be
51
+ * told apart from a morph, while `menu.open = false` is a message the
52
+ * component can see.
53
+ *
54
+ * ```html
55
+ * <lt-popover placement="bottom-end">
56
+ * <button class="lt-button" aria-controls="menu" aria-expanded="false">Actions</button>
57
+ * <ul id="menu" class="lt-popover" popover="manual">…</ul>
58
+ * </lt-popover>
59
+ * ```
60
+ */
61
+ export declare class LtPopover extends HostElement {
62
+ static observedAttributes: readonly ["open", "placement", "server-controlled"];
63
+ private panel?;
64
+ private triggerElement?;
65
+ private observer?;
66
+ /**
67
+ * What the component was last asked for, through the `open` property.
68
+ *
69
+ * `open` lives on the host, and a morph removes everything that is not in
70
+ * the server's HTML. Without anything more, every single patch closed a
71
+ * popover the user had just opened.
72
+ *
73
+ * A removed attribute looks the same whoever removed it, so the component
74
+ * cannot tell a morph from an app. The distinction is instead **how** the app
75
+ * says it: if it goes through the property, as in `menu.open = false`,
76
+ * `hide()` or `toggle()`, that is a message, and it is followed. If something
77
+ * sets the attribute directly, as Datastar's `data-attr:open` does, it cannot
78
+ * be told apart from a morph, and then the page should say
79
+ * `server-controlled` and let the server decide the state.
80
+ */
81
+ private wantsOpen;
82
+ /** Whether the panel is open. Mirrored, so CSS can match the state. */
83
+ get open(): boolean;
84
+ set open(value: boolean);
85
+ /** Which edge the panel hangs from. Default: `bottom-start`. */
86
+ get placement(): PopoverPlacement;
87
+ set placement(value: PopoverPlacement);
88
+ connectedCallback(): void;
89
+ disconnectedCallback(): void;
90
+ attributeChangedCallback(name: string): void;
91
+ private sync;
92
+ /**
93
+ * Says so when a patch replaced the open panel because the id from the
94
+ * server changed.
95
+ *
96
+ * Datastar and idiomorph recognise an element by its id, and a new id is a
97
+ * new element to them. The component opens the new panel again, but focus,
98
+ * and what the user typed in a field in it, are gone. It happens when the
99
+ * template builds the id from something that changes between renders, such
100
+ * as a random number or a counter.
101
+ *
102
+ * The message comes only when the popover was open and both panels had an id
103
+ * from the server, with different values. A panel without an id is kept by
104
+ * the morph, and a server that deliberately sends another panel while the
105
+ * popover is closed has nothing to fix.
106
+ */
107
+ private warnAboutReplacedPanel;
108
+ /** The panel: the one with `popover`, otherwise the one with the class. */
109
+ private findPanel;
110
+ /**
111
+ * The button: the one pointing to the panel with `aria-controls`, otherwise
112
+ * the first button outside the panel that does not point to anything else. A
113
+ * button with an `aria-controls` pointing elsewhere is not a fallback: then
114
+ * the server has said something else, and that is not to be guessed around.
115
+ */
116
+ private findTrigger;
117
+ private handleTriggerClick;
118
+ private handlePanelToggle;
119
+ private handleOutsideClick;
120
+ private handleKeydown;
121
+ /** Works out where the panel goes, against the button's place on screen. */
122
+ private reposition;
123
+ private emit;
124
+ /**
125
+ * Opens the panel. Through the setter also when it is open already, as
126
+ * when the server sent `open`: the call is the app's message, and without
127
+ * it the next patch without `open` closed the panel.
128
+ */
129
+ show(): void;
130
+ /** Closes the panel. Through the setter also when it is closed, as `show()`. */
131
+ hide(): void;
132
+ /** Opens or closes. */
133
+ toggle(): void;
134
+ }
135
+ export declare function defineLtPopover(tagName?: string): void;
136
+ //# sourceMappingURL=lt-popover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lt-popover.d.ts","sourceRoot":"","sources":["../../../../src/components/frame/popover/lt-popover.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,WAAW,EAMZ,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,cAAc,CAAA;AAErB,eAAO,MAAM,cAAc,EAAG,YAAqB,CAAA;AAEnD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;CAGnB,CAAA;AAEV;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,qBAAa,SAAU,SAAQ,WAAW;IACxC,MAAM,CAAC,kBAAkB,sDAAoD;IAE7E,OAAO,CAAC,KAAK,CAAC,CAAa;IAC3B,OAAO,CAAC,cAAc,CAAC,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,CAAkB;IACnC;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,SAAS,CAAQ;IAEzB,uEAAuE;IACvE,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAStB;IAED,gEAAgE;IAChE,IAAI,SAAS,IAAI,gBAAgB,CAGhC;IAED,IAAI,SAAS,CAAC,KAAK,EAAE,gBAAgB,EAEpC;IAED,iBAAiB,IAAI,IAAI;IAuCzB,oBAAoB,IAAI,IAAI;IAgB5B,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAU5C,OAAO,CAAC,IAAI;IA0KZ;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,sBAAsB;IAkB9B,2EAA2E;IAC3E,OAAO,CAAC,SAAS;IAIjB;;;;;OAKG;IACH,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,kBAAkB,CAQzB;IAED,OAAO,CAAC,iBAAiB,CAkBxB;IAED,OAAO,CAAC,kBAAkB,CAOzB;IAED,OAAO,CAAC,aAAa,CA2CpB;IAED,4EAA4E;IAC5E,OAAO,CAAC,UAAU,CA0CjB;IAED,OAAO,CAAC,IAAI;IAUZ;;;;OAIG;IACH,IAAI,IAAI,IAAI;IAMZ,gFAAgF;IAChF,IAAI,IAAI,IAAI;IAMZ,uBAAuB;IACvB,MAAM,IAAI,IAAI;CAIf;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,MAAuB,GAAG,IAAI,CAEtE"}
@@ -0,0 +1,520 @@
1
+ import { addClass, defineElement, HostElement, isServerControlled, SERVER_CONTROLLED, setAttr, setFlag, warnAboutMarkup, } from "../../host-element.js";
2
+ import { isPopoverPlacement, POPOVER_CLASS, } from "./popover.js";
3
+ export const LT_POPOVER_TAG = "lt-popover";
4
+ /**
5
+ * The parts the popover 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_POPOVER_PARTS = {
10
+ trigger: "button, [role='button']",
11
+ panel: `[popover], .${POPOVER_CLASS}`,
12
+ };
13
+ /**
14
+ * A panel that hangs below a button, and closes itself.
15
+ *
16
+ * The panel uses the browser's own `popover`, so it goes into the top layer
17
+ * and lies above everything else without `z-index`. `lt.popover()` writes
18
+ * `popover="manual"`, so Escape and clicks outside are handled by the
19
+ * component: with `auto` the browser closed the panel before the button got
20
+ * its click, and the button could not be used to close it again. Handwritten
21
+ * markup with a bare `popover` is `auto`, and then the component follows along
22
+ * when the browser closes it.
23
+ *
24
+ * What the top layer does not do is place the panel. `position-anchor` is not
25
+ * yet in every browser, so the position is worked out here.
26
+ *
27
+ * When the markup is made with JavaScript, `lt.popover()` writes the wiring:
28
+ * `aria-controls` on the button, and the class, the id and `popover` on the
29
+ * panel. When the markup comes from a template without JavaScript, the
30
+ * template writes a button and a panel with the class `lt-popover` and an id:
31
+ * the component sets `popover="manual"` and writes `aria-controls` on the
32
+ * button from the id. Only what is missing, so what the server wrote stays.
33
+ * The component sets `open` on the host, `aria-expanded` on the button and the
34
+ * position on the panel, and puts back everything it has written when a patch
35
+ * removes it. The template needs no `data-preserve-attr`.
36
+ *
37
+ * The component never writes an id on the panel. Datastar and idiomorph
38
+ * recognise an element by its id, and a panel with an id the server did not
39
+ * send was replaced on the next patch, along with focus and what the user had
40
+ * done in it. Without an id the panel is kept, but the button cannot be
41
+ * connected to it with `aria-controls`, and the component says so in the
42
+ * console.
43
+ *
44
+ * The repair works one way: if someone has asked for the popover to be open,
45
+ * it stays open through a patch. If the server sends `open`, it opens, since
46
+ * that is something the server actually said.
47
+ *
48
+ * For the server to decide the state, set `server-controlled` on the host.
49
+ * That is also the answer when the page controls `open` with an attribute from
50
+ * outside, as with Datastar's `data-attr:open`: a removed attribute cannot be
51
+ * told apart from a morph, while `menu.open = false` is a message the
52
+ * component can see.
53
+ *
54
+ * ```html
55
+ * <lt-popover placement="bottom-end">
56
+ * <button class="lt-button" aria-controls="menu" aria-expanded="false">Actions</button>
57
+ * <ul id="menu" class="lt-popover" popover="manual">…</ul>
58
+ * </lt-popover>
59
+ * ```
60
+ */
61
+ export class LtPopover extends HostElement {
62
+ constructor() {
63
+ super(...arguments);
64
+ /**
65
+ * What the component was last asked for, through the `open` property.
66
+ *
67
+ * `open` lives on the host, and a morph removes everything that is not in
68
+ * the server's HTML. Without anything more, every single patch closed a
69
+ * popover the user had just opened.
70
+ *
71
+ * A removed attribute looks the same whoever removed it, so the component
72
+ * cannot tell a morph from an app. The distinction is instead **how** the app
73
+ * says it: if it goes through the property, as in `menu.open = false`,
74
+ * `hide()` or `toggle()`, that is a message, and it is followed. If something
75
+ * sets the attribute directly, as Datastar's `data-attr:open` does, it cannot
76
+ * be told apart from a morph, and then the page should say
77
+ * `server-controlled` and let the server decide the state.
78
+ */
79
+ this.wantsOpen = false;
80
+ this.handleTriggerClick = () => {
81
+ const closing = this.open;
82
+ this.toggle();
83
+ // Safari gives a clicked button no focus: focus in the panel went to
84
+ // `<body>` with the click, before the panel closed, and `sync()` did not
85
+ // see it there. The other browsers have given the button focus already.
86
+ if (closing && document.activeElement === document.body)
87
+ this.triggerElement?.focus();
88
+ };
89
+ this.handlePanelToggle = (event) => {
90
+ const state = event.newState;
91
+ /*
92
+ * The event applies only when it matches the panel. `toggle` is delivered as
93
+ * a separate task, after everything that happened in the same round, and can
94
+ * describe a state that has already changed. A patch that takes `open` on
95
+ * the host and `popover` on the panel in the same morph closes the panel
96
+ * here in `sync()`, reopens it in the microtask afterwards, and only then
97
+ * does "closed" arrive from the close. Before, it was taken as the user's,
98
+ * and the popover the user had open stayed closed after a patch that said
99
+ * nothing about it.
100
+ *
101
+ * The component's own `showPopover()` and `hidePopover()` also fire the
102
+ * event, but then `open` already matches, and nothing happens.
103
+ */
104
+ const showing = event.currentTarget.matches(":popover-open");
105
+ if (state === "closed" && this.open && !showing)
106
+ this.hide();
107
+ else if (state === "open" && !this.open && showing)
108
+ this.show();
109
+ };
110
+ this.handleOutsideClick = (event) => {
111
+ // `composedPath()` and not `target`: when the component is in a shadow
112
+ // root, `target` is retargeted to the shadow host, and a click in the panel
113
+ // itself looked like a click outside.
114
+ const target = event.composedPath()[0];
115
+ if (this.contains(target) || this.panel?.contains(target))
116
+ return;
117
+ this.hide();
118
+ };
119
+ this.handleKeydown = (event) => {
120
+ if (event.key !== "Escape" || !this.open)
121
+ return;
122
+ // Something else has already used the key press, such as a suggestion list
123
+ // that closed. Without this one press closed both the list and the popover.
124
+ if (event.defaultPrevented)
125
+ return;
126
+ // `composedPath()` and not `contains`: a field in a shadow root in the
127
+ // panel is not in the tree `contains` sees, and a press there closed nothing.
128
+ const path = event.composedPath();
129
+ for (const node of path) {
130
+ if (node === this)
131
+ break;
132
+ // An open popover inside this one is closer. It takes the press, and this
133
+ // one closes on the next. The listeners are both on `document`, and the
134
+ // outer one came first: before, it closed and left the inner one open.
135
+ if (node instanceof LtPopover && node.open)
136
+ return;
137
+ // A modal dialog opened on top of the popover is closed by its own press.
138
+ if (node instanceof HTMLDialogElement &&
139
+ node.matches(":modal") &&
140
+ !node.contains(this)) {
141
+ return;
142
+ }
143
+ }
144
+ /*
145
+ * Focus is moved back only when it was in the popover, or nowhere else: on
146
+ * `body`, or on a dialog or a `<main tabindex="-1">` the popover is in. A
147
+ * mouse click does not give the button focus in Safari, and inside a modal
148
+ * dialog the dialog gets the focus. If focus was in another field, it stays
149
+ * there. Before, it jumped to the button.
150
+ */
151
+ const target = path[0];
152
+ const fromWindow = path.includes(this) || (target instanceof Node && target.contains(this));
153
+ // Used here. Without this it also closed a modal dialog the popover was
154
+ // in: one press took both, and the user lost the dialog.
155
+ event.preventDefault();
156
+ this.hide();
157
+ // Without this focus is on a panel that no longer exists, and the next
158
+ // key press starts at the top of the page.
159
+ if (fromWindow)
160
+ this.triggerElement?.focus();
161
+ };
162
+ /** Works out where the panel goes, against the button's place on screen. */
163
+ this.reposition = () => {
164
+ if (!this.open || !this.panel || !this.triggerElement)
165
+ return;
166
+ const anchor = this.triggerElement.getBoundingClientRect();
167
+ const panel = this.panel.getBoundingClientRect();
168
+ const space = 4;
169
+ const below = this.placement.startsWith("bottom");
170
+ // `start` and `end` follow the reading direction: in a right-to-left
171
+ // document `start` is the button's right edge. Without this the panel was on
172
+ // the wrong side of the button in RTL. `:dir(rtl)` and not `direction` from
173
+ // `getComputedStyle`: the stylesheet flips the value with `:dir(rtl)`, so
174
+ // both read the HTML direction from `dir`. A page that sets
175
+ // `direction: rtl` in CSS without `dir` is not flipped, neither here nor in
176
+ // the stylesheet, as with the background icons.
177
+ const rtl = this.panel.matches(":dir(rtl)");
178
+ const alignRight = this.placement.endsWith("end") !== rtl;
179
+ let top = below ? anchor.bottom + space : anchor.top - panel.height - space;
180
+ let left = alignRight ? anchor.right - panel.width : anchor.left;
181
+ // The panel must not end up off screen. If it goes out at the side, it is
182
+ // moved in. If there is no room on the side of the button the placement asks
183
+ // for, it goes on the other side, and is then clamped into the viewport
184
+ // either way. `top-*` lacked the last part, and a panel at the top of the
185
+ // page lay entirely off screen, with no way to scroll it into view.
186
+ left = Math.max(space, Math.min(left, window.innerWidth - panel.width - space));
187
+ if (below && top + panel.height > window.innerHeight) {
188
+ top = anchor.top - panel.height - space;
189
+ }
190
+ else if (!below && top < space) {
191
+ top = anchor.bottom + space;
192
+ }
193
+ top = Math.max(space, Math.min(top, window.innerHeight - panel.height - space));
194
+ this.panel.style.setProperty("--lt-popover-top", `${Math.round(top)}px`);
195
+ this.panel.style.setProperty("--lt-popover-left", `${Math.round(left)}px`);
196
+ };
197
+ }
198
+ /** Whether the panel is open. Mirrored, so CSS can match the state. */
199
+ get open() {
200
+ return this.hasAttribute("open");
201
+ }
202
+ set open(value) {
203
+ // The message is noted here, and not in `show()` and `hide()`. Both go
204
+ // through the setter, but so does `menu.open = false` from an app, and
205
+ // without this the component set the attribute straight back again.
206
+ //
207
+ // No memory when the server decides the state. Without that guard the
208
+ // popover popped open by itself the moment `server-controlled` was removed.
209
+ this.wantsOpen = isServerControlled(this) ? false : value;
210
+ setFlag(this, "open", value);
211
+ }
212
+ /** Which edge the panel hangs from. Default: `bottom-start`. */
213
+ get placement() {
214
+ const value = this.getAttribute("placement");
215
+ return isPopoverPlacement(value) ? value : "bottom-start";
216
+ }
217
+ set placement(value) {
218
+ setAttr(this, "placement", value);
219
+ }
220
+ connectedCallback() {
221
+ window.addEventListener("resize", this.reposition);
222
+ window.addEventListener("scroll", this.reposition, true);
223
+ /*
224
+ * The attributes are included, not only the children. `aria-expanded` on the
225
+ * button and the position on the panel are something the component works
226
+ * out, so if a patch removes them, they must come back. Every write in
227
+ * `sync()` compares first, or the observer would trigger itself.
228
+ */
229
+ this.observer = new MutationObserver((records) => {
230
+ // `type` concerns only the button. A password field in the panel that
231
+ // switches between `password` and `text` must not run all of `sync()`.
232
+ const onlyOtherTypes = records.every((record) => record.attributeName === "type" &&
233
+ record.target !== this.triggerElement);
234
+ if (!onlyOtherTypes)
235
+ this.sync();
236
+ });
237
+ this.observer.observe(this, {
238
+ childList: true,
239
+ subtree: true,
240
+ attributes: true,
241
+ attributeFilter: [
242
+ "aria-expanded",
243
+ "style",
244
+ // The wiring the component fills in when the markup came without it.
245
+ "popover",
246
+ "id",
247
+ "aria-controls",
248
+ "class",
249
+ // A patch from a template without `type` removes it, and then the
250
+ // button submits the form again.
251
+ "type",
252
+ ],
253
+ });
254
+ this.sync();
255
+ }
256
+ disconnectedCallback() {
257
+ window.removeEventListener("resize", this.reposition);
258
+ window.removeEventListener("scroll", this.reposition, true);
259
+ document.removeEventListener("click", this.handleOutsideClick, true);
260
+ document.removeEventListener("keydown", this.handleKeydown);
261
+ this.observer?.disconnect();
262
+ this.observer = undefined;
263
+ this.triggerElement?.removeEventListener("click", this.handleTriggerClick);
264
+ this.panel?.removeEventListener("toggle", this.handlePanelToggle);
265
+ // The reference must be reset, or `sync()` sees that the button is the
266
+ // same when the element is inserted again, and skips attaching the listener
267
+ // again. Then the panel can no longer be opened.
268
+ this.triggerElement = undefined;
269
+ this.panel = undefined;
270
+ }
271
+ attributeChangedCallback(name) {
272
+ // `server-controlled` turned on midway: the component lets go, and the
273
+ // next patch decides.
274
+ if (name === SERVER_CONTROLLED && isServerControlled(this)) {
275
+ this.wantsOpen = false;
276
+ }
277
+ if (this.isConnected)
278
+ this.sync();
279
+ }
280
+ sync() {
281
+ /*
282
+ * Puts `open` back when a patch took it.
283
+ *
284
+ * One way only: if `open` is there, the popover is open, and then either the
285
+ * user or the server has said so. If it is gone while the user opened it, the
286
+ * morph took it, and then it comes back.
287
+ */
288
+ const repairing = this.wantsOpen && !this.open && !isServerControlled(this);
289
+ if (repairing) {
290
+ /*
291
+ * Wait until the whole patch has landed before opening the popover again.
292
+ *
293
+ * A morph sets one attribute at a time, and `open` comes before
294
+ * `server-controlled` in document order. When the component repaired at
295
+ * once, it put `open` back while the server was in the middle of saying it
296
+ * was taking over the state, and the popover stayed open afterwards.
297
+ * `queueMicrotask` runs after the whole patch is done, and the condition is
298
+ * checked again there.
299
+ *
300
+ * Until then the panel stays as it is: closing it while the repair waits
301
+ * took the focus from a button in it to the trigger on every patch.
302
+ * When the repair is called off, `sync()` closes the panel for real.
303
+ */
304
+ queueMicrotask(() => {
305
+ if (!this.isConnected)
306
+ return;
307
+ if (!isServerControlled(this) && this.wantsOpen && !this.open)
308
+ setFlag(this, "open", true);
309
+ else
310
+ this.sync();
311
+ });
312
+ }
313
+ // The parts are recognised by the wiring that must be there anyway: the
314
+ // panel is the one with `popover`, and the button is the one pointing to the
315
+ // panel with `aria-controls`. Before, the button had `slot="trigger"`, a
316
+ // leftover from the time the component had shadow DOM. Without a shadow
317
+ // root `slot` does nothing in HTML, so the attribute was a label that looked
318
+ // like something it was not.
319
+ const panel = this.findPanel();
320
+ if (panel) {
321
+ // Only what is missing. A template may have written `popover` without a
322
+ // value, and that is `auto`; then the component follows along when the
323
+ // browser closes it.
324
+ addClass(panel, POPOVER_CLASS);
325
+ if (!panel.hasAttribute("popover"))
326
+ setAttr(panel, "popover", "manual");
327
+ // Never an id on the panel: see the comment at the top. Without an id there
328
+ // is nothing for `aria-controls` to point to.
329
+ warnAboutMarkup(this, "the panel has no id, so the button cannot be connected to it " +
330
+ "with aria-controls. Write an id on the panel in the template, " +
331
+ 'such as id="menu", and the same value in aria-controls on the ' +
332
+ "button.", () => {
333
+ const found = this.findPanel();
334
+ return found !== null && !found.id;
335
+ });
336
+ }
337
+ const trigger = panel ? this.findTrigger(panel) : null;
338
+ if (panel?.id && trigger && !trigger.hasAttribute("aria-controls")) {
339
+ setAttr(trigger, "aria-controls", panel.id);
340
+ }
341
+ // A `<button>` without `type` is a submit button, and so is one with an
342
+ // empty or unknown `type`, which a template can write. A help popover next
343
+ // to a field sits inside the form, and a click to open it submitted the
344
+ // form, or brought up the error summary, instead of showing the panel. A
345
+ // button that says `submit` itself is left alone.
346
+ if (trigger instanceof HTMLButtonElement &&
347
+ trigger.type === "submit" &&
348
+ trigger.getAttribute("type")?.toLowerCase() !== "submit") {
349
+ setAttr(trigger, "type", "button");
350
+ }
351
+ if (!trigger || !panel) {
352
+ /*
353
+ * Two different faults, and a message for each, so the developer looks in
354
+ * the right place. An empty element is a region the server has not filled
355
+ * yet, and that is not a fault in the markup.
356
+ */
357
+ const isEmpty = () => this.childElementCount === 0;
358
+ if (!panel) {
359
+ warnAboutMarkup(this, "found no panel: an element with popover or the class " +
360
+ "lt-popover. Without one there is nothing to open or position.", () => !isEmpty() && this.findPanel() === null);
361
+ }
362
+ else {
363
+ warnAboutMarkup(this, "found no button: neither one with aria-controls pointing to " +
364
+ "the panel nor a <button> outside the panel. Without it the " +
365
+ "component does not know what opens the popover.", () => {
366
+ const found = this.findPanel();
367
+ return !isEmpty() && found !== null && !this.findTrigger(found);
368
+ });
369
+ }
370
+ /*
371
+ * Let go of what we had. When a patch removed the panel, the component
372
+ * otherwise held on to a detached node, and `reposition()` kept working out
373
+ * the position of something that is not on the page.
374
+ *
375
+ * The listeners on `document` must go too. Without that they stayed in the
376
+ * capture phase for as long as the markup was broken, and a click anywhere
377
+ * on the page gave the app a `popover-toggle` it had not asked for.
378
+ */
379
+ this.triggerElement?.removeEventListener("click", this.handleTriggerClick);
380
+ this.triggerElement = undefined;
381
+ this.panel?.removeEventListener("toggle", this.handlePanelToggle);
382
+ this.panel = undefined;
383
+ document.removeEventListener("click", this.handleOutsideClick, true);
384
+ document.removeEventListener("keydown", this.handleKeydown);
385
+ return;
386
+ }
387
+ if (this.triggerElement !== trigger) {
388
+ this.triggerElement?.removeEventListener("click", this.handleTriggerClick);
389
+ trigger.addEventListener("click", this.handleTriggerClick);
390
+ this.triggerElement = trigger;
391
+ }
392
+ if (this.panel !== panel) {
393
+ if (this.panel)
394
+ this.warnAboutReplacedPanel(this.panel, panel);
395
+ /*
396
+ * The state is in the markup as `:popover-open`, and is read from there.
397
+ * When the browser closes a `popover="auto"` itself, because another one
398
+ * opens or the user clicks outside, `toggle` reports it. Without the
399
+ * listener the host kept `open` and the button `aria-expanded="true"` over a
400
+ * closed panel, and the next click did nothing visible.
401
+ */
402
+ this.panel?.removeEventListener("toggle", this.handlePanelToggle);
403
+ panel.addEventListener("toggle", this.handlePanelToggle);
404
+ this.panel = panel;
405
+ }
406
+ // Shown while a repair waits, so the button says the same as the panel.
407
+ const shown = this.open || repairing;
408
+ // Written by the component, and set again if a patch took it.
409
+ setAttr(trigger, "aria-expanded", String(shown));
410
+ if (shown) {
411
+ if (!panel.matches(":popover-open"))
412
+ panel.showPopover();
413
+ this.reposition();
414
+ document.addEventListener("click", this.handleOutsideClick, true);
415
+ document.addEventListener("keydown", this.handleKeydown);
416
+ }
417
+ else {
418
+ if (panel.matches(":popover-open")) {
419
+ /*
420
+ * Focus in the panel goes back to the button, whatever closed it:
421
+ * `hide()`, `toggle()`, the server taking `open`. Otherwise it stays
422
+ * on a button that is no longer shown, and the next key press starts
423
+ * at the top of the page. Escape did this alone before. Focus
424
+ * elsewhere, such as a field the user clicked outside, stays.
425
+ */
426
+ const inside = panel.contains(document.activeElement);
427
+ panel.hidePopover();
428
+ if (inside)
429
+ trigger.focus();
430
+ }
431
+ document.removeEventListener("click", this.handleOutsideClick, true);
432
+ document.removeEventListener("keydown", this.handleKeydown);
433
+ }
434
+ }
435
+ /**
436
+ * Says so when a patch replaced the open panel because the id from the
437
+ * server changed.
438
+ *
439
+ * Datastar and idiomorph recognise an element by its id, and a new id is a
440
+ * new element to them. The component opens the new panel again, but focus,
441
+ * and what the user typed in a field in it, are gone. It happens when the
442
+ * template builds the id from something that changes between renders, such
443
+ * as a random number or a counter.
444
+ *
445
+ * The message comes only when the popover was open and both panels had an id
446
+ * from the server, with different values. A panel without an id is kept by
447
+ * the morph, and a server that deliberately sends another panel while the
448
+ * popover is closed has nothing to fix.
449
+ */
450
+ warnAboutReplacedPanel(lost, panel) {
451
+ if (lost.isConnected || !this.wantsOpen)
452
+ return;
453
+ if (!lost.id || !panel.id || lost.id === panel.id)
454
+ return;
455
+ warnAboutMarkup(this, "a server update replaced the panel while it was open, because " +
456
+ "the panel's id was different from last time and the update did " +
457
+ "not recognise it. The panel is opened again, but focus and " +
458
+ "what the user did in it are lost; build the id from something " +
459
+ "that is the same every time, not from a random number or a " +
460
+ "counter.",
461
+ // The replacement has happened and cannot undo itself, unless a new
462
+ // update has already replaced the panel again.
463
+ () => !lost.isConnected && this.findPanel() === panel);
464
+ }
465
+ /** The panel: the one with `popover`, otherwise the one with the class. */
466
+ findPanel() {
467
+ return this.querySelector(LT_POPOVER_PARTS.panel);
468
+ }
469
+ /**
470
+ * The button: the one pointing to the panel with `aria-controls`, otherwise
471
+ * the first button outside the panel that does not point to anything else. A
472
+ * button with an `aria-controls` pointing elsewhere is not a fallback: then
473
+ * the server has said something else, and that is not to be guessed around.
474
+ */
475
+ findTrigger(panel) {
476
+ if (panel.id) {
477
+ const pointing = this.querySelector(`[aria-controls="${CSS.escape(panel.id)}"]`);
478
+ if (pointing)
479
+ return pointing;
480
+ }
481
+ return ([...this.querySelectorAll(LT_POPOVER_PARTS.trigger)].find((button) => !panel.contains(button) && !button.hasAttribute("aria-controls")) ?? null);
482
+ }
483
+ emit(open) {
484
+ this.dispatchEvent(new CustomEvent("popover-toggle", {
485
+ detail: { open },
486
+ bubbles: true,
487
+ composed: true,
488
+ }));
489
+ }
490
+ /**
491
+ * Opens the panel. Through the setter also when it is open already, as
492
+ * when the server sent `open`: the call is the app's message, and without
493
+ * it the next patch without `open` closed the panel.
494
+ */
495
+ show() {
496
+ const was = this.open;
497
+ this.open = true;
498
+ if (!was)
499
+ this.emit(true);
500
+ }
501
+ /** Closes the panel. Through the setter also when it is closed, as `show()`. */
502
+ hide() {
503
+ const was = this.open;
504
+ this.open = false;
505
+ if (was)
506
+ this.emit(false);
507
+ }
508
+ /** Opens or closes. */
509
+ toggle() {
510
+ if (this.open)
511
+ this.hide();
512
+ else
513
+ this.show();
514
+ }
515
+ }
516
+ LtPopover.observedAttributes = ["open", "placement", SERVER_CONTROLLED];
517
+ export function defineLtPopover(tagName = LT_POPOVER_TAG) {
518
+ defineElement(tagName, LtPopover);
519
+ }
520
+ //# sourceMappingURL=lt-popover.js.map