@supersoniks/concorde 5.1.0 → 5.1.1

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 (312) hide show
  1. package/.claude/launch.json +15 -0
  2. package/.claude/vite.http.config.mjs +7 -0
  3. package/.taste-skill/after/desktop-fold.jpg +0 -0
  4. package/.taste-skill/after/desktop-page-01.jpg +0 -0
  5. package/.taste-skill/after/desktop-page-02.jpg +0 -0
  6. package/.taste-skill/after/desktop-page-03.jpg +0 -0
  7. package/.taste-skill/after/mobile-fold.jpg +0 -0
  8. package/.taste-skill/after/mobile-page-01.jpg +0 -0
  9. package/.taste-skill/after/report.json +4103 -0
  10. package/.taste-skill/after/tablet-fold.jpg +0 -0
  11. package/.taste-skill/after/tablet-page-01.jpg +0 -0
  12. package/.taste-skill/after/tablet-page-02.jpg +0 -0
  13. package/.taste-skill/before/desktop-fold.jpg +0 -0
  14. package/.taste-skill/before/desktop-page-01.jpg +0 -0
  15. package/.taste-skill/before/desktop-page-02.jpg +0 -0
  16. package/.taste-skill/before/mobile-fold.jpg +0 -0
  17. package/.taste-skill/before/mobile-page-01.jpg +0 -0
  18. package/.taste-skill/before/report.json +2556 -0
  19. package/.taste-skill/before/tablet-fold.jpg +0 -0
  20. package/.taste-skill/before/tablet-page-01.jpg +0 -0
  21. package/.taste-skill/direction.json +510 -0
  22. package/.taste-skill/notes.md +84 -0
  23. package/.taste-skill/prod/desktop-fold.jpg +0 -0
  24. package/.taste-skill/prod/desktop-page-01.jpg +0 -0
  25. package/.taste-skill/prod/desktop-page-02.jpg +0 -0
  26. package/.taste-skill/prod/desktop-page-03.jpg +0 -0
  27. package/.taste-skill/prod/mobile-fold.jpg +0 -0
  28. package/.taste-skill/prod/mobile-page-01.jpg +0 -0
  29. package/.taste-skill/prod/mobile-page-02.jpg +0 -0
  30. package/.taste-skill/prod/report.json +1973 -0
  31. package/.taste-skill/prod/tablet-fold.jpg +0 -0
  32. package/.taste-skill/prod/tablet-page-01.jpg +0 -0
  33. package/.taste-skill/prod/tablet-page-02.jpg +0 -0
  34. package/.tmp-cem/custom-elements.json +1939 -1939
  35. package/AUDIT.md +228 -0
  36. package/PLAN-AMELIORATION.md +220 -0
  37. package/build-infos.json +1 -1
  38. package/concorde-core.bundle.js +16 -16
  39. package/concorde-core.es.js +235 -233
  40. package/dist/concorde-core.bundle.js +16 -16
  41. package/dist/concorde-core.es.js +235 -233
  42. package/dist/img/archive/concorde-001-2cv.webp +0 -0
  43. package/dist/img/archive/concorde-red-arrows-2002-poster.jpg +0 -0
  44. package/dist/img/archive/concorde-red-arrows-2002.webm +0 -0
  45. package/dist/img/archive/credits.json +28 -0
  46. package/docs/assets/index-Bb-_LRyY.js +12280 -0
  47. package/docs/assets/index-CD4WyL6o.css +1 -0
  48. package/docs/docs-mock-api-sw.js +2 -0
  49. package/docs/docs-mock-api-sw.js.map +2 -2
  50. package/docs/index.html +9 -7
  51. package/index.html +27 -63
  52. package/package.json +11 -4
  53. package/public/img/archive/concorde-001-2cv.webp +0 -0
  54. package/public/img/archive/concorde-red-arrows-2002-poster.jpg +0 -0
  55. package/public/img/archive/concorde-red-arrows-2002.webm +0 -0
  56. package/public/img/archive/credits.json +28 -0
  57. package/scripts/post-build-docs.js +0 -0
  58. package/scripts/post-build.mjs +0 -0
  59. package/src/core/components/functional/fetch/fetch.md +2 -2
  60. package/src/core/components/functional/if/if.md +0 -0
  61. package/src/core/components/functional/if/if.ts +0 -0
  62. package/src/core/components/functional/list/list.demo.ts +0 -0
  63. package/src/core/components/functional/list/list.md +0 -0
  64. package/src/core/components/functional/router/router.md +0 -0
  65. package/src/core/components/functional/router/router.ts +0 -0
  66. package/src/core/components/functional/sdui/SDUIDescriptorTransformer.ts +0 -0
  67. package/src/core/components/functional/sdui/component-catalog.gaps.json +1 -1
  68. package/src/core/components/functional/sdui/component-catalog.json +1 -1
  69. package/src/core/components/functional/sdui/types.ts +0 -0
  70. package/src/core/components/functional/states/states.md +0 -0
  71. package/src/core/components/functional/submit/submit.md +0 -0
  72. package/src/core/components/functional/subscriber/subscriber.ts +0 -0
  73. package/src/core/components/functional/value/value.ts +0 -0
  74. package/src/core/components/ui/_css/size.ts +0 -0
  75. package/src/core/components/ui/captcha/altchaStyles.ts +0 -0
  76. package/src/core/components/ui/form/radio/radio.md +0 -0
  77. package/src/core/components/ui/form/select/select.md +0 -0
  78. package/src/core/components/ui/form/switch/switch.md +0 -0
  79. package/src/core/components/ui/modal/modal.ts +14 -11
  80. package/src/core/mixins/Subscriber.ts +0 -0
  81. package/src/core/utils/DataBindObserver.ts +0 -0
  82. package/src/core/utils/Objects.ts +0 -0
  83. package/src/core/utils/route.ts +0 -0
  84. package/src/docs/_core-concept/subscriber.md +0 -0
  85. package/src/docs/_getting-started/components.md +5 -0
  86. package/src/docs/_getting-started/my-first-subscriber.md +0 -0
  87. package/src/docs/_getting-started/pubsub.md +0 -0
  88. package/src/docs/_getting-started/theming.md +2 -2
  89. package/src/docs/code.ts +88 -75
  90. package/src/docs/components/docs-demo-sources.ts +16 -8
  91. package/src/docs/components/docs-lit-demo.ts +19 -37
  92. package/src/docs/docs.ts +5 -0
  93. package/src/docs/example/docs-boarding-pass-demo.ts +134 -0
  94. package/src/docs/example/docs-provider-keys.ts +12 -0
  95. package/src/docs/example/users.ts +0 -0
  96. package/src/docs/header/header.ts +233 -69
  97. package/src/docs/home/catalog.ts +44 -0
  98. package/src/docs/home/home.ts +513 -0
  99. package/src/docs/home/mach-stage.ts +389 -0
  100. package/src/docs/layout.ts +3 -1
  101. package/src/docs/navigation/components-index.ts +56 -0
  102. package/src/docs/navigation/navigation.ts +240 -232
  103. package/src/docs/navigation/pager.ts +67 -0
  104. package/src/docs/navigation/toc.ts +98 -0
  105. package/src/docs/search/docs-search.json +330 -20
  106. package/src/docs/search/markdown-renderer.ts +11 -3
  107. package/src/docs/search/page.ts +0 -0
  108. package/src/docs/shiki/index.ts +109 -0
  109. package/src/docs/tailwind/css/base/scrollbar.css +22 -0
  110. package/src/docs/tailwind/css/base/theme.css +96 -0
  111. package/src/docs/tailwind/css/base/typography.css +4 -0
  112. package/src/docs/tailwind/css/docs/boarding-pass.css +65 -0
  113. package/src/docs/tailwind/css/docs/content.css +32 -0
  114. package/src/docs/tailwind/css/docs/page.css +10 -0
  115. package/src/docs/tailwind/css/docs.css +9 -0
  116. package/src/docs/tailwind/css/home/hero.css +210 -0
  117. package/src/docs/tailwind/css/home/motion.css +84 -0
  118. package/src/docs/tailwind/css/home/sections.css +416 -0
  119. package/src/docs/tailwind/css/tailwind.css +7 -185
  120. package/src/tsconfig.json +23 -2
  121. package/src/tsconfig.tsbuildinfo +1 -1
  122. package/tailwind.config.js +8 -4
  123. package/.github/workflows/ci.yml +0 -21
  124. package/.github-export-ignore +0 -30
  125. package/CONTRIBUTING.md +0 -59
  126. package/DEV.md +0 -54
  127. package/LICENSE +0 -21
  128. package/OPEN_SOURCE_CHECKPOINT.md +0 -133
  129. package/concorde-3d.bundle.js +0 -3960
  130. package/concorde-3d.es.js +0 -33433
  131. package/concorde-hugging-face-infer.bundle.js +0 -32
  132. package/concorde-hugging-face-infer.es.js +0 -2952
  133. package/concorde-interactive.bundle.js +0 -1157
  134. package/concorde-interactive.es.js +0 -10734
  135. package/concorde-shader.bundle.js +0 -116
  136. package/concorde-shader.es.js +0 -8353
  137. package/concorde-webgpu.bundle.js +0 -307
  138. package/concorde-webgpu.es.js +0 -8627
  139. package/docs/assets/index-D8MVWqY6.js +0 -12251
  140. package/docs/assets/index-DiD0qYvE.css +0 -1
  141. package/docs/crawl/core/components/functional/date/date.html +0 -190
  142. package/docs/crawl/core/components/functional/fetch/fetch.html +0 -109
  143. package/docs/crawl/core/components/functional/if/if.html +0 -27
  144. package/docs/crawl/core/components/functional/jsonata/jsonata.html +0 -79
  145. package/docs/crawl/core/components/functional/list/list.html +0 -70
  146. package/docs/crawl/core/components/functional/mix/mix.html +0 -45
  147. package/docs/crawl/core/components/functional/queue/queue.html +0 -96
  148. package/docs/crawl/core/components/functional/router/router.html +0 -106
  149. package/docs/crawl/core/components/functional/sdui/sdui.html +0 -269
  150. package/docs/crawl/core/components/functional/states/states.html +0 -66
  151. package/docs/crawl/core/components/functional/submit/submit.html +0 -160
  152. package/docs/crawl/core/components/functional/subscriber/subscriber.html +0 -67
  153. package/docs/crawl/core/components/functional/value/value.html +0 -51
  154. package/docs/crawl/core/components/ui/alert/alert.html +0 -110
  155. package/docs/crawl/core/components/ui/alert-messages/alert-messages.html +0 -23
  156. package/docs/crawl/core/components/ui/badge/badge.html +0 -119
  157. package/docs/crawl/core/components/ui/button/button.html +0 -149
  158. package/docs/crawl/core/components/ui/captcha/captcha.html +0 -30
  159. package/docs/crawl/core/components/ui/card/card.html +0 -99
  160. package/docs/crawl/core/components/ui/divider/divider.html +0 -58
  161. package/docs/crawl/core/components/ui/form/checkbox/checkbox.html +0 -73
  162. package/docs/crawl/core/components/ui/form/fieldset/fieldset.html +0 -135
  163. package/docs/crawl/core/components/ui/form/form-actions/form-actions.html +0 -79
  164. package/docs/crawl/core/components/ui/form/form-layout/form-layout.html +0 -62
  165. package/docs/crawl/core/components/ui/form/input/input.html +0 -109
  166. package/docs/crawl/core/components/ui/form/input-autocomplete/input-autocomplete.html +0 -38
  167. package/docs/crawl/core/components/ui/form/radio/radio.html +0 -56
  168. package/docs/crawl/core/components/ui/form/select/select.html +0 -73
  169. package/docs/crawl/core/components/ui/form/switch/switch.html +0 -56
  170. package/docs/crawl/core/components/ui/form/textarea/textarea.html +0 -59
  171. package/docs/crawl/core/components/ui/group/group.html +0 -82
  172. package/docs/crawl/core/components/ui/icon/icon.html +0 -133
  173. package/docs/crawl/core/components/ui/image/image.html +0 -110
  174. package/docs/crawl/core/components/ui/link/link.html +0 -42
  175. package/docs/crawl/core/components/ui/loader/loader.html +0 -50
  176. package/docs/crawl/core/components/ui/menu/menu.html +0 -322
  177. package/docs/crawl/core/components/ui/modal/modal.html +0 -117
  178. package/docs/crawl/core/components/ui/pop/pop.html +0 -102
  179. package/docs/crawl/core/components/ui/progress/progress.html +0 -58
  180. package/docs/crawl/core/components/ui/table/table.html +0 -413
  181. package/docs/crawl/core/components/ui/toast/toast.html +0 -122
  182. package/docs/crawl/core/components/ui/tooltip/tooltip.html +0 -79
  183. package/docs/crawl/docs/_core-concept/dataFlow.html +0 -177
  184. package/docs/crawl/docs/_core-concept/overview.html +0 -66
  185. package/docs/crawl/docs/_core-concept/subscriber.html +0 -75
  186. package/docs/crawl/docs/_decorators/ancestor-attribute.html +0 -116
  187. package/docs/crawl/docs/_decorators/auto-subscribe.html +0 -202
  188. package/docs/crawl/docs/_decorators/bind.html +0 -141
  189. package/docs/crawl/docs/_decorators/get.html +0 -149
  190. package/docs/crawl/docs/_decorators/handle.html +0 -165
  191. package/docs/crawl/docs/_decorators/on-assign.html +0 -355
  192. package/docs/crawl/docs/_decorators/patch.html +0 -78
  193. package/docs/crawl/docs/_decorators/post.html +0 -139
  194. package/docs/crawl/docs/_decorators/publish.html +0 -61
  195. package/docs/crawl/docs/_decorators/put.html +0 -78
  196. package/docs/crawl/docs/_decorators/subscribe.html +0 -109
  197. package/docs/crawl/docs/_decorators/wait-for-ancestors.html +0 -137
  198. package/docs/crawl/docs/_directives/sub.html +0 -93
  199. package/docs/crawl/docs/_getting-started/ai-agents.html +0 -173
  200. package/docs/crawl/docs/_getting-started/concorde-manual-install.html +0 -100
  201. package/docs/crawl/docs/_getting-started/concorde-outside.html +0 -58
  202. package/docs/crawl/docs/_getting-started/create-a-component.html +0 -111
  203. package/docs/crawl/docs/_getting-started/my-first-component.html +0 -189
  204. package/docs/crawl/docs/_getting-started/my-first-subscriber.html +0 -110
  205. package/docs/crawl/docs/_getting-started/pubsub.html +0 -62
  206. package/docs/crawl/docs/_getting-started/start.html +0 -76
  207. package/docs/crawl/docs/_getting-started/theming.html +0 -85
  208. package/docs/crawl/docs/_misc/api-configuration.html +0 -149
  209. package/docs/crawl/docs/_misc/dataProviderKey.html +0 -135
  210. package/docs/crawl/docs/_misc/docs-mock-api.html +0 -158
  211. package/docs/crawl/docs/_misc/dynamic-path.html +0 -180
  212. package/docs/crawl/docs/_misc/endpoint.html +0 -50
  213. package/docs/crawl/docs/_misc/formelement-subscriber-removal.html +0 -138
  214. package/docs/crawl/docs/_misc/html-integration.html +0 -48
  215. package/docs/crawl/hubs/decorators.html +0 -547
  216. package/docs/crawl/hubs/form-components.html +0 -359
  217. package/docs/crawl/hubs/remote-data.html +0 -452
  218. package/docs/crawl/index.html +0 -101
  219. package/docs/llms-full.txt +0 -5761
  220. package/docs/llms.txt +0 -104
  221. package/docs/sitemap.xml +0 -237
  222. package/docs/src/core/components/functional/date/date.md +0 -290
  223. package/docs/src/core/components/functional/fetch/fetch.md +0 -125
  224. package/docs/src/core/components/functional/if/if.md +0 -9
  225. package/docs/src/core/components/functional/jsonata/jsonata.md +0 -56
  226. package/docs/src/core/components/functional/list/list.md +0 -65
  227. package/docs/src/core/components/functional/mix/mix.md +0 -41
  228. package/docs/src/core/components/functional/queue/queue.md +0 -72
  229. package/docs/src/core/components/functional/router/router.md +0 -94
  230. package/docs/src/core/components/functional/sdui/default-library.json +0 -108
  231. package/docs/src/core/components/functional/sdui/example.json +0 -99
  232. package/docs/src/core/components/functional/sdui/sdui.md +0 -356
  233. package/docs/src/core/components/functional/states/states.md +0 -87
  234. package/docs/src/core/components/functional/submit/submit.md +0 -114
  235. package/docs/src/core/components/functional/subscriber/subscriber.md +0 -91
  236. package/docs/src/core/components/functional/value/value.md +0 -35
  237. package/docs/src/core/components/ui/alert/alert.md +0 -121
  238. package/docs/src/core/components/ui/alert-messages/alert-messages.md +0 -0
  239. package/docs/src/core/components/ui/badge/badge.md +0 -127
  240. package/docs/src/core/components/ui/button/button.md +0 -182
  241. package/docs/src/core/components/ui/captcha/captcha.md +0 -12
  242. package/docs/src/core/components/ui/card/card.md +0 -97
  243. package/docs/src/core/components/ui/divider/divider.md +0 -35
  244. package/docs/src/core/components/ui/form/checkbox/checkbox.md +0 -77
  245. package/docs/src/core/components/ui/form/fieldset/fieldset.md +0 -129
  246. package/docs/src/core/components/ui/form/form-actions/form-actions.md +0 -77
  247. package/docs/src/core/components/ui/form/form-layout/form-layout.md +0 -44
  248. package/docs/src/core/components/ui/form/input/input.md +0 -142
  249. package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +0 -29
  250. package/docs/src/core/components/ui/form/radio/radio.md +0 -57
  251. package/docs/src/core/components/ui/form/select/select.md +0 -71
  252. package/docs/src/core/components/ui/form/switch/switch.md +0 -57
  253. package/docs/src/core/components/ui/form/textarea/textarea.md +0 -65
  254. package/docs/src/core/components/ui/group/group.md +0 -75
  255. package/docs/src/core/components/ui/icon/icon.md +0 -125
  256. package/docs/src/core/components/ui/icon/icons.json +0 -1
  257. package/docs/src/core/components/ui/image/image.md +0 -107
  258. package/docs/src/core/components/ui/link/link.md +0 -43
  259. package/docs/src/core/components/ui/loader/loader.md +0 -55
  260. package/docs/src/core/components/ui/menu/menu.md +0 -329
  261. package/docs/src/core/components/ui/modal/modal.md +0 -119
  262. package/docs/src/core/components/ui/pop/pop.md +0 -96
  263. package/docs/src/core/components/ui/progress/progress.md +0 -63
  264. package/docs/src/core/components/ui/table/table.md +0 -455
  265. package/docs/src/core/components/ui/toast/toast.md +0 -166
  266. package/docs/src/core/components/ui/tooltip/tooltip.md +0 -82
  267. package/docs/src/docs/_core-concept/dataFlow.md +0 -88
  268. package/docs/src/docs/_core-concept/overview.md +0 -57
  269. package/docs/src/docs/_core-concept/subscriber.md +0 -75
  270. package/docs/src/docs/_decorators/ancestor-attribute.md +0 -127
  271. package/docs/src/docs/_decorators/auto-subscribe.md +0 -202
  272. package/docs/src/docs/_decorators/bind.md +0 -167
  273. package/docs/src/docs/_decorators/get.md +0 -162
  274. package/docs/src/docs/_decorators/handle.md +0 -175
  275. package/docs/src/docs/_decorators/on-assign.md +0 -390
  276. package/docs/src/docs/_decorators/patch.md +0 -70
  277. package/docs/src/docs/_decorators/post.md +0 -146
  278. package/docs/src/docs/_decorators/publish.md +0 -55
  279. package/docs/src/docs/_decorators/put.md +0 -70
  280. package/docs/src/docs/_decorators/subscribe.md +0 -100
  281. package/docs/src/docs/_decorators/wait-for-ancestors.md +0 -163
  282. package/docs/src/docs/_directives/sub.md +0 -91
  283. package/docs/src/docs/_getting-started/ai-agents.md +0 -76
  284. package/docs/src/docs/_getting-started/concorde-manual-install.md +0 -133
  285. package/docs/src/docs/_getting-started/concorde-outside.md +0 -33
  286. package/docs/src/docs/_getting-started/create-a-component.md +0 -139
  287. package/docs/src/docs/_getting-started/my-first-component.md +0 -236
  288. package/docs/src/docs/_getting-started/my-first-subscriber.md +0 -120
  289. package/docs/src/docs/_getting-started/pubsub.md +0 -37
  290. package/docs/src/docs/_getting-started/start.md +0 -47
  291. package/docs/src/docs/_getting-started/theming.md +0 -91
  292. package/docs/src/docs/_misc/api-configuration.md +0 -81
  293. package/docs/src/docs/_misc/dataProviderKey.md +0 -168
  294. package/docs/src/docs/_misc/docs-mock-api.md +0 -63
  295. package/docs/src/docs/_misc/dynamic-path.md +0 -71
  296. package/docs/src/docs/_misc/endpoint.md +0 -45
  297. package/docs/src/docs/_misc/formelement-subscriber-removal.md +0 -115
  298. package/docs/src/docs/_misc/html-integration.md +0 -15
  299. package/docs/src/docs/search/docs-search.json +0 -9507
  300. package/docs/src/tag-list.json +0 -1
  301. package/docs/src/tsconfig-model.json +0 -23
  302. package/docs/src/tsconfig.declarations.json +0 -22
  303. package/docs/src/tsconfig.emit.json +0 -23
  304. package/docs/src/tsconfig.json +0 -1182
  305. package/gitlab/job_github_mirror.sh +0 -39
  306. package/scripts/github-export.mjs +0 -150
  307. package/src/css.d.ts +0 -19
  308. package/src/docs/prism/index.ts +0 -6
  309. package/src/docs/prism/prism.css +0 -158
  310. package/src/docs/prism/prism.js +0 -1022
  311. package/src/tsconfig.declarations.json +0 -22
  312. package/src/tsconfig.emit.json +0 -23
@@ -0,0 +1,389 @@
1
+ import { LitElement, html } from "lit";
2
+ import { customElement } from "lit/decorators.js";
3
+
4
+ /** The Concorde silhouette from the brand icon, nose up, in a 66 × 66 box centred on (33, 33). */
5
+ const PLANE =
6
+ "M33.2499 62.03C33.8799 59.24 34.26 56.17 34.39 53.08C34.57 52.78 34.9099 52.6 35.2599 52.64H35.39C35.48 52.64 35.5799 52.64 35.6899 52.64H35.7599C35.7599 52.64 35.7999 52.64 35.8299 52.64C36.2499 52.62 36.6799 52.58 36.9099 52.56C36.9399 52.56 36.9599 52.56 36.9799 52.56C37.0099 52.56 37.0299 52.56 37.0499 52.56H37.0899L37.2099 51.93H37.4799L37.5799 52.4L37.6899 52.49H39.2699L39.39 52.38L39.5099 51.93H39.7899L39.8399 52.21L39.9999 52.29L45.2099 51.86L46.2799 51.29C46.2799 51.29 46.2799 50.85 46.2399 50.25V50.18C46.2399 50.18 46.2399 50.13 46.2399 50.11C46.2099 49.62 46.1399 49.13 46.0399 48.65C45.7899 47.45 45.29 46 42.2 41.58C39.11 37.16 38.04 35.52 35.89 27.63C35.85 27.48 35.8199 27.35 35.7899 27.2C35.1399 24.53 34.6899 22.95 34.5199 22.38V10.89C34.4999 9.60996 34.3999 8.33996 34.2099 7.07996C34.0499 5.97996 33.6099 4.89996 33.3499 3.95996H32.6299C32.3599 4.89996 31.9299 5.97996 31.7699 7.06996C31.5799 8.33996 31.4799 9.60996 31.4599 10.89V22.38C31.2899 22.95 30.8299 24.52 30.1899 27.2C30.1599 27.35 30.1199 27.49 30.0899 27.63C27.9499 35.52 26.8699 37.16 23.7799 41.58C20.6899 46 20.1899 47.45 19.9399 48.65C19.8399 49.13 19.7799 49.62 19.7399 50.11C19.7399 50.13 19.7399 50.16 19.7399 50.18V50.25C19.6999 50.85 19.7 51.29 19.7 51.29L20.7699 51.86L25.9799 52.29L26.14 52.21L26.1899 51.93H26.4799L26.5999 52.38L26.7299 52.49H28.2999L28.4099 52.4L28.5099 51.93H28.7699L28.89 52.56H28.9399C28.9399 52.56 28.9799 52.56 29.0099 52.56C29.0299 52.56 29.0499 52.56 29.0799 52.56C29.3099 52.58 29.7499 52.63 30.1599 52.64C30.1799 52.64 30.2099 52.64 30.2299 52.64H30.2999C30.4099 52.64 30.5099 52.64 30.5999 52.64H30.7299C31.0799 52.6 31.4299 52.77 31.6099 53.08C31.7299 56.17 32.1099 59.24 32.7399 62.03H33.2499Z";
7
+
8
+ /** Speed of sound on the stage, in stage widths per second. */
9
+ const SOUND = 0.19;
10
+ /** Cruise: Concorde flew at Mach 2.02, 18 000 m up. */
11
+ const CRUISE = 2.02;
12
+ /** Grid cells across the field; every fourth line is heavier. */
13
+ const GRID = 24;
14
+ const WAVE_EVERY = 0.05;
15
+ const WAVE_LIFE = 2.6;
16
+
17
+ const clamp = (v: number, lo: number, hi: number) =>
18
+ Math.min(hi, Math.max(lo, v));
19
+ const smooth = (a: number, b: number, v: number) => {
20
+ const t = clamp((v - a) / (b - a), 0, 1);
21
+ return t * t * (3 - 2 * t);
22
+ };
23
+
24
+ type Wave = { x: number; y: number; t: number };
25
+
26
+ /**
27
+ * The hero's orange field as a Mach diagram: the aircraft drops a sound wave as it flies and,
28
+ * once it outruns them, the waves pile into the shock cone. On autopilot it accelerates through
29
+ * the barrier on every pass; a moving pointer steers it and moving fast
30
+ * enough breaks the barrier by hand. Reduced motion gets one still frame at cruise.
31
+ */
32
+ @customElement("docs-mach-stage")
33
+ export class DocsMachStage extends LitElement {
34
+ private canvas?: HTMLCanvasElement;
35
+ private ints: HTMLElement[] = [];
36
+ private decs: HTMLElement[] = [];
37
+ private plane = new Path2D(PLANE);
38
+ private waves: Wave[] = [];
39
+ private x = -0.3;
40
+ private y = 0.55;
41
+ private vx = 0.75 * SOUND;
42
+ private vy = 0;
43
+ private mach = 0;
44
+ private time = 0;
45
+ private lastWave = 0;
46
+ private pointer: { x: number; y: number; t: number } | null = null;
47
+ private boom = -10;
48
+ private frame = 0;
49
+ private last = 0;
50
+ private resize?: ResizeObserver;
51
+ private visible = true;
52
+ private io?: IntersectionObserver;
53
+
54
+ createRenderRoot() {
55
+ return this;
56
+ }
57
+
58
+ render() {
59
+ return html`<canvas class="mach-canvas" aria-hidden="true"></canvas>
60
+ <p class="mach-readout" aria-label="Concorde cruise speed: Mach 2.02">
61
+ <span class="mach-label">mach</span>
62
+ <span class="mach-value">
63
+ ${[
64
+ "mach-layer",
65
+ "mach-layer mach-ghost-a",
66
+ "mach-layer mach-ghost-b",
67
+ ].map(
68
+ (layer, i) =>
69
+ html`<span class=${layer} aria-hidden=${i ? "true" : "false"}
70
+ ><span class="mach-int">0</span><span class="mach-dot">.</span
71
+ ><span class="mach-dec">00</span></span
72
+ >`,
73
+ )}
74
+ </span>
75
+ </p>
76
+ <p class="mach-note">
77
+ cruise mach 2.02 · 18 000 m · paris – new york in 3 h 30
78
+ </p>`;
79
+ }
80
+
81
+ firstUpdated() {
82
+ this.canvas = this.querySelector("canvas")!;
83
+ this.ints = [...this.querySelectorAll<HTMLElement>(".mach-int")];
84
+ this.decs = [...this.querySelectorAll<HTMLElement>(".mach-dec")];
85
+ this.resize = new ResizeObserver(() => this.fit());
86
+ this.resize.observe(this);
87
+ this.io = new IntersectionObserver(
88
+ ([e]) => (this.visible = e.isIntersecting),
89
+ );
90
+ this.io.observe(this);
91
+ this.addEventListener("pointermove", this.onPointer);
92
+ this.addEventListener("pointerdown", this.onPointer);
93
+ this.addEventListener("pointerleave", this.onLeave);
94
+ this.fit();
95
+ if (matchMedia("(prefers-reduced-motion: reduce)").matches) {
96
+ this.still();
97
+ return;
98
+ }
99
+ this.frame = requestAnimationFrame(this.tick);
100
+ }
101
+
102
+ disconnectedCallback() {
103
+ super.disconnectedCallback();
104
+ cancelAnimationFrame(this.frame);
105
+ this.resize?.disconnect();
106
+ this.io?.disconnect();
107
+ }
108
+
109
+ private onPointer = (e: PointerEvent) => {
110
+ const r = this.getBoundingClientRect();
111
+ this.pointer = {
112
+ x: (e.clientX - r.left) / r.width,
113
+ y: (e.clientY - r.top) / r.width,
114
+ t: this.time,
115
+ };
116
+ };
117
+
118
+ private onLeave = () => {
119
+ this.pointer = null;
120
+ };
121
+
122
+ private fit() {
123
+ const c = this.canvas!;
124
+ const dpr = Math.min(devicePixelRatio || 1, 2);
125
+ c.width = Math.round(this.clientWidth * dpr);
126
+ c.height = Math.round(this.clientHeight * dpr);
127
+ // publish the grid cell so the field's bevel can be cut along the grid
128
+ this.parentElement?.style.setProperty(
129
+ "--mach-cell",
130
+ `${this.clientWidth / GRID}px`,
131
+ );
132
+ if (matchMedia("(prefers-reduced-motion: reduce)").matches) this.still();
133
+ }
134
+
135
+ /** Height of the field in stage widths (positions are kept in widths so speed is uniform). */
136
+ private get aspect() {
137
+ return this.clientHeight / Math.max(1, this.clientWidth);
138
+ }
139
+
140
+ private tick = (now: number) => {
141
+ this.frame = requestAnimationFrame(this.tick);
142
+ const dt = Math.min(0.05, (now - (this.last || now)) / 1000);
143
+ this.last = now;
144
+ if (!this.visible || !dt) return;
145
+ this.time += dt;
146
+ this.fly(dt);
147
+ if (this.time - this.lastWave > WAVE_EVERY) {
148
+ this.lastWave = this.time;
149
+ this.waves.push({ x: this.x, y: this.y, t: this.time });
150
+ }
151
+ this.waves = this.waves.filter((w) => this.time - w.t < WAVE_LIFE);
152
+ this.draw();
153
+ };
154
+
155
+ private fly(dt: number) {
156
+ const h = this.aspect;
157
+ const before = this.mach;
158
+ // flown by heading and speed, never by position, so it always carries on along an arc
159
+ let speed = Math.hypot(this.vx, this.vy);
160
+ let heading = Math.atan2(this.vy, this.vx);
161
+ let wantSpeed: number;
162
+ let wantHeading: number;
163
+ let turn: number;
164
+ let throttle: number;
165
+ const steering = this.pointer && this.time - this.pointer.t < 0.4;
166
+ if (steering) {
167
+ // head for a moving pointer; the further ahead it runs, the faster the aircraft goes
168
+ const dx = this.pointer!.x - this.x;
169
+ const dy = this.pointer!.y - this.y;
170
+ wantHeading = Math.atan2(dy, dx);
171
+ wantSpeed = clamp(Math.hypot(dx, dy) * 2.5, 0.6 * SOUND, 2.4 * SOUND);
172
+ turn = 5;
173
+ throttle = 4;
174
+ } else {
175
+ // autopilot: endless passes, speeding up to cruise across the field and easing off
176
+ // while out of sight, so each pass hands over to the next without a cut
177
+ const up = smooth(-0.1, 0.65, this.x);
178
+ const down = smooth(1.0, 1.2, this.x);
179
+ wantSpeed = (0.6 + (CRUISE - 0.6) * up * (1 - down)) * SOUND;
180
+ const cy = h * 0.55 + Math.sin(this.time * 0.6) * h * 0.06;
181
+ wantHeading = Math.atan2(cy - this.y, 0.6);
182
+ turn = 2;
183
+ throttle = 2;
184
+ }
185
+ let delta = wantHeading - heading;
186
+ delta = Math.atan2(Math.sin(delta), Math.cos(delta));
187
+ heading += delta * Math.min(1, dt * turn);
188
+ speed += (wantSpeed - speed) * Math.min(1, dt * throttle);
189
+ this.vx = Math.cos(heading) * speed;
190
+ this.vy = Math.sin(heading) * speed;
191
+ this.x += this.vx * dt;
192
+ this.y += this.vy * dt;
193
+ // out of sight on the right, back in on the left; the old waves fade where they were left
194
+ if (!steering && this.x > 1.3) this.x -= 1.6;
195
+ this.mach = speed / SOUND;
196
+ if (before < 1 && this.mach >= 1) this.boom = this.time;
197
+ }
198
+
199
+ private colours() {
200
+ const s = getComputedStyle(this);
201
+ return { ink: s.color, field: s.backgroundColor };
202
+ }
203
+
204
+ private draw() {
205
+ const c = this.canvas!;
206
+ const g = c.getContext("2d")!;
207
+ const W = c.width;
208
+ const u = W; // one stage width in device pixels
209
+ const { ink } = this.colours();
210
+ g.clearRect(0, 0, c.width, c.height);
211
+ g.strokeStyle = ink;
212
+ g.fillStyle = ink;
213
+ const px = this.x * u;
214
+ const py = this.y * u;
215
+
216
+ // graph paper under the diagram: a fine square grid, every fourth line heavier
217
+ const cell = u / GRID;
218
+ g.lineWidth = Math.max(1, u * 0.0008);
219
+ for (let i = 0, x = 0; x <= c.width; i++, x += cell) {
220
+ g.globalAlpha = i % 4 ? 0.1 : 0.22;
221
+ g.beginPath();
222
+ g.moveTo(Math.round(x) + 0.5, 0);
223
+ g.lineTo(Math.round(x) + 0.5, c.height);
224
+ g.stroke();
225
+ }
226
+ for (let i = 0, y = 0; y <= c.height; i++, y += cell) {
227
+ g.globalAlpha = i % 4 ? 0.1 : 0.22;
228
+ g.beginPath();
229
+ g.moveTo(0, Math.round(y) + 0.5);
230
+ g.lineTo(c.width, Math.round(y) + 0.5);
231
+ g.stroke();
232
+ }
233
+
234
+ // the shock cone, filled, once supersonic
235
+ if (this.mach > 1.02) {
236
+ const mu = Math.asin(1 / this.mach);
237
+ const dir = Math.atan2(this.vy, this.vx);
238
+ const len = u * 2;
239
+ g.globalAlpha = Math.min(0.22, (this.mach - 1) * 0.35);
240
+ g.beginPath();
241
+ g.moveTo(px, py);
242
+ g.lineTo(px - Math.cos(dir - mu) * len, py - Math.sin(dir - mu) * len);
243
+ g.lineTo(px - Math.cos(dir + mu) * len, py - Math.sin(dir + mu) * len);
244
+ g.closePath();
245
+ g.fill();
246
+ }
247
+
248
+ // the waves: each one a circle growing at the speed of sound from where it was dropped
249
+ g.lineWidth = Math.max(2, u * 0.003);
250
+ for (const w of this.waves) {
251
+ const age = this.time - w.t;
252
+ const r = age * SOUND * u;
253
+ g.globalAlpha = Math.max(0, 1 - age / WAVE_LIFE) * 0.9;
254
+ g.beginPath();
255
+ g.arc(w.x * u, w.y * u, r, 0, Math.PI * 2);
256
+ g.stroke();
257
+ }
258
+
259
+ this.construct(g, u, px, py);
260
+
261
+ // the boom: one heavy ring when the barrier goes
262
+ const since = this.time - this.boom;
263
+ if (since >= 0 && since < 1.4) {
264
+ g.globalAlpha = 1 - since / 1.4;
265
+ g.lineWidth = u * 0.018 * (1 - since / 1.4) + 2;
266
+ g.beginPath();
267
+ g.arc(px, py, since * SOUND * u * 3.2, 0, Math.PI * 2);
268
+ g.stroke();
269
+ }
270
+
271
+ // the aircraft, pointing where it flies
272
+ g.globalAlpha = 1;
273
+ const size = u * 0.15;
274
+ g.save();
275
+ g.translate(px, py);
276
+ g.rotate(Math.atan2(this.vy, this.vx) + Math.PI / 2);
277
+ g.scale(size / 66, size / 66);
278
+ g.translate(-33, -33);
279
+ g.fill(this.plane);
280
+ g.restore();
281
+
282
+ const [int, dec] = this.mach.toFixed(2).split(".");
283
+ for (const el of this.ints) el.textContent = int;
284
+ for (const el of this.decs) el.textContent = dec;
285
+ // the readout splits and shakes for a moment as the barrier goes
286
+ this.toggleAttribute("data-boom", since >= 0 && since < 0.9);
287
+ this.toggleAttribute("data-supersonic", this.mach >= 1);
288
+ }
289
+
290
+ /**
291
+ * Construction lines, as on a textbook figure: the flight path, the Mach lines run out to the
292
+ * edges, a few radii dropped square onto them from the centres that made them, and the angle.
293
+ */
294
+ private construct(
295
+ g: CanvasRenderingContext2D,
296
+ u: number,
297
+ px: number,
298
+ py: number,
299
+ ) {
300
+ const c = this.canvas!;
301
+ const dir = Math.atan2(this.vy, this.vx);
302
+ const reach = Math.hypot(c.width, c.height) * 2;
303
+ const line = (x1: number, y1: number, x2: number, y2: number) => {
304
+ g.beginPath();
305
+ g.moveTo(x1, y1);
306
+ g.lineTo(x2, y2);
307
+ g.stroke();
308
+ };
309
+ g.lineWidth = Math.max(1, u * 0.0012);
310
+
311
+ // flight path, dashed, through the whole field
312
+ g.globalAlpha = 0.45;
313
+ g.setLineDash([u * 0.012, u * 0.008]);
314
+ line(
315
+ px - Math.cos(dir) * reach,
316
+ py - Math.sin(dir) * reach,
317
+ px + Math.cos(dir) * reach,
318
+ py + Math.sin(dir) * reach,
319
+ );
320
+ g.setLineDash([]);
321
+
322
+ // centre marks where the waves were dropped
323
+ const mark = u * 0.006;
324
+ g.globalAlpha = 0.5;
325
+ this.waves.forEach((w, i) => {
326
+ if (i % 6) return;
327
+ line(w.x * u - mark, w.y * u, w.x * u + mark, w.y * u);
328
+ line(w.x * u, w.y * u - mark, w.x * u, w.y * u + mark);
329
+ });
330
+
331
+ if (this.mach <= 1.02) return;
332
+ const mu = Math.asin(1 / this.mach);
333
+ for (const side of [-1, 1]) {
334
+ const ex = Math.cos(dir + Math.PI + side * mu);
335
+ const ey = Math.sin(dir + Math.PI + side * mu);
336
+ // the Mach line, run out past the cone to the edge
337
+ g.globalAlpha = 0.6;
338
+ line(px, py, px + ex * reach, py + ey * reach);
339
+ // radii, square to the Mach line, from a few of the centres
340
+ g.globalAlpha = 0.45;
341
+ this.waves.forEach((w, i) => {
342
+ if (i % 12 || this.time - w.t < 0.5) return;
343
+ const cx = w.x * u;
344
+ const cy = w.y * u;
345
+ const along = (cx - px) * ex + (cy - py) * ey;
346
+ if (along <= 0) return;
347
+ line(cx, cy, px + ex * along, py + ey * along);
348
+ });
349
+ }
350
+
351
+ // the angle, marked at the apex, its value set just outside the cone where no wave reaches
352
+ const r = u * 0.12;
353
+ g.globalAlpha = 1;
354
+ g.lineWidth = Math.max(2, u * 0.003);
355
+ g.beginPath();
356
+ g.arc(px, py, r, dir + Math.PI - mu, dir + Math.PI + mu);
357
+ g.stroke();
358
+ const edge = dir + Math.PI + mu;
359
+ const out = edge + Math.PI / 2;
360
+ const gap = u * 0.03;
361
+ g.font = `600 ${Math.round(u * 0.024)}px ${getComputedStyle(this).fontFamily}`;
362
+ g.textAlign = "center";
363
+ g.textBaseline = "middle";
364
+ const deg = ((mu * 180) / Math.PI).toFixed(1);
365
+ g.fillText(
366
+ `μ ${deg}°`,
367
+ px + Math.cos(edge) * r * 1.1 + Math.cos(out) * gap,
368
+ py + Math.sin(edge) * r * 1.1 + Math.sin(out) * gap,
369
+ );
370
+ }
371
+
372
+ /** Reduced motion: the field at cruise, waves laid out as they would be, nothing moving. */
373
+ private still() {
374
+ if (!this.canvas) return;
375
+ const h = this.aspect;
376
+ this.x = 0.68;
377
+ this.y = h * 0.55;
378
+ this.vx = CRUISE * SOUND;
379
+ this.vy = 0;
380
+ this.mach = CRUISE;
381
+ this.time = WAVE_LIFE;
382
+ this.boom = -10;
383
+ this.waves = [];
384
+ for (let t = 0; t < WAVE_LIFE; t += WAVE_EVERY * 2) {
385
+ this.waves.push({ x: this.x - this.vx * (WAVE_LIFE - t), y: this.y, t });
386
+ }
387
+ this.draw();
388
+ }
389
+ }
@@ -1,5 +1,7 @@
1
1
  const onLocationChange = (location: Location) => {
2
- if (location.pathname === "/" && location.hash === "") {
2
+ // Docs pages all live in the hash: no hash means the home, whatever the path
3
+ // (served at /, /index.html or from a sub-folder).
4
+ if (location.hash === "") {
3
5
  document.documentElement.setAttribute("data-home", "");
4
6
  } else {
5
7
  document.documentElement.removeAttribute("data-home");
@@ -0,0 +1,56 @@
1
+ import { html, LitElement } from "lit";
2
+ import { customElement } from "lit/decorators.js";
3
+ import { docsNavigation } from "./navigation";
4
+
5
+ export type Page = { label: string; href: string };
6
+
7
+ /** Sidebar sections listed on the Components page, in display order. */
8
+ const SECTIONS = [
9
+ { title: "UI components", id: "ui-components" },
10
+ { title: "Functional components", id: "functional-components" },
11
+ ];
12
+
13
+ /** Pages of a sidebar section: the items between its title and the next one. */
14
+ export function sectionPages(title: string): Page[] {
15
+ const start = docsNavigation.indexOf(title);
16
+ if (start < 0) return [];
17
+ const pages: Page[] = [];
18
+ for (const item of docsNavigation.slice(start + 1)) {
19
+ if (typeof item === "string") break;
20
+ pages.push(item);
21
+ }
22
+ return pages;
23
+ }
24
+
25
+ const tagName = "docs-components-index";
26
+ /**
27
+ * Plain index of every component, grouped like the sidebar.
28
+ * Light DOM so the page headings feed the "On this page" navigation.
29
+ */
30
+ @customElement(tagName)
31
+ export class DocsComponentsIndex extends LitElement {
32
+ createRenderRoot() {
33
+ return this;
34
+ }
35
+
36
+ render() {
37
+ return SECTIONS.map(
38
+ (section) => html`
39
+ <h2 id=${section.id}>${section.title}</h2>
40
+ <div
41
+ class="not-prose grid grid-cols-2 sm:grid-cols-3 gap-x-8 gap-y-3 mt-6 mb-12"
42
+ >
43
+ ${sectionPages(section.title).map(
44
+ (page) =>
45
+ html`<sonic-link
46
+ href=${page.href}
47
+ pushState
48
+ class="hover:underline underline-offset-4"
49
+ >${page.label}</sonic-link
50
+ >`,
51
+ )}
52
+ </div>
53
+ `,
54
+ );
55
+ }
56
+ }